| 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
8 #include "flutter/shell/platform/linux/fl_view_accessible.h"
9 #include "flutter/shell/platform/linux/public/flutter_linux/fl_engine.h"
10 #include "flutter/shell/platform/linux/testing/fl_test.h"
11 #include "flutter/shell/platform/linux/testing/mock_signal_handler.h"
12
13 static const FlutterSemanticsNode kBatchEndNode = {
14 .id = kFlutterSemanticsNodeIdBatchEnd};
15
16 TEST(FlViewAccessibleTest, BuildTree) {
17 g_autoptr(FlEngine) engine = make_mock_engine();
18 g_autoptr(FlViewAccessible) accessible = FL_VIEW_ACCESSIBLE(
19 g_object_new(fl_view_accessible_get_type(), "engine", engine, nullptr));
20
21 const int32_t children[] = {111, 222};
22 const FlutterSemanticsNode root_node = {
23 .id = 0,
24 .label = "root",
25 .child_count = 2,
26 .children_in_traversal_order = children,
27 };
28 fl_view_accessible_handle_update_semantics_node(accessible, &root_node);
29
30 const FlutterSemanticsNode child1_node = {.id = 111, .label = "child 1"};
31 fl_view_accessible_handle_update_semantics_node(accessible, &child1_node);
32
33 const FlutterSemanticsNode child2_node = {.id = 222, .label = "child 2"};
34 fl_view_accessible_handle_update_semantics_node(accessible, &child2_node);
35
36 fl_view_accessible_handle_update_semantics_node(accessible, &kBatchEndNode);
37
38 AtkObject* root_object =
39 atk_object_ref_accessible_child(ATK_OBJECT(accessible), 0);
40 EXPECT_STREQ(atk_object_get_name(root_object), "root");
41 EXPECT_EQ(atk_object_get_index_in_parent(root_object), 0);
42 EXPECT_EQ(atk_object_get_n_accessible_children(root_object), 2);
43
44 AtkObject* child1_object = atk_object_ref_accessible_child(root_object, 0);
45 EXPECT_STREQ(atk_object_get_name(child1_object), "child 1");
46 EXPECT_EQ(atk_object_get_parent(child1_object), root_object);
47 EXPECT_EQ(atk_object_get_index_in_parent(child1_object), 0);
48 EXPECT_EQ(atk_object_get_n_accessible_children(child1_object), 0);
49
50 AtkObject* child2_object = atk_object_ref_accessible_child(root_object, 1);
51 EXPECT_STREQ(atk_object_get_name(child2_object), "child 2");
52 EXPECT_EQ(atk_object_get_parent(child2_object), root_object);
53 EXPECT_EQ(atk_object_get_index_in_parent(child2_object), 1);
54 EXPECT_EQ(atk_object_get_n_accessible_children(child2_object), 0);
55 }
56
57 TEST(FlViewAccessibleTest, AddRemoveChildren) {
58 g_autoptr(FlEngine) engine = make_mock_engine();
59 g_autoptr(FlViewAccessible) accessible = FL_VIEW_ACCESSIBLE(
60 g_object_new(fl_view_accessible_get_type(), "engine", engine, nullptr));
61
62 FlutterSemanticsNode root_node = {
63 .id = 0,
64 .label = "root",
65 .child_count = 0,
66 };
67 fl_view_accessible_handle_update_semantics_node(accessible, &root_node);
68
69 fl_view_accessible_handle_update_semantics_node(accessible, &kBatchEndNode);
70
71 AtkObject* root_object =
72 atk_object_ref_accessible_child(ATK_OBJECT(accessible), 0);
73 EXPECT_EQ(atk_object_get_n_accessible_children(root_object), 0);
74
75 // add child1
76 AtkObject* child1_object = nullptr;
77 {
78 flutter::testing::MockSignalHandler2<gint, AtkObject*> child1_added(
79 root_object, "children-changed::add");
80 EXPECT_SIGNAL2(child1_added, ::testing::Eq(0), ::testing::A<AtkObject*>())
81 .WillOnce(::testing::SaveArg<1>(&child1_object));
82
83 const int32_t children[] = {111};
84 root_node.child_count = 1;
85 root_node.children_in_traversal_order = children;
86 fl_view_accessible_handle_update_semantics_node(accessible, &root_node);
87
88 const FlutterSemanticsNode child1_node = {.id = 111, .label = "child 1"};
89 fl_view_accessible_handle_update_semantics_node(accessible, &child1_node);
90
91 fl_view_accessible_handle_update_semantics_node(accessible, &kBatchEndNode);
92 }
93
94 EXPECT_EQ(atk_object_get_n_accessible_children(root_object), 1);
95 EXPECT_EQ(atk_object_ref_accessible_child(root_object, 0), child1_object);
96
97 EXPECT_STREQ(atk_object_get_name(child1_object), "child 1");
98 EXPECT_EQ(atk_object_get_parent(child1_object), root_object);
99 EXPECT_EQ(atk_object_get_index_in_parent(child1_object), 0);
100 EXPECT_EQ(atk_object_get_n_accessible_children(child1_object), 0);
101
102 // add child2
103 AtkObject* child2_object = nullptr;
104 {
105 flutter::testing::MockSignalHandler2<gint, AtkObject*> child2_added(
106 root_object, "children-changed::add");
107 EXPECT_SIGNAL2(child2_added, ::testing::Eq(1), ::testing::A<AtkObject*>())
108 .WillOnce(::testing::SaveArg<1>(&child2_object));
109
110 const int32_t children[] = {111, 222};
111 root_node.child_count = 2;
112 root_node.children_in_traversal_order = children;
113 fl_view_accessible_handle_update_semantics_node(accessible, &root_node);
114
115 const FlutterSemanticsNode child2_node = {.id = 222, .label = "child 2"};
116 fl_view_accessible_handle_update_semantics_node(accessible, &child2_node);
117
118 fl_view_accessible_handle_update_semantics_node(accessible, &kBatchEndNode);
119 }
120
121 EXPECT_EQ(atk_object_get_n_accessible_children(root_object), 2);
122 EXPECT_EQ(atk_object_ref_accessible_child(root_object, 0), child1_object);
123 EXPECT_EQ(atk_object_ref_accessible_child(root_object, 1), child2_object);
124
125 EXPECT_STREQ(atk_object_get_name(child1_object), "child 1");
126 EXPECT_EQ(atk_object_get_parent(child1_object), root_object);
127 EXPECT_EQ(atk_object_get_index_in_parent(child1_object), 0);
128 EXPECT_EQ(atk_object_get_n_accessible_children(child1_object), 0);
129
130 EXPECT_STREQ(atk_object_get_name(child2_object), "child 2");
131 EXPECT_EQ(atk_object_get_parent(child2_object), root_object);
132 EXPECT_EQ(atk_object_get_index_in_parent(child2_object), 1);
133 EXPECT_EQ(atk_object_get_n_accessible_children(child2_object), 0);
134
135 // remove child1
136 {
137 flutter::testing::MockSignalHandler2<gint, AtkObject*> child1_removed(
138 root_object, "children-changed::remove");
139 EXPECT_SIGNAL2(child1_removed, ::testing::Eq(0),
140 ::testing::Eq(child1_object));
141
142 const int32_t children[] = {222};
143 root_node.child_count = 1;
144 root_node.children_in_traversal_order = children;
145 fl_view_accessible_handle_update_semantics_node(accessible, &root_node);
146
147 fl_view_accessible_handle_update_semantics_node(accessible, &kBatchEndNode);
148 }
149
150 EXPECT_EQ(atk_object_get_n_accessible_children(root_object), 1);
151 EXPECT_EQ(atk_object_ref_accessible_child(root_object, 0), child2_object);
152
153 EXPECT_STREQ(atk_object_get_name(child2_object), "child 2");
154 EXPECT_EQ(atk_object_get_parent(child2_object), root_object);
155 EXPECT_EQ(atk_object_get_index_in_parent(child2_object), 0);
156 EXPECT_EQ(atk_object_get_n_accessible_children(child2_object), 0);
157
158 // remove child2
159 {
160 flutter::testing::MockSignalHandler2<gint, AtkObject*> child2_removed(
161 root_object, "children-changed::remove");
162 EXPECT_SIGNAL2(child2_removed, ::testing::Eq(0),
163 ::testing::Eq(child2_object));
164
165 root_node.child_count = 0;
166 fl_view_accessible_handle_update_semantics_node(accessible, &root_node);
167
168 fl_view_accessible_handle_update_semantics_node(accessible, &kBatchEndNode);
169 }
170
171 EXPECT_EQ(atk_object_get_n_accessible_children(root_object), 0);
172 }
fl_view_accessible.h
fl_view_accessible_handle_update_semantics_node
void fl_view_accessible_handle_update_semantics_node(FlViewAccessible *self, const FlutterSemanticsNode *node)
Definition: fl_view_accessible.cc:192
make_mock_engine
static FlEngine * make_mock_engine()
Definition: fl_event_channel_test.cc:24
TEST
TEST(FlViewAccessibleTest, BuildTree)
Definition: fl_view_accessible_test.cc:16
fl_engine.h
engine
FlEngine * engine
Definition: fl_view_accessible.cc:29
kBatchEndNode
static const FlutterSemanticsNode kBatchEndNode
Definition: fl_view_accessible_test.cc:13