import { describe, expect, it } from 'vitest'; import { ConnectorMetaSchema } from '@rareindex/connectors'; import { listFixtures, loadFixture, runFixtureSuite } from '@rareindex/connectors/testing'; import metaJson from './meta.json' with { type: 'json' }; import createConnector, { categoryFor, leafCategoryIds, normalizeItem, parseItemsPage, trimItem } from './index.js'; import { isBundleMultilingual, parenCount, parseEuDate, parseEuMoney, yearFromTitle } from '../_g8-auctions-eu-apac-lib/index.js'; const meta = ConnectorMetaSchema.parse(metaJson); const connector = createConnector(meta); const API_ITEM = { id: 5224154, catalog_number: null, auction_id: 9524392, currency: 'EUR', reserve_met: true, reserve_amount: 200, estimate: 450, upper_estimate: null, starting_bid_amount: 25, hammered: false, state: 'sold', title: 'CORTÉBERT, WALTHAM, IMMERFORT ETC., Armbanduhren Konvolut, 20. Jahrhundert. (4).', description: '
Konvolut bestehend aus vier Armbanduhren:
\n\nCortébert, Handaufzug, 1950er Jahre.
', condition: 'Altersgemäße Gebrauchsspuren.
', company_id: 237, category_id: 15, ends_at: 1788854835, published_at: 1788164174, type: 'online', location: 'Cologne', house: 'Stockholms Auktionsverk Köln', placement: 'auf Anfrage', url: 'https://auctionet.com/en/5224154-cortebert-waltham-immerfort-etc-wristwatch-collection-20th-century-4', images: [{ thumb: 't.jpg', mini: 'm.jpg', w640: 'https://images.auctionet.com/thumbs/w640_item_5224154_x.jpg', hd: 'hd.jpg' }], bids: [ { id: 42504089, bidder: 7, amount: 220, your_bid: false, reserve_met: true, auto: false, timestamp: 1788854655 }, { id: 42502618, bidder: 4, amount: 200, your_bid: false, reserve_met: true, auto: false, timestamp: 1788846567 }, ], }; describe('auctionet', () => { runFixtureSuite(connector, it, expect); it('fixtures: sold lots become hammer-basis sales in native currency, unsold lots become ended auction_lots', async () => { let sales = 0; let lots = 0; for (const name of listFixtures('auctionet')) { const fx = loadFixture('auctionet', name); const out = await connector.normalize(fx.raw); for (const r of out) { if (!('attributes' in r)) continue; expect(r.attributes.identifiers.auctionet_item_id).toMatch(/^\d+$/); expect(r.sourceUrl).toMatch(/^https:\/\/auctionet\.com\/en\/(events\/[^/]+\/)?\d+-/); if (r.kind === 'sale') { sales++; expect(['SEK', 'EUR', 'DKK', 'GBP']).toContain(r.currency); expect(r.buyerPremiumIncluded).toBe(false); expect(r.attributes.metadata.price_basis).toBe('winning_bid_excl_buyer_fee'); expect(r.auctionHouse).toBeTruthy(); expect(r.saleDate.getUTCFullYear()).toBeGreaterThanOrEqual(2011); } else if (r.kind === 'auction_lot') { lots++; expect(r.status).toBe('ended'); } } } expect(sales).toBeGreaterThan(20); expect(lots).toBeGreaterThan(0); }); it('trims the API item and normalises it (winning bid = hammer, EUR, bundle of 4)', () => { const item = trimItem(API_ITEM); expect(item).toMatchObject({ id: 5224154, currency: 'EUR', state: 'sold', winningBid: 220, winningBidAt: 1788854655, bidCount: 2, house: 'Stockholms Auktionsverk Köln', location: 'Cologne', categoryId: 15 }); expect(item.images).toEqual(['https://images.auctionet.com/thumbs/w640_item_5224154_x.jpg']); expect(item.description).toBe('Konvolut bestehend aus vier Armbanduhren: Cortébert, Handaufzug, 1950er Jahre.'); const rec = normalizeItem(meta, item, new Date('2026-09-08T10:00:00Z')); expect(rec?.kind).toBe('sale'); if (rec?.kind !== 'sale') return; expect(rec.price).toBe(220); expect(rec.currency).toBe('EUR'); expect(rec.saleDate.toISOString()).toBe('2026-09-08T08:07:15.000Z'); expect(rec.isBundle).toBe(true); expect(rec.attributes.categorySlug).toBe('other_watches'); expect(rec.attributes.year).toBeNull(); // "20. Jahrhundert", "(4)" — no year expect(rec.buyerPremiumIncluded).toBe(false); expect(rec.lotNumber).toBeNull(); expect(rec.condition.conditionRaw).toBe('Altersgemäße Gebrauchsspuren.'); }); it('unsold and out-of-taxonomy items', () => { const unsold = trimItem({ ...API_ITEM, id: 1, state: 'unsold', bids: [], category_id: 128, title: 'MYNT, 5 kronor, Sverige 1955.' }); const rec = normalizeItem(meta, unsold, new Date()); expect(rec?.kind).toBe('auction_lot'); if (rec?.kind === 'auction_lot') { expect(rec.status).toBe('ended'); expect(rec.currentBid).toBeNull(); expect(rec.estimateLow).toBe(450); expect(rec.attributes.categorySlug).toBe('coins'); expect(rec.attributes.year).toBe(1955); } const weapon = trimItem({ ...API_ITEM, id: 2, category_id: 61, title: 'GEVÄR, Husqvarna.' }); expect(normalizeItem(meta, weapon, new Date())).toBeNull(); const unknownCurrency = trimItem({ ...API_ITEM, id: 3, currency: 'XXX' }); expect(normalizeItem(meta, unknownCurrency, new Date())).toBeNull(); }); it('parses a page and pagination metadata', () => { const p = parseItemsPage({ items: [API_ITEM], pagination: { current_page: 1, total_pages: 50, total_entries: 3917226 } }, 'https://auctionet.com/api/v2/items.json?is=ended', 1, { categoryId: null, countryCode: null }); expect(p?.items).toHaveLength(1); expect(p?.totalEntries).toBe(3917226); expect(parseItemsPage({ error: 'x' }, 'u', 1, { categoryId: null, countryCode: null })).toBeNull(); }); it('maps Auctionet categories + multilingual titles to taxonomy slugs', () => { expect(categoryFor(15, 'ARMBANDSUR, Rolex, Datejust, ref 16233, stål och guld.').slug).toBe('rolex'); expect(categoryFor(15, 'ARMBANDSUR, Omega, Seamaster, stål, dam, manuell.').slug).toBe('omega'); expect(categoryFor(110, 'FICKUR, silver, 1800-talets slut.').slug).toBe('other_watches'); expect(categoryFor(128, 'ÄLDRE SVENSKA SEDLAR, 49 st, 1960-80-tal.').slug).toBe('banknotes'); expect(categoryFor(128, 'MYNT, 1 riksdaler 1776.').slug).toBe('coins'); expect(categoryFor(135, 'ORDEN, Vasaorden, riddartecken, guld.').slug).toBe('medals'); expect(categoryFor(136, 'FRIMÄRKEN, samling i album.').slug).toBe('stamps'); expect(categoryFor(19, 'SOFFBORD, Bruno Mathsson, Karl Mathsson, 1960-tal.').slug).toBe('antiques'); expect(categoryFor(18, 'HANS J. WEGNER, armchair "The Chair", Johannes Hansen, Denmark.').slug).toBe('design_furniture'); expect(categoryFor(28, 'OLJEMÅLNING, signerad, landskap.').slug).toBe('art'); expect(categoryFor(26, 'FOTOGRAFI, gelatin silver print.').slug).toBe('photography'); expect(categoryFor(170, 'MACALLAN 18 Years Old Sherry Oak, 70 cl.').slug).toBe('whisky'); expect(categoryFor(170, 'CHÂTEAU MARGAUX 1990, 1 flaska.').slug).toBe('wine'); expect(categoryFor(49, 'HERMÈS, handväska "Birkin 35", Togo.').slug).toBe('luxury_handbags'); expect(categoryFor(268, 'POKÉMON, Charizard, Base Set, holo.').slug).toBe('pokemon'); expect(categoryFor(211, 'SERIETIDNINGAR, Kalle Anka & Co, 1950-tal, 12 st.').slug).toBe('independent_comics'); expect(categoryFor(275, 'MODELLBILAR, Dinky Toys, 5 st.').slug).toBe('model_cars'); expect(categoryFor(215, 'VOLVO P1800 S, 1966.').slug).toBe('automobiles'); expect(categoryFor(61, 'GEVÄR').slug).toBeNull(); expect(categoryFor(253, 'MOTOR').slug).toBeNull(); expect(categoryFor(999, 'Random unknown thing').slug).toBeNull(); expect(categoryFor(999, 'LEICA M3 camera body').slug).toBe('cameras'); expect(leafCategoryIds()).not.toContain(16); // parent "Furniture" expect(leafCategoryIds()).toContain(19); expect(leafCategoryIds()).toContain(42); // Mirrors (childless root) expect(leafCategoryIds()).not.toContain(61); // licence weapons }); it('shared multilingual helpers', () => { expect(parseEuDate('12 juin 2026')?.toISOString()).toBe('2026-06-12T00:00:00.000Z'); expect(parseEuDate('jeudi 09 juillet 2026 14:00')?.toISOString()).toBe('2026-07-09T00:00:00.000Z'); expect(parseEuDate('12. Juni 2026')?.toISOString()).toBe('2026-06-12T00:00:00.000Z'); expect(parseEuDate('1. März 2025')?.toISOString()).toBe('2025-03-01T00:00:00.000Z'); expect(parseEuDate('12 giugno 2026')?.toISOString()).toBe('2026-06-12T00:00:00.000Z'); expect(parseEuDate('12 de junio de 2026')?.toISOString()).toBe('2026-06-12T00:00:00.000Z'); expect(parseEuDate('den 12 juni 2026')?.toISOString()).toBe('2026-06-12T00:00:00.000Z'); expect(parseEuDate('22–23 juin 2026')?.toISOString()).toBe('2026-06-22T00:00:00.000Z'); expect(parseEuDate('June 12, 2026')?.toISOString()).toBe('2026-06-12T00:00:00.000Z'); expect(parseEuDate('12.06.2026')?.toISOString()).toBe('2026-06-12T00:00:00.000Z'); expect(parseEuDate('2026-06-12T14:00:00Z')?.toISOString()).toBe('2026-06-12T00:00:00.000Z'); expect(parseEuDate('12 joulukuuta 2025')?.toISOString()).toBe('2025-12-12T00:00:00.000Z'); expect(parseEuDate('nonsense')).toBeNull(); expect(parseEuMoney('1.250,00 €', 'EUR')).toMatchObject({ amount: 1250, currency: 'EUR' }); expect(parseEuMoney('1 250 €', 'EUR')).toMatchObject({ amount: 1250, currency: 'EUR' }); expect(parseEuMoney('1 081 EUR', 'EUR')).toMatchObject({ amount: 1081, currency: 'EUR' }); expect(parseEuMoney('593EUR', 'EUR')).toMatchObject({ amount: 593, currency: 'EUR' }); expect(parseEuMoney('€ 12.500', 'EUR')).toMatchObject({ amount: 12500, currency: 'EUR' }); expect(parseEuMoney("CHF 1'250", 'CHF', 'ch')).toMatchObject({ amount: 1250, currency: 'CHF' }); expect(parseEuMoney('12 000 SEK', 'SEK')).toMatchObject({ amount: 12000, currency: 'SEK' }); expect(parseEuMoney('4 000 kr', 'SEK')).toMatchObject({ amount: 4000, currency: 'SEK' }); expect(parseEuMoney('£1,250', 'GBP', 'en')).toMatchObject({ amount: 1250, currency: 'GBP' }); expect(parseEuMoney('HK$1,250,000', 'HKD', 'en')).toMatchObject({ amount: 1_250_000, currency: 'HKD' }); expect(parseEuMoney('¥1,250,000', 'JPY', 'en')).toMatchObject({ amount: 1_250_000, currency: 'JPY' }); expect(parseEuMoney('AU$2,400', 'AUD', 'en')).toMatchObject({ amount: 2400, currency: 'AUD' }); expect(parseEuMoney('1.250', 'EUR')).toMatchObject({ amount: 1250 }); expect(parseEuMoney('1.25', 'EUR')).toMatchObject({ amount: 1.25 }); expect(parseEuMoney('n/a', 'EUR')).toBeNull(); expect(parseEuMoney('1 250', null)).toBeNull(); expect(isBundleMultilingual('Armbanduhren Konvolut (4)')).toBe(true); expect(isBundleMultilingual('SEDLAR, 49 st')).toBe(true); expect(isBundleMultilingual('Lot de trois montres')).toBe(true); expect(isBundleMultilingual('Lotto di sei tazze')).toBe(true); expect(isBundleMultilingual('SÄNGBORD, ett par')).toBe(false); expect(isBundleMultilingual('ARMBANDSUR, Rolex, Datejust')).toBe(false); expect(parenCount('LJUSSTAKAR, ett par, silver. (2).')).toBe(2); expect(parenCount('12 st glas')).toBe(12); expect(yearFromTitle('SÄNGBORD, ett par, 1900/2000-tal')).toBeNull(); expect(yearFromTitle('SOFFBORD, 1960-tal')).toBeNull(); expect(yearFromTitle('Cortébert, 1950er Jahre')).toBeNull(); expect(yearFromTitle('Rolex Datejust, 1980s')).toBeNull(); expect(yearFromTitle('VOLVO P1800 S, 1966.')).toBe(1966); expect(yearFromTitle('MYNT, 1 riksdaler 1776.')).toBe(1776); expect(yearFromTitle('CHÂTEAU MARGAUX 1990')).toBe(1990); }); });