import { describe, expect, it } from 'vitest'; import meta from './meta.json' with { type: 'json' }; import { localMeta } from '../_lib/local-meta.js'; import { listFixtures, loadFixture, runFixtureSuite } from '@rareindex/connectors/testing'; import createConnector, { barcodeIds, idFromApiUrl, parseCoverPrice, parseKeyDate, trimIssue, trimSeries } from './index.js'; import { publisherCategory } from '../_g6-comics-toys-games-lib/comics.js'; const connector = createConnector(localMeta(meta)); describe('gcd', () => { runFixtureSuite(connector, it, expect); it('parses GCD key dates without inventing missing day/month', () => { expect(parseKeyDate('1988-05-00')).toEqual({ year: 1988, date: null }); expect(parseKeyDate('1988-02-23')).toEqual({ year: 1988, date: new Date(Date.UTC(1988, 1, 23)) }); expect(parseKeyDate('1867-00-00')).toEqual({ year: 1867, date: null }); expect(parseKeyDate('')).toEqual({ year: null, date: null }); expect(parseKeyDate(null)).toEqual({ year: null, date: null }); }); it('parses cover prices only when an ISO currency is printed', () => { expect(parseCoverPrice('0.12 USD')).toEqual({ amount: 0.12, currency: 'USD' }); expect(parseCoverPrice('1.95 USD; 2.60 CAD; 0.50 GBP')).toEqual({ amount: 1.95, currency: 'USD' }); expect(parseCoverPrice('0.00 FREE')).toBeNull(); expect(parseCoverPrice('[none]')).toBeNull(); expect(parseCoverPrice('')).toBeNull(); }); it('derives deterministic identifiers from api urls and barcodes', () => { expect(idFromApiUrl('https://www.comics.org/api/issue/127538/?format=json')).toBe('127538'); expect(idFromApiUrl('https://www.comics.org/api/publisher/78/?format=json')).toBe('78'); expect(idFromApiUrl(null)).toBeNull(); expect(barcodeIds('759606024605')).toEqual({ upc: '759606024605' }); expect(barcodeIds('75960602460500111')).toEqual({ upc: '759606024605', upc_supplement: '00111' }); expect(barcodeIds('9781302900000')).toEqual({ isbn: '9781302900000', ean: '9781302900000' }); expect(barcodeIds('')).toEqual({}); }); it('maps publishers to taxonomy families', () => { expect(publisherCategory('Marvel')).toBe('marvel_comics'); expect(publisherCategory('DC')).toBe('dc_comics'); expect(publisherCategory('Harrier')).toBe('independent_comics'); expect(publisherCategory('Shueisha', 'ja')).toBe('manga'); expect(publisherCategory(null)).toBe('comics'); }); it('trims live API shapes and normalises fixtures into catalog items with comics_org_id', async () => { const issue = trimIssue({ api_url: 'https://www.comics.org/api/issue/1/?format=json', number: '[nn]', key_date: '1867-00-00', price: '[none]', story_set: [{ type: 'cover', pencils: 'Gustave Doré' }] }); expect(issue.id).toBe('1'); expect(issue.cover_pencils).toBe('Gustave Doré'); expect(issue.story_count).toBe(1); const series = trimSeries({ api_url: 'https://www.comics.org/api/series/10814/?format=json', name: '!Gag!', country: 'gb', language: 'en', year_began: 1987, year_ended: 1989, active_issues: ['a', 'b'] }); expect(series).toMatchObject({ id: '10814', country: 'gb', issue_count: 2 }); for (const name of listFixtures('gcd')) { const fx = loadFixture('gcd', name); const out = await connector.normalize(fx.raw); expect(out.length).toBeGreaterThan(0); for (const r of out) { expect(r.kind).toBe('catalog_item'); if (r.kind !== 'catalog_item') continue; expect(r.attributes.identifiers.comics_org_id).toMatch(/^\d+$/); expect(r.sourceUrl).toBe(`https://www.comics.org/issue/${r.attributes.identifiers.comics_org_id}/`); expect(r.attributes.metadata.license).toContain('CC-BY-SA'); expect(r.confidence).toBeLessThan(1); } } const gag = await connector.normalize(loadFixture('gcd', 'series-page1-0-10814').raw); const first = gag[0]; if (first?.kind !== 'catalog_item') throw new Error('expected catalog item'); expect(first.attributes).toMatchObject({ categorySlug: 'independent_comics', brand: 'Harrier', set: '!Gag!', number: '1', year: 1987, country: 'GB', originalMsrp: 1.95, originalMsrpCurrency: 'USD' }); expect(first.releaseDate).toBeNull(); }); });