Skip to main content
Glama
server.test.ts7.26 kB
import { describe, it, expect, beforeAll, afterAll } from 'vitest'; import { Client } from '@modelcontextprotocol/sdk/client/index.js'; import { InMemoryTransport } from '@modelcontextprotocol/sdk/inMemory.js'; import { createServer } from '../src/server.js'; import { closeBrowser } from '../src/browser.js'; import { closeAllTabs } from '../src/tabs.js'; describe('Puppeteer MCP Server', () => { let client: Client; beforeAll(async () => { const server = createServer(); const [clientTransport, serverTransport] = InMemoryTransport.createLinkedPair(); await server.connect(serverTransport); client = new Client({ name: 'test-client', version: '1.0.0' }); await client.connect(clientTransport); }, 30000); afterAll(async () => { await closeAllTabs(); await closeBrowser(); }, 30000); describe('Tab Management', () => { it('should list tabs', async () => { const result = await client.callTool({ name: 'list_tabs', arguments: {} }); expect(result.content).toBeDefined(); expect(result.content[0]).toHaveProperty('text'); const data = JSON.parse((result.content[0] as { text: string }).text); expect(data).toHaveProperty('tabs'); expect(Array.isArray(data.tabs)).toBe(true); }); it('should create a new tab', async () => { const result = await client.callTool({ name: 'new_tab', arguments: {} }); expect(result.content).toBeDefined(); const data = JSON.parse((result.content[0] as { text: string }).text); expect(data).toHaveProperty('id'); expect(data.id).toMatch(/^tab_/); }); it('should create a new tab with URL', async () => { const result = await client.callTool({ name: 'new_tab', arguments: { url: 'https://example.com' }, }); expect(result.content).toBeDefined(); const data = JSON.parse((result.content[0] as { text: string }).text); expect(data).toHaveProperty('id'); expect(data.url).toContain('example.com'); }, 30000); }); describe('Navigation', () => { it('should navigate to a URL', async () => { const result = await client.callTool({ name: 'navigate', arguments: { url: 'https://example.com' }, }); expect(result.content).toBeDefined(); const data = JSON.parse((result.content[0] as { text: string }).text); expect(data.url).toContain('example.com'); expect(data).toHaveProperty('title'); }, 30000); it('should reload the page', async () => { // First navigate to a page await client.callTool({ name: 'navigate', arguments: { url: 'https://example.com' }, }); const result = await client.callTool({ name: 'reload', arguments: {}, }); expect(result.content).toBeDefined(); const data = JSON.parse((result.content[0] as { text: string }).text); expect(data.url).toContain('example.com'); }, 30000); }); describe('Content', () => { it('should evaluate JavaScript', async () => { await client.callTool({ name: 'navigate', arguments: { url: 'https://example.com' }, }); const result = await client.callTool({ name: 'evaluate', arguments: { script: 'return 1 + 1' }, }); expect(result.content).toBeDefined(); const data = JSON.parse((result.content[0] as { text: string }).text); expect(data.result).toBe(2); }, 30000); it('should get page content', async () => { await client.callTool({ name: 'navigate', arguments: { url: 'https://example.com' }, }); const result = await client.callTool({ name: 'get_content', arguments: { type: 'text' }, }); expect(result.content).toBeDefined(); const data = JSON.parse((result.content[0] as { text: string }).text); expect(data).toHaveProperty('content'); expect(data.content).toContain('Example Domain'); }, 30000); it('should query selector', async () => { await client.callTool({ name: 'navigate', arguments: { url: 'https://example.com' }, }); const result = await client.callTool({ name: 'query_selector', arguments: { selector: 'h1' }, }); expect(result.content).toBeDefined(); const data = JSON.parse((result.content[0] as { text: string }).text); expect(data.exists).toBe(true); expect(data.tagName).toBe('h1'); }, 30000); }); describe('Media', () => { it('should take a screenshot', async () => { await client.callTool({ name: 'navigate', arguments: { url: 'https://example.com' }, }); const result = await client.callTool({ name: 'screenshot', arguments: { format: 'png' }, }); expect(result.content).toBeDefined(); // Screenshot returns image content block const imageBlock = result.content[0] as { type: string; data: string; mimeType: string }; expect(imageBlock.type).toBe('image'); expect(imageBlock.mimeType).toBe('image/png'); expect(imageBlock.data).toBeDefined(); expect(imageBlock.data.length).toBeGreaterThan(0); }, 30000); }); describe('Waiting', () => { it('should wait for a selector', async () => { await client.callTool({ name: 'navigate', arguments: { url: 'https://example.com' }, }); const result = await client.callTool({ name: 'wait_for_selector', arguments: { selector: 'h1' }, }); expect(result.content).toBeDefined(); const data = JSON.parse((result.content[0] as { text: string }).text); expect(data.found).toBe(true); }, 30000); it('should wait for specified time', async () => { const startTime = Date.now(); const result = await client.callTool({ name: 'wait', arguments: { ms: 100 }, }); const endTime = Date.now(); expect(result.content).toBeDefined(); const data = JSON.parse((result.content[0] as { text: string }).text); expect(data.waited).toBe(100); expect(endTime - startTime).toBeGreaterThanOrEqual(100); }); }); describe('Error Handling', () => { it('should return error for non-existent selector', async () => { await client.callTool({ name: 'navigate', arguments: { url: 'https://example.com' }, }); const result = await client.callTool({ name: 'click', arguments: { selector: '#non-existent-element-12345', timeout: 1000 }, }); expect(result.content).toBeDefined(); expect(result.isError).toBe(true); const data = JSON.parse((result.content[0] as { text: string }).text); expect(data.error).toBe('E101'); // SELECTOR_NOT_FOUND }, 30000); it('should return error for invalid tab ID', async () => { const result = await client.callTool({ name: 'switch_tab', arguments: { tabId: 'non-existent-tab' }, }); expect(result.content).toBeDefined(); expect(result.isError).toBe(true); const data = JSON.parse((result.content[0] as { text: string }).text); expect(data.error).toBe('E003'); // TAB_NOT_FOUND }); }); });

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/andytango/puppeteer-mcp'

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