1 /*
2 * Copyright 2018, Sean Healy
3 * Distributed under the terms of the MIT License.
4 */
5
6
7
8 #include "common.h"
9
10 #include <Application.h>
11 #include <Window.h>
12 #include <TestUtils.h>
13
14
15 #include <OutlineListView.h>
16
17 BListItem* gExpected[16];
18 int gIndex = 0;
19 int gCount = 0;
20
21
22 template<>
23 struct CppUnit::assertion_traits<BListItem*>
24 {
equalCppUnit::assertion_traits25 static bool equal(const BListItem* x, const BListItem* y) {
26 return x == y;
27 }
28
toStringCppUnit::assertion_traits29 static string toString(const BListItem* x) {
30 if (x == NULL)
31 return "(null)";
32 return ((BStringItem*)x)->Text();
33 }
34 };
35
36
37 BListItem*
CheckExpected(BListItem * item,void * arg)38 CheckExpected(BListItem* item, void* arg)
39 {
40 BStringItem* str = (BStringItem*)item;
41 fprintf(stderr, "Item @%d: %s\n", gIndex, str == NULL ? "(null)" : str->Text());
42
43 CHK(gIndex < gCount);
44 CPPUNIT_ASSERT_EQUAL(gExpected[gIndex], item);
45 gIndex++;
46 return NULL;
47 }
48
49
50 BListItem*
FillExpected(BListItem * item,void * arg)51 FillExpected(BListItem* item, void* arg)
52 {
53 gExpected[gCount] = item;
54 gCount++;
55 return NULL;
56 }
57
58
59 void
CheckItemsUnder(BOutlineListView * view,BListItem * superitem,bool oneLevelOnly)60 CheckItemsUnder(BOutlineListView* view, BListItem* superitem, bool oneLevelOnly)
61 {
62 for (int i = 0; i < gCount; i++)
63 CPPUNIT_ASSERT_EQUAL(gExpected[i], view->ItemUnderAt(superitem, oneLevelOnly, i));
64
65 // Check that we don't get more items
66 CPPUNIT_ASSERT_EQUAL((BListItem*)NULL, view->ItemUnderAt(superitem, oneLevelOnly, gCount));
67 }
68
69
70 class OutlineListViewTest: public TestCase
71 {
72 public:
OutlineListViewTest()73 OutlineListViewTest() {}
OutlineListViewTest(std::string name)74 OutlineListViewTest(std::string name) : TestCase(name) {}
75
76 void EachItemUnder();
77 void AddUnder();
78 void ItemUnderAt();
79
80 static Test* Suite();
81
82 private:
83 static BOutlineListView* _SetupTest(const char* name);
84 };
85
86
87 void
EachItemUnder()88 OutlineListViewTest::EachItemUnder()
89 {
90 BOutlineListView* view = _SetupTest("OutlineListView_EachItemUnder");
91
92 // First test is easy
93 gExpected[0] = view->FullListItemAt(6);
94 gExpected[1] = view->FullListItemAt(8);
95 gExpected[2] = view->FullListItemAt(9);
96 gCount = 3;
97 gIndex = 0;
98
99 fprintf(stderr, "Easy test\n");
100 view->EachItemUnder(view->FullListItemAt(5), true, CheckExpected, NULL);
101 CPPUNIT_ASSERT_EQUAL(gCount, view->CountItemsUnder(view->FullListItemAt(5), true));
102
103 // Check that collapsing an item does not change the outcome
104 gIndex = 0;
105 view->Collapse(view->FullListItemAt(0));
106
107 fprintf(stderr, "One collapsed\n");
108 view->EachItemUnder(view->FullListItemAt(5), true, CheckExpected, NULL);
109
110 gIndex = 0;
111 view->Collapse(view->FullListItemAt(5));
112
113 fprintf(stderr, "Two collapsed\n");
114 view->EachItemUnder(view->FullListItemAt(5), true, CheckExpected, NULL);
115 CPPUNIT_ASSERT_EQUAL(gCount, view->CountItemsUnder(view->FullListItemAt(5), true));
116
117 // Also check deeper levels
118 gExpected[1] = view->FullListItemAt(7);
119 gExpected[2] = view->FullListItemAt(8);
120 gExpected[3] = view->FullListItemAt(9);
121 gCount = 4;
122 gIndex = 0;
123
124 fprintf(stderr, "All levels\n");
125 view->EachItemUnder(view->FullListItemAt(5), false, CheckExpected, NULL);
126 CPPUNIT_ASSERT_EQUAL(gCount, view->CountItemsUnder(view->FullListItemAt(5), false));
127
128 view->Expand(view->FullListItemAt(5));
129 view->Collapse(view->FullListItemAt(6));
130 gIndex = 0;
131
132 fprintf(stderr, "All levels with a collapsed sublevel\n");
133 view->EachItemUnder(view->FullListItemAt(5), false, CheckExpected, NULL);
134 CPPUNIT_ASSERT_EQUAL(gCount, view->CountItemsUnder(view->FullListItemAt(5), false));
135
136 // NULL is the parent of level 0 items
137 gExpected[0] = view->FullListItemAt(0);
138 gExpected[1] = view->FullListItemAt(5);
139 gExpected[2] = view->FullListItemAt(10);
140 gCount = 3;
141 gIndex = 0;
142
143 fprintf(stderr, "Level 0\n");
144 view->EachItemUnder(NULL, true, CheckExpected, NULL);
145 CPPUNIT_ASSERT_EQUAL(gCount, view->CountItemsUnder(NULL, true));
146
147 // No visits when the item is not in the list
148 BListItem* notfound = new BStringItem("Not found");
149 gCount = 0;
150 gIndex = 0;
151
152 fprintf(stderr, "Item not in the list\n");
153 view->EachItemUnder(notfound, true, CheckExpected, NULL);
154 CPPUNIT_ASSERT_EQUAL(gCount, view->CountItemsUnder(notfound, true));
155 view->EachItemUnder(notfound, false, CheckExpected, NULL);
156 CPPUNIT_ASSERT_EQUAL(gCount, view->CountItemsUnder(notfound, false));
157
158 // Don't actually run anything
159 delete view->Window();
160 }
161
162
163 void
AddUnder()164 OutlineListViewTest::AddUnder()
165 {
166 BOutlineListView* view = _SetupTest("OutlineListView_AddUnder");
167
168 BListItem* one = view->FullListItemAt(0);
169 BListItem* oneA = view->FullListItemAt(1);
170 BListItem* oneA0 = new BStringItem("One-A-0");
171 BListItem* oneA1 = view->FullListItemAt(2);
172
173 int32 count = view->FullListCountItems();
174
175 BListItem* last = view->FullListItemAt(count - 1);
176 BListItem* newLast = new BStringItem("NewLast");
177
178 view->AddUnder(newLast, NULL);
179 view->AddUnder(oneA0, oneA);
180
181 fprintf(stderr, "Count\n");
182 CPPUNIT_ASSERT_EQUAL(count + 2, view->FullListCountItems());
183
184 fprintf(stderr, "Insertion order\n");
185 CPPUNIT_ASSERT_EQUAL(one, view->FullListItemAt(0));
186 CPPUNIT_ASSERT_EQUAL(oneA, view->FullListItemAt(1));
187 CPPUNIT_ASSERT_EQUAL(oneA0, view->FullListItemAt(2));
188 CPPUNIT_ASSERT_EQUAL(oneA1, view->FullListItemAt(3));
189 CPPUNIT_ASSERT_EQUAL(last, view->FullListItemAt(count));
190 CPPUNIT_ASSERT_EQUAL(newLast, view->FullListItemAt(count + 1));
191
192 fprintf(stderr, "Levels\n");
193 CPPUNIT_ASSERT_EQUAL(0, one->OutlineLevel());
194 CPPUNIT_ASSERT_EQUAL(1, oneA->OutlineLevel());
195 CPPUNIT_ASSERT_EQUAL(2, oneA0->OutlineLevel());
196 CPPUNIT_ASSERT_EQUAL(2, oneA1->OutlineLevel());
197 CPPUNIT_ASSERT_EQUAL(0, newLast->OutlineLevel());
198
199 // Don't actually run anything
200 delete view->Window();
201 }
202
203
204 void
ItemUnderAt()205 OutlineListViewTest::ItemUnderAt()
206 {
207 BOutlineListView* view = _SetupTest("OutlineListView_ItemUnderAt");
208
209 // EachItemUnder has already been checked, we can use it to know what to expect
210 gCount = 0;
211 view->EachItemUnder(view->FullListItemAt(5), true, FillExpected, NULL);
212
213 fprintf(stderr, "Easy test\n");
214 CheckItemsUnder(view, view->FullListItemAt(5), true);
215
216 // Check that collapsing an item does not change the outcome
217 view->Collapse(view->FullListItemAt(0));
218
219 fprintf(stderr, "One collapsed\n");
220 CheckItemsUnder(view, view->FullListItemAt(5), true);
221
222 view->Collapse(view->FullListItemAt(5));
223
224 fprintf(stderr, "Two collapsed\n");
225 CheckItemsUnder(view, view->FullListItemAt(5), true);
226
227 // Also check deeper levels
228 gCount = 0;
229 view->EachItemUnder(view->FullListItemAt(5), false, FillExpected, NULL);
230
231 fprintf(stderr, "All levels\n");
232 CheckItemsUnder(view, view->FullListItemAt(5), false);
233
234 view->Expand(view->FullListItemAt(5));
235 view->Collapse(view->FullListItemAt(6));
236
237 fprintf(stderr, "All levels with a collapsed sublevel\n");
238 CheckItemsUnder(view, view->FullListItemAt(5), false);
239
240 // NULL is the parent of level 0 items
241 gCount = 0;
242 view->EachItemUnder(NULL, true, FillExpected, NULL);
243
244 fprintf(stderr, "Level 0\n");
245 CheckItemsUnder(view, NULL, true);
246
247 // Get NULL when the item is not in the list
248 BListItem* notfound = new BStringItem("Not found");
249 fprintf(stderr, "Item not in the list\n");
250 CPPUNIT_ASSERT_EQUAL((BListItem*)NULL, view->ItemUnderAt(notfound, true, 0));
251 CPPUNIT_ASSERT_EQUAL((BListItem*)NULL, view->ItemUnderAt(notfound, false, 0));
252
253 // Don't actually run anything
254 delete view->Window();
255 }
256
257
258 Test*
Suite()259 OutlineListViewTest::Suite()
260 {
261 TestSuite* SuiteOfTests = new TestSuite;
262
263 ADD_TEST4(BOutlineListView, SuiteOfTests, OutlineListViewTest, EachItemUnder);
264 ADD_TEST4(BOutlineListView, SuiteOfTests, OutlineListViewTest, AddUnder);
265 ADD_TEST4(BOutlineListView, SuiteOfTests, OutlineListViewTest, ItemUnderAt);
266
267 return SuiteOfTests;
268 }
269
270
271 BOutlineListView*
_SetupTest(const char * name)272 OutlineListViewTest::_SetupTest(const char* name)
273 {
274 if (be_app == NULL)
275 new BApplication("application/x-vnd.OutlineListView.test");
276
277 BWindow* window = new BWindow(BRect(50, 50, 550, 550), name,
278 B_TITLED_WINDOW, B_QUIT_ON_WINDOW_CLOSE, 0);
279
280 BOutlineListView* view = new BOutlineListView(BRect(5, 5, 495, 495), "View",
281 B_MULTIPLE_SELECTION_LIST, B_FOLLOW_ALL);
282 window->AddChild(view);
283
284 view->AddItem(new BStringItem("One", 0));
285 view->AddItem(new BStringItem("One-A", 1));
286 view->AddItem(new BStringItem("One-A-1", 2));
287 view->AddItem(new BStringItem("One-B", 1));
288 view->AddItem(new BStringItem("One-C", 1));
289
290 view->AddItem(new BStringItem("Two", 0));
291 view->AddItem(new BStringItem("Two-A", 1));
292 view->AddItem(new BStringItem("Two-A-1", 2));
293 view->AddItem(new BStringItem("Two-B", 1));
294 view->AddItem(new BStringItem("Two-C", 1));
295
296 view->AddItem(new BStringItem("Three", 0));
297 view->AddItem(new BStringItem("Three-A", 1));
298 view->AddItem(new BStringItem("Three-A-1", 2));
299 view->AddItem(new BStringItem("Three-B", 1));
300 view->AddItem(new BStringItem("Three-C", 1));
301
302 return view;
303 }
304
305
OutlineListViewTestSuite()306 CppUnit::Test* OutlineListViewTestSuite()
307 {
308 CppUnit::TestSuite* testSuite = new CppUnit::TestSuite();
309
310 testSuite->addTest(OutlineListViewTest::Suite());
311
312 return testSuite;
313 }
314