"""Tests for the batch operations tool.""" import json import os from tests.conftest import requires_sch_api class TestBatchValidation: """Tests for batch JSON validation (no kicad-sch-api needed for some).""" def test_bad_json_file(self, tmp_output_dir): from mckicad.tools.batch import apply_batch # Create a schematic file (minimal) sch_path = os.path.join(tmp_output_dir, "test.kicad_sch") with open(sch_path, "w") as f: f.write("(kicad_sch (version 20230121))") # Create a bad JSON file bad_json = os.path.join(tmp_output_dir, "bad.json") with open(bad_json, "w") as f: f.write("{invalid json}") result = apply_batch( schematic_path=sch_path, batch_file=bad_json, ) assert result["success"] is False assert "json" in result["error"].lower() or "JSON" in result["error"] def test_nonexistent_batch_file(self, tmp_output_dir): from mckicad.tools.batch import apply_batch sch_path = os.path.join(tmp_output_dir, "test.kicad_sch") with open(sch_path, "w") as f: f.write("(kicad_sch (version 20230121))") result = apply_batch( schematic_path=sch_path, batch_file="/nonexistent/batch.json", ) assert result["success"] is False assert "not found" in result["error"].lower() def test_bad_schematic_path(self, batch_json_file): from mckicad.tools.batch import apply_batch result = apply_batch( schematic_path="/nonexistent/path.kicad_sch", batch_file=batch_json_file, ) assert result["success"] is False @requires_sch_api class TestBatchDryRun: """Tests for batch dry_run mode.""" def test_dry_run_returns_preview(self, populated_schematic_with_ic, batch_json_file): from mckicad.tools.batch import apply_batch result = apply_batch( schematic_path=populated_schematic_with_ic, batch_file=batch_json_file, dry_run=True, ) assert result["success"] is True assert result["dry_run"] is True assert "preview" in result assert result["preview"]["components"] == 2 assert result["preview"]["wires"] == 1 assert result["preview"]["labels"] == 1 assert result["preview"]["no_connects"] == 1 assert result["validation"] == "passed" def test_dry_run_catches_missing_fields(self, populated_schematic_with_ic, tmp_output_dir): from mckicad.tools.batch import apply_batch bad_data = { "components": [{"lib_id": "Device:R"}], # missing x, y } batch_path = os.path.join(tmp_output_dir, "bad_batch.json") with open(batch_path, "w") as f: json.dump(bad_data, f) result = apply_batch( schematic_path=populated_schematic_with_ic, batch_file=batch_path, dry_run=True, ) assert result["success"] is False assert "validation_errors" in result def test_empty_batch_rejected(self, populated_schematic_with_ic, tmp_output_dir): from mckicad.tools.batch import apply_batch batch_path = os.path.join(tmp_output_dir, "empty_batch.json") with open(batch_path, "w") as f: json.dump({}, f) result = apply_batch( schematic_path=populated_schematic_with_ic, batch_file=batch_path, ) assert result["success"] is False @requires_sch_api class TestBatchApply: """Integration tests for applying batch operations.""" def test_apply_components_and_wires(self, populated_schematic_with_ic, batch_json_file): from kicad_sch_api import load_schematic from mckicad.tools.batch import apply_batch result = apply_batch( schematic_path=populated_schematic_with_ic, batch_file=batch_json_file, ) assert result["success"] is True assert result["components_placed"] == 2 assert result["wires_placed"] == 1 assert result["labels_placed"] == 1 assert result["no_connects_placed"] == 1 # Verify components exist in saved schematic sch = load_schematic(populated_schematic_with_ic) r10 = sch.components.get("R10") assert r10 is not None assert r10.value == "1k" def test_apply_with_power_symbols(self, populated_schematic_with_ic, tmp_output_dir): from mckicad.tools.batch import apply_batch data = { "components": [ {"lib_id": "Device:C", "reference": "C20", "value": "100nF", "x": 300, "y": 100}, ], "power_symbols": [ {"net": "GND", "pin_ref": "C20", "pin_number": "2"}, ], } batch_path = os.path.join(tmp_output_dir, "pwr_batch.json") with open(batch_path, "w") as f: json.dump(data, f) result = apply_batch( schematic_path=populated_schematic_with_ic, batch_file=batch_path, ) assert result["success"] is True assert result["components_placed"] == 1 assert result["power_symbols_placed"] == 1 def test_mckicad_sidecar_lookup(self, populated_schematic_with_ic, tmp_output_dir): """Test that relative paths resolve to .mckicad/ directory.""" from mckicad.tools.batch import apply_batch # Create .mckicad/ sidecar next to schematic sch_dir = os.path.dirname(populated_schematic_with_ic) mckicad_dir = os.path.join(sch_dir, ".mckicad") os.makedirs(mckicad_dir, exist_ok=True) data = { "labels": [{"text": "SIDECAR_TEST", "x": 100, "y": 100}], } sidecar_path = os.path.join(mckicad_dir, "sidecar_batch.json") with open(sidecar_path, "w") as f: json.dump(data, f) # Use relative path — should find it in .mckicad/ result = apply_batch( schematic_path=populated_schematic_with_ic, batch_file="sidecar_batch.json", ) assert result["success"] is True assert result["labels_placed"] == 1