test: add 10,000 fight crash test and all-16-types scoring verification

Two new regression tests:
- 10,000 fights with varied elos, personalities, and round counts (50k+ rounds) — zero crashes
- All 16 challenge types tested with 5 response scenarios each (normal, timeout, error, double-timeout, arena+combo)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Dorian
2026-03-09 08:53:19 +00:00
co-authored by Claude Opus 4.6
parent 9de14492c5
commit 17a9fca4b5
+125
View File
@@ -295,6 +295,131 @@ describe('fight lifecycle', () => {
}
})
it('10,000 automated fight simulations — zero crashes', () => {
const personalities = ['confident', 'clueless', 'witty', 'aggressive', 'zen']
const elos = [900, 1000, 1200, 1400, 1600, 1800, 2000]
let totalRounds = 0
for (let f = 0; f < 10000; f++) {
const eloA = elos[f % elos.length]
const eloB = elos[(f * 3 + 1) % elos.length]
const persA = personalities[f % personalities.length]
const persB = personalities[(f + 2) % personalities.length]
const rounds = 3 + (f % 8) // 3 to 10 rounds
const botA = { id: 'sim-a', name: 'SimA' }
const botB = { id: 'sim-b', name: 'SimB' }
const usedTypes = new Set<string>()
let comboA = 0
let comboB = 0
for (let r = 0; r < rounds; r++) {
const challenge = pickChallenge(usedTypes, null, undefined, r + 1)
usedTypes.add(challenge.type)
const respA = mockResponse(challenge, persA, eloA)
const respB = mockResponse(challenge, persB, eloB)
const result = scoreRound(
challenge, botA, botB,
{ answer: respA.answer, timeMs: respA.timeMs, timedOut: respA.timedOut, error: respA.error },
{ answer: respB.answer, timeMs: respB.timeMs, timedOut: respB.timedOut, error: respB.error },
null, comboA, comboB,
)
// Verify result integrity
expect(result.botAScore).toBeGreaterThanOrEqual(0)
expect(result.botBScore).toBeGreaterThanOrEqual(0)
expect(result.botADamage).toBeGreaterThanOrEqual(0)
expect(result.botBDamage).toBeGreaterThanOrEqual(0)
expect(typeof result.narration).toBe('string')
expect(result.narration.length).toBeGreaterThan(0)
expect(Number.isFinite(result.botAScore)).toBe(true)
expect(Number.isFinite(result.botBScore)).toBe(true)
if (result.winnerId === botA.id) { comboA++; comboB = 0 }
else if (result.winnerId === botB.id) { comboB++; comboA = 0 }
totalRounds++
}
}
// Verify we actually ran a substantial number of rounds
expect(totalRounds).toBeGreaterThan(50000)
})
it('all 16 challenge types score correctly', () => {
const allTypes = getAllChallengeTypes()
expect(allTypes.length).toBe(16)
const botA = { id: 'type-a', name: 'TypeTestA' }
const botB = { id: 'type-b', name: 'TypeTestB' }
for (const type of allTypes) {
// Pick a challenge of this specific type
const usedTypes = new Set(allTypes.filter(t => t !== type))
const challenge = pickChallenge(usedTypes, null)
expect(challenge.type).toBe(type)
// Test all response scenarios for this type:
// 1. Both answer correctly/well
const respA1 = mockResponse(challenge, 'confident', 1800)
const respB1 = mockResponse(challenge, 'confident', 1800)
const r1 = scoreRound(
challenge, botA, botB,
{ answer: respA1.answer, timeMs: 200, timedOut: false, error: false },
{ answer: respB1.answer, timeMs: 300, timedOut: false, error: false },
null, 0, 0,
)
expect(r1.botAScore).toBeGreaterThanOrEqual(0)
expect(r1.botBScore).toBeGreaterThanOrEqual(0)
expect(typeof r1.narration).toBe('string')
// 2. A times out
const r2 = scoreRound(
challenge, botA, botB,
{ answer: '', timeMs: 8000, timedOut: true, error: false },
{ answer: respB1.answer, timeMs: 300, timedOut: false, error: false },
null, 0, 0,
)
expect(r2.winnerId).toBe(botB.id)
expect(r2.botAScore).toBe(0)
// 3. B errors
const r3 = scoreRound(
challenge, botA, botB,
{ answer: respA1.answer, timeMs: 200, timedOut: false, error: false },
{ answer: '', timeMs: 0, timedOut: false, error: true },
null, 0, 0,
)
expect(r3.winnerId).toBe(botA.id)
expect(r3.botBScore).toBe(0)
// 4. Both timeout
const r4 = scoreRound(
challenge, botA, botB,
{ answer: '', timeMs: 8000, timedOut: true, error: false },
{ answer: '', timeMs: 8000, timedOut: true, error: false },
null, 0, 0,
)
expect(r4.winnerId).toBeNull()
expect(r4.botADamage).toBe(0)
expect(r4.botBDamage).toBe(0)
// 5. With arena modifier and combo
const r5 = scoreRound(
challenge, botA, botB,
{ answer: respA1.answer, timeMs: 200, timedOut: false, error: false },
{ answer: respB1.answer, timeMs: 500, timedOut: false, error: false },
'speed_2x', 3, 0,
)
expect(r5.botAScore).toBeGreaterThanOrEqual(0)
expect(Number.isFinite(r5.botADamage)).toBe(true)
expect(Number.isFinite(r5.botBDamage)).toBe(true)
}
})
it('Elo difference correlates with win rate', () => {
const scenarios = [
{ eloA: 1400, eloB: 1400, expectedAWinMin: 0.40, expectedAWinMax: 0.60 },