playwright 1.55.0-alpha-2025-08-06 → 1.55.0-alpha-2025-08-07
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.
Potentially problematic release.
This version of playwright might be problematic. Click here for more details.
- package/lib/index.js +77 -71
- package/package.json +2 -2
package/lib/index.js
CHANGED
|
@@ -103,16 +103,12 @@ const playwrightFixtures = {
|
|
|
103
103
|
}
|
|
104
104
|
});
|
|
105
105
|
await use(browser2);
|
|
106
|
-
await browser2.
|
|
107
|
-
await browser2.close({ reason: "Test ended." });
|
|
108
|
-
}, { internal: true });
|
|
106
|
+
await browser2.close({ reason: "Test ended." });
|
|
109
107
|
return;
|
|
110
108
|
}
|
|
111
109
|
const browser = await playwright[browserName].launch();
|
|
112
110
|
await use(browser);
|
|
113
|
-
await browser.
|
|
114
|
-
await browser.close({ reason: "Test ended." });
|
|
115
|
-
}, { internal: true });
|
|
111
|
+
await browser.close({ reason: "Test ended." });
|
|
116
112
|
}, { scope: "worker", timeout: 0 }],
|
|
117
113
|
acceptDownloads: [({ contextOptions }, use) => use(contextOptions.acceptDownloads ?? true), { option: true }],
|
|
118
114
|
bypassCSP: [({ contextOptions }, use) => use(contextOptions.bypassCSP ?? false), { option: true }],
|
|
@@ -310,6 +306,7 @@ const playwrightFixtures = {
|
|
|
310
306
|
const videoMode = normalizeVideoMode(video);
|
|
311
307
|
const captureVideo = shouldCaptureVideo(videoMode, testInfo) && !_reuseContext;
|
|
312
308
|
const contexts = /* @__PURE__ */ new Map();
|
|
309
|
+
let counter = 0;
|
|
313
310
|
await use(async (options) => {
|
|
314
311
|
const hook = testInfoImpl._currentHookType();
|
|
315
312
|
if (hook === "beforeAll" || hook === "afterAll") {
|
|
@@ -326,10 +323,6 @@ const playwrightFixtures = {
|
|
|
326
323
|
}
|
|
327
324
|
} : {};
|
|
328
325
|
const context = await browser.newContext({ ...videoOptions, ...options });
|
|
329
|
-
const contextData = { pagesWithVideo: [] };
|
|
330
|
-
contexts.set(context, contextData);
|
|
331
|
-
if (captureVideo)
|
|
332
|
-
context.on("page", (page) => contextData.pagesWithVideo.push(page));
|
|
333
326
|
if (process.env.PW_CLOCK === "frozen") {
|
|
334
327
|
await context._wrapApiCall(async () => {
|
|
335
328
|
await context.clock.install({ time: 0 });
|
|
@@ -340,30 +333,36 @@ const playwrightFixtures = {
|
|
|
340
333
|
await context.clock.install({ time: 0 });
|
|
341
334
|
}, { internal: true });
|
|
342
335
|
}
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
336
|
+
let closed = false;
|
|
337
|
+
const close = async () => {
|
|
338
|
+
if (closed)
|
|
339
|
+
return;
|
|
340
|
+
closed = true;
|
|
341
|
+
const closeReason = testInfo.status === "timedOut" ? "Test timeout of " + testInfo.timeout + "ms exceeded." : "Test ended.";
|
|
349
342
|
await context.close({ reason: closeReason });
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
}
|
|
364
|
-
}
|
|
365
|
-
}
|
|
366
|
-
|
|
343
|
+
const testFailed = testInfo.status !== testInfo.expectedStatus;
|
|
344
|
+
const preserveVideo = captureVideo && (videoMode === "on" || testFailed && videoMode === "retain-on-failure" || videoMode === "on-first-retry" && testInfo.retry === 1);
|
|
345
|
+
if (preserveVideo) {
|
|
346
|
+
const { pagesWithVideo: pagesForVideo } = contexts.get(context);
|
|
347
|
+
const videos = pagesForVideo.map((p) => p.video()).filter((video2) => !!video2);
|
|
348
|
+
await Promise.all(videos.map(async (v) => {
|
|
349
|
+
try {
|
|
350
|
+
const savedPath = testInfo.outputPath(`video${counter ? "-" + counter : ""}.webm`);
|
|
351
|
+
++counter;
|
|
352
|
+
await v.saveAs(savedPath);
|
|
353
|
+
testInfo.attachments.push({ name: "video", path: savedPath, contentType: "video/webm" });
|
|
354
|
+
} catch (e) {
|
|
355
|
+
}
|
|
356
|
+
}));
|
|
357
|
+
}
|
|
358
|
+
};
|
|
359
|
+
const contextData = { close, pagesWithVideo: [] };
|
|
360
|
+
if (captureVideo)
|
|
361
|
+
context.on("page", (page) => contextData.pagesWithVideo.push(page));
|
|
362
|
+
contexts.set(context, contextData);
|
|
363
|
+
return { context, close };
|
|
364
|
+
});
|
|
365
|
+
await Promise.all([...contexts.values()].map((data) => data.close()));
|
|
367
366
|
}, { scope: "test", title: "context", box: true }],
|
|
368
367
|
_optionContextReuseMode: ["none", { scope: "worker", option: true }],
|
|
369
368
|
_optionConnectOptions: [void 0, { scope: "worker", option: true }],
|
|
@@ -374,17 +373,19 @@ const playwrightFixtures = {
|
|
|
374
373
|
const reuse = mode === "when-possible" && normalizeVideoMode(video) === "off";
|
|
375
374
|
await use(reuse);
|
|
376
375
|
}, { scope: "worker", title: "context", box: true }],
|
|
377
|
-
context: async ({
|
|
378
|
-
|
|
376
|
+
context: async ({ browser, _reuseContext, _contextFactory }, use, testInfo) => {
|
|
377
|
+
const browserImpl = browser;
|
|
378
|
+
attachConnectedHeaderIfNeeded(testInfo, browserImpl);
|
|
379
379
|
if (!_reuseContext) {
|
|
380
|
-
|
|
380
|
+
const { context: context2, close } = await _contextFactory();
|
|
381
|
+
await use(context2);
|
|
382
|
+
await close();
|
|
381
383
|
return;
|
|
382
384
|
}
|
|
383
|
-
const
|
|
384
|
-
const context = await browser._newContextForReuse(defaultContextOptions);
|
|
385
|
+
const context = await browserImpl._wrapApiCall(() => browserImpl._newContextForReuse(), { internal: true });
|
|
385
386
|
await use(context);
|
|
386
387
|
const closeReason = testInfo.status === "timedOut" ? "Test timeout of " + testInfo.timeout + "ms exceeded." : "Test ended.";
|
|
387
|
-
await
|
|
388
|
+
await browserImpl._wrapApiCall(() => browserImpl._disconnectFromReusedContext(closeReason), { internal: true });
|
|
388
389
|
},
|
|
389
390
|
page: async ({ context, _reuseContext }, use) => {
|
|
390
391
|
if (!_reuseContext) {
|
|
@@ -548,7 +549,9 @@ class ArtifactsRecorder {
|
|
|
548
549
|
const screenshotOptions = typeof screenshot === "string" ? void 0 : screenshot;
|
|
549
550
|
this._startedCollectingArtifacts = Symbol("startedCollectingArtifacts");
|
|
550
551
|
this._screenshotRecorder = new SnapshotRecorder(this, normalizeScreenshotMode(screenshot), "screenshot", "image/png", ".png", async (page, path2) => {
|
|
551
|
-
await page.
|
|
552
|
+
await page._wrapApiCall(async () => {
|
|
553
|
+
await page.screenshot({ ...screenshotOptions, timeout: 5e3, path: path2, caret: "initial" });
|
|
554
|
+
}, { internal: true });
|
|
552
555
|
});
|
|
553
556
|
}
|
|
554
557
|
async willStartTest(testInfo) {
|
|
@@ -560,10 +563,10 @@ class ArtifactsRecorder {
|
|
|
560
563
|
await Promise.all(existingApiRequests.map((c) => this.didCreateRequestContext(c)));
|
|
561
564
|
}
|
|
562
565
|
async didCreateBrowserContext(context) {
|
|
563
|
-
await this._startTraceChunkOnContextCreation(context.tracing);
|
|
566
|
+
await this._startTraceChunkOnContextCreation(context, context.tracing);
|
|
564
567
|
}
|
|
565
568
|
async willCloseBrowserContext(context) {
|
|
566
|
-
await this._stopTracing(context.tracing);
|
|
569
|
+
await this._stopTracing(context, context.tracing);
|
|
567
570
|
await this._screenshotRecorder.captureTemporary(context);
|
|
568
571
|
await this._takePageSnapshot(context);
|
|
569
572
|
}
|
|
@@ -578,17 +581,17 @@ class ArtifactsRecorder {
|
|
|
578
581
|
if (!page)
|
|
579
582
|
return;
|
|
580
583
|
try {
|
|
581
|
-
|
|
584
|
+
await page._wrapApiCall(async () => {
|
|
585
|
+
this._pageSnapshot = await page._snapshotForAI({ timeout: 5e3 });
|
|
586
|
+
}, { internal: true });
|
|
582
587
|
} catch {
|
|
583
588
|
}
|
|
584
589
|
}
|
|
585
590
|
async didCreateRequestContext(context) {
|
|
586
|
-
|
|
587
|
-
await this._startTraceChunkOnContextCreation(tracing2);
|
|
591
|
+
await this._startTraceChunkOnContextCreation(context, context._tracing);
|
|
588
592
|
}
|
|
589
593
|
async willCloseRequestContext(context) {
|
|
590
|
-
|
|
591
|
-
await this._stopTracing(tracing2);
|
|
594
|
+
await this._stopTracing(context, context._tracing);
|
|
592
595
|
}
|
|
593
596
|
async didFinishTestFunction() {
|
|
594
597
|
await this._screenshotRecorder.maybeCapture();
|
|
@@ -598,10 +601,9 @@ class ArtifactsRecorder {
|
|
|
598
601
|
const leftoverContexts = this._playwright._allContexts();
|
|
599
602
|
const leftoverApiRequests = Array.from(this._playwright.request._contexts);
|
|
600
603
|
await Promise.all(leftoverContexts.map(async (context2) => {
|
|
601
|
-
await this._stopTracing(context2.tracing);
|
|
604
|
+
await this._stopTracing(context2, context2.tracing);
|
|
602
605
|
}).concat(leftoverApiRequests.map(async (context2) => {
|
|
603
|
-
|
|
604
|
-
await this._stopTracing(tracing2);
|
|
606
|
+
await this._stopTracing(context2, context2._tracing);
|
|
605
607
|
})));
|
|
606
608
|
await this._screenshotRecorder.persistTemporary();
|
|
607
609
|
const context = leftoverContexts[0];
|
|
@@ -624,30 +626,34 @@ class ArtifactsRecorder {
|
|
|
624
626
|
}, void 0);
|
|
625
627
|
}
|
|
626
628
|
}
|
|
627
|
-
async _startTraceChunkOnContextCreation(tracing2) {
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
629
|
+
async _startTraceChunkOnContextCreation(channelOwner, tracing2) {
|
|
630
|
+
await channelOwner._wrapApiCall(async () => {
|
|
631
|
+
const options = this._testInfo._tracing.traceOptions();
|
|
632
|
+
if (options) {
|
|
633
|
+
const title = this._testInfo._tracing.traceTitle();
|
|
634
|
+
const name = this._testInfo._tracing.generateNextTraceRecordingName();
|
|
635
|
+
if (!tracing2[kTracingStarted]) {
|
|
636
|
+
await tracing2.start({ ...options, title, name });
|
|
637
|
+
tracing2[kTracingStarted] = true;
|
|
638
|
+
} else {
|
|
639
|
+
await tracing2.startChunk({ title, name });
|
|
640
|
+
}
|
|
635
641
|
} else {
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
tracing2[kTracingStarted] = false;
|
|
641
|
-
await tracing2.stop();
|
|
642
|
+
if (tracing2[kTracingStarted]) {
|
|
643
|
+
tracing2[kTracingStarted] = false;
|
|
644
|
+
await tracing2.stop();
|
|
645
|
+
}
|
|
642
646
|
}
|
|
643
|
-
}
|
|
647
|
+
}, { internal: true });
|
|
644
648
|
}
|
|
645
|
-
async _stopTracing(tracing2) {
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
649
|
+
async _stopTracing(channelOwner, tracing2) {
|
|
650
|
+
await channelOwner._wrapApiCall(async () => {
|
|
651
|
+
if (tracing2[this._startedCollectingArtifacts])
|
|
652
|
+
return;
|
|
653
|
+
tracing2[this._startedCollectingArtifacts] = true;
|
|
654
|
+
if (this._testInfo._tracing.traceOptions() && tracing2[kTracingStarted])
|
|
655
|
+
await tracing2.stopChunk({ path: this._testInfo._tracing.maybeGenerateNextTraceRecordingPath() });
|
|
656
|
+
}, { internal: true });
|
|
651
657
|
}
|
|
652
658
|
}
|
|
653
659
|
function renderTitle(type, method, params, title) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "playwright",
|
|
3
|
-
"version": "1.55.0-alpha-2025-08-
|
|
3
|
+
"version": "1.55.0-alpha-2025-08-07",
|
|
4
4
|
"description": "A high-level API to automate web browsers",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -56,7 +56,7 @@
|
|
|
56
56
|
},
|
|
57
57
|
"license": "Apache-2.0",
|
|
58
58
|
"dependencies": {
|
|
59
|
-
"playwright-core": "1.55.0-alpha-2025-08-
|
|
59
|
+
"playwright-core": "1.55.0-alpha-2025-08-07"
|
|
60
60
|
},
|
|
61
61
|
"optionalDependencies": {
|
|
62
62
|
"fsevents": "2.3.2"
|