playwright-test-agent 0.1.9 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json
CHANGED
|
@@ -5,39 +5,45 @@ description: Use first when a user asks to investigate or test a website, browse
|
|
|
5
5
|
|
|
6
6
|
# Playwright Test Agent
|
|
7
7
|
|
|
8
|
-
Use Planner -> Generator -> Healer for durable tests. `AGENTS.md` or `CLAUDE.md` defines the platform-specific role routing.
|
|
8
|
+
Use Planner -> Generator -> Healer for durable tests. `AGENTS.md` or `CLAUDE.md` defines the platform-specific role routing. The role that owns the current phase uses `playwright-cli`; the parent does not perform another role's browser work.
|
|
9
9
|
|
|
10
|
-
##
|
|
10
|
+
## Required phase handoff
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
1. Planner investigates the application and saves a Markdown plan under `specs/`.
|
|
13
|
+
2. The parent presents that plan and waits for user confirmation.
|
|
14
|
+
3. Generator validates the confirmed plan and writes executable tests.
|
|
15
|
+
4. The parent executes the generated tests with `npx playwright test`.
|
|
16
|
+
5. If all generated tests pass, report the result. If any fail, Healer diagnoses, fixes justified test defects, and reruns the affected tests until they pass or a genuine blocker is identified.
|
|
13
17
|
|
|
14
|
-
|
|
15
|
-
playwright-cli open <deployed-url>
|
|
16
|
-
```
|
|
18
|
+
Every phase is required in that order. Planner exploration without a saved plan is incomplete. Generator output without test files is incomplete. Generated test files that have not been executed are not a successful test result. Healer must never start before a real generated-test failure exists.
|
|
17
19
|
|
|
18
|
-
|
|
20
|
+
On Claude Code, the parent must start `playwright-test-planner`; only that Planner may open the website. The parent must not call `playwright-cli`, Chrome DevTools, browser MCP tools, or another browser integration. On Codex, the main agent does not spawn a Playwright subagent; it explicitly assumes one phase at a time, and may call CLI only while acting in that phase. Preserve the official Playwright Test MCP configuration and role tools; CLI is the preferred live-browser path and prevents missing MCP tools from blocking the workflow.
|
|
19
21
|
|
|
20
|
-
|
|
22
|
+
Before Planner, the parent may read relevant local project information to understand routes, requirements, fixtures, and constraints. It may ask for information that is necessary or could materially change the test purpose, scope, assertions, access, or safety, such as the deployed URL, account or role, expected behavior, target environment, allowed data mutations, and authorization boundary. Keep this preparation focused: do not locate a seed file or turn config, test-directory, agent-definition, fixture, or generated-file discovery into a prerequisite.
|
|
23
|
+
|
|
24
|
+
If the available context is sufficient, start/enter Planner without further confirmation. During exploration, pause when required information is missing, incorrect, or contradictory, including credentials, URL, role, prerequisites, expected behavior that changes assertions, or authorization for a consequential action. Ask the user for the specific correction, then resume or restart Planner with the answer and blocking observation. Do not guess credentials, probe nearby environments, bypass access controls, or wander through unrelated pages.
|
|
21
25
|
|
|
22
26
|
Keep credentials and tokens in environment variables or ignored secret files. Never copy them into plans, tests, screenshots, evidence, or chat.
|
|
23
27
|
|
|
24
28
|
## Planner
|
|
25
29
|
|
|
26
|
-
Planner
|
|
30
|
+
Planner—not the parent—opens the supplied URL with `playwright-cli open <deployed-url>`, investigates the application, converts its findings into a human-readable Markdown test plan, and saves it under `specs/`. Once the parent has supplied the objective, URL, access information, relevant project context, and constraints, Planner's first browser action must be that CLI command. It then uses compact `snapshot` or `find` output and refs for interaction. A seed is not a prerequisite and must not be located before exploration.
|
|
27
31
|
|
|
28
32
|
The plan contains prerequisites, test data, independent scenarios, steps, observable expected results, exclusions, and intended output files. Reconnaissance must not mutate durable/shared data or perform consequential actions unless authorized.
|
|
29
33
|
|
|
30
|
-
|
|
34
|
+
Planner returns the saved plan path and a scenario summary. The parent shows the plan and exclusions to the user. Generator starts only after the user explicitly confirms that plan.
|
|
31
35
|
|
|
32
36
|
## Generator
|
|
33
37
|
|
|
34
|
-
Generator converts the confirmed plan into executable
|
|
38
|
+
Generator starts only after confirmation and converts the confirmed plan into executable Playwright test code. Generator—not the parent—uses `playwright-cli` to validate flows, locators, and assertions, writes the test files, and returns their paths. Generate only confirmed scenarios; prefer independent tests, semantic locators, explicit assertions, and environment-based secrets.
|
|
39
|
+
|
|
40
|
+
After Generator returns, the parent executes the generated test files with `npx playwright test`. This execution step is mandatory. If all tests pass, report the executed result. If any fail, pass the failed test names, failure output, confirmed plan, and generated file paths to Healer.
|
|
35
41
|
|
|
36
42
|
For API-only scenarios, use Playwright `APIRequestContext` directly and assert status, headers, schema, stable business invariants, and safe mutation cleanup.
|
|
37
43
|
|
|
38
44
|
## Healer
|
|
39
45
|
|
|
40
|
-
Use Healer only for failures.
|
|
46
|
+
Use Healer only for real failures from executing generated tests. Healer—not the parent—reproduces the failing tests with `npx playwright test`, inspects the UI with `playwright-cli`, applies justified test-side changes, and reruns the affected tests within guardrails until they pass or a genuine blocker is identified.
|
|
41
47
|
|
|
42
48
|
Do not weaken assertions, add arbitrary sleeps, retry blindly, or skip merely to pass. If behavior conflicts with the confirmed plan, preserve evidence and ask whether it is a regression or intended change. Classify unresolved failures as application defect, test defect, environment/data problem, or product decision.
|
|
43
49
|
|
|
@@ -13,24 +13,44 @@ const cliFirstInstructions = (role) => `${ROLE_BLOCK_START}
|
|
|
13
13
|
|
|
14
14
|
## Browser tool priority
|
|
15
15
|
|
|
16
|
-
Use the installed \`playwright-cli\` command as the primary browser interface. Read the globally installed \`playwright-cli\` skill when available. Start or attach a session with \`playwright-cli open\`/\`attach\`, navigate with \`goto\`, inspect compact state with \`snapshot\`, and interact through refs from the latest snapshot. Prefer \`snapshot\` and \`find\` over screenshots. Keep credentials in environment variables or ignored files and never print them.
|
|
16
|
+
Use the installed \`playwright-cli\` command as the primary browser interface for this role. Read the globally installed \`playwright-cli\` skill when available. Start or attach a session with \`playwright-cli open\`/\`attach\`, navigate with \`goto\`, inspect compact state with \`snapshot\`, and interact through refs from the latest snapshot. Prefer \`snapshot\` and \`find\` over screenshots. Keep credentials in environment variables or ignored files and never print them.
|
|
17
17
|
|
|
18
|
-
|
|
18
|
+
Keep the official Playwright Test MCP configuration and tools generated for this role; do not remove or disable them. Prefer CLI for live page interaction and use it when those MCP tools are unavailable, so missing \`planner_*\`, \`generator_*\`, \`test_*\`, or \`browser_*\` tools must not block the phase. Do not call Chrome DevTools or an unrelated browser integration, and do not spawn a nested or same-role agent.
|
|
19
19
|
|
|
20
|
-
${role === 'planner' ? 'FAST START:
|
|
20
|
+
${role === 'planner' ? 'FAST START: you are the Planner. The parent may pass relevant local-project context and answers gathered before this phase. When the request contains the test objective, deployed URL, and any information required to access the target, your first browser action must be `playwright-cli open <url>`; do not call `planner_setup_page` or any other browser/MCP action before this CLI open. After the session is open, use compact CLI `snapshot`/`find` output for exploration; MCP tools remain available as an optional supplement. Do not wait for the parent agent to open a browser, and do not first locate or read a seed file, Playwright config, test directory, agent definition, source tree, fixtures, or existing tests. Ask only when the supplied information is still missing, incorrect, contradictory, or exploration reaches a real blocker such as required credentials, ambiguous expected behavior that changes assertions, or authorization for a consequential action. Investigation is not the final output: you must turn the findings into a complete Markdown test plan and save it under `specs/` using filesystem tools or the available planner save tool. Return the saved plan path and scenario summary to the parent.' : ''}${role === 'generator' ? 'You are the Generator. Start only after the user confirms the saved test plan. Begin live validation with `playwright-cli open`/`attach` and use CLI snapshots/find to verify the confirmed plan; MCP setup and browser tools remain optional. Generate executable Playwright test code for the confirmed scenarios and write the test files using filesystem tools or the available generator write tool. Return the generated test file paths to the parent; generating code does not complete the workflow because the parent must execute the generated tests next.' : ''}${role === 'healer' ? 'You are the Healer. Start only after execution of the generated tests reports failures. Receive the failing test names and failure output, reproduce them with `npx playwright test`, begin UI diagnosis with `playwright-cli open`/`attach`, and use CLI snapshots/find to inspect the current UI; MCP tools remain optional. Diagnose and patch justified test defects, rerun the affected tests, and continue within the healer guardrails until they pass or a genuine application/environment/product blocker is identified. Return the final run result and classification to the parent.' : ''}
|
|
21
21
|
|
|
22
22
|
${ROLE_BLOCK_END}`;
|
|
23
23
|
const CODEX_INSTRUCTIONS = `${BLOCK_START}
|
|
24
24
|
## Playwright Test Agent
|
|
25
25
|
|
|
26
|
-
|
|
26
|
+
Codex routing is mandatory for website, browser workflow, HTTP API, or application-feature testing:
|
|
27
|
+
|
|
28
|
+
1. Load \`.agents/skills/playwright-test-agent/SKILL.md\`.
|
|
29
|
+
2. Before Planner, the main agent may read relevant local project information and ask for information that materially affects the test, such as the deployed URL, account or role, expected behavior, environment, and authorization boundary. Do not perform a seed/config/generated-file audit or open the website during preparation.
|
|
30
|
+
3. Do not start Playwright subagents. Once the required context is available, the main agent explicitly assumes the Planner role in this session.
|
|
31
|
+
4. Planner's first live browser action is \`playwright-cli open <url>\`. Prefer CLI while preserving the generated Playwright Test MCP configuration and tools. Do not call Chrome DevTools or an unrelated browser integration.
|
|
32
|
+
5. Planner must convert its investigation into a complete Markdown test plan under \`specs/\`. Show that saved plan to the user and wait for explicit confirmation; investigation alone is not completion.
|
|
33
|
+
6. After confirmation, assume Generator and generate executable Playwright test code for the confirmed plan. When generation finishes, execute the generated tests with \`npx playwright test\`; generating files alone is not completion.
|
|
34
|
+
7. If every generated test passes, report the result. If any generated test fails, assume Healer with the failed test names and output; diagnose, patch, and rerun until the tests pass or a genuine application/environment/product blocker is identified. Never skip execution and never report generated-but-unexecuted tests as passing.
|
|
35
|
+
|
|
36
|
+
Ask only for information that is necessary or could materially change scope, assertions, access, or safety. Do not guess or create nested agents.
|
|
27
37
|
|
|
28
38
|
${BLOCK_END}`;
|
|
29
39
|
|
|
30
40
|
const CLAUDE_INSTRUCTIONS = `${BLOCK_START}
|
|
31
41
|
## Playwright Test Agent
|
|
32
42
|
|
|
33
|
-
|
|
43
|
+
Claude Code routing is mandatory for website, browser workflow, HTTP API, or application-feature testing:
|
|
44
|
+
|
|
45
|
+
1. Load \`.claude/skills/playwright-test-agent/SKILL.md\`.
|
|
46
|
+
2. Before starting Planner, the main agent may read relevant local project information and ask for information that materially affects the test, such as the deployed URL, account or role, expected behavior, environment, and authorization boundary. Do not perform a seed/config/generated-file audit.
|
|
47
|
+
3. Once the required context is available, directly start \`playwright-test-planner\` with the objective, deployed URL, supplied access information, relevant project context, and constraints. The main agent must not open or inspect the website itself and must not call \`playwright-cli\`, Chrome DevTools, browser MCP tools, or another browser integration.
|
|
48
|
+
4. Planner opens and investigates the website with \`playwright-cli\`, converts its findings into a complete Markdown test plan under \`specs/\`, and returns the saved plan path. After Planner returns, show that plan to the user and wait for explicit confirmation; investigation alone is not completion.
|
|
49
|
+
5. Only after confirmation, directly start \`playwright-test-generator\` with the confirmed plan. Generator must validate the confirmed scenarios and write executable Playwright test files, then return their paths.
|
|
50
|
+
6. After Generator returns, the main agent must execute the generated tests with \`npx playwright test\`. Generating test files alone never completes the workflow.
|
|
51
|
+
7. If every generated test passes, report the result. If any generated test fails, directly start \`playwright-test-healer\` with the failed test names, failure output, confirmed plan, and generated file paths. Healer diagnoses and patches justified test defects and reruns the affected tests until they pass or it identifies a genuine application/environment/product blocker. Never report generated-but-unexecuted tests as passing.
|
|
52
|
+
|
|
53
|
+
Start each role directly and never create a nested or same-role intermediary. Do not locate a seed file or make setup-file discovery a prerequisite to Planner. If exploration finds missing, incorrect, or contradictory required information, let Planner pause and return the precise question; after the user answers, start or resume Planner with that answer and the blocking observation. Do not guess.
|
|
34
54
|
|
|
35
55
|
${BLOCK_END}`;
|
|
36
56
|
|
|
@@ -141,11 +161,11 @@ function patchClaudeRole(source, role) {
|
|
|
141
161
|
const remainder = header.slice(blockStart);
|
|
142
162
|
const nextKey = remainder.search(/\r?\n(?=[A-Za-z0-9_-]+:\s*)/);
|
|
143
163
|
const blockEnd = nextKey === -1 ? header.length : blockStart + nextKey;
|
|
144
|
-
|
|
164
|
+
let toolsBlock = header.slice(blockStart, blockEnd);
|
|
145
165
|
if (!/^\s*-\s+Bash\s*$/m.test(toolsBlock)) {
|
|
146
|
-
|
|
147
|
-
header.slice(blockStart);
|
|
166
|
+
toolsBlock = `\n - Bash${toolsBlock}`;
|
|
148
167
|
}
|
|
168
|
+
header = header.slice(0, blockStart) + toolsBlock + header.slice(blockEnd);
|
|
149
169
|
} else {
|
|
150
170
|
header = `${header.trimEnd()}\ntools: Bash`;
|
|
151
171
|
}
|
|
@@ -171,6 +191,61 @@ async function configureCliFirstRoles(projectDir) {
|
|
|
171
191
|
}
|
|
172
192
|
}
|
|
173
193
|
|
|
194
|
+
function escapeRegExp(value) {
|
|
195
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
function upsertTomlSection(source, section, settings) {
|
|
199
|
+
const headerPattern = new RegExp(`^\\[${escapeRegExp(section)}\\][ \\t]*$`, 'm');
|
|
200
|
+
const header = source.match(headerPattern);
|
|
201
|
+
|
|
202
|
+
if (!header) {
|
|
203
|
+
const body = Object.entries(settings).map(([key, value]) => `${key} = ${value}`).join('\n');
|
|
204
|
+
const separator = source.length === 0 ? '' : source.endsWith('\n') ? '\n' : '\n\n';
|
|
205
|
+
return `${source}${separator}[${section}]\n${body}\n`;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
const bodyStart = header.index + header[0].length;
|
|
209
|
+
const remainder = source.slice(bodyStart);
|
|
210
|
+
const nextHeader = remainder.search(/\r?\n(?=\[[^\]]+\][ \\t]*(?:\r?\n|$))/);
|
|
211
|
+
const bodyEnd = nextHeader === -1 ? source.length : bodyStart + nextHeader;
|
|
212
|
+
let body = source.slice(bodyStart, bodyEnd);
|
|
213
|
+
|
|
214
|
+
for (const [key, value] of Object.entries(settings)) {
|
|
215
|
+
const settingPattern = new RegExp(`(^|\\n)${escapeRegExp(key)}[ \\t]*=[^\\r\\n]*`);
|
|
216
|
+
if (settingPattern.test(body)) {
|
|
217
|
+
body = body.replace(settingPattern, `$1${key} = ${value}`);
|
|
218
|
+
} else {
|
|
219
|
+
body = `${body.trimEnd()}\n${key} = ${value}\n`;
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
return source.slice(0, bodyStart) + body + source.slice(bodyEnd);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
async function configureCodexMcp(projectDir) {
|
|
227
|
+
const codexDir = path.join(projectDir, '.codex');
|
|
228
|
+
const file = path.join(codexDir, 'config.toml');
|
|
229
|
+
await mkdir(codexDir, { recursive: true });
|
|
230
|
+
let source = await exists(file) ? await readFile(file, 'utf8') : '';
|
|
231
|
+
const command = process.platform === 'win32' ? '"cmd"' : '"npx"';
|
|
232
|
+
const args = process.platform === 'win32'
|
|
233
|
+
? '["/d", "/s", "/c", "npx", "--no-install", "playwright", "run-test-mcp-server"]'
|
|
234
|
+
: '["--no-install", "playwright", "run-test-mcp-server"]';
|
|
235
|
+
|
|
236
|
+
source = upsertTomlSection(source, 'mcp_servers.playwright-test', {
|
|
237
|
+
command,
|
|
238
|
+
args,
|
|
239
|
+
cwd: '"."',
|
|
240
|
+
enabled: 'true',
|
|
241
|
+
default_tools_approval_mode: '"approve"',
|
|
242
|
+
});
|
|
243
|
+
source = upsertTomlSection(source, 'mcp_servers.playwright-test.env', {
|
|
244
|
+
PLAYWRIGHT_MCP_OUTPUT_DIR: '".playwright-evidence/mcp"',
|
|
245
|
+
});
|
|
246
|
+
await writeFile(file, source, 'utf8');
|
|
247
|
+
}
|
|
248
|
+
|
|
174
249
|
async function installPlaywrightCli(projectDir, run) {
|
|
175
250
|
await run(projectDir, 'npm', ['install', '-g', '@playwright/cli@latest']);
|
|
176
251
|
await run(projectDir, 'playwright-cli', ['install', '--skills=agents', '--global']);
|
|
@@ -222,33 +297,7 @@ async function disableTraceScreenshots(projectDir) {
|
|
|
222
297
|
}
|
|
223
298
|
}
|
|
224
299
|
|
|
225
|
-
async function
|
|
226
|
-
const file = path.join(projectDir, '.mcp.json');
|
|
227
|
-
if (!await exists(file)) return;
|
|
228
|
-
const config = JSON.parse(await readFile(file, 'utf8'));
|
|
229
|
-
const server = config.mcpServers?.['playwright-test'];
|
|
230
|
-
if (!server) return;
|
|
231
|
-
server.env = {
|
|
232
|
-
...(server.env ?? {}),
|
|
233
|
-
PLAYWRIGHT_MCP_OUTPUT_DIR: '.playwright-evidence/mcp',
|
|
234
|
-
};
|
|
235
|
-
await writeFile(file, `${JSON.stringify(config, null, 2)}\n`, 'utf8');
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
async function configureCodexAgents(projectDir) {
|
|
239
|
-
for (const name of ['planner', 'generator', 'healer']) {
|
|
240
|
-
const file = path.join(projectDir, '.codex', 'agents', `playwright_test_${name}.toml`);
|
|
241
|
-
if (!await exists(file)) continue;
|
|
242
|
-
let source = await readFile(file, 'utf8');
|
|
243
|
-
if (!source.includes('[mcp_servers.playwright-test.env]')) {
|
|
244
|
-
source = `${source.trimEnd()}\n\n[mcp_servers.playwright-test.env]\n` +
|
|
245
|
-
'PLAYWRIGHT_MCP_OUTPUT_DIR = ".playwright-evidence/mcp"\n';
|
|
246
|
-
await writeFile(file, source, 'utf8');
|
|
247
|
-
}
|
|
248
|
-
}
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
async function initializePlaywright(projectDir, run) {
|
|
300
|
+
async function initializePlaywright(projectDir, run) {
|
|
252
301
|
const configPath = path.join(projectDir, 'playwright.config.ts');
|
|
253
302
|
if (!await exists(configPath)) {
|
|
254
303
|
await run(projectDir, 'npm', [
|
|
@@ -272,12 +321,11 @@ async function initializePlaywright(projectDir, run) {
|
|
|
272
321
|
await disableTraceScreenshots(projectDir);
|
|
273
322
|
|
|
274
323
|
await run(projectDir, 'npx', ['--no-install', 'playwright', 'init-agents', '--loop=codex']);
|
|
275
|
-
await run(projectDir, 'npx', ['--no-install', 'playwright', 'init-agents', '--loop=claude']);
|
|
276
|
-
await mkdir(path.join(projectDir, '.playwright-evidence', 'mcp'), { recursive: true });
|
|
277
|
-
await
|
|
278
|
-
await configureCodexAgents(projectDir);
|
|
324
|
+
await run(projectDir, 'npx', ['--no-install', 'playwright', 'init-agents', '--loop=claude']);
|
|
325
|
+
await mkdir(path.join(projectDir, '.playwright-evidence', 'mcp'), { recursive: true });
|
|
326
|
+
await configureCodexMcp(projectDir);
|
|
279
327
|
await configureCliFirstRoles(projectDir);
|
|
280
|
-
}
|
|
328
|
+
}
|
|
281
329
|
|
|
282
330
|
async function runStage(name, action) {
|
|
283
331
|
process.stdout.write(`[playwright-test-agent] ${name}...\n`);
|