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 ** No Commercial Usage
11 ** This file contains pre-release code and may not be distributed.
12 ** You may use this file in accordance with the terms and conditions
13 ** contained in the Technology Preview License Agreement accompanying
16 ** GNU Lesser General Public License Usage
17 ** Alternatively, this file may be used under the terms of the GNU Lesser
18 ** General Public License version 2.1 as published by the Free Software
19 ** Foundation and appearing in the file LICENSE.LGPL included in the
20 ** packaging of this file. Please review the following information to
21 ** ensure the GNU Lesser General Public License version 2.1 requirements
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 ** In addition, as a special exception, Nokia gives you certain additional
25 ** rights. These rights are described in the Nokia Qt LGPL Exception
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at qt-info@nokia.com.
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/qdeclarativeglobalscriptclass_p.h>
53 #include <private/qscriptdeclarativeclass_p.h>
54 #include "testtypes.h"
55 #include "testhttpserver.h"
56 #include "../../../shared/util.h"
59 // In Symbian OS test data is located in applications private dir
64 This test covers evaluation of ECMAScript expressions and bindings from within
65 QML. This does not include static QML language issues.
67 Static QML language issues are covered in qmllanguage
69 inline QUrl TEST_FILE(const QString &filename)
71 QFileInfo fileInfo(__FILE__);
72 return QUrl::fromLocalFile(fileInfo.absoluteDir().filePath("data/" + filename));
75 inline QUrl TEST_FILE(const char *filename)
77 return TEST_FILE(QLatin1String(filename));
80 class tst_qdeclarativeecmascript : public QObject
84 tst_qdeclarativeecmascript() {}
88 void assignBasicTypes();
89 void idShortcutInvalidates();
90 void boolPropertiesEvaluateAsBool();
92 void signalAssignment();
94 void basicExpressions();
95 void basicExpressions_data();
96 void arrayExpressions();
97 void contextPropertiesTriggerReeval();
98 void objectPropertiesTriggerReeval();
99 void deferredProperties();
100 void deferredPropertiesErrors();
101 void extensionObjects();
102 void overrideExtensionProperties();
103 void attachedProperties();
105 void valueTypeFunctions();
106 void constantsOverrideBindings();
107 void outerBindingOverridesInnerBinding();
108 void aliasPropertyAndBinding();
109 void nonExistentAttachedObject();
111 void signalParameterTypes();
112 void objectsCompareAsEqual();
113 void dynamicCreation_data();
114 void dynamicCreation();
115 void dynamicDestruction();
116 void objectToString();
117 void selfDeletingBinding();
118 void extendedObjectPropertyLookup();
120 void functionErrors();
121 void propertyAssignmentErrors();
122 void signalTriggeredBindings();
123 void listProperties();
124 void exceptionClearsOnReeval();
125 void exceptionSlotProducesWarning();
126 void exceptionBindingProducesWarning();
127 void transientErrors();
128 void shutdownErrors();
129 void compositePropertyType();
131 void undefinedResetsProperty();
132 void listToVariant();
133 void multiEngineObject();
134 void deletedObject();
135 void attachedPropertyScope();
136 void scriptConnect();
137 void scriptDisconnect();
139 void cppOwnershipReturnValue();
140 void ownershipCustomReturnValue();
141 void qlistqobjectMethods();
142 void strictlyEquals();
144 void numberAssignment();
145 void propertySplicing();
146 void signalWithUnknownTypes();
148 void importScripts();
149 void scarceResources();
150 void propertyChangeSlots();
154 void dynamicCreationCrash();
156 void nullObjectBinding();
157 void deletedEngine();
158 void libraryScriptAssert();
159 void variantsAssignedUndefined();
161 void qtcreatorbug_1289();
162 void noSpuriousWarningsAtShutdown();
163 void canAssignNullToQObject();
164 void functionAssignment_fromBinding();
165 void functionAssignment_fromJS();
166 void functionAssignment_fromJS_data();
167 void functionAssignmentfromJS_invalid();
173 void nonscriptable();
176 void sharedAttachedObject();
178 void writeRemovesBinding();
179 void aliasBindingsAssignCorrectly();
180 void aliasBindingsOverrideTarget();
181 void aliasWritesOverrideBindings();
182 void pushCleanContext();
187 void callQtInvokables();
188 void invokableObjectArg();
189 void invokableObjectRet();
191 void revisionErrors();
194 QDeclarativeEngine engine;
197 void tst_qdeclarativeecmascript::initTestCase() { registerTypes(); }
199 void tst_qdeclarativeecmascript::assignBasicTypes()
202 QDeclarativeComponent component(&engine, TEST_FILE("assignBasicTypes.qml"));
203 MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
204 QVERIFY(object != 0);
205 QCOMPARE(object->flagProperty(), MyTypeObject::FlagVal1 | MyTypeObject::FlagVal3);
206 QCOMPARE(object->enumProperty(), MyTypeObject::EnumVal2);
207 QCOMPARE(object->stringProperty(), QString("Hello World!"));
208 QCOMPARE(object->uintProperty(), uint(10));
209 QCOMPARE(object->intProperty(), -19);
210 QCOMPARE((float)object->realProperty(), float(23.2));
211 QCOMPARE((float)object->doubleProperty(), float(-19.75));
212 QCOMPARE((float)object->floatProperty(), float(8.5));
213 QCOMPARE(object->colorProperty(), QColor("red"));
214 QCOMPARE(object->dateProperty(), QDate(1982, 11, 25));
215 QCOMPARE(object->timeProperty(), QTime(11, 11, 32));
216 QCOMPARE(object->dateTimeProperty(), QDateTime(QDate(2009, 5, 12), QTime(13, 22, 1)));
217 QCOMPARE(object->pointProperty(), QPoint(99,13));
218 QCOMPARE(object->pointFProperty(), QPointF(-10.1, 12.3));
219 QCOMPARE(object->sizeProperty(), QSize(99, 13));
220 QCOMPARE(object->sizeFProperty(), QSizeF(0.1, 0.2));
221 QCOMPARE(object->rectProperty(), QRect(9, 7, 100, 200));
222 QCOMPARE(object->rectFProperty(), QRectF(1000.1, -10.9, 400, 90.99));
223 QCOMPARE(object->boolProperty(), true);
224 QCOMPARE(object->variantProperty(), QVariant("Hello World!"));
225 QCOMPARE(object->vectorProperty(), QVector3D(10, 1, 2.2));
226 QCOMPARE(object->urlProperty(), component.url().resolved(QUrl("main.qml")));
230 QDeclarativeComponent component(&engine, TEST_FILE("assignBasicTypes.2.qml"));
231 MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
232 QVERIFY(object != 0);
233 QCOMPARE(object->flagProperty(), MyTypeObject::FlagVal1 | MyTypeObject::FlagVal3);
234 QCOMPARE(object->enumProperty(), MyTypeObject::EnumVal2);
235 QCOMPARE(object->stringProperty(), QString("Hello World!"));
236 QCOMPARE(object->uintProperty(), uint(10));
237 QCOMPARE(object->intProperty(), -19);
238 QCOMPARE((float)object->realProperty(), float(23.2));
239 QCOMPARE((float)object->doubleProperty(), float(-19.75));
240 QCOMPARE((float)object->floatProperty(), float(8.5));
241 QCOMPARE(object->colorProperty(), QColor("red"));
242 QCOMPARE(object->dateProperty(), QDate(1982, 11, 25));
243 QCOMPARE(object->timeProperty(), QTime(11, 11, 32));
244 QCOMPARE(object->dateTimeProperty(), QDateTime(QDate(2009, 5, 12), QTime(13, 22, 1)));
245 QCOMPARE(object->pointProperty(), QPoint(99,13));
246 QCOMPARE(object->pointFProperty(), QPointF(-10.1, 12.3));
247 QCOMPARE(object->sizeProperty(), QSize(99, 13));
248 QCOMPARE(object->sizeFProperty(), QSizeF(0.1, 0.2));
249 QCOMPARE(object->rectProperty(), QRect(9, 7, 100, 200));
250 QCOMPARE(object->rectFProperty(), QRectF(1000.1, -10.9, 400, 90.99));
251 QCOMPARE(object->boolProperty(), true);
252 QCOMPARE(object->variantProperty(), QVariant("Hello World!"));
253 QCOMPARE(object->vectorProperty(), QVector3D(10, 1, 2.2));
254 QCOMPARE(object->urlProperty(), component.url().resolved(QUrl("main.qml")));
259 void tst_qdeclarativeecmascript::idShortcutInvalidates()
262 QDeclarativeComponent component(&engine, TEST_FILE("idShortcutInvalidates.qml"));
263 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
264 QVERIFY(object != 0);
265 QVERIFY(object->objectProperty() != 0);
266 delete object->objectProperty();
267 QVERIFY(object->objectProperty() == 0);
272 QDeclarativeComponent component(&engine, TEST_FILE("idShortcutInvalidates.1.qml"));
273 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
274 QVERIFY(object != 0);
275 QVERIFY(object->objectProperty() != 0);
276 delete object->objectProperty();
277 QVERIFY(object->objectProperty() == 0);
282 void tst_qdeclarativeecmascript::boolPropertiesEvaluateAsBool()
285 QDeclarativeComponent component(&engine, TEST_FILE("boolPropertiesEvaluateAsBool.1.qml"));
286 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
287 QVERIFY(object != 0);
288 QCOMPARE(object->stringProperty(), QLatin1String("pass"));
292 QDeclarativeComponent component(&engine, TEST_FILE("boolPropertiesEvaluateAsBool.2.qml"));
293 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
294 QVERIFY(object != 0);
295 QCOMPARE(object->stringProperty(), QLatin1String("pass"));
300 void tst_qdeclarativeecmascript::signalAssignment()
303 QDeclarativeComponent component(&engine, TEST_FILE("signalAssignment.1.qml"));
304 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
305 QVERIFY(object != 0);
306 QCOMPARE(object->string(), QString());
307 emit object->basicSignal();
308 QCOMPARE(object->string(), QString("pass"));
313 QDeclarativeComponent component(&engine, TEST_FILE("signalAssignment.2.qml"));
314 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
315 QVERIFY(object != 0);
316 QCOMPARE(object->string(), QString());
317 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
318 QCOMPARE(object->string(), QString("pass 19 Hello world! 10.25 3 2"));
323 void tst_qdeclarativeecmascript::methods()
326 QDeclarativeComponent component(&engine, TEST_FILE("methods.1.qml"));
327 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
328 QVERIFY(object != 0);
329 QCOMPARE(object->methodCalled(), false);
330 QCOMPARE(object->methodIntCalled(), false);
331 emit object->basicSignal();
332 QCOMPARE(object->methodCalled(), true);
333 QCOMPARE(object->methodIntCalled(), false);
338 QDeclarativeComponent component(&engine, TEST_FILE("methods.2.qml"));
339 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
340 QVERIFY(object != 0);
341 QCOMPARE(object->methodCalled(), false);
342 QCOMPARE(object->methodIntCalled(), false);
343 emit object->basicSignal();
344 QCOMPARE(object->methodCalled(), false);
345 QCOMPARE(object->methodIntCalled(), true);
350 QDeclarativeComponent component(&engine, TEST_FILE("methods.3.qml"));
351 QObject *object = component.create();
352 QVERIFY(object != 0);
353 QCOMPARE(object->property("test").toInt(), 19);
358 QDeclarativeComponent component(&engine, TEST_FILE("methods.4.qml"));
359 QObject *object = component.create();
360 QVERIFY(object != 0);
361 QCOMPARE(object->property("test").toInt(), 19);
362 QCOMPARE(object->property("test2").toInt(), 17);
363 QCOMPARE(object->property("test3").toInt(), 16);
368 QDeclarativeComponent component(&engine, TEST_FILE("methods.5.qml"));
369 QObject *object = component.create();
370 QVERIFY(object != 0);
371 QCOMPARE(object->property("test").toInt(), 9);
376 void tst_qdeclarativeecmascript::bindingLoop()
378 QDeclarativeComponent component(&engine, TEST_FILE("bindingLoop.qml"));
379 QString warning = component.url().toString() + ":9:9: QML MyQmlObject: Binding loop detected for property \"stringProperty\"";
380 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
381 QObject *object = component.create();
382 QVERIFY(object != 0);
386 void tst_qdeclarativeecmascript::basicExpressions_data()
388 QTest::addColumn<QString>("expression");
389 QTest::addColumn<QVariant>("result");
390 QTest::addColumn<bool>("nest");
392 QTest::newRow("Syntax error (self test)") << "{console.log({'a':1'}.a)}" << QVariant() << false;
393 QTest::newRow("Context property") << "a" << QVariant(1944) << false;
394 QTest::newRow("Context property") << "a" << QVariant(1944) << true;
395 QTest::newRow("Context property expression") << "a * 2" << QVariant(3888) << false;
396 QTest::newRow("Context property expression") << "a * 2" << QVariant(3888) << true;
397 QTest::newRow("Overridden context property") << "b" << QVariant("Milk") << false;
398 QTest::newRow("Overridden context property") << "b" << QVariant("Cow") << true;
399 QTest::newRow("Object property") << "object.stringProperty" << QVariant("Object1") << false;
400 QTest::newRow("Object property") << "object.stringProperty" << QVariant("Object1") << true;
401 QTest::newRow("Overridden object property") << "objectOverride.stringProperty" << QVariant("Object2") << false;
402 QTest::newRow("Overridden object property") << "objectOverride.stringProperty" << QVariant("Object3") << true;
403 QTest::newRow("Default object property") << "horseLegs" << QVariant(4) << false;
404 QTest::newRow("Default object property") << "antLegs" << QVariant(6) << false;
405 QTest::newRow("Default object property") << "emuLegs" << QVariant(2) << false;
406 QTest::newRow("Nested default object property") << "horseLegs" << QVariant(4) << true;
407 QTest::newRow("Nested default object property") << "antLegs" << QVariant(7) << true;
408 QTest::newRow("Nested default object property") << "emuLegs" << QVariant(2) << true;
409 QTest::newRow("Nested default object property") << "humanLegs" << QVariant(2) << true;
410 QTest::newRow("Context property override default object property") << "millipedeLegs" << QVariant(100) << true;
413 void tst_qdeclarativeecmascript::basicExpressions()
415 QFETCH(QString, expression);
416 QFETCH(QVariant, result);
422 MyDefaultObject1 default1;
423 MyDefaultObject3 default3;
424 object1.setStringProperty("Object1");
425 object2.setStringProperty("Object2");
426 object3.setStringProperty("Object3");
428 QDeclarativeContext context(engine.rootContext());
429 QDeclarativeContext nestedContext(&context);
431 context.setContextObject(&default1);
432 context.setContextProperty("a", QVariant(1944));
433 context.setContextProperty("b", QVariant("Milk"));
434 context.setContextProperty("object", &object1);
435 context.setContextProperty("objectOverride", &object2);
436 nestedContext.setContextObject(&default3);
437 nestedContext.setContextProperty("b", QVariant("Cow"));
438 nestedContext.setContextProperty("objectOverride", &object3);
439 nestedContext.setContextProperty("millipedeLegs", QVariant(100));
441 MyExpression expr(nest?&nestedContext:&context, expression);
442 QCOMPARE(expr.evaluate(), result);
445 void tst_qdeclarativeecmascript::arrayExpressions()
451 QDeclarativeContext context(engine.rootContext());
452 context.setContextProperty("a", &obj1);
453 context.setContextProperty("b", &obj2);
454 context.setContextProperty("c", &obj3);
456 MyExpression expr(&context, "[a, b, c, 10]");
457 QVariant result = expr.evaluate();
458 QCOMPARE(result.userType(), qMetaTypeId<QList<QObject *> >());
459 QList<QObject *> list = qvariant_cast<QList<QObject *> >(result);
460 QCOMPARE(list.count(), 4);
461 QCOMPARE(list.at(0), &obj1);
462 QCOMPARE(list.at(1), &obj2);
463 QCOMPARE(list.at(2), &obj3);
464 QCOMPARE(list.at(3), (QObject *)0);
467 // Tests that modifying a context property will reevaluate expressions
468 void tst_qdeclarativeecmascript::contextPropertiesTriggerReeval()
470 QDeclarativeContext context(engine.rootContext());
473 MyQmlObject *object3 = new MyQmlObject;
475 object1.setStringProperty("Hello");
476 object2.setStringProperty("World");
478 context.setContextProperty("testProp", QVariant(1));
479 context.setContextProperty("testObj", &object1);
480 context.setContextProperty("testObj2", object3);
483 MyExpression expr(&context, "testProp + 1");
484 QCOMPARE(expr.changed, false);
485 QCOMPARE(expr.evaluate(), QVariant(2));
487 context.setContextProperty("testProp", QVariant(2));
488 QCOMPARE(expr.changed, true);
489 QCOMPARE(expr.evaluate(), QVariant(3));
493 MyExpression expr(&context, "testProp + testProp + testProp");
494 QCOMPARE(expr.changed, false);
495 QCOMPARE(expr.evaluate(), QVariant(6));
497 context.setContextProperty("testProp", QVariant(4));
498 QCOMPARE(expr.changed, true);
499 QCOMPARE(expr.evaluate(), QVariant(12));
503 MyExpression expr(&context, "testObj.stringProperty");
504 QCOMPARE(expr.changed, false);
505 QCOMPARE(expr.evaluate(), QVariant("Hello"));
507 context.setContextProperty("testObj", &object2);
508 QCOMPARE(expr.changed, true);
509 QCOMPARE(expr.evaluate(), QVariant("World"));
513 MyExpression expr(&context, "testObj.stringProperty /**/");
514 QCOMPARE(expr.changed, false);
515 QCOMPARE(expr.evaluate(), QVariant("World"));
517 context.setContextProperty("testObj", &object1);
518 QCOMPARE(expr.changed, true);
519 QCOMPARE(expr.evaluate(), QVariant("Hello"));
523 MyExpression expr(&context, "testObj2");
524 QCOMPARE(expr.changed, false);
525 QCOMPARE(expr.evaluate(), QVariant::fromValue((QObject *)object3));
531 void tst_qdeclarativeecmascript::objectPropertiesTriggerReeval()
533 QDeclarativeContext context(engine.rootContext());
537 context.setContextProperty("testObj", &object1);
539 object1.setStringProperty(QLatin1String("Hello"));
540 object2.setStringProperty(QLatin1String("Dog"));
541 object3.setStringProperty(QLatin1String("Cat"));
544 MyExpression expr(&context, "testObj.stringProperty");
545 QCOMPARE(expr.changed, false);
546 QCOMPARE(expr.evaluate(), QVariant("Hello"));
548 object1.setStringProperty(QLatin1String("World"));
549 QCOMPARE(expr.changed, true);
550 QCOMPARE(expr.evaluate(), QVariant("World"));
554 MyExpression expr(&context, "testObj.objectProperty.stringProperty");
555 QCOMPARE(expr.changed, false);
556 QCOMPARE(expr.evaluate(), QVariant());
558 object1.setObjectProperty(&object2);
559 QCOMPARE(expr.changed, true);
560 expr.changed = false;
561 QCOMPARE(expr.evaluate(), QVariant("Dog"));
563 object1.setObjectProperty(&object3);
564 QCOMPARE(expr.changed, true);
565 expr.changed = false;
566 QCOMPARE(expr.evaluate(), QVariant("Cat"));
568 object1.setObjectProperty(0);
569 QCOMPARE(expr.changed, true);
570 expr.changed = false;
571 QCOMPARE(expr.evaluate(), QVariant());
573 object1.setObjectProperty(&object3);
574 QCOMPARE(expr.changed, true);
575 expr.changed = false;
576 QCOMPARE(expr.evaluate(), QVariant("Cat"));
578 object3.setStringProperty("Donkey");
579 QCOMPARE(expr.changed, true);
580 expr.changed = false;
581 QCOMPARE(expr.evaluate(), QVariant("Donkey"));
585 void tst_qdeclarativeecmascript::deferredProperties()
587 QDeclarativeComponent component(&engine, TEST_FILE("deferredProperties.qml"));
588 MyDeferredObject *object =
589 qobject_cast<MyDeferredObject *>(component.create());
590 QVERIFY(object != 0);
591 QCOMPARE(object->value(), 0);
592 QVERIFY(object->objectProperty() == 0);
593 QVERIFY(object->objectProperty2() != 0);
594 qmlExecuteDeferred(object);
595 QCOMPARE(object->value(), 10);
596 QVERIFY(object->objectProperty() != 0);
597 MyQmlObject *qmlObject =
598 qobject_cast<MyQmlObject *>(object->objectProperty());
599 QVERIFY(qmlObject != 0);
600 QCOMPARE(qmlObject->value(), 10);
601 object->setValue(19);
602 QCOMPARE(qmlObject->value(), 19);
607 // Check errors on deferred properties are correctly emitted
608 void tst_qdeclarativeecmascript::deferredPropertiesErrors()
610 QDeclarativeComponent component(&engine, TEST_FILE("deferredPropertiesErrors.qml"));
611 MyDeferredObject *object =
612 qobject_cast<MyDeferredObject *>(component.create());
613 QVERIFY(object != 0);
614 QCOMPARE(object->value(), 0);
615 QVERIFY(object->objectProperty() == 0);
616 QVERIFY(object->objectProperty2() == 0);
618 QString warning = component.url().toString() + ":6: Unable to assign [undefined] to QObject* objectProperty";
619 QTest::ignoreMessage(QtWarningMsg, qPrintable(warning));
621 qmlExecuteDeferred(object);
626 void tst_qdeclarativeecmascript::extensionObjects()
628 QDeclarativeComponent component(&engine, TEST_FILE("extensionObjects.qml"));
629 MyExtendedObject *object =
630 qobject_cast<MyExtendedObject *>(component.create());
631 QVERIFY(object != 0);
632 QCOMPARE(object->baseProperty(), 13);
633 QCOMPARE(object->coreProperty(), 9);
634 object->setProperty("extendedProperty", QVariant(11));
635 object->setProperty("baseExtendedProperty", QVariant(92));
636 QCOMPARE(object->coreProperty(), 11);
637 QCOMPARE(object->baseProperty(), 92);
639 MyExtendedObject *nested = qobject_cast<MyExtendedObject*>(qvariant_cast<QObject *>(object->property("nested")));
641 QCOMPARE(nested->baseProperty(), 13);
642 QCOMPARE(nested->coreProperty(), 9);
643 nested->setProperty("extendedProperty", QVariant(11));
644 nested->setProperty("baseExtendedProperty", QVariant(92));
645 QCOMPARE(nested->coreProperty(), 11);
646 QCOMPARE(nested->baseProperty(), 92);
651 void tst_qdeclarativeecmascript::overrideExtensionProperties()
653 QDeclarativeComponent component(&engine, TEST_FILE("extensionObjectsPropertyOverride.qml"));
654 OverrideDefaultPropertyObject *object =
655 qobject_cast<OverrideDefaultPropertyObject *>(component.create());
656 QVERIFY(object != 0);
657 QVERIFY(object->secondProperty() != 0);
658 QVERIFY(object->firstProperty() == 0);
663 void tst_qdeclarativeecmascript::attachedProperties()
666 QDeclarativeComponent component(&engine, TEST_FILE("attachedProperty.qml"));
667 QObject *object = component.create();
668 QVERIFY(object != 0);
669 QCOMPARE(object->property("a").toInt(), 19);
670 QCOMPARE(object->property("b").toInt(), 19);
671 QCOMPARE(object->property("c").toInt(), 19);
672 QCOMPARE(object->property("d").toInt(), 19);
677 QDeclarativeComponent component(&engine, TEST_FILE("attachedProperty.2.qml"));
678 QObject *object = component.create();
679 QVERIFY(object != 0);
680 QCOMPARE(object->property("a").toInt(), 26);
681 QCOMPARE(object->property("b").toInt(), 26);
682 QCOMPARE(object->property("c").toInt(), 26);
683 QCOMPARE(object->property("d").toInt(), 26);
687 QDeclarativeComponent component(&engine, TEST_FILE("writeAttachedProperty.qml"));
688 QObject *object = component.create();
689 QVERIFY(object != 0);
691 QMetaObject::invokeMethod(object, "writeValue2");
693 MyQmlAttachedObject *attached =
694 qobject_cast<MyQmlAttachedObject *>(qmlAttachedPropertiesObject<MyQmlObject>(object));
695 QVERIFY(attached != 0);
697 QCOMPARE(attached->value2(), 9);
702 void tst_qdeclarativeecmascript::enums()
706 QDeclarativeComponent component(&engine, TEST_FILE("enums.1.qml"));
707 QObject *object = component.create();
708 QVERIFY(object != 0);
710 QCOMPARE(object->property("a").toInt(), 0);
711 QCOMPARE(object->property("b").toInt(), 1);
712 QCOMPARE(object->property("c").toInt(), 2);
713 QCOMPARE(object->property("d").toInt(), 3);
714 QCOMPARE(object->property("e").toInt(), 0);
715 QCOMPARE(object->property("f").toInt(), 1);
716 QCOMPARE(object->property("g").toInt(), 2);
717 QCOMPARE(object->property("h").toInt(), 3);
718 QCOMPARE(object->property("i").toInt(), 19);
719 QCOMPARE(object->property("j").toInt(), 19);
723 // Non-existent enums
725 QDeclarativeComponent component(&engine, TEST_FILE("enums.2.qml"));
727 QString warning1 = component.url().toString() + ":5: Unable to assign [undefined] to int a";
728 QString warning2 = component.url().toString() + ":6: Unable to assign [undefined] to int b";
729 QTest::ignoreMessage(QtWarningMsg, qPrintable(warning1));
730 QTest::ignoreMessage(QtWarningMsg, qPrintable(warning2));
732 QObject *object = component.create();
733 QVERIFY(object != 0);
734 QCOMPARE(object->property("a").toInt(), 0);
735 QCOMPARE(object->property("b").toInt(), 0);
741 void tst_qdeclarativeecmascript::valueTypeFunctions()
743 QDeclarativeComponent component(&engine, TEST_FILE("valueTypeFunctions.qml"));
744 MyTypeObject *obj = qobject_cast<MyTypeObject*>(component.create());
746 QCOMPARE(obj->rectProperty(), QRect(0,0,100,100));
747 QCOMPARE(obj->rectFProperty(), QRectF(0,0.5,100,99.5));
753 Tests that writing a constant to a property with a binding on it disables the
756 void tst_qdeclarativeecmascript::constantsOverrideBindings()
760 QDeclarativeComponent component(&engine, TEST_FILE("constantsOverrideBindings.1.qml"));
761 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
762 QVERIFY(object != 0);
764 QCOMPARE(object->property("c2").toInt(), 0);
765 object->setProperty("c1", QVariant(9));
766 QCOMPARE(object->property("c2").toInt(), 9);
768 emit object->basicSignal();
770 QCOMPARE(object->property("c2").toInt(), 13);
771 object->setProperty("c1", QVariant(8));
772 QCOMPARE(object->property("c2").toInt(), 13);
777 // During construction
779 QDeclarativeComponent component(&engine, TEST_FILE("constantsOverrideBindings.2.qml"));
780 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
781 QVERIFY(object != 0);
783 QCOMPARE(object->property("c1").toInt(), 0);
784 QCOMPARE(object->property("c2").toInt(), 10);
785 object->setProperty("c1", QVariant(9));
786 QCOMPARE(object->property("c1").toInt(), 9);
787 QCOMPARE(object->property("c2").toInt(), 10);
795 QDeclarativeComponent component(&engine, TEST_FILE("constantsOverrideBindings.3.qml"));
796 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
797 QVERIFY(object != 0);
799 QCOMPARE(object->property("c2").toInt(), 0);
800 object->setProperty("c1", QVariant(9));
801 QCOMPARE(object->property("c2").toInt(), 9);
803 object->setProperty("c2", QVariant(13));
804 QCOMPARE(object->property("c2").toInt(), 13);
805 object->setProperty("c1", QVariant(7));
806 QCOMPARE(object->property("c1").toInt(), 7);
807 QCOMPARE(object->property("c2").toInt(), 13);
815 QDeclarativeComponent component(&engine, TEST_FILE("constantsOverrideBindings.4.qml"));
816 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
817 QVERIFY(object != 0);
819 QCOMPARE(object->property("c1").toInt(), 0);
820 QCOMPARE(object->property("c3").toInt(), 10);
821 object->setProperty("c1", QVariant(9));
822 QCOMPARE(object->property("c1").toInt(), 9);
823 QCOMPARE(object->property("c3").toInt(), 10);
830 Tests that assigning a binding to a property that already has a binding causes
831 the original binding to be disabled.
833 void tst_qdeclarativeecmascript::outerBindingOverridesInnerBinding()
835 QDeclarativeComponent component(&engine,
836 TEST_FILE("outerBindingOverridesInnerBinding.qml"));
837 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
838 QVERIFY(object != 0);
840 QCOMPARE(object->property("c1").toInt(), 0);
841 QCOMPARE(object->property("c2").toInt(), 0);
842 QCOMPARE(object->property("c3").toInt(), 0);
844 object->setProperty("c1", QVariant(9));
845 QCOMPARE(object->property("c1").toInt(), 9);
846 QCOMPARE(object->property("c2").toInt(), 0);
847 QCOMPARE(object->property("c3").toInt(), 0);
849 object->setProperty("c3", QVariant(8));
850 QCOMPARE(object->property("c1").toInt(), 9);
851 QCOMPARE(object->property("c2").toInt(), 8);
852 QCOMPARE(object->property("c3").toInt(), 8);
858 Access a non-existent attached object.
860 Tests for a regression where this used to crash.
862 void tst_qdeclarativeecmascript::nonExistentAttachedObject()
864 QDeclarativeComponent component(&engine, TEST_FILE("nonExistentAttachedObject.qml"));
866 QString warning = component.url().toString() + ":4: Unable to assign [undefined] to QString stringProperty";
867 QTest::ignoreMessage(QtWarningMsg, qPrintable(warning));
869 QObject *object = component.create();
870 QVERIFY(object != 0);
875 void tst_qdeclarativeecmascript::scope()
878 QDeclarativeComponent component(&engine, TEST_FILE("scope.qml"));
879 QObject *object = component.create();
880 QVERIFY(object != 0);
882 QCOMPARE(object->property("test1").toInt(), 1);
883 QCOMPARE(object->property("test2").toInt(), 2);
884 QCOMPARE(object->property("test3").toString(), QString("1Test"));
885 QCOMPARE(object->property("test4").toString(), QString("2Test"));
886 QCOMPARE(object->property("test5").toInt(), 1);
887 QCOMPARE(object->property("test6").toInt(), 1);
888 QCOMPARE(object->property("test7").toInt(), 2);
889 QCOMPARE(object->property("test8").toInt(), 2);
890 QCOMPARE(object->property("test9").toInt(), 1);
891 QCOMPARE(object->property("test10").toInt(), 3);
897 QDeclarativeComponent component(&engine, TEST_FILE("scope.2.qml"));
898 QObject *object = component.create();
899 QVERIFY(object != 0);
901 QCOMPARE(object->property("test1").toInt(), 19);
902 QCOMPARE(object->property("test2").toInt(), 19);
903 QCOMPARE(object->property("test3").toInt(), 14);
904 QCOMPARE(object->property("test4").toInt(), 14);
905 QCOMPARE(object->property("test5").toInt(), 24);
906 QCOMPARE(object->property("test6").toInt(), 24);
912 QDeclarativeComponent component(&engine, TEST_FILE("scope.3.qml"));
913 QObject *object = component.create();
914 QVERIFY(object != 0);
916 QCOMPARE(object->property("test1").toBool(), true);
917 QCOMPARE(object->property("test2").toBool(), true);
918 QCOMPARE(object->property("test3").toBool(), true);
923 // Signal argument scope
925 QDeclarativeComponent component(&engine, TEST_FILE("scope.4.qml"));
926 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
927 QVERIFY(object != 0);
929 QCOMPARE(object->property("test").toInt(), 0);
930 QCOMPARE(object->property("test2").toString(), QString());
932 emit object->argumentSignal(13, "Argument Scope", 9, MyQmlObject::EnumValue4, Qt::RightButton);
934 QCOMPARE(object->property("test").toInt(), 13);
935 QCOMPARE(object->property("test2").toString(), QString("Argument Scope"));
941 QDeclarativeComponent component(&engine, TEST_FILE("scope.5.qml"));
942 QObject *object = component.create();
943 QVERIFY(object != 0);
945 QCOMPARE(object->property("test1").toBool(), true);
946 QCOMPARE(object->property("test2").toBool(), true);
952 QDeclarativeComponent component(&engine, TEST_FILE("scope.6.qml"));
953 QObject *object = component.create();
954 QVERIFY(object != 0);
956 QCOMPARE(object->property("test").toBool(), true);
963 Tests that "any" type passes through a synthesized signal parameter. This
964 is essentially a test of QDeclarativeMetaType::copy()
966 void tst_qdeclarativeecmascript::signalParameterTypes()
968 QDeclarativeComponent component(&engine, TEST_FILE("signalParameterTypes.qml"));
969 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
970 QVERIFY(object != 0);
972 emit object->basicSignal();
974 QCOMPARE(object->property("intProperty").toInt(), 10);
975 QCOMPARE(object->property("realProperty").toReal(), 19.2);
976 QVERIFY(object->property("colorProperty").value<QColor>() == QColor(255, 255, 0, 255));
977 QVERIFY(object->property("variantProperty") == QVariant::fromValue(QColor(255, 0, 255, 255)));
978 QVERIFY(object->property("enumProperty") == MyQmlObject::EnumValue3);
979 QVERIFY(object->property("qtEnumProperty") == Qt::LeftButton);
985 Test that two JS objects for the same QObject compare as equal.
987 void tst_qdeclarativeecmascript::objectsCompareAsEqual()
989 QDeclarativeComponent component(&engine, TEST_FILE("objectsCompareAsEqual.qml"));
990 QObject *object = component.create();
991 QVERIFY(object != 0);
993 QCOMPARE(object->property("test1").toBool(), true);
994 QCOMPARE(object->property("test2").toBool(), true);
995 QCOMPARE(object->property("test3").toBool(), true);
996 QCOMPARE(object->property("test4").toBool(), true);
997 QCOMPARE(object->property("test5").toBool(), true);
1003 Confirm bindings and alias properties can coexist.
1005 Tests for a regression where the binding would not reevaluate.
1007 void tst_qdeclarativeecmascript::aliasPropertyAndBinding()
1009 QDeclarativeComponent component(&engine, TEST_FILE("aliasPropertyAndBinding.qml"));
1010 QObject *object = component.create();
1011 QVERIFY(object != 0);
1013 QCOMPARE(object->property("c2").toInt(), 3);
1014 QCOMPARE(object->property("c3").toInt(), 3);
1016 object->setProperty("c2", QVariant(19));
1018 QCOMPARE(object->property("c2").toInt(), 19);
1019 QCOMPARE(object->property("c3").toInt(), 19);
1024 void tst_qdeclarativeecmascript::dynamicCreation_data()
1026 QTest::addColumn<QString>("method");
1027 QTest::addColumn<QString>("createdName");
1029 QTest::newRow("One") << "createOne" << "objectOne";
1030 QTest::newRow("Two") << "createTwo" << "objectTwo";
1031 QTest::newRow("Three") << "createThree" << "objectThree";
1035 Test using createQmlObject to dynamically generate an item
1036 Also using createComponent is tested.
1038 void tst_qdeclarativeecmascript::dynamicCreation()
1040 QFETCH(QString, method);
1041 QFETCH(QString, createdName);
1043 QDeclarativeComponent component(&engine, TEST_FILE("dynamicCreation.qml"));
1044 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1045 QVERIFY(object != 0);
1047 QMetaObject::invokeMethod(object, method.toUtf8());
1048 QObject *created = object->objectProperty();
1050 QCOMPARE(created->objectName(), createdName);
1056 Tests the destroy function
1058 void tst_qdeclarativeecmascript::dynamicDestruction()
1060 QDeclarativeComponent component(&engine, TEST_FILE("dynamicDeletion.qml"));
1061 QDeclarativeGuard<MyQmlObject> object = qobject_cast<MyQmlObject*>(component.create());
1062 QVERIFY(object != 0);
1063 QDeclarativeGuard<QObject> createdQmlObject = 0;
1065 QMetaObject::invokeMethod(object, "create");
1066 createdQmlObject = object->objectProperty();
1067 QVERIFY(createdQmlObject);
1068 QCOMPARE(createdQmlObject->objectName(), QString("emptyObject"));
1070 QMetaObject::invokeMethod(object, "killOther");
1071 QVERIFY(createdQmlObject);
1072 QCoreApplication::instance()->processEvents(QEventLoop::DeferredDeletion);
1073 QVERIFY(createdQmlObject);
1074 for (int ii = 0; createdQmlObject && ii < 50; ++ii) { // After 5 seconds we should give up
1075 if (createdQmlObject) {
1077 QCoreApplication::instance()->processEvents(QEventLoop::DeferredDeletion);
1080 QVERIFY(!createdQmlObject);
1082 QDeclarativeEngine::setObjectOwnership(object, QDeclarativeEngine::JavaScriptOwnership);
1083 QMetaObject::invokeMethod(object, "killMe");
1086 QCoreApplication::instance()->processEvents(QEventLoop::DeferredDeletion);
1091 tests that id.toString() works
1093 void tst_qdeclarativeecmascript::objectToString()
1095 QDeclarativeComponent component(&engine, TEST_FILE("declarativeToString.qml"));
1096 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1097 QVERIFY(object != 0);
1098 QMetaObject::invokeMethod(object, "testToString");
1099 QVERIFY(object->stringProperty().startsWith("MyQmlObject_QML_"));
1100 QVERIFY(object->stringProperty().endsWith(", \"objName\")"));
1106 Tests bindings that indirectly cause their own deletion work.
1108 This test is best run under valgrind to ensure no invalid memory access occur.
1110 void tst_qdeclarativeecmascript::selfDeletingBinding()
1113 QDeclarativeComponent component(&engine, TEST_FILE("selfDeletingBinding.qml"));
1114 QObject *object = component.create();
1115 QVERIFY(object != 0);
1116 object->setProperty("triggerDelete", true);
1121 QDeclarativeComponent component(&engine, TEST_FILE("selfDeletingBinding.2.qml"));
1122 QObject *object = component.create();
1123 QVERIFY(object != 0);
1124 object->setProperty("triggerDelete", true);
1130 Test that extended object properties can be accessed.
1132 This test a regression where this used to crash. The issue was specificially
1133 for extended objects that did not include a synthesized meta object (so non-root
1134 and no synthesiszed properties).
1136 void tst_qdeclarativeecmascript::extendedObjectPropertyLookup()
1138 QDeclarativeComponent component(&engine, TEST_FILE("extendedObjectPropertyLookup.qml"));
1139 QObject *object = component.create();
1140 QVERIFY(object != 0);
1145 Test file/lineNumbers for binding/Script errors.
1147 void tst_qdeclarativeecmascript::scriptErrors()
1149 QDeclarativeComponent component(&engine, TEST_FILE("scriptErrors.qml"));
1150 QString url = component.url().toString();
1152 QString warning1 = url.left(url.length() - 3) + "js:2: Error: Invalid write to global property \"a\"";
1153 QString warning2 = url + ":5: ReferenceError: Can't find variable: a";
1154 QString warning3 = url.left(url.length() - 3) + "js:4: Error: Invalid write to global property \"a\"";
1155 QString warning4 = url + ":10: ReferenceError: Can't find variable: a";
1156 QString warning5 = url + ":8: ReferenceError: Can't find variable: a";
1157 QString warning6 = url + ":7: Unable to assign [undefined] to int x";
1158 QString warning7 = url + ":12: Error: Cannot assign to read-only property \"trueProperty\"";
1159 QString warning8 = url + ":13: Error: Cannot assign to non-existent property \"fakeProperty\"";
1161 QTest::ignoreMessage(QtWarningMsg, warning1.toLatin1().constData());
1162 QTest::ignoreMessage(QtWarningMsg, warning2.toLatin1().constData());
1163 QTest::ignoreMessage(QtWarningMsg, warning3.toLatin1().constData());
1164 QTest::ignoreMessage(QtWarningMsg, warning5.toLatin1().constData());
1165 QTest::ignoreMessage(QtWarningMsg, warning6.toLatin1().constData());
1166 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
1167 QVERIFY(object != 0);
1169 QTest::ignoreMessage(QtWarningMsg, warning4.toLatin1().constData());
1170 emit object->basicSignal();
1172 QTest::ignoreMessage(QtWarningMsg, warning7.toLatin1().constData());
1173 emit object->anotherBasicSignal();
1175 QTest::ignoreMessage(QtWarningMsg, warning8.toLatin1().constData());
1176 emit object->thirdBasicSignal();
1182 Test file/lineNumbers for inline functions.
1184 void tst_qdeclarativeecmascript::functionErrors()
1186 QDeclarativeComponent component(&engine, TEST_FILE("functionErrors.qml"));
1187 QString url = component.url().toString();
1189 QString warning = url + ":5: Error: Invalid write to global property \"a\"";
1191 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
1193 QObject *object = component.create();
1194 QVERIFY(object != 0);
1197 // test that if an exception occurs while invoking js function from cpp, it is reported as expected.
1198 QDeclarativeComponent componentTwo(&engine, TEST_FILE("scarceresources/scarceResourceFunctionFail.qml"));
1199 url = componentTwo.url().toString();
1200 object = componentTwo.create();
1201 QVERIFY(object != 0);
1202 warning = url + QLatin1String(":16: TypeError: Result of expression 'scarceResourceProvider.scarceResource' [[object Object]] is not a function.");
1203 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData()); // we expect a meaningful warning to be printed.
1204 QMetaObject::invokeMethod(object, "retrieveScarceResource");
1209 Test various errors that can occur when assigning a property from script
1211 void tst_qdeclarativeecmascript::propertyAssignmentErrors()
1213 QDeclarativeComponent component(&engine, TEST_FILE("propertyAssignmentErrors.qml"));
1215 QString url = component.url().toString();
1217 QString warning1 = url + ":11:Error: Cannot assign [undefined] to int";
1218 QString warning2 = url + ":17:Error: Cannot assign QString to int";
1220 QTest::ignoreMessage(QtDebugMsg, warning1.toLatin1().constData());
1221 QTest::ignoreMessage(QtDebugMsg, warning2.toLatin1().constData());
1223 QObject *object = component.create();
1224 QVERIFY(object != 0);
1230 Test bindings still work when the reeval is triggered from within
1233 void tst_qdeclarativeecmascript::signalTriggeredBindings()
1235 QDeclarativeComponent component(&engine, TEST_FILE("signalTriggeredBindings.qml"));
1236 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1237 QVERIFY(object != 0);
1239 QCOMPARE(object->property("base").toReal(), 50.);
1240 QCOMPARE(object->property("test1").toReal(), 50.);
1241 QCOMPARE(object->property("test2").toReal(), 50.);
1243 object->basicSignal();
1245 QCOMPARE(object->property("base").toReal(), 200.);
1246 QCOMPARE(object->property("test1").toReal(), 200.);
1247 QCOMPARE(object->property("test2").toReal(), 200.);
1249 object->argumentSignal(10, QString(), 10, MyQmlObject::EnumValue4, Qt::RightButton);
1251 QCOMPARE(object->property("base").toReal(), 400.);
1252 QCOMPARE(object->property("test1").toReal(), 400.);
1253 QCOMPARE(object->property("test2").toReal(), 400.);
1259 Test that list properties can be iterated from ECMAScript
1261 void tst_qdeclarativeecmascript::listProperties()
1263 QDeclarativeComponent component(&engine, TEST_FILE("listProperties.qml"));
1264 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1265 QVERIFY(object != 0);
1267 QCOMPARE(object->property("test1").toInt(), 21);
1268 QCOMPARE(object->property("test2").toInt(), 2);
1269 QCOMPARE(object->property("test3").toBool(), true);
1270 QCOMPARE(object->property("test4").toBool(), true);
1275 void tst_qdeclarativeecmascript::exceptionClearsOnReeval()
1277 QDeclarativeComponent component(&engine, TEST_FILE("exceptionClearsOnReeval.qml"));
1278 QString url = component.url().toString();
1280 QString warning = url + ":4: TypeError: Result of expression 'objectProperty' [null] is not an object.";
1282 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
1283 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1284 QVERIFY(object != 0);
1286 QCOMPARE(object->property("test").toBool(), false);
1288 MyQmlObject object2;
1289 MyQmlObject object3;
1290 object2.setObjectProperty(&object3);
1291 object->setObjectProperty(&object2);
1293 QCOMPARE(object->property("test").toBool(), true);
1298 void tst_qdeclarativeecmascript::exceptionSlotProducesWarning()
1300 QDeclarativeComponent component(&engine, TEST_FILE("exceptionProducesWarning.qml"));
1301 QString url = component.url().toString();
1303 QString warning = component.url().toString() + ":6: Error: JS exception";
1305 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
1306 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1307 QVERIFY(object != 0);
1311 void tst_qdeclarativeecmascript::exceptionBindingProducesWarning()
1313 QDeclarativeComponent component(&engine, TEST_FILE("exceptionProducesWarning2.qml"));
1314 QString url = component.url().toString();
1316 QString warning = component.url().toString() + ":5: Error: JS exception";
1318 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
1319 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1320 QVERIFY(object != 0);
1324 static int transientErrorsMsgCount = 0;
1325 static void transientErrorsMsgHandler(QtMsgType, const char *)
1327 ++transientErrorsMsgCount;
1330 // Check that transient binding errors are not displayed
1331 void tst_qdeclarativeecmascript::transientErrors()
1334 QDeclarativeComponent component(&engine, TEST_FILE("transientErrors.qml"));
1336 transientErrorsMsgCount = 0;
1337 QtMsgHandler old = qInstallMsgHandler(transientErrorsMsgHandler);
1339 QObject *object = component.create();
1340 QVERIFY(object != 0);
1342 qInstallMsgHandler(old);
1344 QCOMPARE(transientErrorsMsgCount, 0);
1349 // One binding erroring multiple times, but then resolving
1351 QDeclarativeComponent component(&engine, TEST_FILE("transientErrors.2.qml"));
1353 transientErrorsMsgCount = 0;
1354 QtMsgHandler old = qInstallMsgHandler(transientErrorsMsgHandler);
1356 QObject *object = component.create();
1357 QVERIFY(object != 0);
1359 qInstallMsgHandler(old);
1361 QCOMPARE(transientErrorsMsgCount, 0);
1367 // Check that errors during shutdown are minimized
1368 void tst_qdeclarativeecmascript::shutdownErrors()
1370 QDeclarativeComponent component(&engine, TEST_FILE("shutdownErrors.qml"));
1371 QObject *object = component.create();
1372 QVERIFY(object != 0);
1374 transientErrorsMsgCount = 0;
1375 QtMsgHandler old = qInstallMsgHandler(transientErrorsMsgHandler);
1379 qInstallMsgHandler(old);
1380 QCOMPARE(transientErrorsMsgCount, 0);
1383 void tst_qdeclarativeecmascript::compositePropertyType()
1385 QDeclarativeComponent component(&engine, TEST_FILE("compositePropertyType.qml"));
1386 QTest::ignoreMessage(QtDebugMsg, "hello world");
1387 QObject *object = qobject_cast<QObject *>(component.create());
1392 void tst_qdeclarativeecmascript::jsObject()
1394 QDeclarativeComponent component(&engine, TEST_FILE("jsObject.qml"));
1395 QObject *object = component.create();
1396 QVERIFY(object != 0);
1398 QCOMPARE(object->property("test").toInt(), 92);
1403 void tst_qdeclarativeecmascript::undefinedResetsProperty()
1406 QDeclarativeComponent component(&engine, TEST_FILE("undefinedResetsProperty.qml"));
1407 QObject *object = component.create();
1408 QVERIFY(object != 0);
1410 QCOMPARE(object->property("resettableProperty").toInt(), 92);
1412 object->setProperty("setUndefined", true);
1414 QCOMPARE(object->property("resettableProperty").toInt(), 13);
1416 object->setProperty("setUndefined", false);
1418 QCOMPARE(object->property("resettableProperty").toInt(), 92);
1423 QDeclarativeComponent component(&engine, TEST_FILE("undefinedResetsProperty.2.qml"));
1424 QObject *object = component.create();
1425 QVERIFY(object != 0);
1427 QCOMPARE(object->property("resettableProperty").toInt(), 19);
1429 QMetaObject::invokeMethod(object, "doReset");
1431 QCOMPARE(object->property("resettableProperty").toInt(), 13);
1438 void tst_qdeclarativeecmascript::bug1()
1440 QDeclarativeComponent component(&engine, TEST_FILE("bug.1.qml"));
1441 QObject *object = component.create();
1442 QVERIFY(object != 0);
1444 QCOMPARE(object->property("test").toInt(), 14);
1446 object->setProperty("a", 11);
1448 QCOMPARE(object->property("test").toInt(), 3);
1450 object->setProperty("b", true);
1452 QCOMPARE(object->property("test").toInt(), 9);
1457 void tst_qdeclarativeecmascript::bug2()
1459 QDeclarativeComponent component(&engine);
1460 component.setData("import Qt.test 1.0;\nQPlainTextEdit { width: 100 }", QUrl());
1462 QObject *object = component.create();
1463 QVERIFY(object != 0);
1468 // Don't crash in createObject when the component has errors.
1469 void tst_qdeclarativeecmascript::dynamicCreationCrash()
1471 QDeclarativeComponent component(&engine, TEST_FILE("dynamicCreation.qml"));
1472 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1473 QVERIFY(object != 0);
1475 QTest::ignoreMessage(QtWarningMsg, "QDeclarativeComponent: Component is not ready");
1476 QMetaObject::invokeMethod(object, "dontCrash");
1477 QObject *created = object->objectProperty();
1478 QVERIFY(created == 0);
1484 void tst_qdeclarativeecmascript::regExpBug()
1486 QDeclarativeComponent component(&engine, TEST_FILE("regExp.qml"));
1487 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1488 QVERIFY(object != 0);
1489 QCOMPARE(object->regExp().pattern(), QLatin1String("[a-zA-z]"));
1493 void tst_qdeclarativeecmascript::callQtInvokables()
1495 MyInvokableObject o;
1497 QDeclarativeEngine qmlengine;
1498 QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(&qmlengine);
1499 QScriptEngine *engine = &ep->scriptEngine;
1501 QStringList names; QList<QScriptValue> values;
1502 names << QLatin1String("object"); values << ep->objectClass->newQObject(&o);
1503 names << QLatin1String("undefined"); values << engine->undefinedValue();
1505 ep->globalClass->explicitSetProperty(names, values);
1507 // Non-existent methods
1509 QCOMPARE(engine->evaluate("object.method_nonexistent()").isError(), true);
1510 QCOMPARE(o.error(), false);
1511 QCOMPARE(o.invoked(), -1);
1512 QCOMPARE(o.actuals().count(), 0);
1515 QCOMPARE(engine->evaluate("object.method_nonexistent(10, 11)").isError(), true);
1516 QCOMPARE(o.error(), false);
1517 QCOMPARE(o.invoked(), -1);
1518 QCOMPARE(o.actuals().count(), 0);
1520 // Insufficient arguments
1522 QCOMPARE(engine->evaluate("object.method_int()").isError(), true);
1523 QCOMPARE(o.error(), false);
1524 QCOMPARE(o.invoked(), -1);
1525 QCOMPARE(o.actuals().count(), 0);
1528 QCOMPARE(engine->evaluate("object.method_intint(10)").isError(), true);
1529 QCOMPARE(o.error(), false);
1530 QCOMPARE(o.invoked(), -1);
1531 QCOMPARE(o.actuals().count(), 0);
1533 // Excessive arguments
1535 QCOMPARE(engine->evaluate("object.method_int(10, 11)").isUndefined(), true);
1536 QCOMPARE(o.error(), false);
1537 QCOMPARE(o.invoked(), 8);
1538 QCOMPARE(o.actuals().count(), 1);
1539 QCOMPARE(o.actuals().at(0), QVariant(10));
1542 QCOMPARE(engine->evaluate("object.method_intint(10, 11, 12)").isUndefined(), true);
1543 QCOMPARE(o.error(), false);
1544 QCOMPARE(o.invoked(), 9);
1545 QCOMPARE(o.actuals().count(), 2);
1546 QCOMPARE(o.actuals().at(0), QVariant(10));
1547 QCOMPARE(o.actuals().at(1), QVariant(11));
1549 // Test return types
1551 QCOMPARE(engine->evaluate("object.method_NoArgs()").isUndefined(), true);
1552 QCOMPARE(o.error(), false);
1553 QCOMPARE(o.invoked(), 0);
1554 QCOMPARE(o.actuals().count(), 0);
1557 QVERIFY(engine->evaluate("object.method_NoArgs_int()").strictlyEquals(QScriptValue(engine, 6)));
1558 QCOMPARE(o.error(), false);
1559 QCOMPARE(o.invoked(), 1);
1560 QCOMPARE(o.actuals().count(), 0);
1563 QVERIFY(engine->evaluate("object.method_NoArgs_real()").strictlyEquals(QScriptValue(engine, 19.75)));
1564 QCOMPARE(o.error(), false);
1565 QCOMPARE(o.invoked(), 2);
1566 QCOMPARE(o.actuals().count(), 0);
1570 QScriptValue ret = engine->evaluate("object.method_NoArgs_QPointF()");
1571 QCOMPARE(ret.toVariant(), QVariant(QPointF(123, 4.5)));
1572 QCOMPARE(o.error(), false);
1573 QCOMPARE(o.invoked(), 3);
1574 QCOMPARE(o.actuals().count(), 0);
1579 QScriptValue ret = engine->evaluate("object.method_NoArgs_QObject()");
1580 QVERIFY(ret.isQObject());
1581 QCOMPARE(ret.toQObject(), (QObject *)&o);
1582 QCOMPARE(o.error(), false);
1583 QCOMPARE(o.invoked(), 4);
1584 QCOMPARE(o.actuals().count(), 0);
1588 QCOMPARE(engine->evaluate("object.method_NoArgs_unknown()").isUndefined(), true);
1589 QCOMPARE(o.error(), false);
1590 QCOMPARE(o.invoked(), 5);
1591 QCOMPARE(o.actuals().count(), 0);
1595 QScriptValue ret = engine->evaluate("object.method_NoArgs_QScriptValue()");
1596 QVERIFY(ret.isString());
1597 QCOMPARE(ret.toString(), QString("Hello world"));
1598 QCOMPARE(o.error(), false);
1599 QCOMPARE(o.invoked(), 6);
1600 QCOMPARE(o.actuals().count(), 0);
1604 QVERIFY(engine->evaluate("object.method_NoArgs_QVariant()").strictlyEquals(QScriptValue(engine, "QML rocks")));
1605 QCOMPARE(o.error(), false);
1606 QCOMPARE(o.invoked(), 7);
1607 QCOMPARE(o.actuals().count(), 0);
1611 QCOMPARE(engine->evaluate("object.method_int(94)").isUndefined(), true);
1612 QCOMPARE(o.error(), false);
1613 QCOMPARE(o.invoked(), 8);
1614 QCOMPARE(o.actuals().count(), 1);
1615 QCOMPARE(o.actuals().at(0), QVariant(94));
1618 QCOMPARE(engine->evaluate("object.method_int(\"94\")").isUndefined(), true);
1619 QCOMPARE(o.error(), false);
1620 QCOMPARE(o.invoked(), 8);
1621 QCOMPARE(o.actuals().count(), 1);
1622 QCOMPARE(o.actuals().at(0), QVariant(94));
1625 QCOMPARE(engine->evaluate("object.method_int(\"not a number\")").isUndefined(), true);
1626 QCOMPARE(o.error(), false);
1627 QCOMPARE(o.invoked(), 8);
1628 QCOMPARE(o.actuals().count(), 1);
1629 QCOMPARE(o.actuals().at(0), QVariant(0));
1632 QCOMPARE(engine->evaluate("object.method_int(null)").isUndefined(), true);
1633 QCOMPARE(o.error(), false);
1634 QCOMPARE(o.invoked(), 8);
1635 QCOMPARE(o.actuals().count(), 1);
1636 QCOMPARE(o.actuals().at(0), QVariant(0));
1639 QCOMPARE(engine->evaluate("object.method_int(undefined)").isUndefined(), true);
1640 QCOMPARE(o.error(), false);
1641 QCOMPARE(o.invoked(), 8);
1642 QCOMPARE(o.actuals().count(), 1);
1643 QCOMPARE(o.actuals().at(0), QVariant(0));
1646 QCOMPARE(engine->evaluate("object.method_int(object)").isUndefined(), true);
1647 QCOMPARE(o.error(), false);
1648 QCOMPARE(o.invoked(), 8);
1649 QCOMPARE(o.actuals().count(), 1);
1650 QCOMPARE(o.actuals().at(0), QVariant(0));
1653 QCOMPARE(engine->evaluate("object.method_intint(122, 9)").isUndefined(), true);
1654 QCOMPARE(o.error(), false);
1655 QCOMPARE(o.invoked(), 9);
1656 QCOMPARE(o.actuals().count(), 2);
1657 QCOMPARE(o.actuals().at(0), QVariant(122));
1658 QCOMPARE(o.actuals().at(1), QVariant(9));
1661 QCOMPARE(engine->evaluate("object.method_real(94.3)").isUndefined(), true);
1662 QCOMPARE(o.error(), false);
1663 QCOMPARE(o.invoked(), 10);
1664 QCOMPARE(o.actuals().count(), 1);
1665 QCOMPARE(o.actuals().at(0), QVariant(94.3));
1668 QCOMPARE(engine->evaluate("object.method_real(\"94.3\")").isUndefined(), true);
1669 QCOMPARE(o.error(), false);
1670 QCOMPARE(o.invoked(), 10);
1671 QCOMPARE(o.actuals().count(), 1);
1672 QCOMPARE(o.actuals().at(0), QVariant(94.3));
1675 QCOMPARE(engine->evaluate("object.method_real(\"not a number\")").isUndefined(), true);
1676 QCOMPARE(o.error(), false);
1677 QCOMPARE(o.invoked(), 10);
1678 QCOMPARE(o.actuals().count(), 1);
1679 QVERIFY(qIsNaN(o.actuals().at(0).toDouble()));
1682 QCOMPARE(engine->evaluate("object.method_real(null)").isUndefined(), true);
1683 QCOMPARE(o.error(), false);
1684 QCOMPARE(o.invoked(), 10);
1685 QCOMPARE(o.actuals().count(), 1);
1686 QCOMPARE(o.actuals().at(0), QVariant(0));
1689 QCOMPARE(engine->evaluate("object.method_real(undefined)").isUndefined(), true);
1690 QCOMPARE(o.error(), false);
1691 QCOMPARE(o.invoked(), 10);
1692 QCOMPARE(o.actuals().count(), 1);
1693 QVERIFY(qIsNaN(o.actuals().at(0).toDouble()));
1696 QCOMPARE(engine->evaluate("object.method_real(object)").isUndefined(), true);
1697 QCOMPARE(o.error(), false);
1698 QCOMPARE(o.invoked(), 10);
1699 QCOMPARE(o.actuals().count(), 1);
1700 QVERIFY(qIsNaN(o.actuals().at(0).toDouble()));
1703 QCOMPARE(engine->evaluate("object.method_QString(\"Hello world\")").isUndefined(), true);
1704 QCOMPARE(o.error(), false);
1705 QCOMPARE(o.invoked(), 11);
1706 QCOMPARE(o.actuals().count(), 1);
1707 QCOMPARE(o.actuals().at(0), QVariant("Hello world"));
1710 QCOMPARE(engine->evaluate("object.method_QString(19)").isUndefined(), true);
1711 QCOMPARE(o.error(), false);
1712 QCOMPARE(o.invoked(), 11);
1713 QCOMPARE(o.actuals().count(), 1);
1714 QCOMPARE(o.actuals().at(0), QVariant("19"));
1718 QString expected = "MyInvokableObject(0x" + QString::number((quintptr)&o, 16) + ")";
1719 QCOMPARE(engine->evaluate("object.method_QString(object)").isUndefined(), true);
1720 QCOMPARE(o.error(), false);
1721 QCOMPARE(o.invoked(), 11);
1722 QCOMPARE(o.actuals().count(), 1);
1723 QCOMPARE(o.actuals().at(0), QVariant(expected));
1727 QCOMPARE(engine->evaluate("object.method_QString(null)").isUndefined(), true);
1728 QCOMPARE(o.error(), false);
1729 QCOMPARE(o.invoked(), 11);
1730 QCOMPARE(o.actuals().count(), 1);
1731 QCOMPARE(o.actuals().at(0), QVariant(QString()));
1734 QCOMPARE(engine->evaluate("object.method_QString(undefined)").isUndefined(), true);
1735 QCOMPARE(o.error(), false);
1736 QCOMPARE(o.invoked(), 11);
1737 QCOMPARE(o.actuals().count(), 1);
1738 QCOMPARE(o.actuals().at(0), QVariant(QString()));
1741 QCOMPARE(engine->evaluate("object.method_QPointF(0)").isUndefined(), true);
1742 QCOMPARE(o.error(), false);
1743 QCOMPARE(o.invoked(), 12);
1744 QCOMPARE(o.actuals().count(), 1);
1745 QCOMPARE(o.actuals().at(0), QVariant(QPointF()));
1748 QCOMPARE(engine->evaluate("object.method_QPointF(null)").isUndefined(), true);
1749 QCOMPARE(o.error(), false);
1750 QCOMPARE(o.invoked(), 12);
1751 QCOMPARE(o.actuals().count(), 1);
1752 QCOMPARE(o.actuals().at(0), QVariant(QPointF()));
1755 QCOMPARE(engine->evaluate("object.method_QPointF(undefined)").isUndefined(), true);
1756 QCOMPARE(o.error(), false);
1757 QCOMPARE(o.invoked(), 12);
1758 QCOMPARE(o.actuals().count(), 1);
1759 QCOMPARE(o.actuals().at(0), QVariant(QPointF()));
1762 QCOMPARE(engine->evaluate("object.method_QPointF(object)").isUndefined(), true);
1763 QCOMPARE(o.error(), false);
1764 QCOMPARE(o.invoked(), 12);
1765 QCOMPARE(o.actuals().count(), 1);
1766 QCOMPARE(o.actuals().at(0), QVariant(QPointF()));
1769 QCOMPARE(engine->evaluate("object.method_QPointF(object.method_get_QPointF())").isUndefined(), true);
1770 QCOMPARE(o.error(), false);
1771 QCOMPARE(o.invoked(), 12);
1772 QCOMPARE(o.actuals().count(), 1);
1773 QCOMPARE(o.actuals().at(0), QVariant(QPointF(99.3, -10.2)));
1776 QCOMPARE(engine->evaluate("object.method_QPointF(object.method_get_QPoint())").isUndefined(), true);
1777 QCOMPARE(o.error(), false);
1778 QCOMPARE(o.invoked(), 12);
1779 QCOMPARE(o.actuals().count(), 1);
1780 QCOMPARE(o.actuals().at(0), QVariant(QPointF(9, 12)));
1783 QCOMPARE(engine->evaluate("object.method_QObject(0)").isUndefined(), true);
1784 QCOMPARE(o.error(), false);
1785 QCOMPARE(o.invoked(), 13);
1786 QCOMPARE(o.actuals().count(), 1);
1787 QCOMPARE(o.actuals().at(0), qVariantFromValue((QObject *)0));
1790 QCOMPARE(engine->evaluate("object.method_QObject(\"Hello world\")").isUndefined(), true);
1791 QCOMPARE(o.error(), false);
1792 QCOMPARE(o.invoked(), 13);
1793 QCOMPARE(o.actuals().count(), 1);
1794 QCOMPARE(o.actuals().at(0), qVariantFromValue((QObject *)0));
1797 QCOMPARE(engine->evaluate("object.method_QObject(null)").isUndefined(), true);
1798 QCOMPARE(o.error(), false);
1799 QCOMPARE(o.invoked(), 13);
1800 QCOMPARE(o.actuals().count(), 1);
1801 QCOMPARE(o.actuals().at(0), qVariantFromValue((QObject *)0));
1804 QCOMPARE(engine->evaluate("object.method_QObject(undefined)").isUndefined(), true);
1805 QCOMPARE(o.error(), false);
1806 QCOMPARE(o.invoked(), 13);
1807 QCOMPARE(o.actuals().count(), 1);
1808 QCOMPARE(o.actuals().at(0), qVariantFromValue((QObject *)0));
1811 QCOMPARE(engine->evaluate("object.method_QObject(object)").isUndefined(), true);
1812 QCOMPARE(o.error(), false);
1813 QCOMPARE(o.invoked(), 13);
1814 QCOMPARE(o.actuals().count(), 1);
1815 QCOMPARE(o.actuals().at(0), qVariantFromValue((QObject *)&o));
1818 QCOMPARE(engine->evaluate("object.method_QScriptValue(null)").isUndefined(), true);
1819 QCOMPARE(o.error(), false);
1820 QCOMPARE(o.invoked(), 14);
1821 QCOMPARE(o.actuals().count(), 1);
1822 QVERIFY(qvariant_cast<QScriptValue>(o.actuals().at(0)).isNull());
1825 QCOMPARE(engine->evaluate("object.method_QScriptValue(undefined)").isUndefined(), true);
1826 QCOMPARE(o.error(), false);
1827 QCOMPARE(o.invoked(), 14);
1828 QCOMPARE(o.actuals().count(), 1);
1829 QVERIFY(qvariant_cast<QScriptValue>(o.actuals().at(0)).isUndefined());
1832 QCOMPARE(engine->evaluate("object.method_QScriptValue(19)").isUndefined(), true);
1833 QCOMPARE(o.error(), false);
1834 QCOMPARE(o.invoked(), 14);
1835 QCOMPARE(o.actuals().count(), 1);
1836 QVERIFY(qvariant_cast<QScriptValue>(o.actuals().at(0)).strictlyEquals(QScriptValue(engine, 19)));
1839 QCOMPARE(engine->evaluate("object.method_QScriptValue([19, 20])").isUndefined(), true);
1840 QCOMPARE(o.error(), false);
1841 QCOMPARE(o.invoked(), 14);
1842 QCOMPARE(o.actuals().count(), 1);
1843 QVERIFY(qvariant_cast<QScriptValue>(o.actuals().at(0)).isArray());
1846 QCOMPARE(engine->evaluate("object.method_intQScriptValue(4, null)").isUndefined(), true);
1847 QCOMPARE(o.error(), false);
1848 QCOMPARE(o.invoked(), 15);
1849 QCOMPARE(o.actuals().count(), 2);
1850 QCOMPARE(o.actuals().at(0), QVariant(4));
1851 QVERIFY(qvariant_cast<QScriptValue>(o.actuals().at(1)).isNull());
1854 QCOMPARE(engine->evaluate("object.method_intQScriptValue(8, undefined)").isUndefined(), true);
1855 QCOMPARE(o.error(), false);
1856 QCOMPARE(o.invoked(), 15);
1857 QCOMPARE(o.actuals().count(), 2);
1858 QCOMPARE(o.actuals().at(0), QVariant(8));
1859 QVERIFY(qvariant_cast<QScriptValue>(o.actuals().at(1)).isUndefined());
1862 QCOMPARE(engine->evaluate("object.method_intQScriptValue(3, 19)").isUndefined(), true);
1863 QCOMPARE(o.error(), false);
1864 QCOMPARE(o.invoked(), 15);
1865 QCOMPARE(o.actuals().count(), 2);
1866 QCOMPARE(o.actuals().at(0), QVariant(3));
1867 QVERIFY(qvariant_cast<QScriptValue>(o.actuals().at(1)).strictlyEquals(QScriptValue(engine, 19)));
1870 QCOMPARE(engine->evaluate("object.method_intQScriptValue(44, [19, 20])").isUndefined(), true);
1871 QCOMPARE(o.error(), false);
1872 QCOMPARE(o.invoked(), 15);
1873 QCOMPARE(o.actuals().count(), 2);
1874 QCOMPARE(o.actuals().at(0), QVariant(44));
1875 QVERIFY(qvariant_cast<QScriptValue>(o.actuals().at(1)).isArray());
1878 QCOMPARE(engine->evaluate("object.method_overload()").isError(), true);
1879 QCOMPARE(o.error(), false);
1880 QCOMPARE(o.invoked(), -1);
1881 QCOMPARE(o.actuals().count(), 0);
1884 QCOMPARE(engine->evaluate("object.method_overload(10)").isUndefined(), true);
1885 QCOMPARE(o.error(), false);
1886 QCOMPARE(o.invoked(), 16);
1887 QCOMPARE(o.actuals().count(), 1);
1888 QCOMPARE(o.actuals().at(0), QVariant(10));
1891 QCOMPARE(engine->evaluate("object.method_overload(10, 11)").isUndefined(), true);
1892 QCOMPARE(o.error(), false);
1893 QCOMPARE(o.invoked(), 17);
1894 QCOMPARE(o.actuals().count(), 2);
1895 QCOMPARE(o.actuals().at(0), QVariant(10));
1896 QCOMPARE(o.actuals().at(1), QVariant(11));
1899 QCOMPARE(engine->evaluate("object.method_overload(\"Hello\")").isUndefined(), true);
1900 QCOMPARE(o.error(), false);
1901 QCOMPARE(o.invoked(), 18);
1902 QCOMPARE(o.actuals().count(), 1);
1903 QCOMPARE(o.actuals().at(0), QVariant(QString("Hello")));
1906 QCOMPARE(engine->evaluate("object.method_with_enum(9)").isUndefined(), true);
1907 QCOMPARE(o.error(), false);
1908 QCOMPARE(o.invoked(), 19);
1909 QCOMPARE(o.actuals().count(), 1);
1910 QCOMPARE(o.actuals().at(0), QVariant(9));
1913 QVERIFY(engine->evaluate("object.method_default(10)").strictlyEquals(QScriptValue(19)));
1914 QCOMPARE(o.error(), false);
1915 QCOMPARE(o.invoked(), 20);
1916 QCOMPARE(o.actuals().count(), 2);
1917 QCOMPARE(o.actuals().at(0), QVariant(10));
1918 QCOMPARE(o.actuals().at(1), QVariant(19));
1921 QVERIFY(engine->evaluate("object.method_default(10, 13)").strictlyEquals(QScriptValue(13)));
1922 QCOMPARE(o.error(), false);
1923 QCOMPARE(o.invoked(), 20);
1924 QCOMPARE(o.actuals().count(), 2);
1925 QCOMPARE(o.actuals().at(0), QVariant(10));
1926 QCOMPARE(o.actuals().at(1), QVariant(13));
1929 QCOMPARE(engine->evaluate("object.method_inherited(9)").isUndefined(), true);
1930 QCOMPARE(o.error(), false);
1931 QCOMPARE(o.invoked(), -3);
1932 QCOMPARE(o.actuals().count(), 1);
1933 QCOMPARE(o.actuals().at(0), QVariant(9));
1936 QCOMPARE(engine->evaluate("object.method_QVariant(9)").isUndefined(), true);
1937 QCOMPARE(o.error(), false);
1938 QCOMPARE(o.invoked(), 21);
1939 QCOMPARE(o.actuals().count(), 2);
1940 QCOMPARE(o.actuals().at(0), QVariant(9));
1941 QCOMPARE(o.actuals().at(1), QVariant());
1944 QCOMPARE(engine->evaluate("object.method_QVariant(\"Hello\", \"World\")").isUndefined(), true);
1945 QCOMPARE(o.error(), false);
1946 QCOMPARE(o.invoked(), 21);
1947 QCOMPARE(o.actuals().count(), 2);
1948 QCOMPARE(o.actuals().at(0), QVariant(QString("Hello")));
1949 QCOMPARE(o.actuals().at(1), QVariant(QString("World")));
1952 // QTBUG-13047 (check that you can pass registered object types as args)
1953 void tst_qdeclarativeecmascript::invokableObjectArg()
1955 QDeclarativeComponent component(&engine, TEST_FILE("invokableObjectArg.qml"));
1957 QObject *o = component.create();
1959 MyQmlObject *qmlobject = qobject_cast<MyQmlObject *>(o);
1961 QCOMPARE(qmlobject->myinvokableObject, qmlobject);
1966 // QTBUG-13047 (check that you can return registered object types from methods)
1967 void tst_qdeclarativeecmascript::invokableObjectRet()
1969 QDeclarativeComponent component(&engine, TEST_FILE("invokableObjectRet.qml"));
1971 QObject *o = component.create();
1973 QCOMPARE(o->property("test").toBool(), true);
1978 void tst_qdeclarativeecmascript::listToVariant()
1980 QDeclarativeComponent component(&engine, TEST_FILE("listToVariant.qml"));
1982 MyQmlContainer container;
1984 QDeclarativeContext context(engine.rootContext());
1985 context.setContextObject(&container);
1987 QObject *object = component.create(&context);
1988 QVERIFY(object != 0);
1990 QVariant v = object->property("test");
1991 QCOMPARE(v.userType(), qMetaTypeId<QDeclarativeListReference>());
1992 QVERIFY(qvariant_cast<QDeclarativeListReference>(v).object() == &container);
1998 void tst_qdeclarativeecmascript::multiEngineObject()
2001 obj.setStringProperty("Howdy planet");
2003 QDeclarativeEngine e1;
2004 e1.rootContext()->setContextProperty("thing", &obj);
2005 QDeclarativeComponent c1(&e1, TEST_FILE("multiEngineObject.qml"));
2007 QDeclarativeEngine e2;
2008 e2.rootContext()->setContextProperty("thing", &obj);
2009 QDeclarativeComponent c2(&e2, TEST_FILE("multiEngineObject.qml"));
2011 QObject *o1 = c1.create();
2012 QObject *o2 = c2.create();
2014 QCOMPARE(o1->property("test").toString(), QString("Howdy planet"));
2015 QCOMPARE(o2->property("test").toString(), QString("Howdy planet"));
2021 // Test that references to QObjects are cleanup when the object is destroyed
2022 void tst_qdeclarativeecmascript::deletedObject()
2024 QDeclarativeComponent component(&engine, TEST_FILE("deletedObject.qml"));
2026 QObject *object = component.create();
2028 QCOMPARE(object->property("test1").toBool(), true);
2029 QCOMPARE(object->property("test2").toBool(), true);
2030 QCOMPARE(object->property("test3").toBool(), true);
2031 QCOMPARE(object->property("test4").toBool(), true);
2036 void tst_qdeclarativeecmascript::attachedPropertyScope()
2038 QDeclarativeComponent component(&engine, TEST_FILE("attachedPropertyScope.qml"));
2040 QObject *object = component.create();
2041 QVERIFY(object != 0);
2043 MyQmlAttachedObject *attached =
2044 qobject_cast<MyQmlAttachedObject *>(qmlAttachedPropertiesObject<MyQmlObject>(object));
2045 QVERIFY(attached != 0);
2047 QCOMPARE(object->property("value2").toInt(), 0);
2049 attached->emitMySignal();
2051 QCOMPARE(object->property("value2").toInt(), 9);
2056 void tst_qdeclarativeecmascript::scriptConnect()
2059 QDeclarativeComponent component(&engine, TEST_FILE("scriptConnect.1.qml"));
2061 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2062 QVERIFY(object != 0);
2064 QCOMPARE(object->property("test").toBool(), false);
2065 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2066 QCOMPARE(object->property("test").toBool(), true);
2072 QDeclarativeComponent component(&engine, TEST_FILE("scriptConnect.2.qml"));
2074 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2075 QVERIFY(object != 0);
2077 QCOMPARE(object->property("test").toBool(), false);
2078 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2079 QCOMPARE(object->property("test").toBool(), true);
2085 QDeclarativeComponent component(&engine, TEST_FILE("scriptConnect.3.qml"));
2087 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2088 QVERIFY(object != 0);
2090 QCOMPARE(object->property("test").toBool(), false);
2091 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2092 QCOMPARE(object->property("test").toBool(), true);
2098 QDeclarativeComponent component(&engine, TEST_FILE("scriptConnect.4.qml"));
2100 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2101 QVERIFY(object != 0);
2103 QCOMPARE(object->methodCalled(), false);
2104 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2105 QCOMPARE(object->methodCalled(), true);
2111 QDeclarativeComponent component(&engine, TEST_FILE("scriptConnect.5.qml"));
2113 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2114 QVERIFY(object != 0);
2116 QCOMPARE(object->methodCalled(), false);
2117 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2118 QCOMPARE(object->methodCalled(), true);
2124 QDeclarativeComponent component(&engine, TEST_FILE("scriptConnect.6.qml"));
2126 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2127 QVERIFY(object != 0);
2129 QCOMPARE(object->property("test").toInt(), 0);
2130 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2131 QCOMPARE(object->property("test").toInt(), 2);
2137 void tst_qdeclarativeecmascript::scriptDisconnect()
2140 QDeclarativeComponent component(&engine, TEST_FILE("scriptDisconnect.1.qml"));
2142 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2143 QVERIFY(object != 0);
2145 QCOMPARE(object->property("test").toInt(), 0);
2146 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2147 QCOMPARE(object->property("test").toInt(), 1);
2148 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2149 QCOMPARE(object->property("test").toInt(), 2);
2150 emit object->basicSignal();
2151 QCOMPARE(object->property("test").toInt(), 2);
2152 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2153 QCOMPARE(object->property("test").toInt(), 2);
2159 QDeclarativeComponent component(&engine, TEST_FILE("scriptDisconnect.2.qml"));
2161 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2162 QVERIFY(object != 0);
2164 QCOMPARE(object->property("test").toInt(), 0);
2165 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2166 QCOMPARE(object->property("test").toInt(), 1);
2167 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2168 QCOMPARE(object->property("test").toInt(), 2);
2169 emit object->basicSignal();
2170 QCOMPARE(object->property("test").toInt(), 2);
2171 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2172 QCOMPARE(object->property("test").toInt(), 2);
2178 QDeclarativeComponent component(&engine, TEST_FILE("scriptDisconnect.3.qml"));
2180 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2181 QVERIFY(object != 0);
2183 QCOMPARE(object->property("test").toInt(), 0);
2184 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2185 QCOMPARE(object->property("test").toInt(), 1);
2186 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2187 QCOMPARE(object->property("test").toInt(), 2);
2188 emit object->basicSignal();
2189 QCOMPARE(object->property("test").toInt(), 2);
2190 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2191 QCOMPARE(object->property("test").toInt(), 3);
2196 QDeclarativeComponent component(&engine, TEST_FILE("scriptDisconnect.4.qml"));
2198 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2199 QVERIFY(object != 0);
2201 QCOMPARE(object->property("test").toInt(), 0);
2202 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2203 QCOMPARE(object->property("test").toInt(), 1);
2204 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2205 QCOMPARE(object->property("test").toInt(), 2);
2206 emit object->basicSignal();
2207 QCOMPARE(object->property("test").toInt(), 2);
2208 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2209 QCOMPARE(object->property("test").toInt(), 3);
2215 class OwnershipObject : public QObject
2219 OwnershipObject() { object = new QObject; }
2221 QPointer<QObject> object;
2224 QObject *getObject() { return object; }
2227 void tst_qdeclarativeecmascript::ownership()
2229 OwnershipObject own;
2230 QDeclarativeContext *context = new QDeclarativeContext(engine.rootContext());
2231 context->setContextObject(&own);
2234 QDeclarativeComponent component(&engine, TEST_FILE("ownership.qml"));
2236 QVERIFY(own.object != 0);
2238 QObject *object = component.create(context);
2239 QDeclarativeEnginePrivate::getScriptEngine(&engine)->collectGarbage();
2241 QCoreApplication::processEvents(QEventLoop::DeferredDeletion);
2243 QVERIFY(own.object == 0);
2248 own.object = new QObject(&own);
2251 QDeclarativeComponent component(&engine, TEST_FILE("ownership.qml"));
2253 QVERIFY(own.object != 0);
2255 QObject *object = component.create(context);
2256 QDeclarativeEnginePrivate::getScriptEngine(&engine)->collectGarbage();
2258 QCoreApplication::processEvents(QEventLoop::DeferredDeletion);
2260 QVERIFY(own.object != 0);
2268 class CppOwnershipReturnValue : public QObject
2272 CppOwnershipReturnValue() : value(0) {}
2273 ~CppOwnershipReturnValue() { delete value; }
2275 Q_INVOKABLE QObject *create() {
2276 value = new QObject;
2277 QDeclarativeEngine::setObjectOwnership(value, QDeclarativeEngine::CppOwnership);
2281 Q_INVOKABLE MyQmlObject *createQmlObject() {
2282 MyQmlObject *rv = new MyQmlObject;
2287 QPointer<QObject> value;
2291 // Test setObjectOwnership(CppOwnership) works even when there is no QDeclarativeData
2292 void tst_qdeclarativeecmascript::cppOwnershipReturnValue()
2294 CppOwnershipReturnValue source;
2297 QDeclarativeEngine engine;
2298 engine.rootContext()->setContextProperty("source", &source);
2300 QVERIFY(source.value == 0);
2302 QDeclarativeComponent component(&engine);
2303 component.setData("import QtQuick 1.0\nQtObject {\nComponent.onCompleted: { var a = source.create(); }\n}\n", QUrl());
2305 QObject *object = component.create();
2307 QVERIFY(object != 0);
2308 QVERIFY(source.value != 0);
2313 QCoreApplication::instance()->processEvents(QEventLoop::DeferredDeletion);
2315 QVERIFY(source.value != 0);
2319 void tst_qdeclarativeecmascript::ownershipCustomReturnValue()
2321 CppOwnershipReturnValue source;
2324 QDeclarativeEngine engine;
2325 engine.rootContext()->setContextProperty("source", &source);
2327 QVERIFY(source.value == 0);
2329 QDeclarativeComponent component(&engine);
2330 component.setData("import QtQuick 1.0\nQtObject {\nComponent.onCompleted: { var a = source.createQmlObject(); }\n}\n", QUrl());
2332 QObject *object = component.create();
2334 QVERIFY(object != 0);
2335 QVERIFY(source.value != 0);
2340 QCoreApplication::instance()->processEvents(QEventLoop::DeferredDeletion);
2342 QVERIFY(source.value == 0);
2345 class QListQObjectMethodsObject : public QObject
2349 QListQObjectMethodsObject() {
2350 m_objects.append(new MyQmlObject());
2351 m_objects.append(new MyQmlObject());
2354 ~QListQObjectMethodsObject() {
2355 qDeleteAll(m_objects);
2359 QList<QObject *> getObjects() { return m_objects; }
2362 QList<QObject *> m_objects;
2365 // Tests that returning a QList<QObject*> from a method works
2366 void tst_qdeclarativeecmascript::qlistqobjectMethods()
2368 QListQObjectMethodsObject obj;
2369 QDeclarativeContext *context = new QDeclarativeContext(engine.rootContext());
2370 context->setContextObject(&obj);
2372 QDeclarativeComponent component(&engine, TEST_FILE("qlistqobjectMethods.qml"));
2374 QObject *object = component.create(context);
2376 QCOMPARE(object->property("test").toInt(), 2);
2377 QCOMPARE(object->property("test2").toBool(), true);
2384 void tst_qdeclarativeecmascript::strictlyEquals()
2386 QDeclarativeComponent component(&engine, TEST_FILE("strictlyEquals.qml"));
2388 QObject *object = component.create();
2389 QVERIFY(object != 0);
2391 QCOMPARE(object->property("test1").toBool(), true);
2392 QCOMPARE(object->property("test2").toBool(), true);
2393 QCOMPARE(object->property("test3").toBool(), true);
2394 QCOMPARE(object->property("test4").toBool(), true);
2395 QCOMPARE(object->property("test5").toBool(), true);
2396 QCOMPARE(object->property("test6").toBool(), true);
2397 QCOMPARE(object->property("test7").toBool(), true);
2398 QCOMPARE(object->property("test8").toBool(), true);
2403 void tst_qdeclarativeecmascript::compiled()
2405 QDeclarativeComponent component(&engine, TEST_FILE("compiled.qml"));
2407 QObject *object = component.create();
2408 QVERIFY(object != 0);
2410 QCOMPARE(object->property("test1").toReal(), qreal(15.7));
2411 QCOMPARE(object->property("test2").toReal(), qreal(-6.7));
2412 QCOMPARE(object->property("test3").toBool(), true);
2413 QCOMPARE(object->property("test4").toBool(), false);
2414 QCOMPARE(object->property("test5").toBool(), false);
2415 QCOMPARE(object->property("test6").toBool(), true);
2417 QCOMPARE(object->property("test7").toInt(), 185);
2418 QCOMPARE(object->property("test8").toInt(), 167);
2419 QCOMPARE(object->property("test9").toBool(), true);
2420 QCOMPARE(object->property("test10").toBool(), false);
2421 QCOMPARE(object->property("test11").toBool(), false);
2422 QCOMPARE(object->property("test12").toBool(), true);
2424 QCOMPARE(object->property("test13").toString(), QLatin1String("HelloWorld"));
2425 QCOMPARE(object->property("test14").toString(), QLatin1String("Hello World"));
2426 QCOMPARE(object->property("test15").toBool(), false);
2427 QCOMPARE(object->property("test16").toBool(), true);
2429 QCOMPARE(object->property("test17").toInt(), 5);
2430 QCOMPARE(object->property("test18").toReal(), qreal(176));
2431 QCOMPARE(object->property("test19").toInt(), 7);
2432 QCOMPARE(object->property("test20").toReal(), qreal(6.7));
2433 QCOMPARE(object->property("test21").toString(), QLatin1String("6.7"));
2434 QCOMPARE(object->property("test22").toString(), QLatin1String("!"));
2435 QCOMPARE(object->property("test23").toBool(), true);
2436 QCOMPARE(qvariant_cast<QColor>(object->property("test24")), QColor(0x11,0x22,0x33));
2437 QCOMPARE(qvariant_cast<QColor>(object->property("test25")), QColor(0x11,0x22,0x33,0xAA));
2442 // Test that numbers assigned in bindings as strings work consistently
2443 void tst_qdeclarativeecmascript::numberAssignment()
2445 QDeclarativeComponent component(&engine, TEST_FILE("numberAssignment.qml"));
2447 QObject *object = component.create();
2448 QVERIFY(object != 0);
2450 QCOMPARE(object->property("test1"), QVariant((qreal)6.7));
2451 QCOMPARE(object->property("test2"), QVariant((qreal)6.7));
2452 QCOMPARE(object->property("test2"), QVariant((qreal)6.7));
2453 QCOMPARE(object->property("test3"), QVariant((qreal)6));
2454 QCOMPARE(object->property("test4"), QVariant((qreal)6));
2456 QCOMPARE(object->property("test5"), QVariant((int)7));
2457 QCOMPARE(object->property("test6"), QVariant((int)7));
2458 QCOMPARE(object->property("test7"), QVariant((int)6));
2459 QCOMPARE(object->property("test8"), QVariant((int)6));
2461 QCOMPARE(object->property("test9"), QVariant((unsigned int)7));
2462 QCOMPARE(object->property("test10"), QVariant((unsigned int)7));
2463 QCOMPARE(object->property("test11"), QVariant((unsigned int)6));
2464 QCOMPARE(object->property("test12"), QVariant((unsigned int)6));
2469 void tst_qdeclarativeecmascript::propertySplicing()
2471 QDeclarativeComponent component(&engine, TEST_FILE("propertySplicing.qml"));
2473 QObject *object = component.create();
2474 QVERIFY(object != 0);
2476 QCOMPARE(object->property("test").toBool(), true);
2482 void tst_qdeclarativeecmascript::signalWithUnknownTypes()
2484 QDeclarativeComponent component(&engine, TEST_FILE("signalWithUnknownTypes.qml"));
2486 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2487 QVERIFY(object != 0);
2489 MyQmlObject::MyType type;
2490 type.value = 0x8971123;
2491 emit object->signalWithUnknownType(type);
2493 MyQmlObject::MyType result = qvariant_cast<MyQmlObject::MyType>(object->variant());
2495 QCOMPARE(result.value, type.value);
2501 void tst_qdeclarativeecmascript::moduleApi()
2503 QDeclarativeComponent component(&engine, TEST_FILE("moduleApi.qml"));
2504 QObject *object = component.create();
2505 QVERIFY(object != 0);
2506 QCOMPARE(object->property("existingUriTest").toInt(), 20);
2507 QCOMPARE(object->property("scriptTest").toInt(), 13);
2508 QCOMPARE(object->property("qobjectTest").toInt(), 20);
2509 QCOMPARE(object->property("qobjectMethodTest").toInt(), 1); // first call of method, so count = 1.
2510 QCOMPARE(object->property("qobjectMinorVersionTest").toInt(), 20);
2511 QCOMPARE(object->property("qobjectMajorVersionTest").toInt(), 20);
2512 QCOMPARE(object->property("qobjectParentedTest").toInt(), 26);
2515 // test that caching of module apis works correctly.
2516 QDeclarativeComponent componentTwo(&engine, TEST_FILE("moduleApiCaching.qml"));
2517 object = componentTwo.create();
2518 QVERIFY(object != 0);
2519 QCOMPARE(object->property("existingUriTest").toInt(), 20);
2520 QCOMPARE(object->property("scriptTest").toInt(), 13); // shouldn't have incremented.
2521 QCOMPARE(object->property("qobjectParentedTest").toInt(), 26); // shouldn't have incremented.
2524 // test that writing to a property of module apis works correctly.
2525 QDeclarativeComponent componentThree(&engine, TEST_FILE("moduleApiWriting.qml"));
2526 QString expectedWarning = QLatin1String("file://") + TEST_FILE("moduleApiWriting.qml").toLocalFile() + QLatin1String(":15: Error: Cannot assign to read-only property \"qobjectTestProperty\"");
2527 QTest::ignoreMessage(QtWarningMsg, expectedWarning.toAscii().constData());
2528 object = componentThree.create();
2529 QVERIFY(object != 0);
2530 QCOMPARE(object->property("readOnlyProperty").toInt(), 20);
2531 QCOMPARE(object->property("writableProperty").toInt(), 50);
2532 QVERIFY(object->setProperty("firstProperty", QVariant(30))); // shouldn't affect value of readOnlyProperty
2533 QVERIFY(object->setProperty("writableProperty", QVariant(30))); // SHOULD affect value of writableProperty
2534 QCOMPARE(object->property("readOnlyProperty").toInt(), 20);
2535 QCOMPARE(object->property("writableProperty").toInt(), 30);
2538 QDeclarativeComponent failOne(&engine, TEST_FILE("moduleApiMajorVersionFail.qml"));
2539 QTest::ignoreMessage(QtWarningMsg, "QDeclarativeComponent: Component is not ready");
2540 object = failOne.create();
2541 QVERIFY(object == 0); // should have failed: invalid major version
2543 QDeclarativeComponent failTwo(&engine, TEST_FILE("moduleApiMinorVersionFail.qml"));
2544 QTest::ignoreMessage(QtWarningMsg, "QDeclarativeComponent: Component is not ready");
2545 object = failTwo.create();
2546 QVERIFY(object == 0); // should have failed: invalid minor version
2549 void tst_qdeclarativeecmascript::importScripts()
2551 QObject *object = 0;
2553 // first, ensure that the required behaviour works.
2554 QDeclarativeComponent component(&engine, TEST_FILE("jsimport/testImport.qml"));
2555 object = component.create();
2556 QVERIFY(object != 0);
2557 QCOMPARE(object->property("importedScriptStringValue"), QVariant(QString(QLatin1String("Hello, World!"))));
2558 QCOMPARE(object->property("importedScriptFunctionValue"), QVariant(20));
2559 QCOMPARE(object->property("importedModuleAttachedPropertyValue"), QVariant(19));
2560 QCOMPARE(object->property("importedModuleEnumValue"), QVariant(2));
2563 QDeclarativeComponent componentTwo(&engine, TEST_FILE("jsimport/testImportScoping.qml"));
2564 object = componentTwo.create();
2565 QVERIFY(object != 0);
2566 QCOMPARE(object->property("componentError"), QVariant(5));
2569 // then, ensure that unintended behaviour does not work.
2570 QDeclarativeComponent failOneComponent(&engine, TEST_FILE("jsimportfail/failOne.qml"));
2571 QString expectedWarning = QLatin1String("file://") + TEST_FILE("jsimportfail/failOne.qml").toLocalFile() + QLatin1String(":6: TypeError: Result of expression 'TestScriptImport.ImportOneJs' [undefined] is not an object.");
2572 QTest::ignoreMessage(QtWarningMsg, expectedWarning.toAscii().constData());
2573 object = failOneComponent.create();
2574 QVERIFY(object != 0);
2575 QVERIFY(object->property("importScriptFunctionValue").toString().isEmpty());
2577 QDeclarativeComponent failTwoComponent(&engine, TEST_FILE("jsimportfail/failTwo.qml"));
2578 expectedWarning = QLatin1String("file://") + TEST_FILE("jsimportfail/failTwo.qml").toLocalFile() + QLatin1String(":6: ReferenceError: Can't find variable: ImportOneJs");
2579 QTest::ignoreMessage(QtWarningMsg, expectedWarning.toAscii().constData());
2580 object = failTwoComponent.create();
2581 QVERIFY(object != 0);
2582 QVERIFY(object->property("importScriptFunctionValue").toString().isEmpty());
2584 QDeclarativeComponent failThreeComponent(&engine, TEST_FILE("jsimportfail/failThree.qml"));
2585 expectedWarning = QLatin1String("file://") + TEST_FILE("jsimportfail/failThree.qml").toLocalFile() + QLatin1String(":7: TypeError: Result of expression 'testQtObject.TestModuleImport.JsQtTest' [undefined] is not an object.");
2586 QTest::ignoreMessage(QtWarningMsg, expectedWarning.toAscii().constData());
2587 object = failThreeComponent.create();
2588 QVERIFY(object != 0);
2589 QCOMPARE(object->property("importedModuleAttachedPropertyValue"), QVariant(false));
2591 QDeclarativeComponent failFourComponent(&engine, TEST_FILE("jsimportfail/failFour.qml"));
2592 expectedWarning = QLatin1String("file://") + TEST_FILE("jsimportfail/failFour.qml").toLocalFile() + QLatin1String(":6: ReferenceError: Can't find variable: JsQtTest");
2593 QTest::ignoreMessage(QtWarningMsg, expectedWarning.toAscii().constData());
2594 object = failFourComponent.create();
2595 QVERIFY(object != 0);
2596 QCOMPARE(object->property("importedModuleEnumValue"), QVariant(0));
2598 QDeclarativeComponent failFiveComponent(&engine, TEST_FILE("jsimportfail/failFive.qml"));
2599 expectedWarning = QLatin1String("file://") + TEST_FILE("jsimportfail/importWithImports.js").toLocalFile() + QLatin1String(":8: ReferenceError: Can't find variable: Component");
2600 QTest::ignoreMessage(QtWarningMsg, expectedWarning.toAscii().constData());
2601 expectedWarning = QLatin1String("file://") + TEST_FILE("jsimportfail/importPragmaLibrary.js").toLocalFile() + QLatin1String(":6: ReferenceError: Can't find variable: Component");
2602 QTest::ignoreMessage(QtWarningMsg, expectedWarning.toAscii().constData());
2603 object = failFiveComponent.create();
2604 QVERIFY(object != 0);
2605 QCOMPARE(object->property("componentError"), QVariant(0));
2608 // also, test that importing scripts with .pragma library works as required
2609 QDeclarativeComponent pragmaLibraryComponent(&engine, TEST_FILE("jsimport/testImportPragmaLibrary.qml"));
2610 object = pragmaLibraryComponent.create();
2611 QVERIFY(object != 0);
2612 QCOMPARE(object->property("testValue"), QVariant(31));
2615 // and that .pragma library scripts don't inherit imports from any .qml file
2616 QDeclarativeComponent pragmaLibraryComponentTwo(&engine, TEST_FILE("jsimportfail/testImportPragmaLibrary.qml"));
2617 object = pragmaLibraryComponentTwo.create();
2618 QVERIFY(object != 0);
2619 QCOMPARE(object->property("testValue"), QVariant(0));
2623 void tst_qdeclarativeecmascript::scarceResources()
2625 QPixmap origPixmap(100, 100);
2626 origPixmap.fill(Qt::blue);
2628 QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(&engine);
2629 ScarceResourceObject *eo = 0;
2630 QObject *object = 0;
2632 // in the following three cases, the instance created from the component
2633 // has a property which is a copy of the scarce resource; hence, the
2634 // resource should NOT be detached prior to deletion of the object instance,
2635 // unless the resource is destroyed explicitly.
2636 QDeclarativeComponent component(&engine, TEST_FILE("scarceresources/scarceResourceCopy.qml"));
2637 object = component.create();
2638 QVERIFY(object != 0);
2639 QVERIFY(object->property("scarceResourceCopy").isValid());
2640 QCOMPARE(object->property("scarceResourceCopy").value<QPixmap>(), origPixmap);
2641 QVERIFY(ep->scarceResources == 0); // should have been released by this point.
2642 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2643 QVERIFY(!eo->scarceResourceIsDetached()); // there are two copies of it in existence: the property of object, and the property of eo.
2646 QDeclarativeComponent componentTwo(&engine, TEST_FILE("scarceresources/scarceResourceCopyFromJs.qml"));
2647 object = componentTwo.create();
2648 QVERIFY(object != 0);
2649 QVERIFY(object->property("scarceResourceCopy").isValid());
2650 QCOMPARE(object->property("scarceResourceCopy").value<QPixmap>(), origPixmap);
2651 QVERIFY(ep->scarceResources == 0); // should have been released by this point.
2652 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2653 QVERIFY(!eo->scarceResourceIsDetached()); // there are two copies of it in existence: the property of object, and the property of eo.
2656 QDeclarativeComponent componentThree(&engine, TEST_FILE("scarceresources/scarceResourceDestroyedCopy.qml"));
2657 object = componentThree.create();
2658 QVERIFY(object != 0);
2659 QVERIFY(!(object->property("scarceResourceCopy").isValid())); // was manually released prior to being returned.
2660 QVERIFY(ep->scarceResources == 0); // should have been released by this point.
2661 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2662 QVERIFY(eo->scarceResourceIsDetached()); // should have explicitly been released during the evaluation of the binding.
2665 // in the following three cases, no other copy should exist in memory,
2666 // and so it should be detached (unless explicitly preserved).
2667 QDeclarativeComponent componentFour(&engine, TEST_FILE("scarceresources/scarceResourceTest.qml"));
2668 object = componentFour.create();
2669 QVERIFY(object != 0);
2670 QVERIFY(object->property("scarceResourceTest").isValid());
2671 QCOMPARE(object->property("scarceResourceTest").toInt(), 100);
2672 QVERIFY(ep->scarceResources == 0); // should have been released by this point.
2673 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2674 QVERIFY(eo->scarceResourceIsDetached()); // the resource should have been released after the binding was evaluated.
2677 QDeclarativeComponent componentFive(&engine, TEST_FILE("scarceresources/scarceResourceTestPreserve.qml"));
2678 object = componentFive.create();
2679 QVERIFY(object != 0);
2680 QVERIFY(object->property("scarceResourceTest").isValid());
2681 QCOMPARE(object->property("scarceResourceTest").toInt(), 100);
2682 QVERIFY(ep->scarceResources == 0); // should have been released by this point.
2683 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2684 QVERIFY(!eo->scarceResourceIsDetached()); // this won't be detached since we explicitly preserved it.
2687 QDeclarativeComponent componentSix(&engine, TEST_FILE("scarceresources/scarceResourceTestMultiple.qml"));
2688 object = componentSix.create();
2689 QVERIFY(object != 0);
2690 QVERIFY(object->property("scarceResourceTest").isValid());
2691 QCOMPARE(object->property("scarceResourceTest").toInt(), 100);
2692 QVERIFY(ep->scarceResources == 0); // should have been released by this point.
2693 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2694 QVERIFY(eo->scarceResourceIsDetached()); // all resources were released manually or automatically released.
2697 // test that scarce resources are handled correctly for imports
2698 QDeclarativeComponent componentSeven(&engine, TEST_FILE("scarceresources/scarceResourceCopyImportNoBinding.qml"));
2699 object = componentSeven.create();
2700 QVERIFY(object != 0); // the import should have caused the addition of a resource to the ScarceResources list
2701 QVERIFY(ep->scarceResources == 0); // but they should have been released by this point.
2704 QDeclarativeComponent componentEight(&engine, TEST_FILE("scarceresources/scarceResourceCopyImportFail.qml"));
2705 object = componentEight.create();
2706 QVERIFY(object != 0);
2707 QVERIFY(!object->property("scarceResourceCopy").isValid()); // wasn't preserved, so shouldn't be valid.
2708 QVERIFY(ep->scarceResources == 0); // should have been released by this point.
2711 QDeclarativeComponent componentNine(&engine, TEST_FILE("scarceresources/scarceResourceCopyImport.qml"));
2712 object = componentNine.create();
2713 QVERIFY(object != 0);
2714 QVERIFY(object->property("scarceResourceCopy").isValid()); // preserved, so should be valid.
2715 QCOMPARE(object->property("scarceResourceCopy").value<QPixmap>(), origPixmap);
2716 QVERIFY(object->property("scarceResourceAssignedCopyOne").isValid()); // assigned before destroy(), so should be valid.
2717 QCOMPARE(object->property("scarceResourceAssignedCopyOne").value<QPixmap>(), origPixmap);
2718 QVERIFY(!object->property("scarceResourceAssignedCopyTwo").isValid()); // assigned after destroy(), so should be invalid.
2719 QVERIFY(ep->scarceResources == 0); // this will still be zero, because "preserve()" REMOVES it from this list.
2722 // test that scarce resources are handled properly in signal invocation
2723 QDeclarativeComponent componentTen(&engine, TEST_FILE("scarceresources/scarceResourceSignal.qml"));
2724 object = componentTen.create();
2725 QVERIFY(object != 0);
2726 QObject *srsc = object->findChild<QObject*>("srsc");
2728 QVERIFY(!srsc->property("scarceResourceCopy").isValid()); // hasn't been instantiated yet.
2729 QCOMPARE(srsc->property("width"), QVariant(5)); // default value is 5.
2730 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2731 QVERIFY(eo->scarceResourceIsDetached()); // should be no other copies of it at this stage.
2732 QMetaObject::invokeMethod(srsc, "testSignal");
2733 QVERIFY(!srsc->property("scarceResourceCopy").isValid()); // still hasn't been instantiated
2734 QCOMPARE(srsc->property("width"), QVariant(10)); // but width was assigned to 10.
2735 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2736 QVERIFY(eo->scarceResourceIsDetached()); // should still be no other copies of it at this stage.
2737 QMetaObject::invokeMethod(srsc, "testSignal2"); // assigns scarceResourceCopy to the scarce pixmap.
2738 QVERIFY(srsc->property("scarceResourceCopy").isValid());
2739 QCOMPARE(srsc->property("scarceResourceCopy").value<QPixmap>(), origPixmap);
2740 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2741 QVERIFY(!(eo->scarceResourceIsDetached())); // should be another copy of the resource now.
2742 QVERIFY(ep->scarceResources == 0); // should have been released by this point.
2745 // test that scarce resources are handled properly from js functions in qml files
2746 QDeclarativeComponent componentEleven(&engine, TEST_FILE("scarceresources/scarceResourceFunction.qml"));
2747 object = componentEleven.create();
2748 QVERIFY(object != 0);
2749 QVERIFY(!object->property("scarceResourceCopy").isValid()); // not yet assigned, so should not be valid
2750 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2751 QVERIFY(eo->scarceResourceIsDetached()); // should be no other copies of it at this stage.
2752 QMetaObject::invokeMethod(object, "retrieveScarceResource");
2753 QVERIFY(object->property("scarceResourceCopy").isValid()); // assigned, so should be valid.
2754 QCOMPARE(object->property("scarceResourceCopy").value<QPixmap>(), origPixmap);
2755 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2756 QVERIFY(!eo->scarceResourceIsDetached()); // should be a copy of the resource at this stage.
2757 QMetaObject::invokeMethod(object, "releaseScarceResource");
2758 QVERIFY(!object->property("scarceResourceCopy").isValid()); // just released, so should not be valid
2759 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2760 QVERIFY(eo->scarceResourceIsDetached()); // should be no other copies of it at this stage.
2761 QVERIFY(ep->scarceResources == 0); // should have been released by this point.
2764 // test that if an exception occurs while invoking js function from cpp, that the resources are released.
2765 QDeclarativeComponent componentTwelve(&engine, TEST_FILE("scarceresources/scarceResourceFunctionFail.qml"));
2766 object = componentTwelve.create();
2767 QVERIFY(object != 0);
2768 QVERIFY(!object->property("scarceResourceCopy").isValid()); // not yet assigned, so should not be valid
2769 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2770 QVERIFY(eo->scarceResourceIsDetached()); // should be no other copies of it at this stage.
2771 QString expectedWarning = QLatin1String("file://") + TEST_FILE("scarceresources/scarceResourceFunctionFail.qml").toLocalFile() + QLatin1String(":16: TypeError: Result of expression 'scarceResourceProvider.scarceResource' [[object Object]] is not a function.");
2772 QTest::ignoreMessage(QtWarningMsg, expectedWarning.toAscii().constData()); // we expect a meaningful warning to be printed.
2773 QMetaObject::invokeMethod(object, "retrieveScarceResource");
2774 QVERIFY(!object->property("scarceResourceCopy").isValid()); // due to exception, assignment will NOT have occurred.
2775 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2776 QVERIFY(eo->scarceResourceIsDetached()); // should be no other copies of it at this stage.
2777 QVERIFY(ep->scarceResources == 0); // should have been released by this point.
2781 void tst_qdeclarativeecmascript::propertyChangeSlots()
2783 // ensure that allowable property names are allowed and onPropertyNameChanged slots are generated correctly.
2784 QDeclarativeComponent component(&engine, TEST_FILE("changeslots/propertyChangeSlots.qml"));
2785 QObject *object = component.create();
2786 QVERIFY(object != 0);
2789 // ensure that invalid property names fail properly.
2790 QTest::ignoreMessage(QtWarningMsg, "QDeclarativeComponent: Component is not ready");
2791 QDeclarativeComponent e1(&engine, TEST_FILE("changeslots/propertyChangeSlotErrors.1.qml"));
2792 QString expectedErrorString = e1.url().toString() + QLatin1String(":9:5: Cannot assign to non-existent property \"on_nameWithUnderscoreChanged\"");
2793 QCOMPARE(e1.errors().at(0).toString(), expectedErrorString);
2794 object = e1.create();
2795 QVERIFY(object == 0);
2798 QTest::ignoreMessage(QtWarningMsg, "QDeclarativeComponent: Component is not ready");
2799 QDeclarativeComponent e2(&engine, TEST_FILE("changeslots/propertyChangeSlotErrors.2.qml"));
2800 expectedErrorString = e2.url().toString() + QLatin1String(":9:5: Cannot assign to non-existent property \"on____nameWithUnderscoresChanged\"");
2801 QCOMPARE(e2.errors().at(0).toString(), expectedErrorString);
2802 object = e2.create();
2803 QVERIFY(object == 0);
2806 QTest::ignoreMessage(QtWarningMsg, "QDeclarativeComponent: Component is not ready");
2807 QDeclarativeComponent e3(&engine, TEST_FILE("changeslots/propertyChangeSlotErrors.3.qml"));
2808 expectedErrorString = e3.url().toString() + QLatin1String(":9:5: Cannot assign to non-existent property \"on$NameWithDollarsignChanged\"");
2809 QCOMPARE(e3.errors().at(0).toString(), expectedErrorString);
2810 object = e3.create();
2811 QVERIFY(object == 0);
2814 QTest::ignoreMessage(QtWarningMsg, "QDeclarativeComponent: Component is not ready");
2815 QDeclarativeComponent e4(&engine, TEST_FILE("changeslots/propertyChangeSlotErrors.4.qml"));
2816 expectedErrorString = e4.url().toString() + QLatin1String(":9:5: Cannot assign to non-existent property \"on_6NameWithUnderscoreNumberChanged\"");
2817 QCOMPARE(e4.errors().at(0).toString(), expectedErrorString);
2818 object = e4.create();
2819 QVERIFY(object == 0);
2823 // Test that assigning a null object works
2824 // Regressed with: df1788b4dbbb2826ae63f26bdf166342595343f4
2825 void tst_qdeclarativeecmascript::nullObjectBinding()
2827 QDeclarativeComponent component(&engine, TEST_FILE("nullObjectBinding.qml"));
2829 QObject *object = component.create();
2830 QVERIFY(object != 0);
2832 QVERIFY(object->property("test") == QVariant::fromValue((QObject *)0));
2837 // Test that bindings don't evaluate once the engine has been destroyed
2838 void tst_qdeclarativeecmascript::deletedEngine()
2840 QDeclarativeEngine *engine = new QDeclarativeEngine;
2841 QDeclarativeComponent component(engine, TEST_FILE("deletedEngine.qml"));
2843 QObject *object = component.create();
2844 QVERIFY(object != 0);
2846 QCOMPARE(object->property("a").toInt(), 39);
2847 object->setProperty("b", QVariant(9));
2848 QCOMPARE(object->property("a").toInt(), 117);
2852 QCOMPARE(object->property("a").toInt(), 117);
2853 object->setProperty("b", QVariant(10));
2854 QCOMPARE(object->property("a").toInt(), 117);
2859 // Test the crashing part of QTBUG-9705
2860 void tst_qdeclarativeecmascript::libraryScriptAssert()
2862 QDeclarativeComponent component(&engine, TEST_FILE("libraryScriptAssert.qml"));
2864 QObject *object = component.create();
2865 QVERIFY(object != 0);
2870 void tst_qdeclarativeecmascript::variantsAssignedUndefined()
2872 QDeclarativeComponent component(&engine, TEST_FILE("variantsAssignedUndefined.qml"));
2874 QObject *object = component.create();
2875 QVERIFY(object != 0);
2877 QCOMPARE(object->property("test1").toInt(), 10);
2878 QCOMPARE(object->property("test2").toInt(), 11);
2880 object->setProperty("runTest", true);
2882 QCOMPARE(object->property("test1"), QVariant());
2883 QCOMPARE(object->property("test2"), QVariant());
2889 void tst_qdeclarativeecmascript::qtbug_9792()
2891 QDeclarativeComponent component(&engine, TEST_FILE("qtbug_9792.qml"));
2893 QDeclarativeContext *context = new QDeclarativeContext(engine.rootContext());
2895 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create(context));
2896 QVERIFY(object != 0);
2898 QTest::ignoreMessage(QtDebugMsg, "Hello world!");
2899 object->basicSignal();
2903 transientErrorsMsgCount = 0;
2904 QtMsgHandler old = qInstallMsgHandler(transientErrorsMsgHandler);
2906 object->basicSignal();
2908 qInstallMsgHandler(old);
2910 QCOMPARE(transientErrorsMsgCount, 0);
2915 // Verifies that QDeclarativeGuard<>s used in the vmemetaobject are cleaned correctly
2916 void tst_qdeclarativeecmascript::qtcreatorbug_1289()
2918 QDeclarativeComponent component(&engine, TEST_FILE("qtcreatorbug_1289.qml"));
2920 QObject *o = component.create();
2923 QObject *nested = qvariant_cast<QObject *>(o->property("object"));
2924 QVERIFY(nested != 0);
2926 QVERIFY(qvariant_cast<QObject *>(nested->property("nestedObject")) == o);
2929 nested = qvariant_cast<QObject *>(o->property("object"));
2930 QVERIFY(nested == 0);
2932 // If the bug is present, the next line will crash
2936 // Test that we shut down without stupid warnings
2937 void tst_qdeclarativeecmascript::noSpuriousWarningsAtShutdown()
2940 QDeclarativeComponent component(&engine, TEST_FILE("noSpuriousWarningsAtShutdown.qml"));
2942 QObject *o = component.create();
2944 transientErrorsMsgCount = 0;
2945 QtMsgHandler old = qInstallMsgHandler(transientErrorsMsgHandler);
2949 qInstallMsgHandler(old);
2951 QCOMPARE(transientErrorsMsgCount, 0);
2956 QDeclarativeComponent component(&engine, TEST_FILE("noSpuriousWarningsAtShutdown.2.qml"));
2958 QObject *o = component.create();
2960 transientErrorsMsgCount = 0;
2961 QtMsgHandler old = qInstallMsgHandler(transientErrorsMsgHandler);
2965 qInstallMsgHandler(old);
2967 QCOMPARE(transientErrorsMsgCount, 0);
2971 void tst_qdeclarativeecmascript::canAssignNullToQObject()
2974 QDeclarativeComponent component(&engine, TEST_FILE("canAssignNullToQObject.1.qml"));
2976 MyQmlObject *o = qobject_cast<MyQmlObject *>(component.create());
2979 QVERIFY(o->objectProperty() != 0);
2981 o->setProperty("runTest", true);
2983 QVERIFY(o->objectProperty() == 0);
2989 QDeclarativeComponent component(&engine, TEST_FILE("canAssignNullToQObject.2.qml"));
2991 MyQmlObject *o = qobject_cast<MyQmlObject *>(component.create());
2994 QVERIFY(o->objectProperty() == 0);
3000 void tst_qdeclarativeecmascript::functionAssignment_fromBinding()
3002 QDeclarativeComponent component(&engine, TEST_FILE("functionAssignment.1.qml"));
3004 QString url = component.url().toString();
3005 QString warning = url + ":4: Unable to assign a function to a property.";
3006 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
3008 MyQmlObject *o = qobject_cast<MyQmlObject *>(component.create());
3011 QVERIFY(!o->property("a").isValid());
3016 void tst_qdeclarativeecmascript::functionAssignment_fromJS()
3018 QFETCH(QString, triggerProperty);
3020 QDeclarativeComponent component(&engine, TEST_FILE("functionAssignment.2.qml"));
3021 QVERIFY2(component.errorString().isEmpty(), qPrintable(component.errorString()));
3023 MyQmlObject *o = qobject_cast<MyQmlObject *>(component.create());
3025 QVERIFY(!o->property("a").isValid());
3027 o->setProperty("aNumber", QVariant(5));
3028 o->setProperty(triggerProperty.toUtf8().constData(), true);
3029 QCOMPARE(o->property("a"), QVariant(50));
3031 o->setProperty("aNumber", QVariant(10));
3032 QCOMPARE(o->property("a"), QVariant(100));
3037 void tst_qdeclarativeecmascript::functionAssignment_fromJS_data()
3039 QTest::addColumn<QString>("triggerProperty");
3041 QTest::newRow("assign to property") << "assignToProperty";
3042 QTest::newRow("assign to property, from JS file") << "assignToPropertyFromJsFile";
3044 QTest::newRow("assign to value type") << "assignToValueType";
3046 QTest::newRow("use 'this'") << "assignWithThis";
3047 QTest::newRow("use 'this' from JS file") << "assignWithThisFromJsFile";
3050 void tst_qdeclarativeecmascript::functionAssignmentfromJS_invalid()
3052 QDeclarativeComponent component(&engine, TEST_FILE("functionAssignment.2.qml"));
3053 QVERIFY2(component.errorString().isEmpty(), qPrintable(component.errorString()));
3055 MyQmlObject *o = qobject_cast<MyQmlObject *>(component.create());
3057 QVERIFY(!o->property("a").isValid());
3059 o->setProperty("assignFuncWithoutReturn", true);
3060 QVERIFY(!o->property("a").isValid());
3062 QString url = component.url().toString();
3063 QString warning = url + ":63: Unable to assign QString to int";
3064 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
3065 o->setProperty("assignWrongType", true);
3067 warning = url + ":70: Unable to assign QString to int";
3068 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
3069 o->setProperty("assignWrongTypeToValueType", true);
3074 void tst_qdeclarativeecmascript::eval()
3076 QDeclarativeComponent component(&engine, TEST_FILE("eval.qml"));
3078 QObject *o = component.create();
3081 QCOMPARE(o->property("test1").toBool(), true);
3082 QCOMPARE(o->property("test2").toBool(), true);
3083 QCOMPARE(o->property("test3").toBool(), true);
3084 QCOMPARE(o->property("test4").toBool(), true);
3085 QCOMPARE(o->property("test5").toBool(), true);
3090 void tst_qdeclarativeecmascript::function()
3092 QDeclarativeComponent component(&engine, TEST_FILE("function.qml"));
3094 QObject *o = component.create();
3097 QCOMPARE(o->property("test1").toBool(), true);
3098 QCOMPARE(o->property("test2").toBool(), true);
3099 QCOMPARE(o->property("test3").toBool(), true);
3104 // Test the "Qt.include" method
3105 void tst_qdeclarativeecmascript::include()
3107 // Non-library relative include
3109 QDeclarativeComponent component(&engine, TEST_FILE("include.qml"));
3110 QObject *o = component.create();
3113 QCOMPARE(o->property("test0").toInt(), 99);
3114 QCOMPARE(o->property("test1").toBool(), true);
3115 QCOMPARE(o->property("test2").toBool(), true);
3116 QCOMPARE(o->property("test2_1").toBool(), true);
3117 QCOMPARE(o->property("test3").toBool(), true);
3118 QCOMPARE(o->property("test3_1").toBool(), true);
3123 // Library relative include
3125 QDeclarativeComponent component(&engine, TEST_FILE("include_shared.qml"));
3126 QObject *o = component.create();
3129 QCOMPARE(o->property("test0").toInt(), 99);
3130 QCOMPARE(o->property("test1").toBool(), true);
3131 QCOMPARE(o->property("test2").toBool(), true);
3132 QCOMPARE(o->property("test2_1").toBool(), true);
3133 QCOMPARE(o->property("test3").toBool(), true);
3134 QCOMPARE(o->property("test3_1").toBool(), true);
3141 QDeclarativeComponent component(&engine, TEST_FILE("include_callback.qml"));
3142 QObject *o = component.create();
3145 QCOMPARE(o->property("test1").toBool(), true);
3146 QCOMPARE(o->property("test2").toBool(), true);
3147 QCOMPARE(o->property("test3").toBool(), true);
3148 QCOMPARE(o->property("test4").toBool(), true);
3149 QCOMPARE(o->property("test5").toBool(), true);
3150 QCOMPARE(o->property("test6").toBool(), true);
3155 // Including file with ".pragma library"
3157 QDeclarativeComponent component(&engine, TEST_FILE("include_pragma.qml"));
3158 QObject *o = component.create();
3160 QCOMPARE(o->property("test1").toInt(), 100);
3167 TestHTTPServer server(8111);
3168 QVERIFY(server.isValid());
3169 server.serveDirectory(SRCDIR "/data");
3171 QDeclarativeComponent component(&engine, TEST_FILE("include_remote.qml"));
3172 QObject *o = component.create();
3175 QTRY_VERIFY(o->property("done").toBool() == true);
3176 QTRY_VERIFY(o->property("done2").toBool() == true);
3178 QCOMPARE(o->property("test1").toBool(), true);
3179 QCOMPARE(o->property("test2").toBool(), true);
3180 QCOMPARE(o->property("test3").toBool(), true);
3181 QCOMPARE(o->property("test4").toBool(), true);
3182 QCOMPARE(o->property("test5").toBool(), true);
3184 QCOMPARE(o->property("test6").toBool(), true);
3185 QCOMPARE(o->property("test7").toBool(), true);
3186 QCOMPARE(o->property("test8").toBool(), true);
3187 QCOMPARE(o->property("test9").toBool(), true);
3188 QCOMPARE(o->property("test10").toBool(), true);
3195 TestHTTPServer server(8111);
3196 QVERIFY(server.isValid());
3197 server.serveDirectory(SRCDIR "/data");
3199 QDeclarativeComponent component(&engine, TEST_FILE("include_remote_missing.qml"));
3200 QObject *o = component.create();
3203 QTRY_VERIFY(o->property("done").toBool() == true);
3205 QCOMPARE(o->property("test1").toBool(), true);
3206 QCOMPARE(o->property("test2").toBool(), true);
3207 QCOMPARE(o->property("test3").toBool(), true);
3213 void tst_qdeclarativeecmascript::qtbug_10696()
3215 QDeclarativeComponent component(&engine, TEST_FILE("qtbug_10696.qml"));
3216 QObject *o = component.create();
3221 void tst_qdeclarativeecmascript::qtbug_11606()
3223 QDeclarativeComponent component(&engine, TEST_FILE("qtbug_11606.qml"));
3224 QObject *o = component.create();
3226 QCOMPARE(o->property("test").toBool(), true);
3230 void tst_qdeclarativeecmascript::qtbug_11600()
3232 QDeclarativeComponent component(&engine, TEST_FILE("qtbug_11600.qml"));
3233 QObject *o = component.create();
3235 QCOMPARE(o->property("test").toBool(), true);
3239 // Reading and writing non-scriptable properties should fail
3240 void tst_qdeclarativeecmascript::nonscriptable()
3242 QDeclarativeComponent component(&engine, TEST_FILE("nonscriptable.qml"));
3243 QObject *o = component.create();
3245 QCOMPARE(o->property("readOk").toBool(), true);
3246 QCOMPARE(o->property("writeOk").toBool(), true);
3250 // deleteLater() should not be callable from QML
3251 void tst_qdeclarativeecmascript::deleteLater()
3253 QDeclarativeComponent component(&engine, TEST_FILE("deleteLater.qml"));
3254 QObject *o = component.create();
3256 QCOMPARE(o->property("test").toBool(), true);
3260 void tst_qdeclarativeecmascript::in()
3262 QDeclarativeComponent component(&engine, TEST_FILE("in.qml"));
3263 QObject *o = component.create();
3265 QCOMPARE(o->property("test1").toBool(), true);
3266 QCOMPARE(o->property("test2").toBool(), true);
3270 void tst_qdeclarativeecmascript::sharedAttachedObject()
3272 QDeclarativeComponent component(&engine, TEST_FILE("sharedAttachedObject.qml"));
3273 QObject *o = component.create();
3275 QCOMPARE(o->property("test1").toBool(), true);
3276 QCOMPARE(o->property("test2").toBool(), true);
3281 void tst_qdeclarativeecmascript::objectName()
3283 QDeclarativeComponent component(&engine, TEST_FILE("objectName.qml"));
3284 QObject *o = component.create();
3287 QCOMPARE(o->property("test1").toString(), QString("hello"));
3288 QCOMPARE(o->property("test2").toString(), QString("ell"));
3290 o->setObjectName("world");
3292 QCOMPARE(o->property("test1").toString(), QString("world"));
3293 QCOMPARE(o->property("test2").toString(), QString("orl"));
3298 void tst_qdeclarativeecmascript::writeRemovesBinding()
3300 QDeclarativeComponent component(&engine, TEST_FILE("writeRemovesBinding.qml"));
3301 QObject *o = component.create();
3304 QCOMPARE(o->property("test").toBool(), true);
3309 // Test bindings assigned to alias properties actually assign to the alias' target
3310 void tst_qdeclarativeecmascript::aliasBindingsAssignCorrectly()
3312 QDeclarativeComponent component(&engine, TEST_FILE("aliasBindingsAssignCorrectly.qml"));
3313 QObject *o = component.create();
3316 QCOMPARE(o->property("test").toBool(), true);
3321 // Test bindings assigned to alias properties override a binding on the target (QTBUG-13719)
3322 void tst_qdeclarativeecmascript::aliasBindingsOverrideTarget()
3325 QDeclarativeComponent component(&engine, TEST_FILE("aliasBindingsOverrideTarget.qml"));
3326 QObject *o = component.create();
3329 QCOMPARE(o->property("test").toBool(), true);
3335 QDeclarativeComponent component(&engine, TEST_FILE("aliasBindingsOverrideTarget.2.qml"));
3336 QObject *o = component.create();
3339 QCOMPARE(o->property("test").toBool(), true);
3345 QDeclarativeComponent component(&engine, TEST_FILE("aliasBindingsOverrideTarget.3.qml"));
3346 QObject *o = component.create();
3349 QCOMPARE(o->property("test").toBool(), true);
3355 // Test that writes to alias properties override bindings on the alias target (QTBUG-13719)
3356 void tst_qdeclarativeecmascript::aliasWritesOverrideBindings()
3359 QDeclarativeComponent component(&engine, TEST_FILE("aliasWritesOverrideBindings.qml"));
3360 QObject *o = component.create();
3363 QCOMPARE(o->property("test").toBool(), true);
3369 QDeclarativeComponent component(&engine, TEST_FILE("aliasWritesOverrideBindings.2.qml"));
3370 QObject *o = component.create();
3373 QCOMPARE(o->property("test").toBool(), true);
3379 QDeclarativeComponent component(&engine, TEST_FILE("aliasWritesOverrideBindings.3.qml"));
3380 QObject *o = component.create();
3383 QCOMPARE(o->property("test").toBool(), true);
3389 void tst_qdeclarativeecmascript::revisionErrors()
3392 QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevisionErrors.qml"));
3393 QString url = component.url().toString();
3395 QString warning1 = url + ":8: ReferenceError: Can't find variable: prop2";
3396 QString warning2 = url + ":11: ReferenceError: Can't find variable: prop2";
3397 QString warning3 = url + ":13: ReferenceError: Can't find variable: method2";
3399 QTest::ignoreMessage(QtWarningMsg, warning1.toLatin1().constData());
3400 QTest::ignoreMessage(QtWarningMsg, warning2.toLatin1().constData());
3401 QTest::ignoreMessage(QtWarningMsg, warning3.toLatin1().constData());
3402 MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create());
3403 QVERIFY(object != 0);
3407 QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevisionErrors2.qml"));
3408 QString url = component.url().toString();
3410 // MyRevisionedSubclass 1.0 uses MyRevisionedClass revision 0
3411 // method2, prop2 from MyRevisionedClass not available
3412 // method4, prop4 from MyRevisionedSubclass not available
3413 QString warning1 = url + ":8: ReferenceError: Can't find variable: prop2";
3414 QString warning2 = url + ":14: ReferenceError: Can't find variable: prop2";
3415 QString warning3 = url + ":10: ReferenceError: Can't find variable: prop4";
3416 QString warning4 = url + ":16: ReferenceError: Can't find variable: prop4";
3417 QString warning5 = url + ":20: ReferenceError: Can't find variable: method2";
3419 QTest::ignoreMessage(QtWarningMsg, warning1.toLatin1().constData());
3420 QTest::ignoreMessage(QtWarningMsg, warning2.toLatin1().constData());
3421 QTest::ignoreMessage(QtWarningMsg, warning3.toLatin1().constData());
3422 QTest::ignoreMessage(QtWarningMsg, warning4.toLatin1().constData());
3423 QTest::ignoreMessage(QtWarningMsg, warning5.toLatin1().constData());
3424 MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create());
3425 QVERIFY(object != 0);
3429 QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevisionErrors3.qml"));
3430 QString url = component.url().toString();
3432 // MyRevisionedSubclass 1.1 uses MyRevisionedClass revision 1
3433 // All properties/methods available, except MyRevisionedBaseClassUnregistered rev 1
3434 QString warning1 = url + ":30: ReferenceError: Can't find variable: methodD";
3435 QString warning2 = url + ":10: ReferenceError: Can't find variable: propD";
3436 QString warning3 = url + ":20: ReferenceError: Can't find variable: propD";
3437 QTest::ignoreMessage(QtWarningMsg, warning1.toLatin1().constData());
3438 QTest::ignoreMessage(QtWarningMsg, warning2.toLatin1().constData());
3439 QTest::ignoreMessage(QtWarningMsg, warning3.toLatin1().constData());
3440 MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create());
3441 QVERIFY(object != 0);
3446 void tst_qdeclarativeecmascript::revision()
3449 QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevision.qml"));
3450 QString url = component.url().toString();
3452 MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create());
3453 QVERIFY(object != 0);
3457 QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevision2.qml"));
3458 QString url = component.url().toString();
3460 MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create());
3461 QVERIFY(object != 0);
3465 QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevision3.qml"));
3466 QString url = component.url().toString();
3468 MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create());
3469 QVERIFY(object != 0);
3472 // Test that non-root classes can resolve revisioned methods
3474 QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevision4.qml"));
3476 QObject *object = component.create();
3477 QVERIFY(object != 0);
3478 QCOMPARE(object->property("test").toReal(), 11.);
3483 // Test for QScriptDeclarativeClass::pushCleanContext()
3484 void tst_qdeclarativeecmascript::pushCleanContext()
3486 QScriptEngine engine;
3487 engine.globalObject().setProperty("a", 6);
3488 QCOMPARE(engine.evaluate("a").toInt32(), 6);
3490 // First confirm pushContext() behaves as we expect
3491 QScriptValue object = engine.newObject();
3492 object.setProperty("a", 15);
3493 QScriptContext *context1 = engine.pushContext();
3494 context1->pushScope(object);
3495 QCOMPARE(engine.evaluate("a").toInt32(), 15);
3497 QScriptContext *context2 = engine.pushContext();
3499 QCOMPARE(engine.evaluate("a").toInt32(), 15);
3500 QScriptValue func1 = engine.evaluate("(function() { return a; })");
3502 // Now check that pushCleanContext() works
3503 QScriptDeclarativeClass::pushCleanContext(&engine);
3504 QCOMPARE(engine.evaluate("a").toInt32(), 6);
3505 QScriptValue func2 = engine.evaluate("(function() { return a; })");
3507 engine.popContext();
3508 QCOMPARE(engine.evaluate("a").toInt32(), 15);
3510 engine.popContext();
3511 QCOMPARE(engine.evaluate("a").toInt32(), 15);
3513 engine.popContext();
3514 QCOMPARE(engine.evaluate("a").toInt32(), 6);
3516 // Check that function objects created in these contexts work
3517 QCOMPARE(func1.call().toInt32(), 15);
3518 QCOMPARE(func2.call().toInt32(), 6);
3521 void tst_qdeclarativeecmascript::realToInt()
3523 QDeclarativeComponent component(&engine, TEST_FILE("realToInt.qml"));
3524 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
3525 QVERIFY(object != 0);
3527 QMetaObject::invokeMethod(object, "test1");
3528 QCOMPARE(object->value(), int(4));
3529 QMetaObject::invokeMethod(object, "test2");
3530 QCOMPARE(object->value(), int(8));
3533 QTEST_MAIN(tst_qdeclarativeecmascript)
3535 #include "tst_qdeclarativeecmascript.moc"