1 /****************************************************************************
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
7 ** This file is part of the test suite of the Qt Toolkit.
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** GNU Lesser General Public License Usage
11 ** This file may be used under the terms of the GNU Lesser General Public
12 ** License version 2.1 as published by the Free Software Foundation and
13 ** appearing in the file LICENSE.LGPL included in the packaging of this
14 ** file. Please review the following information to ensure the GNU Lesser
15 ** General Public License version 2.1 requirements will be met:
16 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
18 ** In addition, as a special exception, Nokia gives you certain additional
19 ** rights. These rights are described in the Nokia Qt LGPL Exception
20 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
22 ** GNU General Public License Usage
23 ** Alternatively, this file may be used under the terms of the GNU General
24 ** Public License version 3.0 as published by the Free Software Foundation
25 ** and appearing in the file LICENSE.GPL included in the packaging of this
26 ** file. Please review the following information to ensure the GNU General
27 ** Public License version 3.0 requirements will be met:
28 ** http://www.gnu.org/copyleft/gpl.html.
31 ** Alternatively, this file may be used in accordance with the terms and
32 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
42 #include <QtDeclarative/qdeclarativecomponent.h>
43 #include <QtDeclarative/qdeclarativeengine.h>
44 #include <QtDeclarative/qdeclarativeexpression.h>
45 #include <QtDeclarative/qdeclarativecontext.h>
46 #include <QtCore/qfileinfo.h>
47 #include <QtCore/qdebug.h>
48 #include <QtDeclarative/private/qdeclarativeguard_p.h>
49 #include <QtCore/qdir.h>
50 #include <QtCore/qnumeric.h>
51 #include <private/qdeclarativeengine_p.h>
52 #include <private/qscriptdeclarativeclass_p.h>
53 #include "testtypes.h"
54 #include "testhttpserver.h"
55 #include "../../../shared/util.h"
58 // In Symbian OS test data is located in applications private dir
63 This test covers evaluation of ECMAScript expressions and bindings from within
64 QML. This does not include static QML language issues.
66 Static QML language issues are covered in qmllanguage
68 inline QUrl TEST_FILE(const QString &filename)
70 QFileInfo fileInfo(__FILE__);
71 return QUrl::fromLocalFile(fileInfo.absoluteDir().filePath("data/" + filename));
74 inline QUrl TEST_FILE(const char *filename)
76 return TEST_FILE(QLatin1String(filename));
79 class tst_qdeclarativeecmascript : public QObject
83 tst_qdeclarativeecmascript() {}
87 void assignBasicTypes();
88 void idShortcutInvalidates();
89 void boolPropertiesEvaluateAsBool();
91 void signalAssignment();
93 void basicExpressions();
94 void basicExpressions_data();
95 void arrayExpressions();
96 void contextPropertiesTriggerReeval();
97 void objectPropertiesTriggerReeval();
98 void deferredProperties();
99 void deferredPropertiesErrors();
100 void extensionObjects();
101 void overrideExtensionProperties();
102 void attachedProperties();
104 void valueTypeFunctions();
105 void constantsOverrideBindings();
106 void outerBindingOverridesInnerBinding();
107 void aliasPropertyAndBinding();
108 void nonExistentAttachedObject();
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();
153 void dynamicCreationCrash();
155 void nullObjectBinding();
156 void deletedEngine();
157 void libraryScriptAssert();
158 void variantsAssignedUndefined();
160 void qtcreatorbug_1289();
161 void noSpuriousWarningsAtShutdown();
162 void canAssignNullToQObject();
163 void functionAssignment_fromBinding();
164 void functionAssignment_fromJS();
165 void functionAssignment_fromJS_data();
166 void functionAssignmentfromJS_invalid();
172 void nonscriptable();
175 void sharedAttachedObject();
177 void writeRemovesBinding();
178 void aliasBindingsAssignCorrectly();
179 void aliasBindingsOverrideTarget();
180 void aliasWritesOverrideBindings();
185 void callQtInvokables();
186 void invokableObjectArg();
187 void invokableObjectRet();
189 void revisionErrors();
192 QDeclarativeEngine engine;
195 void tst_qdeclarativeecmascript::initTestCase() { registerTypes(); }
197 void tst_qdeclarativeecmascript::assignBasicTypes()
200 QDeclarativeComponent component(&engine, TEST_FILE("assignBasicTypes.qml"));
201 MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
202 QVERIFY(object != 0);
203 QCOMPARE(object->flagProperty(), MyTypeObject::FlagVal1 | MyTypeObject::FlagVal3);
204 QCOMPARE(object->enumProperty(), MyTypeObject::EnumVal2);
205 QCOMPARE(object->stringProperty(), QString("Hello World!"));
206 QCOMPARE(object->uintProperty(), uint(10));
207 QCOMPARE(object->intProperty(), -19);
208 QCOMPARE((float)object->realProperty(), float(23.2));
209 QCOMPARE((float)object->doubleProperty(), float(-19.75));
210 QCOMPARE((float)object->floatProperty(), float(8.5));
211 QCOMPARE(object->colorProperty(), QColor("red"));
212 QCOMPARE(object->dateProperty(), QDate(1982, 11, 25));
213 QCOMPARE(object->timeProperty(), QTime(11, 11, 32));
214 QCOMPARE(object->dateTimeProperty(), QDateTime(QDate(2009, 5, 12), QTime(13, 22, 1)));
215 QCOMPARE(object->pointProperty(), QPoint(99,13));
216 QCOMPARE(object->pointFProperty(), QPointF(-10.1, 12.3));
217 QCOMPARE(object->sizeProperty(), QSize(99, 13));
218 QCOMPARE(object->sizeFProperty(), QSizeF(0.1, 0.2));
219 QCOMPARE(object->rectProperty(), QRect(9, 7, 100, 200));
220 QCOMPARE(object->rectFProperty(), QRectF(1000.1, -10.9, 400, 90.99));
221 QCOMPARE(object->boolProperty(), true);
222 QCOMPARE(object->variantProperty(), QVariant("Hello World!"));
223 QCOMPARE(object->vectorProperty(), QVector3D(10, 1, 2.2));
224 QCOMPARE(object->urlProperty(), component.url().resolved(QUrl("main.qml")));
228 QDeclarativeComponent component(&engine, TEST_FILE("assignBasicTypes.2.qml"));
229 MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
230 QVERIFY(object != 0);
231 QCOMPARE(object->flagProperty(), MyTypeObject::FlagVal1 | MyTypeObject::FlagVal3);
232 QCOMPARE(object->enumProperty(), MyTypeObject::EnumVal2);
233 QCOMPARE(object->stringProperty(), QString("Hello World!"));
234 QCOMPARE(object->uintProperty(), uint(10));
235 QCOMPARE(object->intProperty(), -19);
236 QCOMPARE((float)object->realProperty(), float(23.2));
237 QCOMPARE((float)object->doubleProperty(), float(-19.75));
238 QCOMPARE((float)object->floatProperty(), float(8.5));
239 QCOMPARE(object->colorProperty(), QColor("red"));
240 QCOMPARE(object->dateProperty(), QDate(1982, 11, 25));
241 QCOMPARE(object->timeProperty(), QTime(11, 11, 32));
242 QCOMPARE(object->dateTimeProperty(), QDateTime(QDate(2009, 5, 12), QTime(13, 22, 1)));
243 QCOMPARE(object->pointProperty(), QPoint(99,13));
244 QCOMPARE(object->pointFProperty(), QPointF(-10.1, 12.3));
245 QCOMPARE(object->sizeProperty(), QSize(99, 13));
246 QCOMPARE(object->sizeFProperty(), QSizeF(0.1, 0.2));
247 QCOMPARE(object->rectProperty(), QRect(9, 7, 100, 200));
248 QCOMPARE(object->rectFProperty(), QRectF(1000.1, -10.9, 400, 90.99));
249 QCOMPARE(object->boolProperty(), true);
250 QCOMPARE(object->variantProperty(), QVariant("Hello World!"));
251 QCOMPARE(object->vectorProperty(), QVector3D(10, 1, 2.2));
252 QCOMPARE(object->urlProperty(), component.url().resolved(QUrl("main.qml")));
257 void tst_qdeclarativeecmascript::idShortcutInvalidates()
260 QDeclarativeComponent component(&engine, TEST_FILE("idShortcutInvalidates.qml"));
261 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
262 QVERIFY(object != 0);
263 QVERIFY(object->objectProperty() != 0);
264 delete object->objectProperty();
265 QVERIFY(object->objectProperty() == 0);
270 QDeclarativeComponent component(&engine, TEST_FILE("idShortcutInvalidates.1.qml"));
271 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
272 QVERIFY(object != 0);
273 QVERIFY(object->objectProperty() != 0);
274 delete object->objectProperty();
275 QVERIFY(object->objectProperty() == 0);
280 void tst_qdeclarativeecmascript::boolPropertiesEvaluateAsBool()
283 QDeclarativeComponent component(&engine, TEST_FILE("boolPropertiesEvaluateAsBool.1.qml"));
284 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
285 QVERIFY(object != 0);
286 QCOMPARE(object->stringProperty(), QLatin1String("pass"));
290 QDeclarativeComponent component(&engine, TEST_FILE("boolPropertiesEvaluateAsBool.2.qml"));
291 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
292 QVERIFY(object != 0);
293 QCOMPARE(object->stringProperty(), QLatin1String("pass"));
298 void tst_qdeclarativeecmascript::signalAssignment()
301 QDeclarativeComponent component(&engine, TEST_FILE("signalAssignment.1.qml"));
302 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
303 QVERIFY(object != 0);
304 QCOMPARE(object->string(), QString());
305 emit object->basicSignal();
306 QCOMPARE(object->string(), QString("pass"));
311 QDeclarativeComponent component(&engine, TEST_FILE("signalAssignment.2.qml"));
312 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
313 QVERIFY(object != 0);
314 QCOMPARE(object->string(), QString());
315 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
316 QCOMPARE(object->string(), QString("pass 19 Hello world! 10.25 3 2"));
321 void tst_qdeclarativeecmascript::methods()
324 QDeclarativeComponent component(&engine, TEST_FILE("methods.1.qml"));
325 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
326 QVERIFY(object != 0);
327 QCOMPARE(object->methodCalled(), false);
328 QCOMPARE(object->methodIntCalled(), false);
329 emit object->basicSignal();
330 QCOMPARE(object->methodCalled(), true);
331 QCOMPARE(object->methodIntCalled(), false);
336 QDeclarativeComponent component(&engine, TEST_FILE("methods.2.qml"));
337 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
338 QVERIFY(object != 0);
339 QCOMPARE(object->methodCalled(), false);
340 QCOMPARE(object->methodIntCalled(), false);
341 emit object->basicSignal();
342 QCOMPARE(object->methodCalled(), false);
343 QCOMPARE(object->methodIntCalled(), true);
348 QDeclarativeComponent component(&engine, TEST_FILE("methods.3.qml"));
349 QObject *object = component.create();
350 QVERIFY(object != 0);
351 QCOMPARE(object->property("test").toInt(), 19);
356 QDeclarativeComponent component(&engine, TEST_FILE("methods.4.qml"));
357 QObject *object = component.create();
358 QVERIFY(object != 0);
359 QCOMPARE(object->property("test").toInt(), 19);
360 QCOMPARE(object->property("test2").toInt(), 17);
361 QCOMPARE(object->property("test3").toInt(), 16);
366 QDeclarativeComponent component(&engine, TEST_FILE("methods.5.qml"));
367 QObject *object = component.create();
368 QVERIFY(object != 0);
369 QCOMPARE(object->property("test").toInt(), 9);
374 void tst_qdeclarativeecmascript::bindingLoop()
376 QDeclarativeComponent component(&engine, TEST_FILE("bindingLoop.qml"));
377 QString warning = component.url().toString() + ":9:9: QML MyQmlObject: Binding loop detected for property \"stringProperty\"";
378 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
379 QObject *object = component.create();
380 QVERIFY(object != 0);
384 void tst_qdeclarativeecmascript::basicExpressions_data()
386 QTest::addColumn<QString>("expression");
387 QTest::addColumn<QVariant>("result");
388 QTest::addColumn<bool>("nest");
390 QTest::newRow("Syntax error (self test)") << "{console.log({'a':1'}.a)}" << QVariant() << false;
391 QTest::newRow("Context property") << "a" << QVariant(1944) << false;
392 QTest::newRow("Context property") << "a" << QVariant(1944) << true;
393 QTest::newRow("Context property expression") << "a * 2" << QVariant(3888) << false;
394 QTest::newRow("Context property expression") << "a * 2" << QVariant(3888) << true;
395 QTest::newRow("Overridden context property") << "b" << QVariant("Milk") << false;
396 QTest::newRow("Overridden context property") << "b" << QVariant("Cow") << true;
397 QTest::newRow("Object property") << "object.stringProperty" << QVariant("Object1") << false;
398 QTest::newRow("Object property") << "object.stringProperty" << QVariant("Object1") << true;
399 QTest::newRow("Overridden object property") << "objectOverride.stringProperty" << QVariant("Object2") << false;
400 QTest::newRow("Overridden object property") << "objectOverride.stringProperty" << QVariant("Object3") << true;
401 QTest::newRow("Default object property") << "horseLegs" << QVariant(4) << false;
402 QTest::newRow("Default object property") << "antLegs" << QVariant(6) << false;
403 QTest::newRow("Default object property") << "emuLegs" << QVariant(2) << false;
404 QTest::newRow("Nested default object property") << "horseLegs" << QVariant(4) << true;
405 QTest::newRow("Nested default object property") << "antLegs" << QVariant(7) << true;
406 QTest::newRow("Nested default object property") << "emuLegs" << QVariant(2) << true;
407 QTest::newRow("Nested default object property") << "humanLegs" << QVariant(2) << true;
408 QTest::newRow("Context property override default object property") << "millipedeLegs" << QVariant(100) << true;
411 void tst_qdeclarativeecmascript::basicExpressions()
413 QFETCH(QString, expression);
414 QFETCH(QVariant, result);
420 MyDefaultObject1 default1;
421 MyDefaultObject3 default3;
422 object1.setStringProperty("Object1");
423 object2.setStringProperty("Object2");
424 object3.setStringProperty("Object3");
426 QDeclarativeContext context(engine.rootContext());
427 QDeclarativeContext nestedContext(&context);
429 context.setContextObject(&default1);
430 context.setContextProperty("a", QVariant(1944));
431 context.setContextProperty("b", QVariant("Milk"));
432 context.setContextProperty("object", &object1);
433 context.setContextProperty("objectOverride", &object2);
434 nestedContext.setContextObject(&default3);
435 nestedContext.setContextProperty("b", QVariant("Cow"));
436 nestedContext.setContextProperty("objectOverride", &object3);
437 nestedContext.setContextProperty("millipedeLegs", QVariant(100));
439 MyExpression expr(nest?&nestedContext:&context, expression);
440 QCOMPARE(expr.evaluate(), result);
443 void tst_qdeclarativeecmascript::arrayExpressions()
449 QDeclarativeContext context(engine.rootContext());
450 context.setContextProperty("a", &obj1);
451 context.setContextProperty("b", &obj2);
452 context.setContextProperty("c", &obj3);
454 MyExpression expr(&context, "[a, b, c, 10]");
455 QVariant result = expr.evaluate();
456 QCOMPARE(result.userType(), qMetaTypeId<QList<QObject *> >());
457 QList<QObject *> list = qvariant_cast<QList<QObject *> >(result);
458 QCOMPARE(list.count(), 4);
459 QCOMPARE(list.at(0), &obj1);
460 QCOMPARE(list.at(1), &obj2);
461 QCOMPARE(list.at(2), &obj3);
462 QCOMPARE(list.at(3), (QObject *)0);
465 // Tests that modifying a context property will reevaluate expressions
466 void tst_qdeclarativeecmascript::contextPropertiesTriggerReeval()
468 QDeclarativeContext context(engine.rootContext());
471 MyQmlObject *object3 = new MyQmlObject;
473 object1.setStringProperty("Hello");
474 object2.setStringProperty("World");
476 context.setContextProperty("testProp", QVariant(1));
477 context.setContextProperty("testObj", &object1);
478 context.setContextProperty("testObj2", object3);
481 MyExpression expr(&context, "testProp + 1");
482 QCOMPARE(expr.changed, false);
483 QCOMPARE(expr.evaluate(), QVariant(2));
485 context.setContextProperty("testProp", QVariant(2));
486 QCOMPARE(expr.changed, true);
487 QCOMPARE(expr.evaluate(), QVariant(3));
491 MyExpression expr(&context, "testProp + testProp + testProp");
492 QCOMPARE(expr.changed, false);
493 QCOMPARE(expr.evaluate(), QVariant(6));
495 context.setContextProperty("testProp", QVariant(4));
496 QCOMPARE(expr.changed, true);
497 QCOMPARE(expr.evaluate(), QVariant(12));
501 MyExpression expr(&context, "testObj.stringProperty");
502 QCOMPARE(expr.changed, false);
503 QCOMPARE(expr.evaluate(), QVariant("Hello"));
505 context.setContextProperty("testObj", &object2);
506 QCOMPARE(expr.changed, true);
507 QCOMPARE(expr.evaluate(), QVariant("World"));
511 MyExpression expr(&context, "testObj.stringProperty /**/");
512 QCOMPARE(expr.changed, false);
513 QCOMPARE(expr.evaluate(), QVariant("World"));
515 context.setContextProperty("testObj", &object1);
516 QCOMPARE(expr.changed, true);
517 QCOMPARE(expr.evaluate(), QVariant("Hello"));
521 MyExpression expr(&context, "testObj2");
522 QCOMPARE(expr.changed, false);
523 QCOMPARE(expr.evaluate(), QVariant::fromValue((QObject *)object3));
529 void tst_qdeclarativeecmascript::objectPropertiesTriggerReeval()
531 QDeclarativeContext context(engine.rootContext());
535 context.setContextProperty("testObj", &object1);
537 object1.setStringProperty(QLatin1String("Hello"));
538 object2.setStringProperty(QLatin1String("Dog"));
539 object3.setStringProperty(QLatin1String("Cat"));
542 MyExpression expr(&context, "testObj.stringProperty");
543 QCOMPARE(expr.changed, false);
544 QCOMPARE(expr.evaluate(), QVariant("Hello"));
546 object1.setStringProperty(QLatin1String("World"));
547 QCOMPARE(expr.changed, true);
548 QCOMPARE(expr.evaluate(), QVariant("World"));
552 MyExpression expr(&context, "testObj.objectProperty.stringProperty");
553 QCOMPARE(expr.changed, false);
554 QCOMPARE(expr.evaluate(), QVariant());
556 object1.setObjectProperty(&object2);
557 QCOMPARE(expr.changed, true);
558 expr.changed = false;
559 QCOMPARE(expr.evaluate(), QVariant("Dog"));
561 object1.setObjectProperty(&object3);
562 QCOMPARE(expr.changed, true);
563 expr.changed = false;
564 QCOMPARE(expr.evaluate(), QVariant("Cat"));
566 object1.setObjectProperty(0);
567 QCOMPARE(expr.changed, true);
568 expr.changed = false;
569 QCOMPARE(expr.evaluate(), QVariant());
571 object1.setObjectProperty(&object3);
572 QCOMPARE(expr.changed, true);
573 expr.changed = false;
574 QCOMPARE(expr.evaluate(), QVariant("Cat"));
576 object3.setStringProperty("Donkey");
577 QCOMPARE(expr.changed, true);
578 expr.changed = false;
579 QCOMPARE(expr.evaluate(), QVariant("Donkey"));
583 void tst_qdeclarativeecmascript::deferredProperties()
585 QDeclarativeComponent component(&engine, TEST_FILE("deferredProperties.qml"));
586 MyDeferredObject *object =
587 qobject_cast<MyDeferredObject *>(component.create());
588 QVERIFY(object != 0);
589 QCOMPARE(object->value(), 0);
590 QVERIFY(object->objectProperty() == 0);
591 QVERIFY(object->objectProperty2() != 0);
592 qmlExecuteDeferred(object);
593 QCOMPARE(object->value(), 10);
594 QVERIFY(object->objectProperty() != 0);
595 MyQmlObject *qmlObject =
596 qobject_cast<MyQmlObject *>(object->objectProperty());
597 QVERIFY(qmlObject != 0);
598 QCOMPARE(qmlObject->value(), 10);
599 object->setValue(19);
600 QCOMPARE(qmlObject->value(), 19);
605 // Check errors on deferred properties are correctly emitted
606 void tst_qdeclarativeecmascript::deferredPropertiesErrors()
608 QDeclarativeComponent component(&engine, TEST_FILE("deferredPropertiesErrors.qml"));
609 MyDeferredObject *object =
610 qobject_cast<MyDeferredObject *>(component.create());
611 QVERIFY(object != 0);
612 QCOMPARE(object->value(), 0);
613 QVERIFY(object->objectProperty() == 0);
614 QVERIFY(object->objectProperty2() == 0);
616 QString warning = component.url().toString() + ":6: Unable to assign [undefined] to QObject* objectProperty";
617 QTest::ignoreMessage(QtWarningMsg, qPrintable(warning));
619 qmlExecuteDeferred(object);
624 void tst_qdeclarativeecmascript::extensionObjects()
626 QDeclarativeComponent component(&engine, TEST_FILE("extensionObjects.qml"));
627 MyExtendedObject *object =
628 qobject_cast<MyExtendedObject *>(component.create());
629 QVERIFY(object != 0);
630 QCOMPARE(object->baseProperty(), 13);
631 QCOMPARE(object->coreProperty(), 9);
632 object->setProperty("extendedProperty", QVariant(11));
633 object->setProperty("baseExtendedProperty", QVariant(92));
634 QCOMPARE(object->coreProperty(), 11);
635 QCOMPARE(object->baseProperty(), 92);
637 MyExtendedObject *nested = qobject_cast<MyExtendedObject*>(qvariant_cast<QObject *>(object->property("nested")));
639 QCOMPARE(nested->baseProperty(), 13);
640 QCOMPARE(nested->coreProperty(), 9);
641 nested->setProperty("extendedProperty", QVariant(11));
642 nested->setProperty("baseExtendedProperty", QVariant(92));
643 QCOMPARE(nested->coreProperty(), 11);
644 QCOMPARE(nested->baseProperty(), 92);
649 void tst_qdeclarativeecmascript::overrideExtensionProperties()
651 QDeclarativeComponent component(&engine, TEST_FILE("extensionObjectsPropertyOverride.qml"));
652 OverrideDefaultPropertyObject *object =
653 qobject_cast<OverrideDefaultPropertyObject *>(component.create());
654 QVERIFY(object != 0);
655 QVERIFY(object->secondProperty() != 0);
656 QVERIFY(object->firstProperty() == 0);
661 void tst_qdeclarativeecmascript::attachedProperties()
664 QDeclarativeComponent component(&engine, TEST_FILE("attachedProperty.qml"));
665 QObject *object = component.create();
666 QVERIFY(object != 0);
667 QCOMPARE(object->property("a").toInt(), 19);
668 QCOMPARE(object->property("b").toInt(), 19);
669 QCOMPARE(object->property("c").toInt(), 19);
670 QCOMPARE(object->property("d").toInt(), 19);
675 QDeclarativeComponent component(&engine, TEST_FILE("attachedProperty.2.qml"));
676 QObject *object = component.create();
677 QVERIFY(object != 0);
678 QCOMPARE(object->property("a").toInt(), 26);
679 QCOMPARE(object->property("b").toInt(), 26);
680 QCOMPARE(object->property("c").toInt(), 26);
681 QCOMPARE(object->property("d").toInt(), 26);
685 QDeclarativeComponent component(&engine, TEST_FILE("writeAttachedProperty.qml"));
686 QObject *object = component.create();
687 QVERIFY(object != 0);
689 QMetaObject::invokeMethod(object, "writeValue2");
691 MyQmlAttachedObject *attached =
692 qobject_cast<MyQmlAttachedObject *>(qmlAttachedPropertiesObject<MyQmlObject>(object));
693 QVERIFY(attached != 0);
695 QCOMPARE(attached->value2(), 9);
700 void tst_qdeclarativeecmascript::enums()
704 QDeclarativeComponent component(&engine, TEST_FILE("enums.1.qml"));
705 QObject *object = component.create();
706 QVERIFY(object != 0);
708 QCOMPARE(object->property("a").toInt(), 0);
709 QCOMPARE(object->property("b").toInt(), 1);
710 QCOMPARE(object->property("c").toInt(), 2);
711 QCOMPARE(object->property("d").toInt(), 3);
712 QCOMPARE(object->property("e").toInt(), 0);
713 QCOMPARE(object->property("f").toInt(), 1);
714 QCOMPARE(object->property("g").toInt(), 2);
715 QCOMPARE(object->property("h").toInt(), 3);
716 QCOMPARE(object->property("i").toInt(), 19);
717 QCOMPARE(object->property("j").toInt(), 19);
721 // Non-existent enums
723 QDeclarativeComponent component(&engine, TEST_FILE("enums.2.qml"));
725 QString warning1 = component.url().toString() + ":5: Unable to assign [undefined] to int a";
726 QString warning2 = component.url().toString() + ":6: Unable to assign [undefined] to int b";
727 QTest::ignoreMessage(QtWarningMsg, qPrintable(warning1));
728 QTest::ignoreMessage(QtWarningMsg, qPrintable(warning2));
730 QObject *object = component.create();
731 QVERIFY(object != 0);
732 QCOMPARE(object->property("a").toInt(), 0);
733 QCOMPARE(object->property("b").toInt(), 0);
739 void tst_qdeclarativeecmascript::valueTypeFunctions()
741 QDeclarativeComponent component(&engine, TEST_FILE("valueTypeFunctions.qml"));
742 MyTypeObject *obj = qobject_cast<MyTypeObject*>(component.create());
744 QCOMPARE(obj->rectProperty(), QRect(0,0,100,100));
745 QCOMPARE(obj->rectFProperty(), QRectF(0,0.5,100,99.5));
751 Tests that writing a constant to a property with a binding on it disables the
754 void tst_qdeclarativeecmascript::constantsOverrideBindings()
758 QDeclarativeComponent component(&engine, TEST_FILE("constantsOverrideBindings.1.qml"));
759 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
760 QVERIFY(object != 0);
762 QCOMPARE(object->property("c2").toInt(), 0);
763 object->setProperty("c1", QVariant(9));
764 QCOMPARE(object->property("c2").toInt(), 9);
766 emit object->basicSignal();
768 QCOMPARE(object->property("c2").toInt(), 13);
769 object->setProperty("c1", QVariant(8));
770 QCOMPARE(object->property("c2").toInt(), 13);
775 // During construction
777 QDeclarativeComponent component(&engine, TEST_FILE("constantsOverrideBindings.2.qml"));
778 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
779 QVERIFY(object != 0);
781 QCOMPARE(object->property("c1").toInt(), 0);
782 QCOMPARE(object->property("c2").toInt(), 10);
783 object->setProperty("c1", QVariant(9));
784 QCOMPARE(object->property("c1").toInt(), 9);
785 QCOMPARE(object->property("c2").toInt(), 10);
793 QDeclarativeComponent component(&engine, TEST_FILE("constantsOverrideBindings.3.qml"));
794 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
795 QVERIFY(object != 0);
797 QCOMPARE(object->property("c2").toInt(), 0);
798 object->setProperty("c1", QVariant(9));
799 QCOMPARE(object->property("c2").toInt(), 9);
801 object->setProperty("c2", QVariant(13));
802 QCOMPARE(object->property("c2").toInt(), 13);
803 object->setProperty("c1", QVariant(7));
804 QCOMPARE(object->property("c1").toInt(), 7);
805 QCOMPARE(object->property("c2").toInt(), 13);
813 QDeclarativeComponent component(&engine, TEST_FILE("constantsOverrideBindings.4.qml"));
814 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
815 QVERIFY(object != 0);
817 QCOMPARE(object->property("c1").toInt(), 0);
818 QCOMPARE(object->property("c3").toInt(), 10);
819 object->setProperty("c1", QVariant(9));
820 QCOMPARE(object->property("c1").toInt(), 9);
821 QCOMPARE(object->property("c3").toInt(), 10);
828 Tests that assigning a binding to a property that already has a binding causes
829 the original binding to be disabled.
831 void tst_qdeclarativeecmascript::outerBindingOverridesInnerBinding()
833 QDeclarativeComponent component(&engine,
834 TEST_FILE("outerBindingOverridesInnerBinding.qml"));
835 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
836 QVERIFY(object != 0);
838 QCOMPARE(object->property("c1").toInt(), 0);
839 QCOMPARE(object->property("c2").toInt(), 0);
840 QCOMPARE(object->property("c3").toInt(), 0);
842 object->setProperty("c1", QVariant(9));
843 QCOMPARE(object->property("c1").toInt(), 9);
844 QCOMPARE(object->property("c2").toInt(), 0);
845 QCOMPARE(object->property("c3").toInt(), 0);
847 object->setProperty("c3", QVariant(8));
848 QCOMPARE(object->property("c1").toInt(), 9);
849 QCOMPARE(object->property("c2").toInt(), 8);
850 QCOMPARE(object->property("c3").toInt(), 8);
856 Access a non-existent attached object.
858 Tests for a regression where this used to crash.
860 void tst_qdeclarativeecmascript::nonExistentAttachedObject()
862 QDeclarativeComponent component(&engine, TEST_FILE("nonExistentAttachedObject.qml"));
864 QString warning = component.url().toString() + ":4: Unable to assign [undefined] to QString stringProperty";
865 QTest::ignoreMessage(QtWarningMsg, qPrintable(warning));
867 QObject *object = component.create();
868 QVERIFY(object != 0);
873 void tst_qdeclarativeecmascript::scope()
876 QDeclarativeComponent component(&engine, TEST_FILE("scope.qml"));
877 QObject *object = component.create();
878 QVERIFY(object != 0);
880 QCOMPARE(object->property("test1").toInt(), 1);
881 QCOMPARE(object->property("test2").toInt(), 2);
882 QCOMPARE(object->property("test3").toString(), QString("1Test"));
883 QCOMPARE(object->property("test4").toString(), QString("2Test"));
884 QCOMPARE(object->property("test5").toInt(), 1);
885 QCOMPARE(object->property("test6").toInt(), 1);
886 QCOMPARE(object->property("test7").toInt(), 2);
887 QCOMPARE(object->property("test8").toInt(), 2);
888 QCOMPARE(object->property("test9").toInt(), 1);
889 QCOMPARE(object->property("test10").toInt(), 3);
895 QDeclarativeComponent component(&engine, TEST_FILE("scope.2.qml"));
896 QObject *object = component.create();
897 QVERIFY(object != 0);
899 QCOMPARE(object->property("test1").toInt(), 19);
900 QCOMPARE(object->property("test2").toInt(), 19);
901 QCOMPARE(object->property("test3").toInt(), 14);
902 QCOMPARE(object->property("test4").toInt(), 14);
903 QCOMPARE(object->property("test5").toInt(), 24);
904 QCOMPARE(object->property("test6").toInt(), 24);
910 QDeclarativeComponent component(&engine, TEST_FILE("scope.3.qml"));
911 QObject *object = component.create();
912 QVERIFY(object != 0);
914 QCOMPARE(object->property("test1").toBool(), true);
915 QCOMPARE(object->property("test2").toBool(), true);
916 QCOMPARE(object->property("test3").toBool(), true);
921 // Signal argument scope
923 QDeclarativeComponent component(&engine, TEST_FILE("scope.4.qml"));
924 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
925 QVERIFY(object != 0);
927 QCOMPARE(object->property("test").toInt(), 0);
928 QCOMPARE(object->property("test2").toString(), QString());
930 emit object->argumentSignal(13, "Argument Scope", 9, MyQmlObject::EnumValue4, Qt::RightButton);
932 QCOMPARE(object->property("test").toInt(), 13);
933 QCOMPARE(object->property("test2").toString(), QString("Argument Scope"));
939 QDeclarativeComponent component(&engine, TEST_FILE("scope.5.qml"));
940 QObject *object = component.create();
941 QVERIFY(object != 0);
943 QCOMPARE(object->property("test1").toBool(), true);
944 QCOMPARE(object->property("test2").toBool(), true);
950 QDeclarativeComponent component(&engine, TEST_FILE("scope.6.qml"));
951 QObject *object = component.create();
952 QVERIFY(object != 0);
954 QCOMPARE(object->property("test").toBool(), true);
961 Tests that "any" type passes through a synthesized signal parameter. This
962 is essentially a test of QDeclarativeMetaType::copy()
964 void tst_qdeclarativeecmascript::signalParameterTypes()
966 QDeclarativeComponent component(&engine, TEST_FILE("signalParameterTypes.qml"));
967 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
968 QVERIFY(object != 0);
970 emit object->basicSignal();
972 QCOMPARE(object->property("intProperty").toInt(), 10);
973 QCOMPARE(object->property("realProperty").toReal(), 19.2);
974 QVERIFY(object->property("colorProperty").value<QColor>() == QColor(255, 255, 0, 255));
975 QVERIFY(object->property("variantProperty") == QVariant::fromValue(QColor(255, 0, 255, 255)));
976 QVERIFY(object->property("enumProperty") == MyQmlObject::EnumValue3);
977 QVERIFY(object->property("qtEnumProperty") == Qt::LeftButton);
983 Test that two JS objects for the same QObject compare as equal.
985 void tst_qdeclarativeecmascript::objectsCompareAsEqual()
987 QDeclarativeComponent component(&engine, TEST_FILE("objectsCompareAsEqual.qml"));
988 QObject *object = component.create();
989 QVERIFY(object != 0);
991 QCOMPARE(object->property("test1").toBool(), true);
992 QCOMPARE(object->property("test2").toBool(), true);
993 QCOMPARE(object->property("test3").toBool(), true);
994 QCOMPARE(object->property("test4").toBool(), true);
995 QCOMPARE(object->property("test5").toBool(), true);
1001 Confirm bindings and alias properties can coexist.
1003 Tests for a regression where the binding would not reevaluate.
1005 void tst_qdeclarativeecmascript::aliasPropertyAndBinding()
1007 QDeclarativeComponent component(&engine, TEST_FILE("aliasPropertyAndBinding.qml"));
1008 QObject *object = component.create();
1009 QVERIFY(object != 0);
1011 QCOMPARE(object->property("c2").toInt(), 3);
1012 QCOMPARE(object->property("c3").toInt(), 3);
1014 object->setProperty("c2", QVariant(19));
1016 QCOMPARE(object->property("c2").toInt(), 19);
1017 QCOMPARE(object->property("c3").toInt(), 19);
1022 void tst_qdeclarativeecmascript::dynamicCreation_data()
1024 QTest::addColumn<QString>("method");
1025 QTest::addColumn<QString>("createdName");
1027 QTest::newRow("One") << "createOne" << "objectOne";
1028 QTest::newRow("Two") << "createTwo" << "objectTwo";
1029 QTest::newRow("Three") << "createThree" << "objectThree";
1033 Test using createQmlObject to dynamically generate an item
1034 Also using createComponent is tested.
1036 void tst_qdeclarativeecmascript::dynamicCreation()
1038 QFETCH(QString, method);
1039 QFETCH(QString, createdName);
1041 QDeclarativeComponent component(&engine, TEST_FILE("dynamicCreation.qml"));
1042 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1043 QVERIFY(object != 0);
1045 QMetaObject::invokeMethod(object, method.toUtf8());
1046 QObject *created = object->objectProperty();
1048 QCOMPARE(created->objectName(), createdName);
1054 Tests the destroy function
1056 void tst_qdeclarativeecmascript::dynamicDestruction()
1058 QDeclarativeComponent component(&engine, TEST_FILE("dynamicDeletion.qml"));
1059 QDeclarativeGuard<MyQmlObject> object = qobject_cast<MyQmlObject*>(component.create());
1060 QVERIFY(object != 0);
1061 QDeclarativeGuard<QObject> createdQmlObject = 0;
1063 QMetaObject::invokeMethod(object, "create");
1064 createdQmlObject = object->objectProperty();
1065 QVERIFY(createdQmlObject);
1066 QCOMPARE(createdQmlObject->objectName(), QString("emptyObject"));
1068 QMetaObject::invokeMethod(object, "killOther");
1069 QVERIFY(createdQmlObject);
1070 QCoreApplication::instance()->processEvents(QEventLoop::DeferredDeletion);
1071 QVERIFY(createdQmlObject);
1072 for (int ii = 0; createdQmlObject && ii < 50; ++ii) { // After 5 seconds we should give up
1073 if (createdQmlObject) {
1075 QCoreApplication::instance()->processEvents(QEventLoop::DeferredDeletion);
1078 QVERIFY(!createdQmlObject);
1080 QDeclarativeEngine::setObjectOwnership(object, QDeclarativeEngine::JavaScriptOwnership);
1081 QMetaObject::invokeMethod(object, "killMe");
1084 QCoreApplication::instance()->processEvents(QEventLoop::DeferredDeletion);
1089 tests that id.toString() works
1091 void tst_qdeclarativeecmascript::objectToString()
1093 QDeclarativeComponent component(&engine, TEST_FILE("declarativeToString.qml"));
1094 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1095 QVERIFY(object != 0);
1096 QMetaObject::invokeMethod(object, "testToString");
1097 QVERIFY(object->stringProperty().startsWith("MyQmlObject_QML_"));
1098 QVERIFY(object->stringProperty().endsWith(", \"objName\")"));
1104 Tests bindings that indirectly cause their own deletion work.
1106 This test is best run under valgrind to ensure no invalid memory access occur.
1108 void tst_qdeclarativeecmascript::selfDeletingBinding()
1111 QDeclarativeComponent component(&engine, TEST_FILE("selfDeletingBinding.qml"));
1112 QObject *object = component.create();
1113 QVERIFY(object != 0);
1114 object->setProperty("triggerDelete", true);
1119 QDeclarativeComponent component(&engine, TEST_FILE("selfDeletingBinding.2.qml"));
1120 QObject *object = component.create();
1121 QVERIFY(object != 0);
1122 object->setProperty("triggerDelete", true);
1128 Test that extended object properties can be accessed.
1130 This test a regression where this used to crash. The issue was specificially
1131 for extended objects that did not include a synthesized meta object (so non-root
1132 and no synthesiszed properties).
1134 void tst_qdeclarativeecmascript::extendedObjectPropertyLookup()
1136 QDeclarativeComponent component(&engine, TEST_FILE("extendedObjectPropertyLookup.qml"));
1137 QObject *object = component.create();
1138 QVERIFY(object != 0);
1143 Test file/lineNumbers for binding/Script errors.
1145 void tst_qdeclarativeecmascript::scriptErrors()
1147 QDeclarativeComponent component(&engine, TEST_FILE("scriptErrors.qml"));
1148 QString url = component.url().toString();
1150 QString warning1 = url.left(url.length() - 3) + "js:2: Error: Invalid write to global property \"a\"";
1151 QString warning2 = url + ":5: ReferenceError: Can't find variable: a";
1152 QString warning3 = url.left(url.length() - 3) + "js:4: Error: Invalid write to global property \"a\"";
1153 QString warning4 = url + ":10: ReferenceError: Can't find variable: a";
1154 QString warning5 = url + ":8: ReferenceError: Can't find variable: a";
1155 QString warning6 = url + ":7: Unable to assign [undefined] to int x";
1156 QString warning7 = url + ":12: Error: Cannot assign to read-only property \"trueProperty\"";
1157 QString warning8 = url + ":13: Error: Cannot assign to non-existent property \"fakeProperty\"";
1159 QTest::ignoreMessage(QtWarningMsg, warning1.toLatin1().constData());
1160 QTest::ignoreMessage(QtWarningMsg, warning2.toLatin1().constData());
1161 QTest::ignoreMessage(QtWarningMsg, warning3.toLatin1().constData());
1162 QTest::ignoreMessage(QtWarningMsg, warning5.toLatin1().constData());
1163 QTest::ignoreMessage(QtWarningMsg, warning6.toLatin1().constData());
1164 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
1165 QVERIFY(object != 0);
1167 QTest::ignoreMessage(QtWarningMsg, warning4.toLatin1().constData());
1168 emit object->basicSignal();
1170 QTest::ignoreMessage(QtWarningMsg, warning7.toLatin1().constData());
1171 emit object->anotherBasicSignal();
1173 QTest::ignoreMessage(QtWarningMsg, warning8.toLatin1().constData());
1174 emit object->thirdBasicSignal();
1180 Test file/lineNumbers for inline functions.
1182 void tst_qdeclarativeecmascript::functionErrors()
1184 QDeclarativeComponent component(&engine, TEST_FILE("functionErrors.qml"));
1185 QString url = component.url().toString();
1187 QString warning = url + ":5: Error: Invalid write to global property \"a\"";
1189 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
1191 QObject *object = component.create();
1192 QVERIFY(object != 0);
1195 // test that if an exception occurs while invoking js function from cpp, it is reported as expected.
1196 QDeclarativeComponent componentTwo(&engine, TEST_FILE("scarceresources/scarceResourceFunctionFail.qml"));
1197 url = componentTwo.url().toString();
1198 object = componentTwo.create();
1199 QVERIFY(object != 0);
1201 QString srpname = object->property("srp_name").toString();
1203 warning = url + QLatin1String(":17: TypeError: Property 'scarceResource' of object ") + srpname +
1204 QLatin1String(" is not a function");
1205 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData()); // we expect a meaningful warning to be printed.
1206 QMetaObject::invokeMethod(object, "retrieveScarceResource");
1211 Test various errors that can occur when assigning a property from script
1213 void tst_qdeclarativeecmascript::propertyAssignmentErrors()
1215 QDeclarativeComponent component(&engine, TEST_FILE("propertyAssignmentErrors.qml"));
1217 QString url = component.url().toString();
1219 QObject *object = component.create();
1220 QVERIFY(object != 0);
1222 QCOMPARE(object->property("test1").toBool(), true);
1223 QCOMPARE(object->property("test2").toBool(), true);
1229 Test bindings still work when the reeval is triggered from within
1232 void tst_qdeclarativeecmascript::signalTriggeredBindings()
1234 QDeclarativeComponent component(&engine, TEST_FILE("signalTriggeredBindings.qml"));
1235 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1236 QVERIFY(object != 0);
1238 QCOMPARE(object->property("base").toReal(), 50.);
1239 QCOMPARE(object->property("test1").toReal(), 50.);
1240 QCOMPARE(object->property("test2").toReal(), 50.);
1242 object->basicSignal();
1244 QCOMPARE(object->property("base").toReal(), 200.);
1245 QCOMPARE(object->property("test1").toReal(), 200.);
1246 QCOMPARE(object->property("test2").toReal(), 200.);
1248 object->argumentSignal(10, QString(), 10, MyQmlObject::EnumValue4, Qt::RightButton);
1250 QCOMPARE(object->property("base").toReal(), 400.);
1251 QCOMPARE(object->property("test1").toReal(), 400.);
1252 QCOMPARE(object->property("test2").toReal(), 400.);
1258 Test that list properties can be iterated from ECMAScript
1260 void tst_qdeclarativeecmascript::listProperties()
1262 QDeclarativeComponent component(&engine, TEST_FILE("listProperties.qml"));
1263 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1264 QVERIFY(object != 0);
1266 QCOMPARE(object->property("test1").toInt(), 21);
1267 QCOMPARE(object->property("test2").toInt(), 2);
1268 QCOMPARE(object->property("test3").toBool(), true);
1269 QCOMPARE(object->property("test4").toBool(), true);
1274 void tst_qdeclarativeecmascript::exceptionClearsOnReeval()
1276 QDeclarativeComponent component(&engine, TEST_FILE("exceptionClearsOnReeval.qml"));
1277 QString url = component.url().toString();
1279 QString warning = url + ":4: TypeError: Cannot read property 'objectProperty' of null";
1281 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
1282 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1283 QVERIFY(object != 0);
1285 QCOMPARE(object->property("test").toBool(), false);
1287 MyQmlObject object2;
1288 MyQmlObject object3;
1289 object2.setObjectProperty(&object3);
1290 object->setObjectProperty(&object2);
1292 QCOMPARE(object->property("test").toBool(), true);
1297 void tst_qdeclarativeecmascript::exceptionSlotProducesWarning()
1299 QDeclarativeComponent component(&engine, TEST_FILE("exceptionProducesWarning.qml"));
1300 QString url = component.url().toString();
1302 QString warning = component.url().toString() + ":6: Error: JS exception";
1304 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
1305 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1306 QVERIFY(object != 0);
1310 void tst_qdeclarativeecmascript::exceptionBindingProducesWarning()
1312 QDeclarativeComponent component(&engine, TEST_FILE("exceptionProducesWarning2.qml"));
1313 QString url = component.url().toString();
1315 QString warning = component.url().toString() + ":5: Error: JS exception";
1317 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
1318 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1319 QVERIFY(object != 0);
1323 static int transientErrorsMsgCount = 0;
1324 static void transientErrorsMsgHandler(QtMsgType, const char *)
1326 ++transientErrorsMsgCount;
1329 // Check that transient binding errors are not displayed
1330 void tst_qdeclarativeecmascript::transientErrors()
1333 QDeclarativeComponent component(&engine, TEST_FILE("transientErrors.qml"));
1335 transientErrorsMsgCount = 0;
1336 QtMsgHandler old = qInstallMsgHandler(transientErrorsMsgHandler);
1338 QObject *object = component.create();
1339 QVERIFY(object != 0);
1341 qInstallMsgHandler(old);
1343 QCOMPARE(transientErrorsMsgCount, 0);
1348 // One binding erroring multiple times, but then resolving
1350 QDeclarativeComponent component(&engine, TEST_FILE("transientErrors.2.qml"));
1352 transientErrorsMsgCount = 0;
1353 QtMsgHandler old = qInstallMsgHandler(transientErrorsMsgHandler);
1355 QObject *object = component.create();
1356 QVERIFY(object != 0);
1358 qInstallMsgHandler(old);
1360 QCOMPARE(transientErrorsMsgCount, 0);
1366 // Check that errors during shutdown are minimized
1367 void tst_qdeclarativeecmascript::shutdownErrors()
1369 QDeclarativeComponent component(&engine, TEST_FILE("shutdownErrors.qml"));
1370 QObject *object = component.create();
1371 QVERIFY(object != 0);
1373 transientErrorsMsgCount = 0;
1374 QtMsgHandler old = qInstallMsgHandler(transientErrorsMsgHandler);
1378 qInstallMsgHandler(old);
1379 QCOMPARE(transientErrorsMsgCount, 0);
1382 void tst_qdeclarativeecmascript::compositePropertyType()
1384 QDeclarativeComponent component(&engine, TEST_FILE("compositePropertyType.qml"));
1385 QTest::ignoreMessage(QtDebugMsg, "hello world");
1386 QObject *object = qobject_cast<QObject *>(component.create());
1391 void tst_qdeclarativeecmascript::jsObject()
1393 QDeclarativeComponent component(&engine, TEST_FILE("jsObject.qml"));
1394 QObject *object = component.create();
1395 QVERIFY(object != 0);
1397 QCOMPARE(object->property("test").toInt(), 92);
1402 void tst_qdeclarativeecmascript::undefinedResetsProperty()
1405 QDeclarativeComponent component(&engine, TEST_FILE("undefinedResetsProperty.qml"));
1406 QObject *object = component.create();
1407 QVERIFY(object != 0);
1409 QCOMPARE(object->property("resettableProperty").toInt(), 92);
1411 object->setProperty("setUndefined", true);
1413 QCOMPARE(object->property("resettableProperty").toInt(), 13);
1415 object->setProperty("setUndefined", false);
1417 QCOMPARE(object->property("resettableProperty").toInt(), 92);
1422 QDeclarativeComponent component(&engine, TEST_FILE("undefinedResetsProperty.2.qml"));
1423 QObject *object = component.create();
1424 QVERIFY(object != 0);
1426 QCOMPARE(object->property("resettableProperty").toInt(), 19);
1428 QMetaObject::invokeMethod(object, "doReset");
1430 QCOMPARE(object->property("resettableProperty").toInt(), 13);
1437 void tst_qdeclarativeecmascript::bug1()
1439 QDeclarativeComponent component(&engine, TEST_FILE("bug.1.qml"));
1440 QObject *object = component.create();
1441 QVERIFY(object != 0);
1443 QCOMPARE(object->property("test").toInt(), 14);
1445 object->setProperty("a", 11);
1447 QCOMPARE(object->property("test").toInt(), 3);
1449 object->setProperty("b", true);
1451 QCOMPARE(object->property("test").toInt(), 9);
1456 void tst_qdeclarativeecmascript::bug2()
1458 QDeclarativeComponent component(&engine);
1459 component.setData("import Qt.test 1.0;\nQPlainTextEdit { width: 100 }", QUrl());
1461 QObject *object = component.create();
1462 QVERIFY(object != 0);
1467 // Don't crash in createObject when the component has errors.
1468 void tst_qdeclarativeecmascript::dynamicCreationCrash()
1470 QDeclarativeComponent component(&engine, TEST_FILE("dynamicCreation.qml"));
1471 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1472 QVERIFY(object != 0);
1474 QTest::ignoreMessage(QtWarningMsg, "QDeclarativeComponent: Component is not ready");
1475 QMetaObject::invokeMethod(object, "dontCrash");
1476 QObject *created = object->objectProperty();
1477 QVERIFY(created == 0);
1483 void tst_qdeclarativeecmascript::regExpBug()
1485 QDeclarativeComponent component(&engine, TEST_FILE("regExp.qml"));
1486 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1487 QVERIFY(object != 0);
1488 QCOMPARE(object->regExp().pattern(), QLatin1String("[a-zA-z]"));
1492 static inline bool evaluate_error(QV8Engine *engine, v8::Handle<v8::Object> o, const char *source)
1494 QString functionSource = QLatin1String("(function(object) { return ") +
1495 QLatin1String(source) + QLatin1String(" })");
1497 v8::Local<v8::Script> program = v8::Script::Compile(engine->toString(functionSource));
1500 v8::Handle<v8::Function> function = v8::Handle<v8::Function>::Cast(program->Run());
1501 if (function.IsEmpty())
1503 v8::Handle<v8::Value> args[] = { o };
1504 function->Call(engine->global(), 1, args);
1505 return tc.HasCaught();
1508 static inline bool evaluate_value(QV8Engine *engine, v8::Handle<v8::Object> o,
1509 const char *source, v8::Handle<v8::Value> result)
1511 QString functionSource = QLatin1String("(function(object) { return ") +
1512 QLatin1String(source) + QLatin1String(" })");
1514 v8::Local<v8::Script> program = v8::Script::Compile(engine->toString(functionSource));
1517 v8::Handle<v8::Function> function = v8::Handle<v8::Function>::Cast(program->Run());
1518 if (function.IsEmpty())
1520 v8::Handle<v8::Value> args[] = { o };
1522 v8::Handle<v8::Value> value = function->Call(engine->global(), 1, args);
1527 return value->StrictEquals(result);
1530 static inline v8::Handle<v8::Value> evaluate(QV8Engine *engine, v8::Handle<v8::Object> o,
1533 QString functionSource = QLatin1String("(function(object) { return ") +
1534 QLatin1String(source) + QLatin1String(" })");
1536 v8::Local<v8::Script> program = v8::Script::Compile(engine->toString(functionSource));
1538 return v8::Handle<v8::Value>();
1539 v8::Handle<v8::Function> function = v8::Handle<v8::Function>::Cast(program->Run());
1540 if (function.IsEmpty())
1541 return v8::Handle<v8::Value>();
1542 v8::Handle<v8::Value> args[] = { o };
1544 v8::Handle<v8::Value> value = function->Call(engine->global(), 1, args);
1547 return v8::Handle<v8::Value>();
1551 #define EVALUATE_ERROR(source) evaluate_error(engine, object, source)
1552 #define EVALUATE_VALUE(source, result) evaluate_value(engine, object, source, result)
1553 #define EVALUATE(source) evaluate(engine, object, source)
1555 void tst_qdeclarativeecmascript::callQtInvokables()
1557 MyInvokableObject o;
1559 QDeclarativeEngine qmlengine;
1560 QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(&qmlengine);
1562 QV8Engine *engine = &ep->v8engine;
1564 v8::HandleScope handle_scope;
1565 v8::Context::Scope scope(engine->context());
1567 v8::Local<v8::Object> object = engine->newQObject(&o)->ToObject();
1569 // Non-existent methods
1571 QVERIFY(EVALUATE_ERROR("object.method_nonexistent()"));
1572 QCOMPARE(o.error(), false);
1573 QCOMPARE(o.invoked(), -1);
1574 QCOMPARE(o.actuals().count(), 0);
1577 QVERIFY(EVALUATE_ERROR("object.method_nonexistent(10, 11)"));
1578 QCOMPARE(o.error(), false);
1579 QCOMPARE(o.invoked(), -1);
1580 QCOMPARE(o.actuals().count(), 0);
1582 // Insufficient arguments
1584 QVERIFY(EVALUATE_ERROR("object.method_int()"));
1585 QCOMPARE(o.error(), false);
1586 QCOMPARE(o.invoked(), -1);
1587 QCOMPARE(o.actuals().count(), 0);
1590 QVERIFY(EVALUATE_ERROR("object.method_intint(10)"));
1591 QCOMPARE(o.error(), false);
1592 QCOMPARE(o.invoked(), -1);
1593 QCOMPARE(o.actuals().count(), 0);
1595 // Excessive arguments
1597 QVERIFY(EVALUATE_VALUE("object.method_int(10, 11)", v8::Undefined()));
1598 QCOMPARE(o.error(), false);
1599 QCOMPARE(o.invoked(), 8);
1600 QCOMPARE(o.actuals().count(), 1);
1601 QCOMPARE(o.actuals().at(0), QVariant(10));
1604 QVERIFY(EVALUATE_VALUE("object.method_intint(10, 11, 12)", v8::Undefined()));
1605 QCOMPARE(o.error(), false);
1606 QCOMPARE(o.invoked(), 9);
1607 QCOMPARE(o.actuals().count(), 2);
1608 QCOMPARE(o.actuals().at(0), QVariant(10));
1609 QCOMPARE(o.actuals().at(1), QVariant(11));
1611 // Test return types
1613 QVERIFY(EVALUATE_VALUE("object.method_NoArgs()", v8::Undefined()));
1614 QCOMPARE(o.error(), false);
1615 QCOMPARE(o.invoked(), 0);
1616 QCOMPARE(o.actuals().count(), 0);
1619 QVERIFY(EVALUATE_VALUE("object.method_NoArgs_int()", v8::Integer::New(6)));
1620 QCOMPARE(o.error(), false);
1621 QCOMPARE(o.invoked(), 1);
1622 QCOMPARE(o.actuals().count(), 0);
1625 QVERIFY(EVALUATE_VALUE("object.method_NoArgs_real()", v8::Number::New(19.75)));
1626 QCOMPARE(o.error(), false);
1627 QCOMPARE(o.invoked(), 2);
1628 QCOMPARE(o.actuals().count(), 0);
1632 v8::Handle<v8::Value> ret = EVALUATE("object.method_NoArgs_QPointF()");
1633 QVERIFY(!ret.IsEmpty());
1634 QCOMPARE(engine->toVariant(ret, -1), QVariant(QPointF(123, 4.5)));
1635 QCOMPARE(o.error(), false);
1636 QCOMPARE(o.invoked(), 3);
1637 QCOMPARE(o.actuals().count(), 0);
1642 v8::Handle<v8::Value> ret = EVALUATE("object.method_NoArgs_QObject()");
1643 QCOMPARE(engine->toQObject(ret), (QObject *)&o);
1644 QCOMPARE(o.error(), false);
1645 QCOMPARE(o.invoked(), 4);
1646 QCOMPARE(o.actuals().count(), 0);
1650 QVERIFY(EVALUATE_VALUE("object.method_NoArgs_unknown()", v8::Undefined()));
1651 QCOMPARE(o.error(), false);
1652 QCOMPARE(o.invoked(), 5);
1653 QCOMPARE(o.actuals().count(), 0);
1655 // XXX enable once qml/qtscript integration is implemented
1659 v8::Handle<v8::Value> ret = EVALUATE("object.method_NoArgs_QScriptValue()");
1660 QVERIFY(ret->IsString());
1661 QCOMPARE(engine->toString(ret), QString("Hello world"));
1662 QCOMPARE(o.error(), false);
1663 QCOMPARE(o.invoked(), 6);
1664 QCOMPARE(o.actuals().count(), 0);
1669 QVERIFY(EVALUATE_VALUE("object.method_NoArgs_QVariant()", engine->toString("QML rocks")));
1670 QCOMPARE(o.error(), false);
1671 QCOMPARE(o.invoked(), 7);
1672 QCOMPARE(o.actuals().count(), 0);
1676 QVERIFY(EVALUATE_VALUE("object.method_int(94)", v8::Undefined()));
1677 QCOMPARE(o.error(), false);
1678 QCOMPARE(o.invoked(), 8);
1679 QCOMPARE(o.actuals().count(), 1);
1680 QCOMPARE(o.actuals().at(0), QVariant(94));
1683 QVERIFY(EVALUATE_VALUE("object.method_int(\"94\")", v8::Undefined()));
1684 QCOMPARE(o.error(), false);
1685 QCOMPARE(o.invoked(), 8);
1686 QCOMPARE(o.actuals().count(), 1);
1687 QCOMPARE(o.actuals().at(0), QVariant(94));
1690 QVERIFY(EVALUATE_VALUE("object.method_int(\"not a number\")", v8::Undefined()));
1691 QCOMPARE(o.error(), false);
1692 QCOMPARE(o.invoked(), 8);
1693 QCOMPARE(o.actuals().count(), 1);
1694 QCOMPARE(o.actuals().at(0), QVariant(0));
1697 QVERIFY(EVALUATE_VALUE("object.method_int(null)", v8::Undefined()));
1698 QCOMPARE(o.error(), false);
1699 QCOMPARE(o.invoked(), 8);
1700 QCOMPARE(o.actuals().count(), 1);
1701 QCOMPARE(o.actuals().at(0), QVariant(0));
1704 QVERIFY(EVALUATE_VALUE("object.method_int(undefined)", v8::Undefined()));
1705 QCOMPARE(o.error(), false);
1706 QCOMPARE(o.invoked(), 8);
1707 QCOMPARE(o.actuals().count(), 1);
1708 QCOMPARE(o.actuals().at(0), QVariant(0));
1711 QVERIFY(EVALUATE_VALUE("object.method_int(object)", v8::Undefined()));
1712 QCOMPARE(o.error(), false);
1713 QCOMPARE(o.invoked(), 8);
1714 QCOMPARE(o.actuals().count(), 1);
1715 QCOMPARE(o.actuals().at(0), QVariant(0));
1718 QVERIFY(EVALUATE_VALUE("object.method_intint(122, 9)", v8::Undefined()));
1719 QCOMPARE(o.error(), false);
1720 QCOMPARE(o.invoked(), 9);
1721 QCOMPARE(o.actuals().count(), 2);
1722 QCOMPARE(o.actuals().at(0), QVariant(122));
1723 QCOMPARE(o.actuals().at(1), QVariant(9));
1726 QVERIFY(EVALUATE_VALUE("object.method_real(94.3)", v8::Undefined()));
1727 QCOMPARE(o.error(), false);
1728 QCOMPARE(o.invoked(), 10);
1729 QCOMPARE(o.actuals().count(), 1);
1730 QCOMPARE(o.actuals().at(0), QVariant(94.3));
1733 QVERIFY(EVALUATE_VALUE("object.method_real(\"94.3\")", v8::Undefined()));
1734 QCOMPARE(o.error(), false);
1735 QCOMPARE(o.invoked(), 10);
1736 QCOMPARE(o.actuals().count(), 1);
1737 QCOMPARE(o.actuals().at(0), QVariant(94.3));
1740 QVERIFY(EVALUATE_VALUE("object.method_real(\"not a number\")", v8::Undefined()));
1741 QCOMPARE(o.error(), false);
1742 QCOMPARE(o.invoked(), 10);
1743 QCOMPARE(o.actuals().count(), 1);
1744 QVERIFY(qIsNaN(o.actuals().at(0).toDouble()));
1747 QVERIFY(EVALUATE_VALUE("object.method_real(null)", v8::Undefined()));
1748 QCOMPARE(o.error(), false);
1749 QCOMPARE(o.invoked(), 10);
1750 QCOMPARE(o.actuals().count(), 1);
1751 QCOMPARE(o.actuals().at(0), QVariant(0));
1754 QVERIFY(EVALUATE_VALUE("object.method_real(undefined)", v8::Undefined()));
1755 QCOMPARE(o.error(), false);
1756 QCOMPARE(o.invoked(), 10);
1757 QCOMPARE(o.actuals().count(), 1);
1758 QVERIFY(qIsNaN(o.actuals().at(0).toDouble()));
1761 QVERIFY(EVALUATE_VALUE("object.method_real(object)", v8::Undefined()));
1762 QCOMPARE(o.error(), false);
1763 QCOMPARE(o.invoked(), 10);
1764 QCOMPARE(o.actuals().count(), 1);
1765 QVERIFY(qIsNaN(o.actuals().at(0).toDouble()));
1768 QVERIFY(EVALUATE_VALUE("object.method_QString(\"Hello world\")", v8::Undefined()));
1769 QCOMPARE(o.error(), false);
1770 QCOMPARE(o.invoked(), 11);
1771 QCOMPARE(o.actuals().count(), 1);
1772 QCOMPARE(o.actuals().at(0), QVariant("Hello world"));
1775 QVERIFY(EVALUATE_VALUE("object.method_QString(19)", v8::Undefined()));
1776 QCOMPARE(o.error(), false);
1777 QCOMPARE(o.invoked(), 11);
1778 QCOMPARE(o.actuals().count(), 1);
1779 QCOMPARE(o.actuals().at(0), QVariant("19"));
1783 QString expected = "MyInvokableObject(0x" + QString::number((quintptr)&o, 16) + ")";
1784 QVERIFY(EVALUATE_VALUE("object.method_QString(object)", v8::Undefined()));
1785 QCOMPARE(o.error(), false);
1786 QCOMPARE(o.invoked(), 11);
1787 QCOMPARE(o.actuals().count(), 1);
1788 QCOMPARE(o.actuals().at(0), QVariant(expected));
1792 QVERIFY(EVALUATE_VALUE("object.method_QString(null)", v8::Undefined()));
1793 QCOMPARE(o.error(), false);
1794 QCOMPARE(o.invoked(), 11);
1795 QCOMPARE(o.actuals().count(), 1);
1796 QCOMPARE(o.actuals().at(0), QVariant(QString()));
1799 QVERIFY(EVALUATE_VALUE("object.method_QString(undefined)", v8::Undefined()));
1800 QCOMPARE(o.error(), false);
1801 QCOMPARE(o.invoked(), 11);
1802 QCOMPARE(o.actuals().count(), 1);
1803 QCOMPARE(o.actuals().at(0), QVariant(QString()));
1806 QVERIFY(EVALUATE_VALUE("object.method_QPointF(0)", v8::Undefined()));
1807 QCOMPARE(o.error(), false);
1808 QCOMPARE(o.invoked(), 12);
1809 QCOMPARE(o.actuals().count(), 1);
1810 QCOMPARE(o.actuals().at(0), QVariant(QPointF()));
1813 QVERIFY(EVALUATE_VALUE("object.method_QPointF(null)", v8::Undefined()));
1814 QCOMPARE(o.error(), false);
1815 QCOMPARE(o.invoked(), 12);
1816 QCOMPARE(o.actuals().count(), 1);
1817 QCOMPARE(o.actuals().at(0), QVariant(QPointF()));
1820 QVERIFY(EVALUATE_VALUE("object.method_QPointF(undefined)", v8::Undefined()));
1821 QCOMPARE(o.error(), false);
1822 QCOMPARE(o.invoked(), 12);
1823 QCOMPARE(o.actuals().count(), 1);
1824 QCOMPARE(o.actuals().at(0), QVariant(QPointF()));
1827 QVERIFY(EVALUATE_VALUE("object.method_QPointF(object)", v8::Undefined()));
1828 QCOMPARE(o.error(), false);
1829 QCOMPARE(o.invoked(), 12);
1830 QCOMPARE(o.actuals().count(), 1);
1831 QCOMPARE(o.actuals().at(0), QVariant(QPointF()));
1834 QVERIFY(EVALUATE_VALUE("object.method_QPointF(object.method_get_QPointF())", v8::Undefined()));
1835 QCOMPARE(o.error(), false);
1836 QCOMPARE(o.invoked(), 12);
1837 QCOMPARE(o.actuals().count(), 1);
1838 QCOMPARE(o.actuals().at(0), QVariant(QPointF(99.3, -10.2)));
1841 QVERIFY(EVALUATE_VALUE("object.method_QPointF(object.method_get_QPoint())", v8::Undefined()));
1842 QCOMPARE(o.error(), false);
1843 QCOMPARE(o.invoked(), 12);
1844 QCOMPARE(o.actuals().count(), 1);
1845 QCOMPARE(o.actuals().at(0), QVariant(QPointF(9, 12)));
1848 QVERIFY(EVALUATE_VALUE("object.method_QObject(0)", v8::Undefined()));
1849 QCOMPARE(o.error(), false);
1850 QCOMPARE(o.invoked(), 13);
1851 QCOMPARE(o.actuals().count(), 1);
1852 QCOMPARE(o.actuals().at(0), qVariantFromValue((QObject *)0));
1855 QVERIFY(EVALUATE_VALUE("object.method_QObject(\"Hello world\")", v8::Undefined()));
1856 QCOMPARE(o.error(), false);
1857 QCOMPARE(o.invoked(), 13);
1858 QCOMPARE(o.actuals().count(), 1);
1859 QCOMPARE(o.actuals().at(0), qVariantFromValue((QObject *)0));
1862 QVERIFY(EVALUATE_VALUE("object.method_QObject(null)", v8::Undefined()));
1863 QCOMPARE(o.error(), false);
1864 QCOMPARE(o.invoked(), 13);
1865 QCOMPARE(o.actuals().count(), 1);
1866 QCOMPARE(o.actuals().at(0), qVariantFromValue((QObject *)0));
1869 QVERIFY(EVALUATE_VALUE("object.method_QObject(undefined)", v8::Undefined()));
1870 QCOMPARE(o.error(), false);
1871 QCOMPARE(o.invoked(), 13);
1872 QCOMPARE(o.actuals().count(), 1);
1873 QCOMPARE(o.actuals().at(0), qVariantFromValue((QObject *)0));
1876 QVERIFY(EVALUATE_VALUE("object.method_QObject(object)", v8::Undefined()));
1877 QCOMPARE(o.error(), false);
1878 QCOMPARE(o.invoked(), 13);
1879 QCOMPARE(o.actuals().count(), 1);
1880 QCOMPARE(o.actuals().at(0), qVariantFromValue((QObject *)&o));
1882 // XXX enable once qml/qtscript integration is implemented
1885 QVERIFY(EVALUATE_VALUE("object.method_QScriptValue(null)", v8::Undefined()));
1886 QCOMPARE(o.error(), false);
1887 QCOMPARE(o.invoked(), 14);
1888 QCOMPARE(o.actuals().count(), 1);
1889 QVERIFY(qvariant_cast<QScriptValue>(o.actuals().at(0)).isNull());
1892 QVERIFY(EVALUATE_VALUE("object.method_QScriptValue(undefined)", v8::Undefined()));
1893 QCOMPARE(o.error(), false);
1894 QCOMPARE(o.invoked(), 14);
1895 QCOMPARE(o.actuals().count(), 1);
1896 QVERIFY(qvariant_cast<QScriptValue>(o.actuals().at(0)).isUndefined());
1899 QVERIFY(EVALUATE_VALUE("object.method_QScriptValue(19)", v8::Undefined()));
1900 QCOMPARE(o.error(), false);
1901 QCOMPARE(o.invoked(), 14);
1902 QCOMPARE(o.actuals().count(), 1);
1903 QVERIFY(qvariant_cast<QScriptValue>(o.actuals().at(0)).strictlyEquals(QScriptValue(engine, 19)));
1906 QVERIFY(EVALUATE_VALUE("object.method_QScriptValue([19, 20])", v8::Undefined()));
1907 QCOMPARE(o.error(), false);
1908 QCOMPARE(o.invoked(), 14);
1909 QCOMPARE(o.actuals().count(), 1);
1910 QVERIFY(qvariant_cast<QScriptValue>(o.actuals().at(0)).isArray());
1913 QVERIFY(EVALUATE_VALUE("object.method_intQScriptValue(4, null)", v8::Undefined()));
1914 QCOMPARE(o.error(), false);
1915 QCOMPARE(o.invoked(), 15);
1916 QCOMPARE(o.actuals().count(), 2);
1917 QCOMPARE(o.actuals().at(0), QVariant(4));
1918 QVERIFY(qvariant_cast<QScriptValue>(o.actuals().at(1)).isNull());
1921 QVERIFY(EVALUATE_VALUE("object.method_intQScriptValue(8, undefined)", v8::Undefined()));
1922 QCOMPARE(o.error(), false);
1923 QCOMPARE(o.invoked(), 15);
1924 QCOMPARE(o.actuals().count(), 2);
1925 QCOMPARE(o.actuals().at(0), QVariant(8));
1926 QVERIFY(qvariant_cast<QScriptValue>(o.actuals().at(1)).isUndefined());
1929 QVERIFY(EVALUATE_VALUE("object.method_intQScriptValue(3, 19)", v8::Undefined()));
1930 QCOMPARE(o.error(), false);
1931 QCOMPARE(o.invoked(), 15);
1932 QCOMPARE(o.actuals().count(), 2);
1933 QCOMPARE(o.actuals().at(0), QVariant(3));
1934 QVERIFY(qvariant_cast<QScriptValue>(o.actuals().at(1)).strictlyEquals(QScriptValue(engine, 19)));
1937 QVERIFY(EVALUATE_VALUE("object.method_intQScriptValue(44, [19, 20])", v8::Undefined()));
1938 QCOMPARE(o.error(), false);
1939 QCOMPARE(o.invoked(), 15);
1940 QCOMPARE(o.actuals().count(), 2);
1941 QCOMPARE(o.actuals().at(0), QVariant(44));
1942 QVERIFY(qvariant_cast<QScriptValue>(o.actuals().at(1)).isArray());
1946 QVERIFY(EVALUATE_ERROR("object.method_overload()"));
1947 QCOMPARE(o.error(), false);
1948 QCOMPARE(o.invoked(), -1);
1949 QCOMPARE(o.actuals().count(), 0);
1952 QVERIFY(EVALUATE_VALUE("object.method_overload(10)", v8::Undefined()));
1953 QCOMPARE(o.error(), false);
1954 QCOMPARE(o.invoked(), 16);
1955 QCOMPARE(o.actuals().count(), 1);
1956 QCOMPARE(o.actuals().at(0), QVariant(10));
1959 QVERIFY(EVALUATE_VALUE("object.method_overload(10, 11)", v8::Undefined()));
1960 QCOMPARE(o.error(), false);
1961 QCOMPARE(o.invoked(), 17);
1962 QCOMPARE(o.actuals().count(), 2);
1963 QCOMPARE(o.actuals().at(0), QVariant(10));
1964 QCOMPARE(o.actuals().at(1), QVariant(11));
1967 QVERIFY(EVALUATE_VALUE("object.method_overload(\"Hello\")", v8::Undefined()));
1968 QCOMPARE(o.error(), false);
1969 QCOMPARE(o.invoked(), 18);
1970 QCOMPARE(o.actuals().count(), 1);
1971 QCOMPARE(o.actuals().at(0), QVariant(QString("Hello")));
1974 QVERIFY(EVALUATE_VALUE("object.method_with_enum(9)", v8::Undefined()));
1975 QCOMPARE(o.error(), false);
1976 QCOMPARE(o.invoked(), 19);
1977 QCOMPARE(o.actuals().count(), 1);
1978 QCOMPARE(o.actuals().at(0), QVariant(9));
1981 QVERIFY(EVALUATE_VALUE("object.method_default(10)", v8::Integer::New(19)));
1982 QCOMPARE(o.error(), false);
1983 QCOMPARE(o.invoked(), 20);
1984 QCOMPARE(o.actuals().count(), 2);
1985 QCOMPARE(o.actuals().at(0), QVariant(10));
1986 QCOMPARE(o.actuals().at(1), QVariant(19));
1989 QVERIFY(EVALUATE_VALUE("object.method_default(10, 13)", v8::Integer::New(13)));
1990 QCOMPARE(o.error(), false);
1991 QCOMPARE(o.invoked(), 20);
1992 QCOMPARE(o.actuals().count(), 2);
1993 QCOMPARE(o.actuals().at(0), QVariant(10));
1994 QCOMPARE(o.actuals().at(1), QVariant(13));
1997 QVERIFY(EVALUATE_VALUE("object.method_inherited(9)", v8::Undefined()));
1998 QCOMPARE(o.error(), false);
1999 QCOMPARE(o.invoked(), -3);
2000 QCOMPARE(o.actuals().count(), 1);
2001 QCOMPARE(o.actuals().at(0), QVariant(9));
2004 QVERIFY(EVALUATE_VALUE("object.method_QVariant(9)", v8::Undefined()));
2005 QCOMPARE(o.error(), false);
2006 QCOMPARE(o.invoked(), 21);
2007 QCOMPARE(o.actuals().count(), 2);
2008 QCOMPARE(o.actuals().at(0), QVariant(9));
2009 QCOMPARE(o.actuals().at(1), QVariant());
2012 QVERIFY(EVALUATE_VALUE("object.method_QVariant(\"Hello\", \"World\")", v8::Undefined()));
2013 QCOMPARE(o.error(), false);
2014 QCOMPARE(o.invoked(), 21);
2015 QCOMPARE(o.actuals().count(), 2);
2016 QCOMPARE(o.actuals().at(0), QVariant(QString("Hello")));
2017 QCOMPARE(o.actuals().at(1), QVariant(QString("World")));
2020 // QTBUG-13047 (check that you can pass registered object types as args)
2021 void tst_qdeclarativeecmascript::invokableObjectArg()
2023 QDeclarativeComponent component(&engine, TEST_FILE("invokableObjectArg.qml"));
2025 QObject *o = component.create();
2027 MyQmlObject *qmlobject = qobject_cast<MyQmlObject *>(o);
2029 QCOMPARE(qmlobject->myinvokableObject, qmlobject);
2034 // QTBUG-13047 (check that you can return registered object types from methods)
2035 void tst_qdeclarativeecmascript::invokableObjectRet()
2037 QDeclarativeComponent component(&engine, TEST_FILE("invokableObjectRet.qml"));
2039 QObject *o = component.create();
2041 QCOMPARE(o->property("test").toBool(), true);
2046 void tst_qdeclarativeecmascript::listToVariant()
2048 QDeclarativeComponent component(&engine, TEST_FILE("listToVariant.qml"));
2050 MyQmlContainer container;
2052 QDeclarativeContext context(engine.rootContext());
2053 context.setContextObject(&container);
2055 QObject *object = component.create(&context);
2056 QVERIFY(object != 0);
2058 QVariant v = object->property("test");
2059 QCOMPARE(v.userType(), qMetaTypeId<QDeclarativeListReference>());
2060 QVERIFY(qvariant_cast<QDeclarativeListReference>(v).object() == &container);
2066 void tst_qdeclarativeecmascript::multiEngineObject()
2069 obj.setStringProperty("Howdy planet");
2071 QDeclarativeEngine e1;
2072 e1.rootContext()->setContextProperty("thing", &obj);
2073 QDeclarativeComponent c1(&e1, TEST_FILE("multiEngineObject.qml"));
2075 QDeclarativeEngine e2;
2076 e2.rootContext()->setContextProperty("thing", &obj);
2077 QDeclarativeComponent c2(&e2, TEST_FILE("multiEngineObject.qml"));
2079 QObject *o1 = c1.create();
2080 QObject *o2 = c2.create();
2082 QCOMPARE(o1->property("test").toString(), QString("Howdy planet"));
2083 QCOMPARE(o2->property("test").toString(), QString("Howdy planet"));
2089 // Test that references to QObjects are cleanup when the object is destroyed
2090 void tst_qdeclarativeecmascript::deletedObject()
2092 QDeclarativeComponent component(&engine, TEST_FILE("deletedObject.qml"));
2094 QObject *object = component.create();
2096 QCOMPARE(object->property("test1").toBool(), true);
2097 QCOMPARE(object->property("test2").toBool(), true);
2098 QCOMPARE(object->property("test3").toBool(), true);
2099 QCOMPARE(object->property("test4").toBool(), true);
2104 void tst_qdeclarativeecmascript::attachedPropertyScope()
2106 QDeclarativeComponent component(&engine, TEST_FILE("attachedPropertyScope.qml"));
2108 QObject *object = component.create();
2109 QVERIFY(object != 0);
2111 MyQmlAttachedObject *attached =
2112 qobject_cast<MyQmlAttachedObject *>(qmlAttachedPropertiesObject<MyQmlObject>(object));
2113 QVERIFY(attached != 0);
2115 QCOMPARE(object->property("value2").toInt(), 0);
2117 attached->emitMySignal();
2119 QCOMPARE(object->property("value2").toInt(), 9);
2124 void tst_qdeclarativeecmascript::scriptConnect()
2127 QDeclarativeComponent component(&engine, TEST_FILE("scriptConnect.1.qml"));
2129 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2130 QVERIFY(object != 0);
2132 QCOMPARE(object->property("test").toBool(), false);
2133 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2134 QCOMPARE(object->property("test").toBool(), true);
2140 QDeclarativeComponent component(&engine, TEST_FILE("scriptConnect.2.qml"));
2142 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2143 QVERIFY(object != 0);
2145 QCOMPARE(object->property("test").toBool(), false);
2146 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2147 QCOMPARE(object->property("test").toBool(), true);
2153 QDeclarativeComponent component(&engine, TEST_FILE("scriptConnect.3.qml"));
2155 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2156 QVERIFY(object != 0);
2158 QCOMPARE(object->property("test").toBool(), false);
2159 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2160 QCOMPARE(object->property("test").toBool(), true);
2166 QDeclarativeComponent component(&engine, TEST_FILE("scriptConnect.4.qml"));
2168 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2169 QVERIFY(object != 0);
2171 QCOMPARE(object->methodCalled(), false);
2172 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2173 QCOMPARE(object->methodCalled(), true);
2179 QDeclarativeComponent component(&engine, TEST_FILE("scriptConnect.5.qml"));
2181 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2182 QVERIFY(object != 0);
2184 QCOMPARE(object->methodCalled(), false);
2185 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2186 QCOMPARE(object->methodCalled(), true);
2192 QDeclarativeComponent component(&engine, TEST_FILE("scriptConnect.6.qml"));
2194 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2195 QVERIFY(object != 0);
2197 QCOMPARE(object->property("test").toInt(), 0);
2198 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2199 QCOMPARE(object->property("test").toInt(), 2);
2205 void tst_qdeclarativeecmascript::scriptDisconnect()
2208 QDeclarativeComponent component(&engine, TEST_FILE("scriptDisconnect.1.qml"));
2210 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2211 QVERIFY(object != 0);
2213 QCOMPARE(object->property("test").toInt(), 0);
2214 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2215 QCOMPARE(object->property("test").toInt(), 1);
2216 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2217 QCOMPARE(object->property("test").toInt(), 2);
2218 emit object->basicSignal();
2219 QCOMPARE(object->property("test").toInt(), 2);
2220 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2221 QCOMPARE(object->property("test").toInt(), 2);
2227 QDeclarativeComponent component(&engine, TEST_FILE("scriptDisconnect.2.qml"));
2229 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2230 QVERIFY(object != 0);
2232 QCOMPARE(object->property("test").toInt(), 0);
2233 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2234 QCOMPARE(object->property("test").toInt(), 1);
2235 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2236 QCOMPARE(object->property("test").toInt(), 2);
2237 emit object->basicSignal();
2238 QCOMPARE(object->property("test").toInt(), 2);
2239 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2240 QCOMPARE(object->property("test").toInt(), 2);
2246 QDeclarativeComponent component(&engine, TEST_FILE("scriptDisconnect.3.qml"));
2248 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2249 QVERIFY(object != 0);
2251 QCOMPARE(object->property("test").toInt(), 0);
2252 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2253 QCOMPARE(object->property("test").toInt(), 1);
2254 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2255 QCOMPARE(object->property("test").toInt(), 2);
2256 emit object->basicSignal();
2257 QCOMPARE(object->property("test").toInt(), 2);
2258 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2259 QCOMPARE(object->property("test").toInt(), 3);
2264 QDeclarativeComponent component(&engine, TEST_FILE("scriptDisconnect.4.qml"));
2266 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2267 QVERIFY(object != 0);
2269 QCOMPARE(object->property("test").toInt(), 0);
2270 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2271 QCOMPARE(object->property("test").toInt(), 1);
2272 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2273 QCOMPARE(object->property("test").toInt(), 2);
2274 emit object->basicSignal();
2275 QCOMPARE(object->property("test").toInt(), 2);
2276 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2277 QCOMPARE(object->property("test").toInt(), 3);
2283 class OwnershipObject : public QObject
2287 OwnershipObject() { object = new QObject; }
2289 QPointer<QObject> object;
2292 QObject *getObject() { return object; }
2295 void tst_qdeclarativeecmascript::ownership()
2297 OwnershipObject own;
2298 QDeclarativeContext *context = new QDeclarativeContext(engine.rootContext());
2299 context->setContextObject(&own);
2302 QDeclarativeComponent component(&engine, TEST_FILE("ownership.qml"));
2304 QVERIFY(own.object != 0);
2306 QObject *object = component.create(context);
2308 engine.collectGarbage();
2310 QCoreApplication::processEvents(QEventLoop::DeferredDeletion);
2312 QVERIFY(own.object == 0);
2317 own.object = new QObject(&own);
2320 QDeclarativeComponent component(&engine, TEST_FILE("ownership.qml"));
2322 QVERIFY(own.object != 0);
2324 QObject *object = component.create(context);
2326 engine.collectGarbage();
2328 QCoreApplication::processEvents(QEventLoop::DeferredDeletion);
2330 QVERIFY(own.object != 0);
2338 class CppOwnershipReturnValue : public QObject
2342 CppOwnershipReturnValue() : value(0) {}
2343 ~CppOwnershipReturnValue() { delete value; }
2345 Q_INVOKABLE QObject *create() {
2346 value = new QObject;
2347 QDeclarativeEngine::setObjectOwnership(value, QDeclarativeEngine::CppOwnership);
2351 Q_INVOKABLE MyQmlObject *createQmlObject() {
2352 MyQmlObject *rv = new MyQmlObject;
2357 QPointer<QObject> value;
2361 // Test setObjectOwnership(CppOwnership) works even when there is no QDeclarativeData
2362 void tst_qdeclarativeecmascript::cppOwnershipReturnValue()
2364 CppOwnershipReturnValue source;
2367 QDeclarativeEngine engine;
2368 engine.rootContext()->setContextProperty("source", &source);
2370 QVERIFY(source.value == 0);
2372 QDeclarativeComponent component(&engine);
2373 component.setData("import QtQuick 1.0\nQtObject {\nComponent.onCompleted: { var a = source.create(); }\n}\n", QUrl());
2375 QObject *object = component.create();
2377 QVERIFY(object != 0);
2378 QVERIFY(source.value != 0);
2383 QCoreApplication::instance()->processEvents(QEventLoop::DeferredDeletion);
2385 QVERIFY(source.value != 0);
2389 void tst_qdeclarativeecmascript::ownershipCustomReturnValue()
2391 CppOwnershipReturnValue source;
2394 QDeclarativeEngine engine;
2395 engine.rootContext()->setContextProperty("source", &source);
2397 QVERIFY(source.value == 0);
2399 QDeclarativeComponent component(&engine);
2400 component.setData("import QtQuick 1.0\nQtObject {\nComponent.onCompleted: { var a = source.createQmlObject(); }\n}\n", QUrl());
2402 QObject *object = component.create();
2404 QVERIFY(object != 0);
2405 QVERIFY(source.value != 0);
2410 engine.collectGarbage();
2411 QCoreApplication::instance()->processEvents(QEventLoop::DeferredDeletion);
2413 QVERIFY(source.value == 0);
2416 class QListQObjectMethodsObject : public QObject
2420 QListQObjectMethodsObject() {
2421 m_objects.append(new MyQmlObject());
2422 m_objects.append(new MyQmlObject());
2425 ~QListQObjectMethodsObject() {
2426 qDeleteAll(m_objects);
2430 QList<QObject *> getObjects() { return m_objects; }
2433 QList<QObject *> m_objects;
2436 // Tests that returning a QList<QObject*> from a method works
2437 void tst_qdeclarativeecmascript::qlistqobjectMethods()
2439 QListQObjectMethodsObject obj;
2440 QDeclarativeContext *context = new QDeclarativeContext(engine.rootContext());
2441 context->setContextObject(&obj);
2443 QDeclarativeComponent component(&engine, TEST_FILE("qlistqobjectMethods.qml"));
2445 QObject *object = component.create(context);
2447 QCOMPARE(object->property("test").toInt(), 2);
2448 QCOMPARE(object->property("test2").toBool(), true);
2455 void tst_qdeclarativeecmascript::strictlyEquals()
2457 QDeclarativeComponent component(&engine, TEST_FILE("strictlyEquals.qml"));
2459 QObject *object = component.create();
2460 QVERIFY(object != 0);
2462 QCOMPARE(object->property("test1").toBool(), true);
2463 QCOMPARE(object->property("test2").toBool(), true);
2464 QCOMPARE(object->property("test3").toBool(), true);
2465 QCOMPARE(object->property("test4").toBool(), true);
2466 QCOMPARE(object->property("test5").toBool(), true);
2467 QCOMPARE(object->property("test6").toBool(), true);
2468 QCOMPARE(object->property("test7").toBool(), true);
2469 QCOMPARE(object->property("test8").toBool(), true);
2474 void tst_qdeclarativeecmascript::compiled()
2476 QDeclarativeComponent component(&engine, TEST_FILE("compiled.qml"));
2478 QObject *object = component.create();
2479 QVERIFY(object != 0);
2481 QCOMPARE(object->property("test1").toReal(), qreal(15.7));
2482 QCOMPARE(object->property("test2").toReal(), qreal(-6.7));
2483 QCOMPARE(object->property("test3").toBool(), true);
2484 QCOMPARE(object->property("test4").toBool(), false);
2485 QCOMPARE(object->property("test5").toBool(), false);
2486 QCOMPARE(object->property("test6").toBool(), true);
2488 QCOMPARE(object->property("test7").toInt(), 185);
2489 QCOMPARE(object->property("test8").toInt(), 167);
2490 QCOMPARE(object->property("test9").toBool(), true);
2491 QCOMPARE(object->property("test10").toBool(), false);
2492 QCOMPARE(object->property("test11").toBool(), false);
2493 QCOMPARE(object->property("test12").toBool(), true);
2495 QCOMPARE(object->property("test13").toString(), QLatin1String("HelloWorld"));
2496 QCOMPARE(object->property("test14").toString(), QLatin1String("Hello World"));
2497 QCOMPARE(object->property("test15").toBool(), false);
2498 QCOMPARE(object->property("test16").toBool(), true);
2500 QCOMPARE(object->property("test17").toInt(), 5);
2501 QCOMPARE(object->property("test18").toReal(), qreal(176));
2502 QCOMPARE(object->property("test19").toInt(), 7);
2503 QCOMPARE(object->property("test20").toReal(), qreal(6.7));
2504 QCOMPARE(object->property("test21").toString(), QLatin1String("6.7"));
2505 QCOMPARE(object->property("test22").toString(), QLatin1String("!"));
2506 QCOMPARE(object->property("test23").toBool(), true);
2507 QCOMPARE(qvariant_cast<QColor>(object->property("test24")), QColor(0x11,0x22,0x33));
2508 QCOMPARE(qvariant_cast<QColor>(object->property("test25")), QColor(0x11,0x22,0x33,0xAA));
2513 // Test that numbers assigned in bindings as strings work consistently
2514 void tst_qdeclarativeecmascript::numberAssignment()
2516 QDeclarativeComponent component(&engine, TEST_FILE("numberAssignment.qml"));
2518 QObject *object = component.create();
2519 QVERIFY(object != 0);
2521 QCOMPARE(object->property("test1"), QVariant((qreal)6.7));
2522 QCOMPARE(object->property("test2"), QVariant((qreal)6.7));
2523 QCOMPARE(object->property("test2"), QVariant((qreal)6.7));
2524 QCOMPARE(object->property("test3"), QVariant((qreal)6));
2525 QCOMPARE(object->property("test4"), QVariant((qreal)6));
2527 QCOMPARE(object->property("test5"), QVariant((int)7));
2528 QCOMPARE(object->property("test6"), QVariant((int)7));
2529 QCOMPARE(object->property("test7"), QVariant((int)6));
2530 QCOMPARE(object->property("test8"), QVariant((int)6));
2532 QCOMPARE(object->property("test9"), QVariant((unsigned int)7));
2533 QCOMPARE(object->property("test10"), QVariant((unsigned int)7));
2534 QCOMPARE(object->property("test11"), QVariant((unsigned int)6));
2535 QCOMPARE(object->property("test12"), QVariant((unsigned int)6));
2540 void tst_qdeclarativeecmascript::propertySplicing()
2542 QDeclarativeComponent component(&engine, TEST_FILE("propertySplicing.qml"));
2544 QObject *object = component.create();
2545 QVERIFY(object != 0);
2547 QCOMPARE(object->property("test").toBool(), true);
2553 void tst_qdeclarativeecmascript::signalWithUnknownTypes()
2555 QDeclarativeComponent component(&engine, TEST_FILE("signalWithUnknownTypes.qml"));
2557 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2558 QVERIFY(object != 0);
2560 MyQmlObject::MyType type;
2561 type.value = 0x8971123;
2562 emit object->signalWithUnknownType(type);
2564 MyQmlObject::MyType result = qvariant_cast<MyQmlObject::MyType>(object->variant());
2566 QCOMPARE(result.value, type.value);
2572 void tst_qdeclarativeecmascript::moduleApi()
2574 QDeclarativeComponent component(&engine, TEST_FILE("moduleApi.qml"));
2575 QObject *object = component.create();
2576 QVERIFY(object != 0);
2577 QCOMPARE(object->property("existingUriTest").toInt(), 20);
2578 QCOMPARE(object->property("scriptTest").toInt(), 13);
2579 QCOMPARE(object->property("qobjectTest").toInt(), 20);
2580 QCOMPARE(object->property("qobjectMethodTest").toInt(), 1); // first call of method, so count = 1.
2581 QCOMPARE(object->property("qobjectMinorVersionTest").toInt(), 20);
2582 QCOMPARE(object->property("qobjectMajorVersionTest").toInt(), 20);
2583 QCOMPARE(object->property("qobjectParentedTest").toInt(), 26);
2586 // test that caching of module apis works correctly.
2587 QDeclarativeComponent componentTwo(&engine, TEST_FILE("moduleApiCaching.qml"));
2588 object = componentTwo.create();
2589 QVERIFY(object != 0);
2590 QCOMPARE(object->property("existingUriTest").toInt(), 20);
2591 QCOMPARE(object->property("scriptTest").toInt(), 13); // shouldn't have incremented.
2592 QCOMPARE(object->property("qobjectParentedTest").toInt(), 26); // shouldn't have incremented.
2595 // test that writing to a property of module apis works correctly.
2596 QDeclarativeComponent componentThree(&engine, TEST_FILE("moduleApiWriting.qml"));
2597 QString expectedWarning = QLatin1String("file://") + TEST_FILE("moduleApiWriting.qml").toLocalFile() + QLatin1String(":15: Error: Cannot assign to read-only property \"qobjectTestProperty\"");
2598 QTest::ignoreMessage(QtWarningMsg, expectedWarning.toAscii().constData());
2599 object = componentThree.create();
2600 QVERIFY(object != 0);
2601 QCOMPARE(object->property("readOnlyProperty").toInt(), 20);
2602 QCOMPARE(object->property("writableProperty").toInt(), 50);
2603 QVERIFY(object->setProperty("firstProperty", QVariant(30))); // shouldn't affect value of readOnlyProperty
2604 QVERIFY(object->setProperty("writableProperty", QVariant(30))); // SHOULD affect value of writableProperty
2605 QCOMPARE(object->property("readOnlyProperty").toInt(), 20);
2606 QCOMPARE(object->property("writableProperty").toInt(), 30);
2609 QDeclarativeComponent failOne(&engine, TEST_FILE("moduleApiMajorVersionFail.qml"));
2610 QTest::ignoreMessage(QtWarningMsg, "QDeclarativeComponent: Component is not ready");
2611 object = failOne.create();
2612 QVERIFY(object == 0); // should have failed: invalid major version
2614 QDeclarativeComponent failTwo(&engine, TEST_FILE("moduleApiMinorVersionFail.qml"));
2615 QTest::ignoreMessage(QtWarningMsg, "QDeclarativeComponent: Component is not ready");
2616 object = failTwo.create();
2617 QVERIFY(object == 0); // should have failed: invalid minor version
2620 void tst_qdeclarativeecmascript::importScripts()
2622 QObject *object = 0;
2624 // first, ensure that the required behaviour works.
2625 QDeclarativeComponent component(&engine, TEST_FILE("jsimport/testImport.qml"));
2626 object = component.create();
2627 QVERIFY(object != 0);
2628 QCOMPARE(object->property("importedScriptStringValue"), QVariant(QString(QLatin1String("Hello, World!"))));
2629 QCOMPARE(object->property("importedScriptFunctionValue"), QVariant(20));
2630 QCOMPARE(object->property("importedModuleAttachedPropertyValue"), QVariant(19));
2631 QCOMPARE(object->property("importedModuleEnumValue"), QVariant(2));
2634 QDeclarativeComponent componentTwo(&engine, TEST_FILE("jsimport/testImportScoping.qml"));
2635 object = componentTwo.create();
2636 QVERIFY(object != 0);
2637 QCOMPARE(object->property("componentError"), QVariant(5));
2640 // then, ensure that unintended behaviour does not work.
2641 QDeclarativeComponent failOneComponent(&engine, TEST_FILE("jsimportfail/failOne.qml"));
2642 QString expectedWarning = QLatin1String("file://") + TEST_FILE("jsimportfail/failOne.qml").toLocalFile() + QLatin1String(":6: TypeError: Result of expression 'TestScriptImport.ImportOneJs' [undefined] is not an object.");
2643 QTest::ignoreMessage(QtWarningMsg, expectedWarning.toAscii().constData());
2644 object = failOneComponent.create();
2645 QVERIFY(object != 0);
2646 QVERIFY(object->property("importScriptFunctionValue").toString().isEmpty());
2648 QDeclarativeComponent failTwoComponent(&engine, TEST_FILE("jsimportfail/failTwo.qml"));
2649 expectedWarning = QLatin1String("file://") + TEST_FILE("jsimportfail/failTwo.qml").toLocalFile() + QLatin1String(":6: ReferenceError: Can't find variable: ImportOneJs");
2650 QTest::ignoreMessage(QtWarningMsg, expectedWarning.toAscii().constData());
2651 object = failTwoComponent.create();
2652 QVERIFY(object != 0);
2653 QVERIFY(object->property("importScriptFunctionValue").toString().isEmpty());
2655 QDeclarativeComponent failThreeComponent(&engine, TEST_FILE("jsimportfail/failThree.qml"));
2656 expectedWarning = QLatin1String("file://") + TEST_FILE("jsimportfail/failThree.qml").toLocalFile() + QLatin1String(":7: TypeError: Result of expression 'testQtObject.TestModuleImport.JsQtTest' [undefined] is not an object.");
2657 QTest::ignoreMessage(QtWarningMsg, expectedWarning.toAscii().constData());
2658 object = failThreeComponent.create();
2659 QVERIFY(object != 0);
2660 QCOMPARE(object->property("importedModuleAttachedPropertyValue"), QVariant(false));
2662 QDeclarativeComponent failFourComponent(&engine, TEST_FILE("jsimportfail/failFour.qml"));
2663 expectedWarning = QLatin1String("file://") + TEST_FILE("jsimportfail/failFour.qml").toLocalFile() + QLatin1String(":6: ReferenceError: Can't find variable: JsQtTest");
2664 QTest::ignoreMessage(QtWarningMsg, expectedWarning.toAscii().constData());
2665 object = failFourComponent.create();
2666 QVERIFY(object != 0);
2667 QCOMPARE(object->property("importedModuleEnumValue"), QVariant(0));
2669 QDeclarativeComponent failFiveComponent(&engine, TEST_FILE("jsimportfail/failFive.qml"));
2670 expectedWarning = QLatin1String("file://") + TEST_FILE("jsimportfail/importWithImports.js").toLocalFile() + QLatin1String(":8: ReferenceError: Can't find variable: Component");
2671 QTest::ignoreMessage(QtWarningMsg, expectedWarning.toAscii().constData());
2672 expectedWarning = QLatin1String("file://") + TEST_FILE("jsimportfail/importPragmaLibrary.js").toLocalFile() + QLatin1String(":6: ReferenceError: Can't find variable: Component");
2673 QTest::ignoreMessage(QtWarningMsg, expectedWarning.toAscii().constData());
2674 object = failFiveComponent.create();
2675 QVERIFY(object != 0);
2676 QCOMPARE(object->property("componentError"), QVariant(0));
2679 // also, test that importing scripts with .pragma library works as required
2680 QDeclarativeComponent pragmaLibraryComponent(&engine, TEST_FILE("jsimport/testImportPragmaLibrary.qml"));
2681 object = pragmaLibraryComponent.create();
2682 QVERIFY(object != 0);
2683 QCOMPARE(object->property("testValue"), QVariant(31));
2686 // and that .pragma library scripts don't inherit imports from any .qml file
2687 QDeclarativeComponent pragmaLibraryComponentTwo(&engine, TEST_FILE("jsimportfail/testImportPragmaLibrary.qml"));
2688 object = pragmaLibraryComponentTwo.create();
2689 QVERIFY(object != 0);
2690 QCOMPARE(object->property("testValue"), QVariant(0));
2694 void tst_qdeclarativeecmascript::scarceResources()
2696 QPixmap origPixmap(100, 100);
2697 origPixmap.fill(Qt::blue);
2699 QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(&engine);
2700 ScarceResourceObject *eo = 0;
2701 QObject *object = 0;
2703 // in the following three cases, the instance created from the component
2704 // has a property which is a copy of the scarce resource; hence, the
2705 // resource should NOT be detached prior to deletion of the object instance,
2706 // unless the resource is destroyed explicitly.
2707 QDeclarativeComponent component(&engine, TEST_FILE("scarceresources/scarceResourceCopy.qml"));
2708 object = component.create();
2709 QVERIFY(object != 0);
2710 QVERIFY(object->property("scarceResourceCopy").isValid());
2711 QCOMPARE(object->property("scarceResourceCopy").value<QPixmap>(), origPixmap);
2712 QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
2713 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2714 QVERIFY(!eo->scarceResourceIsDetached()); // there are two copies of it in existence: the property of object, and the property of eo.
2717 QDeclarativeComponent componentTwo(&engine, TEST_FILE("scarceresources/scarceResourceCopyFromJs.qml"));
2718 object = componentTwo.create();
2719 QVERIFY(object != 0);
2720 QVERIFY(object->property("scarceResourceCopy").isValid());
2721 QCOMPARE(object->property("scarceResourceCopy").value<QPixmap>(), origPixmap);
2722 QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
2723 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2724 QVERIFY(!eo->scarceResourceIsDetached()); // there are two copies of it in existence: the property of object, and the property of eo.
2727 QDeclarativeComponent componentThree(&engine, TEST_FILE("scarceresources/scarceResourceDestroyedCopy.qml"));
2728 object = componentThree.create();
2729 QVERIFY(object != 0);
2730 QVERIFY(!(object->property("scarceResourceCopy").isValid())); // was manually released prior to being returned.
2731 QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
2732 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2733 QVERIFY(eo->scarceResourceIsDetached()); // should have explicitly been released during the evaluation of the binding.
2736 // in the following three cases, no other copy should exist in memory,
2737 // and so it should be detached (unless explicitly preserved).
2738 QDeclarativeComponent componentFour(&engine, TEST_FILE("scarceresources/scarceResourceTest.qml"));
2739 object = componentFour.create();
2740 QVERIFY(object != 0);
2741 QVERIFY(object->property("scarceResourceTest").isValid());
2742 QCOMPARE(object->property("scarceResourceTest").toInt(), 100);
2743 QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
2744 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2745 QVERIFY(eo->scarceResourceIsDetached()); // the resource should have been released after the binding was evaluated.
2748 QDeclarativeComponent componentFive(&engine, TEST_FILE("scarceresources/scarceResourceTestPreserve.qml"));
2749 object = componentFive.create();
2750 QVERIFY(object != 0);
2751 QVERIFY(object->property("scarceResourceTest").isValid());
2752 QCOMPARE(object->property("scarceResourceTest").toInt(), 100);
2753 QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
2754 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2755 QVERIFY(!eo->scarceResourceIsDetached()); // this won't be detached since we explicitly preserved it.
2758 QDeclarativeComponent componentSix(&engine, TEST_FILE("scarceresources/scarceResourceTestMultiple.qml"));
2759 object = componentSix.create();
2760 QVERIFY(object != 0);
2761 QVERIFY(object->property("scarceResourceTest").isValid());
2762 QCOMPARE(object->property("scarceResourceTest").toInt(), 100);
2763 QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
2764 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2765 QVERIFY(eo->scarceResourceIsDetached()); // all resources were released manually or automatically released.
2768 // test that scarce resources are handled correctly for imports
2769 QDeclarativeComponent componentSeven(&engine, TEST_FILE("scarceresources/scarceResourceCopyImportNoBinding.qml"));
2770 object = componentSeven.create();
2771 QVERIFY(object != 0); // the import should have caused the addition of a resource to the ScarceResources list
2772 QVERIFY(ep->scarceResources.isEmpty()); // but they should have been released by this point.
2775 QDeclarativeComponent componentEight(&engine, TEST_FILE("scarceresources/scarceResourceCopyImportFail.qml"));
2776 object = componentEight.create();
2777 QVERIFY(object != 0);
2778 QVERIFY(!object->property("scarceResourceCopy").isValid()); // wasn't preserved, so shouldn't be valid.
2779 QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
2782 QDeclarativeComponent componentNine(&engine, TEST_FILE("scarceresources/scarceResourceCopyImport.qml"));
2783 object = componentNine.create();
2784 QVERIFY(object != 0);
2785 QVERIFY(object->property("scarceResourceCopy").isValid()); // preserved, so should be valid.
2786 QCOMPARE(object->property("scarceResourceCopy").value<QPixmap>(), origPixmap);
2787 QVERIFY(object->property("scarceResourceAssignedCopyOne").isValid()); // assigned before destroy(), so should be valid.
2788 QCOMPARE(object->property("scarceResourceAssignedCopyOne").value<QPixmap>(), origPixmap);
2789 QVERIFY(!object->property("scarceResourceAssignedCopyTwo").isValid()); // assigned after destroy(), so should be invalid.
2790 QVERIFY(ep->scarceResources.isEmpty()); // this will still be zero, because "preserve()" REMOVES it from this list.
2793 // test that scarce resources are handled properly in signal invocation
2794 QDeclarativeComponent componentTen(&engine, TEST_FILE("scarceresources/scarceResourceSignal.qml"));
2795 object = componentTen.create();
2796 QVERIFY(object != 0);
2797 QObject *srsc = object->findChild<QObject*>("srsc");
2799 QVERIFY(!srsc->property("scarceResourceCopy").isValid()); // hasn't been instantiated yet.
2800 QCOMPARE(srsc->property("width"), QVariant(5)); // default value is 5.
2801 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2802 QVERIFY(eo->scarceResourceIsDetached()); // should be no other copies of it at this stage.
2803 QMetaObject::invokeMethod(srsc, "testSignal");
2804 QVERIFY(!srsc->property("scarceResourceCopy").isValid()); // still hasn't been instantiated
2805 QCOMPARE(srsc->property("width"), QVariant(10)); // but width was assigned to 10.
2806 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2807 QVERIFY(eo->scarceResourceIsDetached()); // should still be no other copies of it at this stage.
2808 QMetaObject::invokeMethod(srsc, "testSignal2"); // assigns scarceResourceCopy to the scarce pixmap.
2809 QVERIFY(srsc->property("scarceResourceCopy").isValid());
2810 QCOMPARE(srsc->property("scarceResourceCopy").value<QPixmap>(), origPixmap);
2811 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2812 QVERIFY(!(eo->scarceResourceIsDetached())); // should be another copy of the resource now.
2813 QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
2816 // test that scarce resources are handled properly from js functions in qml files
2817 QDeclarativeComponent componentEleven(&engine, TEST_FILE("scarceresources/scarceResourceFunction.qml"));
2818 object = componentEleven.create();
2819 QVERIFY(object != 0);
2820 QVERIFY(!object->property("scarceResourceCopy").isValid()); // not yet assigned, so should not be valid
2821 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2822 QVERIFY(eo->scarceResourceIsDetached()); // should be no other copies of it at this stage.
2823 QMetaObject::invokeMethod(object, "retrieveScarceResource");
2824 QVERIFY(object->property("scarceResourceCopy").isValid()); // assigned, so should be valid.
2825 QCOMPARE(object->property("scarceResourceCopy").value<QPixmap>(), origPixmap);
2826 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2827 QVERIFY(!eo->scarceResourceIsDetached()); // should be a copy of the resource at this stage.
2828 QMetaObject::invokeMethod(object, "releaseScarceResource");
2829 QVERIFY(!object->property("scarceResourceCopy").isValid()); // just released, so should not be valid
2830 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2831 QVERIFY(eo->scarceResourceIsDetached()); // should be no other copies of it at this stage.
2832 QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
2835 // test that if an exception occurs while invoking js function from cpp, that the resources are released.
2836 QDeclarativeComponent componentTwelve(&engine, TEST_FILE("scarceresources/scarceResourceFunctionFail.qml"));
2837 object = componentTwelve.create();
2838 QVERIFY(object != 0);
2839 QVERIFY(!object->property("scarceResourceCopy").isValid()); // not yet assigned, so should not be valid
2840 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2841 QVERIFY(eo->scarceResourceIsDetached()); // should be no other copies of it at this stage.
2842 QString srp_name = object->property("srp_name").toString();
2843 QString expectedWarning = componentTwelve.url().toString() + QLatin1String(":17: TypeError: Property 'scarceResource' of object ") + srp_name + QLatin1String(" is not a function");
2844 QTest::ignoreMessage(QtWarningMsg, qPrintable(expectedWarning)); // we expect a meaningful warning to be printed.
2845 QMetaObject::invokeMethod(object, "retrieveScarceResource");
2846 QVERIFY(!object->property("scarceResourceCopy").isValid()); // due to exception, assignment will NOT have occurred.
2847 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2848 QVERIFY(eo->scarceResourceIsDetached()); // should be no other copies of it at this stage.
2849 QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
2853 void tst_qdeclarativeecmascript::propertyChangeSlots()
2855 // ensure that allowable property names are allowed and onPropertyNameChanged slots are generated correctly.
2856 QDeclarativeComponent component(&engine, TEST_FILE("changeslots/propertyChangeSlots.qml"));
2857 QObject *object = component.create();
2858 QVERIFY(object != 0);
2861 // ensure that invalid property names fail properly.
2862 QTest::ignoreMessage(QtWarningMsg, "QDeclarativeComponent: Component is not ready");
2863 QDeclarativeComponent e1(&engine, TEST_FILE("changeslots/propertyChangeSlotErrors.1.qml"));
2864 QString expectedErrorString = e1.url().toString() + QLatin1String(":9:5: Cannot assign to non-existent property \"on_nameWithUnderscoreChanged\"");
2865 QCOMPARE(e1.errors().at(0).toString(), expectedErrorString);
2866 object = e1.create();
2867 QVERIFY(object == 0);
2870 QTest::ignoreMessage(QtWarningMsg, "QDeclarativeComponent: Component is not ready");
2871 QDeclarativeComponent e2(&engine, TEST_FILE("changeslots/propertyChangeSlotErrors.2.qml"));
2872 expectedErrorString = e2.url().toString() + QLatin1String(":9:5: Cannot assign to non-existent property \"on____nameWithUnderscoresChanged\"");
2873 QCOMPARE(e2.errors().at(0).toString(), expectedErrorString);
2874 object = e2.create();
2875 QVERIFY(object == 0);
2878 QTest::ignoreMessage(QtWarningMsg, "QDeclarativeComponent: Component is not ready");
2879 QDeclarativeComponent e3(&engine, TEST_FILE("changeslots/propertyChangeSlotErrors.3.qml"));
2880 expectedErrorString = e3.url().toString() + QLatin1String(":9:5: Cannot assign to non-existent property \"on$NameWithDollarsignChanged\"");
2881 QCOMPARE(e3.errors().at(0).toString(), expectedErrorString);
2882 object = e3.create();
2883 QVERIFY(object == 0);
2886 QTest::ignoreMessage(QtWarningMsg, "QDeclarativeComponent: Component is not ready");
2887 QDeclarativeComponent e4(&engine, TEST_FILE("changeslots/propertyChangeSlotErrors.4.qml"));
2888 expectedErrorString = e4.url().toString() + QLatin1String(":9:5: Cannot assign to non-existent property \"on_6NameWithUnderscoreNumberChanged\"");
2889 QCOMPARE(e4.errors().at(0).toString(), expectedErrorString);
2890 object = e4.create();
2891 QVERIFY(object == 0);
2895 // Test that assigning a null object works
2896 // Regressed with: df1788b4dbbb2826ae63f26bdf166342595343f4
2897 void tst_qdeclarativeecmascript::nullObjectBinding()
2899 QDeclarativeComponent component(&engine, TEST_FILE("nullObjectBinding.qml"));
2901 QObject *object = component.create();
2902 QVERIFY(object != 0);
2904 QVERIFY(object->property("test") == QVariant::fromValue((QObject *)0));
2909 // Test that bindings don't evaluate once the engine has been destroyed
2910 void tst_qdeclarativeecmascript::deletedEngine()
2912 QDeclarativeEngine *engine = new QDeclarativeEngine;
2913 QDeclarativeComponent component(engine, TEST_FILE("deletedEngine.qml"));
2915 QObject *object = component.create();
2916 QVERIFY(object != 0);
2918 QCOMPARE(object->property("a").toInt(), 39);
2919 object->setProperty("b", QVariant(9));
2920 QCOMPARE(object->property("a").toInt(), 117);
2924 QCOMPARE(object->property("a").toInt(), 117);
2925 object->setProperty("b", QVariant(10));
2926 QCOMPARE(object->property("a").toInt(), 117);
2931 // Test the crashing part of QTBUG-9705
2932 void tst_qdeclarativeecmascript::libraryScriptAssert()
2934 QDeclarativeComponent component(&engine, TEST_FILE("libraryScriptAssert.qml"));
2936 QObject *object = component.create();
2937 QVERIFY(object != 0);
2942 void tst_qdeclarativeecmascript::variantsAssignedUndefined()
2944 QDeclarativeComponent component(&engine, TEST_FILE("variantsAssignedUndefined.qml"));
2946 QObject *object = component.create();
2947 QVERIFY(object != 0);
2949 QCOMPARE(object->property("test1").toInt(), 10);
2950 QCOMPARE(object->property("test2").toInt(), 11);
2952 object->setProperty("runTest", true);
2954 QCOMPARE(object->property("test1"), QVariant());
2955 QCOMPARE(object->property("test2"), QVariant());
2961 void tst_qdeclarativeecmascript::qtbug_9792()
2963 QDeclarativeComponent component(&engine, TEST_FILE("qtbug_9792.qml"));
2965 QDeclarativeContext *context = new QDeclarativeContext(engine.rootContext());
2967 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create(context));
2968 QVERIFY(object != 0);
2970 QTest::ignoreMessage(QtDebugMsg, "Hello world!");
2971 object->basicSignal();
2975 transientErrorsMsgCount = 0;
2976 QtMsgHandler old = qInstallMsgHandler(transientErrorsMsgHandler);
2978 object->basicSignal();
2980 qInstallMsgHandler(old);
2982 QCOMPARE(transientErrorsMsgCount, 0);
2987 // Verifies that QDeclarativeGuard<>s used in the vmemetaobject are cleaned correctly
2988 void tst_qdeclarativeecmascript::qtcreatorbug_1289()
2990 QDeclarativeComponent component(&engine, TEST_FILE("qtcreatorbug_1289.qml"));
2992 QObject *o = component.create();
2995 QObject *nested = qvariant_cast<QObject *>(o->property("object"));
2996 QVERIFY(nested != 0);
2998 QVERIFY(qvariant_cast<QObject *>(nested->property("nestedObject")) == o);
3001 nested = qvariant_cast<QObject *>(o->property("object"));
3002 QVERIFY(nested == 0);
3004 // If the bug is present, the next line will crash
3008 // Test that we shut down without stupid warnings
3009 void tst_qdeclarativeecmascript::noSpuriousWarningsAtShutdown()
3012 QDeclarativeComponent component(&engine, TEST_FILE("noSpuriousWarningsAtShutdown.qml"));
3014 QObject *o = component.create();
3016 transientErrorsMsgCount = 0;
3017 QtMsgHandler old = qInstallMsgHandler(transientErrorsMsgHandler);
3021 qInstallMsgHandler(old);
3023 QCOMPARE(transientErrorsMsgCount, 0);
3028 QDeclarativeComponent component(&engine, TEST_FILE("noSpuriousWarningsAtShutdown.2.qml"));
3030 QObject *o = component.create();
3032 transientErrorsMsgCount = 0;
3033 QtMsgHandler old = qInstallMsgHandler(transientErrorsMsgHandler);
3037 qInstallMsgHandler(old);
3039 QCOMPARE(transientErrorsMsgCount, 0);
3043 void tst_qdeclarativeecmascript::canAssignNullToQObject()
3046 QDeclarativeComponent component(&engine, TEST_FILE("canAssignNullToQObject.1.qml"));
3048 MyQmlObject *o = qobject_cast<MyQmlObject *>(component.create());
3051 QVERIFY(o->objectProperty() != 0);
3053 o->setProperty("runTest", true);
3055 QVERIFY(o->objectProperty() == 0);
3061 QDeclarativeComponent component(&engine, TEST_FILE("canAssignNullToQObject.2.qml"));
3063 MyQmlObject *o = qobject_cast<MyQmlObject *>(component.create());
3066 QVERIFY(o->objectProperty() == 0);
3072 void tst_qdeclarativeecmascript::functionAssignment_fromBinding()
3074 QDeclarativeComponent component(&engine, TEST_FILE("functionAssignment.1.qml"));
3076 QString url = component.url().toString();
3077 QString warning = url + ":4: Unable to assign a function to a property.";
3078 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
3080 MyQmlObject *o = qobject_cast<MyQmlObject *>(component.create());
3083 QVERIFY(!o->property("a").isValid());
3088 void tst_qdeclarativeecmascript::functionAssignment_fromJS()
3090 QFETCH(QString, triggerProperty);
3092 QDeclarativeComponent component(&engine, TEST_FILE("functionAssignment.2.qml"));
3093 QVERIFY2(component.errorString().isEmpty(), qPrintable(component.errorString()));
3095 MyQmlObject *o = qobject_cast<MyQmlObject *>(component.create());
3097 QVERIFY(!o->property("a").isValid());
3099 o->setProperty("aNumber", QVariant(5));
3100 o->setProperty(triggerProperty.toUtf8().constData(), true);
3101 QCOMPARE(o->property("a"), QVariant(50));
3103 o->setProperty("aNumber", QVariant(10));
3104 QCOMPARE(o->property("a"), QVariant(100));
3109 void tst_qdeclarativeecmascript::functionAssignment_fromJS_data()
3111 QTest::addColumn<QString>("triggerProperty");
3113 QTest::newRow("assign to property") << "assignToProperty";
3114 QTest::newRow("assign to property, from JS file") << "assignToPropertyFromJsFile";
3116 QTest::newRow("assign to value type") << "assignToValueType";
3118 QTest::newRow("use 'this'") << "assignWithThis";
3119 QTest::newRow("use 'this' from JS file") << "assignWithThisFromJsFile";
3122 void tst_qdeclarativeecmascript::functionAssignmentfromJS_invalid()
3124 QDeclarativeComponent component(&engine, TEST_FILE("functionAssignment.2.qml"));
3125 QVERIFY2(component.errorString().isEmpty(), qPrintable(component.errorString()));
3127 MyQmlObject *o = qobject_cast<MyQmlObject *>(component.create());
3129 QVERIFY(!o->property("a").isValid());
3131 o->setProperty("assignFuncWithoutReturn", true);
3132 QVERIFY(!o->property("a").isValid());
3134 QString url = component.url().toString();
3135 QString warning = url + ":67: Unable to assign QString to int";
3136 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
3137 o->setProperty("assignWrongType", true);
3139 warning = url + ":71: Unable to assign QString to int";
3140 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
3141 o->setProperty("assignWrongTypeToValueType", true);
3146 void tst_qdeclarativeecmascript::eval()
3148 QDeclarativeComponent component(&engine, TEST_FILE("eval.qml"));
3150 QObject *o = component.create();
3153 QCOMPARE(o->property("test1").toBool(), true);
3154 QCOMPARE(o->property("test2").toBool(), true);
3155 QCOMPARE(o->property("test3").toBool(), true);
3156 QCOMPARE(o->property("test4").toBool(), true);
3157 QCOMPARE(o->property("test5").toBool(), true);
3162 void tst_qdeclarativeecmascript::function()
3164 QDeclarativeComponent component(&engine, TEST_FILE("function.qml"));
3166 QObject *o = component.create();
3169 QCOMPARE(o->property("test1").toBool(), true);
3170 QCOMPARE(o->property("test2").toBool(), true);
3171 QCOMPARE(o->property("test3").toBool(), true);
3176 // Test the "Qt.include" method
3177 void tst_qdeclarativeecmascript::include()
3179 // Non-library relative include
3181 QDeclarativeComponent component(&engine, TEST_FILE("include.qml"));
3182 QObject *o = component.create();
3185 QCOMPARE(o->property("test0").toInt(), 99);
3186 QCOMPARE(o->property("test1").toBool(), true);
3187 QCOMPARE(o->property("test2").toBool(), true);
3188 QCOMPARE(o->property("test2_1").toBool(), true);
3189 QCOMPARE(o->property("test3").toBool(), true);
3190 QCOMPARE(o->property("test3_1").toBool(), true);
3195 // Library relative include
3197 QDeclarativeComponent component(&engine, TEST_FILE("include_shared.qml"));
3198 QObject *o = component.create();
3201 QCOMPARE(o->property("test0").toInt(), 99);
3202 QCOMPARE(o->property("test1").toBool(), true);
3203 QCOMPARE(o->property("test2").toBool(), true);
3204 QCOMPARE(o->property("test2_1").toBool(), true);
3205 QCOMPARE(o->property("test3").toBool(), true);
3206 QCOMPARE(o->property("test3_1").toBool(), true);
3213 QDeclarativeComponent component(&engine, TEST_FILE("include_callback.qml"));
3214 QObject *o = component.create();
3217 QCOMPARE(o->property("test1").toBool(), true);
3218 QCOMPARE(o->property("test2").toBool(), true);
3219 QCOMPARE(o->property("test3").toBool(), true);
3220 QCOMPARE(o->property("test4").toBool(), true);
3221 QCOMPARE(o->property("test5").toBool(), true);
3222 QCOMPARE(o->property("test6").toBool(), true);
3227 // Including file with ".pragma library"
3229 QDeclarativeComponent component(&engine, TEST_FILE("include_pragma.qml"));
3230 QObject *o = component.create();
3232 QCOMPARE(o->property("test1").toInt(), 100);
3239 TestHTTPServer server(8111);
3240 QVERIFY(server.isValid());
3241 server.serveDirectory(SRCDIR "/data");
3243 QDeclarativeComponent component(&engine, TEST_FILE("include_remote.qml"));
3244 QObject *o = component.create();
3247 QTRY_VERIFY(o->property("done").toBool() == true);
3248 QTRY_VERIFY(o->property("done2").toBool() == true);
3250 QCOMPARE(o->property("test1").toBool(), true);
3251 QCOMPARE(o->property("test2").toBool(), true);
3252 QCOMPARE(o->property("test3").toBool(), true);
3253 QCOMPARE(o->property("test4").toBool(), true);
3254 QCOMPARE(o->property("test5").toBool(), true);
3256 QCOMPARE(o->property("test6").toBool(), true);
3257 QCOMPARE(o->property("test7").toBool(), true);
3258 QCOMPARE(o->property("test8").toBool(), true);
3259 QCOMPARE(o->property("test9").toBool(), true);
3260 QCOMPARE(o->property("test10").toBool(), true);
3267 TestHTTPServer server(8111);
3268 QVERIFY(server.isValid());
3269 server.serveDirectory(SRCDIR "/data");
3271 QDeclarativeComponent component(&engine, TEST_FILE("include_remote_missing.qml"));
3272 QObject *o = component.create();
3275 QTRY_VERIFY(o->property("done").toBool() == true);
3277 QCOMPARE(o->property("test1").toBool(), true);
3278 QCOMPARE(o->property("test2").toBool(), true);
3279 QCOMPARE(o->property("test3").toBool(), true);
3285 void tst_qdeclarativeecmascript::qtbug_10696()
3287 QDeclarativeComponent component(&engine, TEST_FILE("qtbug_10696.qml"));
3288 QObject *o = component.create();
3293 void tst_qdeclarativeecmascript::qtbug_11606()
3295 QDeclarativeComponent component(&engine, TEST_FILE("qtbug_11606.qml"));
3296 QObject *o = component.create();
3298 QCOMPARE(o->property("test").toBool(), true);
3302 void tst_qdeclarativeecmascript::qtbug_11600()
3304 QDeclarativeComponent component(&engine, TEST_FILE("qtbug_11600.qml"));
3305 QObject *o = component.create();
3307 QCOMPARE(o->property("test").toBool(), true);
3311 // Reading and writing non-scriptable properties should fail
3312 void tst_qdeclarativeecmascript::nonscriptable()
3314 QDeclarativeComponent component(&engine, TEST_FILE("nonscriptable.qml"));
3315 QObject *o = component.create();
3317 QCOMPARE(o->property("readOk").toBool(), true);
3318 QCOMPARE(o->property("writeOk").toBool(), true);
3322 // deleteLater() should not be callable from QML
3323 void tst_qdeclarativeecmascript::deleteLater()
3325 QDeclarativeComponent component(&engine, TEST_FILE("deleteLater.qml"));
3326 QObject *o = component.create();
3328 QCOMPARE(o->property("test").toBool(), true);
3332 void tst_qdeclarativeecmascript::in()
3334 QDeclarativeComponent component(&engine, TEST_FILE("in.qml"));
3335 QObject *o = component.create();
3337 QCOMPARE(o->property("test1").toBool(), true);
3338 QCOMPARE(o->property("test2").toBool(), true);
3342 void tst_qdeclarativeecmascript::sharedAttachedObject()
3344 QDeclarativeComponent component(&engine, TEST_FILE("sharedAttachedObject.qml"));
3345 QObject *o = component.create();
3347 QCOMPARE(o->property("test1").toBool(), true);
3348 QCOMPARE(o->property("test2").toBool(), true);
3353 void tst_qdeclarativeecmascript::objectName()
3355 QDeclarativeComponent component(&engine, TEST_FILE("objectName.qml"));
3356 QObject *o = component.create();
3359 QCOMPARE(o->property("test1").toString(), QString("hello"));
3360 QCOMPARE(o->property("test2").toString(), QString("ell"));
3362 o->setObjectName("world");
3364 QCOMPARE(o->property("test1").toString(), QString("world"));
3365 QCOMPARE(o->property("test2").toString(), QString("orl"));
3370 void tst_qdeclarativeecmascript::writeRemovesBinding()
3372 QDeclarativeComponent component(&engine, TEST_FILE("writeRemovesBinding.qml"));
3373 QObject *o = component.create();
3376 QCOMPARE(o->property("test").toBool(), true);
3381 // Test bindings assigned to alias properties actually assign to the alias' target
3382 void tst_qdeclarativeecmascript::aliasBindingsAssignCorrectly()
3384 QDeclarativeComponent component(&engine, TEST_FILE("aliasBindingsAssignCorrectly.qml"));
3385 QObject *o = component.create();
3388 QCOMPARE(o->property("test").toBool(), true);
3393 // Test bindings assigned to alias properties override a binding on the target (QTBUG-13719)
3394 void tst_qdeclarativeecmascript::aliasBindingsOverrideTarget()
3397 QDeclarativeComponent component(&engine, TEST_FILE("aliasBindingsOverrideTarget.qml"));
3398 QObject *o = component.create();
3401 QCOMPARE(o->property("test").toBool(), true);
3407 QDeclarativeComponent component(&engine, TEST_FILE("aliasBindingsOverrideTarget.2.qml"));
3408 QObject *o = component.create();
3411 QCOMPARE(o->property("test").toBool(), true);
3417 QDeclarativeComponent component(&engine, TEST_FILE("aliasBindingsOverrideTarget.3.qml"));
3418 QObject *o = component.create();
3421 QCOMPARE(o->property("test").toBool(), true);
3427 // Test that writes to alias properties override bindings on the alias target (QTBUG-13719)
3428 void tst_qdeclarativeecmascript::aliasWritesOverrideBindings()
3431 QDeclarativeComponent component(&engine, TEST_FILE("aliasWritesOverrideBindings.qml"));
3432 QObject *o = component.create();
3435 QCOMPARE(o->property("test").toBool(), true);
3441 QDeclarativeComponent component(&engine, TEST_FILE("aliasWritesOverrideBindings.2.qml"));
3442 QObject *o = component.create();
3445 QCOMPARE(o->property("test").toBool(), true);
3451 QDeclarativeComponent component(&engine, TEST_FILE("aliasWritesOverrideBindings.3.qml"));
3452 QObject *o = component.create();
3455 QCOMPARE(o->property("test").toBool(), true);
3461 void tst_qdeclarativeecmascript::revisionErrors()
3464 QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevisionErrors.qml"));
3465 QString url = component.url().toString();
3467 QString warning1 = url + ":8: ReferenceError: Can't find variable: prop2";
3468 QString warning2 = url + ":11: ReferenceError: Can't find variable: prop2";
3469 QString warning3 = url + ":13: ReferenceError: Can't find variable: method2";
3471 QTest::ignoreMessage(QtWarningMsg, warning1.toLatin1().constData());
3472 QTest::ignoreMessage(QtWarningMsg, warning2.toLatin1().constData());
3473 QTest::ignoreMessage(QtWarningMsg, warning3.toLatin1().constData());
3474 MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create());
3475 QVERIFY(object != 0);
3479 QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevisionErrors2.qml"));
3480 QString url = component.url().toString();
3482 // MyRevisionedSubclass 1.0 uses MyRevisionedClass revision 0
3483 // method2, prop2 from MyRevisionedClass not available
3484 // method4, prop4 from MyRevisionedSubclass not available
3485 QString warning1 = url + ":8: ReferenceError: Can't find variable: prop2";
3486 QString warning2 = url + ":14: ReferenceError: Can't find variable: prop2";
3487 QString warning3 = url + ":10: ReferenceError: Can't find variable: prop4";
3488 QString warning4 = url + ":16: ReferenceError: Can't find variable: prop4";
3489 QString warning5 = url + ":20: ReferenceError: Can't find variable: method2";
3491 QTest::ignoreMessage(QtWarningMsg, warning1.toLatin1().constData());
3492 QTest::ignoreMessage(QtWarningMsg, warning2.toLatin1().constData());
3493 QTest::ignoreMessage(QtWarningMsg, warning3.toLatin1().constData());
3494 QTest::ignoreMessage(QtWarningMsg, warning4.toLatin1().constData());
3495 QTest::ignoreMessage(QtWarningMsg, warning5.toLatin1().constData());
3496 MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create());
3497 QVERIFY(object != 0);
3501 QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevisionErrors3.qml"));
3502 QString url = component.url().toString();
3504 // MyRevisionedSubclass 1.1 uses MyRevisionedClass revision 1
3505 // All properties/methods available, except MyRevisionedBaseClassUnregistered rev 1
3506 QString warning1 = url + ":30: ReferenceError: Can't find variable: methodD";
3507 QString warning2 = url + ":10: ReferenceError: Can't find variable: propD";
3508 QString warning3 = url + ":20: ReferenceError: Can't find variable: propD";
3509 QTest::ignoreMessage(QtWarningMsg, warning1.toLatin1().constData());
3510 QTest::ignoreMessage(QtWarningMsg, warning2.toLatin1().constData());
3511 QTest::ignoreMessage(QtWarningMsg, warning3.toLatin1().constData());
3512 MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create());
3513 QVERIFY(object != 0);
3518 void tst_qdeclarativeecmascript::revision()
3521 QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevision.qml"));
3522 QString url = component.url().toString();
3524 MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create());
3525 QVERIFY(object != 0);
3529 QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevision2.qml"));
3530 QString url = component.url().toString();
3532 MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create());
3533 QVERIFY(object != 0);
3537 QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevision3.qml"));
3538 QString url = component.url().toString();
3540 MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create());
3541 QVERIFY(object != 0);
3544 // Test that non-root classes can resolve revisioned methods
3546 QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevision4.qml"));
3548 QObject *object = component.create();
3549 QVERIFY(object != 0);
3550 QCOMPARE(object->property("test").toReal(), 11.);
3555 void tst_qdeclarativeecmascript::realToInt()
3557 QDeclarativeComponent component(&engine, TEST_FILE("realToInt.qml"));
3558 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
3559 QVERIFY(object != 0);
3561 QMetaObject::invokeMethod(object, "test1");
3562 QCOMPARE(object->value(), int(4));
3563 QMetaObject::invokeMethod(object, "test2");
3564 QCOMPARE(object->value(), int(8));
3567 QTEST_MAIN(tst_qdeclarativeecmascript)
3569 #include "tst_qdeclarativeecmascript.moc"