1 /****************************************************************************
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
7 ** This file is part of the test suite of the Qt Toolkit.
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** GNU Lesser General Public License Usage
11 ** This file may be used under the terms of the GNU Lesser General Public
12 ** License version 2.1 as published by the Free Software Foundation and
13 ** appearing in the file LICENSE.LGPL included in the packaging of this
14 ** file. Please review the following information to ensure the GNU Lesser
15 ** General Public License version 2.1 requirements will be met:
16 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
18 ** In addition, as a special exception, Nokia gives you certain additional
19 ** rights. These rights are described in the Nokia Qt LGPL Exception
20 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
22 ** GNU General Public License Usage
23 ** Alternatively, this file may be used under the terms of the GNU General
24 ** Public License version 3.0 as published by the Free Software Foundation
25 ** and appearing in the file LICENSE.GPL included in the packaging of this
26 ** file. Please review the following information to ensure the GNU General
27 ** Public License version 3.0 requirements will be met:
28 ** http://www.gnu.org/copyleft/gpl.html.
31 ** Alternatively, this file may be used in accordance with the terms and
32 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
42 #include <QtDeclarative/qdeclarativecomponent.h>
43 #include <QtDeclarative/qdeclarativeengine.h>
44 #include <QtDeclarative/qdeclarativeexpression.h>
45 #include <QtDeclarative/qdeclarativecontext.h>
46 #include <QtCore/qfileinfo.h>
47 #include <QtCore/qdebug.h>
48 #include <QtDeclarative/private/qdeclarativeguard_p.h>
49 #include <QtCore/qdir.h>
50 #include <QtCore/qnumeric.h>
51 #include <private/qdeclarativeengine_p.h>
52 #include "testtypes.h"
53 #include "testhttpserver.h"
54 #include "../../../shared/util.h"
57 // In Symbian OS test data is located in applications private dir
62 This test covers evaluation of ECMAScript expressions and bindings from within
63 QML. This does not include static QML language issues.
65 Static QML language issues are covered in qmllanguage
67 inline QUrl TEST_FILE(const QString &filename)
69 QFileInfo fileInfo(__FILE__);
70 return QUrl::fromLocalFile(fileInfo.absoluteDir().filePath("data/" + filename));
73 inline QUrl TEST_FILE(const char *filename)
75 return TEST_FILE(QLatin1String(filename));
78 class tst_qdeclarativeecmascript : public QObject
82 tst_qdeclarativeecmascript() {}
86 void assignBasicTypes();
87 void idShortcutInvalidates();
88 void boolPropertiesEvaluateAsBool();
90 void signalAssignment();
92 void basicExpressions();
93 void basicExpressions_data();
94 void arrayExpressions();
95 void contextPropertiesTriggerReeval();
96 void objectPropertiesTriggerReeval();
97 void deferredProperties();
98 void deferredPropertiesErrors();
99 void extensionObjects();
100 void overrideExtensionProperties();
101 void attachedProperties();
103 void valueTypeFunctions();
104 void constantsOverrideBindings();
105 void outerBindingOverridesInnerBinding();
106 void aliasPropertyAndBinding();
107 void nonExistentAttachedObject();
110 void signalParameterTypes();
111 void objectsCompareAsEqual();
112 void dynamicCreation_data();
113 void dynamicCreation();
114 void dynamicDestruction();
115 void objectToString();
116 void selfDeletingBinding();
117 void extendedObjectPropertyLookup();
119 void functionErrors();
120 void propertyAssignmentErrors();
121 void signalTriggeredBindings();
122 void listProperties();
123 void exceptionClearsOnReeval();
124 void exceptionSlotProducesWarning();
125 void exceptionBindingProducesWarning();
126 void transientErrors();
127 void shutdownErrors();
128 void compositePropertyType();
130 void undefinedResetsProperty();
131 void listToVariant();
132 void multiEngineObject();
133 void deletedObject();
134 void attachedPropertyScope();
135 void scriptConnect();
136 void scriptDisconnect();
138 void cppOwnershipReturnValue();
139 void ownershipCustomReturnValue();
140 void qlistqobjectMethods();
141 void strictlyEquals();
143 void numberAssignment();
144 void propertySplicing();
145 void signalWithUnknownTypes();
147 void importScripts();
148 void scarceResources();
149 void propertyChangeSlots();
150 void elementAssign();
151 void objectPassThroughSignals();
152 void booleanConversion();
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();
184 void aliasToCompositeElement();
186 void dynamicString();
189 void callQtInvokables();
190 void invokableObjectArg();
191 void invokableObjectRet();
193 void revisionErrors();
197 QDeclarativeEngine engine;
200 void tst_qdeclarativeecmascript::initTestCase() { registerTypes(); }
202 void tst_qdeclarativeecmascript::assignBasicTypes()
205 QDeclarativeComponent component(&engine, TEST_FILE("assignBasicTypes.qml"));
206 MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
207 QVERIFY(object != 0);
208 QCOMPARE(object->flagProperty(), MyTypeObject::FlagVal1 | MyTypeObject::FlagVal3);
209 QCOMPARE(object->enumProperty(), MyTypeObject::EnumVal2);
210 QCOMPARE(object->stringProperty(), QString("Hello World!"));
211 QCOMPARE(object->uintProperty(), uint(10));
212 QCOMPARE(object->intProperty(), -19);
213 QCOMPARE((float)object->realProperty(), float(23.2));
214 QCOMPARE((float)object->doubleProperty(), float(-19.75));
215 QCOMPARE((float)object->floatProperty(), float(8.5));
216 QCOMPARE(object->colorProperty(), QColor("red"));
217 QCOMPARE(object->dateProperty(), QDate(1982, 11, 25));
218 QCOMPARE(object->timeProperty(), QTime(11, 11, 32));
219 QCOMPARE(object->dateTimeProperty(), QDateTime(QDate(2009, 5, 12), QTime(13, 22, 1)));
220 QCOMPARE(object->pointProperty(), QPoint(99,13));
221 QCOMPARE(object->pointFProperty(), QPointF(-10.1, 12.3));
222 QCOMPARE(object->sizeProperty(), QSize(99, 13));
223 QCOMPARE(object->sizeFProperty(), QSizeF(0.1, 0.2));
224 QCOMPARE(object->rectProperty(), QRect(9, 7, 100, 200));
225 QCOMPARE(object->rectFProperty(), QRectF(1000.1, -10.9, 400, 90.99));
226 QCOMPARE(object->boolProperty(), true);
227 QCOMPARE(object->variantProperty(), QVariant("Hello World!"));
228 QCOMPARE(object->vectorProperty(), QVector3D(10, 1, 2.2));
229 QCOMPARE(object->urlProperty(), component.url().resolved(QUrl("main.qml")));
233 QDeclarativeComponent component(&engine, TEST_FILE("assignBasicTypes.2.qml"));
234 MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
235 QVERIFY(object != 0);
236 QCOMPARE(object->flagProperty(), MyTypeObject::FlagVal1 | MyTypeObject::FlagVal3);
237 QCOMPARE(object->enumProperty(), MyTypeObject::EnumVal2);
238 QCOMPARE(object->stringProperty(), QString("Hello World!"));
239 QCOMPARE(object->uintProperty(), uint(10));
240 QCOMPARE(object->intProperty(), -19);
241 QCOMPARE((float)object->realProperty(), float(23.2));
242 QCOMPARE((float)object->doubleProperty(), float(-19.75));
243 QCOMPARE((float)object->floatProperty(), float(8.5));
244 QCOMPARE(object->colorProperty(), QColor("red"));
245 QCOMPARE(object->dateProperty(), QDate(1982, 11, 25));
246 QCOMPARE(object->timeProperty(), QTime(11, 11, 32));
247 QCOMPARE(object->dateTimeProperty(), QDateTime(QDate(2009, 5, 12), QTime(13, 22, 1)));
248 QCOMPARE(object->pointProperty(), QPoint(99,13));
249 QCOMPARE(object->pointFProperty(), QPointF(-10.1, 12.3));
250 QCOMPARE(object->sizeProperty(), QSize(99, 13));
251 QCOMPARE(object->sizeFProperty(), QSizeF(0.1, 0.2));
252 QCOMPARE(object->rectProperty(), QRect(9, 7, 100, 200));
253 QCOMPARE(object->rectFProperty(), QRectF(1000.1, -10.9, 400, 90.99));
254 QCOMPARE(object->boolProperty(), true);
255 QCOMPARE(object->variantProperty(), QVariant("Hello World!"));
256 QCOMPARE(object->vectorProperty(), QVector3D(10, 1, 2.2));
257 QCOMPARE(object->urlProperty(), component.url().resolved(QUrl("main.qml")));
262 void tst_qdeclarativeecmascript::idShortcutInvalidates()
265 QDeclarativeComponent component(&engine, TEST_FILE("idShortcutInvalidates.qml"));
266 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
267 QVERIFY(object != 0);
268 QVERIFY(object->objectProperty() != 0);
269 delete object->objectProperty();
270 QVERIFY(object->objectProperty() == 0);
275 QDeclarativeComponent component(&engine, TEST_FILE("idShortcutInvalidates.1.qml"));
276 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
277 QVERIFY(object != 0);
278 QVERIFY(object->objectProperty() != 0);
279 delete object->objectProperty();
280 QVERIFY(object->objectProperty() == 0);
285 void tst_qdeclarativeecmascript::boolPropertiesEvaluateAsBool()
288 QDeclarativeComponent component(&engine, TEST_FILE("boolPropertiesEvaluateAsBool.1.qml"));
289 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
290 QVERIFY(object != 0);
291 QCOMPARE(object->stringProperty(), QLatin1String("pass"));
295 QDeclarativeComponent component(&engine, TEST_FILE("boolPropertiesEvaluateAsBool.2.qml"));
296 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
297 QVERIFY(object != 0);
298 QCOMPARE(object->stringProperty(), QLatin1String("pass"));
303 void tst_qdeclarativeecmascript::signalAssignment()
306 QDeclarativeComponent component(&engine, TEST_FILE("signalAssignment.1.qml"));
307 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
308 QVERIFY(object != 0);
309 QCOMPARE(object->string(), QString());
310 emit object->basicSignal();
311 QCOMPARE(object->string(), QString("pass"));
316 QDeclarativeComponent component(&engine, TEST_FILE("signalAssignment.2.qml"));
317 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
318 QVERIFY(object != 0);
319 QCOMPARE(object->string(), QString());
320 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
321 QCOMPARE(object->string(), QString("pass 19 Hello world! 10.25 3 2"));
326 void tst_qdeclarativeecmascript::methods()
329 QDeclarativeComponent component(&engine, TEST_FILE("methods.1.qml"));
330 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
331 QVERIFY(object != 0);
332 QCOMPARE(object->methodCalled(), false);
333 QCOMPARE(object->methodIntCalled(), false);
334 emit object->basicSignal();
335 QCOMPARE(object->methodCalled(), true);
336 QCOMPARE(object->methodIntCalled(), false);
341 QDeclarativeComponent component(&engine, TEST_FILE("methods.2.qml"));
342 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
343 QVERIFY(object != 0);
344 QCOMPARE(object->methodCalled(), false);
345 QCOMPARE(object->methodIntCalled(), false);
346 emit object->basicSignal();
347 QCOMPARE(object->methodCalled(), false);
348 QCOMPARE(object->methodIntCalled(), true);
353 QDeclarativeComponent component(&engine, TEST_FILE("methods.3.qml"));
354 QObject *object = component.create();
355 QVERIFY(object != 0);
356 QCOMPARE(object->property("test").toInt(), 19);
361 QDeclarativeComponent component(&engine, TEST_FILE("methods.4.qml"));
362 QObject *object = component.create();
363 QVERIFY(object != 0);
364 QCOMPARE(object->property("test").toInt(), 19);
365 QCOMPARE(object->property("test2").toInt(), 17);
366 QCOMPARE(object->property("test3").toInt(), 16);
371 QDeclarativeComponent component(&engine, TEST_FILE("methods.5.qml"));
372 QObject *object = component.create();
373 QVERIFY(object != 0);
374 QCOMPARE(object->property("test").toInt(), 9);
379 void tst_qdeclarativeecmascript::bindingLoop()
381 QDeclarativeComponent component(&engine, TEST_FILE("bindingLoop.qml"));
382 QString warning = component.url().toString() + ":9:9: QML MyQmlObject: Binding loop detected for property \"stringProperty\"";
383 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
384 QObject *object = component.create();
385 QVERIFY(object != 0);
389 void tst_qdeclarativeecmascript::basicExpressions_data()
391 QTest::addColumn<QString>("expression");
392 QTest::addColumn<QVariant>("result");
393 QTest::addColumn<bool>("nest");
395 QTest::newRow("Syntax error (self test)") << "{console.log({'a':1'}.a)}" << QVariant() << false;
396 QTest::newRow("Context property") << "a" << QVariant(1944) << false;
397 QTest::newRow("Context property") << "a" << QVariant(1944) << true;
398 QTest::newRow("Context property expression") << "a * 2" << QVariant(3888) << false;
399 QTest::newRow("Context property expression") << "a * 2" << QVariant(3888) << true;
400 QTest::newRow("Overridden context property") << "b" << QVariant("Milk") << false;
401 QTest::newRow("Overridden context property") << "b" << QVariant("Cow") << true;
402 QTest::newRow("Object property") << "object.stringProperty" << QVariant("Object1") << false;
403 QTest::newRow("Object property") << "object.stringProperty" << QVariant("Object1") << true;
404 QTest::newRow("Overridden object property") << "objectOverride.stringProperty" << QVariant("Object2") << false;
405 QTest::newRow("Overridden object property") << "objectOverride.stringProperty" << QVariant("Object3") << true;
406 QTest::newRow("Default object property") << "horseLegs" << QVariant(4) << false;
407 QTest::newRow("Default object property") << "antLegs" << QVariant(6) << false;
408 QTest::newRow("Default object property") << "emuLegs" << QVariant(2) << false;
409 QTest::newRow("Nested default object property") << "horseLegs" << QVariant(4) << true;
410 QTest::newRow("Nested default object property") << "antLegs" << QVariant(7) << true;
411 QTest::newRow("Nested default object property") << "emuLegs" << QVariant(2) << true;
412 QTest::newRow("Nested default object property") << "humanLegs" << QVariant(2) << true;
413 QTest::newRow("Context property override default object property") << "millipedeLegs" << QVariant(100) << true;
416 void tst_qdeclarativeecmascript::basicExpressions()
418 QFETCH(QString, expression);
419 QFETCH(QVariant, result);
425 MyDefaultObject1 default1;
426 MyDefaultObject3 default3;
427 object1.setStringProperty("Object1");
428 object2.setStringProperty("Object2");
429 object3.setStringProperty("Object3");
431 QDeclarativeContext context(engine.rootContext());
432 QDeclarativeContext nestedContext(&context);
434 context.setContextObject(&default1);
435 context.setContextProperty("a", QVariant(1944));
436 context.setContextProperty("b", QVariant("Milk"));
437 context.setContextProperty("object", &object1);
438 context.setContextProperty("objectOverride", &object2);
439 nestedContext.setContextObject(&default3);
440 nestedContext.setContextProperty("b", QVariant("Cow"));
441 nestedContext.setContextProperty("objectOverride", &object3);
442 nestedContext.setContextProperty("millipedeLegs", QVariant(100));
444 MyExpression expr(nest?&nestedContext:&context, expression);
445 QCOMPARE(expr.evaluate(), result);
448 void tst_qdeclarativeecmascript::arrayExpressions()
454 QDeclarativeContext context(engine.rootContext());
455 context.setContextProperty("a", &obj1);
456 context.setContextProperty("b", &obj2);
457 context.setContextProperty("c", &obj3);
459 MyExpression expr(&context, "[a, b, c, 10]");
460 QVariant result = expr.evaluate();
461 QCOMPARE(result.userType(), qMetaTypeId<QList<QObject *> >());
462 QList<QObject *> list = qvariant_cast<QList<QObject *> >(result);
463 QCOMPARE(list.count(), 4);
464 QCOMPARE(list.at(0), &obj1);
465 QCOMPARE(list.at(1), &obj2);
466 QCOMPARE(list.at(2), &obj3);
467 QCOMPARE(list.at(3), (QObject *)0);
470 // Tests that modifying a context property will reevaluate expressions
471 void tst_qdeclarativeecmascript::contextPropertiesTriggerReeval()
473 QDeclarativeContext context(engine.rootContext());
476 MyQmlObject *object3 = new MyQmlObject;
478 object1.setStringProperty("Hello");
479 object2.setStringProperty("World");
481 context.setContextProperty("testProp", QVariant(1));
482 context.setContextProperty("testObj", &object1);
483 context.setContextProperty("testObj2", object3);
486 MyExpression expr(&context, "testProp + 1");
487 QCOMPARE(expr.changed, false);
488 QCOMPARE(expr.evaluate(), QVariant(2));
490 context.setContextProperty("testProp", QVariant(2));
491 QCOMPARE(expr.changed, true);
492 QCOMPARE(expr.evaluate(), QVariant(3));
496 MyExpression expr(&context, "testProp + testProp + testProp");
497 QCOMPARE(expr.changed, false);
498 QCOMPARE(expr.evaluate(), QVariant(6));
500 context.setContextProperty("testProp", QVariant(4));
501 QCOMPARE(expr.changed, true);
502 QCOMPARE(expr.evaluate(), QVariant(12));
506 MyExpression expr(&context, "testObj.stringProperty");
507 QCOMPARE(expr.changed, false);
508 QCOMPARE(expr.evaluate(), QVariant("Hello"));
510 context.setContextProperty("testObj", &object2);
511 QCOMPARE(expr.changed, true);
512 QCOMPARE(expr.evaluate(), QVariant("World"));
516 MyExpression expr(&context, "testObj.stringProperty /**/");
517 QCOMPARE(expr.changed, false);
518 QCOMPARE(expr.evaluate(), QVariant("World"));
520 context.setContextProperty("testObj", &object1);
521 QCOMPARE(expr.changed, true);
522 QCOMPARE(expr.evaluate(), QVariant("Hello"));
526 MyExpression expr(&context, "testObj2");
527 QCOMPARE(expr.changed, false);
528 QCOMPARE(expr.evaluate(), QVariant::fromValue((QObject *)object3));
534 void tst_qdeclarativeecmascript::objectPropertiesTriggerReeval()
536 QDeclarativeContext context(engine.rootContext());
540 context.setContextProperty("testObj", &object1);
542 object1.setStringProperty(QLatin1String("Hello"));
543 object2.setStringProperty(QLatin1String("Dog"));
544 object3.setStringProperty(QLatin1String("Cat"));
547 MyExpression expr(&context, "testObj.stringProperty");
548 QCOMPARE(expr.changed, false);
549 QCOMPARE(expr.evaluate(), QVariant("Hello"));
551 object1.setStringProperty(QLatin1String("World"));
552 QCOMPARE(expr.changed, true);
553 QCOMPARE(expr.evaluate(), QVariant("World"));
557 MyExpression expr(&context, "testObj.objectProperty.stringProperty");
558 QCOMPARE(expr.changed, false);
559 QCOMPARE(expr.evaluate(), QVariant());
561 object1.setObjectProperty(&object2);
562 QCOMPARE(expr.changed, true);
563 expr.changed = false;
564 QCOMPARE(expr.evaluate(), QVariant("Dog"));
566 object1.setObjectProperty(&object3);
567 QCOMPARE(expr.changed, true);
568 expr.changed = false;
569 QCOMPARE(expr.evaluate(), QVariant("Cat"));
571 object1.setObjectProperty(0);
572 QCOMPARE(expr.changed, true);
573 expr.changed = false;
574 QCOMPARE(expr.evaluate(), QVariant());
576 object1.setObjectProperty(&object3);
577 QCOMPARE(expr.changed, true);
578 expr.changed = false;
579 QCOMPARE(expr.evaluate(), QVariant("Cat"));
581 object3.setStringProperty("Donkey");
582 QCOMPARE(expr.changed, true);
583 expr.changed = false;
584 QCOMPARE(expr.evaluate(), QVariant("Donkey"));
588 void tst_qdeclarativeecmascript::deferredProperties()
590 QDeclarativeComponent component(&engine, TEST_FILE("deferredProperties.qml"));
591 MyDeferredObject *object =
592 qobject_cast<MyDeferredObject *>(component.create());
593 QVERIFY(object != 0);
594 QCOMPARE(object->value(), 0);
595 QVERIFY(object->objectProperty() == 0);
596 QVERIFY(object->objectProperty2() != 0);
597 qmlExecuteDeferred(object);
598 QCOMPARE(object->value(), 10);
599 QVERIFY(object->objectProperty() != 0);
600 MyQmlObject *qmlObject =
601 qobject_cast<MyQmlObject *>(object->objectProperty());
602 QVERIFY(qmlObject != 0);
603 QCOMPARE(qmlObject->value(), 10);
604 object->setValue(19);
605 QCOMPARE(qmlObject->value(), 19);
610 // Check errors on deferred properties are correctly emitted
611 void tst_qdeclarativeecmascript::deferredPropertiesErrors()
613 QDeclarativeComponent component(&engine, TEST_FILE("deferredPropertiesErrors.qml"));
614 MyDeferredObject *object =
615 qobject_cast<MyDeferredObject *>(component.create());
616 QVERIFY(object != 0);
617 QCOMPARE(object->value(), 0);
618 QVERIFY(object->objectProperty() == 0);
619 QVERIFY(object->objectProperty2() == 0);
621 QString warning = component.url().toString() + ":6: Unable to assign [undefined] to QObject* objectProperty";
622 QTest::ignoreMessage(QtWarningMsg, qPrintable(warning));
624 qmlExecuteDeferred(object);
629 void tst_qdeclarativeecmascript::extensionObjects()
631 QDeclarativeComponent component(&engine, TEST_FILE("extensionObjects.qml"));
632 MyExtendedObject *object =
633 qobject_cast<MyExtendedObject *>(component.create());
634 QVERIFY(object != 0);
635 QCOMPARE(object->baseProperty(), 13);
636 QCOMPARE(object->coreProperty(), 9);
637 object->setProperty("extendedProperty", QVariant(11));
638 object->setProperty("baseExtendedProperty", QVariant(92));
639 QCOMPARE(object->coreProperty(), 11);
640 QCOMPARE(object->baseProperty(), 92);
642 MyExtendedObject *nested = qobject_cast<MyExtendedObject*>(qvariant_cast<QObject *>(object->property("nested")));
644 QCOMPARE(nested->baseProperty(), 13);
645 QCOMPARE(nested->coreProperty(), 9);
646 nested->setProperty("extendedProperty", QVariant(11));
647 nested->setProperty("baseExtendedProperty", QVariant(92));
648 QCOMPARE(nested->coreProperty(), 11);
649 QCOMPARE(nested->baseProperty(), 92);
654 void tst_qdeclarativeecmascript::overrideExtensionProperties()
656 QDeclarativeComponent component(&engine, TEST_FILE("extensionObjectsPropertyOverride.qml"));
657 OverrideDefaultPropertyObject *object =
658 qobject_cast<OverrideDefaultPropertyObject *>(component.create());
659 QVERIFY(object != 0);
660 QVERIFY(object->secondProperty() != 0);
661 QVERIFY(object->firstProperty() == 0);
666 void tst_qdeclarativeecmascript::attachedProperties()
669 QDeclarativeComponent component(&engine, TEST_FILE("attachedProperty.qml"));
670 QObject *object = component.create();
671 QVERIFY(object != 0);
672 QCOMPARE(object->property("a").toInt(), 19);
673 QCOMPARE(object->property("b").toInt(), 19);
674 QCOMPARE(object->property("c").toInt(), 19);
675 QCOMPARE(object->property("d").toInt(), 19);
680 QDeclarativeComponent component(&engine, TEST_FILE("attachedProperty.2.qml"));
681 QObject *object = component.create();
682 QVERIFY(object != 0);
683 QCOMPARE(object->property("a").toInt(), 26);
684 QCOMPARE(object->property("b").toInt(), 26);
685 QCOMPARE(object->property("c").toInt(), 26);
686 QCOMPARE(object->property("d").toInt(), 26);
690 QDeclarativeComponent component(&engine, TEST_FILE("writeAttachedProperty.qml"));
691 QObject *object = component.create();
692 QVERIFY(object != 0);
694 QMetaObject::invokeMethod(object, "writeValue2");
696 MyQmlAttachedObject *attached =
697 qobject_cast<MyQmlAttachedObject *>(qmlAttachedPropertiesObject<MyQmlObject>(object));
698 QVERIFY(attached != 0);
700 QCOMPARE(attached->value2(), 9);
705 void tst_qdeclarativeecmascript::enums()
709 QDeclarativeComponent component(&engine, TEST_FILE("enums.1.qml"));
710 QObject *object = component.create();
711 QVERIFY(object != 0);
713 QCOMPARE(object->property("a").toInt(), 0);
714 QCOMPARE(object->property("b").toInt(), 1);
715 QCOMPARE(object->property("c").toInt(), 2);
716 QCOMPARE(object->property("d").toInt(), 3);
717 QCOMPARE(object->property("e").toInt(), 0);
718 QCOMPARE(object->property("f").toInt(), 1);
719 QCOMPARE(object->property("g").toInt(), 2);
720 QCOMPARE(object->property("h").toInt(), 3);
721 QCOMPARE(object->property("i").toInt(), 19);
722 QCOMPARE(object->property("j").toInt(), 19);
726 // Non-existent enums
728 QDeclarativeComponent component(&engine, TEST_FILE("enums.2.qml"));
730 QString warning1 = component.url().toString() + ":5: Unable to assign [undefined] to int a";
731 QString warning2 = component.url().toString() + ":6: Unable to assign [undefined] to int b";
732 QTest::ignoreMessage(QtWarningMsg, qPrintable(warning1));
733 QTest::ignoreMessage(QtWarningMsg, qPrintable(warning2));
735 QObject *object = component.create();
736 QVERIFY(object != 0);
737 QCOMPARE(object->property("a").toInt(), 0);
738 QCOMPARE(object->property("b").toInt(), 0);
744 void tst_qdeclarativeecmascript::valueTypeFunctions()
746 QDeclarativeComponent component(&engine, TEST_FILE("valueTypeFunctions.qml"));
747 MyTypeObject *obj = qobject_cast<MyTypeObject*>(component.create());
749 QCOMPARE(obj->rectProperty(), QRect(0,0,100,100));
750 QCOMPARE(obj->rectFProperty(), QRectF(0,0.5,100,99.5));
756 Tests that writing a constant to a property with a binding on it disables the
759 void tst_qdeclarativeecmascript::constantsOverrideBindings()
763 QDeclarativeComponent component(&engine, TEST_FILE("constantsOverrideBindings.1.qml"));
764 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
765 QVERIFY(object != 0);
767 QCOMPARE(object->property("c2").toInt(), 0);
768 object->setProperty("c1", QVariant(9));
769 QCOMPARE(object->property("c2").toInt(), 9);
771 emit object->basicSignal();
773 QCOMPARE(object->property("c2").toInt(), 13);
774 object->setProperty("c1", QVariant(8));
775 QCOMPARE(object->property("c2").toInt(), 13);
780 // During construction
782 QDeclarativeComponent component(&engine, TEST_FILE("constantsOverrideBindings.2.qml"));
783 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
784 QVERIFY(object != 0);
786 QCOMPARE(object->property("c1").toInt(), 0);
787 QCOMPARE(object->property("c2").toInt(), 10);
788 object->setProperty("c1", QVariant(9));
789 QCOMPARE(object->property("c1").toInt(), 9);
790 QCOMPARE(object->property("c2").toInt(), 10);
798 QDeclarativeComponent component(&engine, TEST_FILE("constantsOverrideBindings.3.qml"));
799 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
800 QVERIFY(object != 0);
802 QCOMPARE(object->property("c2").toInt(), 0);
803 object->setProperty("c1", QVariant(9));
804 QCOMPARE(object->property("c2").toInt(), 9);
806 object->setProperty("c2", QVariant(13));
807 QCOMPARE(object->property("c2").toInt(), 13);
808 object->setProperty("c1", QVariant(7));
809 QCOMPARE(object->property("c1").toInt(), 7);
810 QCOMPARE(object->property("c2").toInt(), 13);
818 QDeclarativeComponent component(&engine, TEST_FILE("constantsOverrideBindings.4.qml"));
819 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
820 QVERIFY(object != 0);
822 QCOMPARE(object->property("c1").toInt(), 0);
823 QCOMPARE(object->property("c3").toInt(), 10);
824 object->setProperty("c1", QVariant(9));
825 QCOMPARE(object->property("c1").toInt(), 9);
826 QCOMPARE(object->property("c3").toInt(), 10);
833 Tests that assigning a binding to a property that already has a binding causes
834 the original binding to be disabled.
836 void tst_qdeclarativeecmascript::outerBindingOverridesInnerBinding()
838 QDeclarativeComponent component(&engine,
839 TEST_FILE("outerBindingOverridesInnerBinding.qml"));
840 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
841 QVERIFY(object != 0);
843 QCOMPARE(object->property("c1").toInt(), 0);
844 QCOMPARE(object->property("c2").toInt(), 0);
845 QCOMPARE(object->property("c3").toInt(), 0);
847 object->setProperty("c1", QVariant(9));
848 QCOMPARE(object->property("c1").toInt(), 9);
849 QCOMPARE(object->property("c2").toInt(), 0);
850 QCOMPARE(object->property("c3").toInt(), 0);
852 object->setProperty("c3", QVariant(8));
853 QCOMPARE(object->property("c1").toInt(), 9);
854 QCOMPARE(object->property("c2").toInt(), 8);
855 QCOMPARE(object->property("c3").toInt(), 8);
861 Access a non-existent attached object.
863 Tests for a regression where this used to crash.
865 void tst_qdeclarativeecmascript::nonExistentAttachedObject()
867 QDeclarativeComponent component(&engine, TEST_FILE("nonExistentAttachedObject.qml"));
869 QString warning = component.url().toString() + ":4: Unable to assign [undefined] to QString stringProperty";
870 QTest::ignoreMessage(QtWarningMsg, qPrintable(warning));
872 QObject *object = component.create();
873 QVERIFY(object != 0);
878 void tst_qdeclarativeecmascript::scope()
881 QDeclarativeComponent component(&engine, TEST_FILE("scope.qml"));
882 QObject *object = component.create();
883 QVERIFY(object != 0);
885 QCOMPARE(object->property("test1").toInt(), 1);
886 QCOMPARE(object->property("test2").toInt(), 2);
887 QCOMPARE(object->property("test3").toString(), QString("1Test"));
888 QCOMPARE(object->property("test4").toString(), QString("2Test"));
889 QCOMPARE(object->property("test5").toInt(), 1);
890 QCOMPARE(object->property("test6").toInt(), 1);
891 QCOMPARE(object->property("test7").toInt(), 2);
892 QCOMPARE(object->property("test8").toInt(), 2);
893 QCOMPARE(object->property("test9").toInt(), 1);
894 QCOMPARE(object->property("test10").toInt(), 3);
900 QDeclarativeComponent component(&engine, TEST_FILE("scope.2.qml"));
901 QObject *object = component.create();
902 QVERIFY(object != 0);
904 QCOMPARE(object->property("test1").toInt(), 19);
905 QCOMPARE(object->property("test2").toInt(), 19);
906 QCOMPARE(object->property("test3").toInt(), 14);
907 QCOMPARE(object->property("test4").toInt(), 14);
908 QCOMPARE(object->property("test5").toInt(), 24);
909 QCOMPARE(object->property("test6").toInt(), 24);
915 QDeclarativeComponent component(&engine, TEST_FILE("scope.3.qml"));
916 QObject *object = component.create();
917 QVERIFY(object != 0);
919 QCOMPARE(object->property("test1").toBool(), true);
920 QCOMPARE(object->property("test2").toBool(), true);
921 QCOMPARE(object->property("test3").toBool(), true);
926 // Signal argument scope
928 QDeclarativeComponent component(&engine, TEST_FILE("scope.4.qml"));
929 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
930 QVERIFY(object != 0);
932 QCOMPARE(object->property("test").toInt(), 0);
933 QCOMPARE(object->property("test2").toString(), QString());
935 emit object->argumentSignal(13, "Argument Scope", 9, MyQmlObject::EnumValue4, Qt::RightButton);
937 QCOMPARE(object->property("test").toInt(), 13);
938 QCOMPARE(object->property("test2").toString(), QString("Argument Scope"));
944 QDeclarativeComponent component(&engine, TEST_FILE("scope.5.qml"));
945 QObject *object = component.create();
946 QVERIFY(object != 0);
948 QCOMPARE(object->property("test1").toBool(), true);
949 QCOMPARE(object->property("test2").toBool(), true);
955 QDeclarativeComponent component(&engine, TEST_FILE("scope.6.qml"));
956 QObject *object = component.create();
957 QVERIFY(object != 0);
959 QCOMPARE(object->property("test").toBool(), true);
965 // In 4.7, non-library javascript files that had no imports shared the imports of their
967 void tst_qdeclarativeecmascript::importScope()
969 QDeclarativeComponent component(&engine, TEST_FILE("importScope.qml"));
970 QObject *o = component.create();
973 QCOMPARE(o->property("test").toInt(), 240);
979 Tests that "any" type passes through a synthesized signal parameter. This
980 is essentially a test of QDeclarativeMetaType::copy()
982 void tst_qdeclarativeecmascript::signalParameterTypes()
984 QDeclarativeComponent component(&engine, TEST_FILE("signalParameterTypes.qml"));
985 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
986 QVERIFY(object != 0);
988 emit object->basicSignal();
990 QCOMPARE(object->property("intProperty").toInt(), 10);
991 QCOMPARE(object->property("realProperty").toReal(), 19.2);
992 QVERIFY(object->property("colorProperty").value<QColor>() == QColor(255, 255, 0, 255));
993 QVERIFY(object->property("variantProperty") == QVariant::fromValue(QColor(255, 0, 255, 255)));
994 QVERIFY(object->property("enumProperty") == MyQmlObject::EnumValue3);
995 QVERIFY(object->property("qtEnumProperty") == Qt::LeftButton);
1001 Test that two JS objects for the same QObject compare as equal.
1003 void tst_qdeclarativeecmascript::objectsCompareAsEqual()
1005 QDeclarativeComponent component(&engine, TEST_FILE("objectsCompareAsEqual.qml"));
1006 QObject *object = component.create();
1007 QVERIFY(object != 0);
1009 QCOMPARE(object->property("test1").toBool(), true);
1010 QCOMPARE(object->property("test2").toBool(), true);
1011 QCOMPARE(object->property("test3").toBool(), true);
1012 QCOMPARE(object->property("test4").toBool(), true);
1013 QCOMPARE(object->property("test5").toBool(), true);
1019 Confirm bindings and alias properties can coexist.
1021 Tests for a regression where the binding would not reevaluate.
1023 void tst_qdeclarativeecmascript::aliasPropertyAndBinding()
1025 QDeclarativeComponent component(&engine, TEST_FILE("aliasPropertyAndBinding.qml"));
1026 QObject *object = component.create();
1027 QVERIFY(object != 0);
1029 QCOMPARE(object->property("c2").toInt(), 3);
1030 QCOMPARE(object->property("c3").toInt(), 3);
1032 object->setProperty("c2", QVariant(19));
1034 QCOMPARE(object->property("c2").toInt(), 19);
1035 QCOMPARE(object->property("c3").toInt(), 19);
1040 void tst_qdeclarativeecmascript::dynamicCreation_data()
1042 QTest::addColumn<QString>("method");
1043 QTest::addColumn<QString>("createdName");
1045 QTest::newRow("One") << "createOne" << "objectOne";
1046 QTest::newRow("Two") << "createTwo" << "objectTwo";
1047 QTest::newRow("Three") << "createThree" << "objectThree";
1051 Test using createQmlObject to dynamically generate an item
1052 Also using createComponent is tested.
1054 void tst_qdeclarativeecmascript::dynamicCreation()
1056 QFETCH(QString, method);
1057 QFETCH(QString, createdName);
1059 QDeclarativeComponent component(&engine, TEST_FILE("dynamicCreation.qml"));
1060 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1061 QVERIFY(object != 0);
1063 QMetaObject::invokeMethod(object, method.toUtf8());
1064 QObject *created = object->objectProperty();
1066 QCOMPARE(created->objectName(), createdName);
1072 Tests the destroy function
1074 void tst_qdeclarativeecmascript::dynamicDestruction()
1077 QDeclarativeComponent component(&engine, TEST_FILE("dynamicDeletion.qml"));
1078 QDeclarativeGuard<MyQmlObject> object = qobject_cast<MyQmlObject*>(component.create());
1079 QVERIFY(object != 0);
1080 QDeclarativeGuard<QObject> createdQmlObject = 0;
1082 QMetaObject::invokeMethod(object, "create");
1083 createdQmlObject = object->objectProperty();
1084 QVERIFY(createdQmlObject);
1085 QCOMPARE(createdQmlObject->objectName(), QString("emptyObject"));
1087 QMetaObject::invokeMethod(object, "killOther");
1088 QVERIFY(createdQmlObject);
1089 QCoreApplication::instance()->processEvents(QEventLoop::DeferredDeletion);
1090 QVERIFY(createdQmlObject);
1091 for (int ii = 0; createdQmlObject && ii < 50; ++ii) { // After 5 seconds we should give up
1092 if (createdQmlObject) {
1094 QCoreApplication::instance()->processEvents(QEventLoop::DeferredDeletion);
1097 QVERIFY(!createdQmlObject);
1099 QDeclarativeEngine::setObjectOwnership(object, QDeclarativeEngine::JavaScriptOwnership);
1100 QMetaObject::invokeMethod(object, "killMe");
1103 QCoreApplication::instance()->processEvents(QEventLoop::DeferredDeletion);
1108 QDeclarativeComponent component(&engine, TEST_FILE("dynamicDeletion.2.qml"));
1109 QObject *o = component.create();
1112 QVERIFY(qvariant_cast<QObject*>(o->property("objectProperty")) == 0);
1114 QMetaObject::invokeMethod(o, "create");
1116 QVERIFY(qvariant_cast<QObject*>(o->property("objectProperty")) != 0);
1118 QMetaObject::invokeMethod(o, "destroy");
1120 QCoreApplication::instance()->processEvents(QEventLoop::DeferredDeletion);
1122 QVERIFY(qvariant_cast<QObject*>(o->property("objectProperty")) == 0);
1129 tests that id.toString() works
1131 void tst_qdeclarativeecmascript::objectToString()
1133 QDeclarativeComponent component(&engine, TEST_FILE("declarativeToString.qml"));
1134 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1135 QVERIFY(object != 0);
1136 QMetaObject::invokeMethod(object, "testToString");
1137 QVERIFY(object->stringProperty().startsWith("MyQmlObject_QML_"));
1138 QVERIFY(object->stringProperty().endsWith(", \"objName\")"));
1144 Tests bindings that indirectly cause their own deletion work.
1146 This test is best run under valgrind to ensure no invalid memory access occur.
1148 void tst_qdeclarativeecmascript::selfDeletingBinding()
1151 QDeclarativeComponent component(&engine, TEST_FILE("selfDeletingBinding.qml"));
1152 QObject *object = component.create();
1153 QVERIFY(object != 0);
1154 object->setProperty("triggerDelete", true);
1159 QDeclarativeComponent component(&engine, TEST_FILE("selfDeletingBinding.2.qml"));
1160 QObject *object = component.create();
1161 QVERIFY(object != 0);
1162 object->setProperty("triggerDelete", true);
1168 Test that extended object properties can be accessed.
1170 This test a regression where this used to crash. The issue was specificially
1171 for extended objects that did not include a synthesized meta object (so non-root
1172 and no synthesiszed properties).
1174 void tst_qdeclarativeecmascript::extendedObjectPropertyLookup()
1176 QDeclarativeComponent component(&engine, TEST_FILE("extendedObjectPropertyLookup.qml"));
1177 QObject *object = component.create();
1178 QVERIFY(object != 0);
1183 Test file/lineNumbers for binding/Script errors.
1185 void tst_qdeclarativeecmascript::scriptErrors()
1187 QDeclarativeComponent component(&engine, TEST_FILE("scriptErrors.qml"));
1188 QString url = component.url().toString();
1190 QString warning1 = url.left(url.length() - 3) + "js:2: Error: Invalid write to global property \"a\"";
1191 QString warning2 = url + ":5: ReferenceError: Can't find variable: a";
1192 QString warning3 = url.left(url.length() - 3) + "js:4: Error: Invalid write to global property \"a\"";
1193 QString warning4 = url + ":10: ReferenceError: Can't find variable: a";
1194 QString warning5 = url + ":8: ReferenceError: Can't find variable: a";
1195 QString warning6 = url + ":7: Unable to assign [undefined] to int x";
1196 QString warning7 = url + ":12: Error: Cannot assign to read-only property \"trueProperty\"";
1197 QString warning8 = url + ":13: Error: Cannot assign to non-existent property \"fakeProperty\"";
1199 QTest::ignoreMessage(QtWarningMsg, warning1.toLatin1().constData());
1200 QTest::ignoreMessage(QtWarningMsg, warning2.toLatin1().constData());
1201 QTest::ignoreMessage(QtWarningMsg, warning3.toLatin1().constData());
1202 QTest::ignoreMessage(QtWarningMsg, warning5.toLatin1().constData());
1203 QTest::ignoreMessage(QtWarningMsg, warning6.toLatin1().constData());
1204 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
1205 QVERIFY(object != 0);
1207 QTest::ignoreMessage(QtWarningMsg, warning4.toLatin1().constData());
1208 emit object->basicSignal();
1210 QTest::ignoreMessage(QtWarningMsg, warning7.toLatin1().constData());
1211 emit object->anotherBasicSignal();
1213 QTest::ignoreMessage(QtWarningMsg, warning8.toLatin1().constData());
1214 emit object->thirdBasicSignal();
1220 Test file/lineNumbers for inline functions.
1222 void tst_qdeclarativeecmascript::functionErrors()
1224 QDeclarativeComponent component(&engine, TEST_FILE("functionErrors.qml"));
1225 QString url = component.url().toString();
1227 QString warning = url + ":5: Error: Invalid write to global property \"a\"";
1229 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
1231 QObject *object = component.create();
1232 QVERIFY(object != 0);
1235 // test that if an exception occurs while invoking js function from cpp, it is reported as expected.
1236 QDeclarativeComponent componentTwo(&engine, TEST_FILE("scarceresources/scarceResourceFunctionFail.qml"));
1237 url = componentTwo.url().toString();
1238 object = componentTwo.create();
1239 QVERIFY(object != 0);
1241 QString srpname = object->property("srp_name").toString();
1243 warning = url + QLatin1String(":17: TypeError: Property 'scarceResource' of object ") + srpname +
1244 QLatin1String(" is not a function");
1245 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData()); // we expect a meaningful warning to be printed.
1246 QMetaObject::invokeMethod(object, "retrieveScarceResource");
1251 Test various errors that can occur when assigning a property from script
1253 void tst_qdeclarativeecmascript::propertyAssignmentErrors()
1255 QDeclarativeComponent component(&engine, TEST_FILE("propertyAssignmentErrors.qml"));
1257 QString url = component.url().toString();
1259 QObject *object = component.create();
1260 QVERIFY(object != 0);
1262 QCOMPARE(object->property("test1").toBool(), true);
1263 QCOMPARE(object->property("test2").toBool(), true);
1269 Test bindings still work when the reeval is triggered from within
1272 void tst_qdeclarativeecmascript::signalTriggeredBindings()
1274 QDeclarativeComponent component(&engine, TEST_FILE("signalTriggeredBindings.qml"));
1275 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1276 QVERIFY(object != 0);
1278 QCOMPARE(object->property("base").toReal(), 50.);
1279 QCOMPARE(object->property("test1").toReal(), 50.);
1280 QCOMPARE(object->property("test2").toReal(), 50.);
1282 object->basicSignal();
1284 QCOMPARE(object->property("base").toReal(), 200.);
1285 QCOMPARE(object->property("test1").toReal(), 200.);
1286 QCOMPARE(object->property("test2").toReal(), 200.);
1288 object->argumentSignal(10, QString(), 10, MyQmlObject::EnumValue4, Qt::RightButton);
1290 QCOMPARE(object->property("base").toReal(), 400.);
1291 QCOMPARE(object->property("test1").toReal(), 400.);
1292 QCOMPARE(object->property("test2").toReal(), 400.);
1298 Test that list properties can be iterated from ECMAScript
1300 void tst_qdeclarativeecmascript::listProperties()
1302 QDeclarativeComponent component(&engine, TEST_FILE("listProperties.qml"));
1303 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1304 QVERIFY(object != 0);
1306 QCOMPARE(object->property("test1").toInt(), 21);
1307 QCOMPARE(object->property("test2").toInt(), 2);
1308 QCOMPARE(object->property("test3").toBool(), true);
1309 QCOMPARE(object->property("test4").toBool(), true);
1314 void tst_qdeclarativeecmascript::exceptionClearsOnReeval()
1316 QDeclarativeComponent component(&engine, TEST_FILE("exceptionClearsOnReeval.qml"));
1317 QString url = component.url().toString();
1319 QString warning = url + ":4: TypeError: Cannot read property 'objectProperty' of null";
1321 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
1322 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1323 QVERIFY(object != 0);
1325 QCOMPARE(object->property("test").toBool(), false);
1327 MyQmlObject object2;
1328 MyQmlObject object3;
1329 object2.setObjectProperty(&object3);
1330 object->setObjectProperty(&object2);
1332 QCOMPARE(object->property("test").toBool(), true);
1337 void tst_qdeclarativeecmascript::exceptionSlotProducesWarning()
1339 QDeclarativeComponent component(&engine, TEST_FILE("exceptionProducesWarning.qml"));
1340 QString url = component.url().toString();
1342 QString warning = component.url().toString() + ":6: Error: JS exception";
1344 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
1345 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1346 QVERIFY(object != 0);
1350 void tst_qdeclarativeecmascript::exceptionBindingProducesWarning()
1352 QDeclarativeComponent component(&engine, TEST_FILE("exceptionProducesWarning2.qml"));
1353 QString url = component.url().toString();
1355 QString warning = component.url().toString() + ":5: Error: JS exception";
1357 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
1358 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1359 QVERIFY(object != 0);
1363 static int transientErrorsMsgCount = 0;
1364 static void transientErrorsMsgHandler(QtMsgType, const char *)
1366 ++transientErrorsMsgCount;
1369 // Check that transient binding errors are not displayed
1370 void tst_qdeclarativeecmascript::transientErrors()
1373 QDeclarativeComponent component(&engine, TEST_FILE("transientErrors.qml"));
1375 transientErrorsMsgCount = 0;
1376 QtMsgHandler old = qInstallMsgHandler(transientErrorsMsgHandler);
1378 QObject *object = component.create();
1379 QVERIFY(object != 0);
1381 qInstallMsgHandler(old);
1383 QCOMPARE(transientErrorsMsgCount, 0);
1388 // One binding erroring multiple times, but then resolving
1390 QDeclarativeComponent component(&engine, TEST_FILE("transientErrors.2.qml"));
1392 transientErrorsMsgCount = 0;
1393 QtMsgHandler old = qInstallMsgHandler(transientErrorsMsgHandler);
1395 QObject *object = component.create();
1396 QVERIFY(object != 0);
1398 qInstallMsgHandler(old);
1400 QCOMPARE(transientErrorsMsgCount, 0);
1406 // Check that errors during shutdown are minimized
1407 void tst_qdeclarativeecmascript::shutdownErrors()
1409 QDeclarativeComponent component(&engine, TEST_FILE("shutdownErrors.qml"));
1410 QObject *object = component.create();
1411 QVERIFY(object != 0);
1413 transientErrorsMsgCount = 0;
1414 QtMsgHandler old = qInstallMsgHandler(transientErrorsMsgHandler);
1418 qInstallMsgHandler(old);
1419 QCOMPARE(transientErrorsMsgCount, 0);
1422 void tst_qdeclarativeecmascript::compositePropertyType()
1424 QDeclarativeComponent component(&engine, TEST_FILE("compositePropertyType.qml"));
1425 QTest::ignoreMessage(QtDebugMsg, "hello world");
1426 QObject *object = qobject_cast<QObject *>(component.create());
1431 void tst_qdeclarativeecmascript::jsObject()
1433 QDeclarativeComponent component(&engine, TEST_FILE("jsObject.qml"));
1434 QObject *object = component.create();
1435 QVERIFY(object != 0);
1437 QCOMPARE(object->property("test").toInt(), 92);
1442 void tst_qdeclarativeecmascript::undefinedResetsProperty()
1445 QDeclarativeComponent component(&engine, TEST_FILE("undefinedResetsProperty.qml"));
1446 QObject *object = component.create();
1447 QVERIFY(object != 0);
1449 QCOMPARE(object->property("resettableProperty").toInt(), 92);
1451 object->setProperty("setUndefined", true);
1453 QCOMPARE(object->property("resettableProperty").toInt(), 13);
1455 object->setProperty("setUndefined", false);
1457 QCOMPARE(object->property("resettableProperty").toInt(), 92);
1462 QDeclarativeComponent component(&engine, TEST_FILE("undefinedResetsProperty.2.qml"));
1463 QObject *object = component.create();
1464 QVERIFY(object != 0);
1466 QCOMPARE(object->property("resettableProperty").toInt(), 19);
1468 QMetaObject::invokeMethod(object, "doReset");
1470 QCOMPARE(object->property("resettableProperty").toInt(), 13);
1477 void tst_qdeclarativeecmascript::bug1()
1479 QDeclarativeComponent component(&engine, TEST_FILE("bug.1.qml"));
1480 QObject *object = component.create();
1481 QVERIFY(object != 0);
1483 QCOMPARE(object->property("test").toInt(), 14);
1485 object->setProperty("a", 11);
1487 QCOMPARE(object->property("test").toInt(), 3);
1489 object->setProperty("b", true);
1491 QCOMPARE(object->property("test").toInt(), 9);
1496 void tst_qdeclarativeecmascript::bug2()
1498 QDeclarativeComponent component(&engine);
1499 component.setData("import Qt.test 1.0;\nQPlainTextEdit { width: 100 }", QUrl());
1501 QObject *object = component.create();
1502 QVERIFY(object != 0);
1507 // Don't crash in createObject when the component has errors.
1508 void tst_qdeclarativeecmascript::dynamicCreationCrash()
1510 QDeclarativeComponent component(&engine, TEST_FILE("dynamicCreation.qml"));
1511 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1512 QVERIFY(object != 0);
1514 QTest::ignoreMessage(QtWarningMsg, "QDeclarativeComponent: Component is not ready");
1515 QMetaObject::invokeMethod(object, "dontCrash");
1516 QObject *created = object->objectProperty();
1517 QVERIFY(created == 0);
1523 void tst_qdeclarativeecmascript::regExpBug()
1525 QDeclarativeComponent component(&engine, TEST_FILE("regExp.qml"));
1526 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1527 QVERIFY(object != 0);
1528 QCOMPARE(object->regExp().pattern(), QLatin1String("[a-zA-z]"));
1532 static inline bool evaluate_error(QV8Engine *engine, v8::Handle<v8::Object> o, const char *source)
1534 QString functionSource = QLatin1String("(function(object) { return ") +
1535 QLatin1String(source) + QLatin1String(" })");
1537 v8::Local<v8::Script> program = v8::Script::Compile(engine->toString(functionSource));
1540 v8::Handle<v8::Function> function = v8::Handle<v8::Function>::Cast(program->Run());
1541 if (function.IsEmpty())
1543 v8::Handle<v8::Value> args[] = { o };
1544 function->Call(engine->global(), 1, args);
1545 return tc.HasCaught();
1548 static inline bool evaluate_value(QV8Engine *engine, v8::Handle<v8::Object> o,
1549 const char *source, v8::Handle<v8::Value> result)
1551 QString functionSource = QLatin1String("(function(object) { return ") +
1552 QLatin1String(source) + QLatin1String(" })");
1554 v8::Local<v8::Script> program = v8::Script::Compile(engine->toString(functionSource));
1557 v8::Handle<v8::Function> function = v8::Handle<v8::Function>::Cast(program->Run());
1558 if (function.IsEmpty())
1560 v8::Handle<v8::Value> args[] = { o };
1562 v8::Handle<v8::Value> value = function->Call(engine->global(), 1, args);
1567 return value->StrictEquals(result);
1570 static inline v8::Handle<v8::Value> evaluate(QV8Engine *engine, v8::Handle<v8::Object> o,
1573 QString functionSource = QLatin1String("(function(object) { return ") +
1574 QLatin1String(source) + QLatin1String(" })");
1576 v8::Local<v8::Script> program = v8::Script::Compile(engine->toString(functionSource));
1578 return v8::Handle<v8::Value>();
1579 v8::Handle<v8::Function> function = v8::Handle<v8::Function>::Cast(program->Run());
1580 if (function.IsEmpty())
1581 return v8::Handle<v8::Value>();
1582 v8::Handle<v8::Value> args[] = { o };
1584 v8::Handle<v8::Value> value = function->Call(engine->global(), 1, args);
1587 return v8::Handle<v8::Value>();
1591 #define EVALUATE_ERROR(source) evaluate_error(engine, object, source)
1592 #define EVALUATE_VALUE(source, result) evaluate_value(engine, object, source, result)
1593 #define EVALUATE(source) evaluate(engine, object, source)
1595 void tst_qdeclarativeecmascript::callQtInvokables()
1597 MyInvokableObject o;
1599 QDeclarativeEngine qmlengine;
1600 QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(&qmlengine);
1602 QV8Engine *engine = ep->v8engine();
1604 v8::HandleScope handle_scope;
1605 v8::Context::Scope scope(engine->context());
1607 v8::Local<v8::Object> object = engine->newQObject(&o)->ToObject();
1609 // Non-existent methods
1611 QVERIFY(EVALUATE_ERROR("object.method_nonexistent()"));
1612 QCOMPARE(o.error(), false);
1613 QCOMPARE(o.invoked(), -1);
1614 QCOMPARE(o.actuals().count(), 0);
1617 QVERIFY(EVALUATE_ERROR("object.method_nonexistent(10, 11)"));
1618 QCOMPARE(o.error(), false);
1619 QCOMPARE(o.invoked(), -1);
1620 QCOMPARE(o.actuals().count(), 0);
1622 // Insufficient arguments
1624 QVERIFY(EVALUATE_ERROR("object.method_int()"));
1625 QCOMPARE(o.error(), false);
1626 QCOMPARE(o.invoked(), -1);
1627 QCOMPARE(o.actuals().count(), 0);
1630 QVERIFY(EVALUATE_ERROR("object.method_intint(10)"));
1631 QCOMPARE(o.error(), false);
1632 QCOMPARE(o.invoked(), -1);
1633 QCOMPARE(o.actuals().count(), 0);
1635 // Excessive arguments
1637 QVERIFY(EVALUATE_VALUE("object.method_int(10, 11)", v8::Undefined()));
1638 QCOMPARE(o.error(), false);
1639 QCOMPARE(o.invoked(), 8);
1640 QCOMPARE(o.actuals().count(), 1);
1641 QCOMPARE(o.actuals().at(0), QVariant(10));
1644 QVERIFY(EVALUATE_VALUE("object.method_intint(10, 11, 12)", v8::Undefined()));
1645 QCOMPARE(o.error(), false);
1646 QCOMPARE(o.invoked(), 9);
1647 QCOMPARE(o.actuals().count(), 2);
1648 QCOMPARE(o.actuals().at(0), QVariant(10));
1649 QCOMPARE(o.actuals().at(1), QVariant(11));
1651 // Test return types
1653 QVERIFY(EVALUATE_VALUE("object.method_NoArgs()", v8::Undefined()));
1654 QCOMPARE(o.error(), false);
1655 QCOMPARE(o.invoked(), 0);
1656 QCOMPARE(o.actuals().count(), 0);
1659 QVERIFY(EVALUATE_VALUE("object.method_NoArgs_int()", v8::Integer::New(6)));
1660 QCOMPARE(o.error(), false);
1661 QCOMPARE(o.invoked(), 1);
1662 QCOMPARE(o.actuals().count(), 0);
1665 QVERIFY(EVALUATE_VALUE("object.method_NoArgs_real()", v8::Number::New(19.75)));
1666 QCOMPARE(o.error(), false);
1667 QCOMPARE(o.invoked(), 2);
1668 QCOMPARE(o.actuals().count(), 0);
1672 v8::Handle<v8::Value> ret = EVALUATE("object.method_NoArgs_QPointF()");
1673 QVERIFY(!ret.IsEmpty());
1674 QCOMPARE(engine->toVariant(ret, -1), QVariant(QPointF(123, 4.5)));
1675 QCOMPARE(o.error(), false);
1676 QCOMPARE(o.invoked(), 3);
1677 QCOMPARE(o.actuals().count(), 0);
1682 v8::Handle<v8::Value> ret = EVALUATE("object.method_NoArgs_QObject()");
1683 QCOMPARE(engine->toQObject(ret), (QObject *)&o);
1684 QCOMPARE(o.error(), false);
1685 QCOMPARE(o.invoked(), 4);
1686 QCOMPARE(o.actuals().count(), 0);
1690 QVERIFY(EVALUATE_VALUE("object.method_NoArgs_unknown()", v8::Undefined()));
1691 QCOMPARE(o.error(), false);
1692 QCOMPARE(o.invoked(), 5);
1693 QCOMPARE(o.actuals().count(), 0);
1697 v8::Handle<v8::Value> ret = EVALUATE("object.method_NoArgs_QScriptValue()");
1698 QVERIFY(ret->IsString());
1699 QCOMPARE(engine->toString(ret), QString("Hello world"));
1700 QCOMPARE(o.error(), false);
1701 QCOMPARE(o.invoked(), 6);
1702 QCOMPARE(o.actuals().count(), 0);
1706 QVERIFY(EVALUATE_VALUE("object.method_NoArgs_QVariant()", engine->toString("QML rocks")));
1707 QCOMPARE(o.error(), false);
1708 QCOMPARE(o.invoked(), 7);
1709 QCOMPARE(o.actuals().count(), 0);
1713 QVERIFY(EVALUATE_VALUE("object.method_int(94)", v8::Undefined()));
1714 QCOMPARE(o.error(), false);
1715 QCOMPARE(o.invoked(), 8);
1716 QCOMPARE(o.actuals().count(), 1);
1717 QCOMPARE(o.actuals().at(0), QVariant(94));
1720 QVERIFY(EVALUATE_VALUE("object.method_int(\"94\")", v8::Undefined()));
1721 QCOMPARE(o.error(), false);
1722 QCOMPARE(o.invoked(), 8);
1723 QCOMPARE(o.actuals().count(), 1);
1724 QCOMPARE(o.actuals().at(0), QVariant(94));
1727 QVERIFY(EVALUATE_VALUE("object.method_int(\"not a number\")", v8::Undefined()));
1728 QCOMPARE(o.error(), false);
1729 QCOMPARE(o.invoked(), 8);
1730 QCOMPARE(o.actuals().count(), 1);
1731 QCOMPARE(o.actuals().at(0), QVariant(0));
1734 QVERIFY(EVALUATE_VALUE("object.method_int(null)", v8::Undefined()));
1735 QCOMPARE(o.error(), false);
1736 QCOMPARE(o.invoked(), 8);
1737 QCOMPARE(o.actuals().count(), 1);
1738 QCOMPARE(o.actuals().at(0), QVariant(0));
1741 QVERIFY(EVALUATE_VALUE("object.method_int(undefined)", v8::Undefined()));
1742 QCOMPARE(o.error(), false);
1743 QCOMPARE(o.invoked(), 8);
1744 QCOMPARE(o.actuals().count(), 1);
1745 QCOMPARE(o.actuals().at(0), QVariant(0));
1748 QVERIFY(EVALUATE_VALUE("object.method_int(object)", v8::Undefined()));
1749 QCOMPARE(o.error(), false);
1750 QCOMPARE(o.invoked(), 8);
1751 QCOMPARE(o.actuals().count(), 1);
1752 QCOMPARE(o.actuals().at(0), QVariant(0));
1755 QVERIFY(EVALUATE_VALUE("object.method_intint(122, 9)", v8::Undefined()));
1756 QCOMPARE(o.error(), false);
1757 QCOMPARE(o.invoked(), 9);
1758 QCOMPARE(o.actuals().count(), 2);
1759 QCOMPARE(o.actuals().at(0), QVariant(122));
1760 QCOMPARE(o.actuals().at(1), QVariant(9));
1763 QVERIFY(EVALUATE_VALUE("object.method_real(94.3)", v8::Undefined()));
1764 QCOMPARE(o.error(), false);
1765 QCOMPARE(o.invoked(), 10);
1766 QCOMPARE(o.actuals().count(), 1);
1767 QCOMPARE(o.actuals().at(0), QVariant(94.3));
1770 QVERIFY(EVALUATE_VALUE("object.method_real(\"94.3\")", v8::Undefined()));
1771 QCOMPARE(o.error(), false);
1772 QCOMPARE(o.invoked(), 10);
1773 QCOMPARE(o.actuals().count(), 1);
1774 QCOMPARE(o.actuals().at(0), QVariant(94.3));
1777 QVERIFY(EVALUATE_VALUE("object.method_real(\"not a number\")", v8::Undefined()));
1778 QCOMPARE(o.error(), false);
1779 QCOMPARE(o.invoked(), 10);
1780 QCOMPARE(o.actuals().count(), 1);
1781 QVERIFY(qIsNaN(o.actuals().at(0).toDouble()));
1784 QVERIFY(EVALUATE_VALUE("object.method_real(null)", v8::Undefined()));
1785 QCOMPARE(o.error(), false);
1786 QCOMPARE(o.invoked(), 10);
1787 QCOMPARE(o.actuals().count(), 1);
1788 QCOMPARE(o.actuals().at(0), QVariant(0));
1791 QVERIFY(EVALUATE_VALUE("object.method_real(undefined)", v8::Undefined()));
1792 QCOMPARE(o.error(), false);
1793 QCOMPARE(o.invoked(), 10);
1794 QCOMPARE(o.actuals().count(), 1);
1795 QVERIFY(qIsNaN(o.actuals().at(0).toDouble()));
1798 QVERIFY(EVALUATE_VALUE("object.method_real(object)", v8::Undefined()));
1799 QCOMPARE(o.error(), false);
1800 QCOMPARE(o.invoked(), 10);
1801 QCOMPARE(o.actuals().count(), 1);
1802 QVERIFY(qIsNaN(o.actuals().at(0).toDouble()));
1805 QVERIFY(EVALUATE_VALUE("object.method_QString(\"Hello world\")", v8::Undefined()));
1806 QCOMPARE(o.error(), false);
1807 QCOMPARE(o.invoked(), 11);
1808 QCOMPARE(o.actuals().count(), 1);
1809 QCOMPARE(o.actuals().at(0), QVariant("Hello world"));
1812 QVERIFY(EVALUATE_VALUE("object.method_QString(19)", v8::Undefined()));
1813 QCOMPARE(o.error(), false);
1814 QCOMPARE(o.invoked(), 11);
1815 QCOMPARE(o.actuals().count(), 1);
1816 QCOMPARE(o.actuals().at(0), QVariant("19"));
1820 QString expected = "MyInvokableObject(0x" + QString::number((quintptr)&o, 16) + ")";
1821 QVERIFY(EVALUATE_VALUE("object.method_QString(object)", v8::Undefined()));
1822 QCOMPARE(o.error(), false);
1823 QCOMPARE(o.invoked(), 11);
1824 QCOMPARE(o.actuals().count(), 1);
1825 QCOMPARE(o.actuals().at(0), QVariant(expected));
1829 QVERIFY(EVALUATE_VALUE("object.method_QString(null)", v8::Undefined()));
1830 QCOMPARE(o.error(), false);
1831 QCOMPARE(o.invoked(), 11);
1832 QCOMPARE(o.actuals().count(), 1);
1833 QCOMPARE(o.actuals().at(0), QVariant(QString()));
1836 QVERIFY(EVALUATE_VALUE("object.method_QString(undefined)", v8::Undefined()));
1837 QCOMPARE(o.error(), false);
1838 QCOMPARE(o.invoked(), 11);
1839 QCOMPARE(o.actuals().count(), 1);
1840 QCOMPARE(o.actuals().at(0), QVariant(QString()));
1843 QVERIFY(EVALUATE_VALUE("object.method_QPointF(0)", v8::Undefined()));
1844 QCOMPARE(o.error(), false);
1845 QCOMPARE(o.invoked(), 12);
1846 QCOMPARE(o.actuals().count(), 1);
1847 QCOMPARE(o.actuals().at(0), QVariant(QPointF()));
1850 QVERIFY(EVALUATE_VALUE("object.method_QPointF(null)", v8::Undefined()));
1851 QCOMPARE(o.error(), false);
1852 QCOMPARE(o.invoked(), 12);
1853 QCOMPARE(o.actuals().count(), 1);
1854 QCOMPARE(o.actuals().at(0), QVariant(QPointF()));
1857 QVERIFY(EVALUATE_VALUE("object.method_QPointF(undefined)", v8::Undefined()));
1858 QCOMPARE(o.error(), false);
1859 QCOMPARE(o.invoked(), 12);
1860 QCOMPARE(o.actuals().count(), 1);
1861 QCOMPARE(o.actuals().at(0), QVariant(QPointF()));
1864 QVERIFY(EVALUATE_VALUE("object.method_QPointF(object)", v8::Undefined()));
1865 QCOMPARE(o.error(), false);
1866 QCOMPARE(o.invoked(), 12);
1867 QCOMPARE(o.actuals().count(), 1);
1868 QCOMPARE(o.actuals().at(0), QVariant(QPointF()));
1871 QVERIFY(EVALUATE_VALUE("object.method_QPointF(object.method_get_QPointF())", v8::Undefined()));
1872 QCOMPARE(o.error(), false);
1873 QCOMPARE(o.invoked(), 12);
1874 QCOMPARE(o.actuals().count(), 1);
1875 QCOMPARE(o.actuals().at(0), QVariant(QPointF(99.3, -10.2)));
1878 QVERIFY(EVALUATE_VALUE("object.method_QPointF(object.method_get_QPoint())", v8::Undefined()));
1879 QCOMPARE(o.error(), false);
1880 QCOMPARE(o.invoked(), 12);
1881 QCOMPARE(o.actuals().count(), 1);
1882 QCOMPARE(o.actuals().at(0), QVariant(QPointF(9, 12)));
1885 QVERIFY(EVALUATE_VALUE("object.method_QObject(0)", v8::Undefined()));
1886 QCOMPARE(o.error(), false);
1887 QCOMPARE(o.invoked(), 13);
1888 QCOMPARE(o.actuals().count(), 1);
1889 QCOMPARE(o.actuals().at(0), qVariantFromValue((QObject *)0));
1892 QVERIFY(EVALUATE_VALUE("object.method_QObject(\"Hello world\")", v8::Undefined()));
1893 QCOMPARE(o.error(), false);
1894 QCOMPARE(o.invoked(), 13);
1895 QCOMPARE(o.actuals().count(), 1);
1896 QCOMPARE(o.actuals().at(0), qVariantFromValue((QObject *)0));
1899 QVERIFY(EVALUATE_VALUE("object.method_QObject(null)", v8::Undefined()));
1900 QCOMPARE(o.error(), false);
1901 QCOMPARE(o.invoked(), 13);
1902 QCOMPARE(o.actuals().count(), 1);
1903 QCOMPARE(o.actuals().at(0), qVariantFromValue((QObject *)0));
1906 QVERIFY(EVALUATE_VALUE("object.method_QObject(undefined)", v8::Undefined()));
1907 QCOMPARE(o.error(), false);
1908 QCOMPARE(o.invoked(), 13);
1909 QCOMPARE(o.actuals().count(), 1);
1910 QCOMPARE(o.actuals().at(0), qVariantFromValue((QObject *)0));
1913 QVERIFY(EVALUATE_VALUE("object.method_QObject(object)", v8::Undefined()));
1914 QCOMPARE(o.error(), false);
1915 QCOMPARE(o.invoked(), 13);
1916 QCOMPARE(o.actuals().count(), 1);
1917 QCOMPARE(o.actuals().at(0), qVariantFromValue((QObject *)&o));
1920 QVERIFY(EVALUATE_VALUE("object.method_QScriptValue(null)", v8::Undefined()));
1921 QCOMPARE(o.error(), false);
1922 QCOMPARE(o.invoked(), 14);
1923 QCOMPARE(o.actuals().count(), 1);
1924 QVERIFY(qvariant_cast<QJSValue>(o.actuals().at(0)).isNull());
1927 QVERIFY(EVALUATE_VALUE("object.method_QScriptValue(undefined)", v8::Undefined()));
1928 QCOMPARE(o.error(), false);
1929 QCOMPARE(o.invoked(), 14);
1930 QCOMPARE(o.actuals().count(), 1);
1931 QVERIFY(qvariant_cast<QJSValue>(o.actuals().at(0)).isUndefined());
1934 QVERIFY(EVALUATE_VALUE("object.method_QScriptValue(19)", v8::Undefined()));
1935 QCOMPARE(o.error(), false);
1936 QCOMPARE(o.invoked(), 14);
1937 QCOMPARE(o.actuals().count(), 1);
1938 QVERIFY(qvariant_cast<QJSValue>(o.actuals().at(0)).strictlyEquals(QJSValue(19)));
1941 QVERIFY(EVALUATE_VALUE("object.method_QScriptValue([19, 20])", v8::Undefined()));
1942 QCOMPARE(o.error(), false);
1943 QCOMPARE(o.invoked(), 14);
1944 QCOMPARE(o.actuals().count(), 1);
1945 QVERIFY(qvariant_cast<QJSValue>(o.actuals().at(0)).isArray());
1948 QVERIFY(EVALUATE_VALUE("object.method_intQScriptValue(4, null)", v8::Undefined()));
1949 QCOMPARE(o.error(), false);
1950 QCOMPARE(o.invoked(), 15);
1951 QCOMPARE(o.actuals().count(), 2);
1952 QCOMPARE(o.actuals().at(0), QVariant(4));
1953 QVERIFY(qvariant_cast<QJSValue>(o.actuals().at(1)).isNull());
1956 QVERIFY(EVALUATE_VALUE("object.method_intQScriptValue(8, undefined)", v8::Undefined()));
1957 QCOMPARE(o.error(), false);
1958 QCOMPARE(o.invoked(), 15);
1959 QCOMPARE(o.actuals().count(), 2);
1960 QCOMPARE(o.actuals().at(0), QVariant(8));
1961 QVERIFY(qvariant_cast<QJSValue>(o.actuals().at(1)).isUndefined());
1964 QVERIFY(EVALUATE_VALUE("object.method_intQScriptValue(3, 19)", v8::Undefined()));
1965 QCOMPARE(o.error(), false);
1966 QCOMPARE(o.invoked(), 15);
1967 QCOMPARE(o.actuals().count(), 2);
1968 QCOMPARE(o.actuals().at(0), QVariant(3));
1969 QVERIFY(qvariant_cast<QJSValue>(o.actuals().at(1)).strictlyEquals(QJSValue(19)));
1972 QVERIFY(EVALUATE_VALUE("object.method_intQScriptValue(44, [19, 20])", v8::Undefined()));
1973 QCOMPARE(o.error(), false);
1974 QCOMPARE(o.invoked(), 15);
1975 QCOMPARE(o.actuals().count(), 2);
1976 QCOMPARE(o.actuals().at(0), QVariant(44));
1977 QVERIFY(qvariant_cast<QJSValue>(o.actuals().at(1)).isArray());
1980 QVERIFY(EVALUATE_ERROR("object.method_overload()"));
1981 QCOMPARE(o.error(), false);
1982 QCOMPARE(o.invoked(), -1);
1983 QCOMPARE(o.actuals().count(), 0);
1986 QVERIFY(EVALUATE_VALUE("object.method_overload(10)", v8::Undefined()));
1987 QCOMPARE(o.error(), false);
1988 QCOMPARE(o.invoked(), 16);
1989 QCOMPARE(o.actuals().count(), 1);
1990 QCOMPARE(o.actuals().at(0), QVariant(10));
1993 QVERIFY(EVALUATE_VALUE("object.method_overload(10, 11)", v8::Undefined()));
1994 QCOMPARE(o.error(), false);
1995 QCOMPARE(o.invoked(), 17);
1996 QCOMPARE(o.actuals().count(), 2);
1997 QCOMPARE(o.actuals().at(0), QVariant(10));
1998 QCOMPARE(o.actuals().at(1), QVariant(11));
2001 QVERIFY(EVALUATE_VALUE("object.method_overload(\"Hello\")", v8::Undefined()));
2002 QCOMPARE(o.error(), false);
2003 QCOMPARE(o.invoked(), 18);
2004 QCOMPARE(o.actuals().count(), 1);
2005 QCOMPARE(o.actuals().at(0), QVariant(QString("Hello")));
2008 QVERIFY(EVALUATE_VALUE("object.method_with_enum(9)", v8::Undefined()));
2009 QCOMPARE(o.error(), false);
2010 QCOMPARE(o.invoked(), 19);
2011 QCOMPARE(o.actuals().count(), 1);
2012 QCOMPARE(o.actuals().at(0), QVariant(9));
2015 QVERIFY(EVALUATE_VALUE("object.method_default(10)", v8::Integer::New(19)));
2016 QCOMPARE(o.error(), false);
2017 QCOMPARE(o.invoked(), 20);
2018 QCOMPARE(o.actuals().count(), 2);
2019 QCOMPARE(o.actuals().at(0), QVariant(10));
2020 QCOMPARE(o.actuals().at(1), QVariant(19));
2023 QVERIFY(EVALUATE_VALUE("object.method_default(10, 13)", v8::Integer::New(13)));
2024 QCOMPARE(o.error(), false);
2025 QCOMPARE(o.invoked(), 20);
2026 QCOMPARE(o.actuals().count(), 2);
2027 QCOMPARE(o.actuals().at(0), QVariant(10));
2028 QCOMPARE(o.actuals().at(1), QVariant(13));
2031 QVERIFY(EVALUATE_VALUE("object.method_inherited(9)", v8::Undefined()));
2032 QCOMPARE(o.error(), false);
2033 QCOMPARE(o.invoked(), -3);
2034 QCOMPARE(o.actuals().count(), 1);
2035 QCOMPARE(o.actuals().at(0), QVariant(9));
2038 QVERIFY(EVALUATE_VALUE("object.method_QVariant(9)", v8::Undefined()));
2039 QCOMPARE(o.error(), false);
2040 QCOMPARE(o.invoked(), 21);
2041 QCOMPARE(o.actuals().count(), 2);
2042 QCOMPARE(o.actuals().at(0), QVariant(9));
2043 QCOMPARE(o.actuals().at(1), QVariant());
2046 QVERIFY(EVALUATE_VALUE("object.method_QVariant(\"Hello\", \"World\")", v8::Undefined()));
2047 QCOMPARE(o.error(), false);
2048 QCOMPARE(o.invoked(), 21);
2049 QCOMPARE(o.actuals().count(), 2);
2050 QCOMPARE(o.actuals().at(0), QVariant(QString("Hello")));
2051 QCOMPARE(o.actuals().at(1), QVariant(QString("World")));
2054 // QTBUG-13047 (check that you can pass registered object types as args)
2055 void tst_qdeclarativeecmascript::invokableObjectArg()
2057 QDeclarativeComponent component(&engine, TEST_FILE("invokableObjectArg.qml"));
2059 QObject *o = component.create();
2061 MyQmlObject *qmlobject = qobject_cast<MyQmlObject *>(o);
2063 QCOMPARE(qmlobject->myinvokableObject, qmlobject);
2068 // QTBUG-13047 (check that you can return registered object types from methods)
2069 void tst_qdeclarativeecmascript::invokableObjectRet()
2071 QDeclarativeComponent component(&engine, TEST_FILE("invokableObjectRet.qml"));
2073 QObject *o = component.create();
2075 QCOMPARE(o->property("test").toBool(), true);
2080 void tst_qdeclarativeecmascript::listToVariant()
2082 QDeclarativeComponent component(&engine, TEST_FILE("listToVariant.qml"));
2084 MyQmlContainer container;
2086 QDeclarativeContext context(engine.rootContext());
2087 context.setContextObject(&container);
2089 QObject *object = component.create(&context);
2090 QVERIFY(object != 0);
2092 QVariant v = object->property("test");
2093 QCOMPARE(v.userType(), qMetaTypeId<QDeclarativeListReference>());
2094 QVERIFY(qvariant_cast<QDeclarativeListReference>(v).object() == &container);
2100 void tst_qdeclarativeecmascript::multiEngineObject()
2103 obj.setStringProperty("Howdy planet");
2105 QDeclarativeEngine e1;
2106 e1.rootContext()->setContextProperty("thing", &obj);
2107 QDeclarativeComponent c1(&e1, TEST_FILE("multiEngineObject.qml"));
2109 QDeclarativeEngine e2;
2110 e2.rootContext()->setContextProperty("thing", &obj);
2111 QDeclarativeComponent c2(&e2, TEST_FILE("multiEngineObject.qml"));
2113 QObject *o1 = c1.create();
2114 QObject *o2 = c2.create();
2116 QCOMPARE(o1->property("test").toString(), QString("Howdy planet"));
2117 QCOMPARE(o2->property("test").toString(), QString("Howdy planet"));
2123 // Test that references to QObjects are cleanup when the object is destroyed
2124 void tst_qdeclarativeecmascript::deletedObject()
2126 QDeclarativeComponent component(&engine, TEST_FILE("deletedObject.qml"));
2128 QObject *object = component.create();
2130 QCOMPARE(object->property("test1").toBool(), true);
2131 QCOMPARE(object->property("test2").toBool(), true);
2132 QCOMPARE(object->property("test3").toBool(), true);
2133 QCOMPARE(object->property("test4").toBool(), true);
2138 void tst_qdeclarativeecmascript::attachedPropertyScope()
2140 QDeclarativeComponent component(&engine, TEST_FILE("attachedPropertyScope.qml"));
2142 QObject *object = component.create();
2143 QVERIFY(object != 0);
2145 MyQmlAttachedObject *attached =
2146 qobject_cast<MyQmlAttachedObject *>(qmlAttachedPropertiesObject<MyQmlObject>(object));
2147 QVERIFY(attached != 0);
2149 QCOMPARE(object->property("value2").toInt(), 0);
2151 attached->emitMySignal();
2153 QCOMPARE(object->property("value2").toInt(), 9);
2158 void tst_qdeclarativeecmascript::scriptConnect()
2161 QDeclarativeComponent component(&engine, TEST_FILE("scriptConnect.1.qml"));
2163 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2164 QVERIFY(object != 0);
2166 QCOMPARE(object->property("test").toBool(), false);
2167 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2168 QCOMPARE(object->property("test").toBool(), true);
2174 QDeclarativeComponent component(&engine, TEST_FILE("scriptConnect.2.qml"));
2176 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2177 QVERIFY(object != 0);
2179 QCOMPARE(object->property("test").toBool(), false);
2180 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2181 QCOMPARE(object->property("test").toBool(), true);
2187 QDeclarativeComponent component(&engine, TEST_FILE("scriptConnect.3.qml"));
2189 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2190 QVERIFY(object != 0);
2192 QCOMPARE(object->property("test").toBool(), false);
2193 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2194 QCOMPARE(object->property("test").toBool(), true);
2200 QDeclarativeComponent component(&engine, TEST_FILE("scriptConnect.4.qml"));
2202 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2203 QVERIFY(object != 0);
2205 QCOMPARE(object->methodCalled(), false);
2206 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2207 QCOMPARE(object->methodCalled(), true);
2213 QDeclarativeComponent component(&engine, TEST_FILE("scriptConnect.5.qml"));
2215 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2216 QVERIFY(object != 0);
2218 QCOMPARE(object->methodCalled(), false);
2219 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2220 QCOMPARE(object->methodCalled(), true);
2226 QDeclarativeComponent component(&engine, TEST_FILE("scriptConnect.6.qml"));
2228 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2229 QVERIFY(object != 0);
2231 QCOMPARE(object->property("test").toInt(), 0);
2232 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2233 QCOMPARE(object->property("test").toInt(), 2);
2239 void tst_qdeclarativeecmascript::scriptDisconnect()
2242 QDeclarativeComponent component(&engine, TEST_FILE("scriptDisconnect.1.qml"));
2244 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2245 QVERIFY(object != 0);
2247 QCOMPARE(object->property("test").toInt(), 0);
2248 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2249 QCOMPARE(object->property("test").toInt(), 1);
2250 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2251 QCOMPARE(object->property("test").toInt(), 2);
2252 emit object->basicSignal();
2253 QCOMPARE(object->property("test").toInt(), 2);
2254 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2255 QCOMPARE(object->property("test").toInt(), 2);
2261 QDeclarativeComponent component(&engine, TEST_FILE("scriptDisconnect.2.qml"));
2263 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2264 QVERIFY(object != 0);
2266 QCOMPARE(object->property("test").toInt(), 0);
2267 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2268 QCOMPARE(object->property("test").toInt(), 1);
2269 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2270 QCOMPARE(object->property("test").toInt(), 2);
2271 emit object->basicSignal();
2272 QCOMPARE(object->property("test").toInt(), 2);
2273 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2274 QCOMPARE(object->property("test").toInt(), 2);
2280 QDeclarativeComponent component(&engine, TEST_FILE("scriptDisconnect.3.qml"));
2282 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2283 QVERIFY(object != 0);
2285 QCOMPARE(object->property("test").toInt(), 0);
2286 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2287 QCOMPARE(object->property("test").toInt(), 1);
2288 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2289 QCOMPARE(object->property("test").toInt(), 2);
2290 emit object->basicSignal();
2291 QCOMPARE(object->property("test").toInt(), 2);
2292 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2293 QCOMPARE(object->property("test").toInt(), 3);
2298 QDeclarativeComponent component(&engine, TEST_FILE("scriptDisconnect.4.qml"));
2300 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2301 QVERIFY(object != 0);
2303 QCOMPARE(object->property("test").toInt(), 0);
2304 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2305 QCOMPARE(object->property("test").toInt(), 1);
2306 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2307 QCOMPARE(object->property("test").toInt(), 2);
2308 emit object->basicSignal();
2309 QCOMPARE(object->property("test").toInt(), 2);
2310 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2311 QCOMPARE(object->property("test").toInt(), 3);
2317 class OwnershipObject : public QObject
2321 OwnershipObject() { object = new QObject; }
2323 QPointer<QObject> object;
2326 QObject *getObject() { return object; }
2329 void tst_qdeclarativeecmascript::ownership()
2331 OwnershipObject own;
2332 QDeclarativeContext *context = new QDeclarativeContext(engine.rootContext());
2333 context->setContextObject(&own);
2336 QDeclarativeComponent component(&engine, TEST_FILE("ownership.qml"));
2338 QVERIFY(own.object != 0);
2340 QObject *object = component.create(context);
2342 engine.collectGarbage();
2344 QCoreApplication::processEvents(QEventLoop::DeferredDeletion);
2346 QVERIFY(own.object == 0);
2351 own.object = new QObject(&own);
2354 QDeclarativeComponent component(&engine, TEST_FILE("ownership.qml"));
2356 QVERIFY(own.object != 0);
2358 QObject *object = component.create(context);
2360 engine.collectGarbage();
2362 QCoreApplication::processEvents(QEventLoop::DeferredDeletion);
2364 QVERIFY(own.object != 0);
2372 class CppOwnershipReturnValue : public QObject
2376 CppOwnershipReturnValue() : value(0) {}
2377 ~CppOwnershipReturnValue() { delete value; }
2379 Q_INVOKABLE QObject *create() {
2380 value = new QObject;
2381 QDeclarativeEngine::setObjectOwnership(value, QDeclarativeEngine::CppOwnership);
2385 Q_INVOKABLE MyQmlObject *createQmlObject() {
2386 MyQmlObject *rv = new MyQmlObject;
2391 QPointer<QObject> value;
2395 // Test setObjectOwnership(CppOwnership) works even when there is no QDeclarativeData
2396 void tst_qdeclarativeecmascript::cppOwnershipReturnValue()
2398 CppOwnershipReturnValue source;
2401 QDeclarativeEngine engine;
2402 engine.rootContext()->setContextProperty("source", &source);
2404 QVERIFY(source.value == 0);
2406 QDeclarativeComponent component(&engine);
2407 component.setData("import QtQuick 1.0\nQtObject {\nComponent.onCompleted: { var a = source.create(); }\n}\n", QUrl());
2409 QObject *object = component.create();
2411 QVERIFY(object != 0);
2412 QVERIFY(source.value != 0);
2417 QCoreApplication::instance()->processEvents(QEventLoop::DeferredDeletion);
2419 QVERIFY(source.value != 0);
2423 void tst_qdeclarativeecmascript::ownershipCustomReturnValue()
2425 CppOwnershipReturnValue source;
2428 QDeclarativeEngine engine;
2429 engine.rootContext()->setContextProperty("source", &source);
2431 QVERIFY(source.value == 0);
2433 QDeclarativeComponent component(&engine);
2434 component.setData("import QtQuick 1.0\nQtObject {\nComponent.onCompleted: { var a = source.createQmlObject(); }\n}\n", QUrl());
2436 QObject *object = component.create();
2438 QVERIFY(object != 0);
2439 QVERIFY(source.value != 0);
2444 engine.collectGarbage();
2445 QCoreApplication::instance()->processEvents(QEventLoop::DeferredDeletion);
2447 QVERIFY(source.value == 0);
2450 class QListQObjectMethodsObject : public QObject
2454 QListQObjectMethodsObject() {
2455 m_objects.append(new MyQmlObject());
2456 m_objects.append(new MyQmlObject());
2459 ~QListQObjectMethodsObject() {
2460 qDeleteAll(m_objects);
2464 QList<QObject *> getObjects() { return m_objects; }
2467 QList<QObject *> m_objects;
2470 // Tests that returning a QList<QObject*> from a method works
2471 void tst_qdeclarativeecmascript::qlistqobjectMethods()
2473 QListQObjectMethodsObject obj;
2474 QDeclarativeContext *context = new QDeclarativeContext(engine.rootContext());
2475 context->setContextObject(&obj);
2477 QDeclarativeComponent component(&engine, TEST_FILE("qlistqobjectMethods.qml"));
2479 QObject *object = component.create(context);
2481 QCOMPARE(object->property("test").toInt(), 2);
2482 QCOMPARE(object->property("test2").toBool(), true);
2489 void tst_qdeclarativeecmascript::strictlyEquals()
2491 QDeclarativeComponent component(&engine, TEST_FILE("strictlyEquals.qml"));
2493 QObject *object = component.create();
2494 QVERIFY(object != 0);
2496 QCOMPARE(object->property("test1").toBool(), true);
2497 QCOMPARE(object->property("test2").toBool(), true);
2498 QCOMPARE(object->property("test3").toBool(), true);
2499 QCOMPARE(object->property("test4").toBool(), true);
2500 QCOMPARE(object->property("test5").toBool(), true);
2501 QCOMPARE(object->property("test6").toBool(), true);
2502 QCOMPARE(object->property("test7").toBool(), true);
2503 QCOMPARE(object->property("test8").toBool(), true);
2508 void tst_qdeclarativeecmascript::compiled()
2510 QDeclarativeComponent component(&engine, TEST_FILE("compiled.qml"));
2512 QObject *object = component.create();
2513 QVERIFY(object != 0);
2515 QCOMPARE(object->property("test1").toReal(), qreal(15.7));
2516 QCOMPARE(object->property("test2").toReal(), qreal(-6.7));
2517 QCOMPARE(object->property("test3").toBool(), true);
2518 QCOMPARE(object->property("test4").toBool(), false);
2519 QCOMPARE(object->property("test5").toBool(), false);
2520 QCOMPARE(object->property("test6").toBool(), true);
2522 QCOMPARE(object->property("test7").toInt(), 185);
2523 QCOMPARE(object->property("test8").toInt(), 167);
2524 QCOMPARE(object->property("test9").toBool(), true);
2525 QCOMPARE(object->property("test10").toBool(), false);
2526 QCOMPARE(object->property("test11").toBool(), false);
2527 QCOMPARE(object->property("test12").toBool(), true);
2529 QCOMPARE(object->property("test13").toString(), QLatin1String("HelloWorld"));
2530 QCOMPARE(object->property("test14").toString(), QLatin1String("Hello World"));
2531 QCOMPARE(object->property("test15").toBool(), false);
2532 QCOMPARE(object->property("test16").toBool(), true);
2534 QCOMPARE(object->property("test17").toInt(), 5);
2535 QCOMPARE(object->property("test18").toReal(), qreal(176));
2536 QCOMPARE(object->property("test19").toInt(), 7);
2537 QCOMPARE(object->property("test20").toReal(), qreal(6.7));
2538 QCOMPARE(object->property("test21").toString(), QLatin1String("6.7"));
2539 QCOMPARE(object->property("test22").toString(), QLatin1String("!"));
2540 QCOMPARE(object->property("test23").toBool(), true);
2541 QCOMPARE(qvariant_cast<QColor>(object->property("test24")), QColor(0x11,0x22,0x33));
2542 QCOMPARE(qvariant_cast<QColor>(object->property("test25")), QColor(0x11,0x22,0x33,0xAA));
2547 // Test that numbers assigned in bindings as strings work consistently
2548 void tst_qdeclarativeecmascript::numberAssignment()
2550 QDeclarativeComponent component(&engine, TEST_FILE("numberAssignment.qml"));
2552 QObject *object = component.create();
2553 QVERIFY(object != 0);
2555 QCOMPARE(object->property("test1"), QVariant((qreal)6.7));
2556 QCOMPARE(object->property("test2"), QVariant((qreal)6.7));
2557 QCOMPARE(object->property("test2"), QVariant((qreal)6.7));
2558 QCOMPARE(object->property("test3"), QVariant((qreal)6));
2559 QCOMPARE(object->property("test4"), QVariant((qreal)6));
2561 QCOMPARE(object->property("test5"), QVariant((int)7));
2562 QCOMPARE(object->property("test6"), QVariant((int)7));
2563 QCOMPARE(object->property("test7"), QVariant((int)6));
2564 QCOMPARE(object->property("test8"), QVariant((int)6));
2566 QCOMPARE(object->property("test9"), QVariant((unsigned int)7));
2567 QCOMPARE(object->property("test10"), QVariant((unsigned int)7));
2568 QCOMPARE(object->property("test11"), QVariant((unsigned int)6));
2569 QCOMPARE(object->property("test12"), QVariant((unsigned int)6));
2574 void tst_qdeclarativeecmascript::propertySplicing()
2576 QDeclarativeComponent component(&engine, TEST_FILE("propertySplicing.qml"));
2578 QObject *object = component.create();
2579 QVERIFY(object != 0);
2581 QCOMPARE(object->property("test").toBool(), true);
2587 void tst_qdeclarativeecmascript::signalWithUnknownTypes()
2589 QDeclarativeComponent component(&engine, TEST_FILE("signalWithUnknownTypes.qml"));
2591 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2592 QVERIFY(object != 0);
2594 MyQmlObject::MyType type;
2595 type.value = 0x8971123;
2596 emit object->signalWithUnknownType(type);
2598 MyQmlObject::MyType result = qvariant_cast<MyQmlObject::MyType>(object->variant());
2600 QCOMPARE(result.value, type.value);
2606 void tst_qdeclarativeecmascript::moduleApi()
2608 QDeclarativeComponent component(&engine, TEST_FILE("moduleApi.qml"));
2609 QObject *object = component.create();
2610 QVERIFY(object != 0);
2611 QCOMPARE(object->property("existingUriTest").toInt(), 20);
2613 QEXPECT_FAIL("", "QTBUG-17318", Continue);
2614 QCOMPARE(object->property("scriptTest").toInt(), 13);
2615 QCOMPARE(object->property("qobjectTest").toInt(), 20);
2616 QCOMPARE(object->property("qobjectMethodTest").toInt(), 1); // first call of method, so count = 1.
2617 QCOMPARE(object->property("qobjectMinorVersionTest").toInt(), 20);
2618 QCOMPARE(object->property("qobjectMajorVersionTest").toInt(), 20);
2619 QCOMPARE(object->property("qobjectParentedTest").toInt(), 26);
2622 // test that caching of module apis works correctly.
2623 QDeclarativeComponent componentTwo(&engine, TEST_FILE("moduleApiCaching.qml"));
2624 object = componentTwo.create();
2625 QVERIFY(object != 0);
2626 QCOMPARE(object->property("existingUriTest").toInt(), 20);
2627 QEXPECT_FAIL("", "QTBUG-17318", Continue);
2628 QCOMPARE(object->property("scriptTest").toInt(), 13); // shouldn't have incremented.
2629 QCOMPARE(object->property("qobjectParentedTest").toInt(), 26); // shouldn't have incremented.
2632 // test that writing to a property of module apis works correctly.
2633 QDeclarativeComponent componentThree(&engine, TEST_FILE("moduleApiWriting.qml"));
2634 QString expectedWarning = QLatin1String("file://") + TEST_FILE("moduleApiWriting.qml").toLocalFile() + QLatin1String(":15: Error: Cannot assign to read-only property \"qobjectTestProperty\"");
2635 QTest::ignoreMessage(QtWarningMsg, expectedWarning.toAscii().constData());
2636 object = componentThree.create();
2637 QVERIFY(object != 0);
2638 QCOMPARE(object->property("readOnlyProperty").toInt(), 20);
2639 QCOMPARE(object->property("writableProperty").toInt(), 50);
2640 QVERIFY(object->setProperty("firstProperty", QVariant(30))); // shouldn't affect value of readOnlyProperty
2641 QVERIFY(object->setProperty("writableProperty", QVariant(30))); // SHOULD affect value of writableProperty
2642 QCOMPARE(object->property("readOnlyProperty").toInt(), 20);
2643 QCOMPARE(object->property("writableProperty").toInt(), 30);
2646 QDeclarativeComponent failOne(&engine, TEST_FILE("moduleApiMajorVersionFail.qml"));
2647 QTest::ignoreMessage(QtWarningMsg, "QDeclarativeComponent: Component is not ready");
2648 object = failOne.create();
2649 QVERIFY(object == 0); // should have failed: invalid major version
2651 QDeclarativeComponent failTwo(&engine, TEST_FILE("moduleApiMinorVersionFail.qml"));
2652 QTest::ignoreMessage(QtWarningMsg, "QDeclarativeComponent: Component is not ready");
2653 object = failTwo.create();
2654 QVERIFY(object == 0); // should have failed: invalid minor version
2657 void tst_qdeclarativeecmascript::importScripts()
2659 QObject *object = 0;
2661 // first, ensure that the required behaviour works.
2662 QDeclarativeComponent component(&engine, TEST_FILE("jsimport/testImport.qml"));
2663 object = component.create();
2664 QVERIFY(object != 0);
2665 QCOMPARE(object->property("importedScriptStringValue"), QVariant(QString(QLatin1String("Hello, World!"))));
2666 QCOMPARE(object->property("importedScriptFunctionValue"), QVariant(20));
2667 QCOMPARE(object->property("importedModuleAttachedPropertyValue"), QVariant(19));
2668 QCOMPARE(object->property("importedModuleEnumValue"), QVariant(2));
2671 QDeclarativeComponent componentTwo(&engine, TEST_FILE("jsimport/testImportScoping.qml"));
2672 object = componentTwo.create();
2673 QVERIFY(object != 0);
2674 QCOMPARE(object->property("componentError"), QVariant(5));
2677 // then, ensure that unintended behaviour does not work.
2678 QDeclarativeComponent failOneComponent(&engine, TEST_FILE("jsimportfail/failOne.qml"));
2679 QString expectedWarning = QLatin1String("file://") + TEST_FILE("jsimportfail/failOne.qml").toLocalFile() + QLatin1String(":6: TypeError: Cannot call method 'greetingString' of undefined");
2680 QTest::ignoreMessage(QtWarningMsg, expectedWarning.toAscii().constData());
2681 object = failOneComponent.create();
2682 QVERIFY(object != 0);
2683 QVERIFY(object->property("importScriptFunctionValue").toString().isEmpty());
2685 QDeclarativeComponent failTwoComponent(&engine, TEST_FILE("jsimportfail/failTwo.qml"));
2686 expectedWarning = QLatin1String("file://") + TEST_FILE("jsimportfail/failTwo.qml").toLocalFile() + QLatin1String(":6: ReferenceError: Can't find variable: ImportOneJs");
2687 QTest::ignoreMessage(QtWarningMsg, expectedWarning.toAscii().constData());
2688 object = failTwoComponent.create();
2689 QVERIFY(object != 0);
2690 QVERIFY(object->property("importScriptFunctionValue").toString().isEmpty());
2692 QDeclarativeComponent failThreeComponent(&engine, TEST_FILE("jsimportfail/failThree.qml"));
2693 expectedWarning = QLatin1String("file://") + TEST_FILE("jsimportfail/failThree.qml").toLocalFile() + QLatin1String(":7: TypeError: Cannot read property 'JsQtTest' of undefined");
2694 QTest::ignoreMessage(QtWarningMsg, expectedWarning.toAscii().constData());
2695 object = failThreeComponent.create();
2696 QVERIFY(object != 0);
2697 QCOMPARE(object->property("importedModuleAttachedPropertyValue"), QVariant(false));
2699 QDeclarativeComponent failFourComponent(&engine, TEST_FILE("jsimportfail/failFour.qml"));
2700 expectedWarning = QLatin1String("file://") + TEST_FILE("jsimportfail/failFour.qml").toLocalFile() + QLatin1String(":6: ReferenceError: Can't find variable: JsQtTest");
2701 QTest::ignoreMessage(QtWarningMsg, expectedWarning.toAscii().constData());
2702 object = failFourComponent.create();
2703 QVERIFY(object != 0);
2704 QCOMPARE(object->property("importedModuleEnumValue"), QVariant(0));
2706 QDeclarativeComponent failFiveComponent(&engine, TEST_FILE("jsimportfail/failFive.qml"));
2707 expectedWarning = QLatin1String("file://") + TEST_FILE("jsimportfail/importWithImports.js").toLocalFile() + QLatin1String(":8: ReferenceError: Can't find variable: Component");
2708 QTest::ignoreMessage(QtWarningMsg, expectedWarning.toAscii().constData());
2709 expectedWarning = QLatin1String("file://") + TEST_FILE("jsimportfail/importPragmaLibrary.js").toLocalFile() + QLatin1String(":6: ReferenceError: Can't find variable: Component");
2710 QTest::ignoreMessage(QtWarningMsg, expectedWarning.toAscii().constData());
2711 object = failFiveComponent.create();
2712 QVERIFY(object != 0);
2713 QCOMPARE(object->property("componentError"), QVariant(0));
2716 // also, test that importing scripts with .pragma library works as required
2717 QDeclarativeComponent pragmaLibraryComponent(&engine, TEST_FILE("jsimport/testImportPragmaLibrary.qml"));
2718 object = pragmaLibraryComponent.create();
2719 QVERIFY(object != 0);
2720 QCOMPARE(object->property("testValue"), QVariant(31));
2723 // and that .pragma library scripts don't inherit imports from any .qml file
2724 QDeclarativeComponent pragmaLibraryComponentTwo(&engine, TEST_FILE("jsimportfail/testImportPragmaLibrary.qml"));
2725 object = pragmaLibraryComponentTwo.create();
2726 QVERIFY(object != 0);
2727 QCOMPARE(object->property("testValue"), QVariant(0));
2731 void tst_qdeclarativeecmascript::scarceResources()
2733 QPixmap origPixmap(100, 100);
2734 origPixmap.fill(Qt::blue);
2736 QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(&engine);
2737 ScarceResourceObject *eo = 0;
2738 QObject *object = 0;
2740 // in the following three cases, the instance created from the component
2741 // has a property which is a copy of the scarce resource; hence, the
2742 // resource should NOT be detached prior to deletion of the object instance,
2743 // unless the resource is destroyed explicitly.
2744 QDeclarativeComponent component(&engine, TEST_FILE("scarceresources/scarceResourceCopy.qml"));
2745 object = component.create();
2746 QVERIFY(object != 0);
2747 QVERIFY(object->property("scarceResourceCopy").isValid());
2748 QCOMPARE(object->property("scarceResourceCopy").value<QPixmap>(), origPixmap);
2749 QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
2750 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2751 QVERIFY(!eo->scarceResourceIsDetached()); // there are two copies of it in existence: the property of object, and the property of eo.
2754 QDeclarativeComponent componentTwo(&engine, TEST_FILE("scarceresources/scarceResourceCopyFromJs.qml"));
2755 object = componentTwo.create();
2756 QVERIFY(object != 0);
2757 QVERIFY(object->property("scarceResourceCopy").isValid());
2758 QCOMPARE(object->property("scarceResourceCopy").value<QPixmap>(), origPixmap);
2759 QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
2760 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2761 QVERIFY(!eo->scarceResourceIsDetached()); // there are two copies of it in existence: the property of object, and the property of eo.
2764 QDeclarativeComponent componentThree(&engine, TEST_FILE("scarceresources/scarceResourceDestroyedCopy.qml"));
2765 object = componentThree.create();
2766 QVERIFY(object != 0);
2767 QVERIFY(!(object->property("scarceResourceCopy").isValid())); // was manually released prior to being returned.
2768 QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
2769 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2770 QVERIFY(eo->scarceResourceIsDetached()); // should have explicitly been released during the evaluation of the binding.
2773 // in the following three cases, no other copy should exist in memory,
2774 // and so it should be detached (unless explicitly preserved).
2775 QDeclarativeComponent componentFour(&engine, TEST_FILE("scarceresources/scarceResourceTest.qml"));
2776 object = componentFour.create();
2777 QVERIFY(object != 0);
2778 QVERIFY(object->property("scarceResourceTest").isValid());
2779 QCOMPARE(object->property("scarceResourceTest").toInt(), 100);
2780 QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
2781 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2782 QVERIFY(eo->scarceResourceIsDetached()); // the resource should have been released after the binding was evaluated.
2785 QDeclarativeComponent componentFive(&engine, TEST_FILE("scarceresources/scarceResourceTestPreserve.qml"));
2786 object = componentFive.create();
2787 QVERIFY(object != 0);
2788 QVERIFY(object->property("scarceResourceTest").isValid());
2789 QCOMPARE(object->property("scarceResourceTest").toInt(), 100);
2790 QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
2791 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2792 QVERIFY(!eo->scarceResourceIsDetached()); // this won't be detached since we explicitly preserved it.
2795 QDeclarativeComponent componentSix(&engine, TEST_FILE("scarceresources/scarceResourceTestMultiple.qml"));
2796 object = componentSix.create();
2797 QVERIFY(object != 0);
2798 QVERIFY(object->property("scarceResourceTest").isValid());
2799 QCOMPARE(object->property("scarceResourceTest").toInt(), 100);
2800 QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
2801 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2802 QVERIFY(eo->scarceResourceIsDetached()); // all resources were released manually or automatically released.
2805 // test that scarce resources are handled correctly for imports
2806 QDeclarativeComponent componentSeven(&engine, TEST_FILE("scarceresources/scarceResourceCopyImportNoBinding.qml"));
2807 object = componentSeven.create();
2808 QVERIFY(object != 0); // the import should have caused the addition of a resource to the ScarceResources list
2809 QVERIFY(ep->scarceResources.isEmpty()); // but they should have been released by this point.
2812 QDeclarativeComponent componentEight(&engine, TEST_FILE("scarceresources/scarceResourceCopyImportFail.qml"));
2813 object = componentEight.create();
2814 QVERIFY(object != 0);
2815 QVERIFY(!object->property("scarceResourceCopy").isValid()); // wasn't preserved, so shouldn't be valid.
2816 QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
2819 QDeclarativeComponent componentNine(&engine, TEST_FILE("scarceresources/scarceResourceCopyImport.qml"));
2820 object = componentNine.create();
2821 QVERIFY(object != 0);
2822 QVERIFY(object->property("scarceResourceCopy").isValid()); // preserved, so should be valid.
2823 QCOMPARE(object->property("scarceResourceCopy").value<QPixmap>(), origPixmap);
2824 QVERIFY(object->property("scarceResourceAssignedCopyOne").isValid()); // assigned before destroy(), so should be valid.
2825 QCOMPARE(object->property("scarceResourceAssignedCopyOne").value<QPixmap>(), origPixmap);
2826 QVERIFY(!object->property("scarceResourceAssignedCopyTwo").isValid()); // assigned after destroy(), so should be invalid.
2827 QVERIFY(ep->scarceResources.isEmpty()); // this will still be zero, because "preserve()" REMOVES it from this list.
2830 // test that scarce resources are handled properly in signal invocation
2831 QDeclarativeComponent componentTen(&engine, TEST_FILE("scarceresources/scarceResourceSignal.qml"));
2832 object = componentTen.create();
2833 QVERIFY(object != 0);
2834 QObject *srsc = object->findChild<QObject*>("srsc");
2836 QVERIFY(!srsc->property("scarceResourceCopy").isValid()); // hasn't been instantiated yet.
2837 QCOMPARE(srsc->property("width"), QVariant(5)); // default value is 5.
2838 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2839 QVERIFY(eo->scarceResourceIsDetached()); // should be no other copies of it at this stage.
2840 QMetaObject::invokeMethod(srsc, "testSignal");
2841 QVERIFY(!srsc->property("scarceResourceCopy").isValid()); // still hasn't been instantiated
2842 QCOMPARE(srsc->property("width"), QVariant(10)); // but width was assigned to 10.
2843 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2844 QVERIFY(eo->scarceResourceIsDetached()); // should still be no other copies of it at this stage.
2845 QMetaObject::invokeMethod(srsc, "testSignal2"); // assigns scarceResourceCopy to the scarce pixmap.
2846 QVERIFY(srsc->property("scarceResourceCopy").isValid());
2847 QCOMPARE(srsc->property("scarceResourceCopy").value<QPixmap>(), origPixmap);
2848 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2849 QVERIFY(!(eo->scarceResourceIsDetached())); // should be another copy of the resource now.
2850 QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
2853 // test that scarce resources are handled properly from js functions in qml files
2854 QDeclarativeComponent componentEleven(&engine, TEST_FILE("scarceresources/scarceResourceFunction.qml"));
2855 object = componentEleven.create();
2856 QVERIFY(object != 0);
2857 QVERIFY(!object->property("scarceResourceCopy").isValid()); // not yet assigned, so should not be valid
2858 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2859 QVERIFY(eo->scarceResourceIsDetached()); // should be no other copies of it at this stage.
2860 QMetaObject::invokeMethod(object, "retrieveScarceResource");
2861 QVERIFY(object->property("scarceResourceCopy").isValid()); // assigned, so should be valid.
2862 QCOMPARE(object->property("scarceResourceCopy").value<QPixmap>(), origPixmap);
2863 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2864 QVERIFY(!eo->scarceResourceIsDetached()); // should be a copy of the resource at this stage.
2865 QMetaObject::invokeMethod(object, "releaseScarceResource");
2866 QVERIFY(!object->property("scarceResourceCopy").isValid()); // just released, so should not be valid
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.
2872 // test that if an exception occurs while invoking js function from cpp, that the resources are released.
2873 QDeclarativeComponent componentTwelve(&engine, TEST_FILE("scarceresources/scarceResourceFunctionFail.qml"));
2874 object = componentTwelve.create();
2875 QVERIFY(object != 0);
2876 QVERIFY(!object->property("scarceResourceCopy").isValid()); // not yet assigned, so should not be valid
2877 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2878 QVERIFY(eo->scarceResourceIsDetached()); // should be no other copies of it at this stage.
2879 QString srp_name = object->property("srp_name").toString();
2880 QString expectedWarning = componentTwelve.url().toString() + QLatin1String(":17: TypeError: Property 'scarceResource' of object ") + srp_name + QLatin1String(" is not a function");
2881 QTest::ignoreMessage(QtWarningMsg, qPrintable(expectedWarning)); // we expect a meaningful warning to be printed.
2882 QMetaObject::invokeMethod(object, "retrieveScarceResource");
2883 QVERIFY(!object->property("scarceResourceCopy").isValid()); // due to exception, assignment will NOT have occurred.
2884 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2885 QVERIFY(eo->scarceResourceIsDetached()); // should be no other copies of it at this stage.
2886 QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
2890 void tst_qdeclarativeecmascript::propertyChangeSlots()
2892 // ensure that allowable property names are allowed and onPropertyNameChanged slots are generated correctly.
2893 QDeclarativeComponent component(&engine, TEST_FILE("changeslots/propertyChangeSlots.qml"));
2894 QObject *object = component.create();
2895 QVERIFY(object != 0);
2898 // ensure that invalid property names fail properly.
2899 QTest::ignoreMessage(QtWarningMsg, "QDeclarativeComponent: Component is not ready");
2900 QDeclarativeComponent e1(&engine, TEST_FILE("changeslots/propertyChangeSlotErrors.1.qml"));
2901 QString expectedErrorString = e1.url().toString() + QLatin1String(":9:5: Cannot assign to non-existent property \"on_nameWithUnderscoreChanged\"");
2902 QCOMPARE(e1.errors().at(0).toString(), expectedErrorString);
2903 object = e1.create();
2904 QVERIFY(object == 0);
2907 QTest::ignoreMessage(QtWarningMsg, "QDeclarativeComponent: Component is not ready");
2908 QDeclarativeComponent e2(&engine, TEST_FILE("changeslots/propertyChangeSlotErrors.2.qml"));
2909 expectedErrorString = e2.url().toString() + QLatin1String(":9:5: Cannot assign to non-existent property \"on____nameWithUnderscoresChanged\"");
2910 QCOMPARE(e2.errors().at(0).toString(), expectedErrorString);
2911 object = e2.create();
2912 QVERIFY(object == 0);
2915 QTest::ignoreMessage(QtWarningMsg, "QDeclarativeComponent: Component is not ready");
2916 QDeclarativeComponent e3(&engine, TEST_FILE("changeslots/propertyChangeSlotErrors.3.qml"));
2917 expectedErrorString = e3.url().toString() + QLatin1String(":9:5: Cannot assign to non-existent property \"on$NameWithDollarsignChanged\"");
2918 QCOMPARE(e3.errors().at(0).toString(), expectedErrorString);
2919 object = e3.create();
2920 QVERIFY(object == 0);
2923 QTest::ignoreMessage(QtWarningMsg, "QDeclarativeComponent: Component is not ready");
2924 QDeclarativeComponent e4(&engine, TEST_FILE("changeslots/propertyChangeSlotErrors.4.qml"));
2925 expectedErrorString = e4.url().toString() + QLatin1String(":9:5: Cannot assign to non-existent property \"on_6NameWithUnderscoreNumberChanged\"");
2926 QCOMPARE(e4.errors().at(0).toString(), expectedErrorString);
2927 object = e4.create();
2928 QVERIFY(object == 0);
2932 // Ensure that QObject type conversion works on binding assignment
2933 void tst_qdeclarativeecmascript::elementAssign()
2935 QDeclarativeComponent component(&engine, TEST_FILE("elementAssign.qml"));
2937 QObject *object = component.create();
2938 QVERIFY(object != 0);
2940 QCOMPARE(object->property("test").toBool(), true);
2946 void tst_qdeclarativeecmascript::objectPassThroughSignals()
2948 QDeclarativeComponent component(&engine, TEST_FILE("objectsPassThroughSignals.qml"));
2950 QObject *object = component.create();
2951 QVERIFY(object != 0);
2953 QCOMPARE(object->property("test").toBool(), true);
2959 void tst_qdeclarativeecmascript::booleanConversion()
2961 QDeclarativeComponent component(&engine, TEST_FILE("booleanConversion.qml"));
2963 QObject *object = component.create();
2964 QVERIFY(object != 0);
2966 QCOMPARE(object->property("test_true1").toBool(), true);
2967 QCOMPARE(object->property("test_true2").toBool(), true);
2968 QCOMPARE(object->property("test_true3").toBool(), true);
2969 QCOMPARE(object->property("test_true4").toBool(), true);
2970 QCOMPARE(object->property("test_true5").toBool(), true);
2972 QCOMPARE(object->property("test_false1").toBool(), false);
2973 QCOMPARE(object->property("test_false2").toBool(), false);
2974 QCOMPARE(object->property("test_false3").toBool(), false);
2979 // Test that assigning a null object works
2980 // Regressed with: df1788b4dbbb2826ae63f26bdf166342595343f4
2981 void tst_qdeclarativeecmascript::nullObjectBinding()
2983 QDeclarativeComponent component(&engine, TEST_FILE("nullObjectBinding.qml"));
2985 QObject *object = component.create();
2986 QVERIFY(object != 0);
2988 QVERIFY(object->property("test") == QVariant::fromValue((QObject *)0));
2993 // Test that bindings don't evaluate once the engine has been destroyed
2994 void tst_qdeclarativeecmascript::deletedEngine()
2996 QDeclarativeEngine *engine = new QDeclarativeEngine;
2997 QDeclarativeComponent component(engine, TEST_FILE("deletedEngine.qml"));
2999 QObject *object = component.create();
3000 QVERIFY(object != 0);
3002 QCOMPARE(object->property("a").toInt(), 39);
3003 object->setProperty("b", QVariant(9));
3004 QCOMPARE(object->property("a").toInt(), 117);
3008 QCOMPARE(object->property("a").toInt(), 117);
3009 object->setProperty("b", QVariant(10));
3010 QCOMPARE(object->property("a").toInt(), 117);
3015 // Test the crashing part of QTBUG-9705
3016 void tst_qdeclarativeecmascript::libraryScriptAssert()
3018 QDeclarativeComponent component(&engine, TEST_FILE("libraryScriptAssert.qml"));
3020 QObject *object = component.create();
3021 QVERIFY(object != 0);
3026 void tst_qdeclarativeecmascript::variantsAssignedUndefined()
3028 QDeclarativeComponent component(&engine, TEST_FILE("variantsAssignedUndefined.qml"));
3030 QObject *object = component.create();
3031 QVERIFY(object != 0);
3033 QCOMPARE(object->property("test1").toInt(), 10);
3034 QCOMPARE(object->property("test2").toInt(), 11);
3036 object->setProperty("runTest", true);
3038 QCOMPARE(object->property("test1"), QVariant());
3039 QCOMPARE(object->property("test2"), QVariant());
3045 void tst_qdeclarativeecmascript::qtbug_9792()
3047 QDeclarativeComponent component(&engine, TEST_FILE("qtbug_9792.qml"));
3049 QDeclarativeContext *context = new QDeclarativeContext(engine.rootContext());
3051 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create(context));
3052 QVERIFY(object != 0);
3054 QTest::ignoreMessage(QtDebugMsg, "Hello world!");
3055 object->basicSignal();
3059 transientErrorsMsgCount = 0;
3060 QtMsgHandler old = qInstallMsgHandler(transientErrorsMsgHandler);
3062 object->basicSignal();
3064 qInstallMsgHandler(old);
3066 QCOMPARE(transientErrorsMsgCount, 0);
3071 // Verifies that QDeclarativeGuard<>s used in the vmemetaobject are cleaned correctly
3072 void tst_qdeclarativeecmascript::qtcreatorbug_1289()
3074 QDeclarativeComponent component(&engine, TEST_FILE("qtcreatorbug_1289.qml"));
3076 QObject *o = component.create();
3079 QObject *nested = qvariant_cast<QObject *>(o->property("object"));
3080 QVERIFY(nested != 0);
3082 QVERIFY(qvariant_cast<QObject *>(nested->property("nestedObject")) == o);
3085 nested = qvariant_cast<QObject *>(o->property("object"));
3086 QVERIFY(nested == 0);
3088 // If the bug is present, the next line will crash
3092 // Test that we shut down without stupid warnings
3093 void tst_qdeclarativeecmascript::noSpuriousWarningsAtShutdown()
3096 QDeclarativeComponent component(&engine, TEST_FILE("noSpuriousWarningsAtShutdown.qml"));
3098 QObject *o = component.create();
3100 transientErrorsMsgCount = 0;
3101 QtMsgHandler old = qInstallMsgHandler(transientErrorsMsgHandler);
3105 qInstallMsgHandler(old);
3107 QCOMPARE(transientErrorsMsgCount, 0);
3112 QDeclarativeComponent component(&engine, TEST_FILE("noSpuriousWarningsAtShutdown.2.qml"));
3114 QObject *o = component.create();
3116 transientErrorsMsgCount = 0;
3117 QtMsgHandler old = qInstallMsgHandler(transientErrorsMsgHandler);
3121 qInstallMsgHandler(old);
3123 QCOMPARE(transientErrorsMsgCount, 0);
3127 void tst_qdeclarativeecmascript::canAssignNullToQObject()
3130 QDeclarativeComponent component(&engine, TEST_FILE("canAssignNullToQObject.1.qml"));
3132 MyQmlObject *o = qobject_cast<MyQmlObject *>(component.create());
3135 QVERIFY(o->objectProperty() != 0);
3137 o->setProperty("runTest", true);
3139 QVERIFY(o->objectProperty() == 0);
3145 QDeclarativeComponent component(&engine, TEST_FILE("canAssignNullToQObject.2.qml"));
3147 MyQmlObject *o = qobject_cast<MyQmlObject *>(component.create());
3150 QVERIFY(o->objectProperty() == 0);
3156 void tst_qdeclarativeecmascript::functionAssignment_fromBinding()
3158 QDeclarativeComponent component(&engine, TEST_FILE("functionAssignment.1.qml"));
3160 QString url = component.url().toString();
3161 QString warning = url + ":4: Unable to assign a function to a property.";
3162 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
3164 MyQmlObject *o = qobject_cast<MyQmlObject *>(component.create());
3167 QVERIFY(!o->property("a").isValid());
3172 void tst_qdeclarativeecmascript::functionAssignment_fromJS()
3174 QFETCH(QString, triggerProperty);
3176 QDeclarativeComponent component(&engine, TEST_FILE("functionAssignment.2.qml"));
3177 QVERIFY2(component.errorString().isEmpty(), qPrintable(component.errorString()));
3179 MyQmlObject *o = qobject_cast<MyQmlObject *>(component.create());
3181 QVERIFY(!o->property("a").isValid());
3183 o->setProperty("aNumber", QVariant(5));
3184 o->setProperty(triggerProperty.toUtf8().constData(), true);
3185 QCOMPARE(o->property("a"), QVariant(50));
3187 o->setProperty("aNumber", QVariant(10));
3188 QCOMPARE(o->property("a"), QVariant(100));
3193 void tst_qdeclarativeecmascript::functionAssignment_fromJS_data()
3195 QTest::addColumn<QString>("triggerProperty");
3197 QTest::newRow("assign to property") << "assignToProperty";
3198 QTest::newRow("assign to property, from JS file") << "assignToPropertyFromJsFile";
3200 QTest::newRow("assign to value type") << "assignToValueType";
3202 QTest::newRow("use 'this'") << "assignWithThis";
3203 QTest::newRow("use 'this' from JS file") << "assignWithThisFromJsFile";
3206 void tst_qdeclarativeecmascript::functionAssignmentfromJS_invalid()
3208 QDeclarativeComponent component(&engine, TEST_FILE("functionAssignment.2.qml"));
3209 QVERIFY2(component.errorString().isEmpty(), qPrintable(component.errorString()));
3211 MyQmlObject *o = qobject_cast<MyQmlObject *>(component.create());
3213 QVERIFY(!o->property("a").isValid());
3215 o->setProperty("assignFuncWithoutReturn", true);
3216 QVERIFY(!o->property("a").isValid());
3218 QString url = component.url().toString();
3219 QString warning = url + ":67: Unable to assign QString to int";
3220 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
3221 o->setProperty("assignWrongType", true);
3223 warning = url + ":71: Unable to assign QString to int";
3224 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
3225 o->setProperty("assignWrongTypeToValueType", true);
3230 void tst_qdeclarativeecmascript::eval()
3232 QDeclarativeComponent component(&engine, TEST_FILE("eval.qml"));
3234 QObject *o = component.create();
3237 QCOMPARE(o->property("test1").toBool(), true);
3238 QCOMPARE(o->property("test2").toBool(), true);
3239 QCOMPARE(o->property("test3").toBool(), true);
3240 QCOMPARE(o->property("test4").toBool(), true);
3241 QCOMPARE(o->property("test5").toBool(), true);
3246 void tst_qdeclarativeecmascript::function()
3248 QDeclarativeComponent component(&engine, TEST_FILE("function.qml"));
3250 QObject *o = component.create();
3253 QCOMPARE(o->property("test1").toBool(), true);
3254 QCOMPARE(o->property("test2").toBool(), true);
3255 QCOMPARE(o->property("test3").toBool(), true);
3260 // Test the "Qt.include" method
3261 void tst_qdeclarativeecmascript::include()
3263 // Non-library relative include
3265 QDeclarativeComponent component(&engine, TEST_FILE("include.qml"));
3266 QObject *o = component.create();
3269 QCOMPARE(o->property("test0").toInt(), 99);
3270 QCOMPARE(o->property("test1").toBool(), true);
3271 QCOMPARE(o->property("test2").toBool(), true);
3272 QCOMPARE(o->property("test2_1").toBool(), true);
3273 QCOMPARE(o->property("test3").toBool(), true);
3274 QCOMPARE(o->property("test3_1").toBool(), true);
3279 // Library relative include
3281 QDeclarativeComponent component(&engine, TEST_FILE("include_shared.qml"));
3282 QObject *o = component.create();
3285 QCOMPARE(o->property("test0").toInt(), 99);
3286 QCOMPARE(o->property("test1").toBool(), true);
3287 QCOMPARE(o->property("test2").toBool(), true);
3288 QCOMPARE(o->property("test2_1").toBool(), true);
3289 QCOMPARE(o->property("test3").toBool(), true);
3290 QCOMPARE(o->property("test3_1").toBool(), true);
3297 QDeclarativeComponent component(&engine, TEST_FILE("include_callback.qml"));
3298 QObject *o = component.create();
3301 QCOMPARE(o->property("test1").toBool(), true);
3302 QCOMPARE(o->property("test2").toBool(), true);
3303 QCOMPARE(o->property("test3").toBool(), true);
3304 QCOMPARE(o->property("test4").toBool(), true);
3305 QCOMPARE(o->property("test5").toBool(), true);
3306 QCOMPARE(o->property("test6").toBool(), true);
3311 // Including file with ".pragma library"
3313 QDeclarativeComponent component(&engine, TEST_FILE("include_pragma.qml"));
3314 QObject *o = component.create();
3316 QCOMPARE(o->property("test1").toInt(), 100);
3323 TestHTTPServer server(8111);
3324 QVERIFY(server.isValid());
3325 server.serveDirectory(SRCDIR "/data");
3327 QDeclarativeComponent component(&engine, TEST_FILE("include_remote.qml"));
3328 QObject *o = component.create();
3331 QTRY_VERIFY(o->property("done").toBool() == true);
3332 QTRY_VERIFY(o->property("done2").toBool() == true);
3334 QCOMPARE(o->property("test1").toBool(), true);
3335 QCOMPARE(o->property("test2").toBool(), true);
3336 QCOMPARE(o->property("test3").toBool(), true);
3337 QCOMPARE(o->property("test4").toBool(), true);
3338 QCOMPARE(o->property("test5").toBool(), true);
3340 QCOMPARE(o->property("test6").toBool(), true);
3341 QCOMPARE(o->property("test7").toBool(), true);
3342 QCOMPARE(o->property("test8").toBool(), true);
3343 QCOMPARE(o->property("test9").toBool(), true);
3344 QCOMPARE(o->property("test10").toBool(), true);
3351 TestHTTPServer server(8111);
3352 QVERIFY(server.isValid());
3353 server.serveDirectory(SRCDIR "/data");
3355 QDeclarativeComponent component(&engine, TEST_FILE("include_remote_missing.qml"));
3356 QObject *o = component.create();
3359 QTRY_VERIFY(o->property("done").toBool() == true);
3361 QCOMPARE(o->property("test1").toBool(), true);
3362 QCOMPARE(o->property("test2").toBool(), true);
3363 QCOMPARE(o->property("test3").toBool(), true);
3369 void tst_qdeclarativeecmascript::qtbug_10696()
3371 QDeclarativeComponent component(&engine, TEST_FILE("qtbug_10696.qml"));
3372 QObject *o = component.create();
3377 void tst_qdeclarativeecmascript::qtbug_11606()
3379 QDeclarativeComponent component(&engine, TEST_FILE("qtbug_11606.qml"));
3380 QObject *o = component.create();
3382 QCOMPARE(o->property("test").toBool(), true);
3386 void tst_qdeclarativeecmascript::qtbug_11600()
3388 QDeclarativeComponent component(&engine, TEST_FILE("qtbug_11600.qml"));
3389 QObject *o = component.create();
3391 QCOMPARE(o->property("test").toBool(), true);
3395 // Reading and writing non-scriptable properties should fail
3396 void tst_qdeclarativeecmascript::nonscriptable()
3398 QDeclarativeComponent component(&engine, TEST_FILE("nonscriptable.qml"));
3399 QObject *o = component.create();
3401 QCOMPARE(o->property("readOk").toBool(), true);
3402 QCOMPARE(o->property("writeOk").toBool(), true);
3406 // deleteLater() should not be callable from QML
3407 void tst_qdeclarativeecmascript::deleteLater()
3409 QDeclarativeComponent component(&engine, TEST_FILE("deleteLater.qml"));
3410 QObject *o = component.create();
3412 QCOMPARE(o->property("test").toBool(), true);
3416 void tst_qdeclarativeecmascript::in()
3418 QDeclarativeComponent component(&engine, TEST_FILE("in.qml"));
3419 QObject *o = component.create();
3421 QCOMPARE(o->property("test1").toBool(), true);
3422 QCOMPARE(o->property("test2").toBool(), true);
3426 void tst_qdeclarativeecmascript::sharedAttachedObject()
3428 QDeclarativeComponent component(&engine, TEST_FILE("sharedAttachedObject.qml"));
3429 QObject *o = component.create();
3431 QCOMPARE(o->property("test1").toBool(), true);
3432 QCOMPARE(o->property("test2").toBool(), true);
3437 void tst_qdeclarativeecmascript::objectName()
3439 QDeclarativeComponent component(&engine, TEST_FILE("objectName.qml"));
3440 QObject *o = component.create();
3443 QCOMPARE(o->property("test1").toString(), QString("hello"));
3444 QCOMPARE(o->property("test2").toString(), QString("ell"));
3446 o->setObjectName("world");
3448 QCOMPARE(o->property("test1").toString(), QString("world"));
3449 QCOMPARE(o->property("test2").toString(), QString("orl"));
3454 void tst_qdeclarativeecmascript::writeRemovesBinding()
3456 QDeclarativeComponent component(&engine, TEST_FILE("writeRemovesBinding.qml"));
3457 QObject *o = component.create();
3460 QCOMPARE(o->property("test").toBool(), true);
3465 // Test bindings assigned to alias properties actually assign to the alias' target
3466 void tst_qdeclarativeecmascript::aliasBindingsAssignCorrectly()
3468 QDeclarativeComponent component(&engine, TEST_FILE("aliasBindingsAssignCorrectly.qml"));
3469 QObject *o = component.create();
3472 QCOMPARE(o->property("test").toBool(), true);
3477 // Test bindings assigned to alias properties override a binding on the target (QTBUG-13719)
3478 void tst_qdeclarativeecmascript::aliasBindingsOverrideTarget()
3481 QDeclarativeComponent component(&engine, TEST_FILE("aliasBindingsOverrideTarget.qml"));
3482 QObject *o = component.create();
3485 QCOMPARE(o->property("test").toBool(), true);
3491 QDeclarativeComponent component(&engine, TEST_FILE("aliasBindingsOverrideTarget.2.qml"));
3492 QObject *o = component.create();
3495 QCOMPARE(o->property("test").toBool(), true);
3501 QDeclarativeComponent component(&engine, TEST_FILE("aliasBindingsOverrideTarget.3.qml"));
3502 QObject *o = component.create();
3505 QCOMPARE(o->property("test").toBool(), true);
3511 // Test that writes to alias properties override bindings on the alias target (QTBUG-13719)
3512 void tst_qdeclarativeecmascript::aliasWritesOverrideBindings()
3515 QDeclarativeComponent component(&engine, TEST_FILE("aliasWritesOverrideBindings.qml"));
3516 QObject *o = component.create();
3519 QCOMPARE(o->property("test").toBool(), true);
3525 QDeclarativeComponent component(&engine, TEST_FILE("aliasWritesOverrideBindings.2.qml"));
3526 QObject *o = component.create();
3529 QCOMPARE(o->property("test").toBool(), true);
3535 QDeclarativeComponent component(&engine, TEST_FILE("aliasWritesOverrideBindings.3.qml"));
3536 QObject *o = component.create();
3539 QCOMPARE(o->property("test").toBool(), true);
3545 // Allow an alais to a composite element
3547 void tst_qdeclarativeecmascript::aliasToCompositeElement()
3549 QDeclarativeComponent component(&engine, TEST_FILE("aliasToCompositeElement.qml"));
3551 QObject *object = component.create();
3552 QVERIFY(object != 0);
3557 void tst_qdeclarativeecmascript::revisionErrors()
3560 QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevisionErrors.qml"));
3561 QString url = component.url().toString();
3563 QString warning1 = url + ":8: ReferenceError: Can't find variable: prop2";
3564 QString warning2 = url + ":11: ReferenceError: Can't find variable: prop2";
3565 QString warning3 = url + ":13: ReferenceError: Can't find variable: method2";
3567 QTest::ignoreMessage(QtWarningMsg, warning1.toLatin1().constData());
3568 QTest::ignoreMessage(QtWarningMsg, warning2.toLatin1().constData());
3569 QTest::ignoreMessage(QtWarningMsg, warning3.toLatin1().constData());
3570 MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create());
3571 QVERIFY(object != 0);
3575 QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevisionErrors2.qml"));
3576 QString url = component.url().toString();
3578 // MyRevisionedSubclass 1.0 uses MyRevisionedClass revision 0
3579 // method2, prop2 from MyRevisionedClass not available
3580 // method4, prop4 from MyRevisionedSubclass not available
3581 QString warning1 = url + ":8: ReferenceError: Can't find variable: prop2";
3582 QString warning2 = url + ":14: ReferenceError: Can't find variable: prop2";
3583 QString warning3 = url + ":10: ReferenceError: Can't find variable: prop4";
3584 QString warning4 = url + ":16: ReferenceError: Can't find variable: prop4";
3585 QString warning5 = url + ":20: ReferenceError: Can't find variable: method2";
3587 QTest::ignoreMessage(QtWarningMsg, warning1.toLatin1().constData());
3588 QTest::ignoreMessage(QtWarningMsg, warning2.toLatin1().constData());
3589 QTest::ignoreMessage(QtWarningMsg, warning3.toLatin1().constData());
3590 QTest::ignoreMessage(QtWarningMsg, warning4.toLatin1().constData());
3591 QTest::ignoreMessage(QtWarningMsg, warning5.toLatin1().constData());
3592 MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create());
3593 QVERIFY(object != 0);
3597 QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevisionErrors3.qml"));
3598 QString url = component.url().toString();
3600 // MyRevisionedSubclass 1.1 uses MyRevisionedClass revision 1
3601 // All properties/methods available, except MyRevisionedBaseClassUnregistered rev 1
3602 QString warning1 = url + ":30: ReferenceError: Can't find variable: methodD";
3603 QString warning2 = url + ":10: ReferenceError: Can't find variable: propD";
3604 QString warning3 = url + ":20: ReferenceError: Can't find variable: propD";
3605 QTest::ignoreMessage(QtWarningMsg, warning1.toLatin1().constData());
3606 QTest::ignoreMessage(QtWarningMsg, warning2.toLatin1().constData());
3607 QTest::ignoreMessage(QtWarningMsg, warning3.toLatin1().constData());
3608 MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create());
3609 QVERIFY(object != 0);
3614 void tst_qdeclarativeecmascript::revision()
3617 QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevision.qml"));
3618 QString url = component.url().toString();
3620 MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create());
3621 QVERIFY(object != 0);
3625 QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevision2.qml"));
3626 QString url = component.url().toString();
3628 MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create());
3629 QVERIFY(object != 0);
3633 QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevision3.qml"));
3634 QString url = component.url().toString();
3636 MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create());
3637 QVERIFY(object != 0);
3640 // Test that non-root classes can resolve revisioned methods
3642 QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevision4.qml"));
3644 QObject *object = component.create();
3645 QVERIFY(object != 0);
3646 QCOMPARE(object->property("test").toReal(), 11.);
3651 void tst_qdeclarativeecmascript::realToInt()
3653 QDeclarativeComponent component(&engine, TEST_FILE("realToInt.qml"));
3654 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
3655 QVERIFY(object != 0);
3657 QMetaObject::invokeMethod(object, "test1");
3658 QCOMPARE(object->value(), int(4));
3659 QMetaObject::invokeMethod(object, "test2");
3660 QCOMPARE(object->value(), int(8));
3662 void tst_qdeclarativeecmascript::dynamicString()
3664 QDeclarativeComponent component(&engine, TEST_FILE("dynamicString.qml"));
3665 QObject *object = component.create();
3666 QVERIFY(object != 0);
3667 QCOMPARE(object->property("stringProperty").toString(),
3668 QString::fromLatin1("string:Hello World false:0 true:1 uint32:100 int32:-100 double:3.14159 date:2011-02-11 05::30:50!"));
3671 QTEST_MAIN(tst_qdeclarativeecmascript)
3673 #include "tst_qdeclarativeecmascript.moc"