Add unit test for the Settings API Bubble.
[chromium-blink-merge.git] / ash / focus_cycler_unittest.cc
blob5b25d966b3c654e5b98679899092bd0b5bb413b3
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.
5 #include "ash/focus_cycler.h"
7 #include "ash/root_window_controller.h"
8 #include "ash/shelf/shelf.h"
9 #include "ash/shelf/shelf_widget.h"
10 #include "ash/shell.h"
11 #include "ash/shell_factory.h"
12 #include "ash/shell_window_ids.h"
13 #include "ash/system/status_area_widget.h"
14 #include "ash/system/status_area_widget_delegate.h"
15 #include "ash/system/tray/system_tray.h"
16 #include "ash/test/ash_test_base.h"
17 #include "ash/wm/window_util.h"
18 #include "ui/aura/test/event_generator.h"
19 #include "ui/aura/test/test_windows.h"
20 #include "ui/aura/window.h"
21 #include "ui/aura/window_event_dispatcher.h"
22 #include "ui/views/accessible_pane_view.h"
23 #include "ui/views/controls/button/menu_button.h"
24 #include "ui/views/widget/widget.h"
26 namespace ash {
27 namespace test {
29 using aura::Window;
30 using internal::FocusCycler;
32 namespace {
34 internal::StatusAreaWidgetDelegate* GetStatusAreaWidgetDelegate(
35 views::Widget* widget) {
36 return static_cast<internal::StatusAreaWidgetDelegate*>(
37 widget->GetContentsView());
40 class PanedWidgetDelegate : public views::WidgetDelegate {
41 public:
42 PanedWidgetDelegate(views::Widget* widget) : widget_(widget) {}
44 void SetAccessiblePanes(const std::vector<views::View*>& panes) {
45 accessible_panes_ = panes;
48 // views::WidgetDelegate.
49 virtual void GetAccessiblePanes(std::vector<views::View*>* panes) OVERRIDE {
50 std::copy(accessible_panes_.begin(),
51 accessible_panes_.end(),
52 std::back_inserter(*panes));
54 virtual views::Widget* GetWidget() OVERRIDE {
55 return widget_;
57 virtual const views::Widget* GetWidget() const OVERRIDE {
58 return widget_;
61 private:
62 views::Widget* widget_;
63 std::vector<views::View*> accessible_panes_;
66 } // namespace
68 class FocusCyclerTest : public AshTestBase {
69 public:
70 FocusCyclerTest() {}
72 virtual void SetUp() OVERRIDE {
73 AshTestBase::SetUp();
75 focus_cycler_.reset(new FocusCycler());
77 ASSERT_TRUE(Shelf::ForPrimaryDisplay());
80 virtual void TearDown() OVERRIDE {
81 if (tray_) {
82 GetStatusAreaWidgetDelegate(tray_->GetWidget())->
83 SetFocusCyclerForTesting(NULL);
84 tray_.reset();
87 shelf_widget()->SetFocusCycler(NULL);
89 focus_cycler_.reset();
91 AshTestBase::TearDown();
94 protected:
95 // Creates the system tray, returning true on success.
96 bool CreateTray() {
97 if (tray_)
98 return false;
99 aura::Window* parent = Shell::GetPrimaryRootWindowController()->
100 GetContainer(ash::internal::kShellWindowId_StatusContainer);
102 internal::StatusAreaWidget* widget = new internal::StatusAreaWidget(parent);
103 widget->CreateTrayViews();
104 widget->Show();
105 tray_.reset(widget->system_tray());
106 if (!tray_->GetWidget())
107 return false;
108 focus_cycler_->AddWidget(tray()->GetWidget());
109 GetStatusAreaWidgetDelegate(tray_->GetWidget())->SetFocusCyclerForTesting(
110 focus_cycler());
111 return true;
114 FocusCycler* focus_cycler() { return focus_cycler_.get(); }
116 SystemTray* tray() { return tray_.get(); }
118 ShelfWidget* shelf_widget() {
119 return Shelf::ForPrimaryDisplay()->shelf_widget();
122 void InstallFocusCycleOnShelf() {
123 // Add the shelf.
124 shelf_widget()->SetFocusCycler(focus_cycler());
127 private:
128 scoped_ptr<FocusCycler> focus_cycler_;
129 scoped_ptr<SystemTray> tray_;
131 DISALLOW_COPY_AND_ASSIGN(FocusCyclerTest);
134 TEST_F(FocusCyclerTest, CycleFocusBrowserOnly) {
135 // Create a single test window.
136 scoped_ptr<Window> window0(CreateTestWindowInShellWithId(0));
137 wm::ActivateWindow(window0.get());
138 EXPECT_TRUE(wm::IsActiveWindow(window0.get()));
140 // Cycle the window
141 focus_cycler()->RotateFocus(FocusCycler::FORWARD);
142 EXPECT_TRUE(wm::IsActiveWindow(window0.get()));
145 TEST_F(FocusCyclerTest, CycleFocusForward) {
146 ASSERT_TRUE(CreateTray());
148 InstallFocusCycleOnShelf();
150 // Create a single test window.
151 scoped_ptr<Window> window0(CreateTestWindowInShellWithId(0));
152 wm::ActivateWindow(window0.get());
153 EXPECT_TRUE(wm::IsActiveWindow(window0.get()));
155 // Cycle focus to the status area.
156 focus_cycler()->RotateFocus(FocusCycler::FORWARD);
157 EXPECT_TRUE(tray()->GetWidget()->IsActive());
159 // Cycle focus to the shelf.
160 focus_cycler()->RotateFocus(FocusCycler::FORWARD);
161 EXPECT_TRUE(shelf_widget()->IsActive());
163 // Cycle focus to the browser.
164 focus_cycler()->RotateFocus(FocusCycler::FORWARD);
165 EXPECT_TRUE(wm::IsActiveWindow(window0.get()));
168 TEST_F(FocusCyclerTest, CycleFocusBackward) {
169 ASSERT_TRUE(CreateTray());
171 InstallFocusCycleOnShelf();
173 // Create a single test window.
174 scoped_ptr<Window> window0(CreateTestWindowInShellWithId(0));
175 wm::ActivateWindow(window0.get());
176 EXPECT_TRUE(wm::IsActiveWindow(window0.get()));
178 // Cycle focus to the shelf.
179 focus_cycler()->RotateFocus(FocusCycler::BACKWARD);
180 EXPECT_TRUE(shelf_widget()->IsActive());
182 // Cycle focus to the status area.
183 focus_cycler()->RotateFocus(FocusCycler::BACKWARD);
184 EXPECT_TRUE(tray()->GetWidget()->IsActive());
186 // Cycle focus to the browser.
187 focus_cycler()->RotateFocus(FocusCycler::BACKWARD);
188 EXPECT_TRUE(wm::IsActiveWindow(window0.get()));
191 TEST_F(FocusCyclerTest, CycleFocusForwardBackward) {
192 ASSERT_TRUE(CreateTray());
194 InstallFocusCycleOnShelf();
196 // Create a single test window.
197 scoped_ptr<Window> window0(CreateTestWindowInShellWithId(0));
198 wm::ActivateWindow(window0.get());
199 EXPECT_TRUE(wm::IsActiveWindow(window0.get()));
201 // Cycle focus to the shelf.
202 focus_cycler()->RotateFocus(FocusCycler::BACKWARD);
203 EXPECT_TRUE(shelf_widget()->IsActive());
205 // Cycle focus to the status area.
206 focus_cycler()->RotateFocus(FocusCycler::BACKWARD);
207 EXPECT_TRUE(tray()->GetWidget()->IsActive());
209 // Cycle focus to the browser.
210 focus_cycler()->RotateFocus(FocusCycler::BACKWARD);
211 EXPECT_TRUE(wm::IsActiveWindow(window0.get()));
213 // Cycle focus to the status area.
214 focus_cycler()->RotateFocus(FocusCycler::FORWARD);
215 EXPECT_TRUE(tray()->GetWidget()->IsActive());
217 // Cycle focus to the shelf.
218 focus_cycler()->RotateFocus(FocusCycler::FORWARD);
219 EXPECT_TRUE(shelf_widget()->IsActive());
221 // Cycle focus to the browser.
222 focus_cycler()->RotateFocus(FocusCycler::FORWARD);
223 EXPECT_TRUE(wm::IsActiveWindow(window0.get()));
226 TEST_F(FocusCyclerTest, CycleFocusNoBrowser) {
227 ASSERT_TRUE(CreateTray());
229 InstallFocusCycleOnShelf();
231 // Add the shelf and focus it.
232 focus_cycler()->FocusWidget(shelf_widget());
234 // Cycle focus to the status area.
235 focus_cycler()->RotateFocus(FocusCycler::FORWARD);
236 EXPECT_TRUE(tray()->GetWidget()->IsActive());
238 // Cycle focus to the shelf.
239 focus_cycler()->RotateFocus(FocusCycler::FORWARD);
240 EXPECT_TRUE(shelf_widget()->IsActive());
242 // Cycle focus to the status area.
243 focus_cycler()->RotateFocus(FocusCycler::FORWARD);
244 EXPECT_TRUE(tray()->GetWidget()->IsActive());
246 // Cycle focus to the shelf.
247 focus_cycler()->RotateFocus(FocusCycler::BACKWARD);
248 EXPECT_TRUE(shelf_widget()->IsActive());
250 // Cycle focus to the status area.
251 focus_cycler()->RotateFocus(FocusCycler::BACKWARD);
252 EXPECT_TRUE(tray()->GetWidget()->IsActive());
255 // Tests that focus cycles from the active browser to the status area and back.
256 TEST_F(FocusCyclerTest, Shelf_CycleFocusForward) {
257 ASSERT_TRUE(CreateTray());
258 InstallFocusCycleOnShelf();
259 shelf_widget()->Hide();
261 // Create two test windows.
262 scoped_ptr<Window> window0(CreateTestWindowInShellWithId(0));
263 scoped_ptr<Window> window1(CreateTestWindowInShellWithId(1));
264 wm::ActivateWindow(window1.get());
265 wm::ActivateWindow(window0.get());
266 EXPECT_TRUE(wm::IsActiveWindow(window0.get()));
268 // Cycle focus to the status area.
269 focus_cycler()->RotateFocus(FocusCycler::FORWARD);
270 EXPECT_TRUE(tray()->GetWidget()->IsActive());
272 // Cycle focus to the browser.
273 focus_cycler()->RotateFocus(FocusCycler::FORWARD);
274 EXPECT_TRUE(wm::IsActiveWindow(window0.get()));
276 // Cycle focus to the status area.
277 focus_cycler()->RotateFocus(FocusCycler::FORWARD);
278 EXPECT_TRUE(tray()->GetWidget()->IsActive());
281 TEST_F(FocusCyclerTest, Shelf_CycleFocusBackwardInvisible) {
282 ASSERT_TRUE(CreateTray());
283 InstallFocusCycleOnShelf();
284 shelf_widget()->Hide();
286 // Create a single test window.
287 scoped_ptr<Window> window0(CreateTestWindowInShellWithId(0));
288 wm::ActivateWindow(window0.get());
289 EXPECT_TRUE(wm::IsActiveWindow(window0.get()));
291 // Cycle focus to the status area.
292 focus_cycler()->RotateFocus(FocusCycler::BACKWARD);
293 EXPECT_TRUE(tray()->GetWidget()->IsActive());
295 // Cycle focus to the browser.
296 focus_cycler()->RotateFocus(FocusCycler::BACKWARD);
297 EXPECT_TRUE(wm::IsActiveWindow(window0.get()));
300 TEST_F(FocusCyclerTest, CycleFocusThroughWindowWithPanes) {
301 ASSERT_TRUE(CreateTray());
303 InstallFocusCycleOnShelf();
305 scoped_ptr<PanedWidgetDelegate> test_widget_delegate;
306 scoped_ptr<views::Widget> browser_widget(new views::Widget);
307 test_widget_delegate.reset(new PanedWidgetDelegate(browser_widget.get()));
308 views::Widget::InitParams widget_params(
309 views::Widget::InitParams::TYPE_WINDOW);
310 widget_params.context = CurrentContext();
311 widget_params.delegate = test_widget_delegate.get();
312 widget_params.ownership =
313 views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
314 browser_widget->Init(widget_params);
315 browser_widget->Show();
317 aura::Window* browser_window = browser_widget->GetNativeView();
319 views::View* root_view = browser_widget->GetRootView();
321 views::AccessiblePaneView* pane1 = new views::AccessiblePaneView();
322 root_view->AddChildView(pane1);
324 views::View* view1 = new views::View;
325 view1->SetFocusable(true);
326 pane1->AddChildView(view1);
328 views::View* view2 = new views::View;
329 view2->SetFocusable(true);
330 pane1->AddChildView(view2);
332 views::AccessiblePaneView* pane2 = new views::AccessiblePaneView();
333 root_view->AddChildView(pane2);
335 views::View* view3 = new views::View;
336 view3->SetFocusable(true);
337 pane2->AddChildView(view3);
339 views::View* view4 = new views::View;
340 view4->SetFocusable(true);
341 pane2->AddChildView(view4);
343 std::vector<views::View*> panes;
344 panes.push_back(pane1);
345 panes.push_back(pane2);
347 test_widget_delegate->SetAccessiblePanes(panes);
349 views::FocusManager* focus_manager = browser_widget->GetFocusManager();
351 // Cycle focus to the status area.
352 focus_cycler()->RotateFocus(FocusCycler::FORWARD);
353 EXPECT_TRUE(tray()->GetWidget()->IsActive());
355 // Cycle focus to the shelf.
356 focus_cycler()->RotateFocus(FocusCycler::FORWARD);
357 EXPECT_TRUE(shelf_widget()->IsActive());
359 // Cycle focus to the first pane in the browser.
360 focus_cycler()->RotateFocus(FocusCycler::FORWARD);
361 EXPECT_TRUE(wm::IsActiveWindow(browser_window));
362 EXPECT_EQ(focus_manager->GetFocusedView(), view1);
364 // Cycle focus to the second pane in the browser.
365 focus_cycler()->RotateFocus(FocusCycler::FORWARD);
366 EXPECT_TRUE(wm::IsActiveWindow(browser_window));
367 EXPECT_EQ(focus_manager->GetFocusedView(), view3);
369 // Cycle focus back to the status area.
370 focus_cycler()->RotateFocus(FocusCycler::FORWARD);
371 EXPECT_TRUE(tray()->GetWidget()->IsActive());
373 // Reverse direction - back to the second pane in the browser.
374 focus_cycler()->RotateFocus(FocusCycler::BACKWARD);
375 EXPECT_TRUE(wm::IsActiveWindow(browser_window));
376 EXPECT_EQ(focus_manager->GetFocusedView(), view3);
378 // Back to the first pane in the browser.
379 focus_cycler()->RotateFocus(FocusCycler::BACKWARD);
380 EXPECT_TRUE(wm::IsActiveWindow(browser_window));
381 EXPECT_EQ(focus_manager->GetFocusedView(), view1);
383 // Back to the shelf.
384 focus_cycler()->RotateFocus(FocusCycler::BACKWARD);
385 EXPECT_TRUE(shelf_widget()->IsActive());
387 // Back to the status area.
388 focus_cycler()->RotateFocus(FocusCycler::BACKWARD);
389 EXPECT_TRUE(tray()->GetWidget()->IsActive());
391 // Pressing "Escape" while on the status area should
392 // deactivate it, and activate the browser window.
393 aura::Window* root = Shell::GetPrimaryRootWindow();
394 aura::test::EventGenerator event_generator(root, root);
395 event_generator.PressKey(ui::VKEY_ESCAPE, 0);
396 EXPECT_TRUE(wm::IsActiveWindow(browser_window));
397 EXPECT_EQ(focus_manager->GetFocusedView(), view1);
399 // Similarly, pressing "Escape" while on the shelf.
400 // should do the same thing.
401 focus_cycler()->RotateFocus(FocusCycler::BACKWARD);
402 EXPECT_TRUE(shelf_widget()->IsActive());
403 event_generator.PressKey(ui::VKEY_ESCAPE, 0);
404 EXPECT_TRUE(wm::IsActiveWindow(browser_window));
405 EXPECT_EQ(focus_manager->GetFocusedView(), view1);
408 } // namespace test
409 } // namespace ash