playwright 1.57.0-alpha-2025-10-15 → 1.57.0-alpha-2025-10-16

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.
@@ -36,6 +36,8 @@ module.exports = __toCommonJS(generateAgents_exports);
36
36
  var import_fs = __toESM(require("fs"));
37
37
  var import_path = __toESM(require("path"));
38
38
  var import_utilsBundle = require("playwright-core/lib/utilsBundle");
39
+ var import_utils = require("playwright-core/lib/utils");
40
+ var import_seed = require("../mcp/test/seed");
39
41
  class AgentParser {
40
42
  static async parseFile(filePath) {
41
43
  const rawMarkdown = await import_fs.default.promises.readFile(filePath, "utf-8");
@@ -164,15 +166,46 @@ async function loadAgents() {
164
166
  const files = await import_fs.default.promises.readdir(__dirname);
165
167
  return Promise.all(files.filter((file) => file.endsWith(".md")).map((file) => AgentParser.parseFile(import_path.default.join(__dirname, file))));
166
168
  }
167
- async function writeFile(filePath, content) {
168
- console.log(`Writing file: ${filePath}`);
169
+ async function writeFile(filePath, content, icon, description) {
170
+ console.log(`- ${icon} ${import_path.default.relative(process.cwd(), filePath)} ${import_utilsBundle.colors.dim("- " + description)}`);
171
+ await (0, import_utils.mkdirIfNeeded)(filePath);
169
172
  await import_fs.default.promises.writeFile(filePath, content, "utf-8");
170
173
  }
171
- async function initClaudeCodeRepo() {
174
+ async function initRepo(config, projectName) {
175
+ const project = (0, import_seed.seedProject)(config, projectName);
176
+ console.log(`\u{1F3AD} Using project "${project.project.name}" as a primary project`);
177
+ if (!import_fs.default.existsSync("specs")) {
178
+ await import_fs.default.promises.mkdir("specs");
179
+ await writeFile(import_path.default.join("specs", "README.md"), `# Specs
180
+
181
+ This is a directory for test plans.
182
+ `, "\u{1F4DD}", "directory for test plans");
183
+ }
184
+ if (!import_fs.default.existsSync("prompts")) {
185
+ await import_fs.default.promises.mkdir("prompts");
186
+ await writeFile(import_path.default.join("prompts", "README.md"), `# Prompts
187
+
188
+ This is a directory for useful prompts.
189
+ `, "\u{1F4DD}", "useful prompts");
190
+ }
191
+ let seedFile = await (0, import_seed.findSeedFile)(project);
192
+ if (!seedFile) {
193
+ seedFile = (0, import_seed.defaultSeedFile)(project);
194
+ await writeFile(seedFile, import_seed.seedFileContent, "\u{1F331}", "default environment seed file");
195
+ }
196
+ const coveragePromptFile = import_path.default.join("prompts", "test-coverage.md");
197
+ if (!import_fs.default.existsSync(coveragePromptFile))
198
+ await writeFile(coveragePromptFile, coveragePrompt(seedFile), "\u{1F4DD}", "test coverage prompt");
199
+ }
200
+ function initRepoDone() {
201
+ console.log("\u2705 Done.");
202
+ }
203
+ async function initClaudeCodeRepo(config, projectName) {
204
+ await initRepo(config, projectName);
172
205
  const agents = await loadAgents();
173
206
  await import_fs.default.promises.mkdir(".claude/agents", { recursive: true });
174
207
  for (const agent of agents)
175
- await writeFile(`.claude/agents/playwright-test-${agent.header.name}.md`, saveAsClaudeCode(agent));
208
+ await writeFile(`.claude/agents/playwright-test-${agent.header.name}.md`, saveAsClaudeCode(agent), "\u{1F916}", "agent definition");
176
209
  await writeFile(".mcp.json", JSON.stringify({
177
210
  mcpServers: {
178
211
  "playwright-test": {
@@ -180,7 +213,8 @@ async function initClaudeCodeRepo() {
180
213
  args: commonMcpServers.playwrightTest.args
181
214
  }
182
215
  }
183
- }, null, 2));
216
+ }, null, 2), "\u{1F527}", "mcp configuration");
217
+ initRepoDone();
184
218
  }
185
219
  const vscodeToolMap = /* @__PURE__ */ new Map([
186
220
  ["ls", ["search/listDirectory", "search/fileSearch"]],
@@ -220,11 +254,12 @@ function saveAsVSCodeChatmode(agent) {
220
254
  lines.push(`<example>${example}</example>`);
221
255
  return lines.join("\n");
222
256
  }
223
- async function initVSCodeRepo() {
257
+ async function initVSCodeRepo(config, projectName) {
258
+ await initRepo(config, projectName);
224
259
  const agents = await loadAgents();
225
260
  await import_fs.default.promises.mkdir(".github/chatmodes", { recursive: true });
226
261
  for (const agent of agents)
227
- await writeFile(`.github/chatmodes/${agent.header.name === "planner" ? " " : ""}\u{1F3AD} ${agent.header.name}.chatmode.md`, saveAsVSCodeChatmode(agent));
262
+ await writeFile(`.github/chatmodes/${agent.header.name === "planner" ? " " : ""}\u{1F3AD} ${agent.header.name}.chatmode.md`, saveAsVSCodeChatmode(agent), "\u{1F916}", "chatmode definition");
228
263
  await import_fs.default.promises.mkdir(".vscode", { recursive: true });
229
264
  const mcpJsonPath = ".vscode/mcp.json";
230
265
  let mcpJson = {
@@ -243,20 +278,52 @@ async function initVSCodeRepo() {
243
278
  args: commonMcpServers.playwrightTest.args,
244
279
  cwd: "${workspaceFolder}"
245
280
  };
246
- await writeFile(mcpJsonPath, JSON.stringify(mcpJson, null, 2));
247
- console.log(import_utilsBundle.colors.yellow(`${import_utilsBundle.colors.bold("Note:")} Playwright Test Agents require VSCode version 1.105+ or VSCode Insiders`));
281
+ await writeFile(mcpJsonPath, JSON.stringify(mcpJson, null, 2), "\u{1F527}", "mcp configuration");
282
+ initRepoDone();
248
283
  }
249
- async function initOpencodeRepo() {
284
+ async function initOpencodeRepo(config, projectName) {
285
+ await initRepo(config, projectName);
250
286
  const agents = await loadAgents();
251
287
  await import_fs.default.promises.mkdir(".opencode/prompts", { recursive: true });
252
288
  for (const agent of agents) {
253
289
  const prompt = [agent.instructions];
254
290
  prompt.push("");
255
291
  prompt.push(...agent.examples.map((example) => `<example>${example}</example>`));
256
- await writeFile(`.opencode/prompts/playwright-test-${agent.header.name}.md`, prompt.join("\n"));
292
+ await writeFile(`.opencode/prompts/playwright-test-${agent.header.name}.md`, prompt.join("\n"), "\u{1F916}", "agent definition");
257
293
  }
258
- await writeFile("opencode.json", saveAsOpencodeJson(agents));
294
+ await writeFile("opencode.json", saveAsOpencodeJson(agents), "\u{1F527}", "opencode configuration");
295
+ initRepoDone();
259
296
  }
297
+ const coveragePrompt = (seedFile) => `
298
+ # Produce test coverage
299
+
300
+ Parameters:
301
+ - Task: the task to perform
302
+ - Seed file (optional): the seed file to use, defaults to ${import_path.default.relative(process.cwd(), seedFile)}
303
+ - Test plan file (optional): the test plan file to write, under specs/ folder.
304
+
305
+ 1. Call #planner subagent with prompt:
306
+
307
+ <plan>
308
+ <task><!-- the task --></task>
309
+ <seed-file><!-- seed file param --></seed-file>
310
+ <plan-file><!-- test plan file --></plan-file>
311
+ </plan>
312
+
313
+ 2. For each test case from the test plan file (1.1, 1.2, ...), Call #generator subagent with prompt:
314
+
315
+ <generate>
316
+ <test-file><!-- Name of the file to save the test into, should be unique for test --></test-file>
317
+ <test-suite><!-- Name of the top level test spec w/o ordinal--></test-suite>
318
+ <test-name><!--Name of the test case without the ordinal --></test-name>
319
+ <seed-file><!-- Seed file from test plan --></seed-file>
320
+ <body><!-- Test case content including steps and expectations --></body>
321
+ </generate>
322
+
323
+ 3. Call #healer subagent with prompt:
324
+
325
+ <heal>Run all tests and fix the failing ones one after another.</heal>
326
+ `;
260
327
  // Annotate the CommonJS export names for ESM import in node:
261
328
  0 && (module.exports = {
262
329
  initClaudeCodeRepo,
@@ -24,8 +24,8 @@ resolving Playwright test failures. Your mission is to systematically identify,
24
24
  broken Playwright tests using a methodical approach.
25
25
 
26
26
  Your workflow:
27
- 1. **Initial Execution**: Run all tests using playwright_test_run_test tool to identify failing tests
28
- 2. **Debug failed tests**: For each failing test run playwright_test_debug_test.
27
+ 1. **Initial Execution**: Run all tests using `test_run` tool to identify failing tests
28
+ 2. **Debug failed tests**: For each failing test run `test_debug`.
29
29
  3. **Error Investigation**: When the test pauses on errors, use available Playwright MCP tools to:
30
30
  - Examine the error details
31
31
  - Capture page snapshot to understand the context
@@ -38,7 +38,7 @@ You will:
38
38
  - Invoke the `planner_setup_page` tool once to set up page before using any other tools
39
39
  - Explore the browser snapshot
40
40
  - Do not take screenshots unless absolutely necessary
41
- - Use browser_* tools to navigate and discover interface
41
+ - Use `browser_*` tools to navigate and discover interface
42
42
  - Thoroughly explore the interface, identifying all interactive elements, forms, navigation paths, and functionality
43
43
 
44
44
  2. **Analyze User Flows**
@@ -61,7 +61,7 @@ const screenshot = (0, import_tool.defineTabTool)({
61
61
  if (params.fullPage && params.ref)
62
62
  throw new Error("fullPage cannot be used with element screenshots.");
63
63
  const fileType = params.type || "png";
64
- const fileName = await tab.context.outputFile(params.filename ?? (0, import_utils2.dateAsFileName)(fileType), { origin: "llm", reason: "Saving screenshot" });
64
+ const fileName = await tab.context.outputFile(params.filename || (0, import_utils2.dateAsFileName)(fileType), { origin: "llm", reason: "Saving screenshot" });
65
65
  const options = {
66
66
  type: fileType,
67
67
  quality: fileType === "png" ? void 0 : 90,
@@ -28,7 +28,10 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
28
28
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
29
  var seed_exports = {};
30
30
  __export(seed_exports, {
31
- ensureSeedTest: () => ensureSeedTest,
31
+ defaultSeedFile: () => defaultSeedFile,
32
+ ensureSeedFile: () => ensureSeedFile,
33
+ findSeedFile: () => findSeedFile,
34
+ seedFileContent: () => seedFileContent,
32
35
  seedProject: () => seedProject
33
36
  });
34
37
  module.exports = __toCommonJS(seed_exports);
@@ -44,29 +47,36 @@ function seedProject(config, projectName) {
44
47
  throw new Error(`Project ${projectName} not found`);
45
48
  return project;
46
49
  }
47
- async function ensureSeedTest(project, logNew) {
50
+ async function findSeedFile(project) {
48
51
  const files = await (0, import_projectUtils.collectFilesForProject)(project);
49
- const seed = files.find((file) => import_path.default.basename(file).includes("seed"));
50
- if (seed)
51
- return seed;
52
+ return files.find((file) => import_path.default.basename(file).includes("seed"));
53
+ }
54
+ function defaultSeedFile(project) {
52
55
  const testDir = project.project.testDir;
53
- const seedFile = import_path.default.resolve(testDir, "seed.spec.ts");
54
- if (logNew) {
55
- console.log(`Writing file: ${import_path.default.relative(process.cwd(), seedFile)}`);
56
- }
57
- await (0, import_utils.mkdirIfNeeded)(seedFile);
58
- await import_fs.default.promises.writeFile(seedFile, `import { test, expect } from '@playwright/test';
56
+ return import_path.default.resolve(testDir, "seed.spec.ts");
57
+ }
58
+ async function ensureSeedFile(project) {
59
+ const seedFile = await findSeedFile(project);
60
+ if (seedFile)
61
+ return seedFile;
62
+ const seedFilePath = defaultSeedFile(project);
63
+ await (0, import_utils.mkdirIfNeeded)(seedFilePath);
64
+ await import_fs.default.promises.writeFile(seedFilePath, seedFileContent);
65
+ return seedFilePath;
66
+ }
67
+ const seedFileContent = `import { test, expect } from '@playwright/test';
59
68
 
60
69
  test.describe('Test group', () => {
61
70
  test('seed', async ({ page }) => {
62
71
  // generate code here.
63
72
  });
64
73
  });
65
- `);
66
- return seedFile;
67
- }
74
+ `;
68
75
  // Annotate the CommonJS export names for ESM import in node:
69
76
  0 && (module.exports = {
70
- ensureSeedTest,
77
+ defaultSeedFile,
78
+ ensureSeedFile,
79
+ findSeedFile,
80
+ seedFileContent,
71
81
  seedProject
72
82
  });
@@ -98,7 +98,7 @@ class TestContext {
98
98
  const config = await testRunner.loadConfig();
99
99
  const project = (0, import_seed.seedProject)(config, projectName);
100
100
  if (!seedFile) {
101
- seedFile = await (0, import_seed.ensureSeedTest)(project, false);
101
+ seedFile = await (0, import_seed.ensureSeedFile)(project);
102
102
  } else {
103
103
  const candidateFiles = [];
104
104
  const testDir = project.project.testDir;
package/lib/program.js CHANGED
@@ -48,7 +48,6 @@ var import_testRunner = require("./runner/testRunner");
48
48
  var import_reporters = require("./runner/reporters");
49
49
  var import_exports = require("./mcp/sdk/exports");
50
50
  var import_testBackend = require("./mcp/test/testBackend");
51
- var import_seed = require("./mcp/test/seed");
52
51
  var import_program3 = require("./mcp/program");
53
52
  var import_watchdog = require("./mcp/browser/watchdog");
54
53
  var import_generateAgents = require("./agents/generateAgents");
@@ -185,19 +184,17 @@ function addInitAgentsCommand(program3) {
185
184
  command.option("-c, --config <file>", `Configuration file to find a project to use for seed test`);
186
185
  command.option("--project <project>", "Project to use for seed test");
187
186
  command.action(async (opts) => {
187
+ const config = await (0, import_configLoader.loadConfigFromFile)(opts.config);
188
188
  if (opts.loop === "opencode") {
189
- await (0, import_generateAgents.initOpencodeRepo)();
189
+ await (0, import_generateAgents.initOpencodeRepo)(config, opts.project);
190
190
  } else if (opts.loop === "vscode") {
191
- await (0, import_generateAgents.initVSCodeRepo)();
191
+ await (0, import_generateAgents.initVSCodeRepo)(config, opts.project);
192
192
  } else if (opts.loop === "claude") {
193
- await (0, import_generateAgents.initClaudeCodeRepo)();
193
+ await (0, import_generateAgents.initClaudeCodeRepo)(config, opts.project);
194
194
  } else {
195
195
  command.help();
196
196
  return;
197
197
  }
198
- const config = await (0, import_configLoader.loadConfigFromFile)(opts.config);
199
- const project = (0, import_seed.seedProject)(config, opts.project);
200
- await (0, import_seed.ensureSeedTest)(project, true);
201
198
  });
202
199
  }
203
200
  async function runTests(args, opts) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "playwright",
3
- "version": "1.57.0-alpha-2025-10-15",
3
+ "version": "1.57.0-alpha-2025-10-16",
4
4
  "description": "A high-level API to automate web browsers",
5
5
  "repository": {
6
6
  "type": "git",
@@ -64,7 +64,7 @@
64
64
  },
65
65
  "license": "Apache-2.0",
66
66
  "dependencies": {
67
- "playwright-core": "1.57.0-alpha-2025-10-15"
67
+ "playwright-core": "1.57.0-alpha-2025-10-16"
68
68
  },
69
69
  "optionalDependencies": {
70
70
  "fsevents": "2.3.2"