@@ -6,6 +6,8 @@ import 'dart:html';
6
6
7
7
import 'package:camera_platform_interface/camera_platform_interface.dart' ;
8
8
import 'package:camera_web/camera_web.dart' ;
9
+ import 'package:camera_web/src/camera_settings.dart' ;
10
+ import 'package:camera_web/src/types/types.dart' ;
9
11
import 'package:flutter/services.dart' ;
10
12
import 'package:flutter_test/flutter_test.dart' ;
11
13
import 'package:integration_test/integration_test.dart' ;
@@ -23,6 +25,7 @@ void main() {
23
25
late Navigator navigator;
24
26
late MediaDevices mediaDevices;
25
27
late VideoElement videoElement;
28
+ late CameraSettings cameraSettings;
26
29
27
30
setUp (() async {
28
31
window = MockWindow ();
@@ -33,26 +36,214 @@ void main() {
33
36
'https://flutter.github.io/assets-for-api-docs/assets/videos/bee.mp4'
34
37
..preload = 'true'
35
38
..width = 10
36
- ..height = 10 ;
39
+ ..height = 10
40
+ ..crossOrigin = 'anonymous' ;
41
+
42
+ cameraSettings = MockCameraSettings ();
37
43
38
44
when (() => window.navigator).thenReturn (navigator);
39
45
when (() => navigator.mediaDevices).thenReturn (mediaDevices);
40
46
when (
41
47
() => mediaDevices.getUserMedia (any ()),
42
48
).thenAnswer ((_) async => videoElement.captureStream ());
43
49
44
- CameraPlatform .instance = CameraPlugin ()..window = window;
50
+ CameraPlatform .instance = CameraPlugin (
51
+ cameraSettings: cameraSettings,
52
+ )..window = window;
53
+ });
54
+
55
+ setUpAll (() {
56
+ registerFallbackValue <MediaStreamTrack >(MockMediaStreamTrack ());
45
57
});
46
58
47
59
testWidgets ('CameraPlugin is the live instance' , (tester) async {
48
60
expect (CameraPlatform .instance, isA <CameraPlugin >());
49
61
});
50
62
51
- testWidgets ('availableCameras throws UnimplementedError' , (tester) async {
52
- expect (
53
- () => CameraPlatform .instance.availableCameras (),
54
- throwsUnimplementedError,
55
- );
63
+ group ('availableCameras' , () {
64
+ setUp (() {
65
+ when (
66
+ () => cameraSettings.getLensDirectionForVideoTrack (
67
+ any (),
68
+ ),
69
+ ).thenReturn (CameraLensDirection .external );
70
+ });
71
+
72
+ testWidgets (
73
+ 'throws CameraException '
74
+ 'with notSupported error '
75
+ 'when there are no media devices' , (tester) async {
76
+ when (() => navigator.mediaDevices).thenReturn (null );
77
+
78
+ expect (
79
+ () => CameraPlatform .instance.availableCameras (),
80
+ throwsA (
81
+ isA <CameraException >().having (
82
+ (e) => e.code,
83
+ 'code' ,
84
+ CameraErrorCodes .notSupported,
85
+ ),
86
+ ),
87
+ );
88
+ });
89
+
90
+ testWidgets (
91
+ 'calls MediaDevices.getUserMedia '
92
+ 'on the video input device' , (tester) async {
93
+ final videoDevice = FakeMediaDeviceInfo (
94
+ '1' ,
95
+ 'Camera 1' ,
96
+ MediaDeviceKind .videoInput,
97
+ );
98
+
99
+ when (mediaDevices.enumerateDevices).thenAnswer (
100
+ (_) => Future .value ([videoDevice]),
101
+ );
102
+
103
+ final _ = await CameraPlatform .instance.availableCameras ();
104
+
105
+ verify (
106
+ () => mediaDevices.getUserMedia (
107
+ CameraOptions (
108
+ video: VideoConstraints (
109
+ deviceId: videoDevice.deviceId,
110
+ ),
111
+ ).toJson (),
112
+ ),
113
+ ).called (1 );
114
+ });
115
+
116
+ testWidgets (
117
+ 'calls CameraSettings.getLensDirectionForVideoTrack '
118
+ 'on the first video track of the video input device' , (tester) async {
119
+ final videoDevice = FakeMediaDeviceInfo (
120
+ '1' ,
121
+ 'Camera 1' ,
122
+ MediaDeviceKind .videoInput,
123
+ );
124
+
125
+ final videoStream =
126
+ FakeMediaStream ([MockMediaStreamTrack (), MockMediaStreamTrack ()]);
127
+
128
+ when (
129
+ () => mediaDevices.getUserMedia (
130
+ CameraOptions (
131
+ video: VideoConstraints (deviceId: videoDevice.deviceId),
132
+ ).toJson (),
133
+ ),
134
+ ).thenAnswer ((_) => Future .value (videoStream));
135
+
136
+ when (mediaDevices.enumerateDevices).thenAnswer (
137
+ (_) => Future .value ([videoDevice]),
138
+ );
139
+
140
+ final _ = await CameraPlatform .instance.availableCameras ();
141
+
142
+ verify (
143
+ () => cameraSettings.getLensDirectionForVideoTrack (
144
+ videoStream.getVideoTracks ().first,
145
+ ),
146
+ ).called (1 );
147
+ });
148
+
149
+ testWidgets (
150
+ 'returns appropriate camera descriptions '
151
+ 'for multiple media devices' , (tester) async {
152
+ final firstVideoDevice = FakeMediaDeviceInfo (
153
+ '1' ,
154
+ 'Camera 1' ,
155
+ MediaDeviceKind .videoInput,
156
+ );
157
+
158
+ final secondVideoDevice = FakeMediaDeviceInfo (
159
+ '4' ,
160
+ '' , // The device label might be empty.
161
+ MediaDeviceKind .videoInput,
162
+ );
163
+
164
+ // Create a video stream for the first video device.
165
+ final firstVideoStream =
166
+ FakeMediaStream ([MockMediaStreamTrack (), MockMediaStreamTrack ()]);
167
+
168
+ // Create a video stream for the second video device.
169
+ final secondVideoStream = FakeMediaStream ([MockMediaStreamTrack ()]);
170
+
171
+ // Mock media devices to return two video input devices
172
+ // and two audio devices.
173
+ when (mediaDevices.enumerateDevices).thenAnswer (
174
+ (_) => Future .value ([
175
+ firstVideoDevice,
176
+ FakeMediaDeviceInfo (
177
+ '2' ,
178
+ 'Camera 2' ,
179
+ MediaDeviceKind .audioInput,
180
+ ),
181
+ FakeMediaDeviceInfo (
182
+ '3' ,
183
+ 'Camera 3' ,
184
+ MediaDeviceKind .audioOutput,
185
+ ),
186
+ secondVideoDevice,
187
+ ]),
188
+ );
189
+
190
+ // Mock media devices to return the first video stream
191
+ // for the first video device.
192
+ when (
193
+ () => mediaDevices.getUserMedia (
194
+ CameraOptions (
195
+ video: VideoConstraints (deviceId: firstVideoDevice.deviceId),
196
+ ).toJson (),
197
+ ),
198
+ ).thenAnswer ((_) => Future .value (firstVideoStream));
199
+
200
+ // Mock media devices to return the second video stream
201
+ // for the second video device.
202
+ when (
203
+ () => mediaDevices.getUserMedia (
204
+ CameraOptions (
205
+ video: VideoConstraints (deviceId: secondVideoDevice.deviceId),
206
+ ).toJson (),
207
+ ),
208
+ ).thenAnswer ((_) => Future .value (secondVideoStream));
209
+
210
+ // Mock camera settings to return a front lens direction
211
+ // for the first video stream.
212
+ when (
213
+ () => cameraSettings.getLensDirectionForVideoTrack (
214
+ firstVideoStream.getVideoTracks ().first,
215
+ ),
216
+ ).thenReturn (CameraLensDirection .front);
217
+
218
+ // Mock camera settings to return a back lens direction
219
+ // for the second video stream.
220
+ when (
221
+ () => cameraSettings.getLensDirectionForVideoTrack (
222
+ secondVideoStream.getVideoTracks ().first,
223
+ ),
224
+ ).thenReturn (CameraLensDirection .back);
225
+
226
+ final cameras = await CameraPlatform .instance.availableCameras ();
227
+
228
+ // Expect two cameras and ignore two audio devices.
229
+ expect (
230
+ cameras,
231
+ equals ([
232
+ CameraDescription (
233
+ // Uses the device label as a camera name.
234
+ name: firstVideoDevice.label! ,
235
+ lensDirection: CameraLensDirection .front,
236
+ sensorOrientation: 0 ,
237
+ ),
238
+ CameraDescription (
239
+ // Fallbacks to the device id if the label is empty.
240
+ name: secondVideoDevice.deviceId! ,
241
+ lensDirection: CameraLensDirection .back,
242
+ sensorOrientation: 0 ,
243
+ )
244
+ ]),
245
+ );
246
+ });
56
247
});
57
248
58
249
testWidgets ('createCamera throws UnimplementedError' , (tester) async {
0 commit comments