Skip to main content
Glama

Grove's MCP Server for Pocket Network

docs-manager.test.ts8.85 kB
import { describe, it, expect, beforeEach, vi } from 'vitest'; import { DocsManager } from '../docs-manager.js'; import type { ServerConfig } from '../../types.js'; describe('DocsManager', () => { let docsManager: DocsManager; let mockConfig: ServerConfig; beforeEach(() => { mockConfig = { baseUrls: { endpoints: 'https://api.example.com', docs: 'https://docs.example.com', }, categories: [], endpoints: [], }; docsManager = new DocsManager(mockConfig); vi.restoreAllMocks(); }); describe('getDocPage', () => { it('should fetch documentation page successfully', async () => { const mockContent = ` <html> <head><title>API Documentation</title></head> <body><h1>Welcome</h1></body> </html> `; global.fetch = vi.fn().mockResolvedValue({ ok: true, text: async () => mockContent, headers: { get: (key: string) => key === 'last-modified' ? '2024-01-01' : null, }, }); const result = await docsManager.getDocPage('/getting-started'); expect(result).not.toBeNull(); expect(result?.title).toBe('API Documentation'); expect(result?.content).toContain('Welcome'); expect(result?.url).toContain('/getting-started'); expect(result?.lastUpdated).toBe('2024-01-01'); }); it('should extract title from markdown heading', async () => { const mockContent = '# Getting Started\n\nThis is the content.'; global.fetch = vi.fn().mockResolvedValue({ ok: true, text: async () => mockContent, headers: { get: () => null, }, }); const result = await docsManager.getDocPage('/guide'); expect(result?.title).toBe('Getting Started'); }); it('should extract title from h1 tag', async () => { const mockContent = '<h1>Main Title</h1><p>Content</p>'; global.fetch = vi.fn().mockResolvedValue({ ok: true, text: async () => mockContent, headers: { get: () => null, }, }); const result = await docsManager.getDocPage('/page'); expect(result?.title).toBe('Main Title'); }); it('should handle h1 tag with HTML content', async () => { const mockContent = '<h1><span class="icon">📖</span> Documentation</h1>'; global.fetch = vi.fn().mockResolvedValue({ ok: true, text: async () => mockContent, headers: { get: () => null, }, }); const result = await docsManager.getDocPage('/page'); expect(result?.title).toContain('Documentation'); }); it('should use "Untitled" when no title found', async () => { const mockContent = '<p>Just some content</p>'; global.fetch = vi.fn().mockResolvedValue({ ok: true, text: async () => mockContent, headers: { get: () => null, }, }); const result = await docsManager.getDocPage('/page'); expect(result?.title).toBe('Untitled'); }); it('should handle paths without leading slash', async () => { global.fetch = vi.fn().mockResolvedValue({ ok: true, text: async () => '<h1>Test</h1>', headers: { get: () => null, }, }); await docsManager.getDocPage('no-slash'); expect(global.fetch).toHaveBeenCalledWith( 'https://docs.example.com/no-slash' ); }); it('should handle paths with leading slash', async () => { global.fetch = vi.fn().mockResolvedValue({ ok: true, text: async () => '<h1>Test</h1>', headers: { get: () => null, }, }); await docsManager.getDocPage('/with-slash'); expect(global.fetch).toHaveBeenCalledWith( 'https://docs.example.com/with-slash' ); }); it('should return null on 404 error', async () => { global.fetch = vi.fn().mockResolvedValue({ ok: false, status: 404, }); const result = await docsManager.getDocPage('/nonexistent'); expect(result).toBeNull(); }); it('should return null on network error', async () => { global.fetch = vi.fn().mockRejectedValue(new Error('Network error')); const result = await docsManager.getDocPage('/error'); expect(result).toBeNull(); }); }); describe('searchDocs', () => { it('should find matching documentation pages', async () => { const pages = [ { path: '/intro', content: '# Introduction\nLearn about our API' }, { path: '/auth', content: '# Authentication\nHow to authenticate' }, { path: '/webhooks', content: '# Webhooks\nWebhook configuration' }, ]; let callCount = 0; global.fetch = vi.fn().mockImplementation(() => { const page = pages[callCount++]; return Promise.resolve({ ok: true, text: async () => page.content, headers: { get: () => null, }, }); }); const results = await docsManager.searchDocs('authentication', [ '/intro', '/auth', '/webhooks', ]); expect(results).toHaveLength(1); expect(results[0].title).toBe('Authentication'); }); it('should search in title and content', async () => { global.fetch = vi.fn().mockResolvedValue({ ok: true, text: async () => '# API Guide\nThis document covers webhooks', headers: { get: () => null, }, }); const results = await docsManager.searchDocs('webhooks', ['/guide']); expect(results).toHaveLength(1); }); it('should be case insensitive', async () => { global.fetch = vi.fn().mockResolvedValue({ ok: true, text: async () => '# Guide\nContent about AUTHENTICATION', headers: { get: () => null, }, }); const results = await docsManager.searchDocs('authentication', ['/guide']); expect(results).toHaveLength(1); }); it('should return empty array when no matches', async () => { global.fetch = vi.fn().mockResolvedValue({ ok: true, text: async () => '# Guide\nSome other content', headers: { get: () => null, }, }); const results = await docsManager.searchDocs('nonexistent', ['/guide']); expect(results).toHaveLength(0); }); it('should skip pages that fail to load', async () => { let callCount = 0; global.fetch = vi.fn().mockImplementation(() => { if (callCount++ === 0) { return Promise.resolve({ ok: false, status: 404, }); } return Promise.resolve({ ok: true, text: async () => '# Valid Page\nContains search term', headers: { get: () => null, }, }); }); const results = await docsManager.searchDocs('search term', [ '/error', '/valid', ]); expect(results).toHaveLength(1); expect(results[0].title).toBe('Valid Page'); }); it('should search default path when none provided', async () => { global.fetch = vi.fn().mockResolvedValue({ ok: true, text: async () => '# Home\nWelcome', headers: { get: () => null, }, }); const results = await docsManager.searchDocs('welcome'); expect(results).toHaveLength(1); }); }); describe('getEndpointDocs', () => { it('should fetch endpoint documentation', async () => { global.fetch = vi.fn().mockResolvedValue({ ok: true, text: async () => '# Get Balance\nReturns wallet balance', headers: { get: () => null, }, }); const result = await docsManager.getEndpointDocs('get-balance'); expect(result).not.toBeNull(); expect(result?.title).toBe('Get Balance'); expect(global.fetch).toHaveBeenCalledWith( 'https://docs.example.com/endpoints/get-balance' ); }); it('should return null for non-existent endpoint docs', async () => { global.fetch = vi.fn().mockResolvedValue({ ok: false, status: 404, }); const result = await docsManager.getEndpointDocs('nonexistent'); expect(result).toBeNull(); }); it('should construct correct path for endpoint docs', async () => { global.fetch = vi.fn().mockResolvedValue({ ok: true, text: async () => '# Docs', headers: { get: () => null, }, }); await docsManager.getEndpointDocs('create-webhook'); expect(global.fetch).toHaveBeenCalledWith( expect.stringContaining('/endpoints/create-webhook') ); }); }); });

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/buildwithgrove/mcp-pocket'

If you have feedback or need assistance with the MCP directory API, please join our Discord server