playwright 1.58.0-alpha-2025-12-06 → 1.58.0-alpha-2025-12-08
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/index.js +4 -9
- package/package.json +2 -2
- package/types/test.d.ts +6 -0
- package/lib/agents/performTask.js +0 -163
package/lib/index.js
CHANGED
|
@@ -33,7 +33,6 @@ __export(index_exports, {
|
|
|
33
33
|
expect: () => import_expect.expect,
|
|
34
34
|
mergeExpects: () => import_expect2.mergeExpects,
|
|
35
35
|
mergeTests: () => import_testType2.mergeTests,
|
|
36
|
-
performCache: () => import_performTask2.performCache,
|
|
37
36
|
test: () => test
|
|
38
37
|
});
|
|
39
38
|
module.exports = __toCommonJS(index_exports);
|
|
@@ -44,12 +43,10 @@ var import_utils = require("playwright-core/lib/utils");
|
|
|
44
43
|
var import_globals = require("./common/globals");
|
|
45
44
|
var import_testType = require("./common/testType");
|
|
46
45
|
var import_browserBackend = require("./mcp/test/browserBackend");
|
|
47
|
-
var import_performTask = require("./agents/performTask");
|
|
48
46
|
var import_expect = require("./matchers/expect");
|
|
49
47
|
var import_configLoader = require("./common/configLoader");
|
|
50
48
|
var import_testType2 = require("./common/testType");
|
|
51
49
|
var import_expect2 = require("./matchers/expect");
|
|
52
|
-
var import_performTask2 = require("./agents/performTask");
|
|
53
50
|
const _baseTest = import_testType.rootTestType.test;
|
|
54
51
|
(0, import_utils.setBoxedStackPrefixes)([import_path.default.dirname(require.resolve("../package.json"))]);
|
|
55
52
|
if (process["__pw_initiator__"]) {
|
|
@@ -114,6 +111,7 @@ const playwrightFixtures = {
|
|
|
114
111
|
await browser.close({ reason: "Test ended." });
|
|
115
112
|
}, { scope: "worker", timeout: 0 }],
|
|
116
113
|
acceptDownloads: [({ contextOptions }, use) => use(contextOptions.acceptDownloads ?? true), { option: true, box: true }],
|
|
114
|
+
agent: [({ contextOptions }, use) => use(contextOptions.agent), { option: true, box: true }],
|
|
117
115
|
bypassCSP: [({ contextOptions }, use) => use(contextOptions.bypassCSP ?? false), { option: true, box: true }],
|
|
118
116
|
colorScheme: [({ contextOptions }, use) => use(contextOptions.colorScheme === void 0 ? "light" : contextOptions.colorScheme), { option: true, box: true }],
|
|
119
117
|
deviceScaleFactor: [({ contextOptions }, use) => use(contextOptions.deviceScaleFactor), { option: true, box: true }],
|
|
@@ -143,6 +141,7 @@ const playwrightFixtures = {
|
|
|
143
141
|
contextOptions: [{}, { option: true, box: true }],
|
|
144
142
|
_combinedContextOptions: [async ({
|
|
145
143
|
acceptDownloads,
|
|
144
|
+
agent,
|
|
146
145
|
bypassCSP,
|
|
147
146
|
clientCertificates,
|
|
148
147
|
colorScheme,
|
|
@@ -169,6 +168,8 @@ const playwrightFixtures = {
|
|
|
169
168
|
const options = {};
|
|
170
169
|
if (acceptDownloads !== void 0)
|
|
171
170
|
options.acceptDownloads = acceptDownloads;
|
|
171
|
+
if (agent !== void 0)
|
|
172
|
+
options.agent = agent;
|
|
172
173
|
if (bypassCSP !== void 0)
|
|
173
174
|
options.bypassCSP = bypassCSP;
|
|
174
175
|
if (colorScheme !== void 0)
|
|
@@ -418,11 +419,6 @@ const playwrightFixtures = {
|
|
|
418
419
|
} else {
|
|
419
420
|
await request.dispose();
|
|
420
421
|
}
|
|
421
|
-
},
|
|
422
|
-
_perform: async ({ context }, use, testInfo) => {
|
|
423
|
-
await use(async (task, options) => {
|
|
424
|
-
await (0, import_performTask.performTask)(testInfo, context, task, options ?? {});
|
|
425
|
-
});
|
|
426
422
|
}
|
|
427
423
|
};
|
|
428
424
|
function normalizeVideoMode(video) {
|
|
@@ -686,6 +682,5 @@ const test = _baseTest.extend(playwrightFixtures);
|
|
|
686
682
|
expect,
|
|
687
683
|
mergeExpects,
|
|
688
684
|
mergeTests,
|
|
689
|
-
performCache,
|
|
690
685
|
test
|
|
691
686
|
});
|
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-08",
|
|
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-08"
|
|
68
68
|
},
|
|
69
69
|
"optionalDependencies": {
|
|
70
70
|
"fsevents": "2.3.2"
|
package/types/test.d.ts
CHANGED
|
@@ -6644,6 +6644,7 @@ export type Fixtures<T extends {} = {}, W extends {} = {}, PT extends {} = {}, P
|
|
|
6644
6644
|
[K in Exclude<keyof T, keyof PW | keyof PT>]?: TestFixtureValue<T[K], T & W & PT & PW> | [TestFixtureValue<T[K], T & W & PT & PW>, { scope?: 'test', auto?: boolean, option?: boolean, timeout?: number | undefined, title?: string, box?: boolean | 'self' }];
|
|
6645
6645
|
};
|
|
6646
6646
|
|
|
6647
|
+
type Agent = Exclude<BrowserContextOptions['agent'], undefined> | undefined;
|
|
6647
6648
|
type BrowserName = 'chromium' | 'firefox' | 'webkit';
|
|
6648
6649
|
type BrowserChannel = Exclude<LaunchOptions['channel'], undefined>;
|
|
6649
6650
|
type ColorScheme = Exclude<BrowserContextOptions['colorScheme'], undefined>;
|
|
@@ -6974,6 +6975,11 @@ export type VideoMode = 'off' | 'on' | 'retain-on-failure' | 'on-first-retry';
|
|
|
6974
6975
|
*
|
|
6975
6976
|
*/
|
|
6976
6977
|
export interface PlaywrightTestOptions {
|
|
6978
|
+
/**
|
|
6979
|
+
* Agent settings for [page.perform(task[, options])](https://playwright.dev/docs/api/class-page#page-perform) and
|
|
6980
|
+
* [page.extract(query, schema[, options])](https://playwright.dev/docs/api/class-page#page-extract).
|
|
6981
|
+
*/
|
|
6982
|
+
agent: Agent;
|
|
6977
6983
|
/**
|
|
6978
6984
|
* Whether to automatically download all the attachments. Defaults to `true` where all the downloads are accepted.
|
|
6979
6985
|
*
|
|
@@ -1,163 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __create = Object.create;
|
|
3
|
-
var __defProp = Object.defineProperty;
|
|
4
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
-
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
-
var __export = (target, all) => {
|
|
9
|
-
for (var name in all)
|
|
10
|
-
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
-
};
|
|
12
|
-
var __copyProps = (to, from, except, desc) => {
|
|
13
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
-
for (let key of __getOwnPropNames(from))
|
|
15
|
-
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
-
}
|
|
18
|
-
return to;
|
|
19
|
-
};
|
|
20
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
-
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
-
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
-
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
-
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
-
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
-
mod
|
|
27
|
-
));
|
|
28
|
-
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
-
var performTask_exports = {};
|
|
30
|
-
__export(performTask_exports, {
|
|
31
|
-
performCache: () => performCache,
|
|
32
|
-
performTask: () => performTask
|
|
33
|
-
});
|
|
34
|
-
module.exports = __toCommonJS(performTask_exports);
|
|
35
|
-
var import_fs = __toESM(require("fs"));
|
|
36
|
-
var import_path = __toESM(require("path"));
|
|
37
|
-
var import_utilsBundle = require("playwright-core/lib/utilsBundle");
|
|
38
|
-
var import_mcpBundle = require("playwright-core/lib/mcpBundle");
|
|
39
|
-
var import_browserContextFactory = require("../mcp/browser/browserContextFactory");
|
|
40
|
-
var import_browserServerBackend = require("../mcp/browser/browserServerBackend");
|
|
41
|
-
var import_config = require("../mcp/browser/config");
|
|
42
|
-
var import_server = require("../mcp/sdk/server");
|
|
43
|
-
const resultSchema = import_mcpBundle.z.object({
|
|
44
|
-
code: import_mcpBundle.z.string().optional().describe(`
|
|
45
|
-
Generated code to perform the task using Playwright API.
|
|
46
|
-
Check out the <code> blocks and combine them. Should be presented in the following form:
|
|
47
|
-
|
|
48
|
-
perform(async ({ page }) => {
|
|
49
|
-
// generated code here.
|
|
50
|
-
});
|
|
51
|
-
`),
|
|
52
|
-
error: import_mcpBundle.z.string().optional().describe("The error that occurred if execution failed.").optional()
|
|
53
|
-
});
|
|
54
|
-
async function performTask(testInfo, context, userTask, options) {
|
|
55
|
-
const cacheStatus = await performTaskFromCache(testInfo, context, userTask);
|
|
56
|
-
if (cacheStatus === "success")
|
|
57
|
-
return;
|
|
58
|
-
const backend = new import_browserServerBackend.BrowserServerBackend(import_config.defaultConfig, (0, import_browserContextFactory.identityBrowserContextFactory)(context));
|
|
59
|
-
const client = await (0, import_server.wrapInClient)(backend, { name: "Internal", version: "0.0.0" });
|
|
60
|
-
const callTool = async (params) => {
|
|
61
|
-
return await client.callTool(params);
|
|
62
|
-
};
|
|
63
|
-
const loop = new import_mcpBundle.Loop(options.provider ?? "github", {
|
|
64
|
-
model: options.model ?? "claude-sonnet-4.5",
|
|
65
|
-
reasoning: options.reasoning,
|
|
66
|
-
temperature: options.temperature,
|
|
67
|
-
maxTokens: options.maxTokens,
|
|
68
|
-
summarize: true,
|
|
69
|
-
debug: import_utilsBundle.debug,
|
|
70
|
-
callTool,
|
|
71
|
-
tools: await backend.listTools()
|
|
72
|
-
});
|
|
73
|
-
try {
|
|
74
|
-
const result = await loop.run(userTask, { resultSchema: (0, import_mcpBundle.zodToJsonSchema)(resultSchema) });
|
|
75
|
-
if (result.code)
|
|
76
|
-
await updatePerformFile(testInfo, userTask, result.code, options);
|
|
77
|
-
} finally {
|
|
78
|
-
await client.close();
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
async function updatePerformFile(testInfo, userTask, taskCode, options) {
|
|
82
|
-
const relativeFile = import_path.default.relative(testInfo.project.testDir, testInfo.file);
|
|
83
|
-
const promptCacheFile = testInfo.file.replace(".spec.ts", ".cache.ts");
|
|
84
|
-
const testTitle = testInfo.title;
|
|
85
|
-
const loop = new import_mcpBundle.Loop(options.provider ?? "github", {
|
|
86
|
-
model: options.model ?? "claude-sonnet-4.5",
|
|
87
|
-
reasoning: options.reasoning,
|
|
88
|
-
temperature: options.temperature,
|
|
89
|
-
maxTokens: options.maxTokens,
|
|
90
|
-
summarize: true,
|
|
91
|
-
debug: import_utilsBundle.debug,
|
|
92
|
-
callTool: async () => ({ content: [] }),
|
|
93
|
-
tools: []
|
|
94
|
-
});
|
|
95
|
-
const resultSchema2 = import_mcpBundle.z.object({
|
|
96
|
-
code: import_mcpBundle.z.string().optional().describe(`
|
|
97
|
-
Generated code with all the perofrm routines combined or updated into the following format:
|
|
98
|
-
|
|
99
|
-
import { performCache } from '@playwright/test';
|
|
100
|
-
|
|
101
|
-
performCache({
|
|
102
|
-
file: 'tests/page/perform-task.spec.ts',
|
|
103
|
-
test: 'perform task',
|
|
104
|
-
task: 'Click the learn more button',
|
|
105
|
-
code: async ({ page }) => {
|
|
106
|
-
await page.getByRole('link', { name: 'Learn more' }).click();
|
|
107
|
-
},
|
|
108
|
-
});
|
|
109
|
-
`)
|
|
110
|
-
});
|
|
111
|
-
const existingCode = await import_fs.default.promises.readFile(promptCacheFile, "utf8").catch(() => "");
|
|
112
|
-
const task = `
|
|
113
|
-
- Create or update a perform file to include performCache block for the given task and code.
|
|
114
|
-
- Dedupe items with the same file, test, and task.
|
|
115
|
-
- Should produce code in the following format
|
|
116
|
-
|
|
117
|
-
import { performCache } from '@playwright/test';
|
|
118
|
-
|
|
119
|
-
performCache({
|
|
120
|
-
file: '<file>',
|
|
121
|
-
test: '<test>',
|
|
122
|
-
task: '<task>',
|
|
123
|
-
code: async ({ page }) => {
|
|
124
|
-
<code>
|
|
125
|
-
},
|
|
126
|
-
});
|
|
127
|
-
|
|
128
|
-
performCache({
|
|
129
|
-
...
|
|
130
|
-
|
|
131
|
-
## Params for the new or updated performCache block
|
|
132
|
-
<file-content>${existingCode}</file-content>
|
|
133
|
-
<file>${relativeFile}</file>
|
|
134
|
-
<test>${testTitle}</test>
|
|
135
|
-
<task>${userTask}</task>
|
|
136
|
-
<code>${taskCode}</code>
|
|
137
|
-
`;
|
|
138
|
-
const result = await loop.run(task, { resultSchema: (0, import_mcpBundle.zodToJsonSchema)(resultSchema2) });
|
|
139
|
-
if (result.code)
|
|
140
|
-
await import_fs.default.promises.writeFile(promptCacheFile, result.code);
|
|
141
|
-
}
|
|
142
|
-
const performCacheMap = /* @__PURE__ */ new Map();
|
|
143
|
-
function performCache(entry) {
|
|
144
|
-
performCacheMap.set(JSON.stringify({ ...entry, code: void 0 }), entry);
|
|
145
|
-
}
|
|
146
|
-
async function performTaskFromCache(testInfo, context, userTask) {
|
|
147
|
-
const relativeFile = import_path.default.relative(testInfo.project.testDir, testInfo.file);
|
|
148
|
-
const key = JSON.stringify({ file: relativeFile, test: testInfo.title, task: userTask });
|
|
149
|
-
const entry = performCacheMap.get(key);
|
|
150
|
-
if (!entry)
|
|
151
|
-
return "cache-miss";
|
|
152
|
-
try {
|
|
153
|
-
await entry.code({ page: context.pages()[0] });
|
|
154
|
-
return "success";
|
|
155
|
-
} catch (error) {
|
|
156
|
-
return error;
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
// Annotate the CommonJS export names for ESM import in node:
|
|
160
|
-
0 && (module.exports = {
|
|
161
|
-
performCache,
|
|
162
|
-
performTask
|
|
163
|
-
});
|