import { expect, type Locator, type Page } from '@playwright/test'; import { BasePage } from './BasePage'; export class InsuranceBasePage extends BasePage { readonly cookieContinueButton: Locator; readonly continueWithSafeliteButton: Locator; constructor(page: Page) { super(page); // Targeting continue buttons with multiple selectors this.cookieContinueButton = page.locator([ 'button:has-text("Continue")', 'button#navNext.btn-success', 'button[name="navNext"][type="submit"]', '.btn-success:has-text("Continue")' ].join(', ')); // Targeting "Continue with Safelite" buttons this.continueWithSafeliteButton = page.locator([ 'button:has-text("Continue with Safelite")', 'button#navNext:has-text("Safelite")', '.btn-success:has-text("Continue with Safelite")' ].join(', ')); } /** * Navigates to the next page in the insurance flow * Overrides the BasePage nextPage() method to handle insurance modal buttons */ async nextPage() { const startingUrl = this.page.url(); let attemptCount = 0; const maxAttempts = 3; while (attemptCount < maxAttempts) { try { // Try navNext ID button first const navNextButton = this.page.locator('#navNext:visible'); if (await navNextButton.count() > 0) { await navNextButton.click(); await this.page.waitForTimeout(500); } // Try button with Continue text else if (await this.cookieContinueButton.isVisible({ timeout: 2000 })) { await this.cookieContinueButton.click(); await this.page.waitForTimeout(500); } // Try button with Continue with Safelite text else if (await this.continueWithSafeliteButton.isVisible({ timeout: 2000 })) { await this.continueWithSafeliteButton.click(); await this.page.waitForTimeout(500); } // Try any button that might work else { const possibleButtons = [ 'button.btn-success', 'button[type="submit"]', 'button[name="navNext"]', '.button-content', 'button:has-text("Continue")', 'button:has-text("Next")' ]; let buttonFound = false; for (const selector of possibleButtons) { const button = this.page.locator(selector); if (await button.count() > 0 && await button.first().isVisible()) { await button.first().click(); buttonFound = true; await this.page.waitForTimeout(500); break; } } if (!buttonFound) { await super.nextPage(); return; } } // Check if URL changed const currentUrl = this.page.url(); if (currentUrl !== startingUrl) { break; } // Try Enter key on second attempt if (attemptCount === 1) { await this.page.keyboard.press('Enter'); await this.page.waitForTimeout(1000); if (this.page.url() !== startingUrl) { break; } } attemptCount++; } catch (error) { attemptCount++; if (attemptCount >= maxAttempts) { await super.nextPage(); return; } await this.page.waitForTimeout(1000); } } // Wait for spinner to disappear try { await expect(this.pageSpinner).toHaveCount(0, { timeout: 60000 }); } catch (error) { // Continue if spinner check fails } // Final navigation stability check await this.page.waitForLoadState('networkidle', { timeout: 10000 }).catch(() => { // Continue if networkidle times out }); } /** * Direct method to click Continue with Safelite button */ async clickContinueWithSafelite() { try { // Try direct ID selector first if (await this.page.$('#navNext:has-text("Safelite")') !== null) { await this.page.click('#navNext'); } else if (await this.continueWithSafeliteButton.isVisible({ timeout: 2000 })) { await this.continueWithSafeliteButton.click(); } else { await this.page.click('button:has-text("Continue with Safelite")'); } return true; } catch (error) { return false; } } }