Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
Namespaces | Macros | Functions
ax_platform_node_win_unittest.cc File Reference
#include "ax_platform_node_win_unittest.h"
#include <oleacc.h>
#include <wrl/client.h>
#include <memory>
#include "ax_fragment_root_win.h"
#include "ax_platform_node_win.h"
#include "base/auto_reset.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "test_ax_node_wrapper.h"
#include "third_party/accessibility/ax/ax_enums.h"
#include "third_party/accessibility/ax/ax_node_data.h"
#include "third_party/accessibility/base/win/atl_module.h"
#include "third_party/accessibility/base/win/scoped_bstr.h"
#include "third_party/accessibility/base/win/scoped_safearray.h"
#include "third_party/accessibility/base/win/scoped_variant.h"

Go to the source code of this file.

Namespaces

namespace  ui
 

Macros

#define EXPECT_UIA_ELEMENTNOTAVAILABLE(expr)    EXPECT_EQ(static_cast<HRESULT>(UIA_E_ELEMENTNOTAVAILABLE), (expr))
 
#define EXPECT_UIA_INVALIDOPERATION(expr)    EXPECT_EQ(static_cast<HRESULT>(UIA_E_INVALIDOPERATION), (expr))
 
#define EXPECT_UIA_ELEMENTNOTENABLED(expr)    EXPECT_EQ(static_cast<HRESULT>(UIA_E_ELEMENTNOTENABLED), (expr))
 
#define EXPECT_UIA_NOTSUPPORTED(expr)    EXPECT_EQ(static_cast<HRESULT>(UIA_E_NOTSUPPORTED), (expr))
 
#define ASSERT_UIA_ELEMENTNOTAVAILABLE(expr)    ASSERT_EQ(static_cast<HRESULT>(UIA_E_ELEMENTNOTAVAILABLE), (expr))
 
#define ASSERT_UIA_INVALIDOPERATION(expr)    ASSERT_EQ(static_cast<HRESULT>(UIA_E_INVALIDOPERATION), (expr))
 
#define ASSERT_UIA_ELEMENTNOTENABLED(expr)    ASSERT_EQ(static_cast<HRESULT>(UIA_E_ELEMENTNOTENABLED), (expr))
 
#define ASSERT_UIA_NOTSUPPORTED(expr)    ASSERT_EQ(static_cast<HRESULT>(UIA_E_NOTSUPPORTED), (expr))
 
#define EXPECT_UIA_EMPTY(node, property_id)
 
#define EXPECT_UIA_VALUE_EQ(node, property_id, expectedVariant)
 
#define EXPECT_UIA_BSTR_EQ(node, property_id, expected)
 
#define EXPECT_UIA_BOOL_EQ(node, property_id, expected)
 
#define EXPECT_UIA_DOUBLE_ARRAY_EQ(node, array_property_id, expected_property_values)
 
#define EXPECT_UIA_INT_EQ(node, property_id, expected)
 
#define EXPECT_UIA_ELEMENT_ARRAY_BSTR_EQ(array, element_test_property_id, expected_property_values)
 
#define EXPECT_UIA_PROPERTY_ELEMENT_ARRAY_BSTR_EQ(node, array_property_id, element_test_property_id, expected_property_values)
 
#define EXPECT_UIA_PROPERTY_UNORDERED_ELEMENT_ARRAY_BSTR_EQ( node, array_property_id, element_test_property_id, expected_property_values)
 

Functions

 ui::TEST_F (AXPlatformNodeWinTest, IAccessibleDetachedObject)
 
 ui::TEST_F (AXPlatformNodeWinTest, IAccessibleHitTest)
 
 ui::TEST_F (AXPlatformNodeWinTest, IAccessibleHitTestDoesNotLoopForever)
 
 ui::TEST_F (AXPlatformNodeWinTest, IAccessibleName)
 
 ui::TEST_F (AXPlatformNodeWinTest, IAccessibleDescription)
 
 ui::TEST_F (AXPlatformNodeWinTest, IAccessibleAccValue)
 
 ui::TEST_F (AXPlatformNodeWinTest, IAccessibleShortcut)
 
 ui::TEST_F (AXPlatformNodeWinTest, IAccessibleSelectionListBoxOptionNothingSelected)
 
 ui::TEST_F (AXPlatformNodeWinTest, IAccessibleSelectionListBoxOptionOneSelected)
 
 ui::TEST_F (AXPlatformNodeWinTest, IAccessibleSelectionListBoxOptionMultipleSelected)
 
 ui::TEST_F (AXPlatformNodeWinTest, IAccessibleSelectionTableNothingSelected)
 
 ui::TEST_F (AXPlatformNodeWinTest, IAccessibleSelectionTableRowOneSelected)
 
 ui::TEST_F (AXPlatformNodeWinTest, IAccessibleSelectionTableRowMultipleSelected)
 
 ui::TEST_F (AXPlatformNodeWinTest, IAccessibleSelectionTableCellOneSelected)
 
 ui::TEST_F (AXPlatformNodeWinTest, IAccessibleSelectionTableCellMultipleSelected)
 
 ui::TEST_F (AXPlatformNodeWinTest, IAccessibleRole)
 
 ui::TEST_F (AXPlatformNodeWinTest, IAccessibleLocation)
 
 ui::TEST_F (AXPlatformNodeWinTest, IAccessibleChildAndParent)
 
 ui::TEST_F (AXPlatformNodeWinTest, AccNavigate)
 
 ui::TEST_F (AXPlatformNodeWinTest, AnnotatedImageName)
 
 ui::TEST_F (AXPlatformNodeWinTest, IGridProviderGetRowCount)
 
 ui::TEST_F (AXPlatformNodeWinTest, IGridProviderGetColumnCount)
 
 ui::TEST_F (AXPlatformNodeWinTest, IGridProviderGetItem)
 
 ui::TEST_F (AXPlatformNodeWinTest, ITableProviderGetColumnHeaders)
 
 ui::TEST_F (AXPlatformNodeWinTest, ITableProviderGetColumnHeadersMultipleHeaders)
 
 ui::TEST_F (AXPlatformNodeWinTest, ITableProviderGetRowHeaders)
 
 ui::TEST_F (AXPlatformNodeWinTest, ITableProviderGetRowOrColumnMajor)
 
 ui::TEST_F (AXPlatformNodeWinTest, ITableItemProviderGetColumnHeaderItems)
 
 ui::TEST_F (AXPlatformNodeWinTest, ITableItemProviderGetRowHeaderItems)
 
 ui::TEST_F (AXPlatformNodeWinTest, UIAGetPropertySimple)
 
 ui::TEST_F (AXPlatformNodeWinTest, UIAGetPropertyValueClickablePoint)
 
 ui::TEST_F (AXPlatformNodeWinTest, UIAGetPropertyValueIsDialog)
 
 ui::TEST_F (AXPlatformNodeWinTest, UIAGetPropertyValueIsControlElementIgnoredInvisible)
 
 ui::TEST_F (AXPlatformNodeWinTest, UIAGetControllerForPropertyId)
 
 ui::TEST_F (AXPlatformNodeWinTest, UIAGetDescribedByPropertyId)
 
 ui::TEST_F (AXPlatformNodeWinTest, UIAItemStatusPropertyId)
 
 ui::TEST_F (AXPlatformNodeWinTest, UIAGetFlowsToPropertyId)
 
 ui::TEST_F (AXPlatformNodeWinTest, UIAGetPropertyValueFlowsFromNone)
 
 ui::TEST_F (AXPlatformNodeWinTest, UIAGetPropertyValueFlowsFromSingle)
 
 ui::TEST_F (AXPlatformNodeWinTest, UIAGetPropertyValueFlowsFromMultiple)
 
 ui::TEST_F (AXPlatformNodeWinTest, UIAGetPropertyValueFrameworkId)
 
 ui::TEST_F (AXPlatformNodeWinTest, GetPropertyValue_LabeledByTest)
 
 ui::TEST_F (AXPlatformNodeWinTest, GetPropertyValue_HelpText)
 
 ui::TEST_F (AXPlatformNodeWinTest, GetPropertyValue_LocalizedControlType)
 
 ui::TEST_F (AXPlatformNodeWinTest, GetPropertyValue_IsControlElement)
 
 ui::TEST_F (AXPlatformNodeWinTest, UIAGetProviderOptions)
 
 ui::TEST_F (AXPlatformNodeWinTest, UIAGetHostRawElementProvider)
 
 ui::TEST_F (AXPlatformNodeWinTest, UIAGetBoundingRectangle)
 
 ui::TEST_F (AXPlatformNodeWinTest, UIAGetFragmentRoot)
 
 ui::TEST_F (AXPlatformNodeWinTest, UIAGetEmbeddedFragmentRoots)
 
 ui::TEST_F (AXPlatformNodeWinTest, UIAGetRuntimeId)
 
 ui::TEST_F (AXPlatformNodeWinTest, UIAIWindowProviderGetIsModalUnset)
 
 ui::TEST_F (AXPlatformNodeWinTest, UIAIWindowProviderGetIsModalFalse)
 
 ui::TEST_F (AXPlatformNodeWinTest, UIAIWindowProviderGetIsModalTrue)
 
 ui::TEST_F (AXPlatformNodeWinTest, UIAIWindowProviderInvalidArgument)
 
 ui::TEST_F (AXPlatformNodeWinTest, UIAIWindowProviderNotSupported)
 
 ui::TEST_F (AXPlatformNodeWinTest, UIANavigate)
 
 ui::TEST_F (AXPlatformNodeWinTest, ISelectionProviderCanSelectMultipleDefault)
 
 ui::TEST_F (AXPlatformNodeWinTest, ISelectionProviderCanSelectMultipleTrue)
 
 ui::TEST_F (AXPlatformNodeWinTest, ISelectionProviderIsSelectionRequiredDefault)
 
 ui::TEST_F (AXPlatformNodeWinTest, ISelectionProviderIsSelectionRequiredTrue)
 
 ui::TEST_F (AXPlatformNodeWinTest, ISelectionProviderGetSelectionNoneSelected)
 
 ui::TEST_F (AXPlatformNodeWinTest, ISelectionProviderGetSelectionSingleItemSelected)
 
 ui::TEST_F (AXPlatformNodeWinTest, ISelectionProviderGetSelectionMultipleItemsSelected)
 
 ui::TEST_F (AXPlatformNodeWinTest, ComputeUIAControlType)
 
 ui::TEST_F (AXPlatformNodeWinTest, UIALandmarkType)
 
 ui::TEST_F (AXPlatformNodeWinTest, UIALocalizedLandmarkType)
 
 ui::TEST_F (AXPlatformNodeWinTest, IRawElementProviderSimple2ShowContextMenu)
 
 ui::TEST_F (AXPlatformNodeWinTest, UIAErrorHandling)
 
 ui::TEST_F (AXPlatformNodeWinTest, GetPatternProviderSupportedPatterns)
 
 ui::TEST_F (AXPlatformNodeWinTest, GetPatternProviderExpandCollapsePattern)
 
 ui::TEST_F (AXPlatformNodeWinTest, GetPatternProviderInvokePattern)
 
 ui::TEST_F (AXPlatformNodeWinTest, IExpandCollapsePatternProviderAction)
 
 ui::TEST_F (AXPlatformNodeWinTest, IInvokeProviderInvoke)
 
 ui::TEST_F (AXPlatformNodeWinTest, ISelectionItemProviderNotSupported)
 
 ui::TEST_F (AXPlatformNodeWinTest, ISelectionItemProviderDisabled)
 
 ui::TEST_F (AXPlatformNodeWinTest, ISelectionItemProviderNotSelectable)
 
 ui::TEST_F (AXPlatformNodeWinTest, ISelectionItemProviderSimple)
 
 ui::TEST_F (AXPlatformNodeWinTest, ISelectionItemProviderRadioButton)
 
 ui::TEST_F (AXPlatformNodeWinTest, ISelectionItemProviderMenuItemRadio)
 
 ui::TEST_F (AXPlatformNodeWinTest, ISelectionItemProviderTable)
 
 ui::TEST_F (AXPlatformNodeWinTest, ISelectionItemProviderGrid)
 
 ui::TEST_F (AXPlatformNodeWinTest, ISelectionItemProviderGetSelectionContainer)
 
 ui::TEST_F (AXPlatformNodeWinTest, ISelectionItemProviderSelectFollowFocus)
 
 ui::TEST_F (AXPlatformNodeWinTest, IValueProvider_GetValue)
 
 ui::TEST_F (AXPlatformNodeWinTest, IValueProvider_SetValue)
 
 ui::TEST_F (AXPlatformNodeWinTest, IValueProvider_IsReadOnly)
 
 ui::TEST_F (AXPlatformNodeWinTest, IScrollProviderSetScrollPercent)
 
 ui::TEST_F (AXPlatformNodeWinTest, MojoEventToUIAPropertyTest)
 

Macro Definition Documentation

◆ ASSERT_UIA_ELEMENTNOTAVAILABLE

#define ASSERT_UIA_ELEMENTNOTAVAILABLE (   expr)     ASSERT_EQ(static_cast<HRESULT>(UIA_E_ELEMENTNOTAVAILABLE), (expr))

Definition at line 53 of file ax_platform_node_win_unittest.cc.

69 { \
70 ScopedVariant actual; \
71 ASSERT_HRESULT_SUCCEEDED( \
72 node->GetPropertyValue(property_id, actual.Receive())); \
73 EXPECT_EQ(VT_EMPTY, actual.type()); \
74 }
75
76#define EXPECT_UIA_VALUE_EQ(node, property_id, expectedVariant) \
77 { \
78 ScopedVariant actual; \
79 ASSERT_HRESULT_SUCCEEDED( \
80 node->GetPropertyValue(property_id, actual.Receive())); \
81 EXPECT_EQ(0, actual.Compare(expectedVariant)); \
82 }
83
84#define EXPECT_UIA_BSTR_EQ(node, property_id, expected) \
85 { \
86 ScopedVariant expectedVariant(expected); \
87 ASSERT_EQ(VT_BSTR, expectedVariant.type()); \
88 ASSERT_NE(nullptr, expectedVariant.ptr()->bstrVal); \
89 ScopedVariant actual; \
90 ASSERT_HRESULT_SUCCEEDED( \
91 node->GetPropertyValue(property_id, actual.Receive())); \
92 ASSERT_EQ(VT_BSTR, actual.type()); \
93 ASSERT_NE(nullptr, actual.ptr()->bstrVal); \
94 EXPECT_STREQ(expectedVariant.ptr()->bstrVal, actual.ptr()->bstrVal); \
95 }
96
97#define EXPECT_UIA_BOOL_EQ(node, property_id, expected) \
98 { \
99 ScopedVariant expectedVariant(expected); \
100 ASSERT_EQ(VT_BOOL, expectedVariant.type()); \
101 ScopedVariant actual; \
102 ASSERT_HRESULT_SUCCEEDED( \
103 node->GetPropertyValue(property_id, actual.Receive())); \
104 EXPECT_EQ(expectedVariant.ptr()->boolVal, actual.ptr()->boolVal); \
105 }
106
107#define EXPECT_UIA_DOUBLE_ARRAY_EQ(node, array_property_id, \
108 expected_property_values) \
109 { \
110 ScopedVariant array; \
111 ASSERT_HRESULT_SUCCEEDED( \
112 node->GetPropertyValue(array_property_id, array.Receive())); \
113 ASSERT_EQ(VT_ARRAY | VT_R8, array.type()); \
114 ASSERT_EQ(1u, SafeArrayGetDim(array.ptr()->parray)); \
115 LONG array_lower_bound; \
116 ASSERT_HRESULT_SUCCEEDED( \
117 SafeArrayGetLBound(array.ptr()->parray, 1, &array_lower_bound)); \
118 LONG array_upper_bound; \
119 ASSERT_HRESULT_SUCCEEDED( \
120 SafeArrayGetUBound(array.ptr()->parray, 1, &array_upper_bound)); \
121 double* array_data; \
122 ASSERT_HRESULT_SUCCEEDED(::SafeArrayAccessData( \
123 array.ptr()->parray, reinterpret_cast<void**>(&array_data))); \
124 size_t count = array_upper_bound - array_lower_bound + 1; \
125 ASSERT_EQ(expected_property_values.size(), count); \
126 for (size_t i = 0; i < count; ++i) { \
127 EXPECT_EQ(array_data[i], expected_property_values[i]); \
128 } \
129 ASSERT_HRESULT_SUCCEEDED(::SafeArrayUnaccessData(array.ptr()->parray)); \
130 }
131
132#define EXPECT_UIA_INT_EQ(node, property_id, expected) \
133 { \
134 ScopedVariant expectedVariant(expected); \
135 ASSERT_EQ(VT_I4, expectedVariant.type()); \
136 ScopedVariant actual; \
137 ASSERT_HRESULT_SUCCEEDED( \
138 node->GetPropertyValue(property_id, actual.Receive())); \
139 EXPECT_EQ(expectedVariant.ptr()->intVal, actual.ptr()->intVal); \
140 }
141
142#define EXPECT_UIA_ELEMENT_ARRAY_BSTR_EQ(array, element_test_property_id, \
143 expected_property_values) \
144 { \
145 ASSERT_EQ(1u, SafeArrayGetDim(array)); \
146 LONG array_lower_bound; \
147 ASSERT_HRESULT_SUCCEEDED( \
148 SafeArrayGetLBound(array, 1, &array_lower_bound)); \
149 LONG array_upper_bound; \
150 ASSERT_HRESULT_SUCCEEDED( \
151 SafeArrayGetUBound(array, 1, &array_upper_bound)); \
152 IUnknown** array_data; \
153 ASSERT_HRESULT_SUCCEEDED( \
154 ::SafeArrayAccessData(array, reinterpret_cast<void**>(&array_data))); \
155 size_t count = array_upper_bound - array_lower_bound + 1; \
156 ASSERT_EQ(expected_property_values.size(), count); \
157 for (size_t i = 0; i < count; ++i) { \
158 ComPtr<IRawElementProviderSimple> element; \
159 ASSERT_HRESULT_SUCCEEDED( \
160 array_data[i]->QueryInterface(IID_PPV_ARGS(&element))); \
161 EXPECT_UIA_BSTR_EQ(element, element_test_property_id, \
162 expected_property_values[i].c_str()); \
163 } \
164 ASSERT_HRESULT_SUCCEEDED(::SafeArrayUnaccessData(array)); \
165 }
166
167#define EXPECT_UIA_PROPERTY_ELEMENT_ARRAY_BSTR_EQ(node, array_property_id, \
168 element_test_property_id, \
169 expected_property_values) \
170 { \
171 ScopedVariant array; \
172 ASSERT_HRESULT_SUCCEEDED( \
173 node->GetPropertyValue(array_property_id, array.Receive())); \
174 ASSERT_EQ(VT_ARRAY | VT_UNKNOWN, array.type()); \
175 EXPECT_UIA_ELEMENT_ARRAY_BSTR_EQ(array.ptr()->parray, \
176 element_test_property_id, \
177 expected_property_values); \
178 }
179
180#define EXPECT_UIA_PROPERTY_UNORDERED_ELEMENT_ARRAY_BSTR_EQ( \
181 node, array_property_id, element_test_property_id, \
182 expected_property_values) \
183 { \
184 ScopedVariant array; \
185 ASSERT_HRESULT_SUCCEEDED( \
186 node->GetPropertyValue(array_property_id, array.Receive())); \
187 ASSERT_EQ(VT_ARRAY | VT_UNKNOWN, array.type()); \
188 ASSERT_EQ(1u, SafeArrayGetDim(array.ptr()->parray)); \
189 LONG array_lower_bound; \
190 ASSERT_HRESULT_SUCCEEDED( \
191 SafeArrayGetLBound(array.ptr()->parray, 1, &array_lower_bound)); \
192 LONG array_upper_bound; \
193 ASSERT_HRESULT_SUCCEEDED( \
194 SafeArrayGetUBound(array.ptr()->parray, 1, &array_upper_bound)); \
195 IUnknown** array_data; \
196 ASSERT_HRESULT_SUCCEEDED(::SafeArrayAccessData( \
197 array.ptr()->parray, reinterpret_cast<void**>(&array_data))); \
198 size_t count = array_upper_bound - array_lower_bound + 1; \
199 ASSERT_EQ(expected_property_values.size(), count); \
200 std::vector<std::wstring> property_values; \
201 for (size_t i = 0; i < count; ++i) { \
202 ComPtr<IRawElementProviderSimple> element; \
203 ASSERT_HRESULT_SUCCEEDED( \
204 array_data[i]->QueryInterface(IID_PPV_ARGS(&element))); \
205 ScopedVariant actual; \
206 ASSERT_HRESULT_SUCCEEDED(element->GetPropertyValue( \
207 element_test_property_id, actual.Receive())); \
208 ASSERT_EQ(VT_BSTR, actual.type()); \
209 ASSERT_NE(nullptr, actual.ptr()->bstrVal); \
210 property_values.push_back(std::wstring( \
211 V_BSTR(actual.ptr()), SysStringLen(V_BSTR(actual.ptr())))); \
212 } \
213 ASSERT_HRESULT_SUCCEEDED(::SafeArrayUnaccessData(array.ptr()->parray)); \
214 EXPECT_THAT(property_values, \
215 testing::UnorderedElementsAreArray(expected_property_values)); \
216 }
217
218MockIRawElementProviderSimple::MockIRawElementProviderSimple() = default;
219MockIRawElementProviderSimple::~MockIRawElementProviderSimple() = default;
220
221HRESULT
222MockIRawElementProviderSimple::CreateMockIRawElementProviderSimple(
223 IRawElementProviderSimple** provider) {
224 CComObject<MockIRawElementProviderSimple>* raw_element_provider = nullptr;
225 HRESULT hr = CComObject<MockIRawElementProviderSimple>::CreateInstance(
226 &raw_element_provider);
227 if (SUCCEEDED(hr)) {
228 *provider = raw_element_provider;
229 }
230
231 return hr;
232}
233
234//
235// IRawElementProviderSimple methods.
236//
237IFACEMETHODIMP MockIRawElementProviderSimple::GetPatternProvider(
238 PATTERNID pattern_id,
239 IUnknown** result) {
240 return E_NOTIMPL;
241}
242
243IFACEMETHODIMP MockIRawElementProviderSimple::GetPropertyValue(
244 PROPERTYID property_id,
245 VARIANT* result) {
246 return E_NOTIMPL;
247}
248
249IFACEMETHODIMP
250MockIRawElementProviderSimple::get_ProviderOptions(enum ProviderOptions* ret) {
251 return E_NOTIMPL;
252}
253
254IFACEMETHODIMP MockIRawElementProviderSimple::get_HostRawElementProvider(
255 IRawElementProviderSimple** provider) {
256 return E_NOTIMPL;
257}
258
259AXPlatformNodeWinTest::AXPlatformNodeWinTest() {
260 // scoped_feature_list_.InitAndEnableFeature(features::kIChromeAccessible);
261}
262
263AXPlatformNodeWinTest::~AXPlatformNodeWinTest() {}
264
265void AXPlatformNodeWinTest::SetUp() {
266 win::CreateATLModuleIfNeeded();
267}
268
269void AXPlatformNodeWinTest::TearDown() {
270 // Destroy the tree and make sure we're not leaking any objects.
271 ax_fragment_root_.reset(nullptr);
272 DestroyTree();
273 TestAXNodeWrapper::SetGlobalIsWebContent(false);
274 TestAXNodeWrapper::ClearHitTestResults();
275 ASSERT_EQ(0U, AXPlatformNodeBase::GetInstanceCountForTesting());
276}
277
278AXPlatformNode* AXPlatformNodeWinTest::AXPlatformNodeFromNode(AXNode* node) {
279 const TestAXNodeWrapper* wrapper =
280 TestAXNodeWrapper::GetOrCreate(GetTree(), node);
281 return wrapper ? wrapper->ax_platform_node() : nullptr;
282}
283
284template <typename T>
285ComPtr<T> AXPlatformNodeWinTest::QueryInterfaceFromNodeId(AXNode::AXID id) {
286 return QueryInterfaceFromNode<T>(GetNodeFromTree(id));
287}
288
289template <typename T>
290ComPtr<T> AXPlatformNodeWinTest::QueryInterfaceFromNode(AXNode* node) {
291 AXPlatformNode* ax_platform_node = AXPlatformNodeFromNode(node);
292 if (!ax_platform_node)
293 return ComPtr<T>();
294 ComPtr<T> result;
295 EXPECT_HRESULT_SUCCEEDED(
296 ax_platform_node->GetNativeViewAccessible()->QueryInterface(__uuidof(T),
297 &result));
298 return result;
299}
300
301ComPtr<IRawElementProviderSimple>
302AXPlatformNodeWinTest::GetRootIRawElementProviderSimple() {
303 return QueryInterfaceFromNode<IRawElementProviderSimple>(GetRootAsAXNode());
304}
305
306ComPtr<IRawElementProviderSimple>
307AXPlatformNodeWinTest::GetIRawElementProviderSimpleFromChildIndex(
308 int child_index) {
309 if (!GetRootAsAXNode() || child_index < 0 ||
310 static_cast<size_t>(child_index) >=
311 GetRootAsAXNode()->children().size()) {
312 return ComPtr<IRawElementProviderSimple>();
313 }
314
315 return QueryInterfaceFromNode<IRawElementProviderSimple>(
316 GetRootAsAXNode()->children()[static_cast<size_t>(child_index)]);
317}
318
319Microsoft::WRL::ComPtr<IRawElementProviderSimple>
320AXPlatformNodeWinTest::GetIRawElementProviderSimpleFromTree(
321 const ui::AXTreeID tree_id,
322 const AXNode::AXID node_id) {
323 return QueryInterfaceFromNode<IRawElementProviderSimple>(
324 GetNodeFromTree(tree_id, node_id));
325}
326
327ComPtr<IRawElementProviderFragment>
328AXPlatformNodeWinTest::GetRootIRawElementProviderFragment() {
329 return QueryInterfaceFromNode<IRawElementProviderFragment>(GetRootAsAXNode());
330}
331
332Microsoft::WRL::ComPtr<IRawElementProviderFragment>
333AXPlatformNodeWinTest::IRawElementProviderFragmentFromNode(AXNode* node) {
334 AXPlatformNode* platform_node = AXPlatformNodeFromNode(node);
335 gfx::NativeViewAccessible native_view =
336 platform_node->GetNativeViewAccessible();
337 ComPtr<IUnknown> unknown_node = native_view;
338 ComPtr<IRawElementProviderFragment> fragment_node;
339 unknown_node.As(&fragment_node);
340
341 return fragment_node;
342}
343
344ComPtr<IAccessible> AXPlatformNodeWinTest::IAccessibleFromNode(AXNode* node) {
345 return QueryInterfaceFromNode<IAccessible>(node);
346}
347
348ComPtr<IAccessible> AXPlatformNodeWinTest::GetRootIAccessible() {
349 return IAccessibleFromNode(GetRootAsAXNode());
350}
351
352void AXPlatformNodeWinTest::CheckVariantHasName(const ScopedVariant& variant,
353 const wchar_t* expected_name) {
354 ASSERT_NE(nullptr, variant.ptr());
355 ComPtr<IAccessible> accessible;
356 ASSERT_HRESULT_SUCCEEDED(
357 V_DISPATCH(variant.ptr())->QueryInterface(IID_PPV_ARGS(&accessible)));
359 EXPECT_EQ(S_OK, accessible->get_accName(SELF, name.Receive()));
360 EXPECT_STREQ(expected_name, name.Get());
361}
362
363void AXPlatformNodeWinTest::InitFragmentRoot() {
364 test_fragment_root_delegate_ = std::make_unique<TestFragmentRootDelegate>();
365 ax_fragment_root_.reset(InitNodeAsFragmentRoot(
366 GetRootAsAXNode(), test_fragment_root_delegate_.get()));
367}
368
369AXFragmentRootWin* AXPlatformNodeWinTest::InitNodeAsFragmentRoot(
370 AXNode* node,
371 TestFragmentRootDelegate* delegate) {
372 delegate->child_ = AXPlatformNodeFromNode(node)->GetNativeViewAccessible();
373 if (node->parent())
374 delegate->parent_ =
375 AXPlatformNodeFromNode(node->parent())->GetNativeViewAccessible();
376
377 return new AXFragmentRootWin(gfx::kMockAcceleratedWidget, delegate);
378}
379
380ComPtr<IRawElementProviderFragmentRoot>
381AXPlatformNodeWinTest::GetFragmentRoot() {
382 ComPtr<IRawElementProviderFragmentRoot> fragment_root_provider;
383 ax_fragment_root_->GetNativeViewAccessible()->QueryInterface(
384 IID_PPV_ARGS(&fragment_root_provider));
385 return fragment_root_provider;
386}
387
388AXPlatformNodeWinTest::PatternSet
389AXPlatformNodeWinTest::GetSupportedPatternsFromNodeId(AXNode::AXID id) {
390 ComPtr<IRawElementProviderSimple> raw_element_provider_simple =
391 QueryInterfaceFromNodeId<IRawElementProviderSimple>(id);
392 PatternSet supported_patterns;
393 static const std::vector<LONG> all_supported_patterns_ = {
394 UIA_TextChildPatternId, UIA_TextEditPatternId,
395 UIA_TextPatternId, UIA_WindowPatternId,
396 UIA_InvokePatternId, UIA_ExpandCollapsePatternId,
397 UIA_GridPatternId, UIA_GridItemPatternId,
398 UIA_RangeValuePatternId, UIA_ScrollPatternId,
399 UIA_ScrollItemPatternId, UIA_TablePatternId,
400 UIA_TableItemPatternId, UIA_SelectionItemPatternId,
401 UIA_SelectionPatternId, UIA_TogglePatternId,
402 UIA_ValuePatternId,
403 };
404 for (LONG property_id : all_supported_patterns_) {
405 ComPtr<IUnknown> provider;
406 if (SUCCEEDED(raw_element_provider_simple->GetPatternProvider(property_id,
407 &provider)) &&
408 provider) {
409 supported_patterns.insert(property_id);
410 }
411 }
412 return supported_patterns;
413}
414
415TestFragmentRootDelegate::TestFragmentRootDelegate() = default;
416
417TestFragmentRootDelegate::~TestFragmentRootDelegate() = default;
418
419gfx::NativeViewAccessible TestFragmentRootDelegate::GetChildOfAXFragmentRoot() {
420 return child_;
421}
422
424TestFragmentRootDelegate::GetParentOfAXFragmentRoot() {
425 return parent_;
426}
427
428bool TestFragmentRootDelegate::IsAXFragmentRootAControlElement() {
429 return is_control_element_;
430}
431
432TEST_F(AXPlatformNodeWinTest, IAccessibleDetachedObject) {
433 AXNodeData root;
434 root.id = 1;
436 root.SetName("Name");
437 Init(root);
438
439 ComPtr<IAccessible> root_obj(GetRootIAccessible());
441 EXPECT_EQ(S_OK, root_obj->get_accName(SELF, name.Receive()));
442 EXPECT_STREQ(L"Name", name.Get());
443
444 // Create an empty tree.
445 SetTree(std::make_unique<AXTree>());
446 ScopedBstr name2;
447 EXPECT_EQ(E_FAIL, root_obj->get_accName(SELF, name2.Receive()));
448}
449
450TEST_F(AXPlatformNodeWinTest, IAccessibleHitTest) {
451 AXNodeData root;
452 root.id = 1;
453 root.relative_bounds.bounds = gfx::RectF(0, 0, 40, 40);
454
455 AXNodeData node1;
456 node1.id = 2;
458 node1.relative_bounds.bounds = gfx::RectF(0, 0, 10, 10);
459 node1.SetName("Name1");
460 root.child_ids.push_back(node1.id);
461
462 AXNodeData node2;
463 node2.id = 3;
465 node2.relative_bounds.bounds = gfx::RectF(20, 20, 20, 20);
466 node2.SetName("Name2");
467 root.child_ids.push_back(node2.id);
468
469 Init(root, node1, node2);
470
471 ComPtr<IAccessible> root_obj(GetRootIAccessible());
472
473 // This is way outside of the root node.
474 ScopedVariant obj_1;
475 EXPECT_EQ(S_FALSE, root_obj->accHitTest(50, 50, obj_1.Receive()));
476 EXPECT_EQ(VT_EMPTY, obj_1.type());
477
478 // This is directly on node 1.
479 EXPECT_EQ(S_OK, root_obj->accHitTest(5, 5, obj_1.Receive()));
480 ASSERT_NE(nullptr, obj_1.ptr());
481 CheckVariantHasName(obj_1, L"Name1");
482
483 // This is directly on node 2 with a scale factor of 1.5.
484 ScopedVariant obj_2;
485 std::unique_ptr<base::AutoReset<float>> scale_factor_reset =
486 TestAXNodeWrapper::SetScaleFactor(1.5);
487 EXPECT_EQ(S_OK, root_obj->accHitTest(38, 38, obj_2.Receive()));
488 ASSERT_NE(nullptr, obj_2.ptr());
489 CheckVariantHasName(obj_2, L"Name2");
490}
491
492TEST_F(AXPlatformNodeWinTest, IAccessibleHitTestDoesNotLoopForever) {
493 AXNodeData root;
494 root.id = 1;
495 root.relative_bounds.bounds = gfx::RectF(0, 0, 40, 40);
496
497 AXNodeData node1;
498 node1.id = 2;
500 node1.relative_bounds.bounds = gfx::RectF(0, 0, 10, 10);
501 node1.SetName("Name1");
502 root.child_ids.push_back(node1.id);
503
504 Init(root, node1);
505
506 // Set up the endless loop.
507 TestAXNodeWrapper::SetHitTestResult(1, 2);
508 TestAXNodeWrapper::SetHitTestResult(2, 1);
509
510 // Hit testing on the root returns the child. Hit testing on the
511 // child returns the root, but that should be rejected rather than
512 // looping endlessly.
513 ComPtr<IAccessible> root_obj(GetRootIAccessible());
514 ScopedVariant obj_1;
515 EXPECT_EQ(S_OK, root_obj->accHitTest(5, 5, obj_1.Receive()));
516 ASSERT_NE(nullptr, obj_1.ptr());
517 CheckVariantHasName(obj_1, L"Name1");
518}
519
520TEST_F(AXPlatformNodeWinTest, IAccessibleName) {
521 AXNodeData root;
522 root.id = 1;
524 root.SetName("Name");
525 Init(root);
526
527 ComPtr<IAccessible> root_obj(GetRootIAccessible());
529 EXPECT_EQ(S_OK, root_obj->get_accName(SELF, name.Receive()));
530 EXPECT_STREQ(L"Name", name.Get());
531
532 EXPECT_EQ(E_INVALIDARG, root_obj->get_accName(SELF, nullptr));
533 ScopedVariant bad_id(999);
534 ScopedBstr name2;
535 EXPECT_EQ(E_INVALIDARG, root_obj->get_accName(bad_id, name2.Receive()));
536}
537
538TEST_F(AXPlatformNodeWinTest, IAccessibleDescription) {
539 AXNodeData root;
540 root.id = 1;
542 "Description");
543 Init(root);
544
545 ComPtr<IAccessible> root_obj(GetRootIAccessible());
546 ScopedBstr description;
547 EXPECT_EQ(S_OK, root_obj->get_accDescription(SELF, description.Receive()));
548 EXPECT_STREQ(L"Description", description.Get());
549
550 EXPECT_EQ(E_INVALIDARG, root_obj->get_accDescription(SELF, nullptr));
551 ScopedVariant bad_id(999);
552 ScopedBstr d2;
553 EXPECT_EQ(E_INVALIDARG, root_obj->get_accDescription(bad_id, d2.Receive()));
554}
555
556TEST_F(AXPlatformNodeWinTest, IAccessibleAccValue) {
557 AXNodeData root;
558 root.id = 1;
560 root.AddStringAttribute(ax::mojom::StringAttribute::kValue, "Value");
561 Init(root);
562
563 ComPtr<IAccessible> root_obj(GetRootIAccessible());
565 EXPECT_EQ(S_OK, root_obj->get_accValue(SELF, value.Receive()));
566 EXPECT_STREQ(L"Value", value.Get());
567
568 EXPECT_EQ(E_INVALIDARG, root_obj->get_accValue(SELF, nullptr));
569 ScopedVariant bad_id(999);
571 EXPECT_EQ(E_INVALIDARG, root_obj->get_accValue(bad_id, v2.Receive()));
572}
573
574TEST_F(AXPlatformNodeWinTest, IAccessibleShortcut) {
575 AXNodeData root;
576 root.id = 1;
578 "Shortcut");
579 Init(root);
580
581 ComPtr<IAccessible> root_obj(GetRootIAccessible());
582 ScopedBstr shortcut;
583 EXPECT_EQ(S_OK, root_obj->get_accKeyboardShortcut(SELF, shortcut.Receive()));
584 EXPECT_STREQ(L"Shortcut", shortcut.Get());
585
586 EXPECT_EQ(E_INVALIDARG, root_obj->get_accKeyboardShortcut(SELF, nullptr));
587 ScopedVariant bad_id(999);
589 EXPECT_EQ(E_INVALIDARG,
590 root_obj->get_accKeyboardShortcut(bad_id, k2.Receive()));
591}
592
593TEST_F(AXPlatformNodeWinTest,
594 IAccessibleSelectionListBoxOptionNothingSelected) {
595 AXNodeData list;
596 list.id = 1;
597 list.role = ax::mojom::Role::kListBox;
598
599 AXNodeData list_item_1;
600 list_item_1.id = 2;
601 list_item_1.role = ax::mojom::Role::kListBoxOption;
602 list_item_1.SetName("Name1");
603
604 AXNodeData list_item_2;
605 list_item_2.id = 3;
606 list_item_2.role = ax::mojom::Role::kListBoxOption;
607 list_item_2.SetName("Name2");
608
609 list.child_ids.push_back(list_item_1.id);
610 list.child_ids.push_back(list_item_2.id);
611
612 Init(list, list_item_1, list_item_2);
613
614 ComPtr<IAccessible> root_obj(GetRootIAccessible());
615 ASSERT_NE(nullptr, root_obj.Get());
616
617 ScopedVariant selection;
618 EXPECT_EQ(S_OK, root_obj->get_accSelection(selection.Receive()));
619 EXPECT_EQ(VT_EMPTY, selection.type());
620}
621
622TEST_F(AXPlatformNodeWinTest, IAccessibleSelectionListBoxOptionOneSelected) {
623 AXNodeData list;
624 list.id = 1;
625 list.role = ax::mojom::Role::kListBox;
626
627 AXNodeData list_item_1;
628 list_item_1.id = 2;
629 list_item_1.role = ax::mojom::Role::kListBoxOption;
630 list_item_1.AddBoolAttribute(ax::mojom::BoolAttribute::kSelected, true);
631 list_item_1.SetName("Name1");
632
633 AXNodeData list_item_2;
634 list_item_2.id = 3;
635 list_item_2.role = ax::mojom::Role::kListBoxOption;
636 list_item_2.SetName("Name2");
637
638 list.child_ids.push_back(list_item_1.id);
639 list.child_ids.push_back(list_item_2.id);
640
641 Init(list, list_item_1, list_item_2);
642
643 ComPtr<IAccessible> root_obj(GetRootIAccessible());
644 ASSERT_NE(nullptr, root_obj.Get());
645
646 ScopedVariant selection;
647 EXPECT_EQ(S_OK, root_obj->get_accSelection(selection.Receive()));
648 EXPECT_EQ(VT_DISPATCH, selection.type());
649
650 CheckVariantHasName(selection, L"Name1");
651}
652
653TEST_F(AXPlatformNodeWinTest,
654 IAccessibleSelectionListBoxOptionMultipleSelected) {
655 AXNodeData list;
656 list.id = 1;
657 list.role = ax::mojom::Role::kListBox;
658
659 AXNodeData list_item_1;
660 list_item_1.id = 2;
661 list_item_1.role = ax::mojom::Role::kListBoxOption;
662 list_item_1.AddBoolAttribute(ax::mojom::BoolAttribute::kSelected, true);
663 list_item_1.SetName("Name1");
664
665 AXNodeData list_item_2;
666 list_item_2.id = 3;
667 list_item_2.role = ax::mojom::Role::kListBoxOption;
668 list_item_2.AddBoolAttribute(ax::mojom::BoolAttribute::kSelected, true);
669 list_item_2.SetName("Name2");
670
671 AXNodeData list_item_3;
672 list_item_3.id = 4;
673 list_item_3.role = ax::mojom::Role::kListBoxOption;
674 list_item_3.SetName("Name3");
675
676 list.child_ids.push_back(list_item_1.id);
677 list.child_ids.push_back(list_item_2.id);
678 list.child_ids.push_back(list_item_3.id);
679
680 Init(list, list_item_1, list_item_2, list_item_3);
681
682 ComPtr<IAccessible> root_obj(GetRootIAccessible());
683 ASSERT_NE(nullptr, root_obj.Get());
684
685 ScopedVariant selection;
686 EXPECT_EQ(S_OK, root_obj->get_accSelection(selection.Receive()));
687 EXPECT_EQ(VT_UNKNOWN, selection.type());
688 ASSERT_NE(nullptr, selection.ptr());
689
690 // Loop through the selections and make sure we have the right ones.
691 ComPtr<IEnumVARIANT> accessibles;
692 ASSERT_HRESULT_SUCCEEDED(
693 V_UNKNOWN(selection.ptr())->QueryInterface(IID_PPV_ARGS(&accessibles)));
694 ULONG retrieved_count;
695
696 // Check out the first selected item.
697 {
698 ScopedVariant item;
699 HRESULT hr = accessibles->Next(1, item.Receive(), &retrieved_count);
700 EXPECT_EQ(S_OK, hr);
701
702 ComPtr<IAccessible> accessible;
703 ASSERT_HRESULT_SUCCEEDED(
704 V_DISPATCH(item.ptr())->QueryInterface(IID_PPV_ARGS(&accessible)));
706 EXPECT_EQ(S_OK, accessible->get_accName(SELF, name.Receive()));
707 EXPECT_STREQ(L"Name1", name.Get());
708 }
709
710 // And the second selected element.
711 {
712 ScopedVariant item;
713 HRESULT hr = accessibles->Next(1, item.Receive(), &retrieved_count);
714 EXPECT_EQ(S_OK, hr);
715
716 ComPtr<IAccessible> accessible;
717 ASSERT_HRESULT_SUCCEEDED(
718 V_DISPATCH(item.ptr())->QueryInterface(IID_PPV_ARGS(&accessible)));
720 EXPECT_EQ(S_OK, accessible->get_accName(SELF, name.Receive()));
721 EXPECT_STREQ(L"Name2", name.Get());
722 }
723
724 // There shouldn't be any more selected.
725 {
726 ScopedVariant item;
727 HRESULT hr = accessibles->Next(1, item.Receive(), &retrieved_count);
728 EXPECT_EQ(S_FALSE, hr);
729 }
730}
731
732TEST_F(AXPlatformNodeWinTest, IAccessibleSelectionTableNothingSelected) {
733 Init(Build3X3Table());
734
735 ComPtr<IAccessible> root_obj(GetRootIAccessible());
736 ASSERT_NE(nullptr, root_obj.Get());
737
738 ScopedVariant selection;
739 EXPECT_EQ(S_OK, root_obj->get_accSelection(selection.Receive()));
740 EXPECT_EQ(VT_EMPTY, selection.type());
741}
742
743TEST_F(AXPlatformNodeWinTest, IAccessibleSelectionTableRowOneSelected) {
744 AXTreeUpdate update = Build3X3Table();
745
746 // 5 == table_row_1
747 update.nodes[5].AddBoolAttribute(ax::mojom::BoolAttribute::kSelected, true);
748
749 Init(update);
750
751 ComPtr<IAccessible> root_obj(GetRootIAccessible());
752 ASSERT_NE(nullptr, root_obj.Get());
753
754 ScopedVariant selection;
755 EXPECT_EQ(S_OK, root_obj->get_accSelection(selection.Receive()));
756 EXPECT_EQ(VT_DISPATCH, selection.type());
757 ASSERT_NE(nullptr, selection.ptr());
758
759 ComPtr<IAccessible> row;
760 ASSERT_HRESULT_SUCCEEDED(
761 V_DISPATCH(selection.ptr())->QueryInterface(IID_PPV_ARGS(&row)));
762
763 ScopedVariant role;
764 EXPECT_HRESULT_SUCCEEDED(row->get_accRole(SELF, role.Receive()));
765 EXPECT_EQ(ROLE_SYSTEM_ROW, V_I4(role.ptr()));
766}
767
768TEST_F(AXPlatformNodeWinTest, IAccessibleSelectionTableRowMultipleSelected) {
769 AXTreeUpdate update = Build3X3Table();
770
771 // 5 == table_row_1
772 // 9 == table_row_2
773 update.nodes[5].AddBoolAttribute(ax::mojom::BoolAttribute::kSelected, true);
774 update.nodes[9].AddBoolAttribute(ax::mojom::BoolAttribute::kSelected, true);
775
776 Init(update);
777
778 ComPtr<IAccessible> root_obj(GetRootIAccessible());
779 ASSERT_NE(nullptr, root_obj.Get());
780
781 ScopedVariant selection;
782 EXPECT_EQ(S_OK, root_obj->get_accSelection(selection.Receive()));
783 EXPECT_EQ(VT_UNKNOWN, selection.type());
784 ASSERT_NE(nullptr, selection.ptr());
785
786 // Loop through the selections and make sure we have the right ones.
787 ComPtr<IEnumVARIANT> accessibles;
788 ASSERT_HRESULT_SUCCEEDED(
789 V_UNKNOWN(selection.ptr())->QueryInterface(IID_PPV_ARGS(&accessibles)));
790 ULONG retrieved_count;
791
792 // Check out the first selected row.
793 {
794 ScopedVariant item;
795 HRESULT hr = accessibles->Next(1, item.Receive(), &retrieved_count);
796 EXPECT_EQ(S_OK, hr);
797
798 ComPtr<IAccessible> accessible;
799 ASSERT_HRESULT_SUCCEEDED(
800 V_DISPATCH(item.ptr())->QueryInterface(IID_PPV_ARGS(&accessible)));
801 ScopedVariant role;
802 EXPECT_HRESULT_SUCCEEDED(accessible->get_accRole(SELF, role.Receive()));
803 EXPECT_EQ(ROLE_SYSTEM_ROW, V_I4(role.ptr()));
804 }
805
806 // And the second selected element.
807 {
808 ScopedVariant item;
809 HRESULT hr = accessibles->Next(1, item.Receive(), &retrieved_count);
810 EXPECT_EQ(S_OK, hr);
811
812 ComPtr<IAccessible> accessible;
813 ASSERT_HRESULT_SUCCEEDED(
814 V_DISPATCH(item.ptr())->QueryInterface(IID_PPV_ARGS(&accessible)));
815 ScopedVariant role;
816 EXPECT_HRESULT_SUCCEEDED(accessible->get_accRole(SELF, role.Receive()));
817 EXPECT_EQ(ROLE_SYSTEM_ROW, V_I4(role.ptr()));
818 }
819
820 // There shouldn't be any more selected.
821 {
822 ScopedVariant item;
823 HRESULT hr = accessibles->Next(1, item.Receive(), &retrieved_count);
824 EXPECT_EQ(S_FALSE, hr);
825 }
826}
827
828TEST_F(AXPlatformNodeWinTest, IAccessibleSelectionTableCellOneSelected) {
829 AXTreeUpdate update = Build3X3Table();
830
831 // 7 == table_cell_1
832 update.nodes[7].AddBoolAttribute(ax::mojom::BoolAttribute::kSelected, true);
833
834 Init(update);
835
836 ComPtr<IAccessible> root_obj(GetRootIAccessible());
837 ASSERT_NE(nullptr, root_obj.Get());
838
839 ComPtr<IDispatch> row2;
840 ASSERT_HRESULT_SUCCEEDED(root_obj->get_accChild(ScopedVariant(2), &row2));
841 ComPtr<IAccessible> row2_accessible;
842 ASSERT_HRESULT_SUCCEEDED(row2.As(&row2_accessible));
843
844 ScopedVariant selection;
845 EXPECT_EQ(S_OK, row2_accessible->get_accSelection(selection.Receive()));
846 EXPECT_EQ(VT_DISPATCH, selection.type());
847 ASSERT_NE(nullptr, selection.ptr());
848
849 ComPtr<IAccessible> cell;
850 ASSERT_HRESULT_SUCCEEDED(
851 V_DISPATCH(selection.ptr())->QueryInterface(IID_PPV_ARGS(&cell)));
852
853 ScopedVariant role;
854 EXPECT_HRESULT_SUCCEEDED(cell->get_accRole(SELF, role.Receive()));
855 EXPECT_EQ(ROLE_SYSTEM_CELL, V_I4(role.ptr()));
856
858 EXPECT_EQ(S_OK, cell->get_accName(SELF, name.Receive()));
859 EXPECT_STREQ(L"1", name.Get());
860}
861
862TEST_F(AXPlatformNodeWinTest, IAccessibleSelectionTableCellMultipleSelected) {
863 AXTreeUpdate update = Build3X3Table();
864
865 // 11 == table_cell_3
866 // 12 == table_cell_4
867 update.nodes[11].AddBoolAttribute(ax::mojom::BoolAttribute::kSelected, true);
868 update.nodes[12].AddBoolAttribute(ax::mojom::BoolAttribute::kSelected, true);
869
870 Init(update);
871
872 ComPtr<IAccessible> root_obj(GetRootIAccessible());
873 ASSERT_NE(nullptr, root_obj.Get());
874
875 ComPtr<IDispatch> row3;
876 ASSERT_HRESULT_SUCCEEDED(root_obj->get_accChild(ScopedVariant(3), &row3));
877 ComPtr<IAccessible> row3_accessible;
878 ASSERT_HRESULT_SUCCEEDED(row3.As(&row3_accessible));
879
880 ScopedVariant selection;
881 EXPECT_EQ(S_OK, row3_accessible->get_accSelection(selection.Receive()));
882 EXPECT_EQ(VT_UNKNOWN, selection.type());
883 ASSERT_NE(nullptr, selection.ptr());
884
885 // Loop through the selections and make sure we have the right ones.
886 ComPtr<IEnumVARIANT> accessibles;
887 ASSERT_HRESULT_SUCCEEDED(
888 V_UNKNOWN(selection.ptr())->QueryInterface(IID_PPV_ARGS(&accessibles)));
889 ULONG retrieved_count;
890
891 // Check out the first selected cell.
892 {
893 ScopedVariant item;
894 HRESULT hr = accessibles->Next(1, item.Receive(), &retrieved_count);
895 EXPECT_EQ(S_OK, hr);
896
897 ComPtr<IAccessible> accessible;
898 ASSERT_HRESULT_SUCCEEDED(
899 V_DISPATCH(item.ptr())->QueryInterface(IID_PPV_ARGS(&accessible)));
901 EXPECT_EQ(S_OK, accessible->get_accName(SELF, name.Receive()));
902 EXPECT_STREQ(L"3", name.Get());
903 }
904
905 // And the second selected cell.
906 {
907 ScopedVariant item;
908 HRESULT hr = accessibles->Next(1, item.Receive(), &retrieved_count);
909 EXPECT_EQ(S_OK, hr);
910
911 ComPtr<IAccessible> accessible;
912 ASSERT_HRESULT_SUCCEEDED(
913 V_DISPATCH(item.ptr())->QueryInterface(IID_PPV_ARGS(&accessible)));
915 EXPECT_EQ(S_OK, accessible->get_accName(SELF, name.Receive()));
916 EXPECT_STREQ(L"4", name.Get());
917 }
918
919 // There shouldn't be any more selected.
920 {
921 ScopedVariant item;
922 HRESULT hr = accessibles->Next(1, item.Receive(), &retrieved_count);
923 EXPECT_EQ(S_FALSE, hr);
924 }
925}
926
927TEST_F(AXPlatformNodeWinTest, IAccessibleRole) {
928 AXNodeData root;
929 root.id = 1;
930 root.child_ids.push_back(2);
931
932 AXNodeData child;
933 child.id = 2;
934
935 Init(root, child);
936 AXNode* child_node = GetRootAsAXNode()->children()[0];
937 ComPtr<IAccessible> child_iaccessible(IAccessibleFromNode(child_node));
938
939 ScopedVariant role;
940
941 child.role = ax::mojom::Role::kAlert;
942 child_node->SetData(child);
943 EXPECT_EQ(S_OK, child_iaccessible->get_accRole(SELF, role.Receive()));
944 EXPECT_EQ(ROLE_SYSTEM_ALERT, V_I4(role.ptr()));
945
946 child.role = ax::mojom::Role::kButton;
947 child_node->SetData(child);
948 EXPECT_EQ(S_OK, child_iaccessible->get_accRole(SELF, role.Receive()));
949 EXPECT_EQ(ROLE_SYSTEM_PUSHBUTTON, V_I4(role.ptr()));
950
952 child_node->SetData(child);
953 EXPECT_EQ(S_OK, child_iaccessible->get_accRole(SELF, role.Receive()));
954 EXPECT_EQ(ROLE_SYSTEM_BUTTONMENU, V_I4(role.ptr()));
955
956 EXPECT_EQ(E_INVALIDARG, child_iaccessible->get_accRole(SELF, nullptr));
957 ScopedVariant bad_id(999);
958 EXPECT_EQ(E_INVALIDARG,
959 child_iaccessible->get_accRole(bad_id, role.Receive()));
960}
961
962TEST_F(AXPlatformNodeWinTest, IAccessibleLocation) {
963 AXNodeData root;
964 root.id = 1;
965 root.relative_bounds.bounds = gfx::RectF(10, 40, 800, 600);
966 Init(root);
967
968 TestAXNodeWrapper::SetGlobalCoordinateOffset(gfx::Vector2d(100, 200));
969
970 LONG x_left, y_top, width, height;
971 EXPECT_EQ(S_OK, GetRootIAccessible()->accLocation(&x_left, &y_top, &width,
972 &height, SELF));
973 EXPECT_EQ(110, x_left);
974 EXPECT_EQ(240, y_top);
975 EXPECT_EQ(800, width);
976 EXPECT_EQ(600, height);
977
978 EXPECT_EQ(E_INVALIDARG, GetRootIAccessible()->accLocation(
979 nullptr, &y_top, &width, &height, SELF));
980 EXPECT_EQ(E_INVALIDARG, GetRootIAccessible()->accLocation(
981 &x_left, nullptr, &width, &height, SELF));
982 EXPECT_EQ(E_INVALIDARG, GetRootIAccessible()->accLocation(
983 &x_left, &y_top, nullptr, &height, SELF));
984 EXPECT_EQ(E_INVALIDARG, GetRootIAccessible()->accLocation(
985 &x_left, &y_top, &width, nullptr, SELF));
986 ScopedVariant bad_id(999);
987 EXPECT_EQ(E_INVALIDARG, GetRootIAccessible()->accLocation(
988 &x_left, &y_top, &width, &height, bad_id));
989
990 // Un-set the global offset so that it doesn't affect subsequent tests.
991 TestAXNodeWrapper::SetGlobalCoordinateOffset(gfx::Vector2d(0, 0));
992}
993
994TEST_F(AXPlatformNodeWinTest, IAccessibleChildAndParent) {
995 AXNodeData root;
996 root.id = 1;
997 root.child_ids.push_back(2);
998 root.child_ids.push_back(3);
999
1000 AXNodeData button;
1001 button.role = ax::mojom::Role::kButton;
1002 button.id = 2;
1003
1004 AXNodeData checkbox;
1005 checkbox.role = ax::mojom::Role::kCheckBox;
1006 checkbox.id = 3;
1007
1008 Init(root, button, checkbox);
1009 AXNode* button_node = GetRootAsAXNode()->children()[0];
1010 AXNode* checkbox_node = GetRootAsAXNode()->children()[1];
1011 ComPtr<IAccessible> root_iaccessible(GetRootIAccessible());
1012 ComPtr<IAccessible> button_iaccessible(IAccessibleFromNode(button_node));
1013 ComPtr<IAccessible> checkbox_iaccessible(IAccessibleFromNode(checkbox_node));
1014
1015 LONG child_count;
1016 EXPECT_EQ(S_OK, root_iaccessible->get_accChildCount(&child_count));
1017 EXPECT_EQ(2L, child_count);
1018 EXPECT_EQ(S_OK, button_iaccessible->get_accChildCount(&child_count));
1019 EXPECT_EQ(0L, child_count);
1020 EXPECT_EQ(S_OK, checkbox_iaccessible->get_accChildCount(&child_count));
1021 EXPECT_EQ(0L, child_count);
1022
1023 {
1024 ComPtr<IDispatch> result;
1025 EXPECT_EQ(S_OK, root_iaccessible->get_accChild(SELF, &result));
1026 EXPECT_EQ(result.Get(), root_iaccessible.Get());
1027 }
1028
1029 {
1030 ComPtr<IDispatch> result;
1031 ScopedVariant child1(1);
1032 EXPECT_EQ(S_OK, root_iaccessible->get_accChild(child1, &result));
1033 EXPECT_EQ(result.Get(), button_iaccessible.Get());
1034 }
1035
1036 {
1037 ComPtr<IDispatch> result;
1038 ScopedVariant child2(2);
1039 EXPECT_EQ(S_OK, root_iaccessible->get_accChild(child2, &result));
1040 EXPECT_EQ(result.Get(), checkbox_iaccessible.Get());
1041 }
1042
1043 {
1044 // Asking for child id 3 should fail.
1045 ComPtr<IDispatch> result;
1046 ScopedVariant child3(3);
1047 EXPECT_EQ(E_INVALIDARG, root_iaccessible->get_accChild(child3, &result));
1048 }
1049
1050 // Now check parents.
1051 {
1052 ComPtr<IDispatch> result;
1053 EXPECT_EQ(S_OK, button_iaccessible->get_accParent(&result));
1054 EXPECT_EQ(result.Get(), root_iaccessible.Get());
1055 }
1056
1057 {
1058 ComPtr<IDispatch> result;
1059 EXPECT_EQ(S_OK, checkbox_iaccessible->get_accParent(&result));
1060 EXPECT_EQ(result.Get(), root_iaccessible.Get());
1061 }
1062
1063 {
1064 ComPtr<IDispatch> result;
1065 EXPECT_EQ(S_FALSE, root_iaccessible->get_accParent(&result));
1066 }
1067}
1068
1069TEST_F(AXPlatformNodeWinTest, AccNavigate) {
1070 AXNodeData root;
1071 root.id = 1;
1073
1074 AXNodeData child1;
1075 child1.id = 2;
1076 child1.role = ax::mojom::Role::kStaticText;
1077 root.child_ids.push_back(2);
1078
1079 AXNodeData child2;
1080 child2.id = 3;
1081 child2.role = ax::mojom::Role::kStaticText;
1082 root.child_ids.push_back(3);
1083
1084 Init(root, child1, child2);
1085 ComPtr<IAccessible> ia_root(GetRootIAccessible());
1086 ComPtr<IDispatch> disp_root;
1087 ASSERT_HRESULT_SUCCEEDED(ia_root.As(&disp_root));
1088 ScopedVariant var_root(disp_root.Get());
1089 ComPtr<IAccessible> ia_child1(
1090 IAccessibleFromNode(GetRootAsAXNode()->children()[0]));
1091 ComPtr<IDispatch> disp_child1;
1092 ASSERT_HRESULT_SUCCEEDED(ia_child1.As(&disp_child1));
1093 ScopedVariant var_child1(disp_child1.Get());
1094 ComPtr<IAccessible> ia_child2(
1095 IAccessibleFromNode(GetRootAsAXNode()->children()[1]));
1096 ComPtr<IDispatch> disp_child2;
1097 ASSERT_HRESULT_SUCCEEDED(ia_child2.As(&disp_child2));
1098 ScopedVariant var_child2(disp_child2.Get());
1100
1101 // Invalid arguments.
1102 EXPECT_EQ(
1103 E_INVALIDARG,
1104 ia_root->accNavigate(NAVDIR_NEXT, ScopedVariant::kEmptyVariant, nullptr));
1105 EXPECT_EQ(E_INVALIDARG,
1106 ia_child1->accNavigate(NAVDIR_NEXT, ScopedVariant::kEmptyVariant,
1107 end.AsInput()));
1108 EXPECT_EQ(VT_EMPTY, end.type());
1109
1110 // Navigating to first/last child should only be from self.
1111 EXPECT_EQ(E_INVALIDARG,
1112 ia_root->accNavigate(NAVDIR_FIRSTCHILD, var_root, end.AsInput()));
1113 EXPECT_EQ(VT_EMPTY, end.type());
1114 EXPECT_EQ(E_INVALIDARG,
1115 ia_root->accNavigate(NAVDIR_LASTCHILD, var_root, end.AsInput()));
1116 EXPECT_EQ(VT_EMPTY, end.type());
1117
1118 // Spatial directions are not supported.
1119 EXPECT_EQ(E_NOTIMPL, ia_child1->accNavigate(NAVDIR_UP, SELF, end.AsInput()));
1120 EXPECT_EQ(E_NOTIMPL, ia_root->accNavigate(NAVDIR_DOWN, SELF, end.AsInput()));
1121 EXPECT_EQ(E_NOTIMPL,
1122 ia_child1->accNavigate(NAVDIR_RIGHT, SELF, end.AsInput()));
1123 EXPECT_EQ(E_NOTIMPL,
1124 ia_child2->accNavigate(NAVDIR_LEFT, SELF, end.AsInput()));
1125 EXPECT_EQ(VT_EMPTY, end.type());
1126
1127 // Logical directions should be supported.
1128 EXPECT_EQ(S_OK, ia_root->accNavigate(NAVDIR_FIRSTCHILD, SELF, end.AsInput()));
1129 EXPECT_EQ(VT_DISPATCH, end.type());
1130 EXPECT_EQ(V_DISPATCH(var_child1.ptr()), V_DISPATCH(end.ptr()));
1131
1132 EXPECT_EQ(S_OK, ia_root->accNavigate(NAVDIR_LASTCHILD, SELF, end.AsInput()));
1133 EXPECT_EQ(VT_DISPATCH, end.type());
1134 EXPECT_EQ(V_DISPATCH(var_child2.ptr()), V_DISPATCH(end.ptr()));
1135
1136 EXPECT_EQ(S_OK, ia_child1->accNavigate(NAVDIR_NEXT, SELF, end.AsInput()));
1137 EXPECT_EQ(VT_DISPATCH, end.type());
1138 EXPECT_EQ(V_DISPATCH(var_child2.ptr()), V_DISPATCH(end.ptr()));
1139
1140 EXPECT_EQ(S_OK, ia_child2->accNavigate(NAVDIR_PREVIOUS, SELF, end.AsInput()));
1141 EXPECT_EQ(VT_DISPATCH, end.type());
1142 EXPECT_EQ(V_DISPATCH(var_child1.ptr()), V_DISPATCH(end.ptr()));
1143
1144 // Child indices can also be passed by variant.
1145 // Indices are one-based.
1146 EXPECT_EQ(S_OK,
1147 ia_root->accNavigate(NAVDIR_NEXT, ScopedVariant(1), end.AsInput()));
1148 EXPECT_EQ(VT_DISPATCH, end.type());
1149 EXPECT_EQ(V_DISPATCH(var_child2.ptr()), V_DISPATCH(end.ptr()));
1150
1151 EXPECT_EQ(S_OK, ia_root->accNavigate(NAVDIR_PREVIOUS, ScopedVariant(2),
1152 end.AsInput()));
1153 EXPECT_EQ(VT_DISPATCH, end.type());
1154 EXPECT_EQ(V_DISPATCH(var_child1.ptr()), V_DISPATCH(end.ptr()));
1155
1156 // Test out-of-bounds.
1157 EXPECT_EQ(S_FALSE,
1158 ia_child1->accNavigate(NAVDIR_PREVIOUS, SELF, end.AsInput()));
1159 EXPECT_EQ(VT_EMPTY, end.type());
1160 EXPECT_EQ(S_FALSE, ia_child2->accNavigate(NAVDIR_NEXT, SELF, end.AsInput()));
1161 EXPECT_EQ(VT_EMPTY, end.type());
1162
1163 EXPECT_EQ(S_FALSE, ia_root->accNavigate(NAVDIR_PREVIOUS, ScopedVariant(1),
1164 end.AsInput()));
1165 EXPECT_EQ(VT_EMPTY, end.type());
1166 EXPECT_EQ(S_FALSE,
1167 ia_root->accNavigate(NAVDIR_NEXT, ScopedVariant(2), end.AsInput()));
1168 EXPECT_EQ(VT_EMPTY, end.type());
1169}
1170
1171TEST_F(AXPlatformNodeWinTest, AnnotatedImageName) {
1172 std::vector<const wchar_t*> expected_names;
1173
1174 AXTreeUpdate tree;
1175 tree.root_id = 1;
1176 tree.nodes.resize(11);
1177 tree.nodes[0].id = 1;
1178 tree.nodes[0].child_ids = {2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
1179
1180 // If the status is EligibleForAnnotation and there's no existing label,
1181 // the name should be the discoverability string.
1182 tree.nodes[1].id = 2;
1183 tree.nodes[1].role = ax::mojom::Role::kImage;
1184 tree.nodes[1].AddStringAttribute(ax::mojom::StringAttribute::kImageAnnotation,
1185 "Annotation");
1186 tree.nodes[1].SetImageAnnotationStatus(
1188 expected_names.push_back(
1189 L"To get missing image descriptions, open the context menu.");
1190
1191 // If the status is EligibleForAnnotation, the discoverability string
1192 // should be appended to the existing name.
1193 tree.nodes[2].id = 3;
1194 tree.nodes[2].role = ax::mojom::Role::kImage;
1195 tree.nodes[2].AddStringAttribute(ax::mojom::StringAttribute::kImageAnnotation,
1196 "Annotation");
1197 tree.nodes[2].SetName("ExistingLabel");
1198 tree.nodes[2].SetImageAnnotationStatus(
1200 expected_names.push_back(
1201 L"ExistingLabel. To get missing image descriptions, open the context "
1202 L"menu.");
1203
1204 // If the status is SilentlyEligibleForAnnotation, the discoverability string
1205 // should not be appended to the existing name.
1206 tree.nodes[3].id = 4;
1207 tree.nodes[3].role = ax::mojom::Role::kImage;
1208 tree.nodes[3].AddStringAttribute(ax::mojom::StringAttribute::kImageAnnotation,
1209 "Annotation");
1210 tree.nodes[3].SetName("ExistingLabel");
1211 tree.nodes[3].SetImageAnnotationStatus(
1213 expected_names.push_back(L"ExistingLabel");
1214
1215 // If the status is IneligibleForAnnotation, nothing should be appended.
1216 tree.nodes[4].id = 5;
1217 tree.nodes[4].role = ax::mojom::Role::kImage;
1218 tree.nodes[4].AddStringAttribute(ax::mojom::StringAttribute::kImageAnnotation,
1219 "Annotation");
1220 tree.nodes[4].SetName("ExistingLabel");
1221 tree.nodes[4].SetImageAnnotationStatus(
1223 expected_names.push_back(L"ExistingLabel");
1224
1225 // If the status is AnnotationPending, pending text should be appended
1226 // to the name.
1227 tree.nodes[5].id = 6;
1228 tree.nodes[5].role = ax::mojom::Role::kImage;
1229 tree.nodes[5].AddStringAttribute(ax::mojom::StringAttribute::kImageAnnotation,
1230 "Annotation");
1231 tree.nodes[5].SetName("ExistingLabel");
1232 tree.nodes[5].SetImageAnnotationStatus(
1234 expected_names.push_back(L"ExistingLabel. Getting description...");
1235
1236 // If the status is AnnotationSucceeded, and there's no annotation,
1237 // nothing should be appended. (Ideally this shouldn't happen.)
1238 tree.nodes[6].id = 7;
1239 tree.nodes[6].role = ax::mojom::Role::kImage;
1240 tree.nodes[6].SetName("ExistingLabel");
1241 tree.nodes[6].SetImageAnnotationStatus(
1243 expected_names.push_back(L"ExistingLabel");
1244
1245 // If the status is AnnotationSucceeded, the annotation should be appended
1246 // to the existing label.
1247 tree.nodes[7].id = 8;
1248 tree.nodes[7].role = ax::mojom::Role::kImage;
1249 tree.nodes[7].AddStringAttribute(ax::mojom::StringAttribute::kImageAnnotation,
1250 "Annotation");
1251 tree.nodes[7].SetName("ExistingLabel");
1252 tree.nodes[7].SetImageAnnotationStatus(
1254 expected_names.push_back(L"ExistingLabel. Annotation");
1255
1256 // If the status is AnnotationEmpty, failure text should be added to the
1257 // name.
1258 tree.nodes[8].id = 9;
1259 tree.nodes[8].role = ax::mojom::Role::kImage;
1260 tree.nodes[8].AddStringAttribute(ax::mojom::StringAttribute::kImageAnnotation,
1261 "Annotation");
1262 tree.nodes[8].SetName("ExistingLabel");
1263 tree.nodes[8].SetImageAnnotationStatus(
1265 expected_names.push_back(L"ExistingLabel. No description available.");
1266
1267 // If the status is AnnotationAdult, appropriate text should be appended
1268 // to the name.
1269 tree.nodes[9].id = 10;
1270 tree.nodes[9].role = ax::mojom::Role::kImage;
1271 tree.nodes[9].AddStringAttribute(ax::mojom::StringAttribute::kImageAnnotation,
1272 "Annotation");
1273 tree.nodes[9].SetName("ExistingLabel");
1274 tree.nodes[9].SetImageAnnotationStatus(
1276 expected_names.push_back(
1277 L"ExistingLabel. Appears to contain adult content. No description "
1278 L"available.");
1279
1280 // If the status is AnnotationProcessFailed, failure text should be added
1281 // to the name.
1282 tree.nodes[10].id = 11;
1283 tree.nodes[10].role = ax::mojom::Role::kImage;
1284 tree.nodes[10].AddStringAttribute(
1286 tree.nodes[10].SetName("ExistingLabel");
1287 tree.nodes[10].SetImageAnnotationStatus(
1289 expected_names.push_back(L"ExistingLabel. No description available.");
1290
1291 // We should have one expected name per child of the root.
1292 ASSERT_EQ(expected_names.size(), tree.nodes[0].child_ids.size());
1293 int child_count = static_cast<int>(expected_names.size());
1294
1295 Init(tree);
1296
1297 ComPtr<IAccessible> root_obj(GetRootIAccessible());
1298
1299 for (int child_index = 0; child_index < child_count; child_index++) {
1300 ComPtr<IDispatch> child_dispatch;
1301 ASSERT_HRESULT_SUCCEEDED(root_obj->get_accChild(
1302 ScopedVariant(child_index + 1), &child_dispatch));
1303 ComPtr<IAccessible> child;
1304 ASSERT_HRESULT_SUCCEEDED(child_dispatch.As(&child));
1305
1307 EXPECT_EQ(S_OK, child->get_accName(SELF, name.Receive()));
1308 EXPECT_STREQ(expected_names[child_index], name.Get());
1309 }
1310}
1311
1312TEST_F(AXPlatformNodeWinTest, IGridProviderGetRowCount) {
1313 Init(BuildAriaColumnAndRowCountGrids());
1314
1315 // Empty Grid
1316 ComPtr<IGridProvider> grid1_provider =
1317 QueryInterfaceFromNode<IGridProvider>(GetRootAsAXNode()->children()[0]);
1318
1319 // Grid with a cell that defines aria-rowindex (4) and aria-colindex (5)
1320 ComPtr<IGridProvider> grid2_provider =
1321 QueryInterfaceFromNode<IGridProvider>(GetRootAsAXNode()->children()[1]);
1322
1323 // Grid that specifies aria-rowcount (2) and aria-colcount (3)
1324 ComPtr<IGridProvider> grid3_provider =
1325 QueryInterfaceFromNode<IGridProvider>(GetRootAsAXNode()->children()[2]);
1326
1327 // Grid that specifies aria-rowcount and aria-colcount are both (-1)
1328 ComPtr<IGridProvider> grid4_provider =
1329 QueryInterfaceFromNode<IGridProvider>(GetRootAsAXNode()->children()[3]);
1330
1331 int row_count;
1332
1333 EXPECT_HRESULT_SUCCEEDED(grid1_provider->get_RowCount(&row_count));
1334 EXPECT_EQ(row_count, 0);
1335
1336 EXPECT_HRESULT_SUCCEEDED(grid2_provider->get_RowCount(&row_count));
1337 EXPECT_EQ(row_count, 4);
1338
1339 EXPECT_HRESULT_SUCCEEDED(grid3_provider->get_RowCount(&row_count));
1340 EXPECT_EQ(row_count, 2);
1341
1342 EXPECT_EQ(E_UNEXPECTED, grid4_provider->get_RowCount(&row_count));
1343}
1344
1345TEST_F(AXPlatformNodeWinTest, IGridProviderGetColumnCount) {
1346 Init(BuildAriaColumnAndRowCountGrids());
1347
1348 // Empty Grid
1349 ComPtr<IGridProvider> grid1_provider =
1350 QueryInterfaceFromNode<IGridProvider>(GetRootAsAXNode()->children()[0]);
1351
1352 // Grid with a cell that defines aria-rowindex (4) and aria-colindex (5)
1353 ComPtr<IGridProvider> grid2_provider =
1354 QueryInterfaceFromNode<IGridProvider>(GetRootAsAXNode()->children()[1]);
1355
1356 // Grid that specifies aria-rowcount (2) and aria-colcount (3)
1357 ComPtr<IGridProvider> grid3_provider =
1358 QueryInterfaceFromNode<IGridProvider>(GetRootAsAXNode()->children()[2]);
1359
1360 // Grid that specifies aria-rowcount and aria-colcount are both (-1)
1361 ComPtr<IGridProvider> grid4_provider =
1362 QueryInterfaceFromNode<IGridProvider>(GetRootAsAXNode()->children()[3]);
1363
1364 int column_count;
1365
1366 EXPECT_HRESULT_SUCCEEDED(grid1_provider->get_ColumnCount(&column_count));
1367 EXPECT_EQ(column_count, 0);
1368
1369 EXPECT_HRESULT_SUCCEEDED(grid2_provider->get_ColumnCount(&column_count));
1370 EXPECT_EQ(column_count, 5);
1371
1372 EXPECT_HRESULT_SUCCEEDED(grid3_provider->get_ColumnCount(&column_count));
1373 EXPECT_EQ(column_count, 3);
1374
1375 EXPECT_EQ(E_UNEXPECTED, grid4_provider->get_ColumnCount(&column_count));
1376}
1377
1378TEST_F(AXPlatformNodeWinTest, IGridProviderGetItem) {
1379 AXNodeData root;
1380 root.id = 1;
1382 root.AddIntAttribute(ax::mojom::IntAttribute::kAriaRowCount, 1);
1384
1385 AXNodeData row1;
1386 row1.id = 2;
1387 row1.role = ax::mojom::Role::kRow;
1388 root.child_ids.push_back(row1.id);
1389
1390 AXNodeData cell1;
1391 cell1.id = 3;
1392 cell1.role = ax::mojom::Role::kCell;
1393 row1.child_ids.push_back(cell1.id);
1394
1395 Init(root, row1, cell1);
1396
1397 ComPtr<IGridProvider> root_igridprovider(
1398 QueryInterfaceFromNode<IGridProvider>(GetRootAsAXNode()));
1399
1400 ComPtr<IRawElementProviderSimple> cell1_irawelementprovidersimple(
1401 QueryInterfaceFromNode<IRawElementProviderSimple>(
1402 GetRootAsAXNode()->children()[0]->children()[0]));
1403
1404 IRawElementProviderSimple* grid_item = nullptr;
1405 EXPECT_HRESULT_SUCCEEDED(root_igridprovider->GetItem(0, 0, &grid_item));
1406 EXPECT_NE(nullptr, grid_item);
1407 EXPECT_EQ(cell1_irawelementprovidersimple.Get(), grid_item);
1408}
1409
1410TEST_F(AXPlatformNodeWinTest, ITableProviderGetColumnHeaders) {
1411 AXNodeData root;
1412 root.id = 1;
1414
1415 AXNodeData row1;
1416 row1.id = 2;
1417 row1.role = ax::mojom::Role::kRow;
1418 root.child_ids.push_back(row1.id);
1419
1420 AXNodeData column_header;
1421 column_header.id = 3;
1422 column_header.role = ax::mojom::Role::kColumnHeader;
1423 column_header.SetName(u"column_header");
1424 row1.child_ids.push_back(column_header.id);
1425
1426 AXNodeData row_header;
1427 row_header.id = 4;
1428 row_header.role = ax::mojom::Role::kRowHeader;
1429 row_header.SetName(u"row_header");
1430 row1.child_ids.push_back(row_header.id);
1431
1432 Init(root, row1, column_header, row_header);
1433
1434 ComPtr<ITableProvider> root_itableprovider(
1435 QueryInterfaceFromNode<ITableProvider>(GetRootAsAXNode()));
1436
1438 EXPECT_HRESULT_SUCCEEDED(
1439 root_itableprovider->GetColumnHeaders(safearray.Receive()));
1440 EXPECT_NE(nullptr, safearray.Get());
1441
1442 std::vector<std::wstring> expected_names = {L"column_header"};
1443 EXPECT_UIA_ELEMENT_ARRAY_BSTR_EQ(safearray.Get(), UIA_NamePropertyId,
1444 expected_names);
1445
1446 // Remove column_header's native event target and verify it's no longer
1447 // returned.
1448 TestAXNodeWrapper* column_header_wrapper = TestAXNodeWrapper::GetOrCreate(
1449 GetTree(), GetRootAsAXNode()->children()[0]->children()[0]);
1450 column_header_wrapper->ResetNativeEventTarget();
1451
1452 safearray.Release();
1453 EXPECT_HRESULT_SUCCEEDED(
1454 root_itableprovider->GetColumnHeaders(safearray.Receive()));
1455 EXPECT_EQ(nullptr, safearray.Get());
1456}
1457
1458TEST_F(AXPlatformNodeWinTest, ITableProviderGetColumnHeadersMultipleHeaders) {
1459 // Build a table like this:
1460 // header_r1c1 | header_r1c2 | header_r1c3
1461 // cell_r2c1 | cell_r2c2 | cell_r2c3
1462 // cell_r3c1 | header_r3c2 |
1463
1464 // <table>
1465 // <tr aria-label="row1">
1466 // <th>header_r1c1</th>
1467 // <th>header_r1c2</th>
1468 // <th>header_r1c3</th>
1469 // </tr>
1470 // <tr aria-label="row2">
1471 // <td>cell_r2c1</td>
1472 // <td>cell_r2c2</td>
1473 // <td>cell_r2c3</td>
1474 // </tr>
1475 // <tr aria-label="row3">
1476 // <td>cell_r3c1</td>
1477 // <th>header_r3c2</th>
1478 // </tr>
1479 // </table>
1480
1481 AXNodeData root;
1482 root.id = 1;
1484
1485 AXNodeData row1;
1486 row1.id = 2;
1487 row1.role = ax::mojom::Role::kRow;
1488 root.child_ids.push_back(row1.id);
1489
1490 AXNodeData row2;
1491 row2.id = 3;
1492 row2.role = ax::mojom::Role::kRow;
1493 root.child_ids.push_back(row2.id);
1494
1495 AXNodeData row3;
1496 row3.id = 4;
1497 row3.role = ax::mojom::Role::kRow;
1498 root.child_ids.push_back(row3.id);
1499
1500 // <tr aria-label="row1">
1501 // <th>header_r1c1</th> <th>header_r1c2</th> <th>header_r1c3</th>
1502 // </tr>
1503 AXNodeData header_r1c1;
1504 header_r1c1.id = 5;
1505 header_r1c1.role = ax::mojom::Role::kColumnHeader;
1506 header_r1c1.SetName(u"header_r1c1");
1507 row1.child_ids.push_back(header_r1c1.id);
1508
1509 AXNodeData header_r1c2;
1510 header_r1c2.id = 6;
1511 header_r1c2.role = ax::mojom::Role::kColumnHeader;
1512 header_r1c2.SetName(u"header_r1c2");
1513 row1.child_ids.push_back(header_r1c2.id);
1514
1515 AXNodeData header_r1c3;
1516 header_r1c3.id = 7;
1517 header_r1c3.role = ax::mojom::Role::kColumnHeader;
1518 header_r1c3.SetName(u"header_r1c3");
1519 row1.child_ids.push_back(header_r1c3.id);
1520
1521 // <tr aria-label="row2">
1522 // <td>cell_r2c1</td> <td>cell_r2c2</td> <td>cell_r2c3</td>
1523 // </tr>
1524 AXNodeData cell_r2c1;
1525 cell_r2c1.id = 8;
1526 cell_r2c1.role = ax::mojom::Role::kCell;
1527 cell_r2c1.SetName(u"cell_r2c1");
1528 row2.child_ids.push_back(cell_r2c1.id);
1529
1530 AXNodeData cell_r2c2;
1531 cell_r2c2.id = 9;
1532 cell_r2c2.role = ax::mojom::Role::kCell;
1533 cell_r2c2.SetName(u"cell_r2c2");
1534 row2.child_ids.push_back(cell_r2c2.id);
1535
1536 AXNodeData cell_r2c3;
1537 cell_r2c3.id = 10;
1538 cell_r2c3.role = ax::mojom::Role::kCell;
1539 cell_r2c3.SetName(u"cell_r2c3");
1540 row2.child_ids.push_back(cell_r2c3.id);
1541
1542 // <tr aria-label="row3">
1543 // <td>cell_r3c1</td> <th>header_r3c2</th>
1544 // </tr>
1545 AXNodeData cell_r3c1;
1546 cell_r3c1.id = 11;
1547 cell_r3c1.role = ax::mojom::Role::kCell;
1548 cell_r3c1.SetName(u"cell_r3c1");
1549 row3.child_ids.push_back(cell_r3c1.id);
1550
1551 AXNodeData header_r3c2;
1552 header_r3c2.id = 12;
1553 header_r3c2.role = ax::mojom::Role::kColumnHeader;
1554 header_r3c2.SetName(u"header_r3c2");
1555 row3.child_ids.push_back(header_r3c2.id);
1556
1557 Init(root, row1, row2, row3, header_r1c1, header_r1c2, header_r1c3, cell_r2c1,
1558 cell_r2c2, cell_r2c3, cell_r3c1, header_r3c2);
1559
1560 ComPtr<ITableProvider> root_itableprovider(
1561 QueryInterfaceFromNode<ITableProvider>(GetRootAsAXNode()));
1562
1564 EXPECT_HRESULT_SUCCEEDED(
1565 root_itableprovider->GetColumnHeaders(safearray.Receive()));
1566 EXPECT_NE(nullptr, safearray.Get());
1567
1568 // Validate that we retrieve all column headers of the table and in the order
1569 // below.
1570 std::vector<std::wstring> expected_names = {L"header_r1c1", L"header_r1c2",
1571 L"header_r3c2", L"header_r1c3"};
1572 EXPECT_UIA_ELEMENT_ARRAY_BSTR_EQ(safearray.Get(), UIA_NamePropertyId,
1573 expected_names);
1574}
1575
1576TEST_F(AXPlatformNodeWinTest, ITableProviderGetRowHeaders) {
1577 AXNodeData root;
1578 root.id = 1;
1580
1581 AXNodeData row1;
1582 row1.id = 2;
1583 row1.role = ax::mojom::Role::kRow;
1584 root.child_ids.push_back(row1.id);
1585
1586 AXNodeData column_header;
1587 column_header.id = 3;
1588 column_header.role = ax::mojom::Role::kColumnHeader;
1589 column_header.SetName(u"column_header");
1590 row1.child_ids.push_back(column_header.id);
1591
1592 AXNodeData row_header;
1593 row_header.id = 4;
1594 row_header.role = ax::mojom::Role::kRowHeader;
1595 row_header.SetName(u"row_header");
1596 row1.child_ids.push_back(row_header.id);
1597
1598 Init(root, row1, column_header, row_header);
1599
1600 ComPtr<ITableProvider> root_itableprovider(
1601 QueryInterfaceFromNode<ITableProvider>(GetRootAsAXNode()));
1602
1604 EXPECT_HRESULT_SUCCEEDED(
1605 root_itableprovider->GetRowHeaders(safearray.Receive()));
1606 EXPECT_NE(nullptr, safearray.Get());
1607 std::vector<std::wstring> expected_names = {L"row_header"};
1608 EXPECT_UIA_ELEMENT_ARRAY_BSTR_EQ(safearray.Get(), UIA_NamePropertyId,
1609 expected_names);
1610
1611 // Remove row_header's native event target and verify it's no longer returned.
1612 TestAXNodeWrapper* row_header_wrapper = TestAXNodeWrapper::GetOrCreate(
1613 GetTree(), GetRootAsAXNode()->children()[0]->children()[1]);
1614 row_header_wrapper->ResetNativeEventTarget();
1615
1616 safearray.Release();
1617 EXPECT_HRESULT_SUCCEEDED(
1618 root_itableprovider->GetRowHeaders(safearray.Receive()));
1619 EXPECT_EQ(nullptr, safearray.Get());
1620}
1621
1622TEST_F(AXPlatformNodeWinTest, ITableProviderGetRowOrColumnMajor) {
1623 AXNodeData root;
1624 root.id = 1;
1626
1627 Init(root);
1628
1629 ComPtr<ITableProvider> root_itableprovider(
1630 QueryInterfaceFromNode<ITableProvider>(GetRootAsAXNode()));
1631
1632 RowOrColumnMajor row_or_column_major;
1633 EXPECT_HRESULT_SUCCEEDED(
1634 root_itableprovider->get_RowOrColumnMajor(&row_or_column_major));
1635 EXPECT_EQ(row_or_column_major, RowOrColumnMajor_RowMajor);
1636}
1637
1638TEST_F(AXPlatformNodeWinTest, ITableItemProviderGetColumnHeaderItems) {
1639 AXNodeData root;
1640 root.id = 1;
1642
1643 AXNodeData row1;
1644 row1.id = 2;
1645 row1.role = ax::mojom::Role::kRow;
1646 root.child_ids.push_back(row1.id);
1647
1648 AXNodeData column_header_1;
1649 column_header_1.id = 3;
1650 column_header_1.role = ax::mojom::Role::kColumnHeader;
1651 column_header_1.SetName(u"column_header_1");
1652 row1.child_ids.push_back(column_header_1.id);
1653
1654 AXNodeData column_header_2;
1655 column_header_2.id = 4;
1656 column_header_2.role = ax::mojom::Role::kColumnHeader;
1657 column_header_2.SetName(u"column_header_2");
1658 row1.child_ids.push_back(column_header_2.id);
1659
1660 AXNodeData row2;
1661 row2.id = 5;
1662 row2.role = ax::mojom::Role::kRow;
1663 root.child_ids.push_back(row2.id);
1664
1665 AXNodeData cell;
1666 cell.id = 6;
1667 cell.role = ax::mojom::Role::kCell;
1668 row2.child_ids.push_back(cell.id);
1669
1670 Init(root, row1, column_header_1, column_header_2, row2, cell);
1671
1672 TestAXNodeWrapper* root_wrapper =
1673 TestAXNodeWrapper::GetOrCreate(GetTree(), GetRootAsAXNode());
1674 root_wrapper->BuildAllWrappers(GetTree(), GetRootAsAXNode());
1675
1676 ComPtr<ITableItemProvider> cell_itableitemprovider(
1677 QueryInterfaceFromNode<ITableItemProvider>(
1678 GetRootAsAXNode()->children()[1]->children()[0]));
1679
1681 EXPECT_HRESULT_SUCCEEDED(
1682 cell_itableitemprovider->GetColumnHeaderItems(safearray.Receive()));
1683 EXPECT_NE(nullptr, safearray.Get());
1684
1685 std::vector<std::wstring> expected_names = {L"column_header_1"};
1686 EXPECT_UIA_ELEMENT_ARRAY_BSTR_EQ(safearray.Get(), UIA_NamePropertyId,
1687 expected_names);
1688
1689 // Remove column_header_1's native event target and verify it's no longer
1690 // returned.
1691 TestAXNodeWrapper* column_header_wrapper = TestAXNodeWrapper::GetOrCreate(
1692 GetTree(), GetRootAsAXNode()->children()[0]->children()[0]);
1693 column_header_wrapper->ResetNativeEventTarget();
1694
1695 safearray.Release();
1696 EXPECT_HRESULT_SUCCEEDED(
1697 cell_itableitemprovider->GetColumnHeaderItems(safearray.Receive()));
1698 EXPECT_EQ(nullptr, safearray.Get());
1699}
1700
1701TEST_F(AXPlatformNodeWinTest, ITableItemProviderGetRowHeaderItems) {
1702 AXNodeData root;
1703 root.id = 1;
1705
1706 AXNodeData row1;
1707 row1.id = 2;
1708 row1.role = ax::mojom::Role::kRow;
1709 root.child_ids.push_back(row1.id);
1710
1711 AXNodeData row_header_1;
1712 row_header_1.id = 3;
1713 row_header_1.role = ax::mojom::Role::kRowHeader;
1714 row_header_1.SetName(u"row_header_1");
1715 row1.child_ids.push_back(row_header_1.id);
1716
1717 AXNodeData cell;
1718 cell.id = 4;
1719 cell.role = ax::mojom::Role::kCell;
1720 row1.child_ids.push_back(cell.id);
1721
1722 AXNodeData row2;
1723 row2.id = 5;
1724 row2.role = ax::mojom::Role::kRow;
1725 root.child_ids.push_back(row2.id);
1726
1727 AXNodeData row_header_2;
1728 row_header_2.id = 6;
1729 row_header_2.role = ax::mojom::Role::kRowHeader;
1730 row_header_2.SetName(u"row_header_2");
1731 row2.child_ids.push_back(row_header_2.id);
1732
1733 Init(root, row1, row_header_1, cell, row2, row_header_2);
1734
1735 TestAXNodeWrapper* root_wrapper =
1736 TestAXNodeWrapper::GetOrCreate(GetTree(), GetRootAsAXNode());
1737 root_wrapper->BuildAllWrappers(GetTree(), GetRootAsAXNode());
1738
1739 ComPtr<ITableItemProvider> cell_itableitemprovider(
1740 QueryInterfaceFromNode<ITableItemProvider>(
1741 GetRootAsAXNode()->children()[0]->children()[1]));
1742
1744 EXPECT_HRESULT_SUCCEEDED(
1745 cell_itableitemprovider->GetRowHeaderItems(safearray.Receive()));
1746 EXPECT_NE(nullptr, safearray.Get());
1747 std::vector<std::wstring> expected_names = {L"row_header_1"};
1748 EXPECT_UIA_ELEMENT_ARRAY_BSTR_EQ(safearray.Get(), UIA_NamePropertyId,
1749 expected_names);
1750
1751 // Remove row_header_1's native event target and verify it's no longer
1752 // returned.
1753 TestAXNodeWrapper* row_header_wrapper = TestAXNodeWrapper::GetOrCreate(
1754 GetTree(), GetRootAsAXNode()->children()[0]->children()[0]);
1755 row_header_wrapper->ResetNativeEventTarget();
1756
1757 safearray.Release();
1758 EXPECT_HRESULT_SUCCEEDED(
1759 cell_itableitemprovider->GetRowHeaderItems(safearray.Receive()));
1760 EXPECT_EQ(nullptr, safearray.Get());
1761}
1762
1763TEST_F(AXPlatformNodeWinTest, UIAGetPropertySimple) {
1764 AXNodeData root;
1766 root.SetName("fake name");
1767 root.AddStringAttribute(ax::mojom::StringAttribute::kAccessKey, "Ctrl+Q");
1768 root.AddStringAttribute(ax::mojom::StringAttribute::kLanguage, "en-us");
1769 root.AddStringAttribute(ax::mojom::StringAttribute::kKeyShortcuts, "Alt+F4");
1771 "fake description");
1772 root.AddIntAttribute(ax::mojom::IntAttribute::kSetSize, 2);
1773 root.AddIntAttribute(ax::mojom::IntAttribute::kInvalidState, 1);
1774 root.id = 1;
1775
1776 AXNodeData child1;
1777 child1.id = 2;
1778 child1.role = ax::mojom::Role::kListItem;
1779 child1.AddIntAttribute(ax::mojom::IntAttribute::kPosInSet, 1);
1780 child1.SetName("child1");
1781 root.child_ids.push_back(child1.id);
1782
1783 Init(root, child1);
1784
1785 ComPtr<IRawElementProviderSimple> root_node =
1786 GetRootIRawElementProviderSimple();
1787 ScopedVariant uia_id;
1788 EXPECT_UIA_BSTR_EQ(root_node, UIA_AccessKeyPropertyId, L"Ctrl+Q");
1789 EXPECT_UIA_BSTR_EQ(root_node, UIA_AcceleratorKeyPropertyId, L"Alt+F4");
1790 ASSERT_HRESULT_SUCCEEDED(root_node->GetPropertyValue(
1791 UIA_AutomationIdPropertyId, uia_id.Receive()));
1792 EXPECT_UIA_BSTR_EQ(root_node, UIA_AutomationIdPropertyId,
1793 uia_id.ptr()->bstrVal);
1794 EXPECT_UIA_BSTR_EQ(root_node, UIA_FullDescriptionPropertyId,
1795 L"fake description");
1796 EXPECT_UIA_BSTR_EQ(root_node, UIA_AriaRolePropertyId, L"list");
1797 EXPECT_UIA_BSTR_EQ(root_node, UIA_AriaPropertiesPropertyId,
1798 L"readonly=true;expanded=false;multiline=false;"
1799 L"multiselectable=false;required=false;setsize=2");
1800 constexpr int en_us_lcid = 1033;
1801 EXPECT_UIA_INT_EQ(root_node, UIA_CulturePropertyId, en_us_lcid);
1802 EXPECT_UIA_BSTR_EQ(root_node, UIA_NamePropertyId, L"fake name");
1803 EXPECT_UIA_INT_EQ(root_node, UIA_ControlTypePropertyId,
1804 int{UIA_ListControlTypeId});
1805 EXPECT_UIA_INT_EQ(root_node, UIA_OrientationPropertyId,
1806 int{OrientationType_None});
1807 EXPECT_UIA_INT_EQ(root_node, UIA_SizeOfSetPropertyId, 2);
1808 EXPECT_UIA_INT_EQ(root_node, UIA_ToggleToggleStatePropertyId,
1809 int{ToggleState_Off});
1810 EXPECT_UIA_BOOL_EQ(root_node, UIA_IsPasswordPropertyId, false);
1811 EXPECT_UIA_BOOL_EQ(root_node, UIA_IsEnabledPropertyId, true);
1812 EXPECT_UIA_BOOL_EQ(root_node, UIA_HasKeyboardFocusPropertyId, false);
1813 EXPECT_UIA_BOOL_EQ(root_node, UIA_IsRequiredForFormPropertyId, false);
1814 EXPECT_UIA_BOOL_EQ(root_node, UIA_IsDataValidForFormPropertyId, true);
1815 EXPECT_UIA_BOOL_EQ(root_node, UIA_IsKeyboardFocusablePropertyId, false);
1816 EXPECT_UIA_BOOL_EQ(root_node, UIA_IsOffscreenPropertyId, false);
1817 ComPtr<IRawElementProviderSimple> child_node1 =
1818 QueryInterfaceFromNode<IRawElementProviderSimple>(
1819 GetRootAsAXNode()->children()[0]);
1820 EXPECT_UIA_INT_EQ(child_node1, UIA_PositionInSetPropertyId, 1);
1821}
1822
1823TEST_F(AXPlatformNodeWinTest, UIAGetPropertyValueClickablePoint) {
1824 AXNodeData root;
1825 root.id = 1;
1827 root.relative_bounds.bounds = gfx::RectF(20, 30, 100, 200);
1828 Init(root);
1829
1830 ComPtr<IRawElementProviderSimple> raw_element_provider_simple =
1831 GetRootIRawElementProviderSimple();
1832
1833 // The clickable point of a rectangle {20, 30, 100, 200} is the rectangle's
1834 // center, with coordinates {x: 70, y: 130}.
1835 std::vector<double> expected_values = {70, 130};
1836 EXPECT_UIA_DOUBLE_ARRAY_EQ(raw_element_provider_simple,
1837 UIA_ClickablePointPropertyId, expected_values);
1838}
1839
1840TEST_F(AXPlatformNodeWinTest, UIAGetPropertyValueIsDialog) {
1841 AXNodeData root;
1842 root.id = 1;
1844 root.child_ids = {2, 3};
1845
1846 AXNodeData alert_dialog;
1847 alert_dialog.id = 2;
1848 alert_dialog.role = ax::mojom::Role::kAlertDialog;
1849
1850 AXNodeData dialog;
1851 dialog.id = 3;
1852 dialog.role = ax::mojom::Role::kDialog;
1853
1854 Init(root, alert_dialog, dialog);
1855
1856 EXPECT_UIA_BOOL_EQ(GetRootIRawElementProviderSimple(), UIA_IsDialogPropertyId,
1857 false);
1858 EXPECT_UIA_BOOL_EQ(GetIRawElementProviderSimpleFromChildIndex(0),
1859 UIA_IsDialogPropertyId, true);
1860 EXPECT_UIA_BOOL_EQ(GetIRawElementProviderSimpleFromChildIndex(1),
1861 UIA_IsDialogPropertyId, true);
1862}
1863
1864TEST_F(AXPlatformNodeWinTest,
1865 UIAGetPropertyValueIsControlElementIgnoredInvisible) {
1866 AXNodeData root;
1867 root.id = 1;
1869 root.child_ids = {2, 3, 4, 5, 6, 7, 8};
1870
1871 AXNodeData normal_button;
1872 normal_button.id = 2;
1873 normal_button.role = ax::mojom::Role::kButton;
1874
1875 AXNodeData ignored_button;
1876 ignored_button.id = 3;
1877 ignored_button.role = ax::mojom::Role::kButton;
1878 ignored_button.AddState(ax::mojom::State::kIgnored);
1879
1880 AXNodeData invisible_button;
1881 invisible_button.id = 4;
1882 invisible_button.role = ax::mojom::Role::kButton;
1883 invisible_button.AddState(ax::mojom::State::kInvisible);
1884
1885 AXNodeData invisible_focusable_button;
1886 invisible_focusable_button.id = 5;
1887 invisible_focusable_button.role = ax::mojom::Role::kButton;
1888 invisible_focusable_button.AddState(ax::mojom::State::kInvisible);
1889 invisible_focusable_button.AddState(ax::mojom::State::kFocusable);
1890
1891 AXNodeData focusable_generic_container;
1892 focusable_generic_container.id = 6;
1893 focusable_generic_container.role = ax::mojom::Role::kGenericContainer;
1894 focusable_generic_container.AddState(ax::mojom::State::kFocusable);
1895
1896 AXNodeData ignored_focusable_generic_container;
1897 ignored_focusable_generic_container.id = 7;
1898 ignored_focusable_generic_container.role = ax::mojom::Role::kGenericContainer;
1899 ignored_focusable_generic_container.AddState(ax::mojom::State::kIgnored);
1900 focusable_generic_container.AddState(ax::mojom::State::kFocusable);
1901
1902 AXNodeData invisible_focusable_generic_container;
1903 invisible_focusable_generic_container.id = 8;
1904 invisible_focusable_generic_container.role =
1906 invisible_focusable_generic_container.AddState(ax::mojom::State::kInvisible);
1907 invisible_focusable_generic_container.AddState(ax::mojom::State::kFocusable);
1908
1909 Init(root, normal_button, ignored_button, invisible_button,
1910 invisible_focusable_button, focusable_generic_container,
1911 ignored_focusable_generic_container,
1912 invisible_focusable_generic_container);
1913
1914 // Turn on web content mode for the AXTree.
1915 TestAXNodeWrapper::SetGlobalIsWebContent(true);
1916
1917 // Normal button (id=2), no invisible or ignored state set. Should be a
1918 // control element.
1919 EXPECT_UIA_BOOL_EQ(GetIRawElementProviderSimpleFromChildIndex(0),
1920 UIA_IsControlElementPropertyId, true);
1921
1922 // Button with ignored state (id=3). Should not be a control element.
1923 EXPECT_UIA_BOOL_EQ(GetIRawElementProviderSimpleFromChildIndex(1),
1924 UIA_IsControlElementPropertyId, false);
1925
1926 // Button with invisible state (id=4). Should not be a control element.
1927 EXPECT_UIA_BOOL_EQ(GetIRawElementProviderSimpleFromChildIndex(2),
1928 UIA_IsControlElementPropertyId, false);
1929
1930 // Button with invisible state, but focusable (id=5). Should not be a control
1931 // element.
1932 EXPECT_UIA_BOOL_EQ(GetIRawElementProviderSimpleFromChildIndex(3),
1933 UIA_IsControlElementPropertyId, false);
1934
1935 // Generic container, focusable (id=6). Should be a control
1936 // element.
1937 EXPECT_UIA_BOOL_EQ(GetIRawElementProviderSimpleFromChildIndex(4),
1938 UIA_IsControlElementPropertyId, true);
1939
1940 // Generic container, ignored but focusable (id=7). Should not be a control
1941 // element.
1942 EXPECT_UIA_BOOL_EQ(GetIRawElementProviderSimpleFromChildIndex(5),
1943 UIA_IsControlElementPropertyId, false);
1944
1945 // Generic container, invisible and ignored, but focusable (id=8). Should not
1946 // be a control element.
1947 EXPECT_UIA_BOOL_EQ(GetIRawElementProviderSimpleFromChildIndex(6),
1948 UIA_IsControlElementPropertyId, false);
1949}
1950
1951TEST_F(AXPlatformNodeWinTest, UIAGetControllerForPropertyId) {
1952 AXNodeData root;
1953 root.id = 1;
1955 root.child_ids = {2, 3, 4};
1956
1957 AXNodeData tab;
1958 tab.id = 2;
1959 tab.role = ax::mojom::Role::kTab;
1960 tab.SetName("tab");
1961 std::vector<AXNode::AXID> controller_ids = {3, 4};
1962 tab.AddIntListAttribute(ax::mojom::IntListAttribute::kControlsIds,
1963 controller_ids);
1964
1965 AXNodeData panel1;
1966 panel1.id = 3;
1967 panel1.role = ax::mojom::Role::kTabPanel;
1968 panel1.SetName("panel1");
1969
1970 AXNodeData panel2;
1971 panel2.id = 4;
1972 panel2.role = ax::mojom::Role::kTabPanel;
1973 panel2.SetName("panel2");
1974
1975 Init(root, tab, panel1, panel2);
1976 TestAXNodeWrapper* root_wrapper =
1977 TestAXNodeWrapper::GetOrCreate(GetTree(), GetRootAsAXNode());
1978 root_wrapper->BuildAllWrappers(GetTree(), GetRootAsAXNode());
1979
1980 ComPtr<IRawElementProviderSimple> tab_node =
1981 QueryInterfaceFromNode<IRawElementProviderSimple>(
1982 GetRootAsAXNode()->children()[0]);
1983
1984 std::vector<std::wstring> expected_names_1 = {L"panel1", L"panel2"};
1986 tab_node, UIA_ControllerForPropertyId, UIA_NamePropertyId,
1987 expected_names_1);
1988
1989 // Remove panel1's native event target and verify it's no longer returned.
1990 TestAXNodeWrapper* panel1_wrapper = TestAXNodeWrapper::GetOrCreate(
1991 GetTree(), GetRootAsAXNode()->children()[1]);
1992 panel1_wrapper->ResetNativeEventTarget();
1993 std::vector<std::wstring> expected_names_2 = {L"panel2"};
1995 tab_node, UIA_ControllerForPropertyId, UIA_NamePropertyId,
1996 expected_names_2);
1997}
1998
1999TEST_F(AXPlatformNodeWinTest, UIAGetDescribedByPropertyId) {
2000 AXNodeData root;
2001 std::vector<AXNode::AXID> describedby_ids = {2, 3, 4};
2003 describedby_ids);
2004 root.id = 1;
2006 root.SetName("root");
2007
2008 AXNodeData child1;
2009 child1.id = 2;
2010 child1.role = ax::mojom::Role::kStaticText;
2011 child1.SetName("child1");
2012
2013 root.child_ids.push_back(child1.id);
2014
2015 AXNodeData child2;
2016 child2.id = 3;
2017 child2.role = ax::mojom::Role::kStaticText;
2018 child2.SetName("child2");
2019
2020 root.child_ids.push_back(child2.id);
2021
2022 Init(root, child1, child2);
2023
2024 ComPtr<IRawElementProviderSimple> root_node =
2025 GetRootIRawElementProviderSimple();
2026
2027 std::vector<std::wstring> expected_names = {L"child1", L"child2"};
2029 root_node, UIA_DescribedByPropertyId, UIA_NamePropertyId, expected_names);
2030}
2031
2032TEST_F(AXPlatformNodeWinTest, UIAItemStatusPropertyId) {
2033 AXNodeData root;
2034 root.id = 1;
2036
2037 AXNodeData row1;
2038 row1.id = 2;
2039 row1.role = ax::mojom::Role::kRow;
2040 row1.AddIntAttribute(ax::mojom::IntAttribute::kSortDirection,
2041 static_cast<int>(ax::mojom::SortDirection::kAscending));
2042 root.child_ids.push_back(row1.id);
2043
2044 AXNodeData header1;
2045 header1.id = 3;
2046 header1.role = ax::mojom::Role::kRowHeader;
2047 header1.AddIntAttribute(
2049 static_cast<int>(ax::mojom::SortDirection::kAscending));
2050 row1.child_ids.push_back(header1.id);
2051
2052 AXNodeData header2;
2053 header2.id = 4;
2054 header2.role = ax::mojom::Role::kColumnHeader;
2055 header2.AddIntAttribute(
2057 static_cast<int>(ax::mojom::SortDirection::kDescending));
2058 row1.child_ids.push_back(header2.id);
2059
2060 AXNodeData header3;
2061 header3.id = 5;
2062 header3.role = ax::mojom::Role::kColumnHeader;
2063 header3.AddIntAttribute(ax::mojom::IntAttribute::kSortDirection,
2064 static_cast<int>(ax::mojom::SortDirection::kOther));
2065 row1.child_ids.push_back(header3.id);
2066
2067 AXNodeData header4;
2068 header4.id = 6;
2069 header4.role = ax::mojom::Role::kColumnHeader;
2070 header4.AddIntAttribute(
2072 static_cast<int>(ax::mojom::SortDirection::kUnsorted));
2073 row1.child_ids.push_back(header4.id);
2074
2075 Init(root, row1, header1, header2, header3, header4);
2076
2077 auto* row_node = GetRootAsAXNode()->children()[0];
2078
2079 EXPECT_UIA_BSTR_EQ(QueryInterfaceFromNode<IRawElementProviderSimple>(
2080 row_node->children()[0]),
2081 UIA_ItemStatusPropertyId, L"ascending");
2082
2083 EXPECT_UIA_BSTR_EQ(QueryInterfaceFromNode<IRawElementProviderSimple>(
2084 row_node->children()[1]),
2085 UIA_ItemStatusPropertyId, L"descending");
2086
2087 EXPECT_UIA_BSTR_EQ(QueryInterfaceFromNode<IRawElementProviderSimple>(
2088 row_node->children()[2]),
2089 UIA_ItemStatusPropertyId, L"other");
2090
2091 EXPECT_UIA_VALUE_EQ(QueryInterfaceFromNode<IRawElementProviderSimple>(
2092 row_node->children()[3]),
2093 UIA_ItemStatusPropertyId, ScopedVariant::kEmptyVariant);
2094
2096 QueryInterfaceFromNode<IRawElementProviderSimple>(row_node),
2097 UIA_ItemStatusPropertyId, ScopedVariant::kEmptyVariant);
2098}
2099
2100TEST_F(AXPlatformNodeWinTest, UIAGetFlowsToPropertyId) {
2101 AXNodeData root;
2102 std::vector<AXNode::AXID> flowto_ids = {2, 3, 4};
2103 root.AddIntListAttribute(ax::mojom::IntListAttribute::kFlowtoIds, flowto_ids);
2104 root.id = 1;
2106 root.SetName("root");
2107
2108 AXNodeData child1;
2109 child1.id = 2;
2110 child1.role = ax::mojom::Role::kStaticText;
2111 child1.SetName("child1");
2112
2113 root.child_ids.push_back(child1.id);
2114
2115 AXNodeData child2;
2116 child2.id = 3;
2117 child2.role = ax::mojom::Role::kStaticText;
2118 child2.SetName("child2");
2119
2120 root.child_ids.push_back(child2.id);
2121
2122 Init(root, child1, child2);
2123
2124 ComPtr<IRawElementProviderSimple> root_node =
2125 GetRootIRawElementProviderSimple();
2126 std::vector<std::wstring> expected_names = {L"child1", L"child2"};
2127 EXPECT_UIA_PROPERTY_ELEMENT_ARRAY_BSTR_EQ(root_node, UIA_FlowsToPropertyId,
2128 UIA_NamePropertyId, expected_names);
2129}
2130
2131TEST_F(AXPlatformNodeWinTest, UIAGetPropertyValueFlowsFromNone) {
2132 AXNodeData root;
2133 root.id = 1;
2135 root.SetName("root");
2136
2137 Init(root);
2138
2139 ComPtr<IRawElementProviderSimple> root_node =
2140 GetRootIRawElementProviderSimple();
2141
2142 ScopedVariant property_value;
2143 EXPECT_HRESULT_SUCCEEDED(root_node->GetPropertyValue(
2144 UIA_FlowsFromPropertyId, property_value.Receive()));
2145 EXPECT_EQ(VT_ARRAY | VT_UNKNOWN, property_value.type());
2146 EXPECT_EQ(nullptr, V_ARRAY(property_value.ptr()));
2147}
2148
2149TEST_F(AXPlatformNodeWinTest, UIAGetPropertyValueFlowsFromSingle) {
2150 AXNodeData root;
2151 root.id = 1;
2153 root.SetName("root");
2154 root.AddIntListAttribute(ax::mojom::IntListAttribute::kFlowtoIds, {2});
2155
2156 AXNodeData child1;
2157 child1.id = 2;
2159 child1.SetName("child1");
2160 root.child_ids.push_back(child1.id);
2161
2162 Init(root, child1);
2163 ASSERT_NE(nullptr,
2164 TestAXNodeWrapper::GetOrCreate(GetTree(), GetRootAsAXNode()));
2165
2166 ComPtr<IRawElementProviderSimple> child_node1 =
2167 QueryInterfaceFromNode<IRawElementProviderSimple>(
2168 GetRootAsAXNode()->children()[0]);
2169 std::vector<std::wstring> expected_names = {L"root"};
2171 child_node1, UIA_FlowsFromPropertyId, UIA_NamePropertyId, expected_names);
2172}
2173
2174TEST_F(AXPlatformNodeWinTest, UIAGetPropertyValueFlowsFromMultiple) {
2175 AXNodeData root;
2176 root.id = 1;
2178 root.SetName("root");
2179 root.AddIntListAttribute(ax::mojom::IntListAttribute::kFlowtoIds, {2, 3});
2180
2181 AXNodeData child1;
2182 child1.id = 2;
2184 child1.SetName("child1");
2185 child1.AddIntListAttribute(ax::mojom::IntListAttribute::kFlowtoIds, {3});
2186 root.child_ids.push_back(child1.id);
2187
2188 AXNodeData child2;
2189 child2.id = 3;
2191 child2.SetName("child2");
2192 root.child_ids.push_back(child2.id);
2193
2194 Init(root, child1, child2);
2195 ASSERT_NE(nullptr,
2196 TestAXNodeWrapper::GetOrCreate(GetTree(), GetRootAsAXNode()));
2197 ASSERT_NE(nullptr, TestAXNodeWrapper::GetOrCreate(
2198 GetTree(), GetRootAsAXNode()->children()[0]));
2199
2200 ComPtr<IRawElementProviderSimple> child_node2 =
2201 QueryInterfaceFromNode<IRawElementProviderSimple>(
2202 GetRootAsAXNode()->children()[1]);
2203 std::vector<std::wstring> expected_names_1 = {L"root", L"child1"};
2205 child_node2, UIA_FlowsFromPropertyId, UIA_NamePropertyId,
2206 expected_names_1);
2207
2208 // Remove child1's native event target and verify it's no longer returned.
2209 TestAXNodeWrapper* child1_wrapper = TestAXNodeWrapper::GetOrCreate(
2210 GetTree(), GetRootAsAXNode()->children()[0]);
2211 child1_wrapper->ResetNativeEventTarget();
2212 std::vector<std::wstring> expected_names_2 = {L"root"};
2214 child_node2, UIA_FlowsFromPropertyId, UIA_NamePropertyId,
2215 expected_names_2);
2216}
2217
2218TEST_F(AXPlatformNodeWinTest, UIAGetPropertyValueFrameworkId) {
2219 AXNodeData root_ax_node_data;
2220 root_ax_node_data.id = 1;
2221 root_ax_node_data.role = ax::mojom::Role::kRootWebArea;
2222 Init(root_ax_node_data);
2223
2224 ComPtr<IRawElementProviderSimple> root_raw_element_provider_simple =
2225 GetRootIRawElementProviderSimple();
2226 EXPECT_UIA_BSTR_EQ(root_raw_element_provider_simple,
2227 UIA_FrameworkIdPropertyId, L"Chrome");
2228}
2229
2230TEST_F(AXPlatformNodeWinTest, GetPropertyValue_LabeledByTest) {
2231 // ++1 root
2232 // ++++2 kGenericContainer LabeledBy 3
2233 // ++++++3 kStaticText "Hello"
2234 // ++++4 kGenericContainer LabeledBy 5
2235 // ++++++5 kGenericContainer
2236 // ++++++++6 kStaticText "3.14"
2237 // ++++7 kAlert LabeledBy 6
2238 AXNodeData root_1;
2239 AXNodeData gc_2;
2240 AXNodeData static_text_3;
2241 AXNodeData gc_4;
2242 AXNodeData gc_5;
2243 AXNodeData static_text_6;
2244 AXNodeData alert_7;
2245
2246 root_1.id = 1;
2247 gc_2.id = 2;
2248 static_text_3.id = 3;
2249 gc_4.id = 4;
2250 gc_5.id = 5;
2251 static_text_6.id = 6;
2252 alert_7.id = 7;
2253
2254 root_1.role = ax::mojom::Role::kRootWebArea;
2255 root_1.child_ids = {gc_2.id, gc_4.id, alert_7.id};
2256
2258 gc_2.AddIntListAttribute(ax::mojom::IntListAttribute::kLabelledbyIds,
2259 {static_text_3.id});
2260 gc_2.child_ids = {static_text_3.id};
2261
2262 static_text_3.role = ax::mojom::Role::kStaticText;
2263 static_text_3.SetName("Hello");
2264
2266 gc_4.AddIntListAttribute(ax::mojom::IntListAttribute::kLabelledbyIds,
2267 {gc_5.id});
2268 gc_4.child_ids = {gc_5.id};
2269
2271 gc_5.child_ids = {static_text_6.id};
2272
2273 static_text_6.role = ax::mojom::Role::kStaticText;
2274 static_text_6.SetName("3.14");
2275
2276 alert_7.role = ax::mojom::Role::kAlert;
2277 alert_7.AddIntListAttribute(ax::mojom::IntListAttribute::kLabelledbyIds,
2278 {static_text_6.id});
2279
2280 Init(root_1, gc_2, static_text_3, gc_4, gc_5, static_text_6, alert_7);
2281
2282 AXNode* root_node = GetRootAsAXNode();
2283 AXNode* gc_2_node = root_node->children()[0];
2284 AXNode* static_text_3_node = gc_2_node->children()[0];
2285 AXNode* gc_4_node = root_node->children()[1];
2286 AXNode* static_text_6_node = gc_4_node->children()[0]->children()[0];
2287 AXNode* alert_7_node = root_node->children()[2];
2288
2289 // Case 1: |gc_2| is labeled by |static_text_3|.
2290
2291 ComPtr<IRawElementProviderSimple> gc_2_provider =
2292 GetIRawElementProviderSimpleFromTree(gc_2_node->tree()->GetAXTreeID(),
2293 gc_2_node->id());
2294 ScopedVariant property_value;
2295 EXPECT_EQ(S_OK, gc_2_provider->GetPropertyValue(UIA_LabeledByPropertyId,
2296 property_value.Receive()));
2297 ASSERT_EQ(property_value.type(), VT_UNKNOWN);
2298 ComPtr<IRawElementProviderSimple> static_text_3_provider;
2299 EXPECT_EQ(S_OK, property_value.ptr()->punkVal->QueryInterface(
2300 IID_PPV_ARGS(&static_text_3_provider)));
2301 EXPECT_UIA_BSTR_EQ(static_text_3_provider, UIA_NamePropertyId, L"Hello");
2302
2303 // Case 2: |gc_4| is labeled by |gc_5| and should return the first static text
2304 // child of that node, which is |static_text_6|.
2305
2306 ComPtr<IRawElementProviderSimple> gc_4_provider =
2307 GetIRawElementProviderSimpleFromTree(gc_4_node->tree()->GetAXTreeID(),
2308 gc_4_node->id());
2309 property_value.Reset();
2310 EXPECT_EQ(S_OK, gc_4_provider->GetPropertyValue(UIA_LabeledByPropertyId,
2311 property_value.Receive()));
2312 ASSERT_EQ(property_value.type(), VT_UNKNOWN);
2313 ComPtr<IRawElementProviderSimple> static_text_6_provider;
2314 EXPECT_EQ(S_OK, property_value.ptr()->punkVal->QueryInterface(
2315 IID_PPV_ARGS(&static_text_6_provider)));
2316 EXPECT_UIA_BSTR_EQ(static_text_6_provider, UIA_NamePropertyId, L"3.14");
2317
2318 // Case 3: Some UIA control types always expect an empty value for this
2319 // property. The role kAlert corresponds to UIA_TextControlTypeId, which
2320 // always expects an empty value. |alert_7| is marked as labeled by
2321 // |static_text_6|, but shouldn't expose it to the UIA_LabeledByPropertyId.
2322
2323 ComPtr<IRawElementProviderSimple> alert_7_provider =
2324 GetIRawElementProviderSimpleFromTree(alert_7_node->tree()->GetAXTreeID(),
2325 alert_7_node->id());
2326 property_value.Reset();
2327 EXPECT_EQ(S_OK, alert_7_provider->GetPropertyValue(UIA_LabeledByPropertyId,
2328 property_value.Receive()));
2329 ASSERT_EQ(property_value.type(), VT_EMPTY);
2330
2331 // Remove the referenced nodes' native event targets and verify it's no longer
2332 // returned.
2333
2334 // Case 1.
2335 TestAXNodeWrapper* static_text_3_node_wrapper =
2336 TestAXNodeWrapper::GetOrCreate(GetTree(), static_text_3_node);
2337 static_text_3_node_wrapper->ResetNativeEventTarget();
2338
2339 property_value.Reset();
2340 EXPECT_EQ(S_OK, gc_2_provider->GetPropertyValue(UIA_LabeledByPropertyId,
2341 property_value.Receive()));
2342 EXPECT_EQ(property_value.type(), VT_EMPTY);
2343
2344 // Case 2.
2345 TestAXNodeWrapper* static_text_6_node_wrapper =
2346 TestAXNodeWrapper::GetOrCreate(GetTree(), static_text_6_node);
2347 static_text_6_node_wrapper->ResetNativeEventTarget();
2348
2349 property_value.Reset();
2350 EXPECT_EQ(S_OK, gc_4_provider->GetPropertyValue(UIA_LabeledByPropertyId,
2351 property_value.Receive()));
2352 EXPECT_EQ(property_value.type(), VT_EMPTY);
2353}
2354
2355TEST_F(AXPlatformNodeWinTest, GetPropertyValue_HelpText) {
2356 AXNodeData root;
2357 root.id = 1;
2359
2360 // Test Placeholder StringAttribute is exposed
2361 AXNodeData input1;
2362 input1.id = 2;
2363 input1.role = ax::mojom::Role::kTextField;
2364 input1.SetName("name-from-title");
2365 input1.AddIntAttribute(ax::mojom::IntAttribute::kNameFrom,
2366 static_cast<int>(ax::mojom::NameFrom::kTitle));
2367 input1.AddStringAttribute(ax::mojom::StringAttribute::kPlaceholder,
2368 "placeholder");
2369 root.child_ids.push_back(input1.id);
2370
2371 // Test NameFrom Title is exposed
2372 AXNodeData input2;
2373 input2.id = 3;
2374 input2.role = ax::mojom::Role::kTextField;
2375 input2.SetName("name-from-title");
2376 input2.AddIntAttribute(ax::mojom::IntAttribute::kNameFrom,
2377 static_cast<int>(ax::mojom::NameFrom::kTitle));
2378 root.child_ids.push_back(input2.id);
2379
2380 // Test NameFrom Placeholder is exposed
2381 AXNodeData input3;
2382 input3.id = 4;
2383 input3.role = ax::mojom::Role::kTextField;
2384 input3.SetName("name-from-placeholder");
2385 input3.AddIntAttribute(ax::mojom::IntAttribute::kNameFrom,
2386 static_cast<int>(ax::mojom::NameFrom::kPlaceholder));
2387 root.child_ids.push_back(input3.id);
2388
2389 // Test Title StringAttribute is exposed
2390 AXNodeData input4;
2391 input4.id = 5;
2392 input4.role = ax::mojom::Role::kTextField;
2393 input4.SetName("name-from-attribute");
2394 input4.AddIntAttribute(ax::mojom::IntAttribute::kNameFrom,
2395 static_cast<int>(ax::mojom::NameFrom::kAttribute));
2396 input4.AddStringAttribute(ax::mojom::StringAttribute::kTooltip, "tooltip");
2397 root.child_ids.push_back(input4.id);
2398
2399 // Test NameFrom (other), without explicit
2400 // Title / Placeholder StringAttribute is not exposed
2401 AXNodeData input5;
2402 input5.id = 6;
2403 input5.role = ax::mojom::Role::kTextField;
2404 input5.SetName("name-from-attribute");
2405 input5.AddIntAttribute(ax::mojom::IntAttribute::kNameFrom,
2406 static_cast<int>(ax::mojom::NameFrom::kAttribute));
2407 root.child_ids.push_back(input5.id);
2408
2409 Init(root, input1, input2, input3, input4, input5);
2410
2411 auto* root_node = GetRootAsAXNode();
2412 EXPECT_UIA_BSTR_EQ(QueryInterfaceFromNode<IRawElementProviderSimple>(
2413 root_node->children()[0]),
2414 UIA_HelpTextPropertyId, L"placeholder");
2415 EXPECT_UIA_BSTR_EQ(QueryInterfaceFromNode<IRawElementProviderSimple>(
2416 root_node->children()[1]),
2417 UIA_HelpTextPropertyId, L"name-from-title");
2418 EXPECT_UIA_BSTR_EQ(QueryInterfaceFromNode<IRawElementProviderSimple>(
2419 root_node->children()[2]),
2420 UIA_HelpTextPropertyId, L"name-from-placeholder");
2421 EXPECT_UIA_BSTR_EQ(QueryInterfaceFromNode<IRawElementProviderSimple>(
2422 root_node->children()[3]),
2423 UIA_HelpTextPropertyId, L"tooltip");
2424 EXPECT_UIA_VALUE_EQ(QueryInterfaceFromNode<IRawElementProviderSimple>(
2425 root_node->children()[4]),
2426 UIA_HelpTextPropertyId, ScopedVariant::kEmptyVariant);
2427}
2428
2429TEST_F(AXPlatformNodeWinTest, GetPropertyValue_LocalizedControlType) {
2430 AXNodeData root;
2432 root.id = 1;
2434 "root role description");
2435
2436 AXNodeData child1;
2437 child1.id = 2;
2438 child1.role = ax::mojom::Role::kSearchBox;
2439 child1.AddStringAttribute(ax::mojom::StringAttribute::kRoleDescription,
2440 "child1 role description");
2441 root.child_ids.push_back(2);
2442
2443 AXNodeData child2;
2444 child2.id = 3;
2445 child2.role = ax::mojom::Role::kSearchBox;
2446 root.child_ids.push_back(3);
2447
2448 Init(root, child1, child2);
2449
2450 ComPtr<IRawElementProviderSimple> root_node =
2451 GetRootIRawElementProviderSimple();
2452 EXPECT_UIA_BSTR_EQ(root_node, UIA_LocalizedControlTypePropertyId,
2453 L"root role description");
2454 EXPECT_UIA_BSTR_EQ(QueryInterfaceFromNode<IRawElementProviderSimple>(
2455 GetRootAsAXNode()->children()[0]),
2456 UIA_LocalizedControlTypePropertyId,
2457 L"child1 role description");
2458 EXPECT_UIA_BSTR_EQ(QueryInterfaceFromNode<IRawElementProviderSimple>(
2459 GetRootAsAXNode()->children()[1]),
2460 UIA_LocalizedControlTypePropertyId, L"search box");
2461}
2462
2463TEST_F(AXPlatformNodeWinTest, GetPropertyValue_IsControlElement) {
2466 update.tree_data.tree_id = tree_id;
2467 update.has_tree_data = true;
2468 update.root_id = 1;
2469 update.nodes.resize(17);
2470 update.nodes[0].id = 1;
2471 update.nodes[0].role = ax::mojom::Role::kRootWebArea;
2472 update.nodes[0].child_ids = {2, 4, 6, 7, 8, 9, 10,
2473 11, 12, 13, 14, 15, 16, 17};
2474 update.nodes[1].id = 2;
2475 update.nodes[1].role = ax::mojom::Role::kButton;
2476 update.nodes[1].child_ids = {3};
2477 update.nodes[2].id = 3;
2478 update.nodes[2].role = ax::mojom::Role::kStaticText;
2479 update.nodes[2].SetName("some text");
2480 update.nodes[3].id = 4;
2482 update.nodes[3].child_ids = {5};
2483 update.nodes[4].id = 5;
2484 update.nodes[4].role = ax::mojom::Role::kStaticText;
2485 update.nodes[4].SetName("more text");
2486 update.nodes[5].id = 6;
2487 update.nodes[5].role = ax::mojom::Role::kTable;
2488 update.nodes[6].id = 7;
2489 update.nodes[6].role = ax::mojom::Role::kList;
2490 update.nodes[7].id = 8;
2491 update.nodes[7].role = ax::mojom::Role::kForm;
2492 update.nodes[8].id = 9;
2493 update.nodes[8].role = ax::mojom::Role::kImage;
2494 update.nodes[9].id = 10;
2495 update.nodes[9].role = ax::mojom::Role::kImage;
2496 update.nodes[9].SetNameExplicitlyEmpty();
2497 update.nodes[10].id = 11;
2498 update.nodes[10].role = ax::mojom::Role::kArticle;
2499 update.nodes[11].id = 12;
2501 update.nodes[11].AddBoolAttribute(ax::mojom::BoolAttribute::kHasAriaAttribute,
2502 true);
2503 update.nodes[12].id = 13;
2505 update.nodes[12].AddBoolAttribute(ax::mojom::BoolAttribute::kEditableRoot,
2506 true);
2507 update.nodes[13].id = 14;
2509 update.nodes[13].SetName("name");
2510 update.nodes[14].id = 15;
2512 update.nodes[14].SetDescription("description");
2513 update.nodes[15].id = 16;
2515 update.nodes[15].AddState(ax::mojom::State::kFocusable);
2516 update.nodes[16].id = 17;
2517 update.nodes[16].role = ax::mojom::Role::kForm;
2518 update.nodes[16].SetName("name");
2519
2520 Init(update);
2521 TestAXNodeWrapper::SetGlobalIsWebContent(true);
2522
2523 EXPECT_UIA_BOOL_EQ(GetIRawElementProviderSimpleFromTree(tree_id, 2),
2524 UIA_IsControlElementPropertyId, true);
2525 EXPECT_UIA_BOOL_EQ(GetIRawElementProviderSimpleFromTree(tree_id, 3),
2526 UIA_IsControlElementPropertyId, false);
2527 EXPECT_UIA_BOOL_EQ(GetIRawElementProviderSimpleFromTree(tree_id, 4),
2528 UIA_IsControlElementPropertyId, false);
2529 EXPECT_UIA_BOOL_EQ(GetIRawElementProviderSimpleFromTree(tree_id, 5),
2530 UIA_IsControlElementPropertyId, true);
2531 EXPECT_UIA_BOOL_EQ(GetIRawElementProviderSimpleFromTree(tree_id, 6),
2532 UIA_IsControlElementPropertyId, true);
2533 EXPECT_UIA_BOOL_EQ(GetIRawElementProviderSimpleFromTree(tree_id, 7),
2534 UIA_IsControlElementPropertyId, true);
2535 EXPECT_UIA_BOOL_EQ(GetIRawElementProviderSimpleFromTree(tree_id, 8),
2536 UIA_IsControlElementPropertyId, false);
2537 EXPECT_UIA_BOOL_EQ(GetIRawElementProviderSimpleFromTree(tree_id, 9),
2538 UIA_IsControlElementPropertyId, true);
2539 EXPECT_UIA_BOOL_EQ(GetIRawElementProviderSimpleFromTree(tree_id, 10),
2540 UIA_IsControlElementPropertyId, false);
2541 EXPECT_UIA_BOOL_EQ(GetIRawElementProviderSimpleFromTree(tree_id, 11),
2542 UIA_IsControlElementPropertyId, true);
2543 EXPECT_UIA_BOOL_EQ(GetIRawElementProviderSimpleFromTree(tree_id, 12),
2544 UIA_IsControlElementPropertyId, true);
2545 EXPECT_UIA_BOOL_EQ(GetIRawElementProviderSimpleFromTree(tree_id, 13),
2546 UIA_IsControlElementPropertyId, true);
2547 EXPECT_UIA_BOOL_EQ(GetIRawElementProviderSimpleFromTree(tree_id, 14),
2548 UIA_IsControlElementPropertyId, true);
2549 EXPECT_UIA_BOOL_EQ(GetIRawElementProviderSimpleFromTree(tree_id, 15),
2550 UIA_IsControlElementPropertyId, true);
2551 EXPECT_UIA_BOOL_EQ(GetIRawElementProviderSimpleFromTree(tree_id, 16),
2552 UIA_IsControlElementPropertyId, true);
2553 EXPECT_UIA_BOOL_EQ(GetIRawElementProviderSimpleFromTree(tree_id, 17),
2554 UIA_IsControlElementPropertyId, true);
2555}
2556
2557TEST_F(AXPlatformNodeWinTest, UIAGetProviderOptions) {
2558 AXNodeData root_data;
2559 root_data.id = 1;
2560 Init(root_data);
2561
2562 ComPtr<IRawElementProviderSimple> root_node =
2563 GetRootIRawElementProviderSimple();
2564
2565 ProviderOptions provider_options = static_cast<ProviderOptions>(0);
2566 EXPECT_HRESULT_SUCCEEDED(root_node->get_ProviderOptions(&provider_options));
2567 EXPECT_EQ(ProviderOptions_ServerSideProvider |
2568 ProviderOptions_UseComThreading |
2569 ProviderOptions_RefuseNonClientSupport |
2570 ProviderOptions_HasNativeIAccessible,
2571 provider_options);
2572}
2573
2574TEST_F(AXPlatformNodeWinTest, UIAGetHostRawElementProvider) {
2575 AXNodeData root_data;
2576 root_data.id = 1;
2577 Init(root_data);
2578
2579 ComPtr<IRawElementProviderSimple> root_node =
2580 GetRootIRawElementProviderSimple();
2581
2582 ComPtr<IRawElementProviderSimple> host_provider;
2583 EXPECT_HRESULT_SUCCEEDED(
2584 root_node->get_HostRawElementProvider(&host_provider));
2585 EXPECT_EQ(nullptr, host_provider.Get());
2586}
2587
2588TEST_F(AXPlatformNodeWinTest, UIAGetBoundingRectangle) {
2589 AXNodeData root_data;
2590 root_data.id = 1;
2591 root_data.relative_bounds.bounds = gfx::RectF(10, 20, 30, 50);
2592 Init(root_data);
2593
2594 ComPtr<IRawElementProviderFragment> root_node =
2595 GetRootIRawElementProviderFragment();
2596
2597 UiaRect bounding_rectangle;
2598 EXPECT_HRESULT_SUCCEEDED(
2599 root_node->get_BoundingRectangle(&bounding_rectangle));
2600 EXPECT_EQ(10, bounding_rectangle.left);
2601 EXPECT_EQ(20, bounding_rectangle.top);
2602 EXPECT_EQ(30, bounding_rectangle.width);
2603 EXPECT_EQ(50, bounding_rectangle.height);
2604}
2605
2606TEST_F(AXPlatformNodeWinTest, UIAGetFragmentRoot) {
2607 // This test needs to be run on a child node since AXPlatformRootNodeWin
2608 // overrides the method.
2609 AXNodeData root_data;
2610 root_data.id = 1;
2611
2612 AXNodeData element1_data;
2613 element1_data.id = 2;
2614 root_data.child_ids.push_back(element1_data.id);
2615
2616 Init(root_data, element1_data);
2617 InitFragmentRoot();
2618
2619 AXNode* root_node = GetRootAsAXNode();
2620 AXNode* element1_node = root_node->children()[0];
2621
2622 ComPtr<IRawElementProviderFragment> element1_provider =
2623 QueryInterfaceFromNode<IRawElementProviderFragment>(element1_node);
2624 ComPtr<IRawElementProviderFragmentRoot> expected_fragment_root =
2625 GetFragmentRoot();
2626
2627 ComPtr<IRawElementProviderFragmentRoot> actual_fragment_root;
2628 EXPECT_HRESULT_SUCCEEDED(
2629 element1_provider->get_FragmentRoot(&actual_fragment_root));
2630 EXPECT_EQ(expected_fragment_root.Get(), actual_fragment_root.Get());
2631
2632 // Test the case where the fragment root has gone away.
2633 ax_fragment_root_.reset();
2634 actual_fragment_root.Reset();
2636 element1_provider->get_FragmentRoot(&actual_fragment_root));
2637
2638 // Test the case where the widget has gone away.
2639 TestAXNodeWrapper* element1_wrapper =
2640 TestAXNodeWrapper::GetOrCreate(GetTree(), element1_node);
2641 element1_wrapper->ResetNativeEventTarget();
2643 element1_provider->get_FragmentRoot(&actual_fragment_root));
2644}
2645
2646TEST_F(AXPlatformNodeWinTest, UIAGetEmbeddedFragmentRoots) {
2647 AXNodeData root_data;
2648 root_data.id = 1;
2649 Init(root_data);
2650
2651 ComPtr<IRawElementProviderFragment> root_provider =
2652 GetRootIRawElementProviderFragment();
2653
2654 base::win::ScopedSafearray embedded_fragment_roots;
2655 EXPECT_HRESULT_SUCCEEDED(root_provider->GetEmbeddedFragmentRoots(
2656 embedded_fragment_roots.Receive()));
2657 EXPECT_EQ(nullptr, embedded_fragment_roots.Get());
2658}
2659
2660TEST_F(AXPlatformNodeWinTest, UIAGetRuntimeId) {
2661 AXNodeData root_data;
2662 root_data.id = 1;
2663 Init(root_data);
2664
2665 ComPtr<IRawElementProviderFragment> root_provider =
2666 GetRootIRawElementProviderFragment();
2667
2668 base::win::ScopedSafearray runtime_id;
2669 EXPECT_HRESULT_SUCCEEDED(root_provider->GetRuntimeId(runtime_id.Receive()));
2670
2671 LONG array_lower_bound;
2672 EXPECT_HRESULT_SUCCEEDED(
2673 ::SafeArrayGetLBound(runtime_id.Get(), 1, &array_lower_bound));
2674 EXPECT_EQ(0, array_lower_bound);
2675
2676 LONG array_upper_bound;
2677 EXPECT_HRESULT_SUCCEEDED(
2678 ::SafeArrayGetUBound(runtime_id.Get(), 1, &array_upper_bound));
2679 EXPECT_EQ(1, array_upper_bound);
2680
2681 int* array_data;
2682 EXPECT_HRESULT_SUCCEEDED(::SafeArrayAccessData(
2683 runtime_id.Get(), reinterpret_cast<void**>(&array_data)));
2684 EXPECT_EQ(UiaAppendRuntimeId, array_data[0]);
2685 EXPECT_NE(-1, array_data[1]);
2686
2687 EXPECT_HRESULT_SUCCEEDED(::SafeArrayUnaccessData(runtime_id.Get()));
2688}
2689
2690TEST_F(AXPlatformNodeWinTest, UIAIWindowProviderGetIsModalUnset) {
2691 AXNodeData root;
2692 root.id = 1;
2694 Init(root);
2695
2696 ComPtr<IRawElementProviderSimple> raw_element_provider_simple =
2697 GetRootIRawElementProviderSimple();
2698 ComPtr<IWindowProvider> window_provider;
2699 EXPECT_HRESULT_SUCCEEDED(raw_element_provider_simple->GetPatternProvider(
2700 UIA_WindowPatternId, &window_provider));
2701 ASSERT_EQ(nullptr, window_provider.Get());
2702}
2703
2704TEST_F(AXPlatformNodeWinTest, UIAIWindowProviderGetIsModalFalse) {
2705 AXNodeData root;
2706 root.id = 1;
2708 root.AddBoolAttribute(ax::mojom::BoolAttribute::kModal, false);
2709 Init(root);
2710
2711 ComPtr<IRawElementProviderSimple> raw_element_provider_simple =
2712 GetRootIRawElementProviderSimple();
2713 ComPtr<IWindowProvider> window_provider;
2714 EXPECT_HRESULT_SUCCEEDED(raw_element_provider_simple->GetPatternProvider(
2715 UIA_WindowPatternId, &window_provider));
2716 ASSERT_NE(nullptr, window_provider.Get());
2717
2718 BOOL is_modal;
2719 EXPECT_HRESULT_SUCCEEDED(window_provider->get_IsModal(&is_modal));
2720 ASSERT_FALSE(is_modal);
2721}
2722
2723TEST_F(AXPlatformNodeWinTest, UIAIWindowProviderGetIsModalTrue) {
2724 AXNodeData root;
2725 root.id = 1;
2727 root.AddBoolAttribute(ax::mojom::BoolAttribute::kModal, true);
2728 Init(root);
2729
2730 ComPtr<IRawElementProviderSimple> raw_element_provider_simple =
2731 GetRootIRawElementProviderSimple();
2732 ComPtr<IWindowProvider> window_provider;
2733 EXPECT_HRESULT_SUCCEEDED(raw_element_provider_simple->GetPatternProvider(
2734 UIA_WindowPatternId, &window_provider));
2735 ASSERT_NE(nullptr, window_provider.Get());
2736
2737 BOOL is_modal;
2738 EXPECT_HRESULT_SUCCEEDED(window_provider->get_IsModal(&is_modal));
2739 ASSERT_TRUE(is_modal);
2740}
2741
2742TEST_F(AXPlatformNodeWinTest, UIAIWindowProviderInvalidArgument) {
2743 AXNodeData root;
2744 root.id = 1;
2746 root.AddBoolAttribute(ax::mojom::BoolAttribute::kModal, true);
2747 Init(root);
2748
2749 ComPtr<IRawElementProviderSimple> raw_element_provider_simple =
2750 GetRootIRawElementProviderSimple();
2751 ComPtr<IWindowProvider> window_provider;
2752 EXPECT_HRESULT_SUCCEEDED(raw_element_provider_simple->GetPatternProvider(
2753 UIA_WindowPatternId, &window_provider));
2754 ASSERT_NE(nullptr, window_provider.Get());
2755
2756 ASSERT_EQ(E_INVALIDARG, window_provider->WaitForInputIdle(0, nullptr));
2757 ASSERT_EQ(E_INVALIDARG, window_provider->get_CanMaximize(nullptr));
2758 ASSERT_EQ(E_INVALIDARG, window_provider->get_CanMinimize(nullptr));
2759 ASSERT_EQ(E_INVALIDARG, window_provider->get_IsModal(nullptr));
2760 ASSERT_EQ(E_INVALIDARG, window_provider->get_WindowVisualState(nullptr));
2761 ASSERT_EQ(E_INVALIDARG, window_provider->get_WindowInteractionState(nullptr));
2762 ASSERT_EQ(E_INVALIDARG, window_provider->get_IsTopmost(nullptr));
2763}
2764
2765TEST_F(AXPlatformNodeWinTest, UIAIWindowProviderNotSupported) {
2766 AXNodeData root;
2767 root.id = 1;
2769 root.AddBoolAttribute(ax::mojom::BoolAttribute::kModal, true);
2770 Init(root);
2771
2772 ComPtr<IRawElementProviderSimple> raw_element_provider_simple =
2773 GetRootIRawElementProviderSimple();
2774 ComPtr<IWindowProvider> window_provider;
2775 EXPECT_HRESULT_SUCCEEDED(raw_element_provider_simple->GetPatternProvider(
2776 UIA_WindowPatternId, &window_provider));
2777 ASSERT_NE(nullptr, window_provider.Get());
2778
2779 BOOL bool_result;
2780 WindowVisualState window_visual_state_result;
2781 WindowInteractionState window_interaction_state_result;
2782
2783 ASSERT_EQ(static_cast<HRESULT>(UIA_E_NOTSUPPORTED),
2784 window_provider->SetVisualState(
2785 WindowVisualState::WindowVisualState_Normal));
2786 ASSERT_EQ(static_cast<HRESULT>(UIA_E_NOTSUPPORTED), window_provider->Close());
2787 ASSERT_EQ(static_cast<HRESULT>(UIA_E_NOTSUPPORTED),
2788 window_provider->WaitForInputIdle(0, &bool_result));
2789 ASSERT_EQ(static_cast<HRESULT>(UIA_E_NOTSUPPORTED),
2790 window_provider->get_CanMaximize(&bool_result));
2791 ASSERT_EQ(static_cast<HRESULT>(UIA_E_NOTSUPPORTED),
2792 window_provider->get_CanMinimize(&bool_result));
2793 ASSERT_EQ(
2794 static_cast<HRESULT>(UIA_E_NOTSUPPORTED),
2795 window_provider->get_WindowVisualState(&window_visual_state_result));
2796 ASSERT_EQ(static_cast<HRESULT>(UIA_E_NOTSUPPORTED),
2797 window_provider->get_WindowInteractionState(
2798 &window_interaction_state_result));
2799 ASSERT_EQ(static_cast<HRESULT>(UIA_E_NOTSUPPORTED),
2800 window_provider->get_IsTopmost(&bool_result));
2801}
2802
2803TEST_F(AXPlatformNodeWinTest, UIANavigate) {
2804 AXNodeData root_data;
2805 root_data.id = 1;
2806
2807 AXNodeData element1_data;
2808 element1_data.id = 2;
2809 root_data.child_ids.push_back(element1_data.id);
2810
2811 AXNodeData element2_data;
2812 element2_data.id = 3;
2813 root_data.child_ids.push_back(element2_data.id);
2814
2815 AXNodeData element3_data;
2816 element3_data.id = 4;
2817 element1_data.child_ids.push_back(element3_data.id);
2818
2819 Init(root_data, element1_data, element2_data, element3_data);
2820
2821 AXNode* root_node = GetRootAsAXNode();
2822 AXNode* element1_node = root_node->children()[0];
2823 AXNode* element2_node = root_node->children()[1];
2824 AXNode* element3_node = element1_node->children()[0];
2825
2826 auto TestNavigate = [this](AXNode* element_node, AXNode* parent,
2827 AXNode* next_sibling, AXNode* prev_sibling,
2828 AXNode* first_child, AXNode* last_child) {
2829 ComPtr<IRawElementProviderFragment> element_provider =
2830 QueryInterfaceFromNode<IRawElementProviderFragment>(element_node);
2831
2832 auto TestNavigateSingle = [&](NavigateDirection direction,
2833 AXNode* expected_node) {
2834 ComPtr<IRawElementProviderFragment> expected_provider =
2835 QueryInterfaceFromNode<IRawElementProviderFragment>(expected_node);
2836
2837 ComPtr<IRawElementProviderFragment> navigated_to_fragment;
2838 EXPECT_HRESULT_SUCCEEDED(
2839 element_provider->Navigate(direction, &navigated_to_fragment));
2840 EXPECT_EQ(expected_provider.Get(), navigated_to_fragment.Get());
2841 };
2842
2843 TestNavigateSingle(NavigateDirection_Parent, parent);
2844 TestNavigateSingle(NavigateDirection_NextSibling, next_sibling);
2845 TestNavigateSingle(NavigateDirection_PreviousSibling, prev_sibling);
2846 TestNavigateSingle(NavigateDirection_FirstChild, first_child);
2847 TestNavigateSingle(NavigateDirection_LastChild, last_child);
2848 };
2849
2850 TestNavigate(root_node,
2851 nullptr, // Parent
2852 nullptr, // NextSibling
2853 nullptr, // PreviousSibling
2854 element1_node, // FirstChild
2855 element2_node); // LastChild
2856
2857 TestNavigate(element1_node, root_node, element2_node, nullptr, element3_node,
2858 element3_node);
2859
2860 TestNavigate(element2_node, root_node, nullptr, element1_node, nullptr,
2861 nullptr);
2862
2863 TestNavigate(element3_node, element1_node, nullptr, nullptr, nullptr,
2864 nullptr);
2865}
2866
2867TEST_F(AXPlatformNodeWinTest, ISelectionProviderCanSelectMultipleDefault) {
2868 Init(BuildListBox(/*option_1_is_selected*/ false,
2869 /*option_2_is_selected*/ false,
2870 /*option_3_is_selected*/ false, {}));
2871
2872 ComPtr<ISelectionProvider> selection_provider(
2873 QueryInterfaceFromNode<ISelectionProvider>(GetRootAsAXNode()));
2874
2875 BOOL multiple = TRUE;
2876 EXPECT_HRESULT_SUCCEEDED(
2877 selection_provider->get_CanSelectMultiple(&multiple));
2878 EXPECT_FALSE(multiple);
2879}
2880
2881TEST_F(AXPlatformNodeWinTest, ISelectionProviderCanSelectMultipleTrue) {
2882 const std::vector<ax::mojom::State> state = {
2884 Init(BuildListBox(/*option_1_is_selected*/ false,
2885 /*option_2_is_selected*/ false,
2886 /*option_3_is_selected*/ false,
2887 /*additional_state*/ state));
2888
2889 ComPtr<ISelectionProvider> selection_provider(
2890 QueryInterfaceFromNode<ISelectionProvider>(GetRootAsAXNode()));
2891
2892 BOOL multiple = FALSE;
2893 EXPECT_HRESULT_SUCCEEDED(
2894 selection_provider->get_CanSelectMultiple(&multiple));
2895 EXPECT_TRUE(multiple);
2896}
2897
2898TEST_F(AXPlatformNodeWinTest, ISelectionProviderIsSelectionRequiredDefault) {
2899 Init(BuildListBox(/*option_1_is_selected*/ false,
2900 /*option_2_is_selected*/ false,
2901 /*option_3_is_selected*/ false,
2902 /*additional_state*/ {}));
2903
2904 ComPtr<ISelectionProvider> selection_provider(
2905 QueryInterfaceFromNode<ISelectionProvider>(GetRootAsAXNode()));
2906
2907 BOOL selection_required = TRUE;
2908 EXPECT_HRESULT_SUCCEEDED(
2909 selection_provider->get_IsSelectionRequired(&selection_required));
2910 EXPECT_FALSE(selection_required);
2911}
2912
2913TEST_F(AXPlatformNodeWinTest, ISelectionProviderIsSelectionRequiredTrue) {
2914 Init(BuildListBox(/*option_1_is_selected*/ false,
2915 /*option_2_is_selected*/ false,
2916 /*option_3_is_selected*/ false,
2917 /*additional_state*/ {ax::mojom::State::kRequired}));
2918
2919 ComPtr<ISelectionProvider> selection_provider(
2920 QueryInterfaceFromNode<ISelectionProvider>(GetRootAsAXNode()));
2921
2922 BOOL selection_required = FALSE;
2923 EXPECT_HRESULT_SUCCEEDED(
2924 selection_provider->get_IsSelectionRequired(&selection_required));
2925 EXPECT_TRUE(selection_required);
2926}
2927
2928TEST_F(AXPlatformNodeWinTest, ISelectionProviderGetSelectionNoneSelected) {
2929 Init(BuildListBox(/*option_1_is_selected*/ false,
2930 /*option_2_is_selected*/ false,
2931 /*option_3_is_selected*/ false,
2932 /*additional_state*/ {ax::mojom::State::kFocusable}));
2933
2934 ComPtr<ISelectionProvider> selection_provider(
2935 QueryInterfaceFromNode<ISelectionProvider>(GetRootAsAXNode()));
2936
2937 base::win::ScopedSafearray selected_items;
2938 EXPECT_HRESULT_SUCCEEDED(
2939 selection_provider->GetSelection(selected_items.Receive()));
2940 EXPECT_NE(nullptr, selected_items.Get());
2941
2942 LONG array_lower_bound;
2943 EXPECT_HRESULT_SUCCEEDED(
2944 ::SafeArrayGetLBound(selected_items.Get(), 1, &array_lower_bound));
2945 EXPECT_EQ(0, array_lower_bound);
2946
2947 LONG array_upper_bound;
2948 EXPECT_HRESULT_SUCCEEDED(
2949 ::SafeArrayGetUBound(selected_items.Get(), 1, &array_upper_bound));
2950 EXPECT_EQ(-1, array_upper_bound);
2951}
2952
2953TEST_F(AXPlatformNodeWinTest,
2954 ISelectionProviderGetSelectionSingleItemSelected) {
2955 Init(BuildListBox(/*option_1_is_selected*/ false,
2956 /*option_2_is_selected*/ true,
2957 /*option_3_is_selected*/ false,
2958 /*additional_state*/ {ax::mojom::State::kFocusable}));
2959
2960 ComPtr<ISelectionProvider> selection_provider(
2961 QueryInterfaceFromNode<ISelectionProvider>(GetRootAsAXNode()));
2962 ComPtr<IRawElementProviderSimple> option2_provider(
2963 QueryInterfaceFromNode<IRawElementProviderSimple>(
2964 GetRootAsAXNode()->children()[1]));
2965
2966 base::win::ScopedSafearray selected_items;
2967 EXPECT_HRESULT_SUCCEEDED(
2968 selection_provider->GetSelection(selected_items.Receive()));
2969 EXPECT_NE(nullptr, selected_items.Get());
2970
2971 LONG array_lower_bound;
2972 EXPECT_HRESULT_SUCCEEDED(
2973 ::SafeArrayGetLBound(selected_items.Get(), 1, &array_lower_bound));
2974 EXPECT_EQ(0, array_lower_bound);
2975
2976 LONG array_upper_bound;
2977 EXPECT_HRESULT_SUCCEEDED(
2978 ::SafeArrayGetUBound(selected_items.Get(), 1, &array_upper_bound));
2979 EXPECT_EQ(0, array_upper_bound);
2980
2981 IRawElementProviderSimple** array_data;
2982 EXPECT_HRESULT_SUCCEEDED(::SafeArrayAccessData(
2983 selected_items.Get(), reinterpret_cast<void**>(&array_data)));
2984 EXPECT_EQ(option2_provider.Get(), array_data[0]);
2985 EXPECT_HRESULT_SUCCEEDED(::SafeArrayUnaccessData(selected_items.Get()));
2986}
2987
2988TEST_F(AXPlatformNodeWinTest,
2989 ISelectionProviderGetSelectionMultipleItemsSelected) {
2990 const std::vector<ax::mojom::State> state = {
2992 Init(BuildListBox(/*option_1_is_selected*/ true,
2993 /*option_2_is_selected*/ true,
2994 /*option_3_is_selected*/ true,
2995 /*additional_state*/ state));
2996
2997 ComPtr<ISelectionProvider> selection_provider(
2998 QueryInterfaceFromNode<ISelectionProvider>(GetRootAsAXNode()));
2999 ComPtr<IRawElementProviderSimple> option1_provider(
3000 QueryInterfaceFromNode<IRawElementProviderSimple>(
3001 GetRootAsAXNode()->children()[0]));
3002 ComPtr<IRawElementProviderSimple> option2_provider(
3003 QueryInterfaceFromNode<IRawElementProviderSimple>(
3004 GetRootAsAXNode()->children()[1]));
3005 ComPtr<IRawElementProviderSimple> option3_provider(
3006 QueryInterfaceFromNode<IRawElementProviderSimple>(
3007 GetRootAsAXNode()->children()[2]));
3008
3009 base::win::ScopedSafearray selected_items;
3010 EXPECT_HRESULT_SUCCEEDED(
3011 selection_provider->GetSelection(selected_items.Receive()));
3012 EXPECT_NE(nullptr, selected_items.Get());
3013
3014 LONG array_lower_bound;
3015 EXPECT_HRESULT_SUCCEEDED(
3016 ::SafeArrayGetLBound(selected_items.Get(), 1, &array_lower_bound));
3017 EXPECT_EQ(0, array_lower_bound);
3018
3019 LONG array_upper_bound;
3020 EXPECT_HRESULT_SUCCEEDED(
3021 ::SafeArrayGetUBound(selected_items.Get(), 1, &array_upper_bound));
3022 EXPECT_EQ(2, array_upper_bound);
3023
3024 IRawElementProviderSimple** array_data;
3025 EXPECT_HRESULT_SUCCEEDED(::SafeArrayAccessData(
3026 selected_items.Get(), reinterpret_cast<void**>(&array_data)));
3027 EXPECT_EQ(option1_provider.Get(), array_data[0]);
3028 EXPECT_EQ(option2_provider.Get(), array_data[1]);
3029 EXPECT_EQ(option3_provider.Get(), array_data[2]);
3030
3031 EXPECT_HRESULT_SUCCEEDED(::SafeArrayUnaccessData(selected_items.Get()));
3032}
3033
3034TEST_F(AXPlatformNodeWinTest, ComputeUIAControlType) {
3035 AXNodeData root;
3036 root.id = 1;
3038
3039 AXNodeData child1;
3040 AXNode::AXID child1_id = 2;
3041 child1.id = child1_id;
3042 child1.role = ax::mojom::Role::kTable;
3043 root.child_ids.push_back(child1_id);
3044
3045 AXNodeData child2;
3046 AXNode::AXID child2_id = 3;
3047 child2.id = child2_id;
3048 child2.role = ax::mojom::Role::kLayoutTable;
3049 root.child_ids.push_back(child2_id);
3050
3051 AXNodeData child3;
3052 AXNode::AXID child3_id = 4;
3053 child3.id = child3_id;
3054 child3.role = ax::mojom::Role::kTextField;
3055 root.child_ids.push_back(child3_id);
3056
3057 AXNodeData child4;
3058 AXNode::AXID child4_id = 5;
3059 child4.id = child4_id;
3060 child4.role = ax::mojom::Role::kSearchBox;
3061 root.child_ids.push_back(child4_id);
3062
3063 Init(root, child1, child2, child3, child4);
3064
3066 QueryInterfaceFromNodeId<IRawElementProviderSimple>(child1_id),
3067 UIA_ControlTypePropertyId, int{UIA_TableControlTypeId});
3069 QueryInterfaceFromNodeId<IRawElementProviderSimple>(child2_id),
3070 UIA_ControlTypePropertyId, int{UIA_TableControlTypeId});
3072 QueryInterfaceFromNodeId<IRawElementProviderSimple>(child3_id),
3073 UIA_ControlTypePropertyId, int{UIA_EditControlTypeId});
3075 QueryInterfaceFromNodeId<IRawElementProviderSimple>(child4_id),
3076 UIA_ControlTypePropertyId, int{UIA_EditControlTypeId});
3077}
3078
3079TEST_F(AXPlatformNodeWinTest, UIALandmarkType) {
3080 auto TestLandmarkType = [this](ax::mojom::Role node_role,
3081 std::optional<LONG> expected_landmark_type,
3082 const std::string& node_name = {}) {
3083 AXNodeData root_data;
3084 root_data.id = 1;
3085 root_data.role = node_role;
3086 if (!node_name.empty())
3087 root_data.SetName(node_name);
3088 Init(root_data);
3089
3090 ComPtr<IRawElementProviderSimple> root_provider =
3091 GetRootIRawElementProviderSimple();
3092
3093 if (expected_landmark_type) {
3094 EXPECT_UIA_INT_EQ(root_provider, UIA_LandmarkTypePropertyId,
3095 expected_landmark_type.value());
3096 } else {
3097 EXPECT_UIA_EMPTY(root_provider, UIA_LandmarkTypePropertyId);
3098 }
3099 };
3100
3101 TestLandmarkType(ax::mojom::Role::kBanner, UIA_CustomLandmarkTypeId);
3102 TestLandmarkType(ax::mojom::Role::kComplementary, UIA_CustomLandmarkTypeId);
3103 TestLandmarkType(ax::mojom::Role::kContentInfo, UIA_CustomLandmarkTypeId);
3104 TestLandmarkType(ax::mojom::Role::kFooter, UIA_CustomLandmarkTypeId);
3105 TestLandmarkType(ax::mojom::Role::kMain, UIA_MainLandmarkTypeId);
3106 TestLandmarkType(ax::mojom::Role::kNavigation, UIA_NavigationLandmarkTypeId);
3107 TestLandmarkType(ax::mojom::Role::kSearch, UIA_SearchLandmarkTypeId);
3108
3109 // Only named forms should be exposed as landmarks.
3110 TestLandmarkType(ax::mojom::Role::kForm, {});
3111 TestLandmarkType(ax::mojom::Role::kForm, UIA_FormLandmarkTypeId, "name");
3112
3113 // Only named regions should be exposed as landmarks.
3114 TestLandmarkType(ax::mojom::Role::kRegion, {});
3115 TestLandmarkType(ax::mojom::Role::kRegion, UIA_CustomLandmarkTypeId, "name");
3116
3117 TestLandmarkType(ax::mojom::Role::kGroup, {});
3118 TestLandmarkType(ax::mojom::Role::kHeading, {});
3119 TestLandmarkType(ax::mojom::Role::kList, {});
3120 TestLandmarkType(ax::mojom::Role::kTable, {});
3121}
3122
3123TEST_F(AXPlatformNodeWinTest, UIALocalizedLandmarkType) {
3124 auto TestLocalizedLandmarkType =
3125 [this](ax::mojom::Role node_role,
3126 const std::wstring& expected_localized_landmark,
3127 const std::string& node_name = {}) {
3128 AXNodeData root_data;
3129 root_data.id = 1;
3130 root_data.role = node_role;
3131 if (!node_name.empty())
3132 root_data.SetName(node_name);
3133 Init(root_data);
3134
3135 ComPtr<IRawElementProviderSimple> root_provider =
3136 GetRootIRawElementProviderSimple();
3137
3138 if (expected_localized_landmark.empty()) {
3139 EXPECT_UIA_EMPTY(root_provider, UIA_LocalizedLandmarkTypePropertyId);
3140 } else {
3141 EXPECT_UIA_BSTR_EQ(root_provider, UIA_LocalizedLandmarkTypePropertyId,
3142 expected_localized_landmark.c_str());
3143 }
3144 };
3145
3146 TestLocalizedLandmarkType(ax::mojom::Role::kBanner, L"banner");
3147 TestLocalizedLandmarkType(ax::mojom::Role::kComplementary, L"complementary");
3148 TestLocalizedLandmarkType(ax::mojom::Role::kContentInfo,
3149 L"content information");
3150 TestLocalizedLandmarkType(ax::mojom::Role::kFooter, L"content information");
3151
3152 // Only named regions should be exposed as landmarks.
3153 TestLocalizedLandmarkType(ax::mojom::Role::kRegion, {});
3154 TestLocalizedLandmarkType(ax::mojom::Role::kRegion, L"region", "name");
3155
3156 TestLocalizedLandmarkType(ax::mojom::Role::kForm, {});
3157 TestLocalizedLandmarkType(ax::mojom::Role::kGroup, {});
3158 TestLocalizedLandmarkType(ax::mojom::Role::kHeading, {});
3159 TestLocalizedLandmarkType(ax::mojom::Role::kList, {});
3160 TestLocalizedLandmarkType(ax::mojom::Role::kMain, {});
3161 TestLocalizedLandmarkType(ax::mojom::Role::kNavigation, {});
3162 TestLocalizedLandmarkType(ax::mojom::Role::kSearch, {});
3163 TestLocalizedLandmarkType(ax::mojom::Role::kTable, {});
3164}
3165
3166TEST_F(AXPlatformNodeWinTest, IRawElementProviderSimple2ShowContextMenu) {
3167 AXNodeData root_data;
3168 root_data.id = 1;
3169
3170 AXNodeData element1_data;
3171 element1_data.id = 2;
3172 root_data.child_ids.push_back(element1_data.id);
3173
3174 AXNodeData element2_data;
3175 element2_data.id = 3;
3176 root_data.child_ids.push_back(element2_data.id);
3177
3178 Init(root_data, element1_data, element2_data);
3179
3180 AXNode* root_node = GetRootAsAXNode();
3181 AXNode* element1_node = root_node->children()[0];
3182 AXNode* element2_node = root_node->children()[1];
3183
3184 ComPtr<IRawElementProviderSimple2> root_provider =
3185 QueryInterfaceFromNode<IRawElementProviderSimple2>(root_node);
3186 ComPtr<IRawElementProviderSimple2> element1_provider =
3187 QueryInterfaceFromNode<IRawElementProviderSimple2>(element1_node);
3188 ComPtr<IRawElementProviderSimple2> element2_provider =
3189 QueryInterfaceFromNode<IRawElementProviderSimple2>(element2_node);
3190
3191 EXPECT_HRESULT_SUCCEEDED(element1_provider->ShowContextMenu());
3192 EXPECT_EQ(element1_node, TestAXNodeWrapper::GetNodeFromLastShowContextMenu());
3193 EXPECT_HRESULT_SUCCEEDED(element2_provider->ShowContextMenu());
3194 EXPECT_EQ(element2_node, TestAXNodeWrapper::GetNodeFromLastShowContextMenu());
3195 EXPECT_HRESULT_SUCCEEDED(root_provider->ShowContextMenu());
3196 EXPECT_EQ(root_node, TestAXNodeWrapper::GetNodeFromLastShowContextMenu());
3197}
3198
3199TEST_F(AXPlatformNodeWinTest, UIAErrorHandling) {
3200 AXNodeData root;
3201 root.id = 1;
3202 Init(root);
3203
3204 ComPtr<IRawElementProviderSimple> simple_provider =
3205 GetRootIRawElementProviderSimple();
3206 ComPtr<IRawElementProviderSimple2> simple2_provider =
3207 QueryInterfaceFromNode<IRawElementProviderSimple2>(GetRootAsAXNode());
3208 ComPtr<IRawElementProviderFragment> fragment_provider =
3209 GetRootIRawElementProviderFragment();
3210 ComPtr<IGridItemProvider> grid_item_provider =
3211 QueryInterfaceFromNode<IGridItemProvider>(GetRootAsAXNode());
3212 ComPtr<IGridProvider> grid_provider =
3213 QueryInterfaceFromNode<IGridProvider>(GetRootAsAXNode());
3214 ComPtr<IScrollItemProvider> scroll_item_provider =
3215 QueryInterfaceFromNode<IScrollItemProvider>(GetRootAsAXNode());
3216 ComPtr<IScrollProvider> scroll_provider =
3217 QueryInterfaceFromNode<IScrollProvider>(GetRootAsAXNode());
3218 ComPtr<ISelectionItemProvider> selection_item_provider =
3219 QueryInterfaceFromNode<ISelectionItemProvider>(GetRootAsAXNode());
3220 ComPtr<ISelectionProvider> selection_provider =
3221 QueryInterfaceFromNode<ISelectionProvider>(GetRootAsAXNode());
3222 ComPtr<ITableItemProvider> table_item_provider =
3223 QueryInterfaceFromNode<ITableItemProvider>(GetRootAsAXNode());
3224 ComPtr<ITableProvider> table_provider =
3225 QueryInterfaceFromNode<ITableProvider>(GetRootAsAXNode());
3226 ComPtr<IExpandCollapseProvider> expand_collapse_provider =
3227 QueryInterfaceFromNode<IExpandCollapseProvider>(GetRootAsAXNode());
3228 ComPtr<IToggleProvider> toggle_provider =
3229 QueryInterfaceFromNode<IToggleProvider>(GetRootAsAXNode());
3230 ComPtr<IValueProvider> value_provider =
3231 QueryInterfaceFromNode<IValueProvider>(GetRootAsAXNode());
3232 ComPtr<IRangeValueProvider> range_value_provider =
3233 QueryInterfaceFromNode<IRangeValueProvider>(GetRootAsAXNode());
3234 ComPtr<IWindowProvider> window_provider =
3235 QueryInterfaceFromNode<IWindowProvider>(GetRootAsAXNode());
3236
3237 // Create an empty tree.
3238 SetTree(std::make_unique<AXTree>());
3239
3240 // IGridItemProvider
3241 int int_result = 0;
3242 EXPECT_EQ(static_cast<HRESULT>(UIA_E_ELEMENTNOTAVAILABLE),
3243 grid_item_provider->get_Column(&int_result));
3244 EXPECT_EQ(static_cast<HRESULT>(UIA_E_ELEMENTNOTAVAILABLE),
3245 grid_item_provider->get_ColumnSpan(&int_result));
3246 EXPECT_EQ(static_cast<HRESULT>(UIA_E_ELEMENTNOTAVAILABLE),
3247 grid_item_provider->get_Row(&int_result));
3248 EXPECT_EQ(static_cast<HRESULT>(UIA_E_ELEMENTNOTAVAILABLE),
3249 grid_item_provider->get_RowSpan(&int_result));
3250
3251 // IExpandCollapseProvider
3252 ExpandCollapseState expand_collapse_state;
3253 EXPECT_EQ(static_cast<HRESULT>(UIA_E_ELEMENTNOTAVAILABLE),
3254 expand_collapse_provider->Collapse());
3255 EXPECT_EQ(static_cast<HRESULT>(UIA_E_ELEMENTNOTAVAILABLE),
3256 expand_collapse_provider->Expand());
3257 EXPECT_EQ(static_cast<HRESULT>(UIA_E_ELEMENTNOTAVAILABLE),
3258 expand_collapse_provider->get_ExpandCollapseState(
3259 &expand_collapse_state));
3260
3261 // IGridProvider
3262 ComPtr<IRawElementProviderSimple> temp_simple_provider;
3263 EXPECT_EQ(static_cast<HRESULT>(UIA_E_ELEMENTNOTAVAILABLE),
3264 grid_provider->GetItem(0, 0, &temp_simple_provider));
3265 EXPECT_EQ(static_cast<HRESULT>(UIA_E_ELEMENTNOTAVAILABLE),
3266 grid_provider->get_RowCount(&int_result));
3267 EXPECT_EQ(static_cast<HRESULT>(UIA_E_ELEMENTNOTAVAILABLE),
3268 grid_provider->get_ColumnCount(&int_result));
3269
3270 // IScrollItemProvider
3271 EXPECT_EQ(static_cast<HRESULT>(UIA_E_ELEMENTNOTAVAILABLE),
3272 scroll_item_provider->ScrollIntoView());
3273
3274 // IScrollProvider
3275 BOOL bool_result = TRUE;
3276 double double_result = 3.14;
3277 EXPECT_EQ(static_cast<HRESULT>(UIA_E_ELEMENTNOTAVAILABLE),
3278 scroll_provider->SetScrollPercent(0, 0));
3279 EXPECT_EQ(static_cast<HRESULT>(UIA_E_ELEMENTNOTAVAILABLE),
3280 scroll_provider->get_HorizontallyScrollable(&bool_result));
3281 EXPECT_EQ(static_cast<HRESULT>(UIA_E_ELEMENTNOTAVAILABLE),
3282 scroll_provider->get_HorizontalScrollPercent(&double_result));
3283 EXPECT_EQ(static_cast<HRESULT>(UIA_E_ELEMENTNOTAVAILABLE),
3284 scroll_provider->get_HorizontalViewSize(&double_result));
3285 EXPECT_EQ(static_cast<HRESULT>(UIA_E_ELEMENTNOTAVAILABLE),
3286 scroll_provider->get_VerticallyScrollable(&bool_result));
3287 EXPECT_EQ(static_cast<HRESULT>(UIA_E_ELEMENTNOTAVAILABLE),
3288 scroll_provider->get_VerticalScrollPercent(&double_result));
3289 EXPECT_EQ(static_cast<HRESULT>(UIA_E_ELEMENTNOTAVAILABLE),
3290 scroll_provider->get_VerticalViewSize(&double_result));
3291
3292 // ISelectionItemProvider
3293 EXPECT_EQ(static_cast<HRESULT>(UIA_E_ELEMENTNOTAVAILABLE),
3294 selection_item_provider->AddToSelection());
3295 EXPECT_EQ(static_cast<HRESULT>(UIA_E_ELEMENTNOTAVAILABLE),
3296 selection_item_provider->RemoveFromSelection());
3297 EXPECT_EQ(static_cast<HRESULT>(UIA_E_ELEMENTNOTAVAILABLE),
3298 selection_item_provider->Select());
3299 EXPECT_EQ(static_cast<HRESULT>(UIA_E_ELEMENTNOTAVAILABLE),
3300 selection_item_provider->get_IsSelected(&bool_result));
3301 EXPECT_EQ(
3302 static_cast<HRESULT>(UIA_E_ELEMENTNOTAVAILABLE),
3303 selection_item_provider->get_SelectionContainer(&temp_simple_provider));
3304
3305 // ISelectionProvider
3306 base::win::ScopedSafearray array_result;
3307 EXPECT_EQ(static_cast<HRESULT>(UIA_E_ELEMENTNOTAVAILABLE),
3308 selection_provider->GetSelection(array_result.Receive()));
3309 EXPECT_EQ(static_cast<HRESULT>(UIA_E_ELEMENTNOTAVAILABLE),
3310 selection_provider->get_CanSelectMultiple(&bool_result));
3311 EXPECT_EQ(static_cast<HRESULT>(UIA_E_ELEMENTNOTAVAILABLE),
3312 selection_provider->get_IsSelectionRequired(&bool_result));
3313
3314 // ITableItemProvider
3315 RowOrColumnMajor row_or_column_major_result;
3316 EXPECT_EQ(static_cast<HRESULT>(UIA_E_ELEMENTNOTAVAILABLE),
3317 table_item_provider->GetColumnHeaderItems(array_result.Receive()));
3318 EXPECT_EQ(static_cast<HRESULT>(UIA_E_ELEMENTNOTAVAILABLE),
3319 table_item_provider->GetRowHeaderItems(array_result.Receive()));
3320
3321 // ITableProvider
3322 EXPECT_EQ(static_cast<HRESULT>(UIA_E_ELEMENTNOTAVAILABLE),
3323 table_provider->GetColumnHeaders(array_result.Receive()));
3324 EXPECT_EQ(static_cast<HRESULT>(UIA_E_ELEMENTNOTAVAILABLE),
3325 table_provider->GetRowHeaders(array_result.Receive()));
3326 EXPECT_EQ(static_cast<HRESULT>(UIA_E_ELEMENTNOTAVAILABLE),
3327 table_provider->get_RowOrColumnMajor(&row_or_column_major_result));
3328
3329 // IRawElementProviderSimple
3330 ScopedVariant variant;
3331 ComPtr<IUnknown> unknown;
3332 ComPtr<IRawElementProviderSimple> host_provider;
3333 ProviderOptions options;
3334 EXPECT_EQ(static_cast<HRESULT>(UIA_E_ELEMENTNOTAVAILABLE),
3335 simple_provider->GetPatternProvider(UIA_WindowPatternId, &unknown));
3336 EXPECT_EQ(static_cast<HRESULT>(UIA_E_ELEMENTNOTAVAILABLE),
3337 simple_provider->GetPropertyValue(UIA_FrameworkIdPropertyId,
3338 variant.Receive()));
3339 EXPECT_EQ(static_cast<HRESULT>(UIA_E_ELEMENTNOTAVAILABLE),
3340 simple_provider->get_ProviderOptions(&options));
3341 EXPECT_EQ(static_cast<HRESULT>(UIA_E_ELEMENTNOTAVAILABLE),
3342 simple_provider->get_HostRawElementProvider(&host_provider));
3343
3344 // IRawElementProviderSimple2
3345 EXPECT_EQ(static_cast<HRESULT>(UIA_E_ELEMENTNOTAVAILABLE),
3346 simple2_provider->ShowContextMenu());
3347
3348 // IRawElementProviderFragment
3349 ComPtr<IRawElementProviderFragment> navigated_to_fragment;
3351 UiaRect bounding_rectangle;
3352 ComPtr<IRawElementProviderFragmentRoot> fragment_root;
3353 EXPECT_EQ(static_cast<HRESULT>(UIA_E_ELEMENTNOTAVAILABLE),
3354 fragment_provider->Navigate(NavigateDirection_Parent,
3355 &navigated_to_fragment));
3356 EXPECT_EQ(static_cast<HRESULT>(UIA_E_ELEMENTNOTAVAILABLE),
3357 fragment_provider->GetRuntimeId(safearray.Receive()));
3358 EXPECT_EQ(static_cast<HRESULT>(UIA_E_ELEMENTNOTAVAILABLE),
3359 fragment_provider->get_BoundingRectangle(&bounding_rectangle));
3360 EXPECT_EQ(static_cast<HRESULT>(UIA_E_ELEMENTNOTAVAILABLE),
3361 fragment_provider->GetEmbeddedFragmentRoots(safearray.Receive()));
3362 EXPECT_EQ(static_cast<HRESULT>(UIA_E_ELEMENTNOTAVAILABLE),
3363 fragment_provider->get_FragmentRoot(&fragment_root));
3364 EXPECT_EQ(static_cast<HRESULT>(UIA_E_ELEMENTNOTAVAILABLE),
3365 fragment_provider->SetFocus());
3366
3367 // IValueProvider
3368 ScopedBstr bstr_value;
3369 EXPECT_EQ(static_cast<HRESULT>(UIA_E_ELEMENTNOTAVAILABLE),
3370 value_provider->SetValue(L"3.14"));
3371 EXPECT_EQ(static_cast<HRESULT>(UIA_E_ELEMENTNOTAVAILABLE),
3372 value_provider->get_Value(bstr_value.Receive()));
3373
3374 // IRangeValueProvider
3375 EXPECT_EQ(static_cast<HRESULT>(UIA_E_ELEMENTNOTAVAILABLE),
3376 range_value_provider->SetValue(double_result));
3377 EXPECT_EQ(static_cast<HRESULT>(UIA_E_ELEMENTNOTAVAILABLE),
3378 range_value_provider->get_LargeChange(&double_result));
3379 EXPECT_EQ(static_cast<HRESULT>(UIA_E_ELEMENTNOTAVAILABLE),
3380 range_value_provider->get_Maximum(&double_result));
3381 EXPECT_EQ(static_cast<HRESULT>(UIA_E_ELEMENTNOTAVAILABLE),
3382 range_value_provider->get_Minimum(&double_result));
3383 EXPECT_EQ(static_cast<HRESULT>(UIA_E_ELEMENTNOTAVAILABLE),
3384 range_value_provider->get_SmallChange(&double_result));
3385 EXPECT_EQ(static_cast<HRESULT>(UIA_E_ELEMENTNOTAVAILABLE),
3386 range_value_provider->get_Value(&double_result));
3387
3388 // IToggleProvider
3389 ToggleState toggle_state;
3390 EXPECT_EQ(static_cast<HRESULT>(UIA_E_ELEMENTNOTAVAILABLE),
3391 toggle_provider->Toggle());
3392 EXPECT_EQ(static_cast<HRESULT>(UIA_E_ELEMENTNOTAVAILABLE),
3393 toggle_provider->get_ToggleState(&toggle_state));
3394
3395 // IWindowProvider
3396 ASSERT_EQ(static_cast<HRESULT>(UIA_E_ELEMENTNOTAVAILABLE),
3397 window_provider->SetVisualState(
3398 WindowVisualState::WindowVisualState_Normal));
3399 ASSERT_EQ(static_cast<HRESULT>(UIA_E_ELEMENTNOTAVAILABLE),
3400 window_provider->Close());
3401 ASSERT_EQ(static_cast<HRESULT>(UIA_E_ELEMENTNOTAVAILABLE),
3402 window_provider->WaitForInputIdle(0, nullptr));
3403 ASSERT_EQ(static_cast<HRESULT>(UIA_E_ELEMENTNOTAVAILABLE),
3404 window_provider->get_CanMaximize(nullptr));
3405 ASSERT_EQ(static_cast<HRESULT>(UIA_E_ELEMENTNOTAVAILABLE),
3406 window_provider->get_CanMinimize(nullptr));
3407 ASSERT_EQ(static_cast<HRESULT>(UIA_E_ELEMENTNOTAVAILABLE),
3408 window_provider->get_IsModal(nullptr));
3409 ASSERT_EQ(static_cast<HRESULT>(UIA_E_ELEMENTNOTAVAILABLE),
3410 window_provider->get_WindowVisualState(nullptr));
3411 ASSERT_EQ(static_cast<HRESULT>(UIA_E_ELEMENTNOTAVAILABLE),
3412 window_provider->get_WindowInteractionState(nullptr));
3413 ASSERT_EQ(static_cast<HRESULT>(UIA_E_ELEMENTNOTAVAILABLE),
3414 window_provider->get_IsTopmost(nullptr));
3415}
3416
3417TEST_F(AXPlatformNodeWinTest, GetPatternProviderSupportedPatterns) {
3418 constexpr AXNode::AXID root_id = 1;
3419 constexpr AXNode::AXID text_field_with_combo_box_id = 2;
3420 constexpr AXNode::AXID meter_id = 3;
3421 constexpr AXNode::AXID group_with_scroll_id = 4;
3422 constexpr AXNode::AXID checkbox_id = 5;
3423 constexpr AXNode::AXID link_id = 6;
3424 constexpr AXNode::AXID table_without_header_id = 7;
3425 constexpr AXNode::AXID table_without_header_cell_id = 8;
3426 constexpr AXNode::AXID table_with_header_id = 9;
3427 constexpr AXNode::AXID table_with_header_row_1_id = 10;
3428 constexpr AXNode::AXID table_with_header_column_header_id = 11;
3429 constexpr AXNode::AXID table_with_header_row_2_id = 12;
3430 constexpr AXNode::AXID table_with_header_cell_id = 13;
3431 constexpr AXNode::AXID grid_without_header_id = 14;
3432 constexpr AXNode::AXID grid_without_header_cell_id = 15;
3433 constexpr AXNode::AXID grid_with_header_id = 16;
3434 constexpr AXNode::AXID grid_with_header_row_1_id = 17;
3435 constexpr AXNode::AXID grid_with_header_column_header_id = 18;
3436 constexpr AXNode::AXID grid_with_header_row_2_id = 19;
3437 constexpr AXNode::AXID grid_with_header_cell_id = 20;
3438
3440 update.tree_data.tree_id = ui::AXTreeID::CreateNewAXTreeID();
3441 update.has_tree_data = true;
3442 update.root_id = root_id;
3443 update.nodes.resize(20);
3444 update.nodes[0].id = root_id;
3445 update.nodes[0].role = ax::mojom::Role::kRootWebArea;
3446 update.nodes[0].child_ids = {text_field_with_combo_box_id,
3447 meter_id,
3448 group_with_scroll_id,
3449 checkbox_id,
3450 link_id,
3451 table_without_header_id,
3452 table_with_header_id,
3453 grid_without_header_id,
3454 grid_with_header_id};
3455 update.nodes[1].id = text_field_with_combo_box_id;
3457 update.nodes[2].id = meter_id;
3458 update.nodes[2].role = ax::mojom::Role::kMeter;
3459 update.nodes[3].id = group_with_scroll_id;
3460 update.nodes[3].role = ax::mojom::Role::kGroup;
3461 update.nodes[3].AddIntAttribute(ax::mojom::IntAttribute::kScrollXMin, 10);
3462 update.nodes[3].AddIntAttribute(ax::mojom::IntAttribute::kScrollXMax, 10);
3463 update.nodes[3].AddIntAttribute(ax::mojom::IntAttribute::kScrollX, 10);
3464 update.nodes[4].id = checkbox_id;
3465 update.nodes[4].role = ax::mojom::Role::kCheckBox;
3466 update.nodes[5].id = link_id;
3467 update.nodes[5].role = ax::mojom::Role::kLink;
3468 update.nodes[6].id = table_without_header_id;
3469 update.nodes[6].role = ax::mojom::Role::kTable;
3470 update.nodes[6].child_ids = {table_without_header_cell_id};
3471 update.nodes[7].id = table_without_header_cell_id;
3472 update.nodes[7].role = ax::mojom::Role::kCell;
3473 update.nodes[8].id = table_with_header_id;
3474 update.nodes[8].role = ax::mojom::Role::kTable;
3475 update.nodes[8].child_ids = {table_with_header_row_1_id,
3476 table_with_header_row_2_id};
3477 update.nodes[9].id = table_with_header_row_1_id;
3478 update.nodes[9].role = ax::mojom::Role::kRow;
3479 update.nodes[9].child_ids = {table_with_header_column_header_id};
3480 update.nodes[10].id = table_with_header_column_header_id;
3481 update.nodes[10].role = ax::mojom::Role::kColumnHeader;
3482 update.nodes[11].id = table_with_header_row_2_id;
3483 update.nodes[11].role = ax::mojom::Role::kRow;
3484 update.nodes[11].child_ids = {table_with_header_cell_id};
3485 update.nodes[12].id = table_with_header_cell_id;
3486 update.nodes[12].role = ax::mojom::Role::kCell;
3487 update.nodes[13].id = grid_without_header_id;
3488 update.nodes[13].role = ax::mojom::Role::kGrid;
3489 update.nodes[13].child_ids = {grid_without_header_cell_id};
3490 update.nodes[14].id = grid_without_header_cell_id;
3491 update.nodes[14].role = ax::mojom::Role::kCell;
3492 update.nodes[14].AddBoolAttribute(ax::mojom::BoolAttribute::kSelected, false);
3493 update.nodes[15].id = grid_with_header_id;
3494 update.nodes[15].role = ax::mojom::Role::kGrid;
3495 update.nodes[15].child_ids = {grid_with_header_row_1_id,
3496 grid_with_header_row_2_id};
3497 update.nodes[16].id = grid_with_header_row_1_id;
3498 update.nodes[16].role = ax::mojom::Role::kRow;
3499 update.nodes[16].child_ids = {grid_with_header_column_header_id};
3500 update.nodes[17].id = grid_with_header_column_header_id;
3501 update.nodes[17].role = ax::mojom::Role::kColumnHeader;
3502 update.nodes[17].AddBoolAttribute(ax::mojom::BoolAttribute::kSelected, false);
3503 update.nodes[18].id = grid_with_header_row_2_id;
3504 update.nodes[18].role = ax::mojom::Role::kRow;
3505 update.nodes[18].child_ids = {grid_with_header_cell_id};
3506 update.nodes[19].id = grid_with_header_cell_id;
3507 update.nodes[19].role = ax::mojom::Role::kCell;
3508 update.nodes[19].AddBoolAttribute(ax::mojom::BoolAttribute::kSelected, false);
3509
3510 Init(update);
3511
3512 EXPECT_EQ(PatternSet({UIA_ScrollItemPatternId, UIA_TextPatternId,
3513 UIA_TextEditPatternId}),
3514 GetSupportedPatternsFromNodeId(root_id));
3515
3516 EXPECT_EQ(PatternSet({UIA_ScrollItemPatternId, UIA_ValuePatternId,
3517 UIA_ExpandCollapsePatternId, UIA_TextPatternId,
3518 UIA_TextEditPatternId}),
3519 GetSupportedPatternsFromNodeId(text_field_with_combo_box_id));
3520
3521 EXPECT_EQ(PatternSet({UIA_ScrollItemPatternId, UIA_ValuePatternId,
3522 UIA_RangeValuePatternId}),
3523 GetSupportedPatternsFromNodeId(meter_id));
3524
3525 EXPECT_EQ(PatternSet({UIA_ScrollItemPatternId, UIA_ScrollPatternId}),
3526 GetSupportedPatternsFromNodeId(group_with_scroll_id));
3527
3528 EXPECT_EQ(PatternSet({UIA_ScrollItemPatternId, UIA_ValuePatternId,
3529 UIA_TogglePatternId}),
3530 GetSupportedPatternsFromNodeId(checkbox_id));
3531
3532 EXPECT_EQ(PatternSet({UIA_ScrollItemPatternId, UIA_ValuePatternId,
3533 UIA_InvokePatternId}),
3534 GetSupportedPatternsFromNodeId(link_id));
3535
3536 EXPECT_EQ(PatternSet({UIA_ScrollItemPatternId, UIA_GridPatternId}),
3537 GetSupportedPatternsFromNodeId(table_without_header_id));
3538
3539 EXPECT_EQ(PatternSet({UIA_ScrollItemPatternId, UIA_GridItemPatternId}),
3540 GetSupportedPatternsFromNodeId(table_without_header_cell_id));
3541
3542 EXPECT_EQ(PatternSet({UIA_ScrollItemPatternId, UIA_GridPatternId,
3543 UIA_TablePatternId}),
3544 GetSupportedPatternsFromNodeId(table_with_header_id));
3545
3546 EXPECT_EQ(PatternSet({UIA_ScrollItemPatternId, UIA_GridItemPatternId,
3547 UIA_TableItemPatternId}),
3548 GetSupportedPatternsFromNodeId(table_with_header_column_header_id));
3549
3550 EXPECT_EQ(PatternSet({UIA_ScrollItemPatternId, UIA_GridItemPatternId,
3551 UIA_TableItemPatternId}),
3552 GetSupportedPatternsFromNodeId(table_with_header_cell_id));
3553
3554 EXPECT_EQ(PatternSet({UIA_ScrollItemPatternId, UIA_ValuePatternId,
3555 UIA_SelectionPatternId, UIA_GridPatternId}),
3556 GetSupportedPatternsFromNodeId(grid_without_header_id));
3557
3558 EXPECT_EQ(PatternSet({UIA_ScrollItemPatternId, UIA_ValuePatternId,
3559 UIA_SelectionItemPatternId, UIA_GridItemPatternId}),
3560 GetSupportedPatternsFromNodeId(grid_without_header_cell_id));
3561
3562 EXPECT_EQ(PatternSet({UIA_ScrollItemPatternId, UIA_ValuePatternId,
3563 UIA_SelectionPatternId, UIA_GridPatternId,
3564 UIA_TablePatternId}),
3565 GetSupportedPatternsFromNodeId(grid_with_header_id));
3566
3567 EXPECT_EQ(PatternSet({UIA_ScrollItemPatternId, UIA_ValuePatternId,
3568 UIA_GridItemPatternId, UIA_TableItemPatternId,
3569 UIA_SelectionItemPatternId}),
3570 GetSupportedPatternsFromNodeId(grid_with_header_column_header_id));
3571
3572 EXPECT_EQ(PatternSet({UIA_ScrollItemPatternId, UIA_ValuePatternId,
3573 UIA_GridItemPatternId, UIA_TableItemPatternId,
3574 UIA_SelectionItemPatternId}),
3575 GetSupportedPatternsFromNodeId(grid_with_header_cell_id));
3576}
3577
3578TEST_F(AXPlatformNodeWinTest, GetPatternProviderExpandCollapsePattern) {
3580 root.id = 1;
3581
3582 ui::AXNodeData list_box;
3583 ui::AXNodeData list_item;
3584 ui::AXNodeData menu_item;
3585 ui::AXNodeData menu_list_option;
3586 ui::AXNodeData tree_item;
3587 ui::AXNodeData combo_box_grouping;
3588 ui::AXNodeData combo_box_menu_button;
3589 ui::AXNodeData disclosure_triangle;
3590 ui::AXNodeData text_field_with_combo_box;
3591
3592 list_box.id = 2;
3593 list_item.id = 3;
3594 menu_item.id = 4;
3595 menu_list_option.id = 5;
3596 tree_item.id = 6;
3597 combo_box_grouping.id = 7;
3598 combo_box_menu_button.id = 8;
3599 disclosure_triangle.id = 9;
3600 text_field_with_combo_box.id = 10;
3601
3602 root.child_ids.push_back(list_box.id);
3603 root.child_ids.push_back(list_item.id);
3604 root.child_ids.push_back(menu_item.id);
3605 root.child_ids.push_back(menu_list_option.id);
3606 root.child_ids.push_back(tree_item.id);
3607 root.child_ids.push_back(combo_box_grouping.id);
3608 root.child_ids.push_back(combo_box_menu_button.id);
3609 root.child_ids.push_back(disclosure_triangle.id);
3610 root.child_ids.push_back(text_field_with_combo_box.id);
3611
3612 // list_box HasPopup set to false, does not support expand collapse.
3615
3616 // list_item HasPopup set to true, supports expand collapse.
3617 list_item.role = ax::mojom::Role::kListItem;
3619
3620 // menu_item has expanded state and supports expand collapse.
3621 menu_item.role = ax::mojom::Role::kMenuItem;
3623
3624 // menu_list_option has collapsed state and supports expand collapse.
3625 menu_list_option.role = ax::mojom::Role::kMenuListOption;
3626 menu_list_option.AddState(ax::mojom::State::kCollapsed);
3627
3628 // These roles by default supports expand collapse.
3629 tree_item.role = ax::mojom::Role::kTreeItem;
3630 combo_box_grouping.role = ax::mojom::Role::kComboBoxGrouping;
3631 combo_box_menu_button.role = ax::mojom::Role::kComboBoxMenuButton;
3632 disclosure_triangle.role = ax::mojom::Role::kDisclosureTriangle;
3633 text_field_with_combo_box.role = ax::mojom::Role::kTextFieldWithComboBox;
3634
3635 Init(root, list_box, list_item, menu_item, menu_list_option, tree_item,
3636 combo_box_grouping, combo_box_menu_button, disclosure_triangle,
3637 text_field_with_combo_box);
3638
3639 // list_box HasPopup set to false, does not support expand collapse.
3640 ComPtr<IRawElementProviderSimple> raw_element_provider_simple =
3641 GetIRawElementProviderSimpleFromChildIndex(0);
3642 ComPtr<IExpandCollapseProvider> expandcollapse_provider;
3643 EXPECT_HRESULT_SUCCEEDED(raw_element_provider_simple->GetPatternProvider(
3644 UIA_ExpandCollapsePatternId, &expandcollapse_provider));
3645 EXPECT_EQ(nullptr, expandcollapse_provider.Get());
3646
3647 // list_item HasPopup set to true, supports expand collapse.
3648 raw_element_provider_simple = GetIRawElementProviderSimpleFromChildIndex(1);
3649 EXPECT_HRESULT_SUCCEEDED(raw_element_provider_simple->GetPatternProvider(
3650 UIA_ExpandCollapsePatternId, &expandcollapse_provider));
3651 EXPECT_NE(nullptr, expandcollapse_provider.Get());
3652
3653 // menu_item has expanded state and supports expand collapse.
3654 raw_element_provider_simple = GetIRawElementProviderSimpleFromChildIndex(2);
3655 EXPECT_HRESULT_SUCCEEDED(raw_element_provider_simple->GetPatternProvider(
3656 UIA_ExpandCollapsePatternId, &expandcollapse_provider));
3657 EXPECT_NE(nullptr, expandcollapse_provider.Get());
3658
3659 // menu_list_option has collapsed state and supports expand collapse.
3660 raw_element_provider_simple = GetIRawElementProviderSimpleFromChildIndex(3);
3661 EXPECT_HRESULT_SUCCEEDED(raw_element_provider_simple->GetPatternProvider(
3662 UIA_ExpandCollapsePatternId, &expandcollapse_provider));
3663 EXPECT_NE(nullptr, expandcollapse_provider.Get());
3664
3665 // tree_item by default supports expand collapse.
3666 raw_element_provider_simple = GetIRawElementProviderSimpleFromChildIndex(4);
3667 EXPECT_HRESULT_SUCCEEDED(raw_element_provider_simple->GetPatternProvider(
3668 UIA_ExpandCollapsePatternId, &expandcollapse_provider));
3669 EXPECT_NE(nullptr, expandcollapse_provider.Get());
3670
3671 // combo_box_grouping by default supports expand collapse.
3672 raw_element_provider_simple = GetIRawElementProviderSimpleFromChildIndex(5);
3673 EXPECT_HRESULT_SUCCEEDED(raw_element_provider_simple->GetPatternProvider(
3674 UIA_ExpandCollapsePatternId, &expandcollapse_provider));
3675 EXPECT_NE(nullptr, expandcollapse_provider.Get());
3676
3677 // combo_box_menu_button by default supports expand collapse.
3678 raw_element_provider_simple = GetIRawElementProviderSimpleFromChildIndex(6);
3679 EXPECT_HRESULT_SUCCEEDED(raw_element_provider_simple->GetPatternProvider(
3680 UIA_ExpandCollapsePatternId, &expandcollapse_provider));
3681 EXPECT_NE(nullptr, expandcollapse_provider.Get());
3682
3683 // disclosure_triangle by default supports expand collapse.
3684 raw_element_provider_simple = GetIRawElementProviderSimpleFromChildIndex(7);
3685 EXPECT_HRESULT_SUCCEEDED(raw_element_provider_simple->GetPatternProvider(
3686 UIA_ExpandCollapsePatternId, &expandcollapse_provider));
3687 EXPECT_NE(nullptr, expandcollapse_provider.Get());
3688
3689 // text_field_with_combo_box by default supports expand collapse.
3690 raw_element_provider_simple = GetIRawElementProviderSimpleFromChildIndex(8);
3691 EXPECT_HRESULT_SUCCEEDED(raw_element_provider_simple->GetPatternProvider(
3692 UIA_ExpandCollapsePatternId, &expandcollapse_provider));
3693 EXPECT_NE(nullptr, expandcollapse_provider.Get());
3694}
3695
3696TEST_F(AXPlatformNodeWinTest, GetPatternProviderInvokePattern) {
3698 root.id = 1;
3699
3701 ui::AXNodeData generic_container;
3702 ui::AXNodeData combo_box_grouping;
3703 ui::AXNodeData check_box;
3704
3705 link.id = 2;
3706 generic_container.id = 3;
3707 combo_box_grouping.id = 4;
3708 check_box.id = 5;
3709
3710 root.child_ids.push_back(link.id);
3711 root.child_ids.push_back(generic_container.id);
3712 root.child_ids.push_back(combo_box_grouping.id);
3713 root.child_ids.push_back(check_box.id);
3714
3715 // Role link is clickable and neither supports expand collapse nor supports
3716 // toggle. It should support invoke pattern.
3718
3719 // Role generic container is not clickable. It should not support invoke
3720 // pattern.
3721 generic_container.role = ax::mojom::Role::kGenericContainer;
3722
3723 // Role combo box grouping supports expand collapse. It should not support
3724 // invoke pattern.
3725 combo_box_grouping.role = ax::mojom::Role::kComboBoxGrouping;
3726
3727 // Role check box supports toggle. It should not support invoke pattern.
3728 check_box.role = ax::mojom::Role::kCheckBox;
3729
3730 Init(root, link, generic_container, combo_box_grouping, check_box);
3731
3732 // Role link is clickable and neither supports expand collapse nor supports
3733 // toggle. It should support invoke pattern.
3734 ComPtr<IRawElementProviderSimple> raw_element_provider_simple =
3735 GetIRawElementProviderSimpleFromChildIndex(0);
3736 ComPtr<IInvokeProvider> invoke_provider;
3737 EXPECT_HRESULT_SUCCEEDED(raw_element_provider_simple->GetPatternProvider(
3738 UIA_InvokePatternId, &invoke_provider));
3739 EXPECT_NE(nullptr, invoke_provider.Get());
3740
3741 // Role generic container is not clickable. It should not support invoke
3742 // pattern.
3743 raw_element_provider_simple = GetIRawElementProviderSimpleFromChildIndex(1);
3744 EXPECT_HRESULT_SUCCEEDED(raw_element_provider_simple->GetPatternProvider(
3745 UIA_InvokePatternId, &invoke_provider));
3746 EXPECT_EQ(nullptr, invoke_provider.Get());
3747
3748 // Role combo box grouping supports expand collapse. It should not support
3749 // invoke pattern.
3750 raw_element_provider_simple = GetIRawElementProviderSimpleFromChildIndex(2);
3751 EXPECT_HRESULT_SUCCEEDED(raw_element_provider_simple->GetPatternProvider(
3752 UIA_InvokePatternId, &invoke_provider));
3753 EXPECT_EQ(nullptr, invoke_provider.Get());
3754
3755 // Role check box supports toggle. It should not support invoke pattern.
3756 raw_element_provider_simple = GetIRawElementProviderSimpleFromChildIndex(3);
3757 EXPECT_HRESULT_SUCCEEDED(raw_element_provider_simple->GetPatternProvider(
3758 UIA_InvokePatternId, &invoke_provider));
3759 EXPECT_EQ(nullptr, invoke_provider.Get());
3760}
3761
3762TEST_F(AXPlatformNodeWinTest, IExpandCollapsePatternProviderAction) {
3764 root.id = 1;
3765
3766 ui::AXNodeData combo_box_grouping_has_popup;
3767 ui::AXNodeData combo_box_grouping_expanded;
3768 ui::AXNodeData combo_box_grouping_collapsed;
3769 ui::AXNodeData combo_box_grouping_disabled;
3770 ui::AXNodeData button_has_popup_menu;
3771 ui::AXNodeData button_has_popup_menu_pressed;
3772 ui::AXNodeData button_has_popup_true;
3773 ui::AXNodeData generic_container_has_popup_menu;
3774
3775 combo_box_grouping_has_popup.id = 2;
3776 combo_box_grouping_expanded.id = 3;
3777 combo_box_grouping_collapsed.id = 4;
3778 combo_box_grouping_disabled.id = 5;
3779 button_has_popup_menu.id = 6;
3780 button_has_popup_menu_pressed.id = 7;
3781 button_has_popup_true.id = 8;
3782 generic_container_has_popup_menu.id = 9;
3783
3784 root.child_ids = {
3785 combo_box_grouping_has_popup.id, combo_box_grouping_expanded.id,
3786 combo_box_grouping_collapsed.id, combo_box_grouping_disabled.id,
3787 button_has_popup_menu.id, button_has_popup_menu_pressed.id,
3788 button_has_popup_true.id, generic_container_has_popup_menu.id};
3789
3790 // combo_box_grouping HasPopup set to true, can collapse, can expand.
3791 // state is ExpandCollapseState_LeafNode.
3792 combo_box_grouping_has_popup.role = ax::mojom::Role::kComboBoxGrouping;
3793 combo_box_grouping_has_popup.SetHasPopup(ax::mojom::HasPopup::kTrue);
3794
3795 // combo_box_grouping Expanded set, can collapse, cannot expand.
3796 // state is ExpandCollapseState_Expanded.
3797 combo_box_grouping_expanded.role = ax::mojom::Role::kComboBoxGrouping;
3798 combo_box_grouping_expanded.AddState(ax::mojom::State::kExpanded);
3799
3800 // combo_box_grouping Collapsed set, can expand, cannot collapse.
3801 // state is ExpandCollapseState_Collapsed.
3802 combo_box_grouping_collapsed.role = ax::mojom::Role::kComboBoxGrouping;
3803 combo_box_grouping_collapsed.AddState(ax::mojom::State::kCollapsed);
3804
3805 // combo_box_grouping is disabled, can neither expand nor collapse.
3806 // state is ExpandCollapseState_LeafNode.
3807 combo_box_grouping_disabled.role = ax::mojom::Role::kComboBoxGrouping;
3808 combo_box_grouping_disabled.SetRestriction(ax::mojom::Restriction::kDisabled);
3809
3810 // button_has_popup_menu HasPopup set to kMenu and is not STATE_PRESSED.
3811 // state is ExpandCollapseState_Collapsed.
3812 button_has_popup_menu.role = ax::mojom::Role::kButton;
3813 button_has_popup_menu.SetHasPopup(ax::mojom::HasPopup::kMenu);
3814
3815 // button_has_popup_menu_pressed HasPopup set to kMenu and is STATE_PRESSED.
3816 // state is ExpandCollapseState_Expanded.
3817 button_has_popup_menu_pressed.role = ax::mojom::Role::kButton;
3818 button_has_popup_menu_pressed.SetHasPopup(ax::mojom::HasPopup::kMenu);
3819 button_has_popup_menu_pressed.SetCheckedState(ax::mojom::CheckedState::kTrue);
3820
3821 // button_has_popup_true HasPopup set to true but is not a menu.
3822 // state is ExpandCollapseState_LeafNode.
3823 button_has_popup_true.role = ax::mojom::Role::kButton;
3824 button_has_popup_true.SetHasPopup(ax::mojom::HasPopup::kTrue);
3825
3826 // generic_container_has_popup_menu HasPopup set to menu but with no expand
3827 // state set.
3828 // state is ExpandCollapseState_LeafNode.
3829 generic_container_has_popup_menu.role = ax::mojom::Role::kGenericContainer;
3830 generic_container_has_popup_menu.SetHasPopup(ax::mojom::HasPopup::kMenu);
3831
3832 Init(root, combo_box_grouping_has_popup, combo_box_grouping_disabled,
3833 combo_box_grouping_expanded, combo_box_grouping_collapsed,
3834 combo_box_grouping_disabled, button_has_popup_menu,
3835 button_has_popup_menu_pressed, button_has_popup_true,
3836 generic_container_has_popup_menu);
3837
3838 // combo_box_grouping HasPopup set to true, can collapse, can expand.
3839 // state is ExpandCollapseState_LeafNode.
3840 ComPtr<IRawElementProviderSimple> raw_element_provider_simple =
3841 GetIRawElementProviderSimpleFromChildIndex(0);
3842 ComPtr<IExpandCollapseProvider> expandcollapse_provider;
3843 EXPECT_HRESULT_SUCCEEDED(raw_element_provider_simple->GetPatternProvider(
3844 UIA_ExpandCollapsePatternId, &expandcollapse_provider));
3845 ASSERT_NE(nullptr, expandcollapse_provider.Get());
3846 EXPECT_HRESULT_SUCCEEDED(expandcollapse_provider->Collapse());
3847 EXPECT_HRESULT_SUCCEEDED(expandcollapse_provider->Expand());
3848 ExpandCollapseState state;
3849 EXPECT_HRESULT_SUCCEEDED(
3850 expandcollapse_provider->get_ExpandCollapseState(&state));
3851 EXPECT_EQ(ExpandCollapseState_LeafNode, state);
3852
3853 // combo_box_grouping Expanded set, can collapse, cannot expand.
3854 // state is ExpandCollapseState_Expanded.
3855 raw_element_provider_simple = GetIRawElementProviderSimpleFromChildIndex(1);
3856 EXPECT_HRESULT_SUCCEEDED(raw_element_provider_simple->GetPatternProvider(
3857 UIA_ExpandCollapsePatternId, &expandcollapse_provider));
3858 ASSERT_NE(nullptr, expandcollapse_provider.Get());
3859 EXPECT_HRESULT_SUCCEEDED(expandcollapse_provider->Collapse());
3860 EXPECT_HRESULT_FAILED(expandcollapse_provider->Expand());
3861 EXPECT_HRESULT_SUCCEEDED(
3862 expandcollapse_provider->get_ExpandCollapseState(&state));
3863 EXPECT_EQ(ExpandCollapseState_Expanded, state);
3864
3865 // combo_box_grouping Collapsed set, can expand, cannot collapse.
3866 // state is ExpandCollapseState_Collapsed.
3867 raw_element_provider_simple = GetIRawElementProviderSimpleFromChildIndex(2);
3868 EXPECT_HRESULT_SUCCEEDED(raw_element_provider_simple->GetPatternProvider(
3869 UIA_ExpandCollapsePatternId, &expandcollapse_provider));
3870 ASSERT_NE(nullptr, expandcollapse_provider.Get());
3871 EXPECT_HRESULT_FAILED(expandcollapse_provider->Collapse());
3872 EXPECT_HRESULT_SUCCEEDED(expandcollapse_provider->Expand());
3873 EXPECT_HRESULT_SUCCEEDED(
3874 expandcollapse_provider->get_ExpandCollapseState(&state));
3875 EXPECT_EQ(ExpandCollapseState_Collapsed, state);
3876
3877 // combo_box_grouping is disabled, can neither expand nor collapse.
3878 // state is ExpandCollapseState_LeafNode.
3879 raw_element_provider_simple = GetIRawElementProviderSimpleFromChildIndex(3);
3880 EXPECT_HRESULT_SUCCEEDED(raw_element_provider_simple->GetPatternProvider(
3881 UIA_ExpandCollapsePatternId, &expandcollapse_provider));
3882 ASSERT_NE(nullptr, expandcollapse_provider.Get());
3883 EXPECT_HRESULT_FAILED(expandcollapse_provider->Collapse());
3884 EXPECT_HRESULT_FAILED(expandcollapse_provider->Expand());
3885 EXPECT_HRESULT_SUCCEEDED(
3886 expandcollapse_provider->get_ExpandCollapseState(&state));
3887 EXPECT_EQ(ExpandCollapseState_LeafNode, state);
3888
3889 // button_has_popup_menu HasPopup set to kMenu and is not STATE_PRESSED.
3890 // state is ExpandCollapseState_Collapsed.
3891 raw_element_provider_simple = GetIRawElementProviderSimpleFromChildIndex(4);
3892 EXPECT_HRESULT_SUCCEEDED(raw_element_provider_simple->GetPatternProvider(
3893 UIA_ExpandCollapsePatternId, &expandcollapse_provider));
3894 ASSERT_NE(nullptr, expandcollapse_provider.Get());
3895 EXPECT_HRESULT_SUCCEEDED(
3896 expandcollapse_provider->get_ExpandCollapseState(&state));
3897 EXPECT_EQ(ExpandCollapseState_Collapsed, state);
3898
3899 // button_has_popup_menu_pressed HasPopup set to kMenu and is STATE_PRESSED.
3900 // state is ExpandCollapseState_Expanded.
3901 raw_element_provider_simple = GetIRawElementProviderSimpleFromChildIndex(5);
3902 EXPECT_HRESULT_SUCCEEDED(raw_element_provider_simple->GetPatternProvider(
3903 UIA_ExpandCollapsePatternId, &expandcollapse_provider));
3904 ASSERT_NE(nullptr, expandcollapse_provider.Get());
3905 EXPECT_HRESULT_SUCCEEDED(
3906 expandcollapse_provider->get_ExpandCollapseState(&state));
3907 EXPECT_EQ(ExpandCollapseState_Expanded, state);
3908
3909 // button_has_popup_true HasPopup set to true but is not a menu.
3910 // state is ExpandCollapseState_LeafNode.
3911 raw_element_provider_simple = GetIRawElementProviderSimpleFromChildIndex(6);
3912 EXPECT_HRESULT_SUCCEEDED(raw_element_provider_simple->GetPatternProvider(
3913 UIA_ExpandCollapsePatternId, &expandcollapse_provider));
3914 ASSERT_NE(nullptr, expandcollapse_provider.Get());
3915 EXPECT_HRESULT_SUCCEEDED(
3916 expandcollapse_provider->get_ExpandCollapseState(&state));
3917 EXPECT_EQ(ExpandCollapseState_LeafNode, state);
3918
3919 // generic_container_has_popup_menu HasPopup set to menu but with no expand
3920 // state set.
3921 // state is ExpandCollapseState_LeafNode.
3922 raw_element_provider_simple = GetIRawElementProviderSimpleFromChildIndex(7);
3923 EXPECT_HRESULT_SUCCEEDED(raw_element_provider_simple->GetPatternProvider(
3924 UIA_ExpandCollapsePatternId, &expandcollapse_provider));
3925 ASSERT_NE(nullptr, expandcollapse_provider.Get());
3926 EXPECT_HRESULT_SUCCEEDED(
3927 expandcollapse_provider->get_ExpandCollapseState(&state));
3928 EXPECT_EQ(ExpandCollapseState_LeafNode, state);
3929}
3930
3931TEST_F(AXPlatformNodeWinTest, IInvokeProviderInvoke) {
3933 root.id = 1;
3934
3935 ui::AXNodeData button;
3936 ui::AXNodeData button_disabled;
3937
3938 button.id = 2;
3939 button_disabled.id = 3;
3940
3941 root.child_ids.push_back(button.id);
3942 root.child_ids.push_back(button_disabled.id);
3943
3944 // generic button can be invoked.
3946
3947 // disabled button, cannot be invoked.
3948 button_disabled.role = ax::mojom::Role::kButton;
3950
3951 Init(root, button, button_disabled);
3952 AXNode* button_node = GetRootAsAXNode()->children()[0];
3953
3954 // generic button can be invoked.
3955 ComPtr<IRawElementProviderSimple> raw_element_provider_simple =
3956 GetIRawElementProviderSimpleFromChildIndex(0);
3957 ComPtr<IInvokeProvider> invoke_provider;
3958 EXPECT_HRESULT_SUCCEEDED(raw_element_provider_simple->GetPatternProvider(
3959 UIA_InvokePatternId, &invoke_provider));
3960 EXPECT_NE(nullptr, invoke_provider.Get());
3961 EXPECT_HRESULT_SUCCEEDED(invoke_provider->Invoke());
3962 EXPECT_EQ(button_node, TestAXNodeWrapper::GetNodeFromLastDefaultAction());
3963
3964 // disabled button, cannot be invoked.
3965 raw_element_provider_simple = GetIRawElementProviderSimpleFromChildIndex(1);
3966 EXPECT_HRESULT_SUCCEEDED(raw_element_provider_simple->GetPatternProvider(
3967 UIA_InvokePatternId, &invoke_provider));
3968 EXPECT_NE(nullptr, invoke_provider.Get());
3969 EXPECT_UIA_ELEMENTNOTENABLED(invoke_provider->Invoke());
3970}
3971
3972TEST_F(AXPlatformNodeWinTest, ISelectionItemProviderNotSupported) {
3973 AXNodeData root;
3974 root.id = 1;
3976
3977 Init(root);
3978
3979 ComPtr<IRawElementProviderSimple> raw_element_provider_simple =
3980 GetRootIRawElementProviderSimple();
3981 ComPtr<ISelectionItemProvider> selection_item_provider;
3982 EXPECT_HRESULT_SUCCEEDED(raw_element_provider_simple->GetPatternProvider(
3983 UIA_SelectionItemPatternId, &selection_item_provider));
3984 ASSERT_EQ(nullptr, selection_item_provider.Get());
3985}
3986
3987TEST_F(AXPlatformNodeWinTest, ISelectionItemProviderDisabled) {
3988 AXNodeData root;
3989 root.id = 1;
3991 static_cast<int>(ax::mojom::Restriction::kDisabled));
3992 root.AddBoolAttribute(ax::mojom::BoolAttribute::kSelected, true);
3994
3995 Init(root);
3996
3997 ComPtr<IRawElementProviderSimple> raw_element_provider_simple =
3998 GetRootIRawElementProviderSimple();
3999 ComPtr<ISelectionItemProvider> selection_item_provider;
4000 EXPECT_HRESULT_SUCCEEDED(raw_element_provider_simple->GetPatternProvider(
4001 UIA_SelectionItemPatternId, &selection_item_provider));
4002 ASSERT_NE(nullptr, selection_item_provider.Get());
4003
4004 BOOL selected;
4005
4006 EXPECT_UIA_ELEMENTNOTENABLED(selection_item_provider->AddToSelection());
4007 EXPECT_UIA_ELEMENTNOTENABLED(selection_item_provider->RemoveFromSelection());
4008 EXPECT_UIA_ELEMENTNOTENABLED(selection_item_provider->Select());
4009 EXPECT_HRESULT_SUCCEEDED(selection_item_provider->get_IsSelected(&selected));
4010 EXPECT_TRUE(selected);
4011}
4012
4013TEST_F(AXPlatformNodeWinTest, ISelectionItemProviderNotSelectable) {
4014 AXNodeData root;
4015 root.id = 1;
4017
4018 Init(root);
4019
4020 ComPtr<IRawElementProviderSimple> raw_element_provider_simple =
4021 GetRootIRawElementProviderSimple();
4022 ComPtr<ISelectionItemProvider> selection_item_provider;
4023 EXPECT_HRESULT_SUCCEEDED(raw_element_provider_simple->GetPatternProvider(
4024 UIA_SelectionItemPatternId, &selection_item_provider));
4025 ASSERT_EQ(nullptr, selection_item_provider.Get());
4026}
4027
4028TEST_F(AXPlatformNodeWinTest, ISelectionItemProviderSimple) {
4029 AXNodeData root;
4030 root.id = 1;
4032
4033 AXNodeData option1;
4034 option1.id = 2;
4035 option1.AddBoolAttribute(ax::mojom::BoolAttribute::kSelected, false);
4036 option1.role = ax::mojom::Role::kListBoxOption;
4037 root.child_ids.push_back(option1.id);
4038
4039 Init(root, option1);
4040
4041 ComPtr<IRawElementProviderSimple> raw_element_provider_simple =
4042 GetIRawElementProviderSimpleFromChildIndex(0);
4043 ComPtr<ISelectionItemProvider> option1_provider;
4044 EXPECT_HRESULT_SUCCEEDED(raw_element_provider_simple->GetPatternProvider(
4045 UIA_SelectionItemPatternId, &option1_provider));
4046 ASSERT_NE(nullptr, option1_provider.Get());
4047
4048 BOOL selected;
4049
4050 // Note: TestAXNodeWrapper::AccessibilityPerformAction will
4051 // flip kSelected for kListBoxOption when the kDoDefault action is fired.
4052
4053 // Initial State
4054 EXPECT_HRESULT_SUCCEEDED(option1_provider->get_IsSelected(&selected));
4055 EXPECT_FALSE(selected);
4056
4057 // AddToSelection should fire event when not selected
4058 EXPECT_HRESULT_SUCCEEDED(option1_provider->AddToSelection());
4059 EXPECT_HRESULT_SUCCEEDED(option1_provider->get_IsSelected(&selected));
4060 EXPECT_TRUE(selected);
4061
4062 // AddToSelection should not fire event when selected
4063 EXPECT_HRESULT_SUCCEEDED(option1_provider->AddToSelection());
4064 EXPECT_HRESULT_SUCCEEDED(option1_provider->get_IsSelected(&selected));
4065 EXPECT_TRUE(selected);
4066
4067 // RemoveFromSelection should fire event when selected
4068 EXPECT_HRESULT_SUCCEEDED(option1_provider->RemoveFromSelection());
4069 EXPECT_HRESULT_SUCCEEDED(option1_provider->get_IsSelected(&selected));
4070 EXPECT_FALSE(selected);
4071
4072 // RemoveFromSelection should not fire event when not selected
4073 EXPECT_HRESULT_SUCCEEDED(option1_provider->RemoveFromSelection());
4074 EXPECT_HRESULT_SUCCEEDED(option1_provider->get_IsSelected(&selected));
4075 EXPECT_FALSE(selected);
4076
4077 // Select should fire event when not selected
4078 EXPECT_HRESULT_SUCCEEDED(option1_provider->Select());
4079 EXPECT_HRESULT_SUCCEEDED(option1_provider->get_IsSelected(&selected));
4080 EXPECT_TRUE(selected);
4081
4082 // Select should not fire event when selected
4083 EXPECT_HRESULT_SUCCEEDED(option1_provider->Select());
4084 EXPECT_HRESULT_SUCCEEDED(option1_provider->get_IsSelected(&selected));
4085 EXPECT_TRUE(selected);
4086}
4087
4088TEST_F(AXPlatformNodeWinTest, ISelectionItemProviderRadioButton) {
4089 AXNodeData root;
4090 root.id = 1;
4092
4093 // CheckedState::kNone
4094 AXNodeData option1;
4095 option1.id = 2;
4096 option1.AddIntAttribute(ax::mojom::IntAttribute::kCheckedState,
4097 static_cast<int>(ax::mojom::CheckedState::kNone));
4098 option1.role = ax::mojom::Role::kRadioButton;
4099 root.child_ids.push_back(option1.id);
4100
4101 // CheckedState::kFalse
4102 AXNodeData option2;
4103 option2.id = 3;
4104 option2.AddIntAttribute(ax::mojom::IntAttribute::kCheckedState,
4105 static_cast<int>(ax::mojom::CheckedState::kFalse));
4106 option2.role = ax::mojom::Role::kRadioButton;
4107 root.child_ids.push_back(option2.id);
4108
4109 // CheckedState::kTrue
4110 AXNodeData option3;
4111 option3.id = 4;
4112 option3.AddIntAttribute(ax::mojom::IntAttribute::kCheckedState,
4113 static_cast<int>(ax::mojom::CheckedState::kTrue));
4114 option3.role = ax::mojom::Role::kRadioButton;
4115 root.child_ids.push_back(option3.id);
4116
4117 // CheckedState::kMixed
4118 AXNodeData option4;
4119 option4.id = 5;
4120 option4.AddIntAttribute(ax::mojom::IntAttribute::kCheckedState,
4121 static_cast<int>(ax::mojom::CheckedState::kMixed));
4122 option4.role = ax::mojom::Role::kRadioButton;
4123 root.child_ids.push_back(option4.id);
4124
4125 Init(root, option1, option2, option3, option4);
4126
4127 BOOL selected;
4128
4129 // Option 1, CheckedState::kNone, ISelectionItemProvider is not supported.
4130 ComPtr<ISelectionItemProvider> option1_provider;
4131 EXPECT_HRESULT_SUCCEEDED(
4132 GetIRawElementProviderSimpleFromChildIndex(0)->GetPatternProvider(
4133 UIA_SelectionItemPatternId, &option1_provider));
4134 ASSERT_EQ(nullptr, option1_provider.Get());
4135
4136 // Option 2, CheckedState::kFalse.
4137 ComPtr<ISelectionItemProvider> option2_provider;
4138 EXPECT_HRESULT_SUCCEEDED(
4139 GetIRawElementProviderSimpleFromChildIndex(1)->GetPatternProvider(
4140 UIA_SelectionItemPatternId, &option2_provider));
4141 ASSERT_NE(nullptr, option2_provider.Get());
4142
4143 EXPECT_HRESULT_SUCCEEDED(option2_provider->get_IsSelected(&selected));
4144 EXPECT_FALSE(selected);
4145
4146 EXPECT_HRESULT_SUCCEEDED(option2_provider->Select());
4147 EXPECT_HRESULT_SUCCEEDED(option2_provider->get_IsSelected(&selected));
4148 EXPECT_TRUE(selected);
4149
4150 // Option 3, CheckedState::kTrue.
4151 ComPtr<ISelectionItemProvider> option3_provider;
4152 EXPECT_HRESULT_SUCCEEDED(
4153 GetIRawElementProviderSimpleFromChildIndex(2)->GetPatternProvider(
4154 UIA_SelectionItemPatternId, &option3_provider));
4155 ASSERT_NE(nullptr, option3_provider.Get());
4156
4157 EXPECT_HRESULT_SUCCEEDED(option3_provider->get_IsSelected(&selected));
4158 EXPECT_TRUE(selected);
4159
4160 EXPECT_HRESULT_SUCCEEDED(option3_provider->RemoveFromSelection());
4161 EXPECT_HRESULT_SUCCEEDED(option3_provider->get_IsSelected(&selected));
4162 EXPECT_FALSE(selected);
4163
4164 EXPECT_HRESULT_SUCCEEDED(option3_provider->AddToSelection());
4165 EXPECT_HRESULT_SUCCEEDED(option3_provider->get_IsSelected(&selected));
4166 EXPECT_TRUE(selected);
4167
4168 // Option 4, CheckedState::kMixed, ISelectionItemProvider is not supported.
4169 ComPtr<ISelectionItemProvider> option4_provider;
4170 EXPECT_HRESULT_SUCCEEDED(
4171 GetIRawElementProviderSimpleFromChildIndex(3)->GetPatternProvider(
4172 UIA_SelectionItemPatternId, &option4_provider));
4173 ASSERT_EQ(nullptr, option4_provider.Get());
4174}
4175
4176TEST_F(AXPlatformNodeWinTest, ISelectionItemProviderMenuItemRadio) {
4177 AXNodeData root;
4178 root.id = 1;
4180
4181 // CheckedState::kNone
4182 AXNodeData option1;
4183 option1.id = 2;
4184 option1.AddIntAttribute(ax::mojom::IntAttribute::kCheckedState,
4185 static_cast<int>(ax::mojom::CheckedState::kNone));
4186 option1.role = ax::mojom::Role::kMenuItemRadio;
4187 root.child_ids.push_back(option1.id);
4188
4189 // CheckedState::kFalse
4190 AXNodeData option2;
4191 option2.id = 3;
4192 option2.AddIntAttribute(ax::mojom::IntAttribute::kCheckedState,
4193 static_cast<int>(ax::mojom::CheckedState::kFalse));
4194 option2.role = ax::mojom::Role::kMenuItemRadio;
4195 root.child_ids.push_back(option2.id);
4196
4197 // CheckedState::kTrue
4198 AXNodeData option3;
4199 option3.id = 4;
4200 option3.AddIntAttribute(ax::mojom::IntAttribute::kCheckedState,
4201 static_cast<int>(ax::mojom::CheckedState::kTrue));
4202 option3.role = ax::mojom::Role::kMenuItemRadio;
4203 root.child_ids.push_back(option3.id);
4204
4205 // CheckedState::kMixed
4206 AXNodeData option4;
4207 option4.id = 5;
4208 option4.AddIntAttribute(ax::mojom::IntAttribute::kCheckedState,
4209 static_cast<int>(ax::mojom::CheckedState::kMixed));
4210 option4.role = ax::mojom::Role::kMenuItemRadio;
4211 root.child_ids.push_back(option4.id);
4212
4213 Init(root, option1, option2, option3, option4);
4214
4215 BOOL selected;
4216
4217 // Option 1, CheckedState::kNone, ISelectionItemProvider is not supported.
4218 ComPtr<ISelectionItemProvider> option1_provider;
4219 EXPECT_HRESULT_SUCCEEDED(
4220 GetIRawElementProviderSimpleFromChildIndex(0)->GetPatternProvider(
4221 UIA_SelectionItemPatternId, &option1_provider));
4222 ASSERT_EQ(nullptr, option1_provider.Get());
4223
4224 // Option 2, CheckedState::kFalse.
4225 ComPtr<ISelectionItemProvider> option2_provider;
4226 EXPECT_HRESULT_SUCCEEDED(
4227 GetIRawElementProviderSimpleFromChildIndex(1)->GetPatternProvider(
4228 UIA_SelectionItemPatternId, &option2_provider));
4229 ASSERT_NE(nullptr, option2_provider.Get());
4230
4231 EXPECT_HRESULT_SUCCEEDED(option2_provider->get_IsSelected(&selected));
4232 EXPECT_FALSE(selected);
4233
4234 EXPECT_HRESULT_SUCCEEDED(option2_provider->Select());
4235 EXPECT_HRESULT_SUCCEEDED(option2_provider->get_IsSelected(&selected));
4236 EXPECT_TRUE(selected);
4237
4238 // Option 3, CheckedState::kTrue.
4239 ComPtr<ISelectionItemProvider> option3_provider;
4240 EXPECT_HRESULT_SUCCEEDED(
4241 GetIRawElementProviderSimpleFromChildIndex(2)->GetPatternProvider(
4242 UIA_SelectionItemPatternId, &option3_provider));
4243 ASSERT_NE(nullptr, option3_provider.Get());
4244
4245 EXPECT_HRESULT_SUCCEEDED(option3_provider->get_IsSelected(&selected));
4246 EXPECT_TRUE(selected);
4247
4248 EXPECT_HRESULT_SUCCEEDED(option3_provider->RemoveFromSelection());
4249 EXPECT_HRESULT_SUCCEEDED(option3_provider->get_IsSelected(&selected));
4250 EXPECT_FALSE(selected);
4251
4252 EXPECT_HRESULT_SUCCEEDED(option3_provider->AddToSelection());
4253 EXPECT_HRESULT_SUCCEEDED(option3_provider->get_IsSelected(&selected));
4254 EXPECT_TRUE(selected);
4255
4256 // Option 4, CheckedState::kMixed, ISelectionItemProvider is not supported.
4257 ComPtr<ISelectionItemProvider> option4_provider;
4258 EXPECT_HRESULT_SUCCEEDED(
4259 GetIRawElementProviderSimpleFromChildIndex(3)->GetPatternProvider(
4260 UIA_SelectionItemPatternId, &option4_provider));
4261 ASSERT_EQ(nullptr, option4_provider.Get());
4262}
4263
4264TEST_F(AXPlatformNodeWinTest, ISelectionItemProviderTable) {
4265 AXNodeData root;
4266 root.id = 1;
4268
4269 AXNodeData row1;
4270 row1.id = 2;
4271 row1.role = ax::mojom::Role::kRow;
4272 root.child_ids.push_back(row1.id);
4273
4274 AXNodeData cell1;
4275 cell1.id = 3;
4276 cell1.role = ax::mojom::Role::kCell;
4277 cell1.AddBoolAttribute(ax::mojom::BoolAttribute::kSelected, false);
4278 row1.child_ids.push_back(cell1.id);
4279
4280 Init(root, row1, cell1);
4281
4282 ComPtr<ISelectionItemProvider> selection_item_provider;
4283 EXPECT_HRESULT_SUCCEEDED(
4284 GetIRawElementProviderSimpleFromChildIndex(0)->GetPatternProvider(
4285 UIA_SelectionItemPatternId, &selection_item_provider));
4286 ASSERT_EQ(nullptr, selection_item_provider.Get());
4287}
4288
4289TEST_F(AXPlatformNodeWinTest, ISelectionItemProviderGrid) {
4290 AXNodeData root;
4291 root.id = 1;
4293
4294 AXNodeData row1;
4295 row1.id = 2;
4296 row1.role = ax::mojom::Role::kRow;
4297 root.child_ids.push_back(row1.id);
4298
4299 AXNodeData cell1;
4300 cell1.id = 3;
4301 cell1.role = ax::mojom::Role::kCell;
4302 cell1.AddBoolAttribute(ax::mojom::BoolAttribute::kSelected, false);
4303 row1.child_ids.push_back(cell1.id);
4304
4305 Init(root, row1, cell1);
4306
4307 const auto* row = GetRootAsAXNode()->children()[0];
4308 ComPtr<IRawElementProviderSimple> raw_element_provider_simple =
4309 QueryInterfaceFromNode<IRawElementProviderSimple>(row->children()[0]);
4310
4311 ComPtr<ISelectionItemProvider> selection_item_provider;
4312 EXPECT_HRESULT_SUCCEEDED(raw_element_provider_simple->GetPatternProvider(
4313 UIA_SelectionItemPatternId, &selection_item_provider));
4314 ASSERT_NE(nullptr, selection_item_provider.Get());
4315
4316 BOOL selected;
4317
4318 // Note: TestAXNodeWrapper::AccessibilityPerformAction will
4319 // flip kSelected for kCell when the kDoDefault action is fired.
4320
4321 // Initial State
4322 EXPECT_HRESULT_SUCCEEDED(selection_item_provider->get_IsSelected(&selected));
4323 EXPECT_FALSE(selected);
4324
4325 // AddToSelection should fire event when not selected
4326 EXPECT_HRESULT_SUCCEEDED(selection_item_provider->AddToSelection());
4327 EXPECT_HRESULT_SUCCEEDED(selection_item_provider->get_IsSelected(&selected));
4328 EXPECT_TRUE(selected);
4329
4330 // AddToSelection should not fire event when selected
4331 EXPECT_HRESULT_SUCCEEDED(selection_item_provider->AddToSelection());
4332 EXPECT_HRESULT_SUCCEEDED(selection_item_provider->get_IsSelected(&selected));
4333 EXPECT_TRUE(selected);
4334
4335 // RemoveFromSelection should fire event when selected
4336 EXPECT_HRESULT_SUCCEEDED(selection_item_provider->RemoveFromSelection());
4337 EXPECT_HRESULT_SUCCEEDED(selection_item_provider->get_IsSelected(&selected));
4338 EXPECT_FALSE(selected);
4339
4340 // RemoveFromSelection should not fire event when not selected
4341 EXPECT_HRESULT_SUCCEEDED(selection_item_provider->RemoveFromSelection());
4342 EXPECT_HRESULT_SUCCEEDED(selection_item_provider->get_IsSelected(&selected));
4343 EXPECT_FALSE(selected);
4344
4345 // Select should fire event when not selected
4346 EXPECT_HRESULT_SUCCEEDED(selection_item_provider->Select());
4347 EXPECT_HRESULT_SUCCEEDED(selection_item_provider->get_IsSelected(&selected));
4348 EXPECT_TRUE(selected);
4349
4350 // Select should not fire event when selected
4351 EXPECT_HRESULT_SUCCEEDED(selection_item_provider->Select());
4352 EXPECT_HRESULT_SUCCEEDED(selection_item_provider->get_IsSelected(&selected));
4353 EXPECT_TRUE(selected);
4354}
4355
4356TEST_F(AXPlatformNodeWinTest, ISelectionItemProviderGetSelectionContainer) {
4357 AXNodeData root;
4358 root.id = 1;
4360
4361 AXNodeData row1;
4362 row1.id = 2;
4363 row1.role = ax::mojom::Role::kRow;
4364 root.child_ids.push_back(row1.id);
4365
4366 AXNodeData cell1;
4367 cell1.id = 3;
4368 cell1.role = ax::mojom::Role::kCell;
4369 cell1.AddBoolAttribute(ax::mojom::BoolAttribute::kSelected, false);
4370 row1.child_ids.push_back(cell1.id);
4371
4372 Init(root, row1, cell1);
4373
4374 ComPtr<IRawElementProviderSimple> container_provider =
4375 GetRootIRawElementProviderSimple();
4376
4377 const auto* row = GetRootAsAXNode()->children()[0];
4378 ComPtr<ISelectionItemProvider> item_provider =
4379 QueryInterfaceFromNode<ISelectionItemProvider>(row->children()[0]);
4380
4381 ComPtr<IRawElementProviderSimple> container;
4382 EXPECT_HRESULT_SUCCEEDED(item_provider->get_SelectionContainer(&container));
4383 EXPECT_NE(nullptr, container);
4384 EXPECT_EQ(container, container_provider);
4385}
4386
4387TEST_F(AXPlatformNodeWinTest, ISelectionItemProviderSelectFollowFocus) {
4388 AXNodeData root;
4389 root.id = 1;
4391
4392 AXNodeData tab1;
4393 tab1.id = 2;
4394 tab1.role = ax::mojom::Role::kTab;
4395 tab1.AddBoolAttribute(ax::mojom::BoolAttribute::kSelected, false);
4396 tab1.SetDefaultActionVerb(ax::mojom::DefaultActionVerb::kClick);
4397 root.child_ids.push_back(tab1.id);
4398
4399 Init(root, tab1);
4400
4401 auto* tab1_node = GetRootAsAXNode()->children()[0];
4402 ComPtr<IRawElementProviderSimple> tab1_raw_element_provider_simple =
4403 QueryInterfaceFromNode<IRawElementProviderSimple>(tab1_node);
4404 ASSERT_NE(nullptr, tab1_raw_element_provider_simple.Get());
4405
4406 ComPtr<IRawElementProviderFragment> tab1_raw_element_provider_fragment =
4407 IRawElementProviderFragmentFromNode(tab1_node);
4408 ASSERT_NE(nullptr, tab1_raw_element_provider_fragment.Get());
4409
4410 ComPtr<ISelectionItemProvider> tab1_selection_item_provider;
4411 EXPECT_HRESULT_SUCCEEDED(tab1_raw_element_provider_simple->GetPatternProvider(
4412 UIA_SelectionItemPatternId, &tab1_selection_item_provider));
4413 ASSERT_NE(nullptr, tab1_selection_item_provider.Get());
4414
4415 BOOL is_selected;
4416 // Before setting focus to "tab1", validate that "tab1" has selected=false.
4417 tab1_selection_item_provider->get_IsSelected(&is_selected);
4418 EXPECT_FALSE(is_selected);
4419
4420 // Setting focus on "tab1" will result in selected=true.
4421 tab1_raw_element_provider_fragment->SetFocus();
4422 tab1_selection_item_provider->get_IsSelected(&is_selected);
4423 EXPECT_TRUE(is_selected);
4424
4425 // Verify that we can still trigger action::kDoDefault through Select().
4426 EXPECT_HRESULT_SUCCEEDED(tab1_selection_item_provider->Select());
4427 tab1_selection_item_provider->get_IsSelected(&is_selected);
4428 EXPECT_TRUE(is_selected);
4429 EXPECT_EQ(tab1_node, TestAXNodeWrapper::GetNodeFromLastDefaultAction());
4430 // Verify that after Select(), "tab1" is still selected.
4431 tab1_selection_item_provider->get_IsSelected(&is_selected);
4432 EXPECT_TRUE(is_selected);
4433
4434 // Since last Select() performed |action::kDoDefault|, which set
4435 // |kSelectedFromFocus| to false. Calling Select() again will not perform
4436 // |action::kDoDefault| again.
4437 TestAXNodeWrapper::SetNodeFromLastDefaultAction(nullptr);
4438 EXPECT_HRESULT_SUCCEEDED(tab1_selection_item_provider->Select());
4439 tab1_selection_item_provider->get_IsSelected(&is_selected);
4440 EXPECT_TRUE(is_selected);
4441 // Verify that after Select(),|action::kDoDefault| was not triggered on
4442 // "tab1".
4443 EXPECT_EQ(nullptr, TestAXNodeWrapper::GetNodeFromLastDefaultAction());
4444}
4445
4446TEST_F(AXPlatformNodeWinTest, IValueProvider_GetValue) {
4447 AXNodeData root;
4448 root.id = 1;
4450
4451 AXNodeData child1;
4452 child1.id = 2;
4454 child1.AddFloatAttribute(ax::mojom::FloatAttribute::kValueForRange, 3.0f);
4455 root.child_ids.push_back(child1.id);
4456
4457 AXNodeData child2;
4458 child2.id = 3;
4459 child2.role = ax::mojom::Role::kTextField;
4460 child2.AddState(ax::mojom::State::kEditable);
4461 child2.AddStringAttribute(ax::mojom::StringAttribute::kValue, "test");
4462 root.child_ids.push_back(child2.id);
4463
4464 AXNodeData child3;
4465 child3.id = 4;
4466 child3.role = ax::mojom::Role::kTextField;
4467 child3.AddStringAttribute(ax::mojom::StringAttribute::kValue, "test");
4468 child3.AddIntAttribute(ax::mojom::IntAttribute::kRestriction,
4469 static_cast<int>(ax::mojom::Restriction::kReadOnly));
4470 root.child_ids.push_back(child3.id);
4471
4472 Init(root, child1, child2, child3);
4473
4474 ScopedBstr bstr_value;
4475
4476 EXPECT_HRESULT_SUCCEEDED(
4477 QueryInterfaceFromNode<IValueProvider>(GetRootAsAXNode()->children()[0])
4478 ->get_Value(bstr_value.Receive()));
4479 EXPECT_STREQ(L"3", bstr_value.Get());
4480 bstr_value.Reset();
4481
4482 EXPECT_HRESULT_SUCCEEDED(
4483 QueryInterfaceFromNode<IValueProvider>(GetRootAsAXNode()->children()[1])
4484 ->get_Value(bstr_value.Receive()));
4485 EXPECT_STREQ(L"test", bstr_value.Get());
4486 bstr_value.Reset();
4487
4488 EXPECT_HRESULT_SUCCEEDED(
4489 QueryInterfaceFromNode<IValueProvider>(GetRootAsAXNode()->children()[2])
4490 ->get_Value(bstr_value.Receive()));
4491 EXPECT_STREQ(L"test", bstr_value.Get());
4492 bstr_value.Reset();
4493}
4494
4495TEST_F(AXPlatformNodeWinTest, IValueProvider_SetValue) {
4496 AXNodeData root;
4497 root.id = 1;
4499
4500 AXNodeData child1;
4501 child1.id = 2;
4503 child1.AddFloatAttribute(ax::mojom::FloatAttribute::kValueForRange, 3.0f);
4504 root.child_ids.push_back(child1.id);
4505
4506 AXNodeData child2;
4507 child2.id = 3;
4508 child2.role = ax::mojom::Role::kTextField;
4509 child2.AddStringAttribute(ax::mojom::StringAttribute::kValue, "test");
4510 root.child_ids.push_back(child2.id);
4511
4512 AXNodeData child3;
4513 child3.id = 4;
4514 child3.role = ax::mojom::Role::kTextField;
4515 child3.AddStringAttribute(ax::mojom::StringAttribute::kValue, "test");
4516 child3.AddIntAttribute(ax::mojom::IntAttribute::kRestriction,
4517 static_cast<int>(ax::mojom::Restriction::kReadOnly));
4518 root.child_ids.push_back(child3.id);
4519
4520 Init(root, child1, child2, child3);
4521
4522 ComPtr<IValueProvider> root_provider =
4523 QueryInterfaceFromNode<IValueProvider>(GetRootAsAXNode());
4524 ComPtr<IValueProvider> provider1 =
4525 QueryInterfaceFromNode<IValueProvider>(GetRootAsAXNode()->children()[0]);
4526 ComPtr<IValueProvider> provider2 =
4527 QueryInterfaceFromNode<IValueProvider>(GetRootAsAXNode()->children()[1]);
4528 ComPtr<IValueProvider> provider3 =
4529 QueryInterfaceFromNode<IValueProvider>(GetRootAsAXNode()->children()[2]);
4530
4531 ScopedBstr bstr_value;
4532
4533 // Note: TestAXNodeWrapper::AccessibilityPerformAction will
4534 // modify the value when the kSetValue action is fired.
4535
4536 EXPECT_UIA_ELEMENTNOTENABLED(provider1->SetValue(L"2"));
4537 EXPECT_HRESULT_SUCCEEDED(provider1->get_Value(bstr_value.Receive()));
4538 EXPECT_STREQ(L"3", bstr_value.Get());
4539 bstr_value.Reset();
4540
4541 EXPECT_HRESULT_SUCCEEDED(provider2->SetValue(L"changed"));
4542 EXPECT_HRESULT_SUCCEEDED(provider2->get_Value(bstr_value.Receive()));
4543 EXPECT_STREQ(L"changed", bstr_value.Get());
4544 bstr_value.Reset();
4545
4546 EXPECT_UIA_ELEMENTNOTENABLED(provider3->SetValue(L"changed"));
4547 EXPECT_HRESULT_SUCCEEDED(provider3->get_Value(bstr_value.Receive()));
4548 EXPECT_STREQ(L"test", bstr_value.Get());
4549 bstr_value.Reset();
4550}
4551
4552TEST_F(AXPlatformNodeWinTest, IValueProvider_IsReadOnly) {
4553 AXNodeData root;
4554 root.id = 1;
4556
4557 AXNodeData child1;
4558 child1.id = 2;
4559 child1.role = ax::mojom::Role::kTextField;
4560 child1.AddState(ax::mojom::State::kEditable);
4561 root.child_ids.push_back(child1.id);
4562
4563 AXNodeData child2;
4564 child2.id = 3;
4565 child2.role = ax::mojom::Role::kTextField;
4566 child2.AddIntAttribute(ax::mojom::IntAttribute::kRestriction,
4567 static_cast<int>(ax::mojom::Restriction::kReadOnly));
4568 root.child_ids.push_back(child2.id);
4569
4570 AXNodeData child3;
4571 child3.id = 4;
4572 child3.role = ax::mojom::Role::kTextField;
4573 child3.AddIntAttribute(ax::mojom::IntAttribute::kRestriction,
4574 static_cast<int>(ax::mojom::Restriction::kDisabled));
4575 root.child_ids.push_back(child3.id);
4576
4577 AXNodeData child4;
4578 child4.id = 5;
4579 child4.role = ax::mojom::Role::kLink;
4580 root.child_ids.push_back(child4.id);
4581
4582 Init(root, child1, child2, child3, child4);
4583
4584 BOOL is_readonly = false;
4585
4586 EXPECT_HRESULT_SUCCEEDED(
4587 QueryInterfaceFromNode<IValueProvider>(GetRootAsAXNode()->children()[0])
4588 ->get_IsReadOnly(&is_readonly));
4589 EXPECT_FALSE(is_readonly);
4590
4591 EXPECT_HRESULT_SUCCEEDED(
4592 QueryInterfaceFromNode<IValueProvider>(GetRootAsAXNode()->children()[1])
4593 ->get_IsReadOnly(&is_readonly));
4594 EXPECT_TRUE(is_readonly);
4595
4596 EXPECT_HRESULT_SUCCEEDED(
4597 QueryInterfaceFromNode<IValueProvider>(GetRootAsAXNode()->children()[2])
4598 ->get_IsReadOnly(&is_readonly));
4599 EXPECT_TRUE(is_readonly);
4600
4601 EXPECT_HRESULT_SUCCEEDED(
4602 QueryInterfaceFromNode<IValueProvider>(GetRootAsAXNode()->children()[3])
4603 ->get_IsReadOnly(&is_readonly));
4604 EXPECT_TRUE(is_readonly);
4605}
4606
4607TEST_F(AXPlatformNodeWinTest, IScrollProviderSetScrollPercent) {
4608 AXNodeData root;
4609 root.id = 1;
4611 root.AddIntAttribute(ax::mojom::IntAttribute::kScrollX, 0);
4612 root.AddIntAttribute(ax::mojom::IntAttribute::kScrollXMin, 0);
4613 root.AddIntAttribute(ax::mojom::IntAttribute::kScrollXMax, 100);
4614
4615 root.AddIntAttribute(ax::mojom::IntAttribute::kScrollY, 60);
4616 root.AddIntAttribute(ax::mojom::IntAttribute::kScrollYMin, 10);
4617 root.AddIntAttribute(ax::mojom::IntAttribute::kScrollYMax, 60);
4618
4619 Init(root);
4620
4621 ComPtr<IScrollProvider> scroll_provider =
4622 QueryInterfaceFromNode<IScrollProvider>(GetRootAsAXNode());
4623 double x_scroll_percent;
4624 double y_scroll_percent;
4625
4626 // Set x scroll percent: 0%, y scroll percent: 0%.
4627 // Expected x scroll percent: 0%, y scroll percent: 0%.
4628 EXPECT_HRESULT_SUCCEEDED(scroll_provider->SetScrollPercent(0, 0));
4629 EXPECT_HRESULT_SUCCEEDED(
4630 scroll_provider->get_HorizontalScrollPercent(&x_scroll_percent));
4631 EXPECT_EQ(x_scroll_percent, 0);
4632 EXPECT_HRESULT_SUCCEEDED(
4633 scroll_provider->get_VerticalScrollPercent(&y_scroll_percent));
4634 EXPECT_EQ(y_scroll_percent, 0);
4635
4636 // Set x scroll percent: 100%, y scroll percent: 100%.
4637 // Expected x scroll percent: 100%, y scroll percent: 100%.
4638 EXPECT_HRESULT_SUCCEEDED(scroll_provider->SetScrollPercent(100, 100));
4639 EXPECT_HRESULT_SUCCEEDED(
4640 scroll_provider->get_HorizontalScrollPercent(&x_scroll_percent));
4641 EXPECT_EQ(x_scroll_percent, 100);
4642 EXPECT_HRESULT_SUCCEEDED(
4643 scroll_provider->get_VerticalScrollPercent(&y_scroll_percent));
4644 EXPECT_EQ(y_scroll_percent, 100);
4645
4646 // Set x scroll percent: 500%, y scroll percent: 600%.
4647 // Expected x scroll percent: 100%, y scroll percent: 100%.
4648 EXPECT_HRESULT_SUCCEEDED(scroll_provider->SetScrollPercent(500, 600));
4649 EXPECT_HRESULT_SUCCEEDED(
4650 scroll_provider->get_HorizontalScrollPercent(&x_scroll_percent));
4651 EXPECT_EQ(x_scroll_percent, 100);
4652 EXPECT_HRESULT_SUCCEEDED(
4653 scroll_provider->get_VerticalScrollPercent(&y_scroll_percent));
4654 EXPECT_EQ(y_scroll_percent, 100);
4655
4656 // Set x scroll percent: -100%, y scroll percent: -200%.
4657 // Expected x scroll percent: 0%, y scroll percent: 0%.
4658 EXPECT_HRESULT_SUCCEEDED(scroll_provider->SetScrollPercent(-100, -200));
4659 EXPECT_HRESULT_SUCCEEDED(
4660 scroll_provider->get_HorizontalScrollPercent(&x_scroll_percent));
4661 EXPECT_EQ(x_scroll_percent, 0);
4662 EXPECT_HRESULT_SUCCEEDED(
4663 scroll_provider->get_VerticalScrollPercent(&y_scroll_percent));
4664 EXPECT_EQ(y_scroll_percent, 0);
4665
4666 // Set x scroll percent: 12%, y scroll percent: 34%.
4667 // Expected x scroll percent: 12%, y scroll percent: 34%.
4668 EXPECT_HRESULT_SUCCEEDED(scroll_provider->SetScrollPercent(12, 34));
4669 EXPECT_HRESULT_SUCCEEDED(
4670 scroll_provider->get_HorizontalScrollPercent(&x_scroll_percent));
4671 EXPECT_EQ(x_scroll_percent, 12);
4672 EXPECT_HRESULT_SUCCEEDED(
4673 scroll_provider->get_VerticalScrollPercent(&y_scroll_percent));
4674 EXPECT_EQ(y_scroll_percent, 34);
4675}
4676
4677TEST_F(AXPlatformNodeWinTest, MojoEventToUIAPropertyTest) {
4678 AXNodeData root;
4679 root.id = 1;
4682 static_cast<int>(ax::mojom::CheckedState::kMixed));
4683
4684 Init(root);
4685
4686 ComPtr<AXPlatformNodeWin> platform_node =
4687 QueryInterfaceFromNode<AXPlatformNodeWin>(GetRootAsAXNode());
4688 EXPECT_EQ(
4689 platform_node->MojoEventToUIAProperty(ax::mojom::Event::kValueChanged),
4690 UIA_ToggleToggleStatePropertyId);
4691}
4692
4693} // namespace ui
const char * options
Vec2Value v2
#define EXPECT_UIA_DOUBLE_ARRAY_EQ(node, array_property_id, expected_property_values)
#define EXPECT_UIA_PROPERTY_ELEMENT_ARRAY_BSTR_EQ(node, array_property_id, element_test_property_id, expected_property_values)
#define EXPECT_UIA_EMPTY(node, property_id)
#define EXPECT_UIA_INT_EQ(node, property_id, expected)
#define EXPECT_UIA_VALUE_EQ(node, property_id, expectedVariant)
#define EXPECT_UIA_ELEMENTNOTAVAILABLE(expr)
#define EXPECT_UIA_ELEMENT_ARRAY_BSTR_EQ(array, element_test_property_id, expected_property_values)
#define EXPECT_UIA_ELEMENTNOTENABLED(expr)
#define EXPECT_UIA_BOOL_EQ(node, property_id, expected)
#define EXPECT_UIA_PROPERTY_UNORDERED_ELEMENT_ARRAY_BSTR_EQ( node, array_property_id, element_test_property_id, expected_property_values)
#define EXPECT_UIA_BSTR_EQ(node, property_id, expected)
void Reset(BSTR bstr=nullptr)
static const VARIANT kEmptyVariant
const VARIANT * ptr() const
VARIANT * AsInput() const
void Reset(const VARIANT &var=kEmptyVariant)
static AXTreeID CreateNewAXTreeID()
Definition ax_tree_id.cc:47
AtkStateType state
glong glong end
TEST_F(FlGnomeSettingsTest, ClockFormat)
uint8_t value
GAsyncResult * result
const char * name
Definition fuchsia.cc:50
void Init()
return FALSE
link(from_root, to_root)
Definition dart_pkg.py:44
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
Definition switches.h:259
UnimplementedNativeViewAccessible * NativeViewAccessible
AXTreeUpdateBase< AXNodeData, AXTreeData > AXTreeUpdate
#define T
int32_t height
int32_t width
void SetRestriction(ax::mojom::Restriction restriction)
void AddState(ax::mojom::State state)
void SetHasPopup(ax::mojom::HasPopup has_popup)
ax::mojom::Role role
void SetCheckedState(ax::mojom::CheckedState checked_state)
#define EXPECT_TRUE(handle)
Definition unit_test.h:685
int BOOL
#define SUCCEEDED(hr)
long LONG
DWORD ULONG

◆ ASSERT_UIA_ELEMENTNOTENABLED

#define ASSERT_UIA_ELEMENTNOTENABLED (   expr)     ASSERT_EQ(static_cast<HRESULT>(UIA_E_ELEMENTNOTENABLED), (expr))

Definition at line 57 of file ax_platform_node_win_unittest.cc.

◆ ASSERT_UIA_INVALIDOPERATION

#define ASSERT_UIA_INVALIDOPERATION (   expr)     ASSERT_EQ(static_cast<HRESULT>(UIA_E_INVALIDOPERATION), (expr))

Definition at line 55 of file ax_platform_node_win_unittest.cc.

◆ ASSERT_UIA_NOTSUPPORTED

#define ASSERT_UIA_NOTSUPPORTED (   expr)     ASSERT_EQ(static_cast<HRESULT>(UIA_E_NOTSUPPORTED), (expr))

Definition at line 59 of file ax_platform_node_win_unittest.cc.

◆ EXPECT_UIA_BOOL_EQ

#define EXPECT_UIA_BOOL_EQ (   node,
  property_id,
  expected 
)
Value:
{ \
ScopedVariant expectedVariant(expected); \
ASSERT_EQ(VT_BOOL, expectedVariant.type()); \
ScopedVariant actual; \
ASSERT_HRESULT_SUCCEEDED( \
node->GetPropertyValue(property_id, actual.Receive())); \
EXPECT_EQ(expectedVariant.ptr()->boolVal, actual.ptr()->boolVal); \
}

Definition at line 97 of file ax_platform_node_win_unittest.cc.

98 { \
99 ScopedVariant expectedVariant(expected); \
100 ASSERT_EQ(VT_BOOL, expectedVariant.type()); \
101 ScopedVariant actual; \
102 ASSERT_HRESULT_SUCCEEDED( \
103 node->GetPropertyValue(property_id, actual.Receive())); \
104 EXPECT_EQ(expectedVariant.ptr()->boolVal, actual.ptr()->boolVal); \
105 }

◆ EXPECT_UIA_BSTR_EQ

#define EXPECT_UIA_BSTR_EQ (   node,
  property_id,
  expected 
)
Value:
{ \
ScopedVariant expectedVariant(expected); \
ASSERT_EQ(VT_BSTR, expectedVariant.type()); \
ASSERT_NE(nullptr, expectedVariant.ptr()->bstrVal); \
ScopedVariant actual; \
ASSERT_HRESULT_SUCCEEDED( \
node->GetPropertyValue(property_id, actual.Receive())); \
ASSERT_EQ(VT_BSTR, actual.type()); \
ASSERT_NE(nullptr, actual.ptr()->bstrVal); \
EXPECT_STREQ(expectedVariant.ptr()->bstrVal, actual.ptr()->bstrVal); \
}

Definition at line 84 of file ax_platform_node_win_unittest.cc.

85 { \
86 ScopedVariant expectedVariant(expected); \
87 ASSERT_EQ(VT_BSTR, expectedVariant.type()); \
88 ASSERT_NE(nullptr, expectedVariant.ptr()->bstrVal); \
89 ScopedVariant actual; \
90 ASSERT_HRESULT_SUCCEEDED( \
91 node->GetPropertyValue(property_id, actual.Receive())); \
92 ASSERT_EQ(VT_BSTR, actual.type()); \
93 ASSERT_NE(nullptr, actual.ptr()->bstrVal); \
94 EXPECT_STREQ(expectedVariant.ptr()->bstrVal, actual.ptr()->bstrVal); \
95 }

◆ EXPECT_UIA_DOUBLE_ARRAY_EQ

#define EXPECT_UIA_DOUBLE_ARRAY_EQ (   node,
  array_property_id,
  expected_property_values 
)
Value:
{ \
ScopedVariant array; \
ASSERT_HRESULT_SUCCEEDED( \
node->GetPropertyValue(array_property_id, array.Receive())); \
ASSERT_EQ(VT_ARRAY | VT_R8, array.type()); \
ASSERT_EQ(1u, SafeArrayGetDim(array.ptr()->parray)); \
LONG array_lower_bound; \
ASSERT_HRESULT_SUCCEEDED( \
SafeArrayGetLBound(array.ptr()->parray, 1, &array_lower_bound)); \
LONG array_upper_bound; \
ASSERT_HRESULT_SUCCEEDED( \
SafeArrayGetUBound(array.ptr()->parray, 1, &array_upper_bound)); \
double* array_data; \
ASSERT_HRESULT_SUCCEEDED(::SafeArrayAccessData( \
array.ptr()->parray, reinterpret_cast<void**>(&array_data))); \
size_t count = array_upper_bound - array_lower_bound + 1; \
ASSERT_EQ(expected_property_values.size(), count); \
for (size_t i = 0; i < count; ++i) { \
EXPECT_EQ(array_data[i], expected_property_values[i]); \
} \
ASSERT_HRESULT_SUCCEEDED(::SafeArrayUnaccessData(array.ptr()->parray)); \
}
int count

Definition at line 107 of file ax_platform_node_win_unittest.cc.

109 { \
110 ScopedVariant array; \
111 ASSERT_HRESULT_SUCCEEDED( \
112 node->GetPropertyValue(array_property_id, array.Receive())); \
113 ASSERT_EQ(VT_ARRAY | VT_R8, array.type()); \
114 ASSERT_EQ(1u, SafeArrayGetDim(array.ptr()->parray)); \
115 LONG array_lower_bound; \
116 ASSERT_HRESULT_SUCCEEDED( \
117 SafeArrayGetLBound(array.ptr()->parray, 1, &array_lower_bound)); \
118 LONG array_upper_bound; \
119 ASSERT_HRESULT_SUCCEEDED( \
120 SafeArrayGetUBound(array.ptr()->parray, 1, &array_upper_bound)); \
121 double* array_data; \
122 ASSERT_HRESULT_SUCCEEDED(::SafeArrayAccessData( \
123 array.ptr()->parray, reinterpret_cast<void**>(&array_data))); \
124 size_t count = array_upper_bound - array_lower_bound + 1; \
125 ASSERT_EQ(expected_property_values.size(), count); \
126 for (size_t i = 0; i < count; ++i) { \
127 EXPECT_EQ(array_data[i], expected_property_values[i]); \
128 } \
129 ASSERT_HRESULT_SUCCEEDED(::SafeArrayUnaccessData(array.ptr()->parray)); \
130 }

◆ EXPECT_UIA_ELEMENT_ARRAY_BSTR_EQ

#define EXPECT_UIA_ELEMENT_ARRAY_BSTR_EQ (   array,
  element_test_property_id,
  expected_property_values 
)
Value:
{ \
ASSERT_EQ(1u, SafeArrayGetDim(array)); \
LONG array_lower_bound; \
ASSERT_HRESULT_SUCCEEDED( \
SafeArrayGetLBound(array, 1, &array_lower_bound)); \
LONG array_upper_bound; \
ASSERT_HRESULT_SUCCEEDED( \
SafeArrayGetUBound(array, 1, &array_upper_bound)); \
IUnknown** array_data; \
ASSERT_HRESULT_SUCCEEDED( \
::SafeArrayAccessData(array, reinterpret_cast<void**>(&array_data))); \
size_t count = array_upper_bound - array_lower_bound + 1; \
ASSERT_EQ(expected_property_values.size(), count); \
for (size_t i = 0; i < count; ++i) { \
ComPtr<IRawElementProviderSimple> element; \
ASSERT_HRESULT_SUCCEEDED( \
array_data[i]->QueryInterface(IID_PPV_ARGS(&element))); \
EXPECT_UIA_BSTR_EQ(element, element_test_property_id, \
expected_property_values[i].c_str()); \
} \
ASSERT_HRESULT_SUCCEEDED(::SafeArrayUnaccessData(array)); \
}

Definition at line 142 of file ax_platform_node_win_unittest.cc.

144 { \
145 ASSERT_EQ(1u, SafeArrayGetDim(array)); \
146 LONG array_lower_bound; \
147 ASSERT_HRESULT_SUCCEEDED( \
148 SafeArrayGetLBound(array, 1, &array_lower_bound)); \
149 LONG array_upper_bound; \
150 ASSERT_HRESULT_SUCCEEDED( \
151 SafeArrayGetUBound(array, 1, &array_upper_bound)); \
152 IUnknown** array_data; \
153 ASSERT_HRESULT_SUCCEEDED( \
154 ::SafeArrayAccessData(array, reinterpret_cast<void**>(&array_data))); \
155 size_t count = array_upper_bound - array_lower_bound + 1; \
156 ASSERT_EQ(expected_property_values.size(), count); \
157 for (size_t i = 0; i < count; ++i) { \
158 ComPtr<IRawElementProviderSimple> element; \
159 ASSERT_HRESULT_SUCCEEDED( \
160 array_data[i]->QueryInterface(IID_PPV_ARGS(&element))); \
161 EXPECT_UIA_BSTR_EQ(element, element_test_property_id, \
162 expected_property_values[i].c_str()); \
163 } \
164 ASSERT_HRESULT_SUCCEEDED(::SafeArrayUnaccessData(array)); \
165 }

◆ EXPECT_UIA_ELEMENTNOTAVAILABLE

#define EXPECT_UIA_ELEMENTNOTAVAILABLE (   expr)     EXPECT_EQ(static_cast<HRESULT>(UIA_E_ELEMENTNOTAVAILABLE), (expr))

Definition at line 44 of file ax_platform_node_win_unittest.cc.

◆ EXPECT_UIA_ELEMENTNOTENABLED

#define EXPECT_UIA_ELEMENTNOTENABLED (   expr)     EXPECT_EQ(static_cast<HRESULT>(UIA_E_ELEMENTNOTENABLED), (expr))

Definition at line 48 of file ax_platform_node_win_unittest.cc.

◆ EXPECT_UIA_EMPTY

#define EXPECT_UIA_EMPTY (   node,
  property_id 
)
Value:
{ \
ScopedVariant actual; \
ASSERT_HRESULT_SUCCEEDED( \
node->GetPropertyValue(property_id, actual.Receive())); \
EXPECT_EQ(VT_EMPTY, actual.type()); \
}

Definition at line 68 of file ax_platform_node_win_unittest.cc.

69 { \
70 ScopedVariant actual; \
71 ASSERT_HRESULT_SUCCEEDED( \
72 node->GetPropertyValue(property_id, actual.Receive())); \
73 EXPECT_EQ(VT_EMPTY, actual.type()); \
74 }

◆ EXPECT_UIA_INT_EQ

#define EXPECT_UIA_INT_EQ (   node,
  property_id,
  expected 
)
Value:
{ \
ScopedVariant expectedVariant(expected); \
ASSERT_EQ(VT_I4, expectedVariant.type()); \
ScopedVariant actual; \
ASSERT_HRESULT_SUCCEEDED( \
node->GetPropertyValue(property_id, actual.Receive())); \
EXPECT_EQ(expectedVariant.ptr()->intVal, actual.ptr()->intVal); \
}

Definition at line 132 of file ax_platform_node_win_unittest.cc.

133 { \
134 ScopedVariant expectedVariant(expected); \
135 ASSERT_EQ(VT_I4, expectedVariant.type()); \
136 ScopedVariant actual; \
137 ASSERT_HRESULT_SUCCEEDED( \
138 node->GetPropertyValue(property_id, actual.Receive())); \
139 EXPECT_EQ(expectedVariant.ptr()->intVal, actual.ptr()->intVal); \
140 }

◆ EXPECT_UIA_INVALIDOPERATION

#define EXPECT_UIA_INVALIDOPERATION (   expr)     EXPECT_EQ(static_cast<HRESULT>(UIA_E_INVALIDOPERATION), (expr))

Definition at line 46 of file ax_platform_node_win_unittest.cc.

◆ EXPECT_UIA_NOTSUPPORTED

#define EXPECT_UIA_NOTSUPPORTED (   expr)     EXPECT_EQ(static_cast<HRESULT>(UIA_E_NOTSUPPORTED), (expr))

Definition at line 50 of file ax_platform_node_win_unittest.cc.

◆ EXPECT_UIA_PROPERTY_ELEMENT_ARRAY_BSTR_EQ

#define EXPECT_UIA_PROPERTY_ELEMENT_ARRAY_BSTR_EQ (   node,
  array_property_id,
  element_test_property_id,
  expected_property_values 
)
Value:
{ \
ScopedVariant array; \
ASSERT_HRESULT_SUCCEEDED( \
node->GetPropertyValue(array_property_id, array.Receive())); \
ASSERT_EQ(VT_ARRAY | VT_UNKNOWN, array.type()); \
EXPECT_UIA_ELEMENT_ARRAY_BSTR_EQ(array.ptr()->parray, \
element_test_property_id, \
expected_property_values); \
}

Definition at line 167 of file ax_platform_node_win_unittest.cc.

170 { \
171 ScopedVariant array; \
172 ASSERT_HRESULT_SUCCEEDED( \
173 node->GetPropertyValue(array_property_id, array.Receive())); \
174 ASSERT_EQ(VT_ARRAY | VT_UNKNOWN, array.type()); \
175 EXPECT_UIA_ELEMENT_ARRAY_BSTR_EQ(array.ptr()->parray, \
176 element_test_property_id, \
177 expected_property_values); \
178 }

◆ EXPECT_UIA_PROPERTY_UNORDERED_ELEMENT_ARRAY_BSTR_EQ

#define EXPECT_UIA_PROPERTY_UNORDERED_ELEMENT_ARRAY_BSTR_EQ (   node,
  array_property_id,
  element_test_property_id,
  expected_property_values 
)

Definition at line 180 of file ax_platform_node_win_unittest.cc.

183 { \
184 ScopedVariant array; \
185 ASSERT_HRESULT_SUCCEEDED( \
186 node->GetPropertyValue(array_property_id, array.Receive())); \
187 ASSERT_EQ(VT_ARRAY | VT_UNKNOWN, array.type()); \
188 ASSERT_EQ(1u, SafeArrayGetDim(array.ptr()->parray)); \
189 LONG array_lower_bound; \
190 ASSERT_HRESULT_SUCCEEDED( \
191 SafeArrayGetLBound(array.ptr()->parray, 1, &array_lower_bound)); \
192 LONG array_upper_bound; \
193 ASSERT_HRESULT_SUCCEEDED( \
194 SafeArrayGetUBound(array.ptr()->parray, 1, &array_upper_bound)); \
195 IUnknown** array_data; \
196 ASSERT_HRESULT_SUCCEEDED(::SafeArrayAccessData( \
197 array.ptr()->parray, reinterpret_cast<void**>(&array_data))); \
198 size_t count = array_upper_bound - array_lower_bound + 1; \
199 ASSERT_EQ(expected_property_values.size(), count); \
200 std::vector<std::wstring> property_values; \
201 for (size_t i = 0; i < count; ++i) { \
202 ComPtr<IRawElementProviderSimple> element; \
203 ASSERT_HRESULT_SUCCEEDED( \
204 array_data[i]->QueryInterface(IID_PPV_ARGS(&element))); \
205 ScopedVariant actual; \
206 ASSERT_HRESULT_SUCCEEDED(element->GetPropertyValue( \
207 element_test_property_id, actual.Receive())); \
208 ASSERT_EQ(VT_BSTR, actual.type()); \
209 ASSERT_NE(nullptr, actual.ptr()->bstrVal); \
210 property_values.push_back(std::wstring( \
211 V_BSTR(actual.ptr()), SysStringLen(V_BSTR(actual.ptr())))); \
212 } \
213 ASSERT_HRESULT_SUCCEEDED(::SafeArrayUnaccessData(array.ptr()->parray)); \
214 EXPECT_THAT(property_values, \
215 testing::UnorderedElementsAreArray(expected_property_values)); \
216 }

◆ EXPECT_UIA_VALUE_EQ

#define EXPECT_UIA_VALUE_EQ (   node,
  property_id,
  expectedVariant 
)
Value:
{ \
ScopedVariant actual; \
ASSERT_HRESULT_SUCCEEDED( \
node->GetPropertyValue(property_id, actual.Receive())); \
EXPECT_EQ(0, actual.Compare(expectedVariant)); \
}
int Compare(const VARIANT &other, bool ignore_case=false) const

Definition at line 76 of file ax_platform_node_win_unittest.cc.

77 { \
78 ScopedVariant actual; \
79 ASSERT_HRESULT_SUCCEEDED( \
80 node->GetPropertyValue(property_id, actual.Receive())); \
81 EXPECT_EQ(0, actual.Compare(expectedVariant)); \
82 }