blob: 87f2774a6c5a75ce49030beb262cd654d9b99cf4 [file] [log] [blame]
// Copyright 2019 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 "ui/accessibility/platform/ax_fragment_root_win.h"
#include "ui/accessibility/platform/ax_platform_node_win.h"
#include "ui/accessibility/platform/ax_platform_node_win_unittest.h"
#include "ui/accessibility/platform/test_ax_node_wrapper.h"
#include <UIAutomationClient.h>
#include <UIAutomationCoreApi.h>
#include "base/auto_reset.h"
#include "base/win/scoped_safearray.h"
#include "base/win/scoped_variant.h"
#include "testing/gtest/include/gtest/gtest.h"
using Microsoft::WRL::ComPtr;
namespace ui {
class AXFragmentRootTest : public ui::AXPlatformNodeWinTest {};
TEST_F(AXFragmentRootTest, TestUIAGetFragmentRoot) {
AXNodeData root;
Init(root);
InitFragmentRoot();
ComPtr<IRawElementProviderFragmentRoot> expected_fragment_root =
GetFragmentRoot();
ComPtr<IRawElementProviderFragment> fragment_provider;
expected_fragment_root.As(&fragment_provider);
ComPtr<IRawElementProviderFragmentRoot> actual_fragment_root;
EXPECT_HRESULT_SUCCEEDED(
fragment_provider->get_FragmentRoot(&actual_fragment_root));
EXPECT_EQ(expected_fragment_root.Get(), actual_fragment_root.Get());
}
TEST_F(AXFragmentRootTest, TestUIAElementProviderFromPoint) {
AXNodeData root_data;
root_data.id = 1;
root_data.relative_bounds.bounds = gfx::RectF(0, 0, 80, 80);
AXNodeData element1_data;
element1_data.id = 2;
element1_data.relative_bounds.bounds = gfx::RectF(0, 0, 50, 50);
root_data.child_ids.push_back(element1_data.id);
AXNodeData element2_data;
element2_data.id = 3;
element2_data.relative_bounds.bounds = gfx::RectF(0, 50, 30, 30);
root_data.child_ids.push_back(element2_data.id);
Init(root_data, element1_data, element2_data);
InitFragmentRoot();
AXNode* root_node = GetRootNode();
AXNode* element1_node = root_node->children()[0];
AXNode* element2_node = root_node->children()[1];
ComPtr<IRawElementProviderFragmentRoot> fragment_root_prov(GetFragmentRoot());
ComPtr<IRawElementProviderFragment> root_provider(
GetRootIRawElementProviderFragment());
ComPtr<IRawElementProviderFragment> element1_provider =
QueryInterfaceFromNode<IRawElementProviderFragment>(element1_node);
ComPtr<IRawElementProviderFragment> element2_provider =
QueryInterfaceFromNode<IRawElementProviderFragment>(element2_node);
ComPtr<IRawElementProviderFragment> provider_from_point;
EXPECT_HRESULT_SUCCEEDED(fragment_root_prov->ElementProviderFromPoint(
23, 31, &provider_from_point));
EXPECT_EQ(element1_provider.Get(), provider_from_point.Get());
EXPECT_HRESULT_SUCCEEDED(fragment_root_prov->ElementProviderFromPoint(
23, 67, &provider_from_point));
EXPECT_EQ(element2_provider.Get(), provider_from_point.Get());
EXPECT_HRESULT_SUCCEEDED(fragment_root_prov->ElementProviderFromPoint(
47, 67, &provider_from_point));
EXPECT_EQ(root_provider.Get(), provider_from_point.Get());
// This is on node 1 with scale factor of 1.5.
std::unique_ptr<base::AutoReset<float>> scale_factor_reset =
TestAXNodeWrapper::SetScaleFactor(1.5);
EXPECT_HRESULT_SUCCEEDED(fragment_root_prov->ElementProviderFromPoint(
60, 60, &provider_from_point));
EXPECT_EQ(element1_provider.Get(), provider_from_point.Get());
}
TEST_F(AXFragmentRootTest, TestUIAGetFocus) {
AXNodeData root_data;
root_data.id = 1;
AXNodeData element1_data;
element1_data.id = 2;
root_data.child_ids.push_back(element1_data.id);
AXNodeData element2_data;
element2_data.id = 3;
root_data.child_ids.push_back(element2_data.id);
Init(root_data, element1_data, element2_data);
InitFragmentRoot();
AXNode* root_node = GetRootNode();
AXNode* element1_node = root_node->children()[0];
AXNode* element2_node = root_node->children()[1];
ComPtr<IRawElementProviderFragmentRoot> fragment_root_prov(GetFragmentRoot());
ComPtr<IRawElementProviderFragment> root_provider(
GetRootIRawElementProviderFragment());
ComPtr<IRawElementProviderFragment> element1_provider =
QueryInterfaceFromNode<IRawElementProviderFragment>(element1_node);
ComPtr<IRawElementProviderFragment> element2_provider =
QueryInterfaceFromNode<IRawElementProviderFragment>(element2_node);
ComPtr<IRawElementProviderFragment> focused_fragment;
EXPECT_HRESULT_SUCCEEDED(root_provider->SetFocus());
EXPECT_HRESULT_SUCCEEDED(fragment_root_prov->GetFocus(&focused_fragment));
EXPECT_EQ(root_provider.Get(), focused_fragment.Get());
EXPECT_HRESULT_SUCCEEDED(element1_provider->SetFocus());
EXPECT_HRESULT_SUCCEEDED(fragment_root_prov->GetFocus(&focused_fragment));
EXPECT_EQ(element1_provider.Get(), focused_fragment.Get());
EXPECT_HRESULT_SUCCEEDED(element2_provider->SetFocus());
EXPECT_HRESULT_SUCCEEDED(fragment_root_prov->GetFocus(&focused_fragment));
EXPECT_EQ(element2_provider.Get(), focused_fragment.Get());
}
TEST_F(AXFragmentRootTest, TestUIAErrorHandling) {
AXNodeData root;
Init(root);
InitFragmentRoot();
ComPtr<IRawElementProviderSimple> simple_provider =
GetRootIRawElementProviderSimple();
ComPtr<IRawElementProviderFragment> fragment_provider =
GetRootIRawElementProviderFragment();
ComPtr<IRawElementProviderFragmentRoot> fragment_root_provider =
GetFragmentRoot();
tree_ = std::make_unique<AXTree>();
ax_fragment_root_.reset(nullptr);
ComPtr<IRawElementProviderSimple> returned_simple_provider;
ComPtr<IRawElementProviderFragment> returned_fragment_provider;
ComPtr<IRawElementProviderFragmentRoot> returned_fragment_root_provider;
base::win::ScopedSafearray returned_runtime_id;
EXPECT_EQ(
static_cast<HRESULT>(UIA_E_ELEMENTNOTAVAILABLE),
simple_provider->get_HostRawElementProvider(&returned_simple_provider));
EXPECT_EQ(
static_cast<HRESULT>(UIA_E_ELEMENTNOTAVAILABLE),
fragment_provider->get_FragmentRoot(&returned_fragment_root_provider));
EXPECT_EQ(static_cast<HRESULT>(UIA_E_ELEMENTNOTAVAILABLE),
fragment_provider->GetRuntimeId(returned_runtime_id.Receive()));
EXPECT_EQ(static_cast<HRESULT>(UIA_E_ELEMENTNOTAVAILABLE),
fragment_root_provider->ElementProviderFromPoint(
67, 23, &returned_fragment_provider));
EXPECT_EQ(static_cast<HRESULT>(UIA_E_ELEMENTNOTAVAILABLE),
fragment_root_provider->GetFocus(&returned_fragment_provider));
}
TEST_F(AXFragmentRootTest, TestGetChildCount) {
AXNodeData root;
Init(root);
InitFragmentRoot();
AXPlatformNodeDelegate* fragment_root = ax_fragment_root_.get();
EXPECT_EQ(1, fragment_root->GetChildCount());
test_fragment_root_delegate_->child_ = nullptr;
EXPECT_EQ(0, fragment_root->GetChildCount());
}
TEST_F(AXFragmentRootTest, TestChildAtIndex) {
AXNodeData root;
Init(root);
InitFragmentRoot();
gfx::NativeViewAccessible native_view_accessible =
AXPlatformNodeFromNode(GetRootNode())->GetNativeViewAccessible();
AXPlatformNodeDelegate* fragment_root = ax_fragment_root_.get();
EXPECT_EQ(native_view_accessible, fragment_root->ChildAtIndex(0));
EXPECT_EQ(nullptr, fragment_root->ChildAtIndex(1));
test_fragment_root_delegate_->child_ = nullptr;
EXPECT_EQ(nullptr, fragment_root->ChildAtIndex(0));
}
TEST_F(AXFragmentRootTest, TestGetParent) {
AXNodeData root;
Init(root);
InitFragmentRoot();
AXPlatformNodeDelegate* fragment_root = ax_fragment_root_.get();
EXPECT_EQ(nullptr, fragment_root->GetParent());
gfx::NativeViewAccessible native_view_accessible =
AXPlatformNodeFromNode(GetRootNode())->GetNativeViewAccessible();
test_fragment_root_delegate_->parent_ = native_view_accessible;
EXPECT_EQ(native_view_accessible, fragment_root->GetParent());
}
TEST_F(AXFragmentRootTest, TestGetPropertyValue) {
AXNodeData root;
Init(root);
InitFragmentRoot();
ComPtr<IRawElementProviderSimple> root_provider;
ax_fragment_root_->GetNativeViewAccessible()->QueryInterface(
IID_PPV_ARGS(&root_provider));
// IsControlElement and IsContentElement should follow the setting on the
// fragment root delegate.
test_fragment_root_delegate_->is_control_element_ = true;
base::win::ScopedVariant result;
EXPECT_HRESULT_SUCCEEDED(root_provider->GetPropertyValue(
UIA_IsControlElementPropertyId, result.Receive()));
EXPECT_EQ(result.type(), VT_BOOL);
EXPECT_EQ(result.ptr()->boolVal, VARIANT_TRUE);
EXPECT_HRESULT_SUCCEEDED(root_provider->GetPropertyValue(
UIA_IsContentElementPropertyId, result.Receive()));
EXPECT_EQ(result.type(), VT_BOOL);
EXPECT_EQ(result.ptr()->boolVal, VARIANT_TRUE);
test_fragment_root_delegate_->is_control_element_ = false;
EXPECT_HRESULT_SUCCEEDED(root_provider->GetPropertyValue(
UIA_IsControlElementPropertyId, result.Receive()));
EXPECT_EQ(result.type(), VT_BOOL);
EXPECT_EQ(result.ptr()->boolVal, VARIANT_FALSE);
EXPECT_HRESULT_SUCCEEDED(root_provider->GetPropertyValue(
UIA_IsContentElementPropertyId, result.Receive()));
EXPECT_EQ(result.type(), VT_BOOL);
EXPECT_EQ(result.ptr()->boolVal, VARIANT_FALSE);
// Other properties should return VT_EMPTY.
EXPECT_HRESULT_SUCCEEDED(root_provider->GetPropertyValue(
UIA_ControlTypePropertyId, result.Receive()));
EXPECT_EQ(result.type(), VT_EMPTY);
}
} // namespace ui