Skip to main content
Glama

Web Inspector MCP

by antonzherdev
getTestIds.test.ts10.1 kB
import { GetTestIdsTool } from '../../../tools/browser/getTestIds.js'; import { ToolContext } from '../../../tools/common/types.js'; import { Page, Browser } from 'playwright'; import { jest } from '@jest/globals'; // Mock Page const mockPageEvaluate = jest.fn() as jest.MockedFunction<(pageFunction: any, arg?: any) => Promise<any>>; const mockIsClosed = jest.fn().mockReturnValue(false); const mockPage = { evaluate: mockPageEvaluate, isClosed: mockIsClosed, } as unknown as Page; // Mock Browser const mockIsConnected = jest.fn().mockReturnValue(true); const mockBrowser = { isConnected: mockIsConnected, } as unknown as Browser; // Mock Server const mockServer = { sendMessage: jest.fn(), }; // Mock Context const mockContext = { page: mockPage, browser: mockBrowser, server: mockServer, } as ToolContext; describe('GetTestIdsTool', () => { let getTestIdsTool: GetTestIdsTool; beforeEach(() => { jest.clearAllMocks(); getTestIdsTool = new GetTestIdsTool(mockServer); mockIsConnected.mockReturnValue(true); mockIsClosed.mockReturnValue(false); }); test('should discover test IDs with default attributes', async () => { const args = {}; mockPageEvaluate.mockResolvedValue({ totalCount: 5, byAttribute: { 'data-testid': ['submit-button', 'email-input', 'password-input'], 'data-test': ['legacy-form', 'old-button'], }, duplicates: {}, }); const result = await getTestIdsTool.execute(args, mockContext); expect(result.isError).toBe(false); expect(result.content[0].text).toContain('Found 5 test IDs:'); expect(result.content[0].text).toContain('data-testid (3):'); expect(result.content[0].text).toContain('submit-button, email-input, password-input'); expect(result.content[0].text).toContain('data-test (2):'); expect(result.content[0].text).toContain('legacy-form, old-button'); expect(result.content[0].text).toContain('💡 Tip: Use these test IDs with selector shortcuts:'); }); test('should discover test IDs with custom attributes', async () => { const args = { attributes: 'data-testid,data-cy' }; mockPageEvaluate.mockResolvedValue({ totalCount: 3, byAttribute: { 'data-testid': ['login-button'], 'data-cy': ['cypress-login', 'cypress-submit'], }, duplicates: {}, }); const result = await getTestIdsTool.execute(args, mockContext); expect(result.isError).toBe(false); expect(result.content[0].text).toContain('Found 3 test IDs:'); expect(result.content[0].text).toContain('data-testid (1):'); expect(result.content[0].text).toContain('login-button'); expect(result.content[0].text).toContain('data-cy (2):'); expect(result.content[0].text).toContain('cypress-login, cypress-submit'); }); test('should handle page with no test IDs', async () => { const args = {}; mockPageEvaluate.mockResolvedValue({ totalCount: 0, byAttribute: {}, duplicates: {}, }); const result = await getTestIdsTool.execute(args, mockContext); expect(result.isError).toBe(false); expect(result.content[0].text).toContain('Found 0 test IDs'); expect(result.content[0].text).toContain('⚠ No test ID attributes found on this page.'); expect(result.content[0].text).toContain('Searched for:'); expect(result.content[0].text).toContain('data-testid'); expect(result.content[0].text).toContain('data-test'); expect(result.content[0].text).toContain('data-cy'); expect(result.content[0].text).toContain('Suggestions:'); expect(result.content[0].text).toContain('Use playwright_inspect_dom to see page structure'); }); test('should handle many test IDs (more than 10)', async () => { const args = {}; const manyTestIds = Array.from({ length: 15 }, (_, i) => `test-id-${i + 1}`); mockPageEvaluate.mockResolvedValue({ totalCount: 15, byAttribute: { 'data-testid': manyTestIds, }, duplicates: {}, }); const result = await getTestIdsTool.execute(args, mockContext); expect(result.isError).toBe(false); expect(result.content[0].text).toContain('Found 15 test IDs:'); expect(result.content[0].text).toContain('data-testid (15):'); expect(result.content[0].text).toContain('test-id-1, test-id-2, test-id-3'); expect(result.content[0].text).toContain('... and 7 more'); }); test('should show all test IDs when 10 or fewer', async () => { const args = {}; const someTestIds = Array.from({ length: 6 }, (_, i) => `button-${i + 1}`); mockPageEvaluate.mockResolvedValue({ totalCount: 6, byAttribute: { 'data-testid': someTestIds, }, duplicates: {}, }); const result = await getTestIdsTool.execute(args, mockContext); expect(result.isError).toBe(false); expect(result.content[0].text).toContain('Found 6 test IDs:'); expect(result.content[0].text).toContain('data-testid (6):'); expect(result.content[0].text).toContain('button-1, button-2, button-3, button-4, button-5, button-6'); expect(result.content[0].text).not.toContain('... and'); }); test('should handle mixed attributes with different counts', async () => { const args = {}; mockPageEvaluate.mockResolvedValue({ totalCount: 4, byAttribute: { 'data-testid': ['main-form', 'submit-btn', 'cancel-btn'], 'data-cy': ['e2e-login'], }, duplicates: {}, }); const result = await getTestIdsTool.execute(args, mockContext); expect(result.isError).toBe(false); expect(result.content[0].text).toContain('Found 4 test IDs:'); expect(result.content[0].text).toContain('data-testid (3):'); expect(result.content[0].text).toContain('data-cy (1):'); expect(result.content[0].text).toContain('main-form, submit-btn, cancel-btn'); expect(result.content[0].text).toContain('e2e-login'); }); test('should include usage tip with correct selector shorthand', async () => { const args = {}; mockPageEvaluate.mockResolvedValue({ totalCount: 2, byAttribute: { 'data-testid': ['login-form'], 'data-cy': ['cypress-test'], }, duplicates: {}, }); const result = await getTestIdsTool.execute(args, mockContext); expect(result.isError).toBe(false); expect(result.content[0].text).toContain('💡 Tip: Use these test IDs with selector shortcuts:'); expect(result.content[0].text).toContain('testid:login-form → [data-testid="login-form"]'); }); test('should show correct shorthand for data-test attribute', async () => { const args = {}; mockPageEvaluate.mockResolvedValue({ totalCount: 1, byAttribute: { 'data-test': ['my-element'], }, duplicates: {}, }); const result = await getTestIdsTool.execute(args, mockContext); expect(result.isError).toBe(false); expect(result.content[0].text).toContain('data-test:my-element → [data-test="my-element"]'); }); test('should handle browser disconnection gracefully', async () => { mockIsConnected.mockReturnValue(false); const result = await getTestIdsTool.execute({}, mockContext); expect(result.isError).toBe(true); expect(result.content[0].text).toContain('Browser is disconnected'); }); test('should handle page closed error gracefully', async () => { mockIsClosed.mockReturnValue(true); const result = await getTestIdsTool.execute({}, mockContext); expect(result.isError).toBe(true); expect(result.content[0].text).toContain('Page is closed'); }); test('should handle evaluate errors gracefully', async () => { mockPageEvaluate.mockRejectedValue(new Error('Evaluation failed')); const result = await getTestIdsTool.execute({}, mockContext); expect(result.isError).toBe(true); expect(result.content[0].text).toContain('Failed to discover test IDs: Evaluation failed'); }); test('should parse custom attributes correctly', async () => { const args = { attributes: 'data-qa, data-automation , data-e2e' }; mockPageEvaluate.mockResolvedValue({ totalCount: 3, byAttribute: { 'data-qa': ['qa-id'], 'data-automation': ['auto-id'], 'data-e2e': ['e2e-id'], }, duplicates: {}, }); const result = await getTestIdsTool.execute(args, mockContext); expect(mockPageEvaluate).toHaveBeenCalledWith( expect.any(Function), ['data-qa', 'data-automation', 'data-e2e'] ); expect(result.isError).toBe(false); }); test('should detect and warn about duplicate test IDs', async () => { const args = {}; mockPageEvaluate.mockResolvedValue({ totalCount: 5, byAttribute: { 'data-testid': ['main-header', 'submit-button', 'main-header'], 'data-test': ['duplicate-id', 'duplicate-id'], }, duplicates: { 'data-testid': { 'main-header': 2, }, 'data-test': { 'duplicate-id': 2, }, }, }); const result = await getTestIdsTool.execute(args, mockContext); expect(result.isError).toBe(false); expect(result.content[0].text).toContain('⚠ Warning: Duplicate test IDs found'); expect(result.content[0].text).toContain('data-testid: "main-header" appears 2 times'); expect(result.content[0].text).toContain('data-test: "duplicate-id" appears 2 times'); expect(result.content[0].text).toContain('Flaky tests'); expect(result.content[0].text).toContain('Ambiguous interactions'); }); test('should not show duplicate warning when no duplicates exist', async () => { const args = {}; mockPageEvaluate.mockResolvedValue({ totalCount: 3, byAttribute: { 'data-testid': ['unique-1', 'unique-2', 'unique-3'], }, duplicates: {}, }); const result = await getTestIdsTool.execute(args, mockContext); expect(result.isError).toBe(false); expect(result.content[0].text).not.toContain('⚠ Warning: Duplicate test IDs'); }); });

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/antonzherdev/mcp-web-inspector'

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