Flutter iOS Embedder
FlutterAppDelegateTest.mm
Go to the documentation of this file.
1 // Copyright 2013 The Flutter Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #import <OCMock/OCMock.h>
6 #import <XCTest/XCTest.h>
7 
13 
15 
16 @interface FlutterAppDelegateTest : XCTestCase
17 @property(strong) FlutterAppDelegate* appDelegate;
18 
19 @property(strong) id mockMainBundle;
20 @property(strong) id mockNavigationChannel;
21 
22 // Retain callback until the tests are done.
23 // https://github.com/flutter/flutter/issues/74267
24 @property(strong) id mockEngineFirstFrameCallback;
25 @end
26 
27 @implementation FlutterAppDelegateTest
28 
29 - (void)setUp {
30  [super setUp];
31 
32  id mockMainBundle = OCMClassMock([NSBundle class]);
33  OCMStub([mockMainBundle mainBundle]).andReturn(mockMainBundle);
34  self.mockMainBundle = mockMainBundle;
35 
37  self.appDelegate = appDelegate;
38 
40  FlutterMethodChannel* navigationChannel = OCMClassMock([FlutterMethodChannel class]);
41  self.mockNavigationChannel = navigationChannel;
42 
43  FlutterEngine* engine = OCMClassMock([FlutterEngine class]);
44  OCMStub([engine navigationChannel]).andReturn(navigationChannel);
45  OCMStub([viewController engine]).andReturn(engine);
46 
47  id mockEngineFirstFrameCallback = [OCMArg invokeBlockWithArgs:@NO, nil];
48  self.mockEngineFirstFrameCallback = mockEngineFirstFrameCallback;
49  OCMStub([engine waitForFirstFrame:3.0 callback:mockEngineFirstFrameCallback]);
51  return viewController;
52  };
53 }
54 
55 - (void)tearDown {
56  // Explicitly stop mocking the NSBundle class property.
57  [self.mockMainBundle stopMocking];
58  [super tearDown];
59 }
60 
61 - (void)testLaunchUrl {
62  OCMStub([self.mockMainBundle objectForInfoDictionaryKey:@"FlutterDeepLinkingEnabled"])
63  .andReturn(@YES);
64 
65  BOOL result =
66  [self.appDelegate application:[UIApplication sharedApplication]
67  openURL:[NSURL URLWithString:@"http://myApp/custom/route?query=test"]
68  options:@{}];
69  XCTAssertTrue(result);
70  OCMVerify([self.mockNavigationChannel
71  invokeMethod:@"pushRouteInformation"
72  arguments:@{@"location" : @"http://myApp/custom/route?query=test"}]);
73 }
74 
75 - (void)testLaunchUrlWithDeepLinkingNotSet {
76  OCMStub([self.mockMainBundle objectForInfoDictionaryKey:@"FlutterDeepLinkingEnabled"])
77  .andReturn(nil);
78 
79  BOOL result =
80  [self.appDelegate application:[UIApplication sharedApplication]
81  openURL:[NSURL URLWithString:@"http://myApp/custom/route?query=test"]
82  options:@{}];
83  XCTAssertFalse(result);
84  OCMReject([self.mockNavigationChannel invokeMethod:OCMOCK_ANY arguments:OCMOCK_ANY]);
85 }
86 
87 - (void)testLaunchUrlWithDeepLinkingDisabled {
88  OCMStub([self.mockMainBundle objectForInfoDictionaryKey:@"FlutterDeepLinkingEnabled"])
89  .andReturn(@NO);
90 
91  BOOL result =
92  [self.appDelegate application:[UIApplication sharedApplication]
93  openURL:[NSURL URLWithString:@"http://myApp/custom/route?query=test"]
94  options:@{}];
95  XCTAssertFalse(result);
96  OCMReject([self.mockNavigationChannel invokeMethod:OCMOCK_ANY arguments:OCMOCK_ANY]);
97 }
98 
99 - (void)testLaunchUrlWithQueryParameterAndFragment {
100  OCMStub([self.mockMainBundle objectForInfoDictionaryKey:@"FlutterDeepLinkingEnabled"])
101  .andReturn(@YES);
102 
103  BOOL result = [self.appDelegate
104  application:[UIApplication sharedApplication]
105  openURL:[NSURL URLWithString:@"http://myApp/custom/route?query=test#fragment"]
106  options:@{}];
107  XCTAssertTrue(result);
108  OCMVerify([self.mockNavigationChannel
109  invokeMethod:@"pushRouteInformation"
110  arguments:@{@"location" : @"http://myApp/custom/route?query=test#fragment"}]);
111 }
112 
113 - (void)testLaunchUrlWithFragmentNoQueryParameter {
114  OCMStub([self.mockMainBundle objectForInfoDictionaryKey:@"FlutterDeepLinkingEnabled"])
115  .andReturn(@YES);
116 
117  BOOL result =
118  [self.appDelegate application:[UIApplication sharedApplication]
119  openURL:[NSURL URLWithString:@"http://myApp/custom/route#fragment"]
120  options:@{}];
121  XCTAssertTrue(result);
122  OCMVerify([self.mockNavigationChannel
123  invokeMethod:@"pushRouteInformation"
124  arguments:@{@"location" : @"http://myApp/custom/route#fragment"}]);
125 }
126 
127 - (void)testReleasesWindowOnDealloc {
128  __weak UIWindow* weakWindow;
129  @autoreleasepool {
130  id mockWindow = OCMClassMock([UIWindow class]);
132  appDelegate.window = mockWindow;
133  weakWindow = mockWindow;
134  XCTAssertNotNil(weakWindow);
135  [mockWindow stopMocking];
136  mockWindow = nil;
137  appDelegate = nil;
138  }
139  // App delegate has released the window.
140  XCTAssertNil(weakWindow);
141 }
142 
143 #pragma mark - Deep linking
144 
145 - (void)testUniversalLinkPushRouteInformation {
146  OCMStub([self.mockMainBundle objectForInfoDictionaryKey:@"FlutterDeepLinkingEnabled"])
147  .andReturn(@YES);
148 
149  NSUserActivity* userActivity = [[NSUserActivity alloc] initWithActivityType:@"com.example.test"];
150  userActivity.webpageURL = [NSURL URLWithString:@"http://myApp/custom/route?query=test"];
151  BOOL result = [self.appDelegate
152  application:[UIApplication sharedApplication]
153  continueUserActivity:userActivity
154  restorationHandler:^(NSArray<id<UIUserActivityRestoring>>* __nullable restorableObjects){
155  }];
156  XCTAssertTrue(result);
157  OCMVerify([self.mockNavigationChannel
158  invokeMethod:@"pushRouteInformation"
159  arguments:@{@"location" : @"http://myApp/custom/route?query=test"}]);
160 }
161 
162 @end
FlutterEngine
Definition: FlutterEngine.h:61
FlutterAppDelegateTest::mockEngineFirstFrameCallback
id mockEngineFirstFrameCallback
Definition: FlutterAppDelegateTest.mm:24
FlutterAppDelegateTest
Definition: FlutterAppDelegateTest.mm:16
FlutterViewController
Definition: FlutterViewController.h:56
FlutterMethodChannel
Definition: FlutterChannels.h:220
FlutterEngine.h
FlutterEngine_Test.h
FlutterAppDelegateTest::appDelegate
FlutterAppDelegate * appDelegate
Definition: FlutterAppDelegateTest.mm:17
FlutterAppDelegateTest::mockMainBundle
id mockMainBundle
Definition: FlutterAppDelegateTest.mm:19
viewController
FlutterViewController * viewController
Definition: FlutterTextInputPluginTest.mm:92
FlutterAppDelegate::window
FlutterAppLifeCycleProvider UIWindow * window
Definition: FlutterAppDelegate.h:30
FlutterAppDelegate
Definition: FlutterAppDelegate.h:27
FlutterAppDelegate.h
FlutterAppDelegateTest::mockNavigationChannel
id mockNavigationChannel
Definition: FlutterAppDelegateTest.mm:20
engine
id engine
Definition: FlutterTextInputPluginTest.mm:89
FlutterAppDelegate::rootFlutterViewControllerGetter
FlutterViewController *(^ rootFlutterViewControllerGetter)(void)
FlutterAppDelegate_Test.h
FLUTTER_ASSERT_ARC
Definition: VsyncWaiterIosTest.mm:15
FlutterViewController.h