Skip to main content
Glama
docs-fetcher.integration.test.ts•6.12 kB
import { afterEach, beforeEach, describe, expect, it, mock } from "bun:test" import { createDocsFetcher } from "../../../src/docs-fetcher.js" describe("DocsFetcher", () => { let fetcher: ReturnType<typeof createDocsFetcher> beforeEach(() => { fetcher = createDocsFetcher({ cacheTtl: 1000, maxCacheSize: 10, requestTimeout: 5000 }) }) afterEach(() => { fetcher.close() }) describe("buildJsonUrl", () => { it("should build correct URL with defaults", async () => { // Mock fetch to capture the URL const originalFetch = global.fetch let capturedUrl = "" global.fetch = mock((url: string | URL | Request) => { if (typeof url === "string") { capturedUrl = url } else if (url instanceof URL) { capturedUrl = url.toString() } else { capturedUrl = url.url } return Promise.resolve({ status: 404, ok: false, headers: new Headers(), json: () => Promise.resolve({}) } as Response) }) as unknown as typeof fetch try { await fetcher.fetchCrateJson("test-crate") } catch {} expect(capturedUrl).toBe("https://docs.rs/crate/test-crate/latest/json") global.fetch = originalFetch }) it("should build URL with version", async () => { const originalFetch = global.fetch let capturedUrl = "" global.fetch = mock((url: string | URL | Request) => { if (typeof url === "string") { capturedUrl = url } else if (url instanceof URL) { capturedUrl = url.toString() } else { capturedUrl = url.url } return Promise.resolve({ status: 404, ok: false, headers: new Headers(), json: () => Promise.resolve({}) } as Response) }) as unknown as typeof fetch try { await fetcher.fetchCrateJson("test-crate", "1.0.0") } catch {} expect(capturedUrl).toBe("https://docs.rs/crate/test-crate/1.0.0/json") global.fetch = originalFetch }) it("should build URL with target", async () => { const originalFetch = global.fetch let capturedUrl = "" global.fetch = mock((url: string | URL | Request) => { if (typeof url === "string") { capturedUrl = url } else if (url instanceof URL) { capturedUrl = url.toString() } else { capturedUrl = url.url } return Promise.resolve({ status: 404, ok: false, headers: new Headers(), json: () => Promise.resolve({}) } as Response) }) as unknown as typeof fetch try { await fetcher.fetchCrateJson("test-crate", "1.0.0", "x86_64-pc-windows-msvc") } catch {} expect(capturedUrl).toBe( "https://docs.rs/crate/test-crate/1.0.0/x86_64-pc-windows-msvc/json" ) global.fetch = originalFetch }) }) describe("fetchCrateJson", () => { it("should handle 404 errors", () => { const originalFetch = global.fetch global.fetch = mock(() => { return Promise.resolve({ status: 404, ok: false, headers: new Headers(), json: () => Promise.resolve({}) } as Response) }) as unknown as typeof fetch expect(fetcher.fetchCrateJson("non-existent-crate")).rejects.toThrow( /Crate 'non-existent-crate' not found/ ) global.fetch = originalFetch }) it("should handle timeouts", () => { const originalFetch = global.fetch global.fetch = mock(() => { return new Promise((_, reject) => { setTimeout(() => { const error = new Error("Aborted") error.name = "AbortError" reject(error) }, 100) }) }) as unknown as typeof fetch const quickFetcher = createDocsFetcher({ requestTimeout: 50 }) expect(quickFetcher.fetchCrateJson("test-crate")).rejects.toThrow( /Request timeout after 50ms/ ) quickFetcher.close() global.fetch = originalFetch }) it("should cache successful responses", async () => { const originalFetch = global.fetch let fetchCount = 0 const testData = { test: "data", format_version: 30 } global.fetch = mock(() => { fetchCount++ return Promise.resolve({ status: 200, ok: true, headers: new Headers(), json: () => Promise.resolve(testData), text: () => Promise.resolve(JSON.stringify(testData)), bodyUsed: false } as Response) }) as unknown as typeof fetch // First call should fetch const result1 = await fetcher.fetchCrateJson("test-crate") expect(result1.data).toEqual(testData) expect(result1.fromCache).toBe(false) expect(fetchCount).toBe(1) // Second call should use cache const result2 = await fetcher.fetchCrateJson("test-crate") expect(result2.data).toEqual(testData) expect(result2.fromCache).toBe(true) expect(fetchCount).toBe(1) // No additional fetch global.fetch = originalFetch }) it("should handle normal JSON responses", async () => { const originalFetch = global.fetch const testData = { test: "uncompressed", format_version: 30 } global.fetch = mock(() => { return Promise.resolve({ status: 200, ok: true, headers: new Headers(), bodyUsed: false, json: () => Promise.resolve(testData), text: () => Promise.resolve(JSON.stringify(testData)) } as Response) }) as unknown as typeof fetch const result = await fetcher.fetchCrateJson("test-crate") expect(result.data).toEqual(testData) expect(result.fromCache).toBe(false) global.fetch = originalFetch }) }) describe("cache operations", () => { it("should clear cache", async () => { const originalFetch = global.fetch let fetchCount = 0 const testData = { test: "data" } global.fetch = mock(() => { fetchCount++ return Promise.resolve({ status: 200, ok: true, headers: new Headers(), json: () => Promise.resolve(testData), text: () => Promise.resolve(JSON.stringify(testData)) } as Response) }) as unknown as typeof fetch // First fetch await fetcher.fetchCrateJson("test-crate") expect(fetchCount).toBe(1) // Clear cache fetcher.clearCache() // Should fetch again await fetcher.fetchCrateJson("test-crate") expect(fetchCount).toBe(2) global.fetch = originalFetch }) }) })

Latest Blog Posts

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/vexxvakan/mcp-docsrs'

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