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
41typedef QPair<QString, QString> QStringPair;
42
43class tst_Snippets : public QObject
44{
45 Q_OBJECT
46
47private slots:
48 void initTestCase();
49
50 void verify();
51 void verify_data();
52
53private:
54 void loadSnippet(const QString &source);
55
56 bool takeScreenshots;
57 QMap<QString, QStringPair> snippetPaths;
58};
59
60static 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
72void 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
89Q_DECLARE_METATYPE(QList<QQmlError>)
90
91void 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
156void 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
166QTEST_MAIN(tst_Snippets)
167
168#include "tst_snippets.moc"
169

source code of qtquickcontrols2/tests/auto/snippets/tst_snippets.cpp