5 #import <OCMock/OCMock.h>
6 #import <XCTest/XCTest.h>
29 fml::WeakPtrFactory<flutter::AccessibilityBridgeIos> factory(
31 fml::WeakPtr<flutter::AccessibilityBridgeIos> bridge = factory.GetWeakPtr();
33 XCTAssertNotNil(
object);
36 - (void)testSetChildren {
37 fml::WeakPtrFactory<flutter::AccessibilityBridgeIos> factory(
39 fml::WeakPtr<flutter::AccessibilityBridgeIos> bridge = factory.GetWeakPtr();
43 XCTAssertEqual(parent, child.
parent);
45 XCTAssertNil(child.
parent);
48 - (void)testAccessibilityHitTestFocusAtLeaf {
49 fml::WeakPtrFactory<flutter::AccessibilityBridgeIos> factory(
51 fml::WeakPtr<flutter::AccessibilityBridgeIos> bridge = factory.GetWeakPtr();
58 object1.
children = @[ object2, object3 ];
61 flutter::SemanticsNode node0;
63 node0.rect = SkRect::MakeXYWH(0, 0, 200, 200);
67 flutter::SemanticsNode node1;
69 node1.rect = SkRect::MakeXYWH(0, 0, 200, 200);
73 flutter::SemanticsNode node2;
75 node2.rect = SkRect::MakeXYWH(0, 0, 100, 100);
79 flutter::SemanticsNode node3;
81 node3.rect = SkRect::MakeXYWH(0, 0, 200, 200);
85 CGPoint point = CGPointMake(10, 10);
89 XCTAssertEqual(hitTestResult, object2);
92 - (void)testAccessibilityHitTestNoFocusableItem {
93 fml::WeakPtrFactory<flutter::AccessibilityBridgeIos> factory(
95 fml::WeakPtr<flutter::AccessibilityBridgeIos> bridge = factory.GetWeakPtr();
102 object1.
children = @[ object2, object3 ];
105 flutter::SemanticsNode node0;
107 node0.rect = SkRect::MakeXYWH(0, 0, 200, 200);
110 flutter::SemanticsNode node1;
112 node1.rect = SkRect::MakeXYWH(0, 0, 200, 200);
115 flutter::SemanticsNode node2;
117 node2.rect = SkRect::MakeXYWH(0, 0, 100, 100);
120 flutter::SemanticsNode node3;
122 node3.rect = SkRect::MakeXYWH(0, 0, 200, 200);
125 CGPoint point = CGPointMake(10, 10);
128 XCTAssertNil(hitTestResult);
131 - (void)testAccessibilityScrollToVisible {
132 fml::WeakPtrFactory<flutter::testing::MockAccessibilityBridge> factory(
134 fml::WeakPtr<flutter::testing::MockAccessibilityBridge> bridge = factory.GetWeakPtr();
137 flutter::SemanticsNode node3;
139 node3.rect = SkRect::MakeXYWH(0, 0, 200, 200);
144 XCTAssertTrue(bridge->observations.size() == 1);
145 XCTAssertTrue(bridge->observations[0].id == 3);
146 XCTAssertTrue(bridge->observations[0].action == flutter::SemanticsAction::kShowOnScreen);
149 - (void)testAccessibilityScrollToVisibleWithChild {
150 fml::WeakPtrFactory<flutter::testing::MockAccessibilityBridge> factory(
152 fml::WeakPtr<flutter::testing::MockAccessibilityBridge> bridge = factory.GetWeakPtr();
155 flutter::SemanticsNode node3;
157 node3.rect = SkRect::MakeXYWH(0, 0, 200, 200);
162 XCTAssertTrue(bridge->observations.size() == 1);
163 XCTAssertTrue(bridge->observations[0].id == 3);
164 XCTAssertTrue(bridge->observations[0].action == flutter::SemanticsAction::kShowOnScreen);
167 - (void)testAccessibilityHitTestOutOfRect {
168 fml::WeakPtrFactory<flutter::AccessibilityBridgeIos> factory(
170 fml::WeakPtr<flutter::AccessibilityBridgeIos> bridge = factory.GetWeakPtr();
177 object1.
children = @[ object2, object3 ];
180 flutter::SemanticsNode node0;
182 node0.rect = SkRect::MakeXYWH(0, 0, 200, 200);
186 flutter::SemanticsNode node1;
188 node1.rect = SkRect::MakeXYWH(0, 0, 200, 200);
192 flutter::SemanticsNode node2;
194 node2.rect = SkRect::MakeXYWH(0, 0, 100, 100);
198 flutter::SemanticsNode node3;
200 node3.rect = SkRect::MakeXYWH(0, 0, 200, 200);
204 CGPoint point = CGPointMake(300, 300);
207 XCTAssertNil(hitTestResult);
210 - (void)testReplaceChildAtIndex {
211 fml::WeakPtrFactory<flutter::AccessibilityBridgeIos> factory(
213 fml::WeakPtr<flutter::AccessibilityBridgeIos> bridge = factory.GetWeakPtr();
219 XCTAssertNil(child1.
parent);
220 XCTAssertEqual(parent, child2.
parent);
221 XCTAssertEqualObjects(parent.
children, @[ child2 ]);
224 - (void)testPlainSemanticsObjectWithLabelHasStaticTextTrait {
225 fml::WeakPtrFactory<flutter::AccessibilityBridgeIos> factory(
227 fml::WeakPtr<flutter::AccessibilityBridgeIos> bridge = factory.GetWeakPtr();
228 flutter::SemanticsNode node;
232 XCTAssertEqual([
object accessibilityTraits], UIAccessibilityTraitStaticText);
235 - (void)testNodeWithImplicitScrollIsAnAccessibilityElementWhenItisHidden {
236 fml::WeakPtrFactory<flutter::AccessibilityBridgeIos> factory(
238 fml::WeakPtr<flutter::AccessibilityBridgeIos> bridge = factory.GetWeakPtr();
239 flutter::SemanticsNode node;
240 node.flags =
static_cast<int32_t
>(flutter::SemanticsFlags::kHasImplicitScrolling) |
241 static_cast<int32_t
>(flutter::SemanticsFlags::kIsHidden);
244 XCTAssertEqual(
object.isAccessibilityElement, YES);
247 - (void)testNodeWithImplicitScrollIsNotAnAccessibilityElementWhenItisNotHidden {
248 fml::WeakPtrFactory<flutter::AccessibilityBridgeIos> factory(
250 fml::WeakPtr<flutter::AccessibilityBridgeIos> bridge = factory.GetWeakPtr();
251 flutter::SemanticsNode node;
252 node.flags =
static_cast<int32_t
>(flutter::SemanticsFlags::kHasImplicitScrolling);
255 XCTAssertEqual(
object.isAccessibilityElement, NO);
258 - (void)testIntresetingSemanticsObjectWithLabelHasStaticTextTrait {
259 fml::WeakPtrFactory<flutter::AccessibilityBridgeIos> factory(
261 fml::WeakPtr<flutter::AccessibilityBridgeIos> bridge = factory.GetWeakPtr();
262 flutter::SemanticsNode node;
268 XCTAssertEqual([
object accessibilityTraits], UIAccessibilityTraitNone);
271 - (void)testIntresetingSemanticsObjectWithLabelHasStaticTextTrait1 {
272 fml::WeakPtrFactory<flutter::AccessibilityBridgeIos> factory(
274 fml::WeakPtr<flutter::AccessibilityBridgeIos> bridge = factory.GetWeakPtr();
275 flutter::SemanticsNode node;
277 node.flags =
static_cast<int32_t
>(flutter::SemanticsFlags::kIsTextField);
280 XCTAssertEqual([
object accessibilityTraits], UIAccessibilityTraitNone);
283 - (void)testIntresetingSemanticsObjectWithLabelHasStaticTextTrait2 {
284 fml::WeakPtrFactory<flutter::AccessibilityBridgeIos> factory(
286 fml::WeakPtr<flutter::AccessibilityBridgeIos> bridge = factory.GetWeakPtr();
287 flutter::SemanticsNode node;
289 node.flags =
static_cast<int32_t
>(flutter::SemanticsFlags::kIsButton);
292 XCTAssertEqual([
object accessibilityTraits], UIAccessibilityTraitButton);
295 - (void)testVerticalFlutterScrollableSemanticsObject {
296 fml::WeakPtrFactory<flutter::AccessibilityBridgeIos> factory(
298 fml::WeakPtr<flutter::AccessibilityBridgeIos> bridge = factory.GetWeakPtr();
300 float transformScale = 0.5f;
301 float screenScale = [[bridge->view() window] screen].scale;
302 float effectivelyScale = transformScale / screenScale;
307 float scrollExtentMax = 500.0;
308 float scrollPosition = 150.0;
310 flutter::SemanticsNode node;
311 node.flags =
static_cast<int32_t
>(flutter::SemanticsFlags::kHasImplicitScrolling);
312 node.actions = flutter::kVerticalScrollSemanticsActions;
313 node.rect = SkRect::MakeXYWH(x, y, w, h);
314 node.scrollExtentMax = scrollExtentMax;
315 node.scrollPosition = scrollPosition;
317 transformScale, 0, 0, 0, 0, transformScale, 0, 0, 0, 0, transformScale, 0, 0, 0, 0, 1.0};
324 XCTAssertEqualWithAccuracy(scrollView.frame.origin.x, x * effectivelyScale,
kFloatCompareEpsilon);
325 XCTAssertEqualWithAccuracy(scrollView.frame.origin.y, y * effectivelyScale,
kFloatCompareEpsilon);
326 XCTAssertEqualWithAccuracy(scrollView.frame.size.width, w * effectivelyScale,
328 XCTAssertEqualWithAccuracy(scrollView.frame.size.height, h * effectivelyScale,
331 XCTAssertEqualWithAccuracy(scrollView.contentSize.width, w * effectivelyScale,
333 XCTAssertEqualWithAccuracy(scrollView.contentSize.height,
336 XCTAssertEqual(scrollView.contentOffset.x, 0);
337 XCTAssertEqualWithAccuracy(scrollView.contentOffset.y, scrollPosition * effectivelyScale,
341 - (void)testVerticalFlutterScrollableSemanticsObjectNoWindowDoesNotCrash {
342 fml::WeakPtrFactory<flutter::AccessibilityBridgeIos> factory(
344 fml::WeakPtr<flutter::AccessibilityBridgeIos> bridge = factory.GetWeakPtr();
346 float transformScale = 0.5f;
351 float scrollExtentMax = 500.0;
352 float scrollPosition = 150.0;
354 flutter::SemanticsNode node;
355 node.flags =
static_cast<int32_t
>(flutter::SemanticsFlags::kHasImplicitScrolling);
356 node.actions = flutter::kVerticalScrollSemanticsActions;
357 node.rect = SkRect::MakeXYWH(x, y, w, h);
358 node.scrollExtentMax = scrollExtentMax;
359 node.scrollPosition = scrollPosition;
361 transformScale, 0, 0, 0, 0, transformScale, 0, 0, 0, 0, transformScale, 0, 0, 0, 0, 1.0};
366 XCTAssertNoThrow([scrollable accessibilityBridgeDidFinishUpdate]);
369 - (void)testHorizontalFlutterScrollableSemanticsObject {
370 fml::WeakPtrFactory<flutter::AccessibilityBridgeIos> factory(
372 fml::WeakPtr<flutter::AccessibilityBridgeIos> bridge = factory.GetWeakPtr();
374 float transformScale = 0.5f;
375 float screenScale = [[bridge->view() window] screen].scale;
376 float effectivelyScale = transformScale / screenScale;
381 float scrollExtentMax = 500.0;
382 float scrollPosition = 150.0;
384 flutter::SemanticsNode node;
385 node.flags =
static_cast<int32_t
>(flutter::SemanticsFlags::kHasImplicitScrolling);
386 node.actions = flutter::kHorizontalScrollSemanticsActions;
387 node.rect = SkRect::MakeXYWH(x, y, w, h);
388 node.scrollExtentMax = scrollExtentMax;
389 node.scrollPosition = scrollPosition;
391 transformScale, 0, 0, 0, 0, transformScale, 0, 0, 0, 0, transformScale, 0, 0, 0, 0, 1.0};
398 XCTAssertEqualWithAccuracy(scrollView.frame.origin.x, x * effectivelyScale,
kFloatCompareEpsilon);
399 XCTAssertEqualWithAccuracy(scrollView.frame.origin.y, y * effectivelyScale,
kFloatCompareEpsilon);
400 XCTAssertEqualWithAccuracy(scrollView.frame.size.width, w * effectivelyScale,
402 XCTAssertEqualWithAccuracy(scrollView.frame.size.height, h * effectivelyScale,
405 XCTAssertEqualWithAccuracy(scrollView.contentSize.width, (w + scrollExtentMax) * effectivelyScale,
407 XCTAssertEqualWithAccuracy(scrollView.contentSize.height, h * effectivelyScale,
410 XCTAssertEqualWithAccuracy(scrollView.contentOffset.x, scrollPosition * effectivelyScale,
412 XCTAssertEqual(scrollView.contentOffset.y, 0);
415 - (void)testCanHandleInfiniteScrollExtent {
416 fml::WeakPtrFactory<flutter::AccessibilityBridgeIos> factory(
418 fml::WeakPtr<flutter::AccessibilityBridgeIos> bridge = factory.GetWeakPtr();
420 float transformScale = 0.5f;
421 float screenScale = [[bridge->view() window] screen].scale;
422 float effectivelyScale = transformScale / screenScale;
427 float scrollExtentMax = INFINITY;
428 float scrollPosition = 150.0;
430 flutter::SemanticsNode node;
431 node.flags =
static_cast<int32_t
>(flutter::SemanticsFlags::kHasImplicitScrolling);
432 node.actions = flutter::kVerticalScrollSemanticsActions;
433 node.rect = SkRect::MakeXYWH(x, y, w, h);
434 node.scrollExtentMax = scrollExtentMax;
435 node.scrollPosition = scrollPosition;
437 transformScale, 0, 0, 0, 0, transformScale, 0, 0, 0, 0, transformScale, 0, 0, 0, 0, 1.0};
443 XCTAssertEqualWithAccuracy(scrollView.frame.origin.x, x * effectivelyScale,
kFloatCompareEpsilon);
444 XCTAssertEqualWithAccuracy(scrollView.frame.origin.y, y * effectivelyScale,
kFloatCompareEpsilon);
445 XCTAssertEqualWithAccuracy(scrollView.frame.size.width, w * effectivelyScale,
447 XCTAssertEqualWithAccuracy(scrollView.frame.size.height, h * effectivelyScale,
450 XCTAssertEqualWithAccuracy(scrollView.contentSize.width, w * effectivelyScale,
452 XCTAssertEqualWithAccuracy(scrollView.contentSize.height,
456 XCTAssertEqual(scrollView.contentOffset.x, 0);
457 XCTAssertEqualWithAccuracy(scrollView.contentOffset.y, scrollPosition * effectivelyScale,
461 - (void)testCanHandleNaNScrollExtentAndScrollPoisition {
462 fml::WeakPtrFactory<flutter::AccessibilityBridgeIos> factory(
464 fml::WeakPtr<flutter::AccessibilityBridgeIos> bridge = factory.GetWeakPtr();
466 float transformScale = 0.5f;
467 float screenScale = [[bridge->view() window] screen].scale;
468 float effectivelyScale = transformScale / screenScale;
473 float scrollExtentMax = std::nan(
"");
474 float scrollPosition = std::nan(
"");
476 flutter::SemanticsNode node;
477 node.flags =
static_cast<int32_t
>(flutter::SemanticsFlags::kHasImplicitScrolling);
478 node.actions = flutter::kVerticalScrollSemanticsActions;
479 node.rect = SkRect::MakeXYWH(x, y, w, h);
480 node.scrollExtentMax = scrollExtentMax;
481 node.scrollPosition = scrollPosition;
483 transformScale, 0, 0, 0, 0, transformScale, 0, 0, 0, 0, transformScale, 0, 0, 0, 0, 1.0};
490 XCTAssertEqualWithAccuracy(scrollView.frame.origin.x, x * effectivelyScale,
kFloatCompareEpsilon);
491 XCTAssertEqualWithAccuracy(scrollView.frame.origin.y, y * effectivelyScale,
kFloatCompareEpsilon);
492 XCTAssertEqualWithAccuracy(scrollView.frame.size.width, w * effectivelyScale,
494 XCTAssertEqualWithAccuracy(scrollView.frame.size.height, h * effectivelyScale,
498 XCTAssertEqualWithAccuracy(scrollView.contentSize.width, w * effectivelyScale,
500 XCTAssertEqualWithAccuracy(scrollView.contentSize.height, h * effectivelyScale,
503 XCTAssertEqual(scrollView.contentOffset.x, 0);
504 XCTAssertEqual(scrollView.contentOffset.y, 0);
507 - (void)testFlutterScrollableSemanticsObjectIsNotHittestable {
508 fml::WeakPtrFactory<flutter::AccessibilityBridgeIos> factory(
510 fml::WeakPtr<flutter::AccessibilityBridgeIos> bridge = factory.GetWeakPtr();
512 flutter::SemanticsNode node;
513 node.flags =
static_cast<int32_t
>(flutter::SemanticsFlags::kHasImplicitScrolling);
514 node.actions = flutter::kHorizontalScrollSemanticsActions;
515 node.rect = SkRect::MakeXYWH(0, 0, 100, 200);
516 node.scrollExtentMax = 100.0;
517 node.scrollPosition = 0.0;
524 XCTAssertEqual([scrollView hitTest:CGPointMake(10, 10) withEvent:nil], nil);
527 - (void)testFlutterScrollableSemanticsObjectIsHiddenWhenVoiceOverIsRunning {
530 fml::WeakPtrFactory<flutter::AccessibilityBridgeIos> factory(mock);
531 fml::WeakPtr<flutter::AccessibilityBridgeIos> bridge = factory.GetWeakPtr();
533 flutter::SemanticsNode node;
534 node.flags =
static_cast<int32_t
>(flutter::SemanticsFlags::kHasImplicitScrolling);
535 node.actions = flutter::kHorizontalScrollSemanticsActions;
536 node.rect = SkRect::MakeXYWH(0, 0, 100, 200);
537 node.scrollExtentMax = 100.0;
538 node.scrollPosition = 0.0;
545 XCTAssertTrue(scrollView.isAccessibilityElement);
547 XCTAssertFalse(scrollView.isAccessibilityElement);
550 - (void)testFlutterSemanticsObjectHasIdentifier {
553 fml::WeakPtrFactory<flutter::AccessibilityBridgeIos> factory(mock);
554 fml::WeakPtr<flutter::AccessibilityBridgeIos> bridge = factory.GetWeakPtr();
556 flutter::SemanticsNode node;
557 node.identifier =
"identifier";
561 XCTAssertTrue([
object.accessibilityIdentifier isEqualToString:
@"identifier"]);
564 - (void)testFlutterScrollableSemanticsObjectWithLabelValueHintIsNotHiddenWhenVoiceOverIsRunning {
567 fml::WeakPtrFactory<flutter::AccessibilityBridgeIos> factory(mock);
568 fml::WeakPtr<flutter::AccessibilityBridgeIos> bridge = factory.GetWeakPtr();
570 flutter::SemanticsNode node;
571 node.flags =
static_cast<int32_t
>(flutter::SemanticsFlags::kHasImplicitScrolling);
572 node.actions = flutter::kHorizontalScrollSemanticsActions;
573 node.rect = SkRect::MakeXYWH(0, 0, 100, 200);
574 node.label =
"label";
575 node.value =
"value";
577 node.scrollExtentMax = 100.0;
578 node.scrollPosition = 0.0;
585 XCTAssertTrue(scrollView.isAccessibilityElement);
587 [scrollView.accessibilityLabel isEqualToString:NSLocalizedString(
@"label",
@"test")]);
589 [scrollView.accessibilityValue isEqualToString:NSLocalizedString(
@"value",
@"test")]);
590 XCTAssertTrue([scrollView.accessibilityHint isEqualToString:NSLocalizedString(
@"hint",
@"test")]);
593 - (void)testFlutterSemanticsObjectMergeTooltipToLabel {
596 fml::WeakPtrFactory<flutter::AccessibilityBridgeIos> factory(mock);
597 fml::WeakPtr<flutter::AccessibilityBridgeIos> bridge = factory.GetWeakPtr();
599 flutter::SemanticsNode node;
600 node.rect = SkRect::MakeXYWH(0, 0, 100, 200);
601 node.label =
"label";
602 node.tooltip =
"tooltip";
605 XCTAssertTrue(
object.isAccessibilityElement);
606 XCTAssertTrue([
object.accessibilityLabel isEqualToString:
@"label\ntooltip"]);
609 - (void)testFlutterSemanticsObjectAttributedStringsDoNotCrashWhenEmpty {
612 fml::WeakPtrFactory<flutter::AccessibilityBridgeIos> factory(mock);
613 fml::WeakPtr<flutter::AccessibilityBridgeIos> bridge = factory.GetWeakPtr();
615 flutter::SemanticsNode node;
616 node.rect = SkRect::MakeXYWH(0, 0, 100, 200);
619 XCTAssertTrue(
object.accessibilityAttributedLabel == nil);
622 - (void)testFlutterScrollableSemanticsObjectReturnsParentContainerIfNoChildren {
625 fml::WeakPtrFactory<flutter::AccessibilityBridgeIos> factory(mock);
626 fml::WeakPtr<flutter::AccessibilityBridgeIos> bridge = factory.GetWeakPtr();
628 flutter::SemanticsNode parent;
630 parent.rect = SkRect::MakeXYWH(0, 0, 100, 200);
631 parent.label =
"label";
632 parent.value =
"value";
633 parent.hint =
"hint";
635 flutter::SemanticsNode node;
637 node.flags =
static_cast<int32_t
>(flutter::SemanticsFlags::kHasImplicitScrolling);
638 node.actions = flutter::kHorizontalScrollSemanticsActions;
639 node.rect = SkRect::MakeXYWH(0, 0, 100, 200);
640 node.label =
"label";
641 node.value =
"value";
643 node.scrollExtentMax = 100.0;
644 node.scrollPosition = 0.0;
645 parent.childrenInTraversalOrder.push_back(1);
656 parentObject.
children = @[ scrollable ];
659 XCTAssertTrue(scrollView.isAccessibilityElement);
665 - (void)testFlutterScrollableSemanticsObjectHidesScrollBar {
666 fml::WeakPtrFactory<flutter::AccessibilityBridgeIos> factory(
668 fml::WeakPtr<flutter::AccessibilityBridgeIos> bridge = factory.GetWeakPtr();
670 flutter::SemanticsNode node;
671 node.flags =
static_cast<int32_t
>(flutter::SemanticsFlags::kHasImplicitScrolling);
672 node.actions = flutter::kHorizontalScrollSemanticsActions;
673 node.rect = SkRect::MakeXYWH(0, 0, 100, 200);
674 node.scrollExtentMax = 100.0;
675 node.scrollPosition = 0.0;
683 XCTAssertFalse(scrollView.showsHorizontalScrollIndicator);
684 XCTAssertFalse(scrollView.showsVerticalScrollIndicator);
687 - (void)testSemanticsObjectBuildsAttributedString {
688 fml::WeakPtrFactory<flutter::AccessibilityBridgeIos> factory(
690 fml::WeakPtr<flutter::AccessibilityBridgeIos> bridge = factory.GetWeakPtr();
691 flutter::SemanticsNode node;
692 node.label =
"label";
693 std::shared_ptr<flutter::SpellOutStringAttribute> attribute =
694 std::make_shared<flutter::SpellOutStringAttribute>();
695 attribute->start = 1;
697 attribute->type = flutter::StringAttributeType::kSpellOut;
698 node.labelAttributes.push_back(attribute);
699 node.value =
"value";
700 attribute = std::make_shared<flutter::SpellOutStringAttribute>();
701 attribute->start = 2;
703 attribute->type = flutter::StringAttributeType::kSpellOut;
704 node.valueAttributes.push_back(attribute);
706 std::shared_ptr<flutter::LocaleStringAttribute> local_attribute =
707 std::make_shared<flutter::LocaleStringAttribute>();
708 local_attribute->start = 3;
709 local_attribute->end = 4;
710 local_attribute->type = flutter::StringAttributeType::kLocale;
711 local_attribute->locale =
"en-MX";
712 node.hintAttributes.push_back(local_attribute);
715 NSMutableAttributedString* expectedAttributedLabel =
716 [[NSMutableAttributedString alloc] initWithString:NSLocalizedString(@"label", @"test")];
717 NSDictionary* attributeDict = @{
718 UIAccessibilitySpeechAttributeSpellOut : @YES,
720 [expectedAttributedLabel setAttributes:attributeDict range:NSMakeRange(1, 1)];
722 [
object.accessibilityAttributedLabel isEqualToAttributedString:expectedAttributedLabel]);
724 NSMutableAttributedString* expectedAttributedValue =
725 [[NSMutableAttributedString alloc] initWithString:NSLocalizedString(@"value", @"test")];
727 UIAccessibilitySpeechAttributeSpellOut : @YES,
729 [expectedAttributedValue setAttributes:attributeDict range:NSMakeRange(2, 1)];
731 [
object.accessibilityAttributedValue isEqualToAttributedString:expectedAttributedValue]);
733 NSMutableAttributedString* expectedAttributedHint =
734 [[NSMutableAttributedString alloc] initWithString:NSLocalizedString(@"hint", @"test")];
736 UIAccessibilitySpeechAttributeLanguage :
@"en-MX",
738 [expectedAttributedHint setAttributes:attributeDict range:NSMakeRange(3, 1)];
740 [
object.accessibilityAttributedHint isEqualToAttributedString:expectedAttributedHint]);
743 - (void)testShouldTriggerAnnouncement {
744 fml::WeakPtrFactory<flutter::AccessibilityBridgeIos> factory(
746 fml::WeakPtr<flutter::AccessibilityBridgeIos> bridge = factory.GetWeakPtr();
750 XCTAssertFalse([
object nodeShouldTriggerAnnouncement:nil]);
753 flutter::SemanticsNode node;
754 node.flags =
static_cast<int32_t
>(flutter::SemanticsFlags::kIsLiveRegion);
756 XCTAssertTrue([
object nodeShouldTriggerAnnouncement:&node]);
760 XCTAssertFalse([
object nodeShouldTriggerAnnouncement:nil]);
763 XCTAssertFalse([
object nodeShouldTriggerAnnouncement:&node]);
766 flutter::SemanticsNode updatedNode;
767 updatedNode.flags =
static_cast<int32_t
>(flutter::SemanticsFlags::kIsLiveRegion);
768 updatedNode.label =
"bar";
769 XCTAssertTrue([
object nodeShouldTriggerAnnouncement:&updatedNode]);
772 updatedNode.flags = 0;
773 XCTAssertFalse([
object nodeShouldTriggerAnnouncement:&updatedNode]);
776 updatedNode.label =
"foo";
778 XCTAssertTrue([
object nodeShouldTriggerAnnouncement:&node]);
781 - (void)testShouldDispatchShowOnScreenActionForHeader {
782 fml::WeakPtrFactory<flutter::testing::MockAccessibilityBridge> factory(
784 fml::WeakPtr<flutter::testing::MockAccessibilityBridge> bridge = factory.GetWeakPtr();
788 flutter::SemanticsNode node;
789 node.flags =
static_cast<int32_t
>(flutter::SemanticsFlags::kIsHeader);
795 [object accessibilityElementDidBecomeFocused];
797 XCTAssertTrue(bridge->observations.size() == 1);
798 XCTAssertTrue(bridge->observations[0].id == 1);
799 XCTAssertTrue(bridge->observations[0].action == flutter::SemanticsAction::kShowOnScreen);
802 - (void)testShouldDispatchShowOnScreenActionForHidden {
803 fml::WeakPtrFactory<flutter::testing::MockAccessibilityBridge> factory(
805 fml::WeakPtr<flutter::testing::MockAccessibilityBridge> bridge = factory.GetWeakPtr();
809 flutter::SemanticsNode node;
810 node.flags =
static_cast<int32_t
>(flutter::SemanticsFlags::kIsHidden);
816 [object accessibilityElementDidBecomeFocused];
818 XCTAssertTrue(bridge->observations.size() == 1);
819 XCTAssertTrue(bridge->observations[0].id == 1);
820 XCTAssertTrue(bridge->observations[0].action == flutter::SemanticsAction::kShowOnScreen);
823 - (void)testFlutterSwitchSemanticsObjectMatchesUISwitch {
824 fml::WeakPtrFactory<flutter::testing::MockAccessibilityBridge> factory(
826 fml::WeakPtr<flutter::testing::MockAccessibilityBridge> bridge = factory.GetWeakPtr();
831 flutter::SemanticsNode node;
832 node.flags =
static_cast<int32_t
>(flutter::SemanticsFlags::kHasToggledState) |
833 static_cast<int32_t
>(flutter::SemanticsFlags::kIsToggled) |
834 static_cast<int32_t
>(flutter::SemanticsFlags::kIsEnabled);
838 UISwitch* nativeSwitch = [[UISwitch alloc] init];
839 nativeSwitch.on = YES;
841 XCTAssertEqual(
object.accessibilityTraits, nativeSwitch.accessibilityTraits);
842 XCTAssertEqualObjects(
object.accessibilityValue, nativeSwitch.accessibilityValue);
845 flutter::SemanticsNode update;
846 update.flags =
static_cast<int32_t
>(flutter::SemanticsFlags::kHasToggledState) |
847 static_cast<int32_t
>(flutter::SemanticsFlags::kIsEnabled);
848 update.label =
"foo";
851 nativeSwitch.on = NO;
853 XCTAssertEqual(
object.accessibilityTraits, nativeSwitch.accessibilityTraits);
854 XCTAssertEqualObjects(
object.accessibilityValue, nativeSwitch.accessibilityValue);
857 - (void)testFlutterSemanticsObjectOfRadioButton {
858 fml::WeakPtrFactory<flutter::testing::MockAccessibilityBridge> factory(
860 fml::WeakPtr<flutter::testing::MockAccessibilityBridge> bridge = factory.GetWeakPtr();
864 flutter::SemanticsNode node;
865 node.flags =
static_cast<int32_t
>(flutter::SemanticsFlags::kIsInMutuallyExclusiveGroup) |
866 static_cast<int32_t
>(flutter::SemanticsFlags::kHasCheckedState) |
867 static_cast<int32_t
>(flutter::SemanticsFlags::kHasEnabledState) |
868 static_cast<int32_t
>(flutter::SemanticsFlags::kIsEnabled);
871 XCTAssertTrue((
object.accessibilityTraits & UIAccessibilityTraitButton) > 0);
872 XCTAssertNil(
object.accessibilityValue);
875 - (void)testFlutterSwitchSemanticsObjectMatchesUISwitchDisabled {
876 fml::WeakPtrFactory<flutter::testing::MockAccessibilityBridge> factory(
878 fml::WeakPtr<flutter::testing::MockAccessibilityBridge> bridge = factory.GetWeakPtr();
883 flutter::SemanticsNode node;
884 node.flags =
static_cast<int32_t
>(flutter::SemanticsFlags::kHasToggledState) |
885 static_cast<int32_t
>(flutter::SemanticsFlags::kIsToggled);
889 UISwitch* nativeSwitch = [[UISwitch alloc] init];
890 nativeSwitch.on = YES;
891 nativeSwitch.enabled = NO;
893 XCTAssertEqual(
object.accessibilityTraits, nativeSwitch.accessibilityTraits);
894 XCTAssertEqualObjects(
object.accessibilityValue, nativeSwitch.accessibilityValue);
897 - (void)testSemanticsObjectDeallocated {
898 fml::WeakPtrFactory<flutter::AccessibilityBridgeIos> factory(
900 fml::WeakPtr<flutter::AccessibilityBridgeIos> bridge = factory.GetWeakPtr();
908 XCTAssertNil(weakObject);
911 - (void)testFlutterSemanticsObjectReturnsNilContainerWhenBridgeIsNotAlive {
916 flutter::SemanticsNode parent;
918 parent.rect = SkRect::MakeXYWH(0, 0, 100, 200);
919 parent.label =
"label";
920 parent.value =
"value";
921 parent.hint =
"hint";
923 flutter::SemanticsNode node;
925 node.flags =
static_cast<int32_t
>(flutter::SemanticsFlags::kHasImplicitScrolling);
926 node.actions = flutter::kHorizontalScrollSemanticsActions;
927 node.rect = SkRect::MakeXYWH(0, 0, 100, 200);
928 node.label =
"label";
929 node.value =
"value";
931 node.scrollExtentMax = 100.0;
932 node.scrollPosition = 0.0;
933 parent.childrenInTraversalOrder.push_back(1);
935 flutter::SemanticsNode node2;
937 node2.rect = SkRect::MakeXYWH(0, 0, 100, 200);
938 node2.label =
"label";
939 node2.value =
"value";
941 node2.scrollExtentMax = 100.0;
942 node2.scrollPosition = 0.0;
943 parent.childrenInTraversalOrder.push_back(2);
949 fml::WeakPtrFactory<flutter::AccessibilityBridgeIos> factory(mock);
950 fml::WeakPtr<flutter::AccessibilityBridgeIos> bridge = factory.GetWeakPtr();
962 parentObject.
children = @[ scrollable, object2 ];
977 XCTAssertNil(scrollable.accessibilityContainer);
978 XCTAssertNil(object2.accessibilityContainer);
981 - (void)testAccessibilityHitTestSearchCanReturnPlatformView {
982 fml::WeakPtrFactory<flutter::AccessibilityBridgeIos> factory(
984 fml::WeakPtr<flutter::AccessibilityBridgeIos> bridge = factory.GetWeakPtr();
993 platformView:platformView];
997 object1.
children = @[ platformViewSemanticsContainer, object3 ];
1000 flutter::SemanticsNode node0;
1002 node0.rect = SkRect::MakeXYWH(0, 0, 200, 200);
1006 flutter::SemanticsNode node1;
1008 node1.rect = SkRect::MakeXYWH(0, 0, 200, 200);
1012 flutter::SemanticsNode node2;
1014 node2.rect = SkRect::MakeXYWH(0, 0, 100, 100);
1018 flutter::SemanticsNode node3;
1020 node3.rect = SkRect::MakeXYWH(0, 0, 200, 200);
1024 CGPoint point = CGPointMake(10, 10);
1027 XCTAssertEqual(hitTestResult, platformView);
1030 - (void)testFlutterPlatformViewSemanticsContainer {
1031 fml::WeakPtrFactory<flutter::testing::MockAccessibilityBridge> factory(
1033 fml::WeakPtr<flutter::testing::MockAccessibilityBridge> bridge = factory.GetWeakPtr();
1038 weakPlatformView = platformView;
1044 platformView:platformView];
1045 weakContainer = container;
1047 XCTAssertNotNil(weakPlatformView);
1048 XCTAssertNotNil(weakContainer);
1052 XCTAssertNotNil(weakPlatformView);
1053 XCTAssertNotNil(weakContainer);
1057 XCTAssertNil(weakPlatformView);
1058 XCTAssertNil(weakContainer);
1061 - (void)testTextInputSemanticsObject {
1062 fml::WeakPtrFactory<flutter::AccessibilityBridgeIos> factory(
1064 fml::WeakPtr<flutter::AccessibilityBridgeIos> bridge = factory.GetWeakPtr();
1066 flutter::SemanticsNode node;
1068 node.flags =
static_cast<int32_t
>(flutter::SemanticsFlags::kIsTextField) |
1069 static_cast<int32_t
>(flutter::SemanticsFlags::kIsReadOnly);
1073 XCTAssertEqual([
object accessibilityTraits], UIAccessibilityTraitNone);
1076 - (void)testTextInputSemanticsObject_canPerformAction {
1077 fml::WeakPtrFactory<flutter::AccessibilityBridgeIos> factory(
1079 fml::WeakPtr<flutter::AccessibilityBridgeIos> bridge = factory.GetWeakPtr();
1081 flutter::SemanticsNode node;
1083 node.flags =
static_cast<int32_t
>(flutter::SemanticsFlags::kIsTextField) |
1084 static_cast<int32_t
>(flutter::SemanticsFlags::kIsReadOnly);
1090 id partialSemanticsObject = OCMPartialMock(
object);
1093 OCMExpect([
textInputSurrogate canPerformAction:[OCMArg anySelector] withSender:OCMOCK_ANY])
1095 XCTAssertTrue([partialSemanticsObject canPerformAction:
@selector(copy:) withSender:nil]);
1097 OCMExpect([
textInputSurrogate canPerformAction:[OCMArg anySelector] withSender:OCMOCK_ANY])
1099 XCTAssertFalse([partialSemanticsObject canPerformAction:
@selector(copy:) withSender:nil]);
1102 - (void)testTextInputSemanticsObject_editActions {
1103 fml::WeakPtrFactory<flutter::AccessibilityBridgeIos> factory(
1105 fml::WeakPtr<flutter::AccessibilityBridgeIos> bridge = factory.GetWeakPtr();
1107 flutter::SemanticsNode node;
1109 node.flags =
static_cast<int32_t
>(flutter::SemanticsFlags::kIsTextField) |
1110 static_cast<int32_t
>(flutter::SemanticsFlags::kIsReadOnly);
1116 id partialSemanticsObject = OCMPartialMock(
object);
1119 XCTestExpectation* copyExpectation =
1120 [
self expectationWithDescription:@"Surrogate's copy method is called."];
1121 XCTestExpectation* cutExpectation =
1122 [
self expectationWithDescription:@"Surrogate's cut method is called."];
1123 XCTestExpectation* pasteExpectation =
1124 [
self expectationWithDescription:@"Surrogate's paste method is called."];
1125 XCTestExpectation* selectAllExpectation =
1126 [
self expectationWithDescription:@"Surrogate's selectAll method is called."];
1127 XCTestExpectation* deleteExpectation =
1128 [
self expectationWithDescription:@"Surrogate's delete method is called."];
1131 [copyExpectation fulfill];
1134 [cutExpectation fulfill];
1137 [pasteExpectation fulfill];
1139 OCMStub([
textInputSurrogate selectAll:OCMOCK_ANY]).andDo(^(NSInvocation* invocation) {
1140 [selectAllExpectation fulfill];
1143 [deleteExpectation fulfill];
1146 [partialSemanticsObject copy:nil];
1147 [partialSemanticsObject cut:nil];
1148 [partialSemanticsObject paste:nil];
1149 [partialSemanticsObject selectAll:nil];
1150 [partialSemanticsObject delete:nil];
1152 [
self waitForExpectationsWithTimeout:1 handler:nil];