kicad-mcp/tests/test_schematic_edit.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

177 lines
5.1 KiB
Python

"""Tests for schematic editing tools."""
import os
import pytest
from tests.conftest import requires_sch_api
@requires_sch_api
@pytest.mark.unit
class TestModifyComponent:
"""Tests for the modify_component tool."""
def test_modify_value(self, populated_schematic):
from mckicad.tools.schematic_edit import modify_component
result = modify_component(
schematic_path=populated_schematic,
reference="R1",
value="22k",
)
assert result["success"] is True
assert any("value" in m for m in result["modified"])
def test_modify_nonexistent_component(self, populated_schematic):
from mckicad.tools.schematic_edit import modify_component
result = modify_component(
schematic_path=populated_schematic,
reference="Z99",
value="1k",
)
assert result["success"] is False
assert "error" in result
def test_modify_no_changes(self, populated_schematic):
from mckicad.tools.schematic_edit import modify_component
result = modify_component(
schematic_path=populated_schematic,
reference="R1",
)
assert result["success"] is True
assert result.get("modified") == []
@requires_sch_api
@pytest.mark.unit
class TestRemoveComponent:
"""Tests for the remove_component tool."""
def test_remove_existing(self, populated_schematic):
from mckicad.tools.schematic_edit import remove_component
result = remove_component(
schematic_path=populated_schematic,
reference="R2",
)
assert result["success"] is True
assert result["reference"] == "R2"
def test_remove_nonexistent(self, populated_schematic):
from mckicad.tools.schematic_edit import remove_component
result = remove_component(
schematic_path=populated_schematic,
reference="Z99",
)
assert result["success"] is False
@requires_sch_api
@pytest.mark.unit
class TestBackupSchematic:
"""Tests for the backup_schematic tool."""
def test_backup_creates_file(self, populated_schematic):
from mckicad.tools.schematic_edit import backup_schematic
result = backup_schematic(schematic_path=populated_schematic)
assert result["success"] is True
assert "backup_path" in result
assert os.path.isfile(result["backup_path"])
@pytest.mark.unit
class TestValidation:
"""Tests for input validation in edit tools."""
def test_invalid_path_extension(self):
from mckicad.tools.schematic_edit import modify_component
result = modify_component(
schematic_path="/tmp/test.txt",
reference="R1",
value="1k",
)
assert result["success"] is False
assert ".kicad_sch" in result["error"]
def test_empty_path(self):
from mckicad.tools.schematic_edit import remove_component
result = remove_component(schematic_path="", reference="R1")
assert result["success"] is False
def test_nonexistent_file(self):
from mckicad.tools.schematic_edit import set_title_block
result = set_title_block(
schematic_path="/tmp/nonexistent.kicad_sch",
title="Test",
)
assert result["success"] is False
@requires_sch_api
@pytest.mark.unit
class TestSetTitleBlock:
"""Tests for the set_title_block tool."""
def test_set_fields(self, populated_schematic):
from mckicad.tools.schematic_edit import set_title_block
result = set_title_block(
schematic_path=populated_schematic,
title="Test Circuit",
revision="1.0",
)
assert result["success"] is True
assert "title" in result.get("fields_set", [])
def test_set_author(self, populated_schematic):
from mckicad.tools.schematic_edit import set_title_block
result = set_title_block(
schematic_path=populated_schematic,
author="Test Author",
)
assert result["success"] is True
assert "author" in result.get("fields_set", [])
def test_no_fields_is_noop(self, populated_schematic):
from mckicad.tools.schematic_edit import set_title_block
result = set_title_block(schematic_path=populated_schematic)
assert result["success"] is True
assert result.get("fields_set") == []
@requires_sch_api
@pytest.mark.unit
class TestAnnotationTools:
"""Tests for add_text_annotation and add_no_connect."""
def test_add_text(self, populated_schematic):
from mckicad.tools.schematic_edit import add_text_annotation
result = add_text_annotation(
schematic_path=populated_schematic,
text="Test note",
x=50,
y=50,
)
assert result["success"] is True
def test_add_no_connect(self, populated_schematic):
from mckicad.tools.schematic_edit import add_no_connect
result = add_no_connect(
schematic_path=populated_schematic,
x=300,
y=300,
)
assert result["success"] is True