Files
csaxs_bec/tests/tests_bec_ipython_client/test_gui_tools.py
T
x01dcandClaude Sonnet 5 7c2311a1f0
CI for csaxs_bec / test (push) Successful in 2m40s
fix(LamNI): reset stale live-view channel, add GUI status/toggle switches
A Ctrl-C interrupting an in-flight RPC call (e.g. mid
set_live_view_signal) could leave the XRayEye widget stuck showing the
smear-preview channel afterward -- and since lamnigui_show_xeyealign()
reuses the existing xeyegui widget across calls rather than recreating
it, that stale state would silently carry into the *next* alignment
run too (including production align()/find_rotation_center(), since
on_live_view_enabled() now respects whichever channel is selected).

Fix: lamnigui_show_xeyealign() unconditionally resets both
set_live_view_signal("image") and set_smear_active(False) every time
it's called -- both are cheap no-ops if already in the default state,
and this is the single shared entry point for every alignment
procedure, so one fix covers all of them.

Also add two GUI-facing controls to XRayEye, in a new row below the
shutter/camera-running toggles:
- "Smear preview channel" -- an interactive toggle mirroring
  set_live_view_signal(), so the operator has a GUI-only recovery path
  independent of the ipython client (e.g. if it's hung/disconnected).
- "Smear integrating" -- a read-only status indicator (disabled
  ToggleSwitch) reflecting whether _smear_sweep() is currently
  accumulating a composite, driven entirely by the automation.

set_live_view_signal() keeps the interactive toggle's visual state in
sync regardless of who changed the channel (automation or operator) --
single source of truth. _smear_sweep() brackets accumulation with
set_smear_active(True)/(False), turning it off as soon as the sweep
ends (independent of the channel switch, which stays on the composite
until the operator's click is collected). Both new XRayEye methods
required regenerating csaxs_bec/bec_widgets/widgets/client.py via
bw-generate-cli --target csaxs_bec.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-24 15:23:17 +02:00

55 lines
2.0 KiB
Python

"""Unit tests for LamniGuiTools.lamnigui_show_xeyealign()'s live-view reset."""
from unittest import mock
from csaxs_bec.bec_ipython_client.plugins.LamNI.gui_tools import LamniGuiTools
# pylint: disable=protected-access
GUI_TOOLS = "csaxs_bec.bec_ipython_client.plugins.LamNI.gui_tools"
def _make_gui_tools():
tools = LamniGuiTools()
client = mock.MagicMock()
tools.set_client(client)
return tools, client
def test_lamnigui_show_xeyealign_resets_live_view_on_reuse():
"""A previously-interrupted run (e.g. Ctrl-C mid set_live_view_signal)
could leave xeyegui stuck on the smear channel/indicator; since the
widget is reused (not recreated) across calls, opening the alignment
view must reset both every time, not just on first creation."""
tools, client = _make_gui_tools()
tools.xeyegui = mock.MagicMock()
tools.xeyegui._is_deleted.return_value = False
client.gui.windows = {"lamni": mock.MagicMock()}
dev_mock = mock.MagicMock()
dev_mock.cam_xeye.live_mode_enabled.get.return_value = True
with mock.patch(f"{GUI_TOOLS}.dev", dev_mock, create=True):
tools.lamnigui_show_xeyealign()
tools.xeyegui.set_live_view_signal.assert_called_once_with("image")
tools.xeyegui.set_smear_active.assert_called_once_with(False)
def test_lamnigui_show_xeyealign_resets_on_fresh_widget_too():
"""Even a freshly-created widget gets the reset call -- cheap/no-op,
and keeps the behavior uniform regardless of prior state."""
tools, client = _make_gui_tools()
client.gui.windows = {"lamni": mock.MagicMock()}
new_widget = mock.MagicMock()
client.gui.lamni.new.return_value = new_widget
dev_mock = mock.MagicMock()
dev_mock.cam_xeye.live_mode_enabled.get.return_value = True
with mock.patch(f"{GUI_TOOLS}.dev", dev_mock, create=True):
tools.lamnigui_show_xeyealign()
new_widget.set_live_view_signal.assert_called_once_with("image")
new_widget.set_smear_active.assert_called_once_with(False)