5 #import <OCMock/OCMock.h>
6 #import <XCTest/XCTest.h>
22 @property(nonatomic) BOOL callbackCalled;
29 - (instancetype)init {
34 - (flutter::Rasterizer::Screenshot)takeScreenshot:(flutter::Rasterizer::ScreenshotType)type
35 asBase64Encoded:(BOOL)base64Encode {
40 _callbackCalled = YES;
50 - (void)testFlutterViewEnableSemanticsWhenIsAccessibilityElementIsCalled {
54 XCTAssertFalse(view.isAccessibilityElement);
58 - (void)testFlutterViewBackgroundColorIsNil {
61 XCTAssertNil(view.backgroundColor);
64 - (void)testLayerScalesMatchScreenAfterLayoutSubviews {
67 view.layer.contentsScale = CGFloat(-99.0);
68 view.layer.rasterizationScale = CGFloat(-99.0);
69 UIScreen* screen = [view
screen];
70 XCTAssertNotEqual(view.layer.contentsScale, screen.scale);
71 XCTAssertNotEqual(view.layer.rasterizationScale, screen.scale);
72 [view layoutSubviews];
73 XCTAssertEqual(view.layer.contentsScale, screen.scale);
74 XCTAssertEqual(view.layer.rasterizationScale, screen.scale);
77 - (void)testViewWillMoveToWindow {
78 NSDictionary* mocks = [
self createWindowMocks];
80 id mockLifecycleDelegate = mocks[@"mockLifecycleDelegate"];
83 id mockEngine = mocks[@"mockEngine"];
84 id mockWindow = mocks[@"mockWindow"];
86 [view willMoveToWindow:mockWindow];
87 OCMVerify(times(1), [mockLifecycleDelegate addFlutterManagedEngine:mockEngine]);
91 - (void)testViewWillMoveToSameWindow {
92 NSDictionary* mocks = [
self createWindowMocks];
94 id mockLifecycleDelegate = mocks[@"mockLifecycleDelegate"];
97 id mockEngine = mocks[@"mockEngine"];
98 id mockWindow = mocks[@"mockWindow"];
100 [view willMoveToWindow:mockWindow];
101 [view willMoveToWindow:mockWindow];
103 OCMVerify(times(2), [mockLifecycleDelegate addFlutterManagedEngine:mockEngine]);
107 - (void)testMultipleViewsWillMoveToSameWindow {
108 NSDictionary* mocks = [
self createWindowMocks];
110 id mockLifecycleDelegate = mocks[@"mockLifecycleDelegate"];
113 id mockEngine1 = mocks[@"mockEngine"];
114 id mockWindow1 = mocks[@"mockWindow"];
121 [view1 willMoveToWindow:mockWindow1];
122 [view2 willMoveToWindow:mockWindow1];
123 [view1 willMoveToWindow:mockWindow1];
124 OCMVerify(times(2), [mockLifecycleDelegate addFlutterManagedEngine:mockEngine1]);
125 OCMVerify(times(1), [mockLifecycleDelegate addFlutterManagedEngine:mockEngine2]);
129 - (void)testMultipleViewsWillMoveToDifferentWindow {
130 NSDictionary* mocks = [
self createWindowMocks];
132 id mockLifecycleDelegate1 = mocks[@"mockLifecycleDelegate"];
135 id mockEngine1 = mocks[@"mockEngine"];
136 id mockWindow1 = mocks[@"mockWindow"];
138 NSDictionary* mocks2 = [
self createWindowMocks];
140 id mockLifecycleDelegate2 = mocks2[@"mockLifecycleDelegate"];
143 id mockEngine2 = mocks2[@"mockEngine"];
144 id mockWindow2 = mocks2[@"mockWindow"];
146 [view1 willMoveToWindow:mockWindow1];
147 [view2 willMoveToWindow:mockWindow2];
148 [view1 willMoveToWindow:mockWindow1];
149 OCMVerify(times(2), [mockLifecycleDelegate1 addFlutterManagedEngine:mockEngine1]);
150 OCMVerify(times(1), [mockLifecycleDelegate2 addFlutterManagedEngine:mockEngine2]);
155 - (void)testViewRemovedFromWindowAndAddedToNewScene {
156 NSDictionary* mocks = [
self createWindowMocks];
158 id mockLifecycleDelegate = mocks[@"mockLifecycleDelegate"];
161 id mockEngine = mocks[@"mockEngine"];
162 id mockWindow = mocks[@"mockWindow"];
164 NSDictionary* mocks2 = [
self createWindowMocks];
165 id mockWindow2 = mocks2[@"mockWindow"];
166 id mockLifecycleDelegate2 = mocks2[@"mockLifecycleDelegate"];
170 id mockView = OCMPartialMock(view);
172 [mockView willMoveToWindow:mockWindow];
173 OCMVerify(times(1), [mockLifecycleDelegate addFlutterManagedEngine:mockEngine]);
176 OCMStub([mockView window]).andReturn(mockWindow);
177 [mockView willMoveToWindow:nil];
180 OCMStub([mockView window]).andReturn(nil);
181 [mockView willMoveToWindow:mockWindow2];
182 OCMVerify(times(1), [mockLifecycleDelegate removeFlutterManagedEngine:mockEngine]);
184 OCMVerify(times(1), [mockLifecycleDelegate2 addFlutterManagedEngine:mockEngine]);
188 - (NSDictionary*)createWindowMocks {
189 return [
self createWindowMocksWithWideGamut:NO];
192 - (NSDictionary*)createWindowMocksWithWideGamut:(BOOL)enableWideGamut {
196 enableWideGamut:enableWideGamut];
197 id mockWindow = OCMClassMock([UIWindow
class]);
198 id mockWindowScene = OCMClassMock([UIWindowScene
class]);
201 id mockSceneDelegate = OCMPartialMock(sceneDelegate);
205 id mockLifecycleDelegate = OCMPartialMock(lifecycleDelegate);
207 OCMStub([mockWindow windowScene]).andReturn(mockWindowScene);
208 OCMStub([mockWindowScene delegate]).andReturn(mockSceneDelegate);
209 OCMStub([mockSceneDelegate sceneLifeCycleDelegate]).andReturn(mockLifecycleDelegate);
213 @"mockLifecycleDelegate" : mockLifecycleDelegate,
214 @"lifecycleDelegate" : lifecycleDelegate,
215 @"mockEngine" : mockEngine,
216 @"mockWindow" : mockWindow,
220 #pragma mark - Wide Gamut Tests
223 - (
FlutterView*)createViewInWindowWithWideGamut:(BOOL)enableWideGamut {
227 enableWideGamut:enableWideGamut];
229 UIWindow* window = [[UIWindow alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
230 [window addSubview:view];
231 view.frame = window.bounds;
232 [view layoutSubviews];
236 - (void)testWideGamutViewSetsBGRA10XRPixelFormat {
237 FlutterView* view = [
self createViewInWindowWithWideGamut:YES];
241 XCTAssertEqual(view.
pixelFormat, MTLPixelFormatBGRA10_XR);
243 XCTAssertEqual(view.
pixelFormat, MTLPixelFormatBGRA8Unorm);
247 - (void)testStandardGamutViewKeepsBGRA8Unorm {
248 FlutterView* view = [
self createViewInWindowWithWideGamut:NO];
249 XCTAssertEqual(view.
pixelFormat, MTLPixelFormatBGRA8Unorm);
252 - (void)testWideGamutViewSetsExtendedSRGBColorSpace {
253 FlutterView* view = [
self createViewInWindowWithWideGamut:YES];
255 CAMetalLayer* layer = (CAMetalLayer*)view.layer;
256 CGColorSpaceRef colorSpace = layer.colorspace;
257 XCTAssertNotNil((__bridge
id)colorSpace);
258 CGColorSpaceRef extendedSRGB = CGColorSpaceCreateWithName(kCGColorSpaceExtendedSRGB);
259 XCTAssertTrue(CFEqual(colorSpace, extendedSRGB));
260 CGColorSpaceRelease(extendedSRGB);
264 - (void)testStandardGamutViewDoesNotSetExtendedColorSpace {
265 FlutterView* view = [
self createViewInWindowWithWideGamut:NO];
266 CAMetalLayer* layer = (CAMetalLayer*)view.layer;
268 XCTAssertNil((__bridge
id)layer.colorspace);
271 #pragma mark - FlutterOverlayView Wide Gamut Tests
273 - (void)testOverlayViewWideGamutSetsBGRA10XR {
275 [[
FlutterOverlayView alloc] initWithContentsScale:2.0 pixelFormat:MTLPixelFormatBGRA10_XR];
276 CAMetalLayer* layer = (CAMetalLayer*)overlay.layer;
277 XCTAssertEqual(layer.pixelFormat, MTLPixelFormatBGRA10_XR);
280 - (void)testOverlayViewWideGamutSetsExtendedSRGBColorSpace {
282 [[
FlutterOverlayView alloc] initWithContentsScale:2.0 pixelFormat:MTLPixelFormatBGRA10_XR];
283 CAMetalLayer* layer = (CAMetalLayer*)overlay.layer;
284 CGColorSpaceRef colorSpace = layer.colorspace;
285 XCTAssertNotNil((__bridge
id)colorSpace);
286 CGColorSpaceRef extendedSRGB = CGColorSpaceCreateWithName(kCGColorSpaceExtendedSRGB);
287 XCTAssertTrue(CFEqual(colorSpace, extendedSRGB));
288 CGColorSpaceRelease(extendedSRGB);
291 - (void)testOverlayViewStandardGamutKeepsBGRA8Unorm {
293 [[
FlutterOverlayView alloc] initWithContentsScale:2.0 pixelFormat:MTLPixelFormatBGRA8Unorm];
294 CAMetalLayer* layer = (CAMetalLayer*)overlay.layer;
295 XCTAssertEqual(layer.pixelFormat, MTLPixelFormatBGRA8Unorm);
298 - (void)testOverlayViewStandardGamutDoesNotSetExtendedColorSpace {
300 [[
FlutterOverlayView alloc] initWithContentsScale:2.0 pixelFormat:MTLPixelFormatBGRA8Unorm];
301 CAMetalLayer* layer = (CAMetalLayer*)overlay.layer;
302 XCTAssertNil((__bridge
id)layer.colorspace);
305 - (void)testOverlayViewContentsScaleIsSet {
307 [[
FlutterOverlayView alloc] initWithContentsScale:3.0 pixelFormat:MTLPixelFormatBGRA10_XR];
308 XCTAssertEqual(overlay.layer.contentsScale, 3.0);
309 XCTAssertEqual(overlay.layer.rasterizationScale, 3.0);
BOOL isWideGamutSupported()
NSPointerArray * flutterManagedEngines
MTLPixelFormat pixelFormat()
FlutterPlatformViewsController * platformViewsController
void flutterViewAccessibilityDidCall()