OLD | NEW |
| (Empty) |
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 "ash/common/system/tray/tray_details_view.h" | |
6 | |
7 #include "ash/common/ash_view_ids.h" | |
8 #include "ash/common/system/tray/hover_highlight_view.h" | |
9 #include "ash/common/system/tray/special_popup_row.h" | |
10 #include "ash/common/system/tray/system_tray.h" | |
11 #include "ash/common/system/tray/system_tray_item.h" | |
12 #include "ash/common/system/tray/tray_constants.h" | |
13 #include "ash/common/system/tray/tray_popup_header_button.h" | |
14 #include "ash/common/system/tray/view_click_listener.h" | |
15 #include "ash/resources/grit/ash_resources.h" | |
16 #include "ash/strings/grit/ash_strings.h" | |
17 #include "ash/test/ash_test_base.h" | |
18 #include "base/memory/ptr_util.h" | |
19 #include "base/run_loop.h" | |
20 #include "base/test/scoped_mock_time_message_loop_task_runner.h" | |
21 #include "base/test/test_mock_time_task_runner.h" | |
22 #include "ui/events/test/event_generator.h" | |
23 #include "ui/views/controls/button/button.h" | |
24 #include "ui/views/view.h" | |
25 #include "ui/views/widget/widget.h" | |
26 | |
27 namespace ash { | |
28 namespace test { | |
29 | |
30 namespace { | |
31 | |
32 class TestDetailsView : public TrayDetailsView { | |
33 public: | |
34 explicit TestDetailsView(SystemTrayItem* owner) : TrayDetailsView(owner) { | |
35 // Uses bluetooth label for testing purpose. It can be changed to any | |
36 // string_id. | |
37 CreateTitleRow(IDS_ASH_STATUS_TRAY_BLUETOOTH); | |
38 } | |
39 | |
40 ~TestDetailsView() override {} | |
41 | |
42 TrayPopupHeaderButton* tray_popup_header_button() { | |
43 return tray_popup_header_button_; | |
44 } | |
45 | |
46 void FocusTitleRow() { title_row()->content()->RequestFocus(); } | |
47 | |
48 void CreateScrollerViews() { CreateScrollableList(); } | |
49 | |
50 private: | |
51 TrayPopupHeaderButton* tray_popup_header_button_; | |
52 | |
53 DISALLOW_COPY_AND_ASSIGN(TestDetailsView); | |
54 }; | |
55 | |
56 // Trivial item implementation that tracks its views for testing. | |
57 class TestItem : public SystemTrayItem { | |
58 public: | |
59 TestItem() | |
60 : SystemTrayItem(AshTestBase::GetPrimarySystemTray(), UMA_TEST), | |
61 tray_view_(nullptr), | |
62 default_view_(nullptr), | |
63 detailed_view_(nullptr) {} | |
64 | |
65 // Overridden from SystemTrayItem: | |
66 views::View* CreateTrayView(LoginStatus status) override { | |
67 tray_view_ = new views::View; | |
68 return tray_view_; | |
69 } | |
70 views::View* CreateDefaultView(LoginStatus status) override { | |
71 default_view_ = new views::View; | |
72 default_view_->SetFocusBehavior(views::View::FocusBehavior::ALWAYS); | |
73 return default_view_; | |
74 } | |
75 views::View* CreateDetailedView(LoginStatus status) override { | |
76 detailed_view_ = new TestDetailsView(this); | |
77 return detailed_view_; | |
78 } | |
79 void DestroyTrayView() override { tray_view_ = NULL; } | |
80 void DestroyDefaultView() override { default_view_ = NULL; } | |
81 void DestroyDetailedView() override { detailed_view_ = NULL; } | |
82 | |
83 views::View* tray_view() const { return tray_view_; } | |
84 views::View* default_view() const { return default_view_; } | |
85 TestDetailsView* detailed_view() const { return detailed_view_; } | |
86 | |
87 private: | |
88 views::View* tray_view_; | |
89 views::View* default_view_; | |
90 TestDetailsView* detailed_view_; | |
91 | |
92 DISALLOW_COPY_AND_ASSIGN(TestItem); | |
93 }; | |
94 | |
95 } // namespace | |
96 | |
97 class TrayDetailsViewTest : public AshTestBase { | |
98 public: | |
99 TrayDetailsViewTest() {} | |
100 ~TrayDetailsViewTest() override {} | |
101 | |
102 HoverHighlightView* CreateAndShowHoverHighlightView() { | |
103 SystemTray* tray = GetPrimarySystemTray(); | |
104 TestItem* test_item = new TestItem; | |
105 tray->AddTrayItem(base::WrapUnique(test_item)); | |
106 tray->ShowDefaultView(BUBBLE_CREATE_NEW); | |
107 RunAllPendingInMessageLoop(); | |
108 tray->ShowDetailedView(test_item, 0, true, BUBBLE_USE_EXISTING); | |
109 RunAllPendingInMessageLoop(); | |
110 | |
111 return static_cast<HoverHighlightView*>( | |
112 test_item->detailed_view()->title_row()->content()); | |
113 } | |
114 | |
115 TrayPopupHeaderButton* CreateAndShowTrayPopupHeaderButton() { | |
116 SystemTray* tray = GetPrimarySystemTray(); | |
117 TestItem* test_item = new TestItem; | |
118 tray->AddTrayItem(base::WrapUnique(test_item)); | |
119 tray->ShowDefaultView(BUBBLE_CREATE_NEW); | |
120 RunAllPendingInMessageLoop(); | |
121 tray->ShowDetailedView(test_item, 0, true, BUBBLE_USE_EXISTING); | |
122 RunAllPendingInMessageLoop(); | |
123 | |
124 return test_item->detailed_view()->tray_popup_header_button(); | |
125 } | |
126 | |
127 void TransitionFromDetailedToDefaultView(TestDetailsView* detailed) { | |
128 detailed->TransitionToDefaultView(); | |
129 (*scoped_task_runner_) | |
130 ->FastForwardBy(base::TimeDelta::FromMilliseconds( | |
131 kTrayDetailedViewTransitionDelayMs)); | |
132 } | |
133 | |
134 void FocusBackButton(TestDetailsView* detailed) { | |
135 detailed->back_button_->RequestFocus(); | |
136 } | |
137 | |
138 void SetUp() override { | |
139 AshTestBase::SetUp(); | |
140 scoped_task_runner_ = | |
141 base::MakeUnique<base::ScopedMockTimeMessageLoopTaskRunner>(); | |
142 } | |
143 | |
144 void TearDown() override { | |
145 scoped_task_runner_.reset(); | |
146 AshTestBase::TearDown(); | |
147 } | |
148 | |
149 private: | |
150 // Used to control the |transition_delay_timer_|. | |
151 std::unique_ptr<base::ScopedMockTimeMessageLoopTaskRunner> | |
152 scoped_task_runner_; | |
153 | |
154 DISALLOW_COPY_AND_ASSIGN(TrayDetailsViewTest); | |
155 }; | |
156 | |
157 TEST_F(TrayDetailsViewTest, TransitionToDefaultViewTest) { | |
158 SystemTray* tray = GetPrimarySystemTray(); | |
159 ASSERT_TRUE(tray->GetWidget()); | |
160 | |
161 TestItem* test_item_1 = new TestItem; | |
162 TestItem* test_item_2 = new TestItem; | |
163 tray->AddTrayItem(base::WrapUnique(test_item_1)); | |
164 tray->AddTrayItem(base::WrapUnique(test_item_2)); | |
165 | |
166 // Ensure the tray views are created. | |
167 ASSERT_TRUE(test_item_1->tray_view() != NULL); | |
168 ASSERT_TRUE(test_item_2->tray_view() != NULL); | |
169 | |
170 // Show the default view. | |
171 tray->ShowDefaultView(BUBBLE_CREATE_NEW); | |
172 RunAllPendingInMessageLoop(); | |
173 | |
174 // Show the detailed view of item 2. | |
175 tray->ShowDetailedView(test_item_2, 0, true, BUBBLE_USE_EXISTING); | |
176 EXPECT_TRUE(test_item_2->detailed_view()); | |
177 RunAllPendingInMessageLoop(); | |
178 EXPECT_FALSE(test_item_2->default_view()); | |
179 | |
180 // Transition back to default view, the default view of item 2 should have | |
181 // focus. | |
182 tray->GetSystemBubble()->bubble_view()->set_can_activate(true); | |
183 FocusBackButton(test_item_2->detailed_view()); | |
184 TransitionFromDetailedToDefaultView(test_item_2->detailed_view()); | |
185 RunAllPendingInMessageLoop(); | |
186 | |
187 EXPECT_TRUE(test_item_2->default_view()); | |
188 EXPECT_FALSE(test_item_2->detailed_view()); | |
189 EXPECT_TRUE(test_item_2->default_view()->HasFocus()); | |
190 | |
191 // Show the detailed view of item 2 again. | |
192 tray->ShowDetailedView(test_item_2, 0, true, BUBBLE_USE_EXISTING); | |
193 EXPECT_TRUE(test_item_2->detailed_view()); | |
194 RunAllPendingInMessageLoop(); | |
195 EXPECT_FALSE(test_item_2->default_view()); | |
196 | |
197 // Transition back to default view, the default view of item 2 should NOT have | |
198 // focus. | |
199 TransitionFromDetailedToDefaultView(test_item_2->detailed_view()); | |
200 RunAllPendingInMessageLoop(); | |
201 | |
202 EXPECT_TRUE(test_item_2->default_view()); | |
203 EXPECT_FALSE(test_item_2->detailed_view()); | |
204 EXPECT_FALSE(test_item_2->default_view()->HasFocus()); | |
205 } | |
206 | |
207 TEST_F(TrayDetailsViewTest, ScrollContentsTest) { | |
208 SystemTray* tray = GetPrimarySystemTray(); | |
209 TestItem* test_item = new TestItem; | |
210 tray->AddTrayItem(base::WrapUnique(test_item)); | |
211 tray->ShowDefaultView(BUBBLE_CREATE_NEW); | |
212 RunAllPendingInMessageLoop(); | |
213 tray->ShowDetailedView(test_item, 0, true, BUBBLE_USE_EXISTING); | |
214 RunAllPendingInMessageLoop(); | |
215 test_item->detailed_view()->CreateScrollerViews(); | |
216 | |
217 test_item->detailed_view()->scroll_content()->SetPaintToLayer(); | |
218 views::View* view1 = new views::View(); | |
219 test_item->detailed_view()->scroll_content()->AddChildView(view1); | |
220 views::View* view2 = new views::View(); | |
221 view2->SetPaintToLayer(); | |
222 test_item->detailed_view()->scroll_content()->AddChildView(view2); | |
223 views::View* view3 = new views::View(); | |
224 view3->SetPaintToLayer(); | |
225 test_item->detailed_view()->scroll_content()->AddChildView(view3); | |
226 | |
227 // Child layers should have same order as the child views. | |
228 const std::vector<ui::Layer*>& layers = | |
229 test_item->detailed_view()->scroll_content()->layer()->children(); | |
230 EXPECT_EQ(2u, layers.size()); | |
231 EXPECT_EQ(view2->layer(), layers[0]); | |
232 EXPECT_EQ(view3->layer(), layers[1]); | |
233 | |
234 // Mark |view2| as sticky and add one more child (which will reorder layers). | |
235 view2->set_id(VIEW_ID_STICKY_HEADER); | |
236 views::View* view4 = new views::View(); | |
237 view4->SetPaintToLayer(); | |
238 test_item->detailed_view()->scroll_content()->AddChildView(view4); | |
239 | |
240 // Sticky header layer should be above the last child's layer. | |
241 EXPECT_EQ(3u, layers.size()); | |
242 EXPECT_EQ(view3->layer(), layers[0]); | |
243 EXPECT_EQ(view4->layer(), layers[1]); | |
244 EXPECT_EQ(view2->layer(), layers[2]); | |
245 } | |
246 | |
247 } // namespace test | |
248 } // namespace ash | |
OLD | NEW |