import { readFileSync } from 'node:fs'; import path from 'node:path'; import { describe, expect, it } from 'vitest'; import meta from './meta.json' with { type: 'json' }; import { localMeta } from '../../api/_lib/local-meta.js'; import { fixtureDir, loadFixture, runFixtureSuite } from '@rareindex/connectors/testing'; import createConnector, { monthFromCode, parseResultsPage, parseSchedule, type PagePayload } from './index.js'; import { sessionEndMonth } from '../../api/_g6-comics-toys-games-lib/comics.js'; const connector = createConnector(localMeta(meta)); describe('comiclink', () => { runFixtureSuite(connector, it, expect); it('discovers past sessions from the schedule page with their closing month (real HTML slice)', () => { const html = readFileSync(path.join(fixtureDir('comiclink'), 'schedule-trimmed.html'), 'utf8'); const sessions = parseSchedule(html); expect(sessions.length).toBeGreaterThan(40); const spring26 = sessions.find((s) => s.code === '2026-Spring-Comics'); expect(spring26).toMatchObject({ label: 'Spring Featured: Comics (5-6/26)', endYear: 2026, endMonth: 6, isArt: false }); expect(sessions.find((s) => s.code === '2026-Spring-ComicArt')?.isArt).toBe(true); expect(sessions.find((s) => s.code === '2023-1-Premium')).toMatchObject({ endYear: 2023, endMonth: 1, isArt: false }); expect(sessions.find((s) => s.code === '2020-12-1-Featured')).toMatchObject({ endYear: 2020, endMonth: 12 }); expect(sessions.find((s) => s.code === '2022-Fall-Comics')).toMatchObject({ endYear: 2022, endMonth: 11 }); // newest first expect((sessions[0]!.endYear ?? 0) * 100 + (sessions[0]!.endMonth ?? 0)).toBeGreaterThanOrEqual((sessions[5]!.endYear ?? 0) * 100 + (sessions[5]!.endMonth ?? 0)); }); it('parses session month codes and labels', () => { expect(monthFromCode('2019-11-ComicAuction', 2019)).toEqual({ year: 2019, month: 11 }); expect(monthFromCode('2023-1-Premium', 2023)).toEqual({ year: 2023, month: 1 }); expect(monthFromCode('2021-Fall-Comics', 2021)).toBeNull(); expect(sessionEndMonth('Fall Featured 11-12/21)', 2021)).toEqual({ year: 2021, month: 12 }); expect(sessionEndMonth('Summer Featured (Aug-Sept)', 2022)).toEqual({ year: 2022, month: 9 }); expect(sessionEndMonth('Jan/Feb 2024 Premium Auction Session: Comic Books', null)).toEqual({ year: 2024, month: 2 }); expect(sessionEndMonth('no month here', null)).toBeNull(); }); it('parses result blocks (title / SOLD in grade / price / item link) from the saved page', () => { const fx = loadFixture('comiclink', 'results-2026-Spring-Comics'); const p = fx.raw.payload as PagePayload; const items = parseResultsPage(p.snapshot!); expect(items.length).toBe(6); expect(items[0]).toMatchObject({ itemId: '1963193', title: 'ACTION COMICS #1', gradeLine: 'CGC 8.5 VF+', price: 601333 }); expect(items[0]!.image).toMatch(/^https:\/\/www\.comiclink\.com\/img\/comics\//); for (const it of items) expect(it.price).toBeGreaterThan(0); }); it('normalises to month-precision auction sales with grader/grade and publisher family', async () => { const out = await connector.normalize(loadFixture('comiclink', 'results-2026-Spring-Comics').raw); expect(out.length).toBe(40); const first = out[0]; if (first?.kind !== 'sale') throw new Error('expected sale'); expect(first.saleDate.toISOString()).toBe('2026-06-01T00:00:00.000Z'); expect(first.attributes).toMatchObject({ categorySlug: 'dc_comics', series: 'Action Comics', number: '1' }); expect(first.grade).toMatchObject({ grader: 'cgc', grade: '8.5' }); expect(first.attributes.metadata.sale_date_precision).toBe('month'); expect(first.buyerPremiumIncluded).toBeNull(); expect(first.auctionHouse).toBe('ComicLink'); expect(first.currency).toBe('USD'); expect(first.sourceUrl).toBe('https://www.comiclink.com/auctions/item.asp?id=1963193'); }); it('skips sessions without a source month instead of inventing a date', async () => { const fx = loadFixture('comiclink', 'results-2026-Spring-Comics'); const p = fx.raw.payload as PagePayload; const out = await connector.normalize({ ...fx.raw, payload: { ...p, session: { ...p.session, endMonth: null, endYear: null } } }); expect(out).toEqual([]); }); });