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 module API enum values in JS")
2819 << TEST_FILE("moduleapi/qobjectModuleApiEnums.qml")
2822 << (QStringList() << "enumValue" << "enumMethod")
2823 << (QVariantList() << 42 << 30)
2829 QTest::newRow("qobject, invalid major version fail")
2830 << TEST_FILE("moduleapi/moduleApiMajorVersionFail.qml")
2831 << QString("QDeclarativeComponent: Component is not ready")
2840 QTest::newRow("qobject, invalid minor version fail")
2841 << TEST_FILE("moduleapi/moduleApiMinorVersionFail.qml")
2842 << QString("QDeclarativeComponent: Component is not ready")
2852 void tst_qdeclarativeecmascript::moduleApi()
2854 QFETCH(QUrl, testfile);
2855 QFETCH(QString, errorMessage);
2856 QFETCH(QStringList, warningMessages);
2857 QFETCH(QStringList, readProperties);
2858 QFETCH(QVariantList, readExpectedValues);
2859 QFETCH(QStringList, writeProperties);
2860 QFETCH(QVariantList, writeValues);
2861 QFETCH(QStringList, readBackProperties);
2862 QFETCH(QVariantList, readBackExpectedValues);
2864 QDeclarativeComponent component(&engine, testfile);
2866 if (!errorMessage.isEmpty())
2867 QTest::ignoreMessage(QtWarningMsg, errorMessage.toAscii().constData());
2869 if (warningMessages.size())
2870 foreach (const QString &warning, warningMessages)
2871 QTest::ignoreMessage(QtWarningMsg, warning.toAscii().constData());
2873 QObject *object = component.create();
2874 if (!errorMessage.isEmpty()) {
2875 QVERIFY(object == 0);
2877 QVERIFY(object != 0);
2878 for (int i = 0; i < readProperties.size(); ++i)
2879 QCOMPARE(object->property(readProperties.at(i).toAscii().constData()), readExpectedValues.at(i));
2880 for (int i = 0; i < writeProperties.size(); ++i)
2881 QVERIFY(object->setProperty(writeProperties.at(i).toAscii().constData(), writeValues.at(i)));
2882 for (int i = 0; i < readBackProperties.size(); ++i)
2883 QCOMPARE(object->property(readBackProperties.at(i).toAscii().constData()), readBackExpectedValues.at(i));
2888 void tst_qdeclarativeecmascript::importScripts()
2890 QObject *object = 0;
2892 // first, ensure that the required behaviour works.
2893 QDeclarativeComponent component(&engine, TEST_FILE("jsimport/testImport.qml"));
2894 object = component.create();
2895 QVERIFY(object != 0);
2896 QCOMPARE(object->property("importedScriptStringValue"), QVariant(QString(QLatin1String("Hello, World!"))));
2897 QCOMPARE(object->property("importedScriptFunctionValue"), QVariant(20));
2898 QCOMPARE(object->property("importedModuleAttachedPropertyValue"), QVariant(19));
2899 QCOMPARE(object->property("importedModuleEnumValue"), QVariant(2));
2902 QDeclarativeComponent componentTwo(&engine, TEST_FILE("jsimport/testImportScoping.qml"));
2903 object = componentTwo.create();
2904 QVERIFY(object != 0);
2905 QCOMPARE(object->property("componentError"), QVariant(5));
2908 // then, ensure that unintended behaviour does not work.
2909 QDeclarativeComponent failOneComponent(&engine, TEST_FILE("jsimportfail/failOne.qml"));
2910 QString expectedWarning = QLatin1String("file://") + TEST_FILE("jsimportfail/failOne.qml").toLocalFile() + QLatin1String(":6: TypeError: Cannot call method 'greetingString' of undefined");
2911 QTest::ignoreMessage(QtWarningMsg, expectedWarning.toAscii().constData());
2912 object = failOneComponent.create();
2913 QVERIFY(object != 0);
2914 QVERIFY(object->property("importScriptFunctionValue").toString().isEmpty());
2916 QDeclarativeComponent failTwoComponent(&engine, TEST_FILE("jsimportfail/failTwo.qml"));
2917 expectedWarning = QLatin1String("file://") + TEST_FILE("jsimportfail/failTwo.qml").toLocalFile() + QLatin1String(":6: ReferenceError: Can't find variable: ImportOneJs");
2918 QTest::ignoreMessage(QtWarningMsg, expectedWarning.toAscii().constData());
2919 object = failTwoComponent.create();
2920 QVERIFY(object != 0);
2921 QVERIFY(object->property("importScriptFunctionValue").toString().isEmpty());
2923 QDeclarativeComponent failThreeComponent(&engine, TEST_FILE("jsimportfail/failThree.qml"));
2924 expectedWarning = QLatin1String("file://") + TEST_FILE("jsimportfail/failThree.qml").toLocalFile() + QLatin1String(":7: TypeError: Cannot read property 'JsQtTest' of undefined");
2925 QTest::ignoreMessage(QtWarningMsg, expectedWarning.toAscii().constData());
2926 object = failThreeComponent.create();
2927 QVERIFY(object != 0);
2928 QCOMPARE(object->property("importedModuleAttachedPropertyValue"), QVariant(false));
2930 QDeclarativeComponent failFourComponent(&engine, TEST_FILE("jsimportfail/failFour.qml"));
2931 expectedWarning = QLatin1String("file://") + TEST_FILE("jsimportfail/failFour.qml").toLocalFile() + QLatin1String(":6: ReferenceError: Can't find variable: JsQtTest");
2932 QTest::ignoreMessage(QtWarningMsg, expectedWarning.toAscii().constData());
2933 object = failFourComponent.create();
2934 QVERIFY(object != 0);
2935 QCOMPARE(object->property("importedModuleEnumValue"), QVariant(0));
2937 QDeclarativeComponent failFiveComponent(&engine, TEST_FILE("jsimportfail/failFive.qml"));
2938 expectedWarning = QLatin1String("file://") + TEST_FILE("jsimportfail/importWithImports.js").toLocalFile() + QLatin1String(":8: ReferenceError: Can't find variable: Component");
2939 QTest::ignoreMessage(QtWarningMsg, expectedWarning.toAscii().constData());
2940 expectedWarning = QLatin1String("file://") + TEST_FILE("jsimportfail/importPragmaLibrary.js").toLocalFile() + QLatin1String(":6: ReferenceError: Can't find variable: Component");
2941 QTest::ignoreMessage(QtWarningMsg, expectedWarning.toAscii().constData());
2942 object = failFiveComponent.create();
2943 QVERIFY(object != 0);
2944 QCOMPARE(object->property("componentError"), QVariant(0));
2947 // also, test that importing scripts with .pragma library works as required
2948 QDeclarativeComponent pragmaLibraryComponent(&engine, TEST_FILE("jsimport/testImportPragmaLibrary.qml"));
2949 object = pragmaLibraryComponent.create();
2950 QVERIFY(object != 0);
2951 QCOMPARE(object->property("testValue"), QVariant(31));
2954 // and that .pragma library scripts don't inherit imports from any .qml file
2955 QDeclarativeComponent pragmaLibraryComponentTwo(&engine, TEST_FILE("jsimportfail/testImportPragmaLibrary.qml"));
2956 object = pragmaLibraryComponentTwo.create();
2957 QVERIFY(object != 0);
2958 QCOMPARE(object->property("testValue"), QVariant(0));
2962 void tst_qdeclarativeecmascript::scarceResources()
2964 QPixmap origPixmap(100, 100);
2965 origPixmap.fill(Qt::blue);
2967 QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(&engine);
2968 ScarceResourceObject *eo = 0;
2969 QObject *object = 0;
2971 // in the following three cases, the instance created from the component
2972 // has a property which is a copy of the scarce resource; hence, the
2973 // resource should NOT be detached prior to deletion of the object instance,
2974 // unless the resource is destroyed explicitly.
2975 QDeclarativeComponent component(&engine, TEST_FILE("scarceresources/scarceResourceCopy.qml"));
2976 object = component.create();
2977 QVERIFY(object != 0);
2978 QVERIFY(object->property("scarceResourceCopy").isValid());
2979 QCOMPARE(object->property("scarceResourceCopy").value<QPixmap>(), origPixmap);
2980 QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
2981 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2982 QVERIFY(!eo->scarceResourceIsDetached()); // there are two copies of it in existence: the property of object, and the property of eo.
2985 QDeclarativeComponent componentTwo(&engine, TEST_FILE("scarceresources/scarceResourceCopyFromJs.qml"));
2986 object = componentTwo.create();
2987 QVERIFY(object != 0);
2988 QVERIFY(object->property("scarceResourceCopy").isValid());
2989 QCOMPARE(object->property("scarceResourceCopy").value<QPixmap>(), origPixmap);
2990 QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
2991 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2992 QVERIFY(!eo->scarceResourceIsDetached()); // there are two copies of it in existence: the property of object, and the property of eo.
2995 QDeclarativeComponent componentThree(&engine, TEST_FILE("scarceresources/scarceResourceDestroyedCopy.qml"));
2996 object = componentThree.create();
2997 QVERIFY(object != 0);
2998 QVERIFY(!(object->property("scarceResourceCopy").isValid())); // was manually released prior to being returned.
2999 QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
3000 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
3001 QVERIFY(eo->scarceResourceIsDetached()); // should have explicitly been released during the evaluation of the binding.
3004 // in the following three cases, no other copy should exist in memory,
3005 // and so it should be detached (unless explicitly preserved).
3006 QDeclarativeComponent componentFour(&engine, TEST_FILE("scarceresources/scarceResourceTest.qml"));
3007 object = componentFour.create();
3008 QVERIFY(object != 0);
3009 QVERIFY(object->property("scarceResourceTest").isValid());
3010 QCOMPARE(object->property("scarceResourceTest").toInt(), 100);
3011 QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
3012 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
3013 QVERIFY(eo->scarceResourceIsDetached()); // the resource should have been released after the binding was evaluated.
3016 QDeclarativeComponent componentFive(&engine, TEST_FILE("scarceresources/scarceResourceTestPreserve.qml"));
3017 object = componentFive.create();
3018 QVERIFY(object != 0);
3019 QVERIFY(object->property("scarceResourceTest").isValid());
3020 QCOMPARE(object->property("scarceResourceTest").toInt(), 100);
3021 QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
3022 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
3023 QVERIFY(!eo->scarceResourceIsDetached()); // this won't be detached since we explicitly preserved it.
3026 QDeclarativeComponent componentSix(&engine, TEST_FILE("scarceresources/scarceResourceTestMultiple.qml"));
3027 object = componentSix.create();
3028 QVERIFY(object != 0);
3029 QVERIFY(object->property("scarceResourceTest").isValid());
3030 QCOMPARE(object->property("scarceResourceTest").toInt(), 100);
3031 QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
3032 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
3033 QVERIFY(eo->scarceResourceIsDetached()); // all resources were released manually or automatically released.
3036 // test that scarce resources are handled correctly for imports
3037 QDeclarativeComponent componentSeven(&engine, TEST_FILE("scarceresources/scarceResourceCopyImportNoBinding.qml"));
3038 object = componentSeven.create();
3039 QVERIFY(object != 0); // the import should have caused the addition of a resource to the ScarceResources list
3040 QVERIFY(ep->scarceResources.isEmpty()); // but they should have been released by this point.
3043 QDeclarativeComponent componentEight(&engine, TEST_FILE("scarceresources/scarceResourceCopyImportFail.qml"));
3044 object = componentEight.create();
3045 QVERIFY(object != 0);
3046 QVERIFY(!object->property("scarceResourceCopy").isValid()); // wasn't preserved, so shouldn't be valid.
3047 QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
3050 QDeclarativeComponent componentNine(&engine, TEST_FILE("scarceresources/scarceResourceCopyImport.qml"));
3051 object = componentNine.create();
3052 QVERIFY(object != 0);
3053 QVERIFY(object->property("scarceResourceCopy").isValid()); // preserved, so should be valid.
3054 QCOMPARE(object->property("scarceResourceCopy").value<QPixmap>(), origPixmap);
3055 QVERIFY(object->property("scarceResourceAssignedCopyOne").isValid()); // assigned before destroy(), so should be valid.
3056 QCOMPARE(object->property("scarceResourceAssignedCopyOne").value<QPixmap>(), origPixmap);
3057 QVERIFY(!object->property("scarceResourceAssignedCopyTwo").isValid()); // assigned after destroy(), so should be invalid.
3058 QVERIFY(ep->scarceResources.isEmpty()); // this will still be zero, because "preserve()" REMOVES it from this list.
3061 // test that scarce resources are handled properly in signal invocation
3062 QDeclarativeComponent componentTen(&engine, TEST_FILE("scarceresources/scarceResourceSignal.qml"));
3063 object = componentTen.create();
3064 QVERIFY(object != 0);
3065 QObject *srsc = object->findChild<QObject*>("srsc");
3067 QVERIFY(!srsc->property("scarceResourceCopy").isValid()); // hasn't been instantiated yet.
3068 QCOMPARE(srsc->property("width"), QVariant(5)); // default value is 5.
3069 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
3070 QVERIFY(eo->scarceResourceIsDetached()); // should be no other copies of it at this stage.
3071 QMetaObject::invokeMethod(srsc, "testSignal");
3072 QVERIFY(!srsc->property("scarceResourceCopy").isValid()); // still hasn't been instantiated
3073 QCOMPARE(srsc->property("width"), QVariant(10)); // but width was assigned to 10.
3074 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
3075 QVERIFY(eo->scarceResourceIsDetached()); // should still be no other copies of it at this stage.
3076 QMetaObject::invokeMethod(srsc, "testSignal2"); // assigns scarceResourceCopy to the scarce pixmap.
3077 QVERIFY(srsc->property("scarceResourceCopy").isValid());
3078 QCOMPARE(srsc->property("scarceResourceCopy").value<QPixmap>(), origPixmap);
3079 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
3080 QVERIFY(!(eo->scarceResourceIsDetached())); // should be another copy of the resource now.
3081 QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
3084 // test that scarce resources are handled properly from js functions in qml files
3085 QDeclarativeComponent componentEleven(&engine, TEST_FILE("scarceresources/scarceResourceFunction.qml"));
3086 object = componentEleven.create();
3087 QVERIFY(object != 0);
3088 QVERIFY(!object->property("scarceResourceCopy").isValid()); // not yet assigned, so should not be valid
3089 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
3090 QVERIFY(eo->scarceResourceIsDetached()); // should be no other copies of it at this stage.
3091 QMetaObject::invokeMethod(object, "retrieveScarceResource");
3092 QVERIFY(object->property("scarceResourceCopy").isValid()); // assigned, so should be valid.
3093 QCOMPARE(object->property("scarceResourceCopy").value<QPixmap>(), origPixmap);
3094 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
3095 QVERIFY(!eo->scarceResourceIsDetached()); // should be a copy of the resource at this stage.
3096 QMetaObject::invokeMethod(object, "releaseScarceResource");
3097 QVERIFY(!object->property("scarceResourceCopy").isValid()); // just released, so should not be valid
3098 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
3099 QVERIFY(eo->scarceResourceIsDetached()); // should be no other copies of it at this stage.
3100 QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
3103 // test that if an exception occurs while invoking js function from cpp, that the resources are released.
3104 QDeclarativeComponent componentTwelve(&engine, TEST_FILE("scarceresources/scarceResourceFunctionFail.qml"));
3105 object = componentTwelve.create();
3106 QVERIFY(object != 0);
3107 QVERIFY(!object->property("scarceResourceCopy").isValid()); // not yet assigned, so should not be valid
3108 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
3109 QVERIFY(eo->scarceResourceIsDetached()); // should be no other copies of it at this stage.
3110 QString srp_name = object->property("srp_name").toString();
3111 QString expectedWarning = componentTwelve.url().toString() + QLatin1String(":17: TypeError: Property 'scarceResource' of object ") + srp_name + QLatin1String(" is not a function");
3112 QTest::ignoreMessage(QtWarningMsg, qPrintable(expectedWarning)); // we expect a meaningful warning to be printed.
3113 QMetaObject::invokeMethod(object, "retrieveScarceResource");
3114 QVERIFY(!object->property("scarceResourceCopy").isValid()); // due to exception, assignment will NOT have occurred.
3115 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
3116 QVERIFY(eo->scarceResourceIsDetached()); // should be no other copies of it at this stage.
3117 QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
3121 void tst_qdeclarativeecmascript::propertyChangeSlots()
3123 // ensure that allowable property names are allowed and onPropertyNameChanged slots are generated correctly.
3124 QDeclarativeComponent component(&engine, TEST_FILE("changeslots/propertyChangeSlots.qml"));
3125 QObject *object = component.create();
3126 QVERIFY(object != 0);
3129 // ensure that invalid property names fail properly.
3130 QTest::ignoreMessage(QtWarningMsg, "QDeclarativeComponent: Component is not ready");
3131 QDeclarativeComponent e1(&engine, TEST_FILE("changeslots/propertyChangeSlotErrors.1.qml"));
3132 QString expectedErrorString = e1.url().toString() + QLatin1String(":9:5: Cannot assign to non-existent property \"on_nameWithUnderscoreChanged\"");
3133 QCOMPARE(e1.errors().at(0).toString(), expectedErrorString);
3134 object = e1.create();
3135 QVERIFY(object == 0);
3138 QTest::ignoreMessage(QtWarningMsg, "QDeclarativeComponent: Component is not ready");
3139 QDeclarativeComponent e2(&engine, TEST_FILE("changeslots/propertyChangeSlotErrors.2.qml"));
3140 expectedErrorString = e2.url().toString() + QLatin1String(":9:5: Cannot assign to non-existent property \"on____nameWithUnderscoresChanged\"");
3141 QCOMPARE(e2.errors().at(0).toString(), expectedErrorString);
3142 object = e2.create();
3143 QVERIFY(object == 0);
3146 QTest::ignoreMessage(QtWarningMsg, "QDeclarativeComponent: Component is not ready");
3147 QDeclarativeComponent e3(&engine, TEST_FILE("changeslots/propertyChangeSlotErrors.3.qml"));
3148 expectedErrorString = e3.url().toString() + QLatin1String(":9:5: Cannot assign to non-existent property \"on$NameWithDollarsignChanged\"");
3149 QCOMPARE(e3.errors().at(0).toString(), expectedErrorString);
3150 object = e3.create();
3151 QVERIFY(object == 0);
3154 QTest::ignoreMessage(QtWarningMsg, "QDeclarativeComponent: Component is not ready");
3155 QDeclarativeComponent e4(&engine, TEST_FILE("changeslots/propertyChangeSlotErrors.4.qml"));
3156 expectedErrorString = e4.url().toString() + QLatin1String(":9:5: Cannot assign to non-existent property \"on_6NameWithUnderscoreNumberChanged\"");
3157 QCOMPARE(e4.errors().at(0).toString(), expectedErrorString);
3158 object = e4.create();
3159 QVERIFY(object == 0);
3163 // Ensure that QObject type conversion works on binding assignment
3164 void tst_qdeclarativeecmascript::elementAssign()
3166 QDeclarativeComponent component(&engine, TEST_FILE("elementAssign.qml"));
3168 QObject *object = component.create();
3169 QVERIFY(object != 0);
3171 QCOMPARE(object->property("test").toBool(), true);
3177 void tst_qdeclarativeecmascript::objectPassThroughSignals()
3179 QDeclarativeComponent component(&engine, TEST_FILE("objectsPassThroughSignals.qml"));
3181 QObject *object = component.create();
3182 QVERIFY(object != 0);
3184 QCOMPARE(object->property("test").toBool(), true);
3190 void tst_qdeclarativeecmascript::booleanConversion()
3192 QDeclarativeComponent component(&engine, TEST_FILE("booleanConversion.qml"));
3194 QObject *object = component.create();
3195 QVERIFY(object != 0);
3197 QCOMPARE(object->property("test_true1").toBool(), true);
3198 QCOMPARE(object->property("test_true2").toBool(), true);
3199 QCOMPARE(object->property("test_true3").toBool(), true);
3200 QCOMPARE(object->property("test_true4").toBool(), true);
3201 QCOMPARE(object->property("test_true5").toBool(), true);
3203 QCOMPARE(object->property("test_false1").toBool(), false);
3204 QCOMPARE(object->property("test_false2").toBool(), false);
3205 QCOMPARE(object->property("test_false3").toBool(), false);
3210 // Test that assigning a null object works
3211 // Regressed with: df1788b4dbbb2826ae63f26bdf166342595343f4
3212 void tst_qdeclarativeecmascript::nullObjectBinding()
3214 QDeclarativeComponent component(&engine, TEST_FILE("nullObjectBinding.qml"));
3216 QObject *object = component.create();
3217 QVERIFY(object != 0);
3219 QVERIFY(object->property("test") == QVariant::fromValue((QObject *)0));
3224 // Test that bindings don't evaluate once the engine has been destroyed
3225 void tst_qdeclarativeecmascript::deletedEngine()
3227 QDeclarativeEngine *engine = new QDeclarativeEngine;
3228 QDeclarativeComponent component(engine, TEST_FILE("deletedEngine.qml"));
3230 QObject *object = component.create();
3231 QVERIFY(object != 0);
3233 QCOMPARE(object->property("a").toInt(), 39);
3234 object->setProperty("b", QVariant(9));
3235 QCOMPARE(object->property("a").toInt(), 117);
3239 QCOMPARE(object->property("a").toInt(), 117);
3240 object->setProperty("b", QVariant(10));
3241 QCOMPARE(object->property("a").toInt(), 117);
3246 // Test the crashing part of QTBUG-9705
3247 void tst_qdeclarativeecmascript::libraryScriptAssert()
3249 QDeclarativeComponent component(&engine, TEST_FILE("libraryScriptAssert.qml"));
3251 QObject *object = component.create();
3252 QVERIFY(object != 0);
3257 void tst_qdeclarativeecmascript::variantsAssignedUndefined()
3259 QDeclarativeComponent component(&engine, TEST_FILE("variantsAssignedUndefined.qml"));
3261 QObject *object = component.create();
3262 QVERIFY(object != 0);
3264 QCOMPARE(object->property("test1").toInt(), 10);
3265 QCOMPARE(object->property("test2").toInt(), 11);
3267 object->setProperty("runTest", true);
3269 QCOMPARE(object->property("test1"), QVariant());
3270 QCOMPARE(object->property("test2"), QVariant());
3276 void tst_qdeclarativeecmascript::qtbug_9792()
3278 QDeclarativeComponent component(&engine, TEST_FILE("qtbug_9792.qml"));
3280 QDeclarativeContext *context = new QDeclarativeContext(engine.rootContext());
3282 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create(context));
3283 QVERIFY(object != 0);
3285 QTest::ignoreMessage(QtDebugMsg, "Hello world!");
3286 object->basicSignal();
3290 transientErrorsMsgCount = 0;
3291 QtMsgHandler old = qInstallMsgHandler(transientErrorsMsgHandler);
3293 object->basicSignal();
3295 qInstallMsgHandler(old);
3297 QCOMPARE(transientErrorsMsgCount, 0);
3302 // Verifies that QDeclarativeGuard<>s used in the vmemetaobject are cleaned correctly
3303 void tst_qdeclarativeecmascript::qtcreatorbug_1289()
3305 QDeclarativeComponent component(&engine, TEST_FILE("qtcreatorbug_1289.qml"));
3307 QObject *o = component.create();
3310 QObject *nested = qvariant_cast<QObject *>(o->property("object"));
3311 QVERIFY(nested != 0);
3313 QVERIFY(qvariant_cast<QObject *>(nested->property("nestedObject")) == o);
3316 nested = qvariant_cast<QObject *>(o->property("object"));
3317 QVERIFY(nested == 0);
3319 // If the bug is present, the next line will crash
3323 // Test that we shut down without stupid warnings
3324 void tst_qdeclarativeecmascript::noSpuriousWarningsAtShutdown()
3327 QDeclarativeComponent component(&engine, TEST_FILE("noSpuriousWarningsAtShutdown.qml"));
3329 QObject *o = component.create();
3331 transientErrorsMsgCount = 0;
3332 QtMsgHandler old = qInstallMsgHandler(transientErrorsMsgHandler);
3336 qInstallMsgHandler(old);
3338 QCOMPARE(transientErrorsMsgCount, 0);
3343 QDeclarativeComponent component(&engine, TEST_FILE("noSpuriousWarningsAtShutdown.2.qml"));
3345 QObject *o = component.create();
3347 transientErrorsMsgCount = 0;
3348 QtMsgHandler old = qInstallMsgHandler(transientErrorsMsgHandler);
3352 qInstallMsgHandler(old);
3354 QCOMPARE(transientErrorsMsgCount, 0);
3358 void tst_qdeclarativeecmascript::canAssignNullToQObject()
3361 QDeclarativeComponent component(&engine, TEST_FILE("canAssignNullToQObject.1.qml"));
3363 MyQmlObject *o = qobject_cast<MyQmlObject *>(component.create());
3366 QVERIFY(o->objectProperty() != 0);
3368 o->setProperty("runTest", true);
3370 QVERIFY(o->objectProperty() == 0);
3376 QDeclarativeComponent component(&engine, TEST_FILE("canAssignNullToQObject.2.qml"));
3378 MyQmlObject *o = qobject_cast<MyQmlObject *>(component.create());
3381 QVERIFY(o->objectProperty() == 0);
3387 void tst_qdeclarativeecmascript::functionAssignment_fromBinding()
3389 QDeclarativeComponent component(&engine, TEST_FILE("functionAssignment.1.qml"));
3391 QString url = component.url().toString();
3392 QString warning = url + ":4: Unable to assign a function to a property.";
3393 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
3395 MyQmlObject *o = qobject_cast<MyQmlObject *>(component.create());
3398 QVERIFY(!o->property("a").isValid());
3403 void tst_qdeclarativeecmascript::functionAssignment_fromJS()
3405 QFETCH(QString, triggerProperty);
3407 QDeclarativeComponent component(&engine, TEST_FILE("functionAssignment.2.qml"));
3408 QVERIFY2(component.errorString().isEmpty(), qPrintable(component.errorString()));
3410 MyQmlObject *o = qobject_cast<MyQmlObject *>(component.create());
3412 QVERIFY(!o->property("a").isValid());
3414 o->setProperty("aNumber", QVariant(5));
3415 o->setProperty(triggerProperty.toUtf8().constData(), true);
3416 QCOMPARE(o->property("a"), QVariant(50));
3418 o->setProperty("aNumber", QVariant(10));
3419 QCOMPARE(o->property("a"), QVariant(100));
3424 void tst_qdeclarativeecmascript::functionAssignment_fromJS_data()
3426 QTest::addColumn<QString>("triggerProperty");
3428 QTest::newRow("assign to property") << "assignToProperty";
3429 QTest::newRow("assign to property, from JS file") << "assignToPropertyFromJsFile";
3431 QTest::newRow("assign to value type") << "assignToValueType";
3433 QTest::newRow("use 'this'") << "assignWithThis";
3434 QTest::newRow("use 'this' from JS file") << "assignWithThisFromJsFile";
3437 void tst_qdeclarativeecmascript::functionAssignmentfromJS_invalid()
3439 QDeclarativeComponent component(&engine, TEST_FILE("functionAssignment.2.qml"));
3440 QVERIFY2(component.errorString().isEmpty(), qPrintable(component.errorString()));
3442 MyQmlObject *o = qobject_cast<MyQmlObject *>(component.create());
3444 QVERIFY(!o->property("a").isValid());
3446 o->setProperty("assignFuncWithoutReturn", true);
3447 QVERIFY(!o->property("a").isValid());
3449 QString url = component.url().toString();
3450 QString warning = url + ":67: Unable to assign QString to int";
3451 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
3452 o->setProperty("assignWrongType", true);
3454 warning = url + ":71: Unable to assign QString to int";
3455 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
3456 o->setProperty("assignWrongTypeToValueType", true);
3461 void tst_qdeclarativeecmascript::eval()
3463 QDeclarativeComponent component(&engine, TEST_FILE("eval.qml"));
3465 QObject *o = component.create();
3468 QCOMPARE(o->property("test1").toBool(), true);
3469 QCOMPARE(o->property("test2").toBool(), true);
3470 QCOMPARE(o->property("test3").toBool(), true);
3471 QCOMPARE(o->property("test4").toBool(), true);
3472 QCOMPARE(o->property("test5").toBool(), true);
3477 void tst_qdeclarativeecmascript::function()
3479 QDeclarativeComponent component(&engine, TEST_FILE("function.qml"));
3481 QObject *o = component.create();
3484 QCOMPARE(o->property("test1").toBool(), true);
3485 QCOMPARE(o->property("test2").toBool(), true);
3486 QCOMPARE(o->property("test3").toBool(), true);
3491 // Test the "Qt.include" method
3492 void tst_qdeclarativeecmascript::include()
3494 // Non-library relative include
3496 QDeclarativeComponent component(&engine, TEST_FILE("include.qml"));
3497 QObject *o = component.create();
3500 QCOMPARE(o->property("test0").toInt(), 99);
3501 QCOMPARE(o->property("test1").toBool(), true);
3502 QCOMPARE(o->property("test2").toBool(), true);
3503 QCOMPARE(o->property("test2_1").toBool(), true);
3504 QCOMPARE(o->property("test3").toBool(), true);
3505 QCOMPARE(o->property("test3_1").toBool(), true);
3510 // Library relative include
3512 QDeclarativeComponent component(&engine, TEST_FILE("include_shared.qml"));
3513 QObject *o = component.create();
3516 QCOMPARE(o->property("test0").toInt(), 99);
3517 QCOMPARE(o->property("test1").toBool(), true);
3518 QCOMPARE(o->property("test2").toBool(), true);
3519 QCOMPARE(o->property("test2_1").toBool(), true);
3520 QCOMPARE(o->property("test3").toBool(), true);
3521 QCOMPARE(o->property("test3_1").toBool(), true);
3528 QDeclarativeComponent component(&engine, TEST_FILE("include_callback.qml"));
3529 QObject *o = component.create();
3532 QCOMPARE(o->property("test1").toBool(), true);
3533 QCOMPARE(o->property("test2").toBool(), true);
3534 QCOMPARE(o->property("test3").toBool(), true);
3535 QCOMPARE(o->property("test4").toBool(), true);
3536 QCOMPARE(o->property("test5").toBool(), true);
3537 QCOMPARE(o->property("test6").toBool(), true);
3542 // Including file with ".pragma library"
3544 QDeclarativeComponent component(&engine, TEST_FILE("include_pragma.qml"));
3545 QObject *o = component.create();
3547 QCOMPARE(o->property("test1").toInt(), 100);
3554 TestHTTPServer server(8111);
3555 QVERIFY(server.isValid());
3556 server.serveDirectory(SRCDIR "/data");
3558 QDeclarativeComponent component(&engine, TEST_FILE("include_remote.qml"));
3559 QObject *o = component.create();
3562 QTRY_VERIFY(o->property("done").toBool() == true);
3563 QTRY_VERIFY(o->property("done2").toBool() == true);
3565 QCOMPARE(o->property("test1").toBool(), true);
3566 QCOMPARE(o->property("test2").toBool(), true);
3567 QCOMPARE(o->property("test3").toBool(), true);
3568 QCOMPARE(o->property("test4").toBool(), true);
3569 QCOMPARE(o->property("test5").toBool(), true);
3571 QCOMPARE(o->property("test6").toBool(), true);
3572 QCOMPARE(o->property("test7").toBool(), true);
3573 QCOMPARE(o->property("test8").toBool(), true);
3574 QCOMPARE(o->property("test9").toBool(), true);
3575 QCOMPARE(o->property("test10").toBool(), true);
3582 TestHTTPServer server(8111);
3583 QVERIFY(server.isValid());
3584 server.serveDirectory(SRCDIR "/data");
3586 QDeclarativeComponent component(&engine, TEST_FILE("include_remote_missing.qml"));
3587 QObject *o = component.create();
3590 QTRY_VERIFY(o->property("done").toBool() == true);
3592 QCOMPARE(o->property("test1").toBool(), true);
3593 QCOMPARE(o->property("test2").toBool(), true);
3594 QCOMPARE(o->property("test3").toBool(), true);
3600 void tst_qdeclarativeecmascript::qtbug_10696()
3602 QDeclarativeComponent component(&engine, TEST_FILE("qtbug_10696.qml"));
3603 QObject *o = component.create();
3608 void tst_qdeclarativeecmascript::qtbug_11606()
3610 QDeclarativeComponent component(&engine, TEST_FILE("qtbug_11606.qml"));
3611 QObject *o = component.create();
3613 QCOMPARE(o->property("test").toBool(), true);
3617 void tst_qdeclarativeecmascript::qtbug_11600()
3619 QDeclarativeComponent component(&engine, TEST_FILE("qtbug_11600.qml"));
3620 QObject *o = component.create();
3622 QCOMPARE(o->property("test").toBool(), true);
3626 // Reading and writing non-scriptable properties should fail
3627 void tst_qdeclarativeecmascript::nonscriptable()
3629 QDeclarativeComponent component(&engine, TEST_FILE("nonscriptable.qml"));
3630 QObject *o = component.create();
3632 QCOMPARE(o->property("readOk").toBool(), true);
3633 QCOMPARE(o->property("writeOk").toBool(), true);
3637 // deleteLater() should not be callable from QML
3638 void tst_qdeclarativeecmascript::deleteLater()
3640 QDeclarativeComponent component(&engine, TEST_FILE("deleteLater.qml"));
3641 QObject *o = component.create();
3643 QCOMPARE(o->property("test").toBool(), true);
3647 void tst_qdeclarativeecmascript::in()
3649 QDeclarativeComponent component(&engine, TEST_FILE("in.qml"));
3650 QObject *o = component.create();
3652 QCOMPARE(o->property("test1").toBool(), true);
3653 QCOMPARE(o->property("test2").toBool(), true);
3657 void tst_qdeclarativeecmascript::sharedAttachedObject()
3659 QDeclarativeComponent component(&engine, TEST_FILE("sharedAttachedObject.qml"));
3660 QObject *o = component.create();
3662 QCOMPARE(o->property("test1").toBool(), true);
3663 QCOMPARE(o->property("test2").toBool(), true);
3668 void tst_qdeclarativeecmascript::objectName()
3670 QDeclarativeComponent component(&engine, TEST_FILE("objectName.qml"));
3671 QObject *o = component.create();
3674 QCOMPARE(o->property("test1").toString(), QString("hello"));
3675 QCOMPARE(o->property("test2").toString(), QString("ell"));
3677 o->setObjectName("world");
3679 QCOMPARE(o->property("test1").toString(), QString("world"));
3680 QCOMPARE(o->property("test2").toString(), QString("orl"));
3685 void tst_qdeclarativeecmascript::writeRemovesBinding()
3687 QDeclarativeComponent component(&engine, TEST_FILE("writeRemovesBinding.qml"));
3688 QObject *o = component.create();
3691 QCOMPARE(o->property("test").toBool(), true);
3696 // Test bindings assigned to alias properties actually assign to the alias' target
3697 void tst_qdeclarativeecmascript::aliasBindingsAssignCorrectly()
3699 QDeclarativeComponent component(&engine, TEST_FILE("aliasBindingsAssignCorrectly.qml"));
3700 QObject *o = component.create();
3703 QCOMPARE(o->property("test").toBool(), true);
3708 // Test bindings assigned to alias properties override a binding on the target (QTBUG-13719)
3709 void tst_qdeclarativeecmascript::aliasBindingsOverrideTarget()
3712 QDeclarativeComponent component(&engine, TEST_FILE("aliasBindingsOverrideTarget.qml"));
3713 QObject *o = component.create();
3716 QCOMPARE(o->property("test").toBool(), true);
3722 QDeclarativeComponent component(&engine, TEST_FILE("aliasBindingsOverrideTarget.2.qml"));
3723 QObject *o = component.create();
3726 QCOMPARE(o->property("test").toBool(), true);
3732 QDeclarativeComponent component(&engine, TEST_FILE("aliasBindingsOverrideTarget.3.qml"));
3733 QObject *o = component.create();
3736 QCOMPARE(o->property("test").toBool(), true);
3742 // Test that writes to alias properties override bindings on the alias target (QTBUG-13719)
3743 void tst_qdeclarativeecmascript::aliasWritesOverrideBindings()
3746 QDeclarativeComponent component(&engine, TEST_FILE("aliasWritesOverrideBindings.qml"));
3747 QObject *o = component.create();
3750 QCOMPARE(o->property("test").toBool(), true);
3756 QDeclarativeComponent component(&engine, TEST_FILE("aliasWritesOverrideBindings.2.qml"));
3757 QObject *o = component.create();
3760 QCOMPARE(o->property("test").toBool(), true);
3766 QDeclarativeComponent component(&engine, TEST_FILE("aliasWritesOverrideBindings.3.qml"));
3767 QObject *o = component.create();
3770 QCOMPARE(o->property("test").toBool(), true);
3776 // Allow an alais to a composite element
3778 void tst_qdeclarativeecmascript::aliasToCompositeElement()
3780 QDeclarativeComponent component(&engine, TEST_FILE("aliasToCompositeElement.qml"));
3782 QObject *object = component.create();
3783 QVERIFY(object != 0);
3788 void tst_qdeclarativeecmascript::revisionErrors()
3791 QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevisionErrors.qml"));
3792 QString url = component.url().toString();
3794 QString warning1 = url + ":8: ReferenceError: Can't find variable: prop2";
3795 QString warning2 = url + ":11: ReferenceError: Can't find variable: prop2";
3796 QString warning3 = url + ":13: ReferenceError: Can't find variable: method2";
3798 QTest::ignoreMessage(QtWarningMsg, warning1.toLatin1().constData());
3799 QTest::ignoreMessage(QtWarningMsg, warning2.toLatin1().constData());
3800 QTest::ignoreMessage(QtWarningMsg, warning3.toLatin1().constData());
3801 MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create());
3802 QVERIFY(object != 0);
3806 QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevisionErrors2.qml"));
3807 QString url = component.url().toString();
3809 // MyRevisionedSubclass 1.0 uses MyRevisionedClass revision 0
3810 // method2, prop2 from MyRevisionedClass not available
3811 // method4, prop4 from MyRevisionedSubclass not available
3812 QString warning1 = url + ":8: ReferenceError: Can't find variable: prop2";
3813 QString warning2 = url + ":14: ReferenceError: Can't find variable: prop2";
3814 QString warning3 = url + ":10: ReferenceError: Can't find variable: prop4";
3815 QString warning4 = url + ":16: ReferenceError: Can't find variable: prop4";
3816 QString warning5 = url + ":20: ReferenceError: Can't find variable: method2";
3818 QTest::ignoreMessage(QtWarningMsg, warning1.toLatin1().constData());
3819 QTest::ignoreMessage(QtWarningMsg, warning2.toLatin1().constData());
3820 QTest::ignoreMessage(QtWarningMsg, warning3.toLatin1().constData());
3821 QTest::ignoreMessage(QtWarningMsg, warning4.toLatin1().constData());
3822 QTest::ignoreMessage(QtWarningMsg, warning5.toLatin1().constData());
3823 MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create());
3824 QVERIFY(object != 0);
3828 QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevisionErrors3.qml"));
3829 QString url = component.url().toString();
3831 // MyRevisionedSubclass 1.1 uses MyRevisionedClass revision 1
3832 // All properties/methods available, except MyRevisionedBaseClassUnregistered rev 1
3833 QString warning1 = url + ":30: ReferenceError: Can't find variable: methodD";
3834 QString warning2 = url + ":10: ReferenceError: Can't find variable: propD";
3835 QString warning3 = url + ":20: ReferenceError: Can't find variable: propD";
3836 QTest::ignoreMessage(QtWarningMsg, warning1.toLatin1().constData());
3837 QTest::ignoreMessage(QtWarningMsg, warning2.toLatin1().constData());
3838 QTest::ignoreMessage(QtWarningMsg, warning3.toLatin1().constData());
3839 MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create());
3840 QVERIFY(object != 0);
3845 void tst_qdeclarativeecmascript::revision()
3848 QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevision.qml"));
3849 QString url = component.url().toString();
3851 MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create());
3852 QVERIFY(object != 0);
3856 QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevision2.qml"));
3857 QString url = component.url().toString();
3859 MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create());
3860 QVERIFY(object != 0);
3864 QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevision3.qml"));
3865 QString url = component.url().toString();
3867 MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create());
3868 QVERIFY(object != 0);
3871 // Test that non-root classes can resolve revisioned methods
3873 QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevision4.qml"));
3875 QObject *object = component.create();
3876 QVERIFY(object != 0);
3877 QCOMPARE(object->property("test").toReal(), 11.);
3882 void tst_qdeclarativeecmascript::realToInt()
3884 QDeclarativeComponent component(&engine, TEST_FILE("realToInt.qml"));
3885 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
3886 QVERIFY(object != 0);
3888 QMetaObject::invokeMethod(object, "test1");
3889 QCOMPARE(object->value(), int(4));
3890 QMetaObject::invokeMethod(object, "test2");
3891 QCOMPARE(object->value(), int(8));
3893 void tst_qdeclarativeecmascript::dynamicString()
3895 QDeclarativeComponent component(&engine, TEST_FILE("dynamicString.qml"));
3896 QObject *object = component.create();
3897 QVERIFY(object != 0);
3898 QCOMPARE(object->property("stringProperty").toString(),
3899 QString::fromLatin1("string:Hello World false:0 true:1 uint32:100 int32:-100 double:3.14159 date:2011-02-11 05::30:50!"));
3902 QTEST_MAIN(tst_qdeclarativeecmascript)
3904 #include "tst_qdeclarativeecmascript.moc"