fixture.test.ts 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
  1. import { describe, expect, test } from "bun:test"
  2. import {
  3. assistantMessage,
  4. event,
  5. toolPart,
  6. userMessage,
  7. validateTimelineEvent,
  8. validateTimelineMessages,
  9. type PartSeed,
  10. } from "./fixture"
  11. describe("timeline fixture validation", () => {
  12. test("accepts a valid timeline", () => {
  13. expect(validateTimelineMessages([userMessage(), assistantMessage()])).toHaveLength(2)
  14. })
  15. test("rejects malformed SDK values at runtime", () => {
  16. expect(() =>
  17. assistantMessage([], {
  18. error: { name: "APIError", data: { message: "failed" } } as never,
  19. }),
  20. ).toThrow()
  21. expect(() =>
  22. validateTimelineEvent({
  23. directory: "C:/OpenCode/TimelineStability",
  24. payload: {
  25. id: "evt_invalid_status",
  26. type: "session.status",
  27. properties: { sessionID: "ses_timeline_stability", status: { type: "retry", attempt: 1 } },
  28. },
  29. }),
  30. ).toThrow()
  31. })
  32. test("rejects duplicate IDs and orphan assistants", () => {
  33. expect(() => validateTimelineMessages([userMessage(), userMessage()])).toThrow(/duplicate message ID/)
  34. expect(() =>
  35. validateTimelineMessages([userMessage(), assistantMessage([], { parentID: "msg_missing_parent" })]),
  36. ).toThrow(/parent user/)
  37. })
  38. test("assigns deterministic event IDs", () => {
  39. const first = event("session.status", { sessionID: "ses_timeline_stability", status: { type: "busy" } })
  40. const second = event("session.status", { sessionID: "ses_timeline_stability", status: { type: "idle" } })
  41. expect(first.payload.id).toMatch(/^evt_timeline_\d{4}$/)
  42. expect(Number(second.payload.id.slice(-4))).toBe(Number(first.payload.id.slice(-4)) + 1)
  43. })
  44. })
  45. if (false) {
  46. const userSeed = { id: "prt_type_user", type: "text", text: "typed" } satisfies PartSeed<"user">
  47. userMessage([userSeed])
  48. // @ts-expect-error Tool completion fields are not valid while pending.
  49. toolPart("prt_invalid_pending", "bash", "pending", {}, { output: "impossible" })
  50. // @ts-expect-error Tool completion fields are not valid while running.
  51. toolPart("prt_invalid_running", "bash", "running", {}, { output: "impossible" })
  52. // @ts-expect-error Tool error fields are not valid after completion.
  53. toolPart("prt_invalid_completed", "bash", "completed", {}, { error: "impossible" })
  54. assistantMessage([
  55. // @ts-expect-error Agent references belong to user messages, not assistant messages.
  56. { id: "prt_invalid_owner", type: "agent", name: "explore", source: { value: "@explore", start: 0, end: 8 } },
  57. ])
  58. // @ts-expect-error Retry status events require message and next.
  59. event("session.status", { sessionID: "ses_timeline_stability", status: { type: "retry", attempt: 1 } })
  60. }