Flutter Engine
The Flutter Engine
ax_event_generator_unittest.cc
Go to the documentation of this file.
1// Copyright 2017 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
6
7#include "base/logging.h"
8#include "gtest/gtest.h"
9
10#include "ax_enums.h"
11#include "ax_node.h"
12
13namespace ui {
14
15namespace {
16
17bool HasEvent(AXEventGenerator& src,
19 int32_t id) {
20 for (const auto& targeted_event : src) {
21 if (targeted_event.event_params.event == event_type &&
22 targeted_event.node->id() == id)
23 return true;
24 }
25 return false;
26}
27
28} // namespace
29
30TEST(AXEventGeneratorTest, LoadCompleteSameTree) {
31 AXTreeUpdate initial_state;
32 initial_state.root_id = 1;
33 initial_state.nodes.resize(1);
34 initial_state.nodes[0].id = 1;
35 initial_state.nodes[0].relative_bounds.bounds = gfx::RectF(0, 0, 800, 600);
36 initial_state.has_tree_data = true;
37 AXTree tree(initial_state);
38
39 AXEventGenerator event_generator(&tree);
40 AXTreeUpdate load_complete_update = initial_state;
41 load_complete_update.tree_data.loaded = true;
42
43 ASSERT_TRUE(tree.Unserialize(load_complete_update));
45 HasEvent(event_generator, AXEventGenerator::Event::LOAD_COMPLETE, 1));
46}
47
48TEST(AXEventGeneratorTest, LoadCompleteNewTree) {
49 AXTreeUpdate initial_state;
50 initial_state.root_id = 1;
51 initial_state.nodes.resize(1);
52 initial_state.nodes[0].id = 1;
53 initial_state.has_tree_data = true;
54 initial_state.tree_data.loaded = true;
55 AXTree tree(initial_state);
56
57 AXEventGenerator event_generator(&tree);
58 AXTreeUpdate load_complete_update;
59 load_complete_update.root_id = 2;
60 load_complete_update.nodes.resize(1);
61 load_complete_update.nodes[0].id = 2;
62 load_complete_update.nodes[0].relative_bounds.bounds =
63 gfx::RectF(0, 0, 800, 600);
64 load_complete_update.has_tree_data = true;
65 load_complete_update.tree_data.loaded = true;
66
67 ASSERT_TRUE(tree.Unserialize(load_complete_update));
69 HasEvent(event_generator, AXEventGenerator::Event::LOAD_COMPLETE, 2));
71 HasEvent(event_generator, AXEventGenerator::Event::SUBTREE_CREATED, 2));
72
73 // Load complete should not be emitted for sizeless roots.
74 load_complete_update.root_id = 3;
75 load_complete_update.nodes.resize(1);
76 load_complete_update.nodes[0].id = 3;
77 load_complete_update.nodes[0].relative_bounds.bounds = gfx::RectF(0, 0, 0, 0);
78 load_complete_update.has_tree_data = true;
79 load_complete_update.tree_data.loaded = true;
80
81 ASSERT_TRUE(tree.Unserialize(load_complete_update));
83 HasEvent(event_generator, AXEventGenerator::Event::SUBTREE_CREATED, 3));
84
85 // TODO(accessibility): http://crbug.com/888758
86 // Load complete should not be emitted for chrome-search URLs.
87 load_complete_update.root_id = 4;
88 load_complete_update.nodes.resize(1);
89 load_complete_update.nodes[0].id = 4;
90 load_complete_update.nodes[0].relative_bounds.bounds =
91 gfx::RectF(0, 0, 800, 600);
92 load_complete_update.nodes[0].AddStringAttribute(
93 ax::mojom::StringAttribute::kUrl, "chrome-search://foo");
94 load_complete_update.has_tree_data = true;
95 load_complete_update.tree_data.loaded = true;
96
97 ASSERT_TRUE(tree.Unserialize(load_complete_update));
99 HasEvent(event_generator, AXEventGenerator::Event::LOAD_COMPLETE, 4));
101 HasEvent(event_generator, AXEventGenerator::Event::SUBTREE_CREATED, 4));
102}
103
104TEST(AXEventGeneratorTest, LoadStart) {
105 AXTreeUpdate initial_state;
106 initial_state.root_id = 1;
107 initial_state.nodes.resize(1);
108 initial_state.nodes[0].id = 1;
109 initial_state.nodes[0].relative_bounds.bounds = gfx::RectF(0, 0, 800, 600);
110 initial_state.has_tree_data = true;
111 AXTree tree(initial_state);
112
113 AXEventGenerator event_generator(&tree);
114 AXTreeUpdate load_start_update;
115 load_start_update.root_id = 2;
116 load_start_update.nodes.resize(1);
117 load_start_update.nodes[0].id = 2;
118 load_start_update.nodes[0].relative_bounds.bounds =
119 gfx::RectF(0, 0, 800, 600);
120 load_start_update.has_tree_data = true;
121 load_start_update.tree_data.loaded = false;
122
123 ASSERT_TRUE(tree.Unserialize(load_start_update));
125 HasEvent(event_generator, AXEventGenerator::Event::LOAD_START, 2));
127 HasEvent(event_generator, AXEventGenerator::Event::SUBTREE_CREATED, 2));
128}
129
130TEST(AXEventGeneratorTest, DocumentSelectionChanged) {
131 AXTreeUpdate initial_state;
132 initial_state.root_id = 1;
133 initial_state.nodes.resize(1);
134 initial_state.nodes[0].id = 1;
135 initial_state.has_tree_data = true;
136 initial_state.tree_data.sel_focus_object_id = 1;
137 initial_state.tree_data.sel_focus_offset = 1;
138 AXTree tree(initial_state);
139
140 AXEventGenerator event_generator(&tree);
141 AXTreeUpdate update = initial_state;
142 update.tree_data.sel_focus_offset = 2;
143
144 ASSERT_TRUE(tree.Unserialize(update));
145 EXPECT_TRUE(HasEvent(event_generator,
147}
148
149TEST(AXEventGeneratorTest, DocumentTitleChanged) {
150 AXTreeUpdate initial_state;
151 initial_state.root_id = 1;
152 initial_state.nodes.resize(1);
153 initial_state.nodes[0].id = 1;
154 initial_state.has_tree_data = true;
155 initial_state.tree_data.title = "Before";
156 AXTree tree(initial_state);
157
158 AXEventGenerator event_generator(&tree);
159 AXTreeUpdate update = initial_state;
160 update.tree_data.title = "After";
161
162 ASSERT_TRUE(tree.Unserialize(update));
163 EXPECT_TRUE(HasEvent(event_generator,
165}
166
167// Do not emit a FOCUS_CHANGED event if focus_id is unchanged.
168TEST(AXEventGeneratorTest, FocusIdUnchanged) {
169 AXTreeUpdate initial_state;
170 initial_state.root_id = 1;
171 initial_state.nodes.resize(2);
172 initial_state.nodes[0].id = 1;
173 initial_state.nodes[0].child_ids.push_back(2);
174 initial_state.nodes[1].id = 2;
175 initial_state.has_tree_data = true;
176 initial_state.tree_data.focus_id = 1;
177 AXTree tree(initial_state);
178
179 AXEventGenerator event_generator(&tree);
180 AXTreeUpdate update = initial_state;
181 update.tree_data.focus_id = 1;
182
183 ASSERT_TRUE(tree.Unserialize(update));
184 EXPECT_FALSE(
185 HasEvent(event_generator, AXEventGenerator::Event::FOCUS_CHANGED, 1));
186}
187
188// Emit a FOCUS_CHANGED event if focus_id changes.
189TEST(AXEventGeneratorTest, FocusIdChanged) {
190 AXTreeUpdate initial_state;
191 initial_state.root_id = 1;
192 initial_state.nodes.resize(2);
193 initial_state.nodes[0].id = 1;
194 initial_state.nodes[0].child_ids.push_back(2);
195 initial_state.nodes[1].id = 2;
196 initial_state.has_tree_data = true;
197 initial_state.tree_data.focus_id = 1;
198 AXTree tree(initial_state);
199
200 AXEventGenerator event_generator(&tree);
201 AXTreeUpdate update = initial_state;
202 update.tree_data.focus_id = 2;
203
204 ASSERT_TRUE(tree.Unserialize(update));
206 HasEvent(event_generator, AXEventGenerator::Event::FOCUS_CHANGED, 2));
207}
208
209TEST(AXEventGeneratorTest, ExpandedAndRowCount) {
210 AXTreeUpdate initial_state;
211 initial_state.root_id = 1;
212 initial_state.nodes.resize(4);
213 initial_state.nodes[0].id = 1;
214 initial_state.nodes[0].role = ax::mojom::Role::kRootWebArea;
215 initial_state.nodes[0].child_ids.push_back(2);
216 initial_state.nodes[0].child_ids.push_back(4);
217 initial_state.nodes[1].id = 2;
218 initial_state.nodes[1].role = ax::mojom::Role::kTable;
219 initial_state.nodes[1].child_ids.push_back(3);
220 initial_state.nodes[2].id = 3;
221 initial_state.nodes[2].role = ax::mojom::Role::kRow;
222 initial_state.nodes[3].id = 4;
223 initial_state.nodes[3].role = ax::mojom::Role::kPopUpButton;
224 initial_state.nodes[3].AddState(ax::mojom::State::kExpanded);
225 AXTree tree(initial_state);
226
227 AXEventGenerator event_generator(&tree);
228 AXTreeUpdate update = initial_state;
229 update.nodes[2].AddState(ax::mojom::State::kExpanded);
230 update.nodes[3].state = 0;
231
232 ASSERT_TRUE(tree.Unserialize(update));
233 EXPECT_TRUE(HasEvent(event_generator, AXEventGenerator::Event::COLLAPSED, 4));
234 EXPECT_TRUE(HasEvent(event_generator, AXEventGenerator::Event::EXPANDED, 3));
236 HasEvent(event_generator, AXEventGenerator::Event::ROW_COUNT_CHANGED, 2));
238 HasEvent(event_generator, AXEventGenerator::Event::STATE_CHANGED, 3));
239 EXPECT_TRUE(HasEvent(event_generator,
241 3));
243 HasEvent(event_generator, AXEventGenerator::Event::STATE_CHANGED, 4));
244 EXPECT_TRUE(HasEvent(event_generator,
246 4));
247}
248
249TEST(AXEventGeneratorTest, SelectedAndSelectedChildren) {
250 AXTreeUpdate initial_state;
251 initial_state.root_id = 1;
252 initial_state.nodes.resize(4);
253 initial_state.nodes[0].id = 1;
254 initial_state.nodes[0].role = ax::mojom::Role::kRootWebArea;
255 initial_state.nodes[0].child_ids.push_back(2);
256 initial_state.nodes[0].child_ids.push_back(4);
257 initial_state.nodes[1].id = 2;
258 initial_state.nodes[1].role = ax::mojom::Role::kMenu;
259 initial_state.nodes[1].child_ids.push_back(3);
260 initial_state.nodes[2].id = 3;
261 initial_state.nodes[2].role = ax::mojom::Role::kMenuItem;
262 initial_state.nodes[3].id = 4;
263 initial_state.nodes[3].role = ax::mojom::Role::kListBoxOption;
264 initial_state.nodes[3].AddBoolAttribute(ax::mojom::BoolAttribute::kSelected,
265 true);
266 AXTree tree(initial_state);
267
268 AXEventGenerator event_generator(&tree);
269 AXTreeUpdate update = initial_state;
270 update.nodes[2].AddBoolAttribute(ax::mojom::BoolAttribute::kSelected, true);
271 update.nodes.pop_back();
272 update.nodes.emplace_back();
273 update.nodes[3].id = 4;
275 update.nodes[3].AddBoolAttribute(ax::mojom::BoolAttribute::kSelected, false);
276
277 ASSERT_TRUE(tree.Unserialize(update));
278 EXPECT_TRUE(HasEvent(event_generator,
281 HasEvent(event_generator, AXEventGenerator::Event::SELECTED_CHANGED, 3));
282 EXPECT_TRUE(HasEvent(event_generator,
284 3));
286 HasEvent(event_generator, AXEventGenerator::Event::SELECTED_CHANGED, 4));
287 EXPECT_TRUE(HasEvent(event_generator,
289 4));
290}
291
292TEST(AXEventGeneratorTest, StringValueChanged) {
293 AXTreeUpdate initial_state;
294 initial_state.root_id = 1;
295 initial_state.nodes.resize(1);
296 initial_state.nodes[0].id = 1;
297 initial_state.nodes[0].role = ax::mojom::Role::kTextField;
298 initial_state.nodes[0].AddStringAttribute(ax::mojom::StringAttribute::kValue,
299 "Before");
300 AXTree tree(initial_state);
301
302 AXEventGenerator event_generator(&tree);
303 AXTreeUpdate update = initial_state;
304 update.nodes[0].string_attributes.clear();
305 update.nodes[0].AddStringAttribute(ax::mojom::StringAttribute::kValue,
306 "After");
307
308 ASSERT_TRUE(tree.Unserialize(update));
310 HasEvent(event_generator, AXEventGenerator::Event::VALUE_CHANGED, 1));
311}
312
313TEST(AXEventGeneratorTest, FloatValueChanged) {
314 AXTreeUpdate initial_state;
315 initial_state.root_id = 1;
316 initial_state.nodes.resize(1);
317 initial_state.nodes[0].id = 1;
318 initial_state.nodes[0].role = ax::mojom::Role::kSlider;
319 initial_state.nodes[0].AddFloatAttribute(
321 AXTree tree(initial_state);
322
323 AXEventGenerator event_generator(&tree);
324 AXTreeUpdate update = initial_state;
325 update.nodes[0].float_attributes.clear();
326 update.nodes[0].AddFloatAttribute(ax::mojom::FloatAttribute::kValueForRange,
327 2.0);
328
329 ASSERT_TRUE(tree.Unserialize(update));
331 HasEvent(event_generator, AXEventGenerator::Event::VALUE_CHANGED, 1));
332}
333
334TEST(AXEventGeneratorTest, InvalidStatusChanged) {
335 AXTreeUpdate initial_state;
336 initial_state.root_id = 1;
337 initial_state.nodes.resize(1);
338 initial_state.nodes[0].id = 1;
339 initial_state.nodes[0].role = ax::mojom::Role::kTextField;
340 initial_state.nodes[0].AddStringAttribute(ax::mojom::StringAttribute::kValue,
341 "Text");
342 AXTree tree(initial_state);
343
344 AXEventGenerator event_generator(&tree);
345 AXTreeUpdate update = initial_state;
346 update.nodes[0].SetInvalidState(ax::mojom::InvalidState::kTrue);
347 ASSERT_TRUE(tree.Unserialize(update));
348 EXPECT_TRUE(HasEvent(event_generator,
350}
351
352TEST(AXEventGeneratorTest, AddLiveRegionAttribute) {
353 AXTreeUpdate initial_state;
354 initial_state.root_id = 1;
355 initial_state.nodes.resize(1);
356 initial_state.nodes[0].id = 1;
357 AXTree tree(initial_state);
358
359 AXEventGenerator event_generator(&tree);
360 AXTreeUpdate update = initial_state;
361 update.nodes[0].AddStringAttribute(ax::mojom::StringAttribute::kLiveStatus,
362 "polite");
363 ASSERT_TRUE(tree.Unserialize(update));
364 EXPECT_TRUE(HasEvent(event_generator,
366 EXPECT_TRUE(HasEvent(event_generator,
368
369 event_generator.ClearEvents();
370 update.nodes[0].AddStringAttribute(ax::mojom::StringAttribute::kLiveStatus,
371 "assertive");
372 ASSERT_TRUE(tree.Unserialize(update));
373 EXPECT_TRUE(HasEvent(event_generator,
375
376 event_generator.ClearEvents();
377 update.nodes[0].AddStringAttribute(ax::mojom::StringAttribute::kLiveStatus,
378 "off");
379
380 ASSERT_TRUE(tree.Unserialize(update));
381 EXPECT_TRUE(HasEvent(event_generator,
383}
384
385TEST(AXEventGeneratorTest, CheckedStateChanged) {
386 AXTreeUpdate initial_state;
387 initial_state.root_id = 1;
388 initial_state.nodes.resize(1);
389 initial_state.nodes[0].id = 1;
390 initial_state.nodes[0].role = ax::mojom::Role::kCheckBox;
391 AXTree tree(initial_state);
392
393 AXEventGenerator event_generator(&tree);
394 AXTreeUpdate update = initial_state;
395 update.nodes[0].SetCheckedState(ax::mojom::CheckedState::kTrue);
396 ASSERT_TRUE(tree.Unserialize(update));
397 EXPECT_TRUE(HasEvent(event_generator,
399 EXPECT_TRUE(HasEvent(event_generator,
401 1));
402}
403
404TEST(AXEventGeneratorTest, ActiveDescendantChanged) {
405 AXTreeUpdate initial_state;
406 initial_state.root_id = 1;
407 initial_state.nodes.resize(3);
408 initial_state.nodes[0].id = 1;
409 initial_state.nodes[0].role = ax::mojom::Role::kListBox;
410 initial_state.nodes[0].child_ids.push_back(2);
411 initial_state.nodes[0].child_ids.push_back(3);
412 initial_state.nodes[0].AddIntAttribute(
414 initial_state.nodes[1].id = 2;
415 initial_state.nodes[1].role = ax::mojom::Role::kListBoxOption;
416 initial_state.nodes[2].id = 3;
417 initial_state.nodes[2].role = ax::mojom::Role::kListBoxOption;
418 AXTree tree(initial_state);
419
420 AXEventGenerator event_generator(&tree);
421 AXTreeUpdate update = initial_state;
422 update.nodes[0].int_attributes.clear();
424 3);
425 ASSERT_TRUE(tree.Unserialize(update));
426 EXPECT_TRUE(HasEvent(event_generator,
428 EXPECT_TRUE(HasEvent(event_generator,
430}
431
432TEST(AXEventGeneratorTest, CreateAlertAndLiveRegion) {
433 AXTreeUpdate initial_state;
434 initial_state.root_id = 1;
435 initial_state.nodes.resize(1);
436 initial_state.nodes[0].id = 1;
437 AXTree tree(initial_state);
438
439 AXEventGenerator event_generator(&tree);
440 AXTreeUpdate update = initial_state;
441 update.nodes.resize(4);
442 update.nodes[0].child_ids.push_back(2);
443 update.nodes[0].child_ids.push_back(3);
444 update.nodes[0].child_ids.push_back(4);
445
446 update.nodes[1].id = 2;
447 update.nodes[1].AddStringAttribute(ax::mojom::StringAttribute::kLiveStatus,
448 "polite");
449
450 // Blink should automatically add aria-live="assertive" to elements with role
451 // kAlert, but we should fire an alert event regardless.
452 update.nodes[2].id = 3;
453 update.nodes[2].role = ax::mojom::Role::kAlert;
454
455 // Elements with role kAlertDialog will *not* usually have a live region
456 // status, but again, we should always fire an alert event.
457 update.nodes[3].id = 4;
459
460 ASSERT_TRUE(tree.Unserialize(update));
461 EXPECT_TRUE(HasEvent(event_generator, AXEventGenerator::Event::ALERT, 3));
462 EXPECT_TRUE(HasEvent(event_generator, AXEventGenerator::Event::ALERT, 4));
464 HasEvent(event_generator, AXEventGenerator::Event::CHILDREN_CHANGED, 1));
465 EXPECT_TRUE(HasEvent(event_generator,
468 HasEvent(event_generator, AXEventGenerator::Event::SUBTREE_CREATED, 2));
470 HasEvent(event_generator, AXEventGenerator::Event::SUBTREE_CREATED, 3));
472 HasEvent(event_generator, AXEventGenerator::Event::SUBTREE_CREATED, 4));
473}
474
475TEST(AXEventGeneratorTest, LiveRegionChanged) {
476 AXTreeUpdate initial_state;
477 initial_state.root_id = 1;
478 initial_state.nodes.resize(3);
479 initial_state.nodes[0].id = 1;
480 initial_state.nodes[0].AddStringAttribute(
482 initial_state.nodes[0].AddStringAttribute(
484 initial_state.nodes[0].child_ids.push_back(2);
485 initial_state.nodes[0].child_ids.push_back(3);
486 initial_state.nodes[1].id = 2;
487 initial_state.nodes[1].role = ax::mojom::Role::kStaticText;
488 initial_state.nodes[1].AddStringAttribute(
490 initial_state.nodes[1].AddStringAttribute(ax::mojom::StringAttribute::kName,
491 "Before 1");
492 initial_state.nodes[2].id = 3;
493 initial_state.nodes[2].role = ax::mojom::Role::kStaticText;
494 initial_state.nodes[2].AddStringAttribute(
496 initial_state.nodes[2].AddStringAttribute(ax::mojom::StringAttribute::kName,
497 "Before 2");
498 AXTree tree(initial_state);
499
500 AXEventGenerator event_generator(&tree);
501 AXTreeUpdate update = initial_state;
502 update.nodes[1].string_attributes.clear();
503 update.nodes[1].AddStringAttribute(
505 update.nodes[1].AddStringAttribute(ax::mojom::StringAttribute::kName,
506 "After 1");
507 update.nodes[2].string_attributes.clear();
508 update.nodes[2].AddStringAttribute(
510 update.nodes[2].AddStringAttribute(ax::mojom::StringAttribute::kName,
511 "After 2");
512
513 ASSERT_TRUE(tree.Unserialize(update));
514 EXPECT_TRUE(HasEvent(event_generator,
516 EXPECT_TRUE(HasEvent(event_generator,
518 EXPECT_TRUE(HasEvent(event_generator,
521 HasEvent(event_generator, AXEventGenerator::Event::NAME_CHANGED, 2));
523 HasEvent(event_generator, AXEventGenerator::Event::NAME_CHANGED, 3));
524}
525
526TEST(AXEventGeneratorTest, LiveRegionOnlyTextChanges) {
527 AXTreeUpdate initial_state;
528 initial_state.root_id = 1;
529 initial_state.nodes.resize(3);
530 initial_state.nodes[0].id = 1;
531 initial_state.nodes[0].AddStringAttribute(
533 initial_state.nodes[0].AddStringAttribute(
535 initial_state.nodes[0].child_ids.push_back(2);
536 initial_state.nodes[0].child_ids.push_back(3);
537 initial_state.nodes[1].id = 2;
538 initial_state.nodes[1].role = ax::mojom::Role::kStaticText;
539 initial_state.nodes[1].AddStringAttribute(
541 initial_state.nodes[1].AddStringAttribute(ax::mojom::StringAttribute::kName,
542 "Before 1");
543 initial_state.nodes[2].id = 3;
544 initial_state.nodes[2].role = ax::mojom::Role::kStaticText;
545 initial_state.nodes[2].AddStringAttribute(
547 initial_state.nodes[2].AddStringAttribute(ax::mojom::StringAttribute::kName,
548 "Before 2");
549 AXTree tree(initial_state);
550
551 AXEventGenerator event_generator(&tree);
552 AXTreeUpdate update = initial_state;
553 update.nodes[1].AddStringAttribute(ax::mojom::StringAttribute::kDescription,
554 "Description 1");
555 update.nodes[2].SetCheckedState(ax::mojom::CheckedState::kTrue);
556
557 // Note that we do NOT expect a LIVE_REGION_CHANGED event here, because
558 // the name did not change.
559 ASSERT_TRUE(tree.Unserialize(update));
560 EXPECT_TRUE(HasEvent(event_generator,
562 EXPECT_TRUE(HasEvent(event_generator,
564 3));
565 EXPECT_TRUE(HasEvent(event_generator,
567}
568
569TEST(AXEventGeneratorTest, BusyLiveRegionChanged) {
570 AXTreeUpdate initial_state;
571 initial_state.root_id = 1;
572 initial_state.nodes.resize(3);
573 initial_state.nodes[0].id = 1;
574 initial_state.nodes[0].AddStringAttribute(
576 initial_state.nodes[0].AddStringAttribute(
578 initial_state.nodes[0].AddBoolAttribute(ax::mojom::BoolAttribute::kBusy,
579 true);
580 initial_state.nodes[0].child_ids.push_back(2);
581 initial_state.nodes[0].child_ids.push_back(3);
582 initial_state.nodes[1].id = 2;
583 initial_state.nodes[1].role = ax::mojom::Role::kStaticText;
584 initial_state.nodes[1].AddStringAttribute(
586 initial_state.nodes[1].AddStringAttribute(ax::mojom::StringAttribute::kName,
587 "Before 1");
588 initial_state.nodes[2].id = 3;
589 initial_state.nodes[2].role = ax::mojom::Role::kStaticText;
590 initial_state.nodes[2].AddStringAttribute(
592 initial_state.nodes[2].AddStringAttribute(ax::mojom::StringAttribute::kName,
593 "Before 2");
594 AXTree tree(initial_state);
595
596 AXEventGenerator event_generator(&tree);
597 AXTreeUpdate update = initial_state;
598 update.nodes[1].string_attributes.clear();
599 update.nodes[1].AddStringAttribute(
601 update.nodes[1].AddStringAttribute(ax::mojom::StringAttribute::kName,
602 "After 1");
603 update.nodes[2].string_attributes.clear();
604 update.nodes[2].AddStringAttribute(
606 update.nodes[2].AddStringAttribute(ax::mojom::StringAttribute::kName,
607 "After 2");
608
609 ASSERT_TRUE(tree.Unserialize(update));
611 HasEvent(event_generator, AXEventGenerator::Event::NAME_CHANGED, 2));
613 HasEvent(event_generator, AXEventGenerator::Event::NAME_CHANGED, 3));
614}
615
616TEST(AXEventGeneratorTest, AddChild) {
617 AXTreeUpdate initial_state;
618 initial_state.root_id = 1;
619 initial_state.nodes.resize(2);
620 initial_state.nodes[0].id = 1;
621 initial_state.nodes[0].child_ids.push_back(2);
622 initial_state.nodes[1].id = 2;
623 AXTree tree(initial_state);
624
625 AXEventGenerator event_generator(&tree);
626 AXTreeUpdate update = initial_state;
627 update.nodes.resize(3);
628 update.nodes[0].child_ids.push_back(3);
629 update.nodes[2].id = 3;
630
631 ASSERT_TRUE(tree.Unserialize(update));
633 HasEvent(event_generator, AXEventGenerator::Event::CHILDREN_CHANGED, 1));
635 HasEvent(event_generator, AXEventGenerator::Event::SUBTREE_CREATED, 3));
636}
637
638TEST(AXEventGeneratorTest, RemoveChild) {
639 AXTreeUpdate initial_state;
640 initial_state.root_id = 1;
641 initial_state.nodes.resize(3);
642 initial_state.nodes[0].id = 1;
643 initial_state.nodes[0].child_ids.push_back(2);
644 initial_state.nodes[0].child_ids.push_back(3);
645 initial_state.nodes[1].id = 2;
646 initial_state.nodes[2].id = 3;
647 AXTree tree(initial_state);
648
649 AXEventGenerator event_generator(&tree);
650 AXTreeUpdate update = initial_state;
651 update.nodes.resize(2);
652 update.nodes[0].child_ids.clear();
653 update.nodes[0].child_ids.push_back(2);
654
655 ASSERT_TRUE(tree.Unserialize(update));
657 HasEvent(event_generator, AXEventGenerator::Event::CHILDREN_CHANGED, 1));
658}
659
660TEST(AXEventGeneratorTest, ReorderChildren) {
661 AXTreeUpdate initial_state;
662 initial_state.root_id = 1;
663 initial_state.nodes.resize(3);
664 initial_state.nodes[0].id = 1;
665 initial_state.nodes[0].child_ids.push_back(2);
666 initial_state.nodes[0].child_ids.push_back(3);
667 initial_state.nodes[1].id = 2;
668 initial_state.nodes[2].id = 3;
669 AXTree tree(initial_state);
670
671 AXEventGenerator event_generator(&tree);
672 AXTreeUpdate update = initial_state;
673 update.nodes[0].child_ids.clear();
674 update.nodes[0].child_ids.push_back(3);
675 update.nodes[0].child_ids.push_back(2);
676
677 ASSERT_TRUE(tree.Unserialize(update));
679 HasEvent(event_generator, AXEventGenerator::Event::CHILDREN_CHANGED, 1));
680}
681
682TEST(AXEventGeneratorTest, ScrollHorizontalPositionChanged) {
683 AXTreeUpdate initial_state;
684 initial_state.root_id = 1;
685 initial_state.nodes.resize(1);
686 initial_state.nodes[0].id = 1;
687 AXTree tree(initial_state);
688
689 AXEventGenerator event_generator(&tree);
690 AXTreeUpdate update = initial_state;
691 update.nodes[0].AddIntAttribute(ax::mojom::IntAttribute::kScrollX, 10);
694 HasEvent(event_generator,
696}
697
698TEST(AXEventGeneratorTest, ScrollVerticalPositionChanged) {
699 AXTreeUpdate initial_state;
700 initial_state.root_id = 1;
701 initial_state.nodes.resize(1);
702 initial_state.nodes[0].id = 1;
703 AXTree tree(initial_state);
704
705 AXEventGenerator event_generator(&tree);
706 AXTreeUpdate update = initial_state;
707 update.nodes[0].AddIntAttribute(ax::mojom::IntAttribute::kScrollY, 10);
708 ASSERT_TRUE(tree.Unserialize(update));
710 HasEvent(event_generator,
712}
713
714TEST(AXEventGeneratorTest, TextAttributeChanged) {
715 AXTreeUpdate initial_state;
716 initial_state.root_id = 1;
717 initial_state.nodes.resize(17);
718 initial_state.nodes[0].id = 1;
719 initial_state.nodes[0].child_ids = {2, 3, 4, 5, 6, 7, 8, 9,
720 10, 11, 12, 13, 14, 15, 16, 17};
721 initial_state.nodes[1].id = 2;
722 initial_state.nodes[2].id = 3;
723 initial_state.nodes[3].id = 4;
724 initial_state.nodes[4].id = 5;
725 initial_state.nodes[5].id = 6;
726 initial_state.nodes[6].id = 7;
727 initial_state.nodes[7].id = 8;
728 initial_state.nodes[8].id = 9;
729 initial_state.nodes[9].id = 10;
730 initial_state.nodes[10].id = 11;
731 initial_state.nodes[11].id = 12;
732 initial_state.nodes[12].id = 13;
733 initial_state.nodes[13].id = 14;
734 initial_state.nodes[14].id = 15;
735 initial_state.nodes[15].id = 16;
736 initial_state.nodes[16].id = 17;
737
738 // To test changing the start and end of existing markers.
739 initial_state.nodes[11].AddIntListAttribute(
741 {static_cast<int32_t>(ax::mojom::MarkerType::kTextMatch)});
742 initial_state.nodes[11].AddIntListAttribute(
744 initial_state.nodes[11].AddIntListAttribute(
746
747 AXTree tree(initial_state);
748
749 AXEventGenerator event_generator(&tree);
750 AXTreeUpdate update = initial_state;
751 update.nodes[1].AddIntAttribute(ax::mojom::IntAttribute::kColor, 0);
752 update.nodes[2].AddIntAttribute(ax::mojom::IntAttribute::kBackgroundColor, 0);
753 update.nodes[3].AddIntAttribute(
755 static_cast<int32_t>(ax::mojom::WritingDirection::kRtl));
756 update.nodes[4].AddIntAttribute(
758 static_cast<int32_t>(ax::mojom::TextPosition::kSuperscript));
759 update.nodes[5].AddIntAttribute(
761 static_cast<int32_t>(ax::mojom::TextStyle::kBold));
762 update.nodes[6].AddIntAttribute(
764 static_cast<int32_t>(ax::mojom::TextDecorationStyle::kSolid));
765 update.nodes[7].AddIntAttribute(
767 static_cast<int32_t>(ax::mojom::TextDecorationStyle::kWavy));
768 update.nodes[8].AddIntAttribute(
770 static_cast<int32_t>(ax::mojom::TextDecorationStyle::kDotted));
771 update.nodes[9].AddIntListAttribute(
773 {static_cast<int32_t>(ax::mojom::MarkerType::kSpelling)});
774 update.nodes[10].AddIntListAttribute(
776 {static_cast<int32_t>(ax::mojom::MarkerType::kGrammar)});
777 update.nodes[11].AddIntListAttribute(ax::mojom::IntListAttribute::kMarkerEnds,
778 {11});
779 update.nodes[12].AddIntListAttribute(
781 {static_cast<int32_t>(ax::mojom::MarkerType::kActiveSuggestion)});
782 update.nodes[13].AddIntListAttribute(
784 {static_cast<int32_t>(ax::mojom::MarkerType::kSuggestion)});
785 update.nodes[14].AddFloatAttribute(ax::mojom::FloatAttribute::kFontSize,
786 12.0f);
787 update.nodes[15].AddFloatAttribute(ax::mojom::FloatAttribute::kFontWeight,
788 600.0f);
789 update.nodes[16].AddStringAttribute(ax::mojom::StringAttribute::kFontFamily,
790 "sans");
791
792 ASSERT_TRUE(tree.Unserialize(update));
793 EXPECT_TRUE(HasEvent(event_generator,
795 EXPECT_TRUE(HasEvent(event_generator,
797 EXPECT_TRUE(HasEvent(event_generator,
799 EXPECT_TRUE(HasEvent(event_generator,
801 EXPECT_TRUE(HasEvent(event_generator,
803 EXPECT_TRUE(HasEvent(event_generator,
805 EXPECT_TRUE(HasEvent(event_generator,
807 EXPECT_TRUE(HasEvent(event_generator,
809 EXPECT_TRUE(HasEvent(event_generator,
811 EXPECT_TRUE(HasEvent(event_generator,
813 EXPECT_TRUE(HasEvent(event_generator,
815 EXPECT_TRUE(HasEvent(event_generator,
817 EXPECT_TRUE(HasEvent(event_generator,
819 EXPECT_TRUE(HasEvent(event_generator,
821 EXPECT_TRUE(HasEvent(event_generator,
823 EXPECT_TRUE(HasEvent(event_generator,
825}
826
827TEST(AXEventGeneratorTest, ObjectAttributeChanged) {
828 AXTreeUpdate initial_state;
829 initial_state.root_id = 1;
830 initial_state.nodes.resize(3);
831 initial_state.nodes[0].id = 1;
832 initial_state.nodes[0].child_ids = {2, 3};
833 initial_state.nodes[1].id = 2;
834 initial_state.nodes[2].id = 3;
835 AXTree tree(initial_state);
836
837 AXEventGenerator event_generator(&tree);
838 AXTreeUpdate update = initial_state;
839 update.nodes[1].AddIntAttribute(ax::mojom::IntAttribute::kTextAlign, 2);
840 update.nodes[2].AddFloatAttribute(ax::mojom::FloatAttribute::kTextIndent,
841 10.0f);
842 ASSERT_TRUE(tree.Unserialize(update));
844 HasEvent(event_generator,
847 HasEvent(event_generator,
849 EXPECT_TRUE(HasEvent(event_generator,
851 EXPECT_TRUE(HasEvent(event_generator,
853}
854
855TEST(AXEventGeneratorTest, OtherAttributeChanged) {
856 AXTreeUpdate initial_state;
857 initial_state.root_id = 1;
858 initial_state.nodes.resize(6);
859 initial_state.nodes[0].id = 1;
860 initial_state.nodes[0].child_ids.push_back(2);
861 initial_state.nodes[0].child_ids.push_back(3);
862 initial_state.nodes[0].child_ids.push_back(4);
863 initial_state.nodes[0].child_ids.push_back(5);
864 initial_state.nodes[0].child_ids.push_back(6);
865 initial_state.nodes[1].id = 2;
866 initial_state.nodes[2].id = 3;
867 initial_state.nodes[3].id = 4;
868 initial_state.nodes[4].id = 5;
869 initial_state.nodes[5].id = 6;
870 AXTree tree(initial_state);
871
872 AXEventGenerator event_generator(&tree);
873 AXTreeUpdate update = initial_state;
874 update.nodes[1].AddStringAttribute(ax::mojom::StringAttribute::kLanguage,
875 "de");
877 7);
878 update.nodes[3].AddFloatAttribute(ax::mojom::FloatAttribute::kFontSize,
879 12.0f);
880 update.nodes[4].AddBoolAttribute(ax::mojom::BoolAttribute::kModal, true);
881 std::vector<int> ids = {2};
882 update.nodes[5].AddIntListAttribute(ax::mojom::IntListAttribute::kControlsIds,
883 ids);
884 ASSERT_TRUE(tree.Unserialize(update));
886 HasEvent(event_generator, AXEventGenerator::Event::CONTROLS_CHANGED, 6));
888 HasEvent(event_generator, AXEventGenerator::Event::LANGUAGE_CHANGED, 2));
889 EXPECT_TRUE(HasEvent(event_generator,
891 EXPECT_TRUE(HasEvent(event_generator,
893 EXPECT_TRUE(HasEvent(event_generator,
895 EXPECT_TRUE(HasEvent(event_generator,
897}
898
899TEST(AXEventGeneratorTest, NameChanged) {
900 AXTreeUpdate initial_state;
901 initial_state.root_id = 1;
902 initial_state.nodes.resize(2);
903 initial_state.nodes[0].id = 1;
904 initial_state.nodes[0].child_ids.push_back(2);
905 initial_state.nodes[1].id = 2;
906 AXTree tree(initial_state);
907
908 AXEventGenerator event_generator(&tree);
909 AXTreeUpdate update = initial_state;
910 update.nodes[1].AddStringAttribute(ax::mojom::StringAttribute::kName,
911 "Hello");
912 ASSERT_TRUE(tree.Unserialize(update));
914 HasEvent(event_generator, AXEventGenerator::Event::NAME_CHANGED, 2));
915}
916
917TEST(AXEventGeneratorTest, DescriptionChanged) {
918 AXTreeUpdate initial_state;
919 initial_state.root_id = 1;
920 initial_state.nodes.resize(1);
921 initial_state.nodes[0].id = 1;
922 AXTree tree(initial_state);
923
924 AXEventGenerator event_generator(&tree);
925 AXTreeUpdate update = initial_state;
926 update.nodes[0].AddStringAttribute(ax::mojom::StringAttribute::kDescription,
927 "Hello");
928 ASSERT_TRUE(tree.Unserialize(update));
929 EXPECT_TRUE(HasEvent(event_generator,
931}
932
933TEST(AXEventGeneratorTest, RoleChanged) {
934 AXTreeUpdate initial_state;
935 initial_state.root_id = 1;
936 initial_state.nodes.resize(1);
937 initial_state.nodes[0].id = 1;
938 AXTree tree(initial_state);
939
940 AXEventGenerator event_generator(&tree);
941 AXTreeUpdate update = initial_state;
942 update.nodes[0].role = ax::mojom::Role::kCheckBox;
943 ASSERT_TRUE(tree.Unserialize(update));
945 HasEvent(event_generator, AXEventGenerator::Event::ROLE_CHANGED, 1));
946}
947
948TEST(AXEventGeneratorTest, MenuItemSelected) {
949 AXTreeUpdate initial_state;
950 initial_state.root_id = 1;
951 initial_state.nodes.resize(3);
952 initial_state.nodes[0].id = 1;
953 initial_state.nodes[0].role = ax::mojom::Role::kMenu;
954 initial_state.nodes[0].child_ids.push_back(2);
955 initial_state.nodes[0].child_ids.push_back(3);
956 initial_state.nodes[0].AddIntAttribute(
958 initial_state.nodes[1].id = 2;
959 initial_state.nodes[1].role = ax::mojom::Role::kMenuListOption;
960 initial_state.nodes[2].id = 3;
961 initial_state.nodes[2].role = ax::mojom::Role::kMenuListOption;
962 AXTree tree(initial_state);
963
964 AXEventGenerator event_generator(&tree);
965 AXTreeUpdate update = initial_state;
966 update.nodes[0].int_attributes.clear();
968 3);
969 ASSERT_TRUE(tree.Unserialize(update));
970 EXPECT_TRUE(HasEvent(event_generator,
972 EXPECT_TRUE(HasEvent(event_generator,
974 EXPECT_TRUE(HasEvent(event_generator,
976}
977
978TEST(AXEventGeneratorTest, NodeBecomesIgnored) {
979 AXTreeUpdate initial_state;
980 initial_state.root_id = 1;
981 initial_state.nodes.resize(5);
982 initial_state.nodes[0].id = 1;
983 initial_state.nodes[0].role = ax::mojom::Role::kRootWebArea;
984 initial_state.nodes[0].child_ids.push_back(2);
985 initial_state.nodes[1].id = 2;
986 initial_state.nodes[1].role = ax::mojom::Role::kArticle;
987 initial_state.nodes[1].child_ids.push_back(3);
988 initial_state.nodes[2].id = 3;
989 initial_state.nodes[2].role = ax::mojom::Role::kGroup;
990 initial_state.nodes[2].AddState(ax::mojom::State::kIgnored);
991 initial_state.nodes[2].child_ids.push_back(4);
992 initial_state.nodes[3].id = 4;
993 initial_state.nodes[3].role = ax::mojom::Role::kGroup;
994 initial_state.nodes[3].child_ids.push_back(5);
995 initial_state.nodes[4].id = 5;
996 initial_state.nodes[4].role = ax::mojom::Role::kStaticText;
997
998 AXTree tree(initial_state);
999
1000 AXEventGenerator event_generator(&tree);
1001 AXTreeUpdate update = initial_state;
1002 update.nodes[3].AddState(ax::mojom::State::kIgnored);
1003 ASSERT_TRUE(tree.Unserialize(update));
1005 HasEvent(event_generator, AXEventGenerator::Event::CHILDREN_CHANGED, 2));
1007 HasEvent(event_generator, AXEventGenerator::Event::IGNORED_CHANGED, 4));
1008}
1009
1010TEST(AXEventGeneratorTest, NodeBecomesIgnored2) {
1011 AXTreeUpdate initial_state;
1012 initial_state.root_id = 1;
1013 initial_state.nodes.resize(5);
1014 initial_state.nodes[0].id = 1;
1015 initial_state.nodes[0].role = ax::mojom::Role::kRootWebArea;
1016 initial_state.nodes[0].child_ids.push_back(2);
1017 initial_state.nodes[1].id = 2;
1018 initial_state.nodes[1].role = ax::mojom::Role::kArticle;
1019 initial_state.nodes[1].child_ids.push_back(3);
1020 initial_state.nodes[2].id = 3;
1021 initial_state.nodes[2].role = ax::mojom::Role::kGroup;
1022 initial_state.nodes[2].AddState(ax::mojom::State::kIgnored);
1023 initial_state.nodes[2].child_ids.push_back(4);
1024 initial_state.nodes[3].id = 4;
1025 initial_state.nodes[3].role = ax::mojom::Role::kGroup;
1026 initial_state.nodes[3].child_ids.push_back(5);
1027 initial_state.nodes[4].id = 5;
1028 initial_state.nodes[4].role = ax::mojom::Role::kStaticText;
1029
1030 AXTree tree(initial_state);
1031
1032 AXEventGenerator event_generator(&tree);
1033 AXTreeUpdate update = initial_state;
1034 // Marking as ignored should fire CHILDREN_CHANGED on 2
1035 update.nodes[3].AddState(ax::mojom::State::kIgnored);
1036 // Remove node id 5 so it also fires CHILDREN_CHANGED on 4.
1037 update.nodes.pop_back();
1038 update.nodes[3].child_ids.clear();
1039 ASSERT_TRUE(tree.Unserialize(update));
1041 HasEvent(event_generator, AXEventGenerator::Event::CHILDREN_CHANGED, 2));
1043 HasEvent(event_generator, AXEventGenerator::Event::IGNORED_CHANGED, 4));
1044}
1045
1046TEST(AXEventGeneratorTest, NodeBecomesUnignored) {
1047 AXTreeUpdate initial_state;
1048 initial_state.root_id = 1;
1049 initial_state.nodes.resize(5);
1050 initial_state.nodes[0].id = 1;
1051 initial_state.nodes[0].role = ax::mojom::Role::kRootWebArea;
1052 initial_state.nodes[0].child_ids.push_back(2);
1053 initial_state.nodes[1].id = 2;
1054 initial_state.nodes[1].role = ax::mojom::Role::kArticle;
1055 initial_state.nodes[1].child_ids.push_back(3);
1056 initial_state.nodes[2].id = 3;
1057 initial_state.nodes[2].role = ax::mojom::Role::kGroup;
1058 initial_state.nodes[2].AddState(ax::mojom::State::kIgnored);
1059 initial_state.nodes[2].child_ids.push_back(4);
1060 initial_state.nodes[3].id = 4;
1061 initial_state.nodes[3].role = ax::mojom::Role::kGroup;
1062 initial_state.nodes[3].AddState(ax::mojom::State::kIgnored);
1063 initial_state.nodes[3].child_ids.push_back(5);
1064 initial_state.nodes[4].id = 5;
1065 initial_state.nodes[4].role = ax::mojom::Role::kStaticText;
1066
1067 AXTree tree(initial_state);
1068
1069 AXEventGenerator event_generator(&tree);
1070 AXTreeUpdate update = initial_state;
1071 update.nodes[3].state = 0;
1072 ASSERT_TRUE(tree.Unserialize(update));
1074 HasEvent(event_generator, AXEventGenerator::Event::CHILDREN_CHANGED, 2));
1076 HasEvent(event_generator, AXEventGenerator::Event::SUBTREE_CREATED, 4));
1078 HasEvent(event_generator, AXEventGenerator::Event::IGNORED_CHANGED, 4));
1079}
1080
1081TEST(AXEventGeneratorTest, NodeBecomesUnignored2) {
1082 AXTreeUpdate initial_state;
1083 initial_state.root_id = 1;
1084 initial_state.nodes.resize(5);
1085 initial_state.nodes[0].id = 1;
1086 initial_state.nodes[0].role = ax::mojom::Role::kRootWebArea;
1087 initial_state.nodes[0].child_ids.push_back(2);
1088 initial_state.nodes[1].id = 2;
1089 initial_state.nodes[1].role = ax::mojom::Role::kArticle;
1090 initial_state.nodes[1].child_ids.push_back(3);
1091 initial_state.nodes[2].id = 3;
1092 initial_state.nodes[2].role = ax::mojom::Role::kGroup;
1093 initial_state.nodes[2].AddState(ax::mojom::State::kIgnored);
1094 initial_state.nodes[2].child_ids.push_back(4);
1095 initial_state.nodes[3].id = 4;
1096 initial_state.nodes[3].role = ax::mojom::Role::kGroup;
1097 initial_state.nodes[3].AddState(ax::mojom::State::kIgnored);
1098 initial_state.nodes[3].child_ids.push_back(5);
1099 initial_state.nodes[4].id = 5;
1100 initial_state.nodes[4].role = ax::mojom::Role::kStaticText;
1101
1102 AXTree tree(initial_state);
1103
1104 AXEventGenerator event_generator(&tree);
1105 AXTreeUpdate update = initial_state;
1106 // Marking as no longer ignored should fire CHILDREN_CHANGED on 2
1107 update.nodes[3].state = 0;
1108 // Remove node id 5 so it also fires CHILDREN_CHANGED on 4.
1109 update.nodes.pop_back();
1110 update.nodes[3].child_ids.clear();
1111 ASSERT_TRUE(tree.Unserialize(update));
1113 HasEvent(event_generator, AXEventGenerator::Event::CHILDREN_CHANGED, 2));
1115 HasEvent(event_generator, AXEventGenerator::Event::SUBTREE_CREATED, 4));
1117 HasEvent(event_generator, AXEventGenerator::Event::IGNORED_CHANGED, 4));
1118}
1119
1120TEST(AXEventGeneratorTest, SubtreeBecomesUnignored) {
1121 AXTreeUpdate initial_state;
1122 initial_state.root_id = 1;
1123 initial_state.nodes.resize(3);
1124 initial_state.nodes[0].id = 1;
1125 initial_state.nodes[0].role = ax::mojom::Role::kRootWebArea;
1126 initial_state.nodes[0].child_ids.push_back(2);
1127 initial_state.nodes[1].id = 2;
1128 initial_state.nodes[1].role = ax::mojom::Role::kArticle;
1129 initial_state.nodes[1].AddState(ax::mojom::State::kIgnored);
1130 initial_state.nodes[1].child_ids.push_back(3);
1131 initial_state.nodes[2].id = 3;
1132 initial_state.nodes[2].role = ax::mojom::Role::kGroup;
1133 initial_state.nodes[2].AddState(ax::mojom::State::kIgnored);
1134
1135 AXTree tree(initial_state);
1136
1137 AXEventGenerator event_generator(&tree);
1138 AXTreeUpdate update = initial_state;
1139 update.nodes[1].RemoveState(ax::mojom::State::kIgnored);
1140 update.nodes[2].RemoveState(ax::mojom::State::kIgnored);
1141 ASSERT_TRUE(tree.Unserialize(update));
1143 HasEvent(event_generator, AXEventGenerator::Event::CHILDREN_CHANGED, 1));
1145 HasEvent(event_generator, AXEventGenerator::Event::SUBTREE_CREATED, 2));
1147 HasEvent(event_generator, AXEventGenerator::Event::IGNORED_CHANGED, 2));
1148}
1149
1150TEST(AXEventGeneratorTest, TwoNodesSwapIgnored) {
1151 AXTreeUpdate initial_state;
1152 initial_state.root_id = 1;
1153 initial_state.nodes.resize(3);
1154 initial_state.nodes[0].id = 1;
1155 initial_state.nodes[0].role = ax::mojom::Role::kRootWebArea;
1156 initial_state.nodes[0].child_ids.push_back(2);
1157 initial_state.nodes[1].id = 2;
1158 initial_state.nodes[1].role = ax::mojom::Role::kArticle;
1159 initial_state.nodes[1].child_ids.push_back(3);
1160 initial_state.nodes[2].id = 3;
1161 initial_state.nodes[2].role = ax::mojom::Role::kGroup;
1162 initial_state.nodes[2].AddState(ax::mojom::State::kIgnored);
1163
1164 AXTree tree(initial_state);
1165
1166 AXEventGenerator event_generator(&tree);
1167 AXTreeUpdate update = initial_state;
1168 update.nodes[1].AddState(ax::mojom::State::kIgnored);
1169 update.nodes[2].RemoveState(ax::mojom::State::kIgnored);
1170 ASSERT_TRUE(tree.Unserialize(update));
1172 HasEvent(event_generator, AXEventGenerator::Event::CHILDREN_CHANGED, 1));
1174 HasEvent(event_generator, AXEventGenerator::Event::IGNORED_CHANGED, 2));
1176 HasEvent(event_generator, AXEventGenerator::Event::IGNORED_CHANGED, 3));
1178 HasEvent(event_generator, AXEventGenerator::Event::SUBTREE_CREATED, 3));
1179}
1180
1181TEST(AXEventGeneratorTest, TwoNodesSwapIgnored2) {
1182 AXTreeUpdate initial_state;
1183 initial_state.root_id = 1;
1184 initial_state.nodes.resize(3);
1185 initial_state.nodes[0].id = 1;
1186 initial_state.nodes[0].role = ax::mojom::Role::kRootWebArea;
1187 initial_state.nodes[0].child_ids.push_back(2);
1188 initial_state.nodes[1].id = 2;
1189 initial_state.nodes[1].role = ax::mojom::Role::kArticle;
1190 initial_state.nodes[1].AddState(ax::mojom::State::kIgnored);
1191 initial_state.nodes[1].child_ids.push_back(3);
1192 initial_state.nodes[2].id = 3;
1193 initial_state.nodes[2].role = ax::mojom::Role::kGroup;
1194
1195 AXTree tree(initial_state);
1196
1197 AXEventGenerator event_generator(&tree);
1198 AXTreeUpdate update = initial_state;
1199 update.nodes[1].RemoveState(ax::mojom::State::kIgnored);
1200 update.nodes[2].AddState(ax::mojom::State::kIgnored);
1201 ASSERT_TRUE(tree.Unserialize(update));
1203 HasEvent(event_generator, AXEventGenerator::Event::CHILDREN_CHANGED, 1));
1205 HasEvent(event_generator, AXEventGenerator::Event::IGNORED_CHANGED, 2));
1207 HasEvent(event_generator, AXEventGenerator::Event::IGNORED_CHANGED, 3));
1209 HasEvent(event_generator, AXEventGenerator::Event::SUBTREE_CREATED, 2));
1210}
1211
1212TEST(AXEventGeneratorTest, IgnoredChangedFiredOnAncestorOnly1) {
1213 // BEFORE
1214 // 1 (IGN)
1215 // / \
1216 // 2 3 (IGN)
1217
1218 // AFTER
1219 // 1 (IGN)
1220 // / \
1221 // 2 (IGN) 3
1222 // IGNORED_CHANGED expected on #2, #3
1223
1224 AXTreeUpdate initial_state;
1225 initial_state.root_id = 1;
1226 initial_state.nodes.resize(3);
1227 initial_state.nodes[0].id = 1;
1228 initial_state.nodes[0].role = ax::mojom::Role::kRootWebArea;
1229 initial_state.nodes[0].AddState(ax::mojom::State::kIgnored);
1230 initial_state.nodes[0].child_ids = {2, 3};
1231
1232 initial_state.nodes[1].id = 2;
1233 initial_state.nodes[1].role = ax::mojom::Role::kStaticText;
1234
1235 initial_state.nodes[2].id = 3;
1236 initial_state.nodes[2].role = ax::mojom::Role::kStaticText;
1237 initial_state.nodes[2].AddState(ax::mojom::State::kIgnored);
1238
1239 AXTree tree(initial_state);
1240
1241 AXEventGenerator event_generator(&tree);
1242 AXTreeUpdate update = initial_state;
1243 update.nodes[1].AddState(ax::mojom::State::kIgnored);
1244 update.nodes[2].RemoveState(ax::mojom::State::kIgnored);
1245 ASSERT_TRUE(tree.Unserialize(update));
1247 HasEvent(event_generator, AXEventGenerator::Event::IGNORED_CHANGED, 2));
1249 HasEvent(event_generator, AXEventGenerator::Event::IGNORED_CHANGED, 3));
1251 HasEvent(event_generator, AXEventGenerator::Event::SUBTREE_CREATED, 3));
1252}
1253
1254TEST(AXEventGeneratorTest, IgnoredChangedFiredOnAncestorOnly2) {
1255 // BEFORE
1256 // 1
1257 // |
1258 // 2
1259 // / \
1260 // 3 4 (IGN)
1261
1262 // AFTER
1263 // 1
1264 // |
1265 // 2 ___
1266 // / \
1267 // 3 (IGN) 4
1268 // IGNORED_CHANGED expected on #3, #4
1269
1270 AXTreeUpdate initial_state;
1271 initial_state.root_id = 1;
1272 initial_state.nodes.resize(4);
1273 initial_state.nodes[0].id = 1;
1274 initial_state.nodes[0].role = ax::mojom::Role::kRootWebArea;
1275 initial_state.nodes[0].child_ids = {2};
1276
1277 initial_state.nodes[1].id = 2;
1278 initial_state.nodes[1].role = ax::mojom::Role::kGroup;
1279 initial_state.nodes[1].child_ids = {3, 4};
1280
1281 initial_state.nodes[2].id = 3;
1282 initial_state.nodes[2].role = ax::mojom::Role::kStaticText;
1283
1284 initial_state.nodes[3].id = 4;
1285 initial_state.nodes[3].role = ax::mojom::Role::kStaticText;
1286 initial_state.nodes[3].AddState(ax::mojom::State::kIgnored);
1287
1288 AXTree tree(initial_state);
1289
1290 AXEventGenerator event_generator(&tree);
1291 AXTreeUpdate update = initial_state;
1292 update.nodes[2].AddState(ax::mojom::State::kIgnored);
1293 update.nodes[3].RemoveState(ax::mojom::State::kIgnored);
1294 ASSERT_TRUE(tree.Unserialize(update));
1296 HasEvent(event_generator, AXEventGenerator::Event::CHILDREN_CHANGED, 2));
1298 HasEvent(event_generator, AXEventGenerator::Event::IGNORED_CHANGED, 3));
1300 HasEvent(event_generator, AXEventGenerator::Event::IGNORED_CHANGED, 4));
1302 HasEvent(event_generator, AXEventGenerator::Event::SUBTREE_CREATED, 4));
1303}
1304
1305TEST(AXEventGeneratorTest, IgnoredChangedFiredOnAncestorOnly3) {
1306 // BEFORE
1307 // 1
1308 // |
1309 // 2 ___
1310 // / \
1311 // 3 (IGN) 4
1312
1313 // AFTER
1314 // 1 (IGN)
1315 // |
1316 // 2
1317 // / \
1318 // 3 4 (IGN)
1319 // IGNORED_CHANGED expected on #1, #3
1320
1321 AXTreeUpdate initial_state;
1322 initial_state.root_id = 1;
1323 initial_state.nodes.resize(4);
1324 initial_state.nodes[0].id = 1;
1325 initial_state.nodes[0].role = ax::mojom::Role::kRootWebArea;
1326 initial_state.nodes[0].child_ids = {2};
1327
1328 initial_state.nodes[1].id = 2;
1329 initial_state.nodes[1].role = ax::mojom::Role::kGroup;
1330 initial_state.nodes[1].child_ids = {3, 4};
1331
1332 initial_state.nodes[2].id = 3;
1333 initial_state.nodes[2].role = ax::mojom::Role::kStaticText;
1334 initial_state.nodes[2].AddState(ax::mojom::State::kIgnored);
1335
1336 initial_state.nodes[3].id = 4;
1337 initial_state.nodes[3].role = ax::mojom::Role::kStaticText;
1338
1339 AXTree tree(initial_state);
1340
1341 AXEventGenerator event_generator(&tree);
1342 AXTreeUpdate update = initial_state;
1343 update.nodes[0].AddState(ax::mojom::State::kIgnored);
1344 update.nodes[2].RemoveState(ax::mojom::State::kIgnored);
1345 update.nodes[3].AddState(ax::mojom::State::kIgnored);
1346 ASSERT_TRUE(tree.Unserialize(update));
1348 HasEvent(event_generator, AXEventGenerator::Event::CHILDREN_CHANGED, 2));
1350 HasEvent(event_generator, AXEventGenerator::Event::IGNORED_CHANGED, 1));
1352 HasEvent(event_generator, AXEventGenerator::Event::IGNORED_CHANGED, 3));
1354 HasEvent(event_generator, AXEventGenerator::Event::SUBTREE_CREATED, 3));
1355}
1356
1357TEST(AXEventGeneratorTest, IgnoredChangedFiredOnAncestorOnly4) {
1358 // BEFORE
1359 // 1 (IGN)
1360 // |
1361 // 2
1362 // |
1363 // 3 (IGN)
1364 // |
1365 // 4 (IGN)
1366 // |
1367 // ____ 5 _____
1368 // / | \
1369 // 6 (IGN) 7 (IGN) 8
1370
1371 // AFTER
1372 // 1 (IGN)
1373 // |
1374 // 2
1375 // |
1376 // 3 (IGN)
1377 // |
1378 // 4 (IGN)
1379 // |
1380 // ____ 5 _____
1381 // / | \
1382 // 6 7 8 (IGN)
1383
1384 // IGNORED_CHANGED expected on #6, #7, #8
1385
1386 AXTreeUpdate initial_state;
1387 initial_state.root_id = 1;
1388 initial_state.nodes.resize(8);
1389 initial_state.nodes[0].id = 1;
1390 initial_state.nodes[0].role = ax::mojom::Role::kRootWebArea;
1391 initial_state.nodes[0].child_ids = {2};
1392
1393 initial_state.nodes[1].id = 2;
1394 initial_state.nodes[1].role = ax::mojom::Role::kGroup;
1395 initial_state.nodes[1].child_ids = {3};
1396
1397 initial_state.nodes[2].id = 3;
1398 initial_state.nodes[2].role = ax::mojom::Role::kGroup;
1399 initial_state.nodes[2].child_ids = {4};
1400 initial_state.nodes[2].AddState(ax::mojom::State::kIgnored);
1401
1402 initial_state.nodes[3].id = 4;
1403 initial_state.nodes[3].role = ax::mojom::Role::kGroup;
1404 initial_state.nodes[3].child_ids = {5};
1405 initial_state.nodes[3].AddState(ax::mojom::State::kIgnored);
1406
1407 initial_state.nodes[4].id = 5;
1408 initial_state.nodes[4].role = ax::mojom::Role::kGroup;
1409 initial_state.nodes[4].child_ids = {6, 7, 8};
1410
1411 initial_state.nodes[5].id = 6;
1412 initial_state.nodes[5].role = ax::mojom::Role::kStaticText;
1413 initial_state.nodes[5].AddState(ax::mojom::State::kIgnored);
1414
1415 initial_state.nodes[6].id = 7;
1416 initial_state.nodes[6].role = ax::mojom::Role::kStaticText;
1417 initial_state.nodes[6].AddState(ax::mojom::State::kIgnored);
1418
1419 initial_state.nodes[7].id = 8;
1420 initial_state.nodes[7].role = ax::mojom::Role::kStaticText;
1421
1422 AXTree tree(initial_state);
1423
1424 AXEventGenerator event_generator(&tree);
1425 AXTreeUpdate update = initial_state;
1426 update.nodes[5].RemoveState(ax::mojom::State::kIgnored);
1427 update.nodes[6].RemoveState(ax::mojom::State::kIgnored);
1428 update.nodes[7].AddState(ax::mojom::State::kIgnored);
1429 ASSERT_TRUE(tree.Unserialize(update));
1431 HasEvent(event_generator, AXEventGenerator::Event::CHILDREN_CHANGED, 5));
1433 HasEvent(event_generator, AXEventGenerator::Event::SUBTREE_CREATED, 6));
1435 HasEvent(event_generator, AXEventGenerator::Event::SUBTREE_CREATED, 7));
1437 HasEvent(event_generator, AXEventGenerator::Event::IGNORED_CHANGED, 6));
1439 HasEvent(event_generator, AXEventGenerator::Event::IGNORED_CHANGED, 7));
1441 HasEvent(event_generator, AXEventGenerator::Event::IGNORED_CHANGED, 8));
1442}
1443
1444TEST(AXEventGeneratorTest, IgnoredChangedFiredOnAncestorOnly5) {
1445 // BEFORE
1446 // 1
1447 // |
1448 // 2
1449 // |
1450 // 3 (IGN)
1451 // |
1452 // 4 (IGN)
1453 // |
1454 // ____ 5 _____
1455 // / | \
1456 // 6 (IGN) 7 8
1457
1458 // AFTER
1459 // 1 (IGN)
1460 // |
1461 // 2
1462 // |
1463 // 3 (IGN)
1464 // |
1465 // 4 (IGN)
1466 // |
1467 // ____ 5 _____
1468 // / | \
1469 // 6 7 (IGN) 8 (IGN)
1470
1471 // IGNORED_CHANGED expected on #1, #6
1472
1473 AXTreeUpdate initial_state;
1474 initial_state.root_id = 1;
1475 initial_state.nodes.resize(8);
1476 initial_state.nodes[0].id = 1;
1477 initial_state.nodes[0].role = ax::mojom::Role::kRootWebArea;
1478 initial_state.nodes[0].child_ids = {2};
1479
1480 initial_state.nodes[1].id = 2;
1481 initial_state.nodes[1].role = ax::mojom::Role::kGroup;
1482 initial_state.nodes[1].child_ids = {3};
1483
1484 initial_state.nodes[2].id = 3;
1485 initial_state.nodes[2].role = ax::mojom::Role::kGroup;
1486 initial_state.nodes[2].child_ids = {4};
1487 initial_state.nodes[2].AddState(ax::mojom::State::kIgnored);
1488
1489 initial_state.nodes[3].id = 4;
1490 initial_state.nodes[3].role = ax::mojom::Role::kGroup;
1491 initial_state.nodes[3].child_ids = {5};
1492 initial_state.nodes[3].AddState(ax::mojom::State::kIgnored);
1493
1494 initial_state.nodes[4].id = 5;
1495 initial_state.nodes[4].role = ax::mojom::Role::kGroup;
1496 initial_state.nodes[4].child_ids = {6, 7, 8};
1497
1498 initial_state.nodes[5].id = 6;
1499 initial_state.nodes[5].role = ax::mojom::Role::kStaticText;
1500 initial_state.nodes[5].AddState(ax::mojom::State::kIgnored);
1501
1502 initial_state.nodes[6].id = 7;
1503 initial_state.nodes[6].role = ax::mojom::Role::kStaticText;
1504
1505 initial_state.nodes[7].id = 8;
1506 initial_state.nodes[7].role = ax::mojom::Role::kStaticText;
1507
1508 AXTree tree(initial_state);
1509
1510 AXEventGenerator event_generator(&tree);
1511 AXTreeUpdate update = initial_state;
1512 update.nodes[0].AddState(ax::mojom::State::kIgnored);
1513 update.nodes[5].RemoveState(ax::mojom::State::kIgnored);
1514 update.nodes[6].AddState(ax::mojom::State::kIgnored);
1515 update.nodes[7].AddState(ax::mojom::State::kIgnored);
1516 ASSERT_TRUE(tree.Unserialize(update));
1518 HasEvent(event_generator, AXEventGenerator::Event::CHILDREN_CHANGED, 5));
1520 HasEvent(event_generator, AXEventGenerator::Event::SUBTREE_CREATED, 6));
1522 HasEvent(event_generator, AXEventGenerator::Event::IGNORED_CHANGED, 1));
1524 HasEvent(event_generator, AXEventGenerator::Event::IGNORED_CHANGED, 6));
1525}
1526
1527TEST(AXEventGeneratorTest, IgnoredChangedFiredOnAncestorOnly6) {
1528 // BEFORE
1529 // 1 (IGN)
1530 // |
1531 // 2
1532 // |
1533 // 3
1534 // |
1535 // 4
1536 // |
1537 // ____ 5 _____
1538 // / | \
1539 // 6 (IGN) 7 (IGN) 8
1540
1541 // AFTER
1542 // 1
1543 // |
1544 // 2
1545 // |
1546 // 3
1547 // |
1548 // 4
1549 // |
1550 // ____ 5 _____
1551 // / | \
1552 // 6 7 8 (IGN)
1553
1554 // IGNORED_CHANGED expected on #1, #8
1555
1556 AXTreeUpdate initial_state;
1557 initial_state.root_id = 1;
1558 initial_state.nodes.resize(8);
1559 initial_state.nodes[0].id = 1;
1560 initial_state.nodes[0].role = ax::mojom::Role::kRootWebArea;
1561 initial_state.nodes[0].child_ids = {2};
1562 initial_state.nodes[0].AddState(ax::mojom::State::kIgnored);
1563
1564 initial_state.nodes[1].id = 2;
1565 initial_state.nodes[1].role = ax::mojom::Role::kGroup;
1566 initial_state.nodes[1].child_ids = {3};
1567
1568 initial_state.nodes[2].id = 3;
1569 initial_state.nodes[2].role = ax::mojom::Role::kGroup;
1570 initial_state.nodes[2].child_ids = {4};
1571
1572 initial_state.nodes[3].id = 4;
1573 initial_state.nodes[3].role = ax::mojom::Role::kGroup;
1574 initial_state.nodes[3].child_ids = {5};
1575
1576 initial_state.nodes[4].id = 5;
1577 initial_state.nodes[4].role = ax::mojom::Role::kGroup;
1578 initial_state.nodes[4].child_ids = {6, 7, 8};
1579
1580 initial_state.nodes[5].id = 6;
1581 initial_state.nodes[5].role = ax::mojom::Role::kStaticText;
1582 initial_state.nodes[5].AddState(ax::mojom::State::kIgnored);
1583
1584 initial_state.nodes[6].id = 7;
1585 initial_state.nodes[6].role = ax::mojom::Role::kStaticText;
1586 initial_state.nodes[6].AddState(ax::mojom::State::kIgnored);
1587
1588 initial_state.nodes[7].id = 8;
1589 initial_state.nodes[7].role = ax::mojom::Role::kStaticText;
1590
1591 AXTree tree(initial_state);
1592
1593 AXEventGenerator event_generator(&tree);
1594 AXTreeUpdate update = initial_state;
1595 update.nodes[0].RemoveState(ax::mojom::State::kIgnored);
1596 update.nodes[5].RemoveState(ax::mojom::State::kIgnored);
1597 update.nodes[6].RemoveState(ax::mojom::State::kIgnored);
1598 update.nodes[7].AddState(ax::mojom::State::kIgnored);
1599 ASSERT_TRUE(tree.Unserialize(update));
1601 HasEvent(event_generator, AXEventGenerator::Event::CHILDREN_CHANGED, 5));
1603 HasEvent(event_generator, AXEventGenerator::Event::SUBTREE_CREATED, 1));
1605 HasEvent(event_generator, AXEventGenerator::Event::SUBTREE_CREATED, 6));
1607 HasEvent(event_generator, AXEventGenerator::Event::SUBTREE_CREATED, 7));
1609 HasEvent(event_generator, AXEventGenerator::Event::IGNORED_CHANGED, 1));
1611 HasEvent(event_generator, AXEventGenerator::Event::IGNORED_CHANGED, 8));
1612}
1613
1614TEST(AXEventGeneratorTest, IgnoredChangedFiredOnAncestorOnly7) {
1615 // BEFORE
1616 // 1 (IGN)
1617 // |
1618 // 2 (IGN)
1619 // |
1620 // 3
1621 // |
1622 // __ 4 ___
1623 // / \
1624 // 5 (IGN) 6 (IGN)
1625
1626 // AFTER
1627 // 1
1628 // |
1629 // 2
1630 // |
1631 // 3 (IGN)
1632 // |
1633 // __ 4 (IGN)
1634 // / \
1635 // 5 (IGN) 6 (IGN)
1636
1637 // IGNORED_CHANGED expected on #1, #3
1638
1639 AXTreeUpdate initial_state;
1640 initial_state.root_id = 1;
1641 initial_state.nodes.resize(6);
1642 initial_state.nodes[0].id = 1;
1643 initial_state.nodes[0].role = ax::mojom::Role::kRootWebArea;
1644 initial_state.nodes[0].child_ids = {2};
1645 initial_state.nodes[0].AddState(ax::mojom::State::kIgnored);
1646
1647 initial_state.nodes[1].id = 2;
1648 initial_state.nodes[1].role = ax::mojom::Role::kGroup;
1649 initial_state.nodes[1].child_ids = {3};
1650 initial_state.nodes[1].AddState(ax::mojom::State::kIgnored);
1651
1652 initial_state.nodes[2].id = 3;
1653 initial_state.nodes[2].role = ax::mojom::Role::kGroup;
1654 initial_state.nodes[2].child_ids = {4};
1655
1656 initial_state.nodes[3].id = 4;
1657 initial_state.nodes[3].role = ax::mojom::Role::kGroup;
1658 initial_state.nodes[3].child_ids = {5, 6};
1659
1660 initial_state.nodes[4].id = 5;
1661 initial_state.nodes[4].role = ax::mojom::Role::kStaticText;
1662 initial_state.nodes[4].AddState(ax::mojom::State::kIgnored);
1663
1664 initial_state.nodes[5].id = 6;
1665 initial_state.nodes[5].role = ax::mojom::Role::kStaticText;
1666 initial_state.nodes[5].AddState(ax::mojom::State::kIgnored);
1667
1668 AXTree tree(initial_state);
1669
1670 AXEventGenerator event_generator(&tree);
1671 AXTreeUpdate update = initial_state;
1672 update.nodes[0].RemoveState(ax::mojom::State::kIgnored);
1673 update.nodes[1].RemoveState(ax::mojom::State::kIgnored);
1674 update.nodes[2].AddState(ax::mojom::State::kIgnored);
1675 update.nodes[3].AddState(ax::mojom::State::kIgnored);
1676 ASSERT_TRUE(tree.Unserialize(update));
1678 HasEvent(event_generator, AXEventGenerator::Event::SUBTREE_CREATED, 1));
1680 HasEvent(event_generator, AXEventGenerator::Event::IGNORED_CHANGED, 1));
1682 HasEvent(event_generator, AXEventGenerator::Event::IGNORED_CHANGED, 3));
1683}
1684
1685TEST(AXEventGeneratorTest, IgnoredChangedFiredOnAncestorOnly8) {
1686 // BEFORE
1687 // ____ 1 ____
1688 // | |
1689 // 2 (IGN) 7
1690 // |
1691 // 3 (IGN)
1692 // |
1693 // 4 (IGN)
1694 // |
1695 // 5 (IGN)
1696 // |
1697 // 6 (IGN)
1698
1699 // AFTER
1700 // ____ 1 ____
1701 // | |
1702 // 2 7 (IGN)
1703 // |
1704 // 3
1705 // |
1706 // 4
1707 // |
1708 // 5
1709 // |
1710 // 6
1711
1712 // IGNORED_CHANGED expected on #2, #7
1713
1714 AXTreeUpdate initial_state;
1715 initial_state.root_id = 1;
1716 initial_state.nodes.resize(7);
1717 initial_state.nodes[0].id = 1;
1718 initial_state.nodes[0].role = ax::mojom::Role::kRootWebArea;
1719 initial_state.nodes[0].child_ids = {2, 7};
1720
1721 initial_state.nodes[1].id = 2;
1722 initial_state.nodes[1].role = ax::mojom::Role::kGroup;
1723 initial_state.nodes[1].child_ids = {3};
1724 initial_state.nodes[1].AddState(ax::mojom::State::kIgnored);
1725
1726 initial_state.nodes[2].id = 3;
1727 initial_state.nodes[2].role = ax::mojom::Role::kGroup;
1728 initial_state.nodes[2].child_ids = {4};
1729 initial_state.nodes[2].AddState(ax::mojom::State::kIgnored);
1730
1731 initial_state.nodes[3].id = 4;
1732 initial_state.nodes[3].role = ax::mojom::Role::kGroup;
1733 initial_state.nodes[3].child_ids = {5};
1734 initial_state.nodes[3].AddState(ax::mojom::State::kIgnored);
1735
1736 initial_state.nodes[4].id = 5;
1737 initial_state.nodes[4].role = ax::mojom::Role::kGroup;
1738 initial_state.nodes[4].child_ids = {6};
1739 initial_state.nodes[4].AddState(ax::mojom::State::kIgnored);
1740
1741 initial_state.nodes[5].id = 5;
1742 initial_state.nodes[5].role = ax::mojom::Role::kStaticText;
1743 initial_state.nodes[5].AddState(ax::mojom::State::kIgnored);
1744
1745 initial_state.nodes[6].id = 7;
1746 initial_state.nodes[6].role = ax::mojom::Role::kStaticText;
1747
1748 AXTree tree(initial_state);
1749
1750 AXEventGenerator event_generator(&tree);
1751 AXTreeUpdate update = initial_state;
1752 update.nodes[1].RemoveState(ax::mojom::State::kIgnored);
1753 update.nodes[2].RemoveState(ax::mojom::State::kIgnored);
1754 update.nodes[3].RemoveState(ax::mojom::State::kIgnored);
1755 update.nodes[4].RemoveState(ax::mojom::State::kIgnored);
1756 update.nodes[5].RemoveState(ax::mojom::State::kIgnored);
1757 update.nodes[6].AddState(ax::mojom::State::kIgnored);
1758 ASSERT_TRUE(tree.Unserialize(update));
1760 HasEvent(event_generator, AXEventGenerator::Event::CHILDREN_CHANGED, 1));
1762 HasEvent(event_generator, AXEventGenerator::Event::SUBTREE_CREATED, 2));
1764 HasEvent(event_generator, AXEventGenerator::Event::IGNORED_CHANGED, 2));
1766 HasEvent(event_generator, AXEventGenerator::Event::IGNORED_CHANGED, 7));
1767}
1768
1769TEST(AXEventGeneratorTest, ActiveDescendantChangeOnDescendant) {
1770 AXTreeUpdate initial_state;
1771 initial_state.root_id = 1;
1772 initial_state.nodes.resize(5);
1773 initial_state.nodes[0].id = 1;
1774 initial_state.nodes[0].role = ax::mojom::Role::kRootWebArea;
1775 initial_state.nodes[0].child_ids.push_back(2);
1776 initial_state.nodes[1].id = 2;
1777 initial_state.nodes[1].role = ax::mojom::Role::kGenericContainer;
1778 initial_state.nodes[1].child_ids.push_back(3);
1779 initial_state.nodes[2].id = 3;
1780 initial_state.nodes[2].role = ax::mojom::Role::kGroup;
1781 initial_state.nodes[2].AddIntAttribute(
1783 initial_state.nodes[2].child_ids.push_back(4);
1784 initial_state.nodes[2].child_ids.push_back(5);
1785 initial_state.nodes[3].id = 4;
1786 initial_state.nodes[3].role = ax::mojom::Role::kGroup;
1787 initial_state.nodes[4].id = 5;
1788 initial_state.nodes[4].role = ax::mojom::Role::kGroup;
1789
1790 AXTree tree(initial_state);
1791
1792 AXEventGenerator event_generator(&tree);
1793 initial_state.nodes[2].RemoveIntAttribute(
1795 initial_state.nodes[2].AddIntAttribute(
1797 AXTreeUpdate update = initial_state;
1798 update.node_id_to_clear = 2;
1799 ASSERT_TRUE(tree.Unserialize(update));
1800 EXPECT_TRUE(HasEvent(event_generator,
1802 EXPECT_TRUE(HasEvent(event_generator,
1804}
1805
1806TEST(AXEventGeneratorTest, ImageAnnotationChanged) {
1807 AXTreeUpdate initial_state;
1808 initial_state.root_id = 1;
1809 initial_state.nodes.resize(1);
1810 initial_state.nodes[0].id = 1;
1811 AXTree tree(initial_state);
1812
1813 AXEventGenerator event_generator(&tree);
1814 AXTreeUpdate update = initial_state;
1815 update.nodes[0].AddStringAttribute(
1817 ASSERT_TRUE(tree.Unserialize(update));
1818 EXPECT_TRUE(HasEvent(event_generator,
1820}
1821
1822TEST(AXEventGeneratorTest, ImageAnnotationStatusChanged) {
1823 AXTreeUpdate initial_state;
1824 initial_state.root_id = 1;
1825 initial_state.nodes.resize(1);
1826 initial_state.nodes[0].id = 1;
1827 AXTree tree(initial_state);
1828
1829 AXEventGenerator event_generator(&tree);
1830 AXTreeUpdate update = initial_state;
1831 update.nodes[0].SetImageAnnotationStatus(
1833
1834 ASSERT_TRUE(tree.Unserialize(update));
1835 EXPECT_TRUE(HasEvent(event_generator,
1837}
1838
1839TEST(AXEventGeneratorTest, StringPropertyChanges) {
1840 AXTreeUpdate initial_state;
1841 initial_state.root_id = 1;
1842 initial_state.nodes.resize(1);
1843 initial_state.nodes[0].id = 1;
1844
1845 struct {
1847 std::string old_value;
1848 std::string new_value;
1849 } attributes[] = {
1855 };
1856 for (auto&& attrib : attributes) {
1857 initial_state.nodes.push_back({});
1858 initial_state.nodes.back().id = initial_state.nodes.size();
1859 initial_state.nodes.back().AddStringAttribute(attrib.id, attrib.old_value);
1860 initial_state.nodes[0].child_ids.push_back(initial_state.nodes.size());
1861 }
1862
1863 AXTree tree(initial_state);
1864
1865 AXEventGenerator event_generator(&tree);
1866 int index = 1;
1867 for (auto&& attrib : attributes) {
1868 initial_state.nodes[index++].AddStringAttribute(attrib.id,
1869 attrib.new_value);
1870 }
1871
1872 AXTreeUpdate update = initial_state;
1874 EXPECT_TRUE(HasEvent(event_generator,
1876 EXPECT_TRUE(HasEvent(event_generator,
1878 EXPECT_TRUE(HasEvent(event_generator,
1881 HasEvent(event_generator, AXEventGenerator::Event::LANGUAGE_CHANGED, 5));
1882 EXPECT_TRUE(HasEvent(event_generator,
1884}
1885
1886TEST(AXEventGeneratorTest, IntPropertyChanges) {
1887 AXTreeUpdate initial_state;
1888 initial_state.root_id = 1;
1889 initial_state.nodes.resize(1);
1890 initial_state.nodes[0].id = 1;
1891
1892 struct {
1894 int old_value;
1895 int new_value;
1896 } attributes[] = {
1900 };
1901 for (auto&& attrib : attributes) {
1902 initial_state.nodes.push_back({});
1903 initial_state.nodes.back().id = initial_state.nodes.size();
1904 initial_state.nodes.back().AddIntAttribute(attrib.id, attrib.old_value);
1905 initial_state.nodes[0].child_ids.push_back(initial_state.nodes.size());
1906 }
1907
1908 AXTree tree(initial_state);
1909
1910 AXEventGenerator event_generator(&tree);
1911 int index = 1;
1912 for (auto&& attrib : attributes)
1913 initial_state.nodes[index++].AddIntAttribute(attrib.id, attrib.new_value);
1914
1915 AXTreeUpdate update = initial_state;
1917 EXPECT_TRUE(HasEvent(event_generator,
1919 EXPECT_TRUE(HasEvent(event_generator,
1922 HasEvent(event_generator, AXEventGenerator::Event::SET_SIZE_CHANGED, 4));
1923}
1924
1925TEST(AXEventGeneratorTest, IntListPropertyChanges) {
1926 AXTreeUpdate initial_state;
1927 initial_state.root_id = 1;
1928 initial_state.nodes.resize(1);
1929 initial_state.nodes[0].id = 1;
1930
1931 struct {
1933 std::vector<int> old_value;
1934 std::vector<int> new_value;
1935 } attributes[] = {
1939 };
1940 for (auto&& attrib : attributes) {
1941 initial_state.nodes.push_back({});
1942 initial_state.nodes.back().id = initial_state.nodes.size();
1943 initial_state.nodes.back().AddIntListAttribute(attrib.id, attrib.old_value);
1944 initial_state.nodes[0].child_ids.push_back(initial_state.nodes.size());
1945 }
1946
1947 AXTree tree(initial_state);
1948
1949 AXEventGenerator event_generator(&tree);
1950 int index = 1;
1951 for (auto&& attrib : attributes) {
1952 initial_state.nodes[index++].AddIntListAttribute(attrib.id,
1953 attrib.new_value);
1954 }
1955
1956 AXTreeUpdate update = initial_state;
1958 EXPECT_TRUE(HasEvent(event_generator,
1961 HasEvent(event_generator, AXEventGenerator::Event::FLOW_FROM_CHANGED, 1));
1963 HasEvent(event_generator, AXEventGenerator::Event::FLOW_FROM_CHANGED, 2));
1965 HasEvent(event_generator, AXEventGenerator::Event::FLOW_TO_CHANGED, 3));
1966 EXPECT_TRUE(HasEvent(event_generator,
1968 EXPECT_TRUE(HasEvent(event_generator,
1970 EXPECT_TRUE(HasEvent(event_generator,
1972 EXPECT_TRUE(HasEvent(event_generator,
1974}
1975
1976TEST(AXEventGeneratorTest, AriaBusyChanged) {
1977 AXTreeUpdate initial_state;
1978 initial_state.root_id = 1;
1979 initial_state.nodes.resize(1);
1980 initial_state.nodes[0].id = 1;
1981 AXTree tree(initial_state);
1982 initial_state.nodes[0].AddBoolAttribute(ax::mojom::BoolAttribute::kBusy,
1983 true);
1984
1985 AXEventGenerator event_generator(&tree);
1986 AXTreeUpdate update = initial_state;
1987 update.nodes[0].AddBoolAttribute(ax::mojom::BoolAttribute::kBusy, false);
1988
1989 ASSERT_TRUE(tree.Unserialize(update));
1991 HasEvent(event_generator, AXEventGenerator::Event::BUSY_CHANGED, 1));
1992 EXPECT_TRUE(HasEvent(event_generator,
1994 EXPECT_TRUE(HasEvent(event_generator,
1996 1));
1997}
1998
1999TEST(AXEventGeneratorTest, MultiselectableStateChanged) {
2000 AXTreeUpdate initial_state;
2001 initial_state.root_id = 1;
2002 initial_state.nodes.resize(1);
2003 initial_state.nodes[0].id = 1;
2004 initial_state.nodes[0].role = ax::mojom::Role::kGrid;
2005
2006 AXTree tree(initial_state);
2007 AXEventGenerator event_generator(&tree);
2008 AXTreeUpdate update = initial_state;
2009
2010 update.nodes[0].AddState(ax::mojom::State::kMultiselectable);
2012 EXPECT_TRUE(HasEvent(event_generator,
2014 1));
2016 HasEvent(event_generator, AXEventGenerator::Event::STATE_CHANGED, 1));
2017 EXPECT_TRUE(HasEvent(event_generator,
2019 1));
2020}
2021
2022TEST(AXEventGeneratorTest, RequiredStateChanged) {
2023 AXTreeUpdate initial_state;
2024 initial_state.root_id = 1;
2025 initial_state.nodes.resize(1);
2026 initial_state.nodes[0].id = 1;
2027 initial_state.nodes[0].role = ax::mojom::Role::kTextField;
2028
2029 AXTree tree(initial_state);
2030 AXEventGenerator event_generator(&tree);
2031 AXTreeUpdate update = initial_state;
2032
2033 update.nodes[0].AddState(ax::mojom::State::kRequired);
2035 EXPECT_TRUE(HasEvent(event_generator,
2038 HasEvent(event_generator, AXEventGenerator::Event::STATE_CHANGED, 1));
2039 EXPECT_TRUE(HasEvent(event_generator,
2041 1));
2042}
2043
2044TEST(AXEventGeneratorTest, FlowToChanged) {
2045 AXTreeUpdate initial_state;
2046 initial_state.root_id = 1;
2047 initial_state.nodes.resize(6);
2048 initial_state.nodes[0].id = 1;
2049 initial_state.nodes[0].role = ax::mojom::Role::kGenericContainer;
2050 initial_state.nodes[0].child_ids.assign({2, 3, 4, 5, 6});
2051 initial_state.nodes[1].id = 2;
2052 initial_state.nodes[1].role = ax::mojom::Role::kGenericContainer;
2053 initial_state.nodes[1].AddIntListAttribute(
2055 initial_state.nodes[2].id = 3;
2056 initial_state.nodes[2].role = ax::mojom::Role::kGenericContainer;
2057 initial_state.nodes[3].id = 4;
2058 initial_state.nodes[3].role = ax::mojom::Role::kGenericContainer;
2059 initial_state.nodes[4].id = 5;
2060 initial_state.nodes[4].role = ax::mojom::Role::kGenericContainer;
2061 initial_state.nodes[5].id = 6;
2062 initial_state.nodes[5].role = ax::mojom::Role::kGenericContainer;
2063
2064 AXTree tree(initial_state);
2065
2066 AXEventGenerator event_generator(&tree);
2067 AXTreeUpdate update = initial_state;
2068 update.nodes[1].AddIntListAttribute(ax::mojom::IntListAttribute::kFlowtoIds,
2069 {4, 5, 6});
2070
2073 HasEvent(event_generator, AXEventGenerator::Event::FLOW_FROM_CHANGED, 3));
2075 HasEvent(event_generator, AXEventGenerator::Event::FLOW_FROM_CHANGED, 5));
2077 HasEvent(event_generator, AXEventGenerator::Event::FLOW_FROM_CHANGED, 6));
2079 HasEvent(event_generator, AXEventGenerator::Event::FLOW_TO_CHANGED, 2));
2080 EXPECT_TRUE(HasEvent(event_generator,
2082}
2083
2084TEST(AXEventGeneratorTest, ControlsChanged) {
2085 AXTreeUpdate initial_state;
2086 initial_state.root_id = 1;
2087 initial_state.nodes.resize(2);
2088 initial_state.nodes[0].id = 1;
2089 initial_state.nodes[0].child_ids.push_back(2);
2090 initial_state.nodes[1].id = 2;
2091
2092 AXTree tree(initial_state);
2093 AXEventGenerator event_generator(&tree);
2094 AXTreeUpdate update = initial_state;
2095
2096 std::vector<int> ids = {2};
2097 update.nodes[0].AddIntListAttribute(ax::mojom::IntListAttribute::kControlsIds,
2098 ids);
2101 HasEvent(event_generator, AXEventGenerator::Event::CONTROLS_CHANGED, 1));
2102 EXPECT_TRUE(HasEvent(event_generator,
2104}
2105
2106TEST(AXEventGeneratorTest, AtomicChanged) {
2107 AXTreeUpdate initial_state;
2108 initial_state.root_id = 1;
2109 initial_state.nodes.resize(1);
2110 initial_state.nodes[0].id = 1;
2111
2112 AXTree tree(initial_state);
2113 AXEventGenerator event_generator(&tree);
2114 AXTreeUpdate update = initial_state;
2115
2116 update.nodes[0].AddBoolAttribute(ax::mojom::BoolAttribute::kLiveAtomic, true);
2119 HasEvent(event_generator, AXEventGenerator::Event::ATOMIC_CHANGED, 1));
2120}
2121
2122TEST(AXEventGeneratorTest, DropeffectChanged) {
2123 AXTreeUpdate initial_state;
2124 initial_state.root_id = 1;
2125 initial_state.nodes.resize(1);
2126 initial_state.nodes[0].id = 1;
2127
2128 AXTree tree(initial_state);
2129 AXEventGenerator event_generator(&tree);
2130 AXTreeUpdate update = initial_state;
2131
2132 update.nodes[0].AddDropeffect(ax::mojom::Dropeffect::kCopy);
2134 EXPECT_TRUE(HasEvent(event_generator,
2136}
2137
2138TEST(AXEventGeneratorTest, GrabbedChanged) {
2139 AXTreeUpdate initial_state;
2140 initial_state.root_id = 1;
2141 initial_state.nodes.resize(1);
2142 initial_state.nodes[0].id = 1;
2143
2144 AXTree tree(initial_state);
2145 AXEventGenerator event_generator(&tree);
2146 AXTreeUpdate update = initial_state;
2147
2148 update.nodes[0].AddBoolAttribute(ax::mojom::BoolAttribute::kGrabbed, true);
2151 HasEvent(event_generator, AXEventGenerator::Event::GRABBED_CHANGED, 1));
2152}
2153
2154TEST(AXEventGeneratorTest, HasPopupChanged) {
2155 AXTreeUpdate initial_state;
2156 initial_state.root_id = 1;
2157 initial_state.nodes.resize(1);
2158 initial_state.nodes[0].id = 1;
2159
2160 AXTree tree(initial_state);
2161 AXEventGenerator event_generator(&tree);
2162 AXTreeUpdate update = initial_state;
2163
2164 update.nodes[0].SetHasPopup(ax::mojom::HasPopup::kTrue);
2167 HasEvent(event_generator, AXEventGenerator::Event::HASPOPUP_CHANGED, 1));
2168 EXPECT_TRUE(HasEvent(event_generator,
2170 1));
2171}
2172
2173TEST(AXEventGeneratorTest, LiveRelevantChanged) {
2174 AXTreeUpdate initial_state;
2175 initial_state.root_id = 1;
2176 initial_state.nodes.resize(1);
2177 initial_state.nodes[0].id = 1;
2178
2179 AXTree tree(initial_state);
2180 AXEventGenerator event_generator(&tree);
2181 AXTreeUpdate update = initial_state;
2182
2183 update.nodes[0].AddStringAttribute(ax::mojom::StringAttribute::kLiveRelevant,
2184 "all");
2186 EXPECT_TRUE(HasEvent(event_generator,
2188}
2189
2190TEST(AXEventGeneratorTest, MultilineStateChanged) {
2191 AXTreeUpdate initial_state;
2192 initial_state.root_id = 1;
2193 initial_state.nodes.resize(1);
2194 initial_state.nodes[0].id = 1;
2195
2196 AXTree tree(initial_state);
2197 AXEventGenerator event_generator(&tree);
2198 AXTreeUpdate update = initial_state;
2199
2200 update.nodes[0].AddState(ax::mojom::State::kMultiline);
2202 EXPECT_TRUE(HasEvent(event_generator,
2205 HasEvent(event_generator, AXEventGenerator::Event::STATE_CHANGED, 1));
2206 EXPECT_TRUE(HasEvent(event_generator,
2208 1));
2209}
2210
2211} // namespace ui
ax::mojom::Event event_type
virtual bool Unserialize(const AXTreeUpdate &update)
Definition: ax_tree.cc:969
StringAttribute
Definition: ax_enums.h:521
IntListAttribute
Definition: ax_enums.h:799
TEST(AXEnumUtilTest, Event)
Definition: update.py:1
AXNode::AXID sel_focus_object_id
Definition: ax_tree_data.h:65
AXNode::AXID focus_id
Definition: ax_tree_data.h:53
int32_t sel_focus_offset
Definition: ax_tree_data.h:66
std::string title
Definition: ax_tree_data.h:48
std::vector< AXNodeData > nodes
const uintptr_t id
#define EXPECT_TRUE(handle)
Definition: unit_test.h:678