upskill-event-manager/wordpress-dev/tests/e2e/utils/LogIntegrator.ts
bengizmo d6211ee364 feat(testing): Implement HVAC_Test_User_Factory and update .gitignore
- 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.
2025-04-14 17:41:36 -03:00

133 lines
No EOL
4.1 KiB
TypeScript

import { LogParser, LogEntry } from './logParser';
import fs from 'fs/promises';
import path from 'path';
import { STAGING_CONFIG } from '../../../playwright.config';
import { Client } from 'ssh2';
export interface LogSource {
name: string;
path: string;
type: 'wordpress' | 'php' | 'nginx-access' | 'nginx-error';
}
export class LogIntegrator {
private logParser: LogParser;
private sources: LogSource[] = [
{
name: 'WordPress Debug',
path: `${STAGING_CONFIG.path}/wp-content/debug.log`,
type: 'wordpress'
},
{
name: 'PHP Error',
path: '/var/log/php_errors.log',
type: 'php'
},
{
name: 'Nginx Access',
path: '/var/log/nginx/access.log',
type: 'nginx-access'
},
{
name: 'Nginx Error',
path: '/var/log/nginx/error.log',
type: 'nginx-error'
}
];
constructor() {
this.logParser = new LogParser();
}
async collectLogs(testStartTime: Date, testEndTime: Date): Promise<Map<string, LogEntry[]>> {
const logs = new Map<string, LogEntry[]>();
for (const source of this.sources) {
const entries = await this.fetchAndFilterLogs(source, testStartTime, testEndTime);
logs.set(source.name, entries);
}
return logs;
}
async assertLogCondition(condition: {
source: string;
level?: 'INFO' | 'WARNING' | 'ERROR';
message?: string | RegExp;
component?: string;
timeWindow?: number;
}): Promise<boolean> {
const source = this.sources.find(s => s.name === condition.source);
if (!source) throw new Error(`Unknown log source: ${condition.source}`);
const entries = await this.logParser.parseLogFile(source.path);
return entries.some(entry => {
if (condition.level && entry.level !== condition.level) return false;
if (condition.component && entry.component !== condition.component) return false;
if (condition.message) {
if (condition.message instanceof RegExp) {
if (!condition.message.test(entry.message)) return false;
} else {
if (entry.message !== condition.message) return false;
}
}
return true;
});
}
private async fetchAndFilterLogs(
source: LogSource,
startTime: Date,
endTime: Date
): Promise<LogEntry[]> {
const entries = await this.logParser.parseLogFile(source.path);
return entries.filter(entry => {
const timestamp = new Date(entry.timestamp);
return timestamp >= startTime && timestamp <= endTime;
});
}
async correlateTestAction(
actionName: string,
timestamp: Date,
timeWindow: number = 5000
): Promise<LogEntry[]> {
const correlatedEntries: LogEntry[] = [];
const startTime = new Date(timestamp.getTime() - timeWindow);
const endTime = new Date(timestamp.getTime() + timeWindow);
for (const source of this.sources) {
const entries = await this.fetchAndFilterLogs(source, startTime, endTime);
correlatedEntries.push(...entries);
}
return correlatedEntries.sort((a, b) =>
new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime()
);
}
async saveLogsToFile(
outputPath: string,
logs: Map<string, LogEntry[]>
): Promise<void> {
const output: Record<string, any> = {};
logs.forEach((entries, source) => {
output[source] = entries.map(entry => ({
timestamp: entry.timestamp,
level: entry.level,
component: entry.component,
message: entry.message,
context: entry.context
}));
});
await fs.mkdir(path.dirname(outputPath), { recursive: true });
await fs.writeFile(
outputPath,
JSON.stringify(output, null, 2)
);
}
}