// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'dart:typed_data';

import 'package:flutter/src/foundation/basic_types.dart';
import 'package:flutter/src/gestures/recognizer.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:mockito/annotations.dart';
import 'package:mockito/mockito.dart';
import 'package:webview_flutter/webview_flutter.dart';
import 'package:webview_flutter_platform_interface/webview_flutter_platform_interface.dart';

import 'webview_flutter_test.mocks.dart';

typedef VoidCallback = void Function();

@GenerateMocks(<Type>[WebViewPlatform, WebViewPlatformController])
void main() {
  TestWidgetsFlutterBinding.ensureInitialized();

  late MockWebViewPlatform mockWebViewPlatform;
  late MockWebViewPlatformController mockWebViewPlatformController;
  late MockWebViewCookieManagerPlatform mockWebViewCookieManagerPlatform;

  setUp(() {
    mockWebViewPlatformController = MockWebViewPlatformController();
    mockWebViewPlatform = MockWebViewPlatform();
    mockWebViewCookieManagerPlatform = MockWebViewCookieManagerPlatform();
    when(mockWebViewPlatform.build(
      context: anyNamed('context'),
      creationParams: anyNamed('creationParams'),
      webViewPlatformCallbacksHandler:
          anyNamed('webViewPlatformCallbacksHandler'),
      javascriptChannelRegistry: anyNamed('javascriptChannelRegistry'),
      onWebViewPlatformCreated: anyNamed('onWebViewPlatformCreated'),
      gestureRecognizers: anyNamed('gestureRecognizers'),
    )).thenAnswer((Invocation invocation) {
      final WebViewPlatformCreatedCallback onWebViewPlatformCreated =
          invocation.namedArguments[const Symbol('onWebViewPlatformCreated')]
              as WebViewPlatformCreatedCallback;
      return TestPlatformWebView(
        mockWebViewPlatformController: mockWebViewPlatformController,
        onWebViewPlatformCreated: onWebViewPlatformCreated,
      );
    });

    WebView.platform = mockWebViewPlatform;
    WebViewCookieManagerPlatform.instance = mockWebViewCookieManagerPlatform;
  });

  tearDown(() {
    mockWebViewCookieManagerPlatform.reset();
  });

  testWidgets('Create WebView', (WidgetTester tester) async {
    await tester.pumpWidget(const WebView());
  });

  testWidgets('Initial url', (WidgetTester tester) async {
    await tester.pumpWidget(const WebView(initialUrl: 'https://youtube.com'));

    final CreationParams params = captureBuildArgs(
      mockWebViewPlatform,
      creationParams: true,
    ).single as CreationParams;

    expect(params.initialUrl, 'https://youtube.com');
  });

  testWidgets('Javascript mode', (WidgetTester tester) async {
    await tester.pumpWidget(const WebView(
      javascriptMode: JavascriptMode.unrestricted,
    ));

    final CreationParams unrestrictedparams = captureBuildArgs(
      mockWebViewPlatform,
      creationParams: true,
    ).single as CreationParams;

    expect(
      unrestrictedparams.webSettings!.javascriptMode,
      JavascriptMode.unrestricted,
    );

    await tester.pumpWidget(const WebView(
      javascriptMode: JavascriptMode.disabled,
    ));

    final CreationParams disabledparams = captureBuildArgs(
      mockWebViewPlatform,
      creationParams: true,
    ).single as CreationParams;

    expect(disabledparams.webSettings!.javascriptMode, JavascriptMode.disabled);
  });

  testWidgets('Load file', (WidgetTester tester) async {
    WebViewController? controller;
    await tester.pumpWidget(
      WebView(
        onWebViewCreated: (WebViewController webViewController) {
          controller = webViewController;
        },
      ),
    );

    expect(controller, isNotNull);

    await controller!.loadFile('/test/path/index.html');

    verify(mockWebViewPlatformController.loadFile(
      '/test/path/index.html',
    ));
  });

  testWidgets('Load file with empty path', (WidgetTester tester) async {
    WebViewController? controller;
    await tester.pumpWidget(
      WebView(
        onWebViewCreated: (WebViewController webViewController) {
          controller = webViewController;
        },
      ),
    );

    expect(controller, isNotNull);

    expect(() => controller!.loadFile(''), throwsAssertionError);
  });

  testWidgets('Load Flutter asset', (WidgetTester tester) async {
    WebViewController? controller;
    await tester.pumpWidget(
      WebView(
        onWebViewCreated: (WebViewController webViewController) {
          controller = webViewController;
        },
      ),
    );

    expect(controller, isNotNull);

    await controller!.loadFlutterAsset('assets/index.html');

    verify(mockWebViewPlatformController.loadFlutterAsset(
      'assets/index.html',
    ));
  });

  testWidgets('Load Flutter asset with empty key', (WidgetTester tester) async {
    WebViewController? controller;
    await tester.pumpWidget(
      WebView(
        onWebViewCreated: (WebViewController webViewController) {
          controller = webViewController;
        },
      ),
    );

    expect(controller, isNotNull);

    expect(() => controller!.loadFlutterAsset(''), throwsAssertionError);
  });

  testWidgets('Load HTML string without base URL', (WidgetTester tester) async {
    WebViewController? controller;
    await tester.pumpWidget(
      WebView(
        onWebViewCreated: (WebViewController webViewController) {
          controller = webViewController;
        },
      ),
    );

    expect(controller, isNotNull);

    await controller!.loadHtmlString('<p>This is a test paragraph.</p>');

    verify(mockWebViewPlatformController.loadHtmlString(
      '<p>This is a test paragraph.</p>',
    ));
  });

  testWidgets('Load HTML string with base URL', (WidgetTester tester) async {
    WebViewController? controller;
    await tester.pumpWidget(
      WebView(
        onWebViewCreated: (WebViewController webViewController) {
          controller = webViewController;
        },
      ),
    );

    expect(controller, isNotNull);

    await controller!.loadHtmlString(
      '<p>This is a test paragraph.</p>',
      baseUrl: 'https://flutter.dev',
    );

    verify(mockWebViewPlatformController.loadHtmlString(
      '<p>This is a test paragraph.</p>',
      baseUrl: 'https://flutter.dev',
    ));
  });

  testWidgets('Load HTML string with empty string',
      (WidgetTester tester) async {
    WebViewController? controller;
    await tester.pumpWidget(
      WebView(
        onWebViewCreated: (WebViewController webViewController) {
          controller = webViewController;
        },
      ),
    );

    expect(controller, isNotNull);

    expect(() => controller!.loadHtmlString(''), throwsAssertionError);
  });

  testWidgets('Load url', (WidgetTester tester) async {
    WebViewController? controller;
    await tester.pumpWidget(
      WebView(
        onWebViewCreated: (WebViewController webViewController) {
          controller = webViewController;
        },
      ),
    );

    expect(controller, isNotNull);

    await controller!.loadUrl('https://flutter.io');

    verify(mockWebViewPlatformController.loadUrl(
      'https://flutter.io',
      argThat(isNull),
    ));
  });

  testWidgets('Invalid urls', (WidgetTester tester) async {
    WebViewController? controller;
    await tester.pumpWidget(
      WebView(
        onWebViewCreated: (WebViewController webViewController) {
          controller = webViewController;
        },
      ),
    );

    expect(controller, isNotNull);

    final CreationParams params = captureBuildArgs(
      mockWebViewPlatform,
      creationParams: true,
    ).single as CreationParams;

    expect(params.initialUrl, isNull);

    expect(() => controller!.loadUrl(''), throwsA(anything));
    expect(() => controller!.loadUrl('flutter.io'), throwsA(anything));
  });

  testWidgets('Headers in loadUrl', (WidgetTester tester) async {
    WebViewController? controller;
    await tester.pumpWidget(
      WebView(
        onWebViewCreated: (WebViewController webViewController) {
          controller = webViewController;
        },
      ),
    );

    expect(controller, isNotNull);

    final Map<String, String> headers = <String, String>{
      'CACHE-CONTROL': 'ABC'
    };
    await controller!.loadUrl('https://flutter.io', headers: headers);

    verify(mockWebViewPlatformController.loadUrl(
      'https://flutter.io',
      <String, String>{'CACHE-CONTROL': 'ABC'},
    ));
  });

  testWidgets('loadRequest', (WidgetTester tester) async {
    WebViewController? controller;
    await tester.pumpWidget(
      WebView(
        onWebViewCreated: (WebViewController webViewController) {
          controller = webViewController;
        },
      ),
    );
    expect(controller, isNotNull);

    final WebViewRequest req = WebViewRequest(
      uri: Uri.parse('https://flutter.dev'),
      method: WebViewRequestMethod.post,
      headers: <String, String>{'foo': 'bar'},
      body: Uint8List.fromList('Test Body'.codeUnits),
    );

    await controller!.loadRequest(req);

    verify(mockWebViewPlatformController.loadRequest(req));
  });

  testWidgets('Clear Cache', (WidgetTester tester) async {
    WebViewController? controller;
    await tester.pumpWidget(
      WebView(
        onWebViewCreated: (WebViewController webViewController) {
          controller = webViewController;
        },
      ),
    );

    expect(controller, isNotNull);

    await controller!.clearCache();

    verify(mockWebViewPlatformController.clearCache());
  });

  testWidgets('Can go back', (WidgetTester tester) async {
    when(mockWebViewPlatformController.canGoBack())
        .thenAnswer((_) => Future<bool>.value(true));

    WebViewController? controller;
    await tester.pumpWidget(
      WebView(
        initialUrl: 'https://flutter.io',
        onWebViewCreated: (WebViewController webViewController) {
          controller = webViewController;
        },
      ),
    );

    expect(controller, isNotNull);
    expect(controller!.canGoBack(), completion(true));
  });

  testWidgets("Can't go forward", (WidgetTester tester) async {
    when(mockWebViewPlatformController.canGoForward())
        .thenAnswer((_) => Future<bool>.value(false));

    WebViewController? controller;
    await tester.pumpWidget(
      WebView(
        onWebViewCreated: (WebViewController webViewController) {
          controller = webViewController;
        },
      ),
    );

    expect(controller, isNotNull);
    expect(controller!.canGoForward(), completion(false));
  });

  testWidgets('Go back', (WidgetTester tester) async {
    WebViewController? controller;
    await tester.pumpWidget(
      WebView(
        initialUrl: 'https://youtube.com',
        onWebViewCreated: (WebViewController webViewController) {
          controller = webViewController;
        },
      ),
    );

    await controller!.goBack();
    verify(mockWebViewPlatformController.goBack());
  });

  testWidgets('Go forward', (WidgetTester tester) async {
    WebViewController? controller;
    await tester.pumpWidget(
      WebView(
        initialUrl: 'https://youtube.com',
        onWebViewCreated: (WebViewController webViewController) {
          controller = webViewController;
        },
      ),
    );

    expect(controller, isNotNull);
    await controller!.goForward();
    verify(mockWebViewPlatformController.goForward());
  });

  testWidgets('Current URL', (WidgetTester tester) async {
    when(mockWebViewPlatformController.currentUrl())
        .thenAnswer((_) => Future<String>.value('https://youtube.com'));

    WebViewController? controller;
    await tester.pumpWidget(
      WebView(
        onWebViewCreated: (WebViewController webViewController) {
          controller = webViewController;
        },
      ),
    );

    expect(controller, isNotNull);
    expect(await controller!.currentUrl(), 'https://youtube.com');
  });

  testWidgets('Reload url', (WidgetTester tester) async {
    late WebViewController controller;
    await tester.pumpWidget(
      WebView(
        initialUrl: 'https://flutter.io',
        onWebViewCreated: (WebViewController webViewController) {
          controller = webViewController;
        },
      ),
    );

    await controller.reload();
    verify(mockWebViewPlatformController.reload());
  });

  testWidgets('evaluate Javascript', (WidgetTester tester) async {
    when(mockWebViewPlatformController.evaluateJavascript('fake js string'))
        .thenAnswer((_) => Future<String>.value('fake js string'));

    late WebViewController controller;
    await tester.pumpWidget(
      WebView(
        initialUrl: 'https://flutter.io',
        javascriptMode: JavascriptMode.unrestricted,
        onWebViewCreated: (WebViewController webViewController) {
          controller = webViewController;
        },
      ),
    );

    expect(
        // ignore: deprecated_member_use_from_same_package
        await controller.evaluateJavascript('fake js string'),
        'fake js string',
        reason: 'should get the argument');
  });

  testWidgets('evaluate Javascript with JavascriptMode disabled',
      (WidgetTester tester) async {
    late WebViewController controller;
    await tester.pumpWidget(
      WebView(
        initialUrl: 'https://flutter.io',
        javascriptMode: JavascriptMode.disabled,
        onWebViewCreated: (WebViewController webViewController) {
          controller = webViewController;
        },
      ),
    );
    expect(
      // ignore: deprecated_member_use_from_same_package
      () => controller.evaluateJavascript('fake js string'),
      throwsA(anything),
    );
  });

  testWidgets('runJavaScript', (WidgetTester tester) async {
    late WebViewController controller;
    await tester.pumpWidget(
      WebView(
        initialUrl: 'https://flutter.io',
        javascriptMode: JavascriptMode.unrestricted,
        onWebViewCreated: (WebViewController webViewController) {
          controller = webViewController;
        },
      ),
    );
    await controller.runJavascript('fake js string');
    verify(mockWebViewPlatformController.runJavascript('fake js string'));
  });

  testWidgets('runJavaScript with JavascriptMode disabled',
      (WidgetTester tester) async {
    late WebViewController controller;
    await tester.pumpWidget(
      WebView(
        initialUrl: 'https://flutter.io',
        javascriptMode: JavascriptMode.disabled,
        onWebViewCreated: (WebViewController webViewController) {
          controller = webViewController;
        },
      ),
    );
    expect(
      () => controller.runJavascript('fake js string'),
      throwsA(anything),
    );
  });

  testWidgets('runJavaScriptReturningResult', (WidgetTester tester) async {
    when(mockWebViewPlatformController
            .runJavascriptReturningResult('fake js string'))
        .thenAnswer((_) => Future<String>.value('fake js string'));

    late WebViewController controller;
    await tester.pumpWidget(
      WebView(
        initialUrl: 'https://flutter.io',
        javascriptMode: JavascriptMode.unrestricted,
        onWebViewCreated: (WebViewController webViewController) {
          controller = webViewController;
        },
      ),
    );
    expect(await controller.runJavascriptReturningResult('fake js string'),
        'fake js string',
        reason: 'should get the argument');
  });

  testWidgets('runJavaScriptReturningResult with JavascriptMode disabled',
      (WidgetTester tester) async {
    late WebViewController controller;
    await tester.pumpWidget(
      WebView(
        initialUrl: 'https://flutter.io',
        javascriptMode: JavascriptMode.disabled,
        onWebViewCreated: (WebViewController webViewController) {
          controller = webViewController;
        },
      ),
    );
    expect(
      () => controller.runJavascriptReturningResult('fake js string'),
      throwsA(anything),
    );
  });

  testWidgets('Cookies can be cleared once', (WidgetTester tester) async {
    await tester.pumpWidget(
      const WebView(
        initialUrl: 'https://flutter.io',
      ),
    );
    final CookieManager cookieManager = CookieManager();
    final bool hasCookies = await cookieManager.clearCookies();
    expect(hasCookies, true);
  });

  testWidgets('Cookies can be set', (WidgetTester tester) async {
    const WebViewCookie cookie =
        WebViewCookie(name: 'foo', value: 'bar', domain: 'flutter.dev');

    await tester.pumpWidget(
      const WebView(
        initialUrl: 'https://flutter.io',
      ),
    );
    final CookieManager cookieManager = CookieManager();
    await cookieManager.setCookie(cookie);
    expect(mockWebViewCookieManagerPlatform.setCookieCalls,
        <WebViewCookie>[cookie]);
  });

  testWidgets('Initial JavaScript channels', (WidgetTester tester) async {
    await tester.pumpWidget(
      WebView(
        initialUrl: 'https://youtube.com',
        javascriptChannels: <JavascriptChannel>{
          JavascriptChannel(
              name: 'Tts', onMessageReceived: (JavascriptMessage msg) {}),
          JavascriptChannel(
              name: 'Alarm', onMessageReceived: (JavascriptMessage msg) {}),
        },
      ),
    );

    final CreationParams params = captureBuildArgs(
      mockWebViewPlatform,
      creationParams: true,
    ).single as CreationParams;

    expect(params.javascriptChannelNames,
        unorderedEquals(<String>['Tts', 'Alarm']));
  });

  test('Only valid JavaScript channel names are allowed', () {
    void noOp(JavascriptMessage msg) {}
    JavascriptChannel(name: 'Tts1', onMessageReceived: noOp);
    JavascriptChannel(name: '_Alarm', onMessageReceived: noOp);
    JavascriptChannel(name: 'foo_bar_', onMessageReceived: noOp);

    VoidCallback createChannel(String name) {
      return () {
        JavascriptChannel(name: name, onMessageReceived: noOp);
      };
    }

    expect(createChannel('1Alarm'), throwsAssertionError);
    expect(createChannel('foo.bar'), throwsAssertionError);
    expect(createChannel(''), throwsAssertionError);
  });

  testWidgets('Unique JavaScript channel names are required',
      (WidgetTester tester) async {
    await tester.pumpWidget(
      WebView(
        initialUrl: 'https://youtube.com',
        javascriptChannels: <JavascriptChannel>{
          JavascriptChannel(
              name: 'Alarm', onMessageReceived: (JavascriptMessage msg) {}),
          JavascriptChannel(
              name: 'Alarm', onMessageReceived: (JavascriptMessage msg) {}),
        },
      ),
    );
    expect(tester.takeException(), isNot(null));
  });

  testWidgets('JavaScript channels update', (WidgetTester tester) async {
    await tester.pumpWidget(
      WebView(
        initialUrl: 'https://youtube.com',
        javascriptChannels: <JavascriptChannel>{
          JavascriptChannel(
              name: 'Tts', onMessageReceived: (JavascriptMessage msg) {}),
          JavascriptChannel(
              name: 'Alarm', onMessageReceived: (JavascriptMessage msg) {}),
        },
      ),
    );

    await tester.pumpWidget(
      WebView(
        initialUrl: 'https://youtube.com',
        javascriptChannels: <JavascriptChannel>{
          JavascriptChannel(
              name: 'Tts', onMessageReceived: (JavascriptMessage msg) {}),
          JavascriptChannel(
              name: 'Alarm2', onMessageReceived: (JavascriptMessage msg) {}),
          JavascriptChannel(
              name: 'Alarm3', onMessageReceived: (JavascriptMessage msg) {}),
        },
      ),
    );

    final JavascriptChannelRegistry channelRegistry = captureBuildArgs(
      mockWebViewPlatform,
      javascriptChannelRegistry: true,
    ).first as JavascriptChannelRegistry;

    expect(
      channelRegistry.channels.keys,
      unorderedEquals(<String>['Tts', 'Alarm2', 'Alarm3']),
    );
  });

  testWidgets('Remove all JavaScript channels and then add',
      (WidgetTester tester) async {
    // This covers a specific bug we had where after updating javascriptChannels to null,
    // updating it again with a subset of the previously registered channels fails as the
    // widget's cache of current channel wasn't properly updated when updating javascriptChannels to
    // null.
    await tester.pumpWidget(
      WebView(
        initialUrl: 'https://youtube.com',
        javascriptChannels: <JavascriptChannel>{
          JavascriptChannel(
              name: 'Tts', onMessageReceived: (JavascriptMessage msg) {}),
        },
      ),
    );

    await tester.pumpWidget(
      const WebView(
        initialUrl: 'https://youtube.com',
      ),
    );

    await tester.pumpWidget(
      WebView(
        initialUrl: 'https://youtube.com',
        javascriptChannels: <JavascriptChannel>{
          JavascriptChannel(
              name: 'Tts', onMessageReceived: (JavascriptMessage msg) {}),
        },
      ),
    );

    final JavascriptChannelRegistry channelRegistry = captureBuildArgs(
      mockWebViewPlatform,
      javascriptChannelRegistry: true,
    ).last as JavascriptChannelRegistry;

    expect(channelRegistry.channels.keys, unorderedEquals(<String>['Tts']));
  });

  testWidgets('JavaScript channel messages', (WidgetTester tester) async {
    final List<String> ttsMessagesReceived = <String>[];
    final List<String> alarmMessagesReceived = <String>[];
    await tester.pumpWidget(
      WebView(
        initialUrl: 'https://youtube.com',
        javascriptChannels: <JavascriptChannel>{
          JavascriptChannel(
              name: 'Tts',
              onMessageReceived: (JavascriptMessage msg) {
                ttsMessagesReceived.add(msg.message);
              }),
          JavascriptChannel(
              name: 'Alarm',
              onMessageReceived: (JavascriptMessage msg) {
                alarmMessagesReceived.add(msg.message);
              }),
        },
      ),
    );

    final JavascriptChannelRegistry channelRegistry = captureBuildArgs(
      mockWebViewPlatform,
      javascriptChannelRegistry: true,
    ).single as JavascriptChannelRegistry;

    expect(ttsMessagesReceived, isEmpty);
    expect(alarmMessagesReceived, isEmpty);

    channelRegistry.onJavascriptChannelMessage('Tts', 'Hello');
    channelRegistry.onJavascriptChannelMessage('Tts', 'World');

    expect(ttsMessagesReceived, <String>['Hello', 'World']);
  });

  group('$PageStartedCallback', () {
    testWidgets('onPageStarted is not null', (WidgetTester tester) async {
      String? returnedUrl;

      await tester.pumpWidget(WebView(
        initialUrl: 'https://youtube.com',
        onPageStarted: (String url) {
          returnedUrl = url;
        },
      ));

      final WebViewPlatformCallbacksHandler handler = captureBuildArgs(
        mockWebViewPlatform,
        webViewPlatformCallbacksHandler: true,
      ).single as WebViewPlatformCallbacksHandler;

      handler.onPageStarted('https://youtube.com');

      expect(returnedUrl, 'https://youtube.com');
    });

    testWidgets('onPageStarted is null', (WidgetTester tester) async {
      await tester.pumpWidget(const WebView(
        initialUrl: 'https://youtube.com',
        onPageStarted: null,
      ));

      final WebViewPlatformCallbacksHandler handler = captureBuildArgs(
        mockWebViewPlatform,
        webViewPlatformCallbacksHandler: true,
      ).single as WebViewPlatformCallbacksHandler;

      // The platform side will always invoke a call for onPageStarted. This is
      // to test that it does not crash on a null callback.
      handler.onPageStarted('https://youtube.com');
    });

    testWidgets('onPageStarted changed', (WidgetTester tester) async {
      String? returnedUrl;

      await tester.pumpWidget(WebView(
        initialUrl: 'https://youtube.com',
        onPageStarted: (String url) {},
      ));

      await tester.pumpWidget(WebView(
        initialUrl: 'https://youtube.com',
        onPageStarted: (String url) {
          returnedUrl = url;
        },
      ));

      final WebViewPlatformCallbacksHandler handler = captureBuildArgs(
        mockWebViewPlatform,
        webViewPlatformCallbacksHandler: true,
      ).last as WebViewPlatformCallbacksHandler;
      handler.onPageStarted('https://youtube.com');

      expect(returnedUrl, 'https://youtube.com');
    });
  });

  group('$PageFinishedCallback', () {
    testWidgets('onPageFinished is not null', (WidgetTester tester) async {
      String? returnedUrl;

      await tester.pumpWidget(WebView(
        initialUrl: 'https://youtube.com',
        onPageFinished: (String url) {
          returnedUrl = url;
        },
      ));

      final WebViewPlatformCallbacksHandler handler = captureBuildArgs(
        mockWebViewPlatform,
        webViewPlatformCallbacksHandler: true,
      ).single as WebViewPlatformCallbacksHandler;
      handler.onPageFinished('https://youtube.com');

      expect(returnedUrl, 'https://youtube.com');
    });

    testWidgets('onPageFinished is null', (WidgetTester tester) async {
      await tester.pumpWidget(const WebView(
        initialUrl: 'https://youtube.com',
        onPageFinished: null,
      ));

      final WebViewPlatformCallbacksHandler handler = captureBuildArgs(
        mockWebViewPlatform,
        webViewPlatformCallbacksHandler: true,
      ).single as WebViewPlatformCallbacksHandler;
      // The platform side will always invoke a call for onPageFinished. This is
      // to test that it does not crash on a null callback.
      handler.onPageFinished('https://youtube.com');
    });

    testWidgets('onPageFinished changed', (WidgetTester tester) async {
      String? returnedUrl;

      await tester.pumpWidget(WebView(
        initialUrl: 'https://youtube.com',
        onPageFinished: (String url) {},
      ));

      await tester.pumpWidget(WebView(
        initialUrl: 'https://youtube.com',
        onPageFinished: (String url) {
          returnedUrl = url;
        },
      ));

      final WebViewPlatformCallbacksHandler handler = captureBuildArgs(
        mockWebViewPlatform,
        webViewPlatformCallbacksHandler: true,
      ).last as WebViewPlatformCallbacksHandler;
      handler.onPageFinished('https://youtube.com');

      expect(returnedUrl, 'https://youtube.com');
    });
  });

  group('$PageLoadingCallback', () {
    testWidgets('onLoadingProgress is not null', (WidgetTester tester) async {
      int? loadingProgress;

      await tester.pumpWidget(WebView(
        initialUrl: 'https://youtube.com',
        onProgress: (int progress) {
          loadingProgress = progress;
        },
      ));

      final WebViewPlatformCallbacksHandler handler = captureBuildArgs(
        mockWebViewPlatform,
        webViewPlatformCallbacksHandler: true,
      ).single as WebViewPlatformCallbacksHandler;
      handler.onProgress(50);

      expect(loadingProgress, 50);
    });

    testWidgets('onLoadingProgress is null', (WidgetTester tester) async {
      await tester.pumpWidget(const WebView(
        initialUrl: 'https://youtube.com',
        onProgress: null,
      ));

      final WebViewPlatformCallbacksHandler handler = captureBuildArgs(
        mockWebViewPlatform,
        webViewPlatformCallbacksHandler: true,
      ).single as WebViewPlatformCallbacksHandler;

      // This is to test that it does not crash on a null callback.
      handler.onProgress(50);
    });

    testWidgets('onLoadingProgress changed', (WidgetTester tester) async {
      int? loadingProgress;

      await tester.pumpWidget(WebView(
        initialUrl: 'https://youtube.com',
        onProgress: (int progress) {},
      ));

      await tester.pumpWidget(WebView(
        initialUrl: 'https://youtube.com',
        onProgress: (int progress) {
          loadingProgress = progress;
        },
      ));

      final WebViewPlatformCallbacksHandler handler = captureBuildArgs(
        mockWebViewPlatform,
        webViewPlatformCallbacksHandler: true,
      ).last as WebViewPlatformCallbacksHandler;
      handler.onProgress(50);

      expect(loadingProgress, 50);
    });
  });

  group('navigationDelegate', () {
    testWidgets('hasNavigationDelegate', (WidgetTester tester) async {
      await tester.pumpWidget(const WebView(
        initialUrl: 'https://youtube.com',
      ));

      final CreationParams params = captureBuildArgs(
        mockWebViewPlatform,
        creationParams: true,
      ).single as CreationParams;

      expect(params.webSettings!.hasNavigationDelegate, false);

      await tester.pumpWidget(WebView(
        initialUrl: 'https://youtube.com',
        navigationDelegate: (NavigationRequest r) =>
            NavigationDecision.navigate,
      ));

      final WebSettings updateSettings =
          verify(mockWebViewPlatformController.updateSettings(captureAny))
              .captured
              .single as WebSettings;

      expect(updateSettings.hasNavigationDelegate, true);
    });

    testWidgets('Block navigation', (WidgetTester tester) async {
      final List<NavigationRequest> navigationRequests = <NavigationRequest>[];

      await tester.pumpWidget(WebView(
          initialUrl: 'https://youtube.com',
          navigationDelegate: (NavigationRequest request) {
            navigationRequests.add(request);
            // Only allow navigating to https://flutter.dev
            return request.url == 'https://flutter.dev'
                ? NavigationDecision.navigate
                : NavigationDecision.prevent;
          }));

      final List<dynamic> args = captureBuildArgs(
        mockWebViewPlatform,
        creationParams: true,
        webViewPlatformCallbacksHandler: true,
      );

      final CreationParams params = args[0] as CreationParams;
      expect(params.webSettings!.hasNavigationDelegate, true);

      final WebViewPlatformCallbacksHandler handler =
          args[1] as WebViewPlatformCallbacksHandler;

      // The navigation delegate only allows navigation to https://flutter.dev
      // so we should still be in https://youtube.com.
      expect(
        handler.onNavigationRequest(
          url: 'https://www.google.com',
          isForMainFrame: true,
        ),
        completion(false),
      );

      expect(navigationRequests.length, 1);
      expect(navigationRequests[0].url, 'https://www.google.com');
      expect(navigationRequests[0].isForMainFrame, true);

      expect(
        handler.onNavigationRequest(
          url: 'https://flutter.dev',
          isForMainFrame: true,
        ),
        completion(true),
      );
    });
  });

  group('debuggingEnabled', () {
    testWidgets('enable debugging', (WidgetTester tester) async {
      await tester.pumpWidget(const WebView(
        debuggingEnabled: true,
      ));

      final CreationParams params = captureBuildArgs(
        mockWebViewPlatform,
        creationParams: true,
      ).single as CreationParams;

      expect(params.webSettings!.debuggingEnabled, true);
    });

    testWidgets('defaults to false', (WidgetTester tester) async {
      await tester.pumpWidget(const WebView());

      final CreationParams params = captureBuildArgs(
        mockWebViewPlatform,
        creationParams: true,
      ).single as CreationParams;

      expect(params.webSettings!.debuggingEnabled, false);
    });

    testWidgets('can be changed', (WidgetTester tester) async {
      final GlobalKey key = GlobalKey();
      await tester.pumpWidget(WebView(key: key));

      await tester.pumpWidget(WebView(
        key: key,
        debuggingEnabled: true,
      ));

      final WebSettings enabledSettings =
          verify(mockWebViewPlatformController.updateSettings(captureAny))
              .captured
              .last as WebSettings;
      expect(enabledSettings.debuggingEnabled, true);

      await tester.pumpWidget(WebView(
        key: key,
        debuggingEnabled: false,
      ));

      final WebSettings disabledSettings =
          verify(mockWebViewPlatformController.updateSettings(captureAny))
              .captured
              .last as WebSettings;
      expect(disabledSettings.debuggingEnabled, false);
    });
  });

  group('zoomEnabled', () {
    testWidgets('Enable zoom', (WidgetTester tester) async {
      await tester.pumpWidget(const WebView(
        zoomEnabled: true,
      ));

      final CreationParams params = captureBuildArgs(
        mockWebViewPlatform,
        creationParams: true,
      ).single as CreationParams;

      expect(params.webSettings!.zoomEnabled, isTrue);
    });

    testWidgets('defaults to true', (WidgetTester tester) async {
      await tester.pumpWidget(const WebView());

      final CreationParams params = captureBuildArgs(
        mockWebViewPlatform,
        creationParams: true,
      ).single as CreationParams;

      expect(params.webSettings!.zoomEnabled, isTrue);
    });

    testWidgets('can be changed', (WidgetTester tester) async {
      final GlobalKey key = GlobalKey();
      await tester.pumpWidget(WebView(key: key));

      await tester.pumpWidget(WebView(
        key: key,
        zoomEnabled: true,
      ));

      final WebSettings enabledSettings =
          verify(mockWebViewPlatformController.updateSettings(captureAny))
              .captured
              .last as WebSettings;
      // Zoom defaults to true, so no changes are made to settings.
      expect(enabledSettings.zoomEnabled, isNull);

      await tester.pumpWidget(WebView(
        key: key,
        zoomEnabled: false,
      ));

      final WebSettings disabledSettings =
          verify(mockWebViewPlatformController.updateSettings(captureAny))
              .captured
              .last as WebSettings;
      expect(disabledSettings.zoomEnabled, isFalse);
    });
  });

  group('Background color', () {
    testWidgets('Defaults to null', (WidgetTester tester) async {
      await tester.pumpWidget(const WebView());

      final CreationParams params = captureBuildArgs(
        mockWebViewPlatform,
        creationParams: true,
      ).single as CreationParams;

      expect(params.backgroundColor, null);
    });

    testWidgets('Can be transparent', (WidgetTester tester) async {
      const Color transparentColor = Color(0x00000000);

      await tester.pumpWidget(const WebView(
        backgroundColor: transparentColor,
      ));

      final CreationParams params = captureBuildArgs(
        mockWebViewPlatform,
        creationParams: true,
      ).single as CreationParams;

      expect(params.backgroundColor, transparentColor);
    });
  });

  group('Custom platform implementation', () {
    setUp(() {
      WebView.platform = MyWebViewPlatform();
    });
    tearDownAll(() {
      WebView.platform = null;
    });

    testWidgets('creation', (WidgetTester tester) async {
      await tester.pumpWidget(
        const WebView(
          initialUrl: 'https://youtube.com',
          gestureNavigationEnabled: true,
        ),
      );

      final MyWebViewPlatform builder = WebView.platform as MyWebViewPlatform;
      final MyWebViewPlatformController platform = builder.lastPlatformBuilt!;

      expect(
          platform.creationParams,
          MatchesCreationParams(CreationParams(
            initialUrl: 'https://youtube.com',
            webSettings: WebSettings(
              javascriptMode: JavascriptMode.disabled,
              hasNavigationDelegate: false,
              debuggingEnabled: false,
              userAgent: const WebSetting<String?>.of(null),
              gestureNavigationEnabled: true,
              zoomEnabled: true,
            ),
          )));
    });

    testWidgets('loadUrl', (WidgetTester tester) async {
      late WebViewController controller;
      await tester.pumpWidget(
        WebView(
          initialUrl: 'https://youtube.com',
          onWebViewCreated: (WebViewController webViewController) {
            controller = webViewController;
          },
        ),
      );

      final MyWebViewPlatform builder = WebView.platform as MyWebViewPlatform;
      final MyWebViewPlatformController platform = builder.lastPlatformBuilt!;

      final Map<String, String> headers = <String, String>{
        'header': 'value',
      };

      await controller.loadUrl('https://google.com', headers: headers);

      expect(platform.lastUrlLoaded, 'https://google.com');
      expect(platform.lastRequestHeaders, headers);
    });
  });

  testWidgets('Set UserAgent', (WidgetTester tester) async {
    await tester.pumpWidget(const WebView(
      initialUrl: 'https://youtube.com',
      javascriptMode: JavascriptMode.unrestricted,
    ));

    final CreationParams params = captureBuildArgs(
      mockWebViewPlatform,
      creationParams: true,
    ).single as CreationParams;

    expect(params.webSettings!.userAgent.value, isNull);

    await tester.pumpWidget(const WebView(
      initialUrl: 'https://youtube.com',
      javascriptMode: JavascriptMode.unrestricted,
      userAgent: 'UA',
    ));

    final WebSettings settings =
        verify(mockWebViewPlatformController.updateSettings(captureAny))
            .captured
            .last as WebSettings;
    expect(settings.userAgent.value, 'UA');
  });
}

List<dynamic> captureBuildArgs(
  MockWebViewPlatform mockWebViewPlatform, {
  bool context = false,
  bool creationParams = false,
  bool webViewPlatformCallbacksHandler = false,
  bool javascriptChannelRegistry = false,
  bool onWebViewPlatformCreated = false,
  bool gestureRecognizers = false,
}) {
  return verify(mockWebViewPlatform.build(
    context: context ? captureAnyNamed('context') : anyNamed('context'),
    creationParams: creationParams
        ? captureAnyNamed('creationParams')
        : anyNamed('creationParams'),
    webViewPlatformCallbacksHandler: webViewPlatformCallbacksHandler
        ? captureAnyNamed('webViewPlatformCallbacksHandler')
        : anyNamed('webViewPlatformCallbacksHandler'),
    javascriptChannelRegistry: javascriptChannelRegistry
        ? captureAnyNamed('javascriptChannelRegistry')
        : anyNamed('javascriptChannelRegistry'),
    onWebViewPlatformCreated: onWebViewPlatformCreated
        ? captureAnyNamed('onWebViewPlatformCreated')
        : anyNamed('onWebViewPlatformCreated'),
    gestureRecognizers: gestureRecognizers
        ? captureAnyNamed('gestureRecognizers')
        : anyNamed('gestureRecognizers'),
  )).captured;
}

// This Widget ensures that onWebViewPlatformCreated is only called once when
// making multiple calls to `WidgetTester.pumpWidget` with different parameters
// for the WebView.
class TestPlatformWebView extends StatefulWidget {
  const TestPlatformWebView({
    Key? key,
    required this.mockWebViewPlatformController,
    this.onWebViewPlatformCreated,
  }) : super(key: key);

  final MockWebViewPlatformController mockWebViewPlatformController;
  final WebViewPlatformCreatedCallback? onWebViewPlatformCreated;

  @override
  State<StatefulWidget> createState() => TestPlatformWebViewState();
}

class TestPlatformWebViewState extends State<TestPlatformWebView> {
  @override
  void initState() {
    super.initState();
    final WebViewPlatformCreatedCallback? onWebViewPlatformCreated =
        widget.onWebViewPlatformCreated;
    if (onWebViewPlatformCreated != null) {
      onWebViewPlatformCreated(widget.mockWebViewPlatformController);
    }
  }

  @override
  Widget build(BuildContext context) {
    return Container();
  }
}

class MyWebViewPlatform implements WebViewPlatform {
  MyWebViewPlatformController? lastPlatformBuilt;

  @override
  Widget build({
    BuildContext? context,
    CreationParams? creationParams,
    required WebViewPlatformCallbacksHandler webViewPlatformCallbacksHandler,
    required JavascriptChannelRegistry javascriptChannelRegistry,
    WebViewPlatformCreatedCallback? onWebViewPlatformCreated,
    Set<Factory<OneSequenceGestureRecognizer>>? gestureRecognizers,
  }) {
    assert(onWebViewPlatformCreated != null);
    lastPlatformBuilt = MyWebViewPlatformController(
        creationParams, gestureRecognizers, webViewPlatformCallbacksHandler);
    onWebViewPlatformCreated!(lastPlatformBuilt);
    return Container();
  }

  @override
  Future<bool> clearCookies() {
    return Future<bool>.sync(() => true);
  }
}

class MyWebViewPlatformController extends WebViewPlatformController {
  MyWebViewPlatformController(this.creationParams, this.gestureRecognizers,
      WebViewPlatformCallbacksHandler platformHandler)
      : super(platformHandler);

  CreationParams? creationParams;
  Set<Factory<OneSequenceGestureRecognizer>>? gestureRecognizers;

  String? lastUrlLoaded;
  Map<String, String>? lastRequestHeaders;

  @override
  Future<void> loadUrl(String url, Map<String, String>? headers) async {
    equals(1, 1);
    lastUrlLoaded = url;
    lastRequestHeaders = headers;
  }
}

class MatchesWebSettings extends Matcher {
  MatchesWebSettings(this._webSettings);

  final WebSettings? _webSettings;

  @override
  Description describe(Description description) =>
      description.add('$_webSettings');

  @override
  bool matches(
      covariant WebSettings webSettings, Map<dynamic, dynamic> matchState) {
    return _webSettings!.javascriptMode == webSettings.javascriptMode &&
        _webSettings!.hasNavigationDelegate ==
            webSettings.hasNavigationDelegate &&
        _webSettings!.debuggingEnabled == webSettings.debuggingEnabled &&
        _webSettings!.gestureNavigationEnabled ==
            webSettings.gestureNavigationEnabled &&
        _webSettings!.userAgent == webSettings.userAgent &&
        _webSettings!.zoomEnabled == webSettings.zoomEnabled;
  }
}

class MatchesCreationParams extends Matcher {
  MatchesCreationParams(this._creationParams);

  final CreationParams _creationParams;

  @override
  Description describe(Description description) =>
      description.add('$_creationParams');

  @override
  bool matches(covariant CreationParams creationParams,
      Map<dynamic, dynamic> matchState) {
    return _creationParams.initialUrl == creationParams.initialUrl &&
        MatchesWebSettings(_creationParams.webSettings)
            .matches(creationParams.webSettings!, matchState) &&
        orderedEquals(_creationParams.javascriptChannelNames)
            .matches(creationParams.javascriptChannelNames, matchState);
  }
}

class MockWebViewCookieManagerPlatform extends WebViewCookieManagerPlatform {
  List<WebViewCookie> setCookieCalls = <WebViewCookie>[];

  @override
  Future<bool> clearCookies() async => true;

  @override
  Future<void> setCookie(WebViewCookie cookie) async {
    setCookieCalls.add(cookie);
  }

  void reset() {
    setCookieCalls = <WebViewCookie>[];
  }
}
