1 /****************************************************************************
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
7 ** This file is part of the test suite of the Qt Toolkit.
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** GNU Lesser General Public License Usage
11 ** This file may be used under the terms of the GNU Lesser General Public
12 ** License version 2.1 as published by the Free Software Foundation and
13 ** appearing in the file LICENSE.LGPL included in the packaging of this
14 ** file. Please review the following information to ensure the GNU Lesser
15 ** General Public License version 2.1 requirements will be met:
16 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
18 ** In addition, as a special exception, Nokia gives you certain additional
19 ** rights. These rights are described in the Nokia Qt LGPL Exception
20 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
22 ** GNU General Public License Usage
23 ** Alternatively, this file may be used under the terms of the GNU General
24 ** Public License version 3.0 as published by the Free Software Foundation
25 ** and appearing in the file LICENSE.GPL included in the packaging of this
26 ** file. Please review the following information to ensure the GNU General
27 ** Public License version 3.0 requirements will be met:
28 ** http://www.gnu.org/copyleft/gpl.html.
31 ** Alternatively, this file may be used in accordance with the terms and
32 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
42 #include <QtDeclarative/qdeclarativecomponent.h>
43 #include <QtDeclarative/qdeclarativeengine.h>
44 #include <QtDeclarative/qdeclarativeexpression.h>
45 #include <QtDeclarative/qdeclarativecontext.h>
46 #include <QtCore/qfileinfo.h>
47 #include <QtCore/qdebug.h>
48 #include <QtDeclarative/private/qdeclarativeguard_p.h>
49 #include <QtCore/qdir.h>
50 #include <QtCore/qnumeric.h>
51 #include <private/qdeclarativeengine_p.h>
52 #include "testtypes.h"
53 #include "testhttpserver.h"
54 #include "../../../shared/util.h"
57 // In Symbian OS test data is located in applications private dir
62 This test covers evaluation of ECMAScript expressions and bindings from within
63 QML. This does not include static QML language issues.
65 Static QML language issues are covered in qmllanguage
67 inline QUrl TEST_FILE(const QString &filename)
69 QFileInfo fileInfo(__FILE__);
70 return QUrl::fromLocalFile(fileInfo.absoluteDir().filePath("data/" + filename));
73 inline QUrl TEST_FILE(const char *filename)
75 return TEST_FILE(QLatin1String(filename));
78 class tst_qdeclarativeecmascript : public QObject
82 tst_qdeclarativeecmascript() {}
86 void assignBasicTypes();
87 void idShortcutInvalidates();
88 void boolPropertiesEvaluateAsBool();
90 void signalAssignment();
92 void basicExpressions();
93 void basicExpressions_data();
94 void arrayExpressions();
95 void contextPropertiesTriggerReeval();
96 void objectPropertiesTriggerReeval();
97 void deferredProperties();
98 void deferredPropertiesErrors();
99 void extensionObjects();
100 void overrideExtensionProperties();
101 void attachedProperties();
103 void valueTypeFunctions();
104 void constantsOverrideBindings();
105 void outerBindingOverridesInnerBinding();
106 void aliasPropertyAndBinding();
107 void aliasPropertyReset();
108 void nonExistentAttachedObject();
111 void signalParameterTypes();
112 void objectsCompareAsEqual();
113 void dynamicCreation_data();
114 void dynamicCreation();
115 void dynamicDestruction();
116 void objectToString();
117 void objectHasOwnProperty();
118 void selfDeletingBinding();
119 void extendedObjectPropertyLookup();
121 void functionErrors();
122 void propertyAssignmentErrors();
123 void signalTriggeredBindings();
124 void listProperties();
125 void exceptionClearsOnReeval();
126 void exceptionSlotProducesWarning();
127 void exceptionBindingProducesWarning();
128 void transientErrors();
129 void shutdownErrors();
130 void compositePropertyType();
132 void undefinedResetsProperty();
133 void listToVariant();
134 void multiEngineObject();
135 void deletedObject();
136 void attachedPropertyScope();
137 void scriptConnect();
138 void scriptDisconnect();
140 void cppOwnershipReturnValue();
141 void ownershipCustomReturnValue();
142 void qlistqobjectMethods();
143 void strictlyEquals();
145 void numberAssignment();
146 void propertySplicing();
147 void signalWithUnknownTypes();
149 void importScripts();
150 void scarceResources();
151 void propertyChangeSlots();
152 void elementAssign();
153 void objectPassThroughSignals();
154 void booleanConversion();
158 void dynamicCreationCrash();
160 void nullObjectBinding();
161 void deletedEngine();
162 void libraryScriptAssert();
163 void variantsAssignedUndefined();
165 void qtcreatorbug_1289();
166 void noSpuriousWarningsAtShutdown();
167 void canAssignNullToQObject();
168 void functionAssignment_fromBinding();
169 void functionAssignment_fromJS();
170 void functionAssignment_fromJS_data();
171 void functionAssignmentfromJS_invalid();
177 void nonscriptable();
180 void sharedAttachedObject();
182 void writeRemovesBinding();
183 void aliasBindingsAssignCorrectly();
184 void aliasBindingsOverrideTarget();
185 void aliasWritesOverrideBindings();
186 void aliasToCompositeElement();
188 void dynamicString();
191 void callQtInvokables();
192 void invokableObjectArg();
193 void invokableObjectRet();
195 void revisionErrors();
199 QDeclarativeEngine engine;
202 void tst_qdeclarativeecmascript::initTestCase() { registerTypes(); }
204 void tst_qdeclarativeecmascript::assignBasicTypes()
207 QDeclarativeComponent component(&engine, TEST_FILE("assignBasicTypes.qml"));
208 MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
209 QVERIFY(object != 0);
210 QCOMPARE(object->flagProperty(), MyTypeObject::FlagVal1 | MyTypeObject::FlagVal3);
211 QCOMPARE(object->enumProperty(), MyTypeObject::EnumVal2);
212 QCOMPARE(object->stringProperty(), QString("Hello World!"));
213 QCOMPARE(object->uintProperty(), uint(10));
214 QCOMPARE(object->intProperty(), -19);
215 QCOMPARE((float)object->realProperty(), float(23.2));
216 QCOMPARE((float)object->doubleProperty(), float(-19.75));
217 QCOMPARE((float)object->floatProperty(), float(8.5));
218 QCOMPARE(object->colorProperty(), QColor("red"));
219 QCOMPARE(object->dateProperty(), QDate(1982, 11, 25));
220 QCOMPARE(object->timeProperty(), QTime(11, 11, 32));
221 QCOMPARE(object->dateTimeProperty(), QDateTime(QDate(2009, 5, 12), QTime(13, 22, 1)));
222 QCOMPARE(object->pointProperty(), QPoint(99,13));
223 QCOMPARE(object->pointFProperty(), QPointF(-10.1, 12.3));
224 QCOMPARE(object->sizeProperty(), QSize(99, 13));
225 QCOMPARE(object->sizeFProperty(), QSizeF(0.1, 0.2));
226 QCOMPARE(object->rectProperty(), QRect(9, 7, 100, 200));
227 QCOMPARE(object->rectFProperty(), QRectF(1000.1, -10.9, 400, 90.99));
228 QCOMPARE(object->boolProperty(), true);
229 QCOMPARE(object->variantProperty(), QVariant("Hello World!"));
230 QCOMPARE(object->vectorProperty(), QVector3D(10, 1, 2.2));
231 QCOMPARE(object->urlProperty(), component.url().resolved(QUrl("main.qml")));
235 QDeclarativeComponent component(&engine, TEST_FILE("assignBasicTypes.2.qml"));
236 MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
237 QVERIFY(object != 0);
238 QCOMPARE(object->flagProperty(), MyTypeObject::FlagVal1 | MyTypeObject::FlagVal3);
239 QCOMPARE(object->enumProperty(), MyTypeObject::EnumVal2);
240 QCOMPARE(object->stringProperty(), QString("Hello World!"));
241 QCOMPARE(object->uintProperty(), uint(10));
242 QCOMPARE(object->intProperty(), -19);
243 QCOMPARE((float)object->realProperty(), float(23.2));
244 QCOMPARE((float)object->doubleProperty(), float(-19.75));
245 QCOMPARE((float)object->floatProperty(), float(8.5));
246 QCOMPARE(object->colorProperty(), QColor("red"));
247 QCOMPARE(object->dateProperty(), QDate(1982, 11, 25));
248 QCOMPARE(object->timeProperty(), QTime(11, 11, 32));
249 QCOMPARE(object->dateTimeProperty(), QDateTime(QDate(2009, 5, 12), QTime(13, 22, 1)));
250 QCOMPARE(object->pointProperty(), QPoint(99,13));
251 QCOMPARE(object->pointFProperty(), QPointF(-10.1, 12.3));
252 QCOMPARE(object->sizeProperty(), QSize(99, 13));
253 QCOMPARE(object->sizeFProperty(), QSizeF(0.1, 0.2));
254 QCOMPARE(object->rectProperty(), QRect(9, 7, 100, 200));
255 QCOMPARE(object->rectFProperty(), QRectF(1000.1, -10.9, 400, 90.99));
256 QCOMPARE(object->boolProperty(), true);
257 QCOMPARE(object->variantProperty(), QVariant("Hello World!"));
258 QCOMPARE(object->vectorProperty(), QVector3D(10, 1, 2.2));
259 QCOMPARE(object->urlProperty(), component.url().resolved(QUrl("main.qml")));
264 void tst_qdeclarativeecmascript::idShortcutInvalidates()
267 QDeclarativeComponent component(&engine, TEST_FILE("idShortcutInvalidates.qml"));
268 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
269 QVERIFY(object != 0);
270 QVERIFY(object->objectProperty() != 0);
271 delete object->objectProperty();
272 QVERIFY(object->objectProperty() == 0);
277 QDeclarativeComponent component(&engine, TEST_FILE("idShortcutInvalidates.1.qml"));
278 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
279 QVERIFY(object != 0);
280 QVERIFY(object->objectProperty() != 0);
281 delete object->objectProperty();
282 QVERIFY(object->objectProperty() == 0);
287 void tst_qdeclarativeecmascript::boolPropertiesEvaluateAsBool()
290 QDeclarativeComponent component(&engine, TEST_FILE("boolPropertiesEvaluateAsBool.1.qml"));
291 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
292 QVERIFY(object != 0);
293 QCOMPARE(object->stringProperty(), QLatin1String("pass"));
297 QDeclarativeComponent component(&engine, TEST_FILE("boolPropertiesEvaluateAsBool.2.qml"));
298 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
299 QVERIFY(object != 0);
300 QCOMPARE(object->stringProperty(), QLatin1String("pass"));
305 void tst_qdeclarativeecmascript::signalAssignment()
308 QDeclarativeComponent component(&engine, TEST_FILE("signalAssignment.1.qml"));
309 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
310 QVERIFY(object != 0);
311 QCOMPARE(object->string(), QString());
312 emit object->basicSignal();
313 QCOMPARE(object->string(), QString("pass"));
318 QDeclarativeComponent component(&engine, TEST_FILE("signalAssignment.2.qml"));
319 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
320 QVERIFY(object != 0);
321 QCOMPARE(object->string(), QString());
322 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
323 QCOMPARE(object->string(), QString("pass 19 Hello world! 10.25 3 2"));
328 void tst_qdeclarativeecmascript::methods()
331 QDeclarativeComponent component(&engine, TEST_FILE("methods.1.qml"));
332 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
333 QVERIFY(object != 0);
334 QCOMPARE(object->methodCalled(), false);
335 QCOMPARE(object->methodIntCalled(), false);
336 emit object->basicSignal();
337 QCOMPARE(object->methodCalled(), true);
338 QCOMPARE(object->methodIntCalled(), false);
343 QDeclarativeComponent component(&engine, TEST_FILE("methods.2.qml"));
344 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
345 QVERIFY(object != 0);
346 QCOMPARE(object->methodCalled(), false);
347 QCOMPARE(object->methodIntCalled(), false);
348 emit object->basicSignal();
349 QCOMPARE(object->methodCalled(), false);
350 QCOMPARE(object->methodIntCalled(), true);
355 QDeclarativeComponent component(&engine, TEST_FILE("methods.3.qml"));
356 QObject *object = component.create();
357 QVERIFY(object != 0);
358 QCOMPARE(object->property("test").toInt(), 19);
363 QDeclarativeComponent component(&engine, TEST_FILE("methods.4.qml"));
364 QObject *object = component.create();
365 QVERIFY(object != 0);
366 QCOMPARE(object->property("test").toInt(), 19);
367 QCOMPARE(object->property("test2").toInt(), 17);
368 QCOMPARE(object->property("test3").toInt(), 16);
373 QDeclarativeComponent component(&engine, TEST_FILE("methods.5.qml"));
374 QObject *object = component.create();
375 QVERIFY(object != 0);
376 QCOMPARE(object->property("test").toInt(), 9);
381 void tst_qdeclarativeecmascript::bindingLoop()
383 QDeclarativeComponent component(&engine, TEST_FILE("bindingLoop.qml"));
384 QString warning = component.url().toString() + ":9:9: QML MyQmlObject: Binding loop detected for property \"stringProperty\"";
385 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
386 QObject *object = component.create();
387 QVERIFY(object != 0);
391 void tst_qdeclarativeecmascript::basicExpressions_data()
393 QTest::addColumn<QString>("expression");
394 QTest::addColumn<QVariant>("result");
395 QTest::addColumn<bool>("nest");
397 QTest::newRow("Syntax error (self test)") << "{console.log({'a':1'}.a)}" << QVariant() << false;
398 QTest::newRow("Context property") << "a" << QVariant(1944) << false;
399 QTest::newRow("Context property") << "a" << QVariant(1944) << true;
400 QTest::newRow("Context property expression") << "a * 2" << QVariant(3888) << false;
401 QTest::newRow("Context property expression") << "a * 2" << QVariant(3888) << true;
402 QTest::newRow("Overridden context property") << "b" << QVariant("Milk") << false;
403 QTest::newRow("Overridden context property") << "b" << QVariant("Cow") << true;
404 QTest::newRow("Object property") << "object.stringProperty" << QVariant("Object1") << false;
405 QTest::newRow("Object property") << "object.stringProperty" << QVariant("Object1") << true;
406 QTest::newRow("Overridden object property") << "objectOverride.stringProperty" << QVariant("Object2") << false;
407 QTest::newRow("Overridden object property") << "objectOverride.stringProperty" << QVariant("Object3") << true;
408 QTest::newRow("Default object property") << "horseLegs" << QVariant(4) << false;
409 QTest::newRow("Default object property") << "antLegs" << QVariant(6) << false;
410 QTest::newRow("Default object property") << "emuLegs" << QVariant(2) << false;
411 QTest::newRow("Nested default object property") << "horseLegs" << QVariant(4) << true;
412 QTest::newRow("Nested default object property") << "antLegs" << QVariant(7) << true;
413 QTest::newRow("Nested default object property") << "emuLegs" << QVariant(2) << true;
414 QTest::newRow("Nested default object property") << "humanLegs" << QVariant(2) << true;
415 QTest::newRow("Context property override default object property") << "millipedeLegs" << QVariant(100) << true;
418 void tst_qdeclarativeecmascript::basicExpressions()
420 QFETCH(QString, expression);
421 QFETCH(QVariant, result);
427 MyDefaultObject1 default1;
428 MyDefaultObject3 default3;
429 object1.setStringProperty("Object1");
430 object2.setStringProperty("Object2");
431 object3.setStringProperty("Object3");
433 QDeclarativeContext context(engine.rootContext());
434 QDeclarativeContext nestedContext(&context);
436 context.setContextObject(&default1);
437 context.setContextProperty("a", QVariant(1944));
438 context.setContextProperty("b", QVariant("Milk"));
439 context.setContextProperty("object", &object1);
440 context.setContextProperty("objectOverride", &object2);
441 nestedContext.setContextObject(&default3);
442 nestedContext.setContextProperty("b", QVariant("Cow"));
443 nestedContext.setContextProperty("objectOverride", &object3);
444 nestedContext.setContextProperty("millipedeLegs", QVariant(100));
446 MyExpression expr(nest?&nestedContext:&context, expression);
447 QCOMPARE(expr.evaluate(), result);
450 void tst_qdeclarativeecmascript::arrayExpressions()
456 QDeclarativeContext context(engine.rootContext());
457 context.setContextProperty("a", &obj1);
458 context.setContextProperty("b", &obj2);
459 context.setContextProperty("c", &obj3);
461 MyExpression expr(&context, "[a, b, c, 10]");
462 QVariant result = expr.evaluate();
463 QCOMPARE(result.userType(), qMetaTypeId<QList<QObject *> >());
464 QList<QObject *> list = qvariant_cast<QList<QObject *> >(result);
465 QCOMPARE(list.count(), 4);
466 QCOMPARE(list.at(0), &obj1);
467 QCOMPARE(list.at(1), &obj2);
468 QCOMPARE(list.at(2), &obj3);
469 QCOMPARE(list.at(3), (QObject *)0);
472 // Tests that modifying a context property will reevaluate expressions
473 void tst_qdeclarativeecmascript::contextPropertiesTriggerReeval()
475 QDeclarativeContext context(engine.rootContext());
478 MyQmlObject *object3 = new MyQmlObject;
480 object1.setStringProperty("Hello");
481 object2.setStringProperty("World");
483 context.setContextProperty("testProp", QVariant(1));
484 context.setContextProperty("testObj", &object1);
485 context.setContextProperty("testObj2", object3);
488 MyExpression expr(&context, "testProp + 1");
489 QCOMPARE(expr.changed, false);
490 QCOMPARE(expr.evaluate(), QVariant(2));
492 context.setContextProperty("testProp", QVariant(2));
493 QCOMPARE(expr.changed, true);
494 QCOMPARE(expr.evaluate(), QVariant(3));
498 MyExpression expr(&context, "testProp + testProp + testProp");
499 QCOMPARE(expr.changed, false);
500 QCOMPARE(expr.evaluate(), QVariant(6));
502 context.setContextProperty("testProp", QVariant(4));
503 QCOMPARE(expr.changed, true);
504 QCOMPARE(expr.evaluate(), QVariant(12));
508 MyExpression expr(&context, "testObj.stringProperty");
509 QCOMPARE(expr.changed, false);
510 QCOMPARE(expr.evaluate(), QVariant("Hello"));
512 context.setContextProperty("testObj", &object2);
513 QCOMPARE(expr.changed, true);
514 QCOMPARE(expr.evaluate(), QVariant("World"));
518 MyExpression expr(&context, "testObj.stringProperty /**/");
519 QCOMPARE(expr.changed, false);
520 QCOMPARE(expr.evaluate(), QVariant("World"));
522 context.setContextProperty("testObj", &object1);
523 QCOMPARE(expr.changed, true);
524 QCOMPARE(expr.evaluate(), QVariant("Hello"));
528 MyExpression expr(&context, "testObj2");
529 QCOMPARE(expr.changed, false);
530 QCOMPARE(expr.evaluate(), QVariant::fromValue((QObject *)object3));
536 void tst_qdeclarativeecmascript::objectPropertiesTriggerReeval()
538 QDeclarativeContext context(engine.rootContext());
542 context.setContextProperty("testObj", &object1);
544 object1.setStringProperty(QLatin1String("Hello"));
545 object2.setStringProperty(QLatin1String("Dog"));
546 object3.setStringProperty(QLatin1String("Cat"));
549 MyExpression expr(&context, "testObj.stringProperty");
550 QCOMPARE(expr.changed, false);
551 QCOMPARE(expr.evaluate(), QVariant("Hello"));
553 object1.setStringProperty(QLatin1String("World"));
554 QCOMPARE(expr.changed, true);
555 QCOMPARE(expr.evaluate(), QVariant("World"));
559 MyExpression expr(&context, "testObj.objectProperty.stringProperty");
560 QCOMPARE(expr.changed, false);
561 QCOMPARE(expr.evaluate(), QVariant());
563 object1.setObjectProperty(&object2);
564 QCOMPARE(expr.changed, true);
565 expr.changed = false;
566 QCOMPARE(expr.evaluate(), QVariant("Dog"));
568 object1.setObjectProperty(&object3);
569 QCOMPARE(expr.changed, true);
570 expr.changed = false;
571 QCOMPARE(expr.evaluate(), QVariant("Cat"));
573 object1.setObjectProperty(0);
574 QCOMPARE(expr.changed, true);
575 expr.changed = false;
576 QCOMPARE(expr.evaluate(), QVariant());
578 object1.setObjectProperty(&object3);
579 QCOMPARE(expr.changed, true);
580 expr.changed = false;
581 QCOMPARE(expr.evaluate(), QVariant("Cat"));
583 object3.setStringProperty("Donkey");
584 QCOMPARE(expr.changed, true);
585 expr.changed = false;
586 QCOMPARE(expr.evaluate(), QVariant("Donkey"));
590 void tst_qdeclarativeecmascript::deferredProperties()
592 QDeclarativeComponent component(&engine, TEST_FILE("deferredProperties.qml"));
593 MyDeferredObject *object =
594 qobject_cast<MyDeferredObject *>(component.create());
595 QVERIFY(object != 0);
596 QCOMPARE(object->value(), 0);
597 QVERIFY(object->objectProperty() == 0);
598 QVERIFY(object->objectProperty2() != 0);
599 qmlExecuteDeferred(object);
600 QCOMPARE(object->value(), 10);
601 QVERIFY(object->objectProperty() != 0);
602 MyQmlObject *qmlObject =
603 qobject_cast<MyQmlObject *>(object->objectProperty());
604 QVERIFY(qmlObject != 0);
605 QCOMPARE(qmlObject->value(), 10);
606 object->setValue(19);
607 QCOMPARE(qmlObject->value(), 19);
612 // Check errors on deferred properties are correctly emitted
613 void tst_qdeclarativeecmascript::deferredPropertiesErrors()
615 QDeclarativeComponent component(&engine, TEST_FILE("deferredPropertiesErrors.qml"));
616 MyDeferredObject *object =
617 qobject_cast<MyDeferredObject *>(component.create());
618 QVERIFY(object != 0);
619 QCOMPARE(object->value(), 0);
620 QVERIFY(object->objectProperty() == 0);
621 QVERIFY(object->objectProperty2() == 0);
623 QString warning = component.url().toString() + ":6: Unable to assign [undefined] to QObject* objectProperty";
624 QTest::ignoreMessage(QtWarningMsg, qPrintable(warning));
626 qmlExecuteDeferred(object);
631 void tst_qdeclarativeecmascript::extensionObjects()
633 QDeclarativeComponent component(&engine, TEST_FILE("extensionObjects.qml"));
634 MyExtendedObject *object =
635 qobject_cast<MyExtendedObject *>(component.create());
636 QVERIFY(object != 0);
637 QCOMPARE(object->baseProperty(), 13);
638 QCOMPARE(object->coreProperty(), 9);
639 object->setProperty("extendedProperty", QVariant(11));
640 object->setProperty("baseExtendedProperty", QVariant(92));
641 QCOMPARE(object->coreProperty(), 11);
642 QCOMPARE(object->baseProperty(), 92);
644 MyExtendedObject *nested = qobject_cast<MyExtendedObject*>(qvariant_cast<QObject *>(object->property("nested")));
646 QCOMPARE(nested->baseProperty(), 13);
647 QCOMPARE(nested->coreProperty(), 9);
648 nested->setProperty("extendedProperty", QVariant(11));
649 nested->setProperty("baseExtendedProperty", QVariant(92));
650 QCOMPARE(nested->coreProperty(), 11);
651 QCOMPARE(nested->baseProperty(), 92);
656 void tst_qdeclarativeecmascript::overrideExtensionProperties()
658 QDeclarativeComponent component(&engine, TEST_FILE("extensionObjectsPropertyOverride.qml"));
659 OverrideDefaultPropertyObject *object =
660 qobject_cast<OverrideDefaultPropertyObject *>(component.create());
661 QVERIFY(object != 0);
662 QVERIFY(object->secondProperty() != 0);
663 QVERIFY(object->firstProperty() == 0);
668 void tst_qdeclarativeecmascript::attachedProperties()
671 QDeclarativeComponent component(&engine, TEST_FILE("attachedProperty.qml"));
672 QObject *object = component.create();
673 QVERIFY(object != 0);
674 QCOMPARE(object->property("a").toInt(), 19);
675 QCOMPARE(object->property("b").toInt(), 19);
676 QCOMPARE(object->property("c").toInt(), 19);
677 QCOMPARE(object->property("d").toInt(), 19);
682 QDeclarativeComponent component(&engine, TEST_FILE("attachedProperty.2.qml"));
683 QObject *object = component.create();
684 QVERIFY(object != 0);
685 QCOMPARE(object->property("a").toInt(), 26);
686 QCOMPARE(object->property("b").toInt(), 26);
687 QCOMPARE(object->property("c").toInt(), 26);
688 QCOMPARE(object->property("d").toInt(), 26);
692 QDeclarativeComponent component(&engine, TEST_FILE("writeAttachedProperty.qml"));
693 QObject *object = component.create();
694 QVERIFY(object != 0);
696 QMetaObject::invokeMethod(object, "writeValue2");
698 MyQmlAttachedObject *attached =
699 qobject_cast<MyQmlAttachedObject *>(qmlAttachedPropertiesObject<MyQmlObject>(object));
700 QVERIFY(attached != 0);
702 QCOMPARE(attached->value2(), 9);
707 void tst_qdeclarativeecmascript::enums()
711 QDeclarativeComponent component(&engine, TEST_FILE("enums.1.qml"));
712 QObject *object = component.create();
713 QVERIFY(object != 0);
715 QCOMPARE(object->property("a").toInt(), 0);
716 QCOMPARE(object->property("b").toInt(), 1);
717 QCOMPARE(object->property("c").toInt(), 2);
718 QCOMPARE(object->property("d").toInt(), 3);
719 QCOMPARE(object->property("e").toInt(), 0);
720 QCOMPARE(object->property("f").toInt(), 1);
721 QCOMPARE(object->property("g").toInt(), 2);
722 QCOMPARE(object->property("h").toInt(), 3);
723 QCOMPARE(object->property("i").toInt(), 19);
724 QCOMPARE(object->property("j").toInt(), 19);
728 // Non-existent enums
730 QDeclarativeComponent component(&engine, TEST_FILE("enums.2.qml"));
732 QString warning1 = component.url().toString() + ":5: Unable to assign [undefined] to int a";
733 QString warning2 = component.url().toString() + ":6: Unable to assign [undefined] to int b";
734 QTest::ignoreMessage(QtWarningMsg, qPrintable(warning1));
735 QTest::ignoreMessage(QtWarningMsg, qPrintable(warning2));
737 QObject *object = component.create();
738 QVERIFY(object != 0);
739 QCOMPARE(object->property("a").toInt(), 0);
740 QCOMPARE(object->property("b").toInt(), 0);
746 void tst_qdeclarativeecmascript::valueTypeFunctions()
748 QDeclarativeComponent component(&engine, TEST_FILE("valueTypeFunctions.qml"));
749 MyTypeObject *obj = qobject_cast<MyTypeObject*>(component.create());
751 QCOMPARE(obj->rectProperty(), QRect(0,0,100,100));
752 QCOMPARE(obj->rectFProperty(), QRectF(0,0.5,100,99.5));
758 Tests that writing a constant to a property with a binding on it disables the
761 void tst_qdeclarativeecmascript::constantsOverrideBindings()
765 QDeclarativeComponent component(&engine, TEST_FILE("constantsOverrideBindings.1.qml"));
766 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
767 QVERIFY(object != 0);
769 QCOMPARE(object->property("c2").toInt(), 0);
770 object->setProperty("c1", QVariant(9));
771 QCOMPARE(object->property("c2").toInt(), 9);
773 emit object->basicSignal();
775 QCOMPARE(object->property("c2").toInt(), 13);
776 object->setProperty("c1", QVariant(8));
777 QCOMPARE(object->property("c2").toInt(), 13);
782 // During construction
784 QDeclarativeComponent component(&engine, TEST_FILE("constantsOverrideBindings.2.qml"));
785 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
786 QVERIFY(object != 0);
788 QCOMPARE(object->property("c1").toInt(), 0);
789 QCOMPARE(object->property("c2").toInt(), 10);
790 object->setProperty("c1", QVariant(9));
791 QCOMPARE(object->property("c1").toInt(), 9);
792 QCOMPARE(object->property("c2").toInt(), 10);
800 QDeclarativeComponent component(&engine, TEST_FILE("constantsOverrideBindings.3.qml"));
801 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
802 QVERIFY(object != 0);
804 QCOMPARE(object->property("c2").toInt(), 0);
805 object->setProperty("c1", QVariant(9));
806 QCOMPARE(object->property("c2").toInt(), 9);
808 object->setProperty("c2", QVariant(13));
809 QCOMPARE(object->property("c2").toInt(), 13);
810 object->setProperty("c1", QVariant(7));
811 QCOMPARE(object->property("c1").toInt(), 7);
812 QCOMPARE(object->property("c2").toInt(), 13);
820 QDeclarativeComponent component(&engine, TEST_FILE("constantsOverrideBindings.4.qml"));
821 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
822 QVERIFY(object != 0);
824 QCOMPARE(object->property("c1").toInt(), 0);
825 QCOMPARE(object->property("c3").toInt(), 10);
826 object->setProperty("c1", QVariant(9));
827 QCOMPARE(object->property("c1").toInt(), 9);
828 QCOMPARE(object->property("c3").toInt(), 10);
835 Tests that assigning a binding to a property that already has a binding causes
836 the original binding to be disabled.
838 void tst_qdeclarativeecmascript::outerBindingOverridesInnerBinding()
840 QDeclarativeComponent component(&engine,
841 TEST_FILE("outerBindingOverridesInnerBinding.qml"));
842 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
843 QVERIFY(object != 0);
845 QCOMPARE(object->property("c1").toInt(), 0);
846 QCOMPARE(object->property("c2").toInt(), 0);
847 QCOMPARE(object->property("c3").toInt(), 0);
849 object->setProperty("c1", QVariant(9));
850 QCOMPARE(object->property("c1").toInt(), 9);
851 QCOMPARE(object->property("c2").toInt(), 0);
852 QCOMPARE(object->property("c3").toInt(), 0);
854 object->setProperty("c3", QVariant(8));
855 QCOMPARE(object->property("c1").toInt(), 9);
856 QCOMPARE(object->property("c2").toInt(), 8);
857 QCOMPARE(object->property("c3").toInt(), 8);
863 Access a non-existent attached object.
865 Tests for a regression where this used to crash.
867 void tst_qdeclarativeecmascript::nonExistentAttachedObject()
869 QDeclarativeComponent component(&engine, TEST_FILE("nonExistentAttachedObject.qml"));
871 QString warning = component.url().toString() + ":4: Unable to assign [undefined] to QString stringProperty";
872 QTest::ignoreMessage(QtWarningMsg, qPrintable(warning));
874 QObject *object = component.create();
875 QVERIFY(object != 0);
880 void tst_qdeclarativeecmascript::scope()
883 QDeclarativeComponent component(&engine, TEST_FILE("scope.qml"));
884 QObject *object = component.create();
885 QVERIFY(object != 0);
887 QCOMPARE(object->property("test1").toInt(), 1);
888 QCOMPARE(object->property("test2").toInt(), 2);
889 QCOMPARE(object->property("test3").toString(), QString("1Test"));
890 QCOMPARE(object->property("test4").toString(), QString("2Test"));
891 QCOMPARE(object->property("test5").toInt(), 1);
892 QCOMPARE(object->property("test6").toInt(), 1);
893 QCOMPARE(object->property("test7").toInt(), 2);
894 QCOMPARE(object->property("test8").toInt(), 2);
895 QCOMPARE(object->property("test9").toInt(), 1);
896 QCOMPARE(object->property("test10").toInt(), 3);
902 QDeclarativeComponent component(&engine, TEST_FILE("scope.2.qml"));
903 QObject *object = component.create();
904 QVERIFY(object != 0);
906 QCOMPARE(object->property("test1").toInt(), 19);
907 QCOMPARE(object->property("test2").toInt(), 19);
908 QCOMPARE(object->property("test3").toInt(), 14);
909 QCOMPARE(object->property("test4").toInt(), 14);
910 QCOMPARE(object->property("test5").toInt(), 24);
911 QCOMPARE(object->property("test6").toInt(), 24);
917 QDeclarativeComponent component(&engine, TEST_FILE("scope.3.qml"));
918 QObject *object = component.create();
919 QVERIFY(object != 0);
921 QCOMPARE(object->property("test1").toBool(), true);
922 QCOMPARE(object->property("test2").toBool(), true);
923 QCOMPARE(object->property("test3").toBool(), true);
928 // Signal argument scope
930 QDeclarativeComponent component(&engine, TEST_FILE("scope.4.qml"));
931 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
932 QVERIFY(object != 0);
934 QCOMPARE(object->property("test").toInt(), 0);
935 QCOMPARE(object->property("test2").toString(), QString());
937 emit object->argumentSignal(13, "Argument Scope", 9, MyQmlObject::EnumValue4, Qt::RightButton);
939 QCOMPARE(object->property("test").toInt(), 13);
940 QCOMPARE(object->property("test2").toString(), QString("Argument Scope"));
946 QDeclarativeComponent component(&engine, TEST_FILE("scope.5.qml"));
947 QObject *object = component.create();
948 QVERIFY(object != 0);
950 QCOMPARE(object->property("test1").toBool(), true);
951 QCOMPARE(object->property("test2").toBool(), true);
957 QDeclarativeComponent component(&engine, TEST_FILE("scope.6.qml"));
958 QObject *object = component.create();
959 QVERIFY(object != 0);
961 QCOMPARE(object->property("test").toBool(), true);
967 // In 4.7, non-library javascript files that had no imports shared the imports of their
969 void tst_qdeclarativeecmascript::importScope()
971 QDeclarativeComponent component(&engine, TEST_FILE("importScope.qml"));
972 QObject *o = component.create();
975 QCOMPARE(o->property("test").toInt(), 240);
981 Tests that "any" type passes through a synthesized signal parameter. This
982 is essentially a test of QDeclarativeMetaType::copy()
984 void tst_qdeclarativeecmascript::signalParameterTypes()
986 QDeclarativeComponent component(&engine, TEST_FILE("signalParameterTypes.qml"));
987 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
988 QVERIFY(object != 0);
990 emit object->basicSignal();
992 QCOMPARE(object->property("intProperty").toInt(), 10);
993 QCOMPARE(object->property("realProperty").toReal(), 19.2);
994 QVERIFY(object->property("colorProperty").value<QColor>() == QColor(255, 255, 0, 255));
995 QVERIFY(object->property("variantProperty") == QVariant::fromValue(QColor(255, 0, 255, 255)));
996 QVERIFY(object->property("enumProperty") == MyQmlObject::EnumValue3);
997 QVERIFY(object->property("qtEnumProperty") == Qt::LeftButton);
1003 Test that two JS objects for the same QObject compare as equal.
1005 void tst_qdeclarativeecmascript::objectsCompareAsEqual()
1007 QDeclarativeComponent component(&engine, TEST_FILE("objectsCompareAsEqual.qml"));
1008 QObject *object = component.create();
1009 QVERIFY(object != 0);
1011 QCOMPARE(object->property("test1").toBool(), true);
1012 QCOMPARE(object->property("test2").toBool(), true);
1013 QCOMPARE(object->property("test3").toBool(), true);
1014 QCOMPARE(object->property("test4").toBool(), true);
1015 QCOMPARE(object->property("test5").toBool(), true);
1021 Confirm bindings and alias properties can coexist.
1023 Tests for a regression where the binding would not reevaluate.
1025 void tst_qdeclarativeecmascript::aliasPropertyAndBinding()
1027 QDeclarativeComponent component(&engine, TEST_FILE("aliasPropertyAndBinding.qml"));
1028 QObject *object = component.create();
1029 QVERIFY(object != 0);
1031 QCOMPARE(object->property("c2").toInt(), 3);
1032 QCOMPARE(object->property("c3").toInt(), 3);
1034 object->setProperty("c2", QVariant(19));
1036 QCOMPARE(object->property("c2").toInt(), 19);
1037 QCOMPARE(object->property("c3").toInt(), 19);
1043 Ensure that we can write undefined value to an alias property,
1044 and that the aliased property is reset correctly if possible.
1046 void tst_qdeclarativeecmascript::aliasPropertyReset()
1048 QObject *object = 0;
1050 // test that a manual write (of undefined) to a resettable aliased property succeeds
1051 QDeclarativeComponent c1(&engine, TEST_FILE("aliasreset/aliasPropertyReset.1.qml"));
1052 object = c1.create();
1053 QVERIFY(object != 0);
1054 QVERIFY(object->property("sourceComponentAlias").value<QDeclarativeComponent*>() != 0);
1055 QCOMPARE(object->property("aliasIsUndefined"), QVariant(false));
1056 QMetaObject::invokeMethod(object, "resetAliased");
1057 QVERIFY(object->property("sourceComponentAlias").value<QDeclarativeComponent*>() == 0);
1058 QCOMPARE(object->property("aliasIsUndefined"), QVariant(true));
1061 // test that a manual write (of undefined) to a resettable alias property succeeds
1062 QDeclarativeComponent c2(&engine, TEST_FILE("aliasreset/aliasPropertyReset.2.qml"));
1063 object = c2.create();
1064 QVERIFY(object != 0);
1065 QVERIFY(object->property("sourceComponentAlias").value<QDeclarativeComponent*>() != 0);
1066 QCOMPARE(object->property("loaderSourceComponentIsUndefined"), QVariant(false));
1067 QMetaObject::invokeMethod(object, "resetAlias");
1068 QVERIFY(object->property("sourceComponentAlias").value<QDeclarativeComponent*>() == 0);
1069 QCOMPARE(object->property("loaderSourceComponentIsUndefined"), QVariant(true));
1072 // test that an alias to a bound property works correctly
1073 QDeclarativeComponent c3(&engine, TEST_FILE("aliasreset/aliasPropertyReset.3.qml"));
1074 object = c3.create();
1075 QVERIFY(object != 0);
1076 QVERIFY(object->property("sourceComponentAlias").value<QDeclarativeComponent*>() != 0);
1077 QCOMPARE(object->property("loaderOneSourceComponentIsUndefined"), QVariant(false));
1078 QCOMPARE(object->property("loaderTwoSourceComponentIsUndefined"), QVariant(false));
1079 QMetaObject::invokeMethod(object, "resetAlias");
1080 QVERIFY(object->property("sourceComponentAlias").value<QDeclarativeComponent*>() == 0);
1081 QCOMPARE(object->property("loaderOneSourceComponentIsUndefined"), QVariant(true));
1082 QCOMPARE(object->property("loaderTwoSourceComponentIsUndefined"), QVariant(false));
1085 // test that a manual write (of undefined) to a resettable alias property
1086 // whose aliased property's object has been deleted, does not crash.
1087 QDeclarativeComponent c4(&engine, TEST_FILE("aliasreset/aliasPropertyReset.4.qml"));
1088 object = c4.create();
1089 QVERIFY(object != 0);
1090 QVERIFY(object->property("sourceComponentAlias").value<QDeclarativeComponent*>() != 0);
1091 QObject *loader = object->findChild<QObject*>("loader");
1092 QVERIFY(loader != 0);
1094 QVERIFY(object->property("sourceComponentAlias").value<QDeclarativeComponent*>() == 0); // deletion should have caused value unset.
1095 QMetaObject::invokeMethod(object, "resetAlias"); // shouldn't crash.
1096 QVERIFY(object->property("sourceComponentAlias").value<QDeclarativeComponent*>() == 0);
1097 QMetaObject::invokeMethod(object, "setAlias"); // shouldn't crash, and shouldn't change value (since it's no longer referencing anything).
1098 QVERIFY(object->property("sourceComponentAlias").value<QDeclarativeComponent*>() == 0);
1101 // test that binding an alias property to an undefined value works correctly
1102 QDeclarativeComponent c5(&engine, TEST_FILE("aliasreset/aliasPropertyReset.5.qml"));
1103 object = c5.create();
1104 QVERIFY(object != 0);
1105 QVERIFY(object->property("sourceComponentAlias").value<QDeclarativeComponent*>() == 0); // bound to undefined value.
1108 // test that a manual write (of undefined) to a non-resettable property fails properly
1109 QUrl url = TEST_FILE("aliasreset/aliasPropertyReset.error.1.qml");
1110 QString warning1 = url.toString() + QLatin1String(":15: Error: Cannot assign [undefined] to int");
1111 QDeclarativeComponent e1(&engine, url);
1112 object = e1.create();
1113 QVERIFY(object != 0);
1114 QCOMPARE(object->property("intAlias").value<int>(), 12);
1115 QCOMPARE(object->property("aliasedIntIsUndefined"), QVariant(false));
1116 QTest::ignoreMessage(QtWarningMsg, warning1.toLatin1().constData());
1117 QMetaObject::invokeMethod(object, "resetAlias");
1118 QCOMPARE(object->property("intAlias").value<int>(), 12);
1119 QCOMPARE(object->property("aliasedIntIsUndefined"), QVariant(false));
1123 void tst_qdeclarativeecmascript::dynamicCreation_data()
1125 QTest::addColumn<QString>("method");
1126 QTest::addColumn<QString>("createdName");
1128 QTest::newRow("One") << "createOne" << "objectOne";
1129 QTest::newRow("Two") << "createTwo" << "objectTwo";
1130 QTest::newRow("Three") << "createThree" << "objectThree";
1134 Test using createQmlObject to dynamically generate an item
1135 Also using createComponent is tested.
1137 void tst_qdeclarativeecmascript::dynamicCreation()
1139 QFETCH(QString, method);
1140 QFETCH(QString, createdName);
1142 QDeclarativeComponent component(&engine, TEST_FILE("dynamicCreation.qml"));
1143 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1144 QVERIFY(object != 0);
1146 QMetaObject::invokeMethod(object, method.toUtf8());
1147 QObject *created = object->objectProperty();
1149 QCOMPARE(created->objectName(), createdName);
1155 Tests the destroy function
1157 void tst_qdeclarativeecmascript::dynamicDestruction()
1160 QDeclarativeComponent component(&engine, TEST_FILE("dynamicDeletion.qml"));
1161 QDeclarativeGuard<MyQmlObject> object = qobject_cast<MyQmlObject*>(component.create());
1162 QVERIFY(object != 0);
1163 QDeclarativeGuard<QObject> createdQmlObject = 0;
1165 QMetaObject::invokeMethod(object, "create");
1166 createdQmlObject = object->objectProperty();
1167 QVERIFY(createdQmlObject);
1168 QCOMPARE(createdQmlObject->objectName(), QString("emptyObject"));
1170 QMetaObject::invokeMethod(object, "killOther");
1171 QVERIFY(createdQmlObject);
1172 QCoreApplication::instance()->processEvents(QEventLoop::DeferredDeletion);
1173 QVERIFY(createdQmlObject);
1174 for (int ii = 0; createdQmlObject && ii < 50; ++ii) { // After 5 seconds we should give up
1175 if (createdQmlObject) {
1177 QCoreApplication::instance()->processEvents(QEventLoop::DeferredDeletion);
1180 QVERIFY(!createdQmlObject);
1182 QDeclarativeEngine::setObjectOwnership(object, QDeclarativeEngine::JavaScriptOwnership);
1183 QMetaObject::invokeMethod(object, "killMe");
1186 QCoreApplication::instance()->processEvents(QEventLoop::DeferredDeletion);
1191 QDeclarativeComponent component(&engine, TEST_FILE("dynamicDeletion.2.qml"));
1192 QObject *o = component.create();
1195 QVERIFY(qvariant_cast<QObject*>(o->property("objectProperty")) == 0);
1197 QMetaObject::invokeMethod(o, "create");
1199 QVERIFY(qvariant_cast<QObject*>(o->property("objectProperty")) != 0);
1201 QMetaObject::invokeMethod(o, "destroy");
1203 QCoreApplication::instance()->processEvents(QEventLoop::DeferredDeletion);
1205 QVERIFY(qvariant_cast<QObject*>(o->property("objectProperty")) == 0);
1212 tests that id.toString() works
1214 void tst_qdeclarativeecmascript::objectToString()
1216 QDeclarativeComponent component(&engine, TEST_FILE("declarativeToString.qml"));
1217 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1218 QVERIFY(object != 0);
1219 QMetaObject::invokeMethod(object, "testToString");
1220 QVERIFY(object->stringProperty().startsWith("MyQmlObject_QML_"));
1221 QVERIFY(object->stringProperty().endsWith(", \"objName\")"));
1227 tests that id.hasOwnProperty() works
1229 void tst_qdeclarativeecmascript::objectHasOwnProperty()
1231 QUrl url = TEST_FILE("declarativeHasOwnProperty.qml");
1232 QString warning1 = url.toString() + ":59: TypeError: Cannot call method 'hasOwnProperty' of undefined";
1233 QString warning2 = url.toString() + ":64: TypeError: Cannot call method 'hasOwnProperty' of undefined";
1234 QString warning3 = url.toString() + ":69: TypeError: Cannot call method 'hasOwnProperty' of undefined";
1236 QDeclarativeComponent component(&engine, url);
1237 QObject *object = component.create();
1238 QVERIFY(object != 0);
1240 // test QObjects in QML
1241 QMetaObject::invokeMethod(object, "testHasOwnPropertySuccess");
1242 QVERIFY(object->property("result").value<bool>() == true);
1243 QMetaObject::invokeMethod(object, "testHasOwnPropertyFailure");
1244 QVERIFY(object->property("result").value<bool>() == false);
1246 // now test other types in QML
1247 QObject *child = object->findChild<QObject*>("typeObj");
1248 QVERIFY(child != 0);
1249 QMetaObject::invokeMethod(child, "testHasOwnPropertySuccess");
1250 QCOMPARE(child->property("valueTypeHasOwnProperty").toBool(), true);
1251 QCOMPARE(child->property("valueTypeHasOwnProperty2").toBool(), true);
1252 QCOMPARE(child->property("variantTypeHasOwnProperty").toBool(), true);
1253 QCOMPARE(child->property("stringTypeHasOwnProperty").toBool(), true);
1254 QCOMPARE(child->property("listTypeHasOwnProperty").toBool(), true);
1255 QCOMPARE(child->property("emptyListTypeHasOwnProperty").toBool(), true);
1256 QCOMPARE(child->property("enumTypeHasOwnProperty").toBool(), true);
1257 QCOMPARE(child->property("typenameHasOwnProperty").toBool(), true);
1258 QCOMPARE(child->property("typenameHasOwnProperty2").toBool(), true);
1259 QCOMPARE(child->property("moduleApiTypeHasOwnProperty").toBool(), true);
1260 QCOMPARE(child->property("moduleApiPropertyTypeHasOwnProperty").toBool(), true);
1262 QTest::ignoreMessage(QtWarningMsg, warning1.toLatin1().constData());
1263 QMetaObject::invokeMethod(child, "testHasOwnPropertyFailureOne");
1264 QCOMPARE(child->property("enumNonValueHasOwnProperty").toBool(), false);
1265 QTest::ignoreMessage(QtWarningMsg, warning2.toLatin1().constData());
1266 QMetaObject::invokeMethod(child, "testHasOwnPropertyFailureTwo");
1267 QCOMPARE(child->property("moduleApiNonPropertyHasOwnProperty").toBool(), false);
1268 QTest::ignoreMessage(QtWarningMsg, warning3.toLatin1().constData());
1269 QMetaObject::invokeMethod(child, "testHasOwnPropertyFailureThree");
1270 QCOMPARE(child->property("listAtInvalidHasOwnProperty").toBool(), false);
1276 Tests bindings that indirectly cause their own deletion work.
1278 This test is best run under valgrind to ensure no invalid memory access occur.
1280 void tst_qdeclarativeecmascript::selfDeletingBinding()
1283 QDeclarativeComponent component(&engine, TEST_FILE("selfDeletingBinding.qml"));
1284 QObject *object = component.create();
1285 QVERIFY(object != 0);
1286 object->setProperty("triggerDelete", true);
1291 QDeclarativeComponent component(&engine, TEST_FILE("selfDeletingBinding.2.qml"));
1292 QObject *object = component.create();
1293 QVERIFY(object != 0);
1294 object->setProperty("triggerDelete", true);
1300 Test that extended object properties can be accessed.
1302 This test a regression where this used to crash. The issue was specificially
1303 for extended objects that did not include a synthesized meta object (so non-root
1304 and no synthesiszed properties).
1306 void tst_qdeclarativeecmascript::extendedObjectPropertyLookup()
1308 QDeclarativeComponent component(&engine, TEST_FILE("extendedObjectPropertyLookup.qml"));
1309 QObject *object = component.create();
1310 QVERIFY(object != 0);
1315 Test file/lineNumbers for binding/Script errors.
1317 void tst_qdeclarativeecmascript::scriptErrors()
1319 QDeclarativeComponent component(&engine, TEST_FILE("scriptErrors.qml"));
1320 QString url = component.url().toString();
1322 QString warning1 = url.left(url.length() - 3) + "js:2: Error: Invalid write to global property \"a\"";
1323 QString warning2 = url + ":5: ReferenceError: Can't find variable: a";
1324 QString warning3 = url.left(url.length() - 3) + "js:4: Error: Invalid write to global property \"a\"";
1325 QString warning4 = url + ":10: ReferenceError: Can't find variable: a";
1326 QString warning5 = url + ":8: ReferenceError: Can't find variable: a";
1327 QString warning6 = url + ":7: Unable to assign [undefined] to int x";
1328 QString warning7 = url + ":12: Error: Cannot assign to read-only property \"trueProperty\"";
1329 QString warning8 = url + ":13: Error: Cannot assign to non-existent property \"fakeProperty\"";
1331 QTest::ignoreMessage(QtWarningMsg, warning1.toLatin1().constData());
1332 QTest::ignoreMessage(QtWarningMsg, warning2.toLatin1().constData());
1333 QTest::ignoreMessage(QtWarningMsg, warning3.toLatin1().constData());
1334 QTest::ignoreMessage(QtWarningMsg, warning5.toLatin1().constData());
1335 QTest::ignoreMessage(QtWarningMsg, warning6.toLatin1().constData());
1336 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
1337 QVERIFY(object != 0);
1339 QTest::ignoreMessage(QtWarningMsg, warning4.toLatin1().constData());
1340 emit object->basicSignal();
1342 QTest::ignoreMessage(QtWarningMsg, warning7.toLatin1().constData());
1343 emit object->anotherBasicSignal();
1345 QTest::ignoreMessage(QtWarningMsg, warning8.toLatin1().constData());
1346 emit object->thirdBasicSignal();
1352 Test file/lineNumbers for inline functions.
1354 void tst_qdeclarativeecmascript::functionErrors()
1356 QDeclarativeComponent component(&engine, TEST_FILE("functionErrors.qml"));
1357 QString url = component.url().toString();
1359 QString warning = url + ":5: Error: Invalid write to global property \"a\"";
1361 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
1363 QObject *object = component.create();
1364 QVERIFY(object != 0);
1367 // test that if an exception occurs while invoking js function from cpp, it is reported as expected.
1368 QDeclarativeComponent componentTwo(&engine, TEST_FILE("scarceresources/scarceResourceFunctionFail.qml"));
1369 url = componentTwo.url().toString();
1370 object = componentTwo.create();
1371 QVERIFY(object != 0);
1373 QString srpname = object->property("srp_name").toString();
1375 warning = url + QLatin1String(":17: TypeError: Property 'scarceResource' of object ") + srpname +
1376 QLatin1String(" is not a function");
1377 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData()); // we expect a meaningful warning to be printed.
1378 QMetaObject::invokeMethod(object, "retrieveScarceResource");
1383 Test various errors that can occur when assigning a property from script
1385 void tst_qdeclarativeecmascript::propertyAssignmentErrors()
1387 QDeclarativeComponent component(&engine, TEST_FILE("propertyAssignmentErrors.qml"));
1389 QString url = component.url().toString();
1391 QObject *object = component.create();
1392 QVERIFY(object != 0);
1394 QCOMPARE(object->property("test1").toBool(), true);
1395 QCOMPARE(object->property("test2").toBool(), true);
1401 Test bindings still work when the reeval is triggered from within
1404 void tst_qdeclarativeecmascript::signalTriggeredBindings()
1406 QDeclarativeComponent component(&engine, TEST_FILE("signalTriggeredBindings.qml"));
1407 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1408 QVERIFY(object != 0);
1410 QCOMPARE(object->property("base").toReal(), 50.);
1411 QCOMPARE(object->property("test1").toReal(), 50.);
1412 QCOMPARE(object->property("test2").toReal(), 50.);
1414 object->basicSignal();
1416 QCOMPARE(object->property("base").toReal(), 200.);
1417 QCOMPARE(object->property("test1").toReal(), 200.);
1418 QCOMPARE(object->property("test2").toReal(), 200.);
1420 object->argumentSignal(10, QString(), 10, MyQmlObject::EnumValue4, Qt::RightButton);
1422 QCOMPARE(object->property("base").toReal(), 400.);
1423 QCOMPARE(object->property("test1").toReal(), 400.);
1424 QCOMPARE(object->property("test2").toReal(), 400.);
1430 Test that list properties can be iterated from ECMAScript
1432 void tst_qdeclarativeecmascript::listProperties()
1434 QDeclarativeComponent component(&engine, TEST_FILE("listProperties.qml"));
1435 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1436 QVERIFY(object != 0);
1438 QCOMPARE(object->property("test1").toInt(), 21);
1439 QCOMPARE(object->property("test2").toInt(), 2);
1440 QCOMPARE(object->property("test3").toBool(), true);
1441 QCOMPARE(object->property("test4").toBool(), true);
1446 void tst_qdeclarativeecmascript::exceptionClearsOnReeval()
1448 QDeclarativeComponent component(&engine, TEST_FILE("exceptionClearsOnReeval.qml"));
1449 QString url = component.url().toString();
1451 QString warning = url + ":4: TypeError: Cannot read property 'objectProperty' of null";
1453 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
1454 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1455 QVERIFY(object != 0);
1457 QCOMPARE(object->property("test").toBool(), false);
1459 MyQmlObject object2;
1460 MyQmlObject object3;
1461 object2.setObjectProperty(&object3);
1462 object->setObjectProperty(&object2);
1464 QCOMPARE(object->property("test").toBool(), true);
1469 void tst_qdeclarativeecmascript::exceptionSlotProducesWarning()
1471 QDeclarativeComponent component(&engine, TEST_FILE("exceptionProducesWarning.qml"));
1472 QString url = component.url().toString();
1474 QString warning = component.url().toString() + ":6: Error: JS exception";
1476 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
1477 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1478 QVERIFY(object != 0);
1482 void tst_qdeclarativeecmascript::exceptionBindingProducesWarning()
1484 QDeclarativeComponent component(&engine, TEST_FILE("exceptionProducesWarning2.qml"));
1485 QString url = component.url().toString();
1487 QString warning = component.url().toString() + ":5: Error: JS exception";
1489 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
1490 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1491 QVERIFY(object != 0);
1495 static int transientErrorsMsgCount = 0;
1496 static void transientErrorsMsgHandler(QtMsgType, const char *)
1498 ++transientErrorsMsgCount;
1501 // Check that transient binding errors are not displayed
1502 void tst_qdeclarativeecmascript::transientErrors()
1505 QDeclarativeComponent component(&engine, TEST_FILE("transientErrors.qml"));
1507 transientErrorsMsgCount = 0;
1508 QtMsgHandler old = qInstallMsgHandler(transientErrorsMsgHandler);
1510 QObject *object = component.create();
1511 QVERIFY(object != 0);
1513 qInstallMsgHandler(old);
1515 QCOMPARE(transientErrorsMsgCount, 0);
1520 // One binding erroring multiple times, but then resolving
1522 QDeclarativeComponent component(&engine, TEST_FILE("transientErrors.2.qml"));
1524 transientErrorsMsgCount = 0;
1525 QtMsgHandler old = qInstallMsgHandler(transientErrorsMsgHandler);
1527 QObject *object = component.create();
1528 QVERIFY(object != 0);
1530 qInstallMsgHandler(old);
1532 QCOMPARE(transientErrorsMsgCount, 0);
1538 // Check that errors during shutdown are minimized
1539 void tst_qdeclarativeecmascript::shutdownErrors()
1541 QDeclarativeComponent component(&engine, TEST_FILE("shutdownErrors.qml"));
1542 QObject *object = component.create();
1543 QVERIFY(object != 0);
1545 transientErrorsMsgCount = 0;
1546 QtMsgHandler old = qInstallMsgHandler(transientErrorsMsgHandler);
1550 qInstallMsgHandler(old);
1551 QCOMPARE(transientErrorsMsgCount, 0);
1554 void tst_qdeclarativeecmascript::compositePropertyType()
1556 QDeclarativeComponent component(&engine, TEST_FILE("compositePropertyType.qml"));
1557 QTest::ignoreMessage(QtDebugMsg, "hello world");
1558 QObject *object = qobject_cast<QObject *>(component.create());
1563 void tst_qdeclarativeecmascript::jsObject()
1565 QDeclarativeComponent component(&engine, TEST_FILE("jsObject.qml"));
1566 QObject *object = component.create();
1567 QVERIFY(object != 0);
1569 QCOMPARE(object->property("test").toInt(), 92);
1574 void tst_qdeclarativeecmascript::undefinedResetsProperty()
1577 QDeclarativeComponent component(&engine, TEST_FILE("undefinedResetsProperty.qml"));
1578 QObject *object = component.create();
1579 QVERIFY(object != 0);
1581 QCOMPARE(object->property("resettableProperty").toInt(), 92);
1583 object->setProperty("setUndefined", true);
1585 QCOMPARE(object->property("resettableProperty").toInt(), 13);
1587 object->setProperty("setUndefined", false);
1589 QCOMPARE(object->property("resettableProperty").toInt(), 92);
1594 QDeclarativeComponent component(&engine, TEST_FILE("undefinedResetsProperty.2.qml"));
1595 QObject *object = component.create();
1596 QVERIFY(object != 0);
1598 QCOMPARE(object->property("resettableProperty").toInt(), 19);
1600 QMetaObject::invokeMethod(object, "doReset");
1602 QCOMPARE(object->property("resettableProperty").toInt(), 13);
1609 void tst_qdeclarativeecmascript::bug1()
1611 QDeclarativeComponent component(&engine, TEST_FILE("bug.1.qml"));
1612 QObject *object = component.create();
1613 QVERIFY(object != 0);
1615 QCOMPARE(object->property("test").toInt(), 14);
1617 object->setProperty("a", 11);
1619 QCOMPARE(object->property("test").toInt(), 3);
1621 object->setProperty("b", true);
1623 QCOMPARE(object->property("test").toInt(), 9);
1628 void tst_qdeclarativeecmascript::bug2()
1630 QDeclarativeComponent component(&engine);
1631 component.setData("import Qt.test 1.0;\nQPlainTextEdit { width: 100 }", QUrl());
1633 QObject *object = component.create();
1634 QVERIFY(object != 0);
1639 // Don't crash in createObject when the component has errors.
1640 void tst_qdeclarativeecmascript::dynamicCreationCrash()
1642 QDeclarativeComponent component(&engine, TEST_FILE("dynamicCreation.qml"));
1643 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1644 QVERIFY(object != 0);
1646 QTest::ignoreMessage(QtWarningMsg, "QDeclarativeComponent: Component is not ready");
1647 QMetaObject::invokeMethod(object, "dontCrash");
1648 QObject *created = object->objectProperty();
1649 QVERIFY(created == 0);
1655 void tst_qdeclarativeecmascript::regExpBug()
1657 QDeclarativeComponent component(&engine, TEST_FILE("regExp.qml"));
1658 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1659 QVERIFY(object != 0);
1660 QCOMPARE(object->regExp().pattern(), QLatin1String("[a-zA-z]"));
1664 static inline bool evaluate_error(QV8Engine *engine, v8::Handle<v8::Object> o, const char *source)
1666 QString functionSource = QLatin1String("(function(object) { return ") +
1667 QLatin1String(source) + QLatin1String(" })");
1669 v8::Local<v8::Script> program = v8::Script::Compile(engine->toString(functionSource));
1672 v8::Handle<v8::Function> function = v8::Handle<v8::Function>::Cast(program->Run());
1673 if (function.IsEmpty())
1675 v8::Handle<v8::Value> args[] = { o };
1676 function->Call(engine->global(), 1, args);
1677 return tc.HasCaught();
1680 static inline bool evaluate_value(QV8Engine *engine, v8::Handle<v8::Object> o,
1681 const char *source, v8::Handle<v8::Value> result)
1683 QString functionSource = QLatin1String("(function(object) { return ") +
1684 QLatin1String(source) + QLatin1String(" })");
1686 v8::Local<v8::Script> program = v8::Script::Compile(engine->toString(functionSource));
1689 v8::Handle<v8::Function> function = v8::Handle<v8::Function>::Cast(program->Run());
1690 if (function.IsEmpty())
1692 v8::Handle<v8::Value> args[] = { o };
1694 v8::Handle<v8::Value> value = function->Call(engine->global(), 1, args);
1699 return value->StrictEquals(result);
1702 static inline v8::Handle<v8::Value> evaluate(QV8Engine *engine, v8::Handle<v8::Object> o,
1705 QString functionSource = QLatin1String("(function(object) { return ") +
1706 QLatin1String(source) + QLatin1String(" })");
1708 v8::Local<v8::Script> program = v8::Script::Compile(engine->toString(functionSource));
1710 return v8::Handle<v8::Value>();
1711 v8::Handle<v8::Function> function = v8::Handle<v8::Function>::Cast(program->Run());
1712 if (function.IsEmpty())
1713 return v8::Handle<v8::Value>();
1714 v8::Handle<v8::Value> args[] = { o };
1716 v8::Handle<v8::Value> value = function->Call(engine->global(), 1, args);
1719 return v8::Handle<v8::Value>();
1723 #define EVALUATE_ERROR(source) evaluate_error(engine, object, source)
1724 #define EVALUATE_VALUE(source, result) evaluate_value(engine, object, source, result)
1725 #define EVALUATE(source) evaluate(engine, object, source)
1727 void tst_qdeclarativeecmascript::callQtInvokables()
1729 MyInvokableObject o;
1731 QDeclarativeEngine qmlengine;
1732 QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(&qmlengine);
1734 QV8Engine *engine = ep->v8engine();
1736 v8::HandleScope handle_scope;
1737 v8::Context::Scope scope(engine->context());
1739 v8::Local<v8::Object> object = engine->newQObject(&o)->ToObject();
1741 // Non-existent methods
1743 QVERIFY(EVALUATE_ERROR("object.method_nonexistent()"));
1744 QCOMPARE(o.error(), false);
1745 QCOMPARE(o.invoked(), -1);
1746 QCOMPARE(o.actuals().count(), 0);
1749 QVERIFY(EVALUATE_ERROR("object.method_nonexistent(10, 11)"));
1750 QCOMPARE(o.error(), false);
1751 QCOMPARE(o.invoked(), -1);
1752 QCOMPARE(o.actuals().count(), 0);
1754 // Insufficient arguments
1756 QVERIFY(EVALUATE_ERROR("object.method_int()"));
1757 QCOMPARE(o.error(), false);
1758 QCOMPARE(o.invoked(), -1);
1759 QCOMPARE(o.actuals().count(), 0);
1762 QVERIFY(EVALUATE_ERROR("object.method_intint(10)"));
1763 QCOMPARE(o.error(), false);
1764 QCOMPARE(o.invoked(), -1);
1765 QCOMPARE(o.actuals().count(), 0);
1767 // Excessive arguments
1769 QVERIFY(EVALUATE_VALUE("object.method_int(10, 11)", v8::Undefined()));
1770 QCOMPARE(o.error(), false);
1771 QCOMPARE(o.invoked(), 8);
1772 QCOMPARE(o.actuals().count(), 1);
1773 QCOMPARE(o.actuals().at(0), QVariant(10));
1776 QVERIFY(EVALUATE_VALUE("object.method_intint(10, 11, 12)", v8::Undefined()));
1777 QCOMPARE(o.error(), false);
1778 QCOMPARE(o.invoked(), 9);
1779 QCOMPARE(o.actuals().count(), 2);
1780 QCOMPARE(o.actuals().at(0), QVariant(10));
1781 QCOMPARE(o.actuals().at(1), QVariant(11));
1783 // Test return types
1785 QVERIFY(EVALUATE_VALUE("object.method_NoArgs()", v8::Undefined()));
1786 QCOMPARE(o.error(), false);
1787 QCOMPARE(o.invoked(), 0);
1788 QCOMPARE(o.actuals().count(), 0);
1791 QVERIFY(EVALUATE_VALUE("object.method_NoArgs_int()", v8::Integer::New(6)));
1792 QCOMPARE(o.error(), false);
1793 QCOMPARE(o.invoked(), 1);
1794 QCOMPARE(o.actuals().count(), 0);
1797 QVERIFY(EVALUATE_VALUE("object.method_NoArgs_real()", v8::Number::New(19.75)));
1798 QCOMPARE(o.error(), false);
1799 QCOMPARE(o.invoked(), 2);
1800 QCOMPARE(o.actuals().count(), 0);
1804 v8::Handle<v8::Value> ret = EVALUATE("object.method_NoArgs_QPointF()");
1805 QVERIFY(!ret.IsEmpty());
1806 QCOMPARE(engine->toVariant(ret, -1), QVariant(QPointF(123, 4.5)));
1807 QCOMPARE(o.error(), false);
1808 QCOMPARE(o.invoked(), 3);
1809 QCOMPARE(o.actuals().count(), 0);
1814 v8::Handle<v8::Value> ret = EVALUATE("object.method_NoArgs_QObject()");
1815 QCOMPARE(engine->toQObject(ret), (QObject *)&o);
1816 QCOMPARE(o.error(), false);
1817 QCOMPARE(o.invoked(), 4);
1818 QCOMPARE(o.actuals().count(), 0);
1822 QVERIFY(EVALUATE_VALUE("object.method_NoArgs_unknown()", v8::Undefined()));
1823 QCOMPARE(o.error(), false);
1824 QCOMPARE(o.invoked(), 5);
1825 QCOMPARE(o.actuals().count(), 0);
1829 v8::Handle<v8::Value> ret = EVALUATE("object.method_NoArgs_QScriptValue()");
1830 QVERIFY(ret->IsString());
1831 QCOMPARE(engine->toString(ret), QString("Hello world"));
1832 QCOMPARE(o.error(), false);
1833 QCOMPARE(o.invoked(), 6);
1834 QCOMPARE(o.actuals().count(), 0);
1838 QVERIFY(EVALUATE_VALUE("object.method_NoArgs_QVariant()", engine->toString("QML rocks")));
1839 QCOMPARE(o.error(), false);
1840 QCOMPARE(o.invoked(), 7);
1841 QCOMPARE(o.actuals().count(), 0);
1845 QVERIFY(EVALUATE_VALUE("object.method_int(94)", v8::Undefined()));
1846 QCOMPARE(o.error(), false);
1847 QCOMPARE(o.invoked(), 8);
1848 QCOMPARE(o.actuals().count(), 1);
1849 QCOMPARE(o.actuals().at(0), QVariant(94));
1852 QVERIFY(EVALUATE_VALUE("object.method_int(\"94\")", v8::Undefined()));
1853 QCOMPARE(o.error(), false);
1854 QCOMPARE(o.invoked(), 8);
1855 QCOMPARE(o.actuals().count(), 1);
1856 QCOMPARE(o.actuals().at(0), QVariant(94));
1859 QVERIFY(EVALUATE_VALUE("object.method_int(\"not a number\")", v8::Undefined()));
1860 QCOMPARE(o.error(), false);
1861 QCOMPARE(o.invoked(), 8);
1862 QCOMPARE(o.actuals().count(), 1);
1863 QCOMPARE(o.actuals().at(0), QVariant(0));
1866 QVERIFY(EVALUATE_VALUE("object.method_int(null)", v8::Undefined()));
1867 QCOMPARE(o.error(), false);
1868 QCOMPARE(o.invoked(), 8);
1869 QCOMPARE(o.actuals().count(), 1);
1870 QCOMPARE(o.actuals().at(0), QVariant(0));
1873 QVERIFY(EVALUATE_VALUE("object.method_int(undefined)", v8::Undefined()));
1874 QCOMPARE(o.error(), false);
1875 QCOMPARE(o.invoked(), 8);
1876 QCOMPARE(o.actuals().count(), 1);
1877 QCOMPARE(o.actuals().at(0), QVariant(0));
1880 QVERIFY(EVALUATE_VALUE("object.method_int(object)", v8::Undefined()));
1881 QCOMPARE(o.error(), false);
1882 QCOMPARE(o.invoked(), 8);
1883 QCOMPARE(o.actuals().count(), 1);
1884 QCOMPARE(o.actuals().at(0), QVariant(0));
1887 QVERIFY(EVALUATE_VALUE("object.method_intint(122, 9)", v8::Undefined()));
1888 QCOMPARE(o.error(), false);
1889 QCOMPARE(o.invoked(), 9);
1890 QCOMPARE(o.actuals().count(), 2);
1891 QCOMPARE(o.actuals().at(0), QVariant(122));
1892 QCOMPARE(o.actuals().at(1), QVariant(9));
1895 QVERIFY(EVALUATE_VALUE("object.method_real(94.3)", v8::Undefined()));
1896 QCOMPARE(o.error(), false);
1897 QCOMPARE(o.invoked(), 10);
1898 QCOMPARE(o.actuals().count(), 1);
1899 QCOMPARE(o.actuals().at(0), QVariant(94.3));
1902 QVERIFY(EVALUATE_VALUE("object.method_real(\"94.3\")", v8::Undefined()));
1903 QCOMPARE(o.error(), false);
1904 QCOMPARE(o.invoked(), 10);
1905 QCOMPARE(o.actuals().count(), 1);
1906 QCOMPARE(o.actuals().at(0), QVariant(94.3));
1909 QVERIFY(EVALUATE_VALUE("object.method_real(\"not a number\")", v8::Undefined()));
1910 QCOMPARE(o.error(), false);
1911 QCOMPARE(o.invoked(), 10);
1912 QCOMPARE(o.actuals().count(), 1);
1913 QVERIFY(qIsNaN(o.actuals().at(0).toDouble()));
1916 QVERIFY(EVALUATE_VALUE("object.method_real(null)", v8::Undefined()));
1917 QCOMPARE(o.error(), false);
1918 QCOMPARE(o.invoked(), 10);
1919 QCOMPARE(o.actuals().count(), 1);
1920 QCOMPARE(o.actuals().at(0), QVariant(0));
1923 QVERIFY(EVALUATE_VALUE("object.method_real(undefined)", v8::Undefined()));
1924 QCOMPARE(o.error(), false);
1925 QCOMPARE(o.invoked(), 10);
1926 QCOMPARE(o.actuals().count(), 1);
1927 QVERIFY(qIsNaN(o.actuals().at(0).toDouble()));
1930 QVERIFY(EVALUATE_VALUE("object.method_real(object)", v8::Undefined()));
1931 QCOMPARE(o.error(), false);
1932 QCOMPARE(o.invoked(), 10);
1933 QCOMPARE(o.actuals().count(), 1);
1934 QVERIFY(qIsNaN(o.actuals().at(0).toDouble()));
1937 QVERIFY(EVALUATE_VALUE("object.method_QString(\"Hello world\")", v8::Undefined()));
1938 QCOMPARE(o.error(), false);
1939 QCOMPARE(o.invoked(), 11);
1940 QCOMPARE(o.actuals().count(), 1);
1941 QCOMPARE(o.actuals().at(0), QVariant("Hello world"));
1944 QVERIFY(EVALUATE_VALUE("object.method_QString(19)", v8::Undefined()));
1945 QCOMPARE(o.error(), false);
1946 QCOMPARE(o.invoked(), 11);
1947 QCOMPARE(o.actuals().count(), 1);
1948 QCOMPARE(o.actuals().at(0), QVariant("19"));
1952 QString expected = "MyInvokableObject(0x" + QString::number((quintptr)&o, 16) + ")";
1953 QVERIFY(EVALUATE_VALUE("object.method_QString(object)", v8::Undefined()));
1954 QCOMPARE(o.error(), false);
1955 QCOMPARE(o.invoked(), 11);
1956 QCOMPARE(o.actuals().count(), 1);
1957 QCOMPARE(o.actuals().at(0), QVariant(expected));
1961 QVERIFY(EVALUATE_VALUE("object.method_QString(null)", v8::Undefined()));
1962 QCOMPARE(o.error(), false);
1963 QCOMPARE(o.invoked(), 11);
1964 QCOMPARE(o.actuals().count(), 1);
1965 QCOMPARE(o.actuals().at(0), QVariant(QString()));
1968 QVERIFY(EVALUATE_VALUE("object.method_QString(undefined)", v8::Undefined()));
1969 QCOMPARE(o.error(), false);
1970 QCOMPARE(o.invoked(), 11);
1971 QCOMPARE(o.actuals().count(), 1);
1972 QCOMPARE(o.actuals().at(0), QVariant(QString()));
1975 QVERIFY(EVALUATE_VALUE("object.method_QPointF(0)", v8::Undefined()));
1976 QCOMPARE(o.error(), false);
1977 QCOMPARE(o.invoked(), 12);
1978 QCOMPARE(o.actuals().count(), 1);
1979 QCOMPARE(o.actuals().at(0), QVariant(QPointF()));
1982 QVERIFY(EVALUATE_VALUE("object.method_QPointF(null)", v8::Undefined()));
1983 QCOMPARE(o.error(), false);
1984 QCOMPARE(o.invoked(), 12);
1985 QCOMPARE(o.actuals().count(), 1);
1986 QCOMPARE(o.actuals().at(0), QVariant(QPointF()));
1989 QVERIFY(EVALUATE_VALUE("object.method_QPointF(undefined)", v8::Undefined()));
1990 QCOMPARE(o.error(), false);
1991 QCOMPARE(o.invoked(), 12);
1992 QCOMPARE(o.actuals().count(), 1);
1993 QCOMPARE(o.actuals().at(0), QVariant(QPointF()));
1996 QVERIFY(EVALUATE_VALUE("object.method_QPointF(object)", v8::Undefined()));
1997 QCOMPARE(o.error(), false);
1998 QCOMPARE(o.invoked(), 12);
1999 QCOMPARE(o.actuals().count(), 1);
2000 QCOMPARE(o.actuals().at(0), QVariant(QPointF()));
2003 QVERIFY(EVALUATE_VALUE("object.method_QPointF(object.method_get_QPointF())", v8::Undefined()));
2004 QCOMPARE(o.error(), false);
2005 QCOMPARE(o.invoked(), 12);
2006 QCOMPARE(o.actuals().count(), 1);
2007 QCOMPARE(o.actuals().at(0), QVariant(QPointF(99.3, -10.2)));
2010 QVERIFY(EVALUATE_VALUE("object.method_QPointF(object.method_get_QPoint())", v8::Undefined()));
2011 QCOMPARE(o.error(), false);
2012 QCOMPARE(o.invoked(), 12);
2013 QCOMPARE(o.actuals().count(), 1);
2014 QCOMPARE(o.actuals().at(0), QVariant(QPointF(9, 12)));
2017 QVERIFY(EVALUATE_VALUE("object.method_QObject(0)", v8::Undefined()));
2018 QCOMPARE(o.error(), false);
2019 QCOMPARE(o.invoked(), 13);
2020 QCOMPARE(o.actuals().count(), 1);
2021 QCOMPARE(o.actuals().at(0), qVariantFromValue((QObject *)0));
2024 QVERIFY(EVALUATE_VALUE("object.method_QObject(\"Hello world\")", v8::Undefined()));
2025 QCOMPARE(o.error(), false);
2026 QCOMPARE(o.invoked(), 13);
2027 QCOMPARE(o.actuals().count(), 1);
2028 QCOMPARE(o.actuals().at(0), qVariantFromValue((QObject *)0));
2031 QVERIFY(EVALUATE_VALUE("object.method_QObject(null)", v8::Undefined()));
2032 QCOMPARE(o.error(), false);
2033 QCOMPARE(o.invoked(), 13);
2034 QCOMPARE(o.actuals().count(), 1);
2035 QCOMPARE(o.actuals().at(0), qVariantFromValue((QObject *)0));
2038 QVERIFY(EVALUATE_VALUE("object.method_QObject(undefined)", v8::Undefined()));
2039 QCOMPARE(o.error(), false);
2040 QCOMPARE(o.invoked(), 13);
2041 QCOMPARE(o.actuals().count(), 1);
2042 QCOMPARE(o.actuals().at(0), qVariantFromValue((QObject *)0));
2045 QVERIFY(EVALUATE_VALUE("object.method_QObject(object)", v8::Undefined()));
2046 QCOMPARE(o.error(), false);
2047 QCOMPARE(o.invoked(), 13);
2048 QCOMPARE(o.actuals().count(), 1);
2049 QCOMPARE(o.actuals().at(0), qVariantFromValue((QObject *)&o));
2052 QVERIFY(EVALUATE_VALUE("object.method_QScriptValue(null)", v8::Undefined()));
2053 QCOMPARE(o.error(), false);
2054 QCOMPARE(o.invoked(), 14);
2055 QCOMPARE(o.actuals().count(), 1);
2056 QVERIFY(qvariant_cast<QJSValue>(o.actuals().at(0)).isNull());
2059 QVERIFY(EVALUATE_VALUE("object.method_QScriptValue(undefined)", v8::Undefined()));
2060 QCOMPARE(o.error(), false);
2061 QCOMPARE(o.invoked(), 14);
2062 QCOMPARE(o.actuals().count(), 1);
2063 QVERIFY(qvariant_cast<QJSValue>(o.actuals().at(0)).isUndefined());
2066 QVERIFY(EVALUATE_VALUE("object.method_QScriptValue(19)", v8::Undefined()));
2067 QCOMPARE(o.error(), false);
2068 QCOMPARE(o.invoked(), 14);
2069 QCOMPARE(o.actuals().count(), 1);
2070 QVERIFY(qvariant_cast<QJSValue>(o.actuals().at(0)).strictlyEquals(QJSValue(19)));
2073 QVERIFY(EVALUATE_VALUE("object.method_QScriptValue([19, 20])", v8::Undefined()));
2074 QCOMPARE(o.error(), false);
2075 QCOMPARE(o.invoked(), 14);
2076 QCOMPARE(o.actuals().count(), 1);
2077 QVERIFY(qvariant_cast<QJSValue>(o.actuals().at(0)).isArray());
2080 QVERIFY(EVALUATE_VALUE("object.method_intQScriptValue(4, null)", v8::Undefined()));
2081 QCOMPARE(o.error(), false);
2082 QCOMPARE(o.invoked(), 15);
2083 QCOMPARE(o.actuals().count(), 2);
2084 QCOMPARE(o.actuals().at(0), QVariant(4));
2085 QVERIFY(qvariant_cast<QJSValue>(o.actuals().at(1)).isNull());
2088 QVERIFY(EVALUATE_VALUE("object.method_intQScriptValue(8, undefined)", v8::Undefined()));
2089 QCOMPARE(o.error(), false);
2090 QCOMPARE(o.invoked(), 15);
2091 QCOMPARE(o.actuals().count(), 2);
2092 QCOMPARE(o.actuals().at(0), QVariant(8));
2093 QVERIFY(qvariant_cast<QJSValue>(o.actuals().at(1)).isUndefined());
2096 QVERIFY(EVALUATE_VALUE("object.method_intQScriptValue(3, 19)", v8::Undefined()));
2097 QCOMPARE(o.error(), false);
2098 QCOMPARE(o.invoked(), 15);
2099 QCOMPARE(o.actuals().count(), 2);
2100 QCOMPARE(o.actuals().at(0), QVariant(3));
2101 QVERIFY(qvariant_cast<QJSValue>(o.actuals().at(1)).strictlyEquals(QJSValue(19)));
2104 QVERIFY(EVALUATE_VALUE("object.method_intQScriptValue(44, [19, 20])", v8::Undefined()));
2105 QCOMPARE(o.error(), false);
2106 QCOMPARE(o.invoked(), 15);
2107 QCOMPARE(o.actuals().count(), 2);
2108 QCOMPARE(o.actuals().at(0), QVariant(44));
2109 QVERIFY(qvariant_cast<QJSValue>(o.actuals().at(1)).isArray());
2112 QVERIFY(EVALUATE_ERROR("object.method_overload()"));
2113 QCOMPARE(o.error(), false);
2114 QCOMPARE(o.invoked(), -1);
2115 QCOMPARE(o.actuals().count(), 0);
2118 QVERIFY(EVALUATE_VALUE("object.method_overload(10)", v8::Undefined()));
2119 QCOMPARE(o.error(), false);
2120 QCOMPARE(o.invoked(), 16);
2121 QCOMPARE(o.actuals().count(), 1);
2122 QCOMPARE(o.actuals().at(0), QVariant(10));
2125 QVERIFY(EVALUATE_VALUE("object.method_overload(10, 11)", v8::Undefined()));
2126 QCOMPARE(o.error(), false);
2127 QCOMPARE(o.invoked(), 17);
2128 QCOMPARE(o.actuals().count(), 2);
2129 QCOMPARE(o.actuals().at(0), QVariant(10));
2130 QCOMPARE(o.actuals().at(1), QVariant(11));
2133 QVERIFY(EVALUATE_VALUE("object.method_overload(\"Hello\")", v8::Undefined()));
2134 QCOMPARE(o.error(), false);
2135 QCOMPARE(o.invoked(), 18);
2136 QCOMPARE(o.actuals().count(), 1);
2137 QCOMPARE(o.actuals().at(0), QVariant(QString("Hello")));
2140 QVERIFY(EVALUATE_VALUE("object.method_with_enum(9)", v8::Undefined()));
2141 QCOMPARE(o.error(), false);
2142 QCOMPARE(o.invoked(), 19);
2143 QCOMPARE(o.actuals().count(), 1);
2144 QCOMPARE(o.actuals().at(0), QVariant(9));
2147 QVERIFY(EVALUATE_VALUE("object.method_default(10)", v8::Integer::New(19)));
2148 QCOMPARE(o.error(), false);
2149 QCOMPARE(o.invoked(), 20);
2150 QCOMPARE(o.actuals().count(), 2);
2151 QCOMPARE(o.actuals().at(0), QVariant(10));
2152 QCOMPARE(o.actuals().at(1), QVariant(19));
2155 QVERIFY(EVALUATE_VALUE("object.method_default(10, 13)", v8::Integer::New(13)));
2156 QCOMPARE(o.error(), false);
2157 QCOMPARE(o.invoked(), 20);
2158 QCOMPARE(o.actuals().count(), 2);
2159 QCOMPARE(o.actuals().at(0), QVariant(10));
2160 QCOMPARE(o.actuals().at(1), QVariant(13));
2163 QVERIFY(EVALUATE_VALUE("object.method_inherited(9)", v8::Undefined()));
2164 QCOMPARE(o.error(), false);
2165 QCOMPARE(o.invoked(), -3);
2166 QCOMPARE(o.actuals().count(), 1);
2167 QCOMPARE(o.actuals().at(0), QVariant(9));
2170 QVERIFY(EVALUATE_VALUE("object.method_QVariant(9)", v8::Undefined()));
2171 QCOMPARE(o.error(), false);
2172 QCOMPARE(o.invoked(), 21);
2173 QCOMPARE(o.actuals().count(), 2);
2174 QCOMPARE(o.actuals().at(0), QVariant(9));
2175 QCOMPARE(o.actuals().at(1), QVariant());
2178 QVERIFY(EVALUATE_VALUE("object.method_QVariant(\"Hello\", \"World\")", v8::Undefined()));
2179 QCOMPARE(o.error(), false);
2180 QCOMPARE(o.invoked(), 21);
2181 QCOMPARE(o.actuals().count(), 2);
2182 QCOMPARE(o.actuals().at(0), QVariant(QString("Hello")));
2183 QCOMPARE(o.actuals().at(1), QVariant(QString("World")));
2186 // QTBUG-13047 (check that you can pass registered object types as args)
2187 void tst_qdeclarativeecmascript::invokableObjectArg()
2189 QDeclarativeComponent component(&engine, TEST_FILE("invokableObjectArg.qml"));
2191 QObject *o = component.create();
2193 MyQmlObject *qmlobject = qobject_cast<MyQmlObject *>(o);
2195 QCOMPARE(qmlobject->myinvokableObject, qmlobject);
2200 // QTBUG-13047 (check that you can return registered object types from methods)
2201 void tst_qdeclarativeecmascript::invokableObjectRet()
2203 QDeclarativeComponent component(&engine, TEST_FILE("invokableObjectRet.qml"));
2205 QObject *o = component.create();
2207 QCOMPARE(o->property("test").toBool(), true);
2212 void tst_qdeclarativeecmascript::listToVariant()
2214 QDeclarativeComponent component(&engine, TEST_FILE("listToVariant.qml"));
2216 MyQmlContainer container;
2218 QDeclarativeContext context(engine.rootContext());
2219 context.setContextObject(&container);
2221 QObject *object = component.create(&context);
2222 QVERIFY(object != 0);
2224 QVariant v = object->property("test");
2225 QCOMPARE(v.userType(), qMetaTypeId<QDeclarativeListReference>());
2226 QVERIFY(qvariant_cast<QDeclarativeListReference>(v).object() == &container);
2232 void tst_qdeclarativeecmascript::multiEngineObject()
2235 obj.setStringProperty("Howdy planet");
2237 QDeclarativeEngine e1;
2238 e1.rootContext()->setContextProperty("thing", &obj);
2239 QDeclarativeComponent c1(&e1, TEST_FILE("multiEngineObject.qml"));
2241 QDeclarativeEngine e2;
2242 e2.rootContext()->setContextProperty("thing", &obj);
2243 QDeclarativeComponent c2(&e2, TEST_FILE("multiEngineObject.qml"));
2245 QObject *o1 = c1.create();
2246 QObject *o2 = c2.create();
2248 QCOMPARE(o1->property("test").toString(), QString("Howdy planet"));
2249 QCOMPARE(o2->property("test").toString(), QString("Howdy planet"));
2255 // Test that references to QObjects are cleanup when the object is destroyed
2256 void tst_qdeclarativeecmascript::deletedObject()
2258 QDeclarativeComponent component(&engine, TEST_FILE("deletedObject.qml"));
2260 QObject *object = component.create();
2262 QCOMPARE(object->property("test1").toBool(), true);
2263 QCOMPARE(object->property("test2").toBool(), true);
2264 QCOMPARE(object->property("test3").toBool(), true);
2265 QCOMPARE(object->property("test4").toBool(), true);
2270 void tst_qdeclarativeecmascript::attachedPropertyScope()
2272 QDeclarativeComponent component(&engine, TEST_FILE("attachedPropertyScope.qml"));
2274 QObject *object = component.create();
2275 QVERIFY(object != 0);
2277 MyQmlAttachedObject *attached =
2278 qobject_cast<MyQmlAttachedObject *>(qmlAttachedPropertiesObject<MyQmlObject>(object));
2279 QVERIFY(attached != 0);
2281 QCOMPARE(object->property("value2").toInt(), 0);
2283 attached->emitMySignal();
2285 QCOMPARE(object->property("value2").toInt(), 9);
2290 void tst_qdeclarativeecmascript::scriptConnect()
2293 QDeclarativeComponent component(&engine, TEST_FILE("scriptConnect.1.qml"));
2295 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2296 QVERIFY(object != 0);
2298 QCOMPARE(object->property("test").toBool(), false);
2299 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2300 QCOMPARE(object->property("test").toBool(), true);
2306 QDeclarativeComponent component(&engine, TEST_FILE("scriptConnect.2.qml"));
2308 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2309 QVERIFY(object != 0);
2311 QCOMPARE(object->property("test").toBool(), false);
2312 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2313 QCOMPARE(object->property("test").toBool(), true);
2319 QDeclarativeComponent component(&engine, TEST_FILE("scriptConnect.3.qml"));
2321 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2322 QVERIFY(object != 0);
2324 QCOMPARE(object->property("test").toBool(), false);
2325 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2326 QCOMPARE(object->property("test").toBool(), true);
2332 QDeclarativeComponent component(&engine, TEST_FILE("scriptConnect.4.qml"));
2334 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2335 QVERIFY(object != 0);
2337 QCOMPARE(object->methodCalled(), false);
2338 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2339 QCOMPARE(object->methodCalled(), true);
2345 QDeclarativeComponent component(&engine, TEST_FILE("scriptConnect.5.qml"));
2347 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2348 QVERIFY(object != 0);
2350 QCOMPARE(object->methodCalled(), false);
2351 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2352 QCOMPARE(object->methodCalled(), true);
2358 QDeclarativeComponent component(&engine, TEST_FILE("scriptConnect.6.qml"));
2360 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2361 QVERIFY(object != 0);
2363 QCOMPARE(object->property("test").toInt(), 0);
2364 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2365 QCOMPARE(object->property("test").toInt(), 2);
2371 void tst_qdeclarativeecmascript::scriptDisconnect()
2374 QDeclarativeComponent component(&engine, TEST_FILE("scriptDisconnect.1.qml"));
2376 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2377 QVERIFY(object != 0);
2379 QCOMPARE(object->property("test").toInt(), 0);
2380 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2381 QCOMPARE(object->property("test").toInt(), 1);
2382 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2383 QCOMPARE(object->property("test").toInt(), 2);
2384 emit object->basicSignal();
2385 QCOMPARE(object->property("test").toInt(), 2);
2386 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2387 QCOMPARE(object->property("test").toInt(), 2);
2393 QDeclarativeComponent component(&engine, TEST_FILE("scriptDisconnect.2.qml"));
2395 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2396 QVERIFY(object != 0);
2398 QCOMPARE(object->property("test").toInt(), 0);
2399 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2400 QCOMPARE(object->property("test").toInt(), 1);
2401 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2402 QCOMPARE(object->property("test").toInt(), 2);
2403 emit object->basicSignal();
2404 QCOMPARE(object->property("test").toInt(), 2);
2405 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2406 QCOMPARE(object->property("test").toInt(), 2);
2412 QDeclarativeComponent component(&engine, TEST_FILE("scriptDisconnect.3.qml"));
2414 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2415 QVERIFY(object != 0);
2417 QCOMPARE(object->property("test").toInt(), 0);
2418 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2419 QCOMPARE(object->property("test").toInt(), 1);
2420 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2421 QCOMPARE(object->property("test").toInt(), 2);
2422 emit object->basicSignal();
2423 QCOMPARE(object->property("test").toInt(), 2);
2424 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2425 QCOMPARE(object->property("test").toInt(), 3);
2430 QDeclarativeComponent component(&engine, TEST_FILE("scriptDisconnect.4.qml"));
2432 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2433 QVERIFY(object != 0);
2435 QCOMPARE(object->property("test").toInt(), 0);
2436 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2437 QCOMPARE(object->property("test").toInt(), 1);
2438 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2439 QCOMPARE(object->property("test").toInt(), 2);
2440 emit object->basicSignal();
2441 QCOMPARE(object->property("test").toInt(), 2);
2442 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2443 QCOMPARE(object->property("test").toInt(), 3);
2449 class OwnershipObject : public QObject
2453 OwnershipObject() { object = new QObject; }
2455 QPointer<QObject> object;
2458 QObject *getObject() { return object; }
2461 void tst_qdeclarativeecmascript::ownership()
2463 OwnershipObject own;
2464 QDeclarativeContext *context = new QDeclarativeContext(engine.rootContext());
2465 context->setContextObject(&own);
2468 QDeclarativeComponent component(&engine, TEST_FILE("ownership.qml"));
2470 QVERIFY(own.object != 0);
2472 QObject *object = component.create(context);
2474 engine.collectGarbage();
2476 QCoreApplication::processEvents(QEventLoop::DeferredDeletion);
2478 QVERIFY(own.object == 0);
2483 own.object = new QObject(&own);
2486 QDeclarativeComponent component(&engine, TEST_FILE("ownership.qml"));
2488 QVERIFY(own.object != 0);
2490 QObject *object = component.create(context);
2492 engine.collectGarbage();
2494 QCoreApplication::processEvents(QEventLoop::DeferredDeletion);
2496 QVERIFY(own.object != 0);
2504 class CppOwnershipReturnValue : public QObject
2508 CppOwnershipReturnValue() : value(0) {}
2509 ~CppOwnershipReturnValue() { delete value; }
2511 Q_INVOKABLE QObject *create() {
2512 value = new QObject;
2513 QDeclarativeEngine::setObjectOwnership(value, QDeclarativeEngine::CppOwnership);
2517 Q_INVOKABLE MyQmlObject *createQmlObject() {
2518 MyQmlObject *rv = new MyQmlObject;
2523 QPointer<QObject> value;
2527 // Test setObjectOwnership(CppOwnership) works even when there is no QDeclarativeData
2528 void tst_qdeclarativeecmascript::cppOwnershipReturnValue()
2530 CppOwnershipReturnValue source;
2533 QDeclarativeEngine engine;
2534 engine.rootContext()->setContextProperty("source", &source);
2536 QVERIFY(source.value == 0);
2538 QDeclarativeComponent component(&engine);
2539 component.setData("import QtQuick 1.0\nQtObject {\nComponent.onCompleted: { var a = source.create(); }\n}\n", QUrl());
2541 QObject *object = component.create();
2543 QVERIFY(object != 0);
2544 QVERIFY(source.value != 0);
2549 QCoreApplication::instance()->processEvents(QEventLoop::DeferredDeletion);
2551 QVERIFY(source.value != 0);
2555 void tst_qdeclarativeecmascript::ownershipCustomReturnValue()
2557 CppOwnershipReturnValue source;
2560 QDeclarativeEngine engine;
2561 engine.rootContext()->setContextProperty("source", &source);
2563 QVERIFY(source.value == 0);
2565 QDeclarativeComponent component(&engine);
2566 component.setData("import QtQuick 1.0\nQtObject {\nComponent.onCompleted: { var a = source.createQmlObject(); }\n}\n", QUrl());
2568 QObject *object = component.create();
2570 QVERIFY(object != 0);
2571 QVERIFY(source.value != 0);
2576 engine.collectGarbage();
2577 QCoreApplication::instance()->processEvents(QEventLoop::DeferredDeletion);
2579 QVERIFY(source.value == 0);
2582 class QListQObjectMethodsObject : public QObject
2586 QListQObjectMethodsObject() {
2587 m_objects.append(new MyQmlObject());
2588 m_objects.append(new MyQmlObject());
2591 ~QListQObjectMethodsObject() {
2592 qDeleteAll(m_objects);
2596 QList<QObject *> getObjects() { return m_objects; }
2599 QList<QObject *> m_objects;
2602 // Tests that returning a QList<QObject*> from a method works
2603 void tst_qdeclarativeecmascript::qlistqobjectMethods()
2605 QListQObjectMethodsObject obj;
2606 QDeclarativeContext *context = new QDeclarativeContext(engine.rootContext());
2607 context->setContextObject(&obj);
2609 QDeclarativeComponent component(&engine, TEST_FILE("qlistqobjectMethods.qml"));
2611 QObject *object = component.create(context);
2613 QCOMPARE(object->property("test").toInt(), 2);
2614 QCOMPARE(object->property("test2").toBool(), true);
2621 void tst_qdeclarativeecmascript::strictlyEquals()
2623 QDeclarativeComponent component(&engine, TEST_FILE("strictlyEquals.qml"));
2625 QObject *object = component.create();
2626 QVERIFY(object != 0);
2628 QCOMPARE(object->property("test1").toBool(), true);
2629 QCOMPARE(object->property("test2").toBool(), true);
2630 QCOMPARE(object->property("test3").toBool(), true);
2631 QCOMPARE(object->property("test4").toBool(), true);
2632 QCOMPARE(object->property("test5").toBool(), true);
2633 QCOMPARE(object->property("test6").toBool(), true);
2634 QCOMPARE(object->property("test7").toBool(), true);
2635 QCOMPARE(object->property("test8").toBool(), true);
2640 void tst_qdeclarativeecmascript::compiled()
2642 QDeclarativeComponent component(&engine, TEST_FILE("compiled.qml"));
2644 QObject *object = component.create();
2645 QVERIFY(object != 0);
2647 QCOMPARE(object->property("test1").toReal(), qreal(15.7));
2648 QCOMPARE(object->property("test2").toReal(), qreal(-6.7));
2649 QCOMPARE(object->property("test3").toBool(), true);
2650 QCOMPARE(object->property("test4").toBool(), false);
2651 QCOMPARE(object->property("test5").toBool(), false);
2652 QCOMPARE(object->property("test6").toBool(), true);
2654 QCOMPARE(object->property("test7").toInt(), 185);
2655 QCOMPARE(object->property("test8").toInt(), 167);
2656 QCOMPARE(object->property("test9").toBool(), true);
2657 QCOMPARE(object->property("test10").toBool(), false);
2658 QCOMPARE(object->property("test11").toBool(), false);
2659 QCOMPARE(object->property("test12").toBool(), true);
2661 QCOMPARE(object->property("test13").toString(), QLatin1String("HelloWorld"));
2662 QCOMPARE(object->property("test14").toString(), QLatin1String("Hello World"));
2663 QCOMPARE(object->property("test15").toBool(), false);
2664 QCOMPARE(object->property("test16").toBool(), true);
2666 QCOMPARE(object->property("test17").toInt(), 5);
2667 QCOMPARE(object->property("test18").toReal(), qreal(176));
2668 QCOMPARE(object->property("test19").toInt(), 7);
2669 QCOMPARE(object->property("test20").toReal(), qreal(6.7));
2670 QCOMPARE(object->property("test21").toString(), QLatin1String("6.7"));
2671 QCOMPARE(object->property("test22").toString(), QLatin1String("!"));
2672 QCOMPARE(object->property("test23").toBool(), true);
2673 QCOMPARE(qvariant_cast<QColor>(object->property("test24")), QColor(0x11,0x22,0x33));
2674 QCOMPARE(qvariant_cast<QColor>(object->property("test25")), QColor(0x11,0x22,0x33,0xAA));
2679 // Test that numbers assigned in bindings as strings work consistently
2680 void tst_qdeclarativeecmascript::numberAssignment()
2682 QDeclarativeComponent component(&engine, TEST_FILE("numberAssignment.qml"));
2684 QObject *object = component.create();
2685 QVERIFY(object != 0);
2687 QCOMPARE(object->property("test1"), QVariant((qreal)6.7));
2688 QCOMPARE(object->property("test2"), QVariant((qreal)6.7));
2689 QCOMPARE(object->property("test2"), QVariant((qreal)6.7));
2690 QCOMPARE(object->property("test3"), QVariant((qreal)6));
2691 QCOMPARE(object->property("test4"), QVariant((qreal)6));
2693 QCOMPARE(object->property("test5"), QVariant((int)7));
2694 QCOMPARE(object->property("test6"), QVariant((int)7));
2695 QCOMPARE(object->property("test7"), QVariant((int)6));
2696 QCOMPARE(object->property("test8"), QVariant((int)6));
2698 QCOMPARE(object->property("test9"), QVariant((unsigned int)7));
2699 QCOMPARE(object->property("test10"), QVariant((unsigned int)7));
2700 QCOMPARE(object->property("test11"), QVariant((unsigned int)6));
2701 QCOMPARE(object->property("test12"), QVariant((unsigned int)6));
2706 void tst_qdeclarativeecmascript::propertySplicing()
2708 QDeclarativeComponent component(&engine, TEST_FILE("propertySplicing.qml"));
2710 QObject *object = component.create();
2711 QVERIFY(object != 0);
2713 QCOMPARE(object->property("test").toBool(), true);
2719 void tst_qdeclarativeecmascript::signalWithUnknownTypes()
2721 QDeclarativeComponent component(&engine, TEST_FILE("signalWithUnknownTypes.qml"));
2723 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2724 QVERIFY(object != 0);
2726 MyQmlObject::MyType type;
2727 type.value = 0x8971123;
2728 emit object->signalWithUnknownType(type);
2730 MyQmlObject::MyType result = qvariant_cast<MyQmlObject::MyType>(object->variant());
2732 QCOMPARE(result.value, type.value);
2738 void tst_qdeclarativeecmascript::moduleApi()
2740 QDeclarativeComponent component(&engine, TEST_FILE("moduleApi.qml"));
2741 QObject *object = component.create();
2742 QVERIFY(object != 0);
2743 QCOMPARE(object->property("existingUriTest").toInt(), 20);
2745 QEXPECT_FAIL("", "QTBUG-17318", Continue);
2746 QCOMPARE(object->property("scriptTest").toInt(), 13);
2747 QCOMPARE(object->property("qobjectTest").toInt(), 20);
2748 QCOMPARE(object->property("qobjectMethodTest").toInt(), 1); // first call of method, so count = 1.
2749 QCOMPARE(object->property("qobjectMinorVersionTest").toInt(), 20);
2750 QCOMPARE(object->property("qobjectMajorVersionTest").toInt(), 20);
2751 QCOMPARE(object->property("qobjectParentedTest").toInt(), 26);
2754 // test that caching of module apis works correctly.
2755 QDeclarativeComponent componentTwo(&engine, TEST_FILE("moduleApiCaching.qml"));
2756 object = componentTwo.create();
2757 QVERIFY(object != 0);
2758 QCOMPARE(object->property("existingUriTest").toInt(), 20);
2759 QEXPECT_FAIL("", "QTBUG-17318", Continue);
2760 QCOMPARE(object->property("scriptTest").toInt(), 13); // shouldn't have incremented.
2761 QCOMPARE(object->property("qobjectParentedTest").toInt(), 26); // shouldn't have incremented.
2764 // test that writing to a property of module apis works correctly.
2765 QDeclarativeComponent componentThree(&engine, TEST_FILE("moduleApiWriting.qml"));
2766 QString expectedWarning = QLatin1String("file://") + TEST_FILE("moduleApiWriting.qml").toLocalFile() + QLatin1String(":15: Error: Cannot assign to read-only property \"qobjectTestProperty\"");
2767 QTest::ignoreMessage(QtWarningMsg, expectedWarning.toAscii().constData());
2768 object = componentThree.create();
2769 QVERIFY(object != 0);
2770 QCOMPARE(object->property("readOnlyProperty").toInt(), 20);
2771 QCOMPARE(object->property("writableProperty").toInt(), 50);
2772 QVERIFY(object->setProperty("firstProperty", QVariant(30))); // shouldn't affect value of readOnlyProperty
2773 QVERIFY(object->setProperty("writableProperty", QVariant(30))); // SHOULD affect value of writableProperty
2774 QCOMPARE(object->property("readOnlyProperty").toInt(), 20);
2775 QCOMPARE(object->property("writableProperty").toInt(), 30);
2778 QDeclarativeComponent failOne(&engine, TEST_FILE("moduleApiMajorVersionFail.qml"));
2779 QTest::ignoreMessage(QtWarningMsg, "QDeclarativeComponent: Component is not ready");
2780 object = failOne.create();
2781 QVERIFY(object == 0); // should have failed: invalid major version
2783 QDeclarativeComponent failTwo(&engine, TEST_FILE("moduleApiMinorVersionFail.qml"));
2784 QTest::ignoreMessage(QtWarningMsg, "QDeclarativeComponent: Component is not ready");
2785 object = failTwo.create();
2786 QVERIFY(object == 0); // should have failed: invalid minor version
2789 void tst_qdeclarativeecmascript::importScripts()
2791 QObject *object = 0;
2793 // first, ensure that the required behaviour works.
2794 QDeclarativeComponent component(&engine, TEST_FILE("jsimport/testImport.qml"));
2795 object = component.create();
2796 QVERIFY(object != 0);
2797 QCOMPARE(object->property("importedScriptStringValue"), QVariant(QString(QLatin1String("Hello, World!"))));
2798 QCOMPARE(object->property("importedScriptFunctionValue"), QVariant(20));
2799 QCOMPARE(object->property("importedModuleAttachedPropertyValue"), QVariant(19));
2800 QCOMPARE(object->property("importedModuleEnumValue"), QVariant(2));
2803 QDeclarativeComponent componentTwo(&engine, TEST_FILE("jsimport/testImportScoping.qml"));
2804 object = componentTwo.create();
2805 QVERIFY(object != 0);
2806 QCOMPARE(object->property("componentError"), QVariant(5));
2809 // then, ensure that unintended behaviour does not work.
2810 QDeclarativeComponent failOneComponent(&engine, TEST_FILE("jsimportfail/failOne.qml"));
2811 QString expectedWarning = QLatin1String("file://") + TEST_FILE("jsimportfail/failOne.qml").toLocalFile() + QLatin1String(":6: TypeError: Cannot call method 'greetingString' of undefined");
2812 QTest::ignoreMessage(QtWarningMsg, expectedWarning.toAscii().constData());
2813 object = failOneComponent.create();
2814 QVERIFY(object != 0);
2815 QVERIFY(object->property("importScriptFunctionValue").toString().isEmpty());
2817 QDeclarativeComponent failTwoComponent(&engine, TEST_FILE("jsimportfail/failTwo.qml"));
2818 expectedWarning = QLatin1String("file://") + TEST_FILE("jsimportfail/failTwo.qml").toLocalFile() + QLatin1String(":6: ReferenceError: Can't find variable: ImportOneJs");
2819 QTest::ignoreMessage(QtWarningMsg, expectedWarning.toAscii().constData());
2820 object = failTwoComponent.create();
2821 QVERIFY(object != 0);
2822 QVERIFY(object->property("importScriptFunctionValue").toString().isEmpty());
2824 QDeclarativeComponent failThreeComponent(&engine, TEST_FILE("jsimportfail/failThree.qml"));
2825 expectedWarning = QLatin1String("file://") + TEST_FILE("jsimportfail/failThree.qml").toLocalFile() + QLatin1String(":7: TypeError: Cannot read property 'JsQtTest' of undefined");
2826 QTest::ignoreMessage(QtWarningMsg, expectedWarning.toAscii().constData());
2827 object = failThreeComponent.create();
2828 QVERIFY(object != 0);
2829 QCOMPARE(object->property("importedModuleAttachedPropertyValue"), QVariant(false));
2831 QDeclarativeComponent failFourComponent(&engine, TEST_FILE("jsimportfail/failFour.qml"));
2832 expectedWarning = QLatin1String("file://") + TEST_FILE("jsimportfail/failFour.qml").toLocalFile() + QLatin1String(":6: ReferenceError: Can't find variable: JsQtTest");
2833 QTest::ignoreMessage(QtWarningMsg, expectedWarning.toAscii().constData());
2834 object = failFourComponent.create();
2835 QVERIFY(object != 0);
2836 QCOMPARE(object->property("importedModuleEnumValue"), QVariant(0));
2838 QDeclarativeComponent failFiveComponent(&engine, TEST_FILE("jsimportfail/failFive.qml"));
2839 expectedWarning = QLatin1String("file://") + TEST_FILE("jsimportfail/importWithImports.js").toLocalFile() + QLatin1String(":8: ReferenceError: Can't find variable: Component");
2840 QTest::ignoreMessage(QtWarningMsg, expectedWarning.toAscii().constData());
2841 expectedWarning = QLatin1String("file://") + TEST_FILE("jsimportfail/importPragmaLibrary.js").toLocalFile() + QLatin1String(":6: ReferenceError: Can't find variable: Component");
2842 QTest::ignoreMessage(QtWarningMsg, expectedWarning.toAscii().constData());
2843 object = failFiveComponent.create();
2844 QVERIFY(object != 0);
2845 QCOMPARE(object->property("componentError"), QVariant(0));
2848 // also, test that importing scripts with .pragma library works as required
2849 QDeclarativeComponent pragmaLibraryComponent(&engine, TEST_FILE("jsimport/testImportPragmaLibrary.qml"));
2850 object = pragmaLibraryComponent.create();
2851 QVERIFY(object != 0);
2852 QCOMPARE(object->property("testValue"), QVariant(31));
2855 // and that .pragma library scripts don't inherit imports from any .qml file
2856 QDeclarativeComponent pragmaLibraryComponentTwo(&engine, TEST_FILE("jsimportfail/testImportPragmaLibrary.qml"));
2857 object = pragmaLibraryComponentTwo.create();
2858 QVERIFY(object != 0);
2859 QCOMPARE(object->property("testValue"), QVariant(0));
2863 void tst_qdeclarativeecmascript::scarceResources()
2865 QPixmap origPixmap(100, 100);
2866 origPixmap.fill(Qt::blue);
2868 QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(&engine);
2869 ScarceResourceObject *eo = 0;
2870 QObject *object = 0;
2872 // in the following three cases, the instance created from the component
2873 // has a property which is a copy of the scarce resource; hence, the
2874 // resource should NOT be detached prior to deletion of the object instance,
2875 // unless the resource is destroyed explicitly.
2876 QDeclarativeComponent component(&engine, TEST_FILE("scarceresources/scarceResourceCopy.qml"));
2877 object = component.create();
2878 QVERIFY(object != 0);
2879 QVERIFY(object->property("scarceResourceCopy").isValid());
2880 QCOMPARE(object->property("scarceResourceCopy").value<QPixmap>(), origPixmap);
2881 QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
2882 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2883 QVERIFY(!eo->scarceResourceIsDetached()); // there are two copies of it in existence: the property of object, and the property of eo.
2886 QDeclarativeComponent componentTwo(&engine, TEST_FILE("scarceresources/scarceResourceCopyFromJs.qml"));
2887 object = componentTwo.create();
2888 QVERIFY(object != 0);
2889 QVERIFY(object->property("scarceResourceCopy").isValid());
2890 QCOMPARE(object->property("scarceResourceCopy").value<QPixmap>(), origPixmap);
2891 QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
2892 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2893 QVERIFY(!eo->scarceResourceIsDetached()); // there are two copies of it in existence: the property of object, and the property of eo.
2896 QDeclarativeComponent componentThree(&engine, TEST_FILE("scarceresources/scarceResourceDestroyedCopy.qml"));
2897 object = componentThree.create();
2898 QVERIFY(object != 0);
2899 QVERIFY(!(object->property("scarceResourceCopy").isValid())); // was manually released prior to being returned.
2900 QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
2901 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2902 QVERIFY(eo->scarceResourceIsDetached()); // should have explicitly been released during the evaluation of the binding.
2905 // in the following three cases, no other copy should exist in memory,
2906 // and so it should be detached (unless explicitly preserved).
2907 QDeclarativeComponent componentFour(&engine, TEST_FILE("scarceresources/scarceResourceTest.qml"));
2908 object = componentFour.create();
2909 QVERIFY(object != 0);
2910 QVERIFY(object->property("scarceResourceTest").isValid());
2911 QCOMPARE(object->property("scarceResourceTest").toInt(), 100);
2912 QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
2913 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2914 QVERIFY(eo->scarceResourceIsDetached()); // the resource should have been released after the binding was evaluated.
2917 QDeclarativeComponent componentFive(&engine, TEST_FILE("scarceresources/scarceResourceTestPreserve.qml"));
2918 object = componentFive.create();
2919 QVERIFY(object != 0);
2920 QVERIFY(object->property("scarceResourceTest").isValid());
2921 QCOMPARE(object->property("scarceResourceTest").toInt(), 100);
2922 QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
2923 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2924 QVERIFY(!eo->scarceResourceIsDetached()); // this won't be detached since we explicitly preserved it.
2927 QDeclarativeComponent componentSix(&engine, TEST_FILE("scarceresources/scarceResourceTestMultiple.qml"));
2928 object = componentSix.create();
2929 QVERIFY(object != 0);
2930 QVERIFY(object->property("scarceResourceTest").isValid());
2931 QCOMPARE(object->property("scarceResourceTest").toInt(), 100);
2932 QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
2933 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2934 QVERIFY(eo->scarceResourceIsDetached()); // all resources were released manually or automatically released.
2937 // test that scarce resources are handled correctly for imports
2938 QDeclarativeComponent componentSeven(&engine, TEST_FILE("scarceresources/scarceResourceCopyImportNoBinding.qml"));
2939 object = componentSeven.create();
2940 QVERIFY(object != 0); // the import should have caused the addition of a resource to the ScarceResources list
2941 QVERIFY(ep->scarceResources.isEmpty()); // but they should have been released by this point.
2944 QDeclarativeComponent componentEight(&engine, TEST_FILE("scarceresources/scarceResourceCopyImportFail.qml"));
2945 object = componentEight.create();
2946 QVERIFY(object != 0);
2947 QVERIFY(!object->property("scarceResourceCopy").isValid()); // wasn't preserved, so shouldn't be valid.
2948 QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
2951 QDeclarativeComponent componentNine(&engine, TEST_FILE("scarceresources/scarceResourceCopyImport.qml"));
2952 object = componentNine.create();
2953 QVERIFY(object != 0);
2954 QVERIFY(object->property("scarceResourceCopy").isValid()); // preserved, so should be valid.
2955 QCOMPARE(object->property("scarceResourceCopy").value<QPixmap>(), origPixmap);
2956 QVERIFY(object->property("scarceResourceAssignedCopyOne").isValid()); // assigned before destroy(), so should be valid.
2957 QCOMPARE(object->property("scarceResourceAssignedCopyOne").value<QPixmap>(), origPixmap);
2958 QVERIFY(!object->property("scarceResourceAssignedCopyTwo").isValid()); // assigned after destroy(), so should be invalid.
2959 QVERIFY(ep->scarceResources.isEmpty()); // this will still be zero, because "preserve()" REMOVES it from this list.
2962 // test that scarce resources are handled properly in signal invocation
2963 QDeclarativeComponent componentTen(&engine, TEST_FILE("scarceresources/scarceResourceSignal.qml"));
2964 object = componentTen.create();
2965 QVERIFY(object != 0);
2966 QObject *srsc = object->findChild<QObject*>("srsc");
2968 QVERIFY(!srsc->property("scarceResourceCopy").isValid()); // hasn't been instantiated yet.
2969 QCOMPARE(srsc->property("width"), QVariant(5)); // default value is 5.
2970 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2971 QVERIFY(eo->scarceResourceIsDetached()); // should be no other copies of it at this stage.
2972 QMetaObject::invokeMethod(srsc, "testSignal");
2973 QVERIFY(!srsc->property("scarceResourceCopy").isValid()); // still hasn't been instantiated
2974 QCOMPARE(srsc->property("width"), QVariant(10)); // but width was assigned to 10.
2975 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2976 QVERIFY(eo->scarceResourceIsDetached()); // should still be no other copies of it at this stage.
2977 QMetaObject::invokeMethod(srsc, "testSignal2"); // assigns scarceResourceCopy to the scarce pixmap.
2978 QVERIFY(srsc->property("scarceResourceCopy").isValid());
2979 QCOMPARE(srsc->property("scarceResourceCopy").value<QPixmap>(), origPixmap);
2980 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2981 QVERIFY(!(eo->scarceResourceIsDetached())); // should be another copy of the resource now.
2982 QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
2985 // test that scarce resources are handled properly from js functions in qml files
2986 QDeclarativeComponent componentEleven(&engine, TEST_FILE("scarceresources/scarceResourceFunction.qml"));
2987 object = componentEleven.create();
2988 QVERIFY(object != 0);
2989 QVERIFY(!object->property("scarceResourceCopy").isValid()); // not yet assigned, so should not be valid
2990 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2991 QVERIFY(eo->scarceResourceIsDetached()); // should be no other copies of it at this stage.
2992 QMetaObject::invokeMethod(object, "retrieveScarceResource");
2993 QVERIFY(object->property("scarceResourceCopy").isValid()); // assigned, so should be valid.
2994 QCOMPARE(object->property("scarceResourceCopy").value<QPixmap>(), origPixmap);
2995 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2996 QVERIFY(!eo->scarceResourceIsDetached()); // should be a copy of the resource at this stage.
2997 QMetaObject::invokeMethod(object, "releaseScarceResource");
2998 QVERIFY(!object->property("scarceResourceCopy").isValid()); // just released, so should not be valid
2999 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
3000 QVERIFY(eo->scarceResourceIsDetached()); // should be no other copies of it at this stage.
3001 QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
3004 // test that if an exception occurs while invoking js function from cpp, that the resources are released.
3005 QDeclarativeComponent componentTwelve(&engine, TEST_FILE("scarceresources/scarceResourceFunctionFail.qml"));
3006 object = componentTwelve.create();
3007 QVERIFY(object != 0);
3008 QVERIFY(!object->property("scarceResourceCopy").isValid()); // not yet assigned, so should not be valid
3009 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
3010 QVERIFY(eo->scarceResourceIsDetached()); // should be no other copies of it at this stage.
3011 QString srp_name = object->property("srp_name").toString();
3012 QString expectedWarning = componentTwelve.url().toString() + QLatin1String(":17: TypeError: Property 'scarceResource' of object ") + srp_name + QLatin1String(" is not a function");
3013 QTest::ignoreMessage(QtWarningMsg, qPrintable(expectedWarning)); // we expect a meaningful warning to be printed.
3014 QMetaObject::invokeMethod(object, "retrieveScarceResource");
3015 QVERIFY(!object->property("scarceResourceCopy").isValid()); // due to exception, assignment will NOT have occurred.
3016 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
3017 QVERIFY(eo->scarceResourceIsDetached()); // should be no other copies of it at this stage.
3018 QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
3022 void tst_qdeclarativeecmascript::propertyChangeSlots()
3024 // ensure that allowable property names are allowed and onPropertyNameChanged slots are generated correctly.
3025 QDeclarativeComponent component(&engine, TEST_FILE("changeslots/propertyChangeSlots.qml"));
3026 QObject *object = component.create();
3027 QVERIFY(object != 0);
3030 // ensure that invalid property names fail properly.
3031 QTest::ignoreMessage(QtWarningMsg, "QDeclarativeComponent: Component is not ready");
3032 QDeclarativeComponent e1(&engine, TEST_FILE("changeslots/propertyChangeSlotErrors.1.qml"));
3033 QString expectedErrorString = e1.url().toString() + QLatin1String(":9:5: Cannot assign to non-existent property \"on_nameWithUnderscoreChanged\"");
3034 QCOMPARE(e1.errors().at(0).toString(), expectedErrorString);
3035 object = e1.create();
3036 QVERIFY(object == 0);
3039 QTest::ignoreMessage(QtWarningMsg, "QDeclarativeComponent: Component is not ready");
3040 QDeclarativeComponent e2(&engine, TEST_FILE("changeslots/propertyChangeSlotErrors.2.qml"));
3041 expectedErrorString = e2.url().toString() + QLatin1String(":9:5: Cannot assign to non-existent property \"on____nameWithUnderscoresChanged\"");
3042 QCOMPARE(e2.errors().at(0).toString(), expectedErrorString);
3043 object = e2.create();
3044 QVERIFY(object == 0);
3047 QTest::ignoreMessage(QtWarningMsg, "QDeclarativeComponent: Component is not ready");
3048 QDeclarativeComponent e3(&engine, TEST_FILE("changeslots/propertyChangeSlotErrors.3.qml"));
3049 expectedErrorString = e3.url().toString() + QLatin1String(":9:5: Cannot assign to non-existent property \"on$NameWithDollarsignChanged\"");
3050 QCOMPARE(e3.errors().at(0).toString(), expectedErrorString);
3051 object = e3.create();
3052 QVERIFY(object == 0);
3055 QTest::ignoreMessage(QtWarningMsg, "QDeclarativeComponent: Component is not ready");
3056 QDeclarativeComponent e4(&engine, TEST_FILE("changeslots/propertyChangeSlotErrors.4.qml"));
3057 expectedErrorString = e4.url().toString() + QLatin1String(":9:5: Cannot assign to non-existent property \"on_6NameWithUnderscoreNumberChanged\"");
3058 QCOMPARE(e4.errors().at(0).toString(), expectedErrorString);
3059 object = e4.create();
3060 QVERIFY(object == 0);
3064 // Ensure that QObject type conversion works on binding assignment
3065 void tst_qdeclarativeecmascript::elementAssign()
3067 QDeclarativeComponent component(&engine, TEST_FILE("elementAssign.qml"));
3069 QObject *object = component.create();
3070 QVERIFY(object != 0);
3072 QCOMPARE(object->property("test").toBool(), true);
3078 void tst_qdeclarativeecmascript::objectPassThroughSignals()
3080 QDeclarativeComponent component(&engine, TEST_FILE("objectsPassThroughSignals.qml"));
3082 QObject *object = component.create();
3083 QVERIFY(object != 0);
3085 QCOMPARE(object->property("test").toBool(), true);
3091 void tst_qdeclarativeecmascript::booleanConversion()
3093 QDeclarativeComponent component(&engine, TEST_FILE("booleanConversion.qml"));
3095 QObject *object = component.create();
3096 QVERIFY(object != 0);
3098 QCOMPARE(object->property("test_true1").toBool(), true);
3099 QCOMPARE(object->property("test_true2").toBool(), true);
3100 QCOMPARE(object->property("test_true3").toBool(), true);
3101 QCOMPARE(object->property("test_true4").toBool(), true);
3102 QCOMPARE(object->property("test_true5").toBool(), true);
3104 QCOMPARE(object->property("test_false1").toBool(), false);
3105 QCOMPARE(object->property("test_false2").toBool(), false);
3106 QCOMPARE(object->property("test_false3").toBool(), false);
3111 // Test that assigning a null object works
3112 // Regressed with: df1788b4dbbb2826ae63f26bdf166342595343f4
3113 void tst_qdeclarativeecmascript::nullObjectBinding()
3115 QDeclarativeComponent component(&engine, TEST_FILE("nullObjectBinding.qml"));
3117 QObject *object = component.create();
3118 QVERIFY(object != 0);
3120 QVERIFY(object->property("test") == QVariant::fromValue((QObject *)0));
3125 // Test that bindings don't evaluate once the engine has been destroyed
3126 void tst_qdeclarativeecmascript::deletedEngine()
3128 QDeclarativeEngine *engine = new QDeclarativeEngine;
3129 QDeclarativeComponent component(engine, TEST_FILE("deletedEngine.qml"));
3131 QObject *object = component.create();
3132 QVERIFY(object != 0);
3134 QCOMPARE(object->property("a").toInt(), 39);
3135 object->setProperty("b", QVariant(9));
3136 QCOMPARE(object->property("a").toInt(), 117);
3140 QCOMPARE(object->property("a").toInt(), 117);
3141 object->setProperty("b", QVariant(10));
3142 QCOMPARE(object->property("a").toInt(), 117);
3147 // Test the crashing part of QTBUG-9705
3148 void tst_qdeclarativeecmascript::libraryScriptAssert()
3150 QDeclarativeComponent component(&engine, TEST_FILE("libraryScriptAssert.qml"));
3152 QObject *object = component.create();
3153 QVERIFY(object != 0);
3158 void tst_qdeclarativeecmascript::variantsAssignedUndefined()
3160 QDeclarativeComponent component(&engine, TEST_FILE("variantsAssignedUndefined.qml"));
3162 QObject *object = component.create();
3163 QVERIFY(object != 0);
3165 QCOMPARE(object->property("test1").toInt(), 10);
3166 QCOMPARE(object->property("test2").toInt(), 11);
3168 object->setProperty("runTest", true);
3170 QCOMPARE(object->property("test1"), QVariant());
3171 QCOMPARE(object->property("test2"), QVariant());
3177 void tst_qdeclarativeecmascript::qtbug_9792()
3179 QDeclarativeComponent component(&engine, TEST_FILE("qtbug_9792.qml"));
3181 QDeclarativeContext *context = new QDeclarativeContext(engine.rootContext());
3183 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create(context));
3184 QVERIFY(object != 0);
3186 QTest::ignoreMessage(QtDebugMsg, "Hello world!");
3187 object->basicSignal();
3191 transientErrorsMsgCount = 0;
3192 QtMsgHandler old = qInstallMsgHandler(transientErrorsMsgHandler);
3194 object->basicSignal();
3196 qInstallMsgHandler(old);
3198 QCOMPARE(transientErrorsMsgCount, 0);
3203 // Verifies that QDeclarativeGuard<>s used in the vmemetaobject are cleaned correctly
3204 void tst_qdeclarativeecmascript::qtcreatorbug_1289()
3206 QDeclarativeComponent component(&engine, TEST_FILE("qtcreatorbug_1289.qml"));
3208 QObject *o = component.create();
3211 QObject *nested = qvariant_cast<QObject *>(o->property("object"));
3212 QVERIFY(nested != 0);
3214 QVERIFY(qvariant_cast<QObject *>(nested->property("nestedObject")) == o);
3217 nested = qvariant_cast<QObject *>(o->property("object"));
3218 QVERIFY(nested == 0);
3220 // If the bug is present, the next line will crash
3224 // Test that we shut down without stupid warnings
3225 void tst_qdeclarativeecmascript::noSpuriousWarningsAtShutdown()
3228 QDeclarativeComponent component(&engine, TEST_FILE("noSpuriousWarningsAtShutdown.qml"));
3230 QObject *o = component.create();
3232 transientErrorsMsgCount = 0;
3233 QtMsgHandler old = qInstallMsgHandler(transientErrorsMsgHandler);
3237 qInstallMsgHandler(old);
3239 QCOMPARE(transientErrorsMsgCount, 0);
3244 QDeclarativeComponent component(&engine, TEST_FILE("noSpuriousWarningsAtShutdown.2.qml"));
3246 QObject *o = component.create();
3248 transientErrorsMsgCount = 0;
3249 QtMsgHandler old = qInstallMsgHandler(transientErrorsMsgHandler);
3253 qInstallMsgHandler(old);
3255 QCOMPARE(transientErrorsMsgCount, 0);
3259 void tst_qdeclarativeecmascript::canAssignNullToQObject()
3262 QDeclarativeComponent component(&engine, TEST_FILE("canAssignNullToQObject.1.qml"));
3264 MyQmlObject *o = qobject_cast<MyQmlObject *>(component.create());
3267 QVERIFY(o->objectProperty() != 0);
3269 o->setProperty("runTest", true);
3271 QVERIFY(o->objectProperty() == 0);
3277 QDeclarativeComponent component(&engine, TEST_FILE("canAssignNullToQObject.2.qml"));
3279 MyQmlObject *o = qobject_cast<MyQmlObject *>(component.create());
3282 QVERIFY(o->objectProperty() == 0);
3288 void tst_qdeclarativeecmascript::functionAssignment_fromBinding()
3290 QDeclarativeComponent component(&engine, TEST_FILE("functionAssignment.1.qml"));
3292 QString url = component.url().toString();
3293 QString warning = url + ":4: Unable to assign a function to a property.";
3294 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
3296 MyQmlObject *o = qobject_cast<MyQmlObject *>(component.create());
3299 QVERIFY(!o->property("a").isValid());
3304 void tst_qdeclarativeecmascript::functionAssignment_fromJS()
3306 QFETCH(QString, triggerProperty);
3308 QDeclarativeComponent component(&engine, TEST_FILE("functionAssignment.2.qml"));
3309 QVERIFY2(component.errorString().isEmpty(), qPrintable(component.errorString()));
3311 MyQmlObject *o = qobject_cast<MyQmlObject *>(component.create());
3313 QVERIFY(!o->property("a").isValid());
3315 o->setProperty("aNumber", QVariant(5));
3316 o->setProperty(triggerProperty.toUtf8().constData(), true);
3317 QCOMPARE(o->property("a"), QVariant(50));
3319 o->setProperty("aNumber", QVariant(10));
3320 QCOMPARE(o->property("a"), QVariant(100));
3325 void tst_qdeclarativeecmascript::functionAssignment_fromJS_data()
3327 QTest::addColumn<QString>("triggerProperty");
3329 QTest::newRow("assign to property") << "assignToProperty";
3330 QTest::newRow("assign to property, from JS file") << "assignToPropertyFromJsFile";
3332 QTest::newRow("assign to value type") << "assignToValueType";
3334 QTest::newRow("use 'this'") << "assignWithThis";
3335 QTest::newRow("use 'this' from JS file") << "assignWithThisFromJsFile";
3338 void tst_qdeclarativeecmascript::functionAssignmentfromJS_invalid()
3340 QDeclarativeComponent component(&engine, TEST_FILE("functionAssignment.2.qml"));
3341 QVERIFY2(component.errorString().isEmpty(), qPrintable(component.errorString()));
3343 MyQmlObject *o = qobject_cast<MyQmlObject *>(component.create());
3345 QVERIFY(!o->property("a").isValid());
3347 o->setProperty("assignFuncWithoutReturn", true);
3348 QVERIFY(!o->property("a").isValid());
3350 QString url = component.url().toString();
3351 QString warning = url + ":67: Unable to assign QString to int";
3352 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
3353 o->setProperty("assignWrongType", true);
3355 warning = url + ":71: Unable to assign QString to int";
3356 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
3357 o->setProperty("assignWrongTypeToValueType", true);
3362 void tst_qdeclarativeecmascript::eval()
3364 QDeclarativeComponent component(&engine, TEST_FILE("eval.qml"));
3366 QObject *o = component.create();
3369 QCOMPARE(o->property("test1").toBool(), true);
3370 QCOMPARE(o->property("test2").toBool(), true);
3371 QCOMPARE(o->property("test3").toBool(), true);
3372 QCOMPARE(o->property("test4").toBool(), true);
3373 QCOMPARE(o->property("test5").toBool(), true);
3378 void tst_qdeclarativeecmascript::function()
3380 QDeclarativeComponent component(&engine, TEST_FILE("function.qml"));
3382 QObject *o = component.create();
3385 QCOMPARE(o->property("test1").toBool(), true);
3386 QCOMPARE(o->property("test2").toBool(), true);
3387 QCOMPARE(o->property("test3").toBool(), true);
3392 // Test the "Qt.include" method
3393 void tst_qdeclarativeecmascript::include()
3395 // Non-library relative include
3397 QDeclarativeComponent component(&engine, TEST_FILE("include.qml"));
3398 QObject *o = component.create();
3401 QCOMPARE(o->property("test0").toInt(), 99);
3402 QCOMPARE(o->property("test1").toBool(), true);
3403 QCOMPARE(o->property("test2").toBool(), true);
3404 QCOMPARE(o->property("test2_1").toBool(), true);
3405 QCOMPARE(o->property("test3").toBool(), true);
3406 QCOMPARE(o->property("test3_1").toBool(), true);
3411 // Library relative include
3413 QDeclarativeComponent component(&engine, TEST_FILE("include_shared.qml"));
3414 QObject *o = component.create();
3417 QCOMPARE(o->property("test0").toInt(), 99);
3418 QCOMPARE(o->property("test1").toBool(), true);
3419 QCOMPARE(o->property("test2").toBool(), true);
3420 QCOMPARE(o->property("test2_1").toBool(), true);
3421 QCOMPARE(o->property("test3").toBool(), true);
3422 QCOMPARE(o->property("test3_1").toBool(), true);
3429 QDeclarativeComponent component(&engine, TEST_FILE("include_callback.qml"));
3430 QObject *o = component.create();
3433 QCOMPARE(o->property("test1").toBool(), true);
3434 QCOMPARE(o->property("test2").toBool(), true);
3435 QCOMPARE(o->property("test3").toBool(), true);
3436 QCOMPARE(o->property("test4").toBool(), true);
3437 QCOMPARE(o->property("test5").toBool(), true);
3438 QCOMPARE(o->property("test6").toBool(), true);
3443 // Including file with ".pragma library"
3445 QDeclarativeComponent component(&engine, TEST_FILE("include_pragma.qml"));
3446 QObject *o = component.create();
3448 QCOMPARE(o->property("test1").toInt(), 100);
3455 TestHTTPServer server(8111);
3456 QVERIFY(server.isValid());
3457 server.serveDirectory(SRCDIR "/data");
3459 QDeclarativeComponent component(&engine, TEST_FILE("include_remote.qml"));
3460 QObject *o = component.create();
3463 QTRY_VERIFY(o->property("done").toBool() == true);
3464 QTRY_VERIFY(o->property("done2").toBool() == true);
3466 QCOMPARE(o->property("test1").toBool(), true);
3467 QCOMPARE(o->property("test2").toBool(), true);
3468 QCOMPARE(o->property("test3").toBool(), true);
3469 QCOMPARE(o->property("test4").toBool(), true);
3470 QCOMPARE(o->property("test5").toBool(), true);
3472 QCOMPARE(o->property("test6").toBool(), true);
3473 QCOMPARE(o->property("test7").toBool(), true);
3474 QCOMPARE(o->property("test8").toBool(), true);
3475 QCOMPARE(o->property("test9").toBool(), true);
3476 QCOMPARE(o->property("test10").toBool(), true);
3483 TestHTTPServer server(8111);
3484 QVERIFY(server.isValid());
3485 server.serveDirectory(SRCDIR "/data");
3487 QDeclarativeComponent component(&engine, TEST_FILE("include_remote_missing.qml"));
3488 QObject *o = component.create();
3491 QTRY_VERIFY(o->property("done").toBool() == true);
3493 QCOMPARE(o->property("test1").toBool(), true);
3494 QCOMPARE(o->property("test2").toBool(), true);
3495 QCOMPARE(o->property("test3").toBool(), true);
3501 void tst_qdeclarativeecmascript::qtbug_10696()
3503 QDeclarativeComponent component(&engine, TEST_FILE("qtbug_10696.qml"));
3504 QObject *o = component.create();
3509 void tst_qdeclarativeecmascript::qtbug_11606()
3511 QDeclarativeComponent component(&engine, TEST_FILE("qtbug_11606.qml"));
3512 QObject *o = component.create();
3514 QCOMPARE(o->property("test").toBool(), true);
3518 void tst_qdeclarativeecmascript::qtbug_11600()
3520 QDeclarativeComponent component(&engine, TEST_FILE("qtbug_11600.qml"));
3521 QObject *o = component.create();
3523 QCOMPARE(o->property("test").toBool(), true);
3527 // Reading and writing non-scriptable properties should fail
3528 void tst_qdeclarativeecmascript::nonscriptable()
3530 QDeclarativeComponent component(&engine, TEST_FILE("nonscriptable.qml"));
3531 QObject *o = component.create();
3533 QCOMPARE(o->property("readOk").toBool(), true);
3534 QCOMPARE(o->property("writeOk").toBool(), true);
3538 // deleteLater() should not be callable from QML
3539 void tst_qdeclarativeecmascript::deleteLater()
3541 QDeclarativeComponent component(&engine, TEST_FILE("deleteLater.qml"));
3542 QObject *o = component.create();
3544 QCOMPARE(o->property("test").toBool(), true);
3548 void tst_qdeclarativeecmascript::in()
3550 QDeclarativeComponent component(&engine, TEST_FILE("in.qml"));
3551 QObject *o = component.create();
3553 QCOMPARE(o->property("test1").toBool(), true);
3554 QCOMPARE(o->property("test2").toBool(), true);
3558 void tst_qdeclarativeecmascript::sharedAttachedObject()
3560 QDeclarativeComponent component(&engine, TEST_FILE("sharedAttachedObject.qml"));
3561 QObject *o = component.create();
3563 QCOMPARE(o->property("test1").toBool(), true);
3564 QCOMPARE(o->property("test2").toBool(), true);
3569 void tst_qdeclarativeecmascript::objectName()
3571 QDeclarativeComponent component(&engine, TEST_FILE("objectName.qml"));
3572 QObject *o = component.create();
3575 QCOMPARE(o->property("test1").toString(), QString("hello"));
3576 QCOMPARE(o->property("test2").toString(), QString("ell"));
3578 o->setObjectName("world");
3580 QCOMPARE(o->property("test1").toString(), QString("world"));
3581 QCOMPARE(o->property("test2").toString(), QString("orl"));
3586 void tst_qdeclarativeecmascript::writeRemovesBinding()
3588 QDeclarativeComponent component(&engine, TEST_FILE("writeRemovesBinding.qml"));
3589 QObject *o = component.create();
3592 QCOMPARE(o->property("test").toBool(), true);
3597 // Test bindings assigned to alias properties actually assign to the alias' target
3598 void tst_qdeclarativeecmascript::aliasBindingsAssignCorrectly()
3600 QDeclarativeComponent component(&engine, TEST_FILE("aliasBindingsAssignCorrectly.qml"));
3601 QObject *o = component.create();
3604 QCOMPARE(o->property("test").toBool(), true);
3609 // Test bindings assigned to alias properties override a binding on the target (QTBUG-13719)
3610 void tst_qdeclarativeecmascript::aliasBindingsOverrideTarget()
3613 QDeclarativeComponent component(&engine, TEST_FILE("aliasBindingsOverrideTarget.qml"));
3614 QObject *o = component.create();
3617 QCOMPARE(o->property("test").toBool(), true);
3623 QDeclarativeComponent component(&engine, TEST_FILE("aliasBindingsOverrideTarget.2.qml"));
3624 QObject *o = component.create();
3627 QCOMPARE(o->property("test").toBool(), true);
3633 QDeclarativeComponent component(&engine, TEST_FILE("aliasBindingsOverrideTarget.3.qml"));
3634 QObject *o = component.create();
3637 QCOMPARE(o->property("test").toBool(), true);
3643 // Test that writes to alias properties override bindings on the alias target (QTBUG-13719)
3644 void tst_qdeclarativeecmascript::aliasWritesOverrideBindings()
3647 QDeclarativeComponent component(&engine, TEST_FILE("aliasWritesOverrideBindings.qml"));
3648 QObject *o = component.create();
3651 QCOMPARE(o->property("test").toBool(), true);
3657 QDeclarativeComponent component(&engine, TEST_FILE("aliasWritesOverrideBindings.2.qml"));
3658 QObject *o = component.create();
3661 QCOMPARE(o->property("test").toBool(), true);
3667 QDeclarativeComponent component(&engine, TEST_FILE("aliasWritesOverrideBindings.3.qml"));
3668 QObject *o = component.create();
3671 QCOMPARE(o->property("test").toBool(), true);
3677 // Allow an alais to a composite element
3679 void tst_qdeclarativeecmascript::aliasToCompositeElement()
3681 QDeclarativeComponent component(&engine, TEST_FILE("aliasToCompositeElement.qml"));
3683 QObject *object = component.create();
3684 QVERIFY(object != 0);
3689 void tst_qdeclarativeecmascript::revisionErrors()
3692 QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevisionErrors.qml"));
3693 QString url = component.url().toString();
3695 QString warning1 = url + ":8: ReferenceError: Can't find variable: prop2";
3696 QString warning2 = url + ":11: ReferenceError: Can't find variable: prop2";
3697 QString warning3 = url + ":13: ReferenceError: Can't find variable: method2";
3699 QTest::ignoreMessage(QtWarningMsg, warning1.toLatin1().constData());
3700 QTest::ignoreMessage(QtWarningMsg, warning2.toLatin1().constData());
3701 QTest::ignoreMessage(QtWarningMsg, warning3.toLatin1().constData());
3702 MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create());
3703 QVERIFY(object != 0);
3707 QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevisionErrors2.qml"));
3708 QString url = component.url().toString();
3710 // MyRevisionedSubclass 1.0 uses MyRevisionedClass revision 0
3711 // method2, prop2 from MyRevisionedClass not available
3712 // method4, prop4 from MyRevisionedSubclass not available
3713 QString warning1 = url + ":8: ReferenceError: Can't find variable: prop2";
3714 QString warning2 = url + ":14: ReferenceError: Can't find variable: prop2";
3715 QString warning3 = url + ":10: ReferenceError: Can't find variable: prop4";
3716 QString warning4 = url + ":16: ReferenceError: Can't find variable: prop4";
3717 QString warning5 = url + ":20: ReferenceError: Can't find variable: method2";
3719 QTest::ignoreMessage(QtWarningMsg, warning1.toLatin1().constData());
3720 QTest::ignoreMessage(QtWarningMsg, warning2.toLatin1().constData());
3721 QTest::ignoreMessage(QtWarningMsg, warning3.toLatin1().constData());
3722 QTest::ignoreMessage(QtWarningMsg, warning4.toLatin1().constData());
3723 QTest::ignoreMessage(QtWarningMsg, warning5.toLatin1().constData());
3724 MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create());
3725 QVERIFY(object != 0);
3729 QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevisionErrors3.qml"));
3730 QString url = component.url().toString();
3732 // MyRevisionedSubclass 1.1 uses MyRevisionedClass revision 1
3733 // All properties/methods available, except MyRevisionedBaseClassUnregistered rev 1
3734 QString warning1 = url + ":30: ReferenceError: Can't find variable: methodD";
3735 QString warning2 = url + ":10: ReferenceError: Can't find variable: propD";
3736 QString warning3 = url + ":20: ReferenceError: Can't find variable: propD";
3737 QTest::ignoreMessage(QtWarningMsg, warning1.toLatin1().constData());
3738 QTest::ignoreMessage(QtWarningMsg, warning2.toLatin1().constData());
3739 QTest::ignoreMessage(QtWarningMsg, warning3.toLatin1().constData());
3740 MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create());
3741 QVERIFY(object != 0);
3746 void tst_qdeclarativeecmascript::revision()
3749 QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevision.qml"));
3750 QString url = component.url().toString();
3752 MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create());
3753 QVERIFY(object != 0);
3757 QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevision2.qml"));
3758 QString url = component.url().toString();
3760 MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create());
3761 QVERIFY(object != 0);
3765 QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevision3.qml"));
3766 QString url = component.url().toString();
3768 MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create());
3769 QVERIFY(object != 0);
3772 // Test that non-root classes can resolve revisioned methods
3774 QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevision4.qml"));
3776 QObject *object = component.create();
3777 QVERIFY(object != 0);
3778 QCOMPARE(object->property("test").toReal(), 11.);
3783 void tst_qdeclarativeecmascript::realToInt()
3785 QDeclarativeComponent component(&engine, TEST_FILE("realToInt.qml"));
3786 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
3787 QVERIFY(object != 0);
3789 QMetaObject::invokeMethod(object, "test1");
3790 QCOMPARE(object->value(), int(4));
3791 QMetaObject::invokeMethod(object, "test2");
3792 QCOMPARE(object->value(), int(8));
3794 void tst_qdeclarativeecmascript::dynamicString()
3796 QDeclarativeComponent component(&engine, TEST_FILE("dynamicString.qml"));
3797 QObject *object = component.create();
3798 QVERIFY(object != 0);
3799 QCOMPARE(object->property("stringProperty").toString(),
3800 QString::fromLatin1("string:Hello World false:0 true:1 uint32:100 int32:-100 double:3.14159 date:2011-02-11 05::30:50!"));
3803 QTEST_MAIN(tst_qdeclarativeecmascript)
3805 #include "tst_qdeclarativeecmascript.moc"