upskill-event-manager/tests/framework/page-objects/TrainerDashboard.js
Ben 7c9ca65cf2
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
feat: add comprehensive test framework and test files
- 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>
2025-08-29 23:23:26 -03:00

449 lines
No EOL
14 KiB
JavaScript

/**
* Trainer Dashboard Page Object Model
*
* Handles trainer dashboard functionality with WordPress integration:
* - Navigation and menu interactions
* - Dashboard widgets and statistics
* - Quick actions and forms
* - Event management shortcuts
*
* @package HVAC_Community_Events
* @version 2.0.0
* @created 2025-08-27
*/
const BasePage = require('./BasePage');
const { expect } = require('@playwright/test');
class TrainerDashboard extends BasePage {
constructor(page) {
super(page);
// Dashboard-specific selectors
this.selectors = {
// Main dashboard elements
dashboard: [
'trainer-dashboard',
'.hvac-trainer-dashboard',
'.trainer-dashboard',
'[data-page="trainer-dashboard"]'
],
// Navigation elements
navigation: [
'trainer-nav',
'.hvac-trainer-nav',
'.trainer-navigation',
'nav.trainer-nav'
],
// Dashboard widgets
widgets: {
eventCount: [
'event-count-widget',
'.event-count',
'[data-widget="event-count"]',
'.dashboard-stat.events'
],
upcomingEvents: [
'upcoming-events',
'.upcoming-events-widget',
'[data-widget="upcoming-events"]'
],
recentActivity: [
'recent-activity',
'.recent-activity-widget',
'[data-widget="recent-activity"]'
],
statistics: [
'trainer-stats',
'.trainer-statistics',
'.dashboard-statistics'
]
},
// Quick action buttons
actions: {
createEvent: [
'create-event-btn',
'a[href*="/create-event"]',
'.create-event-button',
'text=Create Event'
],
manageEvents: [
'manage-events-btn',
'a[href*="/manage-events"]',
'.manage-events-button',
'text=Manage Events'
],
editProfile: [
'edit-profile-btn',
'a[href*="/profile/edit"]',
'.edit-profile-button',
'text=Edit Profile'
],
viewProfile: [
'view-profile-btn',
'a[href*="/profile"]',
'.view-profile-button',
'text=View Profile'
]
},
// Breadcrumb navigation
breadcrumb: [
'.hvac-breadcrumb',
'.breadcrumb',
'[data-testid="breadcrumb"]'
],
// Welcome message
welcomeMessage: [
'welcome-message',
'.welcome-message',
'.trainer-welcome'
],
// Menu items
menuItems: {
dashboard: 'a[href*="/trainer/dashboard"]',
events: 'a[href*="/trainer/events"], text=My Events',
createEvent: 'a[href*="/create-event"], text=Create Event',
profile: 'a[href*="/profile"], text=Profile',
venues: 'a[href*="/venues"], text=Venues',
organizers: 'a[href*="/organizers"], text=Organizers',
trainingLeads: 'a[href*="/training-leads"], text=Training Leads',
resources: 'a[href*="/resources"], text=Resources',
documentation: 'a[href*="/documentation"], text=Documentation',
announcements: 'a[href*="/announcements"], text=Announcements'
}
};
this.urls = {
dashboard: '/trainer/dashboard/',
events: '/trainer/events/',
createEvent: '/trainer/create-event/',
profile: '/trainer/profile/',
editProfile: '/trainer/profile/edit/',
venues: '/trainer/venues/',
organizers: '/trainer/organizers/',
trainingLeads: '/trainer/training-leads/',
documentation: '/trainer/documentation/'
};
}
/**
* Navigate to trainer dashboard
*/
async navigate() {
await this.goto(this.urls.dashboard);
await this.waitForDashboardLoad();
}
/**
* Wait for dashboard to fully load
*/
async waitForDashboardLoad() {
// Wait for main dashboard container
await this.waitForVisible(this.selectors.dashboard);
// Wait for navigation to be present
await this.waitForVisible(this.selectors.navigation);
// Wait for WordPress and AJAX to complete
await this.waitForWordPressReady();
await this.waitForAjax();
console.log('✅ Trainer dashboard loaded');
}
/**
* Verify dashboard is displayed correctly
*/
async verifyDashboard() {
// Check main dashboard container
await expect(this.locator(this.selectors.dashboard)).toBeVisible();
// Check breadcrumb
if (await this.isVisible(this.selectors.breadcrumb)) {
await this.verifyBreadcrumbs(['Dashboard']);
}
// Check navigation menu
await expect(this.locator(this.selectors.navigation)).toBeVisible();
// Check welcome message if present
if (await this.isVisible(this.selectors.welcomeMessage)) {
console.log('✅ Welcome message displayed');
}
console.log('✅ Dashboard verification complete');
}
/**
* Get dashboard statistics
*/
async getDashboardStats() {
const stats = {};
// Get event count if visible
if (await this.isVisible(this.selectors.widgets.eventCount)) {
const eventCountText = await this.getText(this.selectors.widgets.eventCount);
stats.eventCount = this.extractNumber(eventCountText);
}
// Get upcoming events count
if (await this.isVisible(this.selectors.widgets.upcomingEvents)) {
const upcomingEventsCount = await this.page
.locator(`${this.selectors.widgets.upcomingEvents.join(', ')} .event-item`)
.count();
stats.upcomingEvents = upcomingEventsCount;
}
console.log('📊 Dashboard stats:', stats);
return stats;
}
/**
* Navigate to create event page
*/
async goToCreateEvent() {
await this.click(this.selectors.actions.createEvent, { waitForNavigation: true });
await this.waitForUrl('**/create-event**');
console.log('🔗 Navigated to Create Event page');
}
/**
* Navigate to manage events page
*/
async goToManageEvents() {
await this.click(this.selectors.actions.manageEvents, { waitForNavigation: true });
await this.waitForUrl('**/events**');
console.log('🔗 Navigated to Manage Events page');
}
/**
* Navigate to profile page
*/
async goToProfile() {
await this.click(this.selectors.actions.viewProfile, { waitForNavigation: true });
await this.waitForUrl('**/profile**');
console.log('🔗 Navigated to Profile page');
}
/**
* Navigate to edit profile page
*/
async goToEditProfile() {
await this.click(this.selectors.actions.editProfile, { waitForNavigation: true });
await this.waitForUrl('**/profile/edit**');
console.log('🔗 Navigated to Edit Profile page');
}
/**
* Use navigation menu to go to specific section
*/
async navigateToSection(section) {
const menuItem = this.selectors.menuItems[section];
if (!menuItem) {
throw new Error(`Unknown navigation section: ${section}`);
}
// Check if navigation menu is visible
if (await this.isVisible('.hvac-menu-toggle, .mobile-menu-toggle')) {
// Mobile menu - open it first
await this.click('.hvac-menu-toggle, .mobile-menu-toggle');
await this.waitForVisible('.hvac-menu.open, .mobile-menu.open');
}
// Click menu item
await this.click(menuItem, { waitForNavigation: true });
// Wait for page to load
const expectedUrl = this.urls[section];
if (expectedUrl) {
await this.waitForUrl(`**${expectedUrl}**`);
}
console.log(`🔗 Navigated to: ${section}`);
}
/**
* Check for announcements
*/
async checkAnnouncements() {
const announcementSelectors = [
'.hvac-announcements',
'.trainer-announcements',
'[data-widget="announcements"]',
'.dashboard-announcements'
];
for (const selector of announcementSelectors) {
if (await this.isVisible(selector)) {
const announcementCount = await this.page.locator(`${selector} .announcement`).count();
console.log(`📢 Found ${announcementCount} announcements`);
return announcementCount;
}
}
return 0;
}
/**
* Get recent activity items
*/
async getRecentActivity() {
if (!await this.isVisible(this.selectors.widgets.recentActivity)) {
return [];
}
const activityItems = await this.page
.locator(`${this.selectors.widgets.recentActivity.join(', ')} .activity-item`)
.allTextContents();
console.log(`📋 Found ${activityItems.length} recent activity items`);
return activityItems;
}
/**
* Search functionality (if available)
*/
async search(query) {
const searchSelectors = [
'[data-testid="search-input"]',
'.dashboard-search input',
'input[name="search"]',
'.search-box input'
];
for (const selector of searchSelectors) {
if (await this.isVisible(selector)) {
await this.fill(selector, query);
await this.page.keyboard.press('Enter');
await this.waitForAjax();
console.log(`🔍 Searched for: ${query}`);
return true;
}
}
console.log('⚠️ Search functionality not found');
return false;
}
/**
* Quick actions on dashboard
*/
async performQuickAction(action) {
const actionHandlers = {
'create-event': () => this.goToCreateEvent(),
'manage-events': () => this.goToManageEvents(),
'edit-profile': () => this.goToEditProfile(),
'view-profile': () => this.goToProfile(),
'view-venues': () => this.navigateToSection('venues'),
'view-organizers': () => this.navigateToSection('organizers'),
'view-training-leads': () => this.navigateToSection('trainingLeads')
};
const handler = actionHandlers[action];
if (!handler) {
throw new Error(`Unknown quick action: ${action}`);
}
await handler();
console.log(`⚡ Performed quick action: ${action}`);
}
/**
* Verify trainer has access to expected dashboard elements
*/
async verifyTrainerAccess() {
// Check that we're authenticated as trainer
await this.verifyUserRole('trainer');
// Check essential navigation items
const essentialItems = ['dashboard', 'events', 'profile'];
for (const item of essentialItems) {
const menuItem = this.selectors.menuItems[item];
await expect(this.locator(menuItem)).toBeVisible();
}
// Check that we can't see admin-only elements
const adminOnlySelectors = [
'.master-trainer-only',
'.admin-only',
'a[href*="/master-trainer/"]',
'a[href*="/wp-admin/"]'
];
for (const selector of adminOnlySelectors) {
await expect(this.locator(selector)).not.toBeVisible();
}
console.log('✅ Trainer access verification complete');
}
/**
* Get dashboard page title
*/
async getPageTitle() {
return await this.page.title();
}
/**
* Check if dashboard has mobile responsive layout
*/
async checkMobileResponsiveness() {
// Set mobile viewport
await this.page.setViewportSize({ width: 375, height: 667 });
// Check if mobile menu toggle is visible
const hasMobileMenu = await this.isVisible('.hvac-menu-toggle, .mobile-menu-toggle');
// Check if navigation is adapted for mobile
const hasMobileNav = await this.isVisible('.hvac-nav-mobile, .mobile-navigation');
// Reset to desktop viewport
await this.page.setViewportSize({
width: this.config.get('browser.viewport.width'),
height: this.config.get('browser.viewport.height')
});
return {
hasMobileMenu,
hasMobileNav,
isMobileResponsive: hasMobileMenu || hasMobileNav
};
}
/**
* Extract number from text (helper method)
*/
extractNumber(text) {
const match = text.match(/\d+/);
return match ? parseInt(match[0], 10) : 0;
}
/**
* Wait for specific widget to load
*/
async waitForWidget(widgetName) {
const widget = this.selectors.widgets[widgetName];
if (!widget) {
throw new Error(`Unknown widget: ${widgetName}`);
}
await this.waitForVisible(widget);
await this.waitForAjax();
console.log(`📊 Widget loaded: ${widgetName}`);
}
/**
* Take screenshot of full dashboard
*/
async screenshotDashboard() {
return await this.takeScreenshot('trainer-dashboard', { fullPage: true });
}
}
module.exports = TrainerDashboard;