1 // Copyright 2013 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/sync/one_click_signin_bubble_view.h" 6 7 #include "base/bind.h" 8 #include "base/bind_helpers.h" 9 #include "base/memory/scoped_ptr.h" 10 #include "chrome/browser/ui/sync/one_click_signin_bubble_delegate.h" 11 #include "chrome/test/base/ui_test_utils.h" 12 #include "ui/views/controls/button/label_button.h" 13 #include "ui/views/test/views_test_base.h" 14 #include "ui/views/widget/widget.h" 15 16 class OneClickSigninBubbleViewTest : public views::ViewsTestBase { 17 public: 18 OneClickSigninBubbleViewTest() 19 : on_start_sync_called_(false), 20 mode_(OneClickSigninSyncStarter::CONFIGURE_SYNC_FIRST), 21 bubble_learn_more_click_count_(0), 22 dialog_learn_more_click_count_(0), 23 advanced_click_count_(0), 24 anchor_widget_(NULL) { 25 } 26 27 virtual void SetUp() OVERRIDE { 28 views::ViewsTestBase::SetUp(); 29 30 // Create a widget to host the anchor view. 31 anchor_widget_ = new views::Widget; 32 views::Widget::InitParams widget_params = CreateParams( 33 views::Widget::InitParams::TYPE_WINDOW); 34 anchor_widget_->Init(widget_params); 35 anchor_widget_->Show(); 36 } 37 38 virtual void TearDown() OVERRIDE { 39 OneClickSigninBubbleView::Hide(); 40 anchor_widget_->Close(); 41 anchor_widget_ = NULL; 42 views::ViewsTestBase::TearDown(); 43 } 44 45 protected: 46 OneClickSigninBubbleView* ShowOneClickSigninBubble( 47 BrowserWindow::OneClickSigninBubbleType bubble_type) { 48 49 scoped_ptr<OneClickSigninBubbleDelegate> delegate; 50 delegate.reset(new OneClickSigninBubbleTestDelegate(this)); 51 52 OneClickSigninBubbleView::ShowBubble( 53 bubble_type, 54 base::string16(), 55 base::string16(), 56 delegate.Pass(), 57 anchor_widget_->GetContentsView(), 58 base::Bind(&OneClickSigninBubbleViewTest::OnStartSync, 59 base::Unretained(this))); 60 61 OneClickSigninBubbleView* view = 62 OneClickSigninBubbleView::view_for_testing(); 63 EXPECT_TRUE(view != NULL); 64 return view; 65 } 66 67 void OnStartSync(OneClickSigninSyncStarter::StartSyncMode mode) { 68 on_start_sync_called_ = true; 69 mode_ = mode; 70 } 71 72 bool on_start_sync_called_; 73 OneClickSigninSyncStarter::StartSyncMode mode_; 74 int bubble_learn_more_click_count_; 75 int dialog_learn_more_click_count_; 76 int advanced_click_count_; 77 78 private: 79 friend class OneClickSigninBubbleTestDelegate; 80 81 class OneClickSigninBubbleTestDelegate 82 : public OneClickSigninBubbleDelegate { 83 public: 84 // |test| is not owned by this object. 85 explicit OneClickSigninBubbleTestDelegate( 86 OneClickSigninBubbleViewTest* test) : test_(test) {} 87 88 // OneClickSigninBubbleDelegate: 89 virtual void OnLearnMoreLinkClicked(bool is_dialog) OVERRIDE { 90 if (is_dialog) 91 ++test_->dialog_learn_more_click_count_; 92 else 93 ++test_->bubble_learn_more_click_count_; 94 } 95 virtual void OnAdvancedLinkClicked() OVERRIDE { 96 ++test_->advanced_click_count_; 97 } 98 99 private: 100 OneClickSigninBubbleViewTest* test_; 101 102 DISALLOW_COPY_AND_ASSIGN(OneClickSigninBubbleTestDelegate); 103 }; 104 105 // Widget to host the anchor view of the bubble. Destroys itself when closed. 106 views::Widget* anchor_widget_; 107 108 DISALLOW_COPY_AND_ASSIGN(OneClickSigninBubbleViewTest); 109 }; 110 111 TEST_F(OneClickSigninBubbleViewTest, ShowBubble) { 112 ShowOneClickSigninBubble(BrowserWindow::ONE_CLICK_SIGNIN_BUBBLE_TYPE_BUBBLE); 113 content::RunAllPendingInMessageLoop(); 114 EXPECT_TRUE(OneClickSigninBubbleView::IsShowing()); 115 } 116 117 TEST_F(OneClickSigninBubbleViewTest, ShowDialog) { 118 ShowOneClickSigninBubble( 119 BrowserWindow::ONE_CLICK_SIGNIN_BUBBLE_TYPE_MODAL_DIALOG); 120 content::RunAllPendingInMessageLoop(); 121 EXPECT_TRUE(OneClickSigninBubbleView::IsShowing()); 122 } 123 124 TEST_F(OneClickSigninBubbleViewTest, HideBubble) { 125 ShowOneClickSigninBubble(BrowserWindow::ONE_CLICK_SIGNIN_BUBBLE_TYPE_BUBBLE); 126 127 OneClickSigninBubbleView::Hide(); 128 content::RunAllPendingInMessageLoop(); 129 EXPECT_FALSE(OneClickSigninBubbleView::IsShowing()); 130 } 131 132 TEST_F(OneClickSigninBubbleViewTest, HideDialog) { 133 ShowOneClickSigninBubble( 134 BrowserWindow::ONE_CLICK_SIGNIN_BUBBLE_TYPE_MODAL_DIALOG); 135 136 OneClickSigninBubbleView::Hide(); 137 content::RunAllPendingInMessageLoop(); 138 EXPECT_FALSE(OneClickSigninBubbleView::IsShowing()); 139 EXPECT_TRUE(on_start_sync_called_); 140 EXPECT_EQ(OneClickSigninSyncStarter::UNDO_SYNC, mode_); 141 } 142 143 TEST_F(OneClickSigninBubbleViewTest, BubbleOkButton) { 144 OneClickSigninBubbleView* view = 145 ShowOneClickSigninBubble( 146 BrowserWindow::ONE_CLICK_SIGNIN_BUBBLE_TYPE_BUBBLE); 147 148 // Simulate pressing the OK button. Set the message loop in the bubble 149 // view so that it can be quit once the bubble is hidden. 150 views::ButtonListener* listener = view; 151 const ui::MouseEvent event(ui::ET_MOUSE_PRESSED, 152 gfx::Point(), gfx::Point(), 153 0, 0); 154 listener->ButtonPressed(view->ok_button_, event); 155 156 // View should no longer be showing. The message loop will exit once the 157 // fade animation of the bubble is done. 158 content::RunAllPendingInMessageLoop(); 159 EXPECT_FALSE(OneClickSigninBubbleView::IsShowing()); 160 } 161 162 TEST_F(OneClickSigninBubbleViewTest, DialogOkButton) { 163 OneClickSigninBubbleView* view = ShowOneClickSigninBubble( 164 BrowserWindow::ONE_CLICK_SIGNIN_BUBBLE_TYPE_MODAL_DIALOG); 165 166 // Simulate pressing the OK button. Set the message loop in the bubble 167 // view so that it can be quit once the bubble is hidden. 168 views::ButtonListener* listener = view; 169 const ui::MouseEvent event(ui::ET_MOUSE_PRESSED, 170 gfx::Point(), gfx::Point(), 171 0, 0); 172 listener->ButtonPressed(view->ok_button_, event); 173 174 // View should no longer be showing and sync should start 175 // The message loop will exit once the fade animation of the dialog is done. 176 content::RunAllPendingInMessageLoop(); 177 EXPECT_FALSE(OneClickSigninBubbleView::IsShowing()); 178 EXPECT_TRUE(on_start_sync_called_); 179 EXPECT_EQ(OneClickSigninSyncStarter::SYNC_WITH_DEFAULT_SETTINGS, mode_); 180 } 181 182 TEST_F(OneClickSigninBubbleViewTest, DialogUndoButton) { 183 OneClickSigninBubbleView* view = ShowOneClickSigninBubble( 184 BrowserWindow::ONE_CLICK_SIGNIN_BUBBLE_TYPE_MODAL_DIALOG); 185 186 // Simulate pressing the undo button. Set the message loop in the bubble 187 // view so that it can be quit once the bubble is hidden. 188 views::ButtonListener* listener = view; 189 const ui::MouseEvent event(ui::ET_MOUSE_PRESSED, 190 gfx::Point(), gfx::Point(), 191 0, 0); 192 listener->ButtonPressed(view->undo_button_, event); 193 194 // View should no longer be showing. The message loop will exit once the 195 // fade animation of the bubble is done. 196 content::RunAllPendingInMessageLoop(); 197 EXPECT_FALSE(OneClickSigninBubbleView::IsShowing()); 198 EXPECT_TRUE(on_start_sync_called_); 199 EXPECT_EQ(OneClickSigninSyncStarter::UNDO_SYNC, mode_); 200 } 201 202 TEST_F(OneClickSigninBubbleViewTest, BubbleAdvancedLink) { 203 OneClickSigninBubbleView* view = ShowOneClickSigninBubble( 204 BrowserWindow::ONE_CLICK_SIGNIN_BUBBLE_TYPE_BUBBLE); 205 206 // Simulate pressing a link in the bubble. 207 views::LinkListener* listener = view; 208 listener->LinkClicked(view->advanced_link_, 0); 209 210 // View should no longer be showing and the OnAdvancedLinkClicked method 211 // of the delegate should have been called. 212 content::RunAllPendingInMessageLoop(); 213 EXPECT_FALSE(OneClickSigninBubbleView::IsShowing()); 214 EXPECT_EQ(1, advanced_click_count_); 215 } 216 217 TEST_F(OneClickSigninBubbleViewTest, DialogAdvancedLink) { 218 OneClickSigninBubbleView* view = ShowOneClickSigninBubble( 219 BrowserWindow::ONE_CLICK_SIGNIN_BUBBLE_TYPE_MODAL_DIALOG); 220 221 // Simulate pressing a link in the bubble. 222 views::LinkListener* listener = view; 223 listener->LinkClicked(view->advanced_link_, 0); 224 225 // View should no longer be showing. No delegate method should have been 226 // called: the callback is responsible to open the settings page. 227 content::RunAllPendingInMessageLoop(); 228 EXPECT_TRUE(on_start_sync_called_); 229 EXPECT_EQ(OneClickSigninSyncStarter::CONFIGURE_SYNC_FIRST, mode_); 230 EXPECT_FALSE(OneClickSigninBubbleView::IsShowing()); 231 EXPECT_EQ(0, advanced_click_count_); 232 } 233 234 TEST_F(OneClickSigninBubbleViewTest, BubbleLearnMoreLink) { 235 OneClickSigninBubbleView* view = ShowOneClickSigninBubble( 236 BrowserWindow::ONE_CLICK_SIGNIN_BUBBLE_TYPE_BUBBLE); 237 238 views::LinkListener* listener = view; 239 listener->LinkClicked(view->learn_more_link_, 0); 240 241 // View should no longer be showing and the OnLearnMoreLinkClicked method 242 // of the delegate should have been called with |is_dialog| == false. 243 content::RunAllPendingInMessageLoop(); 244 EXPECT_FALSE(OneClickSigninBubbleView::IsShowing()); 245 EXPECT_EQ(1, bubble_learn_more_click_count_); 246 EXPECT_EQ(0, dialog_learn_more_click_count_); 247 } 248 249 TEST_F(OneClickSigninBubbleViewTest, DialogLearnMoreLink) { 250 OneClickSigninBubbleView* view = ShowOneClickSigninBubble( 251 BrowserWindow::ONE_CLICK_SIGNIN_BUBBLE_TYPE_MODAL_DIALOG); 252 253 views::LinkListener* listener = view; 254 listener->LinkClicked(view->learn_more_link_, 0); 255 256 // View should still be showing and the OnLearnMoreLinkClicked method 257 // of the delegate should have been called with |is_dialog| == true. 258 content::RunAllPendingInMessageLoop(); 259 EXPECT_TRUE(OneClickSigninBubbleView::IsShowing()); 260 EXPECT_EQ(0, bubble_learn_more_click_count_); 261 EXPECT_EQ(1, dialog_learn_more_click_count_); 262 } 263 264 TEST_F(OneClickSigninBubbleViewTest, BubblePressEnterKey) { 265 OneClickSigninBubbleView* one_click_view = ShowOneClickSigninBubble( 266 BrowserWindow::ONE_CLICK_SIGNIN_BUBBLE_TYPE_BUBBLE); 267 268 // Simulate pressing the Enter key. 269 views::View* view = one_click_view; 270 const ui::Accelerator accelerator(ui::VKEY_RETURN, 0); 271 view->AcceleratorPressed(accelerator); 272 273 // View should no longer be showing. The message loop will exit once the 274 // fade animation of the bubble is done. 275 content::RunAllPendingInMessageLoop(); 276 EXPECT_FALSE(OneClickSigninBubbleView::IsShowing()); 277 } 278 279 TEST_F(OneClickSigninBubbleViewTest, DialogPressEnterKey) { 280 OneClickSigninBubbleView* one_click_view = ShowOneClickSigninBubble( 281 BrowserWindow::ONE_CLICK_SIGNIN_BUBBLE_TYPE_MODAL_DIALOG); 282 283 // Simulate pressing the Enter key. 284 views::View* view = one_click_view; 285 const ui::Accelerator accelerator(ui::VKEY_RETURN, 0); 286 view->AcceleratorPressed(accelerator); 287 288 // View should no longer be showing. The message loop will exit once the 289 // fade animation of the bubble is done. 290 content::RunAllPendingInMessageLoop(); 291 EXPECT_FALSE(OneClickSigninBubbleView::IsShowing()); 292 EXPECT_TRUE(on_start_sync_called_); 293 EXPECT_EQ(OneClickSigninSyncStarter::SYNC_WITH_DEFAULT_SETTINGS, mode_); 294 } 295 296 TEST_F(OneClickSigninBubbleViewTest, BubblePressEscapeKey) { 297 OneClickSigninBubbleView* one_click_view = ShowOneClickSigninBubble( 298 BrowserWindow::ONE_CLICK_SIGNIN_BUBBLE_TYPE_BUBBLE); 299 300 // Simulate pressing the Escape key. 301 views::View* view = one_click_view; 302 const ui::Accelerator accelerator(ui::VKEY_ESCAPE, 0); 303 view->AcceleratorPressed(accelerator); 304 305 // View should no longer be showing. The message loop will exit once the 306 // fade animation of the bubble is done. 307 content::RunAllPendingInMessageLoop(); 308 EXPECT_FALSE(OneClickSigninBubbleView::IsShowing()); 309 } 310 311 TEST_F(OneClickSigninBubbleViewTest, DialogPressEscapeKey) { 312 OneClickSigninBubbleView* one_click_view = ShowOneClickSigninBubble( 313 BrowserWindow::ONE_CLICK_SIGNIN_BUBBLE_TYPE_MODAL_DIALOG); 314 315 // Simulate pressing the Escape key. 316 views::View* view = one_click_view; 317 const ui::Accelerator accelerator(ui::VKEY_ESCAPE, 0); 318 view->AcceleratorPressed(accelerator); 319 320 // View should no longer be showing. The message loop will exit once the 321 // fade animation of the bubble is done. 322 content::RunAllPendingInMessageLoop(); 323 EXPECT_FALSE(OneClickSigninBubbleView::IsShowing()); 324 EXPECT_TRUE(on_start_sync_called_); 325 EXPECT_EQ(OneClickSigninSyncStarter::UNDO_SYNC, mode_); 326 } 327