updated tests
This commit is contained in:
parent
55a2a41a04
commit
24e452f29c
|
@ -7,6 +7,10 @@
|
||||||
- Added support for `onPermissionRequest` event on iOS 15.0+
|
- Added support for `onPermissionRequest` event on iOS 15.0+
|
||||||
- Updated `getMetaThemeColor` 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
|
## 5.4.3
|
||||||
|
|
||||||
- Added Bitwise OR operator support for `AndroidActionModeMenuItem` class
|
- Added Bitwise OR operator support for `AndroidActionModeMenuItem` class
|
||||||
|
|
|
@ -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_CROSS_PLATFORM_URL_2 = Uri.parse('https://www.bing.com/');
|
||||||
final TEST_URL_1 = Uri.parse('https://github.com/flutter');
|
final TEST_URL_1 = Uri.parse('https://github.com/flutter');
|
||||||
final TEST_URL_2 = Uri.parse('https://www.google.com/');
|
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');
|
|
@ -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);
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
|
@ -1,9 +1,19 @@
|
||||||
import 'package:flutter_test/flutter_test.dart';
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
|
|
||||||
|
import 'audio_playback_policy.dart';
|
||||||
|
import 'get_title.dart';
|
||||||
import 'initial_url_request.dart';
|
import 'initial_url_request.dart';
|
||||||
import 'set_get_settings.dart';
|
|
||||||
import 'javascript_code_evaluation.dart';
|
import 'javascript_code_evaluation.dart';
|
||||||
|
import 'javascript_handler.dart';
|
||||||
|
import 'load_file_url.dart';
|
||||||
import 'load_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() {
|
void main() {
|
||||||
group('InAppWebView', () {
|
group('InAppWebView', () {
|
||||||
|
@ -11,5 +21,15 @@ void main() {
|
||||||
setGetSettings();
|
setGetSettings();
|
||||||
javascriptCodeEvaluation();
|
javascriptCodeEvaluation();
|
||||||
loadUrl();
|
loadUrl();
|
||||||
|
loadFileUrl();
|
||||||
|
javascriptHandler();
|
||||||
|
resizeWebView();
|
||||||
|
setCustomUserAgent();
|
||||||
|
videoPlaybackPolicy();
|
||||||
|
audioPlaybackPolicy();
|
||||||
|
getTitle();
|
||||||
|
programmaticScroll();
|
||||||
|
shouldOverrideUrlLoading();
|
||||||
|
onLoadError();
|
||||||
});
|
});
|
||||||
}
|
}
|
|
@ -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);
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
|
@ -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
|
@ -544,7 +544,7 @@ class InAppWebViewSettings
|
||||||
///- Android native WebView
|
///- Android native WebView
|
||||||
String? regexToCancelSubFramesLoading;
|
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+.
|
///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,
|
///**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.initialScale = 0,
|
||||||
this.supportMultipleWindows = false,
|
this.supportMultipleWindows = false,
|
||||||
this.regexToCancelSubFramesLoading,
|
this.regexToCancelSubFramesLoading,
|
||||||
this.useHybridComposition = false,
|
this.useHybridComposition = true,
|
||||||
this.useShouldInterceptRequest = false,
|
this.useShouldInterceptRequest = false,
|
||||||
this.useOnRenderProcessGone = false,
|
this.useOnRenderProcessGone = false,
|
||||||
this.overScrollMode = OverScrollMode.OVER_SCROLL_IF_CONTENT_SCROLLS,
|
this.overScrollMode = OverScrollMode.OVER_SCROLL_IF_CONTENT_SCROLLS,
|
||||||
|
|
Loading…
Reference in New Issue