Flutter iOS Embedder
FlutterPlatformPluginTest.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 
14 
16 
17 @interface FlutterPlatformPluginTest : XCTestCase
18 @end
19 
20 @interface FlutterPlatformPlugin ()
21 - (BOOL)isLiveTextInputAvailable;
22 - (void)searchWeb:(NSString*)searchTerm;
23 - (void)showLookUpViewController:(NSString*)term;
24 - (void)showShareViewController:(NSString*)content;
25 @end
26 
27 @interface UIViewController ()
28 - (void)presentViewController:(UIViewController*)viewControllerToPresent
29  animated:(BOOL)flag
30  completion:(void (^)(void))completion;
31 @end
32 
33 @implementation FlutterPlatformPluginTest
34 
35 - (void)testSearchWebInvokedWithEscapedTerm {
36  id mockApplication = OCMClassMock([UIApplication class]);
37  OCMStub([mockApplication sharedApplication]).andReturn(mockApplication);
38 
39  FlutterEngine* engine = [[FlutterEngine alloc] initWithName:@"test" project:nil];
40  [engine runWithEntrypoint:nil];
41 
42  XCTestExpectation* invokeExpectation =
43  [self expectationWithDescription:@"Web search launched with escaped search term"];
44 
45  FlutterPlatformPlugin* plugin = [[FlutterPlatformPlugin alloc] initWithEngine:engine];
46  FlutterPlatformPlugin* mockPlugin = OCMPartialMock(plugin);
47 
48  FlutterMethodCall* methodCall = [FlutterMethodCall methodCallWithMethodName:@"SearchWeb.invoke"
49  arguments:@"Testing Word!"];
50 
51  FlutterResult result = ^(id result) {
52  OCMVerify([mockPlugin searchWeb:@"Testing Word!"]);
53  OCMVerify([mockApplication openURL:[NSURL URLWithString:@"x-web-search://?Testing%20Word!"]
54  options:@{}
55  completionHandler:nil]);
56  [invokeExpectation fulfill];
57  };
58 
59  [mockPlugin handleMethodCall:methodCall result:result];
60  [self waitForExpectationsWithTimeout:1 handler:nil];
61  [mockApplication stopMocking];
62 }
63 
64 - (void)testSearchWebSkippedIfAppExtension {
65  id mockBundle = OCMPartialMock([NSBundle mainBundle]);
66  OCMStub([mockBundle objectForInfoDictionaryKey:@"NSExtension"]).andReturn(@{
67  @"NSExtensionPointIdentifier" : @"com.apple.share-services"
68  });
69  id mockApplication = OCMClassMock([UIApplication class]);
70  OCMStub([mockApplication sharedApplication]).andReturn(mockApplication);
71  OCMReject([mockApplication openURL:OCMOCK_ANY options:OCMOCK_ANY completionHandler:OCMOCK_ANY]);
72  FlutterEngine* engine = [[FlutterEngine alloc] initWithName:@"test" project:nil];
73  [engine runWithEntrypoint:nil];
74 
75  XCTestExpectation* invokeExpectation =
76  [self expectationWithDescription:@"Web search launched with non escaped search term"];
77 
78  FlutterPlatformPlugin* plugin = [[FlutterPlatformPlugin alloc] initWithEngine:engine];
79  FlutterPlatformPlugin* mockPlugin = OCMPartialMock(plugin);
80 
81  FlutterMethodCall* methodCall = [FlutterMethodCall methodCallWithMethodName:@"SearchWeb.invoke"
82  arguments:@"Test"];
83 
84  FlutterResult result = ^(id result) {
85  OCMVerify([mockPlugin searchWeb:@"Test"]);
86 
87  [invokeExpectation fulfill];
88  };
89 
90  [mockPlugin handleMethodCall:methodCall result:result];
91  [self waitForExpectationsWithTimeout:1 handler:nil];
92  [mockBundle stopMocking];
93  [mockApplication stopMocking];
94 }
95 
96 - (void)testLookUpCallInitiated {
97  FlutterEngine* engine = [[FlutterEngine alloc] initWithName:@"test" project:nil];
98  [engine runWithEntrypoint:nil];
99 
100  XCTestExpectation* presentExpectation =
101  [self expectationWithDescription:@"Look Up view controller presented"];
102 
103  FlutterViewController* engineViewController = [[FlutterViewController alloc] initWithEngine:engine
104  nibName:nil
105  bundle:nil];
106  FlutterViewController* mockEngineViewController = OCMPartialMock(engineViewController);
107 
108  FlutterPlatformPlugin* plugin = [[FlutterPlatformPlugin alloc] initWithEngine:engine];
109  FlutterPlatformPlugin* mockPlugin = OCMPartialMock(plugin);
110 
111  FlutterMethodCall* methodCall = [FlutterMethodCall methodCallWithMethodName:@"LookUp.invoke"
112  arguments:@"Test"];
113  FlutterResult result = ^(id result) {
114  OCMVerify([mockEngineViewController
115  presentViewController:[OCMArg isKindOfClass:[UIReferenceLibraryViewController class]]
116  animated:YES
117  completion:nil]);
118  [presentExpectation fulfill];
119  };
120  [mockPlugin handleMethodCall:methodCall result:result];
121  [self waitForExpectationsWithTimeout:2 handler:nil];
122 }
123 
124 - (void)testShareScreenInvoked {
125  FlutterEngine* engine = [[FlutterEngine alloc] initWithName:@"test" project:nil];
126  [engine runWithEntrypoint:nil];
127 
128  XCTestExpectation* presentExpectation =
129  [self expectationWithDescription:@"Share view controller presented"];
130 
131  FlutterViewController* engineViewController = [[FlutterViewController alloc] initWithEngine:engine
132  nibName:nil
133  bundle:nil];
134  FlutterViewController* mockEngineViewController = OCMPartialMock(engineViewController);
135  OCMStub([mockEngineViewController
136  presentViewController:[OCMArg isKindOfClass:[UIActivityViewController class]]
137  animated:YES
138  completion:nil]);
139 
140  FlutterPlatformPlugin* plugin = [[FlutterPlatformPlugin alloc] initWithEngine:engine];
141  FlutterPlatformPlugin* mockPlugin = OCMPartialMock(plugin);
142 
143  FlutterMethodCall* methodCall = [FlutterMethodCall methodCallWithMethodName:@"Share.invoke"
144  arguments:@"Test"];
145  FlutterResult result = ^(id result) {
146  OCMVerify([mockEngineViewController
147  presentViewController:[OCMArg isKindOfClass:[UIActivityViewController class]]
148  animated:YES
149  completion:nil]);
150  [presentExpectation fulfill];
151  };
152  [mockPlugin handleMethodCall:methodCall result:result];
153  [self waitForExpectationsWithTimeout:1 handler:nil];
154 }
155 
156 - (void)testShareScreenInvokedOnIPad {
157  FlutterEngine* engine = [[FlutterEngine alloc] initWithName:@"test" project:nil];
158  [engine runWithEntrypoint:nil];
159 
160  XCTestExpectation* presentExpectation =
161  [self expectationWithDescription:@"Share view controller presented on iPad"];
162 
163  FlutterViewController* engineViewController = [[FlutterViewController alloc] initWithEngine:engine
164  nibName:nil
165  bundle:nil];
166  FlutterViewController* mockEngineViewController = OCMPartialMock(engineViewController);
167  OCMStub([mockEngineViewController
168  presentViewController:[OCMArg isKindOfClass:[UIActivityViewController class]]
169  animated:YES
170  completion:nil]);
171 
172  id mockTraitCollection = OCMClassMock([UITraitCollection class]);
173  OCMStub([mockTraitCollection userInterfaceIdiom]).andReturn(UIUserInterfaceIdiomPad);
174 
175  FlutterPlatformPlugin* plugin = [[FlutterPlatformPlugin alloc] initWithEngine:engine];
176  FlutterPlatformPlugin* mockPlugin = OCMPartialMock(plugin);
177 
178  FlutterMethodCall* methodCall = [FlutterMethodCall methodCallWithMethodName:@"Share.invoke"
179  arguments:@"Test"];
180  FlutterResult result = ^(id result) {
181  OCMVerify([mockEngineViewController
182  presentViewController:[OCMArg isKindOfClass:[UIActivityViewController class]]
183  animated:YES
184  completion:nil]);
185  [presentExpectation fulfill];
186  };
187  [mockPlugin handleMethodCall:methodCall result:result];
188  [self waitForExpectationsWithTimeout:1 handler:nil];
189 }
190 
191 - (void)testClipboardHasCorrectStrings {
192  [UIPasteboard generalPasteboard].string = nil;
193  FlutterEngine* engine = [[FlutterEngine alloc] initWithName:@"test" project:nil];
194  FlutterPlatformPlugin* plugin = [[FlutterPlatformPlugin alloc] initWithEngine:engine];
195 
196  XCTestExpectation* setStringExpectation = [self expectationWithDescription:@"setString"];
197  FlutterResult resultSet = ^(id result) {
198  [setStringExpectation fulfill];
199  };
200  FlutterMethodCall* methodCallSet =
201  [FlutterMethodCall methodCallWithMethodName:@"Clipboard.setData"
202  arguments:@{@"text" : @"some string"}];
203  [plugin handleMethodCall:methodCallSet result:resultSet];
204  [self waitForExpectationsWithTimeout:1 handler:nil];
205 
206  XCTestExpectation* hasStringsExpectation = [self expectationWithDescription:@"hasStrings"];
207  FlutterResult result = ^(id result) {
208  XCTAssertTrue([result[@"value"] boolValue]);
209  [hasStringsExpectation fulfill];
210  };
211  FlutterMethodCall* methodCall =
212  [FlutterMethodCall methodCallWithMethodName:@"Clipboard.hasStrings" arguments:nil];
213  [plugin handleMethodCall:methodCall result:result];
214  [self waitForExpectationsWithTimeout:1 handler:nil];
215 
216  XCTestExpectation* getDataExpectation = [self expectationWithDescription:@"getData"];
217  FlutterResult getDataResult = ^(id result) {
218  XCTAssertEqualObjects(result[@"text"], @"some string");
219  [getDataExpectation fulfill];
220  };
221  FlutterMethodCall* methodCallGetData =
222  [FlutterMethodCall methodCallWithMethodName:@"Clipboard.getData" arguments:@"text/plain"];
223  [plugin handleMethodCall:methodCallGetData result:getDataResult];
224  [self waitForExpectationsWithTimeout:1 handler:nil];
225 }
226 
227 - (void)testClipboardSetDataToNullDoNotCrash {
228  [UIPasteboard generalPasteboard].string = nil;
229  FlutterEngine* engine = [[FlutterEngine alloc] initWithName:@"test" project:nil];
230  FlutterPlatformPlugin* plugin = [[FlutterPlatformPlugin alloc] initWithEngine:engine];
231 
232  XCTestExpectation* setStringExpectation = [self expectationWithDescription:@"setData"];
233  FlutterResult resultSet = ^(id result) {
234  [setStringExpectation fulfill];
235  };
236  FlutterMethodCall* methodCallSet =
237  [FlutterMethodCall methodCallWithMethodName:@"Clipboard.setData"
238  arguments:@{@"text" : [NSNull null]}];
239  [plugin handleMethodCall:methodCallSet result:resultSet];
240 
241  XCTestExpectation* getDataExpectation = [self expectationWithDescription:@"getData"];
242  FlutterResult result = ^(id result) {
243  XCTAssertEqualObjects(result[@"text"], @"null");
244  [getDataExpectation fulfill];
245  };
246  FlutterMethodCall* methodCall = [FlutterMethodCall methodCallWithMethodName:@"Clipboard.getData"
247  arguments:@"text/plain"];
248  [plugin handleMethodCall:methodCall result:result];
249  [self waitForExpectationsWithTimeout:1 handler:nil];
250 }
251 
252 - (void)testPopSystemNavigator {
253  FlutterEngine* engine = [[FlutterEngine alloc] initWithName:@"test" project:nil];
254  [engine runWithEntrypoint:nil];
255  FlutterViewController* flutterViewController =
256  [[FlutterViewController alloc] initWithEngine:engine nibName:nil bundle:nil];
257  UINavigationController* navigationController =
258  [[UINavigationController alloc] initWithRootViewController:flutterViewController];
259  UITabBarController* tabBarController = [[UITabBarController alloc] init];
260  tabBarController.viewControllers = @[ navigationController ];
261  FlutterPlatformPlugin* plugin = [[FlutterPlatformPlugin alloc] initWithEngine:engine];
262 
263  id navigationControllerMock = OCMPartialMock(navigationController);
264  OCMStub([navigationControllerMock popViewControllerAnimated:YES]);
265  // Set some string to the pasteboard.
266  XCTestExpectation* navigationPopCalled = [self expectationWithDescription:@"SystemNavigator.pop"];
267  FlutterResult resultSet = ^(id result) {
268  [navigationPopCalled fulfill];
269  };
270  FlutterMethodCall* methodCallSet =
271  [FlutterMethodCall methodCallWithMethodName:@"SystemNavigator.pop" arguments:@(YES)];
272  [plugin handleMethodCall:methodCallSet result:resultSet];
273  [self waitForExpectationsWithTimeout:1 handler:nil];
274  OCMVerify([navigationControllerMock popViewControllerAnimated:YES]);
275 
276  [flutterViewController deregisterNotifications];
277 }
278 
279 - (void)testWhetherDeviceHasLiveTextInputInvokeCorrectly {
280  FlutterEngine* engine = [[FlutterEngine alloc] initWithName:@"test" project:nil];
281  XCTestExpectation* invokeExpectation =
282  [self expectationWithDescription:@"isLiveTextInputAvailableInvoke"];
283  FlutterPlatformPlugin* plugin = [[FlutterPlatformPlugin alloc] initWithEngine:engine];
284  FlutterPlatformPlugin* mockPlugin = OCMPartialMock(plugin);
285  FlutterMethodCall* methodCall =
286  [FlutterMethodCall methodCallWithMethodName:@"LiveText.isLiveTextInputAvailable"
287  arguments:nil];
288  FlutterResult result = ^(id result) {
289  OCMVerify([mockPlugin isLiveTextInputAvailable]);
290  [invokeExpectation fulfill];
291  };
292  [mockPlugin handleMethodCall:methodCall result:result];
293  [self waitForExpectationsWithTimeout:1 handler:nil];
294 }
295 
296 - (void)testViewControllerBasedStatusBarHiddenUpdate {
297  id bundleMock = OCMPartialMock([NSBundle mainBundle]);
298  OCMStub([bundleMock objectForInfoDictionaryKey:@"UIViewControllerBasedStatusBarAppearance"])
299  .andReturn(@YES);
300  {
301  // Enabling system UI overlays to update status bar.
302  FlutterEngine* engine = [[FlutterEngine alloc] initWithName:@"test" project:nil];
303  [engine runWithEntrypoint:nil];
304  FlutterViewController* flutterViewController =
305  [[FlutterViewController alloc] initWithEngine:engine nibName:nil bundle:nil];
306  XCTAssertFalse(flutterViewController.prefersStatusBarHidden);
307 
308  // Update to hidden.
309  FlutterPlatformPlugin* plugin = [engine platformPlugin];
310 
311  XCTestExpectation* enableSystemUIOverlaysCalled =
312  [self expectationWithDescription:@"setEnabledSystemUIOverlays"];
313  FlutterResult resultSet = ^(id result) {
314  [enableSystemUIOverlaysCalled fulfill];
315  };
316  FlutterMethodCall* methodCallSet =
317  [FlutterMethodCall methodCallWithMethodName:@"SystemChrome.setEnabledSystemUIOverlays"
318  arguments:@[ @"SystemUiOverlay.bottom" ]];
319  [plugin handleMethodCall:methodCallSet result:resultSet];
320  [self waitForExpectationsWithTimeout:1 handler:nil];
321  XCTAssertTrue(flutterViewController.prefersStatusBarHidden);
322 
323  // Update to shown.
324  XCTestExpectation* enableSystemUIOverlaysCalled2 =
325  [self expectationWithDescription:@"setEnabledSystemUIOverlays"];
326  FlutterResult resultSet2 = ^(id result) {
327  [enableSystemUIOverlaysCalled2 fulfill];
328  };
329  FlutterMethodCall* methodCallSet2 =
330  [FlutterMethodCall methodCallWithMethodName:@"SystemChrome.setEnabledSystemUIOverlays"
331  arguments:@[ @"SystemUiOverlay.top" ]];
332  [plugin handleMethodCall:methodCallSet2 result:resultSet2];
333  [self waitForExpectationsWithTimeout:1 handler:nil];
334  XCTAssertFalse(flutterViewController.prefersStatusBarHidden);
335 
336  [flutterViewController deregisterNotifications];
337  }
338  {
339  // Enable system UI mode to update status bar.
340  FlutterEngine* engine = [[FlutterEngine alloc] initWithName:@"test" project:nil];
341  [engine runWithEntrypoint:nil];
342  FlutterViewController* flutterViewController =
343  [[FlutterViewController alloc] initWithEngine:engine nibName:nil bundle:nil];
344  XCTAssertFalse(flutterViewController.prefersStatusBarHidden);
345 
346  // Update to hidden.
347  FlutterPlatformPlugin* plugin = [engine platformPlugin];
348 
349  XCTestExpectation* enableSystemUIModeCalled =
350  [self expectationWithDescription:@"setEnabledSystemUIMode"];
351  FlutterResult resultSet = ^(id result) {
352  [enableSystemUIModeCalled fulfill];
353  };
354  FlutterMethodCall* methodCallSet =
355  [FlutterMethodCall methodCallWithMethodName:@"SystemChrome.setEnabledSystemUIMode"
356  arguments:@"SystemUiMode.immersive"];
357  [plugin handleMethodCall:methodCallSet result:resultSet];
358  [self waitForExpectationsWithTimeout:1 handler:nil];
359  XCTAssertTrue(flutterViewController.prefersStatusBarHidden);
360 
361  // Update to shown.
362  XCTestExpectation* enableSystemUIModeCalled2 =
363  [self expectationWithDescription:@"setEnabledSystemUIMode"];
364  FlutterResult resultSet2 = ^(id result) {
365  [enableSystemUIModeCalled2 fulfill];
366  };
367  FlutterMethodCall* methodCallSet2 =
368  [FlutterMethodCall methodCallWithMethodName:@"SystemChrome.setEnabledSystemUIMode"
369  arguments:@"SystemUiMode.edgeToEdge"];
370  [plugin handleMethodCall:methodCallSet2 result:resultSet2];
371  [self waitForExpectationsWithTimeout:1 handler:nil];
372  XCTAssertFalse(flutterViewController.prefersStatusBarHidden);
373 
374  [flutterViewController deregisterNotifications];
375  }
376  [bundleMock stopMocking];
377 }
378 
379 - (void)testStatusBarHiddenUpdate {
380  id bundleMock = OCMPartialMock([NSBundle mainBundle]);
381  OCMStub([bundleMock objectForInfoDictionaryKey:@"UIViewControllerBasedStatusBarAppearance"])
382  .andReturn(@NO);
383  id mockApplication = OCMClassMock([UIApplication class]);
384  OCMStub([mockApplication sharedApplication]).andReturn(mockApplication);
385 
386  // Enabling system UI overlays to update status bar.
387  FlutterEngine* engine = [[FlutterEngine alloc] initWithName:@"test" project:nil];
388  [engine runWithEntrypoint:nil];
389  FlutterViewController* flutterViewController =
390  [[FlutterViewController alloc] initWithEngine:engine nibName:nil bundle:nil];
391 
392  // Update the visibility of the status bar to hidden.
393  FlutterPlatformPlugin* plugin = [engine platformPlugin];
394 
395  XCTestExpectation* systemOverlaysBottomExpectation =
396  [self expectationWithDescription:@"setEnabledSystemUIOverlays"];
397  FlutterResult systemOverlaysBottomResult = ^(id result) {
398  [systemOverlaysBottomExpectation fulfill];
399  };
400  FlutterMethodCall* setSystemOverlaysBottomCall =
401  [FlutterMethodCall methodCallWithMethodName:@"SystemChrome.setEnabledSystemUIOverlays"
402  arguments:@[ @"SystemUiOverlay.bottom" ]];
403  [plugin handleMethodCall:setSystemOverlaysBottomCall result:systemOverlaysBottomResult];
404  [self waitForExpectationsWithTimeout:1 handler:nil];
405  OCMVerify([mockApplication setStatusBarHidden:YES]);
406 
407  // Update the visibility of the status bar to shown.
408  XCTestExpectation* systemOverlaysTopExpectation =
409  [self expectationWithDescription:@"setEnabledSystemUIOverlays"];
410  FlutterResult systemOverlaysTopResult = ^(id result) {
411  [systemOverlaysTopExpectation fulfill];
412  };
413  FlutterMethodCall* setSystemOverlaysTopCall =
414  [FlutterMethodCall methodCallWithMethodName:@"SystemChrome.setEnabledSystemUIOverlays"
415  arguments:@[ @"SystemUiOverlay.top" ]];
416  [plugin handleMethodCall:setSystemOverlaysTopCall result:systemOverlaysTopResult];
417  [self waitForExpectationsWithTimeout:1 handler:nil];
418  OCMVerify([mockApplication setStatusBarHidden:NO]);
419 
420  [flutterViewController deregisterNotifications];
421  [mockApplication stopMocking];
422  [bundleMock stopMocking];
423 }
424 
425 - (void)testStatusBarHiddenNotUpdatedInAppExtension {
426  id bundleMock = OCMPartialMock([NSBundle mainBundle]);
427  OCMStub([bundleMock objectForInfoDictionaryKey:@"UIViewControllerBasedStatusBarAppearance"])
428  .andReturn(@NO);
429  OCMStub([bundleMock objectForInfoDictionaryKey:@"NSExtension"]).andReturn(@{
430  @"NSExtensionPointIdentifier" : @"com.apple.share-services"
431  });
432  id mockApplication = OCMClassMock([UIApplication class]);
433  OCMStub([mockApplication sharedApplication]).andReturn(mockApplication);
434  OCMReject([mockApplication setStatusBarHidden:OCMOCK_ANY]);
435 
436  // Enabling system UI overlays to update status bar.
437  FlutterEngine* engine = [[FlutterEngine alloc] initWithName:@"test" project:nil];
438  [engine runWithEntrypoint:nil];
439  FlutterViewController* flutterViewController =
440  [[FlutterViewController alloc] initWithEngine:engine nibName:nil bundle:nil];
441 
442  // Update the visibility of the status bar to hidden does not occur with extensions.
443  FlutterPlatformPlugin* plugin = [engine platformPlugin];
444 
445  XCTestExpectation* systemOverlaysBottomExpectation =
446  [self expectationWithDescription:@"setEnabledSystemUIOverlays"];
447  FlutterResult systemOverlaysBottomResult = ^(id result) {
448  [systemOverlaysBottomExpectation fulfill];
449  };
450  FlutterMethodCall* setSystemOverlaysBottomCall =
451  [FlutterMethodCall methodCallWithMethodName:@"SystemChrome.setEnabledSystemUIOverlays"
452  arguments:@[ @"SystemUiOverlay.bottom" ]];
453  [plugin handleMethodCall:setSystemOverlaysBottomCall result:systemOverlaysBottomResult];
454  [self waitForExpectationsWithTimeout:1 handler:nil];
455  OCMReject([mockApplication setStatusBarHidden:YES]);
456 
457  // Update the visibility of the status bar to shown does not occur with extensions.
458  XCTestExpectation* systemOverlaysTopExpectation =
459  [self expectationWithDescription:@"setEnabledSystemUIOverlays"];
460  FlutterResult systemOverlaysTopResult = ^(id result) {
461  [systemOverlaysTopExpectation fulfill];
462  };
463  FlutterMethodCall* setSystemOverlaysTopCall =
464  [FlutterMethodCall methodCallWithMethodName:@"SystemChrome.setEnabledSystemUIOverlays"
465  arguments:@[ @"SystemUiOverlay.top" ]];
466  [plugin handleMethodCall:setSystemOverlaysTopCall result:systemOverlaysTopResult];
467  [self waitForExpectationsWithTimeout:1 handler:nil];
468  OCMReject([mockApplication setStatusBarHidden:NO]);
469 
470  [flutterViewController deregisterNotifications];
471  [mockApplication stopMocking];
472  [bundleMock stopMocking];
473 }
474 
475 - (void)testStatusBarStyle {
476  id bundleMock = OCMPartialMock([NSBundle mainBundle]);
477  OCMStub([bundleMock objectForInfoDictionaryKey:@"UIViewControllerBasedStatusBarAppearance"])
478  .andReturn(@NO);
479  id mockApplication = OCMClassMock([UIApplication class]);
480  OCMStub([mockApplication sharedApplication]).andReturn(mockApplication);
481 
482  FlutterEngine* engine = [[FlutterEngine alloc] initWithName:@"test" project:nil];
483  [engine runWithEntrypoint:nil];
484  FlutterViewController* flutterViewController =
485  [[FlutterViewController alloc] initWithEngine:engine nibName:nil bundle:nil];
486  XCTAssertFalse(flutterViewController.prefersStatusBarHidden);
487 
488  FlutterPlatformPlugin* plugin = [engine platformPlugin];
489 
490  XCTestExpectation* enableSystemUIModeCalled =
491  [self expectationWithDescription:@"setSystemUIOverlayStyle"];
492  FlutterResult resultSet = ^(id result) {
493  [enableSystemUIModeCalled fulfill];
494  };
495  FlutterMethodCall* methodCallSet =
496  [FlutterMethodCall methodCallWithMethodName:@"SystemChrome.setSystemUIOverlayStyle"
497  arguments:@{@"statusBarBrightness" : @"Brightness.dark"}];
498  [plugin handleMethodCall:methodCallSet result:resultSet];
499  [self waitForExpectationsWithTimeout:1 handler:nil];
500 
501  OCMVerify([mockApplication setStatusBarStyle:UIStatusBarStyleLightContent]);
502 
503  [flutterViewController deregisterNotifications];
504  [mockApplication stopMocking];
505  [bundleMock stopMocking];
506 }
507 
508 - (void)testStatusBarStyleNotUpdatedInAppExtension {
509  id bundleMock = OCMPartialMock([NSBundle mainBundle]);
510  OCMStub([bundleMock objectForInfoDictionaryKey:@"UIViewControllerBasedStatusBarAppearance"])
511  .andReturn(@NO);
512  OCMStub([bundleMock objectForInfoDictionaryKey:@"NSExtension"]).andReturn(@{
513  @"NSExtensionPointIdentifier" : @"com.apple.share-services"
514  });
515  id mockApplication = OCMClassMock([UIApplication class]);
516  OCMStub([mockApplication sharedApplication]).andReturn(mockApplication);
517  OCMReject([mockApplication setStatusBarHidden:OCMOCK_ANY]);
518 
519  FlutterEngine* engine = [[FlutterEngine alloc] initWithName:@"test" project:nil];
520  [engine runWithEntrypoint:nil];
521  FlutterViewController* flutterViewController =
522  [[FlutterViewController alloc] initWithEngine:engine nibName:nil bundle:nil];
523  XCTAssertFalse(flutterViewController.prefersStatusBarHidden);
524 
525  FlutterPlatformPlugin* plugin = [engine platformPlugin];
526 
527  XCTestExpectation* enableSystemUIModeCalled =
528  [self expectationWithDescription:@"setSystemUIOverlayStyle"];
529  FlutterResult resultSet = ^(id result) {
530  [enableSystemUIModeCalled fulfill];
531  };
532  FlutterMethodCall* methodCallSet =
533  [FlutterMethodCall methodCallWithMethodName:@"SystemChrome.setSystemUIOverlayStyle"
534  arguments:@{@"statusBarBrightness" : @"Brightness.dark"}];
535  [plugin handleMethodCall:methodCallSet result:resultSet];
536  [self waitForExpectationsWithTimeout:1 handler:nil];
537 
538  [flutterViewController deregisterNotifications];
539  [mockApplication stopMocking];
540  [bundleMock stopMocking];
541 }
542 
543 @end
void(^ FlutterResult)(id _Nullable result)
BOOL runWithEntrypoint:(nullable NSString *entrypoint)
instancetype methodCallWithMethodName:arguments:(NSString *method,[arguments] id _Nullable arguments)
void handleMethodCall:result:(FlutterMethodCall *call,[result] FlutterResult result)