| Flutter macOS Embedder |

Instance Methods | Class Methods | List of all members
FlutterViewControllerTestObjC Class Reference
Inheritance diagram for FlutterViewControllerTestObjC:

## Instance Methods
(bool) | - testKeyEventsAreSentToFramework:
(bool) | - testKeyEventsArePropagatedIfNotHandled:
(bool) | - testKeyEventsAreNotPropagatedIfHandled:
(bool) | - testCtrlTabKeyEventIsPropagated:
(bool) | - testKeyEquivalentIsPassedToTextInputPlugin:
(bool) | - testFlagsChangedEventsArePropagatedIfNotHandled:
(bool) | - testKeyboardIsRestartedOnEngineRestart:
(bool) | - testTrackpadGesturesAreSentToFramework:
(bool) | - testMouseDownUpEventsSentToNextResponder:
(bool) | - testModifierKeysAreSynthesizedOnMouseMove:
(bool) | - testViewWillAppearCalledMultipleTimes:
(bool) | - testFlutterViewIsConfigured:
(bool) | - testLookupKeyAssets
(bool) | - testLookupKeyAssetsWithPackage
(bool) | - testViewControllerIsReleased

## Class Methods
(void) | + respondFalseForSendEvent:callback:userData:

## Detailed Description

Definition at line 95 of file FlutterViewControllerTest.mm.

## Method Documentation

## ◆ respondFalseForSendEvent:callback:userData:

+ (void) respondFalseForSendEvent: |  | (const FlutterKeyEvent&) | event
callback: |  | (nullable FlutterKeyEventCallback) | callback
userData: |  | (nullable void*) | userData

Definition at line 698 of file FlutterViewControllerTest.mm.

698 :(const FlutterKeyEvent&)event
699 callback:(nullable FlutterKeyEventCallback)callback
700 userData:(nullable void*)userData {
701 if (callback != nullptr) {
702 callback(false, userData);
703 }
704 }

## ◆ testCtrlTabKeyEventIsPropagated:

- (bool) testCtrlTabKeyEventIsPropagated: |  | (id) | mockEngine |

Definition at line 369 of file FlutterViewControllerTest.mm.

369 :(id)engineMock {
370 __block bool called = false;
371 __block FlutterKeyEvent last_event;
372 OCMStub([[engineMock ignoringNonObjectArgs] sendKeyEvent:FlutterKeyEvent {}
373 callback:nil
374 userData:nil])
375 .andDo((^(NSInvocation* invocation) {
376 FlutterKeyEvent* event;
377 [invocation getArgument:&event atIndex:2];
378 called = true;
379 last_event = *event;
380 }));
381 FlutterViewController* viewController = [[FlutterViewController alloc] initWithEngine:engineMock
382 nibName:@""
383 bundle:nil];
384 // Ctrl+tab
385 NSEvent* event = [NSEvent keyEventWithType:NSEventTypeKeyDown
386 location:NSZeroPoint
387 modifierFlags:0x40101
388 timestamp:0
389 windowNumber:0
390 context:nil
391 characters:@""
392 charactersIgnoringModifiers:@""
393 isARepeat:NO
394 keyCode:48];
395 const uint64_t kPhysicalKeyTab = 0x7002b;
396
397 [viewController viewWillAppear]; // Initializes the event channel.
398 // Creates a NSWindow so that FlutterView view can be first responder.
399 NSWindow* window = [[NSWindow alloc] initWithContentRect:NSMakeRect(0, 0, 800, 600)
400 styleMask:NSBorderlessWindowMask
401 backing:NSBackingStoreBuffered
402 defer:NO];
403 window.contentView = viewController.view;
404 [window makeFirstResponder:viewController.flutterView];
405 [viewController.view performKeyEquivalent:event];
406
407 EXPECT_TRUE(called);
408 EXPECT_EQ(last_event.type, kFlutterKeyEventTypeDown);
409 EXPECT_EQ(last_event.physical, kPhysicalKeyTab);
410 return true;
411 }

## ◆ testFlagsChangedEventsArePropagatedIfNotHandled:

- (bool) testFlagsChangedEventsArePropagatedIfNotHandled: |  | (id) | mockEngine |

Definition at line 537 of file FlutterViewControllerTest.mm.

537 :(id)engineMock {
538 id binaryMessengerMock = OCMProtocolMock(@protocol(FlutterBinaryMessenger));
539 OCMStub( // NOLINT(google-objc-avoid-throwing-exception)
540 [engineMock binaryMessenger])
541 .andReturn(binaryMessengerMock);
542 OCMStub([[engineMock ignoringNonObjectArgs] sendKeyEvent:FlutterKeyEvent {}
543 callback:nil
544 userData:nil])
545 .andCall([FlutterViewControllerTestObjC class],
546 @selector(respondFalseForSendEvent:callback:userData:));
547 FlutterViewController* viewController = [[FlutterViewController alloc] initWithEngine:engineMock
548 nibName:@""
549 bundle:nil];
550 id responderMock = flutter::testing::mockResponder();
551 id responderWrapper = [[FlutterResponderWrapper alloc] initWithResponder:responderMock];
552 viewController.nextResponder = responderWrapper;
553 NSDictionary* expectedEvent = @{
554 @"keymap" : @"macos",
555 @"type" : @"keydown",
556 @"keyCode" : @(56), // SHIFT key
557 @"modifiers" : @(537001986),
558 };
559 NSData* encodedKeyEvent = [[FlutterJSONMessageCodec sharedInstance] encode:expectedEvent];
560 CGEventRef cgEvent = CGEventCreateKeyboardEvent(NULL, 56, TRUE); // SHIFT key
561 CGEventSetType(cgEvent, kCGEventFlagsChanged);
562 NSEvent* event = [NSEvent eventWithCGEvent:cgEvent];
563 OCMExpect( // NOLINT(google-objc-avoid-throwing-exception)
564 [binaryMessengerMock sendOnChannel:@"flutter/keyevent"
565 message:encodedKeyEvent
566 binaryReply:[OCMArg any]])
567 .andDo((^(NSInvocation* invocation) {
568 FlutterBinaryReply handler;
569 [invocation getArgument:&handler atIndex:4];
570 NSDictionary* reply = @{
571 @"handled" : @(false),
572 };
573 NSData* encodedReply = [[FlutterJSONMessageCodec sharedInstance] encode:reply];
574 handler(encodedReply);
575 }));
576 [viewController viewWillAppear]; // Initializes the event channel.
577 [viewController flagsChanged:event];
578 @try {
579 OCMVerify( // NOLINT(google-objc-avoid-throwing-exception)
580 [binaryMessengerMock sendOnChannel:@"flutter/keyevent"
581 message:encodedKeyEvent
582 binaryReply:[OCMArg any]]);
583 } @catch (NSException* e) {
584 NSLog(@"%@", e.reason);
585 return false;
586 }
587 return true;
588 }

References FlutterBinaryReply, and <FlutterMessageCodec>::sharedInstance.

## ◆ testFlutterViewIsConfigured:

- (bool) testFlutterViewIsConfigured: |  | (id) | mockEngine |

Definition at line 518 of file FlutterViewControllerTest.mm.

518 :(id)engineMock {
519 FlutterRenderer* renderer_ = [[FlutterRenderer alloc] initWithFlutterEngine:engineMock];
520 OCMStub([engineMock renderer]).andReturn(renderer_);
521
522 FlutterViewController* viewController = [[FlutterViewController alloc] initWithEngine:engineMock
523 nibName:@""
524 bundle:nil];
525 [viewController loadView];
526
527 @try {
528 // Make sure "renderer" was called during "loadView", which means "flutterView" is created
529 OCMVerify([engineMock renderer]);
530 } @catch (...) {
531 return false;
532 }
533
534 return true;
535 }

## ◆ testKeyboardIsRestartedOnEngineRestart:

- (bool) testKeyboardIsRestartedOnEngineRestart: |  | (id) | mockEngine |

Definition at line 645 of file FlutterViewControllerTest.mm.

645 :(id)engineMock {
646 id binaryMessengerMock = OCMProtocolMock(@protocol(FlutterBinaryMessenger));
647 OCMStub( // NOLINT(google-objc-avoid-throwing-exception)
648 [engineMock binaryMessenger])
649 .andReturn(binaryMessengerMock);
650 __block bool called = false;
651 __block FlutterKeyEvent last_event;
652 OCMStub([[engineMock ignoringNonObjectArgs] sendKeyEvent:FlutterKeyEvent {}
653 callback:nil
654 userData:nil])
655 .andDo((^(NSInvocation* invocation) {
656 FlutterKeyEvent* event;
657 [invocation getArgument:&event atIndex:2];
658 called = true;
659 last_event = *event;
660 }));
661
662 FlutterViewController* viewController = [[FlutterViewController alloc] initWithEngine:engineMock
663 nibName:@""
664 bundle:nil];
665 [viewController viewWillAppear];
666 NSEvent* keyADown = [NSEvent keyEventWithType:NSEventTypeKeyDown
667 location:NSZeroPoint
668 modifierFlags:0x100
669 timestamp:0
670 windowNumber:0
671 context:nil
672 characters:@"a"
673 charactersIgnoringModifiers:@"a"
674 isARepeat:FALSE
675 keyCode:0];
676 const uint64_t kPhysicalKeyA = 0x70004;
677
678 // Send KeyA key down event twice. Without restarting the keyboard during
679 // onPreEngineRestart, the second event received will be an empty event with
680 // physical key 0x0 because duplicate key down events are ignored.
681
682 called = false;
683 [viewController keyDown:keyADown];
684 EXPECT_TRUE(called);
685 EXPECT_EQ(last_event.type, kFlutterKeyEventTypeDown);
686 EXPECT_EQ(last_event.physical, kPhysicalKeyA);
687
688 [viewController onPreEngineRestart];
689
690 called = false;
691 [viewController keyDown:keyADown];
692 EXPECT_TRUE(called);
693 EXPECT_EQ(last_event.type, kFlutterKeyEventTypeDown);
694 EXPECT_EQ(last_event.physical, kPhysicalKeyA);
695 return true;
696 }

References FlutterViewController::onPreEngineRestart.

## ◆ testKeyEquivalentIsPassedToTextInputPlugin:

- (bool) testKeyEquivalentIsPassedToTextInputPlugin: |  | (id) | mockEngine |

Definition at line 413 of file FlutterViewControllerTest.mm.

413 :(id)engineMock {
414 __block bool called = false;
415 __block FlutterKeyEvent last_event;
416 OCMStub([[engineMock ignoringNonObjectArgs] sendKeyEvent:FlutterKeyEvent {}
417 callback:nil
418 userData:nil])
419 .andDo((^(NSInvocation* invocation) {
420 FlutterKeyEvent* event;
421 [invocation getArgument:&event atIndex:2];
422 called = true;
423 last_event = *event;
424 }));
425 FlutterViewController* viewController = [[FlutterViewController alloc] initWithEngine:engineMock
426 nibName:@""
427 bundle:nil];
428 // Ctrl+tab
429 NSEvent* event = [NSEvent keyEventWithType:NSEventTypeKeyDown
430 location:NSZeroPoint
431 modifierFlags:0x40101
432 timestamp:0
433 windowNumber:0
434 context:nil
435 characters:@""
436 charactersIgnoringModifiers:@""
437 isARepeat:NO
438 keyCode:48];
439 const uint64_t kPhysicalKeyTab = 0x7002b;
440
441 [viewController viewWillAppear]; // Initializes the event channel.
442
443 NSWindow* window = [[NSWindow alloc] initWithContentRect:NSMakeRect(0, 0, 800, 600)
444 styleMask:NSBorderlessWindowMask
445 backing:NSBackingStoreBuffered
446 defer:NO];
447 window.contentView = viewController.view;
448
449 [viewController.view addSubview:viewController.textInputPlugin];
450
451 // Make the textInputPlugin first responder. This should still result in
452 // view controller reporting the key event.
453 [window makeFirstResponder:viewController.textInputPlugin];
454
455 [viewController.view performKeyEquivalent:event];
456
457 EXPECT_TRUE(called);
458 EXPECT_EQ(last_event.type, kFlutterKeyEventTypeDown);
459 EXPECT_EQ(last_event.physical, kPhysicalKeyTab);
460 return true;
461 }

## ◆ testKeyEventsAreNotPropagatedIfHandled:

- (bool) testKeyEventsAreNotPropagatedIfHandled: |  | (id) | mockEngine |

Definition at line 590 of file FlutterViewControllerTest.mm.

590 :(id)engineMock {
591 id binaryMessengerMock = OCMProtocolMock(@protocol(FlutterBinaryMessenger));
592 OCMStub( // NOLINT(google-objc-avoid-throwing-exception)
593 [engineMock binaryMessenger])
594 .andReturn(binaryMessengerMock);
595 OCMStub([[engineMock ignoringNonObjectArgs] sendKeyEvent:FlutterKeyEvent {}
596 callback:nil
597 userData:nil])
598 .andCall([FlutterViewControllerTestObjC class],
599 @selector(respondFalseForSendEvent:callback:userData:));
600 FlutterViewController* viewController = [[FlutterViewController alloc] initWithEngine:engineMock
601 nibName:@""
602 bundle:nil];
603 id responderMock = flutter::testing::mockResponder();
604 id responderWrapper = [[FlutterResponderWrapper alloc] initWithResponder:responderMock];
605 viewController.nextResponder = responderWrapper;
606 NSDictionary* expectedEvent = @{
607 @"keymap" : @"macos",
608 @"type" : @"keydown",
609 @"keyCode" : @(65),
610 @"modifiers" : @(538968064),
611 @"characters" : @".",
612 @"charactersIgnoringModifiers" : @".",
613 };
614 NSData* encodedKeyEvent = [[FlutterJSONMessageCodec sharedInstance] encode:expectedEvent];
615 CGEventRef cgEvent = CGEventCreateKeyboardEvent(NULL, 65, TRUE);
616 NSEvent* event = [NSEvent eventWithCGEvent:cgEvent];
617 OCMExpect( // NOLINT(google-objc-avoid-throwing-exception)
618 [binaryMessengerMock sendOnChannel:@"flutter/keyevent"
619 message:encodedKeyEvent
620 binaryReply:[OCMArg any]])
621 .andDo((^(NSInvocation* invocation) {
622 FlutterBinaryReply handler;
623 [invocation getArgument:&handler atIndex:4];
624 NSDictionary* reply = @{
625 @"handled" : @(true),
626 };
627 NSData* encodedReply = [[FlutterJSONMessageCodec sharedInstance] encode:reply];
628 handler(encodedReply);
629 }));
630 [viewController viewWillAppear]; // Initializes the event channel.
631 [viewController keyDown:event];
632 @try {
633 OCMVerify( // NOLINT(google-objc-avoid-throwing-exception)
634 never(), [responderMock keyDown:[OCMArg any]]);
635 OCMVerify( // NOLINT(google-objc-avoid-throwing-exception)
636 [binaryMessengerMock sendOnChannel:@"flutter/keyevent"
637 message:encodedKeyEvent
638 binaryReply:[OCMArg any]]);
639 } @catch (...) {
640 return false;
641 }
642 return true;
643 }

References FlutterBinaryReply, and <FlutterMessageCodec>::sharedInstance.

## ◆ testKeyEventsArePropagatedIfNotHandled:

- (bool) testKeyEventsArePropagatedIfNotHandled: |  | (id) | mockEngine |

Definition at line 463 of file FlutterViewControllerTest.mm.

463 :(id)engineMock {
464 id binaryMessengerMock = OCMProtocolMock(@protocol(FlutterBinaryMessenger));
465 OCMStub( // NOLINT(google-objc-avoid-throwing-exception)
466 [engineMock binaryMessenger])
467 .andReturn(binaryMessengerMock);
468 OCMStub([[engineMock ignoringNonObjectArgs] sendKeyEvent:FlutterKeyEvent {}
469 callback:nil
470 userData:nil])
471 .andCall([FlutterViewControllerTestObjC class],
472 @selector(respondFalseForSendEvent:callback:userData:));
473 FlutterViewController* viewController = [[FlutterViewController alloc] initWithEngine:engineMock
474 nibName:@""
475 bundle:nil];
476 id responderMock = flutter::testing::mockResponder();
477 id responderWrapper = [[FlutterResponderWrapper alloc] initWithResponder:responderMock];
478 viewController.nextResponder = responderWrapper;
479 NSDictionary* expectedEvent = @{
480 @"keymap" : @"macos",
481 @"type" : @"keydown",
482 @"keyCode" : @(65),
483 @"modifiers" : @(538968064),
484 @"characters" : @".",
485 @"charactersIgnoringModifiers" : @".",
486 };
487 NSData* encodedKeyEvent = [[FlutterJSONMessageCodec sharedInstance] encode:expectedEvent];
488 CGEventRef cgEvent = CGEventCreateKeyboardEvent(NULL, 65, TRUE);
489 NSEvent* event = [NSEvent eventWithCGEvent:cgEvent];
490 OCMExpect( // NOLINT(google-objc-avoid-throwing-exception)
491 [binaryMessengerMock sendOnChannel:@"flutter/keyevent"
492 message:encodedKeyEvent
493 binaryReply:[OCMArg any]])
494 .andDo((^(NSInvocation* invocation) {
495 FlutterBinaryReply handler;
496 [invocation getArgument:&handler atIndex:4];
497 NSDictionary* reply = @{
498 @"handled" : @(false),
499 };
500 NSData* encodedReply = [[FlutterJSONMessageCodec sharedInstance] encode:reply];
501 handler(encodedReply);
502 }));
503 [viewController viewWillAppear]; // Initializes the event channel.
504 [viewController keyDown:event];
505 @try {
506 OCMVerify( // NOLINT(google-objc-avoid-throwing-exception)
507 [responderMock keyDown:[OCMArg any]]);
508 OCMVerify( // NOLINT(google-objc-avoid-throwing-exception)
509 [binaryMessengerMock sendOnChannel:@"flutter/keyevent"
510 message:encodedKeyEvent
511 binaryReply:[OCMArg any]]);
512 } @catch (...) {
513 return false;
514 }
515 return true;
516 }

References FlutterBinaryReply, and <FlutterMessageCodec>::sharedInstance.

## ◆ testKeyEventsAreSentToFramework:

- (bool) testKeyEventsAreSentToFramework: |  | (id) | mockEngine |

Definition at line 331 of file FlutterViewControllerTest.mm.

331 :(id)engineMock {
332 id binaryMessengerMock = OCMProtocolMock(@protocol(FlutterBinaryMessenger));
333 OCMStub( // NOLINT(google-objc-avoid-throwing-exception)
334 [engineMock binaryMessenger])
335 .andReturn(binaryMessengerMock);
336 OCMStub([[engineMock ignoringNonObjectArgs] sendKeyEvent:FlutterKeyEvent {}
337 callback:nil
338 userData:nil])
339 .andCall([FlutterViewControllerTestObjC class],
340 @selector(respondFalseForSendEvent:callback:userData:));
341 FlutterViewController* viewController = [[FlutterViewController alloc] initWithEngine:engineMock
342 nibName:@""
343 bundle:nil];
344 NSDictionary* expectedEvent = @{
345 @"keymap" : @"macos",
346 @"type" : @"keydown",
347 @"keyCode" : @(65),
348 @"modifiers" : @(538968064),
349 @"characters" : @".",
350 @"charactersIgnoringModifiers" : @".",
351 };
352 NSData* encodedKeyEvent = [[FlutterJSONMessageCodec sharedInstance] encode:expectedEvent];
353 CGEventRef cgEvent = CGEventCreateKeyboardEvent(NULL, 65, TRUE);
354 NSEvent* event = [NSEvent eventWithCGEvent:cgEvent];
355 [viewController viewWillAppear]; // Initializes the event channel.
356 [viewController keyDown:event];
357 @try {
358 OCMVerify( // NOLINT(google-objc-avoid-throwing-exception)
359 [binaryMessengerMock sendOnChannel:@"flutter/keyevent"
360 message:encodedKeyEvent
361 binaryReply:[OCMArg any]]);
362 } @catch (...) {
363 return false;
364 }
365 return true;
366 }

References <FlutterMessageCodec>::sharedInstance.

## ◆ testLookupKeyAssets

- (bool) testLookupKeyAssets |  |  |

Definition at line 1016 of file FlutterViewControllerTest.mm.

1016 {
1017 FlutterViewController* viewController = [[FlutterViewController alloc] initWithProject:nil];
1018 NSString* key = [viewController lookupKeyForAsset:@"test.png"];
1019 EXPECT_TRUE(
1020 [key isEqualToString:@"Contents/Frameworks/App.framework/Resources/flutter_assets/test.png"]);
1021 return true;
1022 }

References FlutterViewController::lookupKeyForAsset:.

## ◆ testLookupKeyAssetsWithPackage

- (bool) testLookupKeyAssetsWithPackage |  |  |

Definition at line 1024 of file FlutterViewControllerTest.mm.

1024 {
1025 FlutterViewController* viewController = [[FlutterViewController alloc] initWithProject:nil];
1026
1027 NSString* packageKey = [viewController lookupKeyForAsset:@"test.png" fromPackage:@"test"];
1028 EXPECT_TRUE([packageKey
1029 isEqualToString:
1030 @"Contents/Frameworks/App.framework/Resources/flutter_assets/packages/test/test.png"]);
1031 return true;
1032 }

References FlutterViewController::lookupKeyForAsset:fromPackage:.

## ◆ testModifierKeysAreSynthesizedOnMouseMove:

- (bool) testModifierKeysAreSynthesizedOnMouseMove: |  | (id) | mockEngine |

Definition at line 1079 of file FlutterViewControllerTest.mm.

1079 :(id)engineMock {
1080 id binaryMessengerMock = OCMProtocolMock(@protocol(FlutterBinaryMessenger));
1081 OCMStub( // NOLINT(google-objc-avoid-throwing-exception)
1082 [engineMock binaryMessenger])
1083 .andReturn(binaryMessengerMock);
1084
1085 // Need to return a real renderer to allow view controller to load.
1086 FlutterRenderer* renderer_ = [[FlutterRenderer alloc] initWithFlutterEngine:engineMock];
1087 OCMStub([engineMock renderer]).andReturn(renderer_);
1088
1089 // Capture calls to sendKeyEvent
1090 __block NSMutableArray<KeyEventWrapper*>* events = [NSMutableArray array];
1091 OCMStub([[engineMock ignoringNonObjectArgs] sendKeyEvent:FlutterKeyEvent {}
1092 callback:nil
1093 userData:nil])
1094 .andDo((^(NSInvocation* invocation) {
1095 FlutterKeyEvent* event;
1096 [invocation getArgument:&event atIndex:2];
1097 [events addObject:[[KeyEventWrapper alloc] initWithEvent:event]];
1098 }));
1099
1100 __block NSMutableArray<NSDictionary*>* channelEvents = [NSMutableArray array];
1101 OCMStub([binaryMessengerMock sendOnChannel:@"flutter/keyevent"
1102 message:[OCMArg any]
1103 binaryReply:[OCMArg any]])
1104 .andDo((^(NSInvocation* invocation) {
1105 NSData* data;
1106 [invocation getArgument:&data atIndex:3];
1107 id event = [[FlutterJSONMessageCodec sharedInstance] decode:data];
1108 [channelEvents addObject:event];
1109 }));
1110
1111 FlutterViewController* viewController = [[FlutterViewController alloc] initWithEngine:engineMock
1112 nibName:@""
1113 bundle:nil];
1114 [viewController loadView];
1115 [viewController viewWillAppear];
1116
1117 // Zeroed modifier flag should not synthesize events.
1118 NSEvent* mouseEvent = flutter::testing::CreateMouseEvent(0x00);
1119 [viewController mouseMoved:mouseEvent];
1120 EXPECT_EQ([events count], 0u);
1121
1122 // For each modifier key, check that key events are synthesized.
1123 for (NSNumber* keyCode in flutter::keyCodeToModifierFlag) {
1124 FlutterKeyEvent* event;
1125 NSDictionary* channelEvent;
1126 NSNumber* logicalKey;
1127 NSNumber* physicalKey;
1128 NSEventModifierFlags flag = [flutter::keyCodeToModifierFlag[keyCode] unsignedLongValue];
1129
1130 // Cocoa event always contain combined flags.
1131 if (flag & (flutter::kModifierFlagShiftLeft | flutter::kModifierFlagShiftRight)) {
1132 flag |= NSEventModifierFlagShift;
1133 }
1134 if (flag & (flutter::kModifierFlagControlLeft | flutter::kModifierFlagControlRight)) {
1135 flag |= NSEventModifierFlagControl;
1136 }
1137 if (flag & (flutter::kModifierFlagAltLeft | flutter::kModifierFlagAltRight)) {
1138 flag |= NSEventModifierFlagOption;
1139 }
1140 if (flag & (flutter::kModifierFlagMetaLeft | flutter::kModifierFlagMetaRight)) {
1141 flag |= NSEventModifierFlagCommand;
1142 }
1143
1144 // Should synthesize down event.
1145 NSEvent* mouseEvent = flutter::testing::CreateMouseEvent(flag);
1146 [viewController mouseMoved:mouseEvent];
1147 EXPECT_EQ([events count], 1u);
1148 event = events[0].data;
1149 logicalKey = [flutter::keyCodeToLogicalKey objectForKey:keyCode];
1150 physicalKey = [flutter::keyCodeToPhysicalKey objectForKey:keyCode];
1151 EXPECT_EQ(event->type, kFlutterKeyEventTypeDown);
1152 EXPECT_EQ(event->logical, logicalKey.unsignedLongLongValue);
1153 EXPECT_EQ(event->physical, physicalKey.unsignedLongLongValue);
1154 EXPECT_EQ(event->synthesized, true);
1155
1156 channelEvent = channelEvents[0];
1157 EXPECT_TRUE([channelEvent[@"type"] isEqual:@"keydown"]);
1158 EXPECT_TRUE([channelEvent[@"keyCode"] isEqual:keyCode]);
1159 EXPECT_TRUE([channelEvent[@"modifiers"] isEqual:@(flag)]);
1160
1161 // Should synthesize up event.
1162 mouseEvent = flutter::testing::CreateMouseEvent(0x00);
1163 [viewController mouseMoved:mouseEvent];
1164 EXPECT_EQ([events count], 2u);
1165 event = events[1].data;
1166 logicalKey = [flutter::keyCodeToLogicalKey objectForKey:keyCode];
1167 physicalKey = [flutter::keyCodeToPhysicalKey objectForKey:keyCode];
1168 EXPECT_EQ(event->type, kFlutterKeyEventTypeUp);
1169 EXPECT_EQ(event->logical, logicalKey.unsignedLongLongValue);
1170 EXPECT_EQ(event->physical, physicalKey.unsignedLongLongValue);
1171 EXPECT_EQ(event->synthesized, true);
1172
1173 channelEvent = channelEvents[1];
1174 EXPECT_TRUE([channelEvent[@"type"] isEqual:@"keyup"]);
1175 EXPECT_TRUE([channelEvent[@"keyCode"] isEqual:keyCode]);
1176 EXPECT_TRUE([channelEvent[@"modifiers"] isEqual:@(0)]);
1177
1178 [events removeAllObjects];
1179 [channelEvents removeAllObjects];
1180 };
1181
1182 return true;
1183 }

References KeyEventWrapper::data, flutter::keyCodeToModifierFlag, flutter::kModifierFlagAltLeft, flutter::kModifierFlagAltRight, flutter::kModifierFlagControlLeft, flutter::kModifierFlagControlRight, flutter::kModifierFlagMetaLeft, flutter::kModifierFlagMetaRight, flutter::kModifierFlagShiftLeft, flutter::kModifierFlagShiftRight, and <FlutterMessageCodec>::sharedInstance.

## ◆ testMouseDownUpEventsSentToNextResponder:

- (bool) testMouseDownUpEventsSentToNextResponder: |  | (id) | mockEngine |

Definition at line 1043 of file FlutterViewControllerTest.mm.

1043 :(id)engineMock {
1044 // The root cause of the above bug is NSResponder mouseDown/mouseUp methods that don't correctly
1045 // walk the responder chain calling the appropriate method on the next responder under certain
1046 // conditions. Simulate this by swizzling out the default implementations and replacing them with
1047 // no-ops.
1048 Method mouseDown = class_getInstanceMethod([NSResponder class], @selector(mouseDown:));
1049 Method mouseUp = class_getInstanceMethod([NSResponder class], @selector(mouseUp:));
1050 IMP noopImp = (IMP)SwizzledNoop;
1051 IMP origMouseDown = method_setImplementation(mouseDown, noopImp);
1052 IMP origMouseUp = method_setImplementation(mouseUp, noopImp);
1053
1054 // Verify that mouseDown/mouseUp trigger mouseDown/mouseUp calls on FlutterViewController.
1055 MouseEventFlutterViewController* viewController =
1056 [[MouseEventFlutterViewController alloc] initWithEngine:engineMock nibName:@"" bundle:nil];
1057 FlutterView* view = (FlutterView*)[viewController view];
1058
1059 EXPECT_FALSE(viewController.mouseDownCalled);
1060 EXPECT_FALSE(viewController.mouseUpCalled);
1061
1062 NSEvent* mouseEvent = flutter::testing::CreateMouseEvent(0x00);
1063 [view mouseDown:mouseEvent];
1064 EXPECT_TRUE(viewController.mouseDownCalled);
1065 EXPECT_FALSE(viewController.mouseUpCalled);
1066
1067 viewController.mouseDownCalled = NO;
1068 [view mouseUp:mouseEvent];
1069 EXPECT_FALSE(viewController.mouseDownCalled);
1070 EXPECT_TRUE(viewController.mouseUpCalled);
1071
1072 // Restore the original NSResponder mouseDown/mouseUp implementations.
1073 method_setImplementation(mouseDown, origMouseDown);
1074 method_setImplementation(mouseUp, origMouseUp);
1075
1076 return true;
1077 }

References MouseEventFlutterViewController::mouseDownCalled, and MouseEventFlutterViewController::mouseUpCalled.

## ◆ testTrackpadGesturesAreSentToFramework:

- (bool) testTrackpadGesturesAreSentToFramework: |  | (id) | mockEngine |

Definition at line 706 of file FlutterViewControllerTest.mm.

706 :(id)engineMock {
707 // Need to return a real renderer to allow view controller to load.
708 FlutterRenderer* renderer_ = [[FlutterRenderer alloc] initWithFlutterEngine:engineMock];
709 OCMStub([engineMock renderer]).andReturn(renderer_);
710 __block bool called = false;
711 __block FlutterPointerEvent last_event;
712 OCMStub([[engineMock ignoringNonObjectArgs] sendPointerEvent:FlutterPointerEvent{}])
713 .andDo((^(NSInvocation* invocation) {
714 FlutterPointerEvent* event;
715 [invocation getArgument:&event atIndex:2];
716 called = true;
717 last_event = *event;
718 }));
719
720 FlutterViewController* viewController = [[FlutterViewController alloc] initWithEngine:engineMock
721 nibName:@""
722 bundle:nil];
723 [viewController loadView];
724
725 // Test for pan events.
726 // Start gesture.
727 CGEventRef cgEventStart = CGEventCreateScrollWheelEvent(NULL, kCGScrollEventUnitPixel, 1, 0);
728 CGEventSetType(cgEventStart, kCGEventScrollWheel);
729 CGEventSetIntegerValueField(cgEventStart, kCGScrollWheelEventScrollPhase, kCGScrollPhaseBegan);
730 CGEventSetIntegerValueField(cgEventStart, kCGScrollWheelEventIsContinuous, 1);
731
732 called = false;
733 [viewController scrollWheel:[NSEvent eventWithCGEvent:cgEventStart]];
734 EXPECT_TRUE(called);
735 EXPECT_EQ(last_event.signal_kind, kFlutterPointerSignalKindNone);
736 EXPECT_EQ(last_event.phase, kPanZoomStart);
737 EXPECT_EQ(last_event.device_kind, kFlutterPointerDeviceKindTrackpad);
738 EXPECT_EQ(last_event.signal_kind, kFlutterPointerSignalKindNone);
739
740 // Update gesture.
741 CGEventRef cgEventUpdate = CGEventCreateCopy(cgEventStart);
742 CGEventSetIntegerValueField(cgEventUpdate, kCGScrollWheelEventScrollPhase, kCGScrollPhaseChanged);
743 CGEventSetIntegerValueField(cgEventUpdate, kCGScrollWheelEventDeltaAxis2, 1); // pan_x
744 CGEventSetIntegerValueField(cgEventUpdate, kCGScrollWheelEventDeltaAxis1, 2); // pan_y
745
746 called = false;
747 [viewController scrollWheel:[NSEvent eventWithCGEvent:cgEventUpdate]];
748 EXPECT_TRUE(called);
749 EXPECT_EQ(last_event.signal_kind, kFlutterPointerSignalKindNone);
750 EXPECT_EQ(last_event.phase, kPanZoomUpdate);
751 EXPECT_EQ(last_event.device_kind, kFlutterPointerDeviceKindTrackpad);
752 EXPECT_EQ(last_event.signal_kind, kFlutterPointerSignalKindNone);
753 EXPECT_EQ(last_event.pan_x, 8 * viewController.flutterView.layer.contentsScale);
754 EXPECT_EQ(last_event.pan_y, 16 * viewController.flutterView.layer.contentsScale);
755
756 // Make sure the pan values accumulate.
757 called = false;
758 [viewController scrollWheel:[NSEvent eventWithCGEvent:cgEventUpdate]];
759 EXPECT_TRUE(called);
760 EXPECT_EQ(last_event.signal_kind, kFlutterPointerSignalKindNone);
761 EXPECT_EQ(last_event.phase, kPanZoomUpdate);
762 EXPECT_EQ(last_event.device_kind, kFlutterPointerDeviceKindTrackpad);
763 EXPECT_EQ(last_event.signal_kind, kFlutterPointerSignalKindNone);
764 EXPECT_EQ(last_event.pan_x, 16 * viewController.flutterView.layer.contentsScale);
765 EXPECT_EQ(last_event.pan_y, 32 * viewController.flutterView.layer.contentsScale);
766
767 // End gesture.
768 CGEventRef cgEventEnd = CGEventCreateCopy(cgEventStart);
769 CGEventSetIntegerValueField(cgEventEnd, kCGScrollWheelEventScrollPhase, kCGScrollPhaseEnded);
770
771 called = false;
772 [viewController scrollWheel:[NSEvent eventWithCGEvent:cgEventEnd]];
773 EXPECT_TRUE(called);
774 EXPECT_EQ(last_event.signal_kind, kFlutterPointerSignalKindNone);
775 EXPECT_EQ(last_event.phase, kPanZoomEnd);
776 EXPECT_EQ(last_event.device_kind, kFlutterPointerDeviceKindTrackpad);
777 EXPECT_EQ(last_event.signal_kind, kFlutterPointerSignalKindNone);
778
779 // Start system momentum.
780 CGEventRef cgEventMomentumStart = CGEventCreateCopy(cgEventStart);
781 CGEventSetIntegerValueField(cgEventMomentumStart, kCGScrollWheelEventScrollPhase, 0);
782 CGEventSetIntegerValueField(cgEventMomentumStart, kCGScrollWheelEventMomentumPhase,
783 kCGMomentumScrollPhaseBegin);
784
785 called = false;
786 [viewController scrollWheel:[NSEvent eventWithCGEvent:cgEventMomentumStart]];
787 EXPECT_FALSE(called);
788
789 // Advance system momentum.
790 CGEventRef cgEventMomentumUpdate = CGEventCreateCopy(cgEventStart);
791 CGEventSetIntegerValueField(cgEventMomentumUpdate, kCGScrollWheelEventScrollPhase, 0);
792 CGEventSetIntegerValueField(cgEventMomentumUpdate, kCGScrollWheelEventMomentumPhase,
793 kCGMomentumScrollPhaseContinue);
794
795 called = false;
796 [viewController scrollWheel:[NSEvent eventWithCGEvent:cgEventMomentumUpdate]];
797 EXPECT_FALSE(called);
798
799 // Mock a touch on the trackpad.
800 id touchMock = OCMClassMock([NSTouch class]);
801 NSSet* touchSet = [NSSet setWithObject:touchMock];
802 id touchEventMock1 = OCMClassMock([NSEvent class]);
803 OCMStub([touchEventMock1 allTouches]).andReturn(touchSet);
804 CGPoint touchLocation = {0, 0};
805 OCMStub([touchEventMock1 locationInWindow]).andReturn(touchLocation);
806 OCMStub([(NSEvent*)touchEventMock1 timestamp]).andReturn(0.150); // 150 milliseconds.
807
808 // Scroll inertia cancel event should not be issued (timestamp too far in the future).
809 called = false;
810 [viewController touchesBeganWithEvent:touchEventMock1];
811 EXPECT_FALSE(called);
812
813 // Mock another touch on the trackpad.
814 id touchEventMock2 = OCMClassMock([NSEvent class]);
815 OCMStub([touchEventMock2 allTouches]).andReturn(touchSet);
816 OCMStub([touchEventMock2 locationInWindow]).andReturn(touchLocation);
817 OCMStub([(NSEvent*)touchEventMock2 timestamp]).andReturn(0.005); // 5 milliseconds.
818
819 // Scroll inertia cancel event should be issued.
820 called = false;
821 [viewController touchesBeganWithEvent:touchEventMock2];
822 EXPECT_TRUE(called);
823 EXPECT_EQ(last_event.signal_kind, kFlutterPointerSignalKindScrollInertiaCancel);
824 EXPECT_EQ(last_event.device_kind, kFlutterPointerDeviceKindTrackpad);
825
826 // End system momentum.
827 CGEventRef cgEventMomentumEnd = CGEventCreateCopy(cgEventStart);
828 CGEventSetIntegerValueField(cgEventMomentumEnd, kCGScrollWheelEventScrollPhase, 0);
829 CGEventSetIntegerValueField(cgEventMomentumEnd, kCGScrollWheelEventMomentumPhase,
830 kCGMomentumScrollPhaseEnd);
831
832 called = false;
833 [viewController scrollWheel:[NSEvent eventWithCGEvent:cgEventMomentumEnd]];
834 EXPECT_FALSE(called);
835
836 // May-begin and cancel are used while macOS determines which type of gesture to choose.
837 CGEventRef cgEventMayBegin = CGEventCreateCopy(cgEventStart);
838 CGEventSetIntegerValueField(cgEventMayBegin, kCGScrollWheelEventScrollPhase,
839 kCGScrollPhaseMayBegin);
840
841 called = false;
842 [viewController scrollWheel:[NSEvent eventWithCGEvent:cgEventMayBegin]];
843 EXPECT_TRUE(called);
844 EXPECT_EQ(last_event.signal_kind, kFlutterPointerSignalKindNone);
845 EXPECT_EQ(last_event.phase, kPanZoomStart);
846 EXPECT_EQ(last_event.device_kind, kFlutterPointerDeviceKindTrackpad);
847 EXPECT_EQ(last_event.signal_kind, kFlutterPointerSignalKindNone);
848
849 // Cancel gesture.
850 CGEventRef cgEventCancel = CGEventCreateCopy(cgEventStart);
851 CGEventSetIntegerValueField(cgEventCancel, kCGScrollWheelEventScrollPhase,
852 kCGScrollPhaseCancelled);
853
854 called = false;
855 [viewController scrollWheel:[NSEvent eventWithCGEvent:cgEventCancel]];
856 EXPECT_TRUE(called);
857 EXPECT_EQ(last_event.signal_kind, kFlutterPointerSignalKindNone);
858 EXPECT_EQ(last_event.phase, kPanZoomEnd);
859 EXPECT_EQ(last_event.device_kind, kFlutterPointerDeviceKindTrackpad);
860 EXPECT_EQ(last_event.signal_kind, kFlutterPointerSignalKindNone);
861
862 // A discrete scroll event should use the PointerSignal system.
863 CGEventRef cgEventDiscrete = CGEventCreateScrollWheelEvent(NULL, kCGScrollEventUnitPixel, 1, 0);
864 CGEventSetType(cgEventDiscrete, kCGEventScrollWheel);
865 CGEventSetIntegerValueField(cgEventDiscrete, kCGScrollWheelEventIsContinuous, 0);
866 CGEventSetIntegerValueField(cgEventDiscrete, kCGScrollWheelEventDeltaAxis2, 1); // scroll_delta_x
867 CGEventSetIntegerValueField(cgEventDiscrete, kCGScrollWheelEventDeltaAxis1, 2); // scroll_delta_y
868
869 called = false;
870 [viewController scrollWheel:[NSEvent eventWithCGEvent:cgEventDiscrete]];
871 EXPECT_TRUE(called);
872 EXPECT_EQ(last_event.signal_kind, kFlutterPointerSignalKindScroll);
873 // pixelsPerLine is 40.0 and direction is reversed.
874 EXPECT_EQ(last_event.scroll_delta_x, -40 * viewController.flutterView.layer.contentsScale);
875 EXPECT_EQ(last_event.scroll_delta_y, -80 * viewController.flutterView.layer.contentsScale);
876
877 // A discrete scroll event should use the PointerSignal system, and flip the
878 // direction when shift is pressed.
879 CGEventRef cgEventDiscreteShift =
880 CGEventCreateScrollWheelEvent(NULL, kCGScrollEventUnitPixel, 1, 0);
881 CGEventSetType(cgEventDiscreteShift, kCGEventScrollWheel);
882 CGEventSetFlags(cgEventDiscreteShift, kCGEventFlagMaskShift | flutter::kModifierFlagShiftLeft);
883 CGEventSetIntegerValueField(cgEventDiscreteShift, kCGScrollWheelEventIsContinuous, 0);
884 CGEventSetIntegerValueField(cgEventDiscreteShift, kCGScrollWheelEventDeltaAxis2,
885 0); // scroll_delta_x
886 CGEventSetIntegerValueField(cgEventDiscreteShift, kCGScrollWheelEventDeltaAxis1,
887 2); // scroll_delta_y
888
889 called = false;
890 [viewController scrollWheel:[NSEvent eventWithCGEvent:cgEventDiscreteShift]];
891 EXPECT_TRUE(called);
892 EXPECT_EQ(last_event.signal_kind, kFlutterPointerSignalKindScroll);
893 // pixelsPerLine is 40.0, direction is reversed and axes have been flipped back.
894 EXPECT_FLOAT_EQ(last_event.scroll_delta_x, 0.0 * viewController.flutterView.layer.contentsScale);
895 EXPECT_FLOAT_EQ(last_event.scroll_delta_y,
896 -80.0 * viewController.flutterView.layer.contentsScale);
897
898 // Test for scale events.
899 // Start gesture.
900 called = false;
901 [viewController magnifyWithEvent:flutter::testing::MockGestureEvent(NSEventTypeMagnify,
902 NSEventPhaseBegan, 1, 0)];
903 EXPECT_TRUE(called);
904 EXPECT_EQ(last_event.signal_kind, kFlutterPointerSignalKindNone);
905 EXPECT_EQ(last_event.phase, kPanZoomStart);
906 EXPECT_EQ(last_event.device_kind, kFlutterPointerDeviceKindTrackpad);
907 EXPECT_EQ(last_event.signal_kind, kFlutterPointerSignalKindNone);
908
909 // Update gesture.
910 called = false;
911 [viewController magnifyWithEvent:flutter::testing::MockGestureEvent(NSEventTypeMagnify,
912 NSEventPhaseChanged, 1, 0)];
913 EXPECT_TRUE(called);
914 EXPECT_EQ(last_event.signal_kind, kFlutterPointerSignalKindNone);
915 EXPECT_EQ(last_event.phase, kPanZoomUpdate);
916 EXPECT_EQ(last_event.device_kind, kFlutterPointerDeviceKindTrackpad);
917 EXPECT_EQ(last_event.signal_kind, kFlutterPointerSignalKindNone);
918 EXPECT_EQ(last_event.pan_x, 0);
919 EXPECT_EQ(last_event.pan_y, 0);
920 EXPECT_EQ(last_event.scale, 2); // macOS uses logarithmic scaling values, the linear value for
921 // flutter here should be 2^1 = 2.
922 EXPECT_EQ(last_event.rotation, 0);
923
924 // Make sure the scale values accumulate.
925 called = false;
926 [viewController magnifyWithEvent:flutter::testing::MockGestureEvent(NSEventTypeMagnify,
927 NSEventPhaseChanged, 1, 0)];
928 EXPECT_TRUE(called);
929 EXPECT_EQ(last_event.signal_kind, kFlutterPointerSignalKindNone);
930 EXPECT_EQ(last_event.phase, kPanZoomUpdate);
931 EXPECT_EQ(last_event.device_kind, kFlutterPointerDeviceKindTrackpad);
932 EXPECT_EQ(last_event.signal_kind, kFlutterPointerSignalKindNone);
933 EXPECT_EQ(last_event.pan_x, 0);
934 EXPECT_EQ(last_event.pan_y, 0);
935 EXPECT_EQ(last_event.scale, 4); // macOS uses logarithmic scaling values, the linear value for
936 // flutter here should be 2^(1+1) = 2.
937 EXPECT_EQ(last_event.rotation, 0);
938
939 // End gesture.
940 called = false;
941 [viewController magnifyWithEvent:flutter::testing::MockGestureEvent(NSEventTypeMagnify,
942 NSEventPhaseEnded, 0, 0)];
943 EXPECT_TRUE(called);
944 EXPECT_EQ(last_event.signal_kind, kFlutterPointerSignalKindNone);
945 EXPECT_EQ(last_event.phase, kPanZoomEnd);
946 EXPECT_EQ(last_event.device_kind, kFlutterPointerDeviceKindTrackpad);
947 EXPECT_EQ(last_event.signal_kind, kFlutterPointerSignalKindNone);
948
949 // Test for rotation events.
950 // Start gesture.
951 called = false;
952 [viewController rotateWithEvent:flutter::testing::MockGestureEvent(NSEventTypeRotate,
953 NSEventPhaseBegan, 1, 0)];
954 EXPECT_TRUE(called);
955 EXPECT_EQ(last_event.signal_kind, kFlutterPointerSignalKindNone);
956 EXPECT_EQ(last_event.phase, kPanZoomStart);
957 EXPECT_EQ(last_event.device_kind, kFlutterPointerDeviceKindTrackpad);
958 EXPECT_EQ(last_event.signal_kind, kFlutterPointerSignalKindNone);
959
960 // Update gesture.
961 called = false;
962 [viewController rotateWithEvent:flutter::testing::MockGestureEvent(
963 NSEventTypeRotate, NSEventPhaseChanged, 0, -180)]; // degrees
964 EXPECT_TRUE(called);
965 EXPECT_EQ(last_event.signal_kind, kFlutterPointerSignalKindNone);
966 EXPECT_EQ(last_event.phase, kPanZoomUpdate);
967 EXPECT_EQ(last_event.device_kind, kFlutterPointerDeviceKindTrackpad);
968 EXPECT_EQ(last_event.signal_kind, kFlutterPointerSignalKindNone);
969 EXPECT_EQ(last_event.pan_x, 0);
970 EXPECT_EQ(last_event.pan_y, 0);
971 EXPECT_EQ(last_event.scale, 1);
972 EXPECT_EQ(last_event.rotation, M_PI); // radians
973
974 // Make sure the rotation values accumulate.
975 called = false;
976 [viewController rotateWithEvent:flutter::testing::MockGestureEvent(
977 NSEventTypeRotate, NSEventPhaseChanged, 0, -360)]; // degrees
978 EXPECT_TRUE(called);
979 EXPECT_EQ(last_event.signal_kind, kFlutterPointerSignalKindNone);
980 EXPECT_EQ(last_event.phase, kPanZoomUpdate);
981 EXPECT_EQ(last_event.device_kind, kFlutterPointerDeviceKindTrackpad);
982 EXPECT_EQ(last_event.signal_kind, kFlutterPointerSignalKindNone);
983 EXPECT_EQ(last_event.pan_x, 0);
984 EXPECT_EQ(last_event.pan_y, 0);
985 EXPECT_EQ(last_event.scale, 1);
986 EXPECT_EQ(last_event.rotation, 3 * M_PI); // radians
987
988 // End gesture.
989 called = false;
990 [viewController rotateWithEvent:flutter::testing::MockGestureEvent(NSEventTypeRotate,
991 NSEventPhaseEnded, 0, 0)];
992 EXPECT_TRUE(called);
993 EXPECT_EQ(last_event.signal_kind, kFlutterPointerSignalKindNone);
994 EXPECT_EQ(last_event.phase, kPanZoomEnd);
995 EXPECT_EQ(last_event.device_kind, kFlutterPointerDeviceKindTrackpad);
996 EXPECT_EQ(last_event.signal_kind, kFlutterPointerSignalKindNone);
997
998 // Test that stray NSEventPhaseCancelled event does not crash
999 called = false;
1000 [viewController rotateWithEvent:flutter::testing::MockGestureEvent(NSEventTypeRotate,
1001 NSEventPhaseCancelled, 0, 0)];
1002 EXPECT_FALSE(called);
1003
1004 return true;
1005 }

References flutter::kModifierFlagShiftLeft.

## ◆ testViewControllerIsReleased

- (bool) testViewControllerIsReleased |  |  |

Definition at line 1185 of file FlutterViewControllerTest.mm.

1185 {
1186 __weak FlutterViewController* weakController;
1187 @autoreleasepool {
1188 id engineMock = flutter::testing::CreateMockFlutterEngine(@"");
1189
1190 FlutterRenderer* renderer_ = [[FlutterRenderer alloc] initWithFlutterEngine:engineMock];
1191 OCMStub([engineMock renderer]).andReturn(renderer_);
1192
1193 FlutterViewController* viewController = [[FlutterViewController alloc] initWithEngine:engineMock
1194 nibName:@""
1195 bundle:nil];
1196 [viewController loadView];
1197 weakController = viewController;
1198
1199 [engineMock shutDownEngine];
1200 }
1201
1202 EXPECT_EQ(weakController, nil);
1203 return true;
1204 }

References flutter::testing::CreateMockFlutterEngine().

## ◆ testViewWillAppearCalledMultipleTimes:

- (bool) testViewWillAppearCalledMultipleTimes: |  | (id) | mockEngine |

Definition at line 1007 of file FlutterViewControllerTest.mm.

1007 :(id)engineMock {
1008 FlutterViewController* viewController = [[FlutterViewController alloc] initWithEngine:engineMock
1009 nibName:@""
1010 bundle:nil];
1011 [viewController viewWillAppear];
1012 [viewController viewWillAppear];
1013 return true;
1014 }

The documentation for this class was generated from the following file:

- shell/platform/darwin/macos/framework/Source/FlutterViewControllerTest.mm

FlutterViewControllerTestObjC
Definition: FlutterViewControllerTest.mm:95
FlutterViewController
Definition: FlutterViewController.h:65
FlutterResponderWrapper
Definition: FlutterViewControllerTest.mm:46
MouseEventFlutterViewController
Definition: FlutterViewControllerTest.mm:80
flutter::testing::CreateMockFlutterEngine
id CreateMockFlutterEngine(NSString *pasteboardString)
Definition: FlutterEngineTestUtils.mm:76
flutter::kModifierFlagMetaLeft
@ kModifierFlagMetaLeft
Definition: KeyCodeMap_Internal.h:83
flutter::kModifierFlagAltRight
@ kModifierFlagAltRight
Definition: KeyCodeMap_Internal.h:86
flutter::kModifierFlagMetaRight
@ kModifierFlagMetaRight
Definition: KeyCodeMap_Internal.h:84
-[FlutterViewController lookupKeyForAsset:]
nonnull NSString * lookupKeyForAsset:(nonnull NSString *asset)
MouseEventFlutterViewController::mouseDownCalled
BOOL mouseDownCalled
Definition: FlutterViewControllerTest.mm:81
KeyEventWrapper
Definition: FlutterViewControllerTest.mm:25
FlutterRenderer
Definition: FlutterRenderer.h:18
flutter::kModifierFlagControlLeft
@ kModifierFlagControlLeft
Definition: KeyCodeMap_Internal.h:80
-[FlutterViewController onPreEngineRestart]
void onPreEngineRestart()
Definition: FlutterViewController.mm:477
flutter::kModifierFlagAltLeft
@ kModifierFlagAltLeft
Definition: KeyCodeMap_Internal.h:85
-[FlutterViewController lookupKeyForAsset:fromPackage:]
nonnull NSString * lookupKeyForAsset:fromPackage:(nonnull NSString *asset,[fromPackage] nonnull NSString *package)
flutter::keyCodeToModifierFlag
const NSDictionary * keyCodeToModifierFlag
Definition: KeyCodeMap.g.mm:223
flutter::kModifierFlagShiftRight
@ kModifierFlagShiftRight
Definition: KeyCodeMap_Internal.h:82
MouseEventFlutterViewController::mouseUpCalled
BOOL mouseUpCalled
Definition: FlutterViewControllerTest.mm:82
FlutterView
Definition: FlutterView.h:48
flutter::kModifierFlagShiftLeft
@ kModifierFlagShiftLeft
Definition: KeyCodeMap_Internal.h:81
FlutterBinaryMessenger-p
Definition: FlutterBinaryMessenger.h:49
flutter::kModifierFlagControlRight
@ kModifierFlagControlRight
Definition: KeyCodeMap_Internal.h:87
FlutterBinaryReply
NS_ASSUME_NONNULL_BEGIN typedef void(^ FlutterBinaryReply)(NSData *_Nullable reply)
+[FlutterMessageCodec-p sharedInstance]
instancetype sharedInstance()
FlutterJSONMessageCodec
Definition: FlutterCodecs.h:81