playwright 1.57.0-alpha-2025-10-19 → 1.57.0-alpha-2025-10-21
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/lib/common/config.js +6 -0
- package/lib/common/testLoader.js +3 -2
- package/lib/isomorphic/teleReceiver.js +1 -0
- package/lib/loader/loaderMain.js +1 -1
- package/lib/reporters/junit.js +4 -2
- package/lib/reporters/merge.js +11 -5
- package/lib/reporters/teleEmitter.js +2 -1
- package/lib/runner/loaderHost.js +1 -1
- package/lib/runner/reporters.js +2 -0
- package/lib/worker/workerMain.js +1 -1
- package/package.json +2 -2
- package/types/test.d.ts +27 -2
- package/types/testReporter.d.ts +5 -0
package/lib/common/config.js
CHANGED
|
@@ -69,6 +69,11 @@ class FullConfigInternal {
|
|
|
69
69
|
this.globalSetups = (Array.isArray(userConfig.globalSetup) ? userConfig.globalSetup : [userConfig.globalSetup]).map((s) => resolveScript(s, configDir)).filter((script) => script !== void 0);
|
|
70
70
|
this.globalTeardowns = (Array.isArray(userConfig.globalTeardown) ? userConfig.globalTeardown : [userConfig.globalTeardown]).map((s) => resolveScript(s, configDir)).filter((script) => script !== void 0);
|
|
71
71
|
userConfig.metadata = userConfig.metadata || {};
|
|
72
|
+
const globalTags = Array.isArray(userConfig.tag) ? userConfig.tag : userConfig.tag ? [userConfig.tag] : [];
|
|
73
|
+
for (const tag of globalTags) {
|
|
74
|
+
if (tag[0] !== "@")
|
|
75
|
+
throw new Error(`Tag must start with "@" symbol, got "${tag}" instead.`);
|
|
76
|
+
}
|
|
72
77
|
this.config = {
|
|
73
78
|
configFile: resolvedConfigFile,
|
|
74
79
|
rootDir: pathResolve(configDir, userConfig.testDir) || configDir,
|
|
@@ -91,6 +96,7 @@ class FullConfigInternal {
|
|
|
91
96
|
quiet: takeFirst(configCLIOverrides.quiet, userConfig.quiet, false),
|
|
92
97
|
projects: [],
|
|
93
98
|
shard: takeFirst(configCLIOverrides.shard, userConfig.shard, null),
|
|
99
|
+
tags: globalTags,
|
|
94
100
|
updateSnapshots: takeFirst(configCLIOverrides.updateSnapshots, userConfig.updateSnapshots, "missing"),
|
|
95
101
|
updateSourceMethod: takeFirst(configCLIOverrides.updateSourceMethod, userConfig.updateSourceMethod, "patch"),
|
|
96
102
|
version: require("../../package.json").version,
|
package/lib/common/testLoader.js
CHANGED
|
@@ -42,12 +42,13 @@ var import_transform = require("../transform/transform");
|
|
|
42
42
|
var import_util2 = require("../util");
|
|
43
43
|
const defaultTimeout = 3e4;
|
|
44
44
|
const cachedFileSuites = /* @__PURE__ */ new Map();
|
|
45
|
-
async function loadTestFile(file,
|
|
45
|
+
async function loadTestFile(file, config, testErrors) {
|
|
46
46
|
if (cachedFileSuites.has(file))
|
|
47
47
|
return cachedFileSuites.get(file);
|
|
48
|
-
const suite = new import_test.Suite(import_path.default.relative(rootDir, file) || import_path.default.basename(file), "file");
|
|
48
|
+
const suite = new import_test.Suite(import_path.default.relative(config.config.rootDir, file) || import_path.default.basename(file), "file");
|
|
49
49
|
suite._requireFile = file;
|
|
50
50
|
suite.location = { file, line: 0, column: 0 };
|
|
51
|
+
suite._tags = [...config.config.tags];
|
|
51
52
|
(0, import_globals.setCurrentlyLoadingFileSuite)(suite);
|
|
52
53
|
if (!(0, import_globals.isWorkerProcess)()) {
|
|
53
54
|
(0, import_compilationCache.startCollectingFileDeps)();
|
package/lib/loader/loaderMain.js
CHANGED
|
@@ -42,7 +42,7 @@ class LoaderMain extends import_process.ProcessRunner {
|
|
|
42
42
|
async loadTestFile(params) {
|
|
43
43
|
const testErrors = [];
|
|
44
44
|
const config = await this._config();
|
|
45
|
-
const fileSuite = await (0, import_testLoader.loadTestFile)(params.file, config
|
|
45
|
+
const fileSuite = await (0, import_testLoader.loadTestFile)(params.file, config, testErrors);
|
|
46
46
|
this._poolBuilder.buildPools(fileSuite);
|
|
47
47
|
return { fileSuite: fileSuite._deepSerialize(), testErrors };
|
|
48
48
|
}
|
package/lib/reporters/junit.js
CHANGED
|
@@ -173,8 +173,10 @@ class JUnitReporter {
|
|
|
173
173
|
const systemOut = [];
|
|
174
174
|
const systemErr = [];
|
|
175
175
|
for (const result of test.results) {
|
|
176
|
-
|
|
177
|
-
|
|
176
|
+
for (const item of result.stdout)
|
|
177
|
+
systemOut.push(item.toString());
|
|
178
|
+
for (const item of result.stderr)
|
|
179
|
+
systemErr.push(item.toString());
|
|
178
180
|
for (const attachment of result.attachments) {
|
|
179
181
|
if (!attachment.path)
|
|
180
182
|
continue;
|
package/lib/reporters/merge.js
CHANGED
|
@@ -72,13 +72,15 @@ async function createMergedReport(config, dir, reporterDescriptions, rootDirOver
|
|
|
72
72
|
}
|
|
73
73
|
};
|
|
74
74
|
await dispatchEvents(eventData.prologue);
|
|
75
|
-
for (const { reportFile, eventPatchers, metadata } of eventData.reports) {
|
|
75
|
+
for (const { reportFile, eventPatchers, metadata, tags } of eventData.reports) {
|
|
76
76
|
const reportJsonl = await import_fs.default.promises.readFile(reportFile);
|
|
77
77
|
const events = parseTestEvents(reportJsonl);
|
|
78
78
|
new import_stringInternPool.JsonStringInternalizer(stringPool).traverse(events);
|
|
79
79
|
eventPatchers.patchers.push(new AttachmentPathPatcher(dir));
|
|
80
80
|
if (metadata.name)
|
|
81
81
|
eventPatchers.patchers.push(new GlobalErrorPatcher(metadata.name));
|
|
82
|
+
if (tags.length)
|
|
83
|
+
eventPatchers.patchers.push(new GlobalErrorPatcher(tags.join(" ")));
|
|
82
84
|
eventPatchers.patchEvents(events);
|
|
83
85
|
await dispatchEvents(events);
|
|
84
86
|
}
|
|
@@ -178,18 +180,22 @@ async function mergeEvents(dir, shardReportFiles, stringPool, printStatus, rootD
|
|
|
178
180
|
if (rootDirOverride)
|
|
179
181
|
eventPatchers.patchers.push(new PathSeparatorPatcher(metadata.pathSeparator));
|
|
180
182
|
eventPatchers.patchEvents(parsedEvents);
|
|
183
|
+
let tags = [];
|
|
181
184
|
for (const event of parsedEvents) {
|
|
182
|
-
if (event.method === "onConfigure")
|
|
185
|
+
if (event.method === "onConfigure") {
|
|
183
186
|
configureEvents.push(event);
|
|
184
|
-
|
|
187
|
+
tags = event.params.config.tags || [];
|
|
188
|
+
} else if (event.method === "onProject") {
|
|
185
189
|
projectEvents.push(event);
|
|
186
|
-
else if (event.method === "onEnd")
|
|
190
|
+
} else if (event.method === "onEnd") {
|
|
187
191
|
endEvents.push(event);
|
|
192
|
+
}
|
|
188
193
|
}
|
|
189
194
|
reports.push({
|
|
190
195
|
eventPatchers,
|
|
191
196
|
reportFile: localPath,
|
|
192
|
-
metadata
|
|
197
|
+
metadata,
|
|
198
|
+
tags
|
|
193
199
|
});
|
|
194
200
|
}
|
|
195
201
|
return {
|
|
@@ -154,7 +154,8 @@ class TeleReporterEmitter {
|
|
|
154
154
|
version: config.version,
|
|
155
155
|
workers: config.workers,
|
|
156
156
|
globalSetup: config.globalSetup,
|
|
157
|
-
globalTeardown: config.globalTeardown
|
|
157
|
+
globalTeardown: config.globalTeardown,
|
|
158
|
+
tags: config.tags
|
|
158
159
|
};
|
|
159
160
|
}
|
|
160
161
|
_serializeProject(suite) {
|
package/lib/runner/loaderHost.js
CHANGED
|
@@ -48,7 +48,7 @@ class InProcessLoaderHost {
|
|
|
48
48
|
return true;
|
|
49
49
|
}
|
|
50
50
|
async loadTestFile(file, testErrors) {
|
|
51
|
-
const result = await (0, import_testLoader.loadTestFile)(file, this._config
|
|
51
|
+
const result = await (0, import_testLoader.loadTestFile)(file, this._config, testErrors);
|
|
52
52
|
this._poolBuilder.buildPools(result, testErrors);
|
|
53
53
|
return result;
|
|
54
54
|
}
|
package/lib/runner/reporters.js
CHANGED
|
@@ -125,6 +125,8 @@ function computeCommandHash(config) {
|
|
|
125
125
|
command.cliGrepInvert = config.cliGrepInvert;
|
|
126
126
|
if (config.cliOnlyChanged)
|
|
127
127
|
command.cliOnlyChanged = config.cliOnlyChanged;
|
|
128
|
+
if (config.config.tags.length)
|
|
129
|
+
command.tags = config.config.tags.join(" ");
|
|
128
130
|
if (Object.keys(command).length)
|
|
129
131
|
parts.push((0, import_utils.calculateSha1)(JSON.stringify(command)).substring(0, 7));
|
|
130
132
|
return parts.join("-");
|
package/lib/worker/workerMain.js
CHANGED
|
@@ -179,7 +179,7 @@ class WorkerMain extends import_process.ProcessRunner {
|
|
|
179
179
|
let fatalUnknownTestIds;
|
|
180
180
|
try {
|
|
181
181
|
await this._loadIfNeeded();
|
|
182
|
-
const fileSuite = await (0, import_testLoader.loadTestFile)(runPayload.file, this._config
|
|
182
|
+
const fileSuite = await (0, import_testLoader.loadTestFile)(runPayload.file, this._config);
|
|
183
183
|
const suite = (0, import_suiteUtils.bindFileSuiteToProject)(this._project, fileSuite);
|
|
184
184
|
if (this._params.repeatEachIndex)
|
|
185
185
|
(0, import_suiteUtils.applyRepeatEachIndex)(this._project, suite, this._params.repeatEachIndex);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "playwright",
|
|
3
|
-
"version": "1.57.0-alpha-2025-10-
|
|
3
|
+
"version": "1.57.0-alpha-2025-10-21",
|
|
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-
|
|
67
|
+
"playwright-core": "1.57.0-alpha-2025-10-21"
|
|
68
68
|
},
|
|
69
69
|
"optionalDependencies": {
|
|
70
70
|
"fsevents": "2.3.2"
|
package/types/test.d.ts
CHANGED
|
@@ -1758,6 +1758,26 @@ interface TestConfig<TestArgs = {}, WorkerArgs = {}> {
|
|
|
1758
1758
|
*/
|
|
1759
1759
|
snapshotPathTemplate?: string;
|
|
1760
1760
|
|
|
1761
|
+
/**
|
|
1762
|
+
* Tag or tags prepended to each test in the report. Useful for tagging your test run to differentiate between
|
|
1763
|
+
* [CI environments](https://playwright.dev/docs/test-sharding#merging-reports-from-multiple-environments).
|
|
1764
|
+
*
|
|
1765
|
+
* Note that each tag must start with `@` symbol. Learn more about [tagging](https://playwright.dev/docs/test-annotations#tag-tests).
|
|
1766
|
+
*
|
|
1767
|
+
* **Usage**
|
|
1768
|
+
*
|
|
1769
|
+
* ```js
|
|
1770
|
+
* // playwright.config.ts
|
|
1771
|
+
* import { defineConfig } from '@playwright/test';
|
|
1772
|
+
*
|
|
1773
|
+
* export default defineConfig({
|
|
1774
|
+
* tag: process.env.CI_ENVIRONMENT_NAME, // for example "@APIv2"
|
|
1775
|
+
* });
|
|
1776
|
+
* ```
|
|
1777
|
+
*
|
|
1778
|
+
*/
|
|
1779
|
+
tag?: string|Array<string>;
|
|
1780
|
+
|
|
1761
1781
|
/**
|
|
1762
1782
|
* Directory that will be recursively scanned for test files. Defaults to the directory of the configuration file.
|
|
1763
1783
|
*
|
|
@@ -2035,6 +2055,11 @@ export interface FullConfig<TestArgs = {}, WorkerArgs = {}> {
|
|
|
2035
2055
|
current: number;
|
|
2036
2056
|
};
|
|
2037
2057
|
|
|
2058
|
+
/**
|
|
2059
|
+
* Resolved global tags. See [testConfig.tag](https://playwright.dev/docs/api/class-testconfig#test-config-tag).
|
|
2060
|
+
*/
|
|
2061
|
+
tags: Array<string>;
|
|
2062
|
+
|
|
2038
2063
|
/**
|
|
2039
2064
|
* See [testConfig.updateSnapshots](https://playwright.dev/docs/api/class-testconfig#test-config-update-snapshots).
|
|
2040
2065
|
*/
|
|
@@ -6180,7 +6205,7 @@ export interface TestType<TestArgs extends {}, WorkerArgs extends {}> {
|
|
|
6180
6205
|
* const name = this.constructor.name + '.' + (context.name as string);
|
|
6181
6206
|
* return test.step(name, async () => {
|
|
6182
6207
|
* return await target.call(this, ...args);
|
|
6183
|
-
* });
|
|
6208
|
+
* }, { box: true });
|
|
6184
6209
|
* };
|
|
6185
6210
|
* }
|
|
6186
6211
|
*
|
|
@@ -6339,7 +6364,7 @@ export interface TestType<TestArgs extends {}, WorkerArgs extends {}> {
|
|
|
6339
6364
|
* const name = this.constructor.name + '.' + (context.name as string);
|
|
6340
6365
|
* return test.step(name, async () => {
|
|
6341
6366
|
* return await target.call(this, ...args);
|
|
6342
|
-
* });
|
|
6367
|
+
* }, { box: true });
|
|
6343
6368
|
* };
|
|
6344
6369
|
* }
|
|
6345
6370
|
*
|
package/types/testReporter.d.ts
CHANGED
|
@@ -127,6 +127,11 @@ export interface FullResult {
|
|
|
127
127
|
* `false`. This way, Playwright will use one of the standard terminal reporters in addition to your custom reporter
|
|
128
128
|
* to enhance user experience.
|
|
129
129
|
*
|
|
130
|
+
* **Reporter errors**
|
|
131
|
+
*
|
|
132
|
+
* Playwright will swallow any errors thrown in your custom reporter methods. If you need to detect or fail on
|
|
133
|
+
* reporter errors, you must wrap and handle them yourself.
|
|
134
|
+
*
|
|
130
135
|
* **Merged report API notes**
|
|
131
136
|
*
|
|
132
137
|
* When merging multiple [`blob`](https://playwright.dev/docs/test-reporters#blob-reporter) reports via
|