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 nonExistentAttachedObject();
110 void signalParameterTypes();
111 void objectsCompareAsEqual();
112 void dynamicCreation_data();
113 void dynamicCreation();
114 void dynamicDestruction();
115 void objectToString();
116 void objectHasOwnProperty();
117 void selfDeletingBinding();
118 void extendedObjectPropertyLookup();
120 void functionErrors();
121 void propertyAssignmentErrors();
122 void signalTriggeredBindings();
123 void listProperties();
124 void exceptionClearsOnReeval();
125 void exceptionSlotProducesWarning();
126 void exceptionBindingProducesWarning();
127 void transientErrors();
128 void shutdownErrors();
129 void compositePropertyType();
131 void undefinedResetsProperty();
132 void listToVariant();
133 void multiEngineObject();
134 void deletedObject();
135 void attachedPropertyScope();
136 void scriptConnect();
137 void scriptDisconnect();
139 void cppOwnershipReturnValue();
140 void ownershipCustomReturnValue();
141 void qlistqobjectMethods();
142 void strictlyEquals();
144 void numberAssignment();
145 void propertySplicing();
146 void signalWithUnknownTypes();
148 void importScripts();
149 void scarceResources();
150 void propertyChangeSlots();
151 void elementAssign();
152 void objectPassThroughSignals();
153 void booleanConversion();
157 void dynamicCreationCrash();
159 void nullObjectBinding();
160 void deletedEngine();
161 void libraryScriptAssert();
162 void variantsAssignedUndefined();
164 void qtcreatorbug_1289();
165 void noSpuriousWarningsAtShutdown();
166 void canAssignNullToQObject();
167 void functionAssignment_fromBinding();
168 void functionAssignment_fromJS();
169 void functionAssignment_fromJS_data();
170 void functionAssignmentfromJS_invalid();
176 void nonscriptable();
179 void sharedAttachedObject();
181 void writeRemovesBinding();
182 void aliasBindingsAssignCorrectly();
183 void aliasBindingsOverrideTarget();
184 void aliasWritesOverrideBindings();
185 void aliasToCompositeElement();
187 void dynamicString();
190 void callQtInvokables();
191 void invokableObjectArg();
192 void invokableObjectRet();
194 void revisionErrors();
198 QDeclarativeEngine engine;
201 void tst_qdeclarativeecmascript::initTestCase() { registerTypes(); }
203 void tst_qdeclarativeecmascript::assignBasicTypes()
206 QDeclarativeComponent component(&engine, TEST_FILE("assignBasicTypes.qml"));
207 MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
208 QVERIFY(object != 0);
209 QCOMPARE(object->flagProperty(), MyTypeObject::FlagVal1 | MyTypeObject::FlagVal3);
210 QCOMPARE(object->enumProperty(), MyTypeObject::EnumVal2);
211 QCOMPARE(object->stringProperty(), QString("Hello World!"));
212 QCOMPARE(object->uintProperty(), uint(10));
213 QCOMPARE(object->intProperty(), -19);
214 QCOMPARE((float)object->realProperty(), float(23.2));
215 QCOMPARE((float)object->doubleProperty(), float(-19.75));
216 QCOMPARE((float)object->floatProperty(), float(8.5));
217 QCOMPARE(object->colorProperty(), QColor("red"));
218 QCOMPARE(object->dateProperty(), QDate(1982, 11, 25));
219 QCOMPARE(object->timeProperty(), QTime(11, 11, 32));
220 QCOMPARE(object->dateTimeProperty(), QDateTime(QDate(2009, 5, 12), QTime(13, 22, 1)));
221 QCOMPARE(object->pointProperty(), QPoint(99,13));
222 QCOMPARE(object->pointFProperty(), QPointF(-10.1, 12.3));
223 QCOMPARE(object->sizeProperty(), QSize(99, 13));
224 QCOMPARE(object->sizeFProperty(), QSizeF(0.1, 0.2));
225 QCOMPARE(object->rectProperty(), QRect(9, 7, 100, 200));
226 QCOMPARE(object->rectFProperty(), QRectF(1000.1, -10.9, 400, 90.99));
227 QCOMPARE(object->boolProperty(), true);
228 QCOMPARE(object->variantProperty(), QVariant("Hello World!"));
229 QCOMPARE(object->vectorProperty(), QVector3D(10, 1, 2.2));
230 QCOMPARE(object->urlProperty(), component.url().resolved(QUrl("main.qml")));
234 QDeclarativeComponent component(&engine, TEST_FILE("assignBasicTypes.2.qml"));
235 MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
236 QVERIFY(object != 0);
237 QCOMPARE(object->flagProperty(), MyTypeObject::FlagVal1 | MyTypeObject::FlagVal3);
238 QCOMPARE(object->enumProperty(), MyTypeObject::EnumVal2);
239 QCOMPARE(object->stringProperty(), QString("Hello World!"));
240 QCOMPARE(object->uintProperty(), uint(10));
241 QCOMPARE(object->intProperty(), -19);
242 QCOMPARE((float)object->realProperty(), float(23.2));
243 QCOMPARE((float)object->doubleProperty(), float(-19.75));
244 QCOMPARE((float)object->floatProperty(), float(8.5));
245 QCOMPARE(object->colorProperty(), QColor("red"));
246 QCOMPARE(object->dateProperty(), QDate(1982, 11, 25));
247 QCOMPARE(object->timeProperty(), QTime(11, 11, 32));
248 QCOMPARE(object->dateTimeProperty(), QDateTime(QDate(2009, 5, 12), QTime(13, 22, 1)));
249 QCOMPARE(object->pointProperty(), QPoint(99,13));
250 QCOMPARE(object->pointFProperty(), QPointF(-10.1, 12.3));
251 QCOMPARE(object->sizeProperty(), QSize(99, 13));
252 QCOMPARE(object->sizeFProperty(), QSizeF(0.1, 0.2));
253 QCOMPARE(object->rectProperty(), QRect(9, 7, 100, 200));
254 QCOMPARE(object->rectFProperty(), QRectF(1000.1, -10.9, 400, 90.99));
255 QCOMPARE(object->boolProperty(), true);
256 QCOMPARE(object->variantProperty(), QVariant("Hello World!"));
257 QCOMPARE(object->vectorProperty(), QVector3D(10, 1, 2.2));
258 QCOMPARE(object->urlProperty(), component.url().resolved(QUrl("main.qml")));
263 void tst_qdeclarativeecmascript::idShortcutInvalidates()
266 QDeclarativeComponent component(&engine, TEST_FILE("idShortcutInvalidates.qml"));
267 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
268 QVERIFY(object != 0);
269 QVERIFY(object->objectProperty() != 0);
270 delete object->objectProperty();
271 QVERIFY(object->objectProperty() == 0);
276 QDeclarativeComponent component(&engine, TEST_FILE("idShortcutInvalidates.1.qml"));
277 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
278 QVERIFY(object != 0);
279 QVERIFY(object->objectProperty() != 0);
280 delete object->objectProperty();
281 QVERIFY(object->objectProperty() == 0);
286 void tst_qdeclarativeecmascript::boolPropertiesEvaluateAsBool()
289 QDeclarativeComponent component(&engine, TEST_FILE("boolPropertiesEvaluateAsBool.1.qml"));
290 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
291 QVERIFY(object != 0);
292 QCOMPARE(object->stringProperty(), QLatin1String("pass"));
296 QDeclarativeComponent component(&engine, TEST_FILE("boolPropertiesEvaluateAsBool.2.qml"));
297 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
298 QVERIFY(object != 0);
299 QCOMPARE(object->stringProperty(), QLatin1String("pass"));
304 void tst_qdeclarativeecmascript::signalAssignment()
307 QDeclarativeComponent component(&engine, TEST_FILE("signalAssignment.1.qml"));
308 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
309 QVERIFY(object != 0);
310 QCOMPARE(object->string(), QString());
311 emit object->basicSignal();
312 QCOMPARE(object->string(), QString("pass"));
317 QDeclarativeComponent component(&engine, TEST_FILE("signalAssignment.2.qml"));
318 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
319 QVERIFY(object != 0);
320 QCOMPARE(object->string(), QString());
321 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
322 QCOMPARE(object->string(), QString("pass 19 Hello world! 10.25 3 2"));
327 void tst_qdeclarativeecmascript::methods()
330 QDeclarativeComponent component(&engine, TEST_FILE("methods.1.qml"));
331 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
332 QVERIFY(object != 0);
333 QCOMPARE(object->methodCalled(), false);
334 QCOMPARE(object->methodIntCalled(), false);
335 emit object->basicSignal();
336 QCOMPARE(object->methodCalled(), true);
337 QCOMPARE(object->methodIntCalled(), false);
342 QDeclarativeComponent component(&engine, TEST_FILE("methods.2.qml"));
343 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
344 QVERIFY(object != 0);
345 QCOMPARE(object->methodCalled(), false);
346 QCOMPARE(object->methodIntCalled(), false);
347 emit object->basicSignal();
348 QCOMPARE(object->methodCalled(), false);
349 QCOMPARE(object->methodIntCalled(), true);
354 QDeclarativeComponent component(&engine, TEST_FILE("methods.3.qml"));
355 QObject *object = component.create();
356 QVERIFY(object != 0);
357 QCOMPARE(object->property("test").toInt(), 19);
362 QDeclarativeComponent component(&engine, TEST_FILE("methods.4.qml"));
363 QObject *object = component.create();
364 QVERIFY(object != 0);
365 QCOMPARE(object->property("test").toInt(), 19);
366 QCOMPARE(object->property("test2").toInt(), 17);
367 QCOMPARE(object->property("test3").toInt(), 16);
372 QDeclarativeComponent component(&engine, TEST_FILE("methods.5.qml"));
373 QObject *object = component.create();
374 QVERIFY(object != 0);
375 QCOMPARE(object->property("test").toInt(), 9);
380 void tst_qdeclarativeecmascript::bindingLoop()
382 QDeclarativeComponent component(&engine, TEST_FILE("bindingLoop.qml"));
383 QString warning = component.url().toString() + ":9:9: QML MyQmlObject: Binding loop detected for property \"stringProperty\"";
384 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
385 QObject *object = component.create();
386 QVERIFY(object != 0);
390 void tst_qdeclarativeecmascript::basicExpressions_data()
392 QTest::addColumn<QString>("expression");
393 QTest::addColumn<QVariant>("result");
394 QTest::addColumn<bool>("nest");
396 QTest::newRow("Syntax error (self test)") << "{console.log({'a':1'}.a)}" << QVariant() << false;
397 QTest::newRow("Context property") << "a" << QVariant(1944) << false;
398 QTest::newRow("Context property") << "a" << QVariant(1944) << true;
399 QTest::newRow("Context property expression") << "a * 2" << QVariant(3888) << false;
400 QTest::newRow("Context property expression") << "a * 2" << QVariant(3888) << true;
401 QTest::newRow("Overridden context property") << "b" << QVariant("Milk") << false;
402 QTest::newRow("Overridden context property") << "b" << QVariant("Cow") << true;
403 QTest::newRow("Object property") << "object.stringProperty" << QVariant("Object1") << false;
404 QTest::newRow("Object property") << "object.stringProperty" << QVariant("Object1") << true;
405 QTest::newRow("Overridden object property") << "objectOverride.stringProperty" << QVariant("Object2") << false;
406 QTest::newRow("Overridden object property") << "objectOverride.stringProperty" << QVariant("Object3") << true;
407 QTest::newRow("Default object property") << "horseLegs" << QVariant(4) << false;
408 QTest::newRow("Default object property") << "antLegs" << QVariant(6) << false;
409 QTest::newRow("Default object property") << "emuLegs" << QVariant(2) << false;
410 QTest::newRow("Nested default object property") << "horseLegs" << QVariant(4) << true;
411 QTest::newRow("Nested default object property") << "antLegs" << QVariant(7) << true;
412 QTest::newRow("Nested default object property") << "emuLegs" << QVariant(2) << true;
413 QTest::newRow("Nested default object property") << "humanLegs" << QVariant(2) << true;
414 QTest::newRow("Context property override default object property") << "millipedeLegs" << QVariant(100) << true;
417 void tst_qdeclarativeecmascript::basicExpressions()
419 QFETCH(QString, expression);
420 QFETCH(QVariant, result);
426 MyDefaultObject1 default1;
427 MyDefaultObject3 default3;
428 object1.setStringProperty("Object1");
429 object2.setStringProperty("Object2");
430 object3.setStringProperty("Object3");
432 QDeclarativeContext context(engine.rootContext());
433 QDeclarativeContext nestedContext(&context);
435 context.setContextObject(&default1);
436 context.setContextProperty("a", QVariant(1944));
437 context.setContextProperty("b", QVariant("Milk"));
438 context.setContextProperty("object", &object1);
439 context.setContextProperty("objectOverride", &object2);
440 nestedContext.setContextObject(&default3);
441 nestedContext.setContextProperty("b", QVariant("Cow"));
442 nestedContext.setContextProperty("objectOverride", &object3);
443 nestedContext.setContextProperty("millipedeLegs", QVariant(100));
445 MyExpression expr(nest?&nestedContext:&context, expression);
446 QCOMPARE(expr.evaluate(), result);
449 void tst_qdeclarativeecmascript::arrayExpressions()
455 QDeclarativeContext context(engine.rootContext());
456 context.setContextProperty("a", &obj1);
457 context.setContextProperty("b", &obj2);
458 context.setContextProperty("c", &obj3);
460 MyExpression expr(&context, "[a, b, c, 10]");
461 QVariant result = expr.evaluate();
462 QCOMPARE(result.userType(), qMetaTypeId<QList<QObject *> >());
463 QList<QObject *> list = qvariant_cast<QList<QObject *> >(result);
464 QCOMPARE(list.count(), 4);
465 QCOMPARE(list.at(0), &obj1);
466 QCOMPARE(list.at(1), &obj2);
467 QCOMPARE(list.at(2), &obj3);
468 QCOMPARE(list.at(3), (QObject *)0);
471 // Tests that modifying a context property will reevaluate expressions
472 void tst_qdeclarativeecmascript::contextPropertiesTriggerReeval()
474 QDeclarativeContext context(engine.rootContext());
477 MyQmlObject *object3 = new MyQmlObject;
479 object1.setStringProperty("Hello");
480 object2.setStringProperty("World");
482 context.setContextProperty("testProp", QVariant(1));
483 context.setContextProperty("testObj", &object1);
484 context.setContextProperty("testObj2", object3);
487 MyExpression expr(&context, "testProp + 1");
488 QCOMPARE(expr.changed, false);
489 QCOMPARE(expr.evaluate(), QVariant(2));
491 context.setContextProperty("testProp", QVariant(2));
492 QCOMPARE(expr.changed, true);
493 QCOMPARE(expr.evaluate(), QVariant(3));
497 MyExpression expr(&context, "testProp + testProp + testProp");
498 QCOMPARE(expr.changed, false);
499 QCOMPARE(expr.evaluate(), QVariant(6));
501 context.setContextProperty("testProp", QVariant(4));
502 QCOMPARE(expr.changed, true);
503 QCOMPARE(expr.evaluate(), QVariant(12));
507 MyExpression expr(&context, "testObj.stringProperty");
508 QCOMPARE(expr.changed, false);
509 QCOMPARE(expr.evaluate(), QVariant("Hello"));
511 context.setContextProperty("testObj", &object2);
512 QCOMPARE(expr.changed, true);
513 QCOMPARE(expr.evaluate(), QVariant("World"));
517 MyExpression expr(&context, "testObj.stringProperty /**/");
518 QCOMPARE(expr.changed, false);
519 QCOMPARE(expr.evaluate(), QVariant("World"));
521 context.setContextProperty("testObj", &object1);
522 QCOMPARE(expr.changed, true);
523 QCOMPARE(expr.evaluate(), QVariant("Hello"));
527 MyExpression expr(&context, "testObj2");
528 QCOMPARE(expr.changed, false);
529 QCOMPARE(expr.evaluate(), QVariant::fromValue((QObject *)object3));
535 void tst_qdeclarativeecmascript::objectPropertiesTriggerReeval()
537 QDeclarativeContext context(engine.rootContext());
541 context.setContextProperty("testObj", &object1);
543 object1.setStringProperty(QLatin1String("Hello"));
544 object2.setStringProperty(QLatin1String("Dog"));
545 object3.setStringProperty(QLatin1String("Cat"));
548 MyExpression expr(&context, "testObj.stringProperty");
549 QCOMPARE(expr.changed, false);
550 QCOMPARE(expr.evaluate(), QVariant("Hello"));
552 object1.setStringProperty(QLatin1String("World"));
553 QCOMPARE(expr.changed, true);
554 QCOMPARE(expr.evaluate(), QVariant("World"));
558 MyExpression expr(&context, "testObj.objectProperty.stringProperty");
559 QCOMPARE(expr.changed, false);
560 QCOMPARE(expr.evaluate(), QVariant());
562 object1.setObjectProperty(&object2);
563 QCOMPARE(expr.changed, true);
564 expr.changed = false;
565 QCOMPARE(expr.evaluate(), QVariant("Dog"));
567 object1.setObjectProperty(&object3);
568 QCOMPARE(expr.changed, true);
569 expr.changed = false;
570 QCOMPARE(expr.evaluate(), QVariant("Cat"));
572 object1.setObjectProperty(0);
573 QCOMPARE(expr.changed, true);
574 expr.changed = false;
575 QCOMPARE(expr.evaluate(), QVariant());
577 object1.setObjectProperty(&object3);
578 QCOMPARE(expr.changed, true);
579 expr.changed = false;
580 QCOMPARE(expr.evaluate(), QVariant("Cat"));
582 object3.setStringProperty("Donkey");
583 QCOMPARE(expr.changed, true);
584 expr.changed = false;
585 QCOMPARE(expr.evaluate(), QVariant("Donkey"));
589 void tst_qdeclarativeecmascript::deferredProperties()
591 QDeclarativeComponent component(&engine, TEST_FILE("deferredProperties.qml"));
592 MyDeferredObject *object =
593 qobject_cast<MyDeferredObject *>(component.create());
594 QVERIFY(object != 0);
595 QCOMPARE(object->value(), 0);
596 QVERIFY(object->objectProperty() == 0);
597 QVERIFY(object->objectProperty2() != 0);
598 qmlExecuteDeferred(object);
599 QCOMPARE(object->value(), 10);
600 QVERIFY(object->objectProperty() != 0);
601 MyQmlObject *qmlObject =
602 qobject_cast<MyQmlObject *>(object->objectProperty());
603 QVERIFY(qmlObject != 0);
604 QCOMPARE(qmlObject->value(), 10);
605 object->setValue(19);
606 QCOMPARE(qmlObject->value(), 19);
611 // Check errors on deferred properties are correctly emitted
612 void tst_qdeclarativeecmascript::deferredPropertiesErrors()
614 QDeclarativeComponent component(&engine, TEST_FILE("deferredPropertiesErrors.qml"));
615 MyDeferredObject *object =
616 qobject_cast<MyDeferredObject *>(component.create());
617 QVERIFY(object != 0);
618 QCOMPARE(object->value(), 0);
619 QVERIFY(object->objectProperty() == 0);
620 QVERIFY(object->objectProperty2() == 0);
622 QString warning = component.url().toString() + ":6: Unable to assign [undefined] to QObject* objectProperty";
623 QTest::ignoreMessage(QtWarningMsg, qPrintable(warning));
625 qmlExecuteDeferred(object);
630 void tst_qdeclarativeecmascript::extensionObjects()
632 QDeclarativeComponent component(&engine, TEST_FILE("extensionObjects.qml"));
633 MyExtendedObject *object =
634 qobject_cast<MyExtendedObject *>(component.create());
635 QVERIFY(object != 0);
636 QCOMPARE(object->baseProperty(), 13);
637 QCOMPARE(object->coreProperty(), 9);
638 object->setProperty("extendedProperty", QVariant(11));
639 object->setProperty("baseExtendedProperty", QVariant(92));
640 QCOMPARE(object->coreProperty(), 11);
641 QCOMPARE(object->baseProperty(), 92);
643 MyExtendedObject *nested = qobject_cast<MyExtendedObject*>(qvariant_cast<QObject *>(object->property("nested")));
645 QCOMPARE(nested->baseProperty(), 13);
646 QCOMPARE(nested->coreProperty(), 9);
647 nested->setProperty("extendedProperty", QVariant(11));
648 nested->setProperty("baseExtendedProperty", QVariant(92));
649 QCOMPARE(nested->coreProperty(), 11);
650 QCOMPARE(nested->baseProperty(), 92);
655 void tst_qdeclarativeecmascript::overrideExtensionProperties()
657 QDeclarativeComponent component(&engine, TEST_FILE("extensionObjectsPropertyOverride.qml"));
658 OverrideDefaultPropertyObject *object =
659 qobject_cast<OverrideDefaultPropertyObject *>(component.create());
660 QVERIFY(object != 0);
661 QVERIFY(object->secondProperty() != 0);
662 QVERIFY(object->firstProperty() == 0);
667 void tst_qdeclarativeecmascript::attachedProperties()
670 QDeclarativeComponent component(&engine, TEST_FILE("attachedProperty.qml"));
671 QObject *object = component.create();
672 QVERIFY(object != 0);
673 QCOMPARE(object->property("a").toInt(), 19);
674 QCOMPARE(object->property("b").toInt(), 19);
675 QCOMPARE(object->property("c").toInt(), 19);
676 QCOMPARE(object->property("d").toInt(), 19);
681 QDeclarativeComponent component(&engine, TEST_FILE("attachedProperty.2.qml"));
682 QObject *object = component.create();
683 QVERIFY(object != 0);
684 QCOMPARE(object->property("a").toInt(), 26);
685 QCOMPARE(object->property("b").toInt(), 26);
686 QCOMPARE(object->property("c").toInt(), 26);
687 QCOMPARE(object->property("d").toInt(), 26);
691 QDeclarativeComponent component(&engine, TEST_FILE("writeAttachedProperty.qml"));
692 QObject *object = component.create();
693 QVERIFY(object != 0);
695 QMetaObject::invokeMethod(object, "writeValue2");
697 MyQmlAttachedObject *attached =
698 qobject_cast<MyQmlAttachedObject *>(qmlAttachedPropertiesObject<MyQmlObject>(object));
699 QVERIFY(attached != 0);
701 QCOMPARE(attached->value2(), 9);
706 void tst_qdeclarativeecmascript::enums()
710 QDeclarativeComponent component(&engine, TEST_FILE("enums.1.qml"));
711 QObject *object = component.create();
712 QVERIFY(object != 0);
714 QCOMPARE(object->property("a").toInt(), 0);
715 QCOMPARE(object->property("b").toInt(), 1);
716 QCOMPARE(object->property("c").toInt(), 2);
717 QCOMPARE(object->property("d").toInt(), 3);
718 QCOMPARE(object->property("e").toInt(), 0);
719 QCOMPARE(object->property("f").toInt(), 1);
720 QCOMPARE(object->property("g").toInt(), 2);
721 QCOMPARE(object->property("h").toInt(), 3);
722 QCOMPARE(object->property("i").toInt(), 19);
723 QCOMPARE(object->property("j").toInt(), 19);
727 // Non-existent enums
729 QDeclarativeComponent component(&engine, TEST_FILE("enums.2.qml"));
731 QString warning1 = component.url().toString() + ":5: Unable to assign [undefined] to int a";
732 QString warning2 = component.url().toString() + ":6: Unable to assign [undefined] to int b";
733 QTest::ignoreMessage(QtWarningMsg, qPrintable(warning1));
734 QTest::ignoreMessage(QtWarningMsg, qPrintable(warning2));
736 QObject *object = component.create();
737 QVERIFY(object != 0);
738 QCOMPARE(object->property("a").toInt(), 0);
739 QCOMPARE(object->property("b").toInt(), 0);
745 void tst_qdeclarativeecmascript::valueTypeFunctions()
747 QDeclarativeComponent component(&engine, TEST_FILE("valueTypeFunctions.qml"));
748 MyTypeObject *obj = qobject_cast<MyTypeObject*>(component.create());
750 QCOMPARE(obj->rectProperty(), QRect(0,0,100,100));
751 QCOMPARE(obj->rectFProperty(), QRectF(0,0.5,100,99.5));
757 Tests that writing a constant to a property with a binding on it disables the
760 void tst_qdeclarativeecmascript::constantsOverrideBindings()
764 QDeclarativeComponent component(&engine, TEST_FILE("constantsOverrideBindings.1.qml"));
765 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
766 QVERIFY(object != 0);
768 QCOMPARE(object->property("c2").toInt(), 0);
769 object->setProperty("c1", QVariant(9));
770 QCOMPARE(object->property("c2").toInt(), 9);
772 emit object->basicSignal();
774 QCOMPARE(object->property("c2").toInt(), 13);
775 object->setProperty("c1", QVariant(8));
776 QCOMPARE(object->property("c2").toInt(), 13);
781 // During construction
783 QDeclarativeComponent component(&engine, TEST_FILE("constantsOverrideBindings.2.qml"));
784 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
785 QVERIFY(object != 0);
787 QCOMPARE(object->property("c1").toInt(), 0);
788 QCOMPARE(object->property("c2").toInt(), 10);
789 object->setProperty("c1", QVariant(9));
790 QCOMPARE(object->property("c1").toInt(), 9);
791 QCOMPARE(object->property("c2").toInt(), 10);
799 QDeclarativeComponent component(&engine, TEST_FILE("constantsOverrideBindings.3.qml"));
800 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
801 QVERIFY(object != 0);
803 QCOMPARE(object->property("c2").toInt(), 0);
804 object->setProperty("c1", QVariant(9));
805 QCOMPARE(object->property("c2").toInt(), 9);
807 object->setProperty("c2", QVariant(13));
808 QCOMPARE(object->property("c2").toInt(), 13);
809 object->setProperty("c1", QVariant(7));
810 QCOMPARE(object->property("c1").toInt(), 7);
811 QCOMPARE(object->property("c2").toInt(), 13);
819 QDeclarativeComponent component(&engine, TEST_FILE("constantsOverrideBindings.4.qml"));
820 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
821 QVERIFY(object != 0);
823 QCOMPARE(object->property("c1").toInt(), 0);
824 QCOMPARE(object->property("c3").toInt(), 10);
825 object->setProperty("c1", QVariant(9));
826 QCOMPARE(object->property("c1").toInt(), 9);
827 QCOMPARE(object->property("c3").toInt(), 10);
834 Tests that assigning a binding to a property that already has a binding causes
835 the original binding to be disabled.
837 void tst_qdeclarativeecmascript::outerBindingOverridesInnerBinding()
839 QDeclarativeComponent component(&engine,
840 TEST_FILE("outerBindingOverridesInnerBinding.qml"));
841 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
842 QVERIFY(object != 0);
844 QCOMPARE(object->property("c1").toInt(), 0);
845 QCOMPARE(object->property("c2").toInt(), 0);
846 QCOMPARE(object->property("c3").toInt(), 0);
848 object->setProperty("c1", QVariant(9));
849 QCOMPARE(object->property("c1").toInt(), 9);
850 QCOMPARE(object->property("c2").toInt(), 0);
851 QCOMPARE(object->property("c3").toInt(), 0);
853 object->setProperty("c3", QVariant(8));
854 QCOMPARE(object->property("c1").toInt(), 9);
855 QCOMPARE(object->property("c2").toInt(), 8);
856 QCOMPARE(object->property("c3").toInt(), 8);
862 Access a non-existent attached object.
864 Tests for a regression where this used to crash.
866 void tst_qdeclarativeecmascript::nonExistentAttachedObject()
868 QDeclarativeComponent component(&engine, TEST_FILE("nonExistentAttachedObject.qml"));
870 QString warning = component.url().toString() + ":4: Unable to assign [undefined] to QString stringProperty";
871 QTest::ignoreMessage(QtWarningMsg, qPrintable(warning));
873 QObject *object = component.create();
874 QVERIFY(object != 0);
879 void tst_qdeclarativeecmascript::scope()
882 QDeclarativeComponent component(&engine, TEST_FILE("scope.qml"));
883 QObject *object = component.create();
884 QVERIFY(object != 0);
886 QCOMPARE(object->property("test1").toInt(), 1);
887 QCOMPARE(object->property("test2").toInt(), 2);
888 QCOMPARE(object->property("test3").toString(), QString("1Test"));
889 QCOMPARE(object->property("test4").toString(), QString("2Test"));
890 QCOMPARE(object->property("test5").toInt(), 1);
891 QCOMPARE(object->property("test6").toInt(), 1);
892 QCOMPARE(object->property("test7").toInt(), 2);
893 QCOMPARE(object->property("test8").toInt(), 2);
894 QCOMPARE(object->property("test9").toInt(), 1);
895 QCOMPARE(object->property("test10").toInt(), 3);
901 QDeclarativeComponent component(&engine, TEST_FILE("scope.2.qml"));
902 QObject *object = component.create();
903 QVERIFY(object != 0);
905 QCOMPARE(object->property("test1").toInt(), 19);
906 QCOMPARE(object->property("test2").toInt(), 19);
907 QCOMPARE(object->property("test3").toInt(), 14);
908 QCOMPARE(object->property("test4").toInt(), 14);
909 QCOMPARE(object->property("test5").toInt(), 24);
910 QCOMPARE(object->property("test6").toInt(), 24);
916 QDeclarativeComponent component(&engine, TEST_FILE("scope.3.qml"));
917 QObject *object = component.create();
918 QVERIFY(object != 0);
920 QCOMPARE(object->property("test1").toBool(), true);
921 QCOMPARE(object->property("test2").toBool(), true);
922 QCOMPARE(object->property("test3").toBool(), true);
927 // Signal argument scope
929 QDeclarativeComponent component(&engine, TEST_FILE("scope.4.qml"));
930 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
931 QVERIFY(object != 0);
933 QCOMPARE(object->property("test").toInt(), 0);
934 QCOMPARE(object->property("test2").toString(), QString());
936 emit object->argumentSignal(13, "Argument Scope", 9, MyQmlObject::EnumValue4, Qt::RightButton);
938 QCOMPARE(object->property("test").toInt(), 13);
939 QCOMPARE(object->property("test2").toString(), QString("Argument Scope"));
945 QDeclarativeComponent component(&engine, TEST_FILE("scope.5.qml"));
946 QObject *object = component.create();
947 QVERIFY(object != 0);
949 QCOMPARE(object->property("test1").toBool(), true);
950 QCOMPARE(object->property("test2").toBool(), true);
956 QDeclarativeComponent component(&engine, TEST_FILE("scope.6.qml"));
957 QObject *object = component.create();
958 QVERIFY(object != 0);
960 QCOMPARE(object->property("test").toBool(), true);
966 // In 4.7, non-library javascript files that had no imports shared the imports of their
968 void tst_qdeclarativeecmascript::importScope()
970 QDeclarativeComponent component(&engine, TEST_FILE("importScope.qml"));
971 QObject *o = component.create();
974 QCOMPARE(o->property("test").toInt(), 240);
980 Tests that "any" type passes through a synthesized signal parameter. This
981 is essentially a test of QDeclarativeMetaType::copy()
983 void tst_qdeclarativeecmascript::signalParameterTypes()
985 QDeclarativeComponent component(&engine, TEST_FILE("signalParameterTypes.qml"));
986 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
987 QVERIFY(object != 0);
989 emit object->basicSignal();
991 QCOMPARE(object->property("intProperty").toInt(), 10);
992 QCOMPARE(object->property("realProperty").toReal(), 19.2);
993 QVERIFY(object->property("colorProperty").value<QColor>() == QColor(255, 255, 0, 255));
994 QVERIFY(object->property("variantProperty") == QVariant::fromValue(QColor(255, 0, 255, 255)));
995 QVERIFY(object->property("enumProperty") == MyQmlObject::EnumValue3);
996 QVERIFY(object->property("qtEnumProperty") == Qt::LeftButton);
1002 Test that two JS objects for the same QObject compare as equal.
1004 void tst_qdeclarativeecmascript::objectsCompareAsEqual()
1006 QDeclarativeComponent component(&engine, TEST_FILE("objectsCompareAsEqual.qml"));
1007 QObject *object = component.create();
1008 QVERIFY(object != 0);
1010 QCOMPARE(object->property("test1").toBool(), true);
1011 QCOMPARE(object->property("test2").toBool(), true);
1012 QCOMPARE(object->property("test3").toBool(), true);
1013 QCOMPARE(object->property("test4").toBool(), true);
1014 QCOMPARE(object->property("test5").toBool(), true);
1020 Confirm bindings and alias properties can coexist.
1022 Tests for a regression where the binding would not reevaluate.
1024 void tst_qdeclarativeecmascript::aliasPropertyAndBinding()
1026 QDeclarativeComponent component(&engine, TEST_FILE("aliasPropertyAndBinding.qml"));
1027 QObject *object = component.create();
1028 QVERIFY(object != 0);
1030 QCOMPARE(object->property("c2").toInt(), 3);
1031 QCOMPARE(object->property("c3").toInt(), 3);
1033 object->setProperty("c2", QVariant(19));
1035 QCOMPARE(object->property("c2").toInt(), 19);
1036 QCOMPARE(object->property("c3").toInt(), 19);
1041 void tst_qdeclarativeecmascript::dynamicCreation_data()
1043 QTest::addColumn<QString>("method");
1044 QTest::addColumn<QString>("createdName");
1046 QTest::newRow("One") << "createOne" << "objectOne";
1047 QTest::newRow("Two") << "createTwo" << "objectTwo";
1048 QTest::newRow("Three") << "createThree" << "objectThree";
1052 Test using createQmlObject to dynamically generate an item
1053 Also using createComponent is tested.
1055 void tst_qdeclarativeecmascript::dynamicCreation()
1057 QFETCH(QString, method);
1058 QFETCH(QString, createdName);
1060 QDeclarativeComponent component(&engine, TEST_FILE("dynamicCreation.qml"));
1061 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1062 QVERIFY(object != 0);
1064 QMetaObject::invokeMethod(object, method.toUtf8());
1065 QObject *created = object->objectProperty();
1067 QCOMPARE(created->objectName(), createdName);
1073 Tests the destroy function
1075 void tst_qdeclarativeecmascript::dynamicDestruction()
1078 QDeclarativeComponent component(&engine, TEST_FILE("dynamicDeletion.qml"));
1079 QDeclarativeGuard<MyQmlObject> object = qobject_cast<MyQmlObject*>(component.create());
1080 QVERIFY(object != 0);
1081 QDeclarativeGuard<QObject> createdQmlObject = 0;
1083 QMetaObject::invokeMethod(object, "create");
1084 createdQmlObject = object->objectProperty();
1085 QVERIFY(createdQmlObject);
1086 QCOMPARE(createdQmlObject->objectName(), QString("emptyObject"));
1088 QMetaObject::invokeMethod(object, "killOther");
1089 QVERIFY(createdQmlObject);
1090 QCoreApplication::instance()->processEvents(QEventLoop::DeferredDeletion);
1091 QVERIFY(createdQmlObject);
1092 for (int ii = 0; createdQmlObject && ii < 50; ++ii) { // After 5 seconds we should give up
1093 if (createdQmlObject) {
1095 QCoreApplication::instance()->processEvents(QEventLoop::DeferredDeletion);
1098 QVERIFY(!createdQmlObject);
1100 QDeclarativeEngine::setObjectOwnership(object, QDeclarativeEngine::JavaScriptOwnership);
1101 QMetaObject::invokeMethod(object, "killMe");
1104 QCoreApplication::instance()->processEvents(QEventLoop::DeferredDeletion);
1109 QDeclarativeComponent component(&engine, TEST_FILE("dynamicDeletion.2.qml"));
1110 QObject *o = component.create();
1113 QVERIFY(qvariant_cast<QObject*>(o->property("objectProperty")) == 0);
1115 QMetaObject::invokeMethod(o, "create");
1117 QVERIFY(qvariant_cast<QObject*>(o->property("objectProperty")) != 0);
1119 QMetaObject::invokeMethod(o, "destroy");
1121 QCoreApplication::instance()->processEvents(QEventLoop::DeferredDeletion);
1123 QVERIFY(qvariant_cast<QObject*>(o->property("objectProperty")) == 0);
1130 tests that id.toString() works
1132 void tst_qdeclarativeecmascript::objectToString()
1134 QDeclarativeComponent component(&engine, TEST_FILE("declarativeToString.qml"));
1135 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1136 QVERIFY(object != 0);
1137 QMetaObject::invokeMethod(object, "testToString");
1138 QVERIFY(object->stringProperty().startsWith("MyQmlObject_QML_"));
1139 QVERIFY(object->stringProperty().endsWith(", \"objName\")"));
1145 tests that id.hasOwnProperty() works
1147 void tst_qdeclarativeecmascript::objectHasOwnProperty()
1149 QUrl url = TEST_FILE("declarativeHasOwnProperty.qml");
1150 QString warning1 = url.toString() + ":59: TypeError: Cannot call method 'hasOwnProperty' of undefined";
1151 QString warning2 = url.toString() + ":64: TypeError: Cannot call method 'hasOwnProperty' of undefined";
1152 QString warning3 = url.toString() + ":69: TypeError: Cannot call method 'hasOwnProperty' of undefined";
1154 QDeclarativeComponent component(&engine, url);
1155 QObject *object = component.create();
1156 QVERIFY(object != 0);
1158 // test QObjects in QML
1159 QMetaObject::invokeMethod(object, "testHasOwnPropertySuccess");
1160 QVERIFY(object->property("result").value<bool>() == true);
1161 QMetaObject::invokeMethod(object, "testHasOwnPropertyFailure");
1162 QVERIFY(object->property("result").value<bool>() == false);
1164 // now test other types in QML
1165 QObject *child = object->findChild<QObject*>("typeObj");
1166 QVERIFY(child != 0);
1167 QMetaObject::invokeMethod(child, "testHasOwnPropertySuccess");
1168 QCOMPARE(child->property("valueTypeHasOwnProperty").toBool(), true);
1169 QCOMPARE(child->property("valueTypeHasOwnProperty2").toBool(), true);
1170 QCOMPARE(child->property("variantTypeHasOwnProperty").toBool(), true);
1171 QCOMPARE(child->property("stringTypeHasOwnProperty").toBool(), true);
1172 QCOMPARE(child->property("listTypeHasOwnProperty").toBool(), true);
1173 QCOMPARE(child->property("emptyListTypeHasOwnProperty").toBool(), true);
1174 QCOMPARE(child->property("enumTypeHasOwnProperty").toBool(), true);
1175 QCOMPARE(child->property("typenameHasOwnProperty").toBool(), true);
1176 QCOMPARE(child->property("typenameHasOwnProperty2").toBool(), true);
1177 QCOMPARE(child->property("moduleApiTypeHasOwnProperty").toBool(), true);
1178 QCOMPARE(child->property("moduleApiPropertyTypeHasOwnProperty").toBool(), true);
1180 QTest::ignoreMessage(QtWarningMsg, warning1.toLatin1().constData());
1181 QMetaObject::invokeMethod(child, "testHasOwnPropertyFailureOne");
1182 QCOMPARE(child->property("enumNonValueHasOwnProperty").toBool(), false);
1183 QTest::ignoreMessage(QtWarningMsg, warning2.toLatin1().constData());
1184 QMetaObject::invokeMethod(child, "testHasOwnPropertyFailureTwo");
1185 QCOMPARE(child->property("moduleApiNonPropertyHasOwnProperty").toBool(), false);
1186 QTest::ignoreMessage(QtWarningMsg, warning3.toLatin1().constData());
1187 QMetaObject::invokeMethod(child, "testHasOwnPropertyFailureThree");
1188 QCOMPARE(child->property("listAtInvalidHasOwnProperty").toBool(), false);
1194 Tests bindings that indirectly cause their own deletion work.
1196 This test is best run under valgrind to ensure no invalid memory access occur.
1198 void tst_qdeclarativeecmascript::selfDeletingBinding()
1201 QDeclarativeComponent component(&engine, TEST_FILE("selfDeletingBinding.qml"));
1202 QObject *object = component.create();
1203 QVERIFY(object != 0);
1204 object->setProperty("triggerDelete", true);
1209 QDeclarativeComponent component(&engine, TEST_FILE("selfDeletingBinding.2.qml"));
1210 QObject *object = component.create();
1211 QVERIFY(object != 0);
1212 object->setProperty("triggerDelete", true);
1218 Test that extended object properties can be accessed.
1220 This test a regression where this used to crash. The issue was specificially
1221 for extended objects that did not include a synthesized meta object (so non-root
1222 and no synthesiszed properties).
1224 void tst_qdeclarativeecmascript::extendedObjectPropertyLookup()
1226 QDeclarativeComponent component(&engine, TEST_FILE("extendedObjectPropertyLookup.qml"));
1227 QObject *object = component.create();
1228 QVERIFY(object != 0);
1233 Test file/lineNumbers for binding/Script errors.
1235 void tst_qdeclarativeecmascript::scriptErrors()
1237 QDeclarativeComponent component(&engine, TEST_FILE("scriptErrors.qml"));
1238 QString url = component.url().toString();
1240 QString warning1 = url.left(url.length() - 3) + "js:2: Error: Invalid write to global property \"a\"";
1241 QString warning2 = url + ":5: ReferenceError: Can't find variable: a";
1242 QString warning3 = url.left(url.length() - 3) + "js:4: Error: Invalid write to global property \"a\"";
1243 QString warning4 = url + ":10: ReferenceError: Can't find variable: a";
1244 QString warning5 = url + ":8: ReferenceError: Can't find variable: a";
1245 QString warning6 = url + ":7: Unable to assign [undefined] to int x";
1246 QString warning7 = url + ":12: Error: Cannot assign to read-only property \"trueProperty\"";
1247 QString warning8 = url + ":13: Error: Cannot assign to non-existent property \"fakeProperty\"";
1249 QTest::ignoreMessage(QtWarningMsg, warning1.toLatin1().constData());
1250 QTest::ignoreMessage(QtWarningMsg, warning2.toLatin1().constData());
1251 QTest::ignoreMessage(QtWarningMsg, warning3.toLatin1().constData());
1252 QTest::ignoreMessage(QtWarningMsg, warning5.toLatin1().constData());
1253 QTest::ignoreMessage(QtWarningMsg, warning6.toLatin1().constData());
1254 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
1255 QVERIFY(object != 0);
1257 QTest::ignoreMessage(QtWarningMsg, warning4.toLatin1().constData());
1258 emit object->basicSignal();
1260 QTest::ignoreMessage(QtWarningMsg, warning7.toLatin1().constData());
1261 emit object->anotherBasicSignal();
1263 QTest::ignoreMessage(QtWarningMsg, warning8.toLatin1().constData());
1264 emit object->thirdBasicSignal();
1270 Test file/lineNumbers for inline functions.
1272 void tst_qdeclarativeecmascript::functionErrors()
1274 QDeclarativeComponent component(&engine, TEST_FILE("functionErrors.qml"));
1275 QString url = component.url().toString();
1277 QString warning = url + ":5: Error: Invalid write to global property \"a\"";
1279 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
1281 QObject *object = component.create();
1282 QVERIFY(object != 0);
1285 // test that if an exception occurs while invoking js function from cpp, it is reported as expected.
1286 QDeclarativeComponent componentTwo(&engine, TEST_FILE("scarceresources/scarceResourceFunctionFail.qml"));
1287 url = componentTwo.url().toString();
1288 object = componentTwo.create();
1289 QVERIFY(object != 0);
1291 QString srpname = object->property("srp_name").toString();
1293 warning = url + QLatin1String(":17: TypeError: Property 'scarceResource' of object ") + srpname +
1294 QLatin1String(" is not a function");
1295 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData()); // we expect a meaningful warning to be printed.
1296 QMetaObject::invokeMethod(object, "retrieveScarceResource");
1301 Test various errors that can occur when assigning a property from script
1303 void tst_qdeclarativeecmascript::propertyAssignmentErrors()
1305 QDeclarativeComponent component(&engine, TEST_FILE("propertyAssignmentErrors.qml"));
1307 QString url = component.url().toString();
1309 QObject *object = component.create();
1310 QVERIFY(object != 0);
1312 QCOMPARE(object->property("test1").toBool(), true);
1313 QCOMPARE(object->property("test2").toBool(), true);
1319 Test bindings still work when the reeval is triggered from within
1322 void tst_qdeclarativeecmascript::signalTriggeredBindings()
1324 QDeclarativeComponent component(&engine, TEST_FILE("signalTriggeredBindings.qml"));
1325 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1326 QVERIFY(object != 0);
1328 QCOMPARE(object->property("base").toReal(), 50.);
1329 QCOMPARE(object->property("test1").toReal(), 50.);
1330 QCOMPARE(object->property("test2").toReal(), 50.);
1332 object->basicSignal();
1334 QCOMPARE(object->property("base").toReal(), 200.);
1335 QCOMPARE(object->property("test1").toReal(), 200.);
1336 QCOMPARE(object->property("test2").toReal(), 200.);
1338 object->argumentSignal(10, QString(), 10, MyQmlObject::EnumValue4, Qt::RightButton);
1340 QCOMPARE(object->property("base").toReal(), 400.);
1341 QCOMPARE(object->property("test1").toReal(), 400.);
1342 QCOMPARE(object->property("test2").toReal(), 400.);
1348 Test that list properties can be iterated from ECMAScript
1350 void tst_qdeclarativeecmascript::listProperties()
1352 QDeclarativeComponent component(&engine, TEST_FILE("listProperties.qml"));
1353 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1354 QVERIFY(object != 0);
1356 QCOMPARE(object->property("test1").toInt(), 21);
1357 QCOMPARE(object->property("test2").toInt(), 2);
1358 QCOMPARE(object->property("test3").toBool(), true);
1359 QCOMPARE(object->property("test4").toBool(), true);
1364 void tst_qdeclarativeecmascript::exceptionClearsOnReeval()
1366 QDeclarativeComponent component(&engine, TEST_FILE("exceptionClearsOnReeval.qml"));
1367 QString url = component.url().toString();
1369 QString warning = url + ":4: TypeError: Cannot read property 'objectProperty' of null";
1371 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
1372 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1373 QVERIFY(object != 0);
1375 QCOMPARE(object->property("test").toBool(), false);
1377 MyQmlObject object2;
1378 MyQmlObject object3;
1379 object2.setObjectProperty(&object3);
1380 object->setObjectProperty(&object2);
1382 QCOMPARE(object->property("test").toBool(), true);
1387 void tst_qdeclarativeecmascript::exceptionSlotProducesWarning()
1389 QDeclarativeComponent component(&engine, TEST_FILE("exceptionProducesWarning.qml"));
1390 QString url = component.url().toString();
1392 QString warning = component.url().toString() + ":6: Error: JS exception";
1394 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
1395 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1396 QVERIFY(object != 0);
1400 void tst_qdeclarativeecmascript::exceptionBindingProducesWarning()
1402 QDeclarativeComponent component(&engine, TEST_FILE("exceptionProducesWarning2.qml"));
1403 QString url = component.url().toString();
1405 QString warning = component.url().toString() + ":5: Error: JS exception";
1407 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
1408 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1409 QVERIFY(object != 0);
1413 static int transientErrorsMsgCount = 0;
1414 static void transientErrorsMsgHandler(QtMsgType, const char *)
1416 ++transientErrorsMsgCount;
1419 // Check that transient binding errors are not displayed
1420 void tst_qdeclarativeecmascript::transientErrors()
1423 QDeclarativeComponent component(&engine, TEST_FILE("transientErrors.qml"));
1425 transientErrorsMsgCount = 0;
1426 QtMsgHandler old = qInstallMsgHandler(transientErrorsMsgHandler);
1428 QObject *object = component.create();
1429 QVERIFY(object != 0);
1431 qInstallMsgHandler(old);
1433 QCOMPARE(transientErrorsMsgCount, 0);
1438 // One binding erroring multiple times, but then resolving
1440 QDeclarativeComponent component(&engine, TEST_FILE("transientErrors.2.qml"));
1442 transientErrorsMsgCount = 0;
1443 QtMsgHandler old = qInstallMsgHandler(transientErrorsMsgHandler);
1445 QObject *object = component.create();
1446 QVERIFY(object != 0);
1448 qInstallMsgHandler(old);
1450 QCOMPARE(transientErrorsMsgCount, 0);
1456 // Check that errors during shutdown are minimized
1457 void tst_qdeclarativeecmascript::shutdownErrors()
1459 QDeclarativeComponent component(&engine, TEST_FILE("shutdownErrors.qml"));
1460 QObject *object = component.create();
1461 QVERIFY(object != 0);
1463 transientErrorsMsgCount = 0;
1464 QtMsgHandler old = qInstallMsgHandler(transientErrorsMsgHandler);
1468 qInstallMsgHandler(old);
1469 QCOMPARE(transientErrorsMsgCount, 0);
1472 void tst_qdeclarativeecmascript::compositePropertyType()
1474 QDeclarativeComponent component(&engine, TEST_FILE("compositePropertyType.qml"));
1475 QTest::ignoreMessage(QtDebugMsg, "hello world");
1476 QObject *object = qobject_cast<QObject *>(component.create());
1481 void tst_qdeclarativeecmascript::jsObject()
1483 QDeclarativeComponent component(&engine, TEST_FILE("jsObject.qml"));
1484 QObject *object = component.create();
1485 QVERIFY(object != 0);
1487 QCOMPARE(object->property("test").toInt(), 92);
1492 void tst_qdeclarativeecmascript::undefinedResetsProperty()
1495 QDeclarativeComponent component(&engine, TEST_FILE("undefinedResetsProperty.qml"));
1496 QObject *object = component.create();
1497 QVERIFY(object != 0);
1499 QCOMPARE(object->property("resettableProperty").toInt(), 92);
1501 object->setProperty("setUndefined", true);
1503 QCOMPARE(object->property("resettableProperty").toInt(), 13);
1505 object->setProperty("setUndefined", false);
1507 QCOMPARE(object->property("resettableProperty").toInt(), 92);
1512 QDeclarativeComponent component(&engine, TEST_FILE("undefinedResetsProperty.2.qml"));
1513 QObject *object = component.create();
1514 QVERIFY(object != 0);
1516 QCOMPARE(object->property("resettableProperty").toInt(), 19);
1518 QMetaObject::invokeMethod(object, "doReset");
1520 QCOMPARE(object->property("resettableProperty").toInt(), 13);
1527 void tst_qdeclarativeecmascript::bug1()
1529 QDeclarativeComponent component(&engine, TEST_FILE("bug.1.qml"));
1530 QObject *object = component.create();
1531 QVERIFY(object != 0);
1533 QCOMPARE(object->property("test").toInt(), 14);
1535 object->setProperty("a", 11);
1537 QCOMPARE(object->property("test").toInt(), 3);
1539 object->setProperty("b", true);
1541 QCOMPARE(object->property("test").toInt(), 9);
1546 void tst_qdeclarativeecmascript::bug2()
1548 QDeclarativeComponent component(&engine);
1549 component.setData("import Qt.test 1.0;\nQPlainTextEdit { width: 100 }", QUrl());
1551 QObject *object = component.create();
1552 QVERIFY(object != 0);
1557 // Don't crash in createObject when the component has errors.
1558 void tst_qdeclarativeecmascript::dynamicCreationCrash()
1560 QDeclarativeComponent component(&engine, TEST_FILE("dynamicCreation.qml"));
1561 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1562 QVERIFY(object != 0);
1564 QTest::ignoreMessage(QtWarningMsg, "QDeclarativeComponent: Component is not ready");
1565 QMetaObject::invokeMethod(object, "dontCrash");
1566 QObject *created = object->objectProperty();
1567 QVERIFY(created == 0);
1573 void tst_qdeclarativeecmascript::regExpBug()
1575 QDeclarativeComponent component(&engine, TEST_FILE("regExp.qml"));
1576 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1577 QVERIFY(object != 0);
1578 QCOMPARE(object->regExp().pattern(), QLatin1String("[a-zA-z]"));
1582 static inline bool evaluate_error(QV8Engine *engine, v8::Handle<v8::Object> o, const char *source)
1584 QString functionSource = QLatin1String("(function(object) { return ") +
1585 QLatin1String(source) + QLatin1String(" })");
1587 v8::Local<v8::Script> program = v8::Script::Compile(engine->toString(functionSource));
1590 v8::Handle<v8::Function> function = v8::Handle<v8::Function>::Cast(program->Run());
1591 if (function.IsEmpty())
1593 v8::Handle<v8::Value> args[] = { o };
1594 function->Call(engine->global(), 1, args);
1595 return tc.HasCaught();
1598 static inline bool evaluate_value(QV8Engine *engine, v8::Handle<v8::Object> o,
1599 const char *source, v8::Handle<v8::Value> result)
1601 QString functionSource = QLatin1String("(function(object) { return ") +
1602 QLatin1String(source) + QLatin1String(" })");
1604 v8::Local<v8::Script> program = v8::Script::Compile(engine->toString(functionSource));
1607 v8::Handle<v8::Function> function = v8::Handle<v8::Function>::Cast(program->Run());
1608 if (function.IsEmpty())
1610 v8::Handle<v8::Value> args[] = { o };
1612 v8::Handle<v8::Value> value = function->Call(engine->global(), 1, args);
1617 return value->StrictEquals(result);
1620 static inline v8::Handle<v8::Value> evaluate(QV8Engine *engine, v8::Handle<v8::Object> o,
1623 QString functionSource = QLatin1String("(function(object) { return ") +
1624 QLatin1String(source) + QLatin1String(" })");
1626 v8::Local<v8::Script> program = v8::Script::Compile(engine->toString(functionSource));
1628 return v8::Handle<v8::Value>();
1629 v8::Handle<v8::Function> function = v8::Handle<v8::Function>::Cast(program->Run());
1630 if (function.IsEmpty())
1631 return v8::Handle<v8::Value>();
1632 v8::Handle<v8::Value> args[] = { o };
1634 v8::Handle<v8::Value> value = function->Call(engine->global(), 1, args);
1637 return v8::Handle<v8::Value>();
1641 #define EVALUATE_ERROR(source) evaluate_error(engine, object, source)
1642 #define EVALUATE_VALUE(source, result) evaluate_value(engine, object, source, result)
1643 #define EVALUATE(source) evaluate(engine, object, source)
1645 void tst_qdeclarativeecmascript::callQtInvokables()
1647 MyInvokableObject o;
1649 QDeclarativeEngine qmlengine;
1650 QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(&qmlengine);
1652 QV8Engine *engine = ep->v8engine();
1654 v8::HandleScope handle_scope;
1655 v8::Context::Scope scope(engine->context());
1657 v8::Local<v8::Object> object = engine->newQObject(&o)->ToObject();
1659 // Non-existent methods
1661 QVERIFY(EVALUATE_ERROR("object.method_nonexistent()"));
1662 QCOMPARE(o.error(), false);
1663 QCOMPARE(o.invoked(), -1);
1664 QCOMPARE(o.actuals().count(), 0);
1667 QVERIFY(EVALUATE_ERROR("object.method_nonexistent(10, 11)"));
1668 QCOMPARE(o.error(), false);
1669 QCOMPARE(o.invoked(), -1);
1670 QCOMPARE(o.actuals().count(), 0);
1672 // Insufficient arguments
1674 QVERIFY(EVALUATE_ERROR("object.method_int()"));
1675 QCOMPARE(o.error(), false);
1676 QCOMPARE(o.invoked(), -1);
1677 QCOMPARE(o.actuals().count(), 0);
1680 QVERIFY(EVALUATE_ERROR("object.method_intint(10)"));
1681 QCOMPARE(o.error(), false);
1682 QCOMPARE(o.invoked(), -1);
1683 QCOMPARE(o.actuals().count(), 0);
1685 // Excessive arguments
1687 QVERIFY(EVALUATE_VALUE("object.method_int(10, 11)", v8::Undefined()));
1688 QCOMPARE(o.error(), false);
1689 QCOMPARE(o.invoked(), 8);
1690 QCOMPARE(o.actuals().count(), 1);
1691 QCOMPARE(o.actuals().at(0), QVariant(10));
1694 QVERIFY(EVALUATE_VALUE("object.method_intint(10, 11, 12)", v8::Undefined()));
1695 QCOMPARE(o.error(), false);
1696 QCOMPARE(o.invoked(), 9);
1697 QCOMPARE(o.actuals().count(), 2);
1698 QCOMPARE(o.actuals().at(0), QVariant(10));
1699 QCOMPARE(o.actuals().at(1), QVariant(11));
1701 // Test return types
1703 QVERIFY(EVALUATE_VALUE("object.method_NoArgs()", v8::Undefined()));
1704 QCOMPARE(o.error(), false);
1705 QCOMPARE(o.invoked(), 0);
1706 QCOMPARE(o.actuals().count(), 0);
1709 QVERIFY(EVALUATE_VALUE("object.method_NoArgs_int()", v8::Integer::New(6)));
1710 QCOMPARE(o.error(), false);
1711 QCOMPARE(o.invoked(), 1);
1712 QCOMPARE(o.actuals().count(), 0);
1715 QVERIFY(EVALUATE_VALUE("object.method_NoArgs_real()", v8::Number::New(19.75)));
1716 QCOMPARE(o.error(), false);
1717 QCOMPARE(o.invoked(), 2);
1718 QCOMPARE(o.actuals().count(), 0);
1722 v8::Handle<v8::Value> ret = EVALUATE("object.method_NoArgs_QPointF()");
1723 QVERIFY(!ret.IsEmpty());
1724 QCOMPARE(engine->toVariant(ret, -1), QVariant(QPointF(123, 4.5)));
1725 QCOMPARE(o.error(), false);
1726 QCOMPARE(o.invoked(), 3);
1727 QCOMPARE(o.actuals().count(), 0);
1732 v8::Handle<v8::Value> ret = EVALUATE("object.method_NoArgs_QObject()");
1733 QCOMPARE(engine->toQObject(ret), (QObject *)&o);
1734 QCOMPARE(o.error(), false);
1735 QCOMPARE(o.invoked(), 4);
1736 QCOMPARE(o.actuals().count(), 0);
1740 QVERIFY(EVALUATE_VALUE("object.method_NoArgs_unknown()", v8::Undefined()));
1741 QCOMPARE(o.error(), false);
1742 QCOMPARE(o.invoked(), 5);
1743 QCOMPARE(o.actuals().count(), 0);
1747 v8::Handle<v8::Value> ret = EVALUATE("object.method_NoArgs_QScriptValue()");
1748 QVERIFY(ret->IsString());
1749 QCOMPARE(engine->toString(ret), QString("Hello world"));
1750 QCOMPARE(o.error(), false);
1751 QCOMPARE(o.invoked(), 6);
1752 QCOMPARE(o.actuals().count(), 0);
1756 QVERIFY(EVALUATE_VALUE("object.method_NoArgs_QVariant()", engine->toString("QML rocks")));
1757 QCOMPARE(o.error(), false);
1758 QCOMPARE(o.invoked(), 7);
1759 QCOMPARE(o.actuals().count(), 0);
1763 QVERIFY(EVALUATE_VALUE("object.method_int(94)", v8::Undefined()));
1764 QCOMPARE(o.error(), false);
1765 QCOMPARE(o.invoked(), 8);
1766 QCOMPARE(o.actuals().count(), 1);
1767 QCOMPARE(o.actuals().at(0), QVariant(94));
1770 QVERIFY(EVALUATE_VALUE("object.method_int(\"94\")", v8::Undefined()));
1771 QCOMPARE(o.error(), false);
1772 QCOMPARE(o.invoked(), 8);
1773 QCOMPARE(o.actuals().count(), 1);
1774 QCOMPARE(o.actuals().at(0), QVariant(94));
1777 QVERIFY(EVALUATE_VALUE("object.method_int(\"not a number\")", v8::Undefined()));
1778 QCOMPARE(o.error(), false);
1779 QCOMPARE(o.invoked(), 8);
1780 QCOMPARE(o.actuals().count(), 1);
1781 QCOMPARE(o.actuals().at(0), QVariant(0));
1784 QVERIFY(EVALUATE_VALUE("object.method_int(null)", v8::Undefined()));
1785 QCOMPARE(o.error(), false);
1786 QCOMPARE(o.invoked(), 8);
1787 QCOMPARE(o.actuals().count(), 1);
1788 QCOMPARE(o.actuals().at(0), QVariant(0));
1791 QVERIFY(EVALUATE_VALUE("object.method_int(undefined)", v8::Undefined()));
1792 QCOMPARE(o.error(), false);
1793 QCOMPARE(o.invoked(), 8);
1794 QCOMPARE(o.actuals().count(), 1);
1795 QCOMPARE(o.actuals().at(0), QVariant(0));
1798 QVERIFY(EVALUATE_VALUE("object.method_int(object)", v8::Undefined()));
1799 QCOMPARE(o.error(), false);
1800 QCOMPARE(o.invoked(), 8);
1801 QCOMPARE(o.actuals().count(), 1);
1802 QCOMPARE(o.actuals().at(0), QVariant(0));
1805 QVERIFY(EVALUATE_VALUE("object.method_intint(122, 9)", v8::Undefined()));
1806 QCOMPARE(o.error(), false);
1807 QCOMPARE(o.invoked(), 9);
1808 QCOMPARE(o.actuals().count(), 2);
1809 QCOMPARE(o.actuals().at(0), QVariant(122));
1810 QCOMPARE(o.actuals().at(1), QVariant(9));
1813 QVERIFY(EVALUATE_VALUE("object.method_real(94.3)", v8::Undefined()));
1814 QCOMPARE(o.error(), false);
1815 QCOMPARE(o.invoked(), 10);
1816 QCOMPARE(o.actuals().count(), 1);
1817 QCOMPARE(o.actuals().at(0), QVariant(94.3));
1820 QVERIFY(EVALUATE_VALUE("object.method_real(\"94.3\")", v8::Undefined()));
1821 QCOMPARE(o.error(), false);
1822 QCOMPARE(o.invoked(), 10);
1823 QCOMPARE(o.actuals().count(), 1);
1824 QCOMPARE(o.actuals().at(0), QVariant(94.3));
1827 QVERIFY(EVALUATE_VALUE("object.method_real(\"not a number\")", v8::Undefined()));
1828 QCOMPARE(o.error(), false);
1829 QCOMPARE(o.invoked(), 10);
1830 QCOMPARE(o.actuals().count(), 1);
1831 QVERIFY(qIsNaN(o.actuals().at(0).toDouble()));
1834 QVERIFY(EVALUATE_VALUE("object.method_real(null)", v8::Undefined()));
1835 QCOMPARE(o.error(), false);
1836 QCOMPARE(o.invoked(), 10);
1837 QCOMPARE(o.actuals().count(), 1);
1838 QCOMPARE(o.actuals().at(0), QVariant(0));
1841 QVERIFY(EVALUATE_VALUE("object.method_real(undefined)", v8::Undefined()));
1842 QCOMPARE(o.error(), false);
1843 QCOMPARE(o.invoked(), 10);
1844 QCOMPARE(o.actuals().count(), 1);
1845 QVERIFY(qIsNaN(o.actuals().at(0).toDouble()));
1848 QVERIFY(EVALUATE_VALUE("object.method_real(object)", v8::Undefined()));
1849 QCOMPARE(o.error(), false);
1850 QCOMPARE(o.invoked(), 10);
1851 QCOMPARE(o.actuals().count(), 1);
1852 QVERIFY(qIsNaN(o.actuals().at(0).toDouble()));
1855 QVERIFY(EVALUATE_VALUE("object.method_QString(\"Hello world\")", v8::Undefined()));
1856 QCOMPARE(o.error(), false);
1857 QCOMPARE(o.invoked(), 11);
1858 QCOMPARE(o.actuals().count(), 1);
1859 QCOMPARE(o.actuals().at(0), QVariant("Hello world"));
1862 QVERIFY(EVALUATE_VALUE("object.method_QString(19)", v8::Undefined()));
1863 QCOMPARE(o.error(), false);
1864 QCOMPARE(o.invoked(), 11);
1865 QCOMPARE(o.actuals().count(), 1);
1866 QCOMPARE(o.actuals().at(0), QVariant("19"));
1870 QString expected = "MyInvokableObject(0x" + QString::number((quintptr)&o, 16) + ")";
1871 QVERIFY(EVALUATE_VALUE("object.method_QString(object)", v8::Undefined()));
1872 QCOMPARE(o.error(), false);
1873 QCOMPARE(o.invoked(), 11);
1874 QCOMPARE(o.actuals().count(), 1);
1875 QCOMPARE(o.actuals().at(0), QVariant(expected));
1879 QVERIFY(EVALUATE_VALUE("object.method_QString(null)", v8::Undefined()));
1880 QCOMPARE(o.error(), false);
1881 QCOMPARE(o.invoked(), 11);
1882 QCOMPARE(o.actuals().count(), 1);
1883 QCOMPARE(o.actuals().at(0), QVariant(QString()));
1886 QVERIFY(EVALUATE_VALUE("object.method_QString(undefined)", v8::Undefined()));
1887 QCOMPARE(o.error(), false);
1888 QCOMPARE(o.invoked(), 11);
1889 QCOMPARE(o.actuals().count(), 1);
1890 QCOMPARE(o.actuals().at(0), QVariant(QString()));
1893 QVERIFY(EVALUATE_VALUE("object.method_QPointF(0)", v8::Undefined()));
1894 QCOMPARE(o.error(), false);
1895 QCOMPARE(o.invoked(), 12);
1896 QCOMPARE(o.actuals().count(), 1);
1897 QCOMPARE(o.actuals().at(0), QVariant(QPointF()));
1900 QVERIFY(EVALUATE_VALUE("object.method_QPointF(null)", v8::Undefined()));
1901 QCOMPARE(o.error(), false);
1902 QCOMPARE(o.invoked(), 12);
1903 QCOMPARE(o.actuals().count(), 1);
1904 QCOMPARE(o.actuals().at(0), QVariant(QPointF()));
1907 QVERIFY(EVALUATE_VALUE("object.method_QPointF(undefined)", v8::Undefined()));
1908 QCOMPARE(o.error(), false);
1909 QCOMPARE(o.invoked(), 12);
1910 QCOMPARE(o.actuals().count(), 1);
1911 QCOMPARE(o.actuals().at(0), QVariant(QPointF()));
1914 QVERIFY(EVALUATE_VALUE("object.method_QPointF(object)", v8::Undefined()));
1915 QCOMPARE(o.error(), false);
1916 QCOMPARE(o.invoked(), 12);
1917 QCOMPARE(o.actuals().count(), 1);
1918 QCOMPARE(o.actuals().at(0), QVariant(QPointF()));
1921 QVERIFY(EVALUATE_VALUE("object.method_QPointF(object.method_get_QPointF())", v8::Undefined()));
1922 QCOMPARE(o.error(), false);
1923 QCOMPARE(o.invoked(), 12);
1924 QCOMPARE(o.actuals().count(), 1);
1925 QCOMPARE(o.actuals().at(0), QVariant(QPointF(99.3, -10.2)));
1928 QVERIFY(EVALUATE_VALUE("object.method_QPointF(object.method_get_QPoint())", v8::Undefined()));
1929 QCOMPARE(o.error(), false);
1930 QCOMPARE(o.invoked(), 12);
1931 QCOMPARE(o.actuals().count(), 1);
1932 QCOMPARE(o.actuals().at(0), QVariant(QPointF(9, 12)));
1935 QVERIFY(EVALUATE_VALUE("object.method_QObject(0)", v8::Undefined()));
1936 QCOMPARE(o.error(), false);
1937 QCOMPARE(o.invoked(), 13);
1938 QCOMPARE(o.actuals().count(), 1);
1939 QCOMPARE(o.actuals().at(0), qVariantFromValue((QObject *)0));
1942 QVERIFY(EVALUATE_VALUE("object.method_QObject(\"Hello world\")", v8::Undefined()));
1943 QCOMPARE(o.error(), false);
1944 QCOMPARE(o.invoked(), 13);
1945 QCOMPARE(o.actuals().count(), 1);
1946 QCOMPARE(o.actuals().at(0), qVariantFromValue((QObject *)0));
1949 QVERIFY(EVALUATE_VALUE("object.method_QObject(null)", v8::Undefined()));
1950 QCOMPARE(o.error(), false);
1951 QCOMPARE(o.invoked(), 13);
1952 QCOMPARE(o.actuals().count(), 1);
1953 QCOMPARE(o.actuals().at(0), qVariantFromValue((QObject *)0));
1956 QVERIFY(EVALUATE_VALUE("object.method_QObject(undefined)", v8::Undefined()));
1957 QCOMPARE(o.error(), false);
1958 QCOMPARE(o.invoked(), 13);
1959 QCOMPARE(o.actuals().count(), 1);
1960 QCOMPARE(o.actuals().at(0), qVariantFromValue((QObject *)0));
1963 QVERIFY(EVALUATE_VALUE("object.method_QObject(object)", v8::Undefined()));
1964 QCOMPARE(o.error(), false);
1965 QCOMPARE(o.invoked(), 13);
1966 QCOMPARE(o.actuals().count(), 1);
1967 QCOMPARE(o.actuals().at(0), qVariantFromValue((QObject *)&o));
1970 QVERIFY(EVALUATE_VALUE("object.method_QScriptValue(null)", v8::Undefined()));
1971 QCOMPARE(o.error(), false);
1972 QCOMPARE(o.invoked(), 14);
1973 QCOMPARE(o.actuals().count(), 1);
1974 QVERIFY(qvariant_cast<QJSValue>(o.actuals().at(0)).isNull());
1977 QVERIFY(EVALUATE_VALUE("object.method_QScriptValue(undefined)", v8::Undefined()));
1978 QCOMPARE(o.error(), false);
1979 QCOMPARE(o.invoked(), 14);
1980 QCOMPARE(o.actuals().count(), 1);
1981 QVERIFY(qvariant_cast<QJSValue>(o.actuals().at(0)).isUndefined());
1984 QVERIFY(EVALUATE_VALUE("object.method_QScriptValue(19)", v8::Undefined()));
1985 QCOMPARE(o.error(), false);
1986 QCOMPARE(o.invoked(), 14);
1987 QCOMPARE(o.actuals().count(), 1);
1988 QVERIFY(qvariant_cast<QJSValue>(o.actuals().at(0)).strictlyEquals(QJSValue(19)));
1991 QVERIFY(EVALUATE_VALUE("object.method_QScriptValue([19, 20])", v8::Undefined()));
1992 QCOMPARE(o.error(), false);
1993 QCOMPARE(o.invoked(), 14);
1994 QCOMPARE(o.actuals().count(), 1);
1995 QVERIFY(qvariant_cast<QJSValue>(o.actuals().at(0)).isArray());
1998 QVERIFY(EVALUATE_VALUE("object.method_intQScriptValue(4, null)", v8::Undefined()));
1999 QCOMPARE(o.error(), false);
2000 QCOMPARE(o.invoked(), 15);
2001 QCOMPARE(o.actuals().count(), 2);
2002 QCOMPARE(o.actuals().at(0), QVariant(4));
2003 QVERIFY(qvariant_cast<QJSValue>(o.actuals().at(1)).isNull());
2006 QVERIFY(EVALUATE_VALUE("object.method_intQScriptValue(8, undefined)", v8::Undefined()));
2007 QCOMPARE(o.error(), false);
2008 QCOMPARE(o.invoked(), 15);
2009 QCOMPARE(o.actuals().count(), 2);
2010 QCOMPARE(o.actuals().at(0), QVariant(8));
2011 QVERIFY(qvariant_cast<QJSValue>(o.actuals().at(1)).isUndefined());
2014 QVERIFY(EVALUATE_VALUE("object.method_intQScriptValue(3, 19)", v8::Undefined()));
2015 QCOMPARE(o.error(), false);
2016 QCOMPARE(o.invoked(), 15);
2017 QCOMPARE(o.actuals().count(), 2);
2018 QCOMPARE(o.actuals().at(0), QVariant(3));
2019 QVERIFY(qvariant_cast<QJSValue>(o.actuals().at(1)).strictlyEquals(QJSValue(19)));
2022 QVERIFY(EVALUATE_VALUE("object.method_intQScriptValue(44, [19, 20])", v8::Undefined()));
2023 QCOMPARE(o.error(), false);
2024 QCOMPARE(o.invoked(), 15);
2025 QCOMPARE(o.actuals().count(), 2);
2026 QCOMPARE(o.actuals().at(0), QVariant(44));
2027 QVERIFY(qvariant_cast<QJSValue>(o.actuals().at(1)).isArray());
2030 QVERIFY(EVALUATE_ERROR("object.method_overload()"));
2031 QCOMPARE(o.error(), false);
2032 QCOMPARE(o.invoked(), -1);
2033 QCOMPARE(o.actuals().count(), 0);
2036 QVERIFY(EVALUATE_VALUE("object.method_overload(10)", v8::Undefined()));
2037 QCOMPARE(o.error(), false);
2038 QCOMPARE(o.invoked(), 16);
2039 QCOMPARE(o.actuals().count(), 1);
2040 QCOMPARE(o.actuals().at(0), QVariant(10));
2043 QVERIFY(EVALUATE_VALUE("object.method_overload(10, 11)", v8::Undefined()));
2044 QCOMPARE(o.error(), false);
2045 QCOMPARE(o.invoked(), 17);
2046 QCOMPARE(o.actuals().count(), 2);
2047 QCOMPARE(o.actuals().at(0), QVariant(10));
2048 QCOMPARE(o.actuals().at(1), QVariant(11));
2051 QVERIFY(EVALUATE_VALUE("object.method_overload(\"Hello\")", v8::Undefined()));
2052 QCOMPARE(o.error(), false);
2053 QCOMPARE(o.invoked(), 18);
2054 QCOMPARE(o.actuals().count(), 1);
2055 QCOMPARE(o.actuals().at(0), QVariant(QString("Hello")));
2058 QVERIFY(EVALUATE_VALUE("object.method_with_enum(9)", v8::Undefined()));
2059 QCOMPARE(o.error(), false);
2060 QCOMPARE(o.invoked(), 19);
2061 QCOMPARE(o.actuals().count(), 1);
2062 QCOMPARE(o.actuals().at(0), QVariant(9));
2065 QVERIFY(EVALUATE_VALUE("object.method_default(10)", v8::Integer::New(19)));
2066 QCOMPARE(o.error(), false);
2067 QCOMPARE(o.invoked(), 20);
2068 QCOMPARE(o.actuals().count(), 2);
2069 QCOMPARE(o.actuals().at(0), QVariant(10));
2070 QCOMPARE(o.actuals().at(1), QVariant(19));
2073 QVERIFY(EVALUATE_VALUE("object.method_default(10, 13)", v8::Integer::New(13)));
2074 QCOMPARE(o.error(), false);
2075 QCOMPARE(o.invoked(), 20);
2076 QCOMPARE(o.actuals().count(), 2);
2077 QCOMPARE(o.actuals().at(0), QVariant(10));
2078 QCOMPARE(o.actuals().at(1), QVariant(13));
2081 QVERIFY(EVALUATE_VALUE("object.method_inherited(9)", v8::Undefined()));
2082 QCOMPARE(o.error(), false);
2083 QCOMPARE(o.invoked(), -3);
2084 QCOMPARE(o.actuals().count(), 1);
2085 QCOMPARE(o.actuals().at(0), QVariant(9));
2088 QVERIFY(EVALUATE_VALUE("object.method_QVariant(9)", v8::Undefined()));
2089 QCOMPARE(o.error(), false);
2090 QCOMPARE(o.invoked(), 21);
2091 QCOMPARE(o.actuals().count(), 2);
2092 QCOMPARE(o.actuals().at(0), QVariant(9));
2093 QCOMPARE(o.actuals().at(1), QVariant());
2096 QVERIFY(EVALUATE_VALUE("object.method_QVariant(\"Hello\", \"World\")", v8::Undefined()));
2097 QCOMPARE(o.error(), false);
2098 QCOMPARE(o.invoked(), 21);
2099 QCOMPARE(o.actuals().count(), 2);
2100 QCOMPARE(o.actuals().at(0), QVariant(QString("Hello")));
2101 QCOMPARE(o.actuals().at(1), QVariant(QString("World")));
2104 // QTBUG-13047 (check that you can pass registered object types as args)
2105 void tst_qdeclarativeecmascript::invokableObjectArg()
2107 QDeclarativeComponent component(&engine, TEST_FILE("invokableObjectArg.qml"));
2109 QObject *o = component.create();
2111 MyQmlObject *qmlobject = qobject_cast<MyQmlObject *>(o);
2113 QCOMPARE(qmlobject->myinvokableObject, qmlobject);
2118 // QTBUG-13047 (check that you can return registered object types from methods)
2119 void tst_qdeclarativeecmascript::invokableObjectRet()
2121 QDeclarativeComponent component(&engine, TEST_FILE("invokableObjectRet.qml"));
2123 QObject *o = component.create();
2125 QCOMPARE(o->property("test").toBool(), true);
2130 void tst_qdeclarativeecmascript::listToVariant()
2132 QDeclarativeComponent component(&engine, TEST_FILE("listToVariant.qml"));
2134 MyQmlContainer container;
2136 QDeclarativeContext context(engine.rootContext());
2137 context.setContextObject(&container);
2139 QObject *object = component.create(&context);
2140 QVERIFY(object != 0);
2142 QVariant v = object->property("test");
2143 QCOMPARE(v.userType(), qMetaTypeId<QDeclarativeListReference>());
2144 QVERIFY(qvariant_cast<QDeclarativeListReference>(v).object() == &container);
2150 void tst_qdeclarativeecmascript::multiEngineObject()
2153 obj.setStringProperty("Howdy planet");
2155 QDeclarativeEngine e1;
2156 e1.rootContext()->setContextProperty("thing", &obj);
2157 QDeclarativeComponent c1(&e1, TEST_FILE("multiEngineObject.qml"));
2159 QDeclarativeEngine e2;
2160 e2.rootContext()->setContextProperty("thing", &obj);
2161 QDeclarativeComponent c2(&e2, TEST_FILE("multiEngineObject.qml"));
2163 QObject *o1 = c1.create();
2164 QObject *o2 = c2.create();
2166 QCOMPARE(o1->property("test").toString(), QString("Howdy planet"));
2167 QCOMPARE(o2->property("test").toString(), QString("Howdy planet"));
2173 // Test that references to QObjects are cleanup when the object is destroyed
2174 void tst_qdeclarativeecmascript::deletedObject()
2176 QDeclarativeComponent component(&engine, TEST_FILE("deletedObject.qml"));
2178 QObject *object = component.create();
2180 QCOMPARE(object->property("test1").toBool(), true);
2181 QCOMPARE(object->property("test2").toBool(), true);
2182 QCOMPARE(object->property("test3").toBool(), true);
2183 QCOMPARE(object->property("test4").toBool(), true);
2188 void tst_qdeclarativeecmascript::attachedPropertyScope()
2190 QDeclarativeComponent component(&engine, TEST_FILE("attachedPropertyScope.qml"));
2192 QObject *object = component.create();
2193 QVERIFY(object != 0);
2195 MyQmlAttachedObject *attached =
2196 qobject_cast<MyQmlAttachedObject *>(qmlAttachedPropertiesObject<MyQmlObject>(object));
2197 QVERIFY(attached != 0);
2199 QCOMPARE(object->property("value2").toInt(), 0);
2201 attached->emitMySignal();
2203 QCOMPARE(object->property("value2").toInt(), 9);
2208 void tst_qdeclarativeecmascript::scriptConnect()
2211 QDeclarativeComponent component(&engine, TEST_FILE("scriptConnect.1.qml"));
2213 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2214 QVERIFY(object != 0);
2216 QCOMPARE(object->property("test").toBool(), false);
2217 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2218 QCOMPARE(object->property("test").toBool(), true);
2224 QDeclarativeComponent component(&engine, TEST_FILE("scriptConnect.2.qml"));
2226 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2227 QVERIFY(object != 0);
2229 QCOMPARE(object->property("test").toBool(), false);
2230 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2231 QCOMPARE(object->property("test").toBool(), true);
2237 QDeclarativeComponent component(&engine, TEST_FILE("scriptConnect.3.qml"));
2239 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2240 QVERIFY(object != 0);
2242 QCOMPARE(object->property("test").toBool(), false);
2243 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2244 QCOMPARE(object->property("test").toBool(), true);
2250 QDeclarativeComponent component(&engine, TEST_FILE("scriptConnect.4.qml"));
2252 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2253 QVERIFY(object != 0);
2255 QCOMPARE(object->methodCalled(), false);
2256 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2257 QCOMPARE(object->methodCalled(), true);
2263 QDeclarativeComponent component(&engine, TEST_FILE("scriptConnect.5.qml"));
2265 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2266 QVERIFY(object != 0);
2268 QCOMPARE(object->methodCalled(), false);
2269 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2270 QCOMPARE(object->methodCalled(), true);
2276 QDeclarativeComponent component(&engine, TEST_FILE("scriptConnect.6.qml"));
2278 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2279 QVERIFY(object != 0);
2281 QCOMPARE(object->property("test").toInt(), 0);
2282 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2283 QCOMPARE(object->property("test").toInt(), 2);
2289 void tst_qdeclarativeecmascript::scriptDisconnect()
2292 QDeclarativeComponent component(&engine, TEST_FILE("scriptDisconnect.1.qml"));
2294 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2295 QVERIFY(object != 0);
2297 QCOMPARE(object->property("test").toInt(), 0);
2298 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2299 QCOMPARE(object->property("test").toInt(), 1);
2300 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2301 QCOMPARE(object->property("test").toInt(), 2);
2302 emit object->basicSignal();
2303 QCOMPARE(object->property("test").toInt(), 2);
2304 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2305 QCOMPARE(object->property("test").toInt(), 2);
2311 QDeclarativeComponent component(&engine, TEST_FILE("scriptDisconnect.2.qml"));
2313 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2314 QVERIFY(object != 0);
2316 QCOMPARE(object->property("test").toInt(), 0);
2317 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2318 QCOMPARE(object->property("test").toInt(), 1);
2319 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2320 QCOMPARE(object->property("test").toInt(), 2);
2321 emit object->basicSignal();
2322 QCOMPARE(object->property("test").toInt(), 2);
2323 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2324 QCOMPARE(object->property("test").toInt(), 2);
2330 QDeclarativeComponent component(&engine, TEST_FILE("scriptDisconnect.3.qml"));
2332 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2333 QVERIFY(object != 0);
2335 QCOMPARE(object->property("test").toInt(), 0);
2336 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2337 QCOMPARE(object->property("test").toInt(), 1);
2338 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2339 QCOMPARE(object->property("test").toInt(), 2);
2340 emit object->basicSignal();
2341 QCOMPARE(object->property("test").toInt(), 2);
2342 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2343 QCOMPARE(object->property("test").toInt(), 3);
2348 QDeclarativeComponent component(&engine, TEST_FILE("scriptDisconnect.4.qml"));
2350 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2351 QVERIFY(object != 0);
2353 QCOMPARE(object->property("test").toInt(), 0);
2354 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2355 QCOMPARE(object->property("test").toInt(), 1);
2356 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2357 QCOMPARE(object->property("test").toInt(), 2);
2358 emit object->basicSignal();
2359 QCOMPARE(object->property("test").toInt(), 2);
2360 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2361 QCOMPARE(object->property("test").toInt(), 3);
2367 class OwnershipObject : public QObject
2371 OwnershipObject() { object = new QObject; }
2373 QPointer<QObject> object;
2376 QObject *getObject() { return object; }
2379 void tst_qdeclarativeecmascript::ownership()
2381 OwnershipObject own;
2382 QDeclarativeContext *context = new QDeclarativeContext(engine.rootContext());
2383 context->setContextObject(&own);
2386 QDeclarativeComponent component(&engine, TEST_FILE("ownership.qml"));
2388 QVERIFY(own.object != 0);
2390 QObject *object = component.create(context);
2392 engine.collectGarbage();
2394 QCoreApplication::processEvents(QEventLoop::DeferredDeletion);
2396 QVERIFY(own.object == 0);
2401 own.object = new QObject(&own);
2404 QDeclarativeComponent component(&engine, TEST_FILE("ownership.qml"));
2406 QVERIFY(own.object != 0);
2408 QObject *object = component.create(context);
2410 engine.collectGarbage();
2412 QCoreApplication::processEvents(QEventLoop::DeferredDeletion);
2414 QVERIFY(own.object != 0);
2422 class CppOwnershipReturnValue : public QObject
2426 CppOwnershipReturnValue() : value(0) {}
2427 ~CppOwnershipReturnValue() { delete value; }
2429 Q_INVOKABLE QObject *create() {
2430 value = new QObject;
2431 QDeclarativeEngine::setObjectOwnership(value, QDeclarativeEngine::CppOwnership);
2435 Q_INVOKABLE MyQmlObject *createQmlObject() {
2436 MyQmlObject *rv = new MyQmlObject;
2441 QPointer<QObject> value;
2445 // Test setObjectOwnership(CppOwnership) works even when there is no QDeclarativeData
2446 void tst_qdeclarativeecmascript::cppOwnershipReturnValue()
2448 CppOwnershipReturnValue source;
2451 QDeclarativeEngine engine;
2452 engine.rootContext()->setContextProperty("source", &source);
2454 QVERIFY(source.value == 0);
2456 QDeclarativeComponent component(&engine);
2457 component.setData("import QtQuick 1.0\nQtObject {\nComponent.onCompleted: { var a = source.create(); }\n}\n", QUrl());
2459 QObject *object = component.create();
2461 QVERIFY(object != 0);
2462 QVERIFY(source.value != 0);
2467 QCoreApplication::instance()->processEvents(QEventLoop::DeferredDeletion);
2469 QVERIFY(source.value != 0);
2473 void tst_qdeclarativeecmascript::ownershipCustomReturnValue()
2475 CppOwnershipReturnValue source;
2478 QDeclarativeEngine engine;
2479 engine.rootContext()->setContextProperty("source", &source);
2481 QVERIFY(source.value == 0);
2483 QDeclarativeComponent component(&engine);
2484 component.setData("import QtQuick 1.0\nQtObject {\nComponent.onCompleted: { var a = source.createQmlObject(); }\n}\n", QUrl());
2486 QObject *object = component.create();
2488 QVERIFY(object != 0);
2489 QVERIFY(source.value != 0);
2494 engine.collectGarbage();
2495 QCoreApplication::instance()->processEvents(QEventLoop::DeferredDeletion);
2497 QVERIFY(source.value == 0);
2500 class QListQObjectMethodsObject : public QObject
2504 QListQObjectMethodsObject() {
2505 m_objects.append(new MyQmlObject());
2506 m_objects.append(new MyQmlObject());
2509 ~QListQObjectMethodsObject() {
2510 qDeleteAll(m_objects);
2514 QList<QObject *> getObjects() { return m_objects; }
2517 QList<QObject *> m_objects;
2520 // Tests that returning a QList<QObject*> from a method works
2521 void tst_qdeclarativeecmascript::qlistqobjectMethods()
2523 QListQObjectMethodsObject obj;
2524 QDeclarativeContext *context = new QDeclarativeContext(engine.rootContext());
2525 context->setContextObject(&obj);
2527 QDeclarativeComponent component(&engine, TEST_FILE("qlistqobjectMethods.qml"));
2529 QObject *object = component.create(context);
2531 QCOMPARE(object->property("test").toInt(), 2);
2532 QCOMPARE(object->property("test2").toBool(), true);
2539 void tst_qdeclarativeecmascript::strictlyEquals()
2541 QDeclarativeComponent component(&engine, TEST_FILE("strictlyEquals.qml"));
2543 QObject *object = component.create();
2544 QVERIFY(object != 0);
2546 QCOMPARE(object->property("test1").toBool(), true);
2547 QCOMPARE(object->property("test2").toBool(), true);
2548 QCOMPARE(object->property("test3").toBool(), true);
2549 QCOMPARE(object->property("test4").toBool(), true);
2550 QCOMPARE(object->property("test5").toBool(), true);
2551 QCOMPARE(object->property("test6").toBool(), true);
2552 QCOMPARE(object->property("test7").toBool(), true);
2553 QCOMPARE(object->property("test8").toBool(), true);
2558 void tst_qdeclarativeecmascript::compiled()
2560 QDeclarativeComponent component(&engine, TEST_FILE("compiled.qml"));
2562 QObject *object = component.create();
2563 QVERIFY(object != 0);
2565 QCOMPARE(object->property("test1").toReal(), qreal(15.7));
2566 QCOMPARE(object->property("test2").toReal(), qreal(-6.7));
2567 QCOMPARE(object->property("test3").toBool(), true);
2568 QCOMPARE(object->property("test4").toBool(), false);
2569 QCOMPARE(object->property("test5").toBool(), false);
2570 QCOMPARE(object->property("test6").toBool(), true);
2572 QCOMPARE(object->property("test7").toInt(), 185);
2573 QCOMPARE(object->property("test8").toInt(), 167);
2574 QCOMPARE(object->property("test9").toBool(), true);
2575 QCOMPARE(object->property("test10").toBool(), false);
2576 QCOMPARE(object->property("test11").toBool(), false);
2577 QCOMPARE(object->property("test12").toBool(), true);
2579 QCOMPARE(object->property("test13").toString(), QLatin1String("HelloWorld"));
2580 QCOMPARE(object->property("test14").toString(), QLatin1String("Hello World"));
2581 QCOMPARE(object->property("test15").toBool(), false);
2582 QCOMPARE(object->property("test16").toBool(), true);
2584 QCOMPARE(object->property("test17").toInt(), 5);
2585 QCOMPARE(object->property("test18").toReal(), qreal(176));
2586 QCOMPARE(object->property("test19").toInt(), 7);
2587 QCOMPARE(object->property("test20").toReal(), qreal(6.7));
2588 QCOMPARE(object->property("test21").toString(), QLatin1String("6.7"));
2589 QCOMPARE(object->property("test22").toString(), QLatin1String("!"));
2590 QCOMPARE(object->property("test23").toBool(), true);
2591 QCOMPARE(qvariant_cast<QColor>(object->property("test24")), QColor(0x11,0x22,0x33));
2592 QCOMPARE(qvariant_cast<QColor>(object->property("test25")), QColor(0x11,0x22,0x33,0xAA));
2597 // Test that numbers assigned in bindings as strings work consistently
2598 void tst_qdeclarativeecmascript::numberAssignment()
2600 QDeclarativeComponent component(&engine, TEST_FILE("numberAssignment.qml"));
2602 QObject *object = component.create();
2603 QVERIFY(object != 0);
2605 QCOMPARE(object->property("test1"), QVariant((qreal)6.7));
2606 QCOMPARE(object->property("test2"), QVariant((qreal)6.7));
2607 QCOMPARE(object->property("test2"), QVariant((qreal)6.7));
2608 QCOMPARE(object->property("test3"), QVariant((qreal)6));
2609 QCOMPARE(object->property("test4"), QVariant((qreal)6));
2611 QCOMPARE(object->property("test5"), QVariant((int)7));
2612 QCOMPARE(object->property("test6"), QVariant((int)7));
2613 QCOMPARE(object->property("test7"), QVariant((int)6));
2614 QCOMPARE(object->property("test8"), QVariant((int)6));
2616 QCOMPARE(object->property("test9"), QVariant((unsigned int)7));
2617 QCOMPARE(object->property("test10"), QVariant((unsigned int)7));
2618 QCOMPARE(object->property("test11"), QVariant((unsigned int)6));
2619 QCOMPARE(object->property("test12"), QVariant((unsigned int)6));
2624 void tst_qdeclarativeecmascript::propertySplicing()
2626 QDeclarativeComponent component(&engine, TEST_FILE("propertySplicing.qml"));
2628 QObject *object = component.create();
2629 QVERIFY(object != 0);
2631 QCOMPARE(object->property("test").toBool(), true);
2637 void tst_qdeclarativeecmascript::signalWithUnknownTypes()
2639 QDeclarativeComponent component(&engine, TEST_FILE("signalWithUnknownTypes.qml"));
2641 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2642 QVERIFY(object != 0);
2644 MyQmlObject::MyType type;
2645 type.value = 0x8971123;
2646 emit object->signalWithUnknownType(type);
2648 MyQmlObject::MyType result = qvariant_cast<MyQmlObject::MyType>(object->variant());
2650 QCOMPARE(result.value, type.value);
2656 void tst_qdeclarativeecmascript::moduleApi()
2658 QDeclarativeComponent component(&engine, TEST_FILE("moduleApi.qml"));
2659 QObject *object = component.create();
2660 QVERIFY(object != 0);
2661 QCOMPARE(object->property("existingUriTest").toInt(), 20);
2663 QEXPECT_FAIL("", "QTBUG-17318", Continue);
2664 QCOMPARE(object->property("scriptTest").toInt(), 13);
2665 QCOMPARE(object->property("qobjectTest").toInt(), 20);
2666 QCOMPARE(object->property("qobjectMethodTest").toInt(), 1); // first call of method, so count = 1.
2667 QCOMPARE(object->property("qobjectMinorVersionTest").toInt(), 20);
2668 QCOMPARE(object->property("qobjectMajorVersionTest").toInt(), 20);
2669 QCOMPARE(object->property("qobjectParentedTest").toInt(), 26);
2672 // test that caching of module apis works correctly.
2673 QDeclarativeComponent componentTwo(&engine, TEST_FILE("moduleApiCaching.qml"));
2674 object = componentTwo.create();
2675 QVERIFY(object != 0);
2676 QCOMPARE(object->property("existingUriTest").toInt(), 20);
2677 QEXPECT_FAIL("", "QTBUG-17318", Continue);
2678 QCOMPARE(object->property("scriptTest").toInt(), 13); // shouldn't have incremented.
2679 QCOMPARE(object->property("qobjectParentedTest").toInt(), 26); // shouldn't have incremented.
2682 // test that writing to a property of module apis works correctly.
2683 QDeclarativeComponent componentThree(&engine, TEST_FILE("moduleApiWriting.qml"));
2684 QString expectedWarning = QLatin1String("file://") + TEST_FILE("moduleApiWriting.qml").toLocalFile() + QLatin1String(":15: Error: Cannot assign to read-only property \"qobjectTestProperty\"");
2685 QTest::ignoreMessage(QtWarningMsg, expectedWarning.toAscii().constData());
2686 object = componentThree.create();
2687 QVERIFY(object != 0);
2688 QCOMPARE(object->property("readOnlyProperty").toInt(), 20);
2689 QCOMPARE(object->property("writableProperty").toInt(), 50);
2690 QVERIFY(object->setProperty("firstProperty", QVariant(30))); // shouldn't affect value of readOnlyProperty
2691 QVERIFY(object->setProperty("writableProperty", QVariant(30))); // SHOULD affect value of writableProperty
2692 QCOMPARE(object->property("readOnlyProperty").toInt(), 20);
2693 QCOMPARE(object->property("writableProperty").toInt(), 30);
2696 QDeclarativeComponent failOne(&engine, TEST_FILE("moduleApiMajorVersionFail.qml"));
2697 QTest::ignoreMessage(QtWarningMsg, "QDeclarativeComponent: Component is not ready");
2698 object = failOne.create();
2699 QVERIFY(object == 0); // should have failed: invalid major version
2701 QDeclarativeComponent failTwo(&engine, TEST_FILE("moduleApiMinorVersionFail.qml"));
2702 QTest::ignoreMessage(QtWarningMsg, "QDeclarativeComponent: Component is not ready");
2703 object = failTwo.create();
2704 QVERIFY(object == 0); // should have failed: invalid minor version
2707 void tst_qdeclarativeecmascript::importScripts()
2709 QObject *object = 0;
2711 // first, ensure that the required behaviour works.
2712 QDeclarativeComponent component(&engine, TEST_FILE("jsimport/testImport.qml"));
2713 object = component.create();
2714 QVERIFY(object != 0);
2715 QCOMPARE(object->property("importedScriptStringValue"), QVariant(QString(QLatin1String("Hello, World!"))));
2716 QCOMPARE(object->property("importedScriptFunctionValue"), QVariant(20));
2717 QCOMPARE(object->property("importedModuleAttachedPropertyValue"), QVariant(19));
2718 QCOMPARE(object->property("importedModuleEnumValue"), QVariant(2));
2721 QDeclarativeComponent componentTwo(&engine, TEST_FILE("jsimport/testImportScoping.qml"));
2722 object = componentTwo.create();
2723 QVERIFY(object != 0);
2724 QCOMPARE(object->property("componentError"), QVariant(5));
2727 // then, ensure that unintended behaviour does not work.
2728 QDeclarativeComponent failOneComponent(&engine, TEST_FILE("jsimportfail/failOne.qml"));
2729 QString expectedWarning = QLatin1String("file://") + TEST_FILE("jsimportfail/failOne.qml").toLocalFile() + QLatin1String(":6: TypeError: Cannot call method 'greetingString' of undefined");
2730 QTest::ignoreMessage(QtWarningMsg, expectedWarning.toAscii().constData());
2731 object = failOneComponent.create();
2732 QVERIFY(object != 0);
2733 QVERIFY(object->property("importScriptFunctionValue").toString().isEmpty());
2735 QDeclarativeComponent failTwoComponent(&engine, TEST_FILE("jsimportfail/failTwo.qml"));
2736 expectedWarning = QLatin1String("file://") + TEST_FILE("jsimportfail/failTwo.qml").toLocalFile() + QLatin1String(":6: ReferenceError: Can't find variable: ImportOneJs");
2737 QTest::ignoreMessage(QtWarningMsg, expectedWarning.toAscii().constData());
2738 object = failTwoComponent.create();
2739 QVERIFY(object != 0);
2740 QVERIFY(object->property("importScriptFunctionValue").toString().isEmpty());
2742 QDeclarativeComponent failThreeComponent(&engine, TEST_FILE("jsimportfail/failThree.qml"));
2743 expectedWarning = QLatin1String("file://") + TEST_FILE("jsimportfail/failThree.qml").toLocalFile() + QLatin1String(":7: TypeError: Cannot read property 'JsQtTest' of undefined");
2744 QTest::ignoreMessage(QtWarningMsg, expectedWarning.toAscii().constData());
2745 object = failThreeComponent.create();
2746 QVERIFY(object != 0);
2747 QCOMPARE(object->property("importedModuleAttachedPropertyValue"), QVariant(false));
2749 QDeclarativeComponent failFourComponent(&engine, TEST_FILE("jsimportfail/failFour.qml"));
2750 expectedWarning = QLatin1String("file://") + TEST_FILE("jsimportfail/failFour.qml").toLocalFile() + QLatin1String(":6: ReferenceError: Can't find variable: JsQtTest");
2751 QTest::ignoreMessage(QtWarningMsg, expectedWarning.toAscii().constData());
2752 object = failFourComponent.create();
2753 QVERIFY(object != 0);
2754 QCOMPARE(object->property("importedModuleEnumValue"), QVariant(0));
2756 QDeclarativeComponent failFiveComponent(&engine, TEST_FILE("jsimportfail/failFive.qml"));
2757 expectedWarning = QLatin1String("file://") + TEST_FILE("jsimportfail/importWithImports.js").toLocalFile() + QLatin1String(":8: ReferenceError: Can't find variable: Component");
2758 QTest::ignoreMessage(QtWarningMsg, expectedWarning.toAscii().constData());
2759 expectedWarning = QLatin1String("file://") + TEST_FILE("jsimportfail/importPragmaLibrary.js").toLocalFile() + QLatin1String(":6: ReferenceError: Can't find variable: Component");
2760 QTest::ignoreMessage(QtWarningMsg, expectedWarning.toAscii().constData());
2761 object = failFiveComponent.create();
2762 QVERIFY(object != 0);
2763 QCOMPARE(object->property("componentError"), QVariant(0));
2766 // also, test that importing scripts with .pragma library works as required
2767 QDeclarativeComponent pragmaLibraryComponent(&engine, TEST_FILE("jsimport/testImportPragmaLibrary.qml"));
2768 object = pragmaLibraryComponent.create();
2769 QVERIFY(object != 0);
2770 QCOMPARE(object->property("testValue"), QVariant(31));
2773 // and that .pragma library scripts don't inherit imports from any .qml file
2774 QDeclarativeComponent pragmaLibraryComponentTwo(&engine, TEST_FILE("jsimportfail/testImportPragmaLibrary.qml"));
2775 object = pragmaLibraryComponentTwo.create();
2776 QVERIFY(object != 0);
2777 QCOMPARE(object->property("testValue"), QVariant(0));
2781 void tst_qdeclarativeecmascript::scarceResources()
2783 QPixmap origPixmap(100, 100);
2784 origPixmap.fill(Qt::blue);
2786 QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(&engine);
2787 ScarceResourceObject *eo = 0;
2788 QObject *object = 0;
2790 // in the following three cases, the instance created from the component
2791 // has a property which is a copy of the scarce resource; hence, the
2792 // resource should NOT be detached prior to deletion of the object instance,
2793 // unless the resource is destroyed explicitly.
2794 QDeclarativeComponent component(&engine, TEST_FILE("scarceresources/scarceResourceCopy.qml"));
2795 object = component.create();
2796 QVERIFY(object != 0);
2797 QVERIFY(object->property("scarceResourceCopy").isValid());
2798 QCOMPARE(object->property("scarceResourceCopy").value<QPixmap>(), origPixmap);
2799 QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
2800 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2801 QVERIFY(!eo->scarceResourceIsDetached()); // there are two copies of it in existence: the property of object, and the property of eo.
2804 QDeclarativeComponent componentTwo(&engine, TEST_FILE("scarceresources/scarceResourceCopyFromJs.qml"));
2805 object = componentTwo.create();
2806 QVERIFY(object != 0);
2807 QVERIFY(object->property("scarceResourceCopy").isValid());
2808 QCOMPARE(object->property("scarceResourceCopy").value<QPixmap>(), origPixmap);
2809 QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
2810 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2811 QVERIFY(!eo->scarceResourceIsDetached()); // there are two copies of it in existence: the property of object, and the property of eo.
2814 QDeclarativeComponent componentThree(&engine, TEST_FILE("scarceresources/scarceResourceDestroyedCopy.qml"));
2815 object = componentThree.create();
2816 QVERIFY(object != 0);
2817 QVERIFY(!(object->property("scarceResourceCopy").isValid())); // was manually released prior to being returned.
2818 QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
2819 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2820 QVERIFY(eo->scarceResourceIsDetached()); // should have explicitly been released during the evaluation of the binding.
2823 // in the following three cases, no other copy should exist in memory,
2824 // and so it should be detached (unless explicitly preserved).
2825 QDeclarativeComponent componentFour(&engine, TEST_FILE("scarceresources/scarceResourceTest.qml"));
2826 object = componentFour.create();
2827 QVERIFY(object != 0);
2828 QVERIFY(object->property("scarceResourceTest").isValid());
2829 QCOMPARE(object->property("scarceResourceTest").toInt(), 100);
2830 QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
2831 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2832 QVERIFY(eo->scarceResourceIsDetached()); // the resource should have been released after the binding was evaluated.
2835 QDeclarativeComponent componentFive(&engine, TEST_FILE("scarceresources/scarceResourceTestPreserve.qml"));
2836 object = componentFive.create();
2837 QVERIFY(object != 0);
2838 QVERIFY(object->property("scarceResourceTest").isValid());
2839 QCOMPARE(object->property("scarceResourceTest").toInt(), 100);
2840 QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
2841 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2842 QVERIFY(!eo->scarceResourceIsDetached()); // this won't be detached since we explicitly preserved it.
2845 QDeclarativeComponent componentSix(&engine, TEST_FILE("scarceresources/scarceResourceTestMultiple.qml"));
2846 object = componentSix.create();
2847 QVERIFY(object != 0);
2848 QVERIFY(object->property("scarceResourceTest").isValid());
2849 QCOMPARE(object->property("scarceResourceTest").toInt(), 100);
2850 QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
2851 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2852 QVERIFY(eo->scarceResourceIsDetached()); // all resources were released manually or automatically released.
2855 // test that scarce resources are handled correctly for imports
2856 QDeclarativeComponent componentSeven(&engine, TEST_FILE("scarceresources/scarceResourceCopyImportNoBinding.qml"));
2857 object = componentSeven.create();
2858 QVERIFY(object != 0); // the import should have caused the addition of a resource to the ScarceResources list
2859 QVERIFY(ep->scarceResources.isEmpty()); // but they should have been released by this point.
2862 QDeclarativeComponent componentEight(&engine, TEST_FILE("scarceresources/scarceResourceCopyImportFail.qml"));
2863 object = componentEight.create();
2864 QVERIFY(object != 0);
2865 QVERIFY(!object->property("scarceResourceCopy").isValid()); // wasn't preserved, so shouldn't be valid.
2866 QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
2869 QDeclarativeComponent componentNine(&engine, TEST_FILE("scarceresources/scarceResourceCopyImport.qml"));
2870 object = componentNine.create();
2871 QVERIFY(object != 0);
2872 QVERIFY(object->property("scarceResourceCopy").isValid()); // preserved, so should be valid.
2873 QCOMPARE(object->property("scarceResourceCopy").value<QPixmap>(), origPixmap);
2874 QVERIFY(object->property("scarceResourceAssignedCopyOne").isValid()); // assigned before destroy(), so should be valid.
2875 QCOMPARE(object->property("scarceResourceAssignedCopyOne").value<QPixmap>(), origPixmap);
2876 QVERIFY(!object->property("scarceResourceAssignedCopyTwo").isValid()); // assigned after destroy(), so should be invalid.
2877 QVERIFY(ep->scarceResources.isEmpty()); // this will still be zero, because "preserve()" REMOVES it from this list.
2880 // test that scarce resources are handled properly in signal invocation
2881 QDeclarativeComponent componentTen(&engine, TEST_FILE("scarceresources/scarceResourceSignal.qml"));
2882 object = componentTen.create();
2883 QVERIFY(object != 0);
2884 QObject *srsc = object->findChild<QObject*>("srsc");
2886 QVERIFY(!srsc->property("scarceResourceCopy").isValid()); // hasn't been instantiated yet.
2887 QCOMPARE(srsc->property("width"), QVariant(5)); // default value is 5.
2888 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2889 QVERIFY(eo->scarceResourceIsDetached()); // should be no other copies of it at this stage.
2890 QMetaObject::invokeMethod(srsc, "testSignal");
2891 QVERIFY(!srsc->property("scarceResourceCopy").isValid()); // still hasn't been instantiated
2892 QCOMPARE(srsc->property("width"), QVariant(10)); // but width was assigned to 10.
2893 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2894 QVERIFY(eo->scarceResourceIsDetached()); // should still be no other copies of it at this stage.
2895 QMetaObject::invokeMethod(srsc, "testSignal2"); // assigns scarceResourceCopy to the scarce pixmap.
2896 QVERIFY(srsc->property("scarceResourceCopy").isValid());
2897 QCOMPARE(srsc->property("scarceResourceCopy").value<QPixmap>(), origPixmap);
2898 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2899 QVERIFY(!(eo->scarceResourceIsDetached())); // should be another copy of the resource now.
2900 QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
2903 // test that scarce resources are handled properly from js functions in qml files
2904 QDeclarativeComponent componentEleven(&engine, TEST_FILE("scarceresources/scarceResourceFunction.qml"));
2905 object = componentEleven.create();
2906 QVERIFY(object != 0);
2907 QVERIFY(!object->property("scarceResourceCopy").isValid()); // not yet assigned, so should not be valid
2908 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2909 QVERIFY(eo->scarceResourceIsDetached()); // should be no other copies of it at this stage.
2910 QMetaObject::invokeMethod(object, "retrieveScarceResource");
2911 QVERIFY(object->property("scarceResourceCopy").isValid()); // assigned, so should be valid.
2912 QCOMPARE(object->property("scarceResourceCopy").value<QPixmap>(), origPixmap);
2913 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2914 QVERIFY(!eo->scarceResourceIsDetached()); // should be a copy of the resource at this stage.
2915 QMetaObject::invokeMethod(object, "releaseScarceResource");
2916 QVERIFY(!object->property("scarceResourceCopy").isValid()); // just released, so should not be valid
2917 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2918 QVERIFY(eo->scarceResourceIsDetached()); // should be no other copies of it at this stage.
2919 QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
2922 // test that if an exception occurs while invoking js function from cpp, that the resources are released.
2923 QDeclarativeComponent componentTwelve(&engine, TEST_FILE("scarceresources/scarceResourceFunctionFail.qml"));
2924 object = componentTwelve.create();
2925 QVERIFY(object != 0);
2926 QVERIFY(!object->property("scarceResourceCopy").isValid()); // not yet assigned, so should not be valid
2927 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2928 QVERIFY(eo->scarceResourceIsDetached()); // should be no other copies of it at this stage.
2929 QString srp_name = object->property("srp_name").toString();
2930 QString expectedWarning = componentTwelve.url().toString() + QLatin1String(":17: TypeError: Property 'scarceResource' of object ") + srp_name + QLatin1String(" is not a function");
2931 QTest::ignoreMessage(QtWarningMsg, qPrintable(expectedWarning)); // we expect a meaningful warning to be printed.
2932 QMetaObject::invokeMethod(object, "retrieveScarceResource");
2933 QVERIFY(!object->property("scarceResourceCopy").isValid()); // due to exception, assignment will NOT have occurred.
2934 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2935 QVERIFY(eo->scarceResourceIsDetached()); // should be no other copies of it at this stage.
2936 QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
2940 void tst_qdeclarativeecmascript::propertyChangeSlots()
2942 // ensure that allowable property names are allowed and onPropertyNameChanged slots are generated correctly.
2943 QDeclarativeComponent component(&engine, TEST_FILE("changeslots/propertyChangeSlots.qml"));
2944 QObject *object = component.create();
2945 QVERIFY(object != 0);
2948 // ensure that invalid property names fail properly.
2949 QTest::ignoreMessage(QtWarningMsg, "QDeclarativeComponent: Component is not ready");
2950 QDeclarativeComponent e1(&engine, TEST_FILE("changeslots/propertyChangeSlotErrors.1.qml"));
2951 QString expectedErrorString = e1.url().toString() + QLatin1String(":9:5: Cannot assign to non-existent property \"on_nameWithUnderscoreChanged\"");
2952 QCOMPARE(e1.errors().at(0).toString(), expectedErrorString);
2953 object = e1.create();
2954 QVERIFY(object == 0);
2957 QTest::ignoreMessage(QtWarningMsg, "QDeclarativeComponent: Component is not ready");
2958 QDeclarativeComponent e2(&engine, TEST_FILE("changeslots/propertyChangeSlotErrors.2.qml"));
2959 expectedErrorString = e2.url().toString() + QLatin1String(":9:5: Cannot assign to non-existent property \"on____nameWithUnderscoresChanged\"");
2960 QCOMPARE(e2.errors().at(0).toString(), expectedErrorString);
2961 object = e2.create();
2962 QVERIFY(object == 0);
2965 QTest::ignoreMessage(QtWarningMsg, "QDeclarativeComponent: Component is not ready");
2966 QDeclarativeComponent e3(&engine, TEST_FILE("changeslots/propertyChangeSlotErrors.3.qml"));
2967 expectedErrorString = e3.url().toString() + QLatin1String(":9:5: Cannot assign to non-existent property \"on$NameWithDollarsignChanged\"");
2968 QCOMPARE(e3.errors().at(0).toString(), expectedErrorString);
2969 object = e3.create();
2970 QVERIFY(object == 0);
2973 QTest::ignoreMessage(QtWarningMsg, "QDeclarativeComponent: Component is not ready");
2974 QDeclarativeComponent e4(&engine, TEST_FILE("changeslots/propertyChangeSlotErrors.4.qml"));
2975 expectedErrorString = e4.url().toString() + QLatin1String(":9:5: Cannot assign to non-existent property \"on_6NameWithUnderscoreNumberChanged\"");
2976 QCOMPARE(e4.errors().at(0).toString(), expectedErrorString);
2977 object = e4.create();
2978 QVERIFY(object == 0);
2982 // Ensure that QObject type conversion works on binding assignment
2983 void tst_qdeclarativeecmascript::elementAssign()
2985 QDeclarativeComponent component(&engine, TEST_FILE("elementAssign.qml"));
2987 QObject *object = component.create();
2988 QVERIFY(object != 0);
2990 QCOMPARE(object->property("test").toBool(), true);
2996 void tst_qdeclarativeecmascript::objectPassThroughSignals()
2998 QDeclarativeComponent component(&engine, TEST_FILE("objectsPassThroughSignals.qml"));
3000 QObject *object = component.create();
3001 QVERIFY(object != 0);
3003 QCOMPARE(object->property("test").toBool(), true);
3009 void tst_qdeclarativeecmascript::booleanConversion()
3011 QDeclarativeComponent component(&engine, TEST_FILE("booleanConversion.qml"));
3013 QObject *object = component.create();
3014 QVERIFY(object != 0);
3016 QCOMPARE(object->property("test_true1").toBool(), true);
3017 QCOMPARE(object->property("test_true2").toBool(), true);
3018 QCOMPARE(object->property("test_true3").toBool(), true);
3019 QCOMPARE(object->property("test_true4").toBool(), true);
3020 QCOMPARE(object->property("test_true5").toBool(), true);
3022 QCOMPARE(object->property("test_false1").toBool(), false);
3023 QCOMPARE(object->property("test_false2").toBool(), false);
3024 QCOMPARE(object->property("test_false3").toBool(), false);
3029 // Test that assigning a null object works
3030 // Regressed with: df1788b4dbbb2826ae63f26bdf166342595343f4
3031 void tst_qdeclarativeecmascript::nullObjectBinding()
3033 QDeclarativeComponent component(&engine, TEST_FILE("nullObjectBinding.qml"));
3035 QObject *object = component.create();
3036 QVERIFY(object != 0);
3038 QVERIFY(object->property("test") == QVariant::fromValue((QObject *)0));
3043 // Test that bindings don't evaluate once the engine has been destroyed
3044 void tst_qdeclarativeecmascript::deletedEngine()
3046 QDeclarativeEngine *engine = new QDeclarativeEngine;
3047 QDeclarativeComponent component(engine, TEST_FILE("deletedEngine.qml"));
3049 QObject *object = component.create();
3050 QVERIFY(object != 0);
3052 QCOMPARE(object->property("a").toInt(), 39);
3053 object->setProperty("b", QVariant(9));
3054 QCOMPARE(object->property("a").toInt(), 117);
3058 QCOMPARE(object->property("a").toInt(), 117);
3059 object->setProperty("b", QVariant(10));
3060 QCOMPARE(object->property("a").toInt(), 117);
3065 // Test the crashing part of QTBUG-9705
3066 void tst_qdeclarativeecmascript::libraryScriptAssert()
3068 QDeclarativeComponent component(&engine, TEST_FILE("libraryScriptAssert.qml"));
3070 QObject *object = component.create();
3071 QVERIFY(object != 0);
3076 void tst_qdeclarativeecmascript::variantsAssignedUndefined()
3078 QDeclarativeComponent component(&engine, TEST_FILE("variantsAssignedUndefined.qml"));
3080 QObject *object = component.create();
3081 QVERIFY(object != 0);
3083 QCOMPARE(object->property("test1").toInt(), 10);
3084 QCOMPARE(object->property("test2").toInt(), 11);
3086 object->setProperty("runTest", true);
3088 QCOMPARE(object->property("test1"), QVariant());
3089 QCOMPARE(object->property("test2"), QVariant());
3095 void tst_qdeclarativeecmascript::qtbug_9792()
3097 QDeclarativeComponent component(&engine, TEST_FILE("qtbug_9792.qml"));
3099 QDeclarativeContext *context = new QDeclarativeContext(engine.rootContext());
3101 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create(context));
3102 QVERIFY(object != 0);
3104 QTest::ignoreMessage(QtDebugMsg, "Hello world!");
3105 object->basicSignal();
3109 transientErrorsMsgCount = 0;
3110 QtMsgHandler old = qInstallMsgHandler(transientErrorsMsgHandler);
3112 object->basicSignal();
3114 qInstallMsgHandler(old);
3116 QCOMPARE(transientErrorsMsgCount, 0);
3121 // Verifies that QDeclarativeGuard<>s used in the vmemetaobject are cleaned correctly
3122 void tst_qdeclarativeecmascript::qtcreatorbug_1289()
3124 QDeclarativeComponent component(&engine, TEST_FILE("qtcreatorbug_1289.qml"));
3126 QObject *o = component.create();
3129 QObject *nested = qvariant_cast<QObject *>(o->property("object"));
3130 QVERIFY(nested != 0);
3132 QVERIFY(qvariant_cast<QObject *>(nested->property("nestedObject")) == o);
3135 nested = qvariant_cast<QObject *>(o->property("object"));
3136 QVERIFY(nested == 0);
3138 // If the bug is present, the next line will crash
3142 // Test that we shut down without stupid warnings
3143 void tst_qdeclarativeecmascript::noSpuriousWarningsAtShutdown()
3146 QDeclarativeComponent component(&engine, TEST_FILE("noSpuriousWarningsAtShutdown.qml"));
3148 QObject *o = component.create();
3150 transientErrorsMsgCount = 0;
3151 QtMsgHandler old = qInstallMsgHandler(transientErrorsMsgHandler);
3155 qInstallMsgHandler(old);
3157 QCOMPARE(transientErrorsMsgCount, 0);
3162 QDeclarativeComponent component(&engine, TEST_FILE("noSpuriousWarningsAtShutdown.2.qml"));
3164 QObject *o = component.create();
3166 transientErrorsMsgCount = 0;
3167 QtMsgHandler old = qInstallMsgHandler(transientErrorsMsgHandler);
3171 qInstallMsgHandler(old);
3173 QCOMPARE(transientErrorsMsgCount, 0);
3177 void tst_qdeclarativeecmascript::canAssignNullToQObject()
3180 QDeclarativeComponent component(&engine, TEST_FILE("canAssignNullToQObject.1.qml"));
3182 MyQmlObject *o = qobject_cast<MyQmlObject *>(component.create());
3185 QVERIFY(o->objectProperty() != 0);
3187 o->setProperty("runTest", true);
3189 QVERIFY(o->objectProperty() == 0);
3195 QDeclarativeComponent component(&engine, TEST_FILE("canAssignNullToQObject.2.qml"));
3197 MyQmlObject *o = qobject_cast<MyQmlObject *>(component.create());
3200 QVERIFY(o->objectProperty() == 0);
3206 void tst_qdeclarativeecmascript::functionAssignment_fromBinding()
3208 QDeclarativeComponent component(&engine, TEST_FILE("functionAssignment.1.qml"));
3210 QString url = component.url().toString();
3211 QString warning = url + ":4: Unable to assign a function to a property.";
3212 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
3214 MyQmlObject *o = qobject_cast<MyQmlObject *>(component.create());
3217 QVERIFY(!o->property("a").isValid());
3222 void tst_qdeclarativeecmascript::functionAssignment_fromJS()
3224 QFETCH(QString, triggerProperty);
3226 QDeclarativeComponent component(&engine, TEST_FILE("functionAssignment.2.qml"));
3227 QVERIFY2(component.errorString().isEmpty(), qPrintable(component.errorString()));
3229 MyQmlObject *o = qobject_cast<MyQmlObject *>(component.create());
3231 QVERIFY(!o->property("a").isValid());
3233 o->setProperty("aNumber", QVariant(5));
3234 o->setProperty(triggerProperty.toUtf8().constData(), true);
3235 QCOMPARE(o->property("a"), QVariant(50));
3237 o->setProperty("aNumber", QVariant(10));
3238 QCOMPARE(o->property("a"), QVariant(100));
3243 void tst_qdeclarativeecmascript::functionAssignment_fromJS_data()
3245 QTest::addColumn<QString>("triggerProperty");
3247 QTest::newRow("assign to property") << "assignToProperty";
3248 QTest::newRow("assign to property, from JS file") << "assignToPropertyFromJsFile";
3250 QTest::newRow("assign to value type") << "assignToValueType";
3252 QTest::newRow("use 'this'") << "assignWithThis";
3253 QTest::newRow("use 'this' from JS file") << "assignWithThisFromJsFile";
3256 void tst_qdeclarativeecmascript::functionAssignmentfromJS_invalid()
3258 QDeclarativeComponent component(&engine, TEST_FILE("functionAssignment.2.qml"));
3259 QVERIFY2(component.errorString().isEmpty(), qPrintable(component.errorString()));
3261 MyQmlObject *o = qobject_cast<MyQmlObject *>(component.create());
3263 QVERIFY(!o->property("a").isValid());
3265 o->setProperty("assignFuncWithoutReturn", true);
3266 QVERIFY(!o->property("a").isValid());
3268 QString url = component.url().toString();
3269 QString warning = url + ":67: Unable to assign QString to int";
3270 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
3271 o->setProperty("assignWrongType", true);
3273 warning = url + ":71: Unable to assign QString to int";
3274 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
3275 o->setProperty("assignWrongTypeToValueType", true);
3280 void tst_qdeclarativeecmascript::eval()
3282 QDeclarativeComponent component(&engine, TEST_FILE("eval.qml"));
3284 QObject *o = component.create();
3287 QCOMPARE(o->property("test1").toBool(), true);
3288 QCOMPARE(o->property("test2").toBool(), true);
3289 QCOMPARE(o->property("test3").toBool(), true);
3290 QCOMPARE(o->property("test4").toBool(), true);
3291 QCOMPARE(o->property("test5").toBool(), true);
3296 void tst_qdeclarativeecmascript::function()
3298 QDeclarativeComponent component(&engine, TEST_FILE("function.qml"));
3300 QObject *o = component.create();
3303 QCOMPARE(o->property("test1").toBool(), true);
3304 QCOMPARE(o->property("test2").toBool(), true);
3305 QCOMPARE(o->property("test3").toBool(), true);
3310 // Test the "Qt.include" method
3311 void tst_qdeclarativeecmascript::include()
3313 // Non-library relative include
3315 QDeclarativeComponent component(&engine, TEST_FILE("include.qml"));
3316 QObject *o = component.create();
3319 QCOMPARE(o->property("test0").toInt(), 99);
3320 QCOMPARE(o->property("test1").toBool(), true);
3321 QCOMPARE(o->property("test2").toBool(), true);
3322 QCOMPARE(o->property("test2_1").toBool(), true);
3323 QCOMPARE(o->property("test3").toBool(), true);
3324 QCOMPARE(o->property("test3_1").toBool(), true);
3329 // Library relative include
3331 QDeclarativeComponent component(&engine, TEST_FILE("include_shared.qml"));
3332 QObject *o = component.create();
3335 QCOMPARE(o->property("test0").toInt(), 99);
3336 QCOMPARE(o->property("test1").toBool(), true);
3337 QCOMPARE(o->property("test2").toBool(), true);
3338 QCOMPARE(o->property("test2_1").toBool(), true);
3339 QCOMPARE(o->property("test3").toBool(), true);
3340 QCOMPARE(o->property("test3_1").toBool(), true);
3347 QDeclarativeComponent component(&engine, TEST_FILE("include_callback.qml"));
3348 QObject *o = component.create();
3351 QCOMPARE(o->property("test1").toBool(), true);
3352 QCOMPARE(o->property("test2").toBool(), true);
3353 QCOMPARE(o->property("test3").toBool(), true);
3354 QCOMPARE(o->property("test4").toBool(), true);
3355 QCOMPARE(o->property("test5").toBool(), true);
3356 QCOMPARE(o->property("test6").toBool(), true);
3361 // Including file with ".pragma library"
3363 QDeclarativeComponent component(&engine, TEST_FILE("include_pragma.qml"));
3364 QObject *o = component.create();
3366 QCOMPARE(o->property("test1").toInt(), 100);
3373 TestHTTPServer server(8111);
3374 QVERIFY(server.isValid());
3375 server.serveDirectory(SRCDIR "/data");
3377 QDeclarativeComponent component(&engine, TEST_FILE("include_remote.qml"));
3378 QObject *o = component.create();
3381 QTRY_VERIFY(o->property("done").toBool() == true);
3382 QTRY_VERIFY(o->property("done2").toBool() == true);
3384 QCOMPARE(o->property("test1").toBool(), true);
3385 QCOMPARE(o->property("test2").toBool(), true);
3386 QCOMPARE(o->property("test3").toBool(), true);
3387 QCOMPARE(o->property("test4").toBool(), true);
3388 QCOMPARE(o->property("test5").toBool(), true);
3390 QCOMPARE(o->property("test6").toBool(), true);
3391 QCOMPARE(o->property("test7").toBool(), true);
3392 QCOMPARE(o->property("test8").toBool(), true);
3393 QCOMPARE(o->property("test9").toBool(), true);
3394 QCOMPARE(o->property("test10").toBool(), true);
3401 TestHTTPServer server(8111);
3402 QVERIFY(server.isValid());
3403 server.serveDirectory(SRCDIR "/data");
3405 QDeclarativeComponent component(&engine, TEST_FILE("include_remote_missing.qml"));
3406 QObject *o = component.create();
3409 QTRY_VERIFY(o->property("done").toBool() == true);
3411 QCOMPARE(o->property("test1").toBool(), true);
3412 QCOMPARE(o->property("test2").toBool(), true);
3413 QCOMPARE(o->property("test3").toBool(), true);
3419 void tst_qdeclarativeecmascript::qtbug_10696()
3421 QDeclarativeComponent component(&engine, TEST_FILE("qtbug_10696.qml"));
3422 QObject *o = component.create();
3427 void tst_qdeclarativeecmascript::qtbug_11606()
3429 QDeclarativeComponent component(&engine, TEST_FILE("qtbug_11606.qml"));
3430 QObject *o = component.create();
3432 QCOMPARE(o->property("test").toBool(), true);
3436 void tst_qdeclarativeecmascript::qtbug_11600()
3438 QDeclarativeComponent component(&engine, TEST_FILE("qtbug_11600.qml"));
3439 QObject *o = component.create();
3441 QCOMPARE(o->property("test").toBool(), true);
3445 // Reading and writing non-scriptable properties should fail
3446 void tst_qdeclarativeecmascript::nonscriptable()
3448 QDeclarativeComponent component(&engine, TEST_FILE("nonscriptable.qml"));
3449 QObject *o = component.create();
3451 QCOMPARE(o->property("readOk").toBool(), true);
3452 QCOMPARE(o->property("writeOk").toBool(), true);
3456 // deleteLater() should not be callable from QML
3457 void tst_qdeclarativeecmascript::deleteLater()
3459 QDeclarativeComponent component(&engine, TEST_FILE("deleteLater.qml"));
3460 QObject *o = component.create();
3462 QCOMPARE(o->property("test").toBool(), true);
3466 void tst_qdeclarativeecmascript::in()
3468 QDeclarativeComponent component(&engine, TEST_FILE("in.qml"));
3469 QObject *o = component.create();
3471 QCOMPARE(o->property("test1").toBool(), true);
3472 QCOMPARE(o->property("test2").toBool(), true);
3476 void tst_qdeclarativeecmascript::sharedAttachedObject()
3478 QDeclarativeComponent component(&engine, TEST_FILE("sharedAttachedObject.qml"));
3479 QObject *o = component.create();
3481 QCOMPARE(o->property("test1").toBool(), true);
3482 QCOMPARE(o->property("test2").toBool(), true);
3487 void tst_qdeclarativeecmascript::objectName()
3489 QDeclarativeComponent component(&engine, TEST_FILE("objectName.qml"));
3490 QObject *o = component.create();
3493 QCOMPARE(o->property("test1").toString(), QString("hello"));
3494 QCOMPARE(o->property("test2").toString(), QString("ell"));
3496 o->setObjectName("world");
3498 QCOMPARE(o->property("test1").toString(), QString("world"));
3499 QCOMPARE(o->property("test2").toString(), QString("orl"));
3504 void tst_qdeclarativeecmascript::writeRemovesBinding()
3506 QDeclarativeComponent component(&engine, TEST_FILE("writeRemovesBinding.qml"));
3507 QObject *o = component.create();
3510 QCOMPARE(o->property("test").toBool(), true);
3515 // Test bindings assigned to alias properties actually assign to the alias' target
3516 void tst_qdeclarativeecmascript::aliasBindingsAssignCorrectly()
3518 QDeclarativeComponent component(&engine, TEST_FILE("aliasBindingsAssignCorrectly.qml"));
3519 QObject *o = component.create();
3522 QCOMPARE(o->property("test").toBool(), true);
3527 // Test bindings assigned to alias properties override a binding on the target (QTBUG-13719)
3528 void tst_qdeclarativeecmascript::aliasBindingsOverrideTarget()
3531 QDeclarativeComponent component(&engine, TEST_FILE("aliasBindingsOverrideTarget.qml"));
3532 QObject *o = component.create();
3535 QCOMPARE(o->property("test").toBool(), true);
3541 QDeclarativeComponent component(&engine, TEST_FILE("aliasBindingsOverrideTarget.2.qml"));
3542 QObject *o = component.create();
3545 QCOMPARE(o->property("test").toBool(), true);
3551 QDeclarativeComponent component(&engine, TEST_FILE("aliasBindingsOverrideTarget.3.qml"));
3552 QObject *o = component.create();
3555 QCOMPARE(o->property("test").toBool(), true);
3561 // Test that writes to alias properties override bindings on the alias target (QTBUG-13719)
3562 void tst_qdeclarativeecmascript::aliasWritesOverrideBindings()
3565 QDeclarativeComponent component(&engine, TEST_FILE("aliasWritesOverrideBindings.qml"));
3566 QObject *o = component.create();
3569 QCOMPARE(o->property("test").toBool(), true);
3575 QDeclarativeComponent component(&engine, TEST_FILE("aliasWritesOverrideBindings.2.qml"));
3576 QObject *o = component.create();
3579 QCOMPARE(o->property("test").toBool(), true);
3585 QDeclarativeComponent component(&engine, TEST_FILE("aliasWritesOverrideBindings.3.qml"));
3586 QObject *o = component.create();
3589 QCOMPARE(o->property("test").toBool(), true);
3595 // Allow an alais to a composite element
3597 void tst_qdeclarativeecmascript::aliasToCompositeElement()
3599 QDeclarativeComponent component(&engine, TEST_FILE("aliasToCompositeElement.qml"));
3601 QObject *object = component.create();
3602 QVERIFY(object != 0);
3607 void tst_qdeclarativeecmascript::revisionErrors()
3610 QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevisionErrors.qml"));
3611 QString url = component.url().toString();
3613 QString warning1 = url + ":8: ReferenceError: Can't find variable: prop2";
3614 QString warning2 = url + ":11: ReferenceError: Can't find variable: prop2";
3615 QString warning3 = url + ":13: ReferenceError: Can't find variable: method2";
3617 QTest::ignoreMessage(QtWarningMsg, warning1.toLatin1().constData());
3618 QTest::ignoreMessage(QtWarningMsg, warning2.toLatin1().constData());
3619 QTest::ignoreMessage(QtWarningMsg, warning3.toLatin1().constData());
3620 MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create());
3621 QVERIFY(object != 0);
3625 QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevisionErrors2.qml"));
3626 QString url = component.url().toString();
3628 // MyRevisionedSubclass 1.0 uses MyRevisionedClass revision 0
3629 // method2, prop2 from MyRevisionedClass not available
3630 // method4, prop4 from MyRevisionedSubclass not available
3631 QString warning1 = url + ":8: ReferenceError: Can't find variable: prop2";
3632 QString warning2 = url + ":14: ReferenceError: Can't find variable: prop2";
3633 QString warning3 = url + ":10: ReferenceError: Can't find variable: prop4";
3634 QString warning4 = url + ":16: ReferenceError: Can't find variable: prop4";
3635 QString warning5 = url + ":20: ReferenceError: Can't find variable: method2";
3637 QTest::ignoreMessage(QtWarningMsg, warning1.toLatin1().constData());
3638 QTest::ignoreMessage(QtWarningMsg, warning2.toLatin1().constData());
3639 QTest::ignoreMessage(QtWarningMsg, warning3.toLatin1().constData());
3640 QTest::ignoreMessage(QtWarningMsg, warning4.toLatin1().constData());
3641 QTest::ignoreMessage(QtWarningMsg, warning5.toLatin1().constData());
3642 MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create());
3643 QVERIFY(object != 0);
3647 QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevisionErrors3.qml"));
3648 QString url = component.url().toString();
3650 // MyRevisionedSubclass 1.1 uses MyRevisionedClass revision 1
3651 // All properties/methods available, except MyRevisionedBaseClassUnregistered rev 1
3652 QString warning1 = url + ":30: ReferenceError: Can't find variable: methodD";
3653 QString warning2 = url + ":10: ReferenceError: Can't find variable: propD";
3654 QString warning3 = url + ":20: ReferenceError: Can't find variable: propD";
3655 QTest::ignoreMessage(QtWarningMsg, warning1.toLatin1().constData());
3656 QTest::ignoreMessage(QtWarningMsg, warning2.toLatin1().constData());
3657 QTest::ignoreMessage(QtWarningMsg, warning3.toLatin1().constData());
3658 MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create());
3659 QVERIFY(object != 0);
3664 void tst_qdeclarativeecmascript::revision()
3667 QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevision.qml"));
3668 QString url = component.url().toString();
3670 MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create());
3671 QVERIFY(object != 0);
3675 QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevision2.qml"));
3676 QString url = component.url().toString();
3678 MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create());
3679 QVERIFY(object != 0);
3683 QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevision3.qml"));
3684 QString url = component.url().toString();
3686 MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create());
3687 QVERIFY(object != 0);
3690 // Test that non-root classes can resolve revisioned methods
3692 QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevision4.qml"));
3694 QObject *object = component.create();
3695 QVERIFY(object != 0);
3696 QCOMPARE(object->property("test").toReal(), 11.);
3701 void tst_qdeclarativeecmascript::realToInt()
3703 QDeclarativeComponent component(&engine, TEST_FILE("realToInt.qml"));
3704 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
3705 QVERIFY(object != 0);
3707 QMetaObject::invokeMethod(object, "test1");
3708 QCOMPARE(object->value(), int(4));
3709 QMetaObject::invokeMethod(object, "test2");
3710 QCOMPARE(object->value(), int(8));
3712 void tst_qdeclarativeecmascript::dynamicString()
3714 QDeclarativeComponent component(&engine, TEST_FILE("dynamicString.qml"));
3715 QObject *object = component.create();
3716 QVERIFY(object != 0);
3717 QCOMPARE(object->property("stringProperty").toString(),
3718 QString::fromLatin1("string:Hello World false:0 true:1 uint32:100 int32:-100 double:3.14159 date:2011-02-11 05::30:50!"));
3721 QTEST_MAIN(tst_qdeclarativeecmascript)
3723 #include "tst_qdeclarativeecmascript.moc"