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