UNPKG

tdpw

Version:

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

252 lines 10.8 kB
"use strict"; /** * Playwright configuration and shard detection utilities */ Object.defineProperty(exports, "__esModule", { value: true }); exports.PlaywrightShardDetector = void 0; const tslib_1 = require("tslib"); const fs_1 = require("../utils/fs"); const path_1 = tslib_1.__importDefault(require("path")); /** * Playwright configuration parser for shard detection */ class PlaywrightShardDetector { /** * Auto-detect shard information from Playwright configuration and environment */ static async detectShardInfo(workingDir) { try { // Strategy 1: Check environment variables first (most reliable in CI) const envShard = this.detectFromEnvironment(); if (envShard) { return envShard; } // Strategy 2: Read from Playwright configuration files const configShard = await this.detectFromPlaywrightConfig(workingDir); if (configShard) { return configShard; } // Strategy 3: Analyze JSON reports for shard indicators const reportShard = await this.detectFromReports(workingDir); if (reportShard) { return reportShard; } return null; } catch (_error) { // Return null on any error - shard detection is best-effort return null; } } /** * Detect shard info from environment variables */ static detectFromEnvironment() { try { const env = process.env; // GitHub Actions matrix strategy if (env.GITHUB_ACTIONS && env.SHARD_INDEX && env.SHARD_TOTAL) { const shardIndex = parseInt(env.SHARD_INDEX, 10); const shardTotal = parseInt(env.SHARD_TOTAL, 10); if (shardIndex > 0 && shardTotal > 0) { return { shardIndex, shardTotal, shardId: `${shardIndex}/${shardTotal}`, }; } } // GitLab CI parallel jobs if (env.GITLAB_CI && env.CI_NODE_INDEX && env.CI_NODE_TOTAL) { const shardIndex = parseInt(env.CI_NODE_INDEX, 10) + 1; // GitLab is 0-indexed const shardTotal = parseInt(env.CI_NODE_TOTAL, 10); if (shardIndex > 0 && shardTotal > 0) { return { shardIndex, shardTotal, shardId: `${shardIndex}/${shardTotal}`, }; } } // CircleCI parallelism if (env.CIRCLECI && env.CIRCLE_NODE_INDEX && env.CIRCLE_NODE_TOTAL) { const shardIndex = parseInt(env.CIRCLE_NODE_INDEX, 10) + 1; // CircleCI is 0-indexed const shardTotal = parseInt(env.CIRCLE_NODE_TOTAL, 10); if (shardIndex > 0 && shardTotal > 0) { return { shardIndex, shardTotal, shardId: `${shardIndex}/${shardTotal}`, }; } } // Generic environment variables if (env.SHARD_INDEX && env.SHARD_TOTAL) { const shardIndex = parseInt(env.SHARD_INDEX, 10); const shardTotal = parseInt(env.SHARD_TOTAL, 10); if (shardIndex > 0 && shardTotal > 0) { return { shardIndex, shardTotal, shardId: `${shardIndex}/${shardTotal}`, }; } } return null; } catch { return null; } } /** * Detect shard info from Playwright configuration files */ static async detectFromPlaywrightConfig(workingDir) { const configFiles = [ 'playwright.config.ts', 'playwright.config.js', 'playwright.config.mjs', 'playwright.config.cjs', ]; for (const configFile of configFiles) { const configPath = path_1.default.join(workingDir, configFile); if (await (0, fs_1.exists)(configPath)) { try { const configContent = await (0, fs_1.readFileBuffer)(configPath); const configText = configContent.toString(); // Look for shard configuration patterns const shardMatch = configText.match(/shard:\s*(\d+)\s*\/\s*(\d+)/); if (shardMatch?.[1] && shardMatch[2]) { const shardIndex = parseInt(shardMatch[1], 10); const shardTotal = parseInt(shardMatch[2], 10); return { shardIndex, shardTotal, shardId: `${shardIndex}/${shardTotal}`, }; } // Look for CLI shard argument patterns const cliShardMatch = configText.match(/--shard[=\s]+(\d+)\/(\d+)/); if (cliShardMatch?.[1] && cliShardMatch[2]) { const shardIndex = parseInt(cliShardMatch[1], 10); const shardTotal = parseInt(cliShardMatch[2], 10); return { shardIndex, shardTotal, shardId: `${shardIndex}/${shardTotal}`, }; } } catch { // Continue to next config file on error continue; } } } return null; } /** * Detect shard info from JSON reports (look for metadata in reports) */ static async detectFromReports(workingDir) { try { // Common report locations const reportPaths = [ path_1.default.join(workingDir, 'playwright-report', 'report.json'), path_1.default.join(workingDir, 'playwright-report', 'results.json'), path_1.default.join(workingDir, 'test-results', 'results.json'), path_1.default.join(workingDir, 'test-results', 'report.json'), path_1.default.join(workingDir, 'results.json'), path_1.default.join(workingDir, 'report.json'), ]; for (const reportPath of reportPaths) { if (await (0, fs_1.exists)(reportPath)) { try { const reportContent = await (0, fs_1.readFileBuffer)(reportPath); const reportText = reportContent.toString(); // Parse JSON to extract shard information from config try { const reportJson = JSON.parse(reportText); // Check for Playwright's config.shard structure (official format) if (reportJson?.config?.shard && typeof reportJson.config.shard === 'object') { const shard = reportJson.config.shard; // Playwright uses "current" and "total" fields if (typeof shard.current === 'number' && typeof shard.total === 'number') { const shardIndex = shard.current; const shardTotal = shard.total; if (shardIndex > 0 && shardTotal > 0 && shardIndex <= shardTotal) { return { shardIndex, shardTotal, shardId: `${shardIndex}/${shardTotal}`, }; } } } } catch { // If JSON parsing fails, continue with regex-based detection } // Fallback: Look for shard indicators using regex patterns const shardMatch = reportText.match(/"shard":\s*"(\d+)\/(\d+)"/); if (shardMatch?.[1] && shardMatch[2]) { const shardIndex = parseInt(shardMatch[1], 10); const shardTotal = parseInt(shardMatch[2], 10); return { shardIndex, shardTotal, shardId: `${shardIndex}/${shardTotal}`, }; } // Look for Playwright CLI metadata if (reportText.includes('--shard')) { const cliMatch = reportText.match(/--shard[=\s]+(\d+)\/(\d+)/); if (cliMatch?.[1] && cliMatch[2]) { const shardIndex = parseInt(cliMatch[1], 10); const shardTotal = parseInt(cliMatch[2], 10); return { shardIndex, shardTotal, shardId: `${shardIndex}/${shardTotal}`, }; } } } catch { // Continue to next report on error continue; } } } return null; } catch { return null; } } /** * Validate shard information */ static validateShardInfo(shardInfo) { return (shardInfo.shardIndex > 0 && shardInfo.shardTotal > 0 && shardInfo.shardIndex <= shardInfo.shardTotal && shardInfo.shardId === `${shardInfo.shardIndex}/${shardInfo.shardTotal}`); } /** * Create default shard info (single shard) */ static createDefaultShardInfo() { return { shardIndex: 1, shardTotal: 1, shardId: '1/1', }; } } exports.PlaywrightShardDetector = PlaywrightShardDetector; //# sourceMappingURL=shard-detection.js.map