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, { parseCataloguePage, parseNzDate, parsePreviousAuctions } 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 = `
Timed Auction

Vintage Toy Auction

Thursday, 2 - Wednesday, 15 October 2025

Auction Details

Sterling Silver & Accoutrements

Wednesday, 21 June 2023

Auction Details
`; const CAT = `

Sterling Silver & Accoutrements Wednesday, 21 June 2023 / 10:00 am start

Geo II S/S Sugar Caster

0001

Geo II S/S Sugar Caster
Estimate: $200 - $350

Rolex Oyster Perpetual wristwatch

Rolex Oyster Perpetual wristwatch
Estimate: $3,000 - $5,000

`; describe('dunbar-sloane', () => { runFixtureSuite(connector, it, expect); it('fixtures: NZD hammer ("plus premium") results', async () => { let sales = 0; for (const name of listFixtures('dunbar-sloane')) { for (const r of await connector.normalize(loadFixture('dunbar-sloane', name).raw)) { if (!('attributes' in r)) continue; expect(r.attributes.identifiers.dunbar_sloane_lot).toMatch(/^\d+\/\S+$/); expect(r.sourceUrl).toMatch(/^https:\/\/auctions\.dunbarsloane\.co\.nz\/\d+\/catalogue\//); if (r.kind === 'sale') { sales++; expect(r.currency).toBe('NZD'); expect(r.buyerPremiumIncluded).toBe(false); expect(r.auctionHouse).toBe('Dunbar Sloane'); } } } expect(sales).toBeGreaterThan(10); }); it('parses NZ dates, the previous-auctions list and a catalogue page', async () => { expect(parseNzDate('Thursday, 2 - Wednesday, 15 October 2025')).toBe('2025-10-02T00:00:00.000Z'); expect(parseNzDate('Wednesday, 21 June 2023 / 10:00 am start')).toBe('2023-06-21T00:00:00.000Z'); expect(parseNzDate('Friday, 17 - Tuesday, 28 October 2025')).toBe('2025-10-17T00:00:00.000Z'); const sales = parsePreviousAuctions(INDEX); expect(sales.map((s) => s.id)).toEqual(['1858', '1745']); expect(sales[0]).toMatchObject({ title: 'Vintage Toy Auction', url: 'https://auctions.dunbarsloane.co.nz/1858/catalogue', date: '2025-10-02T00:00:00.000Z' }); const p = parseCataloguePage(CAT, sales[1]!, 1)!; expect(p.hasMore).toBe(true); expect(parseCataloguePage(CAT, sales[1]!, 6)!.hasMore).toBe(false); expect(p.sale).toMatchObject({ title: 'Sterling Silver & Accoutrements', date: '2023-06-21T00:00:00.000Z' }); expect(p.lots[0]).toMatchObject({ lotNo: '0001', title: 'Geo II S/S Sugar Caster', price: 140, currency: 'NZD', premiumIncluded: false, estimateLow: 200, estimateHigh: 350, sold: true, url: 'https://auctions.dunbarsloane.co.nz/1745/catalogue/0001', image: 'https://d1v8q4.tandemauctions.com/1745/0001/sq/875763a3.webp' }); expect(p.lots[1]).toMatchObject({ lotNo: '0002', price: null, sold: false, estimateLow: 3000, estimateHigh: 5000 }); const out = await connector.normalize({ url: sales[1]!.url, kind: 'sale', engine: 'api', fetchedAt: new Date(), payload: { kind: 'sale_results', url: sales[1]!.url, sale: { ...sales[1]!, ...p.sale, extra: sales[1]!.extra }, page: 1, totalLots: null, lots: p.lots } }); expect(out.map((r) => r.kind)).toEqual(['sale', 'auction_lot']); expect(attrsOf(out[0]!).categorySlug).toBe('silver'); expect(attrsOf(out[1]!).categorySlug).toBe('rolex'); expect(connector.salePageUrl(sales[1]!, 2)).toBe('https://auctions.dunbarsloane.co.nz/1745/catalogue?page=2'); expect(parseCataloguePage('x', sales[1]!, 1)).toBeNull(); }); });