247 lines
8.2 KiB
TypeScript
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()
|
|
})
|
|
})
|