import { describe, it, expect } from 'vitest' import { mockResponse } from './mock.js' import { pickChallenge } from './challenges.js' describe('mockResponse', () => { it('returns a valid response structure', () => { const challenge = pickChallenge(new Set(), null) const resp = mockResponse(challenge, 'confident', 1500) expect(resp).toHaveProperty('answer') expect(resp).toHaveProperty('trashTalk') expect(resp).toHaveProperty('timeMs') expect(resp).toHaveProperty('timedOut') expect(resp).toHaveProperty('error') expect(typeof resp.timeMs).toBe('number') expect(typeof resp.timedOut).toBe('boolean') expect(typeof resp.error).toBe('boolean') }) it('high ELO bots answer correctly more often (factual)', () => { let highCorrect = 0 let lowCorrect = 0 const runs = 200 for (let i = 0; i < runs; i++) { const challenge = pickChallenge(new Set(), null) if (challenge.scoring !== 'factual' || !challenge.answers?.length) continue const highResp = mockResponse(challenge, 'confident', 1900) const lowResp = mockResponse(challenge, 'clueless', 900) if (!highResp.timedOut && !highResp.error && challenge.answers.includes(highResp.answer)) highCorrect++ if (!lowResp.timedOut && !lowResp.error && challenge.answers.includes(lowResp.answer)) lowCorrect++ } // High ELO should answer correctly more often expect(highCorrect).toBeGreaterThan(lowCorrect) }) it('low ELO bots time out / error more often', () => { let highFails = 0 let lowFails = 0 const runs = 500 for (let i = 0; i < runs; i++) { const challenge = pickChallenge(new Set(), null) const highResp = mockResponse(challenge, 'confident', 1900) const lowResp = mockResponse(challenge, 'clueless', 900) if (highResp.timedOut || highResp.error) highFails++ if (lowResp.timedOut || lowResp.error) lowFails++ } expect(lowFails).toBeGreaterThan(highFails) }) it('high ELO bots respond faster on average', () => { let highTotal = 0 let lowTotal = 0 let highCount = 0 let lowCount = 0 const runs = 200 for (let i = 0; i < runs; i++) { const challenge = pickChallenge(new Set(), null) const highResp = mockResponse(challenge, 'confident', 1900) const lowResp = mockResponse(challenge, 'clueless', 900) if (!highResp.timedOut && !highResp.error) { highTotal += highResp.timeMs; highCount++ } if (!lowResp.timedOut && !lowResp.error) { lowTotal += lowResp.timeMs; lowCount++ } } const highAvg = highTotal / Math.max(highCount, 1) const lowAvg = lowTotal / Math.max(lowCount, 1) expect(highAvg).toBeLessThan(lowAvg) }) it('creative challenges return non-empty answers', () => { for (let i = 0; i < 50; i++) { const challenge = pickChallenge(new Set(), null) if (challenge.scoring !== 'creative') continue const resp = mockResponse(challenge, 'witty', 1500) if (!resp.timedOut && !resp.error) { expect(resp.answer.length).toBeGreaterThan(0) } } }) it('trash talk is always a string', () => { for (let i = 0; i < 20; i++) { const challenge = pickChallenge(new Set(), null) const resp = mockResponse(challenge, 'confident', 1900) expect(typeof resp.trashTalk).toBe('string') } }) it('timeMs is always positive', () => { for (let i = 0; i < 50; i++) { const challenge = pickChallenge(new Set(), null) const resp = mockResponse(challenge, 'confident', 1500) expect(resp.timeMs).toBeGreaterThan(0) } }) })