Files
cimtechniques-service-suite/tests/test_history_dialog.py

186 lines
6.5 KiB
Python

import pytest
from cim_suite.modules.da12.domain.controller import StationController
from cim_suite.modules.da12.protocol import messages as m
from cim_suite.modules.da12.ui.history_dialog import HistoryDialog
def _record(serial="8000B1C9D1003344", sid=1):
return m.SensorRecord(
id=sid, serial=serial, name="Freezer 1", type_text="01",
scale=1.0, offset=0.0, time="12:00:00", average=10.0, value=10.2,
alarm="OK", disp=0, dp=1, calc=0,
)
def test_dialog_opens_and_requests_history(qtbot):
ctrl = StationController()
sent: list[str] = []
class _T:
is_open = True
def start(self): pass
def stop(self): pass
def write(self, cmd): sent.append(cmd)
ctrl.attach(_T())
dlg = HistoryDialog(ctrl, _record(), None)
qtbot.addWidget(dlg)
dlg.pull_history()
assert any(s.startswith("{c001") for s in sent)
def test_dialog_appends_live_point(qtbot):
ctrl = StationController()
dlg = HistoryDialog(ctrl, _record(), None)
qtbot.addWidget(dlg)
start = dlg.point_count()
ctrl._process("{C01\t0066}") # current 10.2 for sensor 1
assert dlg.point_count() > start
def test_dialog_export_sheet_nonempty_after_live(qtbot):
ctrl = StationController()
dlg = HistoryDialog(ctrl, _record(), None)
qtbot.addWidget(dlg)
ctrl._process("{C01\t0066}")
sheet = dlg.build_export_sheet()
assert sheet.headers and len(sheet.rows) >= 1
def test_dialog_only_reacts_to_its_sensor(qtbot):
ctrl = StationController()
dlg = HistoryDialog(ctrl, _record(sid=1), None)
qtbot.addWidget(dlg)
start = dlg.point_count()
ctrl._process("{C02\t0066}") # different sensor
assert dlg.point_count() == start
def test_dialog_draws_limit_lines_from_limits(qtbot):
ctrl = StationController()
ctrl.limits.upsert(m.AlarmLimits(id=1, enable=1, delay=0,
lo_alarm=0.0, lo_warn=2.0, hi_warn=20.0, hi_alarm=25.0))
dlg = HistoryDialog(ctrl, _record(sid=1), None)
qtbot.addWidget(dlg)
# Two samples with distinct timestamps so the x-axis has a non-zero range
ctrl.history.record_live(1, current=10.0, timestamp=1000000)
ctrl.history.record_live(1, current=11.0, timestamp=1000060)
ctrl.historyChanged.emit(1)
visible = [ls for ls in dlg._limit_series if ls.isVisible()]
assert len(visible) == 4 # all four limits set -> four guide lines shown
def test_dialog_disconnects_on_close(qtbot):
ctrl = StationController()
dlg = HistoryDialog(ctrl, _record(sid=1), None)
qtbot.addWidget(dlg)
ctrl._process("{C01\t0066}")
before = dlg.point_count()
dlg.close()
ctrl._process("{C01\t0066}") # should NOT trigger a reload now
assert dlg.point_count() == before
def test_dialog_expected_interval_reads_setting_6(qtbot):
ctrl = StationController()
ctrl.settings.upsert(m.SettingLine(row=6, text="Update Interval\t30", type_code=0))
dlg = HistoryDialog(ctrl, _record(sid=1), None)
qtbot.addWidget(dlg)
assert dlg._expected_interval_ms() == 30000
# ---------------------------------------------------------------------------
# §5.10 chart restyling tests
# ---------------------------------------------------------------------------
def test_chart_styled_per_spec(qtbot):
from PySide6.QtCore import Qt
from cim_suite.core.ui.theme import current, qcolor
ctrl = StationController()
dlg = HistoryDialog(ctrl, _record(), None)
qtbot.addWidget(dlg)
t = current()
# Average series pen width and color
assert dlg._avg.pen().widthF() == pytest.approx(1.6)
assert dlg._avg.pen().color().name() == qcolor(t.chart["average"]).name()
# Chart background is surface
assert dlg._chart.backgroundBrush().color().name() == qcolor(t.surface).name()
# All four limit-line series use CustomDashLine
for ls in dlg._limit_series:
assert ls.pen().style() == Qt.PenStyle.CustomDashLine
# Low lines (indices 0 and 1) have ~55% opacity; hi lines (2 and 3) are opaque
assert dlg._limit_series[0].pen().color().alphaF() == pytest.approx(0.55, abs=0.02)
assert dlg._limit_series[1].pen().color().alphaF() == pytest.approx(0.55, abs=0.02)
assert dlg._limit_series[3].pen().color().alphaF() == pytest.approx(1.0, abs=0.02)
def test_header_strip_names_the_sensor(qtbot):
ctrl = StationController()
dlg = HistoryDialog(ctrl, _record(), None)
qtbot.addWidget(dlg)
assert dlg._header.text().startswith("LIVE TREND — #")
def test_axis_ticks_are_faint(qtbot):
from cim_suite.core.ui.theme import current, qcolor
ctrl = StationController()
dlg = HistoryDialog(ctrl, _record(), None)
qtbot.addWidget(dlg)
t = current()
expected = qcolor(t.faint).name()
assert dlg._axis_x.labelsBrush().color().name() == expected
def test_limit_legend_markers_hidden_after_draw(qtbot):
"""Regression: §5.10 limit-guide series must never appear in the legend.
QtCharts re-shows a series' legend marker when setVisible(True) is called;
_draw_limit_lines must suppress those markers after each draw.
"""
ctrl = StationController()
ctrl.limits.upsert(m.AlarmLimits(id=1, enable=1, delay=0,
lo_alarm=0.0, lo_warn=2.0, hi_warn=20.0, hi_alarm=25.0))
dlg = HistoryDialog(ctrl, _record(sid=1), None)
qtbot.addWidget(dlg)
# Give the x-axis a non-zero range so the limit lines become visible.
ctrl.history.record_live(1, current=10.0, timestamp=1000000)
ctrl.history.record_live(1, current=11.0, timestamp=1000060)
ctrl.historyChanged.emit(1)
# All four limit series are visible (confirmed by the existing test above).
assert all(ls.isVisible() for ls in dlg._limit_series)
# Every legend marker for each limit series must be hidden.
legend = dlg._chart.legend()
for ls in dlg._limit_series:
for marker in legend.markers(ls):
assert not marker.isVisible(), (
"Limit-series legend marker should be hidden but isVisible()=True"
)
def test_theme_switch_restyles(qtbot, monkeypatch):
import cim_suite.core.ui.theme.manager as _mgr
from cim_suite.core.ui.theme import qcolor
from cim_suite.core.ui.theme.tokens import DARK
ctrl = StationController()
dlg = HistoryDialog(ctrl, _record(), None)
qtbot.addWidget(dlg)
# Switch to dark theme by monkeypatching the module-level name.
monkeypatch.setattr(_mgr, "_current_name", "dark")
dlg._apply_chart_theme()
expected_avg_color = qcolor(DARK.chart["average"]).name()
assert dlg._avg.pen().color().name() == expected_avg_color