- Add interactive modal popup for announcement 'Read More' functionality - Fix nonce conflict by creating separate hvac_announcements_ajax object - Implement secure AJAX handler with rate limiting and permission checks - Add comprehensive modal CSS with smooth animations and responsive design - Include accessibility features (ARIA, keyboard navigation, screen reader support) - Create detailed documentation in docs/ANNOUNCEMENT-MODAL-SYSTEM.md - Update API-REFERENCE.md with new modal endpoints and security details - Add automated Playwright E2E testing for modal functionality - All modal interactions working: click to open, X to close, ESC to close, outside click - Production-ready with full error handling and content sanitization 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
136 lines
No EOL
4.9 KiB
JavaScript
136 lines
No EOL
4.9 KiB
JavaScript
/**
|
|
* Test announcement modal functionality
|
|
*/
|
|
|
|
const { chromium } = require('playwright');
|
|
|
|
async function testAnnouncementModal() {
|
|
console.log('🎭 Starting announcement modal test...');
|
|
|
|
const browser = await chromium.launch({
|
|
headless: false,
|
|
slowMo: 1000
|
|
});
|
|
|
|
try {
|
|
const context = await browser.newContext({
|
|
viewport: { width: 1200, height: 800 }
|
|
});
|
|
|
|
const page = await context.newPage();
|
|
|
|
// Navigate to staging login
|
|
console.log('📋 Step 1: Navigating to staging login...');
|
|
await page.goto('https://upskill-staging.measurequick.com/training-login/');
|
|
await page.waitForLoadState('networkidle');
|
|
|
|
// Login as test trainer
|
|
console.log('🔐 Step 2: Logging in as test trainer...');
|
|
await page.fill('#username', 'test_trainer');
|
|
await page.fill('#password', 'TestTrainer123!');
|
|
await page.click('input[type="submit"]');
|
|
await page.waitForLoadState('networkidle');
|
|
|
|
// Navigate to resources page
|
|
console.log('📚 Step 3: Navigating to resources page...');
|
|
await page.goto('https://upskill-staging.measurequick.com/trainer/resources/');
|
|
await page.waitForLoadState('networkidle');
|
|
|
|
// Take screenshot of resources page
|
|
console.log('📸 Step 4: Taking screenshot of resources page...');
|
|
await page.screenshot({ path: 'resources-page-before-modal.png', fullPage: true });
|
|
|
|
// Look for announcement and Read More button
|
|
console.log('🔍 Step 5: Looking for Read More button...');
|
|
const readMoreButton = await page.locator('.read-more-btn').first();
|
|
|
|
if (await readMoreButton.count() === 0) {
|
|
console.log('❌ No Read More buttons found on page');
|
|
return false;
|
|
}
|
|
|
|
console.log('✅ Found Read More button');
|
|
|
|
// Click Read More button
|
|
console.log('👆 Step 6: Clicking Read More button...');
|
|
await readMoreButton.click();
|
|
|
|
// Wait for modal to appear
|
|
console.log('⏳ Step 7: Waiting for modal to appear...');
|
|
await page.waitForSelector('#announcement-modal.active', { timeout: 5000 });
|
|
|
|
// Check if modal is visible
|
|
const modal = page.locator('#announcement-modal');
|
|
const isVisible = await modal.isVisible();
|
|
|
|
if (!isVisible) {
|
|
console.log('❌ Modal is not visible after clicking Read More');
|
|
return false;
|
|
}
|
|
|
|
console.log('✅ Modal appeared successfully');
|
|
|
|
// Take screenshot with modal open
|
|
console.log('📸 Step 8: Taking screenshot with modal open...');
|
|
await page.screenshot({ path: 'resources-page-with-modal.png', fullPage: true });
|
|
|
|
// Check modal content
|
|
console.log('📝 Step 9: Checking modal content...');
|
|
const modalTitle = await page.locator('.modal-title').textContent();
|
|
const modalContent = await page.locator('.modal-content-text').textContent();
|
|
|
|
console.log('Modal Title:', modalTitle);
|
|
console.log('Modal Content Preview:', modalContent.substring(0, 100) + '...');
|
|
|
|
// Test modal close button
|
|
console.log('❌ Step 10: Testing modal close button...');
|
|
await page.click('.modal-close');
|
|
|
|
// Wait for modal to disappear
|
|
await page.waitForTimeout(500);
|
|
const isModalHidden = await page.locator('#announcement-modal').isHidden();
|
|
|
|
if (!isModalHidden) {
|
|
console.log('❌ Modal did not close with close button');
|
|
return false;
|
|
}
|
|
|
|
console.log('✅ Modal closed successfully with close button');
|
|
|
|
// Test opening modal again and closing with ESC key
|
|
console.log('⌨️ Step 11: Testing ESC key close...');
|
|
await readMoreButton.click();
|
|
await page.waitForSelector('#announcement-modal.active');
|
|
await page.keyboard.press('Escape');
|
|
await page.waitForTimeout(500);
|
|
|
|
const isModalHiddenAfterEsc = await page.locator('#announcement-modal').isHidden();
|
|
|
|
if (!isModalHiddenAfterEsc) {
|
|
console.log('❌ Modal did not close with ESC key');
|
|
return false;
|
|
}
|
|
|
|
console.log('✅ Modal closed successfully with ESC key');
|
|
|
|
console.log('🎉 All modal tests passed!');
|
|
return true;
|
|
|
|
} catch (error) {
|
|
console.error('❌ Test failed with error:', error.message);
|
|
return false;
|
|
} finally {
|
|
await browser.close();
|
|
}
|
|
}
|
|
|
|
// Run the test
|
|
testAnnouncementModal().then(success => {
|
|
if (success) {
|
|
console.log('✅ Announcement modal functionality is working correctly!');
|
|
process.exit(0);
|
|
} else {
|
|
console.log('❌ Announcement modal test failed');
|
|
process.exit(1);
|
|
}
|
|
}); |