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%
6.1 KB · 69 lines typescript
Raw Blame History
1import { describe, expect, it } from 'vitest';2import { readFileSync } from 'node:fs';3import path from 'node:path';4import { fileURLToPath } from 'node:url';5import { loadFixture, runFixtureSuite } from '@rareindex/connectors/testing';6import { localMeta } from '../_lib/local-meta.js';7import createConnector, { parsePricesRealised, parseSalesIndex } from './index.js';89const dir = path.dirname(fileURLToPath(import.meta.url));10const connector = createConnector(localMeta(JSON.parse(readFileSync(path.join(dir, 'meta.json'), 'utf8'))));1112const INDEX = `<ul class="past-sales__list"><li class="past-sale-row past-sale-row--rich" data-sale-number="142"><p class="past-sale-row__meta"><span class="past-sale-row__label">Sale 142</span><span class="past-sale-row__date">28-30 July 2026</span><span class="past-sale-row__city">Sydney</span></p><p class="past-sale-row__title">Sale 142 Important Coins, Medals &amp; Banknotes</p><p class="past-sale-row__chips"><a class="past-sale-row__chip" href="/auctions/sale/142">Browse catalogue</a><a class="past-sale-row__chip" href="/auctions/sale/142/prices-realised">Prices Realised</a></p></li>13<li class="past-sale-row" data-sale-number="143"><p class="past-sale-row__meta"><span class="past-sale-row__label">Sale 143</span><span class="past-sale-row__date">17-19 November 2026</span></p><p class="past-sale-row__title">Upcoming</p><p class="past-sale-row__chips"><a class="past-sale-row__chip" href="/auctions/sale/143">Browse catalogue</a></p></li></ul>`;1415const PR = `<h1>Prices Realised · Sale 142</h1><p class="prices-realised__sale-title">Sale 142 Important Coins, Medals &amp; Banknotes</p><p class="prices-realised__venue">Wyoming 175 Macquarie St Sydney, NSW 2000</p><p class="prices-realised__dates">28-30 July 2026</p>16<p class="prices-realised__total"><span class="prices-realised__total-note">All prices exclude buyer and vendor premiums.</span></p>17<table class="table prices-realised__table"><tbody>18<tr><td class="prices-realised__cell-lot"><a href="/auctions/lot/?id=457987" class="prices-realised__lot-link"> Lot 1 </a></td><td class="prices-realised__cell-desc"><strong>George V - Elizabeth II,</strong> florins, 1927 Canberra, 1951 Jubilee (2), 1954 Royal Visit.<em> Good very fine - extremely fine.</em> (4)</td><td class="prices-realised__cell-price"> $90 </td></tr>19<tr><td class="prices-realised__cell-lot"><a href="/auctions/lot/?id=458100" class="prices-realised__lot-link"> Lot 120 </a></td><td class="prices-realised__cell-desc"><strong>George V,</strong> sovereign, 1918 Perth (S.4001), PCGS MS64.<em> Uncirculated.</em></td><td class="prices-realised__cell-price"> $1,250 </td></tr>20<tr><td class="prices-realised__cell-lot"><a href="/auctions/lot/?id=458101" class="prices-realised__lot-link"> Lot 121 </a></td><td class="prices-realised__cell-desc"><strong>Commonwealth of Australia,</strong> ten shillings, Riddle/Sheehan (1934) (R.10).<em> Fine.</em></td><td class="prices-realised__cell-price"><span class="prices-realised__status">Passed in</span></td></tr>21</tbody></table>`;2223describe('noble-numismatics', () => {24  runFixtureSuite(connector, it, expect);2526  it('parses the sales index (only sales with a prices-realised link are crawled)', () => {27    const s = parseSalesIndex(INDEX);28    expect(s.length).toBe(2);29    expect(s[0]).toEqual({ number: '142', title: 'Sale 142 Important Coins, Medals & Banknotes', dateText: '28-30 July 2026', city: 'Sydney', hasPrices: true });30    expect(s[1]!.hasPrices).toBe(false);31  });3233  it('parses prices realised rows: lot id, headline, grading sentence, price or status', () => {34    const p = parsePricesRealised(PR, '142')!;35    expect(p.sale).toEqual({ number: '142', title: 'Sale 142 Important Coins, Medals & Banknotes', dateText: '28-30 July 2026', city: 'Wyoming 175 Macquarie St Sydney, NSW 2000' });36    expect(p.premiumNote).toBe('All prices exclude buyer and vendor premiums.');37    expect(p.lots.length).toBe(3);38    expect(p.lots[0]).toMatchObject({ lotId: '457987', lotNumber: '1', headline: 'George V - Elizabeth II', gradingText: 'Good very fine - extremely fine.', priceText: '$90', status: null });39    expect(p.lots[2]).toMatchObject({ lotId: '458101', priceText: null, status: 'Passed in' });40  });4142  it('normalises AUD hammer sales dated by the sale, skips passed-in lots, flags multiples', async () => {43    const page = parsePricesRealised(PR, '142')!;44    const payload = { kind: 'prices_realised' as const, sale: page.sale, url: 'https://www.noble.com.au/auctions/sale/142/prices-realised', premiumNote: page.premiumNote, chunk: 0, totalLots: 3, lots: page.lots };45    const out = await connector.normalize({ url: payload.url, externalId: 'x', kind: 'sale', engine: 'api', fetchedAt: new Date('2026-09-08T00:00:00Z'), payload });46    expect(out.length).toBe(2);47    const florins = out[0]!;48    const sov = out[1]!;49    if (florins.kind !== 'sale' || sov.kind !== 'sale') throw new Error('sale');50    expect(florins).toMatchObject({ price: 90, currency: 'AUD', buyerPremiumIncluded: false, isBundle: true, lotNumber: '1', auctionHouse: 'Noble Numismatics', sourceUrl: 'https://www.noble.com.au/auctions/lot/?id=457987' });51    expect(florins.saleDate.toISOString()).toBe('2026-07-28T00:00:00.000Z');52    expect(florins.condition.conditionRaw).toBe('Good very fine - extremely fine');53    expect(sov).toMatchObject({ price: 1250, isBundle: false });54    expect(sov.grade).toMatchObject({ grader: 'pcgs', grade: 'MS64' });55    expect(sov.attributes).toMatchObject({ categorySlug: 'coins', year: 1918 });56    expect(sov.attributes.identifiers.noble_lot).toBe('458100');57  });5859  it('fixtures: 2026 and 1994 sales normalise to AUD hammer prices', async () => {60    for (const name of ['sale-142-prices-realised', 'sale-44-prices-realised-1994']) {61      const out = await connector.normalize(loadFixture('noble-numismatics', name).raw);62      expect(out.length).toBeGreaterThan(0);63      for (const r of out) if (r.kind === 'sale') expect(r).toMatchObject({ currency: 'AUD', buyerPremiumIncluded: false });64    }65    const old = await connector.normalize(loadFixture('noble-numismatics', 'sale-44-prices-realised-1994').raw);66    if (old[0]!.kind === 'sale') expect(old[0]!.saleDate.getUTCFullYear()).toBe(1994);67  });68});69