5#import <OCMock/OCMock.h>
6#import <XCTest/XCTest.h>
43@property(nonatomic, strong) UIView*
view;
49 if (
self = [super init]) {
61- (NSObject<FlutterPlatformView>*)createWithFrame:(CGRect)frame
62 viewIdentifier:(int64_t)viewId
63 arguments:(
id _Nullable)
args {
71class MockDelegate :
public PlatformView::Delegate {
73 void OnPlatformViewCreated(std::unique_ptr<Surface>
surface)
override {}
74 void OnPlatformViewDestroyed()
override {}
75 void OnPlatformViewScheduleFrame()
override {}
76 void OnPlatformViewAddView(int64_t
view_id,
77 const ViewportMetrics& viewport_metrics,
78 AddViewCallback
callback)
override {}
79 void OnPlatformViewRemoveView(int64_t
view_id, RemoveViewCallback
callback)
override {}
80 void OnPlatformViewSendViewFocusEvent(
const ViewFocusEvent& event)
override {};
81 void OnPlatformViewSetNextFrameCallback(
const fml::closure& closure)
override {}
82 void OnPlatformViewSetViewportMetrics(int64_t
view_id,
const ViewportMetrics& metrics)
override {}
84 void OnPlatformViewDispatchPlatformMessage(std::unique_ptr<PlatformMessage>
message)
override {}
85 void OnPlatformViewDispatchPointerDataPacket(std::unique_ptr<PointerDataPacket> packet)
override {
88 return {.has_platform_view =
false};
90 void OnPlatformViewDispatchSemanticsAction(int64_t
view_id,
94 void OnPlatformViewSetSemanticsEnabled(
bool enabled)
override {}
95 void OnPlatformViewSetAccessibilityFeatures(int32_t flags)
override {}
96 void OnPlatformViewRegisterTexture(std::shared_ptr<Texture>
texture)
override {}
97 void OnPlatformViewUnregisterTexture(int64_t
texture_id)
override {}
98 void OnPlatformViewMarkTextureFrameAvailable(int64_t
texture_id)
override {}
100 void LoadDartDeferredLibrary(intptr_t loading_unit_id,
101 std::unique_ptr<const fml::Mapping> snapshot_data,
102 std::unique_ptr<const fml::Mapping> snapshot_instructions)
override {
104 void LoadDartDeferredLibraryError(intptr_t loading_unit_id,
105 const std::string error_message,
106 bool transient)
override {}
107 void UpdateAssetResolverByType(std::unique_ptr<flutter::AssetResolver> updated_asset_resolver,
113class MockIosDelegate :
public AccessibilityBridge::IosDelegate {
115 bool IsFlutterViewControllerPresentingModalViewController(
117 return result_IsFlutterViewControllerPresentingModalViewController_;
120 void PostAccessibilityNotification(UIAccessibilityNotifications notification,
121 id argument)
override {
122 if (on_PostAccessibilityNotification_) {
123 on_PostAccessibilityNotification_(notification, argument);
126 std::function<void(UIAccessibilityNotifications,
id)> on_PostAccessibilityNotification_;
127 bool result_IsFlutterViewControllerPresentingModalViewController_ =
false;
134 auto thread = std::make_unique<fml::Thread>(
name);
135 auto runner = thread->GetTaskRunner();
146 flutter::MockDelegate mock_delegate;
147 auto thread_task_runner = CreateNewThread(
"AccessibilityBridgeTest");
153 auto platform_view = std::make_unique<flutter::PlatformViewIOS>(
155 mock_delegate.settings_.enable_impeller
161 std::make_shared<fml::SyncSwitch>());
163 std::make_unique<flutter::AccessibilityBridge>(nil,
166 XCTAssertTrue(bridge.get());
169- (void)testUpdateSemanticsEmpty {
170 flutter::MockDelegate mock_delegate;
171 auto thread_task_runner = CreateNewThread(
"AccessibilityBridgeTest");
177 auto platform_view = std::make_unique<flutter::PlatformViewIOS>(
179 mock_delegate.settings_.enable_impeller
185 std::make_shared<fml::SyncSwitch>());
186 id mockFlutterView = OCMClassMock([
FlutterView class]);
188 OCMStub([mockFlutterViewController viewIfLoaded]).andReturn(mockFlutterView);
189 OCMExpect([mockFlutterView setAccessibilityElements:[OCMArg isNil]]);
191 std::make_unique<flutter::AccessibilityBridge>(mockFlutterViewController,
196 bridge->UpdateSemantics(nodes, actions);
197 OCMVerifyAll(mockFlutterView);
200- (void)testUpdateSemanticsOneNode {
201 flutter::MockDelegate mock_delegate;
202 auto thread_task_runner = CreateNewThread(
"AccessibilityBridgeTest");
208 auto platform_view = std::make_unique<flutter::PlatformViewIOS>(
210 mock_delegate.settings_.enable_impeller
216 std::make_shared<fml::SyncSwitch>());
217 id mockFlutterView = OCMClassMock([
FlutterView class]);
219 OCMStub([mockFlutterViewController
view]).andReturn(mockFlutterView);
220 std::string label =
"some label";
222 __block
auto bridge =
223 std::make_unique<flutter::AccessibilityBridge>(mockFlutterViewController,
227 OCMExpect([mockFlutterView setAccessibilityElements:[OCMArg checkWithBlock:^BOOL(NSArray* value) {
228 if ([value count] != 1) {
232 SemanticsObject* object = container.semanticsObject;
233 return object.uid == kRootNodeId &&
234 object.bridge.get() == bridge.get() &&
235 object.node.label == label;
242 semantics_node.
label = label;
243 nodes[kRootNodeId] = semantics_node;
245 bridge->UpdateSemantics(nodes, actions);
246 OCMVerifyAll(mockFlutterView);
249- (void)testIsVoiceOverRunning {
250 flutter::MockDelegate mock_delegate;
251 auto thread_task_runner = CreateNewThread(
"AccessibilityBridgeTest");
257 auto platform_view = std::make_unique<flutter::PlatformViewIOS>(
259 mock_delegate.settings_.enable_impeller
265 std::make_shared<fml::SyncSwitch>());
266 id mockFlutterView = OCMClassMock([
FlutterView class]);
268 OCMStub([mockFlutterViewController
view]).andReturn(mockFlutterView);
269 OCMStub([mockFlutterViewController isVoiceOverRunning]).andReturn(YES);
271 __block
auto bridge =
272 std::make_unique<flutter::AccessibilityBridge>(mockFlutterViewController,
276 XCTAssertTrue(bridge->isVoiceOverRunning());
279- (void)testSemanticsDeallocated {
281 flutter::MockDelegate mock_delegate;
282 auto thread_task_runner = CreateNewThread(
"AccessibilityBridgeTest");
293 auto platform_view = std::make_unique<flutter::PlatformViewIOS>(
295 mock_delegate.settings_.enable_impeller
298 flutterPlatformViewsController,
301 std::make_shared<fml::SyncSwitch>());
302 id mockFlutterView = OCMClassMock([
FlutterView class]);
304 OCMStub([mockFlutterViewController
view]).andReturn(mockFlutterView);
305 std::string label =
"some label";
306 flutterPlatformViewsController.
flutterView = mockFlutterView;
309 [flutterPlatformViewsController
311 withId:@"MockFlutterPlatformView"
315 [flutterPlatformViewsController
319 @"viewType" : @"MockFlutterPlatformView"
323 auto bridge = std::make_unique<flutter::AccessibilityBridge>(
324 mockFlutterViewController,
326 flutterPlatformViewsController);
330 semantics_node.
id = 2;
332 semantics_node.
label = label;
333 nodes[kRootNodeId] = semantics_node;
335 bridge->UpdateSemantics(nodes, actions);
337 [flutterPlatformViewsController
reset];
342- (void)testSemanticsDeallocatedWithoutLoadingView {
347 flutter::MockDelegate mock_delegate;
348 auto thread_task_runner = CreateNewThread(
"AccessibilityBridgeTest");
359 auto platform_view = std::make_unique<flutter::PlatformViewIOS>(
361 mock_delegate.settings_.enable_impeller
364 flutterPlatformViewsController,
367 std::make_shared<fml::SyncSwitch>());
370 [flutterPlatformViewsController
372 withId:@"MockFlutterPlatformView"
376 [flutterPlatformViewsController
380 @"viewType" : @"MockFlutterPlatformView"
384 auto bridge = std::make_unique<flutter::AccessibilityBridge>(
385 flutterViewController,
387 flutterPlatformViewsController);
390 [flutterPlatformViewsController
reset];
394 XCTAssertNil(flutterViewController.viewIfLoaded);
395 [flutterViewController deregisterNotifications];
398- (void)testReplacedSemanticsDoesNotCleanupChildren {
399 flutter::MockDelegate mock_delegate;
400 auto thread_task_runner = CreateNewThread(
"AccessibilityBridgeTest");
411 auto platform_view = std::make_unique<flutter::PlatformViewIOS>(
413 mock_delegate.settings_.enable_impeller
416 flutterPlatformViewsController,
419 std::make_shared<fml::SyncSwitch>());
425 OCMStub([mockFlutterViewController
view]).andReturn(flutterView);
426 std::string label =
"some label";
427 auto bridge = std::make_unique<flutter::AccessibilityBridge>(
428 mockFlutterViewController,
430 flutterPlatformViewsController);
435 parent.
rect = SkRect::MakeXYWH(0, 0, 100, 200);
436 parent.
label =
"label";
437 parent.
value =
"value";
438 parent.
hint =
"hint";
442 node.
rect = SkRect::MakeXYWH(0, 0, 100, 200);
443 node.
label =
"label";
444 node.
value =
"value";
453 child.
rect = SkRect::MakeXYWH(0, 0, 100, 200);
454 child.
label =
"label";
455 child.
value =
"value";
464 bridge->UpdateSemantics(nodes, actions);
470 new_node.
rect = SkRect::MakeXYWH(0, 0, 100, 200);
473 new_node.
label =
"label";
474 new_node.
value =
"value";
475 new_node.
hint =
"hint";
481 new_nodes[1] = new_node;
482 bridge->UpdateSemantics(new_nodes, actions);
486 id rootContainer = flutterView.accessibilityElements[0];
487 XCTAssertTrue([rootContainer accessibilityElementCount] ==
489 id scrollableContainer = [rootContainer accessibilityElementAtIndex:1];
490 XCTAssertTrue([scrollableContainer accessibilityElementCount] ==
492 id child = [scrollableContainer accessibilityElementAtIndex:1];
494 XCTAssertNotNil([child accessibilityContainer]);
497- (void)testScrollableSemanticsDeallocated {
498 flutter::MockDelegate mock_delegate;
499 auto thread_task_runner = CreateNewThread(
"AccessibilityBridgeTest");
510 auto platform_view = std::make_unique<flutter::PlatformViewIOS>(
512 mock_delegate.settings_.enable_impeller
515 flutterPlatformViewsController,
518 std::make_shared<fml::SyncSwitch>());
524 OCMStub([mockFlutterViewController
view]).andReturn(flutterView);
525 std::string label =
"some label";
527 auto bridge = std::make_unique<flutter::AccessibilityBridge>(
528 mockFlutterViewController,
530 flutterPlatformViewsController);
535 parent.
rect = SkRect::MakeXYWH(0, 0, 100, 200);
536 parent.
label =
"label";
537 parent.
value =
"value";
538 parent.
hint =
"hint";
544 node.
rect = SkRect::MakeXYWH(0, 0, 100, 200);
545 node.
label =
"label";
546 node.
value =
"value";
555 bridge->UpdateSemantics(nodes, actions);
556 XCTAssertTrue([flutterView.subviews count] == 1);
558 XCTAssertTrue([flutterView.subviews[0].accessibilityLabel isEqualToString:
@"label"]);
564 new_parent.
rect = SkRect::MakeXYWH(0, 0, 100, 200);
565 new_parent.
label =
"label";
566 new_parent.
value =
"value";
567 new_parent.
hint =
"hint";
568 new_nodes[0] = new_parent;
569 bridge->UpdateSemantics(new_nodes, actions);
571 XCTAssertTrue([flutterView.subviews count] == 0);
574- (void)testBridgeReplacesSemanticsNode {
575 flutter::MockDelegate mock_delegate;
576 auto thread_task_runner = CreateNewThread(
"AccessibilityBridgeTest");
585 auto platform_view = std::make_unique<flutter::PlatformViewIOS>(
587 mock_delegate.settings_.enable_impeller
590 flutterPlatformViewsController,
593 std::make_shared<fml::SyncSwitch>());
599 OCMStub([mockFlutterViewController
view]).andReturn(flutterView);
600 std::string label =
"some label";
602 auto bridge = std::make_unique<flutter::AccessibilityBridge>(
603 mockFlutterViewController,
605 flutterPlatformViewsController);
610 parent.
rect = SkRect::MakeXYWH(0, 0, 100, 200);
611 parent.
label =
"label";
612 parent.
value =
"value";
613 parent.
hint =
"hint";
619 node.
rect = SkRect::MakeXYWH(0, 0, 100, 200);
620 node.
label =
"label";
621 node.
value =
"value";
630 bridge->UpdateSemantics(nodes, actions);
631 XCTAssertTrue([flutterView.subviews count] == 1);
633 XCTAssertTrue([flutterView.subviews[0].accessibilityLabel isEqualToString:
@"label"]);
639 new_node.
rect = SkRect::MakeXYWH(0, 0, 100, 200);
640 new_node.
label =
"label";
641 new_node.
value =
"value";
642 new_node.
hint =
"hint";
645 new_nodes[1] = new_node;
646 bridge->UpdateSemantics(new_nodes, actions);
648 XCTAssertTrue([flutterView.subviews count] == 0);
651- (void)testAnnouncesRouteChanges {
652 flutter::MockDelegate mock_delegate;
653 auto thread_task_runner = CreateNewThread(
"AccessibilityBridgeTest");
659 auto platform_view = std::make_unique<flutter::PlatformViewIOS>(
661 mock_delegate.settings_.enable_impeller
667 std::make_shared<fml::SyncSwitch>());
668 id mockFlutterView = OCMClassMock([
FlutterView class]);
670 OCMStub([mockFlutterViewController
view]).andReturn(mockFlutterView);
672 NSMutableArray<NSDictionary<NSString*, id>*>* accessibility_notifications =
673 [[NSMutableArray alloc] init];
674 auto ios_delegate = std::make_unique<flutter::MockIosDelegate>();
675 ios_delegate->on_PostAccessibilityNotification_ =
676 [accessibility_notifications](UIAccessibilityNotifications notification,
id argument) {
677 [accessibility_notifications addObject:@{
678 @"notification" : @(notification),
679 @"argument" : argument ? argument : [NSNull null],
682 __block
auto bridge =
683 std::make_unique<flutter::AccessibilityBridge>(mockFlutterViewController,
686 std::move(ios_delegate));
693 node1.
label =
"node1";
697 nodes[node1.
id] = node1;
700 node2.
label =
"node2";
701 nodes[node2.
id] = node2;
705 node3.
label =
"node3";
706 nodes[node3.
id] = node3;
712 nodes[root_node.
id] = root_node;
713 bridge->UpdateSemantics(nodes, actions);
715 XCTAssertEqual([accessibility_notifications count], 1ul);
716 XCTAssertEqualObjects(accessibility_notifications[0][
@"argument"],
@"node3");
717 XCTAssertEqual([accessibility_notifications[0][
@"notification"] unsignedIntValue],
718 UIAccessibilityScreenChangedNotification);
721- (void)testRadioButtonIsNotSwitchButton {
722 flutter::MockDelegate mock_delegate;
723 auto thread_task_runner = CreateNewThread(
"AccessibilityBridgeTest");
729 auto platform_view = std::make_unique<flutter::PlatformViewIOS>(
731 mock_delegate.settings_.enable_impeller
737 std::make_shared<fml::SyncSwitch>());
743 OCMStub([mockFlutterViewController
view]).andReturn(flutterView);
744 auto ios_delegate = std::make_unique<flutter::MockIosDelegate>();
745 __block
auto bridge =
746 std::make_unique<flutter::AccessibilityBridge>(mockFlutterViewController,
749 std::move(ios_delegate));
759 nodes[root_node.
id] = root_node;
760 bridge->UpdateSemantics(nodes, actions);
765 XCTAssertTrue((rootNode.accessibilityTraits & UIAccessibilityTraitButton) > 0);
766 XCTAssertNil(rootNode.accessibilityValue);
769- (void)testSemanticObjectWithNoAccessibilityFlagNotMarkedAsResponsiveToUserInteraction {
770 flutter::MockDelegate mock_delegate;
771 auto thread_task_runner = CreateNewThread(
"AccessibilityBridgeTest");
777 auto platform_view = std::make_unique<flutter::PlatformViewIOS>(
779 mock_delegate.settings_.enable_impeller
785 std::make_shared<fml::SyncSwitch>());
791 OCMStub([mockFlutterViewController
view]).andReturn(flutterView);
792 auto ios_delegate = std::make_unique<flutter::MockIosDelegate>();
793 __block
auto bridge =
794 std::make_unique<flutter::AccessibilityBridge>(mockFlutterViewController,
797 std::move(ios_delegate));
805 nodes[root_node.
id] = root_node;
806 bridge->UpdateSemantics(nodes, actions);
811 XCTAssertFalse(rootNode.accessibilityRespondsToUserInteraction);
814- (void)testSemanticObjectWithAccessibilityFlagsMarkedAsResponsiveToUserInteraction {
815 flutter::MockDelegate mock_delegate;
816 auto thread_task_runner = CreateNewThread(
"AccessibilityBridgeTest");
822 auto platform_view = std::make_unique<flutter::PlatformViewIOS>(
824 mock_delegate.settings_.enable_impeller
830 std::make_shared<fml::SyncSwitch>());
836 OCMStub([mockFlutterViewController
view]).andReturn(flutterView);
837 auto ios_delegate = std::make_unique<flutter::MockIosDelegate>();
838 __block
auto bridge =
839 std::make_unique<flutter::AccessibilityBridge>(mockFlutterViewController,
842 std::move(ios_delegate));
851 nodes[root_node.
id] = root_node;
852 bridge->UpdateSemantics(nodes, actions);
857 XCTAssertTrue(rootNode.accessibilityRespondsToUserInteraction);
862- (void)testLabeledParentAndChildNotInteractive {
863 flutter::MockDelegate mock_delegate;
864 auto thread_task_runner = CreateNewThread(
"AccessibilityBridgeTest");
873 auto platform_view = std::make_unique<flutter::PlatformViewIOS>(
875 mock_delegate.settings_.enable_impeller
878 flutterPlatformViewsController,
881 std::make_shared<fml::SyncSwitch>());
887 OCMStub([mockFlutterViewController
view]).andReturn(flutterView);
890 auto bridge = std::make_unique<flutter::AccessibilityBridge>(
891 mockFlutterViewController,
893 flutterPlatformViewsController);
899 parent.
rect = SkRect::MakeXYWH(0, 0, 100, 200);
900 parent.
label =
"parent_label";
904 node.
rect = SkRect::MakeXYWH(0, 0, 100, 200);
905 node.
label =
"child_label";
912 bridge->UpdateSemantics(nodes, actions);
918 XCTAssertTrue([parentNode.accessibilityLabel isEqualToString:
@"parent_label"]);
919 XCTAssertTrue([childNode.accessibilityLabel isEqualToString:
@"child_label"]);
920 XCTAssertFalse(parentNode.accessibilityRespondsToUserInteraction);
921 XCTAssertFalse(childNode.accessibilityRespondsToUserInteraction);
925- (void)testLayoutChangeWithNonAccessibilityElement {
926 flutter::MockDelegate mock_delegate;
927 auto thread_task_runner = CreateNewThread(
"AccessibilityBridgeTest");
933 auto platform_view = std::make_unique<flutter::PlatformViewIOS>(
935 mock_delegate.settings_.enable_impeller
941 std::make_shared<fml::SyncSwitch>());
942 id mockFlutterView = OCMClassMock([
FlutterView class]);
944 OCMStub([mockFlutterViewController
view]).andReturn(mockFlutterView);
946 NSMutableArray<NSDictionary<NSString*, id>*>* accessibility_notifications =
947 [[NSMutableArray alloc] init];
948 auto ios_delegate = std::make_unique<flutter::MockIosDelegate>();
949 ios_delegate->on_PostAccessibilityNotification_ =
950 [accessibility_notifications](UIAccessibilityNotifications notification,
id argument) {
951 [accessibility_notifications addObject:@{
952 @"notification" : @(notification),
953 @"argument" : argument ? argument : [NSNull null],
956 __block
auto bridge =
957 std::make_unique<flutter::AccessibilityBridge>(mockFlutterViewController,
960 std::move(ios_delegate));
967 node1.
label =
"node1";
970 nodes[node1.
id] = node1;
973 node2.
label =
"node2";
974 nodes[node2.
id] = node2;
977 node3.
label =
"node3";
978 nodes[node3.
id] = node3;
981 root_node.
label =
"root";
984 nodes[root_node.
id] = root_node;
985 bridge->UpdateSemantics(nodes, actions);
988 bridge->AccessibilityObjectDidBecomeFocused(1);
1000 new_nodes[new_node1.
id] = new_node1;
1001 bridge->UpdateSemantics(new_nodes, new_actions);
1003 XCTAssertEqual([accessibility_notifications count], 1ul);
1004 SemanticsObject* focusObject = accessibility_notifications[0][@"argument"];
1006 XCTAssertEqual([focusObject uid], 2);
1007 XCTAssertEqual([accessibility_notifications[0][
@"notification"] unsignedIntValue],
1008 UIAccessibilityLayoutChangedNotification);
1011- (void)testLayoutChangeDoesCallNativeAccessibility {
1012 flutter::MockDelegate mock_delegate;
1013 auto thread_task_runner = CreateNewThread(
"AccessibilityBridgeTest");
1018 thread_task_runner);
1019 auto platform_view = std::make_unique<flutter::PlatformViewIOS>(
1021 mock_delegate.settings_.enable_impeller
1027 std::make_shared<fml::SyncSwitch>());
1028 id mockFlutterView = OCMClassMock([
FlutterView class]);
1030 OCMStub([mockFlutterViewController
view]).andReturn(mockFlutterView);
1032 NSMutableArray<NSDictionary<NSString*, id>*>* accessibility_notifications =
1033 [[NSMutableArray alloc] init];
1034 auto ios_delegate = std::make_unique<flutter::MockIosDelegate>();
1035 ios_delegate->on_PostAccessibilityNotification_ =
1036 [accessibility_notifications](UIAccessibilityNotifications notification,
id argument) {
1037 [accessibility_notifications addObject:@{
1038 @"notification" : @(notification),
1039 @"argument" : argument ? argument : [NSNull null],
1042 __block
auto bridge =
1043 std::make_unique<flutter::AccessibilityBridge>(mockFlutterViewController,
1046 std::move(ios_delegate));
1053 node1.
label =
"node1";
1054 nodes[node1.
id] = node1;
1057 root_node.
label =
"root";
1061 nodes[root_node.
id] = root_node;
1062 bridge->UpdateSemantics(nodes, actions);
1065 bridge->AccessibilityObjectDidBecomeFocused(0);
1073 new_root_node.
label =
"root";
1075 new_nodes[new_root_node.
id] = new_root_node;
1076 bridge->UpdateSemantics(new_nodes, new_actions);
1078 XCTAssertEqual([accessibility_notifications count], 1ul);
1079 id focusObject = accessibility_notifications[0][@"argument"];
1083 XCTAssertEqualObjects(focusObject, [NSNull null]);
1084 XCTAssertEqual([accessibility_notifications[0][
@"notification"] unsignedIntValue],
1085 UIAccessibilityLayoutChangedNotification);
1088- (void)testLayoutChangeDoesCallNativeAccessibilityWhenFocusChanged {
1089 flutter::MockDelegate mock_delegate;
1090 auto thread_task_runner = CreateNewThread(
"AccessibilityBridgeTest");
1095 thread_task_runner);
1096 auto platform_view = std::make_unique<flutter::PlatformViewIOS>(
1098 mock_delegate.settings_.enable_impeller
1104 std::make_shared<fml::SyncSwitch>());
1105 id mockFlutterView = OCMClassMock([
FlutterView class]);
1107 OCMStub([mockFlutterViewController
view]).andReturn(mockFlutterView);
1109 NSMutableArray<NSDictionary<NSString*, id>*>* accessibility_notifications =
1110 [[NSMutableArray alloc] init];
1111 auto ios_delegate = std::make_unique<flutter::MockIosDelegate>();
1112 ios_delegate->on_PostAccessibilityNotification_ =
1113 [accessibility_notifications](UIAccessibilityNotifications notification,
id argument) {
1114 [accessibility_notifications addObject:@{
1115 @"notification" : @(notification),
1116 @"argument" : argument ? argument : [NSNull null],
1119 __block
auto bridge =
1120 std::make_unique<flutter::AccessibilityBridge>(mockFlutterViewController,
1123 std::move(ios_delegate));
1130 node1.
label =
"node1";
1131 nodes[node1.
id] = node1;
1134 root_node.
label =
"root";
1138 nodes[root_node.
id] = root_node;
1139 bridge->UpdateSemantics(nodes, actions);
1142 bridge->AccessibilityObjectDidBecomeFocused(1);
1150 new_root_node.
label =
"root";
1152 new_nodes[new_root_node.
id] = new_root_node;
1153 bridge->UpdateSemantics(new_nodes, new_actions);
1155 XCTAssertEqual([accessibility_notifications count], 1ul);
1156 SemanticsObject* focusObject2 = accessibility_notifications[0][@"argument"];
1160 XCTAssertEqual([accessibility_notifications[0][
@"notification"] unsignedIntValue],
1161 UIAccessibilityLayoutChangedNotification);
1164- (void)testScrollableSemanticsContainerReturnsCorrectChildren {
1165 flutter::MockDelegate mock_delegate;
1166 auto thread_task_runner = CreateNewThread(
"AccessibilityBridgeTest");
1171 thread_task_runner);
1172 auto platform_view = std::make_unique<flutter::PlatformViewIOS>(
1174 mock_delegate.settings_.enable_impeller
1180 std::make_shared<fml::SyncSwitch>());
1181 id mockFlutterView = OCMClassMock([
FlutterView class]);
1183 OCMStub([mockFlutterViewController
view]).andReturn(mockFlutterView);
1185 OCMExpect([mockFlutterView
1186 setAccessibilityElements:[OCMArg checkWithBlock:^BOOL(NSArray* value) {
1187 if ([value count] != 1) {
1190 SemanticsObjectContainer* container = value[0];
1191 SemanticsObject* object = container.semanticsObject;
1192 FlutterScrollableSemanticsObject* scrollable =
1193 (FlutterScrollableSemanticsObject*)object.children[0];
1194 id nativeScrollable = scrollable.nativeAccessibility;
1195 SemanticsObjectContainer* scrollableContainer = [nativeScrollable accessibilityContainer];
1196 return [scrollableContainer indexOfAccessibilityElement:nativeScrollable] == 1;
1198 auto ios_delegate = std::make_unique<flutter::MockIosDelegate>();
1199 __block
auto bridge =
1200 std::make_unique<flutter::AccessibilityBridge>(mockFlutterViewController,
1203 std::move(ios_delegate));
1210 node1.
label =
"node1";
1212 nodes[node1.
id] = node1;
1215 root_node.
label =
"root";
1218 nodes[root_node.
id] = root_node;
1219 bridge->UpdateSemantics(nodes, actions);
1220 OCMVerifyAll(mockFlutterView);
1223- (void)testAnnouncesRouteChangesAndLayoutChangeInOneUpdate {
1224 flutter::MockDelegate mock_delegate;
1225 auto thread_task_runner = CreateNewThread(
"AccessibilityBridgeTest");
1230 thread_task_runner);
1231 auto platform_view = std::make_unique<flutter::PlatformViewIOS>(
1233 mock_delegate.settings_.enable_impeller
1239 std::make_shared<fml::SyncSwitch>());
1240 id mockFlutterView = OCMClassMock([
FlutterView class]);
1242 OCMStub([mockFlutterViewController
view]).andReturn(mockFlutterView);
1244 NSMutableArray<NSDictionary<NSString*, id>*>* accessibility_notifications =
1245 [[NSMutableArray alloc] init];
1246 auto ios_delegate = std::make_unique<flutter::MockIosDelegate>();
1247 ios_delegate->on_PostAccessibilityNotification_ =
1248 [accessibility_notifications](UIAccessibilityNotifications notification,
id argument) {
1249 [accessibility_notifications addObject:@{
1250 @"notification" : @(notification),
1251 @"argument" : argument ? argument : [NSNull null],
1254 __block
auto bridge =
1255 std::make_unique<flutter::AccessibilityBridge>(mockFlutterViewController,
1258 std::move(ios_delegate));
1265 node1.
label =
"node1";
1268 nodes[node1.
id] = node1;
1271 node3.
label =
"node3";
1272 nodes[node3.
id] = node3;
1275 root_node.
label =
"root";
1278 nodes[root_node.
id] = root_node;
1279 bridge->UpdateSemantics(nodes, actions);
1281 XCTAssertEqual([accessibility_notifications count], 1ul);
1282 XCTAssertEqualObjects(accessibility_notifications[0][
@"argument"],
@"node1");
1283 XCTAssertEqual([accessibility_notifications[0][
@"notification"] unsignedIntValue],
1284 UIAccessibilityScreenChangedNotification);
1287 bridge->AccessibilityObjectDidBecomeFocused(0);
1293 new_node1.
label =
"new_node1";
1298 new_nodes[new_node1.
id] = new_node1;
1301 new_node2.
label =
"new_node2";
1304 new_nodes[new_node2.
id] = new_node2;
1307 new_root_node.
label =
"root";
1310 new_nodes[new_root_node.
id] = new_root_node;
1311 bridge->UpdateSemantics(new_nodes, actions);
1312 XCTAssertEqual([accessibility_notifications count], 3ul);
1313 XCTAssertEqualObjects(accessibility_notifications[1][
@"argument"],
@"new_node2");
1314 XCTAssertEqual([accessibility_notifications[1][
@"notification"] unsignedIntValue],
1315 UIAccessibilityScreenChangedNotification);
1316 SemanticsObject* focusObject = accessibility_notifications[2][@"argument"];
1317 XCTAssertEqual([focusObject uid], 0);
1318 XCTAssertEqual([accessibility_notifications[2][
@"notification"] unsignedIntValue],
1319 UIAccessibilityLayoutChangedNotification);
1322- (void)testAnnouncesRouteChangesWhenAddAdditionalRoute {
1323 flutter::MockDelegate mock_delegate;
1324 auto thread_task_runner = CreateNewThread(
"AccessibilityBridgeTest");
1329 thread_task_runner);
1330 auto platform_view = std::make_unique<flutter::PlatformViewIOS>(
1332 mock_delegate.settings_.enable_impeller
1338 std::make_shared<fml::SyncSwitch>());
1339 id mockFlutterView = OCMClassMock([
FlutterView class]);
1341 OCMStub([mockFlutterViewController
view]).andReturn(mockFlutterView);
1343 NSMutableArray<NSDictionary<NSString*, id>*>* accessibility_notifications =
1344 [[NSMutableArray alloc] init];
1345 auto ios_delegate = std::make_unique<flutter::MockIosDelegate>();
1346 ios_delegate->on_PostAccessibilityNotification_ =
1347 [accessibility_notifications](UIAccessibilityNotifications notification,
id argument) {
1348 [accessibility_notifications addObject:@{
1349 @"notification" : @(notification),
1350 @"argument" : argument ? argument : [NSNull null],
1353 __block
auto bridge =
1354 std::make_unique<flutter::AccessibilityBridge>(mockFlutterViewController,
1357 std::move(ios_delegate));
1364 node1.
label =
"node1";
1367 nodes[node1.
id] = node1;
1373 nodes[root_node.
id] = root_node;
1374 bridge->UpdateSemantics(nodes, actions);
1376 XCTAssertEqual([accessibility_notifications count], 1ul);
1377 XCTAssertEqualObjects(accessibility_notifications[0][
@"argument"],
@"node1");
1378 XCTAssertEqual([accessibility_notifications[0][
@"notification"] unsignedIntValue],
1379 UIAccessibilityScreenChangedNotification);
1385 new_node1.
label =
"new_node1";
1390 new_nodes[new_node1.
id] = new_node1;
1393 new_node2.
label =
"new_node2";
1396 new_nodes[new_node2.
id] = new_node2;
1402 new_nodes[new_root_node.
id] = new_root_node;
1403 bridge->UpdateSemantics(new_nodes, actions);
1404 XCTAssertEqual([accessibility_notifications count], 2ul);
1405 XCTAssertEqualObjects(accessibility_notifications[1][
@"argument"],
@"new_node2");
1406 XCTAssertEqual([accessibility_notifications[1][
@"notification"] unsignedIntValue],
1407 UIAccessibilityScreenChangedNotification);
1410- (void)testAnnouncesRouteChangesRemoveRouteInMiddle {
1411 flutter::MockDelegate mock_delegate;
1412 auto thread_task_runner = CreateNewThread(
"AccessibilityBridgeTest");
1417 thread_task_runner);
1418 auto platform_view = std::make_unique<flutter::PlatformViewIOS>(
1420 mock_delegate.settings_.enable_impeller
1426 std::make_shared<fml::SyncSwitch>());
1427 id mockFlutterView = OCMClassMock([
FlutterView class]);
1429 OCMStub([mockFlutterViewController
view]).andReturn(mockFlutterView);
1431 NSMutableArray<NSDictionary<NSString*, id>*>* accessibility_notifications =
1432 [[NSMutableArray alloc] init];
1433 auto ios_delegate = std::make_unique<flutter::MockIosDelegate>();
1434 ios_delegate->on_PostAccessibilityNotification_ =
1435 [accessibility_notifications](UIAccessibilityNotifications notification,
id argument) {
1436 [accessibility_notifications addObject:@{
1437 @"notification" : @(notification),
1438 @"argument" : argument ? argument : [NSNull null],
1441 __block
auto bridge =
1442 std::make_unique<flutter::AccessibilityBridge>(mockFlutterViewController,
1445 std::move(ios_delegate));
1452 node1.
label =
"node1";
1457 nodes[node1.
id] = node1;
1460 node2.
label =
"node2";
1463 nodes[node2.
id] = node2;
1469 nodes[root_node.
id] = root_node;
1470 bridge->UpdateSemantics(nodes, actions);
1472 XCTAssertEqual([accessibility_notifications count], 1ul);
1473 XCTAssertEqualObjects(accessibility_notifications[0][
@"argument"],
@"node2");
1474 XCTAssertEqual([accessibility_notifications[0][
@"notification"] unsignedIntValue],
1475 UIAccessibilityScreenChangedNotification);
1481 new_node1.
label =
"new_node1";
1484 new_nodes[new_node1.
id] = new_node1;
1487 new_node2.
label =
"new_node2";
1490 new_nodes[new_node2.
id] = new_node2;
1496 new_nodes[new_root_node.
id] = new_root_node;
1497 bridge->UpdateSemantics(new_nodes, actions);
1498 XCTAssertEqual([accessibility_notifications count], 2ul);
1499 XCTAssertEqualObjects(accessibility_notifications[1][
@"argument"],
@"new_node2");
1500 XCTAssertEqual([accessibility_notifications[1][
@"notification"] unsignedIntValue],
1501 UIAccessibilityScreenChangedNotification);
1504- (void)testHandleEvent {
1505 flutter::MockDelegate mock_delegate;
1506 auto thread_task_runner = CreateNewThread(
"AccessibilityBridgeTest");
1511 thread_task_runner);
1512 auto platform_view = std::make_unique<flutter::PlatformViewIOS>(
1514 mock_delegate.settings_.enable_impeller
1520 std::make_shared<fml::SyncSwitch>());
1521 id mockFlutterView = OCMClassMock([
FlutterView class]);
1523 OCMStub([mockFlutterViewController
view]).andReturn(mockFlutterView);
1525 NSMutableArray<NSDictionary<NSString*, id>*>* accessibility_notifications =
1526 [[NSMutableArray alloc] init];
1527 auto ios_delegate = std::make_unique<flutter::MockIosDelegate>();
1528 ios_delegate->on_PostAccessibilityNotification_ =
1529 [accessibility_notifications](UIAccessibilityNotifications notification,
id argument) {
1530 [accessibility_notifications addObject:@{
1531 @"notification" : @(notification),
1532 @"argument" : argument ? argument : [NSNull null],
1535 __block
auto bridge =
1536 std::make_unique<flutter::AccessibilityBridge>(mockFlutterViewController,
1539 std::move(ios_delegate));
1541 NSDictionary<NSString*, id>* annotatedEvent = @{
@"type" :
@"focus",
@"nodeId" : @123};
1543 bridge->HandleEvent(annotatedEvent);
1545 XCTAssertEqual([accessibility_notifications count], 1ul);
1546 XCTAssertEqual([accessibility_notifications[0][
@"notification"] unsignedIntValue],
1547 UIAccessibilityLayoutChangedNotification);
1550- (void)testAccessibilityObjectDidBecomeFocused {
1551 flutter::MockDelegate mock_delegate;
1552 auto thread = std::make_unique<fml::Thread>(
"AccessibilityBridgeTest");
1553 auto thread_task_runner = thread->GetTaskRunner();
1558 thread_task_runner);
1559 id messenger = OCMProtocolMock(
@protocol(FlutterBinaryMessenger));
1563 OCMStub([flutterViewController
engine]).andReturn(
engine);
1564 OCMStub([
engine binaryMessenger]).andReturn(messenger);
1566 OCMStub([messenger setMessageHandlerOnChannel:
@"flutter/accessibility"
1567 binaryMessageHandler:[OCMArg any]])
1568 .andReturn(connection);
1570 auto platform_view = std::make_unique<flutter::PlatformViewIOS>(
1572 mock_delegate.settings_.enable_impeller
1578 std::make_shared<fml::SyncSwitch>());
1580 thread_task_runner->PostTask([&] {
1581 platform_view->SetOwnerViewController(flutterViewController);
1583 std::make_unique<flutter::AccessibilityBridge>(nil,
1586 XCTAssertTrue(bridge.get());
1587 OCMVerify([messenger setMessageHandlerOnChannel:
@"flutter/accessibility"
1588 binaryMessageHandler:[OCMArg isNotNil]]);
1590 bridge->AccessibilityObjectDidBecomeFocused(123);
1592 NSDictionary<NSString*, id>* annotatedEvent = @{
@"type" :
@"didGainFocus",
@"nodeId" : @123};
1595 OCMVerify([messenger sendOnChannel:
@"flutter/accessibility" message:encodedMessage]);
1600 [engine stopMocking];
1603- (void)testAnnouncesRouteChangesWhenNoNamesRoute {
1604 flutter::MockDelegate mock_delegate;
1605 auto thread_task_runner = CreateNewThread(
"AccessibilityBridgeTest");
1610 thread_task_runner);
1611 auto platform_view = std::make_unique<flutter::PlatformViewIOS>(
1613 mock_delegate.settings_.enable_impeller
1619 std::make_shared<fml::SyncSwitch>());
1620 id mockFlutterView = OCMClassMock([
FlutterView class]);
1622 OCMStub([mockFlutterViewController
view]).andReturn(mockFlutterView);
1624 NSMutableArray<NSDictionary<NSString*, id>*>* accessibility_notifications =
1625 [[NSMutableArray alloc] init];
1626 auto ios_delegate = std::make_unique<flutter::MockIosDelegate>();
1627 ios_delegate->on_PostAccessibilityNotification_ =
1628 [accessibility_notifications](UIAccessibilityNotifications notification,
id argument) {
1629 [accessibility_notifications addObject:@{
1630 @"notification" : @(notification),
1631 @"argument" : argument ? argument : [NSNull null],
1634 __block
auto bridge =
1635 std::make_unique<flutter::AccessibilityBridge>(mockFlutterViewController,
1638 std::move(ios_delegate));
1645 node1.
label =
"node1";
1650 nodes[node1.
id] = node1;
1653 node2.
label =
"node2";
1654 nodes[node2.
id] = node2;
1657 node3.
label =
"node3";
1658 nodes[node3.
id] = node3;
1663 nodes[root_node.
id] = root_node;
1664 bridge->UpdateSemantics(nodes, actions);
1667 XCTAssertEqual([accessibility_notifications count], 1ul);
1668 id focusObject = accessibility_notifications[0][@"argument"];
1669 XCTAssertTrue([focusObject isKindOfClass:[NSString class]]);
1670 XCTAssertEqualObjects(focusObject,
@"node1");
1671 XCTAssertEqual([accessibility_notifications[0][
@"notification"] unsignedIntValue],
1672 UIAccessibilityScreenChangedNotification);
1675- (void)testAnnouncesLayoutChangeWithNilIfLastFocusIsRemoved {
1676 flutter::MockDelegate mock_delegate;
1677 auto thread_task_runner = CreateNewThread(
"AccessibilityBridgeTest");
1682 thread_task_runner);
1683 auto platform_view = std::make_unique<flutter::PlatformViewIOS>(
1685 mock_delegate.settings_.enable_impeller
1691 std::make_shared<fml::SyncSwitch>());
1693 id mockFlutterView = OCMClassMock([
FlutterView class]);
1694 OCMStub([mockFlutterViewController
view]).andReturn(mockFlutterView);
1696 NSMutableArray<NSDictionary<NSString*, id>*>* accessibility_notifications =
1697 [[NSMutableArray alloc] init];
1698 auto ios_delegate = std::make_unique<flutter::MockIosDelegate>();
1699 ios_delegate->on_PostAccessibilityNotification_ =
1700 [accessibility_notifications](UIAccessibilityNotifications notification,
id argument) {
1701 [accessibility_notifications addObject:@{
1702 @"notification" : @(notification),
1703 @"argument" : argument ? argument : [NSNull null],
1706 __block
auto bridge =
1707 std::make_unique<flutter::AccessibilityBridge>(mockFlutterViewController,
1710 std::move(ios_delegate));
1717 route_node.
label =
"route";
1718 first_update[route_node.
id] = route_node;
1721 root_node.
label =
"root";
1724 first_update[root_node.
id] = root_node;
1725 bridge->UpdateSemantics(first_update, actions);
1727 XCTAssertEqual([accessibility_notifications count], 0ul);
1729 bridge->AccessibilityObjectDidBecomeFocused(1);
1735 new_root_node.
label =
"root";
1736 second_update[root_node.
id] = new_root_node;
1737 bridge->UpdateSemantics(second_update, actions);
1738 SemanticsObject* focusObject = accessibility_notifications[0][@"argument"];
1740 XCTAssertEqual([focusObject uid], 0);
1741 XCTAssertEqualObjects([focusObject accessibilityLabel],
@"root");
1742 XCTAssertEqual([accessibility_notifications[0][
@"notification"] unsignedIntValue],
1743 UIAccessibilityLayoutChangedNotification);
1746- (void)testAnnouncesLayoutChangeWithTheSameItemFocused {
1747 flutter::MockDelegate mock_delegate;
1748 auto thread_task_runner = CreateNewThread(
"AccessibilityBridgeTest");
1753 thread_task_runner);
1754 auto platform_view = std::make_unique<flutter::PlatformViewIOS>(
1756 mock_delegate.settings_.enable_impeller
1762 std::make_shared<fml::SyncSwitch>());
1764 id mockFlutterView = OCMClassMock([
FlutterView class]);
1765 OCMStub([mockFlutterViewController
view]).andReturn(mockFlutterView);
1767 NSMutableArray<NSDictionary<NSString*, id>*>* accessibility_notifications =
1768 [[NSMutableArray alloc] init];
1769 auto ios_delegate = std::make_unique<flutter::MockIosDelegate>();
1770 ios_delegate->on_PostAccessibilityNotification_ =
1771 [accessibility_notifications](UIAccessibilityNotifications notification,
id argument) {
1772 [accessibility_notifications addObject:@{
1773 @"notification" : @(notification),
1774 @"argument" : argument ? argument : [NSNull null],
1777 __block
auto bridge =
1778 std::make_unique<flutter::AccessibilityBridge>(mockFlutterViewController,
1781 std::move(ios_delegate));
1788 node_one.
label =
"route1";
1789 first_update[node_one.
id] = node_one;
1792 node_two.
label =
"route2";
1793 first_update[node_two.
id] = node_two;
1796 root_node.
label =
"root";
1799 first_update[root_node.
id] = root_node;
1800 bridge->UpdateSemantics(first_update, actions);
1802 XCTAssertEqual([accessibility_notifications count], 0ul);
1804 bridge->AccessibilityObjectDidBecomeFocused(1);
1810 new_root_node.
label =
"root";
1813 second_update[root_node.
id] = new_root_node;
1814 bridge->UpdateSemantics(second_update, actions);
1815 id focusObject = accessibility_notifications[0][@"argument"];
1818 XCTAssertEqualObjects(focusObject, [NSNull null]);
1819 XCTAssertEqual([accessibility_notifications[0][
@"notification"] unsignedIntValue],
1820 UIAccessibilityLayoutChangedNotification);
1823- (void)testAnnouncesLayoutChangeWhenFocusMovedOutside {
1824 flutter::MockDelegate mock_delegate;
1825 auto thread_task_runner = CreateNewThread(
"AccessibilityBridgeTest");
1830 thread_task_runner);
1831 auto platform_view = std::make_unique<flutter::PlatformViewIOS>(
1833 mock_delegate.settings_.enable_impeller
1839 std::make_shared<fml::SyncSwitch>());
1841 id mockFlutterView = OCMClassMock([
FlutterView class]);
1842 OCMStub([mockFlutterViewController
view]).andReturn(mockFlutterView);
1844 NSMutableArray<NSDictionary<NSString*, id>*>* accessibility_notifications =
1845 [[NSMutableArray alloc] init];
1846 auto ios_delegate = std::make_unique<flutter::MockIosDelegate>();
1847 ios_delegate->on_PostAccessibilityNotification_ =
1848 [accessibility_notifications](UIAccessibilityNotifications notification,
id argument) {
1849 [accessibility_notifications addObject:@{
1850 @"notification" : @(notification),
1851 @"argument" : argument ? argument : [NSNull null],
1854 __block
auto bridge =
1855 std::make_unique<flutter::AccessibilityBridge>(mockFlutterViewController,
1858 std::move(ios_delegate));
1865 node_one.
label =
"route1";
1866 first_update[node_one.
id] = node_one;
1869 node_two.
label =
"route2";
1870 first_update[node_two.
id] = node_two;
1873 root_node.
label =
"root";
1876 first_update[root_node.
id] = root_node;
1877 bridge->UpdateSemantics(first_update, actions);
1879 XCTAssertEqual([accessibility_notifications count], 0ul);
1881 bridge->AccessibilityObjectDidBecomeFocused(1);
1883 bridge->AccessibilityObjectDidLoseFocus(1);
1889 new_root_node.
label =
"root";
1892 second_update[root_node.
id] = new_root_node;
1893 bridge->UpdateSemantics(second_update, actions);
1894 NSNull* focusObject = accessibility_notifications[0][@"argument"];
1897 XCTAssertEqual(focusObject, [NSNull null]);
1898 XCTAssertEqual([accessibility_notifications[0][
@"notification"] unsignedIntValue],
1899 UIAccessibilityLayoutChangedNotification);
1902- (void)testAnnouncesScrollChangeWithLastFocused {
1903 flutter::MockDelegate mock_delegate;
1904 auto thread_task_runner = CreateNewThread(
"AccessibilityBridgeTest");
1909 thread_task_runner);
1910 auto platform_view = std::make_unique<flutter::PlatformViewIOS>(
1912 mock_delegate.settings_.enable_impeller
1918 std::make_shared<fml::SyncSwitch>());
1920 id mockFlutterView = OCMClassMock([
FlutterView class]);
1921 OCMStub([mockFlutterViewController
view]).andReturn(mockFlutterView);
1923 NSMutableArray<NSDictionary<NSString*, id>*>* accessibility_notifications =
1924 [[NSMutableArray alloc] init];
1925 auto ios_delegate = std::make_unique<flutter::MockIosDelegate>();
1926 ios_delegate->on_PostAccessibilityNotification_ =
1927 [accessibility_notifications](UIAccessibilityNotifications notification,
id argument) {
1928 [accessibility_notifications addObject:@{
1929 @"notification" : @(notification),
1930 @"argument" : argument ? argument : [NSNull null],
1933 __block
auto bridge =
1934 std::make_unique<flutter::AccessibilityBridge>(mockFlutterViewController,
1937 std::move(ios_delegate));
1944 node_one.
label =
"route1";
1946 first_update[node_one.
id] = node_one;
1949 root_node.
label =
"root";
1952 first_update[root_node.
id] = root_node;
1953 bridge->UpdateSemantics(first_update, actions);
1956 [accessibility_notifications removeAllObjects];
1959 bridge->AccessibilityObjectDidBecomeFocused(1);
1964 new_node_one.
id = 1;
1965 new_node_one.
label =
"route1";
1967 second_update[new_node_one.
id] = new_node_one;
1968 bridge->UpdateSemantics(second_update, actions);
1969 SemanticsObject* focusObject = accessibility_notifications[0][@"argument"];
1972 XCTAssertEqual([focusObject uid], 1);
1973 XCTAssertEqual([accessibility_notifications[0][
@"notification"] unsignedIntValue],
1974 UIAccessibilityPageScrolledNotification);
1977- (void)testAnnouncesScrollChangeDoesCallNativeAccessibility {
1978 flutter::MockDelegate mock_delegate;
1979 auto thread_task_runner = CreateNewThread(
"AccessibilityBridgeTest");
1984 thread_task_runner);
1985 auto platform_view = std::make_unique<flutter::PlatformViewIOS>(
1987 mock_delegate.settings_.enable_impeller
1993 std::make_shared<fml::SyncSwitch>());
1995 id mockFlutterView = OCMClassMock([
FlutterView class]);
1996 OCMStub([mockFlutterViewController
view]).andReturn(mockFlutterView);
1998 NSMutableArray<NSDictionary<NSString*, id>*>* accessibility_notifications =
1999 [[NSMutableArray alloc] init];
2000 auto ios_delegate = std::make_unique<flutter::MockIosDelegate>();
2001 ios_delegate->on_PostAccessibilityNotification_ =
2002 [accessibility_notifications](UIAccessibilityNotifications notification,
id argument) {
2003 [accessibility_notifications addObject:@{
2004 @"notification" : @(notification),
2005 @"argument" : argument ? argument : [NSNull null],
2008 __block
auto bridge =
2009 std::make_unique<flutter::AccessibilityBridge>(mockFlutterViewController,
2012 std::move(ios_delegate));
2019 node_one.
label =
"route1";
2022 first_update[node_one.
id] = node_one;
2025 root_node.
label =
"root";
2028 first_update[root_node.
id] = root_node;
2029 bridge->UpdateSemantics(first_update, actions);
2032 [accessibility_notifications removeAllObjects];
2035 bridge->AccessibilityObjectDidBecomeFocused(1);
2040 new_node_one.
id = 1;
2041 new_node_one.
label =
"route1";
2044 second_update[new_node_one.
id] = new_node_one;
2045 bridge->UpdateSemantics(second_update, actions);
2046 SemanticsObject* focusObject = accessibility_notifications[0][@"argument"];
2050 XCTAssertEqual([accessibility_notifications[0][
@"notification"] unsignedIntValue],
2051 UIAccessibilityPageScrolledNotification);
2054- (void)testAnnouncesIgnoresRouteChangesWhenModal {
2055 flutter::MockDelegate mock_delegate;
2056 auto thread_task_runner = CreateNewThread(
"AccessibilityBridgeTest");
2061 thread_task_runner);
2062 auto platform_view = std::make_unique<flutter::PlatformViewIOS>(
2064 mock_delegate.settings_.enable_impeller
2070 std::make_shared<fml::SyncSwitch>());
2071 id mockFlutterView = OCMClassMock([
FlutterView class]);
2073 OCMStub([mockFlutterViewController
view]).andReturn(mockFlutterView);
2074 std::string label =
"some label";
2076 NSMutableArray<NSDictionary<NSString*, id>*>* accessibility_notifications =
2077 [[NSMutableArray alloc] init];
2078 auto ios_delegate = std::make_unique<flutter::MockIosDelegate>();
2079 ios_delegate->on_PostAccessibilityNotification_ =
2080 [accessibility_notifications](UIAccessibilityNotifications notification,
id argument) {
2081 [accessibility_notifications addObject:@{
2082 @"notification" : @(notification),
2083 @"argument" : argument ? argument : [NSNull null],
2086 ios_delegate->result_IsFlutterViewControllerPresentingModalViewController_ =
true;
2087 __block
auto bridge =
2088 std::make_unique<flutter::AccessibilityBridge>(mockFlutterViewController,
2091 std::move(ios_delegate));
2100 route_node.
label =
"route";
2101 nodes[route_node.
id] = route_node;
2104 root_node.
label = label;
2107 nodes[root_node.
id] = root_node;
2108 bridge->UpdateSemantics(nodes, actions);
2110 XCTAssertEqual([accessibility_notifications count], 0ul);
2113- (void)testAnnouncesIgnoresLayoutChangeWhenModal {
2114 flutter::MockDelegate mock_delegate;
2115 auto thread_task_runner = CreateNewThread(
"AccessibilityBridgeTest");
2120 thread_task_runner);
2121 auto platform_view = std::make_unique<flutter::PlatformViewIOS>(
2123 mock_delegate.settings_.enable_impeller
2129 std::make_shared<fml::SyncSwitch>());
2130 id mockFlutterView = OCMClassMock([
FlutterView class]);
2132 OCMStub([mockFlutterViewController
view]).andReturn(mockFlutterView);
2134 NSMutableArray<NSDictionary<NSString*, id>*>* accessibility_notifications =
2135 [[NSMutableArray alloc] init];
2136 auto ios_delegate = std::make_unique<flutter::MockIosDelegate>();
2137 ios_delegate->on_PostAccessibilityNotification_ =
2138 [accessibility_notifications](UIAccessibilityNotifications notification,
id argument) {
2139 [accessibility_notifications addObject:@{
2140 @"notification" : @(notification),
2141 @"argument" : argument ? argument : [NSNull null],
2144 ios_delegate->result_IsFlutterViewControllerPresentingModalViewController_ =
true;
2145 __block
auto bridge =
2146 std::make_unique<flutter::AccessibilityBridge>(mockFlutterViewController,
2149 std::move(ios_delegate));
2156 child_node.
label =
"child_node";
2157 nodes[child_node.
id] = child_node;
2160 root_node.
label =
"root";
2163 nodes[root_node.
id] = root_node;
2164 bridge->UpdateSemantics(nodes, actions);
2170 new_root_node.
label =
"root";
2171 new_nodes[new_root_node.
id] = new_root_node;
2172 bridge->UpdateSemantics(new_nodes, actions);
2174 XCTAssertEqual([accessibility_notifications count], 0ul);
2177- (void)testAnnouncesIgnoresScrollChangeWhenModal {
2178 flutter::MockDelegate mock_delegate;
2179 auto thread_task_runner = CreateNewThread(
"AccessibilityBridgeTest");
2184 thread_task_runner);
2185 auto platform_view = std::make_unique<flutter::PlatformViewIOS>(
2187 mock_delegate.settings_.enable_impeller
2193 std::make_shared<fml::SyncSwitch>());
2194 id mockFlutterView = OCMClassMock([
FlutterView class]);
2196 OCMStub([mockFlutterViewController
view]).andReturn(mockFlutterView);
2198 NSMutableArray<NSDictionary<NSString*, id>*>* accessibility_notifications =
2199 [[NSMutableArray alloc] init];
2200 auto ios_delegate = std::make_unique<flutter::MockIosDelegate>();
2201 ios_delegate->on_PostAccessibilityNotification_ =
2202 [accessibility_notifications](UIAccessibilityNotifications notification,
id argument) {
2203 [accessibility_notifications addObject:@{
2204 @"notification" : @(notification),
2205 @"argument" : argument ? argument : [NSNull null],
2208 ios_delegate->result_IsFlutterViewControllerPresentingModalViewController_ =
true;
2209 __block
auto bridge =
2210 std::make_unique<flutter::AccessibilityBridge>(mockFlutterViewController,
2213 std::move(ios_delegate));
2220 root_node.
label =
"root";
2222 nodes[root_node.
id] = root_node;
2223 bridge->UpdateSemantics(nodes, actions);
2229 new_root_node.
label =
"root";
2231 new_nodes[new_root_node.
id] = new_root_node;
2232 bridge->UpdateSemantics(new_nodes, actions);
2234 XCTAssertEqual([accessibility_notifications count], 0ul);
2237- (void)testAccessibilityMessageAfterDeletion {
2238 flutter::MockDelegate mock_delegate;
2239 auto thread = std::make_unique<fml::Thread>(
"AccessibilityBridgeTest");
2240 auto thread_task_runner = thread->GetTaskRunner();
2245 thread_task_runner);
2246 id messenger = OCMProtocolMock(
@protocol(FlutterBinaryMessenger));
2250 OCMStub([flutterViewController
engine]).andReturn(
engine);
2251 OCMStub([
engine binaryMessenger]).andReturn(messenger);
2253 OCMStub([messenger setMessageHandlerOnChannel:
@"flutter/accessibility"
2254 binaryMessageHandler:[OCMArg any]])
2255 .andReturn(connection);
2257 auto platform_view = std::make_unique<flutter::PlatformViewIOS>(
2259 mock_delegate.settings_.enable_impeller
2265 std::make_shared<fml::SyncSwitch>());
2267 thread_task_runner->PostTask([&] {
2268 platform_view->SetOwnerViewController(flutterViewController);
2270 std::make_unique<flutter::AccessibilityBridge>(nil,
2273 XCTAssertTrue(bridge.get());
2274 OCMVerify([messenger setMessageHandlerOnChannel:
@"flutter/accessibility"
2275 binaryMessageHandler:[OCMArg isNotNil]]);
2280 OCMVerify([messenger cleanUpConnection:connection]);
2281 [engine stopMocking];
2284- (void)testFlutterSemanticsScrollViewManagedObjectLifecycleCorrectly {
2285 flutter::MockDelegate mock_delegate;
2286 auto thread_task_runner = CreateNewThread(
"AccessibilityBridgeTest");
2291 thread_task_runner);
2292 auto platform_view = std::make_unique<flutter::PlatformViewIOS>(
2294 mock_delegate.settings_.enable_impeller
2300 std::make_shared<fml::SyncSwitch>());
2301 id mockFlutterView = OCMClassMock([
FlutterView class]);
2303 OCMStub([mockFlutterViewController
view]).andReturn(mockFlutterView);
2305 auto ios_delegate = std::make_unique<flutter::MockIosDelegate>();
2306 __block
auto bridge =
2307 std::make_unique<flutter::AccessibilityBridge>(mockFlutterViewController,
2310 std::move(ios_delegate));
2319 XCTAssertTrue(flutterSemanticsScrollView);
2322 XCTAssertFalse([flutterSemanticsScrollView isAccessibilityElement]);
2325- (void)testPlatformViewDestructorDoesNotCallSemanticsAPIs {
2326 class TestDelegate :
public flutter::MockDelegate {
2328 void OnPlatformViewSetSemanticsEnabled(
bool enabled)
override { set_semantics_enabled_calls++; }
2329 int set_semantics_enabled_calls = 0;
2332 TestDelegate test_delegate;
2333 auto thread = std::make_unique<fml::Thread>(
"AccessibilityBridgeTest");
2334 auto thread_task_runner = thread->GetTaskRunner();
2339 thread_task_runner);
2342 thread_task_runner->PostTask([&] {
2343 auto platform_view = std::make_unique<flutter::PlatformViewIOS>(
2345 test_delegate.settings_.enable_impeller
2351 std::make_shared<fml::SyncSwitch>());
2359 OCMStub([mockFlutterViewController platformViewsController])
2360 .andReturn(flutterPlatformViewsController);
2361 platform_view->SetOwnerViewController(mockFlutterViewController);
2364 XCTAssertNotEqual(test_delegate.set_semantics_enabled_calls, 0);
2367 test_delegate.set_semantics_enabled_calls = 0;
2369 XCTAssertEqual(test_delegate.set_semantics_enabled_calls, 0);
2376- (void)testResetsAccessibilityElementsOnHotRestart {
2377 flutter::MockDelegate mock_delegate;
2378 auto thread = std::make_unique<fml::Thread>(
"AccessibilityBridgeTest");
2379 auto thread_task_runner = thread->GetTaskRunner();
2384 thread_task_runner);
2385 id mockFlutterView = OCMClassMock([
FlutterView class]);
2387 OCMStub([mockFlutterViewController viewIfLoaded]).andReturn(mockFlutterView);
2390 thread_task_runner->PostTask([&] {
2391 auto platform_view = std::make_unique<flutter::PlatformViewIOS>(
2393 mock_delegate.settings_.enable_impeller
2399 std::make_shared<fml::SyncSwitch>());
2401 platform_view->SetOwnerViewController(mockFlutterViewController);
2405 OCMExpect([mockFlutterView setAccessibilityElements:[OCMArg isNil]]);
2407 OCMVerifyAll(mockFlutterView);
2414- (void)testWeakViewController {
2415 flutter::MockDelegate mock_delegate;
2416 auto thread_task_runner = CreateNewThread(
"AccessibilityBridgeTest");
2421 thread_task_runner);
2422 auto platform_view = std::make_unique<flutter::PlatformViewIOS>(
2424 mock_delegate.settings_.enable_impeller
2430 std::make_shared<fml::SyncSwitch>());
2432 std::unique_ptr<flutter::AccessibilityBridge> bridge;
2434 id mockFlutterView = OCMClassMock([
FlutterView class]);
2436 OCMStub([mockFlutterViewController viewIfLoaded]).andReturn(mockFlutterView);
2437 OCMStub([mockFlutterViewController
view]).andReturn(mockFlutterView);
2439 bridge = std::make_unique<flutter::AccessibilityBridge>(
2440 mockFlutterViewController,
2443 XCTAssertTrue(bridge.get());
2444 XCTAssertNotNil(bridge->view());
2446 XCTAssertNil(bridge->view());
int64_t FlutterBinaryMessengerConnection
void(^ FlutterResult)(id _Nullable result)
constexpr int32_t kRootNodeId
static __weak MockPlatformView * gMockPlatformView
AssetResolverType
Identifies the type of AssetResolver an instance is.
A Mapping like NonOwnedMapping, but uses Free as its release proc.
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
G_BEGIN_DECLS FlutterViewId view_id
FlutterDesktopBinaryReply callback
instancetype methodCallWithMethodName:arguments:(NSString *method,[arguments] id _Nullable arguments)
constexpr int kHorizontalScrollSemanticsActions
std::unordered_map< int32_t, SemanticsNode > SemanticsNodeUpdates
std::unordered_map< int32_t, CustomAccessibilityAction > CustomAccessibilityActionUpdates
std::function< void()> closure
instancetype sharedInstance()
impeller::ShaderType type
SemanticsCheckState isChecked
SemanticsTristate isEnabled
bool isInMutuallyExclusiveGroup
bool hasImplicitScrolling
std::vector< int32_t > childrenInHitTestOrder
std::vector< int32_t > childrenInTraversalOrder