1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "chrome/browser/ui/views/tabs/stacked_tab_strip_layout.h" 6 7 #include <string> 8 9 #include "base/strings/string_number_conversions.h" 10 #include "base/strings/string_util.h" 11 #include "testing/gtest/include/gtest/gtest.h" 12 #include "ui/views/view.h" 13 #include "ui/views/view_model.h" 14 15 namespace { 16 17 struct CommonTestData { 18 const int initial_x; 19 const int width; 20 const int tab_size; 21 const int tab_padding; 22 const int stacked_offset; 23 const int mini_tab_count; 24 const int active_index; 25 const std::string start_bounds; 26 const std::string expected_bounds; 27 }; 28 29 } // namespace 30 31 class StackedTabStripLayoutTest : public testing::Test { 32 public: 33 StackedTabStripLayoutTest() {} 34 35 protected: 36 void Reset(StackedTabStripLayout* layout, 37 int x, 38 int width, 39 int mini_tab_count, 40 int active_index) { 41 layout->Reset(x, width, mini_tab_count, active_index); 42 } 43 44 void CreateLayout(const CommonTestData& data) { 45 if (!data.start_bounds.empty()) 46 PrepareChildViewsFromString(data.start_bounds); 47 else 48 PrepareChildViewsFromString(data.expected_bounds); 49 layout_.reset(new StackedTabStripLayout( 50 gfx::Size(data.tab_size, 10), data.tab_padding, 51 data.stacked_offset, 4, &view_model_)); 52 if (data.start_bounds.empty()) { 53 PrepareChildViewsFromString(data.expected_bounds); 54 layout_->Reset(data.initial_x, data.width, data.mini_tab_count, 55 data.active_index); 56 } else { 57 ASSERT_NO_FATAL_FAILURE(SetBoundsFromString(data.start_bounds)); 58 layout_->Reset(data.initial_x, data.width, data.mini_tab_count, 59 data.active_index); 60 ASSERT_NO_FATAL_FAILURE(SetBoundsFromString(data.start_bounds)); 61 } 62 } 63 64 void AddViewToViewModel(int index) { 65 views::View* child_view = new views::View; 66 view_.AddChildView(child_view); 67 view_model_.Add(child_view, index); 68 } 69 70 void PrepareChildViewsFromString(const std::string& bounds) { 71 std::vector<std::string> positions; 72 Tokenize(bounds, " ", &positions); 73 PrepareChildViews(static_cast<int>(positions.size())); 74 } 75 76 void PrepareChildViews(int count) { 77 view_model_.Clear(); 78 view_.RemoveAllChildViews(true); 79 for (int i = 0; i < count; ++i) 80 AddViewToViewModel(i); 81 } 82 83 void SetBoundsFromString(const std::string& bounds) { 84 std::vector<std::string> positions; 85 Tokenize(bounds, " ", &positions); 86 PrepareChildViews(static_cast<int>(positions.size())); 87 for (int i = 0; i < view_model_.view_size(); ++i) { 88 int x = 0; 89 gfx::Rect bounds(view_model_.ideal_bounds(i)); 90 ASSERT_TRUE(base::StringToInt(positions[i], &x)); 91 bounds.set_x(x); 92 view_model_.set_ideal_bounds(i, bounds); 93 } 94 } 95 96 std::string BoundsString() const { 97 std::string result; 98 for (int i = 0; i < view_model_.view_size(); ++i) { 99 if (!result.empty()) 100 result += " "; 101 result += base::IntToString(view_model_.ideal_bounds(i).x()); 102 } 103 return result; 104 } 105 106 std::string BoundsString2(int active_index) const { 107 std::string result; 108 for (int i = 0; i < view_model_.view_size(); ++i) { 109 if (!result.empty()) 110 result += " "; 111 if (i == active_index) 112 result += "["; 113 result += base::IntToString(view_model_.ideal_bounds(i).x()); 114 if (i == active_index) 115 result += "]"; 116 } 117 return result; 118 } 119 120 void Validate(int active_index, int max_width) { 121 // Make sure none of the tabs are more than 90 apart 122 // (tab_size(100) + padding (-10)). 123 for (int j = 1; j < view_model_.view_size(); ++j) 124 EXPECT_LE(ideal_x(j) - ideal_x(j - 1), max_width - 100); 125 } 126 127 int ideal_x(int index) const { 128 return view_model_.ideal_bounds(index).x(); 129 } 130 131 scoped_ptr<StackedTabStripLayout> layout_; 132 views::ViewModel view_model_; 133 134 private: 135 views::View view_; 136 137 DISALLOW_COPY_AND_ASSIGN(StackedTabStripLayoutTest); 138 }; 139 140 // Random data. 141 TEST_F(StackedTabStripLayoutTest, ValidateInitialLayout) { 142 StackedTabStripLayout layout(gfx::Size(100, 10), -10, 2, 4, &view_model_); 143 PrepareChildViews(12); 144 145 for (int i = 120; i < 600; ++i) { 146 for (int j = 0; j < 12; ++j) { 147 Reset(&layout, 0, i, 0, j); 148 Validate(j, i); 149 if (HasNonfatalFailure()) 150 return; 151 } 152 } 153 } 154 155 // Ensure initial layout is correct. 156 TEST_F(StackedTabStripLayoutTest, InitialLayout) { 157 struct CommonTestData test_data[] = { 158 { 0, 198, 100, -10, 1, 0, 9, "", 159 "0 0 0 0 0 0 1 2 3 4 94 95 96 97 98 98 98 98" }, 160 { 0, 198, 100, -10, 1, 0, 0, "", "0 90 94 95 96 97 98 98 98" }, 161 { 0, 300, 100, -10, 1, 0, 0, "", 162 "0 90 180 196 197 198 199 200 200 200 200" }, 163 { 0, 300, 100, -10, 1, 0, 10, "", "0 0 0 0 1 2 3 4 20 110 200" }, 164 { 0, 300, 100, -10, 1, 0, 1, "", "0 90 180 196 197 198 199 200 200" }, 165 { 0, 643, 160, -27, 6, 0, 0, "", "0 133 266 399" }, 166 { 0, 300, 100, -10, 1, 0, 7, "", "0 1 2 3 4 20 110 200" }, 167 { 0, 300, 100, -10, 1, 0, 6, "", "0 1 2 3 4 20 110 200" }, 168 { 0, 300, 100, -10, 1, 0, 4, "", "0 1 2 3 4 94 184 199 200" }, 169 }; 170 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_data); ++i) { 171 CreateLayout(test_data[i]); 172 EXPECT_EQ(test_data[i].expected_bounds, BoundsString()) << " at " << i; 173 } 174 } 175 176 // Assertions for dragging from an existing configuration. 177 TEST_F(StackedTabStripLayoutTest, DragActiveTabExisting) { 178 struct TestData { 179 struct CommonTestData common_data; 180 const int delta; 181 } test_data[] = { 182 // 183 // The following set of tests create 6 tabs, the first two are pinned and 184 // the 2nd tab is selected. 185 // 186 // 1 pixel to the right, should push only mini-tabs and first non-mini-tab. 187 { { 10, 240, 100, -10, 2, 2, 1, "0 5 10 100 138 140", 188 "1 6 11 101 138 140" }, 1 }, 189 // Push enough to collapse the 4th tab. 190 { { 10, 240, 100, -10, 2, 2, 1, "0 5 10 100 138 140", 191 "36 41 46 136 138 140" }, 36 }, 192 // 1 past collapsing the 4th. 193 { { 10, 240, 100, -10, 2, 2, 1, "0 5 10 100 138 140", 194 "37 42 47 136 138 140" }, 37 }, 195 // Collapse the third. 196 { { 10, 240, 100, -10, 2, 2, 1, "0 5 10 100 138 140", 197 "124 129 134 136 138 140" }, 124 }, 198 // One past collapsing the third. 199 { { 10, 240, 100, -10, 2, 2, 1, "0 5 10 100 138 140", 200 "124 129 134 136 138 140" }, 125 }, 201 202 // 203 // The following set of tests create 6 tabs, the first two are pinned and 204 // the 5th is selected. 205 // 206 // 1 pixel to the right, should expose part of a tab. 207 { { 10, 240, 100, -10, 2, 2, 4, "0 5 10 90 130 140", "0 5 10 90 131 140" }, 208 1 }, 209 // Push the tab as far to the right as it'll go. 210 { { 10, 240, 100, -10, 2, 2, 4, "0 5 10 90 130 140", "0 5 10 90 138 140" }, 211 8 }, 212 // One past as far to the right as it'll go. Should expose more of the tab 213 // before it. 214 { { 10, 240, 100, -10, 2, 2, 4, "0 5 10 90 130 140", "0 5 10 91 138 140" }, 215 9 }, 216 // Enough so that the pinned tabs start pulling in. 217 { { 10, 240, 100, -10, 2, 2, 4, "0 5 10 90 130 140", "1 6 11 101 138 140" }, 218 19 }, 219 // One more than last. 220 { { 10, 240, 100, -10, 2, 2, 4, "0 5 10 90 130 140", "2 7 12 102 138 140" }, 221 20 }, 222 // Enough to collapse the fourth as small it can get. 223 { { 10, 240, 100, -10, 2, 2, 4, "0 5 10 90 130 140", 224 "36 41 46 136 138 140" }, 54 }, 225 // Enough to collapse the third as small it can get. 226 { { 10, 240, 100, -10, 2, 2, 4, "0 5 10 90 130 140", 227 "124 129 134 136 138 140" }, 142 }, 228 // One more than last, shouldn't change anything. 229 { { 10, 240, 100, -10, 2, 2, 4, "0 5 10 90 130 140", 230 "124 129 134 136 138 140" }, 143 }, 231 232 // 233 // The following set of tests create 3 tabs with the second selected. 234 // 235 // Drags in 2, pulling the rightmost tab along. 236 { { 0, 240, 100, -10, 2, 0, 1, "0 90 140", "2 92 140" }, 2 }, 237 // Drags the rightmost tab as far to right as possible. 238 { { 0, 240, 100, -10, 2, 0, 1, "0 90 140", "48 138 140" }, 48 }, 239 // Drags so much that the left most tabs pulls in. 240 { { 0, 240, 100, -10, 2, 0, 1, "0 90 140", "135 138 140" }, 135 }, 241 // Drags so far that no more tabs pull in. 242 { { 0, 240, 100, -10, 2, 0, 1, "0 90 140", "136 138 140" }, 200 }, 243 // Drags to the left most position before the right tabs start pulling in. 244 { { 0, 240, 100, -10, 2, 0, 1, "0 90 140", "0 50 140" }, -40 }, 245 // Drags 1 beyond the left most position, which should pull in the right 246 // tab slightly. 247 { { 0, 240, 100, -10, 2, 0, 1, "0 90 140", "0 49 139" }, -41 }, 248 // Drags to the left as far as the tab goes. 249 { { 0, 240, 100, -10, 2, 0, 1, "0 90 140", "0 2 92" }, -88 }, 250 // Drags one past as far to the left as the tab goes. Should keep pulling 251 // in the rightmost tab. 252 { { 0, 240, 100, -10, 2, 0, 1, "0 90 140", "0 2 91" }, -89 }, 253 }; 254 255 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_data); ++i) { 256 CreateLayout(test_data[i].common_data); 257 layout_->DragActiveTab(test_data[i].delta); 258 EXPECT_EQ(test_data[i].common_data.expected_bounds, BoundsString()) << 259 " at " << i; 260 } 261 } 262 263 // Assertions for SizeToFit(). 264 TEST_F(StackedTabStripLayoutTest, SizeToFit) { 265 struct CommonTestData test_data[] = { 266 // Dragged to the right. 267 { 10, 240, 100, -10, 2, 2, 1, "0 5 10 100 138 140", "1 6 11 101 138 140"}, 268 { 10, 240, 100, -10, 2, 2, 1, "0 5 10 100 138 140", 269 "124 129 134 136 138 140" }, 270 271 // Dragged to the left. 272 { 0, 240, 100, -10, 2, 0, 1, "0 50 140", "0 49 139" }, 273 274 // Dragged to the left. 275 { 0, 240, 100, -10, 2, 0, 1, "0 49 89 140", "0 49 89 139" }, 276 }; 277 278 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_data); ++i) { 279 CreateLayout(test_data[i]); 280 SetBoundsFromString(test_data[i].expected_bounds); 281 layout_->SizeToFit(); 282 // NOTE: because of the way the code is structured this asserts on 283 // |start_bound|, not |expected_bounds|. 284 EXPECT_EQ(test_data[i].start_bounds, BoundsString()) << " at " << i; 285 } 286 } 287 288 // Assertions for AddTab(). 289 TEST_F(StackedTabStripLayoutTest, AddTab) { 290 struct TestData { 291 CommonTestData common_data; 292 int add_index; 293 bool add_active; 294 bool add_mini; 295 } test_data[] = { 296 // Adding a background tab test cases. 297 { { 0, 300, 100, -10, 2, 0, 1, "0 90 180 198 200", "0 16 106 196 198 200"}, 298 3, false, false }, 299 { { 0, 300, 100, -10, 2, 0, 1, "0 90 180 198 200", "0 2 4 20 110 200"}, 300 5, false, false }, 301 { { 0, 300, 100, -10, 2, 0, 1, "0 90 180 198 200", "0 90 180 196 198 200"}, 302 2, false, false }, 303 { { 0, 300, 100, -10, 2, 0, 1, "0 90 180 198 200", "0 2 4 94 184 200"}, 304 0, false, false }, 305 306 { { 4, 200, 100, -10, 2, 1, 2, "0 4 10 100", "0 0 8 10 100"}, 307 1, false, true }, 308 { { 4, 200, 100, -10, 2, 1, 2, "0 4 10 100", "0 0 8 98 100"}, 309 1, true, true }, 310 { { 4, 200, 100, -10, 2, 1, 2, "0 4 10 100", "0 0 8 98 100"}, 311 0, true, true }, 312 { { 0, 200, 100, -10, 2, 0, 2, "0 2 10 100", "0 4 94 98 100"}, 313 0, true, true }, 314 315 { { 0, 200, 100, -10, 2, 0, 0, "0 90 92 92 94 96 98 100", 316 "0 0 0 2 4 6 8 98 100"}, 317 7, true, false }, 318 { { 0, 200, 100, -10, 2, 0, 7, "0 2 4 6 8 8 10 100", 319 "0 0 2 4 6 8 96 98 100"}, 320 5, true, false }, 321 { { 0, 200, 100, -10, 2, 0, 7, "0 2 4 6 8 8 10 100", 322 "0 2 4 6 8 94 96 98 100"}, 323 4, true, false }, 324 { { 0, 200, 100, -10, 2, 0, 2, "0 2 10 100", "0 2 10 98 100"}, 325 2, true, false }, 326 { { 0, 200, 100, -10, 2, 0, 2, "0 2 10 100", "0 2 4 10 100"}, 327 4, true, false }, 328 { { 0, 200, 100, -10, 2, 0, 2, "0 2 10 100", "0 90 96 98 100"}, 329 0, true, false }, 330 }; 331 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_data); ++i) { 332 CreateLayout(test_data[i].common_data); 333 int add_types = 0; 334 if (test_data[i].add_active) 335 add_types |= StackedTabStripLayout::kAddTypeActive; 336 if (test_data[i].add_mini) 337 add_types |= StackedTabStripLayout::kAddTypeMini; 338 AddViewToViewModel(test_data[i].add_index); 339 layout_->AddTab(test_data[i].add_index, add_types, 340 test_data[i].common_data.initial_x + 341 (test_data[i].add_mini ? 4 : 0)); 342 EXPECT_EQ(test_data[i].common_data.expected_bounds, BoundsString()) << 343 " at " << i; 344 } 345 } 346 347 // Assertions around removing tabs. 348 TEST_F(StackedTabStripLayoutTest, RemoveTab) { 349 // TODO: add coverage of removing mini tabs! 350 struct TestData { 351 struct CommonTestData common_data; 352 const int remove_index; 353 const int x_after_remove; 354 } test_data[] = { 355 { { 0, 882, 220, -29, 2, 0, 4, "0 23 214 405 596 602", 356 "0 191 382 573 662" }, 1, 0 }, 357 358 // Remove before active. 359 { { 0, 200, 100, -10, 2, 0, 4, "0 2 4 6 8 10 80 98 100", 360 "0 2 6 8 10 80 98 100" }, 361 2, 0 }, 362 363 // Stacked tabs on both sides. 364 { { 0, 200, 100, -10, 2, 0, 4, "0 2 4 6 8 10 80 98 100", 365 "0 2 4 6 10 80 98 100" }, 366 4, 0 }, 367 368 // Mini-tabs. 369 { { 8, 200, 100, -10, 2, 1, 0, "0 8 94 96 98 100", "0 86 88 90 100" }, 370 0, 0 }, 371 { { 16, 200, 100, -10, 2, 2, 0, "0 8 16 94 96 98 100", "8 8 86 88 90 100" }, 372 0, 8 }, 373 { { 16, 200, 100, -10, 2, 2, 0, "0 8 16 94 96 98 100", "0 8 86 88 90 100" }, 374 1, 8 }, 375 376 // Remove from ideal layout. 377 { { 0, 200, 100, -10, 2, 0, 0, "0 90 94 96 98 100", "0 90 96 98 100" }, 378 0, 0 }, 379 { { 0, 200, 100, -10, 2, 0, 0, "0 90 94 96 98 100", "0 90 96 98 100" }, 380 1, 0 }, 381 { { 0, 200, 100, -10, 2, 0, 0, "0 90 94 96 98 100", "0 90 96 98 100" }, 382 2, 0 }, 383 { { 0, 200, 100, -10, 2, 0, 0, "0 90 94 96 98 100", "0 90 94 98 100" }, 384 3, 0 }, 385 { { 0, 200, 100, -10, 2, 0, 0, "0 90 94 96 98 100", "0 90 94 96 100" }, 386 5, 0 }, 387 }; 388 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_data); ++i) { 389 CreateLayout(test_data[i].common_data); 390 int old_x = view_model_.ideal_bounds(test_data[i].remove_index).x(); 391 view_model_.Remove(test_data[i].remove_index); 392 layout_->RemoveTab(test_data[i].remove_index, test_data[i].x_after_remove, 393 old_x); 394 EXPECT_EQ(test_data[i].common_data.expected_bounds, BoundsString()) << 395 " at " << i; 396 } 397 } 398 399 // Assertions for SetWidth(). 400 TEST_F(StackedTabStripLayoutTest, SetWidth) { 401 struct TestData { 402 CommonTestData common_data; 403 int new_width; 404 } test_data[] = { 405 { { 0, 500, 100, -10, 2, 0, 4, "0 90 180 270 360 400", 406 "0 90 180 196 198 200"}, 300 }, 407 408 // Verifies a bug in AdjustTrailingStackedTabs(). 409 { { 0, 103, 100, -10, 2, 0, 0, "", "0 2"}, 102 }, 410 411 { { 8, 250, 100, -10, 2, 2, 2, "0 4 8 98 148 150", "0 4 8 98 160 250"}, 412 350 }, 413 { { 8, 250, 100, -10, 2, 2, 2, "0 4 8 98 148 150", "0 4 8 96 98 100"}, 414 200 }, 415 416 { { 0, 250, 100, -10, 2, 0, 2, "0 40 90 120 150", "0 40 90 98 100"}, 200 }, 417 { { 0, 250, 100, -10, 2, 0, 2, "0 2 60 150", "0 2 60 100"}, 200 }, 418 { { 0, 250, 100, -10, 2, 0, 2, "0 40 120 150", "0 40 98 100"}, 200 }, 419 420 { { 0, 200, 100, -10, 2, 0, 2, "0 2 10 100", "0 2 60 150"}, 250 }, 421 { { 0, 200, 100, -10, 2, 0, 2, "0 2 4 10 100", "0 2 20 110 200"}, 300 }, 422 }; 423 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_data); ++i) { 424 CreateLayout(test_data[i].common_data); 425 layout_->SetWidth(test_data[i].new_width); 426 EXPECT_EQ(test_data[i].common_data.expected_bounds, BoundsString()) << 427 " at " << i; 428 } 429 } 430 431 // Assertions for SetActiveIndex(). 432 TEST_F(StackedTabStripLayoutTest, SetActiveIndex) { 433 struct TestData { 434 CommonTestData common_data; 435 int new_index; 436 } test_data[] = { 437 { { 0, 250, 100, -10, 2, 0, 2, "0 4 8 98 148 150", "0 90 144 146 148 150"}, 438 0 }, 439 { { 0, 250, 100, -10, 2, 0, 2, "0 4 8 98 148 150", "0 2 4 58 148 150"}, 4 }, 440 { { 0, 250, 100, -10, 2, 0, 2, "0 4 8 98 148 150", "0 2 4 6 60 150"}, 5 }, 441 { { 4, 250, 100, -10, 2, 1, 2, "0 4 8 98 148 150", "0 4 94 146 148 150"}, 442 0 }, 443 }; 444 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_data); ++i) { 445 CreateLayout(test_data[i].common_data); 446 layout_->SetActiveIndex(test_data[i].new_index); 447 EXPECT_EQ(test_data[i].common_data.expected_bounds, BoundsString()) << 448 " at " << i; 449 } 450 } 451 452 // Makes sure don't crash when resized and only one tab. 453 TEST_F(StackedTabStripLayoutTest, EmptyTest) { 454 StackedTabStripLayout layout(gfx::Size(160, 10), -27, 6, 4, &view_model_); 455 PrepareChildViews(1); 456 layout.AddTab(0, StackedTabStripLayout::kAddTypeActive, 0); 457 layout.SetWidth(100); 458 layout.SetWidth(50); 459 layout.SetWidth(0); 460 layout.SetWidth(500); 461 } 462 463 // Assertions around removing tabs. 464 TEST_F(StackedTabStripLayoutTest, MoveTab) { 465 // TODO: add coverage of removing mini tabs! 466 struct TestData { 467 struct CommonTestData common_data; 468 const int from; 469 const int to; 470 const int new_active_index; 471 const int new_start_x; 472 const int new_mini_tab_count; 473 } test_data[] = { 474 // Moves and unpins. 475 { { 10, 300, 100, -10, 2, 2, 0, "", "0 5 10 100 190 198 200" }, 476 0, 1, 2, 5, 1 }, 477 478 // Moves and pins. 479 { { 0, 300, 100, -10, 2, 0, 4, "", "0 5 95 185 196 198 200" }, 480 2, 0, 0, 5, 1 }, 481 { { 0, 300, 100, -10, 2, 1, 2, "", "0 5 10 100 190 198 200" }, 482 2, 0, 0, 10, 2 }, 483 484 { { 0, 200, 100, -10, 2, 0, 4, "0 2 4 6 96 98 100", "0 2 4 6 96 98 100" }, 485 2, 0, 4, 0, 0 }, 486 { { 0, 200, 100, -10, 2, 0, 4, "0 2 4 6 96 98 100", "0 2 4 6 8 10 100" }, 487 0, 6, 6, 0, 0 }, 488 }; 489 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_data); ++i) { 490 CreateLayout(test_data[i].common_data); 491 view_model_.MoveViewOnly(test_data[i].from, test_data[i].to); 492 for (int j = 0; j < test_data[i].new_mini_tab_count; ++j) { 493 gfx::Rect bounds; 494 bounds.set_x(j * 5); 495 view_model_.set_ideal_bounds(j, bounds); 496 } 497 layout_->MoveTab(test_data[i].from, test_data[i].to, 498 test_data[i].new_active_index, test_data[i].new_start_x, 499 test_data[i].new_mini_tab_count); 500 EXPECT_EQ(test_data[i].common_data.expected_bounds, BoundsString()) << 501 " at " << i; 502 } 503 } 504 505 // Assertions around IsStacked(). 506 TEST_F(StackedTabStripLayoutTest, IsStacked) { 507 // A single tab with enough space should never be stacked. 508 PrepareChildViews(1); 509 layout_.reset(new StackedTabStripLayout( 510 gfx::Size(100, 10), -10, 2, 4, &view_model_)); 511 Reset(layout_.get(), 0, 400, 0, 0); 512 EXPECT_FALSE(layout_->IsStacked(0)); 513 514 // First tab active, remaining tabs stacked. 515 PrepareChildViews(8); 516 Reset(layout_.get(), 0, 400, 0, 0); 517 EXPECT_FALSE(layout_->IsStacked(0)); 518 EXPECT_TRUE(layout_->IsStacked(7)); 519 520 // Last tab active, preceeding tabs stacked. 521 layout_->SetActiveIndex(7); 522 EXPECT_FALSE(layout_->IsStacked(7)); 523 EXPECT_TRUE(layout_->IsStacked(0)); 524 } 525 526 // Assertions around SetXAndMiniCount. 527 TEST_F(StackedTabStripLayoutTest, SetXAndMiniCount) { 528 // Verifies we don't crash when transitioning to all mini-tabs. 529 PrepareChildViews(1); 530 layout_.reset(new StackedTabStripLayout( 531 gfx::Size(100, 10), -10, 2, 4, &view_model_)); 532 Reset(layout_.get(), 0, 400, 0, 0); 533 layout_->SetXAndMiniCount(0, 1); 534 } 535 536 // Assertions around SetXAndMiniCount. 537 TEST_F(StackedTabStripLayoutTest, SetActiveTabLocation) { 538 struct TestData { 539 struct CommonTestData common_data; 540 const int location; 541 } test_data[] = { 542 // Active tab is the first tab, can't be moved. 543 { { 0, 300, 100, -10, 2, 0, 0, "", "0 90 180 194 196 198 200" }, 50 }, 544 545 // Active tab is pinned; should result in nothing. 546 { { 0, 300, 100, -10, 2, 2, 1, "", "0 0 0 90 180 198 200" }, 199 }, 547 548 // Location is too far to the right, ends up being pushed in. 549 { { 0, 300, 100, -10, 2, 0, 3, "", "0 14 104 194 196 198 200" }, 199 }, 550 551 // Location can be honored. 552 { { 0, 300, 100, -10, 2, 0, 3, "", "0 2 4 40 130 198 200" }, 40 }, 553 }; 554 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_data); ++i) { 555 CreateLayout(test_data[i].common_data); 556 layout_->SetActiveTabLocation(test_data[i].location); 557 EXPECT_EQ(test_data[i].common_data.expected_bounds, BoundsString()) << 558 " at " << i; 559 } 560 } 561