from unittest.mock import MagicMock, patch import pytest from aare.gui.main_window import MainWindow @pytest.fixture def mock_ui_state(): with patch("aare.gui.main_window.UIStateManager") as mock: yield mock def test_main_window_init(qtbot, mock_ui_state): with ( patch("requests.get") as mock_get, patch("aare.gui.main_window.DAQWorker"), patch("aare.gui.main_window.PredictionSubscriber"), patch("aare.gui.main_window.VideoThread"), patch("aare.gui.main_window.JFJochDBusClient"), patch("aare.gui.main_window.jwt.decode") as mock_jwt, ): mock_get.return_value.status_code = 200 mock_get.return_value.json.return_value = {"status": "ok"} mock_jwt.return_value = { "sub": "testuser", "staff": True, "pgroups": ["p123"], "session": 15, } fake_token = "header.payload.signature" win = MainWindow( base_url="http://localhost:5210", token=fake_token, default_image=None, zmq_addr=None, pred_zmq_addr=None, beamline_cam_addr="localhost", gonio_cam_addr="localhost", gonio_cam_id=1, ) win.show() qtbot.addWidget(win) assert win.windowTitle() == "AareGUI" assert win.isVisible() def test_main_window_mount_view(qtbot, mock_ui_state): with ( patch("requests.get"), patch("aare.gui.main_window.DAQWorker"), patch("aare.gui.main_window.PredictionSubscriber"), patch("aare.gui.main_window.VideoThread"), patch("aare.gui.main_window.JFJochDBusClient"), patch("aare.gui.main_window.jwt.decode") as mock_jwt, ): mock_jwt.return_value = { "sub": "testuser", "staff": True, "pgroups": ["p123"], "session": 15, } fake_token = "header.payload.signature" win = MainWindow( base_url=None, token=fake_token, default_image=None, zmq_addr=None, pred_zmq_addr=None, beamline_cam_addr=None, gonio_cam_addr=None, gonio_cam_id=None, ) qtbot.addWidget(win) win.mount_view() def test_mark_user_interaction_reports_backend(qtbot, mock_ui_state): with ( patch("requests.get"), patch("aare.gui.main_window.DAQWorker"), patch("aare.gui.main_window.PredictionSubscriber"), patch("aare.gui.main_window.VideoThread"), patch("aare.gui.main_window.JFJochDBusClient"), patch("aare.gui.main_window.jwt.decode") as mock_jwt, ): mock_jwt.return_value = { "sub": "testuser", "staff": True, "pgroups": ["p123"], "session": 15, } fake_token = "header.payload.signature" win = MainWindow( base_url=None, token=fake_token, default_image=None, zmq_addr=None, pred_zmq_addr=None, beamline_cam_addr=None, gonio_cam_addr=None, gonio_cam_id=None, ) qtbot.addWidget(win) win._last_interaction_report_ts = -999.0 win._mark_user_interaction() win.daq.report_gui_interaction.assert_called_once_with(15) def test_automation_activity_refreshes_idle_timestamp(qtbot, mock_ui_state): with ( patch("requests.get"), patch("aare.gui.main_window.DAQWorker"), patch("aare.gui.main_window.PredictionSubscriber"), patch("aare.gui.main_window.VideoThread"), patch("aare.gui.main_window.JFJochDBusClient"), patch("aare.gui.main_window.jwt.decode") as mock_jwt, ): from aarecommon.math.coordinate import Coordinate, SmargonCoordinate from aarecommon.math.diffraction_geometry import DiffractionGeometry from aarecommon.math.sample_geometry import SampleGeometryModel from aarecommon.models.models import ( BeamlineStateEnum, BeamlineStatus, CrystalSize, DAQStatusModel, SampleCameraSettings, SessionsStateEnum, SessionStatus, ) mock_jwt.return_value = { "sub": "testuser", "staff": True, "pgroups": ["p123"], "session": 15, } fake_token = "header.payload.signature" win = MainWindow( base_url=None, token=fake_token, default_image=None, zmq_addr=None, pred_zmq_addr=None, beamline_cam_addr=None, gonio_cam_addr=None, gonio_cam_id=None, ) qtbot.addWidget(win) win.job_list_panel.is_running = MagicMock(return_value=True) win._last_user_interaction_ts = 100.0 status = DAQStatusModel( geom=SampleGeometryModel( beam_location_pxl=Coordinate(x=1000, y=1000), pixel_in_mm=0.001, aerotech=Coordinate(), aerotech_meas=Coordinate(), smargon=SmargonCoordinate(sh_mm=Coordinate(), phi_deg=0, chi_deg=0), omega_deg=0, beam_size_mm=Coordinate(x=0.01, y=0.01), ), diffraction=DiffractionGeometry( energy_keV=12.4, dtz_mm=100.0, detector_size_pxl=(1553, 1630), pixel_size_mm=0.150, beam_center_pxl=(750.0, 750.0), detector_description="PILATUS 4", detector_serial_number="1", poni_rot1_rad=0.0, poni_rot2_rad=0.0, ), bl=BeamlineStatus( name="SIMULATED", ring_current_mA=400.0, front_light=50.0, back_light=50.0, cryojet_K=100.0, shutter_open=False, exp_shutter_open=False, flux_ph_s=1e12, sample_camera=SampleCameraSettings(gain=1.0, exposure=0.02), transmission=1.0, zoom=1.0, commissioning_mode=False, dtz_min=120.0, dtz_max=1600.0, ), state=BeamlineStateEnum.SampleAlignment, busy=False, session=SessionStatus( session=SessionsStateEnum.Vacant, current_pgroup="p123", staff=True ), crystal_size=CrystalSize(x=0, y=0, z=0), ) with patch("aare.gui.main_window.time.time", return_value=250.0): win.update_daq_status(status) assert win._last_user_interaction_ts == 250.0 def test_idle_timeout_closes_when_inactive_and_not_running(qtbot, mock_ui_state): with ( patch("requests.get"), patch("aare.gui.main_window.DAQWorker"), patch("aare.gui.main_window.PredictionSubscriber"), patch("aare.gui.main_window.VideoThread"), patch("aare.gui.main_window.JFJochDBusClient"), patch("aare.gui.main_window.jwt.decode") as mock_jwt, ): mock_jwt.return_value = { "sub": "testuser", "staff": True, "pgroups": ["p123"], "session": 15, } fake_token = "header.payload.signature" win = MainWindow( base_url=None, token=fake_token, default_image=None, zmq_addr=None, pred_zmq_addr=None, beamline_cam_addr=None, gonio_cam_addr=None, gonio_cam_id=None, ) qtbot.addWidget(win) win._idle_close_timeout_s = 10 win._last_user_interaction_ts = 100.0 win.close = MagicMock() with patch("aare.gui.main_window.time.time", return_value=111.0): win._check_idle_timeout() win.close.assert_called_once() def test_idle_timeout_does_not_close_while_automation_active(qtbot, mock_ui_state): with ( patch("requests.get"), patch("aare.gui.main_window.DAQWorker"), patch("aare.gui.main_window.PredictionSubscriber"), patch("aare.gui.main_window.VideoThread"), patch("aare.gui.main_window.JFJochDBusClient"), patch("aare.gui.main_window.jwt.decode") as mock_jwt, ): mock_jwt.return_value = { "sub": "testuser", "staff": True, "pgroups": ["p123"], "session": 15, } fake_token = "header.payload.signature" win = MainWindow( base_url=None, token=fake_token, default_image=None, zmq_addr=None, pred_zmq_addr=None, beamline_cam_addr=None, gonio_cam_addr=None, gonio_cam_id=None, ) qtbot.addWidget(win) win._idle_close_timeout_s = 10 win._last_user_interaction_ts = 100.0 win.job_list_panel.is_running = MagicMock(return_value=True) win.close = MagicMock() with patch("aare.gui.main_window.time.time", return_value=111.0): win._check_idle_timeout() win.close.assert_not_called() def test_cleanup_returns_from_portrait_mode(qtbot, mock_ui_state): with ( patch("requests.get"), patch("aare.gui.main_window.DAQWorker"), patch("aare.gui.main_window.PredictionSubscriber"), patch("aare.gui.main_window.VideoThread"), patch("aare.gui.main_window.JFJochDBusClient"), patch("aare.gui.main_window.jwt.decode") as mock_jwt, ): mock_jwt.return_value = { "sub": "testuser", "staff": True, "pgroups": ["p123"], "session": 15, } fake_token = "header.payload.signature" win = MainWindow( base_url=None, token=fake_token, default_image=None, zmq_addr=None, pred_zmq_addr=None, beamline_cam_addr=None, gonio_cam_addr=None, gonio_cam_id=None, ) qtbot.addWidget(win) win.enter_portrait_mode() assert win.content_stack.currentWidget() is win.portrait_mode_page win.cleanup() assert win.content_stack.currentWidget() is win._standard_main_page def test_cleanup_returns_from_compact_automation_view(qtbot, mock_ui_state): with ( patch("requests.get"), patch("aare.gui.main_window.DAQWorker"), patch("aare.gui.main_window.PredictionSubscriber"), patch("aare.gui.main_window.VideoThread"), patch("aare.gui.main_window.JFJochDBusClient"), patch("aare.gui.main_window.jwt.decode") as mock_jwt, ): mock_jwt.return_value = { "sub": "testuser", "staff": True, "pgroups": ["p123"], "session": 15, } fake_token = "header.payload.signature" win = MainWindow( base_url=None, token=fake_token, default_image=None, zmq_addr=None, pred_zmq_addr=None, beamline_cam_addr=None, gonio_cam_addr=None, gonio_cam_id=None, ) qtbot.addWidget(win) win.enter_compact_automation_view() assert win.content_stack.currentWidget() is win.compact_automation_page win.cleanup() assert win.content_stack.currentWidget() is win._standard_main_page