Initial import from the monolithic Qt.
[profile/ivi/qtdeclarative.git] / tests / auto / declarative / qdeclarativedom / tst_qdeclarativedom.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
6 **
7 ** This file is part of the test suite of the Qt Toolkit.
8 **
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** No Commercial Usage
11 ** This file contains pre-release code and may not be distributed.
12 ** You may use this file in accordance with the terms and conditions
13 ** contained in the Technology Preview License Agreement accompanying
14 ** this package.
15 **
16 ** GNU Lesser General Public License Usage
17 ** Alternatively, this file may be used under the terms of the GNU Lesser
18 ** General Public License version 2.1 as published by the Free Software
19 ** Foundation and appearing in the file LICENSE.LGPL included in the
20 ** packaging of this file.  Please review the following information to
21 ** ensure the GNU Lesser General Public License version 2.1 requirements
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23 **
24 ** In addition, as a special exception, Nokia gives you certain additional
25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27 **
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at qt-info@nokia.com.
30 **
31 **
32 **
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 #include <qtest.h>
42 #include <QtDeclarative/qdeclarativeengine.h>
43 #include <QtDeclarative/qdeclarativecomponent.h>
44 #include <QtDeclarative/private/qdeclarativedom_p.h>
45
46 #include <QtCore/QDebug>
47 #include <QtCore/QFile>
48
49 #ifdef Q_OS_SYMBIAN
50 // In Symbian OS test data is located in applications private dir
51 #define SRCDIR "."
52 #endif
53
54 class tst_qdeclarativedom : public QObject
55 {
56     Q_OBJECT
57 public:
58     tst_qdeclarativedom() {}
59
60 private slots:
61     void loadSimple();
62     void loadProperties();
63     void loadGroupedProperties();
64     void loadChildObject();
65     void loadComposite();
66     void loadImports();
67     void loadErrors();
68     void loadSyntaxErrors();
69     void loadRemoteErrors();
70     void loadDynamicProperty();
71     void loadComponent();
72
73     void testValueSource();
74     void testValueInterceptor();
75
76     void object_dynamicProperty();
77     void object_property();
78     void object_url();
79
80     void copy();
81     void position();
82 private:
83     QDeclarativeEngine engine;
84 };
85
86
87 void tst_qdeclarativedom::loadSimple()
88 {
89     QByteArray qml = "import QtQuick 1.0\n"
90                       "Item {}";
91
92     QDeclarativeDomDocument document;
93     QVERIFY(document.load(&engine, qml));
94     QVERIFY(document.errors().isEmpty());
95
96     QDeclarativeDomObject rootObject = document.rootObject();
97     QVERIFY(rootObject.isValid());
98     QVERIFY(!rootObject.isComponent());
99     QVERIFY(!rootObject.isCustomType());
100     QVERIFY(rootObject.objectType() == "QtQuick/Item");
101     QVERIFY(rootObject.objectTypeMajorVersion() == 1);
102     QVERIFY(rootObject.objectTypeMinorVersion() == 0);
103 }
104
105 // Test regular properties
106 void tst_qdeclarativedom::loadProperties()
107 {
108     QByteArray qml = "import QtQuick 1.0\n"
109                      "Item { id : item; x : 300; visible : true }";
110
111     QDeclarativeDomDocument document;
112     QVERIFY(document.load(&engine, qml));
113
114     QDeclarativeDomObject rootObject = document.rootObject();
115     QVERIFY(rootObject.isValid());
116     QVERIFY(rootObject.objectId() == "item");
117     QCOMPARE(rootObject.properties().size(), 3);
118
119     QDeclarativeDomProperty xProperty = rootObject.property("x");
120     QVERIFY(xProperty.propertyName() == "x");
121     QCOMPARE(xProperty.propertyNameParts().count(), 1);
122     QVERIFY(xProperty.propertyNameParts().at(0) == "x");
123     QCOMPARE(xProperty.position(), 37);
124     QCOMPARE(xProperty.length(), 1);
125     QVERIFY(xProperty.value().isLiteral());
126     QVERIFY(xProperty.value().toLiteral().literal() == "300");
127
128     QDeclarativeDomProperty visibleProperty = rootObject.property("visible");
129     QVERIFY(visibleProperty.propertyName() == "visible");
130     QCOMPARE(visibleProperty.propertyNameParts().count(), 1);
131     QVERIFY(visibleProperty.propertyNameParts().at(0) == "visible");
132     QCOMPARE(visibleProperty.position(), 46);
133     QCOMPARE(visibleProperty.length(), 7);
134     QVERIFY(visibleProperty.value().isLiteral());
135     QVERIFY(visibleProperty.value().toLiteral().literal() == "true");
136 }
137
138 // Test grouped properties
139 void tst_qdeclarativedom::loadGroupedProperties()
140 {
141     {
142         QByteArray qml = "import QtQuick 1.0\n"
143                          "Item { anchors.left: parent.left; anchors.right: parent.right }";
144
145         QDeclarativeDomDocument document;
146         QVERIFY(document.load(&engine, qml));
147
148         QDeclarativeDomObject rootItem = document.rootObject();
149         QVERIFY(rootItem.isValid());
150         QVERIFY(rootItem.properties().size() == 2);
151
152         // Order is not deterministic
153         QDeclarativeDomProperty p0 = rootItem.properties().at(0);
154         QDeclarativeDomProperty p1 = rootItem.properties().at(1);
155         QDeclarativeDomProperty leftProperty;
156         QDeclarativeDomProperty rightProperty;
157         if (p0.propertyName() == "anchors.left") {
158             leftProperty = p0;
159             rightProperty = p1;
160         } else {
161             leftProperty = p1;
162             rightProperty = p0;
163         }
164
165         QVERIFY(leftProperty.propertyName() == "anchors.left");
166         QCOMPARE(leftProperty.propertyNameParts().count(), 2);
167         QVERIFY(leftProperty.propertyNameParts().at(0) == "anchors");
168         QVERIFY(leftProperty.propertyNameParts().at(1) == "left");
169         QCOMPARE(leftProperty.position(), 26);
170         QCOMPARE(leftProperty.length(), 12);
171         QVERIFY(leftProperty.value().isBinding());
172         QVERIFY(leftProperty.value().toBinding().binding() == "parent.left");
173
174         QVERIFY(rightProperty.propertyName() == "anchors.right");
175         QCOMPARE(rightProperty.propertyNameParts().count(), 2);
176         QVERIFY(rightProperty.propertyNameParts().at(0) == "anchors");
177         QVERIFY(rightProperty.propertyNameParts().at(1) == "right");
178         QCOMPARE(rightProperty.position(), 53);
179         QCOMPARE(rightProperty.length(), 13);
180         QVERIFY(rightProperty.value().isBinding());
181         QVERIFY(rightProperty.value().toBinding().binding() == "parent.right");
182     }
183
184     {
185         QByteArray qml = "import QtQuick 1.0\n"
186                          "Item { \n"
187                          "    anchors {\n"
188                          "        left: parent.left\n"
189                          "        right: parent.right\n"
190                          "    }\n"
191                          "}";
192
193         QDeclarativeDomDocument document;
194         QVERIFY(document.load(&engine, qml));
195
196         QDeclarativeDomObject rootItem = document.rootObject();
197         QVERIFY(rootItem.isValid());
198         QVERIFY(rootItem.properties().size() == 2);
199
200         // Order is not deterministic
201         QDeclarativeDomProperty p0 = rootItem.properties().at(0);
202         QDeclarativeDomProperty p1 = rootItem.properties().at(1);
203         QDeclarativeDomProperty leftProperty;
204         QDeclarativeDomProperty rightProperty;
205         if (p0.propertyName() == "anchors.left") {
206             leftProperty = p0;
207             rightProperty = p1;
208         } else {
209             leftProperty = p1;
210             rightProperty = p0;
211         }
212
213         QVERIFY(leftProperty.propertyName() == "anchors.left");
214         QCOMPARE(leftProperty.propertyNameParts().count(), 2);
215         QVERIFY(leftProperty.propertyNameParts().at(0) == "anchors");
216         QVERIFY(leftProperty.propertyNameParts().at(1) == "left");
217         QCOMPARE(leftProperty.position(), 49);
218         QCOMPARE(leftProperty.length(), 4);
219         QVERIFY(leftProperty.value().isBinding());
220         QVERIFY(leftProperty.value().toBinding().binding() == "parent.left");
221
222         QVERIFY(rightProperty.propertyName() == "anchors.right");
223         QCOMPARE(rightProperty.propertyNameParts().count(), 2);
224         QVERIFY(rightProperty.propertyNameParts().at(0) == "anchors");
225         QVERIFY(rightProperty.propertyNameParts().at(1) == "right");
226         QCOMPARE(rightProperty.position(), 75);
227         QCOMPARE(rightProperty.length(), 5);
228         QVERIFY(rightProperty.value().isBinding());
229         QVERIFY(rightProperty.value().toBinding().binding() == "parent.right");
230     }
231
232 }
233
234 void tst_qdeclarativedom::loadChildObject()
235 {
236     QByteArray qml = "import QtQuick 1.0\n"
237                      "Item { Item {} }";
238
239     QDeclarativeDomDocument document;
240     QVERIFY(document.load(&engine, qml));
241
242     QDeclarativeDomObject rootItem = document.rootObject();
243     QVERIFY(rootItem.isValid());
244     QVERIFY(rootItem.properties().size() == 1);
245
246     QDeclarativeDomProperty listProperty = rootItem.properties().at(0);
247     QVERIFY(listProperty.isDefaultProperty());
248     QVERIFY(listProperty.value().isList());
249
250     QDeclarativeDomList list = listProperty.value().toList();
251     QVERIFY(list.values().size() == 1);
252
253     QDeclarativeDomObject childItem = list.values().first().toObject();
254     QVERIFY(childItem.isValid());
255     QVERIFY(childItem.objectType() == "QtQuick/Item");
256 }
257
258 void tst_qdeclarativedom::loadComposite()
259 {
260     QFile file(SRCDIR  "/data/top.qml");
261     QVERIFY(file.open(QIODevice::ReadOnly | QIODevice::Text));
262
263     QDeclarativeDomDocument document;
264     QVERIFY(document.load(&engine, file.readAll(), QUrl::fromLocalFile(file.fileName())));
265     QVERIFY(document.errors().isEmpty());
266
267     QDeclarativeDomObject rootItem = document.rootObject();
268     QVERIFY(rootItem.isValid());
269     QCOMPARE(rootItem.objectType(), QByteArray("MyComponent"));
270     QCOMPARE(rootItem.properties().size(), 2);
271
272     QDeclarativeDomProperty widthProperty = rootItem.property("width");
273     QVERIFY(widthProperty.value().isLiteral());
274
275     QDeclarativeDomProperty heightProperty = rootItem.property("height");
276     QVERIFY(heightProperty.value().isLiteral());
277 }
278
279 void tst_qdeclarativedom::testValueSource()
280 {
281     QByteArray qml = "import QtQuick 1.0\n"
282                      "Rectangle { SpringAnimation on height { spring: 1.4; damping: .15; to: Math.min(Math.max(-130, value*2.2 - 130), 133); }}";
283
284     QDeclarativeEngine freshEngine;
285     QDeclarativeDomDocument document;
286     QVERIFY(document.load(&freshEngine, qml));
287
288     QDeclarativeDomObject rootItem = document.rootObject();
289     QVERIFY(rootItem.isValid());
290     QDeclarativeDomProperty heightProperty = rootItem.properties().at(0);
291     QVERIFY(heightProperty.propertyName() == "height");
292     QVERIFY(heightProperty.value().isValueSource());
293
294     const QDeclarativeDomValueValueSource valueSource = heightProperty.value().toValueSource();
295     QDeclarativeDomObject valueSourceObject = valueSource.object();
296     QVERIFY(valueSourceObject.isValid());
297
298     QVERIFY(valueSourceObject.objectType() == "QtQuick/SpringAnimation");
299
300     const QDeclarativeDomValue springValue = valueSourceObject.property("spring").value();
301     QVERIFY(!springValue.isInvalid());
302     QVERIFY(springValue.isLiteral());
303     QVERIFY(springValue.toLiteral().literal() == "1.4");
304
305     const QDeclarativeDomValue sourceValue = valueSourceObject.property("to").value();
306     QVERIFY(!sourceValue.isInvalid());
307     QVERIFY(sourceValue.isBinding());
308     QVERIFY(sourceValue.toBinding().binding() == "Math.min(Math.max(-130, value*2.2 - 130), 133)");
309 }
310
311 void tst_qdeclarativedom::testValueInterceptor()
312 {
313     QByteArray qml = "import QtQuick 1.0\n"
314                      "Rectangle { Behavior on height { NumberAnimation { duration: 100 } } }";
315
316     QDeclarativeEngine freshEngine;
317     QDeclarativeDomDocument document;
318     QVERIFY(document.load(&freshEngine, qml));
319
320     QDeclarativeDomObject rootItem = document.rootObject();
321     QVERIFY(rootItem.isValid());
322     QDeclarativeDomProperty heightProperty = rootItem.properties().at(0);
323     QVERIFY(heightProperty.propertyName() == "height");
324     QVERIFY(heightProperty.value().isValueInterceptor());
325
326     const QDeclarativeDomValueValueInterceptor valueInterceptor = heightProperty.value().toValueInterceptor();
327     QDeclarativeDomObject valueInterceptorObject = valueInterceptor.object();
328     QVERIFY(valueInterceptorObject.isValid());
329
330     QVERIFY(valueInterceptorObject.objectType() == "QtQuick/Behavior");
331
332     const QDeclarativeDomValue animationValue = valueInterceptorObject.property("animation").value();
333     QVERIFY(!animationValue.isInvalid());
334     QVERIFY(animationValue.isObject());
335 }
336
337 // Test QDeclarativeDomDocument::imports()
338 void tst_qdeclarativedom::loadImports()
339 {
340     QByteArray qml = "import QtQuick 1.0\n"
341                      "import importlib.sublib 1.1\n"
342                      "import importlib.sublib 1.0 as NewFoo\n"
343                      "import 'import'\n"
344                      "import 'import' as X\n"
345                      "Item {}";
346
347     QDeclarativeEngine engine;
348     engine.addImportPath(SRCDIR "/data");
349     QDeclarativeDomDocument document;
350     QVERIFY(document.load(&engine, qml, QUrl::fromLocalFile(SRCDIR "/data/dummy.qml")));
351
352     QCOMPARE(document.imports().size(), 5);
353
354     QDeclarativeDomImport import = document.imports().at(0);
355     QCOMPARE(import.type(), QDeclarativeDomImport::Library);
356     QCOMPARE(import.uri(), QLatin1String("QtQuick"));
357     QCOMPARE(import.qualifier(), QString());
358     QCOMPARE(import.version(), QLatin1String("1.0"));
359
360     import = document.imports().at(1);
361     QCOMPARE(import.type(), QDeclarativeDomImport::Library);
362     QCOMPARE(import.uri(), QLatin1String("importlib.sublib"));
363     QCOMPARE(import.qualifier(), QString());
364     QCOMPARE(import.version(), QLatin1String("1.1"));
365
366     import = document.imports().at(2);
367     QCOMPARE(import.type(), QDeclarativeDomImport::Library);
368     QCOMPARE(import.uri(), QLatin1String("importlib.sublib"));
369     QCOMPARE(import.qualifier(), QLatin1String("NewFoo"));
370     QCOMPARE(import.version(), QLatin1String("1.0"));
371
372     import = document.imports().at(3);
373     QCOMPARE(import.type(), QDeclarativeDomImport::File);
374     QCOMPARE(import.uri(), QLatin1String("import"));
375     QCOMPARE(import.qualifier(), QLatin1String(""));
376     QCOMPARE(import.version(), QLatin1String(""));
377
378     import = document.imports().at(4);
379     QCOMPARE(import.type(), QDeclarativeDomImport::File);
380     QCOMPARE(import.uri(), QLatin1String("import"));
381     QCOMPARE(import.qualifier(), QLatin1String("X"));
382     QCOMPARE(import.version(), QLatin1String(""));
383 }
384
385 // Test loading a file with errors
386 void tst_qdeclarativedom::loadErrors()
387 {
388     QByteArray qml = "import QtQuick 1.0\n"
389                      "Item {\n"
390                      "  foo: 12\n"
391                      "}";
392
393     QDeclarativeDomDocument document;
394     QVERIFY(false == document.load(&engine, qml));
395
396     QCOMPARE(document.errors().count(), 1);
397     QDeclarativeError error = document.errors().first();
398
399     QCOMPARE(error.url(), QUrl());
400     QCOMPARE(error.line(), 3);
401     QCOMPARE(error.column(), 3);
402     QCOMPARE(error.description(), QString("Cannot assign to non-existent property \"foo\""));
403 }
404
405 // Test loading a file with syntax errors
406 void tst_qdeclarativedom::loadSyntaxErrors()
407 {
408     QByteArray qml = "import QtQuick 1.0\n"
409                      "asdf";
410
411     QDeclarativeDomDocument document;
412     QVERIFY(false == document.load(&engine, qml));
413
414     QCOMPARE(document.errors().count(), 1);
415     QDeclarativeError error = document.errors().first();
416
417     QCOMPARE(error.url(), QUrl());
418     QCOMPARE(error.line(), 2);
419     QCOMPARE(error.column(), 1);
420     QCOMPARE(error.description(), QString("Syntax error"));
421 }
422
423 // Test attempting to load a file with remote references
424 void tst_qdeclarativedom::loadRemoteErrors()
425 {
426     QByteArray qml = "import QtQuick 1.0\n"
427                      "import \"http://localhost/exampleQmlScript.js\" as Script\n"
428                      "Item {\n"
429                      "}";
430     QDeclarativeDomDocument document;
431     QVERIFY(false == document.load(&engine, qml));
432
433     QCOMPARE(document.errors().count(), 1);
434     QDeclarativeError error = document.errors().first();
435
436     QCOMPARE(error.url(), QUrl());
437     QCOMPARE(error.line(), -1);
438     QCOMPARE(error.column(), -1);
439     QCOMPARE(error.description(), QString("QDeclarativeDomDocument supports local types only"));
440 }
441
442 // Test dynamic property declarations
443 void tst_qdeclarativedom::loadDynamicProperty()
444 {
445     {
446         QByteArray qml = "import QtQuick 1.0\n"
447                          "Item {\n"
448                          "    property int a\n"
449                          "    property bool b\n"
450                          "    property double c\n"
451                          "    property real d\n"
452                          "    property string e\n"
453                          "    property url f\n"
454                          "    property color g\n"
455                          "    property date h\n"
456                          "    property variant i\n"
457                          "    property QtObject j\n"
458                          "}";
459
460         QDeclarativeDomDocument document;
461         QVERIFY(document.load(&engine, qml));
462
463         QDeclarativeDomObject rootObject = document.rootObject();
464         QVERIFY(rootObject.isValid());
465
466         QCOMPARE(rootObject.dynamicProperties().count(), 10);
467
468 #define DP_TEST(index, name, type, test_position, test_length, propTypeName) \
469     { \
470         QDeclarativeDomDynamicProperty d = rootObject.dynamicProperties().at(index); \
471         QVERIFY(d.isValid()); \
472         QVERIFY(d.propertyName() == # name ); \
473         QVERIFY(d.propertyType() == type); \
474         QVERIFY(d.propertyTypeName() == propTypeName); \
475         QVERIFY(d.isDefaultProperty() == false); \
476         QVERIFY(d.defaultValue().isValid() == false); \
477         QCOMPARE(d.position(), test_position); \
478         QCOMPARE(d.length(), test_length); \
479     } \
480
481         DP_TEST(0, a, QVariant::Int, 30, 14, "int");
482         DP_TEST(1, b, QVariant::Bool, 49, 15, "bool");
483         DP_TEST(2, c, QMetaType::QReal, 69, 17, "double");
484         DP_TEST(3, d, QMetaType::QReal, 91, 15, "real");
485         DP_TEST(4, e, QVariant::String, 111, 17, "string");
486         DP_TEST(5, f, QVariant::Url, 133, 14, "url");
487         DP_TEST(6, g, QVariant::Color, 152, 16, "color");
488         DP_TEST(7, h, QVariant::DateTime, 173, 15, "date");
489         DP_TEST(8, i, qMetaTypeId<QVariant>(), 193, 18, "variant");
490         DP_TEST(9, j, -1, 216, 19, "QtObject");
491     }
492
493     {
494         QByteArray qml = "import QtQuick 1.0\n"
495                          "Item {\n"
496                          "    id: item\n"
497                          "    property int a: 12\n"
498                          "    property int b: a + 6\n"
499                          "    default property QtObject c\n"
500                          "    property alias d: item.a\n"
501                          "}\n";
502
503         QDeclarativeDomDocument document;
504         QVERIFY(document.load(&engine, qml));
505
506         QDeclarativeDomObject rootObject = document.rootObject();
507         QVERIFY(rootObject.isValid());
508
509         QCOMPARE(rootObject.dynamicProperties().count(), 4);
510
511         {
512             QDeclarativeDomDynamicProperty d = rootObject.dynamicProperties().at(0);
513             QVERIFY(d.isDefaultProperty() == false);
514             QVERIFY(d.isAlias() == false);
515             QVERIFY(d.defaultValue().isValid());
516             QVERIFY(d.defaultValue().propertyName() == "a");
517             QVERIFY(d.defaultValue().value().isLiteral());
518         }
519
520         {
521             QDeclarativeDomDynamicProperty d = rootObject.dynamicProperties().at(1);
522             QVERIFY(d.isDefaultProperty() == false);
523             QVERIFY(d.isAlias() == false);
524             QVERIFY(d.defaultValue().isValid());
525             QVERIFY(d.defaultValue().propertyName() == "b");
526             QVERIFY(d.defaultValue().value().isBinding());
527         }
528
529         {
530             QDeclarativeDomDynamicProperty d = rootObject.dynamicProperties().at(2);
531             QVERIFY(d.isDefaultProperty() == true);
532             QVERIFY(d.isAlias() == false);
533             QVERIFY(d.defaultValue().isValid() == false);
534         }
535
536         {
537             QDeclarativeDomDynamicProperty d = rootObject.dynamicProperties().at(3);
538             QVERIFY(d.isDefaultProperty() == false);
539             QVERIFY(d.isAlias() == true);
540         }
541     }
542 }
543
544 // Test inline components
545 void tst_qdeclarativedom::loadComponent()
546 {
547     // Explicit component
548     {
549         QByteArray qml = "import QtQuick 1.0\n"
550                          "Item {\n"
551                          "    Component {\n"
552                          "        id: myComponent\n"
553                          "        Item {}\n"
554                          "    }\n"
555                          "}";
556
557         QDeclarativeDomDocument document;
558         QVERIFY(document.load(&engine, qml));
559
560         QDeclarativeDomObject rootItem = document.rootObject();
561         QVERIFY(rootItem.isValid());
562         QVERIFY(rootItem.properties().size() == 1);
563
564         QDeclarativeDomProperty listProperty = rootItem.properties().at(0);
565         QVERIFY(listProperty.isDefaultProperty());
566         QVERIFY(listProperty.value().isList());
567
568         QDeclarativeDomList list = listProperty.value().toList();
569         QVERIFY(list.values().size() == 1);
570
571         QDeclarativeDomObject componentObject = list.values().first().toObject();
572         QVERIFY(componentObject.isValid());
573         QVERIFY(componentObject.objectClassName() == "Component");
574         QVERIFY(componentObject.isComponent());
575
576         QDeclarativeDomComponent component = componentObject.toComponent();
577         QVERIFY(component.isValid());
578         QVERIFY(component.objectType() == "QtQuick/Component");
579         QVERIFY(component.objectTypeMajorVersion() == 1);
580         QVERIFY(component.objectTypeMinorVersion() == 0);
581         QVERIFY(component.objectClassName() == "Component");
582         QVERIFY(component.objectId() == "myComponent");
583         QVERIFY(component.properties().isEmpty());
584         QVERIFY(component.dynamicProperties().isEmpty());
585         QVERIFY(component.isCustomType() == false);
586         QVERIFY(component.customTypeData() == "");
587         QVERIFY(component.isComponent());
588         QCOMPARE(component.position(), 30);
589         QCOMPARE(component.length(), 57);
590
591         QVERIFY(component.componentRoot().isValid());
592         QVERIFY(component.componentRoot().objectClassName() == "Item");
593     }
594
595     // Implicit component
596     {
597         QByteArray qml = "import QtQuick 1.0\n"
598                          "ListView {\n"
599                          "    delegate: Item {}\n"
600                          "}";
601
602         QDeclarativeDomDocument document;
603         QVERIFY(document.load(&engine, qml));
604
605         QDeclarativeDomObject rootItem = document.rootObject();
606         QVERIFY(rootItem.isValid());
607         QVERIFY(rootItem.properties().size() == 1);
608
609         QDeclarativeDomProperty delegate = rootItem.property("delegate");
610
611         QDeclarativeDomObject componentObject = delegate.value().toObject();
612         QVERIFY(componentObject.isValid());
613         QVERIFY(componentObject.objectClassName() == "Component");
614         QVERIFY(componentObject.isComponent());
615
616         QDeclarativeDomComponent component = componentObject.toComponent();
617         QVERIFY(component.isValid());
618         QVERIFY(component.objectType() == "QtQuick/Component");
619         QVERIFY(component.objectClassName() == "Component");
620         QVERIFY(component.objectId() == "");
621         QVERIFY(component.properties().isEmpty());
622         QVERIFY(component.dynamicProperties().isEmpty());
623         QVERIFY(component.isCustomType() == false);
624         QVERIFY(component.customTypeData() == "");
625         QVERIFY(component.isComponent());
626         QCOMPARE(component.position(), 44);
627         QCOMPARE(component.length(), 7);
628
629         QVERIFY(component.componentRoot().isValid());
630         QVERIFY(component.componentRoot().objectClassName() == "Item");
631     }
632 }
633
634 // Test QDeclarativeDomObject::dynamicProperty() method
635 void tst_qdeclarativedom::object_dynamicProperty()
636 {
637     // Invalid object
638     {
639         QDeclarativeDomObject object;
640         QVERIFY(object.dynamicProperty("").isValid() == false);
641         QVERIFY(object.dynamicProperty("foo").isValid() == false);
642     }
643
644
645     // Valid object, no dynamic properties
646     {
647         QByteArray qml = "import QtQuick 1.0\n"
648                          "Item {}";
649
650         QDeclarativeDomDocument document;
651         QVERIFY(document.load(&engine, qml));
652
653         QDeclarativeDomObject rootObject = document.rootObject();
654         QVERIFY(rootObject.isValid());
655
656         QVERIFY(rootObject.dynamicProperty("").isValid() == false);
657         QVERIFY(rootObject.dynamicProperty("foo").isValid() == false);
658     }
659
660     // Valid object, dynamic properties
661     {
662         QByteArray qml = "import QtQuick 1.0\n"
663                          "Item {\n"
664                          "    property int a\n"
665                          "}";
666
667         QDeclarativeDomDocument document;
668         QVERIFY(document.load(&engine, qml));
669
670         QDeclarativeDomObject rootObject = document.rootObject();
671         QVERIFY(rootObject.isValid());
672
673         QVERIFY(rootObject.dynamicProperty("").isValid() == false);
674         QVERIFY(rootObject.dynamicProperty("foo").isValid() == false);
675
676         QDeclarativeDomDynamicProperty p = rootObject.dynamicProperty("a");
677         QVERIFY(p.isValid());
678         QVERIFY(p.propertyName() == "a");
679         QVERIFY(p.propertyType() == QVariant::Int);
680         QVERIFY(p.propertyTypeName() == "int");
681         QVERIFY(p.isDefaultProperty() == false);
682         QCOMPARE(p.position(), 30);
683         QCOMPARE(p.length(), 14);
684     }
685
686 }
687
688 // Test QDeclarativeObject::property() method
689 void tst_qdeclarativedom::object_property()
690 {
691     // Invalid object
692     {
693         QDeclarativeDomObject object;
694         QVERIFY(object.property("").isValid() == false);
695         QVERIFY(object.property("foo").isValid() == false);
696     }
697
698     // Valid object - no default
699     {
700         QByteArray qml = "import QtQuick 1.0\n"
701                          "Item {\n"
702                          "    x: 10\n"
703                          "    y: 12\n"
704                          "}\n";
705
706         QDeclarativeDomDocument document;
707         QVERIFY(document.load(&engine, qml));
708
709         QDeclarativeDomObject rootObject = document.rootObject();
710         QVERIFY(rootObject.isValid());
711
712         QVERIFY(rootObject.property("").isValid() == false);
713         QVERIFY(rootObject.property("foo").isValid() == false);
714
715         QDeclarativeDomProperty x = rootObject.property("x");
716         QVERIFY(x.isValid());
717         QVERIFY(x.propertyName() == "x");
718         QVERIFY(x.propertyNameParts().count() == 1);
719         QVERIFY(x.propertyNameParts().at(0) == "x");
720         QVERIFY(x.isDefaultProperty() == false);
721         QVERIFY(x.value().isLiteral());
722         QVERIFY(x.value().toLiteral().literal() == "10");
723         QCOMPARE(x.position(), 30);
724         QCOMPARE(x.length(), 1);
725
726         QDeclarativeDomProperty y = rootObject.property("y");
727         QVERIFY(y.isValid());
728         QVERIFY(y.propertyName() == "y");
729         QVERIFY(y.propertyNameParts().count() == 1);
730         QVERIFY(y.propertyNameParts().at(0) == "y");
731         QVERIFY(y.isDefaultProperty() == false);
732         QVERIFY(y.value().isLiteral());
733         QVERIFY(y.value().toLiteral().literal() == "12");
734         QCOMPARE(y.position(), 40);
735         QCOMPARE(y.length(), 1);
736     }
737
738     // Valid object - with default
739     {
740         QByteArray qml = "import QtQuick 1.0\n"
741                          "Item {\n"
742                          "    x: 10\n"
743                          "    y: 12\n"
744                          "    Item {}\n"
745                          "}\n";
746
747         QDeclarativeDomDocument document;
748         QVERIFY(document.load(&engine, qml));
749
750         QDeclarativeDomObject rootObject = document.rootObject();
751         QVERIFY(rootObject.isValid());
752
753         QVERIFY(rootObject.property("").isValid() == false);
754         QVERIFY(rootObject.property("foo").isValid() == false);
755
756         QDeclarativeDomProperty x = rootObject.property("x");
757         QVERIFY(x.isValid());
758         QVERIFY(x.propertyName() == "x");
759         QVERIFY(x.propertyNameParts().count() == 1);
760         QVERIFY(x.propertyNameParts().at(0) == "x");
761         QVERIFY(x.isDefaultProperty() == false);
762         QVERIFY(x.value().isLiteral());
763         QVERIFY(x.value().toLiteral().literal() == "10");
764         QCOMPARE(x.position(), 30);
765         QCOMPARE(x.length(), 1);
766
767         QDeclarativeDomProperty y = rootObject.property("y");
768         QVERIFY(y.isValid());
769         QVERIFY(y.propertyName() == "y");
770         QVERIFY(y.propertyNameParts().count() == 1);
771         QVERIFY(y.propertyNameParts().at(0) == "y");
772         QVERIFY(y.isDefaultProperty() == false);
773         QVERIFY(y.value().isLiteral());
774         QVERIFY(y.value().toLiteral().literal() == "12");
775         QCOMPARE(y.position(), 40);
776         QCOMPARE(y.length(), 1);
777
778         QDeclarativeDomProperty data = rootObject.property("data");
779         QVERIFY(data.isValid());
780         QVERIFY(data.propertyName() == "data");
781         QVERIFY(data.propertyNameParts().count() == 1);
782         QVERIFY(data.propertyNameParts().at(0) == "data");
783         QVERIFY(data.isDefaultProperty() == true);
784         QVERIFY(data.value().isList());
785         QCOMPARE(data.position(), 50);
786         QCOMPARE(data.length(), 0);
787     }
788 }
789
790 // Tests the QDeclarativeDomObject::url() method
791 void tst_qdeclarativedom::object_url()
792 {
793     // Invalid object
794     {
795         QDeclarativeDomObject object;
796         QCOMPARE(object.url(), QUrl());
797     }
798
799     // Valid builtin object
800     {
801         QByteArray qml = "import QtQuick 1.0\n"
802                          "Item {}";
803
804         QDeclarativeDomDocument document;
805         QVERIFY(document.load(&engine, qml));
806
807         QDeclarativeDomObject rootObject = document.rootObject();
808         QVERIFY(rootObject.isValid());
809         QCOMPARE(rootObject.url(), QUrl());
810     }
811
812     // Valid composite object
813     {
814         QByteArray qml = "import QtQuick 1.0\n"
815                          "MyItem {}";
816
817         QUrl myUrl = QUrl::fromLocalFile(SRCDIR "/data/main.qml");
818         QUrl subUrl = QUrl::fromLocalFile(SRCDIR "/data/MyItem.qml");
819
820         QDeclarativeDomDocument document;
821         QVERIFY(document.load(&engine, qml, myUrl));
822
823         QDeclarativeDomObject rootObject = document.rootObject();
824         QVERIFY(rootObject.isValid());
825         QCOMPARE(rootObject.url(), subUrl);
826     }
827 }
828
829 // Test copy constructors and operators
830 void tst_qdeclarativedom::copy()
831 {
832     QByteArray qml = "import QtQuick 1.0\n"
833                      "MyItem {\n"
834                      "    id: myItem\n"
835                      "    property int a: 10\n"
836                      "    x: 10\n"
837                      "    y: x + 10\n"
838                      "    NumberAnimation on z {}\n"
839                      "    Behavior on opacity {}\n"
840                      "    Component {\n"
841                      "        Item{}\n"
842                      "    }\n"
843                      "    children: [ Item{}, Item{} ]\n"
844                      "}\n";
845
846     QUrl myUrl = QUrl::fromLocalFile(SRCDIR "/data/main.qml");
847
848     QDeclarativeDomDocument document;
849     QVERIFY(document.load(&engine, qml, myUrl));
850
851     // QDeclarativeDomDocument
852     {
853         QDeclarativeDomDocument document2(document);
854         QDeclarativeDomDocument document3;
855         document3 = document;
856
857         QCOMPARE(document.imports().count(), document2.imports().count());
858         QCOMPARE(document.errors().count(), document2.errors().count());
859         QCOMPARE(document.rootObject().objectClassName(), document2.rootObject().objectClassName());
860
861         QCOMPARE(document.imports().count(), document3.imports().count());
862         QCOMPARE(document.errors().count(), document3.errors().count());
863         QCOMPARE(document.rootObject().objectClassName(), document3.rootObject().objectClassName());
864     }
865
866     // QDeclarativeDomImport
867     {
868         QCOMPARE(document.imports().count(), 1);
869         QDeclarativeDomImport import = document.imports().at(0);
870
871         QDeclarativeDomImport import2(import);
872         QDeclarativeDomImport import3;
873         import3 = import2;
874
875         QCOMPARE(import.type(), import2.type());
876         QCOMPARE(import.uri(), import2.uri());
877         QCOMPARE(import.version(), import2.version());
878         QCOMPARE(import.qualifier(), import2.qualifier());
879
880         QCOMPARE(import.type(), import3.type());
881         QCOMPARE(import.uri(), import3.uri());
882         QCOMPARE(import.version(), import3.version());
883         QCOMPARE(import.qualifier(), import3.qualifier());
884     }
885
886     // QDeclarativeDomObject
887     {
888         QDeclarativeDomObject object = document.rootObject();
889         QVERIFY(object.isValid());
890
891         QDeclarativeDomObject object2(object);
892         QDeclarativeDomObject object3;
893         object3 = object;
894
895         QCOMPARE(object.isValid(), object2.isValid());
896         QCOMPARE(object.objectType(), object2.objectType());
897         QCOMPARE(object.objectClassName(), object2.objectClassName());
898         QCOMPARE(object.objectTypeMajorVersion(), object2.objectTypeMajorVersion());
899         QCOMPARE(object.objectTypeMinorVersion(), object2.objectTypeMinorVersion());
900         QCOMPARE(object.objectId(), object2.objectId());
901         QCOMPARE(object.properties().count(), object2.properties().count());
902         QCOMPARE(object.dynamicProperties().count(), object2.dynamicProperties().count());
903         QCOMPARE(object.isCustomType(), object2.isCustomType());
904         QCOMPARE(object.customTypeData(), object2.customTypeData());
905         QCOMPARE(object.isComponent(), object2.isComponent());
906         QCOMPARE(object.position(), object2.position());
907         QCOMPARE(object.length(), object2.length());
908         QCOMPARE(object.url(), object2.url());
909
910         QCOMPARE(object.isValid(), object3.isValid());
911         QCOMPARE(object.objectType(), object3.objectType());
912         QCOMPARE(object.objectClassName(), object3.objectClassName());
913         QCOMPARE(object.objectTypeMajorVersion(), object3.objectTypeMajorVersion());
914         QCOMPARE(object.objectTypeMinorVersion(), object3.objectTypeMinorVersion());
915         QCOMPARE(object.objectId(), object3.objectId());
916         QCOMPARE(object.properties().count(), object3.properties().count());
917         QCOMPARE(object.dynamicProperties().count(), object3.dynamicProperties().count());
918         QCOMPARE(object.isCustomType(), object3.isCustomType());
919         QCOMPARE(object.customTypeData(), object3.customTypeData());
920         QCOMPARE(object.isComponent(), object3.isComponent());
921         QCOMPARE(object.position(), object3.position());
922         QCOMPARE(object.length(), object3.length());
923         QCOMPARE(object.url(), object3.url());
924     }
925
926     // QDeclarativeDomDynamicProperty
927     {
928         QDeclarativeDomObject object = document.rootObject();
929         QDeclarativeDomDynamicProperty property = object.dynamicProperty("a");
930
931         QDeclarativeDomDynamicProperty property2(property);
932         QDeclarativeDomDynamicProperty property3;
933         property3 = property;
934
935         QCOMPARE(property.isValid(), property2.isValid());
936         QCOMPARE(property.propertyName(), property2.propertyName());
937         QCOMPARE(property.propertyType(), property2.propertyType());
938         QCOMPARE(property.propertyTypeName(), property2.propertyTypeName());
939         QCOMPARE(property.isDefaultProperty(), property2.isDefaultProperty());
940         QCOMPARE(property.defaultValue().propertyName(), property2.defaultValue().propertyName());
941         QCOMPARE(property.position(), property2.position());
942         QCOMPARE(property.length(), property2.length());
943
944         QCOMPARE(property.isValid(), property3.isValid());
945         QCOMPARE(property.propertyName(), property3.propertyName());
946         QCOMPARE(property.propertyType(), property3.propertyType());
947         QCOMPARE(property.propertyTypeName(), property3.propertyTypeName());
948         QCOMPARE(property.isDefaultProperty(), property3.isDefaultProperty());
949         QCOMPARE(property.defaultValue().propertyName(), property3.defaultValue().propertyName());
950         QCOMPARE(property.position(), property3.position());
951         QCOMPARE(property.length(), property3.length());
952     }
953
954     // QDeclarativeDomProperty
955     {
956         QDeclarativeDomObject object = document.rootObject();
957         QDeclarativeDomProperty property = object.property("opacity");
958
959         QDeclarativeDomProperty property2(property);
960         QDeclarativeDomProperty property3;
961         property3 = property;
962
963         QCOMPARE(property.isValid(), property2.isValid());
964         QCOMPARE(property.propertyName(), property2.propertyName());
965         QCOMPARE(property.propertyNameParts(), property2.propertyNameParts());
966         QCOMPARE(property.isDefaultProperty(), property2.isDefaultProperty());
967         QCOMPARE(property.value().type(), property2.value().type());
968         QCOMPARE(property.position(), property2.position());
969         QCOMPARE(property.length(), property2.length());
970
971         QCOMPARE(property.isValid(), property3.isValid());
972         QCOMPARE(property.propertyName(), property3.propertyName());
973         QCOMPARE(property.propertyNameParts(), property3.propertyNameParts());
974         QCOMPARE(property.isDefaultProperty(), property3.isDefaultProperty());
975         QCOMPARE(property.value().type(), property3.value().type());
976         QCOMPARE(property.position(), property3.position());
977         QCOMPARE(property.length(), property3.length());
978     }
979
980     // QDeclarativeDomValueLiteral
981     {
982         QDeclarativeDomObject object = document.rootObject();
983         QDeclarativeDomProperty property = object.property("x");
984         QDeclarativeDomValueLiteral literal = property.value().toLiteral();
985         QCOMPARE(literal.literal(), QString("10"));
986
987         QDeclarativeDomValueLiteral literal2(literal);
988         QDeclarativeDomValueLiteral literal3;
989         literal3 = literal2;
990
991         QCOMPARE(literal2.literal(), QString("10"));
992         QCOMPARE(literal3.literal(), QString("10"));
993     }
994
995
996     // QDeclarativeDomValueBinding
997     {
998         QDeclarativeDomObject object = document.rootObject();
999         QDeclarativeDomProperty property = object.property("y");
1000         QDeclarativeDomValueBinding binding = property.value().toBinding();
1001         QCOMPARE(binding.binding(), QString("x + 10"));
1002
1003         QDeclarativeDomValueBinding binding2(binding);
1004         QDeclarativeDomValueBinding binding3;
1005         binding3 = binding2;
1006
1007         QCOMPARE(binding2.binding(), QString("x + 10"));
1008         QCOMPARE(binding3.binding(), QString("x + 10"));
1009     }
1010
1011     // QDeclarativeDomValueValueSource
1012     {
1013         QDeclarativeDomObject object = document.rootObject();
1014         QDeclarativeDomProperty property = object.property("z");
1015         QDeclarativeDomValueValueSource source = property.value().toValueSource();
1016         QCOMPARE(source.object().objectClassName(), QByteArray("NumberAnimation"));
1017
1018         QDeclarativeDomValueValueSource source2(source);
1019         QDeclarativeDomValueValueSource source3;
1020         source3 = source;
1021
1022         QCOMPARE(source2.object().objectClassName(), QByteArray("NumberAnimation"));
1023         QCOMPARE(source3.object().objectClassName(), QByteArray("NumberAnimation"));
1024     }
1025
1026     // QDeclarativeDomValueValueInterceptor
1027     {
1028         QDeclarativeDomObject object = document.rootObject();
1029         QDeclarativeDomProperty property = object.property("opacity");
1030         QDeclarativeDomValueValueInterceptor interceptor = property.value().toValueInterceptor();
1031         QCOMPARE(interceptor.object().objectClassName(), QByteArray("Behavior"));
1032
1033         QDeclarativeDomValueValueInterceptor interceptor2(interceptor);
1034         QDeclarativeDomValueValueInterceptor interceptor3;
1035         interceptor3 = interceptor;
1036
1037         QCOMPARE(interceptor2.object().objectClassName(), QByteArray("Behavior"));
1038         QCOMPARE(interceptor3.object().objectClassName(), QByteArray("Behavior"));
1039     }
1040
1041     // QDeclarativeDomComponent
1042     {
1043         QDeclarativeDomObject object = document.rootObject();
1044         QDeclarativeDomProperty property = object.property("data");
1045         QCOMPARE(property.value().toList().values().count(), 1);
1046         QDeclarativeDomComponent component =
1047             property.value().toList().values().at(0).toObject().toComponent();
1048         QCOMPARE(component.componentRoot().objectClassName(), QByteArray("Item"));
1049
1050         QDeclarativeDomComponent component2(component);
1051         QDeclarativeDomComponent component3;
1052         component3 = component;
1053
1054         QCOMPARE(component.componentRoot().objectClassName(), component2.componentRoot().objectClassName());
1055         QCOMPARE(component.isValid(), component2.isValid());
1056         QCOMPARE(component.objectType(), component2.objectType());
1057         QCOMPARE(component.objectClassName(), component2.objectClassName());
1058         QCOMPARE(component.objectTypeMajorVersion(), component2.objectTypeMajorVersion());
1059         QCOMPARE(component.objectTypeMinorVersion(), component2.objectTypeMinorVersion());
1060         QCOMPARE(component.objectId(), component2.objectId());
1061         QCOMPARE(component.properties().count(), component2.properties().count());
1062         QCOMPARE(component.dynamicProperties().count(), component2.dynamicProperties().count());
1063         QCOMPARE(component.isCustomType(), component2.isCustomType());
1064         QCOMPARE(component.customTypeData(), component2.customTypeData());
1065         QCOMPARE(component.isComponent(), component2.isComponent());
1066         QCOMPARE(component.position(), component2.position());
1067         QCOMPARE(component.length(), component2.length());
1068         QCOMPARE(component.url(), component2.url());
1069
1070         QCOMPARE(component.componentRoot().objectClassName(), component3.componentRoot().objectClassName());
1071         QCOMPARE(component.isValid(), component3.isValid());
1072         QCOMPARE(component.objectType(), component3.objectType());
1073         QCOMPARE(component.objectClassName(), component3.objectClassName());
1074         QCOMPARE(component.objectTypeMajorVersion(), component3.objectTypeMajorVersion());
1075         QCOMPARE(component.objectTypeMinorVersion(), component3.objectTypeMinorVersion());
1076         QCOMPARE(component.objectId(), component3.objectId());
1077         QCOMPARE(component.properties().count(), component3.properties().count());
1078         QCOMPARE(component.dynamicProperties().count(), component3.dynamicProperties().count());
1079         QCOMPARE(component.isCustomType(), component3.isCustomType());
1080         QCOMPARE(component.customTypeData(), component3.customTypeData());
1081         QCOMPARE(component.isComponent(), component3.isComponent());
1082         QCOMPARE(component.position(), component3.position());
1083         QCOMPARE(component.length(), component3.length());
1084         QCOMPARE(component.url(), component3.url());
1085     }
1086
1087     // QDeclarativeDomValue
1088     {
1089         QDeclarativeDomObject object = document.rootObject();
1090         QDeclarativeDomProperty property = object.property("data");
1091         QDeclarativeDomValue value = property.value();
1092
1093         QDeclarativeDomValue value2(value);
1094         QDeclarativeDomValue value3;
1095         value3 = value;
1096
1097         QCOMPARE(value.type(), value2.type());
1098         QCOMPARE(value.isInvalid(), value2.isInvalid());
1099         QCOMPARE(value.isLiteral(), value2.isLiteral());
1100         QCOMPARE(value.isBinding(), value2.isBinding());
1101         QCOMPARE(value.isValueSource(), value2.isValueSource());
1102         QCOMPARE(value.isValueInterceptor(), value2.isValueInterceptor());
1103         QCOMPARE(value.isObject(), value2.isObject());
1104         QCOMPARE(value.isList(), value2.isList());
1105         QCOMPARE(value.position(), value2.position());
1106         QCOMPARE(value.length(), value2.length());
1107
1108         QCOMPARE(value.type(), value3.type());
1109         QCOMPARE(value.isInvalid(), value3.isInvalid());
1110         QCOMPARE(value.isLiteral(), value3.isLiteral());
1111         QCOMPARE(value.isBinding(), value3.isBinding());
1112         QCOMPARE(value.isValueSource(), value3.isValueSource());
1113         QCOMPARE(value.isValueInterceptor(), value3.isValueInterceptor());
1114         QCOMPARE(value.isObject(), value3.isObject());
1115         QCOMPARE(value.isList(), value3.isList());
1116         QCOMPARE(value.position(), value3.position());
1117         QCOMPARE(value.length(), value3.length());
1118     }
1119     {
1120         QDeclarativeDomObject object = document.rootObject();
1121         QDeclarativeDomProperty property = object.property("x");
1122         QDeclarativeDomValue value = property.value();
1123
1124         QDeclarativeDomValue value2(value);
1125         QDeclarativeDomValue value3;
1126         value3 = value;
1127
1128         QCOMPARE(value.type(), value2.type());
1129         QCOMPARE(value.isInvalid(), value2.isInvalid());
1130         QCOMPARE(value.isLiteral(), value2.isLiteral());
1131         QCOMPARE(value.isBinding(), value2.isBinding());
1132         QCOMPARE(value.isValueSource(), value2.isValueSource());
1133         QCOMPARE(value.isValueInterceptor(), value2.isValueInterceptor());
1134         QCOMPARE(value.isObject(), value2.isObject());
1135         QCOMPARE(value.isList(), value2.isList());
1136         QCOMPARE(value.position(), value2.position());
1137         QCOMPARE(value.length(), value2.length());
1138
1139         QCOMPARE(value.type(), value3.type());
1140         QCOMPARE(value.isInvalid(), value3.isInvalid());
1141         QCOMPARE(value.isLiteral(), value3.isLiteral());
1142         QCOMPARE(value.isBinding(), value3.isBinding());
1143         QCOMPARE(value.isValueSource(), value3.isValueSource());
1144         QCOMPARE(value.isValueInterceptor(), value3.isValueInterceptor());
1145         QCOMPARE(value.isObject(), value3.isObject());
1146         QCOMPARE(value.isList(), value3.isList());
1147         QCOMPARE(value.position(), value3.position());
1148         QCOMPARE(value.length(), value3.length());
1149     }
1150     {
1151         QDeclarativeDomValue value;
1152
1153         QDeclarativeDomValue value2(value);
1154         QDeclarativeDomValue value3;
1155         value3 = value;
1156
1157         QCOMPARE(value.type(), value2.type());
1158         QCOMPARE(value.isInvalid(), value2.isInvalid());
1159         QCOMPARE(value.isLiteral(), value2.isLiteral());
1160         QCOMPARE(value.isBinding(), value2.isBinding());
1161         QCOMPARE(value.isValueSource(), value2.isValueSource());
1162         QCOMPARE(value.isValueInterceptor(), value2.isValueInterceptor());
1163         QCOMPARE(value.isObject(), value2.isObject());
1164         QCOMPARE(value.isList(), value2.isList());
1165         QCOMPARE(value.position(), value2.position());
1166         QCOMPARE(value.length(), value2.length());
1167
1168         QCOMPARE(value.type(), value3.type());
1169         QCOMPARE(value.isInvalid(), value3.isInvalid());
1170         QCOMPARE(value.isLiteral(), value3.isLiteral());
1171         QCOMPARE(value.isBinding(), value3.isBinding());
1172         QCOMPARE(value.isValueSource(), value3.isValueSource());
1173         QCOMPARE(value.isValueInterceptor(), value3.isValueInterceptor());
1174         QCOMPARE(value.isObject(), value3.isObject());
1175         QCOMPARE(value.isList(), value3.isList());
1176         QCOMPARE(value.position(), value3.position());
1177         QCOMPARE(value.length(), value3.length());
1178     }
1179
1180     // QDeclarativeDomList
1181     {
1182         QDeclarativeDomObject object = document.rootObject();
1183         QDeclarativeDomProperty property = object.property("children");
1184         QDeclarativeDomList list = property.value().toList();
1185         QCOMPARE(list.values().count(), 2);
1186
1187         QDeclarativeDomList list2(list);
1188         QDeclarativeDomList list3;
1189         list3 = list2;
1190
1191         QCOMPARE(list.values().count(), list2.values().count());
1192         QCOMPARE(list.position(), list2.position());
1193         QCOMPARE(list.length(), list2.length());
1194         QCOMPARE(list.commaPositions(), list2.commaPositions());
1195
1196         QCOMPARE(list.values().count(), list3.values().count());
1197         QCOMPARE(list.position(), list3.position());
1198         QCOMPARE(list.length(), list3.length());
1199         QCOMPARE(list.commaPositions(), list3.commaPositions());
1200
1201     }
1202 }
1203
1204 // Tests the position/length of various elements
1205 void tst_qdeclarativedom::position()
1206 {
1207     QByteArray qml = "import QtQuick 1.0\n"
1208                      "Item {\n"
1209                      "    id: myItem\n"
1210                      "    property int a: 10\n"
1211                      "    x: 10\n"
1212                      "    y: x + 10\n"
1213                      "    NumberAnimation on z {}\n"
1214                      "    Behavior on opacity {}\n"
1215                      "    Component {\n"
1216                      "        Item{}\n"
1217                      "    }\n"
1218                      "    children: [ Item{}, Item{} ]\n"
1219                      "}\n";
1220
1221
1222     QDeclarativeDomDocument document;
1223     QVERIFY(document.load(&engine, qml));
1224
1225     QDeclarativeDomObject root = document.rootObject();
1226
1227     // All QDeclarativeDomDynamicProperty
1228     QDeclarativeDomDynamicProperty dynProp = root.dynamicProperty("a");
1229     QCOMPARE(dynProp.position(), 45);
1230     QCOMPARE(dynProp.length(), 18);
1231
1232     // All QDeclarativeDomProperty
1233     QDeclarativeDomProperty x = root.property("x");
1234     QCOMPARE(x.position(), 68);
1235     QCOMPARE(x.length(), 1);
1236
1237     QDeclarativeDomProperty y = root.property("y");
1238     QCOMPARE(y.position(), 78);
1239     QCOMPARE(y.length(), 1);
1240
1241     QDeclarativeDomProperty z = root.property("z");
1242     QCOMPARE(z.position(), 111);
1243     QCOMPARE(z.length(), 1);
1244
1245     QDeclarativeDomProperty opacity = root.property("opacity");
1246     QCOMPARE(opacity.position(), 132);
1247     QCOMPARE(opacity.length(), 7);
1248
1249     QDeclarativeDomProperty data = root.property("data");
1250     QCOMPARE(data.position(), 147);
1251     QCOMPARE(data.length(), 0);
1252
1253     QDeclarativeDomProperty children = root.property("children");
1254     QCOMPARE(children.position(), 184);
1255     QCOMPARE(children.length(), 8);
1256
1257     QDeclarativeDomList dataList = data.value().toList();
1258     QCOMPARE(dataList.values().count(), 1);
1259     QDeclarativeDomList childrenList = children.value().toList();
1260     QCOMPARE(childrenList.values().count(), 2);
1261
1262     // All QDeclarativeDomObject
1263     QCOMPARE(root.position(), 19);
1264     QCOMPARE(root.length(), 195);
1265
1266     QDeclarativeDomObject numberAnimation = z.value().toValueSource().object();
1267     QCOMPARE(numberAnimation.position(), 92);
1268     QCOMPARE(numberAnimation.length(), 23);
1269
1270     QDeclarativeDomObject behavior = opacity.value().toValueInterceptor().object();
1271     QCOMPARE(behavior.position(), 120);
1272     QCOMPARE(behavior.length(), 22);
1273
1274     QDeclarativeDomObject component = dataList.values().at(0).toObject();
1275     QCOMPARE(component.position(), 147);
1276     QCOMPARE(component.length(), 32);
1277
1278     QDeclarativeDomObject componentRoot = component.toComponent().componentRoot();
1279     QCOMPARE(componentRoot.position(), 167);
1280     QCOMPARE(componentRoot.length(), 6);
1281
1282     QDeclarativeDomObject child1 = childrenList.values().at(0).toObject();
1283     QCOMPARE(child1.position(), 196);
1284     QCOMPARE(child1.length(), 6);
1285
1286     QDeclarativeDomObject child2 = childrenList.values().at(1).toObject();
1287     QCOMPARE(child2.position(), 204);
1288     QCOMPARE(child2.length(), 6);
1289
1290     // All QDeclarativeDomValue
1291     QDeclarativeDomValue xValue = x.value();
1292     QCOMPARE(xValue.position(), 71);
1293     QCOMPARE(xValue.length(), 2);
1294
1295     QDeclarativeDomValue yValue = y.value();
1296     QCOMPARE(yValue.position(), 81);
1297     QCOMPARE(yValue.length(), 6);
1298
1299     QDeclarativeDomValue zValue = z.value();
1300     QCOMPARE(zValue.position(), 92);
1301     QCOMPARE(zValue.length(), 23);
1302
1303     QDeclarativeDomValue opacityValue = opacity.value();
1304     QCOMPARE(opacityValue.position(), 120);
1305     QCOMPARE(opacityValue.length(), 22);
1306
1307     QDeclarativeDomValue dataValue = data.value();
1308     QCOMPARE(dataValue.position(), 147);
1309     QCOMPARE(dataValue.length(), 32);
1310
1311     QDeclarativeDomValue child1Value = childrenList.values().at(0);
1312     QCOMPARE(child1Value.position(), 196);
1313     QCOMPARE(child1Value.length(), 6);
1314
1315     QDeclarativeDomValue child2Value = childrenList.values().at(1);
1316     QCOMPARE(child2Value.position(), 204);
1317     QCOMPARE(child2Value.length(), 6);
1318
1319     // All QDeclarativeDomList
1320     QCOMPARE(childrenList.position(), 194);
1321     QCOMPARE(childrenList.length(), 18);
1322 }
1323
1324 QTEST_MAIN(tst_qdeclarativedom)
1325
1326 #include "tst_qdeclarativedom.moc"