TypeScript 61.9%
HTML 37.2%
SQL 0.7%
1import { describe, expect, it } from 'vitest';2import metaJson from './meta.json' with { type: 'json' };3import { loadFixture, runFixtureSuite } from '@rareindex/connectors/testing';4import { missingRequirements } from '@rareindex/connectors';5import { localMeta } from '../_lib/local-meta.js';6import createConnector, { parseSearchResponse, priceOf, resolveTaxonomyPath, searchUrl } from './index.js';78const meta = localMeta(metaJson);9const connector = createConnector(meta);1011describe('etsy (gated)', () => {12 runFixtureSuite(connector, it, expect);1314 it('is gated on ETSY_API_KEY', () => {15 expect(meta.requires).toEqual(['ETSY_API_KEY']);16 expect(missingRequirements(meta, {})).toEqual(['ETSY_API_KEY']);17 expect(missingRequirements(meta, { ETSY_API_KEY: 'k' })).toEqual([]);18 });1920 it('builds findAllListingsActive URLs and resolves taxonomy paths', () => {21 const url = new URL(searchUrl({ keywords: 'vintage fountain pen', categorySlug: 'pens', minPrice: 50 }, { limit: 100, offset: 200, sortOn: 'created', sortOrder: 'desc' }, 1234));22 expect(url.origin + url.pathname).toBe('https://openapi.etsy.com/v3/application/listings/active');23 expect(url.searchParams.get('keywords')).toBe('vintage fountain pen');24 expect(url.searchParams.get('taxonomy_id')).toBe('1234');25 expect(url.searchParams.get('min_price')).toBe('50');26 expect(url.searchParams.get('limit')).toBe('100');27 expect(url.searchParams.get('offset')).toBe('200');28 const tree = { count: 1, results: [{ id: 1, name: 'Toys & Games', children: [{ id: 10, name: 'Games & Puzzles', children: [{ id: 100, name: 'Card Games', children: [] }] }] }] };29 expect(resolveTaxonomyPath(tree, ['Toys & Games', 'Games & Puzzles', 'Card Games'])).toBe(100);30 expect(resolveTaxonomyPath(tree, ['toys & games'])).toBe(1);31 expect(resolveTaxonomyPath(tree, ['Nope'])).toBeNull();32 });3334 it('parses Money prices (amount/divisor) and normalises native-currency listings', async () => {35 expect(priceOf({ amount: 12999, divisor: 100, currency_code: 'USD' })).toBe(129.99);36 expect(priceOf({ amount: 0, divisor: 100, currency_code: 'USD' })).toBeNull();37 const fx = loadFixture('etsy', 'docs-listings-active');38 const payload = fx.raw.payload as { listings: unknown[] };39 const parsed = parseSearchResponse({ count: 3, results: payload.listings });40 expect(parsed?.listings.length).toBe(payload.listings.length);41 expect(parseSearchResponse({ error: 'Invalid API key' })).toBeNull();42 const out = await connector.normalize(fx.raw);43 // one made_to_order listing is skipped44 expect(out.length).toBe(payload.listings.length - 1);45 const first = out[0]!;46 if (first.kind !== 'listing') throw new Error('expected listing');47 expect(first.currency).toBe('USD');48 expect(first.price).toBe(129.99);49 expect(first.attributes.identifiers.etsy_listing_id).toMatch(/^\d+$/);50 expect(first.imageUrls[0]).toMatch(/etsystatic/);51 expect(first.seller).toBeTruthy();52 expect(first.listedAt?.getUTCFullYear()).toBe(2026);53 const gbp = out.find((r) => r.kind === 'listing' && r.currency === 'GBP');54 expect(gbp).toBeTruthy();55 });56});57