feat(mcp): support test-id-attribute option (#37760)
infra / docs & lint (push) Waiting to run Details
infra / Lint snippets (push) Waiting to run Details
components / ${{ matrix.os }} - Node.js ${{ matrix.node-version }} (18, macos-latest) (push) Waiting to run Details
components / ${{ matrix.os }} - Node.js ${{ matrix.node-version }} (18, ubuntu-latest) (push) Waiting to run Details
components / ${{ matrix.os }} - Node.js ${{ matrix.node-version }} (18, windows-latest) (push) Waiting to run Details
components / ${{ matrix.os }} - Node.js ${{ matrix.node-version }} (20, ubuntu-latest) (push) Waiting to run Details
components / ${{ matrix.os }} - Node.js ${{ matrix.node-version }} (22, ubuntu-latest) (push) Waiting to run Details
MCP / ${{ matrix.os }} (macos-15) (push) Waiting to run Details
MCP / ${{ matrix.os }} (ubuntu-latest) (push) Waiting to run Details
MCP / ${{ matrix.os }} (windows-latest) (push) Waiting to run Details
tests others / Stress - ${{ matrix.os }} (macos-latest) (push) Waiting to run Details
tests others / Stress - ${{ matrix.os }} (ubuntu-latest) (push) Waiting to run Details
tests others / Stress - ${{ matrix.os }} (windows-latest) (push) Waiting to run Details
tests others / WebView2 (push) Waiting to run Details
tests others / time library - ${{ matrix.clock }} (frozen) (push) Waiting to run Details
tests others / time library - ${{ matrix.clock }} (realtime) (push) Waiting to run Details
tests others / time test runner - ${{ matrix.clock }} (frozen) (push) Waiting to run Details
tests others / time test runner - ${{ matrix.clock }} (realtime) (push) Waiting to run Details
tests others / Electron - ${{ matrix.os }} (macos-latest) (push) Waiting to run Details
tests others / Electron - ${{ matrix.os }} (ubuntu-latest) (push) Waiting to run Details
tests others / Electron - ${{ matrix.os }} (windows-latest) (push) Waiting to run Details
tests 1 / ${{ matrix.os }} (${{ matrix.browser }} - Node.js ${{ matrix.node-version }}) (chromium, 18, ubuntu-22.04) (push) Waiting to run Details
tests 1 / ${{ matrix.os }} (${{ matrix.browser }} - Node.js ${{ matrix.node-version }}) (chromium, 20, ubuntu-22.04) (push) Waiting to run Details
tests 1 / ${{ matrix.os }} (${{ matrix.browser }} - Node.js ${{ matrix.node-version }}) (chromium, 22, ubuntu-22.04) (push) Waiting to run Details
tests 1 / ${{ matrix.os }} (${{ matrix.browser }} - Node.js ${{ matrix.node-version }}) (chromium, 24, ubuntu-22.04) (push) Waiting to run Details
tests 1 / ${{ matrix.os }} (${{ matrix.browser }} - Node.js ${{ matrix.node-version }}) (firefox, 18, ubuntu-22.04) (push) Waiting to run Details
tests 1 / ${{ matrix.os }} (${{ matrix.browser }} - Node.js ${{ matrix.node-version }}) (webkit, 18, ubuntu-22.04) (push) Waiting to run Details
tests 1 / ${{ matrix.os }} (chromium tip-of-tree) (ubuntu-22.04) (push) Waiting to run Details
tests 1 / Test Runner (18, macos-latest, 1, 2) (push) Waiting to run Details
tests 1 / Test Runner (18, macos-latest, 2, 2) (push) Waiting to run Details
tests 1 / Test Runner (18, ubuntu-latest, 1, 2) (push) Waiting to run Details
tests 1 / Test Runner (18, ubuntu-latest, 2, 2) (push) Waiting to run Details
tests 1 / Test Runner (18, windows-latest, 1, 2) (push) Waiting to run Details
tests 1 / Test Runner (18, windows-latest, 2, 2) (push) Waiting to run Details
tests 1 / Test Runner (20, ubuntu-latest, 1, 2) (push) Waiting to run Details
tests 1 / Test Runner (20, ubuntu-latest, 2, 2) (push) Waiting to run Details
tests 1 / Test Runner (22, ubuntu-latest, 1, 2) (push) Waiting to run Details
tests 1 / Test Runner (22, ubuntu-latest, 2, 2) (push) Waiting to run Details
tests 1 / Test Runner (24, ubuntu-latest, 1, 2) (push) Waiting to run Details
tests 1 / Test Runner (24, ubuntu-latest, 2, 2) (push) Waiting to run Details
tests 1 / Web Components (push) Waiting to run Details
tests 1 / VSCode Extension (push) Waiting to run Details
tests 1 / Installation Test ${{ matrix.os }} (macos-latest) (push) Waiting to run Details
tests 1 / Installation Test ${{ matrix.os }} (ubuntu-latest) (push) Waiting to run Details
tests 1 / Installation Test ${{ matrix.os }} (windows-latest) (push) Waiting to run Details
tests 2 / ${{ matrix.os }} (${{ matrix.browser }}) (chromium, ubuntu-24.04) (push) Waiting to run Details
tests 2 / ${{ matrix.os }} (${{ matrix.browser }}) (firefox, ubuntu-24.04) (push) Waiting to run Details
tests 2 / ${{ matrix.os }} (${{ matrix.browser }}) (webkit, ubuntu-24.04) (push) Waiting to run Details
tests 2 / ${{ matrix.os }} (${{ matrix.browser }}) (chromium, macos-14-large) (push) Waiting to run Details
tests 2 / ${{ matrix.os }} (${{ matrix.browser }}) (chromium, macos-14-xlarge) (push) Waiting to run Details
tests 2 / ${{ matrix.os }} (${{ matrix.browser }}) (chromium, macos-15-large) (push) Waiting to run Details
tests 2 / ${{ matrix.os }} (${{ matrix.browser }}) (chromium, macos-15-xlarge) (push) Waiting to run Details
tests 2 / ${{ matrix.os }} (${{ matrix.browser }}) (firefox, macos-14-large) (push) Waiting to run Details
tests 2 / ${{ matrix.os }} (${{ matrix.browser }}) (firefox, macos-14-xlarge) (push) Waiting to run Details
tests 2 / ${{ matrix.os }} (${{ matrix.browser }}) (firefox, macos-15-large) (push) Waiting to run Details
tests 2 / ${{ matrix.os }} (${{ matrix.browser }}) (firefox, macos-15-xlarge) (push) Waiting to run Details
tests 2 / ${{ matrix.os }} (${{ matrix.browser }}) (webkit, macos-14-large) (push) Waiting to run Details
tests 2 / ${{ matrix.os }} (${{ matrix.browser }}) (webkit, macos-14-xlarge) (push) Waiting to run Details
tests 2 / ${{ matrix.os }} (${{ matrix.browser }}) (webkit, macos-15-large) (push) Waiting to run Details
tests 2 / ${{ matrix.os }} (${{ matrix.browser }}) (webkit, macos-15-xlarge) (push) Waiting to run Details
tests 2 / ${{ matrix.os }} (${{ matrix.browser }}) (webkit, macos-26-xlarge) (push) Waiting to run Details
tests 2 / Windows (chromium) (push) Waiting to run Details
tests 2 / Windows (firefox) (push) Waiting to run Details
tests 2 / Windows (webkit) (push) Waiting to run Details
tests 2 / Installation Test ${{ matrix.os }} (${{ matrix.node_version }}) (20, ubuntu-latest) (push) Waiting to run Details
tests 2 / Installation Test ${{ matrix.os }} (${{ matrix.node_version }}) (22, ubuntu-latest) (push) Waiting to run Details
tests 2 / Installation Test ${{ matrix.os }} (${{ matrix.node_version }}) (24, ubuntu-latest) (push) Waiting to run Details
tests 2 / headed ${{ matrix.browser }} (${{ matrix.os }}) (chromium, macos-14-xlarge) (push) Waiting to run Details
tests 2 / headed ${{ matrix.browser }} (${{ matrix.os }}) (chromium, ubuntu-24.04) (push) Waiting to run Details
tests 2 / headed ${{ matrix.browser }} (${{ matrix.os }}) (chromium, windows-latest) (push) Waiting to run Details
tests 2 / headed ${{ matrix.browser }} (${{ matrix.os }}) (firefox, macos-14-xlarge) (push) Waiting to run Details
tests 2 / headed ${{ matrix.browser }} (${{ matrix.os }}) (firefox, ubuntu-24.04) (push) Waiting to run Details
tests 2 / headed ${{ matrix.browser }} (${{ matrix.os }}) (firefox, windows-latest) (push) Waiting to run Details
tests 2 / headed ${{ matrix.browser }} (${{ matrix.os }}) (webkit, macos-14-xlarge) (push) Waiting to run Details
tests 2 / headed ${{ matrix.browser }} (${{ matrix.os }}) (webkit, ubuntu-22.04) (push) Waiting to run Details
tests 2 / headed ${{ matrix.browser }} (${{ matrix.os }}) (webkit, ubuntu-24.04) (push) Waiting to run Details
tests 2 / headed ${{ matrix.browser }} (${{ matrix.os }}) (webkit, windows-latest) (push) Waiting to run Details
tests 2 / Transport (driver) (push) Waiting to run Details
tests 2 / Transport (service) (push) Waiting to run Details
tests 2 / Tracing ${{ matrix.browser }} ${{ matrix.channel }} (chromium, chromium-tip-of-tree, ubuntu-22.04) (push) Waiting to run Details
tests 2 / Tracing ${{ matrix.browser }} ${{ matrix.channel }} (chromium, ubuntu-22.04) (push) Waiting to run Details
tests 2 / Tracing ${{ matrix.browser }} ${{ matrix.channel }} (firefox, ubuntu-22.04) (push) Waiting to run Details
tests 2 / Tracing ${{ matrix.browser }} ${{ matrix.channel }} (webkit, ubuntu-24.04) (push) Waiting to run Details
tests 2 / Test ${{ matrix.channel }} on ${{ matrix.runs-on }} (chrome, macos-latest) (push) Waiting to run Details
tests 2 / Test ${{ matrix.channel }} on ${{ matrix.runs-on }} (chrome, ubuntu-22.04) (push) Waiting to run Details
tests 2 / Test ${{ matrix.channel }} on ${{ matrix.runs-on }} (chrome, windows-latest) (push) Waiting to run Details
tests 2 / Test ${{ matrix.channel }} on ${{ matrix.runs-on }} (chrome-beta, macos-latest) (push) Waiting to run Details
tests 2 / Test ${{ matrix.channel }} on ${{ matrix.runs-on }} (chrome-beta, ubuntu-22.04) (push) Waiting to run Details
tests 2 / Test ${{ matrix.channel }} on ${{ matrix.runs-on }} (chrome-beta, windows-latest) (push) Waiting to run Details
tests 2 / Test ${{ matrix.channel }} on ${{ matrix.runs-on }} (msedge, macos-latest) (push) Waiting to run Details
tests 2 / Test ${{ matrix.channel }} on ${{ matrix.runs-on }} (msedge, ubuntu-22.04) (push) Waiting to run Details
tests 2 / Test ${{ matrix.channel }} on ${{ matrix.runs-on }} (msedge, windows-latest) (push) Waiting to run Details
tests 2 / Test ${{ matrix.channel }} on ${{ matrix.runs-on }} (msedge-beta, macos-latest) (push) Waiting to run Details
tests 2 / Test ${{ matrix.channel }} on ${{ matrix.runs-on }} (msedge-beta, ubuntu-22.04) (push) Waiting to run Details
tests 2 / Test ${{ matrix.channel }} on ${{ matrix.runs-on }} (msedge-beta, windows-latest) (push) Waiting to run Details
tests 2 / Test ${{ matrix.channel }} on ${{ matrix.runs-on }} (msedge-dev, macos-latest) (push) Waiting to run Details
tests 2 / Test ${{ matrix.channel }} on ${{ matrix.runs-on }} (msedge-dev, ubuntu-22.04) (push) Waiting to run Details
tests 2 / Test ${{ matrix.channel }} on ${{ matrix.runs-on }} (msedge-dev, windows-latest) (push) Waiting to run Details
tests 2 / Chromium tip-of-tree ${{ matrix.os }}${{ matrix.headed }} (, macos-13) (push) Waiting to run Details
tests 2 / Chromium tip-of-tree ${{ matrix.os }}${{ matrix.headed }} (, windows-latest) (push) Waiting to run Details
tests 2 / Chromium tip-of-tree ${{ matrix.os }}${{ matrix.headed }} (--headed, macos-13) (push) Waiting to run Details
tests 2 / Chromium tip-of-tree ${{ matrix.os }}${{ matrix.headed }} (--headed, ubuntu-22.04) (push) Waiting to run Details
tests 2 / Chromium tip-of-tree ${{ matrix.os }}${{ matrix.headed }} (--headed, windows-latest) (push) Waiting to run Details
tests 2 / Chromium tip-of-tree headless-shell-${{ matrix.os }} (ubuntu-22.04) (push) Waiting to run Details
tests 2 / Firefox Beta ${{ matrix.os }} (macos-latest) (push) Waiting to run Details
tests 2 / Firefox Beta ${{ matrix.os }} (ubuntu-22.04) (push) Waiting to run Details
tests 2 / Firefox Beta ${{ matrix.os }} (windows-latest) (push) Waiting to run Details
tests 2 / build-playwright-driver (push) Waiting to run Details
tests 2 / Test channel=chromium (macos-latest) (push) Waiting to run Details
tests 2 / Test channel=chromium (ubuntu-latest) (push) Waiting to run Details
tests 2 / Test channel=chromium (windows-latest) (push) Waiting to run Details
tests Video / Video Linux (chromium, ubuntu-22.04) (push) Waiting to run Details
tests Video / Video Linux (chromium, ubuntu-24.04) (push) Waiting to run Details
tests Video / Video Linux (firefox, ubuntu-22.04) (push) Waiting to run Details
tests Video / Video Linux (firefox, ubuntu-24.04) (push) Waiting to run Details
tests Video / Video Linux (webkit, ubuntu-22.04) (push) Waiting to run Details
tests Video / Video Linux (webkit, ubuntu-24.04) (push) Waiting to run Details
Internal Tests / trigger (push) Waiting to run Details

This commit is contained in:
Pavel Feldman 2025-10-07 14:35:08 -07:00 committed by GitHub
parent e4679234a3
commit 47f3da37a2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 81 additions and 0 deletions

View File

@ -59,6 +59,7 @@ export type CLIOptions = {
secrets?: Record<string, string>;
sharedBrowserContext?: boolean;
storageState?: string;
testIdAttribute?: string;
timeoutAction?: number;
timeoutNavigation?: number;
userAgent?: string;
@ -236,6 +237,7 @@ export function configFromCLIOptions(cliOptions: CLIOptions): Config {
sharedBrowserContext: cliOptions.sharedBrowserContext,
outputDir: cliOptions.outputDir,
imageResponses: cliOptions.imageResponses,
testIdAttribute: cliOptions.testIdAttribute,
timeouts: {
action: cliOptions.timeoutAction,
navigation: cliOptions.timeoutNavigation,
@ -277,6 +279,7 @@ function configFromEnv(): Config {
options.saveVideo = resolutionParser('--save-video', process.env.PLAYWRIGHT_MCP_SAVE_VIDEO);
options.secrets = dotenvFileLoader(process.env.PLAYWRIGHT_MCP_SECRETS_FILE);
options.storageState = envToString(process.env.PLAYWRIGHT_MCP_STORAGE_STATE);
options.testIdAttribute = envToString(process.env.PLAYWRIGHT_MCP_TEST_ID_ATTRIBUTE);
options.timeoutAction = numberParser(process.env.PLAYWRIGHT_MCP_TIMEOUT_ACTION);
options.timeoutNavigation = numberParser(process.env.PLAYWRIGHT_MCP_TIMEOUT_NAVIGATION);
options.userAgent = envToString(process.env.PLAYWRIGHT_MCP_USER_AGENT);

View File

@ -18,6 +18,7 @@ import fs from 'fs';
import path from 'path';
import { debug } from 'playwright-core/lib/utilsBundle';
import { selectors } from 'playwright-core';
import { logUnhandledError } from '../log';
import { Tab } from './tab';
@ -233,6 +234,9 @@ export class Context {
if (this._closeBrowserContextPromise)
throw new Error('Another browser context is being closed.');
// TODO: move to the browser context factory to make it based on isolation mode.
if (this.config.testIdAttribute)
selectors.setTestIdAttribute(this.config.testIdAttribute);
const result = await this._browserContextFactory.createContext(this._clientInfo, this._abortController.signal, this._runningToolName);
const { browserContext } = result;
await this._setupRequestInterception(browserContext);

View File

@ -149,6 +149,11 @@ export type Config = {
blockedOrigins?: string[];
};
/**
* Specify the attribute to use for test ids, defaults to "data-testid".
*/
testIdAttribute?: string;
timeouts?: {
/*
* Configures default action timeout: https://playwright.dev/docs/api/class-page#page-set-default-timeout. Defaults to 5000ms.

View File

@ -58,6 +58,7 @@ export function decorateCommand(command: Command, version: string) {
.option('--secrets <path>', 'path to a file containing secrets in the dotenv format', dotenvFileLoader)
.option('--shared-browser-context', 'reuse the same browser context between all connected HTTP clients.')
.option('--storage-state <path>', 'path to the storage state file for isolated sessions.')
.option('--test-id-attribute <attribute>', 'specify the attribute to use for test ids, defaults to "data-testid"')
.option('--timeout-action <timeout>', 'specify action timeout in milliseconds, defaults to 5000ms', numberParser)
.option('--timeout-navigation <timeout>', 'specify navigation timeout in milliseconds, defaults to 60000ms', numberParser)
.option('--user-agent <ua string>', 'specify user agent string')

View File

@ -153,3 +153,30 @@ test('browser_click (modifiers)', async ({ client, server, mcpBrowser }) => {
pageState: expect.stringContaining(`- generic [ref=e3]: ctrlKey:false metaKey:false shiftKey:true altKey:true`),
});
});
test('browser_click (test id attribute)', async ({ startClient, server, mcpBrowser }) => {
server.setContent('/', `
<title>Title</title>
<button data-tid="submit">Submit</button>
`, 'text/html');
const { client } = await startClient({
args: [
'--test-id-attribute', 'data-tid',
],
});
await client.callTool({
name: 'browser_navigate',
arguments: { url: server.PREFIX },
});
expect(await client.callTool({
name: 'browser_click',
arguments: {
element: 'Submit button',
ref: 'e2',
},
})).toHaveResponse({
code: `await page.getByTestId('submit').click();`,
});
});

View File

@ -276,3 +276,44 @@ test('generator_write_test', async ({ startClient }, testInfo) => {
const code = fs.readFileSync(testInfo.outputPath('a.test.ts'), 'utf8');
expect(code).toBe(`// Test content`);
});
test('should respect custom test id', async ({ startClient }) => {
await writeFiles({
'playwright.config.ts': `
import { defineConfig } from '@playwright/test';
export default defineConfig({
use: {
testIdAttribute: 'data-tid'
}
});
`,
'a.test.ts': `
import { test, expect } from '@playwright/test';
test.beforeEach(async ({ page }) => {
await page.setContent('<button data-tid="submit">Submit</button>');
});
test('template', async ({ page }) => {
});
`,
});
const { client } = await startClient();
await client.callTool({
name: 'generator_setup_page',
arguments: {
plan: 'Test plan',
seedFile: 'a.test.ts',
},
});
expect(await client.callTool({
name: 'browser_click',
arguments: {
element: 'Submit button',
ref: 'e2',
intent: 'Click submit button',
},
})).toHaveResponse({
code: `await page.getByTestId('submit').click();`,
});
});