playwright-test-agent 0.1.3 → 0.1.6
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.
|
@@ -7,7 +7,7 @@ import { initializeProject } from '../playwright-test-agent/scripts/init-playwri
|
|
|
7
7
|
const usage = `Usage: playwright-test-agent init [target-directory]
|
|
8
8
|
|
|
9
9
|
Initialize Playwright Test agents, install the playwright-test-agent skill,
|
|
10
|
-
and update AGENTS.md and CLAUDE.md
|
|
10
|
+
configure the project MCP servers, and update AGENTS.md and CLAUDE.md.`;
|
|
11
11
|
|
|
12
12
|
const [command, targetDirectory, ...extraArguments] = process.argv.slice(2);
|
|
13
13
|
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "playwright-test-agent",
|
|
3
|
-
"version": "0.1.
|
|
4
|
-
"description": "Initialize Playwright Test agents and
|
|
3
|
+
"version": "0.1.6",
|
|
4
|
+
"description": "Initialize Playwright Test, its agents, MCP configuration, and the playwright-test-agent skill.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
7
|
"playwright-test-agent": "bin/playwright-test-agent.mjs"
|
|
@@ -1,109 +1,64 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: playwright-test-agent
|
|
3
|
-
description: Use first when a user asks to test a website, browser workflow, HTTP API, or application feature, including planning,
|
|
3
|
+
description: Use first when a user asks to investigate or test a website, browser workflow, HTTP API, or application feature with Playwright, including test planning, generation, execution, debugging, healing, and evidence collection.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Playwright Test Agent
|
|
7
7
|
|
|
8
|
-
Use Playwright
|
|
8
|
+
Use Playwright's Planner -> Generator -> Healer workflow for durable, auditable tests. `AGENTS.md` or `CLAUDE.md` defines how the active platform assumes or launches those roles; this Skill contains only their shared workflow.
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
## Prepare the objective
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
The main agent may inspect the local project for relevant requirements, routes, fixtures, and constraints. Do not require a setup audit or check for a seed, Playwright config, or generated files before beginning Planner.
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
|---|---|---|
|
|
16
|
-
| Planner | `playwright_test_planner` | `playwright-test-planner` |
|
|
17
|
-
| Generator | `playwright_test_generator` | `playwright-test-generator` |
|
|
18
|
-
| Healer | `playwright_test_healer` | `playwright-test-healer` |
|
|
14
|
+
Before planning, ask the user for information that could materially change the test purpose, scope, safety, or expected behavior, such as the deployed URL, intended role, success criteria, allowed data mutations, and required environment. Do not ask for UI details Planner can safely discover.
|
|
19
15
|
|
|
20
|
-
|
|
16
|
+
If the request is sufficient, begin Planner immediately. If investigation reveals that a URL, credential, role, prerequisite, expected result, or authorization boundary is missing, incorrect, or contradictory, pause Planner and ask for the specific correction. Resume Planner with the corrected information and blocking observation. Do not guess credentials, probe nearby environments, bypass access controls, or wander through unrelated pages.
|
|
21
17
|
|
|
22
|
-
|
|
18
|
+
Keep credentials and tokens in environment variables or ignored secret files. Never copy them into plans, tests, screenshots, evidence, or chat.
|
|
23
19
|
|
|
24
|
-
|
|
25
|
-
- **Planner:** Run the generated seed to establish page context, global setup, dependencies, fixtures, and hooks. Explore the deployed application for the requested scenarios and user flows, compare observations with the request and optional PRD, and save a precise human-readable Markdown plan under `specs/`. It does not generate the formal test files.
|
|
26
|
-
- **Generator:** Read the complete user-confirmed Markdown plan and the same generated seed, execute each scenario to validate locators and assertions against the live application, and generate executable Playwright tests under the configured test directory. It must not invent unconfirmed scenarios or expected behavior.
|
|
27
|
-
- **Healer:** Run the failing test, replay its steps, inspect the current UI, propose and apply test-side patches, and rerun until the test passes or a guardrail stops the loop. It must report a likely broken product, environment/data problem, or plan conflict instead of weakening assertions merely to obtain a pass.
|
|
20
|
+
## Planner
|
|
28
21
|
|
|
29
|
-
|
|
22
|
+
Planner owns live application investigation and saves a human-readable Markdown plan under `specs/`. Start page setup immediately. Supply a seed only when the user or request explicitly identifies one; otherwise allow Playwright to use its initialized default. Do not perform a separate seed/config discovery pass.
|
|
30
23
|
|
|
31
|
-
|
|
32
|
-
request + deployed URL -> locate generated seed -> planner -> user confirms plan
|
|
33
|
-
-> generator -> healer for failures -> final report
|
|
34
|
-
```
|
|
35
|
-
|
|
36
|
-
## Initialize once per project
|
|
37
|
-
|
|
38
|
-
Inspect the target project first. If Playwright Test, its config, or either Codex/Claude agent set is missing, tell the user initialization will modify the project, then run from the target project:
|
|
39
|
-
|
|
40
|
-
```bash
|
|
41
|
-
npx playwright-test-agent init
|
|
42
|
-
```
|
|
43
|
-
|
|
44
|
-
The command installs this skill for Codex and Claude, selects the ready-to-use Playwright defaults (TypeScript, `playwright-tests/`, no GitHub Actions, Chromium with browser installation), and runs both:
|
|
45
|
-
|
|
46
|
-
```text
|
|
47
|
-
npx playwright init-agents --loop=codex
|
|
48
|
-
npx playwright init-agents --loop=claude
|
|
49
|
-
```
|
|
50
|
-
|
|
51
|
-
It uses the project-local Playwright command. Never install a global/additional Playwright CLI or run `playwright init-skills`.
|
|
52
|
-
|
|
53
|
-
`playwright init-agents` also creates the project's default `seed.spec.ts`. Its directory follows the selected Playwright project's `testDir`, so it may be under `playwright-tests/`, `e2e/`, `tests/`, or another configured directory. Do not hardcode the path. Locate it from `playwright.config.*`, the generated agent definitions, or the filesystem before invoking planner or generator.
|
|
54
|
-
|
|
55
|
-
## Understand the request
|
|
24
|
+
The plan contains prerequisites, test data requirements, independent scenarios, steps, observable expected results, exclusions, and intended test outputs. Reconnaissance must not create durable/shared data or perform purchases, submissions, messages, deletion, or other consequential actions unless the user authorized them.
|
|
56
25
|
|
|
57
|
-
|
|
26
|
+
Show the completed scenario list and exclusions to the user. Generator may start only after the user confirms the plan.
|
|
58
27
|
|
|
59
|
-
|
|
28
|
+
## Generator
|
|
60
29
|
|
|
61
|
-
|
|
30
|
+
Generator converts the complete confirmed Markdown plan into executable Playwright tests and validates locators and assertions against the application. Generate only confirmed scenarios. Prefer independent tests, semantic locators, assertions for every expected result, and environment-based secrets.
|
|
62
31
|
|
|
63
|
-
|
|
32
|
+
For API-only scenarios, Playwright `APIRequestContext` tests may be written directly. Assert status, headers, schema, stable business invariants, and safe mutation cleanup.
|
|
64
33
|
|
|
65
|
-
|
|
34
|
+
## Healer
|
|
66
35
|
|
|
67
|
-
|
|
36
|
+
Use Healer only for failing generated tests. Diagnose one failing test at a time, replay the failure, inspect the current application state, apply a test-side correction when justified, and rerun within the role's guardrails.
|
|
68
37
|
|
|
69
|
-
|
|
38
|
+
Do not weaken assertions, add arbitrary sleeps, retry blindly, or skip a test merely to obtain a pass. If behavior conflicts with the confirmed plan, preserve the evidence and ask whether it is a regression or intended product change. Classify unresolved failures as an application defect, test defect, environment/data problem, or product decision.
|
|
70
39
|
|
|
71
|
-
|
|
40
|
+
## Evidence
|
|
72
41
|
|
|
73
|
-
|
|
42
|
+
Keep generated evidence under `.playwright-evidence/`:
|
|
74
43
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
Show the complete scenario list and exclusions to the user. Ask whether it is complete. Revise until confirmed. Do not invoke the generator or formally execute tests before confirmation.
|
|
84
|
-
|
|
85
|
-
## Generate and run
|
|
86
|
-
|
|
87
|
-
For confirmed UI scenarios, invoke the Generator once for the complete confirmed plan (or complete selected scenario set), explicitly naming the Markdown plan and the same generated seed; use the configured Playwright test directory for generated tests. The Generator executes scenarios against the live application to validate locators and assertions while generating. Its internal per-scenario setup does not mean starting a new Generator agent for every scenario. Require one independent test per file, semantic locators, an assertion for every expected result, and environment-based secrets.
|
|
88
|
-
|
|
89
|
-
For confirmed API-only scenarios, write `APIRequestContext` tests directly under `playwright-tests/`. Assert status, headers, schema, and stable business invariants; define safe setup/cleanup for mutations.
|
|
44
|
+
```text
|
|
45
|
+
.playwright-evidence/
|
|
46
|
+
|-- mcp/
|
|
47
|
+
|-- snapshots/
|
|
48
|
+
|-- test-results/
|
|
49
|
+
`-- report/
|
|
50
|
+
```
|
|
90
51
|
|
|
91
|
-
|
|
52
|
+
Keep trace DOM snapshots, sources, network data, and attachments, but set trace `screenshots: false`. Trace screenshots are screencast frames and can create hundreds of JPEG resources. Explicit screenshots and failure evidence remain available when needed; avoid secrets and sensitive personal data.
|
|
92
53
|
|
|
93
|
-
|
|
54
|
+
Report the plan path, generated test paths, pass/fail/flaky/skipped counts when tests ran, evidence paths, and failure classification. Never report a skipped or unresolved test as success.
|
|
94
55
|
|
|
95
|
-
##
|
|
56
|
+
## Initialization
|
|
96
57
|
|
|
97
|
-
|
|
58
|
+
When this Skill or the Playwright Test tools are unavailable, run from the target project:
|
|
98
59
|
|
|
99
|
-
```
|
|
100
|
-
|
|
101
|
-
├── mcp/ # page YAML snapshots, screenshots, and agent logs
|
|
102
|
-
├── snapshots/ # reusable visual/ARIA baselines
|
|
103
|
-
├── test-results/ # failure screenshots, traces, videos, attachments
|
|
104
|
-
└── report/ # HTML report
|
|
60
|
+
```bash
|
|
61
|
+
npx playwright-test-agent init
|
|
105
62
|
```
|
|
106
63
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
Finish by reporting the plan path, generated test paths, environment without secrets, pass/fail/flaky/skipped counts, and evidence paths. Classify failures as application defect, test defect, environment/data problem, or unresolved product decision.
|
|
64
|
+
The initializer installs the Skill, generates the official role definitions, and configures each platform. Restart the active agent session after initialization so newly configured tools are registered.
|
|
@@ -10,21 +10,24 @@ const BLOCK_END = '<!-- playwright-test-agent:end -->';
|
|
|
10
10
|
const CODEX_INSTRUCTIONS = `${BLOCK_START}
|
|
11
11
|
## Playwright Test Agent
|
|
12
12
|
|
|
13
|
-
For
|
|
13
|
+
For website, browser workflow, HTTP API, or application-feature testing, first load and follow \`.agents/skills/playwright-test-agent/SKILL.md\`.
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
Codex must not start \`playwright_test_planner\`, \`playwright_test_generator\`, \`playwright_test_healer\`, or another Playwright subagent. The main agent performs Planner -> Generator -> Healer in the same session with the project-level \`playwright-test\` MCP tools.
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
For each phase, read the matching generated role definition and follow its \`developer_instructions\` directly:
|
|
18
|
+
- Planner: \`.codex/agents/playwright_test_planner.toml\`; call \`planner_setup_page\`, \`browser_*\`, then \`planner_save_plan\`.
|
|
19
|
+
- Generator: \`.codex/agents/playwright_test_generator.toml\`; call \`generator_setup_page\`, \`browser_*\`, \`generator_read_log\`, then \`generator_write_test\`.
|
|
20
|
+
- Healer: \`.codex/agents/playwright_test_healer.toml\`; call \`test_list\`, \`test_run\`, \`test_debug\`, and relevant \`browser_*\` tools.
|
|
21
|
+
|
|
22
|
+
These TOML files are role instructions to read, not agents to launch. If the project-level \`playwright-test\` tools are absent, ask the user to rerun \`npx playwright-test-agent init\` and restart Codex; do not create a subagent fallback. Ask for missing or contradictory test-purpose, access, role, data, or safety information before or during Planner, then resume the same phase after clarification. The Skill contains the shared testing rules.
|
|
18
23
|
${BLOCK_END}`;
|
|
19
24
|
|
|
20
25
|
const CLAUDE_INSTRUCTIONS = `${BLOCK_START}
|
|
21
26
|
## Playwright Test Agent
|
|
22
27
|
|
|
23
|
-
For
|
|
24
|
-
|
|
25
|
-
For UI testing, the Claude Code subagents are \`playwright-test-planner\`, \`playwright-test-generator\`, and \`playwright-test-healer\`. The main agent may inspect only the local project; it must not open, navigate, inspect, screenshot, or otherwise investigate the deployed website itself. Before starting Planner, the main agent may ask for necessary information that materially affects test purpose, scope, expected outcomes, roles, allowed side effects, data, or environment constraints. It must not ask for UI details Planner can safely discover. Once the objective, deployed URL, and necessary non-discoverable constraints are available, start \`playwright-test-planner\` to perform all live page investigation.
|
|
28
|
+
For website, browser workflow, HTTP API, or application-feature testing, first load and follow \`.claude/skills/playwright-test-agent/SKILL.md\`.
|
|
26
29
|
|
|
27
|
-
|
|
30
|
+
Claude Code uses the official \`playwright-test-planner\`, \`playwright-test-generator\`, and \`playwright-test-healer\` subagents. Start each required role directly and never insert a nested or same-role intermediary. Use Planner for all live website investigation, Generator only after the user confirms the saved plan, and Healer for failing generated tests. Ask for missing or contradictory test-purpose, access, role, data, or safety information before or during Planner, then resume the same phase after clarification. The Skill contains the shared testing rules.
|
|
28
31
|
${BLOCK_END}`;
|
|
29
32
|
|
|
30
33
|
const exists = async (file) => {
|
|
@@ -98,10 +101,38 @@ async function patchPlaywrightConfig(projectDir) {
|
|
|
98
101
|
/use:\s*\{/,
|
|
99
102
|
"outputDir: '.playwright-evidence/test-results',\n snapshotPathTemplate: '.playwright-evidence/snapshots/{testFilePath}/{arg}{ext}',\n use: {\n screenshot: 'only-on-failure',\n video: 'retain-on-failure',",
|
|
100
103
|
);
|
|
101
|
-
source = source.replace(
|
|
104
|
+
source = source.replace(
|
|
105
|
+
/trace:\s*['"][^'"]+['"]/,
|
|
106
|
+
"trace: { mode: 'retain-on-failure', screenshots: false, snapshots: true, sources: true, attachments: true }",
|
|
107
|
+
);
|
|
102
108
|
await writeFile(configPath, source, 'utf8');
|
|
103
109
|
}
|
|
104
110
|
|
|
111
|
+
function withoutTraceScreenshots(source) {
|
|
112
|
+
const replacement = "trace: { mode: 'retain-on-failure', screenshots: false, snapshots: true, sources: true, attachments: true }";
|
|
113
|
+
const fromString = source.replace(/trace:\s*['"][^'"]+['"]/, replacement);
|
|
114
|
+
if (fromString !== source) return fromString;
|
|
115
|
+
|
|
116
|
+
return source.replace(/trace:\s*\{([\s\S]*?)\}/, (setting, body) => {
|
|
117
|
+
if (/screenshots\s*:/.test(body)) {
|
|
118
|
+
return setting.replace(/screenshots\s*:\s*(?:true|false)/, 'screenshots: false');
|
|
119
|
+
}
|
|
120
|
+
return setting.replace('{', '{ screenshots: false,');
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
async function disableTraceScreenshots(projectDir) {
|
|
125
|
+
const configPath = path.join(projectDir, 'playwright.config.ts');
|
|
126
|
+
if (!await exists(configPath)) return;
|
|
127
|
+
|
|
128
|
+
let source = await readFile(configPath, 'utf8');
|
|
129
|
+
const updated = withoutTraceScreenshots(source);
|
|
130
|
+
|
|
131
|
+
if (updated !== source) {
|
|
132
|
+
await writeFile(configPath, updated, 'utf8');
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
105
136
|
async function configureClaudeMcp(projectDir) {
|
|
106
137
|
const file = path.join(projectDir, '.mcp.json');
|
|
107
138
|
if (!await exists(file)) return;
|
|
@@ -115,17 +146,128 @@ async function configureClaudeMcp(projectDir) {
|
|
|
115
146
|
await writeFile(file, `${JSON.stringify(config, null, 2)}\n`, 'utf8');
|
|
116
147
|
}
|
|
117
148
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
149
|
+
function normalizeTomlTableName(name) {
|
|
150
|
+
return name
|
|
151
|
+
.split('.')
|
|
152
|
+
.map((part) => part.trim().replace(/^(?:"([^"]+)"|'([^']+)')$/, '$1$2'))
|
|
153
|
+
.join('.');
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
function findTomlTables(lines, tableName) {
|
|
157
|
+
const matches = [];
|
|
158
|
+
for (let index = 0; index < lines.length; index += 1) {
|
|
159
|
+
const match = lines[index].match(/^\s*\[([^\]]+)\]\s*(?:#.*)?$/);
|
|
160
|
+
if (match && normalizeTomlTableName(match[1]) === tableName) matches.push(index);
|
|
161
|
+
}
|
|
162
|
+
return matches;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
function listTomlTableNames(lines) {
|
|
166
|
+
return lines
|
|
167
|
+
.map((line) => line.match(/^\s*\[([^\]]+)\]\s*(?:#.*)?$/))
|
|
168
|
+
.filter(Boolean)
|
|
169
|
+
.map((match) => normalizeTomlTableName(match[1]));
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
function assignmentEnd(lines, start, limit) {
|
|
173
|
+
let square = 0;
|
|
174
|
+
let curly = 0;
|
|
175
|
+
let quote = null;
|
|
176
|
+
let escaped = false;
|
|
177
|
+
|
|
178
|
+
for (let index = start; index < limit; index += 1) {
|
|
179
|
+
for (const character of lines[index]) {
|
|
180
|
+
if (escaped) {
|
|
181
|
+
escaped = false;
|
|
182
|
+
} else if (quote === '"' && character === '\\') {
|
|
183
|
+
escaped = true;
|
|
184
|
+
} else if (quote) {
|
|
185
|
+
if (character === quote) quote = null;
|
|
186
|
+
} else if (character === '"' || character === "'") {
|
|
187
|
+
quote = character;
|
|
188
|
+
} else if (character === '#') {
|
|
189
|
+
break;
|
|
190
|
+
} else if (character === '[') {
|
|
191
|
+
square += 1;
|
|
192
|
+
} else if (character === ']') {
|
|
193
|
+
square -= 1;
|
|
194
|
+
} else if (character === '{') {
|
|
195
|
+
curly += 1;
|
|
196
|
+
} else if (character === '}') {
|
|
197
|
+
curly -= 1;
|
|
198
|
+
}
|
|
127
199
|
}
|
|
200
|
+
if (square <= 0 && curly <= 0 && !quote) return index + 1;
|
|
128
201
|
}
|
|
202
|
+
return limit;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
function replaceTomlTable(lines, tableName, assignments, removedKeys = []) {
|
|
206
|
+
const matches = findTomlTables(lines, tableName);
|
|
207
|
+
if (matches.length > 1) {
|
|
208
|
+
throw new Error(`duplicate [${tableName}] tables in .codex/config.toml`);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
const body = [`[${tableName}]`, ...Object.entries(assignments).map(([key, value]) => `${key} = ${value}`)];
|
|
212
|
+
if (matches.length === 0) {
|
|
213
|
+
while (lines.at(-1) === '') lines.pop();
|
|
214
|
+
if (lines.length > 0) lines.push('');
|
|
215
|
+
lines.push(...body, '');
|
|
216
|
+
return;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
const start = matches[0];
|
|
220
|
+
let end = start + 1;
|
|
221
|
+
while (end < lines.length && !/^\s*\[\[?[^\]]+\]\]?\s*(?:#.*)?$/.test(lines[end])) {
|
|
222
|
+
end += 1;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
const replacedKeys = new Set([...Object.keys(assignments), ...removedKeys]);
|
|
226
|
+
const preserved = [];
|
|
227
|
+
for (let index = start + 1; index < end;) {
|
|
228
|
+
const match = lines[index].match(/^\s*([A-Za-z0-9_-]+)\s*=/);
|
|
229
|
+
if (match && replacedKeys.has(match[1])) {
|
|
230
|
+
index = assignmentEnd(lines, index, end);
|
|
231
|
+
} else {
|
|
232
|
+
preserved.push(lines[index]);
|
|
233
|
+
index += 1;
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
while (preserved[0] === '') preserved.shift();
|
|
237
|
+
while (preserved.at(-1) === '') preserved.pop();
|
|
238
|
+
lines.splice(start, end - start, ...body, ...(preserved.length ? ['', ...preserved] : []), '');
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
async function configureCodexMainMcp(projectDir) {
|
|
242
|
+
const codexDir = path.join(projectDir, '.codex');
|
|
243
|
+
const file = path.join(codexDir, 'config.toml');
|
|
244
|
+
await mkdir(codexDir, { recursive: true });
|
|
245
|
+
|
|
246
|
+
const source = await exists(file) ? await readFile(file, 'utf8') : '';
|
|
247
|
+
const lines = source.replace(/\r\n?/g, '\n').split('\n');
|
|
248
|
+
const command = process.platform === 'win32' ? 'cmd' : 'npx';
|
|
249
|
+
const args = process.platform === 'win32'
|
|
250
|
+
? '["/d", "/s", "/c", "npx", "--no-install", "playwright", "run-test-mcp-server"]'
|
|
251
|
+
: '["--no-install", "playwright", "run-test-mcp-server"]';
|
|
252
|
+
|
|
253
|
+
replaceTomlTable(lines, 'mcp_servers.playwright-test', {
|
|
254
|
+
command: `"${command}"`,
|
|
255
|
+
args,
|
|
256
|
+
cwd: '"."',
|
|
257
|
+
enabled: 'true',
|
|
258
|
+
default_tools_approval_mode: '"approve"',
|
|
259
|
+
}, ['enabled_tools', 'disabled_tools']);
|
|
260
|
+
replaceTomlTable(lines, 'mcp_servers.playwright-test.env', {
|
|
261
|
+
PLAYWRIGHT_MCP_OUTPUT_DIR: '".playwright-evidence/mcp"',
|
|
262
|
+
});
|
|
263
|
+
for (const tableName of new Set(listTomlTableNames(lines))) {
|
|
264
|
+
if (tableName.startsWith('mcp_servers.playwright-test.tools.')) {
|
|
265
|
+
replaceTomlTable(lines, tableName, { approval_mode: '"approve"' });
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
while (lines.at(-1) === '') lines.pop();
|
|
270
|
+
await writeFile(file, `${lines.join('\n')}\n`, 'utf8');
|
|
129
271
|
}
|
|
130
272
|
|
|
131
273
|
async function initializePlaywright(projectDir, run) {
|
|
@@ -149,11 +291,13 @@ async function initializePlaywright(projectDir, run) {
|
|
|
149
291
|
await patchPlaywrightConfig(projectDir);
|
|
150
292
|
}
|
|
151
293
|
|
|
294
|
+
await disableTraceScreenshots(projectDir);
|
|
295
|
+
|
|
152
296
|
await run(projectDir, 'npx', ['--no-install', 'playwright', 'init-agents', '--loop=codex']);
|
|
153
297
|
await run(projectDir, 'npx', ['--no-install', 'playwright', 'init-agents', '--loop=claude']);
|
|
154
298
|
await mkdir(path.join(projectDir, '.playwright-evidence', 'mcp'), { recursive: true });
|
|
155
299
|
await configureClaudeMcp(projectDir);
|
|
156
|
-
await
|
|
300
|
+
await configureCodexMainMcp(projectDir);
|
|
157
301
|
}
|
|
158
302
|
|
|
159
303
|
async function runStage(name, action) {
|
|
@@ -179,7 +323,8 @@ export async function initializeProject({
|
|
|
179
323
|
|
|
180
324
|
process.stdout.write(
|
|
181
325
|
'Playwright Test Agent ready: skills installed for Codex and Claude, ' +
|
|
182
|
-
'tests in playwright-tests/, evidence in .playwright-evidence
|
|
326
|
+
'tests in playwright-tests/, evidence in .playwright-evidence/. ' +
|
|
327
|
+
'Restart Codex so it loads the project-level playwright-test MCP server.\n',
|
|
183
328
|
);
|
|
184
329
|
}
|
|
185
330
|
|