import { describe, expect, it } from 'vitest'; import { AssetAttributesSchema } from '@rareindex/shared'; import { buildCanonicalKey, composeTitle, deterministicIdentifiers } from './canonical-key.ts'; import { fuzzyCandidateScore } from './resolver.ts'; const charizardA = AssetAttributesSchema.parse({ categorySlug: 'pokemon', set: 'Base Set', number: '4/102', name: 'Charizard', variant: '1st Edition Holo', language: 'English', year: 1999, identifiers: { pokemontcg_id: 'base1-4' } }); const charizardB = AssetAttributesSchema.parse({ categorySlug: 'pokemon', setCode: 'base set', number: '#4/102', name: 'Charizard ', variant: '1st edition holo', language: 'english' }); describe('canonical key', () => { it('collides for the same card described differently', () => { expect(buildCanonicalKey(charizardA)).toBe(buildCanonicalKey(charizardB)); expect(buildCanonicalKey(charizardA)).toBe('pokemon|base set|4/102|charizard|1st edition holo|english'); }); it('separates variants and languages', () => { const unlimited = { ...charizardA, variant: 'Unlimited Holo' }; const jp = { ...charizardA, language: 'Japanese' }; expect(buildCanonicalKey(unlimited)).not.toBe(buildCanonicalKey(charizardA)); expect(buildCanonicalKey(jp)).not.toBe(buildCanonicalKey(charizardA)); }); it('uses references for watches and style codes for sneakers', () => { const w = AssetAttributesSchema.parse({ categorySlug: 'rolex', brand: 'Rolex', model: 'Daytona', reference: '116500LN', name: 'Cosmograph Daytona' }); expect(buildCanonicalKey(w)).toBe('rolex|rolex|116500ln|'); const s = AssetAttributesSchema.parse({ categorySlug: 'nike_jordan', brand: 'Jordan', name: 'Air Jordan 1 Retro High OG Chicago', identifiers: { style_code: '555088-101' } }); expect(buildCanonicalKey(s)).toBe('nike_jordan|555088-101'); }); it('composes titles', () => { expect(composeTitle(charizardA)).toBe('Charizard #4/102 · Base Set 1st Edition Holo · (1999)'); expect(deterministicIdentifiers({ pokemontcg_id: 'base1-4', junk: 'x' })).toEqual({ pokemontcg_id: 'base1-4' }); }); it('scores fuzzy candidates', () => { expect(fuzzyCandidateScore({ title: 'Charizard #4/102 · Base Set 1st Edition Holo · (1999)', number: '4/102', year: 1999, setName: 'Base Set' }, charizardA, 0.7)).toBeGreaterThan(0.7); expect(fuzzyCandidateScore({ title: 'Blastoise #2/102 · Base Set', number: '2/102', year: 1999, setName: 'Base Set' }, charizardA, 0.7)).toBe(0); }); });