1+ import { TEST_AGENT_RUNTIME_IMPL } from '@codebuff/common/testing/impl/agent-runtime'
12import {
23 clearMockedModules ,
34 mockModule ,
@@ -10,23 +11,18 @@ import {
1011 describe ,
1112 expect ,
1213 mock ,
13- spyOn ,
1414 test ,
1515} from 'bun:test'
1616
1717import { searchWeb } from '../linkup-api'
1818
19+ import type { AgentRuntimeDeps } from '@codebuff/common/types/contracts/agent-runtime'
20+
1921// Mock environment variables
2022process . env . LINKUP_API_KEY = 'test-api-key'
2123
2224describe ( 'Linkup API' , ( ) => {
23- // Mock logger with spy functions to verify logging calls
24- const mockLogger = {
25- debug : mock ( ( ) => { } ) ,
26- error : mock ( ( ) => { } ) ,
27- info : mock ( ( ) => { } ) ,
28- warn : mock ( ( ) => { } ) ,
29- }
25+ let agentRuntimeImpl : AgentRuntimeDeps
3026
3127 beforeAll ( ( ) => {
3228 mockModule ( '@codebuff/internal' , ( ) => ( {
@@ -42,13 +38,9 @@ describe('Linkup API', () => {
4238 } )
4339
4440 beforeEach ( ( ) => {
45- // Reset fetch mock before each test
46- spyOn ( global , 'fetch' ) . mockResolvedValue ( new Response ( ) )
47- // Reset logger mocks
48- mockLogger . debug . mockClear ( )
49- mockLogger . error . mockClear ( )
50- mockLogger . info . mockClear ( )
51- mockLogger . warn . mockClear ( )
41+ agentRuntimeImpl = {
42+ ...TEST_AGENT_RUNTIME_IMPL ,
43+ }
5244 } )
5345
5446 afterEach ( ( ) => {
@@ -73,24 +65,26 @@ describe('Linkup API', () => {
7365 ] ,
7466 }
7567
76- spyOn ( global , 'fetch' ) . mockResolvedValue (
77- new Response ( JSON . stringify ( mockResponse ) , {
78- status : 200 ,
79- headers : { 'Content-Type' : 'application/json' } ,
80- } ) ,
81- )
68+ agentRuntimeImpl . fetch = mock ( ( ) => {
69+ return Promise . resolve (
70+ new Response ( JSON . stringify ( mockResponse ) , {
71+ status : 200 ,
72+ headers : { 'Content-Type' : 'application/json' } ,
73+ } ) ,
74+ )
75+ } ) as unknown as typeof global . fetch
8276
8377 const result = await searchWeb ( {
78+ ...agentRuntimeImpl ,
8479 query : 'React tutorial' ,
85- logger : mockLogger ,
8680 } )
8781
8882 expect ( result ) . toBe (
8983 'React is a JavaScript library for building user interfaces. You can learn how to build your first React application by following the official documentation.' ,
9084 )
9185
9286 // Verify fetch was called with correct parameters
93- expect ( fetch ) . toHaveBeenCalledWith (
87+ expect ( agentRuntimeImpl . fetch ) . toHaveBeenCalledWith (
9488 'https://api.linkup.so/v1/search' ,
9589 expect . objectContaining ( {
9690 method : 'POST' ,
@@ -120,25 +114,27 @@ describe('Linkup API', () => {
120114 ] ,
121115 }
122116
123- spyOn ( global , 'fetch' ) . mockResolvedValue (
124- new Response ( JSON . stringify ( mockResponse ) , {
125- status : 200 ,
126- headers : { 'Content-Type' : 'application/json' } ,
127- } ) ,
128- )
117+ agentRuntimeImpl . fetch = mock ( ( ) => {
118+ return Promise . resolve (
119+ new Response ( JSON . stringify ( mockResponse ) , {
120+ status : 200 ,
121+ headers : { 'Content-Type' : 'application/json' } ,
122+ } ) ,
123+ )
124+ } ) as unknown as typeof global . fetch
129125
130126 const result = await searchWeb ( {
127+ ...agentRuntimeImpl ,
131128 query : 'React patterns' ,
132129 depth : 'deep' ,
133- logger : mockLogger ,
134130 } )
135131
136132 expect ( result ) . toBe (
137133 'Advanced React patterns include render props, higher-order components, and custom hooks for building reusable and maintainable components.' ,
138134 )
139135
140136 // Verify fetch was called with correct parameters
141- expect ( fetch ) . toHaveBeenCalledWith (
137+ expect ( agentRuntimeImpl . fetch ) . toHaveBeenCalledWith (
142138 'https://api.linkup.so/v1/search' ,
143139 expect . objectContaining ( {
144140 body : JSON . stringify ( {
@@ -151,48 +147,59 @@ describe('Linkup API', () => {
151147 } )
152148
153149 test ( 'should handle API errors gracefully' , async ( ) => {
154- spyOn ( global , 'fetch' ) . mockResolvedValue (
155- new Response ( 'Internal Server Error' , {
156- status : 500 ,
157- statusText : 'Internal Server Error' ,
158- } ) ,
159- )
150+ agentRuntimeImpl . fetch = mock ( ( ) => {
151+ return Promise . resolve (
152+ new Response ( 'Internal Server Error' , {
153+ status : 500 ,
154+ statusText : 'Internal Server Error' ,
155+ } ) ,
156+ )
157+ } ) as unknown as typeof global . fetch
160158
161- const result = await searchWeb ( { query : 'test query' , logger : mockLogger } )
159+ const result = await searchWeb ( { ... agentRuntimeImpl , query : 'test query' } )
162160
163161 expect ( result ) . toBeNull ( )
164162 } )
165163
166164 test ( 'should handle network errors' , async ( ) => {
167- spyOn ( global , 'fetch' ) . mockRejectedValue ( new Error ( 'Network error' ) )
165+ agentRuntimeImpl . fetch = mock ( ( ) => {
166+ return Promise . reject ( new Error ( 'Network error' ) )
167+ } ) as unknown as typeof global . fetch
168168
169- const result = await searchWeb ( { query : 'test query' , logger : mockLogger } )
169+ const result = await searchWeb ( { ... agentRuntimeImpl , query : 'test query' } )
170170
171171 expect ( result ) . toBeNull ( )
172172 } )
173173
174174 test ( 'should handle invalid response format' , async ( ) => {
175- spyOn ( global , 'fetch' ) . mockResolvedValue (
176- new Response ( JSON . stringify ( { invalid : 'format' } ) , {
177- status : 200 ,
178- headers : { 'Content-Type' : 'application/json' } ,
179- } ) ,
180- )
175+ agentRuntimeImpl . fetch = mock ( ( ) => {
176+ return Promise . resolve (
177+ new Response ( JSON . stringify ( { invalid : 'format' } ) , {
178+ status : 200 ,
179+ headers : { 'Content-Type' : 'application/json' } ,
180+ } ) ,
181+ )
182+ } ) as unknown as typeof global . fetch
181183
182- const result = await searchWeb ( { query : 'test query' , logger : mockLogger } )
184+ const result = await searchWeb ( { ... agentRuntimeImpl , query : 'test query' } )
183185
184186 expect ( result ) . toBeNull ( )
185187 } )
186188
187189 test ( 'should handle missing answer field' , async ( ) => {
188- spyOn ( global , 'fetch' ) . mockResolvedValue (
189- new Response ( JSON . stringify ( { sources : [ ] } ) , {
190- status : 200 ,
191- headers : { 'Content-Type' : 'application/json' } ,
192- } ) ,
193- )
190+ agentRuntimeImpl . fetch = mock ( ( ) => {
191+ return Promise . resolve (
192+ new Response ( JSON . stringify ( { sources : [ ] } ) , {
193+ status : 200 ,
194+ headers : { 'Content-Type' : 'application/json' } ,
195+ } ) ,
196+ )
197+ } ) as unknown as typeof global . fetch
194198
195- const result = await searchWeb ( { query : 'test query' , logger : mockLogger } )
199+ const result = await searchWeb ( {
200+ ...agentRuntimeImpl ,
201+ query : 'test query' ,
202+ } )
196203
197204 expect ( result ) . toBeNull ( )
198205 } )
@@ -202,14 +209,16 @@ describe('Linkup API', () => {
202209 sources : [ ] ,
203210 }
204211
205- spyOn ( global , 'fetch' ) . mockResolvedValue (
206- new Response ( JSON . stringify ( mockResponse ) , {
207- status : 200 ,
208- headers : { 'Content-Type' : 'application/json' } ,
209- } ) ,
210- )
212+ agentRuntimeImpl . fetch = mock ( ( ) => {
213+ return Promise . resolve (
214+ new Response ( JSON . stringify ( mockResponse ) , {
215+ status : 200 ,
216+ headers : { 'Content-Type' : 'application/json' } ,
217+ } ) ,
218+ )
219+ } ) as unknown as typeof global . fetch
211220
212- const result = await searchWeb ( { query : 'test query' , logger : mockLogger } )
221+ const result = await searchWeb ( { ... agentRuntimeImpl , query : 'test query' } )
213222
214223 expect ( result ) . toBeNull ( )
215224 } )
@@ -222,17 +231,19 @@ describe('Linkup API', () => {
222231 ] ,
223232 }
224233
225- spyOn ( global , 'fetch' ) . mockResolvedValue (
226- new Response ( JSON . stringify ( mockResponse ) , {
227- status : 200 ,
228- headers : { 'Content-Type' : 'application/json' } ,
229- } ) ,
230- )
234+ agentRuntimeImpl . fetch = mock ( ( ) => {
235+ return Promise . resolve (
236+ new Response ( JSON . stringify ( mockResponse ) , {
237+ status : 200 ,
238+ headers : { 'Content-Type' : 'application/json' } ,
239+ } ) ,
240+ )
241+ } ) as unknown as typeof global . fetch
231242
232- await searchWeb ( { query : 'test query' , logger : mockLogger } )
243+ await searchWeb ( { ... agentRuntimeImpl , query : 'test query' } )
233244
234245 // Verify fetch was called with default parameters
235- expect ( fetch ) . toHaveBeenCalledWith (
246+ expect ( agentRuntimeImpl . fetch ) . toHaveBeenCalledWith (
236247 'https://api.linkup.so/v1/search' ,
237248 expect . objectContaining ( {
238249 body : JSON . stringify ( {
@@ -245,39 +256,44 @@ describe('Linkup API', () => {
245256 } )
246257
247258 test ( 'should handle malformed JSON response' , async ( ) => {
248- spyOn ( global , 'fetch' ) . mockResolvedValue (
249- new Response ( 'invalid json{' , {
250- status : 200 ,
251- headers : { 'Content-Type' : 'application/json' } ,
252- } ) ,
253- )
259+ agentRuntimeImpl . fetch = mock ( ( ) => {
260+ return Promise . resolve (
261+ new Response ( 'invalid json{' , {
262+ status : 200 ,
263+ headers : { 'Content-Type' : 'application/json' } ,
264+ } ) ,
265+ )
266+ } ) as unknown as typeof global . fetch
267+ agentRuntimeImpl . logger . error = mock ( ( ) => { } )
254268
255- const result = await searchWeb ( { query : 'test query' , logger : mockLogger } )
269+ const result = await searchWeb ( { ... agentRuntimeImpl , query : 'test query' } )
256270
257271 expect ( result ) . toBeNull ( )
258272 // Verify that error logging was called
259- expect ( mockLogger . error ) . toHaveBeenCalled ( )
273+ expect ( agentRuntimeImpl . logger . error ) . toHaveBeenCalled ( )
260274 } )
261275
262276 test ( 'should log detailed error information for 404 responses' , async ( ) => {
263277 const mockErrorResponse =
264278 'Not Found - The requested endpoint does not exist'
265- spyOn ( global , 'fetch' ) . mockResolvedValue (
266- new Response ( mockErrorResponse , {
267- status : 404 ,
268- statusText : 'Not Found' ,
269- headers : { 'Content-Type' : 'text/plain' } ,
270- } ) ,
271- )
279+ agentRuntimeImpl . fetch = mock ( ( ) => {
280+ return Promise . resolve (
281+ new Response ( mockErrorResponse , {
282+ status : 404 ,
283+ statusText : 'Not Found' ,
284+ headers : { 'Content-Type' : 'text/plain' } ,
285+ } ) ,
286+ )
287+ } ) as unknown as typeof global . fetch
272288
273289 const result = await searchWeb ( {
290+ ...agentRuntimeImpl ,
274291 query : 'test query for 404' ,
275- logger : mockLogger ,
276292 } )
277293
278294 expect ( result ) . toBeNull ( )
279295 // Verify that detailed error logging was called with 404 info
280- expect ( mockLogger . error ) . toHaveBeenCalledWith (
296+ expect ( agentRuntimeImpl . logger . error ) . toHaveBeenCalledWith (
281297 expect . objectContaining ( {
282298 status : 404 ,
283299 statusText : 'Not Found' ,
0 commit comments