d9cbed093a004faf76f27892cac69a7a868b89d7
[profile/ivi/qtdeclarative.git] / tests / auto / quick / qquickrepeater / tst_qquickrepeater.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
5 **
6 ** This file is part of the test suite of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
16 **
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
20 **
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
28 **
29 ** Other Usage
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
32 **
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include <QtTest/QtTest>
43 #include <QtTest/QSignalSpy>
44 #include <private/qlistmodelinterface_p.h>
45 #include <QtQml/qqmlengine.h>
46 #include <QtQuick/qquickview.h>
47 #include <QtQml/qqmlcontext.h>
48 #include <QtQml/qqmlexpression.h>
49 #include <QtQml/qqmlincubator.h>
50 #include <private/qquickrepeater_p.h>
51 #include <QtQuick/private/qquicktext_p.h>
52
53 #include "../../shared/util.h"
54 #include "../shared/viewtestutil.h"
55 #include "../shared/visualtestutil.h"
56
57 using namespace QQuickViewTestUtil;
58 using namespace QQuickVisualTestUtil;
59
60
61 class tst_QQuickRepeater : public QQmlDataTest
62 {
63     Q_OBJECT
64 public:
65     tst_QQuickRepeater();
66
67 private slots:
68     void numberModel();
69     void objectList();
70     void stringList();
71     void dataModel_adding();
72     void dataModel_removing();
73     void dataModel_changes();
74     void itemModel();
75     void resetModel();
76     void modelChanged();
77     void properties();
78     void asynchronous();
79     void initParent();
80     void dynamicModelCrash();
81 };
82
83 class TestObject : public QObject
84 {
85     Q_OBJECT
86
87     Q_PROPERTY(bool error READ error WRITE setError)
88     Q_PROPERTY(bool useModel READ useModel NOTIFY useModelChanged)
89
90 public:
91     TestObject() : QObject(), mError(true), mUseModel(false) {}
92
93     bool error() const { return mError; }
94     void setError(bool err) { mError = err; }
95
96     bool useModel() const { return mUseModel; }
97     void setUseModel(bool use) { mUseModel = use; emit useModelChanged(); }
98
99 signals:
100     void useModelChanged();
101
102 private:
103     bool mError;
104     bool mUseModel;
105 };
106
107 tst_QQuickRepeater::tst_QQuickRepeater()
108 {
109 }
110
111 void tst_QQuickRepeater::numberModel()
112 {
113     QQuickView *canvas = createView();
114
115     QQmlContext *ctxt = canvas->rootContext();
116     ctxt->setContextProperty("testData", 5);
117     TestObject *testObject = new TestObject;
118     ctxt->setContextProperty("testObject", testObject);
119
120     canvas->setSource(testFileUrl("intmodel.qml"));
121     qApp->processEvents();
122
123     QQuickRepeater *repeater = findItem<QQuickRepeater>(canvas->rootObject(), "repeater");
124     QVERIFY(repeater != 0);
125     QCOMPARE(repeater->parentItem()->childItems().count(), 5+1);
126
127     QVERIFY(!repeater->itemAt(-1));
128     for (int i=0; i<repeater->count(); i++)
129         QCOMPARE(repeater->itemAt(i), repeater->parentItem()->childItems().at(i));
130     QVERIFY(!repeater->itemAt(repeater->count()));
131
132     QMetaObject::invokeMethod(canvas->rootObject(), "checkProperties");
133     QVERIFY(testObject->error() == false);
134
135     delete testObject;
136     delete canvas;
137 }
138
139 class MyObject : public QObject
140 {
141     Q_OBJECT
142     Q_PROPERTY(int idx READ idx CONSTANT)
143 public:
144     MyObject(int i) : QObject(), m_idx(i) {}
145
146     int idx() const { return m_idx; }
147
148     int m_idx;
149 };
150
151 void tst_QQuickRepeater::objectList()
152 {
153     QQuickView *canvas = createView();
154     QObjectList data;
155     for (int i=0; i<100; i++)
156         data << new MyObject(i);
157
158     QQmlContext *ctxt = canvas->rootContext();
159     ctxt->setContextProperty("testData", QVariant::fromValue(data));
160
161     canvas->setSource(testFileUrl("objlist.qml"));
162     qApp->processEvents();
163
164     QQuickRepeater *repeater = findItem<QQuickRepeater>(canvas->rootObject(), "repeater");
165     QVERIFY(repeater != 0);
166     QCOMPARE(repeater->property("errors").toInt(), 0);//If this fails either they are out of order or can't find the object's data
167     QCOMPARE(repeater->property("instantiated").toInt(), 100);
168
169     QVERIFY(!repeater->itemAt(-1));
170     for (int i=0; i<data.count(); i++)
171         QCOMPARE(repeater->itemAt(i), repeater->parentItem()->childItems().at(i));
172     QVERIFY(!repeater->itemAt(data.count()));
173
174     QSignalSpy addedSpy(repeater, SIGNAL(itemAdded(int,QQuickItem*)));
175     QSignalSpy removedSpy(repeater, SIGNAL(itemRemoved(int,QQuickItem*)));
176     ctxt->setContextProperty("testData", QVariant::fromValue(data));
177     QCOMPARE(addedSpy.count(), data.count());
178     QCOMPARE(removedSpy.count(), data.count());
179
180     qDeleteAll(data);
181     delete canvas;
182 }
183
184 /*
185 The Repeater element creates children at its own position in its parent's
186 stacking order.  In this test we insert a repeater between two other Text
187 elements to test this.
188 */
189 void tst_QQuickRepeater::stringList()
190 {
191     QQuickView *canvas = createView();
192
193     QStringList data;
194     data << "One";
195     data << "Two";
196     data << "Three";
197     data << "Four";
198
199     QQmlContext *ctxt = canvas->rootContext();
200     ctxt->setContextProperty("testData", data);
201
202     canvas->setSource(testFileUrl("repeater1.qml"));
203     qApp->processEvents();
204
205     QQuickRepeater *repeater = findItem<QQuickRepeater>(canvas->rootObject(), "repeater");
206     QVERIFY(repeater != 0);
207
208     QQuickItem *container = findItem<QQuickItem>(canvas->rootObject(), "container");
209     QVERIFY(container != 0);
210
211     QCOMPARE(container->childItems().count(), data.count() + 3);
212
213     bool saw_repeater = false;
214     for (int i = 0; i < container->childItems().count(); ++i) {
215
216         if (i == 0) {
217             QQuickText *name = qobject_cast<QQuickText*>(container->childItems().at(i));
218             QVERIFY(name != 0);
219             QCOMPARE(name->text(), QLatin1String("Zero"));
220         } else if (i == container->childItems().count() - 2) {
221             // The repeater itself
222             QQuickRepeater *rep = qobject_cast<QQuickRepeater*>(container->childItems().at(i));
223             QCOMPARE(rep, repeater);
224             saw_repeater = true;
225             continue;
226         } else if (i == container->childItems().count() - 1) {
227             QQuickText *name = qobject_cast<QQuickText*>(container->childItems().at(i));
228             QVERIFY(name != 0);
229             QCOMPARE(name->text(), QLatin1String("Last"));
230         } else {
231             QQuickText *name = qobject_cast<QQuickText*>(container->childItems().at(i));
232             QVERIFY(name != 0);
233             QCOMPARE(name->text(), data.at(i-1));
234         }
235     }
236     QVERIFY(saw_repeater);
237
238     delete canvas;
239 }
240
241 void tst_QQuickRepeater::dataModel_adding()
242 {
243     QQuickView *canvas = createView();
244     QQmlContext *ctxt = canvas->rootContext();
245     TestObject *testObject = new TestObject;
246     ctxt->setContextProperty("testObject", testObject);
247
248     QaimModel testModel;
249     ctxt->setContextProperty("testData", &testModel);
250     canvas->setSource(testFileUrl("repeater2.qml"));
251     qApp->processEvents();
252
253     QQuickRepeater *repeater = findItem<QQuickRepeater>(canvas->rootObject(), "repeater");
254     QVERIFY(repeater != 0);
255     QQuickItem *container = findItem<QQuickItem>(canvas->rootObject(), "container");
256     QVERIFY(container != 0);
257
258     QVERIFY(!repeater->itemAt(0));
259
260     QSignalSpy countSpy(repeater, SIGNAL(countChanged()));
261     QSignalSpy addedSpy(repeater, SIGNAL(itemAdded(int,QQuickItem*)));
262
263     // add to empty model
264     testModel.addItem("two", "2");
265     QCOMPARE(repeater->itemAt(0), container->childItems().at(0));
266     QCOMPARE(countSpy.count(), 1); countSpy.clear();
267     QCOMPARE(addedSpy.count(), 1);
268     QCOMPARE(addedSpy.at(0).at(0).toInt(), 0);
269     QCOMPARE(addedSpy.at(0).at(1).value<QQuickItem*>(), container->childItems().at(0));
270     addedSpy.clear();
271
272     // insert at start
273     testModel.insertItem(0, "one", "1");
274     QCOMPARE(repeater->itemAt(0), container->childItems().at(0));
275     QCOMPARE(countSpy.count(), 1); countSpy.clear();
276     QCOMPARE(addedSpy.count(), 1);
277     QCOMPARE(addedSpy.at(0).at(0).toInt(), 0);
278     QCOMPARE(addedSpy.at(0).at(1).value<QQuickItem*>(), container->childItems().at(0));
279     addedSpy.clear();
280
281     // insert at end
282     testModel.insertItem(2, "four", "4");
283     QCOMPARE(repeater->itemAt(2), container->childItems().at(2));
284     QCOMPARE(countSpy.count(), 1); countSpy.clear();
285     QCOMPARE(addedSpy.count(), 1);
286     QCOMPARE(addedSpy.at(0).at(0).toInt(), 2);
287     QCOMPARE(addedSpy.at(0).at(1).value<QQuickItem*>(), container->childItems().at(2));
288     addedSpy.clear();
289
290     // insert in middle
291     testModel.insertItem(2, "three", "3");
292     QCOMPARE(repeater->itemAt(2), container->childItems().at(2));
293     QCOMPARE(countSpy.count(), 1); countSpy.clear();
294     QCOMPARE(addedSpy.count(), 1);
295     QCOMPARE(addedSpy.at(0).at(0).toInt(), 2);
296     QCOMPARE(addedSpy.at(0).at(1).value<QQuickItem*>(), container->childItems().at(2));
297     addedSpy.clear();
298
299     delete testObject;
300     addedSpy.clear();
301     countSpy.clear();
302     delete canvas;
303 }
304
305 void tst_QQuickRepeater::dataModel_removing()
306 {
307     QQuickView *canvas = createView();
308     QQmlContext *ctxt = canvas->rootContext();
309     TestObject *testObject = new TestObject;
310     ctxt->setContextProperty("testObject", testObject);
311
312     QaimModel testModel;
313     testModel.addItem("one", "1");
314     testModel.addItem("two", "2");
315     testModel.addItem("three", "3");
316     testModel.addItem("four", "4");
317     testModel.addItem("five", "5");
318
319     ctxt->setContextProperty("testData", &testModel);
320     canvas->setSource(testFileUrl("repeater2.qml"));
321     qApp->processEvents();
322
323     QQuickRepeater *repeater = findItem<QQuickRepeater>(canvas->rootObject(), "repeater");
324     QVERIFY(repeater != 0);
325     QQuickItem *container = findItem<QQuickItem>(canvas->rootObject(), "container");
326     QVERIFY(container != 0);
327     QCOMPARE(container->childItems().count(), repeater->count()+1);
328
329     QSignalSpy countSpy(repeater, SIGNAL(countChanged()));
330     QSignalSpy removedSpy(repeater, SIGNAL(itemRemoved(int,QQuickItem*)));
331
332     // remove at start
333     QQuickItem *item = repeater->itemAt(0);
334     QCOMPARE(item, container->childItems().at(0));
335
336     testModel.removeItem(0);
337     QVERIFY(repeater->itemAt(0) != item);
338     QCOMPARE(countSpy.count(), 1); countSpy.clear();
339     QCOMPARE(removedSpy.count(), 1);
340     QCOMPARE(removedSpy.at(0).at(0).toInt(), 0);
341     QCOMPARE(removedSpy.at(0).at(1).value<QQuickItem*>(), item);
342     removedSpy.clear();
343
344     // remove at end
345     int lastIndex = testModel.count()-1;
346     item = repeater->itemAt(lastIndex);
347     QCOMPARE(item, container->childItems().at(lastIndex));
348
349     testModel.removeItem(lastIndex);
350     QVERIFY(repeater->itemAt(lastIndex) != item);
351     QCOMPARE(countSpy.count(), 1); countSpy.clear();
352     QCOMPARE(removedSpy.count(), 1);
353     QCOMPARE(removedSpy.at(0).at(0).toInt(), lastIndex);
354     QCOMPARE(removedSpy.at(0).at(1).value<QQuickItem*>(), item);
355     removedSpy.clear();
356
357     // remove from middle
358     item = repeater->itemAt(1);
359     QCOMPARE(item, container->childItems().at(1));
360
361     testModel.removeItem(1);
362     QVERIFY(repeater->itemAt(lastIndex) != item);
363     QCOMPARE(countSpy.count(), 1); countSpy.clear();
364     QCOMPARE(removedSpy.count(), 1);
365     QCOMPARE(removedSpy.at(0).at(0).toInt(), 1);
366     QCOMPARE(removedSpy.at(0).at(1).value<QQuickItem*>(), item);
367     removedSpy.clear();
368
369     delete testObject;
370     delete canvas;
371 }
372
373 void tst_QQuickRepeater::dataModel_changes()
374 {
375     QQuickView *canvas = createView();
376     QQmlContext *ctxt = canvas->rootContext();
377     TestObject *testObject = new TestObject;
378     ctxt->setContextProperty("testObject", testObject);
379
380     QaimModel testModel;
381     testModel.addItem("one", "1");
382     testModel.addItem("two", "2");
383     testModel.addItem("three", "3");
384
385     ctxt->setContextProperty("testData", &testModel);
386     canvas->setSource(testFileUrl("repeater2.qml"));
387     qApp->processEvents();
388
389     QQuickRepeater *repeater = findItem<QQuickRepeater>(canvas->rootObject(), "repeater");
390     QVERIFY(repeater != 0);
391     QQuickItem *container = findItem<QQuickItem>(canvas->rootObject(), "container");
392     QVERIFY(container != 0);
393     QCOMPARE(container->childItems().count(), repeater->count()+1);
394
395     // Check that model changes are propagated
396     QQuickText *text = findItem<QQuickText>(canvas->rootObject(), "myName", 1);
397     QVERIFY(text);
398     QCOMPARE(text->text(), QString("two"));
399
400     testModel.modifyItem(1, "Item two", "_2");
401     text = findItem<QQuickText>(canvas->rootObject(), "myName", 1);
402     QVERIFY(text);
403     QCOMPARE(text->text(), QString("Item two"));
404
405     text = findItem<QQuickText>(canvas->rootObject(), "myNumber", 1);
406     QVERIFY(text);
407     QCOMPARE(text->text(), QString("_2"));
408
409     delete testObject;
410     delete canvas;
411 }
412
413 void tst_QQuickRepeater::itemModel()
414 {
415     QQuickView *canvas = createView();
416     QQmlContext *ctxt = canvas->rootContext();
417     TestObject *testObject = new TestObject;
418     ctxt->setContextProperty("testObject", testObject);
419
420     canvas->setSource(testFileUrl("itemlist.qml"));
421     qApp->processEvents();
422
423     QQuickRepeater *repeater = findItem<QQuickRepeater>(canvas->rootObject(), "repeater");
424     QVERIFY(repeater != 0);
425
426     QQuickItem *container = findItem<QQuickItem>(canvas->rootObject(), "container");
427     QVERIFY(container != 0);
428
429     QCOMPARE(container->childItems().count(), 1);
430
431     testObject->setUseModel(true);
432     QMetaObject::invokeMethod(canvas->rootObject(), "checkProperties");
433     QVERIFY(testObject->error() == false);
434
435     QCOMPARE(container->childItems().count(), 4);
436     QVERIFY(qobject_cast<QObject*>(container->childItems().at(0))->objectName() == "item1");
437     QVERIFY(qobject_cast<QObject*>(container->childItems().at(1))->objectName() == "item2");
438     QVERIFY(qobject_cast<QObject*>(container->childItems().at(2))->objectName() == "item3");
439     QVERIFY(container->childItems().at(3) == repeater);
440
441     QMetaObject::invokeMethod(canvas->rootObject(), "switchModel");
442     QCOMPARE(container->childItems().count(), 3);
443     QVERIFY(qobject_cast<QObject*>(container->childItems().at(0))->objectName() == "item4");
444     QVERIFY(qobject_cast<QObject*>(container->childItems().at(1))->objectName() == "item5");
445     QVERIFY(container->childItems().at(2) == repeater);
446
447     testObject->setUseModel(false);
448     QCOMPARE(container->childItems().count(), 1);
449
450     delete testObject;
451     delete canvas;
452 }
453
454 void tst_QQuickRepeater::resetModel()
455 {
456     QQuickView *canvas = createView();
457
458     QStringList dataA;
459     for (int i=0; i<10; i++)
460         dataA << QString::number(i);
461
462     QQmlContext *ctxt = canvas->rootContext();
463     ctxt->setContextProperty("testData", dataA);
464     canvas->setSource(testFileUrl("repeater1.qml"));
465     qApp->processEvents();
466     QQuickRepeater *repeater = findItem<QQuickRepeater>(canvas->rootObject(), "repeater");
467     QVERIFY(repeater != 0);
468     QQuickItem *container = findItem<QQuickItem>(canvas->rootObject(), "container");
469     QVERIFY(container != 0);
470
471     QCOMPARE(repeater->count(), dataA.count());
472     for (int i=0; i<repeater->count(); i++)
473         QCOMPARE(repeater->itemAt(i), container->childItems().at(i+1)); // +1 to skip first Text object
474
475     QSignalSpy modelChangedSpy(repeater, SIGNAL(modelChanged()));
476     QSignalSpy countSpy(repeater, SIGNAL(countChanged()));
477     QSignalSpy addedSpy(repeater, SIGNAL(itemAdded(int,QQuickItem*)));
478     QSignalSpy removedSpy(repeater, SIGNAL(itemRemoved(int,QQuickItem*)));
479
480     QStringList dataB;
481     for (int i=0; i<20; i++)
482         dataB << QString::number(i);
483
484     // reset context property
485     ctxt->setContextProperty("testData", dataB);
486     QCOMPARE(repeater->count(), dataB.count());
487
488     QCOMPARE(modelChangedSpy.count(), 1);
489     QCOMPARE(countSpy.count(), 1);
490     QCOMPARE(removedSpy.count(), dataA.count());
491     QCOMPARE(addedSpy.count(), dataB.count());
492     for (int i=0; i<dataB.count(); i++) {
493         QCOMPARE(addedSpy.at(i).at(0).toInt(), i);
494         QCOMPARE(addedSpy.at(i).at(1).value<QQuickItem*>(), repeater->itemAt(i));
495     }
496     modelChangedSpy.clear();
497     countSpy.clear();
498     removedSpy.clear();
499     addedSpy.clear();
500
501     // reset via setModel()
502     repeater->setModel(dataA);
503     QCOMPARE(repeater->count(), dataA.count());
504
505     QCOMPARE(modelChangedSpy.count(), 1);
506     QCOMPARE(countSpy.count(), 1);
507     QCOMPARE(removedSpy.count(), dataB.count());
508     QCOMPARE(addedSpy.count(), dataA.count());
509     for (int i=0; i<dataA.count(); i++) {
510         QCOMPARE(addedSpy.at(i).at(0).toInt(), i);
511         QCOMPARE(addedSpy.at(i).at(1).value<QQuickItem*>(), repeater->itemAt(i));
512     }
513
514     modelChangedSpy.clear();
515     countSpy.clear();
516     removedSpy.clear();
517     addedSpy.clear();
518
519     delete canvas;
520 }
521
522 // QTBUG-17156
523 void tst_QQuickRepeater::modelChanged()
524 {
525     QQmlEngine engine;
526     QQmlComponent component(&engine, testFileUrl("modelChanged.qml"));
527
528     QQuickItem *rootObject = qobject_cast<QQuickItem*>(component.create());
529     QVERIFY(rootObject);
530     QQuickRepeater *repeater = findItem<QQuickRepeater>(rootObject, "repeater");
531     QVERIFY(repeater);
532
533     repeater->setModel(4);
534     QCOMPARE(repeater->count(), 4);
535     QCOMPARE(repeater->property("itemsCount").toInt(), 4);
536     QCOMPARE(repeater->property("itemsFound").toList().count(), 4);
537
538     repeater->setModel(10);
539     QCOMPARE(repeater->count(), 10);
540     QCOMPARE(repeater->property("itemsCount").toInt(), 10);
541     QCOMPARE(repeater->property("itemsFound").toList().count(), 10);
542
543     delete rootObject;
544 }
545
546 void tst_QQuickRepeater::properties()
547 {
548     QQmlEngine engine;
549     QQmlComponent component(&engine, testFileUrl("properties.qml"));
550
551     QQuickItem *rootObject = qobject_cast<QQuickItem*>(component.create());
552     QVERIFY(rootObject);
553
554     QQuickRepeater *repeater = findItem<QQuickRepeater>(rootObject, "repeater");
555     QVERIFY(repeater);
556
557     QSignalSpy modelSpy(repeater, SIGNAL(modelChanged()));
558     repeater->setModel(3);
559     QCOMPARE(modelSpy.count(),1);
560     repeater->setModel(3);
561     QCOMPARE(modelSpy.count(),1);
562
563     QSignalSpy delegateSpy(repeater, SIGNAL(delegateChanged()));
564
565     QQmlComponent rectComponent(&engine);
566     rectComponent.setData("import QtQuick 2.0; Rectangle {}", QUrl::fromLocalFile(""));
567
568     repeater->setDelegate(&rectComponent);
569     QCOMPARE(delegateSpy.count(),1);
570     repeater->setDelegate(&rectComponent);
571     QCOMPARE(delegateSpy.count(),1);
572
573     delete rootObject;
574 }
575
576 void tst_QQuickRepeater::asynchronous()
577 {
578     QQuickView *canvas = createView();
579     canvas->show();
580     QQmlIncubationController controller;
581     canvas->engine()->setIncubationController(&controller);
582
583     canvas->setSource(testFileUrl("asyncloader.qml"));
584
585     QQuickItem *rootObject = qobject_cast<QQuickItem*>(canvas->rootObject());
586     QVERIFY(rootObject);
587
588     QQuickItem *container = findItem<QQuickItem>(rootObject, "container");
589     QVERIFY(!container);
590     while (!container) {
591         bool b = false;
592         controller.incubateWhile(&b);
593         container = findItem<QQuickItem>(rootObject, "container");
594     }
595
596     QQuickRepeater *repeater = 0;
597     while (!repeater) {
598         bool b = false;
599         controller.incubateWhile(&b);
600         repeater = findItem<QQuickRepeater>(rootObject, "repeater");
601     }
602
603     // items will be created one at a time
604     for (int i = 0; i < 10; ++i) {
605         QString name("delegate");
606         name += QString::number(i);
607         QVERIFY(findItem<QQuickItem>(container, name) == 0);
608         QQuickItem *item = 0;
609         while (!item) {
610             bool b = false;
611             controller.incubateWhile(&b);
612             item = findItem<QQuickItem>(container, name);
613         }
614     }
615
616     {
617         bool b = true;
618         controller.incubateWhile(&b);
619     }
620
621     // verify positioning
622     for (int i = 0; i < 10; ++i) {
623         QString name("delegate");
624         name += QString::number(i);
625         QQuickItem *item = findItem<QQuickItem>(container, name);
626         QTRY_COMPARE(item->y(), i * 50.0);
627     }
628
629     delete canvas;
630 }
631
632 void tst_QQuickRepeater::initParent()
633 {
634     QQmlEngine engine;
635     QQmlComponent component(&engine, testFileUrl("initparent.qml"));
636
637     QQuickItem *rootObject = qobject_cast<QQuickItem*>(component.create());
638     QVERIFY(rootObject);
639
640     QCOMPARE(qvariant_cast<QQuickItem*>(rootObject->property("parentItem")), rootObject);
641 }
642
643 void tst_QQuickRepeater::dynamicModelCrash()
644 {
645     QQmlEngine engine;
646     QQmlComponent component(&engine, testFileUrl("dynamicmodelcrash.qml"));
647
648     // Don't crash
649     QQuickItem *rootObject = qobject_cast<QQuickItem*>(component.create());
650     QVERIFY(rootObject);
651
652     QQuickRepeater *repeater = findItem<QQuickRepeater>(rootObject, "rep");
653     QVERIFY(repeater);
654     QVERIFY(qvariant_cast<QObject *>(repeater->model()) == 0);
655 }
656
657 QTEST_MAIN(tst_QQuickRepeater)
658
659 #include "tst_qquickrepeater.moc"