Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
ax_fragment_root_win_unittest.cc
Go to the documentation of this file.
1// Copyright 2019 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
9
10#include <UIAutomationClient.h>
11#include <UIAutomationCoreApi.h>
12
13#include "base/auto_reset.h"
16#include "gtest/gtest.h"
17#include "uia_registrar_win.h"
18
20using Microsoft::WRL::ComPtr;
21
22namespace ui {
23
24#define EXPECT_UIA_BSTR_EQ(node, property_id, expected) \
25 { \
26 ScopedVariant expectedVariant(expected); \
27 ASSERT_EQ(VT_BSTR, expectedVariant.type()); \
28 ASSERT_NE(nullptr, expectedVariant.ptr()->bstrVal); \
29 ScopedVariant actual; \
30 ASSERT_HRESULT_SUCCEEDED( \
31 node->GetPropertyValue(property_id, actual.Receive())); \
32 ASSERT_EQ(VT_BSTR, actual.type()); \
33 ASSERT_NE(nullptr, actual.ptr()->bstrVal); \
34 EXPECT_STREQ(expectedVariant.ptr()->bstrVal, actual.ptr()->bstrVal); \
35 }
36
44
45TEST_F(AXFragmentRootTest, UIAFindItemByPropertyUniqueId) {
46 AXNodeData root;
47 root.id = 1;
49 root.SetName("root");
50 root.child_ids = {2, 3};
51
52 AXNodeData text1;
53 text1.id = 2;
55 text1.SetName("text1");
56
57 AXNodeData button;
58 button.id = 3;
60 button.SetName("button");
61 button.child_ids = {4};
62
63 AXNodeData text2;
64 text2.id = 4;
66 text2.SetName("text2");
67
68 Init(root, text1, button, text2);
69 InitFragmentRoot();
70
71 ComPtr<IRawElementProviderSimple> root_raw_element_provider_simple;
72 ax_fragment_root_->GetNativeViewAccessible()->QueryInterface(
73 IID_PPV_ARGS(&root_raw_element_provider_simple));
74 ComPtr<IRawElementProviderSimple> text1_raw_element_provider_simple =
75 GetIRawElementProviderSimpleFromChildIndex(0);
76 ComPtr<IRawElementProviderSimple> button_raw_element_provider_simple =
77 GetIRawElementProviderSimpleFromChildIndex(1);
78
79 AXNode* text1_node = GetRootAsAXNode()->children()[0];
80 AXNode* button_node = GetRootAsAXNode()->children()[1];
81
82 ComPtr<IItemContainerProvider> item_container_provider;
83 EXPECT_HRESULT_SUCCEEDED(root_raw_element_provider_simple->GetPatternProvider(
84 UIA_ItemContainerPatternId, &item_container_provider));
85 ASSERT_NE(nullptr, item_container_provider.Get());
86
87 ScopedVariant unique_id_variant;
88 int32_t unique_id;
89 ComPtr<IRawElementProviderSimple> result;
90
91 // When |start_after_element| is an invalid element, we should fail at finding
92 // the item.
93 {
94 unique_id = AXPlatformNodeFromNode(GetRootAsAXNode())->GetUniqueId();
95 unique_id_variant.Set(SysAllocString(reinterpret_cast<const wchar_t*>(
96 base::NumberToString16(-unique_id).c_str())));
97
98 ComPtr<IRawElementProviderSimple> invalid_element_provider_simple;
99 EXPECT_HRESULT_SUCCEEDED(
101 &invalid_element_provider_simple));
102
103 EXPECT_HRESULT_FAILED(item_container_provider->FindItemByProperty(
104 invalid_element_provider_simple.Get(),
106 unique_id_variant, &result));
107 result.Reset();
108 unique_id_variant.Release();
109 }
110
111 // Fetch the AxUniqueId of "root", and verify we can retrieve its
112 // corresponding IRawElementProviderSimple through FindItemByProperty().
113 {
114 unique_id = AXPlatformNodeFromNode(GetRootAsAXNode())->GetUniqueId();
115 unique_id_variant.Set(SysAllocString(reinterpret_cast<const wchar_t*>(
116 base::NumberToString16(-unique_id).c_str())));
117
118 // When |start_after_element| of FindItemByProperty() is nullptr, we should
119 // be able to find "text1".
120 EXPECT_HRESULT_SUCCEEDED(item_container_provider->FindItemByProperty(
122 unique_id_variant, &result));
123 EXPECT_UIA_BSTR_EQ(result, UIA_NamePropertyId, L"root");
124 result.Reset();
125
126 // When |start_after_element| of FindItemByProperty() is "text1", there
127 // should be no element found, since "text1" comes after the element we are
128 // looking for.
129 EXPECT_HRESULT_SUCCEEDED(item_container_provider->FindItemByProperty(
130 text1_raw_element_provider_simple.Get(),
132 unique_id_variant, &result));
133 EXPECT_EQ(nullptr, result.Get());
134 result.Reset();
135
136 // When |start_after_element| of FindItemByProperty() is "button", there
137 // should be no element found, since "button" comes after the element we are
138 // looking for.
139 EXPECT_HRESULT_SUCCEEDED(item_container_provider->FindItemByProperty(
140 button_raw_element_provider_simple.Get(),
142 unique_id_variant, &result));
143 EXPECT_EQ(nullptr, result.Get());
144
145 result.Reset();
146 unique_id_variant.Release();
147 }
148
149 // Fetch the AxUniqueId of "text1", and verify if we can retrieve its
150 // corresponding IRawElementProviderSimple through FindItemByProperty().
151 {
152 unique_id = AXPlatformNodeFromNode(text1_node)->GetUniqueId();
153 unique_id_variant.Set(SysAllocString(reinterpret_cast<const wchar_t*>(
154 base::NumberToString16(-unique_id).c_str())));
155
156 // When |start_after_element| of FindItemByProperty() is nullptr, we should
157 // be able to find "text1".
158 EXPECT_HRESULT_SUCCEEDED(item_container_provider->FindItemByProperty(
160 unique_id_variant, &result));
161 EXPECT_UIA_BSTR_EQ(result, UIA_NamePropertyId, L"text1");
162 result.Reset();
163
164 // When |start_after_element| of FindItemByProperty() is "text1", there
165 // should be no element found, since "text1" equals the element we are
166 // looking for.
167 EXPECT_HRESULT_SUCCEEDED(item_container_provider->FindItemByProperty(
168 text1_raw_element_provider_simple.Get(),
170 unique_id_variant, &result));
171 EXPECT_EQ(nullptr, result.Get());
172 result.Reset();
173
174 // When |start_after_element| of FindItemByProperty() is "button", there
175 // should be no element found, since "button" comes after the element we are
176 // looking for.
177 EXPECT_HRESULT_SUCCEEDED(item_container_provider->FindItemByProperty(
178 button_raw_element_provider_simple.Get(),
180 unique_id_variant, &result));
181 EXPECT_EQ(nullptr, result.Get());
182 result.Reset();
183 unique_id_variant.Release();
184 }
185
186 // Fetch the AxUniqueId of "button", and verify we can retrieve its
187 // corresponding IRawElementProviderSimple through FindItemByProperty().
188 {
189 unique_id = AXPlatformNodeFromNode(button_node)->GetUniqueId();
190 unique_id_variant.Set(SysAllocString(reinterpret_cast<const wchar_t*>(
191 base::NumberToString16(-unique_id).c_str())));
192
193 // When |start_after_element| of FindItemByProperty() is nullptr, we should
194 // be able to find "button".
195 EXPECT_HRESULT_SUCCEEDED(item_container_provider->FindItemByProperty(
197 unique_id_variant, &result));
198 EXPECT_UIA_BSTR_EQ(result, UIA_NamePropertyId, L"button");
199 result.Reset();
200
201 // When |start_after_element| of FindItemByProperty() is "text1", we should
202 // be able to find "button".
203 EXPECT_HRESULT_SUCCEEDED(item_container_provider->FindItemByProperty(
204 text1_raw_element_provider_simple.Get(),
206 unique_id_variant, &result));
207 EXPECT_UIA_BSTR_EQ(result, UIA_NamePropertyId, L"button");
208 result.Reset();
209
210 // When |start_after_element| of FindItemByProperty() is "button", there
211 // should be no element found, since "button" equals the element we are
212 // looking for.
213 EXPECT_HRESULT_SUCCEEDED(item_container_provider->FindItemByProperty(
214 button_raw_element_provider_simple.Get(),
216 unique_id_variant, &result));
217 EXPECT_EQ(nullptr, result.Get());
218 result.Reset();
219 unique_id_variant.Release();
220 }
221
222 // Fetch the AxUniqueId of "text2", and verify we can retrieve its
223 // corresponding IRawElementProviderSimple through FindItemByProperty().
224 {
225 unique_id =
226 AXPlatformNodeFromNode(button_node->children()[0])->GetUniqueId();
227 unique_id_variant.Set(SysAllocString(reinterpret_cast<const wchar_t*>(
228 base::NumberToString16(-unique_id).c_str())));
229
230 // When |start_after_element| of FindItemByProperty() is nullptr, we should
231 // be able to find "text2".
232 EXPECT_HRESULT_SUCCEEDED(item_container_provider->FindItemByProperty(
234 unique_id_variant, &result));
235 EXPECT_UIA_BSTR_EQ(result, UIA_NamePropertyId, L"text2");
236
237 // When |start_after_element| of FindItemByProperty() is root, we should
238 // be able to find "text2".
239 EXPECT_HRESULT_SUCCEEDED(item_container_provider->FindItemByProperty(
240 root_raw_element_provider_simple.Get(),
242 unique_id_variant, &result));
243 EXPECT_UIA_BSTR_EQ(result, UIA_NamePropertyId, L"text2");
244
245 // When |start_after_element| of FindItemByProperty() is "text1", we should
246 // be able to find "text2".
247 EXPECT_HRESULT_SUCCEEDED(item_container_provider->FindItemByProperty(
248 text1_raw_element_provider_simple.Get(),
250 unique_id_variant, &result));
251 EXPECT_UIA_BSTR_EQ(result, UIA_NamePropertyId, L"text2");
252
253 // When |start_after_element| of FindItemByProperty() is "button", we should
254 // be able to find "text2".
255 EXPECT_HRESULT_SUCCEEDED(item_container_provider->FindItemByProperty(
256 button_raw_element_provider_simple.Get(),
258 unique_id_variant, &result));
259 EXPECT_UIA_BSTR_EQ(result, UIA_NamePropertyId, L"text2");
260 }
261}
262
263TEST_F(AXFragmentRootTest, TestUIAGetFragmentRoot) {
264 AXNodeData root;
265 root.id = 1;
266 Init(root);
267 InitFragmentRoot();
268
269 ComPtr<IRawElementProviderFragmentRoot> expected_fragment_root =
270 GetFragmentRoot();
271 ComPtr<IRawElementProviderFragment> fragment_provider;
272 expected_fragment_root.As(&fragment_provider);
273
274 ComPtr<IRawElementProviderFragmentRoot> actual_fragment_root;
275 EXPECT_HRESULT_SUCCEEDED(
276 fragment_provider->get_FragmentRoot(&actual_fragment_root));
277 EXPECT_EQ(expected_fragment_root.Get(), actual_fragment_root.Get());
278}
279
280TEST_F(AXFragmentRootTest, DISABLED_TestUIAElementProviderFromPoint) {
281 AXNodeData root_data;
282 root_data.id = 1;
283 root_data.relative_bounds.bounds = gfx::RectF(0, 0, 80, 80);
284
285 AXNodeData element1_data;
286 element1_data.id = 2;
287 element1_data.relative_bounds.bounds = gfx::RectF(0, 0, 50, 50);
288 root_data.child_ids.push_back(element1_data.id);
289
290 AXNodeData element2_data;
291 element2_data.id = 3;
292 element2_data.relative_bounds.bounds = gfx::RectF(0, 50, 30, 30);
293 root_data.child_ids.push_back(element2_data.id);
294
295 Init(root_data, element1_data, element2_data);
296 InitFragmentRoot();
297
298 AXNode* root_node = GetRootAsAXNode();
299 AXNode* element1_node = root_node->children()[0];
300 AXNode* element2_node = root_node->children()[1];
301
302 ComPtr<IRawElementProviderFragmentRoot> fragment_root_prov(GetFragmentRoot());
303 ComPtr<IRawElementProviderFragment> root_provider(
304 GetRootIRawElementProviderFragment());
305 ComPtr<IRawElementProviderFragment> element1_provider =
306 QueryInterfaceFromNode<IRawElementProviderFragment>(element1_node);
307 ComPtr<IRawElementProviderFragment> element2_provider =
308 QueryInterfaceFromNode<IRawElementProviderFragment>(element2_node);
309
310 ComPtr<IRawElementProviderFragment> provider_from_point;
311 EXPECT_HRESULT_SUCCEEDED(fragment_root_prov->ElementProviderFromPoint(
312 23, 31, &provider_from_point));
313 EXPECT_EQ(element1_provider.Get(), provider_from_point.Get());
314
315 EXPECT_HRESULT_SUCCEEDED(fragment_root_prov->ElementProviderFromPoint(
316 23, 67, &provider_from_point));
317 EXPECT_EQ(element2_provider.Get(), provider_from_point.Get());
318
319 EXPECT_HRESULT_SUCCEEDED(fragment_root_prov->ElementProviderFromPoint(
320 47, 67, &provider_from_point));
321 EXPECT_EQ(root_provider.Get(), provider_from_point.Get());
322
323 // This is on node 1 with scale factor of 1.5.
324 std::unique_ptr<base::AutoReset<float>> scale_factor_reset =
326 EXPECT_HRESULT_SUCCEEDED(fragment_root_prov->ElementProviderFromPoint(
327 60, 60, &provider_from_point));
328 EXPECT_EQ(element1_provider.Get(), provider_from_point.Get());
329}
330
331TEST_F(AXFragmentRootTest, TestUIAGetFocus) {
332 AXNodeData root_data;
333 root_data.id = 1;
334
335 AXNodeData element1_data;
336 element1_data.id = 2;
337 root_data.child_ids.push_back(element1_data.id);
338
339 AXNodeData element2_data;
340 element2_data.id = 3;
341 root_data.child_ids.push_back(element2_data.id);
342
343 Init(root_data, element1_data, element2_data);
344 InitFragmentRoot();
345
346 AXNode* root_node = GetRootAsAXNode();
347 AXNode* element1_node = root_node->children()[0];
348 AXNode* element2_node = root_node->children()[1];
349
350 ComPtr<IRawElementProviderFragmentRoot> fragment_root_prov(GetFragmentRoot());
351 ComPtr<IRawElementProviderFragment> root_provider(
352 GetRootIRawElementProviderFragment());
353 ComPtr<IRawElementProviderFragment> element1_provider =
354 QueryInterfaceFromNode<IRawElementProviderFragment>(element1_node);
355 ComPtr<IRawElementProviderFragment> element2_provider =
356 QueryInterfaceFromNode<IRawElementProviderFragment>(element2_node);
357
358 ComPtr<IRawElementProviderFragment> focused_fragment;
359 EXPECT_HRESULT_SUCCEEDED(root_provider->SetFocus());
360 EXPECT_HRESULT_SUCCEEDED(fragment_root_prov->GetFocus(&focused_fragment));
361 EXPECT_EQ(root_provider.Get(), focused_fragment.Get());
362
363 EXPECT_HRESULT_SUCCEEDED(element1_provider->SetFocus());
364 EXPECT_HRESULT_SUCCEEDED(fragment_root_prov->GetFocus(&focused_fragment));
365 EXPECT_EQ(element1_provider.Get(), focused_fragment.Get());
366
367 EXPECT_HRESULT_SUCCEEDED(element2_provider->SetFocus());
368 EXPECT_HRESULT_SUCCEEDED(fragment_root_prov->GetFocus(&focused_fragment));
369 EXPECT_EQ(element2_provider.Get(), focused_fragment.Get());
370}
371
372TEST_F(AXFragmentRootTest, TestUIAErrorHandling) {
373 AXNodeData root;
374 root.id = 1;
375 Init(root);
376 InitFragmentRoot();
377
378 ComPtr<IRawElementProviderSimple> simple_provider =
379 GetRootIRawElementProviderSimple();
380 ComPtr<IRawElementProviderFragment> fragment_provider =
381 GetRootIRawElementProviderFragment();
382 ComPtr<IRawElementProviderFragmentRoot> fragment_root_provider =
383 GetFragmentRoot();
384
385 SetTree(std::make_unique<AXTree>());
386 ax_fragment_root_.reset(nullptr);
387
388 ComPtr<IRawElementProviderSimple> returned_simple_provider;
389 ComPtr<IRawElementProviderFragment> returned_fragment_provider;
390 ComPtr<IRawElementProviderFragmentRoot> returned_fragment_root_provider;
391 base::win::ScopedSafearray returned_runtime_id;
392
393 EXPECT_EQ(
394 static_cast<HRESULT>(UIA_E_ELEMENTNOTAVAILABLE),
395 simple_provider->get_HostRawElementProvider(&returned_simple_provider));
396
397 EXPECT_EQ(
398 static_cast<HRESULT>(UIA_E_ELEMENTNOTAVAILABLE),
399 fragment_provider->get_FragmentRoot(&returned_fragment_root_provider));
400
401 EXPECT_EQ(static_cast<HRESULT>(UIA_E_ELEMENTNOTAVAILABLE),
402 fragment_provider->GetRuntimeId(returned_runtime_id.Receive()));
403
404 EXPECT_EQ(static_cast<HRESULT>(UIA_E_ELEMENTNOTAVAILABLE),
405 fragment_root_provider->ElementProviderFromPoint(
406 67, 23, &returned_fragment_provider));
407
408 EXPECT_EQ(static_cast<HRESULT>(UIA_E_ELEMENTNOTAVAILABLE),
409 fragment_root_provider->GetFocus(&returned_fragment_provider));
410}
411
412TEST_F(AXFragmentRootTest, TestGetChildCount) {
413 AXNodeData root;
414 root.id = 1;
415 Init(root);
416 InitFragmentRoot();
417
418 AXPlatformNodeDelegate* fragment_root = ax_fragment_root_.get();
419 EXPECT_EQ(1, fragment_root->GetChildCount());
420
421 test_fragment_root_delegate_->child_ = nullptr;
422 EXPECT_EQ(0, fragment_root->GetChildCount());
423}
424
425TEST_F(AXFragmentRootTest, TestChildAtIndex) {
426 AXNodeData root;
427 root.id = 1;
428 Init(root);
429 InitFragmentRoot();
430
431 gfx::NativeViewAccessible native_view_accessible =
432 AXPlatformNodeFromNode(GetRootAsAXNode())->GetNativeViewAccessible();
433 AXPlatformNodeDelegate* fragment_root = ax_fragment_root_.get();
434 EXPECT_EQ(native_view_accessible, fragment_root->ChildAtIndex(0));
435 EXPECT_EQ(nullptr, fragment_root->ChildAtIndex(1));
436
437 test_fragment_root_delegate_->child_ = nullptr;
438 EXPECT_EQ(nullptr, fragment_root->ChildAtIndex(0));
439}
440
441TEST_F(AXFragmentRootTest, TestGetParent) {
442 AXNodeData root;
443 root.id = 1;
444 Init(root);
445 InitFragmentRoot();
446
447 AXPlatformNodeDelegate* fragment_root = ax_fragment_root_.get();
448 EXPECT_EQ(nullptr, fragment_root->GetParent());
449
450 gfx::NativeViewAccessible native_view_accessible =
451 AXPlatformNodeFromNode(GetRootAsAXNode())->GetNativeViewAccessible();
452 test_fragment_root_delegate_->parent_ = native_view_accessible;
453 EXPECT_EQ(native_view_accessible, fragment_root->GetParent());
454}
455
456TEST_F(AXFragmentRootTest, TestGetPropertyValue) {
457 AXNodeData root;
458 root.id = 1;
459 Init(root);
460 InitFragmentRoot();
461
462 ComPtr<IRawElementProviderSimple> root_provider;
463 ax_fragment_root_->GetNativeViewAccessible()->QueryInterface(
464 IID_PPV_ARGS(&root_provider));
465
466 // IsControlElement and IsContentElement should follow the setting on the
467 // fragment root delegate.
468 test_fragment_root_delegate_->is_control_element_ = true;
470 EXPECT_HRESULT_SUCCEEDED(root_provider->GetPropertyValue(
471 UIA_IsControlElementPropertyId, result.Receive()));
472 EXPECT_EQ(result.type(), VT_BOOL);
473 EXPECT_EQ(result.ptr()->boolVal, VARIANT_TRUE);
474 EXPECT_HRESULT_SUCCEEDED(root_provider->GetPropertyValue(
475 UIA_IsContentElementPropertyId, result.Receive()));
476 EXPECT_EQ(result.type(), VT_BOOL);
477 EXPECT_EQ(result.ptr()->boolVal, VARIANT_TRUE);
478
479 test_fragment_root_delegate_->is_control_element_ = false;
480 EXPECT_HRESULT_SUCCEEDED(root_provider->GetPropertyValue(
481 UIA_IsControlElementPropertyId, result.Receive()));
482 EXPECT_EQ(result.type(), VT_BOOL);
483 EXPECT_EQ(result.ptr()->boolVal, VARIANT_FALSE);
484 EXPECT_HRESULT_SUCCEEDED(root_provider->GetPropertyValue(
485 UIA_IsContentElementPropertyId, result.Receive()));
486 EXPECT_EQ(result.type(), VT_BOOL);
487 EXPECT_EQ(result.ptr()->boolVal, VARIANT_FALSE);
488
489 // Other properties should return VT_EMPTY.
490 EXPECT_HRESULT_SUCCEEDED(root_provider->GetPropertyValue(
491 UIA_ControlTypePropertyId, result.Receive()));
492 EXPECT_EQ(result.type(), VT_EMPTY);
493}
494
495TEST_F(AXFragmentRootTest, TestUIAMultipleFragmentRoots) {
496 // Consider the following platform-neutral tree:
497 //
498 // N1
499 // _____/ \_____
500 // / \
501 // N2---N3---N4---N5
502 // / \ / \
503 // N6---N7 N8---N9
504 //
505 // N3 and N5 are nodes for which we need a fragment root. This will correspond
506 // to the following tree in UIA:
507 //
508 // U1
509 // _____/ \_____
510 // / \
511 // U2---R3---U4---R5
512 // | |
513 // U3 U5
514 // / \ / \
515 // U6---U7 U8---U9
516
517 ui::AXNodeData top_fragment_root_n1;
518 top_fragment_root_n1.id = 1;
519
520 ui::AXNodeData sibling_n2;
521 sibling_n2.id = 2;
522
523 ui::AXNodeData child_fragment_root_n3;
524 child_fragment_root_n3.id = 3;
525
526 ui::AXNodeData sibling_n6;
527 sibling_n6.id = 6;
528 ui::AXNodeData sibling_n7;
529 sibling_n7.id = 7;
530
531 child_fragment_root_n3.child_ids = {6, 7};
532
533 ui::AXNodeData sibling_n4;
534 sibling_n4.id = 4;
535
536 ui::AXNodeData child_fragment_root_n5;
537 child_fragment_root_n5.id = 5;
538
539 ui::AXNodeData sibling_n8;
540 sibling_n8.id = 8;
541 ui::AXNodeData sibling_n9;
542 sibling_n9.id = 9;
543
544 child_fragment_root_n5.child_ids = {8, 9};
545 top_fragment_root_n1.child_ids = {2, 3, 4, 5};
546
548 update.has_tree_data = true;
549 update.root_id = top_fragment_root_n1.id;
550 update.nodes = {top_fragment_root_n1,
551 sibling_n2,
552 child_fragment_root_n3,
553 sibling_n6,
554 sibling_n7,
555 sibling_n4,
556 child_fragment_root_n5,
557 sibling_n8,
558 sibling_n9};
559 update.tree_data.tree_id = ui::AXTreeID::CreateNewAXTreeID();
560
561 Init(update);
562 InitFragmentRoot();
563
564 AXNode* root_node = GetRootAsAXNode();
565
566 // Set up other fragment roots
567 AXNode* child_fragment_root_n3_node = root_node->children()[1];
568 std::unique_ptr<TestFragmentRootDelegate> n3_fragment_root_delegate =
569 std::make_unique<TestFragmentRootDelegate>();
570 std::unique_ptr<AXFragmentRootWin> n3_fragment_root(InitNodeAsFragmentRoot(
571 child_fragment_root_n3_node, n3_fragment_root_delegate.get()));
572
573 AXNode* child_fragment_root_n5_node = root_node->children()[3];
574 std::unique_ptr<TestFragmentRootDelegate> n5_fragment_root_delegate =
575 std::make_unique<TestFragmentRootDelegate>();
576 std::unique_ptr<AXFragmentRootWin> n5_fragment_root(InitNodeAsFragmentRoot(
577 child_fragment_root_n5_node, n5_fragment_root_delegate.get()));
578
579 // Test navigation from root fragment
580 ComPtr<IRawElementProviderFragmentRoot> root_fragment_root =
581 GetFragmentRoot();
582 ComPtr<IRawElementProviderFragment> root_fragment;
583 root_fragment_root.As(&root_fragment);
584
585 ComPtr<IRawElementProviderFragment> test_fragment;
586 EXPECT_HRESULT_SUCCEEDED(
587 root_fragment->Navigate(NavigateDirection_Parent, &test_fragment));
588 EXPECT_EQ(nullptr, test_fragment.Get());
589
590 EXPECT_HRESULT_SUCCEEDED(
591 root_fragment->Navigate(NavigateDirection_NextSibling, &test_fragment));
592 EXPECT_EQ(nullptr, test_fragment.Get());
593
594 EXPECT_HRESULT_SUCCEEDED(root_fragment->Navigate(
595 NavigateDirection_PreviousSibling, &test_fragment));
596 EXPECT_EQ(nullptr, test_fragment.Get());
597
598 EXPECT_HRESULT_SUCCEEDED(
599 root_fragment->Navigate(NavigateDirection_FirstChild, &test_fragment));
600 ComPtr<IUnknown> root_child_unknown = test_fragment_root_delegate_->child_;
601 ComPtr<IRawElementProviderFragment> root_child_fragment;
602 root_child_unknown.As(&root_child_fragment);
603 EXPECT_EQ(root_child_fragment.Get(), test_fragment.Get());
604
605 EXPECT_HRESULT_SUCCEEDED(
606 root_fragment->Navigate(NavigateDirection_LastChild, &test_fragment));
607 EXPECT_EQ(root_child_fragment.Get(), test_fragment.Get());
608
609 // Test navigation from first child root (R3)
610 ComPtr<IRawElementProviderFragmentRoot> n3_fragment_root_provider;
611 n3_fragment_root->GetNativeViewAccessible()->QueryInterface(
612 IID_PPV_ARGS(&n3_fragment_root_provider));
613
614 ComPtr<IRawElementProviderFragment> n3_fragment;
615 n3_fragment_root_provider.As(&n3_fragment);
616 EXPECT_HRESULT_SUCCEEDED(
617 n3_fragment->Navigate(NavigateDirection_Parent, &test_fragment));
618 EXPECT_EQ(root_child_fragment.Get(), test_fragment.Get());
619
620 AXNode* sibling_n2_node = root_node->children()[0];
621 EXPECT_HRESULT_SUCCEEDED(
622 n3_fragment->Navigate(NavigateDirection_PreviousSibling, &test_fragment));
623 EXPECT_EQ(IRawElementProviderFragmentFromNode(sibling_n2_node).Get(),
624 test_fragment.Get());
625
626 AXNode* sibling_n4_node = root_node->children()[2];
627 EXPECT_HRESULT_SUCCEEDED(
628 n3_fragment->Navigate(NavigateDirection_NextSibling, &test_fragment));
629 EXPECT_EQ(IRawElementProviderFragmentFromNode(sibling_n4_node).Get(),
630 test_fragment.Get());
631
632 EXPECT_HRESULT_SUCCEEDED(
633 n3_fragment->Navigate(NavigateDirection_FirstChild, &test_fragment));
634 EXPECT_EQ(
635 IRawElementProviderFragmentFromNode(child_fragment_root_n3_node).Get(),
636 test_fragment.Get());
637 EXPECT_HRESULT_SUCCEEDED(
638 n3_fragment->Navigate(NavigateDirection_LastChild, &test_fragment));
639 EXPECT_EQ(
640 IRawElementProviderFragmentFromNode(child_fragment_root_n3_node).Get(),
641 test_fragment.Get());
642
643 // Test navigation from second child root (R5)
644 ComPtr<IRawElementProviderFragmentRoot> n5_fragment_root_provider;
645 n5_fragment_root->GetNativeViewAccessible()->QueryInterface(
646 IID_PPV_ARGS(&n5_fragment_root_provider));
647
648 ComPtr<IRawElementProviderFragment> n5_fragment;
649 n5_fragment_root_provider.As(&n5_fragment);
650 EXPECT_HRESULT_SUCCEEDED(
651 n5_fragment->Navigate(NavigateDirection_Parent, &test_fragment));
652 EXPECT_EQ(root_child_fragment.Get(), test_fragment.Get());
653 EXPECT_HRESULT_SUCCEEDED(
654 n5_fragment->Navigate(NavigateDirection_NextSibling, &test_fragment));
655 EXPECT_EQ(nullptr, test_fragment.Get());
656 EXPECT_HRESULT_SUCCEEDED(
657 n5_fragment->Navigate(NavigateDirection_PreviousSibling, &test_fragment));
658 EXPECT_EQ(IRawElementProviderFragmentFromNode(sibling_n4_node).Get(),
659 test_fragment.Get());
660 EXPECT_HRESULT_SUCCEEDED(
661 n5_fragment->Navigate(NavigateDirection_FirstChild, &test_fragment));
662 EXPECT_EQ(
663 IRawElementProviderFragmentFromNode(child_fragment_root_n5_node).Get(),
664 test_fragment.Get());
665 EXPECT_HRESULT_SUCCEEDED(
666 n5_fragment->Navigate(NavigateDirection_LastChild, &test_fragment));
667 EXPECT_EQ(
668 IRawElementProviderFragmentFromNode(child_fragment_root_n5_node).Get(),
669 test_fragment.Get());
670}
671
672TEST_F(AXFragmentRootTest, TestFragmentRootMap) {
673 AXNodeData root;
674 root.id = 1;
675 Init(root);
676
677 // There should be nothing in the map before we create a fragment root.
678 // Call GetForAcceleratedWidget() first to ensure that querying for a
679 // fragment root doesn't inadvertently create an empty entry in the map
680 // (https://crbug.com/1071185).
682 gfx::kMockAcceleratedWidget));
684 GetRootIAccessible().Get()));
685
686 // After initializing a fragment root, we should be able to retrieve it using
687 // its accelerated widget, or as the parent of its child.
688 InitFragmentRoot();
689 EXPECT_EQ(ax_fragment_root_.get(), AXFragmentRootWin::GetForAcceleratedWidget(
690 gfx::kMockAcceleratedWidget));
691 EXPECT_EQ(ax_fragment_root_.get(), AXFragmentRootWin::GetFragmentRootParentOf(
692 GetRootIAccessible().Get()));
693
694 // After deleting a fragment root, it should no longer be reachable from the
695 // map.
696 ax_fragment_root_.reset();
698 gfx::kMockAcceleratedWidget));
700 GetRootIAccessible().Get()));
701}
702
703} // namespace ui
#define EXPECT_UIA_BSTR_EQ(node, property_id, expected)
void Set(const wchar_t *str)
AXFragmentRootTest()=default
AXFragmentRootTest & operator=(const AXFragmentRootTest &)=delete
AXFragmentRootTest(const AXFragmentRootTest &)=delete
~AXFragmentRootTest() override=default
static AXFragmentRootWin * GetForAcceleratedWidget(gfx::AcceleratedWidget widget)
static AXFragmentRootWin * GetFragmentRootParentOf(gfx::NativeViewAccessible accessible)
const std::vector< AXNode * > & children() const
Definition ax_node.h:113
virtual gfx::NativeViewAccessible ChildAtIndex(int index)=0
virtual int GetChildCount() const =0
virtual gfx::NativeViewAccessible GetParent()=0
static AXTreeID CreateNewAXTreeID()
Definition ax_tree_id.cc:47
static HRESULT CreateMockIRawElementProviderSimple(IRawElementProviderSimple **provider)
static std::unique_ptr< base::AutoReset< float > > SetScaleFactor(float value)
PROPERTYID GetUiaUniqueIdPropertyId() const
static const UiaRegistrarWin & GetInstance()
GAsyncResult * result
void Init()
std::u16string NumberToString16(float number)
UnimplementedNativeViewAccessible * NativeViewAccessible
TEST_F(AXPositionTest, Clone)
AXRelativeBounds relative_bounds
std::vector< int32_t > child_ids
void SetName(const std::string &name)
ax::mojom::Role role