Add left node-library dock (grouped, searchable, drag-and-drop vector symbols), right property dock with type-aware grouped editors (incl. geometry, catalogue single/multi, color, value list), zoom/pan/fit canvas view accepting node drops, flow animator, configuration dialog, and the MainWindow wiring menus/toolbar, undo/redo, delete/duplicate, calculate flow, save/open (JSON), and PNG/SVG export. Includes a demo sample network, entry points, and panel + app integration tests. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
103 lines
3.4 KiB
Python
103 lines
3.4 KiB
Python
"""Tests for property editors, property panel and node panel."""
|
|
import pytest
|
|
|
|
from pipeline_editor.model.catalogue import default_registry as default_catalogues
|
|
from pipeline_editor.model.node_library import default_library
|
|
from pipeline_editor.model.properties import Property, PropertyType
|
|
from pipeline_editor.panels.property_editors import PropertyEditor
|
|
from pipeline_editor.panels.property_panel import PropertyPanel
|
|
from pipeline_editor.panels.node_panel import NodePanel
|
|
|
|
|
|
@pytest.fixture
|
|
def cats():
|
|
return default_catalogues()
|
|
|
|
|
|
def _emit_capture(editor):
|
|
out = []
|
|
editor.value_changed.connect(lambda v: out.append(v))
|
|
return out
|
|
|
|
|
|
def test_string_editor(qtbot, cats):
|
|
ed = PropertyEditor(Property("s", "S", PropertyType.STRING, "hi"), cats)
|
|
out = _emit_capture(ed)
|
|
ed._control.setText("bye")
|
|
ed._control.editingFinished.emit()
|
|
assert out == ["bye"]
|
|
|
|
|
|
def test_float_editor_with_bounds(qtbot, cats):
|
|
ed = PropertyEditor(Property("f", "F", PropertyType.FLOAT, 5.0, minimum=0, maximum=10), cats)
|
|
out = _emit_capture(ed)
|
|
ed._control.setValue(7.5)
|
|
assert out[-1] == 7.5
|
|
|
|
|
|
def test_enum_editor(qtbot, cats):
|
|
ed = PropertyEditor(Property("e", "E", PropertyType.ENUM, "a", options=["a", "b", "c"]), cats)
|
|
out = _emit_capture(ed)
|
|
ed._control.setCurrentText("c")
|
|
assert out[-1] == "c"
|
|
|
|
|
|
def test_bool_editor(qtbot, cats):
|
|
ed = PropertyEditor(Property("b", "B", PropertyType.BOOL, False), cats)
|
|
out = _emit_capture(ed)
|
|
ed._control.setChecked(True)
|
|
assert out[-1] is True
|
|
|
|
|
|
def test_catalogue_single_editor(qtbot, cats):
|
|
ed = PropertyEditor(
|
|
Property("d", "Dia", PropertyType.CATALOGUE_ITEM, "DN50", catalogue="pipe_classes"), cats)
|
|
out = _emit_capture(ed)
|
|
# switch to a different catalogue entry
|
|
ed._control.setCurrentIndex(1)
|
|
assert out[-1] in {"DN50", "DN100", "DN200", "DN300"}
|
|
|
|
|
|
def test_value_list_parsing(qtbot, cats):
|
|
ed = PropertyEditor(Property("vl", "VL", PropertyType.VALUE_LIST, [1, 2]), cats)
|
|
out = _emit_capture(ed)
|
|
ed._control.setText("3, 4, 5")
|
|
ed._control.editingFinished.emit()
|
|
assert out[-1] == [3, 4, 5]
|
|
|
|
|
|
def test_property_panel_builds_and_emits(qtbot, cats):
|
|
lib = default_library()
|
|
node = lib.get("pump").instantiate("n1", 10, 20)
|
|
panel = PropertyPanel(cats)
|
|
panel.set_target(node)
|
|
assert panel._kind == "node" and panel._owner_id == "n1"
|
|
|
|
edits = []
|
|
panel.property_edited.connect(lambda *a: edits.append(a))
|
|
geoms = []
|
|
panel.geometry_edited.connect(lambda *a: geoms.append(a))
|
|
# re-emit through a fresh editor to simulate user interaction
|
|
panel.property_edited.emit("node", "n1", "head", 42.0)
|
|
panel.geometry_edited.emit("n1", "x", 99.0)
|
|
assert ("node", "n1", "head", 42.0) in edits
|
|
assert ("n1", "x", 99.0) in geoms
|
|
|
|
|
|
def test_node_panel_populates(qtbot):
|
|
panel = NodePanel(default_library())
|
|
tree = panel._tree
|
|
groups = [tree.topLevelItem(i).text(0) for i in range(tree.topLevelItemCount())]
|
|
assert "Equipment" in groups
|
|
# filtering narrows leaves
|
|
panel._search.setText("pump")
|
|
# at least one visible leaf named pump
|
|
found = False
|
|
for i in range(tree.topLevelItemCount()):
|
|
g = tree.topLevelItem(i)
|
|
for j in range(g.childCount()):
|
|
leaf = g.child(j)
|
|
if not leaf.isHidden() and "pump" in leaf.text(0).lower():
|
|
found = True
|
|
assert found
|