重构
This commit is contained in:
137
apps/api/src/domains/odds/markets.service.spec.ts
Normal file
137
apps/api/src/domains/odds/markets.service.spec.ts
Normal file
@@ -0,0 +1,137 @@
|
||||
import { MarketsService } from './markets.service';
|
||||
|
||||
function selection(selectionCode: string, odds = 1.9) {
|
||||
return {
|
||||
selectionCode,
|
||||
selectionName: selectionCode,
|
||||
odds,
|
||||
status: 'OPEN',
|
||||
};
|
||||
}
|
||||
|
||||
function errorCode(error: unknown) {
|
||||
const response = (error as { getResponse?: () => unknown }).getResponse?.();
|
||||
return (response as { code?: string } | undefined)?.code;
|
||||
}
|
||||
|
||||
function createPrismaMock() {
|
||||
let marketId = 100n;
|
||||
let selectionId = 1000n;
|
||||
return {
|
||||
match: {
|
||||
findUnique: jest.fn().mockResolvedValue({ id: 1n }),
|
||||
},
|
||||
market: {
|
||||
findFirst: jest.fn().mockResolvedValue(null),
|
||||
create: jest.fn().mockImplementation(async ({ data }) => ({ id: marketId++, ...data })),
|
||||
update: jest.fn().mockImplementation(async ({ where, data }) => ({ id: where.id, ...data })),
|
||||
findUnique: jest.fn().mockImplementation(async ({ where }) => ({ id: where.id, selections: [] })),
|
||||
findMany: jest.fn().mockResolvedValue([]),
|
||||
updateMany: jest.fn().mockResolvedValue({ count: 0 }),
|
||||
},
|
||||
marketSelection: {
|
||||
findMany: jest.fn().mockResolvedValue([]),
|
||||
create: jest.fn().mockImplementation(async ({ data }) => ({ id: selectionId++, ...data })),
|
||||
update: jest.fn(),
|
||||
updateMany: jest.fn().mockResolvedValue({ count: 0 }),
|
||||
},
|
||||
oddsChangeLog: {
|
||||
create: jest.fn(),
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
describe('MarketsService line value rules', () => {
|
||||
it('exposes usesLineValue in market definitions', () => {
|
||||
const service = new MarketsService(createPrismaMock() as never);
|
||||
|
||||
const definitions = service.listMarketDefinitions();
|
||||
|
||||
expect(definitions.find((d) => d.marketType === 'FT_HANDICAP')?.usesLineValue).toBe(true);
|
||||
expect(definitions.find((d) => d.marketType === 'FT_1X2')?.usesLineValue).toBe(false);
|
||||
});
|
||||
|
||||
it('rejects line markets without a numeric line value', async () => {
|
||||
const service = new MarketsService(createPrismaMock() as never);
|
||||
|
||||
let caughtCode: string | undefined;
|
||||
try {
|
||||
await service.saveMatchMarkets(1n, [
|
||||
{
|
||||
marketType: 'FT_HANDICAP',
|
||||
lineValue: null,
|
||||
selections: [selection('HOME'), selection('AWAY')],
|
||||
},
|
||||
]);
|
||||
} catch (error) {
|
||||
caughtCode = errorCode(error);
|
||||
}
|
||||
expect(caughtCode).toBe('MARKET_LINE_REQUIRED');
|
||||
});
|
||||
|
||||
it('rejects non-line markets with a line value', async () => {
|
||||
const service = new MarketsService(createPrismaMock() as never);
|
||||
|
||||
let caughtCode: string | undefined;
|
||||
try {
|
||||
await service.saveMatchMarkets(1n, [
|
||||
{
|
||||
marketType: 'FT_1X2',
|
||||
lineValue: 1,
|
||||
selections: [selection('HOME'), selection('DRAW'), selection('AWAY')],
|
||||
},
|
||||
]);
|
||||
} catch (error) {
|
||||
caughtCode = errorCode(error);
|
||||
}
|
||||
expect(caughtCode).toBe('MARKET_LINE_NOT_ALLOWED');
|
||||
});
|
||||
|
||||
it('allows non-line markets with null line value', async () => {
|
||||
const prisma = createPrismaMock();
|
||||
const service = new MarketsService(prisma as never);
|
||||
|
||||
const result = await service.saveMatchMarkets(1n, [
|
||||
{
|
||||
marketType: 'FT_1X2',
|
||||
lineValue: null,
|
||||
selections: [selection('HOME'), selection('DRAW'), selection('AWAY')],
|
||||
},
|
||||
]);
|
||||
|
||||
expect(result).toEqual({ updated: 1, closed: 0 });
|
||||
expect(prisma.market.create).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
data: expect.objectContaining({
|
||||
marketType: 'FT_1X2',
|
||||
lineKey: 'FT_1X2:none',
|
||||
lineValue: null,
|
||||
}),
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
it('keeps distinct line keys for copied line markets', async () => {
|
||||
const prisma = createPrismaMock();
|
||||
const service = new MarketsService(prisma as never);
|
||||
|
||||
const result = await service.saveMatchMarkets(1n, [
|
||||
{
|
||||
marketType: 'FT_HANDICAP',
|
||||
lineValue: -0.5,
|
||||
selections: [selection('HOME'), selection('AWAY')],
|
||||
},
|
||||
{
|
||||
marketType: 'FT_HANDICAP',
|
||||
lineValue: -0.25,
|
||||
selections: [selection('HOME'), selection('AWAY')],
|
||||
},
|
||||
]);
|
||||
|
||||
expect(result).toEqual({ updated: 2, closed: 0 });
|
||||
expect(prisma.market.create.mock.calls.map(([arg]) => arg.data.lineKey)).toEqual([
|
||||
'FT_HANDICAP:-0.50',
|
||||
'FT_HANDICAP:-0.25',
|
||||
]);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user