playwright 1.58.0-alpha-2025-12-08 → 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 +2 -2
- package/lib/common/process.js +28 -0
- package/lib/runner/dispatcher.js +11 -0
- package/lib/runner/processHost.js +16 -0
- package/lib/worker/testInfo.js +12 -9
- package/lib/worker/workerMain.js +9 -16
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# 🎭 Playwright
|
|
2
2
|
|
|
3
|
-
[](https://www.npmjs.com/package/playwright) <!-- GEN:chromium-version-badge -->[](https://www.chromium.org/Home)<!-- GEN:stop --> <!-- GEN:firefox-version-badge -->[](https://www.npmjs.com/package/playwright) <!-- GEN:chromium-version-badge -->[](https://www.chromium.org/Home)<!-- GEN:stop --> <!-- GEN:firefox-version-badge -->[](https://www.mozilla.org/en-US/firefox/new/)<!-- GEN:stop --> <!-- GEN:webkit-version-badge -->[](https://webkit.org/)<!-- GEN:stop --> [](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.
|
|
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/lib/common/process.js
CHANGED
|
@@ -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
|
package/lib/runner/dispatcher.js
CHANGED
|
@@ -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__" });
|
package/lib/worker/testInfo.js
CHANGED
|
@@ -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,
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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) {
|
package/lib/worker/workerMain.js
CHANGED
|
@@ -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.
|
|
239
|
-
this.
|
|
240
|
-
this.
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
(
|
|
244
|
-
|
|
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-
|
|
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-
|
|
67
|
+
"playwright-core": "1.58.0-alpha-2025-12-09"
|
|
68
68
|
},
|
|
69
69
|
"optionalDependencies": {
|
|
70
70
|
"fsevents": "2.3.2"
|