blob: 61e43c104b57fdea643c9ab1534e9dc870991162 [file] [log] [blame]
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@import Flutter;
@import XCTest;
@import webview_flutter_wkwebview;
@import webview_flutter_wkwebview.Test;
// OCMock library doesn't generate a valid modulemap.
#import <OCMock/OCMock.h>
static bool feq(CGFloat a, CGFloat b) { return fabs(b - a) < FLT_EPSILON; }
@interface FLTWebViewTests : XCTestCase
@property(strong, nonatomic) NSObject<FlutterBinaryMessenger> *mockBinaryMessenger;
@end
@implementation FLTWebViewTests
- (void)setUp {
[super setUp];
self.mockBinaryMessenger = OCMProtocolMock(@protocol(FlutterBinaryMessenger));
}
- (void)testCanInitFLTWebViewController {
FLTWebViewController *controller =
[[FLTWebViewController alloc] initWithFrame:CGRectMake(0, 0, 300, 400)
viewIdentifier:1
arguments:nil
binaryMessenger:self.mockBinaryMessenger];
XCTAssertNotNil(controller);
}
- (void)testCanInitFLTWebViewFactory {
FLTWebViewFactory *factory =
[[FLTWebViewFactory alloc] initWithMessenger:self.mockBinaryMessenger];
XCTAssertNotNil(factory);
}
- (void)webViewContentInsetBehaviorShouldBeNeverOnIOS11 {
if (@available(iOS 11, *)) {
FLTWebViewController *controller =
[[FLTWebViewController alloc] initWithFrame:CGRectMake(0, 0, 300, 400)
viewIdentifier:1
arguments:nil
binaryMessenger:self.mockBinaryMessenger];
UIView *view = controller.view;
XCTAssertTrue([view isKindOfClass:WKWebView.class]);
WKWebView *webView = (WKWebView *)view;
XCTAssertEqual(webView.scrollView.contentInsetAdjustmentBehavior,
UIScrollViewContentInsetAdjustmentNever);
}
}
- (void)testWebViewScrollIndicatorAticautomaticallyAdjustsScrollIndicatorInsetsShouldbeNoOnIOS13 {
if (@available(iOS 13, *)) {
FLTWebViewController *controller =
[[FLTWebViewController alloc] initWithFrame:CGRectMake(0, 0, 300, 400)
viewIdentifier:1
arguments:nil
binaryMessenger:self.mockBinaryMessenger];
UIView *view = controller.view;
XCTAssertTrue([view isKindOfClass:WKWebView.class]);
WKWebView *webView = (WKWebView *)view;
XCTAssertFalse(webView.scrollView.automaticallyAdjustsScrollIndicatorInsets);
}
}
- (void)testContentInsetsSumAlwaysZeroAfterSetFrame {
FLTWKWebView *webView = [[FLTWKWebView alloc] initWithFrame:CGRectMake(0, 0, 300, 400)];
webView.scrollView.contentInset = UIEdgeInsetsMake(0, 0, 300, 0);
XCTAssertFalse(UIEdgeInsetsEqualToEdgeInsets(webView.scrollView.contentInset, UIEdgeInsetsZero));
webView.frame = CGRectMake(0, 0, 300, 200);
XCTAssertTrue(UIEdgeInsetsEqualToEdgeInsets(webView.scrollView.contentInset, UIEdgeInsetsZero));
XCTAssertTrue(CGRectEqualToRect(webView.frame, CGRectMake(0, 0, 300, 200)));
if (@available(iOS 11, *)) {
// After iOS 11, we need to make sure the contentInset compensates the adjustedContentInset.
UIScrollView *partialMockScrollView = OCMPartialMock(webView.scrollView);
UIEdgeInsets insetToAdjust = UIEdgeInsetsMake(0, 0, 300, 0);
OCMStub(partialMockScrollView.adjustedContentInset).andReturn(insetToAdjust);
XCTAssertTrue(UIEdgeInsetsEqualToEdgeInsets(webView.scrollView.contentInset, UIEdgeInsetsZero));
webView.frame = CGRectMake(0, 0, 300, 100);
XCTAssertTrue(feq(webView.scrollView.contentInset.bottom, -insetToAdjust.bottom));
XCTAssertTrue(CGRectEqualToRect(webView.frame, CGRectMake(0, 0, 300, 100)));
}
}
- (void)testRunJavascriptFailsForNullString {
// Setup
FLTWebViewController *controller =
[[FLTWebViewController alloc] initWithFrame:CGRectMake(0, 0, 300, 400)
viewIdentifier:1
arguments:nil
binaryMessenger:self.mockBinaryMessenger];
XCTestExpectation *resultExpectation =
[self expectationWithDescription:@"Should return error result over the method channel."];
// Run
[controller onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"runJavascript"
arguments:nil]
result:^(id _Nullable result) {
XCTAssertTrue([result class] == [FlutterError class]);
[resultExpectation fulfill];
}];
// Verify
[self waitForExpectationsWithTimeout:30.0 handler:nil];
}
- (void)testRunJavascriptRunsStringWithSuccessResult {
// Setup
FLTWebViewController *controller =
[[FLTWebViewController alloc] initWithFrame:CGRectMake(0, 0, 300, 400)
viewIdentifier:1
arguments:nil
binaryMessenger:self.mockBinaryMessenger];
XCTestExpectation *resultExpectation =
[self expectationWithDescription:@"Should return successful result over the method channel."];
FLTWKWebView *mockView = OCMClassMock(FLTWKWebView.class);
[OCMStub([mockView evaluateJavaScript:[OCMArg any]
completionHandler:[OCMArg any]]) andDo:^(NSInvocation *invocation) {
// __unsafe_unretained: https://github.com/erikdoe/ocmock/issues/384#issuecomment-589376668
__unsafe_unretained void (^evalResultHandler)(id, NSError *);
[invocation getArgument:&evalResultHandler atIndex:3];
evalResultHandler(@"RESULT", nil);
}];
controller.webView = mockView;
// Run
[controller onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"runJavascript"
arguments:@"Test JavaScript String"]
result:^(id _Nullable result) {
XCTAssertNil(result);
[resultExpectation fulfill];
}];
// Verify
[self waitForExpectationsWithTimeout:30.0 handler:nil];
}
- (void)testRunJavascriptReturnsErrorResultForWKError {
// Setup
FLTWebViewController *controller =
[[FLTWebViewController alloc] initWithFrame:CGRectMake(0, 0, 300, 400)
viewIdentifier:1
arguments:nil
binaryMessenger:self.mockBinaryMessenger];
XCTestExpectation *resultExpectation =
[self expectationWithDescription:@"Should return error result over the method channel."];
NSError *testError =
[NSError errorWithDomain:@""
// Any error code but WKErrorJavascriptResultTypeIsUnsupported
code:WKErrorJavaScriptResultTypeIsUnsupported + 1
userInfo:@{NSLocalizedDescriptionKey : @"Test Error"}];
FLTWKWebView *mockView = OCMClassMock(FLTWKWebView.class);
[OCMStub([mockView evaluateJavaScript:[OCMArg any]
completionHandler:[OCMArg any]]) andDo:^(NSInvocation *invocation) {
// __unsafe_unretained: https://github.com/erikdoe/ocmock/issues/384#issuecomment-589376668
__unsafe_unretained void (^evalResultHandler)(id, NSError *);
[invocation getArgument:&evalResultHandler atIndex:3];
evalResultHandler(nil, testError);
}];
controller.webView = mockView;
// Run
[controller onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"runJavascript"
arguments:@"Test JavaScript String"]
result:^(id _Nullable result) {
XCTAssertTrue([result class] == [FlutterError class]);
[resultExpectation fulfill];
}];
// Verify
[self waitForExpectationsWithTimeout:30.0 handler:nil];
}
- (void)testRunJavascriptReturnsSuccessForWKErrorJavascriptResultTypeIsUnsupported {
// Setup
FLTWebViewController *controller =
[[FLTWebViewController alloc] initWithFrame:CGRectMake(0, 0, 300, 400)
viewIdentifier:1
arguments:nil
binaryMessenger:self.mockBinaryMessenger];
XCTestExpectation *resultExpectation =
[self expectationWithDescription:@"Should return nil result over the method channel."];
NSError *testError = [NSError errorWithDomain:@""
code:WKErrorJavaScriptResultTypeIsUnsupported
userInfo:@{NSLocalizedDescriptionKey : @"Test Error"}];
FLTWKWebView *mockView = OCMClassMock(FLTWKWebView.class);
[OCMStub([mockView evaluateJavaScript:[OCMArg any]
completionHandler:[OCMArg any]]) andDo:^(NSInvocation *invocation) {
// __unsafe_unretained: https://github.com/erikdoe/ocmock/issues/384#issuecomment-589376668
__unsafe_unretained void (^evalResultHandler)(id, NSError *);
[invocation getArgument:&evalResultHandler atIndex:3];
evalResultHandler(nil, testError);
}];
controller.webView = mockView;
// Run
[controller onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"runJavascript"
arguments:@"Test JavaScript String"]
result:^(id _Nullable result) {
XCTAssertNil(result);
[resultExpectation fulfill];
}];
// Verify
[self waitForExpectationsWithTimeout:30.0 handler:nil];
}
- (void)testRunJavascriptReturningResultFailsForNullString {
// Setup
FLTWebViewController *controller =
[[FLTWebViewController alloc] initWithFrame:CGRectMake(0, 0, 300, 400)
viewIdentifier:1
arguments:nil
binaryMessenger:self.mockBinaryMessenger];
XCTestExpectation *resultExpectation =
[self expectationWithDescription:@"Should return error result over the method channel."];
// Run
[controller
onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"runJavascriptReturningResult"
arguments:nil]
result:^(id _Nullable result) {
XCTAssertTrue([result class] == [FlutterError class]);
[resultExpectation fulfill];
}];
// Verify
[self waitForExpectationsWithTimeout:30.0 handler:nil];
}
- (void)testRunJavascriptReturningResultRunsStringWithSuccessResult {
// Setup
FLTWebViewController *controller =
[[FLTWebViewController alloc] initWithFrame:CGRectMake(0, 0, 300, 400)
viewIdentifier:1
arguments:nil
binaryMessenger:self.mockBinaryMessenger];
XCTestExpectation *resultExpectation =
[self expectationWithDescription:@"Should return successful result over the method channel."];
FLTWKWebView *mockView = OCMClassMock(FLTWKWebView.class);
[OCMStub([mockView evaluateJavaScript:[OCMArg any]
completionHandler:[OCMArg any]]) andDo:^(NSInvocation *invocation) {
// __unsafe_unretained: https://github.com/erikdoe/ocmock/issues/384#issuecomment-589376668
__unsafe_unretained void (^evalResultHandler)(id, NSError *);
[invocation getArgument:&evalResultHandler atIndex:3];
evalResultHandler(@"RESULT", nil);
}];
controller.webView = mockView;
// Run
[controller
onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"runJavascriptReturningResult"
arguments:@"Test JavaScript String"]
result:^(id _Nullable result) {
XCTAssertTrue([@"RESULT" isEqualToString:result]);
[resultExpectation fulfill];
}];
// Verify
[self waitForExpectationsWithTimeout:30.0 handler:nil];
}
- (void)testRunJavascriptReturningResultReturnsErrorResultForWKError {
// Setup
FLTWebViewController *controller =
[[FLTWebViewController alloc] initWithFrame:CGRectMake(0, 0, 300, 400)
viewIdentifier:1
arguments:nil
binaryMessenger:self.mockBinaryMessenger];
XCTestExpectation *resultExpectation =
[self expectationWithDescription:@"Should return error result over the method channel."];
NSError *testError = [NSError errorWithDomain:@""
code:5
userInfo:@{NSLocalizedDescriptionKey : @"Test Error"}];
FLTWKWebView *mockView = OCMClassMock(FLTWKWebView.class);
[OCMStub([mockView evaluateJavaScript:[OCMArg any]
completionHandler:[OCMArg any]]) andDo:^(NSInvocation *invocation) {
// __unsafe_unretained: https://github.com/erikdoe/ocmock/issues/384#issuecomment-589376668
__unsafe_unretained void (^evalResultHandler)(id, NSError *);
[invocation getArgument:&evalResultHandler atIndex:3];
evalResultHandler(nil, testError);
}];
controller.webView = mockView;
// Run
[controller
onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"runJavascriptReturningResult"
arguments:@"Test JavaScript String"]
result:^(id _Nullable result) {
XCTAssertTrue([result class] == [FlutterError class]);
[resultExpectation fulfill];
}];
// Verify
[self waitForExpectationsWithTimeout:30.0 handler:nil];
}
- (void)testBuildNSURLRequestReturnsNilForNonDictionaryValue {
// Setup
FLTWebViewController *controller =
[[FLTWebViewController alloc] initWithFrame:CGRectMake(0, 0, 300, 400)
viewIdentifier:1
arguments:nil
binaryMessenger:self.mockBinaryMessenger];
// Run
NSURLRequest *request = [controller buildNSURLRequest:@{@"request" : @"Non Dictionary Value"}];
// Verify
XCTAssertNil(request);
}
- (void)testBuildNSURLRequestReturnsNilForMissingURI {
// Setup
FLTWebViewController *controller =
[[FLTWebViewController alloc] initWithFrame:CGRectMake(0, 0, 300, 400)
viewIdentifier:1
arguments:nil
binaryMessenger:self.mockBinaryMessenger];
// Run
NSURLRequest *request = [controller buildNSURLRequest:@{@"request" : @{}}];
// Verify
XCTAssertNil(request);
}
- (void)testBuildNSURLRequestReturnsNilForInvalidURI {
// Setup
FLTWebViewController *controller =
[[FLTWebViewController alloc] initWithFrame:CGRectMake(0, 0, 300, 400)
viewIdentifier:1
arguments:nil
binaryMessenger:self.mockBinaryMessenger];
// Run
NSDictionary *requestData = @{@"uri" : @"invalid uri"};
NSURLRequest *request = [controller buildNSURLRequest:@{@"request" : requestData}];
// Verify
XCTAssertNil(request);
}
- (void)testBuildNSURLRequestBuildsNSMutableURLRequestWithOptionalParameters {
// Setup
FLTWebViewController *controller =
[[FLTWebViewController alloc] initWithFrame:CGRectMake(0, 0, 300, 400)
viewIdentifier:1
arguments:nil
binaryMessenger:self.mockBinaryMessenger];
// Run
NSDictionary *requestData = @{
@"uri" : @"https://flutter.dev",
@"method" : @"POST",
@"headers" : @{@"Foo" : @"Bar"},
@"body" : [FlutterStandardTypedData
typedDataWithBytes:[@"Test Data" dataUsingEncoding:NSUTF8StringEncoding]],
};
NSURLRequest *request = [controller buildNSURLRequest:@{@"request" : requestData}];
// Verify
XCTAssertNotNil(request);
XCTAssertEqualObjects(request.URL.absoluteString, @"https://flutter.dev");
XCTAssertEqualObjects(request.HTTPMethod, @"POST");
XCTAssertEqualObjects(request.allHTTPHeaderFields, @{@"Foo" : @"Bar"});
XCTAssertEqualObjects(request.HTTPBody, [@"Test Data" dataUsingEncoding:NSUTF8StringEncoding]);
}
- (void)testBuildNSURLRequestBuildsNSMutableURLRequestWithoutOptionalParameters {
// Setup
FLTWebViewController *controller =
[[FLTWebViewController alloc] initWithFrame:CGRectMake(0, 0, 300, 400)
viewIdentifier:1
arguments:nil
binaryMessenger:self.mockBinaryMessenger];
// Run
NSDictionary *requestData = @{
@"uri" : @"https://flutter.dev",
};
NSURLRequest *request = [controller buildNSURLRequest:@{@"request" : requestData}];
// Verify
XCTAssertNotNil(request);
XCTAssertEqualObjects(request.URL.absoluteString, @"https://flutter.dev");
XCTAssertEqualObjects(request.HTTPMethod, @"GET");
XCTAssertNil(request.allHTTPHeaderFields);
XCTAssertNil(request.HTTPBody);
}
- (void)testOnLoadUrlReturnsErrorResultForInvalidRequest {
// Setup
FLTWebViewController *controller =
[[FLTWebViewController alloc] initWithFrame:CGRectMake(0, 0, 300, 400)
viewIdentifier:1
arguments:nil
binaryMessenger:self.mockBinaryMessenger];
XCTestExpectation *resultExpectation =
[self expectationWithDescription:@"Should return error result when request cannot be built"];
// Run
FlutterMethodCall *methodCall = [FlutterMethodCall methodCallWithMethodName:@"loadUrl"
arguments:@{}];
[controller onLoadUrl:methodCall
result:^(id _Nullable result) {
XCTAssertTrue([result class] == [FlutterError class]);
[resultExpectation fulfill];
}];
// Verify
[self waitForExpectationsWithTimeout:30.0 handler:nil];
}
- (void)testOnLoadUrlLoadsRequestWithSuccessResult {
// Setup
FLTWebViewController *controller =
[[FLTWebViewController alloc] initWithFrame:CGRectMake(0, 0, 300, 400)
viewIdentifier:1
arguments:nil
binaryMessenger:self.mockBinaryMessenger];
XCTestExpectation *resultExpectation = [self expectationWithDescription:@"Should return nil"];
FLTWKWebView *mockView = OCMClassMock(FLTWKWebView.class);
controller.webView = mockView;
// Run
FlutterMethodCall *methodCall =
[FlutterMethodCall methodCallWithMethodName:@"loadUrl"
arguments:@{@"url" : @"https://flutter.dev/"}];
[controller onLoadUrl:methodCall
result:^(id _Nullable result) {
XCTAssertNil(result);
[resultExpectation fulfill];
}];
// Verify
OCMVerify([mockView loadRequest:[OCMArg any]]);
[self waitForExpectationsWithTimeout:30.0 handler:nil];
}
- (void)testOnLoadRequestReturnsErroResultForInvalidRequest {
// Setup
FLTWebViewController *controller =
[[FLTWebViewController alloc] initWithFrame:CGRectMake(0, 0, 300, 400)
viewIdentifier:1
arguments:nil
binaryMessenger:self.mockBinaryMessenger];
XCTestExpectation *resultExpectation =
[self expectationWithDescription:@"Should return error result when request cannot be built"];
// Run
FlutterMethodCall *methodCall = [FlutterMethodCall methodCallWithMethodName:@"loadRequest"
arguments:@{}];
[controller onLoadRequest:methodCall
result:^(id _Nullable result) {
XCTAssertTrue([result class] == [FlutterError class]);
[resultExpectation fulfill];
}];
// Verify
[self waitForExpectationsWithTimeout:30.0 handler:nil];
}
- (void)testOnLoadRequestLoadsRequestWithSuccessResult {
// Setup
FLTWebViewController *controller =
[[FLTWebViewController alloc] initWithFrame:CGRectMake(0, 0, 300, 400)
viewIdentifier:1
arguments:nil
binaryMessenger:self.mockBinaryMessenger];
XCTestExpectation *resultExpectation = [self expectationWithDescription:@"Should return nil"];
FLTWKWebView *mockView = OCMClassMock(FLTWKWebView.class);
controller.webView = mockView;
// Run
FlutterMethodCall *methodCall = [FlutterMethodCall
methodCallWithMethodName:@"loadRequest"
arguments:@{@"request" : @{@"uri" : @"https://flutter.dev/"}}];
[controller onLoadRequest:methodCall
result:^(id _Nullable result) {
XCTAssertNil(result);
[resultExpectation fulfill];
}];
// Verify
OCMVerify([mockView loadRequest:[OCMArg any]]);
[self waitForExpectationsWithTimeout:30.0 handler:nil];
}
@end