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