diff options
author | Kent Hansen <kent.hansen@nokia.com> | 2012-03-23 14:31:47 +0100 |
---|---|---|
committer | Kent Hansen <kent.hansen@nokia.com> | 2012-03-23 14:31:47 +0100 |
commit | 0655209fdad022bd0f6eb20ce85522cb56506bf0 (patch) | |
tree | cdba0c1590655f5cb75a68cedff74f8a683db3a2 /tests/auto/qml/qqmlecmascript | |
parent | c3babc03c99c6ca5fa210486e133eb456a405bab (diff) | |
parent | 3d8f103c2641f35e7681485102a1b59886db8934 (diff) |
Merge master into api_changes
Conflicts:
src/qml/qml/qqmlboundsignal.cpp
src/qml/qml/qqmlpropertycache.cpp
Change-Id: I5193a193fa301c0b518291645bf626a5fa07118f
Diffstat (limited to 'tests/auto/qml/qqmlecmascript')
16 files changed, 405 insertions, 3 deletions
diff --git a/tests/auto/qml/qqmlecmascript/data/assignDate.2.qml b/tests/auto/qml/qqmlecmascript/data/assignDate.2.qml new file mode 100644 index 0000000000..578701844c --- /dev/null +++ b/tests/auto/qml/qqmlecmascript/data/assignDate.2.qml @@ -0,0 +1,6 @@ +import Qt.test 1.0 + +MyTypeObject { + dateProperty: if(1) new Date("1982-11-25") + dateTimeProperty: if(1) new Date("2009-05-12T13:22:01") +} diff --git a/tests/auto/qml/qqmlecmascript/data/assignDate.3.qml b/tests/auto/qml/qqmlecmascript/data/assignDate.3.qml new file mode 100644 index 0000000000..32b88d0183 --- /dev/null +++ b/tests/auto/qml/qqmlecmascript/data/assignDate.3.qml @@ -0,0 +1,6 @@ +import Qt.test 1.0 + +MyTypeObject { + dateProperty: if(1) "1982-11-25Z" + dateTimeProperty: if(1) "2009-05-12T13:22:01Z" +} diff --git a/tests/auto/qml/qqmlecmascript/data/assignDate.4.qml b/tests/auto/qml/qqmlecmascript/data/assignDate.4.qml new file mode 100644 index 0000000000..16213c691f --- /dev/null +++ b/tests/auto/qml/qqmlecmascript/data/assignDate.4.qml @@ -0,0 +1,6 @@ +import Qt.test 1.0 + +MyTypeObject { + dateProperty: if(1) new Date("1982-11-25Z") + dateTimeProperty: if(1) new Date("2009-05-12T13:22:01Z") +} diff --git a/tests/auto/qml/qqmlecmascript/data/assignDate.5.qml b/tests/auto/qml/qqmlecmascript/data/assignDate.5.qml new file mode 100644 index 0000000000..ff1d85fbef --- /dev/null +++ b/tests/auto/qml/qqmlecmascript/data/assignDate.5.qml @@ -0,0 +1,6 @@ +import Qt.test 1.0 + +MyTypeObject { + dateProperty: if(1) "1982-11-25Z" + dateTimeProperty: if(1) "2009-05-12T15:22:01+02:00" +} diff --git a/tests/auto/qml/qqmlecmascript/data/assignDate.6.qml b/tests/auto/qml/qqmlecmascript/data/assignDate.6.qml new file mode 100644 index 0000000000..859c02f79c --- /dev/null +++ b/tests/auto/qml/qqmlecmascript/data/assignDate.6.qml @@ -0,0 +1,6 @@ +import Qt.test 1.0 + +MyTypeObject { + dateProperty: if(1) new Date("1982-11-25") + dateTimeProperty: if(1) new Date("2009-05-12T15:22:01+02:00") +} diff --git a/tests/auto/qml/qqmlecmascript/data/assignDate.qml b/tests/auto/qml/qqmlecmascript/data/assignDate.qml new file mode 100644 index 0000000000..07a638d50f --- /dev/null +++ b/tests/auto/qml/qqmlecmascript/data/assignDate.qml @@ -0,0 +1,9 @@ +import Qt.test 1.0 +import QtQuick 2.0 + +MyTypeObject { + Component.onCompleted: { + dateProperty = new Date("1982-11-25") + dateTimeProperty = new Date("2009-05-12T13:22:01") + } +} diff --git a/tests/auto/qml/qqmlecmascript/data/componentCreation.qml b/tests/auto/qml/qqmlecmascript/data/componentCreation.qml new file mode 100644 index 0000000000..d21301ea13 --- /dev/null +++ b/tests/auto/qml/qqmlecmascript/data/componentCreation.qml @@ -0,0 +1,52 @@ +import Qt.test 1.0 +import QtQuick 2.0 + +MyTypeObject{ + id: obj + objectName: "obj" + + function url() + { + obj.componentProperty = Qt.createComponent('dynamicCreation.helper.qml'); + } + + function urlMode() + { + obj.componentProperty = Qt.createComponent('dynamicCreation.helper.qml', Component.PreferSynchronous); + } + + function urlParent() + { + obj.componentProperty = Qt.createComponent('dynamicCreation.helper.qml', obj); + } + + function urlNullParent() + { + obj.componentProperty = Qt.createComponent('dynamicCreation.helper.qml', null); + } + + function urlModeParent() + { + obj.componentProperty = Qt.createComponent('dynamicCreation.helper.qml', Component.PreferSynchronous, obj); + } + + function urlModeNullParent() + { + obj.componentProperty = Qt.createComponent('dynamicCreation.helper.qml', Component.PreferSynchronous, null); + } + + function invalidSecondArg() + { + obj.componentProperty = Qt.createComponent('dynamicCreation.helper.qml', 'Bad argument'); + } + + function invalidThirdArg() + { + obj.componentProperty = Qt.createComponent('dynamicCreation.helper.qml', Component.PreferSynchronous, 'Bad argument'); + } + + function invalidMode() + { + obj.componentProperty = Qt.createComponent('dynamicCreation.helper.qml', -666); + } +} diff --git a/tests/auto/qml/qqmlecmascript/data/enums.3.qml b/tests/auto/qml/qqmlecmascript/data/enums.3.qml new file mode 100644 index 0000000000..c77d635a1e --- /dev/null +++ b/tests/auto/qml/qqmlecmascript/data/enums.3.qml @@ -0,0 +1,41 @@ +import QtQuick 2.0 +import Qt.test 1.0 +import Qt.test 1.0 as Namespace + +Item { + // Enums from type + property int a: Item.Center + property int b: Item.Right + + // Enums from Qt + property int c: Qt.blue + property int d: Qt.darkRed + + // Enums from other type + property int e: MyQmlObject.EnumValue3 + property int f: MyQmlObject.EnumValue4 + + // Enums from namespaced other type + property int h: Namespace.MyQmlObject.EnumValue3 + property int i: Namespace.MyQmlObject.EnumValue4 + + // Count the onChanged signals to see whether + // they're assigned as literals or via bindings + property int ac: 0 + property int bc: 0 + property int cc: 0 + property int dc: 0 + property int ec: 0 + property int fc: 0 + property int hc: 0 + property int ic: 0 + + onAChanged: ac++ + onBChanged: bc++ + onCChanged: cc++ + onDChanged: dc++ + onEChanged: ec++ + onFChanged: fc++ + onHChanged: hc++ + onIChanged: ic++ +} diff --git a/tests/auto/qml/qqmlecmascript/data/jsimport/testJsImport.qml b/tests/auto/qml/qqmlecmascript/data/jsimport/testJsImport.qml new file mode 100644 index 0000000000..ae43e90210 --- /dev/null +++ b/tests/auto/qml/qqmlecmascript/data/jsimport/testJsImport.qml @@ -0,0 +1,13 @@ +import QtQuick 2.0 + +import com.nokia.JsModule 1.0 +import com.nokia.JsModule 1.0 as RenamedModule +import "testJsModuleImport.js" as TestJsModuleImport + +QtObject { + id: testQtObject + + property string importedScriptStringValue: ScriptAPI.greeting(); + property string renamedScriptStringValue: RenamedModule.ScriptAPI.greeting(); + property string reimportedScriptStringValue: TestJsModuleImport.importedValue(); +} diff --git a/tests/auto/qml/qqmlecmascript/data/jsimport/testJsModuleImport.js b/tests/auto/qml/qqmlecmascript/data/jsimport/testJsModuleImport.js new file mode 100644 index 0000000000..2d21953d2c --- /dev/null +++ b/tests/auto/qml/qqmlecmascript/data/jsimport/testJsModuleImport.js @@ -0,0 +1,5 @@ +.import com.nokia.JsModule 1.0 as JsModule + +function importedValue() { + return JsModule.ScriptAPI.greeting(); +} diff --git a/tests/auto/qml/qqmlecmascript/data/lib/com/nokia/JsModule/ScriptAPI.js b/tests/auto/qml/qqmlecmascript/data/lib/com/nokia/JsModule/ScriptAPI.js new file mode 100644 index 0000000000..b90033eeb4 --- /dev/null +++ b/tests/auto/qml/qqmlecmascript/data/lib/com/nokia/JsModule/ScriptAPI.js @@ -0,0 +1,5 @@ +var major = 1 +var minor = 0 + +function greeting() { return "Hello" } + diff --git a/tests/auto/qml/qqmlecmascript/data/lib/com/nokia/JsModule/qmldir b/tests/auto/qml/qqmlecmascript/data/lib/com/nokia/JsModule/qmldir new file mode 100644 index 0000000000..c33d1e7a0d --- /dev/null +++ b/tests/auto/qml/qqmlecmascript/data/lib/com/nokia/JsModule/qmldir @@ -0,0 +1 @@ +ScriptAPI 1.0 ScriptAPI.js diff --git a/tests/auto/qml/qqmlecmascript/data/ownershipConsistency.qml b/tests/auto/qml/qqmlecmascript/data/ownershipConsistency.qml new file mode 100644 index 0000000000..7ae099e32e --- /dev/null +++ b/tests/auto/qml/qqmlecmascript/data/ownershipConsistency.qml @@ -0,0 +1,21 @@ +import QtQuick 2.0 + +Item { + Loader { + source: "PropertyVarBaseItem.qml" + onLoaded: item.destroy() + } + Loader { + Component.onCompleted: setSource("PropertyVarBaseItem.qml", { random: "" }) + onLoaded: item.destroy() + } + + Repeater { + model: 1 + Item { Component.onCompleted: destroy() } + } + Repeater { + model: 1 + Item { id: me; Component.onCompleted: { setObject(me); getObject().destroy() } } + } +} diff --git a/tests/auto/qml/qqmlecmascript/data/ownershipRootObject.qml b/tests/auto/qml/qqmlecmascript/data/ownershipRootObject.qml new file mode 100644 index 0000000000..b1b0b72a87 --- /dev/null +++ b/tests/auto/qml/qqmlecmascript/data/ownershipRootObject.qml @@ -0,0 +1,6 @@ +import QtQuick 2.0 + +QtObject { + id: root + Component.onCompleted: { setObject(root); getObject() } +} diff --git a/tests/auto/qml/qqmlecmascript/testtypes.cpp b/tests/auto/qml/qqmlecmascript/testtypes.cpp index 64e91fbc95..a79207a1c8 100644 --- a/tests/auto/qml/qqmlecmascript/testtypes.cpp +++ b/tests/auto/qml/qqmlecmascript/testtypes.cpp @@ -196,7 +196,7 @@ void registerTypes() qmlRegisterModuleApi("Qt.test.qobjectApi",2,0,qobject_api); // register (qobject) module API for a uri which doesn't contain elements, major version set qmlRegisterModuleApi("Qt.test.qobjectApiParented",1,0,qobject_api_engine_parent); // register (parented qobject) module API for a uri which doesn't contain elements - qRegisterMetaType<MyQmlObject::MyType>("MyEnum2"); + qRegisterMetaType<MyQmlObject::MyEnum2>("MyEnum2"); qRegisterMetaType<Qt::MouseButtons>("Qt::MouseButtons"); qmlRegisterType<CircularReferenceObject>("Qt.test", 1, 0, "CircularReferenceObject"); diff --git a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp index 861ff2e641..d932bc6d09 100644 --- a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp +++ b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp @@ -71,6 +71,8 @@ public: private slots: void initTestCase(); void assignBasicTypes(); + void assignDate_data(); + void assignDate(); void idShortcutInvalidates(); void boolPropertiesEvaluateAsBool(); void methods(); @@ -97,6 +99,8 @@ private slots: void importScope(); void signalParameterTypes(); void objectsCompareAsEqual(); + void componentCreation_data(); + void componentCreation(); void dynamicCreation_data(); void dynamicCreation(); void dynamicDestruction(); @@ -129,6 +133,8 @@ private slots: void ownership(); void cppOwnershipReturnValue(); void ownershipCustomReturnValue(); + void ownershipRootObject(); + void ownershipConsistency(); void qlistqobjectMethods(); void strictlyEquals(); void compiled(); @@ -255,6 +261,9 @@ void tst_qqmlecmascript::initTestCase() { QQmlDataTest::initTestCase(); registerTypes(); + + QString dataDir(dataDirectory() + QLatin1Char('/') + QLatin1String("lib")); + engine.addImportPath(dataDir); } void tst_qqmlecmascript::assignBasicTypes() @@ -274,7 +283,7 @@ void tst_qqmlecmascript::assignBasicTypes() QCOMPARE(object->colorProperty(), QColor("red")); QCOMPARE(object->dateProperty(), QDate(1982, 11, 25)); QCOMPARE(object->timeProperty(), QTime(11, 11, 32)); - QCOMPARE(object->dateTimeProperty(), QDateTime(QDate(2009, 5, 12), QTime(13, 22, 1))); + QCOMPARE(object->dateTimeProperty(), QDateTime(QDate(2009, 5, 12), QTime(13, 22, 1), Qt::UTC)); QCOMPARE(object->pointProperty(), QPoint(99,13)); QCOMPARE(object->pointFProperty(), QPointF(-10.1, 12.3)); QCOMPARE(object->sizeProperty(), QSize(99, 13)); @@ -302,7 +311,7 @@ void tst_qqmlecmascript::assignBasicTypes() QCOMPARE(object->colorProperty(), QColor("red")); QCOMPARE(object->dateProperty(), QDate(1982, 11, 25)); QCOMPARE(object->timeProperty(), QTime(11, 11, 32)); - QCOMPARE(object->dateTimeProperty(), QDateTime(QDate(2009, 5, 12), QTime(13, 22, 1))); + QCOMPARE(object->dateTimeProperty(), QDateTime(QDate(2009, 5, 12), QTime(13, 22, 1), Qt::UTC)); QCOMPARE(object->pointProperty(), QPoint(99,13)); QCOMPARE(object->pointFProperty(), QPointF(-10.1, 12.3)); QCOMPARE(object->sizeProperty(), QSize(99, 13)); @@ -317,6 +326,28 @@ void tst_qqmlecmascript::assignBasicTypes() } } +void tst_qqmlecmascript::assignDate_data() +{ + QTest::addColumn<QUrl>("source"); + QTest::newRow("Component.onComplete JS") << testFileUrl("assignDate.qml"); + QTest::newRow("Binding JS") << testFileUrl("assignDate.2.qml"); + QTest::newRow("Binding UTC") << testFileUrl("assignDate.3.qml"); + QTest::newRow("Binding JS UTC") << testFileUrl("assignDate.4.qml"); + QTest::newRow("Binding UTC+2") << testFileUrl("assignDate.5.qml"); + QTest::newRow("Binding JS UTC+2 ") << testFileUrl("assignDate.6.qml"); +} + +void tst_qqmlecmascript::assignDate() +{ + QFETCH(QUrl, source); + QQmlComponent component(&engine, source); + QScopedPointer<QObject> obj(component.create()); + MyTypeObject *object = qobject_cast<MyTypeObject *>(obj.data()); + QVERIFY(object != 0); + QCOMPARE(object->dateProperty(), QDate(1982, 11, 25)); + QCOMPARE(object->dateTimeProperty(), QDateTime(QDate(2009, 5, 12), QTime(13, 22, 1), Qt::UTC)); +} + void tst_qqmlecmascript::idShortcutInvalidates() { { @@ -820,6 +851,34 @@ void tst_qqmlecmascript::enums() delete object; } + // Enums as literals + { + QQmlComponent component(&engine, testFileUrl("enums.3.qml")); + QObject *object = component.create(); + QVERIFY(object != 0); + + // check the values are what we expect + QCOMPARE(object->property("a").toInt(), 4); + QCOMPARE(object->property("b").toInt(), 5); + QCOMPARE(object->property("c").toInt(), 9); + QCOMPARE(object->property("d").toInt(), 13); + QCOMPARE(object->property("e").toInt(), 2); + QCOMPARE(object->property("f").toInt(), 3); + QCOMPARE(object->property("h").toInt(), 2); + QCOMPARE(object->property("i").toInt(), 3); + + // count of change signals + QCOMPARE(object->property("ac").toInt(), 0); + QCOMPARE(object->property("bc").toInt(), 0); + QCOMPARE(object->property("cc").toInt(), 0); + QCOMPARE(object->property("dc").toInt(), 0); + QCOMPARE(object->property("ec").toInt(), 0); + QCOMPARE(object->property("fc").toInt(), 0); + QCOMPARE(object->property("hc").toInt(), 1); // namespace -> binding + QCOMPARE(object->property("ic").toInt(), 1); // namespace -> binding + + delete object; + } } void tst_qqmlecmascript::valueTypeFunctions() @@ -1199,6 +1258,89 @@ void tst_qqmlecmascript::aliasPropertyReset() delete object; } +void tst_qqmlecmascript::componentCreation_data() +{ + QTest::addColumn<QString>("method"); + QTest::addColumn<QString>("creationError"); + QTest::addColumn<QString>("createdParent"); + + QTest::newRow("url") + << "url" + << "" + << ""; + QTest::newRow("urlMode") + << "urlMode" + << "" + << ""; + QTest::newRow("urlParent") + << "urlParent" + << "" + << "obj"; + QTest::newRow("urlNullParent") + << "urlNullParent" + << "" + << "null"; + QTest::newRow("urlModeParent") + << "urlModeParent" + << "" + << "obj"; + QTest::newRow("urlModeNullParent") + << "urlModeNullParent" + << "" + << "null"; + QTest::newRow("invalidSecondArg") + << "invalidSecondArg" + << ":40: Error: Qt.createComponent(): Invalid arguments" + << ""; + QTest::newRow("invalidThirdArg") + << "invalidThirdArg" + << ":45: Error: Qt.createComponent(): Invalid parent object" + << ""; + QTest::newRow("invalidMode") + << "invalidMode" + << ":50: Error: Qt.createComponent(): Invalid arguments" + << ""; +} + +/* +Test using createComponent to dynamically generate a component. +*/ +void tst_qqmlecmascript::componentCreation() +{ + QFETCH(QString, method); + QFETCH(QString, creationError); + QFETCH(QString, createdParent); + + QUrl testUrl(testFileUrl("componentCreation.qml")); + + if (!creationError.isEmpty()) { + QString warning = testUrl.toString() + creationError; + QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData()); + } + + QQmlComponent component(&engine, testUrl); + MyTypeObject *object = qobject_cast<MyTypeObject*>(component.create()); + QVERIFY(object != 0); + + QMetaObject::invokeMethod(object, method.toUtf8()); + QQmlComponent *created = object->componentProperty(); + + if (creationError.isEmpty()) { + QVERIFY(created); + + QObject *expectedParent; + if (createdParent.isEmpty()) { + // For now, the parent should be the engine; this will change for QTBUG-24841 + expectedParent = &engine; + } else if (createdParent == QLatin1String("obj")) { + expectedParent = object; + } else if (createdParent == QLatin1String("null")) { + expectedParent = 0; + } + QCOMPARE(created->parent(), expectedParent); + } +} + void tst_qqmlecmascript::dynamicCreation_data() { QTest::addColumn<QString>("method"); @@ -2800,6 +2942,72 @@ void tst_qqmlecmascript::ownershipCustomReturnValue() QVERIFY(source.value == 0); } +//the return value from getObject will be JS ownership, +//unless strong Cpp ownership has been set +class OwnershipChangingObject : public QObject +{ + Q_OBJECT +public: + OwnershipChangingObject(): object(0) { } + + QPointer<QObject> object; + +public slots: + QObject *getObject() { return object; } + void setObject(QObject *obj) { object = obj; } +}; + +void tst_qqmlecmascript::ownershipRootObject() +{ + OwnershipChangingObject own; + QQmlContext *context = new QQmlContext(engine.rootContext()); + context->setContextObject(&own); + + QQmlComponent component(&engine, testFileUrl("ownershipRootObject.qml")); + QQmlGuard<QObject> object = component.create(context); + QVERIFY(object); + + engine.collectGarbage(); + + QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete); + QCoreApplication::processEvents(); + + QVERIFY(own.object != 0); + + delete context; + delete object; +} + +void tst_qqmlecmascript::ownershipConsistency() +{ + OwnershipChangingObject own; + QQmlContext *context = new QQmlContext(engine.rootContext()); + context->setContextObject(&own); + + QString expectedWarning = testFileUrl("ownershipConsistency.qml").toString() + QLatin1String(":19: Error: Invalid attempt to destroy() an indestructible object"); + QTest::ignoreMessage(QtWarningMsg, qPrintable(expectedWarning)); // we expect a meaningful warning to be printed. + expectedWarning = testFileUrl("ownershipConsistency.qml").toString() + QLatin1String(":15: Error: Invalid attempt to destroy() an indestructible object"); + QTest::ignoreMessage(QtWarningMsg, qPrintable(expectedWarning)); // we expect a meaningful warning to be printed. + expectedWarning = testFileUrl("ownershipConsistency.qml").toString() + QLatin1String(":6: Error: Invalid attempt to destroy() an indestructible object"); + QTest::ignoreMessage(QtWarningMsg, qPrintable(expectedWarning)); // we expect a meaningful warning to be printed. + expectedWarning = testFileUrl("ownershipConsistency.qml").toString() + QLatin1String(":10: Error: Invalid attempt to destroy() an indestructible object"); + QTest::ignoreMessage(QtWarningMsg, qPrintable(expectedWarning)); // we expect a meaningful warning to be printed. + + QQmlComponent component(&engine, testFileUrl("ownershipConsistency.qml")); + QQmlGuard<QObject> object = component.create(context); + QVERIFY(object); + + engine.collectGarbage(); + + QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete); + QCoreApplication::processEvents(); + + QVERIFY(own.object != 0); + + delete context; + delete object; +} + class QListQObjectMethodsObject : public QObject { Q_OBJECT @@ -3299,6 +3507,17 @@ void tst_qqmlecmascript::importScripts_data() << QStringList() << (QStringList() << QLatin1String("testValue")) << (QVariantList() << QVariant(20)); + + QTest::newRow("import module which exports a script") + << testFileUrl("jsimport/testJsImport.qml") + << QString() + << QStringList() + << (QStringList() << QLatin1String("importedScriptStringValue") + << QLatin1String("renamedScriptStringValue") + << QLatin1String("reimportedScriptStringValue")) + << (QVariantList() << QVariant(QString("Hello")) + << QVariant(QString("Hello")) + << QVariant(QString("Hello"))); } void tst_qqmlecmascript::importScripts() |