5 #import <Foundation/Foundation.h>
6 #import <OCMock/OCMock.h>
7 #import <XCTest/XCTest.h>
9 #import <objc/runtime.h>
11 #import "flutter/common/settings.h"
12 #include "flutter/fml/synchronization/sync_switch.h"
15 #import "flutter/shell/platform/darwin/common/test_utils_swift/test_utils_swift.h"
16 #import "flutter/shell/platform/darwin/ios/InternalFlutterSwift/InternalFlutterSwift.h"
35 + (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar>*)registrar {
40 @property(nonatomic) BOOL ensureSemanticsEnabledCalled;
46 _ensureSemanticsEnabledCalled = YES;
60 @property(nonatomic, assign) BOOL failOnDealloc;
66 XCTFail(
"FakeBinaryMessageRelay should not be deallocated");
88 - (void)testShellGetters {
94 XCTAssertEqual(
engine.platformTaskRunner.get(),
nullptr);
95 XCTAssertEqual(
engine.uiTaskRunner.get(),
nullptr);
96 XCTAssertEqual(
engine.rasterTaskRunner.get(),
nullptr);
99 - (void)testInfoPlist {
101 NSURL* flutterFrameworkURL =
102 [NSBundle.mainBundle.privateFrameworksURL URLByAppendingPathComponent:@"Flutter.framework"];
103 NSBundle* flutterBundle = [NSBundle bundleWithURL:flutterFrameworkURL];
104 XCTAssertEqualObjects(flutterBundle.bundleIdentifier,
@"io.flutter.flutter");
106 NSDictionary<NSString*, id>* infoDictionary = flutterBundle.infoDictionary;
109 NSError* regexError = NULL;
110 NSRegularExpression* osVersionRegex =
111 [NSRegularExpression regularExpressionWithPattern:@"((0|[1-9]\\d*)\\.)*(0|[1-9]\\d*)"
112 options:NSRegularExpressionCaseInsensitive
114 XCTAssertNil(regexError);
117 NSString* testString =
@"9";
118 NSUInteger versionMatches =
119 [osVersionRegex numberOfMatchesInString:testString
120 options:NSMatchingAnchored
121 range:NSMakeRange(0, testString.length)];
122 XCTAssertEqual(versionMatches, 1UL);
124 versionMatches = [osVersionRegex numberOfMatchesInString:testString
125 options:NSMatchingAnchored
126 range:NSMakeRange(0, testString.length)];
127 XCTAssertEqual(versionMatches, 1UL);
128 testString =
@"9.0.1";
129 versionMatches = [osVersionRegex numberOfMatchesInString:testString
130 options:NSMatchingAnchored
131 range:NSMakeRange(0, testString.length)];
132 XCTAssertEqual(versionMatches, 1UL);
133 testString =
@".0.1";
134 versionMatches = [osVersionRegex numberOfMatchesInString:testString
135 options:NSMatchingAnchored
136 range:NSMakeRange(0, testString.length)];
137 XCTAssertEqual(versionMatches, 0UL);
140 NSString* minimumOSVersion = infoDictionary[@"MinimumOSVersion"];
141 versionMatches = [osVersionRegex numberOfMatchesInString:minimumOSVersion
142 options:NSMatchingAnchored
143 range:NSMakeRange(0, minimumOSVersion.length)];
144 XCTAssertEqual(versionMatches, 1UL);
147 XCTAssertEqual(((NSString*)infoDictionary[
@"FlutterEngine"]).length, 40UL);
152 XCTAssertTrue(((NSString*)infoDictionary[
@"ClangVersion"]).length > 15UL);
155 - (void)testDeallocated {
161 XCTAssertNotNil(weakEngine);
163 XCTAssertNil(weakEngine);
166 - (void)testSendMessageBeforeRun {
170 XCTAssertThrows([
engine.binaryMessenger
172 message:[
@"bar" dataUsingEncoding:NSUTF8StringEncoding]
176 - (void)testSetMessageHandlerBeforeRun {
180 XCTAssertThrows([
engine.binaryMessenger
181 setMessageHandlerOnChannel:
@"foo"
187 - (void)testNilSetMessageHandlerBeforeRun {
191 XCTAssertNoThrow([
engine.binaryMessenger setMessageHandlerOnChannel:
@"foo"
192 binaryMessageHandler:nil]);
195 - (void)testNotifyPluginOfDealloc {
197 OCMStub([plugin detachFromEngineForRegistrar:[OCMArg any]]);
202 [registrar publish:plugin];
204 OCMVerify([plugin detachFromEngineForRegistrar:[OCMArg any]]);
207 - (void)testGetViewControllerFromRegistrar {
210 id mockEngine = OCMPartialMock(
engine);
211 NSObject<FlutterPluginRegistrar>* registrar = [mockEngine registrarForPlugin:@"plugin"];
218 - (void)testSetBinaryMessengerToSameBinaryMessenger {
232 - (void)testRunningInitialRouteSendsNavigationMessage {
245 NSData* encodedSetInitialRouteMethod =
247 OCMVerify([mockBinaryMessenger sendOnChannel:
@"flutter/navigation"
248 message:encodedSetInitialRouteMethod]);
251 - (void)testInitialRouteSettingsSendsNavigationMessage {
255 settings.route =
"test";
265 NSData* encodedSetInitialRouteMethod =
267 OCMVerify([mockBinaryMessenger sendOnChannel:
@"flutter/navigation"
268 message:encodedSetInitialRouteMethod]);
271 - (void)testPlatformViewsControllerRenderingMetalBackend {
279 - (void)testWaitForFirstFrameTimeout {
282 XCTestExpectation* timeoutFirstFrame = [
self expectationWithDescription:@"timeoutFirstFrame"];
285 if (timeoutFirstFrame) {
286 [timeoutFirstFrame fulfill];
289 [
self waitForExpectations:@[ timeoutFirstFrame ]];
299 XCTAssertNotNil(spawn);
302 - (void)testEngineId {
305 int64_t id1 =
engine.engineIdentifier;
306 XCTAssertTrue(id1 != 0);
311 int64_t id2 = spawn.engineIdentifier;
313 XCTAssertEqual([
FlutterEngine engineForIdentifier:id2], spawn);
316 - (void)testSetHandlerAfterRun {
318 XCTestExpectation* gotMessage = [
self expectationWithDescription:@"gotMessage"];
319 dispatch_async(dispatch_get_main_queue(), ^{
321 fml::AutoResetWaitableEvent latch;
323 flutter::Shell& shell =
engine.shell;
324 fml::TaskRunner::RunNowOrPostTask(
325 engine.shell.GetTaskRunners().GetUITaskRunner(), [&latch, &shell] {
326 flutter::Engine::Delegate& delegate = shell;
327 auto message = std::make_unique<flutter::PlatformMessage>(
"foo", nullptr);
328 delegate.OnEngineHandlePlatformMessage(std::move(message));
332 [registrar.messenger setMessageHandlerOnChannel:@"foo"
333 binaryMessageHandler:^(NSData* message, FlutterBinaryReply reply) {
334 [gotMessage fulfill];
337 [
self waitForExpectations:@[ gotMessage ]];
340 - (void)testThreadPrioritySetCorrectly {
341 XCTestExpectation* prioritiesSet = [
self expectationWithDescription:@"prioritiesSet"];
342 prioritiesSet.expectedFulfillmentCount = 2;
344 IMP mockSetThreadPriority =
345 imp_implementationWithBlock(^(NSThread* thread,
double threadPriority) {
346 if ([thread.name hasSuffix:
@".raster"]) {
347 XCTAssertEqual(threadPriority, 1.0);
348 [prioritiesSet fulfill];
349 }
else if ([thread.name hasSuffix:
@".io"]) {
350 XCTAssertEqual(threadPriority, 0.5);
351 [prioritiesSet fulfill];
354 Method method = class_getInstanceMethod([NSThread
class],
@selector(setThreadPriority:));
355 IMP originalSetThreadPriority = method_getImplementation(method);
356 method_setImplementation(method, mockSetThreadPriority);
360 [
self waitForExpectations:@[ prioritiesSet ]];
362 method_setImplementation(method, originalSetThreadPriority);
365 - (void)testCanEnableDisableEmbedderAPIThroughInfoPlist {
369 settings.enable_software_rendering =
true;
372 XCTAssertFalse(
engine.enableEmbedderAPI);
376 id mockMainBundle = OCMPartialMock([NSBundle mainBundle]);
377 OCMStub([mockMainBundle objectForInfoDictionaryKey:
@"FLTEnableIOSEmbedderAPI"])
380 settings.enable_software_rendering =
true;
383 XCTAssertTrue(
engine.enableEmbedderAPI);
387 - (void)testFlutterTextInputViewDidResignFirstResponderWillCallTextInputClientConnectionClosed {
392 [engine flutterTextInputView:nil didResignFirstResponderWithTextInputClient:1];
397 OCMVerify([mockBinaryMessenger sendOnChannel:
@"flutter/textinput" message:encodedMethodCall]);
400 - (void)testFlutterEngineUpdatesDisplays {
402 id mockEngine = OCMPartialMock(
engine);
405 OCMVerify(times(1), [mockEngine updateDisplays]);
406 engine.viewController = nil;
407 OCMVerify(times(2), [mockEngine updateDisplays]);
410 - (void)testLifeCycleNotificationDidEnterBackgroundForApplication {
414 NSNotification* sceneNotification =
415 [NSNotification notificationWithName:UISceneDidEnterBackgroundNotification
418 NSNotification* applicationNotification =
419 [NSNotification notificationWithName:UIApplicationDidEnterBackgroundNotification
422 id mockEngine = OCMPartialMock(
engine);
423 [NSNotificationCenter.defaultCenter postNotification:sceneNotification];
424 [NSNotificationCenter.defaultCenter postNotification:applicationNotification];
425 OCMVerify(times(1), [mockEngine applicationDidEnterBackground:[OCMArg any]]);
426 XCTAssertTrue(
engine.isGpuDisabled);
427 BOOL gpuDisabled = NO;
428 [engine
shell].GetIsGpuDisabledSyncSwitch()->Execute(
429 fml::SyncSwitch::Handlers().SetIfTrue([&] { gpuDisabled = YES; }).SetIfFalse([&] {
432 XCTAssertTrue(gpuDisabled);
435 - (void)testLifeCycleNotificationDidEnterBackgroundForScene {
436 id mockBundle = OCMPartialMock([NSBundle mainBundle]);
437 OCMStub([mockBundle objectForInfoDictionaryKey:
@"NSExtension"]).andReturn(@{
438 @"NSExtensionPointIdentifier" :
@"com.apple.share-services"
443 NSNotification* sceneNotification =
444 [NSNotification notificationWithName:UISceneDidEnterBackgroundNotification
447 NSNotification* applicationNotification =
448 [NSNotification notificationWithName:UIApplicationDidEnterBackgroundNotification
451 id mockEngine = OCMPartialMock(
engine);
452 [NSNotificationCenter.defaultCenter postNotification:sceneNotification];
453 [NSNotificationCenter.defaultCenter postNotification:applicationNotification];
454 OCMVerify(times(1), [mockEngine sceneDidEnterBackground:[OCMArg any]]);
455 XCTAssertTrue(
engine.isGpuDisabled);
456 BOOL gpuDisabled = NO;
457 [engine
shell].GetIsGpuDisabledSyncSwitch()->Execute(
458 fml::SyncSwitch::Handlers().SetIfTrue([&] { gpuDisabled = YES; }).SetIfFalse([&] {
461 XCTAssertTrue(gpuDisabled);
462 [mockBundle stopMocking];
465 - (void)testLifeCycleNotificationWillEnterForegroundForApplication {
469 NSNotification* sceneNotification =
470 [NSNotification notificationWithName:UISceneWillEnterForegroundNotification
473 NSNotification* applicationNotification =
474 [NSNotification notificationWithName:UIApplicationWillEnterForegroundNotification
477 id mockEngine = OCMPartialMock(
engine);
478 [NSNotificationCenter.defaultCenter postNotification:sceneNotification];
479 [NSNotificationCenter.defaultCenter postNotification:applicationNotification];
480 OCMVerify(times(1), [mockEngine applicationWillEnterForeground:[OCMArg any]]);
481 XCTAssertFalse(
engine.isGpuDisabled);
482 BOOL gpuDisabled = YES;
483 [engine
shell].GetIsGpuDisabledSyncSwitch()->Execute(
484 fml::SyncSwitch::Handlers().SetIfTrue([&] { gpuDisabled = YES; }).SetIfFalse([&] {
487 XCTAssertFalse(gpuDisabled);
490 - (void)testLifeCycleNotificationWillEnterForegroundForScene {
491 id mockBundle = OCMPartialMock([NSBundle mainBundle]);
492 OCMStub([mockBundle objectForInfoDictionaryKey:
@"NSExtension"]).andReturn(@{
493 @"NSExtensionPointIdentifier" :
@"com.apple.share-services"
498 NSNotification* sceneNotification =
499 [NSNotification notificationWithName:UISceneWillEnterForegroundNotification
502 NSNotification* applicationNotification =
503 [NSNotification notificationWithName:UIApplicationWillEnterForegroundNotification
506 id mockEngine = OCMPartialMock(
engine);
507 [NSNotificationCenter.defaultCenter postNotification:sceneNotification];
508 [NSNotificationCenter.defaultCenter postNotification:applicationNotification];
509 OCMVerify(times(1), [mockEngine sceneWillEnterForeground:[OCMArg any]]);
510 XCTAssertFalse(
engine.isGpuDisabled);
511 BOOL gpuDisabled = YES;
512 [engine
shell].GetIsGpuDisabledSyncSwitch()->Execute(
513 fml::SyncSwitch::Handlers().SetIfTrue([&] { gpuDisabled = YES; }).SetIfFalse([&] {
516 XCTAssertFalse(gpuDisabled);
517 [mockBundle stopMocking];
520 - (void)testLifeCycleNotificationSceneWillConnect {
524 id mockScene = OCMClassMock([UIWindowScene
class]);
527 OCMStub([mockScene delegate]).andReturn(mockLifecycleProvider);
528 OCMStub([mockLifecycleProvider sceneLifeCycleDelegate]).andReturn(mockLifecycleDelegate);
530 NSNotification* sceneNotification =
531 [NSNotification notificationWithName:UISceneWillConnectNotification
535 [NSNotificationCenter.defaultCenter postNotification:sceneNotification];
536 OCMVerify(times(1), [mockLifecycleDelegate
engine:
engine
537 receivedConnectNotificationFor:mockScene]);
540 - (void)testSpawnsShareGpuContext {
547 XCTAssertNotNil(spawn);
548 XCTAssertTrue(
engine.platformView !=
nullptr);
550 std::shared_ptr<flutter::IOSContext> engine_context =
engine.platformView->GetIosContext();
552 XCTAssertEqual(engine_context, spawn_context);
555 - (void)testEnableSemanticsWhenFlutterViewAccessibilityDidCall {
557 engine.ensureSemanticsEnabledCalled = NO;
558 [engine flutterViewAccessibilityDidCall];
559 XCTAssertTrue(
engine.ensureSemanticsEnabledCalled);
562 - (void)testCanMergePlatformAndUIThread {
563 #if defined(TARGET_IPHONE_SIMULATOR) && TARGET_IPHONE_SIMULATOR
569 XCTAssertEqual(
engine.shell.GetTaskRunners().GetUITaskRunner(),
570 engine.shell.GetTaskRunners().GetPlatformTaskRunner());
574 - (void)testCanUnMergePlatformAndUIThread {
575 #if defined(TARGET_IPHONE_SIMULATOR) && TARGET_IPHONE_SIMULATOR
577 settings.merged_platform_ui_thread = flutter::Settings::MergedPlatformUIThread::kDisabled;
582 XCTAssertNotEqual(
engine.shell.GetTaskRunners().GetUITaskRunner(),
583 engine.shell.GetTaskRunners().GetPlatformTaskRunner());
587 - (void)testAddSceneDelegateToRegistrar {
590 id mockEngine = OCMPartialMock(
engine);
591 NSObject<FlutterPluginRegistrar>* registrar = [mockEngine registrarForPlugin:@"plugin"];
593 [registrar addSceneDelegate:mockPlugin];
595 OCMVerify(times(1), [mockEngine addSceneLifeCycleDelegate:[OCMArg any]]);
598 - (void)testNotifyAppDelegateOfEngineInitialization {
602 id mockApplication = OCMClassMock([UIApplication
class]);
603 OCMStub([mockApplication sharedApplication]).andReturn(mockApplication);
605 OCMStub([mockApplication delegate]).andReturn(mockAppDelegate);
607 [engine performImplicitEngineCallback];
608 OCMVerify(times(1), [mockAppDelegate didInitializeImplicitFlutterEngine:[OCMArg any]]);
611 - (void)testRegistrarForPlugin {
619 OCMStub([mockEngine
viewController]).andReturn(mockViewController);
620 OCMStub([mockEngine binaryMessenger]).andReturn(mockBinaryMessenger);
621 OCMStub([mockEngine textureRegistry]).andReturn(mockTextureRegistry);
622 OCMStub([mockEngine platformViewsController]).andReturn(mockPlatformViewController);
624 NSString* pluginKey =
@"plugin";
625 NSString* assetKey =
@"asset";
626 NSString* factoryKey =
@"platform_view_factory";
628 NSObject<FlutterPluginRegistrar>* registrar = [mockEngine
registrarForPlugin:pluginKey];
630 XCTAssertTrue([registrar respondsToSelector:
@selector(messenger)]);
631 XCTAssertTrue([registrar respondsToSelector:
@selector(textures)]);
632 XCTAssertTrue([registrar respondsToSelector:
@selector(registerViewFactory:withId:)]);
633 XCTAssertTrue([registrar
634 respondsToSelector:
@selector(registerViewFactory:withId:gestureRecognizersBlockingPolicy:)]);
635 XCTAssertTrue([registrar respondsToSelector:
@selector(
viewController)]);
636 XCTAssertTrue([registrar respondsToSelector:
@selector(publish:)]);
637 XCTAssertTrue([registrar respondsToSelector:
@selector(valuePublishedByPlugin:)]);
638 XCTAssertTrue([registrar respondsToSelector:
@selector(addMethodCallDelegate:channel:)]);
639 XCTAssertTrue([registrar respondsToSelector:
@selector(addApplicationDelegate:)]);
640 XCTAssertTrue([registrar respondsToSelector:
@selector(lookupKeyForAsset:)]);
641 XCTAssertTrue([registrar respondsToSelector:
@selector(lookupKeyForAsset:fromPackage:)]);
644 XCTAssertEqual(registrar.messenger, mockBinaryMessenger);
645 XCTAssertEqual(registrar.textures, mockTextureRegistry);
646 XCTAssertEqual(registrar.viewController, mockViewController);
651 [registrar registerViewFactory:mockPlatformViewFactory withId:factoryKey];
652 [registrar registerViewFactory:mockPlatformViewFactory
654 gestureRecognizersBlockingPolicy:FlutterPlatformViewGestureRecognizersBlockingPolicyEager];
655 OCMVerify(times(2), [mockPlatformViewController registerViewFactory:mockPlatformViewFactory
657 gestureRecognizersBlockingPolicy:
662 [registrar publish:plugin];
666 id published = [registrar valuePublishedByPlugin:pluginKey];
667 XCTAssertEqual(plugin, published);
670 [registrar lookupKeyForAsset:assetKey];
671 OCMVerify(times(1), [mockEngine lookupKeyForAsset:assetKey]);
672 [registrar lookupKeyForAsset:assetKey fromPackage:pluginKey];
673 OCMVerify(times(1), [mockEngine lookupKeyForAsset:assetKey fromPackage:pluginKey]);
676 - (void)testRegistrarForApplication {
684 OCMStub([mockEngine
viewController]).andReturn(mockViewController);
685 OCMStub([mockEngine binaryMessenger]).andReturn(mockBinaryMessenger);
686 OCMStub([mockEngine textureRegistry]).andReturn(mockTextureRegistry);
687 OCMStub([mockEngine platformViewsController]).andReturn(mockPlatformViewController);
689 NSString* pluginKey =
@"plugin";
690 NSString* factoryKey =
@"platform_view_factory";
692 NSObject<FlutterApplicationRegistrar>* registrar = [mockEngine registrarForApplication:pluginKey];
694 XCTAssertTrue([registrar respondsToSelector:
@selector(messenger)]);
695 XCTAssertTrue([registrar respondsToSelector:
@selector(textures)]);
696 XCTAssertTrue([registrar respondsToSelector:
@selector(registerViewFactory:withId:)]);
697 XCTAssertTrue([registrar
698 respondsToSelector:
@selector(registerViewFactory:withId:gestureRecognizersBlockingPolicy:)]);
699 XCTAssertFalse([registrar respondsToSelector:
@selector(
viewController)]);
700 XCTAssertFalse([registrar respondsToSelector:
@selector(publish:)]);
701 XCTAssertFalse([registrar respondsToSelector:
@selector(valuePublishedByPlugin:)]);
702 XCTAssertFalse([registrar respondsToSelector:
@selector(addMethodCallDelegate:channel:)]);
703 XCTAssertFalse([registrar respondsToSelector:
@selector(addApplicationDelegate:)]);
704 XCTAssertFalse([registrar respondsToSelector:
@selector(lookupKeyForAsset:)]);
705 XCTAssertFalse([registrar respondsToSelector:
@selector(lookupKeyForAsset:fromPackage:)]);
708 XCTAssertEqual(registrar.messenger, mockBinaryMessenger);
709 XCTAssertEqual(registrar.textures, mockTextureRegistry);
714 [registrar registerViewFactory:mockPlatformViewFactory withId:factoryKey];
715 [registrar registerViewFactory:mockPlatformViewFactory
717 gestureRecognizersBlockingPolicy:FlutterPlatformViewGestureRecognizersBlockingPolicyEager];
718 OCMVerify(times(2), [mockPlatformViewController registerViewFactory:mockPlatformViewFactory
720 gestureRecognizersBlockingPolicy:
724 - (void)testSendDeepLinkToFrameworkTimesOut {
727 id mockEngine = OCMPartialMock(
engine);
728 id mockEngineFirstFrameCallback = [OCMArg invokeBlockWithArgs:@YES, nil];
729 OCMStub([mockEngine waitForFirstFrame:3.0 callback:mockEngineFirstFrameCallback]);
731 NSURL* url = [NSURL URLWithString:@"example.com"];
733 [mockEngine sendDeepLinkToFramework:url
734 completionHandler:^(BOOL success) {
735 XCTAssertFalse(success);
739 - (void)testSendDeepLinkToFrameworkUsingNavigationChannel {
740 NSString* urlString =
@"example.com";
741 NSURL* url = [NSURL URLWithString:urlString];
744 id mockEngine = OCMPartialMock(
engine);
745 id mockEngineFirstFrameCallback = [OCMArg invokeBlockWithArgs:@NO, nil];
746 OCMStub([mockEngine waitForFirstFrame:3.0 callback:mockEngineFirstFrameCallback]);
748 OCMStub([mockEngine navigationChannel]).andReturn(mockNavigationChannel);
749 id mockNavigationChannelCallback = [OCMArg invokeBlockWithArgs:@1, nil];
750 OCMStub([mockNavigationChannel invokeMethod:
@"pushRouteInformation"
751 arguments:@{
@"location" : urlString}
752 result:mockNavigationChannelCallback]);
754 [mockEngine sendDeepLinkToFramework:url
755 completionHandler:^(BOOL success) {
756 XCTAssertTrue(success);
760 - (void)testSendDeepLinkToFrameworkUsingNavigationChannelFails {
761 NSString* urlString =
@"example.com";
762 NSURL* url = [NSURL URLWithString:urlString];
765 id mockEngine = OCMPartialMock(
engine);
766 id mockEngineFirstFrameCallback = [OCMArg invokeBlockWithArgs:@NO, nil];
767 OCMStub([mockEngine waitForFirstFrame:3.0 callback:mockEngineFirstFrameCallback]);
769 OCMStub([mockEngine navigationChannel]).andReturn(mockNavigationChannel);
770 id mockNavigationChannelCallback = [OCMArg invokeBlockWithArgs:@0, nil];
771 OCMStub([mockNavigationChannel invokeMethod:
@"pushRouteInformation"
772 arguments:@{
@"location" : urlString}
773 result:mockNavigationChannelCallback]);
775 [mockEngine sendDeepLinkToFramework:url
776 completionHandler:^(BOOL success) {
777 XCTAssertFalse(success);
781 #pragma mark - Scene Lifecycle Warning Tests
783 - (void)testAddApplicationDelegateLogsWarningWhenPluginDoesNotConformToSceneDelegate {
784 FlutterStringOutputWriter* writer = [[FlutterStringOutputWriter alloc] init];
785 writer.expectedOutput =
@"uses deprecated application lifecycle events";
786 FlutterLogger.outputWriter = writer;
795 id mockApplication = OCMClassMock([UIApplication
class]);
796 OCMStub([mockApplication sharedApplication]).andReturn(mockApplication);
797 OCMStub([mockApplication delegate]).andReturn(mockAppDelegate);
799 [registrar addApplicationDelegate:mockPlugin];
801 XCTAssertTrue(writer.gotExpectedOutput,
802 @"Expected warning about plugin not adopting scenes was not logged");
805 - (void)testAddApplicationDelegateDoesNotLogWarningWhenPluginConformsToSceneDelegate {
806 FlutterStringOutputWriter* writer = [[FlutterStringOutputWriter alloc] init];
807 FlutterLogger.outputWriter = writer;
810 id<FlutterPluginRegistrar> registrar = [engine
registrarForPlugin:@"TestPluginWithSceneEvents"];
815 id mockApplication = OCMClassMock([UIApplication
class]);
816 OCMStub([mockApplication sharedApplication]).andReturn(mockApplication);
817 OCMStub([mockApplication delegate]).andReturn(mockAppDelegate);
819 [registrar addApplicationDelegate:mockPlugin];
821 XCTAssertFalse(writer.didLog,
@"No warning should be logged for scene-conforming plugin");
824 - (void)testAddApplicationDelegateDoesNotLogWarningWhenPluginDoesNotUseLifecycleEvents {
825 FlutterStringOutputWriter* writer = [[FlutterStringOutputWriter alloc] init];
826 FlutterLogger.outputWriter = writer;
837 id mockApplication = OCMClassMock([UIApplication
class]);
838 OCMStub([mockApplication sharedApplication]).andReturn(mockApplication);
839 OCMStub([mockApplication delegate]).andReturn(mockAppDelegate);
841 [registrar addApplicationDelegate:plugin];
843 XCTAssertFalse(writer.didLog,
844 @"No warning should be logged for a plugin that doesn't use lifecycle events");
NS_ASSUME_NONNULL_BEGIN typedef void(^ FlutterBinaryReply)(NSData *_Nullable reply)
flutter::Settings FLTDefaultSettingsForBundle(NSBundle *bundle, NSProcessInfo *processInfoOrNil)
@ FlutterPlatformViewGestureRecognizersBlockingPolicyEager
FlutterViewController * viewController
flutter::PlatformViewIOS * platformView()
FlutterEngine * spawnWithEntrypoint:libraryURI:initialRoute:entrypointArgs:(/*nullable */NSString *entrypoint,[libraryURI]/*nullable */NSString *libraryURI,[initialRoute]/*nullable */NSString *initialRoute,[entrypointArgs]/*nullable */NSArray< NSString * > *entrypointArgs)
void setBinaryMessenger:(FlutterBinaryMessengerRelay *binaryMessenger)
flutter::IOSRenderingAPI platformViewsRenderingAPI()
BOOL runWithEntrypoint:initialRoute:(nullable NSString *entrypoint,[initialRoute] nullable NSString *initialRoute)
NSMutableDictionary * pluginPublications
void ensureSemanticsEnabled()
void waitForFirstFrame:callback:(NSTimeInterval timeout,[callback] void(^ callback)(BOOL didTimeout))
instancetype methodCallWithMethodName:arguments:(NSString *method,[arguments] id _Nullable arguments)
nullable NSObject< FlutterPluginRegistrar > * registrarForPlugin:(NSString *pluginKey)