upskill-event-manager/wordpress-dev/tests/e2e/visual-page-verification.spec.ts
bengizmo 7a559746f9 fix: Resolve certificate reports 404 error and enhance legacy redirects
- Add missing render_certificate_fix() method to main plugin class
- Remove duplicate shortcode registration causing PHP errors
- Enhance legacy redirect system with dual-hook approach for better compatibility
- Update certificate reports template URLs to hierarchical structure
- Add comprehensive E2E test suite with Playwright for all plugin pages
- Create deployment and verification scripts for automated testing
- Add detailed documentation for deployment, troubleshooting, and maintenance
- Update package.json with Playwright test dependencies
- Achieve 89% success rate for plugin functionality and 100% for redirects

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-06-17 14:13:50 -03:00

285 lines
No EOL
13 KiB
TypeScript

import { test, expect, Page } from '@playwright/test';
/**
* Visual Page Verification Test Suite for HVAC Community Events Plugin
*
* This test suite focuses on visual verification of all pages without requiring
* specific login credentials. It tests:
* - Page accessibility and loading
* - Visual appearance via screenshots
* - Basic page structure and content
* - Error handling and redirects
*/
// Pages that should be accessible without authentication
const PUBLIC_PAGES = [
{ url: '/training-login/', title: 'Login Page', description: 'Main login page for trainers' }
];
// Pages that require authentication (will show login or access denied)
const AUTHENTICATED_PAGES = [
{ url: '/trainer/dashboard/', title: 'Trainer Dashboard', description: 'Personal trainer dashboard' },
{ url: '/trainer/my-profile/', title: 'Trainer Profile', description: 'Trainer profile management' },
{ url: '/trainer/registration/', title: 'Trainer Registration', description: 'New trainer registration' },
{ url: '/trainer/documentation/', title: 'Trainer Documentation', description: 'Help and documentation' },
{ url: '/trainer/event/manage/', title: 'Manage Event', description: 'Create and edit events' },
{ url: '/trainer/event/summary/', title: 'Event Summary', description: 'Event details and attendee management' },
{ url: '/trainer/email-attendees/', title: 'Email Attendees', description: 'Send emails to attendees' },
{ url: '/trainer/certificate-reports/', title: 'Certificate Reports', description: 'View issued certificates' },
{ url: '/trainer/generate-certificates/', title: 'Generate Certificates', description: 'Create new certificates' },
{ url: '/trainer/communication-templates/', title: 'Communication Templates', description: 'Manage email templates' },
{ url: '/trainer/communication-schedules/', title: 'Communication Schedules', description: 'Schedule automated communications' },
{ url: '/trainer/attendee-profile/', title: 'Attendee Profile', description: 'View attendee profiles' },
{ url: '/master-trainer/dashboard/', title: 'Master Dashboard', description: 'System-wide analytics and management' },
{ url: '/master-trainer/google-sheets/', title: 'Google Sheets Integration', description: 'Google Sheets integration' },
{ url: '/master-trainer/certificate-fix/', title: 'Certificate System Diagnostics', description: 'Certificate diagnostics (restricted)' }
];
// Legacy URLs that should redirect
const LEGACY_REDIRECTS = [
{ from: '/hvac-dashboard/', to: '/trainer/dashboard/', description: 'Dashboard redirect' },
{ from: '/manage-event/', to: '/trainer/event/manage/', description: 'Manage event redirect' },
{ from: '/trainer-profile/', to: '/trainer/my-profile/', description: 'Profile redirect' },
{ from: '/certificate-reports/', to: '/trainer/certificate-reports/', description: 'Certificate reports redirect' },
{ from: '/generate-certificates/', to: '/trainer/generate-certificates/', description: 'Generate certificates redirect' }
];
// Helper functions
async function takePageScreenshot(page: Page, category: string, pageName: string) {
const sanitizedName = pageName.toLowerCase().replace(/[^a-z0-9]/g, '-');
await page.screenshot({
path: `test-results/screenshots/${category}-${sanitizedName}.png`,
fullPage: true
});
}
async function verifyPageAccessibility(page: Page, expectedUrl: string, pageTitle: string) {
// Wait for page to load
await page.waitForLoadState('networkidle');
// Check page is not showing generic server errors
const bodyText = await page.locator('body').textContent();
// Basic checks for major errors
expect(bodyText).not.toContain('Fatal error');
expect(bodyText).not.toContain('Parse error');
expect(bodyText).not.toContain('Warning: Cannot modify header');
expect(bodyText).not.toContain('500 Internal Server Error');
// Check for WordPress or plugin content
const hasWordPressElements = await page.locator('body[class*="wp-"], #wp-admin-bar, .wp-').isVisible().catch(() => false);
const hasPluginElements = await page.locator('[class*="hvac"], [id*="hvac"], [class*="community"], [class*="event"], [class*="trainer"]').isVisible().catch(() => false);
const hasContentArea = await page.locator('.entry-content, .content, main, #content, .site-content').isVisible().catch(() => false);
// Should have at least some recognizable structure
const hasValidStructure = hasWordPressElements || hasPluginElements || hasContentArea;
console.log(`Page: ${pageTitle}`);
console.log(` - Has WordPress elements: ${hasWordPressElements}`);
console.log(` - Has plugin elements: ${hasPluginElements}`);
console.log(` - Has content area: ${hasContentArea}`);
console.log(` - Valid structure: ${hasValidStructure}`);
return {
hasValidStructure,
hasWordPressElements,
hasPluginElements,
hasContentArea,
bodyText: bodyText || ''
};
}
test.describe('HVAC Plugin Public Pages', () => {
for (const pageConfig of PUBLIC_PAGES) {
test(`${pageConfig.title} loads and displays correctly`, async ({ page }) => {
await page.goto(pageConfig.url);
// Take screenshot for visual verification
const screenshotName = pageConfig.title.toLowerCase().replace(/\s+/g, '-');
await takePageScreenshot(page, 'public', screenshotName);
// Verify page accessibility
const verification = await verifyPageAccessibility(page, pageConfig.url, pageConfig.title);
// Public pages should load properly
expect(verification.hasValidStructure).toBe(true);
// Check URL is correct
expect(page.url()).toContain(pageConfig.url);
console.log(`✓ Verified ${pageConfig.title} page loads correctly`);
});
}
});
test.describe('HVAC Plugin Authenticated Pages Response', () => {
for (const pageConfig of AUTHENTICATED_PAGES) {
test(`${pageConfig.title} page responds appropriately when not logged in`, async ({ page }) => {
await page.goto(pageConfig.url);
// Take screenshot for visual verification
const screenshotName = pageConfig.title.toLowerCase().replace(/\s+/g, '-');
await takePageScreenshot(page, 'auth-required', screenshotName);
// Verify page responds (not server error)
const verification = await verifyPageAccessibility(page, pageConfig.url, pageConfig.title);
// Should either:
// 1. Redirect to login page
// 2. Show access denied message
// 3. Show login form
// 4. Load page structure (if auth is handled client-side)
const currentUrl = page.url();
const isRedirectedToLogin = currentUrl.includes('/training-login/') || currentUrl.includes('/wp-login');
const showsAccessDenied = verification.bodyText.includes('Access denied') ||
verification.bodyText.includes('Unauthorized') ||
verification.bodyText.includes('Please log in') ||
verification.bodyText.includes('Login required');
const hasLoginForm = await page.locator('input[type="password"], input[name="pwd"], .login-form').isVisible().catch(() => false);
// At least one of these should be true for proper auth handling
const properAuthHandling = isRedirectedToLogin || showsAccessDenied || hasLoginForm || verification.hasValidStructure;
console.log(`Page: ${pageConfig.title}`);
console.log(` - Redirected to login: ${isRedirectedToLogin}`);
console.log(` - Shows access denied: ${showsAccessDenied}`);
console.log(` - Has login form: ${hasLoginForm}`);
console.log(` - Has valid structure: ${verification.hasValidStructure}`);
console.log(` - Proper auth handling: ${properAuthHandling}`);
expect(properAuthHandling).toBe(true);
console.log(`✓ Verified ${pageConfig.title} handles authentication properly`);
});
}
});
test.describe('HVAC Plugin Legacy URL Redirects', () => {
for (const redirectConfig of LEGACY_REDIRECTS) {
test(`Legacy URL ${redirectConfig.from} redirects properly`, async ({ page }) => {
// Navigate to legacy URL
await page.goto(redirectConfig.from);
// Wait for any redirects to complete
await page.waitForLoadState('networkidle');
// Take screenshot of final destination
const screenshotName = `legacy-${redirectConfig.from.replace(/[^a-z0-9]/g, '-')}`;
await takePageScreenshot(page, 'redirects', screenshotName);
// Check if URL changed (redirect occurred)
const finalUrl = page.url();
const redirectOccurred = !finalUrl.includes(redirectConfig.from) || finalUrl.includes(redirectConfig.to);
// Verify page loads properly after redirect
const verification = await verifyPageAccessibility(page, finalUrl, redirectConfig.description);
console.log(`Legacy URL: ${redirectConfig.from}`);
console.log(` - Final URL: ${finalUrl}`);
console.log(` - Redirect occurred: ${redirectOccurred}`);
console.log(` - Expected target: ${redirectConfig.to}`);
console.log(` - Valid structure: ${verification.hasValidStructure}`);
// Should either redirect to target or handle gracefully
expect(redirectOccurred).toBe(true);
expect(verification.hasValidStructure).toBe(true);
console.log(`✓ Verified legacy URL ${redirectConfig.from} redirects properly`);
});
}
});
test.describe('HVAC Plugin Visual Documentation', () => {
test('Generate comprehensive page documentation', async ({ page }) => {
// Test all pages for visual documentation
const allPages = [...PUBLIC_PAGES, ...AUTHENTICATED_PAGES];
let successfulPages = 0;
let totalPages = allPages.length;
for (const pageConfig of allPages) {
try {
await page.goto(pageConfig.url, { timeout: 10000 });
await page.waitForLoadState('networkidle', { timeout: 5000 });
// Take screenshot
const screenshotName = pageConfig.title.toLowerCase().replace(/[^a-z0-9]/g, '-');
await takePageScreenshot(page, 'documentation', screenshotName);
// Quick verification
const verification = await verifyPageAccessibility(page, pageConfig.url, pageConfig.title);
if (verification.hasValidStructure) {
successfulPages++;
console.log(`✓ Documented ${pageConfig.title}`);
} else {
console.log(`${pageConfig.title} may have issues`);
}
} catch (error) {
console.log(`✗ Failed to document ${pageConfig.title}: ${error}`);
}
}
// Report summary
console.log(`\n=== DOCUMENTATION SUMMARY ===`);
console.log(`Successfully documented: ${successfulPages}/${totalPages} pages`);
console.log(`Success rate: ${Math.round((successfulPages/totalPages) * 100)}%`);
// At least 70% of pages should be accessible for documentation
expect(successfulPages / totalPages).toBeGreaterThan(0.7);
console.log('✓ Generated comprehensive visual documentation');
});
});
test.describe('HVAC Plugin Navigation Structure', () => {
test('Verify hierarchical URL structure exists', async ({ page }) => {
// Test that the hierarchical structure is properly implemented
const hierarchicalTests = [
{ url: '/trainer/', description: 'Trainer base URL' },
{ url: '/trainer/dashboard/', description: 'Trainer dashboard URL' },
{ url: '/master-trainer/', description: 'Master trainer base URL' },
{ url: '/master-trainer/dashboard/', description: 'Master trainer dashboard URL' }
];
let workingHierarchy = 0;
for (const test of hierarchicalTests) {
try {
await page.goto(test.url, { timeout: 10000 });
await page.waitForLoadState('networkidle', { timeout: 5000 });
const verification = await verifyPageAccessibility(page, test.url, test.description);
// Take screenshot
const screenshotName = test.description.toLowerCase().replace(/[^a-z0-9]/g, '-');
await takePageScreenshot(page, 'hierarchy', screenshotName);
if (verification.hasValidStructure) {
workingHierarchy++;
console.log(`${test.description} responds properly`);
} else {
console.log(`${test.description} may have issues`);
}
} catch (error) {
console.log(`${test.description} failed: ${error}`);
}
}
console.log(`\n=== HIERARCHY VERIFICATION ===`);
console.log(`Working hierarchical URLs: ${workingHierarchy}/${hierarchicalTests.length}`);
// At least 75% should work
expect(workingHierarchy / hierarchicalTests.length).toBeGreaterThan(0.75);
console.log('✓ Verified hierarchical URL structure exists');
});
});