import { describe, expect, it } from 'vitest'; import { readFileSync } from 'node:fs'; import path from 'node:path'; import { fileURLToPath } from 'node:url'; import { loadFixture, runFixtureSuite } from '@rareindex/connectors/testing'; import { localMeta } from '../../api/_lib/local-meta.js'; import createConnector, { noonansDefaultSlug, parseCataloguePage, parsePastCatalogues } from './index.js'; import { parseAuctionDate } from '../_g5-numismatics-lib/index.js'; const dir = path.dirname(fileURLToPath(import.meta.url)); const connector = createConnector(localMeta(JSON.parse(readFileSync(path.join(dir, 'meta.json'), 'utf8')))); const INDEX = `
Coins and Historical Medals

30 June 2026

.

Coins and Historical Medals

23 & 24 June 2026

Jewellery, Objects of Vertu, Silver and Watches

8 July 2026

British and Irish Banknotes

`; const LIST = `

680 lots found

x

Lot

№ 1

.

British Iron Age, CANTII, cast Potin Units (6), Nipples type, crude outline head right (ABC 174; S 64) [6]. Fine or better £90-£120

Hammer Price: £280

№ 76

Kings of Mercia, Coenwulf (796-821), Penny, East Anglia, Herbert, 1.36g/11h (N 364; S 920). A full round coin with a superb portrait, good very fine £2,000-£3,000

Hammer Price: £3,800

№ 55

George III, Sovereign, 1817, NGC MS 62 (S 3785) £1,500-£2,000

Hammer Price: Unsold

`; describe('noonans', () => { runFixtureSuite(connector, it, expect); it('parses the past-catalogues index and classifies sales by title', () => { const a = parsePastCatalogues(INDEX); expect(a).toEqual([ { id: '935', title: 'Coins and Historical Medals', dateText: '30 June 2026' }, { id: '882', title: 'Jewellery, Objects of Vertu, Silver and Watches', dateText: '23 & 24 June 2026' }, { id: '870', title: 'British and Irish Banknotes', dateText: '8 July 2026' }, ]); expect(noonansDefaultSlug('Coins and Historical Medals')).toBe('coins'); expect(noonansDefaultSlug('British and Irish Banknotes')).toBe('banknotes'); expect(noonansDefaultSlug('Orders, Decorations, Medals and Militaria')).toBe('medals'); expect(noonansDefaultSlug('British Trade Tokens, Tickets and Passes')).toBe('medals'); expect(noonansDefaultSlug('Jewellery, Objects of Vertu, Silver and Watches')).toBeNull(); expect(parseAuctionDate('23 & 24 June 2026')?.toISOString()).toBe('2026-06-23T00:00:00.000Z'); }); it('parses list-layout lots: description, estimate tail, hammer, lot id, pagination total', () => { const p = parseCataloguePage(LIST, { id: '935', title: 'Coins and Historical Medals', dateText: '30 June 2026' }, 'https://www.noonans.co.uk/archive/past-catalogues/935/catalogue/?layout=list&offset=40'); expect(p.offset).toBe(40); expect(p.totalLots).toBe(680); expect(p.lots.length).toBe(3); expect(p.lots[0]).toMatchObject({ lotId: '527995', lotNumber: '1', estimateText: '£90-£120', hammerText: '£280', image: 'https://media.noonans.co.uk/x/629852/Internet%20Image%201_w200h170.jpg' }); expect(p.lots[0]!.description.endsWith('Fine or better')).toBe(true); expect(p.lots[1]).toMatchObject({ lotId: '532131', estimateText: '£2,000-£3,000', hammerText: '£3,800' }); expect(p.lots[2]!.hammerText).toBe('Unsold'); }); it('normalises hammer prices in GBP, skips unsold, keeps estimate and grade', async () => { const p = parseCataloguePage(LIST, { id: '935', title: 'Coins and Historical Medals', dateText: '30 June 2026' }, 'u'); const out = await connector.normalize({ url: 'u', externalId: 'x', kind: 'sale', engine: 'firecrawl', fetchedAt: new Date('2026-09-08T00:00:00Z'), payload: p }); expect(out.length).toBe(2); const bundle = out[0]!; const penny = out[1]!; if (bundle.kind !== 'sale' || penny.kind !== 'sale') throw new Error('sale'); expect(bundle).toMatchObject({ price: 280, currency: 'GBP', buyerPremiumIncluded: false, lotNumber: '1', isBundle: true, auctionHouse: 'Noonans Mayfair', location: 'GB' }); expect(bundle.attributes.metadata).toMatchObject({ estimate_low: 90, estimate_high: 120, estimate_currency: 'GBP' }); expect(penny).toMatchObject({ price: 3800, lotNumber: '76', isBundle: false, sourceUrl: 'https://www.noonans.co.uk/archive/past-catalogues/935/catalogue/532131/' }); expect(penny.saleDate.toISOString()).toBe('2026-06-30T00:00:00.000Z'); expect(penny.attributes.categorySlug).toBe('coins'); expect(penny.attributes.identifiers.noonans_lot).toBe('532131'); expect(penny.condition.conditionRaw).toBe('good very fine'); }); it('fixture lots normalise to GBP hammer sales', async () => { const out = await connector.normalize(loadFixture('noonans', 'catalogue-page').raw); expect(out.length).toBeGreaterThan(0); for (const r of out) if (r.kind === 'sale') expect(r).toMatchObject({ currency: 'GBP', buyerPremiumIncluded: false }); }); });