Repository: microsoft/playwright
File: packages/playwright/src/program.ts (TypeScript)

Code before:
}

const kTraceModes: TraceMode[] = ['on', 'off', 'on-first-retry', 'on-all-retries', 'retain-on-failure', 'retain-on-first-failure'];

// Note: update docs/src/test-cli-js.md when you update this, program is the source of truth.

const testOptions: [string, { description: string, choices?: string[], preset?: string }][] = [
  /* 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', { description: `Run tests with Playwright Inspector. Shortcut for "PWDEBUG=1" environment variable and "--timeout=0 --max-failures=1 --headed --workers=1 --pause" options` }],
  ['--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` }],
  ['--pause', { description: `Pause at end of test execution` }],
  ['--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 ${builtInReporters.map(name => `"${name}"`).join(', ')} (default: "${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"` }],
  ['--shard-weights <weights>', { description: `Weights for each shard, colon-separated, for example "2:1:1" for 3 shards where the first shard should be allocated half of the work` }],
  ['--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: ${defaultTimeout})` }],
  ['--trace <mode>', { description: `Force tracing mode`, choices: kTraceModes as string[] }],
  ['--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);

Review comment (suggestion):
```suggestion
  ['--pause', { description: `Run tests in headed mode and pause at the end of test execution` }],
```

Code after:
}

const kTraceModes: TraceMode[] = ['on', 'off', 'on-first-retry', 'on-all-retries', 'retain-on-failure', 'retain-on-first-failure'];

// Note: update docs/src/test-cli-js.md when you update this, program is the source of truth.

const testOptions: [string, { description: string, choices?: string[], preset?: string }][] = [
  /* 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', { description: `Run tests with Playwright Inspector. Shortcut for "PWDEBUG=1" environment variable and "--timeout=0 --max-failures=1 --headed --workers=1 --pause" options` }],
  ['--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` }],
  ['--pause', { description: `Run tests in headed mode and pause at the end of test execution` }],
  ['--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 ${builtInReporters.map(name => `"${name}"`).join(', ')} (default: "${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"` }],
  ['--shard-weights <weights>', { description: `Weights for each shard, colon-separated, for example "2:1:1" for 3 shards where the first shard should be allocated half of the work` }],
  ['--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: ${defaultTimeout})` }],
  ['--trace <mode>', { description: `Force tracing mode`, choices: kTraceModes as string[] }],
  ['--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);