diff options
Diffstat (limited to 'tests/auto/qml/qqmlcomponent')
20 files changed, 216 insertions, 24 deletions
diff --git a/tests/auto/qml/qqmlcomponent/data/AliasToSubcomponentRequiredBase.qml b/tests/auto/qml/qqmlcomponent/data/AliasToSubcomponentRequiredBase.qml new file mode 100644 index 0000000000..f693cb4c2e --- /dev/null +++ b/tests/auto/qml/qqmlcomponent/data/AliasToSubcomponentRequiredBase.qml @@ -0,0 +1,10 @@ +import QtQuick 2.13 + +Item { + property alias i_alias: sub.i + + Item { + id: sub + required property int i + } +} diff --git a/tests/auto/qml/qqmlcomponent/data/BaseWithRequired.qml b/tests/auto/qml/qqmlcomponent/data/BaseWithRequired.qml new file mode 100644 index 0000000000..0ce61c8d9d --- /dev/null +++ b/tests/auto/qml/qqmlcomponent/data/BaseWithRequired.qml @@ -0,0 +1,6 @@ +import QtQuick 2.14 + +Item { + id: base + required property int i +} diff --git a/tests/auto/qml/qqmlcomponent/data/RequiredDefault.qml b/tests/auto/qml/qqmlcomponent/data/RequiredDefault.qml new file mode 100644 index 0000000000..7e8f225a52 --- /dev/null +++ b/tests/auto/qml/qqmlcomponent/data/RequiredDefault.qml @@ -0,0 +1,5 @@ +import QtQuick 2.15 + +Item { + required default property Text requiredDefault +} diff --git a/tests/auto/qml/qqmlcomponent/data/aliasToSubcomponentNotSet.qml b/tests/auto/qml/qqmlcomponent/data/aliasToSubcomponentNotSet.qml new file mode 100644 index 0000000000..527eb417e5 --- /dev/null +++ b/tests/auto/qml/qqmlcomponent/data/aliasToSubcomponentNotSet.qml @@ -0,0 +1,4 @@ +import QtQuick 2.13 + +AliasToSubcomponentRequiredBase { +} diff --git a/tests/auto/qml/qqmlcomponent/data/createdFromQml.qml b/tests/auto/qml/qqmlcomponent/data/createdFromQml.qml new file mode 100644 index 0000000000..60a2077606 --- /dev/null +++ b/tests/auto/qml/qqmlcomponent/data/createdFromQml.qml @@ -0,0 +1,11 @@ +import QtQuick 2.14 + +Item { + id: root + property Item it + Component.onCompleted: function() { + let component = Qt.createComponent("requiredNotSet.qml", Component.PreferSynchronous, root) + console.assert(component.status == Component.Ready) + it = component.createObject(component, {i: 42}) + } +} diff --git a/tests/auto/qml/qqmlcomponent/data/createdFromQmlFail.qml b/tests/auto/qml/qqmlcomponent/data/createdFromQmlFail.qml new file mode 100644 index 0000000000..e09ddcccc1 --- /dev/null +++ b/tests/auto/qml/qqmlcomponent/data/createdFromQmlFail.qml @@ -0,0 +1,11 @@ +import QtQuick 2.14 + +Item { + id: root + property Item it + Component.onCompleted: function() { + let component = Qt.createComponent("requiredNotSet.qml", Component.PreferSynchronous, root) + console.assert(component.status == Component.Ready) + root.it = component.createObject(component) + } +} diff --git a/tests/auto/qml/qqmlcomponent/data/requiredDefault.1.qml b/tests/auto/qml/qqmlcomponent/data/requiredDefault.1.qml new file mode 100644 index 0000000000..68dff22f33 --- /dev/null +++ b/tests/auto/qml/qqmlcomponent/data/requiredDefault.1.qml @@ -0,0 +1,5 @@ +import QtQuick 2.15 + +RequiredDefault { + Text {text: "Hello, world!"} +} diff --git a/tests/auto/qml/qqmlcomponent/data/requiredDefault.2.qml b/tests/auto/qml/qqmlcomponent/data/requiredDefault.2.qml new file mode 100644 index 0000000000..a6c4e8ea3f --- /dev/null +++ b/tests/auto/qml/qqmlcomponent/data/requiredDefault.2.qml @@ -0,0 +1,3 @@ +import QtQuick 2.15 + +RequiredDefault { } diff --git a/tests/auto/qml/qqmlcomponent/data/requiredDefault.3.qml b/tests/auto/qml/qqmlcomponent/data/requiredDefault.3.qml new file mode 100644 index 0000000000..19b3271858 --- /dev/null +++ b/tests/auto/qml/qqmlcomponent/data/requiredDefault.3.qml @@ -0,0 +1,6 @@ +import QtQuick 2.15 +import qt.test 1.0 + +RequiredDefaultCpp { + Text {text: "Hello, world!"} +} diff --git a/tests/auto/qml/qqmlcomponent/data/requiredDefault.4.qml b/tests/auto/qml/qqmlcomponent/data/requiredDefault.4.qml new file mode 100644 index 0000000000..acd56db328 --- /dev/null +++ b/tests/auto/qml/qqmlcomponent/data/requiredDefault.4.qml @@ -0,0 +1,4 @@ +import QtQuick 2.15 +import qt.test 1.0 + +RequiredDefaultCpp { } diff --git a/tests/auto/qml/qqmlcomponent/data/requiredNotSet.qml b/tests/auto/qml/qqmlcomponent/data/requiredNotSet.qml new file mode 100644 index 0000000000..c0b5d695f1 --- /dev/null +++ b/tests/auto/qml/qqmlcomponent/data/requiredNotSet.qml @@ -0,0 +1,5 @@ +import QtQuick 2.14 + +Item { + required property int i +} diff --git a/tests/auto/qml/qqmlcomponent/data/requiredSetInSameFile.qml b/tests/auto/qml/qqmlcomponent/data/requiredSetInSameFile.qml new file mode 100644 index 0000000000..76dfcd87e5 --- /dev/null +++ b/tests/auto/qml/qqmlcomponent/data/requiredSetInSameFile.qml @@ -0,0 +1,6 @@ +import QtQuick 2.14 + +Item { + required property int i + i: 42 +} diff --git a/tests/auto/qml/qqmlcomponent/data/requiredSetLater.qml b/tests/auto/qml/qqmlcomponent/data/requiredSetLater.qml new file mode 100644 index 0000000000..3b7811e453 --- /dev/null +++ b/tests/auto/qml/qqmlcomponent/data/requiredSetLater.qml @@ -0,0 +1,5 @@ +import QtQuick 2.14 + +BaseWithRequired { + i: 13 +} diff --git a/tests/auto/qml/qqmlcomponent/data/requiredSetViaAliasAfterSameFile.qml b/tests/auto/qml/qqmlcomponent/data/requiredSetViaAliasAfterSameFile.qml new file mode 100644 index 0000000000..163616bc8a --- /dev/null +++ b/tests/auto/qml/qqmlcomponent/data/requiredSetViaAliasAfterSameFile.qml @@ -0,0 +1,8 @@ +import QtQuick 2.14 + +Item { + id: withAlias + j: 42 + required property int i + property alias j: withAlias.i +} diff --git a/tests/auto/qml/qqmlcomponent/data/requiredSetViaAliasBeforeSameFile.qml b/tests/auto/qml/qqmlcomponent/data/requiredSetViaAliasBeforeSameFile.qml new file mode 100644 index 0000000000..e59bccf379 --- /dev/null +++ b/tests/auto/qml/qqmlcomponent/data/requiredSetViaAliasBeforeSameFile.qml @@ -0,0 +1,8 @@ +import QtQuick 2.14 + +Item { + id: withAlias + required property int i + j: 42 + property alias j: withAlias.i +} diff --git a/tests/auto/qml/qqmlcomponent/data/requiredSetViaAliasParentFile.qml b/tests/auto/qml/qqmlcomponent/data/requiredSetViaAliasParentFile.qml new file mode 100644 index 0000000000..0bc2f8a7df --- /dev/null +++ b/tests/auto/qml/qqmlcomponent/data/requiredSetViaAliasParentFile.qml @@ -0,0 +1,7 @@ +import QtQuick 2.14 + +BaseWithRequired { + id: withAlias + property alias j: withAlias.i + j: 42 +} diff --git a/tests/auto/qml/qqmlcomponent/data/requiredSetViaChainedAlias.qml b/tests/auto/qml/qqmlcomponent/data/requiredSetViaChainedAlias.qml new file mode 100644 index 0000000000..45cf02d3d8 --- /dev/null +++ b/tests/auto/qml/qqmlcomponent/data/requiredSetViaChainedAlias.qml @@ -0,0 +1,9 @@ +import QtQml 2.12 + +QtObject { + id: stuff + required property int x; + property alias y: stuff.x + property alias z: stuff.y + z: 5 +} diff --git a/tests/auto/qml/qqmlcomponent/data/setViaAliasToSubcomponent.qml b/tests/auto/qml/qqmlcomponent/data/setViaAliasToSubcomponent.qml new file mode 100644 index 0000000000..2dc182ea82 --- /dev/null +++ b/tests/auto/qml/qqmlcomponent/data/setViaAliasToSubcomponent.qml @@ -0,0 +1,5 @@ +import QtQuick 2.13 + +AliasToSubcomponentRequiredBase { + i_alias: 42 +} diff --git a/tests/auto/qml/qqmlcomponent/data/shadowing.qml b/tests/auto/qml/qqmlcomponent/data/shadowing.qml new file mode 100644 index 0000000000..4d119d8884 --- /dev/null +++ b/tests/auto/qml/qqmlcomponent/data/shadowing.qml @@ -0,0 +1,5 @@ +import QtQuick 2.14 + +BaseWithRequired { + property int i: 13 +} diff --git a/tests/auto/qml/qqmlcomponent/tst_qqmlcomponent.cpp b/tests/auto/qml/qqmlcomponent/tst_qqmlcomponent.cpp index 1d2fa42b75..43cbd93396 100644 --- a/tests/auto/qml/qqmlcomponent/tst_qqmlcomponent.cpp +++ b/tests/auto/qml/qqmlcomponent/tst_qqmlcomponent.cpp @@ -121,6 +121,9 @@ private slots: void relativeUrl_data(); void relativeUrl(); void setDataNoEngineNoSegfault(); + void testRequiredProperties_data(); + void testRequiredProperties(); + void testRequiredPropertiesFromQml(); void testSetInitialProperties(); private: @@ -668,35 +671,96 @@ void tst_qqmlcomponent::setDataNoEngineNoSegfault() QVERIFY(!c); } -void tst_qqmlcomponent::testSetInitialProperties() +class RequiredDefaultCpp : public QObject +{ + Q_OBJECT +public: + Q_PROPERTY(QQuickItem *defaultProperty MEMBER m_defaultProperty NOTIFY defaultPropertyChanged REQUIRED) + Q_SIGNAL void defaultPropertyChanged(); + Q_CLASSINFO("DefaultProperty", "defaultProperty") +private: + QQuickItem *m_defaultProperty = nullptr; +}; + +void tst_qqmlcomponent::testRequiredProperties_data() +{ + qmlRegisterType<RequiredDefaultCpp>("qt.test", 1, 0, "RequiredDefaultCpp"); + QTest::addColumn<QUrl>("testFile"); + QTest::addColumn<bool>("shouldSucceed"); + QTest::addColumn<QString>("errorMsg"); + + QTest::addRow("requiredSetViaChainedAlias") << testFileUrl("requiredSetViaChainedAlias.qml") << true << ""; + QTest::addRow("requiredNotSet") << testFileUrl("requiredNotSet.qml") << false << "Required property i was not initialized"; + QTest::addRow("requiredSetInSameFile") << testFileUrl("requiredSetInSameFile.qml") << true << ""; + QTest::addRow("requiredSetViaAlias1") << testFileUrl("requiredSetViaAliasBeforeSameFile.qml") << true << ""; + QTest::addRow("requiredSetViaAlias2") << testFileUrl("requiredSetViaAliasAfterSameFile.qml") << true << ""; + QTest::addRow("requiredSetViaAlias3") << testFileUrl("requiredSetViaAliasParentFile.qml") << true << ""; + QTest::addRow("shadowing") << testFileUrl("shadowing.qml") << false << "Required property i was not initialized"; + QTest::addRow("setLater") << testFileUrl("requiredSetLater.qml") << true << ""; + QTest::addRow("setViaAliasToSubcomponent") << testFileUrl("setViaAliasToSubcomponent.qml") << true << ""; + QTest::addRow("aliasToSubcomponentNotSet") << testFileUrl("aliasToSubcomponentNotSet.qml") << false << "It can be set via the alias property i_alias"; + QTest::addRow("required default set") << testFileUrl("requiredDefault.1.qml") << true << ""; + QTest::addRow("required default not set") << testFileUrl("requiredDefault.2.qml") << false << "Required property requiredDefault was not initialized"; + QTest::addRow("required default set (C++)") << testFileUrl("requiredDefault.3.qml") << true << ""; + QTest::addRow("required default not set (C++)") << testFileUrl("requiredDefault.4.qml") << false << "Required property defaultProperty was not initialized"; +} + + +void tst_qqmlcomponent::testRequiredProperties() +{ + QQmlEngine eng; + using QScopedObjPointer = QScopedPointer<QObject>; + QFETCH(QUrl, testFile); + QFETCH(bool, shouldSucceed); + QQmlComponent comp(&eng); + comp.loadUrl(testFile); + QScopedObjPointer obj {comp.create()}; + if (shouldSucceed) + QVERIFY(obj); + else { + QVERIFY(!obj); + QFETCH(QString, errorMsg); + QVERIFY(comp.errorString().contains(errorMsg)); + } +} + +void tst_qqmlcomponent::testRequiredPropertiesFromQml() { QQmlEngine eng; { - // JSON based initialization QQmlComponent comp(&eng); - comp.loadUrl(testFileUrl("allJSONTypes.qml")); - QScopedPointer<QObject> obj { comp.beginCreate(eng.rootContext()) }; + comp.loadUrl(testFileUrl("createdFromQml.qml")); + QScopedPointer<QObject> obj { comp.create() }; QVERIFY(obj); - comp.setInitialProperties(obj.get(), QVariantMap { - {QLatin1String("i"), 42}, - {QLatin1String("b"), true}, - {QLatin1String("d"), 3.1416}, - {QLatin1String("s"), QLatin1String("hello world")}, - {QLatin1String("nothing"), QVariant::fromValue(nullptr)} - }); - comp.completeCreate(); - if (!comp.errors().empty()) - qDebug() << comp.errorString() << comp.errors(); - QVERIFY(comp.errors().empty()); - QCOMPARE(obj->property("i"), 42); - QCOMPARE(obj->property("b"), true); - QCOMPARE(obj->property("d"), 3.1416); - QCOMPARE(obj->property("s"), QLatin1String("hello world")); - QCOMPARE(obj->property("nothing"), QVariant::fromValue(nullptr)); + auto root = qvariant_cast<QQuickItem*>(obj->property("it")); + QVERIFY(root); + QCOMPARE(root->property("i").toInt(), 42); } { - // QVariant + QTest::ignoreMessage(QtMsgType::QtWarningMsg, QRegularExpression(".*requiredNotSet.qml:4:5: Required property i was not initialized")); QQmlComponent comp(&eng); + comp.loadUrl(testFileUrl("createdFromQmlFail.qml")); + QScopedPointer<QObject> obj { comp.create() }; + QVERIFY(obj); + QCOMPARE(qvariant_cast<QQuickItem *>(obj->property("it")), nullptr); + } +} + +struct ComponentWithPublicSetInitial : QQmlComponent +{ + using QQmlComponent::QQmlComponent; + void setInitialProperties(QObject *o, QVariantMap map) + { + QQmlComponent::setInitialProperties(o, map); + } +}; + +void tst_qqmlcomponent::testSetInitialProperties() +{ + QQmlEngine eng; + { + // QVariant + ComponentWithPublicSetInitial comp(&eng); comp.loadUrl(testFileUrl("variantBasedInitialization.qml")); QScopedPointer<QObject> obj { comp.beginCreate(eng.rootContext()) }; QVERIFY(obj); @@ -728,8 +792,6 @@ void tst_qqmlcomponent::testSetInitialProperties() }); #undef ASJSON comp.completeCreate(); - if (!comp.errors().empty()) - qDebug() << comp.errorString() << comp.errors(); QVERIFY(comp.errors().empty()); QCOMPARE(obj->property("i"), 42); QCOMPARE(obj->property("b"), true); @@ -751,13 +813,20 @@ void tst_qqmlcomponent::testSetInitialProperties() } { + // createWithInitialProperties convenience function + QQmlComponent comp(&eng); + comp.loadUrl(testFileUrl("requiredNotSet.qml")); + QScopedPointer<QObject> obj {comp.createWithInitialProperties( QVariantMap { {QLatin1String("i"), QJsonValue{42}} })}; + QVERIFY(obj); + QCOMPARE(obj->property("i"), 42); + } + { // createWithInitialProperties: setting a nonexistent property QQmlComponent comp(&eng); comp.loadUrl(testFileUrl("allJSONTypes.qml")); QScopedPointer<QObject> obj { comp.createWithInitialProperties(QVariantMap { {"notThePropertiesYoureLookingFor", 42} }) }; - qDebug() << comp.errorString(); QVERIFY(obj); QVERIFY(comp.errorString().contains("Could not set property notThePropertiesYoureLookingFor")); } |