10 #include "flutter/testing/autoreleasepool_test.h"
11 #include "flutter/testing/testing.h"
21 AccessibilityBridgeMacSpy(__weak
FlutterEngine* flutter_engine,
28 void DispatchMacOSNotification(gfx::NativeViewAccessible native_node,
29 NSAccessibilityNotificationName mac_notification)
override {
38 - (std::shared_ptr<flutter::AccessibilityBridgeMac>)createAccessibilityBridgeWithEngine:
43 - (std::shared_ptr<flutter::AccessibilityBridgeMac>)createAccessibilityBridgeWithEngine:
45 return std::make_shared<flutter::testing::AccessibilityBridgeMacSpy>(
engine,
self);
55 NSString* fixtures = @(testing::GetFixturesPath());
57 initWithAssetsPath:fixtures
58 ICUDataPath:[fixtures stringByAppendingString:@"/icudtl.dat"]];
65 class AccessibilityBridgeMacWindowTest :
public AutoreleasePoolTest {
67 AccessibilityBridgeMacWindowTest() {
69 gWindow_ = [[NSWindow alloc] initWithContentRect:NSMakeRect(0, 0, 800, 600)
70 styleMask:NSBorderlessWindowMask
71 backing:NSBackingStoreBuffered
76 NSWindow* GetWindow()
const {
return gWindow_; }
79 static NSWindow* gWindow_;
80 FML_DISALLOW_COPY_AND_ASSIGN(AccessibilityBridgeMacWindowTest);
83 NSWindow* AccessibilityBridgeMacWindowTest::gWindow_ = nil;
86 using AccessibilityBridgeMacTest = AutoreleasePoolTest;
90 TEST_F(AccessibilityBridgeMacWindowTest, SendsAccessibilityCreateNotificationFlutterViewWindow) {
93 NSWindow* expectedTarget = GetWindow();
94 expectedTarget.contentView = viewController.view;
98 engine.semanticsEnabled = YES;
99 auto bridge = std::static_pointer_cast<AccessibilityBridgeMacSpy>(
100 viewController.accessibilityBridge.lock());
101 FlutterSemanticsNode2 root;
103 root.flags =
static_cast<FlutterSemanticsFlag
>(0);
104 root.actions =
static_cast<FlutterSemanticsAction
>(0);
105 root.text_selection_base = -1;
106 root.text_selection_extent = -1;
110 root.increased_value =
"";
111 root.decreased_value =
"";
113 root.child_count = 0;
114 root.custom_accessibility_actions_count = 0;
115 bridge->AddFlutterSemanticsNodeUpdate(root);
117 bridge->CommitUpdates();
118 auto platform_node_delegate = bridge->GetFlutterPlatformNodeDelegateFromID(0).lock();
122 ui::AXNode ax_node(&tree,
nullptr, 0, 0);
123 ui::AXNodeData node_data;
125 ax_node.SetData(node_data);
126 std::vector<ui::AXEventIntent> intent;
127 ui::AXEventGenerator::EventParams event_params(ui::AXEventGenerator::Event::CHILDREN_CHANGED,
128 ax::mojom::EventFrom::kNone, intent);
129 ui::AXEventGenerator::TargetedEvent targeted_event(&ax_node, event_params);
131 bridge->OnAccessibilityEvent(targeted_event);
133 ASSERT_EQ(bridge->actual_notifications.size(), 1u);
134 auto target = bridge->actual_notifications.find([NSAccessibilityCreatedNotification UTF8String]);
135 ASSERT_NE(target, bridge->actual_notifications.end());
136 EXPECT_EQ(target->second, expectedTarget);
147 TEST_F(AccessibilityBridgeMacWindowTest, NonZeroRootNodeId) {
150 NSWindow* expectedTarget = GetWindow();
151 expectedTarget.contentView = viewController.view;
155 engine.semanticsEnabled = YES;
156 auto bridge = std::static_pointer_cast<AccessibilityBridgeMacSpy>(
157 viewController.accessibilityBridge.lock());
159 FlutterSemanticsNode2 node1;
160 std::vector<int32_t> node1_children{2};
162 node1.flags =
static_cast<FlutterSemanticsFlag
>(0);
163 node1.actions =
static_cast<FlutterSemanticsAction
>(0);
164 node1.text_selection_base = -1;
165 node1.text_selection_extent = -1;
166 node1.label =
"node1";
169 node1.increased_value =
"";
170 node1.decreased_value =
"";
172 node1.child_count = node1_children.size();
173 node1.children_in_traversal_order = node1_children.data();
174 node1.children_in_hit_test_order = node1_children.data();
175 node1.custom_accessibility_actions_count = 0;
177 FlutterSemanticsNode2 node2;
179 node2.flags =
static_cast<FlutterSemanticsFlag
>(0);
180 node2.actions =
static_cast<FlutterSemanticsAction
>(0);
181 node2.text_selection_base = -1;
182 node2.text_selection_extent = -1;
183 node2.label =
"node2";
186 node2.increased_value =
"";
187 node2.decreased_value =
"";
189 node2.child_count = 0;
190 node2.custom_accessibility_actions_count = 0;
192 bridge->AddFlutterSemanticsNodeUpdate(node1);
193 bridge->AddFlutterSemanticsNodeUpdate(node2);
194 bridge->CommitUpdates();
197 auto root_delegate = bridge->GetFlutterPlatformNodeDelegateFromID(1).lock();
198 ASSERT_TRUE(root_delegate);
199 ASSERT_EQ(root_delegate->GetChildCount(), 1);
202 auto child_delegate = bridge->GetFlutterPlatformNodeDelegateFromID(2).lock();
203 ASSERT_TRUE(child_delegate);
204 ASSERT_EQ(child_delegate->GetChildCount(), 0);
207 auto invalid_delegate = bridge->GetFlutterPlatformNodeDelegateFromID(0).lock();
208 ASSERT_FALSE(invalid_delegate);
213 TEST_F(AccessibilityBridgeMacTest, DoesNotSendAccessibilityCreateNotificationWhenHeadless) {
219 engine.semanticsEnabled = YES;
220 auto bridge = std::static_pointer_cast<AccessibilityBridgeMacSpy>(
221 viewController.accessibilityBridge.lock());
222 FlutterSemanticsNode2 root;
224 root.flags =
static_cast<FlutterSemanticsFlag
>(0);
225 root.actions =
static_cast<FlutterSemanticsAction
>(0);
226 root.text_selection_base = -1;
227 root.text_selection_extent = -1;
231 root.increased_value =
"";
232 root.decreased_value =
"";
234 root.child_count = 0;
235 root.custom_accessibility_actions_count = 0;
236 bridge->AddFlutterSemanticsNodeUpdate(root);
238 bridge->CommitUpdates();
239 auto platform_node_delegate = bridge->GetFlutterPlatformNodeDelegateFromID(0).lock();
243 ui::AXNode ax_node(&tree,
nullptr, 0, 0);
244 ui::AXNodeData node_data;
246 ax_node.SetData(node_data);
247 std::vector<ui::AXEventIntent> intent;
248 ui::AXEventGenerator::EventParams event_params(ui::AXEventGenerator::Event::CHILDREN_CHANGED,
249 ax::mojom::EventFrom::kNone, intent);
250 ui::AXEventGenerator::TargetedEvent targeted_event(&ax_node, event_params);
252 bridge->OnAccessibilityEvent(targeted_event);
255 EXPECT_EQ(bridge->actual_notifications.size(), 0u);
259 TEST_F(AccessibilityBridgeMacTest, DoesNotSendAccessibilityCreateNotificationWhenNoWindow) {
265 engine.semanticsEnabled = YES;
266 auto bridge = std::static_pointer_cast<AccessibilityBridgeMacSpy>(
267 viewController.accessibilityBridge.lock());
268 FlutterSemanticsNode2 root;
270 root.flags =
static_cast<FlutterSemanticsFlag
>(0);
271 root.actions =
static_cast<FlutterSemanticsAction
>(0);
272 root.text_selection_base = -1;
273 root.text_selection_extent = -1;
277 root.increased_value =
"";
278 root.decreased_value =
"";
280 root.child_count = 0;
281 root.custom_accessibility_actions_count = 0;
282 bridge->AddFlutterSemanticsNodeUpdate(root);
284 bridge->CommitUpdates();
285 auto platform_node_delegate = bridge->GetFlutterPlatformNodeDelegateFromID(0).lock();
289 ui::AXNode ax_node(&tree,
nullptr, 0, 0);
290 ui::AXNodeData node_data;
292 ax_node.SetData(node_data);
293 std::vector<ui::AXEventIntent> intent;
294 ui::AXEventGenerator::EventParams event_params(ui::AXEventGenerator::Event::CHILDREN_CHANGED,
295 ax::mojom::EventFrom::kNone, intent);
296 ui::AXEventGenerator::TargetedEvent targeted_event(&ax_node, event_params);
298 bridge->OnAccessibilityEvent(targeted_event);
301 EXPECT_EQ(bridge->actual_notifications.size(), 0u);