profileShare

rasmusjy / roundtable

Read-only snapshot

No repository description.

main default branch 181 files Expires Sep 13, 2026, 9:06 AM

Commit

test demo fixture expansion

commit c0ee0c9

1 changed file with +62 and −0

added src/lib/demo-fixtures.test.ts +62 −0
@@ -0,0 +1,62 @@
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 +});