Skip to main content
Glama

MkDocs MCP Search Server

fetch-doc.spec.ts4.65 kB
/** * Simplified test approach for docFetcher * * This test uses direct mocking of the module's dependencies * rather than trying to mock the underlying libraries. */ // Mock the modules before importing anything // Now import the modules import { fetchService } from './services/fetch'; import { ContentType } from './services/fetch/types'; import { clearDocCache, fetchDocPage } from './fetch-doc'; import * as cacache from 'cacache'; jest.mock('./services/fetch', () => ({ fetchService: { fetch: jest.fn(), clearCache: jest.fn() } })); // Mock cacache directly with a simple implementation jest.mock('cacache', () => ({ get: jest.fn().mockImplementation(() => Promise.resolve({ data: Buffer.from('cached content'), metadata: {} })), put: jest.fn().mockResolvedValue(), rm: { all: jest.fn().mockResolvedValue() } })); // Mock crypto jest.mock('crypto', () => ({ createHash: jest.fn().mockReturnValue({ update: jest.fn().mockReturnThis(), digest: jest.fn().mockReturnValue('mocked-hash') }) })); // Create a simple mock for Headers class MockHeaders { private headers: Record<string, string> = {}; constructor(init?: Record<string, string>) { if (init) { this.headers = { ...init }; } } get(name: string): string | null { return this.headers[name.toLowerCase()] || null; } has(name: string): boolean { return name.toLowerCase() in this.headers; } } describe('[DocFetcher] When fetching documentation pages', () => { beforeEach(() => { jest.clearAllMocks(); }); it('should fetch a page and convert it to markdown', async () => { // Arrange const mockHtml = ` <html> <body> <div class="md-content" data-md-component="content"> <h1>Test Heading</h1> <p>Test paragraph</p> </div> </body> </html> `; (fetchService.fetch as jest.Mock).mockResolvedValueOnce({ ok: true, status: 200, statusText: 'OK', headers: new MockHeaders({ 'etag': 'abc123' }), text: jest.fn().mockResolvedValueOnce(mockHtml) }); // Mock cacache.get.info to throw ENOENT (cache miss) (cacache.get as any).info = jest.fn().mockRejectedValueOnce(new Error('ENOENT')); // Act const url = 'https://example.com/latest/core/logger/'; const result = await fetchDocPage(url); // Assert expect(fetchService.fetch).toHaveBeenCalledWith(url, expect.any(Object)); expect(result).toContain('# Test Heading'); expect(result).toContain('Test paragraph'); }); it('should reject invalid URLs', async () => { // Mock isValidUrl to return false for this test jest.spyOn(global, 'URL').mockImplementationOnce(() => { throw new Error('Invalid URL'); }); // Mock fetchService.fetch to return a mock response const fetchMock = fetchService.fetch as jest.Mock; fetchMock.mockClear(); // Act const url = 'invalid://example.com/not-allowed'; const result = await fetchDocPage(url); // Assert expect(result).toContain('Error fetching documentation'); // Just check for any error message, not specifically "Invalid URL" expect(result).toMatch(/Error/); }); it('should handle fetch errors gracefully', async () => { // Arrange (fetchService.fetch as jest.Mock).mockRejectedValueOnce(new Error('Network error')); // Act const url = 'https://example.com/latest/core/logger/'; const result = await fetchDocPage(url); // Assert expect(result).toContain('Error fetching documentation'); expect(result).toContain('Network error'); }); it('should handle non-200 responses gracefully', async () => { // Arrange (fetchService.fetch as jest.Mock).mockResolvedValueOnce({ ok: false, status: 404, statusText: 'Not Found', headers: new MockHeaders() }); // Act const url = 'https://example.com/latest/core/nonexistent/'; const result = await fetchDocPage(url); // Assert expect(result).toContain('Error fetching documentation'); expect(result).toContain('Failed to fetch page: 404 Not Found'); }); }); describe('[DocFetcher] When clearing the cache', () => { beforeEach(() => { jest.clearAllMocks(); }); it('should clear both web page and markdown caches', async () => { // Act await clearDocCache(); // Assert expect(fetchService.clearCache).toHaveBeenCalledWith(ContentType.WEB_PAGE); expect(cacache.rm.all).toHaveBeenCalledWith(expect.stringContaining('markdown-cache')); }); });

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/serverless-dna/mkdocs-mcp'

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