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