Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit 6e91de1

Browse files
committed
Adding tests for ViewController platform view support.
1 parent 1925716 commit 6e91de1

10 files changed

+308
-1
lines changed

ci/licenses_golden/licenses_flutter

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1073,6 +1073,8 @@ FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterIOSur
10731073
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterMouseCursorPlugin.h
10741074
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterMouseCursorPlugin.mm
10751075
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterPlatformViews.h
1076+
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterPlatformViewMock.h
1077+
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterPlatformViewMock.mm
10761078
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterResizeSynchronizer.h
10771079
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterResizeSynchronizer.mm
10781080
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterSurfaceManager.h

shell/platform/darwin/macos/BUILD.gn

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,8 @@ executable("flutter_desktop_darwin_unittests") {
128128
sources = [
129129
"framework/Source/FlutterEngineTest.mm",
130130
"framework/Source/FlutterGLCompositorUnittests.mm",
131+
"framework/Source/FlutterPlatformViewMock.h",
132+
"framework/Source/FlutterPlatformViewMock.mm",
131133
"framework/Source/FlutterViewControllerTest.mm",
132134
"framework/Source/FlutterViewControllerTestUtils.h",
133135
"framework/Source/FlutterViewControllerTestUtils.mm",
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
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 <Foundation/Foundation.h>
6+
#import <Foundation/NSObject.h>
7+
8+
#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterPlatformViews.h"
9+
10+
@interface FlutterPlatformViewMock : NSObject <FlutterPlatformView>
11+
@property(nonatomic, strong) NSView* view;
12+
@end
13+
14+
@interface MockPlatformView : NSView
15+
@end
16+
17+
@interface FlutterPlatformViewMockFactory : NSObject <FlutterPlatformViewFactory>
18+
@end
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
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 <Cocoa/Cocoa.h>
6+
#import <Foundation/Foundation.h>
7+
8+
#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterPlatformViewMock.h"
9+
#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterPlatformViews.h"
10+
11+
@implementation MockPlatformView
12+
13+
- (instancetype)initWithFrame:(CGRect)frame {
14+
self = [super initWithFrame:frame];
15+
return self;
16+
}
17+
18+
@end
19+
20+
@implementation FlutterPlatformViewMock
21+
22+
- (instancetype)initWithFrame:(CGRect)frame arguments:(id _Nullable)args {
23+
if (self = [super init]) {
24+
_view = [[MockPlatformView alloc] initWithFrame:frame];
25+
}
26+
return self;
27+
}
28+
29+
@end
30+
31+
@implementation FlutterPlatformViewMockFactory
32+
- (NSObject<FlutterPlatformView>*)createWithFrame:(CGRect)frame
33+
viewIdentifier:(int64_t)viewId
34+
arguments:(id _Nullable)args {
35+
return [[FlutterPlatformViewMock alloc] initWithFrame:frame arguments:args];
36+
}
37+
38+
- (NSObject<FlutterMessageCodec>*)createArgsCodec {
39+
return [FlutterStandardMessageCodec sharedInstance];
40+
}
41+
42+
@end
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterPlatformViews_Internal.h"
2+
3+
namespace flutter {
4+
5+
FlutterPlatformViewsController::FlutterPlatformViewsController() {};
6+
7+
FlutterPlatformViewsController::~FlutterPlatformViewsController() = default;
8+
9+
} // namespace flutter
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
2+
#include <map>
3+
#include <unordered_set>
4+
5+
#include "flutter/fml/platform/darwin/scoped_nsobject.h"
6+
7+
namespace flutter {
8+
9+
class FlutterPlatformViewsController {
10+
public:
11+
FlutterPlatformViewsController();
12+
13+
~FlutterPlatformViewsController();
14+
private:
15+
std::map<int, fml::scoped_nsobject<NSView>> views;
16+
std::unordered_set<int64_t> viewsToDispose;
17+
std::map<std::string, fml::scoped_nsobject<NSObject<FlutterPlatformViewFactory>>> factories_;
18+
}
19+
20+
} // namespace flutter

shell/platform/darwin/macos/framework/Source/FlutterViewController.mm

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -434,7 +434,6 @@ - (void)onCreate:(nonnull FlutterMethodCall*)call result:(nonnull FlutterResult)
434434
- (void)onDispose:(nonnull FlutterMethodCall*)call result:(nonnull FlutterResult)result {
435435
NSNumber* arg = [call arguments];
436436
int64_t viewId = [arg longLongValue];
437-
NSLog(@"onDispose ViewId: %lld", viewId);
438437

439438
if (_platformViews.count(viewId) == 0) {
440439
result([FlutterError errorWithCode:@"unknown_view"

shell/platform/darwin/macos/framework/Source/FlutterViewControllerTest.mm

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,14 @@
66

77
#import <OCMock/OCMock.h>
88

9+
#import "flutter/shell/platform/darwin/common/framework/Headers/FlutterChannels.h"
910
#import "flutter/shell/platform/darwin/macos/framework/Headers/FlutterEngine.h"
1011
#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterDartProject_Internal.h"
1112
#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterEngine_Internal.h"
13+
#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterPlatformViewMock.h"
14+
#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterPlatformViews.h"
1215
#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterViewControllerTestUtils.h"
16+
1317
#include "flutter/testing/testing.h"
1418

1519
namespace flutter::testing {
@@ -53,4 +57,138 @@
5357
EXPECT_TRUE(value);
5458
}
5559

60+
TEST(FlutterViewController, TestCreatePlatformViewNoMatchingViewType) {
61+
NSString* fixtures = @(testing::GetFixturesPath());
62+
FlutterDartProject* project = [[FlutterDartProject alloc]
63+
initWithAssetsPath:fixtures
64+
ICUDataPath:[fixtures stringByAppendingString:@"/icudtl.dat"]];
65+
66+
// Use id so we can access private handleMethodCall method.
67+
id viewController = [[FlutterViewController alloc] initWithProject:project];
68+
69+
FlutterMethodCall* methodCall =
70+
[FlutterMethodCall methodCallWithMethodName:@"create"
71+
arguments:@{
72+
@"id" : @2,
73+
@"viewType" : @"FlutterPlatformViewMock"
74+
}];
75+
76+
__block bool errored = false;
77+
FlutterResult result = ^(id result) {
78+
if ([result isKindOfClass:[FlutterError class]]) {
79+
errored = true;
80+
}
81+
};
82+
83+
[viewController onCreate:methodCall result:result];
84+
85+
// We expect the call to error since no factories are registered.
86+
EXPECT_TRUE(errored);
87+
}
88+
89+
TEST(FlutterViewController, TestRegisterPlatformViewFactoryAndCreate) {
90+
NSString* fixtures = @(testing::GetFixturesPath());
91+
FlutterDartProject* project = [[FlutterDartProject alloc]
92+
initWithAssetsPath:fixtures
93+
ICUDataPath:[fixtures stringByAppendingString:@"/icudtl.dat"]];
94+
95+
// Use id so we can access private handleMethodCall method.
96+
id viewController = [[FlutterViewController alloc] initWithProject:project];
97+
98+
FlutterPlatformViewMockFactory* factory = [FlutterPlatformViewMockFactory alloc];
99+
100+
[viewController registerViewFactory:factory withId:@"MockPlatformView"];
101+
102+
FlutterMethodCall* methodCall =
103+
[FlutterMethodCall methodCallWithMethodName:@"create"
104+
arguments:@{
105+
@"id" : @2,
106+
@"viewType" : @"MockPlatformView"
107+
}];
108+
109+
__block bool success = false;
110+
FlutterResult result = ^(id result) {
111+
// If a platform view is successfully created, the result is nil.
112+
if (result == nil) {
113+
success = true;
114+
}
115+
};
116+
[viewController onCreate:methodCall result:result];
117+
118+
EXPECT_TRUE(success);
119+
}
120+
121+
TEST(FlutterViewController, TestCreateAndDispose) {
122+
NSString* fixtures = @(testing::GetFixturesPath());
123+
FlutterDartProject* project = [[FlutterDartProject alloc]
124+
initWithAssetsPath:fixtures
125+
ICUDataPath:[fixtures stringByAppendingString:@"/icudtl.dat"]];
126+
127+
// Use id so we can access private handleMethodCall method.
128+
id viewController = [[FlutterViewController alloc] initWithProject:project];
129+
130+
FlutterPlatformViewMockFactory* factory = [FlutterPlatformViewMockFactory alloc];
131+
132+
[viewController registerViewFactory:factory withId:@"MockPlatformView"];
133+
134+
FlutterMethodCall* methodCallOnCreate =
135+
[FlutterMethodCall methodCallWithMethodName:@"create"
136+
arguments:@{
137+
@"id" : @2,
138+
@"viewType" : @"MockPlatformView"
139+
}];
140+
141+
__block bool created = false;
142+
FlutterResult resultOnCreate = ^(id result) {
143+
// If a platform view is successfully created, the result is nil.
144+
if (result == nil) {
145+
created = true;
146+
}
147+
};
148+
149+
[viewController onCreate:methodCallOnCreate result:resultOnCreate];
150+
151+
FlutterMethodCall* methodCallOnDispose =
152+
[FlutterMethodCall methodCallWithMethodName:@"dispose"
153+
arguments:[NSNumber numberWithLongLong:2]];
154+
155+
__block bool disposed = false;
156+
FlutterResult resultOnDispose = ^(id result) {
157+
// If a platform view is successfully created, the result is nil.
158+
if (result == nil) {
159+
disposed = true;
160+
}
161+
};
162+
163+
[viewController onDispose:methodCallOnDispose result:resultOnDispose];
164+
165+
EXPECT_TRUE(created);
166+
EXPECT_TRUE(disposed);
167+
}
168+
169+
TEST(FlutterViewController, TestDisposeOnMissingViewId) {
170+
NSString* fixtures = @(testing::GetFixturesPath());
171+
FlutterDartProject* project = [[FlutterDartProject alloc]
172+
initWithAssetsPath:fixtures
173+
ICUDataPath:[fixtures stringByAppendingString:@"/icudtl.dat"]];
174+
175+
// Use id so we can access private handleMethodCall method.
176+
id viewController = [[FlutterViewController alloc] initWithProject:project];
177+
178+
FlutterMethodCall* methodCall =
179+
[FlutterMethodCall methodCallWithMethodName:@"dispose"
180+
arguments:[NSNumber numberWithLongLong:20]];
181+
182+
__block bool errored = false;
183+
FlutterResult result = ^(id result) {
184+
if ([result isKindOfClass:[FlutterError class]]) {
185+
errored = true;
186+
}
187+
};
188+
189+
[viewController onDispose:methodCall result:result];
190+
191+
EXPECT_TRUE(errored);
192+
}
193+
56194
} // flutter::testing
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
#import <Foundation/Foundation.h>
2+
#import <Foundation/NSObject.h>
3+
4+
#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterPlatformViews.h"
5+
6+
@interface MockFlutterPlatformView : NSObject <FlutterPlatformView>
7+
@property(nonatomic, strong) NSView* view;
8+
@end
9+
10+
@interface MockPlatformView : NSTextView
11+
@end
12+
13+
@interface MockFlutterPlatformFactory : NSObject <FlutterPlatformViewFactory>
14+
@end
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
#import <Cocoa/Cocoa.h>
2+
3+
#import <Foundation/Foundation.h>
4+
#import <WebKit/WebKit.h>
5+
6+
#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterPlatformViews.h"
7+
#import "flutter/shell/platform/darwin/macos/framework/Source/MockFlutterPlatformView.h"
8+
9+
@implementation MockPlatformView
10+
11+
- (instancetype)initWithFrame:(CGRect)frame {
12+
self = [super initWithFrame:frame];
13+
[super setString:@"hello1"];
14+
[super setTextColor:[NSColor blueColor]];
15+
return self;
16+
}
17+
18+
@end
19+
20+
@implementation MockFlutterPlatformView
21+
22+
- (instancetype)init {
23+
if (self = [super init]) {
24+
_view = [[MockPlatformView alloc] init];
25+
}
26+
return self;
27+
}
28+
29+
- (instancetype)initWithFrame:(CGRect)frame arguments:(id _Nullable)args {
30+
if (self = [super init]) {
31+
WKUserContentController* userContentController = [[WKUserContentController alloc] init];
32+
WKWebViewConfiguration* configuration = [[WKWebViewConfiguration alloc] init];
33+
configuration.userContentController = userContentController;
34+
35+
WKWebView* webView = [[WKWebView alloc] initWithFrame:frame];
36+
37+
NSURL *url = [NSURL URLWithString:@"https://flutter.dev/"];
38+
NSURLRequest *request = [NSURLRequest requestWithURL:url];
39+
40+
[webView loadRequest:request];
41+
_view = webView;
42+
}
43+
return self;
44+
}
45+
46+
- (void)dealloc {
47+
_view = nil;
48+
}
49+
50+
@end
51+
52+
@implementation MockFlutterPlatformFactory
53+
- (NSObject<FlutterPlatformView>*)createWithFrame:(CGRect)frame
54+
viewIdentifier:(int64_t)viewId
55+
arguments:(id _Nullable)args {
56+
return [[MockFlutterPlatformView alloc] initWithFrame:frame arguments:args];
57+
}
58+
59+
- (NSObject<FlutterMessageCodec>*)createArgsCodec {
60+
return [FlutterStandardMessageCodec sharedInstance];
61+
}
62+
63+
@end

0 commit comments

Comments
 (0)