arda-site-scan
Version:
A standalone CLI tool for comprehensive website analysis including screenshots, SEO, and accessibility testing using Playwright
206 lines • 7.81 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.StandardTestOutputHandler = void 0;
const path_1 = __importDefault(require("path"));
const fs_1 = require("fs");
const chalk_1 = __importDefault(require("chalk"));
const test_output_types_js_1 = require("../types/test-output-types.js");
/**
* Centralized handler for all test output operations
* Implements DRY principles and standardized file management
*/
class StandardTestOutputHandler {
outputDir;
constructor(outputDir = 'arda-site-scan-sessions') {
this.outputDir = outputDir;
}
/**
* Generate the appropriate output path for a test
*/
generateOutputPath(sessionId, testType, config, context) {
const baseDir = path_1.default.join(this.outputDir, sessionId);
// Generate filename from pattern
const filename = this.generateFilename(testType, config, context);
if (config.type === 'per-page') {
if (!context.pageName) {
throw new Error(`Page name is required for per-page test output: ${testType}`);
}
// Per-page tests go in page-specific subdirectories
const pagePath = path_1.default.join(baseDir, context.pageName);
if (config.subdirectory) {
return path_1.default.join(pagePath, config.subdirectory, filename);
}
return path_1.default.join(pagePath, filename);
}
else {
// Site-wide tests go in session root
if (config.subdirectory) {
return path_1.default.join(baseDir, config.subdirectory, filename);
}
return path_1.default.join(baseDir, filename);
}
}
/**
* Save content to the appropriate location
*/
async saveOutput(content, outputPath, config) {
try {
// Ensure directory exists
await this.ensureOutputDirectory(outputPath);
// Write file
await fs_1.promises.writeFile(outputPath, content, 'utf8');
// Get file stats
const stats = await fs_1.promises.stat(outputPath);
console.log(chalk_1.default.green(` 📄 ${config.type === 'per-page' ? 'Page' : 'Site'} output saved: ${outputPath}`));
return {
success: true,
outputPath,
fileSize: stats.size,
metadata: {
type: config.type,
extension: config.fileExtension,
mimeType: config.mimeType
}
};
}
catch (error) {
const errorMessage = error instanceof Error ? error.message : String(error);
console.error(chalk_1.default.red(` ❌ Failed to save output: ${errorMessage}`));
return {
success: false,
error: errorMessage
};
}
}
/**
* Ensure the necessary directories exist for the output
*/
async ensureOutputDirectory(outputPath) {
const dirPath = path_1.default.dirname(outputPath);
await fs_1.promises.mkdir(dirPath, { recursive: true });
}
/**
* Get relative path for use in reports and links
*/
getRelativePath(outputPath, basePath) {
return path_1.default.relative(basePath, outputPath);
}
/**
* Generate standardized filename from pattern and context
*/
generateFilename(testType, config, context) {
const pattern = config.filenamePattern || testType;
let filename = test_output_types_js_1.OutputTypeUtils.replacePlaceholders(pattern, {
pageName: context.pageName,
testType: testType,
viewport: context.viewport,
...context.additionalData
});
// Ensure filename is safe for filesystem
filename = this.sanitizeFilename(filename);
return `${filename}.${config.fileExtension}`;
}
/**
* Sanitize filename for cross-platform compatibility
*/
sanitizeFilename(filename) {
return filename
.replace(/[<>:"/\\|?*]/g, '-') // Replace invalid characters
.replace(/\s+/g, '-') // Replace spaces with hyphens
.replace(/-+/g, '-') // Replace multiple hyphens with single
.replace(/^-|-$/g, '') // Remove leading/trailing hyphens
.toLowerCase();
}
/**
* Create a standardized test result with output information
*/
static createTestResult(testType, status, outputResult, error) {
const config = test_output_types_js_1.OUTPUT_CONFIGURATIONS[testType];
return {
testType,
status,
startTime: new Date(),
endTime: status !== 'pending' ? new Date() : undefined,
outputPath: outputResult?.outputPath,
outputType: config?.type,
error
};
}
/**
* Update an existing test result with completion information
*/
static completeTestResult(testResult, status, outputResult, error) {
return {
...testResult,
status,
endTime: new Date(),
outputPath: outputResult?.outputPath,
error
};
}
/**
* Get page name from URL (utility method)
*/
static getPageNameFromUrl(url) {
try {
const urlObj = new URL(url);
const pathSegments = urlObj.pathname.split('/').filter(segment => segment.length > 0);
if (pathSegments.length === 0) {
return 'home';
}
return pathSegments.join('-').toLowerCase().replace(/[^a-z0-9-]/g, '-');
}
catch (error) {
return 'unknown-page';
}
}
/**
* Filter test results by output type
*/
static filterResultsByOutputType(results, outputType) {
return results.filter(result => {
const config = test_output_types_js_1.OUTPUT_CONFIGURATIONS[result.testType];
return config?.type === outputType;
});
}
/**
* Group per-page results by page
*/
static groupPerPageResultsByPage(results) {
const perPageResults = this.filterResultsByOutputType(results, 'per-page');
const groupedResults = new Map();
for (const result of perPageResults) {
if (!result.outputPath)
continue;
// Extract page name from output path
const pathParts = result.outputPath.split(path_1.default.sep);
const sessionIndex = pathParts.findIndex(part => part.match(/^\d{2}-\d{2}-\d{4}_\d{2}-\d{2}$/));
if (sessionIndex >= 0 && pathParts.length > sessionIndex + 1) {
const pageName = pathParts[sessionIndex + 1];
if (!groupedResults.has(pageName)) {
groupedResults.set(pageName, []);
}
groupedResults.get(pageName).push(result);
}
}
return groupedResults;
}
/**
* Validate output configuration and provide helpful error messages
*/
static validateConfiguration(testType) {
const config = test_output_types_js_1.OUTPUT_CONFIGURATIONS[testType];
if (!config) {
return {
valid: false,
errors: [`No output configuration found for test type: ${testType}`]
};
}
return test_output_types_js_1.OutputTypeUtils.validateOutputConfig(config);
}
}
exports.StandardTestOutputHandler = StandardTestOutputHandler;
//# sourceMappingURL=test-output-handler.js.map