From 24e452f29cfb43af82191bf053bf932b2b05f77c Mon Sep 17 00:00:00 2001 From: Lorenzo Pichilli Date: Thu, 28 Apr 2022 01:10:20 +0200 Subject: [PATCH] updated tests --- CHANGELOG.md | 4 + example/integration_test/constants.dart | 5 +- .../in_app_webview/audio_playback_policy.dart | 125 ++ .../in_app_webview/get_title.dart | 67 + .../in_app_webview/javascript_handler.dart | 80 ++ .../in_app_webview/load_file_url.dart | 150 +++ .../integration_test/in_app_webview/main.dart | 22 +- .../in_app_webview/on_load_error.dart | 77 ++ .../in_app_webview/programmatic_scroll.dart | 176 +++ .../in_app_webview/resize_webview.dart | 104 ++ .../in_app_webview/set_custom_useragent.dart | 49 + .../should_override_url_loading.dart | 250 ++++ .../in_app_webview/video_playback_policy.dart | 236 ++++ .../webview_flutter_test.dart | 1137 +---------------- .../in_app_webview_settings.dart | 4 +- 15 files changed, 1349 insertions(+), 1137 deletions(-) create mode 100644 example/integration_test/in_app_webview/audio_playback_policy.dart create mode 100644 example/integration_test/in_app_webview/get_title.dart create mode 100644 example/integration_test/in_app_webview/javascript_handler.dart create mode 100644 example/integration_test/in_app_webview/load_file_url.dart create mode 100644 example/integration_test/in_app_webview/on_load_error.dart create mode 100644 example/integration_test/in_app_webview/programmatic_scroll.dart create mode 100644 example/integration_test/in_app_webview/resize_webview.dart create mode 100644 example/integration_test/in_app_webview/set_custom_useragent.dart create mode 100644 example/integration_test/in_app_webview/should_override_url_loading.dart create mode 100644 example/integration_test/in_app_webview/video_playback_policy.dart diff --git a/CHANGELOG.md b/CHANGELOG.md index 87a3cb08..cf08cdeb 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 diff --git a/example/integration_test/constants.dart b/example/integration_test/constants.dart index 781bc2ee..d774a815 100644 --- a/example/integration_test/constants.dart +++ b/example/integration_test/constants.dart @@ -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'); \ No newline at end of file +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'); \ No newline at end of file diff --git a/example/integration_test/in_app_webview/audio_playback_policy.dart b/example/integration_test/in_app_webview/audio_playback_policy.dart new file mode 100644 index 00000000..0112c8da --- /dev/null +++ b/example/integration_test/in_app_webview/audio_playback_policy.dart @@ -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 = ''' + + Audio auto play + + + + + + + '''; + audioTestBase64 = base64Encode(const Utf8Encoder().convert(audioTest)); + }); + + testWidgets('Auto media playback', (WidgetTester tester) async { + Completer controllerCompleter = + Completer(); + Completer pageStarted = Completer(); + Completer pageLoaded = Completer(); + + 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(); + pageStarted = Completer(); + pageLoaded = Completer(); + + // 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); +} \ No newline at end of file diff --git a/example/integration_test/in_app_webview/get_title.dart b/example/integration_test/in_app_webview/get_title.dart new file mode 100644 index 00000000..da3e03ca --- /dev/null +++ b/example/integration_test/in_app_webview/get_title.dart @@ -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 = ''' + + Some title + + + + + '''; + 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 pageStarted = Completer(); + final Completer pageLoaded = Completer(); + final Completer controllerCompleter = Completer(); + + 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); +} \ No newline at end of file diff --git a/example/integration_test/in_app_webview/javascript_handler.dart b/example/integration_test/in_app_webview/javascript_handler.dart new file mode 100644 index 00000000..0380701f --- /dev/null +++ b/example/integration_test/in_app_webview/javascript_handler.dart @@ -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(); + final Completer pageStarted = Completer(); + final Completer pageLoaded = Completer(); + final Completer handlerFoo = Completer(); + final Completer handlerFooWithArgs = Completer(); + final List messagesReceived = []; + 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?); + messagesReceived.add(args[3]?.cast() + as Map?); + messagesReceived.add(args[4]?.cast() + as Map?); + 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?, ["bar", 5]), true); + expect(mapEquals(messagesReceived[3], {"foo": "baz"}), true); + expect( + mapEquals( + messagesReceived[4], {"bar": "bar_value", "baz": "baz_value"}), + true); + }, skip: shouldSkip); +} \ No newline at end of file diff --git a/example/integration_test/in_app_webview/load_file_url.dart b/example/integration_test/in_app_webview/load_file_url.dart new file mode 100644 index 00000000..aadf088f --- /dev/null +++ b/example/integration_test/in_app_webview/load_file_url.dart @@ -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 = """ + + + file scheme + + + + + + """; + 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 consoleMessageShouldNotComplete = + Completer(); + 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 consoleMessageCompleter = + Completer(); + 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 consoleMessageShouldNotComplete = + Completer(); + 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 consoleMessageCompleter = + Completer(); + 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); +} diff --git a/example/integration_test/in_app_webview/main.dart b/example/integration_test/in_app_webview/main.dart index fc3d2a6e..7d30a0ef 100644 --- a/example/integration_test/in_app_webview/main.dart +++ b/example/integration_test/in_app_webview/main.dart @@ -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(); }); } \ No newline at end of file diff --git a/example/integration_test/in_app_webview/on_load_error.dart b/example/integration_test/in_app_webview/on_load_error.dart new file mode 100644 index 00000000..5c83c419 --- /dev/null +++ b/example/integration_test/in_app_webview/on_load_error.dart @@ -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 errorUrlCompleter = Completer(); + final Completer errorCodeCompleter = Completer(); + + 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 errorUrlCompleter = Completer(); + final Completer errorCodeCompleter = Completer(); + final Completer errorMessageCompleter = Completer(); + + 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); +} diff --git a/example/integration_test/in_app_webview/programmatic_scroll.dart b/example/integration_test/in_app_webview/programmatic_scroll.dart new file mode 100644 index 00000000..92cdb5ec --- /dev/null +++ b/example/integration_test/in_app_webview/programmatic_scroll.dart @@ -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 = ''' + + + + + + +
+ + + '''; + + 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 pageLoaded = Completer(); + final Completer controllerCompleter = + Completer(); + + 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 = ''' + + + + + + +
+ + + '''; + + final String scrollTestPageBase64 = + base64Encode(const Utf8Encoder().convert(scrollTestPage)); + + final Completer pageLoaded = Completer(); + final Completer controllerCompleter = + Completer(); + + 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); +} \ No newline at end of file diff --git a/example/integration_test/in_app_webview/resize_webview.dart b/example/integration_test/in_app_webview/resize_webview.dart new file mode 100644 index 00000000..43ff9084 --- /dev/null +++ b/example/integration_test/in_app_webview/resize_webview.dart @@ -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 = ''' + + Resize test + + + + + + '''; + final String resizeTestBase64 = + base64Encode(const Utf8Encoder().convert(resizeTest)); + final Completer resizeCompleter = Completer(); + final Completer pageStarted = Completer(); + final Completer pageLoaded = Completer(); + final Completer controllerCompleter = Completer(); + 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: [ + 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: [ + SizedBox( + width: 400, + height: 400, + child: webView, + ), + ], + ), + ), + ); + + await resizeCompleter.future; + }, skip: shouldSkip); +} \ No newline at end of file diff --git a/example/integration_test/in_app_webview/set_custom_useragent.dart b/example/integration_test/in_app_webview/set_custom_useragent.dart new file mode 100644 index 00000000..cdf9d2b6 --- /dev/null +++ b/example/integration_test/in_app_webview/set_custom_useragent.dart @@ -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(); + 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); +} diff --git a/example/integration_test/in_app_webview/should_override_url_loading.dart b/example/integration_test/in_app_webview/should_override_url_loading.dart new file mode 100644 index 00000000..bf776a86 --- /dev/null +++ b/example/integration_test/in_app_webview/should_override_url_loading.dart @@ -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 = + '''flutter_inappwebview'''; + 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(); + final StreamController pageLoads = + StreamController.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(); + final StreamController pageLoads = + StreamController.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(); + final StreamController pageLoads = + StreamController.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(); + final StreamController pageLoads = + StreamController.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.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); +} diff --git a/example/integration_test/in_app_webview/video_playback_policy.dart b/example/integration_test/in_app_webview/video_playback_policy.dart new file mode 100644 index 00000000..d35ab163 --- /dev/null +++ b/example/integration_test/in_app_webview/video_playback_policy.dart @@ -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 = ''' + + Video auto play + + + + + + + '''; + videoTestBase64 = base64Encode(const Utf8Encoder().convert(videoTest)); + }); + + testWidgets('Auto media playback', (WidgetTester tester) async { + Completer controllerCompleter = + Completer(); + Completer pageLoaded = Completer(); + + 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(); + pageLoaded = Completer(); + + // 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 controllerCompleter = + Completer(); + Completer pageLoaded = Completer(); + Completer onEnterFullscreenCompleter = Completer(); + + 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 controllerCompleter = + Completer(); + Completer pageLoaded = Completer(); + Completer onEnterFullscreenCompleter = Completer(); + + 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 controllerCompleter = + Completer(); + Completer pageLoaded = Completer(); + Completer onExitFullscreenCompleter = Completer(); + + 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); +} diff --git a/example/integration_test/webview_flutter_test.dart b/example/integration_test/webview_flutter_test.dart index 0fb93521..af21803a 100644 --- a/example/integration_test/webview_flutter_test.dart +++ b/example/integration_test/webview_flutter_test.dart @@ -1,19 +1,16 @@ import 'dart:async'; import 'dart:collection'; import 'dart:convert'; -// import 'dart:io'; import 'dart:typed_data'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.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 'package:integration_test/integration_test.dart'; -import 'package:path_provider/path_provider.dart'; -import 'in_app_webview/main.dart' as in_app_webview_test; +import 'in_app_webview/main.dart' as in_app_webview_tests; import '.env.dart'; @@ -21,1140 +18,14 @@ import 'util.dart'; void main() { IntegrationTestWidgetsFlutterBinding.ensureInitialized(); + if (defaultTargetPlatform == TargetPlatform.android) { InAppWebViewController.setWebContentsDebuggingEnabled(true); } - in_app_webview_test.main(); + in_app_webview_tests.main(); - group('OLD InAppWebView', () { - - - - // group("iOS loadFileURL", () { - // 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 = """ - // - // - // file scheme - // - // - // - // - // - // """; - // 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 consoleMessageShouldNotComplete = - // Completer(); - // 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 consoleMessageCompleter = - // Completer(); - // await tester.pumpWidget( - // Directionality( - // textDirection: TextDirection.ltr, - // child: InAppWebView( - // key: GlobalKey(), - // initialUrlRequest: - // URLRequest(url: Uri.parse('file://${fileHtml.path}')), - // initialOptions: InAppWebViewGroupOptions( - // ios: IOSInAppWebViewOptions( - // 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: defaultTargetPlatform != TargetPlatform.iOS); - // - // testWidgets( - // 'loadUrl with file:// scheme and allowingReadAccessTo argument', - // (WidgetTester tester) async { - // final Completer consoleMessageShouldNotComplete = - // Completer(); - // 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 consoleMessageCompleter = - // Completer(); - // 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: defaultTargetPlatform != TargetPlatform.iOS); - // }, skip: defaultTargetPlatform != TargetPlatform.iOS); - - testWidgets('JavaScript Handler', (WidgetTester tester) async { - final Completer controllerCompleter = Completer(); - final Completer pageStarted = Completer(); - final Completer pageLoaded = Completer(); - final Completer handlerFoo = Completer(); - final Completer handlerFooWithArgs = Completer(); - final List messagesReceived = []; - 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?); - messagesReceived.add(args[3]?.cast() - as Map?); - messagesReceived.add(args[4]?.cast() - as Map?); - handlerFooWithArgs.complete(); - }); - }, - initialOptions: InAppWebViewGroupOptions( - crossPlatform: InAppWebViewOptions(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?, ["bar", 5]), true); - expect(mapEquals(messagesReceived[3], {"foo": "baz"}), true); - expect( - mapEquals( - messagesReceived[4], {"bar": "bar_value", "baz": "baz_value"}), - true); - }); - - testWidgets('resize webview', (WidgetTester tester) async { - final String resizeTest = ''' - - Resize test - - - - - - '''; - final String resizeTestBase64 = - base64Encode(const Utf8Encoder().convert(resizeTest)); - final Completer resizeCompleter = Completer(); - final Completer pageStarted = Completer(); - final Completer pageLoaded = Completer(); - final Completer controllerCompleter = Completer(); - 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(); - }, - initialOptions: InAppWebViewGroupOptions( - crossPlatform: InAppWebViewOptions(javaScriptEnabled: true)), - ); - - await tester.pumpWidget( - Directionality( - textDirection: TextDirection.ltr, - child: Column( - children: [ - 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: [ - SizedBox( - width: 400, - height: 400, - child: webView, - ), - ], - ), - ), - ); - - await resizeCompleter.future; - }); - - testWidgets('set custom userAgent', (WidgetTester tester) async { - final Completer controllerCompleter1 = - Completer(); - await tester.pumpWidget( - Directionality( - textDirection: TextDirection.ltr, - child: InAppWebView( - initialUrlRequest: URLRequest(url: Uri.parse('about:blank')), - initialOptions: InAppWebViewGroupOptions( - crossPlatform: InAppWebViewOptions( - 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.setOptions( - options: InAppWebViewGroupOptions( - crossPlatform: InAppWebViewOptions( - userAgent: 'Custom_User_Agent2', - ))); - - final String customUserAgent2 = - await controller1.evaluateJavascript(source: 'navigator.userAgent;'); - expect(customUserAgent2, 'Custom_User_Agent2'); - }); - - 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 = ''' - - Video auto play - - - - - - - '''; - videoTestBase64 = base64Encode(const Utf8Encoder().convert(videoTest)); - }); - - testWidgets('Auto media playback', (WidgetTester tester) async { - Completer controllerCompleter = - Completer(); - Completer pageLoaded = Completer(); - - 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); - }, - initialOptions: InAppWebViewGroupOptions( - crossPlatform: InAppWebViewOptions( - 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(); - pageLoaded = Completer(); - - // 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); - }, - initialOptions: InAppWebViewGroupOptions( - crossPlatform: InAppWebViewOptions( - 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 controllerCompleter = - Completer(); - Completer pageLoaded = Completer(); - Completer onEnterFullscreenCompleter = Completer(); - - 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); - }, - initialOptions: InAppWebViewGroupOptions( - crossPlatform: InAppWebViewOptions( - javaScriptEnabled: true, - mediaPlaybackRequiresUserGesture: false, - ), - ios: IOSInAppWebViewOptions(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 controllerCompleter = - Completer(); - Completer pageLoaded = Completer(); - Completer onEnterFullscreenCompleter = Completer(); - - 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); - }, - initialOptions: InAppWebViewGroupOptions( - crossPlatform: InAppWebViewOptions( - javaScriptEnabled: true, - mediaPlaybackRequiresUserGesture: false, - ), - ios: - IOSInAppWebViewOptions(allowsInlineMediaPlayback: false)), - onLoadStop: (controller, url) { - pageLoaded.complete(); - }, - onEnterFullscreen: (controller) { - onEnterFullscreenCompleter.complete(); - }, - ), - ), - ); - - await pageLoaded.future; - await expectLater(onEnterFullscreenCompleter.future, completes); - }, skip: true); - - testWidgets('exit fullscreen event', (WidgetTester tester) async { - Completer controllerCompleter = - Completer(); - Completer pageLoaded = Completer(); - Completer onExitFullscreenCompleter = Completer(); - - 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); - }, - initialOptions: InAppWebViewGroupOptions( - crossPlatform: InAppWebViewOptions( - javaScriptEnabled: true, - mediaPlaybackRequiresUserGesture: false, - ), - ios: - IOSInAppWebViewOptions(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: true /*defaultTargetPlatform != TargetPlatform.android*/); - }); - - 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 = ''' - - Audio auto play - - - - - - - '''; - audioTestBase64 = base64Encode(const Utf8Encoder().convert(audioTest)); - }); - - testWidgets('Auto media playback', (WidgetTester tester) async { - Completer controllerCompleter = - Completer(); - Completer pageStarted = Completer(); - Completer pageLoaded = Completer(); - - 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); - }, - initialOptions: InAppWebViewGroupOptions( - crossPlatform: InAppWebViewOptions( - 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(); - pageStarted = Completer(); - pageLoaded = Completer(); - - // 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); - }, - initialOptions: InAppWebViewGroupOptions( - crossPlatform: InAppWebViewOptions( - 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); - }); - }); - - testWidgets('getTitle', (WidgetTester tester) async { - final String getTitleTest = ''' - - Some title - - - - - '''; - final String getTitleTestBase64 = - base64Encode(const Utf8Encoder().convert(getTitleTest)); - final Completer pageStarted = Completer(); - final Completer pageLoaded = Completer(); - final Completer controllerCompleter = Completer(); - - await tester.pumpWidget( - Directionality( - textDirection: TextDirection.ltr, - child: InAppWebView( - initialUrlRequest: URLRequest( - url: Uri.parse( - 'data:text/html;charset=utf-8;base64,$getTitleTestBase64')), - 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, 'Some title'); - }); - - group('Programmatic Scroll', () { - testWidgets('setAndGetScrollPosition', (WidgetTester tester) async { - final String scrollTestPage = ''' - - - - - - -
- - - '''; - - final String scrollTestPageBase64 = - base64Encode(const Utf8Encoder().convert(scrollTestPage)); - - final Completer pageLoaded = Completer(); - final Completer controllerCompleter = - Completer(); - - 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); - }, - 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); - }); - }); - - group('Android Hybrid Composition', () { - testWidgets('setAndGetScrollPosition', (WidgetTester tester) async { - final String scrollTestPage = ''' - - - - - - -
- - - '''; - - final String scrollTestPageBase64 = - base64Encode(const Utf8Encoder().convert(scrollTestPage)); - - final Completer pageLoaded = Completer(); - final Completer controllerCompleter = - Completer(); - - 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); - }, - initialOptions: InAppWebViewGroupOptions( - android: - AndroidInAppWebViewOptions(useHybridComposition: true)), - 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: defaultTargetPlatform != TargetPlatform.android); - - group('shouldOverrideUrlLoading', () { - final String page = - '''flutter_inappwebview'''; - final String pageEncoded = 'data:text/html;charset=utf-8;base64,' + - base64Encode(const Utf8Encoder().convert(page)); - - testWidgets('can allow requests', (WidgetTester tester) async { - final Completer controllerCompleter = - Completer(); - final StreamController pageLoads = - StreamController.broadcast(); - await tester.pumpWidget( - Directionality( - textDirection: TextDirection.ltr, - child: InAppWebView( - key: GlobalKey(), - initialUrlRequest: URLRequest(url: Uri.parse(pageEncoded)), - onWebViewCreated: (controller) { - controllerCompleter.complete(controller); - }, - initialOptions: InAppWebViewGroupOptions( - crossPlatform: InAppWebViewOptions( - javaScriptEnabled: true, useShouldOverrideUrlLoading: true), - ), - shouldOverrideUrlLoading: (controller, navigationAction) async { - return (navigationAction.request.url!.host - .contains('youtube.com')) - ? 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 = "https://www.google.com/"'); - - await pageLoads.stream.first; // Wait for the next page load. - final String? currentUrl = (await controller.getUrl())?.toString(); - expect(currentUrl, 'https://www.google.com/'); - - pageLoads.close(); - }); - - testWidgets( - 'allow requests on iOS only if iosWKNavigationType == IOSWKNavigationType.LINK_ACTIVATED', - (WidgetTester tester) async { - final Completer controllerCompleter = - Completer(); - final StreamController pageLoads = - StreamController.broadcast(); - await tester.pumpWidget( - Directionality( - textDirection: TextDirection.ltr, - child: InAppWebView( - key: GlobalKey(), - initialUrlRequest: URLRequest(url: Uri.parse(pageEncoded)), - onWebViewCreated: (controller) { - controllerCompleter.complete(controller); - }, - initialOptions: InAppWebViewGroupOptions( - crossPlatform: InAppWebViewOptions( - javaScriptEnabled: true, useShouldOverrideUrlLoading: true), - ), - shouldOverrideUrlLoading: (controller, navigationAction) async { - var isFirstLoad = - navigationAction.request.url!.scheme == "data"; - return (isFirstLoad || - navigationAction.iosWKNavigationType == - IOSWKNavigationType.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 = "https://www.google.com/"'); - - // 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 - .map((event) => event as String?) - .first - .timeout(const Duration(milliseconds: 500), onTimeout: () => null); - String? currentUrl = (await controller.getUrl())?.toString(); - expect(currentUrl, isNot('https://www.google.com/')); - - 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, - 'https://github.com/pichillilorenzo/flutter_inappwebview'); - - pageLoads.close(); - }, skip: defaultTargetPlatform != TargetPlatform.iOS); - - testWidgets('can block requests', (WidgetTester tester) async { - final Completer controllerCompleter = - Completer(); - final StreamController pageLoads = - StreamController.broadcast(); - await tester.pumpWidget( - Directionality( - textDirection: TextDirection.ltr, - child: InAppWebView( - key: GlobalKey(), - initialUrlRequest: URLRequest(url: Uri.parse(pageEncoded)), - onWebViewCreated: (controller) { - controllerCompleter.complete(controller); - }, - initialOptions: InAppWebViewGroupOptions( - crossPlatform: InAppWebViewOptions( - javaScriptEnabled: true, useShouldOverrideUrlLoading: true), - ), - shouldOverrideUrlLoading: (controller, navigationAction) async { - return (navigationAction.request.url!.host - .contains('youtube.com')) - ? 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 = "https://www.youtube.com/"'); - - // 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 - .map((event) => event as String?) - .first - .timeout(const Duration(milliseconds: 500), onTimeout: () => null); - final String? currentUrl = (await controller.getUrl())?.toString(); - expect(currentUrl, isNot(contains('youtube.com'))); - - pageLoads.close(); - }); - - testWidgets('supports asynchronous decisions', - (WidgetTester tester) async { - final Completer controllerCompleter = - Completer(); - final StreamController pageLoads = - StreamController.broadcast(); - await tester.pumpWidget( - Directionality( - textDirection: TextDirection.ltr, - child: InAppWebView( - key: GlobalKey(), - initialUrlRequest: URLRequest(url: Uri.parse(pageEncoded)), - onWebViewCreated: (controller) { - controllerCompleter.complete(controller); - }, - initialOptions: InAppWebViewGroupOptions( - crossPlatform: InAppWebViewOptions( - javaScriptEnabled: true, useShouldOverrideUrlLoading: true), - ), - shouldOverrideUrlLoading: (controller, navigationAction) async { - var action = NavigationActionPolicy.CANCEL; - action = await Future.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 = "https://www.google.com"'); - - await pageLoads.stream.first; // Wait for second page to load. - final String? currentUrl = (await controller.getUrl())?.toString(); - expect(currentUrl, 'https://www.google.com/'); - - pageLoads.close(); - }); - }); - - testWidgets('onLoadError', (WidgetTester tester) async { - final Completer errorUrlCompleter = Completer(); - final Completer errorCodeCompleter = Completer(); - - await tester.pumpWidget( - Directionality( - textDirection: TextDirection.ltr, - child: InAppWebView( - key: GlobalKey(), - initialUrlRequest: - URLRequest(url: Uri.parse('https://www.notawebsite..com')), - 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) { - expect(code, -1003); - } - expect(url, 'https://www.notawebsite..com/'); - }); - - testWidgets('onLoadError is not called with valid url', - (WidgetTester tester) async { - final Completer errorUrlCompleter = Completer(); - final Completer errorCodeCompleter = Completer(); - final Completer errorMessageCompleter = Completer(); - - 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); - }); + group('InAppWebView', () { testWidgets('launches with allowsBackForwardNavigationGestures true on iOS', (WidgetTester tester) async { diff --git a/lib/src/in_app_webview/in_app_webview_settings.dart b/lib/src/in_app_webview/in_app_webview_settings.dart index bcddcd7f..b52cc737 100755 --- a/lib/src/in_app_webview/in_app_webview_settings.dart +++ b/lib/src/in_app_webview/in_app_webview_settings.dart @@ -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,