Flutter Linux Embedder
fl_view_accessible_test.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 
5 // Included first as it collides with the X11 headers.
6 #include "gtest/gtest.h"
7 
10 #include "flutter/shell/platform/linux/testing/mock_signal_handler.h"
11 
12 TEST(FlViewAccessibleTest, BuildTree) {
13  g_autoptr(FlDartProject) project = fl_dart_project_new();
14  g_autoptr(FlEngine) engine = fl_engine_new(project);
15  g_autoptr(FlViewAccessible) accessible = fl_view_accessible_new(engine, 456);
16 
17  int32_t children[] = {111, 222};
18  FlutterSemanticsFlags flags = {};
19  FlutterSemanticsNode2 root_node = {.id = 0,
20  .label = "root",
21  .child_count = 2,
22  .children_in_traversal_order = children,
23  .flags2 = &flags,
24  .identifier = ""};
25  FlutterSemanticsNode2 child1_node = {
26  .id = 111, .label = "child 1", .flags2 = &flags};
27  FlutterSemanticsNode2 child2_node = {
28  .id = 222, .label = "child 2", .flags2 = &flags};
29  FlutterSemanticsNode2* nodes[3] = {&root_node, &child1_node, &child2_node};
30  FlutterSemanticsUpdate2 update = {.node_count = 3, .nodes = nodes};
32 
33  AtkObject* root_object =
34  atk_object_ref_accessible_child(ATK_OBJECT(accessible), 0);
35  EXPECT_STREQ(atk_object_get_name(root_object), "root");
36  EXPECT_EQ(atk_object_get_index_in_parent(root_object), 0);
37  EXPECT_EQ(atk_object_get_n_accessible_children(root_object), 2);
38 
39  AtkObject* child1_object = atk_object_ref_accessible_child(root_object, 0);
40  EXPECT_STREQ(atk_object_get_name(child1_object), "child 1");
41  EXPECT_EQ(atk_object_get_parent(child1_object), root_object);
42  EXPECT_EQ(atk_object_get_index_in_parent(child1_object), 0);
43  EXPECT_EQ(atk_object_get_n_accessible_children(child1_object), 0);
44 
45  AtkObject* child2_object = atk_object_ref_accessible_child(root_object, 1);
46  EXPECT_STREQ(atk_object_get_name(child2_object), "child 2");
47  EXPECT_EQ(atk_object_get_parent(child2_object), root_object);
48  EXPECT_EQ(atk_object_get_index_in_parent(child2_object), 1);
49  EXPECT_EQ(atk_object_get_n_accessible_children(child2_object), 0);
50 }
51 
52 TEST(FlViewAccessibleTest, AddRemoveChildren) {
53  g_autoptr(FlDartProject) project = fl_dart_project_new();
54  g_autoptr(FlEngine) engine = fl_engine_new(project);
55  g_autoptr(FlViewAccessible) accessible = fl_view_accessible_new(engine, 456);
56 
57  FlutterSemanticsFlags flags = {};
58  FlutterSemanticsNode2 root_node = {
59  .id = 0, .label = "root", .child_count = 0, .flags2 = &flags};
60  FlutterSemanticsNode2* nodes[1] = {&root_node};
61  FlutterSemanticsUpdate2 update = {.node_count = 1, .nodes = nodes};
63 
64  AtkObject* root_object =
65  atk_object_ref_accessible_child(ATK_OBJECT(accessible), 0);
66  EXPECT_EQ(atk_object_get_n_accessible_children(root_object), 0);
67 
68  // add child1
69  AtkObject* child1_object = nullptr;
70  FlutterSemanticsNode2 child1_node = {
71  .id = 111, .label = "child 1", .flags2 = &flags};
72  {
73  flutter::testing::MockSignalHandler2<gint, AtkObject*> child1_added(
74  root_object, "children-changed::add");
75  EXPECT_SIGNAL2(child1_added, ::testing::Eq(0), ::testing::A<AtkObject*>())
76  .WillOnce(::testing::SaveArg<1>(&child1_object));
77 
78  int32_t children[] = {111};
79  root_node.child_count = 1;
80  root_node.children_in_traversal_order = children;
81  FlutterSemanticsNode2* nodes[2] = {&root_node, &child1_node};
82  FlutterSemanticsUpdate2 update = {.node_count = 2, .nodes = nodes};
84  }
85 
86  EXPECT_EQ(atk_object_get_n_accessible_children(root_object), 1);
87  EXPECT_EQ(atk_object_ref_accessible_child(root_object, 0), child1_object);
88 
89  EXPECT_STREQ(atk_object_get_name(child1_object), "child 1");
90  EXPECT_EQ(atk_object_get_parent(child1_object), root_object);
91  EXPECT_EQ(atk_object_get_index_in_parent(child1_object), 0);
92  EXPECT_EQ(atk_object_get_n_accessible_children(child1_object), 0);
93 
94  // add child2
95  AtkObject* child2_object = nullptr;
96  FlutterSemanticsNode2 child2_node = {
97  .id = 222, .label = "child 2", .flags2 = &flags};
98  {
99  flutter::testing::MockSignalHandler2<gint, AtkObject*> child2_added(
100  root_object, "children-changed::add");
101  EXPECT_SIGNAL2(child2_added, ::testing::Eq(1), ::testing::A<AtkObject*>())
102  .WillOnce(::testing::SaveArg<1>(&child2_object));
103 
104  int32_t children[] = {111, 222};
105  root_node.child_count = 2;
106  root_node.children_in_traversal_order = children;
107  FlutterSemanticsNode2* nodes[3] = {&root_node, &child1_node, &child2_node};
108  FlutterSemanticsUpdate2 update = {.node_count = 3, .nodes = nodes};
110  }
111 
112  EXPECT_EQ(atk_object_get_n_accessible_children(root_object), 2);
113  EXPECT_EQ(atk_object_ref_accessible_child(root_object, 0), child1_object);
114  EXPECT_EQ(atk_object_ref_accessible_child(root_object, 1), child2_object);
115 
116  EXPECT_STREQ(atk_object_get_name(child1_object), "child 1");
117  EXPECT_EQ(atk_object_get_parent(child1_object), root_object);
118  EXPECT_EQ(atk_object_get_index_in_parent(child1_object), 0);
119  EXPECT_EQ(atk_object_get_n_accessible_children(child1_object), 0);
120 
121  EXPECT_STREQ(atk_object_get_name(child2_object), "child 2");
122  EXPECT_EQ(atk_object_get_parent(child2_object), root_object);
123  EXPECT_EQ(atk_object_get_index_in_parent(child2_object), 1);
124  EXPECT_EQ(atk_object_get_n_accessible_children(child2_object), 0);
125 
126  // remove child1
127  {
128  flutter::testing::MockSignalHandler2<gint, AtkObject*> child1_removed(
129  root_object, "children-changed::remove");
130  EXPECT_SIGNAL2(child1_removed, ::testing::Eq(0),
131  ::testing::Eq(child1_object));
132 
133  const int32_t children[] = {222};
134  root_node.child_count = 1;
135  root_node.children_in_traversal_order = children;
136  FlutterSemanticsNode2* nodes[3] = {&root_node, &child2_node};
137  FlutterSemanticsUpdate2 update = {.node_count = 2, .nodes = nodes};
139  }
140 
141  EXPECT_EQ(atk_object_get_n_accessible_children(root_object), 1);
142  EXPECT_EQ(atk_object_ref_accessible_child(root_object, 0), child2_object);
143 
144  EXPECT_STREQ(atk_object_get_name(child2_object), "child 2");
145  EXPECT_EQ(atk_object_get_parent(child2_object), root_object);
146  EXPECT_EQ(atk_object_get_index_in_parent(child2_object), 0);
147  EXPECT_EQ(atk_object_get_n_accessible_children(child2_object), 0);
148 
149  // remove child2
150  {
151  flutter::testing::MockSignalHandler2<gint, AtkObject*> child2_removed(
152  root_object, "children-changed::remove");
153  EXPECT_SIGNAL2(child2_removed, ::testing::Eq(0),
154  ::testing::Eq(child2_object));
155 
156  root_node.child_count = 0;
157  FlutterSemanticsNode2* nodes[1] = {&root_node};
158  FlutterSemanticsUpdate2 update = {.node_count = 1, .nodes = nodes};
160  }
161 
162  EXPECT_EQ(atk_object_get_n_accessible_children(root_object), 0);
163 }
FlViewAccessible * accessible
g_autoptr(FlEngine) engine
G_MODULE_EXPORT FlDartProject * fl_dart_project_new()
G_MODULE_EXPORT FlEngine * fl_engine_new(FlDartProject *project)
Definition: fl_engine.cc:697
FlViewAccessible * fl_view_accessible_new(FlEngine *engine, FlutterViewId view_id)
void fl_view_accessible_handle_update_semantics(FlViewAccessible *self, const FlutterSemanticsUpdate2 *update)
TEST(FlViewAccessibleTest, BuildTree)