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  OCMStub([self.mockNavigationChannel
66  invokeMethod:@"pushRouteInformation"
67  arguments:@{@"location" : @"http://myApp/custom/route?query=test"}])
68  .andReturn(@YES);
69 
70  BOOL result =
71  [self.appDelegate application:[UIApplication sharedApplication]
72  openURL:[NSURL URLWithString:@"http://myApp/custom/route?query=test"]
73  options:@{}];
74 
75  XCTAssertTrue(result);
76  OCMVerifyAll(self.mockNavigationChannel);
77 }
78 
79 - (void)testLaunchUrlWithDeepLinkingNotSet {
80  OCMStub([self.mockMainBundle objectForInfoDictionaryKey:@"FlutterDeepLinkingEnabled"])
81  .andReturn(nil);
82 
83  OCMStub([self.mockNavigationChannel
84  invokeMethod:@"pushRouteInformation"
85  arguments:@{@"location" : @"http://myApp/custom/route?query=test"}])
86  .andReturn(@YES);
87 
88  BOOL result =
89  [self.appDelegate application:[UIApplication sharedApplication]
90  openURL:[NSURL URLWithString:@"http://myApp/custom/route?query=test"]
91  options:@{}];
92 
93  XCTAssertTrue(result);
94  OCMVerifyAll(self.mockNavigationChannel);
95 }
96 
97 - (void)testLaunchUrlWithDeepLinkingDisabled {
98  OCMStub([self.mockMainBundle objectForInfoDictionaryKey:@"FlutterDeepLinkingEnabled"])
99  .andReturn(@NO);
100 
101  BOOL result =
102  [self.appDelegate application:[UIApplication sharedApplication]
103  openURL:[NSURL URLWithString:@"http://myApp/custom/route?query=test"]
104  options:@{}];
105  XCTAssertFalse(result);
106  OCMReject([self.mockNavigationChannel invokeMethod:OCMOCK_ANY arguments:OCMOCK_ANY]);
107 }
108 
109 - (void)testLaunchUrlWithQueryParameterAndFragment {
110  OCMStub([self.mockMainBundle objectForInfoDictionaryKey:@"FlutterDeepLinkingEnabled"])
111  .andReturn(@YES);
112  OCMStub([self.mockNavigationChannel
113  invokeMethod:@"pushRouteInformation"
114  arguments:@{@"location" : @"http://myApp/custom/route?query=test#fragment"}])
115  .andReturn(@YES);
116  BOOL result = [self.appDelegate
117  application:[UIApplication sharedApplication]
118  openURL:[NSURL URLWithString:@"http://myApp/custom/route?query=test#fragment"]
119  options:@{}];
120  XCTAssertTrue(result);
121  OCMVerifyAll(self.mockNavigationChannel);
122 }
123 
124 - (void)testLaunchUrlWithFragmentNoQueryParameter {
125  OCMStub([self.mockMainBundle objectForInfoDictionaryKey:@"FlutterDeepLinkingEnabled"])
126  .andReturn(@YES);
127  OCMStub([self.mockNavigationChannel
128  invokeMethod:@"pushRouteInformation"
129  arguments:@{@"location" : @"http://myApp/custom/route#fragment"}])
130  .andReturn(@YES);
131  BOOL result =
132  [self.appDelegate application:[UIApplication sharedApplication]
133  openURL:[NSURL URLWithString:@"http://myApp/custom/route#fragment"]
134  options:@{}];
135  XCTAssertTrue(result);
136  OCMVerifyAll(self.mockNavigationChannel);
137 }
138 
139 - (void)testReleasesWindowOnDealloc {
140  __weak UIWindow* weakWindow;
141  @autoreleasepool {
142  id mockWindow = OCMClassMock([UIWindow class]);
144  appDelegate.window = mockWindow;
145  weakWindow = mockWindow;
146  XCTAssertNotNil(weakWindow);
147  [mockWindow stopMocking];
148  mockWindow = nil;
149  appDelegate = nil;
150  }
151  // App delegate has released the window.
152  XCTAssertNil(weakWindow);
153 }
154 
155 #pragma mark - Deep linking
156 
157 - (void)testUniversalLinkPushRouteInformation {
158  OCMStub([self.mockMainBundle objectForInfoDictionaryKey:@"FlutterDeepLinkingEnabled"])
159  .andReturn(@YES);
160  OCMStub([self.mockNavigationChannel
161  invokeMethod:@"pushRouteInformation"
162  arguments:@{@"location" : @"http://myApp/custom/route?query=test"}])
163  .andReturn(@YES);
164  NSUserActivity* userActivity = [[NSUserActivity alloc] initWithActivityType:@"com.example.test"];
165  userActivity.webpageURL = [NSURL URLWithString:@"http://myApp/custom/route?query=test"];
166  BOOL result = [self.appDelegate
167  application:[UIApplication sharedApplication]
168  continueUserActivity:userActivity
169  restorationHandler:^(NSArray<id<UIUserActivityRestoring>>* __nullable restorableObjects){
170  }];
171  XCTAssertTrue(result);
172  OCMVerifyAll(self.mockNavigationChannel);
173 }
174 
175 @end
FlutterEngine
Definition: FlutterEngine.h:61
FlutterAppDelegateTest::mockEngineFirstFrameCallback
id mockEngineFirstFrameCallback
Definition: FlutterAppDelegateTest.mm:24
FlutterAppDelegateTest
Definition: FlutterAppDelegateTest.mm:16
FlutterViewController
Definition: FlutterViewController.h:57
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: FlutterChannelKeyResponder.mm:13
FlutterViewController.h