// 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';
// TODO(a14n): remove this import once Flutter 3.1 or later reaches stable (including flutter/flutter#106316)
// ignore: unnecessary_import
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 int cameraId = 1;

    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(const 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(MockMediaStreamTrack());
      registerFallbackValue(MockCameraOptions());
      registerFallbackValue(FlashMode.off);
    });

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

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

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

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

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

      testWidgets(
          'releases the camera stream '
          'used to request video and audio permissions',
          (WidgetTester tester) async {
        final MockMediaStreamTrack videoTrack = MockMediaStreamTrack();

        bool videoTrackStopped = false;
        when(videoTrack.stop).thenAnswer((Invocation _) {
          videoTrackStopped = true;
        });

        when(
          () => cameraService.getMediaStreamForOptions(
            const CameraOptions(
              audio: AudioConstraints(enabled: true),
            ),
          ),
        ).thenAnswer(
          (_) => Future<MediaStream>.value(
            FakeMediaStream(<MediaStreamTrack>[videoTrack]),
          ),
        );

        final List<CameraDescription> _ =
            await CameraPlatform.instance.availableCameras();

        expect(videoTrackStopped, isTrue);
      });

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

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

        final List<CameraDescription> _ =
            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', (WidgetTester tester) async {
        final FakeMediaDeviceInfo videoDevice = FakeMediaDeviceInfo(
          '',
          'Camera 1',
          MediaDeviceKind.videoInput,
        );

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

        final List<CameraDescription> _ =
            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', (WidgetTester tester) async {
        final FakeMediaDeviceInfo videoDevice = FakeMediaDeviceInfo(
          '1',
          'Camera 1',
          MediaDeviceKind.videoInput,
        );

        final FakeMediaStream videoStream = FakeMediaStream(
            <MediaStreamTrack>[MockMediaStreamTrack(), MockMediaStreamTrack()]);

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

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

        final List<CameraDescription> _ =
            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', (WidgetTester tester) async {
        final FakeMediaDeviceInfo firstVideoDevice = FakeMediaDeviceInfo(
          '1',
          'Camera 1',
          MediaDeviceKind.videoInput,
        );

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

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

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

        // Mock media devices to return two video input devices
        // and two audio devices.
        when(mediaDevices.enumerateDevices).thenAnswer(
          (_) => Future<List<dynamic>>.value(<Object>[
            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(
            (Invocation _) => Future<MediaStream>.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(
            (Invocation _) => Future<MediaStream>.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 List<CameraDescription> cameras =
            await CameraPlatform.instance.availableCameras();

        // Expect two cameras and ignore two audio devices.
        expect(
          cameras,
          equals(<CameraDescription>[
            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', (WidgetTester tester) async {
        final FakeMediaDeviceInfo videoDevice = FakeMediaDeviceInfo(
          '1',
          'Camera 1',
          MediaDeviceKind.videoInput,
        );

        final FakeMediaStream videoStream = FakeMediaStream(
            <MediaStreamTrack>[MockMediaStreamTrack(), MockMediaStreamTrack()]);

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

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

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

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

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

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

      testWidgets(
          'releases the video stream '
          'of a video input device', (WidgetTester tester) async {
        final FakeMediaDeviceInfo videoDevice = FakeMediaDeviceInfo(
          '1',
          'Camera 1',
          MediaDeviceKind.videoInput,
        );

        final FakeMediaStream videoStream = FakeMediaStream(
            <MediaStreamTrack>[MockMediaStreamTrack(), MockMediaStreamTrack()]);

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

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

        final List<CameraDescription> _ =
            await CameraPlatform.instance.availableCameras();

        for (final MediaStreamTrack videoTrack
            in videoStream.getVideoTracks()) {
          verify(videoTrack.stop).called(1);
        }
      });

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

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

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

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

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

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

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

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

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

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

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

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

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

        const CameraMetadata 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', (WidgetTester tester) async {
          when(
            () => cameraService
                .mapResolutionPresetToSize(ResolutionPreset.ultraHigh),
          ).thenReturn(ultraHighResolutionSize);

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

          expect(
            (CameraPlatform.instance as CameraPlugin).cameras[cameraId],
            isA<Camera>()
                .having(
                  (Camera camera) => camera.textureId,
                  'textureId',
                  cameraId,
                )
                .having(
                  (Camera camera) => camera.options,
                  'options',
                  CameraOptions(
                    audio: const 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', (WidgetTester tester) async {
          when(
            () => cameraService.mapResolutionPresetToSize(ResolutionPreset.max),
          ).thenReturn(maxResolutionSize);

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

          expect(
            (CameraPlatform.instance as CameraPlugin).cameras[cameraId],
            isA<Camera>().having(
              (Camera camera) => camera.options,
              'options',
              CameraOptions(
                audio: const AudioConstraints(),
                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', (WidgetTester tester) async {
        expect(
          () => CameraPlatform.instance.createCamera(
            const CameraDescription(
              name: 'name',
              lensDirection: CameraLensDirection.back,
              sensorOrientation: 0,
            ),
            ResolutionPreset.ultraHigh,
          ),
          throwsA(
            isA<CameraException>().having(
              (CameraException e) => e.code,
              'code',
              CameraErrorCode.missingMetadata.toString(),
            ),
          ),
        );
      });
    });

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

      late StreamController<Event> errorStreamController, abortStreamController;
      late StreamController<MediaStreamTrack> endedStreamController;

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

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

        when(camera.getVideoSize).thenReturn(const Size(10, 10));
        when(camera.initialize)
            .thenAnswer((Invocation _) => Future<void>.value());
        when(camera.play).thenAnswer((Invocation _) => Future<void>.value());

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

        when(() => camera.onEnded)
            .thenAnswer((Invocation _) => endedStreamController.stream);
      });

      testWidgets('initializes and plays the camera',
          (WidgetTester tester) async {
        // 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);
      });

      testWidgets('starts listening to the camera video error and abort events',
          (WidgetTester tester) async {
        // Save the camera in the camera plugin.
        (CameraPlatform.instance as CameraPlugin).cameras[cameraId] = camera;

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

        await CameraPlatform.instance.initializeCamera(cameraId);

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

      testWidgets('starts listening to the camera ended events',
          (WidgetTester tester) async {
        // Save the camera in the camera plugin.
        (CameraPlatform.instance as CameraPlugin).cameras[cameraId] = camera;

        expect(endedStreamController.hasListener, isFalse);

        await CameraPlatform.instance.initializeCamera(cameraId);

        expect(endedStreamController.hasListener, isTrue);
      });

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

        testWidgets('when camera throws CameraWebException',
            (WidgetTester tester) async {
          final CameraWebException 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(
                (PlatformException e) => e.code,
                'code',
                exception.code.toString(),
              ),
            ),
          );
        });

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

          when(camera.initialize)
              .thenAnswer((Invocation _) => Future<void>.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(
                (PlatformException e) => e.code,
                'code',
                exception.name,
              ),
            ),
          );
        });
      });
    });

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

      testWidgets(
          'requests full-screen mode '
          'on documentElement', (WidgetTester 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', (WidgetTester 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', (WidgetTester tester) async {
          when(() => window.screen).thenReturn(null);

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

        final XFile 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', (WidgetTester tester) async {
          expect(
            () => CameraPlatform.instance.takePicture(cameraId),
            throwsA(
              isA<PlatformException>().having(
                (PlatformException e) => e.code,
                'code',
                CameraErrorCode.notFound.toString(),
              ),
            ),
          );
        });

        testWidgets('when takePicture throws DomException',
            (WidgetTester tester) async {
          final MockCamera camera = MockCamera();
          final FakeDomException 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(
                (PlatformException e) => e.code,
                'code',
                exception.name,
              ),
            ),
          );
        });

        testWidgets('when takePicture throws CameraWebException',
            (WidgetTester tester) async {
          final MockCamera camera = MockCamera();
          final CameraWebException 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(
                (PlatformException e) => e.code,
                'code',
                exception.code.toString(),
              ),
            ),
          );
        });
      });
    });

    group('startVideoRecording', () {
      late Camera camera;

      setUp(() {
        camera = MockCamera();

        when(camera.startVideoRecording).thenAnswer((Invocation _) async {});

        when(() => camera.onVideoRecordingError)
            .thenAnswer((Invocation _) => const Stream<ErrorEvent>.empty());
      });

      testWidgets('starts a video recording', (WidgetTester tester) async {
        // Save the camera in the camera plugin.
        (CameraPlatform.instance as CameraPlugin).cameras[cameraId] = camera;

        await CameraPlatform.instance.startVideoRecording(cameraId);

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

      testWidgets('listens to the onVideoRecordingError stream',
          (WidgetTester tester) async {
        final StreamController<ErrorEvent> videoRecordingErrorController =
            StreamController<ErrorEvent>();

        when(() => camera.onVideoRecordingError)
            .thenAnswer((Invocation _) => videoRecordingErrorController.stream);

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

        await CameraPlatform.instance.startVideoRecording(cameraId);

        expect(
          videoRecordingErrorController.hasListener,
          isTrue,
        );
      });

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

        testWidgets('when startVideoRecording throws DomException',
            (WidgetTester tester) async {
          final FakeDomException exception =
              FakeDomException(DomException.INVALID_STATE);

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

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

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

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

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

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

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

    group('stopVideoRecording', () {
      testWidgets('stops a video recording', (WidgetTester tester) async {
        final MockCamera camera = MockCamera();
        final MockXFile capturedVideo = MockXFile();

        when(camera.stopVideoRecording)
            .thenAnswer((Invocation _) => Future<XFile>.value(capturedVideo));

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

        final XFile video =
            await CameraPlatform.instance.stopVideoRecording(cameraId);

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

        expect(video, capturedVideo);
      });

      testWidgets('stops listening to the onVideoRecordingError stream',
          (WidgetTester tester) async {
        final MockCamera camera = MockCamera();
        final StreamController<ErrorEvent> videoRecordingErrorController =
            StreamController<ErrorEvent>();

        when(camera.startVideoRecording).thenAnswer((Invocation _) async {});

        when(camera.stopVideoRecording)
            .thenAnswer((Invocation _) => Future<XFile>.value(MockXFile()));

        when(() => camera.onVideoRecordingError)
            .thenAnswer((Invocation _) => videoRecordingErrorController.stream);

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

        await CameraPlatform.instance.startVideoRecording(cameraId);
        final XFile _ =
            await CameraPlatform.instance.stopVideoRecording(cameraId);

        expect(
          videoRecordingErrorController.hasListener,
          isFalse,
        );
      });

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

        testWidgets('when stopVideoRecording throws DomException',
            (WidgetTester tester) async {
          final MockCamera camera = MockCamera();
          final FakeDomException exception =
              FakeDomException(DomException.INVALID_STATE);

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

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

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

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

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

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

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

    group('pauseVideoRecording', () {
      testWidgets('pauses a video recording', (WidgetTester tester) async {
        final MockCamera camera = MockCamera();

        when(camera.pauseVideoRecording).thenAnswer((Invocation _) async {});

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

        await CameraPlatform.instance.pauseVideoRecording(cameraId);

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

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

        testWidgets('when pauseVideoRecording throws DomException',
            (WidgetTester tester) async {
          final MockCamera camera = MockCamera();
          final FakeDomException exception =
              FakeDomException(DomException.INVALID_STATE);

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

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

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

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

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

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

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

    group('resumeVideoRecording', () {
      testWidgets('resumes a video recording', (WidgetTester tester) async {
        final MockCamera camera = MockCamera();

        when(camera.resumeVideoRecording).thenAnswer((Invocation _) async {});

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

        await CameraPlatform.instance.resumeVideoRecording(cameraId);

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

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

        testWidgets('when resumeVideoRecording throws DomException',
            (WidgetTester tester) async {
          final MockCamera camera = MockCamera();
          final FakeDomException exception =
              FakeDomException(DomException.INVALID_STATE);

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

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

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

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

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

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

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

    group('setFlashMode', () {
      testWidgets('calls setFlashMode on the camera',
          (WidgetTester tester) async {
        final MockCamera camera = MockCamera();
        const FlashMode 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', (WidgetTester tester) async {
          expect(
            () => CameraPlatform.instance.setFlashMode(
              cameraId,
              FlashMode.always,
            ),
            throwsA(
              isA<PlatformException>().having(
                (PlatformException e) => e.code,
                'code',
                CameraErrorCode.notFound.toString(),
              ),
            ),
          );
        });

        testWidgets('when setFlashMode throws DomException',
            (WidgetTester tester) async {
          final MockCamera camera = MockCamera();
          final FakeDomException 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(
                (PlatformException e) => e.code,
                'code',
                exception.name,
              ),
            ),
          );
        });

        testWidgets('when setFlashMode throws CameraWebException',
            (WidgetTester tester) async {
          final MockCamera camera = MockCamera();
          final CameraWebException 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(
                (PlatformException e) => e.code,
                'code',
                exception.code.toString(),
              ),
            ),
          );
        });
      });
    });

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

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

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

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

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

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

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

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

    group('getMaxZoomLevel', () {
      testWidgets('calls getMaxZoomLevel on the camera',
          (WidgetTester tester) async {
        final MockCamera camera = MockCamera();
        const double 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', (WidgetTester tester) async {
          expect(
            () async => CameraPlatform.instance.getMaxZoomLevel(
              cameraId,
            ),
            throwsA(
              isA<PlatformException>().having(
                (PlatformException e) => e.code,
                'code',
                CameraErrorCode.notFound.toString(),
              ),
            ),
          );
        });

        testWidgets('when getMaxZoomLevel throws DomException',
            (WidgetTester tester) async {
          final MockCamera camera = MockCamera();
          final FakeDomException 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 => CameraPlatform.instance.getMaxZoomLevel(
              cameraId,
            ),
            throwsA(
              isA<PlatformException>().having(
                (PlatformException e) => e.code,
                'code',
                exception.name,
              ),
            ),
          );
        });

        testWidgets('when getMaxZoomLevel throws CameraWebException',
            (WidgetTester tester) async {
          final MockCamera camera = MockCamera();
          final CameraWebException 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 => CameraPlatform.instance.getMaxZoomLevel(
              cameraId,
            ),
            throwsA(
              isA<PlatformException>().having(
                (PlatformException e) => e.code,
                'code',
                exception.code.toString(),
              ),
            ),
          );
        });
      });
    });

    group('getMinZoomLevel', () {
      testWidgets('calls getMinZoomLevel on the camera',
          (WidgetTester tester) async {
        final MockCamera camera = MockCamera();
        const double 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', (WidgetTester tester) async {
          expect(
            () async => CameraPlatform.instance.getMinZoomLevel(
              cameraId,
            ),
            throwsA(
              isA<PlatformException>().having(
                (PlatformException e) => e.code,
                'code',
                CameraErrorCode.notFound.toString(),
              ),
            ),
          );
        });

        testWidgets('when getMinZoomLevel throws DomException',
            (WidgetTester tester) async {
          final MockCamera camera = MockCamera();
          final FakeDomException 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 => CameraPlatform.instance.getMinZoomLevel(
              cameraId,
            ),
            throwsA(
              isA<PlatformException>().having(
                (PlatformException e) => e.code,
                'code',
                exception.name,
              ),
            ),
          );
        });

        testWidgets('when getMinZoomLevel throws CameraWebException',
            (WidgetTester tester) async {
          final MockCamera camera = MockCamera();
          final CameraWebException 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 => CameraPlatform.instance.getMinZoomLevel(
              cameraId,
            ),
            throwsA(
              isA<PlatformException>().having(
                (PlatformException e) => e.code,
                'code',
                exception.code.toString(),
              ),
            ),
          );
        });
      });
    });

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

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

        const double 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', (WidgetTester tester) async {
          expect(
            () async => CameraPlatform.instance.setZoomLevel(
              cameraId,
              100.0,
            ),
            throwsA(
              isA<CameraException>().having(
                (CameraException e) => e.code,
                'code',
                CameraErrorCode.notFound.toString(),
              ),
            ),
          );
        });

        testWidgets('when setZoomLevel throws DomException',
            (WidgetTester tester) async {
          final MockCamera camera = MockCamera();
          final FakeDomException 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 => CameraPlatform.instance.setZoomLevel(
              cameraId,
              100.0,
            ),
            throwsA(
              isA<CameraException>().having(
                (CameraException e) => e.code,
                'code',
                exception.name,
              ),
            ),
          );
        });

        testWidgets('when setZoomLevel throws PlatformException',
            (WidgetTester tester) async {
          final MockCamera camera = MockCamera();
          final PlatformException 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 => CameraPlatform.instance.setZoomLevel(
              cameraId,
              100.0,
            ),
            throwsA(
              isA<CameraException>().having(
                (CameraException e) => e.code,
                'code',
                exception.code,
              ),
            ),
          );
        });

        testWidgets('when setZoomLevel throws CameraWebException',
            (WidgetTester tester) async {
          final MockCamera camera = MockCamera();
          final CameraWebException 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 => CameraPlatform.instance.setZoomLevel(
              cameraId,
              100.0,
            ),
            throwsA(
              isA<CameraException>().having(
                (CameraException e) => e.code,
                'code',
                exception.code.toString(),
              ),
            ),
          );
        });
      });
    });

    group('pausePreview', () {
      testWidgets('calls pause on the camera', (WidgetTester tester) async {
        final MockCamera 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', (WidgetTester tester) async {
          expect(
            () async => CameraPlatform.instance.pausePreview(cameraId),
            throwsA(
              isA<PlatformException>().having(
                (PlatformException e) => e.code,
                'code',
                CameraErrorCode.notFound.toString(),
              ),
            ),
          );
        });

        testWidgets('when pause throws DomException',
            (WidgetTester tester) async {
          final MockCamera camera = MockCamera();
          final FakeDomException 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 => CameraPlatform.instance.pausePreview(cameraId),
            throwsA(
              isA<PlatformException>().having(
                (PlatformException e) => e.code,
                'code',
                exception.name,
              ),
            ),
          );
        });
      });
    });

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

        when(camera.play).thenAnswer((Invocation _) 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', (WidgetTester tester) async {
          expect(
            () async => CameraPlatform.instance.resumePreview(cameraId),
            throwsA(
              isA<PlatformException>().having(
                (PlatformException e) => e.code,
                'code',
                CameraErrorCode.notFound.toString(),
              ),
            ),
          );
        });

        testWidgets('when play throws DomException',
            (WidgetTester tester) async {
          final MockCamera camera = MockCamera();
          final FakeDomException 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 => CameraPlatform.instance.resumePreview(cameraId),
            throwsA(
              isA<PlatformException>().having(
                (PlatformException e) => e.code,
                'code',
                exception.name,
              ),
            ),
          );
        });

        testWidgets('when play throws CameraWebException',
            (WidgetTester tester) async {
          final MockCamera camera = MockCamera();
          final CameraWebException 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 => CameraPlatform.instance.resumePreview(cameraId),
            throwsA(
              isA<PlatformException>().having(
                (PlatformException e) => e.code,
                'code',
                exception.code.toString(),
              ),
            ),
          );
        });
      });
    });

    testWidgets(
        'buildPreview returns an HtmlElementView '
        'with an appropriate view type', (WidgetTester tester) async {
      final Camera 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(
          (widgets.HtmlElementView view) => view.viewType,
          'viewType',
          camera.getViewType(),
        ),
      );
    });

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

      late StreamController<Event> errorStreamController, abortStreamController;
      late StreamController<MediaStreamTrack> endedStreamController;
      late StreamController<ErrorEvent> videoRecordingErrorController;

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

        errorStreamController = StreamController<Event>();
        abortStreamController = StreamController<Event>();
        endedStreamController = StreamController<MediaStreamTrack>();
        videoRecordingErrorController = StreamController<ErrorEvent>();

        when(camera.getVideoSize).thenReturn(const Size(10, 10));
        when(camera.initialize)
            .thenAnswer((Invocation _) => Future<void>.value());
        when(camera.play).thenAnswer((Invocation _) => Future<void>.value());
        when(camera.dispose).thenAnswer((Invocation _) => Future<void>.value());

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

        when(() => camera.onEnded)
            .thenAnswer((Invocation _) => endedStreamController.stream);

        when(() => camera.onVideoRecordingError)
            .thenAnswer((Invocation _) => videoRecordingErrorController.stream);

        when(camera.startVideoRecording).thenAnswer((Invocation _) async {});
      });

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

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

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

        // Save cameras in the camera plugin.
        (CameraPlatform.instance as CameraPlugin).cameras.addAll(<int, Camera>{
          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(<int, Camera>{
            secondCameraId: secondCamera,
          }),
        );
      });

      testWidgets('cancels the camera video error and abort subscriptions',
          (WidgetTester tester) async {
        // Save the camera in the camera plugin.
        (CameraPlatform.instance as CameraPlugin).cameras[cameraId] = camera;

        await CameraPlatform.instance.initializeCamera(cameraId);
        await CameraPlatform.instance.dispose(cameraId);

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

      testWidgets('cancels the camera ended subscriptions',
          (WidgetTester tester) async {
        // Save the camera in the camera plugin.
        (CameraPlatform.instance as CameraPlugin).cameras[cameraId] = camera;

        await CameraPlatform.instance.initializeCamera(cameraId);
        await CameraPlatform.instance.dispose(cameraId);

        expect(endedStreamController.hasListener, isFalse);
      });

      testWidgets('cancels the camera video recording error subscriptions',
          (WidgetTester tester) async {
        // Save the camera in the camera plugin.
        (CameraPlatform.instance as CameraPlugin).cameras[cameraId] = camera;

        await CameraPlatform.instance.initializeCamera(cameraId);
        await CameraPlatform.instance.startVideoRecording(cameraId);
        await CameraPlatform.instance.dispose(cameraId);

        expect(videoRecordingErrorController.hasListener, isFalse);
      });

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

        testWidgets('when dispose throws DomException',
            (WidgetTester tester) async {
          final MockCamera camera = MockCamera();
          final FakeDomException 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(
                (PlatformException e) => e.code,
                'code',
                exception.name,
              ),
            ),
          );
        });
      });
    });

    group('getCamera', () {
      testWidgets('returns the correct camera', (WidgetTester tester) async {
        final Camera 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', (WidgetTester tester) async {
        expect(
          () => (CameraPlatform.instance as CameraPlugin).getCamera(cameraId),
          throwsA(
            isA<PlatformException>().having(
              (PlatformException e) => e.code,
              'code',
              CameraErrorCode.notFound.toString(),
            ),
          ),
        );
      });
    });

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

      late StreamController<Event> errorStreamController, abortStreamController;
      late StreamController<MediaStreamTrack> endedStreamController;
      late StreamController<ErrorEvent> videoRecordingErrorController;

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

        errorStreamController = StreamController<Event>();
        abortStreamController = StreamController<Event>();
        endedStreamController = StreamController<MediaStreamTrack>();
        videoRecordingErrorController = StreamController<ErrorEvent>();

        when(camera.getVideoSize).thenReturn(const Size(10, 10));
        when(camera.initialize)
            .thenAnswer((Invocation _) => Future<void>.value());
        when(camera.play).thenAnswer((Invocation _) => Future<void>.value());

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

        when(() => camera.onEnded)
            .thenAnswer((Invocation _) => endedStreamController.stream);

        when(() => camera.onVideoRecordingError)
            .thenAnswer((Invocation _) => videoRecordingErrorController.stream);

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

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

        videoElement = getVideoElementWithBlankStream(videoSize);

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

        final Camera 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<CameraInitializedEvent> streamQueue =
            StreamQueue<CameraInitializedEvent>(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',
          (WidgetTester tester) async {
        expect(
          CameraPlatform.instance.onCameraResolutionChanged(cameraId),
          emits(isEmpty),
        );
      });

      testWidgets(
          'onCameraClosing emits a CameraClosingEvent '
          'on the camera ended event', (WidgetTester tester) async {
        // Save the camera in the camera plugin.
        (CameraPlatform.instance as CameraPlugin).cameras[cameraId] = camera;

        final Stream<CameraClosingEvent> eventStream =
            CameraPlatform.instance.onCameraClosing(cameraId);

        final StreamQueue<CameraClosingEvent> streamQueue =
            StreamQueue<CameraClosingEvent>(eventStream);

        await CameraPlatform.instance.initializeCamera(cameraId);

        endedStreamController.add(MockMediaStreamTrack());

        expect(
          await streamQueue.next,
          equals(
            const CameraClosingEvent(cameraId),
          ),
        );

        await streamQueue.cancel();
      });

      group('onCameraError', () {
        setUp(() {
          // Save the camera in the camera plugin.
          (CameraPlatform.instance as CameraPlugin).cameras[cameraId] = camera;
        });

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

          final StreamQueue<CameraErrorEvent> streamQueue =
              StreamQueue<CameraErrorEvent>(eventStream);

          await CameraPlatform.instance.initializeCamera(cameraId);

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

          final CameraErrorCode 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 the camera video error event '
            'with no message', (WidgetTester tester) async {
          final Stream<CameraErrorEvent> eventStream =
              CameraPlatform.instance.onCameraError(cameraId);

          final StreamQueue<CameraErrorEvent> streamQueue =
              StreamQueue<CameraErrorEvent>(eventStream);

          await CameraPlatform.instance.initializeCamera(cameraId);

          final FakeMediaError error =
              FakeMediaError(MediaError.MEDIA_ERR_NETWORK);
          final CameraErrorCode 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 the camera video abort event', (WidgetTester tester) async {
          final Stream<CameraErrorEvent> eventStream =
              CameraPlatform.instance.onCameraError(cameraId);

          final StreamQueue<CameraErrorEvent> streamQueue =
              StreamQueue<CameraErrorEvent>(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', (WidgetTester tester) async {
          final CameraWebException exception = CameraWebException(
            cameraId,
            CameraErrorCode.notStarted,
            'description',
          );

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

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

          final StreamQueue<CameraErrorEvent> streamQueue =
              StreamQueue<CameraErrorEvent>(eventStream);

          expect(
            () async => 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', (WidgetTester tester) async {
          final CameraWebException exception = CameraWebException(
            cameraId,
            CameraErrorCode.notStarted,
            'description',
          );

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

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

          final StreamQueue<CameraErrorEvent> streamQueue =
              StreamQueue<CameraErrorEvent>(eventStream);

          expect(
            () async => 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', (WidgetTester tester) async {
          final CameraWebException exception = CameraWebException(
            cameraId,
            CameraErrorCode.zoomLevelNotSupported,
            'description',
          );

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

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

          final StreamQueue<CameraErrorEvent> streamQueue =
              StreamQueue<CameraErrorEvent>(eventStream);

          expect(
            () async => 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', (WidgetTester tester) async {
          final CameraWebException exception = CameraWebException(
            cameraId,
            CameraErrorCode.zoomLevelNotSupported,
            'description',
          );

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

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

          final StreamQueue<CameraErrorEvent> streamQueue =
              StreamQueue<CameraErrorEvent>(eventStream);

          expect(
            () async => 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', (WidgetTester tester) async {
          final CameraWebException exception = CameraWebException(
            cameraId,
            CameraErrorCode.zoomLevelNotSupported,
            'description',
          );

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

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

          final StreamQueue<CameraErrorEvent> streamQueue =
              StreamQueue<CameraErrorEvent>(eventStream);

          expect(
            () async => 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', (WidgetTester tester) async {
          final CameraWebException exception = CameraWebException(
            cameraId,
            CameraErrorCode.unknown,
            'description',
          );

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

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

          final StreamQueue<CameraErrorEvent> streamQueue =
              StreamQueue<CameraErrorEvent>(eventStream);

          expect(
            () async => 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(
            'emits a CameraErrorEvent '
            'on startVideoRecording error', (WidgetTester tester) async {
          final CameraWebException exception = CameraWebException(
            cameraId,
            CameraErrorCode.notStarted,
            'description',
          );

          when(() => camera.onVideoRecordingError)
              .thenAnswer((Invocation _) => const Stream<ErrorEvent>.empty());

          when(
            () => camera.startVideoRecording(
              maxVideoDuration: any(named: 'maxVideoDuration'),
            ),
          ).thenThrow(exception);

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

          final StreamQueue<CameraErrorEvent> streamQueue =
              StreamQueue<CameraErrorEvent>(eventStream);

          expect(
            () async => CameraPlatform.instance.startVideoRecording(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 the camera video recording error event',
            (WidgetTester tester) async {
          final Stream<CameraErrorEvent> eventStream =
              CameraPlatform.instance.onCameraError(cameraId);

          final StreamQueue<CameraErrorEvent> streamQueue =
              StreamQueue<CameraErrorEvent>(eventStream);

          await CameraPlatform.instance.initializeCamera(cameraId);
          await CameraPlatform.instance.startVideoRecording(cameraId);

          final FakeErrorEvent errorEvent = FakeErrorEvent('type', 'message');

          videoRecordingErrorController.add(errorEvent);

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

          await streamQueue.cancel();
        });

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

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

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

          final StreamQueue<CameraErrorEvent> streamQueue =
              StreamQueue<CameraErrorEvent>(eventStream);

          expect(
            () async => CameraPlatform.instance.stopVideoRecording(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 pauseVideoRecording error', (WidgetTester tester) async {
          final CameraWebException exception = CameraWebException(
            cameraId,
            CameraErrorCode.notStarted,
            'description',
          );

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

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

          final StreamQueue<CameraErrorEvent> streamQueue =
              StreamQueue<CameraErrorEvent>(eventStream);

          expect(
            () async => CameraPlatform.instance.pauseVideoRecording(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 resumeVideoRecording error', (WidgetTester tester) async {
          final CameraWebException exception = CameraWebException(
            cameraId,
            CameraErrorCode.notStarted,
            'description',
          );

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

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

          final StreamQueue<CameraErrorEvent> streamQueue =
              StreamQueue<CameraErrorEvent>(eventStream);

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

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

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

      testWidgets('onVideoRecordedEvent emits a VideoRecordedEvent',
          (WidgetTester tester) async {
        final MockCamera camera = MockCamera();
        final MockXFile capturedVideo = MockXFile();
        final Stream<VideoRecordedEvent> stream =
            Stream<VideoRecordedEvent>.value(
                VideoRecordedEvent(cameraId, capturedVideo, Duration.zero));
        when(() => camera.onVideoRecordedEvent)
            .thenAnswer((Invocation _) => stream);

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

        final StreamQueue<VideoRecordedEvent> streamQueue =
            StreamQueue<VideoRecordedEvent>(
                CameraPlatform.instance.onVideoRecordedEvent(cameraId));

        expect(
          await streamQueue.next,
          equals(
            VideoRecordedEvent(cameraId, capturedVideo, Duration.zero),
          ),
        );
      });

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

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

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

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

        testWidgets('emits the initial DeviceOrientationChangedEvent',
            (WidgetTester tester) async {
          when(
            () => cameraService.mapOrientationTypeToDeviceOrientation(
              OrientationType.portraitPrimary,
            ),
          ).thenReturn(DeviceOrientation.portraitUp);

          // Set the initial screen orientation to portraitPrimary.
          when(() => screenOrientation.type)
              .thenReturn(OrientationType.portraitPrimary);

          final StreamController<Event> eventStreamController =
              StreamController<Event>();

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

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

          final StreamQueue<DeviceOrientationChangedEvent> streamQueue =
              StreamQueue<DeviceOrientationChangedEvent>(eventStream);

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

          await streamQueue.cancel();
        });

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

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

          final StreamController<Event> eventStreamController =
              StreamController<Event>();

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

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

          final StreamQueue<DeviceOrientationChangedEvent> streamQueue =
              StreamQueue<DeviceOrientationChangedEvent>(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('change'));

          expect(
            await streamQueue.next,
            equals(
              const 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('change'));

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

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