playwright 1.56.0-alpha-2025-09-23 → 1.56.0-alpha-1758747822000
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/agents/generateAgents.js +25 -10
- package/lib/agents/generator.md +5 -5
- package/lib/agents/healer.md +4 -4
- package/lib/agents/planner.md +5 -5
- package/lib/index.js +3 -50
- package/lib/matchers/toBeTruthy.js +0 -2
- package/lib/matchers/toEqual.js +0 -2
- package/lib/matchers/toMatchText.js +0 -3
- package/lib/mcp/browser/browserContextFactory.js +20 -9
- package/lib/mcp/browser/browserServerBackend.js +2 -0
- package/lib/mcp/browser/config.js +55 -18
- package/lib/mcp/browser/context.js +17 -1
- package/lib/mcp/browser/response.js +27 -20
- package/lib/mcp/browser/sessionLog.js +1 -1
- package/lib/mcp/browser/tab.js +6 -32
- package/lib/mcp/browser/tools/dialogs.js +6 -1
- package/lib/mcp/browser/tools/files.js +6 -1
- package/lib/mcp/browser/tools/pdf.js +1 -1
- package/lib/mcp/browser/tools/screenshot.js +1 -1
- package/lib/mcp/browser/tools/snapshot.js +1 -1
- package/lib/mcp/browser/tools/tracing.js +1 -1
- package/lib/mcp/browser/tools/utils.js +2 -2
- package/lib/mcp/browser/tools.js +5 -0
- package/lib/mcp/log.js +2 -2
- package/lib/mcp/program.js +1 -1
- package/lib/mcp/sdk/http.js +17 -5
- package/lib/mcp/sdk/server.js +1 -1
- package/lib/mcp/test/browserBackend.js +29 -33
- package/lib/program.js +6 -4
- package/lib/runner/lastRun.js +6 -16
- package/lib/runner/loadUtils.js +35 -2
- package/lib/runner/tasks.js +9 -1
- package/lib/runner/testRunner.js +2 -1
- package/lib/util.js +12 -6
- package/lib/worker/testInfo.js +1 -0
- package/lib/worker/workerMain.js +4 -1
- package/package.json +2 -2
package/lib/runner/loadUtils.js
CHANGED
|
@@ -32,10 +32,13 @@ __export(loadUtils_exports, {
|
|
|
32
32
|
createRootSuite: () => createRootSuite,
|
|
33
33
|
loadFileSuites: () => loadFileSuites,
|
|
34
34
|
loadGlobalHook: () => loadGlobalHook,
|
|
35
|
-
loadReporter: () => loadReporter
|
|
35
|
+
loadReporter: () => loadReporter,
|
|
36
|
+
loadTestList: () => loadTestList
|
|
36
37
|
});
|
|
37
38
|
module.exports = __toCommonJS(loadUtils_exports);
|
|
38
39
|
var import_path = __toESM(require("path"));
|
|
40
|
+
var import_fs = __toESM(require("fs"));
|
|
41
|
+
var import_utils = require("playwright-core/lib/utils");
|
|
39
42
|
var import_loaderHost = require("./loaderHost");
|
|
40
43
|
var import_util = require("../util");
|
|
41
44
|
var import_projectUtils = require("./projectUtils");
|
|
@@ -290,11 +293,41 @@ function sourceMapSources(file, cache) {
|
|
|
290
293
|
return sources;
|
|
291
294
|
}
|
|
292
295
|
}
|
|
296
|
+
async function loadTestList(config, filePath) {
|
|
297
|
+
try {
|
|
298
|
+
const content = await import_fs.default.promises.readFile(filePath, "utf-8");
|
|
299
|
+
const lines = content.split("\n").map((line) => line.trim()).filter((line) => line && !line.startsWith("#"));
|
|
300
|
+
const descriptions = lines.map((line) => {
|
|
301
|
+
const delimiter = line.includes("\u203A") ? "\u203A" : ">";
|
|
302
|
+
const tokens = line.split(delimiter).map((token) => token.trim());
|
|
303
|
+
let project;
|
|
304
|
+
if (tokens[0].startsWith("[")) {
|
|
305
|
+
if (!tokens[0].endsWith("]"))
|
|
306
|
+
throw new Error(`Malformed test description: ${line}`);
|
|
307
|
+
project = tokens[0].substring(1, tokens[0].length - 1);
|
|
308
|
+
tokens.shift();
|
|
309
|
+
}
|
|
310
|
+
return { project, file: (0, import_utils.toPosixPath)((0, import_util.parseLocationArg)(tokens[0]).file), titlePath: tokens.slice(1) };
|
|
311
|
+
});
|
|
312
|
+
return (test) => descriptions.some((d) => {
|
|
313
|
+
const [projectName, , ...titles] = test.titlePath();
|
|
314
|
+
if (d.project !== void 0 && d.project !== projectName)
|
|
315
|
+
return false;
|
|
316
|
+
const relativeFile = (0, import_utils.toPosixPath)(import_path.default.relative(config.config.rootDir, test.location.file));
|
|
317
|
+
if (relativeFile !== d.file)
|
|
318
|
+
return false;
|
|
319
|
+
return d.titlePath.length === titles.length && d.titlePath.every((_, index) => titles[index] === d.titlePath[index]);
|
|
320
|
+
});
|
|
321
|
+
} catch (e) {
|
|
322
|
+
throw (0, import_util.errorWithFile)(filePath, "Cannot read test list file: " + e.message);
|
|
323
|
+
}
|
|
324
|
+
}
|
|
293
325
|
// Annotate the CommonJS export names for ESM import in node:
|
|
294
326
|
0 && (module.exports = {
|
|
295
327
|
collectProjectsAndTestFiles,
|
|
296
328
|
createRootSuite,
|
|
297
329
|
loadFileSuites,
|
|
298
330
|
loadGlobalHook,
|
|
299
|
-
loadReporter
|
|
331
|
+
loadReporter,
|
|
332
|
+
loadTestList
|
|
300
333
|
});
|
package/lib/runner/tasks.js
CHANGED
|
@@ -249,10 +249,18 @@ function createLoadTask(mode, options) {
|
|
|
249
249
|
const changedFiles = await (0, import_vcs.detectChangedTestFiles)(testRun.config.cliOnlyChanged, testRun.config.configDir);
|
|
250
250
|
testRun.config.preOnlyTestFilters.push((test) => changedFiles.has(test.location.file));
|
|
251
251
|
}
|
|
252
|
+
if (testRun.config.cliTestList) {
|
|
253
|
+
const testListFilter = await (0, import_loadUtils.loadTestList)(testRun.config, testRun.config.cliTestList);
|
|
254
|
+
testRun.config.preOnlyTestFilters.push(testListFilter);
|
|
255
|
+
}
|
|
256
|
+
if (testRun.config.cliTestListInvert) {
|
|
257
|
+
const testListInvertFilter = await (0, import_loadUtils.loadTestList)(testRun.config, testRun.config.cliTestListInvert);
|
|
258
|
+
testRun.config.preOnlyTestFilters.push((test) => !testListInvertFilter(test));
|
|
259
|
+
}
|
|
252
260
|
const { rootSuite, topLevelProjects } = await (0, import_loadUtils.createRootSuite)(testRun, options.failOnLoadErrors ? errors : softErrors, !!options.filterOnly);
|
|
253
261
|
testRun.rootSuite = rootSuite;
|
|
254
262
|
testRun.failureTracker.onRootSuite(rootSuite, topLevelProjects);
|
|
255
|
-
if (options.failOnLoadErrors && !testRun.rootSuite.allTests().length && !testRun.config.cliPassWithNoTests && !testRun.config.config.shard && !testRun.config.cliOnlyChanged) {
|
|
263
|
+
if (options.failOnLoadErrors && !testRun.rootSuite.allTests().length && !testRun.config.cliPassWithNoTests && !testRun.config.config.shard && !testRun.config.cliOnlyChanged && !testRun.config.cliTestList && !testRun.config.cliTestListInvert) {
|
|
256
264
|
if (testRun.config.cliArgs.length) {
|
|
257
265
|
throw new Error([
|
|
258
266
|
`No tests found.`,
|
package/lib/runner/testRunner.js
CHANGED
|
@@ -365,7 +365,8 @@ async function runAllTestsWithConfig(config) {
|
|
|
365
365
|
(0, import_webServerPlugin.webServerPluginsForConfig)(config).forEach((p) => config.plugins.push({ factory: p }));
|
|
366
366
|
const reporters = await (0, import_reporters.createReporters)(config, listOnly ? "list" : "test", false);
|
|
367
367
|
const lastRun = new import_lastRun.LastRunReporter(config);
|
|
368
|
-
|
|
368
|
+
if (config.cliLastFailed)
|
|
369
|
+
await lastRun.filterLastFailed();
|
|
369
370
|
const reporter = new import_internalReporter.InternalReporter([...reporters, lastRun]);
|
|
370
371
|
const tasks = listOnly ? [
|
|
371
372
|
(0, import_tasks.createLoadTask)("in-process", { failOnLoadErrors: true, filterOnly: false }),
|
package/lib/util.js
CHANGED
|
@@ -48,6 +48,7 @@ __export(util_exports, {
|
|
|
48
48
|
getPackageJsonPath: () => getPackageJsonPath,
|
|
49
49
|
mergeObjects: () => mergeObjects,
|
|
50
50
|
normalizeAndSaveAttachment: () => normalizeAndSaveAttachment,
|
|
51
|
+
parseLocationArg: () => parseLocationArg,
|
|
51
52
|
relativeFilePath: () => relativeFilePath,
|
|
52
53
|
removeDirAndLogToConsole: () => removeDirAndLogToConsole,
|
|
53
54
|
resolveImportSpecifierAfterMapping: () => resolveImportSpecifierAfterMapping,
|
|
@@ -105,14 +106,18 @@ function serializeError(error) {
|
|
|
105
106
|
value: import_util.default.inspect(error)
|
|
106
107
|
};
|
|
107
108
|
}
|
|
109
|
+
function parseLocationArg(arg) {
|
|
110
|
+
const match = /^(.*?):(\d+):?(\d+)?$/.exec(arg);
|
|
111
|
+
return {
|
|
112
|
+
file: match ? match[1] : arg,
|
|
113
|
+
line: match ? parseInt(match[2], 10) : null,
|
|
114
|
+
column: match?.[3] ? parseInt(match[3], 10) : null
|
|
115
|
+
};
|
|
116
|
+
}
|
|
108
117
|
function createFileFiltersFromArguments(args) {
|
|
109
118
|
return args.map((arg) => {
|
|
110
|
-
const
|
|
111
|
-
return {
|
|
112
|
-
re: forceRegExp(match ? match[1] : arg),
|
|
113
|
-
line: match ? parseInt(match[2], 10) : null,
|
|
114
|
-
column: match?.[3] ? parseInt(match[3], 10) : null
|
|
115
|
-
};
|
|
119
|
+
const parsed = parseLocationArg(arg);
|
|
120
|
+
return { re: forceRegExp(parsed.file), line: parsed.line, column: parsed.column };
|
|
116
121
|
});
|
|
117
122
|
}
|
|
118
123
|
function createFileMatcherFromArguments(args) {
|
|
@@ -385,6 +390,7 @@ function stripAnsiEscapes(str) {
|
|
|
385
390
|
getPackageJsonPath,
|
|
386
391
|
mergeObjects,
|
|
387
392
|
normalizeAndSaveAttachment,
|
|
393
|
+
parseLocationArg,
|
|
388
394
|
relativeFilePath,
|
|
389
395
|
removeDirAndLogToConsole,
|
|
390
396
|
resolveImportSpecifierAfterMapping,
|
package/lib/worker/testInfo.js
CHANGED
package/lib/worker/workerMain.js
CHANGED
|
@@ -318,7 +318,10 @@ class WorkerMain extends import_process.ProcessRunner {
|
|
|
318
318
|
await testInfo._runAsStep({ title: "After Hooks", category: "hook" }, async () => {
|
|
319
319
|
let firstAfterHooksError;
|
|
320
320
|
try {
|
|
321
|
-
await testInfo._runWithTimeout({ type: "test", slot: afterHooksSlot }, async () =>
|
|
321
|
+
await testInfo._runWithTimeout({ type: "test", slot: afterHooksSlot }, async () => {
|
|
322
|
+
for (const fn of testInfo._onDidFinishTestFunctions)
|
|
323
|
+
await fn();
|
|
324
|
+
});
|
|
322
325
|
} catch (error) {
|
|
323
326
|
firstAfterHooksError = firstAfterHooksError ?? error;
|
|
324
327
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "playwright",
|
|
3
|
-
"version": "1.56.0-alpha-
|
|
3
|
+
"version": "1.56.0-alpha-1758747822000",
|
|
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.56.0-alpha-
|
|
67
|
+
"playwright-core": "1.56.0-alpha-1758747822000"
|
|
68
68
|
},
|
|
69
69
|
"optionalDependencies": {
|
|
70
70
|
"fsevents": "2.3.2"
|