upskill-event-manager/wordpress-dev/tests/e2e/pages/LoginPage.ts
bengizmo d6211ee364 feat(testing): Implement HVAC_Test_User_Factory and update .gitignore
- Add HVAC_Test_User_Factory class with:
  * User creation with specific roles
  * Multiple role support
  * Persona management system
  * Account cleanup integration
- Create comprehensive test suite in HVAC_Test_User_Factory_Test.php
- Update testing improvement plan documentation
- Add implementation decisions to project memory bank
- Restructure .gitignore with:
  * Whitelist approach for better file management
  * Explicit backup exclusions
  * Specific bin directory inclusions

Part of the Account Management component from the testing framework improvement plan.
2025-04-14 17:41:36 -03:00

201 lines
No EOL
7.8 KiB
TypeScript

import { Page, expect } from '@playwright/test';
import { LogParser } from '../utils/logParser';
export class LoginPage {
readonly page: Page;
private readonly selectors = {
usernameInput: '#user_login',
passwordInput: '#user_pass',
loginButton: '#wp-submit',
rememberMeCheckbox: '#rememberme',
errorMessage: '#login_error, .hvac-login-error, .notice-error',
resetPasswordLink: '.wp-login-lost-password, .hvac-lostpassword-link',
registerLink: '.wp-login-register, .hvac-register-link',
successMessage: '.message, .updated, .success'
};
constructor(page: Page) {
this.page = page;
}
async navigate() {
await this.page.goto('/community-login/');
}
async login(username: string, password: string, rememberMe = false) {
await this.page.fill(this.selectors.usernameInput, username);
await this.page.fill(this.selectors.passwordInput, password);
if (rememberMe) {
await this.page.check(this.selectors.rememberMeCheckbox);
}
await this.page.click(this.selectors.loginButton);
}
async verifyLoginError(expectedMessage: string) {
try {
console.log('Waiting for login failure indicators...');
// Check if we're on either the community login page or WordPress login page with error
const currentUrl = this.page.url();
console.log('Current URL:', currentUrl);
const isErrorPage = currentUrl.includes('login=failed') ||
currentUrl.includes('wp-login.php');
expect(isErrorPage).toBe(true);
console.log('Waiting for error message to appear...');
const errorElement = await this.page.waitForSelector(this.selectors.errorMessage, {
state: 'visible',
timeout: 20000 // Increased timeout to 20 seconds
});
const actualError = await errorElement.textContent();
console.log('Found error message:', actualError);
if (!actualError) {
throw new Error('Error message element found but contains no text');
}
// Take screenshot for debugging
await this.page.screenshot({
path: `test-results/login-error-${Date.now()}.png`,
fullPage: true
});
// Clean up and normalize the error message text
const cleanError = actualError
.replace(/\s+/g, ' ')
.trim()
.toLowerCase();
const cleanExpected = expectedMessage
.toLowerCase()
.trim();
console.log('Cleaned error message:', cleanError);
console.log('Expected to contain:', cleanExpected);
// WordPress prefixes errors with "Error:" - handle both formats
const normalizedError = cleanError.replace(/^error:\s*/i, '');
const normalizedExpected = cleanExpected.replace(/^error:\s*/i, '');
expect(normalizedError).toContain(normalizedExpected);
// Additional check for error message visibility
const isVisible = await errorElement.isVisible();
expect(isVisible).toBe(true);
} catch (error) {
console.error('Failed to verify login error:', error);
// Take screenshot on failure
await this.page.screenshot({
path: `test-results/login-error-failure-${Date.now()}.png`,
fullPage: true
});
// Log the page content for debugging
const content = await this.page.content();
console.error('Page content at failure:', content);
throw error;
}
}
async verifySuccessfulLogin() {
// After successful login, we should be redirected to the dashboard
await expect(this.page).toHaveURL(/.*\/wp-admin\/?$/);
}
async clickResetPassword() {
try {
console.log('Waiting for password reset link...');
// Wait for the link to be visible and stable
await this.page.waitForSelector(this.selectors.resetPasswordLink, {
state: 'visible',
timeout: 10000
});
// Get all matching links and click the first one that contains relevant text
const links = await this.page.$$(this.selectors.resetPasswordLink);
for (const link of links) {
const text = await link.textContent();
if (text && (text.toLowerCase().includes('lost') || text.toLowerCase().includes('forgot'))) {
console.log('Found password reset link with text:', text);
await link.click();
return;
}
}
throw new Error('No password reset link with expected text found');
} catch (error) {
console.error('Failed to click password reset link:', error);
await this.page.screenshot({
path: `test-results/reset-password-failure-${Date.now()}.png`,
fullPage: true
});
throw error;
}
}
async checkLogEntries(logParser: LogParser) {
try {
const logs = await logParser.parseLogFile('wordpress.log');
const loginAttempt = logs.find(log =>
log.component === 'auth' &&
log.message.includes('login_attempt')
);
expect(loginAttempt).toBeTruthy();
} catch (error) {
console.warn('Warning: Could not check log entries:', error);
// Skip log verification if we can't access the logs
return;
}
}
async verifyRememberMeCookie() {
try {
console.log('Checking for WordPress authentication cookies...');
// Wait briefly for cookies to be set
await this.page.waitForTimeout(1000);
const cookies = await this.page.context().cookies();
console.log('Found cookies:', cookies.map(c => c.name).join(', '));
// WordPress sets multiple cookies for persistent login
const requiredCookies = [
'wordpress_logged_in_', // Main login cookie
'wordpress_sec_' // Security cookie
];
const foundCookies = requiredCookies.map(cookiePrefix => {
const cookie = cookies.find(c => c.name.startsWith(cookiePrefix));
if (!cookie) {
console.warn(`Missing expected cookie with prefix: ${cookiePrefix}`);
}
return cookie;
});
// Verify both cookies exist and have appropriate expiration
foundCookies.forEach(cookie => {
expect(cookie, `Cookie with prefix ${cookie?.name} should exist`).toBeTruthy();
if (cookie) {
// WordPress "Remember Me" cookies typically expire in 14 days
const twoWeeksFromNow = Date.now() + (14 * 24 * 60 * 60 * 1000);
expect(cookie.expires * 1000).toBeGreaterThan(Date.now());
expect(cookie.expires * 1000).toBeLessThanOrEqual(twoWeeksFromNow);
}
});
console.log('Successfully verified WordPress authentication cookies');
} catch (error) {
console.error('Failed to verify WordPress authentication cookies:', error);
await this.page.screenshot({
path: `test-results/cookie-check-failure-${Date.now()}.png`,
fullPage: true
});
throw error;
}
}
}