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 <private/qscriptdeclarativeclass_p.h>
53 #include "testtypes.h"
54 #include "testhttpserver.h"
55 #include "../../../shared/util.h"
58 // In Symbian OS test data is located in applications private dir
63 This test covers evaluation of ECMAScript expressions and bindings from within
64 QML. This does not include static QML language issues.
66 Static QML language issues are covered in qmllanguage
68 inline QUrl TEST_FILE(const QString &filename)
70 QFileInfo fileInfo(__FILE__);
71 return QUrl::fromLocalFile(fileInfo.absoluteDir().filePath("data/" + filename));
74 inline QUrl TEST_FILE(const char *filename)
76 return TEST_FILE(QLatin1String(filename));
79 class tst_qdeclarativeecmascript : public QObject
83 tst_qdeclarativeecmascript() {}
87 void assignBasicTypes();
88 void idShortcutInvalidates();
89 void boolPropertiesEvaluateAsBool();
91 void signalAssignment();
93 void basicExpressions();
94 void basicExpressions_data();
95 void arrayExpressions();
96 void contextPropertiesTriggerReeval();
97 void objectPropertiesTriggerReeval();
98 void deferredProperties();
99 void deferredPropertiesErrors();
100 void extensionObjects();
101 void overrideExtensionProperties();
102 void attachedProperties();
104 void valueTypeFunctions();
105 void constantsOverrideBindings();
106 void outerBindingOverridesInnerBinding();
107 void aliasPropertyAndBinding();
108 void nonExistentAttachedObject();
111 void signalParameterTypes();
112 void objectsCompareAsEqual();
113 void dynamicCreation_data();
114 void dynamicCreation();
115 void dynamicDestruction();
116 void objectToString();
117 void selfDeletingBinding();
118 void extendedObjectPropertyLookup();
120 void functionErrors();
121 void propertyAssignmentErrors();
122 void signalTriggeredBindings();
123 void listProperties();
124 void exceptionClearsOnReeval();
125 void exceptionSlotProducesWarning();
126 void exceptionBindingProducesWarning();
127 void transientErrors();
128 void shutdownErrors();
129 void compositePropertyType();
131 void undefinedResetsProperty();
132 void listToVariant();
133 void multiEngineObject();
134 void deletedObject();
135 void attachedPropertyScope();
136 void scriptConnect();
137 void scriptDisconnect();
139 void cppOwnershipReturnValue();
140 void ownershipCustomReturnValue();
141 void qlistqobjectMethods();
142 void strictlyEquals();
144 void numberAssignment();
145 void propertySplicing();
146 void signalWithUnknownTypes();
148 void importScripts();
149 void scarceResources();
150 void propertyChangeSlots();
151 void elementAssign();
152 void objectPassThroughSignals();
156 void dynamicCreationCrash();
158 void nullObjectBinding();
159 void deletedEngine();
160 void libraryScriptAssert();
161 void variantsAssignedUndefined();
163 void qtcreatorbug_1289();
164 void noSpuriousWarningsAtShutdown();
165 void canAssignNullToQObject();
166 void functionAssignment_fromBinding();
167 void functionAssignment_fromJS();
168 void functionAssignment_fromJS_data();
169 void functionAssignmentfromJS_invalid();
175 void nonscriptable();
178 void sharedAttachedObject();
180 void writeRemovesBinding();
181 void aliasBindingsAssignCorrectly();
182 void aliasBindingsOverrideTarget();
183 void aliasWritesOverrideBindings();
188 void callQtInvokables();
189 void invokableObjectArg();
190 void invokableObjectRet();
192 void revisionErrors();
196 QDeclarativeEngine engine;
199 void tst_qdeclarativeecmascript::initTestCase() { registerTypes(); }
201 void tst_qdeclarativeecmascript::assignBasicTypes()
204 QDeclarativeComponent component(&engine, TEST_FILE("assignBasicTypes.qml"));
205 MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
206 QVERIFY(object != 0);
207 QCOMPARE(object->flagProperty(), MyTypeObject::FlagVal1 | MyTypeObject::FlagVal3);
208 QCOMPARE(object->enumProperty(), MyTypeObject::EnumVal2);
209 QCOMPARE(object->stringProperty(), QString("Hello World!"));
210 QCOMPARE(object->uintProperty(), uint(10));
211 QCOMPARE(object->intProperty(), -19);
212 QCOMPARE((float)object->realProperty(), float(23.2));
213 QCOMPARE((float)object->doubleProperty(), float(-19.75));
214 QCOMPARE((float)object->floatProperty(), float(8.5));
215 QCOMPARE(object->colorProperty(), QColor("red"));
216 QCOMPARE(object->dateProperty(), QDate(1982, 11, 25));
217 QCOMPARE(object->timeProperty(), QTime(11, 11, 32));
218 QCOMPARE(object->dateTimeProperty(), QDateTime(QDate(2009, 5, 12), QTime(13, 22, 1)));
219 QCOMPARE(object->pointProperty(), QPoint(99,13));
220 QCOMPARE(object->pointFProperty(), QPointF(-10.1, 12.3));
221 QCOMPARE(object->sizeProperty(), QSize(99, 13));
222 QCOMPARE(object->sizeFProperty(), QSizeF(0.1, 0.2));
223 QCOMPARE(object->rectProperty(), QRect(9, 7, 100, 200));
224 QCOMPARE(object->rectFProperty(), QRectF(1000.1, -10.9, 400, 90.99));
225 QCOMPARE(object->boolProperty(), true);
226 QCOMPARE(object->variantProperty(), QVariant("Hello World!"));
227 QCOMPARE(object->vectorProperty(), QVector3D(10, 1, 2.2));
228 QCOMPARE(object->urlProperty(), component.url().resolved(QUrl("main.qml")));
232 QDeclarativeComponent component(&engine, TEST_FILE("assignBasicTypes.2.qml"));
233 MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
234 QVERIFY(object != 0);
235 QCOMPARE(object->flagProperty(), MyTypeObject::FlagVal1 | MyTypeObject::FlagVal3);
236 QCOMPARE(object->enumProperty(), MyTypeObject::EnumVal2);
237 QCOMPARE(object->stringProperty(), QString("Hello World!"));
238 QCOMPARE(object->uintProperty(), uint(10));
239 QCOMPARE(object->intProperty(), -19);
240 QCOMPARE((float)object->realProperty(), float(23.2));
241 QCOMPARE((float)object->doubleProperty(), float(-19.75));
242 QCOMPARE((float)object->floatProperty(), float(8.5));
243 QCOMPARE(object->colorProperty(), QColor("red"));
244 QCOMPARE(object->dateProperty(), QDate(1982, 11, 25));
245 QCOMPARE(object->timeProperty(), QTime(11, 11, 32));
246 QCOMPARE(object->dateTimeProperty(), QDateTime(QDate(2009, 5, 12), QTime(13, 22, 1)));
247 QCOMPARE(object->pointProperty(), QPoint(99,13));
248 QCOMPARE(object->pointFProperty(), QPointF(-10.1, 12.3));
249 QCOMPARE(object->sizeProperty(), QSize(99, 13));
250 QCOMPARE(object->sizeFProperty(), QSizeF(0.1, 0.2));
251 QCOMPARE(object->rectProperty(), QRect(9, 7, 100, 200));
252 QCOMPARE(object->rectFProperty(), QRectF(1000.1, -10.9, 400, 90.99));
253 QCOMPARE(object->boolProperty(), true);
254 QCOMPARE(object->variantProperty(), QVariant("Hello World!"));
255 QCOMPARE(object->vectorProperty(), QVector3D(10, 1, 2.2));
256 QCOMPARE(object->urlProperty(), component.url().resolved(QUrl("main.qml")));
261 void tst_qdeclarativeecmascript::idShortcutInvalidates()
264 QDeclarativeComponent component(&engine, TEST_FILE("idShortcutInvalidates.qml"));
265 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
266 QVERIFY(object != 0);
267 QVERIFY(object->objectProperty() != 0);
268 delete object->objectProperty();
269 QVERIFY(object->objectProperty() == 0);
274 QDeclarativeComponent component(&engine, TEST_FILE("idShortcutInvalidates.1.qml"));
275 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
276 QVERIFY(object != 0);
277 QVERIFY(object->objectProperty() != 0);
278 delete object->objectProperty();
279 QVERIFY(object->objectProperty() == 0);
284 void tst_qdeclarativeecmascript::boolPropertiesEvaluateAsBool()
287 QDeclarativeComponent component(&engine, TEST_FILE("boolPropertiesEvaluateAsBool.1.qml"));
288 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
289 QVERIFY(object != 0);
290 QCOMPARE(object->stringProperty(), QLatin1String("pass"));
294 QDeclarativeComponent component(&engine, TEST_FILE("boolPropertiesEvaluateAsBool.2.qml"));
295 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
296 QVERIFY(object != 0);
297 QCOMPARE(object->stringProperty(), QLatin1String("pass"));
302 void tst_qdeclarativeecmascript::signalAssignment()
305 QDeclarativeComponent component(&engine, TEST_FILE("signalAssignment.1.qml"));
306 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
307 QVERIFY(object != 0);
308 QCOMPARE(object->string(), QString());
309 emit object->basicSignal();
310 QCOMPARE(object->string(), QString("pass"));
315 QDeclarativeComponent component(&engine, TEST_FILE("signalAssignment.2.qml"));
316 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
317 QVERIFY(object != 0);
318 QCOMPARE(object->string(), QString());
319 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
320 QCOMPARE(object->string(), QString("pass 19 Hello world! 10.25 3 2"));
325 void tst_qdeclarativeecmascript::methods()
328 QDeclarativeComponent component(&engine, TEST_FILE("methods.1.qml"));
329 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
330 QVERIFY(object != 0);
331 QCOMPARE(object->methodCalled(), false);
332 QCOMPARE(object->methodIntCalled(), false);
333 emit object->basicSignal();
334 QCOMPARE(object->methodCalled(), true);
335 QCOMPARE(object->methodIntCalled(), false);
340 QDeclarativeComponent component(&engine, TEST_FILE("methods.2.qml"));
341 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
342 QVERIFY(object != 0);
343 QCOMPARE(object->methodCalled(), false);
344 QCOMPARE(object->methodIntCalled(), false);
345 emit object->basicSignal();
346 QCOMPARE(object->methodCalled(), false);
347 QCOMPARE(object->methodIntCalled(), true);
352 QDeclarativeComponent component(&engine, TEST_FILE("methods.3.qml"));
353 QObject *object = component.create();
354 QVERIFY(object != 0);
355 QCOMPARE(object->property("test").toInt(), 19);
360 QDeclarativeComponent component(&engine, TEST_FILE("methods.4.qml"));
361 QObject *object = component.create();
362 QVERIFY(object != 0);
363 QCOMPARE(object->property("test").toInt(), 19);
364 QCOMPARE(object->property("test2").toInt(), 17);
365 QCOMPARE(object->property("test3").toInt(), 16);
370 QDeclarativeComponent component(&engine, TEST_FILE("methods.5.qml"));
371 QObject *object = component.create();
372 QVERIFY(object != 0);
373 QCOMPARE(object->property("test").toInt(), 9);
378 void tst_qdeclarativeecmascript::bindingLoop()
380 QDeclarativeComponent component(&engine, TEST_FILE("bindingLoop.qml"));
381 QString warning = component.url().toString() + ":9:9: QML MyQmlObject: Binding loop detected for property \"stringProperty\"";
382 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
383 QObject *object = component.create();
384 QVERIFY(object != 0);
388 void tst_qdeclarativeecmascript::basicExpressions_data()
390 QTest::addColumn<QString>("expression");
391 QTest::addColumn<QVariant>("result");
392 QTest::addColumn<bool>("nest");
394 QTest::newRow("Syntax error (self test)") << "{console.log({'a':1'}.a)}" << QVariant() << false;
395 QTest::newRow("Context property") << "a" << QVariant(1944) << false;
396 QTest::newRow("Context property") << "a" << QVariant(1944) << true;
397 QTest::newRow("Context property expression") << "a * 2" << QVariant(3888) << false;
398 QTest::newRow("Context property expression") << "a * 2" << QVariant(3888) << true;
399 QTest::newRow("Overridden context property") << "b" << QVariant("Milk") << false;
400 QTest::newRow("Overridden context property") << "b" << QVariant("Cow") << true;
401 QTest::newRow("Object property") << "object.stringProperty" << QVariant("Object1") << false;
402 QTest::newRow("Object property") << "object.stringProperty" << QVariant("Object1") << true;
403 QTest::newRow("Overridden object property") << "objectOverride.stringProperty" << QVariant("Object2") << false;
404 QTest::newRow("Overridden object property") << "objectOverride.stringProperty" << QVariant("Object3") << true;
405 QTest::newRow("Default object property") << "horseLegs" << QVariant(4) << false;
406 QTest::newRow("Default object property") << "antLegs" << QVariant(6) << false;
407 QTest::newRow("Default object property") << "emuLegs" << QVariant(2) << false;
408 QTest::newRow("Nested default object property") << "horseLegs" << QVariant(4) << true;
409 QTest::newRow("Nested default object property") << "antLegs" << QVariant(7) << true;
410 QTest::newRow("Nested default object property") << "emuLegs" << QVariant(2) << true;
411 QTest::newRow("Nested default object property") << "humanLegs" << QVariant(2) << true;
412 QTest::newRow("Context property override default object property") << "millipedeLegs" << QVariant(100) << true;
415 void tst_qdeclarativeecmascript::basicExpressions()
417 QFETCH(QString, expression);
418 QFETCH(QVariant, result);
424 MyDefaultObject1 default1;
425 MyDefaultObject3 default3;
426 object1.setStringProperty("Object1");
427 object2.setStringProperty("Object2");
428 object3.setStringProperty("Object3");
430 QDeclarativeContext context(engine.rootContext());
431 QDeclarativeContext nestedContext(&context);
433 context.setContextObject(&default1);
434 context.setContextProperty("a", QVariant(1944));
435 context.setContextProperty("b", QVariant("Milk"));
436 context.setContextProperty("object", &object1);
437 context.setContextProperty("objectOverride", &object2);
438 nestedContext.setContextObject(&default3);
439 nestedContext.setContextProperty("b", QVariant("Cow"));
440 nestedContext.setContextProperty("objectOverride", &object3);
441 nestedContext.setContextProperty("millipedeLegs", QVariant(100));
443 MyExpression expr(nest?&nestedContext:&context, expression);
444 QCOMPARE(expr.evaluate(), result);
447 void tst_qdeclarativeecmascript::arrayExpressions()
453 QDeclarativeContext context(engine.rootContext());
454 context.setContextProperty("a", &obj1);
455 context.setContextProperty("b", &obj2);
456 context.setContextProperty("c", &obj3);
458 MyExpression expr(&context, "[a, b, c, 10]");
459 QVariant result = expr.evaluate();
460 QCOMPARE(result.userType(), qMetaTypeId<QList<QObject *> >());
461 QList<QObject *> list = qvariant_cast<QList<QObject *> >(result);
462 QCOMPARE(list.count(), 4);
463 QCOMPARE(list.at(0), &obj1);
464 QCOMPARE(list.at(1), &obj2);
465 QCOMPARE(list.at(2), &obj3);
466 QCOMPARE(list.at(3), (QObject *)0);
469 // Tests that modifying a context property will reevaluate expressions
470 void tst_qdeclarativeecmascript::contextPropertiesTriggerReeval()
472 QDeclarativeContext context(engine.rootContext());
475 MyQmlObject *object3 = new MyQmlObject;
477 object1.setStringProperty("Hello");
478 object2.setStringProperty("World");
480 context.setContextProperty("testProp", QVariant(1));
481 context.setContextProperty("testObj", &object1);
482 context.setContextProperty("testObj2", object3);
485 MyExpression expr(&context, "testProp + 1");
486 QCOMPARE(expr.changed, false);
487 QCOMPARE(expr.evaluate(), QVariant(2));
489 context.setContextProperty("testProp", QVariant(2));
490 QCOMPARE(expr.changed, true);
491 QCOMPARE(expr.evaluate(), QVariant(3));
495 MyExpression expr(&context, "testProp + testProp + testProp");
496 QCOMPARE(expr.changed, false);
497 QCOMPARE(expr.evaluate(), QVariant(6));
499 context.setContextProperty("testProp", QVariant(4));
500 QCOMPARE(expr.changed, true);
501 QCOMPARE(expr.evaluate(), QVariant(12));
505 MyExpression expr(&context, "testObj.stringProperty");
506 QCOMPARE(expr.changed, false);
507 QCOMPARE(expr.evaluate(), QVariant("Hello"));
509 context.setContextProperty("testObj", &object2);
510 QCOMPARE(expr.changed, true);
511 QCOMPARE(expr.evaluate(), QVariant("World"));
515 MyExpression expr(&context, "testObj.stringProperty /**/");
516 QCOMPARE(expr.changed, false);
517 QCOMPARE(expr.evaluate(), QVariant("World"));
519 context.setContextProperty("testObj", &object1);
520 QCOMPARE(expr.changed, true);
521 QCOMPARE(expr.evaluate(), QVariant("Hello"));
525 MyExpression expr(&context, "testObj2");
526 QCOMPARE(expr.changed, false);
527 QCOMPARE(expr.evaluate(), QVariant::fromValue((QObject *)object3));
533 void tst_qdeclarativeecmascript::objectPropertiesTriggerReeval()
535 QDeclarativeContext context(engine.rootContext());
539 context.setContextProperty("testObj", &object1);
541 object1.setStringProperty(QLatin1String("Hello"));
542 object2.setStringProperty(QLatin1String("Dog"));
543 object3.setStringProperty(QLatin1String("Cat"));
546 MyExpression expr(&context, "testObj.stringProperty");
547 QCOMPARE(expr.changed, false);
548 QCOMPARE(expr.evaluate(), QVariant("Hello"));
550 object1.setStringProperty(QLatin1String("World"));
551 QCOMPARE(expr.changed, true);
552 QCOMPARE(expr.evaluate(), QVariant("World"));
556 MyExpression expr(&context, "testObj.objectProperty.stringProperty");
557 QCOMPARE(expr.changed, false);
558 QCOMPARE(expr.evaluate(), QVariant());
560 object1.setObjectProperty(&object2);
561 QCOMPARE(expr.changed, true);
562 expr.changed = false;
563 QCOMPARE(expr.evaluate(), QVariant("Dog"));
565 object1.setObjectProperty(&object3);
566 QCOMPARE(expr.changed, true);
567 expr.changed = false;
568 QCOMPARE(expr.evaluate(), QVariant("Cat"));
570 object1.setObjectProperty(0);
571 QCOMPARE(expr.changed, true);
572 expr.changed = false;
573 QCOMPARE(expr.evaluate(), QVariant());
575 object1.setObjectProperty(&object3);
576 QCOMPARE(expr.changed, true);
577 expr.changed = false;
578 QCOMPARE(expr.evaluate(), QVariant("Cat"));
580 object3.setStringProperty("Donkey");
581 QCOMPARE(expr.changed, true);
582 expr.changed = false;
583 QCOMPARE(expr.evaluate(), QVariant("Donkey"));
587 void tst_qdeclarativeecmascript::deferredProperties()
589 QDeclarativeComponent component(&engine, TEST_FILE("deferredProperties.qml"));
590 MyDeferredObject *object =
591 qobject_cast<MyDeferredObject *>(component.create());
592 QVERIFY(object != 0);
593 QCOMPARE(object->value(), 0);
594 QVERIFY(object->objectProperty() == 0);
595 QVERIFY(object->objectProperty2() != 0);
596 qmlExecuteDeferred(object);
597 QCOMPARE(object->value(), 10);
598 QVERIFY(object->objectProperty() != 0);
599 MyQmlObject *qmlObject =
600 qobject_cast<MyQmlObject *>(object->objectProperty());
601 QVERIFY(qmlObject != 0);
602 QCOMPARE(qmlObject->value(), 10);
603 object->setValue(19);
604 QCOMPARE(qmlObject->value(), 19);
609 // Check errors on deferred properties are correctly emitted
610 void tst_qdeclarativeecmascript::deferredPropertiesErrors()
612 QDeclarativeComponent component(&engine, TEST_FILE("deferredPropertiesErrors.qml"));
613 MyDeferredObject *object =
614 qobject_cast<MyDeferredObject *>(component.create());
615 QVERIFY(object != 0);
616 QCOMPARE(object->value(), 0);
617 QVERIFY(object->objectProperty() == 0);
618 QVERIFY(object->objectProperty2() == 0);
620 QString warning = component.url().toString() + ":6: Unable to assign [undefined] to QObject* objectProperty";
621 QTest::ignoreMessage(QtWarningMsg, qPrintable(warning));
623 qmlExecuteDeferred(object);
628 void tst_qdeclarativeecmascript::extensionObjects()
630 QDeclarativeComponent component(&engine, TEST_FILE("extensionObjects.qml"));
631 MyExtendedObject *object =
632 qobject_cast<MyExtendedObject *>(component.create());
633 QVERIFY(object != 0);
634 QCOMPARE(object->baseProperty(), 13);
635 QCOMPARE(object->coreProperty(), 9);
636 object->setProperty("extendedProperty", QVariant(11));
637 object->setProperty("baseExtendedProperty", QVariant(92));
638 QCOMPARE(object->coreProperty(), 11);
639 QCOMPARE(object->baseProperty(), 92);
641 MyExtendedObject *nested = qobject_cast<MyExtendedObject*>(qvariant_cast<QObject *>(object->property("nested")));
643 QCOMPARE(nested->baseProperty(), 13);
644 QCOMPARE(nested->coreProperty(), 9);
645 nested->setProperty("extendedProperty", QVariant(11));
646 nested->setProperty("baseExtendedProperty", QVariant(92));
647 QCOMPARE(nested->coreProperty(), 11);
648 QCOMPARE(nested->baseProperty(), 92);
653 void tst_qdeclarativeecmascript::overrideExtensionProperties()
655 QDeclarativeComponent component(&engine, TEST_FILE("extensionObjectsPropertyOverride.qml"));
656 OverrideDefaultPropertyObject *object =
657 qobject_cast<OverrideDefaultPropertyObject *>(component.create());
658 QVERIFY(object != 0);
659 QVERIFY(object->secondProperty() != 0);
660 QVERIFY(object->firstProperty() == 0);
665 void tst_qdeclarativeecmascript::attachedProperties()
668 QDeclarativeComponent component(&engine, TEST_FILE("attachedProperty.qml"));
669 QObject *object = component.create();
670 QVERIFY(object != 0);
671 QCOMPARE(object->property("a").toInt(), 19);
672 QCOMPARE(object->property("b").toInt(), 19);
673 QCOMPARE(object->property("c").toInt(), 19);
674 QCOMPARE(object->property("d").toInt(), 19);
679 QDeclarativeComponent component(&engine, TEST_FILE("attachedProperty.2.qml"));
680 QObject *object = component.create();
681 QVERIFY(object != 0);
682 QCOMPARE(object->property("a").toInt(), 26);
683 QCOMPARE(object->property("b").toInt(), 26);
684 QCOMPARE(object->property("c").toInt(), 26);
685 QCOMPARE(object->property("d").toInt(), 26);
689 QDeclarativeComponent component(&engine, TEST_FILE("writeAttachedProperty.qml"));
690 QObject *object = component.create();
691 QVERIFY(object != 0);
693 QMetaObject::invokeMethod(object, "writeValue2");
695 MyQmlAttachedObject *attached =
696 qobject_cast<MyQmlAttachedObject *>(qmlAttachedPropertiesObject<MyQmlObject>(object));
697 QVERIFY(attached != 0);
699 QCOMPARE(attached->value2(), 9);
704 void tst_qdeclarativeecmascript::enums()
708 QDeclarativeComponent component(&engine, TEST_FILE("enums.1.qml"));
709 QObject *object = component.create();
710 QVERIFY(object != 0);
712 QCOMPARE(object->property("a").toInt(), 0);
713 QCOMPARE(object->property("b").toInt(), 1);
714 QCOMPARE(object->property("c").toInt(), 2);
715 QCOMPARE(object->property("d").toInt(), 3);
716 QCOMPARE(object->property("e").toInt(), 0);
717 QCOMPARE(object->property("f").toInt(), 1);
718 QCOMPARE(object->property("g").toInt(), 2);
719 QCOMPARE(object->property("h").toInt(), 3);
720 QCOMPARE(object->property("i").toInt(), 19);
721 QCOMPARE(object->property("j").toInt(), 19);
725 // Non-existent enums
727 QDeclarativeComponent component(&engine, TEST_FILE("enums.2.qml"));
729 QString warning1 = component.url().toString() + ":5: Unable to assign [undefined] to int a";
730 QString warning2 = component.url().toString() + ":6: Unable to assign [undefined] to int b";
731 QTest::ignoreMessage(QtWarningMsg, qPrintable(warning1));
732 QTest::ignoreMessage(QtWarningMsg, qPrintable(warning2));
734 QObject *object = component.create();
735 QVERIFY(object != 0);
736 QCOMPARE(object->property("a").toInt(), 0);
737 QCOMPARE(object->property("b").toInt(), 0);
743 void tst_qdeclarativeecmascript::valueTypeFunctions()
745 QDeclarativeComponent component(&engine, TEST_FILE("valueTypeFunctions.qml"));
746 MyTypeObject *obj = qobject_cast<MyTypeObject*>(component.create());
748 QCOMPARE(obj->rectProperty(), QRect(0,0,100,100));
749 QCOMPARE(obj->rectFProperty(), QRectF(0,0.5,100,99.5));
755 Tests that writing a constant to a property with a binding on it disables the
758 void tst_qdeclarativeecmascript::constantsOverrideBindings()
762 QDeclarativeComponent component(&engine, TEST_FILE("constantsOverrideBindings.1.qml"));
763 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
764 QVERIFY(object != 0);
766 QCOMPARE(object->property("c2").toInt(), 0);
767 object->setProperty("c1", QVariant(9));
768 QCOMPARE(object->property("c2").toInt(), 9);
770 emit object->basicSignal();
772 QCOMPARE(object->property("c2").toInt(), 13);
773 object->setProperty("c1", QVariant(8));
774 QCOMPARE(object->property("c2").toInt(), 13);
779 // During construction
781 QDeclarativeComponent component(&engine, TEST_FILE("constantsOverrideBindings.2.qml"));
782 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
783 QVERIFY(object != 0);
785 QCOMPARE(object->property("c1").toInt(), 0);
786 QCOMPARE(object->property("c2").toInt(), 10);
787 object->setProperty("c1", QVariant(9));
788 QCOMPARE(object->property("c1").toInt(), 9);
789 QCOMPARE(object->property("c2").toInt(), 10);
797 QDeclarativeComponent component(&engine, TEST_FILE("constantsOverrideBindings.3.qml"));
798 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
799 QVERIFY(object != 0);
801 QCOMPARE(object->property("c2").toInt(), 0);
802 object->setProperty("c1", QVariant(9));
803 QCOMPARE(object->property("c2").toInt(), 9);
805 object->setProperty("c2", QVariant(13));
806 QCOMPARE(object->property("c2").toInt(), 13);
807 object->setProperty("c1", QVariant(7));
808 QCOMPARE(object->property("c1").toInt(), 7);
809 QCOMPARE(object->property("c2").toInt(), 13);
817 QDeclarativeComponent component(&engine, TEST_FILE("constantsOverrideBindings.4.qml"));
818 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
819 QVERIFY(object != 0);
821 QCOMPARE(object->property("c1").toInt(), 0);
822 QCOMPARE(object->property("c3").toInt(), 10);
823 object->setProperty("c1", QVariant(9));
824 QCOMPARE(object->property("c1").toInt(), 9);
825 QCOMPARE(object->property("c3").toInt(), 10);
832 Tests that assigning a binding to a property that already has a binding causes
833 the original binding to be disabled.
835 void tst_qdeclarativeecmascript::outerBindingOverridesInnerBinding()
837 QDeclarativeComponent component(&engine,
838 TEST_FILE("outerBindingOverridesInnerBinding.qml"));
839 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
840 QVERIFY(object != 0);
842 QCOMPARE(object->property("c1").toInt(), 0);
843 QCOMPARE(object->property("c2").toInt(), 0);
844 QCOMPARE(object->property("c3").toInt(), 0);
846 object->setProperty("c1", QVariant(9));
847 QCOMPARE(object->property("c1").toInt(), 9);
848 QCOMPARE(object->property("c2").toInt(), 0);
849 QCOMPARE(object->property("c3").toInt(), 0);
851 object->setProperty("c3", QVariant(8));
852 QCOMPARE(object->property("c1").toInt(), 9);
853 QCOMPARE(object->property("c2").toInt(), 8);
854 QCOMPARE(object->property("c3").toInt(), 8);
860 Access a non-existent attached object.
862 Tests for a regression where this used to crash.
864 void tst_qdeclarativeecmascript::nonExistentAttachedObject()
866 QDeclarativeComponent component(&engine, TEST_FILE("nonExistentAttachedObject.qml"));
868 QString warning = component.url().toString() + ":4: Unable to assign [undefined] to QString stringProperty";
869 QTest::ignoreMessage(QtWarningMsg, qPrintable(warning));
871 QObject *object = component.create();
872 QVERIFY(object != 0);
877 void tst_qdeclarativeecmascript::scope()
880 QDeclarativeComponent component(&engine, TEST_FILE("scope.qml"));
881 QObject *object = component.create();
882 QVERIFY(object != 0);
884 QCOMPARE(object->property("test1").toInt(), 1);
885 QCOMPARE(object->property("test2").toInt(), 2);
886 QCOMPARE(object->property("test3").toString(), QString("1Test"));
887 QCOMPARE(object->property("test4").toString(), QString("2Test"));
888 QCOMPARE(object->property("test5").toInt(), 1);
889 QCOMPARE(object->property("test6").toInt(), 1);
890 QCOMPARE(object->property("test7").toInt(), 2);
891 QCOMPARE(object->property("test8").toInt(), 2);
892 QCOMPARE(object->property("test9").toInt(), 1);
893 QCOMPARE(object->property("test10").toInt(), 3);
899 QDeclarativeComponent component(&engine, TEST_FILE("scope.2.qml"));
900 QObject *object = component.create();
901 QVERIFY(object != 0);
903 QCOMPARE(object->property("test1").toInt(), 19);
904 QCOMPARE(object->property("test2").toInt(), 19);
905 QCOMPARE(object->property("test3").toInt(), 14);
906 QCOMPARE(object->property("test4").toInt(), 14);
907 QCOMPARE(object->property("test5").toInt(), 24);
908 QCOMPARE(object->property("test6").toInt(), 24);
914 QDeclarativeComponent component(&engine, TEST_FILE("scope.3.qml"));
915 QObject *object = component.create();
916 QVERIFY(object != 0);
918 QCOMPARE(object->property("test1").toBool(), true);
919 QCOMPARE(object->property("test2").toBool(), true);
920 QCOMPARE(object->property("test3").toBool(), true);
925 // Signal argument scope
927 QDeclarativeComponent component(&engine, TEST_FILE("scope.4.qml"));
928 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
929 QVERIFY(object != 0);
931 QCOMPARE(object->property("test").toInt(), 0);
932 QCOMPARE(object->property("test2").toString(), QString());
934 emit object->argumentSignal(13, "Argument Scope", 9, MyQmlObject::EnumValue4, Qt::RightButton);
936 QCOMPARE(object->property("test").toInt(), 13);
937 QCOMPARE(object->property("test2").toString(), QString("Argument Scope"));
943 QDeclarativeComponent component(&engine, TEST_FILE("scope.5.qml"));
944 QObject *object = component.create();
945 QVERIFY(object != 0);
947 QCOMPARE(object->property("test1").toBool(), true);
948 QCOMPARE(object->property("test2").toBool(), true);
954 QDeclarativeComponent component(&engine, TEST_FILE("scope.6.qml"));
955 QObject *object = component.create();
956 QVERIFY(object != 0);
958 QCOMPARE(object->property("test").toBool(), true);
964 // In 4.7, non-library javascript files that had no imports shared the imports of their
966 void tst_qdeclarativeecmascript::importScope()
968 QDeclarativeComponent component(&engine, TEST_FILE("importScope.qml"));
969 QObject *o = component.create();
972 QCOMPARE(o->property("test").toInt(), 240);
978 Tests that "any" type passes through a synthesized signal parameter. This
979 is essentially a test of QDeclarativeMetaType::copy()
981 void tst_qdeclarativeecmascript::signalParameterTypes()
983 QDeclarativeComponent component(&engine, TEST_FILE("signalParameterTypes.qml"));
984 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
985 QVERIFY(object != 0);
987 emit object->basicSignal();
989 QCOMPARE(object->property("intProperty").toInt(), 10);
990 QCOMPARE(object->property("realProperty").toReal(), 19.2);
991 QVERIFY(object->property("colorProperty").value<QColor>() == QColor(255, 255, 0, 255));
992 QVERIFY(object->property("variantProperty") == QVariant::fromValue(QColor(255, 0, 255, 255)));
993 QVERIFY(object->property("enumProperty") == MyQmlObject::EnumValue3);
994 QVERIFY(object->property("qtEnumProperty") == Qt::LeftButton);
1000 Test that two JS objects for the same QObject compare as equal.
1002 void tst_qdeclarativeecmascript::objectsCompareAsEqual()
1004 QDeclarativeComponent component(&engine, TEST_FILE("objectsCompareAsEqual.qml"));
1005 QObject *object = component.create();
1006 QVERIFY(object != 0);
1008 QCOMPARE(object->property("test1").toBool(), true);
1009 QCOMPARE(object->property("test2").toBool(), true);
1010 QCOMPARE(object->property("test3").toBool(), true);
1011 QCOMPARE(object->property("test4").toBool(), true);
1012 QCOMPARE(object->property("test5").toBool(), true);
1018 Confirm bindings and alias properties can coexist.
1020 Tests for a regression where the binding would not reevaluate.
1022 void tst_qdeclarativeecmascript::aliasPropertyAndBinding()
1024 QDeclarativeComponent component(&engine, TEST_FILE("aliasPropertyAndBinding.qml"));
1025 QObject *object = component.create();
1026 QVERIFY(object != 0);
1028 QCOMPARE(object->property("c2").toInt(), 3);
1029 QCOMPARE(object->property("c3").toInt(), 3);
1031 object->setProperty("c2", QVariant(19));
1033 QCOMPARE(object->property("c2").toInt(), 19);
1034 QCOMPARE(object->property("c3").toInt(), 19);
1039 void tst_qdeclarativeecmascript::dynamicCreation_data()
1041 QTest::addColumn<QString>("method");
1042 QTest::addColumn<QString>("createdName");
1044 QTest::newRow("One") << "createOne" << "objectOne";
1045 QTest::newRow("Two") << "createTwo" << "objectTwo";
1046 QTest::newRow("Three") << "createThree" << "objectThree";
1050 Test using createQmlObject to dynamically generate an item
1051 Also using createComponent is tested.
1053 void tst_qdeclarativeecmascript::dynamicCreation()
1055 QFETCH(QString, method);
1056 QFETCH(QString, createdName);
1058 QDeclarativeComponent component(&engine, TEST_FILE("dynamicCreation.qml"));
1059 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1060 QVERIFY(object != 0);
1062 QMetaObject::invokeMethod(object, method.toUtf8());
1063 QObject *created = object->objectProperty();
1065 QCOMPARE(created->objectName(), createdName);
1071 Tests the destroy function
1073 void tst_qdeclarativeecmascript::dynamicDestruction()
1075 QDeclarativeComponent component(&engine, TEST_FILE("dynamicDeletion.qml"));
1076 QDeclarativeGuard<MyQmlObject> object = qobject_cast<MyQmlObject*>(component.create());
1077 QVERIFY(object != 0);
1078 QDeclarativeGuard<QObject> createdQmlObject = 0;
1080 QMetaObject::invokeMethod(object, "create");
1081 createdQmlObject = object->objectProperty();
1082 QVERIFY(createdQmlObject);
1083 QCOMPARE(createdQmlObject->objectName(), QString("emptyObject"));
1085 QMetaObject::invokeMethod(object, "killOther");
1086 QVERIFY(createdQmlObject);
1087 QCoreApplication::instance()->processEvents(QEventLoop::DeferredDeletion);
1088 QVERIFY(createdQmlObject);
1089 for (int ii = 0; createdQmlObject && ii < 50; ++ii) { // After 5 seconds we should give up
1090 if (createdQmlObject) {
1092 QCoreApplication::instance()->processEvents(QEventLoop::DeferredDeletion);
1095 QVERIFY(!createdQmlObject);
1097 QDeclarativeEngine::setObjectOwnership(object, QDeclarativeEngine::JavaScriptOwnership);
1098 QMetaObject::invokeMethod(object, "killMe");
1101 QCoreApplication::instance()->processEvents(QEventLoop::DeferredDeletion);
1106 tests that id.toString() works
1108 void tst_qdeclarativeecmascript::objectToString()
1110 QDeclarativeComponent component(&engine, TEST_FILE("declarativeToString.qml"));
1111 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1112 QVERIFY(object != 0);
1113 QMetaObject::invokeMethod(object, "testToString");
1114 QVERIFY(object->stringProperty().startsWith("MyQmlObject_QML_"));
1115 QVERIFY(object->stringProperty().endsWith(", \"objName\")"));
1121 Tests bindings that indirectly cause their own deletion work.
1123 This test is best run under valgrind to ensure no invalid memory access occur.
1125 void tst_qdeclarativeecmascript::selfDeletingBinding()
1128 QDeclarativeComponent component(&engine, TEST_FILE("selfDeletingBinding.qml"));
1129 QObject *object = component.create();
1130 QVERIFY(object != 0);
1131 object->setProperty("triggerDelete", true);
1136 QDeclarativeComponent component(&engine, TEST_FILE("selfDeletingBinding.2.qml"));
1137 QObject *object = component.create();
1138 QVERIFY(object != 0);
1139 object->setProperty("triggerDelete", true);
1145 Test that extended object properties can be accessed.
1147 This test a regression where this used to crash. The issue was specificially
1148 for extended objects that did not include a synthesized meta object (so non-root
1149 and no synthesiszed properties).
1151 void tst_qdeclarativeecmascript::extendedObjectPropertyLookup()
1153 QDeclarativeComponent component(&engine, TEST_FILE("extendedObjectPropertyLookup.qml"));
1154 QObject *object = component.create();
1155 QVERIFY(object != 0);
1160 Test file/lineNumbers for binding/Script errors.
1162 void tst_qdeclarativeecmascript::scriptErrors()
1164 QDeclarativeComponent component(&engine, TEST_FILE("scriptErrors.qml"));
1165 QString url = component.url().toString();
1167 QString warning1 = url.left(url.length() - 3) + "js:2: Error: Invalid write to global property \"a\"";
1168 QString warning2 = url + ":5: ReferenceError: Can't find variable: a";
1169 QString warning3 = url.left(url.length() - 3) + "js:4: Error: Invalid write to global property \"a\"";
1170 QString warning4 = url + ":10: ReferenceError: Can't find variable: a";
1171 QString warning5 = url + ":8: ReferenceError: Can't find variable: a";
1172 QString warning6 = url + ":7: Unable to assign [undefined] to int x";
1173 QString warning7 = url + ":12: Error: Cannot assign to read-only property \"trueProperty\"";
1174 QString warning8 = url + ":13: Error: Cannot assign to non-existent property \"fakeProperty\"";
1176 QTest::ignoreMessage(QtWarningMsg, warning1.toLatin1().constData());
1177 QTest::ignoreMessage(QtWarningMsg, warning2.toLatin1().constData());
1178 QTest::ignoreMessage(QtWarningMsg, warning3.toLatin1().constData());
1179 QTest::ignoreMessage(QtWarningMsg, warning5.toLatin1().constData());
1180 QTest::ignoreMessage(QtWarningMsg, warning6.toLatin1().constData());
1181 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
1182 QVERIFY(object != 0);
1184 QTest::ignoreMessage(QtWarningMsg, warning4.toLatin1().constData());
1185 emit object->basicSignal();
1187 QTest::ignoreMessage(QtWarningMsg, warning7.toLatin1().constData());
1188 emit object->anotherBasicSignal();
1190 QTest::ignoreMessage(QtWarningMsg, warning8.toLatin1().constData());
1191 emit object->thirdBasicSignal();
1197 Test file/lineNumbers for inline functions.
1199 void tst_qdeclarativeecmascript::functionErrors()
1201 QDeclarativeComponent component(&engine, TEST_FILE("functionErrors.qml"));
1202 QString url = component.url().toString();
1204 QString warning = url + ":5: Error: Invalid write to global property \"a\"";
1206 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
1208 QObject *object = component.create();
1209 QVERIFY(object != 0);
1212 // test that if an exception occurs while invoking js function from cpp, it is reported as expected.
1213 QDeclarativeComponent componentTwo(&engine, TEST_FILE("scarceresources/scarceResourceFunctionFail.qml"));
1214 url = componentTwo.url().toString();
1215 object = componentTwo.create();
1216 QVERIFY(object != 0);
1218 QString srpname = object->property("srp_name").toString();
1220 warning = url + QLatin1String(":17: TypeError: Property 'scarceResource' of object ") + srpname +
1221 QLatin1String(" is not a function");
1222 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData()); // we expect a meaningful warning to be printed.
1223 QMetaObject::invokeMethod(object, "retrieveScarceResource");
1228 Test various errors that can occur when assigning a property from script
1230 void tst_qdeclarativeecmascript::propertyAssignmentErrors()
1232 QDeclarativeComponent component(&engine, TEST_FILE("propertyAssignmentErrors.qml"));
1234 QString url = component.url().toString();
1236 QObject *object = component.create();
1237 QVERIFY(object != 0);
1239 QCOMPARE(object->property("test1").toBool(), true);
1240 QCOMPARE(object->property("test2").toBool(), true);
1246 Test bindings still work when the reeval is triggered from within
1249 void tst_qdeclarativeecmascript::signalTriggeredBindings()
1251 QDeclarativeComponent component(&engine, TEST_FILE("signalTriggeredBindings.qml"));
1252 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1253 QVERIFY(object != 0);
1255 QCOMPARE(object->property("base").toReal(), 50.);
1256 QCOMPARE(object->property("test1").toReal(), 50.);
1257 QCOMPARE(object->property("test2").toReal(), 50.);
1259 object->basicSignal();
1261 QCOMPARE(object->property("base").toReal(), 200.);
1262 QCOMPARE(object->property("test1").toReal(), 200.);
1263 QCOMPARE(object->property("test2").toReal(), 200.);
1265 object->argumentSignal(10, QString(), 10, MyQmlObject::EnumValue4, Qt::RightButton);
1267 QCOMPARE(object->property("base").toReal(), 400.);
1268 QCOMPARE(object->property("test1").toReal(), 400.);
1269 QCOMPARE(object->property("test2").toReal(), 400.);
1275 Test that list properties can be iterated from ECMAScript
1277 void tst_qdeclarativeecmascript::listProperties()
1279 QDeclarativeComponent component(&engine, TEST_FILE("listProperties.qml"));
1280 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1281 QVERIFY(object != 0);
1283 QCOMPARE(object->property("test1").toInt(), 21);
1284 QCOMPARE(object->property("test2").toInt(), 2);
1285 QCOMPARE(object->property("test3").toBool(), true);
1286 QCOMPARE(object->property("test4").toBool(), true);
1291 void tst_qdeclarativeecmascript::exceptionClearsOnReeval()
1293 QDeclarativeComponent component(&engine, TEST_FILE("exceptionClearsOnReeval.qml"));
1294 QString url = component.url().toString();
1296 QString warning = url + ":4: TypeError: Cannot read property 'objectProperty' of null";
1298 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
1299 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1300 QVERIFY(object != 0);
1302 QCOMPARE(object->property("test").toBool(), false);
1304 MyQmlObject object2;
1305 MyQmlObject object3;
1306 object2.setObjectProperty(&object3);
1307 object->setObjectProperty(&object2);
1309 QCOMPARE(object->property("test").toBool(), true);
1314 void tst_qdeclarativeecmascript::exceptionSlotProducesWarning()
1316 QDeclarativeComponent component(&engine, TEST_FILE("exceptionProducesWarning.qml"));
1317 QString url = component.url().toString();
1319 QString warning = component.url().toString() + ":6: Error: JS exception";
1321 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
1322 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1323 QVERIFY(object != 0);
1327 void tst_qdeclarativeecmascript::exceptionBindingProducesWarning()
1329 QDeclarativeComponent component(&engine, TEST_FILE("exceptionProducesWarning2.qml"));
1330 QString url = component.url().toString();
1332 QString warning = component.url().toString() + ":5: Error: JS exception";
1334 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
1335 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1336 QVERIFY(object != 0);
1340 static int transientErrorsMsgCount = 0;
1341 static void transientErrorsMsgHandler(QtMsgType, const char *)
1343 ++transientErrorsMsgCount;
1346 // Check that transient binding errors are not displayed
1347 void tst_qdeclarativeecmascript::transientErrors()
1350 QDeclarativeComponent component(&engine, TEST_FILE("transientErrors.qml"));
1352 transientErrorsMsgCount = 0;
1353 QtMsgHandler old = qInstallMsgHandler(transientErrorsMsgHandler);
1355 QObject *object = component.create();
1356 QVERIFY(object != 0);
1358 qInstallMsgHandler(old);
1360 QCOMPARE(transientErrorsMsgCount, 0);
1365 // One binding erroring multiple times, but then resolving
1367 QDeclarativeComponent component(&engine, TEST_FILE("transientErrors.2.qml"));
1369 transientErrorsMsgCount = 0;
1370 QtMsgHandler old = qInstallMsgHandler(transientErrorsMsgHandler);
1372 QObject *object = component.create();
1373 QVERIFY(object != 0);
1375 qInstallMsgHandler(old);
1377 QCOMPARE(transientErrorsMsgCount, 0);
1383 // Check that errors during shutdown are minimized
1384 void tst_qdeclarativeecmascript::shutdownErrors()
1386 QDeclarativeComponent component(&engine, TEST_FILE("shutdownErrors.qml"));
1387 QObject *object = component.create();
1388 QVERIFY(object != 0);
1390 transientErrorsMsgCount = 0;
1391 QtMsgHandler old = qInstallMsgHandler(transientErrorsMsgHandler);
1395 qInstallMsgHandler(old);
1396 QCOMPARE(transientErrorsMsgCount, 0);
1399 void tst_qdeclarativeecmascript::compositePropertyType()
1401 QDeclarativeComponent component(&engine, TEST_FILE("compositePropertyType.qml"));
1402 QTest::ignoreMessage(QtDebugMsg, "hello world");
1403 QObject *object = qobject_cast<QObject *>(component.create());
1408 void tst_qdeclarativeecmascript::jsObject()
1410 QDeclarativeComponent component(&engine, TEST_FILE("jsObject.qml"));
1411 QObject *object = component.create();
1412 QVERIFY(object != 0);
1414 QCOMPARE(object->property("test").toInt(), 92);
1419 void tst_qdeclarativeecmascript::undefinedResetsProperty()
1422 QDeclarativeComponent component(&engine, TEST_FILE("undefinedResetsProperty.qml"));
1423 QObject *object = component.create();
1424 QVERIFY(object != 0);
1426 QCOMPARE(object->property("resettableProperty").toInt(), 92);
1428 object->setProperty("setUndefined", true);
1430 QCOMPARE(object->property("resettableProperty").toInt(), 13);
1432 object->setProperty("setUndefined", false);
1434 QCOMPARE(object->property("resettableProperty").toInt(), 92);
1439 QDeclarativeComponent component(&engine, TEST_FILE("undefinedResetsProperty.2.qml"));
1440 QObject *object = component.create();
1441 QVERIFY(object != 0);
1443 QCOMPARE(object->property("resettableProperty").toInt(), 19);
1445 QMetaObject::invokeMethod(object, "doReset");
1447 QCOMPARE(object->property("resettableProperty").toInt(), 13);
1454 void tst_qdeclarativeecmascript::bug1()
1456 QDeclarativeComponent component(&engine, TEST_FILE("bug.1.qml"));
1457 QObject *object = component.create();
1458 QVERIFY(object != 0);
1460 QCOMPARE(object->property("test").toInt(), 14);
1462 object->setProperty("a", 11);
1464 QCOMPARE(object->property("test").toInt(), 3);
1466 object->setProperty("b", true);
1468 QCOMPARE(object->property("test").toInt(), 9);
1473 void tst_qdeclarativeecmascript::bug2()
1475 QDeclarativeComponent component(&engine);
1476 component.setData("import Qt.test 1.0;\nQPlainTextEdit { width: 100 }", QUrl());
1478 QObject *object = component.create();
1479 QVERIFY(object != 0);
1484 // Don't crash in createObject when the component has errors.
1485 void tst_qdeclarativeecmascript::dynamicCreationCrash()
1487 QDeclarativeComponent component(&engine, TEST_FILE("dynamicCreation.qml"));
1488 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1489 QVERIFY(object != 0);
1491 QTest::ignoreMessage(QtWarningMsg, "QDeclarativeComponent: Component is not ready");
1492 QMetaObject::invokeMethod(object, "dontCrash");
1493 QObject *created = object->objectProperty();
1494 QVERIFY(created == 0);
1500 void tst_qdeclarativeecmascript::regExpBug()
1502 QDeclarativeComponent component(&engine, TEST_FILE("regExp.qml"));
1503 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1504 QVERIFY(object != 0);
1505 QCOMPARE(object->regExp().pattern(), QLatin1String("[a-zA-z]"));
1509 static inline bool evaluate_error(QV8Engine *engine, v8::Handle<v8::Object> o, const char *source)
1511 QString functionSource = QLatin1String("(function(object) { return ") +
1512 QLatin1String(source) + QLatin1String(" })");
1514 v8::Local<v8::Script> program = v8::Script::Compile(engine->toString(functionSource));
1517 v8::Handle<v8::Function> function = v8::Handle<v8::Function>::Cast(program->Run());
1518 if (function.IsEmpty())
1520 v8::Handle<v8::Value> args[] = { o };
1521 function->Call(engine->global(), 1, args);
1522 return tc.HasCaught();
1525 static inline bool evaluate_value(QV8Engine *engine, v8::Handle<v8::Object> o,
1526 const char *source, v8::Handle<v8::Value> result)
1528 QString functionSource = QLatin1String("(function(object) { return ") +
1529 QLatin1String(source) + QLatin1String(" })");
1531 v8::Local<v8::Script> program = v8::Script::Compile(engine->toString(functionSource));
1534 v8::Handle<v8::Function> function = v8::Handle<v8::Function>::Cast(program->Run());
1535 if (function.IsEmpty())
1537 v8::Handle<v8::Value> args[] = { o };
1539 v8::Handle<v8::Value> value = function->Call(engine->global(), 1, args);
1544 return value->StrictEquals(result);
1547 static inline v8::Handle<v8::Value> evaluate(QV8Engine *engine, v8::Handle<v8::Object> o,
1550 QString functionSource = QLatin1String("(function(object) { return ") +
1551 QLatin1String(source) + QLatin1String(" })");
1553 v8::Local<v8::Script> program = v8::Script::Compile(engine->toString(functionSource));
1555 return v8::Handle<v8::Value>();
1556 v8::Handle<v8::Function> function = v8::Handle<v8::Function>::Cast(program->Run());
1557 if (function.IsEmpty())
1558 return v8::Handle<v8::Value>();
1559 v8::Handle<v8::Value> args[] = { o };
1561 v8::Handle<v8::Value> value = function->Call(engine->global(), 1, args);
1564 return v8::Handle<v8::Value>();
1568 #define EVALUATE_ERROR(source) evaluate_error(engine, object, source)
1569 #define EVALUATE_VALUE(source, result) evaluate_value(engine, object, source, result)
1570 #define EVALUATE(source) evaluate(engine, object, source)
1572 void tst_qdeclarativeecmascript::callQtInvokables()
1574 MyInvokableObject o;
1576 QDeclarativeEngine qmlengine;
1577 QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(&qmlengine);
1579 QV8Engine *engine = &ep->v8engine;
1581 v8::HandleScope handle_scope;
1582 v8::Context::Scope scope(engine->context());
1584 v8::Local<v8::Object> object = engine->newQObject(&o)->ToObject();
1586 // Non-existent methods
1588 QVERIFY(EVALUATE_ERROR("object.method_nonexistent()"));
1589 QCOMPARE(o.error(), false);
1590 QCOMPARE(o.invoked(), -1);
1591 QCOMPARE(o.actuals().count(), 0);
1594 QVERIFY(EVALUATE_ERROR("object.method_nonexistent(10, 11)"));
1595 QCOMPARE(o.error(), false);
1596 QCOMPARE(o.invoked(), -1);
1597 QCOMPARE(o.actuals().count(), 0);
1599 // Insufficient arguments
1601 QVERIFY(EVALUATE_ERROR("object.method_int()"));
1602 QCOMPARE(o.error(), false);
1603 QCOMPARE(o.invoked(), -1);
1604 QCOMPARE(o.actuals().count(), 0);
1607 QVERIFY(EVALUATE_ERROR("object.method_intint(10)"));
1608 QCOMPARE(o.error(), false);
1609 QCOMPARE(o.invoked(), -1);
1610 QCOMPARE(o.actuals().count(), 0);
1612 // Excessive arguments
1614 QVERIFY(EVALUATE_VALUE("object.method_int(10, 11)", v8::Undefined()));
1615 QCOMPARE(o.error(), false);
1616 QCOMPARE(o.invoked(), 8);
1617 QCOMPARE(o.actuals().count(), 1);
1618 QCOMPARE(o.actuals().at(0), QVariant(10));
1621 QVERIFY(EVALUATE_VALUE("object.method_intint(10, 11, 12)", v8::Undefined()));
1622 QCOMPARE(o.error(), false);
1623 QCOMPARE(o.invoked(), 9);
1624 QCOMPARE(o.actuals().count(), 2);
1625 QCOMPARE(o.actuals().at(0), QVariant(10));
1626 QCOMPARE(o.actuals().at(1), QVariant(11));
1628 // Test return types
1630 QVERIFY(EVALUATE_VALUE("object.method_NoArgs()", v8::Undefined()));
1631 QCOMPARE(o.error(), false);
1632 QCOMPARE(o.invoked(), 0);
1633 QCOMPARE(o.actuals().count(), 0);
1636 QVERIFY(EVALUATE_VALUE("object.method_NoArgs_int()", v8::Integer::New(6)));
1637 QCOMPARE(o.error(), false);
1638 QCOMPARE(o.invoked(), 1);
1639 QCOMPARE(o.actuals().count(), 0);
1642 QVERIFY(EVALUATE_VALUE("object.method_NoArgs_real()", v8::Number::New(19.75)));
1643 QCOMPARE(o.error(), false);
1644 QCOMPARE(o.invoked(), 2);
1645 QCOMPARE(o.actuals().count(), 0);
1649 v8::Handle<v8::Value> ret = EVALUATE("object.method_NoArgs_QPointF()");
1650 QVERIFY(!ret.IsEmpty());
1651 QCOMPARE(engine->toVariant(ret, -1), QVariant(QPointF(123, 4.5)));
1652 QCOMPARE(o.error(), false);
1653 QCOMPARE(o.invoked(), 3);
1654 QCOMPARE(o.actuals().count(), 0);
1659 v8::Handle<v8::Value> ret = EVALUATE("object.method_NoArgs_QObject()");
1660 QCOMPARE(engine->toQObject(ret), (QObject *)&o);
1661 QCOMPARE(o.error(), false);
1662 QCOMPARE(o.invoked(), 4);
1663 QCOMPARE(o.actuals().count(), 0);
1667 QVERIFY(EVALUATE_VALUE("object.method_NoArgs_unknown()", v8::Undefined()));
1668 QCOMPARE(o.error(), false);
1669 QCOMPARE(o.invoked(), 5);
1670 QCOMPARE(o.actuals().count(), 0);
1672 // XXX enable once qml/qtscript integration is implemented
1676 v8::Handle<v8::Value> ret = EVALUATE("object.method_NoArgs_QScriptValue()");
1677 QVERIFY(ret->IsString());
1678 QCOMPARE(engine->toString(ret), QString("Hello world"));
1679 QCOMPARE(o.error(), false);
1680 QCOMPARE(o.invoked(), 6);
1681 QCOMPARE(o.actuals().count(), 0);
1686 QVERIFY(EVALUATE_VALUE("object.method_NoArgs_QVariant()", engine->toString("QML rocks")));
1687 QCOMPARE(o.error(), false);
1688 QCOMPARE(o.invoked(), 7);
1689 QCOMPARE(o.actuals().count(), 0);
1693 QVERIFY(EVALUATE_VALUE("object.method_int(94)", v8::Undefined()));
1694 QCOMPARE(o.error(), false);
1695 QCOMPARE(o.invoked(), 8);
1696 QCOMPARE(o.actuals().count(), 1);
1697 QCOMPARE(o.actuals().at(0), QVariant(94));
1700 QVERIFY(EVALUATE_VALUE("object.method_int(\"94\")", v8::Undefined()));
1701 QCOMPARE(o.error(), false);
1702 QCOMPARE(o.invoked(), 8);
1703 QCOMPARE(o.actuals().count(), 1);
1704 QCOMPARE(o.actuals().at(0), QVariant(94));
1707 QVERIFY(EVALUATE_VALUE("object.method_int(\"not a number\")", v8::Undefined()));
1708 QCOMPARE(o.error(), false);
1709 QCOMPARE(o.invoked(), 8);
1710 QCOMPARE(o.actuals().count(), 1);
1711 QCOMPARE(o.actuals().at(0), QVariant(0));
1714 QVERIFY(EVALUATE_VALUE("object.method_int(null)", v8::Undefined()));
1715 QCOMPARE(o.error(), false);
1716 QCOMPARE(o.invoked(), 8);
1717 QCOMPARE(o.actuals().count(), 1);
1718 QCOMPARE(o.actuals().at(0), QVariant(0));
1721 QVERIFY(EVALUATE_VALUE("object.method_int(undefined)", v8::Undefined()));
1722 QCOMPARE(o.error(), false);
1723 QCOMPARE(o.invoked(), 8);
1724 QCOMPARE(o.actuals().count(), 1);
1725 QCOMPARE(o.actuals().at(0), QVariant(0));
1728 QVERIFY(EVALUATE_VALUE("object.method_int(object)", v8::Undefined()));
1729 QCOMPARE(o.error(), false);
1730 QCOMPARE(o.invoked(), 8);
1731 QCOMPARE(o.actuals().count(), 1);
1732 QCOMPARE(o.actuals().at(0), QVariant(0));
1735 QVERIFY(EVALUATE_VALUE("object.method_intint(122, 9)", v8::Undefined()));
1736 QCOMPARE(o.error(), false);
1737 QCOMPARE(o.invoked(), 9);
1738 QCOMPARE(o.actuals().count(), 2);
1739 QCOMPARE(o.actuals().at(0), QVariant(122));
1740 QCOMPARE(o.actuals().at(1), QVariant(9));
1743 QVERIFY(EVALUATE_VALUE("object.method_real(94.3)", v8::Undefined()));
1744 QCOMPARE(o.error(), false);
1745 QCOMPARE(o.invoked(), 10);
1746 QCOMPARE(o.actuals().count(), 1);
1747 QCOMPARE(o.actuals().at(0), QVariant(94.3));
1750 QVERIFY(EVALUATE_VALUE("object.method_real(\"94.3\")", v8::Undefined()));
1751 QCOMPARE(o.error(), false);
1752 QCOMPARE(o.invoked(), 10);
1753 QCOMPARE(o.actuals().count(), 1);
1754 QCOMPARE(o.actuals().at(0), QVariant(94.3));
1757 QVERIFY(EVALUATE_VALUE("object.method_real(\"not a number\")", v8::Undefined()));
1758 QCOMPARE(o.error(), false);
1759 QCOMPARE(o.invoked(), 10);
1760 QCOMPARE(o.actuals().count(), 1);
1761 QVERIFY(qIsNaN(o.actuals().at(0).toDouble()));
1764 QVERIFY(EVALUATE_VALUE("object.method_real(null)", v8::Undefined()));
1765 QCOMPARE(o.error(), false);
1766 QCOMPARE(o.invoked(), 10);
1767 QCOMPARE(o.actuals().count(), 1);
1768 QCOMPARE(o.actuals().at(0), QVariant(0));
1771 QVERIFY(EVALUATE_VALUE("object.method_real(undefined)", v8::Undefined()));
1772 QCOMPARE(o.error(), false);
1773 QCOMPARE(o.invoked(), 10);
1774 QCOMPARE(o.actuals().count(), 1);
1775 QVERIFY(qIsNaN(o.actuals().at(0).toDouble()));
1778 QVERIFY(EVALUATE_VALUE("object.method_real(object)", v8::Undefined()));
1779 QCOMPARE(o.error(), false);
1780 QCOMPARE(o.invoked(), 10);
1781 QCOMPARE(o.actuals().count(), 1);
1782 QVERIFY(qIsNaN(o.actuals().at(0).toDouble()));
1785 QVERIFY(EVALUATE_VALUE("object.method_QString(\"Hello world\")", v8::Undefined()));
1786 QCOMPARE(o.error(), false);
1787 QCOMPARE(o.invoked(), 11);
1788 QCOMPARE(o.actuals().count(), 1);
1789 QCOMPARE(o.actuals().at(0), QVariant("Hello world"));
1792 QVERIFY(EVALUATE_VALUE("object.method_QString(19)", v8::Undefined()));
1793 QCOMPARE(o.error(), false);
1794 QCOMPARE(o.invoked(), 11);
1795 QCOMPARE(o.actuals().count(), 1);
1796 QCOMPARE(o.actuals().at(0), QVariant("19"));
1800 QString expected = "MyInvokableObject(0x" + QString::number((quintptr)&o, 16) + ")";
1801 QVERIFY(EVALUATE_VALUE("object.method_QString(object)", v8::Undefined()));
1802 QCOMPARE(o.error(), false);
1803 QCOMPARE(o.invoked(), 11);
1804 QCOMPARE(o.actuals().count(), 1);
1805 QCOMPARE(o.actuals().at(0), QVariant(expected));
1809 QVERIFY(EVALUATE_VALUE("object.method_QString(null)", v8::Undefined()));
1810 QCOMPARE(o.error(), false);
1811 QCOMPARE(o.invoked(), 11);
1812 QCOMPARE(o.actuals().count(), 1);
1813 QCOMPARE(o.actuals().at(0), QVariant(QString()));
1816 QVERIFY(EVALUATE_VALUE("object.method_QString(undefined)", v8::Undefined()));
1817 QCOMPARE(o.error(), false);
1818 QCOMPARE(o.invoked(), 11);
1819 QCOMPARE(o.actuals().count(), 1);
1820 QCOMPARE(o.actuals().at(0), QVariant(QString()));
1823 QVERIFY(EVALUATE_VALUE("object.method_QPointF(0)", v8::Undefined()));
1824 QCOMPARE(o.error(), false);
1825 QCOMPARE(o.invoked(), 12);
1826 QCOMPARE(o.actuals().count(), 1);
1827 QCOMPARE(o.actuals().at(0), QVariant(QPointF()));
1830 QVERIFY(EVALUATE_VALUE("object.method_QPointF(null)", v8::Undefined()));
1831 QCOMPARE(o.error(), false);
1832 QCOMPARE(o.invoked(), 12);
1833 QCOMPARE(o.actuals().count(), 1);
1834 QCOMPARE(o.actuals().at(0), QVariant(QPointF()));
1837 QVERIFY(EVALUATE_VALUE("object.method_QPointF(undefined)", v8::Undefined()));
1838 QCOMPARE(o.error(), false);
1839 QCOMPARE(o.invoked(), 12);
1840 QCOMPARE(o.actuals().count(), 1);
1841 QCOMPARE(o.actuals().at(0), QVariant(QPointF()));
1844 QVERIFY(EVALUATE_VALUE("object.method_QPointF(object)", v8::Undefined()));
1845 QCOMPARE(o.error(), false);
1846 QCOMPARE(o.invoked(), 12);
1847 QCOMPARE(o.actuals().count(), 1);
1848 QCOMPARE(o.actuals().at(0), QVariant(QPointF()));
1851 QVERIFY(EVALUATE_VALUE("object.method_QPointF(object.method_get_QPointF())", v8::Undefined()));
1852 QCOMPARE(o.error(), false);
1853 QCOMPARE(o.invoked(), 12);
1854 QCOMPARE(o.actuals().count(), 1);
1855 QCOMPARE(o.actuals().at(0), QVariant(QPointF(99.3, -10.2)));
1858 QVERIFY(EVALUATE_VALUE("object.method_QPointF(object.method_get_QPoint())", v8::Undefined()));
1859 QCOMPARE(o.error(), false);
1860 QCOMPARE(o.invoked(), 12);
1861 QCOMPARE(o.actuals().count(), 1);
1862 QCOMPARE(o.actuals().at(0), QVariant(QPointF(9, 12)));
1865 QVERIFY(EVALUATE_VALUE("object.method_QObject(0)", v8::Undefined()));
1866 QCOMPARE(o.error(), false);
1867 QCOMPARE(o.invoked(), 13);
1868 QCOMPARE(o.actuals().count(), 1);
1869 QCOMPARE(o.actuals().at(0), qVariantFromValue((QObject *)0));
1872 QVERIFY(EVALUATE_VALUE("object.method_QObject(\"Hello world\")", v8::Undefined()));
1873 QCOMPARE(o.error(), false);
1874 QCOMPARE(o.invoked(), 13);
1875 QCOMPARE(o.actuals().count(), 1);
1876 QCOMPARE(o.actuals().at(0), qVariantFromValue((QObject *)0));
1879 QVERIFY(EVALUATE_VALUE("object.method_QObject(null)", v8::Undefined()));
1880 QCOMPARE(o.error(), false);
1881 QCOMPARE(o.invoked(), 13);
1882 QCOMPARE(o.actuals().count(), 1);
1883 QCOMPARE(o.actuals().at(0), qVariantFromValue((QObject *)0));
1886 QVERIFY(EVALUATE_VALUE("object.method_QObject(undefined)", v8::Undefined()));
1887 QCOMPARE(o.error(), false);
1888 QCOMPARE(o.invoked(), 13);
1889 QCOMPARE(o.actuals().count(), 1);
1890 QCOMPARE(o.actuals().at(0), qVariantFromValue((QObject *)0));
1893 QVERIFY(EVALUATE_VALUE("object.method_QObject(object)", v8::Undefined()));
1894 QCOMPARE(o.error(), false);
1895 QCOMPARE(o.invoked(), 13);
1896 QCOMPARE(o.actuals().count(), 1);
1897 QCOMPARE(o.actuals().at(0), qVariantFromValue((QObject *)&o));
1899 // XXX enable once qml/qtscript integration is implemented
1902 QVERIFY(EVALUATE_VALUE("object.method_QScriptValue(null)", v8::Undefined()));
1903 QCOMPARE(o.error(), false);
1904 QCOMPARE(o.invoked(), 14);
1905 QCOMPARE(o.actuals().count(), 1);
1906 QVERIFY(qvariant_cast<QScriptValue>(o.actuals().at(0)).isNull());
1909 QVERIFY(EVALUATE_VALUE("object.method_QScriptValue(undefined)", v8::Undefined()));
1910 QCOMPARE(o.error(), false);
1911 QCOMPARE(o.invoked(), 14);
1912 QCOMPARE(o.actuals().count(), 1);
1913 QVERIFY(qvariant_cast<QScriptValue>(o.actuals().at(0)).isUndefined());
1916 QVERIFY(EVALUATE_VALUE("object.method_QScriptValue(19)", v8::Undefined()));
1917 QCOMPARE(o.error(), false);
1918 QCOMPARE(o.invoked(), 14);
1919 QCOMPARE(o.actuals().count(), 1);
1920 QVERIFY(qvariant_cast<QScriptValue>(o.actuals().at(0)).strictlyEquals(QScriptValue(engine, 19)));
1923 QVERIFY(EVALUATE_VALUE("object.method_QScriptValue([19, 20])", v8::Undefined()));
1924 QCOMPARE(o.error(), false);
1925 QCOMPARE(o.invoked(), 14);
1926 QCOMPARE(o.actuals().count(), 1);
1927 QVERIFY(qvariant_cast<QScriptValue>(o.actuals().at(0)).isArray());
1930 QVERIFY(EVALUATE_VALUE("object.method_intQScriptValue(4, null)", v8::Undefined()));
1931 QCOMPARE(o.error(), false);
1932 QCOMPARE(o.invoked(), 15);
1933 QCOMPARE(o.actuals().count(), 2);
1934 QCOMPARE(o.actuals().at(0), QVariant(4));
1935 QVERIFY(qvariant_cast<QScriptValue>(o.actuals().at(1)).isNull());
1938 QVERIFY(EVALUATE_VALUE("object.method_intQScriptValue(8, undefined)", v8::Undefined()));
1939 QCOMPARE(o.error(), false);
1940 QCOMPARE(o.invoked(), 15);
1941 QCOMPARE(o.actuals().count(), 2);
1942 QCOMPARE(o.actuals().at(0), QVariant(8));
1943 QVERIFY(qvariant_cast<QScriptValue>(o.actuals().at(1)).isUndefined());
1946 QVERIFY(EVALUATE_VALUE("object.method_intQScriptValue(3, 19)", v8::Undefined()));
1947 QCOMPARE(o.error(), false);
1948 QCOMPARE(o.invoked(), 15);
1949 QCOMPARE(o.actuals().count(), 2);
1950 QCOMPARE(o.actuals().at(0), QVariant(3));
1951 QVERIFY(qvariant_cast<QScriptValue>(o.actuals().at(1)).strictlyEquals(QScriptValue(engine, 19)));
1954 QVERIFY(EVALUATE_VALUE("object.method_intQScriptValue(44, [19, 20])", v8::Undefined()));
1955 QCOMPARE(o.error(), false);
1956 QCOMPARE(o.invoked(), 15);
1957 QCOMPARE(o.actuals().count(), 2);
1958 QCOMPARE(o.actuals().at(0), QVariant(44));
1959 QVERIFY(qvariant_cast<QScriptValue>(o.actuals().at(1)).isArray());
1963 QVERIFY(EVALUATE_ERROR("object.method_overload()"));
1964 QCOMPARE(o.error(), false);
1965 QCOMPARE(o.invoked(), -1);
1966 QCOMPARE(o.actuals().count(), 0);
1969 QVERIFY(EVALUATE_VALUE("object.method_overload(10)", v8::Undefined()));
1970 QCOMPARE(o.error(), false);
1971 QCOMPARE(o.invoked(), 16);
1972 QCOMPARE(o.actuals().count(), 1);
1973 QCOMPARE(o.actuals().at(0), QVariant(10));
1976 QVERIFY(EVALUATE_VALUE("object.method_overload(10, 11)", v8::Undefined()));
1977 QCOMPARE(o.error(), false);
1978 QCOMPARE(o.invoked(), 17);
1979 QCOMPARE(o.actuals().count(), 2);
1980 QCOMPARE(o.actuals().at(0), QVariant(10));
1981 QCOMPARE(o.actuals().at(1), QVariant(11));
1984 QVERIFY(EVALUATE_VALUE("object.method_overload(\"Hello\")", v8::Undefined()));
1985 QCOMPARE(o.error(), false);
1986 QCOMPARE(o.invoked(), 18);
1987 QCOMPARE(o.actuals().count(), 1);
1988 QCOMPARE(o.actuals().at(0), QVariant(QString("Hello")));
1991 QVERIFY(EVALUATE_VALUE("object.method_with_enum(9)", v8::Undefined()));
1992 QCOMPARE(o.error(), false);
1993 QCOMPARE(o.invoked(), 19);
1994 QCOMPARE(o.actuals().count(), 1);
1995 QCOMPARE(o.actuals().at(0), QVariant(9));
1998 QVERIFY(EVALUATE_VALUE("object.method_default(10)", v8::Integer::New(19)));
1999 QCOMPARE(o.error(), false);
2000 QCOMPARE(o.invoked(), 20);
2001 QCOMPARE(o.actuals().count(), 2);
2002 QCOMPARE(o.actuals().at(0), QVariant(10));
2003 QCOMPARE(o.actuals().at(1), QVariant(19));
2006 QVERIFY(EVALUATE_VALUE("object.method_default(10, 13)", v8::Integer::New(13)));
2007 QCOMPARE(o.error(), false);
2008 QCOMPARE(o.invoked(), 20);
2009 QCOMPARE(o.actuals().count(), 2);
2010 QCOMPARE(o.actuals().at(0), QVariant(10));
2011 QCOMPARE(o.actuals().at(1), QVariant(13));
2014 QVERIFY(EVALUATE_VALUE("object.method_inherited(9)", v8::Undefined()));
2015 QCOMPARE(o.error(), false);
2016 QCOMPARE(o.invoked(), -3);
2017 QCOMPARE(o.actuals().count(), 1);
2018 QCOMPARE(o.actuals().at(0), QVariant(9));
2021 QVERIFY(EVALUATE_VALUE("object.method_QVariant(9)", v8::Undefined()));
2022 QCOMPARE(o.error(), false);
2023 QCOMPARE(o.invoked(), 21);
2024 QCOMPARE(o.actuals().count(), 2);
2025 QCOMPARE(o.actuals().at(0), QVariant(9));
2026 QCOMPARE(o.actuals().at(1), QVariant());
2029 QVERIFY(EVALUATE_VALUE("object.method_QVariant(\"Hello\", \"World\")", v8::Undefined()));
2030 QCOMPARE(o.error(), false);
2031 QCOMPARE(o.invoked(), 21);
2032 QCOMPARE(o.actuals().count(), 2);
2033 QCOMPARE(o.actuals().at(0), QVariant(QString("Hello")));
2034 QCOMPARE(o.actuals().at(1), QVariant(QString("World")));
2037 // QTBUG-13047 (check that you can pass registered object types as args)
2038 void tst_qdeclarativeecmascript::invokableObjectArg()
2040 QDeclarativeComponent component(&engine, TEST_FILE("invokableObjectArg.qml"));
2042 QObject *o = component.create();
2044 MyQmlObject *qmlobject = qobject_cast<MyQmlObject *>(o);
2046 QCOMPARE(qmlobject->myinvokableObject, qmlobject);
2051 // QTBUG-13047 (check that you can return registered object types from methods)
2052 void tst_qdeclarativeecmascript::invokableObjectRet()
2054 QDeclarativeComponent component(&engine, TEST_FILE("invokableObjectRet.qml"));
2056 QObject *o = component.create();
2058 QCOMPARE(o->property("test").toBool(), true);
2063 void tst_qdeclarativeecmascript::listToVariant()
2065 QDeclarativeComponent component(&engine, TEST_FILE("listToVariant.qml"));
2067 MyQmlContainer container;
2069 QDeclarativeContext context(engine.rootContext());
2070 context.setContextObject(&container);
2072 QObject *object = component.create(&context);
2073 QVERIFY(object != 0);
2075 QVariant v = object->property("test");
2076 QCOMPARE(v.userType(), qMetaTypeId<QDeclarativeListReference>());
2077 QVERIFY(qvariant_cast<QDeclarativeListReference>(v).object() == &container);
2083 void tst_qdeclarativeecmascript::multiEngineObject()
2086 obj.setStringProperty("Howdy planet");
2088 QDeclarativeEngine e1;
2089 e1.rootContext()->setContextProperty("thing", &obj);
2090 QDeclarativeComponent c1(&e1, TEST_FILE("multiEngineObject.qml"));
2092 QDeclarativeEngine e2;
2093 e2.rootContext()->setContextProperty("thing", &obj);
2094 QDeclarativeComponent c2(&e2, TEST_FILE("multiEngineObject.qml"));
2096 QObject *o1 = c1.create();
2097 QObject *o2 = c2.create();
2099 QCOMPARE(o1->property("test").toString(), QString("Howdy planet"));
2100 QCOMPARE(o2->property("test").toString(), QString("Howdy planet"));
2106 // Test that references to QObjects are cleanup when the object is destroyed
2107 void tst_qdeclarativeecmascript::deletedObject()
2109 QDeclarativeComponent component(&engine, TEST_FILE("deletedObject.qml"));
2111 QObject *object = component.create();
2113 QCOMPARE(object->property("test1").toBool(), true);
2114 QCOMPARE(object->property("test2").toBool(), true);
2115 QCOMPARE(object->property("test3").toBool(), true);
2116 QCOMPARE(object->property("test4").toBool(), true);
2121 void tst_qdeclarativeecmascript::attachedPropertyScope()
2123 QDeclarativeComponent component(&engine, TEST_FILE("attachedPropertyScope.qml"));
2125 QObject *object = component.create();
2126 QVERIFY(object != 0);
2128 MyQmlAttachedObject *attached =
2129 qobject_cast<MyQmlAttachedObject *>(qmlAttachedPropertiesObject<MyQmlObject>(object));
2130 QVERIFY(attached != 0);
2132 QCOMPARE(object->property("value2").toInt(), 0);
2134 attached->emitMySignal();
2136 QCOMPARE(object->property("value2").toInt(), 9);
2141 void tst_qdeclarativeecmascript::scriptConnect()
2144 QDeclarativeComponent component(&engine, TEST_FILE("scriptConnect.1.qml"));
2146 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2147 QVERIFY(object != 0);
2149 QCOMPARE(object->property("test").toBool(), false);
2150 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2151 QCOMPARE(object->property("test").toBool(), true);
2157 QDeclarativeComponent component(&engine, TEST_FILE("scriptConnect.2.qml"));
2159 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2160 QVERIFY(object != 0);
2162 QCOMPARE(object->property("test").toBool(), false);
2163 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2164 QCOMPARE(object->property("test").toBool(), true);
2170 QDeclarativeComponent component(&engine, TEST_FILE("scriptConnect.3.qml"));
2172 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2173 QVERIFY(object != 0);
2175 QCOMPARE(object->property("test").toBool(), false);
2176 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2177 QCOMPARE(object->property("test").toBool(), true);
2183 QDeclarativeComponent component(&engine, TEST_FILE("scriptConnect.4.qml"));
2185 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2186 QVERIFY(object != 0);
2188 QCOMPARE(object->methodCalled(), false);
2189 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2190 QCOMPARE(object->methodCalled(), true);
2196 QDeclarativeComponent component(&engine, TEST_FILE("scriptConnect.5.qml"));
2198 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2199 QVERIFY(object != 0);
2201 QCOMPARE(object->methodCalled(), false);
2202 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2203 QCOMPARE(object->methodCalled(), true);
2209 QDeclarativeComponent component(&engine, TEST_FILE("scriptConnect.6.qml"));
2211 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2212 QVERIFY(object != 0);
2214 QCOMPARE(object->property("test").toInt(), 0);
2215 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2216 QCOMPARE(object->property("test").toInt(), 2);
2222 void tst_qdeclarativeecmascript::scriptDisconnect()
2225 QDeclarativeComponent component(&engine, TEST_FILE("scriptDisconnect.1.qml"));
2227 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2228 QVERIFY(object != 0);
2230 QCOMPARE(object->property("test").toInt(), 0);
2231 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2232 QCOMPARE(object->property("test").toInt(), 1);
2233 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2234 QCOMPARE(object->property("test").toInt(), 2);
2235 emit object->basicSignal();
2236 QCOMPARE(object->property("test").toInt(), 2);
2237 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2238 QCOMPARE(object->property("test").toInt(), 2);
2244 QDeclarativeComponent component(&engine, TEST_FILE("scriptDisconnect.2.qml"));
2246 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2247 QVERIFY(object != 0);
2249 QCOMPARE(object->property("test").toInt(), 0);
2250 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2251 QCOMPARE(object->property("test").toInt(), 1);
2252 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2253 QCOMPARE(object->property("test").toInt(), 2);
2254 emit object->basicSignal();
2255 QCOMPARE(object->property("test").toInt(), 2);
2256 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2257 QCOMPARE(object->property("test").toInt(), 2);
2263 QDeclarativeComponent component(&engine, TEST_FILE("scriptDisconnect.3.qml"));
2265 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2266 QVERIFY(object != 0);
2268 QCOMPARE(object->property("test").toInt(), 0);
2269 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2270 QCOMPARE(object->property("test").toInt(), 1);
2271 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2272 QCOMPARE(object->property("test").toInt(), 2);
2273 emit object->basicSignal();
2274 QCOMPARE(object->property("test").toInt(), 2);
2275 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2276 QCOMPARE(object->property("test").toInt(), 3);
2281 QDeclarativeComponent component(&engine, TEST_FILE("scriptDisconnect.4.qml"));
2283 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2284 QVERIFY(object != 0);
2286 QCOMPARE(object->property("test").toInt(), 0);
2287 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2288 QCOMPARE(object->property("test").toInt(), 1);
2289 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2290 QCOMPARE(object->property("test").toInt(), 2);
2291 emit object->basicSignal();
2292 QCOMPARE(object->property("test").toInt(), 2);
2293 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2294 QCOMPARE(object->property("test").toInt(), 3);
2300 class OwnershipObject : public QObject
2304 OwnershipObject() { object = new QObject; }
2306 QPointer<QObject> object;
2309 QObject *getObject() { return object; }
2312 void tst_qdeclarativeecmascript::ownership()
2314 OwnershipObject own;
2315 QDeclarativeContext *context = new QDeclarativeContext(engine.rootContext());
2316 context->setContextObject(&own);
2319 QDeclarativeComponent component(&engine, TEST_FILE("ownership.qml"));
2321 QVERIFY(own.object != 0);
2323 QObject *object = component.create(context);
2325 engine.collectGarbage();
2327 QCoreApplication::processEvents(QEventLoop::DeferredDeletion);
2329 QVERIFY(own.object == 0);
2334 own.object = new QObject(&own);
2337 QDeclarativeComponent component(&engine, TEST_FILE("ownership.qml"));
2339 QVERIFY(own.object != 0);
2341 QObject *object = component.create(context);
2343 engine.collectGarbage();
2345 QCoreApplication::processEvents(QEventLoop::DeferredDeletion);
2347 QVERIFY(own.object != 0);
2355 class CppOwnershipReturnValue : public QObject
2359 CppOwnershipReturnValue() : value(0) {}
2360 ~CppOwnershipReturnValue() { delete value; }
2362 Q_INVOKABLE QObject *create() {
2363 value = new QObject;
2364 QDeclarativeEngine::setObjectOwnership(value, QDeclarativeEngine::CppOwnership);
2368 Q_INVOKABLE MyQmlObject *createQmlObject() {
2369 MyQmlObject *rv = new MyQmlObject;
2374 QPointer<QObject> value;
2378 // Test setObjectOwnership(CppOwnership) works even when there is no QDeclarativeData
2379 void tst_qdeclarativeecmascript::cppOwnershipReturnValue()
2381 CppOwnershipReturnValue source;
2384 QDeclarativeEngine engine;
2385 engine.rootContext()->setContextProperty("source", &source);
2387 QVERIFY(source.value == 0);
2389 QDeclarativeComponent component(&engine);
2390 component.setData("import QtQuick 1.0\nQtObject {\nComponent.onCompleted: { var a = source.create(); }\n}\n", QUrl());
2392 QObject *object = component.create();
2394 QVERIFY(object != 0);
2395 QVERIFY(source.value != 0);
2400 QCoreApplication::instance()->processEvents(QEventLoop::DeferredDeletion);
2402 QVERIFY(source.value != 0);
2406 void tst_qdeclarativeecmascript::ownershipCustomReturnValue()
2408 CppOwnershipReturnValue source;
2411 QDeclarativeEngine engine;
2412 engine.rootContext()->setContextProperty("source", &source);
2414 QVERIFY(source.value == 0);
2416 QDeclarativeComponent component(&engine);
2417 component.setData("import QtQuick 1.0\nQtObject {\nComponent.onCompleted: { var a = source.createQmlObject(); }\n}\n", QUrl());
2419 QObject *object = component.create();
2421 QVERIFY(object != 0);
2422 QVERIFY(source.value != 0);
2427 engine.collectGarbage();
2428 QCoreApplication::instance()->processEvents(QEventLoop::DeferredDeletion);
2430 QVERIFY(source.value == 0);
2433 class QListQObjectMethodsObject : public QObject
2437 QListQObjectMethodsObject() {
2438 m_objects.append(new MyQmlObject());
2439 m_objects.append(new MyQmlObject());
2442 ~QListQObjectMethodsObject() {
2443 qDeleteAll(m_objects);
2447 QList<QObject *> getObjects() { return m_objects; }
2450 QList<QObject *> m_objects;
2453 // Tests that returning a QList<QObject*> from a method works
2454 void tst_qdeclarativeecmascript::qlistqobjectMethods()
2456 QListQObjectMethodsObject obj;
2457 QDeclarativeContext *context = new QDeclarativeContext(engine.rootContext());
2458 context->setContextObject(&obj);
2460 QDeclarativeComponent component(&engine, TEST_FILE("qlistqobjectMethods.qml"));
2462 QObject *object = component.create(context);
2464 QCOMPARE(object->property("test").toInt(), 2);
2465 QCOMPARE(object->property("test2").toBool(), true);
2472 void tst_qdeclarativeecmascript::strictlyEquals()
2474 QDeclarativeComponent component(&engine, TEST_FILE("strictlyEquals.qml"));
2476 QObject *object = component.create();
2477 QVERIFY(object != 0);
2479 QCOMPARE(object->property("test1").toBool(), true);
2480 QCOMPARE(object->property("test2").toBool(), true);
2481 QCOMPARE(object->property("test3").toBool(), true);
2482 QCOMPARE(object->property("test4").toBool(), true);
2483 QCOMPARE(object->property("test5").toBool(), true);
2484 QCOMPARE(object->property("test6").toBool(), true);
2485 QCOMPARE(object->property("test7").toBool(), true);
2486 QCOMPARE(object->property("test8").toBool(), true);
2491 void tst_qdeclarativeecmascript::compiled()
2493 QDeclarativeComponent component(&engine, TEST_FILE("compiled.qml"));
2495 QObject *object = component.create();
2496 QVERIFY(object != 0);
2498 QCOMPARE(object->property("test1").toReal(), qreal(15.7));
2499 QCOMPARE(object->property("test2").toReal(), qreal(-6.7));
2500 QCOMPARE(object->property("test3").toBool(), true);
2501 QCOMPARE(object->property("test4").toBool(), false);
2502 QCOMPARE(object->property("test5").toBool(), false);
2503 QCOMPARE(object->property("test6").toBool(), true);
2505 QCOMPARE(object->property("test7").toInt(), 185);
2506 QCOMPARE(object->property("test8").toInt(), 167);
2507 QCOMPARE(object->property("test9").toBool(), true);
2508 QCOMPARE(object->property("test10").toBool(), false);
2509 QCOMPARE(object->property("test11").toBool(), false);
2510 QCOMPARE(object->property("test12").toBool(), true);
2512 QCOMPARE(object->property("test13").toString(), QLatin1String("HelloWorld"));
2513 QCOMPARE(object->property("test14").toString(), QLatin1String("Hello World"));
2514 QCOMPARE(object->property("test15").toBool(), false);
2515 QCOMPARE(object->property("test16").toBool(), true);
2517 QCOMPARE(object->property("test17").toInt(), 5);
2518 QCOMPARE(object->property("test18").toReal(), qreal(176));
2519 QCOMPARE(object->property("test19").toInt(), 7);
2520 QCOMPARE(object->property("test20").toReal(), qreal(6.7));
2521 QCOMPARE(object->property("test21").toString(), QLatin1String("6.7"));
2522 QCOMPARE(object->property("test22").toString(), QLatin1String("!"));
2523 QCOMPARE(object->property("test23").toBool(), true);
2524 QCOMPARE(qvariant_cast<QColor>(object->property("test24")), QColor(0x11,0x22,0x33));
2525 QCOMPARE(qvariant_cast<QColor>(object->property("test25")), QColor(0x11,0x22,0x33,0xAA));
2530 // Test that numbers assigned in bindings as strings work consistently
2531 void tst_qdeclarativeecmascript::numberAssignment()
2533 QDeclarativeComponent component(&engine, TEST_FILE("numberAssignment.qml"));
2535 QObject *object = component.create();
2536 QVERIFY(object != 0);
2538 QCOMPARE(object->property("test1"), QVariant((qreal)6.7));
2539 QCOMPARE(object->property("test2"), QVariant((qreal)6.7));
2540 QCOMPARE(object->property("test2"), QVariant((qreal)6.7));
2541 QCOMPARE(object->property("test3"), QVariant((qreal)6));
2542 QCOMPARE(object->property("test4"), QVariant((qreal)6));
2544 QCOMPARE(object->property("test5"), QVariant((int)7));
2545 QCOMPARE(object->property("test6"), QVariant((int)7));
2546 QCOMPARE(object->property("test7"), QVariant((int)6));
2547 QCOMPARE(object->property("test8"), QVariant((int)6));
2549 QCOMPARE(object->property("test9"), QVariant((unsigned int)7));
2550 QCOMPARE(object->property("test10"), QVariant((unsigned int)7));
2551 QCOMPARE(object->property("test11"), QVariant((unsigned int)6));
2552 QCOMPARE(object->property("test12"), QVariant((unsigned int)6));
2557 void tst_qdeclarativeecmascript::propertySplicing()
2559 QDeclarativeComponent component(&engine, TEST_FILE("propertySplicing.qml"));
2561 QObject *object = component.create();
2562 QVERIFY(object != 0);
2564 QCOMPARE(object->property("test").toBool(), true);
2570 void tst_qdeclarativeecmascript::signalWithUnknownTypes()
2572 QDeclarativeComponent component(&engine, TEST_FILE("signalWithUnknownTypes.qml"));
2574 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2575 QVERIFY(object != 0);
2577 MyQmlObject::MyType type;
2578 type.value = 0x8971123;
2579 emit object->signalWithUnknownType(type);
2581 MyQmlObject::MyType result = qvariant_cast<MyQmlObject::MyType>(object->variant());
2583 QCOMPARE(result.value, type.value);
2589 void tst_qdeclarativeecmascript::moduleApi()
2591 QDeclarativeComponent component(&engine, TEST_FILE("moduleApi.qml"));
2592 QObject *object = component.create();
2593 QVERIFY(object != 0);
2594 QCOMPARE(object->property("existingUriTest").toInt(), 20);
2596 QEXPECT_FAIL("", "QTBUG-17318", Continue);
2597 QCOMPARE(object->property("scriptTest").toInt(), 13);
2598 QCOMPARE(object->property("qobjectTest").toInt(), 20);
2599 QCOMPARE(object->property("qobjectMethodTest").toInt(), 1); // first call of method, so count = 1.
2600 QCOMPARE(object->property("qobjectMinorVersionTest").toInt(), 20);
2601 QCOMPARE(object->property("qobjectMajorVersionTest").toInt(), 20);
2602 QCOMPARE(object->property("qobjectParentedTest").toInt(), 26);
2605 // test that caching of module apis works correctly.
2606 QDeclarativeComponent componentTwo(&engine, TEST_FILE("moduleApiCaching.qml"));
2607 object = componentTwo.create();
2608 QVERIFY(object != 0);
2609 QCOMPARE(object->property("existingUriTest").toInt(), 20);
2610 QEXPECT_FAIL("", "QTBUG-17318", Continue);
2611 QCOMPARE(object->property("scriptTest").toInt(), 13); // shouldn't have incremented.
2612 QCOMPARE(object->property("qobjectParentedTest").toInt(), 26); // shouldn't have incremented.
2615 // test that writing to a property of module apis works correctly.
2616 QDeclarativeComponent componentThree(&engine, TEST_FILE("moduleApiWriting.qml"));
2617 QString expectedWarning = QLatin1String("file://") + TEST_FILE("moduleApiWriting.qml").toLocalFile() + QLatin1String(":15: Error: Cannot assign to read-only property \"qobjectTestProperty\"");
2618 QTest::ignoreMessage(QtWarningMsg, expectedWarning.toAscii().constData());
2619 object = componentThree.create();
2620 QVERIFY(object != 0);
2621 QCOMPARE(object->property("readOnlyProperty").toInt(), 20);
2622 QCOMPARE(object->property("writableProperty").toInt(), 50);
2623 QVERIFY(object->setProperty("firstProperty", QVariant(30))); // shouldn't affect value of readOnlyProperty
2624 QVERIFY(object->setProperty("writableProperty", QVariant(30))); // SHOULD affect value of writableProperty
2625 QCOMPARE(object->property("readOnlyProperty").toInt(), 20);
2626 QCOMPARE(object->property("writableProperty").toInt(), 30);
2629 QDeclarativeComponent failOne(&engine, TEST_FILE("moduleApiMajorVersionFail.qml"));
2630 QTest::ignoreMessage(QtWarningMsg, "QDeclarativeComponent: Component is not ready");
2631 object = failOne.create();
2632 QVERIFY(object == 0); // should have failed: invalid major version
2634 QDeclarativeComponent failTwo(&engine, TEST_FILE("moduleApiMinorVersionFail.qml"));
2635 QTest::ignoreMessage(QtWarningMsg, "QDeclarativeComponent: Component is not ready");
2636 object = failTwo.create();
2637 QVERIFY(object == 0); // should have failed: invalid minor version
2640 void tst_qdeclarativeecmascript::importScripts()
2642 QObject *object = 0;
2644 // first, ensure that the required behaviour works.
2645 QDeclarativeComponent component(&engine, TEST_FILE("jsimport/testImport.qml"));
2646 object = component.create();
2647 QVERIFY(object != 0);
2648 QCOMPARE(object->property("importedScriptStringValue"), QVariant(QString(QLatin1String("Hello, World!"))));
2649 QCOMPARE(object->property("importedScriptFunctionValue"), QVariant(20));
2650 QCOMPARE(object->property("importedModuleAttachedPropertyValue"), QVariant(19));
2651 QCOMPARE(object->property("importedModuleEnumValue"), QVariant(2));
2654 QDeclarativeComponent componentTwo(&engine, TEST_FILE("jsimport/testImportScoping.qml"));
2655 object = componentTwo.create();
2656 QVERIFY(object != 0);
2657 QCOMPARE(object->property("componentError"), QVariant(5));
2660 // then, ensure that unintended behaviour does not work.
2661 QDeclarativeComponent failOneComponent(&engine, TEST_FILE("jsimportfail/failOne.qml"));
2662 QString expectedWarning = QLatin1String("file://") + TEST_FILE("jsimportfail/failOne.qml").toLocalFile() + QLatin1String(":6: TypeError: Cannot call method 'greetingString' of undefined");
2663 QTest::ignoreMessage(QtWarningMsg, expectedWarning.toAscii().constData());
2664 object = failOneComponent.create();
2665 QVERIFY(object != 0);
2666 QVERIFY(object->property("importScriptFunctionValue").toString().isEmpty());
2668 QDeclarativeComponent failTwoComponent(&engine, TEST_FILE("jsimportfail/failTwo.qml"));
2669 expectedWarning = QLatin1String("file://") + TEST_FILE("jsimportfail/failTwo.qml").toLocalFile() + QLatin1String(":6: ReferenceError: Can't find variable: ImportOneJs");
2670 QTest::ignoreMessage(QtWarningMsg, expectedWarning.toAscii().constData());
2671 object = failTwoComponent.create();
2672 QVERIFY(object != 0);
2673 QVERIFY(object->property("importScriptFunctionValue").toString().isEmpty());
2675 QDeclarativeComponent failThreeComponent(&engine, TEST_FILE("jsimportfail/failThree.qml"));
2676 expectedWarning = QLatin1String("file://") + TEST_FILE("jsimportfail/failThree.qml").toLocalFile() + QLatin1String(":7: TypeError: Cannot read property 'JsQtTest' of undefined");
2677 QTest::ignoreMessage(QtWarningMsg, expectedWarning.toAscii().constData());
2678 object = failThreeComponent.create();
2679 QVERIFY(object != 0);
2680 QCOMPARE(object->property("importedModuleAttachedPropertyValue"), QVariant(false));
2682 QDeclarativeComponent failFourComponent(&engine, TEST_FILE("jsimportfail/failFour.qml"));
2683 expectedWarning = QLatin1String("file://") + TEST_FILE("jsimportfail/failFour.qml").toLocalFile() + QLatin1String(":6: ReferenceError: Can't find variable: JsQtTest");
2684 QTest::ignoreMessage(QtWarningMsg, expectedWarning.toAscii().constData());
2685 object = failFourComponent.create();
2686 QVERIFY(object != 0);
2687 QCOMPARE(object->property("importedModuleEnumValue"), QVariant(0));
2689 QDeclarativeComponent failFiveComponent(&engine, TEST_FILE("jsimportfail/failFive.qml"));
2690 expectedWarning = QLatin1String("file://") + TEST_FILE("jsimportfail/importWithImports.js").toLocalFile() + QLatin1String(":8: ReferenceError: Can't find variable: Component");
2691 QTest::ignoreMessage(QtWarningMsg, expectedWarning.toAscii().constData());
2692 expectedWarning = QLatin1String("file://") + TEST_FILE("jsimportfail/importPragmaLibrary.js").toLocalFile() + QLatin1String(":6: ReferenceError: Can't find variable: Component");
2693 QTest::ignoreMessage(QtWarningMsg, expectedWarning.toAscii().constData());
2694 object = failFiveComponent.create();
2695 QVERIFY(object != 0);
2696 QCOMPARE(object->property("componentError"), QVariant(0));
2699 // also, test that importing scripts with .pragma library works as required
2700 QDeclarativeComponent pragmaLibraryComponent(&engine, TEST_FILE("jsimport/testImportPragmaLibrary.qml"));
2701 object = pragmaLibraryComponent.create();
2702 QVERIFY(object != 0);
2703 QCOMPARE(object->property("testValue"), QVariant(31));
2706 // and that .pragma library scripts don't inherit imports from any .qml file
2707 QDeclarativeComponent pragmaLibraryComponentTwo(&engine, TEST_FILE("jsimportfail/testImportPragmaLibrary.qml"));
2708 object = pragmaLibraryComponentTwo.create();
2709 QVERIFY(object != 0);
2710 QCOMPARE(object->property("testValue"), QVariant(0));
2714 void tst_qdeclarativeecmascript::scarceResources()
2716 QPixmap origPixmap(100, 100);
2717 origPixmap.fill(Qt::blue);
2719 QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(&engine);
2720 ScarceResourceObject *eo = 0;
2721 QObject *object = 0;
2723 // in the following three cases, the instance created from the component
2724 // has a property which is a copy of the scarce resource; hence, the
2725 // resource should NOT be detached prior to deletion of the object instance,
2726 // unless the resource is destroyed explicitly.
2727 QDeclarativeComponent component(&engine, TEST_FILE("scarceresources/scarceResourceCopy.qml"));
2728 object = component.create();
2729 QVERIFY(object != 0);
2730 QVERIFY(object->property("scarceResourceCopy").isValid());
2731 QCOMPARE(object->property("scarceResourceCopy").value<QPixmap>(), origPixmap);
2732 QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
2733 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2734 QVERIFY(!eo->scarceResourceIsDetached()); // there are two copies of it in existence: the property of object, and the property of eo.
2737 QDeclarativeComponent componentTwo(&engine, TEST_FILE("scarceresources/scarceResourceCopyFromJs.qml"));
2738 object = componentTwo.create();
2739 QVERIFY(object != 0);
2740 QVERIFY(object->property("scarceResourceCopy").isValid());
2741 QCOMPARE(object->property("scarceResourceCopy").value<QPixmap>(), origPixmap);
2742 QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
2743 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2744 QVERIFY(!eo->scarceResourceIsDetached()); // there are two copies of it in existence: the property of object, and the property of eo.
2747 QDeclarativeComponent componentThree(&engine, TEST_FILE("scarceresources/scarceResourceDestroyedCopy.qml"));
2748 object = componentThree.create();
2749 QVERIFY(object != 0);
2750 QVERIFY(!(object->property("scarceResourceCopy").isValid())); // was manually released prior to being returned.
2751 QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
2752 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2753 QVERIFY(eo->scarceResourceIsDetached()); // should have explicitly been released during the evaluation of the binding.
2756 // in the following three cases, no other copy should exist in memory,
2757 // and so it should be detached (unless explicitly preserved).
2758 QDeclarativeComponent componentFour(&engine, TEST_FILE("scarceresources/scarceResourceTest.qml"));
2759 object = componentFour.create();
2760 QVERIFY(object != 0);
2761 QVERIFY(object->property("scarceResourceTest").isValid());
2762 QCOMPARE(object->property("scarceResourceTest").toInt(), 100);
2763 QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
2764 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2765 QVERIFY(eo->scarceResourceIsDetached()); // the resource should have been released after the binding was evaluated.
2768 QDeclarativeComponent componentFive(&engine, TEST_FILE("scarceresources/scarceResourceTestPreserve.qml"));
2769 object = componentFive.create();
2770 QVERIFY(object != 0);
2771 QVERIFY(object->property("scarceResourceTest").isValid());
2772 QCOMPARE(object->property("scarceResourceTest").toInt(), 100);
2773 QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
2774 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2775 QVERIFY(!eo->scarceResourceIsDetached()); // this won't be detached since we explicitly preserved it.
2778 QDeclarativeComponent componentSix(&engine, TEST_FILE("scarceresources/scarceResourceTestMultiple.qml"));
2779 object = componentSix.create();
2780 QVERIFY(object != 0);
2781 QVERIFY(object->property("scarceResourceTest").isValid());
2782 QCOMPARE(object->property("scarceResourceTest").toInt(), 100);
2783 QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
2784 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2785 QVERIFY(eo->scarceResourceIsDetached()); // all resources were released manually or automatically released.
2788 // test that scarce resources are handled correctly for imports
2789 QDeclarativeComponent componentSeven(&engine, TEST_FILE("scarceresources/scarceResourceCopyImportNoBinding.qml"));
2790 object = componentSeven.create();
2791 QVERIFY(object != 0); // the import should have caused the addition of a resource to the ScarceResources list
2792 QVERIFY(ep->scarceResources.isEmpty()); // but they should have been released by this point.
2795 QDeclarativeComponent componentEight(&engine, TEST_FILE("scarceresources/scarceResourceCopyImportFail.qml"));
2796 object = componentEight.create();
2797 QVERIFY(object != 0);
2798 QVERIFY(!object->property("scarceResourceCopy").isValid()); // wasn't preserved, so shouldn't be valid.
2799 QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
2802 QDeclarativeComponent componentNine(&engine, TEST_FILE("scarceresources/scarceResourceCopyImport.qml"));
2803 object = componentNine.create();
2804 QVERIFY(object != 0);
2805 QVERIFY(object->property("scarceResourceCopy").isValid()); // preserved, so should be valid.
2806 QCOMPARE(object->property("scarceResourceCopy").value<QPixmap>(), origPixmap);
2807 QVERIFY(object->property("scarceResourceAssignedCopyOne").isValid()); // assigned before destroy(), so should be valid.
2808 QCOMPARE(object->property("scarceResourceAssignedCopyOne").value<QPixmap>(), origPixmap);
2809 QVERIFY(!object->property("scarceResourceAssignedCopyTwo").isValid()); // assigned after destroy(), so should be invalid.
2810 QVERIFY(ep->scarceResources.isEmpty()); // this will still be zero, because "preserve()" REMOVES it from this list.
2813 // test that scarce resources are handled properly in signal invocation
2814 QDeclarativeComponent componentTen(&engine, TEST_FILE("scarceresources/scarceResourceSignal.qml"));
2815 object = componentTen.create();
2816 QVERIFY(object != 0);
2817 QObject *srsc = object->findChild<QObject*>("srsc");
2819 QVERIFY(!srsc->property("scarceResourceCopy").isValid()); // hasn't been instantiated yet.
2820 QCOMPARE(srsc->property("width"), QVariant(5)); // default value is 5.
2821 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2822 QVERIFY(eo->scarceResourceIsDetached()); // should be no other copies of it at this stage.
2823 QMetaObject::invokeMethod(srsc, "testSignal");
2824 QVERIFY(!srsc->property("scarceResourceCopy").isValid()); // still hasn't been instantiated
2825 QCOMPARE(srsc->property("width"), QVariant(10)); // but width was assigned to 10.
2826 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2827 QVERIFY(eo->scarceResourceIsDetached()); // should still be no other copies of it at this stage.
2828 QMetaObject::invokeMethod(srsc, "testSignal2"); // assigns scarceResourceCopy to the scarce pixmap.
2829 QVERIFY(srsc->property("scarceResourceCopy").isValid());
2830 QCOMPARE(srsc->property("scarceResourceCopy").value<QPixmap>(), origPixmap);
2831 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2832 QVERIFY(!(eo->scarceResourceIsDetached())); // should be another copy of the resource now.
2833 QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
2836 // test that scarce resources are handled properly from js functions in qml files
2837 QDeclarativeComponent componentEleven(&engine, TEST_FILE("scarceresources/scarceResourceFunction.qml"));
2838 object = componentEleven.create();
2839 QVERIFY(object != 0);
2840 QVERIFY(!object->property("scarceResourceCopy").isValid()); // not yet assigned, so should not be valid
2841 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2842 QVERIFY(eo->scarceResourceIsDetached()); // should be no other copies of it at this stage.
2843 QMetaObject::invokeMethod(object, "retrieveScarceResource");
2844 QVERIFY(object->property("scarceResourceCopy").isValid()); // assigned, so should be valid.
2845 QCOMPARE(object->property("scarceResourceCopy").value<QPixmap>(), origPixmap);
2846 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2847 QVERIFY(!eo->scarceResourceIsDetached()); // should be a copy of the resource at this stage.
2848 QMetaObject::invokeMethod(object, "releaseScarceResource");
2849 QVERIFY(!object->property("scarceResourceCopy").isValid()); // just released, so should not be valid
2850 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2851 QVERIFY(eo->scarceResourceIsDetached()); // should be no other copies of it at this stage.
2852 QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
2855 // test that if an exception occurs while invoking js function from cpp, that the resources are released.
2856 QDeclarativeComponent componentTwelve(&engine, TEST_FILE("scarceresources/scarceResourceFunctionFail.qml"));
2857 object = componentTwelve.create();
2858 QVERIFY(object != 0);
2859 QVERIFY(!object->property("scarceResourceCopy").isValid()); // not yet assigned, so should not be valid
2860 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2861 QVERIFY(eo->scarceResourceIsDetached()); // should be no other copies of it at this stage.
2862 QString srp_name = object->property("srp_name").toString();
2863 QString expectedWarning = componentTwelve.url().toString() + QLatin1String(":17: TypeError: Property 'scarceResource' of object ") + srp_name + QLatin1String(" is not a function");
2864 QTest::ignoreMessage(QtWarningMsg, qPrintable(expectedWarning)); // we expect a meaningful warning to be printed.
2865 QMetaObject::invokeMethod(object, "retrieveScarceResource");
2866 QVERIFY(!object->property("scarceResourceCopy").isValid()); // due to exception, assignment will NOT have occurred.
2867 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2868 QVERIFY(eo->scarceResourceIsDetached()); // should be no other copies of it at this stage.
2869 QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
2873 void tst_qdeclarativeecmascript::propertyChangeSlots()
2875 // ensure that allowable property names are allowed and onPropertyNameChanged slots are generated correctly.
2876 QDeclarativeComponent component(&engine, TEST_FILE("changeslots/propertyChangeSlots.qml"));
2877 QObject *object = component.create();
2878 QVERIFY(object != 0);
2881 // ensure that invalid property names fail properly.
2882 QTest::ignoreMessage(QtWarningMsg, "QDeclarativeComponent: Component is not ready");
2883 QDeclarativeComponent e1(&engine, TEST_FILE("changeslots/propertyChangeSlotErrors.1.qml"));
2884 QString expectedErrorString = e1.url().toString() + QLatin1String(":9:5: Cannot assign to non-existent property \"on_nameWithUnderscoreChanged\"");
2885 QCOMPARE(e1.errors().at(0).toString(), expectedErrorString);
2886 object = e1.create();
2887 QVERIFY(object == 0);
2890 QTest::ignoreMessage(QtWarningMsg, "QDeclarativeComponent: Component is not ready");
2891 QDeclarativeComponent e2(&engine, TEST_FILE("changeslots/propertyChangeSlotErrors.2.qml"));
2892 expectedErrorString = e2.url().toString() + QLatin1String(":9:5: Cannot assign to non-existent property \"on____nameWithUnderscoresChanged\"");
2893 QCOMPARE(e2.errors().at(0).toString(), expectedErrorString);
2894 object = e2.create();
2895 QVERIFY(object == 0);
2898 QTest::ignoreMessage(QtWarningMsg, "QDeclarativeComponent: Component is not ready");
2899 QDeclarativeComponent e3(&engine, TEST_FILE("changeslots/propertyChangeSlotErrors.3.qml"));
2900 expectedErrorString = e3.url().toString() + QLatin1String(":9:5: Cannot assign to non-existent property \"on$NameWithDollarsignChanged\"");
2901 QCOMPARE(e3.errors().at(0).toString(), expectedErrorString);
2902 object = e3.create();
2903 QVERIFY(object == 0);
2906 QTest::ignoreMessage(QtWarningMsg, "QDeclarativeComponent: Component is not ready");
2907 QDeclarativeComponent e4(&engine, TEST_FILE("changeslots/propertyChangeSlotErrors.4.qml"));
2908 expectedErrorString = e4.url().toString() + QLatin1String(":9:5: Cannot assign to non-existent property \"on_6NameWithUnderscoreNumberChanged\"");
2909 QCOMPARE(e4.errors().at(0).toString(), expectedErrorString);
2910 object = e4.create();
2911 QVERIFY(object == 0);
2915 // Ensure that QObject type conversion works on binding assignment
2916 void tst_qdeclarativeecmascript::elementAssign()
2918 QDeclarativeComponent component(&engine, TEST_FILE("elementAssign.qml"));
2920 QObject *object = component.create();
2921 QVERIFY(object != 0);
2923 QCOMPARE(object->property("test").toBool(), true);
2929 void tst_qdeclarativeecmascript::objectPassThroughSignals()
2931 QDeclarativeComponent component(&engine, TEST_FILE("objectsPassThroughSignals.qml"));
2933 QObject *object = component.create();
2934 QVERIFY(object != 0);
2936 QCOMPARE(object->property("test").toBool(), true);
2941 // Test that assigning a null object works
2942 // Regressed with: df1788b4dbbb2826ae63f26bdf166342595343f4
2943 void tst_qdeclarativeecmascript::nullObjectBinding()
2945 QDeclarativeComponent component(&engine, TEST_FILE("nullObjectBinding.qml"));
2947 QObject *object = component.create();
2948 QVERIFY(object != 0);
2950 QVERIFY(object->property("test") == QVariant::fromValue((QObject *)0));
2955 // Test that bindings don't evaluate once the engine has been destroyed
2956 void tst_qdeclarativeecmascript::deletedEngine()
2958 QDeclarativeEngine *engine = new QDeclarativeEngine;
2959 QDeclarativeComponent component(engine, TEST_FILE("deletedEngine.qml"));
2961 QObject *object = component.create();
2962 QVERIFY(object != 0);
2964 QCOMPARE(object->property("a").toInt(), 39);
2965 object->setProperty("b", QVariant(9));
2966 QCOMPARE(object->property("a").toInt(), 117);
2970 QCOMPARE(object->property("a").toInt(), 117);
2971 object->setProperty("b", QVariant(10));
2972 QCOMPARE(object->property("a").toInt(), 117);
2977 // Test the crashing part of QTBUG-9705
2978 void tst_qdeclarativeecmascript::libraryScriptAssert()
2980 QDeclarativeComponent component(&engine, TEST_FILE("libraryScriptAssert.qml"));
2982 QObject *object = component.create();
2983 QVERIFY(object != 0);
2988 void tst_qdeclarativeecmascript::variantsAssignedUndefined()
2990 QDeclarativeComponent component(&engine, TEST_FILE("variantsAssignedUndefined.qml"));
2992 QObject *object = component.create();
2993 QVERIFY(object != 0);
2995 QCOMPARE(object->property("test1").toInt(), 10);
2996 QCOMPARE(object->property("test2").toInt(), 11);
2998 object->setProperty("runTest", true);
3000 QCOMPARE(object->property("test1"), QVariant());
3001 QCOMPARE(object->property("test2"), QVariant());
3007 void tst_qdeclarativeecmascript::qtbug_9792()
3009 QDeclarativeComponent component(&engine, TEST_FILE("qtbug_9792.qml"));
3011 QDeclarativeContext *context = new QDeclarativeContext(engine.rootContext());
3013 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create(context));
3014 QVERIFY(object != 0);
3016 QTest::ignoreMessage(QtDebugMsg, "Hello world!");
3017 object->basicSignal();
3021 transientErrorsMsgCount = 0;
3022 QtMsgHandler old = qInstallMsgHandler(transientErrorsMsgHandler);
3024 object->basicSignal();
3026 qInstallMsgHandler(old);
3028 QCOMPARE(transientErrorsMsgCount, 0);
3033 // Verifies that QDeclarativeGuard<>s used in the vmemetaobject are cleaned correctly
3034 void tst_qdeclarativeecmascript::qtcreatorbug_1289()
3036 QDeclarativeComponent component(&engine, TEST_FILE("qtcreatorbug_1289.qml"));
3038 QObject *o = component.create();
3041 QObject *nested = qvariant_cast<QObject *>(o->property("object"));
3042 QVERIFY(nested != 0);
3044 QVERIFY(qvariant_cast<QObject *>(nested->property("nestedObject")) == o);
3047 nested = qvariant_cast<QObject *>(o->property("object"));
3048 QVERIFY(nested == 0);
3050 // If the bug is present, the next line will crash
3054 // Test that we shut down without stupid warnings
3055 void tst_qdeclarativeecmascript::noSpuriousWarningsAtShutdown()
3058 QDeclarativeComponent component(&engine, TEST_FILE("noSpuriousWarningsAtShutdown.qml"));
3060 QObject *o = component.create();
3062 transientErrorsMsgCount = 0;
3063 QtMsgHandler old = qInstallMsgHandler(transientErrorsMsgHandler);
3067 qInstallMsgHandler(old);
3069 QCOMPARE(transientErrorsMsgCount, 0);
3074 QDeclarativeComponent component(&engine, TEST_FILE("noSpuriousWarningsAtShutdown.2.qml"));
3076 QObject *o = component.create();
3078 transientErrorsMsgCount = 0;
3079 QtMsgHandler old = qInstallMsgHandler(transientErrorsMsgHandler);
3083 qInstallMsgHandler(old);
3085 QCOMPARE(transientErrorsMsgCount, 0);
3089 void tst_qdeclarativeecmascript::canAssignNullToQObject()
3092 QDeclarativeComponent component(&engine, TEST_FILE("canAssignNullToQObject.1.qml"));
3094 MyQmlObject *o = qobject_cast<MyQmlObject *>(component.create());
3097 QVERIFY(o->objectProperty() != 0);
3099 o->setProperty("runTest", true);
3101 QVERIFY(o->objectProperty() == 0);
3107 QDeclarativeComponent component(&engine, TEST_FILE("canAssignNullToQObject.2.qml"));
3109 MyQmlObject *o = qobject_cast<MyQmlObject *>(component.create());
3112 QVERIFY(o->objectProperty() == 0);
3118 void tst_qdeclarativeecmascript::functionAssignment_fromBinding()
3120 QDeclarativeComponent component(&engine, TEST_FILE("functionAssignment.1.qml"));
3122 QString url = component.url().toString();
3123 QString warning = url + ":4: Unable to assign a function to a property.";
3124 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
3126 MyQmlObject *o = qobject_cast<MyQmlObject *>(component.create());
3129 QVERIFY(!o->property("a").isValid());
3134 void tst_qdeclarativeecmascript::functionAssignment_fromJS()
3136 QFETCH(QString, triggerProperty);
3138 QDeclarativeComponent component(&engine, TEST_FILE("functionAssignment.2.qml"));
3139 QVERIFY2(component.errorString().isEmpty(), qPrintable(component.errorString()));
3141 MyQmlObject *o = qobject_cast<MyQmlObject *>(component.create());
3143 QVERIFY(!o->property("a").isValid());
3145 o->setProperty("aNumber", QVariant(5));
3146 o->setProperty(triggerProperty.toUtf8().constData(), true);
3147 QCOMPARE(o->property("a"), QVariant(50));
3149 o->setProperty("aNumber", QVariant(10));
3150 QCOMPARE(o->property("a"), QVariant(100));
3155 void tst_qdeclarativeecmascript::functionAssignment_fromJS_data()
3157 QTest::addColumn<QString>("triggerProperty");
3159 QTest::newRow("assign to property") << "assignToProperty";
3160 QTest::newRow("assign to property, from JS file") << "assignToPropertyFromJsFile";
3162 QTest::newRow("assign to value type") << "assignToValueType";
3164 QTest::newRow("use 'this'") << "assignWithThis";
3165 QTest::newRow("use 'this' from JS file") << "assignWithThisFromJsFile";
3168 void tst_qdeclarativeecmascript::functionAssignmentfromJS_invalid()
3170 QDeclarativeComponent component(&engine, TEST_FILE("functionAssignment.2.qml"));
3171 QVERIFY2(component.errorString().isEmpty(), qPrintable(component.errorString()));
3173 MyQmlObject *o = qobject_cast<MyQmlObject *>(component.create());
3175 QVERIFY(!o->property("a").isValid());
3177 o->setProperty("assignFuncWithoutReturn", true);
3178 QVERIFY(!o->property("a").isValid());
3180 QString url = component.url().toString();
3181 QString warning = url + ":67: Unable to assign QString to int";
3182 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
3183 o->setProperty("assignWrongType", true);
3185 warning = url + ":71: Unable to assign QString to int";
3186 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
3187 o->setProperty("assignWrongTypeToValueType", true);
3192 void tst_qdeclarativeecmascript::eval()
3194 QDeclarativeComponent component(&engine, TEST_FILE("eval.qml"));
3196 QObject *o = component.create();
3199 QCOMPARE(o->property("test1").toBool(), true);
3200 QCOMPARE(o->property("test2").toBool(), true);
3201 QCOMPARE(o->property("test3").toBool(), true);
3202 QCOMPARE(o->property("test4").toBool(), true);
3203 QCOMPARE(o->property("test5").toBool(), true);
3208 void tst_qdeclarativeecmascript::function()
3210 QDeclarativeComponent component(&engine, TEST_FILE("function.qml"));
3212 QObject *o = component.create();
3215 QCOMPARE(o->property("test1").toBool(), true);
3216 QCOMPARE(o->property("test2").toBool(), true);
3217 QCOMPARE(o->property("test3").toBool(), true);
3222 // Test the "Qt.include" method
3223 void tst_qdeclarativeecmascript::include()
3225 // Non-library relative include
3227 QDeclarativeComponent component(&engine, TEST_FILE("include.qml"));
3228 QObject *o = component.create();
3231 QCOMPARE(o->property("test0").toInt(), 99);
3232 QCOMPARE(o->property("test1").toBool(), true);
3233 QCOMPARE(o->property("test2").toBool(), true);
3234 QCOMPARE(o->property("test2_1").toBool(), true);
3235 QCOMPARE(o->property("test3").toBool(), true);
3236 QCOMPARE(o->property("test3_1").toBool(), true);
3241 // Library relative include
3243 QDeclarativeComponent component(&engine, TEST_FILE("include_shared.qml"));
3244 QObject *o = component.create();
3247 QCOMPARE(o->property("test0").toInt(), 99);
3248 QCOMPARE(o->property("test1").toBool(), true);
3249 QCOMPARE(o->property("test2").toBool(), true);
3250 QCOMPARE(o->property("test2_1").toBool(), true);
3251 QCOMPARE(o->property("test3").toBool(), true);
3252 QCOMPARE(o->property("test3_1").toBool(), true);
3259 QDeclarativeComponent component(&engine, TEST_FILE("include_callback.qml"));
3260 QObject *o = component.create();
3263 QCOMPARE(o->property("test1").toBool(), true);
3264 QCOMPARE(o->property("test2").toBool(), true);
3265 QCOMPARE(o->property("test3").toBool(), true);
3266 QCOMPARE(o->property("test4").toBool(), true);
3267 QCOMPARE(o->property("test5").toBool(), true);
3268 QCOMPARE(o->property("test6").toBool(), true);
3273 // Including file with ".pragma library"
3275 QDeclarativeComponent component(&engine, TEST_FILE("include_pragma.qml"));
3276 QObject *o = component.create();
3278 QCOMPARE(o->property("test1").toInt(), 100);
3285 TestHTTPServer server(8111);
3286 QVERIFY(server.isValid());
3287 server.serveDirectory(SRCDIR "/data");
3289 QDeclarativeComponent component(&engine, TEST_FILE("include_remote.qml"));
3290 QObject *o = component.create();
3293 QTRY_VERIFY(o->property("done").toBool() == true);
3294 QTRY_VERIFY(o->property("done2").toBool() == true);
3296 QCOMPARE(o->property("test1").toBool(), true);
3297 QCOMPARE(o->property("test2").toBool(), true);
3298 QCOMPARE(o->property("test3").toBool(), true);
3299 QCOMPARE(o->property("test4").toBool(), true);
3300 QCOMPARE(o->property("test5").toBool(), true);
3302 QCOMPARE(o->property("test6").toBool(), true);
3303 QCOMPARE(o->property("test7").toBool(), true);
3304 QCOMPARE(o->property("test8").toBool(), true);
3305 QCOMPARE(o->property("test9").toBool(), true);
3306 QCOMPARE(o->property("test10").toBool(), true);
3313 TestHTTPServer server(8111);
3314 QVERIFY(server.isValid());
3315 server.serveDirectory(SRCDIR "/data");
3317 QDeclarativeComponent component(&engine, TEST_FILE("include_remote_missing.qml"));
3318 QObject *o = component.create();
3321 QTRY_VERIFY(o->property("done").toBool() == true);
3323 QCOMPARE(o->property("test1").toBool(), true);
3324 QCOMPARE(o->property("test2").toBool(), true);
3325 QCOMPARE(o->property("test3").toBool(), true);
3331 void tst_qdeclarativeecmascript::qtbug_10696()
3333 QDeclarativeComponent component(&engine, TEST_FILE("qtbug_10696.qml"));
3334 QObject *o = component.create();
3339 void tst_qdeclarativeecmascript::qtbug_11606()
3341 QDeclarativeComponent component(&engine, TEST_FILE("qtbug_11606.qml"));
3342 QObject *o = component.create();
3344 QCOMPARE(o->property("test").toBool(), true);
3348 void tst_qdeclarativeecmascript::qtbug_11600()
3350 QDeclarativeComponent component(&engine, TEST_FILE("qtbug_11600.qml"));
3351 QObject *o = component.create();
3353 QCOMPARE(o->property("test").toBool(), true);
3357 // Reading and writing non-scriptable properties should fail
3358 void tst_qdeclarativeecmascript::nonscriptable()
3360 QDeclarativeComponent component(&engine, TEST_FILE("nonscriptable.qml"));
3361 QObject *o = component.create();
3363 QCOMPARE(o->property("readOk").toBool(), true);
3364 QCOMPARE(o->property("writeOk").toBool(), true);
3368 // deleteLater() should not be callable from QML
3369 void tst_qdeclarativeecmascript::deleteLater()
3371 QDeclarativeComponent component(&engine, TEST_FILE("deleteLater.qml"));
3372 QObject *o = component.create();
3374 QCOMPARE(o->property("test").toBool(), true);
3378 void tst_qdeclarativeecmascript::in()
3380 QDeclarativeComponent component(&engine, TEST_FILE("in.qml"));
3381 QObject *o = component.create();
3383 QCOMPARE(o->property("test1").toBool(), true);
3384 QCOMPARE(o->property("test2").toBool(), true);
3388 void tst_qdeclarativeecmascript::sharedAttachedObject()
3390 QDeclarativeComponent component(&engine, TEST_FILE("sharedAttachedObject.qml"));
3391 QObject *o = component.create();
3393 QCOMPARE(o->property("test1").toBool(), true);
3394 QCOMPARE(o->property("test2").toBool(), true);
3399 void tst_qdeclarativeecmascript::objectName()
3401 QDeclarativeComponent component(&engine, TEST_FILE("objectName.qml"));
3402 QObject *o = component.create();
3405 QCOMPARE(o->property("test1").toString(), QString("hello"));
3406 QCOMPARE(o->property("test2").toString(), QString("ell"));
3408 o->setObjectName("world");
3410 QCOMPARE(o->property("test1").toString(), QString("world"));
3411 QCOMPARE(o->property("test2").toString(), QString("orl"));
3416 void tst_qdeclarativeecmascript::writeRemovesBinding()
3418 QDeclarativeComponent component(&engine, TEST_FILE("writeRemovesBinding.qml"));
3419 QObject *o = component.create();
3422 QCOMPARE(o->property("test").toBool(), true);
3427 // Test bindings assigned to alias properties actually assign to the alias' target
3428 void tst_qdeclarativeecmascript::aliasBindingsAssignCorrectly()
3430 QDeclarativeComponent component(&engine, TEST_FILE("aliasBindingsAssignCorrectly.qml"));
3431 QObject *o = component.create();
3434 QCOMPARE(o->property("test").toBool(), true);
3439 // Test bindings assigned to alias properties override a binding on the target (QTBUG-13719)
3440 void tst_qdeclarativeecmascript::aliasBindingsOverrideTarget()
3443 QDeclarativeComponent component(&engine, TEST_FILE("aliasBindingsOverrideTarget.qml"));
3444 QObject *o = component.create();
3447 QCOMPARE(o->property("test").toBool(), true);
3453 QDeclarativeComponent component(&engine, TEST_FILE("aliasBindingsOverrideTarget.2.qml"));
3454 QObject *o = component.create();
3457 QCOMPARE(o->property("test").toBool(), true);
3463 QDeclarativeComponent component(&engine, TEST_FILE("aliasBindingsOverrideTarget.3.qml"));
3464 QObject *o = component.create();
3467 QCOMPARE(o->property("test").toBool(), true);
3473 // Test that writes to alias properties override bindings on the alias target (QTBUG-13719)
3474 void tst_qdeclarativeecmascript::aliasWritesOverrideBindings()
3477 QDeclarativeComponent component(&engine, TEST_FILE("aliasWritesOverrideBindings.qml"));
3478 QObject *o = component.create();
3481 QCOMPARE(o->property("test").toBool(), true);
3487 QDeclarativeComponent component(&engine, TEST_FILE("aliasWritesOverrideBindings.2.qml"));
3488 QObject *o = component.create();
3491 QCOMPARE(o->property("test").toBool(), true);
3497 QDeclarativeComponent component(&engine, TEST_FILE("aliasWritesOverrideBindings.3.qml"));
3498 QObject *o = component.create();
3501 QCOMPARE(o->property("test").toBool(), true);
3507 void tst_qdeclarativeecmascript::revisionErrors()
3510 QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevisionErrors.qml"));
3511 QString url = component.url().toString();
3513 QString warning1 = url + ":8: ReferenceError: Can't find variable: prop2";
3514 QString warning2 = url + ":11: ReferenceError: Can't find variable: prop2";
3515 QString warning3 = url + ":13: ReferenceError: Can't find variable: method2";
3517 QTest::ignoreMessage(QtWarningMsg, warning1.toLatin1().constData());
3518 QTest::ignoreMessage(QtWarningMsg, warning2.toLatin1().constData());
3519 QTest::ignoreMessage(QtWarningMsg, warning3.toLatin1().constData());
3520 MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create());
3521 QVERIFY(object != 0);
3525 QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevisionErrors2.qml"));
3526 QString url = component.url().toString();
3528 // MyRevisionedSubclass 1.0 uses MyRevisionedClass revision 0
3529 // method2, prop2 from MyRevisionedClass not available
3530 // method4, prop4 from MyRevisionedSubclass not available
3531 QString warning1 = url + ":8: ReferenceError: Can't find variable: prop2";
3532 QString warning2 = url + ":14: ReferenceError: Can't find variable: prop2";
3533 QString warning3 = url + ":10: ReferenceError: Can't find variable: prop4";
3534 QString warning4 = url + ":16: ReferenceError: Can't find variable: prop4";
3535 QString warning5 = url + ":20: ReferenceError: Can't find variable: method2";
3537 QTest::ignoreMessage(QtWarningMsg, warning1.toLatin1().constData());
3538 QTest::ignoreMessage(QtWarningMsg, warning2.toLatin1().constData());
3539 QTest::ignoreMessage(QtWarningMsg, warning3.toLatin1().constData());
3540 QTest::ignoreMessage(QtWarningMsg, warning4.toLatin1().constData());
3541 QTest::ignoreMessage(QtWarningMsg, warning5.toLatin1().constData());
3542 MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create());
3543 QVERIFY(object != 0);
3547 QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevisionErrors3.qml"));
3548 QString url = component.url().toString();
3550 // MyRevisionedSubclass 1.1 uses MyRevisionedClass revision 1
3551 // All properties/methods available, except MyRevisionedBaseClassUnregistered rev 1
3552 QString warning1 = url + ":30: ReferenceError: Can't find variable: methodD";
3553 QString warning2 = url + ":10: ReferenceError: Can't find variable: propD";
3554 QString warning3 = url + ":20: ReferenceError: Can't find variable: propD";
3555 QTest::ignoreMessage(QtWarningMsg, warning1.toLatin1().constData());
3556 QTest::ignoreMessage(QtWarningMsg, warning2.toLatin1().constData());
3557 QTest::ignoreMessage(QtWarningMsg, warning3.toLatin1().constData());
3558 MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create());
3559 QVERIFY(object != 0);
3564 void tst_qdeclarativeecmascript::revision()
3567 QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevision.qml"));
3568 QString url = component.url().toString();
3570 MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create());
3571 QVERIFY(object != 0);
3575 QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevision2.qml"));
3576 QString url = component.url().toString();
3578 MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create());
3579 QVERIFY(object != 0);
3583 QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevision3.qml"));
3584 QString url = component.url().toString();
3586 MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create());
3587 QVERIFY(object != 0);
3590 // Test that non-root classes can resolve revisioned methods
3592 QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevision4.qml"));
3594 QObject *object = component.create();
3595 QVERIFY(object != 0);
3596 QCOMPARE(object->property("test").toReal(), 11.);
3601 void tst_qdeclarativeecmascript::realToInt()
3603 QDeclarativeComponent component(&engine, TEST_FILE("realToInt.qml"));
3604 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
3605 QVERIFY(object != 0);
3607 QMetaObject::invokeMethod(object, "test1");
3608 QCOMPARE(object->value(), int(4));
3609 QMetaObject::invokeMethod(object, "test2");
3610 QCOMPARE(object->value(), int(8));
3613 QTEST_MAIN(tst_qdeclarativeecmascript)
3615 #include "tst_qdeclarativeecmascript.moc"