aboutsummaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/auto/qml/ecmascripttests/qjstest/test262runner.cpp2
-rw-r--r--tests/auto/qml/qjsengine/tst_qjsengine.cpp15
-rw-r--r--tests/auto/qml/qmllint/data/FromRootDirectParent.qml14
-rw-r--r--tests/auto/qml/qmllint/data/SignalHandler.qml10
-rw-r--r--tests/auto/qml/qmllint/data/nonSpuriousParentWarning.qml8
-rw-r--r--tests/auto/qml/qmllint/data/spuriousParentWarning.qml7
-rw-r--r--tests/auto/qml/qmllint/main.cpp39
-rw-r--r--tests/auto/qml/qmlmin/tst_qmlmin.cpp2
-rw-r--r--tests/auto/qml/qqmlapplicationengine/tst_qqmlapplicationengine.cpp6
-rw-r--r--tests/auto/qml/qqmldirparser/CMakeLists.txt15
-rw-r--r--tests/auto/qml/qqmldirparser/qqmldirparser.pro2
-rw-r--r--tests/auto/qml/qqmlecmascript/data/generatorFunction.qml22
-rw-r--r--tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp29
-rw-r--r--tests/auto/qml/qqmlengine/CMakeLists.txt23
-rw-r--r--tests/auto/qml/qqmlengine/qqmlengine.pro2
-rw-r--r--tests/auto/qml/qqmlengine/tst_qqmlengine.cpp54
-rw-r--r--tests/auto/qml/qqmlerror/tst_qqmlerror.cpp2
-rw-r--r--tests/auto/qml/qqmlexpression/tst_qqmlexpression.cpp7
-rw-r--r--tests/auto/qml/qqmlimport/CMakeLists.txt33
-rw-r--r--tests/auto/qml/qqmlimport/data/QTBUG-77102/imports/MyPlugin/MyComponent_0_9.qml14
-rw-r--r--tests/auto/qml/qqmlimport/data/QTBUG-77102/imports/MyPlugin/MyComponent_1_0.qml15
-rw-r--r--tests/auto/qml/qqmlimport/data/QTBUG-77102/imports/MyPlugin/MySettings_1_0.qml7
-rw-r--r--tests/auto/qml/qqmlimport/data/QTBUG-77102/imports/MyPlugin/qmldir6
-rw-r--r--tests/auto/qml/qqmlimport/data/QTBUG-77102/main.0.9.fail.qml11
-rw-r--r--tests/auto/qml/qqmlimport/data/QTBUG-77102/main.0.9.qml11
-rw-r--r--tests/auto/qml/qqmlimport/data/QTBUG-77102/main.1.0.qml11
-rw-r--r--tests/auto/qml/qqmlimport/data/QTBUG-77102/main.nonumber.qml11
-rw-r--r--tests/auto/qml/qqmlimport/qqmlimport.pro5
-rw-r--r--tests/auto/qml/qqmlimport/tst_qqmlimport.cpp50
-rw-r--r--tests/auto/qml/qqmllocale/tst_qqmllocale.cpp17
-rw-r--r--tests/auto/qml/qqmlnotifier/tst_qqmlnotifier.cpp3
-rw-r--r--tests/auto/qml/qqmlpromise/data/promisechain.qml24
-rw-r--r--tests/auto/qml/qqmlpromise/tst_qqmlpromise.cpp15
-rw-r--r--tests/auto/qml/qqmlproperty/data/nullPropertyBinding.qml22
-rw-r--r--tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp17
-rw-r--r--tests/auto/quick/pointerhandlers/multipointtoucharea_interop/data/dragParentOfMPTA.qml50
-rw-r--r--tests/auto/quick/pointerhandlers/multipointtoucharea_interop/tst_multipointtoucharea_interop.cpp43
-rw-r--r--tests/auto/quick/pointerhandlers/qquickdraghandler/tst_qquickdraghandler.cpp82
-rw-r--r--tests/auto/quick/pointerhandlers/qquicktaphandler/data/Button.qml2
-rw-r--r--tests/auto/quick/pointerhandlers/qquicktaphandler/tst_qquicktaphandler.cpp8
-rw-r--r--tests/auto/quick/qquickflickable/tst_qquickflickable.cpp3
-rw-r--r--tests/auto/quick/qquicklistview/data/resizeAfterComponentComplete.qml77
-rw-r--r--tests/auto/quick/qquicklistview/tst_qquicklistview.cpp16
-rw-r--r--tests/auto/quick/qquickshape/data/pathitem8.pngbin0 -> 7323 bytes
-rw-r--r--tests/auto/quick/qquickshape/data/pathitem8.qml88
-rw-r--r--tests/auto/quick/qquickshape/tst_qquickshape.cpp30
-rw-r--r--tests/auto/quick/qquicktext/BLACKLIST2
-rw-r--r--tests/manual/nodetypes_ng/MultiClipRects.qml20
-rw-r--r--tests/manual/scenegraph_lancelot/data/shape/shape_multiline.qml74
49 files changed, 935 insertions, 91 deletions
diff --git a/tests/auto/qml/ecmascripttests/qjstest/test262runner.cpp b/tests/auto/qml/ecmascripttests/qjstest/test262runner.cpp
index 33efcb4da4..9fe2de5368 100644
--- a/tests/auto/qml/ecmascripttests/qjstest/test262runner.cpp
+++ b/tests/auto/qml/ecmascripttests/qjstest/test262runner.cpp
@@ -597,7 +597,7 @@ void SingleTest::run()
void SingleTest::runExternalTest()
{
- auto runTest = [=] (const char *header, TestCase::Result *result) {
+ auto runTest = [this] (const char *header, TestCase::Result *result) {
QTemporaryFile tempFile;
tempFile.open();
tempFile.write(header);
diff --git a/tests/auto/qml/qjsengine/tst_qjsengine.cpp b/tests/auto/qml/qjsengine/tst_qjsengine.cpp
index e08a1cc37e..0ccb8210bc 100644
--- a/tests/auto/qml/qjsengine/tst_qjsengine.cpp
+++ b/tests/auto/qml/qjsengine/tst_qjsengine.cpp
@@ -249,6 +249,8 @@ private slots:
void interrupt_data();
void interrupt();
+ void triggerBackwardJumpWithDestructuring();
+
public:
Q_INVOKABLE QJSValue throwingCppMethod1();
Q_INVOKABLE void throwingCppMethod2();
@@ -4938,6 +4940,19 @@ void tst_QJSEngine::interrupt()
#endif
}
+void tst_QJSEngine::triggerBackwardJumpWithDestructuring()
+{
+ QJSEngine engine;
+ auto value = engine.evaluate(
+ "function makeArray(n) { return [...Array(n).keys()]; }\n"
+ "for (let i=0;i<100;++i) {\n"
+ " let arr = makeArray(20)\n"
+ " arr.sort( (a, b) => b - a )\n"
+ "}"
+ );
+ QVERIFY(!value.isError());
+}
+
QTEST_MAIN(tst_QJSEngine)
#include "tst_qjsengine.moc"
diff --git a/tests/auto/qml/qmllint/data/FromRootDirectParent.qml b/tests/auto/qml/qmllint/data/FromRootDirectParent.qml
deleted file mode 100644
index c0bfd0f26b..0000000000
--- a/tests/auto/qml/qmllint/data/FromRootDirectParent.qml
+++ /dev/null
@@ -1,14 +0,0 @@
-import QtQuick 2.0
-
-Item {
- id: root
- property int unqualified: 42
-
- Item {
- x: unqualified // user defined property from root
- }
-
- QtObject {
- property int check: x // existing property from root
- }
-}
diff --git a/tests/auto/qml/qmllint/data/SignalHandler.qml b/tests/auto/qml/qmllint/data/SignalHandler.qml
index bdf503e3dc..865277cedb 100644
--- a/tests/auto/qml/qmllint/data/SignalHandler.qml
+++ b/tests/auto/qml/qmllint/data/SignalHandler.qml
@@ -1,5 +1,13 @@
import QtQuick 2.0
MouseArea {
- onDoubleClicked: console.log(mouse);
+ onDoubleClicked: {
+ console.log(mouse);
+ // do further things
+ }
+ onClicked: console.info(mouse)
+ onPositionChanged: {
+ console.log(mouse)
+ }
+ onPressAndHold: console.warn(mouse)
}
diff --git a/tests/auto/qml/qmllint/data/nonSpuriousParentWarning.qml b/tests/auto/qml/qmllint/data/nonSpuriousParentWarning.qml
new file mode 100644
index 0000000000..a59b736929
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/nonSpuriousParentWarning.qml
@@ -0,0 +1,8 @@
+import QtQuick 2.12
+import QtQml 2.12
+
+Item {
+ QtObject {
+ property int x: parent.x
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/spuriousParentWarning.qml b/tests/auto/qml/qmllint/data/spuriousParentWarning.qml
new file mode 100644
index 0000000000..1323593031
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/spuriousParentWarning.qml
@@ -0,0 +1,7 @@
+import QtQuick 2.12
+
+Item {
+ Unknown {
+ property int x: parent.x
+ }
+}
diff --git a/tests/auto/qml/qmllint/main.cpp b/tests/auto/qml/qmllint/main.cpp
index 038826790b..928575bc82 100644
--- a/tests/auto/qml/qmllint/main.cpp
+++ b/tests/auto/qml/qmllint/main.cpp
@@ -40,6 +40,7 @@ private Q_SLOTS:
void test_data();
void testUnqualified();
void testUnqualified_data();
+ void testUnqualifiedNoSpuriousParentWarning();
private:
QString m_qmllintPath;
};
@@ -73,13 +74,14 @@ void TestQmllint::test_data()
void TestQmllint::testUnqualified()
{
+ auto qmlImportDir = QLibraryInfo::location(QLibraryInfo::Qml2ImportsPath);
QFETCH(QString, filename);
QFETCH(QString, warningMessage);
QFETCH(int, warningLine);
QFETCH(int, warningColumn);
filename.prepend(QStringLiteral("data/"));
QStringList args;
- args << QStringLiteral("-U") << filename;
+ args << QStringLiteral("-U") << filename << QStringLiteral("-I") << qmlImportDir;
QProcess process;
process.start(m_qmllintPath, args);
@@ -106,14 +108,41 @@ void TestQmllint::testUnqualified_data()
// access property of root object
QTest::newRow("FromRootDirect") << QStringLiteral("FromRoot.qml") << QStringLiteral("x: root.unqualified") << 9 << 16; // new property
QTest::newRow("FromRootAccess") << QStringLiteral("FromRoot.qml") << QStringLiteral("property int check: root.x") << 13 << 33; // builtin property
- // access property of root object from direct child
- QTest::newRow("FromRootDirectParentDirect") << QStringLiteral("FromRootDirectParent.qml") << QStringLiteral("x: parent.unqualified") << 8 << 12;
- QTest::newRow("FromRootDirectParentAccess") << QStringLiteral("FromRootDirectParent.qml") << QStringLiteral("property int check: parent.x") << 12 << 29;
// access injected name from signal
- QTest::newRow("SignalHandler") << QStringLiteral("SignalHandler.qml") << QStringLiteral("onDoubleClicked: function(mouse) {...") << 4 << 34;
+ QTest::newRow("SignalHandler1") << QStringLiteral("SignalHandler.qml") << QStringLiteral("onDoubleClicked: function(mouse) {...") << 5 << 21;
+ QTest::newRow("SignalHandler2") << QStringLiteral("SignalHandler.qml") << QStringLiteral("onPositionChanged: function(mouse) {...") << 10 << 21;
+ QTest::newRow("SignalHandlerShort1") << QStringLiteral("SignalHandler.qml") << QStringLiteral("onClicked: (mouse) => {...") << 8 << 29;
+ QTest::newRow("SignalHandlerShort2") << QStringLiteral("SignalHandler.qml") << QStringLiteral("onPressAndHold: (mouse) => {...") << 12 << 34;
}
+void TestQmllint::testUnqualifiedNoSpuriousParentWarning()
+{
+ auto qmlImportDir = QLibraryInfo::location(QLibraryInfo::Qml2ImportsPath);
+ {
+ QString filename = QLatin1String("spuriousParentWarning.qml");
+ filename.prepend(QStringLiteral("data/"));
+ QStringList args;
+ args << QStringLiteral("-U") << filename << QStringLiteral("-I") << qmlImportDir;
+ QProcess process;
+ process.start(m_qmllintPath, args);
+ QVERIFY(process.waitForFinished());
+ QVERIFY(process.exitStatus() == QProcess::NormalExit);
+ QVERIFY(process.exitCode() == 0);
+ }
+ {
+ QString filename = QLatin1String("nonSpuriousParentWarning.qml");
+ filename.prepend(QStringLiteral("data/"));
+ QStringList args;
+ args << QStringLiteral("-U") << filename << QStringLiteral("-I") << qmlImportDir;
+ QProcess process;
+ process.start(m_qmllintPath, args);
+ QVERIFY(process.waitForFinished());
+ QVERIFY(process.exitStatus() == QProcess::NormalExit);
+ QVERIFY(process.exitCode());
+ }
+}
+
void TestQmllint::test()
{
QFETCH(QString, filename);
diff --git a/tests/auto/qml/qmlmin/tst_qmlmin.cpp b/tests/auto/qml/qmlmin/tst_qmlmin.cpp
index 696ec66246..cae833cd60 100644
--- a/tests/auto/qml/qmlmin/tst_qmlmin.cpp
+++ b/tests/auto/qml/qmlmin/tst_qmlmin.cpp
@@ -130,6 +130,8 @@ void tst_qmlmin::initTestCase()
invalidFiles << "tests/auto/qml/qjsengine/script/com/trolltech/syntaxerror/__init__.js";
invalidFiles << "tests/auto/qml/debugger/qqmlpreview/data/broken.qml";
invalidFiles << "tests/auto/qml/qqmllanguage/data/fuzzed.2.qml";
+ // generatorFunction.qml is not invalid per se, but the minifier cannot handle yield statements
+ invalidFiles << "tests/auto/qml/qqmlecmascript/data/generatorFunction.qml";
#endif
}
diff --git a/tests/auto/qml/qqmlapplicationengine/tst_qqmlapplicationengine.cpp b/tests/auto/qml/qqmlapplicationengine/tst_qqmlapplicationengine.cpp
index a9c28a0911..8787a43884 100644
--- a/tests/auto/qml/qqmlapplicationengine/tst_qqmlapplicationengine.cpp
+++ b/tests/auto/qml/qqmlapplicationengine/tst_qqmlapplicationengine.cpp
@@ -96,6 +96,9 @@ void tst_qqmlapplicationengine::basicLoading()
// will break.
void tst_qqmlapplicationengine::testNonResolvedPath()
{
+#ifdef Q_OS_ANDROID
+ QSKIP("Android stores QML files in resources, and the path to a resource cannot be relative in this case");
+#endif
{
// NOTE NOTE NOTE! Missing testFileUrl is *WANTED* here! We want a
// non-resolved URL.
@@ -117,6 +120,9 @@ void tst_qqmlapplicationengine::testNonResolvedPath()
void tst_qqmlapplicationengine::application_data()
{
+#ifdef Q_OS_ANDROID
+ QSKIP("Cannot launch external process on Android");
+#endif
QTest::addColumn<QByteArray>("qmlFile");
QTest::addColumn<QByteArray>("expectedStdErr");
diff --git a/tests/auto/qml/qqmldirparser/CMakeLists.txt b/tests/auto/qml/qqmldirparser/CMakeLists.txt
index 21a8fa44ae..30efe97fed 100644
--- a/tests/auto/qml/qqmldirparser/CMakeLists.txt
+++ b/tests/auto/qml/qqmldirparser/CMakeLists.txt
@@ -4,6 +4,14 @@
## tst_qqmldirparser Test:
#####################################################################
+# Collect test data
+
+file(GLOB test_data_glob
+ LIST_DIRECTORIES true
+ RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
+ "data/*")
+list(APPEND test_data ${test_data_glob})
+
add_qt_test(tst_qqmldirparser
GUI
SOURCES
@@ -16,17 +24,12 @@ add_qt_test(tst_qqmldirparser
PUBLIC_LIBRARIES
Qt::Gui
Qt::Qml
+ TESTDATA ${test_data}
)
-#### Keys ignored in scope 1:.:.:qqmldirparser.pro:<TRUE>:
-# CONFIG = "testcase"
-
## Scopes:
#####################################################################
-#### Keys ignored in scope 2:.:.:qqmldirparser.pro:APPLE_OSX:
-# CONFIG = "-app_bundle"
-
extend_target(tst_qqmldirparser CONDITION ANDROID OR APPLE_IOS
DEFINES
QT_QMLTEST_DATADIR=\\\":/data\\\"
diff --git a/tests/auto/qml/qqmldirparser/qqmldirparser.pro b/tests/auto/qml/qqmldirparser/qqmldirparser.pro
index dda74b1ef9..b5373a6e8f 100644
--- a/tests/auto/qml/qqmldirparser/qqmldirparser.pro
+++ b/tests/auto/qml/qqmldirparser/qqmldirparser.pro
@@ -6,3 +6,5 @@ macx:CONFIG -= app_bundle
SOURCES += tst_qqmldirparser.cpp
include (../../shared/util.pri)
+
+TESTDATA = data/*
diff --git a/tests/auto/qml/qqmlecmascript/data/generatorFunction.qml b/tests/auto/qml/qqmlecmascript/data/generatorFunction.qml
new file mode 100644
index 0000000000..66bb642f34
--- /dev/null
+++ b/tests/auto/qml/qqmlecmascript/data/generatorFunction.qml
@@ -0,0 +1,22 @@
+import QtQml 2.12
+
+QtObject {
+ id: root
+ property bool test1: false;
+ property bool test2: false;
+ property bool test3: false;
+ property bool done: false;
+ function *gen() {
+ yield 1
+ yield 2
+ yield 3
+ }
+
+ Component.onCompleted: {
+ let it = root.gen();
+ root.test1 = (it.next().value == 1);
+ root.test2 = (it.next().value == 2);
+ root.test3 = (it.next().value == 3);
+ root.done = it.next().done;
+ }
+}
diff --git a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
index d603ca6907..b44fe9766c 100644
--- a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
+++ b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
@@ -233,6 +233,7 @@ private slots:
void functionAssignment_afterBinding();
void eval();
void function();
+ void topLevelGeneratorFunction();
void qtbug_10696();
void qtbug_11606();
void qtbug_11600();
@@ -2048,7 +2049,7 @@ void tst_qqmlecmascript::functionErrors()
QObject *resource = qobject_cast<ScarceResourceObject*>(QQmlProperty::read(object, "a").value<QObject*>());
warning = url + QLatin1String(":16: TypeError: Property 'scarceResource' of object ScarceResourceObject(0x%1) is not a function");
- warning = warning.arg(QString::number((qintptr)resource, 16));
+ warning = warning.arg(QString::number((quintptr)resource, 16));
QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData()); // we expect a meaningful warning to be printed.
QMetaObject::invokeMethod(object, "retrieveScarceResource");
delete object;
@@ -4573,7 +4574,7 @@ void tst_qqmlecmascript::scarceResources_other()
eo = qobject_cast<ScarceResourceObject*>(QQmlProperty::read(object, "a").value<QObject*>());
QVERIFY(eo->scarceResourceIsDetached()); // should be no other copies of it at this stage.
expectedWarning = varComponentTwelve.url().toString() + QLatin1String(":16: TypeError: Property 'scarceResource' of object ScarceResourceObject(0x%1) is not a function");
- expectedWarning = expectedWarning.arg(QString::number((qintptr)eo, 16));
+ expectedWarning = expectedWarning.arg(QString::number((quintptr)eo, 16));
QTest::ignoreMessage(QtWarningMsg, qPrintable(expectedWarning)); // we expect a meaningful warning to be printed.
QMetaObject::invokeMethod(object, "retrieveScarceResource");
QVERIFY(!object->property("scarceResourceCopy").isValid()); // due to exception, assignment will NOT have occurred.
@@ -4647,7 +4648,7 @@ void tst_qqmlecmascript::scarceResources_other()
eo = qobject_cast<ScarceResourceObject*>(QQmlProperty::read(object, "a").value<QObject*>());
QVERIFY(eo->scarceResourceIsDetached()); // should be no other copies of it at this stage.
expectedWarning = variantComponentTwelve.url().toString() + QLatin1String(":16: TypeError: Property 'scarceResource' of object ScarceResourceObject(0x%1) is not a function");
- expectedWarning = expectedWarning.arg(QString::number((qintptr)eo, 16));
+ expectedWarning = expectedWarning.arg(QString::number((quintptr)eo, 16));
QTest::ignoreMessage(QtWarningMsg, qPrintable(expectedWarning)); // we expect a meaningful warning to be printed.
QMetaObject::invokeMethod(object, "retrieveScarceResource");
QVERIFY(!object->property("scarceResourceCopy").isValid()); // due to exception, assignment will NOT have occurred.
@@ -6348,6 +6349,28 @@ void tst_qqmlecmascript::function()
delete o;
}
+// QTBUG-77096
+void tst_qqmlecmascript::topLevelGeneratorFunction()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine, testFileUrl("generatorFunction.qml"));
+
+ QScopedPointer<QObject> o {component.create()};
+ QVERIFY(o != nullptr);
+
+ // check that generator works correctly in QML
+ QCOMPARE(o->property("test1").toBool(), true);
+ QCOMPARE(o->property("test2").toBool(), true);
+ QCOMPARE(o->property("test3").toBool(), true);
+ QCOMPARE(o->property("done").toBool(), true);
+
+ // check that generator is accessible from C++
+ QVariant returnedValue;
+ QMetaObject::invokeMethod(o.get(), "gen", Q_RETURN_ARG(QVariant, returnedValue));
+ auto it = returnedValue.value<QJSValue>();
+ QCOMPARE(it.property("next").callWithInstance(it).property("value").toInt(), 1);
+}
+
// Test the "Qt.include" method
void tst_qqmlecmascript::include()
{
diff --git a/tests/auto/qml/qqmlengine/CMakeLists.txt b/tests/auto/qml/qqmlengine/CMakeLists.txt
index 5f38633234..e4c38d384c 100644
--- a/tests/auto/qml/qqmlengine/CMakeLists.txt
+++ b/tests/auto/qml/qqmlengine/CMakeLists.txt
@@ -4,6 +4,14 @@
## tst_qqmlengine Test:
#####################################################################
+# Collect test data
+
+file(GLOB test_data_glob
+ LIST_DIRECTORIES true
+ RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
+ "data/*")
+list(APPEND test_data ${test_data_glob})
+
add_qt_test(tst_qqmlengine
GUI
SOURCES
@@ -19,27 +27,26 @@ add_qt_test(tst_qqmlengine
Qt::Gui
Qt::Network
Qt::Qml
+ TESTDATA ${test_data}
)
# Resources:
+set(qmake_immediate_resource_files
+ "data/qrcurls.js"
+ "data/qrcurls.qml"
+)
+
add_qt_resource(tst_qqmlengine "qmake_immediate"
PREFIX
"/"
FILES
- data/qrcurls.js
- data/qrcurls.qml
+ ${qmake_immediate_resource_files}
)
-#### Keys ignored in scope 1:.:.:qqmlengine.pro:<TRUE>:
-# CONFIG = "testcase"
-
## Scopes:
#####################################################################
-#### Keys ignored in scope 2:.:.:qqmlengine.pro:APPLE_OSX:
-# CONFIG = "-app_bundle"
-
extend_target(tst_qqmlengine CONDITION boot2qt
DEFINES
SKIP_GCCORRUPTION_TEST
diff --git a/tests/auto/qml/qqmlengine/qqmlengine.pro b/tests/auto/qml/qqmlengine/qqmlengine.pro
index d2eb92bfd5..8946201ea0 100644
--- a/tests/auto/qml/qqmlengine/qqmlengine.pro
+++ b/tests/auto/qml/qqmlengine/qqmlengine.pro
@@ -4,6 +4,8 @@ macx:CONFIG -= app_bundle
include (../../shared/util.pri)
+TESTDATA = data/*
+
SOURCES += tst_qqmlengine.cpp
QT += core-private gui-private qml-private network testlib
diff --git a/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp b/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp
index 66d50cfe39..aae42e9ebb 100644
--- a/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp
+++ b/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp
@@ -428,7 +428,7 @@ void tst_qqmlengine::trimComponentCache()
engine.setIncubationController(&componentCache);
QQmlComponent component(&engine, testFileUrl(file));
- QVERIFY(component.isReady());
+ QVERIFY2(component.isReady(), qPrintable(component.errorString()));
QScopedPointer<QObject> object(component.create());
QVERIFY(object != nullptr);
QCOMPARE(object->property("success").toBool(), true);
@@ -742,13 +742,17 @@ public:
CustomSelector(const QUrl &base):m_base(base){}
virtual QUrl intercept(const QUrl &url, QQmlAbstractUrlInterceptor::DataType d)
{
- if (url.scheme() != QStringLiteral("file"))
+ if ((url.scheme() != QStringLiteral("file") && url.scheme() != QStringLiteral("qrc"))
+ || url.path().contains("QtQml"))
return url;
if (!m_interceptionPoints.contains(d))
return url;
- if (url.path().endsWith("Test.2/qmldir"))//Special case
- return QUrl::fromLocalFile(m_base.path() + "interception/module/intercepted/qmldir");
+ if (url.path().endsWith("Test.2/qmldir")) {//Special case
+ QUrl url = m_base;
+ url.setPath(m_base.path() + "interception/module/intercepted/qmldir");
+ return url;
+ }
// Special case: with 5.10 we always add the implicit import, so we need to explicitly handle this case now
if (url.path().endsWith("intercepted/qmldir"))
return url;
@@ -836,7 +840,7 @@ void tst_qqmlengine::urlInterceptor()
QFETCH(QString, expectedAbsoluteUrl);
QQmlEngine e;
- e.addImportPath(testFileUrl("interception/imports").toLocalFile());
+ e.addImportPath(testFileUrl("interception/imports").url());
CustomSelector cs(testFileUrl(""));
cs.m_interceptionPoints = interceptionPoint;
e.setUrlInterceptor(&cs);
@@ -1033,6 +1037,46 @@ void tst_qqmlengine::singletonInstance()
{
qmlRegisterSingletonType<CppSingleton>("Qt.test",1,0,"NotAmbiguous", [](QQmlEngine* qeng, QJSEngine* jeng) -> QObject* {return CppSingleton::create(qeng, jeng);}); // test that overloads for qmlRegisterSingleton are not ambiguous
}
+ {
+ // Register QObject* directly
+ CppSingleton single;
+ int id = qmlRegisterSingletonInstance("Qt.test", 1, 0, "CppOwned",
+ &single);
+ QQmlEngine engine2;
+ CppSingleton *singlePtr = engine2.singletonInstance<CppSingleton *>(id);
+ QVERIFY(singlePtr);
+ QCOMPARE(&single, singlePtr);
+ QVERIFY(engine2.objectOwnership(singlePtr) == QQmlEngine::CppOwnership);
+ }
+
+ {
+ CppSingleton single;
+ QQmlEngine engineA;
+ QQmlEngine engineB;
+ int id = qmlRegisterSingletonInstance("Qt.test", 1, 0, "CppOwned", &single);
+ auto singlePtr = engineA.singletonInstance<CppSingleton *>(id);
+ QVERIFY(singlePtr);
+ singlePtr = engineA.singletonInstance<CppSingleton *>(id); // accessing the singleton multiple times from the same engine is fine
+ QVERIFY(singlePtr);
+ QTest::ignoreMessage(QtMsgType::QtCriticalMsg, "<Unknown File>: qmlRegisterSingletonType(): \"CppOwned\" is not available because the callback function returns a null pointer.");
+ QTest::ignoreMessage(QtMsgType::QtWarningMsg, "<Unknown File>: Singleton registered by registerSingletonInstance must only be accessed from one engine");
+ QCOMPARE(&single, singlePtr);
+ auto noSinglePtr = engineB.singletonInstance<CppSingleton *>(id);
+ QVERIFY(!noSinglePtr);
+ }
+
+ {
+ CppSingleton single;
+ QThread newThread {};
+ single.moveToThread(&newThread);
+ QCOMPARE(single.thread(), &newThread);
+ QQmlEngine engineB;
+ int id = qmlRegisterSingletonInstance("Qt.test", 1, 0, "CppOwned", &single);
+ QTest::ignoreMessage(QtMsgType::QtCriticalMsg, "<Unknown File>: qmlRegisterSingletonType(): \"CppOwned\" is not available because the callback function returns a null pointer.");
+ QTest::ignoreMessage(QtMsgType::QtWarningMsg, "<Unknown File>: Registered object must live in the same thread as the engine it was registered with");
+ auto noSinglePtr = engineB.singletonInstance<CppSingleton *>(id);
+ QVERIFY(!noSinglePtr);
+ }
{
// Invalid types
diff --git a/tests/auto/qml/qqmlerror/tst_qqmlerror.cpp b/tests/auto/qml/qqmlerror/tst_qqmlerror.cpp
index 7a7185e909..f282e60417 100644
--- a/tests/auto/qml/qqmlerror/tst_qqmlerror.cpp
+++ b/tests/auto/qml/qqmlerror/tst_qqmlerror.cpp
@@ -195,7 +195,7 @@ void tst_qqmlerror::debug()
}
{
- QUrl url(dataDirectoryUrl().resolved(QUrl("test.txt")));
+ QUrl url = testFileUrl("test.txt");
QQmlError error;
error.setUrl(url);
error.setDescription("An Error");
diff --git a/tests/auto/qml/qqmlexpression/tst_qqmlexpression.cpp b/tests/auto/qml/qqmlexpression/tst_qqmlexpression.cpp
index 1decc04ad2..0ba29d6b6a 100644
--- a/tests/auto/qml/qqmlexpression/tst_qqmlexpression.cpp
+++ b/tests/auto/qml/qqmlexpression/tst_qqmlexpression.cpp
@@ -28,6 +28,7 @@
#include <qtest.h>
#include <QtQml/qqmlengine.h>
+#include <QtQml/qqmlfile.h>
#include <QtQml/qqmlcomponent.h>
#include <QtQml/qqmlexpression.h>
#include <QtQml/qqmlscriptstring.h>
@@ -125,10 +126,12 @@ void tst_qqmlexpression::expressionFromDataComponent()
QQmlEngine engine;
QQmlComponent c(&engine);
- QUrl url = testFileUrl("expressionFromDataComponent.qml");
+ const QString fn(QLatin1String("expressionFromDataComponent.qml"));
+ QUrl url = testFileUrl(fn);
+ QString path = testFile(fn);
{
- QFile f(url.toLocalFile());
+ QFile f(path);
QVERIFY(f.open(QIODevice::ReadOnly));
c.setData(f.readAll(), url);
}
diff --git a/tests/auto/qml/qqmlimport/CMakeLists.txt b/tests/auto/qml/qqmlimport/CMakeLists.txt
index 71f71c7326..50b588cb04 100644
--- a/tests/auto/qml/qqmlimport/CMakeLists.txt
+++ b/tests/auto/qml/qqmlimport/CMakeLists.txt
@@ -4,6 +4,32 @@
## tst_qqmlimport Test:
#####################################################################
+# Collect test data
+
+file(GLOB test_data_glob
+ LIST_DIRECTORIES true
+ RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
+ "data/*")
+list(APPEND test_data ${test_data_glob})
+
+file(GLOB test_data_glob
+ LIST_DIRECTORIES true
+ RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
+ "MyPluginSupported/*")
+list(APPEND test_data ${test_data_glob})
+
+file(GLOB test_data_glob
+ LIST_DIRECTORIES true
+ RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
+ "MyPluginUnsupported/*")
+list(APPEND test_data ${test_data_glob})
+
+file(GLOB test_data_glob
+ LIST_DIRECTORIES true
+ RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
+ "FormFromQmlDir/*")
+list(APPEND test_data ${test_data_glob})
+
add_qt_test(tst_qqmlimport
GUI
SOURCES
@@ -17,17 +43,12 @@ add_qt_test(tst_qqmlimport
Qt::Gui
Qt::Qml
Qt::Quick
+ TESTDATA ${test_data}
)
-#### Keys ignored in scope 1:.:.:qqmlimport.pro:<TRUE>:
-# CONFIG = "testcase"
-
## Scopes:
#####################################################################
-#### Keys ignored in scope 2:.:.:qqmlimport.pro:APPLE_OSX:
-# CONFIG = "-app_bundle"
-
extend_target(tst_qqmlimport CONDITION ANDROID OR APPLE_IOS
DEFINES
QT_QMLTEST_DATADIR=\\\":/data\\\"
diff --git a/tests/auto/qml/qqmlimport/data/QTBUG-77102/imports/MyPlugin/MyComponent_0_9.qml b/tests/auto/qml/qqmlimport/data/QTBUG-77102/imports/MyPlugin/MyComponent_0_9.qml
new file mode 100644
index 0000000000..a63e2d121c
--- /dev/null
+++ b/tests/auto/qml/qqmlimport/data/QTBUG-77102/imports/MyPlugin/MyComponent_0_9.qml
@@ -0,0 +1,14 @@
+import QtQuick 2.0
+
+Rectangle {
+ width: 50
+ height: 50
+
+ color: "yellow"
+
+ Text {
+ anchors.centerIn: parent
+ text: "0.9"
+
+ }
+}
diff --git a/tests/auto/qml/qqmlimport/data/QTBUG-77102/imports/MyPlugin/MyComponent_1_0.qml b/tests/auto/qml/qqmlimport/data/QTBUG-77102/imports/MyPlugin/MyComponent_1_0.qml
new file mode 100644
index 0000000000..d9cff582bb
--- /dev/null
+++ b/tests/auto/qml/qqmlimport/data/QTBUG-77102/imports/MyPlugin/MyComponent_1_0.qml
@@ -0,0 +1,15 @@
+
+import QtQuick 2.0
+
+Rectangle {
+ width: 50
+ height: 50
+
+ color: "orange"
+
+ Text {
+ anchors.centerIn: parent
+ text: "1.0"
+
+ }
+}
diff --git a/tests/auto/qml/qqmlimport/data/QTBUG-77102/imports/MyPlugin/MySettings_1_0.qml b/tests/auto/qml/qqmlimport/data/QTBUG-77102/imports/MyPlugin/MySettings_1_0.qml
new file mode 100644
index 0000000000..63ad6ba1a5
--- /dev/null
+++ b/tests/auto/qml/qqmlimport/data/QTBUG-77102/imports/MyPlugin/MySettings_1_0.qml
@@ -0,0 +1,7 @@
+pragma Singleton
+
+import QtQuick 2.0
+
+Item {
+ property int baseWidth: 50
+}
diff --git a/tests/auto/qml/qqmlimport/data/QTBUG-77102/imports/MyPlugin/qmldir b/tests/auto/qml/qqmlimport/data/QTBUG-77102/imports/MyPlugin/qmldir
new file mode 100644
index 0000000000..57b8c55f81
--- /dev/null
+++ b/tests/auto/qml/qqmlimport/data/QTBUG-77102/imports/MyPlugin/qmldir
@@ -0,0 +1,6 @@
+module MyPlugin
+
+MyComponent 0.9 MyComponent_0_9.qml
+
+MyComponent 1.0 MyComponent_1_0.qml
+singleton MySettings 1.0 MySettings_1_0.qml
diff --git a/tests/auto/qml/qqmlimport/data/QTBUG-77102/main.0.9.fail.qml b/tests/auto/qml/qqmlimport/data/QTBUG-77102/main.0.9.fail.qml
new file mode 100644
index 0000000000..0fbcec607a
--- /dev/null
+++ b/tests/auto/qml/qqmlimport/data/QTBUG-77102/main.0.9.fail.qml
@@ -0,0 +1,11 @@
+import QtQuick 2.12
+import MyPlugin 0.9
+
+Item {
+ width: MySettings.baseWidth
+ height: 100
+
+ MyComponent {
+ anchors.centerIn: parent
+ }
+}
diff --git a/tests/auto/qml/qqmlimport/data/QTBUG-77102/main.0.9.qml b/tests/auto/qml/qqmlimport/data/QTBUG-77102/main.0.9.qml
new file mode 100644
index 0000000000..53fc25699c
--- /dev/null
+++ b/tests/auto/qml/qqmlimport/data/QTBUG-77102/main.0.9.qml
@@ -0,0 +1,11 @@
+import QtQuick 2.12
+import MyPlugin 0.9
+
+Item {
+ width: 100
+ height: 100
+
+ MyComponent {
+ anchors.centerIn: parent
+ }
+}
diff --git a/tests/auto/qml/qqmlimport/data/QTBUG-77102/main.1.0.qml b/tests/auto/qml/qqmlimport/data/QTBUG-77102/main.1.0.qml
new file mode 100644
index 0000000000..1f6244068b
--- /dev/null
+++ b/tests/auto/qml/qqmlimport/data/QTBUG-77102/main.1.0.qml
@@ -0,0 +1,11 @@
+import QtQuick 2.12
+import MyPlugin 1.0
+
+Item {
+ width: MySettings.baseWidth
+ height: 100
+
+ MyComponent {
+ anchors.centerIn: parent
+ }
+}
diff --git a/tests/auto/qml/qqmlimport/data/QTBUG-77102/main.nonumber.qml b/tests/auto/qml/qqmlimport/data/QTBUG-77102/main.nonumber.qml
new file mode 100644
index 0000000000..dea00c0163
--- /dev/null
+++ b/tests/auto/qml/qqmlimport/data/QTBUG-77102/main.nonumber.qml
@@ -0,0 +1,11 @@
+import QtQuick 2.12
+import "imports/MyPlugin"
+
+Item {
+ width: MySettings.baseWidth
+ height: 100
+
+ MyComponent {
+ anchors.centerIn: parent
+ }
+}
diff --git a/tests/auto/qml/qqmlimport/qqmlimport.pro b/tests/auto/qml/qqmlimport/qqmlimport.pro
index c8b0f68d9f..ba80547f4e 100644
--- a/tests/auto/qml/qqmlimport/qqmlimport.pro
+++ b/tests/auto/qml/qqmlimport/qqmlimport.pro
@@ -6,3 +6,8 @@ osx:CONFIG -= app_bundle
SOURCES += tst_qqmlimport.cpp
include (../../shared/util.pri)
+
+TESTDATA = data/* \
+ MyPluginSupported/* \
+ MyPluginUnsupported/* \
+ FormFromQmlDir/*
diff --git a/tests/auto/qml/qqmlimport/tst_qqmlimport.cpp b/tests/auto/qml/qqmlimport/tst_qqmlimport.cpp
index a3cb68fdcb..ca1e52ad2c 100644
--- a/tests/auto/qml/qqmlimport/tst_qqmlimport.cpp
+++ b/tests/auto/qml/qqmlimport/tst_qqmlimport.cpp
@@ -45,6 +45,7 @@ private slots:
void completeQmldirPaths_data();
void completeQmldirPaths();
void interceptQmldir();
+ void singletonVersionResolution();
void cleanup();
};
@@ -77,7 +78,7 @@ void tst_QQmlImport::testDesignerSupported()
QVERIFY(window->errors().isEmpty());
QString warningString("%1:30:1: module does not support the designer \"MyPluginUnsupported\" \n import MyPluginUnsupported 1.0\r \n ^ ");
-#ifndef Q_OS_WIN
+#if !defined(Q_OS_WIN) && !defined(Q_OS_ANDROID)
warningString.remove('\r');
#endif
warningString = warningString.arg(testFileUrl("testfile_unsupported.qml").toString());
@@ -129,6 +130,9 @@ void tst_QQmlImport::uiFormatLoading()
void tst_QQmlImport::importPathOrder()
{
+#ifdef Q_OS_ANDROID
+ QSKIP("QLibraryInfo::location(QLibraryInfo::Qml2ImportsPath) returns bogus path on Android, but its nevertheless unusable.");
+#endif
QStringList expectedImportPaths;
QString appDirPath = QCoreApplication::applicationDirPath();
QString qml2Imports = QLibraryInfo::location(QLibraryInfo::Qml2ImportsPath);
@@ -212,6 +216,50 @@ void tst_QQmlImport::interceptQmldir()
QVERIFY(!obj.isNull());
}
+// QTBUG-77102
+void tst_QQmlImport::singletonVersionResolution()
+{
+ QQmlEngine engine;
+ engine.addImportPath(testFile("QTBUG-77102/imports"));
+ {
+ // Singleton with higher version is simply ignored when importing lower version of plugin
+ QQmlComponent component(&engine);
+ component.loadUrl(testFileUrl("QTBUG-77102/main.0.9.qml"));
+ QVERIFY(component.isReady());
+ QScopedPointer<QObject> obj(component.create());
+ QVERIFY(!obj.isNull());
+ }
+ {
+ // but the singleton is not accessible
+ QQmlComponent component(&engine);
+ QTest::ignoreMessage(QtMsgType::QtWarningMsg, QRegularExpression {".*ReferenceError: MySettings is not defined$"} );
+ component.loadUrl(testFileUrl("QTBUG-77102/main.0.9.fail.qml"));
+ QVERIFY(component.isReady());
+ QScopedPointer<QObject> obj(component.create());
+ QVERIFY(!obj.isNull());
+ }
+ {
+ // unless a version which is high enough is imported
+ QQmlComponent component(&engine);
+ component.loadUrl(testFileUrl("QTBUG-77102/main.1.0.qml"));
+ QVERIFY(component.isReady());
+ QScopedPointer<QObject> obj(component.create());
+ QVERIFY(!obj.isNull());
+ auto item = qobject_cast<QQuickItem*>(obj.get());
+ QCOMPARE(item->width(), 50);
+ }
+ {
+ // or when there is no number because we are importing from a path
+ QQmlComponent component(&engine);
+ component.loadUrl(testFileUrl("QTBUG-77102/main.nonumber.qml"));
+ QVERIFY(component.isReady());
+ QScopedPointer<QObject> obj(component.create());
+ QVERIFY(!obj.isNull());
+ auto item = qobject_cast<QQuickItem*>(obj.get());
+ QCOMPARE(item->width(), 50);
+ }
+}
+
QTEST_MAIN(tst_QQmlImport)
diff --git a/tests/auto/qml/qqmllocale/tst_qqmllocale.cpp b/tests/auto/qml/qqmllocale/tst_qqmllocale.cpp
index cc13fb4b5f..a90749208c 100644
--- a/tests/auto/qml/qqmllocale/tst_qqmllocale.cpp
+++ b/tests/auto/qml/qqmllocale/tst_qqmllocale.cpp
@@ -32,6 +32,8 @@
#include <QtQml/qqmlcomponent.h>
#include <QtQml/qqmlcontext.h>
#include <QtCore/QDateTime>
+#include <QtCore/qscopeguard.h>
+#include <QtCore/qscopedpointer.h>
#include <qcolor.h>
#include "../../shared/util.h"
@@ -1270,13 +1272,21 @@ void tst_qqmllocale::timeZoneUpdated()
// Set the timezone to Brisbane time, AEST-10:00
setTimeZone(QByteArray("Australia/Brisbane"));
+ QScopedPointer<QObject> obj;
+ auto cleanup = qScopeGuard([&original, &obj] {
+ // Restore to original time zone
+ setTimeZone(original);
+ QMetaObject::invokeMethod(obj.data(), "resetTimeZone");
+ });
+
DateFormatter formatter;
QQmlEngine e;
e.rootContext()->setContextObject(&formatter);
QQmlComponent c(&e, testFileUrl("timeZoneUpdated.qml"));
- QScopedPointer<QObject> obj(c.create());
+ QVERIFY2(!c.isError(), qPrintable(c.errorString()));
+ obj.reset(c.create());
QVERIFY(obj);
QVERIFY(obj->property("success").toBool());
@@ -1284,11 +1294,6 @@ void tst_qqmllocale::timeZoneUpdated()
setTimeZone(QByteArray("Asia/Kolkata"));
QMetaObject::invokeMethod(obj.data(), "check");
-
- // Reset to original time
- setTimeZone(original);
- QMetaObject::invokeMethod(obj.data(), "resetTimeZone");
-
QVERIFY(obj->property("success").toBool());
}
#endif
diff --git a/tests/auto/qml/qqmlnotifier/tst_qqmlnotifier.cpp b/tests/auto/qml/qqmlnotifier/tst_qqmlnotifier.cpp
index a5332c8860..de762d66c5 100644
--- a/tests/auto/qml/qqmlnotifier/tst_qqmlnotifier.cpp
+++ b/tests/auto/qml/qqmlnotifier/tst_qqmlnotifier.cpp
@@ -342,6 +342,9 @@ void tst_qqmlnotifier::lotsOfBindings()
void tst_qqmlnotifier::deleteFromHandler()
{
+#ifdef Q_OS_ANDROID
+ QSKIP("Android seems to have problems with QProcess");
+#endif
#if !QT_CONFIG(process)
QSKIP("Need QProcess support to test qFatal.");
#else
diff --git a/tests/auto/qml/qqmlpromise/data/promisechain.qml b/tests/auto/qml/qqmlpromise/data/promisechain.qml
new file mode 100644
index 0000000000..fa1809aef0
--- /dev/null
+++ b/tests/auto/qml/qqmlpromise/data/promisechain.qml
@@ -0,0 +1,24 @@
+import QtQml 2.0
+
+QtObject {
+ property int x: 0
+ id: root;
+ Component.onCompleted: {
+ new Promise((res) => {
+ res(1)
+ })
+ .then((data) => {
+ console.debug(data)
+ return new Promise((res) => {res(2)});
+ })
+ .then((data) => {
+ console.debug(data)
+ return new Promise((res) => {res(3)});
+ })
+ .then((data) => {
+ console.debug(data);
+ root.x = 42;
+ });
+ }
+
+}
diff --git a/tests/auto/qml/qqmlpromise/tst_qqmlpromise.cpp b/tests/auto/qml/qqmlpromise/tst_qqmlpromise.cpp
index 0f4bb5cdcc..41850d0263 100644
--- a/tests/auto/qml/qqmlpromise/tst_qqmlpromise.cpp
+++ b/tests/auto/qml/qqmlpromise/tst_qqmlpromise.cpp
@@ -82,6 +82,7 @@ private slots:
void then_fulfilled_non_callable();
void then_reject_non_callable();
void then_resolve_multiple_then();
+ void promiseChain();
private:
void execute_test(QString testName);
@@ -270,6 +271,20 @@ void tst_qqmlpromise::execute_test(QString testName)
QTRY_COMPARE(object->property("wasTestSuccessful").toBool(), true);
}
+void tst_qqmlpromise::promiseChain()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine, testFileUrl("promisechain.qml"));
+ QVERIFY(component.isReady());
+ QTest::ignoreMessage(QtDebugMsg, "1");
+ QTest::ignoreMessage(QtDebugMsg, "2");
+ QTest::ignoreMessage(QtDebugMsg, "3");
+ QScopedPointer<QObject> root(component.create());
+ QVERIFY(root);
+ QTRY_VERIFY(root->property("x") == 42);
+
+}
+
QTEST_MAIN(tst_qqmlpromise)
diff --git a/tests/auto/qml/qqmlproperty/data/nullPropertyBinding.qml b/tests/auto/qml/qqmlproperty/data/nullPropertyBinding.qml
new file mode 100644
index 0000000000..4fffc7aead
--- /dev/null
+++ b/tests/auto/qml/qqmlproperty/data/nullPropertyBinding.qml
@@ -0,0 +1,22 @@
+import QtQuick 2.12
+
+Item {
+ id: root
+
+ width: 640
+ height: 480
+
+ property bool toggle: false
+ property Item bound
+ property string message: "defined"
+
+ readonly property Item item: root.toggle ? root : null
+
+ Binding { target: root; property: "bound"; value: item}
+
+ function tog() {
+ console.info(root.bound ? root.bound.message: "undefined")
+ root.toggle = !root.toggle
+ return 42;
+ }
+}
diff --git a/tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp b/tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp
index 04c61ec11b..67da768f73 100644
--- a/tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp
+++ b/tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp
@@ -144,6 +144,7 @@ private slots:
void deeplyNestedObject();
void readOnlyDynamicProperties();
void aliasToIdWithMatchingQmlFileNameOnCaseInsensitiveFileSystem();
+ void nullPropertyBinding();
void floatToStringPrecision_data();
void floatToStringPrecision();
@@ -2059,6 +2060,22 @@ void tst_qqmlproperty::aliasToIdWithMatchingQmlFileNameOnCaseInsensitiveFileSyst
QVERIFY(property.isValid());
}
+// QTBUG-77027
+void tst_qqmlproperty::nullPropertyBinding()
+{
+ const QUrl url = testFileUrl("nullPropertyBinding.qml");
+ QQmlEngine engine;
+ QQmlComponent component(&engine, url);
+ QScopedPointer<QObject> root(component.create());
+ QVERIFY(root);
+ QTest::ignoreMessage(QtMsgType::QtInfoMsg, "undefined");
+ QMetaObject::invokeMethod(root.get(), "tog");
+ QTest::ignoreMessage(QtMsgType::QtInfoMsg, "defined");
+ QMetaObject::invokeMethod(root.get(), "tog");
+ QTest::ignoreMessage(QtMsgType::QtInfoMsg, "undefined");
+ QMetaObject::invokeMethod(root.get(), "tog");
+}
+
void tst_qqmlproperty::floatToStringPrecision_data()
{
QTest::addColumn<QString>("propertyName");
diff --git a/tests/auto/quick/pointerhandlers/multipointtoucharea_interop/data/dragParentOfMPTA.qml b/tests/auto/quick/pointerhandlers/multipointtoucharea_interop/data/dragParentOfMPTA.qml
new file mode 100644
index 0000000000..dc7e5f6411
--- /dev/null
+++ b/tests/auto/quick/pointerhandlers/multipointtoucharea_interop/data/dragParentOfMPTA.qml
@@ -0,0 +1,50 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 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$
+**
+****************************************************************************/
+
+import QtQuick 2.12
+
+Item {
+ width: 640
+ height: 480
+ property alias touchpointPressed: tp1.pressed
+
+ Rectangle {
+ color: tp1.pressed ? "lightsteelblue" : drag.active ? "tomato" : "wheat"
+ width: 180
+ height: 180
+
+ DragHandler { id: drag }
+
+ MultiPointTouchArea {
+ anchors.fill: parent
+ touchPoints: [
+ TouchPoint { id: tp1 }
+ ]
+ }
+ }
+}
diff --git a/tests/auto/quick/pointerhandlers/multipointtoucharea_interop/tst_multipointtoucharea_interop.cpp b/tests/auto/quick/pointerhandlers/multipointtoucharea_interop/tst_multipointtoucharea_interop.cpp
index 58bc3d40b5..35fed99e8b 100644
--- a/tests/auto/quick/pointerhandlers/multipointtoucharea_interop/tst_multipointtoucharea_interop.cpp
+++ b/tests/auto/quick/pointerhandlers/multipointtoucharea_interop/tst_multipointtoucharea_interop.cpp
@@ -56,6 +56,7 @@ private slots:
void touchDrag();
void touchesThenPinch();
void unloadHandlerWithPassiveGrab();
+ void dragHandlerInParentStealingGrabFromItem();
private:
void createView(QScopedPointer<QQuickView> &window, const char *fileName);
@@ -300,6 +301,48 @@ void tst_MptaInterop::unloadHandlerWithPassiveGrab()
QTest::mouseRelease(window, Qt::LeftButton, 0, point); // QTBUG-73819: don't crash
}
+void tst_MptaInterop::dragHandlerInParentStealingGrabFromItem() // QTBUG-75025
+{
+ const int dragThreshold = QGuiApplication::styleHints()->startDragDistance();
+ QScopedPointer<QQuickView> windowPtr;
+ createView(windowPtr, "dragParentOfMPTA.qml");
+ QQuickView * window = windowPtr.data();
+ auto pointerEvent = QQuickWindowPrivate::get(window)->pointerEventInstance(QQuickPointerDevice::genericMouseDevice());
+
+ QPointer<QQuickPointerHandler> handler = window->rootObject()->findChild<QQuickPointerHandler*>();
+ QVERIFY(handler);
+ QQuickMultiPointTouchArea *mpta = window->rootObject()->findChild<QQuickMultiPointTouchArea*>();
+ QVERIFY(mpta);
+
+ // In QTBUG-75025 there is a QQ Controls Button; the MPTA here stands in for that,
+ // simply as an Item that grabs the mouse. The bug has nothing to do with MPTA specifically.
+
+ QPoint point(20, 20);
+ QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, point);
+ QCOMPARE(window->mouseGrabberItem(), mpta);
+ QCOMPARE(window->rootObject()->property("touchpointPressed").toBool(), true);
+
+ // Start dragging
+ // DragHandler keeps monitoring, due to its passive grab,
+ // and eventually steals the exclusive grab from MPTA
+ int dragStoleGrab = 0;
+ for (int i = 0; i < 4; ++i) {
+ point += QPoint(dragThreshold / 2, 0);
+ QTest::mouseMove(window, point);
+ if (!dragStoleGrab && pointerEvent->point(0)->exclusiveGrabber() == handler)
+ dragStoleGrab = i;
+ }
+ if (dragStoleGrab)
+ qCDebug(lcPointerTests, "DragHandler stole the grab after %d events", dragStoleGrab);
+ QVERIFY(dragStoleGrab > 1);
+ QCOMPARE(handler->active(), true);
+ QCOMPARE(window->rootObject()->property("touchpointPressed").toBool(), false);
+
+ QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, point);
+ QCOMPARE(handler->active(), false);
+ QCOMPARE(window->rootObject()->property("touchpointPressed").toBool(), false);
+}
+
QTEST_MAIN(tst_MptaInterop)
#include "tst_multipointtoucharea_interop.moc"
diff --git a/tests/auto/quick/pointerhandlers/qquickdraghandler/tst_qquickdraghandler.cpp b/tests/auto/quick/pointerhandlers/qquickdraghandler/tst_qquickdraghandler.cpp
index 7636bb38f1..66314f88a2 100644
--- a/tests/auto/quick/pointerhandlers/qquickdraghandler/tst_qquickdraghandler.cpp
+++ b/tests/auto/quick/pointerhandlers/qquickdraghandler/tst_qquickdraghandler.cpp
@@ -54,6 +54,7 @@ private slots:
void defaultPropertyValues();
void touchDrag();
+ void mouseDrag_data();
void mouseDrag();
void dragFromMargin();
void snapMode_data();
@@ -195,8 +196,22 @@ void tst_DragHandler::touchDrag()
QCOMPARE(centroidChangedSpy.count(), 5);
}
+void tst_DragHandler::mouseDrag_data()
+{
+ QTest::addColumn<Qt::MouseButtons>("acceptedButtons");
+ QTest::addColumn<Qt::MouseButtons>("dragButton");
+ QTest::newRow("left: drag") << Qt::MouseButtons(Qt::LeftButton) << Qt::MouseButtons(Qt::LeftButton);
+ QTest::newRow("right: don't drag") << Qt::MouseButtons(Qt::LeftButton) << Qt::MouseButtons(Qt::RightButton);
+ QTest::newRow("left: don't drag") << Qt::MouseButtons(Qt::RightButton | Qt::MiddleButton) << Qt::MouseButtons(Qt::LeftButton);
+ QTest::newRow("right or middle: drag") << Qt::MouseButtons(Qt::RightButton | Qt::MiddleButton) << Qt::MouseButtons(Qt::MiddleButton);
+}
+
void tst_DragHandler::mouseDrag()
{
+ QFETCH(Qt::MouseButtons, acceptedButtons);
+ QFETCH(Qt::MouseButtons, dragButton);
+ bool shouldDrag = bool(acceptedButtons & dragButton);
+
const int dragThreshold = QGuiApplication::styleHints()->startDragDistance();
QScopedPointer<QQuickView> windowPtr;
createView(windowPtr, "draggables.qml");
@@ -206,6 +221,7 @@ void tst_DragHandler::mouseDrag()
QVERIFY(ball);
QQuickDragHandler *dragHandler = ball->findChild<QQuickDragHandler*>();
QVERIFY(dragHandler);
+ dragHandler->setAcceptedButtons(acceptedButtons); // QTBUG-76875
QSignalSpy translationChangedSpy(dragHandler, SIGNAL(translationChanged()));
QSignalSpy centroidChangedSpy(dragHandler, SIGNAL(centroidChanged()));
@@ -213,45 +229,57 @@ void tst_DragHandler::mouseDrag()
QPointF ballCenter = ball->clipRect().center();
QPointF scenePressPos = ball->mapToScene(ballCenter);
QPoint p1 = scenePressPos.toPoint();
- QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, p1);
+ QTest::mousePress(window, static_cast<Qt::MouseButton>(int(dragButton)), Qt::NoModifier, p1);
QVERIFY(!dragHandler->active());
- QCOMPARE(dragHandler->centroid().position(), ballCenter);
- QCOMPARE(dragHandler->centroid().pressPosition(), ballCenter);
- QCOMPARE(dragHandler->centroid().scenePosition(), scenePressPos);
- QCOMPARE(dragHandler->centroid().scenePressPosition(), scenePressPos);
- QCOMPARE(dragHandler->centroid().velocity(), QVector2D());
- QCOMPARE(centroidChangedSpy.count(), 1);
+ if (shouldDrag) {
+ QCOMPARE(dragHandler->centroid().position(), ballCenter);
+ QCOMPARE(dragHandler->centroid().pressPosition(), ballCenter);
+ QCOMPARE(dragHandler->centroid().scenePosition(), scenePressPos);
+ QCOMPARE(dragHandler->centroid().scenePressPosition(), scenePressPos);
+ QCOMPARE(dragHandler->centroid().velocity(), QVector2D());
+ QCOMPARE(centroidChangedSpy.count(), 1);
+ }
p1 += QPoint(dragThreshold, 0);
QTest::mouseMove(window, p1);
- QTRY_VERIFY(dragHandler->centroid().velocity().x() > 0);
- QCOMPARE(centroidChangedSpy.count(), 2);
- QVERIFY(!dragHandler->active());
+ if (shouldDrag) {
+ QTRY_VERIFY(dragHandler->centroid().velocity().x() > 0);
+ QCOMPARE(centroidChangedSpy.count(), 2);
+ QVERIFY(!dragHandler->active());
+ }
p1 += QPoint(1, 0);
QTest::mouseMove(window, p1);
- QTRY_VERIFY(dragHandler->active());
+ if (shouldDrag)
+ QTRY_VERIFY(dragHandler->active());
+ else
+ QVERIFY(!dragHandler->active());
QCOMPARE(translationChangedSpy.count(), 0);
- QCOMPARE(centroidChangedSpy.count(), 3);
+ if (shouldDrag)
+ QCOMPARE(centroidChangedSpy.count(), 3);
QCOMPARE(dragHandler->translation().x(), 0.0);
QPointF sceneGrabPos = p1;
- QCOMPARE(dragHandler->centroid().sceneGrabPosition(), sceneGrabPos);
+ if (shouldDrag)
+ QCOMPARE(dragHandler->centroid().sceneGrabPosition(), sceneGrabPos);
p1 += QPoint(19, 0);
QTest::mouseMove(window, p1);
- QTRY_VERIFY(dragHandler->active());
- QCOMPARE(dragHandler->centroid().position(), ballCenter);
- QCOMPARE(dragHandler->centroid().pressPosition(), ballCenter);
- QCOMPARE(dragHandler->centroid().scenePosition(), ball->mapToScene(ballCenter));
- QCOMPARE(dragHandler->centroid().scenePressPosition(), scenePressPos);
- QCOMPARE(dragHandler->centroid().sceneGrabPosition(), sceneGrabPos);
- QCOMPARE(dragHandler->translation().x(), dragThreshold + 20.0);
- QCOMPARE(dragHandler->translation().y(), 0.0);
- QVERIFY(dragHandler->centroid().velocity().x() > 0);
- QCOMPARE(centroidChangedSpy.count(), 4);
- QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, p1);
+ QVERIFY(shouldDrag ? dragHandler->active() : !dragHandler->active());
+ if (shouldDrag) {
+ QCOMPARE(dragHandler->centroid().position(), ballCenter);
+ QCOMPARE(dragHandler->centroid().pressPosition(), ballCenter);
+ QCOMPARE(dragHandler->centroid().scenePosition(), ball->mapToScene(ballCenter));
+ QCOMPARE(dragHandler->centroid().scenePressPosition(), scenePressPos);
+ QCOMPARE(dragHandler->centroid().sceneGrabPosition(), sceneGrabPos);
+ QCOMPARE(dragHandler->translation().x(), dragThreshold + 20.0);
+ QCOMPARE(dragHandler->translation().y(), 0.0);
+ QVERIFY(dragHandler->centroid().velocity().x() > 0);
+ QCOMPARE(centroidChangedSpy.count(), 4);
+ }
+ QTest::mouseRelease(window, static_cast<Qt::MouseButton>(int(dragButton)), Qt::NoModifier, p1);
QTRY_VERIFY(!dragHandler->active());
QCOMPARE(dragHandler->centroid().pressedButtons(), Qt::NoButton);
- QCOMPARE(ball->mapToScene(ballCenter).toPoint(), p1);
- QCOMPARE(translationChangedSpy.count(), 1);
- QCOMPARE(centroidChangedSpy.count(), 5);
+ if (shouldDrag)
+ QCOMPARE(ball->mapToScene(ballCenter).toPoint(), p1);
+ QCOMPARE(translationChangedSpy.count(), shouldDrag ? 1 : 0);
+ QCOMPARE(centroidChangedSpy.count(), shouldDrag ? 5 : 0);
}
void tst_DragHandler::dragFromMargin() // QTBUG-74966
diff --git a/tests/auto/quick/pointerhandlers/qquicktaphandler/data/Button.qml b/tests/auto/quick/pointerhandlers/qquicktaphandler/data/Button.qml
index 221e7df139..042b730799 100644
--- a/tests/auto/quick/pointerhandlers/qquicktaphandler/data/Button.qml
+++ b/tests/auto/quick/pointerhandlers/qquicktaphandler/data/Button.qml
@@ -34,6 +34,7 @@ Rectangle {
property alias pressed: tap.pressed
property bool checked: false
property alias gesturePolicy: tap.gesturePolicy
+ property point tappedPosition: Qt.point(0, 0)
signal tapped
signal canceled
@@ -51,6 +52,7 @@ Rectangle {
longPressThreshold: 100 // CI can be insanely slow, so don't demand a timely release to generate onTapped
onTapped: {
tapFlash.start()
+ root.tappedPosition = point.scenePosition
root.tapped()
}
onCanceled: root.canceled()
diff --git a/tests/auto/quick/pointerhandlers/qquicktaphandler/tst_qquicktaphandler.cpp b/tests/auto/quick/pointerhandlers/qquicktaphandler/tst_qquicktaphandler.cpp
index 33cea69147..e77ea97518 100644
--- a/tests/auto/quick/pointerhandlers/qquicktaphandler/tst_qquicktaphandler.cpp
+++ b/tests/auto/quick/pointerhandlers/qquicktaphandler/tst_qquicktaphandler.cpp
@@ -107,6 +107,8 @@ void tst_TapHandler::touchGesturePolicyDragThreshold()
QQuickItem *buttonDragThreshold = window->rootObject()->findChild<QQuickItem*>("DragThreshold");
QVERIFY(buttonDragThreshold);
+ QQuickTapHandler *tapHandler = buttonDragThreshold->findChild<QQuickTapHandler*>();
+ QVERIFY(tapHandler);
QSignalSpy dragThresholdTappedSpy(buttonDragThreshold, SIGNAL(tapped()));
// DragThreshold button stays pressed while touchpoint stays within dragThreshold, emits tapped on release
@@ -122,6 +124,8 @@ void tst_TapHandler::touchGesturePolicyDragThreshold()
QQuickTouchUtils::flush(window);
QTRY_VERIFY(!buttonDragThreshold->property("pressed").toBool());
QCOMPARE(dragThresholdTappedSpy.count(), 1);
+ QCOMPARE(buttonDragThreshold->property("tappedPosition").toPoint(), p1);
+ QCOMPARE(tapHandler->point().position(), QPointF());
// DragThreshold button is no longer pressed if touchpoint goes beyond dragThreshold
dragThresholdTappedSpy.clear();
@@ -152,6 +156,8 @@ void tst_TapHandler::mouseGesturePolicyDragThreshold()
QQuickItem *buttonDragThreshold = window->rootObject()->findChild<QQuickItem*>("DragThreshold");
QVERIFY(buttonDragThreshold);
+ QQuickTapHandler *tapHandler = buttonDragThreshold->findChild<QQuickTapHandler*>();
+ QVERIFY(tapHandler);
QSignalSpy dragThresholdTappedSpy(buttonDragThreshold, SIGNAL(tapped()));
// DragThreshold button stays pressed while mouse stays within dragThreshold, emits tapped on release
@@ -164,6 +170,8 @@ void tst_TapHandler::mouseGesturePolicyDragThreshold()
QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, p1);
QTRY_VERIFY(!buttonDragThreshold->property("pressed").toBool());
QTRY_COMPARE(dragThresholdTappedSpy.count(), 1);
+ QCOMPARE(buttonDragThreshold->property("tappedPosition").toPoint(), p1);
+ QCOMPARE(tapHandler->point().position(), QPointF());
// DragThreshold button is no longer pressed if mouse goes beyond dragThreshold
dragThresholdTappedSpy.clear();
diff --git a/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp b/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp
index 65a08ce87f..2314b82e8c 100644
--- a/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp
+++ b/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp
@@ -1652,6 +1652,7 @@ void tst_qquickflickable::flickTwiceUsingTouches()
QQuickViewTestUtil::moveMouseAway(window.data());
window->show();
QVERIFY(window->rootObject() != nullptr);
+ QVERIFY(QTest::qWaitForWindowActive(window.data()));
QQuickFlickable *flickable = qobject_cast<QQuickFlickable*>(window->rootObject());
QVERIFY(flickable != nullptr);
@@ -1994,6 +1995,7 @@ void tst_qquickflickable::nestedMouseAreaUsingTouch()
QQuickViewTestUtil::moveMouseAway(window.data());
window->show();
QVERIFY(window->rootObject() != nullptr);
+ QVERIFY(QTest::qWaitForWindowActive(window.data()));
QQuickFlickable *flickable = qobject_cast<QQuickFlickable*>(window->rootObject());
QVERIFY(flickable != nullptr);
@@ -2489,6 +2491,7 @@ void tst_qquickflickable::synchronousDrag()
QQuickViewTestUtil::moveMouseAway(window);
window->show();
QVERIFY(window->rootObject() != nullptr);
+ QVERIFY(QTest::qWaitForWindowActive(window));
QQuickFlickable *flickable = qobject_cast<QQuickFlickable*>(window->rootObject());
QVERIFY(flickable != nullptr);
diff --git a/tests/auto/quick/qquicklistview/data/resizeAfterComponentComplete.qml b/tests/auto/quick/qquicklistview/data/resizeAfterComponentComplete.qml
new file mode 100644
index 0000000000..851d8f9a0c
--- /dev/null
+++ b/tests/auto/quick/qquicklistview/data/resizeAfterComponentComplete.qml
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 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:BSD$
+** 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.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.12
+
+ListView {
+ id: listView
+ property var lastItem
+ anchors.fill: parent
+ model: 10
+ delegate: Rectangle {
+ width: parent.width
+ height: 40
+ border.color: "lightsteelblue"
+ Text {
+ text: "Item" + (index + 1)
+ }
+ Component.onCompleted: {
+ if (index == 9)
+ listView.lastItem = this
+ }
+ }
+
+ populate: Transition {
+ NumberAnimation {
+ properties: "x,y"
+ duration: 1000
+ }
+ }
+}
diff --git a/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp b/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp
index f14a6e75f6..bab2ec34f8 100644
--- a/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp
+++ b/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp
@@ -278,6 +278,7 @@ private slots:
void addOnCompleted();
void setPositionOnLayout();
void touchCancel();
+ void resizeAfterComponentComplete();
private:
template <class T> void items(const QUrl &source);
@@ -9020,6 +9021,21 @@ void tst_QQuickListView::touchCancel() // QTBUG-74679
QTRY_COMPARE(listview->contentY(), 500.0);
}
+void tst_QQuickListView::resizeAfterComponentComplete() // QTBUG-76487
+{
+ QScopedPointer<QQuickView> window(createView());
+ window->setSource(testFileUrl("resizeAfterComponentComplete.qml"));
+ window->resize(640, 480);
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window.data()));
+
+ QObject *listView = window->rootObject();
+ QVERIFY(listView);
+
+ QObject *lastItem = qvariant_cast<QObject *>(listView->property("lastItem"));
+ QTRY_COMPARE(lastItem->property("y").toInt(), 9 * lastItem->property("height").toInt());
+}
+
QTEST_MAIN(tst_QQuickListView)
#include "tst_qquicklistview.moc"
diff --git a/tests/auto/quick/qquickshape/data/pathitem8.png b/tests/auto/quick/qquickshape/data/pathitem8.png
new file mode 100644
index 0000000000..ee585958ec
--- /dev/null
+++ b/tests/auto/quick/qquickshape/data/pathitem8.png
Binary files differ
diff --git a/tests/auto/quick/qquickshape/data/pathitem8.qml b/tests/auto/quick/qquickshape/data/pathitem8.qml
new file mode 100644
index 0000000000..9789ff90e0
--- /dev/null
+++ b/tests/auto/quick/qquickshape/data/pathitem8.qml
@@ -0,0 +1,88 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 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$
+**
+****************************************************************************/
+
+import QtQuick 2.14
+import QtQuick.Shapes 1.14
+
+Item {
+ id: item
+ width: 200
+ height: 150
+
+ Shape {
+ vendorExtensionsEnabled: false
+ objectName: "shape"
+ id: shape
+ anchors.fill: parent
+
+ ShapePath {
+ strokeWidth: 4
+ strokeColor: "red"
+ scale: Qt.size(shape.width - 1, shape.height - 1)
+ fillGradient: LinearGradient {
+ x1: 20; y1: 20
+ x2: 180; y2: 130
+ GradientStop { position: 0; color: "blue" }
+ GradientStop { position: 0.2; color: "green" }
+ GradientStop { position: 0.4; color: "red" }
+ GradientStop { position: 0.6; color: "yellow" }
+ GradientStop { position: 1; color: "cyan" }
+ }
+ strokeStyle: ShapePath.DashLine
+ dashPattern: [ 1, 4 ]
+ PathMultiline {
+ paths: [[Qt.point(20.0 / (item.width - 1.0), 20.0 / (item.height - 1.0)),
+ Qt.point(180.0 / (item.width - 1.0), 130.0 / (item.height - 1.0)),
+ Qt.point(20.0 / (item.width - 1.0), 130.0 / (item.height - 1.0)),
+ Qt.point(20.0 / (item.width - 1.0), 20.0 / (item.height - 1.0)) ],
+ [Qt.point( 0.45 , 0.67 ),
+ Qt.point( 0.414906666468 , 0.573581858547 ),
+ Qt.point( 0.32604722665 , 0.522278837048 ),
+ Qt.point( 0.225 , 0.540096189432 ),
+ Qt.point( 0.159046106882 , 0.618696978501 ),
+ Qt.point( 0.159046106882 , 0.721303021499 ),
+ Qt.point( 0.225 , 0.799903810568 ),
+ Qt.point( 0.32604722665 , 0.817721162952 ),
+ Qt.point( 0.414906666468 , 0.766418141453 ),
+ Qt.point( 0.45 , 0.67 ),
+ ],
+ [Qt.point( 0.69 , 0.75 ),
+ Qt.point( 0.668943999881 , 0.692149115128 ),
+ Qt.point( 0.61562833599 , 0.661367302229 ),
+ Qt.point( 0.555 , 0.672057713659 ),
+ Qt.point( 0.515427664129 , 0.719218187101 ),
+ Qt.point( 0.515427664129 , 0.780781812899 ),
+ Qt.point( 0.555 , 0.827942286341 ),
+ Qt.point( 0.61562833599 , 0.838632697771 ),
+ Qt.point( 0.668943999881 , 0.807850884872 ),
+ Qt.point( 0.69 , 0.75 ),
+ ]]
+ }
+ }
+ }
+}
diff --git a/tests/auto/quick/qquickshape/tst_qquickshape.cpp b/tests/auto/quick/qquickshape/tst_qquickshape.cpp
index 174ada65a5..b3b8d2d148 100644
--- a/tests/auto/quick/qquickshape/tst_qquickshape.cpp
+++ b/tests/auto/quick/qquickshape/tst_qquickshape.cpp
@@ -59,6 +59,7 @@ private slots:
void radialGrad();
void conicalGrad();
void renderPolyline();
+ void renderMultiline();
};
tst_QQuickShape::tst_QQuickShape()
@@ -343,6 +344,35 @@ void tst_QQuickShape::renderPolyline()
QVERIFY2(res, qPrintable(errorMessage));
}
+void tst_QQuickShape::renderMultiline()
+{
+ QScopedPointer<QQuickView> window(createView());
+
+ window->setSource(testFileUrl("pathitem8.qml"));
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window.data()));
+
+ if ((QGuiApplication::platformName() == QLatin1String("offscreen"))
+ || (QGuiApplication::platformName() == QLatin1String("minimal")))
+ QEXPECT_FAIL("", "Failure due to grabWindow not functional on offscreen/minimimal platforms", Abort);
+
+ QImage img = window->grabWindow();
+ QVERIFY(!img.isNull());
+
+ QImage refImg(testFileUrl("pathitem8.png").toLocalFile());
+ QVERIFY(!refImg.isNull());
+
+ QString errorMessage;
+ const QImage actualImg = img.convertToFormat(refImg.format());
+ const bool res = QQuickVisualTestUtil::compareImages(actualImg, refImg, &errorMessage);
+ if (!res) { // For visual inspection purposes.
+ QTest::qWait(5000);
+ const QString &tempLocation = QStandardPaths::writableLocation(QStandardPaths::TempLocation);
+ actualImg.save(tempLocation + QLatin1String("/pathitem8.png"));
+ }
+ QVERIFY2(res, qPrintable(errorMessage));
+}
+
QTEST_MAIN(tst_QQuickShape)
#include "tst_qquickshape.moc"
diff --git a/tests/auto/quick/qquicktext/BLACKLIST b/tests/auto/quick/qquicktext/BLACKLIST
index 6c3c3af154..594f9af3b3 100644
--- a/tests/auto/quick/qquicktext/BLACKLIST
+++ b/tests/auto/quick/qquicktext/BLACKLIST
@@ -4,3 +4,5 @@ qemu
osx-10.12
[fontSizeMode]
opensuse-42.1
+[contentSize]
+windows gcc
diff --git a/tests/manual/nodetypes_ng/MultiClipRects.qml b/tests/manual/nodetypes_ng/MultiClipRects.qml
index 793ebeae93..2d3804af21 100644
--- a/tests/manual/nodetypes_ng/MultiClipRects.qml
+++ b/tests/manual/nodetypes_ng/MultiClipRects.qml
@@ -61,8 +61,8 @@ Item {
GradientStop { position: 1; color: "black" }
}
- // Clip using scissor, 2 levels.
- // This means that the lightGreen-yellow-blue batch's clip list will have two clips.
+ // Clip using scissor, up to 2 levels. This means that the
+ // lightGreen-yellow-blue batch's clip list will have two clips.
Row {
spacing: 10
Repeater {
@@ -103,9 +103,9 @@ Item {
}
}
- // Clip using stencil, 2 levels.
- // This means that the lightGreen-yellow batch's clip list will have two clips
- // and so two stencil draw calls before drawing the actual content.
+ // Clip using stencil, up to 3 levels. This means that the
+ // lightGreen-yellow-blue batch's clip list will have three clips and
+ // so two stencil draw calls before drawing the actual content.
Row {
spacing: 10
Repeater {
@@ -133,6 +133,16 @@ Item {
x: 75
y: 75
NumberAnimation on rotation { from: 360; to: 0; duration: 5000; loops: Animation.Infinite; }
+ clip: true
+
+ Rectangle {
+ color: "blue"
+ width: 50
+ height: 50
+ x: 0
+ y: 0
+ NumberAnimation on rotation { from: 360; to: 0; duration: 5000; loops: Animation.Infinite; }
+ }
}
}
}
diff --git a/tests/manual/scenegraph_lancelot/data/shape/shape_multiline.qml b/tests/manual/scenegraph_lancelot/data/shape/shape_multiline.qml
new file mode 100644
index 0000000000..8524915bc4
--- /dev/null
+++ b/tests/manual/scenegraph_lancelot/data/shape/shape_multiline.qml
@@ -0,0 +1,74 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 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$
+**
+****************************************************************************/
+
+import QtQuick 2.14
+import QtQuick.Shapes 1.14
+
+Item {
+ id: root
+ width: 320
+ height: 320
+
+ Shape {
+ vendorExtensionsEnabled: false
+ anchors.fill: parent
+
+ ShapePath {
+ strokeWidth: 1
+ strokeColor: "red"
+ fillColor: Qt.rgba(1,0,0,0.3)
+ scale: Qt.size(root.width - 1, root.height - 1)
+ PathMultiline {
+ paths: [
+ [Qt.point(0.5, 0.06698),
+ Qt.point(1, 0.93301),
+ Qt.point(0, 0.93301),
+ Qt.point(0.5, 0.06698)],
+
+ [Qt.point(0.5, 0.12472),
+ Qt.point(0.95, 0.90414),
+ Qt.point(0.05, 0.90414),
+ Qt.point(0.5, 0.12472)],
+
+ [Qt.point(0.47131, 0.32986),
+ Qt.point(0.36229, 0.64789),
+ Qt.point(0.51492, 0.58590),
+ Qt.point(0.47563, 0.76014),
+ Qt.point(0.44950, 0.73590),
+ Qt.point(0.46292, 0.83392),
+ Qt.point(0.52162, 0.75190),
+ Qt.point(0.48531, 0.76230),
+ Qt.point(0.57529, 0.53189),
+ Qt.point(0.41261, 0.59189),
+ Qt.point(0.53001, 0.32786),
+ Qt.point(0.47131, 0.32986)]
+ ]
+ }
+ }
+ }
+}