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();
191 void signalHandlers();
193 void callQtInvokables();
194 void invokableObjectArg();
195 void invokableObjectRet();
197 void revisionErrors();
201 QDeclarativeEngine engine;
204 void tst_qdeclarativeecmascript::initTestCase() { registerTypes(); }
206 void tst_qdeclarativeecmascript::assignBasicTypes()
209 QDeclarativeComponent component(&engine, TEST_FILE("assignBasicTypes.qml"));
210 MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
211 QVERIFY(object != 0);
212 QCOMPARE(object->flagProperty(), MyTypeObject::FlagVal1 | MyTypeObject::FlagVal3);
213 QCOMPARE(object->enumProperty(), MyTypeObject::EnumVal2);
214 QCOMPARE(object->stringProperty(), QString("Hello World!"));
215 QCOMPARE(object->uintProperty(), uint(10));
216 QCOMPARE(object->intProperty(), -19);
217 QCOMPARE((float)object->realProperty(), float(23.2));
218 QCOMPARE((float)object->doubleProperty(), float(-19.75));
219 QCOMPARE((float)object->floatProperty(), float(8.5));
220 QCOMPARE(object->colorProperty(), QColor("red"));
221 QCOMPARE(object->dateProperty(), QDate(1982, 11, 25));
222 QCOMPARE(object->timeProperty(), QTime(11, 11, 32));
223 QCOMPARE(object->dateTimeProperty(), QDateTime(QDate(2009, 5, 12), QTime(13, 22, 1)));
224 QCOMPARE(object->pointProperty(), QPoint(99,13));
225 QCOMPARE(object->pointFProperty(), QPointF(-10.1, 12.3));
226 QCOMPARE(object->sizeProperty(), QSize(99, 13));
227 QCOMPARE(object->sizeFProperty(), QSizeF(0.1, 0.2));
228 QCOMPARE(object->rectProperty(), QRect(9, 7, 100, 200));
229 QCOMPARE(object->rectFProperty(), QRectF(1000.1, -10.9, 400, 90.99));
230 QCOMPARE(object->boolProperty(), true);
231 QCOMPARE(object->variantProperty(), QVariant("Hello World!"));
232 QCOMPARE(object->vectorProperty(), QVector3D(10, 1, 2.2));
233 QCOMPARE(object->urlProperty(), component.url().resolved(QUrl("main.qml")));
237 QDeclarativeComponent component(&engine, TEST_FILE("assignBasicTypes.2.qml"));
238 MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
239 QVERIFY(object != 0);
240 QCOMPARE(object->flagProperty(), MyTypeObject::FlagVal1 | MyTypeObject::FlagVal3);
241 QCOMPARE(object->enumProperty(), MyTypeObject::EnumVal2);
242 QCOMPARE(object->stringProperty(), QString("Hello World!"));
243 QCOMPARE(object->uintProperty(), uint(10));
244 QCOMPARE(object->intProperty(), -19);
245 QCOMPARE((float)object->realProperty(), float(23.2));
246 QCOMPARE((float)object->doubleProperty(), float(-19.75));
247 QCOMPARE((float)object->floatProperty(), float(8.5));
248 QCOMPARE(object->colorProperty(), QColor("red"));
249 QCOMPARE(object->dateProperty(), QDate(1982, 11, 25));
250 QCOMPARE(object->timeProperty(), QTime(11, 11, 32));
251 QCOMPARE(object->dateTimeProperty(), QDateTime(QDate(2009, 5, 12), QTime(13, 22, 1)));
252 QCOMPARE(object->pointProperty(), QPoint(99,13));
253 QCOMPARE(object->pointFProperty(), QPointF(-10.1, 12.3));
254 QCOMPARE(object->sizeProperty(), QSize(99, 13));
255 QCOMPARE(object->sizeFProperty(), QSizeF(0.1, 0.2));
256 QCOMPARE(object->rectProperty(), QRect(9, 7, 100, 200));
257 QCOMPARE(object->rectFProperty(), QRectF(1000.1, -10.9, 400, 90.99));
258 QCOMPARE(object->boolProperty(), true);
259 QCOMPARE(object->variantProperty(), QVariant("Hello World!"));
260 QCOMPARE(object->vectorProperty(), QVector3D(10, 1, 2.2));
261 QCOMPARE(object->urlProperty(), component.url().resolved(QUrl("main.qml")));
266 void tst_qdeclarativeecmascript::idShortcutInvalidates()
269 QDeclarativeComponent component(&engine, TEST_FILE("idShortcutInvalidates.qml"));
270 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
271 QVERIFY(object != 0);
272 QVERIFY(object->objectProperty() != 0);
273 delete object->objectProperty();
274 QVERIFY(object->objectProperty() == 0);
279 QDeclarativeComponent component(&engine, TEST_FILE("idShortcutInvalidates.1.qml"));
280 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
281 QVERIFY(object != 0);
282 QVERIFY(object->objectProperty() != 0);
283 delete object->objectProperty();
284 QVERIFY(object->objectProperty() == 0);
289 void tst_qdeclarativeecmascript::boolPropertiesEvaluateAsBool()
292 QDeclarativeComponent component(&engine, TEST_FILE("boolPropertiesEvaluateAsBool.1.qml"));
293 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
294 QVERIFY(object != 0);
295 QCOMPARE(object->stringProperty(), QLatin1String("pass"));
299 QDeclarativeComponent component(&engine, TEST_FILE("boolPropertiesEvaluateAsBool.2.qml"));
300 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
301 QVERIFY(object != 0);
302 QCOMPARE(object->stringProperty(), QLatin1String("pass"));
307 void tst_qdeclarativeecmascript::signalAssignment()
310 QDeclarativeComponent component(&engine, TEST_FILE("signalAssignment.1.qml"));
311 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
312 QVERIFY(object != 0);
313 QCOMPARE(object->string(), QString());
314 emit object->basicSignal();
315 QCOMPARE(object->string(), QString("pass"));
320 QDeclarativeComponent component(&engine, TEST_FILE("signalAssignment.2.qml"));
321 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
322 QVERIFY(object != 0);
323 QCOMPARE(object->string(), QString());
324 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
325 QCOMPARE(object->string(), QString("pass 19 Hello world! 10.25 3 2"));
330 void tst_qdeclarativeecmascript::methods()
333 QDeclarativeComponent component(&engine, TEST_FILE("methods.1.qml"));
334 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
335 QVERIFY(object != 0);
336 QCOMPARE(object->methodCalled(), false);
337 QCOMPARE(object->methodIntCalled(), false);
338 emit object->basicSignal();
339 QCOMPARE(object->methodCalled(), true);
340 QCOMPARE(object->methodIntCalled(), false);
345 QDeclarativeComponent component(&engine, TEST_FILE("methods.2.qml"));
346 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
347 QVERIFY(object != 0);
348 QCOMPARE(object->methodCalled(), false);
349 QCOMPARE(object->methodIntCalled(), false);
350 emit object->basicSignal();
351 QCOMPARE(object->methodCalled(), false);
352 QCOMPARE(object->methodIntCalled(), true);
357 QDeclarativeComponent component(&engine, TEST_FILE("methods.3.qml"));
358 QObject *object = component.create();
359 QVERIFY(object != 0);
360 QCOMPARE(object->property("test").toInt(), 19);
365 QDeclarativeComponent component(&engine, TEST_FILE("methods.4.qml"));
366 QObject *object = component.create();
367 QVERIFY(object != 0);
368 QCOMPARE(object->property("test").toInt(), 19);
369 QCOMPARE(object->property("test2").toInt(), 17);
370 QCOMPARE(object->property("test3").toInt(), 16);
375 QDeclarativeComponent component(&engine, TEST_FILE("methods.5.qml"));
376 QObject *object = component.create();
377 QVERIFY(object != 0);
378 QCOMPARE(object->property("test").toInt(), 9);
383 void tst_qdeclarativeecmascript::bindingLoop()
385 QDeclarativeComponent component(&engine, TEST_FILE("bindingLoop.qml"));
386 QString warning = component.url().toString() + ":9:9: QML MyQmlObject: Binding loop detected for property \"stringProperty\"";
387 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
388 QObject *object = component.create();
389 QVERIFY(object != 0);
393 void tst_qdeclarativeecmascript::basicExpressions_data()
395 QTest::addColumn<QString>("expression");
396 QTest::addColumn<QVariant>("result");
397 QTest::addColumn<bool>("nest");
399 QTest::newRow("Syntax error (self test)") << "{console.log({'a':1'}.a)}" << QVariant() << false;
400 QTest::newRow("Context property") << "a" << QVariant(1944) << false;
401 QTest::newRow("Context property") << "a" << QVariant(1944) << true;
402 QTest::newRow("Context property expression") << "a * 2" << QVariant(3888) << false;
403 QTest::newRow("Context property expression") << "a * 2" << QVariant(3888) << true;
404 QTest::newRow("Overridden context property") << "b" << QVariant("Milk") << false;
405 QTest::newRow("Overridden context property") << "b" << QVariant("Cow") << true;
406 QTest::newRow("Object property") << "object.stringProperty" << QVariant("Object1") << false;
407 QTest::newRow("Object property") << "object.stringProperty" << QVariant("Object1") << true;
408 QTest::newRow("Overridden object property") << "objectOverride.stringProperty" << QVariant("Object2") << false;
409 QTest::newRow("Overridden object property") << "objectOverride.stringProperty" << QVariant("Object3") << true;
410 QTest::newRow("Default object property") << "horseLegs" << QVariant(4) << false;
411 QTest::newRow("Default object property") << "antLegs" << QVariant(6) << false;
412 QTest::newRow("Default object property") << "emuLegs" << QVariant(2) << false;
413 QTest::newRow("Nested default object property") << "horseLegs" << QVariant(4) << true;
414 QTest::newRow("Nested default object property") << "antLegs" << QVariant(7) << true;
415 QTest::newRow("Nested default object property") << "emuLegs" << QVariant(2) << true;
416 QTest::newRow("Nested default object property") << "humanLegs" << QVariant(2) << true;
417 QTest::newRow("Context property override default object property") << "millipedeLegs" << QVariant(100) << true;
420 void tst_qdeclarativeecmascript::basicExpressions()
422 QFETCH(QString, expression);
423 QFETCH(QVariant, result);
429 MyDefaultObject1 default1;
430 MyDefaultObject3 default3;
431 object1.setStringProperty("Object1");
432 object2.setStringProperty("Object2");
433 object3.setStringProperty("Object3");
435 QDeclarativeContext context(engine.rootContext());
436 QDeclarativeContext nestedContext(&context);
438 context.setContextObject(&default1);
439 context.setContextProperty("a", QVariant(1944));
440 context.setContextProperty("b", QVariant("Milk"));
441 context.setContextProperty("object", &object1);
442 context.setContextProperty("objectOverride", &object2);
443 nestedContext.setContextObject(&default3);
444 nestedContext.setContextProperty("b", QVariant("Cow"));
445 nestedContext.setContextProperty("objectOverride", &object3);
446 nestedContext.setContextProperty("millipedeLegs", QVariant(100));
448 MyExpression expr(nest?&nestedContext:&context, expression);
449 QCOMPARE(expr.evaluate(), result);
452 void tst_qdeclarativeecmascript::arrayExpressions()
458 QDeclarativeContext context(engine.rootContext());
459 context.setContextProperty("a", &obj1);
460 context.setContextProperty("b", &obj2);
461 context.setContextProperty("c", &obj3);
463 MyExpression expr(&context, "[a, b, c, 10]");
464 QVariant result = expr.evaluate();
465 QCOMPARE(result.userType(), qMetaTypeId<QList<QObject *> >());
466 QList<QObject *> list = qvariant_cast<QList<QObject *> >(result);
467 QCOMPARE(list.count(), 4);
468 QCOMPARE(list.at(0), &obj1);
469 QCOMPARE(list.at(1), &obj2);
470 QCOMPARE(list.at(2), &obj3);
471 QCOMPARE(list.at(3), (QObject *)0);
474 // Tests that modifying a context property will reevaluate expressions
475 void tst_qdeclarativeecmascript::contextPropertiesTriggerReeval()
477 QDeclarativeContext context(engine.rootContext());
480 MyQmlObject *object3 = new MyQmlObject;
482 object1.setStringProperty("Hello");
483 object2.setStringProperty("World");
485 context.setContextProperty("testProp", QVariant(1));
486 context.setContextProperty("testObj", &object1);
487 context.setContextProperty("testObj2", object3);
490 MyExpression expr(&context, "testProp + 1");
491 QCOMPARE(expr.changed, false);
492 QCOMPARE(expr.evaluate(), QVariant(2));
494 context.setContextProperty("testProp", QVariant(2));
495 QCOMPARE(expr.changed, true);
496 QCOMPARE(expr.evaluate(), QVariant(3));
500 MyExpression expr(&context, "testProp + testProp + testProp");
501 QCOMPARE(expr.changed, false);
502 QCOMPARE(expr.evaluate(), QVariant(6));
504 context.setContextProperty("testProp", QVariant(4));
505 QCOMPARE(expr.changed, true);
506 QCOMPARE(expr.evaluate(), QVariant(12));
510 MyExpression expr(&context, "testObj.stringProperty");
511 QCOMPARE(expr.changed, false);
512 QCOMPARE(expr.evaluate(), QVariant("Hello"));
514 context.setContextProperty("testObj", &object2);
515 QCOMPARE(expr.changed, true);
516 QCOMPARE(expr.evaluate(), QVariant("World"));
520 MyExpression expr(&context, "testObj.stringProperty /**/");
521 QCOMPARE(expr.changed, false);
522 QCOMPARE(expr.evaluate(), QVariant("World"));
524 context.setContextProperty("testObj", &object1);
525 QCOMPARE(expr.changed, true);
526 QCOMPARE(expr.evaluate(), QVariant("Hello"));
530 MyExpression expr(&context, "testObj2");
531 QCOMPARE(expr.changed, false);
532 QCOMPARE(expr.evaluate(), QVariant::fromValue((QObject *)object3));
538 void tst_qdeclarativeecmascript::objectPropertiesTriggerReeval()
540 QDeclarativeContext context(engine.rootContext());
544 context.setContextProperty("testObj", &object1);
546 object1.setStringProperty(QLatin1String("Hello"));
547 object2.setStringProperty(QLatin1String("Dog"));
548 object3.setStringProperty(QLatin1String("Cat"));
551 MyExpression expr(&context, "testObj.stringProperty");
552 QCOMPARE(expr.changed, false);
553 QCOMPARE(expr.evaluate(), QVariant("Hello"));
555 object1.setStringProperty(QLatin1String("World"));
556 QCOMPARE(expr.changed, true);
557 QCOMPARE(expr.evaluate(), QVariant("World"));
561 MyExpression expr(&context, "testObj.objectProperty.stringProperty");
562 QCOMPARE(expr.changed, false);
563 QCOMPARE(expr.evaluate(), QVariant());
565 object1.setObjectProperty(&object2);
566 QCOMPARE(expr.changed, true);
567 expr.changed = false;
568 QCOMPARE(expr.evaluate(), QVariant("Dog"));
570 object1.setObjectProperty(&object3);
571 QCOMPARE(expr.changed, true);
572 expr.changed = false;
573 QCOMPARE(expr.evaluate(), QVariant("Cat"));
575 object1.setObjectProperty(0);
576 QCOMPARE(expr.changed, true);
577 expr.changed = false;
578 QCOMPARE(expr.evaluate(), QVariant());
580 object1.setObjectProperty(&object3);
581 QCOMPARE(expr.changed, true);
582 expr.changed = false;
583 QCOMPARE(expr.evaluate(), QVariant("Cat"));
585 object3.setStringProperty("Donkey");
586 QCOMPARE(expr.changed, true);
587 expr.changed = false;
588 QCOMPARE(expr.evaluate(), QVariant("Donkey"));
592 void tst_qdeclarativeecmascript::deferredProperties()
594 QDeclarativeComponent component(&engine, TEST_FILE("deferredProperties.qml"));
595 MyDeferredObject *object =
596 qobject_cast<MyDeferredObject *>(component.create());
597 QVERIFY(object != 0);
598 QCOMPARE(object->value(), 0);
599 QVERIFY(object->objectProperty() == 0);
600 QVERIFY(object->objectProperty2() != 0);
601 qmlExecuteDeferred(object);
602 QCOMPARE(object->value(), 10);
603 QVERIFY(object->objectProperty() != 0);
604 MyQmlObject *qmlObject =
605 qobject_cast<MyQmlObject *>(object->objectProperty());
606 QVERIFY(qmlObject != 0);
607 QCOMPARE(qmlObject->value(), 10);
608 object->setValue(19);
609 QCOMPARE(qmlObject->value(), 19);
614 // Check errors on deferred properties are correctly emitted
615 void tst_qdeclarativeecmascript::deferredPropertiesErrors()
617 QDeclarativeComponent component(&engine, TEST_FILE("deferredPropertiesErrors.qml"));
618 MyDeferredObject *object =
619 qobject_cast<MyDeferredObject *>(component.create());
620 QVERIFY(object != 0);
621 QCOMPARE(object->value(), 0);
622 QVERIFY(object->objectProperty() == 0);
623 QVERIFY(object->objectProperty2() == 0);
625 QString warning = component.url().toString() + ":6: Unable to assign [undefined] to QObject* objectProperty";
626 QTest::ignoreMessage(QtWarningMsg, qPrintable(warning));
628 qmlExecuteDeferred(object);
633 void tst_qdeclarativeecmascript::extensionObjects()
635 QDeclarativeComponent component(&engine, TEST_FILE("extensionObjects.qml"));
636 MyExtendedObject *object =
637 qobject_cast<MyExtendedObject *>(component.create());
638 QVERIFY(object != 0);
639 QCOMPARE(object->baseProperty(), 13);
640 QCOMPARE(object->coreProperty(), 9);
641 object->setProperty("extendedProperty", QVariant(11));
642 object->setProperty("baseExtendedProperty", QVariant(92));
643 QCOMPARE(object->coreProperty(), 11);
644 QCOMPARE(object->baseProperty(), 92);
646 MyExtendedObject *nested = qobject_cast<MyExtendedObject*>(qvariant_cast<QObject *>(object->property("nested")));
648 QCOMPARE(nested->baseProperty(), 13);
649 QCOMPARE(nested->coreProperty(), 9);
650 nested->setProperty("extendedProperty", QVariant(11));
651 nested->setProperty("baseExtendedProperty", QVariant(92));
652 QCOMPARE(nested->coreProperty(), 11);
653 QCOMPARE(nested->baseProperty(), 92);
658 void tst_qdeclarativeecmascript::overrideExtensionProperties()
660 QDeclarativeComponent component(&engine, TEST_FILE("extensionObjectsPropertyOverride.qml"));
661 OverrideDefaultPropertyObject *object =
662 qobject_cast<OverrideDefaultPropertyObject *>(component.create());
663 QVERIFY(object != 0);
664 QVERIFY(object->secondProperty() != 0);
665 QVERIFY(object->firstProperty() == 0);
670 void tst_qdeclarativeecmascript::attachedProperties()
673 QDeclarativeComponent component(&engine, TEST_FILE("attachedProperty.qml"));
674 QObject *object = component.create();
675 QVERIFY(object != 0);
676 QCOMPARE(object->property("a").toInt(), 19);
677 QCOMPARE(object->property("b").toInt(), 19);
678 QCOMPARE(object->property("c").toInt(), 19);
679 QCOMPARE(object->property("d").toInt(), 19);
684 QDeclarativeComponent component(&engine, TEST_FILE("attachedProperty.2.qml"));
685 QObject *object = component.create();
686 QVERIFY(object != 0);
687 QCOMPARE(object->property("a").toInt(), 26);
688 QCOMPARE(object->property("b").toInt(), 26);
689 QCOMPARE(object->property("c").toInt(), 26);
690 QCOMPARE(object->property("d").toInt(), 26);
694 QDeclarativeComponent component(&engine, TEST_FILE("writeAttachedProperty.qml"));
695 QObject *object = component.create();
696 QVERIFY(object != 0);
698 QMetaObject::invokeMethod(object, "writeValue2");
700 MyQmlAttachedObject *attached =
701 qobject_cast<MyQmlAttachedObject *>(qmlAttachedPropertiesObject<MyQmlObject>(object));
702 QVERIFY(attached != 0);
704 QCOMPARE(attached->value2(), 9);
709 void tst_qdeclarativeecmascript::enums()
713 QDeclarativeComponent component(&engine, TEST_FILE("enums.1.qml"));
714 QObject *object = component.create();
715 QVERIFY(object != 0);
717 QCOMPARE(object->property("a").toInt(), 0);
718 QCOMPARE(object->property("b").toInt(), 1);
719 QCOMPARE(object->property("c").toInt(), 2);
720 QCOMPARE(object->property("d").toInt(), 3);
721 QCOMPARE(object->property("e").toInt(), 0);
722 QCOMPARE(object->property("f").toInt(), 1);
723 QCOMPARE(object->property("g").toInt(), 2);
724 QCOMPARE(object->property("h").toInt(), 3);
725 QCOMPARE(object->property("i").toInt(), 19);
726 QCOMPARE(object->property("j").toInt(), 19);
730 // Non-existent enums
732 QDeclarativeComponent component(&engine, TEST_FILE("enums.2.qml"));
734 QString warning1 = component.url().toString() + ":5: Unable to assign [undefined] to int a";
735 QString warning2 = component.url().toString() + ":6: Unable to assign [undefined] to int b";
736 QTest::ignoreMessage(QtWarningMsg, qPrintable(warning1));
737 QTest::ignoreMessage(QtWarningMsg, qPrintable(warning2));
739 QObject *object = component.create();
740 QVERIFY(object != 0);
741 QCOMPARE(object->property("a").toInt(), 0);
742 QCOMPARE(object->property("b").toInt(), 0);
748 void tst_qdeclarativeecmascript::valueTypeFunctions()
750 QDeclarativeComponent component(&engine, TEST_FILE("valueTypeFunctions.qml"));
751 MyTypeObject *obj = qobject_cast<MyTypeObject*>(component.create());
753 QCOMPARE(obj->rectProperty(), QRect(0,0,100,100));
754 QCOMPARE(obj->rectFProperty(), QRectF(0,0.5,100,99.5));
760 Tests that writing a constant to a property with a binding on it disables the
763 void tst_qdeclarativeecmascript::constantsOverrideBindings()
767 QDeclarativeComponent component(&engine, TEST_FILE("constantsOverrideBindings.1.qml"));
768 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
769 QVERIFY(object != 0);
771 QCOMPARE(object->property("c2").toInt(), 0);
772 object->setProperty("c1", QVariant(9));
773 QCOMPARE(object->property("c2").toInt(), 9);
775 emit object->basicSignal();
777 QCOMPARE(object->property("c2").toInt(), 13);
778 object->setProperty("c1", QVariant(8));
779 QCOMPARE(object->property("c2").toInt(), 13);
784 // During construction
786 QDeclarativeComponent component(&engine, TEST_FILE("constantsOverrideBindings.2.qml"));
787 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
788 QVERIFY(object != 0);
790 QCOMPARE(object->property("c1").toInt(), 0);
791 QCOMPARE(object->property("c2").toInt(), 10);
792 object->setProperty("c1", QVariant(9));
793 QCOMPARE(object->property("c1").toInt(), 9);
794 QCOMPARE(object->property("c2").toInt(), 10);
802 QDeclarativeComponent component(&engine, TEST_FILE("constantsOverrideBindings.3.qml"));
803 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
804 QVERIFY(object != 0);
806 QCOMPARE(object->property("c2").toInt(), 0);
807 object->setProperty("c1", QVariant(9));
808 QCOMPARE(object->property("c2").toInt(), 9);
810 object->setProperty("c2", QVariant(13));
811 QCOMPARE(object->property("c2").toInt(), 13);
812 object->setProperty("c1", QVariant(7));
813 QCOMPARE(object->property("c1").toInt(), 7);
814 QCOMPARE(object->property("c2").toInt(), 13);
822 QDeclarativeComponent component(&engine, TEST_FILE("constantsOverrideBindings.4.qml"));
823 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
824 QVERIFY(object != 0);
826 QCOMPARE(object->property("c1").toInt(), 0);
827 QCOMPARE(object->property("c3").toInt(), 10);
828 object->setProperty("c1", QVariant(9));
829 QCOMPARE(object->property("c1").toInt(), 9);
830 QCOMPARE(object->property("c3").toInt(), 10);
837 Tests that assigning a binding to a property that already has a binding causes
838 the original binding to be disabled.
840 void tst_qdeclarativeecmascript::outerBindingOverridesInnerBinding()
842 QDeclarativeComponent component(&engine,
843 TEST_FILE("outerBindingOverridesInnerBinding.qml"));
844 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
845 QVERIFY(object != 0);
847 QCOMPARE(object->property("c1").toInt(), 0);
848 QCOMPARE(object->property("c2").toInt(), 0);
849 QCOMPARE(object->property("c3").toInt(), 0);
851 object->setProperty("c1", QVariant(9));
852 QCOMPARE(object->property("c1").toInt(), 9);
853 QCOMPARE(object->property("c2").toInt(), 0);
854 QCOMPARE(object->property("c3").toInt(), 0);
856 object->setProperty("c3", QVariant(8));
857 QCOMPARE(object->property("c1").toInt(), 9);
858 QCOMPARE(object->property("c2").toInt(), 8);
859 QCOMPARE(object->property("c3").toInt(), 8);
865 Access a non-existent attached object.
867 Tests for a regression where this used to crash.
869 void tst_qdeclarativeecmascript::nonExistentAttachedObject()
871 QDeclarativeComponent component(&engine, TEST_FILE("nonExistentAttachedObject.qml"));
873 QString warning = component.url().toString() + ":4: Unable to assign [undefined] to QString stringProperty";
874 QTest::ignoreMessage(QtWarningMsg, qPrintable(warning));
876 QObject *object = component.create();
877 QVERIFY(object != 0);
882 void tst_qdeclarativeecmascript::scope()
885 QDeclarativeComponent component(&engine, TEST_FILE("scope.qml"));
886 QObject *object = component.create();
887 QVERIFY(object != 0);
889 QCOMPARE(object->property("test1").toInt(), 1);
890 QCOMPARE(object->property("test2").toInt(), 2);
891 QCOMPARE(object->property("test3").toString(), QString("1Test"));
892 QCOMPARE(object->property("test4").toString(), QString("2Test"));
893 QCOMPARE(object->property("test5").toInt(), 1);
894 QCOMPARE(object->property("test6").toInt(), 1);
895 QCOMPARE(object->property("test7").toInt(), 2);
896 QCOMPARE(object->property("test8").toInt(), 2);
897 QCOMPARE(object->property("test9").toInt(), 1);
898 QCOMPARE(object->property("test10").toInt(), 3);
904 QDeclarativeComponent component(&engine, TEST_FILE("scope.2.qml"));
905 QObject *object = component.create();
906 QVERIFY(object != 0);
908 QCOMPARE(object->property("test1").toInt(), 19);
909 QCOMPARE(object->property("test2").toInt(), 19);
910 QCOMPARE(object->property("test3").toInt(), 14);
911 QCOMPARE(object->property("test4").toInt(), 14);
912 QCOMPARE(object->property("test5").toInt(), 24);
913 QCOMPARE(object->property("test6").toInt(), 24);
919 QDeclarativeComponent component(&engine, TEST_FILE("scope.3.qml"));
920 QObject *object = component.create();
921 QVERIFY(object != 0);
923 QCOMPARE(object->property("test1").toBool(), true);
924 QCOMPARE(object->property("test2").toBool(), true);
925 QCOMPARE(object->property("test3").toBool(), true);
930 // Signal argument scope
932 QDeclarativeComponent component(&engine, TEST_FILE("scope.4.qml"));
933 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
934 QVERIFY(object != 0);
936 QCOMPARE(object->property("test").toInt(), 0);
937 QCOMPARE(object->property("test2").toString(), QString());
939 emit object->argumentSignal(13, "Argument Scope", 9, MyQmlObject::EnumValue4, Qt::RightButton);
941 QCOMPARE(object->property("test").toInt(), 13);
942 QCOMPARE(object->property("test2").toString(), QString("Argument Scope"));
948 QDeclarativeComponent component(&engine, TEST_FILE("scope.5.qml"));
949 QObject *object = component.create();
950 QVERIFY(object != 0);
952 QCOMPARE(object->property("test1").toBool(), true);
953 QCOMPARE(object->property("test2").toBool(), true);
959 QDeclarativeComponent component(&engine, TEST_FILE("scope.6.qml"));
960 QObject *object = component.create();
961 QVERIFY(object != 0);
963 QCOMPARE(object->property("test").toBool(), true);
969 // In 4.7, non-library javascript files that had no imports shared the imports of their
971 void tst_qdeclarativeecmascript::importScope()
973 QDeclarativeComponent component(&engine, TEST_FILE("importScope.qml"));
974 QObject *o = component.create();
977 QCOMPARE(o->property("test").toInt(), 240);
983 Tests that "any" type passes through a synthesized signal parameter. This
984 is essentially a test of QDeclarativeMetaType::copy()
986 void tst_qdeclarativeecmascript::signalParameterTypes()
988 QDeclarativeComponent component(&engine, TEST_FILE("signalParameterTypes.qml"));
989 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
990 QVERIFY(object != 0);
992 emit object->basicSignal();
994 QCOMPARE(object->property("intProperty").toInt(), 10);
995 QCOMPARE(object->property("realProperty").toReal(), 19.2);
996 QVERIFY(object->property("colorProperty").value<QColor>() == QColor(255, 255, 0, 255));
997 QVERIFY(object->property("variantProperty") == QVariant::fromValue(QColor(255, 0, 255, 255)));
998 QVERIFY(object->property("enumProperty") == MyQmlObject::EnumValue3);
999 QVERIFY(object->property("qtEnumProperty") == Qt::LeftButton);
1005 Test that two JS objects for the same QObject compare as equal.
1007 void tst_qdeclarativeecmascript::objectsCompareAsEqual()
1009 QDeclarativeComponent component(&engine, TEST_FILE("objectsCompareAsEqual.qml"));
1010 QObject *object = component.create();
1011 QVERIFY(object != 0);
1013 QCOMPARE(object->property("test1").toBool(), true);
1014 QCOMPARE(object->property("test2").toBool(), true);
1015 QCOMPARE(object->property("test3").toBool(), true);
1016 QCOMPARE(object->property("test4").toBool(), true);
1017 QCOMPARE(object->property("test5").toBool(), true);
1023 Confirm bindings and alias properties can coexist.
1025 Tests for a regression where the binding would not reevaluate.
1027 void tst_qdeclarativeecmascript::aliasPropertyAndBinding()
1029 QDeclarativeComponent component(&engine, TEST_FILE("aliasPropertyAndBinding.qml"));
1030 QObject *object = component.create();
1031 QVERIFY(object != 0);
1033 QCOMPARE(object->property("c2").toInt(), 3);
1034 QCOMPARE(object->property("c3").toInt(), 3);
1036 object->setProperty("c2", QVariant(19));
1038 QCOMPARE(object->property("c2").toInt(), 19);
1039 QCOMPARE(object->property("c3").toInt(), 19);
1045 Ensure that we can write undefined value to an alias property,
1046 and that the aliased property is reset correctly if possible.
1048 void tst_qdeclarativeecmascript::aliasPropertyReset()
1050 QObject *object = 0;
1052 // test that a manual write (of undefined) to a resettable aliased property succeeds
1053 QDeclarativeComponent c1(&engine, TEST_FILE("aliasreset/aliasPropertyReset.1.qml"));
1054 object = c1.create();
1055 QVERIFY(object != 0);
1056 QVERIFY(object->property("sourceComponentAlias").value<QDeclarativeComponent*>() != 0);
1057 QCOMPARE(object->property("aliasIsUndefined"), QVariant(false));
1058 QMetaObject::invokeMethod(object, "resetAliased");
1059 QVERIFY(object->property("sourceComponentAlias").value<QDeclarativeComponent*>() == 0);
1060 QCOMPARE(object->property("aliasIsUndefined"), QVariant(true));
1063 // test that a manual write (of undefined) to a resettable alias property succeeds
1064 QDeclarativeComponent c2(&engine, TEST_FILE("aliasreset/aliasPropertyReset.2.qml"));
1065 object = c2.create();
1066 QVERIFY(object != 0);
1067 QVERIFY(object->property("sourceComponentAlias").value<QDeclarativeComponent*>() != 0);
1068 QCOMPARE(object->property("loaderSourceComponentIsUndefined"), QVariant(false));
1069 QMetaObject::invokeMethod(object, "resetAlias");
1070 QVERIFY(object->property("sourceComponentAlias").value<QDeclarativeComponent*>() == 0);
1071 QCOMPARE(object->property("loaderSourceComponentIsUndefined"), QVariant(true));
1074 // test that an alias to a bound property works correctly
1075 QDeclarativeComponent c3(&engine, TEST_FILE("aliasreset/aliasPropertyReset.3.qml"));
1076 object = c3.create();
1077 QVERIFY(object != 0);
1078 QVERIFY(object->property("sourceComponentAlias").value<QDeclarativeComponent*>() != 0);
1079 QCOMPARE(object->property("loaderOneSourceComponentIsUndefined"), QVariant(false));
1080 QCOMPARE(object->property("loaderTwoSourceComponentIsUndefined"), QVariant(false));
1081 QMetaObject::invokeMethod(object, "resetAlias");
1082 QVERIFY(object->property("sourceComponentAlias").value<QDeclarativeComponent*>() == 0);
1083 QCOMPARE(object->property("loaderOneSourceComponentIsUndefined"), QVariant(true));
1084 QCOMPARE(object->property("loaderTwoSourceComponentIsUndefined"), QVariant(false));
1087 // test that a manual write (of undefined) to a resettable alias property
1088 // whose aliased property's object has been deleted, does not crash.
1089 QDeclarativeComponent c4(&engine, TEST_FILE("aliasreset/aliasPropertyReset.4.qml"));
1090 object = c4.create();
1091 QVERIFY(object != 0);
1092 QVERIFY(object->property("sourceComponentAlias").value<QDeclarativeComponent*>() != 0);
1093 QObject *loader = object->findChild<QObject*>("loader");
1094 QVERIFY(loader != 0);
1096 QVERIFY(object->property("sourceComponentAlias").value<QDeclarativeComponent*>() == 0); // deletion should have caused value unset.
1097 QMetaObject::invokeMethod(object, "resetAlias"); // shouldn't crash.
1098 QVERIFY(object->property("sourceComponentAlias").value<QDeclarativeComponent*>() == 0);
1099 QMetaObject::invokeMethod(object, "setAlias"); // shouldn't crash, and shouldn't change value (since it's no longer referencing anything).
1100 QVERIFY(object->property("sourceComponentAlias").value<QDeclarativeComponent*>() == 0);
1103 // test that binding an alias property to an undefined value works correctly
1104 QDeclarativeComponent c5(&engine, TEST_FILE("aliasreset/aliasPropertyReset.5.qml"));
1105 object = c5.create();
1106 QVERIFY(object != 0);
1107 QVERIFY(object->property("sourceComponentAlias").value<QDeclarativeComponent*>() == 0); // bound to undefined value.
1110 // test that a manual write (of undefined) to a non-resettable property fails properly
1111 QUrl url = TEST_FILE("aliasreset/aliasPropertyReset.error.1.qml");
1112 QString warning1 = url.toString() + QLatin1String(":15: Error: Cannot assign [undefined] to int");
1113 QDeclarativeComponent e1(&engine, url);
1114 object = e1.create();
1115 QVERIFY(object != 0);
1116 QCOMPARE(object->property("intAlias").value<int>(), 12);
1117 QCOMPARE(object->property("aliasedIntIsUndefined"), QVariant(false));
1118 QTest::ignoreMessage(QtWarningMsg, warning1.toLatin1().constData());
1119 QMetaObject::invokeMethod(object, "resetAlias");
1120 QCOMPARE(object->property("intAlias").value<int>(), 12);
1121 QCOMPARE(object->property("aliasedIntIsUndefined"), QVariant(false));
1125 void tst_qdeclarativeecmascript::dynamicCreation_data()
1127 QTest::addColumn<QString>("method");
1128 QTest::addColumn<QString>("createdName");
1130 QTest::newRow("One") << "createOne" << "objectOne";
1131 QTest::newRow("Two") << "createTwo" << "objectTwo";
1132 QTest::newRow("Three") << "createThree" << "objectThree";
1136 Test using createQmlObject to dynamically generate an item
1137 Also using createComponent is tested.
1139 void tst_qdeclarativeecmascript::dynamicCreation()
1141 QFETCH(QString, method);
1142 QFETCH(QString, createdName);
1144 QDeclarativeComponent component(&engine, TEST_FILE("dynamicCreation.qml"));
1145 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1146 QVERIFY(object != 0);
1148 QMetaObject::invokeMethod(object, method.toUtf8());
1149 QObject *created = object->objectProperty();
1151 QCOMPARE(created->objectName(), createdName);
1157 Tests the destroy function
1159 void tst_qdeclarativeecmascript::dynamicDestruction()
1162 QDeclarativeComponent component(&engine, TEST_FILE("dynamicDeletion.qml"));
1163 QDeclarativeGuard<MyQmlObject> object = qobject_cast<MyQmlObject*>(component.create());
1164 QVERIFY(object != 0);
1165 QDeclarativeGuard<QObject> createdQmlObject = 0;
1167 QMetaObject::invokeMethod(object, "create");
1168 createdQmlObject = object->objectProperty();
1169 QVERIFY(createdQmlObject);
1170 QCOMPARE(createdQmlObject->objectName(), QString("emptyObject"));
1172 QMetaObject::invokeMethod(object, "killOther");
1173 QVERIFY(createdQmlObject);
1174 QCoreApplication::instance()->processEvents(QEventLoop::DeferredDeletion);
1175 QVERIFY(createdQmlObject);
1176 for (int ii = 0; createdQmlObject && ii < 50; ++ii) { // After 5 seconds we should give up
1177 if (createdQmlObject) {
1179 QCoreApplication::instance()->processEvents(QEventLoop::DeferredDeletion);
1182 QVERIFY(!createdQmlObject);
1184 QDeclarativeEngine::setObjectOwnership(object, QDeclarativeEngine::JavaScriptOwnership);
1185 QMetaObject::invokeMethod(object, "killMe");
1188 QCoreApplication::instance()->processEvents(QEventLoop::DeferredDeletion);
1193 QDeclarativeComponent component(&engine, TEST_FILE("dynamicDeletion.2.qml"));
1194 QObject *o = component.create();
1197 QVERIFY(qvariant_cast<QObject*>(o->property("objectProperty")) == 0);
1199 QMetaObject::invokeMethod(o, "create");
1201 QVERIFY(qvariant_cast<QObject*>(o->property("objectProperty")) != 0);
1203 QMetaObject::invokeMethod(o, "destroy");
1205 QCoreApplication::instance()->processEvents(QEventLoop::DeferredDeletion);
1207 QVERIFY(qvariant_cast<QObject*>(o->property("objectProperty")) == 0);
1214 tests that id.toString() works
1216 void tst_qdeclarativeecmascript::objectToString()
1218 QDeclarativeComponent component(&engine, TEST_FILE("declarativeToString.qml"));
1219 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1220 QVERIFY(object != 0);
1221 QMetaObject::invokeMethod(object, "testToString");
1222 QVERIFY(object->stringProperty().startsWith("MyQmlObject_QML_"));
1223 QVERIFY(object->stringProperty().endsWith(", \"objName\")"));
1229 tests that id.hasOwnProperty() works
1231 void tst_qdeclarativeecmascript::objectHasOwnProperty()
1233 QUrl url = TEST_FILE("declarativeHasOwnProperty.qml");
1234 QString warning1 = url.toString() + ":59: TypeError: Cannot call method 'hasOwnProperty' of undefined";
1235 QString warning2 = url.toString() + ":64: TypeError: Cannot call method 'hasOwnProperty' of undefined";
1236 QString warning3 = url.toString() + ":69: TypeError: Cannot call method 'hasOwnProperty' of undefined";
1238 QDeclarativeComponent component(&engine, url);
1239 QObject *object = component.create();
1240 QVERIFY(object != 0);
1242 // test QObjects in QML
1243 QMetaObject::invokeMethod(object, "testHasOwnPropertySuccess");
1244 QVERIFY(object->property("result").value<bool>() == true);
1245 QMetaObject::invokeMethod(object, "testHasOwnPropertyFailure");
1246 QVERIFY(object->property("result").value<bool>() == false);
1248 // now test other types in QML
1249 QObject *child = object->findChild<QObject*>("typeObj");
1250 QVERIFY(child != 0);
1251 QMetaObject::invokeMethod(child, "testHasOwnPropertySuccess");
1252 QCOMPARE(child->property("valueTypeHasOwnProperty").toBool(), true);
1253 QCOMPARE(child->property("valueTypeHasOwnProperty2").toBool(), true);
1254 QCOMPARE(child->property("variantTypeHasOwnProperty").toBool(), true);
1255 QCOMPARE(child->property("stringTypeHasOwnProperty").toBool(), true);
1256 QCOMPARE(child->property("listTypeHasOwnProperty").toBool(), true);
1257 QCOMPARE(child->property("emptyListTypeHasOwnProperty").toBool(), true);
1258 QCOMPARE(child->property("enumTypeHasOwnProperty").toBool(), true);
1259 QCOMPARE(child->property("typenameHasOwnProperty").toBool(), true);
1260 QCOMPARE(child->property("typenameHasOwnProperty2").toBool(), true);
1261 QCOMPARE(child->property("moduleApiTypeHasOwnProperty").toBool(), true);
1262 QCOMPARE(child->property("moduleApiPropertyTypeHasOwnProperty").toBool(), true);
1264 QTest::ignoreMessage(QtWarningMsg, warning1.toLatin1().constData());
1265 QMetaObject::invokeMethod(child, "testHasOwnPropertyFailureOne");
1266 QCOMPARE(child->property("enumNonValueHasOwnProperty").toBool(), false);
1267 QTest::ignoreMessage(QtWarningMsg, warning2.toLatin1().constData());
1268 QMetaObject::invokeMethod(child, "testHasOwnPropertyFailureTwo");
1269 QCOMPARE(child->property("moduleApiNonPropertyHasOwnProperty").toBool(), false);
1270 QTest::ignoreMessage(QtWarningMsg, warning3.toLatin1().constData());
1271 QMetaObject::invokeMethod(child, "testHasOwnPropertyFailureThree");
1272 QCOMPARE(child->property("listAtInvalidHasOwnProperty").toBool(), false);
1278 Tests bindings that indirectly cause their own deletion work.
1280 This test is best run under valgrind to ensure no invalid memory access occur.
1282 void tst_qdeclarativeecmascript::selfDeletingBinding()
1285 QDeclarativeComponent component(&engine, TEST_FILE("selfDeletingBinding.qml"));
1286 QObject *object = component.create();
1287 QVERIFY(object != 0);
1288 object->setProperty("triggerDelete", true);
1293 QDeclarativeComponent component(&engine, TEST_FILE("selfDeletingBinding.2.qml"));
1294 QObject *object = component.create();
1295 QVERIFY(object != 0);
1296 object->setProperty("triggerDelete", true);
1302 Test that extended object properties can be accessed.
1304 This test a regression where this used to crash. The issue was specificially
1305 for extended objects that did not include a synthesized meta object (so non-root
1306 and no synthesiszed properties).
1308 void tst_qdeclarativeecmascript::extendedObjectPropertyLookup()
1310 QDeclarativeComponent component(&engine, TEST_FILE("extendedObjectPropertyLookup.qml"));
1311 QObject *object = component.create();
1312 QVERIFY(object != 0);
1317 Test file/lineNumbers for binding/Script errors.
1319 void tst_qdeclarativeecmascript::scriptErrors()
1321 QDeclarativeComponent component(&engine, TEST_FILE("scriptErrors.qml"));
1322 QString url = component.url().toString();
1324 QString warning1 = url.left(url.length() - 3) + "js:2: Error: Invalid write to global property \"a\"";
1325 QString warning2 = url + ":5: ReferenceError: Can't find variable: a";
1326 QString warning3 = url.left(url.length() - 3) + "js:4: Error: Invalid write to global property \"a\"";
1327 QString warning4 = url + ":10: ReferenceError: Can't find variable: a";
1328 QString warning5 = url + ":8: ReferenceError: Can't find variable: a";
1329 QString warning6 = url + ":7: Unable to assign [undefined] to int x";
1330 QString warning7 = url + ":12: Error: Cannot assign to read-only property \"trueProperty\"";
1331 QString warning8 = url + ":13: Error: Cannot assign to non-existent property \"fakeProperty\"";
1333 QTest::ignoreMessage(QtWarningMsg, warning1.toLatin1().constData());
1334 QTest::ignoreMessage(QtWarningMsg, warning2.toLatin1().constData());
1335 QTest::ignoreMessage(QtWarningMsg, warning3.toLatin1().constData());
1336 QTest::ignoreMessage(QtWarningMsg, warning5.toLatin1().constData());
1337 QTest::ignoreMessage(QtWarningMsg, warning6.toLatin1().constData());
1338 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
1339 QVERIFY(object != 0);
1341 QTest::ignoreMessage(QtWarningMsg, warning4.toLatin1().constData());
1342 emit object->basicSignal();
1344 QTest::ignoreMessage(QtWarningMsg, warning7.toLatin1().constData());
1345 emit object->anotherBasicSignal();
1347 QTest::ignoreMessage(QtWarningMsg, warning8.toLatin1().constData());
1348 emit object->thirdBasicSignal();
1354 Test file/lineNumbers for inline functions.
1356 void tst_qdeclarativeecmascript::functionErrors()
1358 QDeclarativeComponent component(&engine, TEST_FILE("functionErrors.qml"));
1359 QString url = component.url().toString();
1361 QString warning = url + ":5: Error: Invalid write to global property \"a\"";
1363 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
1365 QObject *object = component.create();
1366 QVERIFY(object != 0);
1369 // test that if an exception occurs while invoking js function from cpp, it is reported as expected.
1370 QDeclarativeComponent componentTwo(&engine, TEST_FILE("scarceresources/scarceResourceFunctionFail.qml"));
1371 url = componentTwo.url().toString();
1372 object = componentTwo.create();
1373 QVERIFY(object != 0);
1375 QString srpname = object->property("srp_name").toString();
1377 warning = url + QLatin1String(":17: TypeError: Property 'scarceResource' of object ") + srpname +
1378 QLatin1String(" is not a function");
1379 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData()); // we expect a meaningful warning to be printed.
1380 QMetaObject::invokeMethod(object, "retrieveScarceResource");
1385 Test various errors that can occur when assigning a property from script
1387 void tst_qdeclarativeecmascript::propertyAssignmentErrors()
1389 QDeclarativeComponent component(&engine, TEST_FILE("propertyAssignmentErrors.qml"));
1391 QString url = component.url().toString();
1393 QObject *object = component.create();
1394 QVERIFY(object != 0);
1396 QCOMPARE(object->property("test1").toBool(), true);
1397 QCOMPARE(object->property("test2").toBool(), true);
1403 Test bindings still work when the reeval is triggered from within
1406 void tst_qdeclarativeecmascript::signalTriggeredBindings()
1408 QDeclarativeComponent component(&engine, TEST_FILE("signalTriggeredBindings.qml"));
1409 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1410 QVERIFY(object != 0);
1412 QCOMPARE(object->property("base").toReal(), 50.);
1413 QCOMPARE(object->property("test1").toReal(), 50.);
1414 QCOMPARE(object->property("test2").toReal(), 50.);
1416 object->basicSignal();
1418 QCOMPARE(object->property("base").toReal(), 200.);
1419 QCOMPARE(object->property("test1").toReal(), 200.);
1420 QCOMPARE(object->property("test2").toReal(), 200.);
1422 object->argumentSignal(10, QString(), 10, MyQmlObject::EnumValue4, Qt::RightButton);
1424 QCOMPARE(object->property("base").toReal(), 400.);
1425 QCOMPARE(object->property("test1").toReal(), 400.);
1426 QCOMPARE(object->property("test2").toReal(), 400.);
1432 Test that list properties can be iterated from ECMAScript
1434 void tst_qdeclarativeecmascript::listProperties()
1436 QDeclarativeComponent component(&engine, TEST_FILE("listProperties.qml"));
1437 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1438 QVERIFY(object != 0);
1440 QCOMPARE(object->property("test1").toInt(), 21);
1441 QCOMPARE(object->property("test2").toInt(), 2);
1442 QCOMPARE(object->property("test3").toBool(), true);
1443 QCOMPARE(object->property("test4").toBool(), true);
1448 void tst_qdeclarativeecmascript::exceptionClearsOnReeval()
1450 QDeclarativeComponent component(&engine, TEST_FILE("exceptionClearsOnReeval.qml"));
1451 QString url = component.url().toString();
1453 QString warning = url + ":4: TypeError: Cannot read property 'objectProperty' of null";
1455 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
1456 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1457 QVERIFY(object != 0);
1459 QCOMPARE(object->property("test").toBool(), false);
1461 MyQmlObject object2;
1462 MyQmlObject object3;
1463 object2.setObjectProperty(&object3);
1464 object->setObjectProperty(&object2);
1466 QCOMPARE(object->property("test").toBool(), true);
1471 void tst_qdeclarativeecmascript::exceptionSlotProducesWarning()
1473 QDeclarativeComponent component(&engine, TEST_FILE("exceptionProducesWarning.qml"));
1474 QString url = component.url().toString();
1476 QString warning = component.url().toString() + ":6: Error: JS exception";
1478 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
1479 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1480 QVERIFY(object != 0);
1484 void tst_qdeclarativeecmascript::exceptionBindingProducesWarning()
1486 QDeclarativeComponent component(&engine, TEST_FILE("exceptionProducesWarning2.qml"));
1487 QString url = component.url().toString();
1489 QString warning = component.url().toString() + ":5: Error: JS exception";
1491 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
1492 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1493 QVERIFY(object != 0);
1497 static int transientErrorsMsgCount = 0;
1498 static void transientErrorsMsgHandler(QtMsgType, const char *)
1500 ++transientErrorsMsgCount;
1503 // Check that transient binding errors are not displayed
1504 void tst_qdeclarativeecmascript::transientErrors()
1507 QDeclarativeComponent component(&engine, TEST_FILE("transientErrors.qml"));
1509 transientErrorsMsgCount = 0;
1510 QtMsgHandler old = qInstallMsgHandler(transientErrorsMsgHandler);
1512 QObject *object = component.create();
1513 QVERIFY(object != 0);
1515 qInstallMsgHandler(old);
1517 QCOMPARE(transientErrorsMsgCount, 0);
1522 // One binding erroring multiple times, but then resolving
1524 QDeclarativeComponent component(&engine, TEST_FILE("transientErrors.2.qml"));
1526 transientErrorsMsgCount = 0;
1527 QtMsgHandler old = qInstallMsgHandler(transientErrorsMsgHandler);
1529 QObject *object = component.create();
1530 QVERIFY(object != 0);
1532 qInstallMsgHandler(old);
1534 QCOMPARE(transientErrorsMsgCount, 0);
1540 // Check that errors during shutdown are minimized
1541 void tst_qdeclarativeecmascript::shutdownErrors()
1543 QDeclarativeComponent component(&engine, TEST_FILE("shutdownErrors.qml"));
1544 QObject *object = component.create();
1545 QVERIFY(object != 0);
1547 transientErrorsMsgCount = 0;
1548 QtMsgHandler old = qInstallMsgHandler(transientErrorsMsgHandler);
1552 qInstallMsgHandler(old);
1553 QCOMPARE(transientErrorsMsgCount, 0);
1556 void tst_qdeclarativeecmascript::compositePropertyType()
1558 QDeclarativeComponent component(&engine, TEST_FILE("compositePropertyType.qml"));
1559 QTest::ignoreMessage(QtDebugMsg, "hello world");
1560 QObject *object = qobject_cast<QObject *>(component.create());
1565 void tst_qdeclarativeecmascript::jsObject()
1567 QDeclarativeComponent component(&engine, TEST_FILE("jsObject.qml"));
1568 QObject *object = component.create();
1569 QVERIFY(object != 0);
1571 QCOMPARE(object->property("test").toInt(), 92);
1576 void tst_qdeclarativeecmascript::undefinedResetsProperty()
1579 QDeclarativeComponent component(&engine, TEST_FILE("undefinedResetsProperty.qml"));
1580 QObject *object = component.create();
1581 QVERIFY(object != 0);
1583 QCOMPARE(object->property("resettableProperty").toInt(), 92);
1585 object->setProperty("setUndefined", true);
1587 QCOMPARE(object->property("resettableProperty").toInt(), 13);
1589 object->setProperty("setUndefined", false);
1591 QCOMPARE(object->property("resettableProperty").toInt(), 92);
1596 QDeclarativeComponent component(&engine, TEST_FILE("undefinedResetsProperty.2.qml"));
1597 QObject *object = component.create();
1598 QVERIFY(object != 0);
1600 QCOMPARE(object->property("resettableProperty").toInt(), 19);
1602 QMetaObject::invokeMethod(object, "doReset");
1604 QCOMPARE(object->property("resettableProperty").toInt(), 13);
1611 void tst_qdeclarativeecmascript::bug1()
1613 QDeclarativeComponent component(&engine, TEST_FILE("bug.1.qml"));
1614 QObject *object = component.create();
1615 QVERIFY(object != 0);
1617 QCOMPARE(object->property("test").toInt(), 14);
1619 object->setProperty("a", 11);
1621 QCOMPARE(object->property("test").toInt(), 3);
1623 object->setProperty("b", true);
1625 QCOMPARE(object->property("test").toInt(), 9);
1630 void tst_qdeclarativeecmascript::bug2()
1632 QDeclarativeComponent component(&engine);
1633 component.setData("import Qt.test 1.0;\nQPlainTextEdit { width: 100 }", QUrl());
1635 QObject *object = component.create();
1636 QVERIFY(object != 0);
1641 // Don't crash in createObject when the component has errors.
1642 void tst_qdeclarativeecmascript::dynamicCreationCrash()
1644 QDeclarativeComponent component(&engine, TEST_FILE("dynamicCreation.qml"));
1645 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1646 QVERIFY(object != 0);
1648 QTest::ignoreMessage(QtWarningMsg, "QDeclarativeComponent: Component is not ready");
1649 QMetaObject::invokeMethod(object, "dontCrash");
1650 QObject *created = object->objectProperty();
1651 QVERIFY(created == 0);
1657 void tst_qdeclarativeecmascript::regExpBug()
1659 QDeclarativeComponent component(&engine, TEST_FILE("regExp.qml"));
1660 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1661 QVERIFY(object != 0);
1662 QCOMPARE(object->regExp().pattern(), QLatin1String("[a-zA-z]"));
1666 static inline bool evaluate_error(QV8Engine *engine, v8::Handle<v8::Object> o, const char *source)
1668 QString functionSource = QLatin1String("(function(object) { return ") +
1669 QLatin1String(source) + QLatin1String(" })");
1671 v8::Local<v8::Script> program = v8::Script::Compile(engine->toString(functionSource));
1674 v8::Handle<v8::Function> function = v8::Handle<v8::Function>::Cast(program->Run());
1675 if (function.IsEmpty())
1677 v8::Handle<v8::Value> args[] = { o };
1678 function->Call(engine->global(), 1, args);
1679 return tc.HasCaught();
1682 static inline bool evaluate_value(QV8Engine *engine, v8::Handle<v8::Object> o,
1683 const char *source, v8::Handle<v8::Value> result)
1685 QString functionSource = QLatin1String("(function(object) { return ") +
1686 QLatin1String(source) + QLatin1String(" })");
1688 v8::Local<v8::Script> program = v8::Script::Compile(engine->toString(functionSource));
1691 v8::Handle<v8::Function> function = v8::Handle<v8::Function>::Cast(program->Run());
1692 if (function.IsEmpty())
1694 v8::Handle<v8::Value> args[] = { o };
1696 v8::Handle<v8::Value> value = function->Call(engine->global(), 1, args);
1701 return value->StrictEquals(result);
1704 static inline v8::Handle<v8::Value> evaluate(QV8Engine *engine, v8::Handle<v8::Object> o,
1707 QString functionSource = QLatin1String("(function(object) { return ") +
1708 QLatin1String(source) + QLatin1String(" })");
1710 v8::Local<v8::Script> program = v8::Script::Compile(engine->toString(functionSource));
1712 return v8::Handle<v8::Value>();
1713 v8::Handle<v8::Function> function = v8::Handle<v8::Function>::Cast(program->Run());
1714 if (function.IsEmpty())
1715 return v8::Handle<v8::Value>();
1716 v8::Handle<v8::Value> args[] = { o };
1718 v8::Handle<v8::Value> value = function->Call(engine->global(), 1, args);
1721 return v8::Handle<v8::Value>();
1725 #define EVALUATE_ERROR(source) evaluate_error(engine, object, source)
1726 #define EVALUATE_VALUE(source, result) evaluate_value(engine, object, source, result)
1727 #define EVALUATE(source) evaluate(engine, object, source)
1729 void tst_qdeclarativeecmascript::callQtInvokables()
1731 MyInvokableObject o;
1733 QDeclarativeEngine qmlengine;
1734 QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(&qmlengine);
1736 QV8Engine *engine = ep->v8engine();
1738 v8::HandleScope handle_scope;
1739 v8::Context::Scope scope(engine->context());
1741 v8::Local<v8::Object> object = engine->newQObject(&o)->ToObject();
1743 // Non-existent methods
1745 QVERIFY(EVALUATE_ERROR("object.method_nonexistent()"));
1746 QCOMPARE(o.error(), false);
1747 QCOMPARE(o.invoked(), -1);
1748 QCOMPARE(o.actuals().count(), 0);
1751 QVERIFY(EVALUATE_ERROR("object.method_nonexistent(10, 11)"));
1752 QCOMPARE(o.error(), false);
1753 QCOMPARE(o.invoked(), -1);
1754 QCOMPARE(o.actuals().count(), 0);
1756 // Insufficient arguments
1758 QVERIFY(EVALUATE_ERROR("object.method_int()"));
1759 QCOMPARE(o.error(), false);
1760 QCOMPARE(o.invoked(), -1);
1761 QCOMPARE(o.actuals().count(), 0);
1764 QVERIFY(EVALUATE_ERROR("object.method_intint(10)"));
1765 QCOMPARE(o.error(), false);
1766 QCOMPARE(o.invoked(), -1);
1767 QCOMPARE(o.actuals().count(), 0);
1769 // Excessive arguments
1771 QVERIFY(EVALUATE_VALUE("object.method_int(10, 11)", v8::Undefined()));
1772 QCOMPARE(o.error(), false);
1773 QCOMPARE(o.invoked(), 8);
1774 QCOMPARE(o.actuals().count(), 1);
1775 QCOMPARE(o.actuals().at(0), QVariant(10));
1778 QVERIFY(EVALUATE_VALUE("object.method_intint(10, 11, 12)", v8::Undefined()));
1779 QCOMPARE(o.error(), false);
1780 QCOMPARE(o.invoked(), 9);
1781 QCOMPARE(o.actuals().count(), 2);
1782 QCOMPARE(o.actuals().at(0), QVariant(10));
1783 QCOMPARE(o.actuals().at(1), QVariant(11));
1785 // Test return types
1787 QVERIFY(EVALUATE_VALUE("object.method_NoArgs()", v8::Undefined()));
1788 QCOMPARE(o.error(), false);
1789 QCOMPARE(o.invoked(), 0);
1790 QCOMPARE(o.actuals().count(), 0);
1793 QVERIFY(EVALUATE_VALUE("object.method_NoArgs_int()", v8::Integer::New(6)));
1794 QCOMPARE(o.error(), false);
1795 QCOMPARE(o.invoked(), 1);
1796 QCOMPARE(o.actuals().count(), 0);
1799 QVERIFY(EVALUATE_VALUE("object.method_NoArgs_real()", v8::Number::New(19.75)));
1800 QCOMPARE(o.error(), false);
1801 QCOMPARE(o.invoked(), 2);
1802 QCOMPARE(o.actuals().count(), 0);
1806 v8::Handle<v8::Value> ret = EVALUATE("object.method_NoArgs_QPointF()");
1807 QVERIFY(!ret.IsEmpty());
1808 QCOMPARE(engine->toVariant(ret, -1), QVariant(QPointF(123, 4.5)));
1809 QCOMPARE(o.error(), false);
1810 QCOMPARE(o.invoked(), 3);
1811 QCOMPARE(o.actuals().count(), 0);
1816 v8::Handle<v8::Value> ret = EVALUATE("object.method_NoArgs_QObject()");
1817 QCOMPARE(engine->toQObject(ret), (QObject *)&o);
1818 QCOMPARE(o.error(), false);
1819 QCOMPARE(o.invoked(), 4);
1820 QCOMPARE(o.actuals().count(), 0);
1824 QVERIFY(EVALUATE_VALUE("object.method_NoArgs_unknown()", v8::Undefined()));
1825 QCOMPARE(o.error(), false);
1826 QCOMPARE(o.invoked(), 5);
1827 QCOMPARE(o.actuals().count(), 0);
1831 v8::Handle<v8::Value> ret = EVALUATE("object.method_NoArgs_QScriptValue()");
1832 QVERIFY(ret->IsString());
1833 QCOMPARE(engine->toString(ret), QString("Hello world"));
1834 QCOMPARE(o.error(), false);
1835 QCOMPARE(o.invoked(), 6);
1836 QCOMPARE(o.actuals().count(), 0);
1840 QVERIFY(EVALUATE_VALUE("object.method_NoArgs_QVariant()", engine->toString("QML rocks")));
1841 QCOMPARE(o.error(), false);
1842 QCOMPARE(o.invoked(), 7);
1843 QCOMPARE(o.actuals().count(), 0);
1847 QVERIFY(EVALUATE_VALUE("object.method_int(94)", v8::Undefined()));
1848 QCOMPARE(o.error(), false);
1849 QCOMPARE(o.invoked(), 8);
1850 QCOMPARE(o.actuals().count(), 1);
1851 QCOMPARE(o.actuals().at(0), QVariant(94));
1854 QVERIFY(EVALUATE_VALUE("object.method_int(\"94\")", v8::Undefined()));
1855 QCOMPARE(o.error(), false);
1856 QCOMPARE(o.invoked(), 8);
1857 QCOMPARE(o.actuals().count(), 1);
1858 QCOMPARE(o.actuals().at(0), QVariant(94));
1861 QVERIFY(EVALUATE_VALUE("object.method_int(\"not a number\")", v8::Undefined()));
1862 QCOMPARE(o.error(), false);
1863 QCOMPARE(o.invoked(), 8);
1864 QCOMPARE(o.actuals().count(), 1);
1865 QCOMPARE(o.actuals().at(0), QVariant(0));
1868 QVERIFY(EVALUATE_VALUE("object.method_int(null)", v8::Undefined()));
1869 QCOMPARE(o.error(), false);
1870 QCOMPARE(o.invoked(), 8);
1871 QCOMPARE(o.actuals().count(), 1);
1872 QCOMPARE(o.actuals().at(0), QVariant(0));
1875 QVERIFY(EVALUATE_VALUE("object.method_int(undefined)", v8::Undefined()));
1876 QCOMPARE(o.error(), false);
1877 QCOMPARE(o.invoked(), 8);
1878 QCOMPARE(o.actuals().count(), 1);
1879 QCOMPARE(o.actuals().at(0), QVariant(0));
1882 QVERIFY(EVALUATE_VALUE("object.method_int(object)", v8::Undefined()));
1883 QCOMPARE(o.error(), false);
1884 QCOMPARE(o.invoked(), 8);
1885 QCOMPARE(o.actuals().count(), 1);
1886 QCOMPARE(o.actuals().at(0), QVariant(0));
1889 QVERIFY(EVALUATE_VALUE("object.method_intint(122, 9)", v8::Undefined()));
1890 QCOMPARE(o.error(), false);
1891 QCOMPARE(o.invoked(), 9);
1892 QCOMPARE(o.actuals().count(), 2);
1893 QCOMPARE(o.actuals().at(0), QVariant(122));
1894 QCOMPARE(o.actuals().at(1), QVariant(9));
1897 QVERIFY(EVALUATE_VALUE("object.method_real(94.3)", v8::Undefined()));
1898 QCOMPARE(o.error(), false);
1899 QCOMPARE(o.invoked(), 10);
1900 QCOMPARE(o.actuals().count(), 1);
1901 QCOMPARE(o.actuals().at(0), QVariant(94.3));
1904 QVERIFY(EVALUATE_VALUE("object.method_real(\"94.3\")", v8::Undefined()));
1905 QCOMPARE(o.error(), false);
1906 QCOMPARE(o.invoked(), 10);
1907 QCOMPARE(o.actuals().count(), 1);
1908 QCOMPARE(o.actuals().at(0), QVariant(94.3));
1911 QVERIFY(EVALUATE_VALUE("object.method_real(\"not a number\")", v8::Undefined()));
1912 QCOMPARE(o.error(), false);
1913 QCOMPARE(o.invoked(), 10);
1914 QCOMPARE(o.actuals().count(), 1);
1915 QVERIFY(qIsNaN(o.actuals().at(0).toDouble()));
1918 QVERIFY(EVALUATE_VALUE("object.method_real(null)", v8::Undefined()));
1919 QCOMPARE(o.error(), false);
1920 QCOMPARE(o.invoked(), 10);
1921 QCOMPARE(o.actuals().count(), 1);
1922 QCOMPARE(o.actuals().at(0), QVariant(0));
1925 QVERIFY(EVALUATE_VALUE("object.method_real(undefined)", v8::Undefined()));
1926 QCOMPARE(o.error(), false);
1927 QCOMPARE(o.invoked(), 10);
1928 QCOMPARE(o.actuals().count(), 1);
1929 QVERIFY(qIsNaN(o.actuals().at(0).toDouble()));
1932 QVERIFY(EVALUATE_VALUE("object.method_real(object)", v8::Undefined()));
1933 QCOMPARE(o.error(), false);
1934 QCOMPARE(o.invoked(), 10);
1935 QCOMPARE(o.actuals().count(), 1);
1936 QVERIFY(qIsNaN(o.actuals().at(0).toDouble()));
1939 QVERIFY(EVALUATE_VALUE("object.method_QString(\"Hello world\")", v8::Undefined()));
1940 QCOMPARE(o.error(), false);
1941 QCOMPARE(o.invoked(), 11);
1942 QCOMPARE(o.actuals().count(), 1);
1943 QCOMPARE(o.actuals().at(0), QVariant("Hello world"));
1946 QVERIFY(EVALUATE_VALUE("object.method_QString(19)", v8::Undefined()));
1947 QCOMPARE(o.error(), false);
1948 QCOMPARE(o.invoked(), 11);
1949 QCOMPARE(o.actuals().count(), 1);
1950 QCOMPARE(o.actuals().at(0), QVariant("19"));
1954 QString expected = "MyInvokableObject(0x" + QString::number((quintptr)&o, 16) + ")";
1955 QVERIFY(EVALUATE_VALUE("object.method_QString(object)", v8::Undefined()));
1956 QCOMPARE(o.error(), false);
1957 QCOMPARE(o.invoked(), 11);
1958 QCOMPARE(o.actuals().count(), 1);
1959 QCOMPARE(o.actuals().at(0), QVariant(expected));
1963 QVERIFY(EVALUATE_VALUE("object.method_QString(null)", v8::Undefined()));
1964 QCOMPARE(o.error(), false);
1965 QCOMPARE(o.invoked(), 11);
1966 QCOMPARE(o.actuals().count(), 1);
1967 QCOMPARE(o.actuals().at(0), QVariant(QString()));
1970 QVERIFY(EVALUATE_VALUE("object.method_QString(undefined)", v8::Undefined()));
1971 QCOMPARE(o.error(), false);
1972 QCOMPARE(o.invoked(), 11);
1973 QCOMPARE(o.actuals().count(), 1);
1974 QCOMPARE(o.actuals().at(0), QVariant(QString()));
1977 QVERIFY(EVALUATE_VALUE("object.method_QPointF(0)", v8::Undefined()));
1978 QCOMPARE(o.error(), false);
1979 QCOMPARE(o.invoked(), 12);
1980 QCOMPARE(o.actuals().count(), 1);
1981 QCOMPARE(o.actuals().at(0), QVariant(QPointF()));
1984 QVERIFY(EVALUATE_VALUE("object.method_QPointF(null)", v8::Undefined()));
1985 QCOMPARE(o.error(), false);
1986 QCOMPARE(o.invoked(), 12);
1987 QCOMPARE(o.actuals().count(), 1);
1988 QCOMPARE(o.actuals().at(0), QVariant(QPointF()));
1991 QVERIFY(EVALUATE_VALUE("object.method_QPointF(undefined)", v8::Undefined()));
1992 QCOMPARE(o.error(), false);
1993 QCOMPARE(o.invoked(), 12);
1994 QCOMPARE(o.actuals().count(), 1);
1995 QCOMPARE(o.actuals().at(0), QVariant(QPointF()));
1998 QVERIFY(EVALUATE_VALUE("object.method_QPointF(object)", v8::Undefined()));
1999 QCOMPARE(o.error(), false);
2000 QCOMPARE(o.invoked(), 12);
2001 QCOMPARE(o.actuals().count(), 1);
2002 QCOMPARE(o.actuals().at(0), QVariant(QPointF()));
2005 QVERIFY(EVALUATE_VALUE("object.method_QPointF(object.method_get_QPointF())", v8::Undefined()));
2006 QCOMPARE(o.error(), false);
2007 QCOMPARE(o.invoked(), 12);
2008 QCOMPARE(o.actuals().count(), 1);
2009 QCOMPARE(o.actuals().at(0), QVariant(QPointF(99.3, -10.2)));
2012 QVERIFY(EVALUATE_VALUE("object.method_QPointF(object.method_get_QPoint())", v8::Undefined()));
2013 QCOMPARE(o.error(), false);
2014 QCOMPARE(o.invoked(), 12);
2015 QCOMPARE(o.actuals().count(), 1);
2016 QCOMPARE(o.actuals().at(0), QVariant(QPointF(9, 12)));
2019 QVERIFY(EVALUATE_VALUE("object.method_QObject(0)", v8::Undefined()));
2020 QCOMPARE(o.error(), false);
2021 QCOMPARE(o.invoked(), 13);
2022 QCOMPARE(o.actuals().count(), 1);
2023 QCOMPARE(o.actuals().at(0), qVariantFromValue((QObject *)0));
2026 QVERIFY(EVALUATE_VALUE("object.method_QObject(\"Hello world\")", v8::Undefined()));
2027 QCOMPARE(o.error(), false);
2028 QCOMPARE(o.invoked(), 13);
2029 QCOMPARE(o.actuals().count(), 1);
2030 QCOMPARE(o.actuals().at(0), qVariantFromValue((QObject *)0));
2033 QVERIFY(EVALUATE_VALUE("object.method_QObject(null)", v8::Undefined()));
2034 QCOMPARE(o.error(), false);
2035 QCOMPARE(o.invoked(), 13);
2036 QCOMPARE(o.actuals().count(), 1);
2037 QCOMPARE(o.actuals().at(0), qVariantFromValue((QObject *)0));
2040 QVERIFY(EVALUATE_VALUE("object.method_QObject(undefined)", v8::Undefined()));
2041 QCOMPARE(o.error(), false);
2042 QCOMPARE(o.invoked(), 13);
2043 QCOMPARE(o.actuals().count(), 1);
2044 QCOMPARE(o.actuals().at(0), qVariantFromValue((QObject *)0));
2047 QVERIFY(EVALUATE_VALUE("object.method_QObject(object)", v8::Undefined()));
2048 QCOMPARE(o.error(), false);
2049 QCOMPARE(o.invoked(), 13);
2050 QCOMPARE(o.actuals().count(), 1);
2051 QCOMPARE(o.actuals().at(0), qVariantFromValue((QObject *)&o));
2054 QVERIFY(EVALUATE_VALUE("object.method_QScriptValue(null)", v8::Undefined()));
2055 QCOMPARE(o.error(), false);
2056 QCOMPARE(o.invoked(), 14);
2057 QCOMPARE(o.actuals().count(), 1);
2058 QVERIFY(qvariant_cast<QJSValue>(o.actuals().at(0)).isNull());
2061 QVERIFY(EVALUATE_VALUE("object.method_QScriptValue(undefined)", v8::Undefined()));
2062 QCOMPARE(o.error(), false);
2063 QCOMPARE(o.invoked(), 14);
2064 QCOMPARE(o.actuals().count(), 1);
2065 QVERIFY(qvariant_cast<QJSValue>(o.actuals().at(0)).isUndefined());
2068 QVERIFY(EVALUATE_VALUE("object.method_QScriptValue(19)", v8::Undefined()));
2069 QCOMPARE(o.error(), false);
2070 QCOMPARE(o.invoked(), 14);
2071 QCOMPARE(o.actuals().count(), 1);
2072 QVERIFY(qvariant_cast<QJSValue>(o.actuals().at(0)).strictlyEquals(QJSValue(19)));
2075 QVERIFY(EVALUATE_VALUE("object.method_QScriptValue([19, 20])", v8::Undefined()));
2076 QCOMPARE(o.error(), false);
2077 QCOMPARE(o.invoked(), 14);
2078 QCOMPARE(o.actuals().count(), 1);
2079 QVERIFY(qvariant_cast<QJSValue>(o.actuals().at(0)).isArray());
2082 QVERIFY(EVALUATE_VALUE("object.method_intQScriptValue(4, null)", v8::Undefined()));
2083 QCOMPARE(o.error(), false);
2084 QCOMPARE(o.invoked(), 15);
2085 QCOMPARE(o.actuals().count(), 2);
2086 QCOMPARE(o.actuals().at(0), QVariant(4));
2087 QVERIFY(qvariant_cast<QJSValue>(o.actuals().at(1)).isNull());
2090 QVERIFY(EVALUATE_VALUE("object.method_intQScriptValue(8, undefined)", v8::Undefined()));
2091 QCOMPARE(o.error(), false);
2092 QCOMPARE(o.invoked(), 15);
2093 QCOMPARE(o.actuals().count(), 2);
2094 QCOMPARE(o.actuals().at(0), QVariant(8));
2095 QVERIFY(qvariant_cast<QJSValue>(o.actuals().at(1)).isUndefined());
2098 QVERIFY(EVALUATE_VALUE("object.method_intQScriptValue(3, 19)", v8::Undefined()));
2099 QCOMPARE(o.error(), false);
2100 QCOMPARE(o.invoked(), 15);
2101 QCOMPARE(o.actuals().count(), 2);
2102 QCOMPARE(o.actuals().at(0), QVariant(3));
2103 QVERIFY(qvariant_cast<QJSValue>(o.actuals().at(1)).strictlyEquals(QJSValue(19)));
2106 QVERIFY(EVALUATE_VALUE("object.method_intQScriptValue(44, [19, 20])", v8::Undefined()));
2107 QCOMPARE(o.error(), false);
2108 QCOMPARE(o.invoked(), 15);
2109 QCOMPARE(o.actuals().count(), 2);
2110 QCOMPARE(o.actuals().at(0), QVariant(44));
2111 QVERIFY(qvariant_cast<QJSValue>(o.actuals().at(1)).isArray());
2114 QVERIFY(EVALUATE_ERROR("object.method_overload()"));
2115 QCOMPARE(o.error(), false);
2116 QCOMPARE(o.invoked(), -1);
2117 QCOMPARE(o.actuals().count(), 0);
2120 QVERIFY(EVALUATE_VALUE("object.method_overload(10)", v8::Undefined()));
2121 QCOMPARE(o.error(), false);
2122 QCOMPARE(o.invoked(), 16);
2123 QCOMPARE(o.actuals().count(), 1);
2124 QCOMPARE(o.actuals().at(0), QVariant(10));
2127 QVERIFY(EVALUATE_VALUE("object.method_overload(10, 11)", v8::Undefined()));
2128 QCOMPARE(o.error(), false);
2129 QCOMPARE(o.invoked(), 17);
2130 QCOMPARE(o.actuals().count(), 2);
2131 QCOMPARE(o.actuals().at(0), QVariant(10));
2132 QCOMPARE(o.actuals().at(1), QVariant(11));
2135 QVERIFY(EVALUATE_VALUE("object.method_overload(\"Hello\")", v8::Undefined()));
2136 QCOMPARE(o.error(), false);
2137 QCOMPARE(o.invoked(), 18);
2138 QCOMPARE(o.actuals().count(), 1);
2139 QCOMPARE(o.actuals().at(0), QVariant(QString("Hello")));
2142 QVERIFY(EVALUATE_VALUE("object.method_with_enum(9)", v8::Undefined()));
2143 QCOMPARE(o.error(), false);
2144 QCOMPARE(o.invoked(), 19);
2145 QCOMPARE(o.actuals().count(), 1);
2146 QCOMPARE(o.actuals().at(0), QVariant(9));
2149 QVERIFY(EVALUATE_VALUE("object.method_default(10)", v8::Integer::New(19)));
2150 QCOMPARE(o.error(), false);
2151 QCOMPARE(o.invoked(), 20);
2152 QCOMPARE(o.actuals().count(), 2);
2153 QCOMPARE(o.actuals().at(0), QVariant(10));
2154 QCOMPARE(o.actuals().at(1), QVariant(19));
2157 QVERIFY(EVALUATE_VALUE("object.method_default(10, 13)", v8::Integer::New(13)));
2158 QCOMPARE(o.error(), false);
2159 QCOMPARE(o.invoked(), 20);
2160 QCOMPARE(o.actuals().count(), 2);
2161 QCOMPARE(o.actuals().at(0), QVariant(10));
2162 QCOMPARE(o.actuals().at(1), QVariant(13));
2165 QVERIFY(EVALUATE_VALUE("object.method_inherited(9)", v8::Undefined()));
2166 QCOMPARE(o.error(), false);
2167 QCOMPARE(o.invoked(), -3);
2168 QCOMPARE(o.actuals().count(), 1);
2169 QCOMPARE(o.actuals().at(0), QVariant(9));
2172 QVERIFY(EVALUATE_VALUE("object.method_QVariant(9)", v8::Undefined()));
2173 QCOMPARE(o.error(), false);
2174 QCOMPARE(o.invoked(), 21);
2175 QCOMPARE(o.actuals().count(), 2);
2176 QCOMPARE(o.actuals().at(0), QVariant(9));
2177 QCOMPARE(o.actuals().at(1), QVariant());
2180 QVERIFY(EVALUATE_VALUE("object.method_QVariant(\"Hello\", \"World\")", v8::Undefined()));
2181 QCOMPARE(o.error(), false);
2182 QCOMPARE(o.invoked(), 21);
2183 QCOMPARE(o.actuals().count(), 2);
2184 QCOMPARE(o.actuals().at(0), QVariant(QString("Hello")));
2185 QCOMPARE(o.actuals().at(1), QVariant(QString("World")));
2188 // QTBUG-13047 (check that you can pass registered object types as args)
2189 void tst_qdeclarativeecmascript::invokableObjectArg()
2191 QDeclarativeComponent component(&engine, TEST_FILE("invokableObjectArg.qml"));
2193 QObject *o = component.create();
2195 MyQmlObject *qmlobject = qobject_cast<MyQmlObject *>(o);
2197 QCOMPARE(qmlobject->myinvokableObject, qmlobject);
2202 // QTBUG-13047 (check that you can return registered object types from methods)
2203 void tst_qdeclarativeecmascript::invokableObjectRet()
2205 QDeclarativeComponent component(&engine, TEST_FILE("invokableObjectRet.qml"));
2207 QObject *o = component.create();
2209 QCOMPARE(o->property("test").toBool(), true);
2214 void tst_qdeclarativeecmascript::listToVariant()
2216 QDeclarativeComponent component(&engine, TEST_FILE("listToVariant.qml"));
2218 MyQmlContainer container;
2220 QDeclarativeContext context(engine.rootContext());
2221 context.setContextObject(&container);
2223 QObject *object = component.create(&context);
2224 QVERIFY(object != 0);
2226 QVariant v = object->property("test");
2227 QCOMPARE(v.userType(), qMetaTypeId<QDeclarativeListReference>());
2228 QVERIFY(qvariant_cast<QDeclarativeListReference>(v).object() == &container);
2234 void tst_qdeclarativeecmascript::multiEngineObject()
2237 obj.setStringProperty("Howdy planet");
2239 QDeclarativeEngine e1;
2240 e1.rootContext()->setContextProperty("thing", &obj);
2241 QDeclarativeComponent c1(&e1, TEST_FILE("multiEngineObject.qml"));
2243 QDeclarativeEngine e2;
2244 e2.rootContext()->setContextProperty("thing", &obj);
2245 QDeclarativeComponent c2(&e2, TEST_FILE("multiEngineObject.qml"));
2247 QObject *o1 = c1.create();
2248 QObject *o2 = c2.create();
2250 QCOMPARE(o1->property("test").toString(), QString("Howdy planet"));
2251 QCOMPARE(o2->property("test").toString(), QString("Howdy planet"));
2257 // Test that references to QObjects are cleanup when the object is destroyed
2258 void tst_qdeclarativeecmascript::deletedObject()
2260 QDeclarativeComponent component(&engine, TEST_FILE("deletedObject.qml"));
2262 QObject *object = component.create();
2264 QCOMPARE(object->property("test1").toBool(), true);
2265 QCOMPARE(object->property("test2").toBool(), true);
2266 QCOMPARE(object->property("test3").toBool(), true);
2267 QCOMPARE(object->property("test4").toBool(), true);
2272 void tst_qdeclarativeecmascript::attachedPropertyScope()
2274 QDeclarativeComponent component(&engine, TEST_FILE("attachedPropertyScope.qml"));
2276 QObject *object = component.create();
2277 QVERIFY(object != 0);
2279 MyQmlAttachedObject *attached =
2280 qobject_cast<MyQmlAttachedObject *>(qmlAttachedPropertiesObject<MyQmlObject>(object));
2281 QVERIFY(attached != 0);
2283 QCOMPARE(object->property("value2").toInt(), 0);
2285 attached->emitMySignal();
2287 QCOMPARE(object->property("value2").toInt(), 9);
2292 void tst_qdeclarativeecmascript::scriptConnect()
2295 QDeclarativeComponent component(&engine, TEST_FILE("scriptConnect.1.qml"));
2297 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2298 QVERIFY(object != 0);
2300 QCOMPARE(object->property("test").toBool(), false);
2301 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2302 QCOMPARE(object->property("test").toBool(), true);
2308 QDeclarativeComponent component(&engine, TEST_FILE("scriptConnect.2.qml"));
2310 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2311 QVERIFY(object != 0);
2313 QCOMPARE(object->property("test").toBool(), false);
2314 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2315 QCOMPARE(object->property("test").toBool(), true);
2321 QDeclarativeComponent component(&engine, TEST_FILE("scriptConnect.3.qml"));
2323 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2324 QVERIFY(object != 0);
2326 QCOMPARE(object->property("test").toBool(), false);
2327 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2328 QCOMPARE(object->property("test").toBool(), true);
2334 QDeclarativeComponent component(&engine, TEST_FILE("scriptConnect.4.qml"));
2336 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2337 QVERIFY(object != 0);
2339 QCOMPARE(object->methodCalled(), false);
2340 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2341 QCOMPARE(object->methodCalled(), true);
2347 QDeclarativeComponent component(&engine, TEST_FILE("scriptConnect.5.qml"));
2349 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2350 QVERIFY(object != 0);
2352 QCOMPARE(object->methodCalled(), false);
2353 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2354 QCOMPARE(object->methodCalled(), true);
2360 QDeclarativeComponent component(&engine, TEST_FILE("scriptConnect.6.qml"));
2362 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2363 QVERIFY(object != 0);
2365 QCOMPARE(object->property("test").toInt(), 0);
2366 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2367 QCOMPARE(object->property("test").toInt(), 2);
2373 void tst_qdeclarativeecmascript::scriptDisconnect()
2376 QDeclarativeComponent component(&engine, TEST_FILE("scriptDisconnect.1.qml"));
2378 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2379 QVERIFY(object != 0);
2381 QCOMPARE(object->property("test").toInt(), 0);
2382 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2383 QCOMPARE(object->property("test").toInt(), 1);
2384 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2385 QCOMPARE(object->property("test").toInt(), 2);
2386 emit object->basicSignal();
2387 QCOMPARE(object->property("test").toInt(), 2);
2388 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2389 QCOMPARE(object->property("test").toInt(), 2);
2395 QDeclarativeComponent component(&engine, TEST_FILE("scriptDisconnect.2.qml"));
2397 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2398 QVERIFY(object != 0);
2400 QCOMPARE(object->property("test").toInt(), 0);
2401 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2402 QCOMPARE(object->property("test").toInt(), 1);
2403 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2404 QCOMPARE(object->property("test").toInt(), 2);
2405 emit object->basicSignal();
2406 QCOMPARE(object->property("test").toInt(), 2);
2407 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2408 QCOMPARE(object->property("test").toInt(), 2);
2414 QDeclarativeComponent component(&engine, TEST_FILE("scriptDisconnect.3.qml"));
2416 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2417 QVERIFY(object != 0);
2419 QCOMPARE(object->property("test").toInt(), 0);
2420 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2421 QCOMPARE(object->property("test").toInt(), 1);
2422 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2423 QCOMPARE(object->property("test").toInt(), 2);
2424 emit object->basicSignal();
2425 QCOMPARE(object->property("test").toInt(), 2);
2426 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2427 QCOMPARE(object->property("test").toInt(), 3);
2432 QDeclarativeComponent component(&engine, TEST_FILE("scriptDisconnect.4.qml"));
2434 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2435 QVERIFY(object != 0);
2437 QCOMPARE(object->property("test").toInt(), 0);
2438 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2439 QCOMPARE(object->property("test").toInt(), 1);
2440 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2441 QCOMPARE(object->property("test").toInt(), 2);
2442 emit object->basicSignal();
2443 QCOMPARE(object->property("test").toInt(), 2);
2444 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2445 QCOMPARE(object->property("test").toInt(), 3);
2451 class OwnershipObject : public QObject
2455 OwnershipObject() { object = new QObject; }
2457 QPointer<QObject> object;
2460 QObject *getObject() { return object; }
2463 void tst_qdeclarativeecmascript::ownership()
2465 OwnershipObject own;
2466 QDeclarativeContext *context = new QDeclarativeContext(engine.rootContext());
2467 context->setContextObject(&own);
2470 QDeclarativeComponent component(&engine, TEST_FILE("ownership.qml"));
2472 QVERIFY(own.object != 0);
2474 QObject *object = component.create(context);
2476 engine.collectGarbage();
2478 QCoreApplication::processEvents(QEventLoop::DeferredDeletion);
2480 QVERIFY(own.object == 0);
2485 own.object = new QObject(&own);
2488 QDeclarativeComponent component(&engine, TEST_FILE("ownership.qml"));
2490 QVERIFY(own.object != 0);
2492 QObject *object = component.create(context);
2494 engine.collectGarbage();
2496 QCoreApplication::processEvents(QEventLoop::DeferredDeletion);
2498 QVERIFY(own.object != 0);
2506 class CppOwnershipReturnValue : public QObject
2510 CppOwnershipReturnValue() : value(0) {}
2511 ~CppOwnershipReturnValue() { delete value; }
2513 Q_INVOKABLE QObject *create() {
2514 value = new QObject;
2515 QDeclarativeEngine::setObjectOwnership(value, QDeclarativeEngine::CppOwnership);
2519 Q_INVOKABLE MyQmlObject *createQmlObject() {
2520 MyQmlObject *rv = new MyQmlObject;
2525 QPointer<QObject> value;
2529 // Test setObjectOwnership(CppOwnership) works even when there is no QDeclarativeData
2530 void tst_qdeclarativeecmascript::cppOwnershipReturnValue()
2532 CppOwnershipReturnValue source;
2535 QDeclarativeEngine engine;
2536 engine.rootContext()->setContextProperty("source", &source);
2538 QVERIFY(source.value == 0);
2540 QDeclarativeComponent component(&engine);
2541 component.setData("import QtQuick 1.0\nQtObject {\nComponent.onCompleted: { var a = source.create(); }\n}\n", QUrl());
2543 QObject *object = component.create();
2545 QVERIFY(object != 0);
2546 QVERIFY(source.value != 0);
2551 QCoreApplication::instance()->processEvents(QEventLoop::DeferredDeletion);
2553 QVERIFY(source.value != 0);
2557 void tst_qdeclarativeecmascript::ownershipCustomReturnValue()
2559 CppOwnershipReturnValue source;
2562 QDeclarativeEngine engine;
2563 engine.rootContext()->setContextProperty("source", &source);
2565 QVERIFY(source.value == 0);
2567 QDeclarativeComponent component(&engine);
2568 component.setData("import QtQuick 1.0\nQtObject {\nComponent.onCompleted: { var a = source.createQmlObject(); }\n}\n", QUrl());
2570 QObject *object = component.create();
2572 QVERIFY(object != 0);
2573 QVERIFY(source.value != 0);
2578 engine.collectGarbage();
2579 QCoreApplication::instance()->processEvents(QEventLoop::DeferredDeletion);
2581 QVERIFY(source.value == 0);
2584 class QListQObjectMethodsObject : public QObject
2588 QListQObjectMethodsObject() {
2589 m_objects.append(new MyQmlObject());
2590 m_objects.append(new MyQmlObject());
2593 ~QListQObjectMethodsObject() {
2594 qDeleteAll(m_objects);
2598 QList<QObject *> getObjects() { return m_objects; }
2601 QList<QObject *> m_objects;
2604 // Tests that returning a QList<QObject*> from a method works
2605 void tst_qdeclarativeecmascript::qlistqobjectMethods()
2607 QListQObjectMethodsObject obj;
2608 QDeclarativeContext *context = new QDeclarativeContext(engine.rootContext());
2609 context->setContextObject(&obj);
2611 QDeclarativeComponent component(&engine, TEST_FILE("qlistqobjectMethods.qml"));
2613 QObject *object = component.create(context);
2615 QCOMPARE(object->property("test").toInt(), 2);
2616 QCOMPARE(object->property("test2").toBool(), true);
2623 void tst_qdeclarativeecmascript::strictlyEquals()
2625 QDeclarativeComponent component(&engine, TEST_FILE("strictlyEquals.qml"));
2627 QObject *object = component.create();
2628 QVERIFY(object != 0);
2630 QCOMPARE(object->property("test1").toBool(), true);
2631 QCOMPARE(object->property("test2").toBool(), true);
2632 QCOMPARE(object->property("test3").toBool(), true);
2633 QCOMPARE(object->property("test4").toBool(), true);
2634 QCOMPARE(object->property("test5").toBool(), true);
2635 QCOMPARE(object->property("test6").toBool(), true);
2636 QCOMPARE(object->property("test7").toBool(), true);
2637 QCOMPARE(object->property("test8").toBool(), true);
2642 void tst_qdeclarativeecmascript::compiled()
2644 QDeclarativeComponent component(&engine, TEST_FILE("compiled.qml"));
2646 QObject *object = component.create();
2647 QVERIFY(object != 0);
2649 QCOMPARE(object->property("test1").toReal(), qreal(15.7));
2650 QCOMPARE(object->property("test2").toReal(), qreal(-6.7));
2651 QCOMPARE(object->property("test3").toBool(), true);
2652 QCOMPARE(object->property("test4").toBool(), false);
2653 QCOMPARE(object->property("test5").toBool(), false);
2654 QCOMPARE(object->property("test6").toBool(), true);
2656 QCOMPARE(object->property("test7").toInt(), 185);
2657 QCOMPARE(object->property("test8").toInt(), 167);
2658 QCOMPARE(object->property("test9").toBool(), true);
2659 QCOMPARE(object->property("test10").toBool(), false);
2660 QCOMPARE(object->property("test11").toBool(), false);
2661 QCOMPARE(object->property("test12").toBool(), true);
2663 QCOMPARE(object->property("test13").toString(), QLatin1String("HelloWorld"));
2664 QCOMPARE(object->property("test14").toString(), QLatin1String("Hello World"));
2665 QCOMPARE(object->property("test15").toBool(), false);
2666 QCOMPARE(object->property("test16").toBool(), true);
2668 QCOMPARE(object->property("test17").toInt(), 5);
2669 QCOMPARE(object->property("test18").toReal(), qreal(176));
2670 QCOMPARE(object->property("test19").toInt(), 7);
2671 QCOMPARE(object->property("test20").toReal(), qreal(6.7));
2672 QCOMPARE(object->property("test21").toString(), QLatin1String("6.7"));
2673 QCOMPARE(object->property("test22").toString(), QLatin1String("!"));
2674 QCOMPARE(object->property("test23").toBool(), true);
2675 QCOMPARE(qvariant_cast<QColor>(object->property("test24")), QColor(0x11,0x22,0x33));
2676 QCOMPARE(qvariant_cast<QColor>(object->property("test25")), QColor(0x11,0x22,0x33,0xAA));
2681 // Test that numbers assigned in bindings as strings work consistently
2682 void tst_qdeclarativeecmascript::numberAssignment()
2684 QDeclarativeComponent component(&engine, TEST_FILE("numberAssignment.qml"));
2686 QObject *object = component.create();
2687 QVERIFY(object != 0);
2689 QCOMPARE(object->property("test1"), QVariant((qreal)6.7));
2690 QCOMPARE(object->property("test2"), QVariant((qreal)6.7));
2691 QCOMPARE(object->property("test2"), QVariant((qreal)6.7));
2692 QCOMPARE(object->property("test3"), QVariant((qreal)6));
2693 QCOMPARE(object->property("test4"), QVariant((qreal)6));
2695 QCOMPARE(object->property("test5"), QVariant((int)7));
2696 QCOMPARE(object->property("test6"), QVariant((int)7));
2697 QCOMPARE(object->property("test7"), QVariant((int)6));
2698 QCOMPARE(object->property("test8"), QVariant((int)6));
2700 QCOMPARE(object->property("test9"), QVariant((unsigned int)7));
2701 QCOMPARE(object->property("test10"), QVariant((unsigned int)7));
2702 QCOMPARE(object->property("test11"), QVariant((unsigned int)6));
2703 QCOMPARE(object->property("test12"), QVariant((unsigned int)6));
2708 void tst_qdeclarativeecmascript::propertySplicing()
2710 QDeclarativeComponent component(&engine, TEST_FILE("propertySplicing.qml"));
2712 QObject *object = component.create();
2713 QVERIFY(object != 0);
2715 QCOMPARE(object->property("test").toBool(), true);
2721 void tst_qdeclarativeecmascript::signalWithUnknownTypes()
2723 QDeclarativeComponent component(&engine, TEST_FILE("signalWithUnknownTypes.qml"));
2725 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2726 QVERIFY(object != 0);
2728 MyQmlObject::MyType type;
2729 type.value = 0x8971123;
2730 emit object->signalWithUnknownType(type);
2732 MyQmlObject::MyType result = qvariant_cast<MyQmlObject::MyType>(object->variant());
2734 QCOMPARE(result.value, type.value);
2740 void tst_qdeclarativeecmascript::moduleApi_data()
2742 QTest::addColumn<QUrl>("testfile");
2743 QTest::addColumn<QString>("errorMessage");
2744 QTest::addColumn<QStringList>("warningMessages");
2745 QTest::addColumn<QStringList>("readProperties");
2746 QTest::addColumn<QVariantList>("readExpectedValues");
2747 QTest::addColumn<QStringList>("writeProperties");
2748 QTest::addColumn<QVariantList>("writeValues");
2749 QTest::addColumn<QStringList>("readBackProperties");
2750 QTest::addColumn<QVariantList>("readBackExpectedValues");
2752 QTest::newRow("qobject, register + read + method")
2753 << TEST_FILE("moduleapi/qobjectModuleApi.qml")
2756 << (QStringList() << "existingUriTest" << "qobjectTest" << "qobjectMethodTest"
2757 << "qobjectMinorVersionTest" << "qobjectMajorVersionTest" << "qobjectParentedTest")
2758 << (QVariantList() << 20 << 20 << 1 << 20 << 20 << 26)
2764 QTest::newRow("script, register + read")
2765 << TEST_FILE("moduleapi/scriptModuleApi.qml")
2768 << (QStringList() << "scriptTest")
2769 << (QVariantList() << 13)
2775 QTest::newRow("qobject, caching + read")
2776 << TEST_FILE("moduleapi/qobjectModuleApiCaching.qml")
2779 << (QStringList() << "existingUriTest" << "qobjectParentedTest")
2780 << (QVariantList() << 20 << 26) // 26, shouldn't have incremented to 27.
2786 QTest::newRow("script, caching + read")
2787 << TEST_FILE("moduleapi/scriptModuleApiCaching.qml")
2790 << (QStringList() << "scriptTest")
2791 << (QVariantList() << 13) // 13, shouldn't have incremented to 14.
2797 QTest::newRow("qobject, writing + readonly constraints")
2798 << TEST_FILE("moduleapi/qobjectModuleApiWriting.qml")
2800 << (QStringList() << QString(QLatin1String("file://") + TEST_FILE("moduleapi/qobjectModuleApiWriting.qml").toLocalFile() + QLatin1String(":14: Error: Cannot assign to read-only property \"qobjectTestProperty\"")))
2801 << (QStringList() << "readOnlyProperty" << "writableProperty")
2802 << (QVariantList() << 20 << 50)
2803 << (QStringList() << "firstProperty" << "writableProperty")
2804 << (QVariantList() << 30 << 30)
2805 << (QStringList() << "readOnlyProperty" << "writableProperty")
2806 << (QVariantList() << 20 << 30);
2808 QTest::newRow("script, writing + readonly constraints")
2809 << TEST_FILE("moduleapi/scriptModuleApiWriting.qml")
2811 << (QStringList() << QString(QLatin1String("file://") + TEST_FILE("moduleapi/scriptModuleApiWriting.qml").toLocalFile() + QLatin1String(":21: Error: Cannot assign to read-only property \"scriptTestProperty\"")))
2812 << (QStringList() << "readBack" << "unchanged")
2813 << (QVariantList() << 13 << 42)
2814 << (QStringList() << "firstProperty" << "secondProperty")
2815 << (QVariantList() << 30 << 30)
2816 << (QStringList() << "readBack" << "unchanged")
2817 << (QVariantList() << 30 << 42);
2819 QTest::newRow("qobject module API enum values in JS")
2820 << TEST_FILE("moduleapi/qobjectModuleApiEnums.qml")
2823 << (QStringList() << "enumValue" << "enumMethod")
2824 << (QVariantList() << 42 << 30)
2830 QTest::newRow("qobject, invalid major version fail")
2831 << TEST_FILE("moduleapi/moduleApiMajorVersionFail.qml")
2832 << QString("QDeclarativeComponent: Component is not ready")
2841 QTest::newRow("qobject, invalid minor version fail")
2842 << TEST_FILE("moduleapi/moduleApiMinorVersionFail.qml")
2843 << QString("QDeclarativeComponent: Component is not ready")
2853 void tst_qdeclarativeecmascript::moduleApi()
2855 QFETCH(QUrl, testfile);
2856 QFETCH(QString, errorMessage);
2857 QFETCH(QStringList, warningMessages);
2858 QFETCH(QStringList, readProperties);
2859 QFETCH(QVariantList, readExpectedValues);
2860 QFETCH(QStringList, writeProperties);
2861 QFETCH(QVariantList, writeValues);
2862 QFETCH(QStringList, readBackProperties);
2863 QFETCH(QVariantList, readBackExpectedValues);
2865 QDeclarativeComponent component(&engine, testfile);
2867 if (!errorMessage.isEmpty())
2868 QTest::ignoreMessage(QtWarningMsg, errorMessage.toAscii().constData());
2870 if (warningMessages.size())
2871 foreach (const QString &warning, warningMessages)
2872 QTest::ignoreMessage(QtWarningMsg, warning.toAscii().constData());
2874 QObject *object = component.create();
2875 if (!errorMessage.isEmpty()) {
2876 QVERIFY(object == 0);
2878 QVERIFY(object != 0);
2879 for (int i = 0; i < readProperties.size(); ++i)
2880 QCOMPARE(object->property(readProperties.at(i).toAscii().constData()), readExpectedValues.at(i));
2881 for (int i = 0; i < writeProperties.size(); ++i)
2882 QVERIFY(object->setProperty(writeProperties.at(i).toAscii().constData(), writeValues.at(i)));
2883 for (int i = 0; i < readBackProperties.size(); ++i)
2884 QCOMPARE(object->property(readBackProperties.at(i).toAscii().constData()), readBackExpectedValues.at(i));
2889 void tst_qdeclarativeecmascript::importScripts()
2891 QObject *object = 0;
2893 // first, ensure that the required behaviour works.
2894 QDeclarativeComponent component(&engine, TEST_FILE("jsimport/testImport.qml"));
2895 object = component.create();
2896 QVERIFY(object != 0);
2897 QCOMPARE(object->property("importedScriptStringValue"), QVariant(QString(QLatin1String("Hello, World!"))));
2898 QCOMPARE(object->property("importedScriptFunctionValue"), QVariant(20));
2899 QCOMPARE(object->property("importedModuleAttachedPropertyValue"), QVariant(19));
2900 QCOMPARE(object->property("importedModuleEnumValue"), QVariant(2));
2903 QDeclarativeComponent componentTwo(&engine, TEST_FILE("jsimport/testImportScoping.qml"));
2904 object = componentTwo.create();
2905 QVERIFY(object != 0);
2906 QCOMPARE(object->property("componentError"), QVariant(5));
2909 // then, ensure that unintended behaviour does not work.
2910 QDeclarativeComponent failOneComponent(&engine, TEST_FILE("jsimportfail/failOne.qml"));
2911 QString expectedWarning = QLatin1String("file://") + TEST_FILE("jsimportfail/failOne.qml").toLocalFile() + QLatin1String(":6: TypeError: Cannot call method 'greetingString' of undefined");
2912 QTest::ignoreMessage(QtWarningMsg, expectedWarning.toAscii().constData());
2913 object = failOneComponent.create();
2914 QVERIFY(object != 0);
2915 QVERIFY(object->property("importScriptFunctionValue").toString().isEmpty());
2917 QDeclarativeComponent failTwoComponent(&engine, TEST_FILE("jsimportfail/failTwo.qml"));
2918 expectedWarning = QLatin1String("file://") + TEST_FILE("jsimportfail/failTwo.qml").toLocalFile() + QLatin1String(":6: ReferenceError: Can't find variable: ImportOneJs");
2919 QTest::ignoreMessage(QtWarningMsg, expectedWarning.toAscii().constData());
2920 object = failTwoComponent.create();
2921 QVERIFY(object != 0);
2922 QVERIFY(object->property("importScriptFunctionValue").toString().isEmpty());
2924 QDeclarativeComponent failThreeComponent(&engine, TEST_FILE("jsimportfail/failThree.qml"));
2925 expectedWarning = QLatin1String("file://") + TEST_FILE("jsimportfail/failThree.qml").toLocalFile() + QLatin1String(":7: TypeError: Cannot read property 'JsQtTest' of undefined");
2926 QTest::ignoreMessage(QtWarningMsg, expectedWarning.toAscii().constData());
2927 object = failThreeComponent.create();
2928 QVERIFY(object != 0);
2929 QCOMPARE(object->property("importedModuleAttachedPropertyValue"), QVariant(false));
2931 QDeclarativeComponent failFourComponent(&engine, TEST_FILE("jsimportfail/failFour.qml"));
2932 expectedWarning = QLatin1String("file://") + TEST_FILE("jsimportfail/failFour.qml").toLocalFile() + QLatin1String(":6: ReferenceError: Can't find variable: JsQtTest");
2933 QTest::ignoreMessage(QtWarningMsg, expectedWarning.toAscii().constData());
2934 object = failFourComponent.create();
2935 QVERIFY(object != 0);
2936 QCOMPARE(object->property("importedModuleEnumValue"), QVariant(0));
2938 QDeclarativeComponent failFiveComponent(&engine, TEST_FILE("jsimportfail/failFive.qml"));
2939 expectedWarning = QLatin1String("file://") + TEST_FILE("jsimportfail/importWithImports.js").toLocalFile() + QLatin1String(":8: ReferenceError: Can't find variable: Component");
2940 QTest::ignoreMessage(QtWarningMsg, expectedWarning.toAscii().constData());
2941 expectedWarning = QLatin1String("file://") + TEST_FILE("jsimportfail/importPragmaLibrary.js").toLocalFile() + QLatin1String(":6: ReferenceError: Can't find variable: Component");
2942 QTest::ignoreMessage(QtWarningMsg, expectedWarning.toAscii().constData());
2943 object = failFiveComponent.create();
2944 QVERIFY(object != 0);
2945 QCOMPARE(object->property("componentError"), QVariant(0));
2948 // also, test that importing scripts with .pragma library works as required
2949 QDeclarativeComponent pragmaLibraryComponent(&engine, TEST_FILE("jsimport/testImportPragmaLibrary.qml"));
2950 object = pragmaLibraryComponent.create();
2951 QVERIFY(object != 0);
2952 QCOMPARE(object->property("testValue"), QVariant(31));
2955 // and that .pragma library scripts don't inherit imports from any .qml file
2956 QDeclarativeComponent pragmaLibraryComponentTwo(&engine, TEST_FILE("jsimportfail/testImportPragmaLibrary.qml"));
2957 object = pragmaLibraryComponentTwo.create();
2958 QVERIFY(object != 0);
2959 QCOMPARE(object->property("testValue"), QVariant(0));
2963 void tst_qdeclarativeecmascript::scarceResources()
2965 QPixmap origPixmap(100, 100);
2966 origPixmap.fill(Qt::blue);
2968 QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(&engine);
2969 ScarceResourceObject *eo = 0;
2970 QObject *object = 0;
2972 // in the following three cases, the instance created from the component
2973 // has a property which is a copy of the scarce resource; hence, the
2974 // resource should NOT be detached prior to deletion of the object instance,
2975 // unless the resource is destroyed explicitly.
2976 QDeclarativeComponent component(&engine, TEST_FILE("scarceresources/scarceResourceCopy.qml"));
2977 object = component.create();
2978 QVERIFY(object != 0);
2979 QVERIFY(object->property("scarceResourceCopy").isValid());
2980 QCOMPARE(object->property("scarceResourceCopy").value<QPixmap>(), origPixmap);
2981 QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
2982 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2983 QVERIFY(!eo->scarceResourceIsDetached()); // there are two copies of it in existence: the property of object, and the property of eo.
2986 QDeclarativeComponent componentTwo(&engine, TEST_FILE("scarceresources/scarceResourceCopyFromJs.qml"));
2987 object = componentTwo.create();
2988 QVERIFY(object != 0);
2989 QVERIFY(object->property("scarceResourceCopy").isValid());
2990 QCOMPARE(object->property("scarceResourceCopy").value<QPixmap>(), origPixmap);
2991 QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
2992 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2993 QVERIFY(!eo->scarceResourceIsDetached()); // there are two copies of it in existence: the property of object, and the property of eo.
2996 QDeclarativeComponent componentThree(&engine, TEST_FILE("scarceresources/scarceResourceDestroyedCopy.qml"));
2997 object = componentThree.create();
2998 QVERIFY(object != 0);
2999 QVERIFY(!(object->property("scarceResourceCopy").isValid())); // was manually released prior to being returned.
3000 QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
3001 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
3002 QVERIFY(eo->scarceResourceIsDetached()); // should have explicitly been released during the evaluation of the binding.
3005 // in the following three cases, no other copy should exist in memory,
3006 // and so it should be detached (unless explicitly preserved).
3007 QDeclarativeComponent componentFour(&engine, TEST_FILE("scarceresources/scarceResourceTest.qml"));
3008 object = componentFour.create();
3009 QVERIFY(object != 0);
3010 QVERIFY(object->property("scarceResourceTest").isValid());
3011 QCOMPARE(object->property("scarceResourceTest").toInt(), 100);
3012 QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
3013 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
3014 QVERIFY(eo->scarceResourceIsDetached()); // the resource should have been released after the binding was evaluated.
3017 QDeclarativeComponent componentFive(&engine, TEST_FILE("scarceresources/scarceResourceTestPreserve.qml"));
3018 object = componentFive.create();
3019 QVERIFY(object != 0);
3020 QVERIFY(object->property("scarceResourceTest").isValid());
3021 QCOMPARE(object->property("scarceResourceTest").toInt(), 100);
3022 QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
3023 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
3024 QVERIFY(!eo->scarceResourceIsDetached()); // this won't be detached since we explicitly preserved it.
3027 QDeclarativeComponent componentSix(&engine, TEST_FILE("scarceresources/scarceResourceTestMultiple.qml"));
3028 object = componentSix.create();
3029 QVERIFY(object != 0);
3030 QVERIFY(object->property("scarceResourceTest").isValid());
3031 QCOMPARE(object->property("scarceResourceTest").toInt(), 100);
3032 QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
3033 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
3034 QVERIFY(eo->scarceResourceIsDetached()); // all resources were released manually or automatically released.
3037 // test that scarce resources are handled correctly for imports
3038 QDeclarativeComponent componentSeven(&engine, TEST_FILE("scarceresources/scarceResourceCopyImportNoBinding.qml"));
3039 object = componentSeven.create();
3040 QVERIFY(object != 0); // the import should have caused the addition of a resource to the ScarceResources list
3041 QVERIFY(ep->scarceResources.isEmpty()); // but they should have been released by this point.
3044 QDeclarativeComponent componentEight(&engine, TEST_FILE("scarceresources/scarceResourceCopyImportFail.qml"));
3045 object = componentEight.create();
3046 QVERIFY(object != 0);
3047 QVERIFY(!object->property("scarceResourceCopy").isValid()); // wasn't preserved, so shouldn't be valid.
3048 QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
3051 QDeclarativeComponent componentNine(&engine, TEST_FILE("scarceresources/scarceResourceCopyImport.qml"));
3052 object = componentNine.create();
3053 QVERIFY(object != 0);
3054 QVERIFY(object->property("scarceResourceCopy").isValid()); // preserved, so should be valid.
3055 QCOMPARE(object->property("scarceResourceCopy").value<QPixmap>(), origPixmap);
3056 QVERIFY(object->property("scarceResourceAssignedCopyOne").isValid()); // assigned before destroy(), so should be valid.
3057 QCOMPARE(object->property("scarceResourceAssignedCopyOne").value<QPixmap>(), origPixmap);
3058 QVERIFY(!object->property("scarceResourceAssignedCopyTwo").isValid()); // assigned after destroy(), so should be invalid.
3059 QVERIFY(ep->scarceResources.isEmpty()); // this will still be zero, because "preserve()" REMOVES it from this list.
3062 // test that scarce resources are handled properly in signal invocation
3063 QDeclarativeComponent componentTen(&engine, TEST_FILE("scarceresources/scarceResourceSignal.qml"));
3064 object = componentTen.create();
3065 QVERIFY(object != 0);
3066 QObject *srsc = object->findChild<QObject*>("srsc");
3068 QVERIFY(!srsc->property("scarceResourceCopy").isValid()); // hasn't been instantiated yet.
3069 QCOMPARE(srsc->property("width"), QVariant(5)); // default value is 5.
3070 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
3071 QVERIFY(eo->scarceResourceIsDetached()); // should be no other copies of it at this stage.
3072 QMetaObject::invokeMethod(srsc, "testSignal");
3073 QVERIFY(!srsc->property("scarceResourceCopy").isValid()); // still hasn't been instantiated
3074 QCOMPARE(srsc->property("width"), QVariant(10)); // but width was assigned to 10.
3075 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
3076 QVERIFY(eo->scarceResourceIsDetached()); // should still be no other copies of it at this stage.
3077 QMetaObject::invokeMethod(srsc, "testSignal2"); // assigns scarceResourceCopy to the scarce pixmap.
3078 QVERIFY(srsc->property("scarceResourceCopy").isValid());
3079 QCOMPARE(srsc->property("scarceResourceCopy").value<QPixmap>(), origPixmap);
3080 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
3081 QVERIFY(!(eo->scarceResourceIsDetached())); // should be another copy of the resource now.
3082 QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
3085 // test that scarce resources are handled properly from js functions in qml files
3086 QDeclarativeComponent componentEleven(&engine, TEST_FILE("scarceresources/scarceResourceFunction.qml"));
3087 object = componentEleven.create();
3088 QVERIFY(object != 0);
3089 QVERIFY(!object->property("scarceResourceCopy").isValid()); // not yet assigned, so should not be valid
3090 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
3091 QVERIFY(eo->scarceResourceIsDetached()); // should be no other copies of it at this stage.
3092 QMetaObject::invokeMethod(object, "retrieveScarceResource");
3093 QVERIFY(object->property("scarceResourceCopy").isValid()); // assigned, so should be valid.
3094 QCOMPARE(object->property("scarceResourceCopy").value<QPixmap>(), origPixmap);
3095 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
3096 QVERIFY(!eo->scarceResourceIsDetached()); // should be a copy of the resource at this stage.
3097 QMetaObject::invokeMethod(object, "releaseScarceResource");
3098 QVERIFY(!object->property("scarceResourceCopy").isValid()); // just released, so should not be valid
3099 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
3100 QVERIFY(eo->scarceResourceIsDetached()); // should be no other copies of it at this stage.
3101 QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
3104 // test that if an exception occurs while invoking js function from cpp, that the resources are released.
3105 QDeclarativeComponent componentTwelve(&engine, TEST_FILE("scarceresources/scarceResourceFunctionFail.qml"));
3106 object = componentTwelve.create();
3107 QVERIFY(object != 0);
3108 QVERIFY(!object->property("scarceResourceCopy").isValid()); // not yet assigned, so should not be valid
3109 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
3110 QVERIFY(eo->scarceResourceIsDetached()); // should be no other copies of it at this stage.
3111 QString srp_name = object->property("srp_name").toString();
3112 QString expectedWarning = componentTwelve.url().toString() + QLatin1String(":17: TypeError: Property 'scarceResource' of object ") + srp_name + QLatin1String(" is not a function");
3113 QTest::ignoreMessage(QtWarningMsg, qPrintable(expectedWarning)); // we expect a meaningful warning to be printed.
3114 QMetaObject::invokeMethod(object, "retrieveScarceResource");
3115 QVERIFY(!object->property("scarceResourceCopy").isValid()); // due to exception, assignment will NOT have occurred.
3116 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
3117 QVERIFY(eo->scarceResourceIsDetached()); // should be no other copies of it at this stage.
3118 QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
3122 void tst_qdeclarativeecmascript::propertyChangeSlots()
3124 // ensure that allowable property names are allowed and onPropertyNameChanged slots are generated correctly.
3125 QDeclarativeComponent component(&engine, TEST_FILE("changeslots/propertyChangeSlots.qml"));
3126 QObject *object = component.create();
3127 QVERIFY(object != 0);
3130 // ensure that invalid property names fail properly.
3131 QTest::ignoreMessage(QtWarningMsg, "QDeclarativeComponent: Component is not ready");
3132 QDeclarativeComponent e1(&engine, TEST_FILE("changeslots/propertyChangeSlotErrors.1.qml"));
3133 QString expectedErrorString = e1.url().toString() + QLatin1String(":9:5: Cannot assign to non-existent property \"on_nameWithUnderscoreChanged\"");
3134 QCOMPARE(e1.errors().at(0).toString(), expectedErrorString);
3135 object = e1.create();
3136 QVERIFY(object == 0);
3139 QTest::ignoreMessage(QtWarningMsg, "QDeclarativeComponent: Component is not ready");
3140 QDeclarativeComponent e2(&engine, TEST_FILE("changeslots/propertyChangeSlotErrors.2.qml"));
3141 expectedErrorString = e2.url().toString() + QLatin1String(":9:5: Cannot assign to non-existent property \"on____nameWithUnderscoresChanged\"");
3142 QCOMPARE(e2.errors().at(0).toString(), expectedErrorString);
3143 object = e2.create();
3144 QVERIFY(object == 0);
3147 QTest::ignoreMessage(QtWarningMsg, "QDeclarativeComponent: Component is not ready");
3148 QDeclarativeComponent e3(&engine, TEST_FILE("changeslots/propertyChangeSlotErrors.3.qml"));
3149 expectedErrorString = e3.url().toString() + QLatin1String(":9:5: Cannot assign to non-existent property \"on$NameWithDollarsignChanged\"");
3150 QCOMPARE(e3.errors().at(0).toString(), expectedErrorString);
3151 object = e3.create();
3152 QVERIFY(object == 0);
3155 QTest::ignoreMessage(QtWarningMsg, "QDeclarativeComponent: Component is not ready");
3156 QDeclarativeComponent e4(&engine, TEST_FILE("changeslots/propertyChangeSlotErrors.4.qml"));
3157 expectedErrorString = e4.url().toString() + QLatin1String(":9:5: Cannot assign to non-existent property \"on_6NameWithUnderscoreNumberChanged\"");
3158 QCOMPARE(e4.errors().at(0).toString(), expectedErrorString);
3159 object = e4.create();
3160 QVERIFY(object == 0);
3164 // Ensure that QObject type conversion works on binding assignment
3165 void tst_qdeclarativeecmascript::elementAssign()
3167 QDeclarativeComponent component(&engine, TEST_FILE("elementAssign.qml"));
3169 QObject *object = component.create();
3170 QVERIFY(object != 0);
3172 QCOMPARE(object->property("test").toBool(), true);
3178 void tst_qdeclarativeecmascript::objectPassThroughSignals()
3180 QDeclarativeComponent component(&engine, TEST_FILE("objectsPassThroughSignals.qml"));
3182 QObject *object = component.create();
3183 QVERIFY(object != 0);
3185 QCOMPARE(object->property("test").toBool(), true);
3191 void tst_qdeclarativeecmascript::booleanConversion()
3193 QDeclarativeComponent component(&engine, TEST_FILE("booleanConversion.qml"));
3195 QObject *object = component.create();
3196 QVERIFY(object != 0);
3198 QCOMPARE(object->property("test_true1").toBool(), true);
3199 QCOMPARE(object->property("test_true2").toBool(), true);
3200 QCOMPARE(object->property("test_true3").toBool(), true);
3201 QCOMPARE(object->property("test_true4").toBool(), true);
3202 QCOMPARE(object->property("test_true5").toBool(), true);
3204 QCOMPARE(object->property("test_false1").toBool(), false);
3205 QCOMPARE(object->property("test_false2").toBool(), false);
3206 QCOMPARE(object->property("test_false3").toBool(), false);
3211 // Test that assigning a null object works
3212 // Regressed with: df1788b4dbbb2826ae63f26bdf166342595343f4
3213 void tst_qdeclarativeecmascript::nullObjectBinding()
3215 QDeclarativeComponent component(&engine, TEST_FILE("nullObjectBinding.qml"));
3217 QObject *object = component.create();
3218 QVERIFY(object != 0);
3220 QVERIFY(object->property("test") == QVariant::fromValue((QObject *)0));
3225 // Test that bindings don't evaluate once the engine has been destroyed
3226 void tst_qdeclarativeecmascript::deletedEngine()
3228 QDeclarativeEngine *engine = new QDeclarativeEngine;
3229 QDeclarativeComponent component(engine, TEST_FILE("deletedEngine.qml"));
3231 QObject *object = component.create();
3232 QVERIFY(object != 0);
3234 QCOMPARE(object->property("a").toInt(), 39);
3235 object->setProperty("b", QVariant(9));
3236 QCOMPARE(object->property("a").toInt(), 117);
3240 QCOMPARE(object->property("a").toInt(), 117);
3241 object->setProperty("b", QVariant(10));
3242 QCOMPARE(object->property("a").toInt(), 117);
3247 // Test the crashing part of QTBUG-9705
3248 void tst_qdeclarativeecmascript::libraryScriptAssert()
3250 QDeclarativeComponent component(&engine, TEST_FILE("libraryScriptAssert.qml"));
3252 QObject *object = component.create();
3253 QVERIFY(object != 0);
3258 void tst_qdeclarativeecmascript::variantsAssignedUndefined()
3260 QDeclarativeComponent component(&engine, TEST_FILE("variantsAssignedUndefined.qml"));
3262 QObject *object = component.create();
3263 QVERIFY(object != 0);
3265 QCOMPARE(object->property("test1").toInt(), 10);
3266 QCOMPARE(object->property("test2").toInt(), 11);
3268 object->setProperty("runTest", true);
3270 QCOMPARE(object->property("test1"), QVariant());
3271 QCOMPARE(object->property("test2"), QVariant());
3277 void tst_qdeclarativeecmascript::qtbug_9792()
3279 QDeclarativeComponent component(&engine, TEST_FILE("qtbug_9792.qml"));
3281 QDeclarativeContext *context = new QDeclarativeContext(engine.rootContext());
3283 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create(context));
3284 QVERIFY(object != 0);
3286 QTest::ignoreMessage(QtDebugMsg, "Hello world!");
3287 object->basicSignal();
3291 transientErrorsMsgCount = 0;
3292 QtMsgHandler old = qInstallMsgHandler(transientErrorsMsgHandler);
3294 object->basicSignal();
3296 qInstallMsgHandler(old);
3298 QCOMPARE(transientErrorsMsgCount, 0);
3303 // Verifies that QDeclarativeGuard<>s used in the vmemetaobject are cleaned correctly
3304 void tst_qdeclarativeecmascript::qtcreatorbug_1289()
3306 QDeclarativeComponent component(&engine, TEST_FILE("qtcreatorbug_1289.qml"));
3308 QObject *o = component.create();
3311 QObject *nested = qvariant_cast<QObject *>(o->property("object"));
3312 QVERIFY(nested != 0);
3314 QVERIFY(qvariant_cast<QObject *>(nested->property("nestedObject")) == o);
3317 nested = qvariant_cast<QObject *>(o->property("object"));
3318 QVERIFY(nested == 0);
3320 // If the bug is present, the next line will crash
3324 // Test that we shut down without stupid warnings
3325 void tst_qdeclarativeecmascript::noSpuriousWarningsAtShutdown()
3328 QDeclarativeComponent component(&engine, TEST_FILE("noSpuriousWarningsAtShutdown.qml"));
3330 QObject *o = component.create();
3332 transientErrorsMsgCount = 0;
3333 QtMsgHandler old = qInstallMsgHandler(transientErrorsMsgHandler);
3337 qInstallMsgHandler(old);
3339 QCOMPARE(transientErrorsMsgCount, 0);
3344 QDeclarativeComponent component(&engine, TEST_FILE("noSpuriousWarningsAtShutdown.2.qml"));
3346 QObject *o = component.create();
3348 transientErrorsMsgCount = 0;
3349 QtMsgHandler old = qInstallMsgHandler(transientErrorsMsgHandler);
3353 qInstallMsgHandler(old);
3355 QCOMPARE(transientErrorsMsgCount, 0);
3359 void tst_qdeclarativeecmascript::canAssignNullToQObject()
3362 QDeclarativeComponent component(&engine, TEST_FILE("canAssignNullToQObject.1.qml"));
3364 MyQmlObject *o = qobject_cast<MyQmlObject *>(component.create());
3367 QVERIFY(o->objectProperty() != 0);
3369 o->setProperty("runTest", true);
3371 QVERIFY(o->objectProperty() == 0);
3377 QDeclarativeComponent component(&engine, TEST_FILE("canAssignNullToQObject.2.qml"));
3379 MyQmlObject *o = qobject_cast<MyQmlObject *>(component.create());
3382 QVERIFY(o->objectProperty() == 0);
3388 void tst_qdeclarativeecmascript::functionAssignment_fromBinding()
3390 QDeclarativeComponent component(&engine, TEST_FILE("functionAssignment.1.qml"));
3392 QString url = component.url().toString();
3393 QString warning = url + ":4: Unable to assign a function to a property.";
3394 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
3396 MyQmlObject *o = qobject_cast<MyQmlObject *>(component.create());
3399 QVERIFY(!o->property("a").isValid());
3404 void tst_qdeclarativeecmascript::functionAssignment_fromJS()
3406 QFETCH(QString, triggerProperty);
3408 QDeclarativeComponent component(&engine, TEST_FILE("functionAssignment.2.qml"));
3409 QVERIFY2(component.errorString().isEmpty(), qPrintable(component.errorString()));
3411 MyQmlObject *o = qobject_cast<MyQmlObject *>(component.create());
3413 QVERIFY(!o->property("a").isValid());
3415 o->setProperty("aNumber", QVariant(5));
3416 o->setProperty(triggerProperty.toUtf8().constData(), true);
3417 QCOMPARE(o->property("a"), QVariant(50));
3419 o->setProperty("aNumber", QVariant(10));
3420 QCOMPARE(o->property("a"), QVariant(100));
3425 void tst_qdeclarativeecmascript::functionAssignment_fromJS_data()
3427 QTest::addColumn<QString>("triggerProperty");
3429 QTest::newRow("assign to property") << "assignToProperty";
3430 QTest::newRow("assign to property, from JS file") << "assignToPropertyFromJsFile";
3432 QTest::newRow("assign to value type") << "assignToValueType";
3434 QTest::newRow("use 'this'") << "assignWithThis";
3435 QTest::newRow("use 'this' from JS file") << "assignWithThisFromJsFile";
3438 void tst_qdeclarativeecmascript::functionAssignmentfromJS_invalid()
3440 QDeclarativeComponent component(&engine, TEST_FILE("functionAssignment.2.qml"));
3441 QVERIFY2(component.errorString().isEmpty(), qPrintable(component.errorString()));
3443 MyQmlObject *o = qobject_cast<MyQmlObject *>(component.create());
3445 QVERIFY(!o->property("a").isValid());
3447 o->setProperty("assignFuncWithoutReturn", true);
3448 QVERIFY(!o->property("a").isValid());
3450 QString url = component.url().toString();
3451 QString warning = url + ":67: Unable to assign QString to int";
3452 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
3453 o->setProperty("assignWrongType", true);
3455 warning = url + ":71: Unable to assign QString to int";
3456 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
3457 o->setProperty("assignWrongTypeToValueType", true);
3462 void tst_qdeclarativeecmascript::eval()
3464 QDeclarativeComponent component(&engine, TEST_FILE("eval.qml"));
3466 QObject *o = component.create();
3469 QCOMPARE(o->property("test1").toBool(), true);
3470 QCOMPARE(o->property("test2").toBool(), true);
3471 QCOMPARE(o->property("test3").toBool(), true);
3472 QCOMPARE(o->property("test4").toBool(), true);
3473 QCOMPARE(o->property("test5").toBool(), true);
3478 void tst_qdeclarativeecmascript::function()
3480 QDeclarativeComponent component(&engine, TEST_FILE("function.qml"));
3482 QObject *o = component.create();
3485 QCOMPARE(o->property("test1").toBool(), true);
3486 QCOMPARE(o->property("test2").toBool(), true);
3487 QCOMPARE(o->property("test3").toBool(), true);
3492 // Test the "Qt.include" method
3493 void tst_qdeclarativeecmascript::include()
3495 // Non-library relative include
3497 QDeclarativeComponent component(&engine, TEST_FILE("include.qml"));
3498 QObject *o = component.create();
3501 QCOMPARE(o->property("test0").toInt(), 99);
3502 QCOMPARE(o->property("test1").toBool(), true);
3503 QCOMPARE(o->property("test2").toBool(), true);
3504 QCOMPARE(o->property("test2_1").toBool(), true);
3505 QCOMPARE(o->property("test3").toBool(), true);
3506 QCOMPARE(o->property("test3_1").toBool(), true);
3511 // Library relative include
3513 QDeclarativeComponent component(&engine, TEST_FILE("include_shared.qml"));
3514 QObject *o = component.create();
3517 QCOMPARE(o->property("test0").toInt(), 99);
3518 QCOMPARE(o->property("test1").toBool(), true);
3519 QCOMPARE(o->property("test2").toBool(), true);
3520 QCOMPARE(o->property("test2_1").toBool(), true);
3521 QCOMPARE(o->property("test3").toBool(), true);
3522 QCOMPARE(o->property("test3_1").toBool(), true);
3529 QDeclarativeComponent component(&engine, TEST_FILE("include_callback.qml"));
3530 QObject *o = component.create();
3533 QCOMPARE(o->property("test1").toBool(), true);
3534 QCOMPARE(o->property("test2").toBool(), true);
3535 QCOMPARE(o->property("test3").toBool(), true);
3536 QCOMPARE(o->property("test4").toBool(), true);
3537 QCOMPARE(o->property("test5").toBool(), true);
3538 QCOMPARE(o->property("test6").toBool(), true);
3543 // Including file with ".pragma library"
3545 QDeclarativeComponent component(&engine, TEST_FILE("include_pragma.qml"));
3546 QObject *o = component.create();
3548 QCOMPARE(o->property("test1").toInt(), 100);
3555 TestHTTPServer server(8111);
3556 QVERIFY(server.isValid());
3557 server.serveDirectory(SRCDIR "/data");
3559 QDeclarativeComponent component(&engine, TEST_FILE("include_remote.qml"));
3560 QObject *o = component.create();
3563 QTRY_VERIFY(o->property("done").toBool() == true);
3564 QTRY_VERIFY(o->property("done2").toBool() == true);
3566 QCOMPARE(o->property("test1").toBool(), true);
3567 QCOMPARE(o->property("test2").toBool(), true);
3568 QCOMPARE(o->property("test3").toBool(), true);
3569 QCOMPARE(o->property("test4").toBool(), true);
3570 QCOMPARE(o->property("test5").toBool(), true);
3572 QCOMPARE(o->property("test6").toBool(), true);
3573 QCOMPARE(o->property("test7").toBool(), true);
3574 QCOMPARE(o->property("test8").toBool(), true);
3575 QCOMPARE(o->property("test9").toBool(), true);
3576 QCOMPARE(o->property("test10").toBool(), true);
3583 TestHTTPServer server(8111);
3584 QVERIFY(server.isValid());
3585 server.serveDirectory(SRCDIR "/data");
3587 QDeclarativeComponent component(&engine, TEST_FILE("include_remote_missing.qml"));
3588 QObject *o = component.create();
3591 QTRY_VERIFY(o->property("done").toBool() == true);
3593 QCOMPARE(o->property("test1").toBool(), true);
3594 QCOMPARE(o->property("test2").toBool(), true);
3595 QCOMPARE(o->property("test3").toBool(), true);
3601 void tst_qdeclarativeecmascript::signalHandlers()
3603 QDeclarativeComponent component(&engine, TEST_FILE("signalHandlers.qml"));
3604 QObject *o = component.create();
3607 QVERIFY(o->property("count").toInt() == 0);
3608 QMetaObject::invokeMethod(o, "testSignalCall");
3609 QCOMPARE(o->property("count").toInt(), 1);
3611 QMetaObject::invokeMethod(o, "testSignalHandlerCall");
3612 QCOMPARE(o->property("count").toInt(), 1);
3613 QCOMPARE(o->property("errorString").toString(), QLatin1String("TypeError: Property 'onTestSignal' of object [object Object] is not a function"));
3615 QVERIFY(o->property("funcCount").toInt() == 0);
3616 QMetaObject::invokeMethod(o, "testSignalConnection");
3617 QCOMPARE(o->property("funcCount").toInt(), 1);
3619 QMetaObject::invokeMethod(o, "testSignalHandlerConnection");
3620 QCOMPARE(o->property("funcCount").toInt(), 2);
3622 QMetaObject::invokeMethod(o, "testSignalDefined");
3623 QCOMPARE(o->property("definedResult").toBool(), true);
3625 QMetaObject::invokeMethod(o, "testSignalHandlerDefined");
3626 QCOMPARE(o->property("definedHandlerResult").toBool(), true);
3631 void tst_qdeclarativeecmascript::qtbug_10696()
3633 QDeclarativeComponent component(&engine, TEST_FILE("qtbug_10696.qml"));
3634 QObject *o = component.create();
3639 void tst_qdeclarativeecmascript::qtbug_11606()
3641 QDeclarativeComponent component(&engine, TEST_FILE("qtbug_11606.qml"));
3642 QObject *o = component.create();
3644 QCOMPARE(o->property("test").toBool(), true);
3648 void tst_qdeclarativeecmascript::qtbug_11600()
3650 QDeclarativeComponent component(&engine, TEST_FILE("qtbug_11600.qml"));
3651 QObject *o = component.create();
3653 QCOMPARE(o->property("test").toBool(), true);
3657 // Reading and writing non-scriptable properties should fail
3658 void tst_qdeclarativeecmascript::nonscriptable()
3660 QDeclarativeComponent component(&engine, TEST_FILE("nonscriptable.qml"));
3661 QObject *o = component.create();
3663 QCOMPARE(o->property("readOk").toBool(), true);
3664 QCOMPARE(o->property("writeOk").toBool(), true);
3668 // deleteLater() should not be callable from QML
3669 void tst_qdeclarativeecmascript::deleteLater()
3671 QDeclarativeComponent component(&engine, TEST_FILE("deleteLater.qml"));
3672 QObject *o = component.create();
3674 QCOMPARE(o->property("test").toBool(), true);
3678 void tst_qdeclarativeecmascript::in()
3680 QDeclarativeComponent component(&engine, TEST_FILE("in.qml"));
3681 QObject *o = component.create();
3683 QCOMPARE(o->property("test1").toBool(), true);
3684 QCOMPARE(o->property("test2").toBool(), true);
3688 void tst_qdeclarativeecmascript::sharedAttachedObject()
3690 QDeclarativeComponent component(&engine, TEST_FILE("sharedAttachedObject.qml"));
3691 QObject *o = component.create();
3693 QCOMPARE(o->property("test1").toBool(), true);
3694 QCOMPARE(o->property("test2").toBool(), true);
3699 void tst_qdeclarativeecmascript::objectName()
3701 QDeclarativeComponent component(&engine, TEST_FILE("objectName.qml"));
3702 QObject *o = component.create();
3705 QCOMPARE(o->property("test1").toString(), QString("hello"));
3706 QCOMPARE(o->property("test2").toString(), QString("ell"));
3708 o->setObjectName("world");
3710 QCOMPARE(o->property("test1").toString(), QString("world"));
3711 QCOMPARE(o->property("test2").toString(), QString("orl"));
3716 void tst_qdeclarativeecmascript::writeRemovesBinding()
3718 QDeclarativeComponent component(&engine, TEST_FILE("writeRemovesBinding.qml"));
3719 QObject *o = component.create();
3722 QCOMPARE(o->property("test").toBool(), true);
3727 // Test bindings assigned to alias properties actually assign to the alias' target
3728 void tst_qdeclarativeecmascript::aliasBindingsAssignCorrectly()
3730 QDeclarativeComponent component(&engine, TEST_FILE("aliasBindingsAssignCorrectly.qml"));
3731 QObject *o = component.create();
3734 QCOMPARE(o->property("test").toBool(), true);
3739 // Test bindings assigned to alias properties override a binding on the target (QTBUG-13719)
3740 void tst_qdeclarativeecmascript::aliasBindingsOverrideTarget()
3743 QDeclarativeComponent component(&engine, TEST_FILE("aliasBindingsOverrideTarget.qml"));
3744 QObject *o = component.create();
3747 QCOMPARE(o->property("test").toBool(), true);
3753 QDeclarativeComponent component(&engine, TEST_FILE("aliasBindingsOverrideTarget.2.qml"));
3754 QObject *o = component.create();
3757 QCOMPARE(o->property("test").toBool(), true);
3763 QDeclarativeComponent component(&engine, TEST_FILE("aliasBindingsOverrideTarget.3.qml"));
3764 QObject *o = component.create();
3767 QCOMPARE(o->property("test").toBool(), true);
3773 // Test that writes to alias properties override bindings on the alias target (QTBUG-13719)
3774 void tst_qdeclarativeecmascript::aliasWritesOverrideBindings()
3777 QDeclarativeComponent component(&engine, TEST_FILE("aliasWritesOverrideBindings.qml"));
3778 QObject *o = component.create();
3781 QCOMPARE(o->property("test").toBool(), true);
3787 QDeclarativeComponent component(&engine, TEST_FILE("aliasWritesOverrideBindings.2.qml"));
3788 QObject *o = component.create();
3791 QCOMPARE(o->property("test").toBool(), true);
3797 QDeclarativeComponent component(&engine, TEST_FILE("aliasWritesOverrideBindings.3.qml"));
3798 QObject *o = component.create();
3801 QCOMPARE(o->property("test").toBool(), true);
3807 // Allow an alais to a composite element
3809 void tst_qdeclarativeecmascript::aliasToCompositeElement()
3811 QDeclarativeComponent component(&engine, TEST_FILE("aliasToCompositeElement.qml"));
3813 QObject *object = component.create();
3814 QVERIFY(object != 0);
3819 void tst_qdeclarativeecmascript::revisionErrors()
3822 QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevisionErrors.qml"));
3823 QString url = component.url().toString();
3825 QString warning1 = url + ":8: ReferenceError: Can't find variable: prop2";
3826 QString warning2 = url + ":11: ReferenceError: Can't find variable: prop2";
3827 QString warning3 = url + ":13: ReferenceError: Can't find variable: method2";
3829 QTest::ignoreMessage(QtWarningMsg, warning1.toLatin1().constData());
3830 QTest::ignoreMessage(QtWarningMsg, warning2.toLatin1().constData());
3831 QTest::ignoreMessage(QtWarningMsg, warning3.toLatin1().constData());
3832 MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create());
3833 QVERIFY(object != 0);
3837 QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevisionErrors2.qml"));
3838 QString url = component.url().toString();
3840 // MyRevisionedSubclass 1.0 uses MyRevisionedClass revision 0
3841 // method2, prop2 from MyRevisionedClass not available
3842 // method4, prop4 from MyRevisionedSubclass not available
3843 QString warning1 = url + ":8: ReferenceError: Can't find variable: prop2";
3844 QString warning2 = url + ":14: ReferenceError: Can't find variable: prop2";
3845 QString warning3 = url + ":10: ReferenceError: Can't find variable: prop4";
3846 QString warning4 = url + ":16: ReferenceError: Can't find variable: prop4";
3847 QString warning5 = url + ":20: ReferenceError: Can't find variable: method2";
3849 QTest::ignoreMessage(QtWarningMsg, warning1.toLatin1().constData());
3850 QTest::ignoreMessage(QtWarningMsg, warning2.toLatin1().constData());
3851 QTest::ignoreMessage(QtWarningMsg, warning3.toLatin1().constData());
3852 QTest::ignoreMessage(QtWarningMsg, warning4.toLatin1().constData());
3853 QTest::ignoreMessage(QtWarningMsg, warning5.toLatin1().constData());
3854 MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create());
3855 QVERIFY(object != 0);
3859 QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevisionErrors3.qml"));
3860 QString url = component.url().toString();
3862 // MyRevisionedSubclass 1.1 uses MyRevisionedClass revision 1
3863 // All properties/methods available, except MyRevisionedBaseClassUnregistered rev 1
3864 QString warning1 = url + ":30: ReferenceError: Can't find variable: methodD";
3865 QString warning2 = url + ":10: ReferenceError: Can't find variable: propD";
3866 QString warning3 = url + ":20: ReferenceError: Can't find variable: propD";
3867 QTest::ignoreMessage(QtWarningMsg, warning1.toLatin1().constData());
3868 QTest::ignoreMessage(QtWarningMsg, warning2.toLatin1().constData());
3869 QTest::ignoreMessage(QtWarningMsg, warning3.toLatin1().constData());
3870 MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create());
3871 QVERIFY(object != 0);
3876 void tst_qdeclarativeecmascript::revision()
3879 QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevision.qml"));
3880 QString url = component.url().toString();
3882 MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create());
3883 QVERIFY(object != 0);
3887 QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevision2.qml"));
3888 QString url = component.url().toString();
3890 MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create());
3891 QVERIFY(object != 0);
3895 QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevision3.qml"));
3896 QString url = component.url().toString();
3898 MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create());
3899 QVERIFY(object != 0);
3902 // Test that non-root classes can resolve revisioned methods
3904 QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevision4.qml"));
3906 QObject *object = component.create();
3907 QVERIFY(object != 0);
3908 QCOMPARE(object->property("test").toReal(), 11.);
3913 void tst_qdeclarativeecmascript::realToInt()
3915 QDeclarativeComponent component(&engine, TEST_FILE("realToInt.qml"));
3916 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
3917 QVERIFY(object != 0);
3919 QMetaObject::invokeMethod(object, "test1");
3920 QCOMPARE(object->value(), int(4));
3921 QMetaObject::invokeMethod(object, "test2");
3922 QCOMPARE(object->value(), int(8));
3924 void tst_qdeclarativeecmascript::dynamicString()
3926 QDeclarativeComponent component(&engine, TEST_FILE("dynamicString.qml"));
3927 QObject *object = component.create();
3928 QVERIFY(object != 0);
3929 QCOMPARE(object->property("stringProperty").toString(),
3930 QString::fromLatin1("string:Hello World false:0 true:1 uint32:100 int32:-100 double:3.14159 date:2011-02-11 05::30:50!"));
3933 QTEST_MAIN(tst_qdeclarativeecmascript)
3935 #include "tst_qdeclarativeecmascript.moc"