diff --git a/chart2/source/controller/inc/uiobject.hxx b/chart2/source/controller/inc/uiobject.hxx index 917ba322bf5e..6de63f5d3fdf 100644 --- a/chart2/source/controller/inc/uiobject.hxx +++ b/chart2/source/controller/inc/uiobject.hxx @@ -32,6 +32,8 @@ public: virtual OUString get_type() const override; + virtual bool equals(const UIObject& rOther) const override; + private: OUString maCID; diff --git a/chart2/source/controller/uitest/uiobject.cxx b/chart2/source/controller/uitest/uiobject.cxx index 783a91982f84..c75f15c3885c 100644 --- a/chart2/source/controller/uitest/uiobject.cxx +++ b/chart2/source/controller/uitest/uiobject.cxx @@ -95,6 +95,14 @@ OUString ChartUIObject::get_type() const return "ChartUIObject for type: "; } +bool ChartUIObject::equals(const UIObject& rOther) const +{ + const ChartUIObject* pOther = dynamic_cast(&rOther); + if (!pOther) + return false; + return mxChartWindow.get() == pOther->mxChartWindow.get(); +} + ChartWindowUIObject::ChartWindowUIObject(const VclPtr& xChartWindow): WindowUIObject(xChartWindow), mxChartWindow(xChartWindow) diff --git a/include/vcl/uitest/uiobject.hxx b/include/vcl/uitest/uiobject.hxx index d27140b2c21b..8f1624dc7f7a 100644 --- a/include/vcl/uitest/uiobject.hxx +++ b/include/vcl/uitest/uiobject.hxx @@ -113,6 +113,11 @@ public: * Gets the corresponding Action string for the event. */ virtual OUString get_action(VclEventId nEvent) const; + + /** + * Does this represent the same underlying UI widget as rOther? + */ + virtual bool equals(const UIObject& rOther) const = 0; }; class UITEST_DLLPUBLIC WindowUIObject : public UIObject @@ -144,6 +149,8 @@ public: static std::unique_ptr create(vcl::Window* pWindow); + virtual bool equals(const UIObject& rOther) const override; + protected: virtual OUString get_name() const; @@ -505,6 +512,8 @@ public: virtual OUString get_type() const override; + virtual bool equals(const UIObject& rOther) const override; + private: SvTreeListEntry* getEntry() const; diff --git a/offapi/com/sun/star/ui/test/XUIObject.idl b/offapi/com/sun/star/ui/test/XUIObject.idl index 8f5febffb17e..4f37b11568e1 100644 --- a/offapi/com/sun/star/ui/test/XUIObject.idl +++ b/offapi/com/sun/star/ui/test/XUIObject.idl @@ -22,6 +22,11 @@ interface XUIObject sequence getChildren(); string getHierarchy(); + + /** Return true if the other XUIObject represents the same underlying vcl widget. + This is necessary because we return a new XUIObject every time we call getChild. + */ + boolean equals([in] XUIObject other); }; }; }; }; }; }; diff --git a/sd/source/ui/uitest/uiobject.cxx b/sd/source/ui/uitest/uiobject.cxx index 00884fc90d6f..2c96b9495b14 100644 --- a/sd/source/ui/uitest/uiobject.cxx +++ b/sd/source/ui/uitest/uiobject.cxx @@ -29,6 +29,8 @@ public: SdrObject* get_object() override; + virtual bool equals(const UIObject& rOther) const override; + private: VclPtr mxWindow; @@ -74,6 +76,14 @@ ImpressSdrObject::ImpressSdrObject(const VclPtr& xImpressWin, OUStri SdrObject* ImpressSdrObject::get_object() { return getObject(mxWindow, maName); } +bool ImpressSdrObject::equals(const UIObject& rOther) const +{ + const ImpressSdrObject* pOther = dynamic_cast(&rOther); + if (!pOther) + return false; + return mxWindow.get() == pOther->mxWindow.get(); +} + ImpressWindowUIObject::ImpressWindowUIObject(const VclPtr& xWindow) : WindowUIObject(xWindow) , mxWindow(xWindow) diff --git a/uitest/uitest/test.py b/uitest/uitest/test.py index fbe5d2a87c99..e6491af3f67f 100644 --- a/uitest/uitest/test.py +++ b/uitest/uitest/test.py @@ -128,18 +128,18 @@ class UITest(object): while not event.executed: time.sleep(DEFAULT_SLEEP) dialog = self._xUITest.getTopFocusWindow() - if parent == dialog: + if parent.equals(dialog): raise Exception("executing the action did not open the dialog") try: yield dialog except: if not close_button: if 'cancel' in dialog.getChildren(): - self.close_dialog_through_button(dialog.getChild("cancel")) + self.close_dialog_through_button(dialog.getChild("cancel"), dialog) raise finally: if close_button: - self.close_dialog_through_button(dialog.getChild(close_button)) + self.close_dialog_through_button(dialog.getChild(close_button), dialog) # Calls UITest.close_dialog_through_button at exit @contextmanager @@ -189,8 +189,9 @@ class UITest(object): return time.sleep(DEFAULT_SLEEP) - def close_dialog_through_button(self, button): - dialog = self._xUITest.getTopFocusWindow() + def close_dialog_through_button(self, button, dialog=None): + if dialog is None: + dialog = self._xUITest.getTopFocusWindow() with EventListener(self._xContext, "DialogClosed" ) as event: button.executeAction("CLICK", tuple()) while True: @@ -199,7 +200,7 @@ class UITest(object): break time.sleep(DEFAULT_SLEEP) parent = self._xUITest.getTopFocusWindow() - if parent == dialog: + if parent.equals(dialog): raise Exception("executing the action did not close the dialog") def close_doc(self): @@ -252,11 +253,11 @@ class UITest(object): except: if not close_button: if 'cancel' in xDialog.getChildren(): - self.close_dialog_through_button(xDialog.getChild("cancel")) + self.close_dialog_through_button(xDialog.getChild("cancel"), xDialog) raise finally: if close_button: - self.close_dialog_through_button(xDialog.getChild(close_button)) + self.close_dialog_through_button(xDialog.getChild(close_button), xDialog) thread.join() return time.sleep(DEFAULT_SLEEP) diff --git a/vcl/source/treelist/uiobject.cxx b/vcl/source/treelist/uiobject.cxx index ca45d76fa9e6..e9999e2ae119 100644 --- a/vcl/source/treelist/uiobject.cxx +++ b/vcl/source/treelist/uiobject.cxx @@ -217,4 +217,13 @@ OUString TreeListEntryUIObject::get_type() const return "TreeListEntry"; } +bool TreeListEntryUIObject::equals(const UIObject& rOther) const +{ + const TreeListEntryUIObject* pOther = dynamic_cast(&rOther); + if (!pOther) + return false; + return mxTreeList.get() == pOther->mxTreeList.get() + && maTreePath == pOther->maTreePath; +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/source/uitest/uiobject.cxx b/vcl/source/uitest/uiobject.cxx index 2671a9145436..d209edd6a5c4 100644 --- a/vcl/source/uitest/uiobject.cxx +++ b/vcl/source/uitest/uiobject.cxx @@ -396,6 +396,14 @@ OUString WindowUIObject::get_type() const return get_name(); } +bool WindowUIObject::equals(const UIObject& rOther) const +{ + const WindowUIObject* pOther = dynamic_cast(&rOther); + if (!pOther) + return false; + return mxWindow.get() == pOther->mxWindow.get(); +} + namespace { vcl::Window* findChild(vcl::Window* pParent, const OUString& rID, bool bRequireVisible = false, OUStringBuffer* debug = nullptr) diff --git a/vcl/source/uitest/uno/uiobject_uno.cxx b/vcl/source/uitest/uno/uiobject_uno.cxx index 1a59520f1943..a17c744c0331 100644 --- a/vcl/source/uitest/uno/uiobject_uno.cxx +++ b/vcl/source/uitest/uno/uiobject_uno.cxx @@ -206,4 +206,9 @@ OUString SAL_CALL UIObjectUnoObj::getHierarchy() return mpObj->dumpHierarchy(); } +sal_Bool SAL_CALL UIObjectUnoObj::equals(const css::uno::Reference& rOther) +{ + return mpObj->equals(*static_cast(*rOther).mpObj); +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/source/uitest/uno/uiobject_uno.hxx b/vcl/source/uitest/uno/uiobject_uno.hxx index e86ce1bfd289..85158fe76b8d 100644 --- a/vcl/source/uitest/uno/uiobject_uno.hxx +++ b/vcl/source/uitest/uno/uiobject_uno.hxx @@ -48,6 +48,8 @@ public: css::uno::Sequence SAL_CALL getSupportedServiceNames() override; OUString SAL_CALL getHierarchy() override; + + sal_Bool SAL_CALL equals(const css::uno::Reference& rOther) override; }; /* vim:set shiftwidth=4 softtabstop=4 expandtab: */