UNPKG

23.4 kBPlain TextView Raw
1/* tslint:disable:no-implicit-dependencies no-any */
2/**
3 * CameraAccess tests
4 */
5import test from "ava";
6import * as sinon from "sinon";
7
8import { BrowserHelper, Camera, CameraAccess } from "..";
9
10const getUserMediaStub: sinon.SinonStub = sinon.stub();
11const getVideoTracksStub: sinon.SinonStub = sinon.stub();
12const applyConstraintsStub: sinon.SinonStub = sinon.stub();
13const getCapabilitiesStub: sinon.SinonStub = sinon.stub();
14const getConstraintsStub: sinon.SinonStub = sinon.stub();
15const getSettingsStub: sinon.SinonStub = sinon.stub();
16const stopStub: sinon.SinonStub = sinon.stub();
17const getSourcesStub: sinon.SinonStub = sinon.stub();
18const enumerateDevicesStub: sinon.SinonStub = sinon.stub();
19
20const stubs: sinon.SinonStub[] = [
21 getUserMediaStub,
22 getVideoTracksStub,
23 applyConstraintsStub,
24 getCapabilitiesStub,
25 getConstraintsStub,
26 getSettingsStub,
27 stopStub,
28 getSourcesStub,
29 enumerateDevicesStub
30];
31
32const emptyCamera: MediaDeviceInfo = {
33 deviceId: "1",
34 groupId: "1",
35 kind: "videoinput",
36 label: "",
37 toJSON(): MediaDeviceInfo {
38 return this;
39 }
40};
41
42const fakeCamera1: MediaDeviceInfo = {
43 deviceId: "1",
44 groupId: "1",
45 kind: "videoinput",
46 label: "Fake Camera Device (back)",
47 toJSON(): MediaDeviceInfo {
48 return this;
49 }
50};
51
52const fakeCamera2: MediaDeviceInfo = {
53 deviceId: "2",
54 groupId: "1",
55 kind: "videoinput",
56 label: "Fake Camera Device (front)",
57 toJSON(): MediaDeviceInfo {
58 return this;
59 }
60};
61
62const fakeCamera3: MediaDeviceInfo = {
63 deviceId: "3",
64 groupId: "1",
65 kind: "videoinput",
66 label: "Fake Camera Device (posteriore)",
67 toJSON(): MediaDeviceInfo {
68 return this;
69 }
70};
71
72const fakeCamera4: MediaDeviceInfo = {
73 deviceId: "4",
74 groupId: "1",
75 kind: "videoinput",
76 label: "Fake Camera Device (unknown)",
77 toJSON(): MediaDeviceInfo {
78 return this;
79 }
80};
81
82const fakeCamera5: MediaDeviceInfo = {
83 deviceId: "5",
84 groupId: "1",
85 kind: "videoinput",
86 label: "Fake Camera Device (unknown)",
87 toJSON(): MediaDeviceInfo {
88 return this;
89 }
90};
91
92const fakeCamera6: MediaDeviceInfo = {
93 deviceId: "6",
94 groupId: "1",
95 kind: "videoinput",
96 label: "Fake Camera Device 5MP",
97 toJSON(): MediaDeviceInfo {
98 return this;
99 }
100};
101
102const fakeCamera7: MediaDeviceInfo = {
103 deviceId: "7",
104 groupId: "1",
105 kind: "videoinput",
106 label: "Fake Camera Device 2MP",
107 toJSON(): MediaDeviceInfo {
108 return this;
109 }
110};
111
112const fakeCamera8: MediaDeviceInfo = {
113 deviceId: "8",
114 groupId: "1",
115 kind: "videoinput",
116 label: "camera2 8, facing back",
117 toJSON(): MediaDeviceInfo {
118 return this;
119 }
120};
121
122const fakeCamera9: MediaDeviceInfo = {
123 deviceId: "9",
124 groupId: "1",
125 kind: "videoinput",
126 label: "camera2 9, facing back",
127 toJSON(): MediaDeviceInfo {
128 return this;
129 }
130};
131
132const illegalFakeCamera1: MediaDeviceInfo = <MediaDeviceInfo>(<unknown>{
133 deviceId: "10",
134 groupId: "1",
135 kind: "videoinput"
136});
137
138const legacyFakeCamera1: MediaDeviceInfo = <MediaDeviceInfo>(<unknown>{
139 groupId: "1",
140 kind: "videoinput",
141 label: "Fake Camera Device (back)"
142});
143
144const legacyFakeCamera2: MediaDeviceInfo = <MediaDeviceInfo>(<unknown>{
145 deviceId: "100",
146 groupId: "1",
147 kind: "video",
148 label: "Fake Camera Device (front)"
149});
150
151const fakeMicrophone: MediaDeviceInfo = {
152 deviceId: "1000",
153 groupId: "1",
154 kind: "audioinput",
155 label: "Fake Microhpone Device #2",
156 toJSON(): MediaDeviceInfo {
157 return this;
158 }
159};
160
161function fakeCompatibleBrowser(): void {
162 Object.defineProperty(navigator, "mediaDevices", {
163 value: {
164 getUserMedia: getUserMediaStub.resolves({
165 getTracks: getVideoTracksStub,
166 getVideoTracks: getVideoTracksStub
167 })
168 },
169 configurable: true
170 });
171 getVideoTracksStub.returns([
172 {
173 applyConstraints: applyConstraintsStub.resolves(),
174 getCapabilities: getCapabilitiesStub.returns(123),
175 getConstraints: getConstraintsStub.returns(456),
176 getSettings: getSettingsStub.returns(789),
177 stop: stopStub
178 }
179 ]);
180
181 window.Blob = <Window["Blob"]>(<unknown>(() => {
182 return;
183 }));
184 window.URL = <Window["URL"]>(<unknown>{
185 createObjectURL: () => {
186 return;
187 }
188 });
189 window.Worker = () => {
190 return;
191 };
192 window.WebAssembly = {};
193}
194
195function resetStubs(): void {
196 stubs.forEach(mock => {
197 mock.resetHistory();
198 });
199}
200
201function getFakeMediaStreamTrack(deviceId: string, facingMode: string, label: string): MediaStreamTrack {
202 return <MediaStreamTrack>(<unknown>{
203 getSettings(): object {
204 return {
205 deviceId,
206 facingMode
207 };
208 },
209 label
210 });
211}
212
213function deepObjectArrayCopy<T>(objectArray: T[]): T[] {
214 return objectArray.map(object => {
215 return { ...object };
216 });
217}
218
219test.beforeEach(() => {
220 window.MediaStreamTrack = undefined;
221 navigator.enumerateDevices = undefined;
222});
223
224test.serial("getCameras (errors)", async t => {
225 resetStubs();
226 let error: Error = await t.throwsAsync(CameraAccess.getCameras());
227 t.is(error.name, "UnsupportedBrowserError");
228 t.false(getUserMediaStub.called);
229 t.false(getSourcesStub.called);
230 fakeCompatibleBrowser();
231 navigator.mediaDevices.enumerateDevices = enumerateDevicesStub
232 .onFirstCall()
233 .resolves([])
234 .onSecondCall()
235 .rejects(new Error("Test error 1"));
236 resetStubs();
237 error = await t.throwsAsync(CameraAccess.getCameras());
238 t.is(error.message, "Test error 1");
239 t.true(getUserMediaStub.called);
240 t.false(getSourcesStub.called);
241 enumerateDevicesStub.reset();
242 navigator.mediaDevices.enumerateDevices = enumerateDevicesStub.resolves([]);
243 navigator.mediaDevices.getUserMedia = getUserMediaStub.rejects(new Error("Test error 2"));
244 resetStubs();
245 error = await t.throwsAsync(CameraAccess.getCameras());
246 t.is(error.message, "Test error 2");
247 t.true(getUserMediaStub.called);
248 t.false(getSourcesStub.called);
249});
250
251test.serial("getCameras (MediaStreamTrack.getSources)", async t => {
252 fakeCompatibleBrowser();
253 // Intentionally no legacy method
254 window.MediaStreamTrack = {};
255 resetStubs();
256 let error: Error = await t.throwsAsync(CameraAccess.getCameras());
257 t.is(error.name, "UnsupportedBrowserError");
258 t.false(getUserMediaStub.called);
259 // Intentionally wrong legacy method
260 window.MediaStreamTrack = {
261 getSources: getSourcesStub.callsArgWith(0, null)
262 };
263 resetStubs();
264 error = await t.throwsAsync(CameraAccess.getCameras());
265 t.is(error.name, "UnsupportedBrowserError");
266 t.false(getUserMediaStub.called);
267 t.true(getSourcesStub.called);
268 window.MediaStreamTrack = {
269 getSources: getSourcesStub.callsArgWith(0, [emptyCamera])
270 };
271 resetStubs();
272 let cameras: Camera[] = await CameraAccess.getCameras();
273 t.true(getUserMediaStub.called);
274 t.true(getSourcesStub.called);
275 t.not(cameras, null);
276 t.is(cameras.length, 1);
277 window.MediaStreamTrack = {
278 getSources: getSourcesStub.callsArgWith(0, [
279 fakeCamera1,
280 fakeCamera2,
281 legacyFakeCamera1,
282 legacyFakeCamera2,
283 fakeMicrophone
284 ])
285 };
286 resetStubs();
287 cameras = await CameraAccess.getCameras();
288 t.false(getUserMediaStub.called);
289 t.true(getSourcesStub.called);
290 t.not(cameras, null);
291 t.is(cameras.length, 4);
292 resetStubs();
293 const newCameras: Camera[] = await CameraAccess.getCameras();
294 t.false(getUserMediaStub.called);
295 t.true(getSourcesStub.called);
296 t.deepEqual(cameras, newCameras);
297 t.is(cameras[0].deviceId, fakeCamera1.deviceId);
298 t.is(cameras[0].label, fakeCamera1.label);
299 t.is(cameras[0].cameraType, Camera.Type.BACK);
300 t.is(cameras[0].currentResolution, undefined);
301 t.is(cameras[1].deviceId, fakeCamera2.deviceId);
302 t.is(cameras[1].label, fakeCamera2.label);
303 t.is(cameras[1].cameraType, Camera.Type.FRONT);
304 t.is(cameras[1].currentResolution, undefined);
305 t.is(cameras[2].deviceId, "");
306 t.is(cameras[2].label, legacyFakeCamera1.label);
307 t.is(cameras[2].cameraType, Camera.Type.BACK);
308 t.is(cameras[2].currentResolution, undefined);
309 t.is(cameras[3].deviceId, legacyFakeCamera2.deviceId);
310 t.is(cameras[3].label, legacyFakeCamera2.label);
311 t.is(cameras[3].cameraType, Camera.Type.FRONT);
312 t.is(cameras[3].currentResolution, undefined);
313});
314
315test.serial("getCameras (navigator.enumerateDevices & navigator.mediaDevices.enumerateDevices)", async t => {
316 fakeCompatibleBrowser();
317 window.MediaStreamTrack = {
318 getSources: getSourcesStub
319 };
320 for (const baseObject of [navigator, navigator.mediaDevices]) {
321 baseObject.enumerateDevices = enumerateDevicesStub.resolves([emptyCamera]);
322 resetStubs();
323 let cameras: Camera[] = await CameraAccess.getCameras();
324 t.true(getUserMediaStub.called);
325 t.true(enumerateDevicesStub.called);
326 t.false(getSourcesStub.called);
327 t.not(cameras, null);
328 t.is(cameras.length, 1);
329 baseObject.enumerateDevices = enumerateDevicesStub.resolves([
330 fakeCamera1,
331 fakeCamera2,
332 illegalFakeCamera1,
333 fakeMicrophone
334 ]);
335 resetStubs();
336 cameras = await CameraAccess.getCameras();
337 t.false(getUserMediaStub.called);
338 t.true(enumerateDevicesStub.called);
339 t.false(getSourcesStub.called);
340 t.not(cameras, null);
341 t.is(cameras.length, 3);
342 resetStubs();
343 const newCameras: Camera[] = await CameraAccess.getCameras();
344 t.false(getUserMediaStub.called);
345 t.true(enumerateDevicesStub.called);
346 t.false(getSourcesStub.called);
347 t.deepEqual(cameras, newCameras);
348 t.is(cameras[0].deviceId, fakeCamera1.deviceId);
349 t.is(cameras[0].label, fakeCamera1.label);
350 t.is(cameras[0].cameraType, Camera.Type.BACK);
351 t.is(cameras[0].currentResolution, undefined);
352 t.is(cameras[1].deviceId, fakeCamera2.deviceId);
353 t.is(cameras[1].label, fakeCamera2.label);
354 t.is(cameras[1].cameraType, Camera.Type.FRONT);
355 t.is(cameras[1].currentResolution, undefined);
356 t.is(cameras[2].deviceId, illegalFakeCamera1.deviceId);
357 t.is(cameras[2].label, "");
358 t.is(cameras[2].cameraType, Camera.Type.FRONT);
359 t.is(cameras[2].currentResolution, undefined);
360 }
361});
362
363test.serial("getCameras (internationalized label)", async t => {
364 fakeCompatibleBrowser();
365 navigator.mediaDevices.enumerateDevices = enumerateDevicesStub.resolves([fakeCamera3]);
366 resetStubs();
367 const cameras: Camera[] = await CameraAccess.getCameras();
368 t.not(cameras, null);
369 t.is(cameras.length, 1);
370 t.is(cameras[0].deviceId, fakeCamera3.deviceId);
371 t.is(cameras[0].label, fakeCamera3.label);
372 t.is(cameras[0].cameraType, Camera.Type.BACK);
373 t.is(cameras[0].currentResolution, undefined);
374});
375
376test.serial("getCameras (no front/back label information)", async t => {
377 fakeCompatibleBrowser();
378 navigator.mediaDevices.enumerateDevices = enumerateDevicesStub.resolves([fakeCamera4, fakeCamera5]);
379 resetStubs();
380 const cameras: Camera[] = await CameraAccess.getCameras();
381 t.not(cameras, null);
382 t.is(cameras.length, 2);
383 t.is(cameras[0].deviceId, fakeCamera4.deviceId);
384 t.is(cameras[0].label, fakeCamera4.label);
385 t.is(cameras[0].cameraType, Camera.Type.FRONT);
386 t.is(cameras[0].currentResolution, undefined);
387 t.is(cameras[1].deviceId, fakeCamera5.deviceId);
388 t.is(cameras[1].label, fakeCamera5.label);
389 t.is(cameras[1].cameraType, Camera.Type.BACK);
390 t.is(cameras[1].currentResolution, undefined);
391});
392
393test.serial("getCameras (resolution label information)", async t => {
394 fakeCompatibleBrowser();
395 navigator.mediaDevices.enumerateDevices = enumerateDevicesStub.resolves([fakeCamera6, fakeCamera7]);
396 resetStubs();
397 const cameras: Camera[] = await CameraAccess.getCameras();
398 t.not(cameras, null);
399 t.is(cameras.length, 2);
400 t.is(cameras[0].deviceId, fakeCamera6.deviceId);
401 t.is(cameras[0].label, fakeCamera6.label);
402 t.is(cameras[0].cameraType, Camera.Type.BACK);
403 t.is(cameras[0].currentResolution, undefined);
404 t.is(cameras[1].deviceId, fakeCamera7.deviceId);
405 t.is(cameras[1].label, fakeCamera7.label);
406 t.is(cameras[1].cameraType, Camera.Type.FRONT);
407 t.is(cameras[1].currentResolution, undefined);
408});
409
410test.serial("getCameras (quickly consecutively)", async t => {
411 fakeCompatibleBrowser();
412 navigator.mediaDevices.enumerateDevices = enumerateDevicesStub.resolves([fakeCamera1, fakeCamera2]);
413 resetStubs();
414 await CameraAccess.getCameras();
415 t.is(enumerateDevicesStub.callCount, 2);
416 resetStubs();
417 // tslint:disable-next-line: no-floating-promises
418 CameraAccess.getCameras();
419 const cameras: Camera[] = await CameraAccess.getCameras();
420 t.is(enumerateDevicesStub.callCount, 2);
421 t.not(cameras, null);
422 t.is(cameras.length, 2);
423 t.is(cameras[0].deviceId, fakeCamera1.deviceId);
424 t.is(cameras[0].label, fakeCamera1.label);
425 t.is(cameras[0].cameraType, Camera.Type.BACK);
426 t.is(cameras[0].currentResolution, undefined);
427 t.is(cameras[1].deviceId, fakeCamera2.deviceId);
428 t.is(cameras[1].label, fakeCamera2.label);
429 t.is(cameras[1].cameraType, Camera.Type.FRONT);
430 t.is(cameras[1].currentResolution, undefined);
431});
432
433test.serial("adjustCamerasFromMainCameraStream", async t => {
434 fakeCompatibleBrowser();
435 navigator.mediaDevices.enumerateDevices = enumerateDevicesStub.resolves([fakeCamera1, fakeCamera2]);
436 const originalCameras: Camera[] = await CameraAccess.getCameras();
437 let cams: Camera[] = deepObjectArrayCopy(originalCameras);
438 t.is(CameraAccess.adjustCamerasFromMainCameraStream(<MediaStreamTrack>(<unknown>{}), cams), undefined);
439 t.is(cams[0].cameraType, Camera.Type.BACK);
440 t.is(cams[1].cameraType, Camera.Type.FRONT);
441 cams = deepObjectArrayCopy(originalCameras);
442 t.is(CameraAccess.adjustCamerasFromMainCameraStream(getFakeMediaStreamTrack("1", "environment", ""), cams), cams[0]);
443 t.is(cams[0].cameraType, Camera.Type.BACK);
444 t.is(cams[1].cameraType, Camera.Type.FRONT);
445 cams = deepObjectArrayCopy(originalCameras);
446 t.is(
447 CameraAccess.adjustCamerasFromMainCameraStream(getFakeMediaStreamTrack("2", "environment", ""), cams),
448 undefined
449 );
450 t.is(cams[0].cameraType, Camera.Type.BACK);
451 t.is(cams[1].cameraType, Camera.Type.BACK);
452 cams = deepObjectArrayCopy(originalCameras);
453 t.is(CameraAccess.adjustCamerasFromMainCameraStream(getFakeMediaStreamTrack("2", "user", ""), cams), undefined);
454 t.is(cams[0].cameraType, Camera.Type.BACK);
455 t.is(cams[1].cameraType, Camera.Type.FRONT);
456});
457
458test.serial("adjustCamerasFromMainCameraStream (unknown cameras)", async t => {
459 fakeCompatibleBrowser();
460 navigator.mediaDevices.enumerateDevices = enumerateDevicesStub.resolves([fakeCamera4, fakeCamera5]);
461 const originalCameras: Camera[] = await CameraAccess.getCameras();
462 let cams: Camera[] = deepObjectArrayCopy(originalCameras);
463 t.is(CameraAccess.adjustCamerasFromMainCameraStream(<MediaStreamTrack>(<unknown>{}), cams), undefined);
464 t.is(cams[0].cameraType, Camera.Type.FRONT);
465 t.is(cams[1].cameraType, Camera.Type.BACK);
466 cams = deepObjectArrayCopy(originalCameras);
467 t.is(CameraAccess.adjustCamerasFromMainCameraStream(getFakeMediaStreamTrack("4", "environment", ""), cams), cams[0]);
468 t.is(cams[0].cameraType, Camera.Type.BACK);
469 t.is(cams[1].cameraType, Camera.Type.FRONT);
470 cams = deepObjectArrayCopy(originalCameras);
471 t.is(CameraAccess.adjustCamerasFromMainCameraStream(getFakeMediaStreamTrack("5", "environment", ""), cams), cams[1]);
472 t.is(cams[0].cameraType, Camera.Type.FRONT);
473 t.is(cams[1].cameraType, Camera.Type.BACK);
474 cams = deepObjectArrayCopy(originalCameras);
475 t.is(CameraAccess.adjustCamerasFromMainCameraStream(getFakeMediaStreamTrack("5", "user", ""), cams), undefined);
476 t.is(cams[0].cameraType, Camera.Type.FRONT);
477 t.is(cams[1].cameraType, Camera.Type.BACK);
478});
479
480test.serial("adjustCamerasFromMainCameraStream (triple camera setup)", async t => {
481 // Back cameras with the lowest ID in label are the main one
482 fakeCompatibleBrowser();
483 navigator.mediaDevices.enumerateDevices = enumerateDevicesStub.resolves([fakeCamera2, fakeCamera9, fakeCamera8]);
484 const originalCameras: Camera[] = await CameraAccess.getCameras();
485 let cams: Camera[] = deepObjectArrayCopy(originalCameras);
486 t.is(CameraAccess.adjustCamerasFromMainCameraStream(getFakeMediaStreamTrack("8", "environment", ""), cams), cams[2]);
487 t.is(cams[0].cameraType, Camera.Type.FRONT);
488 t.is(cams[1].cameraType, Camera.Type.BACK);
489 t.is(cams[2].cameraType, Camera.Type.BACK);
490 cams = deepObjectArrayCopy(originalCameras);
491 t.is(
492 CameraAccess.adjustCamerasFromMainCameraStream(getFakeMediaStreamTrack("9", "environment", ""), cams),
493 undefined
494 );
495 t.is(cams[0].cameraType, Camera.Type.FRONT);
496 t.is(cams[1].cameraType, Camera.Type.BACK);
497 t.is(cams[2].cameraType, Camera.Type.BACK);
498});
499
500// tslint:disable-next-line:max-func-body-length
501test.serial("accessCameraStream", async t => {
502 fakeCompatibleBrowser();
503 const fakeEmptyBackCamera: Camera = {
504 deviceId: "",
505 label: "",
506 cameraType: Camera.Type.BACK
507 };
508
509 resetStubs();
510 let mediaStream: MediaStream = await CameraAccess.accessCameraStream(0, fakeEmptyBackCamera);
511 t.true(getUserMediaStub.called);
512 t.deepEqual(getUserMediaStub.args[0][0], {
513 audio: false,
514 video: {
515 facingMode: { ideal: "environment" },
516 width: { min: 1400, ideal: 1920, max: 1920 },
517 height: { min: 900, ideal: 1440, max: 1440 }
518 }
519 });
520 t.not(mediaStream, null);
521
522 const fakeEmptyFrontCamera: Camera = {
523 deviceId: "",
524 label: "",
525 cameraType: Camera.Type.FRONT
526 };
527
528 resetStubs();
529 mediaStream = await CameraAccess.accessCameraStream(0, fakeEmptyFrontCamera);
530 t.true(getUserMediaStub.called);
531 t.deepEqual(getUserMediaStub.args[0][0], {
532 audio: false,
533 video: {
534 facingMode: { ideal: "user" },
535 width: { min: 1400, ideal: 1920, max: 1920 },
536 height: { min: 900, ideal: 1440, max: 1440 }
537 }
538 });
539 t.not(mediaStream, null);
540
541 const fakeCamera: Camera = {
542 deviceId: fakeCamera1.deviceId,
543 label: fakeCamera1.label,
544 cameraType: Camera.Type.BACK
545 };
546
547 resetStubs();
548 mediaStream = await CameraAccess.accessCameraStream(0, fakeCamera);
549 t.true(getUserMediaStub.called);
550 t.deepEqual(getUserMediaStub.args[0][0], {
551 audio: false,
552 video: {
553 deviceId: { exact: fakeCamera.deviceId },
554 width: { min: 1400, ideal: 1920, max: 1920 },
555 height: { min: 900, ideal: 1440, max: 1440 }
556 }
557 });
558 t.not(mediaStream, null);
559 resetStubs();
560 mediaStream = await CameraAccess.accessCameraStream(1, fakeCamera);
561 t.true(getUserMediaStub.called);
562 t.deepEqual(getUserMediaStub.args[0][0], {
563 audio: false,
564 video: {
565 deviceId: { exact: fakeCamera.deviceId },
566 width: { min: 1200, ideal: 1920, max: 1920 },
567 height: { min: 900, ideal: 1200, max: 1200 }
568 }
569 });
570 t.not(mediaStream, null);
571 resetStubs();
572 mediaStream = await CameraAccess.accessCameraStream(2, fakeCamera);
573 t.true(getUserMediaStub.called);
574 t.deepEqual(getUserMediaStub.args[0][0], {
575 audio: false,
576 video: {
577 deviceId: { exact: fakeCamera.deviceId },
578 width: { min: 1080, ideal: 1920, max: 1920 },
579 height: { min: 900, ideal: 1080, max: 1080 }
580 }
581 });
582 t.not(mediaStream, null);
583 resetStubs();
584 mediaStream = await CameraAccess.accessCameraStream(3, fakeCamera);
585 t.true(getUserMediaStub.called);
586 t.deepEqual(getUserMediaStub.args[0][0], {
587 audio: false,
588 video: {
589 deviceId: { exact: fakeCamera.deviceId },
590 width: { min: 960, ideal: 1280, max: 1440 },
591 height: { min: 480, ideal: 960, max: 960 }
592 }
593 });
594 t.not(mediaStream, null);
595 resetStubs();
596 mediaStream = await CameraAccess.accessCameraStream(4, fakeCamera);
597 t.true(getUserMediaStub.called);
598 t.deepEqual(getUserMediaStub.args[0][0], {
599 audio: false,
600 video: {
601 deviceId: { exact: fakeCamera.deviceId },
602 width: { min: 720, ideal: 1280, max: 1440 },
603 height: { min: 480, ideal: 720, max: 768 }
604 }
605 });
606 t.not(mediaStream, null);
607 resetStubs();
608 mediaStream = await CameraAccess.accessCameraStream(5, fakeCamera);
609 t.true(getUserMediaStub.called);
610 t.deepEqual(getUserMediaStub.args[0][0], {
611 audio: false,
612 video: {
613 deviceId: { exact: fakeCamera.deviceId },
614 width: { min: 640, ideal: 960, max: 1440 },
615 height: { min: 480, ideal: 720, max: 720 }
616 }
617 });
618 t.not(mediaStream, null);
619 resetStubs();
620 mediaStream = await CameraAccess.accessCameraStream(6, fakeCamera);
621 t.true(getUserMediaStub.called);
622 t.deepEqual(getUserMediaStub.args[0][0], {
623 audio: false,
624 video: {
625 deviceId: { exact: fakeCamera.deviceId }
626 }
627 });
628 t.not(mediaStream, null);
629});
630
631test.serial("accessCameraStream (Safari)", async t => {
632 fakeCompatibleBrowser();
633 BrowserHelper.userAgentInfo.setUA(
634 "Mozilla/5.0 (iPhone; CPU iPhone OS 11_3 like Mac OS X) " +
635 "AppleWebKit/605.1.15 (KHTML, like Gecko) Version/11.0 Mobile/15E148 Safari/604.1"
636 );
637
638 const fakeCamera: Camera = {
639 deviceId: fakeCamera1.deviceId,
640 label: fakeCamera1.label,
641 cameraType: Camera.Type.BACK
642 };
643
644 resetStubs();
645 let mediaStream: MediaStream = await CameraAccess.accessCameraStream(0, fakeCamera);
646 t.true(getUserMediaStub.called);
647 t.deepEqual(getUserMediaStub.args[0][0], {
648 audio: false,
649 video: {
650 deviceId: { exact: fakeCamera.deviceId },
651 width: { min: 1400, ideal: 1920, max: 1920 },
652 height: { min: 900, ideal: 1080, max: 1440 }
653 }
654 });
655 t.not(mediaStream, null);
656 resetStubs();
657 mediaStream = await CameraAccess.accessCameraStream(1, fakeCamera);
658 t.true(getUserMediaStub.called);
659 t.deepEqual(getUserMediaStub.args[0][0], {
660 audio: false,
661 video: {
662 deviceId: { exact: fakeCamera.deviceId },
663 width: { min: 1200, ideal: 1600, max: 1920 },
664 height: { min: 900, ideal: 1080, max: 1200 }
665 }
666 });
667 t.not(mediaStream, null);
668 resetStubs();
669 mediaStream = await CameraAccess.accessCameraStream(2, fakeCamera);
670 t.true(getUserMediaStub.called);
671 t.deepEqual(getUserMediaStub.args[0][0], {
672 audio: false,
673 video: {
674 deviceId: { exact: fakeCamera.deviceId },
675 width: { min: 1080, ideal: 1600, max: 1920 },
676 height: { min: 900, ideal: 900, max: 1080 }
677 }
678 });
679 t.not(mediaStream, null);
680 resetStubs();
681 mediaStream = await CameraAccess.accessCameraStream(3, fakeCamera);
682 t.true(getUserMediaStub.called);
683 t.deepEqual(getUserMediaStub.args[0][0], {
684 audio: false,
685 video: {
686 deviceId: { exact: fakeCamera.deviceId },
687 width: { min: 960, ideal: 1280, max: 1440 },
688 height: { min: 480, ideal: 720, max: 960 }
689 }
690 });
691 t.not(mediaStream, null);
692 resetStubs();
693 mediaStream = await CameraAccess.accessCameraStream(4, fakeCamera);
694 t.true(getUserMediaStub.called);
695 t.deepEqual(getUserMediaStub.args[0][0], {
696 audio: false,
697 video: {
698 deviceId: { exact: fakeCamera.deviceId },
699 width: { min: 720, ideal: 1024, max: 1440 },
700 height: { min: 480, ideal: 768, max: 768 }
701 }
702 });
703 t.not(mediaStream, null);
704 resetStubs();
705 mediaStream = await CameraAccess.accessCameraStream(5, fakeCamera);
706 t.true(getUserMediaStub.called);
707 t.deepEqual(getUserMediaStub.args[0][0], {
708 audio: false,
709 video: {
710 deviceId: { exact: fakeCamera.deviceId },
711 width: { min: 640, ideal: 800, max: 1440 },
712 height: { min: 480, ideal: 600, max: 720 }
713 }
714 });
715 t.not(mediaStream, null);
716 resetStubs();
717 mediaStream = await CameraAccess.accessCameraStream(6, fakeCamera);
718 t.true(getUserMediaStub.called);
719 t.deepEqual(getUserMediaStub.args[0][0], {
720 audio: false,
721 video: {
722 deviceId: { exact: fakeCamera.deviceId }
723 }
724 });
725 t.not(mediaStream, null);
726});