SPB Git forge

spb/rareindex

Public
54commits 1branches 0releases
7.1 MBsize
maindefault branch
10 days agolast push
TypeScript 61.9% HTML 37.2% SQL 0.7%
5.7 KB · 62 lines typescript
Raw Blame History
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, { parseAuctionSnapshot, parsePastSales, parseSalePage } 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 = `<h2>juillet 2026</h2><div class="card auction-card grid gap-y-4 md:grid-cols-12" wire:key="auction-1531"> <div class="auction-card-container self-end md:!col-span-4"> <a href="/fr/auctions/design-online-t2442" class="w-full h-full"> <img src="x" class="h-full w-full object-cover"> </a> </div> <div class="flex-col justify-between md:flex md:col-span-8"> <div> <div class="mb-1 text-sm uppercase !text-green "> Online Only </div> <h3 class="max-w-3xl"> <a href="/fr/auctions/design-online-t2442">Design Online</a> </h3></div></div></div>16<div class="card auction-card grid" wire:key="auction-1465"><a href="/fr/auctions/bijoux-horlogerie_20260218"></a><h3 class="max-w-3xl"> <a href="/fr/auctions/bijoux-horlogerie_20260218">Bijoux & Horlogerie</a> </h3></div>`;1718const SALE = `<h1 class="-mb-2 text-4xl">Bijoux & Horlogerie</h1><div wire:snapshot="{&quot;data&quot;:{&quot;page&quot;:[{&quot;title&quot;:&quot;Bijoux &amp; Horlogerie&quot;,&quot;start_date&quot;:&quot;2026-02-13 18:00&quot;,&quot;end_date&quot;:&quot;2026-02-23 18:00&quot;,&quot;place&quot;:&quot;Online&quot;,&quot;number&quot;:2381,&quot;auction_status&quot;:&quot;finished&quot;}]}}"></div>19<div>Résultat (Frais de vente inclus)</div>20<div id="product-577430" class="card product-card swiper-slide !h-auto" wire:key="product-577430"> <div class="relative"> <a href="/fr/products/cartier-paris-1-2381-fr" class="absolute"></a> <div wire:snapshot="{&quot;data&quot;:{&quot;isFavorited&quot;:false}}"></div> <div class="product-card-container"> <img src="https://www.piasa.fr/image/resized/abc/320/480" class="block w-full h-auto"> </div> <div class=" -mt-2.5 mr-3 text-3xl font-medium text-gray-400 md:text-2xl lg:font-normal" > 01 </div> <h3 class=" text-sm md:text-base !normal-case" > CARTIER, Paris </h3> <div class=" text-sm md:text-base mt-2 normal-case"> Années 1900-10 </div> <div class=" -mb-1 text-xm uppercase text-gray-300">Estimation</div> <div class=" mt-1 uppercase ">6 000 / 8 000 €</div> <div class=" -mb-1 text-xm uppercase text-gray-300">Résultat</div> <div class=" mt-1 uppercase ">23 878 €</div> </div></div>21<div id="product-577431" class="card product-card swiper-slide !h-auto"> <a href="/fr/products/freres-rochat-suisse-vers-1810-2-2381-fr"></a> <div class=" -mt-2.5 mr-3 text-3xl font-medium text-gray-400" > 02 </div> <h3 class=" text-sm"> FRÈRES ROCHAT, Suisse </h3> <div class=" text-sm mt-2 normal-case"> Vers 1810 </div> <div class=" -mb-1 text-xm uppercase text-gray-300">Estimation</div> <div class=" mt-1 uppercase ">30 000 / 40 000 €</div> </div>`;2223describe('piasa', () => {24  runFixtureSuite(connector, it, expect);2526  it('fixtures: EUR premium-inclusive results', async () => {27    let sales = 0;28    for (const name of listFixtures('piasa')) {29      for (const r of await connector.normalize(loadFixture('piasa', name).raw)) {30        if (!('attributes' in r)) continue;31        expect(r.attributes.identifiers.piasa_lot).toMatch(/^[a-z0-9_-]+\/\S+$/);32        expect(r.sourceUrl).toMatch(/^https:\/\/www\.piasa\.fr\/fr\/products\//);33        if (r.kind === 'sale') {34          sales++;35          expect(r.currency).toBe('EUR');36          expect(r.buyerPremiumIncluded).toBe(true);37          expect(r.auctionHouse).toBe('PIASA');38        }39      }40    }41    expect(sales).toBeGreaterThan(5);42  });4344  it('parses the past-sales index, the Livewire snapshot and the inlined product cards', async () => {45    const sales = parsePastSales(INDEX);46    expect(sales.map((s) => s.id)).toEqual(['design-online-t2442', 'bijoux-horlogerie_20260218']);47    expect(sales[0]).toMatchObject({ title: 'Design Online', url: 'https://www.piasa.fr/fr/auctions/design-online-t2442', location: 'Online' });48    expect(parseAuctionSnapshot(SALE)).toMatchObject({ startDate: '2026-02-13 18:00', endDate: '2026-02-23 18:00', place: 'Online', number: '2381', status: 'finished' });49    const p = parseSalePage(SALE, sales[1]!)!;50    expect(p.hasMore).toBe(false);51    expect(p.sale).toMatchObject({ date: '2026-02-23T00:00:00.000Z', location: 'Online' });52    expect(p.lots).toHaveLength(2);53    expect(p.lots[0]).toMatchObject({ lotNo: '01', title: 'CARTIER, Paris', subtitle: 'Années 1900-10', price: 23878, currency: 'EUR', premiumIncluded: true, estimateLow: 6000, estimateHigh: 8000, sold: true, url: 'https://www.piasa.fr/fr/products/cartier-paris-1-2381-fr', image: 'https://www.piasa.fr/image/resized/abc/320/480' });54    expect(p.lots[1]).toMatchObject({ lotNo: '02', price: null, sold: false, estimateLow: 30000, estimateHigh: 40000 });55    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, ...p.sale!.extra } }, page: 1, totalLots: 2, lots: p.lots } });56    expect(out.map((r) => r.kind)).toEqual(['sale', 'auction_lot']);57    if (out[0]!.kind === 'sale') expect(out[0]!.saleDate.toISOString()).toBe('2026-02-23T00:00:00.000Z');58    expect(['jewelry', 'other_watches']).toContain(attrsOf(out[0]!).categorySlug);59    expect(parseSalePage('<html>x</html>', sales[1]!)).toBeNull();60  });61});62