xref: /haiku/src/tests/kits/interface/OutlineListViewTest.cpp (revision dd2a1e350b303b855a50fd64e6cb55618be1ae6a)
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 {
25 	static bool equal(const BListItem* x, const BListItem* y) {
26 		return x == y;
27 	}
28 
29 	static string toString(const BListItem* x) {
30 		if (x == NULL)
31 			return "(null)";
32 		return ((BStringItem*)x)->Text();
33 	}
34 };
35 
36 
37 BListItem*
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*
51 FillExpected(BListItem* item, void* arg)
52 {
53 	gExpected[gCount] = item;
54 	gCount++;
55 	return NULL;
56 }
57 
58 
59 void
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:
73 		OutlineListViewTest() {}
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
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
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
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*
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*
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 
306 CppUnit::Test* OutlineListViewTestSuite()
307 {
308 	CppUnit::TestSuite* testSuite = new CppUnit::TestSuite();
309 
310 	testSuite->addTest(OutlineListViewTest::Suite());
311 
312 	return testSuite;
313 }
314