upskill-event-manager/tests/framework/browser/BrowserManager.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

249 lines
No EOL
6.5 KiB
JavaScript

/**
* Browser Manager - Centralized browser lifecycle management
* Provides singleton browser instances with proper cleanup and configuration
*/
const { chromium, firefox, webkit } = require('playwright');
const path = require('path');
class BrowserManager {
constructor() {
this.browser = null;
this.context = null;
this.page = null;
this.config = null;
}
/**
* Initialize browser with configuration
* @param {Object} config - Browser configuration
* @returns {Promise<void>}
*/
async initialize(config) {
this.config = {
browserType: 'chromium',
headless: true,
slowMo: 0,
timeout: 30000,
viewport: { width: 1280, height: 720 },
video: false,
screenshot: 'only-on-failure',
...config
};
// Launch browser based on type
const browserType = this._getBrowserType(this.config.browserType);
this.browser = await browserType.launch({
headless: this.config.headless,
slowMo: this.config.slowMo,
args: this._getBrowserArgs()
});
// Create context with configuration
this.context = await this.browser.newContext({
viewport: this.config.viewport,
video: this.config.video ? {
dir: path.join(process.cwd(), 'tests/evidence/videos')
} : undefined,
recordVideo: this.config.video ? {
dir: path.join(process.cwd(), 'tests/evidence/videos'),
size: this.config.viewport
} : undefined
});
// Set default timeout
this.context.setDefaultTimeout(this.config.timeout);
// Create initial page
this.page = await this.context.newPage();
// Set up page defaults
await this._setupPageDefaults();
return { browser: this.browser, context: this.context, page: this.page };
}
/**
* Get new page instance
* @returns {Promise<Page>}
*/
async getNewPage() {
if (!this.context) {
throw new Error('Browser not initialized. Call initialize() first.');
}
return await this.context.newPage();
}
/**
* Get current page
* @returns {Page}
*/
getCurrentPage() {
if (!this.page) {
throw new Error('No active page. Browser may not be initialized.');
}
return this.page;
}
/**
* Close current page
* @returns {Promise<void>}
*/
async closePage() {
if (this.page) {
await this.page.close();
this.page = null;
}
}
/**
* Clean shutdown of browser
* @returns {Promise<void>}
*/
async cleanup() {
try {
if (this.page) {
await this.page.close();
this.page = null;
}
if (this.context) {
await this.context.close();
this.context = null;
}
if (this.browser) {
await this.browser.close();
this.browser = null;
}
} catch (error) {
console.warn('Error during browser cleanup:', error.message);
}
}
/**
* Take screenshot of current page
* @param {string} filename - Screenshot filename
* @param {Object} options - Screenshot options
* @returns {Promise<string>} Path to screenshot
*/
async takeScreenshot(filename, options = {}) {
if (!this.page) {
throw new Error('No active page for screenshot');
}
const screenshotPath = path.join(
process.cwd(),
'tests/evidence/screenshots',
filename
);
await this.page.screenshot({
path: screenshotPath,
fullPage: true,
...options
});
return screenshotPath;
}
/**
* Wait for page load with network idle
* @param {number} timeout - Wait timeout
* @returns {Promise<void>}
*/
async waitForPageLoad(timeout = 30000) {
if (!this.page) return;
try {
await this.page.waitForLoadState('networkidle', { timeout });
} catch (error) {
console.warn('Page load wait timeout:', error.message);
}
}
/**
* Get browser type instance
* @param {string} browserType - Browser type name
* @returns {BrowserType}
* @private
*/
_getBrowserType(browserType) {
switch (browserType.toLowerCase()) {
case 'firefox':
return firefox;
case 'webkit':
case 'safari':
return webkit;
case 'chromium':
case 'chrome':
default:
return chromium;
}
}
/**
* Get browser launch arguments
* @returns {string[]}
* @private
*/
_getBrowserArgs() {
return [
'--no-sandbox',
'--disable-dev-shm-usage',
'--disable-extensions',
'--disable-background-timer-throttling',
'--disable-backgrounding-occluded-windows',
'--disable-renderer-backgrounding',
'--disable-features=TranslateUI',
'--no-default-browser-check',
'--no-first-run'
];
}
/**
* Set up default page configuration
* @returns {Promise<void>}
* @private
*/
async _setupPageDefaults() {
if (!this.page) return;
// Set user agent
await this.page.setExtraHTTPHeaders({
'User-Agent': 'HVAC-Testing-Framework/2.0'
});
// Set up console logging
this.page.on('console', (msg) => {
if (msg.type() === 'error') {
console.error('Browser console error:', msg.text());
}
});
// Set up page error handling
this.page.on('pageerror', (error) => {
console.error('Page error:', error.message);
});
// Set up network error handling
this.page.on('requestfailed', (request) => {
console.warn('Request failed:', request.url(), request.failure()?.errorText);
});
}
}
// Singleton instance
let browserManager = null;
/**
* Get singleton BrowserManager instance
* @returns {BrowserManager}
*/
function getBrowserManager() {
if (!browserManager) {
browserManager = new BrowserManager();
}
return browserManager;
}
module.exports = { BrowserManager, getBrowserManager };