Chromium Code Reviews| Index: ui/views/widget/native_widget_mac_accessibility_unittest.mm |
| diff --git a/ui/views/widget/native_widget_mac_accessibility_unittest.mm b/ui/views/widget/native_widget_mac_accessibility_unittest.mm |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..bb8104e8eceb14314acabe00a174e4780d4c4119 |
| --- /dev/null |
| +++ b/ui/views/widget/native_widget_mac_accessibility_unittest.mm |
| @@ -0,0 +1,236 @@ |
| +// Copyright 2016 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#include <memory> |
| + |
| +#import <Cocoa/Cocoa.h> |
| + |
| +#include "base/strings/sys_string_conversions.h" |
| +#include "base/strings/utf_string_conversions.h" |
| +#import "testing/gtest_mac.h" |
| +#include "ui/accessibility/ax_enums.h" |
| +#include "ui/accessibility/ax_view_state.h" |
| +#import "ui/accessibility/platform/ax_platform_node_mac.h" |
| +#include "ui/base/ime/text_input_type.h" |
| +#import "ui/gfx/mac/coordinate_conversion.h" |
| +#include "ui/views/controls/textfield/textfield.h" |
| +#include "ui/views/test/widget_test.h" |
| +#include "ui/views/widget/widget.h" |
| + |
| +// TODO(patricialor): Test against Cocoa attributes as well to ensure |
| +// consistency between Cocoa and toolkit-views. |
| + |
| +// Expose some methods from AXPlatformNodeCocoa for testing purposes only. |
| +@interface AXPlatformNodeCocoa (Testing) |
| +- (NSString*)AXRole; |
| +@end |
| + |
| +namespace views { |
| + |
| +namespace { |
| + |
| +class FlexibleRoleTestView : public View { |
| + public: |
| + FlexibleRoleTestView(ui::AXRole role) : role_(role) {} |
|
tapted
2016/06/10 03:17:18
nit: explicit
Patti Lor
2016/06/16 07:05:21
Done.
|
| + void SetRole(ui::AXRole role) { role_ = role; } |
|
tapted
2016/06/10 03:17:18
SetRole -> set_role for basic setters
Patti Lor
2016/06/16 07:05:22
Done.
|
| + |
| + // View: |
| + void GetAccessibleState(ui::AXViewState* state) override { |
| + View::GetAccessibleState(state); |
| + state->role = role_; |
| + } |
| + |
| + void AddChildView(View* view) { |
|
tapted
2016/06/10 03:17:17
This isn't virtual, so we should give it a new nam
Patti Lor
2016/06/16 07:05:21
Changed it to 'FitBoundsToNewChild'.
|
| + View::AddChildView(view); |
| + // Allow the child to take its full size for accurate hit tests. |
|
tapted
2016/06/10 03:17:17
This is making the parent take the size of the chi
Patti Lor
2016/06/16 07:05:22
That was the intention, do you think it makes more
tapted
2016/06/17 03:32:49
Ah, I just meant the comment didn't seem to match,
|
| + SetBoundsRect(view->bounds()); |
| + } |
| + |
| + private: |
| + ui::AXRole role_; |
| + DISALLOW_COPY_AND_ASSIGN(FlexibleRoleTestView); |
|
tapted
2016/06/10 03:17:17
nit: blank line before
Patti Lor
2016/06/16 07:05:21
Done.
|
| +}; |
| + |
| +class NativeWidgetMacAccessibilityTest : public test::WidgetTest { |
| + public: |
| + void SetUp() override { |
| + test::WidgetTest::SetUp(); |
| + widget_ = CreateTopLevelPlatformWidget(); |
| + widget_->SetBounds(gfx::Rect(50, 50, 100, 100)); |
| + midpoint_in_screen_ = gfx::ScreenPointToNSPoint( |
| + widget_->GetWindowBoundsInScreen().CenterPoint()); |
| + widget()->Show(); |
| + } |
| + |
| + void TearDown() override { |
| + widget_->CloseNow(); |
| + test::WidgetTest::TearDown(); |
| + } |
| + |
| + id AttributeValueAtMidpoint(NSString* attribute) { |
| + // Accessibility hit tests come in Cocoa screen coordinates. |
| + id hit = |
| + [widget_->GetNativeWindow() accessibilityHitTest:midpoint_in_screen_]; |
| + id value = [hit accessibilityAttributeValue:attribute]; |
| + return value; |
| + } |
| + |
| + Textfield* AddChildTextfield(const gfx::Size& size) { |
| + Textfield* textfield = new Textfield; |
| + textfield->SetText(kTestString); |
| + textfield->SetAccessibleName(kTestTextfieldTitle); |
| + textfield->SetSize(size); |
| + widget()->GetContentsView()->AddChildView(textfield); |
| + return textfield; |
| + } |
| + |
| + Widget* widget() { return widget_; } |
| + gfx::Rect widget_bounds() { return widget_->GetClientAreaBoundsInScreen(); } |
| + |
| + const base::string16 kTestString = base::ASCIIToUTF16("Green"); |
| + const base::string16 kTestTextfieldTitle = |
|
tapted
2016/06/10 03:17:18
since these aren't compile time constants, we shou
Patti Lor
2016/06/16 07:05:21
Done.
|
| + base::ASCIIToUTF16("Test textfield"); |
| + |
| + private: |
| + Widget* widget_; |
|
tapted
2016/06/10 03:17:18
whoops - these should be initialized = nullptr
Patti Lor
2016/06/16 07:05:21
Done.
Patti Lor
2016/06/16 07:05:21
Done.
|
| + |
| + NSPoint midpoint_in_screen_; |
|
tapted
2016/06/10 03:17:17
= {0, 0}
Patti Lor
2016/06/16 07:05:21
Removed entirely, realised some things were broken
|
| +}; |
|
tapted
2016/06/10 03:17:18
nit: DISALLOW_COPY... You'll need a default constr
Patti Lor
2016/06/16 07:05:21
Done.
|
| + |
| +} // namespace |
| + |
| +// Test for NSAccessibilityChildrenAttribute, including with ignored children in |
| +// the accessibility tree. |
| +TEST_F(NativeWidgetMacAccessibilityTest, ChildrenAttribute) { |
| + // Check childless views don't have accessibility children. |
| + EXPECT_EQ(0u, |
| + [AttributeValueAtMidpoint(NSAccessibilityChildrenAttribute) count]); |
| + |
| + const size_t kNumChildren = 3; |
| + for (size_t i = 0; i < kNumChildren; ++i) { |
| + // Make sure the labels won't interfere with the hit test. |
| + AddChildTextfield(gfx::Size()); |
| + } |
| + |
| + EXPECT_EQ(kNumChildren, |
| + [AttributeValueAtMidpoint(NSAccessibilityChildrenAttribute) count]); |
| + |
| + // Check ignored children don't show up in the accessibility tree. |
| + widget()->GetContentsView()->AddChildView( |
| + new FlexibleRoleTestView(ui::AX_ROLE_IGNORED)); |
| + EXPECT_EQ(kNumChildren, |
| + [AttributeValueAtMidpoint(NSAccessibilityChildrenAttribute) count]); |
| +} |
| + |
| +// Test for NSAccessibilityParentAttribute, including for a widget with no |
| +// parent. |
| +TEST_F(NativeWidgetMacAccessibilityTest, ParentAttribute) { |
| + Textfield* child = AddChildTextfield(widget()->GetContentsView()->size()); |
| + |
| + // Views with widget parents will have a NSWindow parent. |
| + EXPECT_NSEQ( |
| + NSAccessibilityWindowRole, |
| + [AttributeValueAtMidpoint(NSAccessibilityParentAttribute) AXRole]); |
| + |
| + // Views with non-widget parents will have the role of the parent view. |
| + widget()->GetContentsView()->RemoveChildView(child); |
| + FlexibleRoleTestView* parent = new FlexibleRoleTestView(ui::AX_ROLE_GROUP); |
| + parent->AddChildView(child); |
| + widget()->GetContentsView()->AddChildView(parent); |
| + EXPECT_NSEQ( |
| + NSAccessibilityGroupRole, |
| + [AttributeValueAtMidpoint(NSAccessibilityParentAttribute) AXRole]); |
| + |
| + // Test an ignored role parent is skipped in favor of the grandparent. |
| + parent->SetRole(ui::AX_ROLE_IGNORED); |
| + EXPECT_NSEQ( |
| + NSAccessibilityWindowRole, |
| + [AttributeValueAtMidpoint(NSAccessibilityParentAttribute) AXRole]); |
| +} |
| + |
| +// Test for NSAccessibilityPositionAttribute, including on widget movement |
| +// updates. |
| +TEST_F(NativeWidgetMacAccessibilityTest, PositionAttribute) { |
| + NSValue* widget_origin = [NSValue |
| + valueWithPoint:gfx::ScreenPointToNSPoint(widget_bounds().bottom_left())]; |
| + EXPECT_NSEQ(widget_origin, |
| + AttributeValueAtMidpoint(NSAccessibilityPositionAttribute)); |
| + |
| + // Check the attribute is updated when the widget is moved. |
| + gfx::Rect new_bounds(25, 30, 60, 30); |
| + widget()->SetBounds(new_bounds); |
| + widget_origin = [NSValue |
| + valueWithPoint:gfx::ScreenPointToNSPoint(new_bounds.bottom_left())]; |
| + EXPECT_NSEQ(widget_origin, |
| + AttributeValueAtMidpoint(NSAccessibilityPositionAttribute)); |
| +} |
| + |
| +// Test for NSAccessibilityRoleAttribute. |
| +TEST_F(NativeWidgetMacAccessibilityTest, RoleAttribute) { |
| + AddChildTextfield(widget()->GetContentsView()->size()); |
| + |
| + EXPECT_NSEQ(NSAccessibilityTextFieldRole, |
| + AttributeValueAtMidpoint(NSAccessibilityRoleAttribute)); |
| +} |
| + |
| +// Test for NSAccessibilitySizeAttribute, including on size updates. |
| +TEST_F(NativeWidgetMacAccessibilityTest, SizeAttribute) { |
| + AddChildTextfield(widget()->GetContentsView()->size()); |
| + |
| + EXPECT_EQ(widget_bounds().size(), |
| + gfx::Size([AttributeValueAtMidpoint(NSAccessibilitySizeAttribute) |
| + sizeValue])); |
| + |
| + // Check the attribute is updated when the widget is resized. |
| + gfx::Size new_size(40, 30); |
| + widget()->SetSize(new_size); |
| + EXPECT_EQ(new_size, gfx::Size([AttributeValueAtMidpoint( |
| + NSAccessibilitySizeAttribute) sizeValue])); |
| +} |
| + |
| +// Test for NSAccessibilitySubroleAttribute. |
| +TEST_F(NativeWidgetMacAccessibilityTest, SubroleAttribute) { |
| + Textfield* textfield = AddChildTextfield(widget()->GetContentsView()->size()); |
| + EXPECT_NSEQ(nil, AttributeValueAtMidpoint(NSAccessibilitySubroleAttribute)); |
| + |
| + textfield->SetTextInputType(ui::TEXT_INPUT_TYPE_PASSWORD); |
| + EXPECT_NSEQ(NSAccessibilitySecureTextFieldSubrole, |
| + AttributeValueAtMidpoint(NSAccessibilitySubroleAttribute)); |
| +} |
| + |
| +// Test for NSAccessibilityTitleAttribute. |
| +TEST_F(NativeWidgetMacAccessibilityTest, TitleAttribute) { |
| + AddChildTextfield(widget()->GetContentsView()->size()); |
| + |
| + EXPECT_NSEQ(base::SysUTF16ToNSString(kTestTextfieldTitle), |
| + AttributeValueAtMidpoint(NSAccessibilityTitleAttribute)); |
| +} |
| + |
| +// Test for NSAccessibilityRoleDescriptionAttribute, including for subroles as |
| +// well. |
| +TEST_F(NativeWidgetMacAccessibilityTest, RoleDescriptionAttribute) { |
| + Textfield* textfield = AddChildTextfield(widget()->GetContentsView()->size()); |
| + |
| + NSString* role_description = |
| + NSAccessibilityRoleDescription(NSAccessibilityTextFieldRole, nil); |
| + EXPECT_NSEQ(role_description, AttributeValueAtMidpoint( |
| + NSAccessibilityRoleDescriptionAttribute)); |
| + |
| + // Test subrole role descriptions take precedence over the main role. |
| + textfield->SetTextInputType(ui::TEXT_INPUT_TYPE_PASSWORD); |
| + role_description = NSAccessibilityRoleDescription( |
| + NSAccessibilityTextFieldRole, NSAccessibilitySecureTextFieldSubrole); |
| + EXPECT_NSEQ(role_description, AttributeValueAtMidpoint( |
| + NSAccessibilityRoleDescriptionAttribute)); |
| +} |
| + |
| +// Test for NSAccessibilityValueAttribute. |
| +TEST_F(NativeWidgetMacAccessibilityTest, ValueAttribute) { |
| + AddChildTextfield(widget()->GetContentsView()->size()); |
| + |
| + EXPECT_NSEQ(base::SysUTF16ToNSString(kTestString), |
| + AttributeValueAtMidpoint(NSAccessibilityValueAttribute)); |
| +} |
| + |
| +} // namespace views |