tab_unittest.cc revision 868fa2fe829687343ffae624259930155e16dbd8
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.h" 6#include "chrome/browser/ui/views/tabs/tab_controller.h" 7 8#include "base/strings/utf_string_conversions.h" 9#include "testing/gtest/include/gtest/gtest.h" 10#include "ui/base/models/list_selection_model.h" 11#include "ui/views/controls/button/image_button.h" 12#include "ui/views/test/views_test_base.h" 13#include "ui/views/widget/widget.h" 14 15using views::Widget; 16 17class FakeTabController : public TabController { 18 public: 19 FakeTabController() : immersive_style_(false) { 20 } 21 virtual ~FakeTabController() {} 22 23 void set_immersive_style(bool value) { immersive_style_ = value; } 24 25 virtual const ui::ListSelectionModel& GetSelectionModel() OVERRIDE { 26 return selection_model_; 27 } 28 virtual bool SupportsMultipleSelection() OVERRIDE { return false; } 29 virtual void SelectTab(Tab* tab) OVERRIDE {} 30 virtual void ExtendSelectionTo(Tab* tab) OVERRIDE {} 31 virtual void ToggleSelected(Tab* tab) OVERRIDE {} 32 virtual void AddSelectionFromAnchorTo(Tab* tab) OVERRIDE {} 33 virtual void CloseTab(Tab* tab, CloseTabSource source) OVERRIDE {} 34 virtual void ShowContextMenuForTab(Tab* tab, 35 const gfx::Point& p) OVERRIDE {} 36 virtual bool IsActiveTab(const Tab* tab) const OVERRIDE { return false; } 37 virtual bool IsTabSelected(const Tab* tab) const OVERRIDE { 38 return false; 39 } 40 virtual bool IsTabPinned(const Tab* tab) const OVERRIDE { return false; } 41 virtual void MaybeStartDrag( 42 Tab* tab, 43 const ui::LocatedEvent& event, 44 const ui::ListSelectionModel& original_selection) OVERRIDE {} 45 virtual void ContinueDrag(views::View* view, 46 const ui::LocatedEvent& event) OVERRIDE {} 47 virtual bool EndDrag(EndDragReason reason) OVERRIDE { return false; } 48 virtual Tab* GetTabAt(Tab* tab, 49 const gfx::Point& tab_in_tab_coordinates) OVERRIDE { 50 return NULL; 51 } 52 virtual void OnMouseEventInTab(views::View* source, 53 const ui::MouseEvent& event) OVERRIDE {} 54 virtual bool ShouldPaintTab(const Tab* tab, gfx::Rect* clip) OVERRIDE { 55 return true; 56 } 57 virtual bool IsImmersiveStyle() const OVERRIDE { return immersive_style_; } 58 59 private: 60 ui::ListSelectionModel selection_model_; 61 bool immersive_style_; 62 63 DISALLOW_COPY_AND_ASSIGN(FakeTabController); 64}; 65 66class TabTest : public views::ViewsTestBase { 67 public: 68 TabTest() {} 69 virtual ~TabTest() {} 70 71 static bool IconAnimationInvariant(const Tab& tab) { 72 bool capture_invariant = 73 tab.data().CaptureActive() == (tab.icon_animation_.get() != NULL); 74 bool audio_invariant = 75 !tab.data().AudioActive() || tab.tab_audio_indicator_->IsAnimating(); 76 return capture_invariant && audio_invariant; 77 } 78}; 79 80TEST_F(TabTest, HitTestTopPixel) { 81 Widget widget; 82 Widget::InitParams params(CreateParams(Widget::InitParams::TYPE_WINDOW)); 83 params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; 84 params.bounds.SetRect(10, 20, 300, 400); 85 widget.Init(params); 86 87 FakeTabController tab_controller; 88 Tab tab(&tab_controller); 89 widget.GetContentsView()->AddChildView(&tab); 90 tab.SetBoundsRect(gfx::Rect(gfx::Point(0, 0), Tab::GetStandardSize())); 91 92 // Tabs have some shadow in the top, so by default we don't hit the tab there. 93 int middle_x = tab.width() / 2; 94 EXPECT_FALSE(tab.HitTestPoint(gfx::Point(middle_x, 0))); 95 96 // Tabs are slanted, so a click halfway down the left edge won't hit it. 97 int middle_y = tab.height() / 2; 98 EXPECT_FALSE(tab.HitTestPoint(gfx::Point(0, middle_y))); 99 100 // If the window is maximized, however, we want clicks in the top edge to 101 // select the tab. 102 widget.Maximize(); 103 EXPECT_TRUE(tab.HitTestPoint(gfx::Point(middle_x, 0))); 104 105 // But clicks in the area above the slanted sides should still miss. 106 EXPECT_FALSE(tab.HitTestPoint(gfx::Point(0, 0))); 107 EXPECT_FALSE(tab.HitTestPoint(gfx::Point(tab.width() - 1, 0))); 108} 109 110// Regression test for http://crbug.com/226253. Calling Layout() more than once 111// shouldn't change the insets of the close button. 112TEST_F(TabTest, CloseButtonLayout) { 113 FakeTabController tab_controller; 114 Tab tab(&tab_controller); 115 tab.SetBounds(0, 0, 100, 50); 116 tab.Layout(); 117 gfx::Insets close_button_insets = tab.close_button_->GetInsets(); 118 tab.Layout(); 119 gfx::Insets close_button_insets_2 = tab.close_button_->GetInsets(); 120 EXPECT_EQ(close_button_insets.top(), close_button_insets_2.top()); 121 EXPECT_EQ(close_button_insets.left(), close_button_insets_2.left()); 122 EXPECT_EQ(close_button_insets.bottom(), close_button_insets_2.bottom()); 123 EXPECT_EQ(close_button_insets.right(), close_button_insets_2.right()); 124 125 // Also make sure the close button is sized as large as the tab. 126 EXPECT_EQ(50, tab.close_button_->bounds().height()); 127} 128 129TEST_F(TabTest, ActivityIndicators) { 130 FakeTabController controller; 131 Tab tab(&controller); 132 133 SkBitmap bitmap; 134 bitmap.setConfig(SkBitmap::kARGB_8888_Config, 16, 16); 135 bitmap.allocPixels(); 136 137 TabRendererData data; 138 data.favicon = gfx::ImageSkia::CreateFrom1xBitmap(bitmap); 139 tab.SetData(data); 140 141 // Audio starts and stops. 142 data.audio_state = TabRendererData::AUDIO_STATE_PLAYING; 143 tab.SetData(data); 144 EXPECT_TRUE(IconAnimationInvariant(tab)); 145 EXPECT_EQ(TabRendererData::AUDIO_STATE_PLAYING, tab.data().audio_state); 146 EXPECT_EQ(TabRendererData::CAPTURE_STATE_NONE, tab.data().capture_state); 147 data.audio_state = TabRendererData::AUDIO_STATE_NONE; 148 tab.SetData(data); 149 EXPECT_TRUE(IconAnimationInvariant(tab)); 150 EXPECT_EQ(TabRendererData::AUDIO_STATE_NONE, tab.data().audio_state); 151 EXPECT_EQ(TabRendererData::CAPTURE_STATE_NONE, tab.data().capture_state); 152 EXPECT_TRUE(IconAnimationInvariant(tab)); 153 154 // Capture starts and stops. 155 data.capture_state = TabRendererData::CAPTURE_STATE_RECORDING; 156 tab.SetData(data); 157 EXPECT_TRUE(IconAnimationInvariant(tab)); 158 EXPECT_EQ(TabRendererData::AUDIO_STATE_NONE, tab.data().audio_state); 159 EXPECT_EQ(TabRendererData::CAPTURE_STATE_RECORDING, tab.data().capture_state); 160 data.capture_state = TabRendererData::CAPTURE_STATE_NONE; 161 tab.SetData(data); 162 EXPECT_TRUE(IconAnimationInvariant(tab)); 163 EXPECT_EQ(TabRendererData::AUDIO_STATE_NONE, tab.data().audio_state); 164 EXPECT_EQ(TabRendererData::CAPTURE_STATE_NONE, tab.data().capture_state); 165 EXPECT_TRUE(IconAnimationInvariant(tab)); 166 167 // Audio starts then capture starts, then audio stops then capture stops. 168 data.audio_state = TabRendererData::AUDIO_STATE_PLAYING; 169 tab.SetData(data); 170 data.capture_state = TabRendererData::CAPTURE_STATE_RECORDING; 171 tab.SetData(data); 172 EXPECT_TRUE(IconAnimationInvariant(tab)); 173 EXPECT_EQ(TabRendererData::AUDIO_STATE_PLAYING, tab.data().audio_state); 174 EXPECT_EQ(TabRendererData::CAPTURE_STATE_RECORDING, tab.data().capture_state); 175 176 data.title = ASCIIToUTF16("test X"); 177 tab.SetData(data); 178 EXPECT_TRUE(IconAnimationInvariant(tab)); 179 180 data.audio_state = TabRendererData::AUDIO_STATE_NONE; 181 tab.SetData(data); 182 EXPECT_TRUE(IconAnimationInvariant(tab)); 183 EXPECT_EQ(TabRendererData::CAPTURE_STATE_RECORDING, tab.data().capture_state); 184 data.capture_state = TabRendererData::CAPTURE_STATE_NONE; 185 tab.SetData(data); 186 EXPECT_TRUE(IconAnimationInvariant(tab)); 187 EXPECT_EQ(TabRendererData::AUDIO_STATE_NONE, tab.data().audio_state); 188 EXPECT_EQ(TabRendererData::CAPTURE_STATE_NONE, tab.data().capture_state); 189 190 // Audio starts then capture starts, then capture stops then audio stops. 191 data.audio_state = TabRendererData::AUDIO_STATE_PLAYING; 192 tab.SetData(data); 193 data.capture_state = TabRendererData::CAPTURE_STATE_RECORDING; 194 tab.SetData(data); 195 EXPECT_TRUE(IconAnimationInvariant(tab)); 196 EXPECT_EQ(TabRendererData::AUDIO_STATE_PLAYING, tab.data().audio_state); 197 EXPECT_EQ(TabRendererData::CAPTURE_STATE_RECORDING, tab.data().capture_state); 198 199 data.title = ASCIIToUTF16("test Y"); 200 tab.SetData(data); 201 EXPECT_TRUE(IconAnimationInvariant(tab)); 202 203 data.capture_state = TabRendererData::CAPTURE_STATE_NONE; 204 tab.SetData(data); 205 EXPECT_TRUE(IconAnimationInvariant(tab)); 206 EXPECT_EQ(TabRendererData::CAPTURE_STATE_NONE, tab.data().capture_state); 207 208 data.audio_state = TabRendererData::AUDIO_STATE_NONE; 209 tab.SetData(data); 210 EXPECT_TRUE(IconAnimationInvariant(tab)); 211 EXPECT_EQ(TabRendererData::AUDIO_STATE_NONE, tab.data().audio_state); 212 EXPECT_EQ(TabRendererData::CAPTURE_STATE_NONE, tab.data().capture_state); 213 EXPECT_TRUE(IconAnimationInvariant(tab)); 214} 215