From 3ad7e50827c1f46ec730e457b9621b227cd35efc Mon Sep 17 00:00:00 2001
From: Christian Stenger <christian.stenger@nokia.com>
Date: Fri, 17 Feb 2012 17:10:53 +0100
Subject: [PATCH] Squish: Verify targets for project creation
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Change-Id: I3af0e0cde985c4b04bd4ae8181c3b82cda22b2b8
Reviewed-by: Robert Löhning <robert.loehning@nokia.com>
---
 tests/system/objects.map                      |   5 +
 tests/system/shared/classes.py                |  22 ++++
 tests/system/shared/project.py                |  20 ++-
 tests/system/shared/utils.py                  |  34 +++++
 tests/system/shared/workarounds.py            |   5 +
 tests/system/suite_general/suite.conf         |   2 +-
 .../tst_create_proj_wizard/test.py            | 122 ++++++++++++++++++
 7 files changed, 205 insertions(+), 5 deletions(-)
 create mode 100644 tests/system/suite_general/tst_create_proj_wizard/test.py

diff --git a/tests/system/objects.map b/tests/system/objects.map
index f3caa2cce2a..689efc6f08c 100644
--- a/tests/system/objects.map
+++ b/tests/system/objects.map
@@ -17,7 +17,9 @@
 :New.templatesView_QListView	{name='templatesView' type='QListView' visible='1' window=':New_Core::Internal::NewDialog'}
 :New_Core::Internal::NewDialog	{name='Core__Internal__NewDialog' type='Core::Internal::NewDialog' visible='1' windowTitle='New'}
 :Next_QPushButton	{text~='(Next.*|Continue)' type='QPushButton' visible='1'}
+:Options.Cancel_QPushButton	{text='Cancel' type='QPushButton' unnamed='1' visible='1' window=':Options_Core::Internal::SettingsDialog'}
 :Options.OK_QPushButton	{text='OK' type='QPushButton' unnamed='1' visible='1' window=':Options_Core::Internal::SettingsDialog'}
+:Options.qt_tabwidget_stackedwidget_QStackedWidget	{name='qt_tabwidget_stackedwidget' type='QStackedWidget' visible='1' window=':Options_Core::Internal::SettingsDialog'}
 :Options.qt_tabwidget_tabbar_QTabBar	{name='qt_tabwidget_tabbar' type='QTabBar' visible='1' window=':Options_Core::Internal::SettingsDialog'}
 :Options_Core::Internal::SettingsDialog	{type='Core::Internal::SettingsDialog' unnamed='1' visible='1' windowTitle~='(Options|Preferences)'}
 :Options_QListView	{type='QListView' unnamed='1' visible='1' window=':Options_Core::Internal::SettingsDialog'}
@@ -43,12 +45,15 @@
 :Qt Gui Application.scrollArea_QScrollArea	{name='scrollArea' type='QScrollArea' visible='1'}
 :Qt Gui Application_Qt4ProjectManager::Internal::GuiAppWizardDialog	{type='Qt4ProjectManager::Internal::GuiAppWizardDialog' unnamed='1' visible='1' windowTitle='Qt Gui Application'}
 :QtCreator.MenuBar_ProjectExplorer::Internal::MiniProjectTargetSelector	{type='ProjectExplorer::Internal::MiniProjectTargetSelector'}
+:QtSupport__Internal__QtVersionManager.QLabel	{container=':qt_tabwidget_stackedwidget.QtSupport__Internal__QtVersionManager_QtSupport::Internal::QtOptionsPageWidget' name='errorLabel' type='QLabel' visible='1'}
+:QtSupport__Internal__QtVersionManager.qtdirList_QTreeWidget	{container=':qt_tabwidget_stackedwidget.QtSupport__Internal__QtVersionManager_QtSupport::Internal::QtOptionsPageWidget' name='qtdirList' type='QTreeWidget' visible='1'}
 :Symbol Server_Utils::CheckableMessageBox	{type='Utils::CheckableMessageBox' unnamed='1' visible='1' windowTitle='Symbol Server'}
 :addToVersionControlComboBox_QComboBox	{name='addToVersionControlComboBox' type='QComboBox' visible='1'}
 :formFileLineEdit_Utils::FileNameValidatingLineEdit	{buddy=':Qt Gui Application.Form file:_QLabel' name='formFileLineEdit' type='Utils::FileNameValidatingLineEdit' visible='1'}
 :headerFileLineEdit_Utils::FileNameValidatingLineEdit	{buddy=':Qt Gui Application.Header file:_QLabel' name='headerFileLineEdit' type='Utils::FileNameValidatingLineEdit' visible='1'}
 :projects.projects.pro_QModelIndex	{column='0' container=':projects_QModelIndex' text='projects.pro' type='QModelIndex'}
 :projects_QModelIndex	{column='0' container=':Qt Creator_Utils::NavigationTreeView' text='projects' type='QModelIndex'}
+:qt_tabwidget_stackedwidget.QtSupport__Internal__QtVersionManager_QtSupport::Internal::QtOptionsPageWidget	{container=':Options.qt_tabwidget_stackedwidget_QStackedWidget' name='QtSupport__Internal__QtVersionManager' type='QtSupport::Internal::QtOptionsPageWidget' visible='1'}
 :scrollArea.Create Build Configurations:_QComboBox_2	{container=':Qt Gui Application.scrollArea_QScrollArea' leftWidget=':scrollArea.Create Build Configurations:_QLabel_2' type='QComboBox' unnamed='1' visible='1'}
 :scrollArea.Create Build Configurations:_QLabel_2	{container=':Qt Gui Application.scrollArea_QScrollArea' text='Create Build Configurations:' type='QLabel' unnamed='1' visible='1'}
 :scrollArea.Edit build configuration:_QComboBox	{container=':Qt Creator.scrollArea_QScrollArea' leftWidget=':scrollArea.Edit build configuration:_QLabel' type='QComboBox' unnamed='1' visible='1'}
diff --git a/tests/system/shared/classes.py b/tests/system/shared/classes.py
index 689aa0cc0be..81978f59fc0 100644
--- a/tests/system/shared/classes.py
+++ b/tests/system/shared/classes.py
@@ -41,6 +41,28 @@ class QtQuickConstants:
         else:
             return None
 
+    @staticmethod
+    def getAllTargets():
+        return [QtQuickConstants.Targets.DESKTOP, QtQuickConstants.Targets.HARMATTAN,
+                QtQuickConstants.Targets.MAEMO5, QtQuickConstants.Targets.SIMULATOR,
+                QtQuickConstants.Targets.SYMBIAN]
+
+    @staticmethod
+    def getAllTargetStrings():
+        return QtQuickConstants.getTargetsAsStrings(QtQuickConstants.getAllTargets())
+
+    @staticmethod
+    def getTargetsAsStrings(targets):
+        if not isinstance(targets, (tuple,list)):
+            test.fatal("Wrong usage... This function handles only tuples or lists.")
+            return None
+        result = []
+        for target in targets:
+            result.append(QtQuickConstants.getStringForTarget(target))
+        if None in result:
+            test.fatal("You've passed at least one unknown target!")
+        return result
+
 # this class holds some constants for easier usage inside the Projects view
 class ProjectSettings:
     BUILD = 1
diff --git a/tests/system/shared/project.py b/tests/system/shared/project.py
index f4af296902a..e29baf35ce1 100644
--- a/tests/system/shared/project.py
+++ b/tests/system/shared/project.py
@@ -1,3 +1,5 @@
+import re
+
 processStarted = False
 processExited = False
 
@@ -75,7 +77,7 @@ def __createProjectSelectType__(category, template):
     clickItem(templatesView, template, 5, 5, 0, Qt.LeftButton)
     text = waitForObject("{type='QTextBrowser' name='templateDescription' visible='1'}").plainText
     clickButton(waitForObject("{text='Choose...' type='QPushButton' unnamed='1' visible='1'}", 20000))
-    return __getSupportedPlatforms__(str(text))
+    return __getSupportedPlatforms__(str(text))[0]
 
 def __createProjectSetNameAndPath__(path, projectName = None, checks = True):
     directoryEdit = waitForObject("{type='Utils::BaseValidatingLineEdit' unnamed='1' visible='1'}", 20000)
@@ -401,7 +403,15 @@ def resetApplicationContextToCreator():
 # to figure out which available targets we have
 # Simulator must be handled in a special way, because this depends on the
 # configured Qt versions and Toolchains and cannot be looked up the same way
-def __getSupportedPlatforms__(text):
+# if you set getAsStrings to True this function returns a list of strings instead
+# of the constants defined in QtQuickConstants.Targets
+def __getSupportedPlatforms__(text, getAsStrings=False):
+    reqPattern = re.compile("requires qt (?P<version>\d+\.\d+(\.\d+)?)", re.IGNORECASE)
+    res = reqPattern.search(text)
+    if res:
+        version = res.group("version")
+    else:
+        version = None
     if 'Supported Platforms' in text:
         supports = text[text.find('Supported Platforms'):].split(":")[1].strip().split(" ")
         result = []
@@ -425,5 +435,7 @@ def __getSupportedPlatforms__(text):
     else:
         test.warning("Returning None (__getSupportedPlatforms__())",
                      "Parsed text: '%s'" % text)
-        return None
-    return result
+        return None, None
+    if getAsStrings:
+        result = QtQuickConstants.getTargetsAsStrings(result)
+    return result, version
diff --git a/tests/system/shared/utils.py b/tests/system/shared/utils.py
index af305beee74..9525e10722a 100644
--- a/tests/system/shared/utils.py
+++ b/tests/system/shared/utils.py
@@ -260,3 +260,37 @@ def __checkParentAccess__(filePath):
             test.log("Got execute permission on '%s'" % tmp)
         else:
             test.fail("No execute permission on '%s'" % tmp)
+
+# this function checks for all configured Qt versions inside
+# options dialog and returns a dict holding the targets as keys
+# and a list of supported versions as value
+def getCorrectlyConfiguredTargets():
+    result = {}
+    invokeMenuItem("Tools", "Options...")
+    waitForObjectItem(":Options_QListView", "Build & Run")
+    clickItem(":Options_QListView", "Build & Run", 14, 15, 0, Qt.LeftButton)
+    clickTab(waitForObject(":Options.qt_tabwidget_tabbar_QTabBar"), "Qt Versions")
+    pattern = re.compile("Qt version (?P<version>.*?) for (?P<target>.*)")
+    treeWidget = waitForObject(":QtSupport__Internal__QtVersionManager.qtdirList_QTreeWidget")
+    root = treeWidget.invisibleRootItem()
+    for childRow in range(root.childCount()):
+        rootChild = root.child(childRow)
+        rootChildText = str(rootChild.text(0)).replace(".", "\\.")
+        for row in range(rootChild.childCount()):
+            subChild = rootChild.child(row)
+            subChildText = str(subChild.text(0)).replace(".", "\\.")
+            clickItem(treeWidget, ".".join([rootChildText,subChildText]), 5, 5, 0, Qt.LeftButton)
+            currentText = str(waitForObject(":QtSupport__Internal__QtVersionManager.QLabel").text)
+            matches = pattern.match(currentText)
+            if matches:
+                target = matches.group("target")
+                version = matches.group("version")
+                if target in result:
+                    oldV = result[target]
+                    if version not in oldV:
+                        oldV.append(version)
+                        result.update({target:oldV})
+                else:
+                    result.update({target:[version]})
+    clickButton(waitForObject(":Options.OK_QPushButton"))
+    return result
diff --git a/tests/system/shared/workarounds.py b/tests/system/shared/workarounds.py
index 81385fdd046..9e69727a902 100644
--- a/tests/system/shared/workarounds.py
+++ b/tests/system/shared/workarounds.py
@@ -168,6 +168,7 @@ class JIRA:
         # ALWAYS update this dict when adding a new function for a workaround!
         def __initBugDict__(self):
             self.__bugs__= {
+                            'QTCREATORBUG-6967':self._workaroundCreator6967_,
                             'QTCREATORBUG-6853':self._workaroundCreator6853_,
                             'QTCREATORBUG-6918':self._workaroundCreator_MacEditorFocus_,
                             'QTCREATORBUG-6953':self._workaroundCreator_MacEditorFocus_
@@ -178,6 +179,10 @@ class JIRA:
 
 ############### functions that hold workarounds #################################
 
+        def _workaroundCreator6967_(self, *args):
+            if args[0] == 'Mobile Qt Application':
+                args[1].remove('Qt Simulator')
+
         def _workaroundCreator6853_(self, *args):
             if "Release" in args[0] and platform.system() == "Linux":
                 snooze(1)
diff --git a/tests/system/suite_general/suite.conf b/tests/system/suite_general/suite.conf
index b114c5f47d3..19435bce406 100644
--- a/tests/system/suite_general/suite.conf
+++ b/tests/system/suite_general/suite.conf
@@ -7,6 +7,6 @@ HOOK_SUB_PROCESSES=false
 IMPLICITAUTSTART=0
 LANGUAGE=Python
 OBJECTMAP=../objects.map
-TEST_CASES=tst_openqt_creator tst_build_speedcrunch tst_cmake_speedcrunch tst_basic_cpp_support tst_select_all
+TEST_CASES=tst_openqt_creator tst_build_speedcrunch tst_cmake_speedcrunch tst_basic_cpp_support tst_select_all tst_create_proj_wizard
 VERSION=2
 WRAPPERS=Qt
diff --git a/tests/system/suite_general/tst_create_proj_wizard/test.py b/tests/system/suite_general/tst_create_proj_wizard/test.py
new file mode 100644
index 00000000000..80ba5ab18f2
--- /dev/null
+++ b/tests/system/suite_general/tst_create_proj_wizard/test.py
@@ -0,0 +1,122 @@
+source("../../shared/qtcreator.py")
+
+import re
+
+def main():
+    global templateDir, textChanged
+    sourceExample = os.path.abspath(sdkPath + "/Examples/4.7/declarative/text/textselection")
+    if not neededFilePresent(sourceExample):
+        return
+    prepareTemplate(sourceExample)
+    startApplication("qtcreator" + SettingsPath)
+    overrideInstallLazySignalHandler()
+    installLazySignalHandler("{type='QTextBrowser' name='templateDescription' visible='1'}",
+                             "textChanged()","__handleTextChanged__")
+    targets = getCorrectlyConfiguredTargets()
+    test.log("Collecting potential project types...")
+    availableProjectTypes = []
+    invokeMenuItem("File", "New File or Project...")
+    categoriesView = waitForObject("{type='QTreeView' name='templateCategoryView' visible='1'}", 20000)
+    catModel = categoriesView.model()
+    projects = catModel.index(0, 0)
+    test.compare("Projects", projects.data())
+    comboBox = waitForObject("{name='comboBox' type='QComboBox' visible='1' "
+                             "window=':New_Core::Internal::NewDialog'}")
+    test.compare(comboBox.currentText, "All templates")
+    for row in range(catModel.rowCount(projects)):
+        index = catModel.index(row, 0, projects)
+        category = str(index.data()).replace(".", "\\.")
+        # skip non-configurable
+        if "Import" in category or "Non-Qt" in category:
+            continue
+        clickItem(categoriesView, "Projects." + category, 5, 5, 0, Qt.LeftButton)
+        templatesView = waitForObject("{name='templatesView' type='QListView' visible='1'}", 20000)
+        # needed because categoriesView and templatesView using same model
+        tempRootIndex = templatesView.rootIndex()
+        tempModel = templatesView.model()
+        for tRow in range(tempModel.rowCount(tempRootIndex)):
+            tIndex = tempModel.index(tRow, 0, tempRootIndex)
+            template = str(tempModel.data(tIndex)).replace(".", "\\.")
+            # skip non-configurable
+            if "Qt Quick UI" in template or "Plain C" in template:
+                continue
+            availableProjectTypes.append({category:template})
+    clickButton(waitForObject("{text='Cancel' type='QPushButton' unnamed='1' visible='1'}", 20000))
+    for current in availableProjectTypes:
+        category = current.keys()[0]
+        template = current.values()[0]
+        invokeMenuItem("File", "New File or Project...")
+        categoriesView = waitForObject("{type='QTreeView' name='templateCategoryView' visible='1'}", 20000)
+        clickItem(categoriesView, "Projects." + category, 5, 5, 0, Qt.LeftButton)
+        templatesView = waitForObject("{name='templatesView' type='QListView' visible='1'}", 20000)
+        test.log("Verifying '%s' -> '%s'" % (category.replace("\\.", "."), template.replace("\\.", ".")))
+        textChanged = False
+        clickItem(templatesView, template, 5, 5, 0, Qt.LeftButton)
+        waitFor("textChanged", 2000)
+        text = waitForObject("{type='QTextBrowser' name='templateDescription' visible='1'}").plainText
+        displayedPlatforms, requiredVersion = __getSupportedPlatforms__(str(text), True)
+        clickButton(waitForObject("{text='Choose...' type='QPushButton' unnamed='1' visible='1'}", 20000))
+        # don't check because project could exist
+        __createProjectSetNameAndPath__(os.path.expanduser("~"), 'untitled', False)
+        try:
+            waitForObject("{name='mainQmlFileGroupBox' title='Main HTML File' type='QGroupBox' visible='1'}", 1000)
+            clickButton(waitForObject(":Next_QPushButton"))
+        except LookupError:
+            try:
+                waitForObject("{text='Select Existing QML file' type='QLabel' visible='1'}", 1000)
+                baseLineEd = waitForObject("{type='Utils::BaseValidatingLineEdit' unnamed='1' visible='1'}", 20000)
+                type(baseLineEd, templateDir + "/qml/textselection.qml")
+                clickButton(waitForObject(":Next_QPushButton"))
+            except LookupError:
+                pass
+        availableCheckboxes = []
+        waitForObject("{type='QLabel' unnamed='1' visible='1' text='Target Setup'}")
+        for current in QtQuickConstants.getAllTargetStrings():
+            try:
+                findObject("{type='QCheckBox' text='%s' visible='1'}" % current)
+                availableCheckboxes.append(current)
+            except:
+                pass
+        JIRA.performWorkaroundIfStillOpen(6967, JIRA.Bug.CREATOR, template, displayedPlatforms)
+        # verification whether expected, found and configured match
+        for t in targets:
+            if requiredVersion:
+                if max(targets[t]) < requiredVersion:
+                    if t in availableCheckboxes:
+                        test.fail("Target '%s' found as checkbox, but required version (%s) is higher "
+                                  "than configured version(s) (%s)!" % (t, requiredVersion, str(targets[t])))
+                    else:
+                        test.passes("Irrelevant target '%s' not found on 'Target setup' page - "
+                                    "required version is '%s', current version(s) are '%s'." %
+                                    (t, requiredVersion, str(targets[t])))
+                    continue
+            found = False
+            if t in displayedPlatforms:
+                if t in availableCheckboxes:
+                    test.passes("Found expected target '%s' on 'Target setup' page." % t)
+                else:
+                    test.fail("Expected target '%s' missing on 'Target setup' page." % t)
+            else:
+                if t in availableCheckboxes:
+                    test.fail("Target '%s' found on 'Target setup' page - but has not been expected!" % t)
+                else:
+                    test.passes("Irrelevant target '%s' not found on 'Target setup' page." % t)
+        clickButton(waitForObject("{text='Cancel' type='QPushButton' unnamed='1' visible='1'}", 20000))
+    invokeMenuItem("File", "Exit")
+
+def prepareTemplate(sourceExample):
+    global templateDir
+    templateDir = tempDir()
+    templateDir = os.path.abspath(templateDir + "/template")
+    shutil.copytree(sourceExample, templateDir)
+
+def cleanup():
+    global templateDir
+    # waiting for a clean exit - for a full-remove of the temp directory
+    waitForCleanShutdown()
+    if templateDir!=None:
+        deleteDirIfExists(os.path.dirname(templateDir))
+
+def __handleTextChanged__(object):
+    global textChanged
+    textChanged = True
-- 
GitLab