summaryrefslogtreecommitdiffstats
path: root/uitest/libreoffice
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 09:06:44 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 09:06:44 +0000
commited5640d8b587fbcfed7dd7967f3de04b37a76f26 (patch)
tree7a5f7c6c9d02226d7471cb3cc8fbbf631b415303 /uitest/libreoffice
parentInitial commit. (diff)
downloadlibreoffice-ed5640d8b587fbcfed7dd7967f3de04b37a76f26.tar.xz
libreoffice-ed5640d8b587fbcfed7dd7967f3de04b37a76f26.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.py17
-rw-r--r--uitest/libreoffice/calc/csv_dialog.py52
-rw-r--r--uitest/libreoffice/calc/document.py63
-rw-r--r--uitest/libreoffice/connection.py193
-rw-r--r--uitest/libreoffice/linguistic/linguservice.py27
-rw-r--r--uitest/libreoffice/uno/eventlistener.py56
-rw-r--r--uitest/libreoffice/uno/propertyvalue.py39
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: