gemini-executor 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +274 -0
- package/agents/gemini-executor/README.md +315 -0
- package/agents/gemini-executor/__tests__/command.test.ts +362 -0
- package/agents/gemini-executor/__tests__/integration.test.ts +486 -0
- package/agents/gemini-executor/__tests__/security.test.ts +257 -0
- package/agents/gemini-executor/__tests__/validation.test.ts +373 -0
- package/agents/gemini-executor/index.ts +309 -0
- package/dist/agents/gemini-executor/index.d.ts +77 -0
- package/dist/agents/gemini-executor/index.d.ts.map +1 -0
- package/dist/agents/gemini-executor/index.js +249 -0
- package/dist/agents/gemini-executor/index.js.map +1 -0
- package/docs/architecture.md +261 -0
- package/package.json +58 -0
- package/skills/gemini/skill.md +362 -0
|
@@ -0,0 +1,486 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Integration Tests for Gemini Executor
|
|
3
|
+
*
|
|
4
|
+
* Tests the complete execute() function with mocked Gemini CLI calls,
|
|
5
|
+
* including error handling, retry logic, and result formatting.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { execute, checkGeminiCLI, ExecutionOptions } from '../index';
|
|
9
|
+
|
|
10
|
+
// Mock child_process module
|
|
11
|
+
jest.mock('child_process');
|
|
12
|
+
|
|
13
|
+
// Get reference to the mocked exec function
|
|
14
|
+
import { exec } from 'child_process';
|
|
15
|
+
const mockExec = exec as jest.MockedFunction<typeof exec>;
|
|
16
|
+
|
|
17
|
+
describe('Integration Tests', () => {
|
|
18
|
+
beforeEach(() => {
|
|
19
|
+
// Clear all mocks before each test
|
|
20
|
+
jest.clearAllMocks();
|
|
21
|
+
mockExec.mockReset();
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
describe('Successful Execution', () => {
|
|
25
|
+
test('should execute successfully with valid options', async () => {
|
|
26
|
+
// Mock successful execution - exec uses callback (error, stdout, stderr)
|
|
27
|
+
mockExec.mockImplementation((_cmd: string, _options: any, callback?: (error: any, stdout: string, stderr: string) => void) => {
|
|
28
|
+
callback?.(null, 'This is Gemini response', '');
|
|
29
|
+
return {} as any;
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
const options: ExecutionOptions = {
|
|
33
|
+
query: 'Test query'
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
const result = await execute(options);
|
|
37
|
+
|
|
38
|
+
expect(result.success).toBe(true);
|
|
39
|
+
expect(result.output).toBe('This is Gemini response');
|
|
40
|
+
expect(result.metadata.retries).toBe(0);
|
|
41
|
+
expect(result.metadata.duration).toBeGreaterThan(0);
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
test('should handle JSON output format', async () => {
|
|
45
|
+
const jsonOutput = JSON.stringify({
|
|
46
|
+
response: 'Gemini JSON response',
|
|
47
|
+
data: { key: 'value' }
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
mockExec.mockImplementation((_cmd: string, _options: any, callback?: (error: any, stdout: string, stderr: string) => void) => {
|
|
51
|
+
callback?.(null, jsonOutput, '');
|
|
52
|
+
return {} as any;
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
const options: ExecutionOptions = {
|
|
56
|
+
query: 'Test query',
|
|
57
|
+
outputFormat: 'json'
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
const result = await execute(options);
|
|
61
|
+
|
|
62
|
+
expect(result.success).toBe(true);
|
|
63
|
+
expect(result.output).toBe(jsonOutput);
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
test('should include file references', async () => {
|
|
67
|
+
mockExec.mockImplementation((_cmd: string, _options: any, callback?: (error: any, stdout: string, stderr: string) => void) => {
|
|
68
|
+
callback?.(null, 'File analysis complete', '');
|
|
69
|
+
return {} as any;
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
const options: ExecutionOptions = {
|
|
73
|
+
query: 'Analyze files',
|
|
74
|
+
files: ['/path/to/file.txt']
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
const result = await execute(options);
|
|
78
|
+
|
|
79
|
+
expect(result.success).toBe(true);
|
|
80
|
+
expect(mockExec).toHaveBeenCalled();
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
test('should use custom model', async () => {
|
|
84
|
+
mockExec.mockImplementation((_cmd: string, _options: any, callback?: (error: any, stdout: string, stderr: string) => void) => {
|
|
85
|
+
callback?.(null, 'Response from thinking model', '');
|
|
86
|
+
return {} as any;
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
const options: ExecutionOptions = {
|
|
90
|
+
query: 'Complex query',
|
|
91
|
+
model: 'gemini-2.0-flash-thinking-exp'
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
const result = await execute(options);
|
|
95
|
+
|
|
96
|
+
expect(result.success).toBe(true);
|
|
97
|
+
expect(result.metadata.model).toContain('gemini');
|
|
98
|
+
});
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
describe('Error Handling', () => {
|
|
102
|
+
test('should return error for empty query', async () => {
|
|
103
|
+
const options: ExecutionOptions = {
|
|
104
|
+
query: ''
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
const result = await execute(options);
|
|
108
|
+
|
|
109
|
+
expect(result.success).toBe(false);
|
|
110
|
+
expect(result.error).toContain('Query cannot be empty');
|
|
111
|
+
expect(result.metadata.retries).toBe(0);
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
test('should return error for whitespace-only query', async () => {
|
|
115
|
+
const options: ExecutionOptions = {
|
|
116
|
+
query: ' \n\t '
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
const result = await execute(options);
|
|
120
|
+
|
|
121
|
+
expect(result.success).toBe(false);
|
|
122
|
+
expect(result.error).toContain('Query cannot be empty');
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
test('should handle command execution errors', async () => {
|
|
126
|
+
mockExec.mockImplementation((_cmd: string, _options: any, callback?: (error: any, stdout: string, stderr: string) => void) => {
|
|
127
|
+
callback?.(new Error('Command failed'), '', '');
|
|
128
|
+
return {} as any;
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
const options: ExecutionOptions = {
|
|
132
|
+
query: 'Test query'
|
|
133
|
+
};
|
|
134
|
+
|
|
135
|
+
const result = await execute(options);
|
|
136
|
+
|
|
137
|
+
expect(result.success).toBe(false);
|
|
138
|
+
expect(result.error).toContain('Command failed');
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
test('should handle timeout errors', async () => {
|
|
142
|
+
mockExec.mockImplementation((_cmd: string, _options: any, callback?: (error: any, stdout: string, stderr: string) => void) => {
|
|
143
|
+
callback?.(new Error('Timeout exceeded'), '', '');
|
|
144
|
+
return {} as any;
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
const options: ExecutionOptions = {
|
|
148
|
+
query: 'Long running query'
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
const config = {
|
|
152
|
+
timeout: 1000 // 1 second
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
const result = await execute(options, config);
|
|
156
|
+
|
|
157
|
+
expect(result.success).toBe(false);
|
|
158
|
+
expect(result.error).toBeTruthy();
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
test('should handle stderr without stdout', async () => {
|
|
162
|
+
mockExec.mockImplementation((_cmd: string, _options: any, callback?: (error: any, stdout: string, stderr: string) => void) => {
|
|
163
|
+
callback?.(null, '', 'Error: API rate limit exceeded');
|
|
164
|
+
return {} as any;
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
const options: ExecutionOptions = {
|
|
168
|
+
query: 'Test query'
|
|
169
|
+
};
|
|
170
|
+
|
|
171
|
+
const result = await execute(options);
|
|
172
|
+
|
|
173
|
+
expect(result.success).toBe(false);
|
|
174
|
+
expect(result.error).toContain('API rate limit');
|
|
175
|
+
});
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
describe('Retry Logic', () => {
|
|
179
|
+
test('should retry on failure', async () => {
|
|
180
|
+
// Fail twice, then succeed
|
|
181
|
+
mockExec
|
|
182
|
+
.mockImplementationOnce((_cmd: string, _options: any, callback?: (error: any, stdout: string, stderr: string) => void) => {
|
|
183
|
+
callback?.(new Error('Temporary error'), '', '');
|
|
184
|
+
return {} as any;
|
|
185
|
+
})
|
|
186
|
+
.mockImplementationOnce((_cmd: string, _options: any, callback?: (error: any, stdout: string, stderr: string) => void) => {
|
|
187
|
+
callback?.(new Error('Temporary error'), '', '');
|
|
188
|
+
return {} as any;
|
|
189
|
+
})
|
|
190
|
+
.mockImplementationOnce((_cmd: string, _options: any, callback?: (error: any, stdout: string, stderr: string) => void) => {
|
|
191
|
+
callback?.(null, 'Success after retries', '');
|
|
192
|
+
return {} as any;
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
const options: ExecutionOptions = {
|
|
196
|
+
query: 'Test query'
|
|
197
|
+
};
|
|
198
|
+
|
|
199
|
+
const config = {
|
|
200
|
+
maxRetries: 3
|
|
201
|
+
};
|
|
202
|
+
|
|
203
|
+
const result = await execute(options, config);
|
|
204
|
+
|
|
205
|
+
expect(result.success).toBe(true);
|
|
206
|
+
expect(result.output).toBe('Success after retries');
|
|
207
|
+
expect(result.metadata.retries).toBe(2);
|
|
208
|
+
expect(mockExec).toHaveBeenCalledTimes(3);
|
|
209
|
+
}, 15000); // Increase timeout to 15s for retry logic
|
|
210
|
+
|
|
211
|
+
test('should fail after max retries', async () => {
|
|
212
|
+
// Always fail
|
|
213
|
+
mockExec.mockImplementation((_cmd: string, _options: any, callback?: (error: any, stdout: string, stderr: string) => void) => {
|
|
214
|
+
callback?.(new Error('Persistent error'), '', '');
|
|
215
|
+
return {} as any;
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
const options: ExecutionOptions = {
|
|
219
|
+
query: 'Test query'
|
|
220
|
+
};
|
|
221
|
+
|
|
222
|
+
const config = {
|
|
223
|
+
maxRetries: 3
|
|
224
|
+
};
|
|
225
|
+
|
|
226
|
+
const result = await execute(options, config);
|
|
227
|
+
|
|
228
|
+
expect(result.success).toBe(false);
|
|
229
|
+
expect(result.error).toContain('Persistent error');
|
|
230
|
+
expect(result.metadata.retries).toBe(2); // maxRetries - 1
|
|
231
|
+
expect(mockExec).toHaveBeenCalledTimes(3);
|
|
232
|
+
}, 15000); // Increase timeout
|
|
233
|
+
|
|
234
|
+
test('should implement exponential backoff', async () => {
|
|
235
|
+
const startTime = Date.now();
|
|
236
|
+
|
|
237
|
+
mockExec
|
|
238
|
+
.mockImplementationOnce((_cmd: string, _options: any, callback?: (error: any, stdout: string, stderr: string) => void) => {
|
|
239
|
+
callback?.(new Error('Error 1'), '', '');
|
|
240
|
+
return {} as any;
|
|
241
|
+
})
|
|
242
|
+
.mockImplementationOnce((_cmd: string, _options: any, callback?: (error: any, stdout: string, stderr: string) => void) => {
|
|
243
|
+
callback?.(new Error('Error 2'), '', '');
|
|
244
|
+
return {} as any;
|
|
245
|
+
})
|
|
246
|
+
.mockImplementationOnce((_cmd: string, _options: any, callback?: (error: any, stdout: string, stderr: string) => void) => {
|
|
247
|
+
callback?.(null, 'Success', '');
|
|
248
|
+
return {} as any;
|
|
249
|
+
});
|
|
250
|
+
|
|
251
|
+
const options: ExecutionOptions = {
|
|
252
|
+
query: 'Test query'
|
|
253
|
+
};
|
|
254
|
+
|
|
255
|
+
const config = {
|
|
256
|
+
maxRetries: 3
|
|
257
|
+
};
|
|
258
|
+
|
|
259
|
+
const result = await execute(options, config);
|
|
260
|
+
|
|
261
|
+
const duration = Date.now() - startTime;
|
|
262
|
+
|
|
263
|
+
expect(result.success).toBe(true);
|
|
264
|
+
// Should take at least 1s + 2s = 3s due to exponential backoff
|
|
265
|
+
expect(duration).toBeGreaterThanOrEqual(3000);
|
|
266
|
+
}, 15000); // Increase timeout to 15s
|
|
267
|
+
|
|
268
|
+
test('should not retry on validation errors', async () => {
|
|
269
|
+
const options: ExecutionOptions = {
|
|
270
|
+
query: '' // Invalid
|
|
271
|
+
};
|
|
272
|
+
|
|
273
|
+
const config = {
|
|
274
|
+
maxRetries: 5
|
|
275
|
+
};
|
|
276
|
+
|
|
277
|
+
const result = await execute(options, config);
|
|
278
|
+
|
|
279
|
+
expect(result.success).toBe(false);
|
|
280
|
+
expect(result.metadata.retries).toBe(0);
|
|
281
|
+
// mockExec should not be called at all
|
|
282
|
+
expect(mockExec).not.toHaveBeenCalled();
|
|
283
|
+
});
|
|
284
|
+
});
|
|
285
|
+
|
|
286
|
+
describe('Configuration Overrides', () => {
|
|
287
|
+
test('should use custom CLI path', async () => {
|
|
288
|
+
mockExec.mockImplementation((_cmd: string, _options: any, callback?: (error: any, stdout: string, stderr: string) => void) => {
|
|
289
|
+
callback?.(null, 'Custom path response', '');
|
|
290
|
+
return {} as any;
|
|
291
|
+
});
|
|
292
|
+
|
|
293
|
+
const options: ExecutionOptions = {
|
|
294
|
+
query: 'Test query'
|
|
295
|
+
};
|
|
296
|
+
|
|
297
|
+
const config = {
|
|
298
|
+
cliPath: '/custom/path/gemini'
|
|
299
|
+
};
|
|
300
|
+
|
|
301
|
+
const result = await execute(options, config);
|
|
302
|
+
|
|
303
|
+
expect(result.success).toBe(true);
|
|
304
|
+
const call = mockExec.mock.calls[0][0];
|
|
305
|
+
expect(call).toContain('/custom/path/gemini');
|
|
306
|
+
});
|
|
307
|
+
|
|
308
|
+
test('should use custom timeout', async () => {
|
|
309
|
+
mockExec.mockImplementation((_cmd: string, _options: any, callback?: (error: any, stdout: string, stderr: string) => void) => {
|
|
310
|
+
callback?.(null, 'Response', '');
|
|
311
|
+
return {} as any;
|
|
312
|
+
});
|
|
313
|
+
|
|
314
|
+
const options: ExecutionOptions = {
|
|
315
|
+
query: 'Test query'
|
|
316
|
+
};
|
|
317
|
+
|
|
318
|
+
const config = {
|
|
319
|
+
timeout: 300000 // 5 minutes
|
|
320
|
+
};
|
|
321
|
+
|
|
322
|
+
const result = await execute(options, config);
|
|
323
|
+
|
|
324
|
+
expect(result.success).toBe(true);
|
|
325
|
+
const callOptions = mockExec.mock.calls[0][1];
|
|
326
|
+
expect(callOptions).toBeDefined();
|
|
327
|
+
expect(callOptions?.timeout).toBe(300000);
|
|
328
|
+
});
|
|
329
|
+
|
|
330
|
+
test('should disable yolo mode', async () => {
|
|
331
|
+
mockExec.mockImplementation((_cmd: string, _options: any, callback?: (error: any, stdout: string, stderr: string) => void) => {
|
|
332
|
+
callback?.(null, 'Response', '');
|
|
333
|
+
return {} as any;
|
|
334
|
+
});
|
|
335
|
+
|
|
336
|
+
const options: ExecutionOptions = {
|
|
337
|
+
query: 'Test query'
|
|
338
|
+
};
|
|
339
|
+
|
|
340
|
+
const config = {
|
|
341
|
+
yolo: false
|
|
342
|
+
};
|
|
343
|
+
|
|
344
|
+
const result = await execute(options, config);
|
|
345
|
+
|
|
346
|
+
expect(result.success).toBe(true);
|
|
347
|
+
const command = mockExec.mock.calls[0][0];
|
|
348
|
+
expect(command).not.toContain('-y');
|
|
349
|
+
});
|
|
350
|
+
});
|
|
351
|
+
|
|
352
|
+
describe('Gemini CLI Availability Check', () => {
|
|
353
|
+
test('should return true if Gemini CLI is available', async () => {
|
|
354
|
+
mockExec.mockImplementation((_cmd: string, _options: any, callback?: (error: any, stdout: string, stderr: string) => void) => {
|
|
355
|
+
callback?.(null, 'gemini version 1.0.0', '');
|
|
356
|
+
return {} as any;
|
|
357
|
+
});
|
|
358
|
+
|
|
359
|
+
const isAvailable = await checkGeminiCLI();
|
|
360
|
+
|
|
361
|
+
expect(isAvailable).toBe(true);
|
|
362
|
+
});
|
|
363
|
+
|
|
364
|
+
test('should return false if Gemini CLI is not found', async () => {
|
|
365
|
+
mockExec.mockImplementation((_cmd: string, _options: any, callback?: (error: any, stdout: string, stderr: string) => void) => {
|
|
366
|
+
callback?.(new Error('Command not found'), '', '');
|
|
367
|
+
return {} as any;
|
|
368
|
+
});
|
|
369
|
+
|
|
370
|
+
const isAvailable = await checkGeminiCLI();
|
|
371
|
+
|
|
372
|
+
expect(isAvailable).toBe(false);
|
|
373
|
+
});
|
|
374
|
+
|
|
375
|
+
test('should check custom CLI path', async () => {
|
|
376
|
+
mockExec.mockImplementation((_cmd: string, _options: any, callback?: (error: any, stdout: string, stderr: string) => void) => {
|
|
377
|
+
callback?.(null, 'version info', '');
|
|
378
|
+
return {} as any;
|
|
379
|
+
});
|
|
380
|
+
|
|
381
|
+
const isAvailable = await checkGeminiCLI({
|
|
382
|
+
cliPath: '/custom/gemini'
|
|
383
|
+
});
|
|
384
|
+
|
|
385
|
+
expect(isAvailable).toBe(true);
|
|
386
|
+
const command = mockExec.mock.calls[0][0];
|
|
387
|
+
expect(command).toContain('/custom/gemini');
|
|
388
|
+
});
|
|
389
|
+
});
|
|
390
|
+
|
|
391
|
+
describe('Metadata Tracking', () => {
|
|
392
|
+
test('should track execution duration', async () => {
|
|
393
|
+
mockExec.mockImplementation((_cmd: string, _options: any, callback?: (error: any, stdout: string, stderr: string) => void) => {
|
|
394
|
+
setTimeout(() => {
|
|
395
|
+
callback?.(null, 'Response', '');
|
|
396
|
+
}, 100);
|
|
397
|
+
return {} as any;
|
|
398
|
+
});
|
|
399
|
+
|
|
400
|
+
const options: ExecutionOptions = {
|
|
401
|
+
query: 'Test query'
|
|
402
|
+
};
|
|
403
|
+
|
|
404
|
+
const result = await execute(options);
|
|
405
|
+
|
|
406
|
+
expect(result.success).toBe(true);
|
|
407
|
+
expect(result.metadata.duration).toBeGreaterThanOrEqual(100);
|
|
408
|
+
expect(result.metadata.duration).toBeLessThan(200);
|
|
409
|
+
});
|
|
410
|
+
|
|
411
|
+
test('should track model used', async () => {
|
|
412
|
+
mockExec.mockImplementation((_cmd: string, _options: any, callback?: (error: any, stdout: string, stderr: string) => void) => {
|
|
413
|
+
callback?.(null, 'Response', '');
|
|
414
|
+
return {} as any;
|
|
415
|
+
});
|
|
416
|
+
|
|
417
|
+
const options: ExecutionOptions = {
|
|
418
|
+
query: 'Test query',
|
|
419
|
+
model: 'gemini-pro'
|
|
420
|
+
};
|
|
421
|
+
|
|
422
|
+
const result = await execute(options);
|
|
423
|
+
|
|
424
|
+
expect(result.success).toBe(true);
|
|
425
|
+
expect(result.metadata.model).toBe('gemini-pro');
|
|
426
|
+
});
|
|
427
|
+
|
|
428
|
+
test('should track retry count', async () => {
|
|
429
|
+
mockExec
|
|
430
|
+
.mockImplementationOnce((_cmd: string, _options: any, callback?: (error: any, stdout: string, stderr: string) => void) => {
|
|
431
|
+
callback?.(new Error('Fail 1'), '', '');
|
|
432
|
+
return {} as any;
|
|
433
|
+
})
|
|
434
|
+
.mockImplementationOnce((_cmd: string, _options: any, callback?: (error: any, stdout: string, stderr: string) => void) => {
|
|
435
|
+
callback?.(null, 'Success', '');
|
|
436
|
+
return {} as any;
|
|
437
|
+
});
|
|
438
|
+
|
|
439
|
+
const options: ExecutionOptions = {
|
|
440
|
+
query: 'Test query'
|
|
441
|
+
};
|
|
442
|
+
|
|
443
|
+
const result = await execute(options);
|
|
444
|
+
|
|
445
|
+
expect(result.success).toBe(true);
|
|
446
|
+
expect(result.metadata.retries).toBe(1);
|
|
447
|
+
}, 15000); // Increase timeout for retry
|
|
448
|
+
});
|
|
449
|
+
|
|
450
|
+
describe('Large Buffer Handling', () => {
|
|
451
|
+
test('should handle large output (10MB)', async () => {
|
|
452
|
+
const largeOutput = 'x'.repeat(10 * 1024 * 1024); // 10MB
|
|
453
|
+
|
|
454
|
+
mockExec.mockImplementation((_cmd: string, _options: any, callback?: (error: any, stdout: string, stderr: string) => void) => {
|
|
455
|
+
callback?.(null, largeOutput, '');
|
|
456
|
+
return {} as any;
|
|
457
|
+
});
|
|
458
|
+
|
|
459
|
+
const options: ExecutionOptions = {
|
|
460
|
+
query: 'Generate large output'
|
|
461
|
+
};
|
|
462
|
+
|
|
463
|
+
const result = await execute(options);
|
|
464
|
+
|
|
465
|
+
expect(result.success).toBe(true);
|
|
466
|
+
expect(result.output?.length).toBe(10 * 1024 * 1024);
|
|
467
|
+
});
|
|
468
|
+
|
|
469
|
+
test('should set appropriate maxBuffer', async () => {
|
|
470
|
+
mockExec.mockImplementation((_cmd: string, _options: any, callback?: (error: any, stdout: string, stderr: string) => void) => {
|
|
471
|
+
callback?.(null, 'Response', '');
|
|
472
|
+
return {} as any;
|
|
473
|
+
});
|
|
474
|
+
|
|
475
|
+
const options: ExecutionOptions = {
|
|
476
|
+
query: 'Test query'
|
|
477
|
+
};
|
|
478
|
+
|
|
479
|
+
await execute(options);
|
|
480
|
+
|
|
481
|
+
const callOptions = mockExec.mock.calls[0][1];
|
|
482
|
+
expect(callOptions).toBeDefined();
|
|
483
|
+
expect(callOptions?.maxBuffer).toBe(10 * 1024 * 1024); // 10MB
|
|
484
|
+
});
|
|
485
|
+
});
|
|
486
|
+
});
|