Skip to content

Commit 86f0235

Browse files
committed
test(tools): cover internal timeout forwarding for ssh path
1 parent bd718a2 commit 86f0235

File tree

1 file changed

+109
-0
lines changed

1 file changed

+109
-0
lines changed

apps/sim/tools/index.test.ts

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ import {
1313
type ExecutionContext,
1414
type MockFetchResponse,
1515
} from '@sim/testing'
16+
import { DEFAULT_EXECUTION_TIMEOUT_MS } from '@/lib/core/execution-limits'
17+
import * as securityValidation from '@/lib/core/security/input-validation.server'
1618
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
1719

1820
// Hoisted mock state - these are available to vi.mock factories
@@ -437,6 +439,113 @@ describe('executeTool Function', () => {
437439
})
438440
})
439441

442+
describe('Internal Tool Timeout Behavior', () => {
443+
let cleanupEnvVars: () => void
444+
445+
beforeEach(() => {
446+
process.env.NEXT_PUBLIC_APP_URL = 'http://localhost:3000'
447+
cleanupEnvVars = setupEnvVars({ NEXT_PUBLIC_APP_URL: 'http://localhost:3000' })
448+
})
449+
450+
afterEach(() => {
451+
vi.restoreAllMocks()
452+
cleanupEnvVars()
453+
})
454+
455+
it('should pass explicit timeout to secureFetchWithPinnedIP for internal routes', async () => {
456+
const expectedTimeout = 600000
457+
458+
const secureFetchSpy = vi
459+
.spyOn(securityValidation, 'secureFetchWithPinnedIP')
460+
.mockResolvedValue({
461+
ok: true,
462+
status: 200,
463+
statusText: 'OK',
464+
headers: new securityValidation.SecureFetchHeaders({ 'content-type': 'application/json' }),
465+
text: async () => JSON.stringify({ success: true }),
466+
json: async () => ({ success: true }),
467+
arrayBuffer: async () => new TextEncoder().encode(JSON.stringify({ success: true })).buffer,
468+
})
469+
470+
const originalFunctionTool = { ...tools.function_execute }
471+
tools.function_execute = {
472+
...tools.function_execute,
473+
transformResponse: vi.fn().mockResolvedValue({
474+
success: true,
475+
output: { result: 'executed' },
476+
}),
477+
}
478+
479+
try {
480+
const result = await executeTool(
481+
'function_execute',
482+
{
483+
code: 'return 1',
484+
timeout: expectedTimeout,
485+
},
486+
true
487+
)
488+
489+
expect(result.success).toBe(true)
490+
expect(secureFetchSpy).toHaveBeenCalled()
491+
expect(secureFetchSpy).toHaveBeenCalledWith(
492+
expect.stringContaining('/api/function/execute'),
493+
'127.0.0.1',
494+
expect.objectContaining({
495+
timeout: expectedTimeout,
496+
})
497+
)
498+
} finally {
499+
tools.function_execute = originalFunctionTool
500+
}
501+
})
502+
503+
it('should use DEFAULT_EXECUTION_TIMEOUT_MS when timeout is not provided', async () => {
504+
const secureFetchSpy = vi
505+
.spyOn(securityValidation, 'secureFetchWithPinnedIP')
506+
.mockResolvedValue({
507+
ok: true,
508+
status: 200,
509+
statusText: 'OK',
510+
headers: new securityValidation.SecureFetchHeaders({ 'content-type': 'application/json' }),
511+
text: async () => JSON.stringify({ success: true }),
512+
json: async () => ({ success: true }),
513+
arrayBuffer: async () => new TextEncoder().encode(JSON.stringify({ success: true })).buffer,
514+
})
515+
516+
const originalFunctionTool = { ...tools.function_execute }
517+
tools.function_execute = {
518+
...tools.function_execute,
519+
transformResponse: vi.fn().mockResolvedValue({
520+
success: true,
521+
output: { result: 'executed' },
522+
}),
523+
}
524+
525+
try {
526+
const result = await executeTool(
527+
'function_execute',
528+
{
529+
code: 'return 1',
530+
},
531+
true
532+
)
533+
534+
expect(result.success).toBe(true)
535+
expect(secureFetchSpy).toHaveBeenCalled()
536+
expect(secureFetchSpy).toHaveBeenCalledWith(
537+
expect.stringContaining('/api/function/execute'),
538+
'127.0.0.1',
539+
expect.objectContaining({
540+
timeout: DEFAULT_EXECUTION_TIMEOUT_MS,
541+
})
542+
)
543+
} finally {
544+
tools.function_execute = originalFunctionTool
545+
}
546+
})
547+
})
548+
440549
describe('Automatic Internal Route Detection', () => {
441550
let cleanupEnvVars: () => void
442551

0 commit comments

Comments
 (0)