1 /****************************************************************************
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
7 ** This file is part of the test suite of the Qt Toolkit.
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** GNU Lesser General Public License Usage
11 ** This file may be used under the terms of the GNU Lesser General Public
12 ** License version 2.1 as published by the Free Software Foundation and
13 ** appearing in the file LICENSE.LGPL included in the packaging of this
14 ** file. Please review the following information to ensure the GNU Lesser
15 ** General Public License version 2.1 requirements will be met:
16 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
18 ** In addition, as a special exception, Nokia gives you certain additional
19 ** rights. These rights are described in the Nokia Qt LGPL Exception
20 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
22 ** GNU General Public License Usage
23 ** Alternatively, this file may be used under the terms of the GNU General
24 ** Public License version 3.0 as published by the Free Software Foundation
25 ** and appearing in the file LICENSE.GPL included in the packaging of this
26 ** file. Please review the following information to ensure the GNU General
27 ** Public License version 3.0 requirements will be met:
28 ** http://www.gnu.org/copyleft/gpl.html.
31 ** Alternatively, this file may be used in accordance with the terms and
32 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
42 #include <QtDeclarative/qdeclarativecomponent.h>
43 #include <QtDeclarative/qdeclarativeengine.h>
44 #include <QtDeclarative/qdeclarativeexpression.h>
45 #include <QtDeclarative/qdeclarativecontext.h>
46 #include <QtCore/qfileinfo.h>
47 #include <QtCore/qdebug.h>
48 #include <QtDeclarative/private/qdeclarativeguard_p.h>
49 #include <QtCore/qdir.h>
50 #include <QtCore/qnumeric.h>
51 #include <private/qdeclarativeengine_p.h>
52 #include "testtypes.h"
53 #include "testhttpserver.h"
54 #include "../../../shared/util.h"
57 // In Symbian OS test data is located in applications private dir
62 This test covers evaluation of ECMAScript expressions and bindings from within
63 QML. This does not include static QML language issues.
65 Static QML language issues are covered in qmllanguage
67 inline QUrl TEST_FILE(const QString &filename)
69 QFileInfo fileInfo(__FILE__);
70 return QUrl::fromLocalFile(fileInfo.absoluteDir().filePath("data/" + filename));
73 inline QUrl TEST_FILE(const char *filename)
75 return TEST_FILE(QLatin1String(filename));
78 class tst_qdeclarativeecmascript : public QObject
82 tst_qdeclarativeecmascript() {}
86 void assignBasicTypes();
87 void idShortcutInvalidates();
88 void boolPropertiesEvaluateAsBool();
90 void signalAssignment();
92 void basicExpressions();
93 void basicExpressions_data();
94 void arrayExpressions();
95 void contextPropertiesTriggerReeval();
96 void objectPropertiesTriggerReeval();
97 void deferredProperties();
98 void deferredPropertiesErrors();
99 void extensionObjects();
100 void overrideExtensionProperties();
101 void attachedProperties();
103 void valueTypeFunctions();
104 void constantsOverrideBindings();
105 void outerBindingOverridesInnerBinding();
106 void aliasPropertyAndBinding();
107 void aliasPropertyReset();
108 void nonExistentAttachedObject();
111 void signalParameterTypes();
112 void objectsCompareAsEqual();
113 void dynamicCreation_data();
114 void dynamicCreation();
115 void dynamicDestruction();
116 void objectToString();
117 void objectHasOwnProperty();
118 void selfDeletingBinding();
119 void extendedObjectPropertyLookup();
121 void functionErrors();
122 void propertyAssignmentErrors();
123 void signalTriggeredBindings();
124 void listProperties();
125 void exceptionClearsOnReeval();
126 void exceptionSlotProducesWarning();
127 void exceptionBindingProducesWarning();
128 void transientErrors();
129 void shutdownErrors();
130 void compositePropertyType();
132 void undefinedResetsProperty();
133 void listToVariant();
134 void multiEngineObject();
135 void deletedObject();
136 void attachedPropertyScope();
137 void scriptConnect();
138 void scriptDisconnect();
140 void cppOwnershipReturnValue();
141 void ownershipCustomReturnValue();
142 void qlistqobjectMethods();
143 void strictlyEquals();
145 void numberAssignment();
146 void propertySplicing();
147 void signalWithUnknownTypes();
148 void moduleApi_data();
150 void importScripts();
151 void scarceResources();
152 void propertyChangeSlots();
153 void elementAssign();
154 void objectPassThroughSignals();
155 void booleanConversion();
159 void dynamicCreationCrash();
161 void nullObjectBinding();
162 void deletedEngine();
163 void libraryScriptAssert();
164 void variantsAssignedUndefined();
166 void qtcreatorbug_1289();
167 void noSpuriousWarningsAtShutdown();
168 void canAssignNullToQObject();
169 void functionAssignment_fromBinding();
170 void functionAssignment_fromJS();
171 void functionAssignment_fromJS_data();
172 void functionAssignmentfromJS_invalid();
178 void nonscriptable();
181 void sharedAttachedObject();
183 void writeRemovesBinding();
184 void aliasBindingsAssignCorrectly();
185 void aliasBindingsOverrideTarget();
186 void aliasWritesOverrideBindings();
187 void aliasToCompositeElement();
189 void dynamicString();
192 void callQtInvokables();
193 void invokableObjectArg();
194 void invokableObjectRet();
196 void revisionErrors();
200 QDeclarativeEngine engine;
203 void tst_qdeclarativeecmascript::initTestCase() { registerTypes(); }
205 void tst_qdeclarativeecmascript::assignBasicTypes()
208 QDeclarativeComponent component(&engine, TEST_FILE("assignBasicTypes.qml"));
209 MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
210 QVERIFY(object != 0);
211 QCOMPARE(object->flagProperty(), MyTypeObject::FlagVal1 | MyTypeObject::FlagVal3);
212 QCOMPARE(object->enumProperty(), MyTypeObject::EnumVal2);
213 QCOMPARE(object->stringProperty(), QString("Hello World!"));
214 QCOMPARE(object->uintProperty(), uint(10));
215 QCOMPARE(object->intProperty(), -19);
216 QCOMPARE((float)object->realProperty(), float(23.2));
217 QCOMPARE((float)object->doubleProperty(), float(-19.75));
218 QCOMPARE((float)object->floatProperty(), float(8.5));
219 QCOMPARE(object->colorProperty(), QColor("red"));
220 QCOMPARE(object->dateProperty(), QDate(1982, 11, 25));
221 QCOMPARE(object->timeProperty(), QTime(11, 11, 32));
222 QCOMPARE(object->dateTimeProperty(), QDateTime(QDate(2009, 5, 12), QTime(13, 22, 1)));
223 QCOMPARE(object->pointProperty(), QPoint(99,13));
224 QCOMPARE(object->pointFProperty(), QPointF(-10.1, 12.3));
225 QCOMPARE(object->sizeProperty(), QSize(99, 13));
226 QCOMPARE(object->sizeFProperty(), QSizeF(0.1, 0.2));
227 QCOMPARE(object->rectProperty(), QRect(9, 7, 100, 200));
228 QCOMPARE(object->rectFProperty(), QRectF(1000.1, -10.9, 400, 90.99));
229 QCOMPARE(object->boolProperty(), true);
230 QCOMPARE(object->variantProperty(), QVariant("Hello World!"));
231 QCOMPARE(object->vectorProperty(), QVector3D(10, 1, 2.2));
232 QCOMPARE(object->urlProperty(), component.url().resolved(QUrl("main.qml")));
236 QDeclarativeComponent component(&engine, TEST_FILE("assignBasicTypes.2.qml"));
237 MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
238 QVERIFY(object != 0);
239 QCOMPARE(object->flagProperty(), MyTypeObject::FlagVal1 | MyTypeObject::FlagVal3);
240 QCOMPARE(object->enumProperty(), MyTypeObject::EnumVal2);
241 QCOMPARE(object->stringProperty(), QString("Hello World!"));
242 QCOMPARE(object->uintProperty(), uint(10));
243 QCOMPARE(object->intProperty(), -19);
244 QCOMPARE((float)object->realProperty(), float(23.2));
245 QCOMPARE((float)object->doubleProperty(), float(-19.75));
246 QCOMPARE((float)object->floatProperty(), float(8.5));
247 QCOMPARE(object->colorProperty(), QColor("red"));
248 QCOMPARE(object->dateProperty(), QDate(1982, 11, 25));
249 QCOMPARE(object->timeProperty(), QTime(11, 11, 32));
250 QCOMPARE(object->dateTimeProperty(), QDateTime(QDate(2009, 5, 12), QTime(13, 22, 1)));
251 QCOMPARE(object->pointProperty(), QPoint(99,13));
252 QCOMPARE(object->pointFProperty(), QPointF(-10.1, 12.3));
253 QCOMPARE(object->sizeProperty(), QSize(99, 13));
254 QCOMPARE(object->sizeFProperty(), QSizeF(0.1, 0.2));
255 QCOMPARE(object->rectProperty(), QRect(9, 7, 100, 200));
256 QCOMPARE(object->rectFProperty(), QRectF(1000.1, -10.9, 400, 90.99));
257 QCOMPARE(object->boolProperty(), true);
258 QCOMPARE(object->variantProperty(), QVariant("Hello World!"));
259 QCOMPARE(object->vectorProperty(), QVector3D(10, 1, 2.2));
260 QCOMPARE(object->urlProperty(), component.url().resolved(QUrl("main.qml")));
265 void tst_qdeclarativeecmascript::idShortcutInvalidates()
268 QDeclarativeComponent component(&engine, TEST_FILE("idShortcutInvalidates.qml"));
269 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
270 QVERIFY(object != 0);
271 QVERIFY(object->objectProperty() != 0);
272 delete object->objectProperty();
273 QVERIFY(object->objectProperty() == 0);
278 QDeclarativeComponent component(&engine, TEST_FILE("idShortcutInvalidates.1.qml"));
279 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
280 QVERIFY(object != 0);
281 QVERIFY(object->objectProperty() != 0);
282 delete object->objectProperty();
283 QVERIFY(object->objectProperty() == 0);
288 void tst_qdeclarativeecmascript::boolPropertiesEvaluateAsBool()
291 QDeclarativeComponent component(&engine, TEST_FILE("boolPropertiesEvaluateAsBool.1.qml"));
292 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
293 QVERIFY(object != 0);
294 QCOMPARE(object->stringProperty(), QLatin1String("pass"));
298 QDeclarativeComponent component(&engine, TEST_FILE("boolPropertiesEvaluateAsBool.2.qml"));
299 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
300 QVERIFY(object != 0);
301 QCOMPARE(object->stringProperty(), QLatin1String("pass"));
306 void tst_qdeclarativeecmascript::signalAssignment()
309 QDeclarativeComponent component(&engine, TEST_FILE("signalAssignment.1.qml"));
310 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
311 QVERIFY(object != 0);
312 QCOMPARE(object->string(), QString());
313 emit object->basicSignal();
314 QCOMPARE(object->string(), QString("pass"));
319 QDeclarativeComponent component(&engine, TEST_FILE("signalAssignment.2.qml"));
320 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
321 QVERIFY(object != 0);
322 QCOMPARE(object->string(), QString());
323 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
324 QCOMPARE(object->string(), QString("pass 19 Hello world! 10.25 3 2"));
329 void tst_qdeclarativeecmascript::methods()
332 QDeclarativeComponent component(&engine, TEST_FILE("methods.1.qml"));
333 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
334 QVERIFY(object != 0);
335 QCOMPARE(object->methodCalled(), false);
336 QCOMPARE(object->methodIntCalled(), false);
337 emit object->basicSignal();
338 QCOMPARE(object->methodCalled(), true);
339 QCOMPARE(object->methodIntCalled(), false);
344 QDeclarativeComponent component(&engine, TEST_FILE("methods.2.qml"));
345 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
346 QVERIFY(object != 0);
347 QCOMPARE(object->methodCalled(), false);
348 QCOMPARE(object->methodIntCalled(), false);
349 emit object->basicSignal();
350 QCOMPARE(object->methodCalled(), false);
351 QCOMPARE(object->methodIntCalled(), true);
356 QDeclarativeComponent component(&engine, TEST_FILE("methods.3.qml"));
357 QObject *object = component.create();
358 QVERIFY(object != 0);
359 QCOMPARE(object->property("test").toInt(), 19);
364 QDeclarativeComponent component(&engine, TEST_FILE("methods.4.qml"));
365 QObject *object = component.create();
366 QVERIFY(object != 0);
367 QCOMPARE(object->property("test").toInt(), 19);
368 QCOMPARE(object->property("test2").toInt(), 17);
369 QCOMPARE(object->property("test3").toInt(), 16);
374 QDeclarativeComponent component(&engine, TEST_FILE("methods.5.qml"));
375 QObject *object = component.create();
376 QVERIFY(object != 0);
377 QCOMPARE(object->property("test").toInt(), 9);
382 void tst_qdeclarativeecmascript::bindingLoop()
384 QDeclarativeComponent component(&engine, TEST_FILE("bindingLoop.qml"));
385 QString warning = component.url().toString() + ":9:9: QML MyQmlObject: Binding loop detected for property \"stringProperty\"";
386 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
387 QObject *object = component.create();
388 QVERIFY(object != 0);
392 void tst_qdeclarativeecmascript::basicExpressions_data()
394 QTest::addColumn<QString>("expression");
395 QTest::addColumn<QVariant>("result");
396 QTest::addColumn<bool>("nest");
398 QTest::newRow("Syntax error (self test)") << "{console.log({'a':1'}.a)}" << QVariant() << false;
399 QTest::newRow("Context property") << "a" << QVariant(1944) << false;
400 QTest::newRow("Context property") << "a" << QVariant(1944) << true;
401 QTest::newRow("Context property expression") << "a * 2" << QVariant(3888) << false;
402 QTest::newRow("Context property expression") << "a * 2" << QVariant(3888) << true;
403 QTest::newRow("Overridden context property") << "b" << QVariant("Milk") << false;
404 QTest::newRow("Overridden context property") << "b" << QVariant("Cow") << true;
405 QTest::newRow("Object property") << "object.stringProperty" << QVariant("Object1") << false;
406 QTest::newRow("Object property") << "object.stringProperty" << QVariant("Object1") << true;
407 QTest::newRow("Overridden object property") << "objectOverride.stringProperty" << QVariant("Object2") << false;
408 QTest::newRow("Overridden object property") << "objectOverride.stringProperty" << QVariant("Object3") << true;
409 QTest::newRow("Default object property") << "horseLegs" << QVariant(4) << false;
410 QTest::newRow("Default object property") << "antLegs" << QVariant(6) << false;
411 QTest::newRow("Default object property") << "emuLegs" << QVariant(2) << false;
412 QTest::newRow("Nested default object property") << "horseLegs" << QVariant(4) << true;
413 QTest::newRow("Nested default object property") << "antLegs" << QVariant(7) << true;
414 QTest::newRow("Nested default object property") << "emuLegs" << QVariant(2) << true;
415 QTest::newRow("Nested default object property") << "humanLegs" << QVariant(2) << true;
416 QTest::newRow("Context property override default object property") << "millipedeLegs" << QVariant(100) << true;
419 void tst_qdeclarativeecmascript::basicExpressions()
421 QFETCH(QString, expression);
422 QFETCH(QVariant, result);
428 MyDefaultObject1 default1;
429 MyDefaultObject3 default3;
430 object1.setStringProperty("Object1");
431 object2.setStringProperty("Object2");
432 object3.setStringProperty("Object3");
434 QDeclarativeContext context(engine.rootContext());
435 QDeclarativeContext nestedContext(&context);
437 context.setContextObject(&default1);
438 context.setContextProperty("a", QVariant(1944));
439 context.setContextProperty("b", QVariant("Milk"));
440 context.setContextProperty("object", &object1);
441 context.setContextProperty("objectOverride", &object2);
442 nestedContext.setContextObject(&default3);
443 nestedContext.setContextProperty("b", QVariant("Cow"));
444 nestedContext.setContextProperty("objectOverride", &object3);
445 nestedContext.setContextProperty("millipedeLegs", QVariant(100));
447 MyExpression expr(nest?&nestedContext:&context, expression);
448 QCOMPARE(expr.evaluate(), result);
451 void tst_qdeclarativeecmascript::arrayExpressions()
457 QDeclarativeContext context(engine.rootContext());
458 context.setContextProperty("a", &obj1);
459 context.setContextProperty("b", &obj2);
460 context.setContextProperty("c", &obj3);
462 MyExpression expr(&context, "[a, b, c, 10]");
463 QVariant result = expr.evaluate();
464 QCOMPARE(result.userType(), qMetaTypeId<QList<QObject *> >());
465 QList<QObject *> list = qvariant_cast<QList<QObject *> >(result);
466 QCOMPARE(list.count(), 4);
467 QCOMPARE(list.at(0), &obj1);
468 QCOMPARE(list.at(1), &obj2);
469 QCOMPARE(list.at(2), &obj3);
470 QCOMPARE(list.at(3), (QObject *)0);
473 // Tests that modifying a context property will reevaluate expressions
474 void tst_qdeclarativeecmascript::contextPropertiesTriggerReeval()
476 QDeclarativeContext context(engine.rootContext());
479 MyQmlObject *object3 = new MyQmlObject;
481 object1.setStringProperty("Hello");
482 object2.setStringProperty("World");
484 context.setContextProperty("testProp", QVariant(1));
485 context.setContextProperty("testObj", &object1);
486 context.setContextProperty("testObj2", object3);
489 MyExpression expr(&context, "testProp + 1");
490 QCOMPARE(expr.changed, false);
491 QCOMPARE(expr.evaluate(), QVariant(2));
493 context.setContextProperty("testProp", QVariant(2));
494 QCOMPARE(expr.changed, true);
495 QCOMPARE(expr.evaluate(), QVariant(3));
499 MyExpression expr(&context, "testProp + testProp + testProp");
500 QCOMPARE(expr.changed, false);
501 QCOMPARE(expr.evaluate(), QVariant(6));
503 context.setContextProperty("testProp", QVariant(4));
504 QCOMPARE(expr.changed, true);
505 QCOMPARE(expr.evaluate(), QVariant(12));
509 MyExpression expr(&context, "testObj.stringProperty");
510 QCOMPARE(expr.changed, false);
511 QCOMPARE(expr.evaluate(), QVariant("Hello"));
513 context.setContextProperty("testObj", &object2);
514 QCOMPARE(expr.changed, true);
515 QCOMPARE(expr.evaluate(), QVariant("World"));
519 MyExpression expr(&context, "testObj.stringProperty /**/");
520 QCOMPARE(expr.changed, false);
521 QCOMPARE(expr.evaluate(), QVariant("World"));
523 context.setContextProperty("testObj", &object1);
524 QCOMPARE(expr.changed, true);
525 QCOMPARE(expr.evaluate(), QVariant("Hello"));
529 MyExpression expr(&context, "testObj2");
530 QCOMPARE(expr.changed, false);
531 QCOMPARE(expr.evaluate(), QVariant::fromValue((QObject *)object3));
537 void tst_qdeclarativeecmascript::objectPropertiesTriggerReeval()
539 QDeclarativeContext context(engine.rootContext());
543 context.setContextProperty("testObj", &object1);
545 object1.setStringProperty(QLatin1String("Hello"));
546 object2.setStringProperty(QLatin1String("Dog"));
547 object3.setStringProperty(QLatin1String("Cat"));
550 MyExpression expr(&context, "testObj.stringProperty");
551 QCOMPARE(expr.changed, false);
552 QCOMPARE(expr.evaluate(), QVariant("Hello"));
554 object1.setStringProperty(QLatin1String("World"));
555 QCOMPARE(expr.changed, true);
556 QCOMPARE(expr.evaluate(), QVariant("World"));
560 MyExpression expr(&context, "testObj.objectProperty.stringProperty");
561 QCOMPARE(expr.changed, false);
562 QCOMPARE(expr.evaluate(), QVariant());
564 object1.setObjectProperty(&object2);
565 QCOMPARE(expr.changed, true);
566 expr.changed = false;
567 QCOMPARE(expr.evaluate(), QVariant("Dog"));
569 object1.setObjectProperty(&object3);
570 QCOMPARE(expr.changed, true);
571 expr.changed = false;
572 QCOMPARE(expr.evaluate(), QVariant("Cat"));
574 object1.setObjectProperty(0);
575 QCOMPARE(expr.changed, true);
576 expr.changed = false;
577 QCOMPARE(expr.evaluate(), QVariant());
579 object1.setObjectProperty(&object3);
580 QCOMPARE(expr.changed, true);
581 expr.changed = false;
582 QCOMPARE(expr.evaluate(), QVariant("Cat"));
584 object3.setStringProperty("Donkey");
585 QCOMPARE(expr.changed, true);
586 expr.changed = false;
587 QCOMPARE(expr.evaluate(), QVariant("Donkey"));
591 void tst_qdeclarativeecmascript::deferredProperties()
593 QDeclarativeComponent component(&engine, TEST_FILE("deferredProperties.qml"));
594 MyDeferredObject *object =
595 qobject_cast<MyDeferredObject *>(component.create());
596 QVERIFY(object != 0);
597 QCOMPARE(object->value(), 0);
598 QVERIFY(object->objectProperty() == 0);
599 QVERIFY(object->objectProperty2() != 0);
600 qmlExecuteDeferred(object);
601 QCOMPARE(object->value(), 10);
602 QVERIFY(object->objectProperty() != 0);
603 MyQmlObject *qmlObject =
604 qobject_cast<MyQmlObject *>(object->objectProperty());
605 QVERIFY(qmlObject != 0);
606 QCOMPARE(qmlObject->value(), 10);
607 object->setValue(19);
608 QCOMPARE(qmlObject->value(), 19);
613 // Check errors on deferred properties are correctly emitted
614 void tst_qdeclarativeecmascript::deferredPropertiesErrors()
616 QDeclarativeComponent component(&engine, TEST_FILE("deferredPropertiesErrors.qml"));
617 MyDeferredObject *object =
618 qobject_cast<MyDeferredObject *>(component.create());
619 QVERIFY(object != 0);
620 QCOMPARE(object->value(), 0);
621 QVERIFY(object->objectProperty() == 0);
622 QVERIFY(object->objectProperty2() == 0);
624 QString warning = component.url().toString() + ":6: Unable to assign [undefined] to QObject* objectProperty";
625 QTest::ignoreMessage(QtWarningMsg, qPrintable(warning));
627 qmlExecuteDeferred(object);
632 void tst_qdeclarativeecmascript::extensionObjects()
634 QDeclarativeComponent component(&engine, TEST_FILE("extensionObjects.qml"));
635 MyExtendedObject *object =
636 qobject_cast<MyExtendedObject *>(component.create());
637 QVERIFY(object != 0);
638 QCOMPARE(object->baseProperty(), 13);
639 QCOMPARE(object->coreProperty(), 9);
640 object->setProperty("extendedProperty", QVariant(11));
641 object->setProperty("baseExtendedProperty", QVariant(92));
642 QCOMPARE(object->coreProperty(), 11);
643 QCOMPARE(object->baseProperty(), 92);
645 MyExtendedObject *nested = qobject_cast<MyExtendedObject*>(qvariant_cast<QObject *>(object->property("nested")));
647 QCOMPARE(nested->baseProperty(), 13);
648 QCOMPARE(nested->coreProperty(), 9);
649 nested->setProperty("extendedProperty", QVariant(11));
650 nested->setProperty("baseExtendedProperty", QVariant(92));
651 QCOMPARE(nested->coreProperty(), 11);
652 QCOMPARE(nested->baseProperty(), 92);
657 void tst_qdeclarativeecmascript::overrideExtensionProperties()
659 QDeclarativeComponent component(&engine, TEST_FILE("extensionObjectsPropertyOverride.qml"));
660 OverrideDefaultPropertyObject *object =
661 qobject_cast<OverrideDefaultPropertyObject *>(component.create());
662 QVERIFY(object != 0);
663 QVERIFY(object->secondProperty() != 0);
664 QVERIFY(object->firstProperty() == 0);
669 void tst_qdeclarativeecmascript::attachedProperties()
672 QDeclarativeComponent component(&engine, TEST_FILE("attachedProperty.qml"));
673 QObject *object = component.create();
674 QVERIFY(object != 0);
675 QCOMPARE(object->property("a").toInt(), 19);
676 QCOMPARE(object->property("b").toInt(), 19);
677 QCOMPARE(object->property("c").toInt(), 19);
678 QCOMPARE(object->property("d").toInt(), 19);
683 QDeclarativeComponent component(&engine, TEST_FILE("attachedProperty.2.qml"));
684 QObject *object = component.create();
685 QVERIFY(object != 0);
686 QCOMPARE(object->property("a").toInt(), 26);
687 QCOMPARE(object->property("b").toInt(), 26);
688 QCOMPARE(object->property("c").toInt(), 26);
689 QCOMPARE(object->property("d").toInt(), 26);
693 QDeclarativeComponent component(&engine, TEST_FILE("writeAttachedProperty.qml"));
694 QObject *object = component.create();
695 QVERIFY(object != 0);
697 QMetaObject::invokeMethod(object, "writeValue2");
699 MyQmlAttachedObject *attached =
700 qobject_cast<MyQmlAttachedObject *>(qmlAttachedPropertiesObject<MyQmlObject>(object));
701 QVERIFY(attached != 0);
703 QCOMPARE(attached->value2(), 9);
708 void tst_qdeclarativeecmascript::enums()
712 QDeclarativeComponent component(&engine, TEST_FILE("enums.1.qml"));
713 QObject *object = component.create();
714 QVERIFY(object != 0);
716 QCOMPARE(object->property("a").toInt(), 0);
717 QCOMPARE(object->property("b").toInt(), 1);
718 QCOMPARE(object->property("c").toInt(), 2);
719 QCOMPARE(object->property("d").toInt(), 3);
720 QCOMPARE(object->property("e").toInt(), 0);
721 QCOMPARE(object->property("f").toInt(), 1);
722 QCOMPARE(object->property("g").toInt(), 2);
723 QCOMPARE(object->property("h").toInt(), 3);
724 QCOMPARE(object->property("i").toInt(), 19);
725 QCOMPARE(object->property("j").toInt(), 19);
729 // Non-existent enums
731 QDeclarativeComponent component(&engine, TEST_FILE("enums.2.qml"));
733 QString warning1 = component.url().toString() + ":5: Unable to assign [undefined] to int a";
734 QString warning2 = component.url().toString() + ":6: Unable to assign [undefined] to int b";
735 QTest::ignoreMessage(QtWarningMsg, qPrintable(warning1));
736 QTest::ignoreMessage(QtWarningMsg, qPrintable(warning2));
738 QObject *object = component.create();
739 QVERIFY(object != 0);
740 QCOMPARE(object->property("a").toInt(), 0);
741 QCOMPARE(object->property("b").toInt(), 0);
747 void tst_qdeclarativeecmascript::valueTypeFunctions()
749 QDeclarativeComponent component(&engine, TEST_FILE("valueTypeFunctions.qml"));
750 MyTypeObject *obj = qobject_cast<MyTypeObject*>(component.create());
752 QCOMPARE(obj->rectProperty(), QRect(0,0,100,100));
753 QCOMPARE(obj->rectFProperty(), QRectF(0,0.5,100,99.5));
759 Tests that writing a constant to a property with a binding on it disables the
762 void tst_qdeclarativeecmascript::constantsOverrideBindings()
766 QDeclarativeComponent component(&engine, TEST_FILE("constantsOverrideBindings.1.qml"));
767 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
768 QVERIFY(object != 0);
770 QCOMPARE(object->property("c2").toInt(), 0);
771 object->setProperty("c1", QVariant(9));
772 QCOMPARE(object->property("c2").toInt(), 9);
774 emit object->basicSignal();
776 QCOMPARE(object->property("c2").toInt(), 13);
777 object->setProperty("c1", QVariant(8));
778 QCOMPARE(object->property("c2").toInt(), 13);
783 // During construction
785 QDeclarativeComponent component(&engine, TEST_FILE("constantsOverrideBindings.2.qml"));
786 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
787 QVERIFY(object != 0);
789 QCOMPARE(object->property("c1").toInt(), 0);
790 QCOMPARE(object->property("c2").toInt(), 10);
791 object->setProperty("c1", QVariant(9));
792 QCOMPARE(object->property("c1").toInt(), 9);
793 QCOMPARE(object->property("c2").toInt(), 10);
801 QDeclarativeComponent component(&engine, TEST_FILE("constantsOverrideBindings.3.qml"));
802 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
803 QVERIFY(object != 0);
805 QCOMPARE(object->property("c2").toInt(), 0);
806 object->setProperty("c1", QVariant(9));
807 QCOMPARE(object->property("c2").toInt(), 9);
809 object->setProperty("c2", QVariant(13));
810 QCOMPARE(object->property("c2").toInt(), 13);
811 object->setProperty("c1", QVariant(7));
812 QCOMPARE(object->property("c1").toInt(), 7);
813 QCOMPARE(object->property("c2").toInt(), 13);
821 QDeclarativeComponent component(&engine, TEST_FILE("constantsOverrideBindings.4.qml"));
822 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
823 QVERIFY(object != 0);
825 QCOMPARE(object->property("c1").toInt(), 0);
826 QCOMPARE(object->property("c3").toInt(), 10);
827 object->setProperty("c1", QVariant(9));
828 QCOMPARE(object->property("c1").toInt(), 9);
829 QCOMPARE(object->property("c3").toInt(), 10);
836 Tests that assigning a binding to a property that already has a binding causes
837 the original binding to be disabled.
839 void tst_qdeclarativeecmascript::outerBindingOverridesInnerBinding()
841 QDeclarativeComponent component(&engine,
842 TEST_FILE("outerBindingOverridesInnerBinding.qml"));
843 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
844 QVERIFY(object != 0);
846 QCOMPARE(object->property("c1").toInt(), 0);
847 QCOMPARE(object->property("c2").toInt(), 0);
848 QCOMPARE(object->property("c3").toInt(), 0);
850 object->setProperty("c1", QVariant(9));
851 QCOMPARE(object->property("c1").toInt(), 9);
852 QCOMPARE(object->property("c2").toInt(), 0);
853 QCOMPARE(object->property("c3").toInt(), 0);
855 object->setProperty("c3", QVariant(8));
856 QCOMPARE(object->property("c1").toInt(), 9);
857 QCOMPARE(object->property("c2").toInt(), 8);
858 QCOMPARE(object->property("c3").toInt(), 8);
864 Access a non-existent attached object.
866 Tests for a regression where this used to crash.
868 void tst_qdeclarativeecmascript::nonExistentAttachedObject()
870 QDeclarativeComponent component(&engine, TEST_FILE("nonExistentAttachedObject.qml"));
872 QString warning = component.url().toString() + ":4: Unable to assign [undefined] to QString stringProperty";
873 QTest::ignoreMessage(QtWarningMsg, qPrintable(warning));
875 QObject *object = component.create();
876 QVERIFY(object != 0);
881 void tst_qdeclarativeecmascript::scope()
884 QDeclarativeComponent component(&engine, TEST_FILE("scope.qml"));
885 QObject *object = component.create();
886 QVERIFY(object != 0);
888 QCOMPARE(object->property("test1").toInt(), 1);
889 QCOMPARE(object->property("test2").toInt(), 2);
890 QCOMPARE(object->property("test3").toString(), QString("1Test"));
891 QCOMPARE(object->property("test4").toString(), QString("2Test"));
892 QCOMPARE(object->property("test5").toInt(), 1);
893 QCOMPARE(object->property("test6").toInt(), 1);
894 QCOMPARE(object->property("test7").toInt(), 2);
895 QCOMPARE(object->property("test8").toInt(), 2);
896 QCOMPARE(object->property("test9").toInt(), 1);
897 QCOMPARE(object->property("test10").toInt(), 3);
903 QDeclarativeComponent component(&engine, TEST_FILE("scope.2.qml"));
904 QObject *object = component.create();
905 QVERIFY(object != 0);
907 QCOMPARE(object->property("test1").toInt(), 19);
908 QCOMPARE(object->property("test2").toInt(), 19);
909 QCOMPARE(object->property("test3").toInt(), 14);
910 QCOMPARE(object->property("test4").toInt(), 14);
911 QCOMPARE(object->property("test5").toInt(), 24);
912 QCOMPARE(object->property("test6").toInt(), 24);
918 QDeclarativeComponent component(&engine, TEST_FILE("scope.3.qml"));
919 QObject *object = component.create();
920 QVERIFY(object != 0);
922 QCOMPARE(object->property("test1").toBool(), true);
923 QCOMPARE(object->property("test2").toBool(), true);
924 QCOMPARE(object->property("test3").toBool(), true);
929 // Signal argument scope
931 QDeclarativeComponent component(&engine, TEST_FILE("scope.4.qml"));
932 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
933 QVERIFY(object != 0);
935 QCOMPARE(object->property("test").toInt(), 0);
936 QCOMPARE(object->property("test2").toString(), QString());
938 emit object->argumentSignal(13, "Argument Scope", 9, MyQmlObject::EnumValue4, Qt::RightButton);
940 QCOMPARE(object->property("test").toInt(), 13);
941 QCOMPARE(object->property("test2").toString(), QString("Argument Scope"));
947 QDeclarativeComponent component(&engine, TEST_FILE("scope.5.qml"));
948 QObject *object = component.create();
949 QVERIFY(object != 0);
951 QCOMPARE(object->property("test1").toBool(), true);
952 QCOMPARE(object->property("test2").toBool(), true);
958 QDeclarativeComponent component(&engine, TEST_FILE("scope.6.qml"));
959 QObject *object = component.create();
960 QVERIFY(object != 0);
962 QCOMPARE(object->property("test").toBool(), true);
968 // In 4.7, non-library javascript files that had no imports shared the imports of their
970 void tst_qdeclarativeecmascript::importScope()
972 QDeclarativeComponent component(&engine, TEST_FILE("importScope.qml"));
973 QObject *o = component.create();
976 QCOMPARE(o->property("test").toInt(), 240);
982 Tests that "any" type passes through a synthesized signal parameter. This
983 is essentially a test of QDeclarativeMetaType::copy()
985 void tst_qdeclarativeecmascript::signalParameterTypes()
987 QDeclarativeComponent component(&engine, TEST_FILE("signalParameterTypes.qml"));
988 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
989 QVERIFY(object != 0);
991 emit object->basicSignal();
993 QCOMPARE(object->property("intProperty").toInt(), 10);
994 QCOMPARE(object->property("realProperty").toReal(), 19.2);
995 QVERIFY(object->property("colorProperty").value<QColor>() == QColor(255, 255, 0, 255));
996 QVERIFY(object->property("variantProperty") == QVariant::fromValue(QColor(255, 0, 255, 255)));
997 QVERIFY(object->property("enumProperty") == MyQmlObject::EnumValue3);
998 QVERIFY(object->property("qtEnumProperty") == Qt::LeftButton);
1004 Test that two JS objects for the same QObject compare as equal.
1006 void tst_qdeclarativeecmascript::objectsCompareAsEqual()
1008 QDeclarativeComponent component(&engine, TEST_FILE("objectsCompareAsEqual.qml"));
1009 QObject *object = component.create();
1010 QVERIFY(object != 0);
1012 QCOMPARE(object->property("test1").toBool(), true);
1013 QCOMPARE(object->property("test2").toBool(), true);
1014 QCOMPARE(object->property("test3").toBool(), true);
1015 QCOMPARE(object->property("test4").toBool(), true);
1016 QCOMPARE(object->property("test5").toBool(), true);
1022 Confirm bindings and alias properties can coexist.
1024 Tests for a regression where the binding would not reevaluate.
1026 void tst_qdeclarativeecmascript::aliasPropertyAndBinding()
1028 QDeclarativeComponent component(&engine, TEST_FILE("aliasPropertyAndBinding.qml"));
1029 QObject *object = component.create();
1030 QVERIFY(object != 0);
1032 QCOMPARE(object->property("c2").toInt(), 3);
1033 QCOMPARE(object->property("c3").toInt(), 3);
1035 object->setProperty("c2", QVariant(19));
1037 QCOMPARE(object->property("c2").toInt(), 19);
1038 QCOMPARE(object->property("c3").toInt(), 19);
1044 Ensure that we can write undefined value to an alias property,
1045 and that the aliased property is reset correctly if possible.
1047 void tst_qdeclarativeecmascript::aliasPropertyReset()
1049 QObject *object = 0;
1051 // test that a manual write (of undefined) to a resettable aliased property succeeds
1052 QDeclarativeComponent c1(&engine, TEST_FILE("aliasreset/aliasPropertyReset.1.qml"));
1053 object = c1.create();
1054 QVERIFY(object != 0);
1055 QVERIFY(object->property("sourceComponentAlias").value<QDeclarativeComponent*>() != 0);
1056 QCOMPARE(object->property("aliasIsUndefined"), QVariant(false));
1057 QMetaObject::invokeMethod(object, "resetAliased");
1058 QVERIFY(object->property("sourceComponentAlias").value<QDeclarativeComponent*>() == 0);
1059 QCOMPARE(object->property("aliasIsUndefined"), QVariant(true));
1062 // test that a manual write (of undefined) to a resettable alias property succeeds
1063 QDeclarativeComponent c2(&engine, TEST_FILE("aliasreset/aliasPropertyReset.2.qml"));
1064 object = c2.create();
1065 QVERIFY(object != 0);
1066 QVERIFY(object->property("sourceComponentAlias").value<QDeclarativeComponent*>() != 0);
1067 QCOMPARE(object->property("loaderSourceComponentIsUndefined"), QVariant(false));
1068 QMetaObject::invokeMethod(object, "resetAlias");
1069 QVERIFY(object->property("sourceComponentAlias").value<QDeclarativeComponent*>() == 0);
1070 QCOMPARE(object->property("loaderSourceComponentIsUndefined"), QVariant(true));
1073 // test that an alias to a bound property works correctly
1074 QDeclarativeComponent c3(&engine, TEST_FILE("aliasreset/aliasPropertyReset.3.qml"));
1075 object = c3.create();
1076 QVERIFY(object != 0);
1077 QVERIFY(object->property("sourceComponentAlias").value<QDeclarativeComponent*>() != 0);
1078 QCOMPARE(object->property("loaderOneSourceComponentIsUndefined"), QVariant(false));
1079 QCOMPARE(object->property("loaderTwoSourceComponentIsUndefined"), QVariant(false));
1080 QMetaObject::invokeMethod(object, "resetAlias");
1081 QVERIFY(object->property("sourceComponentAlias").value<QDeclarativeComponent*>() == 0);
1082 QCOMPARE(object->property("loaderOneSourceComponentIsUndefined"), QVariant(true));
1083 QCOMPARE(object->property("loaderTwoSourceComponentIsUndefined"), QVariant(false));
1086 // test that a manual write (of undefined) to a resettable alias property
1087 // whose aliased property's object has been deleted, does not crash.
1088 QDeclarativeComponent c4(&engine, TEST_FILE("aliasreset/aliasPropertyReset.4.qml"));
1089 object = c4.create();
1090 QVERIFY(object != 0);
1091 QVERIFY(object->property("sourceComponentAlias").value<QDeclarativeComponent*>() != 0);
1092 QObject *loader = object->findChild<QObject*>("loader");
1093 QVERIFY(loader != 0);
1095 QVERIFY(object->property("sourceComponentAlias").value<QDeclarativeComponent*>() == 0); // deletion should have caused value unset.
1096 QMetaObject::invokeMethod(object, "resetAlias"); // shouldn't crash.
1097 QVERIFY(object->property("sourceComponentAlias").value<QDeclarativeComponent*>() == 0);
1098 QMetaObject::invokeMethod(object, "setAlias"); // shouldn't crash, and shouldn't change value (since it's no longer referencing anything).
1099 QVERIFY(object->property("sourceComponentAlias").value<QDeclarativeComponent*>() == 0);
1102 // test that binding an alias property to an undefined value works correctly
1103 QDeclarativeComponent c5(&engine, TEST_FILE("aliasreset/aliasPropertyReset.5.qml"));
1104 object = c5.create();
1105 QVERIFY(object != 0);
1106 QVERIFY(object->property("sourceComponentAlias").value<QDeclarativeComponent*>() == 0); // bound to undefined value.
1109 // test that a manual write (of undefined) to a non-resettable property fails properly
1110 QUrl url = TEST_FILE("aliasreset/aliasPropertyReset.error.1.qml");
1111 QString warning1 = url.toString() + QLatin1String(":15: Error: Cannot assign [undefined] to int");
1112 QDeclarativeComponent e1(&engine, url);
1113 object = e1.create();
1114 QVERIFY(object != 0);
1115 QCOMPARE(object->property("intAlias").value<int>(), 12);
1116 QCOMPARE(object->property("aliasedIntIsUndefined"), QVariant(false));
1117 QTest::ignoreMessage(QtWarningMsg, warning1.toLatin1().constData());
1118 QMetaObject::invokeMethod(object, "resetAlias");
1119 QCOMPARE(object->property("intAlias").value<int>(), 12);
1120 QCOMPARE(object->property("aliasedIntIsUndefined"), QVariant(false));
1124 void tst_qdeclarativeecmascript::dynamicCreation_data()
1126 QTest::addColumn<QString>("method");
1127 QTest::addColumn<QString>("createdName");
1129 QTest::newRow("One") << "createOne" << "objectOne";
1130 QTest::newRow("Two") << "createTwo" << "objectTwo";
1131 QTest::newRow("Three") << "createThree" << "objectThree";
1135 Test using createQmlObject to dynamically generate an item
1136 Also using createComponent is tested.
1138 void tst_qdeclarativeecmascript::dynamicCreation()
1140 QFETCH(QString, method);
1141 QFETCH(QString, createdName);
1143 QDeclarativeComponent component(&engine, TEST_FILE("dynamicCreation.qml"));
1144 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1145 QVERIFY(object != 0);
1147 QMetaObject::invokeMethod(object, method.toUtf8());
1148 QObject *created = object->objectProperty();
1150 QCOMPARE(created->objectName(), createdName);
1156 Tests the destroy function
1158 void tst_qdeclarativeecmascript::dynamicDestruction()
1161 QDeclarativeComponent component(&engine, TEST_FILE("dynamicDeletion.qml"));
1162 QDeclarativeGuard<MyQmlObject> object = qobject_cast<MyQmlObject*>(component.create());
1163 QVERIFY(object != 0);
1164 QDeclarativeGuard<QObject> createdQmlObject = 0;
1166 QMetaObject::invokeMethod(object, "create");
1167 createdQmlObject = object->objectProperty();
1168 QVERIFY(createdQmlObject);
1169 QCOMPARE(createdQmlObject->objectName(), QString("emptyObject"));
1171 QMetaObject::invokeMethod(object, "killOther");
1172 QVERIFY(createdQmlObject);
1173 QCoreApplication::instance()->processEvents(QEventLoop::DeferredDeletion);
1174 QVERIFY(createdQmlObject);
1175 for (int ii = 0; createdQmlObject && ii < 50; ++ii) { // After 5 seconds we should give up
1176 if (createdQmlObject) {
1178 QCoreApplication::instance()->processEvents(QEventLoop::DeferredDeletion);
1181 QVERIFY(!createdQmlObject);
1183 QDeclarativeEngine::setObjectOwnership(object, QDeclarativeEngine::JavaScriptOwnership);
1184 QMetaObject::invokeMethod(object, "killMe");
1187 QCoreApplication::instance()->processEvents(QEventLoop::DeferredDeletion);
1192 QDeclarativeComponent component(&engine, TEST_FILE("dynamicDeletion.2.qml"));
1193 QObject *o = component.create();
1196 QVERIFY(qvariant_cast<QObject*>(o->property("objectProperty")) == 0);
1198 QMetaObject::invokeMethod(o, "create");
1200 QVERIFY(qvariant_cast<QObject*>(o->property("objectProperty")) != 0);
1202 QMetaObject::invokeMethod(o, "destroy");
1204 QCoreApplication::instance()->processEvents(QEventLoop::DeferredDeletion);
1206 QVERIFY(qvariant_cast<QObject*>(o->property("objectProperty")) == 0);
1213 tests that id.toString() works
1215 void tst_qdeclarativeecmascript::objectToString()
1217 QDeclarativeComponent component(&engine, TEST_FILE("declarativeToString.qml"));
1218 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1219 QVERIFY(object != 0);
1220 QMetaObject::invokeMethod(object, "testToString");
1221 QVERIFY(object->stringProperty().startsWith("MyQmlObject_QML_"));
1222 QVERIFY(object->stringProperty().endsWith(", \"objName\")"));
1228 tests that id.hasOwnProperty() works
1230 void tst_qdeclarativeecmascript::objectHasOwnProperty()
1232 QUrl url = TEST_FILE("declarativeHasOwnProperty.qml");
1233 QString warning1 = url.toString() + ":59: TypeError: Cannot call method 'hasOwnProperty' of undefined";
1234 QString warning2 = url.toString() + ":64: TypeError: Cannot call method 'hasOwnProperty' of undefined";
1235 QString warning3 = url.toString() + ":69: TypeError: Cannot call method 'hasOwnProperty' of undefined";
1237 QDeclarativeComponent component(&engine, url);
1238 QObject *object = component.create();
1239 QVERIFY(object != 0);
1241 // test QObjects in QML
1242 QMetaObject::invokeMethod(object, "testHasOwnPropertySuccess");
1243 QVERIFY(object->property("result").value<bool>() == true);
1244 QMetaObject::invokeMethod(object, "testHasOwnPropertyFailure");
1245 QVERIFY(object->property("result").value<bool>() == false);
1247 // now test other types in QML
1248 QObject *child = object->findChild<QObject*>("typeObj");
1249 QVERIFY(child != 0);
1250 QMetaObject::invokeMethod(child, "testHasOwnPropertySuccess");
1251 QCOMPARE(child->property("valueTypeHasOwnProperty").toBool(), true);
1252 QCOMPARE(child->property("valueTypeHasOwnProperty2").toBool(), true);
1253 QCOMPARE(child->property("variantTypeHasOwnProperty").toBool(), true);
1254 QCOMPARE(child->property("stringTypeHasOwnProperty").toBool(), true);
1255 QCOMPARE(child->property("listTypeHasOwnProperty").toBool(), true);
1256 QCOMPARE(child->property("emptyListTypeHasOwnProperty").toBool(), true);
1257 QCOMPARE(child->property("enumTypeHasOwnProperty").toBool(), true);
1258 QCOMPARE(child->property("typenameHasOwnProperty").toBool(), true);
1259 QCOMPARE(child->property("typenameHasOwnProperty2").toBool(), true);
1260 QCOMPARE(child->property("moduleApiTypeHasOwnProperty").toBool(), true);
1261 QCOMPARE(child->property("moduleApiPropertyTypeHasOwnProperty").toBool(), true);
1263 QTest::ignoreMessage(QtWarningMsg, warning1.toLatin1().constData());
1264 QMetaObject::invokeMethod(child, "testHasOwnPropertyFailureOne");
1265 QCOMPARE(child->property("enumNonValueHasOwnProperty").toBool(), false);
1266 QTest::ignoreMessage(QtWarningMsg, warning2.toLatin1().constData());
1267 QMetaObject::invokeMethod(child, "testHasOwnPropertyFailureTwo");
1268 QCOMPARE(child->property("moduleApiNonPropertyHasOwnProperty").toBool(), false);
1269 QTest::ignoreMessage(QtWarningMsg, warning3.toLatin1().constData());
1270 QMetaObject::invokeMethod(child, "testHasOwnPropertyFailureThree");
1271 QCOMPARE(child->property("listAtInvalidHasOwnProperty").toBool(), false);
1277 Tests bindings that indirectly cause their own deletion work.
1279 This test is best run under valgrind to ensure no invalid memory access occur.
1281 void tst_qdeclarativeecmascript::selfDeletingBinding()
1284 QDeclarativeComponent component(&engine, TEST_FILE("selfDeletingBinding.qml"));
1285 QObject *object = component.create();
1286 QVERIFY(object != 0);
1287 object->setProperty("triggerDelete", true);
1292 QDeclarativeComponent component(&engine, TEST_FILE("selfDeletingBinding.2.qml"));
1293 QObject *object = component.create();
1294 QVERIFY(object != 0);
1295 object->setProperty("triggerDelete", true);
1301 Test that extended object properties can be accessed.
1303 This test a regression where this used to crash. The issue was specificially
1304 for extended objects that did not include a synthesized meta object (so non-root
1305 and no synthesiszed properties).
1307 void tst_qdeclarativeecmascript::extendedObjectPropertyLookup()
1309 QDeclarativeComponent component(&engine, TEST_FILE("extendedObjectPropertyLookup.qml"));
1310 QObject *object = component.create();
1311 QVERIFY(object != 0);
1316 Test file/lineNumbers for binding/Script errors.
1318 void tst_qdeclarativeecmascript::scriptErrors()
1320 QDeclarativeComponent component(&engine, TEST_FILE("scriptErrors.qml"));
1321 QString url = component.url().toString();
1323 QString warning1 = url.left(url.length() - 3) + "js:2: Error: Invalid write to global property \"a\"";
1324 QString warning2 = url + ":5: ReferenceError: Can't find variable: a";
1325 QString warning3 = url.left(url.length() - 3) + "js:4: Error: Invalid write to global property \"a\"";
1326 QString warning4 = url + ":10: ReferenceError: Can't find variable: a";
1327 QString warning5 = url + ":8: ReferenceError: Can't find variable: a";
1328 QString warning6 = url + ":7: Unable to assign [undefined] to int x";
1329 QString warning7 = url + ":12: Error: Cannot assign to read-only property \"trueProperty\"";
1330 QString warning8 = url + ":13: Error: Cannot assign to non-existent property \"fakeProperty\"";
1332 QTest::ignoreMessage(QtWarningMsg, warning1.toLatin1().constData());
1333 QTest::ignoreMessage(QtWarningMsg, warning2.toLatin1().constData());
1334 QTest::ignoreMessage(QtWarningMsg, warning3.toLatin1().constData());
1335 QTest::ignoreMessage(QtWarningMsg, warning5.toLatin1().constData());
1336 QTest::ignoreMessage(QtWarningMsg, warning6.toLatin1().constData());
1337 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
1338 QVERIFY(object != 0);
1340 QTest::ignoreMessage(QtWarningMsg, warning4.toLatin1().constData());
1341 emit object->basicSignal();
1343 QTest::ignoreMessage(QtWarningMsg, warning7.toLatin1().constData());
1344 emit object->anotherBasicSignal();
1346 QTest::ignoreMessage(QtWarningMsg, warning8.toLatin1().constData());
1347 emit object->thirdBasicSignal();
1353 Test file/lineNumbers for inline functions.
1355 void tst_qdeclarativeecmascript::functionErrors()
1357 QDeclarativeComponent component(&engine, TEST_FILE("functionErrors.qml"));
1358 QString url = component.url().toString();
1360 QString warning = url + ":5: Error: Invalid write to global property \"a\"";
1362 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
1364 QObject *object = component.create();
1365 QVERIFY(object != 0);
1368 // test that if an exception occurs while invoking js function from cpp, it is reported as expected.
1369 QDeclarativeComponent componentTwo(&engine, TEST_FILE("scarceresources/scarceResourceFunctionFail.qml"));
1370 url = componentTwo.url().toString();
1371 object = componentTwo.create();
1372 QVERIFY(object != 0);
1374 QString srpname = object->property("srp_name").toString();
1376 warning = url + QLatin1String(":17: TypeError: Property 'scarceResource' of object ") + srpname +
1377 QLatin1String(" is not a function");
1378 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData()); // we expect a meaningful warning to be printed.
1379 QMetaObject::invokeMethod(object, "retrieveScarceResource");
1384 Test various errors that can occur when assigning a property from script
1386 void tst_qdeclarativeecmascript::propertyAssignmentErrors()
1388 QDeclarativeComponent component(&engine, TEST_FILE("propertyAssignmentErrors.qml"));
1390 QString url = component.url().toString();
1392 QObject *object = component.create();
1393 QVERIFY(object != 0);
1395 QCOMPARE(object->property("test1").toBool(), true);
1396 QCOMPARE(object->property("test2").toBool(), true);
1402 Test bindings still work when the reeval is triggered from within
1405 void tst_qdeclarativeecmascript::signalTriggeredBindings()
1407 QDeclarativeComponent component(&engine, TEST_FILE("signalTriggeredBindings.qml"));
1408 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1409 QVERIFY(object != 0);
1411 QCOMPARE(object->property("base").toReal(), 50.);
1412 QCOMPARE(object->property("test1").toReal(), 50.);
1413 QCOMPARE(object->property("test2").toReal(), 50.);
1415 object->basicSignal();
1417 QCOMPARE(object->property("base").toReal(), 200.);
1418 QCOMPARE(object->property("test1").toReal(), 200.);
1419 QCOMPARE(object->property("test2").toReal(), 200.);
1421 object->argumentSignal(10, QString(), 10, MyQmlObject::EnumValue4, Qt::RightButton);
1423 QCOMPARE(object->property("base").toReal(), 400.);
1424 QCOMPARE(object->property("test1").toReal(), 400.);
1425 QCOMPARE(object->property("test2").toReal(), 400.);
1431 Test that list properties can be iterated from ECMAScript
1433 void tst_qdeclarativeecmascript::listProperties()
1435 QDeclarativeComponent component(&engine, TEST_FILE("listProperties.qml"));
1436 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1437 QVERIFY(object != 0);
1439 QCOMPARE(object->property("test1").toInt(), 21);
1440 QCOMPARE(object->property("test2").toInt(), 2);
1441 QCOMPARE(object->property("test3").toBool(), true);
1442 QCOMPARE(object->property("test4").toBool(), true);
1447 void tst_qdeclarativeecmascript::exceptionClearsOnReeval()
1449 QDeclarativeComponent component(&engine, TEST_FILE("exceptionClearsOnReeval.qml"));
1450 QString url = component.url().toString();
1452 QString warning = url + ":4: TypeError: Cannot read property 'objectProperty' of null";
1454 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
1455 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1456 QVERIFY(object != 0);
1458 QCOMPARE(object->property("test").toBool(), false);
1460 MyQmlObject object2;
1461 MyQmlObject object3;
1462 object2.setObjectProperty(&object3);
1463 object->setObjectProperty(&object2);
1465 QCOMPARE(object->property("test").toBool(), true);
1470 void tst_qdeclarativeecmascript::exceptionSlotProducesWarning()
1472 QDeclarativeComponent component(&engine, TEST_FILE("exceptionProducesWarning.qml"));
1473 QString url = component.url().toString();
1475 QString warning = component.url().toString() + ":6: Error: JS exception";
1477 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
1478 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1479 QVERIFY(object != 0);
1483 void tst_qdeclarativeecmascript::exceptionBindingProducesWarning()
1485 QDeclarativeComponent component(&engine, TEST_FILE("exceptionProducesWarning2.qml"));
1486 QString url = component.url().toString();
1488 QString warning = component.url().toString() + ":5: Error: JS exception";
1490 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
1491 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1492 QVERIFY(object != 0);
1496 static int transientErrorsMsgCount = 0;
1497 static void transientErrorsMsgHandler(QtMsgType, const char *)
1499 ++transientErrorsMsgCount;
1502 // Check that transient binding errors are not displayed
1503 void tst_qdeclarativeecmascript::transientErrors()
1506 QDeclarativeComponent component(&engine, TEST_FILE("transientErrors.qml"));
1508 transientErrorsMsgCount = 0;
1509 QtMsgHandler old = qInstallMsgHandler(transientErrorsMsgHandler);
1511 QObject *object = component.create();
1512 QVERIFY(object != 0);
1514 qInstallMsgHandler(old);
1516 QCOMPARE(transientErrorsMsgCount, 0);
1521 // One binding erroring multiple times, but then resolving
1523 QDeclarativeComponent component(&engine, TEST_FILE("transientErrors.2.qml"));
1525 transientErrorsMsgCount = 0;
1526 QtMsgHandler old = qInstallMsgHandler(transientErrorsMsgHandler);
1528 QObject *object = component.create();
1529 QVERIFY(object != 0);
1531 qInstallMsgHandler(old);
1533 QCOMPARE(transientErrorsMsgCount, 0);
1539 // Check that errors during shutdown are minimized
1540 void tst_qdeclarativeecmascript::shutdownErrors()
1542 QDeclarativeComponent component(&engine, TEST_FILE("shutdownErrors.qml"));
1543 QObject *object = component.create();
1544 QVERIFY(object != 0);
1546 transientErrorsMsgCount = 0;
1547 QtMsgHandler old = qInstallMsgHandler(transientErrorsMsgHandler);
1551 qInstallMsgHandler(old);
1552 QCOMPARE(transientErrorsMsgCount, 0);
1555 void tst_qdeclarativeecmascript::compositePropertyType()
1557 QDeclarativeComponent component(&engine, TEST_FILE("compositePropertyType.qml"));
1558 QTest::ignoreMessage(QtDebugMsg, "hello world");
1559 QObject *object = qobject_cast<QObject *>(component.create());
1564 void tst_qdeclarativeecmascript::jsObject()
1566 QDeclarativeComponent component(&engine, TEST_FILE("jsObject.qml"));
1567 QObject *object = component.create();
1568 QVERIFY(object != 0);
1570 QCOMPARE(object->property("test").toInt(), 92);
1575 void tst_qdeclarativeecmascript::undefinedResetsProperty()
1578 QDeclarativeComponent component(&engine, TEST_FILE("undefinedResetsProperty.qml"));
1579 QObject *object = component.create();
1580 QVERIFY(object != 0);
1582 QCOMPARE(object->property("resettableProperty").toInt(), 92);
1584 object->setProperty("setUndefined", true);
1586 QCOMPARE(object->property("resettableProperty").toInt(), 13);
1588 object->setProperty("setUndefined", false);
1590 QCOMPARE(object->property("resettableProperty").toInt(), 92);
1595 QDeclarativeComponent component(&engine, TEST_FILE("undefinedResetsProperty.2.qml"));
1596 QObject *object = component.create();
1597 QVERIFY(object != 0);
1599 QCOMPARE(object->property("resettableProperty").toInt(), 19);
1601 QMetaObject::invokeMethod(object, "doReset");
1603 QCOMPARE(object->property("resettableProperty").toInt(), 13);
1610 void tst_qdeclarativeecmascript::bug1()
1612 QDeclarativeComponent component(&engine, TEST_FILE("bug.1.qml"));
1613 QObject *object = component.create();
1614 QVERIFY(object != 0);
1616 QCOMPARE(object->property("test").toInt(), 14);
1618 object->setProperty("a", 11);
1620 QCOMPARE(object->property("test").toInt(), 3);
1622 object->setProperty("b", true);
1624 QCOMPARE(object->property("test").toInt(), 9);
1629 void tst_qdeclarativeecmascript::bug2()
1631 QDeclarativeComponent component(&engine);
1632 component.setData("import Qt.test 1.0;\nQPlainTextEdit { width: 100 }", QUrl());
1634 QObject *object = component.create();
1635 QVERIFY(object != 0);
1640 // Don't crash in createObject when the component has errors.
1641 void tst_qdeclarativeecmascript::dynamicCreationCrash()
1643 QDeclarativeComponent component(&engine, TEST_FILE("dynamicCreation.qml"));
1644 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1645 QVERIFY(object != 0);
1647 QTest::ignoreMessage(QtWarningMsg, "QDeclarativeComponent: Component is not ready");
1648 QMetaObject::invokeMethod(object, "dontCrash");
1649 QObject *created = object->objectProperty();
1650 QVERIFY(created == 0);
1656 void tst_qdeclarativeecmascript::regExpBug()
1658 QDeclarativeComponent component(&engine, TEST_FILE("regExp.qml"));
1659 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1660 QVERIFY(object != 0);
1661 QCOMPARE(object->regExp().pattern(), QLatin1String("[a-zA-z]"));
1665 static inline bool evaluate_error(QV8Engine *engine, v8::Handle<v8::Object> o, const char *source)
1667 QString functionSource = QLatin1String("(function(object) { return ") +
1668 QLatin1String(source) + QLatin1String(" })");
1670 v8::Local<v8::Script> program = v8::Script::Compile(engine->toString(functionSource));
1673 v8::Handle<v8::Function> function = v8::Handle<v8::Function>::Cast(program->Run());
1674 if (function.IsEmpty())
1676 v8::Handle<v8::Value> args[] = { o };
1677 function->Call(engine->global(), 1, args);
1678 return tc.HasCaught();
1681 static inline bool evaluate_value(QV8Engine *engine, v8::Handle<v8::Object> o,
1682 const char *source, v8::Handle<v8::Value> result)
1684 QString functionSource = QLatin1String("(function(object) { return ") +
1685 QLatin1String(source) + QLatin1String(" })");
1687 v8::Local<v8::Script> program = v8::Script::Compile(engine->toString(functionSource));
1690 v8::Handle<v8::Function> function = v8::Handle<v8::Function>::Cast(program->Run());
1691 if (function.IsEmpty())
1693 v8::Handle<v8::Value> args[] = { o };
1695 v8::Handle<v8::Value> value = function->Call(engine->global(), 1, args);
1700 return value->StrictEquals(result);
1703 static inline v8::Handle<v8::Value> evaluate(QV8Engine *engine, v8::Handle<v8::Object> o,
1706 QString functionSource = QLatin1String("(function(object) { return ") +
1707 QLatin1String(source) + QLatin1String(" })");
1709 v8::Local<v8::Script> program = v8::Script::Compile(engine->toString(functionSource));
1711 return v8::Handle<v8::Value>();
1712 v8::Handle<v8::Function> function = v8::Handle<v8::Function>::Cast(program->Run());
1713 if (function.IsEmpty())
1714 return v8::Handle<v8::Value>();
1715 v8::Handle<v8::Value> args[] = { o };
1717 v8::Handle<v8::Value> value = function->Call(engine->global(), 1, args);
1720 return v8::Handle<v8::Value>();
1724 #define EVALUATE_ERROR(source) evaluate_error(engine, object, source)
1725 #define EVALUATE_VALUE(source, result) evaluate_value(engine, object, source, result)
1726 #define EVALUATE(source) evaluate(engine, object, source)
1728 void tst_qdeclarativeecmascript::callQtInvokables()
1730 MyInvokableObject o;
1732 QDeclarativeEngine qmlengine;
1733 QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(&qmlengine);
1735 QV8Engine *engine = ep->v8engine();
1737 v8::HandleScope handle_scope;
1738 v8::Context::Scope scope(engine->context());
1740 v8::Local<v8::Object> object = engine->newQObject(&o)->ToObject();
1742 // Non-existent methods
1744 QVERIFY(EVALUATE_ERROR("object.method_nonexistent()"));
1745 QCOMPARE(o.error(), false);
1746 QCOMPARE(o.invoked(), -1);
1747 QCOMPARE(o.actuals().count(), 0);
1750 QVERIFY(EVALUATE_ERROR("object.method_nonexistent(10, 11)"));
1751 QCOMPARE(o.error(), false);
1752 QCOMPARE(o.invoked(), -1);
1753 QCOMPARE(o.actuals().count(), 0);
1755 // Insufficient arguments
1757 QVERIFY(EVALUATE_ERROR("object.method_int()"));
1758 QCOMPARE(o.error(), false);
1759 QCOMPARE(o.invoked(), -1);
1760 QCOMPARE(o.actuals().count(), 0);
1763 QVERIFY(EVALUATE_ERROR("object.method_intint(10)"));
1764 QCOMPARE(o.error(), false);
1765 QCOMPARE(o.invoked(), -1);
1766 QCOMPARE(o.actuals().count(), 0);
1768 // Excessive arguments
1770 QVERIFY(EVALUATE_VALUE("object.method_int(10, 11)", v8::Undefined()));
1771 QCOMPARE(o.error(), false);
1772 QCOMPARE(o.invoked(), 8);
1773 QCOMPARE(o.actuals().count(), 1);
1774 QCOMPARE(o.actuals().at(0), QVariant(10));
1777 QVERIFY(EVALUATE_VALUE("object.method_intint(10, 11, 12)", v8::Undefined()));
1778 QCOMPARE(o.error(), false);
1779 QCOMPARE(o.invoked(), 9);
1780 QCOMPARE(o.actuals().count(), 2);
1781 QCOMPARE(o.actuals().at(0), QVariant(10));
1782 QCOMPARE(o.actuals().at(1), QVariant(11));
1784 // Test return types
1786 QVERIFY(EVALUATE_VALUE("object.method_NoArgs()", v8::Undefined()));
1787 QCOMPARE(o.error(), false);
1788 QCOMPARE(o.invoked(), 0);
1789 QCOMPARE(o.actuals().count(), 0);
1792 QVERIFY(EVALUATE_VALUE("object.method_NoArgs_int()", v8::Integer::New(6)));
1793 QCOMPARE(o.error(), false);
1794 QCOMPARE(o.invoked(), 1);
1795 QCOMPARE(o.actuals().count(), 0);
1798 QVERIFY(EVALUATE_VALUE("object.method_NoArgs_real()", v8::Number::New(19.75)));
1799 QCOMPARE(o.error(), false);
1800 QCOMPARE(o.invoked(), 2);
1801 QCOMPARE(o.actuals().count(), 0);
1805 v8::Handle<v8::Value> ret = EVALUATE("object.method_NoArgs_QPointF()");
1806 QVERIFY(!ret.IsEmpty());
1807 QCOMPARE(engine->toVariant(ret, -1), QVariant(QPointF(123, 4.5)));
1808 QCOMPARE(o.error(), false);
1809 QCOMPARE(o.invoked(), 3);
1810 QCOMPARE(o.actuals().count(), 0);
1815 v8::Handle<v8::Value> ret = EVALUATE("object.method_NoArgs_QObject()");
1816 QCOMPARE(engine->toQObject(ret), (QObject *)&o);
1817 QCOMPARE(o.error(), false);
1818 QCOMPARE(o.invoked(), 4);
1819 QCOMPARE(o.actuals().count(), 0);
1823 QVERIFY(EVALUATE_VALUE("object.method_NoArgs_unknown()", v8::Undefined()));
1824 QCOMPARE(o.error(), false);
1825 QCOMPARE(o.invoked(), 5);
1826 QCOMPARE(o.actuals().count(), 0);
1830 v8::Handle<v8::Value> ret = EVALUATE("object.method_NoArgs_QScriptValue()");
1831 QVERIFY(ret->IsString());
1832 QCOMPARE(engine->toString(ret), QString("Hello world"));
1833 QCOMPARE(o.error(), false);
1834 QCOMPARE(o.invoked(), 6);
1835 QCOMPARE(o.actuals().count(), 0);
1839 QVERIFY(EVALUATE_VALUE("object.method_NoArgs_QVariant()", engine->toString("QML rocks")));
1840 QCOMPARE(o.error(), false);
1841 QCOMPARE(o.invoked(), 7);
1842 QCOMPARE(o.actuals().count(), 0);
1846 QVERIFY(EVALUATE_VALUE("object.method_int(94)", v8::Undefined()));
1847 QCOMPARE(o.error(), false);
1848 QCOMPARE(o.invoked(), 8);
1849 QCOMPARE(o.actuals().count(), 1);
1850 QCOMPARE(o.actuals().at(0), QVariant(94));
1853 QVERIFY(EVALUATE_VALUE("object.method_int(\"94\")", v8::Undefined()));
1854 QCOMPARE(o.error(), false);
1855 QCOMPARE(o.invoked(), 8);
1856 QCOMPARE(o.actuals().count(), 1);
1857 QCOMPARE(o.actuals().at(0), QVariant(94));
1860 QVERIFY(EVALUATE_VALUE("object.method_int(\"not a number\")", v8::Undefined()));
1861 QCOMPARE(o.error(), false);
1862 QCOMPARE(o.invoked(), 8);
1863 QCOMPARE(o.actuals().count(), 1);
1864 QCOMPARE(o.actuals().at(0), QVariant(0));
1867 QVERIFY(EVALUATE_VALUE("object.method_int(null)", v8::Undefined()));
1868 QCOMPARE(o.error(), false);
1869 QCOMPARE(o.invoked(), 8);
1870 QCOMPARE(o.actuals().count(), 1);
1871 QCOMPARE(o.actuals().at(0), QVariant(0));
1874 QVERIFY(EVALUATE_VALUE("object.method_int(undefined)", v8::Undefined()));
1875 QCOMPARE(o.error(), false);
1876 QCOMPARE(o.invoked(), 8);
1877 QCOMPARE(o.actuals().count(), 1);
1878 QCOMPARE(o.actuals().at(0), QVariant(0));
1881 QVERIFY(EVALUATE_VALUE("object.method_int(object)", v8::Undefined()));
1882 QCOMPARE(o.error(), false);
1883 QCOMPARE(o.invoked(), 8);
1884 QCOMPARE(o.actuals().count(), 1);
1885 QCOMPARE(o.actuals().at(0), QVariant(0));
1888 QVERIFY(EVALUATE_VALUE("object.method_intint(122, 9)", v8::Undefined()));
1889 QCOMPARE(o.error(), false);
1890 QCOMPARE(o.invoked(), 9);
1891 QCOMPARE(o.actuals().count(), 2);
1892 QCOMPARE(o.actuals().at(0), QVariant(122));
1893 QCOMPARE(o.actuals().at(1), QVariant(9));
1896 QVERIFY(EVALUATE_VALUE("object.method_real(94.3)", v8::Undefined()));
1897 QCOMPARE(o.error(), false);
1898 QCOMPARE(o.invoked(), 10);
1899 QCOMPARE(o.actuals().count(), 1);
1900 QCOMPARE(o.actuals().at(0), QVariant(94.3));
1903 QVERIFY(EVALUATE_VALUE("object.method_real(\"94.3\")", v8::Undefined()));
1904 QCOMPARE(o.error(), false);
1905 QCOMPARE(o.invoked(), 10);
1906 QCOMPARE(o.actuals().count(), 1);
1907 QCOMPARE(o.actuals().at(0), QVariant(94.3));
1910 QVERIFY(EVALUATE_VALUE("object.method_real(\"not a number\")", v8::Undefined()));
1911 QCOMPARE(o.error(), false);
1912 QCOMPARE(o.invoked(), 10);
1913 QCOMPARE(o.actuals().count(), 1);
1914 QVERIFY(qIsNaN(o.actuals().at(0).toDouble()));
1917 QVERIFY(EVALUATE_VALUE("object.method_real(null)", v8::Undefined()));
1918 QCOMPARE(o.error(), false);
1919 QCOMPARE(o.invoked(), 10);
1920 QCOMPARE(o.actuals().count(), 1);
1921 QCOMPARE(o.actuals().at(0), QVariant(0));
1924 QVERIFY(EVALUATE_VALUE("object.method_real(undefined)", v8::Undefined()));
1925 QCOMPARE(o.error(), false);
1926 QCOMPARE(o.invoked(), 10);
1927 QCOMPARE(o.actuals().count(), 1);
1928 QVERIFY(qIsNaN(o.actuals().at(0).toDouble()));
1931 QVERIFY(EVALUATE_VALUE("object.method_real(object)", v8::Undefined()));
1932 QCOMPARE(o.error(), false);
1933 QCOMPARE(o.invoked(), 10);
1934 QCOMPARE(o.actuals().count(), 1);
1935 QVERIFY(qIsNaN(o.actuals().at(0).toDouble()));
1938 QVERIFY(EVALUATE_VALUE("object.method_QString(\"Hello world\")", v8::Undefined()));
1939 QCOMPARE(o.error(), false);
1940 QCOMPARE(o.invoked(), 11);
1941 QCOMPARE(o.actuals().count(), 1);
1942 QCOMPARE(o.actuals().at(0), QVariant("Hello world"));
1945 QVERIFY(EVALUATE_VALUE("object.method_QString(19)", v8::Undefined()));
1946 QCOMPARE(o.error(), false);
1947 QCOMPARE(o.invoked(), 11);
1948 QCOMPARE(o.actuals().count(), 1);
1949 QCOMPARE(o.actuals().at(0), QVariant("19"));
1953 QString expected = "MyInvokableObject(0x" + QString::number((quintptr)&o, 16) + ")";
1954 QVERIFY(EVALUATE_VALUE("object.method_QString(object)", v8::Undefined()));
1955 QCOMPARE(o.error(), false);
1956 QCOMPARE(o.invoked(), 11);
1957 QCOMPARE(o.actuals().count(), 1);
1958 QCOMPARE(o.actuals().at(0), QVariant(expected));
1962 QVERIFY(EVALUATE_VALUE("object.method_QString(null)", v8::Undefined()));
1963 QCOMPARE(o.error(), false);
1964 QCOMPARE(o.invoked(), 11);
1965 QCOMPARE(o.actuals().count(), 1);
1966 QCOMPARE(o.actuals().at(0), QVariant(QString()));
1969 QVERIFY(EVALUATE_VALUE("object.method_QString(undefined)", v8::Undefined()));
1970 QCOMPARE(o.error(), false);
1971 QCOMPARE(o.invoked(), 11);
1972 QCOMPARE(o.actuals().count(), 1);
1973 QCOMPARE(o.actuals().at(0), QVariant(QString()));
1976 QVERIFY(EVALUATE_VALUE("object.method_QPointF(0)", v8::Undefined()));
1977 QCOMPARE(o.error(), false);
1978 QCOMPARE(o.invoked(), 12);
1979 QCOMPARE(o.actuals().count(), 1);
1980 QCOMPARE(o.actuals().at(0), QVariant(QPointF()));
1983 QVERIFY(EVALUATE_VALUE("object.method_QPointF(null)", v8::Undefined()));
1984 QCOMPARE(o.error(), false);
1985 QCOMPARE(o.invoked(), 12);
1986 QCOMPARE(o.actuals().count(), 1);
1987 QCOMPARE(o.actuals().at(0), QVariant(QPointF()));
1990 QVERIFY(EVALUATE_VALUE("object.method_QPointF(undefined)", v8::Undefined()));
1991 QCOMPARE(o.error(), false);
1992 QCOMPARE(o.invoked(), 12);
1993 QCOMPARE(o.actuals().count(), 1);
1994 QCOMPARE(o.actuals().at(0), QVariant(QPointF()));
1997 QVERIFY(EVALUATE_VALUE("object.method_QPointF(object)", v8::Undefined()));
1998 QCOMPARE(o.error(), false);
1999 QCOMPARE(o.invoked(), 12);
2000 QCOMPARE(o.actuals().count(), 1);
2001 QCOMPARE(o.actuals().at(0), QVariant(QPointF()));
2004 QVERIFY(EVALUATE_VALUE("object.method_QPointF(object.method_get_QPointF())", v8::Undefined()));
2005 QCOMPARE(o.error(), false);
2006 QCOMPARE(o.invoked(), 12);
2007 QCOMPARE(o.actuals().count(), 1);
2008 QCOMPARE(o.actuals().at(0), QVariant(QPointF(99.3, -10.2)));
2011 QVERIFY(EVALUATE_VALUE("object.method_QPointF(object.method_get_QPoint())", v8::Undefined()));
2012 QCOMPARE(o.error(), false);
2013 QCOMPARE(o.invoked(), 12);
2014 QCOMPARE(o.actuals().count(), 1);
2015 QCOMPARE(o.actuals().at(0), QVariant(QPointF(9, 12)));
2018 QVERIFY(EVALUATE_VALUE("object.method_QObject(0)", v8::Undefined()));
2019 QCOMPARE(o.error(), false);
2020 QCOMPARE(o.invoked(), 13);
2021 QCOMPARE(o.actuals().count(), 1);
2022 QCOMPARE(o.actuals().at(0), qVariantFromValue((QObject *)0));
2025 QVERIFY(EVALUATE_VALUE("object.method_QObject(\"Hello world\")", v8::Undefined()));
2026 QCOMPARE(o.error(), false);
2027 QCOMPARE(o.invoked(), 13);
2028 QCOMPARE(o.actuals().count(), 1);
2029 QCOMPARE(o.actuals().at(0), qVariantFromValue((QObject *)0));
2032 QVERIFY(EVALUATE_VALUE("object.method_QObject(null)", v8::Undefined()));
2033 QCOMPARE(o.error(), false);
2034 QCOMPARE(o.invoked(), 13);
2035 QCOMPARE(o.actuals().count(), 1);
2036 QCOMPARE(o.actuals().at(0), qVariantFromValue((QObject *)0));
2039 QVERIFY(EVALUATE_VALUE("object.method_QObject(undefined)", v8::Undefined()));
2040 QCOMPARE(o.error(), false);
2041 QCOMPARE(o.invoked(), 13);
2042 QCOMPARE(o.actuals().count(), 1);
2043 QCOMPARE(o.actuals().at(0), qVariantFromValue((QObject *)0));
2046 QVERIFY(EVALUATE_VALUE("object.method_QObject(object)", v8::Undefined()));
2047 QCOMPARE(o.error(), false);
2048 QCOMPARE(o.invoked(), 13);
2049 QCOMPARE(o.actuals().count(), 1);
2050 QCOMPARE(o.actuals().at(0), qVariantFromValue((QObject *)&o));
2053 QVERIFY(EVALUATE_VALUE("object.method_QScriptValue(null)", v8::Undefined()));
2054 QCOMPARE(o.error(), false);
2055 QCOMPARE(o.invoked(), 14);
2056 QCOMPARE(o.actuals().count(), 1);
2057 QVERIFY(qvariant_cast<QJSValue>(o.actuals().at(0)).isNull());
2060 QVERIFY(EVALUATE_VALUE("object.method_QScriptValue(undefined)", v8::Undefined()));
2061 QCOMPARE(o.error(), false);
2062 QCOMPARE(o.invoked(), 14);
2063 QCOMPARE(o.actuals().count(), 1);
2064 QVERIFY(qvariant_cast<QJSValue>(o.actuals().at(0)).isUndefined());
2067 QVERIFY(EVALUATE_VALUE("object.method_QScriptValue(19)", v8::Undefined()));
2068 QCOMPARE(o.error(), false);
2069 QCOMPARE(o.invoked(), 14);
2070 QCOMPARE(o.actuals().count(), 1);
2071 QVERIFY(qvariant_cast<QJSValue>(o.actuals().at(0)).strictlyEquals(QJSValue(19)));
2074 QVERIFY(EVALUATE_VALUE("object.method_QScriptValue([19, 20])", v8::Undefined()));
2075 QCOMPARE(o.error(), false);
2076 QCOMPARE(o.invoked(), 14);
2077 QCOMPARE(o.actuals().count(), 1);
2078 QVERIFY(qvariant_cast<QJSValue>(o.actuals().at(0)).isArray());
2081 QVERIFY(EVALUATE_VALUE("object.method_intQScriptValue(4, null)", v8::Undefined()));
2082 QCOMPARE(o.error(), false);
2083 QCOMPARE(o.invoked(), 15);
2084 QCOMPARE(o.actuals().count(), 2);
2085 QCOMPARE(o.actuals().at(0), QVariant(4));
2086 QVERIFY(qvariant_cast<QJSValue>(o.actuals().at(1)).isNull());
2089 QVERIFY(EVALUATE_VALUE("object.method_intQScriptValue(8, undefined)", v8::Undefined()));
2090 QCOMPARE(o.error(), false);
2091 QCOMPARE(o.invoked(), 15);
2092 QCOMPARE(o.actuals().count(), 2);
2093 QCOMPARE(o.actuals().at(0), QVariant(8));
2094 QVERIFY(qvariant_cast<QJSValue>(o.actuals().at(1)).isUndefined());
2097 QVERIFY(EVALUATE_VALUE("object.method_intQScriptValue(3, 19)", v8::Undefined()));
2098 QCOMPARE(o.error(), false);
2099 QCOMPARE(o.invoked(), 15);
2100 QCOMPARE(o.actuals().count(), 2);
2101 QCOMPARE(o.actuals().at(0), QVariant(3));
2102 QVERIFY(qvariant_cast<QJSValue>(o.actuals().at(1)).strictlyEquals(QJSValue(19)));
2105 QVERIFY(EVALUATE_VALUE("object.method_intQScriptValue(44, [19, 20])", v8::Undefined()));
2106 QCOMPARE(o.error(), false);
2107 QCOMPARE(o.invoked(), 15);
2108 QCOMPARE(o.actuals().count(), 2);
2109 QCOMPARE(o.actuals().at(0), QVariant(44));
2110 QVERIFY(qvariant_cast<QJSValue>(o.actuals().at(1)).isArray());
2113 QVERIFY(EVALUATE_ERROR("object.method_overload()"));
2114 QCOMPARE(o.error(), false);
2115 QCOMPARE(o.invoked(), -1);
2116 QCOMPARE(o.actuals().count(), 0);
2119 QVERIFY(EVALUATE_VALUE("object.method_overload(10)", v8::Undefined()));
2120 QCOMPARE(o.error(), false);
2121 QCOMPARE(o.invoked(), 16);
2122 QCOMPARE(o.actuals().count(), 1);
2123 QCOMPARE(o.actuals().at(0), QVariant(10));
2126 QVERIFY(EVALUATE_VALUE("object.method_overload(10, 11)", v8::Undefined()));
2127 QCOMPARE(o.error(), false);
2128 QCOMPARE(o.invoked(), 17);
2129 QCOMPARE(o.actuals().count(), 2);
2130 QCOMPARE(o.actuals().at(0), QVariant(10));
2131 QCOMPARE(o.actuals().at(1), QVariant(11));
2134 QVERIFY(EVALUATE_VALUE("object.method_overload(\"Hello\")", v8::Undefined()));
2135 QCOMPARE(o.error(), false);
2136 QCOMPARE(o.invoked(), 18);
2137 QCOMPARE(o.actuals().count(), 1);
2138 QCOMPARE(o.actuals().at(0), QVariant(QString("Hello")));
2141 QVERIFY(EVALUATE_VALUE("object.method_with_enum(9)", v8::Undefined()));
2142 QCOMPARE(o.error(), false);
2143 QCOMPARE(o.invoked(), 19);
2144 QCOMPARE(o.actuals().count(), 1);
2145 QCOMPARE(o.actuals().at(0), QVariant(9));
2148 QVERIFY(EVALUATE_VALUE("object.method_default(10)", v8::Integer::New(19)));
2149 QCOMPARE(o.error(), false);
2150 QCOMPARE(o.invoked(), 20);
2151 QCOMPARE(o.actuals().count(), 2);
2152 QCOMPARE(o.actuals().at(0), QVariant(10));
2153 QCOMPARE(o.actuals().at(1), QVariant(19));
2156 QVERIFY(EVALUATE_VALUE("object.method_default(10, 13)", v8::Integer::New(13)));
2157 QCOMPARE(o.error(), false);
2158 QCOMPARE(o.invoked(), 20);
2159 QCOMPARE(o.actuals().count(), 2);
2160 QCOMPARE(o.actuals().at(0), QVariant(10));
2161 QCOMPARE(o.actuals().at(1), QVariant(13));
2164 QVERIFY(EVALUATE_VALUE("object.method_inherited(9)", v8::Undefined()));
2165 QCOMPARE(o.error(), false);
2166 QCOMPARE(o.invoked(), -3);
2167 QCOMPARE(o.actuals().count(), 1);
2168 QCOMPARE(o.actuals().at(0), QVariant(9));
2171 QVERIFY(EVALUATE_VALUE("object.method_QVariant(9)", v8::Undefined()));
2172 QCOMPARE(o.error(), false);
2173 QCOMPARE(o.invoked(), 21);
2174 QCOMPARE(o.actuals().count(), 2);
2175 QCOMPARE(o.actuals().at(0), QVariant(9));
2176 QCOMPARE(o.actuals().at(1), QVariant());
2179 QVERIFY(EVALUATE_VALUE("object.method_QVariant(\"Hello\", \"World\")", v8::Undefined()));
2180 QCOMPARE(o.error(), false);
2181 QCOMPARE(o.invoked(), 21);
2182 QCOMPARE(o.actuals().count(), 2);
2183 QCOMPARE(o.actuals().at(0), QVariant(QString("Hello")));
2184 QCOMPARE(o.actuals().at(1), QVariant(QString("World")));
2187 // QTBUG-13047 (check that you can pass registered object types as args)
2188 void tst_qdeclarativeecmascript::invokableObjectArg()
2190 QDeclarativeComponent component(&engine, TEST_FILE("invokableObjectArg.qml"));
2192 QObject *o = component.create();
2194 MyQmlObject *qmlobject = qobject_cast<MyQmlObject *>(o);
2196 QCOMPARE(qmlobject->myinvokableObject, qmlobject);
2201 // QTBUG-13047 (check that you can return registered object types from methods)
2202 void tst_qdeclarativeecmascript::invokableObjectRet()
2204 QDeclarativeComponent component(&engine, TEST_FILE("invokableObjectRet.qml"));
2206 QObject *o = component.create();
2208 QCOMPARE(o->property("test").toBool(), true);
2213 void tst_qdeclarativeecmascript::listToVariant()
2215 QDeclarativeComponent component(&engine, TEST_FILE("listToVariant.qml"));
2217 MyQmlContainer container;
2219 QDeclarativeContext context(engine.rootContext());
2220 context.setContextObject(&container);
2222 QObject *object = component.create(&context);
2223 QVERIFY(object != 0);
2225 QVariant v = object->property("test");
2226 QCOMPARE(v.userType(), qMetaTypeId<QDeclarativeListReference>());
2227 QVERIFY(qvariant_cast<QDeclarativeListReference>(v).object() == &container);
2233 void tst_qdeclarativeecmascript::multiEngineObject()
2236 obj.setStringProperty("Howdy planet");
2238 QDeclarativeEngine e1;
2239 e1.rootContext()->setContextProperty("thing", &obj);
2240 QDeclarativeComponent c1(&e1, TEST_FILE("multiEngineObject.qml"));
2242 QDeclarativeEngine e2;
2243 e2.rootContext()->setContextProperty("thing", &obj);
2244 QDeclarativeComponent c2(&e2, TEST_FILE("multiEngineObject.qml"));
2246 QObject *o1 = c1.create();
2247 QObject *o2 = c2.create();
2249 QCOMPARE(o1->property("test").toString(), QString("Howdy planet"));
2250 QCOMPARE(o2->property("test").toString(), QString("Howdy planet"));
2256 // Test that references to QObjects are cleanup when the object is destroyed
2257 void tst_qdeclarativeecmascript::deletedObject()
2259 QDeclarativeComponent component(&engine, TEST_FILE("deletedObject.qml"));
2261 QObject *object = component.create();
2263 QCOMPARE(object->property("test1").toBool(), true);
2264 QCOMPARE(object->property("test2").toBool(), true);
2265 QCOMPARE(object->property("test3").toBool(), true);
2266 QCOMPARE(object->property("test4").toBool(), true);
2271 void tst_qdeclarativeecmascript::attachedPropertyScope()
2273 QDeclarativeComponent component(&engine, TEST_FILE("attachedPropertyScope.qml"));
2275 QObject *object = component.create();
2276 QVERIFY(object != 0);
2278 MyQmlAttachedObject *attached =
2279 qobject_cast<MyQmlAttachedObject *>(qmlAttachedPropertiesObject<MyQmlObject>(object));
2280 QVERIFY(attached != 0);
2282 QCOMPARE(object->property("value2").toInt(), 0);
2284 attached->emitMySignal();
2286 QCOMPARE(object->property("value2").toInt(), 9);
2291 void tst_qdeclarativeecmascript::scriptConnect()
2294 QDeclarativeComponent component(&engine, TEST_FILE("scriptConnect.1.qml"));
2296 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2297 QVERIFY(object != 0);
2299 QCOMPARE(object->property("test").toBool(), false);
2300 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2301 QCOMPARE(object->property("test").toBool(), true);
2307 QDeclarativeComponent component(&engine, TEST_FILE("scriptConnect.2.qml"));
2309 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2310 QVERIFY(object != 0);
2312 QCOMPARE(object->property("test").toBool(), false);
2313 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2314 QCOMPARE(object->property("test").toBool(), true);
2320 QDeclarativeComponent component(&engine, TEST_FILE("scriptConnect.3.qml"));
2322 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2323 QVERIFY(object != 0);
2325 QCOMPARE(object->property("test").toBool(), false);
2326 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2327 QCOMPARE(object->property("test").toBool(), true);
2333 QDeclarativeComponent component(&engine, TEST_FILE("scriptConnect.4.qml"));
2335 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2336 QVERIFY(object != 0);
2338 QCOMPARE(object->methodCalled(), false);
2339 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2340 QCOMPARE(object->methodCalled(), true);
2346 QDeclarativeComponent component(&engine, TEST_FILE("scriptConnect.5.qml"));
2348 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2349 QVERIFY(object != 0);
2351 QCOMPARE(object->methodCalled(), false);
2352 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2353 QCOMPARE(object->methodCalled(), true);
2359 QDeclarativeComponent component(&engine, TEST_FILE("scriptConnect.6.qml"));
2361 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2362 QVERIFY(object != 0);
2364 QCOMPARE(object->property("test").toInt(), 0);
2365 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2366 QCOMPARE(object->property("test").toInt(), 2);
2372 void tst_qdeclarativeecmascript::scriptDisconnect()
2375 QDeclarativeComponent component(&engine, TEST_FILE("scriptDisconnect.1.qml"));
2377 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2378 QVERIFY(object != 0);
2380 QCOMPARE(object->property("test").toInt(), 0);
2381 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2382 QCOMPARE(object->property("test").toInt(), 1);
2383 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2384 QCOMPARE(object->property("test").toInt(), 2);
2385 emit object->basicSignal();
2386 QCOMPARE(object->property("test").toInt(), 2);
2387 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2388 QCOMPARE(object->property("test").toInt(), 2);
2394 QDeclarativeComponent component(&engine, TEST_FILE("scriptDisconnect.2.qml"));
2396 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2397 QVERIFY(object != 0);
2399 QCOMPARE(object->property("test").toInt(), 0);
2400 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2401 QCOMPARE(object->property("test").toInt(), 1);
2402 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2403 QCOMPARE(object->property("test").toInt(), 2);
2404 emit object->basicSignal();
2405 QCOMPARE(object->property("test").toInt(), 2);
2406 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2407 QCOMPARE(object->property("test").toInt(), 2);
2413 QDeclarativeComponent component(&engine, TEST_FILE("scriptDisconnect.3.qml"));
2415 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2416 QVERIFY(object != 0);
2418 QCOMPARE(object->property("test").toInt(), 0);
2419 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2420 QCOMPARE(object->property("test").toInt(), 1);
2421 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2422 QCOMPARE(object->property("test").toInt(), 2);
2423 emit object->basicSignal();
2424 QCOMPARE(object->property("test").toInt(), 2);
2425 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2426 QCOMPARE(object->property("test").toInt(), 3);
2431 QDeclarativeComponent component(&engine, TEST_FILE("scriptDisconnect.4.qml"));
2433 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2434 QVERIFY(object != 0);
2436 QCOMPARE(object->property("test").toInt(), 0);
2437 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2438 QCOMPARE(object->property("test").toInt(), 1);
2439 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2440 QCOMPARE(object->property("test").toInt(), 2);
2441 emit object->basicSignal();
2442 QCOMPARE(object->property("test").toInt(), 2);
2443 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2444 QCOMPARE(object->property("test").toInt(), 3);
2450 class OwnershipObject : public QObject
2454 OwnershipObject() { object = new QObject; }
2456 QPointer<QObject> object;
2459 QObject *getObject() { return object; }
2462 void tst_qdeclarativeecmascript::ownership()
2464 OwnershipObject own;
2465 QDeclarativeContext *context = new QDeclarativeContext(engine.rootContext());
2466 context->setContextObject(&own);
2469 QDeclarativeComponent component(&engine, TEST_FILE("ownership.qml"));
2471 QVERIFY(own.object != 0);
2473 QObject *object = component.create(context);
2475 engine.collectGarbage();
2477 QCoreApplication::processEvents(QEventLoop::DeferredDeletion);
2479 QVERIFY(own.object == 0);
2484 own.object = new QObject(&own);
2487 QDeclarativeComponent component(&engine, TEST_FILE("ownership.qml"));
2489 QVERIFY(own.object != 0);
2491 QObject *object = component.create(context);
2493 engine.collectGarbage();
2495 QCoreApplication::processEvents(QEventLoop::DeferredDeletion);
2497 QVERIFY(own.object != 0);
2505 class CppOwnershipReturnValue : public QObject
2509 CppOwnershipReturnValue() : value(0) {}
2510 ~CppOwnershipReturnValue() { delete value; }
2512 Q_INVOKABLE QObject *create() {
2513 value = new QObject;
2514 QDeclarativeEngine::setObjectOwnership(value, QDeclarativeEngine::CppOwnership);
2518 Q_INVOKABLE MyQmlObject *createQmlObject() {
2519 MyQmlObject *rv = new MyQmlObject;
2524 QPointer<QObject> value;
2528 // Test setObjectOwnership(CppOwnership) works even when there is no QDeclarativeData
2529 void tst_qdeclarativeecmascript::cppOwnershipReturnValue()
2531 CppOwnershipReturnValue source;
2534 QDeclarativeEngine engine;
2535 engine.rootContext()->setContextProperty("source", &source);
2537 QVERIFY(source.value == 0);
2539 QDeclarativeComponent component(&engine);
2540 component.setData("import QtQuick 1.0\nQtObject {\nComponent.onCompleted: { var a = source.create(); }\n}\n", QUrl());
2542 QObject *object = component.create();
2544 QVERIFY(object != 0);
2545 QVERIFY(source.value != 0);
2550 QCoreApplication::instance()->processEvents(QEventLoop::DeferredDeletion);
2552 QVERIFY(source.value != 0);
2556 void tst_qdeclarativeecmascript::ownershipCustomReturnValue()
2558 CppOwnershipReturnValue source;
2561 QDeclarativeEngine engine;
2562 engine.rootContext()->setContextProperty("source", &source);
2564 QVERIFY(source.value == 0);
2566 QDeclarativeComponent component(&engine);
2567 component.setData("import QtQuick 1.0\nQtObject {\nComponent.onCompleted: { var a = source.createQmlObject(); }\n}\n", QUrl());
2569 QObject *object = component.create();
2571 QVERIFY(object != 0);
2572 QVERIFY(source.value != 0);
2577 engine.collectGarbage();
2578 QCoreApplication::instance()->processEvents(QEventLoop::DeferredDeletion);
2580 QVERIFY(source.value == 0);
2583 class QListQObjectMethodsObject : public QObject
2587 QListQObjectMethodsObject() {
2588 m_objects.append(new MyQmlObject());
2589 m_objects.append(new MyQmlObject());
2592 ~QListQObjectMethodsObject() {
2593 qDeleteAll(m_objects);
2597 QList<QObject *> getObjects() { return m_objects; }
2600 QList<QObject *> m_objects;
2603 // Tests that returning a QList<QObject*> from a method works
2604 void tst_qdeclarativeecmascript::qlistqobjectMethods()
2606 QListQObjectMethodsObject obj;
2607 QDeclarativeContext *context = new QDeclarativeContext(engine.rootContext());
2608 context->setContextObject(&obj);
2610 QDeclarativeComponent component(&engine, TEST_FILE("qlistqobjectMethods.qml"));
2612 QObject *object = component.create(context);
2614 QCOMPARE(object->property("test").toInt(), 2);
2615 QCOMPARE(object->property("test2").toBool(), true);
2622 void tst_qdeclarativeecmascript::strictlyEquals()
2624 QDeclarativeComponent component(&engine, TEST_FILE("strictlyEquals.qml"));
2626 QObject *object = component.create();
2627 QVERIFY(object != 0);
2629 QCOMPARE(object->property("test1").toBool(), true);
2630 QCOMPARE(object->property("test2").toBool(), true);
2631 QCOMPARE(object->property("test3").toBool(), true);
2632 QCOMPARE(object->property("test4").toBool(), true);
2633 QCOMPARE(object->property("test5").toBool(), true);
2634 QCOMPARE(object->property("test6").toBool(), true);
2635 QCOMPARE(object->property("test7").toBool(), true);
2636 QCOMPARE(object->property("test8").toBool(), true);
2641 void tst_qdeclarativeecmascript::compiled()
2643 QDeclarativeComponent component(&engine, TEST_FILE("compiled.qml"));
2645 QObject *object = component.create();
2646 QVERIFY(object != 0);
2648 QCOMPARE(object->property("test1").toReal(), qreal(15.7));
2649 QCOMPARE(object->property("test2").toReal(), qreal(-6.7));
2650 QCOMPARE(object->property("test3").toBool(), true);
2651 QCOMPARE(object->property("test4").toBool(), false);
2652 QCOMPARE(object->property("test5").toBool(), false);
2653 QCOMPARE(object->property("test6").toBool(), true);
2655 QCOMPARE(object->property("test7").toInt(), 185);
2656 QCOMPARE(object->property("test8").toInt(), 167);
2657 QCOMPARE(object->property("test9").toBool(), true);
2658 QCOMPARE(object->property("test10").toBool(), false);
2659 QCOMPARE(object->property("test11").toBool(), false);
2660 QCOMPARE(object->property("test12").toBool(), true);
2662 QCOMPARE(object->property("test13").toString(), QLatin1String("HelloWorld"));
2663 QCOMPARE(object->property("test14").toString(), QLatin1String("Hello World"));
2664 QCOMPARE(object->property("test15").toBool(), false);
2665 QCOMPARE(object->property("test16").toBool(), true);
2667 QCOMPARE(object->property("test17").toInt(), 5);
2668 QCOMPARE(object->property("test18").toReal(), qreal(176));
2669 QCOMPARE(object->property("test19").toInt(), 7);
2670 QCOMPARE(object->property("test20").toReal(), qreal(6.7));
2671 QCOMPARE(object->property("test21").toString(), QLatin1String("6.7"));
2672 QCOMPARE(object->property("test22").toString(), QLatin1String("!"));
2673 QCOMPARE(object->property("test23").toBool(), true);
2674 QCOMPARE(qvariant_cast<QColor>(object->property("test24")), QColor(0x11,0x22,0x33));
2675 QCOMPARE(qvariant_cast<QColor>(object->property("test25")), QColor(0x11,0x22,0x33,0xAA));
2680 // Test that numbers assigned in bindings as strings work consistently
2681 void tst_qdeclarativeecmascript::numberAssignment()
2683 QDeclarativeComponent component(&engine, TEST_FILE("numberAssignment.qml"));
2685 QObject *object = component.create();
2686 QVERIFY(object != 0);
2688 QCOMPARE(object->property("test1"), QVariant((qreal)6.7));
2689 QCOMPARE(object->property("test2"), QVariant((qreal)6.7));
2690 QCOMPARE(object->property("test2"), QVariant((qreal)6.7));
2691 QCOMPARE(object->property("test3"), QVariant((qreal)6));
2692 QCOMPARE(object->property("test4"), QVariant((qreal)6));
2694 QCOMPARE(object->property("test5"), QVariant((int)7));
2695 QCOMPARE(object->property("test6"), QVariant((int)7));
2696 QCOMPARE(object->property("test7"), QVariant((int)6));
2697 QCOMPARE(object->property("test8"), QVariant((int)6));
2699 QCOMPARE(object->property("test9"), QVariant((unsigned int)7));
2700 QCOMPARE(object->property("test10"), QVariant((unsigned int)7));
2701 QCOMPARE(object->property("test11"), QVariant((unsigned int)6));
2702 QCOMPARE(object->property("test12"), QVariant((unsigned int)6));
2707 void tst_qdeclarativeecmascript::propertySplicing()
2709 QDeclarativeComponent component(&engine, TEST_FILE("propertySplicing.qml"));
2711 QObject *object = component.create();
2712 QVERIFY(object != 0);
2714 QCOMPARE(object->property("test").toBool(), true);
2720 void tst_qdeclarativeecmascript::signalWithUnknownTypes()
2722 QDeclarativeComponent component(&engine, TEST_FILE("signalWithUnknownTypes.qml"));
2724 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2725 QVERIFY(object != 0);
2727 MyQmlObject::MyType type;
2728 type.value = 0x8971123;
2729 emit object->signalWithUnknownType(type);
2731 MyQmlObject::MyType result = qvariant_cast<MyQmlObject::MyType>(object->variant());
2733 QCOMPARE(result.value, type.value);
2739 void tst_qdeclarativeecmascript::moduleApi_data()
2741 QTest::addColumn<QUrl>("testfile");
2742 QTest::addColumn<QString>("errorMessage");
2743 QTest::addColumn<QStringList>("warningMessages");
2744 QTest::addColumn<QStringList>("readProperties");
2745 QTest::addColumn<QVariantList>("readExpectedValues");
2746 QTest::addColumn<QStringList>("writeProperties");
2747 QTest::addColumn<QVariantList>("writeValues");
2748 QTest::addColumn<QStringList>("readBackProperties");
2749 QTest::addColumn<QVariantList>("readBackExpectedValues");
2751 QTest::newRow("qobject, register + read + method")
2752 << TEST_FILE("moduleapi/qobjectModuleApi.qml")
2755 << (QStringList() << "existingUriTest" << "qobjectTest" << "qobjectMethodTest"
2756 << "qobjectMinorVersionTest" << "qobjectMajorVersionTest" << "qobjectParentedTest")
2757 << (QVariantList() << 20 << 20 << 1 << 20 << 20 << 26)
2763 QTest::newRow("script, register + read")
2764 << TEST_FILE("moduleapi/scriptModuleApi.qml")
2767 << (QStringList() << "scriptTest")
2768 << (QVariantList() << 13)
2774 QTest::newRow("qobject, caching + read")
2775 << TEST_FILE("moduleapi/qobjectModuleApiCaching.qml")
2778 << (QStringList() << "existingUriTest" << "qobjectParentedTest")
2779 << (QVariantList() << 20 << 26) // 26, shouldn't have incremented to 27.
2785 QTest::newRow("script, caching + read")
2786 << TEST_FILE("moduleapi/scriptModuleApiCaching.qml")
2789 << (QStringList() << "scriptTest")
2790 << (QVariantList() << 13) // 13, shouldn't have incremented to 14.
2796 QTest::newRow("qobject, writing + readonly constraints")
2797 << TEST_FILE("moduleapi/qobjectModuleApiWriting.qml")
2799 << (QStringList() << QString(QLatin1String("file://") + TEST_FILE("moduleapi/qobjectModuleApiWriting.qml").toLocalFile() + QLatin1String(":14: Error: Cannot assign to read-only property \"qobjectTestProperty\"")))
2800 << (QStringList() << "readOnlyProperty" << "writableProperty")
2801 << (QVariantList() << 20 << 50)
2802 << (QStringList() << "firstProperty" << "writableProperty")
2803 << (QVariantList() << 30 << 30)
2804 << (QStringList() << "readOnlyProperty" << "writableProperty")
2805 << (QVariantList() << 20 << 30);
2807 QTest::newRow("script, writing + readonly constraints")
2808 << TEST_FILE("moduleapi/scriptModuleApiWriting.qml")
2810 << (QStringList() << QString(QLatin1String("file://") + TEST_FILE("moduleapi/scriptModuleApiWriting.qml").toLocalFile() + QLatin1String(":21: Error: Cannot assign to read-only property \"scriptTestProperty\"")))
2811 << (QStringList() << "readBack" << "unchanged")
2812 << (QVariantList() << 13 << 42)
2813 << (QStringList() << "firstProperty" << "secondProperty")
2814 << (QVariantList() << 30 << 30)
2815 << (QStringList() << "readBack" << "unchanged")
2816 << (QVariantList() << 30 << 42);
2818 QTest::newRow("qobject, invalid major version fail")
2819 << TEST_FILE("moduleapi/moduleApiMajorVersionFail.qml")
2820 << QString("QDeclarativeComponent: Component is not ready")
2829 QTest::newRow("qobject, invalid minor version fail")
2830 << TEST_FILE("moduleapi/moduleApiMinorVersionFail.qml")
2831 << QString("QDeclarativeComponent: Component is not ready")
2841 void tst_qdeclarativeecmascript::moduleApi()
2843 QFETCH(QUrl, testfile);
2844 QFETCH(QString, errorMessage);
2845 QFETCH(QStringList, warningMessages);
2846 QFETCH(QStringList, readProperties);
2847 QFETCH(QVariantList, readExpectedValues);
2848 QFETCH(QStringList, writeProperties);
2849 QFETCH(QVariantList, writeValues);
2850 QFETCH(QStringList, readBackProperties);
2851 QFETCH(QVariantList, readBackExpectedValues);
2853 QDeclarativeComponent component(&engine, testfile);
2855 if (!errorMessage.isEmpty())
2856 QTest::ignoreMessage(QtWarningMsg, errorMessage.toAscii().constData());
2858 if (warningMessages.size())
2859 foreach (const QString &warning, warningMessages)
2860 QTest::ignoreMessage(QtWarningMsg, warning.toAscii().constData());
2862 QObject *object = component.create();
2863 if (!errorMessage.isEmpty()) {
2864 QVERIFY(object == 0);
2866 QVERIFY(object != 0);
2867 for (int i = 0; i < readProperties.size(); ++i)
2868 QCOMPARE(object->property(readProperties.at(i).toAscii().constData()), readExpectedValues.at(i));
2869 for (int i = 0; i < writeProperties.size(); ++i)
2870 QVERIFY(object->setProperty(writeProperties.at(i).toAscii().constData(), writeValues.at(i)));
2871 for (int i = 0; i < readBackProperties.size(); ++i)
2872 QCOMPARE(object->property(readBackProperties.at(i).toAscii().constData()), readBackExpectedValues.at(i));
2877 void tst_qdeclarativeecmascript::importScripts()
2879 QObject *object = 0;
2881 // first, ensure that the required behaviour works.
2882 QDeclarativeComponent component(&engine, TEST_FILE("jsimport/testImport.qml"));
2883 object = component.create();
2884 QVERIFY(object != 0);
2885 QCOMPARE(object->property("importedScriptStringValue"), QVariant(QString(QLatin1String("Hello, World!"))));
2886 QCOMPARE(object->property("importedScriptFunctionValue"), QVariant(20));
2887 QCOMPARE(object->property("importedModuleAttachedPropertyValue"), QVariant(19));
2888 QCOMPARE(object->property("importedModuleEnumValue"), QVariant(2));
2891 QDeclarativeComponent componentTwo(&engine, TEST_FILE("jsimport/testImportScoping.qml"));
2892 object = componentTwo.create();
2893 QVERIFY(object != 0);
2894 QCOMPARE(object->property("componentError"), QVariant(5));
2897 // then, ensure that unintended behaviour does not work.
2898 QDeclarativeComponent failOneComponent(&engine, TEST_FILE("jsimportfail/failOne.qml"));
2899 QString expectedWarning = QLatin1String("file://") + TEST_FILE("jsimportfail/failOne.qml").toLocalFile() + QLatin1String(":6: TypeError: Cannot call method 'greetingString' of undefined");
2900 QTest::ignoreMessage(QtWarningMsg, expectedWarning.toAscii().constData());
2901 object = failOneComponent.create();
2902 QVERIFY(object != 0);
2903 QVERIFY(object->property("importScriptFunctionValue").toString().isEmpty());
2905 QDeclarativeComponent failTwoComponent(&engine, TEST_FILE("jsimportfail/failTwo.qml"));
2906 expectedWarning = QLatin1String("file://") + TEST_FILE("jsimportfail/failTwo.qml").toLocalFile() + QLatin1String(":6: ReferenceError: Can't find variable: ImportOneJs");
2907 QTest::ignoreMessage(QtWarningMsg, expectedWarning.toAscii().constData());
2908 object = failTwoComponent.create();
2909 QVERIFY(object != 0);
2910 QVERIFY(object->property("importScriptFunctionValue").toString().isEmpty());
2912 QDeclarativeComponent failThreeComponent(&engine, TEST_FILE("jsimportfail/failThree.qml"));
2913 expectedWarning = QLatin1String("file://") + TEST_FILE("jsimportfail/failThree.qml").toLocalFile() + QLatin1String(":7: TypeError: Cannot read property 'JsQtTest' of undefined");
2914 QTest::ignoreMessage(QtWarningMsg, expectedWarning.toAscii().constData());
2915 object = failThreeComponent.create();
2916 QVERIFY(object != 0);
2917 QCOMPARE(object->property("importedModuleAttachedPropertyValue"), QVariant(false));
2919 QDeclarativeComponent failFourComponent(&engine, TEST_FILE("jsimportfail/failFour.qml"));
2920 expectedWarning = QLatin1String("file://") + TEST_FILE("jsimportfail/failFour.qml").toLocalFile() + QLatin1String(":6: ReferenceError: Can't find variable: JsQtTest");
2921 QTest::ignoreMessage(QtWarningMsg, expectedWarning.toAscii().constData());
2922 object = failFourComponent.create();
2923 QVERIFY(object != 0);
2924 QCOMPARE(object->property("importedModuleEnumValue"), QVariant(0));
2926 QDeclarativeComponent failFiveComponent(&engine, TEST_FILE("jsimportfail/failFive.qml"));
2927 expectedWarning = QLatin1String("file://") + TEST_FILE("jsimportfail/importWithImports.js").toLocalFile() + QLatin1String(":8: ReferenceError: Can't find variable: Component");
2928 QTest::ignoreMessage(QtWarningMsg, expectedWarning.toAscii().constData());
2929 expectedWarning = QLatin1String("file://") + TEST_FILE("jsimportfail/importPragmaLibrary.js").toLocalFile() + QLatin1String(":6: ReferenceError: Can't find variable: Component");
2930 QTest::ignoreMessage(QtWarningMsg, expectedWarning.toAscii().constData());
2931 object = failFiveComponent.create();
2932 QVERIFY(object != 0);
2933 QCOMPARE(object->property("componentError"), QVariant(0));
2936 // also, test that importing scripts with .pragma library works as required
2937 QDeclarativeComponent pragmaLibraryComponent(&engine, TEST_FILE("jsimport/testImportPragmaLibrary.qml"));
2938 object = pragmaLibraryComponent.create();
2939 QVERIFY(object != 0);
2940 QCOMPARE(object->property("testValue"), QVariant(31));
2943 // and that .pragma library scripts don't inherit imports from any .qml file
2944 QDeclarativeComponent pragmaLibraryComponentTwo(&engine, TEST_FILE("jsimportfail/testImportPragmaLibrary.qml"));
2945 object = pragmaLibraryComponentTwo.create();
2946 QVERIFY(object != 0);
2947 QCOMPARE(object->property("testValue"), QVariant(0));
2951 void tst_qdeclarativeecmascript::scarceResources()
2953 QPixmap origPixmap(100, 100);
2954 origPixmap.fill(Qt::blue);
2956 QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(&engine);
2957 ScarceResourceObject *eo = 0;
2958 QObject *object = 0;
2960 // in the following three cases, the instance created from the component
2961 // has a property which is a copy of the scarce resource; hence, the
2962 // resource should NOT be detached prior to deletion of the object instance,
2963 // unless the resource is destroyed explicitly.
2964 QDeclarativeComponent component(&engine, TEST_FILE("scarceresources/scarceResourceCopy.qml"));
2965 object = component.create();
2966 QVERIFY(object != 0);
2967 QVERIFY(object->property("scarceResourceCopy").isValid());
2968 QCOMPARE(object->property("scarceResourceCopy").value<QPixmap>(), origPixmap);
2969 QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
2970 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2971 QVERIFY(!eo->scarceResourceIsDetached()); // there are two copies of it in existence: the property of object, and the property of eo.
2974 QDeclarativeComponent componentTwo(&engine, TEST_FILE("scarceresources/scarceResourceCopyFromJs.qml"));
2975 object = componentTwo.create();
2976 QVERIFY(object != 0);
2977 QVERIFY(object->property("scarceResourceCopy").isValid());
2978 QCOMPARE(object->property("scarceResourceCopy").value<QPixmap>(), origPixmap);
2979 QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
2980 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2981 QVERIFY(!eo->scarceResourceIsDetached()); // there are two copies of it in existence: the property of object, and the property of eo.
2984 QDeclarativeComponent componentThree(&engine, TEST_FILE("scarceresources/scarceResourceDestroyedCopy.qml"));
2985 object = componentThree.create();
2986 QVERIFY(object != 0);
2987 QVERIFY(!(object->property("scarceResourceCopy").isValid())); // was manually released prior to being returned.
2988 QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
2989 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2990 QVERIFY(eo->scarceResourceIsDetached()); // should have explicitly been released during the evaluation of the binding.
2993 // in the following three cases, no other copy should exist in memory,
2994 // and so it should be detached (unless explicitly preserved).
2995 QDeclarativeComponent componentFour(&engine, TEST_FILE("scarceresources/scarceResourceTest.qml"));
2996 object = componentFour.create();
2997 QVERIFY(object != 0);
2998 QVERIFY(object->property("scarceResourceTest").isValid());
2999 QCOMPARE(object->property("scarceResourceTest").toInt(), 100);
3000 QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
3001 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
3002 QVERIFY(eo->scarceResourceIsDetached()); // the resource should have been released after the binding was evaluated.
3005 QDeclarativeComponent componentFive(&engine, TEST_FILE("scarceresources/scarceResourceTestPreserve.qml"));
3006 object = componentFive.create();
3007 QVERIFY(object != 0);
3008 QVERIFY(object->property("scarceResourceTest").isValid());
3009 QCOMPARE(object->property("scarceResourceTest").toInt(), 100);
3010 QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
3011 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
3012 QVERIFY(!eo->scarceResourceIsDetached()); // this won't be detached since we explicitly preserved it.
3015 QDeclarativeComponent componentSix(&engine, TEST_FILE("scarceresources/scarceResourceTestMultiple.qml"));
3016 object = componentSix.create();
3017 QVERIFY(object != 0);
3018 QVERIFY(object->property("scarceResourceTest").isValid());
3019 QCOMPARE(object->property("scarceResourceTest").toInt(), 100);
3020 QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
3021 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
3022 QVERIFY(eo->scarceResourceIsDetached()); // all resources were released manually or automatically released.
3025 // test that scarce resources are handled correctly for imports
3026 QDeclarativeComponent componentSeven(&engine, TEST_FILE("scarceresources/scarceResourceCopyImportNoBinding.qml"));
3027 object = componentSeven.create();
3028 QVERIFY(object != 0); // the import should have caused the addition of a resource to the ScarceResources list
3029 QVERIFY(ep->scarceResources.isEmpty()); // but they should have been released by this point.
3032 QDeclarativeComponent componentEight(&engine, TEST_FILE("scarceresources/scarceResourceCopyImportFail.qml"));
3033 object = componentEight.create();
3034 QVERIFY(object != 0);
3035 QVERIFY(!object->property("scarceResourceCopy").isValid()); // wasn't preserved, so shouldn't be valid.
3036 QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
3039 QDeclarativeComponent componentNine(&engine, TEST_FILE("scarceresources/scarceResourceCopyImport.qml"));
3040 object = componentNine.create();
3041 QVERIFY(object != 0);
3042 QVERIFY(object->property("scarceResourceCopy").isValid()); // preserved, so should be valid.
3043 QCOMPARE(object->property("scarceResourceCopy").value<QPixmap>(), origPixmap);
3044 QVERIFY(object->property("scarceResourceAssignedCopyOne").isValid()); // assigned before destroy(), so should be valid.
3045 QCOMPARE(object->property("scarceResourceAssignedCopyOne").value<QPixmap>(), origPixmap);
3046 QVERIFY(!object->property("scarceResourceAssignedCopyTwo").isValid()); // assigned after destroy(), so should be invalid.
3047 QVERIFY(ep->scarceResources.isEmpty()); // this will still be zero, because "preserve()" REMOVES it from this list.
3050 // test that scarce resources are handled properly in signal invocation
3051 QDeclarativeComponent componentTen(&engine, TEST_FILE("scarceresources/scarceResourceSignal.qml"));
3052 object = componentTen.create();
3053 QVERIFY(object != 0);
3054 QObject *srsc = object->findChild<QObject*>("srsc");
3056 QVERIFY(!srsc->property("scarceResourceCopy").isValid()); // hasn't been instantiated yet.
3057 QCOMPARE(srsc->property("width"), QVariant(5)); // default value is 5.
3058 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
3059 QVERIFY(eo->scarceResourceIsDetached()); // should be no other copies of it at this stage.
3060 QMetaObject::invokeMethod(srsc, "testSignal");
3061 QVERIFY(!srsc->property("scarceResourceCopy").isValid()); // still hasn't been instantiated
3062 QCOMPARE(srsc->property("width"), QVariant(10)); // but width was assigned to 10.
3063 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
3064 QVERIFY(eo->scarceResourceIsDetached()); // should still be no other copies of it at this stage.
3065 QMetaObject::invokeMethod(srsc, "testSignal2"); // assigns scarceResourceCopy to the scarce pixmap.
3066 QVERIFY(srsc->property("scarceResourceCopy").isValid());
3067 QCOMPARE(srsc->property("scarceResourceCopy").value<QPixmap>(), origPixmap);
3068 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
3069 QVERIFY(!(eo->scarceResourceIsDetached())); // should be another copy of the resource now.
3070 QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
3073 // test that scarce resources are handled properly from js functions in qml files
3074 QDeclarativeComponent componentEleven(&engine, TEST_FILE("scarceresources/scarceResourceFunction.qml"));
3075 object = componentEleven.create();
3076 QVERIFY(object != 0);
3077 QVERIFY(!object->property("scarceResourceCopy").isValid()); // not yet assigned, so should not be valid
3078 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
3079 QVERIFY(eo->scarceResourceIsDetached()); // should be no other copies of it at this stage.
3080 QMetaObject::invokeMethod(object, "retrieveScarceResource");
3081 QVERIFY(object->property("scarceResourceCopy").isValid()); // assigned, so should be valid.
3082 QCOMPARE(object->property("scarceResourceCopy").value<QPixmap>(), origPixmap);
3083 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
3084 QVERIFY(!eo->scarceResourceIsDetached()); // should be a copy of the resource at this stage.
3085 QMetaObject::invokeMethod(object, "releaseScarceResource");
3086 QVERIFY(!object->property("scarceResourceCopy").isValid()); // just released, so should not be valid
3087 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
3088 QVERIFY(eo->scarceResourceIsDetached()); // should be no other copies of it at this stage.
3089 QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
3092 // test that if an exception occurs while invoking js function from cpp, that the resources are released.
3093 QDeclarativeComponent componentTwelve(&engine, TEST_FILE("scarceresources/scarceResourceFunctionFail.qml"));
3094 object = componentTwelve.create();
3095 QVERIFY(object != 0);
3096 QVERIFY(!object->property("scarceResourceCopy").isValid()); // not yet assigned, so should not be valid
3097 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
3098 QVERIFY(eo->scarceResourceIsDetached()); // should be no other copies of it at this stage.
3099 QString srp_name = object->property("srp_name").toString();
3100 QString expectedWarning = componentTwelve.url().toString() + QLatin1String(":17: TypeError: Property 'scarceResource' of object ") + srp_name + QLatin1String(" is not a function");
3101 QTest::ignoreMessage(QtWarningMsg, qPrintable(expectedWarning)); // we expect a meaningful warning to be printed.
3102 QMetaObject::invokeMethod(object, "retrieveScarceResource");
3103 QVERIFY(!object->property("scarceResourceCopy").isValid()); // due to exception, assignment will NOT have occurred.
3104 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
3105 QVERIFY(eo->scarceResourceIsDetached()); // should be no other copies of it at this stage.
3106 QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
3110 void tst_qdeclarativeecmascript::propertyChangeSlots()
3112 // ensure that allowable property names are allowed and onPropertyNameChanged slots are generated correctly.
3113 QDeclarativeComponent component(&engine, TEST_FILE("changeslots/propertyChangeSlots.qml"));
3114 QObject *object = component.create();
3115 QVERIFY(object != 0);
3118 // ensure that invalid property names fail properly.
3119 QTest::ignoreMessage(QtWarningMsg, "QDeclarativeComponent: Component is not ready");
3120 QDeclarativeComponent e1(&engine, TEST_FILE("changeslots/propertyChangeSlotErrors.1.qml"));
3121 QString expectedErrorString = e1.url().toString() + QLatin1String(":9:5: Cannot assign to non-existent property \"on_nameWithUnderscoreChanged\"");
3122 QCOMPARE(e1.errors().at(0).toString(), expectedErrorString);
3123 object = e1.create();
3124 QVERIFY(object == 0);
3127 QTest::ignoreMessage(QtWarningMsg, "QDeclarativeComponent: Component is not ready");
3128 QDeclarativeComponent e2(&engine, TEST_FILE("changeslots/propertyChangeSlotErrors.2.qml"));
3129 expectedErrorString = e2.url().toString() + QLatin1String(":9:5: Cannot assign to non-existent property \"on____nameWithUnderscoresChanged\"");
3130 QCOMPARE(e2.errors().at(0).toString(), expectedErrorString);
3131 object = e2.create();
3132 QVERIFY(object == 0);
3135 QTest::ignoreMessage(QtWarningMsg, "QDeclarativeComponent: Component is not ready");
3136 QDeclarativeComponent e3(&engine, TEST_FILE("changeslots/propertyChangeSlotErrors.3.qml"));
3137 expectedErrorString = e3.url().toString() + QLatin1String(":9:5: Cannot assign to non-existent property \"on$NameWithDollarsignChanged\"");
3138 QCOMPARE(e3.errors().at(0).toString(), expectedErrorString);
3139 object = e3.create();
3140 QVERIFY(object == 0);
3143 QTest::ignoreMessage(QtWarningMsg, "QDeclarativeComponent: Component is not ready");
3144 QDeclarativeComponent e4(&engine, TEST_FILE("changeslots/propertyChangeSlotErrors.4.qml"));
3145 expectedErrorString = e4.url().toString() + QLatin1String(":9:5: Cannot assign to non-existent property \"on_6NameWithUnderscoreNumberChanged\"");
3146 QCOMPARE(e4.errors().at(0).toString(), expectedErrorString);
3147 object = e4.create();
3148 QVERIFY(object == 0);
3152 // Ensure that QObject type conversion works on binding assignment
3153 void tst_qdeclarativeecmascript::elementAssign()
3155 QDeclarativeComponent component(&engine, TEST_FILE("elementAssign.qml"));
3157 QObject *object = component.create();
3158 QVERIFY(object != 0);
3160 QCOMPARE(object->property("test").toBool(), true);
3166 void tst_qdeclarativeecmascript::objectPassThroughSignals()
3168 QDeclarativeComponent component(&engine, TEST_FILE("objectsPassThroughSignals.qml"));
3170 QObject *object = component.create();
3171 QVERIFY(object != 0);
3173 QCOMPARE(object->property("test").toBool(), true);
3179 void tst_qdeclarativeecmascript::booleanConversion()
3181 QDeclarativeComponent component(&engine, TEST_FILE("booleanConversion.qml"));
3183 QObject *object = component.create();
3184 QVERIFY(object != 0);
3186 QCOMPARE(object->property("test_true1").toBool(), true);
3187 QCOMPARE(object->property("test_true2").toBool(), true);
3188 QCOMPARE(object->property("test_true3").toBool(), true);
3189 QCOMPARE(object->property("test_true4").toBool(), true);
3190 QCOMPARE(object->property("test_true5").toBool(), true);
3192 QCOMPARE(object->property("test_false1").toBool(), false);
3193 QCOMPARE(object->property("test_false2").toBool(), false);
3194 QCOMPARE(object->property("test_false3").toBool(), false);
3199 // Test that assigning a null object works
3200 // Regressed with: df1788b4dbbb2826ae63f26bdf166342595343f4
3201 void tst_qdeclarativeecmascript::nullObjectBinding()
3203 QDeclarativeComponent component(&engine, TEST_FILE("nullObjectBinding.qml"));
3205 QObject *object = component.create();
3206 QVERIFY(object != 0);
3208 QVERIFY(object->property("test") == QVariant::fromValue((QObject *)0));
3213 // Test that bindings don't evaluate once the engine has been destroyed
3214 void tst_qdeclarativeecmascript::deletedEngine()
3216 QDeclarativeEngine *engine = new QDeclarativeEngine;
3217 QDeclarativeComponent component(engine, TEST_FILE("deletedEngine.qml"));
3219 QObject *object = component.create();
3220 QVERIFY(object != 0);
3222 QCOMPARE(object->property("a").toInt(), 39);
3223 object->setProperty("b", QVariant(9));
3224 QCOMPARE(object->property("a").toInt(), 117);
3228 QCOMPARE(object->property("a").toInt(), 117);
3229 object->setProperty("b", QVariant(10));
3230 QCOMPARE(object->property("a").toInt(), 117);
3235 // Test the crashing part of QTBUG-9705
3236 void tst_qdeclarativeecmascript::libraryScriptAssert()
3238 QDeclarativeComponent component(&engine, TEST_FILE("libraryScriptAssert.qml"));
3240 QObject *object = component.create();
3241 QVERIFY(object != 0);
3246 void tst_qdeclarativeecmascript::variantsAssignedUndefined()
3248 QDeclarativeComponent component(&engine, TEST_FILE("variantsAssignedUndefined.qml"));
3250 QObject *object = component.create();
3251 QVERIFY(object != 0);
3253 QCOMPARE(object->property("test1").toInt(), 10);
3254 QCOMPARE(object->property("test2").toInt(), 11);
3256 object->setProperty("runTest", true);
3258 QCOMPARE(object->property("test1"), QVariant());
3259 QCOMPARE(object->property("test2"), QVariant());
3265 void tst_qdeclarativeecmascript::qtbug_9792()
3267 QDeclarativeComponent component(&engine, TEST_FILE("qtbug_9792.qml"));
3269 QDeclarativeContext *context = new QDeclarativeContext(engine.rootContext());
3271 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create(context));
3272 QVERIFY(object != 0);
3274 QTest::ignoreMessage(QtDebugMsg, "Hello world!");
3275 object->basicSignal();
3279 transientErrorsMsgCount = 0;
3280 QtMsgHandler old = qInstallMsgHandler(transientErrorsMsgHandler);
3282 object->basicSignal();
3284 qInstallMsgHandler(old);
3286 QCOMPARE(transientErrorsMsgCount, 0);
3291 // Verifies that QDeclarativeGuard<>s used in the vmemetaobject are cleaned correctly
3292 void tst_qdeclarativeecmascript::qtcreatorbug_1289()
3294 QDeclarativeComponent component(&engine, TEST_FILE("qtcreatorbug_1289.qml"));
3296 QObject *o = component.create();
3299 QObject *nested = qvariant_cast<QObject *>(o->property("object"));
3300 QVERIFY(nested != 0);
3302 QVERIFY(qvariant_cast<QObject *>(nested->property("nestedObject")) == o);
3305 nested = qvariant_cast<QObject *>(o->property("object"));
3306 QVERIFY(nested == 0);
3308 // If the bug is present, the next line will crash
3312 // Test that we shut down without stupid warnings
3313 void tst_qdeclarativeecmascript::noSpuriousWarningsAtShutdown()
3316 QDeclarativeComponent component(&engine, TEST_FILE("noSpuriousWarningsAtShutdown.qml"));
3318 QObject *o = component.create();
3320 transientErrorsMsgCount = 0;
3321 QtMsgHandler old = qInstallMsgHandler(transientErrorsMsgHandler);
3325 qInstallMsgHandler(old);
3327 QCOMPARE(transientErrorsMsgCount, 0);
3332 QDeclarativeComponent component(&engine, TEST_FILE("noSpuriousWarningsAtShutdown.2.qml"));
3334 QObject *o = component.create();
3336 transientErrorsMsgCount = 0;
3337 QtMsgHandler old = qInstallMsgHandler(transientErrorsMsgHandler);
3341 qInstallMsgHandler(old);
3343 QCOMPARE(transientErrorsMsgCount, 0);
3347 void tst_qdeclarativeecmascript::canAssignNullToQObject()
3350 QDeclarativeComponent component(&engine, TEST_FILE("canAssignNullToQObject.1.qml"));
3352 MyQmlObject *o = qobject_cast<MyQmlObject *>(component.create());
3355 QVERIFY(o->objectProperty() != 0);
3357 o->setProperty("runTest", true);
3359 QVERIFY(o->objectProperty() == 0);
3365 QDeclarativeComponent component(&engine, TEST_FILE("canAssignNullToQObject.2.qml"));
3367 MyQmlObject *o = qobject_cast<MyQmlObject *>(component.create());
3370 QVERIFY(o->objectProperty() == 0);
3376 void tst_qdeclarativeecmascript::functionAssignment_fromBinding()
3378 QDeclarativeComponent component(&engine, TEST_FILE("functionAssignment.1.qml"));
3380 QString url = component.url().toString();
3381 QString warning = url + ":4: Unable to assign a function to a property.";
3382 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
3384 MyQmlObject *o = qobject_cast<MyQmlObject *>(component.create());
3387 QVERIFY(!o->property("a").isValid());
3392 void tst_qdeclarativeecmascript::functionAssignment_fromJS()
3394 QFETCH(QString, triggerProperty);
3396 QDeclarativeComponent component(&engine, TEST_FILE("functionAssignment.2.qml"));
3397 QVERIFY2(component.errorString().isEmpty(), qPrintable(component.errorString()));
3399 MyQmlObject *o = qobject_cast<MyQmlObject *>(component.create());
3401 QVERIFY(!o->property("a").isValid());
3403 o->setProperty("aNumber", QVariant(5));
3404 o->setProperty(triggerProperty.toUtf8().constData(), true);
3405 QCOMPARE(o->property("a"), QVariant(50));
3407 o->setProperty("aNumber", QVariant(10));
3408 QCOMPARE(o->property("a"), QVariant(100));
3413 void tst_qdeclarativeecmascript::functionAssignment_fromJS_data()
3415 QTest::addColumn<QString>("triggerProperty");
3417 QTest::newRow("assign to property") << "assignToProperty";
3418 QTest::newRow("assign to property, from JS file") << "assignToPropertyFromJsFile";
3420 QTest::newRow("assign to value type") << "assignToValueType";
3422 QTest::newRow("use 'this'") << "assignWithThis";
3423 QTest::newRow("use 'this' from JS file") << "assignWithThisFromJsFile";
3426 void tst_qdeclarativeecmascript::functionAssignmentfromJS_invalid()
3428 QDeclarativeComponent component(&engine, TEST_FILE("functionAssignment.2.qml"));
3429 QVERIFY2(component.errorString().isEmpty(), qPrintable(component.errorString()));
3431 MyQmlObject *o = qobject_cast<MyQmlObject *>(component.create());
3433 QVERIFY(!o->property("a").isValid());
3435 o->setProperty("assignFuncWithoutReturn", true);
3436 QVERIFY(!o->property("a").isValid());
3438 QString url = component.url().toString();
3439 QString warning = url + ":67: Unable to assign QString to int";
3440 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
3441 o->setProperty("assignWrongType", true);
3443 warning = url + ":71: Unable to assign QString to int";
3444 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
3445 o->setProperty("assignWrongTypeToValueType", true);
3450 void tst_qdeclarativeecmascript::eval()
3452 QDeclarativeComponent component(&engine, TEST_FILE("eval.qml"));
3454 QObject *o = component.create();
3457 QCOMPARE(o->property("test1").toBool(), true);
3458 QCOMPARE(o->property("test2").toBool(), true);
3459 QCOMPARE(o->property("test3").toBool(), true);
3460 QCOMPARE(o->property("test4").toBool(), true);
3461 QCOMPARE(o->property("test5").toBool(), true);
3466 void tst_qdeclarativeecmascript::function()
3468 QDeclarativeComponent component(&engine, TEST_FILE("function.qml"));
3470 QObject *o = component.create();
3473 QCOMPARE(o->property("test1").toBool(), true);
3474 QCOMPARE(o->property("test2").toBool(), true);
3475 QCOMPARE(o->property("test3").toBool(), true);
3480 // Test the "Qt.include" method
3481 void tst_qdeclarativeecmascript::include()
3483 // Non-library relative include
3485 QDeclarativeComponent component(&engine, TEST_FILE("include.qml"));
3486 QObject *o = component.create();
3489 QCOMPARE(o->property("test0").toInt(), 99);
3490 QCOMPARE(o->property("test1").toBool(), true);
3491 QCOMPARE(o->property("test2").toBool(), true);
3492 QCOMPARE(o->property("test2_1").toBool(), true);
3493 QCOMPARE(o->property("test3").toBool(), true);
3494 QCOMPARE(o->property("test3_1").toBool(), true);
3499 // Library relative include
3501 QDeclarativeComponent component(&engine, TEST_FILE("include_shared.qml"));
3502 QObject *o = component.create();
3505 QCOMPARE(o->property("test0").toInt(), 99);
3506 QCOMPARE(o->property("test1").toBool(), true);
3507 QCOMPARE(o->property("test2").toBool(), true);
3508 QCOMPARE(o->property("test2_1").toBool(), true);
3509 QCOMPARE(o->property("test3").toBool(), true);
3510 QCOMPARE(o->property("test3_1").toBool(), true);
3517 QDeclarativeComponent component(&engine, TEST_FILE("include_callback.qml"));
3518 QObject *o = component.create();
3521 QCOMPARE(o->property("test1").toBool(), true);
3522 QCOMPARE(o->property("test2").toBool(), true);
3523 QCOMPARE(o->property("test3").toBool(), true);
3524 QCOMPARE(o->property("test4").toBool(), true);
3525 QCOMPARE(o->property("test5").toBool(), true);
3526 QCOMPARE(o->property("test6").toBool(), true);
3531 // Including file with ".pragma library"
3533 QDeclarativeComponent component(&engine, TEST_FILE("include_pragma.qml"));
3534 QObject *o = component.create();
3536 QCOMPARE(o->property("test1").toInt(), 100);
3543 TestHTTPServer server(8111);
3544 QVERIFY(server.isValid());
3545 server.serveDirectory(SRCDIR "/data");
3547 QDeclarativeComponent component(&engine, TEST_FILE("include_remote.qml"));
3548 QObject *o = component.create();
3551 QTRY_VERIFY(o->property("done").toBool() == true);
3552 QTRY_VERIFY(o->property("done2").toBool() == true);
3554 QCOMPARE(o->property("test1").toBool(), true);
3555 QCOMPARE(o->property("test2").toBool(), true);
3556 QCOMPARE(o->property("test3").toBool(), true);
3557 QCOMPARE(o->property("test4").toBool(), true);
3558 QCOMPARE(o->property("test5").toBool(), true);
3560 QCOMPARE(o->property("test6").toBool(), true);
3561 QCOMPARE(o->property("test7").toBool(), true);
3562 QCOMPARE(o->property("test8").toBool(), true);
3563 QCOMPARE(o->property("test9").toBool(), true);
3564 QCOMPARE(o->property("test10").toBool(), true);
3571 TestHTTPServer server(8111);
3572 QVERIFY(server.isValid());
3573 server.serveDirectory(SRCDIR "/data");
3575 QDeclarativeComponent component(&engine, TEST_FILE("include_remote_missing.qml"));
3576 QObject *o = component.create();
3579 QTRY_VERIFY(o->property("done").toBool() == true);
3581 QCOMPARE(o->property("test1").toBool(), true);
3582 QCOMPARE(o->property("test2").toBool(), true);
3583 QCOMPARE(o->property("test3").toBool(), true);
3589 void tst_qdeclarativeecmascript::qtbug_10696()
3591 QDeclarativeComponent component(&engine, TEST_FILE("qtbug_10696.qml"));
3592 QObject *o = component.create();
3597 void tst_qdeclarativeecmascript::qtbug_11606()
3599 QDeclarativeComponent component(&engine, TEST_FILE("qtbug_11606.qml"));
3600 QObject *o = component.create();
3602 QCOMPARE(o->property("test").toBool(), true);
3606 void tst_qdeclarativeecmascript::qtbug_11600()
3608 QDeclarativeComponent component(&engine, TEST_FILE("qtbug_11600.qml"));
3609 QObject *o = component.create();
3611 QCOMPARE(o->property("test").toBool(), true);
3615 // Reading and writing non-scriptable properties should fail
3616 void tst_qdeclarativeecmascript::nonscriptable()
3618 QDeclarativeComponent component(&engine, TEST_FILE("nonscriptable.qml"));
3619 QObject *o = component.create();
3621 QCOMPARE(o->property("readOk").toBool(), true);
3622 QCOMPARE(o->property("writeOk").toBool(), true);
3626 // deleteLater() should not be callable from QML
3627 void tst_qdeclarativeecmascript::deleteLater()
3629 QDeclarativeComponent component(&engine, TEST_FILE("deleteLater.qml"));
3630 QObject *o = component.create();
3632 QCOMPARE(o->property("test").toBool(), true);
3636 void tst_qdeclarativeecmascript::in()
3638 QDeclarativeComponent component(&engine, TEST_FILE("in.qml"));
3639 QObject *o = component.create();
3641 QCOMPARE(o->property("test1").toBool(), true);
3642 QCOMPARE(o->property("test2").toBool(), true);
3646 void tst_qdeclarativeecmascript::sharedAttachedObject()
3648 QDeclarativeComponent component(&engine, TEST_FILE("sharedAttachedObject.qml"));
3649 QObject *o = component.create();
3651 QCOMPARE(o->property("test1").toBool(), true);
3652 QCOMPARE(o->property("test2").toBool(), true);
3657 void tst_qdeclarativeecmascript::objectName()
3659 QDeclarativeComponent component(&engine, TEST_FILE("objectName.qml"));
3660 QObject *o = component.create();
3663 QCOMPARE(o->property("test1").toString(), QString("hello"));
3664 QCOMPARE(o->property("test2").toString(), QString("ell"));
3666 o->setObjectName("world");
3668 QCOMPARE(o->property("test1").toString(), QString("world"));
3669 QCOMPARE(o->property("test2").toString(), QString("orl"));
3674 void tst_qdeclarativeecmascript::writeRemovesBinding()
3676 QDeclarativeComponent component(&engine, TEST_FILE("writeRemovesBinding.qml"));
3677 QObject *o = component.create();
3680 QCOMPARE(o->property("test").toBool(), true);
3685 // Test bindings assigned to alias properties actually assign to the alias' target
3686 void tst_qdeclarativeecmascript::aliasBindingsAssignCorrectly()
3688 QDeclarativeComponent component(&engine, TEST_FILE("aliasBindingsAssignCorrectly.qml"));
3689 QObject *o = component.create();
3692 QCOMPARE(o->property("test").toBool(), true);
3697 // Test bindings assigned to alias properties override a binding on the target (QTBUG-13719)
3698 void tst_qdeclarativeecmascript::aliasBindingsOverrideTarget()
3701 QDeclarativeComponent component(&engine, TEST_FILE("aliasBindingsOverrideTarget.qml"));
3702 QObject *o = component.create();
3705 QCOMPARE(o->property("test").toBool(), true);
3711 QDeclarativeComponent component(&engine, TEST_FILE("aliasBindingsOverrideTarget.2.qml"));
3712 QObject *o = component.create();
3715 QCOMPARE(o->property("test").toBool(), true);
3721 QDeclarativeComponent component(&engine, TEST_FILE("aliasBindingsOverrideTarget.3.qml"));
3722 QObject *o = component.create();
3725 QCOMPARE(o->property("test").toBool(), true);
3731 // Test that writes to alias properties override bindings on the alias target (QTBUG-13719)
3732 void tst_qdeclarativeecmascript::aliasWritesOverrideBindings()
3735 QDeclarativeComponent component(&engine, TEST_FILE("aliasWritesOverrideBindings.qml"));
3736 QObject *o = component.create();
3739 QCOMPARE(o->property("test").toBool(), true);
3745 QDeclarativeComponent component(&engine, TEST_FILE("aliasWritesOverrideBindings.2.qml"));
3746 QObject *o = component.create();
3749 QCOMPARE(o->property("test").toBool(), true);
3755 QDeclarativeComponent component(&engine, TEST_FILE("aliasWritesOverrideBindings.3.qml"));
3756 QObject *o = component.create();
3759 QCOMPARE(o->property("test").toBool(), true);
3765 // Allow an alais to a composite element
3767 void tst_qdeclarativeecmascript::aliasToCompositeElement()
3769 QDeclarativeComponent component(&engine, TEST_FILE("aliasToCompositeElement.qml"));
3771 QObject *object = component.create();
3772 QVERIFY(object != 0);
3777 void tst_qdeclarativeecmascript::revisionErrors()
3780 QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevisionErrors.qml"));
3781 QString url = component.url().toString();
3783 QString warning1 = url + ":8: ReferenceError: Can't find variable: prop2";
3784 QString warning2 = url + ":11: ReferenceError: Can't find variable: prop2";
3785 QString warning3 = url + ":13: ReferenceError: Can't find variable: method2";
3787 QTest::ignoreMessage(QtWarningMsg, warning1.toLatin1().constData());
3788 QTest::ignoreMessage(QtWarningMsg, warning2.toLatin1().constData());
3789 QTest::ignoreMessage(QtWarningMsg, warning3.toLatin1().constData());
3790 MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create());
3791 QVERIFY(object != 0);
3795 QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevisionErrors2.qml"));
3796 QString url = component.url().toString();
3798 // MyRevisionedSubclass 1.0 uses MyRevisionedClass revision 0
3799 // method2, prop2 from MyRevisionedClass not available
3800 // method4, prop4 from MyRevisionedSubclass not available
3801 QString warning1 = url + ":8: ReferenceError: Can't find variable: prop2";
3802 QString warning2 = url + ":14: ReferenceError: Can't find variable: prop2";
3803 QString warning3 = url + ":10: ReferenceError: Can't find variable: prop4";
3804 QString warning4 = url + ":16: ReferenceError: Can't find variable: prop4";
3805 QString warning5 = url + ":20: ReferenceError: Can't find variable: method2";
3807 QTest::ignoreMessage(QtWarningMsg, warning1.toLatin1().constData());
3808 QTest::ignoreMessage(QtWarningMsg, warning2.toLatin1().constData());
3809 QTest::ignoreMessage(QtWarningMsg, warning3.toLatin1().constData());
3810 QTest::ignoreMessage(QtWarningMsg, warning4.toLatin1().constData());
3811 QTest::ignoreMessage(QtWarningMsg, warning5.toLatin1().constData());
3812 MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create());
3813 QVERIFY(object != 0);
3817 QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevisionErrors3.qml"));
3818 QString url = component.url().toString();
3820 // MyRevisionedSubclass 1.1 uses MyRevisionedClass revision 1
3821 // All properties/methods available, except MyRevisionedBaseClassUnregistered rev 1
3822 QString warning1 = url + ":30: ReferenceError: Can't find variable: methodD";
3823 QString warning2 = url + ":10: ReferenceError: Can't find variable: propD";
3824 QString warning3 = url + ":20: ReferenceError: Can't find variable: propD";
3825 QTest::ignoreMessage(QtWarningMsg, warning1.toLatin1().constData());
3826 QTest::ignoreMessage(QtWarningMsg, warning2.toLatin1().constData());
3827 QTest::ignoreMessage(QtWarningMsg, warning3.toLatin1().constData());
3828 MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create());
3829 QVERIFY(object != 0);
3834 void tst_qdeclarativeecmascript::revision()
3837 QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevision.qml"));
3838 QString url = component.url().toString();
3840 MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create());
3841 QVERIFY(object != 0);
3845 QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevision2.qml"));
3846 QString url = component.url().toString();
3848 MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create());
3849 QVERIFY(object != 0);
3853 QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevision3.qml"));
3854 QString url = component.url().toString();
3856 MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create());
3857 QVERIFY(object != 0);
3860 // Test that non-root classes can resolve revisioned methods
3862 QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevision4.qml"));
3864 QObject *object = component.create();
3865 QVERIFY(object != 0);
3866 QCOMPARE(object->property("test").toReal(), 11.);
3871 void tst_qdeclarativeecmascript::realToInt()
3873 QDeclarativeComponent component(&engine, TEST_FILE("realToInt.qml"));
3874 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
3875 QVERIFY(object != 0);
3877 QMetaObject::invokeMethod(object, "test1");
3878 QCOMPARE(object->value(), int(4));
3879 QMetaObject::invokeMethod(object, "test2");
3880 QCOMPARE(object->value(), int(8));
3882 void tst_qdeclarativeecmascript::dynamicString()
3884 QDeclarativeComponent component(&engine, TEST_FILE("dynamicString.qml"));
3885 QObject *object = component.create();
3886 QVERIFY(object != 0);
3887 QCOMPARE(object->property("stringProperty").toString(),
3888 QString::fromLatin1("string:Hello World false:0 true:1 uint32:100 int32:-100 double:3.14159 date:2011-02-11 05::30:50!"));
3891 QTEST_MAIN(tst_qdeclarativeecmascript)
3893 #include "tst_qdeclarativeecmascript.moc"