upskill-event-manager/tests/framework/core/BaseTest.js
Ben 7c9ca65cf2
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
feat: add comprehensive test framework and test files
- 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>
2025-08-29 23:23:26 -03:00

411 lines
No EOL
14 KiB
JavaScript

/**
* Base Test Class for HVAC Testing Framework
*
* Provides standardized test foundation with:
* - WordPress-aware setup and teardown
* - Screenshot and video management
* - Database isolation and cleanup
* - Error handling and recovery
* - Consistent test reporting
*
* @package HVAC_Community_Events
* @version 2.0.0
* @created 2025-08-27
*/
const { test, expect } = require('@playwright/test');
const fs = require('fs').promises;
const path = require('path');
const ConfigManager = require('./ConfigManager');
const AuthManager = require('./AuthManager');
const WordPressUtils = require('../utils/WordPressUtils');
const ScreenshotManager = require('../utils/ScreenshotManager');
class BaseTest {
constructor() {
this.config = ConfigManager;
this.authManager = AuthManager;
this.wpUtils = new WordPressUtils();
this.screenshotManager = new ScreenshotManager();
this.testStartTime = null;
this.testContext = null;
this.testMetadata = {};
}
/**
* Configure test with metadata and options
*/
configure(metadata = {}) {
this.testMetadata = {
category: metadata.category || 'general',
priority: metadata.priority || 'medium',
tags: metadata.tags || [],
requirements: metadata.requirements || [],
author: metadata.author || 'automated',
...metadata
};
return this;
}
/**
* Standard test setup - call this in beforeEach
*/
async setup(page, testInfo) {
this.testStartTime = Date.now();
this.testContext = {
page,
testInfo,
testId: this.generateTestId(testInfo),
screenshotPath: this.getScreenshotPath(testInfo)
};
// Set up error handling
this.setupErrorHandling(page);
// Set up WordPress environment
await this.setupWordPressEnvironment(page);
// Initialize test data if needed
if (this.config.get('testData.seedData')) {
await this.setupTestData();
}
// Take initial screenshot if configured
if (this.config.get('media.screenshotMode') === 'all') {
await this.screenshotManager.capture(page, 'test-start', this.testContext.screenshotPath);
}
console.log(`🧪 Test setup complete: ${testInfo.title}`);
}
/**
* Standard test teardown - call this in afterEach
*/
async teardown(page, testInfo) {
const testDuration = Date.now() - this.testStartTime;
const testPassed = testInfo.status === 'passed';
try {
// Take final screenshot if test failed or if configured for all tests
const screenshotMode = this.config.get('media.screenshotMode');
if (!testPassed || screenshotMode === 'all') {
await this.screenshotManager.capture(
page,
testPassed ? 'test-end' : 'test-failure',
this.testContext.screenshotPath
);
}
// Clean up test data if configured
if (this.config.get('testData.cleanupAfterTests')) {
await this.cleanupTestData();
}
// Log test completion
const status = testPassed ? '✅ PASSED' : '❌ FAILED';
console.log(`${status} ${testInfo.title} (${testDuration}ms)`);
// Record test metrics
await this.recordTestMetrics(testInfo, testDuration, testPassed);
} catch (error) {
console.error('Error during test teardown:', error.message);
}
}
/**
* Set up error handling for the page
*/
setupErrorHandling(page) {
// Handle console errors
page.on('console', msg => {
if (msg.type() === 'error') {
console.error(`🔴 Console Error: ${msg.text()}`);
}
});
// Handle page errors
page.on('pageerror', error => {
console.error(`🔴 Page Error: ${error.message}`);
});
// Handle failed requests (optional)
page.on('requestfailed', request => {
if (request.url().includes(this.config.get('app.baseUrl'))) {
console.warn(`⚠️ Request Failed: ${request.method()} ${request.url()}`);
}
});
}
/**
* Set up WordPress environment for test
*/
async setupWordPressEnvironment(page) {
// Set WordPress-specific headers and context
await page.setExtraHTTPHeaders({
'User-Agent': 'HVAC-Testing-Framework/2.0 Playwright',
'X-Test-Framework': 'HVAC-WordPress-Tests'
});
// Add WordPress helper scripts
await page.addInitScript(`
window.HVAC_TEST_MODE = true;
window.HVAC_TEST_ID = '${this.testContext.testId}';
window.HVAC_TEST_START = ${this.testStartTime};
// WordPress-specific test helpers
window.hvacTestHelpers = {
waitForAjax: function() {
return new Promise(resolve => {
if (typeof jQuery !== 'undefined' && jQuery.active === 0) {
resolve();
} else if (typeof jQuery !== 'undefined') {
jQuery(document).ajaxStop(resolve);
} else {
// Fallback for non-jQuery AJAX
setTimeout(resolve, 100);
}
});
},
waitForWordPress: function() {
return new Promise(resolve => {
if (document.readyState === 'complete') {
resolve();
} else {
window.addEventListener('load', resolve);
}
});
},
triggerWordPressEvent: function(eventName, data) {
if (typeof jQuery !== 'undefined') {
jQuery(document).trigger(eventName, data);
}
}
};
`);
// Flush rewrite rules if configured
if (this.config.get('wordpress.flushRewriteRules')) {
await this.wpUtils.flushRewriteRules();
}
// Clear cache if configured
if (this.config.get('wordpress.clearCache')) {
await this.wpUtils.clearCache();
}
}
/**
* Set up test data for the test
*/
async setupTestData() {
// This method can be overridden by specific test classes
// to set up role-specific test data
console.log('📋 Setting up test data...');
// Load fixtures if available
const fixtures = this.config.get('testData.fixtures');
if (fixtures && fixtures.users) {
await this.loadUserFixtures(fixtures.users);
}
}
/**
* Clean up test data after test
*/
async cleanupTestData() {
console.log('🧹 Cleaning up test data...');
// Clean up test-specific data
await this.wpUtils.cleanupTestData(this.testContext.testId);
}
/**
* Load user fixtures for testing
*/
async loadUserFixtures(fixturesPath) {
try {
const fixtures = JSON.parse(await fs.readFile(fixturesPath, 'utf8'));
// Process user fixtures as needed
console.log(`📂 Loaded user fixtures: ${Object.keys(fixtures).length} users`);
} catch (error) {
console.warn('Could not load user fixtures:', error.message);
}
}
/**
* Authenticate as specific user role
*/
async authenticateAs(page, role, options = {}) {
console.log(`🔐 Authenticating as: ${role}`);
return await this.authManager.authenticate(page, role, options);
}
/**
* Wait for WordPress-specific conditions
*/
async waitForWordPress(page, condition = 'ready') {
switch (condition) {
case 'ready':
await page.waitForFunction('document.readyState === "complete"');
break;
case 'ajax':
await page.waitForFunction(`
window.hvacTestHelpers && window.hvacTestHelpers.waitForAjax()
`);
break;
case 'dom-ready':
await page.waitForFunction('document.readyState !== "loading"');
break;
case 'network-idle':
await page.waitForLoadState('networkidle');
break;
default:
throw new Error(`Unknown WordPress condition: ${condition}`);
}
}
/**
* Take screenshot with context
*/
async takeScreenshot(page, name = 'screenshot', fullPage = false) {
return await this.screenshotManager.capture(
page,
name,
this.testContext.screenshotPath,
{ fullPage }
);
}
/**
* Assert WordPress-specific conditions
*/
async assertWordPressState(page, assertions) {
if (assertions.authenticated) {
// Check if user is authenticated
const isLoggedIn = await page.evaluate(() => {
return document.body.classList.contains('logged-in') ||
document.querySelector('#wpadminbar') !== null ||
window.location.pathname.includes('/wp-admin/');
});
expect(isLoggedIn).toBe(true);
}
if (assertions.role) {
// Verify user has expected role
const hasRole = await page.evaluate((expectedRole) => {
return document.body.classList.contains(`role-${expectedRole}`) ||
window.HVAC_AUTH_ROLE === expectedRole;
}, assertions.role);
expect(hasRole).toBe(true);
}
if (assertions.capability) {
// Check if user has specific capability
await expect(page.locator(`[data-capability="${assertions.capability}"]`)).toBeVisible();
}
if (assertions.nonce) {
// Verify WordPress nonce is present
const nonceExists = await page.evaluate((nonceName) => {
return document.querySelector(`[name="_wpnonce"]`) !== null ||
document.querySelector(`[name="${nonceName}"]`) !== null;
}, assertions.nonce);
expect(nonceExists).toBe(true);
}
}
/**
* Generate unique test ID
*/
generateTestId(testInfo) {
const timestamp = Date.now();
const testName = testInfo.title.replace(/[^a-zA-Z0-9]/g, '-').toLowerCase();
return `hvac-test-${testName}-${timestamp}`;
}
/**
* Get screenshot path for test
*/
getScreenshotPath(testInfo) {
const screenshotDir = this.config.get('media.screenshotDir');
const testName = testInfo.title.replace(/[^a-zA-Z0-9]/g, '-').toLowerCase();
const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
return path.join(screenshotDir, `${testName}-${timestamp}`);
}
/**
* Record test metrics for reporting
*/
async recordTestMetrics(testInfo, duration, passed) {
const metrics = {
testId: this.testContext.testId,
title: testInfo.title,
category: this.testMetadata.category,
priority: this.testMetadata.priority,
tags: this.testMetadata.tags,
duration,
passed,
timestamp: new Date().toISOString(),
environment: this.config.getEnvironment(),
metadata: this.testMetadata
};
// Write metrics to results directory
const resultsDir = this.config.get('reporting.outputDir');
const metricsFile = path.join(resultsDir, 'test-metrics.jsonl');
try {
await fs.mkdir(resultsDir, { recursive: true });
await fs.appendFile(metricsFile, JSON.stringify(metrics) + '\n');
} catch (error) {
console.warn('Could not record test metrics:', error.message);
}
}
/**
* Helper method to create WordPress-aware test
*/
static create(title, testFn, metadata = {}) {
return test(title, async ({ page }, testInfo) => {
const baseTest = new BaseTest();
baseTest.configure(metadata);
try {
await baseTest.setup(page, testInfo);
await testFn(page, testInfo, baseTest);
} finally {
await baseTest.teardown(page, testInfo);
}
});
}
/**
* Helper method to create WordPress-aware describe block
*/
static describe(title, testSuite, metadata = {}) {
return test.describe(title, () => {
// Set up common hooks for the test suite
test.beforeAll(async () => {
console.log(`📦 Starting test suite: ${title}`);
});
test.afterAll(async () => {
console.log(`📦 Completed test suite: ${title}`);
});
// Run the test suite
testSuite();
});
}
}
module.exports = BaseTest;