import { Page, expect } from '@playwright/test'; import { BasePage } from './BasePage'; /** * Page object representing the Certificate-related pages * Handles both Certificate Generation and Certificate Reports pages */ export class CertificatePage extends BasePage { // Selectors for Generate Certificates page private readonly generatePageTitle = 'h1:text("Generate Certificates")'; private readonly eventSelectDropdown = '#event_id'; private readonly selectedEventName = '.hvac-selected-event strong'; private readonly attendeeList = '.hvac-attendee-list'; private readonly attendeeItems = '.hvac-attendee-item'; private readonly checkedInLabel = '.hvac-checked-in'; private readonly checkAllButton = 'button:text("Select All")'; private readonly checkCheckedInButton = 'button:text("Select Checked-In")'; private readonly generateButton = 'button[type="submit"]:text("Generate Certificates")'; private readonly successMessage = '.hvac-success-message'; private readonly errorMessage = '.hvac-error-message'; // Selectors for Certificate Reports page private readonly reportsPageTitle = 'h1:text("Certificate Reports")'; private readonly filterForm = 'form.hvac-certificate-filters'; private readonly eventFilterSelect = '#filter_event'; private readonly attendeeSearchInput = '#search_attendee'; private readonly revokedFilterSelect = '#filter_revoked'; private readonly filterButton = 'button[type="submit"]:text("Filter")'; private readonly resetButton = 'button[type="reset"]:text("Reset Filters")'; private readonly certificateTable = '.hvac-certificate-table'; private readonly certificateItems = '.hvac-certificate-item'; private readonly viewCertificateLinks = 'a:text("View")'; private readonly certificatePreview = '.hvac-certificate-preview'; private readonly closePreviewButton = '.hvac-preview-close'; constructor(page: Page) { super(page); } /** * Navigate to the Generate Certificates page */ async navigateToGenerateCertificates(): Promise { await this.page.goto('/generate-certificates/'); await this.page.waitForLoadState('networkidle'); await this.page.waitForSelector(this.generatePageTitle); } /** * Navigate to the Certificate Reports page */ async navigateToCertificateReports(): Promise { await this.page.goto('/certificate-reports/'); await this.page.waitForLoadState('networkidle'); await this.page.waitForSelector(this.reportsPageTitle); } /** * Check if the Generate Certificates page is visible */ async isGenerateCertificatesPageVisible(): Promise { return await this.page.isVisible(this.generatePageTitle); } /** * Check if the Certificate Reports page is visible */ async isCertificateReportsPageVisible(): Promise { return await this.page.isVisible(this.reportsPageTitle); } /** * Select an event from the dropdown on Generate Certificates page */ async selectEvent(eventName: string): Promise { await this.page.selectOption(this.eventSelectDropdown, { label: new RegExp(eventName, 'i') }); await this.page.waitForSelector(this.attendeeList); // Verify the selected event const selectedText = await this.page.textContent(this.selectedEventName); expect(selectedText).toContain(eventName); } /** * Get total number of attendees listed */ async getAttendeeCount(): Promise { return await this.page.locator(this.attendeeItems).count(); } /** * Get number of checked-in attendees */ async getCheckedInAttendeeCount(): Promise { return await this.page.locator(this.checkedInLabel).count(); } /** * Select all attendees */ async selectAllAttendees(): Promise { await this.page.click(this.checkAllButton); } /** * Select only checked-in attendees */ async selectCheckedInAttendees(): Promise { await this.page.click(this.checkCheckedInButton); } /** * Generate certificates for selected attendees */ async generateCertificates(): Promise { await this.page.click(this.generateButton); await this.page.waitForLoadState('networkidle'); // Wait for either success or error message await this.page.waitForSelector(`${this.successMessage}, ${this.errorMessage}`); } /** * Check if success message is visible */ async isSuccessMessageVisible(): Promise { return await this.page.isVisible(this.successMessage); } /** * Get success message text */ async getSuccessMessage(): Promise { return await this.page.textContent(this.successMessage); } /** * Filter certificates by event name */ async searchCertificates(eventName: string): Promise { await this.page.selectOption(this.eventFilterSelect, { label: new RegExp(eventName, 'i') }); await this.page.click(this.filterButton); await this.page.waitForLoadState('networkidle'); } /** * Filter certificates by attendee name or email */ async searchAttendee(searchTerm: string): Promise { await this.page.fill(this.attendeeSearchInput, searchTerm); await this.page.click(this.filterButton); await this.page.waitForLoadState('networkidle'); } /** * Reset all filters */ async resetFilters(): Promise { await this.page.click(this.resetButton); await this.page.waitForLoadState('networkidle'); } /** * Get the number of certificates in the table */ async getCertificateCount(): Promise { return await this.page.locator(this.certificateItems).count(); } /** * View a certificate by index */ async viewCertificate(index: number): Promise { const viewLinks = this.page.locator(this.viewCertificateLinks); const count = await viewLinks.count(); if (index >= count) { throw new Error(`Cannot view certificate at index ${index}. Only ${count} certificates available.`); } await viewLinks.nth(index).click(); await this.page.waitForSelector(this.certificatePreview); } /** * Close the certificate preview */ async closePreview(): Promise { await this.page.click(this.closePreviewButton); await this.page.waitForSelector(this.certificatePreview, { state: 'hidden' }); } }