deckhearth/test/lib/card-import/lorcana-bulk.test.js
Randall Stillwell c6cc637f8a
Some checks are pending
CI / Lint (push) Waiting to run
CI / Schema map up to date (push) Waiting to run
CI / Forbidden patterns (9 checks) (push) Waiting to run
CI / Migrations apply (node-pg-migrate) (push) Waiting to run
CI / Unit tests (vitest) (push) Waiting to run
fix(pricing): test fixes and post-merge tooling
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-09 11:51:08 -05:00

117 lines
3.3 KiB
JavaScript

import { beforeEach, describe, expect, it, vi } from 'vitest';
vi.mock('../../../lib/pricing/price-history.js', () => ({
recordPriceSnapshots: vi.fn(async (rows) => rows.length),
}));
import { recordPriceSnapshots } from '../../../lib/pricing/price-history.js';
import {
enrichLorcanaRowWithFolio,
mapLorcanaCard,
runBulkLorcanaSync,
} from '../../../lib/card-import/lorcana-bulk.js';
import { buildFolioPriceIndex } from '../../../lib/pricing/foolio-client.js';
describe('mapLorcanaCard pricing', () => {
it('includes price fields when Foilio pricing is provided', () => {
const mapped = mapLorcanaCard(
{
Unique_ID: 'TFC-001',
Name: 'Ariel - On Human Legs',
Set_Name: 'The First Chapter',
Set_ID: 'TFC',
Card_Num: 1,
},
{ currentPrice: 1.25, marketPrice: 1.5, currency: 'USD' }
);
expect(mapped.currentPrice).toBe(1.25);
expect(mapped.marketPrice).toBe(1.5);
expect(mapped.pricesUpdatedAt).toBeInstanceOf(Date);
});
});
describe('enrichLorcanaRowWithFolio', () => {
it('matches by card id and tracks matched/unmatched counts', () => {
const index = buildFolioPriceIndex([
{ card_id: 'TFC-001', usd_low: 1, usd_market: 2 },
]);
const stats = { pricesMatched: 0, unmatchedCount: 0 };
const enriched = enrichLorcanaRowWithFolio(
mapLorcanaCard({
Unique_ID: 'TFC-001',
Name: 'Ariel - On Human Legs',
Set_ID: 'TFC',
}),
index,
stats
);
expect(enriched.currentPrice).toBe(1);
expect(enriched.marketPrice).toBe(2);
expect(stats.pricesMatched).toBe(1);
expect(stats.unmatchedCount).toBe(0);
});
it('increments unmatchedCount when no feed row matches', () => {
const stats = { pricesMatched: 0, unmatchedCount: 0 };
const enriched = enrichLorcanaRowWithFolio(
mapLorcanaCard({
Unique_ID: 'TFC-999',
Name: 'Unknown',
Set_ID: 'TFC',
}),
buildFolioPriceIndex([]),
stats
);
expect(enriched.currentPrice ?? null).toBeNull();
expect(stats.unmatchedCount).toBe(1);
});
});
describe('runBulkLorcanaSync', () => {
beforeEach(() => {
vi.mocked(recordPriceSnapshots).mockClear();
vi.restoreAllMocks();
});
it('fetches Foilio feed once and reports price match summary', async () => {
const fetchFolioIndex = vi.fn(async () => buildFolioPriceIndex([
{ card_id: 'TFC-001', usd_low: 0.5, usd_market: 0.75 },
]));
vi.stubGlobal('fetch', vi.fn(async () => ({
ok: true,
json: async () => ([
{
Unique_ID: 'TFC-001',
Name: 'Ariel - On Human Legs',
Set_Name: 'The First Chapter',
Set_ID: 'TFC',
Card_Num: 1,
Gamemode: 'Lorcana',
},
]),
})));
const query = vi.fn(async (text, values) => {
if (String(text).includes('SELECT id, scryfall_id')) {
return { rows: [{ id: 1, scryfall_id: 'TFC-001' }], rowCount: 1 };
}
return { rows: [], rowCount: 0 };
});
const summary = await runBulkLorcanaSync({
sql: { query },
fetchFolioIndex,
});
expect(fetchFolioIndex).toHaveBeenCalledTimes(1);
expect(summary.pricesMatched).toBe(1);
expect(summary.unmatchedCount).toBe(0);
expect(summary.upserted).toBe(1);
expect(recordPriceSnapshots).toHaveBeenCalled();
});
});