"""Tests for the power symbol tool and geometry helper.""" import os from tests.conftest import requires_sch_api @requires_sch_api class TestAddPowerSymbolToPin: """Tests for the _geometry.add_power_symbol_to_pin() helper.""" def test_ground_symbol_placed_below_pin(self, tmp_output_dir): from kicad_sch_api import create_schematic from mckicad.patterns._geometry import add_power_symbol_to_pin path = os.path.join(tmp_output_dir, "pwr_test.kicad_sch") sch = create_schematic("pwr_test") sch.components.add(lib_id="Device:R", reference="R1", value="10k", position=(100, 100)) pin_pos = sch.get_component_pin_position("R1", "2") assert pin_pos is not None result = add_power_symbol_to_pin( sch=sch, pin_position=(pin_pos.x, pin_pos.y), net="GND", ) assert result["net"] == "GND" assert result["direction"] == "down" assert result["reference"].startswith("#PWR") assert result["lib_id"] == "power:GND" assert result["wire_id"] is not None # Ground symbol should be below the pin (higher Y in KiCad coords) assert result["symbol_position"]["y"] > pin_pos.y sch.save(path) def test_supply_symbol_placed_above_pin(self, tmp_output_dir): from kicad_sch_api import create_schematic from mckicad.patterns._geometry import add_power_symbol_to_pin path = os.path.join(tmp_output_dir, "pwr_test2.kicad_sch") sch = create_schematic("pwr_test2") sch.components.add(lib_id="Device:R", reference="R1", value="10k", position=(100, 100)) pin_pos = sch.get_component_pin_position("R1", "1") assert pin_pos is not None result = add_power_symbol_to_pin( sch=sch, pin_position=(pin_pos.x, pin_pos.y), net="+3V3", ) assert result["net"] == "+3V3" assert result["direction"] == "up" assert result["lib_id"] == "power:+3V3" # Supply symbol should be above the pin (lower Y in KiCad coords) assert result["symbol_position"]["y"] < pin_pos.y sch.save(path) def test_custom_lib_id_override(self, tmp_output_dir): from kicad_sch_api import create_schematic from mckicad.patterns._geometry import add_power_symbol_to_pin sch = create_schematic("pwr_test3") sch.components.add(lib_id="Device:C", reference="C1", value="100nF", position=(100, 100)) pin_pos = sch.get_component_pin_position("C1", "1") assert pin_pos is not None result = add_power_symbol_to_pin( sch=sch, pin_position=(pin_pos.x, pin_pos.y), net="VCC", lib_id="power:VCC", ) assert result["lib_id"] == "power:VCC" def test_sequential_pwr_references(self, tmp_output_dir): from kicad_sch_api import create_schematic from mckicad.patterns._geometry import add_power_symbol_to_pin sch = create_schematic("pwr_seq") sch.components.add(lib_id="Device:R", reference="R1", value="10k", position=(100, 100)) pin1 = sch.get_component_pin_position("R1", "1") pin2 = sch.get_component_pin_position("R1", "2") assert pin1 is not None assert pin2 is not None r1 = add_power_symbol_to_pin(sch, (pin1.x, pin1.y), "+3V3") r2 = add_power_symbol_to_pin(sch, (pin2.x, pin2.y), "GND") # References should be sequential assert r1["reference"] != r2["reference"] assert r1["reference"].startswith("#PWR") assert r2["reference"].startswith("#PWR") @requires_sch_api class TestAddPowerSymbolTool: """Integration tests for the add_power_symbol MCP tool.""" def test_add_gnd_to_resistor_pin(self, populated_schematic_with_ic): from mckicad.tools.power_symbols import add_power_symbol result = add_power_symbol( schematic_path=populated_schematic_with_ic, net="GND", pin_ref="R1", pin_number="2", ) assert result["success"] is True assert result["net"] == "GND" assert result["target_component"] == "R1" assert result["target_pin"] == "2" assert result["reference"].startswith("#PWR") assert result["engine"] == "kicad-sch-api" def test_add_vcc_to_cap_pin(self, populated_schematic_with_ic): from mckicad.tools.power_symbols import add_power_symbol result = add_power_symbol( schematic_path=populated_schematic_with_ic, net="VCC", pin_ref="C1", pin_number="1", ) assert result["success"] is True assert result["net"] == "VCC" def test_invalid_pin_ref(self, populated_schematic_with_ic): from mckicad.tools.power_symbols import add_power_symbol result = add_power_symbol( schematic_path=populated_schematic_with_ic, net="GND", pin_ref="NONEXISTENT", pin_number="1", ) assert result["success"] is False assert "not found" in result["error"].lower() or "NONEXISTENT" in result["error"] def test_empty_net_rejected(self, populated_schematic_with_ic): from mckicad.tools.power_symbols import add_power_symbol result = add_power_symbol( schematic_path=populated_schematic_with_ic, net="", pin_ref="R1", pin_number="1", ) assert result["success"] is False def test_bad_schematic_path(self): from mckicad.tools.power_symbols import add_power_symbol result = add_power_symbol( schematic_path="/nonexistent/path.kicad_sch", net="GND", pin_ref="R1", pin_number="1", ) assert result["success"] is False