Sessions 5-7a: 955 tests, deployment ready

This commit is contained in:
Kev
2026-06-08 18:35:13 -04:00
parent 06b82624a2
commit 1fa04dc776
371 changed files with 49366 additions and 955 deletions
+106
View File
@@ -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);
});
});