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/qdeclarativeglobalscriptclass_p.h>
53 #include <private/qscriptdeclarativeclass_p.h>
54 #include "testtypes.h"
55 #include "testhttpserver.h"
56 #include "../../../shared/util.h"
59 // In Symbian OS test data is located in applications private dir
64 This test covers evaluation of ECMAScript expressions and bindings from within
65 QML. This does not include static QML language issues.
67 Static QML language issues are covered in qmllanguage
69 inline QUrl TEST_FILE(const QString &filename)
71 QFileInfo fileInfo(__FILE__);
72 return QUrl::fromLocalFile(fileInfo.absoluteDir().filePath("data/" + filename));
75 inline QUrl TEST_FILE(const char *filename)
77 return TEST_FILE(QLatin1String(filename));
80 class tst_qdeclarativeecmascript : public QObject
84 tst_qdeclarativeecmascript() {}
88 void assignBasicTypes();
89 void idShortcutInvalidates();
90 void boolPropertiesEvaluateAsBool();
92 void signalAssignment();
94 void basicExpressions();
95 void basicExpressions_data();
96 void arrayExpressions();
97 void contextPropertiesTriggerReeval();
98 void objectPropertiesTriggerReeval();
99 void deferredProperties();
100 void deferredPropertiesErrors();
101 void extensionObjects();
102 void overrideExtensionProperties();
103 void attachedProperties();
105 void valueTypeFunctions();
106 void constantsOverrideBindings();
107 void outerBindingOverridesInnerBinding();
108 void aliasPropertyAndBinding();
109 void nonExistentAttachedObject();
112 void signalParameterTypes();
113 void objectsCompareAsEqual();
114 void dynamicCreation_data();
115 void dynamicCreation();
116 void dynamicDestruction();
117 void objectToString();
118 void selfDeletingBinding();
119 void extendedObjectPropertyLookup();
121 void functionErrors();
122 void propertyAssignmentErrors();
123 void signalTriggeredBindings();
124 void listProperties();
125 void exceptionClearsOnReeval();
126 void exceptionSlotProducesWarning();
127 void exceptionBindingProducesWarning();
128 void transientErrors();
129 void shutdownErrors();
130 void compositePropertyType();
132 void undefinedResetsProperty();
133 void listToVariant();
134 void multiEngineObject();
135 void deletedObject();
136 void attachedPropertyScope();
137 void scriptConnect();
138 void scriptDisconnect();
140 void cppOwnershipReturnValue();
141 void ownershipCustomReturnValue();
142 void qlistqobjectMethods();
143 void strictlyEquals();
145 void numberAssignment();
146 void propertySplicing();
147 void signalWithUnknownTypes();
149 void importScripts();
150 void scarceResources();
151 void propertyChangeSlots();
155 void dynamicCreationCrash();
157 void nullObjectBinding();
158 void deletedEngine();
159 void libraryScriptAssert();
160 void variantsAssignedUndefined();
162 void qtcreatorbug_1289();
163 void noSpuriousWarningsAtShutdown();
164 void canAssignNullToQObject();
165 void functionAssignment_fromBinding();
166 void functionAssignment_fromJS();
167 void functionAssignment_fromJS_data();
168 void functionAssignmentfromJS_invalid();
174 void nonscriptable();
177 void sharedAttachedObject();
179 void writeRemovesBinding();
180 void aliasBindingsAssignCorrectly();
181 void aliasBindingsOverrideTarget();
182 void aliasWritesOverrideBindings();
183 void pushCleanContext();
188 void callQtInvokables();
189 void invokableObjectArg();
190 void invokableObjectRet();
192 void revisionErrors();
195 QDeclarativeEngine engine;
198 void tst_qdeclarativeecmascript::initTestCase() { registerTypes(); }
200 void tst_qdeclarativeecmascript::assignBasicTypes()
203 QDeclarativeComponent component(&engine, TEST_FILE("assignBasicTypes.qml"));
204 MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
205 QVERIFY(object != 0);
206 QCOMPARE(object->flagProperty(), MyTypeObject::FlagVal1 | MyTypeObject::FlagVal3);
207 QCOMPARE(object->enumProperty(), MyTypeObject::EnumVal2);
208 QCOMPARE(object->stringProperty(), QString("Hello World!"));
209 QCOMPARE(object->uintProperty(), uint(10));
210 QCOMPARE(object->intProperty(), -19);
211 QCOMPARE((float)object->realProperty(), float(23.2));
212 QCOMPARE((float)object->doubleProperty(), float(-19.75));
213 QCOMPARE((float)object->floatProperty(), float(8.5));
214 QCOMPARE(object->colorProperty(), QColor("red"));
215 QCOMPARE(object->dateProperty(), QDate(1982, 11, 25));
216 QCOMPARE(object->timeProperty(), QTime(11, 11, 32));
217 QCOMPARE(object->dateTimeProperty(), QDateTime(QDate(2009, 5, 12), QTime(13, 22, 1)));
218 QCOMPARE(object->pointProperty(), QPoint(99,13));
219 QCOMPARE(object->pointFProperty(), QPointF(-10.1, 12.3));
220 QCOMPARE(object->sizeProperty(), QSize(99, 13));
221 QCOMPARE(object->sizeFProperty(), QSizeF(0.1, 0.2));
222 QCOMPARE(object->rectProperty(), QRect(9, 7, 100, 200));
223 QCOMPARE(object->rectFProperty(), QRectF(1000.1, -10.9, 400, 90.99));
224 QCOMPARE(object->boolProperty(), true);
225 QCOMPARE(object->variantProperty(), QVariant("Hello World!"));
226 QCOMPARE(object->vectorProperty(), QVector3D(10, 1, 2.2));
227 QCOMPARE(object->urlProperty(), component.url().resolved(QUrl("main.qml")));
231 QDeclarativeComponent component(&engine, TEST_FILE("assignBasicTypes.2.qml"));
232 MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
233 QVERIFY(object != 0);
234 QCOMPARE(object->flagProperty(), MyTypeObject::FlagVal1 | MyTypeObject::FlagVal3);
235 QCOMPARE(object->enumProperty(), MyTypeObject::EnumVal2);
236 QCOMPARE(object->stringProperty(), QString("Hello World!"));
237 QCOMPARE(object->uintProperty(), uint(10));
238 QCOMPARE(object->intProperty(), -19);
239 QCOMPARE((float)object->realProperty(), float(23.2));
240 QCOMPARE((float)object->doubleProperty(), float(-19.75));
241 QCOMPARE((float)object->floatProperty(), float(8.5));
242 QCOMPARE(object->colorProperty(), QColor("red"));
243 QCOMPARE(object->dateProperty(), QDate(1982, 11, 25));
244 QCOMPARE(object->timeProperty(), QTime(11, 11, 32));
245 QCOMPARE(object->dateTimeProperty(), QDateTime(QDate(2009, 5, 12), QTime(13, 22, 1)));
246 QCOMPARE(object->pointProperty(), QPoint(99,13));
247 QCOMPARE(object->pointFProperty(), QPointF(-10.1, 12.3));
248 QCOMPARE(object->sizeProperty(), QSize(99, 13));
249 QCOMPARE(object->sizeFProperty(), QSizeF(0.1, 0.2));
250 QCOMPARE(object->rectProperty(), QRect(9, 7, 100, 200));
251 QCOMPARE(object->rectFProperty(), QRectF(1000.1, -10.9, 400, 90.99));
252 QCOMPARE(object->boolProperty(), true);
253 QCOMPARE(object->variantProperty(), QVariant("Hello World!"));
254 QCOMPARE(object->vectorProperty(), QVector3D(10, 1, 2.2));
255 QCOMPARE(object->urlProperty(), component.url().resolved(QUrl("main.qml")));
260 void tst_qdeclarativeecmascript::idShortcutInvalidates()
263 QDeclarativeComponent component(&engine, TEST_FILE("idShortcutInvalidates.qml"));
264 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
265 QVERIFY(object != 0);
266 QVERIFY(object->objectProperty() != 0);
267 delete object->objectProperty();
268 QVERIFY(object->objectProperty() == 0);
273 QDeclarativeComponent component(&engine, TEST_FILE("idShortcutInvalidates.1.qml"));
274 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
275 QVERIFY(object != 0);
276 QVERIFY(object->objectProperty() != 0);
277 delete object->objectProperty();
278 QVERIFY(object->objectProperty() == 0);
283 void tst_qdeclarativeecmascript::boolPropertiesEvaluateAsBool()
286 QDeclarativeComponent component(&engine, TEST_FILE("boolPropertiesEvaluateAsBool.1.qml"));
287 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
288 QVERIFY(object != 0);
289 QCOMPARE(object->stringProperty(), QLatin1String("pass"));
293 QDeclarativeComponent component(&engine, TEST_FILE("boolPropertiesEvaluateAsBool.2.qml"));
294 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
295 QVERIFY(object != 0);
296 QCOMPARE(object->stringProperty(), QLatin1String("pass"));
301 void tst_qdeclarativeecmascript::signalAssignment()
304 QDeclarativeComponent component(&engine, TEST_FILE("signalAssignment.1.qml"));
305 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
306 QVERIFY(object != 0);
307 QCOMPARE(object->string(), QString());
308 emit object->basicSignal();
309 QCOMPARE(object->string(), QString("pass"));
314 QDeclarativeComponent component(&engine, TEST_FILE("signalAssignment.2.qml"));
315 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
316 QVERIFY(object != 0);
317 QCOMPARE(object->string(), QString());
318 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
319 QCOMPARE(object->string(), QString("pass 19 Hello world! 10.25 3 2"));
324 void tst_qdeclarativeecmascript::methods()
327 QDeclarativeComponent component(&engine, TEST_FILE("methods.1.qml"));
328 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
329 QVERIFY(object != 0);
330 QCOMPARE(object->methodCalled(), false);
331 QCOMPARE(object->methodIntCalled(), false);
332 emit object->basicSignal();
333 QCOMPARE(object->methodCalled(), true);
334 QCOMPARE(object->methodIntCalled(), false);
339 QDeclarativeComponent component(&engine, TEST_FILE("methods.2.qml"));
340 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
341 QVERIFY(object != 0);
342 QCOMPARE(object->methodCalled(), false);
343 QCOMPARE(object->methodIntCalled(), false);
344 emit object->basicSignal();
345 QCOMPARE(object->methodCalled(), false);
346 QCOMPARE(object->methodIntCalled(), true);
351 QDeclarativeComponent component(&engine, TEST_FILE("methods.3.qml"));
352 QObject *object = component.create();
353 QVERIFY(object != 0);
354 QCOMPARE(object->property("test").toInt(), 19);
359 QDeclarativeComponent component(&engine, TEST_FILE("methods.4.qml"));
360 QObject *object = component.create();
361 QVERIFY(object != 0);
362 QCOMPARE(object->property("test").toInt(), 19);
363 QCOMPARE(object->property("test2").toInt(), 17);
364 QCOMPARE(object->property("test3").toInt(), 16);
369 QDeclarativeComponent component(&engine, TEST_FILE("methods.5.qml"));
370 QObject *object = component.create();
371 QVERIFY(object != 0);
372 QCOMPARE(object->property("test").toInt(), 9);
377 void tst_qdeclarativeecmascript::bindingLoop()
379 QDeclarativeComponent component(&engine, TEST_FILE("bindingLoop.qml"));
380 QString warning = component.url().toString() + ":9:9: QML MyQmlObject: Binding loop detected for property \"stringProperty\"";
381 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
382 QObject *object = component.create();
383 QVERIFY(object != 0);
387 void tst_qdeclarativeecmascript::basicExpressions_data()
389 QTest::addColumn<QString>("expression");
390 QTest::addColumn<QVariant>("result");
391 QTest::addColumn<bool>("nest");
393 QTest::newRow("Syntax error (self test)") << "{console.log({'a':1'}.a)}" << QVariant() << false;
394 QTest::newRow("Context property") << "a" << QVariant(1944) << false;
395 QTest::newRow("Context property") << "a" << QVariant(1944) << true;
396 QTest::newRow("Context property expression") << "a * 2" << QVariant(3888) << false;
397 QTest::newRow("Context property expression") << "a * 2" << QVariant(3888) << true;
398 QTest::newRow("Overridden context property") << "b" << QVariant("Milk") << false;
399 QTest::newRow("Overridden context property") << "b" << QVariant("Cow") << true;
400 QTest::newRow("Object property") << "object.stringProperty" << QVariant("Object1") << false;
401 QTest::newRow("Object property") << "object.stringProperty" << QVariant("Object1") << true;
402 QTest::newRow("Overridden object property") << "objectOverride.stringProperty" << QVariant("Object2") << false;
403 QTest::newRow("Overridden object property") << "objectOverride.stringProperty" << QVariant("Object3") << true;
404 QTest::newRow("Default object property") << "horseLegs" << QVariant(4) << false;
405 QTest::newRow("Default object property") << "antLegs" << QVariant(6) << false;
406 QTest::newRow("Default object property") << "emuLegs" << QVariant(2) << false;
407 QTest::newRow("Nested default object property") << "horseLegs" << QVariant(4) << true;
408 QTest::newRow("Nested default object property") << "antLegs" << QVariant(7) << true;
409 QTest::newRow("Nested default object property") << "emuLegs" << QVariant(2) << true;
410 QTest::newRow("Nested default object property") << "humanLegs" << QVariant(2) << true;
411 QTest::newRow("Context property override default object property") << "millipedeLegs" << QVariant(100) << true;
414 void tst_qdeclarativeecmascript::basicExpressions()
416 QFETCH(QString, expression);
417 QFETCH(QVariant, result);
423 MyDefaultObject1 default1;
424 MyDefaultObject3 default3;
425 object1.setStringProperty("Object1");
426 object2.setStringProperty("Object2");
427 object3.setStringProperty("Object3");
429 QDeclarativeContext context(engine.rootContext());
430 QDeclarativeContext nestedContext(&context);
432 context.setContextObject(&default1);
433 context.setContextProperty("a", QVariant(1944));
434 context.setContextProperty("b", QVariant("Milk"));
435 context.setContextProperty("object", &object1);
436 context.setContextProperty("objectOverride", &object2);
437 nestedContext.setContextObject(&default3);
438 nestedContext.setContextProperty("b", QVariant("Cow"));
439 nestedContext.setContextProperty("objectOverride", &object3);
440 nestedContext.setContextProperty("millipedeLegs", QVariant(100));
442 MyExpression expr(nest?&nestedContext:&context, expression);
443 QCOMPARE(expr.evaluate(), result);
446 void tst_qdeclarativeecmascript::arrayExpressions()
452 QDeclarativeContext context(engine.rootContext());
453 context.setContextProperty("a", &obj1);
454 context.setContextProperty("b", &obj2);
455 context.setContextProperty("c", &obj3);
457 MyExpression expr(&context, "[a, b, c, 10]");
458 QVariant result = expr.evaluate();
459 QCOMPARE(result.userType(), qMetaTypeId<QList<QObject *> >());
460 QList<QObject *> list = qvariant_cast<QList<QObject *> >(result);
461 QCOMPARE(list.count(), 4);
462 QCOMPARE(list.at(0), &obj1);
463 QCOMPARE(list.at(1), &obj2);
464 QCOMPARE(list.at(2), &obj3);
465 QCOMPARE(list.at(3), (QObject *)0);
468 // Tests that modifying a context property will reevaluate expressions
469 void tst_qdeclarativeecmascript::contextPropertiesTriggerReeval()
471 QDeclarativeContext context(engine.rootContext());
474 MyQmlObject *object3 = new MyQmlObject;
476 object1.setStringProperty("Hello");
477 object2.setStringProperty("World");
479 context.setContextProperty("testProp", QVariant(1));
480 context.setContextProperty("testObj", &object1);
481 context.setContextProperty("testObj2", object3);
484 MyExpression expr(&context, "testProp + 1");
485 QCOMPARE(expr.changed, false);
486 QCOMPARE(expr.evaluate(), QVariant(2));
488 context.setContextProperty("testProp", QVariant(2));
489 QCOMPARE(expr.changed, true);
490 QCOMPARE(expr.evaluate(), QVariant(3));
494 MyExpression expr(&context, "testProp + testProp + testProp");
495 QCOMPARE(expr.changed, false);
496 QCOMPARE(expr.evaluate(), QVariant(6));
498 context.setContextProperty("testProp", QVariant(4));
499 QCOMPARE(expr.changed, true);
500 QCOMPARE(expr.evaluate(), QVariant(12));
504 MyExpression expr(&context, "testObj.stringProperty");
505 QCOMPARE(expr.changed, false);
506 QCOMPARE(expr.evaluate(), QVariant("Hello"));
508 context.setContextProperty("testObj", &object2);
509 QCOMPARE(expr.changed, true);
510 QCOMPARE(expr.evaluate(), QVariant("World"));
514 MyExpression expr(&context, "testObj.stringProperty /**/");
515 QCOMPARE(expr.changed, false);
516 QCOMPARE(expr.evaluate(), QVariant("World"));
518 context.setContextProperty("testObj", &object1);
519 QCOMPARE(expr.changed, true);
520 QCOMPARE(expr.evaluate(), QVariant("Hello"));
524 MyExpression expr(&context, "testObj2");
525 QCOMPARE(expr.changed, false);
526 QCOMPARE(expr.evaluate(), QVariant::fromValue((QObject *)object3));
532 void tst_qdeclarativeecmascript::objectPropertiesTriggerReeval()
534 QDeclarativeContext context(engine.rootContext());
538 context.setContextProperty("testObj", &object1);
540 object1.setStringProperty(QLatin1String("Hello"));
541 object2.setStringProperty(QLatin1String("Dog"));
542 object3.setStringProperty(QLatin1String("Cat"));
545 MyExpression expr(&context, "testObj.stringProperty");
546 QCOMPARE(expr.changed, false);
547 QCOMPARE(expr.evaluate(), QVariant("Hello"));
549 object1.setStringProperty(QLatin1String("World"));
550 QCOMPARE(expr.changed, true);
551 QCOMPARE(expr.evaluate(), QVariant("World"));
555 MyExpression expr(&context, "testObj.objectProperty.stringProperty");
556 QCOMPARE(expr.changed, false);
557 QCOMPARE(expr.evaluate(), QVariant());
559 object1.setObjectProperty(&object2);
560 QCOMPARE(expr.changed, true);
561 expr.changed = false;
562 QCOMPARE(expr.evaluate(), QVariant("Dog"));
564 object1.setObjectProperty(&object3);
565 QCOMPARE(expr.changed, true);
566 expr.changed = false;
567 QCOMPARE(expr.evaluate(), QVariant("Cat"));
569 object1.setObjectProperty(0);
570 QCOMPARE(expr.changed, true);
571 expr.changed = false;
572 QCOMPARE(expr.evaluate(), QVariant());
574 object1.setObjectProperty(&object3);
575 QCOMPARE(expr.changed, true);
576 expr.changed = false;
577 QCOMPARE(expr.evaluate(), QVariant("Cat"));
579 object3.setStringProperty("Donkey");
580 QCOMPARE(expr.changed, true);
581 expr.changed = false;
582 QCOMPARE(expr.evaluate(), QVariant("Donkey"));
586 void tst_qdeclarativeecmascript::deferredProperties()
588 QDeclarativeComponent component(&engine, TEST_FILE("deferredProperties.qml"));
589 MyDeferredObject *object =
590 qobject_cast<MyDeferredObject *>(component.create());
591 QVERIFY(object != 0);
592 QCOMPARE(object->value(), 0);
593 QVERIFY(object->objectProperty() == 0);
594 QVERIFY(object->objectProperty2() != 0);
595 qmlExecuteDeferred(object);
596 QCOMPARE(object->value(), 10);
597 QVERIFY(object->objectProperty() != 0);
598 MyQmlObject *qmlObject =
599 qobject_cast<MyQmlObject *>(object->objectProperty());
600 QVERIFY(qmlObject != 0);
601 QCOMPARE(qmlObject->value(), 10);
602 object->setValue(19);
603 QCOMPARE(qmlObject->value(), 19);
608 // Check errors on deferred properties are correctly emitted
609 void tst_qdeclarativeecmascript::deferredPropertiesErrors()
611 QDeclarativeComponent component(&engine, TEST_FILE("deferredPropertiesErrors.qml"));
612 MyDeferredObject *object =
613 qobject_cast<MyDeferredObject *>(component.create());
614 QVERIFY(object != 0);
615 QCOMPARE(object->value(), 0);
616 QVERIFY(object->objectProperty() == 0);
617 QVERIFY(object->objectProperty2() == 0);
619 QString warning = component.url().toString() + ":6: Unable to assign [undefined] to QObject* objectProperty";
620 QTest::ignoreMessage(QtWarningMsg, qPrintable(warning));
622 qmlExecuteDeferred(object);
627 void tst_qdeclarativeecmascript::extensionObjects()
629 QDeclarativeComponent component(&engine, TEST_FILE("extensionObjects.qml"));
630 MyExtendedObject *object =
631 qobject_cast<MyExtendedObject *>(component.create());
632 QVERIFY(object != 0);
633 QCOMPARE(object->baseProperty(), 13);
634 QCOMPARE(object->coreProperty(), 9);
635 object->setProperty("extendedProperty", QVariant(11));
636 object->setProperty("baseExtendedProperty", QVariant(92));
637 QCOMPARE(object->coreProperty(), 11);
638 QCOMPARE(object->baseProperty(), 92);
640 MyExtendedObject *nested = qobject_cast<MyExtendedObject*>(qvariant_cast<QObject *>(object->property("nested")));
642 QCOMPARE(nested->baseProperty(), 13);
643 QCOMPARE(nested->coreProperty(), 9);
644 nested->setProperty("extendedProperty", QVariant(11));
645 nested->setProperty("baseExtendedProperty", QVariant(92));
646 QCOMPARE(nested->coreProperty(), 11);
647 QCOMPARE(nested->baseProperty(), 92);
652 void tst_qdeclarativeecmascript::overrideExtensionProperties()
654 QDeclarativeComponent component(&engine, TEST_FILE("extensionObjectsPropertyOverride.qml"));
655 OverrideDefaultPropertyObject *object =
656 qobject_cast<OverrideDefaultPropertyObject *>(component.create());
657 QVERIFY(object != 0);
658 QVERIFY(object->secondProperty() != 0);
659 QVERIFY(object->firstProperty() == 0);
664 void tst_qdeclarativeecmascript::attachedProperties()
667 QDeclarativeComponent component(&engine, TEST_FILE("attachedProperty.qml"));
668 QObject *object = component.create();
669 QVERIFY(object != 0);
670 QCOMPARE(object->property("a").toInt(), 19);
671 QCOMPARE(object->property("b").toInt(), 19);
672 QCOMPARE(object->property("c").toInt(), 19);
673 QCOMPARE(object->property("d").toInt(), 19);
678 QDeclarativeComponent component(&engine, TEST_FILE("attachedProperty.2.qml"));
679 QObject *object = component.create();
680 QVERIFY(object != 0);
681 QCOMPARE(object->property("a").toInt(), 26);
682 QCOMPARE(object->property("b").toInt(), 26);
683 QCOMPARE(object->property("c").toInt(), 26);
684 QCOMPARE(object->property("d").toInt(), 26);
688 QDeclarativeComponent component(&engine, TEST_FILE("writeAttachedProperty.qml"));
689 QObject *object = component.create();
690 QVERIFY(object != 0);
692 QMetaObject::invokeMethod(object, "writeValue2");
694 MyQmlAttachedObject *attached =
695 qobject_cast<MyQmlAttachedObject *>(qmlAttachedPropertiesObject<MyQmlObject>(object));
696 QVERIFY(attached != 0);
698 QCOMPARE(attached->value2(), 9);
703 void tst_qdeclarativeecmascript::enums()
707 QDeclarativeComponent component(&engine, TEST_FILE("enums.1.qml"));
708 QObject *object = component.create();
709 QVERIFY(object != 0);
711 QCOMPARE(object->property("a").toInt(), 0);
712 QCOMPARE(object->property("b").toInt(), 1);
713 QCOMPARE(object->property("c").toInt(), 2);
714 QCOMPARE(object->property("d").toInt(), 3);
715 QCOMPARE(object->property("e").toInt(), 0);
716 QCOMPARE(object->property("f").toInt(), 1);
717 QCOMPARE(object->property("g").toInt(), 2);
718 QCOMPARE(object->property("h").toInt(), 3);
719 QCOMPARE(object->property("i").toInt(), 19);
720 QCOMPARE(object->property("j").toInt(), 19);
724 // Non-existent enums
726 QDeclarativeComponent component(&engine, TEST_FILE("enums.2.qml"));
728 QString warning1 = component.url().toString() + ":5: Unable to assign [undefined] to int a";
729 QString warning2 = component.url().toString() + ":6: Unable to assign [undefined] to int b";
730 QTest::ignoreMessage(QtWarningMsg, qPrintable(warning1));
731 QTest::ignoreMessage(QtWarningMsg, qPrintable(warning2));
733 QObject *object = component.create();
734 QVERIFY(object != 0);
735 QCOMPARE(object->property("a").toInt(), 0);
736 QCOMPARE(object->property("b").toInt(), 0);
742 void tst_qdeclarativeecmascript::valueTypeFunctions()
744 QDeclarativeComponent component(&engine, TEST_FILE("valueTypeFunctions.qml"));
745 MyTypeObject *obj = qobject_cast<MyTypeObject*>(component.create());
747 QCOMPARE(obj->rectProperty(), QRect(0,0,100,100));
748 QCOMPARE(obj->rectFProperty(), QRectF(0,0.5,100,99.5));
754 Tests that writing a constant to a property with a binding on it disables the
757 void tst_qdeclarativeecmascript::constantsOverrideBindings()
761 QDeclarativeComponent component(&engine, TEST_FILE("constantsOverrideBindings.1.qml"));
762 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
763 QVERIFY(object != 0);
765 QCOMPARE(object->property("c2").toInt(), 0);
766 object->setProperty("c1", QVariant(9));
767 QCOMPARE(object->property("c2").toInt(), 9);
769 emit object->basicSignal();
771 QCOMPARE(object->property("c2").toInt(), 13);
772 object->setProperty("c1", QVariant(8));
773 QCOMPARE(object->property("c2").toInt(), 13);
778 // During construction
780 QDeclarativeComponent component(&engine, TEST_FILE("constantsOverrideBindings.2.qml"));
781 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
782 QVERIFY(object != 0);
784 QCOMPARE(object->property("c1").toInt(), 0);
785 QCOMPARE(object->property("c2").toInt(), 10);
786 object->setProperty("c1", QVariant(9));
787 QCOMPARE(object->property("c1").toInt(), 9);
788 QCOMPARE(object->property("c2").toInt(), 10);
796 QDeclarativeComponent component(&engine, TEST_FILE("constantsOverrideBindings.3.qml"));
797 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
798 QVERIFY(object != 0);
800 QCOMPARE(object->property("c2").toInt(), 0);
801 object->setProperty("c1", QVariant(9));
802 QCOMPARE(object->property("c2").toInt(), 9);
804 object->setProperty("c2", QVariant(13));
805 QCOMPARE(object->property("c2").toInt(), 13);
806 object->setProperty("c1", QVariant(7));
807 QCOMPARE(object->property("c1").toInt(), 7);
808 QCOMPARE(object->property("c2").toInt(), 13);
816 QDeclarativeComponent component(&engine, TEST_FILE("constantsOverrideBindings.4.qml"));
817 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
818 QVERIFY(object != 0);
820 QCOMPARE(object->property("c1").toInt(), 0);
821 QCOMPARE(object->property("c3").toInt(), 10);
822 object->setProperty("c1", QVariant(9));
823 QCOMPARE(object->property("c1").toInt(), 9);
824 QCOMPARE(object->property("c3").toInt(), 10);
831 Tests that assigning a binding to a property that already has a binding causes
832 the original binding to be disabled.
834 void tst_qdeclarativeecmascript::outerBindingOverridesInnerBinding()
836 QDeclarativeComponent component(&engine,
837 TEST_FILE("outerBindingOverridesInnerBinding.qml"));
838 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
839 QVERIFY(object != 0);
841 QCOMPARE(object->property("c1").toInt(), 0);
842 QCOMPARE(object->property("c2").toInt(), 0);
843 QCOMPARE(object->property("c3").toInt(), 0);
845 object->setProperty("c1", QVariant(9));
846 QCOMPARE(object->property("c1").toInt(), 9);
847 QCOMPARE(object->property("c2").toInt(), 0);
848 QCOMPARE(object->property("c3").toInt(), 0);
850 object->setProperty("c3", QVariant(8));
851 QCOMPARE(object->property("c1").toInt(), 9);
852 QCOMPARE(object->property("c2").toInt(), 8);
853 QCOMPARE(object->property("c3").toInt(), 8);
859 Access a non-existent attached object.
861 Tests for a regression where this used to crash.
863 void tst_qdeclarativeecmascript::nonExistentAttachedObject()
865 QDeclarativeComponent component(&engine, TEST_FILE("nonExistentAttachedObject.qml"));
867 QString warning = component.url().toString() + ":4: Unable to assign [undefined] to QString stringProperty";
868 QTest::ignoreMessage(QtWarningMsg, qPrintable(warning));
870 QObject *object = component.create();
871 QVERIFY(object != 0);
876 void tst_qdeclarativeecmascript::scope()
879 QDeclarativeComponent component(&engine, TEST_FILE("scope.qml"));
880 QObject *object = component.create();
881 QVERIFY(object != 0);
883 QCOMPARE(object->property("test1").toInt(), 1);
884 QCOMPARE(object->property("test2").toInt(), 2);
885 QCOMPARE(object->property("test3").toString(), QString("1Test"));
886 QCOMPARE(object->property("test4").toString(), QString("2Test"));
887 QCOMPARE(object->property("test5").toInt(), 1);
888 QCOMPARE(object->property("test6").toInt(), 1);
889 QCOMPARE(object->property("test7").toInt(), 2);
890 QCOMPARE(object->property("test8").toInt(), 2);
891 QCOMPARE(object->property("test9").toInt(), 1);
892 QCOMPARE(object->property("test10").toInt(), 3);
898 QDeclarativeComponent component(&engine, TEST_FILE("scope.2.qml"));
899 QObject *object = component.create();
900 QVERIFY(object != 0);
902 QCOMPARE(object->property("test1").toInt(), 19);
903 QCOMPARE(object->property("test2").toInt(), 19);
904 QCOMPARE(object->property("test3").toInt(), 14);
905 QCOMPARE(object->property("test4").toInt(), 14);
906 QCOMPARE(object->property("test5").toInt(), 24);
907 QCOMPARE(object->property("test6").toInt(), 24);
913 QDeclarativeComponent component(&engine, TEST_FILE("scope.3.qml"));
914 QObject *object = component.create();
915 QVERIFY(object != 0);
917 QCOMPARE(object->property("test1").toBool(), true);
918 QCOMPARE(object->property("test2").toBool(), true);
919 QCOMPARE(object->property("test3").toBool(), true);
924 // Signal argument scope
926 QDeclarativeComponent component(&engine, TEST_FILE("scope.4.qml"));
927 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
928 QVERIFY(object != 0);
930 QCOMPARE(object->property("test").toInt(), 0);
931 QCOMPARE(object->property("test2").toString(), QString());
933 emit object->argumentSignal(13, "Argument Scope", 9, MyQmlObject::EnumValue4, Qt::RightButton);
935 QCOMPARE(object->property("test").toInt(), 13);
936 QCOMPARE(object->property("test2").toString(), QString("Argument Scope"));
942 QDeclarativeComponent component(&engine, TEST_FILE("scope.5.qml"));
943 QObject *object = component.create();
944 QVERIFY(object != 0);
946 QCOMPARE(object->property("test1").toBool(), true);
947 QCOMPARE(object->property("test2").toBool(), true);
953 QDeclarativeComponent component(&engine, TEST_FILE("scope.6.qml"));
954 QObject *object = component.create();
955 QVERIFY(object != 0);
957 QCOMPARE(object->property("test").toBool(), true);
963 // In 4.7, non-library javascript files that had no imports shared the imports of their
965 void tst_qdeclarativeecmascript::importScope()
967 QDeclarativeComponent component(&engine, TEST_FILE("importScope.qml"));
968 QObject *o = component.create();
971 QCOMPARE(o->property("test").toInt(), 240);
977 Tests that "any" type passes through a synthesized signal parameter. This
978 is essentially a test of QDeclarativeMetaType::copy()
980 void tst_qdeclarativeecmascript::signalParameterTypes()
982 QDeclarativeComponent component(&engine, TEST_FILE("signalParameterTypes.qml"));
983 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
984 QVERIFY(object != 0);
986 emit object->basicSignal();
988 QCOMPARE(object->property("intProperty").toInt(), 10);
989 QCOMPARE(object->property("realProperty").toReal(), 19.2);
990 QVERIFY(object->property("colorProperty").value<QColor>() == QColor(255, 255, 0, 255));
991 QVERIFY(object->property("variantProperty") == QVariant::fromValue(QColor(255, 0, 255, 255)));
992 QVERIFY(object->property("enumProperty") == MyQmlObject::EnumValue3);
993 QVERIFY(object->property("qtEnumProperty") == Qt::LeftButton);
999 Test that two JS objects for the same QObject compare as equal.
1001 void tst_qdeclarativeecmascript::objectsCompareAsEqual()
1003 QDeclarativeComponent component(&engine, TEST_FILE("objectsCompareAsEqual.qml"));
1004 QObject *object = component.create();
1005 QVERIFY(object != 0);
1007 QCOMPARE(object->property("test1").toBool(), true);
1008 QCOMPARE(object->property("test2").toBool(), true);
1009 QCOMPARE(object->property("test3").toBool(), true);
1010 QCOMPARE(object->property("test4").toBool(), true);
1011 QCOMPARE(object->property("test5").toBool(), true);
1017 Confirm bindings and alias properties can coexist.
1019 Tests for a regression where the binding would not reevaluate.
1021 void tst_qdeclarativeecmascript::aliasPropertyAndBinding()
1023 QDeclarativeComponent component(&engine, TEST_FILE("aliasPropertyAndBinding.qml"));
1024 QObject *object = component.create();
1025 QVERIFY(object != 0);
1027 QCOMPARE(object->property("c2").toInt(), 3);
1028 QCOMPARE(object->property("c3").toInt(), 3);
1030 object->setProperty("c2", QVariant(19));
1032 QCOMPARE(object->property("c2").toInt(), 19);
1033 QCOMPARE(object->property("c3").toInt(), 19);
1038 void tst_qdeclarativeecmascript::dynamicCreation_data()
1040 QTest::addColumn<QString>("method");
1041 QTest::addColumn<QString>("createdName");
1043 QTest::newRow("One") << "createOne" << "objectOne";
1044 QTest::newRow("Two") << "createTwo" << "objectTwo";
1045 QTest::newRow("Three") << "createThree" << "objectThree";
1049 Test using createQmlObject to dynamically generate an item
1050 Also using createComponent is tested.
1052 void tst_qdeclarativeecmascript::dynamicCreation()
1054 QFETCH(QString, method);
1055 QFETCH(QString, createdName);
1057 QDeclarativeComponent component(&engine, TEST_FILE("dynamicCreation.qml"));
1058 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1059 QVERIFY(object != 0);
1061 QMetaObject::invokeMethod(object, method.toUtf8());
1062 QObject *created = object->objectProperty();
1064 QCOMPARE(created->objectName(), createdName);
1070 Tests the destroy function
1072 void tst_qdeclarativeecmascript::dynamicDestruction()
1074 QDeclarativeComponent component(&engine, TEST_FILE("dynamicDeletion.qml"));
1075 QDeclarativeGuard<MyQmlObject> object = qobject_cast<MyQmlObject*>(component.create());
1076 QVERIFY(object != 0);
1077 QDeclarativeGuard<QObject> createdQmlObject = 0;
1079 QMetaObject::invokeMethod(object, "create");
1080 createdQmlObject = object->objectProperty();
1081 QVERIFY(createdQmlObject);
1082 QCOMPARE(createdQmlObject->objectName(), QString("emptyObject"));
1084 QMetaObject::invokeMethod(object, "killOther");
1085 QVERIFY(createdQmlObject);
1086 QCoreApplication::instance()->processEvents(QEventLoop::DeferredDeletion);
1087 QVERIFY(createdQmlObject);
1088 for (int ii = 0; createdQmlObject && ii < 50; ++ii) { // After 5 seconds we should give up
1089 if (createdQmlObject) {
1091 QCoreApplication::instance()->processEvents(QEventLoop::DeferredDeletion);
1094 QVERIFY(!createdQmlObject);
1096 QDeclarativeEngine::setObjectOwnership(object, QDeclarativeEngine::JavaScriptOwnership);
1097 QMetaObject::invokeMethod(object, "killMe");
1100 QCoreApplication::instance()->processEvents(QEventLoop::DeferredDeletion);
1105 tests that id.toString() works
1107 void tst_qdeclarativeecmascript::objectToString()
1109 QDeclarativeComponent component(&engine, TEST_FILE("declarativeToString.qml"));
1110 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1111 QVERIFY(object != 0);
1112 QMetaObject::invokeMethod(object, "testToString");
1113 QVERIFY(object->stringProperty().startsWith("MyQmlObject_QML_"));
1114 QVERIFY(object->stringProperty().endsWith(", \"objName\")"));
1120 Tests bindings that indirectly cause their own deletion work.
1122 This test is best run under valgrind to ensure no invalid memory access occur.
1124 void tst_qdeclarativeecmascript::selfDeletingBinding()
1127 QDeclarativeComponent component(&engine, TEST_FILE("selfDeletingBinding.qml"));
1128 QObject *object = component.create();
1129 QVERIFY(object != 0);
1130 object->setProperty("triggerDelete", true);
1135 QDeclarativeComponent component(&engine, TEST_FILE("selfDeletingBinding.2.qml"));
1136 QObject *object = component.create();
1137 QVERIFY(object != 0);
1138 object->setProperty("triggerDelete", true);
1144 Test that extended object properties can be accessed.
1146 This test a regression where this used to crash. The issue was specificially
1147 for extended objects that did not include a synthesized meta object (so non-root
1148 and no synthesiszed properties).
1150 void tst_qdeclarativeecmascript::extendedObjectPropertyLookup()
1152 QDeclarativeComponent component(&engine, TEST_FILE("extendedObjectPropertyLookup.qml"));
1153 QObject *object = component.create();
1154 QVERIFY(object != 0);
1159 Test file/lineNumbers for binding/Script errors.
1161 void tst_qdeclarativeecmascript::scriptErrors()
1163 QDeclarativeComponent component(&engine, TEST_FILE("scriptErrors.qml"));
1164 QString url = component.url().toString();
1166 QString warning1 = url.left(url.length() - 3) + "js:2: Error: Invalid write to global property \"a\"";
1167 QString warning2 = url + ":5: ReferenceError: Can't find variable: a";
1168 QString warning3 = url.left(url.length() - 3) + "js:4: Error: Invalid write to global property \"a\"";
1169 QString warning4 = url + ":10: ReferenceError: Can't find variable: a";
1170 QString warning5 = url + ":8: ReferenceError: Can't find variable: a";
1171 QString warning6 = url + ":7: Unable to assign [undefined] to int x";
1172 QString warning7 = url + ":12: Error: Cannot assign to read-only property \"trueProperty\"";
1173 QString warning8 = url + ":13: Error: Cannot assign to non-existent property \"fakeProperty\"";
1175 QTest::ignoreMessage(QtWarningMsg, warning1.toLatin1().constData());
1176 QTest::ignoreMessage(QtWarningMsg, warning2.toLatin1().constData());
1177 QTest::ignoreMessage(QtWarningMsg, warning3.toLatin1().constData());
1178 QTest::ignoreMessage(QtWarningMsg, warning5.toLatin1().constData());
1179 QTest::ignoreMessage(QtWarningMsg, warning6.toLatin1().constData());
1180 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
1181 QVERIFY(object != 0);
1183 QTest::ignoreMessage(QtWarningMsg, warning4.toLatin1().constData());
1184 emit object->basicSignal();
1186 QTest::ignoreMessage(QtWarningMsg, warning7.toLatin1().constData());
1187 emit object->anotherBasicSignal();
1189 QTest::ignoreMessage(QtWarningMsg, warning8.toLatin1().constData());
1190 emit object->thirdBasicSignal();
1196 Test file/lineNumbers for inline functions.
1198 void tst_qdeclarativeecmascript::functionErrors()
1200 QDeclarativeComponent component(&engine, TEST_FILE("functionErrors.qml"));
1201 QString url = component.url().toString();
1203 QString warning = url + ":5: Error: Invalid write to global property \"a\"";
1205 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
1207 QObject *object = component.create();
1208 QVERIFY(object != 0);
1211 // test that if an exception occurs while invoking js function from cpp, it is reported as expected.
1212 QDeclarativeComponent componentTwo(&engine, TEST_FILE("scarceresources/scarceResourceFunctionFail.qml"));
1213 url = componentTwo.url().toString();
1214 object = componentTwo.create();
1215 QVERIFY(object != 0);
1216 warning = url + QLatin1String(":16: TypeError: Result of expression 'scarceResourceProvider.scarceResource' [[object Object]] is not a function.");
1217 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData()); // we expect a meaningful warning to be printed.
1218 QMetaObject::invokeMethod(object, "retrieveScarceResource");
1223 Test various errors that can occur when assigning a property from script
1225 void tst_qdeclarativeecmascript::propertyAssignmentErrors()
1227 QDeclarativeComponent component(&engine, TEST_FILE("propertyAssignmentErrors.qml"));
1229 QString url = component.url().toString();
1231 QString warning1 = url + ":11:Error: Cannot assign [undefined] to int";
1232 QString warning2 = url + ":17:Error: Cannot assign QString to int";
1234 QTest::ignoreMessage(QtDebugMsg, warning1.toLatin1().constData());
1235 QTest::ignoreMessage(QtDebugMsg, warning2.toLatin1().constData());
1237 QObject *object = component.create();
1238 QVERIFY(object != 0);
1244 Test bindings still work when the reeval is triggered from within
1247 void tst_qdeclarativeecmascript::signalTriggeredBindings()
1249 QDeclarativeComponent component(&engine, TEST_FILE("signalTriggeredBindings.qml"));
1250 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1251 QVERIFY(object != 0);
1253 QCOMPARE(object->property("base").toReal(), 50.);
1254 QCOMPARE(object->property("test1").toReal(), 50.);
1255 QCOMPARE(object->property("test2").toReal(), 50.);
1257 object->basicSignal();
1259 QCOMPARE(object->property("base").toReal(), 200.);
1260 QCOMPARE(object->property("test1").toReal(), 200.);
1261 QCOMPARE(object->property("test2").toReal(), 200.);
1263 object->argumentSignal(10, QString(), 10, MyQmlObject::EnumValue4, Qt::RightButton);
1265 QCOMPARE(object->property("base").toReal(), 400.);
1266 QCOMPARE(object->property("test1").toReal(), 400.);
1267 QCOMPARE(object->property("test2").toReal(), 400.);
1273 Test that list properties can be iterated from ECMAScript
1275 void tst_qdeclarativeecmascript::listProperties()
1277 QDeclarativeComponent component(&engine, TEST_FILE("listProperties.qml"));
1278 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1279 QVERIFY(object != 0);
1281 QCOMPARE(object->property("test1").toInt(), 21);
1282 QCOMPARE(object->property("test2").toInt(), 2);
1283 QCOMPARE(object->property("test3").toBool(), true);
1284 QCOMPARE(object->property("test4").toBool(), true);
1289 void tst_qdeclarativeecmascript::exceptionClearsOnReeval()
1291 QDeclarativeComponent component(&engine, TEST_FILE("exceptionClearsOnReeval.qml"));
1292 QString url = component.url().toString();
1294 QString warning = url + ":4: TypeError: Result of expression 'objectProperty' [null] is not an object.";
1296 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
1297 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1298 QVERIFY(object != 0);
1300 QCOMPARE(object->property("test").toBool(), false);
1302 MyQmlObject object2;
1303 MyQmlObject object3;
1304 object2.setObjectProperty(&object3);
1305 object->setObjectProperty(&object2);
1307 QCOMPARE(object->property("test").toBool(), true);
1312 void tst_qdeclarativeecmascript::exceptionSlotProducesWarning()
1314 QDeclarativeComponent component(&engine, TEST_FILE("exceptionProducesWarning.qml"));
1315 QString url = component.url().toString();
1317 QString warning = component.url().toString() + ":6: Error: JS exception";
1319 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
1320 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1321 QVERIFY(object != 0);
1325 void tst_qdeclarativeecmascript::exceptionBindingProducesWarning()
1327 QDeclarativeComponent component(&engine, TEST_FILE("exceptionProducesWarning2.qml"));
1328 QString url = component.url().toString();
1330 QString warning = component.url().toString() + ":5: Error: JS exception";
1332 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
1333 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1334 QVERIFY(object != 0);
1338 static int transientErrorsMsgCount = 0;
1339 static void transientErrorsMsgHandler(QtMsgType, const char *)
1341 ++transientErrorsMsgCount;
1344 // Check that transient binding errors are not displayed
1345 void tst_qdeclarativeecmascript::transientErrors()
1348 QDeclarativeComponent component(&engine, TEST_FILE("transientErrors.qml"));
1350 transientErrorsMsgCount = 0;
1351 QtMsgHandler old = qInstallMsgHandler(transientErrorsMsgHandler);
1353 QObject *object = component.create();
1354 QVERIFY(object != 0);
1356 qInstallMsgHandler(old);
1358 QCOMPARE(transientErrorsMsgCount, 0);
1363 // One binding erroring multiple times, but then resolving
1365 QDeclarativeComponent component(&engine, TEST_FILE("transientErrors.2.qml"));
1367 transientErrorsMsgCount = 0;
1368 QtMsgHandler old = qInstallMsgHandler(transientErrorsMsgHandler);
1370 QObject *object = component.create();
1371 QVERIFY(object != 0);
1373 qInstallMsgHandler(old);
1375 QCOMPARE(transientErrorsMsgCount, 0);
1381 // Check that errors during shutdown are minimized
1382 void tst_qdeclarativeecmascript::shutdownErrors()
1384 QDeclarativeComponent component(&engine, TEST_FILE("shutdownErrors.qml"));
1385 QObject *object = component.create();
1386 QVERIFY(object != 0);
1388 transientErrorsMsgCount = 0;
1389 QtMsgHandler old = qInstallMsgHandler(transientErrorsMsgHandler);
1393 qInstallMsgHandler(old);
1394 QCOMPARE(transientErrorsMsgCount, 0);
1397 void tst_qdeclarativeecmascript::compositePropertyType()
1399 QDeclarativeComponent component(&engine, TEST_FILE("compositePropertyType.qml"));
1400 QTest::ignoreMessage(QtDebugMsg, "hello world");
1401 QObject *object = qobject_cast<QObject *>(component.create());
1406 void tst_qdeclarativeecmascript::jsObject()
1408 QDeclarativeComponent component(&engine, TEST_FILE("jsObject.qml"));
1409 QObject *object = component.create();
1410 QVERIFY(object != 0);
1412 QCOMPARE(object->property("test").toInt(), 92);
1417 void tst_qdeclarativeecmascript::undefinedResetsProperty()
1420 QDeclarativeComponent component(&engine, TEST_FILE("undefinedResetsProperty.qml"));
1421 QObject *object = component.create();
1422 QVERIFY(object != 0);
1424 QCOMPARE(object->property("resettableProperty").toInt(), 92);
1426 object->setProperty("setUndefined", true);
1428 QCOMPARE(object->property("resettableProperty").toInt(), 13);
1430 object->setProperty("setUndefined", false);
1432 QCOMPARE(object->property("resettableProperty").toInt(), 92);
1437 QDeclarativeComponent component(&engine, TEST_FILE("undefinedResetsProperty.2.qml"));
1438 QObject *object = component.create();
1439 QVERIFY(object != 0);
1441 QCOMPARE(object->property("resettableProperty").toInt(), 19);
1443 QMetaObject::invokeMethod(object, "doReset");
1445 QCOMPARE(object->property("resettableProperty").toInt(), 13);
1452 void tst_qdeclarativeecmascript::bug1()
1454 QDeclarativeComponent component(&engine, TEST_FILE("bug.1.qml"));
1455 QObject *object = component.create();
1456 QVERIFY(object != 0);
1458 QCOMPARE(object->property("test").toInt(), 14);
1460 object->setProperty("a", 11);
1462 QCOMPARE(object->property("test").toInt(), 3);
1464 object->setProperty("b", true);
1466 QCOMPARE(object->property("test").toInt(), 9);
1471 void tst_qdeclarativeecmascript::bug2()
1473 QDeclarativeComponent component(&engine);
1474 component.setData("import Qt.test 1.0;\nQPlainTextEdit { width: 100 }", QUrl());
1476 QObject *object = component.create();
1477 QVERIFY(object != 0);
1482 // Don't crash in createObject when the component has errors.
1483 void tst_qdeclarativeecmascript::dynamicCreationCrash()
1485 QDeclarativeComponent component(&engine, TEST_FILE("dynamicCreation.qml"));
1486 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1487 QVERIFY(object != 0);
1489 QTest::ignoreMessage(QtWarningMsg, "QDeclarativeComponent: Component is not ready");
1490 QMetaObject::invokeMethod(object, "dontCrash");
1491 QObject *created = object->objectProperty();
1492 QVERIFY(created == 0);
1498 void tst_qdeclarativeecmascript::regExpBug()
1500 QDeclarativeComponent component(&engine, TEST_FILE("regExp.qml"));
1501 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
1502 QVERIFY(object != 0);
1503 QCOMPARE(object->regExp().pattern(), QLatin1String("[a-zA-z]"));
1507 void tst_qdeclarativeecmascript::callQtInvokables()
1509 MyInvokableObject o;
1511 QDeclarativeEngine qmlengine;
1512 QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(&qmlengine);
1513 QScriptEngine *engine = &ep->scriptEngine;
1515 QStringList names; QList<QScriptValue> values;
1516 names << QLatin1String("object"); values << ep->objectClass->newQObject(&o);
1517 names << QLatin1String("undefined"); values << engine->undefinedValue();
1519 ep->globalClass->explicitSetProperty(names, values);
1521 // Non-existent methods
1523 QCOMPARE(engine->evaluate("object.method_nonexistent()").isError(), true);
1524 QCOMPARE(o.error(), false);
1525 QCOMPARE(o.invoked(), -1);
1526 QCOMPARE(o.actuals().count(), 0);
1529 QCOMPARE(engine->evaluate("object.method_nonexistent(10, 11)").isError(), true);
1530 QCOMPARE(o.error(), false);
1531 QCOMPARE(o.invoked(), -1);
1532 QCOMPARE(o.actuals().count(), 0);
1534 // Insufficient arguments
1536 QCOMPARE(engine->evaluate("object.method_int()").isError(), true);
1537 QCOMPARE(o.error(), false);
1538 QCOMPARE(o.invoked(), -1);
1539 QCOMPARE(o.actuals().count(), 0);
1542 QCOMPARE(engine->evaluate("object.method_intint(10)").isError(), true);
1543 QCOMPARE(o.error(), false);
1544 QCOMPARE(o.invoked(), -1);
1545 QCOMPARE(o.actuals().count(), 0);
1547 // Excessive arguments
1549 QCOMPARE(engine->evaluate("object.method_int(10, 11)").isUndefined(), true);
1550 QCOMPARE(o.error(), false);
1551 QCOMPARE(o.invoked(), 8);
1552 QCOMPARE(o.actuals().count(), 1);
1553 QCOMPARE(o.actuals().at(0), QVariant(10));
1556 QCOMPARE(engine->evaluate("object.method_intint(10, 11, 12)").isUndefined(), true);
1557 QCOMPARE(o.error(), false);
1558 QCOMPARE(o.invoked(), 9);
1559 QCOMPARE(o.actuals().count(), 2);
1560 QCOMPARE(o.actuals().at(0), QVariant(10));
1561 QCOMPARE(o.actuals().at(1), QVariant(11));
1563 // Test return types
1565 QCOMPARE(engine->evaluate("object.method_NoArgs()").isUndefined(), true);
1566 QCOMPARE(o.error(), false);
1567 QCOMPARE(o.invoked(), 0);
1568 QCOMPARE(o.actuals().count(), 0);
1571 QVERIFY(engine->evaluate("object.method_NoArgs_int()").strictlyEquals(QScriptValue(engine, 6)));
1572 QCOMPARE(o.error(), false);
1573 QCOMPARE(o.invoked(), 1);
1574 QCOMPARE(o.actuals().count(), 0);
1577 QVERIFY(engine->evaluate("object.method_NoArgs_real()").strictlyEquals(QScriptValue(engine, 19.75)));
1578 QCOMPARE(o.error(), false);
1579 QCOMPARE(o.invoked(), 2);
1580 QCOMPARE(o.actuals().count(), 0);
1584 QScriptValue ret = engine->evaluate("object.method_NoArgs_QPointF()");
1585 QCOMPARE(ret.toVariant(), QVariant(QPointF(123, 4.5)));
1586 QCOMPARE(o.error(), false);
1587 QCOMPARE(o.invoked(), 3);
1588 QCOMPARE(o.actuals().count(), 0);
1593 QScriptValue ret = engine->evaluate("object.method_NoArgs_QObject()");
1594 QVERIFY(ret.isQObject());
1595 QCOMPARE(ret.toQObject(), (QObject *)&o);
1596 QCOMPARE(o.error(), false);
1597 QCOMPARE(o.invoked(), 4);
1598 QCOMPARE(o.actuals().count(), 0);
1602 QCOMPARE(engine->evaluate("object.method_NoArgs_unknown()").isUndefined(), true);
1603 QCOMPARE(o.error(), false);
1604 QCOMPARE(o.invoked(), 5);
1605 QCOMPARE(o.actuals().count(), 0);
1609 QScriptValue ret = engine->evaluate("object.method_NoArgs_QScriptValue()");
1610 QVERIFY(ret.isString());
1611 QCOMPARE(ret.toString(), QString("Hello world"));
1612 QCOMPARE(o.error(), false);
1613 QCOMPARE(o.invoked(), 6);
1614 QCOMPARE(o.actuals().count(), 0);
1618 QVERIFY(engine->evaluate("object.method_NoArgs_QVariant()").strictlyEquals(QScriptValue(engine, "QML rocks")));
1619 QCOMPARE(o.error(), false);
1620 QCOMPARE(o.invoked(), 7);
1621 QCOMPARE(o.actuals().count(), 0);
1625 QCOMPARE(engine->evaluate("object.method_int(94)").isUndefined(), true);
1626 QCOMPARE(o.error(), false);
1627 QCOMPARE(o.invoked(), 8);
1628 QCOMPARE(o.actuals().count(), 1);
1629 QCOMPARE(o.actuals().at(0), QVariant(94));
1632 QCOMPARE(engine->evaluate("object.method_int(\"94\")").isUndefined(), true);
1633 QCOMPARE(o.error(), false);
1634 QCOMPARE(o.invoked(), 8);
1635 QCOMPARE(o.actuals().count(), 1);
1636 QCOMPARE(o.actuals().at(0), QVariant(94));
1639 QCOMPARE(engine->evaluate("object.method_int(\"not a number\")").isUndefined(), true);
1640 QCOMPARE(o.error(), false);
1641 QCOMPARE(o.invoked(), 8);
1642 QCOMPARE(o.actuals().count(), 1);
1643 QCOMPARE(o.actuals().at(0), QVariant(0));
1646 QCOMPARE(engine->evaluate("object.method_int(null)").isUndefined(), true);
1647 QCOMPARE(o.error(), false);
1648 QCOMPARE(o.invoked(), 8);
1649 QCOMPARE(o.actuals().count(), 1);
1650 QCOMPARE(o.actuals().at(0), QVariant(0));
1653 QCOMPARE(engine->evaluate("object.method_int(undefined)").isUndefined(), true);
1654 QCOMPARE(o.error(), false);
1655 QCOMPARE(o.invoked(), 8);
1656 QCOMPARE(o.actuals().count(), 1);
1657 QCOMPARE(o.actuals().at(0), QVariant(0));
1660 QCOMPARE(engine->evaluate("object.method_int(object)").isUndefined(), true);
1661 QCOMPARE(o.error(), false);
1662 QCOMPARE(o.invoked(), 8);
1663 QCOMPARE(o.actuals().count(), 1);
1664 QCOMPARE(o.actuals().at(0), QVariant(0));
1667 QCOMPARE(engine->evaluate("object.method_intint(122, 9)").isUndefined(), true);
1668 QCOMPARE(o.error(), false);
1669 QCOMPARE(o.invoked(), 9);
1670 QCOMPARE(o.actuals().count(), 2);
1671 QCOMPARE(o.actuals().at(0), QVariant(122));
1672 QCOMPARE(o.actuals().at(1), QVariant(9));
1675 QCOMPARE(engine->evaluate("object.method_real(94.3)").isUndefined(), true);
1676 QCOMPARE(o.error(), false);
1677 QCOMPARE(o.invoked(), 10);
1678 QCOMPARE(o.actuals().count(), 1);
1679 QCOMPARE(o.actuals().at(0), QVariant(94.3));
1682 QCOMPARE(engine->evaluate("object.method_real(\"94.3\")").isUndefined(), true);
1683 QCOMPARE(o.error(), false);
1684 QCOMPARE(o.invoked(), 10);
1685 QCOMPARE(o.actuals().count(), 1);
1686 QCOMPARE(o.actuals().at(0), QVariant(94.3));
1689 QCOMPARE(engine->evaluate("object.method_real(\"not a number\")").isUndefined(), true);
1690 QCOMPARE(o.error(), false);
1691 QCOMPARE(o.invoked(), 10);
1692 QCOMPARE(o.actuals().count(), 1);
1693 QVERIFY(qIsNaN(o.actuals().at(0).toDouble()));
1696 QCOMPARE(engine->evaluate("object.method_real(null)").isUndefined(), true);
1697 QCOMPARE(o.error(), false);
1698 QCOMPARE(o.invoked(), 10);
1699 QCOMPARE(o.actuals().count(), 1);
1700 QCOMPARE(o.actuals().at(0), QVariant(0));
1703 QCOMPARE(engine->evaluate("object.method_real(undefined)").isUndefined(), true);
1704 QCOMPARE(o.error(), false);
1705 QCOMPARE(o.invoked(), 10);
1706 QCOMPARE(o.actuals().count(), 1);
1707 QVERIFY(qIsNaN(o.actuals().at(0).toDouble()));
1710 QCOMPARE(engine->evaluate("object.method_real(object)").isUndefined(), true);
1711 QCOMPARE(o.error(), false);
1712 QCOMPARE(o.invoked(), 10);
1713 QCOMPARE(o.actuals().count(), 1);
1714 QVERIFY(qIsNaN(o.actuals().at(0).toDouble()));
1717 QCOMPARE(engine->evaluate("object.method_QString(\"Hello world\")").isUndefined(), true);
1718 QCOMPARE(o.error(), false);
1719 QCOMPARE(o.invoked(), 11);
1720 QCOMPARE(o.actuals().count(), 1);
1721 QCOMPARE(o.actuals().at(0), QVariant("Hello world"));
1724 QCOMPARE(engine->evaluate("object.method_QString(19)").isUndefined(), true);
1725 QCOMPARE(o.error(), false);
1726 QCOMPARE(o.invoked(), 11);
1727 QCOMPARE(o.actuals().count(), 1);
1728 QCOMPARE(o.actuals().at(0), QVariant("19"));
1732 QString expected = "MyInvokableObject(0x" + QString::number((quintptr)&o, 16) + ")";
1733 QCOMPARE(engine->evaluate("object.method_QString(object)").isUndefined(), true);
1734 QCOMPARE(o.error(), false);
1735 QCOMPARE(o.invoked(), 11);
1736 QCOMPARE(o.actuals().count(), 1);
1737 QCOMPARE(o.actuals().at(0), QVariant(expected));
1741 QCOMPARE(engine->evaluate("object.method_QString(null)").isUndefined(), true);
1742 QCOMPARE(o.error(), false);
1743 QCOMPARE(o.invoked(), 11);
1744 QCOMPARE(o.actuals().count(), 1);
1745 QCOMPARE(o.actuals().at(0), QVariant(QString()));
1748 QCOMPARE(engine->evaluate("object.method_QString(undefined)").isUndefined(), true);
1749 QCOMPARE(o.error(), false);
1750 QCOMPARE(o.invoked(), 11);
1751 QCOMPARE(o.actuals().count(), 1);
1752 QCOMPARE(o.actuals().at(0), QVariant(QString()));
1755 QCOMPARE(engine->evaluate("object.method_QPointF(0)").isUndefined(), true);
1756 QCOMPARE(o.error(), false);
1757 QCOMPARE(o.invoked(), 12);
1758 QCOMPARE(o.actuals().count(), 1);
1759 QCOMPARE(o.actuals().at(0), QVariant(QPointF()));
1762 QCOMPARE(engine->evaluate("object.method_QPointF(null)").isUndefined(), true);
1763 QCOMPARE(o.error(), false);
1764 QCOMPARE(o.invoked(), 12);
1765 QCOMPARE(o.actuals().count(), 1);
1766 QCOMPARE(o.actuals().at(0), QVariant(QPointF()));
1769 QCOMPARE(engine->evaluate("object.method_QPointF(undefined)").isUndefined(), true);
1770 QCOMPARE(o.error(), false);
1771 QCOMPARE(o.invoked(), 12);
1772 QCOMPARE(o.actuals().count(), 1);
1773 QCOMPARE(o.actuals().at(0), QVariant(QPointF()));
1776 QCOMPARE(engine->evaluate("object.method_QPointF(object)").isUndefined(), true);
1777 QCOMPARE(o.error(), false);
1778 QCOMPARE(o.invoked(), 12);
1779 QCOMPARE(o.actuals().count(), 1);
1780 QCOMPARE(o.actuals().at(0), QVariant(QPointF()));
1783 QCOMPARE(engine->evaluate("object.method_QPointF(object.method_get_QPointF())").isUndefined(), true);
1784 QCOMPARE(o.error(), false);
1785 QCOMPARE(o.invoked(), 12);
1786 QCOMPARE(o.actuals().count(), 1);
1787 QCOMPARE(o.actuals().at(0), QVariant(QPointF(99.3, -10.2)));
1790 QCOMPARE(engine->evaluate("object.method_QPointF(object.method_get_QPoint())").isUndefined(), true);
1791 QCOMPARE(o.error(), false);
1792 QCOMPARE(o.invoked(), 12);
1793 QCOMPARE(o.actuals().count(), 1);
1794 QCOMPARE(o.actuals().at(0), QVariant(QPointF(9, 12)));
1797 QCOMPARE(engine->evaluate("object.method_QObject(0)").isUndefined(), true);
1798 QCOMPARE(o.error(), false);
1799 QCOMPARE(o.invoked(), 13);
1800 QCOMPARE(o.actuals().count(), 1);
1801 QCOMPARE(o.actuals().at(0), qVariantFromValue((QObject *)0));
1804 QCOMPARE(engine->evaluate("object.method_QObject(\"Hello world\")").isUndefined(), true);
1805 QCOMPARE(o.error(), false);
1806 QCOMPARE(o.invoked(), 13);
1807 QCOMPARE(o.actuals().count(), 1);
1808 QCOMPARE(o.actuals().at(0), qVariantFromValue((QObject *)0));
1811 QCOMPARE(engine->evaluate("object.method_QObject(null)").isUndefined(), true);
1812 QCOMPARE(o.error(), false);
1813 QCOMPARE(o.invoked(), 13);
1814 QCOMPARE(o.actuals().count(), 1);
1815 QCOMPARE(o.actuals().at(0), qVariantFromValue((QObject *)0));
1818 QCOMPARE(engine->evaluate("object.method_QObject(undefined)").isUndefined(), true);
1819 QCOMPARE(o.error(), false);
1820 QCOMPARE(o.invoked(), 13);
1821 QCOMPARE(o.actuals().count(), 1);
1822 QCOMPARE(o.actuals().at(0), qVariantFromValue((QObject *)0));
1825 QCOMPARE(engine->evaluate("object.method_QObject(object)").isUndefined(), true);
1826 QCOMPARE(o.error(), false);
1827 QCOMPARE(o.invoked(), 13);
1828 QCOMPARE(o.actuals().count(), 1);
1829 QCOMPARE(o.actuals().at(0), qVariantFromValue((QObject *)&o));
1832 QCOMPARE(engine->evaluate("object.method_QScriptValue(null)").isUndefined(), true);
1833 QCOMPARE(o.error(), false);
1834 QCOMPARE(o.invoked(), 14);
1835 QCOMPARE(o.actuals().count(), 1);
1836 QVERIFY(qvariant_cast<QScriptValue>(o.actuals().at(0)).isNull());
1839 QCOMPARE(engine->evaluate("object.method_QScriptValue(undefined)").isUndefined(), true);
1840 QCOMPARE(o.error(), false);
1841 QCOMPARE(o.invoked(), 14);
1842 QCOMPARE(o.actuals().count(), 1);
1843 QVERIFY(qvariant_cast<QScriptValue>(o.actuals().at(0)).isUndefined());
1846 QCOMPARE(engine->evaluate("object.method_QScriptValue(19)").isUndefined(), true);
1847 QCOMPARE(o.error(), false);
1848 QCOMPARE(o.invoked(), 14);
1849 QCOMPARE(o.actuals().count(), 1);
1850 QVERIFY(qvariant_cast<QScriptValue>(o.actuals().at(0)).strictlyEquals(QScriptValue(engine, 19)));
1853 QCOMPARE(engine->evaluate("object.method_QScriptValue([19, 20])").isUndefined(), true);
1854 QCOMPARE(o.error(), false);
1855 QCOMPARE(o.invoked(), 14);
1856 QCOMPARE(o.actuals().count(), 1);
1857 QVERIFY(qvariant_cast<QScriptValue>(o.actuals().at(0)).isArray());
1860 QCOMPARE(engine->evaluate("object.method_intQScriptValue(4, null)").isUndefined(), true);
1861 QCOMPARE(o.error(), false);
1862 QCOMPARE(o.invoked(), 15);
1863 QCOMPARE(o.actuals().count(), 2);
1864 QCOMPARE(o.actuals().at(0), QVariant(4));
1865 QVERIFY(qvariant_cast<QScriptValue>(o.actuals().at(1)).isNull());
1868 QCOMPARE(engine->evaluate("object.method_intQScriptValue(8, undefined)").isUndefined(), true);
1869 QCOMPARE(o.error(), false);
1870 QCOMPARE(o.invoked(), 15);
1871 QCOMPARE(o.actuals().count(), 2);
1872 QCOMPARE(o.actuals().at(0), QVariant(8));
1873 QVERIFY(qvariant_cast<QScriptValue>(o.actuals().at(1)).isUndefined());
1876 QCOMPARE(engine->evaluate("object.method_intQScriptValue(3, 19)").isUndefined(), true);
1877 QCOMPARE(o.error(), false);
1878 QCOMPARE(o.invoked(), 15);
1879 QCOMPARE(o.actuals().count(), 2);
1880 QCOMPARE(o.actuals().at(0), QVariant(3));
1881 QVERIFY(qvariant_cast<QScriptValue>(o.actuals().at(1)).strictlyEquals(QScriptValue(engine, 19)));
1884 QCOMPARE(engine->evaluate("object.method_intQScriptValue(44, [19, 20])").isUndefined(), true);
1885 QCOMPARE(o.error(), false);
1886 QCOMPARE(o.invoked(), 15);
1887 QCOMPARE(o.actuals().count(), 2);
1888 QCOMPARE(o.actuals().at(0), QVariant(44));
1889 QVERIFY(qvariant_cast<QScriptValue>(o.actuals().at(1)).isArray());
1892 QCOMPARE(engine->evaluate("object.method_overload()").isError(), true);
1893 QCOMPARE(o.error(), false);
1894 QCOMPARE(o.invoked(), -1);
1895 QCOMPARE(o.actuals().count(), 0);
1898 QCOMPARE(engine->evaluate("object.method_overload(10)").isUndefined(), true);
1899 QCOMPARE(o.error(), false);
1900 QCOMPARE(o.invoked(), 16);
1901 QCOMPARE(o.actuals().count(), 1);
1902 QCOMPARE(o.actuals().at(0), QVariant(10));
1905 QCOMPARE(engine->evaluate("object.method_overload(10, 11)").isUndefined(), true);
1906 QCOMPARE(o.error(), false);
1907 QCOMPARE(o.invoked(), 17);
1908 QCOMPARE(o.actuals().count(), 2);
1909 QCOMPARE(o.actuals().at(0), QVariant(10));
1910 QCOMPARE(o.actuals().at(1), QVariant(11));
1913 QCOMPARE(engine->evaluate("object.method_overload(\"Hello\")").isUndefined(), true);
1914 QCOMPARE(o.error(), false);
1915 QCOMPARE(o.invoked(), 18);
1916 QCOMPARE(o.actuals().count(), 1);
1917 QCOMPARE(o.actuals().at(0), QVariant(QString("Hello")));
1920 QCOMPARE(engine->evaluate("object.method_with_enum(9)").isUndefined(), true);
1921 QCOMPARE(o.error(), false);
1922 QCOMPARE(o.invoked(), 19);
1923 QCOMPARE(o.actuals().count(), 1);
1924 QCOMPARE(o.actuals().at(0), QVariant(9));
1927 QVERIFY(engine->evaluate("object.method_default(10)").strictlyEquals(QScriptValue(19)));
1928 QCOMPARE(o.error(), false);
1929 QCOMPARE(o.invoked(), 20);
1930 QCOMPARE(o.actuals().count(), 2);
1931 QCOMPARE(o.actuals().at(0), QVariant(10));
1932 QCOMPARE(o.actuals().at(1), QVariant(19));
1935 QVERIFY(engine->evaluate("object.method_default(10, 13)").strictlyEquals(QScriptValue(13)));
1936 QCOMPARE(o.error(), false);
1937 QCOMPARE(o.invoked(), 20);
1938 QCOMPARE(o.actuals().count(), 2);
1939 QCOMPARE(o.actuals().at(0), QVariant(10));
1940 QCOMPARE(o.actuals().at(1), QVariant(13));
1943 QCOMPARE(engine->evaluate("object.method_inherited(9)").isUndefined(), true);
1944 QCOMPARE(o.error(), false);
1945 QCOMPARE(o.invoked(), -3);
1946 QCOMPARE(o.actuals().count(), 1);
1947 QCOMPARE(o.actuals().at(0), QVariant(9));
1950 QCOMPARE(engine->evaluate("object.method_QVariant(9)").isUndefined(), true);
1951 QCOMPARE(o.error(), false);
1952 QCOMPARE(o.invoked(), 21);
1953 QCOMPARE(o.actuals().count(), 2);
1954 QCOMPARE(o.actuals().at(0), QVariant(9));
1955 QCOMPARE(o.actuals().at(1), QVariant());
1958 QCOMPARE(engine->evaluate("object.method_QVariant(\"Hello\", \"World\")").isUndefined(), true);
1959 QCOMPARE(o.error(), false);
1960 QCOMPARE(o.invoked(), 21);
1961 QCOMPARE(o.actuals().count(), 2);
1962 QCOMPARE(o.actuals().at(0), QVariant(QString("Hello")));
1963 QCOMPARE(o.actuals().at(1), QVariant(QString("World")));
1966 // QTBUG-13047 (check that you can pass registered object types as args)
1967 void tst_qdeclarativeecmascript::invokableObjectArg()
1969 QDeclarativeComponent component(&engine, TEST_FILE("invokableObjectArg.qml"));
1971 QObject *o = component.create();
1973 MyQmlObject *qmlobject = qobject_cast<MyQmlObject *>(o);
1975 QCOMPARE(qmlobject->myinvokableObject, qmlobject);
1980 // QTBUG-13047 (check that you can return registered object types from methods)
1981 void tst_qdeclarativeecmascript::invokableObjectRet()
1983 QDeclarativeComponent component(&engine, TEST_FILE("invokableObjectRet.qml"));
1985 QObject *o = component.create();
1987 QCOMPARE(o->property("test").toBool(), true);
1992 void tst_qdeclarativeecmascript::listToVariant()
1994 QDeclarativeComponent component(&engine, TEST_FILE("listToVariant.qml"));
1996 MyQmlContainer container;
1998 QDeclarativeContext context(engine.rootContext());
1999 context.setContextObject(&container);
2001 QObject *object = component.create(&context);
2002 QVERIFY(object != 0);
2004 QVariant v = object->property("test");
2005 QCOMPARE(v.userType(), qMetaTypeId<QDeclarativeListReference>());
2006 QVERIFY(qvariant_cast<QDeclarativeListReference>(v).object() == &container);
2012 void tst_qdeclarativeecmascript::multiEngineObject()
2015 obj.setStringProperty("Howdy planet");
2017 QDeclarativeEngine e1;
2018 e1.rootContext()->setContextProperty("thing", &obj);
2019 QDeclarativeComponent c1(&e1, TEST_FILE("multiEngineObject.qml"));
2021 QDeclarativeEngine e2;
2022 e2.rootContext()->setContextProperty("thing", &obj);
2023 QDeclarativeComponent c2(&e2, TEST_FILE("multiEngineObject.qml"));
2025 QObject *o1 = c1.create();
2026 QObject *o2 = c2.create();
2028 QCOMPARE(o1->property("test").toString(), QString("Howdy planet"));
2029 QCOMPARE(o2->property("test").toString(), QString("Howdy planet"));
2035 // Test that references to QObjects are cleanup when the object is destroyed
2036 void tst_qdeclarativeecmascript::deletedObject()
2038 QDeclarativeComponent component(&engine, TEST_FILE("deletedObject.qml"));
2040 QObject *object = component.create();
2042 QCOMPARE(object->property("test1").toBool(), true);
2043 QCOMPARE(object->property("test2").toBool(), true);
2044 QCOMPARE(object->property("test3").toBool(), true);
2045 QCOMPARE(object->property("test4").toBool(), true);
2050 void tst_qdeclarativeecmascript::attachedPropertyScope()
2052 QDeclarativeComponent component(&engine, TEST_FILE("attachedPropertyScope.qml"));
2054 QObject *object = component.create();
2055 QVERIFY(object != 0);
2057 MyQmlAttachedObject *attached =
2058 qobject_cast<MyQmlAttachedObject *>(qmlAttachedPropertiesObject<MyQmlObject>(object));
2059 QVERIFY(attached != 0);
2061 QCOMPARE(object->property("value2").toInt(), 0);
2063 attached->emitMySignal();
2065 QCOMPARE(object->property("value2").toInt(), 9);
2070 void tst_qdeclarativeecmascript::scriptConnect()
2073 QDeclarativeComponent component(&engine, TEST_FILE("scriptConnect.1.qml"));
2075 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2076 QVERIFY(object != 0);
2078 QCOMPARE(object->property("test").toBool(), false);
2079 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2080 QCOMPARE(object->property("test").toBool(), true);
2086 QDeclarativeComponent component(&engine, TEST_FILE("scriptConnect.2.qml"));
2088 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2089 QVERIFY(object != 0);
2091 QCOMPARE(object->property("test").toBool(), false);
2092 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2093 QCOMPARE(object->property("test").toBool(), true);
2099 QDeclarativeComponent component(&engine, TEST_FILE("scriptConnect.3.qml"));
2101 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2102 QVERIFY(object != 0);
2104 QCOMPARE(object->property("test").toBool(), false);
2105 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2106 QCOMPARE(object->property("test").toBool(), true);
2112 QDeclarativeComponent component(&engine, TEST_FILE("scriptConnect.4.qml"));
2114 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2115 QVERIFY(object != 0);
2117 QCOMPARE(object->methodCalled(), false);
2118 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2119 QCOMPARE(object->methodCalled(), true);
2125 QDeclarativeComponent component(&engine, TEST_FILE("scriptConnect.5.qml"));
2127 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2128 QVERIFY(object != 0);
2130 QCOMPARE(object->methodCalled(), false);
2131 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2132 QCOMPARE(object->methodCalled(), true);
2138 QDeclarativeComponent component(&engine, TEST_FILE("scriptConnect.6.qml"));
2140 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2141 QVERIFY(object != 0);
2143 QCOMPARE(object->property("test").toInt(), 0);
2144 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2145 QCOMPARE(object->property("test").toInt(), 2);
2151 void tst_qdeclarativeecmascript::scriptDisconnect()
2154 QDeclarativeComponent component(&engine, TEST_FILE("scriptDisconnect.1.qml"));
2156 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2157 QVERIFY(object != 0);
2159 QCOMPARE(object->property("test").toInt(), 0);
2160 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2161 QCOMPARE(object->property("test").toInt(), 1);
2162 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2163 QCOMPARE(object->property("test").toInt(), 2);
2164 emit object->basicSignal();
2165 QCOMPARE(object->property("test").toInt(), 2);
2166 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2167 QCOMPARE(object->property("test").toInt(), 2);
2173 QDeclarativeComponent component(&engine, TEST_FILE("scriptDisconnect.2.qml"));
2175 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2176 QVERIFY(object != 0);
2178 QCOMPARE(object->property("test").toInt(), 0);
2179 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2180 QCOMPARE(object->property("test").toInt(), 1);
2181 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2182 QCOMPARE(object->property("test").toInt(), 2);
2183 emit object->basicSignal();
2184 QCOMPARE(object->property("test").toInt(), 2);
2185 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2186 QCOMPARE(object->property("test").toInt(), 2);
2192 QDeclarativeComponent component(&engine, TEST_FILE("scriptDisconnect.3.qml"));
2194 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2195 QVERIFY(object != 0);
2197 QCOMPARE(object->property("test").toInt(), 0);
2198 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2199 QCOMPARE(object->property("test").toInt(), 1);
2200 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2201 QCOMPARE(object->property("test").toInt(), 2);
2202 emit object->basicSignal();
2203 QCOMPARE(object->property("test").toInt(), 2);
2204 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2205 QCOMPARE(object->property("test").toInt(), 3);
2210 QDeclarativeComponent component(&engine, TEST_FILE("scriptDisconnect.4.qml"));
2212 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2213 QVERIFY(object != 0);
2215 QCOMPARE(object->property("test").toInt(), 0);
2216 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2217 QCOMPARE(object->property("test").toInt(), 1);
2218 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2219 QCOMPARE(object->property("test").toInt(), 2);
2220 emit object->basicSignal();
2221 QCOMPARE(object->property("test").toInt(), 2);
2222 emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
2223 QCOMPARE(object->property("test").toInt(), 3);
2229 class OwnershipObject : public QObject
2233 OwnershipObject() { object = new QObject; }
2235 QPointer<QObject> object;
2238 QObject *getObject() { return object; }
2241 void tst_qdeclarativeecmascript::ownership()
2243 OwnershipObject own;
2244 QDeclarativeContext *context = new QDeclarativeContext(engine.rootContext());
2245 context->setContextObject(&own);
2248 QDeclarativeComponent component(&engine, TEST_FILE("ownership.qml"));
2250 QVERIFY(own.object != 0);
2252 QObject *object = component.create(context);
2253 QDeclarativeEnginePrivate::getScriptEngine(&engine)->collectGarbage();
2255 QCoreApplication::processEvents(QEventLoop::DeferredDeletion);
2257 QVERIFY(own.object == 0);
2262 own.object = new QObject(&own);
2265 QDeclarativeComponent component(&engine, TEST_FILE("ownership.qml"));
2267 QVERIFY(own.object != 0);
2269 QObject *object = component.create(context);
2270 QDeclarativeEnginePrivate::getScriptEngine(&engine)->collectGarbage();
2272 QCoreApplication::processEvents(QEventLoop::DeferredDeletion);
2274 QVERIFY(own.object != 0);
2282 class CppOwnershipReturnValue : public QObject
2286 CppOwnershipReturnValue() : value(0) {}
2287 ~CppOwnershipReturnValue() { delete value; }
2289 Q_INVOKABLE QObject *create() {
2290 value = new QObject;
2291 QDeclarativeEngine::setObjectOwnership(value, QDeclarativeEngine::CppOwnership);
2295 Q_INVOKABLE MyQmlObject *createQmlObject() {
2296 MyQmlObject *rv = new MyQmlObject;
2301 QPointer<QObject> value;
2305 // Test setObjectOwnership(CppOwnership) works even when there is no QDeclarativeData
2306 void tst_qdeclarativeecmascript::cppOwnershipReturnValue()
2308 CppOwnershipReturnValue source;
2311 QDeclarativeEngine engine;
2312 engine.rootContext()->setContextProperty("source", &source);
2314 QVERIFY(source.value == 0);
2316 QDeclarativeComponent component(&engine);
2317 component.setData("import QtQuick 1.0\nQtObject {\nComponent.onCompleted: { var a = source.create(); }\n}\n", QUrl());
2319 QObject *object = component.create();
2321 QVERIFY(object != 0);
2322 QVERIFY(source.value != 0);
2327 QCoreApplication::instance()->processEvents(QEventLoop::DeferredDeletion);
2329 QVERIFY(source.value != 0);
2333 void tst_qdeclarativeecmascript::ownershipCustomReturnValue()
2335 CppOwnershipReturnValue source;
2338 QDeclarativeEngine engine;
2339 engine.rootContext()->setContextProperty("source", &source);
2341 QVERIFY(source.value == 0);
2343 QDeclarativeComponent component(&engine);
2344 component.setData("import QtQuick 1.0\nQtObject {\nComponent.onCompleted: { var a = source.createQmlObject(); }\n}\n", QUrl());
2346 QObject *object = component.create();
2348 QVERIFY(object != 0);
2349 QVERIFY(source.value != 0);
2354 QCoreApplication::instance()->processEvents(QEventLoop::DeferredDeletion);
2356 QVERIFY(source.value == 0);
2359 class QListQObjectMethodsObject : public QObject
2363 QListQObjectMethodsObject() {
2364 m_objects.append(new MyQmlObject());
2365 m_objects.append(new MyQmlObject());
2368 ~QListQObjectMethodsObject() {
2369 qDeleteAll(m_objects);
2373 QList<QObject *> getObjects() { return m_objects; }
2376 QList<QObject *> m_objects;
2379 // Tests that returning a QList<QObject*> from a method works
2380 void tst_qdeclarativeecmascript::qlistqobjectMethods()
2382 QListQObjectMethodsObject obj;
2383 QDeclarativeContext *context = new QDeclarativeContext(engine.rootContext());
2384 context->setContextObject(&obj);
2386 QDeclarativeComponent component(&engine, TEST_FILE("qlistqobjectMethods.qml"));
2388 QObject *object = component.create(context);
2390 QCOMPARE(object->property("test").toInt(), 2);
2391 QCOMPARE(object->property("test2").toBool(), true);
2398 void tst_qdeclarativeecmascript::strictlyEquals()
2400 QDeclarativeComponent component(&engine, TEST_FILE("strictlyEquals.qml"));
2402 QObject *object = component.create();
2403 QVERIFY(object != 0);
2405 QCOMPARE(object->property("test1").toBool(), true);
2406 QCOMPARE(object->property("test2").toBool(), true);
2407 QCOMPARE(object->property("test3").toBool(), true);
2408 QCOMPARE(object->property("test4").toBool(), true);
2409 QCOMPARE(object->property("test5").toBool(), true);
2410 QCOMPARE(object->property("test6").toBool(), true);
2411 QCOMPARE(object->property("test7").toBool(), true);
2412 QCOMPARE(object->property("test8").toBool(), true);
2417 void tst_qdeclarativeecmascript::compiled()
2419 QDeclarativeComponent component(&engine, TEST_FILE("compiled.qml"));
2421 QObject *object = component.create();
2422 QVERIFY(object != 0);
2424 QCOMPARE(object->property("test1").toReal(), qreal(15.7));
2425 QCOMPARE(object->property("test2").toReal(), qreal(-6.7));
2426 QCOMPARE(object->property("test3").toBool(), true);
2427 QCOMPARE(object->property("test4").toBool(), false);
2428 QCOMPARE(object->property("test5").toBool(), false);
2429 QCOMPARE(object->property("test6").toBool(), true);
2431 QCOMPARE(object->property("test7").toInt(), 185);
2432 QCOMPARE(object->property("test8").toInt(), 167);
2433 QCOMPARE(object->property("test9").toBool(), true);
2434 QCOMPARE(object->property("test10").toBool(), false);
2435 QCOMPARE(object->property("test11").toBool(), false);
2436 QCOMPARE(object->property("test12").toBool(), true);
2438 QCOMPARE(object->property("test13").toString(), QLatin1String("HelloWorld"));
2439 QCOMPARE(object->property("test14").toString(), QLatin1String("Hello World"));
2440 QCOMPARE(object->property("test15").toBool(), false);
2441 QCOMPARE(object->property("test16").toBool(), true);
2443 QCOMPARE(object->property("test17").toInt(), 5);
2444 QCOMPARE(object->property("test18").toReal(), qreal(176));
2445 QCOMPARE(object->property("test19").toInt(), 7);
2446 QCOMPARE(object->property("test20").toReal(), qreal(6.7));
2447 QCOMPARE(object->property("test21").toString(), QLatin1String("6.7"));
2448 QCOMPARE(object->property("test22").toString(), QLatin1String("!"));
2449 QCOMPARE(object->property("test23").toBool(), true);
2450 QCOMPARE(qvariant_cast<QColor>(object->property("test24")), QColor(0x11,0x22,0x33));
2451 QCOMPARE(qvariant_cast<QColor>(object->property("test25")), QColor(0x11,0x22,0x33,0xAA));
2456 // Test that numbers assigned in bindings as strings work consistently
2457 void tst_qdeclarativeecmascript::numberAssignment()
2459 QDeclarativeComponent component(&engine, TEST_FILE("numberAssignment.qml"));
2461 QObject *object = component.create();
2462 QVERIFY(object != 0);
2464 QCOMPARE(object->property("test1"), QVariant((qreal)6.7));
2465 QCOMPARE(object->property("test2"), QVariant((qreal)6.7));
2466 QCOMPARE(object->property("test2"), QVariant((qreal)6.7));
2467 QCOMPARE(object->property("test3"), QVariant((qreal)6));
2468 QCOMPARE(object->property("test4"), QVariant((qreal)6));
2470 QCOMPARE(object->property("test5"), QVariant((int)7));
2471 QCOMPARE(object->property("test6"), QVariant((int)7));
2472 QCOMPARE(object->property("test7"), QVariant((int)6));
2473 QCOMPARE(object->property("test8"), QVariant((int)6));
2475 QCOMPARE(object->property("test9"), QVariant((unsigned int)7));
2476 QCOMPARE(object->property("test10"), QVariant((unsigned int)7));
2477 QCOMPARE(object->property("test11"), QVariant((unsigned int)6));
2478 QCOMPARE(object->property("test12"), QVariant((unsigned int)6));
2483 void tst_qdeclarativeecmascript::propertySplicing()
2485 QDeclarativeComponent component(&engine, TEST_FILE("propertySplicing.qml"));
2487 QObject *object = component.create();
2488 QVERIFY(object != 0);
2490 QCOMPARE(object->property("test").toBool(), true);
2496 void tst_qdeclarativeecmascript::signalWithUnknownTypes()
2498 QDeclarativeComponent component(&engine, TEST_FILE("signalWithUnknownTypes.qml"));
2500 MyQmlObject *object = qobject_cast<MyQmlObject *>(component.create());
2501 QVERIFY(object != 0);
2503 MyQmlObject::MyType type;
2504 type.value = 0x8971123;
2505 emit object->signalWithUnknownType(type);
2507 MyQmlObject::MyType result = qvariant_cast<MyQmlObject::MyType>(object->variant());
2509 QCOMPARE(result.value, type.value);
2515 void tst_qdeclarativeecmascript::moduleApi()
2517 QDeclarativeComponent component(&engine, TEST_FILE("moduleApi.qml"));
2518 QObject *object = component.create();
2519 QVERIFY(object != 0);
2520 QCOMPARE(object->property("existingUriTest").toInt(), 20);
2521 QCOMPARE(object->property("scriptTest").toInt(), 13);
2522 QCOMPARE(object->property("qobjectTest").toInt(), 20);
2523 QCOMPARE(object->property("qobjectMethodTest").toInt(), 1); // first call of method, so count = 1.
2524 QCOMPARE(object->property("qobjectMinorVersionTest").toInt(), 20);
2525 QCOMPARE(object->property("qobjectMajorVersionTest").toInt(), 20);
2526 QCOMPARE(object->property("qobjectParentedTest").toInt(), 26);
2529 // test that caching of module apis works correctly.
2530 QDeclarativeComponent componentTwo(&engine, TEST_FILE("moduleApiCaching.qml"));
2531 object = componentTwo.create();
2532 QVERIFY(object != 0);
2533 QCOMPARE(object->property("existingUriTest").toInt(), 20);
2534 QCOMPARE(object->property("scriptTest").toInt(), 13); // shouldn't have incremented.
2535 QCOMPARE(object->property("qobjectParentedTest").toInt(), 26); // shouldn't have incremented.
2538 // test that writing to a property of module apis works correctly.
2539 QDeclarativeComponent componentThree(&engine, TEST_FILE("moduleApiWriting.qml"));
2540 QString expectedWarning = QLatin1String("file://") + TEST_FILE("moduleApiWriting.qml").toLocalFile() + QLatin1String(":15: Error: Cannot assign to read-only property \"qobjectTestProperty\"");
2541 QTest::ignoreMessage(QtWarningMsg, expectedWarning.toAscii().constData());
2542 object = componentThree.create();
2543 QVERIFY(object != 0);
2544 QCOMPARE(object->property("readOnlyProperty").toInt(), 20);
2545 QCOMPARE(object->property("writableProperty").toInt(), 50);
2546 QVERIFY(object->setProperty("firstProperty", QVariant(30))); // shouldn't affect value of readOnlyProperty
2547 QVERIFY(object->setProperty("writableProperty", QVariant(30))); // SHOULD affect value of writableProperty
2548 QCOMPARE(object->property("readOnlyProperty").toInt(), 20);
2549 QCOMPARE(object->property("writableProperty").toInt(), 30);
2552 QDeclarativeComponent failOne(&engine, TEST_FILE("moduleApiMajorVersionFail.qml"));
2553 QTest::ignoreMessage(QtWarningMsg, "QDeclarativeComponent: Component is not ready");
2554 object = failOne.create();
2555 QVERIFY(object == 0); // should have failed: invalid major version
2557 QDeclarativeComponent failTwo(&engine, TEST_FILE("moduleApiMinorVersionFail.qml"));
2558 QTest::ignoreMessage(QtWarningMsg, "QDeclarativeComponent: Component is not ready");
2559 object = failTwo.create();
2560 QVERIFY(object == 0); // should have failed: invalid minor version
2563 void tst_qdeclarativeecmascript::importScripts()
2565 QObject *object = 0;
2567 // first, ensure that the required behaviour works.
2568 QDeclarativeComponent component(&engine, TEST_FILE("jsimport/testImport.qml"));
2569 object = component.create();
2570 QVERIFY(object != 0);
2571 QCOMPARE(object->property("importedScriptStringValue"), QVariant(QString(QLatin1String("Hello, World!"))));
2572 QCOMPARE(object->property("importedScriptFunctionValue"), QVariant(20));
2573 QCOMPARE(object->property("importedModuleAttachedPropertyValue"), QVariant(19));
2574 QCOMPARE(object->property("importedModuleEnumValue"), QVariant(2));
2577 QDeclarativeComponent componentTwo(&engine, TEST_FILE("jsimport/testImportScoping.qml"));
2578 object = componentTwo.create();
2579 QVERIFY(object != 0);
2580 QCOMPARE(object->property("componentError"), QVariant(5));
2583 // then, ensure that unintended behaviour does not work.
2584 QDeclarativeComponent failOneComponent(&engine, TEST_FILE("jsimportfail/failOne.qml"));
2585 QString expectedWarning = QLatin1String("file://") + TEST_FILE("jsimportfail/failOne.qml").toLocalFile() + QLatin1String(":6: TypeError: Result of expression 'TestScriptImport.ImportOneJs' [undefined] is not an object.");
2586 QTest::ignoreMessage(QtWarningMsg, expectedWarning.toAscii().constData());
2587 object = failOneComponent.create();
2588 QVERIFY(object != 0);
2589 QVERIFY(object->property("importScriptFunctionValue").toString().isEmpty());
2591 QDeclarativeComponent failTwoComponent(&engine, TEST_FILE("jsimportfail/failTwo.qml"));
2592 expectedWarning = QLatin1String("file://") + TEST_FILE("jsimportfail/failTwo.qml").toLocalFile() + QLatin1String(":6: ReferenceError: Can't find variable: ImportOneJs");
2593 QTest::ignoreMessage(QtWarningMsg, expectedWarning.toAscii().constData());
2594 object = failTwoComponent.create();
2595 QVERIFY(object != 0);
2596 QVERIFY(object->property("importScriptFunctionValue").toString().isEmpty());
2598 QDeclarativeComponent failThreeComponent(&engine, TEST_FILE("jsimportfail/failThree.qml"));
2599 expectedWarning = QLatin1String("file://") + TEST_FILE("jsimportfail/failThree.qml").toLocalFile() + QLatin1String(":7: TypeError: Result of expression 'testQtObject.TestModuleImport.JsQtTest' [undefined] is not an object.");
2600 QTest::ignoreMessage(QtWarningMsg, expectedWarning.toAscii().constData());
2601 object = failThreeComponent.create();
2602 QVERIFY(object != 0);
2603 QCOMPARE(object->property("importedModuleAttachedPropertyValue"), QVariant(false));
2605 QDeclarativeComponent failFourComponent(&engine, TEST_FILE("jsimportfail/failFour.qml"));
2606 expectedWarning = QLatin1String("file://") + TEST_FILE("jsimportfail/failFour.qml").toLocalFile() + QLatin1String(":6: ReferenceError: Can't find variable: JsQtTest");
2607 QTest::ignoreMessage(QtWarningMsg, expectedWarning.toAscii().constData());
2608 object = failFourComponent.create();
2609 QVERIFY(object != 0);
2610 QCOMPARE(object->property("importedModuleEnumValue"), QVariant(0));
2612 QDeclarativeComponent failFiveComponent(&engine, TEST_FILE("jsimportfail/failFive.qml"));
2613 expectedWarning = QLatin1String("file://") + TEST_FILE("jsimportfail/importWithImports.js").toLocalFile() + QLatin1String(":8: ReferenceError: Can't find variable: Component");
2614 QTest::ignoreMessage(QtWarningMsg, expectedWarning.toAscii().constData());
2615 expectedWarning = QLatin1String("file://") + TEST_FILE("jsimportfail/importPragmaLibrary.js").toLocalFile() + QLatin1String(":6: ReferenceError: Can't find variable: Component");
2616 QTest::ignoreMessage(QtWarningMsg, expectedWarning.toAscii().constData());
2617 object = failFiveComponent.create();
2618 QVERIFY(object != 0);
2619 QCOMPARE(object->property("componentError"), QVariant(0));
2622 // also, test that importing scripts with .pragma library works as required
2623 QDeclarativeComponent pragmaLibraryComponent(&engine, TEST_FILE("jsimport/testImportPragmaLibrary.qml"));
2624 object = pragmaLibraryComponent.create();
2625 QVERIFY(object != 0);
2626 QCOMPARE(object->property("testValue"), QVariant(31));
2629 // and that .pragma library scripts don't inherit imports from any .qml file
2630 QDeclarativeComponent pragmaLibraryComponentTwo(&engine, TEST_FILE("jsimportfail/testImportPragmaLibrary.qml"));
2631 object = pragmaLibraryComponentTwo.create();
2632 QVERIFY(object != 0);
2633 QCOMPARE(object->property("testValue"), QVariant(0));
2637 void tst_qdeclarativeecmascript::scarceResources()
2639 QPixmap origPixmap(100, 100);
2640 origPixmap.fill(Qt::blue);
2642 QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(&engine);
2643 ScarceResourceObject *eo = 0;
2644 QObject *object = 0;
2646 // in the following three cases, the instance created from the component
2647 // has a property which is a copy of the scarce resource; hence, the
2648 // resource should NOT be detached prior to deletion of the object instance,
2649 // unless the resource is destroyed explicitly.
2650 QDeclarativeComponent component(&engine, TEST_FILE("scarceresources/scarceResourceCopy.qml"));
2651 object = component.create();
2652 QVERIFY(object != 0);
2653 QVERIFY(object->property("scarceResourceCopy").isValid());
2654 QCOMPARE(object->property("scarceResourceCopy").value<QPixmap>(), origPixmap);
2655 QVERIFY(ep->scarceResources == 0); // should have been released by this point.
2656 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2657 QVERIFY(!eo->scarceResourceIsDetached()); // there are two copies of it in existence: the property of object, and the property of eo.
2660 QDeclarativeComponent componentTwo(&engine, TEST_FILE("scarceresources/scarceResourceCopyFromJs.qml"));
2661 object = componentTwo.create();
2662 QVERIFY(object != 0);
2663 QVERIFY(object->property("scarceResourceCopy").isValid());
2664 QCOMPARE(object->property("scarceResourceCopy").value<QPixmap>(), origPixmap);
2665 QVERIFY(ep->scarceResources == 0); // should have been released by this point.
2666 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2667 QVERIFY(!eo->scarceResourceIsDetached()); // there are two copies of it in existence: the property of object, and the property of eo.
2670 QDeclarativeComponent componentThree(&engine, TEST_FILE("scarceresources/scarceResourceDestroyedCopy.qml"));
2671 object = componentThree.create();
2672 QVERIFY(object != 0);
2673 QVERIFY(!(object->property("scarceResourceCopy").isValid())); // was manually released prior to being returned.
2674 QVERIFY(ep->scarceResources == 0); // should have been released by this point.
2675 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2676 QVERIFY(eo->scarceResourceIsDetached()); // should have explicitly been released during the evaluation of the binding.
2679 // in the following three cases, no other copy should exist in memory,
2680 // and so it should be detached (unless explicitly preserved).
2681 QDeclarativeComponent componentFour(&engine, TEST_FILE("scarceresources/scarceResourceTest.qml"));
2682 object = componentFour.create();
2683 QVERIFY(object != 0);
2684 QVERIFY(object->property("scarceResourceTest").isValid());
2685 QCOMPARE(object->property("scarceResourceTest").toInt(), 100);
2686 QVERIFY(ep->scarceResources == 0); // should have been released by this point.
2687 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2688 QVERIFY(eo->scarceResourceIsDetached()); // the resource should have been released after the binding was evaluated.
2691 QDeclarativeComponent componentFive(&engine, TEST_FILE("scarceresources/scarceResourceTestPreserve.qml"));
2692 object = componentFive.create();
2693 QVERIFY(object != 0);
2694 QVERIFY(object->property("scarceResourceTest").isValid());
2695 QCOMPARE(object->property("scarceResourceTest").toInt(), 100);
2696 QVERIFY(ep->scarceResources == 0); // should have been released by this point.
2697 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2698 QVERIFY(!eo->scarceResourceIsDetached()); // this won't be detached since we explicitly preserved it.
2701 QDeclarativeComponent componentSix(&engine, TEST_FILE("scarceresources/scarceResourceTestMultiple.qml"));
2702 object = componentSix.create();
2703 QVERIFY(object != 0);
2704 QVERIFY(object->property("scarceResourceTest").isValid());
2705 QCOMPARE(object->property("scarceResourceTest").toInt(), 100);
2706 QVERIFY(ep->scarceResources == 0); // should have been released by this point.
2707 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2708 QVERIFY(eo->scarceResourceIsDetached()); // all resources were released manually or automatically released.
2711 // test that scarce resources are handled correctly for imports
2712 QDeclarativeComponent componentSeven(&engine, TEST_FILE("scarceresources/scarceResourceCopyImportNoBinding.qml"));
2713 object = componentSeven.create();
2714 QVERIFY(object != 0); // the import should have caused the addition of a resource to the ScarceResources list
2715 QVERIFY(ep->scarceResources == 0); // but they should have been released by this point.
2718 QDeclarativeComponent componentEight(&engine, TEST_FILE("scarceresources/scarceResourceCopyImportFail.qml"));
2719 object = componentEight.create();
2720 QVERIFY(object != 0);
2721 QVERIFY(!object->property("scarceResourceCopy").isValid()); // wasn't preserved, so shouldn't be valid.
2722 QVERIFY(ep->scarceResources == 0); // should have been released by this point.
2725 QDeclarativeComponent componentNine(&engine, TEST_FILE("scarceresources/scarceResourceCopyImport.qml"));
2726 object = componentNine.create();
2727 QVERIFY(object != 0);
2728 QVERIFY(object->property("scarceResourceCopy").isValid()); // preserved, so should be valid.
2729 QCOMPARE(object->property("scarceResourceCopy").value<QPixmap>(), origPixmap);
2730 QVERIFY(object->property("scarceResourceAssignedCopyOne").isValid()); // assigned before destroy(), so should be valid.
2731 QCOMPARE(object->property("scarceResourceAssignedCopyOne").value<QPixmap>(), origPixmap);
2732 QVERIFY(!object->property("scarceResourceAssignedCopyTwo").isValid()); // assigned after destroy(), so should be invalid.
2733 QVERIFY(ep->scarceResources == 0); // this will still be zero, because "preserve()" REMOVES it from this list.
2736 // test that scarce resources are handled properly in signal invocation
2737 QDeclarativeComponent componentTen(&engine, TEST_FILE("scarceresources/scarceResourceSignal.qml"));
2738 object = componentTen.create();
2739 QVERIFY(object != 0);
2740 QObject *srsc = object->findChild<QObject*>("srsc");
2742 QVERIFY(!srsc->property("scarceResourceCopy").isValid()); // hasn't been instantiated yet.
2743 QCOMPARE(srsc->property("width"), QVariant(5)); // default value is 5.
2744 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2745 QVERIFY(eo->scarceResourceIsDetached()); // should be no other copies of it at this stage.
2746 QMetaObject::invokeMethod(srsc, "testSignal");
2747 QVERIFY(!srsc->property("scarceResourceCopy").isValid()); // still hasn't been instantiated
2748 QCOMPARE(srsc->property("width"), QVariant(10)); // but width was assigned to 10.
2749 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2750 QVERIFY(eo->scarceResourceIsDetached()); // should still be no other copies of it at this stage.
2751 QMetaObject::invokeMethod(srsc, "testSignal2"); // assigns scarceResourceCopy to the scarce pixmap.
2752 QVERIFY(srsc->property("scarceResourceCopy").isValid());
2753 QCOMPARE(srsc->property("scarceResourceCopy").value<QPixmap>(), origPixmap);
2754 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2755 QVERIFY(!(eo->scarceResourceIsDetached())); // should be another copy of the resource now.
2756 QVERIFY(ep->scarceResources == 0); // should have been released by this point.
2759 // test that scarce resources are handled properly from js functions in qml files
2760 QDeclarativeComponent componentEleven(&engine, TEST_FILE("scarceresources/scarceResourceFunction.qml"));
2761 object = componentEleven.create();
2762 QVERIFY(object != 0);
2763 QVERIFY(!object->property("scarceResourceCopy").isValid()); // not yet assigned, so should not be valid
2764 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2765 QVERIFY(eo->scarceResourceIsDetached()); // should be no other copies of it at this stage.
2766 QMetaObject::invokeMethod(object, "retrieveScarceResource");
2767 QVERIFY(object->property("scarceResourceCopy").isValid()); // assigned, so should be valid.
2768 QCOMPARE(object->property("scarceResourceCopy").value<QPixmap>(), origPixmap);
2769 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2770 QVERIFY(!eo->scarceResourceIsDetached()); // should be a copy of the resource at this stage.
2771 QMetaObject::invokeMethod(object, "releaseScarceResource");
2772 QVERIFY(!object->property("scarceResourceCopy").isValid()); // just released, so should not be valid
2773 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2774 QVERIFY(eo->scarceResourceIsDetached()); // should be no other copies of it at this stage.
2775 QVERIFY(ep->scarceResources == 0); // should have been released by this point.
2778 // test that if an exception occurs while invoking js function from cpp, that the resources are released.
2779 QDeclarativeComponent componentTwelve(&engine, TEST_FILE("scarceresources/scarceResourceFunctionFail.qml"));
2780 object = componentTwelve.create();
2781 QVERIFY(object != 0);
2782 QVERIFY(!object->property("scarceResourceCopy").isValid()); // not yet assigned, so should not be valid
2783 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2784 QVERIFY(eo->scarceResourceIsDetached()); // should be no other copies of it at this stage.
2785 QString expectedWarning = QLatin1String("file://") + TEST_FILE("scarceresources/scarceResourceFunctionFail.qml").toLocalFile() + QLatin1String(":16: TypeError: Result of expression 'scarceResourceProvider.scarceResource' [[object Object]] is not a function.");
2786 QTest::ignoreMessage(QtWarningMsg, expectedWarning.toAscii().constData()); // we expect a meaningful warning to be printed.
2787 QMetaObject::invokeMethod(object, "retrieveScarceResource");
2788 QVERIFY(!object->property("scarceResourceCopy").isValid()); // due to exception, assignment will NOT have occurred.
2789 eo = qobject_cast<ScarceResourceObject*>(QDeclarativeProperty::read(object, "a").value<QObject*>());
2790 QVERIFY(eo->scarceResourceIsDetached()); // should be no other copies of it at this stage.
2791 QVERIFY(ep->scarceResources == 0); // should have been released by this point.
2795 void tst_qdeclarativeecmascript::propertyChangeSlots()
2797 // ensure that allowable property names are allowed and onPropertyNameChanged slots are generated correctly.
2798 QDeclarativeComponent component(&engine, TEST_FILE("changeslots/propertyChangeSlots.qml"));
2799 QObject *object = component.create();
2800 QVERIFY(object != 0);
2803 // ensure that invalid property names fail properly.
2804 QTest::ignoreMessage(QtWarningMsg, "QDeclarativeComponent: Component is not ready");
2805 QDeclarativeComponent e1(&engine, TEST_FILE("changeslots/propertyChangeSlotErrors.1.qml"));
2806 QString expectedErrorString = e1.url().toString() + QLatin1String(":9:5: Cannot assign to non-existent property \"on_nameWithUnderscoreChanged\"");
2807 QCOMPARE(e1.errors().at(0).toString(), expectedErrorString);
2808 object = e1.create();
2809 QVERIFY(object == 0);
2812 QTest::ignoreMessage(QtWarningMsg, "QDeclarativeComponent: Component is not ready");
2813 QDeclarativeComponent e2(&engine, TEST_FILE("changeslots/propertyChangeSlotErrors.2.qml"));
2814 expectedErrorString = e2.url().toString() + QLatin1String(":9:5: Cannot assign to non-existent property \"on____nameWithUnderscoresChanged\"");
2815 QCOMPARE(e2.errors().at(0).toString(), expectedErrorString);
2816 object = e2.create();
2817 QVERIFY(object == 0);
2820 QTest::ignoreMessage(QtWarningMsg, "QDeclarativeComponent: Component is not ready");
2821 QDeclarativeComponent e3(&engine, TEST_FILE("changeslots/propertyChangeSlotErrors.3.qml"));
2822 expectedErrorString = e3.url().toString() + QLatin1String(":9:5: Cannot assign to non-existent property \"on$NameWithDollarsignChanged\"");
2823 QCOMPARE(e3.errors().at(0).toString(), expectedErrorString);
2824 object = e3.create();
2825 QVERIFY(object == 0);
2828 QTest::ignoreMessage(QtWarningMsg, "QDeclarativeComponent: Component is not ready");
2829 QDeclarativeComponent e4(&engine, TEST_FILE("changeslots/propertyChangeSlotErrors.4.qml"));
2830 expectedErrorString = e4.url().toString() + QLatin1String(":9:5: Cannot assign to non-existent property \"on_6NameWithUnderscoreNumberChanged\"");
2831 QCOMPARE(e4.errors().at(0).toString(), expectedErrorString);
2832 object = e4.create();
2833 QVERIFY(object == 0);
2837 // Test that assigning a null object works
2838 // Regressed with: df1788b4dbbb2826ae63f26bdf166342595343f4
2839 void tst_qdeclarativeecmascript::nullObjectBinding()
2841 QDeclarativeComponent component(&engine, TEST_FILE("nullObjectBinding.qml"));
2843 QObject *object = component.create();
2844 QVERIFY(object != 0);
2846 QVERIFY(object->property("test") == QVariant::fromValue((QObject *)0));
2851 // Test that bindings don't evaluate once the engine has been destroyed
2852 void tst_qdeclarativeecmascript::deletedEngine()
2854 QDeclarativeEngine *engine = new QDeclarativeEngine;
2855 QDeclarativeComponent component(engine, TEST_FILE("deletedEngine.qml"));
2857 QObject *object = component.create();
2858 QVERIFY(object != 0);
2860 QCOMPARE(object->property("a").toInt(), 39);
2861 object->setProperty("b", QVariant(9));
2862 QCOMPARE(object->property("a").toInt(), 117);
2866 QCOMPARE(object->property("a").toInt(), 117);
2867 object->setProperty("b", QVariant(10));
2868 QCOMPARE(object->property("a").toInt(), 117);
2873 // Test the crashing part of QTBUG-9705
2874 void tst_qdeclarativeecmascript::libraryScriptAssert()
2876 QDeclarativeComponent component(&engine, TEST_FILE("libraryScriptAssert.qml"));
2878 QObject *object = component.create();
2879 QVERIFY(object != 0);
2884 void tst_qdeclarativeecmascript::variantsAssignedUndefined()
2886 QDeclarativeComponent component(&engine, TEST_FILE("variantsAssignedUndefined.qml"));
2888 QObject *object = component.create();
2889 QVERIFY(object != 0);
2891 QCOMPARE(object->property("test1").toInt(), 10);
2892 QCOMPARE(object->property("test2").toInt(), 11);
2894 object->setProperty("runTest", true);
2896 QCOMPARE(object->property("test1"), QVariant());
2897 QCOMPARE(object->property("test2"), QVariant());
2903 void tst_qdeclarativeecmascript::qtbug_9792()
2905 QDeclarativeComponent component(&engine, TEST_FILE("qtbug_9792.qml"));
2907 QDeclarativeContext *context = new QDeclarativeContext(engine.rootContext());
2909 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create(context));
2910 QVERIFY(object != 0);
2912 QTest::ignoreMessage(QtDebugMsg, "Hello world!");
2913 object->basicSignal();
2917 transientErrorsMsgCount = 0;
2918 QtMsgHandler old = qInstallMsgHandler(transientErrorsMsgHandler);
2920 object->basicSignal();
2922 qInstallMsgHandler(old);
2924 QCOMPARE(transientErrorsMsgCount, 0);
2929 // Verifies that QDeclarativeGuard<>s used in the vmemetaobject are cleaned correctly
2930 void tst_qdeclarativeecmascript::qtcreatorbug_1289()
2932 QDeclarativeComponent component(&engine, TEST_FILE("qtcreatorbug_1289.qml"));
2934 QObject *o = component.create();
2937 QObject *nested = qvariant_cast<QObject *>(o->property("object"));
2938 QVERIFY(nested != 0);
2940 QVERIFY(qvariant_cast<QObject *>(nested->property("nestedObject")) == o);
2943 nested = qvariant_cast<QObject *>(o->property("object"));
2944 QVERIFY(nested == 0);
2946 // If the bug is present, the next line will crash
2950 // Test that we shut down without stupid warnings
2951 void tst_qdeclarativeecmascript::noSpuriousWarningsAtShutdown()
2954 QDeclarativeComponent component(&engine, TEST_FILE("noSpuriousWarningsAtShutdown.qml"));
2956 QObject *o = component.create();
2958 transientErrorsMsgCount = 0;
2959 QtMsgHandler old = qInstallMsgHandler(transientErrorsMsgHandler);
2963 qInstallMsgHandler(old);
2965 QCOMPARE(transientErrorsMsgCount, 0);
2970 QDeclarativeComponent component(&engine, TEST_FILE("noSpuriousWarningsAtShutdown.2.qml"));
2972 QObject *o = component.create();
2974 transientErrorsMsgCount = 0;
2975 QtMsgHandler old = qInstallMsgHandler(transientErrorsMsgHandler);
2979 qInstallMsgHandler(old);
2981 QCOMPARE(transientErrorsMsgCount, 0);
2985 void tst_qdeclarativeecmascript::canAssignNullToQObject()
2988 QDeclarativeComponent component(&engine, TEST_FILE("canAssignNullToQObject.1.qml"));
2990 MyQmlObject *o = qobject_cast<MyQmlObject *>(component.create());
2993 QVERIFY(o->objectProperty() != 0);
2995 o->setProperty("runTest", true);
2997 QVERIFY(o->objectProperty() == 0);
3003 QDeclarativeComponent component(&engine, TEST_FILE("canAssignNullToQObject.2.qml"));
3005 MyQmlObject *o = qobject_cast<MyQmlObject *>(component.create());
3008 QVERIFY(o->objectProperty() == 0);
3014 void tst_qdeclarativeecmascript::functionAssignment_fromBinding()
3016 QDeclarativeComponent component(&engine, TEST_FILE("functionAssignment.1.qml"));
3018 QString url = component.url().toString();
3019 QString warning = url + ":4: Unable to assign a function to a property.";
3020 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
3022 MyQmlObject *o = qobject_cast<MyQmlObject *>(component.create());
3025 QVERIFY(!o->property("a").isValid());
3030 void tst_qdeclarativeecmascript::functionAssignment_fromJS()
3032 QFETCH(QString, triggerProperty);
3034 QDeclarativeComponent component(&engine, TEST_FILE("functionAssignment.2.qml"));
3035 QVERIFY2(component.errorString().isEmpty(), qPrintable(component.errorString()));
3037 MyQmlObject *o = qobject_cast<MyQmlObject *>(component.create());
3039 QVERIFY(!o->property("a").isValid());
3041 o->setProperty("aNumber", QVariant(5));
3042 o->setProperty(triggerProperty.toUtf8().constData(), true);
3043 QCOMPARE(o->property("a"), QVariant(50));
3045 o->setProperty("aNumber", QVariant(10));
3046 QCOMPARE(o->property("a"), QVariant(100));
3051 void tst_qdeclarativeecmascript::functionAssignment_fromJS_data()
3053 QTest::addColumn<QString>("triggerProperty");
3055 QTest::newRow("assign to property") << "assignToProperty";
3056 QTest::newRow("assign to property, from JS file") << "assignToPropertyFromJsFile";
3058 QTest::newRow("assign to value type") << "assignToValueType";
3060 QTest::newRow("use 'this'") << "assignWithThis";
3061 QTest::newRow("use 'this' from JS file") << "assignWithThisFromJsFile";
3064 void tst_qdeclarativeecmascript::functionAssignmentfromJS_invalid()
3066 QDeclarativeComponent component(&engine, TEST_FILE("functionAssignment.2.qml"));
3067 QVERIFY2(component.errorString().isEmpty(), qPrintable(component.errorString()));
3069 MyQmlObject *o = qobject_cast<MyQmlObject *>(component.create());
3071 QVERIFY(!o->property("a").isValid());
3073 o->setProperty("assignFuncWithoutReturn", true);
3074 QVERIFY(!o->property("a").isValid());
3076 QString url = component.url().toString();
3077 QString warning = url + ":63: Unable to assign QString to int";
3078 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
3079 o->setProperty("assignWrongType", true);
3081 warning = url + ":70: Unable to assign QString to int";
3082 QTest::ignoreMessage(QtWarningMsg, warning.toLatin1().constData());
3083 o->setProperty("assignWrongTypeToValueType", true);
3088 void tst_qdeclarativeecmascript::eval()
3090 QDeclarativeComponent component(&engine, TEST_FILE("eval.qml"));
3092 QObject *o = component.create();
3095 QCOMPARE(o->property("test1").toBool(), true);
3096 QCOMPARE(o->property("test2").toBool(), true);
3097 QCOMPARE(o->property("test3").toBool(), true);
3098 QCOMPARE(o->property("test4").toBool(), true);
3099 QCOMPARE(o->property("test5").toBool(), true);
3104 void tst_qdeclarativeecmascript::function()
3106 QDeclarativeComponent component(&engine, TEST_FILE("function.qml"));
3108 QObject *o = component.create();
3111 QCOMPARE(o->property("test1").toBool(), true);
3112 QCOMPARE(o->property("test2").toBool(), true);
3113 QCOMPARE(o->property("test3").toBool(), true);
3118 // Test the "Qt.include" method
3119 void tst_qdeclarativeecmascript::include()
3121 // Non-library relative include
3123 QDeclarativeComponent component(&engine, TEST_FILE("include.qml"));
3124 QObject *o = component.create();
3127 QCOMPARE(o->property("test0").toInt(), 99);
3128 QCOMPARE(o->property("test1").toBool(), true);
3129 QCOMPARE(o->property("test2").toBool(), true);
3130 QCOMPARE(o->property("test2_1").toBool(), true);
3131 QCOMPARE(o->property("test3").toBool(), true);
3132 QCOMPARE(o->property("test3_1").toBool(), true);
3137 // Library relative include
3139 QDeclarativeComponent component(&engine, TEST_FILE("include_shared.qml"));
3140 QObject *o = component.create();
3143 QCOMPARE(o->property("test0").toInt(), 99);
3144 QCOMPARE(o->property("test1").toBool(), true);
3145 QCOMPARE(o->property("test2").toBool(), true);
3146 QCOMPARE(o->property("test2_1").toBool(), true);
3147 QCOMPARE(o->property("test3").toBool(), true);
3148 QCOMPARE(o->property("test3_1").toBool(), true);
3155 QDeclarativeComponent component(&engine, TEST_FILE("include_callback.qml"));
3156 QObject *o = component.create();
3159 QCOMPARE(o->property("test1").toBool(), true);
3160 QCOMPARE(o->property("test2").toBool(), true);
3161 QCOMPARE(o->property("test3").toBool(), true);
3162 QCOMPARE(o->property("test4").toBool(), true);
3163 QCOMPARE(o->property("test5").toBool(), true);
3164 QCOMPARE(o->property("test6").toBool(), true);
3169 // Including file with ".pragma library"
3171 QDeclarativeComponent component(&engine, TEST_FILE("include_pragma.qml"));
3172 QObject *o = component.create();
3174 QCOMPARE(o->property("test1").toInt(), 100);
3181 TestHTTPServer server(8111);
3182 QVERIFY(server.isValid());
3183 server.serveDirectory(SRCDIR "/data");
3185 QDeclarativeComponent component(&engine, TEST_FILE("include_remote.qml"));
3186 QObject *o = component.create();
3189 QTRY_VERIFY(o->property("done").toBool() == true);
3190 QTRY_VERIFY(o->property("done2").toBool() == true);
3192 QCOMPARE(o->property("test1").toBool(), true);
3193 QCOMPARE(o->property("test2").toBool(), true);
3194 QCOMPARE(o->property("test3").toBool(), true);
3195 QCOMPARE(o->property("test4").toBool(), true);
3196 QCOMPARE(o->property("test5").toBool(), true);
3198 QCOMPARE(o->property("test6").toBool(), true);
3199 QCOMPARE(o->property("test7").toBool(), true);
3200 QCOMPARE(o->property("test8").toBool(), true);
3201 QCOMPARE(o->property("test9").toBool(), true);
3202 QCOMPARE(o->property("test10").toBool(), true);
3209 TestHTTPServer server(8111);
3210 QVERIFY(server.isValid());
3211 server.serveDirectory(SRCDIR "/data");
3213 QDeclarativeComponent component(&engine, TEST_FILE("include_remote_missing.qml"));
3214 QObject *o = component.create();
3217 QTRY_VERIFY(o->property("done").toBool() == true);
3219 QCOMPARE(o->property("test1").toBool(), true);
3220 QCOMPARE(o->property("test2").toBool(), true);
3221 QCOMPARE(o->property("test3").toBool(), true);
3227 void tst_qdeclarativeecmascript::qtbug_10696()
3229 QDeclarativeComponent component(&engine, TEST_FILE("qtbug_10696.qml"));
3230 QObject *o = component.create();
3235 void tst_qdeclarativeecmascript::qtbug_11606()
3237 QDeclarativeComponent component(&engine, TEST_FILE("qtbug_11606.qml"));
3238 QObject *o = component.create();
3240 QCOMPARE(o->property("test").toBool(), true);
3244 void tst_qdeclarativeecmascript::qtbug_11600()
3246 QDeclarativeComponent component(&engine, TEST_FILE("qtbug_11600.qml"));
3247 QObject *o = component.create();
3249 QCOMPARE(o->property("test").toBool(), true);
3253 // Reading and writing non-scriptable properties should fail
3254 void tst_qdeclarativeecmascript::nonscriptable()
3256 QDeclarativeComponent component(&engine, TEST_FILE("nonscriptable.qml"));
3257 QObject *o = component.create();
3259 QCOMPARE(o->property("readOk").toBool(), true);
3260 QCOMPARE(o->property("writeOk").toBool(), true);
3264 // deleteLater() should not be callable from QML
3265 void tst_qdeclarativeecmascript::deleteLater()
3267 QDeclarativeComponent component(&engine, TEST_FILE("deleteLater.qml"));
3268 QObject *o = component.create();
3270 QCOMPARE(o->property("test").toBool(), true);
3274 void tst_qdeclarativeecmascript::in()
3276 QDeclarativeComponent component(&engine, TEST_FILE("in.qml"));
3277 QObject *o = component.create();
3279 QCOMPARE(o->property("test1").toBool(), true);
3280 QCOMPARE(o->property("test2").toBool(), true);
3284 void tst_qdeclarativeecmascript::sharedAttachedObject()
3286 QDeclarativeComponent component(&engine, TEST_FILE("sharedAttachedObject.qml"));
3287 QObject *o = component.create();
3289 QCOMPARE(o->property("test1").toBool(), true);
3290 QCOMPARE(o->property("test2").toBool(), true);
3295 void tst_qdeclarativeecmascript::objectName()
3297 QDeclarativeComponent component(&engine, TEST_FILE("objectName.qml"));
3298 QObject *o = component.create();
3301 QCOMPARE(o->property("test1").toString(), QString("hello"));
3302 QCOMPARE(o->property("test2").toString(), QString("ell"));
3304 o->setObjectName("world");
3306 QCOMPARE(o->property("test1").toString(), QString("world"));
3307 QCOMPARE(o->property("test2").toString(), QString("orl"));
3312 void tst_qdeclarativeecmascript::writeRemovesBinding()
3314 QDeclarativeComponent component(&engine, TEST_FILE("writeRemovesBinding.qml"));
3315 QObject *o = component.create();
3318 QCOMPARE(o->property("test").toBool(), true);
3323 // Test bindings assigned to alias properties actually assign to the alias' target
3324 void tst_qdeclarativeecmascript::aliasBindingsAssignCorrectly()
3326 QDeclarativeComponent component(&engine, TEST_FILE("aliasBindingsAssignCorrectly.qml"));
3327 QObject *o = component.create();
3330 QCOMPARE(o->property("test").toBool(), true);
3335 // Test bindings assigned to alias properties override a binding on the target (QTBUG-13719)
3336 void tst_qdeclarativeecmascript::aliasBindingsOverrideTarget()
3339 QDeclarativeComponent component(&engine, TEST_FILE("aliasBindingsOverrideTarget.qml"));
3340 QObject *o = component.create();
3343 QCOMPARE(o->property("test").toBool(), true);
3349 QDeclarativeComponent component(&engine, TEST_FILE("aliasBindingsOverrideTarget.2.qml"));
3350 QObject *o = component.create();
3353 QCOMPARE(o->property("test").toBool(), true);
3359 QDeclarativeComponent component(&engine, TEST_FILE("aliasBindingsOverrideTarget.3.qml"));
3360 QObject *o = component.create();
3363 QCOMPARE(o->property("test").toBool(), true);
3369 // Test that writes to alias properties override bindings on the alias target (QTBUG-13719)
3370 void tst_qdeclarativeecmascript::aliasWritesOverrideBindings()
3373 QDeclarativeComponent component(&engine, TEST_FILE("aliasWritesOverrideBindings.qml"));
3374 QObject *o = component.create();
3377 QCOMPARE(o->property("test").toBool(), true);
3383 QDeclarativeComponent component(&engine, TEST_FILE("aliasWritesOverrideBindings.2.qml"));
3384 QObject *o = component.create();
3387 QCOMPARE(o->property("test").toBool(), true);
3393 QDeclarativeComponent component(&engine, TEST_FILE("aliasWritesOverrideBindings.3.qml"));
3394 QObject *o = component.create();
3397 QCOMPARE(o->property("test").toBool(), true);
3403 void tst_qdeclarativeecmascript::revisionErrors()
3406 QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevisionErrors.qml"));
3407 QString url = component.url().toString();
3409 QString warning1 = url + ":8: ReferenceError: Can't find variable: prop2";
3410 QString warning2 = url + ":11: ReferenceError: Can't find variable: prop2";
3411 QString warning3 = url + ":13: ReferenceError: Can't find variable: method2";
3413 QTest::ignoreMessage(QtWarningMsg, warning1.toLatin1().constData());
3414 QTest::ignoreMessage(QtWarningMsg, warning2.toLatin1().constData());
3415 QTest::ignoreMessage(QtWarningMsg, warning3.toLatin1().constData());
3416 MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create());
3417 QVERIFY(object != 0);
3421 QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevisionErrors2.qml"));
3422 QString url = component.url().toString();
3424 // MyRevisionedSubclass 1.0 uses MyRevisionedClass revision 0
3425 // method2, prop2 from MyRevisionedClass not available
3426 // method4, prop4 from MyRevisionedSubclass not available
3427 QString warning1 = url + ":8: ReferenceError: Can't find variable: prop2";
3428 QString warning2 = url + ":14: ReferenceError: Can't find variable: prop2";
3429 QString warning3 = url + ":10: ReferenceError: Can't find variable: prop4";
3430 QString warning4 = url + ":16: ReferenceError: Can't find variable: prop4";
3431 QString warning5 = url + ":20: ReferenceError: Can't find variable: method2";
3433 QTest::ignoreMessage(QtWarningMsg, warning1.toLatin1().constData());
3434 QTest::ignoreMessage(QtWarningMsg, warning2.toLatin1().constData());
3435 QTest::ignoreMessage(QtWarningMsg, warning3.toLatin1().constData());
3436 QTest::ignoreMessage(QtWarningMsg, warning4.toLatin1().constData());
3437 QTest::ignoreMessage(QtWarningMsg, warning5.toLatin1().constData());
3438 MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create());
3439 QVERIFY(object != 0);
3443 QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevisionErrors3.qml"));
3444 QString url = component.url().toString();
3446 // MyRevisionedSubclass 1.1 uses MyRevisionedClass revision 1
3447 // All properties/methods available, except MyRevisionedBaseClassUnregistered rev 1
3448 QString warning1 = url + ":30: ReferenceError: Can't find variable: methodD";
3449 QString warning2 = url + ":10: ReferenceError: Can't find variable: propD";
3450 QString warning3 = url + ":20: ReferenceError: Can't find variable: propD";
3451 QTest::ignoreMessage(QtWarningMsg, warning1.toLatin1().constData());
3452 QTest::ignoreMessage(QtWarningMsg, warning2.toLatin1().constData());
3453 QTest::ignoreMessage(QtWarningMsg, warning3.toLatin1().constData());
3454 MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create());
3455 QVERIFY(object != 0);
3460 void tst_qdeclarativeecmascript::revision()
3463 QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevision.qml"));
3464 QString url = component.url().toString();
3466 MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create());
3467 QVERIFY(object != 0);
3471 QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevision2.qml"));
3472 QString url = component.url().toString();
3474 MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create());
3475 QVERIFY(object != 0);
3479 QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevision3.qml"));
3480 QString url = component.url().toString();
3482 MyRevisionedClass *object = qobject_cast<MyRevisionedClass *>(component.create());
3483 QVERIFY(object != 0);
3486 // Test that non-root classes can resolve revisioned methods
3488 QDeclarativeComponent component(&engine, TEST_FILE("metaobjectRevision4.qml"));
3490 QObject *object = component.create();
3491 QVERIFY(object != 0);
3492 QCOMPARE(object->property("test").toReal(), 11.);
3497 // Test for QScriptDeclarativeClass::pushCleanContext()
3498 void tst_qdeclarativeecmascript::pushCleanContext()
3500 QScriptEngine engine;
3501 engine.globalObject().setProperty("a", 6);
3502 QCOMPARE(engine.evaluate("a").toInt32(), 6);
3504 // First confirm pushContext() behaves as we expect
3505 QScriptValue object = engine.newObject();
3506 object.setProperty("a", 15);
3507 QScriptContext *context1 = engine.pushContext();
3508 context1->pushScope(object);
3509 QCOMPARE(engine.evaluate("a").toInt32(), 15);
3511 QScriptContext *context2 = engine.pushContext();
3513 QCOMPARE(engine.evaluate("a").toInt32(), 15);
3514 QScriptValue func1 = engine.evaluate("(function() { return a; })");
3516 // Now check that pushCleanContext() works
3517 QScriptDeclarativeClass::pushCleanContext(&engine);
3518 QCOMPARE(engine.evaluate("a").toInt32(), 6);
3519 QScriptValue func2 = engine.evaluate("(function() { return a; })");
3521 engine.popContext();
3522 QCOMPARE(engine.evaluate("a").toInt32(), 15);
3524 engine.popContext();
3525 QCOMPARE(engine.evaluate("a").toInt32(), 15);
3527 engine.popContext();
3528 QCOMPARE(engine.evaluate("a").toInt32(), 6);
3530 // Check that function objects created in these contexts work
3531 QCOMPARE(func1.call().toInt32(), 15);
3532 QCOMPARE(func2.call().toInt32(), 6);
3535 void tst_qdeclarativeecmascript::realToInt()
3537 QDeclarativeComponent component(&engine, TEST_FILE("realToInt.qml"));
3538 MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create());
3539 QVERIFY(object != 0);
3541 QMetaObject::invokeMethod(object, "test1");
3542 QCOMPARE(object->value(), int(4));
3543 QMetaObject::invokeMethod(object, "test2");
3544 QCOMPARE(object->value(), int(8));
3547 QTEST_MAIN(tst_qdeclarativeecmascript)
3549 #include "tst_qdeclarativeecmascript.moc"