diff options
Diffstat (limited to 'tests/auto')
65 files changed, 1446 insertions, 52 deletions
diff --git a/tests/auto/particles/qquickimageparticle/tst_qquickimageparticle.cpp b/tests/auto/particles/qquickimageparticle/tst_qquickimageparticle.cpp index 6f48cb85bd..06c0e898d3 100644 --- a/tests/auto/particles/qquickimageparticle/tst_qquickimageparticle.cpp +++ b/tests/auto/particles/qquickimageparticle/tst_qquickimageparticle.cpp @@ -243,46 +243,50 @@ void tst_qquickimageparticle::test_deformed() void tst_qquickimageparticle::test_tabled() { - QQuickView* view = createView(testFileUrl("tabled.qml"), 600); - QQuickParticleSystem* system = view->rootObject()->findChild<QQuickParticleSystem*>("system"); - ensureAnimTime(600, system->m_animation); + #if defined(Q_OS_LINUX) + QSKIP("Crashing on Ubuntu 22.04: QTBUG-107707"); + #else + QQuickView* view = createView(testFileUrl("tabled.qml"), 600); + QQuickParticleSystem* system = view->rootObject()->findChild<QQuickParticleSystem*>("system"); + ensureAnimTime(600, system->m_animation); - QVERIFY(extremelyFuzzyCompare(system->groupData[0]->size(), 500, 10)); - for (QQuickParticleData *d : qAsConst(system->groupData[0]->data)) { - if (d->t == -1) - continue; //Particle data unused + QVERIFY(extremelyFuzzyCompare(system->groupData[0]->size(), 500, 10)); + for (QQuickParticleData *d : qAsConst(system->groupData[0]->data)) { + if (d->t == -1) + continue; //Particle data unused - QCOMPARE(d->x, 0.f); - QCOMPARE(d->y, 0.f); - QCOMPARE(d->vx, 0.f); - QCOMPARE(d->vy, 0.f); - QCOMPARE(d->ax, 0.f); - QCOMPARE(d->ay, 0.f); - QCOMPARE(d->lifeSpan, 0.5f); - QCOMPARE(d->size, 32.f); - QCOMPARE(d->endSize, 32.f); - QVERIFY(myFuzzyLEQ(d->t, ((qreal)system->timeInt/1000.0))); - QCOMPARE(d->color.r, (uchar)255); - QCOMPARE(d->color.g, (uchar)255); - QCOMPARE(d->color.b, (uchar)255); - QCOMPARE(d->color.a, (uchar)255); - QCOMPARE(d->xx, 1.0f); - QCOMPARE(d->xy, 0.0f); - QCOMPARE(d->yy, 1.0f); - QCOMPARE(d->yx, 0.0f); - QCOMPARE(d->rotation, 0.0f); - QCOMPARE(d->rotationVelocity, 0.0f); - QCOMPARE(d->autoRotate, (uchar)0); - QCOMPARE(d->animX, 0.0f); - QCOMPARE(d->animY, 0.0f); - QCOMPARE(d->animWidth, 1.0f); - QCOMPARE(d->animHeight, 1.0f); - QCOMPARE(d->frameDuration, 1.0f); - QCOMPARE(d->frameCount, 1.0f); - QCOMPARE(d->animT, -1.0f); - //TODO: This performance level doesn't alter particleData, but goes straight to shaders. Find something to test - } - delete view; + QCOMPARE(d->x, 0.f); + QCOMPARE(d->y, 0.f); + QCOMPARE(d->vx, 0.f); + QCOMPARE(d->vy, 0.f); + QCOMPARE(d->ax, 0.f); + QCOMPARE(d->ay, 0.f); + QCOMPARE(d->lifeSpan, 0.5f); + QCOMPARE(d->size, 32.f); + QCOMPARE(d->endSize, 32.f); + QVERIFY(myFuzzyLEQ(d->t, ((qreal)system->timeInt/1000.0))); + QCOMPARE(d->color.r, (uchar)255); + QCOMPARE(d->color.g, (uchar)255); + QCOMPARE(d->color.b, (uchar)255); + QCOMPARE(d->color.a, (uchar)255); + QCOMPARE(d->xx, 1.0f); + QCOMPARE(d->xy, 0.0f); + QCOMPARE(d->yy, 1.0f); + QCOMPARE(d->yx, 0.0f); + QCOMPARE(d->rotation, 0.0f); + QCOMPARE(d->rotationVelocity, 0.0f); + QCOMPARE(d->autoRotate, (uchar)0); + QCOMPARE(d->animX, 0.0f); + QCOMPARE(d->animY, 0.0f); + QCOMPARE(d->animWidth, 1.0f); + QCOMPARE(d->animHeight, 1.0f); + QCOMPARE(d->frameDuration, 1.0f); + QCOMPARE(d->frameCount, 1.0f); + QCOMPARE(d->animT, -1.0f); + //TODO: This performance level doesn't alter particleData, but goes straight to shaders. Find something to test + } + delete view; + #endif } diff --git a/tests/auto/qml/debugger/qv4debugger/CMakeLists.txt b/tests/auto/qml/debugger/qv4debugger/CMakeLists.txt index e8fe26cb5a..92565f55c1 100644 --- a/tests/auto/qml/debugger/qv4debugger/CMakeLists.txt +++ b/tests/auto/qml/debugger/qv4debugger/CMakeLists.txt @@ -20,6 +20,7 @@ qt6_add_qml_module(testCppTypes SOURCES commontypes.h ) +qt_autogen_tools_initial_setup(testCppTypesplugin) qt_internal_add_test(tst_qv4debugger SOURCES diff --git a/tests/auto/qml/ecmascripttests/qjstest/test262runner.cpp b/tests/auto/qml/ecmascripttests/qjstest/test262runner.cpp index 24633d9c6d..9037ed0c92 100644 --- a/tests/auto/qml/ecmascripttests/qjstest/test262runner.cpp +++ b/tests/auto/qml/ecmascripttests/qjstest/test262runner.cpp @@ -393,9 +393,7 @@ void Test262Runner::loadTestExpectations() return; } - int line = 0; while (!file.atEnd()) { - ++line; QByteArray line = file.readLine().trimmed(); if (line.startsWith('#') || line.isEmpty()) continue; @@ -440,9 +438,7 @@ void Test262Runner::updateTestExpectations() QTemporaryFile updatedExpectations; updatedExpectations.open(); - int line = 0; while (!file.atEnd()) { - ++line; QByteArray originalLine = file.readLine(); QByteArray line = originalLine.trimmed(); if (line.startsWith('#') || line.isEmpty()) { diff --git a/tests/auto/qml/qmldiskcache/tst_qmldiskcache.cpp b/tests/auto/qml/qmldiskcache/tst_qmldiskcache.cpp index 3f429fec22..d84aaaeba3 100644 --- a/tests/auto/qml/qmldiskcache/tst_qmldiskcache.cpp +++ b/tests/auto/qml/qmldiskcache/tst_qmldiskcache.cpp @@ -65,6 +65,7 @@ private slots: void cppRegisteredSingletonDependency(); void cacheModuleScripts(); void reuseStaticMappings(); + void invalidateSaveLoadCache(); private: QDir m_qmlCacheDirectory; @@ -550,6 +551,7 @@ void tst_qmldiskcache::recompileAfterChange() CleanlyLoadingComponent component(&engine, testCompiler.testFilePath); QScopedPointer<TypeVersion2> obj(qobject_cast<TypeVersion2*>(component.create())); QVERIFY(!obj.isNull()); + qDebug() << obj->property("x"); QVERIFY(QFileInfo(testCompiler.cacheFilePath).lastModified() > initialCacheTimeStamp); } } @@ -1030,6 +1032,112 @@ void tst_qmldiskcache::reuseStaticMappings() QCOMPARE(testCompiler.unitData(), data1); } +class AParent : public QObject +{ + Q_OBJECT + Q_PROPERTY(int x MEMBER x) +public: + AParent(QObject *parent = nullptr) : QObject(parent) {} + int x = 25; +}; + +class BParent : public QObject +{ + Q_OBJECT + + // Insert y before x, to change the property index of x + Q_PROPERTY(int y MEMBER y) + + Q_PROPERTY(int x MEMBER x) +public: + BParent(QObject *parent = nullptr) : QObject(parent) {} + int y = 13; + int x = 25; +}; + +static QString writeTempFile( + const QTemporaryDir &tempDir, const QString &fileName, const char *contents) { + QFile f(tempDir.path() + '/' + fileName); + const bool ok = f.open(QIODevice::WriteOnly | QIODevice::Truncate); + Q_ASSERT(ok); + f.write(contents); + return f.fileName(); +}; + +void tst_qmldiskcache::invalidateSaveLoadCache() +{ + qmlRegisterType<AParent>("Base", 1, 0, "Parent"); + QQmlEngine e; + + // If you store a CU to a .qmlc file at run time, the .qmlc file will contain + // alias entries with the encodedMetaPropertyIndex pre-resolved. That's in + // contrast to .qmlc files generated ahead of time. Exploit that to cause + // a need to recompile the file. + + QTemporaryDir tempDir; + const QString fileName = writeTempFile( + tempDir, QLatin1String("a.qml"), + "import Base\nParent { id: self; property alias z: self.x }"); + const QUrl url = QUrl::fromLocalFile(fileName); + waitForFileSystem(); + + { + QQmlComponent a(&e, url); + QVERIFY2(a.isReady(), qPrintable(a.errorString())); + QScopedPointer<QObject> ao(a.create()); + QVERIFY(!ao.isNull()); + AParent *ap = qobject_cast<AParent *>(ao.data()); + QCOMPARE(ap->property("z").toInt(), ap->x); + } + + QString errorString; + QQmlRefPointer<QV4::ExecutableCompilationUnit> oldUnit + = QV4::ExecutableCompilationUnit::create(); + QVERIFY2(oldUnit->loadFromDisk(url, QFileInfo(fileName).lastModified(), &errorString), qPrintable(errorString)); + + // Produce a checksum mismatch. + e.clearComponentCache(); + qmlClearTypeRegistrations(); + qmlRegisterType<BParent>("Base", 1, 0, "Parent"); + + { + QQmlComponent b(&e, url); + QVERIFY2(b.isReady(), qPrintable(b.errorString())); + QScopedPointer<QObject> bo(b.create()); + QVERIFY(!bo.isNull()); + BParent *bp = qobject_cast<BParent *>(bo.data()); + QCOMPARE(bp->property("z").toInt(), bp->x); + } + + // Make it recompile again. + e.clearComponentCache(); + { + QFile file(fileName); + file.open(QIODevice::WriteOnly | QIODevice::Append); + file.write(" "); + } + waitForFileSystem(); + + { + QQmlComponent b(&e, url); + QVERIFY2(b.isReady(), qPrintable(b.errorString())); + QScopedPointer<QObject> bo(b.create()); + QVERIFY(!bo.isNull()); + BParent *bp = qobject_cast<BParent *>(bo.data()); + QCOMPARE(bp->property("z").toInt(), bp->x); + } + + // Verify that the mapped unit data is actually different now. + // The cache should have been invalidated after all. + // So, now we should be able to load a freshly written CU. + + QQmlRefPointer<QV4::ExecutableCompilationUnit> unit + = QV4::ExecutableCompilationUnit::create(); + QVERIFY2(unit->loadFromDisk(url, QFileInfo(fileName).lastModified(), &errorString), qPrintable(errorString)); + + QVERIFY(unit->unitData() != oldUnit->unitData()); +} + QTEST_MAIN(tst_qmldiskcache) #include "tst_qmldiskcache.moc" diff --git a/tests/auto/qml/qmlformat/data/ecmaScriptClassInQml.formatted.qml b/tests/auto/qml/qmlformat/data/ecmaScriptClassInQml.formatted.qml new file mode 100644 index 0000000000..edbb12c6e6 --- /dev/null +++ b/tests/auto/qml/qmlformat/data/ecmaScriptClassInQml.formatted.qml @@ -0,0 +1,37 @@ +import QtQuick + +Item { + + function f() { + var count = 0; + class Person { + constructor(name){ + this._name = name; + } + } + class Employee extends Person { + constructor(name, age){ + super(name); + this._name = name; + this._age = age; + ++count; + } + + doWork(){} + + /* do we get the comment? */ get name(){ + return this._name.toUpperCase(); + } + + set name(newName){ + if (newName) { + this._name = newName; + } + } + + static get count(){ + return count; + } + } + } +} diff --git a/tests/auto/qml/qmlformat/data/ecmaScriptClassInQml.qml b/tests/auto/qml/qmlformat/data/ecmaScriptClassInQml.qml new file mode 100644 index 0000000000..268859d3cc --- /dev/null +++ b/tests/auto/qml/qmlformat/data/ecmaScriptClassInQml.qml @@ -0,0 +1,45 @@ +import QtQuick + +Item { + +function f() { + +var count = 0; + +class Person { + constructor(name) { + this._name = name + } +} + +class Employee extends Person{ + + + constructor(name, age) { + super(name); + this._name = name; + this._age = age; + ++count; + } + + doWork() { + + } + + get /* do we get the comment? */ name() { + return this._name.toUpperCase(); + } + + set name(newName){ + if(newName){ + this._name = newName; + } + } + + static get count() { return count;} +} + + +} + +}
\ No newline at end of file diff --git a/tests/auto/qml/qmlformat/tst_qmlformat.cpp b/tests/auto/qml/qmlformat/tst_qmlformat.cpp index 65b423b919..843c078f8c 100644 --- a/tests/auto/qml/qmlformat/tst_qmlformat.cpp +++ b/tests/auto/qml/qmlformat/tst_qmlformat.cpp @@ -252,6 +252,9 @@ void TestQmlformat::testFormat_data() << "emptyObject.formatted.qml" << QStringList {}; QTest::newRow("arrow functions") << "arrowFunctions.qml" << "arrowFunctions.formatted.qml" << QStringList {}; + QTest::newRow("ecmaScriptClassInQml") + << "ecmaScriptClassInQml.qml" + << "ecmaScriptClassInQml.formatted.qml" << QStringList {}; } void TestQmlformat::testFormat() diff --git a/tests/auto/qml/qmltyperegistrar/CMakeLists.txt b/tests/auto/qml/qmltyperegistrar/CMakeLists.txt index 9ab6c69b9c..02a0347ac2 100644 --- a/tests/auto/qml/qmltyperegistrar/CMakeLists.txt +++ b/tests/auto/qml/qmltyperegistrar/CMakeLists.txt @@ -67,3 +67,4 @@ qt_add_qml_module(tst-qmltyperegistrar-with-dashes SOURCES foo.cpp foo.h ) +qt_autogen_tools_initial_setup(tst-qmltyperegistrar-with-dashesplugin) diff --git a/tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.cpp b/tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.cpp index aeb46a8274..27f83ca22f 100644 --- a/tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.cpp +++ b/tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.cpp @@ -300,4 +300,11 @@ void tst_qmltyperegistrar::methodReturnType() QVERIFY(qmltypesData.contains("type: \"QQmlComponent\"")); } +void tst_qmltyperegistrar::omitInvisible() +{ + // If it cannot resolve the type a QML_FOREIGN refers to, it should not generate anything. + QVERIFY(qmltypesData.contains( + R"(Component { file: "tst_qmltyperegistrar.h"; name: "Invisible"; accessSemantics: "none" })")); +} + QTEST_MAIN(tst_qmltyperegistrar) diff --git a/tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.h b/tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.h index 7cfce1c2be..1372c32d02 100644 --- a/tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.h +++ b/tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.h @@ -398,6 +398,17 @@ public: Q_INVOKABLE QQmlComponent *createAThing(int) { return nullptr; } }; +class Invisible : public QObject +{ +}; + +struct InvisibleForeign +{ + Q_GADGET + QML_FOREIGN(Invisible) + QML_NAMED_ELEMENT(Invisible) +}; + class tst_qmltyperegistrar : public QObject { Q_OBJECT @@ -429,6 +440,7 @@ private slots: void namespacesAndValueTypes(); void derivedFromForeignPrivate(); void methodReturnType(); + void omitInvisible(); private: QByteArray qmltypesData; diff --git a/tests/auto/qml/qqmlconnections/data/invalidTarget.qml b/tests/auto/qml/qqmlconnections/data/invalidTarget.qml new file mode 100644 index 0000000000..23599649ec --- /dev/null +++ b/tests/auto/qml/qqmlconnections/data/invalidTarget.qml @@ -0,0 +1,31 @@ +import QtQml + +QtObject { + id: root + objectName: button.objectName + + property QtObject b: QtObject { + objectName: "button" + id: button + signal clicked + } + + property Connections c: Connections { + id: connections + target: null + function onClicked() { button.destroy(); } + } + + property Timer t: Timer { + interval: 10 + running: true + onTriggered: { + root.objectName = connections.target.objectName + } + } + + Component.onCompleted: { + connections.target = button; + button.clicked() + } +} diff --git a/tests/auto/qml/qqmlconnections/tst_qqmlconnections.cpp b/tests/auto/qml/qqmlconnections/tst_qqmlconnections.cpp index 1cdf458c0d..a28a8dd9dd 100644 --- a/tests/auto/qml/qqmlconnections/tst_qqmlconnections.cpp +++ b/tests/auto/qml/qqmlconnections/tst_qqmlconnections.cpp @@ -78,6 +78,7 @@ private slots: void noAcceleratedGlobalLookup(); void bindToPropertyWithUnderscoreChangeHandler(); + void invalidTarget(); private: QQmlEngine engine; @@ -490,6 +491,25 @@ void tst_qqmlconnections::bindToPropertyWithUnderscoreChangeHandler() QVERIFY(root->property("success").toBool()); } +void tst_qqmlconnections::invalidTarget() +{ + QQmlEngine engine; + const QUrl url = testFileUrl("invalidTarget.qml"); + QQmlComponent component(&engine, url); + QVERIFY2(component.isReady(), qPrintable(component.errorString())); + + QScopedPointer<QObject> root {component.create()}; + QVERIFY(root); + QCOMPARE(root->objectName(), QStringLiteral("button")); + + QTest::ignoreMessage( + QtWarningMsg, + qPrintable( + url.toString() + + QLatin1String(":5:5: TypeError: Cannot read property 'objectName' of null"))); + QTRY_VERIFY(root->objectName().isEmpty()); +} + QTEST_MAIN(tst_qqmlconnections) #include "tst_qqmlconnections.moc" diff --git a/tests/auto/qml/qqmlecmascript/data/methodTypeMismatch.qml b/tests/auto/qml/qqmlecmascript/data/methodTypeMismatch.qml new file mode 100644 index 0000000000..fdf5f4ea11 --- /dev/null +++ b/tests/auto/qml/qqmlecmascript/data/methodTypeMismatch.qml @@ -0,0 +1,25 @@ +import QtQuick 2.0 + +Item { + id: self + property font myFont + property int notMyFont + + property var object + + function callWithFont() { + object.method_gadget(myFont) // should be fine + } + function callWithInt() { + object.method_gadget(123) + } + function callWithInt2() { + object.method_gadget(notMyFont) + } + function callWithNull() { + object.method_gadget(null) + } + function callWithAllowedNull() { + object.method_qobject(null) + } +} diff --git a/tests/auto/qml/qqmlecmascript/data/readOnlyBindable.qml b/tests/auto/qml/qqmlecmascript/data/readOnlyBindable.qml new file mode 100644 index 0000000000..116036c9ff --- /dev/null +++ b/tests/auto/qml/qqmlecmascript/data/readOnlyBindable.qml @@ -0,0 +1,7 @@ +import Qt.test +import QtQuick + +ReadOnlyBindable { + property int v: 12 + x: v +} diff --git a/tests/auto/qml/qqmlecmascript/testtypes.cpp b/tests/auto/qml/qqmlecmascript/testtypes.cpp index 87d8ed0c1f..cd83702d3a 100644 --- a/tests/auto/qml/qqmlecmascript/testtypes.cpp +++ b/tests/auto/qml/qqmlecmascript/testtypes.cpp @@ -560,6 +560,7 @@ void registerTypes() qmlRegisterType<Receiver>("Qt.test", 1,0, "Receiver"); qmlRegisterType<Sender>("Qt.test", 1,0, "Sender"); + qmlRegisterTypesAndRevisions<ReadOnlyBindable>("Qt.test", 1); } #include "testtypes.moc" diff --git a/tests/auto/qml/qqmlecmascript/testtypes.h b/tests/auto/qml/qqmlecmascript/testtypes.h index acc066fddd..a3df73972e 100644 --- a/tests/auto/qml/qqmlecmascript/testtypes.h +++ b/tests/auto/qml/qqmlecmascript/testtypes.h @@ -833,12 +833,38 @@ public: Q_INVOKABLE void method_unknown(NonRegisteredType) { invoke(28); } + Q_PROPERTY(QFont someFont READ someFont WRITE setSomeFont NOTIFY someFontChanged); + QFont someFont() { return m_someFont; } + void setSomeFont(const QFont &f) + { + if (f == m_someFont) + return; + m_someFont = f; + emit someFontChanged(); + } + Q_INVOKABLE void method_gadget(QFont f) + { + invoke(40); + m_actuals << f; + } + Q_INVOKABLE void method_qobject(QObject *o) + { + invoke(41); + m_actuals << QVariant::fromValue(o); + } + private: friend class MyInvokableBaseObject; void invoke(int idx) { if (m_invoked != -1) m_invokedError = true; m_invoked = idx;} int m_invoked; bool m_invokedError; QVariantList m_actuals; + + QFont m_someFont; + +public: +Q_SIGNALS: + void someFontChanged(); }; MyInvokableBaseObject::~MyInvokableBaseObject() {} @@ -1847,6 +1873,25 @@ public slots: int slot1(int i, int j, int k) {return i+j+k;} }; +class ReadOnlyBindable : public QObject +{ + Q_OBJECT + QML_ELEMENT + Q_PROPERTY(int x READ x WRITE setX BINDABLE bindableX) + Q_OBJECT_BINDABLE_PROPERTY(ReadOnlyBindable, int, _xProp) + +public: + ReadOnlyBindable(QObject *parent = nullptr) + : QObject(parent) + { + setX(7); + } + + int x() const { return _xProp.value(); } + void setX(int x) { _xProp.setValue(x); } + QBindable<int> bindableX() const { return &_xProp; } +}; + void registerTypes(); #endif // TESTTYPES_H diff --git a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp index 2d38bf0524..f47c7132a2 100644 --- a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp +++ b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp @@ -428,6 +428,9 @@ private slots: void functionAsDefaultArgument(); void internalClassParentGc(); + void methodTypeMismatch(); + + void doNotCrashOnReadOnlyBindable(); private: // static void propertyVarWeakRefCallback(v8::Persistent<v8::Value> object, void* parameter); @@ -3331,6 +3334,19 @@ void tst_qqmlecmascript::callQtInvokables() QJSValue callback = qvariant_cast<QJSValue>(o->actuals().at(1)); QVERIFY(!callback.isNull()); QVERIFY(callback.isCallable()); + + o->reset(); + QVERIFY(EVALUATE_VALUE("object.method_gadget(object.someFont)", + QV4::Primitive::undefinedValue())); + QCOMPARE(o->error(), false); + QCOMPARE(o->invoked(), 40); + QCOMPARE(o->actuals(), QVariantList() << QVariant(o->someFont())); + + o->reset(); + QVERIFY(EVALUATE_ERROR("object.method_gadget(123)")); + QCOMPARE(o->error(), false); + QCOMPARE(o->invoked(), -1); + QCOMPARE(o->actuals(), QVariantList()); } void tst_qqmlecmascript::resolveClashingProperties() @@ -9978,6 +9994,85 @@ void tst_qqmlecmascript::internalClassParentGc() QCOMPARE(root->objectName(), "3"); } +void tst_qqmlecmascript::methodTypeMismatch() +{ + QQmlEngine engine; + QQmlComponent component(&engine, testFileUrl("methodTypeMismatch.qml")); + + QScopedPointer<MyInvokableObject> object(new MyInvokableObject()); + + QScopedPointer<QObject> o(component.create()); + QVERIFY2(o, qPrintable(component.errorString())); + o->setProperty("object", QVariant::fromValue(object.get())); + + auto mo = o->metaObject(); + QVERIFY(mo); + + auto method = mo->method(mo->indexOfMethod("callWithFont()")); + QVERIFY(method.isValid()); + QVERIFY(method.invoke(o.get())); + QCOMPARE(object->actuals(), QVariantList() << QVariant(object->someFont())); + + QRegularExpression argumentConversionErrorMatcher("Could not convert argument 0"); + QRegularExpression argumentConversionErrorMatcher2(".*/methodTypeMismatch.qml"); + QRegularExpression typeErrorMatcher( + ".*/methodTypeMismatch\\.qml:..: TypeError: Passing incompatible arguments to C\\+\\+ " + "functions from JavaScript is not allowed."); + + QTest::ignoreMessage(QtWarningMsg, argumentConversionErrorMatcher); + QTest::ignoreMessage(QtWarningMsg, argumentConversionErrorMatcher2); + QTest::ignoreMessage(QtWarningMsg, typeErrorMatcher); + object->reset(); + method = mo->method(mo->indexOfMethod("callWithInt()")); + QVERIFY(method.isValid()); + QVERIFY(method.invoke(o.get())); + QCOMPARE(object->actuals().size(), + 0); // actuals() should not contain reinterpret_cast<QFont>(123) !!! + + QTest::ignoreMessage(QtWarningMsg, argumentConversionErrorMatcher); + QTest::ignoreMessage(QtWarningMsg, argumentConversionErrorMatcher2); + QTest::ignoreMessage(QtWarningMsg, typeErrorMatcher); + object->reset(); + method = mo->method(mo->indexOfMethod("callWithInt2()")); + QVERIFY(method.isValid()); + QVERIFY(method.invoke(o.get())); + QCOMPARE(object->actuals().size(), + 0); // actuals() should not contain reinterpret_cast<QFont>(0) !!! + + QTest::ignoreMessage(QtWarningMsg, argumentConversionErrorMatcher); + QTest::ignoreMessage(QtWarningMsg, argumentConversionErrorMatcher2); + QTest::ignoreMessage(QtWarningMsg, typeErrorMatcher); + object->reset(); + method = mo->method(mo->indexOfMethod("callWithNull()")); + QVERIFY(method.isValid()); + QVERIFY(method.invoke(o.get())); + QCOMPARE(object->actuals().size(), + 0); // actuals() should not contain reinterpret_cast<QFont>(nullptr) !!! + + // make sure that null is still accepted by functions accepting, e.g., a QObject*! + object->reset(); + method = mo->method(mo->indexOfMethod("callWithAllowedNull()")); + QVERIFY(method.isValid()); + QVERIFY(method.invoke(o.get())); + QCOMPARE(object->actuals(), QVariantList() << QVariant::fromValue((QObject *)nullptr)); +} + +void tst_qqmlecmascript::doNotCrashOnReadOnlyBindable() +{ + QQmlEngine engine; + QQmlComponent c(&engine, testFileUrl("readOnlyBindable.qml")); + QVERIFY2(c.isReady(), qPrintable(c.errorString())); +#ifndef QT_NO_DEBUG + QTest::ignoreMessage( + QtWarningMsg, + "setBinding: Could not set binding via bindable interface. " + "The QBindable is read-only."); +#endif + QScopedPointer<QObject> o(c.create()); + QVERIFY(o); + QCOMPARE(o->property("x").toInt(), 7); +} + QTEST_MAIN(tst_qqmlecmascript) #include "tst_qqmlecmascript.moc" diff --git a/tests/auto/qml/qqmlfileselector/data/qmldirtest/main.qml b/tests/auto/qml/qqmlfileselector/data/qmldirtest/main.qml new file mode 100644 index 0000000000..d6dd2c9b90 --- /dev/null +++ b/tests/auto/qml/qqmlfileselector/data/qmldirtest/main.qml @@ -0,0 +1,13 @@ +import QtQuick +import qmldirtest + +Window { + width: 640 + height: 480 + visible: true + property color color: mybutton.color + + MyButton { + id: mybutton + } +} diff --git a/tests/auto/qml/qqmlfileselector/data/qmldirtest/qml/+linux/MyButton.qml b/tests/auto/qml/qqmlfileselector/data/qmldirtest/qml/+linux/MyButton.qml new file mode 100644 index 0000000000..cc6eb967da --- /dev/null +++ b/tests/auto/qml/qqmlfileselector/data/qmldirtest/qml/+linux/MyButton.qml @@ -0,0 +1,7 @@ +import QtQuick + +Rectangle { + width: 300 + height: 50 + color: "blue" +} diff --git a/tests/auto/qml/qqmlfileselector/data/qmldirtest/qml/+macos/MyButton.qml b/tests/auto/qml/qqmlfileselector/data/qmldirtest/qml/+macos/MyButton.qml new file mode 100644 index 0000000000..5bf632c48d --- /dev/null +++ b/tests/auto/qml/qqmlfileselector/data/qmldirtest/qml/+macos/MyButton.qml @@ -0,0 +1,7 @@ +import QtQuick + +Rectangle { + width: 300 + height: 50 + color: "yellow" +} diff --git a/tests/auto/qml/qqmlfileselector/data/qmldirtest/qml/MyButton.qml b/tests/auto/qml/qqmlfileselector/data/qmldirtest/qml/MyButton.qml new file mode 100644 index 0000000000..32db428c4f --- /dev/null +++ b/tests/auto/qml/qqmlfileselector/data/qmldirtest/qml/MyButton.qml @@ -0,0 +1,7 @@ +import QtQuick + +Rectangle { + width: 300 + height: 50 + color: "green" +} diff --git a/tests/auto/qml/qqmlfileselector/data/qmldirtest/qmldir b/tests/auto/qml/qqmlfileselector/data/qmldirtest/qmldir new file mode 100644 index 0000000000..ac68d9097d --- /dev/null +++ b/tests/auto/qml/qqmlfileselector/data/qmldirtest/qmldir @@ -0,0 +1,5 @@ +module qmldirtest +MyButton 1.0 qml/MyButton.qml +MyButton 1.0 qml/+linux/MyButton.qml +MyButton 1.0 qml/+macos/MyButton.qml + diff --git a/tests/auto/qml/qqmlfileselector/tst_qqmlfileselector.cpp b/tests/auto/qml/qqmlfileselector/tst_qqmlfileselector.cpp index 4c99bcf9c8..fe55d8b056 100644 --- a/tests/auto/qml/qqmlfileselector/tst_qqmlfileselector.cpp +++ b/tests/auto/qml/qqmlfileselector/tst_qqmlfileselector.cpp @@ -47,7 +47,7 @@ private slots: void basicTest(); void basicTestCached(); void applicationEngineTest(); - + void qmldirCompatibility(); }; void tst_qqmlfileselector::basicTest() @@ -95,6 +95,23 @@ void tst_qqmlfileselector::applicationEngineTest() QCOMPARE(object->property("value").toString(), QString("selected")); } +void tst_qqmlfileselector::qmldirCompatibility() +{ + QQmlApplicationEngine engine; + engine.addImportPath(dataDirectory()); + engine.load(testFileUrl("qmldirtest/main.qml")); + QVERIFY(!engine.rootObjects().isEmpty()); + QObject *object = engine.rootObjects().at(0); + auto color = object->property("color").value<QColor>(); +#if defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID) + QCOMPARE(color, QColorConstants::Svg::blue); +#elif defined(Q_OS_DARWIN) + QCOMPARE(color, QColorConstants::Svg::yellow); +#else + QCOMPARE(color, QColorConstants::Svg::green); +#endif +} + QTEST_MAIN(tst_qqmlfileselector) #include "tst_qqmlfileselector.moc" diff --git a/tests/auto/qml/qqmllanguage/data/MyRectangle.qml b/tests/auto/qml/qqmllanguage/data/MyRectangle.qml new file mode 100644 index 0000000000..4d5e7c6c8d --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/MyRectangle.qml @@ -0,0 +1,10 @@ +import QtQuick + +Item { + property alias rectangle1AnchorsleftMargin: rectangle1.anchors.leftMargin + + Rectangle { + id: rectangle1 + anchors.leftMargin: 250 + } +} diff --git a/tests/auto/qml/qqmllanguage/data/alias.19.qml b/tests/auto/qml/qqmllanguage/data/alias.19.qml new file mode 100644 index 0000000000..a96c0c694d --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/alias.19.qml @@ -0,0 +1,11 @@ +import QtQuick + +Item { + id: myThing + width: 1920 + + MyRectangle { + rectangle1AnchorsleftMargin: myThing.width / 2 + Component.onCompleted: myThing.height = rectangle1AnchorsleftMargin + } +} diff --git a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp index 06b2738c9e..047df2f6d0 100644 --- a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp +++ b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp @@ -2257,6 +2257,16 @@ void tst_qqmllanguage::aliasProperties() QQmlComponent component(&engine, testFileUrl("alias.18.qml")); VERIFY_ERRORS("alias.18.errors.txt"); } + + // Binding on deep alias + { + QQmlComponent component(&engine, testFileUrl("alias.19.qml")); + VERIFY_ERRORS(0); + + QScopedPointer<QObject> object(component.create()); + QVERIFY(!object.isNull()); + QCOMPARE(object->property("height").toInt(), 960); + } } // QTBUG-13374 Test that alias properties and signals can coexist diff --git a/tests/auto/qml/qqmllistmodel/data/protectQObjectFromGC.qml b/tests/auto/qml/qqmllistmodel/data/protectQObjectFromGC.qml new file mode 100644 index 0000000000..43b375b681 --- /dev/null +++ b/tests/auto/qml/qqmllistmodel/data/protectQObjectFromGC.qml @@ -0,0 +1,21 @@ +import QtQml +import QtQml.Models + +ListModel { + id: filesModel + property Component testComponent: Component { + id: testComponent + QtObject { + required property string name + } + } + Component.onCompleted: { + filesModel.clear() + for(let i = 0; i < 10; i++) { + filesModel.append({ + path: testComponent.createObject(null, { name: "" + i }) + }) + } + gc() + } +} diff --git a/tests/auto/qml/qqmllistmodel/tst_qqmllistmodel.cpp b/tests/auto/qml/qqmllistmodel/tst_qqmllistmodel.cpp index 37b0f6f1fe..fbdf6d90f3 100644 --- a/tests/auto/qml/qqmllistmodel/tst_qqmllistmodel.cpp +++ b/tests/auto/qml/qqmllistmodel/tst_qqmllistmodel.cpp @@ -139,6 +139,7 @@ private slots: void listElementWithTemplateString(); void destroyComponentObject(); void objectOwnershipFlip(); + void protectQObjectFromGC(); }; bool tst_qqmllistmodel::compareVariantList(const QVariantList &testList, QVariant object) @@ -1882,7 +1883,7 @@ void tst_qqmllistmodel::destroyComponentObject() Q_RETURN_ARG(QVariant, retVal)); QVERIFY(retVal.toBool()); QTRY_VERIFY(created.isNull()); - QTRY_VERIFY(list->get(0).property("obj").isUndefined()); + QTRY_VERIFY(list->get(0).property("obj").isNull()); QCOMPARE(list->count(), 1); } @@ -1920,6 +1921,25 @@ void tst_qqmllistmodel::objectOwnershipFlip() QCOMPARE(QJSEngine::objectOwnership(item.data()), QJSEngine::CppOwnership); } +void tst_qqmllistmodel::protectQObjectFromGC() +{ + QQmlEngine engine; + QQmlComponent component(&engine, testFileUrl("protectQObjectFromGC.qml")); + QVERIFY2(component.isReady(), qPrintable(component.errorString())); + QScopedPointer<QObject> root(component.create()); + QVERIFY(!root.isNull()); + + QQmlListModel *listModel = qobject_cast<QQmlListModel *>(root.data()); + QVERIFY(listModel); + QCOMPARE(listModel->count(), 10); + + for (int i = 0; i < 10; ++i) { + QObject *element = qjsvalue_cast<QObject *>(listModel->get(i).property("path")); + QVERIFY(element); + QCOMPARE(element->property("name").toString(), QString::number(i)); + } +} + QTEST_MAIN(tst_qqmllistmodel) #include "tst_qqmllistmodel.moc" diff --git a/tests/auto/qml/qqmlmetatype/tst_qqmlmetatype.cpp b/tests/auto/qml/qqmlmetatype/tst_qqmlmetatype.cpp index be493484ee..f726855727 100644 --- a/tests/auto/qml/qqmlmetatype/tst_qqmlmetatype.cpp +++ b/tests/auto/qml/qqmlmetatype/tst_qqmlmetatype.cpp @@ -72,6 +72,8 @@ private slots: void enumsInRecursiveImport_data(); void enumsInRecursiveImport(); + + void clearPropertyCaches(); }; class TestType : public QObject @@ -734,6 +736,24 @@ void tst_qqmlmetatype::enumsInRecursiveImport() QTRY_COMPARE(obj->property("color").toString(), QString("green")); } +void tst_qqmlmetatype::clearPropertyCaches() +{ + qmlClearTypeRegistrations(); + qmlRegisterType<TestType>("ClearPropertyCaches", 1, 0, "A"); + + QQmlRefPointer<QQmlPropertyCache> oldCache( + QQmlMetaType::propertyCache(&TestType::staticMetaObject)); + QVERIFY(oldCache); + + qmlClearTypeRegistrations(); + qmlRegisterType<TestType>("ClearPropertyCaches", 1, 0, "B"); + QQmlRefPointer<QQmlPropertyCache> newCache( + QQmlMetaType::propertyCache(&TestType::staticMetaObject)); + QVERIFY(newCache); + + QVERIFY(oldCache.data() != newCache.data()); +} + QTEST_MAIN(tst_qqmlmetatype) #include "tst_qqmlmetatype.moc" diff --git a/tests/auto/quick/pointerhandlers/qquicktaphandler/BLACKLIST b/tests/auto/quick/pointerhandlers/qquicktaphandler/BLACKLIST deleted file mode 100644 index 9cc6783375..0000000000 --- a/tests/auto/quick/pointerhandlers/qquicktaphandler/BLACKLIST +++ /dev/null @@ -1,4 +0,0 @@ -# QTBUG-103072 -[gesturePolicyDragWithinBounds] -android - diff --git a/tests/auto/quick/qquickcanvasitem/data/tst_arc.qml b/tests/auto/quick/qquickcanvasitem/data/tst_arc.qml index 33fffd4cb1..00d13f31f4 100644 --- a/tests/auto/quick/qquickcanvasitem/data/tst_arc.qml +++ b/tests/auto/quick/qquickcanvasitem/data/tst_arc.qml @@ -6,6 +6,7 @@ CanvasTestCase { function init_data() { return testData("2d"); } function test_angle_1(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); ctx.reset(); @@ -21,6 +22,7 @@ CanvasTestCase { } function test_angle_2(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); ctx.reset(); @@ -36,6 +38,7 @@ CanvasTestCase { } function test_angle_3(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); ctx.reset(); ctx.fillStyle = '#0f0'; @@ -53,6 +56,7 @@ CanvasTestCase { } function test_angle_4(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); ctx.reset(); @@ -71,6 +75,7 @@ CanvasTestCase { } function test_angle_5(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); ctx.reset(); @@ -90,6 +95,7 @@ CanvasTestCase { function test_angle_6(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); ctx.reset(); @@ -110,6 +116,7 @@ CanvasTestCase { function test_empty(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); ctx.reset(); @@ -125,6 +132,7 @@ CanvasTestCase { } function test_nonempty(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); ctx.reset(); @@ -141,6 +149,7 @@ CanvasTestCase { } function test_nonfinite(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); ctx.reset(); @@ -199,6 +208,7 @@ CanvasTestCase { } function test_end(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); ctx.reset(); @@ -216,6 +226,7 @@ CanvasTestCase { } function test_negative(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); ctx.reset(); @@ -234,6 +245,7 @@ CanvasTestCase { function test_scale_1(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); ctx.reset(); @@ -270,6 +282,7 @@ CanvasTestCase { function test_scale_2(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); ctx.reset(); @@ -296,6 +309,7 @@ CanvasTestCase { function test_selfintersect_1(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); ctx.reset(); @@ -316,6 +330,7 @@ CanvasTestCase { function test_selfintersect_2(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); ctx.reset(); @@ -340,6 +355,7 @@ CanvasTestCase { function test_shape_1(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); ctx.reset(); @@ -361,6 +377,7 @@ CanvasTestCase { function test_shape_2(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); ctx.reset(); @@ -381,6 +398,7 @@ CanvasTestCase { } function test_shape_3(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); ctx.reset(); @@ -401,6 +419,7 @@ CanvasTestCase { function test_shape_4(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); ctx.reset(); @@ -421,6 +440,7 @@ CanvasTestCase { function test_shape_5(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); ctx.reset(); @@ -441,6 +461,7 @@ CanvasTestCase { function test_twopie(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); ctx.reset(); @@ -488,6 +509,7 @@ CanvasTestCase { function test_zero(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); ctx.reset(); diff --git a/tests/auto/quick/qquickcanvasitem/data/tst_arcto.qml b/tests/auto/quick/qquickcanvasitem/data/tst_arcto.qml index ef1b7a7b2a..81412d98c9 100644 --- a/tests/auto/quick/qquickcanvasitem/data/tst_arcto.qml +++ b/tests/auto/quick/qquickcanvasitem/data/tst_arcto.qml @@ -7,6 +7,7 @@ CanvasTestCase { function test_coincide(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); ctx.reset(); ctx.fillStyle = '#f00'; @@ -44,6 +45,7 @@ CanvasTestCase { } function test_collinear(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); ctx.reset(); @@ -109,6 +111,7 @@ CanvasTestCase { } function test_subpath(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); ctx.reset(); @@ -135,6 +138,7 @@ CanvasTestCase { function test_negative(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); ctx.reset(); @@ -152,6 +156,7 @@ CanvasTestCase { function test_nonfinite(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); ctx.reset(); @@ -208,6 +213,7 @@ CanvasTestCase { } function test_scale(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); ctx.reset(); @@ -237,6 +243,7 @@ CanvasTestCase { function test_shape(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); ctx.reset(); @@ -348,6 +355,7 @@ CanvasTestCase { function test_transform(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); ctx.reset(); @@ -374,6 +382,7 @@ CanvasTestCase { } function test_zero(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); ctx.reset(); diff --git a/tests/auto/quick/qquickcanvasitem/data/tst_composite.qml b/tests/auto/quick/qquickcanvasitem/data/tst_composite.qml index 8a5a52cf1e..4ee24ad437 100644 --- a/tests/auto/quick/qquickcanvasitem/data/tst_composite.qml +++ b/tests/auto/quick/qquickcanvasitem/data/tst_composite.qml @@ -6,6 +6,7 @@ CanvasTestCase { function init_data() { return testData("2d"); } function test_clearRect(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); ctx.reset(); ctx.fillStyle = '#f00'; @@ -17,6 +18,7 @@ CanvasTestCase { function test_clip(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); var composites = [ {compsite:"copy"}, {compsite:"destination-atop"}, @@ -47,6 +49,7 @@ CanvasTestCase { function test_globalAlpha(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); ctx.reset(); compare(ctx.globalAlpha, 1.0); @@ -83,6 +86,7 @@ CanvasTestCase { function test_operation(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); ctx.reset(); ctx.globalCompositeOperation = 'xor'; @@ -137,6 +141,7 @@ CanvasTestCase { function test_solid(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); ctx.reset(); ctx.fillStyle = Qt.rgba(0, 1, 1, 1.0); @@ -233,6 +238,7 @@ CanvasTestCase { } function test_transparent(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); ctx.reset(); ctx.fillStyle = 'rgba(0, 255, 0, 0.5)'; @@ -330,6 +336,7 @@ CanvasTestCase { function test_uncovered(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); ctx.reset(); ctx.fillStyle = 'rgba(0, 255, 0, 0.5)'; diff --git a/tests/auto/quick/qquickcanvasitem/data/tst_fillStyle.qml b/tests/auto/quick/qquickcanvasitem/data/tst_fillStyle.qml index 58ea6d7f59..9e8c0785c3 100644 --- a/tests/auto/quick/qquickcanvasitem/data/tst_fillStyle.qml +++ b/tests/auto/quick/qquickcanvasitem/data/tst_fillStyle.qml @@ -6,6 +6,7 @@ CanvasTestCase { function init_data() { return testData("2d"); } function test_default(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); ctx.reset(); verify(ctx.fillStyle, "#000000"); @@ -14,6 +15,7 @@ CanvasTestCase { } function test_get(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); ctx.reset(); ctx.fillStyle = '#fa0'; @@ -23,6 +25,7 @@ CanvasTestCase { } function test_hex(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); ctx.reset(); ctx.fillStyle = '#f00'; @@ -37,6 +40,7 @@ CanvasTestCase { } function test_invalid(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); ctx.reset(); ctx.fillStyle = '#fa0'; @@ -60,6 +64,7 @@ CanvasTestCase { } function test_saverestore(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); var old = ctx.fillStyle; ctx.save(); @@ -75,6 +80,7 @@ CanvasTestCase { } function test_namedColor(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); ctx.reset(); ctx.fillStyle = "red"; @@ -91,6 +97,7 @@ CanvasTestCase { } function test_rgba(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); ctx.reset(); ctx.fillStyle = "rgb(-100, 300, 255)"; @@ -108,6 +115,7 @@ CanvasTestCase { function test_hsla(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); ctx.reset(); ctx.fillStyle = "hsla(120, 100%, 50%, 0.499)"; diff --git a/tests/auto/quick/qquickcanvasitem/data/tst_fillrect.qml b/tests/auto/quick/qquickcanvasitem/data/tst_fillrect.qml index ce1c27c6bc..213abdd622 100644 --- a/tests/auto/quick/qquickcanvasitem/data/tst_fillrect.qml +++ b/tests/auto/quick/qquickcanvasitem/data/tst_fillrect.qml @@ -6,6 +6,7 @@ CanvasTestCase { function init_data() { return testData("2d"); } function test_fillRect(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); ctx.fillStyle = "red"; ctx.fillRect(0, 0, canvas.width, canvas.height); diff --git a/tests/auto/quick/qquickcanvasitem/data/tst_gradient.qml b/tests/auto/quick/qquickcanvasitem/data/tst_gradient.qml index 7c87d896fb..70e77c8760 100644 --- a/tests/auto/quick/qquickcanvasitem/data/tst_gradient.qml +++ b/tests/auto/quick/qquickcanvasitem/data/tst_gradient.qml @@ -6,6 +6,7 @@ CanvasTestCase { function init_data() { return testData("2d"); } function test_basic(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); ctx.reset(); ctx.fillStyle = '#0f0'; @@ -18,6 +19,7 @@ CanvasTestCase { function test_interpolate(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); ctx.reset(); @@ -166,6 +168,7 @@ CanvasTestCase { } function test_radial(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); ctx.reset(); ctx.fillStyle = '#0f0'; @@ -788,6 +791,7 @@ CanvasTestCase { } function test_linear(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); ctx.reset(); try { var err = false; @@ -907,6 +911,7 @@ CanvasTestCase { } function test_object(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); ctx.reset(); var g1 = ctx.createLinearGradient(0, 0, 100, 0); @@ -978,6 +983,7 @@ CanvasTestCase { function test_conical(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); ctx.reset(); var g = ctx.createConicalGradient(10, 10, 50); diff --git a/tests/auto/quick/qquickcanvasitem/data/tst_image.qml b/tests/auto/quick/qquickcanvasitem/data/tst_image.qml index 1f695d7080..a1eb272cd0 100644 --- a/tests/auto/quick/qquickcanvasitem/data/tst_image.qml +++ b/tests/auto/quick/qquickcanvasitem/data/tst_image.qml @@ -11,12 +11,12 @@ CanvasTestCase { canvas.loadImage('rgrg-256x256.png'); canvas.loadImage('ggrr-256x256.png'); canvas.loadImage('broken.png'); - while (!canvas.isImageLoaded('green.png')) - wait(200); + tryVerify(function() { return canvas.isImageLoaded('green.png'); }) } function test_3args(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); loadImages(canvas); ctx.reset(); @@ -35,6 +35,7 @@ CanvasTestCase { } function test_5args(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); loadImages(canvas); @@ -54,6 +55,7 @@ CanvasTestCase { } function test_9args(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); loadImages(canvas); @@ -118,6 +120,7 @@ CanvasTestCase { } function test_animated(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); loadImages(canvas); @@ -125,6 +128,7 @@ CanvasTestCase { } function test_clip(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); loadImages(canvas); @@ -139,6 +143,7 @@ CanvasTestCase { } function test_self(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); loadImages(canvas); @@ -170,6 +175,7 @@ CanvasTestCase { function test_outsidesource(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); loadImages(canvas); @@ -207,6 +213,7 @@ CanvasTestCase { function test_null(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); loadImages(canvas); @@ -220,15 +227,18 @@ CanvasTestCase { function test_url(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); canvas.loadImage(testCase.green); + tryVerify(function() { return canvas.isImageLoaded(testCase.green); }) ctx.drawImage(testCase.green, 0, 0); comparePixel(ctx, 0,0, 0,255,0,255,2); } function test_composite(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); loadImages(canvas); @@ -241,12 +251,14 @@ CanvasTestCase { } function test_path(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); loadImages(canvas); } function test_transform(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); loadImages(canvas); @@ -260,6 +272,7 @@ CanvasTestCase { function test_imageitem(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); loadImages(canvas); @@ -268,6 +281,7 @@ CanvasTestCase { function test_imageData(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); loadImages(canvas); @@ -276,6 +290,7 @@ CanvasTestCase { function test_wrongtype(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); loadImages(canvas); @@ -293,6 +308,7 @@ CanvasTestCase { function test_nonfinite(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); loadImages(canvas); @@ -606,6 +622,7 @@ CanvasTestCase { function test_negative(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); loadImages(canvas); @@ -661,6 +678,7 @@ CanvasTestCase { function test_canvas(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); loadImages(canvas); @@ -684,6 +702,7 @@ CanvasTestCase { function test_broken(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); loadImages(canvas); @@ -694,6 +713,7 @@ CanvasTestCase { function test_alpha(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); loadImages(canvas); @@ -706,6 +726,7 @@ CanvasTestCase { } function test_multiple_painting(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); loadImages(canvas); diff --git a/tests/auto/quick/qquickcanvasitem/data/tst_imagedata.qml b/tests/auto/quick/qquickcanvasitem/data/tst_imagedata.qml index 76b99a765e..aab7a95589 100644 --- a/tests/auto/quick/qquickcanvasitem/data/tst_imagedata.qml +++ b/tests/auto/quick/qquickcanvasitem/data/tst_imagedata.qml @@ -11,6 +11,7 @@ CanvasTestCase { skip("ctx.getImageData crashes on offscreen/minimal platforms"); var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); var size = 17 ctx.reset(); diff --git a/tests/auto/quick/qquickcanvasitem/data/tst_line.qml b/tests/auto/quick/qquickcanvasitem/data/tst_line.qml index ba7ff09728..e5d03e5db7 100644 --- a/tests/auto/quick/qquickcanvasitem/data/tst_line.qml +++ b/tests/auto/quick/qquickcanvasitem/data/tst_line.qml @@ -6,6 +6,7 @@ CanvasTestCase { function init_data() { return testData("2d"); } function test_default(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); ctx.reset(); compare(ctx.lineWidth, 1); @@ -16,6 +17,7 @@ CanvasTestCase { function test_cross(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); ctx.reset(); ctx.fillStyle = '#0f0'; @@ -43,6 +45,7 @@ CanvasTestCase { function test_join(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); ctx.reset(); @@ -306,6 +309,7 @@ CanvasTestCase { } function test_miter(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); ctx.reset(); ctx.fillStyle = '#f00'; @@ -481,6 +485,7 @@ CanvasTestCase { } function test_width(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); ctx.reset(); ctx.fillStyle = '#0f0'; @@ -625,6 +630,7 @@ CanvasTestCase { skip("line::test_cap crashes on Android, QTBUG-103257") var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); ctx.reset(); @@ -841,6 +847,7 @@ CanvasTestCase { function test_lineDash(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); ctx.reset(); ctx.strokeStyle = "#fff"; @@ -899,6 +906,7 @@ CanvasTestCase { function test_lineDashReset(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); ctx.reset(); ctx.strokeStyle = "#ff0000"; @@ -930,6 +938,7 @@ CanvasTestCase { function test_lineDashOffset(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); ctx.reset(); ctx.strokeStyle = "#fff"; diff --git a/tests/auto/quick/qquickcanvasitem/data/tst_path.qml b/tests/auto/quick/qquickcanvasitem/data/tst_path.qml index 60c782c8fa..ae08b58519 100644 --- a/tests/auto/quick/qquickcanvasitem/data/tst_path.qml +++ b/tests/auto/quick/qquickcanvasitem/data/tst_path.qml @@ -6,6 +6,7 @@ CanvasTestCase { function init_data() { return testData("2d"); } function test_basic(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); ctx.reset(); ctx.fillStyle = '#0f0'; @@ -36,6 +37,7 @@ CanvasTestCase { } function test_beginPath(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); ctx.fillStyle = '#0f0'; ctx.fillRect(0, 0, 100, 50); @@ -48,6 +50,7 @@ CanvasTestCase { } function test_closePath(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); ctx.reset(); ctx.fillStyle = '#0f0'; @@ -86,6 +89,7 @@ CanvasTestCase { function test_isPointInPath(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); ctx.reset(); ctx.arc(50, 25, 10, 0, Math.PI, false); @@ -256,6 +260,7 @@ CanvasTestCase { function test_fill(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); ctx.reset(); ctx.fillStyle = '#f00'; @@ -378,6 +383,7 @@ CanvasTestCase { } function test_stroke(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); ctx.reset(); ctx.fillStyle = '#0f0'; @@ -662,6 +668,7 @@ CanvasTestCase { } function test_clip(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); ctx.reset(); ctx.fillStyle = '#f00'; @@ -784,6 +791,7 @@ CanvasTestCase { function test_moveTo(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); ctx.reset(); ctx.fillStyle = '#f00'; @@ -839,6 +847,7 @@ CanvasTestCase { } function test_lineTo(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); ctx.reset(); ctx.fillStyle = '#f00'; @@ -904,6 +913,7 @@ CanvasTestCase { } function test_bezierCurveTo(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); ctx.reset(); ctx.fillStyle = '#f00'; @@ -1072,6 +1082,7 @@ CanvasTestCase { } function test_quadraticCurveTo(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); ctx.reset(); ctx.fillStyle = '#f00'; @@ -1173,6 +1184,7 @@ CanvasTestCase { } function test_rect(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); ctx.reset(); @@ -1371,6 +1383,7 @@ CanvasTestCase { function test_clearRect(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); ctx.reset(); ctx.fillStyle = '#0f0'; @@ -1383,6 +1396,7 @@ CanvasTestCase { } function test_fillRect(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); ctx.reset(); ctx.beginPath(); @@ -1397,6 +1411,7 @@ CanvasTestCase { function test_strokeRect(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); ctx.reset(); ctx.beginPath(); @@ -1412,6 +1427,7 @@ CanvasTestCase { } function test_transform(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); ctx.reset(); ctx.fillStyle = '#f00'; diff --git a/tests/auto/quick/qquickcanvasitem/data/tst_pattern.qml b/tests/auto/quick/qquickcanvasitem/data/tst_pattern.qml index 1d7fd2c12f..e0a4d7ad23 100644 --- a/tests/auto/quick/qquickcanvasitem/data/tst_pattern.qml +++ b/tests/auto/quick/qquickcanvasitem/data/tst_pattern.qml @@ -6,36 +6,42 @@ CanvasTestCase { function init_data() { return testData("2d"); } function test_basic(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); ctx.reset(); canvas.destroy() } function test_animated(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); ctx.reset(); canvas.destroy() } function test_image(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); ctx.reset(); canvas.destroy() } function test_modified(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); ctx.reset(); canvas.destroy() } function test_paint(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); ctx.reset(); canvas.destroy() } function test_repeat(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); ctx.reset(); canvas.destroy() diff --git a/tests/auto/quick/qquickcanvasitem/data/tst_pixel.qml b/tests/auto/quick/qquickcanvasitem/data/tst_pixel.qml index 281264ba92..ef908db92a 100644 --- a/tests/auto/quick/qquickcanvasitem/data/tst_pixel.qml +++ b/tests/auto/quick/qquickcanvasitem/data/tst_pixel.qml @@ -7,6 +7,7 @@ CanvasTestCase { function init_data() { return testData("2d"); } function test_createImageData(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); var imageData = ctx.createImageData(1, 1); var imageDataValues = imageData.data; @@ -20,24 +21,28 @@ CanvasTestCase { } function test_getImageData(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); ctx.reset(); canvas.destroy() } function test_object(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); ctx.reset(); canvas.destroy() } function test_putImageData(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); ctx.reset(); canvas.destroy() } function test_filters(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); ctx.reset(); canvas.destroy() diff --git a/tests/auto/quick/qquickcanvasitem/data/tst_shadow.qml b/tests/auto/quick/qquickcanvasitem/data/tst_shadow.qml index 2baaa072d0..14318b3f56 100644 --- a/tests/auto/quick/qquickcanvasitem/data/tst_shadow.qml +++ b/tests/auto/quick/qquickcanvasitem/data/tst_shadow.qml @@ -6,12 +6,14 @@ CanvasTestCase { function init_data() { return testData("2d"); } function test_basic(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); ctx.reset(); canvas.destroy() } function test_blur(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); ctx.reset(); canvas.destroy() @@ -19,6 +21,7 @@ CanvasTestCase { function test_clip(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); ctx.reset(); canvas.destroy() @@ -26,6 +29,7 @@ CanvasTestCase { function test_composite(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); ctx.reset(); canvas.destroy() @@ -33,6 +37,7 @@ CanvasTestCase { function test_enable(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); ctx.reset(); canvas.destroy() @@ -40,36 +45,42 @@ CanvasTestCase { function test_gradient(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); ctx.reset(); canvas.destroy() } function test_image(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); ctx.reset(); canvas.destroy() } function test_offset(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); ctx.reset(); canvas.destroy() } function test_pattern(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); ctx.reset(); canvas.destroy() } function test_stroke(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); ctx.reset(); canvas.destroy() } function test_tranform(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); ctx.reset(); canvas.destroy() diff --git a/tests/auto/quick/qquickcanvasitem/data/tst_state.qml b/tests/auto/quick/qquickcanvasitem/data/tst_state.qml index 18464def7c..ce02f9d7f7 100644 --- a/tests/auto/quick/qquickcanvasitem/data/tst_state.qml +++ b/tests/auto/quick/qquickcanvasitem/data/tst_state.qml @@ -6,6 +6,7 @@ CanvasTestCase { function init_data() { return testData("2d"); } function test_bitmap(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); ctx.reset(); ctx.fillStyle = '#f00'; @@ -19,6 +20,7 @@ CanvasTestCase { } function test_clip(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); ctx.reset(); @@ -35,6 +37,7 @@ CanvasTestCase { } function test_fillStyle(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); ctx.reset(); // Test that restore() undoes any modifications @@ -56,6 +59,7 @@ CanvasTestCase { } function test_font(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); ctx.reset(); @@ -78,6 +82,7 @@ CanvasTestCase { } function test_globalAlpha(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); ctx.reset(); @@ -100,6 +105,7 @@ CanvasTestCase { } function test_globalCompositeOperation(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); ctx.reset(); @@ -122,6 +128,7 @@ CanvasTestCase { } function test_lineCap(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); ctx.reset(); @@ -144,6 +151,7 @@ CanvasTestCase { } function test_lineJoin(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); ctx.reset(); @@ -166,6 +174,7 @@ CanvasTestCase { } function test_lineWidth(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); ctx.reset(); @@ -188,6 +197,7 @@ CanvasTestCase { } function test_miterLimit(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); ctx.reset(); @@ -210,6 +220,7 @@ CanvasTestCase { } function test_path(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); ctx.reset(); @@ -225,6 +236,7 @@ CanvasTestCase { } function test_shadow(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); ctx.reset(); @@ -295,6 +307,7 @@ CanvasTestCase { } function test_stack(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); ctx.reset(); @@ -330,6 +343,7 @@ CanvasTestCase { } function test_strokeStyle(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); ctx.reset(); @@ -353,6 +367,7 @@ CanvasTestCase { function test_text(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); ctx.reset(); @@ -392,6 +407,7 @@ CanvasTestCase { function test_transform(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); ctx.reset(); diff --git a/tests/auto/quick/qquickcanvasitem/data/tst_strokeStyle.qml b/tests/auto/quick/qquickcanvasitem/data/tst_strokeStyle.qml index a3f1ab0a9b..0dc39b8b4c 100644 --- a/tests/auto/quick/qquickcanvasitem/data/tst_strokeStyle.qml +++ b/tests/auto/quick/qquickcanvasitem/data/tst_strokeStyle.qml @@ -8,6 +8,7 @@ CanvasTestCase { function init_data() { return testData("2d"); } function test_default(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); ctx.reset(); compare(ctx.strokeStyle, "#000000") @@ -17,6 +18,7 @@ CanvasTestCase { } function test_saverestore(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); var old = ctx.strokeStyle; ctx.save(); @@ -33,6 +35,7 @@ CanvasTestCase { } function test_namedColor(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); ctx.reset(); ctx.strokeStyle = "red"; @@ -50,6 +53,7 @@ CanvasTestCase { } function test_colorFromObjectToString(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); ctx.reset(); @@ -68,6 +72,7 @@ CanvasTestCase { } function test_withInvalidColor(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); ctx.reset(); diff --git a/tests/auto/quick/qquickcanvasitem/data/tst_svgpath.qml b/tests/auto/quick/qquickcanvasitem/data/tst_svgpath.qml index 2b39357bed..011fbd497b 100644 --- a/tests/auto/quick/qquickcanvasitem/data/tst_svgpath.qml +++ b/tests/auto/quick/qquickcanvasitem/data/tst_svgpath.qml @@ -6,6 +6,7 @@ CanvasTestCase { function init_data() { return testData("2d"); } function test_svgpath(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); var svgs = [ // Absolute coordinates, explicit commands. diff --git a/tests/auto/quick/qquickcanvasitem/data/tst_text.qml b/tests/auto/quick/qquickcanvasitem/data/tst_text.qml index bfc4067040..f7cd66890b 100644 --- a/tests/auto/quick/qquickcanvasitem/data/tst_text.qml +++ b/tests/auto/quick/qquickcanvasitem/data/tst_text.qml @@ -6,36 +6,42 @@ CanvasTestCase { function init_data() { return testData("2d"); } function test_baseLine(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); ctx.reset(); canvas.destroy() } function test_align(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); ctx.reset(); canvas.destroy() } function test_stroke(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); ctx.reset(); canvas.destroy() } function test_fill(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); ctx.reset(); canvas.destroy() } function test_font(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); ctx.reset(); canvas.destroy() } function test_measure(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); ctx.reset(); canvas.destroy() diff --git a/tests/auto/quick/qquickcanvasitem/data/tst_transform.qml b/tests/auto/quick/qquickcanvasitem/data/tst_transform.qml index b2f5b51fa5..bbfec6a106 100644 --- a/tests/auto/quick/qquickcanvasitem/data/tst_transform.qml +++ b/tests/auto/quick/qquickcanvasitem/data/tst_transform.qml @@ -6,6 +6,7 @@ CanvasTestCase { function init_data() { return testData("2d"); } function test_order(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); ctx.reset(); ctx.fillStyle = '#f00'; @@ -20,6 +21,7 @@ CanvasTestCase { } function test_rotate(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); ctx.reset(); ctx.fillStyle = '#f00'; @@ -90,6 +92,7 @@ CanvasTestCase { } function test_scale(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); ctx.reset(); @@ -182,6 +185,7 @@ CanvasTestCase { } function test_setTransform(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); ctx.reset(); ctx.fillStyle = '#f00'; @@ -325,6 +329,7 @@ CanvasTestCase { } function test_transform(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); ctx.reset(); ctx.fillStyle = '#f00'; @@ -460,6 +465,7 @@ CanvasTestCase { } function test_translate(row) { var canvas = createCanvasObject(row); + tryVerify(function() { return canvas.available; }); var ctx = canvas.getContext('2d'); ctx.reset(); ctx.fillStyle = '#f00'; diff --git a/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp b/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp index a6fb0fcb59..51020672b7 100644 --- a/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp +++ b/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp @@ -3117,7 +3117,12 @@ void tst_qquickflickable::setContentPositionWhileDragging() // QTBUG-104966 } else if (newExtent >= 0) { // ...or reduce the content size be be less than current (contentX, contentY) position // This forces the content item to move. - expectedContentPos = moveDelta; + // contentY: 150 + // 320 - 150 = 170 pixels down to bottom + // Now reduce contentHeight to 200 + // since we are at the bottom, and the flickable is 100 pixels tall, contentY must land + // at newExtent - 100. + if (isHorizontal) { flickable->setContentWidth(newExtent); } else { @@ -3127,6 +3132,7 @@ void tst_qquickflickable::setContentPositionWhileDragging() // QTBUG-104966 // We therefore cannot scroll/flick it further down. Drag it up towards the top instead // (by moving mouse down). pos += moveDelta; + expectedContentPos = unitDelta * (newExtent - (isHorizontal ? flickable->width() : flickable->height())); } QTest::mouseMove(&window, pos); diff --git a/tests/auto/quick/qquickflipable/data/flip-y-axis-flipable.qml b/tests/auto/quick/qquickflipable/data/flip-y-axis-flipable.qml new file mode 100644 index 0000000000..1b6a3f5018 --- /dev/null +++ b/tests/auto/quick/qquickflipable/data/flip-y-axis-flipable.qml @@ -0,0 +1,32 @@ +// Copyright (C) 2023 UnionTech Software Technology Co., Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +import QtQuick + +Flipable { + id: flipable + + property real angle: 0 + width: 3840 // wider than 1024 * 2: part of it goes behind the camera while flipping + height: 2160 + + front: Rectangle { + width: parent.width + height: parent.height + color: "red" + anchors.centerIn: parent + } + back: Rectangle { + color: "yellow" + anchors.centerIn: parent + width: parent.width + height: parent.height + } + transform: Rotation { + id: rotation + origin.x: flipable.width / 2 + origin.y: flipable.height / 2 + axis.x: 0; axis.y: 1; axis.z: 0 + angle: flipable.angle + } +} diff --git a/tests/auto/quick/qquickflipable/tst_qquickflipable.cpp b/tests/auto/quick/qquickflipable/tst_qquickflipable.cpp index 7106041eda..55747a7cdd 100644 --- a/tests/auto/quick/qquickflipable/tst_qquickflipable.cpp +++ b/tests/auto/quick/qquickflipable/tst_qquickflipable.cpp @@ -52,6 +52,9 @@ private slots: void QTBUG_9161_crash(); void QTBUG_8474_qgv_abort(); + void flipRotationAngle_data(); + void flipRotationAngle(); + private: QQmlEngine engine; }; @@ -137,6 +140,31 @@ void tst_qquickflipable::QTBUG_8474_qgv_abort() delete window; } +void tst_qquickflipable::flipRotationAngle_data() +{ + QTest::addColumn<int>("angle"); + QTest::addColumn<QQuickFlipable::Side>("side"); + + QTest::newRow("89") << 89 << QQuickFlipable::Front; + QTest::newRow("91") << 91 << QQuickFlipable::Back; + QTest::newRow("-89") << -89 << QQuickFlipable::Front; + QTest::newRow("-91") << -91 << QQuickFlipable::Back; +} + +void tst_qquickflipable::flipRotationAngle() // QTBUG-75954 +{ + QFETCH(int, angle); + QFETCH(QQuickFlipable::Side, side); + + QQmlEngine engine; + QQmlComponent c(&engine, testFileUrl("flip-y-axis-flipable.qml")); + QQuickFlipable *obj = qobject_cast<QQuickFlipable*>(c.create()); + QVERIFY(obj != nullptr); + obj->setProperty("angle", angle); + QCOMPARE(obj->side(), side); + delete obj; +} + QTEST_MAIN(tst_qquickflipable) #include "tst_qquickflipable.moc" diff --git a/tests/auto/quick/qquicklistview2/data/qtbug86744.qml b/tests/auto/quick/qquicklistview2/data/qtbug86744.qml new file mode 100644 index 0000000000..c69a4f7ec6 --- /dev/null +++ b/tests/auto/quick/qquicklistview2/data/qtbug86744.qml @@ -0,0 +1,25 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +import QtQuick +import QtQml.Models + +Item { + height: 200 + width: 100 + DelegateModel { + id: dm + model: 2 + delegate: Item { + width: 100 + height: 20 + property bool isCurrent: ListView.isCurrentItem + } + } + ListView { + objectName: "listView" + model: dm + currentIndex: 1 + anchors.fill: parent + } +} diff --git a/tests/auto/quick/qquicklistview2/data/qtbug98315.qml b/tests/auto/quick/qquicklistview2/data/qtbug98315.qml new file mode 100644 index 0000000000..bf2ed857b1 --- /dev/null +++ b/tests/auto/quick/qquicklistview2/data/qtbug98315.qml @@ -0,0 +1,98 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +import QtQuick +import QtQml.Models + +Item { + width: 500 + height: 200 + + property list<QtObject> myModel: [ + QtObject { + objectName: "Item 0" + property bool selected: true + }, + QtObject { + objectName: "Item 1" + property bool selected: false + }, + QtObject { + objectName: "Item 2" + property bool selected: false + }, + QtObject { + objectName: "Item 3" + property bool selected: true + }, + QtObject { + objectName: "Item 4" + property bool selected: true + }, + QtObject { + objectName: "Item 5" + property bool selected: true + }, + QtObject { + objectName: "Item 6" + property bool selected: false + } + ] + + ListView { + objectName: "listView" + id: listview + width: 500 + height: 200 + + focus: true + clip: true + spacing: 2 + orientation: ListView.Horizontal + highlightMoveDuration: 300 + highlightMoveVelocity: -1 + preferredHighlightBegin: (500 - 100) / 2 + preferredHighlightEnd: (500 + 100) / 2 + highlightRangeMode: ListView.StrictlyEnforceRange + cacheBuffer: 500 + currentIndex: 1 + + model: DelegateModel { + id: delegateModel + filterOnGroup: "visible" + model: myModel + groups: [ + DelegateModelGroup { + name: "visible" + includeByDefault: true + } + ] + delegate: Rectangle { + id: tile + objectName: model.modelData.objectName + + width: 100 + height: 100 + border.width: 0 + anchors.verticalCenter: parent.verticalCenter + + visible: model.modelData.selected + Component.onCompleted: { + DelegateModel.inPersistedItems = true + DelegateModel.inVisible = Qt.binding(function () { + return model.modelData.selected + }) + } + + property bool isCurrent: ListView.isCurrentItem + color: isCurrent ? "red" : "green" + + Text { + id: valueText + anchors.centerIn: parent + text: model.modelData.objectName + } + } + } + } +} diff --git a/tests/auto/quick/qquicklistview2/tst_qquicklistview2.cpp b/tests/auto/quick/qquicklistview2/tst_qquicklistview2.cpp index 2c701bd5dc..4c6f9c70e2 100644 --- a/tests/auto/quick/qquicklistview2/tst_qquicklistview2.cpp +++ b/tests/auto/quick/qquicklistview2/tst_qquicklistview2.cpp @@ -63,6 +63,8 @@ private slots: void tapDelegateDuringFlicking(); void flickDuringFlicking_data(); void flickDuringFlicking(); + void isCurrentItem_DelegateModel(); + void isCurrentItem_NoRegressionWithDelegateModelGroups(); private: void flickWithTouch(QQuickWindow *window, const QPoint &from, const QPoint &to); @@ -423,6 +425,45 @@ void tst_QQuickListView2::delegateModelRefresh() QTRY_VERIFY(engine.rootObjects().first()->property("done").toBool()); } +void tst_QQuickListView2::isCurrentItem_DelegateModel() +{ + QScopedPointer<QQuickView> window(createView()); + window->setSource(testFileUrl("qtbug86744.qml")); + window->resize(640, 480); + window->show(); + QVERIFY(QTest::qWaitForWindowExposed(window.data())); + QQuickListView* listView = window->rootObject()->findChild<QQuickListView*>("listView"); + QVERIFY(listView); + QVariant value = listView->itemAtIndex(1)->property("isCurrent"); + QVERIFY(value.toBool() == true); +} + +void tst_QQuickListView2::isCurrentItem_NoRegressionWithDelegateModelGroups() +{ + QScopedPointer<QQuickView> window(createView()); + window->setSource(testFileUrl("qtbug98315.qml")); + window->show(); + QVERIFY(QTest::qWaitForWindowExposed(window.data())); + QQuickListView* listView = window->rootObject()->findChild<QQuickListView*>("listView"); + QVERIFY(listView); + + QQuickItem *item3 = listView->itemAtIndex(1); + QVERIFY(item3); + QCOMPARE(item3->property("isCurrent").toBool(), true); + + QObject *item0 = listView->itemAtIndex(0); + QVERIFY(item0); + QCOMPARE(item0->property("isCurrent").toBool(), false); + + // Press left arrow key -> Item 1 should become current, Item 3 should not + // be current anymore. After a previous fix of QTBUG-86744 it was working + // incorrectly - see QTBUG-98315 + QTest::keyPress(window.get(), Qt::Key_Left); + + QTRY_COMPARE(item0->property("isCurrent").toBool(), true); + QCOMPARE(item3->property("isCurrent").toBool(), false); +} + QTEST_MAIN(tst_QQuickListView2) #include "tst_qquicklistview2.moc" diff --git a/tests/auto/quick/qquickloader/tst_qquickloader.cpp b/tests/auto/quick/qquickloader/tst_qquickloader.cpp index 620ada57db..067fa759d8 100644 --- a/tests/auto/quick/qquickloader/tst_qquickloader.cpp +++ b/tests/auto/quick/qquickloader/tst_qquickloader.cpp @@ -133,6 +133,7 @@ private slots: void statusChangeOnlyEmittedOnce(); void setSourceAndCheckStatus(); + void loadComponentWithStates(); void asyncLoaderRace(); void noEngine(); @@ -1518,6 +1519,26 @@ void tst_QQuickLoader::setSourceAndCheckStatus() QCOMPARE(loader->status(), QQuickLoader::Null); } +void tst_QQuickLoader::loadComponentWithStates() +{ + QQmlEngine engine; + QQmlComponent component(&engine); + component.setData(QByteArray("import QtQuick\n" + "Loader {\n" + "id: loader\n" + "property int createdObjCount: 0\n" + "states: [ State { when: true; PropertyChanges { target: loader; sourceComponent: myComp } } ]\n" + "Component { id: myComp; Item { Component.onCompleted: { ++createdObjCount } } }\n" + "}" ) + , dataDirectoryUrl()); + QScopedPointer<QQuickLoader> loader(qobject_cast<QQuickLoader*>(component.create())); + QTest::qWait(200); + QTRY_VERIFY(loader != nullptr); + QVERIFY(loader->item()); + QCOMPARE(static_cast<QQuickItem*>(loader.data())->childItems().size(), 1); + QCOMPARE(loader->property("createdObjCount").toInt(), 1); +} + void tst_QQuickLoader::asyncLoaderRace() { QQmlApplicationEngine engine; diff --git a/tests/auto/quickcontrols2/controls/data/tst_splitview.qml b/tests/auto/quickcontrols2/controls/data/tst_splitview.qml index 6004f9eb44..76174a3c8e 100644 --- a/tests/auto/quickcontrols2/controls/data/tst_splitview.qml +++ b/tests/auto/quickcontrols2/controls/data/tst_splitview.qml @@ -2575,4 +2575,26 @@ TestCase { mouseMove(control, control.width - 100, control.height / 2) verify(!targetHandle.SplitHandle.hovered) } + + function test_touch() { + let control = createTemporaryObject(threeSizedItemsComponent, testCase) + verify(control) + + let touch = touchEvent(control) + + let handles = findHandles(control) + let firstHandle = handles[0] + let handleCenter = control.mapFromItem(firstHandle, firstHandle.width / 2, firstHandle.height / 2) + touch.press(0, control, handleCenter.x, handleCenter.y).commit() + verify(firstHandle.SplitHandle.pressed) + + touch.move(0, control, handleCenter.x + 100, handleCenter.y).commit() + verify(firstHandle.SplitHandle.pressed) + let firstItem = control.itemAt(0) + compare(firstItem.width, 125) + + touch.release(0, control, handleCenter.x + 100, handleCenter.y).commit() + verify(!firstHandle.SplitHandle.pressed) + compare(firstItem.width, 125) + } } diff --git a/tests/auto/quickcontrols2/qquickdrawer/data/itemPartialOverlayModal.qml b/tests/auto/quickcontrols2/qquickdrawer/data/itemPartialOverlayModal.qml new file mode 100644 index 0000000000..23aa4ca3c2 --- /dev/null +++ b/tests/auto/quickcontrols2/qquickdrawer/data/itemPartialOverlayModal.qml @@ -0,0 +1,13 @@ +import QtQuick 2.15 +import QtQuick.Controls 2.15 + +Item { + width: 400; height: 400 + + Drawer { + edge: Qt.LeftEdge + height: 200 + width: 200 + modal: true + } +} diff --git a/tests/auto/quickcontrols2/qquickdrawer/tst_qquickdrawer.cpp b/tests/auto/quickcontrols2/qquickdrawer/tst_qquickdrawer.cpp index 6b6713bdde..2c6d50a591 100644 --- a/tests/auto/quickcontrols2/qquickdrawer/tst_qquickdrawer.cpp +++ b/tests/auto/quickcontrols2/qquickdrawer/tst_qquickdrawer.cpp @@ -46,14 +46,16 @@ #include <QtGui/private/qguiapplication_p.h> #include <QtQuick/private/qquickwindow_p.h> #include <QtQuick/private/qquickflickable_p.h> +#include <QtQuick/qquickview.h> #include <QtQuickTestUtils/private/qmlutils_p.h> #include <QtQuickTestUtils/private/visualtestutils_p.h> #include <QtQuickTemplates2/private/qquickapplicationwindow_p.h> -#include <QtQuickTemplates2/private/qquickoverlay_p.h> +#include <QtQuickTemplates2/private/qquickoverlay_p_p.h> #include <QtQuickTemplates2/private/qquickpopup_p_p.h> #include <QtQuickTemplates2/private/qquickdrawer_p.h> #include <QtQuickTemplates2/private/qquickbutton_p.h> #include <QtQuickTemplates2/private/qquickslider_p.h> +#include <QtQuickTestUtils/private/viewtestutils_p.h> #include <QtQuickControlsTestUtils/private/controlstestutils_p.h> #include <QtQuickControlsTestUtils/private/qtest_quickcontrols_p.h> @@ -121,6 +123,8 @@ private slots: void topEdgeScreenEdge(); + void touchOutsideOverlay(); + private: QScopedPointer<QPointingDevice> touchDevice; }; @@ -1393,6 +1397,41 @@ void tst_QQuickDrawer::topEdgeScreenEdge() QTRY_COMPARE(drawer->position(), 1.0); } +void tst_QQuickDrawer::touchOutsideOverlay() // QTBUG-103811 +{ + QQuickView window; + QVERIFY(QQuickTest::showView(window, testFileUrl("itemPartialOverlayModal.qml"))); + auto *drawer = window.rootObject()->findChild<QQuickDrawer*>(); + QVERIFY(drawer); + QSignalSpy openedSpy(drawer, &QQuickDrawer::opened); + QSignalSpy closedSpy(drawer, &QQuickDrawer::closed); + + drawer->open(); + QVERIFY(openedSpy.size() == 1 || openedSpy.wait()); + QVERIFY(drawer->isOpened()); + + // tap-dance in bottom area beyond the overlay + QPoint p1(100, 250); + QPoint p2(300, 250); + QTest::touchEvent(&window, touchDevice.data()).press(1, p1); + p1 -= QPoint(1, 0); + QTest::touchEvent(&window, touchDevice.data()).move(1, p1).press(2, p2); + p2 -= QPoint(1, 0); + QTest::touchEvent(&window, touchDevice.data()).release(1, p1).move(2, p2); + QTest::touchEvent(&window, touchDevice.data()).press(1, p1).stationary(2); + QTest::touchEvent(&window, touchDevice.data()).release(1, p1).release(2, p2); + QQuickTouchUtils::flush(&window); + + // tap the overlay to try to close the drawer + QVERIFY(drawer->closePolicy().testFlag(QQuickPopup::CloseOnReleaseOutside)); + const QPoint p3(300, 100); + QTest::touchEvent(&window, touchDevice.data()).press(3, p3); + QTest::touchEvent(&window, touchDevice.data()).release(3, p3); + QQuickTouchUtils::flush(&window); + QVERIFY(closedSpy.size() == 1 || closedSpy.wait()); + QCOMPARE(drawer->isOpened(), false); +} + QTEST_QUICKCONTROLS_MAIN(tst_QQuickDrawer) #include "tst_qquickdrawer.moc" diff --git a/tests/auto/quickcontrols2/qquickpopup/data/mirroredCombobox.qml b/tests/auto/quickcontrols2/qquickpopup/data/mirroredCombobox.qml new file mode 100644 index 0000000000..ed48179bce --- /dev/null +++ b/tests/auto/quickcontrols2/qquickpopup/data/mirroredCombobox.qml @@ -0,0 +1,26 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +import QtQuick +import QtQuick.Controls + +Window { + width: 400 + height: 400 + + contentItem.rotation: 180 + + ComboBox { + objectName: "first" + x: 100 + y: 300 // is missing space, needs to unroll in the "mirrored" direction + model: ["First", "Second", "Third", "Fourth", "Fifth"] + } + + ComboBox { + objectName: "second" + x: 200 + y: 100 // has enough space to unroll + model: ["A", "B", "C"] + } +} diff --git a/tests/auto/quickcontrols2/qquickpopup/data/rotatedCombobox.qml b/tests/auto/quickcontrols2/qquickpopup/data/rotatedCombobox.qml new file mode 100644 index 0000000000..df217be4b7 --- /dev/null +++ b/tests/auto/quickcontrols2/qquickpopup/data/rotatedCombobox.qml @@ -0,0 +1,26 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +import QtQuick +import QtQuick.Controls + +Window { + width: 400 + height: 400 + + contentItem.rotation: 90 + + ComboBox { + objectName: "first" + x: 100 + y: 320 // is missing space, needs to unroll in the "mirrored" direction + model: ["First", "Second", "Third", "Fourth", "Fifth"] + } + + ComboBox { + objectName: "second" + x: 200 + y: 100 // has enough space to unroll + model: ["A", "B", "C"] + } +} diff --git a/tests/auto/quickcontrols2/qquickpopup/tst_qquickpopup.cpp b/tests/auto/quickcontrols2/qquickpopup/tst_qquickpopup.cpp index 75d66335f1..d2cfda9375 100644 --- a/tests/auto/quickcontrols2/qquickpopup/tst_qquickpopup.cpp +++ b/tests/auto/quickcontrols2/qquickpopup/tst_qquickpopup.cpp @@ -118,6 +118,8 @@ private slots: void dimmerContainmentMask(); void shrinkPopupThatWasLargerThanWindow_data(); void shrinkPopupThatWasLargerThanWindow(); + void mirroredCombobox(); + void rotatedCombobox(); private: static bool hasWindowActivation(); @@ -1878,6 +1880,155 @@ void tst_QQuickPopup::shrinkPopupThatWasLargerThanWindow() .arg(popup->height()).arg(window->height()))); } +void tst_QQuickPopup::mirroredCombobox() +{ +#ifdef Q_OS_ANDROID + // Android screens might be pretty small, such that additional + // repositioning (apart from the mirroring) will happen to the + // popups and mess up the expected positions below. + QSKIP("Skipping test for Android."); +#endif + QStringList nativeStyles; + nativeStyles.append("macOS"); + nativeStyles.append("iOS"); + nativeStyles.append("Windows"); + if (nativeStyles.contains(QQuickStyle::name())) + QSKIP("Skipping test for native styles: they might rearrange their combobox the way they " + "want."); + + QQuickControlsApplicationHelper helper(this, "mirroredCombobox.qml"); + QVERIFY2(helper.ready, helper.failureMessage()); + + QQuickWindow *window = helper.window; + window->show(); + QVERIFY(QTest::qWaitForWindowExposed(window)); + + { + QQuickComboBox *comboBox = window->findChild<QQuickComboBox *>("first"); + QVERIFY(comboBox); + QQuickPopup *popup = comboBox->popup(); + QVERIFY(popup); + popup->open(); + QTRY_COMPARE(popup->isVisible(), true); + const QPointF popupPos(popup->contentItem()->mapToItem(comboBox->parentItem(), + popup->contentItem()->position())); + const QSizeF popupSize(popup->contentItem()->size()); + + // ignore popup.{top,bottom}Padding() as not included in popup->contentItem()->size() + // some styles prefer to draw the popup "over" (in z-axis direction) the combobox to hide + // the combobox + const bool styleDrawsPopupOverCombobox = + comboBox->position().y() - popupSize.height() + comboBox->size().height() + == popupPos.y(); + // some styles prefer to draw the popup below (in y-axis direction) the combobox + const bool styleDrawsPopupBelowCombobox = + comboBox->position().y() - popupSize.height() + comboBox->topPadding() + == popupPos.y(); + + QVERIFY(styleDrawsPopupOverCombobox || styleDrawsPopupBelowCombobox); + + popup->close(); + } + + { + QQuickComboBox *comboBox = window->findChild<QQuickComboBox *>("second"); + QVERIFY(comboBox); + QQuickPopup *popup = comboBox->popup(); + QVERIFY(popup); + popup->open(); + QTRY_COMPARE(popup->isVisible(), true); + const QPointF popupPos(popup->contentItem()->mapToItem(comboBox->parentItem(), + popup->contentItem()->position())); + + // some styles prefer to draw the popup "over" (in z-axis direction) the combobox to hide + // the combobox + const bool styleDrawsPopupOverCombobox = comboBox->position().y() + comboBox->topPadding() + + popup->topPadding() + popup->bottomPadding() + == popupPos.y(); + // some styles prefer to draw the popup above (in y-axis direction) the combobox + const bool styleDrawsPopupAboveCombobox = + comboBox->position().y() + comboBox->height() - comboBox->topPadding() + == popupPos.y(); + + QVERIFY(styleDrawsPopupOverCombobox || styleDrawsPopupAboveCombobox); + + popup->close(); + } +} + +void tst_QQuickPopup::rotatedCombobox() +{ +#ifdef Q_OS_ANDROID + // Android screens might be pretty small, such that additional + // repositioning (apart from the rotating) will happen to the + // popups and mess up the expected positions below. + QSKIP("Skipping test for Android."); +#endif + QStringList nativeStyles; + nativeStyles.append("macOS"); + nativeStyles.append("iOS"); + nativeStyles.append("Windows"); + if (nativeStyles.contains(QQuickStyle::name())) + QSKIP("Skipping test for native styles: they might rearrange their combobox the way they " + "want."); + + QQuickControlsApplicationHelper helper(this, "rotatedCombobox.qml"); + QVERIFY2(helper.ready, helper.failureMessage()); + + QQuickWindow *window = helper.window; + window->show(); + QVERIFY(QTest::qWaitForWindowExposed(window)); + + { + QQuickComboBox *comboBox = window->findChild<QQuickComboBox *>("first"); + QVERIFY(comboBox); + QQuickPopup *popup = comboBox->popup(); + QVERIFY(popup); + popup->open(); + QTRY_COMPARE(popup->isVisible(), true); + const QPointF popupPos(popup->contentItem()->mapToItem(comboBox->parentItem(), + popup->contentItem()->position())); + const QSizeF popupSize(popup->contentItem()->size()); + + // ignore popup.{left,right}Padding() as not included in popup->contentItem()->size() + // some styles prefer to draw the popup "over" (in z-axis direction) the combobox to hide + // the combobox + const bool styleDrawsPopupOverCombobox = + comboBox->position().x() - popupSize.width() + comboBox->width() == popupPos.x(); + // some styles prefer to draw the popup right (in x-axis direction) of the combobox + const bool styleDrawsPopupBelowCombobox = + comboBox->position().x() - popupSize.width() - comboBox->leftPadding() + == popupPos.x(); + + QVERIFY(styleDrawsPopupOverCombobox || styleDrawsPopupBelowCombobox); + } + + { + QQuickComboBox *comboBox = window->findChild<QQuickComboBox *>("second"); + QVERIFY(comboBox); + QQuickPopup *popup = comboBox->popup(); + QVERIFY(popup); + popup->open(); + QTRY_COMPARE(popup->isVisible(), true); + const QPointF popupPos(popup->contentItem()->mapToItem(comboBox->parentItem(), + popup->contentItem()->position())); + + // some styles prefer to draw the popup "over" (in z-axis direction) the combobox to hide + // the combobox + const bool styleDrawsPopupOverCombobox = comboBox->position().x() + comboBox->leftPadding() + + popup->leftPadding() + popup->rightPadding() + == popupPos.x(); + // some styles prefer to draw the popup left (in y-axis direction) of the combobox + const bool styleDrawsPopupAboveCombobox = + comboBox->position().x() + comboBox->width() - comboBox->leftPadding() + == popupPos.x(); + + QVERIFY(styleDrawsPopupOverCombobox || styleDrawsPopupAboveCombobox); + + popup->close(); + } +} + QTEST_QUICKCONTROLS_MAIN(tst_QQuickPopup) #include "tst_qquickpopup.moc" diff --git a/tests/auto/quickwidgets/qquickwidget/CMakeLists.txt b/tests/auto/quickwidgets/qquickwidget/CMakeLists.txt index 24da087db5..5ce5cf3125 100644 --- a/tests/auto/quickwidgets/qquickwidget/CMakeLists.txt +++ b/tests/auto/quickwidgets/qquickwidget/CMakeLists.txt @@ -19,6 +19,7 @@ qt_internal_add_test(tst_qquickwidget Qt::GuiPrivate Qt::QmlPrivate Qt::QuickPrivate + Qt::QuickTemplates2Private Qt::QuickWidgets Qt::QuickWidgetsPrivate Qt::WidgetsPrivate diff --git a/tests/auto/quickwidgets/qquickwidget/data/button.qml b/tests/auto/quickwidgets/qquickwidget/data/button.qml new file mode 100644 index 0000000000..30698908d7 --- /dev/null +++ b/tests/auto/quickwidgets/qquickwidget/data/button.qml @@ -0,0 +1,27 @@ +import QtQuick +import QtQuick.Controls.Basic + +Item { + width: 100 + height: 100 + visible: true + + property bool wasPressed: false + property bool wasReleased: false + property bool wasClicked: false + + Popup { + closePolicy: Popup.NoAutoClose + visible: true + + Button { + objectName: "button" + text: "TAP ME" + anchors.fill: parent + + onPressed: wasPressed = true + onReleased: wasReleased = true + onClicked: wasClicked = true + } + } +} diff --git a/tests/auto/quickwidgets/qquickwidget/data/mouse.qml b/tests/auto/quickwidgets/qquickwidget/data/mouse.qml index 5d1c6e8443..25a7329a08 100644 --- a/tests/auto/quickwidgets/qquickwidget/data/mouse.qml +++ b/tests/auto/quickwidgets/qquickwidget/data/mouse.qml @@ -7,8 +7,10 @@ Rectangle { property bool wasClicked: false property bool wasDoubleClicked: false property bool wasMoved: false + color: ma.pressed ? "wheat" : "lightsteelblue" MouseArea { + id: ma anchors.fill: parent hoverEnabled: true onClicked: wasClicked = true diff --git a/tests/auto/quickwidgets/qquickwidget/tst_qquickwidget.cpp b/tests/auto/quickwidgets/qquickwidget/tst_qquickwidget.cpp index 1ef70e6515..54673b70ce 100644 --- a/tests/auto/quickwidgets/qquickwidget/tst_qquickwidget.cpp +++ b/tests/auto/quickwidgets/qquickwidget/tst_qquickwidget.cpp @@ -35,6 +35,8 @@ #include <QtQuick/qquickview.h> #include <QtQuick/qquickitem.h> #include <QtQuick/private/qquickitem_p.h> +#include <QtQuick/private/qquickmousearea_p.h> +#include <QtQuickTemplates2/private/qquickbutton_p.h> #include <QtQuickTestUtils/private/qmlutils_p.h> #include <QtGui/QWindow> #include <QtGui/QScreen> @@ -148,6 +150,9 @@ private slots: void mouseEventWindowPos(); void synthMouseFromTouch_data(); void synthMouseFromTouch(); + void touchTapMouseArea(); + void touchTapButton(); + void touchMultipleWidgets(); void tabKey(); void resizeOverlay(); void controls(); @@ -641,6 +646,7 @@ void tst_qquickwidget::synthMouseFromTouch() QTest::touchEvent(&window, device).move(0, p2, &window); QTest::touchEvent(&window, device).release(0, p2, &window); + qCDebug(lcTests) << item->m_touchEvents << item->m_mouseEvents; QCOMPARE(item->m_touchEvents.count(), synthMouse ? 0 : (acceptTouch ? 3 : 1)); QCOMPARE(item->m_mouseEvents.count(), synthMouse ? 3 : 0); QCOMPARE(childView->m_mouseEvents.count(), 0); @@ -648,6 +654,98 @@ void tst_qquickwidget::synthMouseFromTouch() QCOMPARE(ev, Qt::MouseEventSynthesizedByQt); } +void tst_qquickwidget::touchTapMouseArea() +{ + QWidget window; + window.resize(100, 100); + window.setObjectName("window widget"); + window.setAttribute(Qt::WA_AcceptTouchEvents); + QVERIFY(QCoreApplication::testAttribute(Qt::AA_SynthesizeMouseForUnhandledTouchEvents)); + QQuickWidget *quick = new QQuickWidget(&window); + quick->setSource(testFileUrl("mouse.qml")); + quick->move(50, 50); + quick->setObjectName("quick widget"); + window.show(); + QVERIFY(QTest::qWaitForWindowExposed(&window)); + QQuickItem *rootItem = quick->rootObject(); + QVERIFY(rootItem); + QQuickMouseArea *ma = rootItem->findChild<QQuickMouseArea *>(); + QVERIFY(ma); + + QPoint p1 = QPoint(70, 70); + QTest::touchEvent(&window, device).press(0, p1, &window); + QTRY_COMPARE(ma->pressed(), true); + QTest::touchEvent(&window, device).move(0, p1, &window); + QTest::touchEvent(&window, device).release(0, p1, &window); + QTRY_COMPARE(ma->pressed(), false); + QVERIFY(rootItem->property("wasClicked").toBool()); +} + +void tst_qquickwidget::touchTapButton() +{ + QWidget window; + QQuickWidget *quick = new QQuickWidget; + quick->setSource(testFileUrl("button.qml")); + + QHBoxLayout hbox; + hbox.addWidget(quick); + window.setLayout(&hbox); + window.show(); + QVERIFY(QTest::qWaitForWindowExposed(&window)); + + QQuickItem *rootItem = quick->rootObject(); + QVERIFY(rootItem); + QQuickButton *button = rootItem->findChild<QQuickButton *>("button"); + QVERIFY(button); + + const QPoint point = quick->mapTo(&window, button->mapToScene(button->boundingRect().center()).toPoint()); + QTest::touchEvent(&window, device).press(0, point, &window).commit(); + QTRY_VERIFY(rootItem->property("wasPressed").toBool()); + QTest::touchEvent(&window, device).release(0, point, &window).commit(); + QTRY_VERIFY(rootItem->property("wasReleased").toBool()); + QTRY_VERIFY(rootItem->property("wasClicked").toBool()); +} + +void tst_qquickwidget::touchMultipleWidgets() +{ + QWidget window; + QQuickWidget *leftQuick = new QQuickWidget; + leftQuick->setSource(testFileUrl("button.qml")); + QQuickWidget *rightQuick = new QQuickWidget; + rightQuick->setSource(testFileUrl("button.qml")); + + QHBoxLayout hbox; + hbox.addWidget(leftQuick); + hbox.addWidget(rightQuick); + window.setLayout(&hbox); + window.show(); + QVERIFY(QTest::qWaitForWindowExposed(&window)); + + QQuickItem *leftRootItem = leftQuick->rootObject(); + QQuickItem *rightRootItem = rightQuick->rootObject(); + QVERIFY(leftRootItem); + QVERIFY(rightRootItem); + QQuickButton *leftButton = leftRootItem->findChild<QQuickButton *>("button"); + QQuickButton *rightButton = rightRootItem->findChild<QQuickButton *>("button"); + QVERIFY(leftButton); + QVERIFY(rightButton); + + const QPoint leftPoint = leftQuick->mapTo(&window, leftButton->mapToScene( + leftButton->boundingRect().center()).toPoint()); + const QPoint rightPoint = rightQuick->mapTo(&window, rightButton->mapToScene( + rightButton->boundingRect().center()).toPoint()); + QTest::touchEvent(&window, device).press(0, leftPoint, &window).commit(); + QTRY_VERIFY(leftRootItem->property("wasPressed").toBool()); + QTest::touchEvent(&window, device).press(1, rightPoint, &window).commit(); + QTRY_VERIFY(rightRootItem->property("wasPressed").toBool()); + QTest::touchEvent(&window, device).release(1, rightPoint, &window).commit(); + QTRY_VERIFY(rightRootItem->property("wasReleased").toBool()); + QVERIFY(rightRootItem->property("wasClicked").toBool()); + QTest::touchEvent(&window, device).release(0, leftPoint, &window).commit(); + QTRY_VERIFY(leftRootItem->property("wasReleased").toBool()); + QVERIFY(leftRootItem->property("wasClicked").toBool()); +} + void tst_qquickwidget::tabKey() { if (QGuiApplication::styleHints()->tabFocusBehavior() != Qt::TabFocusAllControls) |