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%
3.4 KB · 48 lines typescript
Raw Blame History
1import { describe, expect, it } from 'vitest';2import { getConnectorMeta } from '@rareindex/connectors';3import { loadFixture, runFixtureSuite } from '@rareindex/connectors/testing';4import createConnector, { parseModelPage } from './index.js';56const connector = createConnector(getConnectorMeta('chrono24'));78describe('chrono24', () => {9  runFixtureSuite(connector, it, expect);1011  it('maps a Rolex Daytona model page to listings', async () => {12    const fx = loadFixture('chrono24', 'rolex__daytona--mod2');13    const out = await connector.normalize(fx.raw);14    expect(out.length).toBeGreaterThan(20);15    const l = out[0];16    if (l?.kind !== 'listing') throw new Error();17    expect(l.attributes.categorySlug).toBe('rolex');18    expect(l.attributes.brand).toBe('Rolex');19    expect(l.attributes.model).toBe('Daytona');20    expect(l.listingType).toBe('fixed_price');21    expect(l.price).toBeGreaterThan(1000);22    expect(l.currency).toBe('USD');23    expect(l.sourceUrl).toMatch(/--id\d+\.htm$/);24    expect(l.attributes.identifiers.chrono24_id).toMatch(/^\d+$/);25    const withRef = out.filter((r) => r.kind === 'listing' && r.attributes.reference);26    expect(withRef.length).toBeGreaterThan(out.length / 2);27  });2829  it('parses the AggregateOffer JSON-LD', () => {30    const html = `<script type="application/ld+json">{"@context":"http://schema.org","@graph":[{"@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","item":{"@id":"https://www.chrono24.com/","name":"Chrono24"},"position":1},{"@type":"ListItem","item":{"@id":"https://www.chrono24.com/rolex/index.htm","name":"Rolex watches"},"position":2},{"@type":"ListItem","item":{"@id":"https://www.chrono24.com/rolex/daytona--mod2.htm","name":"Daytona watches"},"position":3}]},{"@type":"AggregateOffer","priceCurrency":"USD","offerCount":2,"offers":[{"@type":"Offer","name":"Rolex Daytona 116500LN Panda 40mm Full Set 2019","price":"31495","priceCurrency":"USD","image":[{"@type":"ImageObject","contentUrl":"https://img.chrono24.com/a.jpg"}],"url":"https://www.chrono24.com/rolex/daytona--id48341690.htm"}]}]}</script>`;31    const p = parseModelPage(html, 'https://www.chrono24.com/rolex/daytona--mod2.htm');32    expect(p.brand).toBe('Rolex');33    expect(p.model).toBe('Daytona');34    expect(p.offers).toEqual([{ name: 'Rolex Daytona 116500LN Panda 40mm Full Set 2019', price: 31495, currency: 'USD', url: 'https://www.chrono24.com/rolex/daytona--id48341690.htm', image: 'https://img.chrono24.com/a.jpg' }]);35  });3637  it('derives reference, year, size and completeness from the offer name', async () => {38    const raw = { url: 'https://www.chrono24.com/rolex/daytona--mod2.htm', externalId: null, kind: 'listing' as const, engine: 'scrapfly' as const, fetchedAt: new Date('2026-09-07T00:00:00Z'), payload: { kind: 'model_page', url: 'https://www.chrono24.com/rolex/daytona--mod2.htm', brand: 'Rolex', model: 'Daytona', breadcrumb: [], totalListings: 1, offers: [{ name: 'Rolex Daytona 116500LN Panda 40mm Full Set 2019 Unworn', price: 31495, currency: 'USD', url: 'https://www.chrono24.com/rolex/daytona--id1.htm', image: null }] } };39    const [l] = await connector.normalize(raw);40    if (l?.kind !== 'listing') throw new Error();41    expect(l.attributes.reference).toBe('116500LN');42    expect(l.attributes.year).toBe(2019);43    expect(l.attributes.size).toBe('40mm');44    expect(l.condition.completeness).toBe('full_set');45    expect(l.condition.condition).toBe('unworn');46  });47});48