1 /****************************************************************************
2 **
3 ** Copyright (C) 2020 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of Qt Creator.
7 **
8 ** Commercial License Usage
9 ** Licensees holding valid commercial Qt licenses may use this file in
10 ** accordance with the commercial license agreement provided with the
11 ** Software or, alternatively, in accordance with the terms contained in
12 ** a written agreement between you and The Qt Company. For licensing terms
13 ** and conditions see https://www.qt.io/terms-conditions. For further
14 ** information use the contact form at https://www.qt.io/contact-us.
15 **
16 ** GNU General Public License Usage
17 ** Alternatively, this file may be used under the terms of the GNU
18 ** General Public License version 3 as published by the Free Software
19 ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
20 ** included in the packaging of this file. Please review the following
21 ** information to ensure the GNU General Public License requirements will
22 ** be met: https://www.gnu.org/licenses/gpl-3.0.html.
23 **
24 ****************************************************************************/
25 
26 #pragma once
27 
28 #include "googletest.h"
29 
30 #include "mocklistmodeleditorview.h"
31 
32 #include <qmldesigner/components/listmodeleditor/listmodeleditormodel.h>
33 #include <qmldesigner/designercore/include/abstractview.h>
34 #include <qmldesigner/designercore/include/bindingproperty.h>
35 #include <qmldesigner/designercore/include/model.h>
36 #include <qmldesigner/designercore/include/nodelistproperty.h>
37 #include <qmldesigner/designercore/include/nodeproperty.h>
38 #include <qmldesigner/designercore/include/variantproperty.h>
39 
40 namespace {
41 
42 using QmlDesigner::AbstractProperty;
43 using QmlDesigner::AbstractView;
44 using QmlDesigner::ListModelEditorModel;
45 using QmlDesigner::ModelNode;
46 
47 MATCHER_P2(HasItem,
48            name,
49            value,
50            std::string(negation ? "hasn't " : "has ") + "(" + name + ", " + value + ")")
51 {
52     QStandardItem *item = arg;
53 
54     return item->data(Qt::UserRole).toString() == name && item->data(Qt::UserRole).toDouble() == value;
55 }
56 
57 MATCHER(IsInvalid, std::string(negation ? "isn't null" : "is null"))
58 {
59     return !arg.isValid();
60 }
61 
62 MATCHER_P3(IsVariantProperty,
63            node,
64            name,
65            value,
66            std::string(negation ? "isn't " : "is ") + "(" + name + ", " + PrintToString(value) + ")")
67 {
68     const QmlDesigner::VariantProperty &property = arg;
69 
70     return property.parentModelNode() == node && property.name() == name && property.value() == value;
71 }
72 
73 MATCHER_P2(IsVariantProperty,
74            name,
75            value,
76            std::string(negation ? "isn't " : "is ") + "(" + name + ", " + PrintToString(value) + ")")
77 {
78     const QmlDesigner::VariantProperty &property = arg;
79 
80     return property.name() == name && property.value() == value;
81 }
82 
83 MATCHER_P2(IsAbstractProperty, node, name, std::string(negation ? "isn't " : "is ") + "(" + name + ")")
84 {
85     const QmlDesigner::AbstractProperty &property = arg;
86 
87     return property.parentModelNode() == node && property.name() == name;
88 }
89 
90 class ListModelEditor : public testing::Test
91 {
92 public:
ListModelEditor()93     ListModelEditor()
94     {
95         designerModel->attachView(&mockView);
96 
97         emptyListModelNode = mockView.createModelNode("QtQml.Models.ListModel", 2, 15);
98 
99         listViewNode = mockView.createModelNode("QtQuick.ListView", 2, 15);
100         listModelNode = mockView.createModelNode("QtQml.Models.ListModel", 2, 15);
101         mockView.rootModelNode().defaultNodeListProperty().reparentHere(listModelNode);
102         element1 = createElement({{"name", "foo"}, {"value", 1}, {"value2", 42}},
103                                  mockView,
104                                  listModelNode);
105         element2 = createElement({{"value", 4}, {"name", "bar"}, {"image", "pic.png"}},
106                                  mockView,
107                                  listModelNode);
108         element3 = createElement({{"image", "pic.png"}, {"name", "poo"}, {"value", 111}},
109                                  mockView,
110                                  listModelNode);
111 
112         componentModel->attachView(&mockComponentView);
113 
114         componentElement = createElement({{"name", "com"}, {"value", 11}, {"value2", 55}},
115                                          mockComponentView,
116                                          mockComponentView.rootModelNode());
117 
118         ON_CALL(mockGoIntoComponent, Call(_)).WillByDefault([](ModelNode node) { return node; });
119     }
120 
121     using Entry = std::pair<QmlDesigner::PropertyName, QVariant>;
122 
createElement(std::initializer_list<Entry> entries,AbstractView & view,ModelNode listModel)123     ModelNode createElement(std::initializer_list<Entry> entries, AbstractView &view, ModelNode listModel)
124     {
125         auto element = view.createModelNode("QtQml.Models/ListElement", 2, 15);
126         listModel.defaultNodeListProperty().reparentHere(element);
127 
128         for (const auto &entry : entries) {
129             element.variantProperty(entry.first).setValue(entry.second);
130         }
131 
132         return element;
133     }
134 
headerLabels(const QmlDesigner::ListModelEditorModel & model) const135     QList<QString> headerLabels(const QmlDesigner::ListModelEditorModel &model) const
136     {
137         QList<QString> labels;
138         labels.reserve(model.columnCount());
139 
140         for (int i = 0; i < model.columnCount(); ++i)
141             labels.push_back(model.headerData(i, Qt::Horizontal).toString());
142 
143         return labels;
144     }
145 
displayValues() const146     QList<QList<QVariant>> displayValues() const
147     {
148         QList<QList<QVariant>> rows;
149 
150         for (int rowIndex = 0; rowIndex < model.rowCount(); ++rowIndex) {
151             QList<QVariant> row;
152 
153             for (int columnIndex = 0; columnIndex < model.columnCount(); ++columnIndex)
154                 row.push_back(model.data(model.index(rowIndex, columnIndex), Qt::DisplayRole));
155 
156             rows.push_back(row);
157         }
158 
159         return rows;
160     }
161 
backgroundColors() const162     QList<QList<QColor>> backgroundColors() const
163     {
164         QList<QList<QColor>> rows;
165 
166         for (int rowIndex = 0; rowIndex < model.rowCount(); ++rowIndex) {
167             QList<QColor> row;
168 
169             for (int columnIndex = 0; columnIndex < model.columnCount(); ++columnIndex)
170                 row.push_back(
171                     model.data(model.index(rowIndex, columnIndex), Qt::BackgroundRole)
172                         .value<QColor>());
173 
174             rows.push_back(row);
175         }
176 
177         return rows;
178     }
179 
properties() const180     QList<QList<QmlDesigner::VariantProperty>> properties() const
181     {
182         QList<QList<QmlDesigner::VariantProperty>> properties;
183         properties.reserve(10);
184 
185         auto nodes = listModelNode.defaultNodeListProperty().toModelNodeList();
186 
187         for (const ModelNode &node : nodes)
188             properties.push_back(node.variantProperties());
189 
190         return properties;
191     }
192 
index(int row,int column) const193     QModelIndex index(int row, int column) const { return model.index(row, column); }
194 
elements(const ModelNode & node) const195     QList<ModelNode> elements(const ModelNode &node) const
196     {
197         return node.defaultNodeListProperty().toModelNodeList();
198     }
199 
200 protected:
201     MockFunction<ModelNode(const ModelNode &)> mockGoIntoComponent;
202     std::unique_ptr<QmlDesigner::Model> designerModel{QmlDesigner::Model::create("QtQuick.Item", 1, 1)};
203     NiceMock<MockListModelEditorView> mockView;
204     QmlDesigner::ListModelEditorModel model{
__anon894792960302null205         [&] { return mockView.createModelNode("QtQml.Models.ListModel", 2, 15); },
__anon894792960402null206         [&] { return mockView.createModelNode("QtQml.Models.ListElement", 2, 15); },
207         mockGoIntoComponent.AsStdFunction()};
208     ModelNode listViewNode;
209     ModelNode listModelNode;
210     ModelNode emptyListModelNode;
211     ModelNode element1;
212     ModelNode element2;
213     ModelNode element3;
214     std::unique_ptr<QmlDesigner::Model> componentModel{
215         QmlDesigner::Model::create("QtQml.Models.ListModel", 1, 1)};
216     NiceMock<MockListModelEditorView> mockComponentView;
217     ModelNode componentElement;
218 };
219 
TEST_F(ListModelEditor,CreatePropertyNameSet)220 TEST_F(ListModelEditor, CreatePropertyNameSet)
221 {
222     model.setListModel(listModelNode);
223 
224     ASSERT_THAT(model.propertyNames(), ElementsAre("image", "name", "value", "value2"));
225 }
226 
TEST_F(ListModelEditor,CreatePropertyNameSetForEmptyList)227 TEST_F(ListModelEditor, CreatePropertyNameSetForEmptyList)
228 {
229     model.setListModel(emptyListModelNode);
230 
231     ASSERT_THAT(model.propertyNames(), IsEmpty());
232 }
233 
TEST_F(ListModelEditor,HorizontalLabels)234 TEST_F(ListModelEditor, HorizontalLabels)
235 {
236     model.setListModel(listModelNode);
237 
238     ASSERT_THAT(headerLabels(model), ElementsAre("image", "name", "value", "value2"));
239 }
240 
TEST_F(ListModelEditor,HorizontalLabelsForEmptyList)241 TEST_F(ListModelEditor, HorizontalLabelsForEmptyList)
242 {
243     model.setListModel(emptyListModelNode);
244 
245     ASSERT_THAT(headerLabels(model), IsEmpty());
246 }
247 
TEST_F(ListModelEditor,DisplayValues)248 TEST_F(ListModelEditor, DisplayValues)
249 {
250     model.setListModel(listModelNode);
251 
252     ASSERT_THAT(displayValues(),
253                 ElementsAre(ElementsAre(IsInvalid(), "foo", 1, 42),
254                             ElementsAre("pic.png", "bar", 4, IsInvalid()),
255                             ElementsAre("pic.png", "poo", 111, IsInvalid())));
256 }
257 
TEST_F(ListModelEditor,ChangeValueChangesDisplayValues)258 TEST_F(ListModelEditor, ChangeValueChangesDisplayValues)
259 {
260     model.setListModel(listModelNode);
261 
262     model.setValue(0, 1, "hello");
263 
264     ASSERT_THAT(displayValues(),
265                 ElementsAre(ElementsAre(IsInvalid(), "hello", 1, 42),
266                             ElementsAre("pic.png", "bar", 4, IsInvalid()),
267                             ElementsAre("pic.png", "poo", 111, IsInvalid())));
268 }
269 
TEST_F(ListModelEditor,EditValueCallVariantPropertiesChanged)270 TEST_F(ListModelEditor, EditValueCallVariantPropertiesChanged)
271 {
272     model.setListModel(listModelNode);
273 
274     EXPECT_CALL(mockView,
275                 variantPropertiesChanged(ElementsAre(IsVariantProperty(element1, "name", "hello")),
276                                          Eq(AbstractView::NoAdditionalChanges)));
277 
278     model.setValue(0, 1, "hello");
279 }
280 
TEST_F(ListModelEditor,ChangeDisplayValueCallsVariantPropertiesChanged)281 TEST_F(ListModelEditor, ChangeDisplayValueCallsVariantPropertiesChanged)
282 {
283     model.setListModel(listModelNode);
284 
285     EXPECT_CALL(mockView,
286                 variantPropertiesChanged(ElementsAre(IsVariantProperty(element1, "name", "hello")),
287                                          Eq(AbstractView::NoAdditionalChanges)))
288         .Times(0);
289 
290     model.setValue(0, 1, "hello", Qt::DisplayRole);
291 }
292 
TEST_F(ListModelEditor,AddRowAddedInvalidRow)293 TEST_F(ListModelEditor, AddRowAddedInvalidRow)
294 {
295     model.setListModel(listModelNode);
296 
297     model.addRow();
298 
299     ASSERT_THAT(displayValues(),
300                 ElementsAre(ElementsAre(IsInvalid(), "foo", 1, 42),
301                             ElementsAre("pic.png", "bar", 4, IsInvalid()),
302                             ElementsAre("pic.png", "poo", 111, IsInvalid()),
303                             ElementsAre(IsInvalid(), IsInvalid(), IsInvalid(), IsInvalid())));
304 }
305 
TEST_F(ListModelEditor,AddRowCreatesNewModelNodeAndReparents)306 TEST_F(ListModelEditor, AddRowCreatesNewModelNodeAndReparents)
307 {
308     model.setListModel(listModelNode);
309 
310     EXPECT_CALL(mockView, nodeCreated(Property(&ModelNode::type, Eq("QtQml.Models.ListElement"))));
311     EXPECT_CALL(mockView,
312                 nodeReparented(Property(&ModelNode::type, Eq("QtQml.Models.ListElement")),
313                                Property(&AbstractProperty::parentModelNode, Eq(listModelNode)),
314                                _,
315                                _));
316 
317     model.addRow();
318 }
319 
TEST_F(ListModelEditor,ChangeAddedRowPropery)320 TEST_F(ListModelEditor, ChangeAddedRowPropery)
321 {
322     model.setListModel(listModelNode);
323     model.addRow();
324 
325     model.setValue(3, 2, 22);
326 
327     ASSERT_THAT(displayValues(),
328                 ElementsAre(ElementsAre(IsInvalid(), "foo", 1, 42),
329                             ElementsAre("pic.png", "bar", 4, IsInvalid()),
330                             ElementsAre("pic.png", "poo", 111, IsInvalid()),
331                             ElementsAre(IsInvalid(), IsInvalid(), 22, IsInvalid())));
332 }
333 
TEST_F(ListModelEditor,ChangeAddedRowProperyCallsVariantPropertiesChanged)334 TEST_F(ListModelEditor, ChangeAddedRowProperyCallsVariantPropertiesChanged)
335 {
336     model.setListModel(listModelNode);
337     ModelNode element4;
338     ON_CALL(mockView, nodeReparented(_, _, _, _)).WillByDefault(SaveArg<0>(&element4));
339     model.addRow();
340 
341     EXPECT_CALL(mockView,
342                 variantPropertiesChanged(ElementsAre(IsVariantProperty(element4, "value", 22)),
343                                          Eq(AbstractView::PropertiesAdded)));
344 
345     model.setValue(3, 2, 22);
346 }
347 
TEST_F(ListModelEditor,AddColumnInsertsPropertyName)348 TEST_F(ListModelEditor, AddColumnInsertsPropertyName)
349 {
350     model.setListModel(listModelNode);
351 
352     model.addColumn("other");
353 
354     ASSERT_THAT(model.propertyNames(), ElementsAre("image", "name", "other", "value", "value2"));
355 }
356 
TEST_F(ListModelEditor,AddColumnInsertsPropertyNameToEmptyModel)357 TEST_F(ListModelEditor, AddColumnInsertsPropertyNameToEmptyModel)
358 {
359     model.setListModel(emptyListModelNode);
360 
361     model.addColumn("foo");
362 
363     ASSERT_THAT(model.propertyNames(), ElementsAre("foo"));
364 }
365 
TEST_F(ListModelEditor,AddTwiceColumnInsertsPropertyNameToEmptyModel)366 TEST_F(ListModelEditor, AddTwiceColumnInsertsPropertyNameToEmptyModel)
367 {
368     model.setListModel(emptyListModelNode);
369     model.addColumn("foo");
370 
371     model.addColumn("foo2");
372 
373     ASSERT_THAT(model.propertyNames(), ElementsAre("foo", "foo2"));
374 }
375 
TEST_F(ListModelEditor,AddSameColumnInsertsPropertyName)376 TEST_F(ListModelEditor, AddSameColumnInsertsPropertyName)
377 {
378     model.setListModel(emptyListModelNode);
379     model.addColumn("foo");
380 
381     model.addColumn("foo");
382 
383     ASSERT_THAT(model.propertyNames(), ElementsAre("foo"));
384 }
385 
TEST_F(ListModelEditor,AddColumnInsertsHeaderLabel)386 TEST_F(ListModelEditor, AddColumnInsertsHeaderLabel)
387 {
388     model.setListModel(listModelNode);
389 
390     model.addColumn("other");
391 
392     ASSERT_THAT(headerLabels(model), ElementsAre("image", "name", "other", "value", "value2"));
393 }
394 
TEST_F(ListModelEditor,AddColumnInsertsHeaderLabelToEmptyModel)395 TEST_F(ListModelEditor, AddColumnInsertsHeaderLabelToEmptyModel)
396 {
397     model.setListModel(emptyListModelNode);
398 
399     model.addColumn("foo");
400 
401     ASSERT_THAT(headerLabels(model), ElementsAre("foo"));
402 }
403 
TEST_F(ListModelEditor,AddTwiceColumnInsertsHeaderLabelToEmptyModel)404 TEST_F(ListModelEditor, AddTwiceColumnInsertsHeaderLabelToEmptyModel)
405 {
406     model.setListModel(emptyListModelNode);
407     model.addColumn("foo");
408 
409     model.addColumn("foo2");
410 
411     ASSERT_THAT(headerLabels(model), ElementsAre("foo", "foo2"));
412 }
413 
TEST_F(ListModelEditor,AddSameColumnInsertsHeaderLabel)414 TEST_F(ListModelEditor, AddSameColumnInsertsHeaderLabel)
415 {
416     model.setListModel(emptyListModelNode);
417     model.addColumn("foo");
418 
419     model.addColumn("foo");
420 
421     ASSERT_THAT(headerLabels(model), ElementsAre("foo"));
422 }
423 
TEST_F(ListModelEditor,AddColumnInsertsDisplayValues)424 TEST_F(ListModelEditor, AddColumnInsertsDisplayValues)
425 {
426     model.setListModel(listModelNode);
427 
428     model.addColumn("other");
429 
430     ASSERT_THAT(displayValues(),
431                 ElementsAre(ElementsAre(IsInvalid(), "foo", IsInvalid(), 1, 42),
432                             ElementsAre("pic.png", "bar", IsInvalid(), 4, IsInvalid()),
433                             ElementsAre("pic.png", "poo", IsInvalid(), 111, IsInvalid())));
434 }
435 
TEST_F(ListModelEditor,ChangeAddColumnPropertyDisplayValue)436 TEST_F(ListModelEditor, ChangeAddColumnPropertyDisplayValue)
437 {
438     model.setListModel(listModelNode);
439     model.addColumn("other");
440 
441     model.setValue(1, 2, 22);
442 
443     ASSERT_THAT(displayValues(),
444                 ElementsAre(ElementsAre(IsInvalid(), "foo", IsInvalid(), 1, 42),
445                             ElementsAre("pic.png", "bar", 22, 4, IsInvalid()),
446                             ElementsAre("pic.png", "poo", IsInvalid(), 111, IsInvalid())));
447 }
448 
TEST_F(ListModelEditor,ChangeAddColumnPropertyCallsVariantPropertiesChanged)449 TEST_F(ListModelEditor, ChangeAddColumnPropertyCallsVariantPropertiesChanged)
450 {
451     model.setListModel(listModelNode);
452     model.addColumn("other");
453 
454     EXPECT_CALL(mockView,
455                 variantPropertiesChanged(ElementsAre(IsVariantProperty(element2, "other", 434)), _));
456 
457     model.setValue(1, 2, 434);
458 }
459 
TEST_F(ListModelEditor,RemoveColumnRemovesDisplayValues)460 TEST_F(ListModelEditor, RemoveColumnRemovesDisplayValues)
461 {
462     model.setListModel(listModelNode);
463 
464     model.removeColumns({index(0, 2)});
465 
466     ASSERT_THAT(displayValues(),
467                 ElementsAre(ElementsAre(IsInvalid(), "foo", 42),
468                             ElementsAre("pic.png", "bar", IsInvalid()),
469                             ElementsAre("pic.png", "poo", IsInvalid())));
470 }
471 
TEST_F(ListModelEditor,RemoveColumnRemovesProperties)472 TEST_F(ListModelEditor, RemoveColumnRemovesProperties)
473 {
474     model.setListModel(listModelNode);
475 
476     EXPECT_CALL(mockView, propertiesRemoved(ElementsAre(IsAbstractProperty(element2, "image"))));
477     EXPECT_CALL(mockView, propertiesRemoved(ElementsAre(IsAbstractProperty(element3, "image"))));
478 
479     model.removeColumns({index(0, 0)});
480 }
481 
TEST_F(ListModelEditor,RemoveColumnRemovesPropertyName)482 TEST_F(ListModelEditor, RemoveColumnRemovesPropertyName)
483 {
484     model.setListModel(listModelNode);
485 
486     model.removeColumns({index(0, 1)});
487 
488     ASSERT_THAT(model.propertyNames(), ElementsAre("image", "value", "value2"));
489 }
490 
TEST_F(ListModelEditor,RemoveRowRemovesDisplayValues)491 TEST_F(ListModelEditor, RemoveRowRemovesDisplayValues)
492 {
493     model.setListModel(listModelNode);
494 
495     model.removeRows({index(1, 0)});
496 
497     ASSERT_THAT(displayValues(),
498                 ElementsAre(ElementsAre(IsInvalid(), "foo", 1, 42),
499                             ElementsAre("pic.png", "poo", 111, IsInvalid())));
500 }
501 
TEST_F(ListModelEditor,RemoveRowRemovesElementInListModel)502 TEST_F(ListModelEditor, RemoveRowRemovesElementInListModel)
503 {
504     model.setListModel(listModelNode);
505 
506     EXPECT_CALL(mockView, nodeRemoved(Eq(element2), _, _));
507 
508     model.removeRows({index(1, 0)});
509 }
510 
TEST_F(ListModelEditor,ConvertStringFloatToFloat)511 TEST_F(ListModelEditor, ConvertStringFloatToFloat)
512 {
513     model.setListModel(listModelNode);
514 
515     model.setValue(1, 1, "25.5");
516 
517     ASSERT_THAT(element2.variantProperty("name").value().value<double>(), 25.5);
518     ASSERT_THAT(element2.variantProperty("name").value().type(), QVariant::Double);
519 }
520 
TEST_F(ListModelEditor,ConvertStringIntegerToDouble)521 TEST_F(ListModelEditor, ConvertStringIntegerToDouble)
522 {
523     model.setListModel(listModelNode);
524 
525     model.setValue(1, 1, "25");
526 
527     ASSERT_THAT(element2.variantProperty("name").value().value<double>(), 25);
528     ASSERT_THAT(element2.variantProperty("name").value().type(), QVariant::Double);
529 }
530 
TEST_F(ListModelEditor,DontConvertStringToNumber)531 TEST_F(ListModelEditor, DontConvertStringToNumber)
532 {
533     model.setListModel(listModelNode);
534 
535     model.setValue(1, 1, "hello");
536 
537     ASSERT_THAT(element2.variantProperty("name").value().value<QString>(), "hello");
538     ASSERT_THAT(element2.variantProperty("name").value().type(), QVariant::String);
539 }
540 
TEST_F(ListModelEditor,EmptyStringsRemovesProperty)541 TEST_F(ListModelEditor, EmptyStringsRemovesProperty)
542 {
543     model.setListModel(listModelNode);
544 
545     model.setValue(1, 1, "");
546 
547     ASSERT_THAT(element2.variantProperty("name").value().value<QString>(), Eq(""));
548 }
549 
TEST_F(ListModelEditor,InvalidVariantRemovesProperty)550 TEST_F(ListModelEditor, InvalidVariantRemovesProperty)
551 {
552     model.setListModel(listModelNode);
553 
554     model.setValue(1, 1, QVariant());
555 
556     ASSERT_FALSE(element2.hasProperty("name"));
557 }
558 
TEST_F(ListModelEditor,DispayValueIsChangedToDouble)559 TEST_F(ListModelEditor, DispayValueIsChangedToDouble)
560 {
561     model.setListModel(listModelNode);
562 
563     model.setValue(1, 1, "25.5");
564 
565     ASSERT_THAT(displayValues()[1][1].type(), QVariant::Double);
566 }
567 
TEST_F(ListModelEditor,StringDispayValueIsNotChanged)568 TEST_F(ListModelEditor, StringDispayValueIsNotChanged)
569 {
570     model.setListModel(listModelNode);
571 
572     model.setValue(1, 1, "25.5a");
573 
574     ASSERT_THAT(displayValues()[1][1].type(), QVariant::String);
575 }
576 
TEST_F(ListModelEditor,SetInvalidToDarkYellowBackgroundColor)577 TEST_F(ListModelEditor, SetInvalidToDarkYellowBackgroundColor)
578 {
579     model.setListModel(listModelNode);
580 
581     ASSERT_THAT(
582         backgroundColors(),
583         ElementsAre(
584             ElementsAre(Qt::darkYellow, Not(Qt::darkYellow), Not(Qt::darkYellow), Not(Qt::darkYellow)),
585             ElementsAre(Not(Qt::darkYellow), Not(Qt::darkYellow), Not(Qt::darkYellow), Qt::darkYellow),
586             ElementsAre(Not(Qt::darkYellow), Not(Qt::darkYellow), Not(Qt::darkYellow), Qt::darkYellow)));
587 }
588 
TEST_F(ListModelEditor,SettingValueChangesBackgroundColor)589 TEST_F(ListModelEditor, SettingValueChangesBackgroundColor)
590 {
591     model.setListModel(listModelNode);
592 
593     model.setValue(0, 0, "foo");
594 
595     ASSERT_THAT(
596         backgroundColors(),
597         ElementsAre(
598             ElementsAre(Not(Qt::darkYellow), Not(Qt::darkYellow), Not(Qt::darkYellow), Not(Qt::darkYellow)),
599             ElementsAre(Not(Qt::darkYellow), Not(Qt::darkYellow), Not(Qt::darkYellow), Qt::darkYellow),
600             ElementsAre(Not(Qt::darkYellow), Not(Qt::darkYellow), Not(Qt::darkYellow), Qt::darkYellow)));
601 }
602 
TEST_F(ListModelEditor,SettingValueChangesByDisplayRoleBackgroundColor)603 TEST_F(ListModelEditor, SettingValueChangesByDisplayRoleBackgroundColor)
604 {
605     model.setListModel(listModelNode);
606 
607     model.setValue(0, 0, "foo", Qt::DisplayRole);
608 
609     ASSERT_THAT(
610         backgroundColors(),
611         ElementsAre(
612             ElementsAre(Not(Qt::darkYellow), Not(Qt::darkYellow), Not(Qt::darkYellow), Not(Qt::darkYellow)),
613             ElementsAre(Not(Qt::darkYellow), Not(Qt::darkYellow), Not(Qt::darkYellow), Qt::darkYellow),
614             ElementsAre(Not(Qt::darkYellow), Not(Qt::darkYellow), Not(Qt::darkYellow), Qt::darkYellow)));
615 }
616 
TEST_F(ListModelEditor,ResettingValueChangesBackgroundColor)617 TEST_F(ListModelEditor, ResettingValueChangesBackgroundColor)
618 {
619     model.setListModel(listModelNode);
620 
621     model.setValue(1, 1, QVariant{});
622 
623     ASSERT_THAT(
624         backgroundColors(),
625         ElementsAre(
626             ElementsAre(Qt::darkYellow, Not(Qt::darkYellow), Not(Qt::darkYellow), Not(Qt::darkYellow)),
627             ElementsAre(Not(Qt::darkYellow), Qt::darkYellow, Not(Qt::darkYellow), Qt::darkYellow),
628             ElementsAre(Not(Qt::darkYellow), Not(Qt::darkYellow), Not(Qt::darkYellow), Qt::darkYellow)));
629 }
630 
TEST_F(ListModelEditor,ResettingValueChangesByDisplayRoleBackgroundColor)631 TEST_F(ListModelEditor, ResettingValueChangesByDisplayRoleBackgroundColor)
632 {
633     model.setListModel(listModelNode);
634 
635     model.setValue(1, 1, QVariant{}, Qt::DisplayRole);
636 
637     ASSERT_THAT(
638         backgroundColors(),
639         ElementsAre(
640             ElementsAre(Qt::darkYellow, Not(Qt::darkYellow), Not(Qt::darkYellow), Not(Qt::darkYellow)),
641             ElementsAre(Not(Qt::darkYellow), Qt::darkYellow, Not(Qt::darkYellow), Qt::darkYellow),
642             ElementsAre(Not(Qt::darkYellow), Not(Qt::darkYellow), Not(Qt::darkYellow), Qt::darkYellow)));
643 }
644 
TEST_F(ListModelEditor,SettingNullValueChangesBackgroundColor)645 TEST_F(ListModelEditor, SettingNullValueChangesBackgroundColor)
646 {
647     model.setListModel(listModelNode);
648 
649     model.setValue(0, 0, 0);
650 
651     ASSERT_THAT(backgroundColors(),
652                 ElementsAre(ElementsAre(_, _, _, _),
653                             ElementsAre(_, _, _, Qt::darkYellow),
654                             ElementsAre(_, _, _, Qt::darkYellow)));
655 }
656 
TEST_F(ListModelEditor,DontRenamePropertyIfColumnNameExists)657 TEST_F(ListModelEditor, DontRenamePropertyIfColumnNameExists)
658 {
659     model.setListModel(listModelNode);
660 
661     model.renameColumn(1, "value2");
662 
663     ASSERT_THAT(model.propertyNames(), ElementsAre("image", "name", "value", "value2"));
664 }
665 
TEST_F(ListModelEditor,DontRenameColumnIfColumnNameExists)666 TEST_F(ListModelEditor, DontRenameColumnIfColumnNameExists)
667 {
668     model.setListModel(listModelNode);
669 
670     model.renameColumn(1, "value2");
671 
672     ASSERT_THAT(headerLabels(model), ElementsAre("image", "name", "value", "value2"));
673 }
674 
TEST_F(ListModelEditor,DontRenameColumnIfColumnNameExistsDoesNotChangeDisplayValues)675 TEST_F(ListModelEditor, DontRenameColumnIfColumnNameExistsDoesNotChangeDisplayValues)
676 {
677     model.setListModel(listModelNode);
678 
679     model.renameColumn(1, "value2");
680 
681     ASSERT_THAT(displayValues(),
682                 ElementsAre(ElementsAre(IsInvalid(), "foo", 1, 42),
683                             ElementsAre("pic.png", "bar", 4, IsInvalid()),
684                             ElementsAre("pic.png", "poo", 111, IsInvalid())));
685 }
686 
TEST_F(ListModelEditor,DontRenameColumnIfColumnNameExistsDoesNotChangeProperties)687 TEST_F(ListModelEditor, DontRenameColumnIfColumnNameExistsDoesNotChangeProperties)
688 {
689     model.setListModel(listModelNode);
690 
691     model.renameColumn(1, "value2");
692 
693     ASSERT_THAT(properties(),
694                 ElementsAre(UnorderedElementsAre(IsVariantProperty("name", "foo"),
695                                                  IsVariantProperty("value", 1),
696                                                  IsVariantProperty("value2", 42)),
697                             UnorderedElementsAre(IsVariantProperty("image", "pic.png"),
698                                                  IsVariantProperty("name", "bar"),
699                                                  IsVariantProperty("value", 4)),
700                             UnorderedElementsAre(IsVariantProperty("image", "pic.png"),
701                                                  IsVariantProperty("name", "poo"),
702                                                  IsVariantProperty("value", 111))));
703 }
704 
TEST_F(ListModelEditor,RenamePropertyButDontChangeOrder)705 TEST_F(ListModelEditor, RenamePropertyButDontChangeOrder)
706 {
707     model.setListModel(listModelNode);
708 
709     model.renameColumn(1, "mood");
710 
711     ASSERT_THAT(model.propertyNames(), ElementsAre("image", "mood", "value", "value2"));
712 }
713 
TEST_F(ListModelEditor,RenameColumnButDontChangeOrder)714 TEST_F(ListModelEditor, RenameColumnButDontChangeOrder)
715 {
716     model.setListModel(listModelNode);
717 
718     model.renameColumn(1, "mood");
719 
720     ASSERT_THAT(headerLabels(model), ElementsAre("image", "mood", "value", "value2"));
721 }
722 
TEST_F(ListModelEditor,RenameColumnButDontChangeOrderDisplayValues)723 TEST_F(ListModelEditor, RenameColumnButDontChangeOrderDisplayValues)
724 {
725     model.setListModel(listModelNode);
726 
727     model.renameColumn(1, "mood");
728 
729     ASSERT_THAT(displayValues(),
730                 ElementsAre(ElementsAre(IsInvalid(), "foo", 1, 42),
731                             ElementsAre("pic.png", "bar", 4, IsInvalid()),
732                             ElementsAre("pic.png", "poo", 111, IsInvalid())));
733 }
734 
TEST_F(ListModelEditor,RenameColumnButDontChangeOrderProperies)735 TEST_F(ListModelEditor, RenameColumnButDontChangeOrderProperies)
736 {
737     model.setListModel(listModelNode);
738 
739     model.renameColumn(1, "mood");
740 
741     ASSERT_THAT(properties(),
742                 ElementsAre(UnorderedElementsAre(IsVariantProperty("mood", "foo"),
743                                                  IsVariantProperty("value", 1),
744                                                  IsVariantProperty("value2", 42)),
745                             UnorderedElementsAre(IsVariantProperty("image", "pic.png"),
746                                                  IsVariantProperty("mood", "bar"),
747                                                  IsVariantProperty("value", 4)),
748                             UnorderedElementsAre(IsVariantProperty("image", "pic.png"),
749                                                  IsVariantProperty("mood", "poo"),
750                                                  IsVariantProperty("value", 111))));
751 }
752 
TEST_F(ListModelEditor,RemoveColumnAfterRenameColumn)753 TEST_F(ListModelEditor, RemoveColumnAfterRenameColumn)
754 {
755     model.setListModel(listModelNode);
756     model.renameColumn(1, "mood");
757 
758     model.removeColumns({index(0, 1)});
759 
760     ASSERT_THAT(properties(),
761                 ElementsAre(UnorderedElementsAre(IsVariantProperty("value", 1),
762                                                  IsVariantProperty("value2", 42)),
763                             UnorderedElementsAre(IsVariantProperty("image", "pic.png"),
764                                                  IsVariantProperty("value", 4)),
765                             UnorderedElementsAre(IsVariantProperty("image", "pic.png"),
766                                                  IsVariantProperty("value", 111))));
767 }
768 
TEST_F(ListModelEditor,ChangeValueAfterRenameColumn)769 TEST_F(ListModelEditor, ChangeValueAfterRenameColumn)
770 {
771     model.setListModel(listModelNode);
772     model.renameColumn(1, "mood");
773 
774     model.setValue(1, 1, "taaa");
775 
776     ASSERT_THAT(properties(),
777                 ElementsAre(UnorderedElementsAre(IsVariantProperty("mood", "foo"),
778                                                  IsVariantProperty("value", 1),
779                                                  IsVariantProperty("value2", 42)),
780                             UnorderedElementsAre(IsVariantProperty("image", "pic.png"),
781                                                  IsVariantProperty("mood", "taaa"),
782                                                  IsVariantProperty("value", 4)),
783                             UnorderedElementsAre(IsVariantProperty("image", "pic.png"),
784                                                  IsVariantProperty("mood", "poo"),
785                                                  IsVariantProperty("value", 111))));
786 }
787 
TEST_F(ListModelEditor,RemovePropertyAfterRenameColumn)788 TEST_F(ListModelEditor, RemovePropertyAfterRenameColumn)
789 {
790     model.setListModel(listModelNode);
791     model.renameColumn(1, "mood");
792 
793     model.setValue(1, 1, {});
794 
795     ASSERT_THAT(properties(),
796                 ElementsAre(UnorderedElementsAre(IsVariantProperty("mood", "foo"),
797                                                  IsVariantProperty("value", 1),
798                                                  IsVariantProperty("value2", 42)),
799                             UnorderedElementsAre(IsVariantProperty("image", "pic.png"),
800                                                  IsVariantProperty("value", 4)),
801                             UnorderedElementsAre(IsVariantProperty("image", "pic.png"),
802                                                  IsVariantProperty("mood", "poo"),
803                                                  IsVariantProperty("value", 111))));
804 }
805 
TEST_F(ListModelEditor,RenameToPrecedingProperty)806 TEST_F(ListModelEditor, RenameToPrecedingProperty)
807 {
808     model.setListModel(listModelNode);
809 
810     model.renameColumn(1, "alpha");
811 
812     ASSERT_THAT(model.propertyNames(), ElementsAre("alpha", "image", "value", "value2"));
813 }
814 
TEST_F(ListModelEditor,RenameToPrecedingColumn)815 TEST_F(ListModelEditor, RenameToPrecedingColumn)
816 {
817     model.setListModel(listModelNode);
818 
819     model.renameColumn(1, "alpha");
820 
821     ASSERT_THAT(headerLabels(model), ElementsAre("alpha", "image", "value", "value2"));
822 }
823 
TEST_F(ListModelEditor,RenameToPrecedingColumnDisplayValues)824 TEST_F(ListModelEditor, RenameToPrecedingColumnDisplayValues)
825 {
826     model.setListModel(listModelNode);
827 
828     model.renameColumn(1, "alpha");
829 
830     ASSERT_THAT(displayValues(),
831                 ElementsAre(ElementsAre("foo", IsInvalid(), 1, 42),
832                             ElementsAre("bar", "pic.png", 4, IsInvalid()),
833                             ElementsAre("poo", "pic.png", 111, IsInvalid())));
834 }
835 
TEST_F(ListModelEditor,RenameToPrecedingColumnProperties)836 TEST_F(ListModelEditor, RenameToPrecedingColumnProperties)
837 {
838     model.setListModel(listModelNode);
839 
840     model.renameColumn(1, "alpha");
841 
842     ASSERT_THAT(properties(),
843                 ElementsAre(UnorderedElementsAre(IsVariantProperty("alpha", "foo"),
844                                                  IsVariantProperty("value", 1),
845                                                  IsVariantProperty("value2", 42)),
846                             UnorderedElementsAre(IsVariantProperty("image", "pic.png"),
847                                                  IsVariantProperty("alpha", "bar"),
848                                                  IsVariantProperty("value", 4)),
849                             UnorderedElementsAre(IsVariantProperty("image", "pic.png"),
850                                                  IsVariantProperty("alpha", "poo"),
851                                                  IsVariantProperty("value", 111))));
852 }
853 
TEST_F(ListModelEditor,RenameToFollowingProperty)854 TEST_F(ListModelEditor, RenameToFollowingProperty)
855 {
856     model.setListModel(listModelNode);
857 
858     model.renameColumn(2, "zoo");
859 
860     ASSERT_THAT(model.propertyNames(), ElementsAre("image", "name", "value2", "zoo"));
861 }
862 
TEST_F(ListModelEditor,RenameToFollowingColumn)863 TEST_F(ListModelEditor, RenameToFollowingColumn)
864 {
865     model.setListModel(listModelNode);
866 
867     model.renameColumn(2, "zoo");
868 
869     ASSERT_THAT(headerLabels(model), ElementsAre("image", "name", "value2", "zoo"));
870 }
871 
TEST_F(ListModelEditor,RenameToFollowingColumnDisplayValues)872 TEST_F(ListModelEditor, RenameToFollowingColumnDisplayValues)
873 {
874     model.setListModel(listModelNode);
875 
876     model.renameColumn(2, "zoo");
877 
878     ASSERT_THAT(displayValues(),
879                 ElementsAre(ElementsAre(IsInvalid(), "foo", 42, 1),
880                             ElementsAre("pic.png", "bar", IsInvalid(), 4),
881                             ElementsAre("pic.png", "poo", IsInvalid(), 111)));
882 }
883 
TEST_F(ListModelEditor,RenameToFollowingColumnProperties)884 TEST_F(ListModelEditor, RenameToFollowingColumnProperties)
885 {
886     model.setListModel(listModelNode);
887 
888     model.renameColumn(2, "zoo");
889 
890     ASSERT_THAT(properties(),
891                 ElementsAre(UnorderedElementsAre(IsVariantProperty("name", "foo"),
892                                                  IsVariantProperty("zoo", 1),
893                                                  IsVariantProperty("value2", 42)),
894                             UnorderedElementsAre(IsVariantProperty("image", "pic.png"),
895                                                  IsVariantProperty("name", "bar"),
896                                                  IsVariantProperty("zoo", 4)),
897                             UnorderedElementsAre(IsVariantProperty("image", "pic.png"),
898                                                  IsVariantProperty("name", "poo"),
899                                                  IsVariantProperty("zoo", 111))));
900 }
901 
TEST_F(ListModelEditor,RenamePropertiesWithInvalidValue)902 TEST_F(ListModelEditor, RenamePropertiesWithInvalidValue)
903 {
904     model.setListModel(listModelNode);
905 
906     model.renameColumn(0, "mood");
907 
908     ASSERT_THAT(properties(),
909                 ElementsAre(UnorderedElementsAre(IsVariantProperty("name", "foo"),
910                                                  IsVariantProperty("value", 1),
911                                                  IsVariantProperty("value2", 42)),
912                             UnorderedElementsAre(IsVariantProperty("mood", "pic.png"),
913                                                  IsVariantProperty("name", "bar"),
914                                                  IsVariantProperty("value", 4)),
915                             UnorderedElementsAre(IsVariantProperty("mood", "pic.png"),
916                                                  IsVariantProperty("name", "poo"),
917                                                  IsVariantProperty("value", 111))));
918 }
919 
TEST_F(ListModelEditor,ChangeValueAfterRenamePropertiesWithInvalidValue)920 TEST_F(ListModelEditor, ChangeValueAfterRenamePropertiesWithInvalidValue)
921 {
922     model.setListModel(listModelNode);
923     model.renameColumn(0, "mood");
924 
925     model.setValue(0, 0, "haaa");
926 
927     ASSERT_THAT(properties(),
928                 ElementsAre(UnorderedElementsAre(IsVariantProperty("mood", "haaa"),
929                                                  IsVariantProperty("name", "foo"),
930                                                  IsVariantProperty("value", 1),
931                                                  IsVariantProperty("value2", 42)),
932                             UnorderedElementsAre(IsVariantProperty("mood", "pic.png"),
933                                                  IsVariantProperty("name", "bar"),
934                                                  IsVariantProperty("value", 4)),
935                             UnorderedElementsAre(IsVariantProperty("mood", "pic.png"),
936                                                  IsVariantProperty("name", "poo"),
937                                                  IsVariantProperty("value", 111))));
938 }
939 
TEST_F(ListModelEditor,RemoveLastRow)940 TEST_F(ListModelEditor, RemoveLastRow)
941 {
942     model.setListModel(emptyListModelNode);
943     model.addColumn("mood");
944     model.addRow();
945 
946     model.removeRows({index(0, 0)});
947 
948     ASSERT_THAT(displayValues(), IsEmpty());
949 }
950 
TEST_F(ListModelEditor,RemoveLastEmptyRow)951 TEST_F(ListModelEditor, RemoveLastEmptyRow)
952 {
953     model.setListModel(emptyListModelNode);
954     model.addColumn("mood");
955     model.addRow();
956     model.removeColumns({index(0, 0)});
957 
958     model.removeRows({index(0, 0)});
959 
960     ASSERT_THAT(displayValues(), ElementsAre(IsEmpty()));
961 }
962 
TEST_F(ListModelEditor,RemoveLastColumn)963 TEST_F(ListModelEditor, RemoveLastColumn)
964 {
965     model.setListModel(emptyListModelNode);
966     model.addColumn("mood");
967     model.addRow();
968 
969     model.removeColumns({index(0, 0)});
970 
971     ASSERT_THAT(displayValues(), ElementsAre(IsEmpty()));
972 }
973 
TEST_F(ListModelEditor,RemoveLastEmptyColumn)974 TEST_F(ListModelEditor, RemoveLastEmptyColumn)
975 {
976     model.setListModel(emptyListModelNode);
977     model.addColumn("mood");
978     model.addRow();
979     model.removeRows({index(0, 0)});
980 
981     model.removeColumns({index(0, 0)});
982 
983     ASSERT_THAT(displayValues(), IsEmpty());
984 }
985 
TEST_F(ListModelEditor,RemoveColumns)986 TEST_F(ListModelEditor, RemoveColumns)
987 {
988     model.setListModel(listModelNode);
989     model.removeColumns({index(0, 1), index(0, 3), index(1, 1), index(0, 4)});
990 
991     ASSERT_THAT(properties(),
992                 ElementsAre(UnorderedElementsAre(IsVariantProperty("value", 1)),
993                             UnorderedElementsAre(IsVariantProperty("image", "pic.png"),
994                                                  IsVariantProperty("value", 4)),
995                             UnorderedElementsAre(IsVariantProperty("image", "pic.png"),
996                                                  IsVariantProperty("value", 111))));
997 }
998 
TEST_F(ListModelEditor,RemoveRows)999 TEST_F(ListModelEditor, RemoveRows)
1000 {
1001     model.setListModel(listModelNode);
1002 
1003     model.removeRows({index(1, 0), index(2, 0), index(3, 0), index(2, 0)});
1004 
1005     ASSERT_THAT(properties(),
1006                 ElementsAre(UnorderedElementsAre(IsVariantProperty("name", "foo"),
1007                                                  IsVariantProperty("value", 1),
1008                                                  IsVariantProperty("value2", 42))));
1009 }
1010 
TEST_F(ListModelEditor,FilterColumns)1011 TEST_F(ListModelEditor, FilterColumns)
1012 {
1013     model.setListModel(listModelNode);
1014     QList<QModelIndex> indices = {index(0, 0), index(1, 1), index(0, 2), index(0, 1)};
1015 
1016     auto columns = ListModelEditorModel::filterColumns(indices);
1017 
1018     ASSERT_THAT(columns, ElementsAre(0, 1, 2));
1019 }
1020 
TEST_F(ListModelEditor,FilterColumnsInvalidColumns)1021 TEST_F(ListModelEditor, FilterColumnsInvalidColumns)
1022 {
1023     QList<QModelIndex> indices = {index(0, 0), index(1, 1), index(0, 2), index(0, 1)};
1024 
1025     auto columns = ListModelEditorModel::filterColumns(indices);
1026 
1027     ASSERT_THAT(columns, IsEmpty());
1028 }
1029 
TEST_F(ListModelEditor,FilterColumnsEmptyInput)1030 TEST_F(ListModelEditor, FilterColumnsEmptyInput)
1031 {
1032     QList<QModelIndex> indices;
1033 
1034     auto columns = ListModelEditorModel::filterColumns(indices);
1035 
1036     ASSERT_THAT(columns, IsEmpty());
1037 }
1038 
TEST_F(ListModelEditor,FilterRows)1039 TEST_F(ListModelEditor, FilterRows)
1040 {
1041     model.setListModel(listModelNode);
1042     QList<QModelIndex> indices = {index(0, 0), index(1, 1), index(2, 2), index(0, 1)};
1043 
1044     auto rows = ListModelEditorModel::filterRows(indices);
1045 
1046     ASSERT_THAT(rows, ElementsAre(0, 1, 2));
1047 }
1048 
TEST_F(ListModelEditor,FilterRowsInvalidColumns)1049 TEST_F(ListModelEditor, FilterRowsInvalidColumns)
1050 {
1051     QList<QModelIndex> indices = {index(0, 0), index(1, 1), index(2, 2), index(0, 1)};
1052 
1053     auto rows = ListModelEditorModel::filterRows(indices);
1054 
1055     ASSERT_THAT(rows, IsEmpty());
1056 }
1057 
TEST_F(ListModelEditor,FilterRowsEmptyInput)1058 TEST_F(ListModelEditor, FilterRowsEmptyInput)
1059 {
1060     QList<QModelIndex> indices;
1061 
1062     auto rows = ListModelEditorModel::filterRows(indices);
1063 
1064     ASSERT_THAT(rows, IsEmpty());
1065 }
1066 
TEST_F(ListModelEditor,CannotMoveEmptyRowsUp)1067 TEST_F(ListModelEditor, CannotMoveEmptyRowsUp)
1068 {
1069     model.setListModel(listModelNode);
1070     QList<QModelIndex> indices = {index(-1, 1)};
1071 
1072     model.moveRowsUp(indices);
1073 
1074     ASSERT_THAT(elements(listModelNode), ElementsAre(element1, element2, element3));
1075 }
1076 
TEST_F(ListModelEditor,MoveRowUp)1077 TEST_F(ListModelEditor, MoveRowUp)
1078 {
1079     model.setListModel(listModelNode);
1080     QList<QModelIndex> indices = {index(1, 1), index(1, 2), index(1, 0)};
1081 
1082     model.moveRowsUp(indices);
1083 
1084     ASSERT_THAT(elements(listModelNode), ElementsAre(element2, element1, element3));
1085 }
1086 
TEST_F(ListModelEditor,MoveRowsUp)1087 TEST_F(ListModelEditor, MoveRowsUp)
1088 {
1089     model.setListModel(listModelNode);
1090     QList<QModelIndex> indices = {index(1, 1), index(2, 2), index(1, 0)};
1091 
1092     model.moveRowsUp(indices);
1093 
1094     ASSERT_THAT(elements(listModelNode), ElementsAre(element2, element3, element1));
1095 }
1096 
TEST_F(ListModelEditor,CannotMoveFirstRowsUp)1097 TEST_F(ListModelEditor, CannotMoveFirstRowsUp)
1098 {
1099     model.setListModel(listModelNode);
1100     QList<QModelIndex> indices = {index(0, 1), index(1, 2), index(0, 0)};
1101 
1102     model.moveRowsUp(indices);
1103 
1104     ASSERT_THAT(elements(listModelNode), ElementsAre(element1, element2, element3));
1105 }
1106 
TEST_F(ListModelEditor,CannotMoveEmptyRowsUpDisplayValues)1107 TEST_F(ListModelEditor, CannotMoveEmptyRowsUpDisplayValues)
1108 {
1109     model.setListModel(listModelNode);
1110     QList<QModelIndex> indices = {index(-1, 1)};
1111 
1112     model.moveRowsUp(indices);
1113 
1114     ASSERT_THAT(displayValues(),
1115                 ElementsAre(ElementsAre(IsInvalid(), "foo", 1, 42),
1116                             ElementsAre("pic.png", "bar", 4, IsInvalid()),
1117                             ElementsAre("pic.png", "poo", 111, IsInvalid())));
1118 }
1119 
TEST_F(ListModelEditor,CannotMoveFirstRowUpDisplayValues)1120 TEST_F(ListModelEditor, CannotMoveFirstRowUpDisplayValues)
1121 {
1122     model.setListModel(listModelNode);
1123     QList<QModelIndex> indices = {index(0, 1), index(1, 2), index(0, 0)};
1124 
1125     model.moveRowsUp(indices);
1126 
1127     ASSERT_THAT(displayValues(),
1128                 ElementsAre(ElementsAre(IsInvalid(), "foo", 1, 42),
1129                             ElementsAre("pic.png", "bar", 4, IsInvalid()),
1130                             ElementsAre("pic.png", "poo", 111, IsInvalid())));
1131 }
1132 
TEST_F(ListModelEditor,MoveRowsUpDisplayValues)1133 TEST_F(ListModelEditor, MoveRowsUpDisplayValues)
1134 {
1135     model.setListModel(listModelNode);
1136     QList<QModelIndex> indices = {index(1, 1), index(2, 2), index(1, 0)};
1137 
1138     model.moveRowsUp(indices);
1139 
1140     ASSERT_THAT(displayValues(),
1141                 ElementsAre(ElementsAre("pic.png", "bar", 4, IsInvalid()),
1142                             ElementsAre("pic.png", "poo", 111, IsInvalid()),
1143                             ElementsAre(IsInvalid(), "foo", 1, 42)));
1144 }
1145 
TEST_F(ListModelEditor,NoSelectionAfterCannotMoveLastRowsDown)1146 TEST_F(ListModelEditor, NoSelectionAfterCannotMoveLastRowsDown)
1147 {
1148     model.setListModel(listModelNode);
1149     QList<QModelIndex> indices = {index(0, 1), index(1, 2), index(0, 0)};
1150 
1151     auto selection = model.moveRowsUp(indices);
1152 
1153     ASSERT_THAT(selection.indexes(), IsEmpty());
1154 }
1155 
TEST_F(ListModelEditor,NoSelectionAfterMoveEmptyRowsDown)1156 TEST_F(ListModelEditor, NoSelectionAfterMoveEmptyRowsDown)
1157 {
1158     model.setListModel(listModelNode);
1159     QList<QModelIndex> indices = {index(-1, 1)};
1160 
1161     auto selection = model.moveRowsUp(indices);
1162 
1163     ASSERT_THAT(selection.indexes(), IsEmpty());
1164 }
1165 
TEST_F(ListModelEditor,SelectionAfterMoveRowsDown)1166 TEST_F(ListModelEditor, SelectionAfterMoveRowsDown)
1167 {
1168     model.setListModel(listModelNode);
1169     QList<QModelIndex> indices = {index(1, 1), index(2, 2), index(1, 0)};
1170 
1171     auto selection = model.moveRowsUp(indices);
1172 
1173     ASSERT_THAT(selection.indexes(),
1174                 ElementsAre(index(0, 0),
1175                             index(0, 1),
1176                             index(0, 2),
1177                             index(0, 3),
1178                             index(1, 0),
1179                             index(1, 1),
1180                             index(1, 2),
1181                             index(1, 3)));
1182 }
1183 
TEST_F(ListModelEditor,CannotMoveEmptyRowsDown)1184 TEST_F(ListModelEditor, CannotMoveEmptyRowsDown)
1185 {
1186     model.setListModel(listModelNode);
1187     QList<QModelIndex> indices = {index(-1, 1)};
1188 
1189     model.moveRowsDown(indices);
1190 
1191     ASSERT_THAT(elements(listModelNode), ElementsAre(element1, element2, element3));
1192 }
1193 
TEST_F(ListModelEditor,MoveRowDown)1194 TEST_F(ListModelEditor, MoveRowDown)
1195 {
1196     model.setListModel(listModelNode);
1197     QList<QModelIndex> indices = {index(1, 1), index(1, 2), index(1, 0)};
1198 
1199     model.moveRowsDown(indices);
1200 
1201     ASSERT_THAT(elements(listModelNode), ElementsAre(element1, element3, element2));
1202 }
1203 
TEST_F(ListModelEditor,MoveRowsDown)1204 TEST_F(ListModelEditor, MoveRowsDown)
1205 {
1206     model.setListModel(listModelNode);
1207     QList<QModelIndex> indices = {index(1, 1), index(0, 2), index(1, 0)};
1208 
1209     model.moveRowsDown(indices);
1210 
1211     ASSERT_THAT(elements(listModelNode), ElementsAre(element3, element1, element2));
1212 }
1213 
TEST_F(ListModelEditor,CannotMoveLastRowsDown)1214 TEST_F(ListModelEditor, CannotMoveLastRowsDown)
1215 {
1216     model.setListModel(listModelNode);
1217     QList<QModelIndex> indices = {index(2, 1), index(1, 2), index(2, 0)};
1218 
1219     model.moveRowsDown(indices);
1220 
1221     ASSERT_THAT(elements(listModelNode), ElementsAre(element1, element2, element3));
1222 }
1223 
TEST_F(ListModelEditor,CannotMoveEmptyRowsDownDisplayValues)1224 TEST_F(ListModelEditor, CannotMoveEmptyRowsDownDisplayValues)
1225 {
1226     model.setListModel(listModelNode);
1227     QList<QModelIndex> indices = {index(-1, 1)};
1228 
1229     model.moveRowsDown(indices);
1230 
1231     ASSERT_THAT(displayValues(),
1232                 ElementsAre(ElementsAre(IsInvalid(), "foo", 1, 42),
1233                             ElementsAre("pic.png", "bar", 4, IsInvalid()),
1234                             ElementsAre("pic.png", "poo", 111, IsInvalid())));
1235 }
1236 
TEST_F(ListModelEditor,CannotMoveLastRowDownDisplayValues)1237 TEST_F(ListModelEditor, CannotMoveLastRowDownDisplayValues)
1238 {
1239     model.setListModel(listModelNode);
1240     QList<QModelIndex> indices = {index(2, 1), index(1, 2), index(2, 0)};
1241 
1242     model.moveRowsDown(indices);
1243 
1244     ASSERT_THAT(displayValues(),
1245                 ElementsAre(ElementsAre(IsInvalid(), "foo", 1, 42),
1246                             ElementsAre("pic.png", "bar", 4, IsInvalid()),
1247                             ElementsAre("pic.png", "poo", 111, IsInvalid())));
1248 }
1249 
TEST_F(ListModelEditor,MoveRowsDownDisplayValues)1250 TEST_F(ListModelEditor, MoveRowsDownDisplayValues)
1251 {
1252     model.setListModel(listModelNode);
1253     QList<QModelIndex> indices = {index(1, 1), index(0, 2), index(1, 0)};
1254 
1255     model.moveRowsDown(indices);
1256 
1257     ASSERT_THAT(displayValues(),
1258                 ElementsAre(ElementsAre("pic.png", "poo", 111, IsInvalid()),
1259                             ElementsAre(IsInvalid(), "foo", 1, 42),
1260                             ElementsAre("pic.png", "bar", 4, IsInvalid())));
1261 }
1262 
TEST_F(ListModelEditor,NoSelectionAfterCannotMoveLastRowsUp)1263 TEST_F(ListModelEditor, NoSelectionAfterCannotMoveLastRowsUp)
1264 {
1265     model.setListModel(listModelNode);
1266     QList<QModelIndex> indices = {index(2, 1), index(1, 2), index(2, 0)};
1267 
1268     auto selection = model.moveRowsDown(indices);
1269 
1270     ASSERT_THAT(selection.indexes(), IsEmpty());
1271 }
1272 
TEST_F(ListModelEditor,NoSelectionAfterMoveEmptyRowsUp)1273 TEST_F(ListModelEditor, NoSelectionAfterMoveEmptyRowsUp)
1274 {
1275     model.setListModel(listModelNode);
1276     QList<QModelIndex> indices = {index(-1, 1)};
1277 
1278     auto selection = model.moveRowsDown(indices);
1279 
1280     ASSERT_THAT(selection.indexes(), IsEmpty());
1281 }
1282 
TEST_F(ListModelEditor,SelectionAfterMoveRowsUp)1283 TEST_F(ListModelEditor, SelectionAfterMoveRowsUp)
1284 {
1285     model.setListModel(listModelNode);
1286     QList<QModelIndex> indices = {index(1, 1), index(0, 2), index(1, 0)};
1287 
1288     auto selection = model.moveRowsDown(indices);
1289 
1290     ASSERT_THAT(selection.indexes(),
1291                 ElementsAre(index(1, 0),
1292                             index(1, 1),
1293                             index(1, 2),
1294                             index(1, 3),
1295                             index(2, 0),
1296                             index(2, 1),
1297                             index(2, 2),
1298                             index(2, 3)));
1299 }
1300 
TEST_F(ListModelEditor,ListViewHasNoModel)1301 TEST_F(ListModelEditor, ListViewHasNoModel)
1302 {
1303     model.setListView(listViewNode);
1304 
1305     ASSERT_THAT(listViewNode.nodeProperty("model").modelNode().type(), Eq("QtQml.Models.ListModel"));
1306 }
1307 
TEST_F(ListModelEditor,ListViewHasModelInside)1308 TEST_F(ListModelEditor, ListViewHasModelInside)
1309 {
1310     listViewNode.nodeProperty("model").reparentHere(listModelNode);
1311 
1312     model.setListView(listViewNode);
1313 
1314     ASSERT_THAT(displayValues(),
1315                 ElementsAre(ElementsAre(IsInvalid(), "foo", 1, 42),
1316                             ElementsAre("pic.png", "bar", 4, IsInvalid()),
1317                             ElementsAre("pic.png", "poo", 111, IsInvalid())));
1318 }
1319 
TEST_F(ListModelEditor,ListViewHasModelBinding)1320 TEST_F(ListModelEditor, ListViewHasModelBinding)
1321 {
1322     listModelNode.setIdWithoutRefactoring("listModel");
1323     listViewNode.bindingProperty("model").setExpression("listModel");
1324 
1325     model.setListView(listViewNode);
1326 
1327     ASSERT_THAT(displayValues(),
1328                 ElementsAre(ElementsAre(IsInvalid(), "foo", 1, 42),
1329                             ElementsAre("pic.png", "bar", 4, IsInvalid()),
1330                             ElementsAre("pic.png", "poo", 111, IsInvalid())));
1331 }
1332 
TEST_F(ListModelEditor,AddBooleanDisplayValues)1333 TEST_F(ListModelEditor, AddBooleanDisplayValues)
1334 {
1335     model.setListModel(listModelNode);
1336 
1337     model.setValue(0, 1, true);
1338 
1339     ASSERT_THAT(displayValues(),
1340                 ElementsAre(ElementsAre(IsInvalid(), true, 1, 42),
1341                             ElementsAre("pic.png", "bar", 4, IsInvalid()),
1342                             ElementsAre("pic.png", "poo", 111, IsInvalid())));
1343 }
1344 
TEST_F(ListModelEditor,AddBooleanProperties)1345 TEST_F(ListModelEditor, AddBooleanProperties)
1346 {
1347     model.setListModel(listModelNode);
1348 
1349     model.setValue(0, 1, true);
1350 
1351     ASSERT_THAT(properties(),
1352                 ElementsAre(UnorderedElementsAre(IsVariantProperty("name", "foo"),
1353                                                  IsVariantProperty("value", true),
1354                                                  IsVariantProperty("value2", 42)),
1355                             UnorderedElementsAre(IsVariantProperty("image", "pic.png"),
1356                                                  IsVariantProperty("name", "bar"),
1357                                                  IsVariantProperty("value", 4)),
1358                             UnorderedElementsAre(IsVariantProperty("image", "pic.png"),
1359                                                  IsVariantProperty("name", "poo"),
1360                                                  IsVariantProperty("value", 111))));
1361 }
1362 
TEST_F(ListModelEditor,AddTrueAsStringProperties)1363 TEST_F(ListModelEditor, AddTrueAsStringProperties)
1364 {
1365     model.setListModel(listModelNode);
1366 
1367     model.setValue(0, 1, "true");
1368 
1369     ASSERT_THAT(properties(),
1370                 ElementsAre(UnorderedElementsAre(IsVariantProperty("name", true),
1371                                                  IsVariantProperty("value", 1),
1372                                                  IsVariantProperty("value2", 42)),
1373                             UnorderedElementsAre(IsVariantProperty("image", "pic.png"),
1374                                                  IsVariantProperty("name", "bar"),
1375                                                  IsVariantProperty("value", 4)),
1376                             UnorderedElementsAre(IsVariantProperty("image", "pic.png"),
1377                                                  IsVariantProperty("name", "poo"),
1378                                                  IsVariantProperty("value", 111))));
1379 }
1380 
TEST_F(ListModelEditor,AddFalseAsStringProperties)1381 TEST_F(ListModelEditor, AddFalseAsStringProperties)
1382 {
1383     model.setListModel(listModelNode);
1384 
1385     model.setValue(0, 1, "false");
1386 
1387     ASSERT_THAT(properties(),
1388                 ElementsAre(UnorderedElementsAre(IsVariantProperty("name", false),
1389                                                  IsVariantProperty("value", 1),
1390                                                  IsVariantProperty("value2", 42)),
1391                             UnorderedElementsAre(IsVariantProperty("image", "pic.png"),
1392                                                  IsVariantProperty("name", "bar"),
1393                                                  IsVariantProperty("value", 4)),
1394                             UnorderedElementsAre(IsVariantProperty("image", "pic.png"),
1395                                                  IsVariantProperty("name", "poo"),
1396                                                  IsVariantProperty("value", 111))));
1397 }
1398 
TEST_F(ListModelEditor,GoIntoComponentForBinding)1399 TEST_F(ListModelEditor, GoIntoComponentForBinding)
1400 {
1401     EXPECT_CALL(mockGoIntoComponent, Call(Eq(listModelNode)))
1402         .WillRepeatedly(Return(mockComponentView.rootModelNode()));
1403     listModelNode.setIdWithoutRefactoring("listModel");
1404     listViewNode.bindingProperty("model").setExpression("listModel");
1405 
1406     model.setListView(listViewNode);
1407 
1408     ASSERT_THAT(displayValues(), ElementsAre(ElementsAre("com", 11, 55)));
1409 }
1410 
TEST_F(ListModelEditor,GoIntoComponentForModelNode)1411 TEST_F(ListModelEditor, GoIntoComponentForModelNode)
1412 {
1413     EXPECT_CALL(mockGoIntoComponent, Call(Eq(listModelNode)))
1414         .WillRepeatedly(Return(mockComponentView.rootModelNode()));
1415     listViewNode.nodeProperty("model").reparentHere(listModelNode);
1416 
1417     model.setListView(listViewNode);
1418 
1419     ASSERT_THAT(displayValues(), ElementsAre(ElementsAre("com", 11, 55)));
1420 }
1421 
1422 } // namespace
1423