1 /****************************************************************************
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
7 ** This file is part of the test suite of the Qt Toolkit.
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** GNU Lesser General Public License Usage
11 ** This file may be used under the terms of the GNU Lesser General Public
12 ** License version 2.1 as published by the Free Software Foundation and
13 ** appearing in the file LICENSE.LGPL included in the packaging of this
14 ** file. Please review the following information to ensure the GNU Lesser
15 ** General Public License version 2.1 requirements will be met:
16 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
18 ** In addition, as a special exception, Nokia gives you certain additional
19 ** rights. These rights are described in the Nokia Qt LGPL Exception
20 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
22 ** GNU General Public License Usage
23 ** Alternatively, this file may be used under the terms of the GNU General
24 ** Public License version 3.0 as published by the Free Software Foundation
25 ** and appearing in the file LICENSE.GPL included in the packaging of this
26 ** file. Please review the following information to ensure the GNU General
27 ** Public License version 3.0 requirements will be met:
28 ** http://www.gnu.org/copyleft/gpl.html.
31 ** Alternatively, this file may be used in accordance with the terms and
32 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
42 #include <QtDeclarative/qdeclarativecomponent.h>
43 #include <QtDeclarative/qdeclarativeengine.h>
44 #include <QtDeclarative/qdeclarativeexpression.h>
45 #include <QtDeclarative/qdeclarativecontext.h>
46 #include <QtCore/qfileinfo.h>
47 #include <QtCore/qdebug.h>
48 #include <QtDeclarative/private/qdeclarativeguard_p.h>
49 #include <QtCore/qdir.h>
50 #include <QtCore/qnumeric.h>
51 #include <private/qdeclarativeengine_p.h>
52 #include <private/qscriptdeclarativeclass_p.h>
53 #include "testtypes.h"
54 #include "testhttpserver.h"
55 #include "../../../shared/util.h"
58 // In Symbian OS test data is located in applications private dir
63 This test covers evaluation of ECMAScript expressions and bindings from within
64 QML. This does not include static QML language issues.
66 Static QML language issues are covered in qmllanguage
68 inline QUrl TEST_FILE(const QString &filename)
70 QFileInfo fileInfo(__FILE__);
71 return QUrl::fromLocalFile(fileInfo.absoluteDir().filePath("data/" + filename));
74 inline QUrl TEST_FILE(const char *filename)
76 return TEST_FILE(QLatin1String(filename));
79 class tst_qdeclarativeecmascript : public QObject
83 tst_qdeclarativeecmascript() {}
87 void assignBasicTypes();
88 void idShortcutInvalidates();
89 void boolPropertiesEvaluateAsBool();
91 void signalAssignment();
93 void basicExpressions();
94 void basicExpressions_data();
95 void arrayExpressions();
96 void contextPropertiesTriggerReeval();
97 void objectPropertiesTriggerReeval();
98 void deferredProperties();
99 void deferredPropertiesErrors();
100 void extensionObjects();
101 void overrideExtensionProperties();
102 void attachedProperties();
104 void valueTypeFunctions();
105 void constantsOverrideBindings();
106 void outerBindingOverridesInnerBinding();
107 void aliasPropertyAndBinding();
108 void nonExistentAttachedObject();
111 void signalParameterTypes();
112 void objectsCompareAsEqual();
113 void dynamicCreation_data();
114 void dynamicCreation();
115 void dynamicDestruction();
116 void objectToString();
117 void selfDeletingBinding();
118 void extendedObjectPropertyLookup();
120 void functionErrors();
121 void propertyAssignmentErrors();
122 void signalTriggeredBindings();
123 void listProperties();
124 void exceptionClearsOnReeval();
125 void exceptionSlotProducesWarning();
126 void exceptionBindingProducesWarning();
127 void transientErrors();
128 void shutdownErrors();
129 void compositePropertyType();
131 void undefinedResetsProperty();
132 void listToVariant();
133 void multiEngineObject();
134 void deletedObject();
135 void attachedPropertyScope();
136 void scriptConnect();
137 void scriptDisconnect();
139 void cppOwnershipReturnValue();
140 void ownershipCustomReturnValue();
141 void qlistqobjectMethods();
142 void strictlyEquals();
144 void numberAssignment();
145 void propertySplicing();
146 void signalWithUnknownTypes();
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 bindings that indirectly cause their own deletion work.
1147 This test is best run under valgrind to ensure no invalid memory access occur.
1149 void tst_qdeclarativeecmascript::selfDeletingBinding()
1152 QDeclarativeComponent component(&engine, TEST_FILE("selfDeletingBinding.qml"));
1153 QObject *object = component.create();
1154 QVERIFY(object != 0);
1155 object->setProperty("triggerDelete", true);
1160 QDeclarativeComponent component(&engine, TEST_FILE("selfDeletingBinding.2.qml"));
1161 QObject *object = component.create();
1162 QVERIFY(object != 0);
1163 object->setProperty("triggerDelete", true);
1169 Test that extended object properties can be accessed.
1171 This test a regression where this used to crash. The issue was specificially
1172 for extended objects that did not include a synthesized meta object (so non-root
1173 and no synthesiszed properties).
1175 void tst_qdeclarativeecmascript::extendedObjectPropertyLookup()
1177 QDeclarativeComponent component(&engine, TEST_FILE("extendedObjectPropertyLookup.qml"));
1178 QObject *object = component.create();
1179 QVERIFY(object != 0);
1184 Test file/lineNumbers for binding/Script errors.
1186 void tst_qdeclarativeecmascript::scriptErrors()
1188 QDeclarativeComponent component(&engine, TEST_FILE("scriptErrors.qml"));
1189 QString url = component.url().toString();
1191 QString warning1 = url.left(url.length() - 3) + "js:2: Error: Invalid write to global property \"a\"";
1192 QString warning2 = url + ":5: ReferenceError: Can't find variable: a";
1193 QString warning3 = url.left(url.length() - 3) + "js:4: Error: Invalid write to global property \"a\"";
1194 QString warning4 = url + ":10: ReferenceError: Can't find variable: a";
1195 QString warning5 = url + ":8: ReferenceError: Can't find variable: a";
1196 QString warning6 = url + ":7: Unable to assign [undefined] to int x";
1197 QString warning7 = url + ":12: Error: Cannot assign to read-only property \"trueProperty\"";
1198 QString warning8 = url + ":13: Error: Cannot assign to non-existent property \"fakeProperty\"";
1200 QTest::ignoreMessage(QtWarningMsg, warning1.toLatin1().constData());
1201 QTest::ignoreMessage(QtWarningMsg, warning2.toLatin1().constData());
1202 QTest::ignoreMessage(QtWarningMsg, warning3.toLatin1().constData());
1203 QTest::ignoreMessage(QtWarningMsg, warning5.toLatin1().constData());
1204 QTest::ignoreMessage(QtWarningMsg, warning6.toLatin1().constData());
1205 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
1206 QVERIFY(object != 0);
1208 QTest::ignoreMessage(QtWarningMsg, warning4.toLatin1().constData());
1209 emit object->basicSignal();
1211 QTest::ignoreMessage(QtWarningMsg, warning7.toLatin1().constData());
1212 emit object->anotherBasicSignal();
1214 QTest::ignoreMessage(QtWarningMsg, warning8.toLatin1().constData());
1215 emit object->thirdBasicSignal();
1221 Test file/lineNumbers for inline functions.
1223 void tst_qdeclarativeecmascript::functionErrors()
1225 QDeclarativeComponent component(&engine, TEST_FILE("functionErrors.qml"));
1226 QString url = component.url().toString();
1228 QString warning = url + ":5: Error: Invalid write to global property \"a\"";
1230 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
1232 QObject *object = component.create();
1233 QVERIFY(object != 0);
1236 // test that if an exception occurs while invoking js function from cpp, it is reported as expected.
1237 QDeclarativeComponent componentTwo(&engine, TEST_FILE("scarceresources/scarceResourceFunctionFail.qml"));
1238 url = componentTwo.url().toString();
1239 object = componentTwo.create();
1240 QVERIFY(object != 0);
1242 QString srpname = object->property("srp_name").toString();
1244 warning = url + QLatin1String(":17: TypeError: Property 'scarceResource' of object ") + srpname +
1245 QLatin1String(" is not a function");
1246 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData()); // we expect a meaningful warning to be printed.
1247 QMetaObject::invokeMethod(object, "retrieveScarceResource");
1252 Test various errors that can occur when assigning a property from script
1254 void tst_qdeclarativeecmascript::propertyAssignmentErrors()
1256 QDeclarativeComponent component(&engine, TEST_FILE("propertyAssignmentErrors.qml"));
1258 QString url = component.url().toString();
1260 QObject *object = component.create();
1261 QVERIFY(object != 0);
1263 QCOMPARE(object->property("test1").toBool(), true);
1264 QCOMPARE(object->property("test2").toBool(), true);
1270 Test bindings still work when the reeval is triggered from within
1273 void tst_qdeclarativeecmascript::signalTriggeredBindings()
1275 QDeclarativeComponent component(&engine, TEST_FILE("signalTriggeredBindings.qml"));
1276 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1277 QVERIFY(object != 0);
1279 QCOMPARE(object->property("base").toReal(), 50.);
1280 QCOMPARE(object->property("test1").toReal(), 50.);
1281 QCOMPARE(object->property("test2").toReal(), 50.);
1283 object->basicSignal();
1285 QCOMPARE(object->property("base").toReal(), 200.);
1286 QCOMPARE(object->property("test1").toReal(), 200.);
1287 QCOMPARE(object->property("test2").toReal(), 200.);
1289 object->argumentSignal(10, QString(), 10, MyQmlObject::EnumValue4, Qt::RightButton);
1291 QCOMPARE(object->property("base").toReal(), 400.);
1292 QCOMPARE(object->property("test1").toReal(), 400.);
1293 QCOMPARE(object->property("test2").toReal(), 400.);
1299 Test that list properties can be iterated from ECMAScript
1301 void tst_qdeclarativeecmascript::listProperties()
1303 QDeclarativeComponent component(&engine, TEST_FILE("listProperties.qml"));
1304 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1305 QVERIFY(object != 0);
1307 QCOMPARE(object->property("test1").toInt(), 21);
1308 QCOMPARE(object->property("test2").toInt(), 2);
1309 QCOMPARE(object->property("test3").toBool(), true);
1310 QCOMPARE(object->property("test4").toBool(), true);
1315 void tst_qdeclarativeecmascript::exceptionClearsOnReeval()
1317 QDeclarativeComponent component(&engine, TEST_FILE("exceptionClearsOnReeval.qml"));
1318 QString url = component.url().toString();
1320 QString warning = url + ":4: TypeError: Cannot read property 'objectProperty' of null";
1322 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
1323 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1324 QVERIFY(object != 0);
1326 QCOMPARE(object->property("test").toBool(), false);
1328 MyQmlObject object2;
1329 MyQmlObject object3;
1330 object2.setObjectProperty(&object3);
1331 object->setObjectProperty(&object2);
1333 QCOMPARE(object->property("test").toBool(), true);
1338 void tst_qdeclarativeecmascript::exceptionSlotProducesWarning()
1340 QDeclarativeComponent component(&engine, TEST_FILE("exceptionProducesWarning.qml"));
1341 QString url = component.url().toString();
1343 QString warning = component.url().toString() + ":6: Error: JS exception";
1345 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
1346 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1347 QVERIFY(object != 0);
1351 void tst_qdeclarativeecmascript::exceptionBindingProducesWarning()
1353 QDeclarativeComponent component(&engine, TEST_FILE("exceptionProducesWarning2.qml"));
1354 QString url = component.url().toString();
1356 QString warning = component.url().toString() + ":5: Error: JS exception";
1358 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
1359 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1360 QVERIFY(object != 0);
1364 static int transientErrorsMsgCount = 0;
1365 static void transientErrorsMsgHandler(QtMsgType, const char *)
1367 ++transientErrorsMsgCount;
1370 // Check that transient binding errors are not displayed
1371 void tst_qdeclarativeecmascript::transientErrors()
1374 QDeclarativeComponent component(&engine, TEST_FILE("transientErrors.qml"));
1376 transientErrorsMsgCount = 0;
1377 QtMsgHandler old = qInstallMsgHandler(transientErrorsMsgHandler);
1379 QObject *object = component.create();
1380 QVERIFY(object != 0);
1382 qInstallMsgHandler(old);
1384 QCOMPARE(transientErrorsMsgCount, 0);
1389 // One binding erroring multiple times, but then resolving
1391 QDeclarativeComponent component(&engine, TEST_FILE("transientErrors.2.qml"));
1393 transientErrorsMsgCount = 0;
1394 QtMsgHandler old = qInstallMsgHandler(transientErrorsMsgHandler);
1396 QObject *object = component.create();
1397 QVERIFY(object != 0);
1399 qInstallMsgHandler(old);
1401 QCOMPARE(transientErrorsMsgCount, 0);
1407 // Check that errors during shutdown are minimized
1408 void tst_qdeclarativeecmascript::shutdownErrors()
1410 QDeclarativeComponent component(&engine, TEST_FILE("shutdownErrors.qml"));
1411 QObject *object = component.create();
1412 QVERIFY(object != 0);
1414 transientErrorsMsgCount = 0;
1415 QtMsgHandler old = qInstallMsgHandler(transientErrorsMsgHandler);
1419 qInstallMsgHandler(old);
1420 QCOMPARE(transientErrorsMsgCount, 0);
1423 void tst_qdeclarativeecmascript::compositePropertyType()
1425 QDeclarativeComponent component(&engine, TEST_FILE("compositePropertyType.qml"));
1426 QTest::ignoreMessage(QtDebugMsg, "hello world");
1427 QObject *object = qobject_cast<QObject *>(component.create());
1432 void tst_qdeclarativeecmascript::jsObject()
1434 QDeclarativeComponent component(&engine, TEST_FILE("jsObject.qml"));
1435 QObject *object = component.create();
1436 QVERIFY(object != 0);
1438 QCOMPARE(object->property("test").toInt(), 92);
1443 void tst_qdeclarativeecmascript::undefinedResetsProperty()
1446 QDeclarativeComponent component(&engine, TEST_FILE("undefinedResetsProperty.qml"));
1447 QObject *object = component.create();
1448 QVERIFY(object != 0);
1450 QCOMPARE(object->property("resettableProperty").toInt(), 92);
1452 object->setProperty("setUndefined", true);
1454 QCOMPARE(object->property("resettableProperty").toInt(), 13);
1456 object->setProperty("setUndefined", false);
1458 QCOMPARE(object->property("resettableProperty").toInt(), 92);
1463 QDeclarativeComponent component(&engine, TEST_FILE("undefinedResetsProperty.2.qml"));
1464 QObject *object = component.create();
1465 QVERIFY(object != 0);
1467 QCOMPARE(object->property("resettableProperty").toInt(), 19);
1469 QMetaObject::invokeMethod(object, "doReset");
1471 QCOMPARE(object->property("resettableProperty").toInt(), 13);
1478 void tst_qdeclarativeecmascript::bug1()
1480 QDeclarativeComponent component(&engine, TEST_FILE("bug.1.qml"));
1481 QObject *object = component.create();
1482 QVERIFY(object != 0);
1484 QCOMPARE(object->property("test").toInt(), 14);
1486 object->setProperty("a", 11);
1488 QCOMPARE(object->property("test").toInt(), 3);
1490 object->setProperty("b", true);
1492 QCOMPARE(object->property("test").toInt(), 9);
1497 void tst_qdeclarativeecmascript::bug2()
1499 QDeclarativeComponent component(&engine);
1500 component.setData("import Qt.test 1.0;\nQPlainTextEdit { width: 100 }", QUrl());
1502 QObject *object = component.create();
1503 QVERIFY(object != 0);
1508 // Don't crash in createObject when the component has errors.
1509 void tst_qdeclarativeecmascript::dynamicCreationCrash()
1511 QDeclarativeComponent component(&engine, TEST_FILE("dynamicCreation.qml"));
1512 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1513 QVERIFY(object != 0);
1515 QTest::ignoreMessage(QtWarningMsg, "QDeclarativeComponent: Component is not ready");
1516 QMetaObject::invokeMethod(object, "dontCrash");
1517 QObject *created = object->objectProperty();
1518 QVERIFY(created == 0);
1524 void tst_qdeclarativeecmascript::regExpBug()
1526 QDeclarativeComponent component(&engine, TEST_FILE("regExp.qml"));
1527 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1528 QVERIFY(object != 0);
1529 QCOMPARE(object->regExp().pattern(), QLatin1String("[a-zA-z]"));
1533 static inline bool evaluate_error(QV8Engine *engine, v8::Handle<v8::Object> o, const char *source)
1535 QString functionSource = QLatin1String("(function(object) { return ") +
1536 QLatin1String(source) + QLatin1String(" })");
1538 v8::Local<v8::Script> program = v8::Script::Compile(engine->toString(functionSource));
1541 v8::Handle<v8::Function> function = v8::Handle<v8::Function>::Cast(program->Run());
1542 if (function.IsEmpty())
1544 v8::Handle<v8::Value> args[] = { o };
1545 function->Call(engine->global(), 1, args);
1546 return tc.HasCaught();
1549 static inline bool evaluate_value(QV8Engine *engine, v8::Handle<v8::Object> o,
1550 const char *source, v8::Handle<v8::Value> result)
1552 QString functionSource = QLatin1String("(function(object) { return ") +
1553 QLatin1String(source) + QLatin1String(" })");
1555 v8::Local<v8::Script> program = v8::Script::Compile(engine->toString(functionSource));
1558 v8::Handle<v8::Function> function = v8::Handle<v8::Function>::Cast(program->Run());
1559 if (function.IsEmpty())
1561 v8::Handle<v8::Value> args[] = { o };
1563 v8::Handle<v8::Value> value = function->Call(engine->global(), 1, args);
1568 return value->StrictEquals(result);
1571 static inline v8::Handle<v8::Value> evaluate(QV8Engine *engine, v8::Handle<v8::Object> o,
1574 QString functionSource = QLatin1String("(function(object) { return ") +
1575 QLatin1String(source) + QLatin1String(" })");
1577 v8::Local<v8::Script> program = v8::Script::Compile(engine->toString(functionSource));
1579 return v8::Handle<v8::Value>();
1580 v8::Handle<v8::Function> function = v8::Handle<v8::Function>::Cast(program->Run());
1581 if (function.IsEmpty())
1582 return v8::Handle<v8::Value>();
1583 v8::Handle<v8::Value> args[] = { o };
1585 v8::Handle<v8::Value> value = function->Call(engine->global(), 1, args);
1588 return v8::Handle<v8::Value>();
1592 #define EVALUATE_ERROR(source) evaluate_error(engine, object, source)
1593 #define EVALUATE_VALUE(source, result) evaluate_value(engine, object, source, result)
1594 #define EVALUATE(source) evaluate(engine, object, source)
1596 void tst_qdeclarativeecmascript::callQtInvokables()
1598 MyInvokableObject o;
1600 QDeclarativeEngine qmlengine;
1601 QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(&qmlengine);
1603 QV8Engine *engine = &ep->v8engine;
1605 v8::HandleScope handle_scope;
1606 v8::Context::Scope scope(engine->context());
1608 v8::Local<v8::Object> object = engine->newQObject(&o)->ToObject();
1610 // Non-existent methods
1612 QVERIFY(EVALUATE_ERROR("object.method_nonexistent()"));
1613 QCOMPARE(o.error(), false);
1614 QCOMPARE(o.invoked(), -1);
1615 QCOMPARE(o.actuals().count(), 0);
1618 QVERIFY(EVALUATE_ERROR("object.method_nonexistent(10, 11)"));
1619 QCOMPARE(o.error(), false);
1620 QCOMPARE(o.invoked(), -1);
1621 QCOMPARE(o.actuals().count(), 0);
1623 // Insufficient arguments
1625 QVERIFY(EVALUATE_ERROR("object.method_int()"));
1626 QCOMPARE(o.error(), false);
1627 QCOMPARE(o.invoked(), -1);
1628 QCOMPARE(o.actuals().count(), 0);
1631 QVERIFY(EVALUATE_ERROR("object.method_intint(10)"));
1632 QCOMPARE(o.error(), false);
1633 QCOMPARE(o.invoked(), -1);
1634 QCOMPARE(o.actuals().count(), 0);
1636 // Excessive arguments
1638 QVERIFY(EVALUATE_VALUE("object.method_int(10, 11)", v8::Undefined()));
1639 QCOMPARE(o.error(), false);
1640 QCOMPARE(o.invoked(), 8);
1641 QCOMPARE(o.actuals().count(), 1);
1642 QCOMPARE(o.actuals().at(0), QVariant(10));
1645 QVERIFY(EVALUATE_VALUE("object.method_intint(10, 11, 12)", v8::Undefined()));
1646 QCOMPARE(o.error(), false);
1647 QCOMPARE(o.invoked(), 9);
1648 QCOMPARE(o.actuals().count(), 2);
1649 QCOMPARE(o.actuals().at(0), QVariant(10));
1650 QCOMPARE(o.actuals().at(1), QVariant(11));
1652 // Test return types
1654 QVERIFY(EVALUATE_VALUE("object.method_NoArgs()", v8::Undefined()));
1655 QCOMPARE(o.error(), false);
1656 QCOMPARE(o.invoked(), 0);
1657 QCOMPARE(o.actuals().count(), 0);
1660 QVERIFY(EVALUATE_VALUE("object.method_NoArgs_int()", v8::Integer::New(6)));
1661 QCOMPARE(o.error(), false);
1662 QCOMPARE(o.invoked(), 1);
1663 QCOMPARE(o.actuals().count(), 0);
1666 QVERIFY(EVALUATE_VALUE("object.method_NoArgs_real()", v8::Number::New(19.75)));
1667 QCOMPARE(o.error(), false);
1668 QCOMPARE(o.invoked(), 2);
1669 QCOMPARE(o.actuals().count(), 0);
1673 v8::Handle<v8::Value> ret = EVALUATE("object.method_NoArgs_QPointF()");
1674 QVERIFY(!ret.IsEmpty());
1675 QCOMPARE(engine->toVariant(ret, -1), QVariant(QPointF(123, 4.5)));
1676 QCOMPARE(o.error(), false);
1677 QCOMPARE(o.invoked(), 3);
1678 QCOMPARE(o.actuals().count(), 0);
1683 v8::Handle<v8::Value> ret = EVALUATE("object.method_NoArgs_QObject()");
1684 QCOMPARE(engine->toQObject(ret), (QObject *)&o);
1685 QCOMPARE(o.error(), false);
1686 QCOMPARE(o.invoked(), 4);
1687 QCOMPARE(o.actuals().count(), 0);
1691 QVERIFY(EVALUATE_VALUE("object.method_NoArgs_unknown()", v8::Undefined()));
1692 QCOMPARE(o.error(), false);
1693 QCOMPARE(o.invoked(), 5);
1694 QCOMPARE(o.actuals().count(), 0);
1696 // XXX enable once qml/qtscript integration is implemented
1700 v8::Handle<v8::Value> ret = EVALUATE("object.method_NoArgs_QScriptValue()");
1701 QVERIFY(ret->IsString());
1702 QCOMPARE(engine->toString(ret), QString("Hello world"));
1703 QCOMPARE(o.error(), false);
1704 QCOMPARE(o.invoked(), 6);
1705 QCOMPARE(o.actuals().count(), 0);
1710 QVERIFY(EVALUATE_VALUE("object.method_NoArgs_QVariant()", engine->toString("QML rocks")));
1711 QCOMPARE(o.error(), false);
1712 QCOMPARE(o.invoked(), 7);
1713 QCOMPARE(o.actuals().count(), 0);
1717 QVERIFY(EVALUATE_VALUE("object.method_int(94)", v8::Undefined()));
1718 QCOMPARE(o.error(), false);
1719 QCOMPARE(o.invoked(), 8);
1720 QCOMPARE(o.actuals().count(), 1);
1721 QCOMPARE(o.actuals().at(0), QVariant(94));
1724 QVERIFY(EVALUATE_VALUE("object.method_int(\"94\")", v8::Undefined()));
1725 QCOMPARE(o.error(), false);
1726 QCOMPARE(o.invoked(), 8);
1727 QCOMPARE(o.actuals().count(), 1);
1728 QCOMPARE(o.actuals().at(0), QVariant(94));
1731 QVERIFY(EVALUATE_VALUE("object.method_int(\"not a number\")", v8::Undefined()));
1732 QCOMPARE(o.error(), false);
1733 QCOMPARE(o.invoked(), 8);
1734 QCOMPARE(o.actuals().count(), 1);
1735 QCOMPARE(o.actuals().at(0), QVariant(0));
1738 QVERIFY(EVALUATE_VALUE("object.method_int(null)", v8::Undefined()));
1739 QCOMPARE(o.error(), false);
1740 QCOMPARE(o.invoked(), 8);
1741 QCOMPARE(o.actuals().count(), 1);
1742 QCOMPARE(o.actuals().at(0), QVariant(0));
1745 QVERIFY(EVALUATE_VALUE("object.method_int(undefined)", v8::Undefined()));
1746 QCOMPARE(o.error(), false);
1747 QCOMPARE(o.invoked(), 8);
1748 QCOMPARE(o.actuals().count(), 1);
1749 QCOMPARE(o.actuals().at(0), QVariant(0));
1752 QVERIFY(EVALUATE_VALUE("object.method_int(object)", v8::Undefined()));
1753 QCOMPARE(o.error(), false);
1754 QCOMPARE(o.invoked(), 8);
1755 QCOMPARE(o.actuals().count(), 1);
1756 QCOMPARE(o.actuals().at(0), QVariant(0));
1759 QVERIFY(EVALUATE_VALUE("object.method_intint(122, 9)", v8::Undefined()));
1760 QCOMPARE(o.error(), false);
1761 QCOMPARE(o.invoked(), 9);
1762 QCOMPARE(o.actuals().count(), 2);
1763 QCOMPARE(o.actuals().at(0), QVariant(122));
1764 QCOMPARE(o.actuals().at(1), QVariant(9));
1767 QVERIFY(EVALUATE_VALUE("object.method_real(94.3)", v8::Undefined()));
1768 QCOMPARE(o.error(), false);
1769 QCOMPARE(o.invoked(), 10);
1770 QCOMPARE(o.actuals().count(), 1);
1771 QCOMPARE(o.actuals().at(0), QVariant(94.3));
1774 QVERIFY(EVALUATE_VALUE("object.method_real(\"94.3\")", v8::Undefined()));
1775 QCOMPARE(o.error(), false);
1776 QCOMPARE(o.invoked(), 10);
1777 QCOMPARE(o.actuals().count(), 1);
1778 QCOMPARE(o.actuals().at(0), QVariant(94.3));
1781 QVERIFY(EVALUATE_VALUE("object.method_real(\"not a number\")", v8::Undefined()));
1782 QCOMPARE(o.error(), false);
1783 QCOMPARE(o.invoked(), 10);
1784 QCOMPARE(o.actuals().count(), 1);
1785 QVERIFY(qIsNaN(o.actuals().at(0).toDouble()));
1788 QVERIFY(EVALUATE_VALUE("object.method_real(null)", v8::Undefined()));
1789 QCOMPARE(o.error(), false);
1790 QCOMPARE(o.invoked(), 10);
1791 QCOMPARE(o.actuals().count(), 1);
1792 QCOMPARE(o.actuals().at(0), QVariant(0));
1795 QVERIFY(EVALUATE_VALUE("object.method_real(undefined)", v8::Undefined()));
1796 QCOMPARE(o.error(), false);
1797 QCOMPARE(o.invoked(), 10);
1798 QCOMPARE(o.actuals().count(), 1);
1799 QVERIFY(qIsNaN(o.actuals().at(0).toDouble()));
1802 QVERIFY(EVALUATE_VALUE("object.method_real(object)", v8::Undefined()));
1803 QCOMPARE(o.error(), false);
1804 QCOMPARE(o.invoked(), 10);
1805 QCOMPARE(o.actuals().count(), 1);
1806 QVERIFY(qIsNaN(o.actuals().at(0).toDouble()));
1809 QVERIFY(EVALUATE_VALUE("object.method_QString(\"Hello world\")", v8::Undefined()));
1810 QCOMPARE(o.error(), false);
1811 QCOMPARE(o.invoked(), 11);
1812 QCOMPARE(o.actuals().count(), 1);
1813 QCOMPARE(o.actuals().at(0), QVariant("Hello world"));
1816 QVERIFY(EVALUATE_VALUE("object.method_QString(19)", v8::Undefined()));
1817 QCOMPARE(o.error(), false);
1818 QCOMPARE(o.invoked(), 11);
1819 QCOMPARE(o.actuals().count(), 1);
1820 QCOMPARE(o.actuals().at(0), QVariant("19"));
1824 QString expected = "MyInvokableObject(0x" + QString::number((quintptr)&o, 16) + ")";
1825 QVERIFY(EVALUATE_VALUE("object.method_QString(object)", v8::Undefined()));
1826 QCOMPARE(o.error(), false);
1827 QCOMPARE(o.invoked(), 11);
1828 QCOMPARE(o.actuals().count(), 1);
1829 QCOMPARE(o.actuals().at(0), QVariant(expected));
1833 QVERIFY(EVALUATE_VALUE("object.method_QString(null)", v8::Undefined()));
1834 QCOMPARE(o.error(), false);
1835 QCOMPARE(o.invoked(), 11);
1836 QCOMPARE(o.actuals().count(), 1);
1837 QCOMPARE(o.actuals().at(0), QVariant(QString()));
1840 QVERIFY(EVALUATE_VALUE("object.method_QString(undefined)", v8::Undefined()));
1841 QCOMPARE(o.error(), false);
1842 QCOMPARE(o.invoked(), 11);
1843 QCOMPARE(o.actuals().count(), 1);
1844 QCOMPARE(o.actuals().at(0), QVariant(QString()));
1847 QVERIFY(EVALUATE_VALUE("object.method_QPointF(0)", v8::Undefined()));
1848 QCOMPARE(o.error(), false);
1849 QCOMPARE(o.invoked(), 12);
1850 QCOMPARE(o.actuals().count(), 1);
1851 QCOMPARE(o.actuals().at(0), QVariant(QPointF()));
1854 QVERIFY(EVALUATE_VALUE("object.method_QPointF(null)", v8::Undefined()));
1855 QCOMPARE(o.error(), false);
1856 QCOMPARE(o.invoked(), 12);
1857 QCOMPARE(o.actuals().count(), 1);
1858 QCOMPARE(o.actuals().at(0), QVariant(QPointF()));
1861 QVERIFY(EVALUATE_VALUE("object.method_QPointF(undefined)", v8::Undefined()));
1862 QCOMPARE(o.error(), false);
1863 QCOMPARE(o.invoked(), 12);
1864 QCOMPARE(o.actuals().count(), 1);
1865 QCOMPARE(o.actuals().at(0), QVariant(QPointF()));
1868 QVERIFY(EVALUATE_VALUE("object.method_QPointF(object)", v8::Undefined()));
1869 QCOMPARE(o.error(), false);
1870 QCOMPARE(o.invoked(), 12);
1871 QCOMPARE(o.actuals().count(), 1);
1872 QCOMPARE(o.actuals().at(0), QVariant(QPointF()));
1875 QVERIFY(EVALUATE_VALUE("object.method_QPointF(object.method_get_QPointF())", v8::Undefined()));
1876 QCOMPARE(o.error(), false);
1877 QCOMPARE(o.invoked(), 12);
1878 QCOMPARE(o.actuals().count(), 1);
1879 QCOMPARE(o.actuals().at(0), QVariant(QPointF(99.3, -10.2)));
1882 QVERIFY(EVALUATE_VALUE("object.method_QPointF(object.method_get_QPoint())", v8::Undefined()));
1883 QCOMPARE(o.error(), false);
1884 QCOMPARE(o.invoked(), 12);
1885 QCOMPARE(o.actuals().count(), 1);
1886 QCOMPARE(o.actuals().at(0), QVariant(QPointF(9, 12)));
1889 QVERIFY(EVALUATE_VALUE("object.method_QObject(0)", v8::Undefined()));
1890 QCOMPARE(o.error(), false);
1891 QCOMPARE(o.invoked(), 13);
1892 QCOMPARE(o.actuals().count(), 1);
1893 QCOMPARE(o.actuals().at(0), qVariantFromValue((QObject *)0));
1896 QVERIFY(EVALUATE_VALUE("object.method_QObject(\"Hello world\")", v8::Undefined()));
1897 QCOMPARE(o.error(), false);
1898 QCOMPARE(o.invoked(), 13);
1899 QCOMPARE(o.actuals().count(), 1);
1900 QCOMPARE(o.actuals().at(0), qVariantFromValue((QObject *)0));
1903 QVERIFY(EVALUATE_VALUE("object.method_QObject(null)", v8::Undefined()));
1904 QCOMPARE(o.error(), false);
1905 QCOMPARE(o.invoked(), 13);
1906 QCOMPARE(o.actuals().count(), 1);
1907 QCOMPARE(o.actuals().at(0), qVariantFromValue((QObject *)0));
1910 QVERIFY(EVALUATE_VALUE("object.method_QObject(undefined)", v8::Undefined()));
1911 QCOMPARE(o.error(), false);
1912 QCOMPARE(o.invoked(), 13);
1913 QCOMPARE(o.actuals().count(), 1);
1914 QCOMPARE(o.actuals().at(0), qVariantFromValue((QObject *)0));
1917 QVERIFY(EVALUATE_VALUE("object.method_QObject(object)", v8::Undefined()));
1918 QCOMPARE(o.error(), false);
1919 QCOMPARE(o.invoked(), 13);
1920 QCOMPARE(o.actuals().count(), 1);
1921 QCOMPARE(o.actuals().at(0), qVariantFromValue((QObject *)&o));
1923 // XXX enable once qml/qtscript integration is implemented
1926 QVERIFY(EVALUATE_VALUE("object.method_QScriptValue(null)", v8::Undefined()));
1927 QCOMPARE(o.error(), false);
1928 QCOMPARE(o.invoked(), 14);
1929 QCOMPARE(o.actuals().count(), 1);
1930 QVERIFY(qvariant_cast<QScriptValue>(o.actuals().at(0)).isNull());
1933 QVERIFY(EVALUATE_VALUE("object.method_QScriptValue(undefined)", v8::Undefined()));
1934 QCOMPARE(o.error(), false);
1935 QCOMPARE(o.invoked(), 14);
1936 QCOMPARE(o.actuals().count(), 1);
1937 QVERIFY(qvariant_cast<QScriptValue>(o.actuals().at(0)).isUndefined());
1940 QVERIFY(EVALUATE_VALUE("object.method_QScriptValue(19)", v8::Undefined()));
1941 QCOMPARE(o.error(), false);
1942 QCOMPARE(o.invoked(), 14);
1943 QCOMPARE(o.actuals().count(), 1);
1944 QVERIFY(qvariant_cast<QScriptValue>(o.actuals().at(0)).strictlyEquals(QScriptValue(engine, 19)));
1947 QVERIFY(EVALUATE_VALUE("object.method_QScriptValue([19, 20])", v8::Undefined()));
1948 QCOMPARE(o.error(), false);
1949 QCOMPARE(o.invoked(), 14);
1950 QCOMPARE(o.actuals().count(), 1);
1951 QVERIFY(qvariant_cast<QScriptValue>(o.actuals().at(0)).isArray());
1954 QVERIFY(EVALUATE_VALUE("object.method_intQScriptValue(4, null)", v8::Undefined()));
1955 QCOMPARE(o.error(), false);
1956 QCOMPARE(o.invoked(), 15);
1957 QCOMPARE(o.actuals().count(), 2);
1958 QCOMPARE(o.actuals().at(0), QVariant(4));
1959 QVERIFY(qvariant_cast<QScriptValue>(o.actuals().at(1)).isNull());
1962 QVERIFY(EVALUATE_VALUE("object.method_intQScriptValue(8, undefined)", v8::Undefined()));
1963 QCOMPARE(o.error(), false);
1964 QCOMPARE(o.invoked(), 15);
1965 QCOMPARE(o.actuals().count(), 2);
1966 QCOMPARE(o.actuals().at(0), QVariant(8));
1967 QVERIFY(qvariant_cast<QScriptValue>(o.actuals().at(1)).isUndefined());
1970 QVERIFY(EVALUATE_VALUE("object.method_intQScriptValue(3, 19)", v8::Undefined()));
1971 QCOMPARE(o.error(), false);
1972 QCOMPARE(o.invoked(), 15);
1973 QCOMPARE(o.actuals().count(), 2);
1974 QCOMPARE(o.actuals().at(0), QVariant(3));
1975 QVERIFY(qvariant_cast<QScriptValue>(o.actuals().at(1)).strictlyEquals(QScriptValue(engine, 19)));
1978 QVERIFY(EVALUATE_VALUE("object.method_intQScriptValue(44, [19, 20])", v8::Undefined()));
1979 QCOMPARE(o.error(), false);
1980 QCOMPARE(o.invoked(), 15);
1981 QCOMPARE(o.actuals().count(), 2);
1982 QCOMPARE(o.actuals().at(0), QVariant(44));
1983 QVERIFY(qvariant_cast<QScriptValue>(o.actuals().at(1)).isArray());
1987 QVERIFY(EVALUATE_ERROR("object.method_overload()"));
1988 QCOMPARE(o.error(), false);
1989 QCOMPARE(o.invoked(), -1);
1990 QCOMPARE(o.actuals().count(), 0);
1993 QVERIFY(EVALUATE_VALUE("object.method_overload(10)", v8::Undefined()));
1994 QCOMPARE(o.error(), false);
1995 QCOMPARE(o.invoked(), 16);
1996 QCOMPARE(o.actuals().count(), 1);
1997 QCOMPARE(o.actuals().at(0), QVariant(10));
2000 QVERIFY(EVALUATE_VALUE("object.method_overload(10, 11)", v8::Undefined()));
2001 QCOMPARE(o.error(), false);
2002 QCOMPARE(o.invoked(), 17);
2003 QCOMPARE(o.actuals().count(), 2);
2004 QCOMPARE(o.actuals().at(0), QVariant(10));
2005 QCOMPARE(o.actuals().at(1), QVariant(11));
2008 QVERIFY(EVALUATE_VALUE("object.method_overload(\"Hello\")", v8::Undefined()));
2009 QCOMPARE(o.error(), false);
2010 QCOMPARE(o.invoked(), 18);
2011 QCOMPARE(o.actuals().count(), 1);
2012 QCOMPARE(o.actuals().at(0), QVariant(QString("Hello")));
2015 QVERIFY(EVALUATE_VALUE("object.method_with_enum(9)", v8::Undefined()));
2016 QCOMPARE(o.error(), false);
2017 QCOMPARE(o.invoked(), 19);
2018 QCOMPARE(o.actuals().count(), 1);
2019 QCOMPARE(o.actuals().at(0), QVariant(9));
2022 QVERIFY(EVALUATE_VALUE("object.method_default(10)", v8::Integer::New(19)));
2023 QCOMPARE(o.error(), false);
2024 QCOMPARE(o.invoked(), 20);
2025 QCOMPARE(o.actuals().count(), 2);
2026 QCOMPARE(o.actuals().at(0), QVariant(10));
2027 QCOMPARE(o.actuals().at(1), QVariant(19));
2030 QVERIFY(EVALUATE_VALUE("object.method_default(10, 13)", v8::Integer::New(13)));
2031 QCOMPARE(o.error(), false);
2032 QCOMPARE(o.invoked(), 20);
2033 QCOMPARE(o.actuals().count(), 2);
2034 QCOMPARE(o.actuals().at(0), QVariant(10));
2035 QCOMPARE(o.actuals().at(1), QVariant(13));
2038 QVERIFY(EVALUATE_VALUE("object.method_inherited(9)", v8::Undefined()));
2039 QCOMPARE(o.error(), false);
2040 QCOMPARE(o.invoked(), -3);
2041 QCOMPARE(o.actuals().count(), 1);
2042 QCOMPARE(o.actuals().at(0), QVariant(9));
2045 QVERIFY(EVALUATE_VALUE("object.method_QVariant(9)", v8::Undefined()));
2046 QCOMPARE(o.error(), false);
2047 QCOMPARE(o.invoked(), 21);
2048 QCOMPARE(o.actuals().count(), 2);
2049 QCOMPARE(o.actuals().at(0), QVariant(9));
2050 QCOMPARE(o.actuals().at(1), QVariant());
2053 QVERIFY(EVALUATE_VALUE("object.method_QVariant(\"Hello\", \"World\")", v8::Undefined()));
2054 QCOMPARE(o.error(), false);
2055 QCOMPARE(o.invoked(), 21);
2056 QCOMPARE(o.actuals().count(), 2);
2057 QCOMPARE(o.actuals().at(0), QVariant(QString("Hello")));
2058 QCOMPARE(o.actuals().at(1), QVariant(QString("World")));
2061 // QTBUG-13047 (check that you can pass registered object types as args)
2062 void tst_qdeclarativeecmascript::invokableObjectArg()
2064 QDeclarativeComponent component(&engine, TEST_FILE("invokableObjectArg.qml"));
2066 QObject *o = component.create();
2068 MyQmlObject *qmlobject = qobject_cast<MyQmlObject *>(o);
2070 QCOMPARE(qmlobject->myinvokableObject, qmlobject);
2075 // QTBUG-13047 (check that you can return registered object types from methods)
2076 void tst_qdeclarativeecmascript::invokableObjectRet()
2078 QDeclarativeComponent component(&engine, TEST_FILE("invokableObjectRet.qml"));
2080 QObject *o = component.create();
2082 QCOMPARE(o->property("test").toBool(), true);
2087 void tst_qdeclarativeecmascript::listToVariant()
2089 QDeclarativeComponent component(&engine, TEST_FILE("listToVariant.qml"));
2091 MyQmlContainer container;
2093 QDeclarativeContext context(engine.rootContext());
2094 context.setContextObject(&container);
2096 QObject *object = component.create(&context);
2097 QVERIFY(object != 0);
2099 QVariant v = object->property("test");
2100 QCOMPARE(v.userType(), qMetaTypeId<QDeclarativeListReference>());
2101 QVERIFY(qvariant_cast<QDeclarativeListReference>(v).object() == &container);
2107 void tst_qdeclarativeecmascript::multiEngineObject()
2110 obj.setStringProperty("Howdy planet");
2112 QDeclarativeEngine e1;
2113 e1.rootContext()->setContextProperty("thing", &obj);
2114 QDeclarativeComponent c1(&e1, TEST_FILE("multiEngineObject.qml"));
2116 QDeclarativeEngine e2;
2117 e2.rootContext()->setContextProperty("thing", &obj);
2118 QDeclarativeComponent c2(&e2, TEST_FILE("multiEngineObject.qml"));
2120 QObject *o1 = c1.create();
2121 QObject *o2 = c2.create();
2123 QCOMPARE(o1->property("test").toString(), QString("Howdy planet"));
2124 QCOMPARE(o2->property("test").toString(), QString("Howdy planet"));
2130 // Test that references to QObjects are cleanup when the object is destroyed
2131 void tst_qdeclarativeecmascript::deletedObject()
2133 QDeclarativeComponent component(&engine, TEST_FILE("deletedObject.qml"));
2135 QObject *object = component.create();
2137 QCOMPARE(object->property("test1").toBool(), true);
2138 QCOMPARE(object->property("test2").toBool(), true);
2139 QCOMPARE(object->property("test3").toBool(), true);
2140 QCOMPARE(object->property("test4").toBool(), true);
2145 void tst_qdeclarativeecmascript::attachedPropertyScope()
2147 QDeclarativeComponent component(&engine, TEST_FILE("attachedPropertyScope.qml"));
2149 QObject *object = component.create();
2150 QVERIFY(object != 0);
2152 MyQmlAttachedObject *attached =
2153 qobject_cast<MyQmlAttachedObject *>(qmlAttachedPropertiesObject<MyQmlObject>(object));
2154 QVERIFY(attached != 0);
2156 QCOMPARE(object->property("value2").toInt(), 0);
2158 attached->emitMySignal();
2160 QCOMPARE(object->property("value2").toInt(), 9);
2165 void tst_qdeclarativeecmascript::scriptConnect()
2168 QDeclarativeComponent component(&engine, TEST_FILE("scriptConnect.1.qml"));
2170 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2171 QVERIFY(object != 0);
2173 QCOMPARE(object->property("test").toBool(), false);
2174 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2175 QCOMPARE(object->property("test").toBool(), true);
2181 QDeclarativeComponent component(&engine, TEST_FILE("scriptConnect.2.qml"));
2183 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2184 QVERIFY(object != 0);
2186 QCOMPARE(object->property("test").toBool(), false);
2187 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2188 QCOMPARE(object->property("test").toBool(), true);
2194 QDeclarativeComponent component(&engine, TEST_FILE("scriptConnect.3.qml"));
2196 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2197 QVERIFY(object != 0);
2199 QCOMPARE(object->property("test").toBool(), false);
2200 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2201 QCOMPARE(object->property("test").toBool(), true);
2207 QDeclarativeComponent component(&engine, TEST_FILE("scriptConnect.4.qml"));
2209 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2210 QVERIFY(object != 0);
2212 QCOMPARE(object->methodCalled(), false);
2213 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2214 QCOMPARE(object->methodCalled(), true);
2220 QDeclarativeComponent component(&engine, TEST_FILE("scriptConnect.5.qml"));
2222 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2223 QVERIFY(object != 0);
2225 QCOMPARE(object->methodCalled(), false);
2226 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2227 QCOMPARE(object->methodCalled(), true);
2233 QDeclarativeComponent component(&engine, TEST_FILE("scriptConnect.6.qml"));
2235 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2236 QVERIFY(object != 0);
2238 QCOMPARE(object->property("test").toInt(), 0);
2239 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2240 QCOMPARE(object->property("test").toInt(), 2);
2246 void tst_qdeclarativeecmascript::scriptDisconnect()
2249 QDeclarativeComponent component(&engine, TEST_FILE("scriptDisconnect.1.qml"));
2251 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2252 QVERIFY(object != 0);
2254 QCOMPARE(object->property("test").toInt(), 0);
2255 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2256 QCOMPARE(object->property("test").toInt(), 1);
2257 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2258 QCOMPARE(object->property("test").toInt(), 2);
2259 emit object->basicSignal();
2260 QCOMPARE(object->property("test").toInt(), 2);
2261 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2262 QCOMPARE(object->property("test").toInt(), 2);
2268 QDeclarativeComponent component(&engine, TEST_FILE("scriptDisconnect.2.qml"));
2270 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2271 QVERIFY(object != 0);
2273 QCOMPARE(object->property("test").toInt(), 0);
2274 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2275 QCOMPARE(object->property("test").toInt(), 1);
2276 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2277 QCOMPARE(object->property("test").toInt(), 2);
2278 emit object->basicSignal();
2279 QCOMPARE(object->property("test").toInt(), 2);
2280 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2281 QCOMPARE(object->property("test").toInt(), 2);
2287 QDeclarativeComponent component(&engine, TEST_FILE("scriptDisconnect.3.qml"));
2289 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2290 QVERIFY(object != 0);
2292 QCOMPARE(object->property("test").toInt(), 0);
2293 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2294 QCOMPARE(object->property("test").toInt(), 1);
2295 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2296 QCOMPARE(object->property("test").toInt(), 2);
2297 emit object->basicSignal();
2298 QCOMPARE(object->property("test").toInt(), 2);
2299 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2300 QCOMPARE(object->property("test").toInt(), 3);
2305 QDeclarativeComponent component(&engine, TEST_FILE("scriptDisconnect.4.qml"));
2307 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2308 QVERIFY(object != 0);
2310 QCOMPARE(object->property("test").toInt(), 0);
2311 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2312 QCOMPARE(object->property("test").toInt(), 1);
2313 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2314 QCOMPARE(object->property("test").toInt(), 2);
2315 emit object->basicSignal();
2316 QCOMPARE(object->property("test").toInt(), 2);
2317 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2318 QCOMPARE(object->property("test").toInt(), 3);
2324 class OwnershipObject : public QObject
2328 OwnershipObject() { object = new QObject; }
2330 QPointer<QObject> object;
2333 QObject *getObject() { return object; }
2336 void tst_qdeclarativeecmascript::ownership()
2338 OwnershipObject own;
2339 QDeclarativeContext *context = new QDeclarativeContext(engine.rootContext());
2340 context->setContextObject(&own);
2343 QDeclarativeComponent component(&engine, TEST_FILE("ownership.qml"));
2345 QVERIFY(own.object != 0);
2347 QObject *object = component.create(context);
2349 engine.collectGarbage();
2351 QCoreApplication::processEvents(QEventLoop::DeferredDeletion);
2353 QVERIFY(own.object == 0);
2358 own.object = new QObject(&own);
2361 QDeclarativeComponent component(&engine, TEST_FILE("ownership.qml"));
2363 QVERIFY(own.object != 0);
2365 QObject *object = component.create(context);
2367 engine.collectGarbage();
2369 QCoreApplication::processEvents(QEventLoop::DeferredDeletion);
2371 QVERIFY(own.object != 0);
2379 class CppOwnershipReturnValue : public QObject
2383 CppOwnershipReturnValue() : value(0) {}
2384 ~CppOwnershipReturnValue() { delete value; }
2386 Q_INVOKABLE QObject *create() {
2387 value = new QObject;
2388 QDeclarativeEngine::setObjectOwnership(value, QDeclarativeEngine::CppOwnership);
2392 Q_INVOKABLE MyQmlObject *createQmlObject() {
2393 MyQmlObject *rv = new MyQmlObject;
2398 QPointer<QObject> value;
2402 // Test setObjectOwnership(CppOwnership) works even when there is no QDeclarativeData
2403 void tst_qdeclarativeecmascript::cppOwnershipReturnValue()
2405 CppOwnershipReturnValue source;
2408 QDeclarativeEngine engine;
2409 engine.rootContext()->setContextProperty("source", &source);
2411 QVERIFY(source.value == 0);
2413 QDeclarativeComponent component(&engine);
2414 component.setData("import QtQuick 1.0\nQtObject {\nComponent.onCompleted: { var a = source.create(); }\n}\n", QUrl());
2416 QObject *object = component.create();
2418 QVERIFY(object != 0);
2419 QVERIFY(source.value != 0);
2424 QCoreApplication::instance()->processEvents(QEventLoop::DeferredDeletion);
2426 QVERIFY(source.value != 0);
2430 void tst_qdeclarativeecmascript::ownershipCustomReturnValue()
2432 CppOwnershipReturnValue source;
2435 QDeclarativeEngine engine;
2436 engine.rootContext()->setContextProperty("source", &source);
2438 QVERIFY(source.value == 0);
2440 QDeclarativeComponent component(&engine);
2441 component.setData("import QtQuick 1.0\nQtObject {\nComponent.onCompleted: { var a = source.createQmlObject(); }\n}\n", QUrl());
2443 QObject *object = component.create();
2445 QVERIFY(object != 0);
2446 QVERIFY(source.value != 0);
2451 engine.collectGarbage();
2452 QCoreApplication::instance()->processEvents(QEventLoop::DeferredDeletion);
2454 QVERIFY(source.value == 0);
2457 class QListQObjectMethodsObject : public QObject
2461 QListQObjectMethodsObject() {
2462 m_objects.append(new MyQmlObject());
2463 m_objects.append(new MyQmlObject());
2466 ~QListQObjectMethodsObject() {
2467 qDeleteAll(m_objects);
2471 QList<QObject *> getObjects() { return m_objects; }
2474 QList<QObject *> m_objects;
2477 // Tests that returning a QList<QObject*> from a method works
2478 void tst_qdeclarativeecmascript::qlistqobjectMethods()
2480 QListQObjectMethodsObject obj;
2481 QDeclarativeContext *context = new QDeclarativeContext(engine.rootContext());
2482 context->setContextObject(&obj);
2484 QDeclarativeComponent component(&engine, TEST_FILE("qlistqobjectMethods.qml"));
2486 QObject *object = component.create(context);
2488 QCOMPARE(object->property("test").toInt(), 2);
2489 QCOMPARE(object->property("test2").toBool(), true);
2496 void tst_qdeclarativeecmascript::strictlyEquals()
2498 QDeclarativeComponent component(&engine, TEST_FILE("strictlyEquals.qml"));
2500 QObject *object = component.create();
2501 QVERIFY(object != 0);
2503 QCOMPARE(object->property("test1").toBool(), true);
2504 QCOMPARE(object->property("test2").toBool(), true);
2505 QCOMPARE(object->property("test3").toBool(), true);
2506 QCOMPARE(object->property("test4").toBool(), true);
2507 QCOMPARE(object->property("test5").toBool(), true);
2508 QCOMPARE(object->property("test6").toBool(), true);
2509 QCOMPARE(object->property("test7").toBool(), true);
2510 QCOMPARE(object->property("test8").toBool(), true);
2515 void tst_qdeclarativeecmascript::compiled()
2517 QDeclarativeComponent component(&engine, TEST_FILE("compiled.qml"));
2519 QObject *object = component.create();
2520 QVERIFY(object != 0);
2522 QCOMPARE(object->property("test1").toReal(), qreal(15.7));
2523 QCOMPARE(object->property("test2").toReal(), qreal(-6.7));
2524 QCOMPARE(object->property("test3").toBool(), true);
2525 QCOMPARE(object->property("test4").toBool(), false);
2526 QCOMPARE(object->property("test5").toBool(), false);
2527 QCOMPARE(object->property("test6").toBool(), true);
2529 QCOMPARE(object->property("test7").toInt(), 185);
2530 QCOMPARE(object->property("test8").toInt(), 167);
2531 QCOMPARE(object->property("test9").toBool(), true);
2532 QCOMPARE(object->property("test10").toBool(), false);
2533 QCOMPARE(object->property("test11").toBool(), false);
2534 QCOMPARE(object->property("test12").toBool(), true);
2536 QCOMPARE(object->property("test13").toString(), QLatin1String("HelloWorld"));
2537 QCOMPARE(object->property("test14").toString(), QLatin1String("Hello World"));
2538 QCOMPARE(object->property("test15").toBool(), false);
2539 QCOMPARE(object->property("test16").toBool(), true);
2541 QCOMPARE(object->property("test17").toInt(), 5);
2542 QCOMPARE(object->property("test18").toReal(), qreal(176));
2543 QCOMPARE(object->property("test19").toInt(), 7);
2544 QCOMPARE(object->property("test20").toReal(), qreal(6.7));
2545 QCOMPARE(object->property("test21").toString(), QLatin1String("6.7"));
2546 QCOMPARE(object->property("test22").toString(), QLatin1String("!"));
2547 QCOMPARE(object->property("test23").toBool(), true);
2548 QCOMPARE(qvariant_cast<QColor>(object->property("test24")), QColor(0x11,0x22,0x33));
2549 QCOMPARE(qvariant_cast<QColor>(object->property("test25")), QColor(0x11,0x22,0x33,0xAA));
2554 // Test that numbers assigned in bindings as strings work consistently
2555 void tst_qdeclarativeecmascript::numberAssignment()
2557 QDeclarativeComponent component(&engine, TEST_FILE("numberAssignment.qml"));
2559 QObject *object = component.create();
2560 QVERIFY(object != 0);
2562 QCOMPARE(object->property("test1"), QVariant((qreal)6.7));
2563 QCOMPARE(object->property("test2"), QVariant((qreal)6.7));
2564 QCOMPARE(object->property("test2"), QVariant((qreal)6.7));
2565 QCOMPARE(object->property("test3"), QVariant((qreal)6));
2566 QCOMPARE(object->property("test4"), QVariant((qreal)6));
2568 QCOMPARE(object->property("test5"), QVariant((int)7));
2569 QCOMPARE(object->property("test6"), QVariant((int)7));
2570 QCOMPARE(object->property("test7"), QVariant((int)6));
2571 QCOMPARE(object->property("test8"), QVariant((int)6));
2573 QCOMPARE(object->property("test9"), QVariant((unsigned int)7));
2574 QCOMPARE(object->property("test10"), QVariant((unsigned int)7));
2575 QCOMPARE(object->property("test11"), QVariant((unsigned int)6));
2576 QCOMPARE(object->property("test12"), QVariant((unsigned int)6));
2581 void tst_qdeclarativeecmascript::propertySplicing()
2583 QDeclarativeComponent component(&engine, TEST_FILE("propertySplicing.qml"));
2585 QObject *object = component.create();
2586 QVERIFY(object != 0);
2588 QCOMPARE(object->property("test").toBool(), true);
2594 void tst_qdeclarativeecmascript::signalWithUnknownTypes()
2596 QDeclarativeComponent component(&engine, TEST_FILE("signalWithUnknownTypes.qml"));
2598 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2599 QVERIFY(object != 0);
2601 MyQmlObject::MyType type;
2602 type.value = 0x8971123;
2603 emit object->signalWithUnknownType(type);
2605 MyQmlObject::MyType result = qvariant_cast<MyQmlObject::MyType>(object->variant());
2607 QCOMPARE(result.value, type.value);
2613 void tst_qdeclarativeecmascript::moduleApi()
2615 QDeclarativeComponent component(&engine, TEST_FILE("moduleApi.qml"));
2616 QObject *object = component.create();
2617 QVERIFY(object != 0);
2618 QCOMPARE(object->property("existingUriTest").toInt(), 20);
2620 QEXPECT_FAIL("", "QTBUG-17318", Continue);
2621 QCOMPARE(object->property("scriptTest").toInt(), 13);
2622 QCOMPARE(object->property("qobjectTest").toInt(), 20);
2623 QCOMPARE(object->property("qobjectMethodTest").toInt(), 1); // first call of method, so count = 1.
2624 QCOMPARE(object->property("qobjectMinorVersionTest").toInt(), 20);
2625 QCOMPARE(object->property("qobjectMajorVersionTest").toInt(), 20);
2626 QCOMPARE(object->property("qobjectParentedTest").toInt(), 26);
2629 // test that caching of module apis works correctly.
2630 QDeclarativeComponent componentTwo(&engine, TEST_FILE("moduleApiCaching.qml"));
2631 object = componentTwo.create();
2632 QVERIFY(object != 0);
2633 QCOMPARE(object->property("existingUriTest").toInt(), 20);
2634 QEXPECT_FAIL("", "QTBUG-17318", Continue);
2635 QCOMPARE(object->property("scriptTest").toInt(), 13); // shouldn't have incremented.
2636 QCOMPARE(object->property("qobjectParentedTest").toInt(), 26); // shouldn't have incremented.
2639 // test that writing to a property of module apis works correctly.
2640 QDeclarativeComponent componentThree(&engine, TEST_FILE("moduleApiWriting.qml"));
2641 QString expectedWarning = QLatin1String("file://") + TEST_FILE("moduleApiWriting.qml").toLocalFile() + QLatin1String(":15: Error: Cannot assign to read-only property \"qobjectTestProperty\"");
2642 QTest::ignoreMessage(QtWarningMsg, expectedWarning.toAscii().constData());
2643 object = componentThree.create();
2644 QVERIFY(object != 0);
2645 QCOMPARE(object->property("readOnlyProperty").toInt(), 20);
2646 QCOMPARE(object->property("writableProperty").toInt(), 50);
2647 QVERIFY(object->setProperty("firstProperty", QVariant(30))); // shouldn't affect value of readOnlyProperty
2648 QVERIFY(object->setProperty("writableProperty", QVariant(30))); // SHOULD affect value of writableProperty
2649 QCOMPARE(object->property("readOnlyProperty").toInt(), 20);
2650 QCOMPARE(object->property("writableProperty").toInt(), 30);
2653 QDeclarativeComponent failOne(&engine, TEST_FILE("moduleApiMajorVersionFail.qml"));
2654 QTest::ignoreMessage(QtWarningMsg, "QDeclarativeComponent: Component is not ready");
2655 object = failOne.create();
2656 QVERIFY(object == 0); // should have failed: invalid major version
2658 QDeclarativeComponent failTwo(&engine, TEST_FILE("moduleApiMinorVersionFail.qml"));
2659 QTest::ignoreMessage(QtWarningMsg, "QDeclarativeComponent: Component is not ready");
2660 object = failTwo.create();
2661 QVERIFY(object == 0); // should have failed: invalid minor version
2664 void tst_qdeclarativeecmascript::importScripts()
2666 QObject *object = 0;
2668 // first, ensure that the required behaviour works.
2669 QDeclarativeComponent component(&engine, TEST_FILE("jsimport/testImport.qml"));
2670 object = component.create();
2671 QVERIFY(object != 0);
2672 QCOMPARE(object->property("importedScriptStringValue"), QVariant(QString(QLatin1String("Hello, World!"))));
2673 QCOMPARE(object->property("importedScriptFunctionValue"), QVariant(20));
2674 QCOMPARE(object->property("importedModuleAttachedPropertyValue"), QVariant(19));
2675 QCOMPARE(object->property("importedModuleEnumValue"), QVariant(2));
2678 QDeclarativeComponent componentTwo(&engine, TEST_FILE("jsimport/testImportScoping.qml"));
2679 object = componentTwo.create();
2680 QVERIFY(object != 0);
2681 QCOMPARE(object->property("componentError"), QVariant(5));
2684 // then, ensure that unintended behaviour does not work.
2685 QDeclarativeComponent failOneComponent(&engine, TEST_FILE("jsimportfail/failOne.qml"));
2686 QString expectedWarning = QLatin1String("file://") + TEST_FILE("jsimportfail/failOne.qml").toLocalFile() + QLatin1String(":6: TypeError: Cannot call method 'greetingString' of undefined");
2687 QTest::ignoreMessage(QtWarningMsg, expectedWarning.toAscii().constData());
2688 object = failOneComponent.create();
2689 QVERIFY(object != 0);
2690 QVERIFY(object->property("importScriptFunctionValue").toString().isEmpty());
2692 QDeclarativeComponent failTwoComponent(&engine, TEST_FILE("jsimportfail/failTwo.qml"));
2693 expectedWarning = QLatin1String("file://") + TEST_FILE("jsimportfail/failTwo.qml").toLocalFile() + QLatin1String(":6: ReferenceError: Can't find variable: ImportOneJs");
2694 QTest::ignoreMessage(QtWarningMsg, expectedWarning.toAscii().constData());
2695 object = failTwoComponent.create();
2696 QVERIFY(object != 0);
2697 QVERIFY(object->property("importScriptFunctionValue").toString().isEmpty());
2699 QDeclarativeComponent failThreeComponent(&engine, TEST_FILE("jsimportfail/failThree.qml"));
2700 expectedWarning = QLatin1String("file://") + TEST_FILE("jsimportfail/failThree.qml").toLocalFile() + QLatin1String(":7: TypeError: Cannot read property 'JsQtTest' of undefined");
2701 QTest::ignoreMessage(QtWarningMsg, expectedWarning.toAscii().constData());
2702 object = failThreeComponent.create();
2703 QVERIFY(object != 0);
2704 QCOMPARE(object->property("importedModuleAttachedPropertyValue"), QVariant(false));
2706 QDeclarativeComponent failFourComponent(&engine, TEST_FILE("jsimportfail/failFour.qml"));
2707 expectedWarning = QLatin1String("file://") + TEST_FILE("jsimportfail/failFour.qml").toLocalFile() + QLatin1String(":6: ReferenceError: Can't find variable: JsQtTest");
2708 QTest::ignoreMessage(QtWarningMsg, expectedWarning.toAscii().constData());
2709 object = failFourComponent.create();
2710 QVERIFY(object != 0);
2711 QCOMPARE(object->property("importedModuleEnumValue"), QVariant(0));
2713 QDeclarativeComponent failFiveComponent(&engine, TEST_FILE("jsimportfail/failFive.qml"));
2714 expectedWarning = QLatin1String("file://") + TEST_FILE("jsimportfail/importWithImports.js").toLocalFile() + QLatin1String(":8: ReferenceError: Can't find variable: Component");
2715 QTest::ignoreMessage(QtWarningMsg, expectedWarning.toAscii().constData());
2716 expectedWarning = QLatin1String("file://") + TEST_FILE("jsimportfail/importPragmaLibrary.js").toLocalFile() + QLatin1String(":6: ReferenceError: Can't find variable: Component");
2717 QTest::ignoreMessage(QtWarningMsg, expectedWarning.toAscii().constData());
2718 object = failFiveComponent.create();
2719 QVERIFY(object != 0);
2720 QCOMPARE(object->property("componentError"), QVariant(0));
2723 // also, test that importing scripts with .pragma library works as required
2724 QDeclarativeComponent pragmaLibraryComponent(&engine, TEST_FILE("jsimport/testImportPragmaLibrary.qml"));
2725 object = pragmaLibraryComponent.create();
2726 QVERIFY(object != 0);
2727 QCOMPARE(object->property("testValue"), QVariant(31));
2730 // and that .pragma library scripts don't inherit imports from any .qml file
2731 QDeclarativeComponent pragmaLibraryComponentTwo(&engine, TEST_FILE("jsimportfail/testImportPragmaLibrary.qml"));
2732 object = pragmaLibraryComponentTwo.create();
2733 QVERIFY(object != 0);
2734 QCOMPARE(object->property("testValue"), QVariant(0));
2738 void tst_qdeclarativeecmascript::scarceResources()
2740 QPixmap origPixmap(100, 100);
2741 origPixmap.fill(Qt::blue);
2743 QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(&engine);
2744 ScarceResourceObject *eo = 0;
2745 QObject *object = 0;
2747 // in the following three cases, the instance created from the component
2748 // has a property which is a copy of the scarce resource; hence, the
2749 // resource should NOT be detached prior to deletion of the object instance,
2750 // unless the resource is destroyed explicitly.
2751 QDeclarativeComponent component(&engine, TEST_FILE("scarceresources/scarceResourceCopy.qml"));
2752 object = component.create();
2753 QVERIFY(object != 0);
2754 QVERIFY(object->property("scarceResourceCopy").isValid());
2755 QCOMPARE(object->property("scarceResourceCopy").value<QPixmap>(), origPixmap);
2756 QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
2757 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2758 QVERIFY(!eo->scarceResourceIsDetached()); // there are two copies of it in existence: the property of object, and the property of eo.
2761 QDeclarativeComponent componentTwo(&engine, TEST_FILE("scarceresources/scarceResourceCopyFromJs.qml"));
2762 object = componentTwo.create();
2763 QVERIFY(object != 0);
2764 QVERIFY(object->property("scarceResourceCopy").isValid());
2765 QCOMPARE(object->property("scarceResourceCopy").value<QPixmap>(), origPixmap);
2766 QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
2767 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2768 QVERIFY(!eo->scarceResourceIsDetached()); // there are two copies of it in existence: the property of object, and the property of eo.
2771 QDeclarativeComponent componentThree(&engine, TEST_FILE("scarceresources/scarceResourceDestroyedCopy.qml"));
2772 object = componentThree.create();
2773 QVERIFY(object != 0);
2774 QVERIFY(!(object->property("scarceResourceCopy").isValid())); // was manually released prior to being returned.
2775 QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
2776 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2777 QVERIFY(eo->scarceResourceIsDetached()); // should have explicitly been released during the evaluation of the binding.
2780 // in the following three cases, no other copy should exist in memory,
2781 // and so it should be detached (unless explicitly preserved).
2782 QDeclarativeComponent componentFour(&engine, TEST_FILE("scarceresources/scarceResourceTest.qml"));
2783 object = componentFour.create();
2784 QVERIFY(object != 0);
2785 QVERIFY(object->property("scarceResourceTest").isValid());
2786 QCOMPARE(object->property("scarceResourceTest").toInt(), 100);
2787 QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
2788 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2789 QVERIFY(eo->scarceResourceIsDetached()); // the resource should have been released after the binding was evaluated.
2792 QDeclarativeComponent componentFive(&engine, TEST_FILE("scarceresources/scarceResourceTestPreserve.qml"));
2793 object = componentFive.create();
2794 QVERIFY(object != 0);
2795 QVERIFY(object->property("scarceResourceTest").isValid());
2796 QCOMPARE(object->property("scarceResourceTest").toInt(), 100);
2797 QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
2798 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2799 QVERIFY(!eo->scarceResourceIsDetached()); // this won't be detached since we explicitly preserved it.
2802 QDeclarativeComponent componentSix(&engine, TEST_FILE("scarceresources/scarceResourceTestMultiple.qml"));
2803 object = componentSix.create();
2804 QVERIFY(object != 0);
2805 QVERIFY(object->property("scarceResourceTest").isValid());
2806 QCOMPARE(object->property("scarceResourceTest").toInt(), 100);
2807 QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
2808 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2809 QVERIFY(eo->scarceResourceIsDetached()); // all resources were released manually or automatically released.
2812 // test that scarce resources are handled correctly for imports
2813 QDeclarativeComponent componentSeven(&engine, TEST_FILE("scarceresources/scarceResourceCopyImportNoBinding.qml"));
2814 object = componentSeven.create();
2815 QVERIFY(object != 0); // the import should have caused the addition of a resource to the ScarceResources list
2816 QVERIFY(ep->scarceResources.isEmpty()); // but they should have been released by this point.
2819 QDeclarativeComponent componentEight(&engine, TEST_FILE("scarceresources/scarceResourceCopyImportFail.qml"));
2820 object = componentEight.create();
2821 QVERIFY(object != 0);
2822 QVERIFY(!object->property("scarceResourceCopy").isValid()); // wasn't preserved, so shouldn't be valid.
2823 QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
2826 QDeclarativeComponent componentNine(&engine, TEST_FILE("scarceresources/scarceResourceCopyImport.qml"));
2827 object = componentNine.create();
2828 QVERIFY(object != 0);
2829 QVERIFY(object->property("scarceResourceCopy").isValid()); // preserved, so should be valid.
2830 QCOMPARE(object->property("scarceResourceCopy").value<QPixmap>(), origPixmap);
2831 QVERIFY(object->property("scarceResourceAssignedCopyOne").isValid()); // assigned before destroy(), so should be valid.
2832 QCOMPARE(object->property("scarceResourceAssignedCopyOne").value<QPixmap>(), origPixmap);
2833 QVERIFY(!object->property("scarceResourceAssignedCopyTwo").isValid()); // assigned after destroy(), so should be invalid.
2834 QVERIFY(ep->scarceResources.isEmpty()); // this will still be zero, because "preserve()" REMOVES it from this list.
2837 // test that scarce resources are handled properly in signal invocation
2838 QDeclarativeComponent componentTen(&engine, TEST_FILE("scarceresources/scarceResourceSignal.qml"));
2839 object = componentTen.create();
2840 QVERIFY(object != 0);
2841 QObject *srsc = object->findChild<QObject*>("srsc");
2843 QVERIFY(!srsc->property("scarceResourceCopy").isValid()); // hasn't been instantiated yet.
2844 QCOMPARE(srsc->property("width"), QVariant(5)); // default value is 5.
2845 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2846 QVERIFY(eo->scarceResourceIsDetached()); // should be no other copies of it at this stage.
2847 QMetaObject::invokeMethod(srsc, "testSignal");
2848 QVERIFY(!srsc->property("scarceResourceCopy").isValid()); // still hasn't been instantiated
2849 QCOMPARE(srsc->property("width"), QVariant(10)); // but width was assigned to 10.
2850 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2851 QVERIFY(eo->scarceResourceIsDetached()); // should still be no other copies of it at this stage.
2852 QMetaObject::invokeMethod(srsc, "testSignal2"); // assigns scarceResourceCopy to the scarce pixmap.
2853 QVERIFY(srsc->property("scarceResourceCopy").isValid());
2854 QCOMPARE(srsc->property("scarceResourceCopy").value<QPixmap>(), origPixmap);
2855 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2856 QVERIFY(!(eo->scarceResourceIsDetached())); // should be another copy of the resource now.
2857 QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
2860 // test that scarce resources are handled properly from js functions in qml files
2861 QDeclarativeComponent componentEleven(&engine, TEST_FILE("scarceresources/scarceResourceFunction.qml"));
2862 object = componentEleven.create();
2863 QVERIFY(object != 0);
2864 QVERIFY(!object->property("scarceResourceCopy").isValid()); // not yet assigned, so should not be valid
2865 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2866 QVERIFY(eo->scarceResourceIsDetached()); // should be no other copies of it at this stage.
2867 QMetaObject::invokeMethod(object, "retrieveScarceResource");
2868 QVERIFY(object->property("scarceResourceCopy").isValid()); // assigned, so should be valid.
2869 QCOMPARE(object->property("scarceResourceCopy").value<QPixmap>(), origPixmap);
2870 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2871 QVERIFY(!eo->scarceResourceIsDetached()); // should be a copy of the resource at this stage.
2872 QMetaObject::invokeMethod(object, "releaseScarceResource");
2873 QVERIFY(!object->property("scarceResourceCopy").isValid()); // just released, so should not be valid
2874 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2875 QVERIFY(eo->scarceResourceIsDetached()); // should be no other copies of it at this stage.
2876 QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
2879 // test that if an exception occurs while invoking js function from cpp, that the resources are released.
2880 QDeclarativeComponent componentTwelve(&engine, TEST_FILE("scarceresources/scarceResourceFunctionFail.qml"));
2881 object = componentTwelve.create();
2882 QVERIFY(object != 0);
2883 QVERIFY(!object->property("scarceResourceCopy").isValid()); // not yet assigned, so should not be valid
2884 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2885 QVERIFY(eo->scarceResourceIsDetached()); // should be no other copies of it at this stage.
2886 QString srp_name = object->property("srp_name").toString();
2887 QString expectedWarning = componentTwelve.url().toString() + QLatin1String(":17: TypeError: Property 'scarceResource' of object ") + srp_name + QLatin1String(" is not a function");
2888 QTest::ignoreMessage(QtWarningMsg, qPrintable(expectedWarning)); // we expect a meaningful warning to be printed.
2889 QMetaObject::invokeMethod(object, "retrieveScarceResource");
2890 QVERIFY(!object->property("scarceResourceCopy").isValid()); // due to exception, assignment will NOT have occurred.
2891 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2892 QVERIFY(eo->scarceResourceIsDetached()); // should be no other copies of it at this stage.
2893 QVERIFY(ep->scarceResources.isEmpty()); // should have been released by this point.
2897 void tst_qdeclarativeecmascript::propertyChangeSlots()
2899 // ensure that allowable property names are allowed and onPropertyNameChanged slots are generated correctly.
2900 QDeclarativeComponent component(&engine, TEST_FILE("changeslots/propertyChangeSlots.qml"));
2901 QObject *object = component.create();
2902 QVERIFY(object != 0);
2905 // ensure that invalid property names fail properly.
2906 QTest::ignoreMessage(QtWarningMsg, "QDeclarativeComponent: Component is not ready");
2907 QDeclarativeComponent e1(&engine, TEST_FILE("changeslots/propertyChangeSlotErrors.1.qml"));
2908 QString expectedErrorString = e1.url().toString() + QLatin1String(":9:5: Cannot assign to non-existent property \"on_nameWithUnderscoreChanged\"");
2909 QCOMPARE(e1.errors().at(0).toString(), expectedErrorString);
2910 object = e1.create();
2911 QVERIFY(object == 0);
2914 QTest::ignoreMessage(QtWarningMsg, "QDeclarativeComponent: Component is not ready");
2915 QDeclarativeComponent e2(&engine, TEST_FILE("changeslots/propertyChangeSlotErrors.2.qml"));
2916 expectedErrorString = e2.url().toString() + QLatin1String(":9:5: Cannot assign to non-existent property \"on____nameWithUnderscoresChanged\"");
2917 QCOMPARE(e2.errors().at(0).toString(), expectedErrorString);
2918 object = e2.create();
2919 QVERIFY(object == 0);
2922 QTest::ignoreMessage(QtWarningMsg, "QDeclarativeComponent: Component is not ready");
2923 QDeclarativeComponent e3(&engine, TEST_FILE("changeslots/propertyChangeSlotErrors.3.qml"));
2924 expectedErrorString = e3.url().toString() + QLatin1String(":9:5: Cannot assign to non-existent property \"on$NameWithDollarsignChanged\"");
2925 QCOMPARE(e3.errors().at(0).toString(), expectedErrorString);
2926 object = e3.create();
2927 QVERIFY(object == 0);
2930 QTest::ignoreMessage(QtWarningMsg, "QDeclarativeComponent: Component is not ready");
2931 QDeclarativeComponent e4(&engine, TEST_FILE("changeslots/propertyChangeSlotErrors.4.qml"));
2932 expectedErrorString = e4.url().toString() + QLatin1String(":9:5: Cannot assign to non-existent property \"on_6NameWithUnderscoreNumberChanged\"");
2933 QCOMPARE(e4.errors().at(0).toString(), expectedErrorString);
2934 object = e4.create();
2935 QVERIFY(object == 0);
2939 // Ensure that QObject type conversion works on binding assignment
2940 void tst_qdeclarativeecmascript::elementAssign()
2942 QDeclarativeComponent component(&engine, TEST_FILE("elementAssign.qml"));
2944 QObject *object = component.create();
2945 QVERIFY(object != 0);
2947 QCOMPARE(object->property("test").toBool(), true);
2953 void tst_qdeclarativeecmascript::objectPassThroughSignals()
2955 QDeclarativeComponent component(&engine, TEST_FILE("objectsPassThroughSignals.qml"));
2957 QObject *object = component.create();
2958 QVERIFY(object != 0);
2960 QCOMPARE(object->property("test").toBool(), true);
2966 void tst_qdeclarativeecmascript::booleanConversion()
2968 QDeclarativeComponent component(&engine, TEST_FILE("booleanConversion.qml"));
2970 QObject *object = component.create();
2971 QVERIFY(object != 0);
2973 QCOMPARE(object->property("test_true1").toBool(), true);
2974 QCOMPARE(object->property("test_true2").toBool(), true);
2975 QCOMPARE(object->property("test_true3").toBool(), true);
2976 QCOMPARE(object->property("test_true4").toBool(), true);
2977 QCOMPARE(object->property("test_true5").toBool(), true);
2979 QCOMPARE(object->property("test_false1").toBool(), false);
2980 QCOMPARE(object->property("test_false2").toBool(), false);
2981 QCOMPARE(object->property("test_false3").toBool(), false);
2986 // Test that assigning a null object works
2987 // Regressed with: df1788b4dbbb2826ae63f26bdf166342595343f4
2988 void tst_qdeclarativeecmascript::nullObjectBinding()
2990 QDeclarativeComponent component(&engine, TEST_FILE("nullObjectBinding.qml"));
2992 QObject *object = component.create();
2993 QVERIFY(object != 0);
2995 QVERIFY(object->property("test") == QVariant::fromValue((QObject *)0));
3000 // Test that bindings don't evaluate once the engine has been destroyed
3001 void tst_qdeclarativeecmascript::deletedEngine()
3003 QDeclarativeEngine *engine = new QDeclarativeEngine;
3004 QDeclarativeComponent component(engine, TEST_FILE("deletedEngine.qml"));
3006 QObject *object = component.create();
3007 QVERIFY(object != 0);
3009 QCOMPARE(object->property("a").toInt(), 39);
3010 object->setProperty("b", QVariant(9));
3011 QCOMPARE(object->property("a").toInt(), 117);
3015 QCOMPARE(object->property("a").toInt(), 117);
3016 object->setProperty("b", QVariant(10));
3017 QCOMPARE(object->property("a").toInt(), 117);
3022 // Test the crashing part of QTBUG-9705
3023 void tst_qdeclarativeecmascript::libraryScriptAssert()
3025 QDeclarativeComponent component(&engine, TEST_FILE("libraryScriptAssert.qml"));
3027 QObject *object = component.create();
3028 QVERIFY(object != 0);
3033 void tst_qdeclarativeecmascript::variantsAssignedUndefined()
3035 QDeclarativeComponent component(&engine, TEST_FILE("variantsAssignedUndefined.qml"));
3037 QObject *object = component.create();
3038 QVERIFY(object != 0);
3040 QCOMPARE(object->property("test1").toInt(), 10);
3041 QCOMPARE(object->property("test2").toInt(), 11);
3043 object->setProperty("runTest", true);
3045 QCOMPARE(object->property("test1"), QVariant());
3046 QCOMPARE(object->property("test2"), QVariant());
3052 void tst_qdeclarativeecmascript::qtbug_9792()
3054 QDeclarativeComponent component(&engine, TEST_FILE("qtbug_9792.qml"));
3056 QDeclarativeContext *context = new QDeclarativeContext(engine.rootContext());
3058 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create(context));
3059 QVERIFY(object != 0);
3061 QTest::ignoreMessage(QtDebugMsg, "Hello world!");
3062 object->basicSignal();
3066 transientErrorsMsgCount = 0;
3067 QtMsgHandler old = qInstallMsgHandler(transientErrorsMsgHandler);
3069 object->basicSignal();
3071 qInstallMsgHandler(old);
3073 QCOMPARE(transientErrorsMsgCount, 0);
3078 // Verifies that QDeclarativeGuard<>s used in the vmemetaobject are cleaned correctly
3079 void tst_qdeclarativeecmascript::qtcreatorbug_1289()
3081 QDeclarativeComponent component(&engine, TEST_FILE("qtcreatorbug_1289.qml"));
3083 QObject *o = component.create();
3086 QObject *nested = qvariant_cast<QObject *>(o->property("object"));
3087 QVERIFY(nested != 0);
3089 QVERIFY(qvariant_cast<QObject *>(nested->property("nestedObject")) == o);
3092 nested = qvariant_cast<QObject *>(o->property("object"));
3093 QVERIFY(nested == 0);
3095 // If the bug is present, the next line will crash
3099 // Test that we shut down without stupid warnings
3100 void tst_qdeclarativeecmascript::noSpuriousWarningsAtShutdown()
3103 QDeclarativeComponent component(&engine, TEST_FILE("noSpuriousWarningsAtShutdown.qml"));
3105 QObject *o = component.create();
3107 transientErrorsMsgCount = 0;
3108 QtMsgHandler old = qInstallMsgHandler(transientErrorsMsgHandler);
3112 qInstallMsgHandler(old);
3114 QCOMPARE(transientErrorsMsgCount, 0);
3119 QDeclarativeComponent component(&engine, TEST_FILE("noSpuriousWarningsAtShutdown.2.qml"));
3121 QObject *o = component.create();
3123 transientErrorsMsgCount = 0;
3124 QtMsgHandler old = qInstallMsgHandler(transientErrorsMsgHandler);
3128 qInstallMsgHandler(old);
3130 QCOMPARE(transientErrorsMsgCount, 0);
3134 void tst_qdeclarativeecmascript::canAssignNullToQObject()
3137 QDeclarativeComponent component(&engine, TEST_FILE("canAssignNullToQObject.1.qml"));
3139 MyQmlObject *o = qobject_cast<MyQmlObject *>(component.create());
3142 QVERIFY(o->objectProperty() != 0);
3144 o->setProperty("runTest", true);
3146 QVERIFY(o->objectProperty() == 0);
3152 QDeclarativeComponent component(&engine, TEST_FILE("canAssignNullToQObject.2.qml"));
3154 MyQmlObject *o = qobject_cast<MyQmlObject *>(component.create());
3157 QVERIFY(o->objectProperty() == 0);
3163 void tst_qdeclarativeecmascript::functionAssignment_fromBinding()
3165 QDeclarativeComponent component(&engine, TEST_FILE("functionAssignment.1.qml"));
3167 QString url = component.url().toString();
3168 QString warning = url + ":4: Unable to assign a function to a property.";
3169 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
3171 MyQmlObject *o = qobject_cast<MyQmlObject *>(component.create());
3174 QVERIFY(!o->property("a").isValid());
3179 void tst_qdeclarativeecmascript::functionAssignment_fromJS()
3181 QFETCH(QString, triggerProperty);
3183 QDeclarativeComponent component(&engine, TEST_FILE("functionAssignment.2.qml"));
3184 QVERIFY2(component.errorString().isEmpty(), qPrintable(component.errorString()));
3186 MyQmlObject *o = qobject_cast<MyQmlObject *>(component.create());
3188 QVERIFY(!o->property("a").isValid());
3190 o->setProperty("aNumber", QVariant(5));
3191 o->setProperty(triggerProperty.toUtf8().constData(), true);
3192 QCOMPARE(o->property("a"), QVariant(50));
3194 o->setProperty("aNumber", QVariant(10));
3195 QCOMPARE(o->property("a"), QVariant(100));
3200 void tst_qdeclarativeecmascript::functionAssignment_fromJS_data()
3202 QTest::addColumn<QString>("triggerProperty");
3204 QTest::newRow("assign to property") << "assignToProperty";
3205 QTest::newRow("assign to property, from JS file") << "assignToPropertyFromJsFile";
3207 QTest::newRow("assign to value type") << "assignToValueType";
3209 QTest::newRow("use 'this'") << "assignWithThis";
3210 QTest::newRow("use 'this' from JS file") << "assignWithThisFromJsFile";
3213 void tst_qdeclarativeecmascript::functionAssignmentfromJS_invalid()
3215 QDeclarativeComponent component(&engine, TEST_FILE("functionAssignment.2.qml"));
3216 QVERIFY2(component.errorString().isEmpty(), qPrintable(component.errorString()));
3218 MyQmlObject *o = qobject_cast<MyQmlObject *>(component.create());
3220 QVERIFY(!o->property("a").isValid());
3222 o->setProperty("assignFuncWithoutReturn", true);
3223 QVERIFY(!o->property("a").isValid());
3225 QString url = component.url().toString();
3226 QString warning = url + ":67: Unable to assign QString to int";
3227 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
3228 o->setProperty("assignWrongType", true);
3230 warning = url + ":71: Unable to assign QString to int";
3231 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
3232 o->setProperty("assignWrongTypeToValueType", true);
3237 void tst_qdeclarativeecmascript::eval()
3239 QDeclarativeComponent component(&engine, TEST_FILE("eval.qml"));
3241 QObject *o = component.create();
3244 QCOMPARE(o->property("test1").toBool(), true);
3245 QCOMPARE(o->property("test2").toBool(), true);
3246 QCOMPARE(o->property("test3").toBool(), true);
3247 QCOMPARE(o->property("test4").toBool(), true);
3248 QCOMPARE(o->property("test5").toBool(), true);
3253 void tst_qdeclarativeecmascript::function()
3255 QDeclarativeComponent component(&engine, TEST_FILE("function.qml"));
3257 QObject *o = component.create();
3260 QCOMPARE(o->property("test1").toBool(), true);
3261 QCOMPARE(o->property("test2").toBool(), true);
3262 QCOMPARE(o->property("test3").toBool(), true);
3267 // Test the "Qt.include" method
3268 void tst_qdeclarativeecmascript::include()
3270 // Non-library relative include
3272 QDeclarativeComponent component(&engine, TEST_FILE("include.qml"));
3273 QObject *o = component.create();
3276 QCOMPARE(o->property("test0").toInt(), 99);
3277 QCOMPARE(o->property("test1").toBool(), true);
3278 QCOMPARE(o->property("test2").toBool(), true);
3279 QCOMPARE(o->property("test2_1").toBool(), true);
3280 QCOMPARE(o->property("test3").toBool(), true);
3281 QCOMPARE(o->property("test3_1").toBool(), true);
3286 // Library relative include
3288 QDeclarativeComponent component(&engine, TEST_FILE("include_shared.qml"));
3289 QObject *o = component.create();
3292 QCOMPARE(o->property("test0").toInt(), 99);
3293 QCOMPARE(o->property("test1").toBool(), true);
3294 QCOMPARE(o->property("test2").toBool(), true);
3295 QCOMPARE(o->property("test2_1").toBool(), true);
3296 QCOMPARE(o->property("test3").toBool(), true);
3297 QCOMPARE(o->property("test3_1").toBool(), true);
3304 QDeclarativeComponent component(&engine, TEST_FILE("include_callback.qml"));
3305 QObject *o = component.create();
3308 QCOMPARE(o->property("test1").toBool(), true);
3309 QCOMPARE(o->property("test2").toBool(), true);
3310 QCOMPARE(o->property("test3").toBool(), true);
3311 QCOMPARE(o->property("test4").toBool(), true);
3312 QCOMPARE(o->property("test5").toBool(), true);
3313 QCOMPARE(o->property("test6").toBool(), true);
3318 // Including file with ".pragma library"
3320 QDeclarativeComponent component(&engine, TEST_FILE("include_pragma.qml"));
3321 QObject *o = component.create();
3323 QCOMPARE(o->property("test1").toInt(), 100);
3330 TestHTTPServer server(8111);
3331 QVERIFY(server.isValid());
3332 server.serveDirectory(SRCDIR "/data");
3334 QDeclarativeComponent component(&engine, TEST_FILE("include_remote.qml"));
3335 QObject *o = component.create();
3338 QTRY_VERIFY(o->property("done").toBool() == true);
3339 QTRY_VERIFY(o->property("done2").toBool() == true);
3341 QCOMPARE(o->property("test1").toBool(), true);
3342 QCOMPARE(o->property("test2").toBool(), true);
3343 QCOMPARE(o->property("test3").toBool(), true);
3344 QCOMPARE(o->property("test4").toBool(), true);
3345 QCOMPARE(o->property("test5").toBool(), true);
3347 QCOMPARE(o->property("test6").toBool(), true);
3348 QCOMPARE(o->property("test7").toBool(), true);
3349 QCOMPARE(o->property("test8").toBool(), true);
3350 QCOMPARE(o->property("test9").toBool(), true);
3351 QCOMPARE(o->property("test10").toBool(), true);
3358 TestHTTPServer server(8111);
3359 QVERIFY(server.isValid());
3360 server.serveDirectory(SRCDIR "/data");
3362 QDeclarativeComponent component(&engine, TEST_FILE("include_remote_missing.qml"));
3363 QObject *o = component.create();
3366 QTRY_VERIFY(o->property("done").toBool() == true);
3368 QCOMPARE(o->property("test1").toBool(), true);
3369 QCOMPARE(o->property("test2").toBool(), true);
3370 QCOMPARE(o->property("test3").toBool(), true);
3376 void tst_qdeclarativeecmascript::qtbug_10696()
3378 QDeclarativeComponent component(&engine, TEST_FILE("qtbug_10696.qml"));
3379 QObject *o = component.create();
3384 void tst_qdeclarativeecmascript::qtbug_11606()
3386 QDeclarativeComponent component(&engine, TEST_FILE("qtbug_11606.qml"));
3387 QObject *o = component.create();
3389 QCOMPARE(o->property("test").toBool(), true);
3393 void tst_qdeclarativeecmascript::qtbug_11600()
3395 QDeclarativeComponent component(&engine, TEST_FILE("qtbug_11600.qml"));
3396 QObject *o = component.create();
3398 QCOMPARE(o->property("test").toBool(), true);
3402 // Reading and writing non-scriptable properties should fail
3403 void tst_qdeclarativeecmascript::nonscriptable()
3405 QDeclarativeComponent component(&engine, TEST_FILE("nonscriptable.qml"));
3406 QObject *o = component.create();
3408 QCOMPARE(o->property("readOk").toBool(), true);
3409 QCOMPARE(o->property("writeOk").toBool(), true);
3413 // deleteLater() should not be callable from QML
3414 void tst_qdeclarativeecmascript::deleteLater()
3416 QDeclarativeComponent component(&engine, TEST_FILE("deleteLater.qml"));
3417 QObject *o = component.create();
3419 QCOMPARE(o->property("test").toBool(), true);
3423 void tst_qdeclarativeecmascript::in()
3425 QDeclarativeComponent component(&engine, TEST_FILE("in.qml"));
3426 QObject *o = component.create();
3428 QCOMPARE(o->property("test1").toBool(), true);
3429 QCOMPARE(o->property("test2").toBool(), true);
3433 void tst_qdeclarativeecmascript::sharedAttachedObject()
3435 QDeclarativeComponent component(&engine, TEST_FILE("sharedAttachedObject.qml"));
3436 QObject *o = component.create();
3438 QCOMPARE(o->property("test1").toBool(), true);
3439 QCOMPARE(o->property("test2").toBool(), true);
3444 void tst_qdeclarativeecmascript::objectName()
3446 QDeclarativeComponent component(&engine, TEST_FILE("objectName.qml"));
3447 QObject *o = component.create();
3450 QCOMPARE(o->property("test1").toString(), QString("hello"));
3451 QCOMPARE(o->property("test2").toString(), QString("ell"));
3453 o->setObjectName("world");
3455 QCOMPARE(o->property("test1").toString(), QString("world"));
3456 QCOMPARE(o->property("test2").toString(), QString("orl"));
3461 void tst_qdeclarativeecmascript::writeRemovesBinding()
3463 QDeclarativeComponent component(&engine, TEST_FILE("writeRemovesBinding.qml"));
3464 QObject *o = component.create();
3467 QCOMPARE(o->property("test").toBool(), true);
3472 // Test bindings assigned to alias properties actually assign to the alias' target
3473 void tst_qdeclarativeecmascript::aliasBindingsAssignCorrectly()
3475 QDeclarativeComponent component(&engine, TEST_FILE("aliasBindingsAssignCorrectly.qml"));
3476 QObject *o = component.create();
3479 QCOMPARE(o->property("test").toBool(), true);
3484 // Test bindings assigned to alias properties override a binding on the target (QTBUG-13719)
3485 void tst_qdeclarativeecmascript::aliasBindingsOverrideTarget()
3488 QDeclarativeComponent component(&engine, TEST_FILE("aliasBindingsOverrideTarget.qml"));
3489 QObject *o = component.create();
3492 QCOMPARE(o->property("test").toBool(), true);
3498 QDeclarativeComponent component(&engine, TEST_FILE("aliasBindingsOverrideTarget.2.qml"));
3499 QObject *o = component.create();
3502 QCOMPARE(o->property("test").toBool(), true);
3508 QDeclarativeComponent component(&engine, TEST_FILE("aliasBindingsOverrideTarget.3.qml"));
3509 QObject *o = component.create();
3512 QCOMPARE(o->property("test").toBool(), true);
3518 // Test that writes to alias properties override bindings on the alias target (QTBUG-13719)
3519 void tst_qdeclarativeecmascript::aliasWritesOverrideBindings()
3522 QDeclarativeComponent component(&engine, TEST_FILE("aliasWritesOverrideBindings.qml"));
3523 QObject *o = component.create();
3526 QCOMPARE(o->property("test").toBool(), true);
3532 QDeclarativeComponent component(&engine, TEST_FILE("aliasWritesOverrideBindings.2.qml"));
3533 QObject *o = component.create();
3536 QCOMPARE(o->property("test").toBool(), true);
3542 QDeclarativeComponent component(&engine, TEST_FILE("aliasWritesOverrideBindings.3.qml"));
3543 QObject *o = component.create();
3546 QCOMPARE(o->property("test").toBool(), true);
3552 // Allow an alais to a composite element
3554 void tst_qdeclarativeecmascript::aliasToCompositeElement()
3556 QDeclarativeComponent component(&engine, TEST_FILE("aliasToCompositeElement.qml"));
3558 QObject *object = component.create();
3559 QVERIFY(object != 0);
3564 void tst_qdeclarativeecmascript::revisionErrors()
3567 QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevisionErrors.qml"));
3568 QString url = component.url().toString();
3570 QString warning1 = url + ":8: ReferenceError: Can't find variable: prop2";
3571 QString warning2 = url + ":11: ReferenceError: Can't find variable: prop2";
3572 QString warning3 = url + ":13: ReferenceError: Can't find variable: method2";
3574 QTest::ignoreMessage(QtWarningMsg, warning1.toLatin1().constData());
3575 QTest::ignoreMessage(QtWarningMsg, warning2.toLatin1().constData());
3576 QTest::ignoreMessage(QtWarningMsg, warning3.toLatin1().constData());
3577 MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create());
3578 QVERIFY(object != 0);
3582 QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevisionErrors2.qml"));
3583 QString url = component.url().toString();
3585 // MyRevisionedSubclass 1.0 uses MyRevisionedClass revision 0
3586 // method2, prop2 from MyRevisionedClass not available
3587 // method4, prop4 from MyRevisionedSubclass not available
3588 QString warning1 = url + ":8: ReferenceError: Can't find variable: prop2";
3589 QString warning2 = url + ":14: ReferenceError: Can't find variable: prop2";
3590 QString warning3 = url + ":10: ReferenceError: Can't find variable: prop4";
3591 QString warning4 = url + ":16: ReferenceError: Can't find variable: prop4";
3592 QString warning5 = url + ":20: ReferenceError: Can't find variable: method2";
3594 QTest::ignoreMessage(QtWarningMsg, warning1.toLatin1().constData());
3595 QTest::ignoreMessage(QtWarningMsg, warning2.toLatin1().constData());
3596 QTest::ignoreMessage(QtWarningMsg, warning3.toLatin1().constData());
3597 QTest::ignoreMessage(QtWarningMsg, warning4.toLatin1().constData());
3598 QTest::ignoreMessage(QtWarningMsg, warning5.toLatin1().constData());
3599 MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create());
3600 QVERIFY(object != 0);
3604 QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevisionErrors3.qml"));
3605 QString url = component.url().toString();
3607 // MyRevisionedSubclass 1.1 uses MyRevisionedClass revision 1
3608 // All properties/methods available, except MyRevisionedBaseClassUnregistered rev 1
3609 QString warning1 = url + ":30: ReferenceError: Can't find variable: methodD";
3610 QString warning2 = url + ":10: ReferenceError: Can't find variable: propD";
3611 QString warning3 = url + ":20: ReferenceError: Can't find variable: propD";
3612 QTest::ignoreMessage(QtWarningMsg, warning1.toLatin1().constData());
3613 QTest::ignoreMessage(QtWarningMsg, warning2.toLatin1().constData());
3614 QTest::ignoreMessage(QtWarningMsg, warning3.toLatin1().constData());
3615 MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create());
3616 QVERIFY(object != 0);
3621 void tst_qdeclarativeecmascript::revision()
3624 QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevision.qml"));
3625 QString url = component.url().toString();
3627 MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create());
3628 QVERIFY(object != 0);
3632 QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevision2.qml"));
3633 QString url = component.url().toString();
3635 MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create());
3636 QVERIFY(object != 0);
3640 QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevision3.qml"));
3641 QString url = component.url().toString();
3643 MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create());
3644 QVERIFY(object != 0);
3647 // Test that non-root classes can resolve revisioned methods
3649 QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevision4.qml"));
3651 QObject *object = component.create();
3652 QVERIFY(object != 0);
3653 QCOMPARE(object->property("test").toReal(), 11.);
3658 void tst_qdeclarativeecmascript::realToInt()
3660 QDeclarativeComponent component(&engine, TEST_FILE("realToInt.qml"));
3661 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
3662 QVERIFY(object != 0);
3664 QMetaObject::invokeMethod(object, "test1");
3665 QCOMPARE(object->value(), int(4));
3666 QMetaObject::invokeMethod(object, "test2");
3667 QCOMPARE(object->value(), int(8));
3669 void tst_qdeclarativeecmascript::dynamicString()
3671 QDeclarativeComponent component(&engine, TEST_FILE("dynamicString.qml"));
3672 QObject *object = component.create();
3673 QVERIFY(object != 0);
3674 QCOMPARE(object->property("stringProperty").toString(),
3675 QString::fromLatin1("string:Hello World false:0 true:1 uint32:100 int32:-100 double:3.14159 date:2011-02-11 05::30:50!"));
3678 QTEST_MAIN(tst_qdeclarativeecmascript)
3680 #include "tst_qdeclarativeecmascript.moc"