Skip to main content
Glama

mcp-playwright

visiblePage.test.ts10.2 kB
import { VisibleTextTool, VisibleHtmlTool } from '../../../tools/browser/visiblePage.js'; import { ToolContext } from '../../../tools/common/types.js'; import { Page, Browser, ElementHandle } from 'playwright'; import { jest } from '@jest/globals'; // Mock the Page object const mockEvaluate = jest.fn() as jest.MockedFunction<(pageFunction: Function | string, arg?: any) => Promise<any>>; const mockContent = jest.fn(); const mockIsClosed = jest.fn().mockReturnValue(false); const mock$ = jest.fn() as jest.MockedFunction<(selector: string) => Promise<ElementHandle | null>>; const mockPage = { evaluate: mockEvaluate, content: mockContent, isClosed: mockIsClosed, $: mock$ } as unknown as Page; // Mock the browser const mockIsConnected = jest.fn().mockReturnValue(true); const mockBrowser = { isConnected: mockIsConnected } as unknown as Browser; // Mock the server const mockServer = { sendMessage: jest.fn() }; // Mock context const mockContext = { page: mockPage, browser: mockBrowser, server: mockServer } as ToolContext; describe('VisibleTextTool', () => { let visibleTextTool: VisibleTextTool; beforeEach(() => { jest.clearAllMocks(); visibleTextTool = new VisibleTextTool(mockServer); // Reset mocks mockIsConnected.mockReturnValue(true); mockIsClosed.mockReturnValue(false); mockEvaluate.mockImplementation(() => Promise.resolve('Sample visible text content')); }); test('should retrieve visible text content', async () => { const args = {}; const result = await visibleTextTool.execute(args, mockContext); expect(mockEvaluate).toHaveBeenCalled(); expect(result.isError).toBe(false); expect(result.content[0].text).toContain('Visible text content'); expect(result.content[0].text).toContain('Sample visible text content'); }); test('should handle missing page', async () => { const args = {}; // Context with browser but without page const contextWithoutPage = { browser: mockBrowser, server: mockServer } as unknown as ToolContext; const result = await visibleTextTool.execute(args, contextWithoutPage); expect(mockEvaluate).not.toHaveBeenCalled(); expect(result.isError).toBe(true); expect(result.content[0].text).toContain('Page is not available'); }); test('should handle disconnected browser', async () => { const args = {}; // Mock disconnected browser mockIsConnected.mockReturnValueOnce(false); const result = await visibleTextTool.execute(args, mockContext); expect(mockEvaluate).not.toHaveBeenCalled(); expect(result.isError).toBe(true); expect(result.content[0].text).toContain('Browser is not connected'); }); test('should handle closed page', async () => { const args = {}; // Mock closed page mockIsClosed.mockReturnValueOnce(true); const result = await visibleTextTool.execute(args, mockContext); expect(mockEvaluate).not.toHaveBeenCalled(); expect(result.isError).toBe(true); expect(result.content[0].text).toContain('Page is not available or has been closed'); }); test('should handle evaluation errors', async () => { const args = {}; // Mock evaluation error mockEvaluate.mockImplementationOnce(() => Promise.reject(new Error('Evaluation failed'))); const result = await visibleTextTool.execute(args, mockContext); expect(mockEvaluate).toHaveBeenCalled(); expect(result.isError).toBe(true); expect(result.content[0].text).toContain('Failed to get visible text content'); expect(result.content[0].text).toContain('Evaluation failed'); }); }); describe('VisibleHtmlTool', () => { let visibleHtmlTool: VisibleHtmlTool; beforeEach(() => { jest.clearAllMocks(); visibleHtmlTool = new VisibleHtmlTool(mockServer); // Reset mocks mockIsConnected.mockReturnValue(true); mockIsClosed.mockReturnValue(false); mockContent.mockImplementation(() => Promise.resolve('<html><body>Sample HTML content</body></html>')); }); test('should retrieve HTML content', async () => { const args = { removeScripts: false }; const result = await visibleHtmlTool.execute(args, mockContext); expect(mockContent).toHaveBeenCalled(); expect(result.isError).toBe(false); expect(result.content[0].text).toContain('HTML content'); expect(result.content[0].text).toContain('<html><body>Sample HTML content</body></html>'); }); test('should supply the correct filters', async () => { const args = { removeScripts: true, removeComments: true, removeStyles: true, removeMeta: true, minify: true, cleanHtml: true }; // Mock the page.evaluate to capture the filter arguments mockEvaluate.mockImplementationOnce((callback, params) => { expect(params).toEqual({ html: '<html><body>Sample HTML content</body></html>', removeScripts: true, removeComments: true, removeStyles: true, removeMeta: true, minify: true }); return Promise.resolve('<html><body>Processed HTML content</body></html>'); }); const result = await visibleHtmlTool.execute(args, mockContext); expect(mockContent).toHaveBeenCalled(); expect(mockEvaluate).toHaveBeenCalled(); expect(result.isError).toBe(false); expect(result.content[0].text).toContain('HTML content'); expect(result.content[0].text).toContain('Processed HTML content'); }); test('should handle individual filter combinations', async () => { const args = { removeScripts: true, minify: true }; // Mock content to return HTML mockContent.mockImplementationOnce(() => Promise.resolve('<html><body>Sample HTML content</body></html>') ); mockEvaluate.mockImplementationOnce((callback, params: any) => { expect(params).toEqual({ html: '<html><body>Sample HTML content</body></html>', removeScripts: true, removeComments: undefined, removeStyles: undefined, removeMeta: undefined, minify: true }); return Promise.resolve('<html><body>Filtered content</body></html>'); }); const result = await visibleHtmlTool.execute(args, mockContext); expect(result.isError).toBe(false); expect(result.content[0].text).toContain('Filtered content'); }); test('should handle selector parameter', async () => { const args = { selector: '#main-content', removeScripts: true }; // Mock element selection const mockElement = { outerHTML: '<div id="main-content">Selected content</div>' } as unknown as ElementHandle<Element>; mock$.mockResolvedValueOnce(mockElement); // Mock evaluate for filtering mockEvaluate.mockImplementation((_: any, params: any) => Promise.resolve('<div>Processed selected content</div>') ); const result = await visibleHtmlTool.execute(args, mockContext); expect(mock$).toHaveBeenCalledWith('#main-content'); expect(result.isError).toBe(false); expect(result.content[0].text).toContain('Processed selected content'); }); test('should handle empty HTML content', async () => { const args = { removeScripts: true }; // Mock content to return empty HTML mockContent.mockImplementationOnce(() => Promise.resolve('')); mockEvaluate.mockImplementationOnce((callback, params: any) => { expect(params.html).toBe(''); return Promise.resolve(''); }); const result = await visibleHtmlTool.execute(args, mockContext); expect(result.isError).toBe(false); expect(result.content[0].text).toContain('HTML content'); }); test('should handle cleanHtml flag setting all filters', async () => { const args = { cleanHtml: true }; mockEvaluate.mockImplementationOnce((callback, params) => { expect(params).toEqual({ html: '<html><body>Sample HTML content</body></html>', removeScripts: true, removeComments: true, removeStyles: true, removeMeta: true, minify: undefined }); return Promise.resolve('<html><body>Processed HTML content</body></html>'); }); const result = await visibleHtmlTool.execute(args, mockContext); expect(result.isError).toBe(false); }); test('should handle missing page', async () => { const args = {}; // Context with browser but without page const contextWithoutPage = { browser: mockBrowser, server: mockServer } as unknown as ToolContext; const result = await visibleHtmlTool.execute(args, contextWithoutPage); expect(mockContent).not.toHaveBeenCalled(); expect(result.isError).toBe(true); expect(result.content[0].text).toContain('Page is not available'); }); test('should handle disconnected browser', async () => { const args = {}; // Mock disconnected browser mockIsConnected.mockReturnValueOnce(false); const result = await visibleHtmlTool.execute(args, mockContext); expect(mockContent).not.toHaveBeenCalled(); expect(result.isError).toBe(true); expect(result.content[0].text).toContain('Browser is not connected'); }); test('should handle closed page', async () => { const args = {}; // Mock closed page mockIsClosed.mockReturnValueOnce(true); const result = await visibleHtmlTool.execute(args, mockContext); expect(mockContent).not.toHaveBeenCalled(); expect(result.isError).toBe(true); expect(result.content[0].text).toContain('Page is not available or has been closed'); }); test('should handle content retrieval errors', async () => { const args = {}; // Mock content error mockContent.mockImplementationOnce(() => Promise.reject(new Error('Content retrieval failed'))); const result = await visibleHtmlTool.execute(args, mockContext); expect(mockContent).toHaveBeenCalled(); expect(result.isError).toBe(true); expect(result.content[0].text).toContain('Failed to get visible HTML content'); expect(result.content[0].text).toContain('Content retrieval failed'); }); });

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/executeautomation/mcp-playwright'

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