import { describe, expect, it } from 'vitest';
import type { NormalizedRecord } from '@rareindex/shared';
import { ConnectorMetaSchema } from '@rareindex/connectors';
import { listFixtures, loadFixture, runFixtureSuite } from '@rareindex/connectors/testing';
import metaJson from './meta.json' with { type: 'json' };
import createConnector, { parseLotPageDate, parseMillonIndex, parseMillonSalePage, parsePagerMax } from './index.js';
const meta = ConnectorMetaSchema.parse(metaJson);
const connector = createConnector(meta);
const attrsOf = (r: NormalizedRecord) => {
if (!('attributes' in r)) throw new Error(`record kind ${r.kind} has no attributes`);
return r.attributes;
};
const INDEX = `Horlogerie
Paris
Vente en ligne
lun 06 Juil - lun 07 Sep
OnlineAstérix, planche originale
Estimation | 3 000 € - 5 000 €
Vente BD online #3 du 6 juillet 2026
`; describe('millon', () => { runFixtureSuite(connector, it, expect); it('fixtures: EUR results with unknown premium basis', async () => { let sales = 0; for (const name of listFixtures('millon')) { for (const r of await connector.normalize(loadFixture('millon', name).raw)) { if (!('attributes' in r)) continue; expect(r.attributes.identifiers.millon_lot).toMatch(/^\d+\/\S+$/); expect(r.sourceUrl).toMatch(/^https:\/\/www\.millon\.com\/catalogue\/vente\d+/); if (r.kind === 'sale') { sales++; expect(r.currency).toBe('EUR'); expect(r.buyerPremiumIncluded).toBeNull(); expect(r.auctionHouse).toBe('Millon'); } } } expect(sales).toBeGreaterThan(10); }); it('parses the past-sales index, pager and lot-page date', () => { const sales = parseMillonIndex(INDEX); expect(sales.map((s) => s.id)).toEqual(['3964', '4187']); expect(sales[0]).toMatchObject({ title: 'BD online #3', url: 'https://www.millon.com/catalogue/vente3964-bd-online-3', location: 'Online' }); expect(parsePagerMax(INDEX)).toBe(49); expect(parseLotPageDate(LOT)).toBe('2026-07-06T00:00:00.000Z'); expect(parseLotPageDate('rien
')).toBeNull(); }); it('parses a sale page (French prices, estimates, sold/unsold, 0-based pagination)', async () => { const sale = { id: '3964', title: 'BD online #3', url: 'https://www.millon.com/catalogue/vente3964-bd-online-3', date: '2026-07-06T00:00:00.000Z', location: null, extra: {} }; const p = parseMillonSalePage(SALE, sale, 1)!; expect(p.hasMore).toBe(true); expect(parseMillonSalePage(SALE, sale, 6)!.hasMore).toBe(false); expect(p.lots).toHaveLength(2); expect(p.lots[0]).toMatchObject({ lotNo: '1', title: 'ANONYME (XX)', subtitle: 'Pifou poche n°49, gag de la page 49.', price: 1160, currency: 'EUR', premiumIncluded: null, estimateLow: 30, estimateHigh: 50, sold: true, url: 'https://www.millon.com/catalogue/vente3964-bd-online-3/lot1-anonyme-xx', image: 'https://www.millon.com/sites/millon/files/styles/x/public/auction-items/958005-3964-img1.jpg.webp?itok=a' }); expect(p.lots[1]).toMatchObject({ lotNo: '2', price: null, sold: false, estimateLow: 3000, estimateHigh: 5000 }); expect(p.sale?.title).toBe('BD online #3'); const out = await connector.normalize({ url: sale.url, kind: 'sale', engine: 'api', fetchedAt: new Date(), payload: { kind: 'sale_results', url: sale.url, sale, page: 1, totalLots: null, lots: p.lots } }); expect(out.map((r) => r.kind)).toEqual(['sale', 'auction_lot']); expect(attrsOf(out[0]!).categorySlug).toBe('independent_comics'); expect(connector.salePageUrl(sale, 2)).toBe('https://www.millon.com/catalogue/vente3964-bd-online-3?page=1'); expect(parseMillonSalePage('', sale, 1)).toBeNull(); }); });