import { Page } from '@playwright/test'; import { BasePage } from './BasePage'; export class CertificatePage extends BasePage { // Generate Certificates page selectors private readonly generateCertificatesTitle = 'h1:has-text("Generate Certificates")'; private readonly eventSelector = 'select[name="event_id"]'; private readonly eventSearchInput = 'input[name="event_search"]'; private readonly selectAllCheckbox = 'input[name="select_all"]'; private readonly attendeeCheckboxes = 'input[name="attendees[]"]'; private readonly generateButton = 'button:has-text("Generate Certificates")'; private readonly previewButton = 'button:has-text("Preview Certificate")'; private readonly successMessage = '.hvac-success-message'; private readonly errorMessage = '.hvac-error-message'; private readonly attendeeList = '.hvac-attendee-list'; private readonly attendeeItem = '.hvac-attendee-item'; private readonly checkinStatusAttribute = 'data-checkin-status'; private readonly loadingIndicator = '.hvac-loading'; // Certificate Reports page selectors private readonly certificateReportsTitle = 'h1:has-text("Certificate Reports")'; private readonly certificateFilterInput = 'input[name="certificate_search"]'; private readonly certificateTable = '.hvac-certificate-table'; private readonly certificateTableRows = '.hvac-certificate-table tbody tr'; private readonly viewCertificateButton = 'button:has-text("View")'; private readonly emailCertificateButton = 'button:has-text("Email")'; private readonly revokeCertificateButton = 'button:has-text("Revoke")'; private readonly certificatePagination = '.hvac-pagination'; private readonly certificateModal = '.hvac-certificate-modal'; private readonly certificatePreview = '.hvac-certificate-preview'; private readonly closeModalButton = '.hvac-modal-close'; private readonly confirmRevocationButton = 'button:has-text("Confirm Revocation")'; private readonly confirmEmailButton = 'button:has-text("Send Email")'; constructor(page: Page) { super(page); } // Common methods async navigateToGenerateCertificates(): Promise { const STAGING_URL = 'https://wordpress-974670-5399585.cloudwaysapps.com'; await this.page.goto(`${STAGING_URL}/generate-certificates/`); await this.page.waitForLoadState('networkidle'); await this.screenshot('generate-certificates-page'); } async navigateToCertificateReports(): Promise { const STAGING_URL = 'https://wordpress-974670-5399585.cloudwaysapps.com'; await this.page.goto(`${STAGING_URL}/certificate-reports/`); await this.page.waitForLoadState('networkidle'); await this.screenshot('certificate-reports-page'); } // Generate Certificates page methods async isGenerateCertificatesPageVisible(): Promise { return await this.isVisible(this.generateCertificatesTitle); } async selectEvent(eventName: string): Promise { // If there's a search input, try using it if (await this.isVisible(this.eventSearchInput)) { await this.fill(this.eventSearchInput, eventName); await this.page.waitForTimeout(500); // Wait for search results } // Select the event from dropdown await this.page.selectOption(this.eventSelector, { label: eventName }); await this.page.waitForTimeout(1000); // Wait for attendee list to load // Wait for loading indicator to disappear if it's present const loadingElement = this.page.locator(this.loadingIndicator); if (await loadingElement.isVisible()) { await loadingElement.waitFor({ state: 'hidden', timeout: 5000 }); } await this.screenshot('event-selected'); } async getAttendeeCount(): Promise { return await this.page.locator(this.attendeeItem).count(); } async getCheckedInAttendeeCount(): Promise { let checkedInCount = 0; const attendees = this.page.locator(this.attendeeItem); const count = await attendees.count(); for (let i = 0; i < count; i++) { const status = await attendees.nth(i).getAttribute(this.checkinStatusAttribute); if (status === 'checked-in') { checkedInCount++; } } return checkedInCount; } async selectAllAttendees(): Promise { await this.click(this.selectAllCheckbox); await this.screenshot('all-attendees-selected'); } async selectCheckedInAttendees(): Promise { // Deselect "Select All" if it's checked const selectAllChecked = await this.page.isChecked(this.selectAllCheckbox); if (selectAllChecked) { await this.click(this.selectAllCheckbox); } // Select only checked-in attendees const attendees = this.page.locator(this.attendeeItem); const count = await attendees.count(); for (let i = 0; i < count; i++) { const status = await attendees.nth(i).getAttribute(this.checkinStatusAttribute); if (status === 'checked-in') { const checkbox = attendees.nth(i).locator('input[type="checkbox"]'); await checkbox.check(); } } await this.screenshot('checked-in-attendees-selected'); } async selectNonCheckedInAttendees(): Promise { // Deselect "Select All" if it's checked const selectAllChecked = await this.page.isChecked(this.selectAllCheckbox); if (selectAllChecked) { await this.click(this.selectAllCheckbox); } // Select only non-checked-in attendees const attendees = this.page.locator(this.attendeeItem); const count = await attendees.count(); for (let i = 0; i < count; i++) { const status = await attendees.nth(i).getAttribute(this.checkinStatusAttribute); if (status !== 'checked-in') { const checkbox = attendees.nth(i).locator('input[type="checkbox"]'); await checkbox.check(); } } await this.screenshot('non-checked-in-attendees-selected'); } async generateCertificates(): Promise { await this.click(this.generateButton); // Wait for loading indicator to disappear if it's present const loadingElement = this.page.locator(this.loadingIndicator); if (await loadingElement.isVisible()) { await loadingElement.waitFor({ state: 'hidden', timeout: 10000 }); } await this.page.waitForTimeout(2000); // Additional wait for any post-processing await this.screenshot('certificates-generated'); } async previewCertificate(): Promise { await this.click(this.previewButton); // Wait for the preview modal to appear await this.waitForElement(this.certificateModal); await this.screenshot('certificate-preview'); } async closePreview(): Promise { if (await this.isVisible(this.closeModalButton)) { await this.click(this.closeModalButton); await this.page.waitForTimeout(500); // Wait for modal to close } } async isSuccessMessageVisible(): Promise { return await this.isVisible(this.successMessage); } async isErrorMessageVisible(): Promise { return await this.isVisible(this.errorMessage); } async getSuccessMessage(): Promise { return await this.getText(this.successMessage); } async getErrorMessage(): Promise { return await this.getText(this.errorMessage); } // Certificate Reports page methods async isCertificateReportsPageVisible(): Promise { return await this.isVisible(this.certificateReportsTitle); } async searchCertificates(query: string): Promise { await this.fill(this.certificateFilterInput, query); await this.page.waitForTimeout(1000); // Wait for search results // Wait for loading indicator to disappear if it's present const loadingElement = this.page.locator(this.loadingIndicator); if (await loadingElement.isVisible()) { await loadingElement.waitFor({ state: 'hidden', timeout: 5000 }); } await this.screenshot('certificate-search'); } async getCertificateCount(): Promise { return await this.page.locator(this.certificateTableRows).count(); } async viewCertificate(index: number = 0): Promise { const viewButtons = this.page.locator(this.viewCertificateButton); await viewButtons.nth(index).click(); // Wait for the preview modal to appear await this.waitForElement(this.certificateModal); await this.screenshot('view-certificate'); } async emailCertificate(index: number = 0): Promise { const emailButtons = this.page.locator(this.emailCertificateButton); await emailButtons.nth(index).click(); // Wait for the email confirmation dialog if (await this.isVisible(this.confirmEmailButton)) { await this.click(this.confirmEmailButton); await this.page.waitForTimeout(2000); // Wait for email to be sent } await this.screenshot('email-certificate'); } async revokeCertificate(index: number = 0): Promise { const revokeButtons = this.page.locator(this.revokeCertificateButton); await revokeButtons.nth(index).click(); // Wait for the revocation confirmation dialog if (await this.isVisible(this.confirmRevocationButton)) { await this.click(this.confirmRevocationButton); await this.page.waitForTimeout(2000); // Wait for revocation to complete } await this.screenshot('revoke-certificate'); } async isPaginationVisible(): Promise { return await this.isVisible(this.certificatePagination); } }