Repository navigation
Expand file tree
/
Copy pathembed-isolation.test.ts
More file actions
120 lines (115 loc) · 5.09 KB
/
Copy pathembed-isolation.test.ts
File metadata and controls
120 lines (115 loc) · 5.09 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
import { describe, expect, it, vi } from 'vitest'
import { runEmbeddedCli } from './embed'
const identity = { endpoint: 'https://sim.test', apiKey: 'fixture', workspaceId: 'workspace' }
describe('embedded CLI output ownership', () => {
it('leaves host logging and process functions untouched through parallel streamed calls', async () => {
const log = vi.spyOn(console, 'log').mockImplementation(() => {})
const error = vi.spyOn(console, 'error').mockImplementation(() => {})
const stdout = vi.spyOn(process.stdout, 'write').mockImplementation(() => true)
const stderr = vi.spyOn(process.stderr, 'write').mockImplementation(() => true)
const exit = process.exit
try {
const results = await Promise.all(
['first', 'second'].map((name) =>
runEmbeddedCli(['files', 'get', name], {
...identity,
transport: async () => {
console.log('host request %s', name)
await Promise.resolve()
console.error('host diagnostic %s', name)
return new Response(
new ReadableStream<Uint8Array>({
async start(controller) {
await Promise.resolve()
process.stdout.write('host stream output')
process.stderr.write('host stream diagnostic')
controller.enqueue(Buffer.from(JSON.stringify({ name })))
controller.close()
},
}),
{ headers: { 'content-type': 'application/json' } }
)
},
})
)
)
expect(results).toEqual(
['first', 'second'].map((name) => ({
exitCode: 0,
stdout: JSON.stringify({ name }),
stderr: '',
}))
)
expect(console.log).toBe(log)
expect(console.error).toBe(error)
expect(process.stdout.write).toBe(stdout)
expect(process.stderr.write).toBe(stderr)
expect(process.exit).toBe(exit)
expect(log).toHaveBeenCalledTimes(2)
expect(error).toHaveBeenCalledTimes(2)
expect(stdout).toHaveBeenCalledWith('host stream output')
expect(stderr).toHaveBeenCalledWith('host stream diagnostic')
} finally {
vi.restoreAllMocks()
}
})
it('keeps a download adapter diagnostic outside the CLI JSON result', async () => {
const log = vi.spyOn(console, 'log').mockImplementation(() => {})
const result = await runEmbeddedCli(
['files', 'get', 'file', '--output-file', 'saved.json'],
{ ...identity, transport: async () => new Response('{}') },
{
writeFile: async (_path, stream) => {
console.log('host saving file')
await new Response(stream).text()
console.log('host file saved')
},
}
)
expect(result.exitCode, result.stderr).toBe(0)
expect(JSON.parse(result.stdout)).toMatchObject({ path: 'saved.json', status: 'saved' })
expect(log).toHaveBeenCalledTimes(2)
expect(result.stderr).toBe('')
})
it('captures subcommand help and usage errors through Commander output configuration', async () => {
const [help, invalid] = await Promise.all([
runEmbeddedCli(['files', 'get', '--help'], identity),
runEmbeddedCli(['files', 'get'], identity),
])
expect(help.exitCode).toBe(0)
expect(help.stdout).toContain('Usage:')
expect(help.stderr).toBe('')
expect(invalid.exitCode).toBe(1)
expect(invalid.stdout).toBe('')
expect(invalid.stderr).toContain('missing required argument')
})
it('answers a guessed flag with the command flags, and an id that opens with a dash with the escape', async () => {
const transport = async () => {
throw new Error('a parse error must not reach the API')
}
const [guessed, dashedId, noArguments, noOptions] = await Promise.all([
runEmbeddedCli(['tables', 'rows', 'batch-delete', 'tbl_1', '--ids', 'row_1', '--yes'], {
...identity,
transport,
}),
runEmbeddedCli(['audit-logs', 'get', '-X9abc'], { ...identity, transport }),
runEmbeddedCli(['logs', 'list', '-X9abc'], { ...identity, transport }),
runEmbeddedCli(['workspaces', 'get', 'ws_1', '--verbose'], { ...identity, transport }),
])
expect(guessed.exitCode).toBe(1)
expect(guessed.stderr).toContain("unknown option '--ids'")
expect(guessed.stderr).toContain('Options for sim tables rows batch-delete:')
expect(guessed.stderr).toContain('--row <value...>')
expect(dashedId.exitCode).toBe(1)
expect(dashedId.stderr).toContain('Example: sim audit-logs get -- -X9abc')
expect(dashedId.stderr).not.toContain('Options for')
// With no positional to escape into, an id-shaped token is just an unknown option.
expect(noArguments.exitCode).toBe(1)
expect(noArguments.stderr).toContain('Options for sim logs list:')
expect(noArguments.stderr).not.toContain('Example:')
// An empty list reads as truncated output rather than as an answer.
expect(noOptions.exitCode).toBe(1)
expect(noOptions.stderr).toContain('sim workspaces get takes no options.')
expect(noOptions.stderr).not.toContain('Options for')
})
})