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