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();
150 void dynamicCreationCrash();
152 void nullObjectBinding();
153 void deletedEngine();
154 void libraryScriptAssert();
155 void variantsAssignedUndefined();
157 void qtcreatorbug_1289();
158 void noSpuriousWarningsAtShutdown();
159 void canAssignNullToQObject();
160 void functionAssignment_fromBinding();
161 void functionAssignment_fromJS();
162 void functionAssignment_fromJS_data();
163 void functionAssignmentfromJS_invalid();
169 void nonscriptable();
172 void sharedAttachedObject();
174 void writeRemovesBinding();
175 void aliasBindingsAssignCorrectly();
176 void aliasBindingsOverrideTarget();
177 void aliasWritesOverrideBindings();
178 void pushCleanContext();
182 void callQtInvokables();
183 void invokableObjectArg();
184 void invokableObjectRet();
186 void revisionErrors();
189 QDeclarativeEngine engine;
192 void tst_qdeclarativeecmascript::initTestCase() { registerTypes(); }
194 void tst_qdeclarativeecmascript::assignBasicTypes()
197 QDeclarativeComponent component(&engine, TEST_FILE("assignBasicTypes.qml"));
198 MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
199 QVERIFY(object != 0);
200 QCOMPARE(object->flagProperty(), MyTypeObject::FlagVal1 | MyTypeObject::FlagVal3);
201 QCOMPARE(object->enumProperty(), MyTypeObject::EnumVal2);
202 QCOMPARE(object->stringProperty(), QString("Hello World!"));
203 QCOMPARE(object->uintProperty(), uint(10));
204 QCOMPARE(object->intProperty(), -19);
205 QCOMPARE((float)object->realProperty(), float(23.2));
206 QCOMPARE((float)object->doubleProperty(), float(-19.75));
207 QCOMPARE((float)object->floatProperty(), float(8.5));
208 QCOMPARE(object->colorProperty(), QColor("red"));
209 QCOMPARE(object->dateProperty(), QDate(1982, 11, 25));
210 QCOMPARE(object->timeProperty(), QTime(11, 11, 32));
211 QCOMPARE(object->dateTimeProperty(), QDateTime(QDate(2009, 5, 12), QTime(13, 22, 1)));
212 QCOMPARE(object->pointProperty(), QPoint(99,13));
213 QCOMPARE(object->pointFProperty(), QPointF(-10.1, 12.3));
214 QCOMPARE(object->sizeProperty(), QSize(99, 13));
215 QCOMPARE(object->sizeFProperty(), QSizeF(0.1, 0.2));
216 QCOMPARE(object->rectProperty(), QRect(9, 7, 100, 200));
217 QCOMPARE(object->rectFProperty(), QRectF(1000.1, -10.9, 400, 90.99));
218 QCOMPARE(object->boolProperty(), true);
219 QCOMPARE(object->variantProperty(), QVariant("Hello World!"));
220 QCOMPARE(object->vectorProperty(), QVector3D(10, 1, 2.2));
221 QCOMPARE(object->urlProperty(), component.url().resolved(QUrl("main.qml")));
225 QDeclarativeComponent component(&engine, TEST_FILE("assignBasicTypes.2.qml"));
226 MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
227 QVERIFY(object != 0);
228 QCOMPARE(object->flagProperty(), MyTypeObject::FlagVal1 | MyTypeObject::FlagVal3);
229 QCOMPARE(object->enumProperty(), MyTypeObject::EnumVal2);
230 QCOMPARE(object->stringProperty(), QString("Hello World!"));
231 QCOMPARE(object->uintProperty(), uint(10));
232 QCOMPARE(object->intProperty(), -19);
233 QCOMPARE((float)object->realProperty(), float(23.2));
234 QCOMPARE((float)object->doubleProperty(), float(-19.75));
235 QCOMPARE((float)object->floatProperty(), float(8.5));
236 QCOMPARE(object->colorProperty(), QColor("red"));
237 QCOMPARE(object->dateProperty(), QDate(1982, 11, 25));
238 QCOMPARE(object->timeProperty(), QTime(11, 11, 32));
239 QCOMPARE(object->dateTimeProperty(), QDateTime(QDate(2009, 5, 12), QTime(13, 22, 1)));
240 QCOMPARE(object->pointProperty(), QPoint(99,13));
241 QCOMPARE(object->pointFProperty(), QPointF(-10.1, 12.3));
242 QCOMPARE(object->sizeProperty(), QSize(99, 13));
243 QCOMPARE(object->sizeFProperty(), QSizeF(0.1, 0.2));
244 QCOMPARE(object->rectProperty(), QRect(9, 7, 100, 200));
245 QCOMPARE(object->rectFProperty(), QRectF(1000.1, -10.9, 400, 90.99));
246 QCOMPARE(object->boolProperty(), true);
247 QCOMPARE(object->variantProperty(), QVariant("Hello World!"));
248 QCOMPARE(object->vectorProperty(), QVector3D(10, 1, 2.2));
249 QCOMPARE(object->urlProperty(), component.url().resolved(QUrl("main.qml")));
254 void tst_qdeclarativeecmascript::idShortcutInvalidates()
257 QDeclarativeComponent component(&engine, TEST_FILE("idShortcutInvalidates.qml"));
258 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
259 QVERIFY(object != 0);
260 QVERIFY(object->objectProperty() != 0);
261 delete object->objectProperty();
262 QVERIFY(object->objectProperty() == 0);
266 QDeclarativeComponent component(&engine, TEST_FILE("idShortcutInvalidates.1.qml"));
267 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
268 QVERIFY(object != 0);
269 QVERIFY(object->objectProperty() != 0);
270 delete object->objectProperty();
271 QVERIFY(object->objectProperty() == 0);
275 void tst_qdeclarativeecmascript::boolPropertiesEvaluateAsBool()
278 QDeclarativeComponent component(&engine, TEST_FILE("boolPropertiesEvaluateAsBool.1.qml"));
279 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
280 QVERIFY(object != 0);
281 QCOMPARE(object->stringProperty(), QLatin1String("pass"));
284 QDeclarativeComponent component(&engine, TEST_FILE("boolPropertiesEvaluateAsBool.2.qml"));
285 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
286 QVERIFY(object != 0);
287 QCOMPARE(object->stringProperty(), QLatin1String("pass"));
291 void tst_qdeclarativeecmascript::signalAssignment()
294 QDeclarativeComponent component(&engine, TEST_FILE("signalAssignment.1.qml"));
295 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
296 QVERIFY(object != 0);
297 QCOMPARE(object->string(), QString());
298 emit object->basicSignal();
299 QCOMPARE(object->string(), QString("pass"));
303 QDeclarativeComponent component(&engine, TEST_FILE("signalAssignment.2.qml"));
304 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
305 QVERIFY(object != 0);
306 QCOMPARE(object->string(), QString());
307 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
308 QCOMPARE(object->string(), QString("pass 19 Hello world! 10.25 3 2"));
312 void tst_qdeclarativeecmascript::methods()
315 QDeclarativeComponent component(&engine, TEST_FILE("methods.1.qml"));
316 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
317 QVERIFY(object != 0);
318 QCOMPARE(object->methodCalled(), false);
319 QCOMPARE(object->methodIntCalled(), false);
320 emit object->basicSignal();
321 QCOMPARE(object->methodCalled(), true);
322 QCOMPARE(object->methodIntCalled(), false);
326 QDeclarativeComponent component(&engine, TEST_FILE("methods.2.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(), false);
333 QCOMPARE(object->methodIntCalled(), true);
337 QDeclarativeComponent component(&engine, TEST_FILE("methods.3.qml"));
338 QObject *object = component.create();
339 QVERIFY(object != 0);
340 QCOMPARE(object->property("test").toInt(), 19);
344 QDeclarativeComponent component(&engine, TEST_FILE("methods.4.qml"));
345 QObject *object = component.create();
346 QVERIFY(object != 0);
347 QCOMPARE(object->property("test").toInt(), 19);
348 QCOMPARE(object->property("test2").toInt(), 17);
349 QCOMPARE(object->property("test3").toInt(), 16);
353 QDeclarativeComponent component(&engine, TEST_FILE("methods.5.qml"));
354 QObject *object = component.create();
355 QVERIFY(object != 0);
356 QCOMPARE(object->property("test").toInt(), 9);
360 void tst_qdeclarativeecmascript::bindingLoop()
362 QDeclarativeComponent component(&engine, TEST_FILE("bindingLoop.qml"));
363 QString warning = component.url().toString() + ":9:9: QML MyQmlObject: Binding loop detected for property \"stringProperty\"";
364 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
365 QObject *object = component.create();
366 QVERIFY(object != 0);
369 void tst_qdeclarativeecmascript::basicExpressions_data()
371 QTest::addColumn<QString>("expression");
372 QTest::addColumn<QVariant>("result");
373 QTest::addColumn<bool>("nest");
375 QTest::newRow("Syntax error (self test)") << "{console.log({'a':1'}.a)}" << QVariant() << false;
376 QTest::newRow("Context property") << "a" << QVariant(1944) << false;
377 QTest::newRow("Context property") << "a" << QVariant(1944) << true;
378 QTest::newRow("Context property expression") << "a * 2" << QVariant(3888) << false;
379 QTest::newRow("Context property expression") << "a * 2" << QVariant(3888) << true;
380 QTest::newRow("Overridden context property") << "b" << QVariant("Milk") << false;
381 QTest::newRow("Overridden context property") << "b" << QVariant("Cow") << true;
382 QTest::newRow("Object property") << "object.stringProperty" << QVariant("Object1") << false;
383 QTest::newRow("Object property") << "object.stringProperty" << QVariant("Object1") << true;
384 QTest::newRow("Overridden object property") << "objectOverride.stringProperty" << QVariant("Object2") << false;
385 QTest::newRow("Overridden object property") << "objectOverride.stringProperty" << QVariant("Object3") << true;
386 QTest::newRow("Default object property") << "horseLegs" << QVariant(4) << false;
387 QTest::newRow("Default object property") << "antLegs" << QVariant(6) << false;
388 QTest::newRow("Default object property") << "emuLegs" << QVariant(2) << false;
389 QTest::newRow("Nested default object property") << "horseLegs" << QVariant(4) << true;
390 QTest::newRow("Nested default object property") << "antLegs" << QVariant(7) << true;
391 QTest::newRow("Nested default object property") << "emuLegs" << QVariant(2) << true;
392 QTest::newRow("Nested default object property") << "humanLegs" << QVariant(2) << true;
393 QTest::newRow("Context property override default object property") << "millipedeLegs" << QVariant(100) << true;
396 void tst_qdeclarativeecmascript::basicExpressions()
398 QFETCH(QString, expression);
399 QFETCH(QVariant, result);
405 MyDefaultObject1 default1;
406 MyDefaultObject3 default3;
407 object1.setStringProperty("Object1");
408 object2.setStringProperty("Object2");
409 object3.setStringProperty("Object3");
411 QDeclarativeContext context(engine.rootContext());
412 QDeclarativeContext nestedContext(&context);
414 context.setContextObject(&default1);
415 context.setContextProperty("a", QVariant(1944));
416 context.setContextProperty("b", QVariant("Milk"));
417 context.setContextProperty("object", &object1);
418 context.setContextProperty("objectOverride", &object2);
419 nestedContext.setContextObject(&default3);
420 nestedContext.setContextProperty("b", QVariant("Cow"));
421 nestedContext.setContextProperty("objectOverride", &object3);
422 nestedContext.setContextProperty("millipedeLegs", QVariant(100));
424 MyExpression expr(nest?&nestedContext:&context, expression);
425 QCOMPARE(expr.evaluate(), result);
428 void tst_qdeclarativeecmascript::arrayExpressions()
434 QDeclarativeContext context(engine.rootContext());
435 context.setContextProperty("a", &obj1);
436 context.setContextProperty("b", &obj2);
437 context.setContextProperty("c", &obj3);
439 MyExpression expr(&context, "[a, b, c, 10]");
440 QVariant result = expr.evaluate();
441 QCOMPARE(result.userType(), qMetaTypeId<QList<QObject *> >());
442 QList<QObject *> list = qvariant_cast<QList<QObject *> >(result);
443 QCOMPARE(list.count(), 4);
444 QCOMPARE(list.at(0), &obj1);
445 QCOMPARE(list.at(1), &obj2);
446 QCOMPARE(list.at(2), &obj3);
447 QCOMPARE(list.at(3), (QObject *)0);
450 // Tests that modifying a context property will reevaluate expressions
451 void tst_qdeclarativeecmascript::contextPropertiesTriggerReeval()
453 QDeclarativeContext context(engine.rootContext());
456 MyQmlObject *object3 = new MyQmlObject;
458 object1.setStringProperty("Hello");
459 object2.setStringProperty("World");
461 context.setContextProperty("testProp", QVariant(1));
462 context.setContextProperty("testObj", &object1);
463 context.setContextProperty("testObj2", object3);
466 MyExpression expr(&context, "testProp + 1");
467 QCOMPARE(expr.changed, false);
468 QCOMPARE(expr.evaluate(), QVariant(2));
470 context.setContextProperty("testProp", QVariant(2));
471 QCOMPARE(expr.changed, true);
472 QCOMPARE(expr.evaluate(), QVariant(3));
476 MyExpression expr(&context, "testProp + testProp + testProp");
477 QCOMPARE(expr.changed, false);
478 QCOMPARE(expr.evaluate(), QVariant(6));
480 context.setContextProperty("testProp", QVariant(4));
481 QCOMPARE(expr.changed, true);
482 QCOMPARE(expr.evaluate(), QVariant(12));
486 MyExpression expr(&context, "testObj.stringProperty");
487 QCOMPARE(expr.changed, false);
488 QCOMPARE(expr.evaluate(), QVariant("Hello"));
490 context.setContextProperty("testObj", &object2);
491 QCOMPARE(expr.changed, true);
492 QCOMPARE(expr.evaluate(), QVariant("World"));
496 MyExpression expr(&context, "testObj.stringProperty /**/");
497 QCOMPARE(expr.changed, false);
498 QCOMPARE(expr.evaluate(), QVariant("World"));
500 context.setContextProperty("testObj", &object1);
501 QCOMPARE(expr.changed, true);
502 QCOMPARE(expr.evaluate(), QVariant("Hello"));
506 MyExpression expr(&context, "testObj2");
507 QCOMPARE(expr.changed, false);
508 QCOMPARE(expr.evaluate(), QVariant::fromValue((QObject *)object3));
513 void tst_qdeclarativeecmascript::objectPropertiesTriggerReeval()
515 QDeclarativeContext context(engine.rootContext());
519 context.setContextProperty("testObj", &object1);
521 object1.setStringProperty(QLatin1String("Hello"));
522 object2.setStringProperty(QLatin1String("Dog"));
523 object3.setStringProperty(QLatin1String("Cat"));
526 MyExpression expr(&context, "testObj.stringProperty");
527 QCOMPARE(expr.changed, false);
528 QCOMPARE(expr.evaluate(), QVariant("Hello"));
530 object1.setStringProperty(QLatin1String("World"));
531 QCOMPARE(expr.changed, true);
532 QCOMPARE(expr.evaluate(), QVariant("World"));
536 MyExpression expr(&context, "testObj.objectProperty.stringProperty");
537 QCOMPARE(expr.changed, false);
538 QCOMPARE(expr.evaluate(), QVariant());
540 object1.setObjectProperty(&object2);
541 QCOMPARE(expr.changed, true);
542 expr.changed = false;
543 QCOMPARE(expr.evaluate(), QVariant("Dog"));
545 object1.setObjectProperty(&object3);
546 QCOMPARE(expr.changed, true);
547 expr.changed = false;
548 QCOMPARE(expr.evaluate(), QVariant("Cat"));
550 object1.setObjectProperty(0);
551 QCOMPARE(expr.changed, true);
552 expr.changed = false;
553 QCOMPARE(expr.evaluate(), QVariant());
555 object1.setObjectProperty(&object3);
556 QCOMPARE(expr.changed, true);
557 expr.changed = false;
558 QCOMPARE(expr.evaluate(), QVariant("Cat"));
560 object3.setStringProperty("Donkey");
561 QCOMPARE(expr.changed, true);
562 expr.changed = false;
563 QCOMPARE(expr.evaluate(), QVariant("Donkey"));
567 void tst_qdeclarativeecmascript::deferredProperties()
569 QDeclarativeComponent component(&engine, TEST_FILE("deferredProperties.qml"));
570 MyDeferredObject *object =
571 qobject_cast<MyDeferredObject *>(component.create());
572 QVERIFY(object != 0);
573 QCOMPARE(object->value(), 0);
574 QVERIFY(object->objectProperty() == 0);
575 QVERIFY(object->objectProperty2() != 0);
576 qmlExecuteDeferred(object);
577 QCOMPARE(object->value(), 10);
578 QVERIFY(object->objectProperty() != 0);
579 MyQmlObject *qmlObject =
580 qobject_cast<MyQmlObject *>(object->objectProperty());
581 QVERIFY(qmlObject != 0);
582 QCOMPARE(qmlObject->value(), 10);
583 object->setValue(19);
584 QCOMPARE(qmlObject->value(), 19);
587 // Check errors on deferred properties are correctly emitted
588 void tst_qdeclarativeecmascript::deferredPropertiesErrors()
590 QDeclarativeComponent component(&engine, TEST_FILE("deferredPropertiesErrors.qml"));
591 MyDeferredObject *object =
592 qobject_cast<MyDeferredObject *>(component.create());
593 QVERIFY(object != 0);
594 QCOMPARE(object->value(), 0);
595 QVERIFY(object->objectProperty() == 0);
596 QVERIFY(object->objectProperty2() == 0);
598 QString warning = component.url().toString() + ":6: Unable to assign [undefined] to QObject* objectProperty";
599 QTest::ignoreMessage(QtWarningMsg, qPrintable(warning));
601 qmlExecuteDeferred(object);
606 void tst_qdeclarativeecmascript::extensionObjects()
608 QDeclarativeComponent component(&engine, TEST_FILE("extensionObjects.qml"));
609 MyExtendedObject *object =
610 qobject_cast<MyExtendedObject *>(component.create());
611 QVERIFY(object != 0);
612 QCOMPARE(object->baseProperty(), 13);
613 QCOMPARE(object->coreProperty(), 9);
614 object->setProperty("extendedProperty", QVariant(11));
615 object->setProperty("baseExtendedProperty", QVariant(92));
616 QCOMPARE(object->coreProperty(), 11);
617 QCOMPARE(object->baseProperty(), 92);
619 MyExtendedObject *nested = qobject_cast<MyExtendedObject*>(qvariant_cast<QObject *>(object->property("nested")));
621 QCOMPARE(nested->baseProperty(), 13);
622 QCOMPARE(nested->coreProperty(), 9);
623 nested->setProperty("extendedProperty", QVariant(11));
624 nested->setProperty("baseExtendedProperty", QVariant(92));
625 QCOMPARE(nested->coreProperty(), 11);
626 QCOMPARE(nested->baseProperty(), 92);
630 void tst_qdeclarativeecmascript::overrideExtensionProperties()
632 QDeclarativeComponent component(&engine, TEST_FILE("extensionObjectsPropertyOverride.qml"));
633 OverrideDefaultPropertyObject *object =
634 qobject_cast<OverrideDefaultPropertyObject *>(component.create());
635 QVERIFY(object != 0);
636 QVERIFY(object->secondProperty() != 0);
637 QVERIFY(object->firstProperty() == 0);
640 void tst_qdeclarativeecmascript::attachedProperties()
643 QDeclarativeComponent component(&engine, TEST_FILE("attachedProperty.qml"));
644 QObject *object = component.create();
645 QVERIFY(object != 0);
646 QCOMPARE(object->property("a").toInt(), 19);
647 QCOMPARE(object->property("b").toInt(), 19);
648 QCOMPARE(object->property("c").toInt(), 19);
649 QCOMPARE(object->property("d").toInt(), 19);
653 QDeclarativeComponent component(&engine, TEST_FILE("writeAttachedProperty.qml"));
654 QObject *object = component.create();
655 QVERIFY(object != 0);
657 QMetaObject::invokeMethod(object, "writeValue2");
659 MyQmlAttachedObject *attached =
660 qobject_cast<MyQmlAttachedObject *>(qmlAttachedPropertiesObject<MyQmlObject>(object));
661 QVERIFY(attached != 0);
663 QCOMPARE(attached->value2(), 9);
667 void tst_qdeclarativeecmascript::enums()
671 QDeclarativeComponent component(&engine, TEST_FILE("enums.1.qml"));
672 QObject *object = component.create();
673 QVERIFY(object != 0);
675 QCOMPARE(object->property("a").toInt(), 0);
676 QCOMPARE(object->property("b").toInt(), 1);
677 QCOMPARE(object->property("c").toInt(), 2);
678 QCOMPARE(object->property("d").toInt(), 3);
679 QCOMPARE(object->property("e").toInt(), 0);
680 QCOMPARE(object->property("f").toInt(), 1);
681 QCOMPARE(object->property("g").toInt(), 2);
682 QCOMPARE(object->property("h").toInt(), 3);
683 QCOMPARE(object->property("i").toInt(), 19);
684 QCOMPARE(object->property("j").toInt(), 19);
686 // Non-existent enums
688 QDeclarativeComponent component(&engine, TEST_FILE("enums.2.qml"));
690 QString warning1 = component.url().toString() + ":5: Unable to assign [undefined] to int a";
691 QString warning2 = component.url().toString() + ":6: Unable to assign [undefined] to int b";
692 QTest::ignoreMessage(QtWarningMsg, qPrintable(warning1));
693 QTest::ignoreMessage(QtWarningMsg, qPrintable(warning2));
695 QObject *object = component.create();
696 QVERIFY(object != 0);
697 QCOMPARE(object->property("a").toInt(), 0);
698 QCOMPARE(object->property("b").toInt(), 0);
702 void tst_qdeclarativeecmascript::valueTypeFunctions()
704 QDeclarativeComponent component(&engine, TEST_FILE("valueTypeFunctions.qml"));
705 MyTypeObject *obj = qobject_cast<MyTypeObject*>(component.create());
707 QCOMPARE(obj->rectProperty(), QRect(0,0,100,100));
708 QCOMPARE(obj->rectFProperty(), QRectF(0,0.5,100,99.5));
712 Tests that writing a constant to a property with a binding on it disables the
715 void tst_qdeclarativeecmascript::constantsOverrideBindings()
719 QDeclarativeComponent component(&engine, TEST_FILE("constantsOverrideBindings.1.qml"));
720 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
721 QVERIFY(object != 0);
723 QCOMPARE(object->property("c2").toInt(), 0);
724 object->setProperty("c1", QVariant(9));
725 QCOMPARE(object->property("c2").toInt(), 9);
727 emit object->basicSignal();
729 QCOMPARE(object->property("c2").toInt(), 13);
730 object->setProperty("c1", QVariant(8));
731 QCOMPARE(object->property("c2").toInt(), 13);
734 // During construction
736 QDeclarativeComponent component(&engine, TEST_FILE("constantsOverrideBindings.2.qml"));
737 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
738 QVERIFY(object != 0);
740 QCOMPARE(object->property("c1").toInt(), 0);
741 QCOMPARE(object->property("c2").toInt(), 10);
742 object->setProperty("c1", QVariant(9));
743 QCOMPARE(object->property("c1").toInt(), 9);
744 QCOMPARE(object->property("c2").toInt(), 10);
750 QDeclarativeComponent component(&engine, TEST_FILE("constantsOverrideBindings.3.qml"));
751 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
752 QVERIFY(object != 0);
754 QCOMPARE(object->property("c2").toInt(), 0);
755 object->setProperty("c1", QVariant(9));
756 QCOMPARE(object->property("c2").toInt(), 9);
758 object->setProperty("c2", QVariant(13));
759 QCOMPARE(object->property("c2").toInt(), 13);
760 object->setProperty("c1", QVariant(7));
761 QCOMPARE(object->property("c1").toInt(), 7);
762 QCOMPARE(object->property("c2").toInt(), 13);
768 QDeclarativeComponent component(&engine, TEST_FILE("constantsOverrideBindings.4.qml"));
769 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
770 QVERIFY(object != 0);
772 QCOMPARE(object->property("c1").toInt(), 0);
773 QCOMPARE(object->property("c3").toInt(), 10);
774 object->setProperty("c1", QVariant(9));
775 QCOMPARE(object->property("c1").toInt(), 9);
776 QCOMPARE(object->property("c3").toInt(), 10);
781 Tests that assigning a binding to a property that already has a binding causes
782 the original binding to be disabled.
784 void tst_qdeclarativeecmascript::outerBindingOverridesInnerBinding()
786 QDeclarativeComponent component(&engine,
787 TEST_FILE("outerBindingOverridesInnerBinding.qml"));
788 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
789 QVERIFY(object != 0);
791 QCOMPARE(object->property("c1").toInt(), 0);
792 QCOMPARE(object->property("c2").toInt(), 0);
793 QCOMPARE(object->property("c3").toInt(), 0);
795 object->setProperty("c1", QVariant(9));
796 QCOMPARE(object->property("c1").toInt(), 9);
797 QCOMPARE(object->property("c2").toInt(), 0);
798 QCOMPARE(object->property("c3").toInt(), 0);
800 object->setProperty("c3", QVariant(8));
801 QCOMPARE(object->property("c1").toInt(), 9);
802 QCOMPARE(object->property("c2").toInt(), 8);
803 QCOMPARE(object->property("c3").toInt(), 8);
807 Access a non-existent attached object.
809 Tests for a regression where this used to crash.
811 void tst_qdeclarativeecmascript::nonExistentAttachedObject()
813 QDeclarativeComponent component(&engine, TEST_FILE("nonExistentAttachedObject.qml"));
815 QString warning = component.url().toString() + ":4: Unable to assign [undefined] to QString stringProperty";
816 QTest::ignoreMessage(QtWarningMsg, qPrintable(warning));
818 QObject *object = component.create();
819 QVERIFY(object != 0);
822 void tst_qdeclarativeecmascript::scope()
825 QDeclarativeComponent component(&engine, TEST_FILE("scope.qml"));
826 QObject *object = component.create();
827 QVERIFY(object != 0);
829 QCOMPARE(object->property("test1").toInt(), 1);
830 QCOMPARE(object->property("test2").toInt(), 2);
831 QCOMPARE(object->property("test3").toString(), QString("1Test"));
832 QCOMPARE(object->property("test4").toString(), QString("2Test"));
833 QCOMPARE(object->property("test5").toInt(), 1);
834 QCOMPARE(object->property("test6").toInt(), 1);
835 QCOMPARE(object->property("test7").toInt(), 2);
836 QCOMPARE(object->property("test8").toInt(), 2);
837 QCOMPARE(object->property("test9").toInt(), 1);
838 QCOMPARE(object->property("test10").toInt(), 3);
842 QDeclarativeComponent component(&engine, TEST_FILE("scope.2.qml"));
843 QObject *object = component.create();
844 QVERIFY(object != 0);
846 QCOMPARE(object->property("test1").toInt(), 19);
847 QCOMPARE(object->property("test2").toInt(), 19);
848 QCOMPARE(object->property("test3").toInt(), 14);
849 QCOMPARE(object->property("test4").toInt(), 14);
850 QCOMPARE(object->property("test5").toInt(), 24);
851 QCOMPARE(object->property("test6").toInt(), 24);
855 QDeclarativeComponent component(&engine, TEST_FILE("scope.3.qml"));
856 QObject *object = component.create();
857 QVERIFY(object != 0);
859 QCOMPARE(object->property("test1").toBool(), true);
860 QCOMPARE(object->property("test2").toBool(), true);
861 QCOMPARE(object->property("test3").toBool(), true);
864 // Signal argument scope
866 QDeclarativeComponent component(&engine, TEST_FILE("scope.4.qml"));
867 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
868 QVERIFY(object != 0);
870 QCOMPARE(object->property("test").toInt(), 0);
871 QCOMPARE(object->property("test2").toString(), QString());
873 emit object->argumentSignal(13, "Argument Scope", 9, MyQmlObject::EnumValue4, Qt::RightButton);
875 QCOMPARE(object->property("test").toInt(), 13);
876 QCOMPARE(object->property("test2").toString(), QString("Argument Scope"));
883 Tests that "any" type passes through a synthesized signal parameter. This
884 is essentially a test of QDeclarativeMetaType::copy()
886 void tst_qdeclarativeecmascript::signalParameterTypes()
888 QDeclarativeComponent component(&engine, TEST_FILE("signalParameterTypes.qml"));
889 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
890 QVERIFY(object != 0);
892 emit object->basicSignal();
894 QCOMPARE(object->property("intProperty").toInt(), 10);
895 QCOMPARE(object->property("realProperty").toReal(), 19.2);
896 QVERIFY(object->property("colorProperty").value<QColor>() == QColor(255, 255, 0, 255));
897 QVERIFY(object->property("variantProperty") == QVariant::fromValue(QColor(255, 0, 255, 255)));
898 QVERIFY(object->property("enumProperty") == MyQmlObject::EnumValue3);
899 QVERIFY(object->property("qtEnumProperty") == Qt::LeftButton);
903 Test that two JS objects for the same QObject compare as equal.
905 void tst_qdeclarativeecmascript::objectsCompareAsEqual()
907 QDeclarativeComponent component(&engine, TEST_FILE("objectsCompareAsEqual.qml"));
908 QObject *object = component.create();
909 QVERIFY(object != 0);
911 QCOMPARE(object->property("test1").toBool(), true);
912 QCOMPARE(object->property("test2").toBool(), true);
913 QCOMPARE(object->property("test3").toBool(), true);
914 QCOMPARE(object->property("test4").toBool(), true);
915 QCOMPARE(object->property("test5").toBool(), true);
919 Confirm bindings and alias properties can coexist.
921 Tests for a regression where the binding would not reevaluate.
923 void tst_qdeclarativeecmascript::aliasPropertyAndBinding()
925 QDeclarativeComponent component(&engine, TEST_FILE("aliasPropertyAndBinding.qml"));
926 QObject *object = component.create();
927 QVERIFY(object != 0);
929 QCOMPARE(object->property("c2").toInt(), 3);
930 QCOMPARE(object->property("c3").toInt(), 3);
932 object->setProperty("c2", QVariant(19));
934 QCOMPARE(object->property("c2").toInt(), 19);
935 QCOMPARE(object->property("c3").toInt(), 19);
938 void tst_qdeclarativeecmascript::dynamicCreation_data()
940 QTest::addColumn<QString>("method");
941 QTest::addColumn<QString>("createdName");
943 QTest::newRow("One") << "createOne" << "objectOne";
944 QTest::newRow("Two") << "createTwo" << "objectTwo";
945 QTest::newRow("Three") << "createThree" << "objectThree";
949 Test using createQmlObject to dynamically generate an item
950 Also using createComponent is tested.
952 void tst_qdeclarativeecmascript::dynamicCreation()
954 QFETCH(QString, method);
955 QFETCH(QString, createdName);
957 QDeclarativeComponent component(&engine, TEST_FILE("dynamicCreation.qml"));
958 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
959 QVERIFY(object != 0);
961 QMetaObject::invokeMethod(object, method.toUtf8());
962 QObject *created = object->objectProperty();
964 QCOMPARE(created->objectName(), createdName);
968 Tests the destroy function
970 void tst_qdeclarativeecmascript::dynamicDestruction()
972 QDeclarativeComponent component(&engine, TEST_FILE("dynamicDeletion.qml"));
973 QDeclarativeGuard<MyQmlObject> object = qobject_cast<MyQmlObject*>(component.create());
974 QVERIFY(object != 0);
975 QDeclarativeGuard<QObject> createdQmlObject = 0;
977 QMetaObject::invokeMethod(object, "create");
978 createdQmlObject = object->objectProperty();
979 QVERIFY(createdQmlObject);
980 QCOMPARE(createdQmlObject->objectName(), QString("emptyObject"));
982 QMetaObject::invokeMethod(object, "killOther");
983 QVERIFY(createdQmlObject);
984 QCoreApplication::instance()->processEvents(QEventLoop::DeferredDeletion);
985 QVERIFY(createdQmlObject);
986 for (int ii = 0; createdQmlObject && ii < 50; ++ii) { // After 5 seconds we should give up
987 if (createdQmlObject) {
989 QCoreApplication::instance()->processEvents(QEventLoop::DeferredDeletion);
992 QVERIFY(!createdQmlObject);
994 QDeclarativeEngine::setObjectOwnership(object, QDeclarativeEngine::JavaScriptOwnership);
995 QMetaObject::invokeMethod(object, "killMe");
998 QCoreApplication::instance()->processEvents(QEventLoop::DeferredDeletion);
1003 tests that id.toString() works
1005 void tst_qdeclarativeecmascript::objectToString()
1007 QDeclarativeComponent component(&engine, TEST_FILE("declarativeToString.qml"));
1008 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1009 QVERIFY(object != 0);
1010 QMetaObject::invokeMethod(object, "testToString");
1011 QVERIFY(object->stringProperty().startsWith("MyQmlObject_QML_"));
1012 QVERIFY(object->stringProperty().endsWith(", \"objName\")"));
1016 Tests bindings that indirectly cause their own deletion work.
1018 This test is best run under valgrind to ensure no invalid memory access occur.
1020 void tst_qdeclarativeecmascript::selfDeletingBinding()
1023 QDeclarativeComponent component(&engine, TEST_FILE("selfDeletingBinding.qml"));
1024 QObject *object = component.create();
1025 QVERIFY(object != 0);
1026 object->setProperty("triggerDelete", true);
1030 QDeclarativeComponent component(&engine, TEST_FILE("selfDeletingBinding.2.qml"));
1031 QObject *object = component.create();
1032 QVERIFY(object != 0);
1033 object->setProperty("triggerDelete", true);
1038 Test that extended object properties can be accessed.
1040 This test a regression where this used to crash. The issue was specificially
1041 for extended objects that did not include a synthesized meta object (so non-root
1042 and no synthesiszed properties).
1044 void tst_qdeclarativeecmascript::extendedObjectPropertyLookup()
1046 QDeclarativeComponent component(&engine, TEST_FILE("extendedObjectPropertyLookup.qml"));
1047 QObject *object = component.create();
1048 QVERIFY(object != 0);
1052 Test file/lineNumbers for binding/Script errors.
1054 void tst_qdeclarativeecmascript::scriptErrors()
1056 QDeclarativeComponent component(&engine, TEST_FILE("scriptErrors.qml"));
1057 QString url = component.url().toString();
1059 QString warning1 = url.left(url.length() - 3) + "js:2: Error: Invalid write to global property \"a\"";
1060 QString warning2 = url + ":5: ReferenceError: Can't find variable: a";
1061 QString warning3 = url.left(url.length() - 3) + "js:4: Error: Invalid write to global property \"a\"";
1062 QString warning4 = url + ":10: ReferenceError: Can't find variable: a";
1063 QString warning5 = url + ":8: ReferenceError: Can't find variable: a";
1064 QString warning6 = url + ":7: Unable to assign [undefined] to int x";
1065 QString warning7 = url + ":12: Error: Cannot assign to read-only property \"trueProperty\"";
1066 QString warning8 = url + ":13: Error: Cannot assign to non-existent property \"fakeProperty\"";
1068 QTest::ignoreMessage(QtWarningMsg, warning1.toLatin1().constData());
1069 QTest::ignoreMessage(QtWarningMsg, warning2.toLatin1().constData());
1070 QTest::ignoreMessage(QtWarningMsg, warning3.toLatin1().constData());
1071 QTest::ignoreMessage(QtWarningMsg, warning5.toLatin1().constData());
1072 QTest::ignoreMessage(QtWarningMsg, warning6.toLatin1().constData());
1073 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
1074 QVERIFY(object != 0);
1076 QTest::ignoreMessage(QtWarningMsg, warning4.toLatin1().constData());
1077 emit object->basicSignal();
1079 QTest::ignoreMessage(QtWarningMsg, warning7.toLatin1().constData());
1080 emit object->anotherBasicSignal();
1082 QTest::ignoreMessage(QtWarningMsg, warning8.toLatin1().constData());
1083 emit object->thirdBasicSignal();
1087 Test file/lineNumbers for inline functions.
1089 void tst_qdeclarativeecmascript::functionErrors()
1091 QDeclarativeComponent component(&engine, TEST_FILE("functionErrors.qml"));
1092 QString url = component.url().toString();
1094 QString warning = url + ":5: Error: Invalid write to global property \"a\"";
1096 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
1098 QObject *object = component.create();
1099 QVERIFY(object != 0);
1104 Test various errors that can occur when assigning a property from script
1106 void tst_qdeclarativeecmascript::propertyAssignmentErrors()
1108 QDeclarativeComponent component(&engine, TEST_FILE("propertyAssignmentErrors.qml"));
1110 QString url = component.url().toString();
1112 QString warning1 = url + ":11:Error: Cannot assign [undefined] to int";
1113 QString warning2 = url + ":17:Error: Cannot assign QString to int";
1115 QTest::ignoreMessage(QtDebugMsg, warning1.toLatin1().constData());
1116 QTest::ignoreMessage(QtDebugMsg, warning2.toLatin1().constData());
1118 QObject *object = component.create();
1119 QVERIFY(object != 0);
1125 Test bindings still work when the reeval is triggered from within
1128 void tst_qdeclarativeecmascript::signalTriggeredBindings()
1130 QDeclarativeComponent component(&engine, TEST_FILE("signalTriggeredBindings.qml"));
1131 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1132 QVERIFY(object != 0);
1134 QCOMPARE(object->property("base").toReal(), 50.);
1135 QCOMPARE(object->property("test1").toReal(), 50.);
1136 QCOMPARE(object->property("test2").toReal(), 50.);
1138 object->basicSignal();
1140 QCOMPARE(object->property("base").toReal(), 200.);
1141 QCOMPARE(object->property("test1").toReal(), 200.);
1142 QCOMPARE(object->property("test2").toReal(), 200.);
1144 object->argumentSignal(10, QString(), 10, MyQmlObject::EnumValue4, Qt::RightButton);
1146 QCOMPARE(object->property("base").toReal(), 400.);
1147 QCOMPARE(object->property("test1").toReal(), 400.);
1148 QCOMPARE(object->property("test2").toReal(), 400.);
1152 Test that list properties can be iterated from ECMAScript
1154 void tst_qdeclarativeecmascript::listProperties()
1156 QDeclarativeComponent component(&engine, TEST_FILE("listProperties.qml"));
1157 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1158 QVERIFY(object != 0);
1160 QCOMPARE(object->property("test1").toInt(), 21);
1161 QCOMPARE(object->property("test2").toInt(), 2);
1162 QCOMPARE(object->property("test3").toBool(), true);
1163 QCOMPARE(object->property("test4").toBool(), true);
1166 void tst_qdeclarativeecmascript::exceptionClearsOnReeval()
1168 QDeclarativeComponent component(&engine, TEST_FILE("exceptionClearsOnReeval.qml"));
1169 QString url = component.url().toString();
1171 QString warning = url + ":4: TypeError: Result of expression 'objectProperty' [null] is not an object.";
1173 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
1174 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1175 QVERIFY(object != 0);
1177 QCOMPARE(object->property("test").toBool(), false);
1179 MyQmlObject object2;
1180 MyQmlObject object3;
1181 object2.setObjectProperty(&object3);
1182 object->setObjectProperty(&object2);
1184 QCOMPARE(object->property("test").toBool(), true);
1187 void tst_qdeclarativeecmascript::exceptionSlotProducesWarning()
1189 QDeclarativeComponent component(&engine, TEST_FILE("exceptionProducesWarning.qml"));
1190 QString url = component.url().toString();
1192 QString warning = component.url().toString() + ":6: Error: JS exception";
1194 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
1195 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1196 QVERIFY(object != 0);
1199 void tst_qdeclarativeecmascript::exceptionBindingProducesWarning()
1201 QDeclarativeComponent component(&engine, TEST_FILE("exceptionProducesWarning2.qml"));
1202 QString url = component.url().toString();
1204 QString warning = component.url().toString() + ":5: Error: JS exception";
1206 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
1207 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1208 QVERIFY(object != 0);
1211 static int transientErrorsMsgCount = 0;
1212 static void transientErrorsMsgHandler(QtMsgType, const char *)
1214 ++transientErrorsMsgCount;
1217 // Check that transient binding errors are not displayed
1218 void tst_qdeclarativeecmascript::transientErrors()
1221 QDeclarativeComponent component(&engine, TEST_FILE("transientErrors.qml"));
1223 transientErrorsMsgCount = 0;
1224 QtMsgHandler old = qInstallMsgHandler(transientErrorsMsgHandler);
1226 QObject *object = component.create();
1227 QVERIFY(object != 0);
1229 qInstallMsgHandler(old);
1231 QCOMPARE(transientErrorsMsgCount, 0);
1234 // One binding erroring multiple times, but then resolving
1236 QDeclarativeComponent component(&engine, TEST_FILE("transientErrors.2.qml"));
1238 transientErrorsMsgCount = 0;
1239 QtMsgHandler old = qInstallMsgHandler(transientErrorsMsgHandler);
1241 QObject *object = component.create();
1242 QVERIFY(object != 0);
1244 qInstallMsgHandler(old);
1246 QCOMPARE(transientErrorsMsgCount, 0);
1250 // Check that errors during shutdown are minimized
1251 void tst_qdeclarativeecmascript::shutdownErrors()
1253 QDeclarativeComponent component(&engine, TEST_FILE("shutdownErrors.qml"));
1254 QObject *object = component.create();
1255 QVERIFY(object != 0);
1257 transientErrorsMsgCount = 0;
1258 QtMsgHandler old = qInstallMsgHandler(transientErrorsMsgHandler);
1262 qInstallMsgHandler(old);
1263 QCOMPARE(transientErrorsMsgCount, 0);
1266 void tst_qdeclarativeecmascript::compositePropertyType()
1268 QDeclarativeComponent component(&engine, TEST_FILE("compositePropertyType.qml"));
1269 QTest::ignoreMessage(QtDebugMsg, "hello world");
1270 QObject *object = qobject_cast<QObject *>(component.create());
1275 void tst_qdeclarativeecmascript::jsObject()
1277 QDeclarativeComponent component(&engine, TEST_FILE("jsObject.qml"));
1278 QObject *object = component.create();
1279 QVERIFY(object != 0);
1281 QCOMPARE(object->property("test").toInt(), 92);
1286 void tst_qdeclarativeecmascript::undefinedResetsProperty()
1289 QDeclarativeComponent component(&engine, TEST_FILE("undefinedResetsProperty.qml"));
1290 QObject *object = component.create();
1291 QVERIFY(object != 0);
1293 QCOMPARE(object->property("resettableProperty").toInt(), 92);
1295 object->setProperty("setUndefined", true);
1297 QCOMPARE(object->property("resettableProperty").toInt(), 13);
1299 object->setProperty("setUndefined", false);
1301 QCOMPARE(object->property("resettableProperty").toInt(), 92);
1306 QDeclarativeComponent component(&engine, TEST_FILE("undefinedResetsProperty.2.qml"));
1307 QObject *object = component.create();
1308 QVERIFY(object != 0);
1310 QCOMPARE(object->property("resettableProperty").toInt(), 19);
1312 QMetaObject::invokeMethod(object, "doReset");
1314 QCOMPARE(object->property("resettableProperty").toInt(), 13);
1321 void tst_qdeclarativeecmascript::bug1()
1323 QDeclarativeComponent component(&engine, TEST_FILE("bug.1.qml"));
1324 QObject *object = component.create();
1325 QVERIFY(object != 0);
1327 QCOMPARE(object->property("test").toInt(), 14);
1329 object->setProperty("a", 11);
1331 QCOMPARE(object->property("test").toInt(), 3);
1333 object->setProperty("b", true);
1335 QCOMPARE(object->property("test").toInt(), 9);
1340 void tst_qdeclarativeecmascript::bug2()
1342 QDeclarativeComponent component(&engine);
1343 component.setData("import Qt.test 1.0;\nQPlainTextEdit { width: 100 }", QUrl());
1345 QObject *object = component.create();
1346 QVERIFY(object != 0);
1351 // Don't crash in createObject when the component has errors.
1352 void tst_qdeclarativeecmascript::dynamicCreationCrash()
1354 QDeclarativeComponent component(&engine, TEST_FILE("dynamicCreation.qml"));
1355 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1356 QVERIFY(object != 0);
1358 QTest::ignoreMessage(QtWarningMsg, "QDeclarativeComponent: Component is not ready");
1359 QMetaObject::invokeMethod(object, "dontCrash");
1360 QObject *created = object->objectProperty();
1361 QVERIFY(created == 0);
1365 void tst_qdeclarativeecmascript::regExpBug()
1367 QDeclarativeComponent component(&engine, TEST_FILE("regExp.qml"));
1368 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1369 QVERIFY(object != 0);
1370 QCOMPARE(object->regExp().pattern(), QLatin1String("[a-zA-z]"));
1373 void tst_qdeclarativeecmascript::callQtInvokables()
1375 MyInvokableObject o;
1377 QDeclarativeEngine qmlengine;
1378 QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(&qmlengine);
1379 QScriptEngine *engine = &ep->scriptEngine;
1381 QStringList names; QList<QScriptValue> values;
1382 names << QLatin1String("object"); values << ep->objectClass->newQObject(&o);
1383 names << QLatin1String("undefined"); values << engine->undefinedValue();
1385 ep->globalClass->explicitSetProperty(names, values);
1387 // Non-existent methods
1389 QCOMPARE(engine->evaluate("object.method_nonexistent()").isError(), true);
1390 QCOMPARE(o.error(), false);
1391 QCOMPARE(o.invoked(), -1);
1392 QCOMPARE(o.actuals().count(), 0);
1395 QCOMPARE(engine->evaluate("object.method_nonexistent(10, 11)").isError(), true);
1396 QCOMPARE(o.error(), false);
1397 QCOMPARE(o.invoked(), -1);
1398 QCOMPARE(o.actuals().count(), 0);
1400 // Insufficient arguments
1402 QCOMPARE(engine->evaluate("object.method_int()").isError(), true);
1403 QCOMPARE(o.error(), false);
1404 QCOMPARE(o.invoked(), -1);
1405 QCOMPARE(o.actuals().count(), 0);
1408 QCOMPARE(engine->evaluate("object.method_intint(10)").isError(), true);
1409 QCOMPARE(o.error(), false);
1410 QCOMPARE(o.invoked(), -1);
1411 QCOMPARE(o.actuals().count(), 0);
1413 // Excessive arguments
1415 QCOMPARE(engine->evaluate("object.method_int(10, 11)").isUndefined(), true);
1416 QCOMPARE(o.error(), false);
1417 QCOMPARE(o.invoked(), 8);
1418 QCOMPARE(o.actuals().count(), 1);
1419 QCOMPARE(o.actuals().at(0), QVariant(10));
1422 QCOMPARE(engine->evaluate("object.method_intint(10, 11, 12)").isUndefined(), true);
1423 QCOMPARE(o.error(), false);
1424 QCOMPARE(o.invoked(), 9);
1425 QCOMPARE(o.actuals().count(), 2);
1426 QCOMPARE(o.actuals().at(0), QVariant(10));
1427 QCOMPARE(o.actuals().at(1), QVariant(11));
1429 // Test return types
1431 QCOMPARE(engine->evaluate("object.method_NoArgs()").isUndefined(), true);
1432 QCOMPARE(o.error(), false);
1433 QCOMPARE(o.invoked(), 0);
1434 QCOMPARE(o.actuals().count(), 0);
1437 QVERIFY(engine->evaluate("object.method_NoArgs_int()").strictlyEquals(QScriptValue(engine, 6)));
1438 QCOMPARE(o.error(), false);
1439 QCOMPARE(o.invoked(), 1);
1440 QCOMPARE(o.actuals().count(), 0);
1443 QVERIFY(engine->evaluate("object.method_NoArgs_real()").strictlyEquals(QScriptValue(engine, 19.75)));
1444 QCOMPARE(o.error(), false);
1445 QCOMPARE(o.invoked(), 2);
1446 QCOMPARE(o.actuals().count(), 0);
1450 QScriptValue ret = engine->evaluate("object.method_NoArgs_QPointF()");
1451 QCOMPARE(ret.toVariant(), QVariant(QPointF(123, 4.5)));
1452 QCOMPARE(o.error(), false);
1453 QCOMPARE(o.invoked(), 3);
1454 QCOMPARE(o.actuals().count(), 0);
1459 QScriptValue ret = engine->evaluate("object.method_NoArgs_QObject()");
1460 QVERIFY(ret.isQObject());
1461 QCOMPARE(ret.toQObject(), (QObject *)&o);
1462 QCOMPARE(o.error(), false);
1463 QCOMPARE(o.invoked(), 4);
1464 QCOMPARE(o.actuals().count(), 0);
1468 QCOMPARE(engine->evaluate("object.method_NoArgs_unknown()").isUndefined(), true);
1469 QCOMPARE(o.error(), false);
1470 QCOMPARE(o.invoked(), 5);
1471 QCOMPARE(o.actuals().count(), 0);
1475 QScriptValue ret = engine->evaluate("object.method_NoArgs_QScriptValue()");
1476 QVERIFY(ret.isString());
1477 QCOMPARE(ret.toString(), QString("Hello world"));
1478 QCOMPARE(o.error(), false);
1479 QCOMPARE(o.invoked(), 6);
1480 QCOMPARE(o.actuals().count(), 0);
1484 QVERIFY(engine->evaluate("object.method_NoArgs_QVariant()").strictlyEquals(QScriptValue(engine, "QML rocks")));
1485 QCOMPARE(o.error(), false);
1486 QCOMPARE(o.invoked(), 7);
1487 QCOMPARE(o.actuals().count(), 0);
1491 QCOMPARE(engine->evaluate("object.method_int(94)").isUndefined(), true);
1492 QCOMPARE(o.error(), false);
1493 QCOMPARE(o.invoked(), 8);
1494 QCOMPARE(o.actuals().count(), 1);
1495 QCOMPARE(o.actuals().at(0), QVariant(94));
1498 QCOMPARE(engine->evaluate("object.method_int(\"94\")").isUndefined(), true);
1499 QCOMPARE(o.error(), false);
1500 QCOMPARE(o.invoked(), 8);
1501 QCOMPARE(o.actuals().count(), 1);
1502 QCOMPARE(o.actuals().at(0), QVariant(94));
1505 QCOMPARE(engine->evaluate("object.method_int(\"not a number\")").isUndefined(), true);
1506 QCOMPARE(o.error(), false);
1507 QCOMPARE(o.invoked(), 8);
1508 QCOMPARE(o.actuals().count(), 1);
1509 QCOMPARE(o.actuals().at(0), QVariant(0));
1512 QCOMPARE(engine->evaluate("object.method_int(null)").isUndefined(), true);
1513 QCOMPARE(o.error(), false);
1514 QCOMPARE(o.invoked(), 8);
1515 QCOMPARE(o.actuals().count(), 1);
1516 QCOMPARE(o.actuals().at(0), QVariant(0));
1519 QCOMPARE(engine->evaluate("object.method_int(undefined)").isUndefined(), true);
1520 QCOMPARE(o.error(), false);
1521 QCOMPARE(o.invoked(), 8);
1522 QCOMPARE(o.actuals().count(), 1);
1523 QCOMPARE(o.actuals().at(0), QVariant(0));
1526 QCOMPARE(engine->evaluate("object.method_int(object)").isUndefined(), true);
1527 QCOMPARE(o.error(), false);
1528 QCOMPARE(o.invoked(), 8);
1529 QCOMPARE(o.actuals().count(), 1);
1530 QCOMPARE(o.actuals().at(0), QVariant(0));
1533 QCOMPARE(engine->evaluate("object.method_intint(122, 9)").isUndefined(), true);
1534 QCOMPARE(o.error(), false);
1535 QCOMPARE(o.invoked(), 9);
1536 QCOMPARE(o.actuals().count(), 2);
1537 QCOMPARE(o.actuals().at(0), QVariant(122));
1538 QCOMPARE(o.actuals().at(1), QVariant(9));
1541 QCOMPARE(engine->evaluate("object.method_real(94.3)").isUndefined(), true);
1542 QCOMPARE(o.error(), false);
1543 QCOMPARE(o.invoked(), 10);
1544 QCOMPARE(o.actuals().count(), 1);
1545 QCOMPARE(o.actuals().at(0), QVariant(94.3));
1548 QCOMPARE(engine->evaluate("object.method_real(\"94.3\")").isUndefined(), true);
1549 QCOMPARE(o.error(), false);
1550 QCOMPARE(o.invoked(), 10);
1551 QCOMPARE(o.actuals().count(), 1);
1552 QCOMPARE(o.actuals().at(0), QVariant(94.3));
1555 QCOMPARE(engine->evaluate("object.method_real(\"not a number\")").isUndefined(), true);
1556 QCOMPARE(o.error(), false);
1557 QCOMPARE(o.invoked(), 10);
1558 QCOMPARE(o.actuals().count(), 1);
1559 QVERIFY(qIsNaN(o.actuals().at(0).toDouble()));
1562 QCOMPARE(engine->evaluate("object.method_real(null)").isUndefined(), true);
1563 QCOMPARE(o.error(), false);
1564 QCOMPARE(o.invoked(), 10);
1565 QCOMPARE(o.actuals().count(), 1);
1566 QCOMPARE(o.actuals().at(0), QVariant(0));
1569 QCOMPARE(engine->evaluate("object.method_real(undefined)").isUndefined(), true);
1570 QCOMPARE(o.error(), false);
1571 QCOMPARE(o.invoked(), 10);
1572 QCOMPARE(o.actuals().count(), 1);
1573 QVERIFY(qIsNaN(o.actuals().at(0).toDouble()));
1576 QCOMPARE(engine->evaluate("object.method_real(object)").isUndefined(), true);
1577 QCOMPARE(o.error(), false);
1578 QCOMPARE(o.invoked(), 10);
1579 QCOMPARE(o.actuals().count(), 1);
1580 QVERIFY(qIsNaN(o.actuals().at(0).toDouble()));
1583 QCOMPARE(engine->evaluate("object.method_QString(\"Hello world\")").isUndefined(), true);
1584 QCOMPARE(o.error(), false);
1585 QCOMPARE(o.invoked(), 11);
1586 QCOMPARE(o.actuals().count(), 1);
1587 QCOMPARE(o.actuals().at(0), QVariant("Hello world"));
1590 QCOMPARE(engine->evaluate("object.method_QString(19)").isUndefined(), true);
1591 QCOMPARE(o.error(), false);
1592 QCOMPARE(o.invoked(), 11);
1593 QCOMPARE(o.actuals().count(), 1);
1594 QCOMPARE(o.actuals().at(0), QVariant("19"));
1598 QString expected = "MyInvokableObject(0x" + QString::number((quintptr)&o, 16) + ")";
1599 QCOMPARE(engine->evaluate("object.method_QString(object)").isUndefined(), true);
1600 QCOMPARE(o.error(), false);
1601 QCOMPARE(o.invoked(), 11);
1602 QCOMPARE(o.actuals().count(), 1);
1603 QCOMPARE(o.actuals().at(0), QVariant(expected));
1607 QCOMPARE(engine->evaluate("object.method_QString(null)").isUndefined(), true);
1608 QCOMPARE(o.error(), false);
1609 QCOMPARE(o.invoked(), 11);
1610 QCOMPARE(o.actuals().count(), 1);
1611 QCOMPARE(o.actuals().at(0), QVariant(QString()));
1614 QCOMPARE(engine->evaluate("object.method_QString(undefined)").isUndefined(), true);
1615 QCOMPARE(o.error(), false);
1616 QCOMPARE(o.invoked(), 11);
1617 QCOMPARE(o.actuals().count(), 1);
1618 QCOMPARE(o.actuals().at(0), QVariant(QString()));
1621 QCOMPARE(engine->evaluate("object.method_QPointF(0)").isUndefined(), true);
1622 QCOMPARE(o.error(), false);
1623 QCOMPARE(o.invoked(), 12);
1624 QCOMPARE(o.actuals().count(), 1);
1625 QCOMPARE(o.actuals().at(0), QVariant(QPointF()));
1628 QCOMPARE(engine->evaluate("object.method_QPointF(null)").isUndefined(), true);
1629 QCOMPARE(o.error(), false);
1630 QCOMPARE(o.invoked(), 12);
1631 QCOMPARE(o.actuals().count(), 1);
1632 QCOMPARE(o.actuals().at(0), QVariant(QPointF()));
1635 QCOMPARE(engine->evaluate("object.method_QPointF(undefined)").isUndefined(), true);
1636 QCOMPARE(o.error(), false);
1637 QCOMPARE(o.invoked(), 12);
1638 QCOMPARE(o.actuals().count(), 1);
1639 QCOMPARE(o.actuals().at(0), QVariant(QPointF()));
1642 QCOMPARE(engine->evaluate("object.method_QPointF(object)").isUndefined(), true);
1643 QCOMPARE(o.error(), false);
1644 QCOMPARE(o.invoked(), 12);
1645 QCOMPARE(o.actuals().count(), 1);
1646 QCOMPARE(o.actuals().at(0), QVariant(QPointF()));
1649 QCOMPARE(engine->evaluate("object.method_QPointF(object.method_get_QPointF())").isUndefined(), true);
1650 QCOMPARE(o.error(), false);
1651 QCOMPARE(o.invoked(), 12);
1652 QCOMPARE(o.actuals().count(), 1);
1653 QCOMPARE(o.actuals().at(0), QVariant(QPointF(99.3, -10.2)));
1656 QCOMPARE(engine->evaluate("object.method_QPointF(object.method_get_QPoint())").isUndefined(), true);
1657 QCOMPARE(o.error(), false);
1658 QCOMPARE(o.invoked(), 12);
1659 QCOMPARE(o.actuals().count(), 1);
1660 QCOMPARE(o.actuals().at(0), QVariant(QPointF(9, 12)));
1663 QCOMPARE(engine->evaluate("object.method_QObject(0)").isUndefined(), true);
1664 QCOMPARE(o.error(), false);
1665 QCOMPARE(o.invoked(), 13);
1666 QCOMPARE(o.actuals().count(), 1);
1667 QCOMPARE(o.actuals().at(0), qVariantFromValue((QObject *)0));
1670 QCOMPARE(engine->evaluate("object.method_QObject(\"Hello world\")").isUndefined(), true);
1671 QCOMPARE(o.error(), false);
1672 QCOMPARE(o.invoked(), 13);
1673 QCOMPARE(o.actuals().count(), 1);
1674 QCOMPARE(o.actuals().at(0), qVariantFromValue((QObject *)0));
1677 QCOMPARE(engine->evaluate("object.method_QObject(null)").isUndefined(), true);
1678 QCOMPARE(o.error(), false);
1679 QCOMPARE(o.invoked(), 13);
1680 QCOMPARE(o.actuals().count(), 1);
1681 QCOMPARE(o.actuals().at(0), qVariantFromValue((QObject *)0));
1684 QCOMPARE(engine->evaluate("object.method_QObject(undefined)").isUndefined(), true);
1685 QCOMPARE(o.error(), false);
1686 QCOMPARE(o.invoked(), 13);
1687 QCOMPARE(o.actuals().count(), 1);
1688 QCOMPARE(o.actuals().at(0), qVariantFromValue((QObject *)0));
1691 QCOMPARE(engine->evaluate("object.method_QObject(object)").isUndefined(), true);
1692 QCOMPARE(o.error(), false);
1693 QCOMPARE(o.invoked(), 13);
1694 QCOMPARE(o.actuals().count(), 1);
1695 QCOMPARE(o.actuals().at(0), qVariantFromValue((QObject *)&o));
1698 QCOMPARE(engine->evaluate("object.method_QScriptValue(null)").isUndefined(), true);
1699 QCOMPARE(o.error(), false);
1700 QCOMPARE(o.invoked(), 14);
1701 QCOMPARE(o.actuals().count(), 1);
1702 QVERIFY(qvariant_cast<QScriptValue>(o.actuals().at(0)).isNull());
1705 QCOMPARE(engine->evaluate("object.method_QScriptValue(undefined)").isUndefined(), true);
1706 QCOMPARE(o.error(), false);
1707 QCOMPARE(o.invoked(), 14);
1708 QCOMPARE(o.actuals().count(), 1);
1709 QVERIFY(qvariant_cast<QScriptValue>(o.actuals().at(0)).isUndefined());
1712 QCOMPARE(engine->evaluate("object.method_QScriptValue(19)").isUndefined(), true);
1713 QCOMPARE(o.error(), false);
1714 QCOMPARE(o.invoked(), 14);
1715 QCOMPARE(o.actuals().count(), 1);
1716 QVERIFY(qvariant_cast<QScriptValue>(o.actuals().at(0)).strictlyEquals(QScriptValue(engine, 19)));
1719 QCOMPARE(engine->evaluate("object.method_QScriptValue([19, 20])").isUndefined(), true);
1720 QCOMPARE(o.error(), false);
1721 QCOMPARE(o.invoked(), 14);
1722 QCOMPARE(o.actuals().count(), 1);
1723 QVERIFY(qvariant_cast<QScriptValue>(o.actuals().at(0)).isArray());
1726 QCOMPARE(engine->evaluate("object.method_intQScriptValue(4, null)").isUndefined(), true);
1727 QCOMPARE(o.error(), false);
1728 QCOMPARE(o.invoked(), 15);
1729 QCOMPARE(o.actuals().count(), 2);
1730 QCOMPARE(o.actuals().at(0), QVariant(4));
1731 QVERIFY(qvariant_cast<QScriptValue>(o.actuals().at(1)).isNull());
1734 QCOMPARE(engine->evaluate("object.method_intQScriptValue(8, undefined)").isUndefined(), true);
1735 QCOMPARE(o.error(), false);
1736 QCOMPARE(o.invoked(), 15);
1737 QCOMPARE(o.actuals().count(), 2);
1738 QCOMPARE(o.actuals().at(0), QVariant(8));
1739 QVERIFY(qvariant_cast<QScriptValue>(o.actuals().at(1)).isUndefined());
1742 QCOMPARE(engine->evaluate("object.method_intQScriptValue(3, 19)").isUndefined(), true);
1743 QCOMPARE(o.error(), false);
1744 QCOMPARE(o.invoked(), 15);
1745 QCOMPARE(o.actuals().count(), 2);
1746 QCOMPARE(o.actuals().at(0), QVariant(3));
1747 QVERIFY(qvariant_cast<QScriptValue>(o.actuals().at(1)).strictlyEquals(QScriptValue(engine, 19)));
1750 QCOMPARE(engine->evaluate("object.method_intQScriptValue(44, [19, 20])").isUndefined(), true);
1751 QCOMPARE(o.error(), false);
1752 QCOMPARE(o.invoked(), 15);
1753 QCOMPARE(o.actuals().count(), 2);
1754 QCOMPARE(o.actuals().at(0), QVariant(44));
1755 QVERIFY(qvariant_cast<QScriptValue>(o.actuals().at(1)).isArray());
1758 QCOMPARE(engine->evaluate("object.method_overload()").isError(), true);
1759 QCOMPARE(o.error(), false);
1760 QCOMPARE(o.invoked(), -1);
1761 QCOMPARE(o.actuals().count(), 0);
1764 QCOMPARE(engine->evaluate("object.method_overload(10)").isUndefined(), true);
1765 QCOMPARE(o.error(), false);
1766 QCOMPARE(o.invoked(), 16);
1767 QCOMPARE(o.actuals().count(), 1);
1768 QCOMPARE(o.actuals().at(0), QVariant(10));
1771 QCOMPARE(engine->evaluate("object.method_overload(10, 11)").isUndefined(), true);
1772 QCOMPARE(o.error(), false);
1773 QCOMPARE(o.invoked(), 17);
1774 QCOMPARE(o.actuals().count(), 2);
1775 QCOMPARE(o.actuals().at(0), QVariant(10));
1776 QCOMPARE(o.actuals().at(1), QVariant(11));
1779 QCOMPARE(engine->evaluate("object.method_overload(\"Hello\")").isUndefined(), true);
1780 QCOMPARE(o.error(), false);
1781 QCOMPARE(o.invoked(), 18);
1782 QCOMPARE(o.actuals().count(), 1);
1783 QCOMPARE(o.actuals().at(0), QVariant(QString("Hello")));
1786 QCOMPARE(engine->evaluate("object.method_with_enum(9)").isUndefined(), true);
1787 QCOMPARE(o.error(), false);
1788 QCOMPARE(o.invoked(), 19);
1789 QCOMPARE(o.actuals().count(), 1);
1790 QCOMPARE(o.actuals().at(0), QVariant(9));
1793 QVERIFY(engine->evaluate("object.method_default(10)").strictlyEquals(QScriptValue(19)));
1794 QCOMPARE(o.error(), false);
1795 QCOMPARE(o.invoked(), 20);
1796 QCOMPARE(o.actuals().count(), 2);
1797 QCOMPARE(o.actuals().at(0), QVariant(10));
1798 QCOMPARE(o.actuals().at(1), QVariant(19));
1801 QVERIFY(engine->evaluate("object.method_default(10, 13)").strictlyEquals(QScriptValue(13)));
1802 QCOMPARE(o.error(), false);
1803 QCOMPARE(o.invoked(), 20);
1804 QCOMPARE(o.actuals().count(), 2);
1805 QCOMPARE(o.actuals().at(0), QVariant(10));
1806 QCOMPARE(o.actuals().at(1), QVariant(13));
1809 QCOMPARE(engine->evaluate("object.method_inherited(9)").isUndefined(), true);
1810 QCOMPARE(o.error(), false);
1811 QCOMPARE(o.invoked(), -3);
1812 QCOMPARE(o.actuals().count(), 1);
1813 QCOMPARE(o.actuals().at(0), QVariant(9));
1816 QCOMPARE(engine->evaluate("object.method_QVariant(9)").isUndefined(), true);
1817 QCOMPARE(o.error(), false);
1818 QCOMPARE(o.invoked(), 21);
1819 QCOMPARE(o.actuals().count(), 2);
1820 QCOMPARE(o.actuals().at(0), QVariant(9));
1821 QCOMPARE(o.actuals().at(1), QVariant());
1824 QCOMPARE(engine->evaluate("object.method_QVariant(\"Hello\", \"World\")").isUndefined(), true);
1825 QCOMPARE(o.error(), false);
1826 QCOMPARE(o.invoked(), 21);
1827 QCOMPARE(o.actuals().count(), 2);
1828 QCOMPARE(o.actuals().at(0), QVariant(QString("Hello")));
1829 QCOMPARE(o.actuals().at(1), QVariant(QString("World")));
1832 // QTBUG-13047 (check that you can pass registered object types as args)
1833 void tst_qdeclarativeecmascript::invokableObjectArg()
1835 QDeclarativeComponent component(&engine, TEST_FILE("invokableObjectArg.qml"));
1837 QObject *o = component.create();
1839 MyQmlObject *qmlobject = qobject_cast<MyQmlObject *>(o);
1841 QCOMPARE(qmlobject->myinvokableObject, qmlobject);
1846 // QTBUG-13047 (check that you can return registered object types from methods)
1847 void tst_qdeclarativeecmascript::invokableObjectRet()
1849 QDeclarativeComponent component(&engine, TEST_FILE("invokableObjectRet.qml"));
1851 QObject *o = component.create();
1853 QCOMPARE(o->property("test").toBool(), true);
1858 void tst_qdeclarativeecmascript::listToVariant()
1860 QDeclarativeComponent component(&engine, TEST_FILE("listToVariant.qml"));
1862 MyQmlContainer container;
1864 QDeclarativeContext context(engine.rootContext());
1865 context.setContextObject(&container);
1867 QObject *object = component.create(&context);
1868 QVERIFY(object != 0);
1870 QVariant v = object->property("test");
1871 QCOMPARE(v.userType(), qMetaTypeId<QDeclarativeListReference>());
1872 QVERIFY(qvariant_cast<QDeclarativeListReference>(v).object() == &container);
1878 void tst_qdeclarativeecmascript::multiEngineObject()
1881 obj.setStringProperty("Howdy planet");
1883 QDeclarativeEngine e1;
1884 e1.rootContext()->setContextProperty("thing", &obj);
1885 QDeclarativeComponent c1(&e1, TEST_FILE("multiEngineObject.qml"));
1887 QDeclarativeEngine e2;
1888 e2.rootContext()->setContextProperty("thing", &obj);
1889 QDeclarativeComponent c2(&e2, TEST_FILE("multiEngineObject.qml"));
1891 QObject *o1 = c1.create();
1892 QObject *o2 = c2.create();
1894 QCOMPARE(o1->property("test").toString(), QString("Howdy planet"));
1895 QCOMPARE(o2->property("test").toString(), QString("Howdy planet"));
1901 // Test that references to QObjects are cleanup when the object is destroyed
1902 void tst_qdeclarativeecmascript::deletedObject()
1904 QDeclarativeComponent component(&engine, TEST_FILE("deletedObject.qml"));
1906 QObject *object = component.create();
1908 QCOMPARE(object->property("test1").toBool(), true);
1909 QCOMPARE(object->property("test2").toBool(), true);
1910 QCOMPARE(object->property("test3").toBool(), true);
1911 QCOMPARE(object->property("test4").toBool(), true);
1916 void tst_qdeclarativeecmascript::attachedPropertyScope()
1918 QDeclarativeComponent component(&engine, TEST_FILE("attachedPropertyScope.qml"));
1920 QObject *object = component.create();
1921 QVERIFY(object != 0);
1923 MyQmlAttachedObject *attached =
1924 qobject_cast<MyQmlAttachedObject *>(qmlAttachedPropertiesObject<MyQmlObject>(object));
1925 QVERIFY(attached != 0);
1927 QCOMPARE(object->property("value2").toInt(), 0);
1929 attached->emitMySignal();
1931 QCOMPARE(object->property("value2").toInt(), 9);
1936 void tst_qdeclarativeecmascript::scriptConnect()
1939 QDeclarativeComponent component(&engine, TEST_FILE("scriptConnect.1.qml"));
1941 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
1942 QVERIFY(object != 0);
1944 QCOMPARE(object->property("test").toBool(), false);
1945 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
1946 QCOMPARE(object->property("test").toBool(), true);
1952 QDeclarativeComponent component(&engine, TEST_FILE("scriptConnect.2.qml"));
1954 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
1955 QVERIFY(object != 0);
1957 QCOMPARE(object->property("test").toBool(), false);
1958 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
1959 QCOMPARE(object->property("test").toBool(), true);
1965 QDeclarativeComponent component(&engine, TEST_FILE("scriptConnect.3.qml"));
1967 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
1968 QVERIFY(object != 0);
1970 QCOMPARE(object->property("test").toBool(), false);
1971 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
1972 QCOMPARE(object->property("test").toBool(), true);
1978 QDeclarativeComponent component(&engine, TEST_FILE("scriptConnect.4.qml"));
1980 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
1981 QVERIFY(object != 0);
1983 QCOMPARE(object->methodCalled(), false);
1984 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
1985 QCOMPARE(object->methodCalled(), true);
1991 QDeclarativeComponent component(&engine, TEST_FILE("scriptConnect.5.qml"));
1993 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
1994 QVERIFY(object != 0);
1996 QCOMPARE(object->methodCalled(), false);
1997 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
1998 QCOMPARE(object->methodCalled(), true);
2004 QDeclarativeComponent component(&engine, TEST_FILE("scriptConnect.6.qml"));
2006 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2007 QVERIFY(object != 0);
2009 QCOMPARE(object->property("test").toInt(), 0);
2010 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2011 QCOMPARE(object->property("test").toInt(), 2);
2017 void tst_qdeclarativeecmascript::scriptDisconnect()
2020 QDeclarativeComponent component(&engine, TEST_FILE("scriptDisconnect.1.qml"));
2022 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2023 QVERIFY(object != 0);
2025 QCOMPARE(object->property("test").toInt(), 0);
2026 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2027 QCOMPARE(object->property("test").toInt(), 1);
2028 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2029 QCOMPARE(object->property("test").toInt(), 2);
2030 emit object->basicSignal();
2031 QCOMPARE(object->property("test").toInt(), 2);
2032 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2033 QCOMPARE(object->property("test").toInt(), 2);
2039 QDeclarativeComponent component(&engine, TEST_FILE("scriptDisconnect.2.qml"));
2041 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2042 QVERIFY(object != 0);
2044 QCOMPARE(object->property("test").toInt(), 0);
2045 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2046 QCOMPARE(object->property("test").toInt(), 1);
2047 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2048 QCOMPARE(object->property("test").toInt(), 2);
2049 emit object->basicSignal();
2050 QCOMPARE(object->property("test").toInt(), 2);
2051 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2052 QCOMPARE(object->property("test").toInt(), 2);
2058 QDeclarativeComponent component(&engine, TEST_FILE("scriptDisconnect.3.qml"));
2060 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2061 QVERIFY(object != 0);
2063 QCOMPARE(object->property("test").toInt(), 0);
2064 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2065 QCOMPARE(object->property("test").toInt(), 1);
2066 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2067 QCOMPARE(object->property("test").toInt(), 2);
2068 emit object->basicSignal();
2069 QCOMPARE(object->property("test").toInt(), 2);
2070 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2071 QCOMPARE(object->property("test").toInt(), 3);
2076 QDeclarativeComponent component(&engine, TEST_FILE("scriptDisconnect.4.qml"));
2078 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2079 QVERIFY(object != 0);
2081 QCOMPARE(object->property("test").toInt(), 0);
2082 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2083 QCOMPARE(object->property("test").toInt(), 1);
2084 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2085 QCOMPARE(object->property("test").toInt(), 2);
2086 emit object->basicSignal();
2087 QCOMPARE(object->property("test").toInt(), 2);
2088 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2089 QCOMPARE(object->property("test").toInt(), 3);
2095 class OwnershipObject : public QObject
2099 OwnershipObject() { object = new QObject; }
2101 QPointer<QObject> object;
2104 QObject *getObject() { return object; }
2107 void tst_qdeclarativeecmascript::ownership()
2109 OwnershipObject own;
2110 QDeclarativeContext *context = new QDeclarativeContext(engine.rootContext());
2111 context->setContextObject(&own);
2114 QDeclarativeComponent component(&engine, TEST_FILE("ownership.qml"));
2116 QVERIFY(own.object != 0);
2118 QObject *object = component.create(context);
2119 QDeclarativeEnginePrivate::getScriptEngine(&engine)->collectGarbage();
2121 QCoreApplication::processEvents(QEventLoop::DeferredDeletion);
2123 QVERIFY(own.object == 0);
2128 own.object = new QObject(&own);
2131 QDeclarativeComponent component(&engine, TEST_FILE("ownership.qml"));
2133 QVERIFY(own.object != 0);
2135 QObject *object = component.create(context);
2136 QDeclarativeEnginePrivate::getScriptEngine(&engine)->collectGarbage();
2138 QCoreApplication::processEvents(QEventLoop::DeferredDeletion);
2140 QVERIFY(own.object != 0);
2146 class CppOwnershipReturnValue : public QObject
2150 CppOwnershipReturnValue() : value(0) {}
2151 ~CppOwnershipReturnValue() { delete value; }
2153 Q_INVOKABLE QObject *create() {
2154 Q_ASSERT(value == 0);
2156 value = new QObject;
2157 QDeclarativeEngine::setObjectOwnership(value, QDeclarativeEngine::CppOwnership);
2161 Q_INVOKABLE MyQmlObject *createQmlObject() {
2162 Q_ASSERT(value == 0);
2164 MyQmlObject *rv = new MyQmlObject;
2169 QPointer<QObject> value;
2173 // Test setObjectOwnership(CppOwnership) works even when there is no QDeclarativeData
2174 void tst_qdeclarativeecmascript::cppOwnershipReturnValue()
2176 CppOwnershipReturnValue source;
2179 QDeclarativeEngine engine;
2180 engine.rootContext()->setContextProperty("source", &source);
2182 QVERIFY(source.value == 0);
2184 QDeclarativeComponent component(&engine);
2185 component.setData("import QtQuick 1.0\nQtObject {\nComponent.onCompleted: { var a = source.create(); }\n}\n", QUrl());
2187 QObject *object = component.create();
2189 QVERIFY(object != 0);
2190 QVERIFY(source.value != 0);
2195 QCoreApplication::instance()->processEvents(QEventLoop::DeferredDeletion);
2197 QVERIFY(source.value != 0);
2201 void tst_qdeclarativeecmascript::ownershipCustomReturnValue()
2203 CppOwnershipReturnValue source;
2206 QDeclarativeEngine engine;
2207 engine.rootContext()->setContextProperty("source", &source);
2209 QVERIFY(source.value == 0);
2211 QDeclarativeComponent component(&engine);
2212 component.setData("import QtQuick 1.0\nQtObject {\nComponent.onCompleted: { var a = source.createQmlObject(); }\n}\n", QUrl());
2214 QObject *object = component.create();
2216 QVERIFY(object != 0);
2217 QVERIFY(source.value != 0);
2222 QCoreApplication::instance()->processEvents(QEventLoop::DeferredDeletion);
2224 QVERIFY(source.value == 0);
2227 class QListQObjectMethodsObject : public QObject
2231 QListQObjectMethodsObject() {
2232 m_objects.append(new MyQmlObject());
2233 m_objects.append(new MyQmlObject());
2236 ~QListQObjectMethodsObject() {
2237 qDeleteAll(m_objects);
2241 QList<QObject *> getObjects() { return m_objects; }
2244 QList<QObject *> m_objects;
2247 // Tests that returning a QList<QObject*> from a method works
2248 void tst_qdeclarativeecmascript::qlistqobjectMethods()
2250 QListQObjectMethodsObject obj;
2251 QDeclarativeContext *context = new QDeclarativeContext(engine.rootContext());
2252 context->setContextObject(&obj);
2254 QDeclarativeComponent component(&engine, TEST_FILE("qlistqobjectMethods.qml"));
2256 QObject *object = component.create(context);
2258 QCOMPARE(object->property("test").toInt(), 2);
2259 QCOMPARE(object->property("test2").toBool(), true);
2265 void tst_qdeclarativeecmascript::strictlyEquals()
2267 QDeclarativeComponent component(&engine, TEST_FILE("strictlyEquals.qml"));
2269 QObject *object = component.create();
2270 QVERIFY(object != 0);
2272 QCOMPARE(object->property("test1").toBool(), true);
2273 QCOMPARE(object->property("test2").toBool(), true);
2274 QCOMPARE(object->property("test3").toBool(), true);
2275 QCOMPARE(object->property("test4").toBool(), true);
2276 QCOMPARE(object->property("test5").toBool(), true);
2277 QCOMPARE(object->property("test6").toBool(), true);
2278 QCOMPARE(object->property("test7").toBool(), true);
2279 QCOMPARE(object->property("test8").toBool(), true);
2284 void tst_qdeclarativeecmascript::compiled()
2286 QDeclarativeComponent component(&engine, TEST_FILE("compiled.qml"));
2288 QObject *object = component.create();
2289 QVERIFY(object != 0);
2291 QCOMPARE(object->property("test1").toReal(), qreal(15.7));
2292 QCOMPARE(object->property("test2").toReal(), qreal(-6.7));
2293 QCOMPARE(object->property("test3").toBool(), true);
2294 QCOMPARE(object->property("test4").toBool(), false);
2295 QCOMPARE(object->property("test5").toBool(), false);
2296 QCOMPARE(object->property("test6").toBool(), true);
2298 QCOMPARE(object->property("test7").toInt(), 185);
2299 QCOMPARE(object->property("test8").toInt(), 167);
2300 QCOMPARE(object->property("test9").toBool(), true);
2301 QCOMPARE(object->property("test10").toBool(), false);
2302 QCOMPARE(object->property("test11").toBool(), false);
2303 QCOMPARE(object->property("test12").toBool(), true);
2305 QCOMPARE(object->property("test13").toString(), QLatin1String("HelloWorld"));
2306 QCOMPARE(object->property("test14").toString(), QLatin1String("Hello World"));
2307 QCOMPARE(object->property("test15").toBool(), false);
2308 QCOMPARE(object->property("test16").toBool(), true);
2310 QCOMPARE(object->property("test17").toInt(), 5);
2311 QCOMPARE(object->property("test18").toReal(), qreal(176));
2312 QCOMPARE(object->property("test19").toInt(), 7);
2313 QCOMPARE(object->property("test20").toReal(), qreal(6.7));
2314 QCOMPARE(object->property("test21").toString(), QLatin1String("6.7"));
2315 QCOMPARE(object->property("test22").toString(), QLatin1String("!"));
2316 QCOMPARE(object->property("test23").toBool(), true);
2317 QCOMPARE(qvariant_cast<QColor>(object->property("test24")), QColor(0x11,0x22,0x33));
2318 QCOMPARE(qvariant_cast<QColor>(object->property("test25")), QColor(0x11,0x22,0x33,0xAA));
2323 // Test that numbers assigned in bindings as strings work consistently
2324 void tst_qdeclarativeecmascript::numberAssignment()
2326 QDeclarativeComponent component(&engine, TEST_FILE("numberAssignment.qml"));
2328 QObject *object = component.create();
2329 QVERIFY(object != 0);
2331 QCOMPARE(object->property("test1"), QVariant((qreal)6.7));
2332 QCOMPARE(object->property("test2"), QVariant((qreal)6.7));
2333 QCOMPARE(object->property("test2"), QVariant((qreal)6.7));
2334 QCOMPARE(object->property("test3"), QVariant((qreal)6));
2335 QCOMPARE(object->property("test4"), QVariant((qreal)6));
2337 QCOMPARE(object->property("test5"), QVariant((int)7));
2338 QCOMPARE(object->property("test6"), QVariant((int)7));
2339 QCOMPARE(object->property("test7"), QVariant((int)6));
2340 QCOMPARE(object->property("test8"), QVariant((int)6));
2342 QCOMPARE(object->property("test9"), QVariant((unsigned int)7));
2343 QCOMPARE(object->property("test10"), QVariant((unsigned int)7));
2344 QCOMPARE(object->property("test11"), QVariant((unsigned int)6));
2345 QCOMPARE(object->property("test12"), QVariant((unsigned int)6));
2350 void tst_qdeclarativeecmascript::propertySplicing()
2352 QDeclarativeComponent component(&engine, TEST_FILE("propertySplicing.qml"));
2354 QObject *object = component.create();
2355 QVERIFY(object != 0);
2357 QCOMPARE(object->property("test").toBool(), true);
2363 void tst_qdeclarativeecmascript::signalWithUnknownTypes()
2365 QDeclarativeComponent component(&engine, TEST_FILE("signalWithUnknownTypes.qml"));
2367 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2368 QVERIFY(object != 0);
2370 MyQmlObject::MyType type;
2371 type.value = 0x8971123;
2372 emit object->signalWithUnknownType(type);
2374 MyQmlObject::MyType result = qvariant_cast<MyQmlObject::MyType>(object->variant());
2376 QCOMPARE(result.value, type.value);
2382 // Test that assigning a null object works
2383 // Regressed with: df1788b4dbbb2826ae63f26bdf166342595343f4
2384 void tst_qdeclarativeecmascript::nullObjectBinding()
2386 QDeclarativeComponent component(&engine, TEST_FILE("nullObjectBinding.qml"));
2388 QObject *object = component.create();
2389 QVERIFY(object != 0);
2391 QVERIFY(object->property("test") == QVariant::fromValue((QObject *)0));
2396 // Test that bindings don't evaluate once the engine has been destroyed
2397 void tst_qdeclarativeecmascript::deletedEngine()
2399 QDeclarativeEngine *engine = new QDeclarativeEngine;
2400 QDeclarativeComponent component(engine, TEST_FILE("deletedEngine.qml"));
2402 QObject *object = component.create();
2403 QVERIFY(object != 0);
2405 QCOMPARE(object->property("a").toInt(), 39);
2406 object->setProperty("b", QVariant(9));
2407 QCOMPARE(object->property("a").toInt(), 117);
2411 QCOMPARE(object->property("a").toInt(), 117);
2412 object->setProperty("b", QVariant(10));
2413 QCOMPARE(object->property("a").toInt(), 117);
2418 // Test the crashing part of QTBUG-9705
2419 void tst_qdeclarativeecmascript::libraryScriptAssert()
2421 QDeclarativeComponent component(&engine, TEST_FILE("libraryScriptAssert.qml"));
2423 QObject *object = component.create();
2424 QVERIFY(object != 0);
2429 void tst_qdeclarativeecmascript::variantsAssignedUndefined()
2431 QDeclarativeComponent component(&engine, TEST_FILE("variantsAssignedUndefined.qml"));
2433 QObject *object = component.create();
2434 QVERIFY(object != 0);
2436 QCOMPARE(object->property("test1").toInt(), 10);
2437 QCOMPARE(object->property("test2").toInt(), 11);
2439 object->setProperty("runTest", true);
2441 QCOMPARE(object->property("test1"), QVariant());
2442 QCOMPARE(object->property("test2"), QVariant());
2448 void tst_qdeclarativeecmascript::qtbug_9792()
2450 QDeclarativeComponent component(&engine, TEST_FILE("qtbug_9792.qml"));
2452 QDeclarativeContext *context = new QDeclarativeContext(engine.rootContext());
2454 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create(context));
2455 QVERIFY(object != 0);
2457 QTest::ignoreMessage(QtDebugMsg, "Hello world!");
2458 object->basicSignal();
2462 transientErrorsMsgCount = 0;
2463 QtMsgHandler old = qInstallMsgHandler(transientErrorsMsgHandler);
2465 object->basicSignal();
2467 qInstallMsgHandler(old);
2469 QCOMPARE(transientErrorsMsgCount, 0);
2474 // Verifies that QDeclarativeGuard<>s used in the vmemetaobject are cleaned correctly
2475 void tst_qdeclarativeecmascript::qtcreatorbug_1289()
2477 QDeclarativeComponent component(&engine, TEST_FILE("qtcreatorbug_1289.qml"));
2479 QObject *o = component.create();
2482 QObject *nested = qvariant_cast<QObject *>(o->property("object"));
2483 QVERIFY(nested != 0);
2485 QVERIFY(qvariant_cast<QObject *>(nested->property("nestedObject")) == o);
2488 nested = qvariant_cast<QObject *>(o->property("object"));
2489 QVERIFY(nested == 0);
2491 // If the bug is present, the next line will crash
2495 // Test that we shut down without stupid warnings
2496 void tst_qdeclarativeecmascript::noSpuriousWarningsAtShutdown()
2499 QDeclarativeComponent component(&engine, TEST_FILE("noSpuriousWarningsAtShutdown.qml"));
2501 QObject *o = component.create();
2503 transientErrorsMsgCount = 0;
2504 QtMsgHandler old = qInstallMsgHandler(transientErrorsMsgHandler);
2508 qInstallMsgHandler(old);
2510 QCOMPARE(transientErrorsMsgCount, 0);
2515 QDeclarativeComponent component(&engine, TEST_FILE("noSpuriousWarningsAtShutdown.2.qml"));
2517 QObject *o = component.create();
2519 transientErrorsMsgCount = 0;
2520 QtMsgHandler old = qInstallMsgHandler(transientErrorsMsgHandler);
2524 qInstallMsgHandler(old);
2526 QCOMPARE(transientErrorsMsgCount, 0);
2530 void tst_qdeclarativeecmascript::canAssignNullToQObject()
2533 QDeclarativeComponent component(&engine, TEST_FILE("canAssignNullToQObject.1.qml"));
2535 MyQmlObject *o = qobject_cast<MyQmlObject *>(component.create());
2538 QVERIFY(o->objectProperty() != 0);
2540 o->setProperty("runTest", true);
2542 QVERIFY(o->objectProperty() == 0);
2548 QDeclarativeComponent component(&engine, TEST_FILE("canAssignNullToQObject.2.qml"));
2550 MyQmlObject *o = qobject_cast<MyQmlObject *>(component.create());
2553 QVERIFY(o->objectProperty() == 0);
2559 void tst_qdeclarativeecmascript::functionAssignment_fromBinding()
2561 QDeclarativeComponent component(&engine, TEST_FILE("functionAssignment.1.qml"));
2563 QString url = component.url().toString();
2564 QString warning = url + ":4: Unable to assign a function to a property.";
2565 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
2567 MyQmlObject *o = qobject_cast<MyQmlObject *>(component.create());
2570 QVERIFY(!o->property("a").isValid());
2575 void tst_qdeclarativeecmascript::functionAssignment_fromJS()
2577 QFETCH(QString, triggerProperty);
2579 QDeclarativeComponent component(&engine, TEST_FILE("functionAssignment.2.qml"));
2580 QVERIFY2(component.errorString().isEmpty(), qPrintable(component.errorString()));
2582 MyQmlObject *o = qobject_cast<MyQmlObject *>(component.create());
2584 QVERIFY(!o->property("a").isValid());
2586 o->setProperty("aNumber", QVariant(5));
2587 o->setProperty(triggerProperty.toUtf8().constData(), true);
2588 QCOMPARE(o->property("a"), QVariant(50));
2590 o->setProperty("aNumber", QVariant(10));
2591 QCOMPARE(o->property("a"), QVariant(100));
2596 void tst_qdeclarativeecmascript::functionAssignment_fromJS_data()
2598 QTest::addColumn<QString>("triggerProperty");
2600 QTest::newRow("assign to property") << "assignToProperty";
2601 QTest::newRow("assign to property, from JS file") << "assignToPropertyFromJsFile";
2603 QTest::newRow("assign to value type") << "assignToValueType";
2605 QTest::newRow("use 'this'") << "assignWithThis";
2606 QTest::newRow("use 'this' from JS file") << "assignWithThisFromJsFile";
2609 void tst_qdeclarativeecmascript::functionAssignmentfromJS_invalid()
2611 QDeclarativeComponent component(&engine, TEST_FILE("functionAssignment.2.qml"));
2612 QVERIFY2(component.errorString().isEmpty(), qPrintable(component.errorString()));
2614 MyQmlObject *o = qobject_cast<MyQmlObject *>(component.create());
2616 QVERIFY(!o->property("a").isValid());
2618 o->setProperty("assignFuncWithoutReturn", true);
2619 QVERIFY(!o->property("a").isValid());
2621 QString url = component.url().toString();
2622 QString warning = url + ":63: Unable to assign QString to int";
2623 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
2624 o->setProperty("assignWrongType", true);
2626 warning = url + ":70: Unable to assign QString to int";
2627 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
2628 o->setProperty("assignWrongTypeToValueType", true);
2633 void tst_qdeclarativeecmascript::eval()
2635 QDeclarativeComponent component(&engine, TEST_FILE("eval.qml"));
2637 QObject *o = component.create();
2640 QCOMPARE(o->property("test1").toBool(), true);
2641 QCOMPARE(o->property("test2").toBool(), true);
2642 QCOMPARE(o->property("test3").toBool(), true);
2643 QCOMPARE(o->property("test4").toBool(), true);
2644 QCOMPARE(o->property("test5").toBool(), true);
2649 void tst_qdeclarativeecmascript::function()
2651 QDeclarativeComponent component(&engine, TEST_FILE("function.qml"));
2653 QObject *o = component.create();
2656 QCOMPARE(o->property("test1").toBool(), true);
2657 QCOMPARE(o->property("test2").toBool(), true);
2658 QCOMPARE(o->property("test3").toBool(), true);
2663 // Test the "Qt.include" method
2664 void tst_qdeclarativeecmascript::include()
2666 // Non-library relative include
2668 QDeclarativeComponent component(&engine, TEST_FILE("include.qml"));
2669 QObject *o = component.create();
2672 QCOMPARE(o->property("test0").toInt(), 99);
2673 QCOMPARE(o->property("test1").toBool(), true);
2674 QCOMPARE(o->property("test2").toBool(), true);
2675 QCOMPARE(o->property("test2_1").toBool(), true);
2676 QCOMPARE(o->property("test3").toBool(), true);
2677 QCOMPARE(o->property("test3_1").toBool(), true);
2682 // Library relative include
2684 QDeclarativeComponent component(&engine, TEST_FILE("include_shared.qml"));
2685 QObject *o = component.create();
2688 QCOMPARE(o->property("test0").toInt(), 99);
2689 QCOMPARE(o->property("test1").toBool(), true);
2690 QCOMPARE(o->property("test2").toBool(), true);
2691 QCOMPARE(o->property("test2_1").toBool(), true);
2692 QCOMPARE(o->property("test3").toBool(), true);
2693 QCOMPARE(o->property("test3_1").toBool(), true);
2700 QDeclarativeComponent component(&engine, TEST_FILE("include_callback.qml"));
2701 QObject *o = component.create();
2704 QCOMPARE(o->property("test1").toBool(), true);
2705 QCOMPARE(o->property("test2").toBool(), true);
2706 QCOMPARE(o->property("test3").toBool(), true);
2707 QCOMPARE(o->property("test4").toBool(), true);
2708 QCOMPARE(o->property("test5").toBool(), true);
2709 QCOMPARE(o->property("test6").toBool(), true);
2714 // Including file with ".pragma library"
2716 QDeclarativeComponent component(&engine, TEST_FILE("include_pragma.qml"));
2717 QObject *o = component.create();
2719 QCOMPARE(o->property("test1").toInt(), 100);
2726 TestHTTPServer server(8111);
2727 QVERIFY(server.isValid());
2728 server.serveDirectory(SRCDIR "/data");
2730 QDeclarativeComponent component(&engine, TEST_FILE("include_remote.qml"));
2731 QObject *o = component.create();
2734 QTRY_VERIFY(o->property("done").toBool() == true);
2735 QTRY_VERIFY(o->property("done2").toBool() == true);
2737 QCOMPARE(o->property("test1").toBool(), true);
2738 QCOMPARE(o->property("test2").toBool(), true);
2739 QCOMPARE(o->property("test3").toBool(), true);
2740 QCOMPARE(o->property("test4").toBool(), true);
2741 QCOMPARE(o->property("test5").toBool(), true);
2743 QCOMPARE(o->property("test6").toBool(), true);
2744 QCOMPARE(o->property("test7").toBool(), true);
2745 QCOMPARE(o->property("test8").toBool(), true);
2746 QCOMPARE(o->property("test9").toBool(), true);
2747 QCOMPARE(o->property("test10").toBool(), true);
2754 TestHTTPServer server(8111);
2755 QVERIFY(server.isValid());
2756 server.serveDirectory(SRCDIR "/data");
2758 QDeclarativeComponent component(&engine, TEST_FILE("include_remote_missing.qml"));
2759 QObject *o = component.create();
2762 QTRY_VERIFY(o->property("done").toBool() == true);
2764 QCOMPARE(o->property("test1").toBool(), true);
2765 QCOMPARE(o->property("test2").toBool(), true);
2766 QCOMPARE(o->property("test3").toBool(), true);
2772 void tst_qdeclarativeecmascript::qtbug_10696()
2774 QDeclarativeComponent component(&engine, TEST_FILE("qtbug_10696.qml"));
2775 QObject *o = component.create();
2780 void tst_qdeclarativeecmascript::qtbug_11606()
2782 QDeclarativeComponent component(&engine, TEST_FILE("qtbug_11606.qml"));
2783 QObject *o = component.create();
2785 QCOMPARE(o->property("test").toBool(), true);
2789 void tst_qdeclarativeecmascript::qtbug_11600()
2791 QDeclarativeComponent component(&engine, TEST_FILE("qtbug_11600.qml"));
2792 QObject *o = component.create();
2794 QCOMPARE(o->property("test").toBool(), true);
2798 // Reading and writing non-scriptable properties should fail
2799 void tst_qdeclarativeecmascript::nonscriptable()
2801 QDeclarativeComponent component(&engine, TEST_FILE("nonscriptable.qml"));
2802 QObject *o = component.create();
2804 QCOMPARE(o->property("readOk").toBool(), true);
2805 QCOMPARE(o->property("writeOk").toBool(), true);
2809 // deleteLater() should not be callable from QML
2810 void tst_qdeclarativeecmascript::deleteLater()
2812 QDeclarativeComponent component(&engine, TEST_FILE("deleteLater.qml"));
2813 QObject *o = component.create();
2815 QCOMPARE(o->property("test").toBool(), true);
2819 void tst_qdeclarativeecmascript::in()
2821 QDeclarativeComponent component(&engine, TEST_FILE("in.qml"));
2822 QObject *o = component.create();
2824 QCOMPARE(o->property("test1").toBool(), true);
2825 QCOMPARE(o->property("test2").toBool(), true);
2829 void tst_qdeclarativeecmascript::sharedAttachedObject()
2831 QDeclarativeComponent component(&engine, TEST_FILE("sharedAttachedObject.qml"));
2832 QObject *o = component.create();
2834 QCOMPARE(o->property("test1").toBool(), true);
2835 QCOMPARE(o->property("test2").toBool(), true);
2840 void tst_qdeclarativeecmascript::objectName()
2842 QDeclarativeComponent component(&engine, TEST_FILE("objectName.qml"));
2843 QObject *o = component.create();
2846 QCOMPARE(o->property("test1").toString(), QString("hello"));
2847 QCOMPARE(o->property("test2").toString(), QString("ell"));
2849 o->setObjectName("world");
2851 QCOMPARE(o->property("test1").toString(), QString("world"));
2852 QCOMPARE(o->property("test2").toString(), QString("orl"));
2857 void tst_qdeclarativeecmascript::writeRemovesBinding()
2859 QDeclarativeComponent component(&engine, TEST_FILE("writeRemovesBinding.qml"));
2860 QObject *o = component.create();
2863 QCOMPARE(o->property("test").toBool(), true);
2868 // Test bindings assigned to alias properties actually assign to the alias' target
2869 void tst_qdeclarativeecmascript::aliasBindingsAssignCorrectly()
2871 QDeclarativeComponent component(&engine, TEST_FILE("aliasBindingsAssignCorrectly.qml"));
2872 QObject *o = component.create();
2875 QCOMPARE(o->property("test").toBool(), true);
2880 // Test bindings assigned to alias properties override a binding on the target (QTBUG-13719)
2881 void tst_qdeclarativeecmascript::aliasBindingsOverrideTarget()
2884 QDeclarativeComponent component(&engine, TEST_FILE("aliasBindingsOverrideTarget.qml"));
2885 QObject *o = component.create();
2888 QCOMPARE(o->property("test").toBool(), true);
2894 QDeclarativeComponent component(&engine, TEST_FILE("aliasBindingsOverrideTarget.2.qml"));
2895 QObject *o = component.create();
2898 QCOMPARE(o->property("test").toBool(), true);
2904 QDeclarativeComponent component(&engine, TEST_FILE("aliasBindingsOverrideTarget.3.qml"));
2905 QObject *o = component.create();
2908 QCOMPARE(o->property("test").toBool(), true);
2914 // Test that writes to alias properties override bindings on the alias target (QTBUG-13719)
2915 void tst_qdeclarativeecmascript::aliasWritesOverrideBindings()
2918 QDeclarativeComponent component(&engine, TEST_FILE("aliasWritesOverrideBindings.qml"));
2919 QObject *o = component.create();
2922 QCOMPARE(o->property("test").toBool(), true);
2928 QDeclarativeComponent component(&engine, TEST_FILE("aliasWritesOverrideBindings.2.qml"));
2929 QObject *o = component.create();
2932 QCOMPARE(o->property("test").toBool(), true);
2938 QDeclarativeComponent component(&engine, TEST_FILE("aliasWritesOverrideBindings.3.qml"));
2939 QObject *o = component.create();
2942 QCOMPARE(o->property("test").toBool(), true);
2948 void tst_qdeclarativeecmascript::revisionErrors()
2951 QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevisionErrors.qml"));
2952 QString url = component.url().toString();
2954 QString warning1 = url + ":8: ReferenceError: Can't find variable: prop2";
2955 QString warning2 = url + ":11: ReferenceError: Can't find variable: prop2";
2956 QString warning3 = url + ":13: ReferenceError: Can't find variable: method2";
2958 QTest::ignoreMessage(QtWarningMsg, warning1.toLatin1().constData());
2959 QTest::ignoreMessage(QtWarningMsg, warning2.toLatin1().constData());
2960 QTest::ignoreMessage(QtWarningMsg, warning3.toLatin1().constData());
2961 MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create());
2962 QVERIFY(object != 0);
2965 QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevisionErrors2.qml"));
2966 QString url = component.url().toString();
2968 // MyRevisionedSubclass 1.0 uses MyRevisionedClass revision 0
2969 // method2, prop2 from MyRevisionedClass not available
2970 // method4, prop4 from MyRevisionedSubclass not available
2971 QString warning1 = url + ":8: ReferenceError: Can't find variable: prop2";
2972 QString warning2 = url + ":14: ReferenceError: Can't find variable: prop2";
2973 QString warning3 = url + ":10: ReferenceError: Can't find variable: prop4";
2974 QString warning4 = url + ":16: ReferenceError: Can't find variable: prop4";
2975 QString warning5 = url + ":20: ReferenceError: Can't find variable: method2";
2977 QTest::ignoreMessage(QtWarningMsg, warning1.toLatin1().constData());
2978 QTest::ignoreMessage(QtWarningMsg, warning2.toLatin1().constData());
2979 QTest::ignoreMessage(QtWarningMsg, warning3.toLatin1().constData());
2980 QTest::ignoreMessage(QtWarningMsg, warning4.toLatin1().constData());
2981 QTest::ignoreMessage(QtWarningMsg, warning5.toLatin1().constData());
2982 MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create());
2983 QVERIFY(object != 0);
2986 QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevisionErrors3.qml"));
2987 QString url = component.url().toString();
2989 // MyRevisionedSubclass 1.1 uses MyRevisionedClass revision 1
2990 // All properties/methods available, except MyRevisionedBaseClassUnregistered rev 1
2991 QString warning1 = url + ":30: ReferenceError: Can't find variable: methodD";
2992 QString warning2 = url + ":10: ReferenceError: Can't find variable: propD";
2993 QString warning3 = url + ":20: ReferenceError: Can't find variable: propD";
2994 QTest::ignoreMessage(QtWarningMsg, warning1.toLatin1().constData());
2995 QTest::ignoreMessage(QtWarningMsg, warning2.toLatin1().constData());
2996 QTest::ignoreMessage(QtWarningMsg, warning3.toLatin1().constData());
2997 MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create());
2998 QVERIFY(object != 0);
3002 void tst_qdeclarativeecmascript::revision()
3005 QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevision.qml"));
3006 QString url = component.url().toString();
3008 MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create());
3009 QVERIFY(object != 0);
3012 QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevision2.qml"));
3013 QString url = component.url().toString();
3015 MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create());
3016 QVERIFY(object != 0);
3019 QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevision3.qml"));
3020 QString url = component.url().toString();
3022 MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create());
3023 QVERIFY(object != 0);
3025 // Test that non-root classes can resolve revisioned methods
3027 QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevision4.qml"));
3029 QObject *object = component.create();
3030 QVERIFY(object != 0);
3031 QCOMPARE(object->property("test").toReal(), 11.);
3036 // Test for QScriptDeclarativeClass::pushCleanContext()
3037 void tst_qdeclarativeecmascript::pushCleanContext()
3039 QScriptEngine engine;
3040 engine.globalObject().setProperty("a", 6);
3041 QCOMPARE(engine.evaluate("a").toInt32(), 6);
3043 // First confirm pushContext() behaves as we expect
3044 QScriptValue object = engine.newObject();
3045 object.setProperty("a", 15);
3046 QScriptContext *context1 = engine.pushContext();
3047 context1->pushScope(object);
3048 QCOMPARE(engine.evaluate("a").toInt32(), 15);
3050 QScriptContext *context2 = engine.pushContext();
3052 QCOMPARE(engine.evaluate("a").toInt32(), 15);
3053 QScriptValue func1 = engine.evaluate("(function() { return a; })");
3055 // Now check that pushCleanContext() works
3056 QScriptDeclarativeClass::pushCleanContext(&engine);
3057 QCOMPARE(engine.evaluate("a").toInt32(), 6);
3058 QScriptValue func2 = engine.evaluate("(function() { return a; })");
3060 engine.popContext();
3061 QCOMPARE(engine.evaluate("a").toInt32(), 15);
3063 engine.popContext();
3064 QCOMPARE(engine.evaluate("a").toInt32(), 15);
3066 engine.popContext();
3067 QCOMPARE(engine.evaluate("a").toInt32(), 6);
3069 // Check that function objects created in these contexts work
3070 QCOMPARE(func1.call().toInt32(), 15);
3071 QCOMPARE(func2.call().toInt32(), 6);
3074 QTEST_MAIN(tst_qdeclarativeecmascript)
3076 #include "tst_qdeclarativeecmascript.moc"