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. 4 5 #import <Cocoa/Cocoa.h> 6 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/gfx/test/ui_cocoa_test_helper.h" 16 17 namespace content { 18 19 class BrowserAccessibilityTest : public ui::CocoaTest { 20 public: 21 virtual void SetUp() { 22 CocoaTest::SetUp(); 23 RebuildAccessibilityTree(); 24 } 25 26 protected: 27 void RebuildAccessibilityTree() { 28 ui::AXNodeData root; 29 root.id = 1000; 30 root.location.set_width(500); 31 root.location.set_height(100); 32 root.role = ui::AX_ROLE_ROOT_WEB_AREA; 33 root.AddStringAttribute(ui::AX_ATTR_HELP, "HelpText"); 34 root.child_ids.push_back(1001); 35 root.child_ids.push_back(1002); 36 37 ui::AXNodeData child1; 38 child1.id = 1001; 39 child1.SetName("Child1"); 40 child1.location.set_width(250); 41 child1.location.set_height(100); 42 child1.role = ui::AX_ROLE_BUTTON; 43 44 ui::AXNodeData child2; 45 child2.id = 1002; 46 child2.location.set_x(250); 47 child2.location.set_width(250); 48 child2.location.set_height(100); 49 child2.role = ui::AX_ROLE_HEADING; 50 51 manager_.reset( 52 new BrowserAccessibilityManagerMac( 53 nil, 54 MakeAXTreeUpdate(root, child1, child2), 55 NULL)); 56 accessibility_.reset([manager_->GetRoot()->ToBrowserAccessibilityCocoa() 57 retain]); 58 } 59 60 base::scoped_nsobject<BrowserAccessibilityCocoa> accessibility_; 61 scoped_ptr<BrowserAccessibilityManager> manager_; 62 }; 63 64 // Standard hit test. 65 TEST_F(BrowserAccessibilityTest, HitTestTest) { 66 BrowserAccessibilityCocoa* firstChild = 67 [accessibility_ accessibilityHitTest:NSMakePoint(50, 50)]; 68 EXPECT_NSEQ(@"Child1", 69 [firstChild accessibilityAttributeValue:NSAccessibilityTitleAttribute]); 70 } 71 72 // Test doing a hit test on the edge of a child. 73 TEST_F(BrowserAccessibilityTest, EdgeHitTest) { 74 BrowserAccessibilityCocoa* firstChild = 75 [accessibility_ accessibilityHitTest:NSZeroPoint]; 76 EXPECT_NSEQ(@"Child1", 77 [firstChild accessibilityAttributeValue:NSAccessibilityTitleAttribute]); 78 } 79 80 // This will test a hit test with invalid coordinates. It is assumed that 81 // the hit test has been narrowed down to this object or one of its children 82 // so it should return itself since it has no better hit result. 83 TEST_F(BrowserAccessibilityTest, InvalidHitTestCoordsTest) { 84 BrowserAccessibilityCocoa* hitTestResult = 85 [accessibility_ accessibilityHitTest:NSMakePoint(-50, 50)]; 86 EXPECT_NSEQ(accessibility_, hitTestResult); 87 } 88 89 // Test to ensure querying standard attributes works. 90 TEST_F(BrowserAccessibilityTest, BasicAttributeTest) { 91 NSString* helpText = [accessibility_ 92 accessibilityAttributeValue:NSAccessibilityHelpAttribute]; 93 EXPECT_NSEQ(@"HelpText", helpText); 94 } 95 96 // Test querying for an invalid attribute to ensure it doesn't crash. 97 TEST_F(BrowserAccessibilityTest, InvalidAttributeTest) { 98 NSString* shouldBeNil = [accessibility_ 99 accessibilityAttributeValue:@"NSAnInvalidAttribute"]; 100 EXPECT_TRUE(shouldBeNil == nil); 101 } 102 103 TEST_F(BrowserAccessibilityTest, RetainedDetachedObjectsReturnNil) { 104 // Get the first child. 105 BrowserAccessibilityCocoa* retainedFirstChild = 106 [accessibility_ accessibilityHitTest:NSMakePoint(50, 50)]; 107 EXPECT_NSEQ(@"Child1", [retainedFirstChild 108 accessibilityAttributeValue:NSAccessibilityTitleAttribute]); 109 110 // Retain it. This simulates what the system might do with an 111 // accessibility object. 112 [retainedFirstChild retain]; 113 114 // Rebuild the accessibility tree, which should detach |retainedFirstChild|. 115 RebuildAccessibilityTree(); 116 117 // Now any attributes we query should return nil. 118 EXPECT_EQ(nil, [retainedFirstChild 119 accessibilityAttributeValue:NSAccessibilityTitleAttribute]); 120 121 // Don't leak memory in the test. 122 [retainedFirstChild release]; 123 } 124 125 } // namespace content 126