@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.
Files changed (181) hide show
  1. package/ThirdPartyNotices.txt +5042 -0
  2. package/cli.js +19 -0
  3. package/index.d.ts +17 -0
  4. package/index.js +17 -0
  5. package/index.mjs +18 -0
  6. package/jsx-runtime.js +42 -0
  7. package/jsx-runtime.mjs +21 -0
  8. package/lib/agents/agentParser.js +89 -0
  9. package/lib/agents/copilot-setup-steps.yml +34 -0
  10. package/lib/agents/generateAgents.js +348 -0
  11. package/lib/agents/playwright-test-coverage.prompt.md +31 -0
  12. package/lib/agents/playwright-test-generate.prompt.md +8 -0
  13. package/lib/agents/playwright-test-generator.agent.md +88 -0
  14. package/lib/agents/playwright-test-heal.prompt.md +6 -0
  15. package/lib/agents/playwright-test-healer.agent.md +55 -0
  16. package/lib/agents/playwright-test-plan.prompt.md +9 -0
  17. package/lib/agents/playwright-test-planner.agent.md +73 -0
  18. package/lib/common/config.js +282 -0
  19. package/lib/common/configLoader.js +344 -0
  20. package/lib/common/esmLoaderHost.js +104 -0
  21. package/lib/common/expectBundle.js +28 -0
  22. package/lib/common/expectBundleImpl.js +407 -0
  23. package/lib/common/fixtures.js +302 -0
  24. package/lib/common/globals.js +58 -0
  25. package/lib/common/ipc.js +60 -0
  26. package/lib/common/poolBuilder.js +85 -0
  27. package/lib/common/process.js +132 -0
  28. package/lib/common/suiteUtils.js +140 -0
  29. package/lib/common/test.js +321 -0
  30. package/lib/common/testLoader.js +101 -0
  31. package/lib/common/testType.js +298 -0
  32. package/lib/common/validators.js +68 -0
  33. package/lib/fsWatcher.js +67 -0
  34. package/lib/index.js +726 -0
  35. package/lib/internalsForTest.js +42 -0
  36. package/lib/isomorphic/events.js +77 -0
  37. package/lib/isomorphic/folders.js +30 -0
  38. package/lib/isomorphic/stringInternPool.js +69 -0
  39. package/lib/isomorphic/teleReceiver.js +521 -0
  40. package/lib/isomorphic/teleSuiteUpdater.js +157 -0
  41. package/lib/isomorphic/testServerConnection.js +225 -0
  42. package/lib/isomorphic/testServerInterface.js +16 -0
  43. package/lib/isomorphic/testTree.js +329 -0
  44. package/lib/isomorphic/types.d.js +16 -0
  45. package/lib/loader/loaderMain.js +59 -0
  46. package/lib/matchers/expect.js +311 -0
  47. package/lib/matchers/matcherHint.js +44 -0
  48. package/lib/matchers/matchers.js +383 -0
  49. package/lib/matchers/toBeTruthy.js +75 -0
  50. package/lib/matchers/toEqual.js +100 -0
  51. package/lib/matchers/toHaveURL.js +101 -0
  52. package/lib/matchers/toMatchAriaSnapshot.js +159 -0
  53. package/lib/matchers/toMatchSnapshot.js +342 -0
  54. package/lib/matchers/toMatchText.js +99 -0
  55. package/lib/mcp/browser/actions.d.js +16 -0
  56. package/lib/mcp/browser/browserContextFactory.js +329 -0
  57. package/lib/mcp/browser/browserServerBackend.js +84 -0
  58. package/lib/mcp/browser/config.js +421 -0
  59. package/lib/mcp/browser/context.js +244 -0
  60. package/lib/mcp/browser/response.js +278 -0
  61. package/lib/mcp/browser/sessionLog.js +75 -0
  62. package/lib/mcp/browser/tab.js +351 -0
  63. package/lib/mcp/browser/tools/common.js +65 -0
  64. package/lib/mcp/browser/tools/console.js +61 -0
  65. package/lib/mcp/browser/tools/dialogs.js +60 -0
  66. package/lib/mcp/browser/tools/evaluate.js +61 -0
  67. package/lib/mcp/browser/tools/files.js +58 -0
  68. package/lib/mcp/browser/tools/form.js +63 -0
  69. package/lib/mcp/browser/tools/install.js +72 -0
  70. package/lib/mcp/browser/tools/keyboard.js +144 -0
  71. package/lib/mcp/browser/tools/mouse.js +159 -0
  72. package/lib/mcp/browser/tools/navigate.js +136 -0
  73. package/lib/mcp/browser/tools/navigateAndWait.js +66 -0
  74. package/lib/mcp/browser/tools/network.js +78 -0
  75. package/lib/mcp/browser/tools/pdf.js +49 -0
  76. package/lib/mcp/browser/tools/runCode.js +78 -0
  77. package/lib/mcp/browser/tools/screenshot.js +93 -0
  78. package/lib/mcp/browser/tools/snapshot.js +205 -0
  79. package/lib/mcp/browser/tools/snapshotViewport.js +63 -0
  80. package/lib/mcp/browser/tools/tabs.js +67 -0
  81. package/lib/mcp/browser/tools/tool.js +47 -0
  82. package/lib/mcp/browser/tools/tracing.js +74 -0
  83. package/lib/mcp/browser/tools/utils.js +94 -0
  84. package/lib/mcp/browser/tools/verify.js +143 -0
  85. package/lib/mcp/browser/tools/wait.js +63 -0
  86. package/lib/mcp/browser/tools.js +82 -0
  87. package/lib/mcp/browser/watchdog.js +44 -0
  88. package/lib/mcp/config.d.js +16 -0
  89. package/lib/mcp/extension/cdpRelay.js +351 -0
  90. package/lib/mcp/extension/extensionContextFactory.js +76 -0
  91. package/lib/mcp/extension/protocol.js +28 -0
  92. package/lib/mcp/index.js +61 -0
  93. package/lib/mcp/log.js +35 -0
  94. package/lib/mcp/program.js +110 -0
  95. package/lib/mcp/sdk/exports.js +28 -0
  96. package/lib/mcp/sdk/http.js +152 -0
  97. package/lib/mcp/sdk/inProcessTransport.js +71 -0
  98. package/lib/mcp/sdk/server.js +223 -0
  99. package/lib/mcp/sdk/tool.js +47 -0
  100. package/lib/mcp/terminal/cli.js +296 -0
  101. package/lib/mcp/terminal/command.js +56 -0
  102. package/lib/mcp/terminal/commands.js +519 -0
  103. package/lib/mcp/terminal/daemon.js +135 -0
  104. package/lib/mcp/terminal/help.json +47 -0
  105. package/lib/mcp/terminal/helpGenerator.js +115 -0
  106. package/lib/mcp/terminal/socketConnection.js +80 -0
  107. package/lib/mcp/test/browserBackend.js +98 -0
  108. package/lib/mcp/test/generatorTools.js +122 -0
  109. package/lib/mcp/test/plannerTools.js +145 -0
  110. package/lib/mcp/test/seed.js +82 -0
  111. package/lib/mcp/test/streams.js +44 -0
  112. package/lib/mcp/test/testBackend.js +99 -0
  113. package/lib/mcp/test/testContext.js +285 -0
  114. package/lib/mcp/test/testTool.js +30 -0
  115. package/lib/mcp/test/testTools.js +108 -0
  116. package/lib/plugins/gitCommitInfoPlugin.js +198 -0
  117. package/lib/plugins/index.js +28 -0
  118. package/lib/plugins/webServerPlugin.js +237 -0
  119. package/lib/program.js +417 -0
  120. package/lib/reporters/base.js +634 -0
  121. package/lib/reporters/blob.js +138 -0
  122. package/lib/reporters/dot.js +99 -0
  123. package/lib/reporters/empty.js +32 -0
  124. package/lib/reporters/github.js +128 -0
  125. package/lib/reporters/html.js +633 -0
  126. package/lib/reporters/internalReporter.js +138 -0
  127. package/lib/reporters/json.js +254 -0
  128. package/lib/reporters/junit.js +232 -0
  129. package/lib/reporters/line.js +131 -0
  130. package/lib/reporters/list.js +253 -0
  131. package/lib/reporters/listModeReporter.js +69 -0
  132. package/lib/reporters/markdown.js +144 -0
  133. package/lib/reporters/merge.js +558 -0
  134. package/lib/reporters/multiplexer.js +112 -0
  135. package/lib/reporters/reporterV2.js +102 -0
  136. package/lib/reporters/teleEmitter.js +317 -0
  137. package/lib/reporters/versions/blobV1.js +16 -0
  138. package/lib/runner/dispatcher.js +530 -0
  139. package/lib/runner/failureTracker.js +72 -0
  140. package/lib/runner/lastRun.js +77 -0
  141. package/lib/runner/loadUtils.js +334 -0
  142. package/lib/runner/loaderHost.js +89 -0
  143. package/lib/runner/processHost.js +180 -0
  144. package/lib/runner/projectUtils.js +241 -0
  145. package/lib/runner/rebase.js +189 -0
  146. package/lib/runner/reporters.js +138 -0
  147. package/lib/runner/sigIntWatcher.js +96 -0
  148. package/lib/runner/storage.js +91 -0
  149. package/lib/runner/taskRunner.js +127 -0
  150. package/lib/runner/tasks.js +410 -0
  151. package/lib/runner/testGroups.js +125 -0
  152. package/lib/runner/testRunner.js +398 -0
  153. package/lib/runner/testServer.js +269 -0
  154. package/lib/runner/uiModeReporter.js +30 -0
  155. package/lib/runner/vcs.js +72 -0
  156. package/lib/runner/watchMode.js +396 -0
  157. package/lib/runner/workerHost.js +104 -0
  158. package/lib/third_party/pirates.js +62 -0
  159. package/lib/third_party/tsconfig-loader.js +103 -0
  160. package/lib/transform/babelBundle.js +46 -0
  161. package/lib/transform/babelBundleImpl.js +461 -0
  162. package/lib/transform/compilationCache.js +274 -0
  163. package/lib/transform/esmLoader.js +103 -0
  164. package/lib/transform/md.js +221 -0
  165. package/lib/transform/portTransport.js +67 -0
  166. package/lib/transform/transform.js +303 -0
  167. package/lib/util.js +400 -0
  168. package/lib/utilsBundle.js +50 -0
  169. package/lib/utilsBundleImpl.js +103 -0
  170. package/lib/worker/fixtureRunner.js +262 -0
  171. package/lib/worker/testInfo.js +536 -0
  172. package/lib/worker/testTracing.js +345 -0
  173. package/lib/worker/timeoutManager.js +174 -0
  174. package/lib/worker/util.js +31 -0
  175. package/lib/worker/workerMain.js +530 -0
  176. package/package.json +72 -0
  177. package/test.d.ts +18 -0
  178. package/test.js +24 -0
  179. package/test.mjs +34 -0
  180. package/types/test.d.ts +10251 -0
  181. package/types/testReporter.d.ts +822 -0
package/lib/program.js ADDED
@@ -0,0 +1,417 @@
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 program_exports = {};
30
+ __export(program_exports, {
31
+ program: () => import_program2.program
32
+ });
33
+ module.exports = __toCommonJS(program_exports);
34
+ var import_fs = __toESM(require("fs"));
35
+ var import_path = __toESM(require("path"));
36
+ var import_program = require("playwright-core/lib/cli/program");
37
+ var import_utils = require("playwright-core/lib/utils");
38
+ var import_config = require("./common/config");
39
+ var import_configLoader = require("./common/configLoader");
40
+ var import_program2 = require("playwright-core/lib/cli/program");
41
+ var import_base = require("./reporters/base");
42
+ var import_html = require("./reporters/html");
43
+ var import_merge = require("./reporters/merge");
44
+ var import_projectUtils = require("./runner/projectUtils");
45
+ var testServer = __toESM(require("./runner/testServer"));
46
+ var import_watchMode = require("./runner/watchMode");
47
+ var import_testRunner = require("./runner/testRunner");
48
+ var import_reporters = require("./runner/reporters");
49
+ var mcp = __toESM(require("./mcp/sdk/exports"));
50
+ var import_testBackend = require("./mcp/test/testBackend");
51
+ var import_program3 = require("./mcp/program");
52
+ var import_watchdog = require("./mcp/browser/watchdog");
53
+ var import_generateAgents = require("./agents/generateAgents");
54
+ const packageJSON = require("../package.json");
55
+ function addTestCommand(program3) {
56
+ const command = program3.command("test [test-filter...]");
57
+ command.description("run tests with Playwright Test");
58
+ const options = testOptions.sort((a, b) => a[0].replace(/-/g, "").localeCompare(b[0].replace(/-/g, "")));
59
+ options.forEach(([name, { description, choices, preset }]) => {
60
+ const option = command.createOption(name, description);
61
+ if (choices)
62
+ option.choices(choices);
63
+ if (preset)
64
+ option.preset(preset);
65
+ command.addOption(option);
66
+ return command;
67
+ });
68
+ command.action(async (args, opts) => {
69
+ try {
70
+ await runTests(args, opts);
71
+ } catch (e) {
72
+ console.error(e);
73
+ (0, import_utils.gracefullyProcessExitDoNotHang)(1);
74
+ }
75
+ });
76
+ command.addHelpText("afterAll", `
77
+ Arguments [test-filter...]:
78
+ Pass arguments to filter test files. Each argument is treated as a regular expression. Matching is performed against the absolute file paths.
79
+
80
+ Examples:
81
+ $ npx playwright test my.spec.ts
82
+ $ npx playwright test some.spec.ts:42
83
+ $ npx playwright test --headed
84
+ $ npx playwright test --project=webkit`);
85
+ }
86
+ function addClearCacheCommand(program3) {
87
+ const command = program3.command("clear-cache");
88
+ command.description("clears build and test caches");
89
+ command.option("-c, --config <file>", `Configuration file, or a test directory with optional "playwright.config.{m,c}?{js,ts}"`);
90
+ command.action(async (opts) => {
91
+ const runner = new import_testRunner.TestRunner((0, import_configLoader.resolveConfigLocation)(opts.config), {});
92
+ const { status } = await runner.clearCache((0, import_reporters.createErrorCollectingReporter)(import_base.terminalScreen));
93
+ const exitCode = status === "interrupted" ? 130 : status === "passed" ? 0 : 1;
94
+ (0, import_utils.gracefullyProcessExitDoNotHang)(exitCode);
95
+ });
96
+ }
97
+ function addDevServerCommand(program3) {
98
+ const command = program3.command("dev-server", { hidden: true });
99
+ command.description("start dev server");
100
+ command.option("-c, --config <file>", `Configuration file, or a test directory with optional "playwright.config.{m,c}?{js,ts}"`);
101
+ command.action(async (options) => {
102
+ const runner = new import_testRunner.TestRunner((0, import_configLoader.resolveConfigLocation)(options.config), {});
103
+ await runner.startDevServer((0, import_reporters.createErrorCollectingReporter)(import_base.terminalScreen), "in-process");
104
+ });
105
+ }
106
+ function addTestServerCommand(program3) {
107
+ const command = program3.command("test-server", { hidden: true });
108
+ command.description("start test server");
109
+ command.option("-c, --config <file>", `Configuration file, or a test directory with optional "playwright.config.{m,c}?{js,ts}"`);
110
+ command.option("--host <host>", "Host to start the server on", "localhost");
111
+ command.option("--port <port>", "Port to start the server on", "0");
112
+ command.action((opts) => runTestServer(opts));
113
+ }
114
+ function addShowReportCommand(program3) {
115
+ const command = program3.command("show-report [report]");
116
+ command.description("show HTML report");
117
+ command.action((report, options) => (0, import_html.showHTMLReport)(report, options.host, +options.port));
118
+ command.option("--host <host>", "Host to serve report on", "localhost");
119
+ command.option("--port <port>", "Port to serve report on", "9323");
120
+ command.addHelpText("afterAll", `
121
+ Arguments [report]:
122
+ When specified, opens given report, otherwise opens last generated report.
123
+
124
+ Examples:
125
+ $ npx playwright show-report
126
+ $ npx playwright show-report playwright-report`);
127
+ }
128
+ function addMergeReportsCommand(program3) {
129
+ const command = program3.command("merge-reports [dir]");
130
+ command.description("merge multiple blob reports (for sharded tests) into a single report");
131
+ command.action(async (dir, options) => {
132
+ try {
133
+ await mergeReports(dir, options);
134
+ } catch (e) {
135
+ console.error(e);
136
+ (0, import_utils.gracefullyProcessExitDoNotHang)(1);
137
+ }
138
+ });
139
+ command.option("-c, --config <file>", `Configuration file. Can be used to specify additional configuration for the output report.`);
140
+ command.option("--reporter <reporter>", `Reporter to use, comma-separated, can be ${import_config.builtInReporters.map((name) => `"${name}"`).join(", ")} (default: "${import_config.defaultReporter}")`);
141
+ command.addHelpText("afterAll", `
142
+ Arguments [dir]:
143
+ Directory containing blob reports.
144
+
145
+ Examples:
146
+ $ npx playwright merge-reports playwright-report`);
147
+ }
148
+ function addBrowserMCPServerCommand(program3) {
149
+ const command = program3.command("run-mcp-server", { hidden: true });
150
+ command.description("Interact with the browser over MCP");
151
+ (0, import_program3.decorateCommand)(command, packageJSON.version);
152
+ }
153
+ function addTestMCPServerCommand(program3) {
154
+ const command = program3.command("run-test-mcp-server", { hidden: true });
155
+ command.description("Interact with the test runner over MCP");
156
+ command.option("--headless", "run browser in headless mode, headed by default");
157
+ command.option("-c, --config <file>", `Configuration file, or a test directory with optional "playwright.config.{m,c}?{js,ts}"`);
158
+ command.option("--host <host>", "host to bind server to. Default is localhost. Use 0.0.0.0 to bind to all interfaces.");
159
+ command.option("--port <port>", "port to listen on for SSE transport.");
160
+ command.action(async (options) => {
161
+ (0, import_watchdog.setupExitWatchdog)();
162
+ const factory = {
163
+ name: "Playwright Test Runner",
164
+ nameInConfig: "playwright-test-runner",
165
+ version: packageJSON.version,
166
+ create: () => new import_testBackend.TestServerBackend(options.config, { muteConsole: options.port === void 0, headless: options.headless })
167
+ };
168
+ await mcp.start(factory, { port: options.port === void 0 ? void 0 : +options.port, host: options.host });
169
+ });
170
+ }
171
+ function addInitAgentsCommand(program3) {
172
+ const command = program3.command("init-agents");
173
+ command.description("Initialize repository agents");
174
+ const option = command.createOption("--loop <loop>", "Agentic loop provider");
175
+ option.choices(["claude", "copilot", "opencode", "vscode", "vscode-legacy"]);
176
+ command.addOption(option);
177
+ command.option("-c, --config <file>", `Configuration file to find a project to use for seed test`);
178
+ command.option("--project <project>", "Project to use for seed test");
179
+ command.option("--prompts", "Whether to include prompts in the agent initialization");
180
+ command.action(async (opts) => {
181
+ const config = await (0, import_configLoader.loadConfigFromFile)(opts.config);
182
+ if (opts.loop === "opencode") {
183
+ await import_generateAgents.OpencodeGenerator.init(config, opts.project, opts.prompts);
184
+ } else if (opts.loop === "vscode-legacy") {
185
+ await import_generateAgents.VSCodeGenerator.init(config, opts.project);
186
+ } else if (opts.loop === "claude") {
187
+ await import_generateAgents.ClaudeGenerator.init(config, opts.project, opts.prompts);
188
+ } else {
189
+ await import_generateAgents.CopilotGenerator.init(config, opts.project, opts.prompts);
190
+ return;
191
+ }
192
+ });
193
+ }
194
+ async function runTests(args, opts) {
195
+ await (0, import_utils.startProfiling)();
196
+ const cliOverrides = overridesFromOptions(opts);
197
+ const config = await (0, import_configLoader.loadConfigFromFile)(opts.config, cliOverrides, opts.deps === false);
198
+ config.cliArgs = args;
199
+ config.cliGrep = opts.grep;
200
+ config.cliOnlyChanged = opts.onlyChanged === true ? "HEAD" : opts.onlyChanged;
201
+ config.cliGrepInvert = opts.grepInvert;
202
+ config.cliListOnly = !!opts.list;
203
+ config.cliProjectFilter = opts.project || void 0;
204
+ config.cliPassWithNoTests = !!opts.passWithNoTests;
205
+ config.cliLastFailed = !!opts.lastFailed;
206
+ config.cliTestList = opts.testList ? import_path.default.resolve(process.cwd(), opts.testList) : void 0;
207
+ config.cliTestListInvert = opts.testListInvert ? import_path.default.resolve(process.cwd(), opts.testListInvert) : void 0;
208
+ (0, import_projectUtils.filterProjects)(config.projects, config.cliProjectFilter);
209
+ if (opts.ui || opts.uiHost || opts.uiPort) {
210
+ if (opts.onlyChanged)
211
+ throw new Error(`--only-changed is not supported in UI mode. If you'd like that to change, see https://github.com/microsoft/playwright/issues/15075 for more details.`);
212
+ const status2 = await testServer.runUIMode(opts.config, cliOverrides, {
213
+ host: opts.uiHost,
214
+ port: opts.uiPort ? +opts.uiPort : void 0,
215
+ args,
216
+ grep: opts.grep,
217
+ grepInvert: opts.grepInvert,
218
+ project: opts.project || void 0,
219
+ reporter: Array.isArray(opts.reporter) ? opts.reporter : opts.reporter ? [opts.reporter] : void 0
220
+ });
221
+ await (0, import_utils.stopProfiling)("runner");
222
+ const exitCode2 = status2 === "interrupted" ? 130 : status2 === "passed" ? 0 : 1;
223
+ (0, import_utils.gracefullyProcessExitDoNotHang)(exitCode2);
224
+ return;
225
+ }
226
+ if (process.env.PWTEST_WATCH) {
227
+ if (opts.onlyChanged)
228
+ throw new Error(`--only-changed is not supported in watch mode. If you'd like that to change, file an issue and let us know about your usecase for it.`);
229
+ const status2 = await (0, import_watchMode.runWatchModeLoop)(
230
+ (0, import_configLoader.resolveConfigLocation)(opts.config),
231
+ {
232
+ projects: opts.project,
233
+ files: args,
234
+ grep: opts.grep
235
+ }
236
+ );
237
+ await (0, import_utils.stopProfiling)("runner");
238
+ const exitCode2 = status2 === "interrupted" ? 130 : status2 === "passed" ? 0 : 1;
239
+ (0, import_utils.gracefullyProcessExitDoNotHang)(exitCode2);
240
+ return;
241
+ }
242
+ const status = await (0, import_testRunner.runAllTestsWithConfig)(config);
243
+ await (0, import_utils.stopProfiling)("runner");
244
+ const exitCode = status === "interrupted" ? 130 : status === "passed" ? 0 : 1;
245
+ (0, import_utils.gracefullyProcessExitDoNotHang)(exitCode);
246
+ }
247
+ async function runTestServer(opts) {
248
+ const host = opts.host;
249
+ const port = opts.port ? +opts.port : void 0;
250
+ const status = await testServer.runTestServer(opts.config, {}, { host, port });
251
+ const exitCode = status === "interrupted" ? 130 : status === "passed" ? 0 : 1;
252
+ (0, import_utils.gracefullyProcessExitDoNotHang)(exitCode);
253
+ }
254
+ async function mergeReports(reportDir, opts) {
255
+ const configFile = opts.config;
256
+ const config = configFile ? await (0, import_configLoader.loadConfigFromFile)(configFile) : await (0, import_configLoader.loadEmptyConfigForMergeReports)();
257
+ const dir = import_path.default.resolve(process.cwd(), reportDir || "");
258
+ const dirStat = await import_fs.default.promises.stat(dir).catch((e) => null);
259
+ if (!dirStat)
260
+ throw new Error("Directory does not exist: " + dir);
261
+ if (!dirStat.isDirectory())
262
+ throw new Error(`"${dir}" is not a directory`);
263
+ let reporterDescriptions = resolveReporterOption(opts.reporter);
264
+ if (!reporterDescriptions && configFile)
265
+ reporterDescriptions = config.config.reporter;
266
+ if (!reporterDescriptions)
267
+ reporterDescriptions = [[import_config.defaultReporter]];
268
+ const rootDirOverride = configFile ? config.config.rootDir : void 0;
269
+ await (0, import_merge.createMergedReport)(config, dir, reporterDescriptions, rootDirOverride);
270
+ (0, import_utils.gracefullyProcessExitDoNotHang)(0);
271
+ }
272
+ function overridesFromOptions(options) {
273
+ const overrides = {
274
+ failOnFlakyTests: options.failOnFlakyTests ? true : void 0,
275
+ forbidOnly: options.forbidOnly ? true : void 0,
276
+ fullyParallel: options.fullyParallel ? true : void 0,
277
+ globalTimeout: options.globalTimeout ? parseInt(options.globalTimeout, 10) : void 0,
278
+ maxFailures: options.x ? 1 : options.maxFailures ? parseInt(options.maxFailures, 10) : void 0,
279
+ outputDir: options.output ? import_path.default.resolve(process.cwd(), options.output) : void 0,
280
+ quiet: options.quiet ? options.quiet : void 0,
281
+ repeatEach: options.repeatEach ? parseInt(options.repeatEach, 10) : void 0,
282
+ retries: options.retries ? parseInt(options.retries, 10) : void 0,
283
+ reporter: resolveReporterOption(options.reporter),
284
+ shard: resolveShardOption(options.shard),
285
+ shardWeights: resolveShardWeightsOption(),
286
+ timeout: options.timeout ? parseInt(options.timeout, 10) : void 0,
287
+ tsconfig: options.tsconfig ? import_path.default.resolve(process.cwd(), options.tsconfig) : void 0,
288
+ ignoreSnapshots: options.ignoreSnapshots ? !!options.ignoreSnapshots : void 0,
289
+ updateSnapshots: options.updateSnapshots,
290
+ updateSourceMethod: options.updateSourceMethod,
291
+ runAgents: options.runAgents,
292
+ workers: options.workers,
293
+ pause: process.env.PWPAUSE ? true : void 0
294
+ };
295
+ if (options.browser) {
296
+ const browserOpt = options.browser.toLowerCase();
297
+ if (!["all", "chromium", "firefox", "webkit"].includes(browserOpt))
298
+ throw new Error(`Unsupported browser "${options.browser}", must be one of "all", "chromium", "firefox" or "webkit"`);
299
+ const browserNames = browserOpt === "all" ? ["chromium", "firefox", "webkit"] : [browserOpt];
300
+ overrides.projects = browserNames.map((browserName) => {
301
+ return {
302
+ name: browserName,
303
+ use: { browserName }
304
+ };
305
+ });
306
+ }
307
+ if (options.headed || options.debug || overrides.pause)
308
+ overrides.use = { headless: false };
309
+ if (!options.ui && options.debug) {
310
+ overrides.debug = true;
311
+ process.env.PWDEBUG = "1";
312
+ }
313
+ if (!options.ui && options.trace) {
314
+ overrides.use = overrides.use || {};
315
+ overrides.use.trace = options.trace;
316
+ }
317
+ if (overrides.tsconfig && !import_fs.default.existsSync(overrides.tsconfig))
318
+ throw new Error(`--tsconfig "${options.tsconfig}" does not exist`);
319
+ return overrides;
320
+ }
321
+ function resolveReporterOption(reporter) {
322
+ if (!reporter || !reporter.length)
323
+ return void 0;
324
+ return reporter.split(",").map((r) => [resolveReporter(r)]);
325
+ }
326
+ function resolveShardOption(shard) {
327
+ if (!shard)
328
+ return void 0;
329
+ const shardPair = shard.split("/");
330
+ if (shardPair.length !== 2) {
331
+ throw new Error(
332
+ `--shard "${shard}", expected format is "current/all", 1-based, for example "3/5".`
333
+ );
334
+ }
335
+ const current = parseInt(shardPair[0], 10);
336
+ const total = parseInt(shardPair[1], 10);
337
+ if (isNaN(total) || total < 1)
338
+ throw new Error(`--shard "${shard}" total must be a positive number`);
339
+ if (isNaN(current) || current < 1 || current > total) {
340
+ throw new Error(
341
+ `--shard "${shard}" current must be a positive number, not greater than shard total`
342
+ );
343
+ }
344
+ return { current, total };
345
+ }
346
+ function resolveShardWeightsOption() {
347
+ const shardWeights = process.env.PWTEST_SHARD_WEIGHTS;
348
+ if (!shardWeights)
349
+ return void 0;
350
+ return shardWeights.split(":").map((w) => {
351
+ const weight = parseInt(w, 10);
352
+ if (isNaN(weight) || weight < 0)
353
+ throw new Error(`PWTEST_SHARD_WEIGHTS="${shardWeights}" weights must be non-negative numbers`);
354
+ return weight;
355
+ });
356
+ }
357
+ function resolveReporter(id) {
358
+ if (import_config.builtInReporters.includes(id))
359
+ return id;
360
+ const localPath = import_path.default.resolve(process.cwd(), id);
361
+ if (import_fs.default.existsSync(localPath))
362
+ return localPath;
363
+ return require.resolve(id, { paths: [process.cwd()] });
364
+ }
365
+ const kTraceModes = ["on", "off", "on-first-retry", "on-all-retries", "retain-on-failure", "retain-on-first-failure"];
366
+ const testOptions = [
367
+ /* deprecated */
368
+ ["--browser <browser>", { description: `Browser to use for tests, one of "all", "chromium", "firefox" or "webkit" (default: "chromium")` }],
369
+ ["-c, --config <file>", { description: `Configuration file, or a test directory with optional "playwright.config.{m,c}?{js,ts}"` }],
370
+ ["--debug", { description: `Run tests with Playwright Inspector. Shortcut for "PWDEBUG=1" environment variable and "--timeout=0 --max-failures=1 --headed --workers=1" options` }],
371
+ ["--fail-on-flaky-tests", { description: `Fail if any test is flagged as flaky (default: false)` }],
372
+ ["--forbid-only", { description: `Fail if test.only is called (default: false)` }],
373
+ ["--fully-parallel", { description: `Run all tests in parallel (default: false)` }],
374
+ ["--global-timeout <timeout>", { description: `Maximum time this test suite can run in milliseconds (default: unlimited)` }],
375
+ ["-g, --grep <grep>", { description: `Only run tests matching this regular expression (default: ".*")` }],
376
+ ["--grep-invert <grep>", { description: `Only run tests that do not match this regular expression` }],
377
+ ["--headed", { description: `Run tests in headed browsers (default: headless)` }],
378
+ ["--ignore-snapshots", { description: `Ignore screenshot and snapshot expectations` }],
379
+ ["--last-failed", { description: `Only re-run the failures` }],
380
+ ["--list", { description: `Collect all the tests and report them, but do not run` }],
381
+ ["--max-failures <N>", { description: `Stop after the first N failures` }],
382
+ ["--no-deps", { description: `Do not run project dependencies` }],
383
+ ["--output <dir>", { description: `Folder for output artifacts (default: "test-results")` }],
384
+ ["--only-changed [ref]", { description: `Only run test files that have been changed between 'HEAD' and 'ref'. Defaults to running all uncommitted changes. Only supports Git.` }],
385
+ ["--pass-with-no-tests", { description: `Makes test run succeed even if no tests were found` }],
386
+ ["--project <project-name...>", { description: `Only run tests from the specified list of projects, supports '*' wildcard (default: run all projects)` }],
387
+ ["--quiet", { description: `Suppress stdio` }],
388
+ ["--repeat-each <N>", { description: `Run each test N times (default: 1)` }],
389
+ ["--reporter <reporter>", { description: `Reporter to use, comma-separated, can be ${import_config.builtInReporters.map((name) => `"${name}"`).join(", ")} (default: "${import_config.defaultReporter}")` }],
390
+ ["--retries <retries>", { description: `Maximum retry count for flaky tests, zero for no retries (default: no retries)` }],
391
+ ["--shard <shard>", { description: `Shard tests and execute only the selected shard, specify in the form "current/all", 1-based, for example "3/5"` }],
392
+ ["--test-list <file>", { description: `Path to a file containing a list of tests to run. See https://playwright.dev/docs/test-cli for more details.` }],
393
+ ["--test-list-invert <file>", { description: `Path to a file containing a list of tests to skip. See https://playwright.dev/docs/test-cli for more details.` }],
394
+ ["--timeout <timeout>", { description: `Specify test timeout threshold in milliseconds, zero for unlimited (default: ${import_config.defaultTimeout})` }],
395
+ ["--trace <mode>", { description: `Force tracing mode`, choices: kTraceModes }],
396
+ ["--tsconfig <path>", { description: `Path to a single tsconfig applicable to all imported files (default: look up tsconfig for each imported file separately)` }],
397
+ ["--ui", { description: `Run tests in interactive UI mode` }],
398
+ ["--ui-host <host>", { description: `Host to serve UI on; specifying this option opens UI in a browser tab` }],
399
+ ["--ui-port <port>", { description: `Port to serve UI on, 0 for any free port; specifying this option opens UI in a browser tab` }],
400
+ ["-u, --update-snapshots [mode]", { description: `Update snapshots with actual results. Running tests without the flag defaults to "missing"`, choices: ["all", "changed", "missing", "none"], preset: "changed" }],
401
+ ["--update-source-method <method>", { description: `Chooses the way source is updated (default: "patch")`, choices: ["overwrite", "3way", "patch"] }],
402
+ ["-j, --workers <workers>", { description: `Number of concurrent workers or percentage of logical CPU cores, use 1 to run in a single worker (default: 50%)` }],
403
+ ["-x", { description: `Stop after the first failure` }]
404
+ ];
405
+ addTestCommand(import_program.program);
406
+ addShowReportCommand(import_program.program);
407
+ addMergeReportsCommand(import_program.program);
408
+ addClearCacheCommand(import_program.program);
409
+ addBrowserMCPServerCommand(import_program.program);
410
+ addTestMCPServerCommand(import_program.program);
411
+ addDevServerCommand(import_program.program);
412
+ addTestServerCommand(import_program.program);
413
+ addInitAgentsCommand(import_program.program);
414
+ // Annotate the CommonJS export names for ESM import in node:
415
+ 0 && (module.exports = {
416
+ program
417
+ });