(deps: TestDeps = {})
| 6813 | } |
| 6814 | |
| 6815 | export function createTestCommand(deps: TestDeps = {}): Command { |
| 6816 | const test = new Command('test').description('Inspect TestSprite tests'); |
| 6817 | |
| 6818 | test |
| 6819 | .command('list') |
| 6820 | .description('List tests in a project') |
| 6821 | // Intentionally NOT `.requiredOption` — Commander's missing-required-option |
| 6822 | // path throws a plain Error and `index.ts` maps it to exit 1, which would |
| 6823 | // bypass the typed `VALIDATION_ERROR` (exit 5) envelope contract from |
| 6824 | // the CLI error spec §2 ("missing required field"). `requireProjectId` |
| 6825 | // below raises `ApiError(VALIDATION_ERROR)` so JSON consumers can read |
| 6826 | // `error.code` and the exit code matches the catalog. |
| 6827 | .option('--project <id>', 'project id (returned by `testsprite project list`)') |
| 6828 | .option('--type <type>', 'filter by test type (frontend|backend)') |
| 6829 | .option('--created-from <source>', 'filter by where the test was authored (portal|mcp|cli)') |
| 6830 | .option( |
| 6831 | '--status <list>', |
| 6832 | 'filter by normalized status (comma-separated). One of: draft, ready, queued, running, passed, failed, blocked, cancelled, unknown — M2.1', |
| 6833 | ) |
| 6834 | .option('--page-size <n>', 'service page-size hint (1-100, default 25)') |
| 6835 | .option('--starting-token <token>', 'opaque cursor from a previous list response') |
| 6836 | .option( |
| 6837 | '--cursor <token>', |
| 6838 | 'alias for --starting-token; accepted for parity with `test result --history`', |
| 6839 | ) |
| 6840 | .option('--max-items <n>', 'stop after this many items across auto-paged pages') |
| 6841 | .addHelpText('after', GLOBAL_OPTS_HINT) |
| 6842 | .action(async (cmdOpts: ListFlagOpts, command: Command) => { |
| 6843 | // Same parser strategy as `project list`: skip Commander's number |
| 6844 | // parser so a non-numeric --page-size surfaces as a typed |
| 6845 | // VALIDATION_ERROR (exit 5) rather than Commander's plain |
| 6846 | // exception (exit 1). Enum filters validate locally too. |
| 6847 | // |
| 6848 | // --cursor is an alias for --starting-token (vocabulary parity with |
| 6849 | // `test result --history`). --starting-token takes precedence if |
| 6850 | // both are supplied (prevents accidental override). |
| 6851 | await runList( |
| 6852 | { |
| 6853 | ...resolveCommonOptions(command), |
| 6854 | projectId: cmdOpts.project, |
| 6855 | type: parseEnumFlag(cmdOpts.type, 'type', TEST_TYPES), |
| 6856 | createdFrom: parseEnumFlag(cmdOpts.createdFrom, 'created-from', CREATED_FROMS), |
| 6857 | status: cmdOpts.status, |
| 6858 | pageSize: parseNumericFlag(cmdOpts.pageSize, 'page-size'), |
| 6859 | startingToken: cmdOpts.startingToken ?? cmdOpts.cursor, |
| 6860 | maxItems: parseNumericFlag(cmdOpts.maxItems, 'max-items'), |
| 6861 | }, |
| 6862 | deps, |
| 6863 | ); |
| 6864 | }); |
| 6865 | |
| 6866 | test |
| 6867 | .command('get <test-id>') |
| 6868 | .description('Get a test by id') |
| 6869 | .addHelpText('after', GLOBAL_OPTS_HINT) |
| 6870 | .action(async (testId: string, _cmdOpts, command: Command) => { |
| 6871 | await runGet({ ...resolveCommonOptions(command), testId }, deps); |
| 6872 | }); |
no test coverage detected