- Add HVAC_Test_User_Factory class with: * User creation with specific roles * Multiple role support * Persona management system * Account cleanup integration - Create comprehensive test suite in HVAC_Test_User_Factory_Test.php - Update testing improvement plan documentation - Add implementation decisions to project memory bank - Restructure .gitignore with: * Whitelist approach for better file management * Explicit backup exclusions * Specific bin directory inclusions Part of the Account Management component from the testing framework improvement plan.
187 lines
No EOL
5.8 KiB
TypeScript
187 lines
No EOL
5.8 KiB
TypeScript
import { TestInfo } from '@playwright/test';
|
|
import fs from 'fs/promises';
|
|
import path from 'path';
|
|
|
|
export enum VerbosityLevel {
|
|
SILENT = 0,
|
|
MINIMAL = 1,
|
|
NORMAL = 2,
|
|
VERBOSE = 3,
|
|
DEBUG = 4,
|
|
ERROR = 5 // Added ERROR level for error logging
|
|
}
|
|
|
|
export interface VerbosityOptions {
|
|
consoleOutput: boolean;
|
|
screenshots: boolean;
|
|
htmlDumps: boolean;
|
|
fileLogs: boolean;
|
|
performanceMetrics: boolean;
|
|
}
|
|
|
|
export class VerbosityController {
|
|
private static instance: VerbosityController;
|
|
private currentLevel: VerbosityLevel;
|
|
private options: Map<VerbosityLevel, VerbosityOptions>;
|
|
|
|
private constructor() {
|
|
this.currentLevel = VerbosityLevel.NORMAL; // Default level
|
|
this.options = new Map([
|
|
[VerbosityLevel.SILENT, {
|
|
consoleOutput: false,
|
|
screenshots: false,
|
|
htmlDumps: false,
|
|
fileLogs: false,
|
|
performanceMetrics: false
|
|
}],
|
|
[VerbosityLevel.MINIMAL, {
|
|
consoleOutput: true,
|
|
screenshots: false,
|
|
htmlDumps: false,
|
|
fileLogs: true,
|
|
performanceMetrics: false
|
|
}],
|
|
[VerbosityLevel.NORMAL, {
|
|
consoleOutput: true,
|
|
screenshots: true,
|
|
htmlDumps: true,
|
|
fileLogs: true,
|
|
performanceMetrics: true
|
|
}],
|
|
[VerbosityLevel.VERBOSE, {
|
|
consoleOutput: true,
|
|
screenshots: true,
|
|
htmlDumps: true,
|
|
fileLogs: true,
|
|
performanceMetrics: true
|
|
}],
|
|
[VerbosityLevel.DEBUG, {
|
|
consoleOutput: true,
|
|
screenshots: true,
|
|
htmlDumps: true,
|
|
fileLogs: true,
|
|
performanceMetrics: true
|
|
}],
|
|
[VerbosityLevel.ERROR, {
|
|
consoleOutput: true,
|
|
screenshots: true,
|
|
htmlDumps: true,
|
|
fileLogs: true,
|
|
performanceMetrics: true
|
|
}]
|
|
]);
|
|
}
|
|
|
|
static getInstance(): VerbosityController {
|
|
if (!VerbosityController.instance) {
|
|
VerbosityController.instance = new VerbosityController();
|
|
}
|
|
return VerbosityController.instance;
|
|
}
|
|
|
|
setLevel(level: VerbosityLevel): void {
|
|
this.currentLevel = level;
|
|
}
|
|
|
|
getLevel(): VerbosityLevel {
|
|
return this.currentLevel;
|
|
}
|
|
|
|
shouldLog(messageLevel: VerbosityLevel): boolean {
|
|
return messageLevel <= this.currentLevel;
|
|
}
|
|
|
|
getOptions(): VerbosityOptions {
|
|
return this.options.get(this.currentLevel) || this.options.get(VerbosityLevel.NORMAL)!;
|
|
}
|
|
|
|
async log(
|
|
message: string,
|
|
level: VerbosityLevel,
|
|
testInfo?: TestInfo,
|
|
error?: Error
|
|
): Promise<void> {
|
|
if (!this.shouldLog(level)) return;
|
|
|
|
const options = this.getOptions();
|
|
if (!options.consoleOutput) return;
|
|
|
|
const timestamp = new Date().toISOString();
|
|
const prefix = `[${timestamp}] [${VerbosityLevel[level]}]`;
|
|
|
|
// Console output
|
|
if (level === VerbosityLevel.ERROR || error) {
|
|
console.error(`${prefix} ${message}`, error || '');
|
|
} else {
|
|
console.log(`${prefix} ${message}`);
|
|
}
|
|
|
|
// File logging
|
|
if (options.fileLogs && testInfo) {
|
|
await this.logToFile(testInfo, `${prefix} ${message}\n${error ? error.stack : ''}\n`);
|
|
}
|
|
}
|
|
|
|
async shouldTakeScreenshot(testInfo: TestInfo): Promise<boolean> {
|
|
const options = this.getOptions();
|
|
if (!options.screenshots) return false;
|
|
|
|
// Additional conditions based on verbosity level
|
|
switch (this.currentLevel) {
|
|
case VerbosityLevel.VERBOSE:
|
|
case VerbosityLevel.DEBUG:
|
|
return true; // Take screenshots for all actions
|
|
case VerbosityLevel.NORMAL:
|
|
return testInfo.status !== 'passed'; // Only for non-passing tests
|
|
case VerbosityLevel.ERROR:
|
|
return testInfo.status === 'failed'; // Only for failed tests
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
|
|
async shouldCaptureHtmlDump(testInfo: TestInfo): Promise<boolean> {
|
|
const options = this.getOptions();
|
|
if (!options.htmlDumps) return false;
|
|
|
|
// Additional conditions based on verbosity level
|
|
switch (this.currentLevel) {
|
|
case VerbosityLevel.DEBUG:
|
|
case VerbosityLevel.VERBOSE:
|
|
return true; // Capture all HTML dumps
|
|
case VerbosityLevel.NORMAL:
|
|
return testInfo.status !== 'passed'; // Only for non-passing tests
|
|
case VerbosityLevel.ERROR:
|
|
return testInfo.status === 'failed'; // Only for failed tests
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
|
|
shouldCapturePerformanceMetrics(): boolean {
|
|
return this.getOptions().performanceMetrics;
|
|
}
|
|
|
|
private async logToFile(testInfo: TestInfo, message: string): Promise<void> {
|
|
const logDir = path.join(testInfo.project.outputDir, 'logs');
|
|
const logFile = path.join(logDir, `${testInfo.testId}.log`);
|
|
|
|
await fs.mkdir(logDir, { recursive: true });
|
|
await fs.appendFile(logFile, message);
|
|
}
|
|
}
|
|
|
|
// Command line argument parser for verbosity
|
|
export function parseVerbosityArgs(args: string[]): VerbosityLevel {
|
|
const verbosityArg = args.find(arg =>
|
|
arg.startsWith('--verbosity=') ||
|
|
arg.startsWith('-v=')
|
|
);
|
|
|
|
if (!verbosityArg) return VerbosityLevel.NORMAL;
|
|
|
|
const value = verbosityArg.split('=')[1].toUpperCase();
|
|
const level = VerbosityLevel[value as keyof typeof VerbosityLevel];
|
|
|
|
return typeof level === 'number' ? level : VerbosityLevel.NORMAL;
|
|
} |