UNPKG

51.7 kBPlain TextView Raw
1/* tslint:disable:no-implicit-dependencies no-any */
2/**
3 * BarcodePicker tests
4 */
5
6import test from "ava";
7import * as sinon from "sinon";
8import { Worker } from "webworker-threads";
9import {
10 Barcode,
11 BarcodePicker,
12 BrowserCompatibility,
13 BrowserHelper,
14 Camera,
15 CameraSettings,
16 configure,
17 CustomError,
18 engineWorkerFunction,
19 ImageSettings,
20 Parser,
21 Scanner,
22 ScanResult,
23 ScanSettings
24} from "..";
25import { BarcodePickerCameraManager } from "./barcodePickerCameraManager";
26
27declare const global: any;
28
29HTMLVideoElement.prototype.load = () => {
30 return;
31};
32HTMLVideoElement.prototype.play = function(): Promise<void> {
33 Object.defineProperty(this, "videoWidth", {
34 value: 4
35 });
36 Object.defineProperty(this, "videoHeight", {
37 value: 4
38 });
39 this.currentTime = 1;
40 this.dispatchEvent(new Event("loadstart"));
41 this.dispatchEvent(new Event("loadeddata"));
42
43 return Promise.resolve();
44};
45
46const fakeCamera1: MediaDeviceInfo = {
47 deviceId: "1",
48 groupId: "1",
49 kind: "videoinput",
50 label: "Fake Camera Device (back)",
51 toJSON(): MediaDeviceInfo {
52 return this;
53 }
54};
55const fakeCamera2: MediaDeviceInfo = {
56 deviceId: "2",
57 groupId: "1",
58 kind: "videoinput",
59 label: "Fake Camera Device (front)",
60 toJSON(): MediaDeviceInfo {
61 return this;
62 }
63};
64
65const fakeCamera1Object: Camera = {
66 deviceId: fakeCamera1.deviceId,
67 label: fakeCamera1.label,
68 cameraType: Camera.Type.BACK,
69 currentResolution: {
70 width: 4,
71 height: 4
72 }
73};
74const fakeCamera2Object: Camera = {
75 deviceId: fakeCamera2.deviceId,
76 label: fakeCamera2.label,
77 cameraType: Camera.Type.FRONT,
78 currentResolution: {
79 width: 4,
80 height: 4
81 }
82};
83
84const sampleBarcode: Barcode = {
85 symbology: Barcode.Symbology.QR,
86 compositeFlag: Barcode.CompositeFlag.NONE,
87 isGs1DataCarrier: false,
88 encodingArray: [],
89 location: {
90 topLeft: { x: 0, y: 0 },
91 topRight: { x: 1, y: 0 },
92 bottomRight: { x: 1, y: 1 },
93 bottomLeft: { x: 0, y: 1 }
94 },
95 data: "",
96 rawData: new Uint8Array()
97};
98
99function fakePartialCompatibleBrowser(): void {
100 BrowserHelper.checkBrowserCompatibility = () => {
101 return {
102 fullSupport: false,
103 scannerSupport: true,
104 missingFeatures: [BrowserCompatibility.Feature.MEDIA_DEVICES]
105 };
106 };
107}
108
109async function fakeFullCompatibleBrowser(configureLibrary: boolean = true): Promise<void> {
110 const mediaStreamTrack: MediaStreamTrack = <MediaStreamTrack>(<unknown>{
111 stop: sinon.spy(),
112 addEventListener: sinon.spy(),
113 getSettings: () => {
114 return {
115 width: 4,
116 height: 4,
117 deviceId: "1",
118 facingMode: "environment"
119 };
120 }
121 });
122
123 Object.defineProperty(navigator, "mediaDevices", {
124 value: {
125 getUserMedia: () => {
126 return Promise.resolve({
127 getTracks: () => {
128 return [mediaStreamTrack];
129 },
130 getVideoTracks: () => {
131 return [mediaStreamTrack];
132 }
133 });
134 }
135 },
136 configurable: true
137 });
138 navigator.enumerateDevices = () => {
139 return Promise.resolve([fakeCamera1, fakeCamera2]);
140 };
141 URL.createObjectURL = sinon.stub();
142
143 BrowserHelper.checkBrowserCompatibility = () => {
144 return {
145 fullSupport: true,
146 scannerSupport: true,
147 missingFeatures: []
148 };
149 };
150
151 if (configureLibrary) {
152 await configure("#".repeat(64));
153 }
154}
155
156async function wait(ms: number): Promise<void> {
157 return new Promise(resolve => {
158 setTimeout(resolve, ms);
159 });
160}
161
162async function prepareBarcodePickerForEvents(): Promise<BarcodePicker> {
163 const s: Scanner = new Scanner();
164 const imageSettings: ImageSettings = {
165 width: 2,
166 height: 2,
167 format: ImageSettings.Format.GRAY_8U
168 };
169 s.applyImageSettings(imageSettings);
170 const barcodePicker: BarcodePicker = await BarcodePicker.create(document.createElement("div"), {
171 accessCamera: false,
172 scanner: s,
173 playSoundOnScan: true,
174 vibrateOnScan: true
175 });
176 sinon.stub((<any>barcodePicker).barcodePickerGui, "getVideoImageData").returns(new Uint8ClampedArray(4));
177 (<any>s).engineWorkerOnMessage({
178 data: ["status", "ready"]
179 });
180 sinon.stub(s, "processImage").callsFake(() => {
181 return Promise.resolve(new ScanResult([], new Uint8ClampedArray(4), imageSettings));
182 });
183
184 return barcodePicker;
185}
186
187global.Worker = Worker;
188global.URL = {
189 createObjectURL: () => {
190 return engineWorkerFunction;
191 }
192};
193
194test.serial("constructor & destroy", async t => {
195 let error: Error = await t.throwsAsync(BarcodePicker.create(document.createElement("div")));
196 t.is(error.name, "UnsupportedBrowserError");
197
198 await fakeFullCompatibleBrowser(false);
199 error = await t.throwsAsync(BarcodePicker.create(document.createElement("div")));
200 t.is(error.name, "LibraryNotConfiguredError");
201
202 await fakeFullCompatibleBrowser();
203 error = await t.throwsAsync(BarcodePicker.create(<HTMLElement>(<unknown>"wrong-argument")));
204 t.is(error.name, "NoOriginElementError");
205
206 error = await t.throwsAsync(BarcodePicker.create(<HTMLElement>(<unknown>{})));
207 t.is(error.name, "NoOriginElementError");
208
209 let barcodePicker: BarcodePicker = await BarcodePicker.create(document.createElement("div"), {
210 singleImageMode: {
211 desktop: { always: true, allowFallback: true },
212 mobile: { always: true, allowFallback: true }
213 }
214 });
215 barcodePicker.destroy();
216
217 fakePartialCompatibleBrowser();
218 barcodePicker = await BarcodePicker.create(document.createElement("div"), {
219 singleImageMode: {
220 desktop: { always: false, allowFallback: true },
221 mobile: { always: false, allowFallback: true }
222 }
223 });
224 barcodePicker.destroy();
225
226 barcodePicker = await BarcodePicker.create(document.createElement("div"));
227 barcodePicker.destroy(false);
228 barcodePicker.getScanner().destroy();
229
230 error = await t.throwsAsync(
231 BarcodePicker.create(document.createElement("div"), {
232 singleImageMode: {
233 desktop: { always: false, allowFallback: false },
234 mobile: { always: false, allowFallback: false }
235 }
236 })
237 );
238 t.is(error.name, "UnsupportedBrowserError");
239
240 barcodePicker = await BarcodePicker.create(document.createElement("div"), {
241 targetScanningFPS: -1
242 });
243 barcodePicker.destroy();
244 t.pass();
245
246 barcodePicker = await BarcodePicker.create(document.createElement("div"), {
247 scanner: new Scanner()
248 });
249 barcodePicker.destroy();
250 t.pass();
251
252 barcodePicker = await BarcodePicker.create(document.createElement("div"), {
253 accessCamera: false
254 });
255 barcodePicker.destroy();
256 t.pass();
257
258 BrowserHelper.userAgentInfo.setUA(
259 "Mozilla/5.0 (iPhone; CPU iPhone OS 11_3 like Mac OS X) " +
260 "AppleWebKit/605.1.15 (KHTML, like Gecko) Version/11.0 Mobile/15E148 Safari/604.1"
261 );
262 barcodePicker = await BarcodePicker.create(document.createElement("div"));
263 barcodePicker.destroy();
264 t.pass();
265});
266
267test.serial("constructor & destroy (with fake camera)", async t => {
268 await fakeFullCompatibleBrowser();
269 const s: Scanner = new Scanner();
270 const barcodePicker: BarcodePicker = await BarcodePicker.create(document.createElement("div"), {
271 scanner: s
272 });
273 (<any>s).engineWorkerOnMessage({
274 data: ["status", "ready"]
275 });
276 barcodePicker.destroy();
277 t.pass();
278});
279
280test.serial("constructor interaction options", async t => {
281 await fakeFullCompatibleBrowser();
282 const setInteractionOptionsSpy: sinon.SinonSpy<[boolean, boolean, boolean, boolean], void> = sinon.spy(
283 BarcodePickerCameraManager.prototype,
284 "setInteractionOptions"
285 );
286 let barcodePicker: BarcodePicker = await BarcodePicker.create(document.createElement("div"), {
287 accessCamera: false
288 });
289 t.is(setInteractionOptionsSpy.callCount, 1);
290 t.deepEqual(setInteractionOptionsSpy.getCall(0).args, [true, true, true, true]);
291 barcodePicker.destroy();
292 barcodePicker = await BarcodePicker.create(document.createElement("div"), {
293 accessCamera: false,
294 enableCameraSwitcher: false,
295 enableTorchToggle: false,
296 enableTapToFocus: false,
297 enablePinchToZoom: false
298 });
299 t.is(setInteractionOptionsSpy.callCount, 2);
300 t.deepEqual(setInteractionOptionsSpy.getCall(1).args, [false, false, false, false]);
301 barcodePicker.destroy();
302 barcodePicker = await BarcodePicker.create(document.createElement("div"), {
303 accessCamera: false,
304 enableCameraSwitcher: false,
305 enableTorchToggle: true,
306 enableTapToFocus: false,
307 enablePinchToZoom: true
308 });
309 t.is(setInteractionOptionsSpy.callCount, 3);
310 t.deepEqual(setInteractionOptionsSpy.getCall(2).args, [false, true, false, true]);
311 barcodePicker.destroy();
312 barcodePicker = await BarcodePicker.create(document.createElement("div"), {
313 accessCamera: false,
314 enableCameraSwitcher: true,
315 enableTorchToggle: false,
316 enableTapToFocus: true,
317 enablePinchToZoom: false
318 });
319 t.is(setInteractionOptionsSpy.callCount, 4);
320 t.deepEqual(setInteractionOptionsSpy.getCall(3).args, [true, false, true, false]);
321 barcodePicker.destroy();
322});
323
324test.serial(
325 "constructor scanningPaused & isScanningPaused & pauseScanning & resumeScanning (with fake camera)",
326 async t => {
327 await fakeFullCompatibleBrowser();
328 const s: Scanner = new Scanner();
329 let barcodePicker: BarcodePicker = await BarcodePicker.create(document.createElement("div"), {
330 scanner: s
331 });
332 t.false(barcodePicker.isScanningPaused());
333 await barcodePicker.resumeScanning();
334 t.false(barcodePicker.isScanningPaused());
335 (<any>s).engineWorkerOnMessage({
336 data: ["status", "ready"]
337 });
338 barcodePicker.pauseScanning();
339 t.true(barcodePicker.isScanningPaused());
340 await barcodePicker.resumeScanning();
341 t.false(barcodePicker.isScanningPaused());
342 barcodePicker.destroy(false);
343 barcodePicker = await BarcodePicker.create(document.createElement("div"), {
344 scanner: s,
345 scanningPaused: true
346 });
347 t.true(barcodePicker.isScanningPaused());
348 await barcodePicker.resumeScanning();
349 t.false(barcodePicker.isScanningPaused());
350 }
351);
352
353test.serial("accessCamera & getActiveCamera & setActiveCamera (with fake camera)", async t => {
354 await fakeFullCompatibleBrowser();
355 let barcodePicker: BarcodePicker = await BarcodePicker.create(document.createElement("div"), {
356 accessCamera: false
357 });
358 t.is(barcodePicker.getActiveCamera(), undefined);
359 await barcodePicker.accessCamera();
360 t.deepEqual(barcodePicker.getActiveCamera(), fakeCamera1Object);
361 barcodePicker.pauseScanning();
362 t.deepEqual(barcodePicker.getActiveCamera(), fakeCamera1Object);
363 barcodePicker.pauseScanning(true);
364 t.is(barcodePicker.getActiveCamera(), undefined);
365 await barcodePicker.resumeScanning();
366 t.deepEqual(barcodePicker.getActiveCamera(), fakeCamera1Object);
367 await barcodePicker.setActiveCamera(fakeCamera2Object);
368 t.deepEqual(barcodePicker.getActiveCamera(), fakeCamera2Object);
369 await barcodePicker.setActiveCamera();
370 t.deepEqual(barcodePicker.getActiveCamera(), fakeCamera1Object);
371 barcodePicker.destroy();
372
373 barcodePicker = await BarcodePicker.create(document.createElement("div"));
374 t.deepEqual(barcodePicker.getActiveCamera(), fakeCamera1Object);
375 await barcodePicker.accessCamera();
376 t.deepEqual(barcodePicker.getActiveCamera(), fakeCamera1Object);
377
378 barcodePicker = await BarcodePicker.create(document.createElement("div"), {
379 accessCamera: false
380 });
381 await barcodePicker.setActiveCamera(fakeCamera2Object);
382 t.deepEqual(barcodePicker.getActiveCamera(), undefined);
383 await barcodePicker.accessCamera();
384 t.deepEqual(barcodePicker.getActiveCamera(), fakeCamera2Object);
385
386 BrowserHelper.userAgentInfo.setUA(
387 "Mozilla/5.0 (Windows NT 10.0; Win64; x64) " +
388 "AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.92 Safari/537.36"
389 );
390 barcodePicker = await BarcodePicker.create(document.createElement("div"));
391 t.deepEqual(barcodePicker.getActiveCamera(), fakeCamera1Object);
392 await barcodePicker.accessCamera();
393 t.deepEqual(barcodePicker.getActiveCamera(), fakeCamera1Object);
394});
395
396test.serial("applyCameraSettings (with fake camera)", async t => {
397 await fakeFullCompatibleBrowser();
398 const barcodePicker: BarcodePicker = await BarcodePicker.create(document.createElement("div"), {
399 accessCamera: false
400 });
401 const cs: CameraSettings = {
402 resolutionPreference: CameraSettings.ResolutionPreference.FULL_HD
403 };
404 const setSelectedCameraSettingsSpy: sinon.SinonSpy = sinon.spy(
405 (<any>barcodePicker).cameraManager,
406 "setSelectedCameraSettings"
407 );
408 const applyCameraSettingsSpy: sinon.SinonSpy = sinon.spy((<any>barcodePicker).cameraManager, "applyCameraSettings");
409 t.is(setSelectedCameraSettingsSpy.callCount, 0);
410 t.is(applyCameraSettingsSpy.callCount, 0);
411 await barcodePicker.applyCameraSettings(cs);
412 t.is(barcodePicker.getActiveCamera(), undefined);
413 t.is(setSelectedCameraSettingsSpy.callCount, 1);
414 t.is(applyCameraSettingsSpy.callCount, 0);
415 t.deepEqual(setSelectedCameraSettingsSpy.getCall(0).args, [cs]);
416 await barcodePicker.applyCameraSettings();
417 t.is(barcodePicker.getActiveCamera(), undefined);
418 t.is(setSelectedCameraSettingsSpy.callCount, 2);
419 t.deepEqual(setSelectedCameraSettingsSpy.getCall(1).args, [undefined]);
420 await barcodePicker.accessCamera();
421 await barcodePicker.applyCameraSettings(cs);
422 t.is(applyCameraSettingsSpy.callCount, 1);
423 t.deepEqual(applyCameraSettingsSpy.getCall(0).args, [cs]);
424 barcodePicker.destroy();
425});
426
427test.serial("constructor scanSettings & applyScanSettings", async t => {
428 await fakeFullCompatibleBrowser();
429 const s: Scanner = new Scanner();
430 let barcodePicker: BarcodePicker = await BarcodePicker.create(document.createElement("div"), {
431 accessCamera: false,
432 scanner: s
433 });
434 const ss: ScanSettings = new ScanSettings({
435 enabledSymbologies: Barcode.Symbology.QR,
436 codeDuplicateFilter: 10,
437 maxNumberOfCodesPerFrame: 10,
438 searchArea: { x: 0.5, y: 0.5, width: 0.5, height: 0.1 }
439 });
440 const applyScanSettingsSpy: sinon.SinonSpy<[ScanSettings], Scanner> = sinon.spy(s, "applyScanSettings");
441 t.is(applyScanSettingsSpy.callCount, 0);
442 barcodePicker.applyScanSettings(ss);
443 t.is(applyScanSettingsSpy.callCount, 1);
444 t.deepEqual(applyScanSettingsSpy.getCall(0).args, [ss]);
445 barcodePicker.destroy(false);
446 applyScanSettingsSpy.resetHistory();
447 barcodePicker = await BarcodePicker.create(document.createElement("div"), {
448 accessCamera: false,
449 scanner: s,
450 scanSettings: ss
451 });
452 t.deepEqual(applyScanSettingsSpy.getCall(0).args, [ss]);
453 barcodePicker.destroy();
454});
455
456test.serial("isVisible & setVisible", async t => {
457 await fakeFullCompatibleBrowser();
458 let barcodePicker: BarcodePicker = await BarcodePicker.create(document.createElement("div"), {
459 accessCamera: false
460 });
461 t.true(barcodePicker.isVisible());
462 barcodePicker.setVisible(false);
463 t.false(barcodePicker.isVisible());
464 barcodePicker.setVisible(true);
465 t.true(barcodePicker.isVisible());
466 barcodePicker = await BarcodePicker.create(document.createElement("div"), {
467 accessCamera: false,
468 visible: false
469 });
470 t.false(barcodePicker.isVisible());
471 barcodePicker.setVisible(true);
472 t.true(barcodePicker.isVisible());
473 barcodePicker.destroy();
474});
475
476test.serial("isMirrorImageEnabled & setMirrorImageEnabled", async t => {
477 await fakeFullCompatibleBrowser();
478 let barcodePicker: BarcodePicker = await BarcodePicker.create(document.createElement("div"), {
479 accessCamera: false
480 });
481 t.false(barcodePicker.isMirrorImageEnabled());
482 barcodePicker.setMirrorImageEnabled(true);
483 t.false(barcodePicker.isMirrorImageEnabled()); // No camera has been accessed yet
484 await barcodePicker.accessCamera();
485 t.false(barcodePicker.isMirrorImageEnabled());
486 barcodePicker.setMirrorImageEnabled(true);
487 t.true(barcodePicker.isMirrorImageEnabled());
488 await barcodePicker.setActiveCamera(fakeCamera2Object);
489 t.true(barcodePicker.isMirrorImageEnabled()); // Front camera
490 barcodePicker.setMirrorImageEnabled(false);
491 t.false(barcodePicker.isMirrorImageEnabled());
492 await barcodePicker.setActiveCamera();
493 t.true(barcodePicker.isMirrorImageEnabled());
494 await barcodePicker.setActiveCamera(fakeCamera2Object);
495 t.false(barcodePicker.isMirrorImageEnabled());
496 barcodePicker.destroy();
497
498 barcodePicker = await BarcodePicker.create(document.createElement("div"), {
499 camera: fakeCamera2Object
500 });
501 t.true(barcodePicker.isMirrorImageEnabled());
502 barcodePicker.setMirrorImageEnabled(false);
503 t.false(barcodePicker.isMirrorImageEnabled());
504 barcodePicker.destroy();
505
506 barcodePicker = await BarcodePicker.create(document.createElement("div"), {
507 camera: fakeCamera2Object
508 });
509 t.true(barcodePicker.isMirrorImageEnabled());
510 barcodePicker.pauseScanning(true);
511 t.false(barcodePicker.isMirrorImageEnabled());
512 barcodePicker.setMirrorImageEnabled(true);
513 t.false(barcodePicker.isMirrorImageEnabled());
514 await barcodePicker.resumeScanning();
515 t.true(barcodePicker.isMirrorImageEnabled());
516 barcodePicker.pauseScanning(true);
517 await barcodePicker.setActiveCamera(fakeCamera1Object);
518 t.false(barcodePicker.isMirrorImageEnabled());
519 await barcodePicker.resumeScanning();
520 t.false(barcodePicker.isMirrorImageEnabled());
521 barcodePicker.destroy();
522});
523
524test.serial("isPlaySoundOnScanEnabled & setPlaySoundOnScanEnabled", async t => {
525 await fakeFullCompatibleBrowser();
526 let barcodePicker: BarcodePicker = await BarcodePicker.create(document.createElement("div"), {
527 accessCamera: false
528 });
529 t.false(barcodePicker.isPlaySoundOnScanEnabled());
530 barcodePicker.setPlaySoundOnScanEnabled(true);
531 t.true(barcodePicker.isPlaySoundOnScanEnabled());
532 barcodePicker.setPlaySoundOnScanEnabled(false);
533 t.false(barcodePicker.isPlaySoundOnScanEnabled());
534 barcodePicker.destroy();
535 barcodePicker = await BarcodePicker.create(document.createElement("div"), {
536 accessCamera: false,
537 playSoundOnScan: true
538 });
539 t.true(barcodePicker.isPlaySoundOnScanEnabled());
540 barcodePicker.setPlaySoundOnScanEnabled(false);
541 t.false(barcodePicker.isPlaySoundOnScanEnabled());
542 barcodePicker.destroy();
543});
544
545test.serial("isVibrateOnScanEnabled & setVibrateOnScanEnabled", async t => {
546 await fakeFullCompatibleBrowser();
547 let barcodePicker: BarcodePicker = await BarcodePicker.create(document.createElement("div"), {
548 accessCamera: false
549 });
550 t.false(barcodePicker.isVibrateOnScanEnabled());
551 barcodePicker.setVibrateOnScanEnabled(true);
552 t.true(barcodePicker.isVibrateOnScanEnabled());
553 barcodePicker.setVibrateOnScanEnabled(false);
554 t.false(barcodePicker.isVibrateOnScanEnabled());
555 barcodePicker = await BarcodePicker.create(document.createElement("div"), {
556 accessCamera: false,
557 vibrateOnScan: true
558 });
559 t.true(barcodePicker.isVibrateOnScanEnabled());
560 barcodePicker.setVibrateOnScanEnabled(false);
561 t.false(barcodePicker.isVibrateOnScanEnabled());
562 barcodePicker.destroy();
563});
564
565test.serial("isCameraSwitcherEnabled & setCameraSwitcherEnabled", async t => {
566 await fakeFullCompatibleBrowser();
567 const barcodePicker: BarcodePicker = await BarcodePicker.create(document.createElement("div"), {
568 accessCamera: false
569 });
570 t.true(barcodePicker.isCameraSwitcherEnabled());
571 barcodePicker.setCameraSwitcherEnabled(false);
572 t.false(barcodePicker.isCameraSwitcherEnabled());
573 barcodePicker.setCameraSwitcherEnabled(true);
574 t.true(barcodePicker.isCameraSwitcherEnabled());
575 barcodePicker.destroy();
576});
577
578test.serial("isTorchToggleEnabled & setTorchToggleEnabled", async t => {
579 await fakeFullCompatibleBrowser();
580 const barcodePicker: BarcodePicker = await BarcodePicker.create(document.createElement("div"), {
581 accessCamera: false
582 });
583 t.true(barcodePicker.isTorchToggleEnabled());
584 barcodePicker.setTorchToggleEnabled(false);
585 t.false(barcodePicker.isTorchToggleEnabled());
586 barcodePicker.setTorchToggleEnabled(true);
587 t.true(barcodePicker.isTorchToggleEnabled());
588 barcodePicker.destroy();
589});
590
591test.serial("isTapToFocusEnabled & setTapToFocusEnabled", async t => {
592 await fakeFullCompatibleBrowser();
593 const barcodePicker: BarcodePicker = await BarcodePicker.create(document.createElement("div"), {
594 accessCamera: false
595 });
596 t.true(barcodePicker.isTapToFocusEnabled());
597 barcodePicker.setTapToFocusEnabled(false);
598 t.false(barcodePicker.isTapToFocusEnabled());
599 barcodePicker.setTapToFocusEnabled(true);
600 t.true(barcodePicker.isTapToFocusEnabled());
601 barcodePicker.destroy();
602});
603
604test.serial("isPinchToZoomEnabled & setPinchToZoomEnabled", async t => {
605 await fakeFullCompatibleBrowser();
606 const barcodePicker: BarcodePicker = await BarcodePicker.create(document.createElement("div"), {
607 accessCamera: false
608 });
609 t.true(barcodePicker.isPinchToZoomEnabled());
610 barcodePicker.setPinchToZoomEnabled(false);
611 t.false(barcodePicker.isPinchToZoomEnabled());
612 barcodePicker.setPinchToZoomEnabled(true);
613 t.true(barcodePicker.isPinchToZoomEnabled());
614 barcodePicker.destroy();
615});
616
617test.serial("setTorchEnabled", async t => {
618 await fakeFullCompatibleBrowser();
619 const barcodePicker: BarcodePicker = await BarcodePicker.create(document.createElement("div"), {
620 accessCamera: false
621 });
622 barcodePicker.setTorchEnabled(true);
623 barcodePicker.setTorchEnabled(false);
624 barcodePicker.destroy();
625 t.pass();
626});
627
628test.serial("setZoom", async t => {
629 await fakeFullCompatibleBrowser();
630 const barcodePicker: BarcodePicker = await BarcodePicker.create(document.createElement("div"), {
631 accessCamera: false
632 });
633 barcodePicker.setZoom(0.1);
634 barcodePicker.setZoom(1);
635 barcodePicker.destroy();
636 t.pass();
637});
638
639test.serial("constructor guiStyle option & setGuiStyle", async t => {
640 await fakeFullCompatibleBrowser();
641 let barcodePicker: BarcodePicker = await BarcodePicker.create(document.createElement("div"), {
642 accessCamera: false
643 });
644 const setGuiStyleSpy: sinon.SinonSpy = sinon.spy((<any>barcodePicker).barcodePickerGui, "setGuiStyle");
645 t.is((<any>barcodePicker).barcodePickerGui.guiStyle, BarcodePicker.GuiStyle.LASER);
646 barcodePicker.setGuiStyle(BarcodePicker.GuiStyle.NONE);
647 t.is(setGuiStyleSpy.callCount, 1);
648 t.deepEqual(setGuiStyleSpy.getCall(0).args, [BarcodePicker.GuiStyle.NONE]);
649 barcodePicker.setGuiStyle(BarcodePicker.GuiStyle.LASER);
650 t.is(setGuiStyleSpy.callCount, 2);
651 t.deepEqual(setGuiStyleSpy.getCall(1).args, [BarcodePicker.GuiStyle.LASER]);
652 barcodePicker.setGuiStyle(BarcodePicker.GuiStyle.VIEWFINDER);
653 t.is(setGuiStyleSpy.callCount, 3);
654 t.deepEqual(setGuiStyleSpy.getCall(2).args, [BarcodePicker.GuiStyle.VIEWFINDER]);
655 barcodePicker.setGuiStyle(BarcodePicker.GuiStyle.NONE);
656 t.is(setGuiStyleSpy.callCount, 4);
657 t.deepEqual(setGuiStyleSpy.getCall(3).args, [BarcodePicker.GuiStyle.NONE]);
658 barcodePicker.destroy();
659 barcodePicker = await BarcodePicker.create(document.createElement("div"), {
660 accessCamera: false,
661 guiStyle: BarcodePicker.GuiStyle.NONE
662 });
663 t.is((<any>barcodePicker).barcodePickerGui.guiStyle, BarcodePicker.GuiStyle.NONE);
664});
665
666test.serial("constructor videoFit option & setVideoFit", async t => {
667 await fakeFullCompatibleBrowser();
668 let barcodePicker: BarcodePicker = await BarcodePicker.create(document.createElement("div"), {
669 accessCamera: false
670 });
671 const setVideoFitSpy: sinon.SinonSpy = sinon.spy((<any>barcodePicker).barcodePickerGui, "setVideoFit");
672 t.is((<any>barcodePicker).barcodePickerGui.videoFit, BarcodePicker.ObjectFit.CONTAIN);
673 barcodePicker.setVideoFit(BarcodePicker.ObjectFit.COVER);
674 t.is(setVideoFitSpy.callCount, 1);
675 t.deepEqual(setVideoFitSpy.getCall(0).args, [BarcodePicker.ObjectFit.COVER]);
676 barcodePicker.setVideoFit(BarcodePicker.ObjectFit.CONTAIN);
677 t.is(setVideoFitSpy.callCount, 2);
678 t.deepEqual(setVideoFitSpy.getCall(1).args, [BarcodePicker.ObjectFit.CONTAIN]);
679 barcodePicker.destroy();
680 barcodePicker = await BarcodePicker.create(document.createElement("div"), {
681 accessCamera: false,
682 videoFit: BarcodePicker.ObjectFit.COVER
683 });
684 t.is((<any>barcodePicker).barcodePickerGui.videoFit, BarcodePicker.ObjectFit.COVER);
685});
686
687test.serial("constructor laserArea option & setLaserArea", async t => {
688 await fakeFullCompatibleBrowser();
689 let barcodePicker: BarcodePicker = await BarcodePicker.create(document.createElement("div"), {
690 accessCamera: false
691 });
692 const setLaserAreaSpy: sinon.SinonSpy = sinon.spy((<any>barcodePicker).barcodePickerGui, "setLaserArea");
693 t.is((<any>barcodePicker).barcodePickerGui.customLaserArea, undefined);
694 barcodePicker.setLaserArea({
695 x: 0.25,
696 y: 0.25,
697 width: 0.5,
698 height: 0.5
699 });
700 t.is(setLaserAreaSpy.callCount, 1);
701 t.deepEqual(setLaserAreaSpy.getCall(0).args, [
702 {
703 x: 0.25,
704 y: 0.25,
705 width: 0.5,
706 height: 0.5
707 }
708 ]);
709 barcodePicker.setLaserArea();
710 t.is(setLaserAreaSpy.callCount, 2);
711 t.deepEqual(setLaserAreaSpy.getCall(1).args, [undefined]);
712 barcodePicker.destroy();
713 barcodePicker = await BarcodePicker.create(document.createElement("div"), {
714 accessCamera: false,
715 laserArea: {
716 x: 0.25,
717 y: 0.25,
718 width: 0.5,
719 height: 0.5
720 }
721 });
722 t.deepEqual((<any>barcodePicker).barcodePickerGui.customLaserArea, {
723 x: 0.25,
724 y: 0.25,
725 width: 0.5,
726 height: 0.5
727 });
728});
729
730test.serial("constructor viewfinderArea option & setViewfinderArea", async t => {
731 await fakeFullCompatibleBrowser();
732 let barcodePicker: BarcodePicker = await BarcodePicker.create(document.createElement("div"), {
733 accessCamera: false
734 });
735 const setViewfinderAreaSpy: sinon.SinonSpy = sinon.spy((<any>barcodePicker).barcodePickerGui, "setViewfinderArea");
736 t.is((<any>barcodePicker).barcodePickerGui.customViewfinderArea, undefined);
737 barcodePicker.setViewfinderArea({
738 x: 0.25,
739 y: 0.25,
740 width: 0.5,
741 height: 0.5
742 });
743 t.is(setViewfinderAreaSpy.callCount, 1);
744 t.deepEqual(setViewfinderAreaSpy.getCall(0).args, [
745 {
746 x: 0.25,
747 y: 0.25,
748 width: 0.5,
749 height: 0.5
750 }
751 ]);
752 barcodePicker.setViewfinderArea();
753 t.is(setViewfinderAreaSpy.callCount, 2);
754 t.deepEqual(setViewfinderAreaSpy.getCall(1).args, [undefined]);
755 barcodePicker.destroy();
756 barcodePicker = await BarcodePicker.create(document.createElement("div"), {
757 accessCamera: false,
758 viewfinderArea: {
759 x: 0.25,
760 y: 0.25,
761 width: 0.5,
762 height: 0.5
763 }
764 });
765 t.deepEqual((<any>barcodePicker).barcodePickerGui.customViewfinderArea, {
766 x: 0.25,
767 y: 0.25,
768 width: 0.5,
769 height: 0.5
770 });
771});
772
773test.serial("createParserForFormat", async t => {
774 await fakeFullCompatibleBrowser();
775 const barcodePicker: BarcodePicker = await BarcodePicker.create(document.createElement("div"), {
776 accessCamera: false
777 });
778 let parser: Parser = barcodePicker.createParserForFormat(Parser.DataFormat.DLID);
779 t.truthy(parser);
780 parser = barcodePicker.createParserForFormat(Parser.DataFormat.GS1_AI);
781 t.truthy(parser);
782 parser = barcodePicker.createParserForFormat(Parser.DataFormat.HIBC);
783 t.truthy(parser);
784 parser = barcodePicker.createParserForFormat(Parser.DataFormat.MRTD);
785 t.truthy(parser);
786 parser = barcodePicker.createParserForFormat(Parser.DataFormat.SWISSQR);
787 t.truthy(parser);
788 barcodePicker.destroy();
789});
790
791test.serial("reassignOriginElement", async t => {
792 await fakeFullCompatibleBrowser();
793 const element: HTMLDivElement = document.createElement("div");
794 const barcodePicker: BarcodePicker = await BarcodePicker.create(element, {
795 accessCamera: false
796 });
797 t.deepEqual((<any>barcodePicker).barcodePickerGui.originElement, element);
798 t.throws(
799 () => {
800 return barcodePicker.reassignOriginElement(<any>"wrong-argument");
801 },
802 CustomError,
803 "A valid origin HTML element must be given"
804 );
805 t.throws(
806 () => {
807 return barcodePicker.reassignOriginElement(<any>{});
808 },
809 CustomError,
810 "A valid origin HTML element must be given"
811 );
812 const reassignOriginElementSpy: sinon.SinonSpy = sinon.spy(
813 (<any>barcodePicker).barcodePickerGui,
814 "reassignOriginElement"
815 );
816 const element2: HTMLDivElement = document.createElement("div");
817 barcodePicker.reassignOriginElement(element2);
818 t.true(reassignOriginElementSpy.calledOnceWithExactly(element2));
819});
820
821test.serial("setTargetScanningFPS", async t => {
822 await fakeFullCompatibleBrowser();
823 const barcodePicker: BarcodePicker = await BarcodePicker.create(document.createElement("div"), {
824 accessCamera: false
825 });
826 t.is((<any>barcodePicker).targetScanningFPS, 30);
827 t.is((<any>barcodePicker).averageProcessingTime, undefined);
828 barcodePicker.setTargetScanningFPS(60);
829 t.is((<any>barcodePicker).targetScanningFPS, 60);
830 (<any>barcodePicker).scheduleNextVideoProcessing(performance.now());
831 t.is((<any>barcodePicker).averageProcessingTime, undefined);
832 barcodePicker.setTargetScanningFPS(30);
833 t.is((<any>barcodePicker).targetScanningFPS, 30);
834 (<any>barcodePicker).scheduleNextVideoProcessing(performance.now());
835 t.true((<any>barcodePicker).averageProcessingTime < 10);
836 barcodePicker.setTargetScanningFPS(10);
837 t.is((<any>barcodePicker).targetScanningFPS, 10);
838 const scheduleVideoProcessingStub: sinon.SinonStub = sinon.stub(<any>barcodePicker, "scheduleVideoProcessing");
839 (<any>barcodePicker).scheduleNextVideoProcessing(performance.now());
840 t.true((<any>barcodePicker).averageProcessingTime < 10);
841 t.is(scheduleVideoProcessingStub.callCount, 1);
842 t.true(scheduleVideoProcessingStub.lastCall.args[0] > 90);
843 const videoProcessingStub: sinon.SinonStub = sinon.stub(<any>barcodePicker, "videoProcessing");
844 (<any>barcodePicker).scheduleNextVideoProcessing(performance.now() - 10000);
845 t.true((<any>barcodePicker).averageProcessingTime > 100);
846 t.is(scheduleVideoProcessingStub.callCount, 1);
847 t.is(videoProcessingStub.callCount, 1);
848 barcodePicker.setTargetScanningFPS(0);
849 t.is((<any>barcodePicker).targetScanningFPS, 30);
850 barcodePicker.destroy();
851});
852
853test.serial("clearSession", async t => {
854 await fakeFullCompatibleBrowser();
855 const s: Scanner = new Scanner();
856 const barcodePicker: BarcodePicker = await BarcodePicker.create(document.createElement("div"), {
857 accessCamera: false,
858 scanner: s
859 });
860 const clearSessionSpy: sinon.SinonSpy<[], Scanner> = sinon.spy(s, "clearSession");
861 t.is(clearSessionSpy.callCount, 0);
862 barcodePicker.clearSession();
863 t.is(clearSessionSpy.callCount, 1);
864 barcodePicker.destroy();
865});
866
867test.serial("addListener", async t => {
868 await fakeFullCompatibleBrowser();
869 const barcodePicker: BarcodePicker = await BarcodePicker.create(document.createElement("div"), {
870 accessCamera: false
871 });
872 const onSpy: sinon.SinonSpy<any, BarcodePicker> = sinon.spy(barcodePicker, "on");
873 const callbackSpy: sinon.SinonSpy = sinon.spy();
874 barcodePicker.addListener("ready", callbackSpy);
875 t.true(onSpy.calledOnceWithExactly("ready", callbackSpy, undefined));
876});
877
878// Deprecated method
879test.serial("onReady", async t => {
880 await fakeFullCompatibleBrowser();
881 const barcodePicker: BarcodePicker = await BarcodePicker.create(document.createElement("div"), {
882 accessCamera: false
883 });
884 const onSpy: sinon.SinonSpy<any, BarcodePicker> = sinon.spy(barcodePicker, "on");
885 const callbackSpy: sinon.SinonSpy = sinon.spy();
886 barcodePicker.onReady(callbackSpy);
887 t.true(onSpy.calledOnceWithExactly("ready", callbackSpy));
888});
889
890// Deprecated methods
891test.serial("onScan & removeScanListener & removeScanListeners", async t => {
892 await fakeFullCompatibleBrowser();
893 const barcodePicker: BarcodePicker = await BarcodePicker.create(document.createElement("div"), {
894 accessCamera: false
895 });
896 const onSpy: sinon.SinonSpy<any, BarcodePicker> = sinon.spy(barcodePicker, "on");
897 const callbackSpy: sinon.SinonSpy = sinon.spy();
898 barcodePicker.onScan(callbackSpy);
899 t.true(onSpy.calledOnceWithExactly("scan", callbackSpy, false));
900 onSpy.resetHistory();
901 barcodePicker.onScan(callbackSpy, false);
902 t.true(onSpy.calledOnceWithExactly("scan", callbackSpy, false));
903 onSpy.resetHistory();
904 barcodePicker.onScan(callbackSpy, true);
905 t.true(onSpy.calledOnceWithExactly("scan", callbackSpy, true));
906 const removeListenerSpy: sinon.SinonSpy<any, BarcodePicker> = sinon.spy(barcodePicker, "removeListener");
907 barcodePicker.removeScanListener(callbackSpy);
908 t.true(removeListenerSpy.calledOnceWithExactly("scan", callbackSpy));
909 const removeAllListenersSpy: sinon.SinonSpy<any, BarcodePicker> = sinon.spy(barcodePicker, "removeAllListeners");
910 barcodePicker.removeScanListeners();
911 t.true(removeAllListenersSpy.calledOnceWithExactly("scan"));
912});
913
914// Deprecated methods
915test.serial("onSubmitFrame & removeSubmitFrameListener & removeSubmitFrameListeners", async t => {
916 await fakeFullCompatibleBrowser();
917 const barcodePicker: BarcodePicker = await BarcodePicker.create(document.createElement("div"), {
918 accessCamera: false
919 });
920 const onSpy: sinon.SinonSpy<any, BarcodePicker> = sinon.spy(barcodePicker, "on");
921 const callbackSpy: sinon.SinonSpy = sinon.spy();
922 barcodePicker.onSubmitFrame(callbackSpy);
923 t.true(onSpy.calledOnceWithExactly("submitFrame", callbackSpy, false));
924 onSpy.resetHistory();
925 barcodePicker.onSubmitFrame(callbackSpy, false);
926 t.true(onSpy.calledOnceWithExactly("submitFrame", callbackSpy, false));
927 onSpy.resetHistory();
928 barcodePicker.onSubmitFrame(callbackSpy, true);
929 t.true(onSpy.calledOnceWithExactly("submitFrame", callbackSpy, true));
930 const removeListenerSpy: sinon.SinonSpy<any, BarcodePicker> = sinon.spy(barcodePicker, "removeListener");
931 barcodePicker.removeSubmitFrameListener(callbackSpy);
932 t.true(removeListenerSpy.calledOnceWithExactly("submitFrame", callbackSpy));
933 const removeAllListenersSpy: sinon.SinonSpy<any, BarcodePicker> = sinon.spy(barcodePicker, "removeAllListeners");
934 barcodePicker.removeSubmitFrameListeners();
935 t.true(removeAllListenersSpy.calledOnceWithExactly("submitFrame"));
936});
937
938// Deprecated methods
939test.serial("onProcessFrame & removeProcessFrameListener & removeProcessFrameListeners", async t => {
940 await fakeFullCompatibleBrowser();
941 const barcodePicker: BarcodePicker = await BarcodePicker.create(document.createElement("div"), {
942 accessCamera: false
943 });
944 const onSpy: sinon.SinonSpy<any, BarcodePicker> = sinon.spy(barcodePicker, "on");
945 const callbackSpy: sinon.SinonSpy = sinon.spy();
946 barcodePicker.onProcessFrame(callbackSpy);
947 t.true(onSpy.calledOnceWithExactly("processFrame", callbackSpy, false));
948 onSpy.resetHistory();
949 barcodePicker.onProcessFrame(callbackSpy, false);
950 t.true(onSpy.calledOnceWithExactly("processFrame", callbackSpy, false));
951 onSpy.resetHistory();
952 barcodePicker.onProcessFrame(callbackSpy, true);
953 t.true(onSpy.calledOnceWithExactly("processFrame", callbackSpy, true));
954 const removeListenerSpy: sinon.SinonSpy<any, BarcodePicker> = sinon.spy(barcodePicker, "removeListener");
955 barcodePicker.removeProcessFrameListener(callbackSpy);
956 t.true(removeListenerSpy.calledOnceWithExactly("processFrame", callbackSpy));
957 const removeAllListenersSpy: sinon.SinonSpy<any, BarcodePicker> = sinon.spy(barcodePicker, "removeAllListeners");
958 barcodePicker.removeProcessFrameListeners();
959 t.true(removeAllListenersSpy.calledOnceWithExactly("processFrame"));
960});
961
962// Deprecated methods
963test.serial("onScanError & removeScanErrorListener & removeScanErrorListeners", async t => {
964 await fakeFullCompatibleBrowser();
965 const barcodePicker: BarcodePicker = await BarcodePicker.create(document.createElement("div"), {
966 accessCamera: false
967 });
968 const onSpy: sinon.SinonSpy<any, BarcodePicker> = sinon.spy(barcodePicker, "on");
969 const callbackSpy: sinon.SinonSpy = sinon.spy();
970 barcodePicker.onScanError(callbackSpy);
971 t.true(onSpy.calledOnceWithExactly("scanError", callbackSpy, false));
972 onSpy.resetHistory();
973 barcodePicker.onScanError(callbackSpy, false);
974 t.true(onSpy.calledOnceWithExactly("scanError", callbackSpy, false));
975 onSpy.resetHistory();
976 barcodePicker.onScanError(callbackSpy, true);
977 t.true(onSpy.calledOnceWithExactly("scanError", callbackSpy, true));
978 const removeListenerSpy: sinon.SinonSpy<any, BarcodePicker> = sinon.spy(barcodePicker, "removeListener");
979 barcodePicker.removeScanErrorListener(callbackSpy);
980 t.true(removeListenerSpy.calledOnceWithExactly("scanError", callbackSpy));
981 const removeAllListenersSpy: sinon.SinonSpy<any, BarcodePicker> = sinon.spy(barcodePicker, "removeAllListeners");
982 barcodePicker.removeScanErrorListeners();
983 t.true(removeAllListenersSpy.calledOnceWithExactly("scanError"));
984});
985
986test.serial("isReady & ready event", async t => {
987 await fakeFullCompatibleBrowser();
988 const s: Scanner = new Scanner();
989 const barcodePicker: BarcodePicker = await BarcodePicker.create(document.createElement("div"), {
990 accessCamera: false,
991 scanner: s
992 });
993 const onReadyCallbackSpy0: sinon.SinonSpy = sinon.spy();
994 const onReadyCallbackSpy1: sinon.SinonSpy = sinon.spy();
995 const onReadyCallbackSpy2: sinon.SinonSpy = sinon.spy();
996 const onReadyCallbackSpy3: sinon.SinonSpy = sinon.spy();
997 const onReadyCallbackSpy4: sinon.SinonSpy = sinon.spy();
998 const onReadyCallbackSpy5: sinon.SinonSpy = sinon.spy();
999 t.false(s.isReady());
1000 t.false(barcodePicker.isReady());
1001 barcodePicker.on("ready", onReadyCallbackSpy0);
1002 barcodePicker.removeAllListeners("ready");
1003 s.on("ready", onReadyCallbackSpy1);
1004 barcodePicker.on("ready", onReadyCallbackSpy2);
1005 barcodePicker.on("ready", onReadyCallbackSpy3);
1006 barcodePicker.on("ready", onReadyCallbackSpy4);
1007 barcodePicker.removeListener("ready", onReadyCallbackSpy4);
1008 t.false(onReadyCallbackSpy0.called);
1009 t.false(onReadyCallbackSpy1.called);
1010 t.false(onReadyCallbackSpy2.called);
1011 t.false(onReadyCallbackSpy3.called);
1012 t.false(onReadyCallbackSpy4.called);
1013 (<any>s).engineWorkerOnMessage({
1014 data: ["status", "ready"]
1015 });
1016 t.true(s.isReady());
1017 t.true(barcodePicker.isReady());
1018 t.false(onReadyCallbackSpy0.called);
1019 t.true(onReadyCallbackSpy1.called);
1020 t.true(onReadyCallbackSpy2.called);
1021 t.true(onReadyCallbackSpy3.called);
1022 t.false(onReadyCallbackSpy4.called);
1023 t.true(onReadyCallbackSpy3.calledAfter(onReadyCallbackSpy2));
1024 t.true(onReadyCallbackSpy1.calledAfter(onReadyCallbackSpy3));
1025 barcodePicker.on("ready", onReadyCallbackSpy5);
1026 t.true(onReadyCallbackSpy5.called);
1027 barcodePicker.destroy();
1028});
1029
1030test.serial("scan event", async t => {
1031 await fakeFullCompatibleBrowser();
1032 const barcodePicker: BarcodePicker = await prepareBarcodePickerForEvents();
1033 const onScanCallbackSpy1: sinon.SinonSpy = sinon.spy();
1034 const onScanCallbackSpy2: sinon.SinonSpy = sinon.spy();
1035 const onScanCallbackSpy3: sinon.SinonSpy = sinon.spy();
1036 barcodePicker.on("scan", onScanCallbackSpy1);
1037 barcodePicker.on("scan", onScanCallbackSpy2);
1038 barcodePicker.on("scan", onScanCallbackSpy3, true);
1039 t.false(onScanCallbackSpy1.called);
1040 t.false(onScanCallbackSpy2.called);
1041 t.false(onScanCallbackSpy3.called);
1042 await (<any>barcodePicker).processVideoFrame(true);
1043 t.is(onScanCallbackSpy1.callCount, 0);
1044 t.is(onScanCallbackSpy2.callCount, 0);
1045 t.is(onScanCallbackSpy3.callCount, 0);
1046 const scanResult: ScanResult = new ScanResult([sampleBarcode], new Uint8ClampedArray(4), <ImageSettings>(
1047 barcodePicker.getScanner().getImageSettings()
1048 ));
1049 (<any>barcodePicker.getScanner().processImage).restore();
1050 barcodePicker.pauseScanning();
1051 await (<any>barcodePicker).processVideoFrame(true);
1052 t.is(onScanCallbackSpy1.callCount, 0);
1053 t.is(onScanCallbackSpy2.callCount, 0);
1054 t.is(onScanCallbackSpy3.callCount, 0);
1055 await barcodePicker.resumeScanning();
1056 sinon.stub(barcodePicker.getScanner(), "processImage").resolves(scanResult);
1057 await (<any>barcodePicker).processVideoFrame(true);
1058 t.is(onScanCallbackSpy1.callCount, 1);
1059 t.is(onScanCallbackSpy2.callCount, 1);
1060 t.is(onScanCallbackSpy3.callCount, 1);
1061 t.deepEqual(onScanCallbackSpy1.getCall(0).args, [scanResult]);
1062 t.deepEqual(onScanCallbackSpy2.getCall(0).args, [scanResult]);
1063 t.deepEqual(onScanCallbackSpy3.getCall(0).args, [scanResult]);
1064 await (<any>barcodePicker).processVideoFrame(true);
1065 t.is(onScanCallbackSpy1.callCount, 2);
1066 t.is(onScanCallbackSpy2.callCount, 2);
1067 t.is(onScanCallbackSpy3.callCount, 1);
1068 barcodePicker.removeListener("scan", onScanCallbackSpy1);
1069 await (<any>barcodePicker).processVideoFrame(true);
1070 t.is(onScanCallbackSpy1.callCount, 2);
1071 t.is(onScanCallbackSpy2.callCount, 3);
1072 t.is(onScanCallbackSpy3.callCount, 1);
1073 await barcodePicker.resumeScanning();
1074 // Intentionally pause before processing is complete
1075 // tslint:disable-next-line: no-floating-promises
1076 (<any>barcodePicker).processVideoFrame(true);
1077 barcodePicker.pauseScanning();
1078 await wait(200);
1079 t.is(onScanCallbackSpy1.callCount, 2);
1080 t.is(onScanCallbackSpy2.callCount, 3);
1081 t.is(onScanCallbackSpy3.callCount, 1);
1082 await barcodePicker.resumeScanning();
1083 barcodePicker.removeAllListeners("scan");
1084 await (<any>barcodePicker).processVideoFrame(true);
1085 t.is(onScanCallbackSpy1.callCount, 2);
1086 t.is(onScanCallbackSpy2.callCount, 3);
1087 t.is(onScanCallbackSpy3.callCount, 1);
1088 barcodePicker.setPlaySoundOnScanEnabled(false);
1089 barcodePicker.setVibrateOnScanEnabled(false);
1090 await (<any>barcodePicker).processVideoFrame(true);
1091 t.is(onScanCallbackSpy1.callCount, 2);
1092 t.is(onScanCallbackSpy2.callCount, 3);
1093 t.is(onScanCallbackSpy3.callCount, 1);
1094 barcodePicker.destroy();
1095});
1096
1097test.serial("submitFrame event", async t => {
1098 await fakeFullCompatibleBrowser();
1099 const barcodePicker: BarcodePicker = await prepareBarcodePickerForEvents();
1100 const scanResult: ScanResult = new ScanResult([], new Uint8ClampedArray(4), <ImageSettings>(
1101 barcodePicker.getScanner().getImageSettings()
1102 ));
1103 (<any>barcodePicker.getScanner().processImage).restore();
1104 sinon.stub(barcodePicker.getScanner(), "processImage").callsFake(() => {
1105 return Promise.resolve(
1106 new ScanResult([sampleBarcode, { ...sampleBarcode }, { ...sampleBarcode }], new Uint8ClampedArray(4), <
1107 ImageSettings
1108 >barcodePicker.getScanner().getImageSettings())
1109 );
1110 });
1111 const onSubmitFrameCallbackSpy1: sinon.SinonSpy = sinon.spy();
1112 const onSubmitFrameCallbackSpy2: sinon.SinonSpy = sinon.spy();
1113 const onSubmitFrameCallbackSpy3: sinon.SinonSpy = sinon.spy();
1114 barcodePicker.on("submitFrame", onSubmitFrameCallbackSpy1);
1115 barcodePicker.on("submitFrame", onSubmitFrameCallbackSpy2);
1116 barcodePicker.on("submitFrame", onSubmitFrameCallbackSpy3, true);
1117 t.false(onSubmitFrameCallbackSpy1.called);
1118 t.false(onSubmitFrameCallbackSpy2.called);
1119 t.false(onSubmitFrameCallbackSpy3.called);
1120 await (<any>barcodePicker).processVideoFrame(true);
1121 t.is(onSubmitFrameCallbackSpy1.callCount, 1);
1122 t.is(onSubmitFrameCallbackSpy2.callCount, 1);
1123 t.is(onSubmitFrameCallbackSpy3.callCount, 1);
1124 // Result will not contain barcodes yet in the submitFrame event
1125 t.deepEqual(onSubmitFrameCallbackSpy1.getCall(0).args, [scanResult]);
1126 t.deepEqual(onSubmitFrameCallbackSpy2.getCall(0).args, [scanResult]);
1127 t.deepEqual(onSubmitFrameCallbackSpy3.getCall(0).args, [scanResult]);
1128 await (<any>barcodePicker).processVideoFrame(true);
1129 t.is(onSubmitFrameCallbackSpy1.callCount, 2);
1130 t.is(onSubmitFrameCallbackSpy2.callCount, 2);
1131 t.is(onSubmitFrameCallbackSpy3.callCount, 1);
1132 barcodePicker.removeListener("submitFrame", onSubmitFrameCallbackSpy1);
1133 await (<any>barcodePicker).processVideoFrame(true);
1134 t.is(onSubmitFrameCallbackSpy1.callCount, 2);
1135 t.is(onSubmitFrameCallbackSpy2.callCount, 3);
1136 t.is(onSubmitFrameCallbackSpy3.callCount, 1);
1137 barcodePicker.removeAllListeners("submitFrame");
1138 await (<any>barcodePicker).processVideoFrame(true);
1139 t.is(onSubmitFrameCallbackSpy1.callCount, 2);
1140 t.is(onSubmitFrameCallbackSpy2.callCount, 3);
1141 t.is(onSubmitFrameCallbackSpy3.callCount, 1);
1142 barcodePicker.destroy();
1143});
1144
1145test.serial("processFrame event", async t => {
1146 await fakeFullCompatibleBrowser();
1147 const barcodePicker: BarcodePicker = await prepareBarcodePickerForEvents();
1148 const scanResult: ScanResult = new ScanResult([], new Uint8ClampedArray(16), <ImageSettings>(
1149 barcodePicker.getScanner().getImageSettings()
1150 ));
1151 (<any>barcodePicker.getScanner().processImage).restore();
1152 sinon.stub(barcodePicker.getScanner(), "processImage").callsFake(() => {
1153 return new Promise(resolve => {
1154 setTimeout(() => {
1155 resolve(scanResult);
1156 }, 100);
1157 });
1158 });
1159 const onProcessFrameCallbackSpy1: sinon.SinonSpy = sinon.spy();
1160 const onProcessFrameCallbackSpy2: sinon.SinonSpy = sinon.spy();
1161 const onProcessFrameCallbackSpy3: sinon.SinonSpy = sinon.spy();
1162 barcodePicker.on("processFrame", onProcessFrameCallbackSpy1);
1163 barcodePicker.on("processFrame", onProcessFrameCallbackSpy2);
1164 barcodePicker.on("processFrame", onProcessFrameCallbackSpy3, true);
1165 t.false(onProcessFrameCallbackSpy1.called);
1166 t.false(onProcessFrameCallbackSpy2.called);
1167 t.false(onProcessFrameCallbackSpy3.called);
1168 await (<any>barcodePicker).processVideoFrame(true);
1169 t.is(onProcessFrameCallbackSpy1.callCount, 1);
1170 t.is(onProcessFrameCallbackSpy2.callCount, 1);
1171 t.is(onProcessFrameCallbackSpy3.callCount, 1);
1172 t.deepEqual(onProcessFrameCallbackSpy1.getCall(0).args, [scanResult]);
1173 t.deepEqual(onProcessFrameCallbackSpy2.getCall(0).args, [scanResult]);
1174 t.deepEqual(onProcessFrameCallbackSpy3.getCall(0).args, [scanResult]);
1175 await (<any>barcodePicker).processVideoFrame(true);
1176 t.is(onProcessFrameCallbackSpy1.callCount, 2);
1177 t.is(onProcessFrameCallbackSpy2.callCount, 2);
1178 t.is(onProcessFrameCallbackSpy3.callCount, 1);
1179 barcodePicker.removeListener("processFrame", onProcessFrameCallbackSpy1);
1180 await (<any>barcodePicker).processVideoFrame(true);
1181 t.is(onProcessFrameCallbackSpy1.callCount, 2);
1182 t.is(onProcessFrameCallbackSpy2.callCount, 3);
1183 t.is(onProcessFrameCallbackSpy3.callCount, 1);
1184 await barcodePicker.resumeScanning();
1185 // Intentionally pause before processing is complete
1186 // tslint:disable-next-line: no-floating-promises
1187 (<any>barcodePicker).processVideoFrame(true);
1188 barcodePicker.pauseScanning();
1189 await wait(200);
1190 t.is(onProcessFrameCallbackSpy1.callCount, 2);
1191 t.is(onProcessFrameCallbackSpy2.callCount, 3);
1192 t.is(onProcessFrameCallbackSpy3.callCount, 1);
1193 await barcodePicker.resumeScanning();
1194 barcodePicker.removeAllListeners("processFrame");
1195 await (<any>barcodePicker).processVideoFrame(true);
1196 t.is(onProcessFrameCallbackSpy1.callCount, 2);
1197 t.is(onProcessFrameCallbackSpy2.callCount, 3);
1198 t.is(onProcessFrameCallbackSpy3.callCount, 1);
1199 barcodePicker.destroy();
1200});
1201
1202test.serial("scanError event", async t => {
1203 await fakeFullCompatibleBrowser();
1204 const barcodePicker: BarcodePicker = await prepareBarcodePickerForEvents();
1205 const onScanErrorCallbackSpy1: sinon.SinonSpy = sinon.spy();
1206 const onScanErrorCallbackSpy2: sinon.SinonSpy = sinon.spy();
1207 const onScanErrorCallbackSpy3: sinon.SinonSpy = sinon.spy();
1208 barcodePicker.on("scanError", onScanErrorCallbackSpy1);
1209 barcodePicker.on("scanError", onScanErrorCallbackSpy2);
1210 barcodePicker.on("scanError", onScanErrorCallbackSpy3, true);
1211 t.false(onScanErrorCallbackSpy1.called);
1212 t.false(onScanErrorCallbackSpy2.called);
1213 t.false(onScanErrorCallbackSpy3.called);
1214 await (<any>barcodePicker).processVideoFrame(true);
1215 t.is(onScanErrorCallbackSpy1.callCount, 0);
1216 t.is(onScanErrorCallbackSpy2.callCount, 0);
1217 t.is(onScanErrorCallbackSpy3.callCount, 0);
1218 const scanError: Error = new CustomError({
1219 name: "ScanditEngineError",
1220 message: `Test error`
1221 });
1222 (<any>barcodePicker.getScanner().processImage).restore();
1223 sinon.stub(barcodePicker.getScanner(), "processImage").rejects(scanError);
1224 await (<any>barcodePicker).processVideoFrame(true);
1225 t.is(onScanErrorCallbackSpy1.callCount, 1);
1226 t.is(onScanErrorCallbackSpy2.callCount, 1);
1227 t.is(onScanErrorCallbackSpy3.callCount, 1);
1228 t.deepEqual(onScanErrorCallbackSpy1.getCall(0).args, [scanError]);
1229 t.deepEqual(onScanErrorCallbackSpy2.getCall(0).args, [scanError]);
1230 t.deepEqual(onScanErrorCallbackSpy3.getCall(0).args, [scanError]);
1231 await barcodePicker.resumeScanning();
1232 await (<any>barcodePicker).processVideoFrame(true);
1233 t.is(onScanErrorCallbackSpy1.callCount, 2);
1234 t.is(onScanErrorCallbackSpy2.callCount, 2);
1235 t.is(onScanErrorCallbackSpy3.callCount, 1);
1236 barcodePicker.removeListener("scanError", onScanErrorCallbackSpy1);
1237 await barcodePicker.resumeScanning();
1238 await (<any>barcodePicker).processVideoFrame(true);
1239 t.is(onScanErrorCallbackSpy1.callCount, 2);
1240 t.is(onScanErrorCallbackSpy2.callCount, 3);
1241 t.is(onScanErrorCallbackSpy3.callCount, 1);
1242 barcodePicker.removeAllListeners("scanError");
1243 await barcodePicker.resumeScanning();
1244 await (<any>barcodePicker).processVideoFrame(true);
1245 t.is(onScanErrorCallbackSpy1.callCount, 2);
1246 t.is(onScanErrorCallbackSpy2.callCount, 3);
1247 t.is(onScanErrorCallbackSpy3.callCount, 1);
1248 barcodePicker.destroy();
1249});
1250
1251test.serial("ScanResult.rejectCode", async t => {
1252 await fakeFullCompatibleBrowser();
1253 const vibrateSpy: sinon.SinonSpy = sinon.spy();
1254 navigator.vibrate = vibrateSpy;
1255 const barcodePicker: BarcodePicker = await prepareBarcodePickerForEvents();
1256 await (<any>barcodePicker).processVideoFrame(true);
1257 t.is(vibrateSpy.callCount, 0);
1258 (<any>barcodePicker.getScanner().processImage).restore();
1259 sinon.stub(barcodePicker.getScanner(), "processImage").callsFake(() => {
1260 return Promise.resolve(
1261 new ScanResult([sampleBarcode], new Uint8ClampedArray(4), <ImageSettings>(
1262 barcodePicker.getScanner().getImageSettings()
1263 ))
1264 );
1265 });
1266 await (<any>barcodePicker).processVideoFrame(true);
1267 t.is(vibrateSpy.callCount, 1);
1268 await (<any>barcodePicker).processVideoFrame(true);
1269 t.is(vibrateSpy.callCount, 2);
1270 barcodePicker.on("scan", listenerScanResult => {
1271 listenerScanResult.rejectCode(listenerScanResult.barcodes[0]);
1272 });
1273 await (<any>barcodePicker).processVideoFrame(true);
1274 t.is(vibrateSpy.callCount, 2);
1275 barcodePicker.removeAllListeners("scan");
1276 await (<any>barcodePicker).processVideoFrame(true);
1277 t.is(vibrateSpy.callCount, 3);
1278 barcodePicker.on("processFrame", listenerScanResult => {
1279 listenerScanResult.rejectCode(listenerScanResult.barcodes[0]);
1280 });
1281 await (<any>barcodePicker).processVideoFrame(true);
1282 t.is(vibrateSpy.callCount, 3);
1283 barcodePicker.removeAllListeners("processFrame");
1284 await (<any>barcodePicker).processVideoFrame(true);
1285 t.is(vibrateSpy.callCount, 4);
1286 (<any>barcodePicker.getScanner().processImage).restore();
1287 sinon.stub(barcodePicker.getScanner(), "processImage").callsFake(() => {
1288 return Promise.resolve(
1289 new ScanResult([sampleBarcode, { ...sampleBarcode }], new Uint8ClampedArray(4), <ImageSettings>(
1290 barcodePicker.getScanner().getImageSettings()
1291 ))
1292 );
1293 });
1294 await (<any>barcodePicker).processVideoFrame(true);
1295 t.is(vibrateSpy.callCount, 5);
1296 barcodePicker.on("scan", listenerScanResult => {
1297 listenerScanResult.rejectCode(listenerScanResult.barcodes[0]);
1298 });
1299 await (<any>barcodePicker).processVideoFrame(true);
1300 t.is(vibrateSpy.callCount, 6);
1301 barcodePicker.on("scan", listenerScanResult => {
1302 listenerScanResult.rejectCode(listenerScanResult.barcodes[1]);
1303 });
1304 await (<any>barcodePicker).processVideoFrame(true);
1305 t.is(vibrateSpy.callCount, 6);
1306 barcodePicker.removeAllListeners("scan");
1307 await (<any>barcodePicker).processVideoFrame(true);
1308 t.is(vibrateSpy.callCount, 7);
1309 barcodePicker.destroy();
1310});
1311
1312test.serial("triggerFatalError", async t => {
1313 await fakeFullCompatibleBrowser();
1314 const barcodePicker: BarcodePicker = await BarcodePicker.create(document.createElement("div"), {
1315 accessCamera: false
1316 });
1317 t.is((<any>barcodePicker).fatalError, undefined);
1318 const error: Error = new Error("Test error");
1319 (<any>barcodePicker).triggerFatalError(error);
1320 t.deepEqual((<any>barcodePicker).fatalError, error);
1321 barcodePicker.destroy();
1322});