Flutter iOS Embedder
FlutterViewControllerTest_mrc.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 
12 
14 
15 @interface UITouch ()
16 
17 @property(nonatomic, readwrite) UITouchPhase phase;
18 
19 @end
20 
22 
23 - (CADisplayLink*)getDisplayLink;
24 
25 @end
26 
28 
29 @property(nonatomic, assign) double targetViewInsetBottom;
30 @property(nonatomic, retain) VSyncClient* keyboardAnimationVSyncClient;
31 
32 @property(nonatomic, retain) VSyncClient* touchRateCorrectionVSyncClient;
33 
35 - (void)setUpKeyboardAnimationVsyncClient:
36  (FlutterKeyboardAnimationCallback)keyboardAnimationCallback;
37 - (void)startKeyBoardAnimation:(NSTimeInterval)duration;
38 - (void)triggerTouchRateCorrectionIfNeeded:(NSSet*)touches;
39 
40 @end
41 
42 @interface FlutterViewControllerTest_mrc : XCTestCase
43 @end
44 
45 @implementation FlutterViewControllerTest_mrc
46 
47 - (void)testSetupKeyboardAnimationVsyncClientWillCreateNewVsyncClientForFlutterViewController {
48  id bundleMock = OCMPartialMock([NSBundle mainBundle]);
49  OCMStub([bundleMock objectForInfoDictionaryKey:@"CADisableMinimumFrameDurationOnPhone"])
50  .andReturn(@YES);
51  id mockDisplayLinkManager = [OCMockObject mockForClass:[DisplayLinkManager class]];
52  double maxFrameRate = 120;
53  [[[mockDisplayLinkManager stub] andReturnValue:@(maxFrameRate)] displayRefreshRate];
54  FlutterEngine* engine = [[[FlutterEngine alloc] init] autorelease];
55  [engine runWithEntrypoint:nil];
57  [[[FlutterViewController alloc] initWithEngine:engine nibName:nil bundle:nil] autorelease];
58  FlutterKeyboardAnimationCallback callback = ^(fml::TimePoint targetTime) {
59  };
60  [viewController setUpKeyboardAnimationVsyncClient:callback];
61  XCTAssertNotNil(viewController.keyboardAnimationVSyncClient);
62  CADisplayLink* link = [viewController.keyboardAnimationVSyncClient getDisplayLink];
63  XCTAssertNotNil(link);
64  if (@available(iOS 15.0, *)) {
65  XCTAssertEqual(link.preferredFrameRateRange.maximum, maxFrameRate);
66  XCTAssertEqual(link.preferredFrameRateRange.preferred, maxFrameRate);
67  XCTAssertEqual(link.preferredFrameRateRange.minimum, maxFrameRate / 2);
68  } else {
69  XCTAssertEqual(link.preferredFramesPerSecond, maxFrameRate);
70  }
71 }
72 
73 - (void)
74  testCreateTouchRateCorrectionVSyncClientWillCreateVsyncClientWhenRefreshRateIsLargerThan60HZ {
75  id mockDisplayLinkManager = [OCMockObject mockForClass:[DisplayLinkManager class]];
76  double maxFrameRate = 120;
77  [[[mockDisplayLinkManager stub] andReturnValue:@(maxFrameRate)] displayRefreshRate];
78  FlutterEngine* engine = [[[FlutterEngine alloc] init] autorelease];
79  [engine runWithEntrypoint:nil];
81  [[[FlutterViewController alloc] initWithEngine:engine nibName:nil bundle:nil] autorelease];
82  [viewController createTouchRateCorrectionVSyncClientIfNeeded];
83  XCTAssertNotNil(viewController.touchRateCorrectionVSyncClient);
84 }
85 
86 - (void)testCreateTouchRateCorrectionVSyncClientWillNotCreateNewVSyncClientWhenClientAlreadyExists {
87  id mockDisplayLinkManager = [OCMockObject mockForClass:[DisplayLinkManager class]];
88  double maxFrameRate = 120;
89  [[[mockDisplayLinkManager stub] andReturnValue:@(maxFrameRate)] displayRefreshRate];
90 
91  FlutterEngine* engine = [[[FlutterEngine alloc] init] autorelease];
92  [engine runWithEntrypoint:nil];
94  [[[FlutterViewController alloc] initWithEngine:engine nibName:nil bundle:nil] autorelease];
95  [viewController createTouchRateCorrectionVSyncClientIfNeeded];
96  VSyncClient* clientBefore = viewController.touchRateCorrectionVSyncClient;
97  XCTAssertNotNil(clientBefore);
98 
99  [viewController createTouchRateCorrectionVSyncClientIfNeeded];
100  VSyncClient* clientAfter = viewController.touchRateCorrectionVSyncClient;
101  XCTAssertNotNil(clientAfter);
102 
103  XCTAssertTrue(clientBefore == clientAfter);
104 }
105 
106 - (void)testCreateTouchRateCorrectionVSyncClientWillNotCreateVsyncClientWhenRefreshRateIs60HZ {
107  id mockDisplayLinkManager = [OCMockObject mockForClass:[DisplayLinkManager class]];
108  double maxFrameRate = 60;
109  [[[mockDisplayLinkManager stub] andReturnValue:@(maxFrameRate)] displayRefreshRate];
110  FlutterEngine* engine = [[[FlutterEngine alloc] init] autorelease];
111  [engine runWithEntrypoint:nil];
113  [[[FlutterViewController alloc] initWithEngine:engine nibName:nil bundle:nil] autorelease];
114  [viewController createTouchRateCorrectionVSyncClientIfNeeded];
115  XCTAssertNil(viewController.touchRateCorrectionVSyncClient);
116 }
117 
118 - (void)testTriggerTouchRateCorrectionVSyncClientCorrectly {
119  id mockDisplayLinkManager = [OCMockObject mockForClass:[DisplayLinkManager class]];
120  double maxFrameRate = 120;
121  [[[mockDisplayLinkManager stub] andReturnValue:@(maxFrameRate)] displayRefreshRate];
122  FlutterEngine* engine = [[[FlutterEngine alloc] init] autorelease];
123  [engine runWithEntrypoint:nil];
125  [[[FlutterViewController alloc] initWithEngine:engine nibName:nil bundle:nil] autorelease];
126  [viewController loadView];
127  [viewController viewDidLoad];
128 
129  VSyncClient* client = viewController.touchRateCorrectionVSyncClient;
130  CADisplayLink* link = [client getDisplayLink];
131 
132  UITouch* fakeTouchBegan = [[[UITouch alloc] init] autorelease];
133  fakeTouchBegan.phase = UITouchPhaseBegan;
134 
135  UITouch* fakeTouchMove = [[[UITouch alloc] init] autorelease];
136  fakeTouchMove.phase = UITouchPhaseMoved;
137 
138  UITouch* fakeTouchEnd = [[[UITouch alloc] init] autorelease];
139  fakeTouchEnd.phase = UITouchPhaseEnded;
140 
141  UITouch* fakeTouchCancelled = [[[UITouch alloc] init] autorelease];
142  fakeTouchCancelled.phase = UITouchPhaseCancelled;
143 
144  [viewController
145  triggerTouchRateCorrectionIfNeeded:[[[NSSet alloc] initWithObjects:fakeTouchBegan, nil]
146  autorelease]];
147  XCTAssertFalse(link.isPaused);
148 
149  [viewController
150  triggerTouchRateCorrectionIfNeeded:[[[NSSet alloc] initWithObjects:fakeTouchEnd, nil]
151  autorelease]];
152  XCTAssertTrue(link.isPaused);
153 
154  [viewController
155  triggerTouchRateCorrectionIfNeeded:[[[NSSet alloc] initWithObjects:fakeTouchMove, nil]
156  autorelease]];
157  XCTAssertFalse(link.isPaused);
158 
159  [viewController
160  triggerTouchRateCorrectionIfNeeded:[[[NSSet alloc] initWithObjects:fakeTouchCancelled, nil]
161  autorelease]];
162  XCTAssertTrue(link.isPaused);
163 
164  [viewController
165  triggerTouchRateCorrectionIfNeeded:[[[NSSet alloc]
166  initWithObjects:fakeTouchBegan, fakeTouchEnd, nil]
167  autorelease]];
168  XCTAssertFalse(link.isPaused);
169 
170  [viewController
171  triggerTouchRateCorrectionIfNeeded:[[[NSSet alloc]
172  initWithObjects:fakeTouchEnd, fakeTouchCancelled, nil]
173  autorelease]];
174  XCTAssertTrue(link.isPaused);
175 
176  [viewController
177  triggerTouchRateCorrectionIfNeeded:[[[NSSet alloc]
178  initWithObjects:fakeTouchMove, fakeTouchEnd, nil]
179  autorelease]];
180  XCTAssertFalse(link.isPaused);
181 }
182 
183 - (void)testFlutterViewControllerStartKeyboardAnimationWillCreateVsyncClientCorrectly {
184  FlutterEngine* engine = [[[FlutterEngine alloc] init] autorelease];
185  [engine runWithEntrypoint:nil];
187  [[[FlutterViewController alloc] initWithEngine:engine nibName:nil bundle:nil] autorelease];
188  viewController.targetViewInsetBottom = 100;
189  [viewController startKeyBoardAnimation:0.25];
190  XCTAssertNotNil(viewController.keyboardAnimationVSyncClient);
191 }
192 
193 - (void)
194  testSetupKeyboardAnimationVsyncClientWillNotCreateNewVsyncClientWhenKeyboardAnimationCallbackIsNil {
195  FlutterEngine* engine = [[[FlutterEngine alloc] init] autorelease];
196  [engine runWithEntrypoint:nil];
198  [[[FlutterViewController alloc] initWithEngine:engine nibName:nil bundle:nil] autorelease];
199  [viewController setUpKeyboardAnimationVsyncClient:nil];
200  XCTAssertNil(viewController.keyboardAnimationVSyncClient);
201 }
202 
203 @end
FlutterViewController(Testing)
Definition: FlutterViewControllerTest_mrc.mm:27
FlutterViewController(Testing)::touchRateCorrectionVSyncClient
VSyncClient * touchRateCorrectionVSyncClient
Definition: FlutterViewControllerTest_mrc.mm:32
FlutterViewController(Testing)::keyboardAnimationVSyncClient
VSyncClient * keyboardAnimationVSyncClient
Definition: FlutterViewControllerTest_mrc.mm:30
FlutterEngine
Definition: FlutterEngine.h:59
FlutterViewController
Definition: FlutterViewController.h:55
-[FlutterEngine runWithEntrypoint:]
BOOL runWithEntrypoint:(nullable NSString *entrypoint)
FLUTTER_ASSERT_NOT_ARC
Definition: VsyncWaiterIosTest.mm:15
FlutterViewController(Testing)::targetViewInsetBottom
double targetViewInsetBottom
Definition: FlutterViewControllerTest_mrc.mm:29
-[VSyncClient(Testing) getDisplayLink]
CADisplayLink * getDisplayLink()
FlutterMacros.h
viewController
FlutterViewController * viewController
Definition: FlutterTextInputPluginTest.mm:92
FlutterKeyboardAnimationCallback
void(^ FlutterKeyboardAnimationCallback)(fml::TimePoint)
Definition: FlutterViewController_Internal.h:36
-[FlutterViewController(Testing) createTouchRateCorrectionVSyncClientIfNeeded]
void createTouchRateCorrectionVSyncClientIfNeeded()
engine
id engine
Definition: FlutterTextInputPluginTest.mm:89
FlutterViewController_Internal.h
VSyncClient(Testing)
Definition: FlutterViewControllerTest_mrc.mm:21
vsync_waiter_ios.h
FlutterViewControllerTest_mrc
Definition: FlutterViewControllerTest_mrc.mm:42
VSyncClient
Definition: vsync_waiter_ios.h:38
FlutterViewController.h