TypeScript 61.9%
HTML 37.2%
SQL 0.7%
1import { describe, expect, it } from 'vitest';2import type { NormalizedRecord } from '@rareindex/shared';3import { ConnectorMetaSchema } from '@rareindex/connectors';4import { listFixtures, loadFixture, runFixtureSuite } from '@rareindex/connectors/testing';5import metaJson from './meta.json' with { type: 'json' };6import createConnector, { humanizeSlug, parseCataloguePage, parseSalesSitemap } from './index.js';78const meta = ConnectorMetaSchema.parse(metaJson);9const connector = createConnector(meta);10const attrsOf = (r: NormalizedRecord) => {11 if (!('attributes' in r)) throw new Error(`record kind ${r.kind} has no attributes`);12 return r.attributes;13};1415const NEXT = {16 props: {17 pageProps: {18 auction: { uuid: 'a-1', sale_no: 'G000002', title: { en: 'Tour Auto 2025 • The Official Sale', fr: 'Tour Auto 2025 • La Vente Officielle' }, start_date: '2025-04-07T14:00:00.000Z', status: 'completed', type: 'live', currency: { code: 'EUR' }, premiums: [{ percent: 25, amount_over: 0 }], branch: { name: 'Aguttes', city: 'Neuilly-sur-seine', country_code: 'FR' } },19 auctionLots: {20 count: 39,21 limit: 24,22 page: 1,23 results: [24 { uuid: 'l-1', lot_no: '1', status: 'sold', low: '15000.00', high: '25000.00', hammer_price: '20000.00', title: { en: 'Michael Schumacher', fr: 'Michael Schumacher' }, quantity: 1, num_of_bids: 0, primary_image: { data: { lg: { url: 'https://media.app.artisio.co/x_lg.jpeg' } } }, dynamic_fields: { en: { title: 'Michael Schumacher', artist: '', car_brand: 'Ferrari', description: 'Official BELL DOMINATOR helmet, worn during the 1999 pre-season tests<br>Numbered 9th.' } } },25 { uuid: 'l-2', lot_no: '2', status: 'unsold', low: '1200.00', high: '1800.00', hammer_price: null, title: { en: 'Ferrari F2008', fr: 'Ferrari F2008' }, quantity: 1, dynamic_fields: { en: { description: 'Nose cone.' } } },26 { uuid: 'l-3', lot_no: '35', status: 'sold', low: '100000.00', high: '150000.00', hammer_price: '235000.00', title: { en: 'CARTIER', fr: 'CARTIER' }, dynamic_fields: { en: { description: 'Tank wristwatch, yellow gold, circa 1975.' } } },27 ],28 },29 },30 },31};32const HTML = `<html><body><a href="/lot/tour-auto-2025-la-vente-officielle-a-1/michael-schumacher-l-1">x</a><a href="/lot/tour-auto-2025-la-vente-officielle-a-1/cartier-l-3">y</a><script id="__NEXT_DATA__" type="application/json">${JSON.stringify(NEXT)}</script></body></html>`;3334describe('aguttes', () => {35 runFixtureSuite(connector, it, expect);3637 it('fixtures: EUR hammer-price sales with the Aguttes lot identifier', async () => {38 let sales = 0;39 for (const name of listFixtures('aguttes')) {40 const out = await connector.normalize(loadFixture('aguttes', name).raw);41 for (const r of out) {42 if (!('attributes' in r)) continue;43 expect(r.attributes.identifiers.aguttes_lot).toMatch(/^[^/]+\/\S+$/);44 expect(r.sourceUrl.startsWith('https://www.aguttes.com/')).toBe(true);45 if (r.kind === 'sale') {46 sales++;47 expect(r.currency).toBe('EUR');48 expect(r.buyerPremiumIncluded).toBe(false);49 expect(r.auctionHouse).toBe('Aguttes');50 expect(r.lotNumber).toBeTruthy();51 }52 }53 }54 expect(sales).toBeGreaterThan(5);55 });5657 it('parses the sitemap (newest catalogues first) and slugs', () => {58 const xml = `<urlset><url><loc>https://www.aguttes.com/catalogue/11442</loc></url><url><loc>https://www.aguttes.com/catalogue/160425</loc></url><url><loc>https://www.aguttes.com/catalogue/livres-manuscrits-6339ab29-3d37-453b-aeeb-d33046b92b2f</loc></url></urlset>`;59 const sales = parseSalesSitemap(xml);60 expect(sales.map((s) => s.id)).toEqual(['livres-manuscrits-6339ab29-3d37-453b-aeeb-d33046b92b2f', '160425', '11442']);61 expect(sales[0]!.title).toBe('livres manuscrits');62 expect(humanizeSlug('livres-manuscrits-6339ab29-3d37-453b-aeeb-d33046b92b2f')).toBe('livres manuscrits');63 });6465 it('parses a catalogue page from __NEXT_DATA__ (hammer, estimates, sold/unsold, pagination, lot URLs)', async () => {66 const sale = { id: '160425', title: '160425', url: 'https://www.aguttes.com/catalogue/160425', date: null, location: null, extra: {} };67 const p = parseCataloguePage(HTML, sale, 1)!;68 expect(p.totalLots).toBe(39);69 expect(p.hasMore).toBe(true);70 expect(p.sale?.date).toBe('2025-04-07T14:00:00.000Z');71 expect(p.sale?.title).toBe('Tour Auto 2025 • The Official Sale');72 expect(p.lots).toHaveLength(3);73 expect(p.lots[0]).toMatchObject({ lotNo: '1', price: 20000, currency: 'EUR', premiumIncluded: false, estimateLow: 15000, estimateHigh: 25000, sold: true, url: 'https://www.aguttes.com/lot/tour-auto-2025-la-vente-officielle-a-1/michael-schumacher-l-1', image: 'https://media.app.artisio.co/x_lg.jpeg' });74 expect(p.lots[0]!.description).toBe('Official BELL DOMINATOR helmet, worn during the 1999 pre-season tests Numbered 9th.');75 expect(p.lots[1]).toMatchObject({ lotNo: '2', price: null, sold: false });76 expect(p.lots[1]!.url).toContain('#lot-2');77 Object.assign(sale, p.sale, { extra: p.sale!.extra });78 const out = await connector.normalize({ url: sale.url, kind: 'sale', engine: 'api', fetchedAt: new Date('2026-09-08T00:00:00Z'), payload: { kind: 'sale_results', url: sale.url, sale, page: 1, totalLots: 39, lots: p.lots } });79 expect(out.map((r) => r.kind)).toEqual(['sale', 'auction_lot', 'sale']);80 const helmet = out[0]!;81 if (helmet.kind === 'sale') {82 expect(helmet.saleDate.toISOString()).toBe('2025-04-07T14:00:00.000Z');83 expect(helmet.attributes.categorySlug).toBe('automotive_memorabilia');84 expect(helmet.location).toBe('Neuilly-sur-seine, France');85 expect(helmet.attributes.metadata.sale_no).toBe('G000002');86 }87 const cartier = out[2]!;88 expect(attrsOf(cartier).categorySlug).toBe('other_watches');89 expect(attrsOf(cartier).brand).toBe('Cartier');90 const unsold = out[1]!;91 if (unsold.kind === 'auction_lot') expect(unsold.status).toBe('ended');92 expect(parseCataloguePage('<html></html>', sale, 1)).toBeNull();93 });94});95