From 8679b5f08bef8a4a2b6338d9bee4cd70d564f288 Mon Sep 17 00:00:00 2001 From: wyzula-jan Date: Wed, 26 Feb 2025 15:26:14 +0100 Subject: [PATCH] test: extended test coverage for axis settings, plot base and qt toolbar action --- tests/unit_tests/test_axis_settings.py | 75 ++++++++++++++++ tests/unit_tests/test_modular_toolbar.py | 22 ++++- tests/unit_tests/test_plot_base_next_gen.py | 95 ++++++++++++++++++++- 3 files changed, 189 insertions(+), 3 deletions(-) diff --git a/tests/unit_tests/test_axis_settings.py b/tests/unit_tests/test_axis_settings.py index 7cd0d170..d55d9260 100644 --- a/tests/unit_tests/test_axis_settings.py +++ b/tests/unit_tests/test_axis_settings.py @@ -29,6 +29,8 @@ def test_axis_settings_init(axis_settings_fixture): assert axis_settings.layout.count() == 1 # scroll area # Check the target assert axis_settings.target_widget == plot_base + # Check the object name + assert axis_settings.objectName() == "AxisSettings" def test_change_ui_updates_plot_base(axis_settings_fixture, qtbot): @@ -103,3 +105,76 @@ def test_scroll_area_behavior(axis_settings_fixture, qtbot): axis_settings, plot_base = axis_settings_fixture scroll_area = axis_settings.scroll_area assert scroll_area.widgetResizable() is True + + +def test_fetch_all_properties(axis_settings_fixture, qtbot): + """ + Tests the `fetch_all_properties` method ensuring that all the properties set on + the `plot_base` instance are correctly synchronized with the user interface (UI) + elements of the `axis_settings` instance. + """ + axis_settings, plot_base = axis_settings_fixture + + # Set all properties on plot_base + plot_base.title = "Plot Title from Code" + plot_base.x_min = 0 + plot_base.x_max = 100 + plot_base.x_label = "X Label" + plot_base.x_log = True + plot_base.x_grid = True + + plot_base.y_min = -50 + plot_base.y_max = 50 + plot_base.y_label = "Y Label" + plot_base.y_log = False + plot_base.y_grid = False + + plot_base.outer_axes = True + + # Fetch properties into the UI + axis_settings.fetch_all_properties() + + # Verify all properties were correctly fetched + assert axis_settings.ui.title.text() == "Plot Title from Code" + + # X axis properties + assert axis_settings.ui.x_min.value() == 0 + assert axis_settings.ui.x_max.value() == 100 + assert axis_settings.ui.x_label.text() == "X Label" + assert axis_settings.ui.x_log.checked is True + assert axis_settings.ui.x_grid.checked is True + + # Y axis properties + assert axis_settings.ui.y_min.value() == -50 + assert axis_settings.ui.y_max.value() == 50 + assert axis_settings.ui.y_label.text() == "Y Label" + assert axis_settings.ui.y_log.checked is False + assert axis_settings.ui.y_grid.checked is False + + # Other properties + assert axis_settings.ui.outer_axes.checked is True + + +def test_accept_changes(axis_settings_fixture, qtbot): + """ + Tests the functionality of applying user-defined changes to the axis settings + UI and verifying the reflected changes in the plot object's properties. + """ + axis_settings, plot_base = axis_settings_fixture + + axis_settings.ui.title.setText("New Title") + axis_settings.ui.x_max.setValue(20) + axis_settings.ui.x_min.setValue(10) + axis_settings.ui.x_label.setText("New X Label") + axis_settings.ui.x_log.checked = True + axis_settings.ui.x_grid.checked = True + + axis_settings.accept_changes() + qtbot.wait(200) + + assert plot_base.title == "New Title" + assert plot_base.x_min == 10 + assert plot_base.x_max == 20 + assert plot_base.x_label == "New X Label" + assert plot_base.x_log is True + assert plot_base.x_grid is True diff --git a/tests/unit_tests/test_modular_toolbar.py b/tests/unit_tests/test_modular_toolbar.py index 9cc8cb5a..680f143b 100644 --- a/tests/unit_tests/test_modular_toolbar.py +++ b/tests/unit_tests/test_modular_toolbar.py @@ -3,7 +3,7 @@ from typing import Literal import pytest from qtpy.QtCore import QPoint, Qt from qtpy.QtGui import QContextMenuEvent -from qtpy.QtWidgets import QComboBox, QLabel, QMenu, QToolButton, QWidget +from qtpy.QtWidgets import QComboBox, QLabel, QMenu, QStyle, QToolButton, QWidget from bec_widgets.qt_utils.toolbar import ( DeviceSelectionAction, @@ -12,6 +12,7 @@ from bec_widgets.qt_utils.toolbar import ( LongPressToolButton, MaterialIconAction, ModularToolBar, + QtIconAction, SeparatorAction, SwitchableToolBarAction, ToolbarBundle, @@ -63,6 +64,12 @@ def material_icon_action(): ) +@pytest.fixture +def qt_icon_action(): + """Fixture to create a QtIconAction.""" + return QtIconAction(standard_icon=QStyle.SP_FileIcon, tooltip="Qt File", checkable=True) + + @pytest.fixture def device_selection_action(): """Fixture to create a DeviceSelectionAction.""" @@ -146,7 +153,12 @@ def test_set_orientation(toolbar_fixture, qtbot, dummy_widget): def test_add_action( - toolbar_fixture, icon_action, separator_action, material_icon_action, dummy_widget + toolbar_fixture, + icon_action, + separator_action, + material_icon_action, + qt_icon_action, + dummy_widget, ): """Test adding different types of actions to the toolbar.""" toolbar = toolbar_fixture @@ -168,6 +180,12 @@ def test_add_action( assert toolbar.widgets["material_icon_action"] == material_icon_action assert material_icon_action.action in toolbar.actions() + # Add QtIconAction + toolbar.add_action("qt_icon_action", qt_icon_action, dummy_widget) + assert "qt_icon_action" in toolbar.widgets + assert toolbar.widgets["qt_icon_action"] == qt_icon_action + assert qt_icon_action.action in toolbar.actions() + def test_hide_show_action(toolbar_fixture, icon_action, qtbot, dummy_widget): """Test hiding and showing actions on the toolbar.""" diff --git a/tests/unit_tests/test_plot_base_next_gen.py b/tests/unit_tests/test_plot_base_next_gen.py index cac364bd..4ffdde0f 100644 --- a/tests/unit_tests/test_plot_base_next_gen.py +++ b/tests/unit_tests/test_plot_base_next_gen.py @@ -1,4 +1,4 @@ -from bec_widgets.widgets.plots_next_gen.plot_base import PlotBase +from bec_widgets.widgets.plots_next_gen.plot_base import PlotBase, UIMode from .client_mocks import mocked_client from .conftest import create_widget @@ -247,3 +247,96 @@ def test_set_method(qtbot, mocked_client): assert pb.y_grid is True assert pb.x_log is True assert pb.outer_axes is True + + +def test_ui_mode_popup(qtbot, mocked_client): + """ + Test that setting ui_mode to POPUP creates a popup bundle with visible actions + and hides the side panel. + """ + pb = create_widget(qtbot, PlotBase, client=mocked_client) + pb.ui_mode = UIMode.POPUP + # The popup bundle should be created and its actions made visible. + assert "popup_bundle" in pb.toolbar.bundles + for action_id in pb.toolbar.bundles["popup_bundle"]: + assert pb.toolbar.widgets[action_id].action.isVisible() is True + # The side panel should be hidden. + assert not pb.side_panel.isVisible() + + +def test_ui_mode_side(qtbot, mocked_client): + """ + Test that setting ui_mode to SIDE shows the side panel and ensures any popup actions + are hidden. + """ + pb = create_widget(qtbot, PlotBase, client=mocked_client) + pb.ui_mode = UIMode.SIDE + # If a popup bundle exists, its actions should be hidden. + if "popup_bundle" in pb.toolbar.bundles: + for action_id in pb.toolbar.bundles["popup_bundle"]: + assert pb.toolbar.widgets[action_id].action.isVisible() is False + + +def test_enable_popups_property(qtbot, mocked_client): + """ + Test the enable_popups property: when enabled, ui_mode should be POPUP, + and when disabled, ui_mode should change to NONE. + """ + pb = create_widget(qtbot, PlotBase, client=mocked_client) + pb.enable_popups = True + assert pb.ui_mode == UIMode.POPUP + # The popup bundle actions should be visible. + assert "popup_bundle" in pb.toolbar.bundles + for action_id in pb.toolbar.bundles["popup_bundle"]: + assert pb.toolbar.widgets[action_id].action.isVisible() is True + + pb.enable_popups = False + assert pb.ui_mode == UIMode.NONE + + +def test_enable_side_panel_property(qtbot, mocked_client): + """ + Test the enable_side_panel property: when enabled, ui_mode should be SIDE, + and when disabled, ui_mode should change to NONE. + """ + pb = create_widget(qtbot, PlotBase, client=mocked_client) + pb.enable_side_panel = True + assert pb.ui_mode == UIMode.SIDE + + pb.enable_side_panel = False + assert pb.ui_mode == UIMode.NONE + + +def test_switching_between_popup_and_side_panel_closes_dialog(qtbot, mocked_client): + """ + Test that if a popup dialog is open (via the axis settings popup) then switching + to side-panel mode closes the dialog. + """ + pb = create_widget(qtbot, PlotBase, client=mocked_client) + pb.ui_mode = UIMode.POPUP + # Open the axis settings popup. + pb.show_axis_settings_popup() + qtbot.wait(100) + # The dialog should now exist and be visible. + assert pb.axis_settings_dialog is not None + assert pb.axis_settings_dialog.isVisible() is True + + # Switch to side panel mode. + pb.ui_mode = UIMode.SIDE + qtbot.wait(100) + # The axis settings dialog should be closed (and reference cleared). + assert pb.axis_settings_dialog is None or pb.axis_settings_dialog.isVisible() is False + + +def test_enable_fps_monitor_property(qtbot, mocked_client): + """ + Test the enable_fps_monitor property: when enabled, the FPS monitor should be hooked + (resulting in a non-None fps_monitor and visible fps_label), and when disabled, the FPS + monitor should be unhooked and the label hidden. + """ + pb = create_widget(qtbot, PlotBase, client=mocked_client) + pb.enable_fps_monitor = True + assert pb.fps_monitor is not None + + pb.enable_fps_monitor = False + assert pb.fps_monitor is None