UNPKG

tdpw

Version:

CLI tool for uploading Playwright test reports to TestDino platform with TestDino storage support

407 lines (381 loc) 16.6 kB
"use strict"; /** * Command registry and execution logic */ Object.defineProperty(exports, "__esModule", { value: true }); exports.commandManager = exports.CommandManager = void 0; const commander_1 = require("commander"); const cache_1 = require("./commands/cache"); const last_failed_1 = require("./commands/last-failed"); const upload_1 = require("./commands/upload"); const types_1 = require("../types"); const version_1 = require("../version"); /** * Command manager for handling subcommands and backward compatibility */ class CommandManager { program; config; constructor() { this.program = new commander_1.Command(); this.setupProgram(); } /** * Setup the main program with subcommands and backward compatibility */ setupProgram() { this.program .name('tdpw') .description('TestDino CLI - Upload reports and cache test metadata') .version(version_1.VERSION) .addHelpText('after', ` Main Commands: cache Store test execution metadata after Playwright runs last-failed Get last failed test cases for Playwright execution upload [report-directory] Upload test reports to TestDino Quick Start: $ npx tdpw cache --token="your-token" # Cache test metadata $ npx tdpw last-failed --token="your-token" # Get failed tests $ npx tdpw upload ./playwright-report --token="your-token" # Upload reports $ npx tdpw upload ./playwright-report --environment="staging" --token="your-token" # Upload with environment tag Legacy Syntax (Deprecated): $ npx tdpw ./playwright-report --token="your-token" # Old syntax (still works) Note: Legacy syntax without 'upload' command is deprecated and will be removed in a future version. Environment Variables: TESTDINO_API_URL API endpoint override TESTDINO_TOKEN API authentication token TESTDINO_TARGET_ENV Target environment for Testrun For command-specific help: $ npx tdpw cache --help $ npx tdpw last-failed --help $ npx tdpw upload --help Documentation: https://docs.testdino.com/cli `); // Cache subcommand (store metadata) this.program .command('cache') .description('Store test execution metadata after Playwright runs') .option('--cache-id <value>', 'Custom cache ID (or TESTDINO_CACHE_ID env var)') .option('--working-dir <path>', 'Directory to scan for test results (default: cwd)') .option('-t, --token <value>', 'TestDino API token (or TESTDINO_TOKEN env var)') .option('-v, --verbose', 'Verbose logging') .action(async (options) => { await this.executeCache(options); }); // Last Failed subcommand (retrieve failure data) this.program .command('last-failed') .description('Get last failed test cases for Playwright execution') .option('--cache-id <value>', 'Custom cache ID (or TESTDINO_CACHE_ID env var)') .option('--branch <name>', 'Override branch name (auto-detected from Git by default)') .option('--commit <hash>', 'Override commit hash (auto-detected from Git by default)') .option('-t, --token <value>', 'TestDino API token (or TESTDINO_TOKEN env var)') .option('-v, --verbose', 'Verbose logging') .action(async (options) => { await this.executeLastFailed(options); }); // Upload subcommand for backward compatibility this.program .command('upload') .description('Upload test reports to TestDino') .arguments('[report-directory]') .option('-t, --token <value>', 'TestDino API token') .option('--environment <value>', 'Target environment tag (e.g., staging, production, qa)') .option('--upload-images', 'Upload image attachments', false) .option('--upload-videos', 'Upload video attachments', false) .option('--upload-html', 'Upload HTML reports', false) .option('--upload-traces', 'Upload trace files', false) .option('--upload-files', 'Upload file attachments', false) .option('--upload-full-json', 'Upload all attachments', false) .option('--json-report <path>', 'Specific JSON report path') .option('--html-report <path>', 'Specific HTML report path') .option('--trace-dir <path>', 'Specific trace directory path') .option('-v, --verbose', 'Verbose logging', false) .action(async (reportDirectory, options) => { await this.executeUpload(reportDirectory, options); }); } /** * Execute cache command */ async executeCache(options) { try { // Validate cache options const validatedOptions = cache_1.CacheOptionsSchema.parse(options); // Create configuration for cache command const config = this.getOrCreateConfig(validatedOptions.token); // Execute cache command const cacheCommand = new cache_1.CacheCommand(config); await cacheCommand.execute(validatedOptions); } catch (error) { throw new types_1.ValidationError(error instanceof Error ? error.message : 'Cache command failed'); } } /** * Execute last failed command */ async executeLastFailed(options) { try { // Validate last-failed options const validatedOptions = last_failed_1.LastFailedOptionsSchema.parse(options); // Create configuration for last failed command const config = this.getOrCreateConfig(validatedOptions.token); // Execute last failed command const lastFailedCommand = new last_failed_1.LastFailedCommand(config); await lastFailedCommand.execute(validatedOptions); } catch (error) { throw new types_1.ValidationError(error instanceof Error ? error.message : 'Last failed command failed'); } } /** * Execute upload command (backward compatibility) */ async executeUpload(reportDirectory, options) { if (!reportDirectory) { throw new types_1.ValidationError('Report directory is required for upload command. Use "npx tdpw cache" for caching metadata.'); } // Resolve environment value: CLI option > env var > default const resolvedEnvironment = this.resolveEnvironmentValue(options.environment); // Build CLIOptions for upload command const cliOptions = { reportDirectory, token: options.token || '', uploadImages: Boolean(options.uploadImages), uploadVideos: Boolean(options.uploadVideos), uploadHtml: Boolean(options.uploadHtml), uploadTraces: Boolean(options.uploadTraces), uploadFiles: Boolean(options.uploadFiles), uploadFullJson: Boolean(options.uploadFullJson), jsonReport: options.jsonReport, htmlReport: options.htmlReport, traceDir: options.traceDir, verbose: Boolean(options.verbose), environment: resolvedEnvironment, }; // Create configuration and execute this.getOrCreateConfig(cliOptions.token); // Ensures config is created with token const uploadCommand = new upload_1.UploadCommand(); await uploadCommand.execute(cliOptions); } /** * Resolve environment value with precedence: CLI option > env var > default * Validates format using regex: /^[a-z0-9]+([_-][a-z0-9]+)*$/ */ resolveEnvironmentValue(cliValue) { const defaultValue = 'unknown'; const envVarValue = process.env.TESTDINO_TARGET_ENV; // Determine the resolved value based on precedence let resolvedValue; if (cliValue !== undefined && cliValue !== '') { resolvedValue = cliValue; } else if (envVarValue !== undefined && envVarValue !== '') { resolvedValue = envVarValue; } else { resolvedValue = defaultValue; } // Skip validation for default value if (resolvedValue === defaultValue) { return resolvedValue; } // Validate format using regex const environmentPattern = /^[a-z0-9]+([_-][a-z0-9]+)*$/; if (!environmentPattern.test(resolvedValue)) { throw new types_1.ValidationError(`Invalid environment value "${resolvedValue}". ` + 'Must contain only lowercase letters, numbers, hyphens, and underscores. ' + 'Examples: staging, production, qa, dev-1, test_env'); } return resolvedValue; } /** * Get or create configuration for cache command */ getOrCreateConfig(token) { if (!this.config) { this.config = this.createConfigForCache(token); } return this.config; } /** * Create configuration specifically for cache command */ createConfigForCache(token) { // Resolve token from CLI option or environment variable const resolvedToken = token || process.env.TESTDINO_TOKEN || ''; if (!resolvedToken) { throw new types_1.ValidationError('API token is required. Provide via --token flag or TESTDINO_TOKEN environment variable.'); } // Create minimal config for cache command const config = { apiUrl: process.env.TESTDINO_API_URL || 'https://api.testdino.com', token: resolvedToken, uploadImages: false, uploadVideos: false, uploadHtml: false, uploadTraces: false, uploadFiles: false, uploadFullJson: false, verbose: false, environment: 'unknown', // Not used by cache command batchSize: 5, maxConcurrentUploads: 10, uploadTimeout: 60000, retryAttempts: 3, }; return config; } /** * Parse and execute commands */ async parseAndExecute(args = process.argv) { try { // Note: Help handling is now done in CLI index.ts before reaching here await this.program.parseAsync(args); } catch (error) { // Re-throw with better context throw new types_1.ValidationError(error instanceof Error ? error.message : 'Command execution failed'); } } /** * Show help */ showHelp() { this.program.help(); } /** * Show cache command help */ showCacheHelp() { console.log(` Usage: tdpw cache [options] Store test execution metadata after Playwright runs Options: --cache-id <value> Custom cache ID (or TESTDINO_CACHE_ID env var) --working-dir <path> Directory to scan for test results (default: cwd) -t, --token <value> TestDino API token (or TESTDINO_TOKEN env var) -v, --verbose Verbose logging -h, --help Display help for cache command Examples: $ npx tdpw cache # Use TESTDINO_TOKEN env var $ npx tdpw cache -t "trx_dev_abc123..." # Provide token directly $ npx tdpw cache --verbose # With detailed logging $ npx tdpw cache --working-dir ./test-results # Custom directory $ npx tdpw cache --cache-id "custom_project_main" # Custom cache ID Cache ID Format: Auto-detected: ciProvider_repoName_branchName (e.g., gh_playwright-tests_main) Custom: Any alphanumeric string with dashes/underscores (5-150 chars) The cache ID uniquely identifies your test runs and enables the "last-failed" feature. Use the same cache ID across workflow runs to share cache data between them. Auto-detection: - Cache ID: Auto-generated from CI provider, repo name, and branch - Branch: Auto-detected from Git metadata - Commit: Auto-detected from Git metadata - Shard info: Automatically detected from Playwright config and JSON reports - JSON Reports: Uses existing TestDino discovery system - Metadata: Reuses existing Git, CI, and system collectors Environment Variables: TESTDINO_API_URL API endpoint override TESTDINO_TOKEN API authentication token TESTDINO_CACHE_ID Custom cache ID override `); } /** * Show last-failed command help */ showLastFailedHelp() { console.log(` Usage: tdpw last-failed [options] Get last failed test cases for Playwright execution Options: --cache-id <value> Custom cache ID (or TESTDINO_CACHE_ID env var) --branch <name> Override branch name (auto-detected from Git by default) --commit <hash> Override commit hash (auto-detected from Git by default) -t, --token <value> TestDino API token (or TESTDINO_TOKEN env var) -v, --verbose Verbose logging -h, --help Display help for last-failed command Examples: $ npx tdpw last-failed # Use TESTDINO_TOKEN env var $ npx tdpw last-failed -t "trx_dev_abc123..." # Provide token directly $ npx tdpw last-failed --verbose # With detailed logging $ npx tdpw last-failed --cache-id "gh_myrepo_main" # Custom cache ID $ npx tdpw last-failed --branch "main" # Override branch Usage with Playwright: # Get failed tests and run them $ npx playwright test $(npx tdpw last-failed) # Or store in a variable $ FAILED_TESTS=$(npx tdpw last-failed) $ npx playwright test $FAILED_TESTS Output Format: The command outputs Playwright CLI arguments for running only the failed tests: - Single file: "tests/example.spec.ts -g \\"test1|test2\\"" - Multiple files: "-g \\"test1|test2|test3\\"" Auto-detection: - Cache ID: Auto-generated from CI provider, repo name, and branch - Branch: Auto-detected from Git (override with --branch) - Commit: Auto-detected from Git (override with --commit) Environment Variables: TESTDINO_API_URL API endpoint override TESTDINO_TOKEN API authentication token TESTDINO_CACHE_ID Custom cache ID override `); } /** * Show upload command help */ showUploadHelp() { console.log(` Usage: tdpw upload [report-directory] [options] Upload test reports to TestDino Arguments: report-directory Directory containing Playwright test reports Options: -t, --token <value> TestDino API token --environment <value> Target environment tag (e.g., staging, production, qa) --upload-images Upload image attachments --upload-videos Upload video attachments --upload-html Upload HTML reports --upload-traces Upload trace files --upload-files Upload file attachments --upload-full-json Upload all attachments --json-report <path> Specific JSON report path --html-report <path> Specific HTML report path --trace-dir <path> Specific trace directory path -v, --verbose Verbose logging -h, --help Display help for upload command Examples: $ npx tdpw upload ./playwright-report --token="trx_dev_abc123..." $ npx tdpw upload ./test-results --upload-images $ npx tdpw upload ./reports --upload-html --verbose $ npx tdpw upload ./test-results --upload-full-json $ npx tdpw upload ./playwright-report --environment="staging" --token="trx_dev_abc123..." Flag Combinations: No flags: Only JSON report uploaded --upload-images: JSON + image attachments --upload-videos: JSON + video attachments --upload-files: JSON + file attachments (.md, .pdf, .txt, .log) --upload-traces: JSON + trace files --upload-html: JSON + HTML + images + videos (complete bundle) --upload-full-json: JSON + images + videos + files (complete bundle) Environment Variables: TESTDINO_API_URL API endpoint override TESTDINO_TOKEN API authentication token TESTDINO_TARGET_ENV Target environment for Testrun `); } /** * Get version */ getVersion() { return version_1.VERSION; } } exports.CommandManager = CommandManager; /** * Export command manager instance */ exports.commandManager = new CommandManager(); //# sourceMappingURL=commands.js.map