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