// 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:async';
import 'dart:html';
import 'dart:ui';

import 'package:async/async.dart';
import 'package:camera_platform_interface/camera_platform_interface.dart';
import 'package:camera_web/camera_web.dart';
import 'package:camera_web/src/camera.dart';
import 'package:camera_web/src/camera_service.dart';
import 'package:camera_web/src/types/types.dart';
import 'package:flutter/services.dart';
import 'package:flutter/widgets.dart' as widgets;
import 'package:flutter_test/flutter_test.dart';
import 'package:integration_test/integration_test.dart';
import 'package:mocktail/mocktail.dart';

import 'helpers/helpers.dart';

void main() {
  IntegrationTestWidgetsFlutterBinding.ensureInitialized();

  group('CameraPlugin', () {
    const cameraId = 0;

    late Window window;
    late Navigator navigator;
    late MediaDevices mediaDevices;
    late VideoElement videoElement;
    late Screen screen;
    late ScreenOrientation screenOrientation;
    late Document document;
    late Element documentElement;

    late CameraService cameraService;

    setUp(() async {
      window = MockWindow();
      navigator = MockNavigator();
      mediaDevices = MockMediaDevices();

      videoElement = getVideoElementWithBlankStream(Size(10, 10));

      when(() => window.navigator).thenReturn(navigator);
      when(() => navigator.mediaDevices).thenReturn(mediaDevices);

      screen = MockScreen();
      screenOrientation = MockScreenOrientation();

      when(() => screen.orientation).thenReturn(screenOrientation);
      when(() => window.screen).thenReturn(screen);

      document = MockDocument();
      documentElement = MockElement();

      when(() => document.documentElement).thenReturn(documentElement);
      when(() => window.document).thenReturn(document);

      cameraService = MockCameraService();

      when(
        () => cameraService.getMediaStreamForOptions(
          any(),
          cameraId: any(named: 'cameraId'),
        ),
      ).thenAnswer(
        (_) async => videoElement.captureStream(),
      );

      CameraPlatform.instance = CameraPlugin(
        cameraService: cameraService,
      )..window = window;
    });

    setUpAll(() {
      registerFallbackValue<MediaStreamTrack>(MockMediaStreamTrack());
      registerFallbackValue<CameraOptions>(MockCameraOptions());
      registerFallbackValue<FlashMode>(FlashMode.off);
    });

    testWidgets('CameraPlugin is the live instance', (tester) async {
      expect(CameraPlatform.instance, isA<CameraPlugin>());
    });

    group('availableCameras', () {
      setUp(() {
        when(
          () => cameraService.getFacingModeForVideoTrack(
            any(),
          ),
        ).thenReturn(null);

        when(mediaDevices.enumerateDevices).thenAnswer(
          (_) async => [],
        );
      });

      testWidgets('requests video and audio permissions', (tester) async {
        final _ = await CameraPlatform.instance.availableCameras();

        verify(
          () => cameraService.getMediaStreamForOptions(
            CameraOptions(
              audio: AudioConstraints(enabled: true),
            ),
          ),
        ).called(1);
      });

      testWidgets(
          'gets a video stream '
          'for a video input device', (tester) async {
        final videoDevice = FakeMediaDeviceInfo(
          '1',
          'Camera 1',
          MediaDeviceKind.videoInput,
        );

        when(mediaDevices.enumerateDevices).thenAnswer(
          (_) => Future.value([videoDevice]),
        );

        final _ = await CameraPlatform.instance.availableCameras();

        verify(
          () => cameraService.getMediaStreamForOptions(
            CameraOptions(
              video: VideoConstraints(
                deviceId: videoDevice.deviceId,
              ),
            ),
          ),
        ).called(1);
      });

      testWidgets(
          'does not get a video stream '
          'for the video input device '
          'with an empty device id', (tester) async {
        final videoDevice = FakeMediaDeviceInfo(
          '',
          'Camera 1',
          MediaDeviceKind.videoInput,
        );

        when(mediaDevices.enumerateDevices).thenAnswer(
          (_) => Future.value([videoDevice]),
        );

        final _ = await CameraPlatform.instance.availableCameras();

        verifyNever(
          () => cameraService.getMediaStreamForOptions(
            CameraOptions(
              video: VideoConstraints(
                deviceId: videoDevice.deviceId,
              ),
            ),
          ),
        );
      });

      testWidgets(
          'gets the facing mode '
          'from the first available video track '
          'of the video input device', (tester) async {
        final videoDevice = FakeMediaDeviceInfo(
          '1',
          'Camera 1',
          MediaDeviceKind.videoInput,
        );

        final videoStream =
            FakeMediaStream([MockMediaStreamTrack(), MockMediaStreamTrack()]);

        when(
          () => cameraService.getMediaStreamForOptions(
            CameraOptions(
              video: VideoConstraints(deviceId: videoDevice.deviceId),
            ),
          ),
        ).thenAnswer((_) => Future.value(videoStream));

        when(mediaDevices.enumerateDevices).thenAnswer(
          (_) => Future.value([videoDevice]),
        );

        final _ = await CameraPlatform.instance.availableCameras();

        verify(
          () => cameraService.getFacingModeForVideoTrack(
            videoStream.getVideoTracks().first,
          ),
        ).called(1);
      });

      testWidgets(
          'returns appropriate camera descriptions '
          'for multiple video devices '
          'based on video streams', (tester) async {
        final firstVideoDevice = FakeMediaDeviceInfo(
          '1',
          'Camera 1',
          MediaDeviceKind.videoInput,
        );

        final secondVideoDevice = FakeMediaDeviceInfo(
          '4',
          'Camera 4',
          MediaDeviceKind.videoInput,
        );

        // Create a video stream for the first video device.
        final firstVideoStream =
            FakeMediaStream([MockMediaStreamTrack(), MockMediaStreamTrack()]);

        // Create a video stream for the second video device.
        final secondVideoStream = FakeMediaStream([MockMediaStreamTrack()]);

        // Mock media devices to return two video input devices
        // and two audio devices.
        when(mediaDevices.enumerateDevices).thenAnswer(
          (_) => Future.value([
            firstVideoDevice,
            FakeMediaDeviceInfo(
              '2',
              'Audio Input 2',
              MediaDeviceKind.audioInput,
            ),
            FakeMediaDeviceInfo(
              '3',
              'Audio Output 3',
              MediaDeviceKind.audioOutput,
            ),
            secondVideoDevice,
          ]),
        );

        // Mock camera service to return the first video stream
        // for the first video device.
        when(
          () => cameraService.getMediaStreamForOptions(
            CameraOptions(
              video: VideoConstraints(deviceId: firstVideoDevice.deviceId),
            ),
          ),
        ).thenAnswer((_) => Future.value(firstVideoStream));

        // Mock camera service to return the second video stream
        // for the second video device.
        when(
          () => cameraService.getMediaStreamForOptions(
            CameraOptions(
              video: VideoConstraints(deviceId: secondVideoDevice.deviceId),
            ),
          ),
        ).thenAnswer((_) => Future.value(secondVideoStream));

        // Mock camera service to return a user facing mode
        // for the first video stream.
        when(
          () => cameraService.getFacingModeForVideoTrack(
            firstVideoStream.getVideoTracks().first,
          ),
        ).thenReturn('user');

        when(() => cameraService.mapFacingModeToLensDirection('user'))
            .thenReturn(CameraLensDirection.front);

        // Mock camera service to return an environment facing mode
        // for the second video stream.
        when(
          () => cameraService.getFacingModeForVideoTrack(
            secondVideoStream.getVideoTracks().first,
          ),
        ).thenReturn('environment');

        when(() => cameraService.mapFacingModeToLensDirection('environment'))
            .thenReturn(CameraLensDirection.back);

        final cameras = await CameraPlatform.instance.availableCameras();

        // Expect two cameras and ignore two audio devices.
        expect(
          cameras,
          equals([
            CameraDescription(
              name: firstVideoDevice.label!,
              lensDirection: CameraLensDirection.front,
              sensorOrientation: 0,
            ),
            CameraDescription(
              name: secondVideoDevice.label!,
              lensDirection: CameraLensDirection.back,
              sensorOrientation: 0,
            )
          ]),
        );
      });

      testWidgets(
          'sets camera metadata '
          'for the camera description', (tester) async {
        final videoDevice = FakeMediaDeviceInfo(
          '1',
          'Camera 1',
          MediaDeviceKind.videoInput,
        );

        final videoStream =
            FakeMediaStream([MockMediaStreamTrack(), MockMediaStreamTrack()]);

        when(mediaDevices.enumerateDevices).thenAnswer(
          (_) => Future.value([videoDevice]),
        );

        when(
          () => cameraService.getMediaStreamForOptions(
            CameraOptions(
              video: VideoConstraints(deviceId: videoDevice.deviceId),
            ),
          ),
        ).thenAnswer((_) => Future.value(videoStream));

        when(
          () => cameraService.getFacingModeForVideoTrack(
            videoStream.getVideoTracks().first,
          ),
        ).thenReturn('left');

        when(() => cameraService.mapFacingModeToLensDirection('left'))
            .thenReturn(CameraLensDirection.external);

        final camera = (await CameraPlatform.instance.availableCameras()).first;

        expect(
          (CameraPlatform.instance as CameraPlugin).camerasMetadata,
          equals({
            camera: CameraMetadata(
              deviceId: videoDevice.deviceId!,
              facingMode: 'left',
            )
          }),
        );
      });

      group('throws CameraException', () {
        testWidgets(
            'with notSupported error '
            'when there are no media devices', (tester) async {
          when(() => navigator.mediaDevices).thenReturn(null);

          expect(
            () => CameraPlatform.instance.availableCameras(),
            throwsA(
              isA<CameraException>().having(
                (e) => e.code,
                'code',
                CameraErrorCode.notSupported.toString(),
              ),
            ),
          );
        });

        testWidgets('when MediaDevices.enumerateDevices throws DomException',
            (tester) async {
          final exception = FakeDomException(DomException.UNKNOWN);

          when(mediaDevices.enumerateDevices).thenThrow(exception);

          expect(
            () => CameraPlatform.instance.availableCameras(),
            throwsA(
              isA<CameraException>().having(
                (e) => e.code,
                'code',
                exception.name,
              ),
            ),
          );
        });

        testWidgets(
            'when CameraService.getMediaStreamForOptions '
            'throws CameraWebException', (tester) async {
          final exception = CameraWebException(
            cameraId,
            CameraErrorCode.security,
            'description',
          );

          when(() => cameraService.getMediaStreamForOptions(any()))
              .thenThrow(exception);

          expect(
            () => CameraPlatform.instance.availableCameras(),
            throwsA(
              isA<CameraException>().having(
                (e) => e.code,
                'code',
                exception.code.toString(),
              ),
            ),
          );
        });

        testWidgets(
            'when CameraService.getMediaStreamForOptions '
            'throws PlatformException', (tester) async {
          final exception = PlatformException(
            code: CameraErrorCode.notSupported.toString(),
            message: 'message',
          );

          when(() => cameraService.getMediaStreamForOptions(any()))
              .thenThrow(exception);

          expect(
            () => CameraPlatform.instance.availableCameras(),
            throwsA(
              isA<CameraException>().having(
                (e) => e.code,
                'code',
                exception.code.toString(),
              ),
            ),
          );
        });
      });
    });

    group('createCamera', () {
      group('creates a camera', () {
        const ultraHighResolutionSize = Size(3840, 2160);
        const maxResolutionSize = Size(3840, 2160);

        final cameraDescription = CameraDescription(
          name: 'name',
          lensDirection: CameraLensDirection.front,
          sensorOrientation: 0,
        );

        final cameraMetadata = CameraMetadata(
          deviceId: 'deviceId',
          facingMode: 'user',
        );

        setUp(() {
          // Add metadata for the camera description.
          (CameraPlatform.instance as CameraPlugin)
              .camerasMetadata[cameraDescription] = cameraMetadata;

          when(
            () => cameraService.mapFacingModeToCameraType('user'),
          ).thenReturn(CameraType.user);
        });

        testWidgets('with appropriate options', (tester) async {
          when(
            () => cameraService
                .mapResolutionPresetToSize(ResolutionPreset.ultraHigh),
          ).thenReturn(ultraHighResolutionSize);

          final cameraId = await CameraPlatform.instance.createCamera(
            cameraDescription,
            ResolutionPreset.ultraHigh,
            enableAudio: true,
          );

          expect(
            (CameraPlatform.instance as CameraPlugin).cameras[cameraId],
            isA<Camera>()
                .having(
                  (camera) => camera.textureId,
                  'textureId',
                  cameraId,
                )
                .having(
                  (camera) => camera.options,
                  'options',
                  CameraOptions(
                    audio: AudioConstraints(enabled: true),
                    video: VideoConstraints(
                      facingMode: FacingModeConstraint(CameraType.user),
                      width: VideoSizeConstraint(
                        ideal: ultraHighResolutionSize.width.toInt(),
                      ),
                      height: VideoSizeConstraint(
                        ideal: ultraHighResolutionSize.height.toInt(),
                      ),
                      deviceId: cameraMetadata.deviceId,
                    ),
                  ),
                ),
          );
        });

        testWidgets(
            'with a max resolution preset '
            'and enabled audio set to false '
            'when no options are specified', (tester) async {
          when(
            () => cameraService.mapResolutionPresetToSize(ResolutionPreset.max),
          ).thenReturn(maxResolutionSize);

          final cameraId = await CameraPlatform.instance.createCamera(
            cameraDescription,
            null,
          );

          expect(
            (CameraPlatform.instance as CameraPlugin).cameras[cameraId],
            isA<Camera>().having(
              (camera) => camera.options,
              'options',
              CameraOptions(
                audio: AudioConstraints(enabled: false),
                video: VideoConstraints(
                  facingMode: FacingModeConstraint(CameraType.user),
                  width: VideoSizeConstraint(
                    ideal: maxResolutionSize.width.toInt(),
                  ),
                  height: VideoSizeConstraint(
                    ideal: maxResolutionSize.height.toInt(),
                  ),
                  deviceId: cameraMetadata.deviceId,
                ),
              ),
            ),
          );
        });
      });

      testWidgets(
          'throws CameraException '
          'with missingMetadata error '
          'if there is no metadata '
          'for the given camera description', (tester) async {
        expect(
          () => CameraPlatform.instance.createCamera(
            CameraDescription(
              name: 'name',
              lensDirection: CameraLensDirection.back,
              sensorOrientation: 0,
            ),
            ResolutionPreset.ultraHigh,
          ),
          throwsA(
            isA<CameraException>().having(
              (e) => e.code,
              'code',
              CameraErrorCode.missingMetadata.toString(),
            ),
          ),
        );
      });
    });

    group('initializeCamera', () {
      late Camera camera;
      late VideoElement videoElement;

      setUp(() {
        camera = MockCamera();
        videoElement = MockVideoElement();

        when(() => camera.videoElement).thenReturn(videoElement);
        when(() => videoElement.onError)
            .thenAnswer((_) => FakeElementStream(Stream.empty()));
        when(() => videoElement.onAbort)
            .thenAnswer((_) => FakeElementStream(Stream.empty()));
      });

      testWidgets('initializes and plays the camera', (tester) async {
        when(camera.getVideoSize).thenAnswer(
          (_) => Future.value(Size(10, 10)),
        );
        when(camera.initialize).thenAnswer((_) => Future.value());
        when(camera.play).thenAnswer((_) => Future.value());

        // Save the camera in the camera plugin.
        (CameraPlatform.instance as CameraPlugin).cameras[cameraId] = camera;

        await CameraPlatform.instance.initializeCamera(cameraId);

        verify(camera.initialize).called(1);
        verify(camera.play).called(1);
      });

      group('throws PlatformException', () {
        testWidgets(
            'with notFound error '
            'if the camera does not exist', (tester) async {
          expect(
            () => CameraPlatform.instance.initializeCamera(cameraId),
            throwsA(
              isA<PlatformException>().having(
                (e) => e.code,
                'code',
                CameraErrorCode.notFound.toString(),
              ),
            ),
          );
        });

        testWidgets('when camera throws CameraWebException', (tester) async {
          final exception = CameraWebException(
            cameraId,
            CameraErrorCode.permissionDenied,
            'description',
          );

          when(camera.initialize).thenThrow(exception);

          // Save the camera in the camera plugin.
          (CameraPlatform.instance as CameraPlugin).cameras[cameraId] = camera;

          expect(
            () => CameraPlatform.instance.initializeCamera(cameraId),
            throwsA(
              isA<PlatformException>().having(
                (e) => e.code,
                'code',
                exception.code.toString(),
              ),
            ),
          );
        });

        testWidgets('when camera throws DomException', (tester) async {
          final exception = FakeDomException(DomException.NOT_ALLOWED);

          when(camera.initialize).thenAnswer((_) => Future.value());
          when(camera.play).thenThrow(exception);

          // Save the camera in the camera plugin.
          (CameraPlatform.instance as CameraPlugin).cameras[cameraId] = camera;

          expect(
            () => CameraPlatform.instance.initializeCamera(cameraId),
            throwsA(
              isA<PlatformException>().having(
                (e) => e.code,
                'code',
                exception.name.toString(),
              ),
            ),
          );
        });
      });
    });

    group('lockCaptureOrientation', () {
      setUp(() {
        when(
          () => cameraService.mapDeviceOrientationToOrientationType(any()),
        ).thenReturn(OrientationType.portraitPrimary);
      });

      testWidgets(
          'requests full-screen mode '
          'on documentElement', (tester) async {
        await CameraPlatform.instance.lockCaptureOrientation(
          cameraId,
          DeviceOrientation.portraitUp,
        );

        verify(documentElement.requestFullscreen).called(1);
      });

      testWidgets(
          'locks the capture orientation '
          'based on the given device orientation', (tester) async {
        when(
          () => cameraService.mapDeviceOrientationToOrientationType(
            DeviceOrientation.landscapeRight,
          ),
        ).thenReturn(OrientationType.landscapeSecondary);

        await CameraPlatform.instance.lockCaptureOrientation(
          cameraId,
          DeviceOrientation.landscapeRight,
        );

        verify(
          () => cameraService.mapDeviceOrientationToOrientationType(
            DeviceOrientation.landscapeRight,
          ),
        ).called(1);

        verify(
          () => screenOrientation.lock(
            OrientationType.landscapeSecondary,
          ),
        ).called(1);
      });

      group('throws PlatformException', () {
        testWidgets(
            'with orientationNotSupported error '
            'when screen is not supported', (tester) async {
          when(() => window.screen).thenReturn(null);

          expect(
            () => CameraPlatform.instance.lockCaptureOrientation(
              cameraId,
              DeviceOrientation.portraitUp,
            ),
            throwsA(
              isA<PlatformException>().having(
                (e) => e.code,
                'code',
                CameraErrorCode.orientationNotSupported.toString(),
              ),
            ),
          );
        });

        testWidgets(
            'with orientationNotSupported error '
            'when screen orientation is not supported', (tester) async {
          when(() => screen.orientation).thenReturn(null);

          expect(
            () => CameraPlatform.instance.lockCaptureOrientation(
              cameraId,
              DeviceOrientation.portraitUp,
            ),
            throwsA(
              isA<PlatformException>().having(
                (e) => e.code,
                'code',
                CameraErrorCode.orientationNotSupported.toString(),
              ),
            ),
          );
        });

        testWidgets(
            'with orientationNotSupported error '
            'when documentElement is not available', (tester) async {
          when(() => document.documentElement).thenReturn(null);

          expect(
            () => CameraPlatform.instance.lockCaptureOrientation(
              cameraId,
              DeviceOrientation.portraitUp,
            ),
            throwsA(
              isA<PlatformException>().having(
                (e) => e.code,
                'code',
                CameraErrorCode.orientationNotSupported.toString(),
              ),
            ),
          );
        });

        testWidgets('when lock throws DomException', (tester) async {
          final exception = FakeDomException(DomException.NOT_ALLOWED);

          when(() => screenOrientation.lock(any())).thenThrow(exception);

          expect(
            () => CameraPlatform.instance.lockCaptureOrientation(
              cameraId,
              DeviceOrientation.portraitDown,
            ),
            throwsA(
              isA<PlatformException>().having(
                (e) => e.code,
                'code',
                exception.name,
              ),
            ),
          );
        });
      });
    });

    group('unlockCaptureOrientation', () {
      setUp(() {
        when(
          () => cameraService.mapDeviceOrientationToOrientationType(any()),
        ).thenReturn(OrientationType.portraitPrimary);
      });

      testWidgets('unlocks the capture orientation', (tester) async {
        await CameraPlatform.instance.unlockCaptureOrientation(
          cameraId,
        );

        verify(screenOrientation.unlock).called(1);
      });

      group('throws PlatformException', () {
        testWidgets(
            'with orientationNotSupported error '
            'when screen is not supported', (tester) async {
          when(() => window.screen).thenReturn(null);

          expect(
            () => CameraPlatform.instance.unlockCaptureOrientation(
              cameraId,
            ),
            throwsA(
              isA<PlatformException>().having(
                (e) => e.code,
                'code',
                CameraErrorCode.orientationNotSupported.toString(),
              ),
            ),
          );
        });

        testWidgets(
            'with orientationNotSupported error '
            'when screen orientation is not supported', (tester) async {
          when(() => screen.orientation).thenReturn(null);

          expect(
            () => CameraPlatform.instance.unlockCaptureOrientation(
              cameraId,
            ),
            throwsA(
              isA<PlatformException>().having(
                (e) => e.code,
                'code',
                CameraErrorCode.orientationNotSupported.toString(),
              ),
            ),
          );
        });

        testWidgets(
            'with orientationNotSupported error '
            'when documentElement is not available', (tester) async {
          when(() => document.documentElement).thenReturn(null);

          expect(
            () => CameraPlatform.instance.unlockCaptureOrientation(
              cameraId,
            ),
            throwsA(
              isA<PlatformException>().having(
                (e) => e.code,
                'code',
                CameraErrorCode.orientationNotSupported.toString(),
              ),
            ),
          );
        });

        testWidgets('when unlock throws DomException', (tester) async {
          final exception = FakeDomException(DomException.NOT_ALLOWED);

          when(screenOrientation.unlock).thenThrow(exception);

          expect(
            () => CameraPlatform.instance.unlockCaptureOrientation(
              cameraId,
            ),
            throwsA(
              isA<PlatformException>().having(
                (e) => e.code,
                'code',
                exception.name,
              ),
            ),
          );
        });
      });
    });

    group('takePicture', () {
      testWidgets('captures a picture', (tester) async {
        final camera = MockCamera();
        final capturedPicture = MockXFile();

        when(camera.takePicture)
            .thenAnswer((_) => Future.value(capturedPicture));

        // Save the camera in the camera plugin.
        (CameraPlatform.instance as CameraPlugin).cameras[cameraId] = camera;

        final picture = await CameraPlatform.instance.takePicture(cameraId);

        verify(camera.takePicture).called(1);

        expect(picture, equals(capturedPicture));
      });

      group('throws PlatformException', () {
        testWidgets(
            'with notFound error '
            'if the camera does not exist', (tester) async {
          expect(
            () => CameraPlatform.instance.takePicture(cameraId),
            throwsA(
              isA<PlatformException>().having(
                (e) => e.code,
                'code',
                CameraErrorCode.notFound.toString(),
              ),
            ),
          );
        });

        testWidgets('when takePicture throws DomException', (tester) async {
          final camera = MockCamera();
          final exception = FakeDomException(DomException.NOT_SUPPORTED);

          when(camera.takePicture).thenThrow(exception);

          // Save the camera in the camera plugin.
          (CameraPlatform.instance as CameraPlugin).cameras[cameraId] = camera;

          expect(
            () => CameraPlatform.instance.takePicture(cameraId),
            throwsA(
              isA<PlatformException>().having(
                (e) => e.code,
                'code',
                exception.name,
              ),
            ),
          );
        });

        testWidgets('when takePicture throws CameraWebException',
            (tester) async {
          final camera = MockCamera();
          final exception = CameraWebException(
            cameraId,
            CameraErrorCode.notStarted,
            'description',
          );

          when(camera.takePicture).thenThrow(exception);

          // Save the camera in the camera plugin.
          (CameraPlatform.instance as CameraPlugin).cameras[cameraId] = camera;

          expect(
            () => CameraPlatform.instance.takePicture(cameraId),
            throwsA(
              isA<PlatformException>().having(
                (e) => e.code,
                'code',
                exception.code.toString(),
              ),
            ),
          );
        });
      });
    });

    testWidgets('prepareForVideoRecording throws UnimplementedError',
        (tester) async {
      expect(
        () => CameraPlatform.instance.prepareForVideoRecording(),
        throwsUnimplementedError,
      );
    });

    testWidgets('startVideoRecording throws UnimplementedError',
        (tester) async {
      expect(
        () => CameraPlatform.instance.startVideoRecording(cameraId),
        throwsUnimplementedError,
      );
    });

    testWidgets('stopVideoRecording throws UnimplementedError', (tester) async {
      expect(
        () => CameraPlatform.instance.stopVideoRecording(cameraId),
        throwsUnimplementedError,
      );
    });

    testWidgets('pauseVideoRecording throws UnimplementedError',
        (tester) async {
      expect(
        () => CameraPlatform.instance.pauseVideoRecording(cameraId),
        throwsUnimplementedError,
      );
    });

    testWidgets('resumeVideoRecording throws UnimplementedError',
        (tester) async {
      expect(
        () => CameraPlatform.instance.resumeVideoRecording(cameraId),
        throwsUnimplementedError,
      );
    });

    group('setFlashMode', () {
      testWidgets('calls setFlashMode on the camera', (tester) async {
        final camera = MockCamera();
        const flashMode = FlashMode.always;

        // Save the camera in the camera plugin.
        (CameraPlatform.instance as CameraPlugin).cameras[cameraId] = camera;

        await CameraPlatform.instance.setFlashMode(
          cameraId,
          flashMode,
        );

        verify(() => camera.setFlashMode(flashMode)).called(1);
      });

      group('throws PlatformException', () {
        testWidgets(
            'with notFound error '
            'if the camera does not exist', (tester) async {
          expect(
            () => CameraPlatform.instance.setFlashMode(
              cameraId,
              FlashMode.always,
            ),
            throwsA(
              isA<PlatformException>().having(
                (e) => e.code,
                'code',
                CameraErrorCode.notFound.toString(),
              ),
            ),
          );
        });

        testWidgets('when setFlashMode throws DomException', (tester) async {
          final camera = MockCamera();
          final exception = FakeDomException(DomException.NOT_SUPPORTED);

          when(() => camera.setFlashMode(any())).thenThrow(exception);

          // Save the camera in the camera plugin.
          (CameraPlatform.instance as CameraPlugin).cameras[cameraId] = camera;

          expect(
            () => CameraPlatform.instance.setFlashMode(
              cameraId,
              FlashMode.always,
            ),
            throwsA(
              isA<PlatformException>().having(
                (e) => e.code,
                'code',
                exception.name,
              ),
            ),
          );
        });

        testWidgets('when setFlashMode throws CameraWebException',
            (tester) async {
          final camera = MockCamera();
          final exception = CameraWebException(
            cameraId,
            CameraErrorCode.notStarted,
            'description',
          );

          when(() => camera.setFlashMode(any())).thenThrow(exception);

          // Save the camera in the camera plugin.
          (CameraPlatform.instance as CameraPlugin).cameras[cameraId] = camera;

          expect(
            () => CameraPlatform.instance.setFlashMode(
              cameraId,
              FlashMode.torch,
            ),
            throwsA(
              isA<PlatformException>().having(
                (e) => e.code,
                'code',
                exception.code.toString(),
              ),
            ),
          );
        });
      });
    });

    testWidgets('setExposureMode throws UnimplementedError', (tester) async {
      expect(
        () => CameraPlatform.instance.setExposureMode(
          cameraId,
          ExposureMode.auto,
        ),
        throwsUnimplementedError,
      );
    });

    testWidgets('setExposurePoint throws UnimplementedError', (tester) async {
      expect(
        () => CameraPlatform.instance.setExposurePoint(
          cameraId,
          const Point(0, 0),
        ),
        throwsUnimplementedError,
      );
    });

    testWidgets('getMinExposureOffset throws UnimplementedError',
        (tester) async {
      expect(
        () => CameraPlatform.instance.getMinExposureOffset(cameraId),
        throwsUnimplementedError,
      );
    });

    testWidgets('getMaxExposureOffset throws UnimplementedError',
        (tester) async {
      expect(
        () => CameraPlatform.instance.getMaxExposureOffset(cameraId),
        throwsUnimplementedError,
      );
    });

    testWidgets('getExposureOffsetStepSize throws UnimplementedError',
        (tester) async {
      expect(
        () => CameraPlatform.instance.getExposureOffsetStepSize(cameraId),
        throwsUnimplementedError,
      );
    });

    testWidgets('setExposureOffset throws UnimplementedError', (tester) async {
      expect(
        () => CameraPlatform.instance.setExposureOffset(
          cameraId,
          0,
        ),
        throwsUnimplementedError,
      );
    });

    testWidgets('setFocusMode throws UnimplementedError', (tester) async {
      expect(
        () => CameraPlatform.instance.setFocusMode(
          cameraId,
          FocusMode.auto,
        ),
        throwsUnimplementedError,
      );
    });

    testWidgets('setFocusPoint throws UnimplementedError', (tester) async {
      expect(
        () => CameraPlatform.instance.setFocusPoint(
          cameraId,
          const Point(0, 0),
        ),
        throwsUnimplementedError,
      );
    });

    group('getMaxZoomLevel', () {
      testWidgets('calls getMaxZoomLevel on the camera', (tester) async {
        final camera = MockCamera();
        const maximumZoomLevel = 100.0;

        when(camera.getMaxZoomLevel).thenReturn(maximumZoomLevel);

        // Save the camera in the camera plugin.
        (CameraPlatform.instance as CameraPlugin).cameras[cameraId] = camera;

        expect(
          await CameraPlatform.instance.getMaxZoomLevel(
            cameraId,
          ),
          equals(maximumZoomLevel),
        );

        verify(camera.getMaxZoomLevel).called(1);
      });

      group('throws PlatformException', () {
        testWidgets(
            'with notFound error '
            'if the camera does not exist', (tester) async {
          expect(
            () async => await CameraPlatform.instance.getMaxZoomLevel(
              cameraId,
            ),
            throwsA(
              isA<PlatformException>().having(
                (e) => e.code,
                'code',
                CameraErrorCode.notFound.toString(),
              ),
            ),
          );
        });

        testWidgets('when getMaxZoomLevel throws DomException', (tester) async {
          final camera = MockCamera();
          final exception = FakeDomException(DomException.NOT_SUPPORTED);

          when(camera.getMaxZoomLevel).thenThrow(exception);

          // Save the camera in the camera plugin.
          (CameraPlatform.instance as CameraPlugin).cameras[cameraId] = camera;

          expect(
            () async => await CameraPlatform.instance.getMaxZoomLevel(
              cameraId,
            ),
            throwsA(
              isA<PlatformException>().having(
                (e) => e.code,
                'code',
                exception.name,
              ),
            ),
          );
        });

        testWidgets('when getMaxZoomLevel throws CameraWebException',
            (tester) async {
          final camera = MockCamera();
          final exception = CameraWebException(
            cameraId,
            CameraErrorCode.notStarted,
            'description',
          );

          when(camera.getMaxZoomLevel).thenThrow(exception);

          // Save the camera in the camera plugin.
          (CameraPlatform.instance as CameraPlugin).cameras[cameraId] = camera;

          expect(
            () async => await CameraPlatform.instance.getMaxZoomLevel(
              cameraId,
            ),
            throwsA(
              isA<PlatformException>().having(
                (e) => e.code,
                'code',
                exception.code.toString(),
              ),
            ),
          );
        });
      });
    });

    group('getMinZoomLevel', () {
      testWidgets('calls getMinZoomLevel on the camera', (tester) async {
        final camera = MockCamera();
        const minimumZoomLevel = 100.0;

        when(camera.getMinZoomLevel).thenReturn(minimumZoomLevel);

        // Save the camera in the camera plugin.
        (CameraPlatform.instance as CameraPlugin).cameras[cameraId] = camera;

        expect(
          await CameraPlatform.instance.getMinZoomLevel(
            cameraId,
          ),
          equals(minimumZoomLevel),
        );

        verify(camera.getMinZoomLevel).called(1);
      });

      group('throws PlatformException', () {
        testWidgets(
            'with notFound error '
            'if the camera does not exist', (tester) async {
          expect(
            () async => await CameraPlatform.instance.getMinZoomLevel(
              cameraId,
            ),
            throwsA(
              isA<PlatformException>().having(
                (e) => e.code,
                'code',
                CameraErrorCode.notFound.toString(),
              ),
            ),
          );
        });

        testWidgets('when getMinZoomLevel throws DomException', (tester) async {
          final camera = MockCamera();
          final exception = FakeDomException(DomException.NOT_SUPPORTED);

          when(camera.getMinZoomLevel).thenThrow(exception);

          // Save the camera in the camera plugin.
          (CameraPlatform.instance as CameraPlugin).cameras[cameraId] = camera;

          expect(
            () async => await CameraPlatform.instance.getMinZoomLevel(
              cameraId,
            ),
            throwsA(
              isA<PlatformException>().having(
                (e) => e.code,
                'code',
                exception.name,
              ),
            ),
          );
        });

        testWidgets('when getMinZoomLevel throws CameraWebException',
            (tester) async {
          final camera = MockCamera();
          final exception = CameraWebException(
            cameraId,
            CameraErrorCode.notStarted,
            'description',
          );

          when(camera.getMinZoomLevel).thenThrow(exception);

          // Save the camera in the camera plugin.
          (CameraPlatform.instance as CameraPlugin).cameras[cameraId] = camera;

          expect(
            () async => await CameraPlatform.instance.getMinZoomLevel(
              cameraId,
            ),
            throwsA(
              isA<PlatformException>().having(
                (e) => e.code,
                'code',
                exception.code.toString(),
              ),
            ),
          );
        });
      });
    });

    group('setZoomLevel', () {
      testWidgets('calls setZoomLevel on the camera', (tester) async {
        final camera = MockCamera();

        // Save the camera in the camera plugin.
        (CameraPlatform.instance as CameraPlugin).cameras[cameraId] = camera;

        const zoom = 100.0;

        await CameraPlatform.instance.setZoomLevel(cameraId, zoom);

        verify(() => camera.setZoomLevel(zoom)).called(1);
      });

      group('throws CameraException', () {
        testWidgets(
            'with notFound error '
            'if the camera does not exist', (tester) async {
          expect(
            () async => await CameraPlatform.instance.setZoomLevel(
              cameraId,
              100.0,
            ),
            throwsA(
              isA<CameraException>().having(
                (e) => e.code,
                'code',
                CameraErrorCode.notFound.toString(),
              ),
            ),
          );
        });

        testWidgets('when setZoomLevel throws DomException', (tester) async {
          final camera = MockCamera();
          final exception = FakeDomException(DomException.NOT_SUPPORTED);

          when(() => camera.setZoomLevel(any())).thenThrow(exception);

          // Save the camera in the camera plugin.
          (CameraPlatform.instance as CameraPlugin).cameras[cameraId] = camera;

          expect(
            () async => await CameraPlatform.instance.setZoomLevel(
              cameraId,
              100.0,
            ),
            throwsA(
              isA<CameraException>().having(
                (e) => e.code,
                'code',
                exception.name,
              ),
            ),
          );
        });

        testWidgets('when setZoomLevel throws PlatformException',
            (tester) async {
          final camera = MockCamera();
          final exception = PlatformException(
            code: CameraErrorCode.notSupported.toString(),
            message: 'message',
          );

          when(() => camera.setZoomLevel(any())).thenThrow(exception);

          // Save the camera in the camera plugin.
          (CameraPlatform.instance as CameraPlugin).cameras[cameraId] = camera;

          expect(
            () async => await CameraPlatform.instance.setZoomLevel(
              cameraId,
              100.0,
            ),
            throwsA(
              isA<CameraException>().having(
                (e) => e.code,
                'code',
                exception.code,
              ),
            ),
          );
        });

        testWidgets('when setZoomLevel throws CameraWebException',
            (tester) async {
          final camera = MockCamera();
          final exception = CameraWebException(
            cameraId,
            CameraErrorCode.notStarted,
            'description',
          );

          when(() => camera.setZoomLevel(any())).thenThrow(exception);

          // Save the camera in the camera plugin.
          (CameraPlatform.instance as CameraPlugin).cameras[cameraId] = camera;

          expect(
            () async => await CameraPlatform.instance.setZoomLevel(
              cameraId,
              100.0,
            ),
            throwsA(
              isA<CameraException>().having(
                (e) => e.code,
                'code',
                exception.code.toString(),
              ),
            ),
          );
        });
      });
    });

    group('pausePreview', () {
      testWidgets('calls pause on the camera', (tester) async {
        final camera = MockCamera();

        // Save the camera in the camera plugin.
        (CameraPlatform.instance as CameraPlugin).cameras[cameraId] = camera;

        await CameraPlatform.instance.pausePreview(cameraId);

        verify(camera.pause).called(1);
      });

      group('throws PlatformException', () {
        testWidgets(
            'with notFound error '
            'if the camera does not exist', (tester) async {
          expect(
            () async => await CameraPlatform.instance.pausePreview(cameraId),
            throwsA(
              isA<PlatformException>().having(
                (e) => e.code,
                'code',
                CameraErrorCode.notFound.toString(),
              ),
            ),
          );
        });

        testWidgets('when pause throws DomException', (tester) async {
          final camera = MockCamera();
          final exception = FakeDomException(DomException.NOT_SUPPORTED);

          when(camera.pause).thenThrow(exception);

          // Save the camera in the camera plugin.
          (CameraPlatform.instance as CameraPlugin).cameras[cameraId] = camera;

          expect(
            () async => await CameraPlatform.instance.pausePreview(cameraId),
            throwsA(
              isA<PlatformException>().having(
                (e) => e.code,
                'code',
                exception.name,
              ),
            ),
          );
        });
      });
    });

    group('resumePreview', () {
      testWidgets('calls play on the camera', (tester) async {
        final camera = MockCamera();

        when(camera.play).thenAnswer((_) async => {});

        // Save the camera in the camera plugin.
        (CameraPlatform.instance as CameraPlugin).cameras[cameraId] = camera;

        await CameraPlatform.instance.resumePreview(cameraId);

        verify(camera.play).called(1);
      });

      group('throws PlatformException', () {
        testWidgets(
            'with notFound error '
            'if the camera does not exist', (tester) async {
          expect(
            () async => await CameraPlatform.instance.resumePreview(cameraId),
            throwsA(
              isA<PlatformException>().having(
                (e) => e.code,
                'code',
                CameraErrorCode.notFound.toString(),
              ),
            ),
          );
        });

        testWidgets('when play throws DomException', (tester) async {
          final camera = MockCamera();
          final exception = FakeDomException(DomException.NOT_SUPPORTED);

          when(camera.play).thenThrow(exception);

          // Save the camera in the camera plugin.
          (CameraPlatform.instance as CameraPlugin).cameras[cameraId] = camera;

          expect(
            () async => await CameraPlatform.instance.resumePreview(cameraId),
            throwsA(
              isA<PlatformException>().having(
                (e) => e.code,
                'code',
                exception.name,
              ),
            ),
          );
        });

        testWidgets('when play throws CameraWebException', (tester) async {
          final camera = MockCamera();
          final exception = CameraWebException(
            cameraId,
            CameraErrorCode.unknown,
            'description',
          );

          when(camera.play).thenThrow(exception);

          // Save the camera in the camera plugin.
          (CameraPlatform.instance as CameraPlugin).cameras[cameraId] = camera;

          expect(
            () async => await CameraPlatform.instance.resumePreview(cameraId),
            throwsA(
              isA<PlatformException>().having(
                (e) => e.code,
                'code',
                exception.code.toString(),
              ),
            ),
          );
        });
      });
    });

    testWidgets(
        'buildPreview returns an HtmlElementView '
        'with an appropriate view type', (tester) async {
      final camera = Camera(
        textureId: cameraId,
        cameraService: cameraService,
      );

      // Save the camera in the camera plugin.
      (CameraPlatform.instance as CameraPlugin).cameras[cameraId] = camera;

      expect(
        CameraPlatform.instance.buildPreview(cameraId),
        isA<widgets.HtmlElementView>().having(
          (view) => view.viewType,
          'viewType',
          camera.getViewType(),
        ),
      );
    });

    group('dispose', () {
      testWidgets('disposes the correct camera', (tester) async {
        const firstCameraId = 0;
        const secondCameraId = 1;

        final firstCamera = MockCamera();
        final secondCamera = MockCamera();

        when(firstCamera.dispose).thenAnswer((_) => Future.value());
        when(secondCamera.dispose).thenAnswer((_) => Future.value());

        // Save cameras in the camera plugin.
        (CameraPlatform.instance as CameraPlugin).cameras.addAll({
          firstCameraId: firstCamera,
          secondCameraId: secondCamera,
        });

        // Dispose the first camera.
        await CameraPlatform.instance.dispose(firstCameraId);

        // The first camera should be disposed.
        verify(firstCamera.dispose).called(1);
        verifyNever(secondCamera.dispose);

        // The first camera should be removed from the camera plugin.
        expect(
          (CameraPlatform.instance as CameraPlugin).cameras,
          equals({
            secondCameraId: secondCamera,
          }),
        );
      });

      testWidgets('cancels camera video and abort error subscriptions',
          (tester) async {
        final camera = MockCamera();
        final videoElement = MockVideoElement();

        final errorStreamController = StreamController<Event>();
        final abortStreamController = StreamController<Event>();

        when(camera.getVideoSize).thenAnswer(
          (_) => Future.value(Size(10, 10)),
        );
        when(camera.initialize).thenAnswer((_) => Future.value());
        when(camera.play).thenAnswer((_) => Future.value());

        when(() => camera.videoElement).thenReturn(videoElement);
        when(() => videoElement.onError)
            .thenAnswer((_) => FakeElementStream(errorStreamController.stream));
        when(() => videoElement.onAbort)
            .thenAnswer((_) => FakeElementStream(abortStreamController.stream));

        // Save the camera in the camera plugin.
        (CameraPlatform.instance as CameraPlugin).cameras[cameraId] = camera;

        await CameraPlatform.instance.initializeCamera(cameraId);

        expect(errorStreamController.hasListener, isTrue);
        expect(abortStreamController.hasListener, isTrue);

        await CameraPlatform.instance.dispose(cameraId);

        expect(errorStreamController.hasListener, isFalse);
        expect(abortStreamController.hasListener, isFalse);
      });

      group('throws PlatformException', () {
        testWidgets(
            'with notFound error '
            'if the camera does not exist', (tester) async {
          expect(
            () => CameraPlatform.instance.dispose(cameraId),
            throwsA(
              isA<PlatformException>().having(
                (e) => e.code,
                'code',
                CameraErrorCode.notFound.toString(),
              ),
            ),
          );
        });

        testWidgets('when dispose throws DomException', (tester) async {
          final camera = MockCamera();
          final exception = FakeDomException(DomException.INVALID_ACCESS);

          when(camera.dispose).thenThrow(exception);

          // Save the camera in the camera plugin.
          (CameraPlatform.instance as CameraPlugin).cameras[cameraId] = camera;

          expect(
            () => CameraPlatform.instance.dispose(cameraId),
            throwsA(
              isA<PlatformException>().having(
                (e) => e.code,
                'code',
                exception.name,
              ),
            ),
          );
        });
      });
    });

    group('getCamera', () {
      testWidgets('returns the correct camera', (tester) async {
        final camera = Camera(
          textureId: cameraId,
          cameraService: cameraService,
        );

        // Save the camera in the camera plugin.
        (CameraPlatform.instance as CameraPlugin).cameras[cameraId] = camera;

        expect(
          (CameraPlatform.instance as CameraPlugin).getCamera(cameraId),
          equals(camera),
        );
      });

      testWidgets(
          'throws PlatformException '
          'with notFound error '
          'if the camera does not exist', (tester) async {
        expect(
          () => (CameraPlatform.instance as CameraPlugin).getCamera(cameraId),
          throwsA(
            isA<PlatformException>().having(
              (e) => e.code,
              'code',
              CameraErrorCode.notFound.toString(),
            ),
          ),
        );
      });
    });

    group('events', () {
      testWidgets(
          'onCameraInitialized emits a CameraInitializedEvent '
          'on initializeCamera', (tester) async {
        // Mock the camera to use a blank video stream of size 1280x720.
        const videoSize = Size(1280, 720);

        videoElement = getVideoElementWithBlankStream(videoSize);

        when(
          () => cameraService.getMediaStreamForOptions(
            any(),
            cameraId: cameraId,
          ),
        ).thenAnswer((_) async => videoElement.captureStream());

        final camera = Camera(
          textureId: cameraId,
          cameraService: cameraService,
        );

        // Save the camera in the camera plugin.
        (CameraPlatform.instance as CameraPlugin).cameras[cameraId] = camera;

        final Stream<CameraInitializedEvent> eventStream =
            CameraPlatform.instance.onCameraInitialized(cameraId);

        final streamQueue = StreamQueue(eventStream);

        await CameraPlatform.instance.initializeCamera(cameraId);

        expect(
          await streamQueue.next,
          equals(
            CameraInitializedEvent(
              cameraId,
              videoSize.width,
              videoSize.height,
              ExposureMode.auto,
              false,
              FocusMode.auto,
              false,
            ),
          ),
        );

        await streamQueue.cancel();
      });

      testWidgets('onCameraResolutionChanged emits an empty stream',
          (tester) async {
        expect(
          CameraPlatform.instance.onCameraResolutionChanged(cameraId),
          emits(isEmpty),
        );
      });

      testWidgets('onCameraClosing throws UnimplementedError', (tester) async {
        expect(
          () => CameraPlatform.instance.onCameraClosing(cameraId),
          throwsUnimplementedError,
        );
      });

      group('onCameraError', () {
        late Camera camera;
        late VideoElement videoElement;

        late StreamController<Event> errorStreamController,
            abortStreamController;

        setUp(() {
          camera = MockCamera();
          videoElement = MockVideoElement();

          errorStreamController = StreamController<Event>();
          abortStreamController = StreamController<Event>();

          when(camera.getVideoSize).thenAnswer(
            (_) => Future.value(Size(10, 10)),
          );
          when(camera.initialize).thenAnswer((_) => Future.value());
          when(camera.play).thenAnswer((_) => Future.value());

          when(() => camera.videoElement).thenReturn(videoElement);
          when(() => videoElement.onError).thenAnswer(
              (_) => FakeElementStream(errorStreamController.stream));
          when(() => videoElement.onAbort).thenAnswer(
              (_) => FakeElementStream(abortStreamController.stream));

          // Save the camera in the camera plugin.
          (CameraPlatform.instance as CameraPlugin).cameras[cameraId] = camera;
        });

        testWidgets(
            'emits a CameraErrorEvent '
            'on initialize video error '
            'with a message', (tester) async {
          final Stream<CameraErrorEvent> eventStream =
              CameraPlatform.instance.onCameraError(cameraId);

          final streamQueue = StreamQueue(eventStream);

          await CameraPlatform.instance.initializeCamera(cameraId);

          final error = FakeMediaError(
            MediaError.MEDIA_ERR_NETWORK,
            'A network error occured.',
          );

          final errorCode = CameraErrorCode.fromMediaError(error);

          when(() => videoElement.error).thenReturn(error);

          errorStreamController.add(Event('error'));

          expect(
            await streamQueue.next,
            equals(
              CameraErrorEvent(
                cameraId,
                'Error code: ${errorCode}, error message: ${error.message}',
              ),
            ),
          );

          await streamQueue.cancel();
        });

        testWidgets(
            'emits a CameraErrorEvent '
            'on initialize video error '
            'with no message', (tester) async {
          final Stream<CameraErrorEvent> eventStream =
              CameraPlatform.instance.onCameraError(cameraId);

          final streamQueue = StreamQueue(eventStream);

          await CameraPlatform.instance.initializeCamera(cameraId);

          final error = FakeMediaError(MediaError.MEDIA_ERR_NETWORK);
          final errorCode = CameraErrorCode.fromMediaError(error);

          when(() => videoElement.error).thenReturn(error);

          errorStreamController.add(Event('error'));

          expect(
            await streamQueue.next,
            equals(
              CameraErrorEvent(
                cameraId,
                'Error code: ${errorCode}, error message: No further diagnostic information can be determined or provided.',
              ),
            ),
          );

          await streamQueue.cancel();
        });

        testWidgets(
            'emits a CameraErrorEvent '
            'on initialize abort error', (tester) async {
          final Stream<CameraErrorEvent> eventStream =
              CameraPlatform.instance.onCameraError(cameraId);

          final streamQueue = StreamQueue(eventStream);

          await CameraPlatform.instance.initializeCamera(cameraId);

          abortStreamController.add(Event('abort'));

          expect(
            await streamQueue.next,
            equals(
              CameraErrorEvent(
                cameraId,
                'Error code: ${CameraErrorCode.abort}, error message: The video element\'s source has not fully loaded.',
              ),
            ),
          );

          await streamQueue.cancel();
        });

        testWidgets(
            'emits a CameraErrorEvent '
            'on takePicture error', (tester) async {
          final exception = CameraWebException(
            cameraId,
            CameraErrorCode.notStarted,
            'description',
          );

          when(camera.takePicture).thenThrow(exception);

          final Stream<CameraErrorEvent> eventStream =
              CameraPlatform.instance.onCameraError(cameraId);

          final streamQueue = StreamQueue(eventStream);

          expect(
            () async => await CameraPlatform.instance.takePicture(cameraId),
            throwsA(
              isA<PlatformException>(),
            ),
          );

          expect(
            await streamQueue.next,
            equals(
              CameraErrorEvent(
                cameraId,
                'Error code: ${exception.code}, error message: ${exception.description}',
              ),
            ),
          );

          await streamQueue.cancel();
        });

        testWidgets(
            'emits a CameraErrorEvent '
            'on setFlashMode error', (tester) async {
          final exception = CameraWebException(
            cameraId,
            CameraErrorCode.notStarted,
            'description',
          );

          when(() => camera.setFlashMode(any())).thenThrow(exception);

          final Stream<CameraErrorEvent> eventStream =
              CameraPlatform.instance.onCameraError(cameraId);

          final streamQueue = StreamQueue(eventStream);

          expect(
            () async => await CameraPlatform.instance.setFlashMode(
              cameraId,
              FlashMode.always,
            ),
            throwsA(
              isA<PlatformException>(),
            ),
          );

          expect(
            await streamQueue.next,
            equals(
              CameraErrorEvent(
                cameraId,
                'Error code: ${exception.code}, error message: ${exception.description}',
              ),
            ),
          );

          await streamQueue.cancel();
        });

        testWidgets(
            'emits a CameraErrorEvent '
            'on getMaxZoomLevel error', (tester) async {
          final exception = CameraWebException(
            cameraId,
            CameraErrorCode.zoomLevelNotSupported,
            'description',
          );

          when(camera.getMaxZoomLevel).thenThrow(exception);

          final Stream<CameraErrorEvent> eventStream =
              CameraPlatform.instance.onCameraError(cameraId);

          final streamQueue = StreamQueue(eventStream);

          expect(
            () async => await CameraPlatform.instance.getMaxZoomLevel(
              cameraId,
            ),
            throwsA(
              isA<PlatformException>(),
            ),
          );

          expect(
            await streamQueue.next,
            equals(
              CameraErrorEvent(
                cameraId,
                'Error code: ${exception.code}, error message: ${exception.description}',
              ),
            ),
          );

          await streamQueue.cancel();
        });

        testWidgets(
            'emits a CameraErrorEvent '
            'on getMinZoomLevel error', (tester) async {
          final exception = CameraWebException(
            cameraId,
            CameraErrorCode.zoomLevelNotSupported,
            'description',
          );

          when(camera.getMinZoomLevel).thenThrow(exception);

          final Stream<CameraErrorEvent> eventStream =
              CameraPlatform.instance.onCameraError(cameraId);

          final streamQueue = StreamQueue(eventStream);

          expect(
            () async => await CameraPlatform.instance.getMinZoomLevel(
              cameraId,
            ),
            throwsA(
              isA<PlatformException>(),
            ),
          );

          expect(
            await streamQueue.next,
            equals(
              CameraErrorEvent(
                cameraId,
                'Error code: ${exception.code}, error message: ${exception.description}',
              ),
            ),
          );

          await streamQueue.cancel();
        });

        testWidgets(
            'emits a CameraErrorEvent '
            'on setZoomLevel error', (tester) async {
          final exception = CameraWebException(
            cameraId,
            CameraErrorCode.zoomLevelNotSupported,
            'description',
          );

          when(() => camera.setZoomLevel(any())).thenThrow(exception);

          final Stream<CameraErrorEvent> eventStream =
              CameraPlatform.instance.onCameraError(cameraId);

          final streamQueue = StreamQueue(eventStream);

          expect(
            () async => await CameraPlatform.instance.setZoomLevel(
              cameraId,
              100.0,
            ),
            throwsA(
              isA<CameraException>(),
            ),
          );

          expect(
            await streamQueue.next,
            equals(
              CameraErrorEvent(
                cameraId,
                'Error code: ${exception.code}, error message: ${exception.description}',
              ),
            ),
          );

          await streamQueue.cancel();
        });

        testWidgets(
            'emits a CameraErrorEvent '
            'on resumePreview error', (tester) async {
          final exception = CameraWebException(
            cameraId,
            CameraErrorCode.unknown,
            'description',
          );

          when(camera.play).thenThrow(exception);

          final Stream<CameraErrorEvent> eventStream =
              CameraPlatform.instance.onCameraError(cameraId);

          final streamQueue = StreamQueue(eventStream);

          expect(
            () async => await CameraPlatform.instance.resumePreview(cameraId),
            throwsA(
              isA<PlatformException>(),
            ),
          );

          expect(
            await streamQueue.next,
            equals(
              CameraErrorEvent(
                cameraId,
                'Error code: ${exception.code}, error message: ${exception.description}',
              ),
            ),
          );

          await streamQueue.cancel();
        });
      });

      testWidgets('onVideoRecordedEvent throws UnimplementedError',
          (tester) async {
        expect(
          () => CameraPlatform.instance.onVideoRecordedEvent(cameraId),
          throwsUnimplementedError,
        );
      });

      group('onDeviceOrientationChanged', () {
        group('emits an empty stream', () {
          testWidgets('when screen is not supported', (tester) async {
            when(() => window.screen).thenReturn(null);

            expect(
              CameraPlatform.instance.onDeviceOrientationChanged(),
              emits(isEmpty),
            );
          });

          testWidgets('when screen orientation is not supported',
              (tester) async {
            when(() => screen.orientation).thenReturn(null);

            expect(
              CameraPlatform.instance.onDeviceOrientationChanged(),
              emits(isEmpty),
            );
          });
        });

        testWidgets(
            'emits a DeviceOrientationChangedEvent '
            'when the screen orientation is changed', (tester) async {
          when(
            () => cameraService.mapOrientationTypeToDeviceOrientation(
              OrientationType.landscapePrimary,
            ),
          ).thenReturn(DeviceOrientation.landscapeLeft);

          when(
            () => cameraService.mapOrientationTypeToDeviceOrientation(
              OrientationType.portraitSecondary,
            ),
          ).thenReturn(DeviceOrientation.portraitDown);

          final eventStreamController = StreamController<Event>();

          when(() => screenOrientation.onChange)
              .thenAnswer((_) => eventStreamController.stream);

          final Stream<DeviceOrientationChangedEvent> eventStream =
              CameraPlatform.instance.onDeviceOrientationChanged();

          final streamQueue = StreamQueue(eventStream);

          // Change the screen orientation to landscapePrimary and
          // emit an event on the screenOrientation.onChange stream.
          when(() => screenOrientation.type)
              .thenReturn(OrientationType.landscapePrimary);

          eventStreamController.add(Event('orientationChanged'));

          expect(
            await streamQueue.next,
            equals(
              DeviceOrientationChangedEvent(
                DeviceOrientation.landscapeLeft,
              ),
            ),
          );

          // Change the screen orientation to portraitSecondary and
          // emit an event on the screenOrientation.onChange stream.
          when(() => screenOrientation.type)
              .thenReturn(OrientationType.portraitSecondary);

          eventStreamController.add(Event('orientationChanged'));

          expect(
            await streamQueue.next,
            equals(
              DeviceOrientationChangedEvent(
                DeviceOrientation.portraitDown,
              ),
            ),
          );

          await streamQueue.cancel();
        });
      });
    });
  });
}
