Files
tfm_ainventory/frontend/tests/lib/labels.test.ts

247 lines
8.2 KiB
TypeScript

import { describe, it, expect, vi } from 'vitest'
import { generateBarcode128, getQRCodeURL } from '@/lib/labels'
describe('Labels Library', () => {
// ============================================================================
// UNIT TESTS: Barcode Generation
// ============================================================================
describe('generateBarcode128', () => {
it('should generate SVG barcode for simple text', () => {
const barcode = generateBarcode128('12345')
expect(barcode).toContain('<svg')
expect(barcode).toContain('</svg>')
expect(barcode).toContain('viewBox')
})
it('should generate valid SVG with rect elements', () => {
const barcode = generateBarcode128('ABC')
expect(barcode).toContain('<rect')
expect(barcode).toContain('/>')
})
it('should include start and stop patterns', () => {
const barcode = generateBarcode128('TEST')
expect(barcode.length).toBeGreaterThan(100)
expect(barcode).toContain('<svg')
})
it('should handle numeric barcodes', () => {
const barcode = generateBarcode128('9876543210')
expect(barcode).toContain('<svg')
expect(barcode).toContain('viewBox')
})
it('should handle alphanumeric barcodes', () => {
const barcode = generateBarcode128('PART-001')
expect(barcode).toContain('<svg')
expect(barcode).toContain('<rect')
})
it('should handle special characters', () => {
const barcode = generateBarcode128('ITEM#123')
expect(barcode).toContain('<svg')
expect(barcode).toContain('viewBox')
})
it('should generate consistent output for same input', () => {
const barcode1 = generateBarcode128('CONSISTENT')
const barcode2 = generateBarcode128('CONSISTENT')
expect(barcode1).toBe(barcode2)
})
it('should generate different output for different inputs', () => {
const barcode1 = generateBarcode128('INPUT1')
const barcode2 = generateBarcode128('INPUT2')
expect(barcode1).not.toBe(barcode2)
})
it('should set proper SVG dimensions in viewBox', () => {
const barcode = generateBarcode128('LENGTH')
const viewBoxMatch = barcode.match(/viewBox="([^"]+)"/)
expect(viewBoxMatch).toBeTruthy()
})
it('should use black fill color for bars', () => {
const barcode = generateBarcode128('COLOR')
expect(barcode).toContain('fill="black"')
})
it('should set rect height to 50 units', () => {
const barcode = generateBarcode128('HEIGHT')
expect(barcode).toContain('height="50"')
})
it('should handle empty string gracefully', () => {
const barcode = generateBarcode128('')
expect(barcode).toContain('<svg')
})
it('should handle long text input', () => {
const longText = 'VERYLONGITEMPARTNUMBER12345'
const barcode = generateBarcode128(longText)
expect(barcode).toContain('<svg')
})
it('should generate SVG with xmlns namespace', () => {
const barcode = generateBarcode128('NS')
expect(barcode).toContain('xmlns')
})
it('should have rectangles positioned sequentially', () => {
const barcode = generateBarcode128('SEQ')
const rects = barcode.match(/<rect/g)
expect(rects && rects.length > 0).toBe(true)
})
})
// ============================================================================
// UNIT TESTS: QR Code URL Generation
// ============================================================================
describe('getQRCodeURL', () => {
it('should generate QR code URL for simple text', () => {
const url = getQRCodeURL('12345')
expect(url).toContain('qrserver.com')
expect(url).toContain('api.qrserver.com/v1/create-qr-code')
})
it('should include data parameter with input text', () => {
const url = getQRCodeURL('TESTDATA')
expect(url).toContain('data=')
expect(url).toContain('TESTDATA')
})
it('should URL encode special characters', () => {
const url = getQRCodeURL('PART#123')
expect(url).toContain('%23') // # encoded
})
it('should include size parameter', () => {
const url = getQRCodeURL('SIZE')
expect(url).toContain('size=300x300')
})
it('should generate consistent URLs for same input', () => {
const url1 = getQRCodeURL('CONSISTENT')
const url2 = getQRCodeURL('CONSISTENT')
expect(url1).toBe(url2)
})
it('should handle spaces in input', () => {
const url = getQRCodeURL('ITEM NAME')
expect(url).toContain('%20') // space encoded
})
it('should handle numeric QR data', () => {
const url = getQRCodeURL('9876543210')
expect(url).toContain('data=9876543210')
})
it('should generate HTTPS URL', () => {
const url = getQRCodeURL('TEST')
expect(url).toContain('https://')
})
it('should handle empty string input', () => {
const url = getQRCodeURL('')
expect(url).toContain('qrserver.com')
})
it('should handle long input text', () => {
const longText = 'VERY_LONG_QR_CODE_DATA_WITH_MANY_CHARACTERS_AND_SPECIAL_MARKS'
const url = getQRCodeURL(longText)
expect(url).toContain('qrserver.com')
expect(url.length).toBeGreaterThan(50)
})
})
// ============================================================================
// INTEGRATION TESTS: Label Dimension Validation
// ============================================================================
describe('Label Dimensions', () => {
it('barcode SVG should be suitable for 62mm x 29mm printing', () => {
const barcode = generateBarcode128('PRINT62X29')
expect(barcode).toContain('viewBox')
})
it('barcode should generate with consistent aspect ratio', () => {
const barcode = generateBarcode128('ASPECT')
expect(barcode).toContain('xmlns')
})
it('QR code URL should return 300x300 image', () => {
const url = getQRCodeURL('300x300')
expect(url).toContain('size=300x300')
})
it('barcode SVG should be scalable', () => {
const barcode = generateBarcode128('SCALE')
expect(barcode).toContain('viewBox')
})
})
// ============================================================================
// INTEGRATION TESTS: Error Handling
// ============================================================================
describe('Error Handling', () => {
it('should not throw on unsupported characters', () => {
expect(() => generateBarcode128('TEST🔒')).not.toThrow()
})
it('should not throw on mixed input', () => {
expect(() => generateBarcode128('Mix123!@#')).not.toThrow()
})
it('should handle QR generation with special chars', () => {
expect(() => getQRCodeURL('SPECIAL&CHARS')).not.toThrow()
})
it('should handle very long barcode input', () => {
const longInput = 'A'.repeat(100)
expect(() => generateBarcode128(longInput)).not.toThrow()
})
it('should generate output for edge case inputs', () => {
const barcode = generateBarcode128(' ')
expect(barcode).toContain('<svg')
})
})
// ============================================================================
// INTEGRATION TESTS: Canvas Export (Validation)
// ============================================================================
describe('Export Validation', () => {
it('barcode SVG should be valid for canvas conversion', () => {
const barcode = generateBarcode128('CANVAS')
expect(barcode).toContain('<svg')
expect(barcode).toContain('xmlns')
})
it('QR URL should be valid for img src attribute', () => {
const url = getQRCodeURL('IMG')
expect(url).toMatch(/^https:\/\//)
})
it('barcode should contain no invalid XML', () => {
const barcode = generateBarcode128('VALID')
expect(barcode).not.toContain('<<')
expect(barcode).not.toContain('>>')
})
it('should generate SVG with proper closure', () => {
const barcode = generateBarcode128('CLOSURE')
const svgOpenCount = (barcode.match(/<svg/g) || []).length
const svgCloseCount = (barcode.match(/<\/svg>/g) || []).length
expect(svgOpenCount).toBe(svgCloseCount)
})
})
afterEach(() => {
vi.clearAllMocks()
})
})