Chromium Code Reviews| Index: ui/accessibility/platform/ax_platform_node_win_unittest.cc |
| diff --git a/ui/accessibility/platform/ax_platform_node_win_unittest.cc b/ui/accessibility/platform/ax_platform_node_win_unittest.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..ffd03640cb385e0a8d4f2e656fba7793ea92c741 |
| --- /dev/null |
| +++ b/ui/accessibility/platform/ax_platform_node_win_unittest.cc |
| @@ -0,0 +1,299 @@ |
| +// Copyright 2015 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 <atlbase.h> |
| +#include <atlcom.h> |
| +#include <oleacc.h> |
| + |
| +#include "base/memory/scoped_ptr.h" |
| +#include "base/win/scoped_bstr.h" |
| +#include "base/win/scoped_comptr.h" |
| +#include "base/win/scoped_variant.h" |
| +#include "testing/gtest/include/gtest/gtest.h" |
| +#include "third_party/iaccessible2/ia2_api_all.h" |
| +#include "ui/accessibility/ax_node_data.h" |
| +#include "ui/accessibility/platform/ax_platform_node.h" |
| +#include "ui/accessibility/platform/test_ax_node_wrapper.h" |
| +#include "ui/base/win/atl_module.h" |
| + |
| +namespace ui { |
| + |
| +namespace { |
| + |
| +// Most IAccessible functions require a VARIANT set to CHILDID_SELF as |
| +// the first argument. |
| +base::win::ScopedVariant SELF(CHILDID_SELF); |
| + |
| +} // namespace |
| + |
| +class AXPlatformNodeWinTest : public testing::Test { |
| + public: |
| + AXPlatformNodeWinTest() {} |
| + virtual ~AXPlatformNodeWinTest() {} |
| + |
| + void SetUp() override { |
| + win::CreateATLModuleIfNeeded(); |
| + } |
| + |
| + // Initialize given an AXTreeUpdate. |
| + void Init(const AXTreeUpdate& initial_state) { |
| + tree_.reset(new AXTree(initial_state)); |
| + } |
| + |
| + // Convenience functions to initialize directly from a few AXNodeDatas. |
| + void Init(const AXNodeData& node1) { |
| + AXTreeUpdate update; |
| + update.nodes.push_back(node1); |
| + Init(update); |
| + } |
| + |
| + void Init(const AXNodeData& node1, |
| + const AXNodeData& node2) { |
| + AXTreeUpdate update; |
| + update.nodes.push_back(node1); |
| + update.nodes.push_back(node2); |
| + Init(update); |
| + } |
| + |
| + void Init(const AXNodeData& node1, |
| + const AXNodeData& node2, |
| + const AXNodeData& node3) { |
| + AXTreeUpdate update; |
| + update.nodes.push_back(node1); |
| + update.nodes.push_back(node2); |
| + update.nodes.push_back(node3); |
| + Init(update); |
| + } |
| + |
| + protected: |
| + AXNode* GetRootNode() { |
| + return tree_->GetRoot(); |
| + } |
| + |
| + IAccessible* IAccessibleFromNode(AXNode* node) { |
| + TestAXNodeWrapper* wrapper = |
| + TestAXNodeWrapper::GetOrCreate(tree_.get(), node); |
| + AXPlatformNode* ax_platform_node = wrapper->ax_platform_node(); |
| + return ax_platform_node->GetNativeViewAccessible(); |
| + } |
| + |
| + IAccessible* GetRootIAccessible() { |
| + return IAccessibleFromNode(GetRootNode()); |
| + } |
| + |
| + base::win::ScopedComPtr<IAccessible2> ToIAccessible2( |
| + IAccessible* accessible) { |
| + base::win::ScopedComPtr<IServiceProvider> service_provider; |
| + CHECK(SUCCEEDED(accessible->QueryInterface(service_provider.Receive()))); |
| + base::win::ScopedComPtr<IAccessible2> result; |
| + CHECK(SUCCEEDED( |
| + service_provider->QueryService(IID_IAccessible2, result.Receive()))); |
| + return result; |
| + } |
| + |
| + scoped_ptr<AXTree> tree_; |
| +}; |
| + |
| +TEST_F(AXPlatformNodeWinTest, TestIAccessibleName) { |
| + AXNodeData root; |
| + root.id = 1; |
| + root.role = AX_ROLE_ROOT_WEB_AREA; |
| + root.AddStringAttribute(AX_ATTR_NAME, "Name"); |
| + Init(root); |
| + |
| + base::win::ScopedBstr name; |
| + ASSERT_EQ(S_OK, GetRootIAccessible()->get_accName(SELF, name.Receive())); |
| + EXPECT_EQ(L"Name", base::string16(name)); |
| +} |
| + |
| +TEST_F(AXPlatformNodeWinTest, TestIAccessibleDescription) { |
| + AXNodeData root; |
| + root.id = 1; |
| + root.role = AX_ROLE_ROOT_WEB_AREA; |
| + root.AddStringAttribute(AX_ATTR_DESCRIPTION, "Description"); |
| + Init(root); |
| + |
| + base::win::ScopedBstr description; |
| + ASSERT_EQ(S_OK, GetRootIAccessible()->get_accDescription( |
| + SELF, description.Receive())); |
| + EXPECT_EQ(L"Description", base::string16(description)); |
| +} |
| + |
| +TEST_F(AXPlatformNodeWinTest, TestIAccessibleHelp) { |
| + AXNodeData root; |
| + root.id = 1; |
| + root.role = AX_ROLE_ROOT_WEB_AREA; |
| + root.AddStringAttribute(AX_ATTR_HELP, "Help"); |
| + Init(root); |
| + |
| + base::win::ScopedBstr help; |
| + ASSERT_EQ(S_OK, GetRootIAccessible()->get_accHelp(SELF, help.Receive())); |
| + EXPECT_EQ(L"Help", base::string16(help)); |
|
David Tseng
2015/02/18 19:51:19
You can throw in some negative test scenarios in t
dmazzoni
2015/02/18 23:20:20
Good idea, done.
|
| +} |
| + |
| +TEST_F(AXPlatformNodeWinTest, TestIAccessibleValue) { |
| + AXNodeData root; |
| + root.id = 1; |
| + root.role = AX_ROLE_ROOT_WEB_AREA; |
| + root.AddStringAttribute(AX_ATTR_VALUE, "Value"); |
| + Init(root); |
| + |
| + base::win::ScopedBstr value; |
| + ASSERT_EQ(S_OK, GetRootIAccessible()->get_accValue(SELF, value.Receive())); |
| + EXPECT_EQ(L"Value", base::string16(value)); |
| +} |
| + |
| +TEST_F(AXPlatformNodeWinTest, TestIAccessibleShortcut) { |
| + AXNodeData root; |
| + root.id = 1; |
| + root.role = AX_ROLE_ROOT_WEB_AREA; |
| + root.AddStringAttribute(AX_ATTR_SHORTCUT, "Shortcut"); |
| + Init(root); |
| + |
| + base::win::ScopedBstr shortcut; |
| + ASSERT_EQ(S_OK, GetRootIAccessible()->get_accKeyboardShortcut( |
| + SELF, shortcut.Receive())); |
| + EXPECT_EQ(L"Shortcut", base::string16(shortcut)); |
| +} |
| + |
| +TEST_F(AXPlatformNodeWinTest, TestIAccessibleRole) { |
| + AXNodeData root; |
| + root.id = 1; |
| + root.role = AX_ROLE_ROOT_WEB_AREA; |
| + root.child_ids.push_back(2); |
| + |
| + AXNodeData child; |
| + child.id = 2; |
| + |
| + Init(root, child); |
| + AXNode* child_node = GetRootNode()->children()[0]; |
| + IAccessible* child_iaccessible = IAccessibleFromNode(child_node); |
| + |
| + base::win::ScopedVariant role; |
| + |
| + child.role = AX_ROLE_ALERT; |
| + child_node->SetData(child); |
| + ASSERT_EQ(S_OK, child_iaccessible->get_accRole(SELF, role.Receive())); |
| + EXPECT_EQ(ROLE_SYSTEM_ALERT, V_I4(&role)); |
| + |
| + child.role = AX_ROLE_BUTTON; |
| + child_node->SetData(child); |
| + ASSERT_EQ(S_OK, child_iaccessible->get_accRole(SELF, role.Receive())); |
| + EXPECT_EQ(ROLE_SYSTEM_PUSHBUTTON, V_I4(&role)); |
| + |
| + child.role = AX_ROLE_POP_UP_BUTTON; |
| + child_node->SetData(child); |
| + ASSERT_EQ(S_OK, child_iaccessible->get_accRole(SELF, role.Receive())); |
| + EXPECT_EQ(ROLE_SYSTEM_BUTTONMENU, V_I4(&role)); |
| +} |
| + |
| +TEST_F(AXPlatformNodeWinTest, TestIAccessibleLocation) { |
| + AXNodeData root; |
| + root.id = 1; |
| + root.role = AX_ROLE_ROOT_WEB_AREA; |
| + root.location = gfx::Rect(10, 40, 800, 600); |
| + Init(root); |
| + |
| + TestAXNodeWrapper::SetGlobalCoordinateOffset(gfx::Vector2d(100, 200)); |
| + |
| + LONG x_left, y_top, width, height; |
| + ASSERT_EQ(S_OK, GetRootIAccessible()->accLocation( |
| + &x_left, &y_top, &width, &height, SELF)); |
| + EXPECT_EQ(110, x_left); |
| + EXPECT_EQ(240, y_top); |
| + EXPECT_EQ(800, width); |
| + EXPECT_EQ(600, height); |
| +} |
| + |
| +TEST_F(AXPlatformNodeWinTest, TestIAccessibleChildAndParent) { |
| + AXNodeData root; |
| + root.id = 1; |
| + root.role = AX_ROLE_ROOT_WEB_AREA; |
| + root.child_ids.push_back(2); |
| + root.child_ids.push_back(3); |
| + |
| + AXNodeData button; |
| + button.role = AX_ROLE_BUTTON; |
| + button.id = 2; |
| + |
| + AXNodeData checkbox; |
| + checkbox.role = AX_ROLE_CHECK_BOX; |
| + checkbox.id = 3; |
| + |
| + Init(root, button, checkbox); |
| + AXNode* button_node = GetRootNode()->children()[0]; |
| + AXNode* checkbox_node = GetRootNode()->children()[1]; |
| + IAccessible* root_iaccessible = GetRootIAccessible(); |
| + IAccessible* button_iaccessible = IAccessibleFromNode(button_node); |
| + IAccessible* checkbox_iaccessible = IAccessibleFromNode(checkbox_node); |
| + |
| + LONG child_count; |
| + ASSERT_EQ(S_OK, root_iaccessible->get_accChildCount(&child_count)); |
| + ASSERT_EQ(2L, child_count); |
| + ASSERT_EQ(S_OK, button_iaccessible->get_accChildCount(&child_count)); |
| + ASSERT_EQ(0L, child_count); |
| + ASSERT_EQ(S_OK, checkbox_iaccessible->get_accChildCount(&child_count)); |
| + ASSERT_EQ(0L, child_count); |
| + |
| + { |
| + base::win::ScopedComPtr<IDispatch> result; |
| + ASSERT_EQ(S_OK, root_iaccessible->get_accChild(SELF, result.Receive())); |
| + ASSERT_EQ(result.get(), root_iaccessible); |
| + } |
| + |
| + { |
| + base::win::ScopedComPtr<IDispatch> result; |
| + base::win::ScopedVariant child1(1); |
| + ASSERT_EQ(S_OK, root_iaccessible->get_accChild(child1, result.Receive())); |
| + ASSERT_EQ(result.get(), button_iaccessible); |
| + } |
| + |
| + { |
| + base::win::ScopedComPtr<IDispatch> result; |
| + base::win::ScopedVariant child2(2); |
| + ASSERT_EQ(S_OK, root_iaccessible->get_accChild(child2, result.Receive())); |
| + ASSERT_EQ(result.get(), checkbox_iaccessible); |
| + } |
| + |
| + { |
| + // Asking for child id 3 should fail. |
| + base::win::ScopedComPtr<IDispatch> result; |
| + base::win::ScopedVariant child3(3); |
| + ASSERT_EQ(E_FAIL, root_iaccessible->get_accChild(child3, result.Receive())); |
| + } |
| + |
| + // We should be able to ask for the button by its unique id too. |
| + LONG button_unique_id; |
| + base::win::ScopedComPtr<IAccessible2> button_iaccessible2 = |
| + ToIAccessible2(button_iaccessible); |
| + button_iaccessible2->get_uniqueID(&button_unique_id); |
| + ASSERT_LT(button_unique_id, 0); |
| + { |
| + base::win::ScopedComPtr<IDispatch> result; |
| + base::win::ScopedVariant button_id_variant(button_unique_id); |
| + ASSERT_EQ(S_OK, root_iaccessible->get_accChild(button_id_variant, |
| + result.Receive())); |
| + ASSERT_EQ(result.get(), button_iaccessible); |
| + } |
| + |
| + // Now check parents. |
| + { |
| + base::win::ScopedComPtr<IDispatch> result; |
| + ASSERT_EQ(S_OK, button_iaccessible->get_accParent(result.Receive())); |
| + ASSERT_EQ(result.get(), root_iaccessible); |
| + } |
| + |
| + { |
| + base::win::ScopedComPtr<IDispatch> result; |
| + ASSERT_EQ(S_OK, checkbox_iaccessible->get_accParent(result.Receive())); |
| + ASSERT_EQ(result.get(), root_iaccessible); |
| + } |
| + |
| + { |
| + base::win::ScopedComPtr<IDispatch> result; |
| + ASSERT_EQ(S_FALSE, root_iaccessible->get_accParent(result.Receive())); |
| + } |
| +} |
| + |
| +} // namespace ui |