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>
295 lines
No EOL
9 KiB
JavaScript
295 lines
No EOL
9 KiB
JavaScript
/**
|
|
* Authentication Setup and State Management
|
|
*
|
|
* Provides shared authentication utilities for all HVAC test suites:
|
|
* - Role-based authentication (trainer, master_trainer, admin)
|
|
* - Authentication state storage and reuse
|
|
* - Login/logout helpers
|
|
* - Session management
|
|
* - Security best practices
|
|
*
|
|
* @package HVAC_Community_Events
|
|
* @version 3.0.0
|
|
* @created 2025-08-20
|
|
*/
|
|
|
|
const { expect } = require('@playwright/test');
|
|
const path = require('path');
|
|
const fs = require('fs').promises;
|
|
|
|
// Authentication configuration
|
|
const AUTH_CONFIG = {
|
|
baseUrl: process.env.UPSKILL_STAGING_URL || 'https://upskill-staging.measurequick.com',
|
|
loginUrl: '/training-login/',
|
|
wpLoginUrl: '/wp-login.php',
|
|
timeout: 15000,
|
|
storageDir: path.join(__dirname, '../.auth'),
|
|
|
|
// Test user credentials for different roles
|
|
users: {
|
|
trainer: {
|
|
email: 'test_trainer@example.com',
|
|
password: 'TestTrainer123!',
|
|
role: 'hvac_trainer',
|
|
dashboardPath: '/trainer/dashboard/',
|
|
storageFile: 'trainer-auth.json'
|
|
},
|
|
master_trainer: {
|
|
email: 'test_master@example.com',
|
|
password: 'TestMaster123!',
|
|
role: 'hvac_master_trainer',
|
|
dashboardPath: '/master-trainer/master-dashboard/',
|
|
storageFile: 'master-trainer-auth.json'
|
|
},
|
|
admin: {
|
|
email: 'admin@example.com',
|
|
password: 'AdminTest123!',
|
|
role: 'administrator',
|
|
dashboardPath: '/wp-admin/',
|
|
storageFile: 'admin-auth.json'
|
|
}
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Ensure authentication storage directory exists
|
|
*/
|
|
async function ensureAuthStorageDir() {
|
|
try {
|
|
await fs.mkdir(AUTH_CONFIG.storageDir, { recursive: true });
|
|
} catch (error) {
|
|
console.warn('Could not create auth storage directory:', error.message);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Save authentication state to file
|
|
* @param {string} userType - User type (trainer, master_trainer, admin)
|
|
* @param {Object} context - Browser context with authentication
|
|
*/
|
|
async function saveAuthState(userType, context) {
|
|
await ensureAuthStorageDir();
|
|
|
|
const user = AUTH_CONFIG.users[userType];
|
|
if (!user) {
|
|
throw new Error(`Unknown user type: ${userType}`);
|
|
}
|
|
|
|
const storageFile = path.join(AUTH_CONFIG.storageDir, user.storageFile);
|
|
|
|
try {
|
|
await context.storageState({ path: storageFile });
|
|
console.log(`✅ Authentication state saved for ${userType}: ${storageFile}`);
|
|
} catch (error) {
|
|
console.warn(`Could not save auth state for ${userType}:`, error.message);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Load authentication state from file
|
|
* @param {string} userType - User type (trainer, master_trainer, admin)
|
|
* @returns {string|null} - Path to storage file or null if not exists
|
|
*/
|
|
async function getAuthStatePath(userType) {
|
|
const user = AUTH_CONFIG.users[userType];
|
|
if (!user) {
|
|
throw new Error(`Unknown user type: ${userType}`);
|
|
}
|
|
|
|
const storageFile = path.join(AUTH_CONFIG.storageDir, user.storageFile);
|
|
|
|
try {
|
|
await fs.access(storageFile);
|
|
return storageFile;
|
|
} catch {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Clear authentication state for user type
|
|
* @param {string} userType - User type (trainer, master_trainer, admin)
|
|
*/
|
|
async function clearAuthState(userType = null) {
|
|
await ensureAuthStorageDir();
|
|
|
|
if (userType) {
|
|
const user = AUTH_CONFIG.users[userType];
|
|
if (user) {
|
|
const storageFile = path.join(AUTH_CONFIG.storageDir, user.storageFile);
|
|
try {
|
|
await fs.unlink(storageFile);
|
|
console.log(`🗑️ Cleared auth state for ${userType}`);
|
|
} catch (error) {
|
|
// File doesn't exist, that's fine
|
|
}
|
|
}
|
|
} else {
|
|
// Clear all auth states
|
|
for (const [type, user] of Object.entries(AUTH_CONFIG.users)) {
|
|
const storageFile = path.join(AUTH_CONFIG.storageDir, user.storageFile);
|
|
try {
|
|
await fs.unlink(storageFile);
|
|
console.log(`🗑️ Cleared auth state for ${type}`);
|
|
} catch {
|
|
// File doesn't exist, that's fine
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Verify user is authenticated and has correct role access
|
|
* @param {Page} page - Playwright page object
|
|
* @param {string} userType - Expected user type
|
|
*/
|
|
async function verifyAuthentication(page, userType) {
|
|
const user = AUTH_CONFIG.users[userType];
|
|
if (!user) {
|
|
throw new Error(`Unknown user type: ${userType}`);
|
|
}
|
|
|
|
// Navigate to expected dashboard
|
|
await page.goto(`${AUTH_CONFIG.baseUrl}${user.dashboardPath}`, {
|
|
waitUntil: 'networkidle',
|
|
timeout: AUTH_CONFIG.timeout
|
|
});
|
|
|
|
// Verify we're not on login page
|
|
const currentUrl = page.url();
|
|
if (currentUrl.includes('/wp-login.php') || currentUrl.includes('/training-login/')) {
|
|
throw new Error(`Authentication failed for ${userType} - redirected to login`);
|
|
}
|
|
|
|
// Verify dashboard is accessible
|
|
await expect(page.locator('body')).toBeVisible({ timeout: 5000 });
|
|
|
|
// Role-specific verification
|
|
switch (userType) {
|
|
case 'trainer':
|
|
await expect(page.locator('text=Dashboard, text=Trainer Dashboard')).toBeVisible({ timeout: 5000 });
|
|
break;
|
|
case 'master_trainer':
|
|
await expect(page.locator('text=Master Dashboard, text=Master Trainer')).toBeVisible({ timeout: 5000 });
|
|
break;
|
|
case 'admin':
|
|
await expect(page.locator('#wpadminbar, .wp-admin')).toBeVisible({ timeout: 5000 });
|
|
break;
|
|
}
|
|
|
|
console.log(`✅ Authentication verified for ${userType}`);
|
|
}
|
|
|
|
/**
|
|
* Perform login for specified user type
|
|
* @param {Page} page - Playwright page object
|
|
* @param {string} userType - User type (trainer, master_trainer, admin)
|
|
* @param {Object} options - Login options
|
|
*/
|
|
async function performLogin(page, userType, options = {}) {
|
|
const user = AUTH_CONFIG.users[userType];
|
|
if (!user) {
|
|
throw new Error(`Unknown user type: ${userType}`);
|
|
}
|
|
|
|
const useWpLogin = options.useWpLogin || userType === 'admin';
|
|
const loginUrl = useWpLogin ? AUTH_CONFIG.wpLoginUrl : AUTH_CONFIG.loginUrl;
|
|
|
|
console.log(`🔑 Logging in as ${userType} via ${loginUrl}`);
|
|
|
|
// Navigate to login page
|
|
await page.goto(`${AUTH_CONFIG.baseUrl}${loginUrl}`, {
|
|
waitUntil: 'networkidle',
|
|
timeout: AUTH_CONFIG.timeout
|
|
});
|
|
|
|
// Wait for login form
|
|
await page.waitForSelector('#user_login, input[name="log"], input[type="email"]', {
|
|
timeout: 10000
|
|
});
|
|
|
|
// Fill login form (handle different form structures)
|
|
const emailField = await page.locator('#user_login, input[name="log"], input[type="email"]').first();
|
|
const passwordField = await page.locator('#user_pass, input[name="pwd"], input[type="password"]').first();
|
|
const submitButton = await page.locator('#wp-submit, button[type="submit"], input[type="submit"]').first();
|
|
|
|
await emailField.fill(user.email);
|
|
await passwordField.fill(user.password);
|
|
|
|
// Submit form and wait for navigation
|
|
await Promise.all([
|
|
page.waitForURL(url => !url.includes('/wp-login.php') && !url.includes('/training-login/'), {
|
|
timeout: AUTH_CONFIG.timeout
|
|
}),
|
|
submitButton.click()
|
|
]);
|
|
|
|
// Verify login was successful
|
|
await verifyAuthentication(page, userType);
|
|
|
|
console.log(`✅ Login successful for ${userType}`);
|
|
}
|
|
|
|
/**
|
|
* Logout current user
|
|
* @param {Page} page - Playwright page object
|
|
*/
|
|
async function performLogout(page) {
|
|
try {
|
|
// Try different logout methods
|
|
const logoutSelectors = [
|
|
'a[href*="wp-login.php?action=logout"]',
|
|
'a[href*="logout"]',
|
|
'text=Logout',
|
|
'text=Log Out',
|
|
'#wp-admin-bar-logout a'
|
|
];
|
|
|
|
for (const selector of logoutSelectors) {
|
|
const logoutLink = await page.locator(selector).first();
|
|
if (await logoutLink.isVisible()) {
|
|
await logoutLink.click();
|
|
await page.waitForLoadState('networkidle');
|
|
break;
|
|
}
|
|
}
|
|
|
|
console.log('✅ Logout completed');
|
|
} catch (error) {
|
|
console.warn('Logout may have failed:', error.message);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get user configuration for specified type
|
|
* @param {string} userType - User type
|
|
* @returns {Object} User configuration
|
|
*/
|
|
function getUserConfig(userType) {
|
|
const user = AUTH_CONFIG.users[userType];
|
|
if (!user) {
|
|
throw new Error(`Unknown user type: ${userType}`);
|
|
}
|
|
return { ...user };
|
|
}
|
|
|
|
/**
|
|
* Get all available user types
|
|
* @returns {string[]} Array of user types
|
|
*/
|
|
function getAvailableUserTypes() {
|
|
return Object.keys(AUTH_CONFIG.users);
|
|
}
|
|
|
|
module.exports = {
|
|
AUTH_CONFIG,
|
|
ensureAuthStorageDir,
|
|
saveAuthState,
|
|
getAuthStatePath,
|
|
clearAuthState,
|
|
verifyAuthentication,
|
|
performLogin,
|
|
performLogout,
|
|
getUserConfig,
|
|
getAvailableUserTypes
|
|
}; |