fixtures.ts 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. /** Controller and UI-domain fixture shapes for the client test runtime. */
  2. import type {
  3. ISession, SessionEventLikeEntry, SessionSnapshot, SessionSummary,
  4. } from '@deepseek-ai/dsh-api-session-controller/client'
  5. import type { WorkspaceSnapshot } from '@deepseek-ai/dsh-api-workspace-controller/client'
  6. import type { SessionId } from '@deepseek-ai/dsh-session/types'
  7. import {
  8. EMPTY_CONVERSATION_SNAPSHOT,
  9. type ConversationSnapshot,
  10. } from '@deepseek-ai/dsh-client-ui-conversation/client'
  11. import {
  12. EMPTY_CHAT_SNAPSHOT,
  13. type ChatSnapshot,
  14. } from '@deepseek-ai/dsh-client-ui-chat/client'
  15. /**
  16. * Fixture overrides for the session behavior face: any subset of the
  17. * production ISession verbs (typed against it, so a face change surfaces
  18. * here at compile time), plus extra members feature-specific casts consume.
  19. * The open Record tail means a misnamed EXTRA member is not caught by the
  20. * compiler (it grafts as dead weight); the ISession verbs stay safe — a
  21. * misnamed verb leaves the fail-loud stub in place, which names itself at
  22. * the first call.
  23. */
  24. export type SessionBehaviorOverrides = Partial<ISession> & Record<string, unknown>
  25. /**
  26. * act-wrapped mutation runner shared by every runtime object: public mutators
  27. * funnel through it so tests never handle SlotCore microtask batching or
  28. * React act themselves.
  29. */
  30. export type Stabilizer = (fn: () => void | Promise<void>) => Promise<void>
  31. /** Mutable top-level snapshot fields accepted by fixture update callbacks. */
  32. export type FixtureSnapshot<T> = { -readonly [Key in keyof T]: T[Key] }
  33. /** Writable test representation of the immutable Session Controller snapshot. */
  34. export type SessionFixtureSnapshot = FixtureSnapshot<SessionSnapshot>
  35. /**
  36. * Session fixture accepted by {@link TestSessions.add}: identity plus optional
  37. * snapshot/list-row overrides and the session behavior face the feature under
  38. * test actually calls (kept open — the runtime never fakes methods a test did
  39. * not supply, so an unstubbed call fails loud at the call site).
  40. */
  41. export interface SessionFixture {
  42. id: string
  43. /** Overrides merged over {@link sessionSnapshot}; Conversation data arrives through the event feed. */
  44. snapshot?: Partial<Omit<SessionSnapshot, 'sessionId'>>
  45. /** List-row overrides merged over the defaults derived from `id`. */
  46. summary?: Partial<Omit<SessionSummary, 'id'>>
  47. /** Session behavior face: exactly the methods the feature under test calls (ISession subset + extras). */
  48. session?: SessionBehaviorOverrides
  49. /** Initial contiguous event window consumed by Conversation assembly. */
  50. events?: readonly SessionEventLikeEntry[]
  51. /** Whether the initial event window has an older page. */
  52. hasMore?: boolean
  53. }
  54. /**
  55. * A complete quiescent Session Controller snapshot.
  56. * @param sessionId - owning session id.
  57. * @returns the snapshot; spread fixture overrides on top.
  58. */
  59. export function sessionSnapshot(sessionId: SessionId): SessionSnapshot {
  60. return {
  61. sessionId,
  62. queue: [],
  63. pendingSubmissions: [],
  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. }