Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
ax_platform_node_win_unittest.cc
Go to the documentation of this file.
1//
2// Copyright 2015 The Chromium Authors. All rights reserved.
3// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5
7
8#include <oleacc.h>
9#include <wrl/client.h>
10
11#include <memory>
12
15#include "base/auto_reset.h"
16#include "gmock/gmock.h"
17#include "gtest/gtest.h"
25
28using Microsoft::WRL::ComPtr;
29
30namespace ui {
31
34
35namespace {
36
37// Most IAccessible functions require a VARIANT set to CHILDID_SELF as
38// the first argument.
39ScopedVariant SELF(CHILDID_SELF);
40
41} // namespace
42
43// Helper macros for UIAutomation HRESULT expectations
44#define EXPECT_UIA_ELEMENTNOTAVAILABLE(expr) \
45 EXPECT_EQ(static_cast<HRESULT>(UIA_E_ELEMENTNOTAVAILABLE), (expr))
46#define EXPECT_UIA_INVALIDOPERATION(expr) \
47 EXPECT_EQ(static_cast<HRESULT>(UIA_E_INVALIDOPERATION), (expr))
48#define EXPECT_UIA_ELEMENTNOTENABLED(expr) \
49 EXPECT_EQ(static_cast<HRESULT>(UIA_E_ELEMENTNOTENABLED), (expr))
50#define EXPECT_UIA_NOTSUPPORTED(expr) \
51 EXPECT_EQ(static_cast<HRESULT>(UIA_E_NOTSUPPORTED), (expr))
52
53#define ASSERT_UIA_ELEMENTNOTAVAILABLE(expr) \
54 ASSERT_EQ(static_cast<HRESULT>(UIA_E_ELEMENTNOTAVAILABLE), (expr))
55#define ASSERT_UIA_INVALIDOPERATION(expr) \
56 ASSERT_EQ(static_cast<HRESULT>(UIA_E_INVALIDOPERATION), (expr))
57#define ASSERT_UIA_ELEMENTNOTENABLED(expr) \
58 ASSERT_EQ(static_cast<HRESULT>(UIA_E_ELEMENTNOTENABLED), (expr))
59#define ASSERT_UIA_NOTSUPPORTED(expr) \
60 ASSERT_EQ(static_cast<HRESULT>(UIA_E_NOTSUPPORTED), (expr))
61
62// Helper macros for testing UIAutomation property values and maintain
63// correct stack tracing and failure causality.
64//
65// WARNING: These aren't intended to be generic EXPECT_BSTR_EQ macros
66// as the logic is specific to extracting and comparing UIA property
67// values.
68#define EXPECT_UIA_EMPTY(node, property_id) \
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
220
221HRESULT
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//
238 PATTERNID pattern_id,
239 IUnknown** result) {
240 return E_NOTIMPL;
241}
242
244 PROPERTYID property_id,
245 VARIANT* result) {
246 return E_NOTIMPL;
247}
248
249IFACEMETHODIMP
251 return E_NOTIMPL;
252}
253
255 IRawElementProviderSimple** provider) {
256 return E_NOTIMPL;
257}
258
260 // scoped_feature_list_.InitAndEnableFeature(features::kIChromeAccessible);
261}
262
264
268
270 // Destroy the tree and make sure we're not leaking any objects.
271 ax_fragment_root_.reset(nullptr);
272 DestroyTree();
276}
277
279 const TestAXNodeWrapper* wrapper =
281 return wrapper ? wrapper->ax_platform_node() : nullptr;
282}
283
284template <typename T>
286 return QueryInterfaceFromNode<T>(GetNodeFromTree(id));
287}
288
289template <typename T>
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>
303 return QueryInterfaceFromNode<IRawElementProviderSimple>(GetRootAsAXNode());
304}
305
306ComPtr<IRawElementProviderSimple>
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>
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>
329 return QueryInterfaceFromNode<IRawElementProviderFragment>(GetRootAsAXNode());
330}
331
332Microsoft::WRL::ComPtr<IRawElementProviderFragment>
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
345 return QueryInterfaceFromNode<IAccessible>(node);
346}
347
351
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
368
370 AXNode* node,
371 TestFragmentRootDelegate* delegate) {
373 if (node->parent())
374 delegate->parent_ =
376
377 return new AXFragmentRootWin(gfx::kMockAcceleratedWidget, delegate);
378}
379
380ComPtr<IRawElementProviderFragmentRoot>
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
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
416
418
422
427
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 =
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.
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;
541 root.AddStringAttribute(ax::mojom::StringAttribute::kDescription,
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;
559 root.role = ax::mojom::Role::kTextField;
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;
577 root.AddStringAttribute(ax::mojom::StringAttribute::kKeyShortcuts,
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);
588 ScopedBstr k2;
589 EXPECT_EQ(E_INVALIDARG,
590 root_obj->get_accKeyboardShortcut(bad_id, k2.Receive()));
591}
592
594 IAccessibleSelectionListBoxOptionNothingSelected) {
595 AXNodeData list;
596 list.id = 1;
598
599 AXNodeData list_item_1;
600 list_item_1.id = 2;
602 list_item_1.SetName("Name1");
603
604 AXNodeData list_item_2;
605 list_item_2.id = 3;
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;
626
627 AXNodeData list_item_1;
628 list_item_1.id = 2;
631 list_item_1.SetName("Name1");
632
633 AXNodeData list_item_2;
634 list_item_2.id = 3;
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
654 IAccessibleSelectionListBoxOptionMultipleSelected) {
655 AXNodeData list;
656 list.id = 1;
658
659 AXNodeData list_item_1;
660 list_item_1.id = 2;
663 list_item_1.SetName("Name1");
664
665 AXNodeData list_item_2;
666 list_item_2.id = 3;
669 list_item_2.SetName("Name2");
670
671 AXNodeData list_item_3;
672 list_item_3.id = 4;
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
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
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
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.
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;
1002 button.id = 2;
1003
1004 AXNodeData checkbox;
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
1070 AXNodeData root;
1071 root.id = 1;
1073
1074 AXNodeData child1;
1075 child1.id = 2;
1077 root.child_ids.push_back(2);
1078
1079 AXNodeData child2;
1080 child2.id = 3;
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;
1381 root.role = ax::mojom::Role::kGrid;
1382 root.AddIntAttribute(ax::mojom::IntAttribute::kAriaRowCount, 1);
1383 root.AddIntAttribute(ax::mojom::IntAttribute::kAriaColumnCount, 1);
1384
1385 AXNodeData row1;
1386 row1.id = 2;
1388 root.child_ids.push_back(row1.id);
1389
1390 AXNodeData cell1;
1391 cell1.id = 3;
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;
1413 root.role = ax::mojom::Role::kTable;
1414
1415 AXNodeData row1;
1416 row1.id = 2;
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;
1483 root.role = ax::mojom::Role::kTable;
1484
1485 AXNodeData row1;
1486 row1.id = 2;
1488 root.child_ids.push_back(row1.id);
1489
1490 AXNodeData row2;
1491 row2.id = 3;
1493 root.child_ids.push_back(row2.id);
1494
1495 AXNodeData row3;
1496 row3.id = 4;
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;
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;
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;
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;
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;
1579 root.role = ax::mojom::Role::kTable;
1580
1581 AXNodeData row1;
1582 row1.id = 2;
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.
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;
1625 root.role = ax::mojom::Role::kTable;
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;
1641 root.role = ax::mojom::Role::kTable;
1642
1643 AXNodeData row1;
1644 row1.id = 2;
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;
1663 root.child_ids.push_back(row2.id);
1664
1665 AXNodeData cell;
1666 cell.id = 6;
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;
1704 root.role = ax::mojom::Role::kTable;
1705
1706 AXNodeData row1;
1707 row1.id = 2;
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;
1720 row1.child_ids.push_back(cell.id);
1721
1722 AXNodeData row2;
1723 row2.id = 5;
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.
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;
1765 root.role = ax::mojom::Role::kList;
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");
1770 root.AddStringAttribute(ax::mojom::StringAttribute::kDescription,
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;
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;
1826 root.role = ax::mojom::Role::kButton;
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;
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
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.
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;
1960 tab.SetName("tab");
1961 std::vector<AXNode::AXID> controller_ids = {3, 4};
1963 controller_ids);
1964
1965 AXNodeData panel1;
1966 panel1.id = 3;
1968 panel1.SetName("panel1");
1969
1970 AXNodeData panel2;
1971 panel2.id = 4;
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.
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};
2002 root.AddIntListAttribute(ax::mojom::IntListAttribute::kDescribedbyIds,
2003 describedby_ids);
2004 root.id = 1;
2005 root.role = ax::mojom::Role::kMarquee;
2006 root.SetName("root");
2007
2008 AXNodeData child1;
2009 child1.id = 2;
2011 child1.SetName("child1");
2012
2013 root.child_ids.push_back(child1.id);
2014
2015 AXNodeData child2;
2016 child2.id = 3;
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;
2035 root.role = ax::mojom::Role::kTable;
2036
2037 AXNodeData row1;
2038 row1.id = 2;
2041 static_cast<int>(ax::mojom::SortDirection::kAscending));
2042 root.child_ids.push_back(row1.id);
2043
2044 AXNodeData header1;
2045 header1.id = 3;
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;
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;
2064 static_cast<int>(ax::mojom::SortDirection::kOther));
2065 row1.child_ids.push_back(header3.id);
2066
2067 AXNodeData header4;
2068 header4.id = 6;
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;
2105 root.role = ax::mojom::Role::kMarquee;
2106 root.SetName("root");
2107
2108 AXNodeData child1;
2109 child1.id = 2;
2111 child1.SetName("child1");
2112
2113 root.child_ids.push_back(child1.id);
2114
2115 AXNodeData child2;
2116 child2.id = 3;
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");
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.
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
2255 root_1.child_ids = {gc_2.id, gc_4.id, alert_7.id};
2256
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
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;
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;
2364 input1.SetName("name-from-title");
2366 static_cast<int>(ax::mojom::NameFrom::kTitle));
2368 "placeholder");
2369 root.child_ids.push_back(input1.id);
2370
2371 // Test NameFrom Title is exposed
2372 AXNodeData input2;
2373 input2.id = 3;
2375 input2.SetName("name-from-title");
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;
2384 input3.SetName("name-from-placeholder");
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;
2393 input4.SetName("name-from-attribute");
2395 static_cast<int>(ax::mojom::NameFrom::kAttribute));
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;
2404 input5.SetName("name-from-attribute");
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;
2431 root.role = ax::mojom::Role::kUnknown;
2432 root.id = 1;
2433 root.AddStringAttribute(ax::mojom::StringAttribute::kRoleDescription,
2434 "root role description");
2435
2436 AXNodeData child1;
2437 child1.id = 2;
2440 "child1 role description");
2441 root.child_ids.push_back(2);
2442
2443 AXNodeData child2;
2444 child2.id = 3;
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);
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
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
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
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
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;
3043 root.child_ids.push_back(child1_id);
3044
3045 AXNodeData child2;
3046 AXNode::AXID child2_id = 3;
3047 child2.id = child2_id;
3049 root.child_ids.push_back(child2_id);
3050
3051 AXNodeData child3;
3052 AXNode::AXID child3_id = 4;
3053 child3.id = child3_id;
3055 root.child_ids.push_back(child3_id);
3056
3057 AXNodeData child4;
3058 AXNode::AXID child4_id = 5;
3059 child4.id = child4_id;
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
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());
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) {
3579 ui::AXNodeData root;
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) {
3697 ui::AXNodeData root;
3698 root.id = 1;
3699
3700 ui::AXNodeData link;
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.
3717 link.role = ax::mojom::Role::kLink;
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) {
3763 ui::AXNodeData root;
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) {
3932 ui::AXNodeData root;
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;
3975 root.role = ax::mojom::Role::kNone;
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;
3990 root.AddIntAttribute(ax::mojom::IntAttribute::kRestriction,
3991 static_cast<int>(ax::mojom::Restriction::kDisabled));
3992 root.AddBoolAttribute(ax::mojom::BoolAttribute::kSelected, true);
3993 root.role = ax::mojom::Role::kTab;
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;
4016 root.role = ax::mojom::Role::kTab;
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;
4031 root.role = ax::mojom::Role::kListBox;
4032
4033 AXNodeData option1;
4034 option1.id = 2;
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;
4091 root.role = ax::mojom::Role::kRadioGroup;
4092
4093 // CheckedState::kNone
4094 AXNodeData option1;
4095 option1.id = 2;
4097 static_cast<int>(ax::mojom::CheckedState::kNone));
4099 root.child_ids.push_back(option1.id);
4100
4101 // CheckedState::kFalse
4102 AXNodeData option2;
4103 option2.id = 3;
4105 static_cast<int>(ax::mojom::CheckedState::kFalse));
4107 root.child_ids.push_back(option2.id);
4108
4109 // CheckedState::kTrue
4110 AXNodeData option3;
4111 option3.id = 4;
4113 static_cast<int>(ax::mojom::CheckedState::kTrue));
4115 root.child_ids.push_back(option3.id);
4116
4117 // CheckedState::kMixed
4118 AXNodeData option4;
4119 option4.id = 5;
4121 static_cast<int>(ax::mojom::CheckedState::kMixed));
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;
4179 root.role = ax::mojom::Role::kMenu;
4180
4181 // CheckedState::kNone
4182 AXNodeData option1;
4183 option1.id = 2;
4185 static_cast<int>(ax::mojom::CheckedState::kNone));
4187 root.child_ids.push_back(option1.id);
4188
4189 // CheckedState::kFalse
4190 AXNodeData option2;
4191 option2.id = 3;
4193 static_cast<int>(ax::mojom::CheckedState::kFalse));
4195 root.child_ids.push_back(option2.id);
4196
4197 // CheckedState::kTrue
4198 AXNodeData option3;
4199 option3.id = 4;
4201 static_cast<int>(ax::mojom::CheckedState::kTrue));
4203 root.child_ids.push_back(option3.id);
4204
4205 // CheckedState::kMixed
4206 AXNodeData option4;
4207 option4.id = 5;
4209 static_cast<int>(ax::mojom::CheckedState::kMixed));
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;
4267 root.role = ax::mojom::Role::kTable;
4268
4269 AXNodeData row1;
4270 row1.id = 2;
4272 root.child_ids.push_back(row1.id);
4273
4274 AXNodeData cell1;
4275 cell1.id = 3;
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;
4292 root.role = ax::mojom::Role::kGrid;
4293
4294 AXNodeData row1;
4295 row1.id = 2;
4297 root.child_ids.push_back(row1.id);
4298
4299 AXNodeData cell1;
4300 cell1.id = 3;
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;
4359 root.role = ax::mojom::Role::kGrid;
4360
4361 AXNodeData row1;
4362 row1.id = 2;
4364 root.child_ids.push_back(row1.id);
4365
4366 AXNodeData cell1;
4367 cell1.id = 3;
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;
4390 root.role = ax::mojom::Role::kTabList;
4391
4392 AXNodeData tab1;
4393 tab1.id = 2;
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);
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.
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".
4444}
4445
4446TEST_F(AXPlatformNodeWinTest, IValueProvider_GetValue) {
4447 AXNodeData root;
4448 root.id = 1;
4450
4451 AXNodeData child1;
4452 child1.id = 2;
4455 root.child_ids.push_back(child1.id);
4456
4457 AXNodeData child2;
4458 child2.id = 3;
4462 root.child_ids.push_back(child2.id);
4463
4464 AXNodeData child3;
4465 child3.id = 4;
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;
4504 root.child_ids.push_back(child1.id);
4505
4506 AXNodeData child2;
4507 child2.id = 3;
4510 root.child_ids.push_back(child2.id);
4511
4512 AXNodeData child3;
4513 child3.id = 4;
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;
4561 root.child_ids.push_back(child1.id);
4562
4563 AXNodeData child2;
4564 child2.id = 3;
4567 static_cast<int>(ax::mojom::Restriction::kReadOnly));
4568 root.child_ids.push_back(child2.id);
4569
4570 AXNodeData child3;
4571 child3.id = 4;
4574 static_cast<int>(ax::mojom::Restriction::kDisabled));
4575 root.child_ids.push_back(child3.id);
4576
4577 AXNodeData child4;
4578 child4.id = 5;
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;
4680 root.role = ax::mojom::Role::kCheckBox;
4681 root.AddIntAttribute(ax::mojom::IntAttribute::kCheckedState,
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_BSTR_EQ(node, property_id, expected)
#define EXPECT_UIA_ELEMENT_ARRAY_BSTR_EQ(array, element_test_property_id, expected_property_values)
#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_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)
void Reset(BSTR bstr=nullptr)
const VARIANT * ptr() const
VARIANT * AsInput() const
void Reset(const VARIANT &var=kEmptyVariant)
virtual AXTreeID GetAXTreeID() const =0
AXID id() const
Definition ax_node.h:110
void SetData(const AXNodeData &src)
Definition ax_node.cc:373
OwnerTree * tree() const
Definition ax_node.h:109
int32_t AXID
Definition ax_node.h:36
const std::vector< AXNode * > & children() const
Definition ax_node.h:113
AXNode * parent() const
Definition ax_node.h:111
static const char16_t kEmbeddedCharacter
static size_t GetInstanceCountForTesting()
Microsoft::WRL::ComPtr< T > QueryInterfaceFromNode(AXNode *node)
std::unique_ptr< AXFragmentRootWin > ax_fragment_root_
Microsoft::WRL::ComPtr< IRawElementProviderFragment > GetRootIRawElementProviderFragment()
Microsoft::WRL::ComPtr< IRawElementProviderSimple > GetIRawElementProviderSimpleFromChildIndex(int child_index)
static const std::u16string kEmbeddedCharacterAsString
void CheckVariantHasName(const base::win::ScopedVariant &variant, const wchar_t *expected_name)
Microsoft::WRL::ComPtr< T > QueryInterfaceFromNodeId(AXNode::AXID id)
Microsoft::WRL::ComPtr< IAccessible > GetRootIAccessible()
Microsoft::WRL::ComPtr< IRawElementProviderSimple > GetIRawElementProviderSimpleFromTree(const ui::AXTreeID tree_id, const AXNode::AXID node_id)
std::unordered_set< LONG > PatternSet
Microsoft::WRL::ComPtr< IRawElementProviderFragment > IRawElementProviderFragmentFromNode(AXNode *node)
AXFragmentRootWin * InitNodeAsFragmentRoot(AXNode *node, TestFragmentRootDelegate *delegate)
Microsoft::WRL::ComPtr< IRawElementProviderSimple > GetRootIRawElementProviderSimple()
Microsoft::WRL::ComPtr< IAccessible > IAccessibleFromNode(AXNode *node)
std::unique_ptr< TestFragmentRootDelegate > test_fragment_root_delegate_
PatternSet GetSupportedPatternsFromNodeId(AXNode::AXID id)
Microsoft::WRL::ComPtr< IRawElementProviderFragmentRoot > GetFragmentRoot()
AXPlatformNode * AXPlatformNodeFromNode(AXNode *node)
virtual gfx::NativeViewAccessible GetNativeViewAccessible()=0
static AXTreeID CreateNewAXTreeID()
Definition ax_tree_id.cc:47
IFACEMETHODIMP GetPatternProvider(PATTERNID pattern_id, IUnknown **result) override
IFACEMETHODIMP GetPropertyValue(PROPERTYID property_id, VARIANT *result) override
static HRESULT CreateMockIRawElementProviderSimple(IRawElementProviderSimple **provider)
IFACEMETHODIMP get_ProviderOptions(enum ProviderOptions *ret) override
IFACEMETHODIMP get_HostRawElementProvider(IRawElementProviderSimple **provider) override
static void SetGlobalIsWebContent(bool is_web_content)
static TestAXNodeWrapper * GetOrCreate(AXTree *tree, AXNode *node)
AXPlatformNode * ax_platform_node() const
static void SetNodeFromLastDefaultAction(AXNode *node)
static const AXNode * GetNodeFromLastShowContextMenu()
static void SetGlobalCoordinateOffset(const gfx::Vector2d &offset)
static const AXNode * GetNodeFromLastDefaultAction()
static std::unique_ptr< base::AutoReset< float > > SetScaleFactor(float value)
static void SetHitTestResult(AXNode::AXID src_node_id, AXNode::AXID dst_node_id)
void BuildAllWrappers(AXTree *tree, AXNode *node)
AXNode * GetNodeFromTree(const AXTreeID tree_id, const AXNode::AXID node_id) const override
AXNode * GetRootAsAXNode() const override
gfx::NativeViewAccessible GetParentOfAXFragmentRoot() override
gfx::NativeViewAccessible GetChildOfAXFragmentRoot() override
AtkStateType state
glong glong end
uint8_t value
GAsyncResult * result
const char * name
Definition fuchsia.cc:50
void Init()
return FALSE
UnimplementedNativeViewAccessible * NativeViewAccessible
void CreateATLModuleIfNeeded()
Definition atl_module.h:22
TEST_F(AXPositionTest, Clone)
#define T
int32_t height
int32_t width
AXRelativeBounds relative_bounds
void AddFloatAttribute(ax::mojom::FloatAttribute attribute, float value)
void SetRestriction(ax::mojom::Restriction restriction)
void AddIntListAttribute(ax::mojom::IntListAttribute attribute, const std::vector< int32_t > &value)
void AddState(ax::mojom::State state)
void SetDefaultActionVerb(ax::mojom::DefaultActionVerb default_action_verb)
void AddIntAttribute(ax::mojom::IntAttribute attribute, int32_t value)
std::vector< int32_t > child_ids
void SetHasPopup(ax::mojom::HasPopup has_popup)
void SetName(const std::string &name)
void AddStringAttribute(ax::mojom::StringAttribute attribute, const std::string &value)
void AddBoolAttribute(ax::mojom::BoolAttribute attribute, bool value)
ax::mojom::Role role
void SetCheckedState(ax::mojom::CheckedState checked_state)
std::vector< AXNodeData > nodes
#define EXPECT_TRUE(handle)
Definition unit_test.h:685
int BOOL
#define SUCCEEDED(hr)
long LONG
DWORD ULONG