1 /****************************************************************************
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
7 ** This file is part of the test suite of the Qt Toolkit.
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** GNU Lesser General Public License Usage
11 ** This file may be used under the terms of the GNU Lesser General Public
12 ** License version 2.1 as published by the Free Software Foundation and
13 ** appearing in the file LICENSE.LGPL included in the packaging of this
14 ** file. Please review the following information to ensure the GNU Lesser
15 ** General Public License version 2.1 requirements will be met:
16 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
18 ** In addition, as a special exception, Nokia gives you certain additional
19 ** rights. These rights are described in the Nokia Qt LGPL Exception
20 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
22 ** GNU General Public License Usage
23 ** Alternatively, this file may be used under the terms of the GNU General
24 ** Public License version 3.0 as published by the Free Software Foundation
25 ** and appearing in the file LICENSE.GPL included in the packaging of this
26 ** file. Please review the following information to ensure the GNU General
27 ** Public License version 3.0 requirements will be met:
28 ** http://www.gnu.org/copyleft/gpl.html.
31 ** Alternatively, this file may be used in accordance with the terms and
32 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
42 #include <QtDeclarative/qdeclarativecomponent.h>
43 #include <QtDeclarative/qdeclarativeengine.h>
44 #include <QtDeclarative/qdeclarativeexpression.h>
45 #include <QtDeclarative/qdeclarativecontext.h>
46 #include <QtCore/qfileinfo.h>
47 #include <QtCore/qdebug.h>
48 #include <QtDeclarative/private/qdeclarativeguard_p.h>
49 #include <QtCore/qdir.h>
50 #include <QtCore/qnumeric.h>
51 #include <private/qdeclarativeengine_p.h>
52 #include <private/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("attachedProperty.2.qml"));
654 QObject *object = component.create();
655 QVERIFY(object != 0);
656 QCOMPARE(object->property("a").toInt(), 26);
657 QCOMPARE(object->property("b").toInt(), 26);
658 QCOMPARE(object->property("c").toInt(), 26);
659 QCOMPARE(object->property("d").toInt(), 26);
663 QDeclarativeComponent component(&engine, TEST_FILE("writeAttachedProperty.qml"));
664 QObject *object = component.create();
665 QVERIFY(object != 0);
667 QMetaObject::invokeMethod(object, "writeValue2");
669 MyQmlAttachedObject *attached =
670 qobject_cast<MyQmlAttachedObject *>(qmlAttachedPropertiesObject<MyQmlObject>(object));
671 QVERIFY(attached != 0);
673 QCOMPARE(attached->value2(), 9);
677 void tst_qdeclarativeecmascript::enums()
681 QDeclarativeComponent component(&engine, TEST_FILE("enums.1.qml"));
682 QObject *object = component.create();
683 QVERIFY(object != 0);
685 QCOMPARE(object->property("a").toInt(), 0);
686 QCOMPARE(object->property("b").toInt(), 1);
687 QCOMPARE(object->property("c").toInt(), 2);
688 QCOMPARE(object->property("d").toInt(), 3);
689 QCOMPARE(object->property("e").toInt(), 0);
690 QCOMPARE(object->property("f").toInt(), 1);
691 QCOMPARE(object->property("g").toInt(), 2);
692 QCOMPARE(object->property("h").toInt(), 3);
693 QCOMPARE(object->property("i").toInt(), 19);
694 QCOMPARE(object->property("j").toInt(), 19);
696 // Non-existent enums
698 QDeclarativeComponent component(&engine, TEST_FILE("enums.2.qml"));
700 QString warning1 = component.url().toString() + ":5: Unable to assign [undefined] to int a";
701 QString warning2 = component.url().toString() + ":6: Unable to assign [undefined] to int b";
702 QTest::ignoreMessage(QtWarningMsg, qPrintable(warning1));
703 QTest::ignoreMessage(QtWarningMsg, qPrintable(warning2));
705 QObject *object = component.create();
706 QVERIFY(object != 0);
707 QCOMPARE(object->property("a").toInt(), 0);
708 QCOMPARE(object->property("b").toInt(), 0);
712 void tst_qdeclarativeecmascript::valueTypeFunctions()
714 QDeclarativeComponent component(&engine, TEST_FILE("valueTypeFunctions.qml"));
715 MyTypeObject *obj = qobject_cast<MyTypeObject*>(component.create());
717 QCOMPARE(obj->rectProperty(), QRect(0,0,100,100));
718 QCOMPARE(obj->rectFProperty(), QRectF(0,0.5,100,99.5));
722 Tests that writing a constant to a property with a binding on it disables the
725 void tst_qdeclarativeecmascript::constantsOverrideBindings()
729 QDeclarativeComponent component(&engine, TEST_FILE("constantsOverrideBindings.1.qml"));
730 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
731 QVERIFY(object != 0);
733 QCOMPARE(object->property("c2").toInt(), 0);
734 object->setProperty("c1", QVariant(9));
735 QCOMPARE(object->property("c2").toInt(), 9);
737 emit object->basicSignal();
739 QCOMPARE(object->property("c2").toInt(), 13);
740 object->setProperty("c1", QVariant(8));
741 QCOMPARE(object->property("c2").toInt(), 13);
744 // During construction
746 QDeclarativeComponent component(&engine, TEST_FILE("constantsOverrideBindings.2.qml"));
747 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
748 QVERIFY(object != 0);
750 QCOMPARE(object->property("c1").toInt(), 0);
751 QCOMPARE(object->property("c2").toInt(), 10);
752 object->setProperty("c1", QVariant(9));
753 QCOMPARE(object->property("c1").toInt(), 9);
754 QCOMPARE(object->property("c2").toInt(), 10);
760 QDeclarativeComponent component(&engine, TEST_FILE("constantsOverrideBindings.3.qml"));
761 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
762 QVERIFY(object != 0);
764 QCOMPARE(object->property("c2").toInt(), 0);
765 object->setProperty("c1", QVariant(9));
766 QCOMPARE(object->property("c2").toInt(), 9);
768 object->setProperty("c2", QVariant(13));
769 QCOMPARE(object->property("c2").toInt(), 13);
770 object->setProperty("c1", QVariant(7));
771 QCOMPARE(object->property("c1").toInt(), 7);
772 QCOMPARE(object->property("c2").toInt(), 13);
778 QDeclarativeComponent component(&engine, TEST_FILE("constantsOverrideBindings.4.qml"));
779 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
780 QVERIFY(object != 0);
782 QCOMPARE(object->property("c1").toInt(), 0);
783 QCOMPARE(object->property("c3").toInt(), 10);
784 object->setProperty("c1", QVariant(9));
785 QCOMPARE(object->property("c1").toInt(), 9);
786 QCOMPARE(object->property("c3").toInt(), 10);
791 Tests that assigning a binding to a property that already has a binding causes
792 the original binding to be disabled.
794 void tst_qdeclarativeecmascript::outerBindingOverridesInnerBinding()
796 QDeclarativeComponent component(&engine,
797 TEST_FILE("outerBindingOverridesInnerBinding.qml"));
798 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
799 QVERIFY(object != 0);
801 QCOMPARE(object->property("c1").toInt(), 0);
802 QCOMPARE(object->property("c2").toInt(), 0);
803 QCOMPARE(object->property("c3").toInt(), 0);
805 object->setProperty("c1", QVariant(9));
806 QCOMPARE(object->property("c1").toInt(), 9);
807 QCOMPARE(object->property("c2").toInt(), 0);
808 QCOMPARE(object->property("c3").toInt(), 0);
810 object->setProperty("c3", QVariant(8));
811 QCOMPARE(object->property("c1").toInt(), 9);
812 QCOMPARE(object->property("c2").toInt(), 8);
813 QCOMPARE(object->property("c3").toInt(), 8);
817 Access a non-existent attached object.
819 Tests for a regression where this used to crash.
821 void tst_qdeclarativeecmascript::nonExistentAttachedObject()
823 QDeclarativeComponent component(&engine, TEST_FILE("nonExistentAttachedObject.qml"));
825 QString warning = component.url().toString() + ":4: Unable to assign [undefined] to QString stringProperty";
826 QTest::ignoreMessage(QtWarningMsg, qPrintable(warning));
828 QObject *object = component.create();
829 QVERIFY(object != 0);
832 void tst_qdeclarativeecmascript::scope()
835 QDeclarativeComponent component(&engine, TEST_FILE("scope.qml"));
836 QObject *object = component.create();
837 QVERIFY(object != 0);
839 QCOMPARE(object->property("test1").toInt(), 1);
840 QCOMPARE(object->property("test2").toInt(), 2);
841 QCOMPARE(object->property("test3").toString(), QString("1Test"));
842 QCOMPARE(object->property("test4").toString(), QString("2Test"));
843 QCOMPARE(object->property("test5").toInt(), 1);
844 QCOMPARE(object->property("test6").toInt(), 1);
845 QCOMPARE(object->property("test7").toInt(), 2);
846 QCOMPARE(object->property("test8").toInt(), 2);
847 QCOMPARE(object->property("test9").toInt(), 1);
848 QCOMPARE(object->property("test10").toInt(), 3);
852 QDeclarativeComponent component(&engine, TEST_FILE("scope.2.qml"));
853 QObject *object = component.create();
854 QVERIFY(object != 0);
856 QCOMPARE(object->property("test1").toInt(), 19);
857 QCOMPARE(object->property("test2").toInt(), 19);
858 QCOMPARE(object->property("test3").toInt(), 14);
859 QCOMPARE(object->property("test4").toInt(), 14);
860 QCOMPARE(object->property("test5").toInt(), 24);
861 QCOMPARE(object->property("test6").toInt(), 24);
865 QDeclarativeComponent component(&engine, TEST_FILE("scope.3.qml"));
866 QObject *object = component.create();
867 QVERIFY(object != 0);
869 QCOMPARE(object->property("test1").toBool(), true);
870 QCOMPARE(object->property("test2").toBool(), true);
871 QCOMPARE(object->property("test3").toBool(), true);
874 // Signal argument scope
876 QDeclarativeComponent component(&engine, TEST_FILE("scope.4.qml"));
877 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
878 QVERIFY(object != 0);
880 QCOMPARE(object->property("test").toInt(), 0);
881 QCOMPARE(object->property("test2").toString(), QString());
883 emit object->argumentSignal(13, "Argument Scope", 9, MyQmlObject::EnumValue4, Qt::RightButton);
885 QCOMPARE(object->property("test").toInt(), 13);
886 QCOMPARE(object->property("test2").toString(), QString("Argument Scope"));
893 Tests that "any" type passes through a synthesized signal parameter. This
894 is essentially a test of QDeclarativeMetaType::copy()
896 void tst_qdeclarativeecmascript::signalParameterTypes()
898 QDeclarativeComponent component(&engine, TEST_FILE("signalParameterTypes.qml"));
899 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
900 QVERIFY(object != 0);
902 emit object->basicSignal();
904 QCOMPARE(object->property("intProperty").toInt(), 10);
905 QCOMPARE(object->property("realProperty").toReal(), 19.2);
906 QVERIFY(object->property("colorProperty").value<QColor>() == QColor(255, 255, 0, 255));
907 QVERIFY(object->property("variantProperty") == QVariant::fromValue(QColor(255, 0, 255, 255)));
908 QVERIFY(object->property("enumProperty") == MyQmlObject::EnumValue3);
909 QVERIFY(object->property("qtEnumProperty") == Qt::LeftButton);
913 Test that two JS objects for the same QObject compare as equal.
915 void tst_qdeclarativeecmascript::objectsCompareAsEqual()
917 QDeclarativeComponent component(&engine, TEST_FILE("objectsCompareAsEqual.qml"));
918 QObject *object = component.create();
919 QVERIFY(object != 0);
921 QCOMPARE(object->property("test1").toBool(), true);
922 QCOMPARE(object->property("test2").toBool(), true);
923 QCOMPARE(object->property("test3").toBool(), true);
924 QCOMPARE(object->property("test4").toBool(), true);
925 QCOMPARE(object->property("test5").toBool(), true);
929 Confirm bindings and alias properties can coexist.
931 Tests for a regression where the binding would not reevaluate.
933 void tst_qdeclarativeecmascript::aliasPropertyAndBinding()
935 QDeclarativeComponent component(&engine, TEST_FILE("aliasPropertyAndBinding.qml"));
936 QObject *object = component.create();
937 QVERIFY(object != 0);
939 QCOMPARE(object->property("c2").toInt(), 3);
940 QCOMPARE(object->property("c3").toInt(), 3);
942 object->setProperty("c2", QVariant(19));
944 QCOMPARE(object->property("c2").toInt(), 19);
945 QCOMPARE(object->property("c3").toInt(), 19);
948 void tst_qdeclarativeecmascript::dynamicCreation_data()
950 QTest::addColumn<QString>("method");
951 QTest::addColumn<QString>("createdName");
953 QTest::newRow("One") << "createOne" << "objectOne";
954 QTest::newRow("Two") << "createTwo" << "objectTwo";
955 QTest::newRow("Three") << "createThree" << "objectThree";
959 Test using createQmlObject to dynamically generate an item
960 Also using createComponent is tested.
962 void tst_qdeclarativeecmascript::dynamicCreation()
964 QFETCH(QString, method);
965 QFETCH(QString, createdName);
967 QDeclarativeComponent component(&engine, TEST_FILE("dynamicCreation.qml"));
968 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
969 QVERIFY(object != 0);
971 QMetaObject::invokeMethod(object, method.toUtf8());
972 QObject *created = object->objectProperty();
974 QCOMPARE(created->objectName(), createdName);
978 Tests the destroy function
980 void tst_qdeclarativeecmascript::dynamicDestruction()
982 QDeclarativeComponent component(&engine, TEST_FILE("dynamicDeletion.qml"));
983 QDeclarativeGuard<MyQmlObject> object = qobject_cast<MyQmlObject*>(component.create());
984 QVERIFY(object != 0);
985 QDeclarativeGuard<QObject> createdQmlObject = 0;
987 QMetaObject::invokeMethod(object, "create");
988 createdQmlObject = object->objectProperty();
989 QVERIFY(createdQmlObject);
990 QCOMPARE(createdQmlObject->objectName(), QString("emptyObject"));
992 QMetaObject::invokeMethod(object, "killOther");
993 QVERIFY(createdQmlObject);
994 QCoreApplication::instance()->processEvents(QEventLoop::DeferredDeletion);
995 QVERIFY(createdQmlObject);
996 for (int ii = 0; createdQmlObject && ii < 50; ++ii) { // After 5 seconds we should give up
997 if (createdQmlObject) {
999 QCoreApplication::instance()->processEvents(QEventLoop::DeferredDeletion);
1002 QVERIFY(!createdQmlObject);
1004 QDeclarativeEngine::setObjectOwnership(object, QDeclarativeEngine::JavaScriptOwnership);
1005 QMetaObject::invokeMethod(object, "killMe");
1008 QCoreApplication::instance()->processEvents(QEventLoop::DeferredDeletion);
1013 tests that id.toString() works
1015 void tst_qdeclarativeecmascript::objectToString()
1017 QDeclarativeComponent component(&engine, TEST_FILE("declarativeToString.qml"));
1018 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1019 QVERIFY(object != 0);
1020 QMetaObject::invokeMethod(object, "testToString");
1021 QVERIFY(object->stringProperty().startsWith("MyQmlObject_QML_"));
1022 QVERIFY(object->stringProperty().endsWith(", \"objName\")"));
1026 Tests bindings that indirectly cause their own deletion work.
1028 This test is best run under valgrind to ensure no invalid memory access occur.
1030 void tst_qdeclarativeecmascript::selfDeletingBinding()
1033 QDeclarativeComponent component(&engine, TEST_FILE("selfDeletingBinding.qml"));
1034 QObject *object = component.create();
1035 QVERIFY(object != 0);
1036 object->setProperty("triggerDelete", true);
1040 QDeclarativeComponent component(&engine, TEST_FILE("selfDeletingBinding.2.qml"));
1041 QObject *object = component.create();
1042 QVERIFY(object != 0);
1043 object->setProperty("triggerDelete", true);
1048 Test that extended object properties can be accessed.
1050 This test a regression where this used to crash. The issue was specificially
1051 for extended objects that did not include a synthesized meta object (so non-root
1052 and no synthesiszed properties).
1054 void tst_qdeclarativeecmascript::extendedObjectPropertyLookup()
1056 QDeclarativeComponent component(&engine, TEST_FILE("extendedObjectPropertyLookup.qml"));
1057 QObject *object = component.create();
1058 QVERIFY(object != 0);
1062 Test file/lineNumbers for binding/Script errors.
1064 void tst_qdeclarativeecmascript::scriptErrors()
1066 QDeclarativeComponent component(&engine, TEST_FILE("scriptErrors.qml"));
1067 QString url = component.url().toString();
1069 QString warning1 = url.left(url.length() - 3) + "js:2: Error: Invalid write to global property \"a\"";
1070 QString warning2 = url + ":5: ReferenceError: Can't find variable: a";
1071 QString warning3 = url.left(url.length() - 3) + "js:4: Error: Invalid write to global property \"a\"";
1072 QString warning4 = url + ":10: ReferenceError: Can't find variable: a";
1073 QString warning5 = url + ":8: ReferenceError: Can't find variable: a";
1074 QString warning6 = url + ":7: Unable to assign [undefined] to int x";
1075 QString warning7 = url + ":12: Error: Cannot assign to read-only property \"trueProperty\"";
1076 QString warning8 = url + ":13: Error: Cannot assign to non-existent property \"fakeProperty\"";
1078 QTest::ignoreMessage(QtWarningMsg, warning1.toLatin1().constData());
1079 QTest::ignoreMessage(QtWarningMsg, warning2.toLatin1().constData());
1080 QTest::ignoreMessage(QtWarningMsg, warning3.toLatin1().constData());
1081 QTest::ignoreMessage(QtWarningMsg, warning5.toLatin1().constData());
1082 QTest::ignoreMessage(QtWarningMsg, warning6.toLatin1().constData());
1083 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
1084 QVERIFY(object != 0);
1086 QTest::ignoreMessage(QtWarningMsg, warning4.toLatin1().constData());
1087 emit object->basicSignal();
1089 QTest::ignoreMessage(QtWarningMsg, warning7.toLatin1().constData());
1090 emit object->anotherBasicSignal();
1092 QTest::ignoreMessage(QtWarningMsg, warning8.toLatin1().constData());
1093 emit object->thirdBasicSignal();
1097 Test file/lineNumbers for inline functions.
1099 void tst_qdeclarativeecmascript::functionErrors()
1101 QDeclarativeComponent component(&engine, TEST_FILE("functionErrors.qml"));
1102 QString url = component.url().toString();
1104 QString warning = url + ":5: Error: Invalid write to global property \"a\"";
1106 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
1108 QObject *object = component.create();
1109 QVERIFY(object != 0);
1114 Test various errors that can occur when assigning a property from script
1116 void tst_qdeclarativeecmascript::propertyAssignmentErrors()
1118 QDeclarativeComponent component(&engine, TEST_FILE("propertyAssignmentErrors.qml"));
1120 QString url = component.url().toString();
1122 QString warning1 = url + ":11:Error: Cannot assign [undefined] to int";
1123 QString warning2 = url + ":17:Error: Cannot assign QString to int";
1125 QTest::ignoreMessage(QtDebugMsg, warning1.toLatin1().constData());
1126 QTest::ignoreMessage(QtDebugMsg, warning2.toLatin1().constData());
1128 QObject *object = component.create();
1129 QVERIFY(object != 0);
1135 Test bindings still work when the reeval is triggered from within
1138 void tst_qdeclarativeecmascript::signalTriggeredBindings()
1140 QDeclarativeComponent component(&engine, TEST_FILE("signalTriggeredBindings.qml"));
1141 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1142 QVERIFY(object != 0);
1144 QCOMPARE(object->property("base").toReal(), 50.);
1145 QCOMPARE(object->property("test1").toReal(), 50.);
1146 QCOMPARE(object->property("test2").toReal(), 50.);
1148 object->basicSignal();
1150 QCOMPARE(object->property("base").toReal(), 200.);
1151 QCOMPARE(object->property("test1").toReal(), 200.);
1152 QCOMPARE(object->property("test2").toReal(), 200.);
1154 object->argumentSignal(10, QString(), 10, MyQmlObject::EnumValue4, Qt::RightButton);
1156 QCOMPARE(object->property("base").toReal(), 400.);
1157 QCOMPARE(object->property("test1").toReal(), 400.);
1158 QCOMPARE(object->property("test2").toReal(), 400.);
1162 Test that list properties can be iterated from ECMAScript
1164 void tst_qdeclarativeecmascript::listProperties()
1166 QDeclarativeComponent component(&engine, TEST_FILE("listProperties.qml"));
1167 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1168 QVERIFY(object != 0);
1170 QCOMPARE(object->property("test1").toInt(), 21);
1171 QCOMPARE(object->property("test2").toInt(), 2);
1172 QCOMPARE(object->property("test3").toBool(), true);
1173 QCOMPARE(object->property("test4").toBool(), true);
1176 void tst_qdeclarativeecmascript::exceptionClearsOnReeval()
1178 QDeclarativeComponent component(&engine, TEST_FILE("exceptionClearsOnReeval.qml"));
1179 QString url = component.url().toString();
1181 QString warning = url + ":4: TypeError: Result of expression 'objectProperty' [null] is not an object.";
1183 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
1184 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1185 QVERIFY(object != 0);
1187 QCOMPARE(object->property("test").toBool(), false);
1189 MyQmlObject object2;
1190 MyQmlObject object3;
1191 object2.setObjectProperty(&object3);
1192 object->setObjectProperty(&object2);
1194 QCOMPARE(object->property("test").toBool(), true);
1197 void tst_qdeclarativeecmascript::exceptionSlotProducesWarning()
1199 QDeclarativeComponent component(&engine, TEST_FILE("exceptionProducesWarning.qml"));
1200 QString url = component.url().toString();
1202 QString warning = component.url().toString() + ":6: Error: JS exception";
1204 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
1205 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1206 QVERIFY(object != 0);
1209 void tst_qdeclarativeecmascript::exceptionBindingProducesWarning()
1211 QDeclarativeComponent component(&engine, TEST_FILE("exceptionProducesWarning2.qml"));
1212 QString url = component.url().toString();
1214 QString warning = component.url().toString() + ":5: Error: JS exception";
1216 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
1217 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1218 QVERIFY(object != 0);
1221 static int transientErrorsMsgCount = 0;
1222 static void transientErrorsMsgHandler(QtMsgType, const char *)
1224 ++transientErrorsMsgCount;
1227 // Check that transient binding errors are not displayed
1228 void tst_qdeclarativeecmascript::transientErrors()
1231 QDeclarativeComponent component(&engine, TEST_FILE("transientErrors.qml"));
1233 transientErrorsMsgCount = 0;
1234 QtMsgHandler old = qInstallMsgHandler(transientErrorsMsgHandler);
1236 QObject *object = component.create();
1237 QVERIFY(object != 0);
1239 qInstallMsgHandler(old);
1241 QCOMPARE(transientErrorsMsgCount, 0);
1244 // One binding erroring multiple times, but then resolving
1246 QDeclarativeComponent component(&engine, TEST_FILE("transientErrors.2.qml"));
1248 transientErrorsMsgCount = 0;
1249 QtMsgHandler old = qInstallMsgHandler(transientErrorsMsgHandler);
1251 QObject *object = component.create();
1252 QVERIFY(object != 0);
1254 qInstallMsgHandler(old);
1256 QCOMPARE(transientErrorsMsgCount, 0);
1260 // Check that errors during shutdown are minimized
1261 void tst_qdeclarativeecmascript::shutdownErrors()
1263 QDeclarativeComponent component(&engine, TEST_FILE("shutdownErrors.qml"));
1264 QObject *object = component.create();
1265 QVERIFY(object != 0);
1267 transientErrorsMsgCount = 0;
1268 QtMsgHandler old = qInstallMsgHandler(transientErrorsMsgHandler);
1272 qInstallMsgHandler(old);
1273 QCOMPARE(transientErrorsMsgCount, 0);
1276 void tst_qdeclarativeecmascript::compositePropertyType()
1278 QDeclarativeComponent component(&engine, TEST_FILE("compositePropertyType.qml"));
1279 QTest::ignoreMessage(QtDebugMsg, "hello world");
1280 QObject *object = qobject_cast<QObject *>(component.create());
1285 void tst_qdeclarativeecmascript::jsObject()
1287 QDeclarativeComponent component(&engine, TEST_FILE("jsObject.qml"));
1288 QObject *object = component.create();
1289 QVERIFY(object != 0);
1291 QCOMPARE(object->property("test").toInt(), 92);
1296 void tst_qdeclarativeecmascript::undefinedResetsProperty()
1299 QDeclarativeComponent component(&engine, TEST_FILE("undefinedResetsProperty.qml"));
1300 QObject *object = component.create();
1301 QVERIFY(object != 0);
1303 QCOMPARE(object->property("resettableProperty").toInt(), 92);
1305 object->setProperty("setUndefined", true);
1307 QCOMPARE(object->property("resettableProperty").toInt(), 13);
1309 object->setProperty("setUndefined", false);
1311 QCOMPARE(object->property("resettableProperty").toInt(), 92);
1316 QDeclarativeComponent component(&engine, TEST_FILE("undefinedResetsProperty.2.qml"));
1317 QObject *object = component.create();
1318 QVERIFY(object != 0);
1320 QCOMPARE(object->property("resettableProperty").toInt(), 19);
1322 QMetaObject::invokeMethod(object, "doReset");
1324 QCOMPARE(object->property("resettableProperty").toInt(), 13);
1331 void tst_qdeclarativeecmascript::bug1()
1333 QDeclarativeComponent component(&engine, TEST_FILE("bug.1.qml"));
1334 QObject *object = component.create();
1335 QVERIFY(object != 0);
1337 QCOMPARE(object->property("test").toInt(), 14);
1339 object->setProperty("a", 11);
1341 QCOMPARE(object->property("test").toInt(), 3);
1343 object->setProperty("b", true);
1345 QCOMPARE(object->property("test").toInt(), 9);
1350 void tst_qdeclarativeecmascript::bug2()
1352 QDeclarativeComponent component(&engine);
1353 component.setData("import Qt.test 1.0;\nQPlainTextEdit { width: 100 }", QUrl());
1355 QObject *object = component.create();
1356 QVERIFY(object != 0);
1361 // Don't crash in createObject when the component has errors.
1362 void tst_qdeclarativeecmascript::dynamicCreationCrash()
1364 QDeclarativeComponent component(&engine, TEST_FILE("dynamicCreation.qml"));
1365 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1366 QVERIFY(object != 0);
1368 QTest::ignoreMessage(QtWarningMsg, "QDeclarativeComponent: Component is not ready");
1369 QMetaObject::invokeMethod(object, "dontCrash");
1370 QObject *created = object->objectProperty();
1371 QVERIFY(created == 0);
1375 void tst_qdeclarativeecmascript::regExpBug()
1377 QDeclarativeComponent component(&engine, TEST_FILE("regExp.qml"));
1378 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1379 QVERIFY(object != 0);
1380 QCOMPARE(object->regExp().pattern(), QLatin1String("[a-zA-z]"));
1383 void tst_qdeclarativeecmascript::callQtInvokables()
1385 MyInvokableObject o;
1387 QDeclarativeEngine qmlengine;
1388 QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(&qmlengine);
1389 QScriptEngine *engine = &ep->scriptEngine;
1391 QStringList names; QList<QScriptValue> values;
1392 names << QLatin1String("object"); values << ep->objectClass->newQObject(&o);
1393 names << QLatin1String("undefined"); values << engine->undefinedValue();
1395 ep->globalClass->explicitSetProperty(names, values);
1397 // Non-existent methods
1399 QCOMPARE(engine->evaluate("object.method_nonexistent()").isError(), true);
1400 QCOMPARE(o.error(), false);
1401 QCOMPARE(o.invoked(), -1);
1402 QCOMPARE(o.actuals().count(), 0);
1405 QCOMPARE(engine->evaluate("object.method_nonexistent(10, 11)").isError(), true);
1406 QCOMPARE(o.error(), false);
1407 QCOMPARE(o.invoked(), -1);
1408 QCOMPARE(o.actuals().count(), 0);
1410 // Insufficient arguments
1412 QCOMPARE(engine->evaluate("object.method_int()").isError(), true);
1413 QCOMPARE(o.error(), false);
1414 QCOMPARE(o.invoked(), -1);
1415 QCOMPARE(o.actuals().count(), 0);
1418 QCOMPARE(engine->evaluate("object.method_intint(10)").isError(), true);
1419 QCOMPARE(o.error(), false);
1420 QCOMPARE(o.invoked(), -1);
1421 QCOMPARE(o.actuals().count(), 0);
1423 // Excessive arguments
1425 QCOMPARE(engine->evaluate("object.method_int(10, 11)").isUndefined(), true);
1426 QCOMPARE(o.error(), false);
1427 QCOMPARE(o.invoked(), 8);
1428 QCOMPARE(o.actuals().count(), 1);
1429 QCOMPARE(o.actuals().at(0), QVariant(10));
1432 QCOMPARE(engine->evaluate("object.method_intint(10, 11, 12)").isUndefined(), true);
1433 QCOMPARE(o.error(), false);
1434 QCOMPARE(o.invoked(), 9);
1435 QCOMPARE(o.actuals().count(), 2);
1436 QCOMPARE(o.actuals().at(0), QVariant(10));
1437 QCOMPARE(o.actuals().at(1), QVariant(11));
1439 // Test return types
1441 QCOMPARE(engine->evaluate("object.method_NoArgs()").isUndefined(), true);
1442 QCOMPARE(o.error(), false);
1443 QCOMPARE(o.invoked(), 0);
1444 QCOMPARE(o.actuals().count(), 0);
1447 QVERIFY(engine->evaluate("object.method_NoArgs_int()").strictlyEquals(QScriptValue(engine, 6)));
1448 QCOMPARE(o.error(), false);
1449 QCOMPARE(o.invoked(), 1);
1450 QCOMPARE(o.actuals().count(), 0);
1453 QVERIFY(engine->evaluate("object.method_NoArgs_real()").strictlyEquals(QScriptValue(engine, 19.75)));
1454 QCOMPARE(o.error(), false);
1455 QCOMPARE(o.invoked(), 2);
1456 QCOMPARE(o.actuals().count(), 0);
1460 QScriptValue ret = engine->evaluate("object.method_NoArgs_QPointF()");
1461 QCOMPARE(ret.toVariant(), QVariant(QPointF(123, 4.5)));
1462 QCOMPARE(o.error(), false);
1463 QCOMPARE(o.invoked(), 3);
1464 QCOMPARE(o.actuals().count(), 0);
1469 QScriptValue ret = engine->evaluate("object.method_NoArgs_QObject()");
1470 QVERIFY(ret.isQObject());
1471 QCOMPARE(ret.toQObject(), (QObject *)&o);
1472 QCOMPARE(o.error(), false);
1473 QCOMPARE(o.invoked(), 4);
1474 QCOMPARE(o.actuals().count(), 0);
1478 QCOMPARE(engine->evaluate("object.method_NoArgs_unknown()").isUndefined(), true);
1479 QCOMPARE(o.error(), false);
1480 QCOMPARE(o.invoked(), 5);
1481 QCOMPARE(o.actuals().count(), 0);
1485 QScriptValue ret = engine->evaluate("object.method_NoArgs_QScriptValue()");
1486 QVERIFY(ret.isString());
1487 QCOMPARE(ret.toString(), QString("Hello world"));
1488 QCOMPARE(o.error(), false);
1489 QCOMPARE(o.invoked(), 6);
1490 QCOMPARE(o.actuals().count(), 0);
1494 QVERIFY(engine->evaluate("object.method_NoArgs_QVariant()").strictlyEquals(QScriptValue(engine, "QML rocks")));
1495 QCOMPARE(o.error(), false);
1496 QCOMPARE(o.invoked(), 7);
1497 QCOMPARE(o.actuals().count(), 0);
1501 QCOMPARE(engine->evaluate("object.method_int(94)").isUndefined(), true);
1502 QCOMPARE(o.error(), false);
1503 QCOMPARE(o.invoked(), 8);
1504 QCOMPARE(o.actuals().count(), 1);
1505 QCOMPARE(o.actuals().at(0), QVariant(94));
1508 QCOMPARE(engine->evaluate("object.method_int(\"94\")").isUndefined(), true);
1509 QCOMPARE(o.error(), false);
1510 QCOMPARE(o.invoked(), 8);
1511 QCOMPARE(o.actuals().count(), 1);
1512 QCOMPARE(o.actuals().at(0), QVariant(94));
1515 QCOMPARE(engine->evaluate("object.method_int(\"not a number\")").isUndefined(), true);
1516 QCOMPARE(o.error(), false);
1517 QCOMPARE(o.invoked(), 8);
1518 QCOMPARE(o.actuals().count(), 1);
1519 QCOMPARE(o.actuals().at(0), QVariant(0));
1522 QCOMPARE(engine->evaluate("object.method_int(null)").isUndefined(), true);
1523 QCOMPARE(o.error(), false);
1524 QCOMPARE(o.invoked(), 8);
1525 QCOMPARE(o.actuals().count(), 1);
1526 QCOMPARE(o.actuals().at(0), QVariant(0));
1529 QCOMPARE(engine->evaluate("object.method_int(undefined)").isUndefined(), true);
1530 QCOMPARE(o.error(), false);
1531 QCOMPARE(o.invoked(), 8);
1532 QCOMPARE(o.actuals().count(), 1);
1533 QCOMPARE(o.actuals().at(0), QVariant(0));
1536 QCOMPARE(engine->evaluate("object.method_int(object)").isUndefined(), true);
1537 QCOMPARE(o.error(), false);
1538 QCOMPARE(o.invoked(), 8);
1539 QCOMPARE(o.actuals().count(), 1);
1540 QCOMPARE(o.actuals().at(0), QVariant(0));
1543 QCOMPARE(engine->evaluate("object.method_intint(122, 9)").isUndefined(), true);
1544 QCOMPARE(o.error(), false);
1545 QCOMPARE(o.invoked(), 9);
1546 QCOMPARE(o.actuals().count(), 2);
1547 QCOMPARE(o.actuals().at(0), QVariant(122));
1548 QCOMPARE(o.actuals().at(1), QVariant(9));
1551 QCOMPARE(engine->evaluate("object.method_real(94.3)").isUndefined(), true);
1552 QCOMPARE(o.error(), false);
1553 QCOMPARE(o.invoked(), 10);
1554 QCOMPARE(o.actuals().count(), 1);
1555 QCOMPARE(o.actuals().at(0), QVariant(94.3));
1558 QCOMPARE(engine->evaluate("object.method_real(\"94.3\")").isUndefined(), true);
1559 QCOMPARE(o.error(), false);
1560 QCOMPARE(o.invoked(), 10);
1561 QCOMPARE(o.actuals().count(), 1);
1562 QCOMPARE(o.actuals().at(0), QVariant(94.3));
1565 QCOMPARE(engine->evaluate("object.method_real(\"not a number\")").isUndefined(), true);
1566 QCOMPARE(o.error(), false);
1567 QCOMPARE(o.invoked(), 10);
1568 QCOMPARE(o.actuals().count(), 1);
1569 QVERIFY(qIsNaN(o.actuals().at(0).toDouble()));
1572 QCOMPARE(engine->evaluate("object.method_real(null)").isUndefined(), true);
1573 QCOMPARE(o.error(), false);
1574 QCOMPARE(o.invoked(), 10);
1575 QCOMPARE(o.actuals().count(), 1);
1576 QCOMPARE(o.actuals().at(0), QVariant(0));
1579 QCOMPARE(engine->evaluate("object.method_real(undefined)").isUndefined(), true);
1580 QCOMPARE(o.error(), false);
1581 QCOMPARE(o.invoked(), 10);
1582 QCOMPARE(o.actuals().count(), 1);
1583 QVERIFY(qIsNaN(o.actuals().at(0).toDouble()));
1586 QCOMPARE(engine->evaluate("object.method_real(object)").isUndefined(), true);
1587 QCOMPARE(o.error(), false);
1588 QCOMPARE(o.invoked(), 10);
1589 QCOMPARE(o.actuals().count(), 1);
1590 QVERIFY(qIsNaN(o.actuals().at(0).toDouble()));
1593 QCOMPARE(engine->evaluate("object.method_QString(\"Hello world\")").isUndefined(), true);
1594 QCOMPARE(o.error(), false);
1595 QCOMPARE(o.invoked(), 11);
1596 QCOMPARE(o.actuals().count(), 1);
1597 QCOMPARE(o.actuals().at(0), QVariant("Hello world"));
1600 QCOMPARE(engine->evaluate("object.method_QString(19)").isUndefined(), true);
1601 QCOMPARE(o.error(), false);
1602 QCOMPARE(o.invoked(), 11);
1603 QCOMPARE(o.actuals().count(), 1);
1604 QCOMPARE(o.actuals().at(0), QVariant("19"));
1608 QString expected = "MyInvokableObject(0x" + QString::number((quintptr)&o, 16) + ")";
1609 QCOMPARE(engine->evaluate("object.method_QString(object)").isUndefined(), true);
1610 QCOMPARE(o.error(), false);
1611 QCOMPARE(o.invoked(), 11);
1612 QCOMPARE(o.actuals().count(), 1);
1613 QCOMPARE(o.actuals().at(0), QVariant(expected));
1617 QCOMPARE(engine->evaluate("object.method_QString(null)").isUndefined(), true);
1618 QCOMPARE(o.error(), false);
1619 QCOMPARE(o.invoked(), 11);
1620 QCOMPARE(o.actuals().count(), 1);
1621 QCOMPARE(o.actuals().at(0), QVariant(QString()));
1624 QCOMPARE(engine->evaluate("object.method_QString(undefined)").isUndefined(), true);
1625 QCOMPARE(o.error(), false);
1626 QCOMPARE(o.invoked(), 11);
1627 QCOMPARE(o.actuals().count(), 1);
1628 QCOMPARE(o.actuals().at(0), QVariant(QString()));
1631 QCOMPARE(engine->evaluate("object.method_QPointF(0)").isUndefined(), true);
1632 QCOMPARE(o.error(), false);
1633 QCOMPARE(o.invoked(), 12);
1634 QCOMPARE(o.actuals().count(), 1);
1635 QCOMPARE(o.actuals().at(0), QVariant(QPointF()));
1638 QCOMPARE(engine->evaluate("object.method_QPointF(null)").isUndefined(), true);
1639 QCOMPARE(o.error(), false);
1640 QCOMPARE(o.invoked(), 12);
1641 QCOMPARE(o.actuals().count(), 1);
1642 QCOMPARE(o.actuals().at(0), QVariant(QPointF()));
1645 QCOMPARE(engine->evaluate("object.method_QPointF(undefined)").isUndefined(), true);
1646 QCOMPARE(o.error(), false);
1647 QCOMPARE(o.invoked(), 12);
1648 QCOMPARE(o.actuals().count(), 1);
1649 QCOMPARE(o.actuals().at(0), QVariant(QPointF()));
1652 QCOMPARE(engine->evaluate("object.method_QPointF(object)").isUndefined(), true);
1653 QCOMPARE(o.error(), false);
1654 QCOMPARE(o.invoked(), 12);
1655 QCOMPARE(o.actuals().count(), 1);
1656 QCOMPARE(o.actuals().at(0), QVariant(QPointF()));
1659 QCOMPARE(engine->evaluate("object.method_QPointF(object.method_get_QPointF())").isUndefined(), true);
1660 QCOMPARE(o.error(), false);
1661 QCOMPARE(o.invoked(), 12);
1662 QCOMPARE(o.actuals().count(), 1);
1663 QCOMPARE(o.actuals().at(0), QVariant(QPointF(99.3, -10.2)));
1666 QCOMPARE(engine->evaluate("object.method_QPointF(object.method_get_QPoint())").isUndefined(), true);
1667 QCOMPARE(o.error(), false);
1668 QCOMPARE(o.invoked(), 12);
1669 QCOMPARE(o.actuals().count(), 1);
1670 QCOMPARE(o.actuals().at(0), QVariant(QPointF(9, 12)));
1673 QCOMPARE(engine->evaluate("object.method_QObject(0)").isUndefined(), true);
1674 QCOMPARE(o.error(), false);
1675 QCOMPARE(o.invoked(), 13);
1676 QCOMPARE(o.actuals().count(), 1);
1677 QCOMPARE(o.actuals().at(0), qVariantFromValue((QObject *)0));
1680 QCOMPARE(engine->evaluate("object.method_QObject(\"Hello world\")").isUndefined(), true);
1681 QCOMPARE(o.error(), false);
1682 QCOMPARE(o.invoked(), 13);
1683 QCOMPARE(o.actuals().count(), 1);
1684 QCOMPARE(o.actuals().at(0), qVariantFromValue((QObject *)0));
1687 QCOMPARE(engine->evaluate("object.method_QObject(null)").isUndefined(), true);
1688 QCOMPARE(o.error(), false);
1689 QCOMPARE(o.invoked(), 13);
1690 QCOMPARE(o.actuals().count(), 1);
1691 QCOMPARE(o.actuals().at(0), qVariantFromValue((QObject *)0));
1694 QCOMPARE(engine->evaluate("object.method_QObject(undefined)").isUndefined(), true);
1695 QCOMPARE(o.error(), false);
1696 QCOMPARE(o.invoked(), 13);
1697 QCOMPARE(o.actuals().count(), 1);
1698 QCOMPARE(o.actuals().at(0), qVariantFromValue((QObject *)0));
1701 QCOMPARE(engine->evaluate("object.method_QObject(object)").isUndefined(), true);
1702 QCOMPARE(o.error(), false);
1703 QCOMPARE(o.invoked(), 13);
1704 QCOMPARE(o.actuals().count(), 1);
1705 QCOMPARE(o.actuals().at(0), qVariantFromValue((QObject *)&o));
1708 QCOMPARE(engine->evaluate("object.method_QScriptValue(null)").isUndefined(), true);
1709 QCOMPARE(o.error(), false);
1710 QCOMPARE(o.invoked(), 14);
1711 QCOMPARE(o.actuals().count(), 1);
1712 QVERIFY(qvariant_cast<QScriptValue>(o.actuals().at(0)).isNull());
1715 QCOMPARE(engine->evaluate("object.method_QScriptValue(undefined)").isUndefined(), true);
1716 QCOMPARE(o.error(), false);
1717 QCOMPARE(o.invoked(), 14);
1718 QCOMPARE(o.actuals().count(), 1);
1719 QVERIFY(qvariant_cast<QScriptValue>(o.actuals().at(0)).isUndefined());
1722 QCOMPARE(engine->evaluate("object.method_QScriptValue(19)").isUndefined(), true);
1723 QCOMPARE(o.error(), false);
1724 QCOMPARE(o.invoked(), 14);
1725 QCOMPARE(o.actuals().count(), 1);
1726 QVERIFY(qvariant_cast<QScriptValue>(o.actuals().at(0)).strictlyEquals(QScriptValue(engine, 19)));
1729 QCOMPARE(engine->evaluate("object.method_QScriptValue([19, 20])").isUndefined(), true);
1730 QCOMPARE(o.error(), false);
1731 QCOMPARE(o.invoked(), 14);
1732 QCOMPARE(o.actuals().count(), 1);
1733 QVERIFY(qvariant_cast<QScriptValue>(o.actuals().at(0)).isArray());
1736 QCOMPARE(engine->evaluate("object.method_intQScriptValue(4, null)").isUndefined(), true);
1737 QCOMPARE(o.error(), false);
1738 QCOMPARE(o.invoked(), 15);
1739 QCOMPARE(o.actuals().count(), 2);
1740 QCOMPARE(o.actuals().at(0), QVariant(4));
1741 QVERIFY(qvariant_cast<QScriptValue>(o.actuals().at(1)).isNull());
1744 QCOMPARE(engine->evaluate("object.method_intQScriptValue(8, undefined)").isUndefined(), true);
1745 QCOMPARE(o.error(), false);
1746 QCOMPARE(o.invoked(), 15);
1747 QCOMPARE(o.actuals().count(), 2);
1748 QCOMPARE(o.actuals().at(0), QVariant(8));
1749 QVERIFY(qvariant_cast<QScriptValue>(o.actuals().at(1)).isUndefined());
1752 QCOMPARE(engine->evaluate("object.method_intQScriptValue(3, 19)").isUndefined(), true);
1753 QCOMPARE(o.error(), false);
1754 QCOMPARE(o.invoked(), 15);
1755 QCOMPARE(o.actuals().count(), 2);
1756 QCOMPARE(o.actuals().at(0), QVariant(3));
1757 QVERIFY(qvariant_cast<QScriptValue>(o.actuals().at(1)).strictlyEquals(QScriptValue(engine, 19)));
1760 QCOMPARE(engine->evaluate("object.method_intQScriptValue(44, [19, 20])").isUndefined(), true);
1761 QCOMPARE(o.error(), false);
1762 QCOMPARE(o.invoked(), 15);
1763 QCOMPARE(o.actuals().count(), 2);
1764 QCOMPARE(o.actuals().at(0), QVariant(44));
1765 QVERIFY(qvariant_cast<QScriptValue>(o.actuals().at(1)).isArray());
1768 QCOMPARE(engine->evaluate("object.method_overload()").isError(), true);
1769 QCOMPARE(o.error(), false);
1770 QCOMPARE(o.invoked(), -1);
1771 QCOMPARE(o.actuals().count(), 0);
1774 QCOMPARE(engine->evaluate("object.method_overload(10)").isUndefined(), true);
1775 QCOMPARE(o.error(), false);
1776 QCOMPARE(o.invoked(), 16);
1777 QCOMPARE(o.actuals().count(), 1);
1778 QCOMPARE(o.actuals().at(0), QVariant(10));
1781 QCOMPARE(engine->evaluate("object.method_overload(10, 11)").isUndefined(), true);
1782 QCOMPARE(o.error(), false);
1783 QCOMPARE(o.invoked(), 17);
1784 QCOMPARE(o.actuals().count(), 2);
1785 QCOMPARE(o.actuals().at(0), QVariant(10));
1786 QCOMPARE(o.actuals().at(1), QVariant(11));
1789 QCOMPARE(engine->evaluate("object.method_overload(\"Hello\")").isUndefined(), true);
1790 QCOMPARE(o.error(), false);
1791 QCOMPARE(o.invoked(), 18);
1792 QCOMPARE(o.actuals().count(), 1);
1793 QCOMPARE(o.actuals().at(0), QVariant(QString("Hello")));
1796 QCOMPARE(engine->evaluate("object.method_with_enum(9)").isUndefined(), true);
1797 QCOMPARE(o.error(), false);
1798 QCOMPARE(o.invoked(), 19);
1799 QCOMPARE(o.actuals().count(), 1);
1800 QCOMPARE(o.actuals().at(0), QVariant(9));
1803 QVERIFY(engine->evaluate("object.method_default(10)").strictlyEquals(QScriptValue(19)));
1804 QCOMPARE(o.error(), false);
1805 QCOMPARE(o.invoked(), 20);
1806 QCOMPARE(o.actuals().count(), 2);
1807 QCOMPARE(o.actuals().at(0), QVariant(10));
1808 QCOMPARE(o.actuals().at(1), QVariant(19));
1811 QVERIFY(engine->evaluate("object.method_default(10, 13)").strictlyEquals(QScriptValue(13)));
1812 QCOMPARE(o.error(), false);
1813 QCOMPARE(o.invoked(), 20);
1814 QCOMPARE(o.actuals().count(), 2);
1815 QCOMPARE(o.actuals().at(0), QVariant(10));
1816 QCOMPARE(o.actuals().at(1), QVariant(13));
1819 QCOMPARE(engine->evaluate("object.method_inherited(9)").isUndefined(), true);
1820 QCOMPARE(o.error(), false);
1821 QCOMPARE(o.invoked(), -3);
1822 QCOMPARE(o.actuals().count(), 1);
1823 QCOMPARE(o.actuals().at(0), QVariant(9));
1826 QCOMPARE(engine->evaluate("object.method_QVariant(9)").isUndefined(), true);
1827 QCOMPARE(o.error(), false);
1828 QCOMPARE(o.invoked(), 21);
1829 QCOMPARE(o.actuals().count(), 2);
1830 QCOMPARE(o.actuals().at(0), QVariant(9));
1831 QCOMPARE(o.actuals().at(1), QVariant());
1834 QCOMPARE(engine->evaluate("object.method_QVariant(\"Hello\", \"World\")").isUndefined(), true);
1835 QCOMPARE(o.error(), false);
1836 QCOMPARE(o.invoked(), 21);
1837 QCOMPARE(o.actuals().count(), 2);
1838 QCOMPARE(o.actuals().at(0), QVariant(QString("Hello")));
1839 QCOMPARE(o.actuals().at(1), QVariant(QString("World")));
1842 // QTBUG-13047 (check that you can pass registered object types as args)
1843 void tst_qdeclarativeecmascript::invokableObjectArg()
1845 QDeclarativeComponent component(&engine, TEST_FILE("invokableObjectArg.qml"));
1847 QObject *o = component.create();
1849 MyQmlObject *qmlobject = qobject_cast<MyQmlObject *>(o);
1851 QCOMPARE(qmlobject->myinvokableObject, qmlobject);
1856 // QTBUG-13047 (check that you can return registered object types from methods)
1857 void tst_qdeclarativeecmascript::invokableObjectRet()
1859 QDeclarativeComponent component(&engine, TEST_FILE("invokableObjectRet.qml"));
1861 QObject *o = component.create();
1863 QCOMPARE(o->property("test").toBool(), true);
1868 void tst_qdeclarativeecmascript::listToVariant()
1870 QDeclarativeComponent component(&engine, TEST_FILE("listToVariant.qml"));
1872 MyQmlContainer container;
1874 QDeclarativeContext context(engine.rootContext());
1875 context.setContextObject(&container);
1877 QObject *object = component.create(&context);
1878 QVERIFY(object != 0);
1880 QVariant v = object->property("test");
1881 QCOMPARE(v.userType(), qMetaTypeId<QDeclarativeListReference>());
1882 QVERIFY(qvariant_cast<QDeclarativeListReference>(v).object() == &container);
1888 void tst_qdeclarativeecmascript::multiEngineObject()
1891 obj.setStringProperty("Howdy planet");
1893 QDeclarativeEngine e1;
1894 e1.rootContext()->setContextProperty("thing", &obj);
1895 QDeclarativeComponent c1(&e1, TEST_FILE("multiEngineObject.qml"));
1897 QDeclarativeEngine e2;
1898 e2.rootContext()->setContextProperty("thing", &obj);
1899 QDeclarativeComponent c2(&e2, TEST_FILE("multiEngineObject.qml"));
1901 QObject *o1 = c1.create();
1902 QObject *o2 = c2.create();
1904 QCOMPARE(o1->property("test").toString(), QString("Howdy planet"));
1905 QCOMPARE(o2->property("test").toString(), QString("Howdy planet"));
1911 // Test that references to QObjects are cleanup when the object is destroyed
1912 void tst_qdeclarativeecmascript::deletedObject()
1914 QDeclarativeComponent component(&engine, TEST_FILE("deletedObject.qml"));
1916 QObject *object = component.create();
1918 QCOMPARE(object->property("test1").toBool(), true);
1919 QCOMPARE(object->property("test2").toBool(), true);
1920 QCOMPARE(object->property("test3").toBool(), true);
1921 QCOMPARE(object->property("test4").toBool(), true);
1926 void tst_qdeclarativeecmascript::attachedPropertyScope()
1928 QDeclarativeComponent component(&engine, TEST_FILE("attachedPropertyScope.qml"));
1930 QObject *object = component.create();
1931 QVERIFY(object != 0);
1933 MyQmlAttachedObject *attached =
1934 qobject_cast<MyQmlAttachedObject *>(qmlAttachedPropertiesObject<MyQmlObject>(object));
1935 QVERIFY(attached != 0);
1937 QCOMPARE(object->property("value2").toInt(), 0);
1939 attached->emitMySignal();
1941 QCOMPARE(object->property("value2").toInt(), 9);
1946 void tst_qdeclarativeecmascript::scriptConnect()
1949 QDeclarativeComponent component(&engine, TEST_FILE("scriptConnect.1.qml"));
1951 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
1952 QVERIFY(object != 0);
1954 QCOMPARE(object->property("test").toBool(), false);
1955 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
1956 QCOMPARE(object->property("test").toBool(), true);
1962 QDeclarativeComponent component(&engine, TEST_FILE("scriptConnect.2.qml"));
1964 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
1965 QVERIFY(object != 0);
1967 QCOMPARE(object->property("test").toBool(), false);
1968 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
1969 QCOMPARE(object->property("test").toBool(), true);
1975 QDeclarativeComponent component(&engine, TEST_FILE("scriptConnect.3.qml"));
1977 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
1978 QVERIFY(object != 0);
1980 QCOMPARE(object->property("test").toBool(), false);
1981 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
1982 QCOMPARE(object->property("test").toBool(), true);
1988 QDeclarativeComponent component(&engine, TEST_FILE("scriptConnect.4.qml"));
1990 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
1991 QVERIFY(object != 0);
1993 QCOMPARE(object->methodCalled(), false);
1994 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
1995 QCOMPARE(object->methodCalled(), true);
2001 QDeclarativeComponent component(&engine, TEST_FILE("scriptConnect.5.qml"));
2003 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2004 QVERIFY(object != 0);
2006 QCOMPARE(object->methodCalled(), false);
2007 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2008 QCOMPARE(object->methodCalled(), true);
2014 QDeclarativeComponent component(&engine, TEST_FILE("scriptConnect.6.qml"));
2016 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2017 QVERIFY(object != 0);
2019 QCOMPARE(object->property("test").toInt(), 0);
2020 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2021 QCOMPARE(object->property("test").toInt(), 2);
2027 void tst_qdeclarativeecmascript::scriptDisconnect()
2030 QDeclarativeComponent component(&engine, TEST_FILE("scriptDisconnect.1.qml"));
2032 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2033 QVERIFY(object != 0);
2035 QCOMPARE(object->property("test").toInt(), 0);
2036 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2037 QCOMPARE(object->property("test").toInt(), 1);
2038 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2039 QCOMPARE(object->property("test").toInt(), 2);
2040 emit object->basicSignal();
2041 QCOMPARE(object->property("test").toInt(), 2);
2042 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2043 QCOMPARE(object->property("test").toInt(), 2);
2049 QDeclarativeComponent component(&engine, TEST_FILE("scriptDisconnect.2.qml"));
2051 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2052 QVERIFY(object != 0);
2054 QCOMPARE(object->property("test").toInt(), 0);
2055 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2056 QCOMPARE(object->property("test").toInt(), 1);
2057 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2058 QCOMPARE(object->property("test").toInt(), 2);
2059 emit object->basicSignal();
2060 QCOMPARE(object->property("test").toInt(), 2);
2061 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2062 QCOMPARE(object->property("test").toInt(), 2);
2068 QDeclarativeComponent component(&engine, TEST_FILE("scriptDisconnect.3.qml"));
2070 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2071 QVERIFY(object != 0);
2073 QCOMPARE(object->property("test").toInt(), 0);
2074 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2075 QCOMPARE(object->property("test").toInt(), 1);
2076 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2077 QCOMPARE(object->property("test").toInt(), 2);
2078 emit object->basicSignal();
2079 QCOMPARE(object->property("test").toInt(), 2);
2080 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2081 QCOMPARE(object->property("test").toInt(), 3);
2086 QDeclarativeComponent component(&engine, TEST_FILE("scriptDisconnect.4.qml"));
2088 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2089 QVERIFY(object != 0);
2091 QCOMPARE(object->property("test").toInt(), 0);
2092 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2093 QCOMPARE(object->property("test").toInt(), 1);
2094 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2095 QCOMPARE(object->property("test").toInt(), 2);
2096 emit object->basicSignal();
2097 QCOMPARE(object->property("test").toInt(), 2);
2098 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2099 QCOMPARE(object->property("test").toInt(), 3);
2105 class OwnershipObject : public QObject
2109 OwnershipObject() { object = new QObject; }
2111 QPointer<QObject> object;
2114 QObject *getObject() { return object; }
2117 void tst_qdeclarativeecmascript::ownership()
2119 OwnershipObject own;
2120 QDeclarativeContext *context = new QDeclarativeContext(engine.rootContext());
2121 context->setContextObject(&own);
2124 QDeclarativeComponent component(&engine, TEST_FILE("ownership.qml"));
2126 QVERIFY(own.object != 0);
2128 QObject *object = component.create(context);
2129 QDeclarativeEnginePrivate::getScriptEngine(&engine)->collectGarbage();
2131 QCoreApplication::processEvents(QEventLoop::DeferredDeletion);
2133 QVERIFY(own.object == 0);
2138 own.object = new QObject(&own);
2141 QDeclarativeComponent component(&engine, TEST_FILE("ownership.qml"));
2143 QVERIFY(own.object != 0);
2145 QObject *object = component.create(context);
2146 QDeclarativeEnginePrivate::getScriptEngine(&engine)->collectGarbage();
2148 QCoreApplication::processEvents(QEventLoop::DeferredDeletion);
2150 QVERIFY(own.object != 0);
2156 class CppOwnershipReturnValue : public QObject
2160 CppOwnershipReturnValue() : value(0) {}
2161 ~CppOwnershipReturnValue() { delete value; }
2163 Q_INVOKABLE QObject *create() {
2164 Q_ASSERT(value == 0);
2166 value = new QObject;
2167 QDeclarativeEngine::setObjectOwnership(value, QDeclarativeEngine::CppOwnership);
2171 Q_INVOKABLE MyQmlObject *createQmlObject() {
2172 Q_ASSERT(value == 0);
2174 MyQmlObject *rv = new MyQmlObject;
2179 QPointer<QObject> value;
2183 // Test setObjectOwnership(CppOwnership) works even when there is no QDeclarativeData
2184 void tst_qdeclarativeecmascript::cppOwnershipReturnValue()
2186 CppOwnershipReturnValue source;
2189 QDeclarativeEngine engine;
2190 engine.rootContext()->setContextProperty("source", &source);
2192 QVERIFY(source.value == 0);
2194 QDeclarativeComponent component(&engine);
2195 component.setData("import QtQuick 1.0\nQtObject {\nComponent.onCompleted: { var a = source.create(); }\n}\n", QUrl());
2197 QObject *object = component.create();
2199 QVERIFY(object != 0);
2200 QVERIFY(source.value != 0);
2205 QCoreApplication::instance()->processEvents(QEventLoop::DeferredDeletion);
2207 QVERIFY(source.value != 0);
2211 void tst_qdeclarativeecmascript::ownershipCustomReturnValue()
2213 CppOwnershipReturnValue source;
2216 QDeclarativeEngine engine;
2217 engine.rootContext()->setContextProperty("source", &source);
2219 QVERIFY(source.value == 0);
2221 QDeclarativeComponent component(&engine);
2222 component.setData("import QtQuick 1.0\nQtObject {\nComponent.onCompleted: { var a = source.createQmlObject(); }\n}\n", QUrl());
2224 QObject *object = component.create();
2226 QVERIFY(object != 0);
2227 QVERIFY(source.value != 0);
2232 QCoreApplication::instance()->processEvents(QEventLoop::DeferredDeletion);
2234 QVERIFY(source.value == 0);
2237 class QListQObjectMethodsObject : public QObject
2241 QListQObjectMethodsObject() {
2242 m_objects.append(new MyQmlObject());
2243 m_objects.append(new MyQmlObject());
2246 ~QListQObjectMethodsObject() {
2247 qDeleteAll(m_objects);
2251 QList<QObject *> getObjects() { return m_objects; }
2254 QList<QObject *> m_objects;
2257 // Tests that returning a QList<QObject*> from a method works
2258 void tst_qdeclarativeecmascript::qlistqobjectMethods()
2260 QListQObjectMethodsObject obj;
2261 QDeclarativeContext *context = new QDeclarativeContext(engine.rootContext());
2262 context->setContextObject(&obj);
2264 QDeclarativeComponent component(&engine, TEST_FILE("qlistqobjectMethods.qml"));
2266 QObject *object = component.create(context);
2268 QCOMPARE(object->property("test").toInt(), 2);
2269 QCOMPARE(object->property("test2").toBool(), true);
2275 void tst_qdeclarativeecmascript::strictlyEquals()
2277 QDeclarativeComponent component(&engine, TEST_FILE("strictlyEquals.qml"));
2279 QObject *object = component.create();
2280 QVERIFY(object != 0);
2282 QCOMPARE(object->property("test1").toBool(), true);
2283 QCOMPARE(object->property("test2").toBool(), true);
2284 QCOMPARE(object->property("test3").toBool(), true);
2285 QCOMPARE(object->property("test4").toBool(), true);
2286 QCOMPARE(object->property("test5").toBool(), true);
2287 QCOMPARE(object->property("test6").toBool(), true);
2288 QCOMPARE(object->property("test7").toBool(), true);
2289 QCOMPARE(object->property("test8").toBool(), true);
2294 void tst_qdeclarativeecmascript::compiled()
2296 QDeclarativeComponent component(&engine, TEST_FILE("compiled.qml"));
2298 QObject *object = component.create();
2299 QVERIFY(object != 0);
2301 QCOMPARE(object->property("test1").toReal(), qreal(15.7));
2302 QCOMPARE(object->property("test2").toReal(), qreal(-6.7));
2303 QCOMPARE(object->property("test3").toBool(), true);
2304 QCOMPARE(object->property("test4").toBool(), false);
2305 QCOMPARE(object->property("test5").toBool(), false);
2306 QCOMPARE(object->property("test6").toBool(), true);
2308 QCOMPARE(object->property("test7").toInt(), 185);
2309 QCOMPARE(object->property("test8").toInt(), 167);
2310 QCOMPARE(object->property("test9").toBool(), true);
2311 QCOMPARE(object->property("test10").toBool(), false);
2312 QCOMPARE(object->property("test11").toBool(), false);
2313 QCOMPARE(object->property("test12").toBool(), true);
2315 QCOMPARE(object->property("test13").toString(), QLatin1String("HelloWorld"));
2316 QCOMPARE(object->property("test14").toString(), QLatin1String("Hello World"));
2317 QCOMPARE(object->property("test15").toBool(), false);
2318 QCOMPARE(object->property("test16").toBool(), true);
2320 QCOMPARE(object->property("test17").toInt(), 5);
2321 QCOMPARE(object->property("test18").toReal(), qreal(176));
2322 QCOMPARE(object->property("test19").toInt(), 7);
2323 QCOMPARE(object->property("test20").toReal(), qreal(6.7));
2324 QCOMPARE(object->property("test21").toString(), QLatin1String("6.7"));
2325 QCOMPARE(object->property("test22").toString(), QLatin1String("!"));
2326 QCOMPARE(object->property("test23").toBool(), true);
2327 QCOMPARE(qvariant_cast<QColor>(object->property("test24")), QColor(0x11,0x22,0x33));
2328 QCOMPARE(qvariant_cast<QColor>(object->property("test25")), QColor(0x11,0x22,0x33,0xAA));
2333 // Test that numbers assigned in bindings as strings work consistently
2334 void tst_qdeclarativeecmascript::numberAssignment()
2336 QDeclarativeComponent component(&engine, TEST_FILE("numberAssignment.qml"));
2338 QObject *object = component.create();
2339 QVERIFY(object != 0);
2341 QCOMPARE(object->property("test1"), QVariant((qreal)6.7));
2342 QCOMPARE(object->property("test2"), QVariant((qreal)6.7));
2343 QCOMPARE(object->property("test2"), QVariant((qreal)6.7));
2344 QCOMPARE(object->property("test3"), QVariant((qreal)6));
2345 QCOMPARE(object->property("test4"), QVariant((qreal)6));
2347 QCOMPARE(object->property("test5"), QVariant((int)7));
2348 QCOMPARE(object->property("test6"), QVariant((int)7));
2349 QCOMPARE(object->property("test7"), QVariant((int)6));
2350 QCOMPARE(object->property("test8"), QVariant((int)6));
2352 QCOMPARE(object->property("test9"), QVariant((unsigned int)7));
2353 QCOMPARE(object->property("test10"), QVariant((unsigned int)7));
2354 QCOMPARE(object->property("test11"), QVariant((unsigned int)6));
2355 QCOMPARE(object->property("test12"), QVariant((unsigned int)6));
2360 void tst_qdeclarativeecmascript::propertySplicing()
2362 QDeclarativeComponent component(&engine, TEST_FILE("propertySplicing.qml"));
2364 QObject *object = component.create();
2365 QVERIFY(object != 0);
2367 QCOMPARE(object->property("test").toBool(), true);
2373 void tst_qdeclarativeecmascript::signalWithUnknownTypes()
2375 QDeclarativeComponent component(&engine, TEST_FILE("signalWithUnknownTypes.qml"));
2377 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2378 QVERIFY(object != 0);
2380 MyQmlObject::MyType type;
2381 type.value = 0x8971123;
2382 emit object->signalWithUnknownType(type);
2384 MyQmlObject::MyType result = qvariant_cast<MyQmlObject::MyType>(object->variant());
2386 QCOMPARE(result.value, type.value);
2392 // Test that assigning a null object works
2393 // Regressed with: df1788b4dbbb2826ae63f26bdf166342595343f4
2394 void tst_qdeclarativeecmascript::nullObjectBinding()
2396 QDeclarativeComponent component(&engine, TEST_FILE("nullObjectBinding.qml"));
2398 QObject *object = component.create();
2399 QVERIFY(object != 0);
2401 QVERIFY(object->property("test") == QVariant::fromValue((QObject *)0));
2406 // Test that bindings don't evaluate once the engine has been destroyed
2407 void tst_qdeclarativeecmascript::deletedEngine()
2409 QDeclarativeEngine *engine = new QDeclarativeEngine;
2410 QDeclarativeComponent component(engine, TEST_FILE("deletedEngine.qml"));
2412 QObject *object = component.create();
2413 QVERIFY(object != 0);
2415 QCOMPARE(object->property("a").toInt(), 39);
2416 object->setProperty("b", QVariant(9));
2417 QCOMPARE(object->property("a").toInt(), 117);
2421 QCOMPARE(object->property("a").toInt(), 117);
2422 object->setProperty("b", QVariant(10));
2423 QCOMPARE(object->property("a").toInt(), 117);
2428 // Test the crashing part of QTBUG-9705
2429 void tst_qdeclarativeecmascript::libraryScriptAssert()
2431 QDeclarativeComponent component(&engine, TEST_FILE("libraryScriptAssert.qml"));
2433 QObject *object = component.create();
2434 QVERIFY(object != 0);
2439 void tst_qdeclarativeecmascript::variantsAssignedUndefined()
2441 QDeclarativeComponent component(&engine, TEST_FILE("variantsAssignedUndefined.qml"));
2443 QObject *object = component.create();
2444 QVERIFY(object != 0);
2446 QCOMPARE(object->property("test1").toInt(), 10);
2447 QCOMPARE(object->property("test2").toInt(), 11);
2449 object->setProperty("runTest", true);
2451 QCOMPARE(object->property("test1"), QVariant());
2452 QCOMPARE(object->property("test2"), QVariant());
2458 void tst_qdeclarativeecmascript::qtbug_9792()
2460 QDeclarativeComponent component(&engine, TEST_FILE("qtbug_9792.qml"));
2462 QDeclarativeContext *context = new QDeclarativeContext(engine.rootContext());
2464 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create(context));
2465 QVERIFY(object != 0);
2467 QTest::ignoreMessage(QtDebugMsg, "Hello world!");
2468 object->basicSignal();
2472 transientErrorsMsgCount = 0;
2473 QtMsgHandler old = qInstallMsgHandler(transientErrorsMsgHandler);
2475 object->basicSignal();
2477 qInstallMsgHandler(old);
2479 QCOMPARE(transientErrorsMsgCount, 0);
2484 // Verifies that QDeclarativeGuard<>s used in the vmemetaobject are cleaned correctly
2485 void tst_qdeclarativeecmascript::qtcreatorbug_1289()
2487 QDeclarativeComponent component(&engine, TEST_FILE("qtcreatorbug_1289.qml"));
2489 QObject *o = component.create();
2492 QObject *nested = qvariant_cast<QObject *>(o->property("object"));
2493 QVERIFY(nested != 0);
2495 QVERIFY(qvariant_cast<QObject *>(nested->property("nestedObject")) == o);
2498 nested = qvariant_cast<QObject *>(o->property("object"));
2499 QVERIFY(nested == 0);
2501 // If the bug is present, the next line will crash
2505 // Test that we shut down without stupid warnings
2506 void tst_qdeclarativeecmascript::noSpuriousWarningsAtShutdown()
2509 QDeclarativeComponent component(&engine, TEST_FILE("noSpuriousWarningsAtShutdown.qml"));
2511 QObject *o = component.create();
2513 transientErrorsMsgCount = 0;
2514 QtMsgHandler old = qInstallMsgHandler(transientErrorsMsgHandler);
2518 qInstallMsgHandler(old);
2520 QCOMPARE(transientErrorsMsgCount, 0);
2525 QDeclarativeComponent component(&engine, TEST_FILE("noSpuriousWarningsAtShutdown.2.qml"));
2527 QObject *o = component.create();
2529 transientErrorsMsgCount = 0;
2530 QtMsgHandler old = qInstallMsgHandler(transientErrorsMsgHandler);
2534 qInstallMsgHandler(old);
2536 QCOMPARE(transientErrorsMsgCount, 0);
2540 void tst_qdeclarativeecmascript::canAssignNullToQObject()
2543 QDeclarativeComponent component(&engine, TEST_FILE("canAssignNullToQObject.1.qml"));
2545 MyQmlObject *o = qobject_cast<MyQmlObject *>(component.create());
2548 QVERIFY(o->objectProperty() != 0);
2550 o->setProperty("runTest", true);
2552 QVERIFY(o->objectProperty() == 0);
2558 QDeclarativeComponent component(&engine, TEST_FILE("canAssignNullToQObject.2.qml"));
2560 MyQmlObject *o = qobject_cast<MyQmlObject *>(component.create());
2563 QVERIFY(o->objectProperty() == 0);
2569 void tst_qdeclarativeecmascript::functionAssignment_fromBinding()
2571 QDeclarativeComponent component(&engine, TEST_FILE("functionAssignment.1.qml"));
2573 QString url = component.url().toString();
2574 QString warning = url + ":4: Unable to assign a function to a property.";
2575 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
2577 MyQmlObject *o = qobject_cast<MyQmlObject *>(component.create());
2580 QVERIFY(!o->property("a").isValid());
2585 void tst_qdeclarativeecmascript::functionAssignment_fromJS()
2587 QFETCH(QString, triggerProperty);
2589 QDeclarativeComponent component(&engine, TEST_FILE("functionAssignment.2.qml"));
2590 QVERIFY2(component.errorString().isEmpty(), qPrintable(component.errorString()));
2592 MyQmlObject *o = qobject_cast<MyQmlObject *>(component.create());
2594 QVERIFY(!o->property("a").isValid());
2596 o->setProperty("aNumber", QVariant(5));
2597 o->setProperty(triggerProperty.toUtf8().constData(), true);
2598 QCOMPARE(o->property("a"), QVariant(50));
2600 o->setProperty("aNumber", QVariant(10));
2601 QCOMPARE(o->property("a"), QVariant(100));
2606 void tst_qdeclarativeecmascript::functionAssignment_fromJS_data()
2608 QTest::addColumn<QString>("triggerProperty");
2610 QTest::newRow("assign to property") << "assignToProperty";
2611 QTest::newRow("assign to property, from JS file") << "assignToPropertyFromJsFile";
2613 QTest::newRow("assign to value type") << "assignToValueType";
2615 QTest::newRow("use 'this'") << "assignWithThis";
2616 QTest::newRow("use 'this' from JS file") << "assignWithThisFromJsFile";
2619 void tst_qdeclarativeecmascript::functionAssignmentfromJS_invalid()
2621 QDeclarativeComponent component(&engine, TEST_FILE("functionAssignment.2.qml"));
2622 QVERIFY2(component.errorString().isEmpty(), qPrintable(component.errorString()));
2624 MyQmlObject *o = qobject_cast<MyQmlObject *>(component.create());
2626 QVERIFY(!o->property("a").isValid());
2628 o->setProperty("assignFuncWithoutReturn", true);
2629 QVERIFY(!o->property("a").isValid());
2631 QString url = component.url().toString();
2632 QString warning = url + ":63: Unable to assign QString to int";
2633 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
2634 o->setProperty("assignWrongType", true);
2636 warning = url + ":70: Unable to assign QString to int";
2637 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
2638 o->setProperty("assignWrongTypeToValueType", true);
2643 void tst_qdeclarativeecmascript::eval()
2645 QDeclarativeComponent component(&engine, TEST_FILE("eval.qml"));
2647 QObject *o = component.create();
2650 QCOMPARE(o->property("test1").toBool(), true);
2651 QCOMPARE(o->property("test2").toBool(), true);
2652 QCOMPARE(o->property("test3").toBool(), true);
2653 QCOMPARE(o->property("test4").toBool(), true);
2654 QCOMPARE(o->property("test5").toBool(), true);
2659 void tst_qdeclarativeecmascript::function()
2661 QDeclarativeComponent component(&engine, TEST_FILE("function.qml"));
2663 QObject *o = component.create();
2666 QCOMPARE(o->property("test1").toBool(), true);
2667 QCOMPARE(o->property("test2").toBool(), true);
2668 QCOMPARE(o->property("test3").toBool(), true);
2673 // Test the "Qt.include" method
2674 void tst_qdeclarativeecmascript::include()
2676 // Non-library relative include
2678 QDeclarativeComponent component(&engine, TEST_FILE("include.qml"));
2679 QObject *o = component.create();
2682 QCOMPARE(o->property("test0").toInt(), 99);
2683 QCOMPARE(o->property("test1").toBool(), true);
2684 QCOMPARE(o->property("test2").toBool(), true);
2685 QCOMPARE(o->property("test2_1").toBool(), true);
2686 QCOMPARE(o->property("test3").toBool(), true);
2687 QCOMPARE(o->property("test3_1").toBool(), true);
2692 // Library relative include
2694 QDeclarativeComponent component(&engine, TEST_FILE("include_shared.qml"));
2695 QObject *o = component.create();
2698 QCOMPARE(o->property("test0").toInt(), 99);
2699 QCOMPARE(o->property("test1").toBool(), true);
2700 QCOMPARE(o->property("test2").toBool(), true);
2701 QCOMPARE(o->property("test2_1").toBool(), true);
2702 QCOMPARE(o->property("test3").toBool(), true);
2703 QCOMPARE(o->property("test3_1").toBool(), true);
2710 QDeclarativeComponent component(&engine, TEST_FILE("include_callback.qml"));
2711 QObject *o = component.create();
2714 QCOMPARE(o->property("test1").toBool(), true);
2715 QCOMPARE(o->property("test2").toBool(), true);
2716 QCOMPARE(o->property("test3").toBool(), true);
2717 QCOMPARE(o->property("test4").toBool(), true);
2718 QCOMPARE(o->property("test5").toBool(), true);
2719 QCOMPARE(o->property("test6").toBool(), true);
2724 // Including file with ".pragma library"
2726 QDeclarativeComponent component(&engine, TEST_FILE("include_pragma.qml"));
2727 QObject *o = component.create();
2729 QCOMPARE(o->property("test1").toInt(), 100);
2736 TestHTTPServer server(8111);
2737 QVERIFY(server.isValid());
2738 server.serveDirectory(SRCDIR "/data");
2740 QDeclarativeComponent component(&engine, TEST_FILE("include_remote.qml"));
2741 QObject *o = component.create();
2744 QTRY_VERIFY(o->property("done").toBool() == true);
2745 QTRY_VERIFY(o->property("done2").toBool() == true);
2747 QCOMPARE(o->property("test1").toBool(), true);
2748 QCOMPARE(o->property("test2").toBool(), true);
2749 QCOMPARE(o->property("test3").toBool(), true);
2750 QCOMPARE(o->property("test4").toBool(), true);
2751 QCOMPARE(o->property("test5").toBool(), true);
2753 QCOMPARE(o->property("test6").toBool(), true);
2754 QCOMPARE(o->property("test7").toBool(), true);
2755 QCOMPARE(o->property("test8").toBool(), true);
2756 QCOMPARE(o->property("test9").toBool(), true);
2757 QCOMPARE(o->property("test10").toBool(), true);
2764 TestHTTPServer server(8111);
2765 QVERIFY(server.isValid());
2766 server.serveDirectory(SRCDIR "/data");
2768 QDeclarativeComponent component(&engine, TEST_FILE("include_remote_missing.qml"));
2769 QObject *o = component.create();
2772 QTRY_VERIFY(o->property("done").toBool() == true);
2774 QCOMPARE(o->property("test1").toBool(), true);
2775 QCOMPARE(o->property("test2").toBool(), true);
2776 QCOMPARE(o->property("test3").toBool(), true);
2782 void tst_qdeclarativeecmascript::qtbug_10696()
2784 QDeclarativeComponent component(&engine, TEST_FILE("qtbug_10696.qml"));
2785 QObject *o = component.create();
2790 void tst_qdeclarativeecmascript::qtbug_11606()
2792 QDeclarativeComponent component(&engine, TEST_FILE("qtbug_11606.qml"));
2793 QObject *o = component.create();
2795 QCOMPARE(o->property("test").toBool(), true);
2799 void tst_qdeclarativeecmascript::qtbug_11600()
2801 QDeclarativeComponent component(&engine, TEST_FILE("qtbug_11600.qml"));
2802 QObject *o = component.create();
2804 QCOMPARE(o->property("test").toBool(), true);
2808 // Reading and writing non-scriptable properties should fail
2809 void tst_qdeclarativeecmascript::nonscriptable()
2811 QDeclarativeComponent component(&engine, TEST_FILE("nonscriptable.qml"));
2812 QObject *o = component.create();
2814 QCOMPARE(o->property("readOk").toBool(), true);
2815 QCOMPARE(o->property("writeOk").toBool(), true);
2819 // deleteLater() should not be callable from QML
2820 void tst_qdeclarativeecmascript::deleteLater()
2822 QDeclarativeComponent component(&engine, TEST_FILE("deleteLater.qml"));
2823 QObject *o = component.create();
2825 QCOMPARE(o->property("test").toBool(), true);
2829 void tst_qdeclarativeecmascript::in()
2831 QDeclarativeComponent component(&engine, TEST_FILE("in.qml"));
2832 QObject *o = component.create();
2834 QCOMPARE(o->property("test1").toBool(), true);
2835 QCOMPARE(o->property("test2").toBool(), true);
2839 void tst_qdeclarativeecmascript::sharedAttachedObject()
2841 QDeclarativeComponent component(&engine, TEST_FILE("sharedAttachedObject.qml"));
2842 QObject *o = component.create();
2844 QCOMPARE(o->property("test1").toBool(), true);
2845 QCOMPARE(o->property("test2").toBool(), true);
2850 void tst_qdeclarativeecmascript::objectName()
2852 QDeclarativeComponent component(&engine, TEST_FILE("objectName.qml"));
2853 QObject *o = component.create();
2856 QCOMPARE(o->property("test1").toString(), QString("hello"));
2857 QCOMPARE(o->property("test2").toString(), QString("ell"));
2859 o->setObjectName("world");
2861 QCOMPARE(o->property("test1").toString(), QString("world"));
2862 QCOMPARE(o->property("test2").toString(), QString("orl"));
2867 void tst_qdeclarativeecmascript::writeRemovesBinding()
2869 QDeclarativeComponent component(&engine, TEST_FILE("writeRemovesBinding.qml"));
2870 QObject *o = component.create();
2873 QCOMPARE(o->property("test").toBool(), true);
2878 // Test bindings assigned to alias properties actually assign to the alias' target
2879 void tst_qdeclarativeecmascript::aliasBindingsAssignCorrectly()
2881 QDeclarativeComponent component(&engine, TEST_FILE("aliasBindingsAssignCorrectly.qml"));
2882 QObject *o = component.create();
2885 QCOMPARE(o->property("test").toBool(), true);
2890 // Test bindings assigned to alias properties override a binding on the target (QTBUG-13719)
2891 void tst_qdeclarativeecmascript::aliasBindingsOverrideTarget()
2894 QDeclarativeComponent component(&engine, TEST_FILE("aliasBindingsOverrideTarget.qml"));
2895 QObject *o = component.create();
2898 QCOMPARE(o->property("test").toBool(), true);
2904 QDeclarativeComponent component(&engine, TEST_FILE("aliasBindingsOverrideTarget.2.qml"));
2905 QObject *o = component.create();
2908 QCOMPARE(o->property("test").toBool(), true);
2914 QDeclarativeComponent component(&engine, TEST_FILE("aliasBindingsOverrideTarget.3.qml"));
2915 QObject *o = component.create();
2918 QCOMPARE(o->property("test").toBool(), true);
2924 // Test that writes to alias properties override bindings on the alias target (QTBUG-13719)
2925 void tst_qdeclarativeecmascript::aliasWritesOverrideBindings()
2928 QDeclarativeComponent component(&engine, TEST_FILE("aliasWritesOverrideBindings.qml"));
2929 QObject *o = component.create();
2932 QCOMPARE(o->property("test").toBool(), true);
2938 QDeclarativeComponent component(&engine, TEST_FILE("aliasWritesOverrideBindings.2.qml"));
2939 QObject *o = component.create();
2942 QCOMPARE(o->property("test").toBool(), true);
2948 QDeclarativeComponent component(&engine, TEST_FILE("aliasWritesOverrideBindings.3.qml"));
2949 QObject *o = component.create();
2952 QCOMPARE(o->property("test").toBool(), true);
2958 void tst_qdeclarativeecmascript::revisionErrors()
2961 QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevisionErrors.qml"));
2962 QString url = component.url().toString();
2964 QString warning1 = url + ":8: ReferenceError: Can't find variable: prop2";
2965 QString warning2 = url + ":11: ReferenceError: Can't find variable: prop2";
2966 QString warning3 = url + ":13: ReferenceError: Can't find variable: method2";
2968 QTest::ignoreMessage(QtWarningMsg, warning1.toLatin1().constData());
2969 QTest::ignoreMessage(QtWarningMsg, warning2.toLatin1().constData());
2970 QTest::ignoreMessage(QtWarningMsg, warning3.toLatin1().constData());
2971 MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create());
2972 QVERIFY(object != 0);
2975 QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevisionErrors2.qml"));
2976 QString url = component.url().toString();
2978 // MyRevisionedSubclass 1.0 uses MyRevisionedClass revision 0
2979 // method2, prop2 from MyRevisionedClass not available
2980 // method4, prop4 from MyRevisionedSubclass not available
2981 QString warning1 = url + ":8: ReferenceError: Can't find variable: prop2";
2982 QString warning2 = url + ":14: ReferenceError: Can't find variable: prop2";
2983 QString warning3 = url + ":10: ReferenceError: Can't find variable: prop4";
2984 QString warning4 = url + ":16: ReferenceError: Can't find variable: prop4";
2985 QString warning5 = url + ":20: ReferenceError: Can't find variable: method2";
2987 QTest::ignoreMessage(QtWarningMsg, warning1.toLatin1().constData());
2988 QTest::ignoreMessage(QtWarningMsg, warning2.toLatin1().constData());
2989 QTest::ignoreMessage(QtWarningMsg, warning3.toLatin1().constData());
2990 QTest::ignoreMessage(QtWarningMsg, warning4.toLatin1().constData());
2991 QTest::ignoreMessage(QtWarningMsg, warning5.toLatin1().constData());
2992 MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create());
2993 QVERIFY(object != 0);
2996 QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevisionErrors3.qml"));
2997 QString url = component.url().toString();
2999 // MyRevisionedSubclass 1.1 uses MyRevisionedClass revision 1
3000 // All properties/methods available, except MyRevisionedBaseClassUnregistered rev 1
3001 QString warning1 = url + ":30: ReferenceError: Can't find variable: methodD";
3002 QString warning2 = url + ":10: ReferenceError: Can't find variable: propD";
3003 QString warning3 = url + ":20: ReferenceError: Can't find variable: propD";
3004 QTest::ignoreMessage(QtWarningMsg, warning1.toLatin1().constData());
3005 QTest::ignoreMessage(QtWarningMsg, warning2.toLatin1().constData());
3006 QTest::ignoreMessage(QtWarningMsg, warning3.toLatin1().constData());
3007 MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create());
3008 QVERIFY(object != 0);
3012 void tst_qdeclarativeecmascript::revision()
3015 QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevision.qml"));
3016 QString url = component.url().toString();
3018 MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create());
3019 QVERIFY(object != 0);
3022 QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevision2.qml"));
3023 QString url = component.url().toString();
3025 MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create());
3026 QVERIFY(object != 0);
3029 QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevision3.qml"));
3030 QString url = component.url().toString();
3032 MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create());
3033 QVERIFY(object != 0);
3035 // Test that non-root classes can resolve revisioned methods
3037 QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevision4.qml"));
3039 QObject *object = component.create();
3040 QVERIFY(object != 0);
3041 QCOMPARE(object->property("test").toReal(), 11.);
3046 // Test for QScriptDeclarativeClass::pushCleanContext()
3047 void tst_qdeclarativeecmascript::pushCleanContext()
3049 QScriptEngine engine;
3050 engine.globalObject().setProperty("a", 6);
3051 QCOMPARE(engine.evaluate("a").toInt32(), 6);
3053 // First confirm pushContext() behaves as we expect
3054 QScriptValue object = engine.newObject();
3055 object.setProperty("a", 15);
3056 QScriptContext *context1 = engine.pushContext();
3057 context1->pushScope(object);
3058 QCOMPARE(engine.evaluate("a").toInt32(), 15);
3060 QScriptContext *context2 = engine.pushContext();
3062 QCOMPARE(engine.evaluate("a").toInt32(), 15);
3063 QScriptValue func1 = engine.evaluate("(function() { return a; })");
3065 // Now check that pushCleanContext() works
3066 QScriptDeclarativeClass::pushCleanContext(&engine);
3067 QCOMPARE(engine.evaluate("a").toInt32(), 6);
3068 QScriptValue func2 = engine.evaluate("(function() { return a; })");
3070 engine.popContext();
3071 QCOMPARE(engine.evaluate("a").toInt32(), 15);
3073 engine.popContext();
3074 QCOMPARE(engine.evaluate("a").toInt32(), 15);
3076 engine.popContext();
3077 QCOMPARE(engine.evaluate("a").toInt32(), 6);
3079 // Check that function objects created in these contexts work
3080 QCOMPARE(func1.call().toInt32(), 15);
3081 QCOMPARE(func2.call().toInt32(), 6);
3084 QTEST_MAIN(tst_qdeclarativeecmascript)
3086 #include "tst_qdeclarativeecmascript.moc"