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%
4.1 KB · 73 lines typescript
Raw Blame History
1import { readFileSync } from 'node:fs';2import path from 'node:path';3import { describe, expect, it } from 'vitest';4import { getConnectorMeta } from '@rareindex/connectors';5import { fixtureDir, loadFixture, runFixtureSuite } from '@rareindex/connectors/testing';6import createConnector, { parseCategoryPage, parseProductPage } from './index.js';78const connector = createConnector(getConnectorMeta('chronext'));9const sample = (name: string) => readFileSync(path.join(fixtureDir('chronext'), name), 'utf8');1011describe('chronext', () => {12  runFixtureSuite(connector, it, expect);1314  it('parses product tiles (brand, model, reference, price text, condition, image, V-id) and the next-page offset link', async () => {15    const p = parseCategoryPage(sample('category-tiles.sample.html'), 'https://www.chronext.com/rolex/datejust-pre-owned', '/rolex/datejust-pre-owned', 1);16    expect(p.tiles).toHaveLength(3);17    const t = p.tiles[0]!;18    expect(t.id).toBe('V01800358');19    expect(t.brand).toBe('Rolex');20    expect(t.model).toBe('Lady-Datejust');21    expect(t.reference).toBe('79160');22    expect(t.priceText).toBe('USD 4,380');23    expect(t.condition).toBe('Like New');24    expect(t.href).toBe('https://www.chronext.com/rolex/lady-datejust/79160/V01800358');25    expect(t.image).toMatch(/^https:\/\/chronexttime\.imgix\.net\//);26    expect(p.nextUrl).toContain('offset%5D=24');27    expect(p.title).toBe('Rolex Datejust Pre-Owned Watches');28    const out = await connector.normalize({ url: p.url, externalId: null, kind: 'listing', engine: 'api', fetchedAt: new Date('2026-09-08T00:00:00Z'), payload: p });29    const l = out[0];30    if (l?.kind !== 'listing') throw new Error('expected listing');31    expect(l.price).toBe(4380);32    expect(l.currency).toBe('USD');33    expect(l.attributes.categorySlug).toBe('rolex');34    expect(l.attributes.reference).toBe('79160');35    expect(l.attributes.identifiers).toEqual({ chronext_id: 'V01800358', reference: '79160' });36    expect(l.condition.conditionRaw).toBe('Excellent');37    expect(l.seller).toBe('CHRONEXT');38  });3940  it('parses the product page JSON-LD (sku, mpn, brand, USD offer)', async () => {41    const p = parseProductPage(sample('product-jsonld.sample.html'), 'https://www.chronext.com/rolex/datejust/116234/V66464');42    if (p?.kind !== 'product_page') throw new Error('expected product page');43    expect(p.product.id).toBe('V66464');44    expect(p.product.sku).toBe('A20325');45    expect(p.product.mpn).toBe('116234');46    expect(p.product.brand).toBe('Rolex');47    expect(p.product.price).toBe(8850);48    expect(p.product.currency).toBe('USD');49    expect(p.product.condition).toBe('RefurbishedCondition');50    const out = await connector.normalize({ url: p.url, externalId: null, kind: 'listing', engine: 'api', fetchedAt: new Date('2026-09-08T00:00:00Z'), payload: p });51    const l = out[0];52    if (l?.kind !== 'listing') throw new Error('expected listing');53    expect(l.attributes.model).toBe('Datejust 36');54    expect(l.attributes.identifiers.chronext_sku).toBe('A20325');55    expect(l.attributes.reference).toBe('116234');56    expect(l.availability).toBe('available');57  });5859  it('category fixture normalises to Rolex listings with references; EUR price text is kept in EUR', async () => {60    const fx = loadFixture('chronext', 'rolex-datejust-p1');61    const out = await connector.normalize(fx.raw);62    expect(out.length).toBeGreaterThan(5);63    expect(out.every((r) => r.kind === 'listing' && r.attributes.categorySlug === 'rolex' && r.currency === 'USD')).toBe(true);64    const eur = await connector.normalize({ ...fx.raw, payload: { ...(fx.raw.payload as object), tiles: [{ id: 'V1', href: 'https://www.chronext.com/omega/speedmaster/311.30.42.30.01.005/V1', brand: 'Omega', model: 'Speedmaster', reference: '311.30.42.30.01.005', priceText: 'EUR 5.850', condition: 'Very Good', image: null }] } });65    const l = eur[0];66    if (l?.kind !== 'listing') throw new Error('expected listing');67    expect(l.currency).toBe('EUR');68    expect(l.price).toBe(5850);69    expect(l.attributes.categorySlug).toBe('omega');70    expect(l.condition.conditionRaw).toBe('Very good');71  });72});73