[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