updated tests

This commit is contained in:
Lorenzo Pichilli 2022-04-28 01:10:20 +02:00
parent 55a2a41a04
commit 24e452f29c
15 changed files with 1349 additions and 1137 deletions

View File

@ -7,6 +7,10 @@
- Added support for `onPermissionRequest` event on iOS 15.0+
- Updated `getMetaThemeColor` on iOS 15.0+
### BREAKING CHANGES
- On Android, the `InAppWebView` widget uses hybrid composition by default (`useHybridComposition: true`).
## 5.4.3
- Added Bitwise OR operator support for `AndroidActionModeMenuItem` class

View File

@ -3,4 +3,7 @@ final TEST_CROSS_PLATFORM_URL_1 = Uri.parse('https://flutter.dev');
final TEST_CROSS_PLATFORM_URL_2 = Uri.parse('https://www.bing.com/');
final TEST_URL_1 = Uri.parse('https://github.com/flutter');
final TEST_URL_2 = Uri.parse('https://www.google.com/');
final TEST_WEB_PLATFORM_URL_1 = Uri.parse(Uri.base.toString().replaceFirst("/#/", "/") + 'page.html');
final TEST_URL_3 = Uri.parse('https://github.com/pichillilorenzo/flutter_inappwebview');
final TEST_URL_4 = Uri.parse('https://www.youtube.com/');
final TEST_WEB_PLATFORM_URL_1 = Uri.parse(Uri.base.toString().replaceFirst("/#/", "/") + 'page.html');
final TEST_NOT_A_WEBSITE_URL = Uri.parse('https://www.notawebsite..com');

View File

@ -0,0 +1,125 @@
import 'dart:async';
import 'dart:convert';
import 'dart:typed_data';
import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
import 'package:flutter_test/flutter_test.dart';
import '../constants.dart';
void audioPlaybackPolicy() {
final shouldSkip = kIsWeb || ![
TargetPlatform.android,
TargetPlatform.iOS,
TargetPlatform.macOS,
].contains(defaultTargetPlatform);
group('Audio playback policy', () {
String audioTestBase64 = "";
setUpAll(() async {
final ByteData audioData =
await rootBundle.load('test_assets/sample_audio.ogg');
final String base64AudioData =
base64Encode(Uint8List.view(audioData.buffer));
final String audioTest = '''
<!DOCTYPE html><html>
<head><title>Audio auto play</title>
<script type="text/javascript">
function play() {
var audio = document.getElementById("audio");
audio.play();
}
function isPaused() {
var audio = document.getElementById("audio");
return audio.paused;
}
</script>
</head>
<body onload="play();">
<audio controls id="audio">
<source src="data:audio/ogg;charset=utf-8;base64,$base64AudioData">
</audio>
</body>
</html>
''';
audioTestBase64 = base64Encode(const Utf8Encoder().convert(audioTest));
});
testWidgets('Auto media playback', (WidgetTester tester) async {
Completer<InAppWebViewController> controllerCompleter =
Completer<InAppWebViewController>();
Completer<void> pageStarted = Completer<void>();
Completer<void> pageLoaded = Completer<void>();
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
child: InAppWebView(
key: GlobalKey(),
initialUrlRequest: URLRequest(
url: Uri.parse(
'data:text/html;charset=utf-8;base64,$audioTestBase64')),
onWebViewCreated: (controller) {
controllerCompleter.complete(controller);
},
initialSettings: InAppWebViewSettings(
javaScriptEnabled: true,
mediaPlaybackRequiresUserGesture: false),
onLoadStart: (controller, url) {
pageStarted.complete();
},
onLoadStop: (controller, url) {
pageLoaded.complete();
},
),
),
);
InAppWebViewController controller = await controllerCompleter.future;
await pageStarted.future;
await pageLoaded.future;
bool isPaused =
await controller.evaluateJavascript(source: 'isPaused();');
expect(isPaused, false);
controllerCompleter = Completer<InAppWebViewController>();
pageStarted = Completer<void>();
pageLoaded = Completer<void>();
// We change the key to re-create a new webview as we change the mediaPlaybackRequiresUserGesture
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
child: InAppWebView(
key: GlobalKey(),
initialUrlRequest: URLRequest(
url: Uri.parse(
'data:text/html;charset=utf-8;base64,$audioTestBase64')),
onWebViewCreated: (controller) {
controllerCompleter.complete(controller);
},
initialSettings: InAppWebViewSettings(
javaScriptEnabled: true,
mediaPlaybackRequiresUserGesture: true),
onLoadStart: (controller, url) {
pageStarted.complete();
},
onLoadStop: (controller, url) {
pageLoaded.complete();
},
),
),
);
controller = await controllerCompleter.future;
await pageStarted.future;
await pageLoaded.future;
isPaused = await controller.evaluateJavascript(source: 'isPaused();');
expect(isPaused, true);
});
}, skip: shouldSkip);
}

View File

@ -0,0 +1,67 @@
import 'dart:async';
import 'dart:convert';
import 'package:flutter/foundation.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
import 'package:flutter_test/flutter_test.dart';
import '../constants.dart';
void getTitle() {
final shouldSkip = !kIsWeb || ![
TargetPlatform.android,
TargetPlatform.iOS,
TargetPlatform.macOS,
].contains(defaultTargetPlatform);
final String getTitleTest = '''
<!DOCTYPE html><html>
<head><title>Some title</title>
</head>
<body>
</body>
</html>
''';
final String getTitleTestBase64 =
base64Encode(const Utf8Encoder().convert(getTitleTest));
var url = !kIsWeb ? Uri.parse(
'data:text/html;charset=utf-8;base64,$getTitleTestBase64') :
TEST_WEB_PLATFORM_URL_1;
var expectedValue = !kIsWeb ? 'Some title' : 'page';
testWidgets('getTitle', (WidgetTester tester) async {
final Completer<void> pageStarted = Completer<void>();
final Completer<void> pageLoaded = Completer<void>();
final Completer controllerCompleter = Completer<InAppWebViewController>();
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
child: InAppWebView(
initialUrlRequest: URLRequest(
url: url),
onWebViewCreated: (controller) {
controllerCompleter.complete(controller);
},
onLoadStart: (controller, url) {
pageStarted.complete();
},
onLoadStop: (controller, url) {
pageLoaded.complete();
},
),
),
);
final InAppWebViewController controller =
await controllerCompleter.future;
await pageStarted.future;
await pageLoaded.future;
final String? title = await controller.getTitle();
expect(title, expectedValue);
}, skip: shouldSkip);
}

View File

@ -0,0 +1,80 @@
import 'dart:async';
import 'package:flutter/foundation.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
import 'package:flutter_test/flutter_test.dart';
import '../util.dart';
void javascriptHandler() {
final shouldSkip = kIsWeb || ![
TargetPlatform.android,
TargetPlatform.iOS,
TargetPlatform.macOS,
].contains(defaultTargetPlatform);
testWidgets('JavaScript Handler', (WidgetTester tester) async {
final Completer controllerCompleter = Completer<InAppWebViewController>();
final Completer<void> pageStarted = Completer<void>();
final Completer<void> pageLoaded = Completer<void>();
final Completer<void> handlerFoo = Completer<void>();
final Completer<void> handlerFooWithArgs = Completer<void>();
final List<dynamic> messagesReceived = <dynamic>[];
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
child: InAppWebView(
key: GlobalKey(),
initialFile:
"test_assets/in_app_webview_javascript_handler_test.html",
onWebViewCreated: (controller) {
controllerCompleter.complete(controller);
controller.addJavaScriptHandler(
handlerName: 'handlerFoo',
callback: (args) {
handlerFoo.complete();
return Foo(bar: 'bar_value', baz: 'baz_value');
});
controller.addJavaScriptHandler(
handlerName: 'handlerFooWithArgs',
callback: (args) {
messagesReceived.add(args[0] as int);
messagesReceived.add(args[1] as bool);
messagesReceived.add(args[2] as List<dynamic>?);
messagesReceived.add(args[3]?.cast<String, String>()
as Map<String, String>?);
messagesReceived.add(args[4]?.cast<String, String>()
as Map<String, String>?);
handlerFooWithArgs.complete();
});
},
initialSettings: InAppWebViewSettings(javaScriptEnabled: true),
onLoadStart: (controller, url) {
pageStarted.complete();
},
onLoadStop: (controller, url) {
pageLoaded.complete();
},
),
),
);
await pageStarted.future;
await pageLoaded.future;
await handlerFoo.future;
await handlerFooWithArgs.future;
expect(messagesReceived[0], 1);
expect(messagesReceived[1], true);
expect(
listEquals(messagesReceived[2] as List<dynamic>?, ["bar", 5]), true);
expect(mapEquals(messagesReceived[3], {"foo": "baz"}), true);
expect(
mapEquals(
messagesReceived[4], {"bar": "bar_value", "baz": "baz_value"}),
true);
}, skip: shouldSkip);
}

View File

@ -0,0 +1,150 @@
import 'dart:async';
import 'dart:io';
import 'package:flutter/foundation.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:path_provider/path_provider.dart';
void loadFileUrl() {
final shouldSkip = kIsWeb ||
![
TargetPlatform.iOS,
TargetPlatform.macOS,
].contains(defaultTargetPlatform);
group('load file URL', () {
late Directory appSupportDir;
late File fileHtml;
late File fileJs;
setUpAll(() async {
appSupportDir = (await getApplicationSupportDirectory());
final Directory htmlFolder = Directory('${appSupportDir.path}/html/');
if (!await htmlFolder.exists()) {
await htmlFolder.create(recursive: true);
}
final Directory jsFolder = Directory('${appSupportDir.path}/js/');
if (!await jsFolder.exists()) {
await jsFolder.create(recursive: true);
}
var html = """
<!DOCTYPE html><html>
<head>
<title>file scheme</title>
</head>
<body>
<script src="../js/main.js"></script>
</body>
</html>
""";
fileHtml = File(htmlFolder.path + "index.html");
fileHtml.writeAsStringSync(html);
var js = """
console.log('message');
""";
fileJs = File(jsFolder.path + "main.js");
fileJs.writeAsStringSync(js);
});
testWidgets('initialUrl with file:// scheme and allowingReadAccessTo',
(WidgetTester tester) async {
final Completer<ConsoleMessage?> consoleMessageShouldNotComplete =
Completer<ConsoleMessage?>();
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
child: InAppWebView(
key: GlobalKey(),
initialUrlRequest:
URLRequest(url: Uri.parse('file://${fileHtml.path}')),
onConsoleMessage: (controller, consoleMessage) {
consoleMessageShouldNotComplete.complete(consoleMessage);
},
),
),
);
var result = await consoleMessageShouldNotComplete.future
.timeout(const Duration(seconds: 2), onTimeout: () => null);
expect(result, null);
final Completer<ConsoleMessage> consoleMessageCompleter =
Completer<ConsoleMessage>();
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
child: InAppWebView(
key: GlobalKey(),
initialUrlRequest:
URLRequest(url: Uri.parse('file://${fileHtml.path}')),
initialSettings: InAppWebViewSettings(
allowingReadAccessTo:
Uri.parse('file://${appSupportDir.path}/')),
onConsoleMessage: (controller, consoleMessage) {
consoleMessageCompleter.complete(consoleMessage);
},
),
),
);
final ConsoleMessage consoleMessage =
await consoleMessageCompleter.future;
expect(consoleMessage.messageLevel, ConsoleMessageLevel.LOG);
expect(consoleMessage.message, 'message');
});
testWidgets('loadUrl with file:// scheme and allowingReadAccessTo argument',
(WidgetTester tester) async {
final Completer<ConsoleMessage?> consoleMessageShouldNotComplete =
Completer<ConsoleMessage?>();
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
child: InAppWebView(
key: GlobalKey(),
onWebViewCreated: (controller) {
controller.loadUrl(
urlRequest:
URLRequest(url: Uri.parse('file://${fileHtml.path}')));
},
onConsoleMessage: (controller, consoleMessage) {
consoleMessageShouldNotComplete.complete(consoleMessage);
},
),
),
);
var result = await consoleMessageShouldNotComplete.future
.timeout(const Duration(seconds: 2), onTimeout: () => null);
expect(result, null);
final Completer<ConsoleMessage> consoleMessageCompleter =
Completer<ConsoleMessage>();
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
child: InAppWebView(
key: GlobalKey(),
onWebViewCreated: (controller) {
controller.loadUrl(
urlRequest:
URLRequest(url: Uri.parse('file://${fileHtml.path}')),
allowingReadAccessTo:
Uri.parse('file://${appSupportDir.path}/'));
},
onConsoleMessage: (controller, consoleMessage) {
consoleMessageCompleter.complete(consoleMessage);
},
),
),
);
final ConsoleMessage consoleMessage =
await consoleMessageCompleter.future;
expect(consoleMessage.messageLevel, ConsoleMessageLevel.LOG);
expect(consoleMessage.message, 'message');
});
}, skip: shouldSkip);
}

View File

@ -1,9 +1,19 @@
import 'package:flutter_test/flutter_test.dart';
import 'audio_playback_policy.dart';
import 'get_title.dart';
import 'initial_url_request.dart';
import 'set_get_settings.dart';
import 'javascript_code_evaluation.dart';
import 'javascript_handler.dart';
import 'load_file_url.dart';
import 'load_url.dart';
import 'on_load_error.dart';
import 'programmatic_scroll.dart';
import 'resize_webview.dart';
import 'set_custom_useragent.dart';
import 'set_get_settings.dart';
import 'should_override_url_loading.dart';
import 'video_playback_policy.dart';
void main() {
group('InAppWebView', () {
@ -11,5 +21,15 @@ void main() {
setGetSettings();
javascriptCodeEvaluation();
loadUrl();
loadFileUrl();
javascriptHandler();
resizeWebView();
setCustomUserAgent();
videoPlaybackPolicy();
audioPlaybackPolicy();
getTitle();
programmaticScroll();
shouldOverrideUrlLoading();
onLoadError();
});
}

View File

@ -0,0 +1,77 @@
import 'dart:async';
import 'package:flutter/foundation.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
import 'package:flutter_test/flutter_test.dart';
import '../constants.dart';
void onLoadError() {
final shouldSkip = kIsWeb ||
![
TargetPlatform.android,
TargetPlatform.iOS,
TargetPlatform.macOS,
].contains(defaultTargetPlatform);
group('onLoadError', () {
testWidgets('invalid url', (WidgetTester tester) async {
final Completer<String> errorUrlCompleter = Completer<String>();
final Completer<int> errorCodeCompleter = Completer<int>();
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
child: InAppWebView(
key: GlobalKey(),
initialUrlRequest: URLRequest(url: TEST_NOT_A_WEBSITE_URL),
onLoadError: (controller, url, code, message) {
errorUrlCompleter.complete(url.toString());
errorCodeCompleter.complete(code);
},
),
),
);
final String url = await errorUrlCompleter.future;
final int code = await errorCodeCompleter.future;
if (defaultTargetPlatform == TargetPlatform.android) {
expect(code, -2);
} else if (defaultTargetPlatform == TargetPlatform.iOS ||
defaultTargetPlatform == TargetPlatform.macOS) {
expect(code, -1003);
}
expect(url, TEST_NOT_A_WEBSITE_URL.toString());
});
testWidgets('event is not called with valid url',
(WidgetTester tester) async {
final Completer<String> errorUrlCompleter = Completer<String>();
final Completer<int> errorCodeCompleter = Completer<int>();
final Completer<String> errorMessageCompleter = Completer<String>();
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
child: InAppWebView(
key: GlobalKey(),
initialUrlRequest: URLRequest(
url: Uri.parse(
'data:text/html;charset=utf-8;base64,PCFET0NUWVBFIGh0bWw+')),
onLoadError: (controller, url, code, message) {
errorUrlCompleter.complete(url.toString());
errorCodeCompleter.complete(code);
errorMessageCompleter.complete(message);
},
),
),
);
expect(errorUrlCompleter.future, doesNotComplete);
expect(errorCodeCompleter.future, doesNotComplete);
expect(errorMessageCompleter.future, doesNotComplete);
});
}, skip: shouldSkip);
}

View File

@ -0,0 +1,176 @@
import 'dart:async';
import 'dart:convert';
import 'package:flutter/foundation.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
import 'package:flutter_test/flutter_test.dart';
import '../constants.dart';
void programmaticScroll() {
final shouldSkip = !kIsWeb || ![
TargetPlatform.android,
TargetPlatform.iOS,
TargetPlatform.macOS,
].contains(defaultTargetPlatform);
group('Programmatic Scroll', () {
final shouldSkipTest1 = !kIsWeb || ![
TargetPlatform.android,
TargetPlatform.iOS,
TargetPlatform.macOS,
].contains(defaultTargetPlatform);
testWidgets('set and get scroll position', (WidgetTester tester) async {
final String scrollTestPage = '''
<!DOCTYPE html>
<html>
<head>
<style>
body {
height: 100%;
width: 100%;
}
#container{
width:5000px;
height:5000px;
}
</style>
</head>
<body>
<div id="container"/>
</body>
</html>
''';
final String scrollTestPageBase64 =
base64Encode(const Utf8Encoder().convert(scrollTestPage));
var url = !kIsWeb ? Uri.parse(
'data:text/html;charset=utf-8;base64,$scrollTestPageBase64') :
TEST_WEB_PLATFORM_URL_1;
final Completer<void> pageLoaded = Completer<void>();
final Completer controllerCompleter =
Completer<InAppWebViewController>();
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
child: InAppWebView(
initialUrlRequest: URLRequest(
url: url),
onWebViewCreated: (controller) {
controllerCompleter.complete(controller);
},
onLoadStop: (controller, url) {
pageLoaded.complete();
},
),
),
);
final InAppWebViewController controller =
await controllerCompleter.future;
await pageLoaded.future;
await controller.scrollTo(x: 0, y: 0);
await tester.pumpAndSettle(Duration(seconds: 3));
// Check scrollTo()
const int X_SCROLL = 123;
const int Y_SCROLL = 321;
await controller.scrollTo(x: X_SCROLL, y: Y_SCROLL);
await tester.pumpAndSettle(Duration(seconds: 2));
int? scrollPosX = await controller.getScrollX();
int? scrollPosY = await controller.getScrollY();
expect(scrollPosX, X_SCROLL);
expect(scrollPosY, Y_SCROLL);
// Check scrollBy() (on top of scrollTo())
await controller.scrollBy(x: X_SCROLL, y: Y_SCROLL);
await tester.pumpAndSettle(Duration(seconds: 2));
scrollPosX = await controller.getScrollX();
scrollPosY = await controller.getScrollY();
expect(scrollPosX, X_SCROLL * 2);
expect(scrollPosY, Y_SCROLL * 2);
}, skip: shouldSkipTest1);
testWidgets('set and get scroll position on Android without Hybrid Composition', (WidgetTester tester) async {
final String scrollTestPage = '''
<!DOCTYPE html>
<html>
<head>
<style>
body {
height: 100%;
width: 100%;
}
#container{
width:5000px;
height:5000px;
}
</style>
</head>
<body>
<div id="container"/>
</body>
</html>
''';
final String scrollTestPageBase64 =
base64Encode(const Utf8Encoder().convert(scrollTestPage));
final Completer<void> pageLoaded = Completer<void>();
final Completer controllerCompleter =
Completer<InAppWebViewController>();
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
child: InAppWebView(
initialUrlRequest: URLRequest(
url: Uri.parse(
'data:text/html;charset=utf-8;base64,$scrollTestPageBase64')),
onWebViewCreated: (controller) {
controllerCompleter.complete(controller);
},
initialSettings: InAppWebViewSettings(
useHybridComposition: false),
onLoadStop: (controller, url) {
pageLoaded.complete();
},
),
),
);
final InAppWebViewController controller =
await controllerCompleter.future;
await pageLoaded.future;
await controller.scrollTo(x: 0, y: 0);
await tester.pumpAndSettle(Duration(seconds: 3));
// Check scrollTo()
const int X_SCROLL = 123;
const int Y_SCROLL = 321;
await controller.scrollTo(x: X_SCROLL, y: Y_SCROLL);
await tester.pumpAndSettle(Duration(seconds: 2));
int? scrollPosX = await controller.getScrollX();
int? scrollPosY = await controller.getScrollY();
expect(scrollPosX, X_SCROLL);
expect(scrollPosY, Y_SCROLL);
// Check scrollBy() (on top of scrollTo())
await controller.scrollBy(x: X_SCROLL, y: Y_SCROLL);
await tester.pumpAndSettle(Duration(seconds: 2));
scrollPosX = await controller.getScrollX();
scrollPosY = await controller.getScrollY();
expect(scrollPosX, X_SCROLL * 2);
expect(scrollPosY, Y_SCROLL * 2);
}, skip: defaultTargetPlatform != TargetPlatform.android);
}, skip: shouldSkip);
}

View File

@ -0,0 +1,104 @@
import 'dart:async';
import 'dart:convert';
import 'package:flutter/foundation.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
import 'package:flutter_test/flutter_test.dart';
import '../constants.dart';
void resizeWebView() {
final shouldSkip = kIsWeb || ![
TargetPlatform.android,
TargetPlatform.iOS,
TargetPlatform.macOS,
].contains(defaultTargetPlatform);
testWidgets('resize webview', (WidgetTester tester) async {
final String resizeTest = '''
<!DOCTYPE html><html>
<head><title>Resize test</title>
<script type="text/javascript">
function onResize() {
window.flutter_inappwebview.callHandler('resize');
}
function onLoad() {
window.onresize = onResize;
}
</script>
</head>
<body onload="onLoad();" bgColor="blue">
</body>
</html>
''';
final String resizeTestBase64 =
base64Encode(const Utf8Encoder().convert(resizeTest));
final Completer<void> resizeCompleter = Completer<void>();
final Completer<void> pageStarted = Completer<void>();
final Completer<void> pageLoaded = Completer<void>();
final Completer controllerCompleter = Completer<InAppWebViewController>();
final GlobalKey key = GlobalKey();
final InAppWebView webView = InAppWebView(
key: key,
initialUrlRequest: URLRequest(
url: Uri.parse(
'data:text/html;charset=utf-8;base64,$resizeTestBase64')),
onWebViewCreated: (controller) {
controllerCompleter.complete(controller);
controller.addJavaScriptHandler(
handlerName: 'resize',
callback: (args) {
resizeCompleter.complete(true);
});
},
onLoadStart: (controller, url) {
pageStarted.complete();
},
onLoadStop: (controller, url) {
pageLoaded.complete();
},
initialSettings: InAppWebViewSettings(javaScriptEnabled: true),
);
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
child: Column(
children: <Widget>[
SizedBox(
width: 200,
height: 200,
child: webView,
),
],
),
),
);
await controllerCompleter.future;
await pageStarted.future;
await pageLoaded.future;
expect(resizeCompleter.isCompleted, false);
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
child: Column(
children: <Widget>[
SizedBox(
width: 400,
height: 400,
child: webView,
),
],
),
),
);
await resizeCompleter.future;
}, skip: shouldSkip);
}

View File

@ -0,0 +1,49 @@
import 'dart:async';
import 'package:flutter/foundation.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
import 'package:flutter_test/flutter_test.dart';
import '../constants.dart';
void setCustomUserAgent() {
final shouldSkip = kIsWeb ||
![
TargetPlatform.android,
TargetPlatform.iOS,
TargetPlatform.macOS,
].contains(defaultTargetPlatform);
testWidgets('set custom userAgent', (WidgetTester tester) async {
final Completer controllerCompleter1 = Completer<InAppWebViewController>();
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
child: InAppWebView(
initialUrlRequest: URLRequest(url: TEST_URL_ABOUT_BLANK),
initialSettings: InAppWebViewSettings(
javaScriptEnabled: true,
userAgent: 'Custom_User_Agent1',
),
onWebViewCreated: (controller) {
controllerCompleter1.complete(controller);
},
),
),
);
InAppWebViewController controller1 = await controllerCompleter1.future;
final String customUserAgent1 =
await controller1.evaluateJavascript(source: 'navigator.userAgent;');
expect(customUserAgent1, 'Custom_User_Agent1');
await controller1.setSettings(
settings: InAppWebViewSettings(
userAgent: 'Custom_User_Agent2',
));
final String customUserAgent2 =
await controller1.evaluateJavascript(source: 'navigator.userAgent;');
expect(customUserAgent2, 'Custom_User_Agent2');
}, skip: shouldSkip);
}

View File

@ -0,0 +1,250 @@
import 'dart:async';
import 'dart:convert';
import 'package:flutter/foundation.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
import 'package:flutter_test/flutter_test.dart';
import '../constants.dart';
void shouldOverrideUrlLoading() {
final shouldSkip = kIsWeb ||
![
TargetPlatform.android,
TargetPlatform.iOS,
TargetPlatform.macOS,
].contains(defaultTargetPlatform);
group('shouldOverrideUrlLoading', () {
final String page =
'''<!DOCTYPE html><head></head><body><a id="link" href="$TEST_URL_3">flutter_inappwebview</a></body></html>''';
final String pageEncoded = 'data:text/html;charset=utf-8;base64,' +
base64Encode(const Utf8Encoder().convert(page));
final shouldSkipTest1 = kIsWeb ||
![
TargetPlatform.android,
TargetPlatform.iOS,
TargetPlatform.macOS,
].contains(defaultTargetPlatform);
testWidgets('can allow requests', (WidgetTester tester) async {
final Completer controllerCompleter = Completer<InAppWebViewController>();
final StreamController<String> pageLoads =
StreamController<String>.broadcast();
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
child: InAppWebView(
key: GlobalKey(),
initialUrlRequest: URLRequest(url: Uri.parse(pageEncoded)),
onWebViewCreated: (controller) {
controllerCompleter.complete(controller);
},
initialSettings: InAppWebViewSettings(
javaScriptEnabled: true,
useShouldOverrideUrlLoading: true,
),
shouldOverrideUrlLoading: (controller, navigationAction) async {
return (navigationAction.request.url!.host
.contains(TEST_URL_4.host.replaceAll("www.", "")))
? NavigationActionPolicy.CANCEL
: NavigationActionPolicy.ALLOW;
},
onLoadStop: (controller, url) {
pageLoads.add(url!.toString());
},
),
),
);
await pageLoads.stream.first; // Wait for initial page load.
final InAppWebViewController controller =
await controllerCompleter.future;
await controller.evaluateJavascript(
source: 'location.href = "$TEST_URL_2"');
await pageLoads.stream.first; // Wait for the next page load.
final String? currentUrl = (await controller.getUrl())?.toString();
expect(currentUrl, TEST_URL_2.toString());
pageLoads.close();
}, skip: shouldSkipTest1);
final shouldSkipTest2 = kIsWeb ||
![
TargetPlatform.iOS,
TargetPlatform.macOS,
].contains(defaultTargetPlatform);
testWidgets(
'allow requests on iOS only if navigationType == NavigationType.LINK_ACTIVATED',
(WidgetTester tester) async {
final Completer controllerCompleter = Completer<InAppWebViewController>();
final StreamController<String> pageLoads =
StreamController<String>.broadcast();
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
child: InAppWebView(
key: GlobalKey(),
initialUrlRequest: URLRequest(url: Uri.parse(pageEncoded)),
onWebViewCreated: (controller) {
controllerCompleter.complete(controller);
},
initialSettings: InAppWebViewSettings(
javaScriptEnabled: true,
useShouldOverrideUrlLoading: true,
),
shouldOverrideUrlLoading: (controller, navigationAction) async {
var isFirstLoad = navigationAction.request.url!.scheme == "data";
return (isFirstLoad ||
navigationAction.navigationType ==
NavigationType.LINK_ACTIVATED)
? NavigationActionPolicy.ALLOW
: NavigationActionPolicy.CANCEL;
},
onLoadStop: (controller, url) {
pageLoads.add(url!.toString());
},
),
),
);
await pageLoads.stream.first; // Wait for initial page load.
final InAppWebViewController controller =
await controllerCompleter.future;
await controller.evaluateJavascript(
source: 'location.href = "$TEST_URL_2"');
// There should never be any second page load, since our new URL is
// blocked. Still wait for a potential page change for some time in order
// to give the test a chance to fail.
await pageLoads.stream
// ignore: unnecessary_cast
.map((event) => event as String?)
.first
.timeout(const Duration(milliseconds: 500), onTimeout: () => null);
String? currentUrl = (await controller.getUrl())?.toString();
expect(currentUrl, isNot(TEST_URL_2.toString()));
await controller.evaluateJavascript(
source: 'document.querySelector("#link").click();');
await pageLoads.stream.first; // Wait for the next page load.
currentUrl = (await controller.getUrl())?.toString();
expect(currentUrl, TEST_URL_3.toString());
pageLoads.close();
}, skip: shouldSkipTest2);
final shouldSkipTest3 = kIsWeb ||
![
TargetPlatform.android,
TargetPlatform.iOS,
TargetPlatform.macOS,
].contains(defaultTargetPlatform);
testWidgets('can block requests', (WidgetTester tester) async {
final Completer controllerCompleter = Completer<InAppWebViewController>();
final StreamController<String> pageLoads =
StreamController<String>.broadcast();
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
child: InAppWebView(
key: GlobalKey(),
initialUrlRequest: URLRequest(url: Uri.parse(pageEncoded)),
onWebViewCreated: (controller) {
controllerCompleter.complete(controller);
},
initialSettings: InAppWebViewSettings(
javaScriptEnabled: true,
useShouldOverrideUrlLoading: true,
),
shouldOverrideUrlLoading: (controller, navigationAction) async {
return (navigationAction.request.url!.host
.contains(TEST_URL_4.host.replaceAll("www.", "")))
? NavigationActionPolicy.CANCEL
: NavigationActionPolicy.ALLOW;
},
onLoadStop: (controller, url) {
pageLoads.add(url!.toString());
},
),
),
);
await pageLoads.stream.first; // Wait for initial page load.
final InAppWebViewController controller =
await controllerCompleter.future;
await controller.evaluateJavascript(
source: 'location.href = "$TEST_URL_4"');
// There should never be any second page load, since our new URL is
// blocked. Still wait for a potential page change for some time in order
// to give the test a chance to fail.
await pageLoads.stream
// ignore: unnecessary_cast
.map((event) => event as String?)
.first
.timeout(const Duration(milliseconds: 500), onTimeout: () => null);
final String? currentUrl = (await controller.getUrl())?.toString();
expect(
currentUrl, isNot(contains(TEST_URL_4.host.replaceAll("www.", ""))));
pageLoads.close();
}, skip: shouldSkipTest3);
final shouldSkipTest4 = kIsWeb ||
![
TargetPlatform.android,
TargetPlatform.iOS,
TargetPlatform.macOS,
].contains(defaultTargetPlatform);
testWidgets('supports asynchronous decisions', (WidgetTester tester) async {
final Completer controllerCompleter = Completer<InAppWebViewController>();
final StreamController<String> pageLoads =
StreamController<String>.broadcast();
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
child: InAppWebView(
key: GlobalKey(),
initialUrlRequest: URLRequest(url: Uri.parse(pageEncoded)),
onWebViewCreated: (controller) {
controllerCompleter.complete(controller);
},
initialSettings: InAppWebViewSettings(
javaScriptEnabled: true,
useShouldOverrideUrlLoading: true,
),
shouldOverrideUrlLoading: (controller, navigationAction) async {
var action = NavigationActionPolicy.CANCEL;
action = await Future<NavigationActionPolicy>.delayed(
const Duration(milliseconds: 10),
() => NavigationActionPolicy.ALLOW);
return action;
},
onLoadStop: (controller, url) {
pageLoads.add(url!.toString());
},
),
),
);
await pageLoads.stream.first; // Wait for initial page load.
final InAppWebViewController controller =
await controllerCompleter.future;
await controller.evaluateJavascript(
source: 'location.href = "$TEST_URL_2"');
await pageLoads.stream.first; // Wait for second page to load.
final String? currentUrl = (await controller.getUrl())?.toString();
expect(currentUrl, TEST_URL_2.toString());
pageLoads.close();
}, skip: shouldSkipTest4);
}, skip: shouldSkip);
}

View File

@ -0,0 +1,236 @@
import 'dart:async';
import 'dart:convert';
import 'dart:typed_data';
import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
import 'package:flutter_test/flutter_test.dart';
void videoPlaybackPolicy() {
final shouldSkip = kIsWeb ||
![
TargetPlatform.android,
TargetPlatform.iOS,
TargetPlatform.macOS,
].contains(defaultTargetPlatform);
group('Video playback policy', () {
String videoTestBase64 = "";
setUpAll(() async {
final ByteData videoData =
await rootBundle.load('test_assets/sample_video.mp4');
final String base64VideoData =
base64Encode(Uint8List.view(videoData.buffer));
final String videoTest = '''
<!DOCTYPE html><html>
<head><title>Video auto play</title>
<script type="text/javascript">
function play() {
var video = document.getElementById("video");
video.play();
}
function isPaused() {
var video = document.getElementById("video");
return video.paused;
}
function exitFullscreen() {
if (document.exitFullscreen) {
document.exitFullscreen();
} else if (document.webkitExitFullscreen) {
document.webkitExitFullscreen();
} else if (document.msExitFullscreen) {
document.msExitFullscreen();
}
}
</script>
</head>
<body onload="play();">
<video controls playsinline autoplay id="video">
<source src="data:video/mp4;charset=utf-8;base64,$base64VideoData">
</video>
</body>
</html>
''';
videoTestBase64 = base64Encode(const Utf8Encoder().convert(videoTest));
});
testWidgets('Auto media playback', (WidgetTester tester) async {
Completer<InAppWebViewController> controllerCompleter =
Completer<InAppWebViewController>();
Completer<void> pageLoaded = Completer<void>();
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
child: InAppWebView(
key: GlobalKey(),
initialUrlRequest: URLRequest(
url: Uri.parse(
'data:text/html;charset=utf-8;base64,$videoTestBase64')),
onWebViewCreated: (controller) {
controllerCompleter.complete(controller);
},
initialSettings: InAppWebViewSettings(
javaScriptEnabled: true,
mediaPlaybackRequiresUserGesture: false),
onLoadStop: (controller, url) {
pageLoaded.complete();
},
),
),
);
InAppWebViewController controller = await controllerCompleter.future;
await pageLoaded.future;
bool isPaused =
await controller.evaluateJavascript(source: 'isPaused();');
expect(isPaused, false);
controllerCompleter = Completer<InAppWebViewController>();
pageLoaded = Completer<void>();
// We change the key to re-create a new webview as we change the mediaPlaybackRequiresUserGesture
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
child: InAppWebView(
key: GlobalKey(),
initialUrlRequest: URLRequest(
url: Uri.parse(
'data:text/html;charset=utf-8;base64,$videoTestBase64')),
onWebViewCreated: (controller) {
controllerCompleter.complete(controller);
},
initialSettings: InAppWebViewSettings(
javaScriptEnabled: true,
mediaPlaybackRequiresUserGesture: true),
onLoadStop: (controller, url) {
pageLoaded.complete();
},
),
),
);
controller = await controllerCompleter.future;
await pageLoaded.future;
isPaused = await controller.evaluateJavascript(source: 'isPaused();');
expect(isPaused, true);
});
testWidgets('Video plays inline when allowsInlineMediaPlayback is true',
(WidgetTester tester) async {
Completer<InAppWebViewController> controllerCompleter =
Completer<InAppWebViewController>();
Completer<void> pageLoaded = Completer<void>();
Completer<void> onEnterFullscreenCompleter = Completer<void>();
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
child: InAppWebView(
key: GlobalKey(),
initialUrlRequest: URLRequest(
url: Uri.parse(
'data:text/html;charset=utf-8;base64,$videoTestBase64')),
onWebViewCreated: (controller) {
controllerCompleter.complete(controller);
},
initialSettings: InAppWebViewSettings(
javaScriptEnabled: true,
mediaPlaybackRequiresUserGesture: false,
allowsInlineMediaPlayback: true),
onLoadStop: (controller, url) {
pageLoaded.complete();
},
onEnterFullscreen: (controller) {
onEnterFullscreenCompleter.complete();
},
),
),
);
await pageLoaded.future;
expect(onEnterFullscreenCompleter.future, doesNotComplete);
});
testWidgets(
'Video plays fullscreen when allowsInlineMediaPlayback is false',
(WidgetTester tester) async {
Completer<InAppWebViewController> controllerCompleter =
Completer<InAppWebViewController>();
Completer<void> pageLoaded = Completer<void>();
Completer<void> onEnterFullscreenCompleter = Completer<void>();
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
child: InAppWebView(
key: GlobalKey(),
initialUrlRequest: URLRequest(
url: Uri.parse(
'data:text/html;charset=utf-8;base64,$videoTestBase64')),
onWebViewCreated: (controller) {
controllerCompleter.complete(controller);
},
initialSettings: InAppWebViewSettings(
javaScriptEnabled: true,
mediaPlaybackRequiresUserGesture: false,
allowsInlineMediaPlayback: false),
onLoadStop: (controller, url) {
pageLoaded.complete();
},
onEnterFullscreen: (controller) {
onEnterFullscreenCompleter.complete();
},
),
),
);
await pageLoaded.future;
await expectLater(onEnterFullscreenCompleter.future, completes);
});
testWidgets('exit fullscreen event', (WidgetTester tester) async {
Completer<InAppWebViewController> controllerCompleter =
Completer<InAppWebViewController>();
Completer<void> pageLoaded = Completer<void>();
Completer<void> onExitFullscreenCompleter = Completer<void>();
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
child: InAppWebView(
key: GlobalKey(),
initialUrlRequest: URLRequest(
url: Uri.parse(
'data:text/html;charset=utf-8;base64,$videoTestBase64')),
onWebViewCreated: (controller) {
controllerCompleter.complete(controller);
},
initialSettings: InAppWebViewSettings(
javaScriptEnabled: true,
mediaPlaybackRequiresUserGesture: false,
allowsInlineMediaPlayback: false),
onLoadStop: (controller, url) {
pageLoaded.complete();
},
onExitFullscreen: (controller) {
onExitFullscreenCompleter.complete();
},
),
),
);
InAppWebViewController controller = await controllerCompleter.future;
await pageLoaded.future;
await Future.delayed(Duration(seconds: 2));
await controller.evaluateJavascript(source: "exitFullscreen();");
await expectLater(onExitFullscreenCompleter.future, completes);
});
}, skip: shouldSkip);
}

File diff suppressed because it is too large Load Diff

View File

@ -544,7 +544,7 @@ class InAppWebViewSettings
///- Android native WebView
String? regexToCancelSubFramesLoading;
///Set to `true` to enable Flutter's new Hybrid Composition. The default value is `false`.
///Set to `false` to disable Flutter Hybrid Composition. The default value is `true`.
///Hybrid Composition is supported starting with Flutter v1.20+.
///
///**NOTE**: It is recommended to use Hybrid Composition only on Android 10+ for a release app,
@ -1119,7 +1119,7 @@ class InAppWebViewSettings
this.initialScale = 0,
this.supportMultipleWindows = false,
this.regexToCancelSubFramesLoading,
this.useHybridComposition = false,
this.useHybridComposition = true,
this.useShouldInterceptRequest = false,
this.useOnRenderProcessGone = false,
this.overScrollMode = OverScrollMode.OVER_SCROLL_IF_CONTENT_SCROLLS,