diff --git a/packages/core/src/cli/commands.ts b/packages/core/src/cli/commands.ts index aa4056717..303a8cdd9 100644 --- a/packages/core/src/cli/commands.ts +++ b/packages/core/src/cli/commands.ts @@ -1,4 +1,4 @@ -import cac, { type CAC } from 'cac'; +import cac, { type CAC, type Command } from 'cac'; import { normalize } from 'pathe'; import type { ListCommandOptions, @@ -11,124 +11,190 @@ import { showRstest } from './prepare'; export type { CommonOptions } from './init'; -const applyCommonOptions = (cli: CAC) => { - cli - .option( - '-c, --config ', - 'Specify the configuration file, can be a relative or absolute path', - ) - .option( - '--config-loader ', - 'Specify the loader to load the config file (auto | jiti | native)', - { - default: 'auto', - }, - ) - .option( - '-r, --root ', - 'Specify the project root directory, can be an absolute path or a path relative to cwd', - ) - .option('--globals', 'Provide global APIs') - .option('--isolate', 'Run tests in an isolated environment') - .option('--include ', 'Match test files') - .option('--exclude ', 'Exclude files from test') - .option('-u, --update', 'Update snapshot files') - .option('--coverage', 'Enable code coverage collection') - .option( - '--project ', - 'Run only projects that match the name, can be a full name or wildcards pattern', - ) - .option( - '--passWithNoTests', - 'Allows the test suite to pass when no files are found', - ) - .option( - '--printConsoleTrace', - 'Print console traces when calling any console method', - ) - .option('--disableConsoleIntercept', 'Disable console intercept') - .option('--logHeapUsage', 'Log heap usage after each test') - .option( - '--slowTestThreshold ', - 'The number of milliseconds after which a test or suite is considered slow', - ) - .option('--reporter ', 'Specify the reporter to use') - .option( - '-t, --testNamePattern ', - 'Run only tests with a name that matches the regex', - ) - .option( - '--testEnvironment ', - 'The environment that will be used for testing', - ) - .option('--testTimeout ', 'Timeout of a test in milliseconds') - .option('--hookTimeout ', 'Timeout of hook in milliseconds') - .option('--hideSkippedTests', 'Hide skipped tests from the output') - .option('--hideSkippedTestFiles', 'Hide skipped test files from the output') - .option('--retry ', 'Number of times to retry a test if it fails') - .option( - '--bail [number]', - 'Stop running tests after n failures. Set to 0 to run all tests regardless of failures', - ) - .option( - '--shard ', - 'Split tests into several shards. This is useful for running tests in parallel on multiple machines.', - ) - .option('--maxConcurrency ', 'Maximum number of concurrent tests') - .option( - '--clearMocks', - 'Automatically clear mock calls, instances, contexts and results before every test', - ) - .option('--resetMocks', 'Automatically reset mock state before every test') - .option( - '--restoreMocks', - 'Automatically restore mock state and implementation before every test', - ) - .option('--browser', 'Run tests in browser mode') - .option('--browser.enabled', 'Run tests in browser mode') - .option( - '--browser.name ', - 'Browser to use: chromium, firefox, webkit (default: chromium)', - ) - .option( - '--browser.headless', - 'Run browser in headless mode (default: true in CI)', - ) - .option('--browser.port ', 'Port for the browser mode dev server') - .option( - '--browser.strictPort', - 'Exit if the specified port is already in use', - ) - .option( - '--unstubGlobals', - 'Restores all global variables that were changed with `rstest.stubGlobal` before every test', - ) - .option( - '--unstubEnvs', - 'Restores all runtime env values that were changed with `rstest.stubEnv` before every test', - ) - .option( - '--includeTaskLocation', - 'Collect test and suite locations. This might increase the running time.', - ); +type OptionConfig = { + default?: string; +}; - cli - .option('--pool ', 'Shorthand for --pool.type') - .option('--pool.type ', 'Specify the test pool type (e.g. forks)') - .option( - '--pool.maxWorkers ', - 'Maximum number or percentage of workers (e.g. 4 or 50%)', - ) - .option( - '--pool.minWorkers ', - 'Minimum number or percentage of workers (e.g. 1 or 25%)', - ) - .option( - '--pool.execArgv ', - 'Additional Node.js execArgv passed to worker processes (can be specified multiple times)', - ); +type OptionDefinition = readonly [ + rawName: string, + description: string, + config?: OptionConfig, +]; + +const runtimeOptionDefinitions: OptionDefinition[] = [ + [ + '-c, --config ', + 'Specify the configuration file, can be a relative or absolute path', + ], + [ + '--config-loader ', + 'Specify the loader to load the config file (auto | jiti | native)', + { default: 'auto' }, + ], + [ + '-r, --root ', + 'Specify the project root directory, can be an absolute path or a path relative to cwd', + ], + ['--globals', 'Provide global APIs'], + ['--isolate', 'Run tests in an isolated environment'], + ['--include ', 'Match test files'], + ['--exclude ', 'Exclude files from test'], + ['-u, --update', 'Update snapshot files'], + ['--coverage', 'Enable code coverage collection'], + [ + '--project ', + 'Run only projects that match the name, can be a full name or wildcards pattern', + ], + [ + '--passWithNoTests', + 'Allows the test suite to pass when no files are found', + ], + [ + '--printConsoleTrace', + 'Print console traces when calling any console method', + ], + ['--disableConsoleIntercept', 'Disable console intercept'], + ['--logHeapUsage', 'Log heap usage after each test'], + [ + '--slowTestThreshold ', + 'The number of milliseconds after which a test or suite is considered slow', + ], + ['--reporter ', 'Specify the reporter to use'], + [ + '-t, --testNamePattern ', + 'Run only tests with a name that matches the regex', + ], + ['--testEnvironment ', 'The environment that will be used for testing'], + ['--testTimeout ', 'Timeout of a test in milliseconds'], + ['--hookTimeout ', 'Timeout of hook in milliseconds'], + ['--hideSkippedTests', 'Hide skipped tests from the output'], + ['--hideSkippedTestFiles', 'Hide skipped test files from the output'], + ['--retry ', 'Number of times to retry a test if it fails'], + [ + '--bail [number]', + 'Stop running tests after n failures. Set to 0 to run all tests regardless of failures', + ], + [ + '--shard ', + 'Split tests into several shards. This is useful for running tests in parallel on multiple machines.', + ], + ['--maxConcurrency ', 'Maximum number of concurrent tests'], + [ + '--clearMocks', + 'Automatically clear mock calls, instances, contexts and results before every test', + ], + ['--resetMocks', 'Automatically reset mock state before every test'], + [ + '--restoreMocks', + 'Automatically restore mock state and implementation before every test', + ], + ['--browser', 'Run tests in browser mode'], + ['--browser.enabled', 'Run tests in browser mode'], + [ + '--browser.name ', + 'Browser to use: chromium, firefox, webkit (default: chromium)', + ], + ['--browser.headless', 'Run browser in headless mode (default: true in CI)'], + ['--browser.port ', 'Port for the browser mode dev server'], + ['--browser.strictPort', 'Exit if the specified port is already in use'], + [ + '--unstubGlobals', + 'Restores all global variables that were changed with `rstest.stubGlobal` before every test', + ], + [ + '--unstubEnvs', + 'Restores all runtime env values that were changed with `rstest.stubEnv` before every test', + ], + [ + '--includeTaskLocation', + 'Collect test and suite locations. This might increase the running time.', + ], +]; + +const poolOptionDefinitions: OptionDefinition[] = [ + ['--pool ', 'Shorthand for --pool.type'], + ['--pool.type ', 'Specify the test pool type (e.g. forks)'], + [ + '--pool.maxWorkers ', + 'Maximum number or percentage of workers (e.g. 4 or 50%)', + ], + [ + '--pool.minWorkers ', + 'Minimum number or percentage of workers (e.g. 1 or 25%)', + ], + [ + '--pool.execArgv ', + 'Additional Node.js execArgv passed to worker processes (can be specified multiple times)', + ], +]; + +const mergeReportsOptionDefinitions: OptionDefinition[] = [ + [ + '-c, --config ', + 'Specify the configuration file, can be a relative or absolute path', + ], + [ + '--config-loader ', + 'Specify the loader to load the config file (auto | jiti | native)', + { default: 'auto' }, + ], + [ + '-r, --root ', + 'Specify the project root directory, can be an absolute path or a path relative to cwd', + ], + ['--coverage', 'Enable code coverage collection'], + ['--reporter ', 'Specify the reporter to use'], + ['--cleanup', 'Remove blob reports directory after merging'], +]; + +const hiddenPassthroughOptionDefinitions: OptionDefinition[] = [ + ['--isolate', 'Run tests in an isolated environment'], +]; + +const listCommandOptionDefinitions: OptionDefinition[] = [ + ['--filesOnly', 'only list the test files'], + ['--json [boolean/path]', 'print tests as JSON or write to a file'], + ['--includeSuites', 'include suites in output'], + ['--printLocation', 'print test case location'], +]; + +const applyOptions = ( + command: CAC | Command, + definitions: readonly OptionDefinition[], +): void => { + for (const [rawName, description, config] of definitions) { + command.option(rawName, description, config); + } }; +const applyRuntimeCommandOptions = (command: Command): void => { + applyOptions(command, runtimeOptionDefinitions); + applyOptions(command, poolOptionDefinitions); +}; + +const filterHelpOptions = ( + sections: Array<{ title?: string; body: string }>, + hiddenOptionPrefixes: string[], +) => + sections.map((section) => { + if (section.title !== 'Options') { + return section; + } + + return { + ...section, + body: section.body + .split('\n') + .filter( + (line) => + !hiddenOptionPrefixes.some((prefix) => + line.trimStart().startsWith(prefix), + ), + ) + .join('\n'), + }; + }); + const handleUnexpectedExit = (rstest: RstestInstance | undefined, err: any) => { for (const reporter of rstest?.context.reporters || []) { reporter.onExit?.(); @@ -203,129 +269,139 @@ export const runRest = async ({ } }; -export function setupCommands(): void { +export function createCli(): CAC { const cli = cac('rstest'); - cli.help(); + cli.help((sections) => { + switch (cli.matchedCommand?.name) { + case 'init': + case 'merge-reports': + return filterHelpOptions(sections, ['--isolate']); + default: + return sections; + } + }); cli.version(RSTEST_VERSION); - // Apply common options to all commands - applyCommonOptions(cli); - - cli + const defaultCommand = cli .command('[...filters]', 'run tests') - .option('-w, --watch', 'Run tests in watch mode') - .action( - async ( - filters: string[], - options: CommonOptions & { - watch?: boolean; - }, - ) => { - if (!determineAgent().isAgent) { - showRstest(); - } - if (options.watch) { - await runRest({ options, filters, command: 'watch' }); - } else { - await runRest({ options, filters, command: 'run' }); - } + .option('-w, --watch', 'Run tests in watch mode'); + applyRuntimeCommandOptions(defaultCommand); + defaultCommand.action( + async ( + filters: string[], + options: CommonOptions & { + watch?: boolean; }, - ); - - cli - .command('run [...filters]', 'run tests without watch mode') - .action(async (filters: string[], options: CommonOptions) => { + ) => { if (!determineAgent().isAgent) { showRstest(); } - await runRest({ options, filters, command: 'run' }); - }); - - cli - .command('watch [...filters]', 'run tests in watch mode') - .action(async (filters: string[], options: CommonOptions) => { - if (!determineAgent().isAgent) { - showRstest(); + if (options.watch) { + await runRest({ options, filters, command: 'watch' }); + } else { + await runRest({ options, filters, command: 'run' }); } - await runRest({ options, filters, command: 'watch' }); - }); - - cli - .command('list [...filters]', 'lists all test files that Rstest will run') - .option('--filesOnly', 'only list the test files') - .option('--json [boolean/path]', 'print tests as JSON or write to a file') - .option('--includeSuites', 'include suites in output') - .option('--printLocation', 'print test case location') - .action( - async ( - filters: string[], - options: CommonOptions & ListCommandOptions, - ) => { - try { - const { config, configFilePath, projects, createRstest } = - await resolveCliRuntime(options); - - if (options.printLocation) { - config.includeTaskLocation = true; - } - - const rstest = createRstest( - { config, configFilePath, projects }, - 'list', - filters.map(normalize), - ); - - await rstest.listTests({ - filesOnly: options.filesOnly, - json: options.json, - includeSuites: options.includeSuites, - printLocation: options.printLocation, - }); - } catch (err) { - logger.error('Failed to run Rstest list.'); - logger.error(formatError(err)); - process.exit(1); - } - }, - ); + }, + ); + + const runCommand = cli.command( + 'run [...filters]', + 'run tests without watch mode', + ); + applyRuntimeCommandOptions(runCommand); + runCommand.action(async (filters: string[], options: CommonOptions) => { + if (!determineAgent().isAgent) { + showRstest(); + } + await runRest({ options, filters, command: 'run' }); + }); + + const watchCommand = cli.command( + 'watch [...filters]', + 'run tests in watch mode', + ); + applyRuntimeCommandOptions(watchCommand); + watchCommand.action(async (filters: string[], options: CommonOptions) => { + if (!determineAgent().isAgent) { + showRstest(); + } + await runRest({ options, filters, command: 'watch' }); + }); + + const listCommand = cli.command( + 'list [...filters]', + 'lists all test files that Rstest will run', + ); + applyRuntimeCommandOptions(listCommand); + applyOptions(listCommand, listCommandOptionDefinitions); + listCommand.action( + async (filters: string[], options: CommonOptions & ListCommandOptions) => { + try { + const { config, configFilePath, projects, createRstest } = + await resolveCliRuntime(options); - cli - .command( - 'merge-reports [path]', - 'Merge blob reports from multiple shards into a unified report', - ) - .option('--cleanup', 'Remove blob reports directory after merging') - .action( - async ( - path: string | undefined, - options: CommonOptions & { cleanup?: boolean }, - ) => { - if (!determineAgent().isAgent) { - showRstest(); + if (options.printLocation) { + config.includeTaskLocation = true; } - try { - const { config, configFilePath, projects, createRstest } = - await resolveCliRuntime(options); - const rstest = createRstest( - { config, configFilePath, projects }, - 'merge-reports', - [], - ); - await rstest.mergeReports({ path, cleanup: options.cleanup }); - } catch (err) { - logger.error('Failed to merge reports.'); - logger.error(formatError(err)); - process.exit(1); - } - }, - ); + const rstest = createRstest( + { config, configFilePath, projects }, + 'list', + filters.map(normalize), + ); + + await rstest.listTests({ + filesOnly: options.filesOnly, + json: options.json, + includeSuites: options.includeSuites, + printLocation: options.printLocation, + }); + } catch (err) { + logger.error('Failed to run Rstest list.'); + logger.error(formatError(err)); + process.exit(1); + } + }, + ); + + const mergeReportsCommand = cli.command( + 'merge-reports [path]', + 'Merge blob reports from multiple shards into a unified report', + ); + applyOptions(mergeReportsCommand, mergeReportsOptionDefinitions); + applyOptions(mergeReportsCommand, hiddenPassthroughOptionDefinitions); + mergeReportsCommand.action( + async ( + path: string | undefined, + options: CommonOptions & { cleanup?: boolean }, + ) => { + if (!determineAgent().isAgent) { + showRstest(); + } + try { + const { config, configFilePath, projects, createRstest } = + await resolveCliRuntime(options); + const rstest = createRstest( + { config, configFilePath, projects }, + 'merge-reports', + [], + ); + + await rstest.mergeReports({ path, cleanup: options.cleanup }); + } catch (err) { + logger.error('Failed to merge reports.'); + logger.error(formatError(err)); + process.exit(1); + } + }, + ); // init command - initialize rstest configuration cli .command('init [project]', 'Initialize rstest configuration') .option('--yes', 'Use default options (non-interactive)') + .option('--isolate', 'Run tests in an isolated environment') .action(async (project: string | undefined, options: { yes?: boolean }) => { try { let selectedProject = project; @@ -370,5 +446,9 @@ export function setupCommands(): void { } }); - cli.parse(); + return cli; +} + +export function setupCommands(): void { + createCli().parse(); } diff --git a/packages/core/tests/cli/commands.test.ts b/packages/core/tests/cli/commands.test.ts new file mode 100644 index 000000000..70767c3b2 --- /dev/null +++ b/packages/core/tests/cli/commands.test.ts @@ -0,0 +1,49 @@ +import { describe, expect, it, onTestFinished, rs } from '@rstest/core'; +import { createCli } from '../../src/cli/commands'; + +const renderHelp = (argv: string[]): string => { + const logs: string[] = []; + + rs.spyOn(console, 'info').mockImplementation((...args) => { + logs.push(args.join(' ')); + }); + + onTestFinished(() => { + rs.resetAllMocks(); + }); + + createCli().parse(argv, { run: false }); + + return logs.join('\n'); +}; + +describe('CLI help output', () => { + it('shows only init-specific options for init help', () => { + const help = renderHelp(['node', 'rstest', 'init', '--help']); + + expect(help).toContain('--yes'); + expect(help).not.toContain('--coverage'); + expect(help).not.toContain('--reporter'); + expect(help).not.toContain('--browser'); + }); + + it('shows only merge-reports options for merge-reports help', () => { + const help = renderHelp(['node', 'rstest', 'merge-reports', '--help']); + + expect(help).toContain('--cleanup'); + expect(help).toContain('--coverage'); + expect(help).toContain('--reporter'); + expect(help).toContain('--config-loader'); + expect(help).not.toContain('--browser'); + expect(help).not.toContain('--update'); + expect(help).not.toContain('--testTimeout'); + }); + + it('rejects unrelated runtime options for init', () => { + const cli = createCli(); + + expect(() => + cli.parse(['node', 'rstest', 'init', '--coverage'], { run: true }), + ).toThrow('Unknown option `--coverage`'); + }); +}); diff --git a/website/docs/en/guide/basic/cli.mdx b/website/docs/en/guide/basic/cli.mdx index a34f30324..55c1d9063 100644 --- a/website/docs/en/guide/basic/cli.mdx +++ b/website/docs/en/guide/basic/cli.mdx @@ -27,16 +27,16 @@ Commands: run [...filters] run tests without watch mode watch [...filters] run tests in watch mode list [...filters] lists all test files that Rstest will run - merge-reports [path] merge blob reports from multiple shards + merge-reports [path] Merge blob reports from multiple shards into a unified report + init [project] Initialize rstest configuration Options: - -w, --watch Run tests in watch mode - -h, --help Display this message - -v, --version Display version number - -c, --config - ... + -h, --help Display this message + -v, --version Display version number ``` +Use `npx rstest -h` to see command-specific options. For example, `npx rstest init -h` only shows initialization options, while `npx rstest merge-reports -h` only shows merge-related options. + ## rstest [...filters] Running `rstest` directly will enable the Rstest test in the current directory. @@ -180,9 +180,33 @@ Use `--cleanup` to remove the blob reports directory after merging: npx rstest merge-reports --cleanup ``` +## rstest init + +`rstest init` creates starter configuration for supported project types. + +```bash +npx rstest init +``` + +Currently, `browser` is the available initializer: + +```bash +npx rstest init browser +``` + +Use `--yes` to skip the interactive prompt and apply the default setup: + +```bash +npx rstest init browser --yes +``` + ## CLI options -Rstest CLI provides several common options that can be used with all commands: +Rstest CLI options are registered per command instead of being shared by every command. + +### Test commands + +`rstest`, `rstest run`, and `rstest watch` share the same test runtime options: | Flag | Description | | ------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- | @@ -217,26 +241,52 @@ Rstest CLI provides several common options that can be used with all commands: | `--restoreMocks` | Automatically restore mock state and implementation before every test, see [restoreMocks](/config/test/restore-mocks) | | `--unstubGlobals` | Restores all global variables that were changed with `rstest.stubGlobal` before every test, see [unstubGlobals](/config/test/unstub-globals) | | `--unstubEnvs` | Restores all `process.env` values that were changed with `rstest.stubEnv` before every test, see [unstubEnvs](/config/test/unstub-envs) | -| `--include ` | Specify test file matching pattern, see [include](/config/test/include) | -| `--includeSource ` | Specify in-source testing file matching pattern, see [includeSource](/config/test/include-source) | +| `--include ` | Specify test file matching pattern, see [include](/config/test/include) | | `--logHeapUsage` | Print heap usage for each test, see [logHeapUsage](/config/test/log-heap-usage) | | `--hideSkippedTests` | Do not display skipped test logs, see [hideSkippedTests](/config/test/hide-skipped-tests) | | `--hideSkippedTestFiles` | Do not display skipped test file logs, see [hideSkippedTestFiles](/config/test/hide-skipped-test-files) | -| `--chaiConfig ` | Customize Chai configuration, see [chaiConfig](/config/test/chai-config) | -| `--env ` | Set environment variables, see [env](/config/test/env) | | `--pool ` | Shorthand for `--pool.type`, see [pool](/config/test/pool) | | `--pool.type ` | Specify the test pool type, see [pool](/config/test/pool) | | `--pool.maxWorkers ` | Maximum number or percentage of workers, see [pool](/config/test/pool) | | `--pool.minWorkers ` | Minimum number or percentage of workers, see [pool](/config/test/pool) | | `--pool.execArgv ` | Additional Node.js execArgv for worker processes (repeatable), see [pool](/config/test/pool) | -| `--setupFiles ` | Specify setup files list, see [setupFiles](/config/test/setup-files) | -| `--snapshotFormat ` | Customize snapshot format, see [snapshotFormat](/config/test/snapshot-format) | -| `--resolveSnapshotPath` | Customize snapshot path resolution, see [resolveSnapshotPath](/config/test/resolve-snapshot-path) | -| `--onConsoleLog ` | Handle console logs, see [onConsoleLog](/config/test/on-console-log) | -| `--name ` | Set test suite name, see [name](/config/test/name) | -| `--projects ` | Configure multi-project testing, see [projects](/config/test/projects) | | `-h, --help` | Display help for command | -| `-v, --version` | Display version | + +`rstest` also supports `-w, --watch`, which switches the default command into watch mode. + +### rstest list + +`rstest list` supports the same filtering and config options as the test commands above, and adds: + +| Flag | Description | +| ----------------------- | ------------------------------------------- | +| `--filesOnly` | Only print matching test files | +| `--json [boolean/path]` | Print tests as JSON or write JSON to a file | +| `--includeSuites` | Include suites in the output | +| `--printLocation` | Print test and suite locations | + +### rstest merge-reports + +`rstest merge-reports` has its own smaller option set: + +| Flag | Description | +| -------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `-c, --config ` | Specify the configuration file, can be a relative or absolute path, see [Specify config file](/guide/basic/configure-rstest#specify-config-file) | +| `--config-loader ` | Specify the config loader (`auto` \| `jiti` \| `native`), see [Rsbuild - Specify config loader](https://rsbuild.rs/guide/configuration/rsbuild#specify-config-loader) | +| `-r, --root ` | Specify the project root directory, see [root](/config/test/root) | +| `--coverage` | Enable coverage generation after merging, see [coverage](/config/test/coverage) | +| `--reporter ` | Specify which reporters run on merged results, see [reporters](/config/test/reporters) | +| `--cleanup` | Remove the blob reports directory after merging | +| `-h, --help` | Display help for command | + +### rstest init + +`rstest init` only accepts initialization-specific options: + +| Flag | Description | +| ------------ | ------------------------------------------- | +| `--yes` | Use default options and skip interactive UI | +| `-h, --help` | Display help for command | ### Boolean option negation diff --git a/website/docs/zh/guide/basic/cli.mdx b/website/docs/zh/guide/basic/cli.mdx index c3c40208e..2979b32a7 100644 --- a/website/docs/zh/guide/basic/cli.mdx +++ b/website/docs/zh/guide/basic/cli.mdx @@ -27,16 +27,16 @@ Commands: run [...filters] run tests without watch mode watch [...filters] run tests in watch mode list [...filters] lists all test files that Rstest will run - merge-reports [path] merge blob reports from multiple shards + merge-reports [path] Merge blob reports from multiple shards into a unified report + init [project] Initialize rstest configuration Options: - -w, --watch Run tests in watch mode - -h, --help Display this message - -v, --version Display version number - -c, --config - ... + -h, --help Display this message + -v, --version Display version number ``` +可以通过 `npx rstest -h` 查看命令专属参数。例如,`npx rstest init -h` 只会显示初始化相关参数,而 `npx rstest merge-reports -h` 只会显示合并报告相关参数。 + ## rstest [...filters] 直接运行 `rstest` 命令将会在当前目录执行 Rstest 测试。 @@ -180,9 +180,33 @@ npx rstest merge-reports ./custom-reports-dir npx rstest merge-reports --cleanup ``` +## rstest init + +`rstest init` 用于为支持的项目类型生成初始配置。 + +```bash +npx rstest init +``` + +当前可用的初始化目标是 `browser`: + +```bash +npx rstest init browser +``` + +使用 `--yes` 可以跳过交互式提问,直接应用默认配置: + +```bash +npx rstest init browser --yes +``` + ## CLI 选项 -Rstest CLI 支持以下常用参数,所有命令均可使用: +Rstest CLI 参数是按命令注册的,并不是所有命令共享同一套参数。 + +### 测试命令 + +`rstest`、`rstest run` 和 `rstest watch` 共享同一组测试运行参数: | 参数 | 说明 | | ------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- | @@ -217,26 +241,52 @@ Rstest CLI 支持以下常用参数,所有命令均可使用: | `--restoreMocks` | 每个测试前自动恢复 mock 状态和实现,详见 [restoreMocks](/config/test/restore-mocks) | | `--unstubGlobals` | 每个测试前恢复被 `rstest.stubGlobal` 修改的全局变量,详见 [unstubGlobals](/config/test/unstub-globals) | | `--unstubEnvs` | 每个测试前恢复被 `rstest.stubEnv` 修改的 `process.env`,详见 [unstubEnvs](/config/test/unstub-envs) | -| `--include ` | 指定测试文件匹配模式,详见 [include](/config/test/include) | -| `--includeSource ` | 指定源码内联测试文件匹配模式,详见 [includeSource](/config/test/include-source) | +| `--include ` | 指定测试文件匹配模式,详见 [include](/config/test/include) | | `--logHeapUsage` | 打印每个测试的堆内存使用情况,详见 [logHeapUsage](/config/test/log-heap-usage) | | `--hideSkippedTests` | 不展示跳过测试的日志,详见 [hideSkippedTests](/config/test/hide-skipped-tests) | | `--hideSkippedTestFiles` | 不展示跳过测试文件的日志,详见 [hideSkippedTestFiles](/config/test/hide-skipped-test-files) | -| `--chaiConfig ` | 自定义 Chai 配置,详见 [chaiConfig](/config/test/chai-config) | -| `--env ` | 设置环境变量,详见 [env](/config/test/env) | | `--pool ` | `--pool.type` 的 shorthand,详见 [pool](/config/test/pool) | | `--pool.type ` | 指定测试线程池类型,详见 [pool](/config/test/pool) | | `--pool.maxWorkers ` | 最大 worker 数量或百分比,详见 [pool](/config/test/pool) | | `--pool.minWorkers ` | 最小 worker 数量或百分比,详见 [pool](/config/test/pool) | | `--pool.execArgv ` | 传给 worker 进程的额外 Node.js execArgv(可重复传入),详见 [pool](/config/test/pool) | -| `--setupFiles ` | 指定 setup 文件列表,详见 [setupFiles](/config/test/setup-files) | -| `--snapshotFormat ` | 自定义快照格式,详见 [snapshotFormat](/config/test/snapshot-format) | -| `--resolveSnapshotPath` | 自定义快照路径解析,详见 [resolveSnapshotPath](/config/test/resolve-snapshot-path) | -| `--onConsoleLog ` | 处理 console 日志,详见 [onConsoleLog](/config/test/on-console-log) | -| `--name ` | 设置测试套件名称,详见 [name](/config/test/name) | -| `--projects ` | 配置多项目测试,详见 [projects](/config/test/projects) | | `-h, --help` | 显示帮助信息 | -| `-v, --version` | 显示版本号 | + +`rstest` 默认命令还额外支持 `-w, --watch`,可直接切换到 watch 模式。 + +### rstest list + +`rstest list` 支持上面测试命令的过滤和配置参数,并额外提供: + +| 参数 | 说明 | +| ----------------------- | --------------------------- | +| `--filesOnly` | 仅输出匹配到的测试文件 | +| `--json [boolean/path]` | 以 JSON 输出,或写入文件 | +| `--includeSuites` | 在输出中包含 suite | +| `--printLocation` | 输出测试和 suite 的位置信息 | + +### rstest merge-reports + +`rstest merge-reports` 只注册一组更小的参数集合: + +| 参数 | 说明 | +| -------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- | +| `-c, --config ` | 指定配置文件路径(相对或绝对路径),详见 [指定配置文件](/guide/basic/configure-rstest#指定配置文件) | +| `--config-loader ` | 指定配置加载器 (`auto` \| `jiti` \| `native`),详见 [Rsbuild - 指定加载方式](https://rsbuild.rs/guide/configuration/rsbuild#specify-config-loader) | +| `-r, --root ` | 指定项目根目录,详见 [root](/config/test/root) | +| `--coverage` | 合并完成后生成覆盖率报告,详见 [coverage](/config/test/coverage) | +| `--reporter ` | 指定在合并结果上运行的报告器,详见 [reporters](/config/test/reporters) | +| `--cleanup` | 合并完成后删除 blob 报告目录 | +| `-h, --help` | 显示帮助信息 | + +### rstest init + +`rstest init` 只接受初始化相关参数: + +| 参数 | 说明 | +| ------------ | -------------------------- | +| `--yes` | 使用默认选项并跳过交互界面 | +| `-h, --help` | 显示帮助信息 | ### 布尔选项取反