"""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))