upskill-event-manager/tests/page-objects/trainer/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

384 lines
No EOL
13 KiB
JavaScript

/**
* Trainer Dashboard Page Object
* Handles all interactions with the regular trainer dashboard
*/
const BasePage = require('../base/BasePage');
class TrainerDashboard extends BasePage {
constructor(page = null) {
super(page);
this.url = '/trainer/dashboard/';
this.title = 'Trainer Dashboard';
this.selectors = {
// Main dashboard elements
dashboardTitle: 'h1, .dashboard-title, .page-title',
welcomeMessage: '.welcome-message, .dashboard-welcome',
userInfo: '.user-info, .current-user',
// Navigation menu
navigationMenu: '.trainer-navigation, .dashboard-nav',
menuItems: '.nav-item, .menu-item',
// Dashboard sections
eventsSection: '.events-section, [data-section="events"]',
profileSection: '.profile-section, [data-section="profile"]',
venueSection: '.venue-section, [data-section="venues"]',
organizerSection: '.organizer-section, [data-section="organizers"]',
// Quick action buttons
quickActions: '.quick-actions, .dashboard-actions',
createEventBtn: 'a[href*="create-event"], .create-event-btn',
manageEventsBtn: 'a[href*="events"], .manage-events-btn',
profileBtn: 'a[href*="profile"], .profile-btn',
venueBtn: 'a[href*="venue"], .venue-btn',
organizerBtn: 'a[href*="organizer"], .organizer-btn',
// Events related
upcomingEvents: '.upcoming-events, .events-list',
eventItems: '.event-item, .event-card',
noEventsMessage: '.no-events, .empty-events',
// Profile related
profileStatus: '.profile-status, .trainer-status',
profileCompletion: '.profile-completion, .completion-status',
editProfileBtn: 'a[href*="edit-profile"], .edit-profile-btn',
// Venue management
venueList: '.venue-list, .venues',
addVenueBtn: 'a[href*="add-venue"], .add-venue-btn',
manageVenuesBtn: 'a[href*="venue/manage"], .manage-venues-btn',
// Training leads
trainingLeadsBtn: 'a[href*="training-leads"], .training-leads-btn',
leadsSection: '.training-leads, [data-section="leads"]',
// Common elements
logoutBtn: '.logout, a[href*="logout"]',
settingsLink: 'a[href*="settings"], .settings-link',
helpLink: 'a[href*="help"], .help-link',
// Error and loading states
loadingIndicator: '.loading, .spinner, .loader',
errorMessage: '.error, .notice-error',
successMessage: '.success, .notice-success',
// Layout elements
mainContent: '.main-content, .dashboard-content',
sidebar: '.sidebar, .dashboard-sidebar',
breadcrumbs: '.breadcrumbs, .breadcrumb-nav'
};
}
/**
* Wait for dashboard page to be fully loaded
* @returns {Promise<void>}
*/
async waitForPageReady() {
// Wait for main dashboard elements
await this.waitForElement(this.selectors.dashboardTitle);
await this.waitForElement(this.selectors.mainContent);
// Wait for navigation to be loaded
await this.waitForElement(this.selectors.navigationMenu);
// Wait for any AJAX loading to complete
await this.waitForAjaxComplete();
}
/**
* Get dashboard title
* @returns {Promise<string>}
*/
async getDashboardTitle() {
return await this.getElementText(this.selectors.dashboardTitle);
}
/**
* Check if user is properly authenticated as trainer
* @returns {Promise<boolean>}
*/
async isAuthenticatedAsTrainer() {
try {
await this.waitForElement(this.selectors.dashboardTitle, 10000);
const title = await this.getDashboardTitle();
return title.toLowerCase().includes('trainer') &&
!title.toLowerCase().includes('master trainer');
} catch (error) {
return false;
}
}
/**
* Navigate to Create Event page
* @returns {Promise<void>}
*/
async navigateToCreateEvent() {
const createBtn = await this.page.$(this.selectors.createEventBtn);
if (createBtn) {
await this.clickElement(this.selectors.createEventBtn);
} else {
await this.page.goto(`${this.page.url().split('/trainer')[0]}/trainer/create-event/`);
}
await this.waitForPageLoad();
}
/**
* Navigate to Manage Events page
* @returns {Promise<void>}
*/
async navigateToManageEvents() {
const manageBtn = await this.page.$(this.selectors.manageEventsBtn);
if (manageBtn) {
await this.clickElement(this.selectors.manageEventsBtn);
} else {
await this.page.goto(`${this.page.url().split('/trainer')[0]}/trainer/events/`);
}
await this.waitForPageLoad();
}
/**
* Navigate to Profile page
* @returns {Promise<void>}
*/
async navigateToProfile() {
const profileBtn = await this.page.$(this.selectors.profileBtn);
if (profileBtn) {
await this.clickElement(this.selectors.profileBtn);
} else {
await this.page.goto(`${this.page.url().split('/trainer')[0]}/trainer/profile/`);
}
await this.waitForPageLoad();
}
/**
* Navigate to Venue Management
* @returns {Promise<void>}
*/
async navigateToVenueManagement() {
const venueBtn = await this.page.$(this.selectors.venueBtn);
if (venueBtn) {
await this.clickElement(this.selectors.venueBtn);
} else {
await this.page.goto(`${this.page.url().split('/trainer')[0]}/trainer/venue/manage/`);
}
await this.waitForPageLoad();
}
/**
* Navigate to Organizer Management
* @returns {Promise<void>}
*/
async navigateToOrganizerManagement() {
const organizerBtn = await this.page.$(this.selectors.organizerBtn);
if (organizerBtn) {
await this.clickElement(this.selectors.organizerBtn);
} else {
await this.page.goto(`${this.page.url().split('/trainer')[0]}/trainer/organizer/manage/`);
}
await this.waitForPageLoad();
}
/**
* Navigate to Training Leads
* @returns {Promise<void>}
*/
async navigateToTrainingLeads() {
const leadsBtn = await this.page.$(this.selectors.trainingLeadsBtn);
if (leadsBtn) {
await this.clickElement(this.selectors.trainingLeadsBtn);
} else {
await this.page.goto(`${this.page.url().split('/trainer')[0]}/trainer/profile/training-leads/`);
}
await this.waitForPageLoad();
}
/**
* Get list of upcoming events
* @returns {Promise<Array>}
*/
async getUpcomingEvents() {
const events = [];
try {
if (await this.hasElement(this.selectors.noEventsMessage)) {
return events; // No events found
}
const eventItems = await this.page.$$(this.selectors.eventItems);
for (const item of eventItems) {
const title = await item.$eval('.event-title, .title, h3, h4', el => el.textContent.trim());
const date = await item.$eval('.event-date, .date', el => el.textContent.trim()).catch(() => null);
const location = await item.$eval('.event-location, .location', el => el.textContent.trim()).catch(() => null);
events.push({ title, date, location });
}
} catch (error) {
console.warn('Failed to get upcoming events:', error.message);
}
return events;
}
/**
* Check profile completion status
* @returns {Promise<Object>}
*/
async getProfileStatus() {
const status = {
isComplete: false,
completionPercentage: 0,
missingFields: []
};
try {
if (await this.hasElement(this.selectors.profileCompletion)) {
const completionText = await this.getElementText(this.selectors.profileCompletion);
const percentMatch = completionText.match(/(\d+)%/);
if (percentMatch) {
status.completionPercentage = parseInt(percentMatch[1], 10);
status.isComplete = status.completionPercentage === 100;
}
}
// Check for any missing field indicators
const missingFieldElements = await this.page.$$('.missing-field, .incomplete-field');
for (const element of missingFieldElements) {
const fieldName = await element.textContent();
status.missingFields.push(fieldName.trim());
}
} catch (error) {
console.warn('Failed to get profile status:', error.message);
}
return status;
}
/**
* Check if navigation menu is present and functional
* @returns {Promise<boolean>}
*/
async hasNavigationMenu() {
try {
await this.waitForElement(this.selectors.navigationMenu, 5000);
const menuItems = await this.page.$$(this.selectors.menuItems);
return menuItems.length > 0;
} catch (error) {
return false;
}
}
/**
* Get all available navigation menu items
* @returns {Promise<Array>}
*/
async getNavigationMenuItems() {
const menuItems = [];
try {
const items = await this.page.$$(this.selectors.menuItems);
for (const item of items) {
const text = await item.textContent();
const href = await item.getAttribute('href');
menuItems.push({ text: text.trim(), href });
}
} catch (error) {
console.warn('Failed to get menu items:', error.message);
}
return menuItems;
}
/**
* Check if specific dashboard section is visible
* @param {string} sectionName - Name of section (events, profile, venue, etc.)
* @returns {Promise<boolean>}
*/
async isDashboardSectionVisible(sectionName) {
const sectionSelectors = {
'events': this.selectors.eventsSection,
'profile': this.selectors.profileSection,
'venue': this.selectors.venueSection,
'organizer': this.selectors.organizerSection,
'leads': this.selectors.leadsSection
};
const selector = sectionSelectors[sectionName];
if (!selector) return false;
return await this.isElementVisible(selector);
}
/**
* Wait for dashboard loading to complete
* @returns {Promise<void>}
*/
async waitForDashboardLoaded() {
// Wait for loading indicators to disappear
try {
await this.waitForElementHidden(this.selectors.loadingIndicator, 10000);
} catch (error) {
// Loading indicator might not be present
}
// Ensure main content is visible
await this.waitForElement(this.selectors.mainContent);
// Wait for any AJAX to complete
await this.waitForAjaxComplete();
}
/**
* Check if trainer has access to specific functionality
* @param {string} functionality - Name of functionality to check
* @returns {Promise<boolean>}
*/
async hasAccessTo(functionality) {
const accessSelectors = {
'createEvents': this.selectors.createEventBtn,
'manageVenues': this.selectors.venueBtn,
'manageOrganizers': this.selectors.organizerBtn,
'trainingLeads': this.selectors.trainingLeadsBtn,
'editProfile': this.selectors.editProfileBtn
};
const selector = accessSelectors[functionality];
if (!selector) return false;
return await this.hasElement(selector);
}
/**
* Logout from trainer dashboard
* @returns {Promise<void>}
*/
async logout() {
const logoutBtn = await this.page.$(this.selectors.logoutBtn);
if (logoutBtn) {
await this.clickElement(this.selectors.logoutBtn);
} else {
// Fallback logout
await this.page.goto('/wp-login.php?action=logout');
}
// Wait for redirect to login page
await this.page.waitForURL(url =>
url.includes('login') ||
url.includes('wp-login'),
{ timeout: 10000 }
);
}
/**
* Take screenshot of dashboard
* @param {string} filename - Screenshot filename
* @returns {Promise<string>}
*/
async takeScreenshot(filename = 'trainer-dashboard.png') {
await this.waitForDashboardLoaded();
return await super.takeScreenshot(filename);
}
}
module.exports = TrainerDashboard;