Flutter Engine
 
Loading...
Searching...
No Matches
accessibility_bridge_unittests.cc
Go to the documentation of this file.
1// Copyright 2013 The Flutter 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
6
7#include "gmock/gmock.h"
8#include "gtest/gtest.h"
9
12
13namespace flutter {
14namespace testing {
15
16using ::testing::Contains;
17
19
21 int32_t id,
22 const char* label,
23 const std::vector<int32_t>* children = nullptr) {
24 return {
25 .id = id,
26 // NOLINTNEXTLINE(clang-analyzer-optin.core.EnumCastOutOfRange)
27 .flags__deprecated__ = static_cast<FlutterSemanticsFlag>(0),
28 // NOLINTNEXTLINE(clang-analyzer-optin.core.EnumCastOutOfRange)
29 .actions = static_cast<FlutterSemanticsAction>(0),
30 .text_selection_base = -1,
31 .text_selection_extent = -1,
32 .label = label,
33 .hint = "",
34 .value = "",
35 .increased_value = "",
36 .decreased_value = "",
37 .child_count = children ? children->size() : 0,
38 .children_in_traversal_order = children ? children->data() : nullptr,
39 .custom_accessibility_actions_count = 0,
40 .tooltip = "",
41 .flags2 = &kEmptyFlags,
42 };
43}
44
46 std::shared_ptr<TestAccessibilityBridge> bridge =
47 std::make_shared<TestAccessibilityBridge>();
48
49 std::vector<int32_t> children{1, 2};
50 FlutterSemanticsNode2 root = CreateSemanticsNode(0, "root", &children);
51 root.identifier = "identifier";
52 FlutterSemanticsNode2 child1 = CreateSemanticsNode(1, "child 1");
53 FlutterSemanticsNode2 child2 = CreateSemanticsNode(2, "child 2");
54
55 bridge->AddFlutterSemanticsNodeUpdate(root);
56 bridge->AddFlutterSemanticsNodeUpdate(child1);
57 bridge->AddFlutterSemanticsNodeUpdate(child2);
58 bridge->CommitUpdates();
59
60 auto root_node = bridge->GetFlutterPlatformNodeDelegateFromID(0).lock();
61 auto child1_node = bridge->GetFlutterPlatformNodeDelegateFromID(1).lock();
62 auto child2_node = bridge->GetFlutterPlatformNodeDelegateFromID(2).lock();
63 EXPECT_EQ(root_node->GetChildCount(), 2);
64 EXPECT_EQ(root_node->GetData().child_ids[0], 1);
65 EXPECT_EQ(root_node->GetData().child_ids[1], 2);
66 EXPECT_EQ(root_node->GetName(), "root");
67 EXPECT_EQ(root_node->GetAuthorUniqueId(), u"identifier");
68
69 EXPECT_EQ(child1_node->GetChildCount(), 0);
70 EXPECT_EQ(child1_node->GetName(), "child 1");
71
72 EXPECT_EQ(child2_node->GetChildCount(), 0);
73 EXPECT_EQ(child2_node->GetName(), "child 2");
74}
75
76// Flutter used to assume that the accessibility root had ID 0.
77// In a multi-view world, each view has its own accessibility root
78// with a globally unique node ID.
79TEST(AccessibilityBridgeTest, AccessibilityRootId) {
80 std::shared_ptr<TestAccessibilityBridge> bridge =
81 std::make_shared<TestAccessibilityBridge>();
82
83 std::vector<int32_t> children{456, 789};
84 FlutterSemanticsNode2 root = CreateSemanticsNode(123, "root", &children);
85 FlutterSemanticsNode2 child1 = CreateSemanticsNode(456, "child 1");
86 FlutterSemanticsNode2 child2 = CreateSemanticsNode(789, "child 2");
87
88 bridge->AddFlutterSemanticsNodeUpdate(root);
89 bridge->AddFlutterSemanticsNodeUpdate(child1);
90 bridge->AddFlutterSemanticsNodeUpdate(child2);
91 bridge->CommitUpdates();
92
93 auto root_node = bridge->GetFlutterPlatformNodeDelegateFromID(123).lock();
94 auto child1_node = bridge->GetFlutterPlatformNodeDelegateFromID(456).lock();
95 auto child2_node = bridge->GetFlutterPlatformNodeDelegateFromID(789).lock();
96 auto fake_delegate = bridge->GetFlutterPlatformNodeDelegateFromID(0).lock();
97
98 EXPECT_EQ(bridge->GetRootAsAXNode()->id(), 123);
99 EXPECT_EQ(bridge->RootDelegate()->GetName(), "root");
100
101 EXPECT_EQ(root_node->GetChildCount(), 2);
102 EXPECT_EQ(root_node->GetData().child_ids[0], 456);
103 EXPECT_EQ(root_node->GetData().child_ids[1], 789);
104 EXPECT_EQ(root_node->GetName(), "root");
105
106 EXPECT_EQ(child1_node->GetChildCount(), 0);
107 EXPECT_EQ(child1_node->GetName(), "child 1");
108
109 EXPECT_EQ(child2_node->GetChildCount(), 0);
110 EXPECT_EQ(child2_node->GetName(), "child 2");
111
112 ASSERT_FALSE(fake_delegate);
113}
114
115// Semantic nodes can be added in any order.
117 std::shared_ptr<TestAccessibilityBridge> bridge =
118 std::make_shared<TestAccessibilityBridge>();
119
120 std::vector<int32_t> root_children{34, 56};
121 std::vector<int32_t> child2_children{78};
122 std::vector<int32_t> child3_children{90};
123 FlutterSemanticsNode2 root = CreateSemanticsNode(12, "root", &root_children);
124 FlutterSemanticsNode2 child1 = CreateSemanticsNode(34, "child 1");
125 FlutterSemanticsNode2 child2 =
126 CreateSemanticsNode(56, "child 2", &child2_children);
127 FlutterSemanticsNode2 child3 =
128 CreateSemanticsNode(78, "child 3", &child3_children);
129 FlutterSemanticsNode2 child4 = CreateSemanticsNode(90, "child 4");
130
131 bridge->AddFlutterSemanticsNodeUpdate(child3);
132 bridge->AddFlutterSemanticsNodeUpdate(child2);
133 bridge->AddFlutterSemanticsNodeUpdate(root);
134 bridge->AddFlutterSemanticsNodeUpdate(child1);
135 bridge->AddFlutterSemanticsNodeUpdate(child4);
136 bridge->CommitUpdates();
137
138 auto root_node = bridge->GetFlutterPlatformNodeDelegateFromID(12).lock();
139 auto child1_node = bridge->GetFlutterPlatformNodeDelegateFromID(34).lock();
140 auto child2_node = bridge->GetFlutterPlatformNodeDelegateFromID(56).lock();
141 auto child3_node = bridge->GetFlutterPlatformNodeDelegateFromID(78).lock();
142 auto child4_node = bridge->GetFlutterPlatformNodeDelegateFromID(90).lock();
143
144 EXPECT_EQ(bridge->GetRootAsAXNode()->id(), 12);
145 EXPECT_EQ(bridge->RootDelegate()->GetName(), "root");
146
147 EXPECT_EQ(root_node->GetChildCount(), 2);
148 EXPECT_EQ(root_node->GetData().child_ids[0], 34);
149 EXPECT_EQ(root_node->GetData().child_ids[1], 56);
150 EXPECT_EQ(root_node->GetName(), "root");
151
152 EXPECT_EQ(child1_node->GetChildCount(), 0);
153 EXPECT_EQ(child1_node->GetName(), "child 1");
154
155 EXPECT_EQ(child2_node->GetChildCount(), 1);
156 EXPECT_EQ(child2_node->GetData().child_ids[0], 78);
157 EXPECT_EQ(child2_node->GetName(), "child 2");
158
159 EXPECT_EQ(child3_node->GetChildCount(), 1);
160 EXPECT_EQ(child3_node->GetData().child_ids[0], 90);
161 EXPECT_EQ(child3_node->GetName(), "child 3");
162
163 EXPECT_EQ(child4_node->GetChildCount(), 0);
164 EXPECT_EQ(child4_node->GetName(), "child 4");
165}
166
167TEST(AccessibilityBridgeTest, CanFireChildrenChangedCorrectly) {
168 std::shared_ptr<TestAccessibilityBridge> bridge =
169 std::make_shared<TestAccessibilityBridge>();
170
171 std::vector<int32_t> children{1};
172 FlutterSemanticsNode2 root = CreateSemanticsNode(0, "root", &children);
173 FlutterSemanticsNode2 child1 = CreateSemanticsNode(1, "child 1");
174
175 bridge->AddFlutterSemanticsNodeUpdate(root);
176 bridge->AddFlutterSemanticsNodeUpdate(child1);
177
178 bridge->CommitUpdates();
179
180 auto root_node = bridge->GetFlutterPlatformNodeDelegateFromID(0).lock();
181 auto child1_node = bridge->GetFlutterPlatformNodeDelegateFromID(1).lock();
182 EXPECT_EQ(root_node->GetChildCount(), 1);
183 EXPECT_EQ(root_node->GetData().child_ids[0], 1);
184 EXPECT_EQ(root_node->GetName(), "root");
185
186 EXPECT_EQ(child1_node->GetChildCount(), 0);
187 EXPECT_EQ(child1_node->GetName(), "child 1");
188 bridge->accessibility_events.clear();
189
190 // Add a child to root.
191 root.child_count = 2;
192 int32_t new_children[] = {1, 2};
193 root.children_in_traversal_order = new_children;
194
195 FlutterSemanticsNode2 child2 = CreateSemanticsNode(2, "child 2");
196
197 bridge->AddFlutterSemanticsNodeUpdate(root);
198 bridge->AddFlutterSemanticsNodeUpdate(child2);
199 bridge->CommitUpdates();
200
201 root_node = bridge->GetFlutterPlatformNodeDelegateFromID(0).lock();
202
203 EXPECT_EQ(root_node->GetChildCount(), 2);
204 EXPECT_EQ(root_node->GetData().child_ids[0], 1);
205 EXPECT_EQ(root_node->GetData().child_ids[1], 2);
206 EXPECT_EQ(bridge->accessibility_events.size(), size_t{2});
207 std::set<ui::AXEventGenerator::Event> actual_event{
208 bridge->accessibility_events.begin(), bridge->accessibility_events.end()};
209 EXPECT_THAT(actual_event,
211 EXPECT_THAT(actual_event,
213}
214
215TEST(AccessibilityBridgeTest, CanHandleSelectionChangeCorrectly) {
216 std::shared_ptr<TestAccessibilityBridge> bridge =
217 std::make_shared<TestAccessibilityBridge>();
219 auto flags = FlutterSemanticsFlags{
221 .is_text_field = true,
222 };
223 root.flags2 = &flags;
224
225 bridge->AddFlutterSemanticsNodeUpdate(root);
226 bridge->CommitUpdates();
227
228 const ui::AXTreeData& tree = bridge->GetAXTreeData();
230 bridge->accessibility_events.clear();
231
232 // Update the selection.
233 root.text_selection_base = 0;
234 root.text_selection_extent = 5;
235 bridge->AddFlutterSemanticsNodeUpdate(root);
236
237 bridge->CommitUpdates();
238
239 EXPECT_EQ(tree.sel_anchor_object_id, 0);
240 EXPECT_EQ(tree.sel_anchor_offset, 0);
241 EXPECT_EQ(tree.sel_focus_object_id, 0);
242 EXPECT_EQ(tree.sel_focus_offset, 5);
243 ASSERT_EQ(bridge->accessibility_events.size(), size_t{2});
244 EXPECT_EQ(bridge->accessibility_events[0],
246 EXPECT_EQ(bridge->accessibility_events[1],
248}
249
250TEST(AccessibilityBridgeTest, DoesNotAssignEditableRootToSelectableText) {
251 std::shared_ptr<TestAccessibilityBridge> bridge =
252 std::make_shared<TestAccessibilityBridge>();
254 auto flags = FlutterSemanticsFlags{
255 .is_text_field = true,
256 .is_read_only = true,
257 };
258 root.flags2 = &flags;
259
260 bridge->AddFlutterSemanticsNodeUpdate(root);
261 bridge->CommitUpdates();
262
263 auto root_node = bridge->GetFlutterPlatformNodeDelegateFromID(0).lock();
264
265 EXPECT_FALSE(root_node->GetData().GetBoolAttribute(
267}
268
269TEST(AccessibilityBridgeTest, SwitchHasSwitchRole) {
270 std::shared_ptr<TestAccessibilityBridge> bridge =
271 std::make_shared<TestAccessibilityBridge>();
273 auto flags = FlutterSemanticsFlags{
276 };
277
278 root.flags2 = &flags;
279 bridge->AddFlutterSemanticsNodeUpdate(root);
280 bridge->CommitUpdates();
281
282 auto root_node = bridge->GetFlutterPlatformNodeDelegateFromID(0).lock();
283 EXPECT_EQ(root_node->GetData().role, ax::mojom::Role::kSwitch);
284}
285
286TEST(AccessibilityBridgeTest, SliderHasSliderRole) {
287 std::shared_ptr<TestAccessibilityBridge> bridge =
288 std::make_shared<TestAccessibilityBridge>();
290 auto flags = FlutterSemanticsFlags{
293 .is_slider = true,
294 };
295
296 root.flags2 = &flags;
297
298 bridge->AddFlutterSemanticsNodeUpdate(root);
299 bridge->CommitUpdates();
300
301 auto root_node = bridge->GetFlutterPlatformNodeDelegateFromID(0).lock();
302 EXPECT_EQ(root_node->GetData().role, ax::mojom::Role::kSlider);
303}
304
305// Ensure that checkboxes have their checked status set apropriately
306// Previously, only Radios could have this flag updated
307// Resulted in the issue seen at
308// https://github.com/flutter/flutter/issues/96218
309// As this fix involved code run on all platforms, it is included here.
310TEST(AccessibilityBridgeTest, CanSetCheckboxChecked) {
311 std::shared_ptr<TestAccessibilityBridge> bridge =
312 std::make_shared<TestAccessibilityBridge>();
314 auto flags = FlutterSemanticsFlags{
316 };
317
318 root.flags2 = &flags;
319 bridge->AddFlutterSemanticsNodeUpdate(root);
320 bridge->CommitUpdates();
321
322 auto root_node = bridge->GetFlutterPlatformNodeDelegateFromID(0).lock();
323 EXPECT_EQ(root_node->GetData().role, ax::mojom::Role::kCheckBox);
324 EXPECT_EQ(root_node->GetData().GetCheckedState(),
326}
327
328// Verify that a node can be moved from one parent to another.
329TEST(AccessibilityBridgeTest, CanReparentNode) {
330 std::shared_ptr<TestAccessibilityBridge> bridge =
331 std::make_shared<TestAccessibilityBridge>();
332
333 std::vector<int32_t> root_children{1};
334 std::vector<int32_t> child1_children{2};
335 FlutterSemanticsNode2 root = CreateSemanticsNode(0, "root", &root_children);
336 FlutterSemanticsNode2 child1 =
337 CreateSemanticsNode(1, "child 1", &child1_children);
338 FlutterSemanticsNode2 child2 = CreateSemanticsNode(2, "child 2");
339
340 bridge->AddFlutterSemanticsNodeUpdate(root);
341 bridge->AddFlutterSemanticsNodeUpdate(child1);
342 bridge->AddFlutterSemanticsNodeUpdate(child2);
343 bridge->CommitUpdates();
344 bridge->accessibility_events.clear();
345
346 // Reparent child2 from child1 to the root.
347 child1.child_count = 0;
348 child1.children_in_traversal_order = nullptr;
349
350 int32_t new_root_children[] = {1, 2};
351 root.child_count = 2;
352 root.children_in_traversal_order = new_root_children;
353
354 bridge->AddFlutterSemanticsNodeUpdate(root);
355 bridge->AddFlutterSemanticsNodeUpdate(child1);
356 bridge->AddFlutterSemanticsNodeUpdate(child2);
357 bridge->CommitUpdates();
358
359 auto root_node = bridge->GetFlutterPlatformNodeDelegateFromID(0).lock();
360 auto child1_node = bridge->GetFlutterPlatformNodeDelegateFromID(1).lock();
361 auto child2_node = bridge->GetFlutterPlatformNodeDelegateFromID(2).lock();
362
363 EXPECT_EQ(root_node->GetChildCount(), 2);
364 EXPECT_EQ(root_node->GetData().child_ids[0], 1);
365 EXPECT_EQ(root_node->GetData().child_ids[1], 2);
366 EXPECT_EQ(root_node->GetName(), "root");
367
368 EXPECT_EQ(child1_node->GetChildCount(), 0);
369 EXPECT_EQ(child1_node->GetName(), "child 1");
370
371 EXPECT_EQ(child2_node->GetChildCount(), 0);
372 EXPECT_EQ(child2_node->GetName(), "child 2");
373
374 ASSERT_EQ(bridge->accessibility_events.size(), size_t{5});
375
376 // Child2 is moved from child1 to root.
377 EXPECT_THAT(bridge->accessibility_events,
379 EXPECT_THAT(bridge->accessibility_events,
381
382 // Child1 is no longer a parent. It loses its group role and disables its
383 // 'clip children' attribute.
384 EXPECT_THAT(
385 bridge->accessibility_events,
387 EXPECT_THAT(bridge->accessibility_events,
389}
390
391// Verify that multiple nodes can be moved to new parents.
392TEST(AccessibilityBridgeTest, CanReparentMultipleNodes) {
393 std::shared_ptr<TestAccessibilityBridge> bridge =
394 std::make_shared<TestAccessibilityBridge>();
395
396 int32_t root_id = 0;
397 int32_t intermediary1_id = 1;
398 int32_t intermediary2_id = 2;
399 int32_t leaf1_id = 3;
400 int32_t leaf2_id = 4;
401 int32_t leaf3_id = 5;
402
403 std::vector<int32_t> root_children{intermediary1_id, intermediary2_id};
404 std::vector<int32_t> intermediary1_children{leaf1_id};
405 std::vector<int32_t> intermediary2_children{leaf2_id, leaf3_id};
407 CreateSemanticsNode(root_id, "root", &root_children);
409 intermediary1_id, "intermediary 1", &intermediary1_children);
411 intermediary2_id, "intermediary 2", &intermediary2_children);
412 FlutterSemanticsNode2 leaf1 = CreateSemanticsNode(leaf1_id, "leaf 1");
413 FlutterSemanticsNode2 leaf2 = CreateSemanticsNode(leaf2_id, "leaf 2");
414 FlutterSemanticsNode2 leaf3 = CreateSemanticsNode(leaf3_id, "leaf 3");
415
416 bridge->AddFlutterSemanticsNodeUpdate(root);
417 bridge->AddFlutterSemanticsNodeUpdate(intermediary1);
418 bridge->AddFlutterSemanticsNodeUpdate(intermediary2);
419 bridge->AddFlutterSemanticsNodeUpdate(leaf1);
420 bridge->AddFlutterSemanticsNodeUpdate(leaf2);
421 bridge->AddFlutterSemanticsNodeUpdate(leaf3);
422 bridge->CommitUpdates();
423 bridge->accessibility_events.clear();
424
425 // Swap intermediary 1's and intermediary2's children.
426 int32_t new_intermediary1_children[] = {leaf2_id, leaf3_id};
427 intermediary1.child_count = 2;
428 intermediary1.children_in_traversal_order = new_intermediary1_children;
429
430 int32_t new_intermediary2_children[] = {leaf1_id};
431 intermediary2.child_count = 1;
432 intermediary2.children_in_traversal_order = new_intermediary2_children;
433
434 bridge->AddFlutterSemanticsNodeUpdate(intermediary1);
435 bridge->AddFlutterSemanticsNodeUpdate(intermediary2);
436 bridge->AddFlutterSemanticsNodeUpdate(leaf1);
437 bridge->AddFlutterSemanticsNodeUpdate(leaf2);
438 bridge->AddFlutterSemanticsNodeUpdate(leaf3);
439 bridge->CommitUpdates();
440
441 auto root_node = bridge->GetFlutterPlatformNodeDelegateFromID(root_id).lock();
442 auto intermediary1_node =
443 bridge->GetFlutterPlatformNodeDelegateFromID(intermediary1_id).lock();
444 auto intermediary2_node =
445 bridge->GetFlutterPlatformNodeDelegateFromID(intermediary2_id).lock();
446 auto leaf1_node =
447 bridge->GetFlutterPlatformNodeDelegateFromID(leaf1_id).lock();
448 auto leaf2_node =
449 bridge->GetFlutterPlatformNodeDelegateFromID(leaf2_id).lock();
450 auto leaf3_node =
451 bridge->GetFlutterPlatformNodeDelegateFromID(leaf3_id).lock();
452
453 EXPECT_EQ(root_node->GetChildCount(), 2);
454 EXPECT_EQ(root_node->GetData().child_ids[0], intermediary1_id);
455 EXPECT_EQ(root_node->GetData().child_ids[1], intermediary2_id);
456 EXPECT_EQ(root_node->GetName(), "root");
457
458 EXPECT_EQ(intermediary1_node->GetChildCount(), 2);
459 EXPECT_EQ(intermediary1_node->GetData().child_ids[0], leaf2_id);
460 EXPECT_EQ(intermediary1_node->GetData().child_ids[1], leaf3_id);
461 EXPECT_EQ(intermediary1_node->GetName(), "intermediary 1");
462
463 EXPECT_EQ(intermediary2_node->GetChildCount(), 1);
464 EXPECT_EQ(intermediary2_node->GetData().child_ids[0], leaf1_id);
465 EXPECT_EQ(intermediary2_node->GetName(), "intermediary 2");
466
467 EXPECT_EQ(leaf1_node->GetChildCount(), 0);
468 EXPECT_EQ(leaf1_node->GetName(), "leaf 1");
469
470 EXPECT_EQ(leaf2_node->GetChildCount(), 0);
471 EXPECT_EQ(leaf2_node->GetName(), "leaf 2");
472
473 EXPECT_EQ(leaf3_node->GetChildCount(), 0);
474 EXPECT_EQ(leaf3_node->GetName(), "leaf 3");
475
476 // Intermediary 1 and intermediary 2 have new children.
477 // Leaf 1, 2, and 3 are all moved.
478 ASSERT_EQ(bridge->accessibility_events.size(), size_t{5});
479 EXPECT_THAT(bridge->accessibility_events,
481 EXPECT_THAT(bridge->accessibility_events,
483}
484
485// Verify that a node with a child can be moved from one parent to another.
486TEST(AccessibilityBridgeTest, CanReparentNodeWithChild) {
487 std::shared_ptr<TestAccessibilityBridge> bridge =
488 std::make_shared<TestAccessibilityBridge>();
489
490 int32_t root_id = 0;
491 int32_t intermediary1_id = 1;
492 int32_t intermediary2_id = 2;
493 int32_t leaf1_id = 3;
494
495 std::vector<int32_t> root_children{intermediary1_id, intermediary2_id};
496 std::vector<int32_t> intermediary1_children{leaf1_id};
498 CreateSemanticsNode(root_id, "root", &root_children);
500 intermediary1_id, "intermediary 1", &intermediary1_children);
501 FlutterSemanticsNode2 intermediary2 =
502 CreateSemanticsNode(intermediary2_id, "intermediary 2");
503 FlutterSemanticsNode2 leaf1 = CreateSemanticsNode(leaf1_id, "leaf 1");
504
505 bridge->AddFlutterSemanticsNodeUpdate(root);
506 bridge->AddFlutterSemanticsNodeUpdate(intermediary1);
507 bridge->AddFlutterSemanticsNodeUpdate(intermediary2);
508 bridge->AddFlutterSemanticsNodeUpdate(leaf1);
509 bridge->CommitUpdates();
510 bridge->accessibility_events.clear();
511
512 // Move intermediary1 from root to intermediary 2.
513 int32_t new_root_children[] = {intermediary2_id};
514 root.child_count = 1;
515 root.children_in_traversal_order = new_root_children;
516
517 int32_t new_intermediary2_children[] = {intermediary1_id};
518 intermediary2.child_count = 1;
519 intermediary2.children_in_traversal_order = new_intermediary2_children;
520
521 bridge->AddFlutterSemanticsNodeUpdate(root);
522 bridge->AddFlutterSemanticsNodeUpdate(intermediary1);
523 bridge->AddFlutterSemanticsNodeUpdate(intermediary2);
524 bridge->AddFlutterSemanticsNodeUpdate(leaf1);
525 bridge->CommitUpdates();
526
527 auto root_node = bridge->GetFlutterPlatformNodeDelegateFromID(root_id).lock();
528 auto intermediary1_node =
529 bridge->GetFlutterPlatformNodeDelegateFromID(intermediary1_id).lock();
530 auto intermediary2_node =
531 bridge->GetFlutterPlatformNodeDelegateFromID(intermediary2_id).lock();
532 auto leaf1_node =
533 bridge->GetFlutterPlatformNodeDelegateFromID(leaf1_id).lock();
534
535 EXPECT_EQ(root_node->GetChildCount(), 1);
536 EXPECT_EQ(root_node->GetData().child_ids[0], intermediary2_id);
537 EXPECT_EQ(root_node->GetName(), "root");
538
539 EXPECT_EQ(intermediary2_node->GetChildCount(), 1);
540 EXPECT_EQ(intermediary2_node->GetData().child_ids[0], intermediary1_id);
541 EXPECT_EQ(intermediary2_node->GetName(), "intermediary 2");
542
543 EXPECT_EQ(intermediary1_node->GetChildCount(), 1);
544 EXPECT_EQ(intermediary1_node->GetData().child_ids[0], leaf1_id);
545 EXPECT_EQ(intermediary1_node->GetName(), "intermediary 1");
546
547 EXPECT_EQ(leaf1_node->GetChildCount(), 0);
548 EXPECT_EQ(leaf1_node->GetName(), "leaf 1");
549
550 ASSERT_EQ(bridge->accessibility_events.size(), size_t{5});
551
552 EXPECT_THAT(bridge->accessibility_events,
554 EXPECT_THAT(bridge->accessibility_events,
556
557 // Intermediary 2 becomes a parent node. It updates to group role and enables
558 // its 'clip children' attribute.
559 EXPECT_THAT(
560 bridge->accessibility_events,
562 EXPECT_THAT(bridge->accessibility_events,
564}
565
566TEST(AccessibilityBridgeTest, AXTreeManagerTest) {
567 std::shared_ptr<TestAccessibilityBridge> bridge =
568 std::make_shared<TestAccessibilityBridge>();
569
570 ui::AXTreeID tree_id = bridge->GetTreeID();
573 ASSERT_EQ(manager, static_cast<ui::AXTreeManager*>(bridge.get()));
574}
575
576TEST(AccessibilityBridgeTest, LineBreakingObjectTest) {
577 std::shared_ptr<TestAccessibilityBridge> bridge =
578 std::make_shared<TestAccessibilityBridge>();
579
580 const int32_t root_id = 0;
581
582 FlutterSemanticsNode2 root = CreateSemanticsNode(root_id, "root", {});
583
584 bridge->AddFlutterSemanticsNodeUpdate(root);
585 bridge->CommitUpdates();
586
587 auto root_node = bridge->GetFlutterPlatformNodeDelegateFromID(root_id).lock();
588 auto root_data = root_node->GetData();
589 EXPECT_TRUE(root_data.HasBoolAttribute(
591 EXPECT_TRUE(root_data.GetBoolAttribute(
593}
594
595} // namespace testing
596} // namespace flutter
flutter::FakeDelegate fake_delegate
static constexpr AXID kInvalidAXID
Definition ax_node.h:41
AXTreeManager * GetManager(AXTreeID tree_id)
static AXTreeManagerMap & GetInstance()
@ kFlutterCheckStateTrue
The semantics node is checked.
Definition embedder.h:284
FlutterSemanticsAction
Definition embedder.h:115
@ kFlutterTristateTrue
The property is applicable and its state is "true" or "on".
Definition embedder.h:275
@ kFlutterTristateFalse
The property is applicable and its state is "false" or "off".
Definition embedder.h:277
FlutterSemanticsFlag
Definition embedder.h:185
FlutterSemanticsNode2 CreateSemanticsNode(int32_t id, const char *label, const std::vector< int32_t > *children=nullptr)
TEST(NativeAssetsManagerTest, NoAvailableAssets)
FlutterSemanticsFlags kEmptyFlags
it will be possible to load the file into Perfetto s trace viewer use test Running tests that layout and measure text will not yield consistent results across various platforms Enabling this option will make font resolution default to the Ahem test font on all disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font manager
FlutterTristate is_enabled
Whether a semantic node is currently enabled.
Definition embedder.h:299
FlutterTristate is_focused
Whether the semantic node currently holds the user's focus.
Definition embedder.h:309
bool is_text_field
Whether the semantic node represents a text field.
Definition embedder.h:313
FlutterCheckState is_checked
Whether a semantics node is checked.
Definition embedder.h:295
const char * identifier
Definition embedder.h:1714
const int32_t * children_in_traversal_order
Array of child node IDs in traversal order. Has length child_count.
Definition embedder.h:1665
int32_t text_selection_extent
The position at which the text selection terminates.
Definition embedder.h:1625
int32_t id
The unique identifier for this node.
Definition embedder.h:1613
size_t child_count
The number of children this node has.
Definition embedder.h:1663
int32_t text_selection_base
The position at which the text selection originates.
Definition embedder.h:1623
FlutterSemanticsFlags * flags2
Definition embedder.h:1705
AXNode::AXID sel_anchor_object_id
AXNode::AXID sel_focus_object_id
int32_t sel_focus_offset
int32_t sel_anchor_offset
const uintptr_t id