kicad-mcp/tests/conftest.py
Ryan Malloy ce65035a17 Add batch operations, power symbols, pattern templates, and schematic editing
New modules:
- patterns/ library: decoupling bank, pull resistor, crystal oscillator
  placement with power symbol attachment and grid math helpers
- tools/batch.py: atomic file-based batch operations with dry_run
- tools/power_symbols.py: add_power_symbol with auto #PWR refs
- tools/schematic_patterns.py: MCP wrappers for pattern library
- tools/schematic_edit.py: modify/remove components, title blocks, annotations
- resources/schematic.py: schematic data resources

43 new tests (99 total), lint clean.
2026-03-04 16:55:09 -07:00

131 lines
4.1 KiB
Python

"""Shared test fixtures for mckicad tests."""
import json
import os
import tempfile
import pytest
# Detect whether kicad-sch-api is available for conditional tests
_HAS_SCH_API = False
try:
from kicad_sch_api import create_schematic, load_schematic # noqa: F401
_HAS_SCH_API = True
except ImportError:
pass
requires_sch_api = pytest.mark.skipif(not _HAS_SCH_API, reason="kicad-sch-api not installed")
@pytest.fixture
def tmp_project_dir(tmp_path):
"""Create a temporary directory with a minimal KiCad project structure."""
project_name = "test_project"
pro_file = tmp_path / f"{project_name}.kicad_pro"
pro_file.write_text('{"meta": {"filename": "test_project.kicad_pro"}}')
sch_file = tmp_path / f"{project_name}.kicad_sch"
sch_file.write_text("(kicad_sch (version 20230121))")
pcb_file = tmp_path / f"{project_name}.kicad_pcb"
pcb_file.write_text("(kicad_pcb (version 20230121))")
return tmp_path
@pytest.fixture
def project_path(tmp_project_dir):
"""Return path to the .kicad_pro file in the temp project."""
return str(tmp_project_dir / "test_project.kicad_pro")
@pytest.fixture
def schematic_path(tmp_project_dir):
"""Return path to the .kicad_sch file in the temp project."""
return str(tmp_project_dir / "test_project.kicad_sch")
@pytest.fixture
def tmp_output_dir():
"""Create a temporary output directory."""
with tempfile.TemporaryDirectory(prefix="mckicad_test_") as d:
yield d
@pytest.fixture
def populated_schematic(tmp_output_dir):
"""Create a schematic with components for testing edit/analysis tools.
Returns the path to the .kicad_sch file, or None if kicad-sch-api
is not installed.
"""
if not _HAS_SCH_API:
pytest.skip("kicad-sch-api not installed")
path = os.path.join(tmp_output_dir, "populated.kicad_sch")
sch = create_schematic("test_populated")
# Add several components
sch.components.add(lib_id="Device:R", reference="R1", value="10k", position=(100, 100))
sch.components.add(lib_id="Device:R", reference="R2", value="4.7k", position=(200, 100))
sch.components.add(lib_id="Device:C", reference="C1", value="100nF", position=(100, 200))
sch.components.add(lib_id="Device:LED", reference="D1", value="Red", position=(200, 200))
# Add a wire
sch.add_wire(start=(100, 100), end=(200, 100))
sch.save(path)
return path
@pytest.fixture
def populated_schematic_with_ic(tmp_output_dir):
"""Create a schematic with multi-pin components for power symbol and pattern tests.
Contains R1 (Device:R) and C1 (Device:C) at known positions. These
2-pin passives have predictable pin layouts suitable for testing
power symbol attachment and pattern placement.
"""
if not _HAS_SCH_API:
pytest.skip("kicad-sch-api not installed")
path = os.path.join(tmp_output_dir, "ic_test.kicad_sch")
sch = create_schematic("ic_test")
sch.components.add(lib_id="Device:R", reference="R1", value="10k", position=(100, 100))
sch.components.add(lib_id="Device:C", reference="C1", value="100nF", position=(200, 100))
sch.save(path)
return path
@pytest.fixture
def batch_json_file(tmp_output_dir):
"""Write a sample batch JSON file and return its path."""
data = {
"components": [
{"lib_id": "Device:R", "reference": "R10", "value": "1k", "x": 100, "y": 100},
{"lib_id": "Device:C", "reference": "C10", "value": "10nF", "x": 200, "y": 100},
],
"wires": [
{"start_x": 100, "start_y": 100, "end_x": 200, "end_y": 100},
],
"labels": [
{"text": "TEST_NET", "x": 150, "y": 80, "global": False},
],
"no_connects": [
{"x": 300, "y": 300},
],
}
path = os.path.join(tmp_output_dir, "test_batch.json")
with open(path, "w") as f:
json.dump(data, f)
return path
@pytest.fixture(autouse=True)
def _set_test_search_paths(tmp_project_dir, monkeypatch):
"""Point KICAD_SEARCH_PATHS at the temp project directory for all tests."""
monkeypatch.setenv("KICAD_SEARCH_PATHS", str(tmp_project_dir))