UNPKG

16.4 kBPlain TextView Raw
1/* tslint:disable:no-implicit-dependencies no-any */
2/**
3 * BarcodePickerGui tests
4 */
5import test from "ava";
6import * as sinon from "sinon";
7import { BarcodePicker, BrowserHelper, ImageSettings, Scanner, ScanSettings } from "..";
8import { BarcodePickerGui } from "./barcodePickerGui";
9
10const defaultBarcodePickerGuiOptions: any = {
11 scanner: sinon.createStubInstance(Scanner, {
12 getScanSettings: new ScanSettings()
13 }),
14 originElement: document.createElement("div"),
15 singleImageMode: false,
16 scanningPaused: false,
17 visible: true,
18 guiStyle: BarcodePicker.GuiStyle.LASER,
19 videoFit: BarcodePicker.ObjectFit.CONTAIN,
20 laserArea: undefined,
21 viewfinderArea: undefined,
22 cameraUploadCallback: () => {
23 return Promise.resolve();
24 },
25 hideLogo: false
26};
27
28function defineConfigurableProperty(object: any, property: string, value: any): void {
29 Object.defineProperty(object, property, {
30 value,
31 configurable: true
32 });
33}
34
35test("constructor & destroy", async t => {
36 let gui: BarcodePickerGui = new BarcodePickerGui({
37 ...defaultBarcodePickerGuiOptions,
38 visible: false
39 });
40 gui.destroy();
41 t.pass();
42
43 BrowserHelper.userAgentInfo.setUA(
44 "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_2) " +
45 "AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.0.2 Safari/605.1.15"
46 );
47 gui = new BarcodePickerGui({
48 ...defaultBarcodePickerGuiOptions,
49 singleImageMode: true,
50 scanningPaused: true,
51 guiStyle: BarcodePicker.GuiStyle.VIEWFINDER,
52 videoFit: BarcodePicker.ObjectFit.COVER,
53 hideLogo: true
54 });
55 gui.destroy();
56
57 t.pass();
58});
59
60test("constructor visible option & isVisible & setVisible", async t => {
61 let gui: BarcodePickerGui = new BarcodePickerGui(defaultBarcodePickerGuiOptions);
62 t.true(gui.isVisible());
63 gui.setVisible(false);
64 t.false(gui.isVisible());
65 gui.setVisible(true);
66 t.true(gui.isVisible());
67
68 gui = new BarcodePickerGui({
69 ...defaultBarcodePickerGuiOptions,
70 visible: false,
71 guiStyle: BarcodePicker.GuiStyle.VIEWFINDER
72 });
73 t.false(gui.isVisible());
74 gui.setVisible(true);
75 t.true(gui.isVisible());
76});
77
78test("constructor guiStyle option & setGuiStyle", async t => {
79 let gui: BarcodePickerGui = new BarcodePickerGui(defaultBarcodePickerGuiOptions);
80 t.is((<any>gui).guiStyle, BarcodePicker.GuiStyle.LASER);
81 t.false((<any>gui).laserContainerElement.classList.contains(BarcodePickerGui.hiddenClassName));
82 t.true((<any>gui).viewfinderElement.classList.contains(BarcodePickerGui.hiddenClassName));
83 gui.setGuiStyle(BarcodePicker.GuiStyle.VIEWFINDER);
84 t.is((<any>gui).guiStyle, BarcodePicker.GuiStyle.VIEWFINDER);
85 t.true((<any>gui).laserContainerElement.classList.contains(BarcodePickerGui.hiddenClassName));
86 t.false((<any>gui).viewfinderElement.classList.contains(BarcodePickerGui.hiddenClassName));
87 gui.setGuiStyle(BarcodePicker.GuiStyle.NONE);
88 t.is((<any>gui).guiStyle, BarcodePicker.GuiStyle.NONE);
89 t.true((<any>gui).laserContainerElement.classList.contains(BarcodePickerGui.hiddenClassName));
90 t.true((<any>gui).viewfinderElement.classList.contains(BarcodePickerGui.hiddenClassName));
91 gui.setGuiStyle(BarcodePicker.GuiStyle.VIEWFINDER);
92 t.is((<any>gui).guiStyle, BarcodePicker.GuiStyle.VIEWFINDER);
93 gui.setGuiStyle(<BarcodePicker.GuiStyle>"invalid");
94 t.is((<any>gui).guiStyle, BarcodePicker.GuiStyle.NONE);
95 t.true((<any>gui).laserContainerElement.classList.contains(BarcodePickerGui.hiddenClassName));
96 t.true((<any>gui).viewfinderElement.classList.contains(BarcodePickerGui.hiddenClassName));
97
98 gui = new BarcodePickerGui({
99 ...defaultBarcodePickerGuiOptions,
100 singleImageMode: true
101 });
102 gui.flashGUI();
103 t.is((<any>gui).guiStyle, BarcodePicker.GuiStyle.NONE);
104 gui.setGuiStyle(BarcodePicker.GuiStyle.LASER);
105 t.is((<any>gui).guiStyle, BarcodePicker.GuiStyle.NONE);
106});
107
108test("reassignOriginElement", async t => {
109 const originElement1: HTMLDivElement = document.createElement("div");
110 const originElement2: HTMLDivElement = document.createElement("div");
111 const gui: BarcodePickerGui = new BarcodePickerGui({
112 ...defaultBarcodePickerGuiOptions,
113 originElement: originElement1
114 });
115 t.deepEqual((<any>gui).originElement, originElement1);
116 gui.reassignOriginElement(originElement2);
117 t.deepEqual((<any>gui).originElement, originElement2);
118 gui.setVisible(false);
119 gui.reassignOriginElement(originElement1);
120 t.deepEqual((<any>gui).originElement, originElement1);
121 t.true(originElement1.classList.contains(BarcodePickerGui.hiddenClassName));
122 t.false(originElement2.classList.contains(BarcodePickerGui.hiddenClassName));
123 gui.reassignOriginElement(originElement2);
124 t.deepEqual((<any>gui).originElement, originElement2);
125 t.false(originElement1.classList.contains(BarcodePickerGui.hiddenClassName));
126 t.true(originElement2.classList.contains(BarcodePickerGui.hiddenClassName));
127});
128
129test("flashGUI", async t => {
130 const gui: BarcodePickerGui = new BarcodePickerGui({
131 ...defaultBarcodePickerGuiOptions,
132 guiStyle: BarcodePicker.GuiStyle.NONE
133 });
134 const flashLaserSpy: sinon.SinonSpy = sinon.spy(<any>gui, "flashLaser");
135 const flashViewfinderSpy: sinon.SinonSpy = sinon.spy(<any>gui, "flashViewfinder");
136 t.is(flashLaserSpy.callCount, 0);
137 t.is(flashViewfinderSpy.callCount, 0);
138 gui.flashGUI();
139 t.is(flashLaserSpy.callCount, 0);
140 t.is(flashViewfinderSpy.callCount, 0);
141 gui.setGuiStyle(BarcodePicker.GuiStyle.LASER);
142 gui.flashGUI();
143 t.is(flashLaserSpy.callCount, 1);
144 t.is(flashViewfinderSpy.callCount, 0);
145 gui.setGuiStyle(BarcodePicker.GuiStyle.VIEWFINDER);
146 gui.flashGUI();
147 t.is(flashLaserSpy.callCount, 1);
148 t.is(flashViewfinderSpy.callCount, 1);
149});
150
151test("setCameraSwitcherVisible", async t => {
152 const gui: BarcodePickerGui = new BarcodePickerGui(defaultBarcodePickerGuiOptions);
153 gui.setCameraSwitcherVisible(false);
154 t.true((<any>gui).cameraSwitcherElement.classList.contains(BarcodePickerGui.hiddenClassName));
155 gui.setCameraSwitcherVisible(true);
156 t.false((<any>gui).cameraSwitcherElement.classList.contains(BarcodePickerGui.hiddenClassName));
157});
158
159test("setTorchTogglerVisible", async t => {
160 const gui: BarcodePickerGui = new BarcodePickerGui(defaultBarcodePickerGuiOptions);
161 gui.setTorchTogglerVisible(false);
162 t.true((<any>gui).torchTogglerElement.classList.contains(BarcodePickerGui.hiddenClassName));
163 gui.setTorchTogglerVisible(true);
164 t.false((<any>gui).torchTogglerElement.classList.contains(BarcodePickerGui.hiddenClassName));
165});
166
167test("resize video", async t => {
168 const scanSettings: ScanSettings = new ScanSettings();
169 const scanner: sinon.SinonStubbedInstance<Scanner> = sinon.createStubInstance(Scanner, {
170 getScanSettings: scanSettings
171 });
172 const originElement: HTMLDivElement = document.createElement("div");
173 const gui: BarcodePickerGui = new BarcodePickerGui({
174 ...defaultBarcodePickerGuiOptions,
175 originElement,
176 scanner: <Scanner>(<unknown>scanner)
177 });
178 // No video dimensions available yet
179 t.is((<any>gui).parentElement.style.maxWidth, "");
180 t.is((<any>gui).parentElement.style.maxHeight, "");
181 defineConfigurableProperty(originElement, "clientWidth", 100);
182 defineConfigurableProperty(originElement, "clientHeight", 100);
183 defineConfigurableProperty(gui.videoElement, "videoWidth", 100);
184 defineConfigurableProperty(gui.videoElement, "videoHeight", 100);
185 gui.setVideoFit(BarcodePicker.ObjectFit.CONTAIN);
186 t.is((<any>gui).parentElement.style.maxWidth, "100px");
187 t.is((<any>gui).parentElement.style.maxHeight, "100px");
188 defineConfigurableProperty(originElement, "clientWidth", 100);
189 defineConfigurableProperty(originElement, "clientHeight", 50);
190 (<any>gui).resize();
191 t.is((<any>gui).parentElement.style.maxWidth, "50px");
192 t.is((<any>gui).parentElement.style.maxHeight, "50px");
193 defineConfigurableProperty(originElement, "clientWidth", 25);
194 defineConfigurableProperty(originElement, "clientHeight", 100);
195 (<any>gui).resize();
196 t.is((<any>gui).parentElement.style.maxWidth, "25px");
197 t.is((<any>gui).parentElement.style.maxHeight, "25px");
198 defineConfigurableProperty(originElement, "clientWidth", 100);
199 defineConfigurableProperty(originElement, "clientHeight", 100);
200 (<any>gui).resize();
201 t.is((<any>gui).parentElement.style.maxWidth, "100px");
202 t.is((<any>gui).parentElement.style.maxHeight, "100px");
203 gui.setVideoFit(BarcodePicker.ObjectFit.COVER);
204 t.deepEqual(scanSettings.getBaseSearchArea(), {
205 x: 0,
206 y: 0,
207 width: 1,
208 height: 1
209 });
210 t.is((<any>gui).parentElement.style.maxWidth, "");
211 t.is((<any>gui).parentElement.style.maxHeight, "");
212 defineConfigurableProperty(gui.videoElement, "videoWidth", 200);
213 defineConfigurableProperty(gui.videoElement, "videoHeight", 100);
214 gui.setVideoFit(BarcodePicker.ObjectFit.CONTAIN);
215 t.is((<any>gui).parentElement.style.maxWidth, "100px");
216 t.is((<any>gui).parentElement.style.maxHeight, "50px");
217 gui.setVideoFit(BarcodePicker.ObjectFit.COVER);
218 t.deepEqual(scanSettings.getBaseSearchArea(), {
219 x: 0.25,
220 y: 0,
221 width: 0.5,
222 height: 1
223 });
224 t.is((<any>gui).parentElement.style.maxWidth, "");
225 t.is((<any>gui).parentElement.style.maxHeight, "");
226 defineConfigurableProperty(gui.videoElement, "videoWidth", 100);
227 defineConfigurableProperty(gui.videoElement, "videoHeight", 200);
228 gui.setVideoFit(BarcodePicker.ObjectFit.CONTAIN);
229 t.is((<any>gui).parentElement.style.maxWidth, "50px");
230 t.is((<any>gui).parentElement.style.maxHeight, "100px");
231 gui.setVideoFit(BarcodePicker.ObjectFit.COVER);
232 t.deepEqual(scanSettings.getBaseSearchArea(), {
233 x: 0,
234 y: 0.25,
235 width: 1,
236 height: 0.5
237 });
238 t.is((<any>gui).parentElement.style.maxWidth, "");
239 t.is((<any>gui).parentElement.style.maxHeight, "");
240});
241
242test("resize singleImage", async t => {
243 const originElement: HTMLDivElement = document.createElement("div");
244 const gui: BarcodePickerGui = new BarcodePickerGui({
245 ...defaultBarcodePickerGuiOptions,
246 originElement,
247 singleImageMode: true
248 });
249 t.is((<any>gui).cameraUploadLabelElement.style.transform, "scale(0)");
250 defineConfigurableProperty(originElement, "clientWidth", 500);
251 defineConfigurableProperty(originElement, "clientHeight", 300);
252 (<any>gui).resize();
253 t.is((<any>gui).cameraUploadLabelElement.style.transform, "scale(1)");
254 defineConfigurableProperty(originElement, "clientWidth", 1000);
255 defineConfigurableProperty(originElement, "clientHeight", 600);
256 (<any>gui).resize();
257 t.is((<any>gui).cameraUploadLabelElement.style.transform, "scale(1)");
258 defineConfigurableProperty(originElement, "clientWidth", 250);
259 (<any>gui).resize();
260 t.is((<any>gui).cameraUploadLabelElement.style.transform, "scale(0.5)");
261 defineConfigurableProperty(originElement, "clientHeight", 30);
262 (<any>gui).resize();
263 t.is((<any>gui).cameraUploadLabelElement.style.transform, "scale(0.1)");
264 defineConfigurableProperty(originElement, "clientWidth", 5);
265 (<any>gui).resize();
266 t.is((<any>gui).cameraUploadLabelElement.style.transform, "scale(0.01)");
267});
268
269// tslint:disable-next-line:max-func-body-length
270test("cameraUploadFile", async t => {
271 function base64StringtoPngFile(base64String: string): File {
272 const byteString: string = atob(base64String);
273 const byteArray: Uint8ClampedArray = new Uint8ClampedArray(byteString.length);
274 for (let i: number = 0; i < byteString.length; i++) {
275 byteArray[i] = byteString.charCodeAt(i);
276 }
277
278 return new File([byteArray], "/test", {
279 type: "image/png"
280 });
281 }
282
283 let imageSettings: ImageSettings | undefined;
284 const scanner: sinon.SinonStubbedInstance<Scanner> = sinon.createStubInstance(Scanner, {
285 getScanSettings: new ScanSettings(),
286 getImageSettings: <sinon.SinonStub<[], ImageSettings | undefined>>(<unknown>sinon.stub().callsFake(():
287 | ImageSettings
288 | undefined => {
289 return imageSettings;
290 })),
291 applyImageSettings: <sinon.SinonStub<[ImageSettings], Scanner>>(<unknown>sinon.stub().callsFake(
292 (newImageSettings: ImageSettings): Scanner => {
293 imageSettings = newImageSettings;
294
295 return <Scanner>(<unknown>scanner);
296 }
297 ))
298 });
299 const gui: BarcodePickerGui = new BarcodePickerGui({
300 ...defaultBarcodePickerGuiOptions,
301 scanner: <Scanner>(<unknown>scanner),
302 singleImageMode: true
303 });
304 Object.defineProperty(Image.prototype, "onprogress", {
305 set: (value: (event: ProgressEvent) => void) => {
306 value(
307 new ProgressEvent("progress", {
308 loaded: 0,
309 total: 100,
310 lengthComputable: true
311 })
312 );
313 }
314 });
315 (<any>gui).cameraUploadFile();
316 let fileList: any = [
317 // 4x4 white image
318 base64StringtoPngFile(
319 "iVBORw0KGgoAAAANSUhEUgAAAAQAAAAECAQAAAAD+Fb1AAAAEElEQVR42mP8/58BDBhxMwCn1gf9tpc9tgAAAABJRU5ErkJggg=="
320 )
321 ];
322 defineConfigurableProperty((<any>gui).cameraUploadInputElement, "files", fileList);
323 (<any>gui).cameraUploadFile();
324 await new Promise(resolve => {
325 setTimeout(resolve, 200);
326 });
327 t.deepEqual(scanner.getImageSettings(), {
328 width: 4,
329 height: 4,
330 format: ImageSettings.Format.RGBA_8U
331 });
332 fileList = [
333 // 1600x100 white image
334 base64StringtoPngFile(
335 // tslint:disable-next-line:max-line-length
336 "iVBORw0KGgoAAAANSUhEUgAABkAAAABkCAQAAAB06DQ2AAABz0lEQVR42u3XQREAAAgDINc/9Czh+YIWpB0AAIAXERAAAEBAAAAAAQEAABAQAABAQAAAAAQEAAAQEAAAQEAAAAAEBAAAEBAAAAABAQAABAQAABAQAAAAAQEAAAQEAABAQAAAAAEBAAAEBAAAQEAAAAABAQAAEBAAAEBAAAAAAQEAABAQAABAQAAAAAQEAAAQEAAAQEAAAAAEBAAAEBAAAAABAQAABAQAAEBAAAAAAQEAAAQEAABAQAAAAAEBAAAQEAAAQEAAAAABAQAAEBAAAEBAAAAABAQAABAQAABAQAAAAAQEAAAQEAAAAAEBAAAEBAAAEBAAAAABAQAABAQAAEBAAAAAAQEAAAQEAABAQAAAAAEBAAAQEAAAQEAAAAAEBAAAEBAAAEBAAAAABAQAABAQAAAAAQEAAAQEAAAQEAAAAAEBAAAEBAAAQEAAAAABAQAABAQAAEBAAAAAAQEAABAQAABAQAAAAAEBAAAQEAAAQEAAAAAEBAAAEBAAAEBAAAAABAQAABAQAAAAAQEAAAQEAAAQEAEBAAAEBAAAEBAAAAABAQAABAQAAEBAAAAAAQEAAAQEAABAQAAAAAEBAAAQEAAAQEAAAAABAQAAuLNeC8edzcWfbQAAAABJRU5ErkJggg=="
337 )
338 ];
339 defineConfigurableProperty((<any>gui).cameraUploadInputElement, "files", fileList);
340 (<any>gui).cameraUploadFile();
341 await new Promise(resolve => {
342 setTimeout(resolve, 200);
343 });
344 t.deepEqual(scanner.getImageSettings(), {
345 width: 1440,
346 height: 90,
347 format: ImageSettings.Format.RGBA_8U
348 });
349 fileList = [
350 // 100x1600 white image
351 base64StringtoPngFile(
352 // tslint:disable-next-line:max-line-length
353 "iVBORw0KGgoAAAANSUhEUgAAAGQAAAZACAQAAAAlBi/FAAAE+UlEQVR42u3PAQ0AAAgDIN8/9M2hgwaknRciIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiJy2QLJ03p1wqRRzwAAAABJRU5ErkJggg=="
354 )
355 ];
356 defineConfigurableProperty((<any>gui).cameraUploadInputElement, "files", fileList);
357 (<any>gui).cameraUploadFile();
358 await new Promise(resolve => {
359 setTimeout(resolve, 200);
360 });
361 t.deepEqual(scanner.getImageSettings(), {
362 width: 90,
363 height: 1440,
364 format: ImageSettings.Format.RGBA_8U
365 });
366});