300 lines
11 KiB
JavaScript
300 lines
11 KiB
JavaScript
const CodeGenerationService = require('../services/CodeGenerationService');
|
|
|
|
describe('CodeGenerationService', () => {
|
|
let codeGenService;
|
|
|
|
beforeEach(() => {
|
|
codeGenService = new CodeGenerationService();
|
|
});
|
|
|
|
describe('Constructor and Configuration', () => {
|
|
test('should initialize with default options', () => {
|
|
expect(codeGenService.supportedBarcodeFormats).toContain('CODE128');
|
|
expect(codeGenService.supportedBarcodeFormats).toContain('CODE39');
|
|
expect(codeGenService.supportedBarcodeFormats).toContain('EAN13');
|
|
expect(codeGenService.defaultBarcodeOptions.format).toBe('CODE128');
|
|
expect(codeGenService.defaultQROptions.errorCorrectionLevel).toBe('M');
|
|
});
|
|
|
|
test('should return supported formats', () => {
|
|
const formats = codeGenService.getSupportedFormats();
|
|
expect(formats).toEqual(['CODE128', 'CODE39', 'EAN13', 'EAN8', 'UPC']);
|
|
});
|
|
});
|
|
|
|
describe('Barcode Generation', () => {
|
|
test('should generate barcode with default CODE128 format', async () => {
|
|
const result = await codeGenService.generateBarcode('TEST123');
|
|
|
|
expect(result.success).toBe(true);
|
|
expect(result.data).toMatch(/^data:image\/png;base64,/);
|
|
expect(result.format).toBe('CODE128');
|
|
expect(result.productCode).toBe('TEST123');
|
|
expect(result.metadata).toHaveProperty('width');
|
|
expect(result.metadata).toHaveProperty('height');
|
|
expect(result.metadata.format).toBe('PNG');
|
|
});
|
|
|
|
test('should generate barcode with specified format', async () => {
|
|
const result = await codeGenService.generateBarcode('TEST123', 'CODE39');
|
|
|
|
expect(result.success).toBe(true);
|
|
expect(result.format).toBe('CODE39');
|
|
expect(result.productCode).toBe('TEST123');
|
|
});
|
|
|
|
test('should handle invalid product code', async () => {
|
|
const result = await codeGenService.generateBarcode('');
|
|
|
|
expect(result.success).toBe(false);
|
|
expect(result.error).toContain('Product code must be a non-empty string');
|
|
});
|
|
|
|
test('should handle null product code', async () => {
|
|
const result = await codeGenService.generateBarcode(null);
|
|
|
|
expect(result.success).toBe(false);
|
|
expect(result.error).toContain('Product code must be a non-empty string');
|
|
});
|
|
|
|
test('should handle unsupported barcode format', async () => {
|
|
const result = await codeGenService.generateBarcode('TEST123', 'INVALID_FORMAT');
|
|
|
|
expect(result.success).toBe(false);
|
|
expect(result.error).toContain('Unsupported barcode format');
|
|
});
|
|
|
|
test('should validate EAN13 format requirements', async () => {
|
|
const validEAN13 = '123456789012';
|
|
const invalidEAN13 = 'ABC123';
|
|
|
|
const validResult = await codeGenService.generateBarcode(validEAN13, 'EAN13');
|
|
expect(validResult.success).toBe(true);
|
|
|
|
const invalidResult = await codeGenService.generateBarcode(invalidEAN13, 'EAN13');
|
|
expect(invalidResult.success).toBe(false);
|
|
expect(invalidResult.error).toContain('EAN13 format requires 12-13 digits');
|
|
});
|
|
|
|
test('should validate EAN8 format requirements', async () => {
|
|
const validEAN8 = '1234567';
|
|
const invalidEAN8 = 'ABC123';
|
|
|
|
const validResult = await codeGenService.generateBarcode(validEAN8, 'EAN8');
|
|
expect(validResult.success).toBe(true);
|
|
|
|
const invalidResult = await codeGenService.generateBarcode(invalidEAN8, 'EAN8');
|
|
expect(invalidResult.success).toBe(false);
|
|
expect(invalidResult.error).toContain('EAN8 format requires 7-8 digits');
|
|
});
|
|
|
|
test('should validate UPC format requirements', async () => {
|
|
const validUPC = '12345678901';
|
|
const invalidUPC = 'ABC123';
|
|
|
|
const validResult = await codeGenService.generateBarcode(validUPC, 'UPC');
|
|
expect(validResult.success).toBe(true);
|
|
|
|
const invalidResult = await codeGenService.generateBarcode(invalidUPC, 'UPC');
|
|
expect(invalidResult.success).toBe(false);
|
|
expect(invalidResult.error).toContain('UPC format requires 11-12 digits');
|
|
});
|
|
|
|
test('should validate CODE39 format requirements', async () => {
|
|
const validCODE39 = 'TEST-123';
|
|
const invalidCODE39 = 'test@123';
|
|
|
|
const validResult = await codeGenService.generateBarcode(validCODE39, 'CODE39');
|
|
expect(validResult.success).toBe(true);
|
|
|
|
const invalidResult = await codeGenService.generateBarcode(invalidCODE39, 'CODE39');
|
|
expect(invalidResult.success).toBe(false);
|
|
expect(invalidResult.error).toContain('CODE39 format supports only uppercase letters');
|
|
});
|
|
|
|
test('should accept custom barcode options', async () => {
|
|
const customOptions = {
|
|
width: 3,
|
|
height: 150,
|
|
background: '#f0f0f0'
|
|
};
|
|
|
|
const result = await codeGenService.generateBarcode('TEST123', 'CODE128', customOptions);
|
|
expect(result.success).toBe(true);
|
|
});
|
|
});
|
|
|
|
describe('QR Code Generation', () => {
|
|
const sampleProductData = {
|
|
product_code: 'PROD001',
|
|
description: 'Test Product',
|
|
category: 'Electronics',
|
|
unit_of_measure: 'pcs'
|
|
};
|
|
|
|
test('should generate QR code with product data', async () => {
|
|
const result = await codeGenService.generateQRCode(sampleProductData);
|
|
|
|
expect(result.success).toBe(true);
|
|
expect(result.data).toMatch(/^data:image\/png;base64,/);
|
|
expect(result.productCode).toBe('PROD001');
|
|
expect(result.embeddedData).toHaveProperty('code', 'PROD001');
|
|
expect(result.embeddedData).toHaveProperty('desc', 'Test Product');
|
|
expect(result.embeddedData).toHaveProperty('cat', 'Electronics');
|
|
expect(result.embeddedData).toHaveProperty('uom', 'pcs');
|
|
expect(result.embeddedData).toHaveProperty('ts');
|
|
expect(result.metadata.format).toBe('PNG');
|
|
});
|
|
|
|
test('should handle minimal product data', async () => {
|
|
const minimalData = { product_code: 'MIN001' };
|
|
const result = await codeGenService.generateQRCode(minimalData);
|
|
|
|
expect(result.success).toBe(true);
|
|
expect(result.embeddedData.code).toBe('MIN001');
|
|
expect(result.embeddedData.desc).toBe('');
|
|
expect(result.embeddedData.cat).toBe('');
|
|
expect(result.embeddedData.uom).toBe('');
|
|
});
|
|
|
|
test('should handle invalid product data', async () => {
|
|
const result = await codeGenService.generateQRCode(null);
|
|
|
|
expect(result.success).toBe(false);
|
|
expect(result.error).toContain('Product data must be an object');
|
|
});
|
|
|
|
test('should require product_code in data', async () => {
|
|
const invalidData = { description: 'Test without code' };
|
|
const result = await codeGenService.generateQRCode(invalidData);
|
|
|
|
expect(result.success).toBe(false);
|
|
expect(result.error).toContain('Product data must include product_code');
|
|
});
|
|
|
|
test('should accept custom QR options', async () => {
|
|
const customOptions = {
|
|
width: 300,
|
|
errorCorrectionLevel: 'H',
|
|
color: {
|
|
dark: '#FF0000',
|
|
light: '#FFFFFF'
|
|
}
|
|
};
|
|
|
|
const result = await codeGenService.generateQRCode(sampleProductData, customOptions);
|
|
expect(result.success).toBe(true);
|
|
expect(result.metadata.errorCorrectionLevel).toBe('H');
|
|
expect(result.metadata.width).toBe(300);
|
|
});
|
|
});
|
|
|
|
describe('Combined Code Generation', () => {
|
|
const sampleProductData = {
|
|
product_code: 'COMBO001',
|
|
description: 'Combo Test Product',
|
|
category: 'Test',
|
|
unit_of_measure: 'pcs'
|
|
};
|
|
|
|
test('should generate both barcode and QR code', async () => {
|
|
const result = await codeGenService.generateBothCodes(sampleProductData);
|
|
|
|
expect(result.productCode).toBe('COMBO001');
|
|
expect(result.barcode.success).toBe(true);
|
|
expect(result.qrCode.success).toBe(true);
|
|
expect(result.barcode.format).toBe('CODE128');
|
|
expect(result.qrCode.productCode).toBe('COMBO001');
|
|
expect(result.timestamp).toBeDefined();
|
|
});
|
|
|
|
test('should generate both codes with custom options', async () => {
|
|
const options = {
|
|
barcodeFormat: 'CODE39',
|
|
barcode: { width: 3 },
|
|
qr: { width: 250 }
|
|
};
|
|
|
|
const result = await codeGenService.generateBothCodes(sampleProductData, options);
|
|
|
|
expect(result.barcode.format).toBe('CODE39');
|
|
expect(result.qrCode.metadata.width).toBe(250);
|
|
});
|
|
|
|
test('should handle errors in individual code generation', async () => {
|
|
const invalidData = { product_code: 'test@invalid' };
|
|
const options = { barcodeFormat: 'CODE39' };
|
|
|
|
const result = await codeGenService.generateBothCodes(invalidData, options);
|
|
|
|
expect(result.barcode.success).toBe(false);
|
|
expect(result.qrCode.success).toBe(true);
|
|
});
|
|
});
|
|
|
|
describe('QR Code Data Parsing', () => {
|
|
test('should parse valid QR code data', () => {
|
|
const qrData = JSON.stringify({
|
|
code: 'PARSE001',
|
|
desc: 'Parsed Product',
|
|
cat: 'Category',
|
|
uom: 'pcs',
|
|
ts: '2023-01-01T00:00:00.000Z'
|
|
});
|
|
|
|
const result = codeGenService.parseQRCodeData(qrData);
|
|
|
|
expect(result.success).toBe(true);
|
|
expect(result.productCode).toBe('PARSE001');
|
|
expect(result.description).toBe('Parsed Product');
|
|
expect(result.category).toBe('Category');
|
|
expect(result.unitOfMeasure).toBe('pcs');
|
|
expect(result.timestamp).toBe('2023-01-01T00:00:00.000Z');
|
|
});
|
|
|
|
test('should handle invalid QR code data', () => {
|
|
const invalidData = 'invalid json data';
|
|
const result = codeGenService.parseQRCodeData(invalidData);
|
|
|
|
expect(result.success).toBe(false);
|
|
expect(result.error).toBe('Invalid QR code data format');
|
|
expect(result.rawData).toBe(invalidData);
|
|
});
|
|
|
|
test('should handle empty QR code data', () => {
|
|
const result = codeGenService.parseQRCodeData('');
|
|
|
|
expect(result.success).toBe(false);
|
|
expect(result.error).toBe('Invalid QR code data format');
|
|
});
|
|
});
|
|
|
|
describe('Format Validation', () => {
|
|
test('should validate format case insensitivity', async () => {
|
|
const result1 = await codeGenService.generateBarcode('TEST123', 'code128');
|
|
const result2 = await codeGenService.generateBarcode('TEST123', 'CODE128');
|
|
|
|
expect(result1.success).toBe(true);
|
|
expect(result2.success).toBe(true);
|
|
expect(result1.format).toBe('CODE128');
|
|
expect(result2.format).toBe('CODE128');
|
|
});
|
|
|
|
test('should handle edge cases in product codes', async () => {
|
|
const edgeCases = [
|
|
{ code: '1', format: 'CODE128', shouldPass: true },
|
|
{ code: 'A'.repeat(50), format: 'CODE128', shouldPass: true },
|
|
{ code: '123456789012', format: 'EAN13', shouldPass: true },
|
|
{ code: '1234567890123', format: 'EAN13', shouldPass: true }
|
|
];
|
|
|
|
for (const testCase of edgeCases) {
|
|
const result = await codeGenService.generateBarcode(testCase.code, testCase.format);
|
|
if (result.success !== testCase.shouldPass) {
|
|
console.log(`Failed test case: ${testCase.code} (${testCase.format}) - Expected: ${testCase.shouldPass}, Got: ${result.success}, Error: ${result.error}`);
|
|
}
|
|
expect(result.success).toBe(testCase.shouldPass);
|
|
}
|
|
});
|
|
});
|
|
}); |