import pytest from unittest.mock import MagicMock, patch from PySide6.QtCore import Qt 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") as mock_daq_cls, \ 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 aare.common.models import ( DAQStatusModel, SessionStatus, BeamlineStatus, SampleCameraSettings, CrystalSize, SessionsStateEnum, BeamlineStateEnum, ) from aare.common.coordinate import Coordinate, SmargonCoordinate from aare.common.diffraction_geometry import DiffractionGeometry from aare.common.sample_geometry import SampleGeometryModel 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()