1 | /**************************************************************************** |
2 | ** |
3 | ** Copyright (C) 2017 The Qt Company Ltd. |
4 | ** Contact: http://www.qt.io/licensing/ |
5 | ** |
6 | ** This file is part of the test suite of the Qt Toolkit. |
7 | ** |
8 | ** $QT_BEGIN_LICENSE:LGPL3$ |
9 | ** Commercial License Usage |
10 | ** Licensees holding valid commercial Qt licenses may use this file in |
11 | ** accordance with the commercial license agreement provided with the |
12 | ** Software or, alternatively, in accordance with the terms contained in |
13 | ** a written agreement between you and The Qt Company. For licensing terms |
14 | ** and conditions see http://www.qt.io/terms-conditions. For further |
15 | ** information use the contact form at http://www.qt.io/contact-us. |
16 | ** |
17 | ** GNU Lesser General Public License Usage |
18 | ** Alternatively, this file may be used under the terms of the GNU Lesser |
19 | ** General Public License version 3 as published by the Free Software |
20 | ** Foundation and appearing in the file LICENSE.LGPLv3 included in the |
21 | ** packaging of this file. Please review the following information to |
22 | ** ensure the GNU Lesser General Public License version 3 requirements |
23 | ** will be met: https://www.gnu.org/licenses/lgpl.html. |
24 | ** |
25 | ** GNU General Public License Usage |
26 | ** Alternatively, this file may be used under the terms of the GNU |
27 | ** General Public License version 2.0 or later as published by the Free |
28 | ** Software Foundation and appearing in the file LICENSE.GPL included in |
29 | ** the packaging of this file. Please review the following information to |
30 | ** ensure the GNU General Public License version 2.0 requirements will be |
31 | ** met: http://www.gnu.org/licenses/gpl-2.0.html. |
32 | ** |
33 | ** $QT_END_LICENSE$ |
34 | ** |
35 | ****************************************************************************/ |
36 | |
37 | #include <QtTest> |
38 | #include <QtQuick> |
39 | #include <QtQuickControls2> |
40 | |
41 | typedef QPair<QString, QString> QStringPair; |
42 | |
43 | class tst_Snippets : public QObject |
44 | { |
45 | Q_OBJECT |
46 | |
47 | private slots: |
48 | void initTestCase(); |
49 | |
50 | void verify(); |
51 | void verify_data(); |
52 | |
53 | private: |
54 | void loadSnippet(const QString &source); |
55 | |
56 | bool takeScreenshots; |
57 | QMap<QString, QStringPair> snippetPaths; |
58 | }; |
59 | |
60 | static QMap<QString, QStringPair> findSnippets(const QDir &inputDir, const QDir &outputDir = QDir()) |
61 | { |
62 | QMap<QString, QStringPair> snippetPaths; |
63 | QDirIterator it(inputDir.path(), QStringList() << "qtquick*.qml" << "qtlabs*.qml" , QDir::Files | QDir::Readable); |
64 | while (it.hasNext()) { |
65 | QFileInfo fi(it.next()); |
66 | const QString outDirPath = !outputDir.path().isEmpty() ? outputDir.filePath(fileName: fi.baseName() + ".png" ) : QString(); |
67 | snippetPaths.insert(key: fi.baseName(), value: qMakePair(x: fi.filePath(), y: outDirPath)); |
68 | } |
69 | return snippetPaths; |
70 | } |
71 | |
72 | void tst_Snippets::initTestCase() |
73 | { |
74 | qInfo() << "Snippets are taken from" << QQC2_SNIPPETS_PATH; |
75 | |
76 | QDir snippetsDir(QQC2_SNIPPETS_PATH); |
77 | QVERIFY(!snippetsDir.path().isEmpty()); |
78 | |
79 | QDir screenshotsDir(QDir::current().filePath(fileName: "screenshots" )); |
80 | |
81 | takeScreenshots = qgetenv(varName: "SCREENSHOTS" ).toInt(); |
82 | if (takeScreenshots) |
83 | QVERIFY(screenshotsDir.exists() || QDir::current().mkpath("screenshots" )); |
84 | |
85 | snippetPaths = findSnippets(inputDir: snippetsDir, outputDir: screenshotsDir); |
86 | QVERIFY(!snippetPaths.isEmpty()); |
87 | } |
88 | |
89 | Q_DECLARE_METATYPE(QList<QQmlError>) |
90 | |
91 | void tst_Snippets::verify() |
92 | { |
93 | QFETCH(QString, input); |
94 | QFETCH(QString, output); |
95 | |
96 | QQmlEngine engine; |
97 | QQmlComponent component(&engine); |
98 | |
99 | qRegisterMetaType<QList<QQmlError> >(); |
100 | QSignalSpy warnings(&engine, SIGNAL(warnings(QList<QQmlError>))); |
101 | QVERIFY(warnings.isValid()); |
102 | |
103 | QUrl url = QUrl::fromLocalFile(localfile: input); |
104 | component.loadUrl(url); |
105 | |
106 | QScopedPointer<QObject> root(component.create()); |
107 | QVERIFY2(!root.isNull(), qPrintable(component.errorString())); |
108 | |
109 | QCOMPARE(component.status(), QQmlComponent::Ready); |
110 | QVERIFY(component.errors().isEmpty()); |
111 | |
112 | QVERIFY(warnings.isEmpty()); |
113 | |
114 | if (takeScreenshots) { |
115 | const QString currentDataTag = QLatin1String(QTest::currentDataTag()); |
116 | static const QString applicationStyle = QQuickStyle::name().isEmpty() ? "Default" : QQuickStyle::name(); |
117 | static const QStringList availableStyles = QQuickStyle::availableStyles(); |
118 | |
119 | bool isStyledSnippet = false; |
120 | const QString snippetStyle = currentDataTag.section(in_sep: "-" , start: 1, end: 1); |
121 | for (const QString &availableStyle : availableStyles) { |
122 | if (!snippetStyle.compare(s: availableStyle, cs: Qt::CaseInsensitive)) { |
123 | if (applicationStyle != availableStyle) |
124 | QSKIP(qPrintable(QString("%1 style specific snippet. Running with the %2 style." ).arg(availableStyle, applicationStyle))); |
125 | isStyledSnippet = true; |
126 | } |
127 | } |
128 | |
129 | if (!isStyledSnippet && !applicationStyle.isEmpty()) { |
130 | int index = output.indexOf(s: "-" , from: output.lastIndexOf(s: "/" )); |
131 | if (index != -1) |
132 | output.insert(i: index, s: "-" + applicationStyle.toLower()); |
133 | } |
134 | |
135 | QQuickWindow *window = qobject_cast<QQuickWindow *>(object: root.data()); |
136 | if (!window) { |
137 | QQuickView *view = new QQuickView; |
138 | view->setContent(url, component: &component, item: root.data()); |
139 | window = view; |
140 | } |
141 | |
142 | window->show(); |
143 | window->requestActivate(); |
144 | QVERIFY(QTest::qWaitForWindowActive(window)); |
145 | |
146 | QSharedPointer<QQuickItemGrabResult> result = window->contentItem()->grabToImage(); |
147 | QSignalSpy spy(result.data(), SIGNAL(ready())); |
148 | QVERIFY(spy.isValid()); |
149 | QVERIFY(spy.wait()); |
150 | QVERIFY(result->saveToFile(output)); |
151 | |
152 | window->close(); |
153 | } |
154 | } |
155 | |
156 | void tst_Snippets::verify_data() |
157 | { |
158 | QTest::addColumn<QString>(name: "input" ); |
159 | QTest::addColumn<QString>(name: "output" ); |
160 | |
161 | QMap<QString, QStringPair>::const_iterator it; |
162 | for (it = snippetPaths.constBegin(); it != snippetPaths.constEnd(); ++it) |
163 | QTest::newRow(qPrintable(it.key())) << it.value().first << it.value().second; |
164 | } |
165 | |
166 | QTEST_MAIN(tst_Snippets) |
167 | |
168 | #include "tst_snippets.moc" |
169 | |