- Add CertificatePage for certificate operations - Create BasePage for common page object functionality - Implement CertificateTestData for test data generation - Create optimized certificate tests with improved stability - Add test-certificate-filter.sh script for testing certificate filtering - Improve test organization and reliability
195 lines
No EOL
6.2 KiB
TypeScript
195 lines
No EOL
6.2 KiB
TypeScript
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<void> {
|
|
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<void> {
|
|
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<boolean> {
|
|
return await this.page.isVisible(this.generatePageTitle);
|
|
}
|
|
|
|
/**
|
|
* Check if the Certificate Reports page is visible
|
|
*/
|
|
async isCertificateReportsPageVisible(): Promise<boolean> {
|
|
return await this.page.isVisible(this.reportsPageTitle);
|
|
}
|
|
|
|
/**
|
|
* Select an event from the dropdown on Generate Certificates page
|
|
*/
|
|
async selectEvent(eventName: string): Promise<void> {
|
|
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<number> {
|
|
return await this.page.locator(this.attendeeItems).count();
|
|
}
|
|
|
|
/**
|
|
* Get number of checked-in attendees
|
|
*/
|
|
async getCheckedInAttendeeCount(): Promise<number> {
|
|
return await this.page.locator(this.checkedInLabel).count();
|
|
}
|
|
|
|
/**
|
|
* Select all attendees
|
|
*/
|
|
async selectAllAttendees(): Promise<void> {
|
|
await this.page.click(this.checkAllButton);
|
|
}
|
|
|
|
/**
|
|
* Select only checked-in attendees
|
|
*/
|
|
async selectCheckedInAttendees(): Promise<void> {
|
|
await this.page.click(this.checkCheckedInButton);
|
|
}
|
|
|
|
/**
|
|
* Generate certificates for selected attendees
|
|
*/
|
|
async generateCertificates(): Promise<void> {
|
|
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<boolean> {
|
|
return await this.page.isVisible(this.successMessage);
|
|
}
|
|
|
|
/**
|
|
* Get success message text
|
|
*/
|
|
async getSuccessMessage(): Promise<string | null> {
|
|
return await this.page.textContent(this.successMessage);
|
|
}
|
|
|
|
/**
|
|
* Filter certificates by event name
|
|
*/
|
|
async searchCertificates(eventName: string): Promise<void> {
|
|
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<void> {
|
|
await this.page.fill(this.attendeeSearchInput, searchTerm);
|
|
await this.page.click(this.filterButton);
|
|
await this.page.waitForLoadState('networkidle');
|
|
}
|
|
|
|
/**
|
|
* Reset all filters
|
|
*/
|
|
async resetFilters(): Promise<void> {
|
|
await this.page.click(this.resetButton);
|
|
await this.page.waitForLoadState('networkidle');
|
|
}
|
|
|
|
/**
|
|
* Get the number of certificates in the table
|
|
*/
|
|
async getCertificateCount(): Promise<number> {
|
|
return await this.page.locator(this.certificateItems).count();
|
|
}
|
|
|
|
/**
|
|
* View a certificate by index
|
|
*/
|
|
async viewCertificate(index: number): Promise<void> {
|
|
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<void> {
|
|
await this.page.click(this.closePreviewButton);
|
|
await this.page.waitForSelector(this.certificatePreview, { state: 'hidden' });
|
|
}
|
|
} |