fixtures.ts 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. /** Controller and UI-domain fixture shapes for the client test runtime. */
  2. import type {
  3. ISession, SessionSnapshot, SessionSummary,
  4. } from '@deepseek-ai/dsh-api-session-controller/client'
  5. import type { SessionEventEntry } from '@deepseek-ai/dsh-api-session-controller/types'
  6. import type { WorkspaceSnapshot } from '@deepseek-ai/dsh-api-workspace-controller/client'
  7. import type { SessionId } from '@deepseek-ai/dsh-session/types'
  8. import {
  9. EMPTY_CONVERSATION_SNAPSHOT,
  10. type ConversationSnapshot,
  11. } from '@deepseek-ai/dsh-client-ui-conversation/client'
  12. import {
  13. EMPTY_CHAT_SNAPSHOT,
  14. type ChatSnapshot,
  15. } from '@deepseek-ai/dsh-client-ui-chat/client'
  16. /**
  17. * Fixture overrides for the session behavior face: any subset of the
  18. * production ISession verbs (typed against it, so a face change surfaces
  19. * here at compile time), plus extra members feature-specific casts consume.
  20. * The open Record tail means a misnamed EXTRA member is not caught by the
  21. * compiler (it grafts as dead weight); the ISession verbs stay safe — a
  22. * misnamed verb leaves the fail-loud stub in place, which names itself at
  23. * the first call.
  24. */
  25. export type SessionBehaviorOverrides = Partial<ISession> & Record<string, unknown>
  26. /**
  27. * act-wrapped mutation runner shared by every runtime object: public mutators
  28. * funnel through it so tests never handle SlotCore microtask batching or
  29. * React act themselves.
  30. */
  31. export type Stabilizer = (fn: () => void | Promise<void>) => Promise<void>
  32. /** Mutable top-level snapshot fields accepted by fixture update callbacks. */
  33. export type FixtureSnapshot<T> = { -readonly [Key in keyof T]: T[Key] }
  34. /** Writable test representation of the immutable Session Controller snapshot. */
  35. export type SessionFixtureSnapshot = FixtureSnapshot<SessionSnapshot>
  36. /**
  37. * Session fixture accepted by {@link TestSessions.add}: identity plus optional
  38. * snapshot/list-row overrides and the session behavior face the feature under
  39. * test actually calls (kept open — the runtime never fakes methods a test did
  40. * not supply, so an unstubbed call fails loud at the call site).
  41. */
  42. export interface SessionFixture {
  43. id: string
  44. /** Overrides merged over {@link sessionSnapshot}; Conversation data arrives through the event feed. */
  45. snapshot?: Partial<Omit<SessionSnapshot, 'sessionId'>>
  46. /** List-row overrides merged over the defaults derived from `id`. */
  47. summary?: Partial<Omit<SessionSummary, 'id'>>
  48. /** Session behavior face: exactly the methods the feature under test calls (ISession subset + extras). */
  49. session?: SessionBehaviorOverrides
  50. /** Initial contiguous event window consumed by Conversation assembly. */
  51. events?: readonly SessionEventEntry[]
  52. /** Whether the initial event window has an older page. */
  53. hasMore?: boolean
  54. }
  55. /**
  56. * A complete quiescent Session Controller snapshot.
  57. * @param sessionId - owning session id.
  58. * @returns the snapshot; spread fixture overrides on top.
  59. */
  60. export function sessionSnapshot(sessionId: SessionId): SessionSnapshot {
  61. return {
  62. sessionId,
  63. queue: [],
  64. running: false,
  65. subagent: null,
  66. removed: false,
  67. openState: 'open',
  68. openError: null,
  69. hasMore: false,
  70. loadingOlder: false,
  71. promptError: null,
  72. blank: false,
  73. lastAgentError: null,
  74. promptAttempted: false,
  75. awaitingFirstTurn: false,
  76. }
  77. }
  78. /**
  79. * A target-neutral Conversation snapshot.
  80. * @param overrides - target roster or activity overrides.
  81. * @returns an immutable fixture value.
  82. */
  83. export function conversationSnapshot(
  84. overrides: Partial<ConversationSnapshot> = {},
  85. ): ConversationSnapshot {
  86. return { ...EMPTY_CONVERSATION_SNAPSHOT, ...overrides }
  87. }
  88. /**
  89. * A Chat target snapshot.
  90. * @param overrides - Chat target overrides.
  91. * @returns an immutable fixture value.
  92. */
  93. export function chatSnapshot(overrides: Partial<ChatSnapshot> = {}): ChatSnapshot {
  94. return { ...EMPTY_CHAT_SNAPSHOT, ...overrides }
  95. }
  96. /**
  97. * A ready Workspace Controller snapshot with no Workspace rows.
  98. * @returns the initial state of the test Workspace source.
  99. */
  100. export function workspaceSnapshot(): WorkspaceSnapshot {
  101. return {
  102. items: [],
  103. archivedSessionIds: [],
  104. state: 'idle',
  105. phase: 'ready',
  106. error: null,
  107. }
  108. }