Skip to main content
Glama

Perplexity MCP Server

server.test.ts11.5 kB
import { describe, expect, it, vi } from "vitest"; import { PerplexityServer } from "../../server/PerplexityServer.js"; import type { IBrowserManager, IDatabaseManager, ISearchEngine } from "../../types/index.js"; // Mock the modules to avoid actual browser initialization and database connections vi.mock("../../server/modules/BrowserManager.js", () => { return { BrowserManager: vi.fn().mockImplementation(() => ({ initialize: vi.fn().mockResolvedValue(undefined), isReady: vi.fn().mockReturnValue(true), cleanup: vi.fn().mockResolvedValue(undefined), getPuppeteerContext: vi.fn().mockReturnValue({ browser: null, page: null, isInitializing: false, searchInputSelector: 'textarea[placeholder*="Ask"]', lastSearchTime: 0, idleTimeout: null, operationCount: 0, log: vi.fn(), setBrowser: vi.fn(), setPage: vi.fn(), setIsInitializing: vi.fn(), setSearchInputSelector: vi.fn(), setIdleTimeout: vi.fn(), incrementOperationCount: vi.fn(), determineRecoveryLevel: vi.fn(), IDLE_TIMEOUT_MS: 300000, }), })), }; }); vi.mock("../../server/modules/DatabaseManager.js", () => { return { DatabaseManager: vi.fn().mockImplementation(() => ({ initialize: vi.fn(), close: vi.fn(), getChatHistory: vi.fn().mockReturnValue([]), saveChatMessage: vi.fn(), isInitialized: vi.fn().mockReturnValue(true), })), }; }); vi.mock("../../server/modules/SearchEngine.js", () => { return { SearchEngine: vi.fn().mockImplementation(() => ({ performSearch: vi.fn().mockResolvedValue("Mock search result"), })), }; }); // Mock logging vi.mock("../../utils/logging.js", () => ({ logInfo: vi.fn(), logWarn: vi.fn(), logError: vi.fn(), })); describe("MCP Server Integration", () => { describe("Server initialization", () => { it("should initialize server components successfully", () => { const server = new PerplexityServer(); expect(server).toBeDefined(); expect(server.getBrowserManager()).toBeDefined(); expect(server.getSearchEngine()).toBeDefined(); expect(server.getDatabaseManager()).toBeDefined(); }); it("should initialize server with custom dependencies", () => { // Mock dependencies const mockBrowserManager: IBrowserManager = { initialize: vi.fn().mockResolvedValue(undefined), navigateToPerplexity: vi.fn().mockResolvedValue(undefined), waitForSearchInput: vi.fn().mockResolvedValue("textarea"), checkForCaptcha: vi.fn().mockResolvedValue(false), performRecovery: vi.fn().mockResolvedValue(undefined), isReady: vi.fn().mockReturnValue(true), cleanup: vi.fn().mockResolvedValue(undefined), getPage: vi.fn().mockReturnValue(null), getBrowser: vi.fn().mockReturnValue(null), resetIdleTimeout: vi.fn(), getPuppeteerContext: vi.fn().mockReturnValue({}), }; const mockSearchEngine: ISearchEngine = { performSearch: vi.fn().mockResolvedValue("Custom search result"), }; const mockDatabaseManager: IDatabaseManager = { initialize: vi.fn(), close: vi.fn(), getChatHistory: vi.fn().mockReturnValue([]), saveChatMessage: vi.fn(), isInitialized: vi.fn().mockReturnValue(true), }; const dependencies = { browserManager: mockBrowserManager, searchEngine: mockSearchEngine, databaseManager: mockDatabaseManager, }; const server = new PerplexityServer(dependencies); expect(server).toBeDefined(); expect(mockDatabaseManager.initialize).toHaveBeenCalled(); }); it("should initialize database during server startup", () => { const server = new PerplexityServer(); const databaseManager = server.getDatabaseManager(); // Since we mocked the DatabaseManager, we can check if initialize was called expect(databaseManager.initialize).toHaveBeenCalled(); }); }); describe("Tool registration", () => { it("should register all required tools", () => { const server = new PerplexityServer(); // We can't directly access the tool handlers, but we can verify the server was created expect(server).toBeDefined(); // Check that we have the expected number of tool handlers const requiredTools = [ "chat_perplexity", "search", "extract_url_content", "get_documentation", "find_apis", "check_deprecated_code", ]; expect(requiredTools.length).toBe(6); }); it("should verify all 6 tools are properly registered", () => { const server = new PerplexityServer(); // Verify the server was created successfully expect(server).toBeDefined(); // Check that all required tools are accounted for const requiredTools = [ "chat_perplexity", "search", "extract_url_content", "get_documentation", "find_apis", "check_deprecated_code", ]; // Test that all tools are present in our list requiredTools.forEach((tool) => { expect(requiredTools).toContain(tool); }); }); it("should handle dynamic tool handler registration", () => { // Test that the server can be instantiated and tool handlers are set up const server = new PerplexityServer(); expect(server).toBeDefined(); // The setupToolHandlers method is called in the constructor // We can't directly test the registration without exposing internals, // but we can verify the server was created successfully }); }); describe("End-to-end workflows", () => { it("should handle basic search workflow", async () => { const server = new PerplexityServer(); const searchEngine = server.getSearchEngine(); // Mock the search engine to return a specific result vi.mocked(searchEngine.performSearch).mockResolvedValue("Test search result"); const result = await searchEngine.performSearch("test query"); expect(result).toBe("Test search result"); expect(searchEngine.performSearch).toHaveBeenCalledWith("test query"); }); it("should handle complete chat flow from request to response", async () => { const server = new PerplexityServer(); const searchEngine = server.getSearchEngine(); // Mock the search engine to return a specific result vi.mocked(searchEngine.performSearch).mockResolvedValue("Chat response"); const result = await searchEngine.performSearch("Hello, how are you?"); expect(result).toBe("Chat response"); expect(searchEngine.performSearch).toHaveBeenCalledWith("Hello, how are you?"); }); it("should handle complete search flow with different query types", async () => { const server = new PerplexityServer(); const searchEngine = server.getSearchEngine(); // Test different types of queries const queries = [ "What is TypeScript?", "How to use React hooks?", "Explain quantum computing", ]; for (const query of queries) { vi.mocked(searchEngine.performSearch).mockResolvedValueOnce(`Result for: ${query}`); const result = await searchEngine.performSearch(query); expect(result).toBe(`Result for: ${query}`); expect(searchEngine.performSearch).toHaveBeenCalledWith(query); } }); it("should handle complete content extraction flow with various URLs", async () => { const server = new PerplexityServer(); const browserManager = server.getBrowserManager(); // Verify that browser manager is properly initialized expect(browserManager).toBeDefined(); expect(browserManager.isReady).toBeDefined(); // Mock browser manager readiness vi.mocked(browserManager.isReady).mockReturnValue(true); expect(browserManager.isReady()).toBe(true); }); it("should handle documentation lookup workflow", async () => { const server = new PerplexityServer(); const searchEngine = server.getSearchEngine(); // Mock the search engine to return a documentation result vi.mocked(searchEngine.performSearch).mockResolvedValue("Documentation for React hooks"); const result = await searchEngine.performSearch( "Documentation for React hooks: focus on performance", ); expect(result).toBe("Documentation for React hooks"); expect(searchEngine.performSearch).toHaveBeenCalledWith( "Documentation for React hooks: focus on performance", ); }); it("should handle API discovery workflow", async () => { const server = new PerplexityServer(); const searchEngine = server.getSearchEngine(); // Mock the search engine to return an API discovery result vi.mocked(searchEngine.performSearch).mockResolvedValue("APIs for image recognition"); const result = await searchEngine.performSearch( "Find APIs for image recognition: prefer free tier options", ); expect(result).toBe("APIs for image recognition"); expect(searchEngine.performSearch).toHaveBeenCalledWith( "Find APIs for image recognition: prefer free tier options", ); }); it("should handle deprecated code checking workflow", async () => { const server = new PerplexityServer(); const searchEngine = server.getSearchEngine(); // Mock the search engine to return a deprecation check result vi.mocked(searchEngine.performSearch).mockResolvedValue("componentWillMount is deprecated"); const result = await searchEngine.performSearch( "Check if this code is deprecated: componentWillMount()", ); expect(result).toBe("componentWillMount is deprecated"); expect(searchEngine.performSearch).toHaveBeenCalledWith( "Check if this code is deprecated: componentWillMount()", ); }); }); describe("Error scenario testing", () => { it("should handle timeout handling in integrated environment", async () => { const server = new PerplexityServer(); const searchEngine = server.getSearchEngine(); // Mock search engine to simulate a timeout vi.mocked(searchEngine.performSearch).mockRejectedValue(new Error("Search timeout")); await expect(searchEngine.performSearch("slow query")).rejects.toThrow("Search timeout"); }); it("should handle malformed request handling", async () => { const server = new PerplexityServer(); const searchEngine = server.getSearchEngine(); // Test with empty query vi.mocked(searchEngine.performSearch).mockResolvedValue("Empty query response"); const result = await searchEngine.performSearch(""); expect(result).toBe("Empty query response"); expect(searchEngine.performSearch).toHaveBeenCalledWith(""); }); it("should handle recovery procedures in integrated environment", async () => { const server = new PerplexityServer(); const browserManager = server.getBrowserManager(); // Test that cleanup method exists and can be called expect(browserManager.cleanup).toBeDefined(); // Mock cleanup to resolve successfully vi.mocked(browserManager.cleanup).mockResolvedValue(undefined); await expect(browserManager.cleanup()).resolves.toBeUndefined(); }); }); });

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/wysh3/perplexity-mcp-zerver'

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