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, { lotsFromJson, parseResultDetail, parseResultsIndex } 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 INDEX = `<div class="col-6 col-md-4 col-lg-3"><div class="catalogue-result-item"><div class="catalogue-result-item-img"><a href="/de/auktionen/ergebnisse/detail/1296-1-african-and-oceanic-art.html"><picture></picture></a></div><div class="catalogue-result-item-info"><div class="catalogue-result-item-info-auction">Auktion 1296</div><div class="catalogue-result-item-info-title"><a href="/de/auktionen/ergebnisse/detail/1296-1-african-and-oceanic-art.html"><h3>African and Oceanic Art</h3></a></div><div class="catalogue-result-item-info-date-location"><div><span class="catalogue-result-item-info-date-date">01.07.2026 14:00</span><span class="catalogue-result-item-info-date-location">, Brussels</span></div></div></div></div></div>16<div class="col-6"><div class="catalogue-result-item"><a href="/de/auktionen/ergebnisse/detail/1293-1-asiatische-kunst.html"></a><div class="catalogue-result-item-info-auction">Auktion 1293</div><h3>Asiatische Kunst</h3><span class="catalogue-result-item-info-date-date">12.06.2026 10:00</span><span class="catalogue-result-item-info-date-location">, Köln</span></div></div>`;1718const DETAIL = `<div class="catalogue-info"><span>27.11.2015, 18:00</span><span>|</span><span>Moderne Kunst</span><span>|</span><span>Köln</span></div><h1 class="catalogue-detail-title">Auktionsergebnisse zu Auktion 1059 - Moderne Kunst</h1><div id="catalogue-result-detail" catalogue_uid="245" catalogue_type="resultList" language="1" v-cloak><p>Alle Ergebnisse beinhalten den Zuschlagspreis und das Aufgeld (ohne Gewähr).</p></div>`;1920const JSON_LOTS = { lots: [21 { uid: 125134, number: 301, position: '', state: 'Z', hammerprice: 74400, hammerprice_type: 'B', estimate: 60000, estimate_to: 80000, title: 'Raoul Dufy', subtitle: "Le funiculaire à L'Estaque", description: 'Öl auf Leinwand 1908', link: 'https://www.lempertz.com/de/kataloge/lot/1059-1/301-raoul-dufy.html' },22 { uid: 125272, number: 300, position: '', state: 'K', hammerprice: 0, estimate: 90000, estimate_to: 110000, title: 'Kees van Dongen', subtitle: 'Femme nue au lierre', link: '/de/kataloge/lot/1059-1/300-kees-van-dongen.html' },23 { uid: 1, number: 12, position: 'A', state: 'V', hammerprice: 1200, estimate: 800, estimate_to: 1200, title: 'Rolex', subtitle: 'Datejust Ref. 16233, Stahl/Gold', link: '/x.html' },24] };2526describe('lempertz', () => {27 runFixtureSuite(connector, it, expect);2829 it('fixtures: premium-inclusive EUR sales, unsold → auction_lot', async () => {30 let sales = 0;31 let lots = 0;32 for (const name of listFixtures('lempertz')) {33 for (const r of await connector.normalize(loadFixture('lempertz', name).raw)) {34 if (r.kind === 'sale') {35 sales++;36 expect(r.currency).toBe('EUR');37 expect(r.buyerPremiumIncluded).toBe(true);38 expect(r.auctionHouse).toBe('Lempertz');39 expect(r.attributes.identifiers.lempertz_lot).toMatch(/^\d+-\d+-.+\/\S+$/);40 expect(r.sourceUrl).toMatch(/^https:\/\/www\.lempertz\.com\//);41 } else if (r.kind === 'auction_lot') lots++;42 }43 }44 expect(sales).toBeGreaterThan(20);45 expect(lots).toBeGreaterThanOrEqual(0);46 });4748 it('parses the results index (German dates, city)', () => {49 const sales = parseResultsIndex(INDEX);50 expect(sales).toHaveLength(2);51 expect(sales[0]).toMatchObject({ id: '1296-1-african-and-oceanic-art', title: 'African and Oceanic Art', url: 'https://www.lempertz.com/de/auktionen/ergebnisse/detail/1296-1-african-and-oceanic-art.html', date: '2026-07-01T00:00:00.000Z', location: 'Brussels' });52 expect(sales[0]!.extra.auction_no).toBe('1296');53 expect(sales[1]!.date).toBe('2026-06-12T00:00:00.000Z');54 });5556 it('parses the detail page header and the JSON lots', async () => {57 const d = parseResultDetail(DETAIL);58 expect(d).toMatchObject({ catalogueUid: '245', language: 'de', dateText: '27.11.2015, 18:00', location: 'Köln', premiumNote: true });59 const sale = { id: '1059-1-moderne-kunst', title: 'Moderne Kunst', url: 'https://www.lempertz.com/de/auktionen/ergebnisse/detail/1059-1-moderne-kunst.html', date: '2015-11-27T00:00:00.000Z', location: 'Köln', extra: {} };60 const lots = lotsFromJson(JSON_LOTS, sale);61 expect(lots).toHaveLength(3);62 expect(lots[0]).toMatchObject({ lotNo: '301', title: 'Raoul Dufy', subtitle: "Le funiculaire à L'Estaque", price: 74400, currency: 'EUR', premiumIncluded: true, estimateLow: 60000, estimateHigh: 80000, sold: true });63 expect(lots[1]).toMatchObject({ lotNo: '300', price: null, sold: false, url: 'https://www.lempertz.com/de/kataloge/lot/1059-1/300-kees-van-dongen.html' });64 expect(lots[2]).toMatchObject({ lotNo: '12A', extra: { under_reserve: true } });65 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: 3, lots } });66 expect(out.map((r) => r.kind)).toEqual(['sale', 'auction_lot', 'sale']);67 expect(attrsOf(out[0]!).categorySlug).toBe('contemporary_art');68 expect(attrsOf(out[2]!).categorySlug).toBe('rolex');69 expect(attrsOf(out[2]!).reference).toBe('16233');70 if (out[0]!.kind === 'sale') expect(out[0]!.saleDate.toISOString()).toBe('2015-11-27T00:00:00.000Z');71 expect(lotsFromJson({ error: true }, sale)).toEqual([]);72 });73});74