UNPKG

tdpw

Version:

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

268 lines 9.94 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.ReportDiscoveryService = void 0; const path_1 = require("path"); const fs_1 = require("../utils/fs"); const validators_1 = require("./validators"); const types_1 = require("../types"); /** * Service to discover Playwright test report files with smart scanning. */ class ReportDiscoveryService { reportDir; constructor(reportDir) { this.reportDir = reportDir; } /** * Discover report files based on CLI options with smart scanning. */ async discover(options) { const baseDir = (0, fs_1.resolvePath)(options.reportDirectory, 'Report directory'); // JSON report discovery with manual override const jsonReportPath = options.jsonReport ?? await this.findJsonReport(baseDir); await (0, validators_1.validateJsonReport)(jsonReportPath); // HTML report discovery (only if upload requested) let htmlReportDir; if (options.uploadHtml) { htmlReportDir = options.htmlReport ?? await this.findHtmlReport(baseDir); if (htmlReportDir) { await (0, validators_1.validateHtmlReportDir)(htmlReportDir); } } // Trace files discovery (only if upload requested) let traceDirectory; if (options.uploadTraces) { traceDirectory = options.traceDir ?? await this.findTraceDir(baseDir); if (traceDirectory) { await (0, validators_1.validateTraceDir)(traceDirectory); } } return { jsonReport: jsonReportPath, htmlReport: htmlReportDir, traceDir: traceDirectory, }; } /** * Smart JSON report discovery - scan for valid Playwright JSON files */ async findJsonReport(baseDir) { // Try common patterns first (faster) const commonPatterns = [ (0, path_1.join)(baseDir, 'report.json'), // Standard Playwright (0, path_1.join)(baseDir, 'results.json'), // Alternative name (0, path_1.join)(baseDir, 'test-results.json'), // Another common name (0, path_1.join)(baseDir, 'playwright-report', 'report.json'), // Nested structure (0, path_1.join)(baseDir, 'playwright-report', 'results.json'), // Nested alternative ]; for (const candidate of commonPatterns) { if (await (0, fs_1.exists)(candidate)) { // Validate it's actually a Playwright report if (await this.isValidPlaywrightJson(candidate)) { return candidate; } } } // If no common patterns found, scan all JSON files const jsonFiles = await this.scanForJsonFiles(baseDir); for (const jsonFile of jsonFiles) { if (await this.isValidPlaywrightJson(jsonFile)) { return jsonFile; } } throw new types_1.FileSystemError(`No valid Playwright JSON report found in ${baseDir}.\n` + '💡 Looked for: report.json, results.json, test-results.json\n' + '💡 Use --json-report <path> to specify exact location'); } /** * Smart HTML report discovery - find directory containing index.html */ async findHtmlReport(baseDir) { // Try common patterns first const commonPatterns = [ baseDir, // Current directory (0, path_1.join)(baseDir, 'html-report'), // Standard name (0, path_1.join)(baseDir, 'playwright-report'), // Standard Playwright (0, path_1.join)(baseDir, 'report'), // Alternative (0, path_1.join)(baseDir, 'test-report'), // Alternative ]; for (const candidate of commonPatterns) { if (await (0, fs_1.isDirectory)(candidate)) { const indexPath = (0, path_1.join)(candidate, 'index.html'); if (await (0, fs_1.exists)(indexPath)) { return candidate; } } } // Scan for any directory containing index.html const htmlDirs = await this.scanForHtmlDirectories(baseDir); if (htmlDirs.length > 0) { const candidateDir = htmlDirs[0]; if (candidateDir !== undefined) { return candidateDir; } } throw new types_1.FileSystemError(`No HTML report directory with index.html found in ${baseDir}.\n` + '💡 Use --html-report <path> to specify exact location'); } /** * Smart trace directory discovery */ async findTraceDir(baseDir) { // Try common patterns const commonPatterns = [ (0, path_1.join)(baseDir, 'trace'), (0, path_1.join)(baseDir, 'traces'), (0, path_1.join)(baseDir, 'test-results'), (0, path_1.join)(baseDir, 'playwright-report', 'trace'), (0, path_1.join)(baseDir, 'playwright-report', 'traces'), ]; for (const candidate of commonPatterns) { if (await (0, fs_1.isDirectory)(candidate)) { // Check if directory contains any trace files if (await this.containsTraceFiles(candidate)) { return candidate; } } } // Scan for directories containing .zip files (common trace format) const traceDirs = await this.scanForTraceDirectories(baseDir); if (traceDirs.length > 0) { const candidateTraceDir = traceDirs[0]; if (candidateTraceDir !== undefined) { return candidateTraceDir; } } throw new types_1.FileSystemError(`No trace directory found in ${baseDir}.\n` + '💡 Use --trace-dir <path> to specify exact location'); } /** * Validate if a JSON file is a valid Playwright report */ async isValidPlaywrightJson(filePath) { try { const content = await (0, fs_1.readFile)(filePath); const data = JSON.parse(content); // Check for required Playwright report structure return (data && typeof data === 'object' && 'config' in data && 'suites' in data && 'stats' in data && Array.isArray(data.suites)); } catch { return false; } } /** * Scan directory recursively for JSON files */ async scanForJsonFiles(dir, maxDepth = 2) { const jsonFiles = []; try { await this.scanDirectory(dir, jsonFiles, (file) => file.endsWith('.json'), 0, maxDepth); } catch { // Ignore scan errors } return jsonFiles; } /** * Scan for directories containing index.html */ async scanForHtmlDirectories(dir, maxDepth = 2) { const htmlDirs = []; try { await this.scanDirectoryForHtml(dir, htmlDirs, 0, maxDepth); } catch { // Ignore scan errors } return htmlDirs; } /** * Scan for directories containing trace files */ async scanForTraceDirectories(dir, maxDepth = 2) { const traceDirs = []; try { await this.scanDirectoryForTraces(dir, traceDirs, 0, maxDepth); } catch { // Ignore scan errors } return traceDirs; } /** * Generic directory scanner for files */ async scanDirectory(dir, results, filter, currentDepth, maxDepth) { if (currentDepth > maxDepth) return; const entries = await (0, fs_1.readDir)(dir); for (const entry of entries) { if (await (0, fs_1.isDirectory)(entry)) { await this.scanDirectory(entry, results, filter, currentDepth + 1, maxDepth); } else if (filter(entry)) { results.push(entry); } } } /** * Scan for HTML directories */ async scanDirectoryForHtml(dir, results, currentDepth, maxDepth) { if (currentDepth > maxDepth) return; // Check if current directory has index.html const indexPath = (0, path_1.join)(dir, 'index.html'); if (await (0, fs_1.exists)(indexPath)) { results.push(dir); return; // Don't scan subdirectories if we found one } // Scan subdirectories const entries = await (0, fs_1.readDir)(dir); for (const entry of entries) { if (await (0, fs_1.isDirectory)(entry)) { await this.scanDirectoryForHtml(entry, results, currentDepth + 1, maxDepth); } } } /** * Scan for trace directories */ async scanDirectoryForTraces(dir, results, currentDepth, maxDepth) { if (currentDepth > maxDepth) return; // Check if current directory contains trace files if (await this.containsTraceFiles(dir)) { results.push(dir); return; } // Scan subdirectories const entries = await (0, fs_1.readDir)(dir); for (const entry of entries) { if (await (0, fs_1.isDirectory)(entry)) { await this.scanDirectoryForTraces(entry, results, currentDepth + 1, maxDepth); } } } /** * Check if directory contains trace files */ async containsTraceFiles(dir) { try { const entries = await (0, fs_1.readDir)(dir); return entries.some(entry => entry.endsWith('.zip') || entry.endsWith('.trace') || entry.includes('trace')); } catch { return false; } } } exports.ReportDiscoveryService = ReportDiscoveryService; //# sourceMappingURL=discovery.js.map