From 0ff0c06bd1696920eb716768fc5a201b67e2ab51 Mon Sep 17 00:00:00 2001 From: Mathias Guijarro Date: Thu, 19 Dec 2024 11:10:54 +0100 Subject: [PATCH] feat: add test for BECGuiClient features .new, .delete, .show, .hide, .close --- bec_widgets/cli/client_utils.py | 3 + .../containers/main_window/main_window.py | 26 +++++++- tests/end-2-end/test_bec_dock_rpc_e2e.py | 59 ++++++++++++++++++- 3 files changed, 86 insertions(+), 2 deletions(-) diff --git a/bec_widgets/cli/client_utils.py b/bec_widgets/cli/client_utils.py index 91837b3a..9eb76a84 100644 --- a/bec_widgets/cli/client_utils.py +++ b/bec_widgets/cli/client_utils.py @@ -274,6 +274,9 @@ class BECGuiClient(RPCBase): if wait: self._gui_started_event.wait() + def _dump(self): + rpc_client = RPCBase(gui_id=f"{self._gui_id}:window", parent=self) + return rpc_client._run_rpc("_dump") def start(self): return self.start_server() diff --git a/bec_widgets/widgets/containers/main_window/main_window.py b/bec_widgets/widgets/containers/main_window/main_window.py index 721c74ee..0a655aac 100644 --- a/bec_widgets/widgets/containers/main_window/main_window.py +++ b/bec_widgets/widgets/containers/main_window/main_window.py @@ -1,4 +1,4 @@ -from qtpy.QtWidgets import QMainWindow +from qtpy.QtWidgets import QApplication, QMainWindow from bec_widgets.utils import BECConnector from bec_widgets.widgets.containers.dock.dock_area import BECDockArea @@ -9,6 +9,30 @@ class BECMainWindow(QMainWindow, BECConnector): BECConnector.__init__(self, **kwargs) QMainWindow.__init__(self, *args, **kwargs) + def _dump(self): + """Return a dictionary with informations about the application state, for use in tests""" + # TODO: ModularToolBar and something else leak top-level widgets (3 or 4 QMenu + 2 QWidget); + # so, a filtering based on title is applied here, but the solution is to not have those widgets + # as top-level (so for now, a window with no title does not appear in _dump() result) + + # NOTE: the main window itself is excluded, since we want to dump dock areas + info = { + tlw.gui_id: { + "title": tlw.windowTitle(), + "visible": tlw.isVisible(), + "class": str(type(tlw)), + } + for tlw in QApplication.instance().topLevelWidgets() + if tlw is not self and tlw.windowTitle() + } + # Add the main window dock area + info[self.centralWidget().gui_id] = { + "title": self.windowTitle(), + "visible": self.isVisible(), + "class": str(type(self.centralWidget())), + } + return info + def new_dock_area(self, name): dock_area = BECDockArea() dock_area.resize(dock_area.minimumSizeHint()) diff --git a/tests/end-2-end/test_bec_dock_rpc_e2e.py b/tests/end-2-end/test_bec_dock_rpc_e2e.py index e70b60a6..c5f69b1c 100644 --- a/tests/end-2-end/test_bec_dock_rpc_e2e.py +++ b/tests/end-2-end/test_bec_dock_rpc_e2e.py @@ -1,9 +1,9 @@ import time import numpy as np +import pytest from bec_lib.endpoints import MessageEndpoints -from bec_widgets.cli.auto_updates import AutoUpdates from bec_widgets.cli.client import BECDockArea, BECFigure, BECImageShow, BECMotorMap, BECWaveform from bec_widgets.utils import Colors @@ -292,3 +292,60 @@ def test_auto_update(bec_client_lib, connected_client_dock_w_auto_updates, qtbot plt_data[f"Scan {status.scan.scan_number} - {dock.selected_device}"]["y"] == last_scan_data["samy"]["samy"].val ) + + +def test_rpc_gui_obj(connected_client_gui_obj, qtbot): + gui = connected_client_gui_obj + + assert gui.selected_device is None + assert len(gui.windows) == 1 + assert gui.windows["main"].widget is gui.main + assert gui.windows["main"].title == "BEC Widgets" + mw = gui.main + assert mw.__class__.__name__ == "BECDockArea" + + xw = gui.new("X") + assert xw.__class__.__name__ == "BECDockArea" + assert len(gui.windows) == 2 + + gui_info = gui._dump() + mw_info = gui_info[mw._gui_id] + assert mw_info["title"] == "BEC Widgets" + assert mw_info["visible"] + xw_info = gui_info[xw._gui_id] + assert xw_info["title"] == "X" + assert xw_info["visible"] + + gui.hide() + gui_info = gui._dump() + assert not any(windows["visible"] for windows in gui_info.values()) + + gui.show() + gui_info = gui._dump() + assert all(windows["visible"] for windows in gui_info.values()) + + assert gui.gui_is_alive() + gui.close() + assert not gui.gui_is_alive() + gui.start_server(wait=True) + assert gui.gui_is_alive() + # calling start multiple times should not change anything + gui.start_server(wait=True) + gui.start() + # gui.windows should have main, and main dock area should have same gui_id as before + assert len(gui.windows) == 1 + assert gui.windows["main"].widget._gui_id == mw._gui_id + # communication should work, main dock area should have same id and be visible + gui_info = gui._dump() + assert gui_info[mw._gui_id]["visible"] + + with pytest.raises(RuntimeError): + gui.main.delete() + + yw = gui.new("Y") + assert len(gui.windows) == 2 + yw.delete() + assert len(gui.windows) == 1 + # check it is really deleted on server + gui_info = gui._dump() + assert yw._gui_id not in gui_info