aboutsummaryrefslogtreecommitdiffstats
path: root/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp')
-rw-r--r--tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp457
1 files changed, 453 insertions, 4 deletions
diff --git a/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp b/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp
index 8df18738ae..cabaddeeb7 100644
--- a/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp
+++ b/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp
@@ -144,6 +144,10 @@ private slots:
void numberAssignment();
void propertySplicing();
void signalWithUnknownTypes();
+ void moduleApi();
+ void importScripts();
+ void scarceResources();
+ void propertyChangeSlots();
void bug1();
void bug2();
@@ -176,6 +180,7 @@ private slots:
void aliasBindingsOverrideTarget();
void aliasWritesOverrideBindings();
void pushCleanContext();
+ void realToInt();
void include();
@@ -260,6 +265,7 @@ void tst_qdeclarativeecmascript::idShortcutInvalidates()
QVERIFY(object->objectProperty() != 0);
delete object->objectProperty();
QVERIFY(object->objectProperty() == 0);
+ delete object;
}
{
@@ -269,6 +275,7 @@ void tst_qdeclarativeecmascript::idShortcutInvalidates()
QVERIFY(object->objectProperty() != 0);
delete object->objectProperty();
QVERIFY(object->objectProperty() == 0);
+ delete object;
}
}
@@ -279,12 +286,14 @@ void tst_qdeclarativeecmascript::boolPropertiesEvaluateAsBool()
MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
QVERIFY(object != 0);
QCOMPARE(object->stringProperty(), QLatin1String("pass"));
+ delete object;
}
{
QDeclarativeComponent component(&engine, TEST_FILE("boolPropertiesEvaluateAsBool.2.qml"));
MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
QVERIFY(object != 0);
QCOMPARE(object->stringProperty(), QLatin1String("pass"));
+ delete object;
}
}
@@ -297,6 +306,7 @@ void tst_qdeclarativeecmascript::signalAssignment()
QCOMPARE(object->string(), QString());
emit object->basicSignal();
QCOMPARE(object->string(), QString("pass"));
+ delete object;
}
{
@@ -306,6 +316,7 @@ void tst_qdeclarativeecmascript::signalAssignment()
QCOMPARE(object->string(), QString());
emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
QCOMPARE(object->string(), QString("pass 19 Hello world! 10.25 3 2"));
+ delete object;
}
}
@@ -320,6 +331,7 @@ void tst_qdeclarativeecmascript::methods()
emit object->basicSignal();
QCOMPARE(object->methodCalled(), true);
QCOMPARE(object->methodIntCalled(), false);
+ delete object;
}
{
@@ -331,6 +343,7 @@ void tst_qdeclarativeecmascript::methods()
emit object->basicSignal();
QCOMPARE(object->methodCalled(), false);
QCOMPARE(object->methodIntCalled(), true);
+ delete object;
}
{
@@ -338,6 +351,7 @@ void tst_qdeclarativeecmascript::methods()
QObject *object = component.create();
QVERIFY(object != 0);
QCOMPARE(object->property("test").toInt(), 19);
+ delete object;
}
{
@@ -347,6 +361,7 @@ void tst_qdeclarativeecmascript::methods()
QCOMPARE(object->property("test").toInt(), 19);
QCOMPARE(object->property("test2").toInt(), 17);
QCOMPARE(object->property("test3").toInt(), 16);
+ delete object;
}
{
@@ -354,6 +369,7 @@ void tst_qdeclarativeecmascript::methods()
QObject *object = component.create();
QVERIFY(object != 0);
QCOMPARE(object->property("test").toInt(), 9);
+ delete object;
}
}
@@ -364,6 +380,7 @@ void tst_qdeclarativeecmascript::bindingLoop()
QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
QObject *object = component.create();
QVERIFY(object != 0);
+ delete object;
}
void tst_qdeclarativeecmascript::basicExpressions_data()
@@ -508,6 +525,7 @@ void tst_qdeclarativeecmascript::contextPropertiesTriggerReeval()
QCOMPARE(expr.evaluate(), QVariant::fromValue((QObject *)object3));
}
+ delete object3;
}
void tst_qdeclarativeecmascript::objectPropertiesTriggerReeval()
@@ -582,6 +600,8 @@ void tst_qdeclarativeecmascript::deferredProperties()
QCOMPARE(qmlObject->value(), 10);
object->setValue(19);
QCOMPARE(qmlObject->value(), 19);
+
+ delete object;
}
// Check errors on deferred properties are correctly emitted
@@ -625,6 +645,7 @@ void tst_qdeclarativeecmascript::extensionObjects()
QCOMPARE(nested->coreProperty(), 11);
QCOMPARE(nested->baseProperty(), 92);
+ delete object;
}
void tst_qdeclarativeecmascript::overrideExtensionProperties()
@@ -635,6 +656,8 @@ void tst_qdeclarativeecmascript::overrideExtensionProperties()
QVERIFY(object != 0);
QVERIFY(object->secondProperty() != 0);
QVERIFY(object->firstProperty() == 0);
+
+ delete object;
}
void tst_qdeclarativeecmascript::attachedProperties()
@@ -647,6 +670,7 @@ void tst_qdeclarativeecmascript::attachedProperties()
QCOMPARE(object->property("b").toInt(), 19);
QCOMPARE(object->property("c").toInt(), 19);
QCOMPARE(object->property("d").toInt(), 19);
+ delete object;
}
{
@@ -671,6 +695,7 @@ void tst_qdeclarativeecmascript::attachedProperties()
QVERIFY(attached != 0);
QCOMPARE(attached->value2(), 9);
+ delete object;
}
}
@@ -692,6 +717,8 @@ void tst_qdeclarativeecmascript::enums()
QCOMPARE(object->property("h").toInt(), 3);
QCOMPARE(object->property("i").toInt(), 19);
QCOMPARE(object->property("j").toInt(), 19);
+
+ delete object;
}
// Non-existent enums
{
@@ -706,6 +733,8 @@ void tst_qdeclarativeecmascript::enums()
QVERIFY(object != 0);
QCOMPARE(object->property("a").toInt(), 0);
QCOMPARE(object->property("b").toInt(), 0);
+
+ delete object;
}
}
@@ -716,6 +745,8 @@ void tst_qdeclarativeecmascript::valueTypeFunctions()
QVERIFY(obj != 0);
QCOMPARE(obj->rectProperty(), QRect(0,0,100,100));
QCOMPARE(obj->rectFProperty(), QRectF(0,0.5,100,99.5));
+
+ delete obj;
}
/*
@@ -739,6 +770,8 @@ void tst_qdeclarativeecmascript::constantsOverrideBindings()
QCOMPARE(object->property("c2").toInt(), 13);
object->setProperty("c1", QVariant(8));
QCOMPARE(object->property("c2").toInt(), 13);
+
+ delete object;
}
// During construction
@@ -752,6 +785,8 @@ void tst_qdeclarativeecmascript::constantsOverrideBindings()
object->setProperty("c1", QVariant(9));
QCOMPARE(object->property("c1").toInt(), 9);
QCOMPARE(object->property("c2").toInt(), 10);
+
+ delete object;
}
#if 0
@@ -770,6 +805,8 @@ void tst_qdeclarativeecmascript::constantsOverrideBindings()
object->setProperty("c1", QVariant(7));
QCOMPARE(object->property("c1").toInt(), 7);
QCOMPARE(object->property("c2").toInt(), 13);
+
+ delete object;
}
#endif
@@ -784,6 +821,8 @@ void tst_qdeclarativeecmascript::constantsOverrideBindings()
object->setProperty("c1", QVariant(9));
QCOMPARE(object->property("c1").toInt(), 9);
QCOMPARE(object->property("c3").toInt(), 10);
+
+ delete object;
}
}
@@ -811,6 +850,8 @@ void tst_qdeclarativeecmascript::outerBindingOverridesInnerBinding()
QCOMPARE(object->property("c1").toInt(), 9);
QCOMPARE(object->property("c2").toInt(), 8);
QCOMPARE(object->property("c3").toInt(), 8);
+
+ delete object;
}
/*
@@ -827,6 +868,8 @@ void tst_qdeclarativeecmascript::nonExistentAttachedObject()
QObject *object = component.create();
QVERIFY(object != 0);
+
+ delete object;
}
void tst_qdeclarativeecmascript::scope()
@@ -846,6 +889,8 @@ void tst_qdeclarativeecmascript::scope()
QCOMPARE(object->property("test8").toInt(), 2);
QCOMPARE(object->property("test9").toInt(), 1);
QCOMPARE(object->property("test10").toInt(), 3);
+
+ delete object;
}
{
@@ -859,6 +904,8 @@ void tst_qdeclarativeecmascript::scope()
QCOMPARE(object->property("test4").toInt(), 14);
QCOMPARE(object->property("test5").toInt(), 24);
QCOMPARE(object->property("test6").toInt(), 24);
+
+ delete object;
}
{
@@ -869,6 +916,8 @@ void tst_qdeclarativeecmascript::scope()
QCOMPARE(object->property("test1").toBool(), true);
QCOMPARE(object->property("test2").toBool(), true);
QCOMPARE(object->property("test3").toBool(), true);
+
+ delete object;
}
// Signal argument scope
@@ -887,6 +936,27 @@ void tst_qdeclarativeecmascript::scope()
delete object;
}
+
+ {
+ QDeclarativeComponent component(&engine, TEST_FILE("scope.5.qml"));
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+
+ QCOMPARE(object->property("test1").toBool(), true);
+ QCOMPARE(object->property("test2").toBool(), true);
+
+ delete object;
+ }
+
+ {
+ QDeclarativeComponent component(&engine, TEST_FILE("scope.6.qml"));
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+
+ QCOMPARE(object->property("test").toBool(), true);
+
+ delete object;
+ }
}
/*
@@ -907,6 +977,8 @@ void tst_qdeclarativeecmascript::signalParameterTypes()
QVERIFY(object->property("variantProperty") == QVariant::fromValue(QColor(255, 0, 255, 255)));
QVERIFY(object->property("enumProperty") == MyQmlObject::EnumValue3);
QVERIFY(object->property("qtEnumProperty") == Qt::LeftButton);
+
+ delete object;
}
/*
@@ -923,6 +995,8 @@ void tst_qdeclarativeecmascript::objectsCompareAsEqual()
QCOMPARE(object->property("test3").toBool(), true);
QCOMPARE(object->property("test4").toBool(), true);
QCOMPARE(object->property("test5").toBool(), true);
+
+ delete object;
}
/*
@@ -943,6 +1017,8 @@ void tst_qdeclarativeecmascript::aliasPropertyAndBinding()
QCOMPARE(object->property("c2").toInt(), 19);
QCOMPARE(object->property("c3").toInt(), 19);
+
+ delete object;
}
void tst_qdeclarativeecmascript::dynamicCreation_data()
@@ -972,6 +1048,8 @@ void tst_qdeclarativeecmascript::dynamicCreation()
QObject *created = object->objectProperty();
QVERIFY(created);
QCOMPARE(created->objectName(), createdName);
+
+ delete object;
}
/*
@@ -1020,6 +1098,8 @@ void tst_qdeclarativeecmascript::objectToString()
QMetaObject::invokeMethod(object, "testToString");
QVERIFY(object->stringProperty().startsWith("MyQmlObject_QML_"));
QVERIFY(object->stringProperty().endsWith(", \"objName\")"));
+
+ delete object;
}
/*
@@ -1034,6 +1114,7 @@ void tst_qdeclarativeecmascript::selfDeletingBinding()
QObject *object = component.create();
QVERIFY(object != 0);
object->setProperty("triggerDelete", true);
+ delete object;
}
{
@@ -1041,6 +1122,7 @@ void tst_qdeclarativeecmascript::selfDeletingBinding()
QObject *object = component.create();
QVERIFY(object != 0);
object->setProperty("triggerDelete", true);
+ delete object;
}
}
@@ -1056,6 +1138,7 @@ void tst_qdeclarativeecmascript::extendedObjectPropertyLookup()
QDeclarativeComponent component(&engine, TEST_FILE("extendedObjectPropertyLookup.qml"));
QObject *object = component.create();
QVERIFY(object != 0);
+ delete object;
}
/*
@@ -1091,6 +1174,8 @@ void tst_qdeclarativeecmascript::scriptErrors()
QTest::ignoreMessage(QtWarningMsg, warning8.toLatin1().constData());
emit object->thirdBasicSignal();
+
+ delete object;
}
/*
@@ -1108,6 +1193,16 @@ void tst_qdeclarativeecmascript::functionErrors()
QObject *object = component.create();
QVERIFY(object != 0);
delete object;
+
+ // test that if an exception occurs while invoking js function from cpp, it is reported as expected.
+ QDeclarativeComponent componentTwo(&engine, TEST_FILE("scarceresources/scarceResourceFunctionFail.qml"));
+ url = componentTwo.url().toString();
+ object = componentTwo.create();
+ QVERIFY(object != 0);
+ warning = url + QLatin1String(":16: TypeError: Result of expression 'scarceResourceProvider.scarceResource' [[object Object]] is not a function.");
+ QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData()); // we expect a meaningful warning to be printed.
+ QMetaObject::invokeMethod(object, "retrieveScarceResource");
+ delete object;
}
/*
@@ -1156,6 +1251,8 @@ void tst_qdeclarativeecmascript::signalTriggeredBindings()
QCOMPARE(object->property("base").toReal(), 400.);
QCOMPARE(object->property("test1").toReal(), 400.);
QCOMPARE(object->property("test2").toReal(), 400.);
+
+ delete object;
}
/*
@@ -1171,6 +1268,8 @@ void tst_qdeclarativeecmascript::listProperties()
QCOMPARE(object->property("test2").toInt(), 2);
QCOMPARE(object->property("test3").toBool(), true);
QCOMPARE(object->property("test4").toBool(), true);
+
+ delete object;
}
void tst_qdeclarativeecmascript::exceptionClearsOnReeval()
@@ -1192,6 +1291,8 @@ void tst_qdeclarativeecmascript::exceptionClearsOnReeval()
object->setObjectProperty(&object2);
QCOMPARE(object->property("test").toBool(), true);
+
+ delete object;
}
void tst_qdeclarativeecmascript::exceptionSlotProducesWarning()
@@ -1204,6 +1305,7 @@ void tst_qdeclarativeecmascript::exceptionSlotProducesWarning()
QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
QVERIFY(object != 0);
+ delete object;
}
void tst_qdeclarativeecmascript::exceptionBindingProducesWarning()
@@ -1216,6 +1318,7 @@ void tst_qdeclarativeecmascript::exceptionBindingProducesWarning()
QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
QVERIFY(object != 0);
+ delete object;
}
static int transientErrorsMsgCount = 0;
@@ -1239,6 +1342,8 @@ void tst_qdeclarativeecmascript::transientErrors()
qInstallMsgHandler(old);
QCOMPARE(transientErrorsMsgCount, 0);
+
+ delete object;
}
// One binding erroring multiple times, but then resolving
@@ -1254,6 +1359,8 @@ void tst_qdeclarativeecmascript::transientErrors()
qInstallMsgHandler(old);
QCOMPARE(transientErrorsMsgCount, 0);
+
+ delete object;
}
}
@@ -1369,6 +1476,8 @@ void tst_qdeclarativeecmascript::dynamicCreationCrash()
QMetaObject::invokeMethod(object, "dontCrash");
QObject *created = object->objectProperty();
QVERIFY(created == 0);
+
+ delete object;
}
//QTBUG-9367
@@ -1378,6 +1487,7 @@ void tst_qdeclarativeecmascript::regExpBug()
MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
QVERIFY(object != 0);
QCOMPARE(object->regExp().pattern(), QLatin1String("[a-zA-z]"));
+ delete object;
}
void tst_qdeclarativeecmascript::callQtInvokables()
@@ -2151,6 +2261,8 @@ void tst_qdeclarativeecmascript::ownership()
delete object;
}
+
+ delete context;
}
class CppOwnershipReturnValue : public QObject
@@ -2161,16 +2273,12 @@ public:
~CppOwnershipReturnValue() { delete value; }
Q_INVOKABLE QObject *create() {
- Q_ASSERT(value == 0);
-
value = new QObject;
QDeclarativeEngine::setObjectOwnership(value, QDeclarativeEngine::CppOwnership);
return value;
}
Q_INVOKABLE MyQmlObject *createQmlObject() {
- Q_ASSERT(value == 0);
-
MyQmlObject *rv = new MyQmlObject;
value = rv;
return rv;
@@ -2269,6 +2377,7 @@ void tst_qdeclarativeecmascript::qlistqobjectMethods()
QCOMPARE(object->property("test2").toBool(), true);
delete object;
+ delete context;
}
// QTBUG-9205
@@ -2389,6 +2498,328 @@ void tst_qdeclarativeecmascript::signalWithUnknownTypes()
delete object;
}
+void tst_qdeclarativeecmascript::moduleApi()
+{
+ QDeclarativeComponent component(&engine, TEST_FILE("moduleApi.qml"));
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+ QCOMPARE(object->property("existingUriTest").toInt(), 20);
+ QCOMPARE(object->property("scriptTest").toInt(), 13);
+ QCOMPARE(object->property("qobjectTest").toInt(), 20);
+ QCOMPARE(object->property("qobjectMethodTest").toInt(), 1); // first call of method, so count = 1.
+ QCOMPARE(object->property("qobjectMinorVersionTest").toInt(), 20);
+ QCOMPARE(object->property("qobjectMajorVersionTest").toInt(), 20);
+ QCOMPARE(object->property("qobjectParentedTest").toInt(), 26);
+ delete object;
+
+ // test that caching of module apis works correctly.
+ QDeclarativeComponent componentTwo(&engine, TEST_FILE("moduleApiCaching.qml"));
+ object = componentTwo.create();
+ QVERIFY(object != 0);
+ QCOMPARE(object->property("existingUriTest").toInt(), 20);
+ QCOMPARE(object->property("scriptTest").toInt(), 13); // shouldn't have incremented.
+ QCOMPARE(object->property("qobjectParentedTest").toInt(), 26); // shouldn't have incremented.
+ delete object;
+
+ // test that writing to a property of module apis works correctly.
+ QDeclarativeComponent componentThree(&engine, TEST_FILE("moduleApiWriting.qml"));
+ QString expectedWarning = QLatin1String("file://") + TEST_FILE("moduleApiWriting.qml").toLocalFile() + QLatin1String(":15: Error: Cannot assign to read-only property \"qobjectTestProperty\"");
+ QTest::ignoreMessage(QtWarningMsg, expectedWarning.toAscii().constData());
+ object = componentThree.create();
+ QVERIFY(object != 0);
+ QCOMPARE(object->property("readOnlyProperty").toInt(), 20);
+ QCOMPARE(object->property("writableProperty").toInt(), 50);
+ QVERIFY(object->setProperty("firstProperty", QVariant(30))); // shouldn't affect value of readOnlyProperty
+ QVERIFY(object->setProperty("writableProperty", QVariant(30))); // SHOULD affect value of writableProperty
+ QCOMPARE(object->property("readOnlyProperty").toInt(), 20);
+ QCOMPARE(object->property("writableProperty").toInt(), 30);
+ delete object;
+
+ QDeclarativeComponent failOne(&engine, TEST_FILE("moduleApiMajorVersionFail.qml"));
+ QTest::ignoreMessage(QtWarningMsg, "QDeclarativeComponent: Component is not ready");
+ object = failOne.create();
+ QVERIFY(object == 0); // should have failed: invalid major version
+
+ QDeclarativeComponent failTwo(&engine, TEST_FILE("moduleApiMinorVersionFail.qml"));
+ QTest::ignoreMessage(QtWarningMsg, "QDeclarativeComponent: Component is not ready");
+ object = failTwo.create();
+ QVERIFY(object == 0); // should have failed: invalid minor version
+}
+
+void tst_qdeclarativeecmascript::importScripts()
+{
+ QObject *object = 0;
+
+ // first, ensure that the required behaviour works.
+ QDeclarativeComponent component(&engine, TEST_FILE("jsimport/testImport.qml"));
+ object = component.create();
+ QVERIFY(object != 0);
+ QCOMPARE(object->property("importedScriptStringValue"), QVariant(QString(QLatin1String("Hello, World!"))));
+ QCOMPARE(object->property("importedScriptFunctionValue"), QVariant(20));
+ QCOMPARE(object->property("importedModuleAttachedPropertyValue"), QVariant(19));
+ QCOMPARE(object->property("importedModuleEnumValue"), QVariant(2));
+ delete object;
+
+ QDeclarativeComponent componentTwo(&engine, TEST_FILE("jsimport/testImportScoping.qml"));
+ object = componentTwo.create();
+ QVERIFY(object != 0);
+ QCOMPARE(object->property("componentError"), QVariant(5));
+ delete object;
+
+ // then, ensure that unintended behaviour does not work.
+ QDeclarativeComponent failOneComponent(&engine, TEST_FILE("jsimportfail/failOne.qml"));
+ QString expectedWarning = QLatin1String("file://") + TEST_FILE("jsimportfail/failOne.qml").toLocalFile() + QLatin1String(":6: TypeError: Result of expression 'TestScriptImport.ImportOneJs' [undefined] is not an object.");
+ QTest::ignoreMessage(QtWarningMsg, expectedWarning.toAscii().constData());
+ object = failOneComponent.create();
+ QVERIFY(object != 0);
+ QVERIFY(object->property("importScriptFunctionValue").toString().isEmpty());
+ delete object;
+ QDeclarativeComponent failTwoComponent(&engine, TEST_FILE("jsimportfail/failTwo.qml"));
+ expectedWarning = QLatin1String("file://") + TEST_FILE("jsimportfail/failTwo.qml").toLocalFile() + QLatin1String(":6: ReferenceError: Can't find variable: ImportOneJs");
+ QTest::ignoreMessage(QtWarningMsg, expectedWarning.toAscii().constData());
+ object = failTwoComponent.create();
+ QVERIFY(object != 0);
+ QVERIFY(object->property("importScriptFunctionValue").toString().isEmpty());
+ delete object;
+ QDeclarativeComponent failThreeComponent(&engine, TEST_FILE("jsimportfail/failThree.qml"));
+ expectedWarning = QLatin1String("file://") + TEST_FILE("jsimportfail/failThree.qml").toLocalFile() + QLatin1String(":7: TypeError: Result of expression 'testQtObject.TestModuleImport.JsQtTest' [undefined] is not an object.");
+ QTest::ignoreMessage(QtWarningMsg, expectedWarning.toAscii().constData());
+ object = failThreeComponent.create();
+ QVERIFY(object != 0);
+ QCOMPARE(object->property("importedModuleAttachedPropertyValue"), QVariant(false));
+ delete object;
+ QDeclarativeComponent failFourComponent(&engine, TEST_FILE("jsimportfail/failFour.qml"));
+ expectedWarning = QLatin1String("file://") + TEST_FILE("jsimportfail/failFour.qml").toLocalFile() + QLatin1String(":6: ReferenceError: Can't find variable: JsQtTest");
+ QTest::ignoreMessage(QtWarningMsg, expectedWarning.toAscii().constData());
+ object = failFourComponent.create();
+ QVERIFY(object != 0);
+ QCOMPARE(object->property("importedModuleEnumValue"), QVariant(0));
+ delete object;
+ QDeclarativeComponent failFiveComponent(&engine, TEST_FILE("jsimportfail/failFive.qml"));
+ expectedWarning = QLatin1String("file://") + TEST_FILE("jsimportfail/importWithImports.js").toLocalFile() + QLatin1String(":8: ReferenceError: Can't find variable: Component");
+ QTest::ignoreMessage(QtWarningMsg, expectedWarning.toAscii().constData());
+ expectedWarning = QLatin1String("file://") + TEST_FILE("jsimportfail/importPragmaLibrary.js").toLocalFile() + QLatin1String(":6: ReferenceError: Can't find variable: Component");
+ QTest::ignoreMessage(QtWarningMsg, expectedWarning.toAscii().constData());
+ object = failFiveComponent.create();
+ QVERIFY(object != 0);
+ QCOMPARE(object->property("componentError"), QVariant(0));
+ delete object;
+
+ // also, test that importing scripts with .pragma library works as required
+ QDeclarativeComponent pragmaLibraryComponent(&engine, TEST_FILE("jsimport/testImportPragmaLibrary.qml"));
+ object = pragmaLibraryComponent.create();
+ QVERIFY(object != 0);
+ QCOMPARE(object->property("testValue"), QVariant(31));
+ delete object;
+
+ // and that .pragma library scripts don't inherit imports from any .qml file
+ QDeclarativeComponent pragmaLibraryComponentTwo(&engine, TEST_FILE("jsimportfail/testImportPragmaLibrary.qml"));
+ object = pragmaLibraryComponentTwo.create();
+ QVERIFY(object != 0);
+ QCOMPARE(object->property("testValue"), QVariant(0));
+ delete object;
+}
+
+void tst_qdeclarativeecmascript::scarceResources()
+{
+ QPixmap origPixmap(100, 100);
+ origPixmap.fill(Qt::blue);
+
+ QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(&engine);
+ ScarceResourceObject *eo = 0;
+ QObject *object = 0;
+
+ // in the following three cases, the instance created from the component
+ // has a property which is a copy of the scarce resource; hence, the
+ // resource should NOT be detached prior to deletion of the object instance,
+ // unless the resource is destroyed explicitly.
+ QDeclarativeComponent component(&engine, TEST_FILE("scarceresources/scarceResourceCopy.qml"));
+ object = component.create();
+ QVERIFY(object != 0);
+ QVERIFY(object->property("scarceResourceCopy").isValid());
+ QCOMPARE(object->property("scarceResourceCopy").value<QPixmap>(), origPixmap);
+ QVERIFY(ep->scarceResources == 0); // should have been released by this point.
+ eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
+ QVERIFY(!eo->scarceResourceIsDetached()); // there are two copies of it in existence: the property of object, and the property of eo.
+ delete object;
+
+ QDeclarativeComponent componentTwo(&engine, TEST_FILE("scarceresources/scarceResourceCopyFromJs.qml"));
+ object = componentTwo.create();
+ QVERIFY(object != 0);
+ QVERIFY(object->property("scarceResourceCopy").isValid());
+ QCOMPARE(object->property("scarceResourceCopy").value<QPixmap>(), origPixmap);
+ QVERIFY(ep->scarceResources == 0); // should have been released by this point.
+ eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
+ QVERIFY(!eo->scarceResourceIsDetached()); // there are two copies of it in existence: the property of object, and the property of eo.
+ delete object;
+
+ QDeclarativeComponent componentThree(&engine, TEST_FILE("scarceresources/scarceResourceDestroyedCopy.qml"));
+ object = componentThree.create();
+ QVERIFY(object != 0);
+ QVERIFY(!(object->property("scarceResourceCopy").isValid())); // was manually released prior to being returned.
+ QVERIFY(ep->scarceResources == 0); // should have been released by this point.
+ eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
+ QVERIFY(eo->scarceResourceIsDetached()); // should have explicitly been released during the evaluation of the binding.
+ delete object;
+
+ // in the following three cases, no other copy should exist in memory,
+ // and so it should be detached (unless explicitly preserved).
+ QDeclarativeComponent componentFour(&engine, TEST_FILE("scarceresources/scarceResourceTest.qml"));
+ object = componentFour.create();
+ QVERIFY(object != 0);
+ QVERIFY(object->property("scarceResourceTest").isValid());
+ QCOMPARE(object->property("scarceResourceTest").toInt(), 100);
+ QVERIFY(ep->scarceResources == 0); // should have been released by this point.
+ eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
+ QVERIFY(eo->scarceResourceIsDetached()); // the resource should have been released after the binding was evaluated.
+ delete object;
+
+ QDeclarativeComponent componentFive(&engine, TEST_FILE("scarceresources/scarceResourceTestPreserve.qml"));
+ object = componentFive.create();
+ QVERIFY(object != 0);
+ QVERIFY(object->property("scarceResourceTest").isValid());
+ QCOMPARE(object->property("scarceResourceTest").toInt(), 100);
+ QVERIFY(ep->scarceResources == 0); // should have been released by this point.
+ eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
+ QVERIFY(!eo->scarceResourceIsDetached()); // this won't be detached since we explicitly preserved it.
+ delete object;
+
+ QDeclarativeComponent componentSix(&engine, TEST_FILE("scarceresources/scarceResourceTestMultiple.qml"));
+ object = componentSix.create();
+ QVERIFY(object != 0);
+ QVERIFY(object->property("scarceResourceTest").isValid());
+ QCOMPARE(object->property("scarceResourceTest").toInt(), 100);
+ QVERIFY(ep->scarceResources == 0); // should have been released by this point.
+ eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
+ QVERIFY(eo->scarceResourceIsDetached()); // all resources were released manually or automatically released.
+ delete object;
+
+ // test that scarce resources are handled correctly for imports
+ QDeclarativeComponent componentSeven(&engine, TEST_FILE("scarceresources/scarceResourceCopyImportNoBinding.qml"));
+ object = componentSeven.create();
+ QVERIFY(object != 0); // the import should have caused the addition of a resource to the ScarceResources list
+ QVERIFY(ep->scarceResources == 0); // but they should have been released by this point.
+ delete object;
+
+ QDeclarativeComponent componentEight(&engine, TEST_FILE("scarceresources/scarceResourceCopyImportFail.qml"));
+ object = componentEight.create();
+ QVERIFY(object != 0);
+ QVERIFY(!object->property("scarceResourceCopy").isValid()); // wasn't preserved, so shouldn't be valid.
+ QVERIFY(ep->scarceResources == 0); // should have been released by this point.
+ delete object;
+
+ QDeclarativeComponent componentNine(&engine, TEST_FILE("scarceresources/scarceResourceCopyImport.qml"));
+ object = componentNine.create();
+ QVERIFY(object != 0);
+ QVERIFY(object->property("scarceResourceCopy").isValid()); // preserved, so should be valid.
+ QCOMPARE(object->property("scarceResourceCopy").value<QPixmap>(), origPixmap);
+ QVERIFY(object->property("scarceResourceAssignedCopyOne").isValid()); // assigned before destroy(), so should be valid.
+ QCOMPARE(object->property("scarceResourceAssignedCopyOne").value<QPixmap>(), origPixmap);
+ QVERIFY(!object->property("scarceResourceAssignedCopyTwo").isValid()); // assigned after destroy(), so should be invalid.
+ QVERIFY(ep->scarceResources == 0); // this will still be zero, because "preserve()" REMOVES it from this list.
+ delete object;
+
+ // test that scarce resources are handled properly in signal invocation
+ QDeclarativeComponent componentTen(&engine, TEST_FILE("scarceresources/scarceResourceSignal.qml"));
+ object = componentTen.create();
+ QVERIFY(object != 0);
+ QObject *srsc = object->findChild<QObject*>("srsc");
+ QVERIFY(srsc);
+ QVERIFY(!srsc->property("scarceResourceCopy").isValid()); // hasn't been instantiated yet.
+ QCOMPARE(srsc->property("width"), QVariant(5)); // default value is 5.
+ eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
+ QVERIFY(eo->scarceResourceIsDetached()); // should be no other copies of it at this stage.
+ QMetaObject::invokeMethod(srsc, "testSignal");
+ QVERIFY(!srsc->property("scarceResourceCopy").isValid()); // still hasn't been instantiated
+ QCOMPARE(srsc->property("width"), QVariant(10)); // but width was assigned to 10.
+ eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
+ QVERIFY(eo->scarceResourceIsDetached()); // should still be no other copies of it at this stage.
+ QMetaObject::invokeMethod(srsc, "testSignal2"); // assigns scarceResourceCopy to the scarce pixmap.
+ QVERIFY(srsc->property("scarceResourceCopy").isValid());
+ QCOMPARE(srsc->property("scarceResourceCopy").value<QPixmap>(), origPixmap);
+ eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
+ QVERIFY(!(eo->scarceResourceIsDetached())); // should be another copy of the resource now.
+ QVERIFY(ep->scarceResources == 0); // should have been released by this point.
+ delete object;
+
+ // test that scarce resources are handled properly from js functions in qml files
+ QDeclarativeComponent componentEleven(&engine, TEST_FILE("scarceresources/scarceResourceFunction.qml"));
+ object = componentEleven.create();
+ QVERIFY(object != 0);
+ QVERIFY(!object->property("scarceResourceCopy").isValid()); // not yet assigned, so should not be valid
+ eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
+ QVERIFY(eo->scarceResourceIsDetached()); // should be no other copies of it at this stage.
+ QMetaObject::invokeMethod(object, "retrieveScarceResource");
+ QVERIFY(object->property("scarceResourceCopy").isValid()); // assigned, so should be valid.
+ QCOMPARE(object->property("scarceResourceCopy").value<QPixmap>(), origPixmap);
+ eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
+ QVERIFY(!eo->scarceResourceIsDetached()); // should be a copy of the resource at this stage.
+ QMetaObject::invokeMethod(object, "releaseScarceResource");
+ QVERIFY(!object->property("scarceResourceCopy").isValid()); // just released, so should not be valid
+ eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
+ QVERIFY(eo->scarceResourceIsDetached()); // should be no other copies of it at this stage.
+ QVERIFY(ep->scarceResources == 0); // should have been released by this point.
+ delete object;
+
+ // test that if an exception occurs while invoking js function from cpp, that the resources are released.
+ QDeclarativeComponent componentTwelve(&engine, TEST_FILE("scarceresources/scarceResourceFunctionFail.qml"));
+ object = componentTwelve.create();
+ QVERIFY(object != 0);
+ QVERIFY(!object->property("scarceResourceCopy").isValid()); // not yet assigned, so should not be valid
+ eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
+ QVERIFY(eo->scarceResourceIsDetached()); // should be no other copies of it at this stage.
+ QString expectedWarning = QLatin1String("file://") + TEST_FILE("scarceresources/scarceResourceFunctionFail.qml").toLocalFile() + QLatin1String(":16: TypeError: Result of expression 'scarceResourceProvider.scarceResource' [[object Object]] is not a function.");
+ QTest::ignoreMessage(QtWarningMsg, expectedWarning.toAscii().constData()); // we expect a meaningful warning to be printed.
+ QMetaObject::invokeMethod(object, "retrieveScarceResource");
+ QVERIFY(!object->property("scarceResourceCopy").isValid()); // due to exception, assignment will NOT have occurred.
+ eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
+ QVERIFY(eo->scarceResourceIsDetached()); // should be no other copies of it at this stage.
+ QVERIFY(ep->scarceResources == 0); // should have been released by this point.
+ delete object;
+}
+
+void tst_qdeclarativeecmascript::propertyChangeSlots()
+{
+ // ensure that allowable property names are allowed and onPropertyNameChanged slots are generated correctly.
+ QDeclarativeComponent component(&engine, TEST_FILE("changeslots/propertyChangeSlots.qml"));
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+ delete object;
+
+ // ensure that invalid property names fail properly.
+ QTest::ignoreMessage(QtWarningMsg, "QDeclarativeComponent: Component is not ready");
+ QDeclarativeComponent e1(&engine, TEST_FILE("changeslots/propertyChangeSlotErrors.1.qml"));
+ QString expectedErrorString = e1.url().toString() + QLatin1String(":9:5: Cannot assign to non-existent property \"on_nameWithUnderscoreChanged\"");
+ QCOMPARE(e1.errors().at(0).toString(), expectedErrorString);
+ object = e1.create();
+ QVERIFY(object == 0);
+ delete object;
+
+ QTest::ignoreMessage(QtWarningMsg, "QDeclarativeComponent: Component is not ready");
+ QDeclarativeComponent e2(&engine, TEST_FILE("changeslots/propertyChangeSlotErrors.2.qml"));
+ expectedErrorString = e2.url().toString() + QLatin1String(":9:5: Cannot assign to non-existent property \"on____nameWithUnderscoresChanged\"");
+ QCOMPARE(e2.errors().at(0).toString(), expectedErrorString);
+ object = e2.create();
+ QVERIFY(object == 0);
+ delete object;
+
+ QTest::ignoreMessage(QtWarningMsg, "QDeclarativeComponent: Component is not ready");
+ QDeclarativeComponent e3(&engine, TEST_FILE("changeslots/propertyChangeSlotErrors.3.qml"));
+ expectedErrorString = e3.url().toString() + QLatin1String(":9:5: Cannot assign to non-existent property \"on$NameWithDollarsignChanged\"");
+ QCOMPARE(e3.errors().at(0).toString(), expectedErrorString);
+ object = e3.create();
+ QVERIFY(object == 0);
+ delete object;
+
+ QTest::ignoreMessage(QtWarningMsg, "QDeclarativeComponent: Component is not ready");
+ QDeclarativeComponent e4(&engine, TEST_FILE("changeslots/propertyChangeSlotErrors.4.qml"));
+ expectedErrorString = e4.url().toString() + QLatin1String(":9:5: Cannot assign to non-existent property \"on_6NameWithUnderscoreNumberChanged\"");
+ QCOMPARE(e4.errors().at(0).toString(), expectedErrorString);
+ object = e4.create();
+ QVERIFY(object == 0);
+ delete object;
+}
+
// Test that assigning a null object works
// Regressed with: df1788b4dbbb2826ae63f26bdf166342595343f4
void tst_qdeclarativeecmascript::nullObjectBinding()
@@ -2970,6 +3401,7 @@ void tst_qdeclarativeecmascript::revisionErrors()
QTest::ignoreMessage(QtWarningMsg, warning3.toLatin1().constData());
MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create());
QVERIFY(object != 0);
+ delete object;
}
{
QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevisionErrors2.qml"));
@@ -2991,6 +3423,7 @@ void tst_qdeclarativeecmascript::revisionErrors()
QTest::ignoreMessage(QtWarningMsg, warning5.toLatin1().constData());
MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create());
QVERIFY(object != 0);
+ delete object;
}
{
QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevisionErrors3.qml"));
@@ -3006,6 +3439,7 @@ void tst_qdeclarativeecmascript::revisionErrors()
QTest::ignoreMessage(QtWarningMsg, warning3.toLatin1().constData());
MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create());
QVERIFY(object != 0);
+ delete object;
}
}
@@ -3017,6 +3451,7 @@ void tst_qdeclarativeecmascript::revision()
MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create());
QVERIFY(object != 0);
+ delete object;
}
{
QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevision2.qml"));
@@ -3024,6 +3459,7 @@ void tst_qdeclarativeecmascript::revision()
MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create());
QVERIFY(object != 0);
+ delete object;
}
{
QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevision3.qml"));
@@ -3031,6 +3467,7 @@ void tst_qdeclarativeecmascript::revision()
MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create());
QVERIFY(object != 0);
+ delete object;
}
// Test that non-root classes can resolve revisioned methods
{
@@ -3081,6 +3518,18 @@ void tst_qdeclarativeecmascript::pushCleanContext()
QCOMPARE(func2.call().toInt32(), 6);
}
+void tst_qdeclarativeecmascript::realToInt()
+{
+ QDeclarativeComponent component(&engine, TEST_FILE("realToInt.qml"));
+ MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
+ QVERIFY(object != 0);
+
+ QMetaObject::invokeMethod(object, "test1");
+ QCOMPARE(object->value(), int(4));
+ QMetaObject::invokeMethod(object, "test2");
+ QCOMPARE(object->value(), int(8));
+}
+
QTEST_MAIN(tst_qdeclarativeecmascript)
#include "tst_qdeclarativeecmascript.moc"