playwright-core 1.58.0-alpha-2025-12-11 → 1.58.0-alpha-2025-12-13
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/ThirdPartyNotices.txt +3 -3
- package/browsers.json +5 -5
- package/lib/client/page.js +4 -3
- package/lib/mcpBundleImpl/index.js +15 -15
- package/lib/protocol/validator.js +26 -8
- package/lib/server/agent/agent.js +20 -7
- package/lib/server/agent/backend.js +2 -5
- package/lib/server/agent/codegen.js +83 -0
- package/lib/server/agent/context.js +18 -1
- package/lib/server/codegen/javascript.js +6 -29
- package/lib/server/deviceDescriptorsSource.json +54 -54
- package/lib/server/dispatchers/pageDispatcher.js +3 -2
- package/lib/utils/isomorphic/stringUtils.js +29 -0
- package/lib/vite/htmlReport/index.html +1 -1
- package/package.json +1 -1
- package/types/protocol.d.ts +172 -111
- package/types/types.d.ts +27 -2
|
@@ -613,7 +613,9 @@ import_validatorPrimitives.scheme.BrowserTypeLaunchPersistentContextParams = (0,
|
|
|
613
613
|
model: import_validatorPrimitives.tString,
|
|
614
614
|
cacheFile: (0, import_validatorPrimitives.tOptional)(import_validatorPrimitives.tString),
|
|
615
615
|
cacheMode: (0, import_validatorPrimitives.tOptional)((0, import_validatorPrimitives.tEnum)(["ignore", "force", "auto"])),
|
|
616
|
-
secrets: (0, import_validatorPrimitives.tOptional)((0, import_validatorPrimitives.tArray)((0, import_validatorPrimitives.tType)("NameValue")))
|
|
616
|
+
secrets: (0, import_validatorPrimitives.tOptional)((0, import_validatorPrimitives.tArray)((0, import_validatorPrimitives.tType)("NameValue"))),
|
|
617
|
+
maxTurns: (0, import_validatorPrimitives.tOptional)(import_validatorPrimitives.tInt),
|
|
618
|
+
maxTokens: (0, import_validatorPrimitives.tOptional)(import_validatorPrimitives.tInt)
|
|
617
619
|
})),
|
|
618
620
|
userDataDir: import_validatorPrimitives.tString,
|
|
619
621
|
slowMo: (0, import_validatorPrimitives.tOptional)(import_validatorPrimitives.tFloat)
|
|
@@ -712,7 +714,9 @@ import_validatorPrimitives.scheme.BrowserNewContextParams = (0, import_validator
|
|
|
712
714
|
model: import_validatorPrimitives.tString,
|
|
713
715
|
cacheFile: (0, import_validatorPrimitives.tOptional)(import_validatorPrimitives.tString),
|
|
714
716
|
cacheMode: (0, import_validatorPrimitives.tOptional)((0, import_validatorPrimitives.tEnum)(["ignore", "force", "auto"])),
|
|
715
|
-
secrets: (0, import_validatorPrimitives.tOptional)((0, import_validatorPrimitives.tArray)((0, import_validatorPrimitives.tType)("NameValue")))
|
|
717
|
+
secrets: (0, import_validatorPrimitives.tOptional)((0, import_validatorPrimitives.tArray)((0, import_validatorPrimitives.tType)("NameValue"))),
|
|
718
|
+
maxTurns: (0, import_validatorPrimitives.tOptional)(import_validatorPrimitives.tInt),
|
|
719
|
+
maxTokens: (0, import_validatorPrimitives.tOptional)(import_validatorPrimitives.tInt)
|
|
716
720
|
})),
|
|
717
721
|
proxy: (0, import_validatorPrimitives.tOptional)((0, import_validatorPrimitives.tObject)({
|
|
718
722
|
server: import_validatorPrimitives.tString,
|
|
@@ -790,7 +794,9 @@ import_validatorPrimitives.scheme.BrowserNewContextForReuseParams = (0, import_v
|
|
|
790
794
|
model: import_validatorPrimitives.tString,
|
|
791
795
|
cacheFile: (0, import_validatorPrimitives.tOptional)(import_validatorPrimitives.tString),
|
|
792
796
|
cacheMode: (0, import_validatorPrimitives.tOptional)((0, import_validatorPrimitives.tEnum)(["ignore", "force", "auto"])),
|
|
793
|
-
secrets: (0, import_validatorPrimitives.tOptional)((0, import_validatorPrimitives.tArray)((0, import_validatorPrimitives.tType)("NameValue")))
|
|
797
|
+
secrets: (0, import_validatorPrimitives.tOptional)((0, import_validatorPrimitives.tArray)((0, import_validatorPrimitives.tType)("NameValue"))),
|
|
798
|
+
maxTurns: (0, import_validatorPrimitives.tOptional)(import_validatorPrimitives.tInt),
|
|
799
|
+
maxTokens: (0, import_validatorPrimitives.tOptional)(import_validatorPrimitives.tInt)
|
|
794
800
|
})),
|
|
795
801
|
proxy: (0, import_validatorPrimitives.tOptional)((0, import_validatorPrimitives.tObject)({
|
|
796
802
|
server: import_validatorPrimitives.tString,
|
|
@@ -913,7 +919,9 @@ import_validatorPrimitives.scheme.BrowserContextInitializer = (0, import_validat
|
|
|
913
919
|
model: import_validatorPrimitives.tString,
|
|
914
920
|
cacheFile: (0, import_validatorPrimitives.tOptional)(import_validatorPrimitives.tString),
|
|
915
921
|
cacheMode: (0, import_validatorPrimitives.tOptional)((0, import_validatorPrimitives.tEnum)(["ignore", "force", "auto"])),
|
|
916
|
-
secrets: (0, import_validatorPrimitives.tOptional)((0, import_validatorPrimitives.tArray)((0, import_validatorPrimitives.tType)("NameValue")))
|
|
922
|
+
secrets: (0, import_validatorPrimitives.tOptional)((0, import_validatorPrimitives.tArray)((0, import_validatorPrimitives.tType)("NameValue"))),
|
|
923
|
+
maxTurns: (0, import_validatorPrimitives.tOptional)(import_validatorPrimitives.tInt),
|
|
924
|
+
maxTokens: (0, import_validatorPrimitives.tOptional)(import_validatorPrimitives.tInt)
|
|
917
925
|
}))
|
|
918
926
|
})
|
|
919
927
|
});
|
|
@@ -1519,16 +1527,24 @@ import_validatorPrimitives.scheme.PageUpdateSubscriptionResult = (0, import_vali
|
|
|
1519
1527
|
import_validatorPrimitives.scheme.PagePerformParams = (0, import_validatorPrimitives.tObject)({
|
|
1520
1528
|
task: import_validatorPrimitives.tString,
|
|
1521
1529
|
key: (0, import_validatorPrimitives.tOptional)(import_validatorPrimitives.tString),
|
|
1522
|
-
maxTurns: (0, import_validatorPrimitives.tOptional)(import_validatorPrimitives.tInt)
|
|
1530
|
+
maxTurns: (0, import_validatorPrimitives.tOptional)(import_validatorPrimitives.tInt),
|
|
1531
|
+
maxTokens: (0, import_validatorPrimitives.tOptional)(import_validatorPrimitives.tInt)
|
|
1532
|
+
});
|
|
1533
|
+
import_validatorPrimitives.scheme.PagePerformResult = (0, import_validatorPrimitives.tObject)({
|
|
1534
|
+
turns: import_validatorPrimitives.tInt,
|
|
1535
|
+
inputTokens: import_validatorPrimitives.tInt,
|
|
1536
|
+
outputTokens: import_validatorPrimitives.tInt
|
|
1523
1537
|
});
|
|
1524
|
-
import_validatorPrimitives.scheme.PagePerformResult = (0, import_validatorPrimitives.tOptional)((0, import_validatorPrimitives.tObject)({}));
|
|
1525
1538
|
import_validatorPrimitives.scheme.PageExtractParams = (0, import_validatorPrimitives.tObject)({
|
|
1526
1539
|
query: import_validatorPrimitives.tString,
|
|
1527
1540
|
schema: import_validatorPrimitives.tAny,
|
|
1528
1541
|
maxTurns: (0, import_validatorPrimitives.tOptional)(import_validatorPrimitives.tInt)
|
|
1529
1542
|
});
|
|
1530
1543
|
import_validatorPrimitives.scheme.PageExtractResult = (0, import_validatorPrimitives.tObject)({
|
|
1531
|
-
result: import_validatorPrimitives.tAny
|
|
1544
|
+
result: import_validatorPrimitives.tAny,
|
|
1545
|
+
turns: import_validatorPrimitives.tInt,
|
|
1546
|
+
inputTokens: import_validatorPrimitives.tInt,
|
|
1547
|
+
outputTokens: import_validatorPrimitives.tInt
|
|
1532
1548
|
});
|
|
1533
1549
|
import_validatorPrimitives.scheme.FrameInitializer = (0, import_validatorPrimitives.tObject)({
|
|
1534
1550
|
url: import_validatorPrimitives.tString,
|
|
@@ -2823,7 +2839,9 @@ import_validatorPrimitives.scheme.AndroidDeviceLaunchBrowserParams = (0, import_
|
|
|
2823
2839
|
model: import_validatorPrimitives.tString,
|
|
2824
2840
|
cacheFile: (0, import_validatorPrimitives.tOptional)(import_validatorPrimitives.tString),
|
|
2825
2841
|
cacheMode: (0, import_validatorPrimitives.tOptional)((0, import_validatorPrimitives.tEnum)(["ignore", "force", "auto"])),
|
|
2826
|
-
secrets: (0, import_validatorPrimitives.tOptional)((0, import_validatorPrimitives.tArray)((0, import_validatorPrimitives.tType)("NameValue")))
|
|
2842
|
+
secrets: (0, import_validatorPrimitives.tOptional)((0, import_validatorPrimitives.tArray)((0, import_validatorPrimitives.tType)("NameValue"))),
|
|
2843
|
+
maxTurns: (0, import_validatorPrimitives.tOptional)(import_validatorPrimitives.tInt),
|
|
2844
|
+
maxTokens: (0, import_validatorPrimitives.tOptional)(import_validatorPrimitives.tInt)
|
|
2827
2845
|
})),
|
|
2828
2846
|
pkg: (0, import_validatorPrimitives.tOptional)(import_validatorPrimitives.tString),
|
|
2829
2847
|
args: (0, import_validatorPrimitives.tOptional)((0, import_validatorPrimitives.tArray)(import_validatorPrimitives.tString)),
|
|
@@ -41,9 +41,10 @@ var import_context = require("./context");
|
|
|
41
41
|
async function pagePerform(progress, page, options) {
|
|
42
42
|
const context = new import_context.Context(progress, page);
|
|
43
43
|
if (await cachedPerform(context, options))
|
|
44
|
-
return;
|
|
45
|
-
await perform(context, options.task, void 0, options);
|
|
44
|
+
return { turns: 0, inputTokens: 0, outputTokens: 0 };
|
|
45
|
+
const { usage } = await perform(context, options.task, void 0, options);
|
|
46
46
|
await updateCache(context, options);
|
|
47
|
+
return usage;
|
|
47
48
|
}
|
|
48
49
|
async function pageExtract(progress, page, options) {
|
|
49
50
|
const context = new import_context.Context(progress, page);
|
|
@@ -53,7 +54,8 @@ Extract the following information from the page. Do not perform any actions, jus
|
|
|
53
54
|
|
|
54
55
|
### Query
|
|
55
56
|
${options.query}`;
|
|
56
|
-
|
|
57
|
+
const { result, usage } = await perform(context, task, options.schema, options);
|
|
58
|
+
return { result, usage };
|
|
57
59
|
}
|
|
58
60
|
async function perform(context, userTask, resultSchema, options = {}) {
|
|
59
61
|
const { progress, page } = context;
|
|
@@ -62,13 +64,17 @@ async function perform(context, userTask, resultSchema, options = {}) {
|
|
|
62
64
|
throw new Error(`page.perform() and page.extract() require the agent to be set on the browser context`);
|
|
63
65
|
const { full } = await page.snapshotForAI(progress);
|
|
64
66
|
const { tools, callTool } = (0, import_backend.toolsForLoop)(context);
|
|
67
|
+
const limits = context.limits(options);
|
|
68
|
+
let turns = 0;
|
|
65
69
|
const loop = new import_mcpBundle.Loop(browserContext._options.agent.provider, {
|
|
66
70
|
model: browserContext._options.agent.model,
|
|
67
71
|
summarize: true,
|
|
68
72
|
debug: import_utilsBundle.debug,
|
|
69
73
|
callTool,
|
|
70
74
|
tools,
|
|
75
|
+
...limits,
|
|
71
76
|
beforeTurn: (params) => {
|
|
77
|
+
++turns;
|
|
72
78
|
const lastReply = params.conversation.messages.findLast((m) => m.role === "assistant");
|
|
73
79
|
const toolCall = lastReply?.content.find((c) => c.type === "tool_call");
|
|
74
80
|
if (!resultSchema && toolCall && toolCall.arguments.thatShouldBeIt)
|
|
@@ -82,15 +88,22 @@ async function perform(context, userTask, resultSchema, options = {}) {
|
|
|
82
88
|
### Page snapshot
|
|
83
89
|
${full}
|
|
84
90
|
`;
|
|
85
|
-
const { result } = await loop.run(task, { resultSchema });
|
|
86
|
-
return
|
|
91
|
+
const { result, usage } = await loop.run(task, { resultSchema });
|
|
92
|
+
return {
|
|
93
|
+
result,
|
|
94
|
+
usage: {
|
|
95
|
+
turns,
|
|
96
|
+
inputTokens: usage.input,
|
|
97
|
+
outputTokens: usage.output
|
|
98
|
+
}
|
|
99
|
+
};
|
|
87
100
|
}
|
|
88
101
|
const allCaches = /* @__PURE__ */ new Map();
|
|
89
102
|
async function cachedPerform(context, options) {
|
|
90
103
|
if (!context.options?.cacheFile || context.options.cacheMode === "ignore")
|
|
91
104
|
return false;
|
|
92
105
|
const cache = await cachedActions(context.options.cacheFile);
|
|
93
|
-
const cacheKey = options.key ?? options.task;
|
|
106
|
+
const cacheKey = (options.key ?? options.task).trim();
|
|
94
107
|
const entry = cache[cacheKey];
|
|
95
108
|
if (!entry) {
|
|
96
109
|
if (context.options.cacheMode === "force")
|
|
@@ -106,7 +119,7 @@ async function updateCache(context, options) {
|
|
|
106
119
|
if (!cacheFile)
|
|
107
120
|
return;
|
|
108
121
|
const cache = await cachedActions(cacheFile);
|
|
109
|
-
const cacheKey = options.key ?? options.task;
|
|
122
|
+
const cacheKey = (options.key ?? options.task).trim();
|
|
110
123
|
cache[cacheKey] = {
|
|
111
124
|
timestamp: Date.now(),
|
|
112
125
|
actions: context.actions
|
|
@@ -32,7 +32,6 @@ __export(backend_exports, {
|
|
|
32
32
|
});
|
|
33
33
|
module.exports = __toCommonJS(backend_exports);
|
|
34
34
|
var import_tools = __toESM(require("./tools"));
|
|
35
|
-
var import_progress = require("../progress");
|
|
36
35
|
var import_mcpBundle = require("../../mcpBundle");
|
|
37
36
|
function toolsForLoop(context) {
|
|
38
37
|
const tools = import_tools.default.map((tool) => {
|
|
@@ -44,6 +43,7 @@ function toolsForLoop(context) {
|
|
|
44
43
|
return result;
|
|
45
44
|
});
|
|
46
45
|
const callTool = async (params) => {
|
|
46
|
+
const intent = params.arguments._meta?.["dev.lowire/intent"];
|
|
47
47
|
const tool = import_tools.default.find((t) => t.schema.name === params.name);
|
|
48
48
|
if (!tool) {
|
|
49
49
|
return {
|
|
@@ -54,11 +54,8 @@ function toolsForLoop(context) {
|
|
|
54
54
|
isError: true
|
|
55
55
|
};
|
|
56
56
|
}
|
|
57
|
-
const progressController = new import_progress.ProgressController();
|
|
58
57
|
try {
|
|
59
|
-
return await
|
|
60
|
-
return await tool.handle(context, params.arguments);
|
|
61
|
-
});
|
|
58
|
+
return await context.callTool(tool, params.arguments, { intent });
|
|
62
59
|
} catch (error) {
|
|
63
60
|
return {
|
|
64
61
|
content: [{ type: "text", text: error.message }],
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
var codegen_exports = {};
|
|
20
|
+
__export(codegen_exports, {
|
|
21
|
+
generateCode: () => generateCode
|
|
22
|
+
});
|
|
23
|
+
module.exports = __toCommonJS(codegen_exports);
|
|
24
|
+
var import_locatorGenerators = require("../../utils/isomorphic/locatorGenerators");
|
|
25
|
+
var import_stringUtils = require("../../utils/isomorphic/stringUtils");
|
|
26
|
+
async function generateCode(sdkLanguage, action) {
|
|
27
|
+
switch (action.method) {
|
|
28
|
+
case "click": {
|
|
29
|
+
const locator = (0, import_locatorGenerators.asLocator)(sdkLanguage, action.selector);
|
|
30
|
+
return `await page.${locator}.click(${(0, import_stringUtils.formatObjectOrVoid)(action.options)});`;
|
|
31
|
+
}
|
|
32
|
+
case "drag": {
|
|
33
|
+
const sourceLocator = (0, import_locatorGenerators.asLocator)(sdkLanguage, action.sourceSelector);
|
|
34
|
+
const targetLocator = (0, import_locatorGenerators.asLocator)(sdkLanguage, action.targetSelector);
|
|
35
|
+
return `await page.${sourceLocator}.dragAndDrop(${targetLocator});`;
|
|
36
|
+
}
|
|
37
|
+
case "hover": {
|
|
38
|
+
const locator = (0, import_locatorGenerators.asLocator)(sdkLanguage, action.selector);
|
|
39
|
+
return `await page.${locator}.hover(${(0, import_stringUtils.formatObjectOrVoid)(action.options)});`;
|
|
40
|
+
}
|
|
41
|
+
case "pressKey": {
|
|
42
|
+
return `await page.keyboard.press(${(0, import_stringUtils.escapeWithQuotes)(action.key, "'")});`;
|
|
43
|
+
}
|
|
44
|
+
case "selectOption": {
|
|
45
|
+
const locator = (0, import_locatorGenerators.asLocator)(sdkLanguage, action.selector);
|
|
46
|
+
return `await page.${locator}.selectOption(${action.labels.length === 1 ? (0, import_stringUtils.escapeWithQuotes)(action.labels[0]) : "[" + action.labels.map((label) => (0, import_stringUtils.escapeWithQuotes)(label)).join(", ") + "]"});`;
|
|
47
|
+
}
|
|
48
|
+
case "pressSequentially": {
|
|
49
|
+
const locator = (0, import_locatorGenerators.asLocator)(sdkLanguage, action.selector);
|
|
50
|
+
const code = [`await page.${locator}.pressSequentially(${(0, import_stringUtils.escapeWithQuotes)(action.text)});`];
|
|
51
|
+
if (action.submit)
|
|
52
|
+
code.push(`await page.keyboard.press('Enter');`);
|
|
53
|
+
return code.join("\n");
|
|
54
|
+
}
|
|
55
|
+
case "fill": {
|
|
56
|
+
const locator = (0, import_locatorGenerators.asLocator)(sdkLanguage, action.selector);
|
|
57
|
+
const code = [`await page.${locator}.fill(${(0, import_stringUtils.escapeWithQuotes)(action.text)});`];
|
|
58
|
+
if (action.submit)
|
|
59
|
+
code.push(`await page.keyboard.press('Enter');`);
|
|
60
|
+
return code.join("\n");
|
|
61
|
+
}
|
|
62
|
+
case "setChecked": {
|
|
63
|
+
const locator = (0, import_locatorGenerators.asLocator)(sdkLanguage, action.selector);
|
|
64
|
+
if (action.checked)
|
|
65
|
+
return `await page.${locator}.check();`;
|
|
66
|
+
else
|
|
67
|
+
return `await page.${locator}.uncheck();`;
|
|
68
|
+
}
|
|
69
|
+
case "expectVisible": {
|
|
70
|
+
const locator = (0, import_locatorGenerators.asLocator)(sdkLanguage, action.selector);
|
|
71
|
+
return `await expect(page.${locator}).toBeVisible();`;
|
|
72
|
+
}
|
|
73
|
+
case "expectValue": {
|
|
74
|
+
const locator = (0, import_locatorGenerators.asLocator)(sdkLanguage, action.selector);
|
|
75
|
+
return `await expect(page.${locator}).toHaveValue(${(0, import_stringUtils.escapeWithQuotes)(action.value)});`;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
throw new Error("Unknown action " + action.method);
|
|
79
|
+
}
|
|
80
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
81
|
+
0 && (module.exports = {
|
|
82
|
+
generateCode
|
|
83
|
+
});
|
|
@@ -23,12 +23,22 @@ __export(context_exports, {
|
|
|
23
23
|
module.exports = __toCommonJS(context_exports);
|
|
24
24
|
var import_browserContext = require("../browserContext");
|
|
25
25
|
var import_actionRunner = require("./actionRunner");
|
|
26
|
+
var import_codegen = require("./codegen");
|
|
26
27
|
class Context {
|
|
27
28
|
constructor(progress, page) {
|
|
28
29
|
this.actions = [];
|
|
29
30
|
this.progress = progress;
|
|
30
31
|
this.page = page;
|
|
31
32
|
this.options = page.browserContext._options.agent;
|
|
33
|
+
this.sdkLanguage = page.browserContext._browser.sdkLanguage();
|
|
34
|
+
}
|
|
35
|
+
async callTool(tool, params, options) {
|
|
36
|
+
this._callIntent = options.intent;
|
|
37
|
+
try {
|
|
38
|
+
return await tool.handle(this, params);
|
|
39
|
+
} finally {
|
|
40
|
+
this._callIntent = void 0;
|
|
41
|
+
}
|
|
32
42
|
}
|
|
33
43
|
async runActionAndWait(action) {
|
|
34
44
|
return await this.runActionsAndWait([action]);
|
|
@@ -38,7 +48,8 @@ class Context {
|
|
|
38
48
|
await this.waitForCompletion(async () => {
|
|
39
49
|
for (const a of action) {
|
|
40
50
|
await (0, import_actionRunner.runAction)(this.progress, this.page, a, this.options?.secrets ?? []);
|
|
41
|
-
this.
|
|
51
|
+
const code = await (0, import_codegen.generateCode)(this.sdkLanguage, a);
|
|
52
|
+
this.actions.push({ ...a, code, intent: this._callIntent });
|
|
42
53
|
}
|
|
43
54
|
});
|
|
44
55
|
return await this.snapshotResult();
|
|
@@ -112,6 +123,12 @@ ${full}`);
|
|
|
112
123
|
}
|
|
113
124
|
}));
|
|
114
125
|
}
|
|
126
|
+
limits(options = {}) {
|
|
127
|
+
return {
|
|
128
|
+
maxTurns: options.maxTurns ?? this.options?.maxTurns ?? 10,
|
|
129
|
+
maxTokens: options.maxTokens ?? this.options?.maxTokens ?? void 0
|
|
130
|
+
};
|
|
131
|
+
}
|
|
115
132
|
_redactText(text) {
|
|
116
133
|
const secrets = this.options?.secrets;
|
|
117
134
|
if (!secrets)
|
|
@@ -90,7 +90,7 @@ class JavaScriptLanguageGenerator {
|
|
|
90
90
|
case "fill":
|
|
91
91
|
return `await ${subject}.${this._asLocator(action.selector)}.fill(${quote(action.text)});`;
|
|
92
92
|
case "setInputFiles":
|
|
93
|
-
return `await ${subject}.${this._asLocator(action.selector)}.setInputFiles(${formatObject(action.files.length === 1 ? action.files[0] : action.files)});`;
|
|
93
|
+
return `await ${subject}.${this._asLocator(action.selector)}.setInputFiles(${(0, import_utils.formatObject)(action.files.length === 1 ? action.files[0] : action.files)});`;
|
|
94
94
|
case "press": {
|
|
95
95
|
const modifiers = (0, import_language.toKeyboardModifiers)(action.modifiers);
|
|
96
96
|
const shortcut = [...modifiers, action.key].join("+");
|
|
@@ -99,7 +99,7 @@ class JavaScriptLanguageGenerator {
|
|
|
99
99
|
case "navigate":
|
|
100
100
|
return `await ${subject}.goto(${quote(action.url)});`;
|
|
101
101
|
case "select":
|
|
102
|
-
return `await ${subject}.${this._asLocator(action.selector)}.selectOption(${formatObject(action.options.length === 1 ? action.options[0] : action.options)});`;
|
|
102
|
+
return `await ${subject}.${this._asLocator(action.selector)}.selectOption(${(0, import_utils.formatObject)(action.options.length === 1 ? action.options[0] : action.options)});`;
|
|
103
103
|
case "assertText":
|
|
104
104
|
return `${this._isTest ? "" : "// "}await expect(${subject}.${this._asLocator(action.selector)}).${action.substring ? "toContainText" : "toHaveText"}(${quote(action.text)});`;
|
|
105
105
|
case "assertChecked":
|
|
@@ -151,7 +151,7 @@ ${useText ? "\ntest.use(" + useText + ");\n" : ""}
|
|
|
151
151
|
const { ${options.browserName}${options.deviceName ? ", devices" : ""} } = require('playwright');
|
|
152
152
|
|
|
153
153
|
(async () => {
|
|
154
|
-
const browser = await ${options.browserName}.launch(${formatObjectOrVoid(options.launchOptions)});
|
|
154
|
+
const browser = await ${options.browserName}.launch(${(0, import_utils.formatObjectOrVoid)(options.launchOptions)});
|
|
155
155
|
const context = await browser.newContext(${formatContextOptions(options.contextOptions, options.deviceName, false)});`);
|
|
156
156
|
if (options.contextOptions.recordHar)
|
|
157
157
|
formatter.add(` await context.routeFromHAR(${quote(options.contextOptions.recordHar.path)});`);
|
|
@@ -171,37 +171,14 @@ function formatOptions(value, hasArguments) {
|
|
|
171
171
|
const keys = Object.keys(value).filter((key) => value[key] !== void 0);
|
|
172
172
|
if (!keys.length)
|
|
173
173
|
return "";
|
|
174
|
-
return (hasArguments ? ", " : "") + formatObject(value);
|
|
175
|
-
}
|
|
176
|
-
function formatObject(value, indent = " ") {
|
|
177
|
-
if (typeof value === "string")
|
|
178
|
-
return quote(value);
|
|
179
|
-
if (Array.isArray(value))
|
|
180
|
-
return `[${value.map((o) => formatObject(o)).join(", ")}]`;
|
|
181
|
-
if (typeof value === "object") {
|
|
182
|
-
const keys = Object.keys(value).filter((key) => value[key] !== void 0).sort();
|
|
183
|
-
if (!keys.length)
|
|
184
|
-
return "{}";
|
|
185
|
-
const tokens = [];
|
|
186
|
-
for (const key of keys)
|
|
187
|
-
tokens.push(`${key}: ${formatObject(value[key])}`);
|
|
188
|
-
return `{
|
|
189
|
-
${indent}${tokens.join(`,
|
|
190
|
-
${indent}`)}
|
|
191
|
-
}`;
|
|
192
|
-
}
|
|
193
|
-
return String(value);
|
|
194
|
-
}
|
|
195
|
-
function formatObjectOrVoid(value, indent = " ") {
|
|
196
|
-
const result = formatObject(value, indent);
|
|
197
|
-
return result === "{}" ? "" : result;
|
|
174
|
+
return (hasArguments ? ", " : "") + (0, import_utils.formatObject)(value);
|
|
198
175
|
}
|
|
199
176
|
function formatContextOptions(options, deviceName, isTest) {
|
|
200
177
|
const device = deviceName && import_deviceDescriptors.deviceDescriptors[deviceName];
|
|
201
178
|
options = { ...options, recordHar: void 0 };
|
|
202
179
|
if (!device)
|
|
203
|
-
return formatObjectOrVoid(options);
|
|
204
|
-
let serializedObject = formatObjectOrVoid((0, import_language.sanitizeDeviceOptions)(device, options));
|
|
180
|
+
return (0, import_utils.formatObjectOrVoid)(options);
|
|
181
|
+
let serializedObject = (0, import_utils.formatObjectOrVoid)((0, import_language.sanitizeDeviceOptions)(device, options));
|
|
205
182
|
if (!serializedObject)
|
|
206
183
|
serializedObject = "{\n}";
|
|
207
184
|
const lines = serializedObject.split("\n");
|