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 "flutter/shell/platform/linux/testing/linux_test.h"
7 #include "gtest/gtest.h"
8 
11 #include "flutter/shell/platform/linux/testing/mock_signal_handler.h"
12 
13 class FlViewAccessibleTest : public flutter::testing::LinuxTest {};
14 
16  g_autoptr(FlViewAccessible) accessible = fl_view_accessible_new(engine, 456);
17 
18  int32_t children[] = {111, 222};
19  FlutterSemanticsFlags flags = {};
20  FlutterSemanticsNode2 root_node = {.id = 0,
21  .label = "root",
22  .child_count = 2,
23  .children_in_traversal_order = children,
24  .flags2 = &flags,
25  .identifier = ""};
26  FlutterSemanticsNode2 child1_node = {
27  .id = 111, .label = "child 1", .flags2 = &flags};
28  FlutterSemanticsNode2 child2_node = {
29  .id = 222, .label = "child 2", .flags2 = &flags};
30  FlutterSemanticsNode2* nodes[3] = {&root_node, &child1_node, &child2_node};
31  FlutterSemanticsUpdate2 update = {.node_count = 3, .nodes = nodes};
33 
34  AtkObject* root_object =
35  atk_object_ref_accessible_child(ATK_OBJECT(accessible), 0);
36  EXPECT_STREQ(atk_object_get_name(root_object), "root");
37  EXPECT_EQ(atk_object_get_index_in_parent(root_object), 0);
38  EXPECT_EQ(atk_object_get_n_accessible_children(root_object), 2);
39 
40  AtkObject* child1_object = atk_object_ref_accessible_child(root_object, 0);
41  EXPECT_STREQ(atk_object_get_name(child1_object), "child 1");
42  EXPECT_EQ(atk_object_get_parent(child1_object), root_object);
43  EXPECT_EQ(atk_object_get_index_in_parent(child1_object), 0);
44  EXPECT_EQ(atk_object_get_n_accessible_children(child1_object), 0);
45 
46  AtkObject* child2_object = atk_object_ref_accessible_child(root_object, 1);
47  EXPECT_STREQ(atk_object_get_name(child2_object), "child 2");
48  EXPECT_EQ(atk_object_get_parent(child2_object), root_object);
49  EXPECT_EQ(atk_object_get_index_in_parent(child2_object), 1);
50  EXPECT_EQ(atk_object_get_n_accessible_children(child2_object), 0);
51 }
52 
53 TEST_F(FlViewAccessibleTest, AddRemoveChildren) {
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};
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};
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};
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};
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};
159  }
160 
161  EXPECT_EQ(atk_object_get_n_accessible_children(root_object), 0);
162 }
FlViewAccessible * accessible
g_autoptr(FlEngine) engine
FlViewAccessible * fl_view_accessible_new(FlEngine *engine, FlutterViewId view_id)
void fl_view_accessible_handle_update_semantics(FlViewAccessible *self, const FlutterSemanticsUpdate2 *update)
TEST_F(FlViewAccessibleTest, BuildTree)