import { Page } from '@playwright/test'; import { VerbosityController } from './VerbosityController'; import { Config } from './Config'; /** * Utility class to set up test data for certificate testing * This helps ensure we have events with both checked-in and non-checked-in attendees */ export class CertificateTestData { private page: Page; private verbosity: VerbosityController; constructor(page: Page) { this.page = page; this.verbosity = VerbosityController.getInstance(); } /** * Login as the test trainer */ async loginAsTrainer(): Promise { this.verbosity.log('Logging in as test_trainer'); await this.page.goto(Config.loginUrl); await this.page.fill('#user_login', Config.testTrainer.username); await this.page.fill('#user_pass', Config.testTrainer.password); await this.page.click('#wp-submit'); await this.page.waitForLoadState('networkidle'); } /** * Creates a test event with a specified name and future date */ async createTestEvent(eventName: string): Promise { this.verbosity.log(`Creating test event: ${eventName}`); await this.page.goto(Config.createEventUrl); await this.page.waitForLoadState('networkidle'); // Fill in event details await this.page.fill('#post_title, input[name="post_title"]', eventName); // Add description const newEventFrame = this.page.frameLocator('iframe[id*="_ifr"]'); const newEventBody = newEventFrame.locator('body'); await newEventBody.fill(`This is a test event created for certificate testing: ${eventName}`); // Set dates (30 days from now) const futureDate = new Date(); futureDate.setDate(futureDate.getDate() + 30); const dateString = `${(futureDate.getMonth() + 1).toString().padStart(2, '0')}/${futureDate.getDate().toString().padStart(2, '0')}/${futureDate.getFullYear()}`; await this.page.fill('input[name="EventStartDate"]', dateString); await this.page.fill('input[name="EventStartTime"]', '10:00 AM'); await this.page.fill('input[name="EventEndDate"]', dateString); await this.page.fill('input[name="EventEndTime"]', '04:00 PM'); // Add a ticket for $100 await this.addTicket('Certificate Test Ticket', '100'); // Submit the event const submitButton = this.page.locator('input[value="Submit Event"], button:has-text("Submit Event")'); await submitButton.click(); await this.page.waitForLoadState('networkidle'); // Get the event ID from the URL if possible const url = this.page.url(); const match = url.match(/post=(\d+)/); if (match && match[1]) { return match[1]; } return null; } /** * Adds a ticket to an event */ private async addTicket(ticketName: string, price: string): Promise { // Look for ticket creation UI elements const ticketNameField = this.page.locator('#tribe-tickets-editor-tickets-name'); const ticketPriceField = this.page.locator('#tribe-tickets-editor-tickets-price'); const addTicketButton = this.page.locator('button:has-text("Add Ticket")'); // If the ticket UI isn't visible, try to open it if (!await ticketNameField.isVisible()) { const addTicketsSection = this.page.locator('a:has-text("Add Tickets")'); if (await addTicketsSection.isVisible()) { await addTicketsSection.click(); await this.page.waitForTimeout(Config.shortWait); } } // Fill in ticket details if (await ticketNameField.isVisible()) { await ticketNameField.fill(ticketName); await ticketPriceField.fill(price); await addTicketButton.click(); await this.page.waitForTimeout(Config.mediumWait); } else { this.verbosity.log('Warning: Ticket creation UI not found'); } } /** * Simulates attendee registrations for an event * Creates a mix of checked-in and non-checked-in attendees */ async createTestAttendees(eventId: string, count: number = 5): Promise { this.verbosity.log(`Creating ${count} test attendees for event ${eventId}`); // First, navigate to the admin area to access the event await this.page.goto(`${Config.stagingUrl}/wp-admin/post.php?post=${eventId}&action=edit`); // Check if we're on the login page and log in if needed if (this.page.url().includes('wp-login.php')) { await this.page.fill('#user_login', Config.testTrainer.username); await this.page.fill('#user_pass', Config.testTrainer.password); await this.page.click('#wp-submit'); await this.page.waitForLoadState('networkidle'); } // Navigate to the attendees tab - this is implementation-specific and may need adjustment const attendeesTab = this.page.locator('a:has-text("Attendees")'); if (await attendeesTab.isVisible()) { await attendeesTab.click(); await this.page.waitForTimeout(Config.shortWait); } // Look for "Add New" button const addNewButton = this.page.locator('a:has-text("Add attendee"), button:has-text("Add attendee")'); for (let i = 1; i <= count; i++) { // Click "Add New" for each attendee if (await addNewButton.isVisible()) { await addNewButton.click(); await this.page.waitForTimeout(Config.shortWait); // Fill in attendee info await this.page.fill('input[name="attendee[email]"]', `test.attendee${i}@example.com`); await this.page.fill('input[name="attendee[full_name]"]', `Test Attendee ${i}`); // Mark every other attendee as checked in if (i % 2 === 0) { const checkinCheckbox = this.page.locator('input[name="attendee[check_in]"]'); if (await checkinCheckbox.isVisible()) { await checkinCheckbox.check(); } } // Save the attendee const saveButton = this.page.locator('button:has-text("Add")'); await saveButton.click(); await this.page.waitForTimeout(Config.shortWait); } else { this.verbosity.log('Warning: Add attendee button not found'); break; } } } /** * Creates a complete test event with attendees for certificate testing */ async setupCertificateTestEvent(): Promise { // Create a uniquely named event const timestamp = new Date().getTime(); const eventName = `Certificate Test Event ${timestamp}`; // Create the event const eventId = await this.createTestEvent(eventName); if (!eventId) { this.verbosity.log('Failed to create test event'); return null; } // Add test attendees (mix of checked-in and non-checked-in) await this.createTestAttendees(eventId, 6); return eventName; } }