[Libreoffice-commits] core.git: 7 commits - include/svtools svtools/inc svtools/source uitest/calc_tests uitest/impress_tests uitest/libreoffice uitest/uitest vcl/source
Markus Mohrhard
markus.mohrhard at googlemail.com
Thu Sep 29 15:31:42 UTC 2016
include/svtools/simptabl.hxx | 3 +
svtools/inc/uitest/uiobject.hxx | 17 +++++++
svtools/source/contnr/simptabl.cxx | 11 ++++
svtools/source/uitest/uiobject.cxx | 28 ++++++++++++
uitest/calc_tests/tdf96453.py | 58 +++++++++++++++++++++++++-
uitest/impress_tests/start.py | 10 +---
uitest/libreoffice/calc/conditional_format.py | 14 ++++++
uitest/libreoffice/calc/document.py | 11 ++++
uitest/uitest/test.py | 23 ++++++++--
vcl/source/window/dialog.cxx | 7 +++
10 files changed, 172 insertions(+), 10 deletions(-)
New commits:
commit 1a142d1dbdc33c9c4694e04f3b8b89848da47da6
Author: Markus Mohrhard <markus.mohrhard at googlemail.com>
Date: Thu Sep 29 17:09:47 2016 +0200
add complete test for tdf#96453
This is the fourth and final part of the UI test tutorial.
The test combines the previous 3 items in the final test. The original test
from the first tutorial is used as a template, the SvSimpleTable support
is used to assert that the table contains the correct amount of entries,
and the UNO helper methods that the document contains the correct amount
of conditional formats.
Change-Id: Ibe2047e10ff6368c145c88b2bcca9648aa7f8f54
diff --git a/uitest/calc_tests/tdf96453.py b/uitest/calc_tests/tdf96453.py
index 478a7a1..020b901 100644
--- a/uitest/calc_tests/tdf96453.py
+++ b/uitest/calc_tests/tdf96453.py
@@ -10,6 +10,10 @@ from uitest.framework import UITestCase
import os
import pathlib
+from uitest.uihelper.common import get_state_as_dict
+from libreoffice.calc.document import get_sheet_from_doc
+from libreoffice.calc.conditional_format import get_conditional_format_from_sheet
+
def get_data_dir():
current_dir = os.path.dirname(os.path.realpath(__file__))
return os.path.join(current_dir, "data")
@@ -23,7 +27,6 @@ class ConditionalFormatDlgTest(UITestCase):
def test_simple_open_manager(self):
calc_doc = self.ui_test.load_file(get_url_for_data_file("tdf96453.ods"))
- print(dir(calc_doc))
self.ui_test.execute_dialog_through_command(".uno:ConditionalFormatManagerDialog")
@@ -34,4 +37,57 @@ class ConditionalFormatDlgTest(UITestCase):
self.ui_test.close_doc()
+ def test_tdf96453(self):
+
+ calc_doc = self.ui_test.load_file(get_url_for_data_file("tdf96453.ods"))
+
+ sheet = get_sheet_from_doc(calc_doc, 0)
+ conditional_format_list = get_conditional_format_from_sheet(sheet)
+ self.assertEqual(conditional_format_list.getLength(), 2)
+
+ self.ui_test.execute_dialog_through_command(".uno:ConditionalFormatManagerDialog")
+
+ xCondFormatMgr = self.xUITest.getTopFocusWindow()
+
+ # check that we have exactly two conditional formats in the beginning
+ xList = xCondFormatMgr.getChild("CONTAINER")
+ list_state = get_state_as_dict(xList)
+ self.assertEqual(list_state['Children'], '2')
+
+ # remove one conditional format
+ xRemoveBtn = xCondFormatMgr.getChild("remove")
+ xRemoveBtn.executeAction("CLICK", tuple())
+
+ # check that the table only shows one
+ # but the document still contains two
+ list_state = get_state_as_dict(xList)
+ self.assertEqual(list_state['Children'], '1')
+
+ self.assertEqual(conditional_format_list.getLength(), 2)
+
+ # add a new conditional format through the add button
+ xAddBtn = xCondFormatMgr.getChild("add")
+ self.ui_test.execute_dialog_through_action(xAddBtn, "CLICK", event_name = "ModelessDialogVisible")
+
+ xCondFormatDlg = self.xUITest.getTopFocusWindow()
+ xCondFormatOkBtn = xCondFormatDlg.getChild("ok")
+ self.ui_test.close_dialog_through_button(xCondFormatOkBtn)
+
+ # we need to get a pointer again as the old window has been deleted
+ xCondFormatMgr = self.xUITest.getTopFocusWindow()
+
+ # check again that we now have 2 and not 3 entries in the list
+ # and still only 2 conditional formats in the document
+ xList = xCondFormatMgr.getChild("CONTAINER")
+ list_state = get_state_as_dict(xList)
+ self.assertEqual(list_state['Children'], '2')
+
+ self.assertEqual(conditional_format_list.getLength(), 2)
+
+ # close the conditional format manager
+ xCancelBtn = xCondFormatMgr.getChild("cancel")
+ xCancelBtn.executeAction("CLICK", tuple())
+
+ self.ui_test.close_doc()
+
# vim:set shiftwidth=4 softtabstop=4 expandtab: */
commit 3da8806e079c8fa75330100e5c17658b4f7e79a0
Author: Markus Mohrhard <markus.mohrhard at googlemail.com>
Date: Thu Sep 29 17:03:06 2016 +0200
add helper methods to deal with Calc UNO
This is the third part of the UI Test tutorial.
The code in uitest/libreoffice is generally useful UNO code that
allows to interact with LibreOffice. This code should be independent
of the UI testing framework and provide external developers a
helpful starting point to writer python extensions.
Change-Id: Ia1429577affd98dcf3f1aee3da3a7256499a1c78
diff --git a/uitest/libreoffice/calc/conditional_format.py b/uitest/libreoffice/calc/conditional_format.py
new file mode 100644
index 0000000..adffc29
--- /dev/null
+++ b/uitest/libreoffice/calc/conditional_format.py
@@ -0,0 +1,14 @@
+# -*- 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/.
+#
+
+# this file provides methods to interact with the new conditional format API
+
+def get_conditional_format_from_sheet(sheet):
+ 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 0000000..356c5ec
--- /dev/null
+++ b/uitest/libreoffice/calc/document.py
@@ -0,0 +1,11 @@
+# -*- 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_sheet_from_doc(document, index):
+ return document.getSheets().getByIndex(index)
+
+# vim:set shiftwidth=4 softtabstop=4 expandtab: */
commit a801155464cf479b3fbf30f27e3f51030d69ba14
Author: Markus Mohrhard <markus.mohrhard at googlemail.com>
Date: Thu Sep 29 17:08:48 2016 +0200
add introspection support for SvSimpleTable
This is the second part of the UI test tutorial.
The tutorial shows how to add introspection support to a new
vcl::Window based UI object.
Change-Id: I2b3ed68d313749787869c7e85f2e27c9d01fff4a
diff --git a/include/svtools/simptabl.hxx b/include/svtools/simptabl.hxx
index 7e46275..051e991 100644
--- a/include/svtools/simptabl.hxx
+++ b/include/svtools/simptabl.hxx
@@ -40,10 +40,13 @@ public:
virtual void dispose() override;
void SetTable(SvSimpleTable* pTable);
+ SvSimpleTable* GetTable();
virtual void Resize() override;
virtual void GetFocus() override;
+
+ virtual FactoryFunction GetUITestFactory() const override;
};
class SVT_DLLPUBLIC SvSimpleTable : public SvHeaderTabListBox
diff --git a/svtools/inc/uitest/uiobject.hxx b/svtools/inc/uitest/uiobject.hxx
index 93cfc15..873c3d5 100644
--- a/svtools/inc/uitest/uiobject.hxx
+++ b/svtools/inc/uitest/uiobject.hxx
@@ -11,6 +11,7 @@
class SvTreeListBox;
class SvTreeListEntry;
+class SvSimpleTable;
class TreeListUIObject : public WindowUIObject
{
@@ -61,4 +62,20 @@ private:
SvTreeListEntry* mpEntry;
};
+class SimpleTableUIObject : public TreeListUIObject
+{
+public:
+ SimpleTableUIObject(VclPtr<SvSimpleTable> xTable);
+
+ virtual StringMap get_state() override;
+
+ static std::unique_ptr<UIObject> createFromContainer(vcl::Window* pWindow);
+
+protected:
+ virtual OUString get_type() const override;
+
+private:
+ VclPtr<SvSimpleTable> mxTable;
+};
+
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svtools/source/contnr/simptabl.cxx b/svtools/source/contnr/simptabl.cxx
index 8515183..88a8cb3 100644
--- a/svtools/source/contnr/simptabl.cxx
+++ b/svtools/source/contnr/simptabl.cxx
@@ -24,6 +24,7 @@
#include <vcl/builderfactory.hxx>
#include <vcl/svapp.hxx>
#include <vcl/settings.hxx>
+#include <uitest/uiobject.hxx>
SvSimpleTableContainer::SvSimpleTableContainer(vcl::Window* pParent, WinBits nBits)
: Control(pParent, nBits)
@@ -50,6 +51,11 @@ void SvSimpleTableContainer::SetTable(SvSimpleTable* pTable)
m_pTable = pTable;
}
+SvSimpleTable* SvSimpleTableContainer::GetTable()
+{
+ return m_pTable.get();
+}
+
bool SvSimpleTableContainer::PreNotify( NotifyEvent& rNEvt )
{
bool bResult = true;
@@ -84,6 +90,11 @@ void SvSimpleTableContainer::GetFocus()
m_pTable->GrabFocus();
}
+FactoryFunction SvSimpleTableContainer::GetUITestFactory() const
+{
+ return SimpleTableUIObject::createFromContainer;
+}
+
// SvSimpleTable ------------------------------------------------------------
SvSimpleTable::SvSimpleTable(SvSimpleTableContainer& rParent, WinBits nBits):
diff --git a/svtools/source/uitest/uiobject.cxx b/svtools/source/uitest/uiobject.cxx
index 6156f44..0a4550f 100644
--- a/svtools/source/uitest/uiobject.cxx
+++ b/svtools/source/uitest/uiobject.cxx
@@ -10,6 +10,7 @@
#include "uitest/uiobject.hxx"
#include <svtools/treelistbox.hxx>
+#include <svtools/simptabl.hxx>
TreeListUIObject::TreeListUIObject(VclPtr<SvTreeListBox> xTreeList):
WindowUIObject(xTreeList),
@@ -140,4 +141,31 @@ OUString TreeListEntryUIObject::get_type() const
return OUString("TreeListEntry");
}
+SimpleTableUIObject::SimpleTableUIObject(VclPtr<SvSimpleTable> xTable):
+ TreeListUIObject(xTable),
+ mxTable(xTable)
+{
+}
+
+StringMap SimpleTableUIObject::get_state()
+{
+ StringMap aMap = TreeListUIObject::get_state();
+
+ aMap["ColumnCount"] = OUString::number(mxTable->TabCount());
+
+ return aMap;
+}
+
+OUString SimpleTableUIObject::UIObject::get_type() const
+{
+ return OUString("SimpleTable");
+}
+
+std::unique_ptr<UIObject> SimpleTableUIObject::createFromContainer(vcl::Window* pWindow)
+{
+ SvSimpleTableContainer* pTableContainer = dynamic_cast<SvSimpleTableContainer*>(pWindow);
+ assert(pTableContainer);
+ return std::unique_ptr<UIObject>(new SimpleTableUIObject(pTableContainer->GetTable()));
+}
+
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
commit d4e19a2394f58191b4d60f445988450142650679
Author: Markus Mohrhard <markus.mohrhard at googlemail.com>
Date: Thu Sep 29 16:36:05 2016 +0200
allow to listen to different events
Change-Id: I4121d35e8052cf25bc2e6089e45c62c3bbcc859a
diff --git a/uitest/uitest/test.py b/uitest/uitest/test.py
index 3720958..0883425 100644
--- a/uitest/uitest/test.py
+++ b/uitest/uitest/test.py
@@ -79,11 +79,11 @@ class UITest(object):
raise DialogNotExecutedException(command)
- def execute_dialog_through_action(self, ui_object, action, parameters = None):
+ def execute_dialog_through_action(self, ui_object, action, parameters = None, event_name = "DialogExecute"):
if parameters is None:
parameters = tuple()
- with EventListener(self._xContext, "DialogExecute") as event:
+ with EventListener(self._xContext, event_name) as event:
ui_object.executeAction(action, parameters)
time_ = 0
while time_ < 30:
@@ -92,7 +92,7 @@ class UITest(object):
return
time_ += DEFAULT_SLEEP
time.sleep(DEFAULT_SLEEP)
- raise DialogNotExecutedException(command)
+ raise DialogNotExecutedException(action)
def create_doc_in_start_center(self, app):
xStartCenter = self._xUITest.getTopFocusWindow()
commit d5c8fa716cfe8599107979db3966e14e8d220c44
Author: Markus Mohrhard <markus.mohrhard at googlemail.com>
Date: Thu Sep 29 16:35:02 2016 +0200
use the new close dialog abstraction in impress
Change-Id: I6fef4bfa5b964c83b21c73ec406bf7fc10958a41
diff --git a/uitest/impress_tests/start.py b/uitest/impress_tests/start.py
index aada10b..b489b7e 100644
--- a/uitest/impress_tests/start.py
+++ b/uitest/impress_tests/start.py
@@ -20,7 +20,7 @@ class SimpleImpressTest(UITestCase):
xTemplateDlg = self.xUITest.getTopFocusWindow()
xCancelBtn = xTemplateDlg.getChild("cancel")
- xCancelBtn.executeAction("CLICK", tuple())
+ self.ui_test.close_dialog_through_button(xCancelBtn)
xImpressDoc = self.xUITest.getTopFocusWindow()
@@ -35,10 +35,9 @@ class SimpleImpressTest(UITestCase):
xTemplateDlg = self.xUITest.getTopFocusWindow()
xCancelBtn = xTemplateDlg.getChild("cancel")
- xCancelBtn.executeAction("CLICK", tuple())
+ self.ui_test.close_dialog_through_button(xCancelBtn)
xImpressDoc = self.xUITest.getTopFocusWindow()
- print(xImpressDoc.getChildren())
xEditWin = xImpressDoc.getChild("impress_win")
@@ -52,10 +51,9 @@ class SimpleImpressTest(UITestCase):
xTemplateDlg = self.xUITest.getTopFocusWindow()
xCancelBtn = xTemplateDlg.getChild("cancel")
- xCancelBtn.executeAction("CLICK", tuple())
+ self.ui_test.close_dialog_through_button(xCancelBtn)
xImpressDoc = self.xUITest.getTopFocusWindow()
- print(xImpressDoc.getChildren())
xEditWin = xImpressDoc.getChild("impress_win")
@@ -67,7 +65,7 @@ class SimpleImpressTest(UITestCase):
xTemplateDlg = self.xUITest.getTopFocusWindow()
xCancelBtn = xTemplateDlg.getChild("cancel")
- xCancelBtn.executeAction("CLICK", tuple())
+ self.ui_test.close_dialog_through_button(xCancelBtn)
xImpressDoc = self.xUITest.getTopFocusWindow()
print(xImpressDoc.getChildren())
commit 0a4eecd49a6744838a23a0a6804a851511aed246
Author: Markus Mohrhard <markus.mohrhard at googlemail.com>
Date: Thu Sep 29 16:32:31 2016 +0200
make use of the new event for closed dialogs
Change-Id: I59102fda8390d9594999ceaa45105e38ecbc970e
diff --git a/uitest/uitest/test.py b/uitest/uitest/test.py
index 2860c02..3720958 100644
--- a/uitest/uitest/test.py
+++ b/uitest/uitest/test.py
@@ -17,6 +17,11 @@ class DialogNotExecutedException(Exception):
def __str__(self):
return "Dialog not executed for: " + self.command
+class DialogNotClosedException(Exception):
+
+ def __str__(self):
+ return "Dialog was not closed"
+
class UITest(object):
def __init__(self, xUITest, xContext):
@@ -105,6 +110,18 @@ class UITest(object):
# report a failure here
+ def close_dialog_through_button(self, button):
+ with EventListener(self._xContext, "DialogClosed" ) as event:
+ button.executeAction("CLICK", tuple())
+ time_ = 0
+ while time_ < 30:
+ if event.executed:
+ time.sleep(DEFAULT_SLEEP)
+ return
+ time_ += DEFAULT_SLEEP
+ time.sleep(DEFAULT_SLEEP)
+ raise DialogNotClosedException()
+
def close_doc(self):
with EventListener(self._xContext, ["DialogExecute", "OnViewClosed"] ) as event:
self._xUITest.executeCommand(".uno:CloseDoc")
commit 814266e801fbc28ea431ac8b13bb40d8a8243cc7
Author: Markus Mohrhard <markus.mohrhard at googlemail.com>
Date: Thu Sep 29 16:33:23 2016 +0200
send an event when the dialog is actually closed
The last data structures in vcl are only updated when the dialog is disposed. Especially mpFirstFrame
is not updated until the dispose. So we need to wait until that point for the UI tests.
Change-Id: I7432600e879c4c7dcffa445ac6b3cd228d0aa856
diff --git a/vcl/source/window/dialog.cxx b/vcl/source/window/dialog.cxx
index 910d6ee..07ceaaa 100644
--- a/vcl/source/window/dialog.cxx
+++ b/vcl/source/window/dialog.cxx
@@ -581,6 +581,13 @@ void Dialog::dispose()
mpActionArea.clear();
mpContentArea.clear();
SystemWindow::dispose();
+
+ css::uno::Reference< css::uno::XComponentContext > xContext(
+ comphelper::getProcessComponentContext() );
+ css::uno::Reference<css::frame::XGlobalEventBroadcaster> xEventBroadcaster(css::frame::theGlobalEventBroadcaster::get(xContext), css::uno::UNO_QUERY_THROW);
+ css::document::DocumentEvent aObject;
+ aObject.EventName = "DialogClosed";
+ xEventBroadcaster->documentEventOccured(aObject);
}
IMPL_LINK_NOARG_TYPED(Dialog, ImplAsyncCloseHdl, void*, void)
More information about the Libreoffice-commits
mailing list