Some checks are pending
HVAC Plugin CI/CD Pipeline / Security Analysis (push) Waiting to run
HVAC Plugin CI/CD Pipeline / Code Quality & Standards (push) Waiting to run
HVAC Plugin CI/CD Pipeline / Unit Tests (push) Waiting to run
HVAC Plugin CI/CD Pipeline / Integration Tests (push) Waiting to run
HVAC Plugin CI/CD Pipeline / Deploy to Staging (push) Blocked by required conditions
HVAC Plugin CI/CD Pipeline / Deploy to Production (push) Blocked by required conditions
HVAC Plugin CI/CD Pipeline / Notification (push) Blocked by required conditions
Security Monitoring & Compliance / Dependency Vulnerability Scan (push) Waiting to run
Security Monitoring & Compliance / Secrets & Credential Scan (push) Waiting to run
Security Monitoring & Compliance / WordPress Security Analysis (push) Waiting to run
Security Monitoring & Compliance / Static Code Security Analysis (push) Waiting to run
Security Monitoring & Compliance / Security Compliance Validation (push) Waiting to run
Security Monitoring & Compliance / Security Summary Report (push) Blocked by required conditions
Security Monitoring & Compliance / Security Team Notification (push) Blocked by required conditions
- Add 90+ test files including E2E, unit, and integration tests - Implement Page Object Model (POM) architecture - Add Docker testing environment with comprehensive services - Include modernized test framework with error recovery - Add specialized test suites for master trainer and trainer workflows - Update .gitignore to properly track test infrastructure 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
281 lines
No EOL
8.6 KiB
JavaScript
281 lines
No EOL
8.6 KiB
JavaScript
/**
|
|
* WordPress Error Detection Utility
|
|
* Detects critical WordPress errors that would block testing
|
|
*
|
|
* Usage:
|
|
* const errorDetector = new WordPressErrorDetector(page);
|
|
* const error = await errorDetector.detectCriticalErrors();
|
|
* if (error) {
|
|
* throw new Error(`Critical WordPress Error: ${error.type} - ${error.message}`);
|
|
* }
|
|
*/
|
|
|
|
class WordPressErrorDetector {
|
|
constructor(page) {
|
|
this.page = page;
|
|
}
|
|
|
|
/**
|
|
* Detect critical WordPress errors that would block testing
|
|
* @returns {Object|null} Error object or null if no errors
|
|
*/
|
|
async detectCriticalErrors() {
|
|
try {
|
|
// Check for fatal PHP errors
|
|
const fatalError = await this.checkFatalPhpError();
|
|
if (fatalError) return fatalError;
|
|
|
|
// Check for database connection errors
|
|
const dbError = await this.checkDatabaseError();
|
|
if (dbError) return dbError;
|
|
|
|
// Check for WordPress maintenance mode
|
|
const maintenanceError = await this.checkMaintenanceMode();
|
|
if (maintenanceError) return maintenanceError;
|
|
|
|
// Check for plugin/theme errors
|
|
const pluginError = await this.checkPluginThemeErrors();
|
|
if (pluginError) return pluginError;
|
|
|
|
// Check for HTTP error codes in page response
|
|
const httpError = await this.checkHttpErrors();
|
|
if (httpError) return httpError;
|
|
|
|
return null;
|
|
} catch (e) {
|
|
return {
|
|
type: 'DETECTION_ERROR',
|
|
message: `Error while detecting WordPress errors: ${e.message}`,
|
|
blocking: true
|
|
};
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Check for fatal PHP errors
|
|
*/
|
|
async checkFatalPhpError() {
|
|
const pageContent = await this.page.content();
|
|
|
|
const fatalErrorPatterns = [
|
|
/Fatal error:/i,
|
|
/Parse error:/i,
|
|
/Fatal Error:/i,
|
|
/PHP Fatal error:/i,
|
|
/Uncaught Error:/i,
|
|
/Call to undefined function/i,
|
|
/Maximum execution time exceeded/i,
|
|
/Allowed memory size.*exhausted/i
|
|
];
|
|
|
|
for (const pattern of fatalErrorPatterns) {
|
|
if (pattern.test(pageContent)) {
|
|
const match = pageContent.match(pattern);
|
|
return {
|
|
type: 'FATAL_PHP_ERROR',
|
|
message: match ? match[0] : 'Fatal PHP error detected',
|
|
blocking: true,
|
|
details: this.extractErrorContext(pageContent, pattern)
|
|
};
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* Check for database connection errors
|
|
*/
|
|
async checkDatabaseError() {
|
|
const pageContent = await this.page.content();
|
|
|
|
const dbErrorPatterns = [
|
|
/Error establishing a database connection/i,
|
|
/Database connection error/i,
|
|
/Can't connect to MySQL server/i,
|
|
/Access denied for user/i,
|
|
/MySQL server has gone away/i,
|
|
/Lost connection to MySQL server/i
|
|
];
|
|
|
|
for (const pattern of dbErrorPatterns) {
|
|
if (pattern.test(pageContent)) {
|
|
return {
|
|
type: 'DATABASE_ERROR',
|
|
message: 'Database connection error detected',
|
|
blocking: true,
|
|
details: this.extractErrorContext(pageContent, pattern)
|
|
};
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* Check for WordPress maintenance mode
|
|
*/
|
|
async checkMaintenanceMode() {
|
|
const pageContent = await this.page.content();
|
|
|
|
const maintenancePatterns = [
|
|
/Briefly unavailable for scheduled maintenance/i,
|
|
/The site is temporarily down for maintenance/i,
|
|
/Maintenance mode is on/i
|
|
];
|
|
|
|
for (const pattern of maintenancePatterns) {
|
|
if (pattern.test(pageContent)) {
|
|
return {
|
|
type: 'MAINTENANCE_MODE',
|
|
message: 'WordPress site is in maintenance mode',
|
|
blocking: true,
|
|
temporary: true
|
|
};
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* Check for plugin/theme errors
|
|
*/
|
|
async checkPluginThemeErrors() {
|
|
const pageContent = await this.page.content();
|
|
|
|
const pluginErrorPatterns = [
|
|
/Plugin could not be activated because it triggered a fatal error/i,
|
|
/The plugin generated.*characters of unexpected output/i,
|
|
/There has been a critical error on this website/i,
|
|
/Something went wrong/i
|
|
];
|
|
|
|
for (const pattern of pluginErrorPatterns) {
|
|
if (pattern.test(pageContent)) {
|
|
return {
|
|
type: 'PLUGIN_THEME_ERROR',
|
|
message: 'Plugin or theme error detected',
|
|
blocking: true,
|
|
details: this.extractErrorContext(pageContent, pattern)
|
|
};
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* Check for HTTP error responses
|
|
*/
|
|
async checkHttpErrors() {
|
|
try {
|
|
const response = this.page.response();
|
|
if (!response) return null;
|
|
|
|
const status = response.status();
|
|
if (status >= 500) {
|
|
return {
|
|
type: 'HTTP_SERVER_ERROR',
|
|
message: `HTTP ${status} error`,
|
|
blocking: true,
|
|
statusCode: status,
|
|
statusText: response.statusText()
|
|
};
|
|
}
|
|
|
|
if (status === 404) {
|
|
const url = response.url();
|
|
// Only consider 404 blocking for critical WordPress files
|
|
if (url.includes('wp-admin') || url.includes('wp-login')) {
|
|
return {
|
|
type: 'HTTP_NOT_FOUND',
|
|
message: `Critical WordPress resource not found: ${url}`,
|
|
blocking: true,
|
|
statusCode: status
|
|
};
|
|
}
|
|
}
|
|
|
|
return null;
|
|
} catch (e) {
|
|
return null; // Non-blocking if we can't check HTTP status
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Extract error context from page content
|
|
*/
|
|
extractErrorContext(content, pattern) {
|
|
try {
|
|
const match = content.match(pattern);
|
|
if (!match) return null;
|
|
|
|
const startIndex = match.index;
|
|
const contextStart = Math.max(0, startIndex - 200);
|
|
const contextEnd = Math.min(content.length, startIndex + 500);
|
|
|
|
return content.substring(contextStart, contextEnd).replace(/\s+/g, ' ').trim();
|
|
} catch (e) {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Check if the current page has WordPress admin access
|
|
*/
|
|
async checkWordPressAccess() {
|
|
try {
|
|
const title = await this.page.title();
|
|
const url = this.page.url();
|
|
|
|
// Check for WordPress indicators
|
|
const isWordPress = title.toLowerCase().includes('wordpress') ||
|
|
await this.page.$('body.wp-admin') !== null ||
|
|
await this.page.$('body.login') !== null ||
|
|
url.includes('wp-admin') ||
|
|
url.includes('wp-login');
|
|
|
|
if (!isWordPress) {
|
|
return {
|
|
type: 'WORDPRESS_ACCESS_ERROR',
|
|
message: 'Unable to access WordPress - site may be down or not responding',
|
|
blocking: true,
|
|
url: url,
|
|
title: title
|
|
};
|
|
}
|
|
|
|
return null;
|
|
} catch (e) {
|
|
return {
|
|
type: 'ACCESS_CHECK_ERROR',
|
|
message: `Error checking WordPress access: ${e.message}`,
|
|
blocking: true
|
|
};
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get comprehensive error report
|
|
*/
|
|
async getErrorReport() {
|
|
const errors = [];
|
|
|
|
const criticalError = await this.detectCriticalErrors();
|
|
if (criticalError) errors.push(criticalError);
|
|
|
|
const accessError = await this.checkWordPressAccess();
|
|
if (accessError) errors.push(accessError);
|
|
|
|
return {
|
|
hasErrors: errors.length > 0,
|
|
blockingErrors: errors.filter(e => e.blocking),
|
|
allErrors: errors,
|
|
timestamp: new Date().toISOString(),
|
|
url: this.page.url()
|
|
};
|
|
}
|
|
}
|
|
|
|
module.exports = WordPressErrorDetector; |