TypeScript 61.9%
HTML 37.2%
SQL 0.7%
1import { describe, expect, it } from 'vitest';2import metaJson from './meta.json' with { type: 'json' };3import { loadFixture, runFixtureSuite } from '@rareindex/connectors/testing';4import { localMeta } from '../_lib/local-meta.js';5import createConnector, { isSold, pageUrl, parseAuctionList, parseEndDate, parseLotPage } from './index.js';67const connector = createConnector(localMeta(metaJson));8const snapshot = (name: string): string => String((loadFixture('whisky-auction', name).raw.payload as { snapshot?: string }).snapshot ?? '');910describe('whisky-auction', () => {11 runFixtureSuite(connector, it, expect);1213 it('parses the lot grid HTML (winning bid, state, end date, product id)', () => {14 const html = snapshot('auction-201-whisky-p0');15 const p = parseLotPage(html);16 expect(p.total).toBeGreaterThan(100);17 expect(p.lots.length).toBeGreaterThanOrEqual(2);18 const first = p.lots[0]!;19 expect(first.lotId).toMatch(/^\d+$/);20 expect(first.url).toMatch(/^https:\/\/whisky\.auction\/auctions\/lot\/\d+\//);21 expect(first.winningBid).toBeGreaterThan(0);22 expect(['met', 'na', 'aftersale']).toContain(first.status);23 expect(first.endDate).toMatch(/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}/);24 expect(first.productId).toMatch(/^\d+$/);25 expect(first.image).toMatch(/media\.whisky\.auction/);26 expect(p.auctionTitle).toMatch(/2026/);27 });2829 it('parses the past-auction list', () => {30 const entries = parseAuctionList(snapshot('auctions-list'));31 expect(entries.length).toBeGreaterThan(1);32 expect(Number(entries[0]!.id)).toBeGreaterThan(Number(entries[1]!.id));33 expect(entries[0]!.endedOn).toMatch(/\d{1,2} [A-Z][a-z]{2} \d{4}/);34 });3536 it('treats NotMet / negative bids as unsold and builds page URLs', () => {37 const base = { lotId: '1', productId: null, url: 'https://whisky.auction/auctions/lot/1/x', title: 'x', sub1: null, sub2: null, image: null, endDate: null, endedOn: null, vatScheme: null } as const;38 expect(isSold({ ...base, winningBid: -1, status: 'notmet' })).toBe(false);39 expect(isSold({ ...base, winningBid: 0, status: 'na' })).toBe(false);40 expect(isSold({ ...base, winningBid: 120, status: 'na' })).toBe(true);41 expect(isSold({ ...base, winningBid: 120, status: 'aftersale' })).toBe(true);42 const url = pageUrl('201', { category: 'Rum', slug: 'rum' }, 2, 90);43 expect(url).toBe('https://whisky.auction/auctions/auction/201?category=Rum&pageIndex=2&pageSize=90&sort=Price&dir=desc');44 expect(parseEndDate('2026-05-19 21:20:00')?.toISOString()).toBe('2026-05-19T21:20:00.000Z');45 expect(parseEndDate('garbage')).toBeNull();46 });4748 it('normalises sold lots into GBP hammer sales dated by the lot end', async () => {49 const fx = loadFixture('whisky-auction', 'auction-201-whisky-p0');50 const out = await connector.normalize(fx.raw);51 expect(out.length).toBeGreaterThan(0);52 for (const r of out) {53 if (r.kind !== 'sale') throw new Error('expected sale');54 expect(r.currency).toBe('GBP');55 expect(r.buyerPremiumIncluded).toBe(false);56 expect(r.attributes.categorySlug).toBe('whisky');57 expect(r.attributes.identifiers.whisky_auction_lot).toMatch(/^\d+$/);58 expect(r.saleDate.toISOString().slice(0, 7)).toBe('2026-05');59 expect(r.auctionHouse).toBe('Whisky.Auction');60 }61 const rum = loadFixture('whisky-auction', 'auction-201-rum-p0');62 const rumOut = await connector.normalize(rum.raw);63 const payload = rum.raw.payload as { lots: Array<{ status: string; winningBid: number | null }> };64 const unsold = payload.lots.filter((l) => l.status === 'notmet').length;65 expect(rumOut.length).toBe(payload.lots.length - unsold);66 for (const r of rumOut) expect((r as { attributes: { categorySlug: string } }).attributes.categorySlug).toBe('rum');67 });68});69