@pedropaulovc/playwright 1.59.0-next
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 +5042 -0
- package/cli.js +19 -0
- package/index.d.ts +17 -0
- package/index.js +17 -0
- package/index.mjs +18 -0
- package/jsx-runtime.js +42 -0
- package/jsx-runtime.mjs +21 -0
- package/lib/agents/agentParser.js +89 -0
- package/lib/agents/copilot-setup-steps.yml +34 -0
- package/lib/agents/generateAgents.js +348 -0
- package/lib/agents/playwright-test-coverage.prompt.md +31 -0
- package/lib/agents/playwright-test-generate.prompt.md +8 -0
- package/lib/agents/playwright-test-generator.agent.md +88 -0
- package/lib/agents/playwright-test-heal.prompt.md +6 -0
- package/lib/agents/playwright-test-healer.agent.md +55 -0
- package/lib/agents/playwright-test-plan.prompt.md +9 -0
- package/lib/agents/playwright-test-planner.agent.md +73 -0
- package/lib/common/config.js +282 -0
- package/lib/common/configLoader.js +344 -0
- package/lib/common/esmLoaderHost.js +104 -0
- package/lib/common/expectBundle.js +28 -0
- package/lib/common/expectBundleImpl.js +407 -0
- package/lib/common/fixtures.js +302 -0
- package/lib/common/globals.js +58 -0
- package/lib/common/ipc.js +60 -0
- package/lib/common/poolBuilder.js +85 -0
- package/lib/common/process.js +132 -0
- package/lib/common/suiteUtils.js +140 -0
- package/lib/common/test.js +321 -0
- package/lib/common/testLoader.js +101 -0
- package/lib/common/testType.js +298 -0
- package/lib/common/validators.js +68 -0
- package/lib/fsWatcher.js +67 -0
- package/lib/index.js +726 -0
- package/lib/internalsForTest.js +42 -0
- package/lib/isomorphic/events.js +77 -0
- package/lib/isomorphic/folders.js +30 -0
- package/lib/isomorphic/stringInternPool.js +69 -0
- package/lib/isomorphic/teleReceiver.js +521 -0
- package/lib/isomorphic/teleSuiteUpdater.js +157 -0
- package/lib/isomorphic/testServerConnection.js +225 -0
- package/lib/isomorphic/testServerInterface.js +16 -0
- package/lib/isomorphic/testTree.js +329 -0
- package/lib/isomorphic/types.d.js +16 -0
- package/lib/loader/loaderMain.js +59 -0
- package/lib/matchers/expect.js +311 -0
- package/lib/matchers/matcherHint.js +44 -0
- package/lib/matchers/matchers.js +383 -0
- package/lib/matchers/toBeTruthy.js +75 -0
- package/lib/matchers/toEqual.js +100 -0
- package/lib/matchers/toHaveURL.js +101 -0
- package/lib/matchers/toMatchAriaSnapshot.js +159 -0
- package/lib/matchers/toMatchSnapshot.js +342 -0
- package/lib/matchers/toMatchText.js +99 -0
- package/lib/mcp/browser/actions.d.js +16 -0
- package/lib/mcp/browser/browserContextFactory.js +329 -0
- package/lib/mcp/browser/browserServerBackend.js +84 -0
- package/lib/mcp/browser/config.js +421 -0
- package/lib/mcp/browser/context.js +244 -0
- package/lib/mcp/browser/response.js +278 -0
- package/lib/mcp/browser/sessionLog.js +75 -0
- package/lib/mcp/browser/tab.js +351 -0
- package/lib/mcp/browser/tools/common.js +65 -0
- package/lib/mcp/browser/tools/console.js +61 -0
- package/lib/mcp/browser/tools/dialogs.js +60 -0
- package/lib/mcp/browser/tools/evaluate.js +61 -0
- package/lib/mcp/browser/tools/files.js +58 -0
- package/lib/mcp/browser/tools/form.js +63 -0
- package/lib/mcp/browser/tools/install.js +72 -0
- package/lib/mcp/browser/tools/keyboard.js +144 -0
- package/lib/mcp/browser/tools/mouse.js +159 -0
- package/lib/mcp/browser/tools/navigate.js +136 -0
- package/lib/mcp/browser/tools/navigateAndWait.js +66 -0
- package/lib/mcp/browser/tools/network.js +78 -0
- package/lib/mcp/browser/tools/pdf.js +49 -0
- package/lib/mcp/browser/tools/runCode.js +78 -0
- package/lib/mcp/browser/tools/screenshot.js +93 -0
- package/lib/mcp/browser/tools/snapshot.js +205 -0
- package/lib/mcp/browser/tools/snapshotViewport.js +63 -0
- package/lib/mcp/browser/tools/tabs.js +67 -0
- package/lib/mcp/browser/tools/tool.js +47 -0
- package/lib/mcp/browser/tools/tracing.js +74 -0
- package/lib/mcp/browser/tools/utils.js +94 -0
- package/lib/mcp/browser/tools/verify.js +143 -0
- package/lib/mcp/browser/tools/wait.js +63 -0
- package/lib/mcp/browser/tools.js +82 -0
- package/lib/mcp/browser/watchdog.js +44 -0
- package/lib/mcp/config.d.js +16 -0
- package/lib/mcp/extension/cdpRelay.js +351 -0
- package/lib/mcp/extension/extensionContextFactory.js +76 -0
- package/lib/mcp/extension/protocol.js +28 -0
- package/lib/mcp/index.js +61 -0
- package/lib/mcp/log.js +35 -0
- package/lib/mcp/program.js +110 -0
- package/lib/mcp/sdk/exports.js +28 -0
- package/lib/mcp/sdk/http.js +152 -0
- package/lib/mcp/sdk/inProcessTransport.js +71 -0
- package/lib/mcp/sdk/server.js +223 -0
- package/lib/mcp/sdk/tool.js +47 -0
- package/lib/mcp/terminal/cli.js +296 -0
- package/lib/mcp/terminal/command.js +56 -0
- package/lib/mcp/terminal/commands.js +519 -0
- package/lib/mcp/terminal/daemon.js +135 -0
- package/lib/mcp/terminal/help.json +47 -0
- package/lib/mcp/terminal/helpGenerator.js +115 -0
- package/lib/mcp/terminal/socketConnection.js +80 -0
- package/lib/mcp/test/browserBackend.js +98 -0
- package/lib/mcp/test/generatorTools.js +122 -0
- package/lib/mcp/test/plannerTools.js +145 -0
- package/lib/mcp/test/seed.js +82 -0
- package/lib/mcp/test/streams.js +44 -0
- package/lib/mcp/test/testBackend.js +99 -0
- package/lib/mcp/test/testContext.js +285 -0
- package/lib/mcp/test/testTool.js +30 -0
- package/lib/mcp/test/testTools.js +108 -0
- package/lib/plugins/gitCommitInfoPlugin.js +198 -0
- package/lib/plugins/index.js +28 -0
- package/lib/plugins/webServerPlugin.js +237 -0
- package/lib/program.js +417 -0
- package/lib/reporters/base.js +634 -0
- package/lib/reporters/blob.js +138 -0
- package/lib/reporters/dot.js +99 -0
- package/lib/reporters/empty.js +32 -0
- package/lib/reporters/github.js +128 -0
- package/lib/reporters/html.js +633 -0
- package/lib/reporters/internalReporter.js +138 -0
- package/lib/reporters/json.js +254 -0
- package/lib/reporters/junit.js +232 -0
- package/lib/reporters/line.js +131 -0
- package/lib/reporters/list.js +253 -0
- package/lib/reporters/listModeReporter.js +69 -0
- package/lib/reporters/markdown.js +144 -0
- package/lib/reporters/merge.js +558 -0
- package/lib/reporters/multiplexer.js +112 -0
- package/lib/reporters/reporterV2.js +102 -0
- package/lib/reporters/teleEmitter.js +317 -0
- package/lib/reporters/versions/blobV1.js +16 -0
- package/lib/runner/dispatcher.js +530 -0
- package/lib/runner/failureTracker.js +72 -0
- package/lib/runner/lastRun.js +77 -0
- package/lib/runner/loadUtils.js +334 -0
- package/lib/runner/loaderHost.js +89 -0
- package/lib/runner/processHost.js +180 -0
- package/lib/runner/projectUtils.js +241 -0
- package/lib/runner/rebase.js +189 -0
- package/lib/runner/reporters.js +138 -0
- package/lib/runner/sigIntWatcher.js +96 -0
- package/lib/runner/storage.js +91 -0
- package/lib/runner/taskRunner.js +127 -0
- package/lib/runner/tasks.js +410 -0
- package/lib/runner/testGroups.js +125 -0
- package/lib/runner/testRunner.js +398 -0
- package/lib/runner/testServer.js +269 -0
- package/lib/runner/uiModeReporter.js +30 -0
- package/lib/runner/vcs.js +72 -0
- package/lib/runner/watchMode.js +396 -0
- package/lib/runner/workerHost.js +104 -0
- package/lib/third_party/pirates.js +62 -0
- package/lib/third_party/tsconfig-loader.js +103 -0
- package/lib/transform/babelBundle.js +46 -0
- package/lib/transform/babelBundleImpl.js +461 -0
- package/lib/transform/compilationCache.js +274 -0
- package/lib/transform/esmLoader.js +103 -0
- package/lib/transform/md.js +221 -0
- package/lib/transform/portTransport.js +67 -0
- package/lib/transform/transform.js +303 -0
- package/lib/util.js +400 -0
- package/lib/utilsBundle.js +50 -0
- package/lib/utilsBundleImpl.js +103 -0
- package/lib/worker/fixtureRunner.js +262 -0
- package/lib/worker/testInfo.js +536 -0
- package/lib/worker/testTracing.js +345 -0
- package/lib/worker/timeoutManager.js +174 -0
- package/lib/worker/util.js +31 -0
- package/lib/worker/workerMain.js +530 -0
- package/package.json +72 -0
- package/test.d.ts +18 -0
- package/test.js +24 -0
- package/test.mjs +34 -0
- package/types/test.d.ts +10251 -0
- package/types/testReporter.d.ts +822 -0
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
{
|
|
2
|
+
"global": "Usage: playwright-cli <command> [args] [options]\n\nCore:\n open <url> open url\n close close the page\n type <text> type text into editable element\n click <ref> [button] perform click on a web page\n dblclick <ref> [button] perform double click on a web page\n fill <ref> <text> fill text into editable element\n drag <startRef> <endRef> perform drag and drop between two elements\n hover <ref> hover over element on page\n select <ref> <vals> select an option in a dropdown\n upload <file> upload one or multiple files\n check <ref> check a checkbox or radio button\n uncheck <ref> uncheck a checkbox or radio button\n snapshot capture page snapshot to obtain element ref\n eval <func> [ref] evaluate javascript expression on page or element\n dialog-accept [prompt] accept a dialog\n dialog-dismiss dismiss a dialog\n resize <w> <h> resize the browser window\n\nNavigation:\n go-back go back to the previous page\n go-forward go forward to the next page\n reload reload the current page\n\nKeyboard:\n key-press <key> press a key on the keyboard, `a`, `arrowleft`\n key-down <key> press a key down on the keyboard\n key-up <key> press a key up on the keyboard\n\nMouse:\n mouse-move <x> <y> move mouse to a given position\n mouse-down [button] press mouse down\n mouse-up [button] press mouse up\n mouse-wheel <dx> <dy> scroll mouse wheel\n\nSave as:\n screenshot [ref] screenshot of the current page or element\n pdf save page as pdf\n\nTabs:\n tab-list list all tabs\n tab-new [url] create a new tab\n tab-close [index] close a browser tab\n tab-select <index> select a browser tab\n\nDevTools:\n console [min-level] list console messages\n network list all network requests since loading the page\n run-code <code> run playwright code snippet\n tracing-start start trace recording\n tracing-stop stop trace recording\n\nSessions:\n session-list list all sessions\n session-stop [name] stop session\n session-stop-all stop all sessions\n session-delete [name] delete session data",
|
|
3
|
+
"commands": {
|
|
4
|
+
"open": "playwright-cli open <url>\n\nOpen URL\n\nArguments:\n <url> the url to navigate to\nOptions:\n --headed run browser in headed mode",
|
|
5
|
+
"close": "playwright-cli close \n\nClose the page\n",
|
|
6
|
+
"type": "playwright-cli type <text>\n\nType text into editable element\n\nArguments:\n <text> text to type into the element\nOptions:\n --submit whether to submit entered text (press enter after)",
|
|
7
|
+
"click": "playwright-cli click <ref> [button]\n\nPerform click on a web page\n\nArguments:\n <ref> exact target element reference from the page snapshot\n [button] button to click, defaults to left\nOptions:\n --modifiers modifier keys to press",
|
|
8
|
+
"dblclick": "playwright-cli dblclick <ref> [button]\n\nPerform double click on a web page\n\nArguments:\n <ref> exact target element reference from the page snapshot\n [button] button to click, defaults to left\nOptions:\n --modifiers modifier keys to press",
|
|
9
|
+
"fill": "playwright-cli fill <ref> <text>\n\nFill text into editable element\n\nArguments:\n <ref> exact target element reference from the page snapshot\n <text> text to fill into the element\nOptions:\n --submit whether to submit entered text (press enter after)",
|
|
10
|
+
"drag": "playwright-cli drag <startRef> <endRef>\n\nPerform drag and drop between two elements\n\nArguments:\n <startRef> exact source element reference from the page snapshot\n <endRef> exact target element reference from the page snapshot\nOptions:\n --headed run browser in headed mode",
|
|
11
|
+
"hover": "playwright-cli hover <ref>\n\nHover over element on page\n\nArguments:\n <ref> exact target element reference from the page snapshot",
|
|
12
|
+
"select": "playwright-cli select <ref> <vals>\n\nSelect an option in a dropdown\n\nArguments:\n <ref> exact target element reference from the page snapshot\n <vals> array of values to select in the dropdown. this can be a single value or multiple values.",
|
|
13
|
+
"upload": "playwright-cli upload <file>\n\nUpload one or multiple files\n\nArguments:\n <file> the absolute paths to the files to upload",
|
|
14
|
+
"check": "playwright-cli check <ref>\n\nCheck a checkbox or radio button\n\nArguments:\n <ref> exact target element reference from the page snapshot",
|
|
15
|
+
"uncheck": "playwright-cli uncheck <ref>\n\nUncheck a checkbox or radio button\n\nArguments:\n <ref> exact target element reference from the page snapshot",
|
|
16
|
+
"snapshot": "playwright-cli snapshot \n\nCapture page snapshot to obtain element ref\n\nOptions:\n --filename save snapshot to markdown file instead of returning it in the response.",
|
|
17
|
+
"eval": "playwright-cli eval <func> [ref]\n\nEvaluate JavaScript expression on page or element\n\nArguments:\n <func> () => { /* code */ } or (element) => { /* code */ } when element is provided\n [ref] exact target element reference from the page snapshot",
|
|
18
|
+
"console": "playwright-cli console [min-level]\n\nList console messages\n\nArguments:\n [min-level] level of the console messages to return. each level includes the messages of more severe levels. defaults to \"info\".\nOptions:\n --clear whether to clear the console list",
|
|
19
|
+
"dialog-accept": "playwright-cli dialog-accept [prompt]\n\nAccept a dialog\n\nArguments:\n [prompt] the text of the prompt in case of a prompt dialog.",
|
|
20
|
+
"dialog-dismiss": "playwright-cli dialog-dismiss \n\nDismiss a dialog\n",
|
|
21
|
+
"resize": "playwright-cli resize <w> <h>\n\nResize the browser window\n\nArguments:\n <w> width of the browser window\n <h> height of the browser window",
|
|
22
|
+
"go-back": "playwright-cli go-back \n\nGo back to the previous page\n",
|
|
23
|
+
"go-forward": "playwright-cli go-forward \n\nGo forward to the next page\n",
|
|
24
|
+
"reload": "playwright-cli reload \n\nReload the current page\n",
|
|
25
|
+
"key-press": "playwright-cli key-press <key>\n\nPress a key on the keyboard, `a`, `ArrowLeft`\n\nArguments:\n <key> name of the key to press or a character to generate, such as `arrowleft` or `a`",
|
|
26
|
+
"key-down": "playwright-cli key-down <key>\n\nPress a key down on the keyboard\n\nArguments:\n <key> name of the key to press or a character to generate, such as `arrowleft` or `a`",
|
|
27
|
+
"key-up": "playwright-cli key-up <key>\n\nPress a key up on the keyboard\n\nArguments:\n <key> name of the key to press or a character to generate, such as `arrowleft` or `a`",
|
|
28
|
+
"mouse-move": "playwright-cli mouse-move <x> <y>\n\nMove mouse to a given position\n\nArguments:\n <x> x coordinate\n <y> y coordinate",
|
|
29
|
+
"mouse-down": "playwright-cli mouse-down [button]\n\nPress mouse down\n\nArguments:\n [button] button to press, defaults to left",
|
|
30
|
+
"mouse-up": "playwright-cli mouse-up [button]\n\nPress mouse up\n\nArguments:\n [button] button to press, defaults to left",
|
|
31
|
+
"mouse-wheel": "playwright-cli mouse-wheel <dx> <dy>\n\nScroll mouse wheel\n\nArguments:\n <dx> y delta\n <dy> x delta",
|
|
32
|
+
"screenshot": "playwright-cli screenshot [ref]\n\nscreenshot of the current page or element\n\nArguments:\n [ref] exact target element reference from the page snapshot.\nOptions:\n --filename file name to save the screenshot to. defaults to `page-{timestamp}.{png|jpeg}` if not specified.\n --fullPage when true, takes a screenshot of the full scrollable page, instead of the currently visible viewport.",
|
|
33
|
+
"pdf": "playwright-cli pdf \n\nSave page as PDF\n\nOptions:\n --filename file name to save the pdf to. defaults to `page-{timestamp}.pdf` if not specified.",
|
|
34
|
+
"tab-list": "playwright-cli tab-list \n\nList all tabs\n",
|
|
35
|
+
"tab-new": "playwright-cli tab-new [url]\n\nCreate a new tab\n\nArguments:\n [url] the url to navigate to in the new tab. if omitted, the new tab will be blank.",
|
|
36
|
+
"tab-close": "playwright-cli tab-close [index]\n\nClose a browser tab\n\nArguments:\n [index] tab index. if omitted, current tab is closed.",
|
|
37
|
+
"tab-select": "playwright-cli tab-select <index>\n\nSelect a browser tab\n\nArguments:\n <index> tab index",
|
|
38
|
+
"network": "playwright-cli network \n\nList all network requests since loading the page\n\nOptions:\n --static whether to include successful static resources like images, fonts, scripts, etc. defaults to false.\n --clear whether to clear the network list",
|
|
39
|
+
"run-code": "playwright-cli run-code <code>\n\nRun Playwright code snippet\n\nArguments:\n <code> a javascript function containing playwright code to execute. it will be invoked with a single argument, page, which you can use for any page interaction.",
|
|
40
|
+
"tracing-start": "playwright-cli tracing-start \n\nStart trace recording\n",
|
|
41
|
+
"tracing-stop": "playwright-cli tracing-stop \n\nStop trace recording\n",
|
|
42
|
+
"session-list": "playwright-cli session-list \n\nList all sessions\n",
|
|
43
|
+
"session-stop": "playwright-cli session-stop [name]\n\nStop session\n\nArguments:\n [name] name of the session to stop. if omitted, current session is stopped.",
|
|
44
|
+
"session-stop-all": "playwright-cli session-stop-all \n\nStop all sessions\n",
|
|
45
|
+
"session-delete": "playwright-cli session-delete [name]\n\nDelete session data\n\nArguments:\n [name] name of the session to delete. if omitted, current session is deleted."
|
|
46
|
+
}
|
|
47
|
+
}
|
|
@@ -0,0 +1,115 @@
|
|
|
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 __copyProps = (to, from, except, desc) => {
|
|
9
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
10
|
+
for (let key of __getOwnPropNames(from))
|
|
11
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
12
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
13
|
+
}
|
|
14
|
+
return to;
|
|
15
|
+
};
|
|
16
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
17
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
18
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
19
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
20
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
21
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
22
|
+
mod
|
|
23
|
+
));
|
|
24
|
+
var import_fs = __toESM(require("fs"));
|
|
25
|
+
var import_path = __toESM(require("path"));
|
|
26
|
+
var import_commands = require("./commands");
|
|
27
|
+
function commandArgs(command) {
|
|
28
|
+
const args = [];
|
|
29
|
+
const shape = command.args ? command.args.shape : {};
|
|
30
|
+
for (const [name, schema] of Object.entries(shape)) {
|
|
31
|
+
const zodSchema = schema;
|
|
32
|
+
const description = zodSchema.description ?? "";
|
|
33
|
+
args.push({ name, description, optional: zodSchema.safeParse(void 0).success });
|
|
34
|
+
}
|
|
35
|
+
return args;
|
|
36
|
+
}
|
|
37
|
+
function commandArgsText(args) {
|
|
38
|
+
return args.map((a) => a.optional ? `[${a.name}]` : `<${a.name}>`).join(" ");
|
|
39
|
+
}
|
|
40
|
+
function generateCommandHelp(command) {
|
|
41
|
+
const args = commandArgs(command);
|
|
42
|
+
const lines = [
|
|
43
|
+
`playwright-cli ${command.name} ${commandArgsText(args)}`,
|
|
44
|
+
"",
|
|
45
|
+
command.description,
|
|
46
|
+
""
|
|
47
|
+
];
|
|
48
|
+
if (args.length) {
|
|
49
|
+
lines.push("Arguments:");
|
|
50
|
+
lines.push(...args.map((a) => formatWithGap(` ${a.optional ? `[${a.name}]` : `<${a.name}>`}`, a.description.toLowerCase())));
|
|
51
|
+
}
|
|
52
|
+
if (command.options) {
|
|
53
|
+
lines.push("Options:");
|
|
54
|
+
const optionsShape = command.options.shape;
|
|
55
|
+
for (const [name, schema] of Object.entries(optionsShape)) {
|
|
56
|
+
const zodSchema = schema;
|
|
57
|
+
const description = (zodSchema.description ?? "").toLowerCase();
|
|
58
|
+
lines.push(formatWithGap(` --${name}`, description));
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return lines.join("\n");
|
|
62
|
+
}
|
|
63
|
+
const categories = [
|
|
64
|
+
{ name: "core", title: "Core" },
|
|
65
|
+
{ name: "navigation", title: "Navigation" },
|
|
66
|
+
{ name: "keyboard", title: "Keyboard" },
|
|
67
|
+
{ name: "mouse", title: "Mouse" },
|
|
68
|
+
{ name: "export", title: "Save as" },
|
|
69
|
+
{ name: "tabs", title: "Tabs" },
|
|
70
|
+
{ name: "storage", title: "Storage" },
|
|
71
|
+
{ name: "devtools", title: "DevTools" },
|
|
72
|
+
{ name: "session", title: "Sessions" }
|
|
73
|
+
];
|
|
74
|
+
function generateHelp() {
|
|
75
|
+
const lines = [];
|
|
76
|
+
lines.push("Usage: playwright-cli <command> [args] [options]");
|
|
77
|
+
const commandsByCategory = /* @__PURE__ */ new Map();
|
|
78
|
+
for (const c of categories)
|
|
79
|
+
commandsByCategory.set(c.name, []);
|
|
80
|
+
for (const command of Object.values(import_commands.commands))
|
|
81
|
+
commandsByCategory.get(command.category).push(command);
|
|
82
|
+
for (const c of categories) {
|
|
83
|
+
const cc = commandsByCategory.get(c.name);
|
|
84
|
+
if (!cc.length)
|
|
85
|
+
continue;
|
|
86
|
+
lines.push(`
|
|
87
|
+
${c.title}:`);
|
|
88
|
+
for (const command of cc)
|
|
89
|
+
lines.push(generateHelpEntry(command));
|
|
90
|
+
}
|
|
91
|
+
return lines.join("\n");
|
|
92
|
+
}
|
|
93
|
+
function generateHelpEntry(command) {
|
|
94
|
+
const args = commandArgs(command);
|
|
95
|
+
const prefix = ` ${command.name} ${commandArgsText(args)}`;
|
|
96
|
+
const suffix = command.description.toLowerCase();
|
|
97
|
+
return formatWithGap(prefix, suffix);
|
|
98
|
+
}
|
|
99
|
+
async function main() {
|
|
100
|
+
const help = {
|
|
101
|
+
global: generateHelp(),
|
|
102
|
+
commands: Object.fromEntries(
|
|
103
|
+
Object.entries(import_commands.commands).map(([name, command]) => [name, generateCommandHelp(command)])
|
|
104
|
+
)
|
|
105
|
+
};
|
|
106
|
+
const fileName = import_path.default.resolve(__dirname, "help.json").replace("lib", "src");
|
|
107
|
+
console.log("Writing ", import_path.default.relative(process.cwd(), fileName));
|
|
108
|
+
await import_fs.default.promises.writeFile(fileName, JSON.stringify(help, null, 2));
|
|
109
|
+
console.log(help.global);
|
|
110
|
+
}
|
|
111
|
+
function formatWithGap(prefix, text) {
|
|
112
|
+
const indent = Math.max(1, 30 - prefix.length);
|
|
113
|
+
return prefix + " ".repeat(indent) + text;
|
|
114
|
+
}
|
|
115
|
+
void main();
|
|
@@ -0,0 +1,80 @@
|
|
|
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 socketConnection_exports = {};
|
|
20
|
+
__export(socketConnection_exports, {
|
|
21
|
+
SocketConnection: () => SocketConnection
|
|
22
|
+
});
|
|
23
|
+
module.exports = __toCommonJS(socketConnection_exports);
|
|
24
|
+
var import_utilsBundle = require("playwright-core/lib/utilsBundle");
|
|
25
|
+
const daemonDebug = (0, import_utilsBundle.debug)("pw:daemon");
|
|
26
|
+
class SocketConnection {
|
|
27
|
+
constructor(socket) {
|
|
28
|
+
this._pendingBuffers = [];
|
|
29
|
+
this._socket = socket;
|
|
30
|
+
socket.on("data", (buffer) => this._onData(buffer));
|
|
31
|
+
socket.on("close", () => {
|
|
32
|
+
this.onclose?.();
|
|
33
|
+
});
|
|
34
|
+
socket.on("error", (e) => daemonDebug(`error: ${e.message}`));
|
|
35
|
+
}
|
|
36
|
+
async send(message) {
|
|
37
|
+
await new Promise((resolve, reject) => {
|
|
38
|
+
this._socket.write(`${JSON.stringify(message)}
|
|
39
|
+
`, (error) => {
|
|
40
|
+
if (error)
|
|
41
|
+
reject(error);
|
|
42
|
+
else
|
|
43
|
+
resolve(void 0);
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
close() {
|
|
48
|
+
this._socket.destroy();
|
|
49
|
+
}
|
|
50
|
+
_onData(buffer) {
|
|
51
|
+
let end = buffer.indexOf("\n");
|
|
52
|
+
if (end === -1) {
|
|
53
|
+
this._pendingBuffers.push(buffer);
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
this._pendingBuffers.push(buffer.slice(0, end));
|
|
57
|
+
const message = Buffer.concat(this._pendingBuffers).toString();
|
|
58
|
+
this._dispatchMessage(message);
|
|
59
|
+
let start = end + 1;
|
|
60
|
+
end = buffer.indexOf("\n", start);
|
|
61
|
+
while (end !== -1) {
|
|
62
|
+
const message2 = buffer.toString(void 0, start, end);
|
|
63
|
+
this._dispatchMessage(message2);
|
|
64
|
+
start = end + 1;
|
|
65
|
+
end = buffer.indexOf("\n", start);
|
|
66
|
+
}
|
|
67
|
+
this._pendingBuffers = [buffer.slice(start)];
|
|
68
|
+
}
|
|
69
|
+
_dispatchMessage(message) {
|
|
70
|
+
try {
|
|
71
|
+
this.onmessage?.(JSON.parse(message));
|
|
72
|
+
} catch (e) {
|
|
73
|
+
daemonDebug("failed to dispatch message", e);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
78
|
+
0 && (module.exports = {
|
|
79
|
+
SocketConnection
|
|
80
|
+
});
|
|
@@ -0,0 +1,98 @@
|
|
|
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 browserBackend_exports = {};
|
|
20
|
+
__export(browserBackend_exports, {
|
|
21
|
+
createCustomMessageHandler: () => createCustomMessageHandler
|
|
22
|
+
});
|
|
23
|
+
module.exports = __toCommonJS(browserBackend_exports);
|
|
24
|
+
var import_config = require("../browser/config");
|
|
25
|
+
var import_browserServerBackend = require("../browser/browserServerBackend");
|
|
26
|
+
var import_tab = require("../browser/tab");
|
|
27
|
+
var import_util = require("../../util");
|
|
28
|
+
var import_browserContextFactory = require("../browser/browserContextFactory");
|
|
29
|
+
function createCustomMessageHandler(testInfo, context) {
|
|
30
|
+
let backend;
|
|
31
|
+
return async (data) => {
|
|
32
|
+
if (data.initialize) {
|
|
33
|
+
if (backend)
|
|
34
|
+
throw new Error("MCP backend is already initialized");
|
|
35
|
+
backend = new import_browserServerBackend.BrowserServerBackend({ ...import_config.defaultConfig, capabilities: ["testing"] }, (0, import_browserContextFactory.identityBrowserContextFactory)(context));
|
|
36
|
+
await backend.initialize(data.initialize.clientInfo);
|
|
37
|
+
const pausedMessage = await generatePausedMessage(testInfo, context);
|
|
38
|
+
return { initialize: { pausedMessage } };
|
|
39
|
+
}
|
|
40
|
+
if (data.listTools) {
|
|
41
|
+
if (!backend)
|
|
42
|
+
throw new Error("MCP backend is not initialized");
|
|
43
|
+
return { listTools: await backend.listTools() };
|
|
44
|
+
}
|
|
45
|
+
if (data.callTool) {
|
|
46
|
+
if (!backend)
|
|
47
|
+
throw new Error("MCP backend is not initialized");
|
|
48
|
+
return { callTool: await backend.callTool(data.callTool.name, data.callTool.arguments) };
|
|
49
|
+
}
|
|
50
|
+
if (data.close) {
|
|
51
|
+
backend?.serverClosed();
|
|
52
|
+
backend = void 0;
|
|
53
|
+
return { close: {} };
|
|
54
|
+
}
|
|
55
|
+
throw new Error("Unknown MCP request");
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
async function generatePausedMessage(testInfo, context) {
|
|
59
|
+
const lines = [];
|
|
60
|
+
if (testInfo.errors.length) {
|
|
61
|
+
lines.push(`### Paused on error:`);
|
|
62
|
+
for (const error of testInfo.errors)
|
|
63
|
+
lines.push((0, import_util.stripAnsiEscapes)(error.message || ""));
|
|
64
|
+
} else {
|
|
65
|
+
lines.push(`### Paused at end of test. ready for interaction`);
|
|
66
|
+
}
|
|
67
|
+
for (let i = 0; i < context.pages().length; i++) {
|
|
68
|
+
const page = context.pages()[i];
|
|
69
|
+
const stateSuffix = context.pages().length > 1 ? i + 1 + " of " + context.pages().length : "state";
|
|
70
|
+
lines.push(
|
|
71
|
+
"",
|
|
72
|
+
`### Page ${stateSuffix}`,
|
|
73
|
+
`- Page URL: ${page.url()}`,
|
|
74
|
+
`- Page Title: ${await page.title()}`.trim()
|
|
75
|
+
);
|
|
76
|
+
let console = testInfo.errors.length ? await import_tab.Tab.collectConsoleMessages(page) : [];
|
|
77
|
+
console = console.filter((msg) => msg.type === "error");
|
|
78
|
+
if (console.length) {
|
|
79
|
+
lines.push("- Console Messages:");
|
|
80
|
+
for (const message of console)
|
|
81
|
+
lines.push(` - ${message.toString()}`);
|
|
82
|
+
}
|
|
83
|
+
lines.push(
|
|
84
|
+
`- Page Snapshot:`,
|
|
85
|
+
"```yaml",
|
|
86
|
+
(await page._snapshotForAI()).full,
|
|
87
|
+
"```"
|
|
88
|
+
);
|
|
89
|
+
}
|
|
90
|
+
lines.push("");
|
|
91
|
+
if (testInfo.errors.length)
|
|
92
|
+
lines.push(`### Task`, `Try recovering from the error prior to continuing`);
|
|
93
|
+
return lines.join("\n");
|
|
94
|
+
}
|
|
95
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
96
|
+
0 && (module.exports = {
|
|
97
|
+
createCustomMessageHandler
|
|
98
|
+
});
|
|
@@ -0,0 +1,122 @@
|
|
|
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 generatorTools_exports = {};
|
|
30
|
+
__export(generatorTools_exports, {
|
|
31
|
+
generatorReadLog: () => generatorReadLog,
|
|
32
|
+
generatorWriteTest: () => generatorWriteTest,
|
|
33
|
+
setupPage: () => setupPage
|
|
34
|
+
});
|
|
35
|
+
module.exports = __toCommonJS(generatorTools_exports);
|
|
36
|
+
var import_fs = __toESM(require("fs"));
|
|
37
|
+
var import_path = __toESM(require("path"));
|
|
38
|
+
var import_mcpBundle = require("playwright-core/lib/mcpBundle");
|
|
39
|
+
var import_testTool = require("./testTool");
|
|
40
|
+
var import_testContext = require("./testContext");
|
|
41
|
+
const setupPage = (0, import_testTool.defineTestTool)({
|
|
42
|
+
schema: {
|
|
43
|
+
name: "generator_setup_page",
|
|
44
|
+
title: "Setup generator page",
|
|
45
|
+
description: "Setup the page for test.",
|
|
46
|
+
inputSchema: import_mcpBundle.z.object({
|
|
47
|
+
plan: import_mcpBundle.z.string().describe("The plan for the test. This should be the actual test plan with all the steps."),
|
|
48
|
+
project: import_mcpBundle.z.string().optional().describe('Project to use for setup. For example: "chromium", if no project is provided uses the first project in the config.'),
|
|
49
|
+
seedFile: import_mcpBundle.z.string().optional().describe('A seed file contains a single test that is used to setup the page for testing, for example: "tests/seed.spec.ts". If no seed file is provided, a default seed file is created.')
|
|
50
|
+
}),
|
|
51
|
+
type: "readOnly"
|
|
52
|
+
},
|
|
53
|
+
handle: async (context, params) => {
|
|
54
|
+
const seed = await context.getOrCreateSeedFile(params.seedFile, params.project);
|
|
55
|
+
context.generatorJournal = new import_testContext.GeneratorJournal(context.rootPath, params.plan, seed);
|
|
56
|
+
const { output, status } = await context.runSeedTest(seed.file, seed.projectName);
|
|
57
|
+
return { content: [{ type: "text", text: output }], isError: status !== "paused" };
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
const generatorReadLog = (0, import_testTool.defineTestTool)({
|
|
61
|
+
schema: {
|
|
62
|
+
name: "generator_read_log",
|
|
63
|
+
title: "Retrieve test log",
|
|
64
|
+
description: "Retrieve the performed test log",
|
|
65
|
+
inputSchema: import_mcpBundle.z.object({}),
|
|
66
|
+
type: "readOnly"
|
|
67
|
+
},
|
|
68
|
+
handle: async (context) => {
|
|
69
|
+
if (!context.generatorJournal)
|
|
70
|
+
throw new Error(`Please setup page using "${setupPage.schema.name}" first.`);
|
|
71
|
+
const result = context.generatorJournal.journal();
|
|
72
|
+
return { content: [{
|
|
73
|
+
type: "text",
|
|
74
|
+
text: result
|
|
75
|
+
}] };
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
const generatorWriteTest = (0, import_testTool.defineTestTool)({
|
|
79
|
+
schema: {
|
|
80
|
+
name: "generator_write_test",
|
|
81
|
+
title: "Write test",
|
|
82
|
+
description: "Write the generated test to the test file",
|
|
83
|
+
inputSchema: import_mcpBundle.z.object({
|
|
84
|
+
fileName: import_mcpBundle.z.string().describe("The file to write the test to"),
|
|
85
|
+
code: import_mcpBundle.z.string().describe("The generated test code")
|
|
86
|
+
}),
|
|
87
|
+
type: "readOnly"
|
|
88
|
+
},
|
|
89
|
+
handle: async (context, params) => {
|
|
90
|
+
if (!context.generatorJournal)
|
|
91
|
+
throw new Error(`Please setup page using "${setupPage.schema.name}" first.`);
|
|
92
|
+
const testRunner = context.existingTestRunner();
|
|
93
|
+
if (!testRunner)
|
|
94
|
+
throw new Error("No test runner found, please setup page and perform actions first.");
|
|
95
|
+
const config = await testRunner.loadConfig();
|
|
96
|
+
const dirs = [];
|
|
97
|
+
for (const project of config.projects) {
|
|
98
|
+
const testDir = import_path.default.relative(context.rootPath, project.project.testDir).replace(/\\/g, "/");
|
|
99
|
+
const fileName = params.fileName.replace(/\\/g, "/");
|
|
100
|
+
if (fileName.startsWith(testDir)) {
|
|
101
|
+
const resolvedFile = import_path.default.resolve(context.rootPath, fileName);
|
|
102
|
+
await import_fs.default.promises.mkdir(import_path.default.dirname(resolvedFile), { recursive: true });
|
|
103
|
+
await import_fs.default.promises.writeFile(resolvedFile, params.code);
|
|
104
|
+
return {
|
|
105
|
+
content: [{
|
|
106
|
+
type: "text",
|
|
107
|
+
text: `### Result
|
|
108
|
+
Test written to ${params.fileName}`
|
|
109
|
+
}]
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
dirs.push(testDir);
|
|
113
|
+
}
|
|
114
|
+
throw new Error(`Test file did not match any of the test dirs: ${dirs.join(", ")}`);
|
|
115
|
+
}
|
|
116
|
+
});
|
|
117
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
118
|
+
0 && (module.exports = {
|
|
119
|
+
generatorReadLog,
|
|
120
|
+
generatorWriteTest,
|
|
121
|
+
setupPage
|
|
122
|
+
});
|
|
@@ -0,0 +1,145 @@
|
|
|
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 plannerTools_exports = {};
|
|
30
|
+
__export(plannerTools_exports, {
|
|
31
|
+
saveTestPlan: () => saveTestPlan,
|
|
32
|
+
setupPage: () => setupPage,
|
|
33
|
+
submitTestPlan: () => submitTestPlan
|
|
34
|
+
});
|
|
35
|
+
module.exports = __toCommonJS(plannerTools_exports);
|
|
36
|
+
var import_fs = __toESM(require("fs"));
|
|
37
|
+
var import_path = __toESM(require("path"));
|
|
38
|
+
var import_mcpBundle = require("playwright-core/lib/mcpBundle");
|
|
39
|
+
var import_testTool = require("./testTool");
|
|
40
|
+
const setupPage = (0, import_testTool.defineTestTool)({
|
|
41
|
+
schema: {
|
|
42
|
+
name: "planner_setup_page",
|
|
43
|
+
title: "Setup planner page",
|
|
44
|
+
description: "Setup the page for test planning",
|
|
45
|
+
inputSchema: import_mcpBundle.z.object({
|
|
46
|
+
project: import_mcpBundle.z.string().optional().describe('Project to use for setup. For example: "chromium", if no project is provided uses the first project in the config.'),
|
|
47
|
+
seedFile: import_mcpBundle.z.string().optional().describe('A seed file contains a single test that is used to setup the page for testing, for example: "tests/seed.spec.ts". If no seed file is provided, a default seed file is created.')
|
|
48
|
+
}),
|
|
49
|
+
type: "readOnly"
|
|
50
|
+
},
|
|
51
|
+
handle: async (context, params) => {
|
|
52
|
+
const seed = await context.getOrCreateSeedFile(params.seedFile, params.project);
|
|
53
|
+
const { output, status } = await context.runSeedTest(seed.file, seed.projectName);
|
|
54
|
+
return { content: [{ type: "text", text: output }], isError: status !== "paused" };
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
const planSchema = import_mcpBundle.z.object({
|
|
58
|
+
overview: import_mcpBundle.z.string().describe("A brief overview of the application to be tested"),
|
|
59
|
+
suites: import_mcpBundle.z.array(import_mcpBundle.z.object({
|
|
60
|
+
name: import_mcpBundle.z.string().describe("The name of the suite"),
|
|
61
|
+
seedFile: import_mcpBundle.z.string().describe("A seed file that was used to setup the page for testing."),
|
|
62
|
+
tests: import_mcpBundle.z.array(import_mcpBundle.z.object({
|
|
63
|
+
name: import_mcpBundle.z.string().describe("The name of the test"),
|
|
64
|
+
file: import_mcpBundle.z.string().describe('The file the test should be saved to, for example: "tests/<suite-name>/<test-name>.spec.ts".'),
|
|
65
|
+
steps: import_mcpBundle.z.array(import_mcpBundle.z.object({
|
|
66
|
+
perform: import_mcpBundle.z.string().optional().describe(`Action to perform. For example: 'Click on the "Submit" button'.`),
|
|
67
|
+
expect: import_mcpBundle.z.string().array().describe(`Expected result of the action where appropriate. For example: 'The page should show the "Thank you for your submission" message'`)
|
|
68
|
+
}))
|
|
69
|
+
}))
|
|
70
|
+
}))
|
|
71
|
+
});
|
|
72
|
+
const submitTestPlan = (0, import_testTool.defineTestTool)({
|
|
73
|
+
schema: {
|
|
74
|
+
name: "planner_submit_plan",
|
|
75
|
+
title: "Submit test plan",
|
|
76
|
+
description: "Submit the test plan to the test planner",
|
|
77
|
+
inputSchema: planSchema,
|
|
78
|
+
type: "readOnly"
|
|
79
|
+
},
|
|
80
|
+
handle: async (context, params) => {
|
|
81
|
+
return {
|
|
82
|
+
content: [{
|
|
83
|
+
type: "text",
|
|
84
|
+
text: JSON.stringify(params, null, 2)
|
|
85
|
+
}]
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
const saveTestPlan = (0, import_testTool.defineTestTool)({
|
|
90
|
+
schema: {
|
|
91
|
+
name: "planner_save_plan",
|
|
92
|
+
title: "Save test plan as markdown file",
|
|
93
|
+
description: "Save the test plan as a markdown file",
|
|
94
|
+
inputSchema: planSchema.extend({
|
|
95
|
+
name: import_mcpBundle.z.string().describe('The name of the test plan, for example: "Test Plan".'),
|
|
96
|
+
fileName: import_mcpBundle.z.string().describe('The file to save the test plan to, for example: "spec/test.plan.md". Relative to the workspace root.')
|
|
97
|
+
}),
|
|
98
|
+
type: "readOnly"
|
|
99
|
+
},
|
|
100
|
+
handle: async (context, params) => {
|
|
101
|
+
const lines = [];
|
|
102
|
+
lines.push(`# ${params.name}`);
|
|
103
|
+
lines.push(``);
|
|
104
|
+
lines.push(`## Application Overview`);
|
|
105
|
+
lines.push(``);
|
|
106
|
+
lines.push(params.overview);
|
|
107
|
+
lines.push(``);
|
|
108
|
+
lines.push(`## Test Scenarios`);
|
|
109
|
+
for (let i = 0; i < params.suites.length; i++) {
|
|
110
|
+
lines.push(``);
|
|
111
|
+
const suite = params.suites[i];
|
|
112
|
+
lines.push(`### ${i + 1}. ${suite.name}`);
|
|
113
|
+
lines.push(``);
|
|
114
|
+
lines.push(`**Seed:** \`${suite.seedFile}\``);
|
|
115
|
+
for (let j = 0; j < suite.tests.length; j++) {
|
|
116
|
+
lines.push(``);
|
|
117
|
+
const test = suite.tests[j];
|
|
118
|
+
lines.push(`#### ${i + 1}.${j + 1}. ${test.name}`);
|
|
119
|
+
lines.push(``);
|
|
120
|
+
lines.push(`**File:** \`${test.file}\``);
|
|
121
|
+
lines.push(``);
|
|
122
|
+
lines.push(`**Steps:**`);
|
|
123
|
+
for (let k = 0; k < test.steps.length; k++) {
|
|
124
|
+
lines.push(` ${k + 1}. ${test.steps[k].perform ?? "-"}`);
|
|
125
|
+
for (const expect of test.steps[k].expect)
|
|
126
|
+
lines.push(` - expect: ${expect}`);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
lines.push(``);
|
|
131
|
+
await import_fs.default.promises.writeFile(import_path.default.resolve(context.rootPath, params.fileName), lines.join("\n"));
|
|
132
|
+
return {
|
|
133
|
+
content: [{
|
|
134
|
+
type: "text",
|
|
135
|
+
text: `Test plan saved to ${params.fileName}`
|
|
136
|
+
}]
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
});
|
|
140
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
141
|
+
0 && (module.exports = {
|
|
142
|
+
saveTestPlan,
|
|
143
|
+
setupPage,
|
|
144
|
+
submitTestPlan
|
|
145
|
+
});
|