deckhearth/test/lib/card-import-sync-catalog.test.js

84 lines
2.6 KiB
JavaScript
Raw Normal View History

import { describe, expect, it, vi, beforeEach } from 'vitest';
import { buildCatalogSyncQueue, runUnifiedCatalogSync } from '../../lib/card-import/sync-catalog.js';
import { runBulkMtgSync } from '../../lib/card-import/bulk-sync.js';
import { runBulkPokemonSync } from '../../lib/card-import/pokemon-bulk.js';
import { runBulkLorcanaSync } from '../../lib/card-import/lorcana-bulk.js';
vi.mock('../../lib/card-import/bulk-sync.js', () => ({
runBulkMtgSync: vi.fn(),
}));
vi.mock('../../lib/card-import/pokemon-bulk.js', () => ({
runBulkPokemonSync: vi.fn(),
}));
vi.mock('../../lib/card-import/lorcana-bulk.js', () => ({
runBulkLorcanaSync: vi.fn(),
}));
vi.mock('@vercel/postgres', () => ({
sql: vi.fn(() => Promise.resolve({ rows: [] })),
}));
describe('buildCatalogSyncQueue', () => {
it('merges MTG and Pokémon missing sets by release date, newest first', () => {
const queue = buildCatalogSyncQueue(
[
{ code: 'fin', name: 'Final Fantasy', releasedAt: '2026-05-01' },
{ code: 'dsk', name: 'Duskmourn', releasedAt: '2024-09-27' },
],
[
{ id: 'sv10', name: 'Perfect Order', releasedAt: '2026-03-27' },
{ id: 'sv9', name: 'Journey Together', releasedAt: '2025-03-28' },
],
3
);
expect(queue).toEqual([
{
game: 'mtg',
setCode: 'fin',
name: 'Final Fantasy',
releasedAt: '2026-05-01',
},
{
game: 'pokemon',
setCode: 'sv10',
name: 'Perfect Order',
releasedAt: '2026-03-27',
},
{
game: 'pokemon',
setCode: 'sv9',
name: 'Journey Together',
releasedAt: '2025-03-28',
},
]);
});
});
describe('runUnifiedCatalogSync', () => {
beforeEach(() => {
vi.clearAllMocks();
});
it('runs all three games and isolates per-game failures', async () => {
runBulkMtgSync.mockResolvedValue({ mode: 'bulk', upserted: 36000, errors: 0 });
runBulkPokemonSync.mockRejectedValue(new Error('Pokemon API down'));
runBulkLorcanaSync.mockResolvedValue({ mode: 'bulk', upserted: 2283, errors: 0 });
const summary = await runUnifiedCatalogSync();
expect(summary.mode).toBe('unified');
expect(summary.mtg.upserted).toBe(36000);
expect(summary.pokemon.error).toBe('Pokemon API down');
expect(summary.lorcana.upserted).toBe(2283);
expect(summary.errors).toEqual([{ game: 'pokemon', message: 'Pokemon API down' }]);
expect(summary.durationMs).toBeGreaterThanOrEqual(0);
expect(runBulkMtgSync).toHaveBeenCalledOnce();
expect(runBulkPokemonSync).toHaveBeenCalledOnce();
expect(runBulkLorcanaSync).toHaveBeenCalledOnce();
});
});