60 lines
2.7 KiB
JavaScript
60 lines
2.7 KiB
JavaScript
// Unit: content formatter (Session 29).
|
|
|
|
const fmt = require('../../src/services/contentFormatter');
|
|
|
|
describe('contentFormatter — slate thread', () => {
|
|
test('formats each post role into readable text', () => {
|
|
const thread = {
|
|
posts: [
|
|
{ role: 'hook', text: '🔥 VYNDR SLATE' },
|
|
{ role: 'pick', player: 'Wemby', stat: 'points', side: 'over', line: 28.5, grade: 'A', confidence: 78, edge: 6.2, analysis: 'Edge on the line.' },
|
|
{ role: 'game_highlight', game: 'ARI @ CIN', time: null, bestHomeML: { odds: '-120', book: 'betmgm' }, total: 9.5, bookCount: 2 },
|
|
{ role: 'movers', movers: [{ player: 'X', stat: 'hits', opening: 1.5, current: 2.5, delta: 1, sharpSignal: false }] },
|
|
{ role: 'schedule', games: [{ away: 'ATL', home: 'NYM', time: null }] },
|
|
{ role: 'cta', text: 'Full slate at vyndr.app' },
|
|
],
|
|
};
|
|
const out = fmt.formatSlateThread(thread);
|
|
expect(out[0]).toBe('🔥 VYNDR SLATE');
|
|
expect(out[1]).toContain('Wemby · points over 28.5');
|
|
expect(out[1]).toContain('Grade: A · 78% confidence');
|
|
expect(out[1]).toContain('Edge: +6.2%');
|
|
expect(out[2]).toContain('ARI @ CIN');
|
|
expect(out[2]).toContain('betmgm');
|
|
expect(out[3]).toContain('Biggest line moves');
|
|
expect(out[4]).toContain('ATL @ NYM');
|
|
expect(out[5]).toBe('Full slate at vyndr.app');
|
|
});
|
|
|
|
test('never emits "undefined"', () => {
|
|
const out = fmt.formatSlateThread({ posts: [{ role: 'pick', player: 'X', stat: 'pts', grade: 'B' }] });
|
|
expect(out[0]).not.toMatch(/undefined/);
|
|
});
|
|
|
|
test('non-thread input → empty array', () => {
|
|
expect(fmt.formatSlateThread(null)).toEqual([]);
|
|
});
|
|
});
|
|
|
|
describe('contentFormatter — POTD + recap', () => {
|
|
test('POTD full', () => {
|
|
const t = fmt.formatPOTD({ dataLevel: 'full', player: 'Wemby', stat: 'points', side: 'over', line: 28.5, grade: 'A', confidence: 78 });
|
|
expect(t).toContain('PROP OF THE DAY');
|
|
expect(t).toContain('Wemby');
|
|
});
|
|
test('POTD game of the day', () => {
|
|
const t = fmt.formatPOTD({ dataLevel: 'lines', subtype: 'game_of_the_day', game: 'ARI @ CIN', total: 9.5 });
|
|
expect(t).toContain('GAME OF THE DAY');
|
|
expect(t).toContain('O/U 9.5');
|
|
});
|
|
test('POTD unavailable', () => {
|
|
expect(fmt.formatPOTD({ available: false })).toMatch(/vyndr\.app/);
|
|
});
|
|
test('recap formats record + win rate', () => {
|
|
const t = fmt.formatRecap({ available: true, date: 'Friday', record: { wins: 3, losses: 2, pushes: 1 }, winRate: 0.6, topHits: [{ player: 'A', stat: 'points', side: 'over', line: 20 }], metrics: { brierScore: 0.18 } });
|
|
expect(t).toContain('3-2-1 (60%)');
|
|
expect(t).toContain('✅ A points over 20');
|
|
expect(t).toContain('Brier: 0.18');
|
|
});
|
|
});
|