Sessions 5-7a: 955 tests, deployment ready
This commit is contained in:
@@ -0,0 +1,106 @@
|
||||
const mockSnaps = { current: [] };
|
||||
jest.mock('../../src/utils/supabase', () => ({
|
||||
getSupabaseServiceClient: () => ({
|
||||
from() {
|
||||
const proxy = {
|
||||
select() { return proxy; },
|
||||
eq() { return proxy; },
|
||||
order() { return Promise.resolve({ data: mockSnaps.current, error: null }); },
|
||||
};
|
||||
return proxy;
|
||||
},
|
||||
}),
|
||||
}));
|
||||
|
||||
const lm = require('../../src/services/intelligence/lineMovement');
|
||||
|
||||
beforeEach(() => {
|
||||
mockSnaps.current = [];
|
||||
});
|
||||
|
||||
describe('getLineMovement', () => {
|
||||
test('returns null when fewer than two snapshots', async () => {
|
||||
mockSnaps.current = [{ line: 25.5, over_odds: -110, under_odds: -110, snapshot_at: 't1' }];
|
||||
expect(await lm.getLineMovement('g', 'P', 'points')).toBeNull();
|
||||
});
|
||||
|
||||
test('reports opening and current line correctly', async () => {
|
||||
mockSnaps.current = [
|
||||
{ line: 25.5, over_odds: -110, under_odds: -110, snapshot_at: 't1' },
|
||||
{ line: 25.5, over_odds: -120, under_odds: +100, snapshot_at: 't2' },
|
||||
{ line: 26.0, over_odds: -130, under_odds: +110, snapshot_at: 't3' },
|
||||
];
|
||||
const result = await lm.getLineMovement('g', 'P', 'points');
|
||||
expect(result).toMatchObject({
|
||||
opening_line: 25.5,
|
||||
current_line: 26.0,
|
||||
movement: 0.5,
|
||||
direction: 'up',
|
||||
snapshots_count: 3,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('reverseLineMovement', () => {
|
||||
test('detects RLM when public is on over but line moves to under', async () => {
|
||||
mockSnaps.current = [
|
||||
{ line: 25.5, over_odds: -110, under_odds: -110, snapshot_at: 't1' },
|
||||
{ line: 24.5, over_odds: -130, under_odds: +110, snapshot_at: 't2' },
|
||||
];
|
||||
const r = await lm.reverseLineMovement('g', 'P', 'points');
|
||||
expect(r.isReverse).toBe(true);
|
||||
expect(r.score).toBeGreaterThan(0);
|
||||
expect(r.publicSide).toBe('over');
|
||||
expect(r.lineDirection).toBe('under');
|
||||
});
|
||||
|
||||
test('returns isReverse=false when line moved with public', async () => {
|
||||
mockSnaps.current = [
|
||||
{ line: 25.5, over_odds: -110, under_odds: -110, snapshot_at: 't1' },
|
||||
{ line: 26.5, over_odds: -130, under_odds: +110, snapshot_at: 't2' },
|
||||
];
|
||||
const r = await lm.reverseLineMovement('g', 'P', 'points');
|
||||
expect(r.isReverse).toBe(false);
|
||||
expect(r.score).toBe(0);
|
||||
});
|
||||
|
||||
test('returns null on flat movement', async () => {
|
||||
mockSnaps.current = [
|
||||
{ line: 25.5, over_odds: -110, under_odds: -110, snapshot_at: 't1' },
|
||||
{ line: 25.5, over_odds: -115, under_odds: -105, snapshot_at: 't2' },
|
||||
];
|
||||
expect(await lm.reverseLineMovement('g', 'P', 'points')).toBeNull();
|
||||
});
|
||||
|
||||
test('uses provided publicBetPct over odds-direction heuristic', async () => {
|
||||
mockSnaps.current = [
|
||||
{ line: 25.5, over_odds: -110, under_odds: -110, snapshot_at: 't1' },
|
||||
{ line: 26.5, over_odds: -110, under_odds: -110, snapshot_at: 't2' },
|
||||
];
|
||||
const r = await lm.reverseLineMovement('g', 'P', 'points', 30);
|
||||
expect(r.isReverse).toBe(true);
|
||||
expect(r.publicSide).toBe('under');
|
||||
expect(r.lineDirection).toBe('over');
|
||||
});
|
||||
});
|
||||
|
||||
describe('juiceDegradation', () => {
|
||||
test('flags juice change when the line itself stayed put', async () => {
|
||||
mockSnaps.current = [
|
||||
{ line: 25.5, over_odds: -110, under_odds: -110, snapshot_at: 't1' },
|
||||
{ line: 25.5, over_odds: -130, under_odds: +110, snapshot_at: 't2' },
|
||||
];
|
||||
const r = await lm.juiceDegradation('g', 'P', 'points');
|
||||
expect(r.applicable).toBe(true);
|
||||
expect(r.score).toBeGreaterThan(0);
|
||||
});
|
||||
|
||||
test('not applicable when line moved significantly', async () => {
|
||||
mockSnaps.current = [
|
||||
{ line: 25.5, over_odds: -110, under_odds: -110, snapshot_at: 't1' },
|
||||
{ line: 28.5, over_odds: -120, under_odds: +100, snapshot_at: 't2' },
|
||||
];
|
||||
const r = await lm.juiceDegradation('g', 'P', 'points');
|
||||
expect(r.applicable).toBe(false);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user