playwright 1.58.0-alpha-2025-12-07 → 1.58.0-alpha-2025-12-09

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/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # 🎭 Playwright
2
2
 
3
- [![npm version](https://img.shields.io/npm/v/playwright.svg)](https://www.npmjs.com/package/playwright) <!-- GEN:chromium-version-badge -->[![Chromium version](https://img.shields.io/badge/chromium-143.0.7499.25-blue.svg?logo=google-chrome)](https://www.chromium.org/Home)<!-- GEN:stop --> <!-- GEN:firefox-version-badge -->[![Firefox version](https://img.shields.io/badge/firefox-145.0.1-blue.svg?logo=firefoxbrowser)](https://www.mozilla.org/en-US/firefox/new/)<!-- GEN:stop --> <!-- GEN:webkit-version-badge -->[![WebKit version](https://img.shields.io/badge/webkit-26.0-blue.svg?logo=safari)](https://webkit.org/)<!-- GEN:stop --> [![Join Discord](https://img.shields.io/badge/join-discord-informational)](https://aka.ms/playwright/discord)
3
+ [![npm version](https://img.shields.io/npm/v/playwright.svg)](https://www.npmjs.com/package/playwright) <!-- GEN:chromium-version-badge -->[![Chromium version](https://img.shields.io/badge/chromium-143.0.7499.25-blue.svg?logo=google-chrome)](https://www.chromium.org/Home)<!-- GEN:stop --> <!-- GEN:firefox-version-badge -->[![Firefox version](https://img.shields.io/badge/firefox-145.0.2-blue.svg?logo=firefoxbrowser)](https://www.mozilla.org/en-US/firefox/new/)<!-- GEN:stop --> <!-- GEN:webkit-version-badge -->[![WebKit version](https://img.shields.io/badge/webkit-26.0-blue.svg?logo=safari)](https://webkit.org/)<!-- GEN:stop --> [![Join Discord](https://img.shields.io/badge/join-discord-informational)](https://aka.ms/playwright/discord)
4
4
 
5
5
  ## [Documentation](https://playwright.dev) | [API reference](https://playwright.dev/docs/api/class-playwright)
6
6
 
@@ -10,7 +10,7 @@ Playwright is a framework for Web Testing and Automation. It allows testing [Chr
10
10
  | :--- | :---: | :---: | :---: |
11
11
  | Chromium <!-- GEN:chromium-version -->143.0.7499.25<!-- GEN:stop --> | :white_check_mark: | :white_check_mark: | :white_check_mark: |
12
12
  | WebKit <!-- GEN:webkit-version -->26.0<!-- GEN:stop --> | :white_check_mark: | :white_check_mark: | :white_check_mark: |
13
- | Firefox <!-- GEN:firefox-version -->145.0.1<!-- GEN:stop --> | :white_check_mark: | :white_check_mark: | :white_check_mark: |
13
+ | Firefox <!-- GEN:firefox-version -->145.0.2<!-- GEN:stop --> | :white_check_mark: | :white_check_mark: | :white_check_mark: |
14
14
 
15
15
  Headless execution is supported for all browsers on all platforms. Check out [system requirements](https://playwright.dev/docs/intro#system-requirements) for details.
16
16
 
package/index.js CHANGED
@@ -14,7 +14,4 @@
14
14
  * limitations under the License.
15
15
  */
16
16
 
17
- const playwright = require('playwright-core');
18
- const { decoratePage } = require('./lib/agents/pageDecorator');
19
- decoratePage(playwright);
20
- module.exports = playwright;
17
+ module.exports = require('playwright-core');
@@ -30,6 +30,13 @@ class ProcessRunner {
30
30
  const response = { method, params };
31
31
  sendMessageToParent({ method: "__dispatch__", params: response });
32
32
  }
33
+ async sendRequest(method, params) {
34
+ return await sendRequestToParent(method, params);
35
+ }
36
+ async sendMessageNoReply(method, params) {
37
+ void sendRequestToParent(method, params).catch(() => {
38
+ });
39
+ }
33
40
  }
34
41
  let gracefullyCloseCalled = false;
35
42
  let forceExitInitiated = false;
@@ -70,6 +77,8 @@ process.on("message", async (message) => {
70
77
  sendMessageToParent({ method: "__dispatch__", params: response });
71
78
  }
72
79
  }
80
+ if (message.method === "__response__")
81
+ handleResponseFromParent(message.params);
73
82
  });
74
83
  const kForceExitTimeout = +(process.env.PWTEST_FORCE_EXIT_TIMEOUT || 3e4);
75
84
  async function gracefullyCloseAndExit(forceExit) {
@@ -98,6 +107,25 @@ function sendMessageToParent(message) {
98
107
  }
99
108
  }
100
109
  }
110
+ let lastId = 0;
111
+ const requestCallbacks = /* @__PURE__ */ new Map();
112
+ async function sendRequestToParent(method, params) {
113
+ const id = ++lastId;
114
+ sendMessageToParent({ method: "__request__", params: { id, method, params } });
115
+ const promise = new import_utils.ManualPromise();
116
+ requestCallbacks.set(id, promise);
117
+ return promise;
118
+ }
119
+ function handleResponseFromParent(response) {
120
+ const promise = requestCallbacks.get(response.id);
121
+ if (!promise)
122
+ return;
123
+ requestCallbacks.delete(response.id);
124
+ if (response.error)
125
+ promise.reject(new Error(response.error.message));
126
+ else
127
+ promise.resolve(response.result);
128
+ }
101
129
  // Annotate the CommonJS export names for ESM import in node:
102
130
  0 && (module.exports = {
103
131
  ProcessRunner
@@ -197,6 +197,12 @@ class Dispatcher {
197
197
  const producedEnv = this._producedEnvByProjectId.get(testGroup.projectId) || {};
198
198
  this._producedEnvByProjectId.set(testGroup.projectId, { ...producedEnv, ...worker.producedEnv() });
199
199
  });
200
+ worker.onRequest("setStorageValue", async (params) => {
201
+ this._setStorageValue(params.fileName, params.key, params.value);
202
+ });
203
+ worker.onRequest("getStorageValue", async (params) => {
204
+ return this._getStorageValue(params.fileName, params.key);
205
+ });
200
206
  return worker;
201
207
  }
202
208
  producedEnvByProjectId() {
@@ -209,6 +215,11 @@ class Dispatcher {
209
215
  await Promise.all(this._workerSlots.map(({ worker }) => worker?.stop()));
210
216
  this._checkFinished();
211
217
  }
218
+ _setStorageValue(fileName, key, value) {
219
+ }
220
+ _getStorageValue(fileName, key) {
221
+ return {};
222
+ }
212
223
  }
213
224
  class JobDispatcher {
214
225
  constructor(job, config, reporter, failureTracker, stopCallback) {
@@ -44,6 +44,7 @@ class ProcessHost extends import_events.EventEmitter {
44
44
  this._lastMessageId = 0;
45
45
  this._callbacks = /* @__PURE__ */ new Map();
46
46
  this._producedEnv = {};
47
+ this._requestHandlers = /* @__PURE__ */ new Map();
47
48
  this._runnerScript = runnerScript;
48
49
  this._processName = processName;
49
50
  this._extraEnv = env;
@@ -95,6 +96,18 @@ class ProcessHost extends import_events.EventEmitter {
95
96
  } else {
96
97
  this.emit(method, params);
97
98
  }
99
+ } else if (message.method === "__request__") {
100
+ const { id, method, params } = message.params;
101
+ const handler = this._requestHandlers.get(method);
102
+ if (!handler) {
103
+ this.send({ method: "__response__", params: { id, error: { message: "Unknown method" } } });
104
+ } else {
105
+ handler(params).then((result) => {
106
+ this.send({ method: "__response__", params: { id, result } });
107
+ }).catch((error2) => {
108
+ this.send({ method: "__response__", params: { id, error: { message: error2.message } } });
109
+ });
110
+ }
98
111
  } else {
99
112
  this.emit(message.method, message.params);
100
113
  }
@@ -138,6 +151,9 @@ class ProcessHost extends import_events.EventEmitter {
138
151
  }
139
152
  async onExit() {
140
153
  }
154
+ onRequest(method, handler) {
155
+ this._requestHandlers.set(method, handler);
156
+ }
141
157
  async stop() {
142
158
  if (!this._processDidExit && !this._didSendStop) {
143
159
  this.send({ method: "__stop__" });
@@ -43,7 +43,7 @@ var import_testTracing = require("./testTracing");
43
43
  var import_util2 = require("./util");
44
44
  var import_transform = require("../transform/transform");
45
45
  class TestInfoImpl {
46
- constructor(configInternal, projectInternal, workerParams, test, retry, onStepBegin, onStepEnd, onAttach, onTestPaused) {
46
+ constructor(configInternal, projectInternal, workerParams, test, retry, callbacks) {
47
47
  this._snapshotNames = { lastAnonymousSnapshotIndex: 0, lastNamedSnapshotIndex: {} };
48
48
  this._ariaSnapshotNames = { lastAnonymousSnapshotIndex: 0, lastNamedSnapshotIndex: {} };
49
49
  this._interruptedPromise = new import_utils.ManualPromise();
@@ -60,10 +60,7 @@ class TestInfoImpl {
60
60
  this.snapshotSuffix = "";
61
61
  this.errors = [];
62
62
  this.testId = test?.id ?? "";
63
- this._onStepBegin = onStepBegin;
64
- this._onStepEnd = onStepEnd;
65
- this._onAttach = onAttach;
66
- this._onTestPaused = onTestPaused;
63
+ this._callbacks = callbacks;
67
64
  this._startTime = (0, import_utils.monotonicTime)();
68
65
  this._startWallTime = Date.now();
69
66
  this._requireFile = test?._requireFile ?? "";
@@ -240,7 +237,7 @@ ${(0, import_utils.stringifyStackFrames)(step.boxedStack).join("\n")}`;
240
237
  suggestedRebaseline: result.suggestedRebaseline,
241
238
  annotations: step.info.annotations
242
239
  };
243
- this._onStepEnd(payload);
240
+ this._callbacks.onStepEnd?.(payload);
244
241
  }
245
242
  if (step.group !== "internal") {
246
243
  const errorForTrace = step.error ? { name: "", message: step.error.message || "", stack: step.error.stack } : void 0;
@@ -262,7 +259,7 @@ ${(0, import_utils.stringifyStackFrames)(step.boxedStack).join("\n")}`;
262
259
  wallTime: Date.now(),
263
260
  location: step.location
264
261
  };
265
- this._onStepBegin(payload);
262
+ this._callbacks.onStepBegin?.(payload);
266
263
  }
267
264
  if (step.group !== "internal") {
268
265
  this._tracing.appendBeforeActionForStep({
@@ -338,7 +335,7 @@ ${(0, import_utils.stringifyStackFrames)(step.boxedStack).join("\n")}`;
338
335
  async _didFinishTestFunction() {
339
336
  const shouldPause = this._workerParams.pauseAtEnd && !this._isFailure() || this._workerParams.pauseOnError && this._isFailure();
340
337
  if (shouldPause) {
341
- this._onTestPaused({ testId: this.testId, errors: this._isFailure() ? this.errors : [] });
338
+ this._callbacks.onTestPaused?.({ testId: this.testId, errors: this._isFailure() ? this.errors : [] });
342
339
  await this._interruptedPromise;
343
340
  }
344
341
  await this._onDidFinishTestFunctionCallback?.();
@@ -367,7 +364,7 @@ ${(0, import_utils.stringifyStackFrames)(step.boxedStack).join("\n")}`;
367
364
  this._tracing.appendBeforeActionForStep({ stepId: stepId2, title: `Attach ${(0, import_utils.escapeWithQuotes)(attachment.name, '"')}`, category: "test.attach", stack: [] });
368
365
  this._tracing.appendAfterActionForStep(stepId2, void 0, [attachment]);
369
366
  }
370
- this._onAttach({
367
+ this._callbacks.onAttach?.({
371
368
  testId: this.testId,
372
369
  name: attachment.name,
373
370
  contentType: attachment.contentType,
@@ -462,6 +459,12 @@ ${(0, import_utils.stringifyStackFrames)(step.boxedStack).join("\n")}`;
462
459
  setTimeout(timeout) {
463
460
  this._timeoutManager.setTimeout(timeout);
464
461
  }
462
+ async _getStorageValue(fileName, key) {
463
+ return await this._callbacks.onGetStorageValue?.({ fileName, key }) ?? Promise.resolve(void 0);
464
+ }
465
+ _setStorageValue(fileName, key, value) {
466
+ this._callbacks.onSetStorageValue?.({ fileName, key, value });
467
+ }
465
468
  }
466
469
  class TestStepInfoImpl {
467
470
  constructor(testInfo, stepId, title, parentStep) {
@@ -95,11 +95,7 @@ class WorkerMain extends import_process.ProcessRunner {
95
95
  if (!this._config) {
96
96
  return;
97
97
  }
98
- const fakeTestInfo = new import_testInfo.TestInfoImpl(this._config, this._project, this._params, void 0, 0, () => {
99
- }, () => {
100
- }, () => {
101
- }, () => {
102
- });
98
+ const fakeTestInfo = new import_testInfo.TestInfoImpl(this._config, this._project, this._params, void 0, 0, {});
103
99
  const runnable = { type: "teardown" };
104
100
  await fakeTestInfo._runWithTimeout(runnable, () => this._loadIfNeeded()).catch(() => {
105
101
  });
@@ -234,17 +230,14 @@ class WorkerMain extends import_process.ProcessRunner {
234
230
  }
235
231
  }
236
232
  async _runTest(test, retry, nextTest) {
237
- const testInfo = new import_testInfo.TestInfoImpl(
238
- this._config,
239
- this._project,
240
- this._params,
241
- test,
242
- retry,
243
- (stepBeginPayload) => this.dispatchEvent("stepBegin", stepBeginPayload),
244
- (stepEndPayload) => this.dispatchEvent("stepEnd", stepEndPayload),
245
- (attachment) => this.dispatchEvent("attach", attachment),
246
- (testPausedPayload) => this.dispatchEvent("testPaused", testPausedPayload)
247
- );
233
+ const testInfo = new import_testInfo.TestInfoImpl(this._config, this._project, this._params, test, retry, {
234
+ onStepBegin: (payload) => this.dispatchEvent("stepBegin", payload),
235
+ onStepEnd: (payload) => this.dispatchEvent("stepEnd", payload),
236
+ onAttach: (payload) => this.dispatchEvent("attach", payload),
237
+ onTestPaused: (payload) => this.dispatchEvent("testPaused", payload),
238
+ onGetStorageValue: (payload) => this.sendRequest("getStorageValue", payload),
239
+ onSetStorageValue: (payload) => this.sendMessageNoReply("setStorageValue", payload)
240
+ });
248
241
  const processAnnotation = (annotation) => {
249
242
  testInfo.annotations.push(annotation);
250
243
  switch (annotation.type) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "playwright",
3
- "version": "1.58.0-alpha-2025-12-07",
3
+ "version": "1.58.0-alpha-2025-12-09",
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.58.0-alpha-2025-12-07"
67
+ "playwright-core": "1.58.0-alpha-2025-12-09"
68
68
  },
69
69
  "optionalDependencies": {
70
70
  "fsevents": "2.3.2"
@@ -1,91 +0,0 @@
1
- "use strict";
2
- var __defProp = Object.defineProperty;
3
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
- var __getOwnPropNames = Object.getOwnPropertyNames;
5
- var __hasOwnProp = Object.prototype.hasOwnProperty;
6
- var __export = (target, all) => {
7
- for (var name in all)
8
- __defProp(target, name, { get: all[name], enumerable: true });
9
- };
10
- var __copyProps = (to, from, except, desc) => {
11
- if (from && typeof from === "object" || typeof from === "function") {
12
- for (let key of __getOwnPropNames(from))
13
- if (!__hasOwnProp.call(to, key) && key !== except)
14
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
- }
16
- return to;
17
- };
18
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
- var pageDecorator_exports = {};
20
- __export(pageDecorator_exports, {
21
- decoratePage: () => decoratePage
22
- });
23
- module.exports = __toCommonJS(pageDecorator_exports);
24
- var import_utilsBundle = require("playwright-core/lib/utilsBundle");
25
- var import_mcpBundle = require("playwright-core/lib/mcpBundle");
26
- var import_browserContextFactory = require("../mcp/browser/browserContextFactory");
27
- var import_browserServerBackend = require("../mcp/browser/browserServerBackend");
28
- var import_config = require("../mcp/browser/config");
29
- var import_server = require("../mcp/sdk/server");
30
- function decoratePage(playwright) {
31
- playwright._instrumentation.addListener({
32
- onPage: (page) => {
33
- page.perform = pagePerform.bind(null, page);
34
- page.extract = pageExtract.bind(null, page);
35
- }
36
- });
37
- }
38
- async function pagePerform(page, userTask, options = {}) {
39
- const resultSchema = {
40
- type: "object",
41
- properties: {
42
- code: { type: "string" }
43
- },
44
- required: ["code"]
45
- };
46
- await perform(page, userTask, resultSchema, options);
47
- }
48
- async function pageExtract(page, query, schema, options = {}) {
49
- const task = `
50
- ### Instructions
51
- Extract the following information from the page. Do not perform any actions, just extract the information.
52
-
53
- ### Query
54
- ${query}`;
55
- return await perform(page, task, (0, import_mcpBundle.zodToJsonSchema)(schema), options);
56
- }
57
- async function perform(page, userTask, resultSchema, options = {}) {
58
- const context = page.context();
59
- if (!context._options.agent)
60
- throw new Error(`page.perform() and page.extract() require the agent to be set on the browser context`);
61
- const { full } = await page._snapshotForAI();
62
- const backend = new import_browserServerBackend.BrowserServerBackend(import_config.defaultConfig, (0, import_browserContextFactory.identityBrowserContextFactory)(context));
63
- const client = await (0, import_server.wrapInClient)(backend, { name: "Internal", version: "0.0.0" });
64
- const callTool = async (params) => {
65
- return await client.callTool(params);
66
- };
67
- const loop = new import_mcpBundle.Loop(context._options.agent.provider, {
68
- model: context._options.agent.model,
69
- summarize: true,
70
- debug: import_utilsBundle.debug,
71
- callTool,
72
- tools: await backend.listTools(),
73
- ...options
74
- });
75
- const task = `${userTask}
76
-
77
- ### Page snapshot
78
- ${full}
79
- `;
80
- try {
81
- return await loop.run(task, {
82
- resultSchema
83
- });
84
- } finally {
85
- await client.close();
86
- }
87
- }
88
- // Annotate the CommonJS export names for ESM import in node:
89
- 0 && (module.exports = {
90
- decoratePage
91
- });