diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 09:06:44 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 09:06:44 +0000 |
commit | ed5640d8b587fbcfed7dd7967f3de04b37a76f26 (patch) | |
tree | 7a5f7c6c9d02226d7471cb3cc8fbbf631b415303 /uitest/libreoffice | |
parent | Initial commit. (diff) | |
download | libreoffice-upstream.tar.xz libreoffice-upstream.zip |
Adding upstream version 4:7.4.7.upstream/4%7.4.7upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'uitest/libreoffice')
-rw-r--r-- | uitest/libreoffice/calc/conditional_format.py | 17 | ||||
-rw-r--r-- | uitest/libreoffice/calc/csv_dialog.py | 52 | ||||
-rw-r--r-- | uitest/libreoffice/calc/document.py | 63 | ||||
-rw-r--r-- | uitest/libreoffice/connection.py | 193 | ||||
-rw-r--r-- | uitest/libreoffice/linguistic/linguservice.py | 27 | ||||
-rw-r--r-- | uitest/libreoffice/uno/eventlistener.py | 56 | ||||
-rw-r--r-- | uitest/libreoffice/uno/propertyvalue.py | 39 |
7 files changed, 447 insertions, 0 deletions
diff --git a/uitest/libreoffice/calc/conditional_format.py b/uitest/libreoffice/calc/conditional_format.py new file mode 100644 index 000000000..40e766943 --- /dev/null +++ b/uitest/libreoffice/calc/conditional_format.py @@ -0,0 +1,17 @@ +# -*- 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/. +# + +# this file provides methods to interact with the new conditional format API + +def get_conditional_format_from_sheet(sheet): + """ Returns a conditional format object belonging to a sheet + + Keyword arguments: + sheet -- a XSheet object""" + return sheet.getPropertyValue("ConditionalFormats") + +# vim: set shiftwidth=4 softtabstop=4 expandtab: diff --git a/uitest/libreoffice/calc/csv_dialog.py b/uitest/libreoffice/calc/csv_dialog.py new file mode 100644 index 000000000..e15eea1a7 --- /dev/null +++ b/uitest/libreoffice/calc/csv_dialog.py @@ -0,0 +1,52 @@ +# -*- 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/. +# + +from uitest.uihelper.common import get_state_as_dict, get_url_for_data_file +from libreoffice.uno.propertyvalue import mkPropertyValues +from contextlib import contextmanager + +@contextmanager +def load_csv_file(UITestCase, fileName, bUseDefaultOptions): + with UITestCase.ui_test.execute_dialog_through_command(".uno:Open", close_button="open") as xOpenDialog: + + xFileName = xOpenDialog.getChild("file_name") + xFileName.executeAction("TYPE", mkPropertyValues({"TEXT": get_url_for_data_file(fileName)})) + + xDialog = UITestCase.ui_test.wait_for_top_focus_window('TextImportCsvDialog') + + try: + if bUseDefaultOptions: + xSeparatedBy = xDialog.getChild("toseparatedby") + xSeparatedBy.executeAction("CLICK", tuple()) + + xTextDelimiter = xDialog.getChild("textdelimiter") + xTextDelimiter.executeAction("TYPE", mkPropertyValues({"KEYCODE":"CTRL+A"})) + xTextDelimiter.executeAction("TYPE", mkPropertyValues({"KEYCODE":"BACKSPACE"})) + xTextDelimiter.executeAction("TYPE", mkPropertyValues({"TEXT": "\""})) + + setToTrue = ['tab', 'comma', 'semicolon'] + for childName in setToTrue: + xChild = xDialog.getChild(childName) + if get_state_as_dict(xChild)['Selected'] == 'false': + xChild.executeAction("CLICK", tuple()) + UITestCase.assertEqual('true', get_state_as_dict(xChild)['Selected']) + + setToFalse = ['space', 'other', 'removespace', 'mergedelimiters', + 'evaluateformulas', 'quotedfieldastext', 'detectspecialnumbers'] + for childName in setToFalse: + xChild = xDialog.getChild(childName) + if get_state_as_dict(xChild)['Selected'] == 'true': + xChild.executeAction("CLICK", tuple()) + UITestCase.assertEqual('false', get_state_as_dict(xChild)['Selected']) + + UITestCase.assertEqual('1', get_state_as_dict(xDialog.getChild("fromrow"))['Text']) + + yield xDialog + finally: + xOK = xDialog.getChild('ok') + with UITestCase.ui_test.wait_until_component_loaded(): + UITestCase.ui_test.close_dialog_through_button(xOK) diff --git a/uitest/libreoffice/calc/document.py b/uitest/libreoffice/calc/document.py new file mode 100644 index 000000000..40a2ec635 --- /dev/null +++ b/uitest/libreoffice/calc/document.py @@ -0,0 +1,63 @@ +# -*- 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/. +# + +def get_sheet_from_doc(document, index=None, name=None): + """ Returns a sheet object for a Spreadsheet document + + Keyword arguments: + index -- the 0-based index of the sheet (may not be used together with name) + name -- the name of the sheet (may not be used together with index) + """ + return document.getSheets().getByIndex(index) + +def get_cell_by_position(document, tab, column, row): + """ Get the cell object through its position in a document + + Keyword arguments: + document -- The document that should be used + tab -- The 0-based sheet number + column -- The 0-based column number + row -- The 0-based row number + """ + sheet = get_sheet_from_doc(document, tab) + return sheet.getCellByPosition(column, row) + +def get_column(document, column, tab = 0): + """ Get the column object through the column index + + Keyword arguments: + document -- The document that should be used + tab -- The 0-based sheet number + column -- The 0-based column number + """ + sheet = get_sheet_from_doc(document, tab) + return sheet.getColumns().getByIndex(column) + +def get_row(document, row, tab = 0): + """ Get the row object through the row index + + Keyword arguments: + document -- The document that should be used + tab -- The 0-based sheet number + column -- The 0-based row number + """ + sheet = get_sheet_from_doc(document, tab) + return sheet.getRows().getByIndex(row) + +def is_row_hidden(document, row, tab = 0): + """ Check whether a row object is hidden + + Keyword arguments: + document -- The document that should be used + tab -- The 0-based sheet number + column -- The 0-based row number + """ + xRow = get_row(document, row, tab) + bVisible = xRow.getPropertyValue("IsVisible") + return not bVisible + +# vim: set shiftwidth=4 softtabstop=4 expandtab: diff --git a/uitest/libreoffice/connection.py b/uitest/libreoffice/connection.py new file mode 100644 index 000000000..2b0e9c227 --- /dev/null +++ b/uitest/libreoffice/connection.py @@ -0,0 +1,193 @@ +# -*- 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 subprocess +import time +import traceback +import uuid +import os + +try: + import pyuno + import uno + import unohelper +except ImportError: + print("pyuno not found: try to set PYTHONPATH and URE_BOOTSTRAP variables") + print("PYTHONPATH=/installation/opt/program") + print("URE_BOOTSTRAP=file:///installation/opt/program/fundamentalrc") + raise + + +class OfficeConnection: + def __init__(self, args): + self.args = args + self.soffice = None + self.xContext = None + + def setUp(self): + """ Create a new connection to a LibreOffice process + + If the connection method is path the instance will be created as a + new subprocess. If the connection method is connect the instance tries + to connect to an existing instance with the specified socket string """ + (method, sep, rest) = self.args["--soffice"].partition(":") + if sep != ":": + raise Exception("soffice parameter does not specify method") + if method == "path": + socket = "pipe,name=pytest" + str(uuid.uuid1()) + try: + userdir = self.args["--userdir"] + except KeyError: + raise Exception("'path' method requires --userdir") + if not(userdir.startswith("file://")): + raise Exception("--userdir must be file URL") + self.soffice = self.bootstrap(rest, userdir, socket) + elif method == "connect": + socket = rest + else: + raise Exception("unsupported connection method: " + method) + + # connect to the soffice instance + success = False + try: + self.xContext = self.connect(socket) + success = True + finally: + if not success and self.soffice: + self.soffice.terminate() + self.soffice.wait() + self.soffice = None + + def bootstrap(self, soffice, userdir, socket): + """ Creates a new LibreOffice process + + @param soffice Path to the soffice installation + @param userdir Directory of the user profile, only one process per user + profile is possible + @param socket The socket string used for the PyUNO connection """ + + argv = [soffice, "--accept=" + socket + ";urp", + "-env:UserInstallation=" + userdir, + "--quickstart=no", "--nofirststartwizard", + "--norestore", "--nologo"] + if "--valgrind" in self.args: + argv.append("--valgrind") + + if "--gdb" in self.args: + argv.insert(0, "gdb") + argv.insert(1, "-ex") + argv.insert(2, "run") + argv.insert(3, "--args") + argv[4] = argv[4].replace("soffice", "soffice.bin") + + env = None + environ = dict(os.environ) + if 'LIBO_LANG' in environ: + env = environ + env['LC_ALL'] = environ['LIBO_LANG'] + + return subprocess.Popen(argv, env=env) + + def connect(self, socket): + """ Tries to connect to the LibreOffice instance through the specified socket""" + xLocalContext = uno.getComponentContext() + xUnoResolver = xLocalContext.ServiceManager.createInstanceWithContext( + "com.sun.star.bridge.UnoUrlResolver", xLocalContext) + url = "uno:" + socket + ";urp;StarOffice.ComponentContext" + print("OfficeConnection: connecting to: " + url) + while True: + if self.soffice and self.soffice.poll() is not None: + raise Exception("soffice has stopped.") + + try: + xContext = xUnoResolver.resolve(url) + return xContext + except pyuno.getClass("com.sun.star.connection.NoConnectException"): + print("NoConnectException: sleeping...") + time.sleep(1) + + def tearDown(self): + """Terminate a LibreOffice instance created with the path connection method. + + Tries to terminate the soffice instance through the normal + XDesktop::terminate method and waits indefinitely for the subprocess + to terminate """ + + if self.soffice: + if self.xContext: + try: + print("tearDown: calling terminate()...") + xMgr = self.xContext.ServiceManager + xDesktop = xMgr.createInstanceWithContext( + "com.sun.star.frame.Desktop", self.xContext) + xDesktop.terminate() + print("...done") + except pyuno.getClass("com.sun.star.beans.UnknownPropertyException"): + print("caught while TearDown:\n", traceback.format_exc()) + pass # ignore, also means disposed + except pyuno.getClass("com.sun.star.lang.DisposedException"): + print("caught while TearDown:\n", traceback.format_exc()) + pass # ignore + else: + self.soffice.terminate() + + ret = self.soffice.wait() + self.xContext = None + self.soffice = None + if ret != 0: + raise Exception("Exit status indicates failure: " + str(ret)) + + @classmethod + def getHelpText(cls): + message = """ + --soffice=method:location + specify soffice instance to connect to + supported methods: 'path', 'connect' + --userdir=URL specify user installation directory for 'path' method + --valgrind pass --valgrind to soffice for 'path' method + + 'location' is a pathname, not a URL. 'userdir' is a URL. + """ + return message + + +class PersistentConnection: + def __init__(self, args): + self.args = args + self.connection = None + + def getContext(self): + """ Returns the XContext corresponding to the LibreOffice instance + + This is the starting point for any PyUNO access to the LibreOffice + instance.""" + return self.connection.xContext + + def setUp(self): + # don't create two connections + if self.connection: + return + + conn = OfficeConnection(self.args) + conn.setUp() + self.connection = conn + + def tearDown(self): + if self.connection: + try: + self.connection.tearDown() + finally: + self.connection = None + + def kill(self): + """ Kills the LibreOffice instance if it was created through the connection + + Only works with the connection method path""" + if self.connection and self.connection.soffice: + self.connection.soffice.kill() + +# vim: set shiftwidth=4 softtabstop=4 expandtab: diff --git a/uitest/libreoffice/linguistic/linguservice.py b/uitest/libreoffice/linguistic/linguservice.py new file mode 100644 index 000000000..7ff9c1ac6 --- /dev/null +++ b/uitest/libreoffice/linguistic/linguservice.py @@ -0,0 +1,27 @@ +# -*- Mode: python; tab-width: 4; indent-tabs-mode: nil; c-basic-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/. +# + + +def get_lingu_service_manager(xContext): + """ Returns the com.sun.star.linguistic2.LinguServiceManager + + Further information: https://api.libreoffice.org/docs/idl/ref/servicecom_1_1sun_1_1star_1_1linguistic2_1_1LinguServiceManager.html + """ + xServiceManager = xContext.getServiceManager() + xLinguServiceManager = xServiceManager.createInstanceWithContext("com.sun.star.linguistic2.LinguServiceManager", xContext) + return xLinguServiceManager + + +def get_spellchecker(xContext): + """ Returns the com.sun.star.linguistic2.XSpellChecker through the + com.sun.star.linguistic2.LinguServiceManager + + Further information: https://api.libreoffice.org/docs/idl/ref/servicecom_1_1sun_1_1star_1_1linguistic2_1_1SpellChecker.html""" + xLinguServiceManager = get_lingu_service_manager(xContext) + return xLinguServiceManager.getSpellChecker() + +# vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/uitest/libreoffice/uno/eventlistener.py b/uitest/libreoffice/uno/eventlistener.py new file mode 100644 index 000000000..b2b834b13 --- /dev/null +++ b/uitest/libreoffice/uno/eventlistener.py @@ -0,0 +1,56 @@ +# -*- 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/. +# + +try: + import pyuno + import unohelper + from com.sun.star.document import XDocumentEventListener +except ImportError: + print("pyuno not found: try to set PYTHONPATH and URE_BOOTSTRAP variables") + print("PYTHONPATH=/installation/opt/program") + print("URE_BOOTSTRAP=file:///installation/opt/program/fundamentalrc") + raise + +class EventListener(XDocumentEventListener,unohelper.Base): + + def __init__(self, xContext, eventNames, **kwargs): + self.xGEB = xContext.ServiceManager.createInstanceWithContext( + "com.sun.star.frame.GlobalEventBroadcaster", xContext) + self.xContext = xContext + self.executed = False + self.eventExecuted = [] + self.printEvents = kwargs.get('printNames', False) + if isinstance(eventNames, str): + self.eventNames = [eventNames] + elif isinstance(eventNames, list): + self.eventNames = eventNames + + def __enter__(self): + self.xGEB.addDocumentEventListener(self) + return self + + def __exit__(self, type, value, traceback): + self.xGEB.removeDocumentEventListener(self) + + def documentEventOccured(self, event): + if self.printEvents is True: + print(event.EventName) + + if event.EventName in self.eventNames: + self.executed = True + self.eventExecuted.append(event.EventName) + else: + print(self.eventNames) + print(event.EventName) + + def hasExecuted(self, eventName): + return eventName in self.eventExecuted + + def disposing(event): + pass + +# vim: set shiftwidth=4 softtabstop=4 expandtab: diff --git a/uitest/libreoffice/uno/propertyvalue.py b/uitest/libreoffice/uno/propertyvalue.py new file mode 100644 index 000000000..4e5c8964b --- /dev/null +++ b/uitest/libreoffice/uno/propertyvalue.py @@ -0,0 +1,39 @@ +# -*- 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/. +# + +try: + import pyuno + import uno +except ImportError: + print("pyuno not found: try to set PYTHONPATH and URE_BOOTSTRAP variables") + print("PYTHONPATH=/installation/opt/program") + print("URE_BOOTSTRAP=file:///installation/opt/program/fundamentalrc") + raise + +def mkPropertyValue(name, value): + """ Create a UNO PropertyValue from two input values. + """ + return uno.createUnoStruct("com.sun.star.beans.PropertyValue", + name, 0, value, 0) + +def mkPropertyValues(vals): + """ Create UNO property values from a map. + """ + return tuple([mkPropertyValue(name, value) for (name, value) in vals.items()]) + +def convert_property_values_to_dict(propMap): + """ Create a dictionary from a sequence of property values + """ + ret = {} + for entry in propMap: + name = entry.Name + val = entry.Value + ret[name] = val + + return ret + +# vim: set shiftwidth=4 softtabstop=4 expandtab: |