aboutsummaryrefslogtreecommitdiffstats
path: root/src/quickcontrolstestutils/controlstestutils.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/quickcontrolstestutils/controlstestutils.cpp')
-rw-r--r--src/quickcontrolstestutils/controlstestutils.cpp182
1 files changed, 182 insertions, 0 deletions
diff --git a/src/quickcontrolstestutils/controlstestutils.cpp b/src/quickcontrolstestutils/controlstestutils.cpp
new file mode 100644
index 0000000000..a1e64784c4
--- /dev/null
+++ b/src/quickcontrolstestutils/controlstestutils.cpp
@@ -0,0 +1,182 @@
+/****************************************************************************
+**
+** Copyright (C) 2021 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "controlstestutils_p.h"
+
+#include <QtTest/qsignalspy.h>
+#include <QtQuickControls2/qquickstyle.h>
+#include <QtQuickTemplates2/private/qquickabstractbutton_p.h>
+#include <QtQuickTemplates2/private/qquickapplicationwindow_p.h>
+
+QQuickControlsTestUtils::QQuickControlsApplicationHelper::QQuickControlsApplicationHelper(QQmlDataTest *testCase,
+ const QString &testFilePath, const QStringList &qmlImportPaths, const QVariantMap &initialProperties)
+ : QQuickApplicationHelper(testCase, testFilePath, qmlImportPaths, initialProperties)
+{
+ if (ready)
+ appWindow = qobject_cast<QQuickApplicationWindow*>(cleanup.data());
+}
+
+bool QQuickControlsTestUtils::QQuickStyleHelper::updateStyle(const QString &style)
+{
+ // If it's not the first time a style has been set and the new style is not different, do nothing.
+ if (!currentStyle.isEmpty() && style == currentStyle)
+ return false;
+
+ engine.reset();
+ currentStyle = style;
+ qmlClearTypeRegistrations();
+ engine.reset(new QQmlEngine);
+ QQuickStyle::setStyle(style);
+
+ QQmlComponent component(engine.data());
+ component.setData(QString::fromUtf8("import QtQuick\nimport QtQuick.Controls\n Control { }").toUtf8(), QUrl());
+
+ return true;
+}
+
+void QQuickControlsTestUtils::forEachControl(QQmlEngine *engine, const QString &qqc2ImportPath,
+ const QString &sourcePath, const QString &targetPath, const QStringList &skipList,
+ QQuickControlsTestUtils::ForEachCallback callback)
+{
+ // We cannot use QQmlComponent to load QML files directly from the source tree.
+ // For styles that use internal QML types (eg. material/Ripple.qml), the source
+ // dir would be added as an "implicit" import path overriding the actual import
+ // path (qtbase/qml/QtQuick/Controls.2/Material). => The QML engine fails to load
+ // the style C++ plugin from the implicit import path (the source dir).
+ //
+ // Therefore we only use the source tree for finding out the set of QML files that
+ // a particular style implements, and then we locate the respective QML files in
+ // the engine's import path. This way we can use QQmlComponent to load each QML file
+ // for benchmarking.
+
+ const QFileInfoList entries = QDir(qqc2ImportPath + QLatin1Char('/') + sourcePath).entryInfoList(
+ QStringList(QStringLiteral("*.qml")), QDir::Files);
+ for (const QFileInfo &entry : entries) {
+ QString name = entry.baseName();
+ if (!skipList.contains(name)) {
+ const auto importPathList = engine->importPathList();
+ for (const QString &importPath : importPathList) {
+ QString name = entry.dir().dirName() + QLatin1Char('/') + entry.fileName();
+ QString filePath = importPath + QLatin1Char('/') + targetPath + QLatin1Char('/') + entry.fileName();
+ if (filePath.startsWith(QLatin1Char(':')))
+ filePath.prepend(QStringLiteral("qrc"));
+ if (QFile::exists(filePath)) {
+ callback(name, QUrl::fromLocalFile(filePath));
+ break;
+ } else {
+ QUrl url(filePath);
+ filePath = QQmlFile::urlToLocalFileOrQrc(filePath);
+ if (!filePath.isEmpty() && QFile::exists(filePath)) {
+ callback(name, url);
+ break;
+ }
+ }
+ }
+ }
+ }
+}
+
+void QQuickControlsTestUtils::addTestRowForEachControl(QQmlEngine *engine, const QString &qqc2ImportPath,
+ const QString &sourcePath, const QString &targetPath, const QStringList &skipList)
+{
+ forEachControl(engine, qqc2ImportPath, sourcePath, targetPath, skipList, [&](const QString &relativePath, const QUrl &absoluteUrl) {
+ QTest::newRow(qPrintable(relativePath)) << absoluteUrl;
+ });
+}
+
+bool QQuickControlsTestUtils::verifyButtonClickable(QQuickAbstractButton *button)
+{
+ if (!button->window()) {
+ qWarning() << "button" << button << "doesn't have an associated window";
+ return false;
+ }
+
+ if (!button->isEnabled()) {
+ qWarning() << "button" << button << "is not enabled";
+ return false;
+ }
+
+ if (!button->isVisible()) {
+ qWarning() << "button" << button << "is not visible";
+ return false;
+ }
+
+ if (button->width() <= 0.0) {
+ qWarning() << "button" << button << "must have a width greater than 0";
+ return false;
+ }
+
+ if (button->height() <= 0.0) {
+ qWarning() << "button" << button << "must have a height greater than 0";
+ return false;
+ }
+
+ return true;
+}
+
+bool QQuickControlsTestUtils::clickButton(QQuickAbstractButton *button)
+{
+ if (!verifyButtonClickable(button))
+ return false;
+
+ QSignalSpy spy(button, &QQuickAbstractButton::clicked);
+ if (!spy.isValid()) {
+ qWarning() << "button" << button << "must have a valid clicked signal";
+ return false;
+ }
+
+ const QPoint buttonCenter = button->mapToScene(QPointF(button->width() / 2, button->height() / 2)).toPoint();
+ QTest::mouseClick(button->window(), Qt::LeftButton, Qt::NoModifier, buttonCenter);
+ if (spy.count() != 1) {
+ qWarning() << "clicked signal of button" << button << "was not emitted after clicking";
+ return false;
+ }
+
+ return true;
+}
+
+bool QQuickControlsTestUtils::doubleClickButton(QQuickAbstractButton *button)
+{
+ if (!verifyButtonClickable(button))
+ return false;
+
+ QSignalSpy spy(button, &QQuickAbstractButton::clicked);
+ if (!spy.isValid()) {
+ qWarning() << "button" << button << "must have a valid doubleClicked signal";
+ return false;
+ }
+
+ const QPoint buttonCenter = button->mapToScene(QPointF(button->width() / 2, button->height() / 2)).toPoint();
+ QTest::mouseDClick(button->window(), Qt::LeftButton, Qt::NoModifier, buttonCenter);
+ if (spy.count() != 1) {
+ qWarning() << "doubleClicked signal of button" << button << "was not emitted after double-clicking";
+ return false;
+ }
+
+ return true;
+}