104 lines
3.8 KiB
JavaScript
104 lines
3.8 KiB
JavaScript
const mockAxiosGet = jest.fn();
|
|
jest.mock('axios', () => ({ get: (...args) => mockAxiosGet(...args) }));
|
|
|
|
const mockCache = { current: new Map() };
|
|
jest.mock('../../src/utils/redis', () => ({
|
|
cacheGet: async (k) => mockCache.current.get(k) ?? null,
|
|
cacheSet: async (k, v) => { mockCache.current.set(k, v); return true; },
|
|
cacheDel: async (k) => { mockCache.current.delete(k); return true; },
|
|
}));
|
|
|
|
jest.mock('../../src/utils/rateLimiter', () => ({
|
|
createLimiter: () => ({ waitForToken: async () => true, snapshot: () => ({}) }),
|
|
createCircuitBreaker: () => ({ call: async (fn) => fn(), snapshot: () => ({}) }),
|
|
}));
|
|
|
|
const injuries = require('../../src/services/intelligence/injuryParser');
|
|
|
|
beforeEach(() => {
|
|
mockAxiosGet.mockReset();
|
|
mockCache.current.clear();
|
|
});
|
|
|
|
describe('injuryParser.getTeamInjuries', () => {
|
|
test('normalizes ESPN injury payload', async () => {
|
|
mockAxiosGet.mockResolvedValue({
|
|
status: 200,
|
|
data: {
|
|
injuries: [
|
|
{ athlete: { id: 3934672, displayName: 'Jalen Brunson' }, status: 'Doubtful', details: { detail: 'Right ankle' } },
|
|
{ athlete: { id: 9999, displayName: 'OG Anunoby' }, status: 'Out' },
|
|
],
|
|
},
|
|
});
|
|
const out = await injuries.getTeamInjuries('nba', 18);
|
|
expect(out).toHaveLength(2);
|
|
expect(out[0]).toMatchObject({ playerId: '3934672', playerName: 'Jalen Brunson', status: 'DOUBTFUL', detail: 'Right ankle' });
|
|
expect(out[1].status).toBe('OUT');
|
|
});
|
|
|
|
test('404 is treated as no current injuries (empty list)', async () => {
|
|
mockAxiosGet.mockResolvedValue({ status: 404, data: {} });
|
|
const out = await injuries.getTeamInjuries('nba', 99);
|
|
expect(out).toEqual([]);
|
|
});
|
|
|
|
test('cache hit avoids second request', async () => {
|
|
mockAxiosGet.mockResolvedValue({ status: 200, data: { injuries: [] } });
|
|
await injuries.getTeamInjuries('nba', 5);
|
|
await injuries.getTeamInjuries('nba', 5);
|
|
expect(mockAxiosGet).toHaveBeenCalledTimes(1);
|
|
});
|
|
|
|
test('returns [] on unsupported sport (no path mapping)', async () => {
|
|
const out = await injuries.getTeamInjuries('curling', 1);
|
|
expect(out).toEqual([]);
|
|
});
|
|
});
|
|
|
|
describe('injuryParser.isPlayerOut + getMissingStarters', () => {
|
|
beforeEach(() => {
|
|
mockAxiosGet.mockResolvedValue({
|
|
status: 200,
|
|
data: {
|
|
injuries: [
|
|
{ athlete: { id: 1, displayName: 'A' }, status: 'OUT' },
|
|
{ athlete: { id: 2, displayName: 'B' }, status: 'PROBABLE' },
|
|
{ athlete: { id: 3, displayName: 'C' }, status: 'DOUBTFUL' },
|
|
],
|
|
},
|
|
});
|
|
});
|
|
|
|
test('isPlayerOut treats OUT and DOUBTFUL as out', async () => {
|
|
expect(await injuries.isPlayerOut('nba', 1, '1')).toBe(true);
|
|
expect(await injuries.isPlayerOut('nba', 1, '3')).toBe(true);
|
|
expect(await injuries.isPlayerOut('nba', 1, '2')).toBe(false);
|
|
expect(await injuries.isPlayerOut('nba', 1, '99')).toBe(false);
|
|
});
|
|
|
|
test('getMissingStarters intersects starter set with injured list', async () => {
|
|
const missing = await injuries.getMissingStarters('nba', 1, ['1', '2', '3', '4']);
|
|
expect(missing.map((m) => m.playerId).sort()).toEqual(['1', '3']);
|
|
});
|
|
});
|
|
|
|
describe('injuryParser.extractGameInjuries (from summary JSON)', () => {
|
|
test('reads injuries from competitions[0].competitors[]', async () => {
|
|
const summary = {
|
|
header: {
|
|
competitions: [{
|
|
competitors: [
|
|
{ homeAway: 'home', injuries: [{ athlete: { id: 1, displayName: 'H1' }, status: 'Out' }] },
|
|
{ homeAway: 'away', injuries: [{ athlete: { id: 2, displayName: 'A1' }, status: 'Probable' }] },
|
|
],
|
|
}],
|
|
},
|
|
};
|
|
const out = await injuries.getGameInjuries('nba', 'g1', summary);
|
|
expect(out.home).toHaveLength(1);
|
|
expect(out.home[0].status).toBe('OUT');
|
|
expect(out.away[0].status).toBe('PROBABLE');
|
|
});
|
|
});
|