tab_strip_unittest.cc revision 0f1bc08d4cfcc34181b0b5cbf065c40f687bf740
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/tab_strip.h" 6 7#include "base/message_loop/message_loop.h" 8#include "chrome/browser/ui/views/tabs/fake_base_tab_strip_controller.h" 9#include "chrome/browser/ui/views/tabs/tab.h" 10#include "chrome/browser/ui/views/tabs/tab_strip.h" 11#include "chrome/browser/ui/views/tabs/tab_strip_controller.h" 12#include "chrome/browser/ui/views/tabs/tab_strip_observer.h" 13#include "chrome/test/base/testing_profile.h" 14#include "testing/gtest/include/gtest/gtest.h" 15#include "ui/gfx/path.h" 16#include "ui/gfx/rect_conversions.h" 17#include "ui/gfx/skia_util.h" 18#include "ui/views/view.h" 19 20namespace { 21 22// Walks up the views hierarchy until it finds a tab view. It returns the 23// found tab view, on NULL if none is found. 24views::View* FindTabView(views::View* view) { 25 views::View* current = view; 26 while (current && strcmp(current->GetClassName(), Tab::kViewClassName)) { 27 current = current->parent(); 28 } 29 return current; 30} 31 32} // namespace 33 34class TestTabStripObserver : public TabStripObserver { 35 public: 36 explicit TestTabStripObserver(TabStrip* tab_strip) 37 : tab_strip_(tab_strip), 38 last_tab_added_(-1), 39 last_tab_removed_(-1), 40 last_tab_moved_from_(-1), 41 last_tab_moved_to_(-1), 42 tabstrip_deleted_(false) { 43 tab_strip_->AddObserver(this); 44 } 45 46 virtual ~TestTabStripObserver() { 47 if (tab_strip_) 48 tab_strip_->RemoveObserver(this); 49 } 50 51 int last_tab_added() const { return last_tab_added_; } 52 int last_tab_removed() const { return last_tab_removed_; } 53 int last_tab_moved_from() const { return last_tab_moved_from_; } 54 int last_tab_moved_to() const { return last_tab_moved_to_; } 55 bool tabstrip_deleted() const { return tabstrip_deleted_; } 56 57 private: 58 // TabStripObserver overrides. 59 virtual void TabStripAddedTabAt(TabStrip* tab_strip, int index) OVERRIDE { 60 last_tab_added_ = index; 61 } 62 63 virtual void TabStripMovedTab(TabStrip* tab_strip, 64 int from_index, 65 int to_index) OVERRIDE { 66 last_tab_moved_from_ = from_index; 67 last_tab_moved_to_ = to_index; 68 } 69 70 virtual void TabStripRemovedTabAt(TabStrip* tab_strip, int index) OVERRIDE { 71 last_tab_removed_ = index; 72 } 73 74 virtual void TabStripDeleted(TabStrip* tab_strip) OVERRIDE { 75 tabstrip_deleted_ = true; 76 tab_strip_ = NULL; 77 } 78 79 TabStrip* tab_strip_; 80 int last_tab_added_; 81 int last_tab_removed_; 82 int last_tab_moved_from_; 83 int last_tab_moved_to_; 84 bool tabstrip_deleted_; 85 86 DISALLOW_COPY_AND_ASSIGN(TestTabStripObserver); 87}; 88 89class TabStripTest : public testing::Test { 90 public: 91 TabStripTest() 92 : controller_(new FakeBaseTabStripController) { 93 tab_strip_ = new TabStrip(controller_); 94 controller_->set_tab_strip(tab_strip_); 95 // Do this to force TabStrip to create the buttons. 96 parent_.AddChildView(tab_strip_); 97 } 98 99 protected: 100 // Returns the rectangular hit test region of |tab| in |tab|'s local 101 // coordinate space. 102 gfx::Rect GetTabHitTestMask(Tab* tab) { 103 gfx::Path mask; 104 tab->GetHitTestMask(views::View::HIT_TEST_SOURCE_TOUCH, &mask); 105 return gfx::ToEnclosingRect((gfx::SkRectToRectF(mask.getBounds()))); 106 } 107 108 // Returns the rectangular hit test region of the tab close button of 109 // |tab| in |tab|'s coordinate space (including padding if |padding| 110 // is true). 111 gfx::Rect GetTabCloseHitTestMask(Tab* tab, bool padding) { 112 gfx::RectF bounds_f = tab->close_button_->GetContentsBounds(); 113 if (padding) 114 bounds_f = tab->close_button_->GetLocalBounds(); 115 views::View::ConvertRectToTarget(tab->close_button_, tab, &bounds_f); 116 return gfx::ToEnclosingRect(bounds_f); 117 } 118 119 // Checks whether |tab| contains |point_in_tabstrip_coords|, where the point 120 // is in |tab_strip_| coordinates. 121 bool IsPointInTab(Tab* tab, const gfx::Point& point_in_tabstrip_coords) { 122 gfx::Point point_in_tab_coords(point_in_tabstrip_coords); 123 views::View::ConvertPointToTarget(tab_strip_, tab, &point_in_tab_coords); 124 return tab->HitTestPoint(point_in_tab_coords); 125 } 126 127 base::MessageLoopForUI ui_loop_; 128 // Owned by TabStrip. 129 FakeBaseTabStripController* controller_; 130 // Owns |tab_strip_|. 131 views::View parent_; 132 TabStrip* tab_strip_; 133 134 private: 135 DISALLOW_COPY_AND_ASSIGN(TabStripTest); 136}; 137 138TEST_F(TabStripTest, GetModelCount) { 139 EXPECT_EQ(0, tab_strip_->GetModelCount()); 140} 141 142TEST_F(TabStripTest, IsValidModelIndex) { 143 EXPECT_FALSE(tab_strip_->IsValidModelIndex(0)); 144} 145 146TEST_F(TabStripTest, tab_count) { 147 EXPECT_EQ(0, tab_strip_->tab_count()); 148} 149 150TEST_F(TabStripTest, CreateTabForDragging) { 151 // Any result is good, as long as it doesn't crash. 152 scoped_ptr<Tab> tab(tab_strip_->CreateTabForDragging()); 153} 154 155TEST_F(TabStripTest, AddTabAt) { 156 TestTabStripObserver observer(tab_strip_); 157 tab_strip_->AddTabAt(0, TabRendererData(), false); 158 ASSERT_EQ(1, tab_strip_->tab_count()); 159 EXPECT_EQ(0, observer.last_tab_added()); 160 Tab* tab = tab_strip_->tab_at(0); 161 EXPECT_FALSE(tab == NULL); 162} 163 164// Confirms that TabStripObserver::TabStripDeleted() is sent. 165TEST_F(TabStripTest, TabStripDeleted) { 166 FakeBaseTabStripController* controller = new FakeBaseTabStripController; 167 TabStrip* tab_strip = new TabStrip(controller); 168 controller->set_tab_strip(tab_strip); 169 TestTabStripObserver observer(tab_strip); 170 delete tab_strip; 171 EXPECT_TRUE(observer.tabstrip_deleted()); 172} 173 174TEST_F(TabStripTest, MoveTab) { 175 TestTabStripObserver observer(tab_strip_); 176 tab_strip_->AddTabAt(0, TabRendererData(), false); 177 tab_strip_->AddTabAt(1, TabRendererData(), false); 178 tab_strip_->AddTabAt(2, TabRendererData(), false); 179 ASSERT_EQ(3, tab_strip_->tab_count()); 180 EXPECT_EQ(2, observer.last_tab_added()); 181 Tab* tab = tab_strip_->tab_at(0); 182 tab_strip_->MoveTab(0, 1, TabRendererData()); 183 EXPECT_EQ(0, observer.last_tab_moved_from()); 184 EXPECT_EQ(1, observer.last_tab_moved_to()); 185 EXPECT_EQ(tab, tab_strip_->tab_at(1)); 186} 187 188// Verifies child views are deleted after an animation completes. 189TEST_F(TabStripTest, RemoveTab) { 190 TestTabStripObserver observer(tab_strip_); 191 controller_->AddTab(0, false); 192 controller_->AddTab(1, false); 193 const int child_view_count = tab_strip_->child_count(); 194 EXPECT_EQ(2, tab_strip_->tab_count()); 195 controller_->RemoveTab(0); 196 EXPECT_EQ(0, observer.last_tab_removed()); 197 // When removing a tab the tabcount should immediately decrement. 198 EXPECT_EQ(1, tab_strip_->tab_count()); 199 // But the number of views should remain the same (it's animatining closed). 200 EXPECT_EQ(child_view_count, tab_strip_->child_count()); 201 tab_strip_->SetBounds(0, 0, 200, 20); 202 // Layout at a different size should force the animation to end and delete 203 // the tab that was removed. 204 tab_strip_->Layout(); 205 EXPECT_EQ(child_view_count - 1, tab_strip_->child_count()); 206 207 // Remove the last tab to make sure things are cleaned up correctly when 208 // the TabStrip is destroyed and an animation is ongoing. 209 controller_->RemoveTab(0); 210 EXPECT_EQ(0, observer.last_tab_removed()); 211} 212 213TEST_F(TabStripTest, ImmersiveMode) { 214 // Immersive mode defaults to off. 215 EXPECT_FALSE(tab_strip_->IsImmersiveStyle()); 216 217 // Tab strip defaults to normal tab height. 218 int normal_height = Tab::GetMinimumUnselectedSize().height(); 219 EXPECT_EQ(normal_height, tab_strip_->GetPreferredSize().height()); 220 221 // Tab strip can toggle immersive mode. 222 tab_strip_->SetImmersiveStyle(true); 223 EXPECT_TRUE(tab_strip_->IsImmersiveStyle()); 224 225 // Now tabs have the immersive height. 226 int immersive_height = Tab::GetImmersiveHeight(); 227 EXPECT_EQ(immersive_height, tab_strip_->GetPreferredSize().height()); 228 229 // Sanity-check immersive tabs are shorter than normal tabs. 230 EXPECT_LT(immersive_height, normal_height); 231} 232 233// Creates a tab strip in stacked layout mode and verifies the correctness 234// of hit tests against the visible/occluded regions of a tab and 235// visible/occluded tab close buttons. 236TEST_F(TabStripTest, TabHitTestMaskWhenStacked) { 237 tab_strip_->SetBounds(0, 0, 300, 20); 238 239 controller_->AddTab(0, false); 240 controller_->AddTab(1, true); 241 controller_->AddTab(2, false); 242 controller_->AddTab(3, false); 243 ASSERT_EQ(4, tab_strip_->tab_count()); 244 245 Tab* left_tab = tab_strip_->tab_at(0); 246 left_tab->SetBoundsRect(gfx::Rect(gfx::Point(0, 0), gfx::Size(200, 20))); 247 248 Tab* active_tab = tab_strip_->tab_at(1); 249 active_tab->SetBoundsRect(gfx::Rect(gfx::Point(150, 0), gfx::Size(200, 20))); 250 ASSERT_TRUE(active_tab->IsActive()); 251 252 Tab* right_tab = tab_strip_->tab_at(2); 253 right_tab->SetBoundsRect(gfx::Rect(gfx::Point(300, 0), gfx::Size(200, 20))); 254 255 Tab* most_right_tab = tab_strip_->tab_at(3); 256 most_right_tab->SetBoundsRect(gfx::Rect(gfx::Point(450, 0), 257 gfx::Size(200, 20))); 258 259 // Switch to stacked layout mode and force a layout to ensure tabs stack. 260 tab_strip_->SetLayoutType(TAB_STRIP_LAYOUT_STACKED, false); 261 tab_strip_->DoLayout(); 262 263 264 // Tests involving |left_tab|, which has part of its bounds and its tab 265 // close button occluded by |active_tab|. 266 267 // Bounds of the tab's hit test mask. 268 gfx::Rect tab_bounds = GetTabHitTestMask(left_tab); 269 EXPECT_EQ(gfx::Rect(6, 2, 61, 27).ToString(), tab_bounds.ToString()); 270 271 // Bounds of the tab close button (without padding) in the tab's 272 // coordinate space. 273 gfx::Rect contents_bounds = GetTabCloseHitTestMask(left_tab, false); 274 // TODO(tdanderson): Uncomment this line once crbug.com/311609 is resolved. 275 //EXPECT_EQ(gfx::Rect(84, 8, 18, 18).ToString(), contents_bounds.ToString()); 276 277 // Verify that the tab close button is occluded. 278 EXPECT_FALSE(tab_bounds.Contains(contents_bounds)); 279 280 // Hit tests in the non-occuluded region of the tab. 281 EXPECT_TRUE(left_tab->HitTestRect(gfx::Rect(6, 2, 2, 2))); 282 EXPECT_TRUE(left_tab->HitTestRect(gfx::Rect(6, 2, 1, 1))); 283 EXPECT_TRUE(left_tab->HitTestRect(gfx::Rect(30, 15, 1, 1))); 284 EXPECT_TRUE(left_tab->HitTestRect(gfx::Rect(30, 15, 25, 35))); 285 EXPECT_TRUE(left_tab->HitTestRect(gfx::Rect(-10, -5, 20, 30))); 286 287 // Hit tests in the occluded region of the tab. 288 EXPECT_FALSE(left_tab->HitTestRect(gfx::Rect(70, 15, 2, 2))); 289 EXPECT_FALSE(left_tab->HitTestRect(gfx::Rect(70, -15, 30, 40))); 290 EXPECT_FALSE(left_tab->HitTestRect(gfx::Rect(87, 20, 5, 3))); 291 292 // Hit tests completely outside of the tab. 293 EXPECT_FALSE(left_tab->HitTestRect(gfx::Rect(-20, -25, 1, 1))); 294 EXPECT_FALSE(left_tab->HitTestRect(gfx::Rect(-20, -25, 3, 19))); 295 296 // All hit tests against the tab close button should fail because 297 // it is occluded by |active_tab|. 298 views::ImageButton* left_close = left_tab->close_button_; 299 EXPECT_FALSE(left_close->HitTestRect(gfx::Rect(1, 1, 1, 1))); 300 EXPECT_FALSE(left_close->HitTestRect(gfx::Rect(1, 1, 5, 10))); 301 EXPECT_FALSE(left_close->HitTestRect(gfx::Rect(10, 10, 1, 1))); 302 EXPECT_FALSE(left_close->HitTestRect(gfx::Rect(10, 10, 3, 4))); 303 304 305 // Tests involving |active_tab|, which is completely visible. 306 307 tab_bounds = GetTabHitTestMask(active_tab); 308 EXPECT_EQ(gfx::Rect(6, 2, 108, 27).ToString(), tab_bounds.ToString()); 309 contents_bounds = GetTabCloseHitTestMask(active_tab, false); 310 // TODO(tdanderson): Uncomment this line once crbug.com/311609 is resolved. 311 //EXPECT_EQ(gfx::Rect(84, 8, 18, 18).ToString(), contents_bounds.ToString()); 312 313 // Verify that the tab close button is not occluded. 314 EXPECT_TRUE(tab_bounds.Contains(contents_bounds)); 315 316 // Bounds of the tab close button (without padding) in the tab's 317 // coordinate space. 318 gfx::Rect local_bounds = GetTabCloseHitTestMask(active_tab, true); 319 EXPECT_EQ(gfx::Rect(81, 0, 39, 29).ToString(), local_bounds.ToString()); 320 321 // Hit tests within the tab. 322 EXPECT_TRUE(active_tab->HitTestRect(gfx::Rect(30, 15, 1, 1))); 323 EXPECT_TRUE(active_tab->HitTestRect(gfx::Rect(30, 15, 2, 2))); 324 325 // Hit tests against the tab close button. Note that if the hit test 326 // source is a mouse, a hit test within the button's padding should fail. 327 views::ImageButton* active_close = active_tab->close_button_; 328 EXPECT_FALSE(active_close->HitTestRect(gfx::Rect(1, 1, 1, 1))); 329 EXPECT_TRUE(active_close->HitTestRect(gfx::Rect(1, 1, 2, 2))); 330 EXPECT_TRUE(active_close->HitTestRect(gfx::Rect(10, 10, 1, 1))); 331 EXPECT_TRUE(active_close->HitTestRect(gfx::Rect(10, 10, 25, 35))); 332 333 334 // Tests involving |most_right_tab|, which has part of its bounds occluded 335 // by |right_tab| but has its tab close button completely visible. 336 337 tab_bounds = GetTabHitTestMask(most_right_tab); 338 EXPECT_EQ(gfx::Rect(84, 2, 30, 27).ToString(), tab_bounds.ToString()); 339 contents_bounds = GetTabCloseHitTestMask(active_tab, false); 340 // TODO(tdanderson): Uncomment this line once crbug.com/311609 is resolved. 341 //EXPECT_EQ(gfx::Rect(84, 8, 18, 18).ToString(), contents_bounds.ToString()); 342 local_bounds = GetTabCloseHitTestMask(active_tab, true); 343 EXPECT_EQ(gfx::Rect(81, 0, 39, 29).ToString(), local_bounds.ToString()); 344 345 // Verify that the tab close button is not occluded. 346 EXPECT_TRUE(tab_bounds.Contains(contents_bounds)); 347 348 // Hit tests in the occluded region of the tab. 349 EXPECT_FALSE(most_right_tab->HitTestRect(gfx::Rect(20, 15, 1, 1))); 350 EXPECT_FALSE(most_right_tab->HitTestRect(gfx::Rect(20, 15, 5, 6))); 351 352 // Hit tests in the non-occluded region of the tab. 353 EXPECT_TRUE(most_right_tab->HitTestRect(gfx::Rect(85, 15, 1, 1))); 354 EXPECT_TRUE(most_right_tab->HitTestRect(gfx::Rect(85, 15, 2, 2))); 355 356 // Hit tests against the tab close button. Note that if the hit test 357 // source is a mouse, a hit test within the button's padding should fail. 358 views::ImageButton* most_right_close = most_right_tab->close_button_; 359 EXPECT_FALSE(most_right_close->HitTestRect(gfx::Rect(1, 1, 1, 1))); 360 EXPECT_TRUE(most_right_close->HitTestRect(gfx::Rect(1, 1, 2, 2))); 361 EXPECT_TRUE(most_right_close->HitTestRect(gfx::Rect(10, 10, 1, 1))); 362 EXPECT_TRUE(most_right_close->HitTestRect(gfx::Rect(10, 10, 25, 35))); 363 EXPECT_TRUE(most_right_close->HitTestRect(gfx::Rect(-10, 10, 25, 35))); 364} 365 366TEST_F(TabStripTest, GetEventHandlerForOverlappingArea) { 367 tab_strip_->SetBounds(0, 0, 1000, 20); 368 369 controller_->AddTab(0, false); 370 controller_->AddTab(1, true); 371 controller_->AddTab(2, false); 372 controller_->AddTab(3, false); 373 ASSERT_EQ(4, tab_strip_->tab_count()); 374 375 // Verify that the active tab will be a tooltip handler for points that hit 376 // it. 377 Tab* left_tab = tab_strip_->tab_at(0); 378 left_tab->SetBoundsRect(gfx::Rect(gfx::Point(0, 0), gfx::Size(200, 20))); 379 380 Tab* active_tab = tab_strip_->tab_at(1); 381 active_tab->SetBoundsRect(gfx::Rect(gfx::Point(150, 0), gfx::Size(200, 20))); 382 ASSERT_TRUE(active_tab->IsActive()); 383 384 Tab* right_tab = tab_strip_->tab_at(2); 385 right_tab->SetBoundsRect(gfx::Rect(gfx::Point(300, 0), gfx::Size(200, 20))); 386 387 Tab* most_right_tab = tab_strip_->tab_at(3); 388 most_right_tab->SetBoundsRect(gfx::Rect(gfx::Point(450, 0), 389 gfx::Size(200, 20))); 390 391 // Test that active tabs gets events from area in which it overlaps with its 392 // left neighbour. 393 gfx::Point left_overlap( 394 (active_tab->x() + left_tab->bounds().right() + 1) / 2, 395 active_tab->bounds().bottom() - 1); 396 397 // Sanity check that the point is in both active and left tab. 398 ASSERT_TRUE(IsPointInTab(active_tab, left_overlap)); 399 ASSERT_TRUE(IsPointInTab(left_tab, left_overlap)); 400 401 EXPECT_EQ(active_tab, 402 FindTabView(tab_strip_->GetEventHandlerForPoint(left_overlap))); 403 404 // Test that active tabs gets events from area in which it overlaps with its 405 // right neighbour. 406 gfx::Point right_overlap((active_tab->bounds().right() + right_tab->x()) / 2, 407 active_tab->bounds().bottom() - 1); 408 409 // Sanity check that the point is in both active and right tab. 410 ASSERT_TRUE(IsPointInTab(active_tab, right_overlap)); 411 ASSERT_TRUE(IsPointInTab(right_tab, right_overlap)); 412 413 EXPECT_EQ(active_tab, 414 FindTabView(tab_strip_->GetEventHandlerForPoint(right_overlap))); 415 416 // Test that if neither of tabs is active, the left one is selected. 417 gfx::Point unactive_overlap( 418 (right_tab->x() + most_right_tab->bounds().right() + 1) / 2, 419 right_tab->bounds().bottom() - 1); 420 421 // Sanity check that the point is in both active and left tab. 422 ASSERT_TRUE(IsPointInTab(right_tab, unactive_overlap)); 423 ASSERT_TRUE(IsPointInTab(most_right_tab, unactive_overlap)); 424 425 EXPECT_EQ(right_tab, 426 FindTabView(tab_strip_->GetEventHandlerForPoint(unactive_overlap))); 427} 428 429TEST_F(TabStripTest, GetTooltipHandler) { 430 tab_strip_->SetBounds(0, 0, 1000, 20); 431 432 controller_->AddTab(0, false); 433 controller_->AddTab(1, true); 434 controller_->AddTab(2, false); 435 controller_->AddTab(3, false); 436 ASSERT_EQ(4, tab_strip_->tab_count()); 437 438 // Verify that the active tab will be a tooltip handler for points that hit 439 // it. 440 Tab* left_tab = tab_strip_->tab_at(0); 441 left_tab->SetBoundsRect(gfx::Rect(gfx::Point(0, 0), gfx::Size(200, 20))); 442 443 Tab* active_tab = tab_strip_->tab_at(1); 444 active_tab->SetBoundsRect(gfx::Rect(gfx::Point(150, 0), gfx::Size(200, 20))); 445 ASSERT_TRUE(active_tab->IsActive()); 446 447 Tab* right_tab = tab_strip_->tab_at(2); 448 right_tab->SetBoundsRect(gfx::Rect(gfx::Point(300, 0), gfx::Size(200, 20))); 449 450 Tab* most_right_tab = tab_strip_->tab_at(3); 451 most_right_tab->SetBoundsRect(gfx::Rect(gfx::Point(450, 0), 452 gfx::Size(200, 20))); 453 454 // Test that active_tab handles tooltips from area in which it overlaps with 455 // its left neighbour. 456 gfx::Point left_overlap( 457 (active_tab->x() + left_tab->bounds().right() + 1) / 2, 458 active_tab->bounds().bottom() - 1); 459 460 // Sanity check that the point is in both active and left tab. 461 ASSERT_TRUE(IsPointInTab(active_tab, left_overlap)); 462 ASSERT_TRUE(IsPointInTab(left_tab, left_overlap)); 463 464 EXPECT_EQ(active_tab, 465 FindTabView(tab_strip_->GetTooltipHandlerForPoint(left_overlap))); 466 467 // Test that active_tab handles tooltips from area in which it overlaps with 468 // its right neighbour. 469 gfx::Point right_overlap((active_tab->bounds().right() + right_tab->x()) / 2, 470 active_tab->bounds().bottom() - 1); 471 472 // Sanity check that the point is in both active and right tab. 473 ASSERT_TRUE(IsPointInTab(active_tab, right_overlap)); 474 ASSERT_TRUE(IsPointInTab(right_tab, right_overlap)); 475 476 EXPECT_EQ(active_tab, 477 FindTabView(tab_strip_->GetTooltipHandlerForPoint(right_overlap))); 478 479 // Test that if neither of tabs is active, the left one is selected. 480 gfx::Point unactive_overlap( 481 (right_tab->x() + most_right_tab->bounds().right() + 1) / 2, 482 right_tab->bounds().bottom() - 1); 483 484 // Sanity check that the point is in both active and left tab. 485 ASSERT_TRUE(IsPointInTab(right_tab, unactive_overlap)); 486 ASSERT_TRUE(IsPointInTab(most_right_tab, unactive_overlap)); 487 488 EXPECT_EQ( 489 right_tab, 490 FindTabView(tab_strip_->GetTooltipHandlerForPoint(unactive_overlap))); 491 492 // Confirm that tab strip doe not return tooltip handler for points that 493 // don't hit it. 494 EXPECT_FALSE(tab_strip_->GetTooltipHandlerForPoint(gfx::Point(-1, 2))); 495} 496