1740b3867SJames Ide'use strict';
2740b3867SJames Ide
3bd4c8242SŁukasz Kosmatyimport { Asset } from 'expo-asset';
4bd4c8242SŁukasz Kosmatyimport { BarCodeScanner } from 'expo-barcode-scanner';
5740b3867SJames Ideimport React from 'react';
6740b3867SJames Ideimport { Platform } from 'react-native';
7740b3867SJames Ide
8740b3867SJames Ideimport { mountAndWaitFor as originalMountAndWaitFor } from './helpers';
9*8a424bebSJames Ideimport * as TestUtils from '../TestUtils';
10740b3867SJames Ide
11740b3867SJames Ideexport const name = 'BarCodeScanner';
12740b3867SJames Ideconst style = { width: 200, height: 200 };
13740b3867SJames Ide
14740b3867SJames Ideexport async function test(t, { setPortalChild, cleanupPortal }) {
1522d1e005SBartosz Kaszubowski  const shouldSkipTestsRequiringPermissions =
1622d1e005SBartosz Kaszubowski    await TestUtils.shouldSkipTestsRequiringPermissionsAsync();
17740b3867SJames Ide  const describeWithPermissions = shouldSkipTestsRequiringPermissions ? t.xdescribe : t.describe;
18740b3867SJames Ide
19bd4c8242SŁukasz Kosmaty  const testPoint = (value, expected, inaccuracy) => {
20bd4c8242SŁukasz Kosmaty    t.expect(value).toBeGreaterThanOrEqual(expected - inaccuracy);
21bd4c8242SŁukasz Kosmaty    t.expect(value).toBeLessThan(expected + inaccuracy);
22bd4c8242SŁukasz Kosmaty  };
23bd4c8242SŁukasz Kosmaty
24bd4c8242SŁukasz Kosmaty  const testBarCodeBounds = (bounds, expectedBounds, sizeInaccuracy, originInaccuracy) => {
25bd4c8242SŁukasz Kosmaty    t.expect(bounds).toBeDefined();
26bd4c8242SŁukasz Kosmaty    t.expect(typeof bounds.origin).toBe('object');
27bd4c8242SŁukasz Kosmaty    t.expect(typeof bounds.origin.x).toBe('number');
28bd4c8242SŁukasz Kosmaty    t.expect(typeof bounds.origin.y).toBe('number');
29bd4c8242SŁukasz Kosmaty    t.expect(typeof bounds.size).toBe('object');
30bd4c8242SŁukasz Kosmaty    t.expect(typeof bounds.size.width).toBe('number');
31bd4c8242SŁukasz Kosmaty    t.expect(typeof bounds.size.height).toBe('number');
32bd4c8242SŁukasz Kosmaty
33bd4c8242SŁukasz Kosmaty    testPoint(bounds.origin.x, expectedBounds.origin.x, originInaccuracy);
34bd4c8242SŁukasz Kosmaty    testPoint(bounds.origin.y, expectedBounds.origin.y, originInaccuracy);
35bd4c8242SŁukasz Kosmaty
36bd4c8242SŁukasz Kosmaty    testPoint(bounds.size.width, expectedBounds.size.width, sizeInaccuracy);
37bd4c8242SŁukasz Kosmaty    testPoint(bounds.size.height, expectedBounds.size.height, sizeInaccuracy);
38bd4c8242SŁukasz Kosmaty  };
39bd4c8242SŁukasz Kosmaty
40740b3867SJames Ide  describeWithPermissions('BarCodeScanner', () => {
41740b3867SJames Ide    const mountAndWaitFor = (child, propName = 'ref') =>
4222d1e005SBartosz Kaszubowski      new Promise((resolve) => {
43740b3867SJames Ide        const response = originalMountAndWaitFor(child, propName, setPortalChild);
44740b3867SJames Ide        setTimeout(() => resolve(response), 1500);
45740b3867SJames Ide      });
46740b3867SJames Ide
47740b3867SJames Ide    t.beforeAll(async () => {
48740b3867SJames Ide      await TestUtils.acceptPermissionsAndRunCommandAsync(() => {
49aca09ec7SCedric van Putten        return BarCodeScanner.requestPermissionsAsync();
50740b3867SJames Ide      });
51740b3867SJames Ide    });
52740b3867SJames Ide
53740b3867SJames Ide    t.beforeEach(async () => {
54aca09ec7SCedric van Putten      const { status } = await BarCodeScanner.getPermissionsAsync();
55740b3867SJames Ide      t.expect(status).toEqual('granted');
56740b3867SJames Ide    });
57740b3867SJames Ide
58740b3867SJames Ide    t.afterEach(async () => {
59740b3867SJames Ide      await cleanupPortal();
60740b3867SJames Ide    });
61740b3867SJames Ide
62740b3867SJames Ide    t.describe('when created', () => {
63740b3867SJames Ide      t.it('displays the view', async () => {
64740b3867SJames Ide        await mountAndWaitFor(<BarCodeScanner style={style} />);
65740b3867SJames Ide      });
66740b3867SJames Ide    });
67740b3867SJames Ide
68740b3867SJames Ide    t.describe('scanFromURLAsync', () => {
69740b3867SJames Ide      t.it('returns empty result when there is no barcode', async () => {
70740b3867SJames Ide        const asset = await Asset.fromModule(require('../assets/black-128x256.png'));
71740b3867SJames Ide        const result = await BarCodeScanner.scanFromURLAsync(asset.uri);
72740b3867SJames Ide
73740b3867SJames Ide        t.expect(result).toBeDefined();
74740b3867SJames Ide        t.expect(result.length).toEqual(0);
75740b3867SJames Ide      });
76740b3867SJames Ide
77740b3867SJames Ide      t.it('scans a QR code from asset', async () => {
78740b3867SJames Ide        const asset = await Asset.fromModule(require('../assets/qrcode_expo.jpg'));
79740b3867SJames Ide        const result = await BarCodeScanner.scanFromURLAsync(asset.uri);
80740b3867SJames Ide
81740b3867SJames Ide        t.expect(result).toBeDefined();
82740b3867SJames Ide        t.expect(result.length).toEqual(1);
83740b3867SJames Ide        t.expect(result[0]).toBeDefined();
84740b3867SJames Ide        t.expect(result[0].type).toEqual(BarCodeScanner.Constants.BarCodeType.qr);
85740b3867SJames Ide        t.expect(result[0].data).toEqual('https://expo.io/');
86bd4c8242SŁukasz Kosmaty        testBarCodeBounds(
87bd4c8242SŁukasz Kosmaty          result[0].bounds,
88bd4c8242SŁukasz Kosmaty          {
89bd4c8242SŁukasz Kosmaty            origin: {
90bd4c8242SŁukasz Kosmaty              x: 40,
91bd4c8242SŁukasz Kosmaty              y: 40,
92bd4c8242SŁukasz Kosmaty            },
93bd4c8242SŁukasz Kosmaty            size: {
94bd4c8242SŁukasz Kosmaty              width: 210,
95bd4c8242SŁukasz Kosmaty              height: 210,
96bd4c8242SŁukasz Kosmaty            },
97bd4c8242SŁukasz Kosmaty          },
9808df3a02SŁukasz Kosmaty          2,
9908df3a02SŁukasz Kosmaty          2
100bd4c8242SŁukasz Kosmaty        );
101bd4c8242SŁukasz Kosmaty        t.expect(result[0].cornerPoints).toBeDefined();
102bd4c8242SŁukasz Kosmaty        t.expect(result[0].cornerPoints.length).toEqual(4);
103740b3867SJames Ide      });
104740b3867SJames Ide
105740b3867SJames Ide      t.it('scans a QR code from photo asset', async () => {
106740b3867SJames Ide        // Public domain photo from https://commons.wikimedia.org/wiki/File:QR_Code_Damaged.jpg
107740b3867SJames Ide        const asset = await Asset.fromModule(require('../assets/qrcode_photo_wikipedia.jpg'));
108740b3867SJames Ide        const result = await BarCodeScanner.scanFromURLAsync(asset.uri);
109740b3867SJames Ide
110740b3867SJames Ide        t.expect(result).toBeDefined();
111740b3867SJames Ide        t.expect(result.length).toEqual(1);
112740b3867SJames Ide        t.expect(result[0]).toBeDefined();
113740b3867SJames Ide        t.expect(result[0].type).toEqual(BarCodeScanner.Constants.BarCodeType.qr);
114740b3867SJames Ide        t.expect(result[0].data).toEqual('http://en.m.wikipedia.org');
115bd4c8242SŁukasz Kosmaty        testBarCodeBounds(
116bd4c8242SŁukasz Kosmaty          result[0].bounds,
117bd4c8242SŁukasz Kosmaty          {
118bd4c8242SŁukasz Kosmaty            origin: {
119bd4c8242SŁukasz Kosmaty              x: 94,
120bd4c8242SŁukasz Kosmaty              y: 94,
121bd4c8242SŁukasz Kosmaty            },
122bd4c8242SŁukasz Kosmaty            size: {
123bd4c8242SŁukasz Kosmaty              width: 294,
124bd4c8242SŁukasz Kosmaty              height: 296,
125bd4c8242SŁukasz Kosmaty            },
126bd4c8242SŁukasz Kosmaty          },
127bd4c8242SŁukasz Kosmaty          10,
128bd4c8242SŁukasz Kosmaty          10
129bd4c8242SŁukasz Kosmaty        );
130bd4c8242SŁukasz Kosmaty        t.expect(result[0].cornerPoints).toBeDefined();
131bd4c8242SŁukasz Kosmaty        t.expect(result[0].cornerPoints.length).toEqual(4);
132740b3867SJames Ide      });
133740b3867SJames Ide
134740b3867SJames Ide      t.it('scans a QR code from base64 URL', async () => {
135740b3867SJames Ide        const url =
136740b3867SJames Ide          'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyAQMAAAAk8RryAAAABlBMVEX/' +
137740b3867SJames Ide          '//8AAABVwtN+AAAAcElEQVQY04XFMQrAMAgFUCGr4FUCXQO9uuAq/KsEugq2m2bqWx79kQRn1EzGyu' +
138740b3867SJames Ide          '1whx/Pc+gxKSnXku4ZNdFQolq2m3jN9/SrD0Ws9l4Ysx5uj9QftqstqQatmey2ftjW6GPI7PvD2iYE' +
139740b3867SJames Ide          'uJbEmlT/eAEXiXvHFX7hfQAAAABJRU5ErkJggg==';
140740b3867SJames Ide        const result = await BarCodeScanner.scanFromURLAsync(url);
141740b3867SJames Ide
142740b3867SJames Ide        t.expect(result).toBeDefined();
143740b3867SJames Ide        t.expect(result.length).toEqual(1);
144740b3867SJames Ide        t.expect(result[0]).toBeDefined();
145740b3867SJames Ide        t.expect(result[0].type).toEqual(BarCodeScanner.Constants.BarCodeType.qr);
146740b3867SJames Ide        t.expect(result[0].data).toEqual('test');
147740b3867SJames Ide      });
148740b3867SJames Ide
149740b3867SJames Ide      if (Platform.OS === 'android') {
150740b3867SJames Ide        t.it('scans a Data Matrix code from asset', async () => {
151740b3867SJames Ide          const asset = await Asset.fromModule(require('../assets/datamatrix_expo.png'));
152740b3867SJames Ide          const result = await BarCodeScanner.scanFromURLAsync(asset.uri);
153740b3867SJames Ide
154740b3867SJames Ide          t.expect(result).toBeDefined();
155740b3867SJames Ide          t.expect(result.length).toEqual(1);
156740b3867SJames Ide          t.expect(result[0]).toBeDefined();
157740b3867SJames Ide          t.expect(result[0].type).toEqual(BarCodeScanner.Constants.BarCodeType.datamatrix);
158740b3867SJames Ide          t.expect(result[0].data).toEqual('https://expo.io/');
159bd4c8242SŁukasz Kosmaty          testBarCodeBounds(
160bd4c8242SŁukasz Kosmaty            result[0].bounds,
161bd4c8242SŁukasz Kosmaty            {
162bd4c8242SŁukasz Kosmaty              origin: {
163bd4c8242SŁukasz Kosmaty                x: 7,
164bd4c8242SŁukasz Kosmaty                y: 7,
165bd4c8242SŁukasz Kosmaty              },
166bd4c8242SŁukasz Kosmaty              size: {
167bd4c8242SŁukasz Kosmaty                width: 141,
168bd4c8242SŁukasz Kosmaty                height: 141,
169bd4c8242SŁukasz Kosmaty              },
170bd4c8242SŁukasz Kosmaty            },
17108df3a02SŁukasz Kosmaty            2,
17208df3a02SŁukasz Kosmaty            2
173bd4c8242SŁukasz Kosmaty          );
174bd4c8242SŁukasz Kosmaty          t.expect(result[0].cornerPoints).toBeDefined();
175bd4c8242SŁukasz Kosmaty          t.expect(result[0].cornerPoints.length).toEqual(4);
176740b3867SJames Ide        });
177740b3867SJames Ide      }
178740b3867SJames Ide
179740b3867SJames Ide      t.it('respects barCodeTypes parameter', async () => {
180740b3867SJames Ide        const asset = await Asset.fromModule(require('../assets/datamatrix_expo.png'));
181740b3867SJames Ide        const result = await BarCodeScanner.scanFromURLAsync(asset.uri, [
182740b3867SJames Ide          BarCodeScanner.Constants.BarCodeType.qr,
183740b3867SJames Ide        ]);
184740b3867SJames Ide
185740b3867SJames Ide        t.expect(result).toBeDefined();
186740b3867SJames Ide        t.expect(result.length).toEqual(0);
187740b3867SJames Ide      });
188740b3867SJames Ide
189740b3867SJames Ide      t.it('works with multiple codes', async () => {
190740b3867SJames Ide        const asset = await Asset.fromModule(require('../assets/multiple_codes.png'));
191740b3867SJames Ide        const result = await BarCodeScanner.scanFromURLAsync(asset.uri);
192740b3867SJames Ide
193740b3867SJames Ide        t.expect(result).toBeDefined();
194740b3867SJames Ide        t.expect(result.length > 0).toBe(true);
195740b3867SJames Ide      });
196740b3867SJames Ide    });
197740b3867SJames Ide  });
198740b3867SJames Ide}
199