🎯 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
255 lines
No EOL
11 KiB
TypeScript
255 lines
No EOL
11 KiB
TypeScript
import { test, expect } from '@playwright/test';
|
||
import { STAGING_URL, PATHS } from './config/staging-config';
|
||
|
||
/**
|
||
* Simple Certificate Preview Test
|
||
*
|
||
* Tests the certificate preview functionality by checking:
|
||
* - Generate Certificates page loads correctly with AJAX
|
||
* - Certificate Reports page shows existing certificates
|
||
* - Certificate security URL patterns are correct
|
||
*/
|
||
test.describe('Certificate Preview - Simple Tests', () => {
|
||
|
||
test.beforeEach(async ({ page }) => {
|
||
// Login as test_trainer
|
||
await page.goto(PATHS.login);
|
||
await page.fill('#user_login', 'test_trainer');
|
||
await page.fill('#user_pass', 'Test123!');
|
||
await page.click('#wp-submit');
|
||
|
||
// Wait for dashboard redirect
|
||
await page.waitForURL('**/hvac-dashboard/**');
|
||
await page.waitForLoadState('networkidle');
|
||
});
|
||
|
||
test('should access Generate Certificates page and verify AJAX functionality', async ({ page }) => {
|
||
console.log('=== Testing Generate Certificates Page Access ===');
|
||
|
||
// Navigate to Generate Certificates
|
||
await page.goto(PATHS.generateCertificates);
|
||
await page.waitForLoadState('networkidle');
|
||
|
||
// Verify page loads
|
||
await expect(page.locator('h1')).toContainText('Generate Certificates');
|
||
console.log('✅ Generate Certificates page loads correctly');
|
||
|
||
// Check if event selector exists (AJAX component)
|
||
const eventSelect = page.locator('#event_id');
|
||
await expect(eventSelect).toBeVisible();
|
||
console.log('✅ Event selector is visible');
|
||
|
||
// Check if AJAX container exists (should be hidden initially)
|
||
const attendeesContainer = page.locator('#step-select-attendees');
|
||
await expect(attendeesContainer).toBeHidden();
|
||
console.log('✅ AJAX attendees container exists and is hidden initially (correct behavior)');
|
||
|
||
// Verify AJAX JavaScript is loaded
|
||
const ajaxScript = await page.evaluate(() => {
|
||
return typeof window.hvacCertificateData !== 'undefined';
|
||
});
|
||
expect(ajaxScript).toBeTruthy();
|
||
console.log('✅ Certificate AJAX JavaScript is loaded');
|
||
|
||
// Test event selection if events are available
|
||
const options = await eventSelect.locator('option:not([value=""])').count();
|
||
console.log(`Found ${options} events with attendees`);
|
||
|
||
if (options > 0) {
|
||
// Select first event to test AJAX loading
|
||
const firstOption = eventSelect.locator('option:not([value=""])').first();
|
||
const eventValue = await firstOption.getAttribute('value');
|
||
|
||
console.log(`Testing AJAX with event ID: ${eventValue}`);
|
||
await eventSelect.selectOption(eventValue);
|
||
|
||
// Wait a moment for AJAX to potentially load
|
||
await page.waitForTimeout(2000);
|
||
|
||
// Check if attendees section becomes visible or gets content
|
||
const attendeesVisible = await attendeesContainer.isVisible();
|
||
console.log(`Attendees section visible after selection: ${attendeesVisible}`);
|
||
}
|
||
});
|
||
|
||
test('should access Certificate Reports page and verify certificate security URLs', async ({ page }) => {
|
||
console.log('=== Testing Certificate Reports Page ===');
|
||
|
||
// Navigate to Certificate Reports
|
||
await page.goto(PATHS.certificatesReport);
|
||
await page.waitForLoadState('networkidle');
|
||
|
||
// Verify page loads
|
||
await expect(page.locator('h1')).toContainText('Certificate Reports');
|
||
console.log('✅ Certificate Reports page loads correctly');
|
||
|
||
// Check for certificate table or stats
|
||
const certificateTable = page.locator('.hvac-certificate-table');
|
||
const certificateStats = page.locator('.hvac-certificate-stats');
|
||
|
||
const hasTable = await certificateTable.isVisible();
|
||
const hasStats = await certificateStats.isVisible();
|
||
|
||
console.log(`Certificate table visible: ${hasTable}`);
|
||
console.log(`Certificate stats visible: ${hasStats}`);
|
||
|
||
if (hasTable) {
|
||
// Check for certificate download links with security pattern
|
||
const downloadLinks = page.locator('a[href*="hvac-certificate/"]');
|
||
const linkCount = await downloadLinks.count();
|
||
|
||
console.log(`Found ${linkCount} certificate download links`);
|
||
|
||
if (linkCount > 0) {
|
||
const firstLink = downloadLinks.first();
|
||
const href = await firstLink.getAttribute('href');
|
||
console.log(`Certificate download URL: ${href}`);
|
||
|
||
// Verify URL format matches security pattern
|
||
expect(href).toMatch(/\/hvac-certificate\/[a-zA-Z0-9]{32}$/);
|
||
console.log('✅ Certificate security URL format is correct');
|
||
}
|
||
}
|
||
|
||
if (hasStats) {
|
||
// Check certificate statistics
|
||
const statCards = page.locator('.hvac-stat-card');
|
||
const statCount = await statCards.count();
|
||
console.log(`Found ${statCount} certificate statistics cards`);
|
||
|
||
if (statCount > 0) {
|
||
for (let i = 0; i < statCount; i++) {
|
||
const card = statCards.nth(i);
|
||
const title = await card.locator('h3').textContent();
|
||
const value = await card.locator('.hvac-stat-value').textContent();
|
||
console.log(`Stat: ${title} = ${value}`);
|
||
}
|
||
}
|
||
}
|
||
});
|
||
|
||
test('should verify certificate security system is active', async ({ page }) => {
|
||
console.log('=== Testing Certificate Security System ===');
|
||
|
||
// Test direct access to certificate URL with invalid token
|
||
const invalidToken = 'a'.repeat(32);
|
||
const invalidUrl = `${STAGING_URL}/hvac-certificate/${invalidToken}`;
|
||
|
||
console.log(`Testing invalid certificate URL: ${invalidUrl}`);
|
||
|
||
const response = await page.goto(invalidUrl);
|
||
|
||
if (response) {
|
||
const status = response.status();
|
||
console.log(`Response status: ${status}`);
|
||
|
||
// Should get an error response for invalid token
|
||
if (status === 200) {
|
||
// Check for error message in content
|
||
const content = await page.textContent('body');
|
||
const hasError = /invalid|expired|not found/i.test(content);
|
||
expect(hasError).toBeTruthy();
|
||
console.log('✅ Invalid certificate URL shows error message');
|
||
} else {
|
||
// Non-200 status is also acceptable (403, 404, etc.)
|
||
expect([403, 404]).toContain(status);
|
||
console.log('✅ Invalid certificate URL returns error status');
|
||
}
|
||
}
|
||
});
|
||
|
||
test('should verify AJAX endpoints are accessible', async ({ page }) => {
|
||
console.log('=== Testing Certificate AJAX Endpoints ===');
|
||
|
||
// Navigate to a page that loads certificate JavaScript
|
||
await page.goto(PATHS.generateCertificates);
|
||
await page.waitForLoadState('networkidle');
|
||
|
||
// Test if AJAX endpoints are properly configured
|
||
const ajaxData = await page.evaluate(() => {
|
||
if (typeof window.hvacCertificateData !== 'undefined') {
|
||
return {
|
||
ajaxUrl: window.hvacCertificateData.ajaxUrl,
|
||
hasGenerateNonce: !!window.hvacCertificateData.generateNonce,
|
||
hasEmailNonce: !!window.hvacCertificateData.emailNonce,
|
||
hasRevokeNonce: !!window.hvacCertificateData.revokeNonce
|
||
};
|
||
}
|
||
return null;
|
||
});
|
||
|
||
expect(ajaxData).not.toBeNull();
|
||
expect(ajaxData.ajaxUrl).toContain('admin-ajax.php');
|
||
expect(ajaxData.hasGenerateNonce).toBeTruthy();
|
||
|
||
console.log('✅ AJAX configuration is properly loaded');
|
||
console.log(`AJAX URL: ${ajaxData.ajaxUrl}`);
|
||
console.log(`Generate nonce present: ${ajaxData.hasGenerateNonce}`);
|
||
console.log(`Email nonce present: ${ajaxData.hasEmailNonce}`);
|
||
console.log(`Revoke nonce present: ${ajaxData.hasRevokeNonce}`);
|
||
});
|
||
|
||
test('should verify certificate preview modal HTML structure exists', async ({ page }) => {
|
||
console.log('=== Testing Certificate Preview Modal Structure ===');
|
||
|
||
// Navigate to Generate Certificates page
|
||
await page.goto(PATHS.generateCertificates);
|
||
await page.waitForLoadState('networkidle');
|
||
|
||
// Check if the preview JavaScript is loaded
|
||
const previewFunctionExists = await page.evaluate(() => {
|
||
return typeof window.GenerateCertificates !== 'undefined' &&
|
||
typeof window.GenerateCertificates?.showCertificatePreview === 'function';
|
||
});
|
||
|
||
if (previewFunctionExists) {
|
||
console.log('✅ Certificate preview JavaScript functions are loaded');
|
||
} else {
|
||
console.log('ℹ️ Certificate preview functions not found in global scope');
|
||
}
|
||
|
||
// Test creating a preview modal programmatically
|
||
await page.evaluate(() => {
|
||
// Simulate the preview button functionality
|
||
if (typeof jQuery !== 'undefined') {
|
||
const $ = jQuery;
|
||
|
||
// Create a test preview button
|
||
$('body').append(`
|
||
<button class="hvac-preview-certificate test-preview-btn"
|
||
data-url="${window.location.origin}/hvac-certificate/test123456789012345678901234567890"
|
||
data-attendee="Test Attendee">
|
||
Test Preview
|
||
</button>
|
||
`);
|
||
|
||
// Trigger preview modal creation
|
||
$('.test-preview-btn').click();
|
||
}
|
||
});
|
||
|
||
// Wait for modal to be created
|
||
await page.waitForTimeout(1000);
|
||
|
||
// Check if modal was created
|
||
const modal = page.locator('#hvac-certificate-preview-modal');
|
||
const modalExists = await modal.count() > 0;
|
||
|
||
if (modalExists) {
|
||
console.log('✅ Certificate preview modal can be created');
|
||
|
||
// Verify modal structure
|
||
const modalHeader = page.locator('#hvac-certificate-preview-modal .hvac-modal-header');
|
||
const modalBody = page.locator('#hvac-certificate-preview-modal .hvac-modal-body');
|
||
const iframe = page.locator('#hvac-certificate-preview-iframe');
|
||
|
||
expect(await modalHeader.count()).toBeGreaterThan(0);
|
||
expect(await modalBody.count()).toBeGreaterThan(0);
|
||
expect(await iframe.count()).toBeGreaterThan(0);
|
||
|
||
console.log('✅ Modal has correct structure with header, body, and iframe');
|
||
} else {
|
||
console.log('ℹ️ Preview modal creation needs further investigation');
|
||
}
|
||
});
|
||
}); |