Add UI-agnostic model layer: typed grouped properties (string/int/float/ bool/enum/color/catalogue item(s)/value list), catalogue registry, port relations with color schemes and compatibility rules, ports, node/edge models, and DiagramDocument with change signals and JSON round-trip. Include a starter node library (source/tank/pump/valve/junction/consumer/ transformer) with matching SVG symbols, plus model+document tests. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
81 lines
2.6 KiB
Python
81 lines
2.6 KiB
Python
"""DiagramDocument tests: add/remove, connect rules, signals, serialization."""
|
|
import pytest
|
|
|
|
from pipeline_editor.model.document import DiagramDocument
|
|
from pipeline_editor.model.edge import EdgeModel
|
|
from pipeline_editor.model.node_library import default_library
|
|
|
|
|
|
@pytest.fixture
|
|
def doc(qapp):
|
|
return DiagramDocument()
|
|
|
|
|
|
@pytest.fixture
|
|
def lib():
|
|
return default_library()
|
|
|
|
|
|
def _add(doc, lib, key, x, y):
|
|
node = lib.get(key).instantiate(doc.next_id("n"), x, y)
|
|
return doc.add_node(node)
|
|
|
|
|
|
def test_add_and_signals(doc, lib):
|
|
events = []
|
|
doc.node_added.connect(lambda nid: events.append(("node", nid)))
|
|
doc.edge_added.connect(lambda eid: events.append(("edge", eid)))
|
|
a = _add(doc, lib, "source", 0, 0)
|
|
b = _add(doc, lib, "pump", 200, 0)
|
|
edge = EdgeModel(doc.next_id("e"), a.node_id, "out", b.node_id, "in")
|
|
doc.add_edge(edge)
|
|
assert ("node", a.node_id) in events
|
|
assert ("edge", edge.edge_id) in events
|
|
assert doc.dirty is True
|
|
|
|
|
|
def test_connect_rules(doc, lib):
|
|
a = _add(doc, lib, "source", 0, 0) # water out
|
|
b = _add(doc, lib, "pump", 200, 0) # water in
|
|
t = _add(doc, lib, "transformer", 0, 200) # power ports
|
|
assert doc.can_connect(a.node_id, "out", b.node_id, "in") is True
|
|
assert doc.can_connect(a.node_id, "out", t.node_id, "hv") is False # water vs power
|
|
assert doc.can_connect(a.node_id, "out", a.node_id, "out") is False # same port
|
|
|
|
|
|
def test_remove_node_cascades_edges(doc, lib):
|
|
a = _add(doc, lib, "source", 0, 0)
|
|
b = _add(doc, lib, "pump", 200, 0)
|
|
e = doc.add_edge(EdgeModel(doc.next_id("e"), a.node_id, "out", b.node_id, "in"))
|
|
removed = doc.remove_node(a.node_id)
|
|
assert e.edge_id in removed
|
|
assert doc.edge(e.edge_id) is None
|
|
assert doc.node(a.node_id) is None
|
|
|
|
|
|
def test_edge_inherits_relation(doc, lib):
|
|
a = _add(doc, lib, "source", 0, 0)
|
|
b = _add(doc, lib, "pump", 200, 0)
|
|
e = doc.add_edge(EdgeModel(doc.next_id("e"), a.node_id, "out", b.node_id, "in"))
|
|
assert e.relation == "water"
|
|
|
|
|
|
def test_serialization_roundtrip(doc, lib):
|
|
a = _add(doc, lib, "source", 10, 20)
|
|
b = _add(doc, lib, "consumer", 300, 20)
|
|
a.properties.set_value("supply", 200)
|
|
doc.add_edge(EdgeModel(doc.next_id("e"), a.node_id, "out", b.node_id, "in"))
|
|
text = doc.to_json()
|
|
|
|
doc2 = DiagramDocument.from_json(text)
|
|
assert list(n.node_id for n in doc2.nodes()) == [a.node_id, b.node_id]
|
|
ra = doc2.node(a.node_id)
|
|
assert ra.x == 10 and ra.properties.value("supply") == 200
|
|
assert sum(1 for _ in doc2.edges()) == 1
|
|
|
|
|
|
def test_clear(doc, lib):
|
|
_add(doc, lib, "source", 0, 0)
|
|
doc.clear()
|
|
assert len(doc) == 0
|