Files
eco/tests/test_assembly_default_widget.py
2026-08-28 14:25:39 +02:00

155 lines
5.0 KiB
Python

from eco.elements.assembly import Assembly
def test_widget_uses_default_widget_override_when_set():
calls = []
class FakeCameraLike(Assembly):
_default_widget = "_widget_viewer"
def _widget_viewer(self):
calls.append("viewer")
return "the viewer object"
obj = FakeCameraLike(name="fake_cam")
result = obj.widget()
assert result == "the viewer object"
assert calls == ["viewer"]
def test_widget_falls_back_to_generic_dispatch_when_no_override(monkeypatch):
calls = []
monkeypatch.setattr(
"eco.utilities.utilities.is_notebook", lambda: True, raising=False
)
monkeypatch.setattr(
"eco.widgets.display_widget.make_assembly_widget",
lambda obj, show_hidden=False: calls.append((obj, show_hidden)) or "generic widget",
raising=False,
)
plain = Assembly(name="plain")
result = plain.widget()
assert result == "generic widget"
assert calls == [(plain, False)]
def test_widget_override_name_pointing_nowhere_falls_back(monkeypatch):
# _default_widget naming a method that doesn't exist shouldn't crash --
# falls back to the generic dispatch instead
monkeypatch.setattr(
"eco.utilities.utilities.is_notebook", lambda: True, raising=False
)
monkeypatch.setattr(
"eco.widgets.display_widget.make_assembly_widget",
lambda obj, show_hidden=False: "generic widget",
raising=False,
)
class BrokenOverride(Assembly):
_default_widget = "no_such_method"
obj = BrokenOverride(name="broken")
assert obj.widget() == "generic widget"
def test_default_widget_is_none_by_default():
assert Assembly._default_widget is None
def test_widget_assembly_bypasses_the_override(monkeypatch):
"""_widget_assembly() is the generic property-grid widget directly --
widget() itself is just a thin dispatcher on top of it (checks
_default_widget, else calls _widget_assembly()). Calling
_widget_assembly() straight always gets the plain grid regardless of
what widget() itself would dispatch to, which is what
eco.widgets.containers.assembly_widget() relies on. Same mocking
rationale as test_widget_normal_true_skips_the_override (avoid
blocking in a real Qt event loop)."""
calls = []
monkeypatch.setattr(
"eco.utilities.utilities.is_notebook", lambda: True, raising=False
)
monkeypatch.setattr(
"eco.widgets.display_widget.make_assembly_widget",
lambda obj, show_hidden=False: "generic widget",
raising=False,
)
class FakeCameraLike(Assembly):
_default_widget = "_widget_viewer"
def _widget_viewer(self):
calls.append("viewer")
return "the viewer object"
obj = FakeCameraLike(name="fake_cam")
result = obj._widget_assembly()
assert calls == [] # override never called
assert result == "generic widget"
def test_widget_normal_true_skips_the_override(monkeypatch):
"""Regression test for a real bug: AxisPTZStreamQt's own "Settings"
button calls cam.widget() wanting the plain property grid, but with
_default_widget = "_widget_viewer" set, plain .widget() just reopened the same
viewer the button was clicked from. normal=True is the escape hatch.
Mocks the generic dispatch target (same as
test_widget_falls_back_to_generic_dispatch_when_no_override) --
without it, normal=True's fallthrough reaches the real
make_assembly_qt_window, which defaults to auto_start=True and blocks
in a real Qt event loop (DisplayQt.start() -> run() -> app.exec_())
since nothing in this test would ever close that window."""
calls = []
monkeypatch.setattr(
"eco.utilities.utilities.is_notebook", lambda: True, raising=False
)
monkeypatch.setattr(
"eco.widgets.display_widget.make_assembly_widget",
lambda obj, show_hidden=False: "generic widget",
raising=False,
)
class FakeCameraLike(Assembly):
_default_widget = "_widget_viewer"
def _widget_viewer(self):
calls.append("viewer")
return "the viewer object"
obj = FakeCameraLike(name="fake_cam")
obj.widget() # normal default (False): uses the override
assert calls == ["viewer"]
result = obj.widget(normal=True)
assert calls == ["viewer"] # override not called a second time
assert result == "generic widget"
def test_widget_normal_true_still_dispatches_generically(monkeypatch):
calls = []
monkeypatch.setattr(
"eco.utilities.utilities.is_notebook", lambda: True, raising=False
)
monkeypatch.setattr(
"eco.widgets.display_widget.make_assembly_widget",
lambda obj, show_hidden=False: calls.append((obj, show_hidden)) or "generic widget",
raising=False,
)
class FakeCameraLike(Assembly):
_default_widget = "_widget_viewer"
def _widget_viewer(self):
return "the viewer object"
obj = FakeCameraLike(name="fake_cam")
result = obj.widget(normal=True)
assert result == "generic widget"
assert calls == [(obj, False)]