Skip to content

Commit 19bda28

Browse files
fix(tests): isolate PitchBook error handling from network
1 parent ef5972a commit 19bda28

1 file changed

Lines changed: 37 additions & 20 deletions

File tree

apps/sim/tools/pitchbook/pitchbook.test.ts

Lines changed: 37 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
/**
22
* @vitest-environment node
33
*/
4+
import { inputValidationMock, inputValidationMockFns } from '@sim/testing'
45
import { describe, expect, it, vi } from 'vitest'
56

7+
vi.mock('@/lib/core/security/input-validation.server', () => inputValidationMock)
8+
69
/**
710
* Only this service's configs are needed; the full registry is ~6,000 modules.
811
* Registration is asserted through the generated `@/tools/tool-ids`.
@@ -484,28 +487,42 @@ describe('pitchbook error extraction', () => {
484487
* not appear anywhere in the tool result, message or retained body.
485488
*/
486489
it('keeps the rejected key out of the whole failed tool result', async () => {
487-
const fetchSpy = vi.spyOn(globalThis, 'fetch').mockResolvedValue(
488-
new Response(
489-
JSON.stringify({
490-
reason: 'UNAUTHORIZED',
491-
message: `Active API key ${SUBMITTED_KEY} not found`,
492-
}),
493-
{ status: 401, headers: { 'content-type': 'application/json' } }
494-
)
490+
const response = new Response(
491+
JSON.stringify({
492+
reason: 'UNAUTHORIZED',
493+
message: `Active API key ${SUBMITTED_KEY} not found`,
494+
}),
495+
{ status: 401, headers: { 'content-type': 'application/json' } }
495496
)
497+
inputValidationMockFns.mockValidateUrlWithDNS.mockResolvedValueOnce({
498+
isValid: true,
499+
resolvedIP: '93.184.216.34',
500+
})
501+
inputValidationMockFns.mockSecureFetchWithPinnedIP.mockResolvedValueOnce({
502+
ok: response.ok,
503+
status: response.status,
504+
statusText: response.statusText,
505+
headers: {
506+
get: (name: string) => response.headers.get(name),
507+
toRecord: () => Object.fromEntries(response.headers.entries()),
508+
},
509+
body: response.body,
510+
text: () => response.text(),
511+
json: () => response.json(),
512+
arrayBuffer: () => response.arrayBuffer(),
513+
})
496514

497-
try {
498-
const result = await executeTool('pitchbook_company_bio', {
499-
apiKey: SUBMITTED_KEY,
500-
pbId: '10618-03',
501-
})
502-
503-
expect(result.success).toBe(false)
504-
expect(JSON.stringify(result.output ?? {})).not.toContain(SUBMITTED_KEY)
505-
expect(result.error ?? '').not.toContain(SUBMITTED_KEY)
506-
} finally {
507-
fetchSpy.mockRestore()
508-
}
515+
const result = await executeTool('pitchbook_company_bio', {
516+
apiKey: SUBMITTED_KEY,
517+
pbId: '10618-03',
518+
})
519+
520+
expect(inputValidationMockFns.mockSecureFetchWithPinnedIP).toHaveBeenCalledOnce()
521+
expect(result.success).toBe(false)
522+
expect(result.error).toBe(
523+
'PitchBook rejected the API key. Check that the key is active and has API access.'
524+
)
525+
expect(JSON.stringify(result)).not.toContain(SUBMITTED_KEY)
509526
})
510527

511528
it('routes every pitchbook tool through the scrubbing extractor', () => {

0 commit comments

Comments
 (0)