From 11f7dbda774aa586fbc3940e52e271ba70a2b8c4 Mon Sep 17 00:00:00 2001
From: Christian Stenger <christian.stenger@nokia.com>
Date: Wed, 21 Sep 2011 17:29:18 +0200
Subject: [PATCH] Added new qml test and continue refactoring

Refactoring of all helper functions to make it easier to
recognize them as such. All helper functions in global
shared scripts now follow the scheme __NAME__
Helper functions normally should not get called from outside.

Change-Id: I0d02028d3f9de1ad251af9226c0460655bd9c9bd
Reviewed-on: http://codereview.qt-project.org/5331
Reviewed-by: Qt Sanity Bot <qt_sanity_bot@ovi.com>
Reviewed-by: Bill King <bill.king@nokia.com>
---
 tests/system/objects.map                      |  2 +
 tests/system/shared/build_utils.py            |  4 +-
 tests/system/shared/editor_utils.py           | 58 +++++++++++
 tests/system/shared/qtcreator.py              | 35 ++++++-
 tests/system/shared/qtquick.py                | 26 +++--
 tests/system/shared/utils.py                  | 25 ++---
 .../tst_basic_cpp_support/test.py             | 13 +--
 tests/system/suite_qtquick/suite.conf         |  2 +-
 .../suite_qtquick/tst_qml_editor/test.py      | 95 +++++++++++++++++++
 .../suite_qtquick/tst_qml_indent/test.py      |  8 +-
 .../tst_qtquick_creation/test.py              |  5 +-
 .../tst_qtquick_creation2/test.py             |  5 +-
 .../tst_qtquick_creation3/test.py             |  5 +-
 .../tst_qtquick_creation4/test.py             |  5 +-
 14 files changed, 225 insertions(+), 63 deletions(-)
 create mode 100644 tests/system/shared/editor_utils.py
 create mode 100644 tests/system/suite_qtquick/tst_qml_editor/test.py

diff --git a/tests/system/objects.map b/tests/system/objects.map
index ebee8e3f950..b7aeffb289c 100644
--- a/tests/system/objects.map
+++ b/tests/system/objects.map
@@ -27,3 +27,5 @@
 :projects_QModelIndex	{column='0' container=':Qt Creator_Utils::NavigationTreeView' text='projects' type='QModelIndex'}
 :scrollArea.Create Build Configurations:_QComboBox	{container=':Project Setup.scrollArea_QScrollArea' leftWidget=':scrollArea.Create Build Configurations:_QLabel' type='QComboBox' unnamed='1' visible='1'}
 :scrollArea.Create Build Configurations:_QLabel	{container=':Project Setup.scrollArea_QScrollArea' text='Create Build Configurations:' type='QLabel' unnamed='1' visible='1'}
+:Qt Creator.Stop_QToolButton	{text='Stop' type='QToolButton' unnamed='1' visible='1' window=':Qt Creator_Core::Internal::MainWindow'}
+:Qt Creator_Core::Internal::OutputPaneToggleButton	{occurrence='3' type='Core::Internal::OutputPaneToggleButton' unnamed='1' visible='1' window=':Qt Creator_Core::Internal::MainWindow'}
diff --git a/tests/system/shared/build_utils.py b/tests/system/shared/build_utils.py
index 1b394e80189..abec04a7ce4 100644
--- a/tests/system/shared/build_utils.py
+++ b/tests/system/shared/build_utils.py
@@ -16,11 +16,11 @@ def overrideInstallLazySignalHandler():
         return
     overridenInstallLazySignalHandlers = True
     global installLazySignalHandler
-    installLazySignalHandler = addSignalHandlerDict(installLazySignalHandler)
+    installLazySignalHandler = __addSignalHandlerDict__(installLazySignalHandler)
 
 # avoids adding a handler to a signal twice or more often
 # do not call this function directly - use overrideInstallLazySignalHandler() instead
-def addSignalHandlerDict(lazySignalHandlerFunction):
+def __addSignalHandlerDict__(lazySignalHandlerFunction):
     global installedSignalHandlers
     def wrappedFunction(name, signalSignature, handlerFunctionName):
         handlers = installedSignalHandlers.get("%s____%s" % (name,signalSignature))
diff --git a/tests/system/shared/editor_utils.py b/tests/system/shared/editor_utils.py
new file mode 100644
index 00000000000..1df31cbb5a4
--- /dev/null
+++ b/tests/system/shared/editor_utils.py
@@ -0,0 +1,58 @@
+import re;
+
+# places the cursor inside the given editor into the given line
+# (leading and trailing whitespaces are ignored!)
+# and goes to the end of the line
+# line can be a regex - but if so, remember to set isRegex to True
+# the function returns True if this went fine, False on error
+def placeCursorToLine(editor,line,isRegex=False):
+    cursor = editor.textCursor()
+    oldPosition = 0
+    cursor.setPosition(oldPosition)
+    found = False
+    if isRegex:
+        regex = re.compile(line)
+    while not found:
+        currentLine = str(lineUnderCursor(editor)).strip()
+        if isRegex:
+            if regex.match(currentLine):
+                found = True
+            else:
+                type(editor, "<Down>")
+                if oldPosition==editor.textCursor().position():
+                    break
+                oldPosition = editor.textCursor().position()
+        else:
+            if currentLine==line:
+                found = True
+            else:
+                type(editor, "<Down>")
+                if oldPosition==editor.textCursor().position():
+                    break
+                oldPosition = editor.textCursor().position()
+    if not found:
+        test.fatal("Couldn't find line matching\n\n%s\n\nLeaving test..." % line)
+        return False
+    cursor=editor.textCursor()
+    cursor.movePosition(QTextCursor.EndOfLine, QTextCursor.MoveAnchor)
+    editor.setTextCursor(cursor)
+    return True
+
+# this function simply opens the context menu inside the given editor
+# at the same position where the text cursor is located at
+def openContextMenuOnTextCursorPosition(editor):
+    rect = editor.cursorRect(editor.textCursor())
+    openContextMenu(editor, rect.x+rect.width/2, rect.y+rect.height/2, 0)
+
+# this function marks/selects the text inside the given editor from position
+# startPosition to endPosition (both inclusive)
+def markText(editor, startPosition, endPosition):
+    cursor = editor.textCursor()
+    cursor.setPosition(startPosition)
+    cursor.movePosition(QTextCursor.StartOfLine)
+    editor.setTextCursor(cursor)
+    cursor.movePosition(QTextCursor.Right, QTextCursor.KeepAnchor, endPosition-startPosition)
+    cursor.movePosition(QTextCursor.EndOfLine, QTextCursor.KeepAnchor)
+    cursor.setPosition(endPosition, QTextCursor.KeepAnchor)
+    editor.setTextCursor(cursor)
+
diff --git a/tests/system/shared/qtcreator.py b/tests/system/shared/qtcreator.py
index ba690a3e695..3e26176fcb3 100644
--- a/tests/system/shared/qtcreator.py
+++ b/tests/system/shared/qtcreator.py
@@ -4,6 +4,9 @@ import os;
 import glob;
 import atexit;
 import codecs;
+import subprocess;
+import errno;
+from datetime import datetime,timedelta;
 
 SDKPath = ''
 SettingsPath = ''
@@ -14,10 +17,36 @@ source("../../shared/utils.py")
 source("../../shared/build_utils.py")
 source("../../shared/mainwin.py")
 source("../../shared/qtquick.py")
+source("../../shared/editor_utils.py")
 
-def removeTmpSettingsDir():
+def waitForCleanShutdown(timeOut=10):
     appCtxt = currentApplicationContext()
-    waitFor("appCtxt.isRunning==False")
+    shutdownDone = False
+    if platform.system() in ('Windows','Microsoft'):
+        endtime = datetime.utcnow() + timedelta(seconds=timeOut)
+        while not shutdownDone:
+            # following work-around because os.kill() works for win not until python 2.7
+            tasks = subprocess.Popen("tasklist /FI \"PID eq %d\"" % appCtxt.pid, shell=True,stdout=subprocess.PIPE)
+            output = tasks.communicate()[0]
+            tasks.stdout.close()
+            if (output=="INFO: No tasks are running which match the specified criteria."
+                or output=="" or output.find("ERROR")==0):
+                shutdownDone=True
+            if not shutdownDone and datetime.utcnow() > endtime:
+                break
+    else:
+        endtime = datetime.utcnow() + timedelta(seconds=timeOut)
+        while not shutdownDone:
+            try:
+                os.kill(appCtxt.pid,0)
+            except OSError, err:
+                if err.errno == errno.EPERM or err.errno == errno.ESRCH:
+                    shutdownDone=True
+            if not shutdownDone and datetime.utcnow() > endtime:
+                break
+
+def __removeTmpSettingsDir__():
+    waitForCleanShutdown()
     deleteDirIfExists(os.path.dirname(tmpSettingsDir))
 
 if platform.system() in ('Windows', 'Microsoft'):
@@ -34,6 +63,6 @@ tmpSettingsDir = tempDir()
 tmpSettingsDir = os.path.abspath(tmpSettingsDir+"/settings")
 shutil.copytree(cwd, tmpSettingsDir)
 # the following only doesn't work if the test ends in an exception
-atexit.register(removeTmpSettingsDir)
+atexit.register(__removeTmpSettingsDir__)
 SettingsPath = " -settingspath %s" % tmpSettingsDir
 
diff --git a/tests/system/shared/qtquick.py b/tests/system/shared/qtquick.py
index c0d2e5ef1d8..d654b603a8a 100644
--- a/tests/system/shared/qtquick.py
+++ b/tests/system/shared/qtquick.py
@@ -44,11 +44,11 @@ class QtQuickConstants:
         else:
             return None
 
-def handleProcessStarted(object):
+def __handleProcessStarted__(object):
     global processStarted
     processStarted = True
 
-def handleProcessExited(object, exitCode):
+def __handleProcessExited__(object, exitCode):
     global processExited
     processExited = True
 
@@ -87,8 +87,8 @@ def chooseDestination(destination=QtQuickConstants.Destinations.DESKTOP):
 def runAndCloseApp():
     global processStarted, processExited
     processStarted = processExited = False
-    installLazySignalHandler("{type='ProjectExplorer::ApplicationLaucher'}", "processStarted()", "handleProcessStarted")
-    installLazySignalHandler("{type='ProjectExplorer::ApplicationLaucher'}", "processExited(int)", "handleProcessExited")
+    installLazySignalHandler("{type='ProjectExplorer::ApplicationLaucher'}", "processStarted()", "__handleProcessStarted__")
+    installLazySignalHandler("{type='ProjectExplorer::ApplicationLaucher'}", "processExited(int)", "__handleProcessExited__")
     runButton = waitForObject("{type='Core::Internal::FancyToolButton' text='Run' visible='1'}", 20000)
     clickButton(runButton)
     waitForSignal("{type='ProjectExplorer::BuildManager' unnamed='1'}", "buildQueueFinished(bool)", 300000)
@@ -103,24 +103,22 @@ def runAndCloseApp():
         invokeMenuItem("File", "Exit")
         return False
     # the following is currently a work-around for not using hooking into subprocesses
-    setWindowState(waitForObject(":Qt Creator_Core::Internal::MainWindow", 20000), WindowState.Minimize)
-    nativeType("<Alt+F4>")
-    waitFor("processExited==True",10000)
-    setWindowState(waitForObject(":Qt Creator_Core::Internal::MainWindow", 20000), WindowState.Normal)
+    if (waitForObject(":Qt Creator_Core::Internal::OutputPaneToggleButton").checked!=True):
+        clickButton(":Qt Creator_Core::Internal::OutputPaneToggleButton")
+    clickButton(":Qt Creator.Stop_QToolButton")
     return True
 
 def runAndCloseQtQuickUI():
     global processStarted, processExited
     processStarted = processExited = False
-    installLazySignalHandler("{type='ProjectExplorer::ApplicationLaucher'}", "processStarted()", "handleProcessStarted")
-    installLazySignalHandler("{type='ProjectExplorer::ApplicationLaucher'}", "processExited(int)", "handleProcessExited")
+    installLazySignalHandler("{type='ProjectExplorer::ApplicationLaucher'}", "processStarted()", "__handleProcessStarted__")
+    installLazySignalHandler("{type='ProjectExplorer::ApplicationLaucher'}", "processExited(int)", "__handleProcessExited__")
     runButton = waitForObject("{type='Core::Internal::FancyToolButton' text='Run' visible='1'}", 20000)
     clickButton(runButton)
     waitFor("processStarted==True", 10000)
     # the following is currently a work-around for not using hooking into subprocesses
-    setWindowState(waitForObject(":Qt Creator_Core::Internal::MainWindow", 20000), WindowState.Minimize)
-    nativeType("<Alt+F4>")
-    waitFor("processExited==True", 10000)
-    setWindowState(waitForObject(":Qt Creator_Core::Internal::MainWindow", 20000), WindowState.Normal)
+    if (waitForObject(":Qt Creator_Core::Internal::OutputPaneToggleButton").checked!=True):
+        clickButton(":Qt Creator_Core::Internal::OutputPaneToggleButton")
+    clickButton(":Qt Creator.Stop_QToolButton")
     return True
 
diff --git a/tests/system/shared/utils.py b/tests/system/shared/utils.py
index 47f92b6d965..3a58cf0aa51 100644
--- a/tests/system/shared/utils.py
+++ b/tests/system/shared/utils.py
@@ -72,29 +72,24 @@ def replaceLineEditorContent(lineEditor, newcontent):
 
 signalObjects = {}
 
-def callbackFunction(object, *args):
+def __callbackFunction__(object, *args):
     global signalObjects
-#    test.log("callbackFunction: "+objectMap.realName(object))
+#    test.log("__callbackFunction__: "+objectMap.realName(object))
     signalObjects[objectMap.realName(object)] += 1
 
 def waitForSignal(object, signal, timeout=30000):
+    global signalObjects
+    realName = prepareForSignal(object, signal)
+    beforeCount = signalObjects[realName]
+    waitFor("signalObjects[realName] > beforeCount", timeout)
+
+def prepareForSignal(object, signal):
     global signalObjects
     overrideInstallLazySignalHandler()
     realName = objectMap.realName(object)
 #    test.log("waitForSignal: "+realName)
     if not (realName in signalObjects):
         signalObjects[realName] = 0
-    beforeCount = signalObjects[realName]
-    installLazySignalHandler(object, signal, "callbackFunction")
-    waitFor("signalObjects[realName] > beforeCount", timeout)
-
-def markText(editor, startPosition, endPosition):
-    cursor = editor.textCursor()
-    cursor.setPosition(startPosition)
-    cursor.movePosition(QTextCursor.StartOfLine)
-    editor.setTextCursor(cursor)
-    cursor.movePosition(QTextCursor.Right, QTextCursor.KeepAnchor, endPosition-startPosition)
-    cursor.movePosition(QTextCursor.EndOfLine, QTextCursor.KeepAnchor)
-    cursor.setPosition(endPosition, QTextCursor.KeepAnchor)
-    editor.setTextCursor(cursor)
+    installLazySignalHandler(object, signal, "__callbackFunction__")
+    return realName
 
diff --git a/tests/system/suite_general/tst_basic_cpp_support/test.py b/tests/system/suite_general/tst_basic_cpp_support/test.py
index 63cb6dd1ed4..3e96390b7c8 100644
--- a/tests/system/suite_general/tst_basic_cpp_support/test.py
+++ b/tests/system/suite_general/tst_basic_cpp_support/test.py
@@ -1,22 +1,13 @@
 source("../../shared/qtcreator.py")
 
-refreshFinishedCount = 0
-
-def handleRefreshFinished(object, fileList):
-    global refreshFinishedCount
-    refreshFinishedCount += 1
-
 def main():
     test.verify(os.path.exists(SDKPath + "/creator/tests/manual/cplusplus-tools/cplusplus-tools.pro"))
 
     startApplication("qtcreator" + SettingsPath)
 
-    ## leave this one like this, it's too fast for delayed installation of signal handler
-    installLazySignalHandler("{type='CppTools::Internal::CppModelManager'}", "sourceFilesRefreshed(QStringList)", "handleRefreshFinished")
+    prepareForSignal("{type='CppTools::Internal::CppModelManager' unnamed='1'}", "sourceFilesRefreshed(QStringList)")
     openQmakeProject(SDKPath + "/creator/tests/manual/cplusplus-tools/cplusplus-tools.pro")
-
-    waitFor("refreshFinishedCount == 1", 20000)
-    test.compare(refreshFinishedCount, 1)
+    waitForSignal("{type='CppTools::Internal::CppModelManager' unnamed='1'}", "sourceFilesRefreshed(QStringList)", 20000)
 
     mouseClick(waitForObject(":*Qt Creator_Utils::FilterLineEdit", 20000), 5, 5, 0, Qt.LeftButton)
     type(waitForObject(":*Qt Creator_Utils::FilterLineEdit"), "dummy.cpp")
diff --git a/tests/system/suite_qtquick/suite.conf b/tests/system/suite_qtquick/suite.conf
index e2ee6f29d46..7f30867a1d6 100644
--- a/tests/system/suite_qtquick/suite.conf
+++ b/tests/system/suite_qtquick/suite.conf
@@ -7,6 +7,6 @@ HOOK_SUB_PROCESSES=true
 IMPLICITAUTSTART=0
 LANGUAGE=Python
 OBJECTMAP=../objects.map
-TEST_CASES=tst_qtquick_creation tst_qtquick_creation2 tst_qtquick_creation3 tst_qtquick_creation4
+TEST_CASES=tst_qtquick_creation tst_qtquick_creation2 tst_qtquick_creation3 tst_qtquick_creation4 tst_qml_indent tst_qml_editor
 VERSION=2
 WRAPPERS=Qt
diff --git a/tests/system/suite_qtquick/tst_qml_editor/test.py b/tests/system/suite_qtquick/tst_qml_editor/test.py
new file mode 100644
index 00000000000..bed1b9e9358
--- /dev/null
+++ b/tests/system/suite_qtquick/tst_qml_editor/test.py
@@ -0,0 +1,95 @@
+source("../../shared/qtcreator.py")
+
+workingDir = None
+templateDir = None
+
+def main():
+    global workingDir,templateDir
+    startApplication("qtcreator" + SettingsPath)
+    # using a temporary directory won't mess up an eventually exisiting
+    workingDir = tempDir()
+    prepareTemplate()
+    createNewQtQuickApplication()
+    # wait for parsing to complete
+    waitForSignal("{type='CppTools::Internal::CppModelManager' unnamed='1'}", "sourceFilesRefreshed(QStringList)", 30000)
+    testRenameId()
+
+    invokeMenuItem("File", "Exit")
+
+def prepareTemplate():
+    global templateDir
+    templateDir = tempDir()
+    templateDir = os.path.abspath(templateDir + "/template")
+    sourceExample = os.path.abspath(SDKPath + "/../Examples/4.7/declarative/text/textselection")
+    shutil.copytree(sourceExample, templateDir)
+
+def createNewQtQuickApplication():
+    global workingDir,templateDir
+    invokeMenuItem("File", "New File or Project...")
+    clickItem(waitForObject("{type='QTreeView' name='templateCategoryView'}", 20000),
+              "Projects.Qt Quick Project", 5, 5, 0, Qt.LeftButton)
+    clickItem(waitForObject("{name='templatesView' type='QListView'}", 20000),
+              "Qt Quick Application", 5, 5, 0, Qt.LeftButton)
+    clickButton(waitForObject("{text='Choose...' type='QPushButton' unnamed='1' visible='1'}", 20000))
+    baseLineEd = waitForObject("{name='nameLineEdit' visible='1' "
+                               "type='Utils::ProjectNameValidatingLineEdit'}", 20000)
+    replaceLineEditorContent(baseLineEd, "untitled")
+    baseLineEd = waitForObject("{type='Utils::BaseValidatingLineEdit' unnamed='1' visible='1'}", 20000)
+    replaceLineEditorContent(baseLineEd, workingDir)
+    stateLabel = findObject("{type='QLabel' name='stateLabel'}")
+    labelCheck = stateLabel.text=="" and stateLabel.styleSheet == ""
+    test.verify(labelCheck, "Project name and base directory without warning or error")
+    # make sure this is not set as default location
+    cbDefaultLocation = waitForObject("{type='QCheckBox' name='projectsDirectoryCheckBox' visible='1'}", 20000)
+    if cbDefaultLocation.checked:
+        clickButton(cbDefaultLocation)
+    # now there's the 'untitled' project inside a temporary directory - step forward...!
+    nextButton = waitForObject("{text?='Next*' type='QPushButton' visible='1'}", 20000)
+    clickButton(nextButton)
+    chooseComponents(QtQuickConstants.Components.EXISTING_QML)
+    # define the existing qml file to import
+    baseLineEd = waitForObject("{type='Utils::BaseValidatingLineEdit' unnamed='1' visible='1'}", 20000)
+    type(baseLineEd, templateDir+"/qml/textselection.qml")
+    clickButton(nextButton)
+    chooseDestination()
+    snooze(1)
+    clickButton(nextButton)
+    clickButton(waitForObject("{type='QPushButton' text='Finish' visible='1'}", 20000))
+
+def testRenameId():
+    test.log("Testing rename of id")
+    navTree = waitForObject("{type='Utils::NavigationTreeView' unnamed='1' visible='1' "
+                            "window=':Qt Creator_Core::Internal::MainWindow'}", 20000)
+    model = navTree.model()
+    treeElement = ("untitled.QML.%s/qml.textselection\\.qml" %
+                   templateDir.replace("\\", "/").replace("_", "\\_"))
+    waitForObjectItem(navTree, treeElement)
+    doubleClickItem(navTree, treeElement, 5, 5, 0, Qt.LeftButton)
+    editor = waitForObject("{type='QmlJSEditor::QmlJSTextEditorWidget' unnamed='1' visible='1' "
+                           "window=':Qt Creator_Core::Internal::MainWindow'}", 20000)
+    originalText = "%s" % editor.plainText
+    line = "TextEdit\s*\{"
+    if not placeCursorToLine(editor, line, True):
+        test.fatal("File seems to have changed... Canceling current test")
+        return False
+    type(editor, "<Down>")
+    openContextMenuOnTextCursorPosition(editor)
+    activateItem(waitForObjectItem("{type='QMenu' visible='1' unnamed='1'}", "Rename Symbol Under Cursor"))
+    type(waitForObject("{leftWidget={text='Replace with:' type='QLabel' unnamed='1' visible='1'} "
+                       "type='Find::Internal::WideEnoughLineEdit' unnamed='1' visible='1' "
+                       "window=':Qt Creator_Core::Internal::MainWindow'}"), "halloballo")
+    clickButton(waitForObject("{text='Replace' type='QToolButton' unnamed='1' visible='1' "
+                              "window=':Qt Creator_Core::Internal::MainWindow'}"))
+    modifiedText = "%s" % editor.plainText
+    originalText = "%s" % (originalText.replace("editor", "__EDITOR__").replace("edit", "halloballo")
+                    .replace("__EDITOR__", "editor"))
+    test.compare(originalText,modifiedText)
+    type(editor, "<Ctrl+S>")
+
+def cleanup():
+    global workingDir, templateDir
+    waitForCleanShutdown()
+    if workingDir!=None:
+        deleteDirIfExists(workingDir)
+    if templateDir!=None:
+        deleteDirIfExists(os.path.dirname(templateDir))
diff --git a/tests/system/suite_qtquick/tst_qml_indent/test.py b/tests/system/suite_qtquick/tst_qml_indent/test.py
index 4b0d0c0c24b..3cef69ba587 100644
--- a/tests/system/suite_qtquick/tst_qml_indent/test.py
+++ b/tests/system/suite_qtquick/tst_qml_indent/test.py
@@ -37,7 +37,7 @@ def createNewQtQuickApplication():
     if cbDefaultLocation.checked:
         clickButton(cbDefaultLocation)
     # now there's the 'untitled' project inside a temporary directory - step forward...!
-    nextButton = waitForObject("{text='Next' type='QPushButton' visible='1'}", 20000)
+    nextButton = waitForObject("{text?='Next*' type='QPushButton' visible='1'}", 20000)
     clickButton(nextButton)
     chooseComponents()
     clickButton(nextButton)
@@ -99,8 +99,7 @@ def testReIndent():
     if originalText==textAfterReIndent:
         test.passes("Text successfully reindented...")
     else:
-        # remove the 2nd parameter of the following???
-        # (it's huge output that takes long time to finish & screenshot is taken either!)
+        # shrink the texts - it's huge output that takes long time to finish & screenshot is taken as well
         originalText = shrinkText(originalText, 20)
         textAfterReIndent = shrinkText(textAfterReIndent, 20)
         test.fail("Re-indent of text unsuccessful...",
@@ -120,8 +119,7 @@ def shrinkText(txt, lines=10):
 def cleanup():
     global workingDir
     # waiting for a clean exit - for a full-remove of the temp directory
-    appCtxt = currentApplicationContext()
-    waitFor("appCtxt.isRunning==False")
+    waitForCleanShutdown()
     if workingDir!=None:
         deleteDirIfExists(workingDir)
 
diff --git a/tests/system/suite_qtquick/tst_qtquick_creation/test.py b/tests/system/suite_qtquick/tst_qtquick_creation/test.py
index 95da6301661..82f1978a56d 100644
--- a/tests/system/suite_qtquick/tst_qtquick_creation/test.py
+++ b/tests/system/suite_qtquick/tst_qtquick_creation/test.py
@@ -36,7 +36,7 @@ def createNewQtQuickApplication():
     if cbDefaultLocation.checked:
         clickButton(cbDefaultLocation)
     # now there's the 'untitled' project inside a temporary directory - step forward...!
-    nextButton = waitForObject("{text='Next' type='QPushButton' visible='1'}", 20000)
+    nextButton = waitForObject("{text?='Next*' type='QPushButton' visible='1'}", 20000)
     clickButton(nextButton)
     chooseComponents()
     clickButton(nextButton)
@@ -48,8 +48,7 @@ def createNewQtQuickApplication():
 def cleanup():
     global workingDir
     # waiting for a clean exit - for a full-remove of the temp directory
-    appCtxt = currentApplicationContext()
-    waitFor("appCtxt.isRunning==False")
+    waitForCleanShutdown()
     if workingDir!=None:
         deleteDirIfExists(workingDir)
 
diff --git a/tests/system/suite_qtquick/tst_qtquick_creation2/test.py b/tests/system/suite_qtquick/tst_qtquick_creation2/test.py
index 418ca6c1e4b..a74f2b6a71e 100644
--- a/tests/system/suite_qtquick/tst_qtquick_creation2/test.py
+++ b/tests/system/suite_qtquick/tst_qtquick_creation2/test.py
@@ -45,7 +45,7 @@ def createNewQtQuickApplication():
     if cbDefaultLocation.checked:
         clickButton(cbDefaultLocation)
     # now there's the 'untitled' project inside a temporary directory - step forward...!
-    nextButton = waitForObject("{text='Next' type='QPushButton' visible='1'}", 20000)
+    nextButton = waitForObject("{text?='Next*' type='QPushButton' visible='1'}", 20000)
     clickButton(nextButton)
     chooseComponents(QtQuickConstants.Components.EXISTING_QML)
     # define the existing qml file to import
@@ -60,8 +60,7 @@ def createNewQtQuickApplication():
 def cleanup():
     global workingDir,templateDir
     # waiting for a clean exit - for a full-remove of the temp directory
-    appCtxt = currentApplicationContext()
-    waitFor("appCtxt.isRunning==False")
+    waitForCleanShutdown()
     if workingDir!=None:
         deleteDirIfExists(workingDir)
     if templateDir!=None:
diff --git a/tests/system/suite_qtquick/tst_qtquick_creation3/test.py b/tests/system/suite_qtquick/tst_qtquick_creation3/test.py
index 1025f00949c..fb537912e41 100644
--- a/tests/system/suite_qtquick/tst_qtquick_creation3/test.py
+++ b/tests/system/suite_qtquick/tst_qtquick_creation3/test.py
@@ -29,14 +29,13 @@ def createNewQtQuickUI():
     if cbDefaultLocation.checked:
         clickButton(cbDefaultLocation)
     # now there's the 'untitled' project inside a temporary directory - step forward...!
-    clickButton(waitForObject("{text='Next' type='QPushButton' visible='1'}", 20000))
+    clickButton(waitForObject("{text?='Next*' type='QPushButton' visible='1'}", 20000))
     clickButton(waitForObject("{type='QPushButton' text='Finish' visible='1'}", 20000))
 
 def cleanup():
     global workingDir
     # waiting for a clean exit - for a full-remove of the temp directory
-    appCtxt = currentApplicationContext()
-    waitFor("appCtxt.isRunning==False")
+    waitForCleanShutdown()
     if workingDir!=None:
         deleteDirIfExists(workingDir)
 
diff --git a/tests/system/suite_qtquick/tst_qtquick_creation4/test.py b/tests/system/suite_qtquick/tst_qtquick_creation4/test.py
index 72336be4359..76ac3419e21 100644
--- a/tests/system/suite_qtquick/tst_qtquick_creation4/test.py
+++ b/tests/system/suite_qtquick/tst_qtquick_creation4/test.py
@@ -33,7 +33,7 @@ def createNewQmlExtension():
     if cbDefaultLocation.checked:
         clickButton(cbDefaultLocation)
     # now there's the 'untitled' project inside a temporary directory - step forward...!
-    nextButton = waitForObject("{text='Next' type='QPushButton' visible='1'}", 20000)
+    nextButton = waitForObject("{text?='Next*' type='QPushButton' visible='1'}", 20000)
     clickButton(nextButton)
     chooseDestination()
     clickButton(nextButton)
@@ -50,8 +50,7 @@ def createNewQmlExtension():
 def cleanup():
     global workingDir
     # waiting for a clean exit - for a full-remove of the temp directory
-    appCtxt = currentApplicationContext()
-    waitFor("appCtxt.isRunning==False")
+    waitForCleanShutdown()
     if workingDir!=None:
         deleteDirIfExists(workingDir)
 
-- 
GitLab