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>
374 lines
No EOL
11 KiB
JavaScript
374 lines
No EOL
11 KiB
JavaScript
/**
|
|
* Unified Configuration Manager for HVAC Testing Framework
|
|
*
|
|
* Provides centralized configuration management with environment-specific settings,
|
|
* WordPress integration, and test execution parameters.
|
|
*
|
|
* @package HVAC_Community_Events
|
|
* @version 2.0.0
|
|
* @created 2025-08-27
|
|
*/
|
|
|
|
const fs = require('fs');
|
|
const path = require('path');
|
|
|
|
class ConfigManager {
|
|
/**
|
|
* Configuration manager instance
|
|
*/
|
|
static instance = null;
|
|
|
|
/**
|
|
* Get configuration manager instance (Singleton pattern)
|
|
*/
|
|
static getInstance() {
|
|
if (!ConfigManager.instance) {
|
|
ConfigManager.instance = new ConfigManager();
|
|
}
|
|
return ConfigManager.instance;
|
|
}
|
|
|
|
constructor() {
|
|
this.config = null;
|
|
this.environment = process.env.NODE_ENV || process.env.HVAC_TEST_ENV || 'staging';
|
|
this.loadConfiguration();
|
|
}
|
|
|
|
/**
|
|
* Load configuration based on environment
|
|
*/
|
|
loadConfiguration() {
|
|
const configPath = path.resolve(__dirname, '../../environments/', `${this.environment}.config.js`);
|
|
|
|
try {
|
|
// Load environment-specific config
|
|
const envConfig = require(configPath);
|
|
|
|
// Load base configuration
|
|
const baseConfig = this.getBaseConfiguration();
|
|
|
|
// Merge configurations (environment overrides base)
|
|
this.config = this.deepMerge(baseConfig, envConfig);
|
|
|
|
console.log(`📋 Loaded configuration for environment: ${this.environment}`);
|
|
|
|
} catch (error) {
|
|
console.warn(`⚠️ Could not load environment config for ${this.environment}, using defaults`);
|
|
this.config = this.getBaseConfiguration();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get base configuration that applies to all environments
|
|
*/
|
|
getBaseConfiguration() {
|
|
return {
|
|
// Test Framework Settings
|
|
framework: {
|
|
name: 'HVAC WordPress Testing Framework',
|
|
version: '2.0.0',
|
|
timeout: 30000,
|
|
retries: 2,
|
|
parallel: true,
|
|
maxWorkers: 4,
|
|
testDataIsolation: true,
|
|
screenshotsOnFailure: true,
|
|
videosOnFailure: true,
|
|
reportFormat: 'html'
|
|
},
|
|
|
|
// WordPress Integration
|
|
wordpress: {
|
|
cliPath: 'wp',
|
|
adminPath: '/wp-admin/',
|
|
loginPath: '/wp-login.php',
|
|
customLoginPath: '/training-login/',
|
|
apiPath: '/wp-json/',
|
|
databaseIsolation: true,
|
|
flushRewriteRules: true,
|
|
clearCache: true
|
|
},
|
|
|
|
// User Roles and Capabilities
|
|
roles: {
|
|
trainer: {
|
|
role: 'hvac_trainer',
|
|
capabilities: [
|
|
'read',
|
|
'manage_hvac_events',
|
|
'edit_hvac_profile',
|
|
'view_hvac_dashboard',
|
|
'manage_attendees',
|
|
'email_attendees'
|
|
],
|
|
defaultPage: '/trainer/dashboard/'
|
|
},
|
|
masterTrainer: {
|
|
role: 'hvac_master_trainer',
|
|
capabilities: [
|
|
'read',
|
|
'manage_hvac_events',
|
|
'edit_hvac_profile',
|
|
'view_hvac_dashboard',
|
|
'manage_attendees',
|
|
'email_attendees',
|
|
'manage_all_events',
|
|
'approve_trainers',
|
|
'edit_trainer_profiles',
|
|
'manage_announcements',
|
|
'view_reports',
|
|
'manage_imports'
|
|
],
|
|
defaultPage: '/master-trainer/master-dashboard/'
|
|
},
|
|
admin: {
|
|
role: 'administrator',
|
|
capabilities: ['manage_options'],
|
|
defaultPage: '/wp-admin/'
|
|
}
|
|
},
|
|
|
|
// Browser Settings
|
|
browser: {
|
|
type: 'chromium',
|
|
headless: process.env.CI === 'true',
|
|
slowMo: process.env.CI === 'true' ? 0 : 100,
|
|
viewport: {
|
|
width: 1280,
|
|
height: 720
|
|
},
|
|
mobileViewport: {
|
|
width: 375,
|
|
height: 667
|
|
},
|
|
args: [
|
|
'--disable-dev-shm-usage',
|
|
'--no-sandbox',
|
|
'--disable-setuid-sandbox'
|
|
]
|
|
},
|
|
|
|
// Screenshot and Video Settings
|
|
media: {
|
|
screenshotDir: './test-results/screenshots',
|
|
videoDir: './test-results/videos',
|
|
screenshotMode: 'only-on-failure',
|
|
videoMode: 'retain-on-failure',
|
|
quality: 80,
|
|
fullPage: false
|
|
},
|
|
|
|
// Test Data Management
|
|
testData: {
|
|
seedData: true,
|
|
cleanupAfterTests: true,
|
|
isolateTransactions: true,
|
|
backupDatabase: false,
|
|
fixtures: {
|
|
users: './fixtures/test-users.json',
|
|
events: './fixtures/test-events.json',
|
|
venues: './fixtures/test-venues.json'
|
|
}
|
|
},
|
|
|
|
// Selectors for stable element identification
|
|
selectors: {
|
|
dataTestIdAttribute: 'data-testid',
|
|
roleAttribute: 'data-role',
|
|
pageAttribute: 'data-page',
|
|
formAttribute: 'data-form',
|
|
buttonAttribute: 'data-action'
|
|
},
|
|
|
|
// Reporting
|
|
reporting: {
|
|
outputDir: './test-results/reports',
|
|
formats: ['html', 'json', 'junit'],
|
|
includeScreenshots: true,
|
|
includeTimings: true,
|
|
groupByCategory: true
|
|
}
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Get configuration value by path (e.g., 'browser.viewport.width')
|
|
*/
|
|
get(path, defaultValue = null) {
|
|
return this.getNestedValue(this.config, path.split('.'), defaultValue);
|
|
}
|
|
|
|
/**
|
|
* Set configuration value by path
|
|
*/
|
|
set(path, value) {
|
|
this.setNestedValue(this.config, path.split('.'), value);
|
|
}
|
|
|
|
/**
|
|
* Get environment name
|
|
*/
|
|
getEnvironment() {
|
|
return this.environment;
|
|
}
|
|
|
|
/**
|
|
* Get full configuration object
|
|
*/
|
|
getAll() {
|
|
return { ...this.config };
|
|
}
|
|
|
|
/**
|
|
* Get user configuration for specific role
|
|
*/
|
|
getUserConfig(role) {
|
|
const roleConfig = this.get(`roles.${role}`);
|
|
const envConfig = this.get(`environments.users.${role}`);
|
|
|
|
return {
|
|
...roleConfig,
|
|
...envConfig
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Get WordPress CLI configuration
|
|
*/
|
|
getWpCliConfig() {
|
|
return {
|
|
path: this.get('wordpress.cliPath'),
|
|
url: this.get('app.baseUrl'),
|
|
dbPrefix: this.get('database.prefix', 'wp_'),
|
|
adminUser: this.get('environments.users.admin.username'),
|
|
adminEmail: this.get('environments.users.admin.email')
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Get browser launch configuration
|
|
*/
|
|
getBrowserConfig() {
|
|
return {
|
|
...this.get('browser'),
|
|
timeout: this.get('framework.timeout'),
|
|
actionTimeout: this.get('framework.timeout') * 0.75
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Check if feature is enabled
|
|
*/
|
|
isFeatureEnabled(feature) {
|
|
return this.get(`features.${feature}`, false);
|
|
}
|
|
|
|
/**
|
|
* Get environment-specific database configuration
|
|
*/
|
|
getDatabaseConfig() {
|
|
return this.get('database', {});
|
|
}
|
|
|
|
/**
|
|
* Get test execution parameters
|
|
*/
|
|
getExecutionConfig() {
|
|
return {
|
|
timeout: this.get('framework.timeout'),
|
|
retries: this.get('framework.retries'),
|
|
parallel: this.get('framework.parallel'),
|
|
maxWorkers: this.get('framework.maxWorkers'),
|
|
globalTimeout: this.get('framework.timeout') * 10
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Validate configuration completeness
|
|
*/
|
|
validate() {
|
|
const required = [
|
|
'app.baseUrl',
|
|
'environments.users.trainer',
|
|
'environments.users.masterTrainer'
|
|
];
|
|
|
|
const missing = required.filter(path => this.get(path) === null);
|
|
|
|
if (missing.length > 0) {
|
|
throw new Error(`Missing required configuration: ${missing.join(', ')}`);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Deep merge two configuration objects
|
|
*/
|
|
deepMerge(target, source) {
|
|
const result = { ...target };
|
|
|
|
for (const key in source) {
|
|
if (source[key] && typeof source[key] === 'object' && !Array.isArray(source[key])) {
|
|
result[key] = this.deepMerge(target[key] || {}, source[key]);
|
|
} else {
|
|
result[key] = source[key];
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Get nested value from object by path array
|
|
*/
|
|
getNestedValue(obj, path, defaultValue) {
|
|
let current = obj;
|
|
|
|
for (const key of path) {
|
|
if (current === null || current === undefined || !current.hasOwnProperty(key)) {
|
|
return defaultValue;
|
|
}
|
|
current = current[key];
|
|
}
|
|
|
|
return current;
|
|
}
|
|
|
|
/**
|
|
* Set nested value in object by path array
|
|
*/
|
|
setNestedValue(obj, path, value) {
|
|
let current = obj;
|
|
|
|
for (let i = 0; i < path.length - 1; i++) {
|
|
const key = path[i];
|
|
if (!current[key] || typeof current[key] !== 'object') {
|
|
current[key] = {};
|
|
}
|
|
current = current[key];
|
|
}
|
|
|
|
current[path[path.length - 1]] = value;
|
|
}
|
|
|
|
/**
|
|
* Export configuration to file for debugging
|
|
*/
|
|
exportToFile(filePath = null) {
|
|
const outputPath = filePath || path.resolve('./test-results/config-export.json');
|
|
const configData = {
|
|
environment: this.environment,
|
|
timestamp: new Date().toISOString(),
|
|
config: this.config
|
|
};
|
|
|
|
fs.writeFileSync(outputPath, JSON.stringify(configData, null, 2));
|
|
console.log(`📁 Configuration exported to: ${outputPath}`);
|
|
|
|
return outputPath;
|
|
}
|
|
}
|
|
|
|
// Export singleton instance
|
|
module.exports = ConfigManager.getInstance(); |