Skip to content

Commit 9146389

Browse files
committed
get_page_content tests
1 parent 252f631 commit 9146389

File tree

1 file changed

+131
-0
lines changed

1 file changed

+131
-0
lines changed

src/app/api/[transport]/route.test.ts

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -301,4 +301,135 @@ Content with <special> characters & symbols.
301301
expect(fullUrl).toBe(baseUrl)
302302
})
303303
})
304+
305+
describe('get_page_content Tool', () => {
306+
it('should retrieve page content successfully', async () => {
307+
const { GET } = await import('./route')
308+
const mockRequest = new Request('https://docs.pmnd.rs/api/sse', {
309+
method: 'POST',
310+
headers: {
311+
'Content-Type': 'application/json',
312+
},
313+
body: JSON.stringify({
314+
jsonrpc: '2.0',
315+
id: 1,
316+
method: 'tools/call',
317+
params: {
318+
name: 'get_page_content',
319+
arguments: {
320+
lib: 'react-three-fiber',
321+
path: '/api/hooks/use-frame',
322+
},
323+
},
324+
}),
325+
})
326+
327+
const response = await GET(mockRequest)
328+
expect(response).toBeDefined()
329+
})
330+
331+
it('should return error when page not found', async () => {
332+
const cheerio = await import('cheerio')
333+
const $ = cheerio.load(mockLlmsFullTxt, { xmlMode: true })
334+
335+
const nonExistentPath = '/non-existent-page'
336+
const page = $('page').filter((_, el) => $(el).attr('path') === nonExistentPath)
337+
338+
expect(page.length).toBe(0)
339+
})
340+
341+
it('should extract correct content for valid page', async () => {
342+
const cheerio = await import('cheerio')
343+
const $ = cheerio.load(mockLlmsFullTxt, { xmlMode: true })
344+
345+
const targetPath = '/api/hooks/use-frame'
346+
const page = $('page').filter((_, el) => $(el).attr('path') === targetPath)
347+
348+
expect(page.length).toBe(1)
349+
const content = page.text().trim()
350+
expect(content).toContain('useFrame Hook')
351+
expect(content).toContain('execute code on every frame')
352+
})
353+
354+
it('should handle multiple libraries correctly', async () => {
355+
const libs = {
356+
'react-three-fiber': { docs_url: 'https://r3f.docs.pmnd.rs' },
357+
zustand: { docs_url: 'https://zustand.docs.pmnd.rs' },
358+
}
359+
360+
const libNames = Object.keys(libs)
361+
expect(libNames).toContain('react-three-fiber')
362+
expect(libNames).toContain('zustand')
363+
})
364+
365+
it('should validate lib parameter is enum', async () => {
366+
const { z } = await import('zod')
367+
const validLibs = ['react-three-fiber', 'zustand']
368+
const libSchema = z.enum(validLibs as [string, ...string[]])
369+
370+
expect(() => libSchema.parse('react-three-fiber')).not.toThrow()
371+
expect(() => libSchema.parse('invalid-library')).toThrow()
372+
})
373+
374+
it('should validate path parameter is string', async () => {
375+
const { z } = await import('zod')
376+
const pathSchema = z.string()
377+
378+
expect(() => pathSchema.parse('/api/hooks/use-frame')).not.toThrow()
379+
expect(() => pathSchema.parse(123)).toThrow()
380+
})
381+
382+
it('should format tool response correctly', async () => {
383+
const cheerio = await import('cheerio')
384+
const $ = cheerio.load(mockLlmsFullTxt, { xmlMode: true })
385+
386+
const page = $('page').filter((_, el) => $(el).attr('path') === '/getting-started')
387+
const content = page.text().trim()
388+
389+
const expectedResponse = {
390+
content: [
391+
{
392+
type: 'text',
393+
text: content,
394+
},
395+
],
396+
}
397+
398+
expect(expectedResponse.content).toHaveLength(1)
399+
expect(expectedResponse.content[0].type).toBe('text')
400+
expect(expectedResponse.content[0].text).toContain('Getting Started')
401+
})
402+
403+
it('should handle fetch errors in tool execution', async () => {
404+
server.use(
405+
http.get('https://error.docs.pmnd.rs/llms-full.txt', () => {
406+
return HttpResponse.error()
407+
}),
408+
)
409+
410+
await expect(fetch('https://error.docs.pmnd.rs/llms-full.txt')).rejects.toThrow()
411+
})
412+
413+
it('should handle 404 errors in tool execution', async () => {
414+
server.use(
415+
http.get('https://notfound.docs.pmnd.rs/llms-full.txt', () => {
416+
return new HttpResponse(null, { status: 404, statusText: 'Not Found' })
417+
}),
418+
)
419+
420+
const response = await fetch('https://notfound.docs.pmnd.rs/llms-full.txt')
421+
expect(response.ok).toBe(false)
422+
expect(response.status).toBe(404)
423+
})
424+
425+
it('should prevent CSS selector injection in tool', async () => {
426+
const cheerio = await import('cheerio')
427+
const $ = cheerio.load(mockLlmsFullTxt, { xmlMode: true })
428+
429+
const maliciousPath = '/getting-started[data-test="hack"]'
430+
const page = $('page').filter((_, el) => $(el).attr('path') === maliciousPath)
431+
432+
expect(page.length).toBe(0)
433+
})
434+
})
304435
})

0 commit comments

Comments
 (0)