Files
AareDAQ/tests/conftest.py
T

205 lines
5.4 KiB
Python

import os
import sys
from types import SimpleNamespace
from unittest.mock import MagicMock, patch
import numpy as np
import pytest
from PySide6.QtWidgets import QApplication
from fastapi.testclient import TestClient
from aare.common.models import SampleShortInfo, DewarAddress
# Ensure safe defaults during tests
os.environ.setdefault("BEAMLINE", "SIMULATED")
os.environ.setdefault("QT_QPA_PLATFORM", "offscreen")
os.environ.setdefault("JWT_AAREDAQ_KEY", "test_key_for_unit_testing")
@pytest.fixture
def mock_logger():
return MagicMock()
# -------------------------
# Qt app fixture
# -------------------------
@pytest.fixture(scope="session")
def qapp():
app = QApplication.instance()
if app is None:
app = QApplication(sys.argv)
return app
@pytest.fixture
def sample_info():
return SampleShortInfo(
db_id=1,
puck_name="puck1",
dewar_name="dew1",
sample_name="sample1",
run_number=1,
user="group1",
pin=3,
location=DewarAddress(segment="A", pos=2),
)
# -------------------------
# Shared DAQ server fixtures
# -------------------------
@pytest.fixture(scope="session")
def server_module():
import aare.daq.server as server
return server
@pytest.fixture
def mock_backend(server_module):
with patch.object(server_module, "daq", create=True) as m_daq, \
patch.object(server_module, "bl", create=True) as m_bl, \
patch.object(server_module, "cfg", create=True) as m_cfg:
m_daq.busy = False
m_daq.camera_image = np.zeros((10, 10, 3), dtype=np.uint8)
m_cfg.pgroup = "p12345"
m_cfg.session_state.return_value = "ACTIVE"
m_cfg.GUI_SESSION_EXPIRE_SECONDS = 10
m_cfg.get_open_gui_sessions.return_value = []
m_cfg.get_gui_session.return_value = None
m_cfg.touch_gui_session.return_value = None
yield {
"daq": m_daq,
"bl": m_bl,
"cfg": m_cfg,
}
@pytest.fixture
def auth_token_data():
from aare.daq.auth import TokenData
return TokenData(
sub="testuser",
staff=True,
pgroups=["p12345"],
session=123,
)
@pytest.fixture
def client(server_module, mock_backend, auth_token_data):
with patch("aare.daq.auth.parse_token", return_value=auth_token_data), \
patch("cv2.imencode", return_value=(True, np.array([1, 2, 3], dtype=np.uint8))), \
patch.object(server_module, "mx_beamline", return_value=mock_backend["bl"]), \
patch.object(server_module, "BeamlineConfig", return_value=mock_backend["cfg"]), \
patch.object(server_module, "AareDAQ", return_value=mock_backend["daq"]):
with TestClient(server_module.app) as c:
yield c
@pytest.fixture
def api(client, mock_backend):
return SimpleNamespace(
client=client,
daq=mock_backend["daq"],
bl=mock_backend["bl"],
cfg=mock_backend["cfg"],
)
@pytest.fixture
def daq_status_factory():
from aare.common.coordinate import Coordinate, SmargonCoordinate
from aare.common.diffraction_geometry import DiffractionGeometry
from aare.common.models import (
BeamlineStateEnum,
BeamlineStatus,
CrystalSize,
DAQStatusModel,
SampleCameraSettings,
SampleGeometryModel,
SessionStatus,
SessionsStateEnum,
)
def _build(
*,
state=BeamlineStateEnum.Maintenance,
busy=False,
current_pgroup="p12345",
staff=True,
session_state=SessionsStateEnum.Vacant,
sample=None,
open_guis=None,
):
geom = SampleGeometryModel(
beam_location_pxl=Coordinate(x=500, y=500),
pixel_in_mm=0.001,
aerotech=Coordinate(x=0, y=0, z=0),
aerotech_meas=Coordinate(x=0, y=0, z=0),
smargon=SmargonCoordinate(
sh_mm=Coordinate(x=0, y=0, z=0),
phi_deg=0.0,
chi_deg=0.0,
),
omega_deg=0.0,
beam_size_mm=Coordinate(x=0.01, y=0.01),
)
diff = DiffractionGeometry(
energy_keV=12.0,
dtz_mm=150.0,
pixel_size_mm=0.075,
beam_center_pxl=(1000.0, 1000.0),
detector_size_pxl=(2000, 2000),
detector_description="Eiger 16M",
detector_serial_number="123",
poni_rot1_rad=0.0,
poni_rot2_rad=0.0,
)
bl_status = BeamlineStatus(
name="X06DA",
ring_current_mA=400.0,
omega=0.0,
front_light=0.0,
back_light=0.0,
cryojet_K=100.0,
shutter_open=False,
exp_shutter_open=False,
flux_ph_s=1e12,
transmission=1.0,
zoom=1.0,
sample_camera=SampleCameraSettings(exposure=0.1, gain=1.0),
commissioning_mode=False,
dtz_min=120.0,
dtz_max=1600.0,
)
session = SessionStatus(
session=session_state,
current_pgroup=current_pgroup,
staff=staff,
)
status = DAQStatusModel(
geom=geom,
diffraction=diff,
bl=bl_status,
state=state,
busy=busy,
session=session,
crystal_size=CrystalSize(x=0, y=0, z=0),
sample=sample,
)
if open_guis is not None:
status.open_guis = open_guis
return status
return _build