Flutter macOS Embedder
flutter_platform_node_delegate_unittests.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 
6 
7 #include "flutter/third_party/accessibility/ax/ax_action_data.h"
8 #include "gtest/gtest.h"
9 
11 
12 namespace flutter {
13 namespace testing {
14 
15 TEST(FlutterPlatformNodeDelegateTest, NodeDelegateHasUniqueId) {
16  std::shared_ptr<TestAccessibilityBridge> bridge =
17  std::make_shared<TestAccessibilityBridge>();
18 
19  // Add node 0: root.
20  FlutterSemanticsNode2 node0{sizeof(FlutterSemanticsNode2), 0};
21  std::vector<int32_t> node0_children{1};
22  node0.child_count = node0_children.size();
23  node0.children_in_traversal_order = node0_children.data();
24  node0.children_in_hit_test_order = node0_children.data();
25 
26  // Add node 1: text child of node 0.
27  FlutterSemanticsNode2 node1{sizeof(FlutterSemanticsNode2), 1};
28  node1.label = "prefecture";
29  node1.value = "Kyoto";
30 
31  bridge->AddFlutterSemanticsNodeUpdate(node0);
32  bridge->AddFlutterSemanticsNodeUpdate(node1);
33  bridge->CommitUpdates();
34 
35  auto node0_delegate = bridge->GetFlutterPlatformNodeDelegateFromID(0).lock();
36  auto node1_delegate = bridge->GetFlutterPlatformNodeDelegateFromID(1).lock();
37  EXPECT_TRUE(node0_delegate->GetUniqueId() != node1_delegate->GetUniqueId());
38 }
39 
40 TEST(FlutterPlatformNodeDelegateTest, canPerfomActions) {
41  std::shared_ptr<TestAccessibilityBridge> bridge =
42  std::make_shared<TestAccessibilityBridge>();
43  FlutterSemanticsNode2 root;
44  root.id = 0;
45  root.flags = FlutterSemanticsFlag::kFlutterSemanticsFlagIsTextField;
46  root.actions = static_cast<FlutterSemanticsAction>(0);
47  root.text_selection_base = -1;
48  root.text_selection_extent = -1;
49  root.label = "root";
50  root.hint = "";
51  root.value = "";
52  root.increased_value = "";
53  root.decreased_value = "";
54  root.tooltip = "";
55  root.child_count = 0;
56  root.custom_accessibility_actions_count = 0;
57  bridge->AddFlutterSemanticsNodeUpdate(root);
58 
59  bridge->CommitUpdates();
60 
61  auto accessibility = bridge->GetFlutterPlatformNodeDelegateFromID(0).lock();
62  // Performs an AXAction.
63  ui::AXActionData action_data;
64  action_data.action = ax::mojom::Action::kDoDefault;
65  accessibility->AccessibilityPerformAction(action_data);
66  EXPECT_EQ(bridge->performed_actions.size(), size_t{1});
67  EXPECT_EQ(bridge->performed_actions[0],
68  FlutterSemanticsAction::kFlutterSemanticsActionTap);
69 
70  action_data.action = ax::mojom::Action::kFocus;
71  accessibility->AccessibilityPerformAction(action_data);
72  EXPECT_EQ(bridge->performed_actions.size(), size_t{2});
73  EXPECT_EQ(
74  bridge->performed_actions[1],
75  FlutterSemanticsAction::kFlutterSemanticsActionDidGainAccessibilityFocus);
76 
77  action_data.action = ax::mojom::Action::kScrollToMakeVisible;
78  accessibility->AccessibilityPerformAction(action_data);
79  EXPECT_EQ(bridge->performed_actions.size(), size_t{3});
80  EXPECT_EQ(bridge->performed_actions[2],
81  FlutterSemanticsAction::kFlutterSemanticsActionShowOnScreen);
82 }
83 
84 TEST(FlutterPlatformNodeDelegateTest, canGetAXNode) {
85  // Set up a flutter accessibility node.
86  std::shared_ptr<TestAccessibilityBridge> bridge =
87  std::make_shared<TestAccessibilityBridge>();
88  FlutterSemanticsNode2 root;
89  root.id = 0;
90  root.flags = FlutterSemanticsFlag::kFlutterSemanticsFlagIsTextField;
91  root.actions = static_cast<FlutterSemanticsAction>(0);
92  root.text_selection_base = -1;
93  root.text_selection_extent = -1;
94  root.label = "root";
95  root.hint = "";
96  root.value = "";
97  root.increased_value = "";
98  root.decreased_value = "";
99  root.tooltip = "";
100  root.child_count = 0;
101  root.custom_accessibility_actions_count = 0;
102  bridge->AddFlutterSemanticsNodeUpdate(root);
103 
104  bridge->CommitUpdates();
105 
106  auto accessibility = bridge->GetFlutterPlatformNodeDelegateFromID(0).lock();
107  EXPECT_EQ(accessibility->GetData().id, 0);
108 }
109 
110 TEST(FlutterPlatformNodeDelegateTest, canCalculateBoundsCorrectly) {
111  std::shared_ptr<TestAccessibilityBridge> bridge =
112  std::make_shared<TestAccessibilityBridge>();
113  FlutterSemanticsNode2 root;
114  root.id = 0;
115  root.label = "root";
116  root.hint = "";
117  root.value = "";
118  root.increased_value = "";
119  root.decreased_value = "";
120  root.tooltip = "";
121  root.child_count = 1;
122  int32_t children[] = {1};
123  root.children_in_traversal_order = children;
124  root.custom_accessibility_actions_count = 0;
125  root.rect = {0, 0, 100, 100}; // LTRB
126  root.transform = {1, 0, 0, 0, 1, 0, 0, 0, 1};
127  bridge->AddFlutterSemanticsNodeUpdate(root);
128 
129  FlutterSemanticsNode2 child1;
130  child1.id = 1;
131  child1.label = "child 1";
132  child1.hint = "";
133  child1.value = "";
134  child1.increased_value = "";
135  child1.decreased_value = "";
136  child1.tooltip = "";
137  child1.child_count = 0;
138  child1.custom_accessibility_actions_count = 0;
139  child1.rect = {0, 0, 50, 50}; // LTRB
140  child1.transform = {0.5, 0, 0, 0, 0.5, 0, 0, 0, 1};
141  bridge->AddFlutterSemanticsNodeUpdate(child1);
142 
143  bridge->CommitUpdates();
144  auto child1_node = bridge->GetFlutterPlatformNodeDelegateFromID(1).lock();
145  ui::AXOffscreenResult result;
146  gfx::Rect bounds =
147  child1_node->GetBoundsRect(ui::AXCoordinateSystem::kScreenDIPs,
148  ui::AXClippingBehavior::kClipped, &result);
149  EXPECT_EQ(bounds.x(), 0);
150  EXPECT_EQ(bounds.y(), 0);
151  EXPECT_EQ(bounds.width(), 25);
152  EXPECT_EQ(bounds.height(), 25);
153  EXPECT_EQ(result, ui::AXOffscreenResult::kOnscreen);
154 }
155 
156 TEST(FlutterPlatformNodeDelegateTest, canCalculateOffScreenBoundsCorrectly) {
157  std::shared_ptr<TestAccessibilityBridge> bridge =
158  std::make_shared<TestAccessibilityBridge>();
159  FlutterSemanticsNode2 root;
160  root.id = 0;
161  root.label = "root";
162  root.hint = "";
163  root.value = "";
164  root.increased_value = "";
165  root.decreased_value = "";
166  root.tooltip = "";
167  root.child_count = 1;
168  int32_t children[] = {1};
169  root.children_in_traversal_order = children;
170  root.custom_accessibility_actions_count = 0;
171  root.rect = {0, 0, 100, 100}; // LTRB
172  root.transform = {1, 0, 0, 0, 1, 0, 0, 0, 1};
173  bridge->AddFlutterSemanticsNodeUpdate(root);
174 
175  FlutterSemanticsNode2 child1;
176  child1.id = 1;
177  child1.label = "child 1";
178  child1.hint = "";
179  child1.value = "";
180  child1.increased_value = "";
181  child1.decreased_value = "";
182  child1.tooltip = "";
183  child1.child_count = 0;
184  child1.custom_accessibility_actions_count = 0;
185  child1.rect = {90, 90, 100, 100}; // LTRB
186  child1.transform = {2, 0, 0, 0, 2, 0, 0, 0, 1};
187  bridge->AddFlutterSemanticsNodeUpdate(child1);
188 
189  bridge->CommitUpdates();
190  auto child1_node = bridge->GetFlutterPlatformNodeDelegateFromID(1).lock();
191  ui::AXOffscreenResult result;
192  gfx::Rect bounds =
193  child1_node->GetBoundsRect(ui::AXCoordinateSystem::kScreenDIPs,
194  ui::AXClippingBehavior::kUnclipped, &result);
195  EXPECT_EQ(bounds.x(), 180);
196  EXPECT_EQ(bounds.y(), 180);
197  EXPECT_EQ(bounds.width(), 20);
198  EXPECT_EQ(bounds.height(), 20);
199  EXPECT_EQ(result, ui::AXOffscreenResult::kOffscreen);
200 }
201 
202 TEST(FlutterPlatformNodeDelegateTest, canUseOwnerBridge) {
203  std::shared_ptr<TestAccessibilityBridge> bridge =
204  std::make_shared<TestAccessibilityBridge>();
205  FlutterSemanticsNode2 root;
206  root.id = 0;
207  root.label = "root";
208  root.hint = "";
209  root.value = "";
210  root.increased_value = "";
211  root.decreased_value = "";
212  root.tooltip = "";
213  root.child_count = 1;
214  int32_t children[] = {1};
215  root.children_in_traversal_order = children;
216  root.custom_accessibility_actions_count = 0;
217  root.rect = {0, 0, 100, 100}; // LTRB
218  root.transform = {1, 0, 0, 0, 1, 0, 0, 0, 1};
219  bridge->AddFlutterSemanticsNodeUpdate(root);
220 
221  FlutterSemanticsNode2 child1;
222  child1.id = 1;
223  child1.label = "child 1";
224  child1.hint = "";
225  child1.value = "";
226  child1.increased_value = "";
227  child1.decreased_value = "";
228  child1.tooltip = "";
229  child1.child_count = 0;
230  child1.custom_accessibility_actions_count = 0;
231  child1.rect = {0, 0, 50, 50}; // LTRB
232  child1.transform = {0.5, 0, 0, 0, 0.5, 0, 0, 0, 1};
233  bridge->AddFlutterSemanticsNodeUpdate(child1);
234 
235  bridge->CommitUpdates();
236  auto child1_node = bridge->GetFlutterPlatformNodeDelegateFromID(1).lock();
237  auto owner_bridge = child1_node->GetOwnerBridge().lock();
238 
239  bool result;
240  gfx::RectF bounds = owner_bridge->RelativeToGlobalBounds(
241  child1_node->GetAXNode(), result, true);
242  EXPECT_EQ(bounds.x(), 0);
243  EXPECT_EQ(bounds.y(), 0);
244  EXPECT_EQ(bounds.width(), 25);
245  EXPECT_EQ(bounds.height(), 25);
246  EXPECT_EQ(result, false);
247 }
248 
249 TEST(FlutterPlatformNodeDelegateTest, selfIsLowestPlatformAncestor) {
250  std::shared_ptr<TestAccessibilityBridge> bridge =
251  std::make_shared<TestAccessibilityBridge>();
252  FlutterSemanticsNode2 root;
253  root.id = 0;
254  root.label = "root";
255  root.hint = "";
256  root.value = "";
257  root.increased_value = "";
258  root.decreased_value = "";
259  root.tooltip = "";
260  root.child_count = 0;
261  root.children_in_traversal_order = nullptr;
262  root.custom_accessibility_actions_count = 0;
263  bridge->AddFlutterSemanticsNodeUpdate(root);
264 
265  bridge->CommitUpdates();
266  auto root_node = bridge->GetFlutterPlatformNodeDelegateFromID(0).lock();
267  auto lowest_platform_ancestor = root_node->GetLowestPlatformAncestor();
268  EXPECT_EQ(root_node->GetNativeViewAccessible(), lowest_platform_ancestor);
269 }
270 
271 TEST(FlutterPlatformNodeDelegateTest, canGetFromNodeID) {
272  std::shared_ptr<TestAccessibilityBridge> bridge =
273  std::make_shared<TestAccessibilityBridge>();
274  FlutterSemanticsNode2 root;
275  root.id = 0;
276  root.label = "root";
277  root.hint = "";
278  root.value = "";
279  root.increased_value = "";
280  root.decreased_value = "";
281  root.tooltip = "";
282  root.child_count = 1;
283  int32_t children[] = {1};
284  root.children_in_traversal_order = children;
285  root.custom_accessibility_actions_count = 0;
286  bridge->AddFlutterSemanticsNodeUpdate(root);
287 
288  FlutterSemanticsNode2 child1;
289  child1.id = 1;
290  child1.label = "child 1";
291  child1.hint = "";
292  child1.value = "";
293  child1.increased_value = "";
294  child1.decreased_value = "";
295  child1.tooltip = "";
296  child1.child_count = 0;
297  child1.custom_accessibility_actions_count = 0;
298  bridge->AddFlutterSemanticsNodeUpdate(child1);
299 
300  bridge->CommitUpdates();
301  auto root_node = bridge->GetFlutterPlatformNodeDelegateFromID(0).lock();
302  auto child1_node = bridge->GetFlutterPlatformNodeDelegateFromID(1).lock();
303  auto node_by_id = root_node->GetFromNodeID(1);
304  EXPECT_EQ(child1_node->GetPlatformNode(), node_by_id);
305 }
306 
307 } // namespace testing
308 } // namespace flutter
flutter::testing::TEST
TEST(FlutterAppDelegateTest, DoesNotCallDelegatesWithoutHandler)
Definition: FlutterAppDelegateTest.mm:32
flutter
Definition: AccessibilityBridgeMac.h:16
flutter_platform_node_delegate.h
test_accessibility_bridge.h