From 710d7229a79fcf7a9af011a4cdd266f516b95cf2 Mon Sep 17 00:00:00 2001 From: appel_c Date: Mon, 2 Dec 2024 16:20:41 +0100 Subject: [PATCH] tests: add test for user script widget --- .../editors/user_script/user_script.py | 27 +++-- tests/unit_tests/test_user_script.py | 110 ++++++++++++++++++ 2 files changed, 126 insertions(+), 11 deletions(-) create mode 100644 tests/unit_tests/test_user_script.py diff --git a/bec_widgets/widgets/editors/user_script/user_script.py b/bec_widgets/widgets/editors/user_script/user_script.py index 8e1d99c6..87987d9e 100644 --- a/bec_widgets/widgets/editors/user_script/user_script.py +++ b/bec_widgets/widgets/editors/user_script/user_script.py @@ -389,8 +389,9 @@ class UserScriptWidget(BECWidget, QWidget): self._vscode_editor.show() # Only works after show was called for the first time self._vscode_editor.zen_mode() - self._code_dialog.show() - self._vscode_editor.show() + else: + self._code_dialog.show() + self._vscode_editor.show() self._vscode_editor.open_file(fname) @SafeSlot(popup_error=True) @@ -487,8 +488,15 @@ class UserScriptWidget(BECWidget, QWidget): info = self.client._scripts[text] caller_args = inspect.getfullargspec(info["cls"]) args = caller_args.args + caller_args.kwonlyargs - # Default of args are ignored + if args: + self._handle_call_with_args(text, caller_args) + else: + self._console.execute_command(f"{text}()") + + def _handle_call_with_args(self, text: str, caller_args: inspect.FullArgSpec) -> None: + """Handle the call with arguments""" defaults = [] + args = caller_args.args + caller_args.kwonlyargs for value in args: if caller_args.kwonlydefaults is not None: defaults.append(caller_args.kwonlydefaults.get(value, None)) @@ -498,14 +506,11 @@ class UserScriptWidget(BECWidget, QWidget): self._script_dialog = InputDialog( parent=self, header="Script Arguments", info=info, fields=fields ) - if args: - if self._script_dialog.exec_(): - args = self._script_dialog.get_inputs() - args = ", ".join([f"{k}={v}" for k, v in args.items()]) - self._console.execute_command(f"{text}({args})") - else: - self._console.execute_command(f"{text}()") - self._script_dialog = None + if self._script_dialog.exec_(): + args = self._script_dialog.get_inputs() + args = ", ".join([f"{k}={v}" for k, v in args.items()]) + self._console.execute_command(f"{text}({args})") + self._script_dialog = None def cleanup(self): """Cleanup the widget""" diff --git a/tests/unit_tests/test_user_script.py b/tests/unit_tests/test_user_script.py new file mode 100644 index 00000000..5a5dd579 --- /dev/null +++ b/tests/unit_tests/test_user_script.py @@ -0,0 +1,110 @@ +import inspect +from unittest import mock + +import pytest +from qtpy.QtWidgets import QLabel + +from bec_widgets.widgets.editors.user_script.user_script import UserScriptWidget + +from .client_mocks import mocked_client + + +def dummy_script(): + pass + + +def dummy_script_with_args(arg1: str, arg2: int = 0): + pass + + +SCRIPTS = { + "dummy_script": {"cls": dummy_script, "fname": "/dummy_path_home_scripts/home_testing.py"}, + "dummy_script_with_args": { + "cls": dummy_script_with_args, + "fname": "/dummy_path_bec_lib_scripts/bec_testing.py", + }, +} + + +@pytest.fixture +def user_script_widget(qtbot, mocked_client): + mocked_client._scripts = SCRIPTS + files = { + "USER": [SCRIPTS["dummy_script"]["fname"]], + "BEC": [SCRIPTS["dummy_script_with_args"]["fname"]], + } + with mock.patch( + "bec_widgets.widgets.editors.user_script.user_script.UserScriptWidget.get_script_files", + return_value=files, + ): + widget = UserScriptWidget(client=mocked_client) + qtbot.addWidget(widget) + qtbot.waitExposed(widget) + yield widget + + +def test_user_script_widget_start_up(user_script_widget): + """Test init the user_script widget with dummy scripts from above""" + assert user_script_widget.tree_widget.columnCount() == 2 + assert len(user_script_widget.tree_widget.children()[0].children()) == 6 + assert user_script_widget.user_scripts["home_testing"].location == "USER" + assert user_script_widget.user_scripts["home_testing"].module_name == "home_testing" + assert user_script_widget.user_scripts["home_testing"].fname == SCRIPTS["dummy_script"]["fname"] + assert user_script_widget.user_scripts["home_testing"].user_script_name == dummy_script.__name__ + + assert user_script_widget.user_scripts["bec_testing"].location == "BEC" + assert user_script_widget.user_scripts["bec_testing"].module_name == "bec_testing" + assert ( + user_script_widget.user_scripts["bec_testing"].fname + == SCRIPTS["dummy_script_with_args"]["fname"] + ) + assert ( + user_script_widget.user_scripts["bec_testing"].user_script_name + == dummy_script_with_args.__name__ + ) + for label in user_script_widget.tree_widget.children()[0].findChildren(QLabel): + assert label.text() in [ + "home_testing", + "bec_testing", + "dummy_script", + "dummy_script_with_args", + ] + + +def test_handle_open_script(user_script_widget): + """Test handling open script""" + with mock.patch.object(user_script_widget, "open_script") as mock_open_script: + user_script_widget.handle_edit_button_clicked("home_testing") + mock_open_script.assert_called_once_with("/dummy_path_home_scripts/home_testing.py") + + +def test_open_script(user_script_widget): + """Test opening script""" + assert user_script_widget._code_dialog is None + # Override the _vscode_ed + with mock.patch.object(user_script_widget._vscode_editor, "show") as mock_show: + with mock.patch.object(user_script_widget._vscode_editor, "open_file") as mock_open_file: + with mock.patch.object(user_script_widget._vscode_editor, "zen_mode") as mock_zen_mode: + user_script_widget.open_script("/dummy_path_home_scripts/home_testing.py") + mock_show.assert_called_once() + mock_open_file.assert_called_once_with("/dummy_path_home_scripts/home_testing.py") + mock_zen_mode.assert_called_once() + assert user_script_widget._code_dialog is not None + + +def test_play_button(user_script_widget): + """Test play button""" + with mock.patch.object(user_script_widget, "_console") as mock_console: + with mock.patch.object(user_script_widget, "_handle_call_with_args") as mock_handle_call: + # Test first with no args + user_script_widget.handle_play_button_clicked("dummy_script") + mock_console.execute_command.caller_args == [ + mock.call("bec.load_all_user_scripts()"), + mock.call("dummy_script()"), + ] + assert user_script_widget._script_dialog is None + + # Test with args + user_script_widget.handle_play_button_clicked("dummy_script_with_args") + caller_args = inspect.getfullargspec(dummy_script_with_args) + assert mock_handle_call.call_args == mock.call("dummy_script_with_args", caller_args)