playwright 1.56.0-alpha-2025-10-01 → 1.56.0-beta-1759412259000

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.
@@ -28,7 +28,6 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
28
28
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
29
  var generatorTools_exports = {};
30
30
  __export(generatorTools_exports, {
31
- generatorLogStep: () => generatorLogStep,
32
31
  generatorReadLog: () => generatorReadLog,
33
32
  generatorWriteTest: () => generatorWriteTest,
34
33
  setupPage: () => setupPage
@@ -52,27 +51,9 @@ const setupPage = (0, import_testTool.defineTestTool)({
52
51
  type: "readOnly"
53
52
  },
54
53
  handle: async (context, params, progress) => {
55
- const seed = await context.getOrCreateSeedFile(params);
54
+ const seed = await context.getOrCreateSeedFile(params.seedFile, params.project);
56
55
  context.generatorJournal = new import_testContext.GeneratorJournal(context.rootPath, params.plan, seed);
57
- await context.runSeedTest(seed.file, params.project, progress);
58
- return { content: [] };
59
- }
60
- });
61
- const generatorLogStep = (0, import_testTool.defineTestTool)({
62
- schema: {
63
- name: "generator_log_step",
64
- title: "Log a test step",
65
- description: "Log a successful test step.",
66
- inputSchema: import_bundle.z.object({
67
- title: import_bundle.z.string().describe("Title of the test step"),
68
- code: import_bundle.z.string().describe("The code for the last step only, as a markdown code block")
69
- }),
70
- type: "readOnly"
71
- },
72
- handle: async (context, params) => {
73
- if (!context.generatorJournal)
74
- throw new Error(`Please setup page using "${setupPage.schema.name}" first.`);
75
- context.generatorJournal.logStep(params.title, params.code);
56
+ await context.runSeedTest(seed.file, seed.projectName, progress);
76
57
  return { content: [] };
77
58
  }
78
59
  });
@@ -103,7 +84,7 @@ const generatorWriteTest = (0, import_testTool.defineTestTool)({
103
84
  fileName: import_bundle.z.string().describe("The file to write the test to"),
104
85
  code: import_bundle.z.string().describe("The generated test code")
105
86
  }),
106
- type: "destructive"
87
+ type: "readOnly"
107
88
  },
108
89
  handle: async (context, params) => {
109
90
  if (!context.generatorJournal)
@@ -117,7 +98,9 @@ const generatorWriteTest = (0, import_testTool.defineTestTool)({
117
98
  const testDir = import_path.default.relative(context.rootPath, project.project.testDir).replace(/\\/g, "/");
118
99
  const fileName = params.fileName.replace(/\\/g, "/");
119
100
  if (fileName.startsWith(testDir)) {
120
- await import_fs.default.promises.writeFile(import_path.default.resolve(context.rootPath, fileName), params.code);
101
+ const resolvedFile = import_path.default.resolve(context.rootPath, fileName);
102
+ await import_fs.default.promises.mkdir(import_path.default.dirname(resolvedFile), { recursive: true });
103
+ await import_fs.default.promises.writeFile(resolvedFile, params.code);
121
104
  return {
122
105
  content: [{
123
106
  type: "text",
@@ -133,7 +116,6 @@ Test written to ${params.fileName}`
133
116
  });
134
117
  // Annotate the CommonJS export names for ESM import in node:
135
118
  0 && (module.exports = {
136
- generatorLogStep,
137
119
  generatorReadLog,
138
120
  generatorWriteTest,
139
121
  setupPage
@@ -35,8 +35,8 @@ const setupPage = (0, import_testTool.defineTestTool)({
35
35
  type: "readOnly"
36
36
  },
37
37
  handle: async (context, params, progress) => {
38
- const seed = await context.getOrCreateSeedFile(params);
39
- await context.runSeedTest(seed.file, params.project, progress);
38
+ const seed = await context.getOrCreateSeedFile(params.seedFile, params.project);
39
+ await context.runSeedTest(seed.file, seed.projectName, progress);
40
40
  return { content: [] };
41
41
  }
42
42
  });
@@ -44,8 +44,7 @@ function seedProject(config, projectName) {
44
44
  throw new Error(`Project ${projectName} not found`);
45
45
  return project;
46
46
  }
47
- async function ensureSeedTest(config, projectName, logNew) {
48
- const project = seedProject(config, projectName);
47
+ async function ensureSeedTest(project, logNew) {
49
48
  const files = await (0, import_projectUtils.collectFilesForProject)(project);
50
49
  const seed = files.find((file) => import_path.default.basename(file).includes("seed"));
51
50
  if (seed)
@@ -38,6 +38,7 @@ var generatorTools = __toESM(require("./generatorTools.js"));
38
38
  var plannerTools = __toESM(require("./plannerTools.js"));
39
39
  var import_tools = require("../browser/tools");
40
40
  var import_configLoader = require("../../common/configLoader");
41
+ var import_response = require("../browser/response");
41
42
  class TestServerBackend {
42
43
  constructor(configOption, options) {
43
44
  this.name = "Playwright";
@@ -45,7 +46,6 @@ class TestServerBackend {
45
46
  this._tools = [
46
47
  plannerTools.setupPage,
47
48
  generatorTools.setupPage,
48
- generatorTools.generatorLogStep,
49
49
  generatorTools.generatorReadLog,
50
50
  generatorTools.generatorWriteTest,
51
51
  testTools.listTests,
@@ -55,11 +55,6 @@ class TestServerBackend {
55
55
  this._context = new import_testContext.TestContext(options);
56
56
  this._configOption = configOption;
57
57
  }
58
- static {
59
- this.allowedOnPause = [
60
- generatorTools.generatorLogStep.schema.name
61
- ];
62
- }
63
58
  async initialize(server, clientInfo) {
64
59
  const rootPath = mcp.firstRootPath(clientInfo);
65
60
  if (this._configOption) {
@@ -75,9 +70,16 @@ class TestServerBackend {
75
70
  async listTools() {
76
71
  return [
77
72
  ...this._tools.map((tool) => mcp.toMcpTool(tool.schema)),
78
- ...import_tools.browserTools.map((tool) => mcp.toMcpTool(tool.schema))
73
+ ...import_tools.browserTools.map((tool) => mcp.toMcpTool(tool.schema, { addIntent: true }))
79
74
  ];
80
75
  }
76
+ async afterCallTool(name, args, result) {
77
+ if (!import_tools.browserTools.find((tool) => tool.schema.name === name))
78
+ return;
79
+ const response = (0, import_response.parseResponse)(result);
80
+ if (response && !response.isError && response.code && typeof args?.["intent"] === "string")
81
+ this._context.generatorJournal?.logStep(args["intent"], response.code);
82
+ }
81
83
  async callTool(name, args, progress) {
82
84
  const tool = this._tools.find((tool2) => tool2.schema.name === name);
83
85
  if (!tool)
@@ -49,7 +49,8 @@ class GeneratorJournal {
49
49
  this._steps = [];
50
50
  }
51
51
  logStep(title, code) {
52
- this._steps.push({ title, code });
52
+ if (title)
53
+ this._steps.push({ title, code });
53
54
  }
54
55
  journal() {
55
56
  const result = [];
@@ -61,7 +62,9 @@ class GeneratorJournal {
61
62
  result.push("```");
62
63
  result.push(`# Steps`);
63
64
  result.push(this._steps.map((step) => `### ${step.title}
64
- ${step.code}`).join("\n\n"));
65
+ \`\`\`ts
66
+ ${step.code}
67
+ \`\`\``).join("\n\n"));
65
68
  return result.join("\n\n");
66
69
  }
67
70
  }
@@ -88,30 +91,36 @@ class TestContext {
88
91
  this._testRunner = testRunner;
89
92
  return testRunner;
90
93
  }
91
- async getOrCreateSeedFile(params) {
94
+ async getOrCreateSeedFile(seedFile, projectName) {
92
95
  const configDir = this.configLocation.configDir;
93
96
  const testRunner = await this.createTestRunner();
94
97
  const config = await testRunner.loadConfig();
95
- let seedFile;
96
- if (!params.seedFile) {
97
- seedFile = await (0, import_seed.ensureSeedTest)(config, params.project, false);
98
+ const project = (0, import_seed.seedProject)(config, projectName);
99
+ if (!seedFile) {
100
+ seedFile = await (0, import_seed.ensureSeedTest)(project, false);
98
101
  } else {
99
102
  const candidateFiles = [];
100
- const testDir = (0, import_seed.seedProject)(config, params.project).project.testDir;
101
- candidateFiles.push(import_path.default.resolve(testDir, params.seedFile));
102
- candidateFiles.push(import_path.default.resolve(configDir, params.seedFile));
103
- candidateFiles.push(import_path.default.resolve(this.rootPath, params.seedFile));
103
+ const testDir = project.project.testDir;
104
+ candidateFiles.push(import_path.default.resolve(testDir, seedFile));
105
+ candidateFiles.push(import_path.default.resolve(configDir, seedFile));
106
+ candidateFiles.push(import_path.default.resolve(this.rootPath, seedFile));
107
+ let resolvedSeedFile;
104
108
  for (const candidateFile of candidateFiles) {
105
109
  if (await (0, import_util.fileExistsAsync)(candidateFile)) {
106
- seedFile = candidateFile;
110
+ resolvedSeedFile = candidateFile;
107
111
  break;
108
112
  }
109
113
  }
110
- if (!seedFile)
114
+ if (!resolvedSeedFile)
111
115
  throw new Error("seed test not found.");
116
+ seedFile = resolvedSeedFile;
112
117
  }
113
118
  const seedFileContent = await import_fs.default.promises.readFile(seedFile, "utf8");
114
- return { file: seedFile, content: seedFileContent };
119
+ return {
120
+ file: seedFile,
121
+ content: seedFileContent,
122
+ projectName: project.project.name
123
+ };
115
124
  }
116
125
  async runSeedTest(seedFile, projectName, progress) {
117
126
  const { screen } = this.createScreen(progress);
@@ -121,7 +130,7 @@ class TestContext {
121
130
  const result = await testRunner.runTests(reporter, {
122
131
  headed: !this.options?.headless,
123
132
  locations: ["/" + (0, import_utils.escapeRegExp)(seedFile) + "/"],
124
- projects: projectName ? [projectName] : void 0,
133
+ projects: [projectName],
125
134
  timeout: 0,
126
135
  workers: 1,
127
136
  pauseAtEnd: true,