diff options
Diffstat (limited to 'uitest/uitest/test.py')
-rw-r--r-- | uitest/uitest/test.py | 260 |
1 files changed, 260 insertions, 0 deletions
diff --git a/uitest/uitest/test.py b/uitest/uitest/test.py new file mode 100644 index 000000000..5ed20add7 --- /dev/null +++ b/uitest/uitest/test.py @@ -0,0 +1,260 @@ +# -*- tab-width: 4; indent-tabs-mode: nil; py-indent-offset: 4 -*- +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# + +import time +import threading +import os.path +from contextlib import contextmanager +from uitest.uihelper.common import get_state_as_dict + +from com.sun.star.uno import RuntimeException + +from libreoffice.uno.eventlistener import EventListener + +DEFAULT_SLEEP = 0.1 + +class UITest(object): + + def __init__(self, xUITest, xContext): + self._xUITest = xUITest + self._xContext = xContext + self._desktop = None + + def get_desktop(self): + if self._desktop: + return self._desktop + + self._desktop = self._xContext.ServiceManager.createInstanceWithContext("com.sun.star.frame.Desktop", self._xContext) + return self._desktop + + def get_frames(self): + desktop = self.get_desktop() + frames = desktop.getFrames() + return frames + + def get_component(self): + desktop = self.get_desktop() + components = desktop.getComponents() + for component in components: + if component is not None: + return component + + def wait_for_top_focus_window(self, id): + while True: + win = self._xUITest.getTopFocusWindow() + if get_state_as_dict(win)['ID'] == id: + return win + time.sleep(DEFAULT_SLEEP) + + def wait_until_child_is_available(self, childName): + while True: + xDialog = self._xUITest.getTopFocusWindow() + if childName in xDialog.getChildren(): + return xDialog.getChild(childName) + else: + time.sleep(DEFAULT_SLEEP) + + def wait_until_property_is_updated(self, element, propertyName, value): + while True: + if get_state_as_dict(element)[propertyName] == value: + return + else: + time.sleep(DEFAULT_SLEEP) + + def wait_until_file_is_available(self, fileName): + while True: + if os.path.isfile(fileName): + return + else: + time.sleep(DEFAULT_SLEEP) + + @contextmanager + def wait_until_component_loaded(self): + with EventListener(self._xContext, "OnLoad") as event: + yield + while True: + if event.executed: + frames = self.get_frames() + if len(frames) == 1: + self.get_desktop().setActiveFrame(frames[0]) + time.sleep(DEFAULT_SLEEP) + return + time.sleep(DEFAULT_SLEEP) + + def load_component_from_url(self, url, eventName="OnLoad"): + with EventListener(self._xContext, eventName) as event: + component = self.get_desktop().loadComponentFromURL(url, "_default", 0, tuple()) + while True: + if event.executed: + frames = self.get_frames() + #activate the newest frame + self.get_desktop().setActiveFrame(frames[-1]) + return component + time.sleep(DEFAULT_SLEEP) + + # Calls UITest.close_doc at exit + @contextmanager + def load_file(self, url): + try: + yield self.load_component_from_url(url) + finally: + self.close_doc() + + # Calls UITest.close_doc at exit + @contextmanager + def load_empty_file(self, app): + try: + yield self.load_component_from_url("private:factory/s" + app, "OnNew") + finally: + self.close_doc() + + # Calls UITest.close_dialog_through_button at exit + @contextmanager + def execute_dialog_through_command(self, command, printNames=False, close_button = "ok", eventName = "DialogExecute"): + with EventListener(self._xContext, eventName, printNames=printNames) as event: + if not self._xUITest.executeDialog(command): + raise Exception("Dialog not executed for: " + command) + while True: + if event.executed: + xDialog = self._xUITest.getTopFocusWindow() + try: + yield xDialog + except: + if not close_button: + if 'cancel' in xDialog.getChildren(): + self.close_dialog_through_button(xDialog.getChild("cancel")) + raise + finally: + if close_button: + self.close_dialog_through_button(xDialog.getChild(close_button)) + return + time.sleep(DEFAULT_SLEEP) + + @contextmanager + def execute_modeless_dialog_through_command(self, command, printNames=False, close_button = "ok"): + with self.execute_dialog_through_command(command, printNames, close_button, "ModelessDialogVisible") as xDialog: + yield xDialog + + # Calls UITest.close_dialog_through_button at exit + @contextmanager + def execute_dialog_through_action(self, ui_object, action, parameters = None, event_name = "DialogExecute", close_button = "ok"): + if parameters is None: + parameters = tuple() + + with EventListener(self._xContext, event_name) as event: + ui_object.executeAction(action, parameters) + while True: + if event.executed: + xDialog = self._xUITest.getTopFocusWindow() + try: + yield xDialog + finally: + if close_button: + self.close_dialog_through_button(xDialog.getChild(close_button)) + return + time.sleep(DEFAULT_SLEEP) + + def _handle_crash_reporter(self): + xCrashReportDlg = self._xUITest.getTopFocusWindow() + state = get_state_as_dict(xCrashReportDlg) + print(state) + if state['ID'] != "CrashReportDialog": + return False + print("found a crash reporter") + xCancelBtn = xCrashReportDlg.getChild("btn_cancel") + self.close_dialog_through_button(xCancelBtn) + return True + + # Calls UITest.close_doc at exit + @contextmanager + def create_doc_in_start_center(self, app): + xStartCenter = self._xUITest.getTopFocusWindow() + try: + xBtn = xStartCenter.getChild(app + "_all") + except RuntimeException: + if self._handle_crash_reporter(): + xStartCenter = self._xUITest.getTopFocusWindow() + xBtn = xStartCenter.getChild(app + "_all") + else: + raise + + with EventListener(self._xContext, "OnNew") as event: + xBtn.executeAction("CLICK", tuple()) + while True: + if event.executed: + frames = self.get_frames() + self.get_desktop().setActiveFrame(frames[0]) + component = self.get_component() + try: + yield component + finally: + self.close_doc() + return + time.sleep(DEFAULT_SLEEP) + + def close_dialog_through_button(self, button): + with EventListener(self._xContext, "DialogClosed" ) as event: + button.executeAction("CLICK", tuple()) + while True: + if event.executed: + time.sleep(DEFAULT_SLEEP) + return + time.sleep(DEFAULT_SLEEP) + + def close_doc(self): + desktop = self.get_desktop() + active_frame = desktop.getActiveFrame() + if not active_frame: + print("close_doc: no active frame") + return + component = active_frame.getController().getModel() + if not component: + print("close_doc: active frame has no component") + return + component.dispose() + frames = desktop.getFrames() + if frames: + frames[0].activate() + + @contextmanager + def execute_blocking_action(self, action, args=(), close_button="ok", printNames=False): + """Executes an action which blocks while a dialog is shown. + + Click a button or perform some other action on the dialog when it + is shown. + + Args: + action(callable): Will be called to show a dialog, and is expected + to block while the dialog is shown. + close_button(str): The name of a button which will be clicked to close + the dialog. if it's empty, the dialog won't be closed from here. + This is useful when consecutive dialogs are open one after the other. + args(tuple, optional): The arguments to be passed to `action` + printNames: print all received event names + """ + + thread = threading.Thread(target=action, args=args) + with EventListener(self._xContext, ["DialogExecute", "ModelessDialogExecute", "ModelessDialogVisible"], printNames=printNames) as event: + thread.start() + while True: + if event.executed: + xDialog = self._xUITest.getTopFocusWindow() + try: + yield xDialog + except: + if not close_button: + if 'cancel' in xDialog.getChildren(): + self.close_dialog_through_button(xDialog.getChild("cancel")) + raise + finally: + if close_button: + self.close_dialog_through_button(xDialog.getChild(close_button)) + thread.join() + return + time.sleep(DEFAULT_SLEEP) + +# vim: set shiftwidth=4 softtabstop=4 expandtab: |