import { describe, it, expect } from 'vitest'; import { parseItemId } from '$lib/scanning/parser'; import { generateItemId, generateSightingId } from '$lib/utils/id'; describe('parseItemId', () => { describe('HTTPS URI format', () => { it('parses a valid HTTPS URI', () => { expect(parseItemId('https://haus.toph.so/abc2345')).toBe('abc2345'); }); it('parses a valid HTTPS URI with different valid ID', () => { expect(parseItemId('https://haus.toph.so/mn3pqr7')).toBe('mn3pqr7'); }); it('returns null for HTTPS URI with invalid characters in ID', () => { expect(parseItemId('https://haus.toph.so/abc1lO0')).toBeNull(); }); it('returns null for HTTPS URI with wrong length ID', () => { expect(parseItemId('https://haus.toph.so/abc23')).toBeNull(); }); it('returns null for wrong domain', () => { expect(parseItemId('https://example.com/abc2345')).toBeNull(); }); }); describe('custom scheme format', () => { it('parses a valid haus:// URI', () => { expect(parseItemId('haus://abc2345')).toBe('abc2345'); }); it('returns null for haus:// URI with invalid characters', () => { expect(parseItemId('haus://abc1lO0')).toBeNull(); }); it('returns null for haus:// URI with wrong length', () => { expect(parseItemId('haus://abc23456789')).toBeNull(); }); }); describe('raw ID format', () => { it('parses a valid raw 7-char ID', () => { expect(parseItemId('abc2345')).toBe('abc2345'); }); it('accepts all valid alphabet characters', () => { // Alphabet: 23456789abcdefghjkmnpqrstuvwxyz expect(parseItemId('2345678')).toBe('2345678'); expect(parseItemId('abcdefg')).toBe('abcdefg'); expect(parseItemId('hjkmnpq')).toBe('hjkmnpq'); expect(parseItemId('rstuvwx')).toBe('rstuvwx'); }); it('rejects excluded characters (0, 1, i, l, o)', () => { expect(parseItemId('abc0def')).toBeNull(); expect(parseItemId('abc1def')).toBeNull(); expect(parseItemId('abcidef')).toBeNull(); expect(parseItemId('abcldef')).toBeNull(); expect(parseItemId('abcodef')).toBeNull(); }); it('rejects uppercase characters', () => { expect(parseItemId('ABCdefg')).toBeNull(); }); }); describe('invalid inputs', () => { it('returns null for empty string', () => { expect(parseItemId('')).toBeNull(); }); it('returns null for wrong length (too short)', () => { expect(parseItemId('abc23')).toBeNull(); }); it('returns null for wrong length (too long)', () => { expect(parseItemId('abc23456')).toBeNull(); }); it('returns null for string with spaces', () => { expect(parseItemId('abc 234')).toBeNull(); }); it('returns null for string with special characters', () => { expect(parseItemId('abc-234')).toBeNull(); }); it('returns null for completely invalid input', () => { expect(parseItemId('not a barcode at all')).toBeNull(); }); }); }); describe('generateItemId', () => { const VALID_CHARS = /^[23456789a-hjkmnp-z]+$/; it('generates a 7-character string', () => { const id = generateItemId(); expect(id).toHaveLength(7); }); it('uses only valid alphabet characters', () => { for (let i = 0; i < 50; i++) { const id = generateItemId(); expect(id).toMatch(VALID_CHARS); } }); it('does not contain ambiguous characters (0, 1, i, l, o)', () => { for (let i = 0; i < 50; i++) { const id = generateItemId(); expect(id).not.toMatch(/[01ilo]/); } }); it('generates unique IDs across multiple calls', () => { const ids = new Set(); for (let i = 0; i < 1000; i++) { ids.add(generateItemId()); } expect(ids.size).toBe(1000); }); }); describe('generateSightingId', () => { it('starts with "s_" prefix', () => { const id = generateSightingId(); expect(id.startsWith('s_')).toBe(true); }); it('has total length of 9 (2 prefix + 7 ID)', () => { const id = generateSightingId(); expect(id).toHaveLength(9); }); it('has a valid item ID after the prefix', () => { const id = generateSightingId(); const suffix = id.slice(2); expect(suffix).toMatch(/^[23456789a-hjkmnp-z]{7}$/); }); it('generates unique IDs across multiple calls', () => { const ids = new Set(); for (let i = 0; i < 100; i++) { ids.add(generateSightingId()); } expect(ids.size).toBe(100); }); });