demo-fixtures.test.ts
2,589 bytes
| 1 | import { describe, expect, it } from 'vitest'; |
|---|---|
| 2 | import { buildDebateResult, FIXTURES, resultToStageEvents } from './demo-fixtures'; |
| 3 | |
| 4 | describe('demo fixtures', () => { |
| 5 | it('ships at least two hand-authored debates', () => { |
| 6 | expect(FIXTURES.length).toBeGreaterThanOrEqual(2); |
| 7 | }); |
| 8 | |
| 9 | for (const spec of FIXTURES) { |
| 10 | describe(spec.question.slice(0, 40), () => { |
| 11 | const result = buildDebateResult(spec); |
| 12 | |
| 13 | it('has one distinct initial answer per model', () => { |
| 14 | expect(result.initialAnswers).toHaveLength(spec.models.length); |
| 15 | const unique = new Set(result.initialAnswers.map((a) => a.content)); |
| 16 | expect(unique.size).toBe(result.initialAnswers.length); |
| 17 | }); |
| 18 | |
| 19 | it('produces a synthesis and non-zero cost attributed per model', () => { |
| 20 | expect(result.synthesis).not.toBeNull(); |
| 21 | expect(result.synthesis!.finalAnswer.length).toBeGreaterThan(20); |
| 22 | expect(result.totals.costUsd).toBeGreaterThan(0); |
| 23 | expect(Object.keys(result.totals.costByModel).length).toBeGreaterThanOrEqual(spec.models.length); |
| 24 | }); |
| 25 | |
| 26 | it('marks convergence.converged consistently with the threshold', () => { |
| 27 | const threshold = spec.convergenceThreshold ?? 85; |
| 28 | for (const round of result.rounds) { |
| 29 | expect(round.convergence!.converged).toBe(round.convergence!.score >= threshold); |
| 30 | } |
| 31 | }); |
| 32 | |
| 33 | it('final answers reflect the last revision content', () => { |
| 34 | const lastRound = result.rounds.at(-1)!; |
| 35 | for (const rev of lastRound.revisions) { |
| 36 | const final = result.finalAnswers.find((a) => a.participantId === rev.participantId); |
| 37 | expect(final?.content).toBe(rev.content); |
| 38 | } |
| 39 | }); |
| 40 | |
| 41 | it('critique reviews resolve to real, non-self participants', () => { |
| 42 | const ids = new Set(result.participants.map((p) => p.id)); |
| 43 | for (const round of result.rounds) { |
| 44 | for (const c of round.critiques) { |
| 45 | for (const r of c.reviews) { |
| 46 | expect(ids.has(r.targetParticipantId)).toBe(true); |
| 47 | expect(r.targetParticipantId).not.toBe(c.reviewerParticipantId); |
| 48 | } |
| 49 | } |
| 50 | } |
| 51 | }); |
| 52 | |
| 53 | it('serializes to the expected durable events', () => { |
| 54 | const events = resultToStageEvents(result); |
| 55 | const count = (t: string) => events.filter((e) => e.type === t).length; |
| 56 | expect(count('answer_completed')).toBe(spec.models.length); |
| 57 | expect(count('synthesis_completed')).toBe(1); |
| 58 | expect(count('convergence_result')).toBe(result.rounds.length); |
| 59 | }); |
| 60 | }); |
| 61 | } |
| 62 | }); |
| 63 | |