scripted-list.client.ts 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051
  1. /** A directory listing the spec settles by hand, one deferred result per call. */
  2. import { vi } from 'vitest'
  3. import type { Mock } from 'vitest'
  4. import type { RemoteResult } from '@deepseek-ai/dsh-api-remotes/client'
  5. import type { ListWorkspaceDirectory } from '../src/client/face.ts'
  6. import type { DirLevel } from '../src/client/store.ts'
  7. /** The scripted listing: the mock the face receives, and the hand that settles it. */
  8. export interface ScriptedList {
  9. readonly list: Mock<ListWorkspaceDirectory>
  10. /**
  11. * Settle the oldest outstanding call and let its store write land.
  12. * @param result - what the endpoint answers.
  13. */
  14. readonly settle: (result: RemoteResult<DirLevel>) => Promise<void>
  15. /**
  16. * Settle the newest outstanding call first, so an older one can arrive after it.
  17. * @param result - what the endpoint answers.
  18. */
  19. readonly settleLatest: (result: RemoteResult<DirLevel>) => Promise<void>
  20. /** Paths of calls not yet settled, oldest first. */
  21. readonly outstanding: () => readonly string[]
  22. }
  23. /**
  24. * Build a listing whose every call stays pending until the spec settles it.
  25. * @returns the scripted listing.
  26. */
  27. /** One listing awaiting the spec's answer. */
  28. interface PendingList {
  29. readonly path: string
  30. resolve(result: RemoteResult<DirLevel>): void
  31. }
  32. export function scriptedList(): ScriptedList {
  33. const pending: PendingList[] = []
  34. const list = vi.fn<ListWorkspaceDirectory>((_sessionId, path) =>
  35. new Promise((resolve) => { pending.push({ path, resolve }) }))
  36. const land = async (call: PendingList | undefined, result: RemoteResult<DirLevel>): Promise<void> => {
  37. if (call === undefined) throw new Error('no outstanding listing to settle')
  38. call.resolve(result)
  39. await Promise.resolve()
  40. await Promise.resolve()
  41. }
  42. return {
  43. list,
  44. settle: result => land(pending.shift(), result),
  45. settleLatest: result => land(pending.pop(), result),
  46. outstanding: () => pending.map(call => call.path),
  47. }
  48. }