1 // Copyright (c) 2012 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.
5 #import <Cocoa/Cocoa.h>
7 #include "base/memory/scoped_ptr.h"
8 #include "base/strings/string_util.h"
9 #include "base/strings/utf_string_conversions.h"
10 #include "content/browser/accessibility/browser_accessibility_cocoa.h"
11 #include "content/browser/accessibility/browser_accessibility_manager.h"
12 #include "content/browser/accessibility/browser_accessibility_manager_mac.h"
13 #include "testing/gtest/include/gtest/gtest.h"
14 #import "testing/gtest_mac.h"
15 #import "ui/base/test/ui_cocoa_test_helper.h"
17 @interface MockAccessibilityDelegate :
18 NSView<BrowserAccessibilityDelegateCocoa>
20 - (NSPoint)accessibilityPointInScreen:(BrowserAccessibilityCocoa*)accessibility;
21 - (void)doDefaultAction:(int32)accessibilityObjectId;
22 - (void)accessibilitySetTextSelection:(int32)accId
23 startOffset:(int32)startOffset
24 endOffset:(int32)endOffset;
25 - (void)performShowMenuAction:(BrowserAccessibilityCocoa*)accessibility;
26 - (void)setAccessibilityFocus:(BOOL)focus
27 accessibilityId:(int32)accessibilityObjectId;
32 @implementation MockAccessibilityDelegate
34 - (NSPoint)accessibilityPointInScreen:
35 (BrowserAccessibilityCocoa*)accessibility {
38 - (void)doDefaultAction:(int32)accessibilityObjectId {
40 - (void)accessibilitySetTextSelection:(int32)accId
41 startOffset:(int32)startOffset
42 endOffset:(int32)endOffset {
44 - (void)performShowMenuAction:(BrowserAccessibilityCocoa*)accessibility {
46 - (void)setAccessibilityFocus:(BOOL)focus
47 accessibilityId:(int32)accessibilityObjectId {
57 class BrowserAccessibilityTest : public ui::CocoaTest {
59 virtual void SetUp() {
61 RebuildAccessibilityTree();
65 void RebuildAccessibilityTree() {
66 AccessibilityNodeData root;
68 root.location.set_width(500);
69 root.location.set_height(100);
70 root.role = WebKit::WebAXRoleRootWebArea;
71 root.AddStringAttribute(AccessibilityNodeData::ATTR_HELP, "HelpText");
72 root.child_ids.push_back(1001);
73 root.child_ids.push_back(1002);
75 AccessibilityNodeData child1;
77 child1.SetName("Child1");
78 child1.location.set_width(250);
79 child1.location.set_height(100);
80 child1.role = WebKit::WebAXRoleButton;
82 AccessibilityNodeData child2;
84 child2.location.set_x(250);
85 child2.location.set_width(250);
86 child2.location.set_height(100);
87 child2.role = WebKit::WebAXRoleHeading;
89 delegate_.reset([[MockAccessibilityDelegate alloc] init]);
91 new BrowserAccessibilityManagerMac(delegate_, root, NULL));
92 manager_->UpdateNodesForTesting(child1, child2);
93 accessibility_.reset([manager_->GetRoot()->ToBrowserAccessibilityCocoa()
97 base::scoped_nsobject<MockAccessibilityDelegate> delegate_;
98 base::scoped_nsobject<BrowserAccessibilityCocoa> accessibility_;
99 scoped_ptr<BrowserAccessibilityManager> manager_;
102 // Standard hit test.
103 TEST_F(BrowserAccessibilityTest, HitTestTest) {
104 BrowserAccessibilityCocoa* firstChild =
105 [accessibility_ accessibilityHitTest:NSMakePoint(50, 50)];
106 EXPECT_NSEQ(@"Child1",
107 [firstChild accessibilityAttributeValue:NSAccessibilityTitleAttribute]);
110 // Test doing a hit test on the edge of a child.
111 TEST_F(BrowserAccessibilityTest, EdgeHitTest) {
112 BrowserAccessibilityCocoa* firstChild =
113 [accessibility_ accessibilityHitTest:NSZeroPoint];
114 EXPECT_NSEQ(@"Child1",
115 [firstChild accessibilityAttributeValue:NSAccessibilityTitleAttribute]);
118 // This will test a hit test with invalid coordinates. It is assumed that
119 // the hit test has been narrowed down to this object or one of its children
120 // so it should return itself since it has no better hit result.
121 TEST_F(BrowserAccessibilityTest, InvalidHitTestCoordsTest) {
122 BrowserAccessibilityCocoa* hitTestResult =
123 [accessibility_ accessibilityHitTest:NSMakePoint(-50, 50)];
124 EXPECT_NSEQ(accessibility_, hitTestResult);
127 // Test to ensure querying standard attributes works.
128 TEST_F(BrowserAccessibilityTest, BasicAttributeTest) {
129 NSString* helpText = [accessibility_
130 accessibilityAttributeValue:NSAccessibilityHelpAttribute];
131 EXPECT_NSEQ(@"HelpText", helpText);
134 // Test querying for an invalid attribute to ensure it doesn't crash.
135 TEST_F(BrowserAccessibilityTest, InvalidAttributeTest) {
136 NSString* shouldBeNil = [accessibility_
137 accessibilityAttributeValue:@"NSAnInvalidAttribute"];
138 EXPECT_TRUE(shouldBeNil == nil);
141 TEST_F(BrowserAccessibilityTest, RetainedDetachedObjectsReturnNil) {
142 // Get the first child.
143 BrowserAccessibilityCocoa* retainedFirstChild =
144 [accessibility_ accessibilityHitTest:NSMakePoint(50, 50)];
145 EXPECT_NSEQ(@"Child1", [retainedFirstChild
146 accessibilityAttributeValue:NSAccessibilityTitleAttribute]);
148 // Retain it. This simulates what the system might do with an
149 // accessibility object.
150 [retainedFirstChild retain];
152 // Rebuild the accessibility tree, which should detach |retainedFirstChild|.
153 RebuildAccessibilityTree();
155 // Now any attributes we query should return nil.
156 EXPECT_EQ(nil, [retainedFirstChild
157 accessibilityAttributeValue:NSAccessibilityTitleAttribute]);
159 // Don't leak memory in the test.
160 [retainedFirstChild release];
163 } // namespace content