import { test, expect } from '@playwright/test'; import { Config } from './utils/Config'; import { BasePage } from './pages/BasePage'; import { LoginPage } from './pages/LoginPage'; import { DashboardPage } from './pages/DashboardPage'; /** * Optimized Certificate Tests * * This file contains E2E tests for the certificate system with a focus * on verifying the attendee search filter functionality. */ // Simple CertificatePage implementation that doesn't depend on external files class CertificatePage extends BasePage { // Certificate Reports page selectors private readonly certificateTitle = 'h1:has-text("Certificate Reports")'; private readonly certificateTable = '.hvac-certificate-table'; private readonly eventFilter = '#filter_event'; private readonly attendeeSearch = '#search_attendee'; private readonly revokedFilter = '#filter_revoked'; private readonly filterSubmit = 'button[type="submit"]'; private readonly clearFilters = 'a.hvac-clear-filters'; private readonly totalCountText = '.hvac-total-count'; private readonly pagination = '.hvac-pagination'; private readonly nextPage = '.hvac-pagination a.next'; private readonly previousPage = '.hvac-pagination a.prev'; private readonly certificateRows = '.hvac-certificate-table tbody tr'; private readonly certificateEventCells = 'td.certificate-event'; private readonly certificateAttendeeCells = 'td.certificate-attendee'; async navigateToCertificateReports(): Promise { await this.page.goto(Config.certificateReportsUrl); await this.page.waitForLoadState('networkidle'); } async isCertificateReportsPageVisible(): Promise { return this.page.locator(this.certificateTitle).isVisible(); } async clearAllFilters(): Promise { if (await this.page.locator(this.clearFilters).isVisible()) { await this.page.click(this.clearFilters); await this.page.waitForTimeout(1000); } } async filterByEvent(eventId: string): Promise { await this.clearAllFilters(); await this.page.selectOption(this.eventFilter, eventId); await this.page.click(this.filterSubmit); await this.page.waitForSelector(this.certificateTable); } async filterByAttendee(searchTerm: string): Promise { await this.clearAllFilters(); await this.page.fill(this.attendeeSearch, searchTerm); await this.page.click(this.filterSubmit); await this.page.waitForSelector(this.certificateTable); } async filterByRevoked(revoked: boolean): Promise { await this.clearAllFilters(); await this.page.selectOption(this.revokedFilter, revoked ? '1' : '0'); await this.page.click(this.filterSubmit); await this.page.waitForSelector(this.certificateTable); } async getCertificateCount(): Promise { const countText = await this.page.locator(this.totalCountText).textContent(); const match = countText?.match(/of (\d+) certificates/); return match ? parseInt(match[1]) : 0; } async getEventCellTexts(): Promise { return this.page.locator(this.certificateEventCells).allTextContents(); } async getAttendeeCellTexts(): Promise { return this.page.locator(this.certificateAttendeeCells).allTextContents(); } async hasPagination(): Promise { return this.page.locator(this.pagination).isVisible(); } async clickNextPage(): Promise { await this.page.click(this.nextPage); await this.page.waitForSelector(this.certificateTable); } } // Simple test that verifies the certificate data and attendee search functionality test('Certificate data and attendee search verification', async ({ page }) => { // Create page objects const loginPage = new LoginPage(page); const dashboardPage = new DashboardPage(page); const certificatePage = new CertificatePage(page); // Test event IDs const testEvents = [ { id: '5641', name: 'HVAC System Design Fundamentals' }, { id: '5668', name: 'Advanced Refrigeration Technology' }, { id: '5688', name: 'Building Automation Systems Workshop' } ]; // Step 1: Login console.log('Step 1: Logging in as test trainer'); await loginPage.navigate(); await loginPage.login(Config.testTrainer.username, Config.testTrainer.password); // Verify successful login const isLoggedIn = await dashboardPage.isVisible('h1:has-text("Dashboard")'); expect(isLoggedIn).toBeTruthy(); // Step 2: Navigate to certificate reports console.log('Step 2: Navigating to certificate reports page'); await certificatePage.navigateToCertificateReports(); // Verify certificate page loaded const certificatePageVisible = await certificatePage.isCertificateReportsPageVisible(); expect(certificatePageVisible).toBeTruthy(); // Step 3: Check total certificate count console.log('Step 3: Checking total certificate count'); const totalCount = await certificatePage.getCertificateCount(); console.log(`Total certificates: ${totalCount}`); expect(totalCount).toBeGreaterThanOrEqual(47); // We expect at least 47 certificates from our test data // Step 4: Test event filtering console.log('Step 4: Testing event filtering'); for (const event of testEvents) { await certificatePage.filterByEvent(event.id); const eventCount = await certificatePage.getCertificateCount(); console.log(`Event "${event.name}" has ${eventCount} certificates`); // Verify all event cells contain the correct name const eventCells = await certificatePage.getEventCellTexts(); for (const cellText of eventCells) { expect(cellText).toContain(event.name); } // Take screenshot for verification await page.screenshot({ path: `event-filter-${event.id}.png` }); } // Step 5: Test attendee name filtering console.log('Step 5: Testing attendee name filtering'); await certificatePage.filterByAttendee('Ben Tester'); const benCount = await certificatePage.getCertificateCount(); console.log(`Attendee "Ben Tester" has ${benCount} certificates`); // Verify attendee cells contain Ben Tester const benCells = await certificatePage.getAttendeeCellTexts(); for (const cellText of benCells) { expect(cellText.toLowerCase()).toContain('ben tester'); } // Take screenshot for verification await page.screenshot({ path: 'attendee-name-filter.png' }); // Step 6: Test attendee email filtering console.log('Step 6: Testing attendee email filtering'); await certificatePage.filterByAttendee('ben@tealmaker.com'); const emailCount = await certificatePage.getCertificateCount(); console.log(`Email "ben@tealmaker.com" has ${emailCount} certificates`); // Take screenshot for verification await page.screenshot({ path: 'attendee-email-filter.png' }); // Step 7: Test partial name filtering console.log('Step 7: Testing partial name filtering'); await certificatePage.filterByAttendee('Smith'); const smithCount = await certificatePage.getCertificateCount(); console.log(`Partial name "Smith" has ${smithCount} certificates`); // Take screenshot for verification await page.screenshot({ path: 'partial-name-filter.png' }); // Step 8: Test partial email filtering console.log('Step 8: Testing partial email filtering'); await certificatePage.filterByAttendee('@gmail'); const gmailCount = await certificatePage.getCertificateCount(); console.log(`Partial email "@gmail" has ${gmailCount} certificates`); // Take screenshot for verification await page.screenshot({ path: 'partial-email-filter.png' }); // Step 9: Test revoked filtering console.log('Step 9: Testing revocation status filtering'); await certificatePage.filterByRevoked(true); const revokedCount = await certificatePage.getCertificateCount(); console.log(`Found ${revokedCount} revoked certificates`); // Take screenshot for verification await page.screenshot({ path: 'revoked-filter.png' }); // Step 10: Test pagination console.log('Step 10: Testing pagination if applicable'); await certificatePage.clearAllFilters(); const hasPagination = await certificatePage.hasPagination(); if (hasPagination) { console.log('Pagination is available, testing navigation'); await certificatePage.clickNextPage(); // Take screenshot of second page await page.screenshot({ path: 'pagination-page-2.png' }); } else { console.log('No pagination available (not enough certificates)'); } console.log('Certificate verification tests completed'); });