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

Side by Side Diff: ui/views/widget/native_widget_mac_accessibility_unittest.mm

Issue 2016243002: Mac a11y: Add RoleDescription and Value attributes to accessibility information. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Address review comments. Created 4 years, 6 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/views.gyp ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2016 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 <memory>
6
7 #import <Cocoa/Cocoa.h>
8
9 #include "base/strings/sys_string_conversions.h"
10 #include "base/strings/utf_string_conversions.h"
11 #import "testing/gtest_mac.h"
12 #include "ui/accessibility/ax_enums.h"
13 #include "ui/accessibility/ax_view_state.h"
14 #import "ui/accessibility/platform/ax_platform_node_mac.h"
15 #include "ui/base/ime/text_input_type.h"
16 #import "ui/gfx/mac/coordinate_conversion.h"
17 #include "ui/views/controls/textfield/textfield.h"
18 #include "ui/views/test/widget_test.h"
19 #include "ui/views/widget/widget.h"
20
21 // Expose some methods from AXPlatformNodeCocoa for testing purposes only.
22 @interface AXPlatformNodeCocoa (Testing)
23 - (NSString*)AXRole;
24 @end
25
26 namespace views {
27
28 namespace {
29
30 NSString* const kTestStringValue = @"Test string value";
31 NSString* const kTestTitle = @"Test textfield";
32
33 class FlexibleRoleTestView : public View {
34 public:
35 explicit FlexibleRoleTestView(ui::AXRole role) : role_(role) {}
36 void set_role(ui::AXRole role) { role_ = role; }
37
38 // Add a child view and resize to fit the child.
39 void FitBoundsToNewChild(View* view) {
40 View::AddChildView(view);
41 // Fit the parent widget to the size of the child for accurate hit tests.
42 SetBoundsRect(view->bounds());
43 }
44
45 // View:
46 void GetAccessibleState(ui::AXViewState* state) override {
47 View::GetAccessibleState(state);
48 state->role = role_;
49 }
50
51 private:
52 ui::AXRole role_;
53
54 DISALLOW_COPY_AND_ASSIGN(FlexibleRoleTestView);
55 };
56
57 class NativeWidgetMacAccessibilityTest : public test::WidgetTest {
58 public:
59 NativeWidgetMacAccessibilityTest() {}
60
61 void SetUp() override {
62 test::WidgetTest::SetUp();
63 widget_ = CreateTopLevelPlatformWidget();
64 widget_->SetBounds(gfx::Rect(50, 50, 100, 100));
65 widget()->Show();
66 }
67
68 void TearDown() override {
69 widget_->CloseNow();
70 test::WidgetTest::TearDown();
71 }
72
73 id AttributeValueAtMidpoint(NSString* attribute) {
74 // Accessibility hit tests come in Cocoa screen coordinates.
75 NSPoint midpoint_in_screen_ = gfx::ScreenPointToNSPoint(
76 widget_->GetWindowBoundsInScreen().CenterPoint());
77 id hit =
78 [widget_->GetNativeWindow() accessibilityHitTest:midpoint_in_screen_];
79 id value = [hit accessibilityAttributeValue:attribute];
80 return value;
81 }
82
83 Textfield* AddChildTextfield(const gfx::Size& size) {
84 Textfield* textfield = new Textfield;
85 textfield->SetText(base::SysNSStringToUTF16(kTestStringValue));
86 textfield->SetAccessibleName(base::SysNSStringToUTF16(kTestTitle));
87 textfield->SetSize(size);
88 widget()->GetContentsView()->AddChildView(textfield);
89 return textfield;
90 }
91
92 Widget* widget() { return widget_; }
93 gfx::Rect GetWidgetBounds() { return widget_->GetClientAreaBoundsInScreen(); }
94
95 private:
96 Widget* widget_ = nullptr;
97
98 DISALLOW_COPY_AND_ASSIGN(NativeWidgetMacAccessibilityTest);
99 };
100
101 } // namespace
102
103 // Test for NSAccessibilityChildrenAttribute, and ensure it excludes ignored
104 // children from the accessibility tree.
105 TEST_F(NativeWidgetMacAccessibilityTest, ChildrenAttribute) {
106 // Check childless views don't have accessibility children.
107 EXPECT_EQ(0u,
108 [AttributeValueAtMidpoint(NSAccessibilityChildrenAttribute) count]);
109
110 const size_t kNumChildren = 3;
111 for (size_t i = 0; i < kNumChildren; ++i) {
112 // Make sure the labels won't interfere with the hit test.
113 AddChildTextfield(gfx::Size());
114 }
115
116 EXPECT_EQ(kNumChildren,
117 [AttributeValueAtMidpoint(NSAccessibilityChildrenAttribute) count]);
118
119 // Check ignored children don't show up in the accessibility tree.
120 widget()->GetContentsView()->AddChildView(
121 new FlexibleRoleTestView(ui::AX_ROLE_IGNORED));
122 EXPECT_EQ(kNumChildren,
123 [AttributeValueAtMidpoint(NSAccessibilityChildrenAttribute) count]);
124 }
125
126 // Test for NSAccessibilityParentAttribute, including for a Widget with no
127 // parent.
128 TEST_F(NativeWidgetMacAccessibilityTest, ParentAttribute) {
129 Textfield* child = AddChildTextfield(widget()->GetContentsView()->size());
130
131 // Views with Widget parents will have a NSWindow parent.
132 EXPECT_NSEQ(
133 NSAccessibilityWindowRole,
134 [AttributeValueAtMidpoint(NSAccessibilityParentAttribute) AXRole]);
135
136 // Views with non-Widget parents will have the role of the parent view.
137 widget()->GetContentsView()->RemoveChildView(child);
138 FlexibleRoleTestView* parent = new FlexibleRoleTestView(ui::AX_ROLE_GROUP);
139 parent->FitBoundsToNewChild(child);
140 widget()->GetContentsView()->AddChildView(parent);
141 EXPECT_NSEQ(
142 NSAccessibilityGroupRole,
143 [AttributeValueAtMidpoint(NSAccessibilityParentAttribute) AXRole]);
144
145 // Test an ignored role parent is skipped in favor of the grandparent.
146 parent->set_role(ui::AX_ROLE_IGNORED);
147 EXPECT_NSEQ(
148 NSAccessibilityWindowRole,
149 [AttributeValueAtMidpoint(NSAccessibilityParentAttribute) AXRole]);
150 }
151
152 // Test for NSAccessibilityPositionAttribute, including on Widget movement
153 // updates.
154 TEST_F(NativeWidgetMacAccessibilityTest, PositionAttribute) {
155 NSValue* widget_origin =
156 [NSValue valueWithPoint:gfx::ScreenPointToNSPoint(
157 GetWidgetBounds().bottom_left())];
158 EXPECT_NSEQ(widget_origin,
159 AttributeValueAtMidpoint(NSAccessibilityPositionAttribute));
160
161 // Check the attribute is updated when the Widget is moved.
162 gfx::Rect new_bounds(60, 80, 100, 100);
163 widget()->SetBounds(new_bounds);
164 widget_origin = [NSValue
165 valueWithPoint:gfx::ScreenPointToNSPoint(new_bounds.bottom_left())];
166 EXPECT_NSEQ(widget_origin,
167 AttributeValueAtMidpoint(NSAccessibilityPositionAttribute));
168 }
169
170 // Tests for accessibility attributes on a views::Textfield.
171 // TODO(patricialor): Test against Cocoa-provided attributes as well to ensure
172 // consistency between Cocoa and toolkit-views.
173 TEST_F(NativeWidgetMacAccessibilityTest, TextfieldAccessibility) {
174 Textfield* textfield = AddChildTextfield(GetWidgetBounds().size());
175
176 // NSAccessibilityTitleAttribute.
177 EXPECT_NSEQ(kTestTitle,
178 AttributeValueAtMidpoint(NSAccessibilityTitleAttribute));
179
180 // NSAccessibilityValueAttribute.
181 EXPECT_NSEQ(kTestStringValue,
182 AttributeValueAtMidpoint(NSAccessibilityValueAttribute));
183
184 // NSAccessibilityRoleAttribute.
185 EXPECT_NSEQ(NSAccessibilityTextFieldRole,
186 AttributeValueAtMidpoint(NSAccessibilityRoleAttribute));
187
188 // NSAccessibilitySubroleAttribute and
189 // NSAccessibilityRoleDescriptionAttribute.
190 EXPECT_NSEQ(nil, AttributeValueAtMidpoint(NSAccessibilitySubroleAttribute));
191 NSString* role_description =
192 NSAccessibilityRoleDescription(NSAccessibilityTextFieldRole, nil);
193 EXPECT_NSEQ(role_description, AttributeValueAtMidpoint(
194 NSAccessibilityRoleDescriptionAttribute));
195
196 // Test accessibility clients can see subroles as well.
197 textfield->SetTextInputType(ui::TEXT_INPUT_TYPE_PASSWORD);
198 EXPECT_NSEQ(NSAccessibilitySecureTextFieldSubrole,
199 AttributeValueAtMidpoint(NSAccessibilitySubroleAttribute));
200 role_description = NSAccessibilityRoleDescription(
201 NSAccessibilityTextFieldRole, NSAccessibilitySecureTextFieldSubrole);
202 EXPECT_NSEQ(role_description, AttributeValueAtMidpoint(
203 NSAccessibilityRoleDescriptionAttribute));
204
205 // Prevent the textfield from interfering with hit tests on the widget itself.
206 widget()->GetContentsView()->RemoveChildView(textfield);
207
208 // NSAccessibilitySizeAttribute.
209 EXPECT_EQ(GetWidgetBounds().size(),
210 gfx::Size([AttributeValueAtMidpoint(NSAccessibilitySizeAttribute)
211 sizeValue]));
212 // Check the attribute is updated when the Widget is resized.
213 gfx::Size new_size(200, 40);
214 widget()->SetSize(new_size);
215 EXPECT_EQ(new_size, gfx::Size([AttributeValueAtMidpoint(
216 NSAccessibilitySizeAttribute) sizeValue]));
217 }
218
219 } // namespace views
OLDNEW
« no previous file with comments | « ui/views/views.gyp ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698