startup.spec.ts 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  1. /** The SDK app command provider and stdin shutdown binding. */
  2. import { EventEmitter } from 'node:events'
  3. import { Context } from '@deepseek-ai/cordis'
  4. import { afterEach, describe, expect, it } from 'vitest'
  5. import { internals, provideCmdline } from '@deepseek-ai/dsh-cmdline'
  6. import { apply, type Config, SDK_APP_STARTUP_SERVICE } from '../src/index.ts'
  7. /** Controllable stdin for one startup invocation. */
  8. class TestStdin extends EventEmitter {
  9. readableEnded = false
  10. resume(): this {
  11. return this
  12. }
  13. end(): void {
  14. this.readableEnded = true
  15. this.emit('end')
  16. }
  17. }
  18. afterEach(() => {
  19. internals.stdin = process.stdin
  20. internals.stdout = process.stdout
  21. internals.stderr = process.stderr
  22. })
  23. /** Run the provider with captured command output and exit requests. */
  24. function start(args: string[], config: Config = {}): { ctx: Context; exits: number[]; out: () => string; stdin: TestStdin } {
  25. const ctx = new Context()
  26. const exits: number[] = []
  27. const stdin = new TestStdin()
  28. let out = ''
  29. const capture = { write: (chunk: string) => { out += chunk; return true } }
  30. internals.stdin = stdin
  31. internals.stdout = capture
  32. internals.stderr = capture
  33. provideCmdline(ctx, {
  34. args,
  35. exit: code => void exits.push(code),
  36. ready: { onReady: (listener) => { listener(); return () => {} } },
  37. })
  38. apply(ctx, config)
  39. return { ctx, exits, out: () => out, stdin }
  40. }
  41. describe('SDK app startup', () => {
  42. it('publishes readiness and requests bounded exit on client EOF', async () => {
  43. const { ctx, exits, stdin } = start([])
  44. expect(ctx.get(SDK_APP_STARTUP_SERVICE)).toEqual({ accepted: true })
  45. stdin.end()
  46. expect(exits).toEqual([0])
  47. await ctx.fiber.dispose()
  48. })
  49. it('prints app help without publishing readiness or binding stdin', () => {
  50. const { ctx, exits, out, stdin } = start(['--help'])
  51. expect(out()).toContain('dsh --profile sdk')
  52. expect(ctx.get(SDK_APP_STARTUP_SERVICE)).toBeUndefined()
  53. expect(exits).toEqual([0])
  54. stdin.end()
  55. expect(exits).toEqual([0])
  56. })
  57. it('renders the selected SDK profile name in help', () => {
  58. const { out } = start(['--help'], { profile: 'sdk-minimal' })
  59. expect(out()).toContain('Usage: dsh --profile sdk-minimal')
  60. expect(out()).toContain('dsh --profile sdk-minimal')
  61. })
  62. })