native-command.spec.ts 1.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243
  1. import { describe, expect, it } from 'vitest'
  2. import { runNativeCommand } from '@deepseek-ai/dsh-native-command'
  3. const node = process.execPath
  4. describe('runNativeCommand', () => {
  5. it('captures utf8 stdout and stderr on exit 0', async () => {
  6. const result = await runNativeCommand(
  7. node,
  8. ['-e', 'process.stdout.write("out✓"); process.stderr.write("err")'],
  9. new AbortController().signal,
  10. )
  11. expect(result).toEqual({ stdout: 'out✓', stderr: 'err' })
  12. })
  13. it('rejects a non-zero exit with code, stdout, and stderr attached', async () => {
  14. const failure = await runNativeCommand(
  15. node,
  16. ['-e', 'process.stdout.write("partial"); process.stderr.write("boom"); process.exit(3)'],
  17. new AbortController().signal,
  18. ).then(() => { throw new Error('unexpected resolve') }, (error: unknown) => error)
  19. expect(failure).toMatchObject({ code: 3, stdout: 'partial', stderr: 'boom' })
  20. expect((failure as Error).cause).toBeInstanceOf(Error)
  21. })
  22. it('rejects a missing executable with the spawn ENOENT code', async () => {
  23. const failure = await runNativeCommand(
  24. 'dsh-definitely-missing-command',
  25. [],
  26. new AbortController().signal,
  27. ).then(() => { throw new Error('unexpected resolve') }, (error: unknown) => error)
  28. expect(failure).toMatchObject({ code: 'ENOENT' })
  29. })
  30. it('terminates the child when the signal aborts', async () => {
  31. const abort = new AbortController()
  32. const pending = runNativeCommand(node, ['-e', 'setTimeout(() => {}, 60_000)'], abort.signal)
  33. abort.abort()
  34. const failure = await pending.then(() => { throw new Error('unexpected resolve') }, (error: unknown) => error)
  35. expect(failure).toBeInstanceOf(Error)
  36. expect((failure as { code?: unknown }).code).toBe('ABORT_ERR')
  37. })
  38. })