Skip to main content
Glama
github-activity-enhanced.test.ts11.2 kB
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; import { registerGitHubActivityTool } from "../tools/github-activity"; // Mock fetch globally const mockFetch = jest.fn(); global.fetch = mockFetch; // Mock the McpServer const mockServer = { registerTool: jest.fn(), } as unknown as McpServer; // Helper to create mock response const createMockResponse = (data: unknown, ok = true, status = 200) => ({ ok, status, statusText: ok ? "OK" : "Not Found", json: jest.fn().mockResolvedValue(data), }); describe("GitHub Activity Tool Enhanced Tests", () => { beforeEach(() => { jest.clearAllMocks(); }); test("should register github-activity tool with all parameters", () => { registerGitHubActivityTool(mockServer); expect(mockServer.registerTool).toHaveBeenCalledWith( "github_activity", expect.objectContaining({ title: "GitHub Activity", description: expect.stringContaining( "Get Duyet's recent GitHub activity", ), inputSchema: expect.objectContaining({ limit: expect.any(Object), include_details: expect.any(Object), }), }), expect.any(Function), ); }); test("should handle WatchEvent type", async () => { const mockEvents = [ { type: "WatchEvent", created_at: "2024-01-01T00:00:00Z", repo: { name: "duyet/test-repo" }, payload: {}, }, ]; mockFetch.mockResolvedValue(createMockResponse(mockEvents)); let toolHandler: any; (mockServer.registerTool as jest.Mock).mockImplementation( (name, _config, handler) => { if (name === "github_activity") { toolHandler = handler; } }, ); registerGitHubActivityTool(mockServer); const result = await toolHandler({ limit: 5, include_details: false }); expect(result.content[0].text).toContain("Starred repository"); expect(result.content[0].text).toContain("duyet/test-repo"); }); test("should handle ForkEvent type", async () => { const mockEvents = [ { type: "ForkEvent", created_at: "2024-01-01T00:00:00Z", repo: { name: "duyet/test-repo" }, payload: {}, }, ]; mockFetch.mockResolvedValue(createMockResponse(mockEvents)); let toolHandler: any; (mockServer.registerTool as jest.Mock).mockImplementation( (name, _config, handler) => { if (name === "github_activity") { toolHandler = handler; } }, ); registerGitHubActivityTool(mockServer); const result = await toolHandler({ limit: 5, include_details: false }); expect(result.content[0].text).toContain("Forked repository"); expect(result.content[0].text).toContain("duyet/test-repo"); }); test("should handle ReleaseEvent type", async () => { const mockEvents = [ { type: "ReleaseEvent", created_at: "2024-01-01T00:00:00Z", repo: { name: "duyet/test-repo" }, payload: { action: "published", release: { tag_name: "v1.0.0", name: "Version 1.0.0", }, }, }, ]; mockFetch.mockResolvedValue(createMockResponse(mockEvents)); let toolHandler: any; (mockServer.registerTool as jest.Mock).mockImplementation( (name, _config, handler) => { if (name === "github_activity") { toolHandler = handler; } }, ); registerGitHubActivityTool(mockServer); const result = await toolHandler({ limit: 5, include_details: true }); expect(result.content[0].text).toContain("published release"); expect(result.content[0].text).toContain("v1.0.0: Version 1.0.0"); }); test("should handle ReleaseEvent without payload", async () => { const mockEvents = [ { type: "ReleaseEvent", created_at: "2024-01-01T00:00:00Z", repo: { name: "duyet/test-repo" }, payload: {}, }, ]; mockFetch.mockResolvedValue(createMockResponse(mockEvents)); let toolHandler: any; (mockServer.registerTool as jest.Mock).mockImplementation( (name, _config, handler) => { if (name === "github_activity") { toolHandler = handler; } }, ); registerGitHubActivityTool(mockServer); const result = await toolHandler({ limit: 5, include_details: false }); expect(result.content[0].text).toContain("created release"); }); test("should handle CreateEvent without ref", async () => { const mockEvents = [ { type: "CreateEvent", created_at: "2024-01-01T00:00:00Z", repo: { name: "duyet/test-repo" }, payload: { ref_type: "repository" }, }, ]; mockFetch.mockResolvedValue(createMockResponse(mockEvents)); let toolHandler: any; (mockServer.registerTool as jest.Mock).mockImplementation( (name, _config, handler) => { if (name === "github_activity") { toolHandler = handler; } }, ); registerGitHubActivityTool(mockServer); const result = await toolHandler({ limit: 5, include_details: false }); expect(result.content[0].text).toContain("Created repository"); }); test("should handle PushEvent without commits", async () => { const mockEvents = [ { type: "PushEvent", created_at: "2024-01-01T00:00:00Z", repo: { name: "duyet/test-repo" }, payload: { commits: [] }, }, ]; mockFetch.mockResolvedValue(createMockResponse(mockEvents)); let toolHandler: any; (mockServer.registerTool as jest.Mock).mockImplementation( (name, _config, handler) => { if (name === "github_activity") { toolHandler = handler; } }, ); registerGitHubActivityTool(mockServer); const result = await toolHandler({ limit: 5, include_details: false }); expect(result.content[0].text).toContain("Pushed 0 commit"); }); test("should handle missing payloads gracefully", async () => { const mockEvents = [ { type: "IssuesEvent", created_at: "2024-01-01T00:00:00Z", repo: { name: "duyet/test-repo" }, payload: {}, }, { type: "PullRequestEvent", created_at: "2024-01-01T00:00:00Z", repo: { name: "duyet/test-repo" }, payload: {}, }, ]; mockFetch.mockResolvedValue(createMockResponse(mockEvents)); let toolHandler: any; (mockServer.registerTool as jest.Mock).mockImplementation( (name, _config, handler) => { if (name === "github_activity") { toolHandler = handler; } }, ); registerGitHubActivityTool(mockServer); const result = await toolHandler({ limit: 5, include_details: false }); expect(result.content[0].text).toContain("updated issue"); expect(result.content[0].text).toContain("updated pull request"); }); test("should handle GitHub API error", async () => { mockFetch.mockResolvedValue(createMockResponse(null, false, 404)); let toolHandler: any; (mockServer.registerTool as jest.Mock).mockImplementation( (name, _config, handler) => { if (name === "github_activity") { toolHandler = handler; } }, ); registerGitHubActivityTool(mockServer); const result = await toolHandler({ limit: 5, include_details: false }); expect(result.content[0].text).toContain("Error fetching GitHub activity"); expect(result.content[0].text).toContain("404"); }); test("should handle empty events array", async () => { mockFetch.mockResolvedValue(createMockResponse([])); let toolHandler: any; (mockServer.registerTool as jest.Mock).mockImplementation( (name, _config, handler) => { if (name === "github_activity") { toolHandler = handler; } }, ); registerGitHubActivityTool(mockServer); const result = await toolHandler({ limit: 5, include_details: false }); expect(result.content[0].text).toContain("No recent GitHub activity found"); }); test("should limit results correctly", async () => { const mockEvents = Array.from({ length: 20 }, (_, i) => ({ type: "PushEvent", created_at: `2024-01-${String(i + 1).padStart(2, "0")}T00:00:00Z`, repo: { name: `duyet/test-repo-${i}` }, payload: { commits: [{ message: `Commit ${i}` }] }, })); mockFetch.mockResolvedValue(createMockResponse(mockEvents)); let toolHandler: any; (mockServer.registerTool as jest.Mock).mockImplementation( (name, _config, handler) => { if (name === "github_activity") { toolHandler = handler; } }, ); registerGitHubActivityTool(mockServer); await toolHandler({ limit: 25, include_details: false }); // Should limit to 20 max - check the URL was called with per_page=20 expect(mockFetch).toHaveBeenCalledWith( expect.stringContaining("per_page=20"), expect.any(Object), ); }); test("should handle invalid limit parameter", async () => { const mockEvents = [ { type: "PushEvent", created_at: "2024-01-01T00:00:00Z", repo: { name: "duyet/test-repo" }, payload: { commits: [] }, }, ]; mockFetch.mockResolvedValue(createMockResponse(mockEvents)); let toolHandler: any; (mockServer.registerTool as jest.Mock).mockImplementation( (name, _config, handler) => { if (name === "github_activity") { toolHandler = handler; } }, ); registerGitHubActivityTool(mockServer); const result = await toolHandler({ include_details: false }); // Test default value // Should default to 5 expect(mockFetch).toHaveBeenCalledWith( expect.stringContaining("per_page=5"), expect.any(Object), ); expect(result.content[0].text).toContain("Recent GitHub Activity"); }); test("should handle unknown event types", async () => { const mockEvents = [ { type: "UnknownEvent", created_at: "2024-01-01T00:00:00Z", repo: { name: "duyet/test-repo" }, payload: {}, }, ]; mockFetch.mockResolvedValue(createMockResponse(mockEvents)); let toolHandler: any; (mockServer.registerTool as jest.Mock).mockImplementation( (name, _config, handler) => { if (name === "github_activity") { toolHandler = handler; } }, ); registerGitHubActivityTool(mockServer); const result = await toolHandler({ limit: 5, include_details: false }); expect(result.content[0].text).toContain("Unknown"); }); test("should handle network error", async () => { mockFetch.mockRejectedValue(new Error("Network error")); let toolHandler: any; (mockServer.registerTool as jest.Mock).mockImplementation( (name, _config, handler) => { if (name === "github_activity") { toolHandler = handler; } }, ); registerGitHubActivityTool(mockServer); const result = await toolHandler({ limit: 5, include_details: false }); expect(result.content[0].text).toContain("Error fetching GitHub activity"); }); });

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/duyet/duyet-mcp-server'

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