| 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 @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
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:92
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:107
FlutterPlatformPluginTest
Definition: FlutterPlatformPluginTest.mm:18
FlutterViewController
Definition: FlutterViewController.h:57
FLUTTER_ASSERT_ARC
Definition: FlutterChannelKeyResponder.mm:13
platform_view_ios.h