File size: 12,979 Bytes
92319bf
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
"use strict";
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
  for (var name in all)
    __defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
  if (from && typeof from === "object" || typeof from === "function") {
    for (let key of __getOwnPropNames(from))
      if (!__hasOwnProp.call(to, key) && key !== except)
        __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
  }
  return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var program_exports = {};
__export(program_exports, {
  program: () => program
});
module.exports = __toCommonJS(program_exports);
var import_bootstrap = require("playwright-core/lib/bootstrap");
var import_coreBundle = require("playwright-core/lib/coreBundle");
var import_common = require("./common");
var import_testActions = require("./cli/testActions");
var import_reportActions = require("./cli/reportActions");
var import_testBackend = require("./mcp/test/testBackend");
var import_generateAgents = require("./agents/generateAgents");
var import_package = require("./package");
const { program } = require("playwright-core/lib/utilsBundle");
const { gracefullyProcessExitDoNotHang } = require("playwright-core/lib/coreBundle").utils;
import_coreBundle.libCli.decorateProgram(program);
function addTestCommand(program2) {
  const command = program2.command("test [test-filter...]");
  command.description("run tests with Playwright Test");
  const options = testOptions.sort((a, b) => a[0].replace(/-/g, "").localeCompare(b[0].replace(/-/g, "")));
  options.forEach(([name, { description, choices, preset }]) => {
    const option = command.createOption(name, description);
    if (choices)
      option.choices(choices);
    if (preset)
      option.preset(preset);
    command.addOption(option);
    return command;
  });
  command.action(async (args, opts) => {
    try {
      await (0, import_testActions.runTests)(args, opts);
    } catch (e) {
      console.error(e);
      gracefullyProcessExitDoNotHang(1);
    }
  });
  command.addHelpText("afterAll", `
Arguments [test-filter...]:
  Pass arguments to filter test files. Each argument is treated as a regular expression. Matching is performed against the absolute file paths.

Examples:
  $ npx playwright test my.spec.ts
  $ npx playwright test some.spec.ts:42
  $ npx playwright test --headed
  $ npx playwright test --project=webkit`);
}
function addClearCacheCommand(program2) {
  const command = program2.command("clear-cache");
  command.description("clears build and test caches");
  command.option("-c, --config <file>", `Configuration file, or a test directory with optional "playwright.config.{m,c}?{js,ts}"`);
  command.action(async (opts) => {
    await (0, import_testActions.clearCache)(opts);
  });
}
function addTestServerCommand(program2) {
  const command = program2.command("test-server", { hidden: true });
  command.description("start test server");
  command.option("-c, --config <file>", `Configuration file, or a test directory with optional "playwright.config.{m,c}?{js,ts}"`);
  command.option("--host <host>", "Host to start the server on", "localhost");
  command.option("--port <port>", "Port to start the server on", "0");
  command.action(async (opts) => {
    await (0, import_testActions.runTestServerAction)(opts);
  });
}
function addShowReportCommand(program2) {
  const command = program2.command("show-report [report]");
  command.description("show HTML report");
  command.action(async (report, options) => {
    await (0, import_reportActions.showReport)(report, options.host, +options.port);
  });
  command.option("--host <host>", "Host to serve report on", "localhost");
  command.option("--port <port>", "Port to serve report on", "9323");
  command.addHelpText("afterAll", `
Arguments [report]:
  When specified, opens given report, otherwise opens last generated report.
  Accepts a directory or a .zip archive whose top-level entry is "index.html" (e.g. one downloaded from a CI artifact).

Examples:
  $ npx playwright show-report
  $ npx playwright show-report playwright-report
  $ npx playwright show-report playwright-report.zip`);
}
function addMergeReportsCommand(program2) {
  const command = program2.command("merge-reports [dir]");
  command.description("merge multiple blob reports (for sharded tests) into a single report");
  command.action(async (dir, options) => {
    try {
      await (0, import_reportActions.mergeReports)(dir, options);
    } catch (e) {
      console.error(e);
      gracefullyProcessExitDoNotHang(1);
    }
  });
  command.option("-c, --config <file>", `Configuration file. Can be used to specify additional configuration for the output report.`);
  command.option("--reporter <reporter>", `Reporter to use, comma-separated, can be ${import_common.builtInReporters.map((name) => `"${name}"`).join(", ")} (default: "${import_common.config.defaultReporter}")`);
  command.addHelpText("afterAll", `
Arguments [dir]:
  Directory containing blob reports.

Examples:
  $ npx playwright merge-reports playwright-report`);
}
function addTestMCPServerCommand(program2) {
  const command = program2.command("run-test-mcp-server", { hidden: true });
  command.description("Interact with the test runner over MCP");
  command.option("--headless", "run browser in headless mode, headed by default");
  command.option("-c, --config <file>", `Configuration file, or a test directory with optional "playwright.config.{m,c}?{js,ts}"`);
  command.option("--host <host>", "host to bind server to. Default is localhost. Use 0.0.0.0 to bind to all interfaces.");
  command.option("--port <port>", "port to listen on for SSE transport.");
  command.action(async (options) => {
    import_coreBundle.tools.setupExitWatchdog();
    const factory = {
      name: "Playwright Test Runner",
      nameInConfig: "playwright-test-runner",
      version: import_package.packageJSON.version,
      toolSchemas: import_testBackend.testServerBackendTools.map((tool) => tool.schema),
      create: async () => new import_testBackend.TestServerBackend(options.config, { muteConsole: options.port === void 0, headless: options.headless }),
      disposed: async () => {
      }
    };
    await import_coreBundle.tools.start(factory, { port: options.port === void 0 ? void 0 : +options.port, host: options.host });
  });
}
function addInitAgentsCommand(program2) {
  const command = program2.command("init-agents");
  command.description("Initialize repository agents");
  const option = command.createOption("--loop <loop>", "Agentic loop provider");
  option.choices(["claude", "copilot", "opencode", "vscode", "vscode-legacy"]);
  command.addOption(option);
  command.option("-c, --config <file>", `Configuration file to find a project to use for seed test`);
  command.option("--project <project>", "Project to use for seed test");
  command.option("--prompts", "Whether to include prompts in the agent initialization");
  command.action(async (opts) => {
    const loadedConfig = await import_common.configLoader.loadConfigFromFile(opts.config);
    if (opts.loop === "opencode") {
      await import_generateAgents.OpencodeGenerator.init(loadedConfig, opts.project, opts.prompts);
    } else if (opts.loop === "vscode-legacy") {
      await import_generateAgents.VSCodeGenerator.init(loadedConfig, opts.project);
    } else if (opts.loop === "claude") {
      await import_generateAgents.ClaudeGenerator.init(loadedConfig, opts.project, opts.prompts);
    } else {
      await import_generateAgents.CopilotGenerator.init(loadedConfig, opts.project, opts.prompts);
      return;
    }
  });
}
const kTraceModes = ["on", "off", "on-first-retry", "on-all-retries", "retain-on-failure", "retain-on-first-failure", "retain-on-failure-and-retries"];
const testOptions = [
  /* deprecated */
  ["--browser <browser>", { description: `Browser to use for tests, one of "all", "chromium", "firefox" or "webkit" (default: "chromium")` }],
  ["-c, --config <file>", { description: `Configuration file, or a test directory with optional "playwright.config.{m,c}?{js,ts}"` }],
  ["--debug [mode]", { description: `Run tests with Playwright Inspector. Shortcut for "PWDEBUG=1" environment variable and "--timeout=0 --max-failures=1 --headed --workers=1" options`, choices: ["inspector", "cli"], preset: "inspector" }],
  ["--fail-on-flaky-tests", { description: `Fail if any test is flagged as flaky (default: false)` }],
  ["--forbid-only", { description: `Fail if test.only is called (default: false)` }],
  ["--fully-parallel", { description: `Run all tests in parallel (default: false)` }],
  ["--global-timeout <timeout>", { description: `Maximum time this test suite can run in milliseconds (default: unlimited)` }],
  ["-g, --grep <grep>", { description: `Only run tests matching this regular expression (default: ".*")` }],
  ["--grep-invert <grep>", { description: `Only run tests that do not match this regular expression` }],
  ["--headed", { description: `Run tests in headed browsers (default: headless)` }],
  ["--ignore-snapshots", { description: `Ignore screenshot and snapshot expectations` }],
  ["--last-failed", { description: `Only re-run the failures` }],
  ["--list", { description: `Collect all the tests and report them, but do not run` }],
  ["--max-failures <N>", { description: `Stop after the first N failures` }],
  ["--no-deps", { description: `Do not run project dependencies` }],
  ["--output <dir>", { description: `Folder for output artifacts (default: "test-results")` }],
  ["--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.` }],
  ["--pass-with-no-tests", { description: `Makes test run succeed even if no tests were found` }],
  ["--project <project-name...>", { description: `Only run tests from the specified list of projects, supports '*' wildcard (default: run all projects)` }],
  ["--quiet", { description: `Suppress stdio` }],
  ["--repeat-each <N>", { description: `Run each test N times (default: 1)` }],
  ["--reporter <reporter>", { description: `Reporter to use, comma-separated, can be ${import_common.builtInReporters.map((name) => `"${name}"`).join(", ")} (default: "${import_common.config.defaultReporter}")` }],
  ["--retries <retries>", { description: `Maximum retry count for flaky tests, zero for no retries (default: no retries)` }],
  ["--run-agents <mode>", { description: `Run agents to generate the code for page.perform`, choices: ["missing", "all", "none"], preset: "none" }],
  ["--shard <shard>", { description: `Shard tests and execute only the selected shard, specify in the form "current/all", 1-based, for example "3/5"` }],
  ["--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.` }],
  ["--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.` }],
  ["--timeout <timeout>", { description: `Specify test timeout threshold in milliseconds, zero for unlimited (default: ${import_common.config.defaultTimeout})` }],
  ["--trace <mode>", { description: `Force tracing mode`, choices: kTraceModes }],
  ["--tsconfig <path>", { description: `Path to a single tsconfig applicable to all imported files (default: look up tsconfig for each imported file separately)` }],
  ["--ui", { description: `Run tests in interactive UI mode` }],
  ["--ui-host <host>", { description: `Host to serve UI on; specifying this option opens UI in a browser tab` }],
  ["--ui-port <port>", { description: `Port to serve UI on, 0 for any free port; specifying this option opens UI in a browser tab` }],
  ["-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" }],
  ["--update-source-method <method>", { description: `Chooses the way source is updated (default: "patch")`, choices: ["overwrite", "3way", "patch"] }],
  ["-j, --workers <workers>", { description: `Number of concurrent workers or percentage of logical CPU cores, use 1 to run in a single worker (default: 50%)` }],
  ["-x", { description: `Stop after the first failure` }]
];
addTestCommand(program);
addShowReportCommand(program);
addMergeReportsCommand(program);
addClearCacheCommand(program);
addTestMCPServerCommand(program);
addTestServerCommand(program);
addInitAgentsCommand(program);
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
  program
});