chore: import upstream snapshot with attribution
This commit is contained in:
@@ -0,0 +1,158 @@
|
||||
import { afterEach, beforeEach, describe, expect, test, vi } from 'vitest'
|
||||
|
||||
const mocks = vi.hoisted(() => {
|
||||
const connect = vi.fn()
|
||||
const run = vi.fn()
|
||||
const sendStdin = vi.fn()
|
||||
const closeStdin = vi.fn()
|
||||
const ensureAPIKey = vi.fn(() => 'test-api-key')
|
||||
const isPipedStdin = vi.fn()
|
||||
const streamStdinChunks = vi.fn()
|
||||
const setupSignalHandlers = vi.fn(() => () => {})
|
||||
|
||||
return {
|
||||
connect,
|
||||
run,
|
||||
sendStdin,
|
||||
closeStdin,
|
||||
ensureAPIKey,
|
||||
isPipedStdin,
|
||||
streamStdinChunks,
|
||||
setupSignalHandlers,
|
||||
}
|
||||
})
|
||||
|
||||
vi.mock('e2b', () => {
|
||||
class CommandExitError extends Error {
|
||||
exitCode: number
|
||||
constructor(exitCode: number) {
|
||||
super(`Command exited with ${exitCode}`)
|
||||
this.exitCode = exitCode
|
||||
}
|
||||
}
|
||||
|
||||
class NotFoundError extends Error {}
|
||||
|
||||
return {
|
||||
Sandbox: {
|
||||
connect: mocks.connect,
|
||||
},
|
||||
CommandExitError,
|
||||
NotFoundError,
|
||||
}
|
||||
})
|
||||
|
||||
vi.mock('../../../src/api', () => ({
|
||||
ensureAPIKey: mocks.ensureAPIKey,
|
||||
}))
|
||||
|
||||
vi.mock('src/utils/signal', () => ({
|
||||
setupSignalHandlers: mocks.setupSignalHandlers,
|
||||
}))
|
||||
|
||||
vi.mock(
|
||||
'../../../src/commands/sandbox/exec_helpers',
|
||||
async (importOriginal: <T>() => Promise<T>) => {
|
||||
const actual =
|
||||
await importOriginal<
|
||||
typeof import('../../../src/commands/sandbox/exec_helpers')
|
||||
>()
|
||||
return {
|
||||
...actual,
|
||||
isPipedStdin: mocks.isPipedStdin,
|
||||
streamStdinChunks: mocks.streamStdinChunks,
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
describe('sandbox exec stdin run flag', () => {
|
||||
beforeEach(() => {
|
||||
vi.resetModules()
|
||||
vi.clearAllMocks()
|
||||
|
||||
const handle = {
|
||||
pid: 1234,
|
||||
error: undefined,
|
||||
wait: vi.fn().mockResolvedValue({ exitCode: 0 }),
|
||||
kill: vi.fn().mockResolvedValue(undefined),
|
||||
disconnect: vi.fn().mockResolvedValue(undefined),
|
||||
}
|
||||
|
||||
mocks.run.mockResolvedValue(handle)
|
||||
mocks.sendStdin.mockResolvedValue(undefined)
|
||||
mocks.closeStdin.mockResolvedValue(undefined)
|
||||
mocks.isPipedStdin.mockReturnValue(false)
|
||||
mocks.streamStdinChunks.mockResolvedValue(undefined)
|
||||
mocks.connect.mockResolvedValue({
|
||||
commands: {
|
||||
run: mocks.run,
|
||||
sendStdin: mocks.sendStdin,
|
||||
closeStdin: mocks.closeStdin,
|
||||
supportsStdinClose: true,
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
afterEach(() => {
|
||||
vi.restoreAllMocks()
|
||||
})
|
||||
|
||||
test('does not pass stdin flag when stdin is not piped', async () => {
|
||||
const exitSpy = vi
|
||||
.spyOn(process, 'exit')
|
||||
.mockImplementation((() => undefined) as never)
|
||||
|
||||
const { execCommand } = await import('../../../src/commands/sandbox/exec')
|
||||
await execCommand.parseAsync(['sandbox-id', 'echo', 'hello'], {
|
||||
from: 'user',
|
||||
})
|
||||
|
||||
expect(mocks.run).toHaveBeenCalledTimes(1)
|
||||
const runOpts = mocks.run.mock.calls[0][1]
|
||||
expect(runOpts).not.toHaveProperty('stdin')
|
||||
expect(mocks.streamStdinChunks).not.toHaveBeenCalled()
|
||||
expect(exitSpy).toHaveBeenCalledWith(0)
|
||||
})
|
||||
|
||||
test('passes stdin: true when stdin piping is active', async () => {
|
||||
mocks.isPipedStdin.mockReturnValue(true)
|
||||
const events: string[] = []
|
||||
mocks.setupSignalHandlers.mockImplementation(() => {
|
||||
events.push('setup')
|
||||
return () => {
|
||||
events.push('cleanup')
|
||||
}
|
||||
})
|
||||
mocks.streamStdinChunks.mockImplementation(
|
||||
async (
|
||||
_stream: NodeJS.ReadableStream,
|
||||
onChunk: (chunk: Uint8Array) => Promise<void | boolean>,
|
||||
_maxBytes: number
|
||||
) => {
|
||||
events.push('stream-start')
|
||||
await onChunk(Buffer.from('hello'))
|
||||
events.push('stream-end')
|
||||
}
|
||||
)
|
||||
const exitSpy = vi
|
||||
.spyOn(process, 'exit')
|
||||
.mockImplementation((() => undefined) as never)
|
||||
|
||||
const { execCommand } = await import('../../../src/commands/sandbox/exec')
|
||||
await execCommand.parseAsync(['sandbox-id', 'cat'], {
|
||||
from: 'user',
|
||||
})
|
||||
|
||||
expect(mocks.run).toHaveBeenCalledTimes(1)
|
||||
const runOpts = mocks.run.mock.calls[0][1]
|
||||
expect(runOpts).toHaveProperty('stdin', true)
|
||||
expect(mocks.streamStdinChunks).toHaveBeenCalled()
|
||||
expect(mocks.sendStdin).toHaveBeenCalled()
|
||||
expect(mocks.closeStdin).toHaveBeenCalled()
|
||||
expect(events).toContain('setup')
|
||||
expect(events).toContain('stream-start')
|
||||
expect(events.indexOf('setup')).toBeLessThan(events.indexOf('stream-start'))
|
||||
expect(events).toContain('cleanup')
|
||||
expect(exitSpy).toHaveBeenCalledWith(0)
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user