diff --git a/src/__tests__/barcode-type-detector.test.ts b/src/__tests__/barcode-type-detector.test.ts index ac132b3..b3b1fca 100644 --- a/src/__tests__/barcode-type-detector.test.ts +++ b/src/__tests__/barcode-type-detector.test.ts @@ -1,18 +1,14 @@ -import { BarcodeTypeDetector } from '../barcode-type-detector'; +import {BarcodeTypeDetector} from '../barcode-type-detector'; import { BarcodeType } from '../enums'; -test('EAN_13', () => { +test('EAN_13 Validation', () => { expect(BarcodeTypeDetector.detect('3614950268099')).toBe(BarcodeType.EAN_13); }); -test('EAN_8', () => { +test('EAN_8 Validation', () => { expect(BarcodeTypeDetector.detect('78635708')).toBe(BarcodeType.EAN_8); }); -test('UPC_A', () => { - expect(BarcodeTypeDetector.detect('012345678905')).toBe(BarcodeType.UPC_A); -}); - -test('UPC_E', () => { - expect(BarcodeTypeDetector.detect('8635709')).toBe(BarcodeType.UPC_E); +test('UPC_A Validation', () => { + expect(BarcodeTypeDetector.detect('123456789104')).toBe(BarcodeType.UPC_A); }); diff --git a/src/barcode-type-detector.ts b/src/barcode-type-detector.ts index 915b8da..a1faaa3 100644 --- a/src/barcode-type-detector.ts +++ b/src/barcode-type-detector.ts @@ -18,27 +18,28 @@ const onlyDigitsRegexp = (length: number): RegExp => new RegExp(`^\\d{${length}} */ const isOnlyDigits = (value: string, length: number): boolean => onlyDigitsRegexp(length).test(value); /** - * EAN control key system based on the Luhn formula + * Control key calculation * @param value */ -const eanKeyController = (value: string): boolean => { - const lastIndex = value.length - 1; +const getEanControlKey = (value: string): number => { const sumCtrl = value - .slice(0, lastIndex) - .split('') - // Chars are only digits - .map(digit => parseInt(digit, 10)) - // Each even char column index is multiply by 3 - // And we make the sum - .reduce((acc, digit, index) => acc + (index % 2 ? digit : digit * 3), 0); - // The calculated control key has to be the same as the last char in value - return parseInt(value.slice(lastIndex), 10) === 10 - (sumCtrl % 10); + .slice(0, value.length - 1) + .split('') + // Chars are only digits + .map(digit => parseInt(digit, 10)) + // Each even char column index is multiply by 3 + // And we make the sum + .reduce((acc, digit, index) => acc + ((index % 2) ? digit : (digit * 3)), 0); + return 10 - (sumCtrl % 10); }; /** - * UPC uses the same control key system as EAN but we have to add a 0 at the beginning of value + * EAN and UPC control key system based on the Luhn formula * @param value */ -const upcKeyController = (value: string): boolean => eanKeyController(`0${value}`); +const eanKeyController = (value: string): boolean => { + // The calculated control key has to be the same as the last char in value + return parseInt(value.slice(value.length - 1), 10) === getEanControlKey(value); +}; /** * Is the value an EAN with specified length ? * @param value @@ -50,7 +51,7 @@ const isEan = (value: string, length: 8 | 13): boolean => isOnlyDigits(value, le * @param value * @param length */ -const isUpc = (value: string, length: 7 | 12): boolean => isOnlyDigits(value, length) && upcKeyController(value); +const isUpc = (value: string): boolean => isOnlyDigits(value, 12) && eanKeyController(value); /** * EAN_13 = ONLY 13 digits + control key checking */ @@ -58,15 +59,11 @@ const ean13Definer: IBarcodeTypeDefiner = { method: value => isEan(value, 13), t /** * UPC_A = ONLY 12 digits + control key checking */ -const upcADefiner: IBarcodeTypeDefiner = { method: value => isUpc(value, 12), type: BarcodeType.UPC_A }; +const upcADefiner: IBarcodeTypeDefiner = { method: value => isUpc(value), type: BarcodeType.UPC_A }; /** * EAN_8 = ONLY 8 digits + control key checking */ const ean8Definer: IBarcodeTypeDefiner = { method: value => isEan(value, 8), type: BarcodeType.EAN_8 }; -/** - * UPC_E = ONLY 7 digits + control key checking - */ -const upcEDefiner: IBarcodeTypeDefiner = { method: value => isUpc(value, 7), type: BarcodeType.UPC_E }; /** * Detector of barcode type */ @@ -87,5 +84,5 @@ export class BarcodeTypeDetector { /** * List of definers */ - private static readonly definers: IBarcodeTypeDefiner[] = [ean13Definer, upcADefiner, ean8Definer, upcEDefiner]; + private static readonly definers: IBarcodeTypeDefiner[] = [ean13Definer, upcADefiner, ean8Definer]; }