| OLD | NEW |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 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 | 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 <memory> | 5 #include <memory> |
| 6 | 6 |
| 7 #import <Cocoa/Cocoa.h> | 7 #import <Cocoa/Cocoa.h> |
| 8 | 8 |
| 9 #include "base/strings/sys_string_conversions.h" | 9 #include "base/strings/sys_string_conversions.h" |
| 10 #include "base/strings/utf_string_conversions.h" | 10 #include "base/strings/utf_string_conversions.h" |
| 11 #import "testing/gtest_mac.h" | 11 #import "testing/gtest_mac.h" |
| 12 #include "ui/accessibility/ax_enums.h" | 12 #include "ui/accessibility/ax_enums.h" |
| 13 #include "ui/accessibility/ax_view_state.h" | 13 #include "ui/accessibility/ax_view_state.h" |
| 14 #import "ui/accessibility/platform/ax_platform_node_mac.h" | 14 #import "ui/accessibility/platform/ax_platform_node_mac.h" |
| 15 #include "ui/base/ime/text_input_type.h" | 15 #include "ui/base/ime/text_input_type.h" |
| 16 #import "ui/gfx/mac/coordinate_conversion.h" | 16 #import "ui/gfx/mac/coordinate_conversion.h" |
| 17 #include "ui/views/accessibility/native_view_accessibility.h" |
| 17 #include "ui/views/controls/label.h" | 18 #include "ui/views/controls/label.h" |
| 18 #include "ui/views/controls/textfield/textfield.h" | 19 #include "ui/views/controls/textfield/textfield.h" |
| 19 #include "ui/views/test/widget_test.h" | 20 #include "ui/views/test/widget_test.h" |
| 20 #include "ui/views/widget/widget.h" | 21 #include "ui/views/widget/widget.h" |
| 21 | 22 |
| 22 // Expose some methods from AXPlatformNodeCocoa for testing purposes only. | 23 // Expose some methods from AXPlatformNodeCocoa for testing purposes only. |
| 23 @interface AXPlatformNodeCocoa (Testing) | 24 @interface AXPlatformNodeCocoa (Testing) |
| 24 - (NSString*)AXRole; | 25 - (NSString*)AXRole; |
| 25 @end | 26 @end |
| 26 | 27 |
| 27 namespace views { | 28 namespace views { |
| 28 | 29 |
| 29 namespace { | 30 namespace { |
| 30 | 31 |
| 31 NSString* const kTestPlaceholderText = @"Test placeholder text"; | 32 NSString* const kTestPlaceholderText = @"Test placeholder text"; |
| 32 NSString* const kTestStringValue = @"Test string value"; | 33 NSString* const kTestStringValue = @"Test string value"; |
| 33 NSString* const kTestTitle = @"Test textfield"; | 34 NSString* const kTestTitle = @"Test textfield"; |
| 34 | 35 |
| 35 class FlexibleRoleTestView : public View { | 36 class FlexibleRoleTestView : public View { |
| 36 public: | 37 public: |
| 37 explicit FlexibleRoleTestView(ui::AXRole role) : role_(role) {} | 38 explicit FlexibleRoleTestView(ui::AXRole role) : role_(role) { |
| 39 SetFocusBehavior(FocusBehavior::ACCESSIBLE_ONLY); |
| 40 } |
| 41 |
| 38 void set_role(ui::AXRole role) { role_ = role; } | 42 void set_role(ui::AXRole role) { role_ = role; } |
| 39 | 43 |
| 40 // Add a child view and resize to fit the child. | 44 // Add a child view and resize to fit the child. |
| 41 void FitBoundsToNewChild(View* view) { | 45 void FitBoundsToNewChild(View* view) { |
| 42 View::AddChildView(view); | 46 View::AddChildView(view); |
| 43 // Fit the parent widget to the size of the child for accurate hit tests. | 47 // Fit the parent widget to the size of the child for accurate hit tests. |
| 44 SetBoundsRect(view->bounds()); | 48 SetBoundsRect(view->bounds()); |
| 45 } | 49 } |
| 46 | 50 |
| 47 // View: | 51 // View: |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 104 | 108 |
| 105 // Test for NSAccessibilityChildrenAttribute, and ensure it excludes ignored | 109 // Test for NSAccessibilityChildrenAttribute, and ensure it excludes ignored |
| 106 // children from the accessibility tree. | 110 // children from the accessibility tree. |
| 107 TEST_F(NativeWidgetMacAccessibilityTest, ChildrenAttribute) { | 111 TEST_F(NativeWidgetMacAccessibilityTest, ChildrenAttribute) { |
| 108 // Check childless views don't have accessibility children. | 112 // Check childless views don't have accessibility children. |
| 109 EXPECT_EQ(0u, | 113 EXPECT_EQ(0u, |
| 110 [AttributeValueAtMidpoint(NSAccessibilityChildrenAttribute) count]); | 114 [AttributeValueAtMidpoint(NSAccessibilityChildrenAttribute) count]); |
| 111 | 115 |
| 112 const size_t kNumChildren = 3; | 116 const size_t kNumChildren = 3; |
| 113 for (size_t i = 0; i < kNumChildren; ++i) { | 117 for (size_t i = 0; i < kNumChildren; ++i) { |
| 114 // Make sure the labels won't interfere with the hit test. | 118 // Add children sized 0x0 to ensure they won't interfere with the hit tests. |
| 115 AddChildTextfield(gfx::Size()); | 119 AddChildTextfield(gfx::Size()); |
| 116 } | 120 } |
| 117 | 121 |
| 118 EXPECT_EQ(kNumChildren, | 122 EXPECT_EQ(kNumChildren, |
| 119 [AttributeValueAtMidpoint(NSAccessibilityChildrenAttribute) count]); | 123 [AttributeValueAtMidpoint(NSAccessibilityChildrenAttribute) count]); |
| 120 | 124 |
| 121 // Check ignored children don't show up in the accessibility tree. | 125 // Check ignored children don't show up in the accessibility tree. |
| 122 widget()->GetContentsView()->AddChildView( | 126 widget()->GetContentsView()->AddChildView( |
| 123 new FlexibleRoleTestView(ui::AX_ROLE_IGNORED)); | 127 new FlexibleRoleTestView(ui::AX_ROLE_IGNORED)); |
| 124 EXPECT_EQ(kNumChildren, | 128 EXPECT_EQ(kNumChildren, |
| 125 [AttributeValueAtMidpoint(NSAccessibilityChildrenAttribute) count]); | 129 [AttributeValueAtMidpoint(NSAccessibilityChildrenAttribute) count]); |
| 126 } | 130 } |
| 127 | 131 |
| 128 // Test for NSAccessibilityParentAttribute, including for a Widget with no | 132 // Test for NSAccessibilityParentAttribute, including for a Widget with no |
| 129 // parent. | 133 // parent. |
| 130 TEST_F(NativeWidgetMacAccessibilityTest, ParentAttribute) { | 134 TEST_F(NativeWidgetMacAccessibilityTest, ParentAttribute) { |
| 131 Textfield* child = AddChildTextfield(widget()->GetContentsView()->size()); | 135 Textfield* child = AddChildTextfield(widget()->GetContentsView()->size()); |
| 132 | 136 |
| 133 // Views with Widget parents will have a NSWindow parent. | 137 // Views with Widget parents will have a RootView (BridgedContentView) parent, |
| 134 EXPECT_NSEQ( | 138 // which doesn't use the legacy NSAccessibility Informal Protocol Reference, |
| 135 NSAccessibilityWindowRole, | 139 // so retrieve the AXRole via accessibilityAttributeValue instead. |
| 136 [AttributeValueAtMidpoint(NSAccessibilityParentAttribute) AXRole]); | 140 EXPECT_NSEQ(NSAccessibilityWindowRole, |
| 141 [AttributeValueAtMidpoint(NSAccessibilityParentAttribute) |
| 142 accessibilityAttributeValue:NSAccessibilityRoleAttribute]); |
| 137 | 143 |
| 138 // Views with non-Widget parents will have the role of the parent view. | 144 // Children of other Views will report their View parent's role. |
| 139 widget()->GetContentsView()->RemoveChildView(child); | 145 widget()->GetContentsView()->RemoveChildView(child); |
| 140 FlexibleRoleTestView* parent = new FlexibleRoleTestView(ui::AX_ROLE_GROUP); | 146 FlexibleRoleTestView* parent = new FlexibleRoleTestView(ui::AX_ROLE_GROUP); |
| 141 parent->FitBoundsToNewChild(child); | 147 parent->FitBoundsToNewChild(child); |
| 142 widget()->GetContentsView()->AddChildView(parent); | 148 widget()->GetContentsView()->AddChildView(parent); |
| 143 EXPECT_NSEQ( | 149 EXPECT_NSEQ( |
| 144 NSAccessibilityGroupRole, | 150 NSAccessibilityGroupRole, |
| 145 [AttributeValueAtMidpoint(NSAccessibilityParentAttribute) AXRole]); | 151 [AttributeValueAtMidpoint(NSAccessibilityParentAttribute) AXRole]); |
| 146 | 152 |
| 147 // Test an ignored role parent is skipped in favor of the grandparent. | 153 // Test an ignored role parent is skipped in favor of the grandparent. |
| 148 parent->set_role(ui::AX_ROLE_IGNORED); | 154 parent->set_role(ui::AX_ROLE_IGNORED); |
| 149 EXPECT_NSEQ( | 155 EXPECT_NSEQ(NSAccessibilityWindowRole, |
| 150 NSAccessibilityWindowRole, | 156 [AttributeValueAtMidpoint(NSAccessibilityParentAttribute) |
| 151 [AttributeValueAtMidpoint(NSAccessibilityParentAttribute) AXRole]); | 157 accessibilityAttributeValue:NSAccessibilityRoleAttribute]); |
| 152 } | 158 } |
| 153 | 159 |
| 154 // Test for NSAccessibilityPositionAttribute, including on Widget movement | 160 // Test for NSAccessibilityPositionAttribute, including on Widget movement |
| 155 // updates. | 161 // updates. |
| 156 TEST_F(NativeWidgetMacAccessibilityTest, PositionAttribute) { | 162 TEST_F(NativeWidgetMacAccessibilityTest, PositionAttribute) { |
| 157 NSValue* widget_origin = | 163 NSValue* widget_origin = |
| 158 [NSValue valueWithPoint:gfx::ScreenPointToNSPoint( | 164 [NSValue valueWithPoint:gfx::ScreenPointToNSPoint( |
| 159 GetWidgetBounds().bottom_left())]; | 165 GetWidgetBounds().bottom_left())]; |
| 160 EXPECT_NSEQ(widget_origin, | 166 EXPECT_NSEQ(widget_origin, |
| 161 AttributeValueAtMidpoint(NSAccessibilityPositionAttribute)); | 167 AttributeValueAtMidpoint(NSAccessibilityPositionAttribute)); |
| 162 | 168 |
| 163 // Check the attribute is updated when the Widget is moved. | 169 // Check the attribute is updated when the Widget is moved. |
| 164 gfx::Rect new_bounds(60, 80, 100, 100); | 170 gfx::Rect new_bounds(60, 80, 100, 100); |
| 165 widget()->SetBounds(new_bounds); | 171 widget()->SetBounds(new_bounds); |
| 166 widget_origin = [NSValue | 172 widget_origin = [NSValue |
| 167 valueWithPoint:gfx::ScreenPointToNSPoint(new_bounds.bottom_left())]; | 173 valueWithPoint:gfx::ScreenPointToNSPoint(new_bounds.bottom_left())]; |
| 168 EXPECT_NSEQ(widget_origin, | 174 EXPECT_NSEQ(widget_origin, |
| 169 AttributeValueAtMidpoint(NSAccessibilityPositionAttribute)); | 175 AttributeValueAtMidpoint(NSAccessibilityPositionAttribute)); |
| 176 |
| 177 // Check the attribute is correct for a View. |
| 178 Textfield* textfield = AddChildTextfield(gfx::Size(70, 70)); |
| 179 widget_origin = [NSValue |
| 180 valueWithPoint:gfx::ScreenPointToNSPoint( |
| 181 textfield->GetBoundsInScreen().bottom_left())]; |
| 182 EXPECT_NSEQ(NSAccessibilityTextFieldRole, |
| 183 AttributeValueAtMidpoint(NSAccessibilityRoleAttribute)); |
| 184 EXPECT_NSEQ(widget_origin, |
| 185 AttributeValueAtMidpoint(NSAccessibilityPositionAttribute)); |
| 170 } | 186 } |
| 171 | 187 |
| 172 // Test for NSAccessibilityHelpAttribute. | 188 // Test for NSAccessibilityHelpAttribute. |
| 173 TEST_F(NativeWidgetMacAccessibilityTest, HelpAttribute) { | 189 TEST_F(NativeWidgetMacAccessibilityTest, HelpAttribute) { |
| 174 Label* label = new Label(base::SysNSStringToUTF16(kTestPlaceholderText)); | 190 Label* label = new Label(base::SysNSStringToUTF16(kTestPlaceholderText)); |
| 191 label->SetFocusBehavior(ClientView::FocusBehavior::ACCESSIBLE_ONLY); |
| 175 label->SetSize(GetWidgetBounds().size()); | 192 label->SetSize(GetWidgetBounds().size()); |
| 176 EXPECT_NSEQ(nil, AttributeValueAtMidpoint(NSAccessibilityHelpAttribute)); | 193 EXPECT_NSEQ(nil, AttributeValueAtMidpoint(NSAccessibilityHelpAttribute)); |
| 177 label->SetTooltipText(base::SysNSStringToUTF16(kTestPlaceholderText)); | 194 label->SetTooltipText(base::SysNSStringToUTF16(kTestPlaceholderText)); |
| 178 widget()->GetContentsView()->AddChildView(label); | 195 widget()->GetContentsView()->AddChildView(label); |
| 179 EXPECT_NSEQ(kTestPlaceholderText, | 196 EXPECT_NSEQ(kTestPlaceholderText, |
| 180 AttributeValueAtMidpoint(NSAccessibilityHelpAttribute)); | 197 AttributeValueAtMidpoint(NSAccessibilityHelpAttribute)); |
| 181 } | 198 } |
| 182 | 199 |
| 183 // Test for NSAccessibilityWindowAttribute and | 200 // Test for NSAccessibilityWindowAttribute and |
| 184 // NSAccessibilityTopLevelUIElementAttribute. | 201 // NSAccessibilityTopLevelUIElementAttribute. |
| (...skipping 12 matching lines...) Expand all Loading... |
| 197 } | 214 } |
| 198 | 215 |
| 199 // Tests for accessibility attributes on a views::Textfield. | 216 // Tests for accessibility attributes on a views::Textfield. |
| 200 // TODO(patricialor): Test against Cocoa-provided attributes as well to ensure | 217 // TODO(patricialor): Test against Cocoa-provided attributes as well to ensure |
| 201 // consistency between Cocoa and toolkit-views. | 218 // consistency between Cocoa and toolkit-views. |
| 202 TEST_F(NativeWidgetMacAccessibilityTest, TextfieldGenericAttributes) { | 219 TEST_F(NativeWidgetMacAccessibilityTest, TextfieldGenericAttributes) { |
| 203 Textfield* textfield = AddChildTextfield(GetWidgetBounds().size()); | 220 Textfield* textfield = AddChildTextfield(GetWidgetBounds().size()); |
| 204 | 221 |
| 205 // NSAccessibilityEnabledAttribute. | 222 // NSAccessibilityEnabledAttribute. |
| 206 textfield->SetEnabled(false); | 223 textfield->SetEnabled(false); |
| 224 // Disabled items should be unfocusable but shouldn't be ignored. |
| 225 EXPECT_FALSE(textfield->IsAccessibilityFocusable()); |
| 226 EXPECT_FALSE(textfield->GetNativeViewAccessibility()->IsIgnored()); |
| 207 EXPECT_EQ(NO, [AttributeValueAtMidpoint(NSAccessibilityEnabledAttribute) | 227 EXPECT_EQ(NO, [AttributeValueAtMidpoint(NSAccessibilityEnabledAttribute) |
| 208 boolValue]); | 228 boolValue]); |
| 209 textfield->SetEnabled(true); | 229 textfield->SetEnabled(true); |
| 210 EXPECT_EQ(YES, [AttributeValueAtMidpoint(NSAccessibilityEnabledAttribute) | 230 EXPECT_EQ(YES, [AttributeValueAtMidpoint(NSAccessibilityEnabledAttribute) |
| 211 boolValue]); | 231 boolValue]); |
| 212 | 232 |
| 213 // NSAccessibilityFocusedAttribute. | 233 // NSAccessibilityFocusedAttribute. |
| 214 EXPECT_EQ(NO, [AttributeValueAtMidpoint(NSAccessibilityFocusedAttribute) | 234 EXPECT_EQ(NO, [AttributeValueAtMidpoint(NSAccessibilityFocusedAttribute) |
| 215 boolValue]); | 235 boolValue]); |
| 216 textfield->RequestFocus(); | 236 textfield->RequestFocus(); |
| (...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 332 EXPECT_FALSE( | 352 EXPECT_FALSE( |
| 333 [ax_node accessibilityIsAttributeSettable:NSAccessibilityValueAttribute]); | 353 [ax_node accessibilityIsAttributeSettable:NSAccessibilityValueAttribute]); |
| 334 [ax_node accessibilitySetValue:kTestStringValue | 354 [ax_node accessibilitySetValue:kTestStringValue |
| 335 forAttribute:NSAccessibilityValueAttribute]; | 355 forAttribute:NSAccessibilityValueAttribute]; |
| 336 EXPECT_NSEQ(kTestPlaceholderText, | 356 EXPECT_NSEQ(kTestPlaceholderText, |
| 337 AttributeValueAtMidpoint(NSAccessibilityValueAttribute)); | 357 AttributeValueAtMidpoint(NSAccessibilityValueAttribute)); |
| 338 EXPECT_EQ(base::SysNSStringToUTF16(kTestPlaceholderText), textfield->text()); | 358 EXPECT_EQ(base::SysNSStringToUTF16(kTestPlaceholderText), textfield->text()); |
| 339 } | 359 } |
| 340 | 360 |
| 341 } // namespace views | 361 } // namespace views |
| OLD | NEW |