diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 16:51:28 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 16:51:28 +0000 |
commit | 940b4d1848e8c70ab7642901a68594e8016caffc (patch) | |
tree | eb72f344ee6c3d9b80a7ecc079ea79e9fba8676d /uitest | |
parent | Initial commit. (diff) | |
download | libreoffice-940b4d1848e8c70ab7642901a68594e8016caffc.tar.xz libreoffice-940b4d1848e8c70ab7642901a68594e8016caffc.zip |
Adding upstream version 1:7.0.4.upstream/1%7.0.4upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'uitest')
104 files changed, 5862 insertions, 0 deletions
diff --git a/uitest/Makefile b/uitest/Makefile new file mode 100644 index 000000000..0997e6284 --- /dev/null +++ b/uitest/Makefile @@ -0,0 +1,14 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*- +# +# This file is part of the LibreOffice project. +# +# 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/. +# + +module_directory:=$(dir $(realpath $(firstword $(MAKEFILE_LIST)))) + +include $(module_directory)/../solenv/gbuild/partial_build.mk + +# vim: set noet sw=4 ts=4: diff --git a/uitest/Module_uitest.mk b/uitest/Module_uitest.mk new file mode 100644 index 000000000..bd65a088e --- /dev/null +++ b/uitest/Module_uitest.mk @@ -0,0 +1,27 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*- +# +# +# This file is part of the LibreOffice project. +# +# 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/. +# + +$(eval $(call gb_Module_Module,uitest)) + +$(eval $(call gb_Module_add_uicheck_targets,uitest,\ + UITest_calc_demo \ + UITest_writer_demo1 \ + UITest_writer_demo2 \ + UITest_writer_demo3 \ + UITest_writer_demo4 \ + UITest_writer_demo5 \ + UITest_writer_demo6 \ + UITest_writer_demo7 \ + UITest_writer_demo8 \ + UITest_impress_demo \ + UITest_demo_ui \ + UITest_math_demo \ + UITest_manual_tests \ +)) diff --git a/uitest/README b/uitest/README new file mode 100644 index 000000000..c941673e7 --- /dev/null +++ b/uitest/README @@ -0,0 +1 @@ +The code for the UI testing framework and the UI tests. diff --git a/uitest/UITest_calc_demo.mk b/uitest/UITest_calc_demo.mk new file mode 100644 index 000000000..9869300a0 --- /dev/null +++ b/uitest/UITest_calc_demo.mk @@ -0,0 +1,15 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*- +# +# This file is part of the LibreOffice project. +# +# 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/. +# + +$(eval $(call gb_UITest_UITest,calc_demo)) + +$(eval $(call gb_UITest_add_modules,calc_demo,$(SRCDIR)/uitest,\ + calc_tests/ \ +)) +# vim: set noet sw=4 ts=4: diff --git a/uitest/UITest_demo_ui.mk b/uitest/UITest_demo_ui.mk new file mode 100644 index 000000000..bb67e21b8 --- /dev/null +++ b/uitest/UITest_demo_ui.mk @@ -0,0 +1,20 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*- +# +# This file is part of the LibreOffice project. +# +# 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/. +# + +$(eval $(call gb_UITest_UITest,demo_ui)) + +$(eval $(call gb_UITest_add_modules,demo_ui,$(SRCDIR)/uitest,\ + demo_ui/ \ +)) + +$(eval $(call gb_UITest_set_defs,demo_ui, \ + TDOC="$(SRCDIR)/uitest/demo_ui/data" \ +)) + +# vim: set noet sw=4 ts=4: diff --git a/uitest/UITest_impress_demo.mk b/uitest/UITest_impress_demo.mk new file mode 100644 index 000000000..e13d95494 --- /dev/null +++ b/uitest/UITest_impress_demo.mk @@ -0,0 +1,15 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*- +# +# This file is part of the LibreOffice project. +# +# 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/. +# + +$(eval $(call gb_UITest_UITest,impress_demo)) + +$(eval $(call gb_UITest_add_modules,impress_demo,$(SRCDIR)/uitest,\ + impress_tests/ \ +)) +# vim: set noet sw=4 ts=4: diff --git a/uitest/UITest_manual_tests.mk b/uitest/UITest_manual_tests.mk new file mode 100644 index 000000000..187ab8317 --- /dev/null +++ b/uitest/UITest_manual_tests.mk @@ -0,0 +1,20 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*- +# +# This file is part of the LibreOffice project. +# +# 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/. +# + +$(eval $(call gb_UITest_UITest,manual_tests)) + +$(eval $(call gb_UITest_add_modules,manual_tests,$(SRCDIR)/uitest,\ + manual_tests/ \ +)) + +$(eval $(call gb_UITest_set_defs,manual_tests, \ + TDOC="$(SRCDIR)/uitest/manual_tests/data" \ +)) + +# vim: set noet sw=4 ts=4: diff --git a/uitest/UITest_math_demo.mk b/uitest/UITest_math_demo.mk new file mode 100644 index 000000000..5c1a6dbd8 --- /dev/null +++ b/uitest/UITest_math_demo.mk @@ -0,0 +1,15 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*- +# +# This file is part of the LibreOffice project. +# +# 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/. +# + +$(eval $(call gb_UITest_UITest,math_demo)) + +$(eval $(call gb_UITest_add_modules,math_demo,$(SRCDIR)/uitest,\ + math_tests/ \ +)) +# vim: set noet sw=4 ts=4: diff --git a/uitest/UITest_writer_demo1.mk b/uitest/UITest_writer_demo1.mk new file mode 100644 index 000000000..e951e4ad2 --- /dev/null +++ b/uitest/UITest_writer_demo1.mk @@ -0,0 +1,20 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*- +# +# This file is part of the LibreOffice project. +# +# 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/. +# + +$(eval $(call gb_UITest_UITest,writer_demo1)) + +$(eval $(call gb_UITest_add_modules,writer_demo1,$(SRCDIR)/uitest,\ + writer_tests1/ \ +)) + +$(eval $(call gb_UITest_set_defs,writer_demo1, \ + TDOC="$(SRCDIR)/uitest/writer_tests/data" \ +)) + +# vim: set noet sw=4 ts=4: diff --git a/uitest/UITest_writer_demo2.mk b/uitest/UITest_writer_demo2.mk new file mode 100644 index 000000000..6f74f97ab --- /dev/null +++ b/uitest/UITest_writer_demo2.mk @@ -0,0 +1,20 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*- +# +# This file is part of the LibreOffice project. +# +# 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/. +# + +$(eval $(call gb_UITest_UITest,writer_demo2)) + +$(eval $(call gb_UITest_add_modules,writer_demo2,$(SRCDIR)/uitest,\ + writer_tests2/ \ +)) + +$(eval $(call gb_UITest_set_defs,writer_demo2, \ + TDOC="$(SRCDIR)/uitest/writer_tests/data" \ +)) + +# vim: set noet sw=4 ts=4: diff --git a/uitest/UITest_writer_demo3.mk b/uitest/UITest_writer_demo3.mk new file mode 100644 index 000000000..9f6302670 --- /dev/null +++ b/uitest/UITest_writer_demo3.mk @@ -0,0 +1,20 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*- +# +# This file is part of the LibreOffice project. +# +# 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/. +# + +$(eval $(call gb_UITest_UITest,writer_demo3)) + +$(eval $(call gb_UITest_add_modules,writer_demo3,$(SRCDIR)/uitest,\ + writer_tests3/ \ +)) + +$(eval $(call gb_UITest_set_defs,writer_demo3, \ + TDOC="$(SRCDIR)/uitest/writer_tests/data" \ +)) + +# vim: set noet sw=4 ts=4: diff --git a/uitest/UITest_writer_demo4.mk b/uitest/UITest_writer_demo4.mk new file mode 100644 index 000000000..5ad99203e --- /dev/null +++ b/uitest/UITest_writer_demo4.mk @@ -0,0 +1,20 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*- +# +# This file is part of the LibreOffice project. +# +# 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/. +# + +$(eval $(call gb_UITest_UITest,writer_demo4)) + +$(eval $(call gb_UITest_add_modules,writer_demo4,$(SRCDIR)/uitest,\ + writer_tests4/ \ +)) + +$(eval $(call gb_UITest_set_defs,writer_demo4, \ + TDOC="$(SRCDIR)/uitest/writer_tests/data" \ +)) + +# vim: set noet sw=4 ts=4: diff --git a/uitest/UITest_writer_demo5.mk b/uitest/UITest_writer_demo5.mk new file mode 100644 index 000000000..1f44c6666 --- /dev/null +++ b/uitest/UITest_writer_demo5.mk @@ -0,0 +1,20 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*- +# +# This file is part of the LibreOffice project. +# +# 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/. +# + +$(eval $(call gb_UITest_UITest,writer_demo5)) + +$(eval $(call gb_UITest_add_modules,writer_demo5,$(SRCDIR)/uitest,\ + writer_tests5/ \ +)) + +$(eval $(call gb_UITest_set_defs,writer_demo5, \ + TDOC="$(SRCDIR)/uitest/writer_tests/data" \ +)) + +# vim: set noet sw=4 ts=4: diff --git a/uitest/UITest_writer_demo6.mk b/uitest/UITest_writer_demo6.mk new file mode 100644 index 000000000..9c1e040a0 --- /dev/null +++ b/uitest/UITest_writer_demo6.mk @@ -0,0 +1,20 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*- +# +# This file is part of the LibreOffice project. +# +# 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/. +# + +$(eval $(call gb_UITest_UITest,writer_demo6)) + +$(eval $(call gb_UITest_add_modules,writer_demo6,$(SRCDIR)/uitest,\ + writer_tests6/ \ +)) + +$(eval $(call gb_UITest_set_defs,writer_demo6, \ + TDOC="$(SRCDIR)/uitest/writer_tests/data" \ +)) + +# vim: set noet sw=4 ts=4: diff --git a/uitest/UITest_writer_demo7.mk b/uitest/UITest_writer_demo7.mk new file mode 100644 index 000000000..10fc45008 --- /dev/null +++ b/uitest/UITest_writer_demo7.mk @@ -0,0 +1,20 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*- +# +# This file is part of the LibreOffice project. +# +# 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/. +# + +$(eval $(call gb_UITest_UITest,writer_demo7)) + +$(eval $(call gb_UITest_add_modules,writer_demo7,$(SRCDIR)/uitest,\ + writer_tests7/ \ +)) + +$(eval $(call gb_UITest_set_defs,writer_demo7, \ + TDOC="$(SRCDIR)/uitest/writer_tests/data" \ +)) + +# vim: set noet sw=4 ts=4: diff --git a/uitest/UITest_writer_demo8.mk b/uitest/UITest_writer_demo8.mk new file mode 100644 index 000000000..7c9eabceb --- /dev/null +++ b/uitest/UITest_writer_demo8.mk @@ -0,0 +1,20 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*- +# +# This file is part of the LibreOffice project. +# +# 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/. +# + +$(eval $(call gb_UITest_UITest,writer_demo8)) + +$(eval $(call gb_UITest_add_modules,writer_demo8,$(SRCDIR)/uitest,\ + writer_tests8/ \ +)) + +$(eval $(call gb_UITest_set_defs,writer_demo8, \ + TDOC="$(SRCDIR)/uitest/writer_tests/data" \ +)) + +# vim: set noet sw=4 ts=4: diff --git a/uitest/__init__.py b/uitest/__init__.py new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/uitest/__init__.py diff --git a/uitest/calc_tests/__init__.py b/uitest/calc_tests/__init__.py new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/uitest/calc_tests/__init__.py diff --git a/uitest/calc_tests/about_test.py b/uitest/calc_tests/about_test.py new file mode 100644 index 000000000..c6dc75b93 --- /dev/null +++ b/uitest/calc_tests/about_test.py @@ -0,0 +1,25 @@ +# -*- 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.framework import UITestCase + +class AboutDlgTest(UITestCase): + + def test_about_dlg(self): + + self.ui_test.create_doc_in_start_center("calc") + + self.ui_test.execute_dialog_through_command(".uno:About") + + xAboutDlg = self.xUITest.getTopFocusWindow() + + xCloseBtn = xAboutDlg.getChild("btnClose") + self.ui_test.close_dialog_through_button(xCloseBtn) + + self.ui_test.close_doc() + +# vim: set shiftwidth=4 softtabstop=4 expandtab: diff --git a/uitest/calc_tests/autofilter.py b/uitest/calc_tests/autofilter.py new file mode 100644 index 000000000..431043b02 --- /dev/null +++ b/uitest/calc_tests/autofilter.py @@ -0,0 +1,49 @@ +# -*- 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.framework import UITestCase +from uitest.path import get_srcdir_url + +from libreoffice.uno.propertyvalue import mkPropertyValues + +import time + +def get_url_for_data_file(file_name): + return get_srcdir_url() + "/uitest/calc_tests/data/" + file_name + +class AutofilterTest(UITestCase): + + def test_launch_autofilter(self): + doc = self.ui_test.load_file(get_url_for_data_file("autofilter.ods")) + + xGridWin = self.xUITest.getTopFocusWindow().getChild("grid_window") + xGridWin.executeAction("LAUNCH", mkPropertyValues({"AUTOFILTER": "", "COL": "1", "ROW": "1"})) + + time.sleep(1) + + self.ui_test.close_doc() + + def test_hierarchy(self): + doc = self.ui_test.load_file(get_url_for_data_file("autofilter.ods")) + + xGridWin = self.xUITest.getTopFocusWindow().getChild("grid_window") + xGridWin.executeAction("LAUNCH", mkPropertyValues({"AUTOFILTER": "", "COL": "0", "ROW": "0"})) + + xFloatWindow = self.xUITest.getFloatWindow() + xCheckListMenu = xFloatWindow.getChild("check_list_menu") + + xTreeList = xCheckListMenu.getChild("check_list_box") + xFirstEntry = xTreeList.getChild("0") + + xFirstEntry.executeAction("CLICK", tuple()) + + xOkBtn = xFloatWindow.getChild("ok") + xOkBtn.executeAction("CLICK", tuple()) + + self.ui_test.close_doc() + +# vim: set shiftwidth=4 softtabstop=4 expandtab: diff --git a/uitest/calc_tests/create_chart.py b/uitest/calc_tests/create_chart.py new file mode 100644 index 000000000..cced0ac63 --- /dev/null +++ b/uitest/calc_tests/create_chart.py @@ -0,0 +1,148 @@ +# -*- 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 libreoffice.uno.propertyvalue import mkPropertyValues + +from uitest.framework import UITestCase +from uitest.uihelper.calc import enter_text_to_cell + +import time +import unittest + +class CalcChartUIDemo(UITestCase): + + def create_insert_chart_dialog(self): + self.ui_test.execute_dialog_through_command(".uno:InsertObjectChart") + # time.sleep(1) # ideally wait for a creation event + return self.xUITest.getTopFocusWindow() + + def fill_spreadsheet(self): + xCalcDoc = self.xUITest.getTopFocusWindow() + xGridWindow = xCalcDoc.getChild("grid_window") + + enter_text_to_cell(xGridWindow, "A1", "col1") + enter_text_to_cell(xGridWindow, "B1", "col2") + enter_text_to_cell(xGridWindow, "C1", "col3") + enter_text_to_cell(xGridWindow, "A2", "1") + enter_text_to_cell(xGridWindow, "B2", "3") + enter_text_to_cell(xGridWindow, "C2", "5") + + xGridWindow.executeAction("SELECT", mkPropertyValues({"RANGE": "A1:C2"})) + + def test_cancel_immediately(self): + + self.ui_test.create_doc_in_start_center("calc") + + self.fill_spreadsheet() + + xChartDlg = self.create_insert_chart_dialog(); + + xCancelBtn = xChartDlg.getChild("cancel") + self.ui_test.close_dialog_through_button(xCancelBtn) + + self.ui_test.close_doc() + + def test_create_from_first_page(self): + + self.ui_test.create_doc_in_start_center("calc") + + self.fill_spreadsheet() + + xChartDlg = self.create_insert_chart_dialog(); + + xOkBtn = xChartDlg.getChild("finish") + self.ui_test.close_dialog_through_button(xOkBtn) + + self.ui_test.close_doc() + + def test_create_from_second_page(self): + + self.ui_test.create_doc_in_start_center("calc") + + self.fill_spreadsheet() + + xChartDlg = self.create_insert_chart_dialog(); + + xNextBtn = xChartDlg.getChild("next") + xNextBtn.executeAction("CLICK", tuple()) + + xDataInRows = xChartDlg.getChild("RB_DATAROWS") + xDataInRows.executeAction("CLICK", tuple()) + + xDataInCols = xChartDlg.getChild("RB_DATACOLS") + xDataInCols.executeAction("CLICK", tuple()) + + xCancelBtn = xChartDlg.getChild("finish") + self.ui_test.close_dialog_through_button(xCancelBtn) + + self.ui_test.close_doc() + + def test_deselect_chart(self): + self.ui_test.create_doc_in_start_center("calc") + + self.fill_spreadsheet() + + xCalcDoc = self.xUITest.getTopFocusWindow() + xGridWindow = xCalcDoc.getChild("grid_window") + + xChartDlg = self.create_insert_chart_dialog(); + + xNextBtn = xChartDlg.getChild("finish") + self.ui_test.close_dialog_through_button(xNextBtn) + + xGridWindow.executeAction("DESELECT", mkPropertyValues({"OBJECT": ""})) + + time.sleep(2) + + self.ui_test.close_doc() + + def test_activate_chart(self): + + self.ui_test.create_doc_in_start_center("calc") + + self.fill_spreadsheet() + + xCalcDoc = self.xUITest.getTopFocusWindow() + xGridWindow = xCalcDoc.getChild("grid_window") + + xChartDlg = self.create_insert_chart_dialog(); + + xNextBtn = xChartDlg.getChild("finish") + self.ui_test.close_dialog_through_button(xNextBtn) + + xGridWindow.executeAction("DESELECT", mkPropertyValues({"OBJECT": ""})) + + xGridWindow.executeAction("SELECT", mkPropertyValues({"OBJECT": "Object 1"})) + xGridWindow.executeAction("ACTIVATE", tuple()) + + xGridWindow.executeAction("DESELECT", mkPropertyValues({"OBJECT": ""})) + + self.ui_test.close_doc() + + def select_chart_element(self): + + self.ui_test.create_doc_in_start_center("calc") + + self.fill_spreadsheet() + + xCalcDoc = self.xUITest.getTopFocusWindow() + xGridWindow = xCalcDoc.getChild("grid_window") + + xChartDlg = self.create_insert_chart_dialog(); + + xNextBtn = xChartDlg.getChild("finish") + self.ui_test.close_dialog_through_button(xNextBtn) + + xGridWindow.executeAction("DESELECT", mkPropertyValues({"OBJECT": ""})) + + xGridWindow.executeAction("SELECT", mkPropertyValues({"OBJECT": "Object 1"})) + xGridWindow.executeAction("ACTIVATE", tuple()) + + xCalcDoc = self.xUITest.getTopFocusWindow() + self.ui_test.close_doc() + +# vim: set shiftwidth=4 softtabstop=4 expandtab: diff --git a/uitest/calc_tests/create_range_name.py b/uitest/calc_tests/create_range_name.py new file mode 100644 index 000000000..1babca7c0 --- /dev/null +++ b/uitest/calc_tests/create_range_name.py @@ -0,0 +1,50 @@ +# -*- 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 libreoffice.uno.propertyvalue import mkPropertyValues + +from uitest.framework import UITestCase +from uitest.uihelper.common import type_text, select_pos + +class CreateRangeNameTest(UITestCase): + + def test_create_range_name(self): + + self.ui_test.create_doc_in_start_center("calc") + + self.ui_test.execute_modeless_dialog_through_command(".uno:AddName") + + xAddNameDlg = self.xUITest.getTopFocusWindow() + + xEdit = xAddNameDlg.getChild("edit") + type_text(xEdit, "simpleRangeName") + + xAddBtn = xAddNameDlg.getChild("add") + self.ui_test.close_dialog_through_button(xAddBtn) + + self.ui_test.close_doc() + + def test_create_local_range_name(self): + + self.ui_test.create_doc_in_start_center("calc") + + self.ui_test.execute_modeless_dialog_through_command(".uno:AddName") + + xAddNameDlg = self.xUITest.getTopFocusWindow() + + xEdit = xAddNameDlg.getChild("edit") + type_text(xEdit, "simpleRangeName") + + xScope = xAddNameDlg.getChild("scope") + select_pos(xScope, "1") + + xAddBtn = xAddNameDlg.getChild("add") + self.ui_test.close_dialog_through_button(xAddBtn) + + self.ui_test.close_doc() + +# vim: set shiftwidth=4 softtabstop=4 expandtab: diff --git a/uitest/calc_tests/data/autofilter.ods b/uitest/calc_tests/data/autofilter.ods Binary files differnew file mode 100644 index 000000000..a03dba608 --- /dev/null +++ b/uitest/calc_tests/data/autofilter.ods diff --git a/uitest/calc_tests/data/tdf96453.ods b/uitest/calc_tests/data/tdf96453.ods Binary files differnew file mode 100644 index 000000000..89114f636 --- /dev/null +++ b/uitest/calc_tests/data/tdf96453.ods diff --git a/uitest/calc_tests/edit_chart.py b/uitest/calc_tests/edit_chart.py new file mode 100644 index 000000000..d74a8c2ec --- /dev/null +++ b/uitest/calc_tests/edit_chart.py @@ -0,0 +1,69 @@ +# -*- 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 libreoffice.uno.propertyvalue import mkPropertyValues + +from uitest.framework import UITestCase +from uitest.uihelper.calc import enter_text_to_cell + +import unittest + +class CalcChartEditUIDemo(UITestCase): + + def fill_spreadsheet(self): + xCalcDoc = self.xUITest.getTopFocusWindow() + xGridWindow = xCalcDoc.getChild("grid_window") + + enter_text_to_cell(xGridWindow, "A1", "col1") + enter_text_to_cell(xGridWindow, "B1", "col2") + enter_text_to_cell(xGridWindow, "C1", "col3") + enter_text_to_cell(xGridWindow, "A2", "1") + enter_text_to_cell(xGridWindow, "B2", "3") + enter_text_to_cell(xGridWindow, "C2", "5") + + xGridWindow.executeAction("SELECT", mkPropertyValues({"RANGE": "A1:C2"})) + + def test_select_secondary_axis(self): + + self.ui_test.create_doc_in_start_center("calc") + + self.fill_spreadsheet() + + xCalcDoc = self.xUITest.getTopFocusWindow() + xGridWindow = xCalcDoc.getChild("grid_window") + + self.ui_test.execute_dialog_through_command(".uno:InsertObjectChart") + + xChartDlg = self.xUITest.getTopFocusWindow() + + xNextBtn = xChartDlg.getChild("finish") + self.ui_test.close_dialog_through_button(xNextBtn) + + xGridWindow.executeAction("DESELECT", mkPropertyValues({"OBJECT": ""})) + + xGridWindow.executeAction("SELECT", mkPropertyValues({"OBJECT": "Object 1"})) + + xGridWindow.executeAction("ACTIVATE", tuple()) + + xChartMainTop = self.xUITest.getTopFocusWindow() + xChartMain = xChartMainTop.getChild("chart_window") + + xSeriesObj = xChartMain.getChild("CID/D=0:CS=0:CT=0:Series=0") + self.ui_test.execute_dialog_through_action(xSeriesObj, "COMMAND", mkPropertyValues({"COMMAND": "FormatDataSeries"})) + + xSeriesFormatDlg = self.xUITest.getTopFocusWindow() + xAxis2 = xSeriesFormatDlg.getChild("RBT_OPT_AXIS_2") + xAxis2.executeAction("CLICK", tuple()) + + xCancelBtn = xSeriesFormatDlg.getChild("ok") + xCancelBtn.executeAction("CLICK", tuple()) + + xGridWindow.executeAction("DESELECT", mkPropertyValues({"OBJECT": ""})) + + self.ui_test.close_doc() + +# vim: set shiftwidth=4 softtabstop=4 expandtab: diff --git a/uitest/calc_tests/function_wizard.py b/uitest/calc_tests/function_wizard.py new file mode 100644 index 000000000..13b833509 --- /dev/null +++ b/uitest/calc_tests/function_wizard.py @@ -0,0 +1,29 @@ +# -*- 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 libreoffice.uno.propertyvalue import mkPropertyValues + +from uitest.framework import UITestCase + +class FunctionWizardTest(UITestCase): + # tdf#98427 + def test_open_function_wizard(self): + self.ui_test.create_doc_in_start_center("calc") + + self.ui_test.execute_modeless_dialog_through_command(".uno:FunctionDialog") + + xFunctionDlg = self.xUITest.getTopFocusWindow() + + xArrayChkBox = xFunctionDlg.getChild("array") + xArrayChkBox.executeAction("CLICK", tuple()) + + xCancelBtn = xFunctionDlg.getChild("cancel") + self.ui_test.close_dialog_through_button(xCancelBtn) + + self.ui_test.close_doc() + +# vim: set shiftwidth=4 softtabstop=4 expandtab: diff --git a/uitest/calc_tests/gridwin.py b/uitest/calc_tests/gridwin.py new file mode 100644 index 000000000..7c9c87de0 --- /dev/null +++ b/uitest/calc_tests/gridwin.py @@ -0,0 +1,48 @@ +# -*- 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 libreoffice.uno.propertyvalue import mkPropertyValues +from uitest.uihelper.common import get_state_as_dict + +from uitest.framework import UITestCase + +class GridWinTest(UITestCase): + + def test_select_object(self): + + self.ui_test.create_doc_in_start_center("calc") + xCalcDoc = self.xUITest.getTopFocusWindow() + xGridWindow = xCalcDoc.getChild("grid_window") + + selectProps = mkPropertyValues({"CELL": "B10"}) + xGridWindow.executeAction("SELECT", selectProps) + + xGridWindow.executeAction("SELECT", mkPropertyValues({"OBJECT": "Object 1"})) + + xGridWindow.executeAction("ACTIVATE", tuple()) + + xGridWindow.executeAction("DESELECT", tuple()) + + self.ui_test.close_doc() + + def test_select_sheet(self): + + self.ui_test.create_doc_in_start_center("calc") + xCalcDoc = self.xUITest.getTopFocusWindow() + xGridWindow = xCalcDoc.getChild("grid_window") + + for i in range(3): + self.ui_test.execute_dialog_through_command(".uno:Insert") + current_dialog = self.xUITest.getTopFocusWindow() + + xOkButton = current_dialog.getChild("ok") + self.ui_test.close_dialog_through_button(xOkButton) + + xGridWindow.executeAction("SELECT", mkPropertyValues({"TABLE": "2"})) + self.assertEqual(get_state_as_dict(xGridWindow)["SelectedTable"], "2") + +# vim: set shiftwidth=4 softtabstop=4 expandtab: diff --git a/uitest/calc_tests/gridwindow.py b/uitest/calc_tests/gridwindow.py new file mode 100644 index 000000000..37afacd00 --- /dev/null +++ b/uitest/calc_tests/gridwindow.py @@ -0,0 +1,43 @@ +# -*- 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 libreoffice.uno.propertyvalue import mkPropertyValues + +from uitest.uihelper.calc import enter_text_to_cell + +from uitest.framework import UITestCase + +class GridWindowTest(UITestCase): + + def test_input(self): + + self.ui_test.create_doc_in_start_center("calc") + xTopWindow = self.xUITest.getTopFocusWindow() + + xGridWindow = xTopWindow.getChild("grid_window") + + enter_text_to_cell(xGridWindow, "C3", "=A1") + enter_text_to_cell(xGridWindow, "A1", "2") + + self.ui_test.close_doc() + + def test_special_keys(self): + + self.ui_test.create_doc_in_start_center("calc") + xTopWindow = self.xUITest.getTopFocusWindow() + + xGridWindow = xTopWindow.getChild("grid_window") + + selectProps = mkPropertyValues({"CELL": "C3"}) + xGridWindow.executeAction("SELECT", selectProps) + + typeProps = mkPropertyValues({"KEYCODE": "CTRL+DOWN"}) + xGridWindow.executeAction("TYPE", typeProps) + + self.ui_test.close_doc() + +# vim: set shiftwidth=4 softtabstop=4 expandtab: diff --git a/uitest/calc_tests/input_window.py b/uitest/calc_tests/input_window.py new file mode 100644 index 000000000..eea8b53d9 --- /dev/null +++ b/uitest/calc_tests/input_window.py @@ -0,0 +1,33 @@ +# -*- 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.framework import UITestCase +from uitest.uihelper.common import get_state_as_dict, type_text +from libreoffice.uno.propertyvalue import mkPropertyValues + +from libreoffice.calc.document import get_cell_by_position + +import time + +class InputWindowTest(UITestCase): + + def test_input_window(self): + + self.ui_test.create_doc_in_start_center("calc") + + xCalcDoc = self.xUITest.getTopFocusWindow() + document = self.ui_test.get_component() + + xInputWin = xCalcDoc.getChild("sc_input_window") + + type_text(xInputWin, "test") + xInputWin.executeAction("TYPE", mkPropertyValues({"KEYCODE": "RETURN"})) + self.assertEqual(get_cell_by_position(document, 0, 0, 0).getString(), "test") + + self.ui_test.close_doc() + +# vim: set shiftwidth=4 softtabstop=4 expandtab: diff --git a/uitest/calc_tests/tdf117987.py b/uitest/calc_tests/tdf117987.py new file mode 100644 index 000000000..3de0b176e --- /dev/null +++ b/uitest/calc_tests/tdf117987.py @@ -0,0 +1,25 @@ +# +# 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.framework import UITestCase +from libreoffice.uno.propertyvalue import mkPropertyValues +from libreoffice.calc.document import get_cell_by_position + +class tdf117987(UITestCase): + + def test_highlight_cell_after_moving_cursor(self): + self.ui_test.create_doc_in_start_center("calc") + xCalcDoc = self.xUITest.getTopFocusWindow() + gridwin = xCalcDoc.getChild("grid_window") + + colorProperty = mkPropertyValues({"BackgroundColor": 16776960}) + gridwin.executeAction("SELECT", mkPropertyValues({"CELL": "A1"})) + self.xUITest.executeCommandWithParameters(".uno:BackgroundColor", colorProperty) + gridwin.executeAction("TYPE", mkPropertyValues({"KEYCODE": "DOWN"})) + self.xUITest.executeCommandWithParameters(".uno:BackgroundColor", colorProperty) + + document = self.ui_test.get_component() + self.assertEqual(get_cell_by_position(document, 0, 0, 1).CellBackColor, 16776960) + self.ui_test.close_doc() diff --git a/uitest/demo_ui/char_dialog.py b/uitest/demo_ui/char_dialog.py new file mode 100644 index 000000000..5dd0212ee --- /dev/null +++ b/uitest/demo_ui/char_dialog.py @@ -0,0 +1,28 @@ +# -*- 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 libreoffice.uno.propertyvalue import mkPropertyValues +from uitest.framework import UITestCase + +class CharDialogText(UITestCase): + + def test_select_char(self): + self.ui_test.create_doc_in_start_center("calc") + + self.ui_test.execute_dialog_through_command(".uno:InsertSymbol") + xCharDialog = self.xUITest.getTopFocusWindow() + + xCharSet = xCharDialog.getChild("showcharset") + + xCharSet.executeAction("SELECT", mkPropertyValues({"COLUMN": "2", "ROW": "2"})) + + xCancelBtn = xCharDialog.getChild("cancel") + self.ui_test.close_dialog_through_button(xCancelBtn) + + self.ui_test.close_doc() + +# vim: set shiftwidth=4 softtabstop=4 expandtab: diff --git a/uitest/demo_ui/checkbox.py b/uitest/demo_ui/checkbox.py new file mode 100644 index 000000000..114473d53 --- /dev/null +++ b/uitest/demo_ui/checkbox.py @@ -0,0 +1,28 @@ +# -*- 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 libreoffice.uno.propertyvalue import mkPropertyValues + +from uitest.framework import UITestCase + +class CheckBoxTest(UITestCase): + + def test_toggle_checkbox(self): + + self.ui_test.create_doc_in_start_center("calc") + + self.ui_test.execute_dialog_through_command(".uno:FormatCellDialog") + xCellsDlg = self.xUITest.getTopFocusWindow() + xNegativeNumRedCB = xCellsDlg.getChild("negnumred") + xNegativeNumRedCB.executeAction("CLICK",tuple()) + + okBtn = xCellsDlg.getChild("ok") + self.ui_test.close_dialog_through_button(okBtn) + + self.ui_test.close_doc() + +# vim: set shiftwidth=4 softtabstop=4 expandtab: diff --git a/uitest/demo_ui/combobox.py b/uitest/demo_ui/combobox.py new file mode 100644 index 000000000..8b47f8338 --- /dev/null +++ b/uitest/demo_ui/combobox.py @@ -0,0 +1,30 @@ +# -*- 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 libreoffice.uno.propertyvalue import mkPropertyValues + +from uitest.framework import UITestCase +from uitest.uihelper.common import select_pos + +class ComboBoxTest(UITestCase): + + def test_select_entry_pos(self): + + self.ui_test.create_doc_in_start_center("calc") + + self.ui_test.execute_modeless_dialog_through_command(".uno:AddName") + xAddNameDlg = self.xUITest.getTopFocusWindow() + + scopeCB = xAddNameDlg.getChild("scope") + select_pos(scopeCB, "1") + + xCancelBtn = xAddNameDlg.getChild("cancel") + self.ui_test.close_dialog_through_button(xCancelBtn) + + self.ui_test.close_doc() + +# vim: set shiftwidth=4 softtabstop=4 expandtab: diff --git a/uitest/demo_ui/command_with_parameters.py b/uitest/demo_ui/command_with_parameters.py new file mode 100644 index 000000000..c82d33595 --- /dev/null +++ b/uitest/demo_ui/command_with_parameters.py @@ -0,0 +1,24 @@ +# -*- 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.framework import UITestCase +from uitest.uihelper.common import type_text +from libreoffice.uno.propertyvalue import mkPropertyValues + +class CommandWithParametersTest(UITestCase): + + def test_text_color_change(self): + + self.ui_test.create_doc_in_start_center("writer") + + self.xUITest.executeCommandWithParameters(".uno:Color", + mkPropertyValues({"Color": 16776960})) + xWriterEdit = self.xUITest.getTopFocusWindow().getChild("writer_edit") + type_text(xWriterEdit, "LibreOffice") + + self.ui_test.close_doc() + +# vim: set shiftwidth=4 softtabstop=4 expandtab: diff --git a/uitest/demo_ui/data/test.ods b/uitest/demo_ui/data/test.ods Binary files differnew file mode 100644 index 000000000..571291d26 --- /dev/null +++ b/uitest/demo_ui/data/test.ods diff --git a/uitest/demo_ui/data/test2.ods b/uitest/demo_ui/data/test2.ods Binary files differnew file mode 100644 index 000000000..550115cb9 --- /dev/null +++ b/uitest/demo_ui/data/test2.ods diff --git a/uitest/demo_ui/edit.py b/uitest/demo_ui/edit.py new file mode 100644 index 000000000..48ada3b1d --- /dev/null +++ b/uitest/demo_ui/edit.py @@ -0,0 +1,55 @@ +# -*- 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 libreoffice.uno.propertyvalue import mkPropertyValues + +from uitest.framework import UITestCase +from uitest.uihelper.common import type_text, get_state_as_dict, select_text + +import time + +class EditTest(UITestCase): + + def test_type_text(self): + + self.ui_test.create_doc_in_start_center("calc") + + self.ui_test.execute_modeless_dialog_through_command(".uno:AddName") + xAddNameDlg = self.xUITest.getTopFocusWindow() + + xEdit = xAddNameDlg.getChild("edit") + + type_text(xEdit, "simpleRangeName") + + xAddBtn = xAddNameDlg.getChild("cancel") + self.ui_test.close_dialog_through_button(xAddBtn) + + self.ui_test.close_doc() + + def test_select_text(self): + + self.ui_test.create_doc_in_start_center("calc") + + self.ui_test.execute_modeless_dialog_through_command(".uno:AddName") + xAddNameDlg = self.xUITest.getTopFocusWindow() + + xEdit = xAddNameDlg.getChild("edit") + + type_text(xEdit, "simpleRangeName") + xEdit.executeAction("SELECT", mkPropertyValues({"FROM": "2", "TO": "9"})) + type_text(xEdit, "otherChars") + self.assertEqual("siotherCharsgeName", get_state_as_dict(xEdit)["Text"]) + + select_text(xEdit, from_pos="2", to="12") + self.assertEqual("otherChars", get_state_as_dict(xEdit)["SelectedText"]) + + xAddBtn = xAddNameDlg.getChild("cancel") + self.ui_test.close_dialog_through_button(xAddBtn) + + self.ui_test.close_doc() + +# vim: set shiftwidth=4 softtabstop=4 expandtab: diff --git a/uitest/demo_ui/gridwin.py b/uitest/demo_ui/gridwin.py new file mode 100644 index 000000000..ddfb13273 --- /dev/null +++ b/uitest/demo_ui/gridwin.py @@ -0,0 +1,51 @@ +# -*- 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 libreoffice.uno.propertyvalue import mkPropertyValues + +from uitest.framework import UITestCase + +class GridWinTest(UITestCase): + + def test_select_cell(self): + + self.ui_test.create_doc_in_start_center("calc") + xCalcDoc = self.xUITest.getTopFocusWindow() + xGridWindow = xCalcDoc.getChild("grid_window") + + selectProps = mkPropertyValues({"CELL": "B10"}) + xGridWindow.executeAction("SELECT", selectProps) + + self.ui_test.close_doc() + + def test_select_range(self): + + self.ui_test.create_doc_in_start_center("calc") + xCalcDoc = self.xUITest.getTopFocusWindow() + xGridWindow = xCalcDoc.getChild("grid_window") + + selectProps = mkPropertyValues({"RANGE": "B10:C20"}) + xGridWindow.executeAction("SELECT", selectProps) + + self.ui_test.close_doc() + + def test_extend_range(self): + + self.ui_test.create_doc_in_start_center("calc") + xTopWindow = self.xUITest.getTopFocusWindow() + + xGridWindow = xTopWindow.getChild("grid_window") + + selectProps = mkPropertyValues({"RANGE": "B10:C20"}) + xGridWindow.executeAction("SELECT", selectProps) + + select2Props = mkPropertyValues({"RANGE": "D3:F5", "EXTEND": "true"}) + xGridWindow.executeAction("SELECT", select2Props) + + self.ui_test.close_doc() + +# vim: set shiftwidth=4 softtabstop=4 expandtab: diff --git a/uitest/demo_ui/handle_multiple_files.py b/uitest/demo_ui/handle_multiple_files.py new file mode 100644 index 000000000..e60d3884b --- /dev/null +++ b/uitest/demo_ui/handle_multiple_files.py @@ -0,0 +1,62 @@ +# -*- 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 libreoffice.uno.propertyvalue import mkPropertyValues +from libreoffice.uno.eventlistener import EventListener + +from uitest.framework import UITestCase + +from uitest.debug import sleep + +import time +import org.libreoffice.unotest +import os +import pathlib + +def get_url_for_data_file(file_name): + return pathlib.Path(org.libreoffice.unotest.makeCopyFromTDOC(file_name)).as_uri() + +class HandleFiles(UITestCase): + + def test_load_file(self): + + calc_file = self.ui_test.load_file(get_url_for_data_file("test.ods")) + + calc_file2 = self.ui_test.load_file(get_url_for_data_file("test2.ods")) + + frames = self.ui_test.get_frames() + self.assertEqual(len(frames), 2) + + self.ui_test.close_doc() + + frames = self.ui_test.get_frames() + self.assertEqual(len(frames), 1) + + # this is currently still necessary as otherwise + # the command is not forwarded to the correct frame + # TODO: provide an additional event that we can use + # and get rid of the sleep + time.sleep(1) + + self.ui_test.close_doc() + + def test_select_frame(self): + calc_file = self.ui_test.load_file(get_url_for_data_file("test.ods")) + + calc_file2 = self.ui_test.load_file(get_url_for_data_file("test2.ods")) + frames = self.ui_test.get_frames() + self.assertEqual(len(frames), 2) + frames[0].activate() + + self.ui_test.close_doc() + + frames = self.ui_test.get_frames() + self.assertEqual(len(frames), 1) + + self.assertTrue(frames[0].getTitle().startswith("test2.ods")) + +# vim: set shiftwidth=4 softtabstop=4 expandtab: diff --git a/uitest/demo_ui/hierarchy.py b/uitest/demo_ui/hierarchy.py new file mode 100644 index 000000000..f5434366f --- /dev/null +++ b/uitest/demo_ui/hierarchy.py @@ -0,0 +1,35 @@ +# -*- 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 libreoffice.uno.propertyvalue import mkPropertyValues + +from uitest.framework import UITestCase + +import json + +class CheckBoxTest(UITestCase): + + def test_get_json(self): + + self.ui_test.create_doc_in_start_center("calc") + + self.ui_test.execute_dialog_through_command(".uno:About") + + xAboutDlg = self.xUITest.getTopFocusWindow() + + json_string = xAboutDlg.getHierarchy() + print(json_string) + json_content = json.loads(json_string) + print(json_content) + print(json.dumps(json_content, indent=4)) + + closeBtn = xAboutDlg.getChild("btnClose") + self.ui_test.close_dialog_through_button(closeBtn) + + self.ui_test.close_doc() + +# vim: set shiftwidth=4 softtabstop=4 expandtab: diff --git a/uitest/demo_ui/listbox.py b/uitest/demo_ui/listbox.py new file mode 100644 index 000000000..780da1ff2 --- /dev/null +++ b/uitest/demo_ui/listbox.py @@ -0,0 +1,48 @@ +# -*- 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 libreoffice.uno.propertyvalue import mkPropertyValues + +from uitest.framework import UITestCase +from uitest.uihelper.common import select_pos + +class ListBoxTest(UITestCase): + + def test_select_entry_pos(self): + + self.ui_test.create_doc_in_start_center("calc") + + self.ui_test.execute_dialog_through_command(".uno:FormatCellDialog") + xCellsDlg = self.xUITest.getTopFocusWindow() + + categoryLB = xCellsDlg.getChild("categorylb") + select_pos(categoryLB, "4") + + xOkBtn = xCellsDlg.getChild("ok") + self.ui_test.close_dialog_through_button(xOkBtn) + + self.ui_test.close_doc() + + def test_select_entry_text(self): + + self.ui_test.create_doc_in_start_center("calc") + + self.ui_test.execute_dialog_through_command(".uno:FormatCellDialog") + xCellsDlg = self.xUITest.getTopFocusWindow() + + categoryLB = xCellsDlg.getChild("categorylb") + props = {"TEXT": "Time"} + + actionProps = mkPropertyValues(props) + categoryLB.executeAction("SELECT", actionProps) + + xOkBtn = xCellsDlg.getChild("ok") + self.ui_test.close_dialog_through_button(xOkBtn) + + self.ui_test.close_doc() + +# vim: set shiftwidth=4 softtabstop=4 expandtab: diff --git a/uitest/demo_ui/radiobutton.py b/uitest/demo_ui/radiobutton.py new file mode 100644 index 000000000..bb2f5bd07 --- /dev/null +++ b/uitest/demo_ui/radiobutton.py @@ -0,0 +1,40 @@ +# -*- 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 libreoffice.uno.propertyvalue import mkPropertyValues + +from uitest.framework import UITestCase + +import time + +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 RadioButtonTest(UITestCase): + + def test_toggle_radiobutton(self): + + self.ui_test.create_doc_in_start_center("calc") + + self.ui_test.execute_dialog_through_command(".uno:FormatCellDialog") + xCellsDlg = self.xUITest.getTopFocusWindow() + xNegativeNumRedCB = xCellsDlg.getChild("negnumred") + xNegativeNumRedCB.executeAction("CLICK",tuple()) + + okBtn = xCellsDlg.getChild("ok") + self.ui_test.close_dialog_through_button(okBtn) + + self.ui_test.close_doc() + +# vim: set shiftwidth=4 softtabstop=4 expandtab: diff --git a/uitest/demo_ui/spinfield.py b/uitest/demo_ui/spinfield.py new file mode 100644 index 000000000..3f73006b1 --- /dev/null +++ b/uitest/demo_ui/spinfield.py @@ -0,0 +1,81 @@ +# -*- 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 libreoffice.uno.propertyvalue import mkPropertyValues + +from uitest.framework import UITestCase +from uitest.uihelper.common import get_state_as_dict, type_text, select_pos + +class SpinFieldTest(UITestCase): + + def test_up(self): + + self.ui_test.create_doc_in_start_center("calc") + + self.ui_test.execute_dialog_through_command(".uno:FormatCellDialog") + xCellsDlg = self.xUITest.getTopFocusWindow() + + # select the numbers tab page + select_pos(xCellsDlg, "0") + + xDecimalPlaces = xCellsDlg.getChild("leadzerosed") + xDecimalPlaces.executeAction("UP", tuple()) + + decimal_places_state = get_state_as_dict(xDecimalPlaces) + assert(decimal_places_state["Text"] == "2") + + okBtn = xCellsDlg.getChild("ok") + self.ui_test.close_dialog_through_button(okBtn) + + self.ui_test.close_doc() + + def test_down(self): + + self.ui_test.create_doc_in_start_center("calc") + + self.ui_test.execute_dialog_through_command(".uno:FormatCellDialog") + xCellsDlg = self.xUITest.getTopFocusWindow() + + # select the numbers tab page + select_pos(xCellsDlg, "0") + + xDecimalPlaces = xCellsDlg.getChild("leadzerosed") + xDecimalPlaces.executeAction("UP", tuple()) + xDecimalPlaces.executeAction("UP", tuple()) + + decimal_places_state = get_state_as_dict(xDecimalPlaces) + assert(decimal_places_state["Text"] == "3") + + xDecimalPlaces.executeAction("DOWN", tuple()) + + decimal_places_state = get_state_as_dict(xDecimalPlaces) + assert(decimal_places_state["Text"] == "2") + + okBtn = xCellsDlg.getChild("ok") + self.ui_test.close_dialog_through_button(okBtn) + + self.ui_test.close_doc() + + def test_text(self): + + self.ui_test.create_doc_in_start_center("calc") + + self.ui_test.execute_dialog_through_command(".uno:FormatCellDialog") + xCellsDlg = self.xUITest.getTopFocusWindow() + + xDecimalPlaces = xCellsDlg.getChild("leadzerosed") + type_text(xDecimalPlaces, "4") + + decimal_places_state = get_state_as_dict(xDecimalPlaces) + assert(decimal_places_state["Text"] == "41") + + okBtn = xCellsDlg.getChild("ok") + self.ui_test.close_dialog_through_button(okBtn) + + self.ui_test.close_doc() + +# vim: set shiftwidth=4 softtabstop=4 expandtab: diff --git a/uitest/demo_ui/tabcontrol.py b/uitest/demo_ui/tabcontrol.py new file mode 100644 index 000000000..47b3f33a3 --- /dev/null +++ b/uitest/demo_ui/tabcontrol.py @@ -0,0 +1,38 @@ +# -*- 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 libreoffice.uno.propertyvalue import mkPropertyValues + +from uitest.uihelper.calc import enter_text_to_cell +from uitest.uihelper.common import select_pos + +from uitest.framework import UITestCase + +class TabControlTest(UITestCase): + + def test_select_pos(self): + + self.ui_test.create_doc_in_start_center("calc") + + xCalcDoc = self.xUITest.getTopFocusWindow() + xGridWindow = xCalcDoc.getChild("grid_window") + enter_text_to_cell(xGridWindow, "B2", "=2+3+4") + xGridWindow.executeAction("SELECT", mkPropertyValues({"CELL": "B2"})) + + self.ui_test.execute_modeless_dialog_through_command(".uno:FunctionDialog") + + xFunctionDlg = self.xUITest.getTopFocusWindow() + + xTabs = xFunctionDlg.getChild("tabcontrol") + select_pos(xTabs, "1") + + xCancelBtn = xFunctionDlg.getChild("cancel") + xCancelBtn.executeAction("CLICK", tuple()) + + self.ui_test.close_doc() + +# vim: set shiftwidth=4 softtabstop=4 expandtab: diff --git a/uitest/demo_ui/tabdialog.py b/uitest/demo_ui/tabdialog.py new file mode 100644 index 000000000..ed46379ab --- /dev/null +++ b/uitest/demo_ui/tabdialog.py @@ -0,0 +1,45 @@ +# -*- 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 libreoffice.uno.propertyvalue import mkPropertyValues + +from uitest.framework import UITestCase +from uitest.uihelper.common import select_pos + +class TabDialogTest(UITestCase): + + def test_select_tab_page_pos(self): + + self.ui_test.create_doc_in_start_center("calc") + + self.ui_test.execute_dialog_through_command(".uno:FormatCellDialog") + xCellsDlg = self.xUITest.getTopFocusWindow() + + select_pos(xCellsDlg, "1") + + xOkBtn = xCellsDlg.getChild("ok") + self.ui_test.close_dialog_through_button(xOkBtn) + + self.ui_test.close_doc() + + def test_select_tab_page_name(self): + + self.ui_test.create_doc_in_start_center("calc") + + self.ui_test.execute_dialog_through_command(".uno:FormatCellDialog") + xCellsDlg = self.xUITest.getTopFocusWindow() + + props = {"NAME": "Borders"} + propsUNO = mkPropertyValues(props) + xCellsDlg.executeAction("SELECT", propsUNO) + + xOkBtn = xCellsDlg.getChild("ok") + self.ui_test.close_dialog_through_button(xOkBtn) + + self.ui_test.close_doc() + +# vim: set shiftwidth=4 softtabstop=4 expandtab: diff --git a/uitest/demo_ui/treelist.py b/uitest/demo_ui/treelist.py new file mode 100644 index 000000000..265fa8b97 --- /dev/null +++ b/uitest/demo_ui/treelist.py @@ -0,0 +1,46 @@ +# -*- 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 libreoffice.uno.propertyvalue import mkPropertyValues +from uitest.uihelper.calc import enter_text_to_cell + +from uitest.uihelper.common import get_state_as_dict, select_pos + +from uitest.framework import UITestCase + +class TreeListTest(UITestCase): + + def test_expand(self): + + self.ui_test.create_doc_in_start_center("calc") + + xCalcDoc = self.xUITest.getTopFocusWindow() + xGridWindow = xCalcDoc.getChild("grid_window") + enter_text_to_cell(xGridWindow, "B2", "=2+3+4") + xGridWindow.executeAction("SELECT", mkPropertyValues({"CELL": "B2"})) + + self.ui_test.execute_modeless_dialog_through_command(".uno:FunctionDialog") + + xFunctionDlg = self.xUITest.getTopFocusWindow() + + xTabs = xFunctionDlg.getChild("tabcontrol") + select_pos(xTabs, "1") + + xTreelist = xTabs.getChild("struct") + + xTreeEntry = xTreelist.getChild('0') + + xTreeEntry.executeAction("COLLAPSE", tuple()) + + xTreeEntry.executeAction("EXPAND", tuple()) + + xCancelBtn = xFunctionDlg.getChild("cancel") + xCancelBtn.executeAction("CLICK", tuple()) + + self.ui_test.close_doc() + +# vim: set shiftwidth=4 softtabstop=4 expandtab: diff --git a/uitest/impress_tests/backgrounds.py b/uitest/impress_tests/backgrounds.py new file mode 100644 index 000000000..6e2493b06 --- /dev/null +++ b/uitest/impress_tests/backgrounds.py @@ -0,0 +1,146 @@ +# +# 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.framework import UITestCase +from uitest.uihelper.common import select_pos +from com.sun.star.awt.GradientStyle import LINEAR +from com.sun.star.drawing.HatchStyle import SINGLE +from com.sun.star.drawing.BitmapMode import REPEAT +from com.sun.star.drawing.RectanglePoint import MIDDLE_MIDDLE + +class ImpressBackgrounds(UITestCase): + + def checkDefaultBackground(self, btn): + document = self.ui_test.get_component() + if btn == 'btnnone': + self.assertEqual(document.DrawPages.getByIndex(0).Background, None) + elif btn == 'btncolor': + self.assertEqual( + hex(document.DrawPages.getByIndex(0).Background.FillColor), '0x729fcf') + self.assertEqual( + hex(document.DrawPages.getByIndex(0).Background.FillColor), '0x729fcf') + elif btn == 'btngradient': + self.assertEqual( + document.DrawPages.getByIndex(0).Background.FillGradient.Style, LINEAR) + self.assertEqual( + hex(document.DrawPages.getByIndex(0).Background.FillGradient.StartColor), '0xdde8cb') + self.assertEqual( + document.DrawPages.getByIndex(0).Background.FillGradient.Angle, 300) + self.assertEqual( + document.DrawPages.getByIndex(0).Background.FillGradient.Border, 0) + self.assertEqual( + document.DrawPages.getByIndex(0).Background.FillGradient.XOffset, 0) + self.assertEqual( + document.DrawPages.getByIndex(0).Background.FillGradient.YOffset, 0) + self.assertEqual( + document.DrawPages.getByIndex(0).Background.FillGradient.StartIntensity, 100) + self.assertEqual( + document.DrawPages.getByIndex(0).Background.FillGradient.EndIntensity, 100) + self.assertEqual( + document.DrawPages.getByIndex(0).Background.FillGradientName, 'Pastel Bouquet') + elif btn == 'btnhatch': + self.assertEqual( + document.DrawPages.getByIndex(0).Background.FillHatch.Style, SINGLE ) + self.assertEqual( + document.DrawPages.getByIndex(0).Background.FillHatch.Color, 0) + self.assertEqual( + document.DrawPages.getByIndex(0).Background.FillHatch.Distance, 102) + self.assertEqual( + document.DrawPages.getByIndex(0).Background.FillHatch.Angle, 0) + self.assertEqual( + document.DrawPages.getByIndex(0).Background.FillHatchName, 'Black 0 Degrees') + elif btn == 'btnbitmap': + self.assertEqual( + document.DrawPages.getByIndex(0).Background.FillBitmapMode, REPEAT) + self.assertEqual( + document.DrawPages.getByIndex(0).Background.FillBitmapPositionOffsetX, 0) + self.assertEqual( + document.DrawPages.getByIndex(0).Background.FillBitmapPositionOffsetY, 0) + self.assertEqual( + document.DrawPages.getByIndex(0).Background.FillBitmapRectanglePoint, MIDDLE_MIDDLE) + self.assertEqual( + document.DrawPages.getByIndex(0).Background.FillBitmapStretch, False) + self.assertEqual( + document.DrawPages.getByIndex(0).Background.FillBitmapTile, True) + self.assertEqual( + document.DrawPages.getByIndex(0).Background.FillBitmapOffsetX, 0) + self.assertEqual( + document.DrawPages.getByIndex(0).Background.FillBitmapOffsetY, 0) + self.assertEqual( + document.DrawPages.getByIndex(0).Background.FillBitmapLogicalSize, True) + self.assertEqual( + document.DrawPages.getByIndex(0).Background.FillBitmapSizeX, 0) + self.assertEqual( + document.DrawPages.getByIndex(0).Background.FillBitmapSizeY, 0) + self.assertEqual(document.DrawPages.getByIndex(0).Background.FillBitmapName, 'Painted White') + elif btn == 'btnpattern': + self.assertEqual( + document.DrawPages.getByIndex(0).Background.FillBitmapMode, REPEAT) + self.assertEqual( + document.DrawPages.getByIndex(0).Background.FillBitmapPositionOffsetX, 0) + self.assertEqual( + document.DrawPages.getByIndex(0).Background.FillBitmapPositionOffsetY, 0) + self.assertEqual( + document.DrawPages.getByIndex(0).Background.FillBitmapRectanglePoint, MIDDLE_MIDDLE) + self.assertEqual( + document.DrawPages.getByIndex(0).Background.FillBitmapStretch, True) + self.assertEqual( + document.DrawPages.getByIndex(0).Background.FillBitmapTile, True) + self.assertEqual( + document.DrawPages.getByIndex(0).Background.FillBitmapOffsetX, 0) + self.assertEqual( + document.DrawPages.getByIndex(0).Background.FillBitmapOffsetY, 0) + self.assertEqual( + document.DrawPages.getByIndex(0).Background.FillBitmapLogicalSize, True) + self.assertEqual( + document.DrawPages.getByIndex(0).Background.FillBitmapSizeX, 0) + self.assertEqual( + document.DrawPages.getByIndex(0).Background.FillBitmapSizeY, 0) + self.assertEqual( + document.DrawPages.getByIndex(0).Background.FillBitmapName, '5 Percent') + + + def test_background_dialog(self): + + self.ui_test.create_doc_in_start_center("impress") + + xTemplateDlg = self.xUITest.getTopFocusWindow() + xCancelBtn = xTemplateDlg.getChild("cancel") + self.ui_test.close_dialog_through_button(xCancelBtn) + + buttons = ['btnbitmap', 'btncolor', 'btngradient', 'btnhatch', 'btnpattern'] + for index, button in enumerate(buttons): + self.ui_test.execute_dialog_through_command(".uno:PageSetup") + + xPageSetupDlg = self.xUITest.getTopFocusWindow() + tabcontrol = xPageSetupDlg.getChild("tabcontrol") + select_pos(tabcontrol, "1") + + xBtn = xPageSetupDlg.getChild(button) + xBtn.executeAction("CLICK", tuple()) + + xOkBtn = xPageSetupDlg.getChild("ok") + xOkBtn.executeAction("CLICK", tuple()) + + self.checkDefaultBackground(button) + + self.ui_test.execute_dialog_through_command(".uno:PageSetup") + + xPageSetupDlg = self.xUITest.getTopFocusWindow() + tabcontrol = xPageSetupDlg.getChild("tabcontrol") + select_pos(tabcontrol, "1") + + xBtn = xPageSetupDlg.getChild('btnnone') + xBtn.executeAction("CLICK", tuple()) + + xOkBtn = xPageSetupDlg.getChild("ok") + xOkBtn.executeAction("CLICK", tuple()) + + self.checkDefaultBackground('btnnone') + + self.ui_test.close_doc() + +# vim: set shiftwidth=4 softtabstop=4 expandtab: diff --git a/uitest/impress_tests/drawinglayer.py b/uitest/impress_tests/drawinglayer.py new file mode 100644 index 000000000..d6a8920e7 --- /dev/null +++ b/uitest/impress_tests/drawinglayer.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 + +from libreoffice.uno.propertyvalue import mkPropertyValues + +from uitest.framework import UITestCase + +from uitest.debug import time + +class ImpressDrawinglayerTest(UITestCase): + + def test_move_object(self): + self.ui_test.create_doc_in_start_center("impress") + + xTemplateDlg = self.xUITest.getTopFocusWindow() + xCancelBtn = xTemplateDlg.getChild("cancel") + self.ui_test.close_dialog_through_button(xCancelBtn) + + xImpressDoc = self.xUITest.getTopFocusWindow() + + xEditWin = xImpressDoc.getChild("impress_win") + + xDrawinglayerObject = xEditWin.getChild("Unnamed Drawinglayer object 1") + print(get_state_as_dict(xDrawinglayerObject)) + xDrawinglayerObject.executeAction("MOVE", mkPropertyValues({"X": "1000", "Y":"1000"})) + + self.ui_test.close_doc() + + def test_resize_object(self): + self.ui_test.create_doc_in_start_center("impress") + + xTemplateDlg = self.xUITest.getTopFocusWindow() + xCancelBtn = xTemplateDlg.getChild("cancel") + self.ui_test.close_dialog_through_button(xCancelBtn) + + xImpressDoc = self.xUITest.getTopFocusWindow() + + xEditWin = xImpressDoc.getChild("impress_win") + + xDrawinglayerObject = xEditWin.getChild("Unnamed Drawinglayer object 1") + print(get_state_as_dict(xDrawinglayerObject)) + xDrawinglayerObject.executeAction("RESIZE", mkPropertyValues({"X": "500", "Y":"4000", "FRAC_X": "0.5", "FRAC_Y": "0.5"})) + + self.ui_test.close_doc() + +# vim: set shiftwidth=4 softtabstop=4 expandtab: diff --git a/uitest/impress_tests/layouts.py b/uitest/impress_tests/layouts.py new file mode 100644 index 000000000..8e108913d --- /dev/null +++ b/uitest/impress_tests/layouts.py @@ -0,0 +1,43 @@ +# +# 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.framework import UITestCase +from libreoffice.uno.propertyvalue import mkPropertyValues + +class ImpressLayouts(UITestCase): + + def test_impress_layouts(self): + + self.ui_test.create_doc_in_start_center("impress") + + xTemplateDlg = self.xUITest.getTopFocusWindow() + xCancelBtn = xTemplateDlg.getChild("cancel") + self.ui_test.close_dialog_through_button(xCancelBtn) + + layouts= (".uno:AssignLayout?WhatLayout:long=20", ".uno:AssignLayout?WhatLayout:long=19", + ".uno:AssignLayout?WhatLayout:long=0", ".uno:AssignLayout?WhatLayout:long=1", + ".uno:AssignLayout?WhatLayout:long=32", ".uno:AssignLayout?WhatLayout:long=3", + ".uno:AssignLayout?WhatLayout:long=12", ".uno:AssignLayout?WhatLayout:long=15", + ".uno:AssignLayout?WhatLayout:long=14", ".uno:AssignLayout?WhatLayout:long=16", + ".uno:AssignLayout?WhatLayout:long=18", ".uno:AssignLayout?WhatLayout:long=34", + ".uno:AssignLayout?WhatLayout:long=28", ".uno:AssignLayout?WhatLayout:long=27", + ".uno:AssignLayout?WhatLayout:long=29", ".uno:AssignLayout?WhatLayout:long=30") + + for i in layouts: + self.xUITest.executeCommand(i) + + xImpressDoc = self.xUITest.getTopFocusWindow() + + xEditWin = xImpressDoc.getChild("impress_win") + + # There's a layout with 7 objects + for j in range(0,6): + xEditWin.executeAction("SELECT", mkPropertyValues({"OBJECT":"Unnamed Drawinglayer object " + str(j)})) + xEditWin.executeAction("DESELECT", tuple()) + + self.ui_test.close_doc() + +# vim: set shiftwidth=4 softtabstop=4 expandtab: diff --git a/uitest/impress_tests/start.py b/uitest/impress_tests/start.py new file mode 100644 index 000000000..de7a6ece7 --- /dev/null +++ b/uitest/impress_tests/start.py @@ -0,0 +1,80 @@ +# -*- 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 + +from libreoffice.uno.propertyvalue import mkPropertyValues + +from uitest.framework import UITestCase + +import time + +class SimpleImpressTest(UITestCase): + def test_start_impress(self): + + self.ui_test.create_doc_in_start_center("impress") + + xTemplateDlg = self.xUITest.getTopFocusWindow() + xCancelBtn = xTemplateDlg.getChild("cancel") + self.ui_test.close_dialog_through_button(xCancelBtn) + + xImpressDoc = self.xUITest.getTopFocusWindow() + + xEditWin = xImpressDoc.getChild("impress_win") + xEditWin.executeAction("SET", mkPropertyValues({"ZOOM": "200"})) + + self.ui_test.close_doc() + + def test_select_page(self): + + self.ui_test.create_doc_in_start_center("impress") + + xTemplateDlg = self.xUITest.getTopFocusWindow() + xCancelBtn = xTemplateDlg.getChild("cancel") + self.ui_test.close_dialog_through_button(xCancelBtn) + + xImpressDoc = self.xUITest.getTopFocusWindow() + + xEditWin = xImpressDoc.getChild("impress_win") + + xEditWin.executeAction("GOTO", mkPropertyValues({"PAGE": "2"})) + + self.ui_test.close_doc() + + def test_select_text(self): + + self.ui_test.create_doc_in_start_center("impress") + + xTemplateDlg = self.xUITest.getTopFocusWindow() + xCancelBtn = xTemplateDlg.getChild("cancel") + self.ui_test.close_dialog_through_button(xCancelBtn) + + xImpressDoc = self.xUITest.getTopFocusWindow() + + xEditWin = xImpressDoc.getChild("impress_win") + + self.ui_test.close_doc() + + def test_select_object(self): + + self.ui_test.create_doc_in_start_center("impress") + + xTemplateDlg = self.xUITest.getTopFocusWindow() + xCancelBtn = xTemplateDlg.getChild("cancel") + self.ui_test.close_dialog_through_button(xCancelBtn) + + xImpressDoc = self.xUITest.getTopFocusWindow() + print(xImpressDoc.getChildren()) + + xEditWin = xImpressDoc.getChild("impress_win") + + xEditWin.executeAction("SELECT", mkPropertyValues({"OBJECT":"Unnamed Drawinglayer object 1"})) + xEditWin.executeAction("DESELECT", tuple()) + + self.ui_test.close_doc() + +# vim: set shiftwidth=4 softtabstop=4 expandtab: 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/document.py b/uitest/libreoffice/calc/document.py new file mode 100644 index 000000000..c4eac000a --- /dev/null +++ b/uitest/libreoffice/calc/document.py @@ -0,0 +1,51 @@ +# -*- 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) + +# 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..cb3ae1a01 --- /dev/null +++ b/uitest/libreoffice/connection.py @@ -0,0 +1,189 @@ +# -*- 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 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.socket = None + self.xContext = None + self.pro = 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 + self.xContext = self.connect(socket) + + 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'] + + self.pro = subprocess.Popen(argv, env=env) + return self.pro + + 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. + + First tries to terminate the soffice instance through the normal + XDesktop::terminate method and waits for about 30 seconds before + considering this attempt failed. After the 30 seconds the subprocess + is terminated """ + + 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 UnknownPropertyException while TearDown") + pass # ignore, also means disposed + except pyuno.getClass("com.sun.star.lang.DisposedException"): + print("caught DisposedException while TearDown") + pass # ignore + else: + self.soffice.terminate() + + ret = self.soffice.wait() + self.xContext = None + self.socket = 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..ba7faec76 --- /dev/null +++ b/uitest/libreoffice/uno/eventlistener.py @@ -0,0 +1,57 @@ +# -*- 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 + 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..a05c6a967 --- /dev/null +++ b/uitest/libreoffice/uno/propertyvalue.py @@ -0,0 +1,40 @@ +# -*- 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 + 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 + +def mkPropertyValue(name, value): + """ Create a UNO ProertyValue 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: diff --git a/uitest/loginterpreter.py b/uitest/loginterpreter.py new file mode 100755 index 000000000..e84d9a0ed --- /dev/null +++ b/uitest/loginterpreter.py @@ -0,0 +1,209 @@ +#!/usr/bin/env python3 +# -*- tab-width: 4; indent-tabs-mode: nil; py-indent-offset: 4 -*- +# +# This file is part of the LibreOffice project. +# +# 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 os +import sys +import argparse + +def parse_line(line): + """ + This function parses a line from log file + and returns the parsed values as a python dictionary + """ + if (line == ""): + return + dict = {} + if "{" in line: + start_index_of_parameters = line.find("{") + end_index_of_parameters = line.find("}") + 1 + parameters = line[start_index_of_parameters:end_index_of_parameters] + if parameters != "": + dict["parameters"] = parameters + line = line[:start_index_of_parameters-1] + word_list = line.split() + dict["keyword"] = word_list[0] + + for index in range(1,len(word_list)): + key, val = word_list[index].split(":",1) + dict[key] = val + return dict + +def parse_args(): + """ + This function parses the command-line arguments + to get the input and output file details + """ + parser = argparse.ArgumentParser(description = "Generate a UI test file from log") + parser.add_argument("input_address", type = str, help = "The log file address") + parser.add_argument("output_address", type = str, help = "The test file address") + parser.add_argument("-d", "--document", metavar = "", help = "Address of the document to be opened") + args = parser.parse_args() + return args + +def get_log_file(input_address): + try: + with open(input_address) as f: + content = f.readlines() + except IOError as err: + print("IO error: {0}".format(err)) + print("Use " + os.path.basename(sys.argv[0]) + " -h to get usage instructions") + sys.exit(1) + + content = [x.strip() for x in content if not x.startswith("Action on element")] + return content + +def initiate_test_generation(address): + try: + f = open(address,"w") + except IOError as err: + print("IO error: {0}".format(err)) + print("Use " + os.path.basename(sys.argv[0]) + " -h to get usage instructions") + sys.exit(1) + initial_text = \ + "# -*- tab-width: 4; indent-tabs-mode: nil; py-indent-offset: 4 -*-\n\n" + \ + "from uitest.framework import UITestCase\n" + \ + "from libreoffice.uno.propertyvalue import mkPropertyValues\n" + \ + "import importlib\n\n" + \ + "class TestClass(UITestCase):\n" + \ + " def test_function(self):\n" + f.write(initial_text) + return f + +def get_coupling_type(line1, line2): + """ + This function checks if two consecutive lines of log file + refer to the same event + """ + action_dict1 = parse_line(line1) + action_dict2 = parse_line(line2) + + if action_dict1["keyword"] == "CommandSent" and \ + action_dict2["keyword"] == "ModalDialogExecuted": + return "COMMAND_MODAL_COUPLE" + + elif action_dict1["keyword"] == "CommandSent" and \ + action_dict2["keyword"] == "ModelessDialogConstructed": + return "COMMAND_MODELESS_COUPLE" + + elif action_dict1["keyword"] == "ButtonUIObject" and \ + action_dict2["keyword"] == "DialogClosed": + return "BUTTON_DIALOGCLOSE_COUPLE" + + elif "parameters" in action_dict1 and \ + "KEYCODE" in action_dict1["parameters"] and \ + action_dict2["keyword"] == "CommandSent": + return "REDUNDANT_COUPLE" + + return "NOT_A_COUPLE" + +def check_app_starting_action(action_dict): + app_starter_button_ids = \ + set(["draw_all", "impress_all", "calc_all" , "writer_all", "database_all", "math_all"]) + + if action_dict["keyword"] == "ButtonUIObject" and action_dict["Action"] == "CLICK" and \ + action_dict["Id"] in app_starter_button_ids: + return True + return False + +def get_test_line_from_one_log_line(log_line): + action_dict = parse_line(log_line) + test_line = " " + if action_dict["keyword"].endswith("UIObject"): + parent = action_dict["Parent"] + if (check_app_starting_action(action_dict)): + test_line +=\ + "MainDoc = self.ui_test.create_doc_in_start_center(\"" + \ + action_dict["Id"][:-4] +"\")\n MainWindow = " + \ + "self.xUITest.getTopFocusWindow()\n" + return test_line + else: + if (parent == ""): + parent = "MainWindow" + test_line += \ + action_dict["Id"] + " = " + parent + ".getChild(\"" + \ + action_dict["Id"] + "\")\n " + \ + action_dict["Id"] + ".executeAction(\"" + \ + action_dict["Action"] + "\"" + if "parameters" in action_dict: + test_line += ", mkPropertyValues(" + \ + action_dict["parameters"] + "))\n" + else: + test_line += ",tuple())\n" + return test_line + elif action_dict["keyword"] == "CommandSent": + if "parameters" not in action_dict: + test_line += "self.xUITest.executeCommand(\"" + \ + action_dict["Name"] + "\")\n" + return test_line + else: + test_line += "self.xUITest.executeCommandWithParameters(\"" + \ + action_dict["Name"] + "\", mkPropertyValues(" + action_dict["parameters"] + \ + "))\n" + return test_line + elif action_dict["keyword"] == "ModalDialogExecuted" or \ + action_dict["keyword"] == "ModelessDialogConstructed": + test_line += action_dict["Id"] + " = " + "self.xUITest.getTopFocusWindow()\n" + return test_line + + return "" + +def get_test_line_from_two_log_lines(log_line1,log_line2): + coupling_type = get_coupling_type(log_line1, log_line2) + action_dict1 = parse_line(log_line1) + action_dict2 = parse_line(log_line2) + test_line = " " + if coupling_type == "COMMAND_MODAL_COUPLE": + test_line += \ + "self.ui_test.execute_dialog_through_command(\"" + \ + action_dict1["Name"] + "\")\n " + \ + action_dict2["Id"] + " = self.xUITest.getTopFocusWindow()\n" + elif coupling_type == "COMMAND_MODELESS_COUPLE": + test_line += \ + "self.ui_test.execute_modeless_dialog_through_command(\"" + \ + action_dict1["Name"] + "\")\n " + \ + action_dict2["Id"] + " = self.xUITest.getTopFocusWindow()\n" + elif coupling_type == "BUTTON_DIALOGCLOSE_COUPLE": + test_line += \ + action_dict1["Id"] + " = " + action_dict1["Parent"] + ".getChild(\"" + \ + action_dict1["Id"] + "\")\n self.ui_test.close_dialog_through_button(" + \ + action_dict1["Id"] + ")\n" + return test_line + +def main(): + args = parse_args() + log_lines = get_log_file(args.input_address) + output_stream = initiate_test_generation(args.output_address) + if args.document is not None: + output_line = " pathmodule = importlib.import_module(\"uitest.path\")\n" + \ + " doc_path = pathmodule.get_srcdir_url() + \"" + args.document + "\"\n" + \ + " MainDoc = self.ui_test.load_file(doc_path)\n" + \ + " MainWindow = self.xUITest.getTopFocusWindow()\n" + output_stream.write(output_line) + line_number = 0 + while line_number < len(log_lines): + if line_number == len(log_lines)-1 or \ + get_coupling_type(log_lines[line_number],log_lines[line_number + 1]) == "NOT_A_COUPLE": + test_line = get_test_line_from_one_log_line(log_lines[line_number]) + output_stream.write(test_line) + line_number += 1 + elif get_coupling_type(log_lines[line_number],log_lines[line_number + 1]) == "REDUNDANT_COUPLE": + line_number += 1 + else: + test_line = get_test_line_from_two_log_lines(log_lines[line_number],log_lines[line_number + 1]) + output_stream.write(test_line) + line_number += 2 + output_stream.write(" self.ui_test.close_doc()") + output_stream.write("\n\n# vim: set shiftwidth=4 softtabstop=4 expandtab:") + output_stream.close() + +if __name__ == '__main__': + main() + +# vim: set shiftwidth=4 softtabstop=4 expandtab: diff --git a/uitest/manual_tests/__init__.py b/uitest/manual_tests/__init__.py new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/uitest/manual_tests/__init__.py diff --git a/uitest/manual_tests/calc.py b/uitest/manual_tests/calc.py new file mode 100644 index 000000000..1b7897983 --- /dev/null +++ b/uitest/manual_tests/calc.py @@ -0,0 +1,235 @@ +# -*- 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.framework import UITestCase + +from libreoffice.uno.propertyvalue import mkPropertyValues +from libreoffice.calc.document import get_cell_by_position + +from uitest.uihelper.common import get_state_as_dict, type_text +from uitest.uihelper.calc import enter_text_to_cell + +import org.libreoffice.unotest +import pathlib +import time + +def get_url_for_data_file(file_name): + return pathlib.Path(org.libreoffice.unotest.makeCopyFromTDOC(file_name)).as_uri() + +class ManualCalcTests(UITestCase): + + # http://manual-test.libreoffice.org/manage/case/189/ + def test_define_database_range(self): + + self.ui_test.create_doc_in_start_center("calc") + + # Select range A1:D10 + xGridWin = self.xUITest.getTopFocusWindow().getChild("grid_window") + xGridWin.executeAction("SELECT", mkPropertyValues({"RANGE": "A1:D10"})) + + # Execute "Define DB Range dialog" + self.ui_test.execute_modeless_dialog_through_command(".uno:DefineDBName") + + xDefineNameDlg = self.xUITest.getTopFocusWindow() + + xEntryBox = xDefineNameDlg.getChild("entry") + type_text(xEntryBox, "my_database") + + xOkBtn = xDefineNameDlg.getChild("ok") + self.ui_test.close_dialog_through_button(xOkBtn) + + # Deselect range + xGridWin.executeAction("SELECT", mkPropertyValues({"CELL": "A1"})) + + # Execute "Select DB Range dialog" + self.ui_test.execute_dialog_through_command(".uno:SelectDB") + xSelectNameDlg = self.xUITest.getTopFocusWindow() + + xListBox = xSelectNameDlg.getChild("treeview") + xListBoxState = get_state_as_dict(xListBox) + self.assertEqual(xListBoxState["SelectionCount"], "1") + self.assertEqual(xListBoxState["SelectEntryText"], "my_database") + + xOkBtn = xSelectNameDlg.getChild("ok") + self.ui_test.close_dialog_through_button(xOkBtn) + + # Assert that the correct range has been selected + gridWinState = get_state_as_dict(xGridWin) + self.assertEqual(gridWinState["MarkedArea"], "Sheet1.A1:Sheet1.D10") + + self.ui_test.close_doc() + + # http://manual-test.libreoffice.org/manage/case/190/ + def test_sort_data(self): + self.ui_test.create_doc_in_start_center("calc") + + # Insert data + xGridWin = self.xUITest.getTopFocusWindow().getChild("grid_window") + enter_text_to_cell(xGridWin, "B1", "3") + enter_text_to_cell(xGridWin, "B2", "25") + enter_text_to_cell(xGridWin, "B3", "17") + enter_text_to_cell(xGridWin, "B4", "9") + enter_text_to_cell(xGridWin, "B5", "19") + enter_text_to_cell(xGridWin, "B6", "0") + enter_text_to_cell(xGridWin, "B7", "107") + enter_text_to_cell(xGridWin, "B8", "89") + enter_text_to_cell(xGridWin, "B9", "8") + enter_text_to_cell(xGridWin, "B10", "33") + + xGridWin.executeAction("SELECT", mkPropertyValues({"RANGE": "B1:B10"})) + + # Execute "Sort" dialog + self.ui_test.execute_dialog_through_command(".uno:DataSort") + xSortDlg = self.xUITest.getTopFocusWindow() + + xOkBtn = xSortDlg.getChild("ok") + self.ui_test.close_dialog_through_button(xOkBtn) + + document = self.ui_test.get_component() + + self.assertEqual(get_cell_by_position(document, 0, 1, 0).getValue(), 0) + self.assertEqual(get_cell_by_position(document, 0, 1, 1).getValue(), 3) + self.assertEqual(get_cell_by_position(document, 0, 1, 2).getValue(), 8) + self.assertEqual(get_cell_by_position(document, 0, 1, 3).getValue(), 9) + self.assertEqual(get_cell_by_position(document, 0, 1, 4).getValue(), 17) + self.assertEqual(get_cell_by_position(document, 0, 1, 5).getValue(), 19) + self.assertEqual(get_cell_by_position(document, 0, 1, 6).getValue(), 25) + self.assertEqual(get_cell_by_position(document, 0, 1, 7).getValue(), 33) + self.assertEqual(get_cell_by_position(document, 0, 1, 8).getValue(), 89) + self.assertEqual(get_cell_by_position(document, 0, 1, 9).getValue(), 107) + + time.sleep(2) + self.ui_test.close_doc() + + # http://manual-test.libreoffice.org/manage/case/191/ + def test_validation(self): + self.ui_test.create_doc_in_start_center("calc") + + xGridWin = self.xUITest.getTopFocusWindow().getChild("grid_window") + xGridWin.executeAction("SELECT", mkPropertyValues({"RANGE": "A1:C10"})) + + self.ui_test.execute_dialog_through_command(".uno:Validation") + xValidationDlg = self.xUITest.getTopFocusWindow() + + xAllowList = xValidationDlg.getChild("allow") + xAllowList.executeAction("SELECT", mkPropertyValues({"POS": "1"})) + + xData = xValidationDlg.getChild("data") + xData.executeAction("SELECT", mkPropertyValues({"POS": "5"})) + + xVal = xValidationDlg.getChild("max") + xVal.executeAction("TYPE", mkPropertyValues({"TEXT":"0"})) + + xOkBtn = xValidationDlg.getChild("ok") + self.ui_test.close_dialog_through_button(xOkBtn) + + def enter_text(cell, text): + enter_text_to_cell(xGridWin, cell, text) + + self.ui_test.execute_blocking_action(enter_text, "ok", args=("A1", "abc")) + self.ui_test.execute_blocking_action(enter_text, "ok", args=("B6", "2.18")) + + enter_text_to_cell(xGridWin, "C2", "24") + + self.ui_test.close_doc() + + # http://manual-test.libreoffice.org/manage/case/187/ + def test_transpose(self): + self.ui_test.create_doc_in_start_center("calc") + + xGridWin = self.xUITest.getTopFocusWindow().getChild("grid_window") + enter_text_to_cell(xGridWin, "B3", "abcd") + enter_text_to_cell(xGridWin, "B4", "edfg") + enter_text_to_cell(xGridWin, "C3", "35") + enter_text_to_cell(xGridWin, "C4", "5678") + + xGridWin.executeAction("SELECT", mkPropertyValues({"RANGE": "A1:C10"})) + + self.xUITest.executeCommand(".uno:Cut") + + xGridWin.executeAction("SELECT", mkPropertyValues({"CELL": "A1"})) + + self.ui_test.execute_dialog_through_command(".uno:PasteSpecial") + + xPasteSpecialDlg = self.xUITest.getTopFocusWindow() + + xAllChkBox = xPasteSpecialDlg.getChild("paste_all") + xAllChkBox.executeAction("CLICK", tuple()) + + xTransposeChkBox = xPasteSpecialDlg.getChild("transpose") + xTransposeChkBox.executeAction("CLICK", tuple()) + + xOkBtn = xPasteSpecialDlg.getChild("ok") + self.ui_test.close_dialog_through_button(xOkBtn) + + document = self.ui_test.get_component() + self.assertEqual(get_cell_by_position(document, 0, 2, 1).getString(), "abcd") + self.assertEqual(get_cell_by_position(document, 0, 2, 2).getValue(), 35) + self.assertEqual(get_cell_by_position(document, 0, 3, 1).getString(), "edfg") + self.assertEqual(get_cell_by_position(document, 0, 3, 2).getValue(), 5678) + + self.ui_test.close_doc() + + # http://manual-test.libreoffice.org/manage/case/151/ + def test_cell_recalc(self): + doc = self.ui_test.load_file(get_url_for_data_file("cell_recalc.ods")) + + xGridWin = self.xUITest.getTopFocusWindow().getChild("grid_window") + xGridWin.executeAction("SELECT", mkPropertyValues({"RANGE": "D2:D9"})) + self.xUITest.executeCommand(".uno:Cut") + + self.assertEqual(get_cell_by_position(doc, 0, 3, 15).getValue(), 0) + + self.xUITest.executeCommand(".uno:Undo") + + for i in range(1, 9): + self.assertTrue(get_cell_by_position(doc, 0, 3, i).getValue() != 0) + + self.assertEqual(get_cell_by_position(doc, 0, 3, 15).getValue(), 195) + + self.ui_test.close_doc() + + # http://manual-test.libreoffice.org/manage/case/143/ + def test_random_numbers(self): + self.ui_test.create_doc_in_start_center("calc") + xGridWin = self.xUITest.getTopFocusWindow().getChild("grid_window") + + xGridWin.executeAction("SELECT", mkPropertyValues({"RANGE": "A2:A10"})) + + self.ui_test.execute_modeless_dialog_through_command(".uno:RandomNumberGeneratorDialog") + xRandomNumberDlg = self.xUITest.getTopFocusWindow() + xDistributionLstBox = xRandomNumberDlg.getChild("distribution-combo") + xDistributionLstBox.executeAction("SELECT", mkPropertyValues({"POS": "1"})) + + xMin = xRandomNumberDlg.getChild("parameter1-spin") + xMin.executeAction("TYPE", mkPropertyValues({"KEYCODE": "CTRL+A"})) + xMin.executeAction("TYPE", mkPropertyValues({"TEXT": "-2"})) + xMax = xRandomNumberDlg.getChild("parameter2-spin") + xMax.executeAction("TYPE", mkPropertyValues({"KEYCODE": "CTRL+A"})) + xMax.executeAction("TYPE", mkPropertyValues({"TEXT": "10"})) + + xApplyBtn = xRandomNumberDlg.getChild("apply") + xApplyBtn.executeAction("CLICK", tuple()) + + doc = self.ui_test.get_component() + + def check_random_values(): + for i in range(1, 9): + val = get_cell_by_position(doc, 0, 0, i).getValue() + self.assertTrue(val <= 10 and val >= -2) + + check_random_values() + + xOkBtn = xRandomNumberDlg.getChild("ok") + self.ui_test.close_dialog_through_button(xOkBtn) + + # we might want to check that clicking 'ok' actually changes the values + check_random_values() + + self.ui_test.close_doc() + +# vim: set shiftwidth=4 softtabstop=4 expandtab: diff --git a/uitest/manual_tests/data/cell_recalc.ods b/uitest/manual_tests/data/cell_recalc.ods Binary files differnew file mode 100644 index 000000000..4b125fd2e --- /dev/null +++ b/uitest/manual_tests/data/cell_recalc.ods diff --git a/uitest/manual_tests/more_calc.py b/uitest/manual_tests/more_calc.py new file mode 100644 index 000000000..08aeb654e --- /dev/null +++ b/uitest/manual_tests/more_calc.py @@ -0,0 +1,52 @@ +# -*- tab-width: 4; indent-tabs-mode: nil; py-indent-offset: 4 -*- +# +# This file is part of the LibreOffice project. +# +# 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.framework import UITestCase + +from libreoffice.calc.document import get_cell_by_position +from libreoffice.uno.propertyvalue import mkPropertyValues + +from uitest.uihelper.calc import enter_text_to_cell + + +class ManualCalcTests(UITestCase): + def test_paste_special(self): + # EN-8:Paste special with options + # This test is to check that paste special combined with some options and link is ok. + # Refers to tdf#84810 + + self.ui_test.create_doc_in_start_center("calc") + + # Write text to cell A1 + xGridWin = self.xUITest.getTopFocusWindow().getChild("grid_window") + enter_text_to_cell(xGridWin, "A1", "abcd") + + # Copy cell A1 to clipboard + xGridWin.executeAction("SELECT", mkPropertyValues({"CELL": "A1"})) + self.xUITest.executeCommand(".uno:Copy") + + # Set cursor to cell A3 + xGridWin.executeAction("SELECT", mkPropertyValues({"CELL": "A3"})) + + # Choose Paste Special Options and paste data + self.ui_test.execute_dialog_through_command(".uno:PasteSpecial") + xPasteSpecialDlg = self.xUITest.getTopFocusWindow() + xAllChkBox = xPasteSpecialDlg.getChild("paste_all") + xAllChkBox.executeAction("CLICK", tuple()) + xLinkChkBox = xPasteSpecialDlg.getChild("link") + xLinkChkBox.executeAction("CLICK", tuple()) + xOkBtn = xPasteSpecialDlg.getChild("ok") + self.ui_test.close_dialog_through_button(xOkBtn) + + # Assert successful paste + document = self.ui_test.get_component() + self.assertEqual(get_cell_by_position(document, 0, 0, 2).getString(), "abcd") + self.ui_test.close_doc() + +# vim: set shiftwidth=4 softtabstop=4 expandtab: diff --git a/uitest/math_tests/start.py b/uitest/math_tests/start.py new file mode 100644 index 000000000..425cb9679 --- /dev/null +++ b/uitest/math_tests/start.py @@ -0,0 +1,92 @@ +# -*- 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 + +from libreoffice.uno.propertyvalue import mkPropertyValues + +from uitest.framework import UITestCase +from uitest.uihelper.common import type_text, select_pos +from uitest.debug import sleep + +import unittest + +class SimpleMathTest(UITestCase): + + def test_start_math(self): + + self.ui_test.create_doc_in_start_center("math") + + xMathDoc = self.xUITest.getTopFocusWindow() + + self.ui_test.close_doc() + + def test_docking_window_listbox(self): + + self.ui_test.create_doc_in_start_center("math") + + xMathDoc = self.xUITest.getTopFocusWindow() + + xList = xMathDoc.getChild("listbox") + state = get_state_as_dict(xList) + self.assertEqual(state["SelectEntryText"], "Unary/Binary Operators") + select_pos(xList, "1") + state = get_state_as_dict(xList) + self.assertEqual(state["SelectEntryText"], "Relations") + + self.ui_test.close_doc() + + def test_math_edit(self): + self.ui_test.create_doc_in_start_center("math") + + xMathDoc = self.xUITest.getTopFocusWindow() + + xMathEdit = xMathDoc.getChild("math_edit") + + type_text(xMathEdit, "E=mc^2") + + self.ui_test.close_doc() + + def test_math_selector(self): + self.ui_test.create_doc_in_start_center("math") + + xMathDoc = self.xUITest.getTopFocusWindow() + + xMathSelector = xMathDoc.getChild("element_selector") + + xElement = xMathSelector.getChild("1") + xElement.executeAction("SELECT", tuple()) + + self.ui_test.close_doc() + + @unittest.skip("on windows the f4 does not always work") + def test_complete_math(self): + self.ui_test.create_doc_in_start_center("math") + + xMathDoc = self.xUITest.getTopFocusWindow() + + xList = xMathDoc.getChild("listbox") + state = get_state_as_dict(xList) + self.assertEqual(state["SelectEntryText"], "Unary/Binary Operators") + select_pos(xList, "1") + + xMathSelector = xMathDoc.getChild("element_selector") + + xElement = xMathSelector.getChild("1") + xElement.executeAction("SELECT", tuple()) + + xMathEdit = xMathDoc.getChild("math_edit") + type_text(xMathEdit, "1") + xMathEdit.executeAction("TYPE", mkPropertyValues({"KEYCODE":"F4"})) + type_text(xMathEdit, "2") + + edit_state = get_state_as_dict(xMathEdit) + self.assertEqual("1 <> 2 ", edit_state["Text"]) + + self.ui_test.close_doc() + +# vim: set shiftwidth=4 softtabstop=4 expandtab: diff --git a/uitest/packaging/Makefile b/uitest/packaging/Makefile new file mode 100644 index 000000000..af63c946e --- /dev/null +++ b/uitest/packaging/Makefile @@ -0,0 +1,16 @@ +all: + @echo "Packaging the libreoffice-connection code" + @mkdir -p libreoffice + @cp ../libreoffice/connection.py libreoffice/. + @touch libreoffice/__init__.py + @python3 setup.py sdist + +clean: + rm -r dist/ + rm -r libreoffice_connection.egg-info/ + rm -r libreoffice/ + rm -r build/ + +publish: + @echo "Uploading the release to pypi" + twine upload dist/* diff --git a/uitest/packaging/README.rst b/uitest/packaging/README.rst new file mode 100644 index 000000000..45d8716f6 --- /dev/null +++ b/uitest/packaging/README.rst @@ -0,0 +1,4 @@ +Connection code for LibreOffice's pyUNO +======================================= + +This code allows out-of-process communication with a LibreOffice instance. The instance can either be started by the script or a connection to a running LibreOffice instance. The code contains several safety checks for hanging and crashed LibreOffice instances. diff --git a/uitest/packaging/setup.cfg b/uitest/packaging/setup.cfg new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/uitest/packaging/setup.cfg diff --git a/uitest/packaging/setup.py b/uitest/packaging/setup.py new file mode 100644 index 000000000..9aa32054c --- /dev/null +++ b/uitest/packaging/setup.py @@ -0,0 +1,34 @@ +from setuptools import setup, find_packages +from codecs import open +from os import path + +here = path.abspath(path.dirname(__file__)) + +# Get the long description from the README file +with open(path.join(here, 'README.rst'), encoding='utf-8') as f: + long_description = f.read() + +setup( + name="libreoffice-connection", + version="0.0.1", + description="Connection code for LibreOffice's pyUNO", + long_description=long_description, + url="http://www.libreoffice.org", + author="The LibreOffice developers", + author_email="libreoffice@lists.freedesktop.org", + license="MPL2", + classifiers=[ + "Development Status :: 3 - Alpha", + "Intended Audience :: Developers", + "License :: OSI Approved :: Mozilla Public License 2.0 (MPL 2.0)", + "Programming Language :: Python :: 3.2", + "Programming Language :: Python :: 3.3", + "Programming Language :: Python :: 3.4", + "Programming Language :: Python :: 3.5", + "Programming Language :: Python :: 3.6", + "Topic :: Office/Business :: Office Suites", + "Topic :: Software Development :: Libraries", + ], + keywords="office automation", + packages=find_packages(), +) diff --git a/uitest/test_main.py b/uitest/test_main.py new file mode 100644 index 000000000..e1737947f --- /dev/null +++ b/uitest/test_main.py @@ -0,0 +1,137 @@ +# -*- 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 sys +import getopt +import os +import unittest +import calc_tests +import importlib +import importlib.machinery + +import uitest.config + +from uitest.framework import UITestCase + +from libreoffice.connection import OfficeConnection + +test_name_limit_found = False + +def parseArgs(argv): + (optlist,args) = getopt.getopt(argv[1:], "hdr", + ["help", "debug", "soffice=", "userdir=", "dir=", "file=", "gdb"]) + return (dict(optlist), args) + +def usage(): + message = """usage: {program} [option]... [task_file]..." + -h | --help: print usage information + {connection_params} + the 'task_file' parameters should be + full absolute pathnames, not URLs.""" + print(message.format(program = os.path.basename(sys.argv[0]), \ + connection_params = OfficeConnection.getHelpText())) + + +def find_test_files(dir_path): + valid_files = [] + for f in os.listdir(dir_path): + file_path = os.path.join(dir_path, f) + + # don't go through the sub-directories + if not os.path.isfile(file_path): + continue + + if os.path.splitext(file_path)[1] == ".swp": + continue # ignore VIM swap files + + # fail on any non .py files + if not os.path.splitext(file_path)[1] == ".py": + raise Exception("file with an extension which is not .py: " + file_path) + + # ignore the __init__.py file + # it is obviously not a test file + if f == "__init__.py": + continue + + valid_files.append(file_path) + + return valid_files + +def get_classes_of_module(module): + md = module.__dict__ + return [ md[c] for c in md if ( + isinstance(md[c], type) and md[c].__module__ == module.__name__ ) ] + +def get_test_case_classes_of_module(module): + classes = get_classes_of_module(module) + return [ c for c in classes if issubclass(c, UITestCase) ] + +def add_tests_for_file(test_file, test_suite): + test_name_limit = os.environ.get('UITEST_TEST_NAME', '') + test_loader = unittest.TestLoader() + module_name = os.path.splitext(os.path.split(test_file)[1])[0] + + loader = importlib.machinery.SourceFileLoader(module_name, test_file) + mod = loader.load_module() + classes = get_test_case_classes_of_module(mod) + global test_name_limit_found + for c in classes: + test_names = test_loader.getTestCaseNames(c) + for test_name in test_names: + full_name = ".".join([module_name, c.__name__, test_name]) + if len(test_name_limit) > 0: + if test_name_limit != full_name: + continue + test_name_limit_found = True + + obj = c(test_name, opts) + test_suite.addTest(obj) + +def get_test_suite_for_dir(opts): + test_suite = unittest.TestSuite() + + valid_test_files = find_test_files(opts['--dir']) + for test_file in valid_test_files: + add_tests_for_file(test_file, test_suite) + return test_suite + + +if __name__ == '__main__': + (opts,args) = parseArgs(sys.argv) + if "-h" in opts or "--help" in opts: + usage() + sys.exit() + elif not "--soffice" in opts: + usage() + sys.exit(1) + elif "--dir" in opts: + test_suite = get_test_suite_for_dir(opts) + test_name_limit = os.environ.get('UITEST_TEST_NAME', '') + print(test_name_limit_found) + if len(test_name_limit) > 0 and not test_name_limit_found: + print("UITEST_TEST_NAME '%s' does not match any test" % test_name_limit) + sys.exit(1) + elif "--file" in opts: + test_suite = unittest.TestSuite() + add_tests_for_file(opts['--file'], test_suite) + else: + usage() + sys.exit() + + if "-d" in opts or "--debug" in opts: + uitest.config.use_sleep = True + + result = unittest.TextTestRunner(stream=sys.stdout, verbosity=2).run(test_suite) + print("Tests run: %d" % result.testsRun) + print("Tests failed: %d" % len(result.failures)) + print("Tests errors: %d" % len(result.errors)) + print("Tests skipped: %d" % len(result.skipped)) + if not result.wasSuccessful(): + sys.exit(1) + sys.exit(0) + +# vim: set shiftwidth=4 softtabstop=4 expandtab: diff --git a/uitest/ui_logger_dsl/General_commands.tx b/uitest/ui_logger_dsl/General_commands.tx new file mode 100644 index 000000000..5f5c40440 --- /dev/null +++ b/uitest/ui_logger_dsl/General_commands.tx @@ -0,0 +1,29 @@ +/* + This file for the log statements that is general for all application + we can use it as general commands then relate it to its application + as we have in the starter command + //==================================== + also I make set zoom to be general as it will be better +*/ + +import type_options + +GeneralCommand: + SideBar | setZoom_command | Select_command | General_type_command_on_UI_Object +; +SideBar: + 'From SIDEBAR ' 'Choose ' '{"PANEL":' name=STRING '}' +; +setZoom_command: + 'Set Zoom to ' zoom_value=INT +; +Select_command: + 'Select ' '{"OBJECT":' name=STRING '}' +; + +//================================================== +//This Part if you want to type text in any of these UI elements This will be handled with this Grammar + +General_type_command_on_UI_Object: + 'Type on' UI_Obj=STRING what_to_type=Type_options 'from' parent_id=ID +;
\ No newline at end of file diff --git a/uitest/ui_logger_dsl/Special_commands.tx b/uitest/ui_logger_dsl/Special_commands.tx new file mode 100644 index 000000000..071cfb9dc --- /dev/null +++ b/uitest/ui_logger_dsl/Special_commands.tx @@ -0,0 +1,209 @@ +import type_options + +/* + This file for the log statements that relates to each different applications + Each Grammar Command here is related to his own application +*/ + +SpecialCommand: + writer_command | calc_command | impress_command | math_command | draw_command +; + +/* + This part for all the writer log statements: + + 1) Type + 2) Select + 3) GOTO page + 4) Create Table + 5) Copy Text + 6) Cut Text + 7) Paste Text + 8) Insert Break Page + + then we can add whatever we need in the future +*/ +writer_command: + writer_Type_command | writer_Select_command | writer_GOTO_command | + writer_Create_table | writer_Copy_Text | writer_Cut_Text | + writer_Paste_Text | writer_Insert_BreakPage +; +writer_Type_command: + 'Type on writer' what_to_type=Type_options +; +writer_Select_command: + 'Select from Pos' from_pos=INT 'to Pos' to_pos=INT +; +writer_GOTO_command: + 'GOTO page number' page_num=INT +; +writer_Create_table: + 'Create Table with Columns :' cols=INT ', Rows :' rows=INT +; +writer_Copy_Text: + 'Copy the Selected Text' +; +writer_Cut_Text: + 'Cut the Selected Text' +; +writer_Paste_Text: + 'Paste in the Current Cursor Location' +; +writer_Insert_BreakPage: + 'Insert Break Page' +; + +//=================================================================// +/* + This part for all the calc log statements: + + 1) select sheet + 2) Select cell or range + 3) launch AutoFill + 4) Delete Cells + 5) Remove Content of a cell + 6) Insert new Cells + 7) Cut Cells + 8) Copy Cells + 9) Paste Cells + 10) Merge Cells + 11) Unmerge Cells + + then we can add whatever we need in the future +*/ +calc_command: + calc_Type_command | calc_switch_sheet | calc_Select_cell | calc_AutoFill_filter | + calc_Delete_Cells | calc_Remove_Content | calc_insert_cells | calc_Cut_Cells | + calc_Copy_Cells | calc_Paste_Cells | calc_UNMerge_Cells | calc_Merge_Cells | + calc_Rename_Sheet | calc_Insert_sheet +; +calc_Type_command: + 'Type on current cell' what_to_type=Type_options +; +calc_switch_sheet: + 'Switch to sheet number' sheet_num=INT +; +calc_Select_cell: + 'Select from calc' select_op=select_options +; +calc_AutoFill_filter: + 'Launch AutoFilter from Col' col_num=INT 'and Row' row_num=INT +; +range_of_cells: + '{' '"RANGE":' input_range=STRING '}' +; +one_cell: + '{' '"CELL":' input_cell=STRING '}' +; +calc_Delete_Cells: + 'Delete The Cells in' '{' '"RANGE":' input_range=STRING '}' +; +calc_Remove_Content: + 'Remove Content from This' '{' '"RANGE":' input_range=STRING '}' +; +calc_insert_cells: + 'Insert Cell around the ' '{' '"RANGE":' input_range=STRING '}' +; +calc_Cut_Cells: + 'CUT the selected ' '{' '"RANGE":' input_range=STRING '}' +; +calc_Copy_Cells: + 'COPY the selected ' '{' '"RANGE":' input_range=STRING '}' +; +calc_Paste_Cells: + 'Paste in the' '{' '"RANGE":' input_range=STRING '}' +; +calc_Merge_Cells: + 'Merge' '{' '"RANGE":' input_range=STRING '}' +; +calc_UNMerge_Cells: + 'Delete the merge between' '{' '"CELL":' input_range=STRING '}' +; +calc_Rename_Sheet: + 'Rename The Selected Tab to ' new_name=STRING +; +calc_Insert_sheet: + 'Insert New Tab ' +; +//this is the select options +select_options: + one_cell | range_of_cells +; + +//=================================================================// +/* + This part for all the impress log statements: + + 1) Type + 2) Insert New Slide + 3) Delete Slide + 4) Duplicate Slide + 5) Rename Slide + + then we can add whatever we need in the future +*/ +impress_command: + impress_Type_command | impress_Insert_Slide | impress_Delete_Page | + impress_Duplicate_Slide | impress_Rename_Slide +; +impress_Type_command: + 'Type on impress ' what_to_type=Type_options +; +impress_Insert_Slide: + 'Insert New Slide at Position ' position_num=INT +; +impress_Delete_Page: + 'Delete Slide number ' position_num=INT +; +impress_Duplicate_Slide: + 'Duplicate The Selected Slide ' +; +impress_Rename_Slide: + 'Rename The Selected Slide from ' old_name=STRING 'to' new_name=STRING +; +//=================================================================// +/* + This part for all the math log statements: + + 1) element selector + 2) Type + + then we can add whatever we need in the future +*/ +math_command: + math_element_selector | math_Type_command +; +math_element_selector: + 'Select element no ' element_no=INT 'From' place=ID +; +math_Type_command: + 'Type on math ' what_to_type=Type_options +; + +//=================================================================// +/* + This part for all the draw log statements: + + 1) Type + 2) Insert New Page + 3) Delete Page + 4) Rename Page + + then we can add whatever we need in the future +*/ +draw_command: + draw_Type_command | draw_Insert_Page | draw_Delete_Page | + draw_Rename_Page +; +draw_Type_command: + 'Type on draw ' what_to_type=Type_options +; +draw_Insert_Page: + 'Insert New Page at Position ' position_num=INT +; +draw_Delete_Page: + 'Delete Page number ' position_num=INT +; +draw_Rename_Page: + 'Rename The Selected Page from ' old_name=STRING 'to' new_name=STRING +;
\ No newline at end of file diff --git a/uitest/ui_logger_dsl/UI_Object_commands.tx b/uitest/ui_logger_dsl/UI_Object_commands.tx new file mode 100644 index 000000000..0f766d87a --- /dev/null +++ b/uitest/ui_logger_dsl/UI_Object_commands.tx @@ -0,0 +1,65 @@ +import type_options + +/* + this file is for The Grammar of: + 1) ButtonUIObject : ( Click event ) + 2) EditUIObject : ( Type event - Clear event - Select Text event ) + 3) CheckBoxUIObject : ( Toggle the value ) + 4) RadioButtonUIObject : ( Select event ) + 5) ListBoxUIObject : ( Select event ) + 6) ComboBoxUIObject ( Select event ) + 7) SpinUIObject ( Increase event - Decrease event ) + 8) TabControlUIObject ( Change tab event ) +*/ + +UIObjectCommand: + ButtonUIObject | CheckBoxUIObject | EditUIObject | + RadioButtonUIObject | ListBoxUIObject | ComboBoxUIObject | + SpinFieldUIObject | TabControlUIObject +; + +ButtonUIObject: + 'Click on' ui_button=STRING ('from' parent_id=ID)? +; +CheckBoxUIObject: + 'Toggle' Check_box_id=STRING 'CheckBox' ('from' parent_id=ID)? +; +RadioButtonUIObject: + 'Select' Radio_button_id=STRING 'RadioButton' ('from' parent_id=ID)? +; +ComboBoxUIObject: + 'Select in' Combo_box_id=STRING 'ComboBox' 'item number' item_num=INT ('from' parent_id=ID)? +; +TabControlUIObject: + 'Choose Tab number' tab_page_number=INT 'in' tab_id=STRING ('from' parent_id=ID)? +; +EditUIObject: + action=action_on_UIObject ('from' parent_id=ID)? +; +SpinFieldUIObject: + change=increase_or_ecrease Spin_id=STRING ('from' parent_id=ID)? +; +ListBoxUIObject: + 'Select element with position ' POS=INT 'in' list_id=STRING ('from' parent_id=ID)? +; +//============================================================= +//helper grammar for EditUIObject +action_on_UIObject: + Type_action | SELECT | Clear +; +Type_action: + 'Type on' edit_button=STRING what_to_type=Type_options +; +SELECT: + 'Select in ' edit_button=STRING + '{"FROM": "' from_pos=INT '" , "TO" : "'to_pos=INT '"}' +; +Clear: + 'Clear' edit_button=STRING +; + +//============================================================= +//helper functions for SpinUIObject +increase_or_ecrease: + 'Increase' | 'Decrease' +; diff --git a/uitest/ui_logger_dsl/dialog_commands.tx b/uitest/ui_logger_dsl/dialog_commands.tx new file mode 100644 index 000000000..b1837f7ef --- /dev/null +++ b/uitest/ui_logger_dsl/dialog_commands.tx @@ -0,0 +1,24 @@ +/* + this file for the Dialog commands + It handle all types of Dialog the Modeless and the Modal + Also It handle the Close Dialog Commands +*/ +DialogCommand: + OpenDialog | CloseDialog +; + +OpenDialog: + OpenModalDialog | OpenModelessDialog +; +OpenModalDialog : + 'Open Modal ' dialog_name=ID +; +OpenModelessDialog : + 'Open Modeless ' dialog_name=ID +; + +CloseDialog: + //the additional_note=STRING? if you need to add name in the future + //Also it's used to make instance of the command of type CloseDialog + 'Close Dialog' additional_note=STRING? +; diff --git a/uitest/ui_logger_dsl/dsl_core.py b/uitest/ui_logger_dsl/dsl_core.py new file mode 100644 index 000000000..7390ec03f --- /dev/null +++ b/uitest/ui_logger_dsl/dsl_core.py @@ -0,0 +1,862 @@ +#!/usr/bin/env python3 +# This file is part of the LibreOffice UI_logger project. +# +# This file contain the implementation of the Compiler +# for the new logger grammar +# +# ul stands for Ui_Logger + +import os +import sys +import argparse +import keyword + +try: + from textx.metamodel import metamodel_from_file +except ImportError: + print("textx is a required package.") + print('Please install the package for example with "pip3 install --user textx"') + sys.exit(1) + +tab = " " +double_tab = " " + + +def parse_args(): + """ + This function parses the command-line arguments + to get the input and output file details + """ + parser = argparse.ArgumentParser(description="Generate a UI test file from log") + parser.add_argument("input_address", type=str, help="The log file address") + parser.add_argument("output_address", type=str, help="The test file address") + args = parser.parse_args() + return args + + +class ul_Compiler: + prev_command = "" + variables = [] + objects = dict() + current_app = "" + parent_hierarchy_count = 0 + last_parent = [] + flag_for_QuerySaveDialog = False + math_element_selector_initializer= False; + + def __init__(self, input_address, output_address): + self.ui_dsl_mm = metamodel_from_file("ui_logger_dsl_grammar.tx") + self.output_stream = self.initiate_test_generation(output_address) + self.input_address = input_address + + def get_log_file(self, input_address): + try: + # load the program + content = self.ui_dsl_mm.model_from_file(input_address) + except IOError as err: + print("IO error: {0}".format(err)) + print( + "Use " + os.path.basename(sys.argv[0]) + " -h to get usage instructions" + ) + sys.exit(1) + + return content + + def initiate_test_generation(self, output_address): + self.last_parent.append("MainWindow") + try: + f = open(output_address, "w") + except IOError as err: + print("IO error: {0}".format(err)) + print( + "Use " + os.path.basename(sys.argv[0]) + " -h to get usage instructions" + ) + sys.exit(1) + line = ( + "# -*- tab-width: 4; indent-tabs-mode: nil; py-indent-offset: 4 -*-\n\n" + + "from uitest.framework import UITestCase\n" + + "from libreoffice.uno.propertyvalue import mkPropertyValues\n" + + "import importlib\n\n" + + "class TestClass(UITestCase):\n" + + tab + + "def test_function(self):\n" + ) + + self.variables.append(line) + + return f + + def compile(self): + self.ui_dsl_mm.register_obj_processors( + { + "UNOCommand": self.handle_uno, + "StarterCommand": self.handle_start, + "CloseDialog": self.handle_Dialog, + "OpenModelessDialog": self.handle_Dialog, + "OpenModalDialog": self.handle_Dialog, + "ButtonUIObject": self.handle_button, + "CheckBoxUIObject": self.handle_check_box, + "TabControlUIObject": self.handle_tab, + "ComboBoxUIObject": self.handle_Combo_box, + "RadioButtonUIObject": self.handle_Radio_button, + "ListBoxUIObject": self.handle_List_box, + "SpinFieldUIObject": self.handle_spin_field, + "EditUIObject": self.handle_Edit_uiObject, + "writer_Type_command": self.handle_writer_type, + "writer_Select_command": self.handle_writer_select, + "writer_GOTO_command": self.handle_writer_goto, + "calc_Select_cell": self.handle_calc_select, + "calc_switch_sheet": self.handle_calc_switch_sheet, + "calc_Type_command": self.handle_calc_Type_command, + "calc_AutoFill_filter": self.handle_calc_AutoFill_filter, + "impress_Type_command": self.handle_impress_Type_command, + "math_element_selector": self.handle_math_element_selector, + "math_Type_command": self.handle_math_Type_command, + "setZoom_command": self.handle_setZoom_command, + "draw_Type_command": self.handle_draw_Type_command, + "SideBar": self.handle_SideBar, + "writer_Copy_Text": self.do_nothing, + "writer_Cut_Text": self.do_nothing, + "writer_Paste_Text": self.do_nothing, + "writer_Insert_BreakPage": self.do_nothing, + "writer_Create_table": self.do_nothing, + "calc_Remove_Content": self.do_nothing, + "calc_Delete_Cells": self.do_nothing, + "calc_insert_cells": self.do_nothing, + "calc_Cut_Cells": self.do_nothing, + "calc_Copy_Cells": self.do_nothing, + "calc_Merge_Cells": self.do_nothing, + "calc_UNMerge_Cells": self.do_nothing, + "calc_Rename_Sheet": self.do_nothing, + "calc_Insert_sheet": self.do_nothing, + "impress_Insert_Slide": self.do_nothing, + "impress_Delete_Page": self.do_nothing, + "impress_Duplicate_Slide": self.do_nothing, + "impress_Rename_Slide": self.do_nothing, + "draw_Insert_Page": self.do_nothing, + "draw_Delete_Page": self.do_nothing, + "draw_Rename_Page": self.do_nothing, + } + ) + + self.log_lines = self.get_log_file(self.input_address) + + def init_app(self): + if self.current_app in self.objects: + self.objects[self.current_app] += 1 + else: + self.objects[self.current_app] = 1 + line = ( + double_tab + + self.current_app + + ' = MainWindow.getChild("' + + self.current_app + + '")\n' + ) + self.variables.append(line) + + def init_Object(self, Id_of_Object, name_of_child, Obj_parent): + + if Id_of_Object in self.objects: + self.objects[Id_of_Object] += 1 + else: + self.objects[Id_of_Object] = 1 + line = ( + double_tab + + Id_of_Object + + " = " + + Obj_parent + + '.getChild("' + + name_of_child + + '")\n' + ) + + self.variables.append(line) + + def write_line_without_parameters(self, Action_holder, Action, Action_type): + line = ( + double_tab + + Action_holder + + '.executeAction("' + + Action + + '",' + + Action_type + + "())\n" + ) + self.variables.append(line) + + def write_line_with_one_parameters( + self, Action_holder, Action, Paramerter_name, parameter_value + ): + line = ( + double_tab + + Action_holder + + '.executeAction("' + + Action + + '", mkPropertyValues({"' + + Paramerter_name + + '": "' + + str(parameter_value) + + '"}))\n' + ) + self.variables.append(line) + + def write_line_with_two_parameters( + self, + Action_holder, + Action, + Paramerter_name_1, + parameter_value_1, + Paramerter_name_2, + parameter_value_2, + ): + + line = ( + double_tab + + Action_holder + + '.executeAction("' + + Action + + '", mkPropertyValues({"' + + Paramerter_name_1 + + '": "' + + str(parameter_value_1) + + '", "' + + Paramerter_name_2 + + '": "' + + str(parameter_value_2) + + '"}))\n' + ) + self.variables.append(line) + + def handle_uno(self, UNOCommand): + if UNOCommand.parameters == None: + line = ( + double_tab + + 'self.xUITest.executeCommand("' + + UNOCommand.uno_command_name + + '")\n' + ) + else: + parameters = "" + for p in UNOCommand.parameters.parameter_data: + parameters = parameters + '"' + p.key + '" : ' + str(p.value) + " ," + parameters = parameters[:-1] + + line = ( + double_tab + + 'self.xUITest.executeCommandWithParameters("' + + UNOCommand.uno_command_name + + '", mkPropertyValues({' + + parameters + + "}) )\n" + ) + + self.variables.append(line) + self.prev_command = UNOCommand + + def handle_start(self, StarterCommand): + line = ( + double_tab + + 'MainDoc = self.ui_test.create_doc_in_start_center("' + + StarterCommand.program_name + + '")\n' + ) + self.variables.append(line) + + line = double_tab + "MainWindow = self.xUITest.getTopFocusWindow()\n" + self.variables.append(line) + app = { + "writer": "writer_edit", + "calc": "grid_window", + "impress": "impress_win", + "math": "math_edit", + "draw": "draw_win", + } + self.current_app = app[StarterCommand.program_name] + self.prev_command = StarterCommand + + def handle_SideBar(self, SideBar): + + line = ' self.xUITest.executeCommand(".uno:Sidebar")\n' + self.variables.append(line) + + self.write_line_with_one_parameters( + "MainWindow", "SIDEBAR", "PANEL", SideBar.name + ) + + self.prev_command = SideBar + + def handle_Dialog(self, DialogCommand): + + if DialogCommand.__class__.__name__ == "OpenModalDialog": + + if DialogCommand.dialog_name != "QuerySaveDialog": + # This part is just to ignore saving the Save dialog while closing the app + + old_line = self.variables.pop() + if self.prev_command.__class__.__name__ == "UNOCommand": + key_word = self.prev_command.uno_command_name[-6:] + else: + key_word = old_line[-9:-3] + + if key_word == "Dialog": + old_line = ( + double_tab + + 'self.ui_test.execute_dialog_through_command("' + + self.prev_command.uno_command_name + + '")\n' + ) + self.variables.append(old_line) + line = ( + double_tab + + DialogCommand.dialog_name + + " = self.xUITest.getTopFocusWindow()\n" + ) + self.variables.append(line) + self.last_parent.append(DialogCommand.dialog_name) + self.parent_hierarchy_count = self.parent_hierarchy_count + 1 + + else: + self.flag_for_QuerySaveDialog = True + + elif DialogCommand.__class__.__name__ == "OpenModelessDialog": + old_line = self.variables.pop() + if self.prev_command.__class__.__name__ == "UNOCommand": + key_word = self.prev_command.uno_command_name[-6:] + else: + key_word = old_line[-9:-3] + + if key_word == "Dialog": + old_line = ( + double_tab + + 'self.ui_test.execute_modeless_dialog_through_command("' + + self.prev_command.uno_command_name + + '")\n' + ) + self.variables.append(old_line) + line = ( + double_tab + + DialogCommand.dialog_name + + " = self.xUITest.getTopFocusWindow()\n" + ) + self.variables.append(line) + self.last_parent.append(DialogCommand.dialog_name) + self.parent_hierarchy_count = self.parent_hierarchy_count + 1 + + elif DialogCommand.__class__.__name__ == "CloseDialog": + + if not (self.flag_for_QuerySaveDialog): + # This part is just to ignore saving the Save dialog while closing the app + + if self.prev_command.__class__.__name__ == "ButtonUIObject": + old_line = self.variables.pop() + line = "" + if keyword.iskeyword(self.prev_command.ui_button): + line = ( + double_tab + + "self.ui_test.close_dialog_through_button(x" + + self.prev_command.ui_button + + ")\n" + ) + else: + line = ( + double_tab + + "self.ui_test.close_dialog_through_button(" + + self.prev_command.ui_button + + ")\n" + ) + self.variables.append(line) + self.last_parent.pop() + self.parent_hierarchy_count = self.parent_hierarchy_count - 1 + else: + self.flag_for_QuerySaveDialog = False + + # This is to solve the problem of re-using the same id again in different Dialogs + + self.objects.clear() + + self.prev_command = DialogCommand + + def handle_button(self, ButtonUIObject): + + if ButtonUIObject.parent_id != "QuerySaveDialog": + # This part is just to ignore saving the Save dialog while closing the app + + name_of_obj = "" + if keyword.iskeyword(ButtonUIObject.ui_button): + name_of_obj = "x" + ButtonUIObject.ui_button + else: + name_of_obj = ButtonUIObject.ui_button + + if ButtonUIObject.parent_id == "": + self.init_Object( + name_of_obj, + ButtonUIObject.ui_button, + self.last_parent[self.parent_hierarchy_count], + ) + else: + self.init_Object( + name_of_obj, ButtonUIObject.ui_button, ButtonUIObject.parent_id + ) + + self.write_line_without_parameters(name_of_obj, "CLICK", "tuple") + + self.prev_command = ButtonUIObject + + def handle_check_box(self, CheckBoxUIObject): + + name_of_obj = "" + if keyword.iskeyword(CheckBoxUIObject.Check_box_id): + name_of_obj = "x" + CheckBoxUIObject.Check_box_id + else: + name_of_obj = CheckBoxUIObject.Check_box_id + + if CheckBoxUIObject.parent_id == "": + self.init_Object( + name_of_obj, + CheckBoxUIObject.Check_box_id, + self.last_parent[self.parent_hierarchy_count], + ) + else: + self.init_Object( + name_of_obj, CheckBoxUIObject.Check_box_id, CheckBoxUIObject.parent_id + ) + + self.write_line_without_parameters(name_of_obj, "CLICK", "tuple") + + self.prev_command = CheckBoxUIObject + + def handle_tab(self, TabControlUIObject): + + name_of_obj = "" + if keyword.iskeyword(TabControlUIObject.tab_id): + name_of_obj = "x" + TabControlUIObject.tab_id + else: + name_of_obj = TabControlUIObject.tab_id + + if TabControlUIObject.parent_id == "": + self.init_Object( + name_of_obj, + TabControlUIObject.tab_id, + self.last_parent[self.parent_hierarchy_count], + ) + else: + self.init_Object( + name_of_obj, TabControlUIObject.tab_id, TabControlUIObject.parent_id + ) + + self.write_line_with_one_parameters( + name_of_obj, "SELECT", "POS", TabControlUIObject.tab_page_number + ) + + self.prev_command = TabControlUIObject + + def handle_Combo_box(self, ComboBoxUIObject): + + name_of_obj = "" + if keyword.iskeyword(ComboBoxUIObject.Combo_box_id): + name_of_obj = "x" + ComboBoxUIObject.Combo_box_id + else: + name_of_obj = ComboBoxUIObject.Combo_box_id + + if ComboBoxUIObject.parent_id == "": + self.init_Object( + name_of_obj, + ComboBoxUIObject.Combo_box_id, + self.last_parent[self.parent_hierarchy_count], + ) + else: + self.init_Object( + name_of_obj, ComboBoxUIObject.Combo_box_id, ComboBoxUIObject.parent_id + ) + + self.write_line_with_one_parameters( + name_of_obj, "SELECT", "POS", ComboBoxUIObject.item_num + ) + + self.prev_command = ComboBoxUIObject + + def handle_Radio_button(self, RadioButtonUIObject): + + name_of_obj = "" + if keyword.iskeyword(RadioButtonUIObject.Radio_button_id): + name_of_obj = "x" + RadioButtonUIObject.Radio_button_id + else: + name_of_obj = RadioButtonUIObject.Radio_button_id + + if RadioButtonUIObject.parent_id == "": + self.init_Object( + name_of_obj, + RadioButtonUIObject.Radio_button_id, + self.last_parent[self.parent_hierarchy_count], + ) + else: + self.init_Object( + name_of_obj, + RadioButtonUIObject.Radio_button_id, + RadioButtonUIObject.parent_id, + ) + + self.write_line_without_parameters(name_of_obj, "CLICK", "tuple") + + self.prev_command = RadioButtonUIObject + + def handle_List_box(self, ListBoxUIObject): + + name_of_obj = "" + if keyword.iskeyword(ListBoxUIObject.list_id): + name_of_obj = "x" + ListBoxUIObject.list_id + else: + name_of_obj = ListBoxUIObject.list_id + + if ListBoxUIObject.parent_id == "": + self.init_Object( + name_of_obj, + ListBoxUIObject.list_id, + self.last_parent[self.parent_hierarchy_count], + ) + else: + self.init_Object( + name_of_obj, ListBoxUIObject.list_id, ListBoxUIObject.parent_id + ) + + self.write_line_with_one_parameters( + name_of_obj, "SELECT", "POS", ListBoxUIObject.POS + ) + + self.prev_command = ListBoxUIObject + + def handle_spin_field(self, SpinFieldUIObject): + + name_of_obj = "" + if keyword.iskeyword(SpinFieldUIObject.Spin_id): + name_of_obj = "x" + SpinFieldUIObject.Spin_id + else: + name_of_obj = SpinFieldUIObject.Spin_id + + if SpinFieldUIObject.parent_id == "": + self.init_Object( + name_of_obj, + SpinFieldUIObject.Spin_id, + self.last_parent[self.parent_hierarchy_count], + ) + else: + self.init_Object( + name_of_obj, SpinFieldUIObject.Spin_id, SpinFieldUIObject.parent_id + ) + + if SpinFieldUIObject.change == "Increase": + self.write_line_without_parameters(name_of_obj, "UP", "tuple") + elif SpinFieldUIObject.change == "Decrease": + self.write_line_without_parameters(name_of_obj, "DOWN", "tuple") + self.prev_command = SpinFieldUIObject + + def handle_Edit_uiObject(self, EditUIObject): + + name_of_obj = "" + if keyword.iskeyword(EditUIObject.action.edit_button): + name_of_obj = "x" + EditUIObject.action.edit_button + else: + name_of_obj = EditUIObject.action.edit_button + + if EditUIObject.parent_id == "": + self.init_Object( + name_of_obj, + EditUIObject.action.edit_button, + self.last_parent[self.parent_hierarchy_count], + ) + else: + self.init_Object( + name_of_obj, EditUIObject.action.edit_button, EditUIObject.parent_id + ) + + if EditUIObject.action.__class__.__name__ == "Type_action": + + if EditUIObject.action.what_to_type.__class__.__name__ == "char": + self.write_line_with_one_parameters( + name_of_obj, + "TYPE", + "TEXT", + EditUIObject.action.what_to_type.input_char, + ) + + elif EditUIObject.action.what_to_type.__class__.__name__ == "KeyCode": + self.write_line_with_one_parameters( + name_of_obj, + "TYPE", + "KEYCODE", + EditUIObject.action.what_to_type.input_key_code, + ) + + if EditUIObject.action.__class__.__name__ == "SELECT": + + self.write_line_with_two_parameters( + name_of_obj, + "SELECT", + "FROM", + EditUIObject.action.from_pos, + "TO", + EditUIObject.action.to_pos, + ) + + if EditUIObject.action.__class__.__name__ == "Clear": + + self.write_line_without_parameters(name_of_obj, "CLEAR", "tuple") + + self.prev_command = EditUIObject + + def handle_writer_type(self, writer_Type_command): + + self.init_app() + + if writer_Type_command.what_to_type.__class__.__name__ == "char": + self.write_line_with_one_parameters( + self.current_app, + "TYPE", + "TEXT", + writer_Type_command.what_to_type.input_char, + ) + + elif writer_Type_command.what_to_type.__class__.__name__ == "KeyCode": + self.write_line_with_one_parameters( + self.current_app, + "TYPE", + "KEYCODE", + writer_Type_command.what_to_type.input_key_code, + ) + + self.prev_command = writer_Type_command + + def handle_writer_select(self, writer_Select_command): + + self.init_app() + + self.write_line_with_two_parameters( + self.current_app, + "SELECT", + "END_POS", + writer_Select_command.from_pos, + "START_POS", + writer_Select_command.to_pos, + ) + + self.prev_command = writer_Select_command + + def handle_writer_goto(self, writer_GOTO_command): + + self.init_app() + + self.write_line_with_one_parameters( + self.current_app, "GOTO", "PAGE", writer_GOTO_command.page_num + ) + + self.prev_command = writer_GOTO_command + + def handle_calc_select(self, calc_Select_cell): + + self.init_app() + + if calc_Select_cell.select_op.__class__.__name__ == "range_of_cells": + self.write_line_with_one_parameters( + self.current_app, + "SELECT", + "RANGE", + calc_Select_cell.select_op.input_range, + ) + + elif calc_Select_cell.select_op.__class__.__name__ == "one_cell": + self.write_line_with_one_parameters( + self.current_app, + "SELECT", + "CELL", + calc_Select_cell.select_op.input_cell, + ) + + self.prev_command = calc_Select_cell + + def handle_calc_switch_sheet(self, calc_switch_sheet): + + self.init_app() + + self.write_line_with_one_parameters( + self.current_app, "SELECT", "TABLE", calc_switch_sheet.sheet_num + ) + + self.prev_command = calc_switch_sheet + + def handle_calc_Type_command(self, calc_Type_command): + + self.init_app() + + if calc_Type_command.what_to_type.__class__.__name__ == "char": + self.write_line_with_one_parameters( + self.current_app, + "TYPE", + "TEXT", + calc_Type_command.what_to_type.input_char, + ) + + elif calc_Type_command.what_to_type.__class__.__name__ == "KeyCode": + self.write_line_with_one_parameters( + self.current_app, + "TYPE", + "KEYCODE", + calc_Type_command.what_to_type.input_key_code, + ) + + self.prev_command = calc_Type_command + + def handle_calc_AutoFill_filter(self, calc_AutoFill_filter): + + self.init_app() + + line = ( + double_tab + + self.current_app + + '.executeAction("LAUNCH", mkPropertyValues' + + '({"AUTOFILTER": "", "COL": "' + + str(calc_AutoFill_filter.col_num) + + '"' + + ', "ROW": "' + + str(calc_AutoFill_filter.row_num) + + '"}))\n' + ) + + self.variables.append(line) + self.prev_command = calc_AutoFill_filter + + def handle_impress_Type_command(self, impress_Type_command): + + self.init_app() + + if impress_Type_command.what_to_type.__class__.__name__ == "char": + self.write_line_with_one_parameters( + self.current_app, + "TYPE", + "TEXT", + impress_Type_command.what_to_type.input_char, + ) + + elif impress_Type_command.what_to_type.__class__.__name__ == "KeyCode": + self.write_line_with_one_parameters( + self.current_app, + "TYPE", + "KEYCODE", + impress_Type_command.what_to_type.input_key_code, + ) + + self.prev_command = impress_Type_command + + def handle_math_Type_command(self, math_Type_command): + + self.init_app() + if math_Type_command.what_to_type.__class__.__name__ == "char": + self.write_line_with_one_parameters( + self.current_app, + "TYPE", + "TEXT", + math_Type_command.what_to_type.input_char, + ) + + elif math_Type_command.what_to_type.__class__.__name__ == "KeyCode": + self.write_line_with_one_parameters( + self.current_app, + "TYPE", + "KEYCODE", + math_Type_command.what_to_type.input_key_code, + ) + + self.prev_command = math_Type_command + + def handle_draw_Type_command(self, draw_Type_command): + + self.init_app() + if draw_Type_command.what_to_type.__class__.__name__ == "char": + self.write_line_with_one_parameters( + self.current_app, + "TYPE", + "TEXT", + draw_Type_command.what_to_type.input_char, + ) + + elif draw_Type_command.what_to_type.__class__.__name__ == "KeyCode": + self.write_line_with_one_parameters( + self.current_app, + "TYPE", + "KEYCODE", + draw_Type_command.what_to_type.input_key_code, + ) + + self.prev_command = draw_Type_command + + def handle_math_element_selector(self, math_element_selector): + + if( self.math_element_selector_initializer == False ): + # This part to initialize the element selector in math application + self.math_element_selector_initializer = True + line = ( + double_tab + + "element_selector" + + ' = MainWindow.getChild("' + + "element_selector" + + '")\n' + ) + self.variables.append(line) + + # this put a prefix of char 'x' to avoid variable with name equal to number only + element_name="x"+str(math_element_selector.element_no) + + line = ( + double_tab + + str(element_name) + + ' = element_selector.getChild("' + + str(math_element_selector.element_no) + + '")\n' + ) + self.variables.append(line) + + self.write_line_without_parameters( + str(element_name), "SELECT", "tuple" + ) + + self.prev_command = math_element_selector + + def handle_setZoom_command(self, setZoom_command): + + self.init_app() + + self.write_line_with_one_parameters( + self.current_app, "SET", "ZOOM", setZoom_command.zoom_value + ) + + self.prev_command = setZoom_command + + def Generate_UI_test(self): + line = double_tab + "self.ui_test.close_doc()" + self.variables.append(line) + + line = "\n\n# vim: set shiftwidth=4 softtabstop=4 expandtab:" + self.variables.append(line) + + for line in self.variables: + self.output_stream.write(str(line)) + + def do_nothing(self, Command): + line = "to be added in the future" + + def __del__(self): + self.output_stream.close() + + +def main(): + args = parse_args() + ui_logger = ul_Compiler(args.input_address, args.output_address) + ui_logger.compile() + for statement in ui_logger.log_lines.commands: + print(statement) + ui_logger.Generate_UI_test() + del ui_logger + + +if __name__ == "__main__": + main() diff --git a/uitest/ui_logger_dsl/example.ul b/uitest/ui_logger_dsl/example.ul new file mode 100644 index 000000000..d82c71a29 --- /dev/null +++ b/uitest/ui_logger_dsl/example.ul @@ -0,0 +1,34 @@ +Start writer +Send UNO Command (".uno:UpdateInputFields") +Send UNO Command (".uno:FontDialog") +Open Modal CharacterPropertiesDialog +Choose Tab number 0 in 'tabcontrol' from CharacterPropertiesDialog +Select in 'westfontnamelb-cjk' ComboBox item number 66 from CharacterPropertiesDialog +Choose Tab number 1 in 'tabcontrol' from CharacterPropertiesDialog +Select element with position 3 in 'effectslb' fromCharacterPropertiesDialog +Toggle 'shadowcb' CheckBox from CharacterPropertiesDialog +Choose Tab number 2 in 'tabcontrol' from CharacterPropertiesDialog +Select '270deg' RadioButton from CharacterPropertiesDialog +Select '90deg' RadioButton from CharacterPropertiesDialog +Increase 'scalewidthsb' from CharacterPropertiesDialog +Increase 'scalewidthsb' from CharacterPropertiesDialog +Increase 'scalewidthsb' from CharacterPropertiesDialog +Decrease 'scalewidthsb' from CharacterPropertiesDialog +Decrease 'scalewidthsb' from CharacterPropertiesDialog +Decrease 'scalewidthsb' from CharacterPropertiesDialog +Toggle 'pairkerning' CheckBox from CharacterPropertiesDialog +Click on 'cancel' from CharacterPropertiesDialog +Close Dialog +Type on writer {"TEXT": "a"} +Type on writer {"TEXT": "n"} +Type on writer {"TEXT": "a"} +Type on writer {"TEXT": " "} +Type on writer {"TEXT": "a"} +Type on writer {"TEXT": "h"} +Type on writer {"TEXT": "m"} +Type on writer {"TEXT": "e"} +Type on writer {"TEXT": "d"} +Select from Pos 4 to Pos 9 +Open Modal QuerySaveDialog +Click on 'discard' from QuerySaveDialog +Close Dialog
\ No newline at end of file diff --git a/uitest/ui_logger_dsl/starter_commands.tx b/uitest/ui_logger_dsl/starter_commands.tx new file mode 100644 index 000000000..93fb0c2e0 --- /dev/null +++ b/uitest/ui_logger_dsl/starter_commands.tx @@ -0,0 +1,13 @@ +//this file for the starters commands when you open any LO application +//It's translate automatic that the button you push to open the app is a starter button + +StarterCommand: + 'Start' program_name=Program +; + + +Program: + "writer"|"calc"|"impress"|"draw"|"math"|"database" +; + + diff --git a/uitest/ui_logger_dsl/type_options.tx b/uitest/ui_logger_dsl/type_options.tx new file mode 100644 index 000000000..b106e7f03 --- /dev/null +++ b/uitest/ui_logger_dsl/type_options.tx @@ -0,0 +1,9 @@ +Type_options: + char | KeyCode +; +char: + '{' '"TEXT":' input_char=STRING '}' +; +KeyCode: + '{' '"KEYCODE":' input_key_code=STRING '}' +; diff --git a/uitest/ui_logger_dsl/ui_logger_dsl_grammar.tx b/uitest/ui_logger_dsl/ui_logger_dsl_grammar.tx new file mode 100644 index 000000000..123c9b6f3 --- /dev/null +++ b/uitest/ui_logger_dsl/ui_logger_dsl_grammar.tx @@ -0,0 +1,29 @@ +//this file is to define the new dsl grammar +/* + This file just Import all Grammar Statements from all other files to this file + The Compiler just work with this file to Compile it + Each file of these imported file has a Comments related to it's content +*/ + +import dialog_commands +import starter_commands +import uno_commands +import UI_Object_commands +import Special_commands +import General_commands + +UILogger: + commands*=Command +; + +Command: + UNOCommand | StarterCommand | UIObjectCommand | DialogCommand | + SpecialCommand | GeneralCommand | Comment +; +/* + The Comment Command is just for give the ability to write a Comment + if you want to write a test Case in the new dsl language +*/ +Comment: + /\/\/.*$/ +; diff --git a/uitest/ui_logger_dsl/uno_commands.tx b/uitest/ui_logger_dsl/uno_commands.tx new file mode 100644 index 000000000..15df9ef86 --- /dev/null +++ b/uitest/ui_logger_dsl/uno_commands.tx @@ -0,0 +1,20 @@ +/* + This file is for the grammar of the UNO Command Statements + It's Automatically have 2 modes one with parameters and one without +*/ + +UNOCommand: + 'Send UNO Command' '(' uno_command_name=STRING ')' (parameters=parameter)? +; + +parameter: + '{' parameter_data *= data ','? '}' +; + +data: + ','? key=STRING ':' value= value_type +; + +value_type: + INT|ID +;
\ No newline at end of file diff --git a/uitest/uitest/bisecting.py b/uitest/uitest/bisecting.py new file mode 100644 index 000000000..7d2f07441 --- /dev/null +++ b/uitest/uitest/bisecting.py @@ -0,0 +1,16 @@ +# -*- 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 functools import wraps + +def requires(revision): + def decorator(f): + f.requires = revision + return f + return decorator + +# vim: set shiftwidth=4 softtabstop=4 expandtab: diff --git a/uitest/uitest/config.py b/uitest/uitest/config.py new file mode 100644 index 000000000..d9a86baae --- /dev/null +++ b/uitest/uitest/config.py @@ -0,0 +1,14 @@ +# -*- 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/. +# + +use_sleep = False + +DEFAULT_SLEEP = 0.1 + +MAX_WAIT = 60 + +# vim: set shiftwidth=4 softtabstop=4 expandtab: diff --git a/uitest/uitest/debug.py b/uitest/uitest/debug.py new file mode 100644 index 000000000..234559174 --- /dev/null +++ b/uitest/uitest/debug.py @@ -0,0 +1,16 @@ +# -*- 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 uitest.config + +import time + +def sleep(seconds): + if uitest.config.use_sleep: + time.sleep(seconds) + +# vim: set shiftwidth=4 softtabstop=4 expandtab: diff --git a/uitest/uitest/framework.py b/uitest/uitest/framework.py new file mode 100644 index 000000000..7149132c3 --- /dev/null +++ b/uitest/uitest/framework.py @@ -0,0 +1,67 @@ +# -*- 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 signal +import unittest +import time + +from uitest.test import UITest + +from libreoffice.connection import PersistentConnection, OfficeConnection + +class UITestCase(unittest.TestCase): + + def __init__(self, test_name, opts): + unittest.TestCase.__init__(self, test_name) + self.opts = opts + + def setUp(self): + self.setSignalHandler() + self.connection = PersistentConnection(self.opts) + self.connection.setUp() + self.xContext = self.connection.getContext() + self.xUITest = self.xContext.ServiceManager.createInstanceWithContext( + "org.libreoffice.uitest.UITest", self.xContext) + + self.ui_test = UITest(self.xUITest, self.xContext) + self.startTime = time.time() + + def tearDown(self): + try: + t = time.time() - self.startTime + print("Execution time for %s: %.3f" % (self.id(), t)) + if self.xContext is not None: + try: + desktop = self.ui_test.get_desktop() + components = desktop.getComponents() + for component in components: + component.close(False) + except Exception as e: + print(e) + + self.connection.tearDown() + finally: + self.resetSignalHandler() + self.connection.kill() + + def signalHandler(self, signum, frame): + if self.connection: + self.connection.kill() + + def setSignalHandler(self): + signal.signal(signal.SIGABRT, self.signalHandler) + signal.signal(signal.SIGSEGV, self.signalHandler) + signal.signal(signal.SIGTERM, self.signalHandler) + signal.signal(signal.SIGILL, self.signalHandler) + + def resetSignalHandler(self): + signal.signal(signal.SIGABRT, signal.SIG_IGN) + signal.signal(signal.SIGSEGV, signal.SIG_IGN) + signal.signal(signal.SIGTERM, signal.SIG_IGN) + signal.signal(signal.SIGILL, signal.SIG_IGN) + +# vim: set shiftwidth=4 softtabstop=4 expandtab: diff --git a/uitest/uitest/path.py b/uitest/uitest/path.py new file mode 100644 index 000000000..5a3aeff22 --- /dev/null +++ b/uitest/uitest/path.py @@ -0,0 +1,31 @@ +# -*- 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 os +from urllib.parse import urljoin +from urllib.request import pathname2url + +def get_src_dir_fallback(): + current_dir = os.path.dirname(os.path.realpath(__file__)) + return os.path.abspath(os.path.join(current_dir, "../../")) + +def path2url(path): + return urljoin('file:', pathname2url(os.path.normpath(path))) + +def get_workdir_url(): + workdir_path = os.environ.get('WORKDIR', os.path.join(get_src_dir_fallback(), 'workdir')) + return path2url(workdir_path) + +def get_srcdir_url(): + srcdir_path = os.environ.get('SRCDIR', get_src_dir_fallback()) + return path2url(srcdir_path) + +def get_instdir_url(): + instdir_path = os.environ.get('INSTDIR', os.path.join(get_src_dir_fallback(), 'instdir')) + return path2url(instdir_path) + +# vim: set shiftwidth=4 softtabstop=4 expandtab: diff --git a/uitest/uitest/test.py b/uitest/uitest/test.py new file mode 100644 index 000000000..556fb511c --- /dev/null +++ b/uitest/uitest/test.py @@ -0,0 +1,223 @@ +# -*- 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 +from uitest.config import DEFAULT_SLEEP +from uitest.config import MAX_WAIT +from uitest.uihelper.common import get_state_as_dict + +from com.sun.star.uno import RuntimeException + +from libreoffice.uno.eventlistener import EventListener + +class DialogNotExecutedException(Exception): + def __init__(self, command): + self.command = command + + def __str__(self): + return "Dialog not executed for: " + self.command + +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_until_child_is_available(self, parent, childName): + time_ = 0 + while time_ < MAX_WAIT: + if childName in parent.getChildren(): + break + else: + time_ += DEFAULT_SLEEP + time.sleep(DEFAULT_SLEEP) + + def wait_until_property_is_updated(self, element, propertyName, value): + time_ = 0 + while time_ < MAX_WAIT: + if get_state_as_dict(element)[propertyName] == value: + break + else: + time_ += DEFAULT_SLEEP + time.sleep(DEFAULT_SLEEP) + + def load_file(self, url): + desktop = self.get_desktop() + with EventListener(self._xContext, "OnLoad") as event: + component = desktop.loadComponentFromURL(url, "_default", 0, tuple()) + time_ = 0 + while time_ < MAX_WAIT: + if event.executed: + frames = self.get_frames() + if len(frames) == 1: + self.get_desktop().setActiveFrame(frames[0]) + time.sleep(DEFAULT_SLEEP) + return component + time_ += DEFAULT_SLEEP + time.sleep(DEFAULT_SLEEP) + + def execute_dialog_through_command(self, command, printNames=False): + with EventListener(self._xContext, "DialogExecute", printNames=printNames) as event: + if not self._xUITest.executeDialog(command): + raise DialogNotExecutedException(command) + while True: + if event.executed: + time.sleep(DEFAULT_SLEEP) + return + time.sleep(DEFAULT_SLEEP) + + def execute_modeless_dialog_through_command(self, command, printNames=False): + with EventListener(self._xContext, "ModelessDialogVisible", printNames = printNames) as event: + if not self._xUITest.executeCommand(command): + raise DialogNotExecutedException(command) + time_ = 0 + while time_ < MAX_WAIT: + if event.executed: + time.sleep(DEFAULT_SLEEP) + return + time_ += DEFAULT_SLEEP + time.sleep(DEFAULT_SLEEP) + + raise DialogNotExecutedException(command) + + def execute_dialog_through_action(self, ui_object, action, parameters = None, event_name = "DialogExecute"): + if parameters is None: + parameters = tuple() + + with EventListener(self._xContext, event_name) as event: + ui_object.executeAction(action, parameters) + time_ = 0 + while time_ < MAX_WAIT: + if event.executed: + time.sleep(DEFAULT_SLEEP) + return + time_ += DEFAULT_SLEEP + time.sleep(DEFAULT_SLEEP) + raise DialogNotExecutedException(action) + + 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 + + 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()) + time_ = 0 + while time_ < MAX_WAIT: + if event.executed: + frames = self.get_frames() + self.get_desktop().setActiveFrame(frames[0]) + print(len(frames)) + return + time_ += DEFAULT_SLEEP + time.sleep(DEFAULT_SLEEP) + + print("failure doc in start center") + + # report a failure here + + 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() + + def execute_blocking_action(self, action, dialog_element=None, + args=(), dialog_handler=None, 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. + dialog_element(str, optional): The name of a button on the dialog + which will be clicked when the dialog is shown. + args(tuple, optional): The arguments to be passed to `action` + dialog_handler(callable, optional): Will be called when the dialog + is shown, with the dialog object passed as a parameter. + 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() + time_ = 0 + # we are not necessarily opening a dialog, so wait much longer + while time_ < 10 * MAX_WAIT: + if event.executed: + xDlg = self._xUITest.getTopFocusWindow() + if dialog_element: + xUIElement = xDlg.getChild(dialog_element) + xUIElement.executeAction("CLICK", tuple()) + if dialog_handler: + dialog_handler(xDlg) + thread.join() + return + + time_ += DEFAULT_SLEEP + time.sleep(DEFAULT_SLEEP) + raise DialogNotExecutedException("did not execute a dialog for a blocking action") + +# vim: set shiftwidth=4 softtabstop=4 expandtab: diff --git a/uitest/uitest/uihelper/__init__.py b/uitest/uitest/uihelper/__init__.py new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/uitest/uitest/uihelper/__init__.py diff --git a/uitest/uitest/uihelper/calc.py b/uitest/uitest/uihelper/calc.py new file mode 100644 index 000000000..e34304c69 --- /dev/null +++ b/uitest/uitest/uihelper/calc.py @@ -0,0 +1,16 @@ +# -*- 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 libreoffice.uno.propertyvalue import mkPropertyValues +from uitest.uihelper.common import type_text + +def enter_text_to_cell(gridwin, cell, text): + gridwin.executeAction("SELECT", mkPropertyValues({"CELL": cell})) + type_text(gridwin, text) + gridwin.executeAction("TYPE", mkPropertyValues({"KEYCODE": "RETURN"})) + +# vim: set shiftwidth=4 softtabstop=4 expandtab: diff --git a/uitest/uitest/uihelper/common.py b/uitest/uitest/uihelper/common.py new file mode 100644 index 000000000..5056ef764 --- /dev/null +++ b/uitest/uitest/uihelper/common.py @@ -0,0 +1,22 @@ +# -*- 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 libreoffice.uno.propertyvalue import convert_property_values_to_dict, mkPropertyValues + +def get_state_as_dict(ui_object): + return convert_property_values_to_dict(ui_object.getState()) + +def type_text(ui_object, text): + ui_object.executeAction("TYPE", mkPropertyValues({"TEXT": text})) + +def select_pos(ui_object, pos): + ui_object.executeAction("SELECT", mkPropertyValues({"POS": pos})) + +def select_text(ui_object, from_pos, to): + ui_object.executeAction("SELECT", mkPropertyValues({"FROM": from_pos, "TO": to})) + +# vim: set shiftwidth=4 softtabstop=4 expandtab: diff --git a/uitest/uitest/uihelper/keyboard.py b/uitest/uitest/uihelper/keyboard.py new file mode 100644 index 000000000..f2d8890af --- /dev/null +++ b/uitest/uitest/uihelper/keyboard.py @@ -0,0 +1,13 @@ +# -*- 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 libreoffice.uno.propertyvalue import convert_property_values_to_dict, mkPropertyValues + +def select_all(ui_object): + ui_object.executeAction("TYPE", mkPropertyValues({"KEYCODE":"CTRL+A"})) + +# vim: set shiftwidth=4 softtabstop=4 expandtab: diff --git a/uitest/uitest/uihelper/testDialog.py b/uitest/uitest/uihelper/testDialog.py new file mode 100644 index 000000000..43f0a5bc0 --- /dev/null +++ b/uitest/uitest/uihelper/testDialog.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/. +# + +from uitest.framework import UITestCase +from uitest.uihelper.common import get_state_as_dict + +# opens the dialogs, closes it with the given close button +# and if there is an "OK" button open the dialog again and close it by using the OK button +# the test only checks if LibreOffice crashes by opening the dialog +def testDialog(UITestCase, app, dialog): + doc = UITestCase.ui_test.create_doc_in_start_center(app) + UITestCase.ui_test.execute_dialog_through_command(dialog['command']) + xDialog = UITestCase.xUITest.getTopFocusWindow() + + xCloseBtn = xDialog.getChild(dialog['closeButton']) + if 'skipTestOK' in dialog and dialog['skipTestOK'] == True: + xOKBtn = None + else: + try: + xOKBtn = xDialog.getChild("ok") + if (get_state_as_dict(xOKBtn)["Enabled"] != "true"): + xOKBtn = None + except: + xOKBtn = None + + UITestCase.ui_test.close_dialog_through_button(xCloseBtn) + if (xOKBtn != None): + print("check also OK button") + UITestCase.ui_test.execute_dialog_through_command(dialog['command']) + xDialog = UITestCase.xUITest.getTopFocusWindow() + xOKBtn = xDialog.getChild("ok") + UITestCase.ui_test.close_dialog_through_button(xOKBtn) + UITestCase.ui_test.close_doc() + +# vim: set shiftwidth=4 softtabstop=4 expandtab: diff --git a/uitest/writer_tests/data/3pages.odt b/uitest/writer_tests/data/3pages.odt Binary files differnew file mode 100644 index 000000000..0f2512903 --- /dev/null +++ b/uitest/writer_tests/data/3pages.odt diff --git a/uitest/writer_tests/data/tdf104649.docx b/uitest/writer_tests/data/tdf104649.docx Binary files differnew file mode 100644 index 000000000..7b1e4fd3c --- /dev/null +++ b/uitest/writer_tests/data/tdf104649.docx diff --git a/uitest/writer_tests/data/tdf114724.odt b/uitest/writer_tests/data/tdf114724.odt Binary files differnew file mode 100644 index 000000000..6c5110868 --- /dev/null +++ b/uitest/writer_tests/data/tdf114724.odt diff --git a/uitest/writer_tests1/pageDialog.py b/uitest/writer_tests1/pageDialog.py new file mode 100644 index 000000000..73e523444 --- /dev/null +++ b/uitest/writer_tests1/pageDialog.py @@ -0,0 +1,239 @@ +# +# 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.framework import UITestCase +from uitest.uihelper.common import select_pos, get_state_as_dict +from com.sun.star.uno import RuntimeException +from com.sun.star.awt.GradientStyle import LINEAR +from com.sun.star.drawing.HatchStyle import SINGLE +from com.sun.star.drawing.BitmapMode import REPEAT +from com.sun.star.drawing.RectanglePoint import MIDDLE_MIDDLE + +from libreoffice.uno.propertyvalue import mkPropertyValues + +class WriterPageDialog(UITestCase): + + def launch_dialog_and_select_tab(self, tab): + self.ui_test.execute_dialog_through_command(".uno:PageDialog") + + xDialog = self.xUITest.getTopFocusWindow() + tabcontrol = xDialog.getChild("tabcontrol") + select_pos(tabcontrol, str(tab)) + + return xDialog + + def click_button(self, dialog, button): + xButton = dialog.getChild(button) + xButton.executeAction("CLICK", tuple()) + + def check_default_area(self, btn): + document = self.ui_test.get_component() + if btn == 'btnnone': + self.assertEqual( + document.StyleFamilies.PageStyles.Standard.BackColor, -1) + elif btn == 'btncolor': + self.assertEqual( + hex(document.StyleFamilies.PageStyles.Standard.BackColor), '0x729fcf') + self.assertEqual( + hex(document.StyleFamilies.PageStyles.Standard.FillColor), '0x729fcf') + self.assertEqual( + hex(document.StyleFamilies.PageStyles.Standard.FillColor), '0x729fcf') + elif btn == 'btngradient': + self.assertEqual( + document.StyleFamilies.PageStyles.Standard.FillGradient.Style, LINEAR) + self.assertEqual( + hex(document.StyleFamilies.PageStyles.Standard.FillGradient.StartColor), '0xdde8cb') + self.assertEqual( + document.StyleFamilies.PageStyles.Standard.FillGradient.Angle, 300) + self.assertEqual( + document.StyleFamilies.PageStyles.Standard.FillGradient.Border, 0) + self.assertEqual( + document.StyleFamilies.PageStyles.Standard.FillGradient.XOffset, 0) + self.assertEqual( + document.StyleFamilies.PageStyles.Standard.FillGradient.YOffset, 0) + self.assertEqual( + document.StyleFamilies.PageStyles.Standard.FillGradient.StartIntensity, 100) + self.assertEqual( + document.StyleFamilies.PageStyles.Standard.FillGradient.EndIntensity, 100) + self.assertEqual( + document.StyleFamilies.PageStyles.Standard.FillGradientName, 'Pastel Bouquet') + elif btn == 'btnhatch': + self.assertEqual( + document.StyleFamilies.PageStyles.Standard.FillHatch.Style, SINGLE ) + self.assertEqual( + document.StyleFamilies.PageStyles.Standard.FillHatch.Color, 0) + self.assertEqual( + document.StyleFamilies.PageStyles.Standard.FillHatch.Distance, 102) + self.assertEqual( + document.StyleFamilies.PageStyles.Standard.FillHatch.Angle, 0) + self.assertEqual( + document.StyleFamilies.PageStyles.Standard.FillHatchName, 'Black 0 Degrees') + elif btn == 'btnbitmap': + self.assertEqual( + document.StyleFamilies.PageStyles.Standard.FillBitmapMode, REPEAT) + self.assertEqual( + document.StyleFamilies.PageStyles.Standard.FillBitmapPositionOffsetX, 0) + self.assertEqual( + document.StyleFamilies.PageStyles.Standard.FillBitmapPositionOffsetY, 0) + self.assertEqual( + document.StyleFamilies.PageStyles.Standard.FillBitmapRectanglePoint, MIDDLE_MIDDLE) + self.assertEqual( + document.StyleFamilies.PageStyles.Standard.FillBitmapStretch, False) + self.assertEqual( + document.StyleFamilies.PageStyles.Standard.FillBitmapTile, True) + self.assertEqual( + document.StyleFamilies.PageStyles.Standard.FillBitmapOffsetX, 0) + self.assertEqual( + document.StyleFamilies.PageStyles.Standard.FillBitmapOffsetY, 0) + self.assertEqual( + document.StyleFamilies.PageStyles.Standard.FillBitmapLogicalSize, True) + self.assertEqual( + document.StyleFamilies.PageStyles.Standard.FillBitmapSizeX, 0) + self.assertEqual( + document.StyleFamilies.PageStyles.Standard.FillBitmapSizeY, 0) + self.assertEqual( + document.StyleFamilies.PageStyles.Standard.FillBitmapName, 'Painted White') + elif btn == 'btnpattern': + self.assertEqual( + document.StyleFamilies.PageStyles.Standard.FillBitmapMode, REPEAT) + self.assertEqual( + document.StyleFamilies.PageStyles.Standard.FillBitmapPositionOffsetX, 0) + self.assertEqual( + document.StyleFamilies.PageStyles.Standard.FillBitmapPositionOffsetY, 0) + self.assertEqual( + document.StyleFamilies.PageStyles.Standard.FillBitmapRectanglePoint, MIDDLE_MIDDLE) + self.assertEqual( + document.StyleFamilies.PageStyles.Standard.FillBitmapStretch, False) + self.assertEqual( + document.StyleFamilies.PageStyles.Standard.FillBitmapTile, True) + self.assertEqual( + document.StyleFamilies.PageStyles.Standard.FillBitmapOffsetX, 0) + self.assertEqual( + document.StyleFamilies.PageStyles.Standard.FillBitmapOffsetY, 0) + self.assertEqual( + document.StyleFamilies.PageStyles.Standard.FillBitmapLogicalSize, True) + self.assertEqual( + document.StyleFamilies.PageStyles.Standard.FillBitmapSizeX, 0) + self.assertEqual( + document.StyleFamilies.PageStyles.Standard.FillBitmapSizeY, 0) + self.assertEqual( + document.StyleFamilies.PageStyles.Standard.FillBitmapName, '5 Percent') + + def test_area_tab(self): + + self.ui_test.create_doc_in_start_center("writer") + + buttons = ['btnbitmap', 'btncolor', 'btngradient', 'btnhatch', 'btnpattern'] + for index, button in enumerate(buttons): + + xDialog = self.launch_dialog_and_select_tab(2) + + self.click_button(xDialog, button) + + self.click_button(xDialog, 'ok') + + self.check_default_area(button) + + xDialog = self.launch_dialog_and_select_tab(2) + + self.click_button(xDialog, 'btnnone') + + self.click_button(xDialog, 'ok') + + self.check_default_area('btnnone') + + self.ui_test.close_doc() + + def test_paper_format(self): + + lPaperFormat = ["A6", "A5", "A4", "A3", "B6 (ISO)", "B5 (ISO)", "B4 (ISO)", "Letter", + "Legal", "Long Bond", "Tabloid", "B6 (JIS)", "B5 (JIS)", "B4 (JIS)", "16 Kai", + "32 Kai", "Big 32 Kai", "User", "DL Envelope", "C6 Envelope", "C6/5 Envelope", + "C5 Envelope", "C4 Envelope", "#6¾ Envelope", "#7¾ (Monarch) Envelope", + "#9 Envelope", "#10 Envelope", "#11 Envelope", "#12 Envelope", "Japanese Postcard"] + + self.ui_test.create_doc_in_start_center("writer") + + for i in range(30): + with self.subTest(i=i): + xDialog = self.launch_dialog_and_select_tab(1) + + xFormatList = xDialog.getChild("comboPageFormat") + select_pos(xFormatList, str(i)) + + self.assertEqual( + get_state_as_dict(xFormatList)["SelectEntryText"], lPaperFormat[i]) + + self.click_button(xDialog, 'ok') + + self.ui_test.close_doc() + + def test_orientation(self): + + self.ui_test.create_doc_in_start_center("writer") + + document = self.ui_test.get_component() + + self.assertEqual( + document.StyleFamilies.PageStyles.Standard.IsLandscape, False) + + xDialog = self.launch_dialog_and_select_tab(1) + + self.click_button(xDialog, 'radiobuttonLandscape') + + self.click_button(xDialog, 'ok') + + self.assertEqual( + document.StyleFamilies.PageStyles.Standard.IsLandscape, True) + + xDialog = self.launch_dialog_and_select_tab(1) + + self.click_button(xDialog, 'radiobuttonPortrait') + + self.click_button(xDialog, 'ok') + + self.assertEqual( + document.StyleFamilies.PageStyles.Standard.IsLandscape, False) + + self.ui_test.close_doc() + + def test_text_direction(self): + + lTextDirection = ['Left-to-right (horizontal)', 'Right-to-left (horizontal)', + 'Right-to-left (vertical)', 'Left-to-right (vertical)'] + + self.ui_test.create_doc_in_start_center("writer") + + document = self.ui_test.get_component() + + for i in range(4): + with self.subTest(i=i): + xDialog = self.launch_dialog_and_select_tab(1) + + xTextDirectionList = xDialog.getChild("comboTextFlowBox") + select_pos(xTextDirectionList, str(i)) + + self.assertEqual( + get_state_as_dict(xTextDirectionList)["SelectEntryText"], lTextDirection[i]) + + self.click_button(xDialog, 'ok') + + self.assertEqual( + document.StyleFamilies.PageStyles.Standard.WritingMode, i) + + self.ui_test.close_doc() + + def test_cancel_button_page_dialog(self): + self.ui_test.create_doc_in_start_center("writer") + + self.ui_test.execute_dialog_through_command(".uno:PageDialog") + xDialog = self.xUITest.getTopFocusWindow() + xCancelBtn = xDialog.getChild("cancel") + self.ui_test.close_dialog_through_button(xCancelBtn) + + self.ui_test.close_doc() + +# vim: set shiftwidth=4 softtabstop=4 expandtab: diff --git a/uitest/writer_tests2/tdf92611.py b/uitest/writer_tests2/tdf92611.py new file mode 100644 index 000000000..8fee6143c --- /dev/null +++ b/uitest/writer_tests2/tdf92611.py @@ -0,0 +1,21 @@ +# +# 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.framework import UITestCase + +class tdf92611(UITestCase): + + def test_launch_and_close_bibliography(self): + + self.ui_test.create_doc_in_start_center("writer") + + self.xUITest.executeCommand(".uno:BibliographyComponent") + + self.xUITest.executeCommand(".uno:CloseWin") + + self.ui_test.close_doc() + +# vim: set shiftwidth=4 softtabstop=4 expandtab: diff --git a/uitest/writer_tests3/tdf104649.py b/uitest/writer_tests3/tdf104649.py new file mode 100644 index 000000000..f6541feee --- /dev/null +++ b/uitest/writer_tests3/tdf104649.py @@ -0,0 +1,37 @@ +# +# 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.framework import UITestCase + +import org.libreoffice.unotest +import pathlib + +def get_url_for_data_file(file_name): + return pathlib.Path(org.libreoffice.unotest.makeCopyFromTDOC(file_name)).as_uri() + +class tdf104649(UITestCase): + + def test_delete_and_undo(self): + + writer_doc = self.ui_test.load_file(get_url_for_data_file("tdf104649.docx")) + + document = self.ui_test.get_component() + + self.assertEqual(document.Text.String[0:4], "Test") + + selection = self.xUITest.executeCommand(".uno:SelectAll") + + self.xUITest.executeCommand(".uno:Delete") + + self.assertEqual(document.Text.String, "") + + self.xUITest.executeCommand(".uno:Undo") + + self.assertEqual(document.Text.String[0:4], "Test") + + self.ui_test.close_doc() + +# vim: set shiftwidth=4 softtabstop=4 expandtab: diff --git a/uitest/writer_tests4/insertTableDialog.py b/uitest/writer_tests4/insertTableDialog.py new file mode 100644 index 000000000..427920e19 --- /dev/null +++ b/uitest/writer_tests4/insertTableDialog.py @@ -0,0 +1,78 @@ +# +# 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.framework import UITestCase +from libreoffice.uno.propertyvalue import mkPropertyValues +from uitest.uihelper.common import get_state_as_dict + +class WriterInsertTableDialog(UITestCase): + + def insert_table(self, name, rows, cols): + + self.ui_test.create_doc_in_start_center("writer") + + self.ui_test.execute_dialog_through_command(".uno:InsertTable") + xDialog = self.xUITest.getTopFocusWindow() + + xNameEdit = xDialog.getChild("nameedit") + + xNameEdit.executeAction("TYPE", mkPropertyValues({"KEYCODE":"CTRL+A"})) + xNameEdit.executeAction("TYPE", mkPropertyValues({"TEXT": name})) + + xColSpin = xDialog.getChild("colspin") + xColSpin.executeAction("TYPE", mkPropertyValues({"KEYCODE":"CTRL+A"})) + xColSpin.executeAction("TYPE", mkPropertyValues({"TEXT": str(cols)})) + + xRowSpin = xDialog.getChild("rowspin") + xRowSpin.executeAction("TYPE", mkPropertyValues({"KEYCODE":"CTRL+A"})) + xRowSpin.executeAction("TYPE", mkPropertyValues({"TEXT": str(rows)})) + + self.assertEqual(get_state_as_dict(xNameEdit)["Text"], name) + self.assertEqual(get_state_as_dict(xColSpin)["Text"], str(cols)) + self.assertEqual(get_state_as_dict(xRowSpin)["Text"], str(rows)) + + xOkBtn = xDialog.getChild("ok") + xOkBtn.executeAction("CLICK", tuple()) + + document = self.ui_test.get_component() + + tables = document.getTextTables() + + self.assertEqual(tables[0].getName(), name) + self.assertEqual(len(tables[0].getRows()), rows) + self.assertEqual(len(tables[0].getColumns()), cols) + + def insertTextIntoCell(self, table, cellName, text ): + tableText = table.getCellByName( cellName ) + tableText.setString( text ) + + def test_tdf104158(self): + + self.insert_table("Test3", 2, 2) + + self.ui_test.execute_dialog_through_command(".uno:TableNumberFormatDialog") + + xNumberFormatDlg = self.xUITest.getTopFocusWindow() + + xOkBtn = xNumberFormatDlg.getChild("ok") + xOkBtn.executeAction("CLICK", tuple()) + + self.ui_test.close_doc() + + def test_cancel_button_insert_table_dialog(self): + self.ui_test.create_doc_in_start_center("writer") + self.ui_test.execute_dialog_through_command(".uno:InsertTable") + Dialog = self.xUITest.getTopFocusWindow() + CancelBtn = Dialog.getChild("cancel") + self.ui_test.close_dialog_through_button(CancelBtn) + + document = self.ui_test.get_component() + tables = document.getTextTables() + self.assertEqual(len(tables), 0) + + self.ui_test.close_doc() + +# vim: set shiftwidth=4 softtabstop=4 expandtab: diff --git a/uitest/writer_tests4/start.py b/uitest/writer_tests4/start.py new file mode 100644 index 000000000..5851e8eff --- /dev/null +++ b/uitest/writer_tests4/start.py @@ -0,0 +1,70 @@ +# -*- 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 libreoffice.uno.propertyvalue import mkPropertyValues + +from uitest.framework import UITestCase +from uitest.uihelper.common import get_state_as_dict, type_text + +import time + +class SimpleWriterTest(UITestCase): + + def test_start_writer(self): + + self.ui_test.create_doc_in_start_center("writer") + + xWriterDoc = self.xUITest.getTopFocusWindow() + + xWriterEdit = xWriterDoc.getChild("writer_edit") + + xWriterEdit.executeAction("SET", mkPropertyValues({"ZOOM": "200"})) + + self.ui_test.close_doc() + + def test_type_text(self): + + self.ui_test.create_doc_in_start_center("writer") + + xWriterDoc = self.xUITest.getTopFocusWindow() + xWriterEdit = xWriterDoc.getChild("writer_edit") + + type_text(xWriterEdit, "This is my first writer text written through the UI testing") + + self.ui_test.close_doc() + + def test_goto_first_page(self): + + self.ui_test.create_doc_in_start_center("writer") + + xWriterDoc = self.xUITest.getTopFocusWindow() + xWriterEdit = xWriterDoc.getChild("writer_edit") + + state = get_state_as_dict(xWriterEdit) + while state["CurrentPage"] == "1": + xWriterEdit.executeAction("TYPE", mkPropertyValues({"KEYCODE": "RETURN"})) + state = get_state_as_dict(xWriterEdit) + + xWriterEdit.executeAction("GOTO", mkPropertyValues({"PAGE": "1"})) + + self.ui_test.close_doc() + + + def test_select_text(self): + + self.ui_test.create_doc_in_start_center("writer") + + xWriterDoc = self.xUITest.getTopFocusWindow() + xWriterEdit = xWriterDoc.getChild("writer_edit") + + type_text(xWriterEdit, "This is my first writer text written through the UI testing") + + xWriterEdit.executeAction("SELECT", mkPropertyValues({"START_POS": "0", "END_POS": "4"})) + + self.ui_test.close_doc() + +# vim: set shiftwidth=4 softtabstop=4 expandtab: diff --git a/uitest/writer_tests5/spellDialog.py b/uitest/writer_tests5/spellDialog.py new file mode 100644 index 000000000..e678afea5 --- /dev/null +++ b/uitest/writer_tests5/spellDialog.py @@ -0,0 +1,102 @@ +# +# 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 re + +from uitest.framework import UITestCase +from uitest.uihelper.common import get_state_as_dict + +from libreoffice.linguistic.linguservice import get_spellchecker +from com.sun.star.lang import Locale + +class SpellingAndGrammarDialog(UITestCase): + + def is_supported_locale(self, language, country): + xSpellChecker = get_spellchecker(self.ui_test._xContext) + locales = xSpellChecker.getLocales() + for locale in locales: + if language != None: + if locale.Language != language: + continue + + if country != None: + if locale.Country != country: + continue + + # we found the correct combination + return True + + def launch_dialog(self): + self.ui_test.execute_modeless_dialog_through_command( + ".uno:SpellingAndGrammarDialog") + + return self.xUITest.getTopFocusWindow() + + TDF46852_INPUT = """\ +dogg +dogg +catt dogg +frogg frogg +frogg catt dogg +dogg catt +frog, dogg, catt""" + + TDF46852_REGEX = """\ +([a-z]+) +\\1 +([a-z]+) \\1 +([a-z]+) \\3 +\\3 \\2 \\1 +\\1 \\2 +\\3, \\1, \\2""" + + def test_tdf46852(self): + supported_locale = self.is_supported_locale("en", "US") + if not supported_locale: + self.skipTest("no dictionary support for en_US available") + # This automates the steps described in the bug report tdf#46852 + + # Step 1: Create a document with repetitious misspelled words + self.ui_test.create_doc_in_start_center("writer") + document = self.ui_test.get_component() + cursor = document.getCurrentController().getViewCursor() + # Inserted text must be en_US, so make sure to set language in current location + cursor.CharLocale = Locale("en", "US", "") + input_text = self.TDF46852_INPUT.replace('\n', '\r') # \r = para break + document.Text.insertString(cursor, input_text, False) + + # Step 2: Place cursor on 4th line after second "frogg" + cursor.goUp(2, False) + cursor.goLeft(1, False) + + # Step 3: Initiate spellchecking, and make sure "Check grammar" is + # unchecked + spell_dialog = self.launch_dialog() + checkgrammar = spell_dialog.getChild('checkgrammar') + if get_state_as_dict(checkgrammar)['Selected'] == 'true': + checkgrammar.executeAction('CLICK', ()) + self.assertTrue(get_state_as_dict(checkgrammar)['Selected'] == 'false') + + # Step 4: Repetitively click on "Correct all" for each misspelling + # prompt until end of document is reached. + changeall = spell_dialog.getChild('changeall') + changeall.executeAction("CLICK", ()) + changeall.executeAction("CLICK", ()) + # The third time we click on changeall, the click action is going to + # block while two message boxes are shown, so we need to do this third + # click specially: + self.ui_test.execute_blocking_action( + changeall.executeAction, args=('CLICK', ()), + # Step 5: Confirm to "Continue check at beginning of document" + dialog_handler=lambda dialog : + self.ui_test.execute_blocking_action( + dialog.getChild('yes').executeAction, 'ok', ('CLICK', ()) + ) + ) + + output_text = document.Text.getString().replace('\r\n', '\n') + self.assertTrue(re.match(self.TDF46852_REGEX, output_text)) + diff --git a/uitest/writer_tests5/tdf114724.py b/uitest/writer_tests5/tdf114724.py new file mode 100644 index 000000000..09341149c --- /dev/null +++ b/uitest/writer_tests5/tdf114724.py @@ -0,0 +1,47 @@ +# +# 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.framework import UITestCase +from libreoffice.uno.propertyvalue import mkPropertyValues +from uitest.uihelper.common import get_state_as_dict +from uitest.path import get_srcdir_url + +def get_url_for_data_file(file_name): + return get_srcdir_url() + "/uitest/writer_tests/data/" + file_name + +class tdf114724(UITestCase): + + def test_track_headings_outline(self): + writer_doc = self.ui_test.load_file(get_url_for_data_file("tdf114724.odt")) + xWriterDoc = self.xUITest.getTopFocusWindow() + xWriterEdit = xWriterDoc.getChild("writer_edit") + + self.xUITest.executeCommand(".uno:Sidebar") + xWriterEdit.executeAction("SIDEBAR", mkPropertyValues({"PANEL": "SwNavigatorPanel"})) + + xNavigatorPanel = xWriterEdit.getChild("NavigatorPanelParent") + xNavigatorPanel.executeAction("ROOT", tuple()) + + xWriterEdit.executeAction("FOCUS", tuple()) + + self.ui_test.wait_until_property_is_updated(xNavigatorPanel, "selectedtext", "Headings") + self.assertEqual(get_state_as_dict(xNavigatorPanel)["selectedtext"], "Headings") + self.assertEqual(get_state_as_dict(xNavigatorPanel)["selectioncount"], "1") + for _ in range(0,3): + xWriterEdit.executeAction("TYPE", mkPropertyValues({"KEYCODE": "DOWN"})) + + self.ui_test.wait_until_property_is_updated(xNavigatorPanel, "selectedtext", "HEADING 4") + self.assertEqual(get_state_as_dict(xNavigatorPanel)["selectedtext"], "HEADING 4") + self.assertEqual(get_state_as_dict(xNavigatorPanel)["selectioncount"], "1") + + for _ in range(0,3): + xWriterEdit.executeAction("TYPE", mkPropertyValues({"KEYCODE": "UP"})) + + self.ui_test.wait_until_property_is_updated(xNavigatorPanel, "selectedtext", "HEADING 1") + self.assertEqual(get_state_as_dict(xNavigatorPanel)["selectedtext"], "HEADING 1") + self.assertEqual(get_state_as_dict(xNavigatorPanel)["selectioncount"], "1") + + self.xUITest.executeCommand(".uno:Sidebar") + self.ui_test.close_doc() diff --git a/uitest/writer_tests6/insertBreakDialog.py b/uitest/writer_tests6/insertBreakDialog.py new file mode 100644 index 000000000..291ffdac5 --- /dev/null +++ b/uitest/writer_tests6/insertBreakDialog.py @@ -0,0 +1,85 @@ +# +# 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.framework import UITestCase +from libreoffice.uno.propertyvalue import mkPropertyValues + +class WriterInsertBreakDialog(UITestCase): + + def launch_dialog_and_select_option(self, child): + + self.ui_test.execute_dialog_through_command(".uno:InsertBreak") + xDialog = self.xUITest.getTopFocusWindow() + + xOption = xDialog.getChild(child) + xOption.executeAction("CLICK", tuple()) + + return xDialog + + def getPages(self, total): + document = self.ui_test.get_component() + + xCursor = document.getCurrentController().getViewCursor() + xCursor.jumpToLastPage() + + self.assertEqual(xCursor.getPage(), total) + + def test_insert_line_break(self): + + self.ui_test.create_doc_in_start_center("writer") + + xDialog = self.launch_dialog_and_select_option("linerb") + xOkBtn = xDialog.getChild("ok") + xOkBtn.executeAction("CLICK", tuple()) + + self.getPages(1) + + self.ui_test.close_doc() + + def test_insert_column_break(self): + + self.ui_test.create_doc_in_start_center("writer") + + xDialog = self.launch_dialog_and_select_option("columnrb") + xOkBtn = xDialog.getChild("ok") + xOkBtn.executeAction("CLICK", tuple()) + + self.getPages(1) + + self.ui_test.close_doc() + + def test_insert_page_break(self): + + self.ui_test.create_doc_in_start_center("writer") + + for i in range(9): + with self.subTest(i=i): + xDialog = self.launch_dialog_and_select_option("pagerb") + + xStyleList = xDialog.getChild("stylelb") + xStyleList.executeAction("SELECT", mkPropertyValues({"POS": str(i)})) + + xOkBtn = xDialog.getChild("ok") + xOkBtn.executeAction("CLICK", tuple()) + + self.getPages(i + 2) + + self.ui_test.close_doc() + + def test_cancel_button_insert_line_break_dialog(self): + + self.ui_test.create_doc_in_start_center("writer") + + self.ui_test.execute_dialog_through_command(".uno:InsertBreak") + xDialog = self.xUITest.getTopFocusWindow() + xCancelBtn = xDialog.getChild("cancel") + self.ui_test.close_dialog_through_button(xCancelBtn) + + self.getPages(1) + + self.ui_test.close_doc() + +# vim: set shiftwidth=4 softtabstop=4 expandtab: diff --git a/uitest/writer_tests6/insertPageHeader.py b/uitest/writer_tests6/insertPageHeader.py new file mode 100644 index 000000000..245073ace --- /dev/null +++ b/uitest/writer_tests6/insertPageHeader.py @@ -0,0 +1,72 @@ +# +# 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.framework import UITestCase + +class WriterInsertPageHeader(UITestCase): + + def insert_header(self): + document = self.ui_test.get_component() + + self.assertEqual( + document.StyleFamilies.PageStyles.Standard.HeaderIsOn, False) + + self.xUITest.executeCommand( + ".uno:InsertPageHeader?PageStyle:string=Default%20Page%20Style&On:bool=true") + + self.assertEqual( + document.StyleFamilies.PageStyles.Standard.HeaderIsOn, True) + + def delete_header(self): + document = self.ui_test.get_component() + + self.assertEqual( + document.StyleFamilies.PageStyles.Standard.HeaderIsOn, True) + + self.ui_test.execute_dialog_through_command( + ".uno:InsertPageHeader?PageStyle:string=Default%20Page%20Style&On:bool=false") + + xDialog = self.xUITest.getTopFocusWindow() + + xOption = xDialog.getChild("yes") + xOption.executeAction("CLICK", tuple()) + + self.assertEqual( + document.StyleFamilies.PageStyles.Standard.HeaderIsOn, False) + + def test_header(self): + self.ui_test.create_doc_in_start_center("writer") + + self.insert_header() + + self.delete_header() + + self.ui_test.close_doc() + + def test_tdf107427(self): + self.ui_test.create_doc_in_start_center("writer") + + self.insert_header() + + self.ui_test.execute_dialog_through_command(".uno:InsertTable") + + xInsertDlg = self.xUITest.getTopFocusWindow() + + xOkBtn = xInsertDlg.getChild("ok") + xOkBtn.executeAction("CLICK", tuple()) + + document = self.ui_test.get_component() + + tables = document.getTextTables() + self.assertEqual(len(tables[0].getRows()), 2) + self.assertEqual(len(tables[0].getColumns()), 2) + + self.xUITest.executeCommand(".uno:SelectAll") + + self.delete_header() + + self.ui_test.close_doc() + diff --git a/uitest/writer_tests7/autoredactDialog.py b/uitest/writer_tests7/autoredactDialog.py new file mode 100644 index 000000000..015081431 --- /dev/null +++ b/uitest/writer_tests7/autoredactDialog.py @@ -0,0 +1,198 @@ +# -*- 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.framework import UITestCase +from libreoffice.uno.propertyvalue import mkPropertyValues +from uitest.uihelper.common import get_state_as_dict +from uitest.uihelper.common import type_text +from uitest.uihelper.common import select_pos +from uitest.uihelper.common import select_text +import time +import re +from uitest.debug import sleep + +class AutoRedactDialog(UITestCase): + + add_target_counter = 0 + + # Open the Auto Redact Dialog + def launch_and_get_autoredact_dialog(self): + self.ui_test.execute_dialog_through_command(".uno:AutoRedactDoc") + xDialog = self.xUITest.getTopFocusWindow() + self.assertTrue(xDialog is not None) + return xDialog + + def getText(self, xObj): + return get_state_as_dict(xObj)["Text"] + + def parseTargetContent(self, xObj): + return re.split(r'\t+', self.getText(xObj)) + + def clearTargetsbox(self, xDialog): + xTargetsListbox = xDialog.getChild("targets") + xDeleteBtn = xDialog.getChild("delete") + + child_count = len(xTargetsListbox.getChildren()) + + if child_count < 1: + return + + for i in range(0, child_count): + child = xTargetsListbox.getChild(0) + child.executeAction("SELECT", tuple()) + xDeleteBtn.executeAction("CLICK", tuple()) + + # Verify + self.assertEqual(len(xTargetsListbox.getChildren()), 0) + + + def test_open_AutoRedactDialog_writer(self): + self.ui_test.create_doc_in_start_center("writer") + xDialog = self.launch_and_get_autoredact_dialog() + xcancBtn = xDialog.getChild("cancel") + self.ui_test.close_dialog_through_button(xcancBtn) + self.ui_test.close_doc() + + def test_add_target(self): + self.ui_test.create_doc_in_start_center("writer") + xDialog = self.launch_and_get_autoredact_dialog() + xAddBtn = xDialog.getChild("add") + + # Make sure we are starting with an empty targets list + self.clearTargetsbox(xDialog) + + # Names need to be distinct + # ["target name", "target content"], + targets_list = [ + ["target1", "content1"], + ["target2", "content2"], + ["target3", "content3"], + ] + + def handle_add_dlg(dialog): #handle add target dialog - need special handling + xNewNameTxt=dialog.getChild("name") + xNewContentTxt=dialog.getChild("content") + xOKBtn = dialog.getChild("close") + xTypeList = dialog.getChild("type") #0: Text, 1: Regex, 2: Predefined + + select_pos(xTypeList, 0) #Text + self.assertEqual(int(get_state_as_dict(xTypeList)["SelectEntryPos"]), 0) + + type_text(xNewNameTxt, targets_list[self.add_target_counter][0]) + type_text(xNewContentTxt, targets_list[self.add_target_counter][1]) + + self.ui_test.close_dialog_through_button(xOKBtn) + + for i in range(0, len(targets_list)): + self.add_target_counter = i + self.ui_test.execute_blocking_action(xAddBtn.executeAction, args=('CLICK', ()), + dialog_handler=handle_add_dlg) #close add target dialog with OK button + + # Make sure targets are added successfully + xTargetsListbox = xDialog.getChild("targets") + targets_box_state_dict = get_state_as_dict(xTargetsListbox) + self.assertEqual(int(targets_box_state_dict["Children"]), len(targets_list)) + + # Make sure targets are added with correct names and contents + for i in range(0, len(targets_list)): + child = xTargetsListbox.getChild(i) + child_text = self.parseTargetContent(child) + self.assertEqual(child_text[0], targets_list[i][0]) #name + self.assertEqual(child_text[2], targets_list[i][1]) #content + + xcancBtn = xDialog.getChild("cancel") + self.ui_test.close_dialog_through_button(xcancBtn) + + # Now let's make sure the dialog remembers last state + xDialog = self.launch_and_get_autoredact_dialog() + xTargetsListbox = xDialog.getChild("targets") + targets_box_state_dict = get_state_as_dict(xTargetsListbox) + self.assertEqual(int(targets_box_state_dict["Children"]), len(targets_list)) + + # Make sure targets are remembered with correct names and contents + for i in range(0, len(targets_list)): + child = xTargetsListbox.getChild(i) + child_text = self.parseTargetContent(child) + self.assertEqual(child_text[0], targets_list[i][0]) #name + self.assertEqual(child_text[2], targets_list[i][1]) #content + + xcancBtn = xDialog.getChild("cancel") + self.ui_test.close_dialog_through_button(xcancBtn) + + self.ui_test.close_doc() + + + def test_edit_target(self): + self.ui_test.create_doc_in_start_center("writer") + xDialog = self.launch_and_get_autoredact_dialog() + xAddBtn = xDialog.getChild("add") + xEditBtn = xDialog.getChild("edit") + + # Make sure we are starting with an empty targets list + self.clearTargetsbox(xDialog) + + # We first need to add a target so that we can edit it + def handle_add_dlg(dialog): #handle add target dialog - need special handling + xNewNameTxt=dialog.getChild("name") + xNewContentTxt=dialog.getChild("content") + xOKBtn = dialog.getChild("close") + xTypeList = dialog.getChild("type") #0: Text, 1: Regex, 2: Predefined + + select_pos(xTypeList, 0) #Text + self.assertEqual(int(get_state_as_dict(xTypeList)["SelectEntryPos"]), 0) + + type_text(xNewNameTxt, "TestTarget") + type_text(xNewContentTxt, "TestContent") + + self.ui_test.close_dialog_through_button(xOKBtn) + + self.ui_test.execute_blocking_action(xAddBtn.executeAction, args=('CLICK', ()), + dialog_handler=handle_add_dlg) #close add target dialog with OK button + + # Make sure target is added successfully + xTargetsListbox = xDialog.getChild("targets") + targets_box_state_dict = get_state_as_dict(xTargetsListbox) + self.assertEqual(int(targets_box_state_dict["Children"]), 1) + + # Select the added target + target_entry = xTargetsListbox.getChild(0) + target_entry.executeAction("SELECT", tuple()) + + # Now edit the target + def handle_edit_dlg(dialog): #handle add target dialog - need special handling + xNameTxt=dialog.getChild("name") + xContentTxt=dialog.getChild("content") + xOKBtn = dialog.getChild("close") + + xNameTxt.executeAction("CLEAR", tuple()) + xContentTxt.executeAction("CLEAR", tuple()) + + type_text(xNameTxt, "TestTargetEdited") + type_text(xContentTxt, "TestContentEdited") + + self.ui_test.close_dialog_through_button(xOKBtn) + + self.ui_test.execute_blocking_action(xEditBtn.executeAction, args=('CLICK', ()), + dialog_handler=handle_edit_dlg) #close add target dialog with OK button + + # Make sure target is still there + xTargetsListbox = xDialog.getChild("targets") + targets_box_state_dict = get_state_as_dict(xTargetsListbox) + self.assertEqual(int(targets_box_state_dict["Children"]), 1) + + # Make sure target has the new values + target_entry = xTargetsListbox.getChild(0) + target_text = self.parseTargetContent(target_entry) + self.assertEqual(target_text[0], "TestTargetEdited") #name + self.assertEqual(target_text[2], "TestContentEdited") #content + + xcancBtn = xDialog.getChild("cancel") + self.ui_test.close_dialog_through_button(xcancBtn) + + self.ui_test.close_doc() + + +# vim: set shiftwidth=4 softtabstop=4 expandtab: diff --git a/uitest/writer_tests7/goToPage.py b/uitest/writer_tests7/goToPage.py new file mode 100644 index 000000000..d20f042df --- /dev/null +++ b/uitest/writer_tests7/goToPage.py @@ -0,0 +1,48 @@ +# +# 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.framework import UITestCase +from libreoffice.uno.propertyvalue import mkPropertyValues +from uitest.uihelper.common import get_state_as_dict +import time +from uitest.path import get_srcdir_url + +def get_url_for_data_file(file_name): + return get_srcdir_url() + "/uitest/writer_tests/data/" + file_name + +class GoToPage_dialog(UITestCase): + + def test_go_to_page(self): + writer_doc = self.ui_test.load_file(get_url_for_data_file("3pages.odt")) + xWriterDoc = self.xUITest.getTopFocusWindow() + xWriterEdit = xWriterDoc.getChild("writer_edit") + + self.ui_test.execute_dialog_through_command(".uno:GotoPage") + xDialog = self.xUITest.getTopFocusWindow() + xPageText = xDialog.getChild("page") + xPageText.executeAction("TYPE", mkPropertyValues({"TEXT":"2"})) + xOkBtn = xDialog.getChild("ok") + xOkBtn.executeAction("CLICK", tuple()) + + self.assertEqual(get_state_as_dict(xWriterEdit)["CurrentPage"], "2") + + self.ui_test.execute_dialog_through_command(".uno:GotoPage") + xDialog = self.xUITest.getTopFocusWindow() + xPageText = xDialog.getChild("page") + xPageText.executeAction("TYPE", mkPropertyValues({"TEXT":"3a"})) + xOkBtn = xDialog.getChild("ok") + xOkBtn.executeAction("CLICK", tuple()) + + self.assertEqual(get_state_as_dict(xWriterEdit)["CurrentPage"], "3") + + # check cancel button + self.ui_test.execute_dialog_through_command(".uno:GotoPage") + xDialog = self.xUITest.getTopFocusWindow() + xCancelBtn = xDialog.getChild("cancel") + self.ui_test.close_dialog_through_button(xCancelBtn) + + self.assertEqual(get_state_as_dict(xWriterEdit)["CurrentPage"], "3") + + self.ui_test.close_doc() diff --git a/uitest/writer_tests8/customizeDialog.py b/uitest/writer_tests8/customizeDialog.py new file mode 100644 index 000000000..92fddfdff --- /dev/null +++ b/uitest/writer_tests8/customizeDialog.py @@ -0,0 +1,92 @@ +# -*- 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 + +from uitest.framework import UITestCase +from libreoffice.uno.propertyvalue import mkPropertyValues +from uitest.uihelper.common import get_state_as_dict +from uitest.uihelper.common import select_pos + +class ConfigureDialog(UITestCase): + + def test_open_ConfigureDialog_writer(self): + + self.ui_test.create_doc_in_start_center("writer") + self.ui_test.execute_dialog_through_command(".uno:ConfigureDialog") + xDialog = self.xUITest.getTopFocusWindow() + + xcancBtn = xDialog.getChild("cancel") + xcancBtn.executeAction("CLICK", tuple()) + + self.ui_test.close_doc() + + def test_search_filter(self): + self.ui_test.create_doc_in_start_center("writer") + self.ui_test.execute_dialog_through_command(".uno:ConfigureDialog") + xDialog = self.xUITest.getTopFocusWindow() + + xfunc = xDialog.getChild("functions") + xSearch = xDialog.getChild("searchEntry") + + initialEntryCount = get_state_as_dict(xfunc)["Children"] + self.assertTrue(initialEntryCount != 0) + + xSearch.executeAction("SET", mkPropertyValues({"TEXT":"format"})) + + # Wait for the search/filter op to be completed + timeout = time.time() + 1 + while time.time() < timeout: + filteredEntryCount = get_state_as_dict(xfunc)["Children"] + if filteredEntryCount != initialEntryCount: + break + time.sleep(0.1) + + self.assertTrue(filteredEntryCount < initialEntryCount) + + xSearch.executeAction("CLEAR", tuple()) + + # Wait for the search/filter op to be completed + timeout = time.time() + 1 + while time.time() < timeout: + finalEntryCount = get_state_as_dict(xfunc)["Children"] + if finalEntryCount != filteredEntryCount: + break + time.sleep(0.1) + + self.assertEqual(initialEntryCount, finalEntryCount) + + + xcancBtn = xDialog.getChild("cancel") #button Cancel + xcancBtn.executeAction("CLICK", tuple()) #click the button + + self.ui_test.close_doc() + + def test_category_listbox(self): + self.ui_test.create_doc_in_start_center("writer") + self.ui_test.execute_dialog_through_command(".uno:ConfigureDialog") + xDialog = self.xUITest.getTopFocusWindow() + + xFunc = xDialog.getChild("functions") + xCategory = xDialog.getChild("commandcategorylist") + + initialEntryCount = get_state_as_dict(xFunc)["Children"] + self.assertTrue(initialEntryCount != 0) + + select_pos(xCategory, "1") + filteredEntryCount = get_state_as_dict(xFunc)["Children"] + self.assertTrue(filteredEntryCount < initialEntryCount) + + select_pos(xCategory, "0") + finalEntryCount = get_state_as_dict(xFunc)["Children"] + self.assertEqual(initialEntryCount, finalEntryCount) + + xcancBtn = xDialog.getChild("cancel") #button Cancel + xcancBtn.executeAction("CLICK", tuple()) #click the button + + self.ui_test.close_doc() + +# vim: set shiftwidth=4 softtabstop=4 expandtab: diff --git a/uitest/writer_tests8/tdf79236.py b/uitest/writer_tests8/tdf79236.py new file mode 100644 index 000000000..8585e48d8 --- /dev/null +++ b/uitest/writer_tests8/tdf79236.py @@ -0,0 +1,124 @@ +# +# 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.framework import UITestCase +import time +from uitest.uihelper.common import get_state_as_dict, type_text + +class tdf79236(UITestCase): + + def test_paragraph(self): + + self.ui_test.create_doc_in_start_center("writer") + + xWriterDoc = self.xUITest.getTopFocusWindow() + xWriterEdit = xWriterDoc.getChild("writer_edit") + + type_text(xWriterEdit, "Test for tdf79236") + + document = self.ui_test.get_component() + + selection = self.xUITest.executeCommand(".uno:SelectAll") + + self.assertEqual(document.CurrentSelection.getByIndex(0).ParaLeftMargin, 0) + self.assertEqual(document.CurrentSelection.getByIndex(0).ParaRightMargin, 0) + self.assertEqual(document.CurrentSelection.getByIndex(0).ParaTopMargin, 0) + self.assertEqual(document.CurrentSelection.getByIndex(0).ParaBottomMargin, 0) + self.assertEqual(document.CurrentSelection.getByIndex(0).ParaFirstLineIndent, 0) + + self.assertEqual(document.CurrentSelection.getByIndex(0).String, "Test for tdf79236") + + self.ui_test.execute_dialog_through_command(".uno:ParagraphDialog") + + xParagraphDlg = self.xUITest.getTopFocusWindow() + + + xLeftSpnBtn = xParagraphDlg.getChild("spinED_LEFTINDENT") + for _ in range(0,20): + xLeftSpnBtn.executeAction("UP", tuple()) + + xRightSpnBtn = xParagraphDlg.getChild("spinED_RIGHTINDENT") + for _ in range(0,20): + xRightSpnBtn.executeAction("UP", tuple()) + + + xLineSpnBtn = xParagraphDlg.getChild("spinED_FLINEINDENT") + for _ in range(0,20): + xLineSpnBtn.executeAction("UP", tuple()) + + + xBottomSpnBtn = xParagraphDlg.getChild("spinED_BOTTOMDIST") + for _ in range(0,20): + xBottomSpnBtn.executeAction("UP", tuple()) + + xTopSpnBtn = xParagraphDlg.getChild("spinED_TOPDIST") + for _ in range(0,20): + xTopSpnBtn.executeAction("UP", tuple()) + + xOkBtn = xParagraphDlg.getChild("ok") + xOkBtn.executeAction("CLICK", tuple()) + + self.assertEqual(document.CurrentSelection.getByIndex(0).ParaLeftMargin, 3704) + self.assertEqual(document.CurrentSelection.getByIndex(0).ParaRightMargin, 3704) + self.assertEqual(document.CurrentSelection.getByIndex(0).ParaTopMargin, 5503) + self.assertEqual(document.CurrentSelection.getByIndex(0).ParaBottomMargin, 5503) + self.assertEqual(document.CurrentSelection.getByIndex(0).ParaFirstLineIndent, 3704) + + self.ui_test.execute_dialog_through_command(".uno:ParagraphDialog") + + xParagraphDlg = self.xUITest.getTopFocusWindow() + + xLeftSpnBtn = xParagraphDlg.getChild("spinED_LEFTINDENT") + for _ in range(0,20): + xLeftSpnBtn.executeAction("DOWN", tuple()) + + xRightSpnBtn = xParagraphDlg.getChild("spinED_RIGHTINDENT") + for _ in range(0,20): + xRightSpnBtn.executeAction("DOWN", tuple()) + + + xLineSpnBtn = xParagraphDlg.getChild("spinED_FLINEINDENT") + for _ in range(0,20): + xLineSpnBtn.executeAction("DOWN", tuple()) + + xBottomSpnBtn = xParagraphDlg.getChild("spinED_BOTTOMDIST") + for _ in range(0,20): + xBottomSpnBtn.executeAction("DOWN", tuple()) + + xTopSpnBtn = xParagraphDlg.getChild("spinED_TOPDIST") + for _ in range(0,20): + xTopSpnBtn.executeAction("DOWN", tuple()) + + xOkBtn = xParagraphDlg.getChild("ok") + self.ui_test.close_dialog_through_button(xOkBtn) + + self.assertEqual(document.CurrentSelection.getByIndex(0).ParaLeftMargin, 0) + self.assertEqual(document.CurrentSelection.getByIndex(0).ParaRightMargin, 0) + self.assertEqual(document.CurrentSelection.getByIndex(0).ParaTopMargin, 0) + self.assertEqual(document.CurrentSelection.getByIndex(0).ParaBottomMargin, 0) + self.assertEqual(document.CurrentSelection.getByIndex(0).ParaFirstLineIndent, 0) + + self.xUITest.executeCommand(".uno:Undo") + + self.assertEqual(document.CurrentSelection.getByIndex(0).ParaLeftMargin, 3704) + self.assertEqual(document.CurrentSelection.getByIndex(0).ParaRightMargin, 3704) + self.assertEqual(document.CurrentSelection.getByIndex(0).ParaTopMargin, 5503) + self.assertEqual(document.CurrentSelection.getByIndex(0).ParaBottomMargin, 5503) + self.assertEqual(document.CurrentSelection.getByIndex(0).ParaFirstLineIndent, 3704) + + self.xUITest.executeCommand(".uno:Undo") + + self.assertEqual(document.CurrentSelection.getByIndex(0).ParaLeftMargin, 0) + self.assertEqual(document.CurrentSelection.getByIndex(0).ParaRightMargin, 0) + self.assertEqual(document.CurrentSelection.getByIndex(0).ParaTopMargin, 0) + self.assertEqual(document.CurrentSelection.getByIndex(0).ParaBottomMargin, 0) + self.assertEqual(document.CurrentSelection.getByIndex(0).ParaFirstLineIndent, 0) + + self.assertEqual(document.CurrentSelection.getByIndex(0).String, "Test for tdf79236") + + self.ui_test.close_doc() + +# vim: set shiftwidth=4 softtabstop=4 expandtab: |