Fork Horse repository, listed by its owner. Publisher snapshot.

packages/forkhorse-dashboard/test/races-fixtures.ts

Snapshot at 34e3175

Containing directory

3,158 bytes · typescriptView raw
1import type { Race, StateResponse } from "../src/contracts.ts";
2import { raceFixtureState } from "./race-fixtures.ts";
3
4export const racesScenarios = ["races-list", "races-empty"];
5
6/** Synthetic FH-081 read snapshots, including every requested list/capture state. */
7export function racesFixtureState(scenario = "races-list"): StateResponse {
8  const state: StateResponse = raceFixtureState("race-open");
9  state.project.id = scenario;
10  state.races = [];
11  state.packets = [];
12  state.claims = [];
13  state.reviews = [];
14  state.forks = [];
15  state.activity = [];
16  state.ledger = [];
17  if (scenario === "races-empty") return state;
18  const add = (id: string, title: string, source = "race-open", offset = 0) => {
19    const fixture = raceFixtureState(source);
20    const race: Race = structuredClone(fixture.races[0]);
21    race.packet = id;
22    const shift = (at: string | null | undefined) => at
23      ? new Date(Date.parse(at) + offset * 60_000).toISOString() : null;
24    race.finishedAt = shift(race.finishedAt);
25    for (const entrant of race.entrants) {
26      entrant.repoName = `${id}--${entrant.agent}`;
27      for (const key of ["claimedAt", "firstPushAt", "reviewRequestedAt", "receiptPassedAt", "approvedAt", "promotedAt", "closedAt"] as const) {
28        // The original claimedAt is always present in these fixed fixtures.
29        const at = shift(entrant[key]);
30        if (key === "claimedAt") entrant.claimedAt = at!;
31        else entrant[key] = at;
32      }
33    }
34    state.races!.push(race);
35    state.packets.push({ ...fixture.packets[0], id, title });
36    state.forks.push(...fixture.forks.map((fork) => ({ ...fork, repoName: `${id}--${fork.agent}` })));
37    state.claims.push(...race.entrants.filter((entrant) => !entrant.closedAt).map((entrant) => ({
38      packet: id, agent: entrant.agent, repoName: entrant.repoName,
39      paths: fixture.packets[0].paths, createdAt: entrant.claimedAt,
40    })));
41    return race;
42  };
43  add("race-three", "Bound retries for transient webhook failures", "race-open", 30);
44  const one = add("race-one", "Make delivery failures readable", "race-open", 40);
45  one.entrants = one.entrants.filter((entrant) => entrant.agent === "cedar");
46  state.claims = state.claims.filter((claim) => claim.packet !== one.packet || claim.agent === "cedar");
47  add("race-zero", "Prepare the next race", "race-empty");
48  add("race-winner", "Record delivery outcomes", "race-finished", 10);
49  const photo = add("race-photo", "Handle simultaneous approved changes", "race-photo", 20);
50  state.packets.find((packet) => packet.id === photo.packet)!.archived = {
51    at: "2026-10-13T15:00:00Z", by: "owner",
52  };
53  const judged = add("race-judged", "Compare bounded retry strategies", "race-open", 50);
54  judged.judge = "fixture-judge";
55  judged.verdict = { ranking: ["birch", "cedar", "amber"], rationale: "Fixture advice only.", at: "2026-10-13T15:10:00Z" };
56  const waiting = add("race-advice", "Review timeout handling", "race-open", 60);
57  waiting.judge = "fixture-judge";
58  waiting.verdict = null;
59  // Reverse response order to exercise the recorded-time sort rather than API order.
60  state.races.reverse();
61  return state;
62}
63