diff --git a/bec_widgets/examples/extreme/extreme.py b/bec_widgets/examples/extreme/extreme.py index b4e8c99e..07c39d7f 100644 --- a/bec_widgets/examples/extreme/extreme.py +++ b/bec_widgets/examples/extreme/extreme.py @@ -1,6 +1,8 @@ import logging import os +# import traceback + import pyqtgraph import pyqtgraph as pg from PyQt5.QtCore import pyqtSignal, pyqtSlot @@ -595,6 +597,7 @@ class ErrorHandler: logging.basicConfig(level=logging.ERROR) # Configure logging def handle_error(self, error_message: str, retry_action=None): + # logging.error(f"{error_message}\n{traceback.format_exc()}") #TODO decide if useful retry_action = self.parent.load_settings_from_yaml choice = QMessageBox.critical( @@ -679,9 +682,6 @@ class ErrorHandler: self.errors.append(error_msg) # TODO add condition for name and entry - def retry_action_test(self): - print("Retry action") - if __name__ == "__main__": import yaml diff --git a/tests/test_extreme.py b/tests/test_extreme.py index 4c35c14b..a7cc39dc 100644 --- a/tests/test_extreme.py +++ b/tests/test_extreme.py @@ -1,9 +1,11 @@ -from unittest.mock import MagicMock +import unittest +from unittest.mock import MagicMock, patch import pyqtgraph as pg import pytest +from PyQt5.QtWidgets import QMessageBox -from bec_widgets.examples.extreme.extreme import PlotApp +from bec_widgets.examples.extreme.extreme import PlotApp, ErrorHandler def setup_plot_app(qtbot, config): @@ -11,9 +13,15 @@ def setup_plot_app(qtbot, config): client = MagicMock() widget = PlotApp(config=config, client=client) qtbot.addWidget(widget) + qtbot.waitExposed(widget) return widget +@pytest.fixture +def error_handler(): + return ErrorHandler() + + config_device_mode_all_filled = { "plot_settings": { "background_color": "black", @@ -167,6 +175,28 @@ config_scan_mode = config = { }, } +config_all_wrong = { + "plot_settings": { + "background_color": "white", + "num_columns": 1, + "colormap": "plasma", + "scan_types": False, + }, + "plot_data": [ + { + "plot_name": "BPM4i plots vs samx", + "x": { + "label": "Motor Y", + # signals are missing + }, + "y": { + "label": "bpm4i", + "signals": [{"name": "bpm4i", "entry": "gauss_bpm"}], # wrong entry + }, + }, + ], +} + @pytest.mark.parametrize( "config, plot_setting_bg, num_plot ,pg_background", @@ -345,6 +375,7 @@ def test_on_scan_segment(qtbot, config, msg, metadata, expected_data, mock_hints plot_app.data = {} plot_app.scanID = 0 + # Get hints plot_app.dev.__getitem__.side_effect = mock_getitem plot_app.on_scan_segment(msg, metadata) @@ -371,7 +402,7 @@ def test_on_scan_segment(qtbot, config, msg, metadata, expected_data, mock_hints ), ], ) -def test_on_scan_segment_error_handling(qtbot, config, msg, metadata, expected_exception_message): +def test_on_scan_message_error_handling(qtbot, config, msg, metadata, expected_exception_message): plot_app = setup_plot_app(qtbot, config) # Initialize @@ -384,3 +415,59 @@ def test_on_scan_segment_error_handling(qtbot, config, msg, metadata, expected_e with pytest.raises(ValueError) as exc_info: plot_app.on_scan_segment(msg, metadata) assert str(exc_info.value) == expected_exception_message + + +def test_error_handler(qtbot, monkeypatch): + plot_app = setup_plot_app(qtbot, config_all_wrong) + + expected_error = "Error: missing signals field for x axis in plot 0 - BPM4i plots vs samx" + + with patch.object(QMessageBox, "critical", return_value=QMessageBox.Cancel) as mock_critical: + plot_app.load_config(config_all_wrong) + mock_critical.assert_called_once_with( + plot_app, + "Configuration Error", + expected_error, + QMessageBox.Cancel, + ) + + +@pytest.mark.parametrize( + "config, expected_errors", + [ + (config_device_mode_all_filled, []), + (config_device_mode_no_entry, []), + (config_scan_mode, []), + ( + config_all_wrong, + ["Missing 'signals' configuration for x axis in plot 0 - 'BPM4i plots vs samx'"], + ), + ], +) +def test_error_handler(error_handler, config, expected_errors): + # Mock QMessageBox + error_handler.handle_error = MagicMock() + + # Mock logging + with unittest.mock.patch("bec_widgets.examples.extreme.extreme.logging") as mocked_logging: + error_handler.validate_config_file(config) + + # Assert + assert error_handler.errors == expected_errors + + # If there are expected errors, check if handle_error was called + if expected_errors: + error_handler.handle_error.assert_called_once() + else: + error_handler.handle_error.assert_not_called() + + +def test_validate_plot_config(error_handler): + plot_config = { + "x": {"label": "Motor X", "signals": []}, # empty signals list should trigger an error + "y": {"label": "Motor Y", "signals": [{"name": "samx", "entry": "samx"}]}, + } + error_handler.validate_plot_config(plot_config, 0) + assert error_handler.errors == [ + "'signals' configuration for x axis in plot 0 must be a non-empty list" + ]