deckhearth/test/lib/pricing/foolio-client.test.js
Randall Stillwell d0468015eb
Some checks failed
CI / Lint (pull_request) Has been cancelled
CI / Schema map up to date (pull_request) Has been cancelled
CI / Forbidden patterns (9 checks) (pull_request) Has been cancelled
CI / Migrations apply (node-pg-migrate) (pull_request) Has been cancelled
Visual diff / Should run? (pull_request) Has been cancelled
CI / Unit tests (vitest) (pull_request) Has been cancelled
Convoy metrics gate / Require role-event telemetry on convoy PRs (pull_request) Has been cancelled
PR Health rollup / Aggregate gate status (pull_request) Has been cancelled
Preview smoke / Should run? (pull_request) Has been cancelled
Preview smoke / Playwright smoke (pull_request) Has been cancelled
Visual diff / Screenshot diff (pull_request) Has been cancelled
feat(pricing): convoy for online prices and local stores
Add pricing schema, free API integrations (MTG bulk, TCGdex, Foolio),
valuation and sort-by-price, card detail pricing UI, and nearby store
discovery via home zip and OSM geo clients.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-08 22:47:46 -05:00

70 lines
1.9 KiB
JavaScript

import { beforeEach, describe, expect, it, vi } from 'vitest';
import {
buildFolioPriceIndex,
getFolioFeedUrl,
matchFolioPrice,
parseFolioPriceEntry,
} from '../../../lib/pricing/foolio-client.js';
describe('foolio-client', () => {
beforeEach(() => {
delete process.env.FOILIO_PRICES_FEED_URL;
vi.restoreAllMocks();
});
it('uses default Foilio feed URL', () => {
expect(getFolioFeedUrl()).toBe('https://foolio.net/api/prices/feed?game=lorcana');
});
it('prefers USD fields when parsing feed rows', () => {
expect(parseFolioPriceEntry({ usd_low: 1, usd_market: 2 })).toEqual({
currentPrice: 1,
marketPrice: 2,
currency: 'USD',
});
});
it('falls back to EUR with currency noted when USD is absent', () => {
expect(parseFolioPriceEntry({ eur_low: 0.5, eur_market: 0.8 })).toEqual({
currentPrice: 0.5,
marketPrice: 0.8,
currency: 'EUR',
});
});
it('indexes feed rows by card id and normalized name|set', () => {
const index = buildFolioPriceIndex([
{
card_id: 'TFC-001',
name: 'Ariel - On Human Legs',
set: 'TFC',
usd_low: 1,
usd_market: 1.5,
},
]);
expect(index.byCardId.get('TFC-001')?.marketPrice).toBe(1.5);
expect(
matchFolioPrice(index, {
scryfallId: 'OTHER',
name: 'Ariel - On Human Legs',
setCode: 'TFC',
})?.currentPrice
).toBe(1);
});
it('fetchFolioPriceFeed loads and indexes the feed once', async () => {
const payload = [{ card_id: 'TFC-001', usd_market: 3 }];
vi.stubGlobal('fetch', vi.fn(async () => ({
ok: true,
json: async () => payload,
})));
const { fetchFolioPriceIndex } = await import('../../../lib/pricing/foolio-client.js');
const index = await fetchFolioPriceIndex();
expect(index.byCardId.get('TFC-001')?.marketPrice).toBe(3);
expect(fetch).toHaveBeenCalledTimes(1);
});
});