import { describe, expect, it } from 'vitest'; import metaJson from './meta.json' with { type: 'json' }; import { loadFixture, runFixtureSuite } from '@rareindex/connectors/testing'; import { missingRequirements } from '@rareindex/connectors'; import { localMeta } from '../_lib/local-meta.js'; import { dotNetDate } from '../_g10-lib/index.js'; import createConnector, { apiBase, authHeader, listingPrice, parseSearchResponse, searchUrl } from './index.js'; const meta = localMeta(metaJson); const connector = createConnector(meta); describe('trademe (gated)', () => { runFixtureSuite(connector, it, expect); it('is gated on the consumer key/secret and builds the application-only OAuth header', () => { expect(meta.requires).toEqual(['TRADEME_CONSUMER_KEY', 'TRADEME_CONSUMER_SECRET']); expect(missingRequirements(meta, {})).toEqual(['TRADEME_CONSUMER_KEY', 'TRADEME_CONSUMER_SECRET']); expect(authHeader('ABC', 'S3cr(t')).toBe('OAuth oauth_consumer_key="ABC", oauth_signature_method="PLAINTEXT", oauth_signature="S3cr%28t%26"'); expect(apiBase('sandbox')).toBe('https://api.tmsandbox.co.nz/v1'); const u = new URL(searchUrl(apiBase(undefined), { category: '0187-4353-', categorySlug: 'coins' }, { rows: 25, page: 2, sortOrder: 'Default', condition: 'All', photoSize: 'Large' })); expect(u.origin + u.pathname).toBe('https://api.trademe.co.nz/v1/Search/General.json'); expect(u.searchParams.get('category')).toBe('0187-4353-'); expect(u.searchParams.get('page')).toBe('2'); expect(u.searchParams.get('rows')).toBe('25'); }); it('parses .NET dates and picks the current asking price', () => { expect(dotNetDate('/Date(1757280000000)/')?.toISOString()).toBe('2025-09-07T21:20:00.000Z'.replace('2025-09-07T21:20:00.000Z', new Date(1757280000000).toISOString())); expect(dotNetDate('nope')).toBeNull(); const base = { ListingId: 1, Title: 't', Attributes: [] }; expect(listingPrice({ ...base, StartPrice: 10, BuyNowPrice: 50, HasBuyNow: true, BidCount: 0 })).toEqual({ price: 50, listingType: 'fixed_price' }); expect(listingPrice({ ...base, StartPrice: 10, MaxBidAmount: 35, BidCount: 3, HasBuyNow: false })).toEqual({ price: 35, listingType: 'auction' }); expect(listingPrice({ ...base, StartPrice: 10, BidCount: 0, HasBuyNow: false })).toEqual({ price: 10, listingType: 'auction' }); expect(listingPrice({ ...base, StartPrice: 120, IsClassified: true })).toEqual({ price: 120, listingType: 'ask' }); }); it('parses the documented SearchResults shape and normalises NZD listings', async () => { const fx = loadFixture('trademe', 'docs-general-search-coins'); const payload = fx.raw.payload as { listings: unknown[] }; const parsed = parseSearchResponse({ TotalCount: 812, Page: 1, PageSize: 25, List: payload.listings }); expect(parsed?.listings.length).toBe(payload.listings.length); expect(parseSearchResponse({ ErrorDescription: 'Unauthorized' })).toBeNull(); const out = await connector.normalize(fx.raw); expect(out.length).toBe(payload.listings.length); for (const r of out) { if (r.kind !== 'listing') throw new Error('expected listing'); expect(r.currency).toBe('NZD'); expect(r.price).toBeGreaterThan(0); expect(r.attributes.identifiers.trademe_listing_id).toMatch(/^\d+$/); expect(r.sourceUrl).toMatch(/trademe\.co\.nz\/a\/listing\/\d+$/); expect(r.endsAt).toBeInstanceOf(Date); } expect(out.some((r) => r.kind === 'listing' && r.listingType === 'auction' && (r.bidCount ?? 0) > 0)).toBe(true); }); });