116 lines
3.2 KiB
JavaScript
116 lines
3.2 KiB
JavaScript
|
|
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
||
|
|
|
||
|
|
vi.mock('../../../lib/sql.js', () => ({
|
||
|
|
sql: Object.assign(vi.fn(async () => ({ rows: [], rowCount: 0 })), {
|
||
|
|
query: vi.fn(async (text, values) => {
|
||
|
|
if (String(text).includes('SELECT id, scryfall_id')) {
|
||
|
|
const ids = values?.[0] ?? [];
|
||
|
|
return {
|
||
|
|
rows: ids.map((scryfallId, index) => ({ id: index + 1, scryfall_id: scryfallId })),
|
||
|
|
rowCount: ids.length,
|
||
|
|
};
|
||
|
|
}
|
||
|
|
return { rows: [], rowCount: 0 };
|
||
|
|
}),
|
||
|
|
}),
|
||
|
|
}));
|
||
|
|
|
||
|
|
vi.mock('../../../lib/pricing/price-history.js', () => ({
|
||
|
|
recordPriceSnapshots: vi.fn(async (rows) => rows.length),
|
||
|
|
}));
|
||
|
|
|
||
|
|
vi.mock('../../../lib/card-import/pokemon-github.js', () => ({
|
||
|
|
fetchPokemonSets: vi.fn(async () => [{ id: 'me3', name: 'Perfect Order', printedTotal: 88 }]),
|
||
|
|
fetchPokemonSetCards: vi.fn(async () => [
|
||
|
|
{
|
||
|
|
id: 'me3-18',
|
||
|
|
name: 'Seel',
|
||
|
|
supertype: 'Pokémon',
|
||
|
|
number: '18',
|
||
|
|
rarity: 'Common',
|
||
|
|
types: ['Water'],
|
||
|
|
},
|
||
|
|
]),
|
||
|
|
mapGithubCardForInsert: vi.fn((card, setMeta) => ({
|
||
|
|
externalId: card.id,
|
||
|
|
name: card.name,
|
||
|
|
setName: setMeta.name,
|
||
|
|
setCode: setMeta.id,
|
||
|
|
cardNumber: `${card.number}/${setMeta.printedTotal}`,
|
||
|
|
rarity: card.rarity,
|
||
|
|
cardType: card.supertype,
|
||
|
|
types: card.types,
|
||
|
|
flavorText: null,
|
||
|
|
hp: null,
|
||
|
|
imageSmall: null,
|
||
|
|
imageLarge: null,
|
||
|
|
})),
|
||
|
|
}));
|
||
|
|
|
||
|
|
import { sql } from '../../../lib/sql.js';
|
||
|
|
import { recordPriceSnapshots } from '../../../lib/pricing/price-history.js';
|
||
|
|
import {
|
||
|
|
mapPokemonBulkRow,
|
||
|
|
runBulkPokemonSync,
|
||
|
|
} from '../../../lib/card-import/pokemon-bulk.js';
|
||
|
|
|
||
|
|
describe('mapPokemonBulkRow', () => {
|
||
|
|
it('includes TCGdex prices and prices_updated_at when pricing is provided', () => {
|
||
|
|
const row = mapPokemonBulkRow(
|
||
|
|
{
|
||
|
|
externalId: 'me3-18',
|
||
|
|
name: 'Seel',
|
||
|
|
setName: 'Perfect Order',
|
||
|
|
setCode: 'me3',
|
||
|
|
cardNumber: '18/88',
|
||
|
|
rarity: 'Common',
|
||
|
|
cardType: 'Pokémon',
|
||
|
|
types: ['Water'],
|
||
|
|
flavorText: null,
|
||
|
|
hp: null,
|
||
|
|
imageSmall: null,
|
||
|
|
imageLarge: null,
|
||
|
|
},
|
||
|
|
{ unlimited: 'Legal' },
|
||
|
|
{ currentPrice: 0.1, marketPrice: 0.2, currency: 'USD' }
|
||
|
|
);
|
||
|
|
|
||
|
|
expect(row.currentPrice).toBe(0.1);
|
||
|
|
expect(row.marketPrice).toBe(0.2);
|
||
|
|
expect(row.pricesUpdatedAt).toBeInstanceOf(Date);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
describe('runBulkPokemonSync', () => {
|
||
|
|
beforeEach(() => {
|
||
|
|
vi.mocked(sql.query).mockClear();
|
||
|
|
vi.mocked(recordPriceSnapshots).mockClear();
|
||
|
|
});
|
||
|
|
|
||
|
|
it('enriches rows from TCGdex and reports match counts', async () => {
|
||
|
|
const fetchTcgdexSetCards = vi.fn(async () => [
|
||
|
|
{
|
||
|
|
id: 'me3-18',
|
||
|
|
localId: '18',
|
||
|
|
name: 'Seel',
|
||
|
|
set: { cardCount: { official: 88 } },
|
||
|
|
pricing: {
|
||
|
|
tcgplayer: { normal: { lowPrice: 0.1, marketPrice: 0.2 } },
|
||
|
|
},
|
||
|
|
},
|
||
|
|
]);
|
||
|
|
|
||
|
|
const summary = await runBulkPokemonSync({
|
||
|
|
fetchTcgdexSetCards,
|
||
|
|
query: sql.query,
|
||
|
|
setDelayMs: 0,
|
||
|
|
});
|
||
|
|
|
||
|
|
expect(summary.pricesMatched).toBe(1);
|
||
|
|
expect(summary.unmatchedCount).toBe(0);
|
||
|
|
expect(summary.snapshotsWritten).toBeGreaterThan(0);
|
||
|
|
expect(recordPriceSnapshots).toHaveBeenCalled();
|
||
|
|
expect(sql.query).toHaveBeenCalled();
|
||
|
|
});
|
||
|
|
});
|