Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(643)

Side by Side Diff: ui/views/accessibility/native_view_accessibility_unittest.cc

Issue 2119413004: a11y: Exclude children of nested keyboard accessible controls from a11y tree. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebase. Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « ui/views/accessibility/native_view_accessibility_mac.mm ('k') | ui/views/view.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "base/memory/ptr_util.h" 5 #include "base/memory/ptr_util.h"
6 #include "base/strings/utf_string_conversions.h" 6 #include "base/strings/utf_string_conversions.h"
7 #include "ui/accessibility/ax_node_data.h" 7 #include "ui/accessibility/ax_node_data.h"
8 #include "ui/gfx/geometry/rect_conversions.h" 8 #include "ui/gfx/geometry/rect_conversions.h"
9 #include "ui/views/accessibility/ax_aura_obj_cache.h" 9 #include "ui/views/accessibility/ax_aura_obj_cache.h"
10 #include "ui/views/accessibility/ax_aura_obj_wrapper.h" 10 #include "ui/views/accessibility/ax_aura_obj_wrapper.h"
11 #include "ui/views/accessibility/ax_widget_obj_wrapper.h" 11 #include "ui/views/accessibility/ax_widget_obj_wrapper.h"
12 #include "ui/views/accessibility/native_view_accessibility_base.h" 12 #include "ui/views/accessibility/native_view_accessibility_base.h"
13 #include "ui/views/controls/button/button.h" 13 #include "ui/views/controls/button/button.h"
14 #include "ui/views/controls/label.h" 14 #include "ui/views/controls/label.h"
15 #include "ui/views/test/views_test_base.h" 15 #include "ui/views/test/views_test_base.h"
16 #include "ui/views/widget/widget.h"
16 17
17 namespace views { 18 namespace views {
18 namespace test { 19 namespace test {
19 20
20 class NativeViewAccessibilityTest;
21
22 namespace { 21 namespace {
23 22
24 class TestButton : public Button { 23 class TestButton : public Button {
25 public: 24 public:
26 TestButton() : Button(NULL) {} 25 TestButton() : Button(NULL) {}
27 }; 26 };
28 27
28 // Adds a View with given bounds and focusability to a parent.
29 View* AddNewChildWithBoundsAndFocusability(View* parent,
30 const gfx::Rect& bounds,
31 bool focusable) {
32 View* child = new View;
33 child->SetBoundsRect(bounds);
34 parent->AddChildView(child);
35 child->SetFocusBehavior(focusable ? ClientView::FocusBehavior::ACCESSIBLE_ONLY
36 : ClientView::FocusBehavior::NEVER);
37 return child;
38 }
39
29 } // namespace 40 } // namespace
30 41
31 class NativeViewAccessibilityTest : public ViewsTestBase { 42 class NativeViewAccessibilityTest : public ViewsTestBase {
32 public: 43 public:
33 NativeViewAccessibilityTest() {} 44 NativeViewAccessibilityTest() {}
34 ~NativeViewAccessibilityTest() override {} 45 ~NativeViewAccessibilityTest() override {}
35 46
36 void SetUp() override { 47 void SetUp() override {
37 ViewsTestBase::SetUp(); 48 ViewsTestBase::SetUp();
38 49
39 widget_ = new views::Widget; 50 widget_ = new Widget;
40 views::Widget::InitParams params = 51 Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_WINDOW);
41 CreateParams(views::Widget::InitParams::TYPE_WINDOW);
42 params.bounds = gfx::Rect(0, 0, 200, 200); 52 params.bounds = gfx::Rect(0, 0, 200, 200);
43 widget_->Init(params); 53 widget_->Init(params);
44 54
45 button_ = new TestButton(); 55 button_ = new TestButton();
46 button_->SetSize(gfx::Size(20, 20)); 56 button_->SetSize(gfx::Size(20, 20));
47 button_accessibility_ = NativeViewAccessibility::Create(button_); 57 button_accessibility_ = NativeViewAccessibility::Create(button_);
48 58
49 label_ = new Label(); 59 label_ = new Label();
50 button_->AddChildView(label_); 60 button_->AddChildView(label_);
51 label_accessibility_ = NativeViewAccessibility::Create(label_); 61 label_accessibility_ = NativeViewAccessibility::Create(label_);
(...skipping 19 matching lines...) Expand all
71 } 81 }
72 82
73 bool SetFocused(NativeViewAccessibilityBase* view_accessibility, 83 bool SetFocused(NativeViewAccessibilityBase* view_accessibility,
74 bool focused) { 84 bool focused) {
75 ui::AXActionData data; 85 ui::AXActionData data;
76 data.action = focused ? ui::AX_ACTION_FOCUS : ui::AX_ACTION_BLUR; 86 data.action = focused ? ui::AX_ACTION_FOCUS : ui::AX_ACTION_BLUR;
77 return view_accessibility->AccessibilityPerformAction(data); 87 return view_accessibility->AccessibilityPerformAction(data);
78 } 88 }
79 89
80 protected: 90 protected:
81 views::Widget* widget_; 91 Widget* widget_;
82 TestButton* button_; 92 TestButton* button_;
83 std::unique_ptr<NativeViewAccessibility> button_accessibility_; 93 std::unique_ptr<NativeViewAccessibility> button_accessibility_;
84 Label* label_; 94 Label* label_;
85 std::unique_ptr<NativeViewAccessibility> label_accessibility_; 95 std::unique_ptr<NativeViewAccessibility> label_accessibility_;
96
97 DISALLOW_COPY_AND_ASSIGN(NativeViewAccessibilityTest);
86 }; 98 };
87 99
88 TEST_F(NativeViewAccessibilityTest, RoleShouldMatch) { 100 TEST_F(NativeViewAccessibilityTest, RoleShouldMatch) {
89 EXPECT_EQ(ui::AX_ROLE_BUTTON, button_accessibility()->GetData().role); 101 EXPECT_EQ(ui::AX_ROLE_BUTTON, button_accessibility()->GetData().role);
102 // Since the label is a subview of |button_|, and the button is keyboard
103 // focusable, the label is assumed to form part of the button and not have a
104 // role of its own.
105 EXPECT_EQ(ui::AX_ROLE_IGNORED, label_accessibility()->GetData().role);
106 // This will happen for all potentially keyboard-focusable Views with
107 // non-keyboard-focusable children, so if we make the button unfocusable, the
108 // label will be allowed to have its own role again.
109 button_->SetFocusBehavior(View::FocusBehavior::NEVER);
90 EXPECT_EQ(ui::AX_ROLE_STATIC_TEXT, label_accessibility()->GetData().role); 110 EXPECT_EQ(ui::AX_ROLE_STATIC_TEXT, label_accessibility()->GetData().role);
91 } 111 }
92 112
93 TEST_F(NativeViewAccessibilityTest, BoundsShouldMatch) { 113 TEST_F(NativeViewAccessibilityTest, BoundsShouldMatch) {
94 gfx::Rect bounds = 114 gfx::Rect bounds =
95 gfx::ToEnclosingRect(button_accessibility()->GetData().location); 115 gfx::ToEnclosingRect(button_accessibility()->GetData().location);
96 gfx::Rect screen_bounds = button_accessibility()->GetScreenBoundsRect(); 116 gfx::Rect screen_bounds = button_accessibility()->GetScreenBoundsRect();
97 117
98 EXPECT_EQ(button_->GetBoundsInScreen(), bounds); 118 EXPECT_EQ(button_->GetBoundsInScreen(), bounds);
99 EXPECT_EQ(screen_bounds, bounds); 119 EXPECT_EQ(screen_bounds, bounds);
100 } 120 }
101 121
102 TEST_F(NativeViewAccessibilityTest, LabelIsChildOfButton) { 122 TEST_F(NativeViewAccessibilityTest, LabelIsChildOfButton) {
123 EXPECT_EQ(0, button_accessibility()->GetChildCount());
124 EXPECT_EQ(nullptr, button_accessibility()->ChildAtIndex(0));
125 EXPECT_EQ(button_->GetNativeViewAccessible(),
126 label_accessibility()->GetParent());
127
128 // If |button_| is no longer focusable, |label_| should show up again.
129 button_->SetFocusBehavior(View::FocusBehavior::NEVER);
103 EXPECT_EQ(1, button_accessibility()->GetChildCount()); 130 EXPECT_EQ(1, button_accessibility()->GetChildCount());
104 EXPECT_EQ(label_->GetNativeViewAccessible(), 131 EXPECT_EQ(label_->GetNativeViewAccessible(),
105 button_accessibility()->ChildAtIndex(0)); 132 button_accessibility()->ChildAtIndex(0));
106 EXPECT_EQ(button_->GetNativeViewAccessible(), 133 EXPECT_EQ(button_->GetNativeViewAccessible(),
107 label_accessibility()->GetParent()); 134 label_accessibility()->GetParent());
108 } 135 }
109 136
110 // Verify Views with invisible ancestors have AX_STATE_INVISIBLE. 137 // Verify Views with invisible ancestors have AX_STATE_INVISIBLE.
111 TEST_F(NativeViewAccessibilityTest, InvisibleViews) { 138 TEST_F(NativeViewAccessibilityTest, InvisibleViews) {
112 EXPECT_TRUE(widget_->IsVisible()); 139 EXPECT_TRUE(widget_->IsVisible());
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
151 bool is_destroying_parent_widget = (parent_widget_ == widget); 178 bool is_destroying_parent_widget = (parent_widget_ == widget);
152 NativeViewAccessibilityBase::OnWidgetDestroying(widget); 179 NativeViewAccessibilityBase::OnWidgetDestroying(widget);
153 if (is_destroying_parent_widget) 180 if (is_destroying_parent_widget)
154 delete this; 181 delete this;
155 } 182 }
156 }; 183 };
157 184
158 TEST_F(NativeViewAccessibilityTest, CrashOnWidgetDestroyed) { 185 TEST_F(NativeViewAccessibilityTest, CrashOnWidgetDestroyed) {
159 std::unique_ptr<Widget> parent_widget(new Widget); 186 std::unique_ptr<Widget> parent_widget(new Widget);
160 Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP); 187 Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
161 params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; 188 params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
162 params.bounds = gfx::Rect(50, 50, 650, 650); 189 params.bounds = gfx::Rect(50, 50, 650, 650);
163 parent_widget->Init(params); 190 parent_widget->Init(params);
164 191
165 std::unique_ptr<Widget> child_widget(new Widget); 192 std::unique_ptr<Widget> child_widget(new Widget);
166 child_widget->Init(params); 193 child_widget->Init(params);
167 194
168 // Make sure that deleting the parent widget can't cause a crash 195 // Make sure that deleting the parent widget can't cause a crash
169 // due to NativeViewAccessibility not unregistering itself as a 196 // due to NativeViewAccessibility not unregistering itself as a
170 // WidgetObserver. Note that TestNativeViewAccessibility is a subclass 197 // WidgetObserver. Note that TestNativeViewAccessibility is a subclass
171 // defined above that destroys itself when its parent widget is destroyed. 198 // defined above that destroys itself when its parent widget is destroyed.
(...skipping 10 matching lines...) Expand all
182 ~DerivedTestView() override {} 209 ~DerivedTestView() override {}
183 210
184 void OnBlur() override { SetVisible(false); } 211 void OnBlur() override { SetVisible(false); }
185 }; 212 };
186 213
187 class AxTestViewsDelegate : public TestViewsDelegate { 214 class AxTestViewsDelegate : public TestViewsDelegate {
188 public: 215 public:
189 AxTestViewsDelegate() {} 216 AxTestViewsDelegate() {}
190 ~AxTestViewsDelegate() override {} 217 ~AxTestViewsDelegate() override {}
191 218
192 void NotifyAccessibilityEvent(views::View* view, 219 void NotifyAccessibilityEvent(View* view, ui::AXEvent event_type) override {
193 ui::AXEvent event_type) override {
194 AXAuraObjCache* ax = AXAuraObjCache::GetInstance(); 220 AXAuraObjCache* ax = AXAuraObjCache::GetInstance();
195 std::vector<AXAuraObjWrapper*> out_children; 221 std::vector<AXAuraObjWrapper*> out_children;
196 AXAuraObjWrapper* ax_obj = ax->GetOrCreate(view->GetWidget()); 222 AXAuraObjWrapper* ax_obj = ax->GetOrCreate(view->GetWidget());
197 ax_obj->GetChildren(&out_children); 223 ax_obj->GetChildren(&out_children);
198 } 224 }
199 225
200 private: 226 private:
201 DISALLOW_COPY_AND_ASSIGN(AxTestViewsDelegate); 227 DISALLOW_COPY_AND_ASSIGN(AxTestViewsDelegate);
202 }; 228 };
203 229
204 class AXViewTest : public ViewsTestBase { 230 class AXViewTest : public ViewsTestBase {
205 public: 231 public:
206 AXViewTest() {} 232 AXViewTest() {}
207 ~AXViewTest() override {} 233 ~AXViewTest() override {}
208 void SetUp() override { 234 void SetUp() override {
209 std::unique_ptr<TestViewsDelegate> views_delegate( 235 std::unique_ptr<TestViewsDelegate> views_delegate(
210 new AxTestViewsDelegate()); 236 new AxTestViewsDelegate());
211 set_views_delegate(std::move(views_delegate)); 237 set_views_delegate(std::move(views_delegate));
212 views::ViewsTestBase::SetUp(); 238 ViewsTestBase::SetUp();
213 } 239 }
214 }; 240 };
215 241
216 // Check if the destruction of the widget ends successfully if |view|'s 242 // Check if the destruction of the widget ends successfully if |view|'s
217 // visibility changed during destruction. 243 // visibility changed during destruction.
218 TEST_F(AXViewTest, LayoutCalledInvalidateRootView) { 244 TEST_F(AXViewTest, LayoutCalledInvalidateRootView) {
219 std::unique_ptr<Widget> widget(new Widget); 245 std::unique_ptr<Widget> widget(new Widget);
220 Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP); 246 Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
221 params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; 247 params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
222 widget->Init(params); 248 widget->Init(params);
223 widget->Show(); 249 widget->Show();
224 250
225 View* root = widget->GetRootView(); 251 View* root = widget->GetRootView();
226 DerivedTestView* parent = new DerivedTestView(); 252 DerivedTestView* parent = new DerivedTestView();
227 DerivedTestView* child = new DerivedTestView(); 253 DerivedTestView* child = new DerivedTestView();
228 root->AddChildView(parent); 254 root->AddChildView(parent);
229 parent->AddChildView(child); 255 parent->AddChildView(child);
230 child->SetFocusBehavior(DerivedTestView::FocusBehavior::ALWAYS); 256 child->SetFocusBehavior(DerivedTestView::FocusBehavior::ALWAYS);
231 parent->SetFocusBehavior(DerivedTestView::FocusBehavior::ALWAYS); 257 parent->SetFocusBehavior(DerivedTestView::FocusBehavior::ALWAYS);
232 root->SetFocusBehavior(DerivedTestView::FocusBehavior::ALWAYS); 258 root->SetFocusBehavior(DerivedTestView::FocusBehavior::ALWAYS);
233 parent->RequestFocus(); 259 parent->RequestFocus();
234 // During the destruction of parent, OnBlur will be called and change the 260 // During the destruction of parent, OnBlur will be called and change the
235 // visibility to false. 261 // visibility to false.
236 parent->SetVisible(true); 262 parent->SetVisible(true);
237 AXAuraObjCache* ax = AXAuraObjCache::GetInstance(); 263 AXAuraObjCache* ax = AXAuraObjCache::GetInstance();
238 ax->GetOrCreate(widget.get()); 264 ax->GetOrCreate(widget.get());
239 } 265 }
240 #endif 266 #endif
241 267
268 // Separate test class for a complicated test case for ignored accessibility
269 // elements which are excluded from the accessibility tree.
270 class NativeViewAccessibilityBaseIgnoredElementsTest : public ViewsTestBase {
271 public:
272 NativeViewAccessibilityBaseIgnoredElementsTest() {
273 a_root_ = new View;
274 NativeViewAccessibilityBase::GetForView(a_root_);
275 }
276
277 void SetUp() override {
278 ViewsTestBase::SetUp();
279 // Set up an accessibility tree where X-nodes should be ignored. A Views
280 // hierarchy as shown on the left should expose the accessibility tree in
281 // the middle, and respond to hit tests as shown on the right. This test
282 // is here for completeness (in practice, it's unlikely a keyboard-focusable
283 // View will be needed as a descendant of another keyboard-focusable View).
284 //
285 // A A
286 // / \ / | \ +++---+---+---++---+---+---+++
287 // B X1 B F E ||| C | D | B || F | A | E |||
288 // / | \ / | \ / \ +++---+---+---++---+---+---+++
289 // C D X2 X3 X4 E C D
290 // | |
291 // X5 F
292 //
293 // Note: For hit tests, the parent's bounds will be divided equally amongst
294 // its children (including ignored elements). This means all Views belonging
295 // on the same level of the Views hierarchy will be the same size.
296 a_root_ = new View;
297 a_root_->SetSize(gfx::Size(400, 20));
298 a_root_->SetFocusBehavior(View::FocusBehavior::ACCESSIBLE_ONLY);
299
300 // Create Views in the left subtree from |a_root_|.
301 gfx::Rect new_bounds(0, 0, a_root_->width() / 2, a_root_->height());
302 View* b = AddNewChildWithBoundsAndFocusability(a_root_, new_bounds, true);
303 // |a_root_| has 6 leaves, so divvy up space equally between them for hit
304 // tests.
305 new_bounds = gfx::Rect(0, 0, a_root_->width() / 6, a_root_->height());
306 View* c = AddNewChildWithBoundsAndFocusability(b, new_bounds, true);
307 View* x5 = AddNewChildWithBoundsAndFocusability(c, new_bounds, false);
308 // Update the |new_bounds| origin to position leaves next to each other.
309 new_bounds.set_x(new_bounds.x() + a_root_->width() / 6);
310 View* d = AddNewChildWithBoundsAndFocusability(b, new_bounds, true);
311 new_bounds.set_x(new_bounds.x() + a_root_->width() / 6);
312 View* x2 = AddNewChildWithBoundsAndFocusability(b, new_bounds, false);
313 new_bounds.set_x(new_bounds.x() + a_root_->width() / 6);
314
315 // Create Views in the right subtree from root |a_root_|.
316 new_bounds.set_size(b->size());
317 View* x1 = AddNewChildWithBoundsAndFocusability(a_root_, new_bounds, false);
318 new_bounds.set_origin(gfx::Point());
319 View* x3 = AddNewChildWithBoundsAndFocusability(x1, new_bounds, false);
320 View* f = AddNewChildWithBoundsAndFocusability(x3, new_bounds, true);
321 new_bounds.set_x(new_bounds.x() + a_root_->width() / 6);
322 View* x4 = AddNewChildWithBoundsAndFocusability(x1, new_bounds, false);
323 new_bounds.set_x(new_bounds.x() + a_root_->width() / 6);
324 View* e = AddNewChildWithBoundsAndFocusability(x1, new_bounds, true);
325
326 // Populate NPlatformativeViewAccessibility instances for convenience.
327 a_root_nva_ = NativeViewAccessibilityBase::GetForView(a_root_);
328 b_nva_ = NativeViewAccessibilityBase::GetForView(b);
329 c_b_nva_ = NativeViewAccessibilityBase::GetForView(c);
330 d_b_nva_ = NativeViewAccessibilityBase::GetForView(d);
331 e_x1_nva_ = NativeViewAccessibilityBase::GetForView(e);
332 f_x3_x1_nva_ = NativeViewAccessibilityBase::GetForView(f);
333 x1_nva_ = NativeViewAccessibilityBase::GetForView(x1);
334 x2_b_nva_ = NativeViewAccessibilityBase::GetForView(x2);
335 x3_x1_nva_ = NativeViewAccessibilityBase::GetForView(x3);
336 x4_x1_nva_ = NativeViewAccessibilityBase::GetForView(x4);
337 x5_c_b_nva_ = NativeViewAccessibilityBase::GetForView(x5);
338
339 // Add everything to a new widget, needed for hit testing and parent tests.
340 widget_ = new Widget;
341 Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_WINDOW);
342 widget_->Init(params);
343 widget_->GetContentsView()->AddChildView(a_root_);
344 widget_->Show();
345 }
346
347 void TearDown() override {
348 widget_->Close();
349 ViewsTestBase::TearDown();
350 }
351
352 protected:
353 // Owned by |widget_|.
354 View* a_root_;
355
356 // Owned by their respective View, which are owned by |widget_|.
357 // The following NativeViewAccessibilityBase objects are named after their
358 // corresponding node as shown in the diagrams in SetUp(), then a list of
359 // their ancestors (minus the root), separated by underscores.
360 NativeViewAccessibilityBase* a_root_nva_;
361 NativeViewAccessibilityBase* b_nva_;
362 NativeViewAccessibilityBase* c_b_nva_;
363 NativeViewAccessibilityBase* d_b_nva_;
364 NativeViewAccessibilityBase* e_x1_nva_;
365 NativeViewAccessibilityBase* f_x3_x1_nva_;
366 NativeViewAccessibilityBase* x1_nva_;
367 NativeViewAccessibilityBase* x2_b_nva_;
368 NativeViewAccessibilityBase* x3_x1_nva_;
369 NativeViewAccessibilityBase* x4_x1_nva_;
370 NativeViewAccessibilityBase* x5_c_b_nva_;
371
372 Widget* widget_ = nullptr;
373
374 private:
375 DISALLOW_COPY_AND_ASSIGN(NativeViewAccessibilityBaseIgnoredElementsTest);
376 };
377
378 // Check the number of a11y children returned accounts for ignored elements.
379 TEST_F(NativeViewAccessibilityBaseIgnoredElementsTest, GetChildCount) {
380 EXPECT_EQ(3, a_root_nva_->GetChildCount());
381 EXPECT_EQ(2, b_nva_->GetChildCount());
382 // Leaf elements will return 0.
383 EXPECT_EQ(0, c_b_nva_->GetChildCount());
384 EXPECT_EQ(0, x5_c_b_nva_->GetChildCount());
385 EXPECT_EQ(0, d_b_nva_->GetChildCount());
386 EXPECT_EQ(0, x2_b_nva_->GetChildCount());
387 EXPECT_EQ(2, x1_nva_->GetChildCount());
388 EXPECT_EQ(1, x3_x1_nva_->GetChildCount());
389 EXPECT_EQ(0, f_x3_x1_nva_->GetChildCount());
390 EXPECT_EQ(0, x4_x1_nva_->GetChildCount());
391 EXPECT_EQ(0, e_x1_nva_->GetChildCount());
392 }
393
394 // Make sure the correct a11y child element is returned at its corresponding
395 // index. Unignored children with ignored parents should move up in the tree.
396 TEST_F(NativeViewAccessibilityBaseIgnoredElementsTest, ChildAtIndex) {
397 EXPECT_EQ(b_nva_->GetNativeObject(), a_root_nva_->ChildAtIndex(0));
398 EXPECT_EQ(f_x3_x1_nva_->GetNativeObject(), a_root_nva_->ChildAtIndex(1));
399 EXPECT_EQ(e_x1_nva_->GetNativeObject(), a_root_nva_->ChildAtIndex(2));
400 EXPECT_EQ(nullptr, a_root_nva_->ChildAtIndex(3));
401
402 EXPECT_EQ(c_b_nva_->GetNativeObject(), b_nva_->ChildAtIndex(0));
403 EXPECT_EQ(d_b_nva_->GetNativeObject(), b_nva_->ChildAtIndex(1));
404 EXPECT_EQ(nullptr, b_nva_->ChildAtIndex(2));
405
406 EXPECT_EQ(f_x3_x1_nva_->GetNativeObject(), x1_nva_->ChildAtIndex(0));
407 EXPECT_EQ(e_x1_nva_->GetNativeObject(), x1_nva_->ChildAtIndex(1));
408 EXPECT_EQ(nullptr, x1_nva_->ChildAtIndex(2));
409
410 EXPECT_EQ(f_x3_x1_nva_->GetNativeObject(), x3_x1_nva_->ChildAtIndex(0));
411
412 // Node with ignored children.
413 EXPECT_EQ(nullptr, c_b_nva_->ChildAtIndex(0));
414 // Node with 0 children.
415 EXPECT_EQ(nullptr, d_b_nva_->ChildAtIndex(0));
416 // Ignored node with 0 children.
417 EXPECT_EQ(nullptr, x2_b_nva_->ChildAtIndex(0));
418 }
419
420 // Check the a11y parents returned correspond to their unignored children.
421 TEST_F(NativeViewAccessibilityBaseIgnoredElementsTest, GetParent) {
422 EXPECT_EQ(a_root_->parent()->GetNativeViewAccessible(),
423 a_root_nva_->GetParent());
424 EXPECT_EQ(a_root_->GetNativeViewAccessible(), b_nva_->GetParent());
425 EXPECT_EQ(b_nva_->GetNativeObject(), c_b_nva_->GetParent());
426 EXPECT_EQ(c_b_nva_->GetNativeObject(), x5_c_b_nva_->GetParent());
427 EXPECT_EQ(b_nva_->GetNativeObject(), d_b_nva_->GetParent());
428 EXPECT_EQ(b_nva_->GetNativeObject(), x2_b_nva_->GetParent());
429 EXPECT_EQ(a_root_->GetNativeViewAccessible(), x1_nva_->GetParent());
430
431 // Skips X1.
432 EXPECT_EQ(a_root_->GetNativeViewAccessible(), x3_x1_nva_->GetParent());
433 EXPECT_EQ(a_root_->GetNativeViewAccessible(), x4_x1_nva_->GetParent());
434 EXPECT_EQ(a_root_->GetNativeViewAccessible(), e_x1_nva_->GetParent());
435
436 // Skips X3 and X1.
437 EXPECT_EQ(a_root_->GetNativeViewAccessible(), f_x3_x1_nva_->GetParent());
438 }
439
440 // Test that a11y hit tests work correctly with ignored elements. A hit on a
441 // ignored element should return its first unignored ancestor.
442 TEST_F(NativeViewAccessibilityBaseIgnoredElementsTest, HitTestSync) {
443 // Move the hit point horizontally, incrementing by the leaf View width.
444 const int min_width = a_root_->GetBoundsInScreen().width() / 6;
445 int curr_x = a_root_->GetBoundsInScreen().x() + min_width / 2;
446 const int y = a_root_->GetBoundsInScreen().CenterPoint().y();
447
448 // HitTestSync isn't recursive, so manually do the recursion until arriving at
449 // the correct answer. I.e., the last NativeViewAccessible being tested for
450 // each |curr_x|, |y| pair below would be the correct return value if
451 // HitTestSync were recursive.
452 EXPECT_EQ(b_nva_->GetNativeObject(), a_root_nva_->HitTestSync(curr_x, y));
453 EXPECT_EQ(c_b_nva_->GetNativeObject(), b_nva_->HitTestSync(curr_x, y));
454 EXPECT_EQ(c_b_nva_->GetNativeObject(), c_b_nva_->HitTestSync(curr_x, y));
455 curr_x += min_width;
456 EXPECT_EQ(b_nva_->GetNativeObject(), a_root_nva_->HitTestSync(curr_x, y));
457 EXPECT_EQ(d_b_nva_->GetNativeObject(), b_nva_->HitTestSync(curr_x, y));
458 curr_x += min_width;
459 EXPECT_EQ(b_nva_->GetNativeObject(), a_root_nva_->HitTestSync(curr_x, y));
460 EXPECT_EQ(b_nva_->GetNativeObject(), b_nva_->HitTestSync(curr_x, y));
461 curr_x += min_width;
462 EXPECT_EQ(x1_nva_->GetNativeObject(), a_root_nva_->HitTestSync(curr_x, y));
463 EXPECT_EQ(x3_x1_nva_->GetNativeObject(), x1_nva_->HitTestSync(curr_x, y));
464 EXPECT_EQ(f_x3_x1_nva_->GetNativeObject(),
465 x3_x1_nva_->HitTestSync(curr_x, y));
466 curr_x += min_width;
467 EXPECT_EQ(x1_nva_->GetNativeObject(), a_root_nva_->HitTestSync(curr_x, y));
468 EXPECT_EQ(a_root_nva_->GetNativeObject(), x1_nva_->HitTestSync(curr_x, y));
469 curr_x += min_width;
470 EXPECT_EQ(x1_nva_->GetNativeObject(), a_root_nva_->HitTestSync(curr_x, y));
471 EXPECT_EQ(e_x1_nva_->GetNativeObject(), x1_nva_->HitTestSync(curr_x, y));
472 }
473
242 } // namespace test 474 } // namespace test
243 } // namespace views 475 } // namespace views
OLDNEW
« no previous file with comments | « ui/views/accessibility/native_view_accessibility_mac.mm ('k') | ui/views/view.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698