<commit_before>defmodule Helix.Hardware.Controller.MotherboardSlotTest do

  use ExUnit.Case, async: true

  alias HELL.TestHelper.Random
  alias Helix.Hardware.Repo
  alias Helix.Hardware.Model.ComponentType
  alias Helix.Hardware.Model.MotherboardSlot
  alias Helix.Hardware.Controller.Component, as: ComponentController
  alias Helix.Hardware.Controller.ComponentSpec, as: SpecController
  alias Helix.Hardware.Controller.Motherboard, as: MotherboardController
  alias Helix.Hardware.Controller.MotherboardSlot, as: MotherboardSlotController

  setup_all do
    # FIXME
    types = case Repo.all(ComponentType) do
      [] ->
        1..5
        |> Enum.map(fn _ -> Burette.Color.name() end)
        |> Enum.uniq()
        |> Enum.map(&ComponentType.create_changeset(%{component_type: &1}))
        |> Enum.map(&Repo.insert!/1)
      ct = [_|_] ->
        ct
    end

    slot_type = Enum.random(["ram", "cpu", "hdd"])
    mobo_type = "mobo"

    component_type(slot_type)
    component_type(mobo_type)

    slot_number = Burette.Number.digits(4)
    spec_params = %{
      component_type: mobo_type,
      spec: %{
        spec_type: mobo_type,
        spec_code: Random.string(min: 20, max: 20),
        slots: %{
          slot_number => %{type: slot_type}
        }
      }
    }

    {:ok, spec} = SpecController.create(spec_params)

    [
      component_types: types,
      slot_type: slot_type,
      mobo_type: mobo_type,
      spec: spec]
  end

  setup %{mobo_type: mobo_type, spec: spec} do
    {:ok, mobo} = create_motherboard(mobo_type, spec.spec_id)
    slot =
      mobo.motherboard_id
      |> MotherboardController.get_slots()
      |> List.first()

    {:ok, slot: slot, mobo: mobo}
  end

  defp create_motherboard(motherboard_type, spec_id) do
    comp_params = %{
      component_type: motherboard_type,
      spec_id: spec_id}
    {:ok, comp} = ComponentController.create(comp_params)

    mobo_params = %{motherboard_id: comp.component_id}
    {:ok, mobo} = MotherboardController.create(mobo_params)
    mobo = Repo.preload(mobo, :component_spec)

    {:ok, mobo}
  end

  defp component_type(name) do
    case Repo.get_by(ComponentType, component_type: name) do
      nil ->
        %{component_type: name}
        |> ComponentType.create_changeset()
        |> Repo.insert!()
      component_type ->
        component_type
    end
  end

  defp component_for(slot) do
    p = %{
      component_type: slot.link_component_type,
      spec: %{spec_code: Random.string(min: 20, max: 20)}
    }
    {:ok, comp_spec} = SpecController.create(p)

    p = %{
      component_type: slot.link_component_type,
      spec_id: comp_spec.spec_id
    }
    {:ok, comp} = ComponentController.create(p)

    comp
  end

  describe "find" do
    test "fetching a slot by it's id", %{slot: slot} do
      assert {:ok, _} = MotherboardSlotController.find(slot.slot_id)
    end

    test "failure to retrieve a slot when it doesn't exists" do
      assert {:error, :notfound} === MotherboardSlotController.find(Random.pk())
    end
  end

  describe "link" do
    test "connecting a component into slot", %{slot: slot} do
      component = component_for(slot)
      {:ok, slot} = MotherboardSlotController.link(slot.slot_id, component.component_id)
      assert component.component_id === slot.link_component_id
    end

    test "failure when slot is already used", %{slot: slot} do
      component = component_for(slot)
      MotherboardSlotController.link(slot.slot_id, component.component_id)
      assert {:error, :slot_already_linked} === MotherboardSlotController.link(slot.slot_id, component.component_id)
    end

    test "failure when component is already used", context do
      %{slot: slot0, spec: spec, mobo_type: mobo_type} = context
      {:ok, mobo} = create_motherboard(mobo_type, spec.spec_id)

      slot1 =
        mobo.motherboard_id
        |> MotherboardController.get_slots()
        |> List.first()

       component = component_for(slot0)
       MotherboardSlotController.link(slot0.slot_id, component.component_id)<commit_msg>- Remove redundant code mobo type binding. - Ensure that `component already linked ` test always uses slots of the same type.<commit_after>defmodule Helix.Hardware.Controller.MotherboardSlotTest do

  use ExUnit.Case, async: true

  alias HELL.TestHelper.Random
  alias Helix.Hardware.Repo
  alias Helix.Hardware.Model.ComponentType
  alias Helix.Hardware.Model.MotherboardSlot
  alias Helix.Hardware.Controller.Component, as: ComponentController
  alias Helix.Hardware.Controller.ComponentSpec, as: SpecController
  alias Helix.Hardware.Controller.Motherboard, as: MotherboardController
  alias Helix.Hardware.Controller.MotherboardSlot, as: MotherboardSlotController

  setup_all do
    # FIXME
    types = case Repo.all(ComponentType) do
      [] ->
        1..5
        |> Enum.map(fn _ -> Burette.Color.name() end)
        |> Enum.uniq()
        |> Enum.map(&ComponentType.create_changeset(%{component_type: &1}))
        |> Enum.map(&Repo.insert!/1)
      ct = [_|_] ->
        ct
    end

    slot_type = Enum.random(["ram", "cpu", "hdd"])

    component_type(slot_type)
    component_type("mobo")

    slot_number = Burette.Number.digits(4)
    spec_params = %{
      component_type: "mobo",
      spec: %{
        spec_type: "mobo",
        spec_code: Random.string(min: 20, max: 20),
        slots: %{
          slot_number => %{type: slot_type}
        }
      }
    }

    {:ok, spec} = SpecController.create(spec_params)

    [
      component_types: types,
      slot_type: slot_type,
      spec: spec]
  end

  setup %{spec: spec} do
    {:ok, mobo} = create_motherboard(spec.spec_id)
    slot =
      mobo.motherboard_id
      |> MotherboardController.get_slots()
      |> List.first()

    {:ok, slot: slot, mobo: mobo}
  end

  defp create_motherboard(spec_id) do
    comp_params = %{
      component_type: "mobo",
      spec_id: spec_id}
    {:ok, comp} = ComponentController.create(comp_params)

    mobo_params = %{motherboard_id: comp.component_id}
    {:ok, mobo} = MotherboardController.create(mobo_params)
    mobo = Repo.preload(mobo, :component_spec)

    {:ok, mobo}
  end

  defp component_type(name) do
    case Repo.get_by(ComponentType, component_type: name) do
      nil ->
        %{component_type: name}
        |> ComponentType.create_changeset()
        |> Repo.insert!()
      component_type ->
        component_type
    end
  end

  defp component_for(slot) do
    p = %{
      component_type: slot.link_component_type,
      spec: %{spec_code: Random.string(min: 20, max: 20)}
    }
    {:ok, comp_spec} = SpecController.create(p)

    p = %{
      component_type: slot.link_component_type,
      spec_id: comp_spec.spec_id
    }
    {:ok, comp} = ComponentController.create(p)

    comp
  end

  describe "find" do
    test "fetching a slot by it's id", %{slot: slot} do
      assert {:ok, _} = MotherboardSlotController.find(slot.slot_id)
    end

    test "failure to retrieve a slot when it doesn't exists" do
      assert {:error, :notfound} === MotherboardSlotController.find(Random.pk())
    end
  end

  describe "link" do
    test "connecting a component into slot", %{slot: slot} do
      component = component_for(slot)
      {:ok, slot} = MotherboardSlotController.link(slot.slot_id, component.component_id)
      assert component.component_id === slot.link_component_id
    end

    test "failure when slot is already used", %{slot: slot} do
      component = component_for(slot)
      MotherboardSlotController.link(slot.slot_id, component.component_id)
      assert {:error, :slot_already_linked} === MotherboardSlotController.link(slot.slot_id, component.component_id)
    end

    test "failure when component is already used", context do
      %{slot: slot0, mobo: mobo} = context
      {:ok, mobo} = create_motherboard(mobo.component.spec_id)

      slot1 =
        mobo.motherboard_id
        |> MotherboardController.get_slots()
        |> Enum.find(&(&1.link_component_type == slot0.link_component_type))

       component = component_for(slot0)
       MotherboardSlotController.link(slot0.slot_id, component.component_id)
{'fraction_non_alphanumeric': 0.11203828690636888, 'fraction_numerical': 0.004417719965639956, 'mean_word_length': 3.0811216825237855, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 35, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7245762', 'n_tokens_mistral': 2745, 'n_tokens_neox': 2607, 'n_words': 560}