test: cover the beamline state bar
Availability sets (routes + menu shortcuts, Moving/unknown), signal gating, palette and cursors per availability, red/blue active states, adaptive label wrapping, left-click hint paths, hover-hint timer lifecycle, and pending-target clearing. Lifts the PR diff coverage back over the 80 percent gate (measured 88 percent locally). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
7a57d85282
commit
3175e437a4
1 file changed
+122
@@ -0,0 +1,122 @@
|
||||
from aarecommon.models.models import BeamlineStateEnum
|
||||
from PySide6.QtCore import Qt
|
||||
|
||||
from aare.gui.panels.beamline_state_panel import BeamlineStatePanel
|
||||
|
||||
|
||||
def _panel(qtbot):
|
||||
panel = BeamlineStatePanel()
|
||||
qtbot.addWidget(panel)
|
||||
return panel
|
||||
|
||||
|
||||
def test_availability_from_maintenance(qtbot):
|
||||
panel = _panel(qtbot)
|
||||
panel.set_current_state(BeamlineStateEnum.Maintenance)
|
||||
assert panel._available_targets() == frozenset({BeamlineStateEnum.SampleExchange})
|
||||
|
||||
|
||||
def test_availability_is_union_of_routes_and_menu_shortcuts(qtbot):
|
||||
panel = _panel(qtbot)
|
||||
panel.set_current_state(BeamlineStateEnum.SampleAlignment)
|
||||
targets = panel._available_targets()
|
||||
assert BeamlineStateEnum.FluxMeasurement in targets # one-hop route
|
||||
assert BeamlineStateEnum.SampleExchange in targets # status-bar shortcut
|
||||
assert BeamlineStateEnum.XtalSnapshot not in targets # two hops away
|
||||
|
||||
|
||||
def test_no_targets_while_moving_or_unknown(qtbot):
|
||||
panel = _panel(qtbot)
|
||||
panel.set_current_state(None)
|
||||
assert panel._available_targets() == frozenset()
|
||||
panel.set_current_state(BeamlineStateEnum.Moving)
|
||||
assert panel._available_targets() == frozenset()
|
||||
|
||||
|
||||
def test_emit_gated_by_availability(qtbot):
|
||||
panel = _panel(qtbot)
|
||||
panel.set_current_state(BeamlineStateEnum.Maintenance)
|
||||
with qtbot.waitSignal(panel.sample_exchange, timeout=1000):
|
||||
panel._emit_for_state(BeamlineStateEnum.SampleExchange)
|
||||
with qtbot.assertNotEmitted(panel.flux_measurement):
|
||||
panel._emit_for_state(BeamlineStateEnum.FluxMeasurement)
|
||||
|
||||
|
||||
def test_active_maintenance_is_red_and_bold(qtbot):
|
||||
panel = _panel(qtbot)
|
||||
panel.set_current_state(BeamlineStateEnum.Maintenance)
|
||||
maintenance = panel._buttons[BeamlineStateEnum.Maintenance]
|
||||
assert maintenance.font().bold()
|
||||
assert "rgb(200, 30, 30)" in maintenance.styleSheet()
|
||||
|
||||
|
||||
def test_availability_palette_and_cursors(qtbot):
|
||||
panel = _panel(qtbot)
|
||||
panel.set_current_state(BeamlineStateEnum.Maintenance)
|
||||
available = panel._buttons[BeamlineStateEnum.SampleExchange]
|
||||
grey = panel._buttons[BeamlineStateEnum.FluxMeasurement]
|
||||
assert "rgb(237, 137, 54)" in available.styleSheet()
|
||||
assert available.cursor().shape() == Qt.CursorShape.PointingHandCursor
|
||||
assert not available.font().bold()
|
||||
assert "rgb(140, 150, 165)" in grey.styleSheet()
|
||||
assert grey.cursor().shape() == Qt.CursorShape.ForbiddenCursor
|
||||
assert grey.toolTip() == ""
|
||||
assert available.toolTip() != ""
|
||||
|
||||
|
||||
def test_active_non_maintenance_is_blue(qtbot):
|
||||
panel = _panel(qtbot)
|
||||
panel.set_current_state(BeamlineStateEnum.SampleAlignment)
|
||||
active = panel._buttons[BeamlineStateEnum.SampleAlignment]
|
||||
assert active.font().bold()
|
||||
assert "rgb(0, 92, 170)" in active.styleSheet()
|
||||
|
||||
|
||||
def test_labels_wrap_when_narrow_and_unwrap_when_wide(qtbot):
|
||||
panel = _panel(qtbot)
|
||||
sample_exchange = panel._buttons[BeamlineStateEnum.SampleExchange]
|
||||
|
||||
panel.resize(600, 60)
|
||||
panel._update_label_mode()
|
||||
assert not panel._single_line
|
||||
assert sample_exchange.text() == "Manual sample\nexchange"
|
||||
|
||||
panel.resize(4000, 60)
|
||||
panel._update_label_mode()
|
||||
assert panel._single_line
|
||||
assert sample_exchange.text() == "Manual sample exchange"
|
||||
|
||||
|
||||
def test_left_click_never_transitions_but_hints(qtbot):
|
||||
panel = _panel(qtbot)
|
||||
panel.set_current_state(BeamlineStateEnum.Maintenance)
|
||||
with qtbot.assertNotEmitted(panel.sample_exchange):
|
||||
panel._on_left_click(BeamlineStateEnum.SampleExchange) # reminder tip
|
||||
panel._on_left_click(BeamlineStateEnum.FluxMeasurement) # reachability hint
|
||||
panel._on_left_click(BeamlineStateEnum.Maintenance) # current: no-op
|
||||
|
||||
|
||||
def test_hover_hint_timer_lifecycle(qtbot):
|
||||
panel = _panel(qtbot)
|
||||
panel.set_current_state(BeamlineStateEnum.Maintenance)
|
||||
panel._set_hovered_state(BeamlineStateEnum.FluxMeasurement)
|
||||
assert panel._hover_hint_timer.isActive()
|
||||
panel._show_hover_hint() # runs the unavailable-hint path
|
||||
panel._clear_hovered_state()
|
||||
assert not panel._hover_hint_timer.isActive()
|
||||
assert panel._hovered_state is None
|
||||
|
||||
|
||||
def test_update_daq_status_sets_state(qtbot, daq_status_factory):
|
||||
panel = _panel(qtbot)
|
||||
panel.update_daq_status(daq_status_factory(state=BeamlineStateEnum.SampleAlignment))
|
||||
assert panel._current_state == BeamlineStateEnum.SampleAlignment
|
||||
|
||||
|
||||
def test_pending_target_cleared_on_arrival(qtbot):
|
||||
panel = _panel(qtbot)
|
||||
panel.set_current_state(BeamlineStateEnum.Maintenance)
|
||||
panel._emit_for_state(BeamlineStateEnum.SampleExchange)
|
||||
assert panel._pending_target_state == BeamlineStateEnum.SampleExchange
|
||||
panel.set_current_state(BeamlineStateEnum.SampleExchange)
|
||||
assert panel._pending_target_state is None
|
||||
Reference in new issue
Block a user