From f8935312adcbdea1a0dc5dac6b34f0ba9229cd4a Mon Sep 17 00:00:00 2001 From: kpatel8hs4io <31411746+kpatel8hs4io@users.noreply.github.com> Date: Wed, 1 Oct 2025 10:39:29 -0400 Subject: [PATCH] adding settlementamount validation and progress bar validation --- .../framework/localTypes/Enums.ts | 26 ++++---- playwright-tests/pages/BasePage.ts | 32 +++++----- .../pages/OrderConfirmationPage.ts | 62 ++++++++++++++----- 3 files changed, 74 insertions(+), 46 deletions(-) diff --git a/playwright-tests/framework/localTypes/Enums.ts b/playwright-tests/framework/localTypes/Enums.ts index 978f92bb2..d112f9110 100644 --- a/playwright-tests/framework/localTypes/Enums.ts +++ b/playwright-tests/framework/localTypes/Enums.ts @@ -5,23 +5,23 @@ export enum PaymentMethod { } export enum ProgressBarPercentages { - VehicleSelectionPage = '8%', - VehicleDamagePage = '11%', - EstimatePage = '18%', - ServiceZipPage = '22%', - VehicleLookupAddressPage = '22%', - VehicleLookupLicensePage = '22%', - VinLookupPage = '22%', - PartQuestionsPage = '30%', + VehicleSelectionPage = '5%', + VehicleDamagePage = '9%', + EstimatePage = '12%', + ServiceZipPage = '20%', + VehicleLookupAddressPage = '20%', + VehicleLookupLicensePage = '20%', + VinLookupPage = '15%', + PartQuestionsPage = '15%', MoldingQuestionsPage = '30%', CapabilityQuestionsPage = '30%', - VehiclePartsPage = '30%', - ServicePackagePage = '62%', - InsuranceCompanyPage = '52%', + VehiclePartsPage = '20%', + ServicePackagePage = '60%', + InsuranceCompanyPage = '60%', ServiceLocationPage = '76%', SchedulePage = '76%', MobileDetailsPage = '76%', - ContactDetailsPage = '84%', - PaymentMethodPage = '97%', + ContactDetailsPage = '85%', + PaymentMethodPage = '98.5%', OrderConfirmationPage = '100%' } \ No newline at end of file diff --git a/playwright-tests/pages/BasePage.ts b/playwright-tests/pages/BasePage.ts index 7c79dfed7..1de8c0b7f 100644 --- a/playwright-tests/pages/BasePage.ts +++ b/playwright-tests/pages/BasePage.ts @@ -25,7 +25,7 @@ export class BasePage { this.pageSpinner = page.getByRole('status'); this.buttonLoadSpin = page.getByRole('alert'); this.hamburgerMenu = this.page.getByRole('button', { name: 'Hamburger Menu (modal window)' }); - this.progressBar = this.page.locator('.progress-bar-outer.progress-bar-inner'); + this.progressBar = this.page.locator('.progress-bar-outer .progress-bar-inner'); } async nextPage() { @@ -133,22 +133,22 @@ export class BasePage { async validateProgressBar(progressPercentage: string, timeout: number = 60000) { // This section has been commented out until progress bar work is completed for parity. - // await waitUntil(async () => { - // let loaderElements = await this.page.locator('button .loader, .buy-loader, timeout, .modal-loader').all(); - // return !(await Promise.any(loaderElements.map(el => el.isVisible())).catch(() => false)); - // }); + await waitUntil(async () => { + let loaderElements = await this.page.locator('button .loader, .buy-loader, timeout, .modal-loader').all(); + return !(await Promise.any(loaderElements.map(el => el.isVisible())).catch(() => false)); + }); - // // Take a screenshot of the page before validating the progress bar - // await this.page.screenshot({ path: `test-results\\ortoni-data\\progress-bar-${Date.now()}.png`, fullPage: true }); - // // Wait until the progress bar element is attached and visible + // Take a screenshot of the page before validating the progress bar + await this.page.screenshot({ path: `test-results\\ortoni-data\\progress-bar-${Date.now()}.png`, fullPage: true }); + // Wait until the progress bar element is attached and visible - // const actualProgressPercentage = await this.progressBar.evaluate( - // async (element) => { - // await new Promise(resolve => setTimeout(resolve, 200)); - // return element.style.width || "Not Found"; - // } - // ); - // Soft.expect(actualProgressPercentage).toBe(progressPercentage); - // console.log(`Progress Bar Percentage: Actual - ${actualProgressPercentage} vs Expected - ${progressPercentage}`); + const actualProgressPercentage = await this.progressBar.evaluate( + async (element) => { + await new Promise(resolve => setTimeout(resolve, 200)); + return element.style.width || "Not Found"; + } + ); + Soft.expect(actualProgressPercentage).toBe(progressPercentage); + console.log(`Progress Bar Percentage: Actual - ${actualProgressPercentage} vs Expected - ${progressPercentage}`); } } \ No newline at end of file diff --git a/playwright-tests/pages/OrderConfirmationPage.ts b/playwright-tests/pages/OrderConfirmationPage.ts index 1f316dfad..e227479fd 100644 --- a/playwright-tests/pages/OrderConfirmationPage.ts +++ b/playwright-tests/pages/OrderConfirmationPage.ts @@ -1,7 +1,7 @@ import { expect, type Locator, type Page } from '@playwright/test'; import { BasePage } from './BasePage'; import { getTestObject } from 'framework/Typedefs'; -import { ServicePackage, PaymentType, ServiceLocation, Soft } from 'safelite-playwright-core'; +import { ServicePackage, PaymentType, ServiceLocation, Soft, waitUntil } from 'safelite-playwright-core'; import { PaymentMethod, ProgressBarPercentages } from "framework/localTypes/Enums"; import { ITestData } from 'framework/TestData'; import { step } from 'framework/localTypes/Step'; @@ -22,6 +22,8 @@ export class OrderConfirmationPage extends BasePage { readonly winshieldWiper: Locator; readonly rainDefense: Locator; readonly appointmentSummarySection: Locator; + readonly orderDetailsSection: Locator; + readonly amountPaid: Locator; constructor(page: Page) { super(page); @@ -38,14 +40,16 @@ export class OrderConfirmationPage extends BasePage { this.finalAmountDue = this.page.locator('div.amount-due'); this.cartServicePackageText = this.cartServicePackageText = this.page.locator('.cart-panel'); this.appointmentSummarySection = this.page.locator('.main .scheduleText, .main .add-to-calendar-text, .main .appointment-text, .main .duration-text-block'); + this.orderDetailsSection = this.page.locator('.cart .vin-toggle a'); + this.amountPaid = this.page.locator('.amount-paid span').nth(1); } async validateOrderConfirmationPage(testData: Partial) { // Destructure data we use const { vehicleDetails, customerDetails, servicePackage, isCashInsuranceFlow, - isPolicyFound, claimDetails, paymentDetails, isUseVehicleOnPolicy, paymentMethod, isPolicyUnverified } = testData; + isPolicyFound, claimDetails, paymentDetails, isUseVehicleOnPolicy, paymentMethod, isPolicyUnverified } = testData; await this.serviceText.waitFor({ state: "visible" }); - + Soft.expect((await this.getActualAppointmentSummary()).map(item => item.toLowerCase())).toEqual((await this.getExpectedAppointmentSummary(testData)).map(item => item.toLowerCase())); // Grab text @@ -85,17 +89,15 @@ export class OrderConfirmationPage extends BasePage { subtotalTextValue?.replaceAll(',', '') const finalAmountDueAmt = Number.parseFloat(finalAmountDueValue!.split('$')[1].replaceAll(',', '')); - - Soft.expect(subtotalAmt).toBeGreaterThan(0); // Soft.expect(deductibleAmt).toEqual(0); - - if ((paymentDetails!.paymentType === PaymentType.PayAtService || isCashInsuranceFlow) && (servicePackageAmt > 0)) { + + if ((paymentDetails!.paymentType === PaymentType.PayAtService || isCashInsuranceFlow) && (servicePackageAmt > 0)) { // Verify amount due > 0 Soft.expect(amountDueAmt).toBeGreaterThan(0); Soft.expect(finalAmountDueAmt).toBeGreaterThan(0); - if (isPolicyUnverified && PaymentType.PayWithInsurance){ + if (isPolicyUnverified && PaymentType.PayWithInsurance) { Soft.expect(finalAmountDueAmt).toContain('Verifying coverage') } } else { @@ -103,8 +105,8 @@ export class OrderConfirmationPage extends BasePage { Soft.expect(amountDueAmt).toEqual(0); Soft.expect(finalAmountDueAmt).toEqual(0); } + } } -} async getFormattedAppointmentDate(appointmentDate: string) { @@ -116,14 +118,39 @@ export class OrderConfirmationPage extends BasePage { return updatedAppointmentDate; } + async toggleOrderDetailsSection() { + await this.orderDetailsSection.click().then( + async () => { + await waitUntil(async () => { + return (await this.page.locator('.vin-toggle.expanded').evaluate(el => window.getComputedStyle(el, ':after').transform)) === 'matrix(-1, 0, 0, -1, 0, 0)'; + }); + } + ); + } + async logOrderNumber() { const sessionStorage = JSON.parse(await this.page.evaluate('sessionStorage.getItem(\'submittedState\')')); return sessionStorage.order.workOrderNumber; } + async validateSettledAmountForPia() { + const sessionStorage = JSON.parse(await this.page.evaluate('sessionStorage.getItem(\'submittedState\')')); + const isPia = sessionStorage.order.payment.isPia; + if (isPia) { + const nextGenSettledAmount = Number.parseFloat(sessionStorage.order.payment.nextGenSettledAmount); + Soft.expect(nextGenSettledAmount, `NextGen Settled Amount > 0. NextGenSettledAmount: ${nextGenSettledAmount}`).toBeGreaterThan(0); + await this.toggleOrderDetailsSection(); + let amountPaid = await this.amountPaid.textContent(); + const parsedAmount = amountPaid === null + ? console.log("Amount paid is null. Check the locator.") + : Number.parseFloat(amountPaid.replace(/[^0-9.]/g, '')); + Soft.expect(parsedAmount).toEqual(nextGenSettledAmount); + } + } + async getActualAppointmentSummary(): Promise { let appointmentSummary: string[] = []; - for (let element of await this.appointmentSummarySection.all()){ + for (let element of await this.appointmentSummarySection.all()) { let text = (await element.textContent() || "").replaceAll(/\u00A0| /g, ' '); appointmentSummary.push(text.trim()); } @@ -146,12 +173,12 @@ export class OrderConfirmationPage extends BasePage { appointmentSummary.push("Add to calendar"); appointmentSummary.push( appointmentDetails?.serviceLocation == ServiceLocation.Mobile - ? appointmentDetails?.serviceAddress - ? ("We're coming to you at" + appointmentDetails.serviceAddress.street + ", " + appointmentDetails.serviceAddress.city + ", " + appointmentDetails.serviceAddress.state + " " + appointmentDetails.serviceAddress.postalCode + "to service your " + `${vehicleDetails!.year} ${vehicleDetails!.make} ${vehicleDetails!.model}`) - : "" - : appointmentDetails?.shopAddress - ? ("You're going to a Safelite shop at" + appointmentDetails.shopAddress + "to service your " + `${vehicleDetails!.year} ${vehicleDetails!.make} ${vehicleDetails!.model}`) - : ""); + ? appointmentDetails?.serviceAddress + ? ("We're coming to you at" + appointmentDetails.serviceAddress.street + ", " + appointmentDetails.serviceAddress.city + ", " + appointmentDetails.serviceAddress.state + " " + appointmentDetails.serviceAddress.postalCode + "to service your " + `${vehicleDetails!.year} ${vehicleDetails!.make} ${vehicleDetails!.model}`) + : "" + : appointmentDetails?.shopAddress + ? ("You're going to a Safelite shop at" + appointmentDetails.shopAddress + "to service your " + `${vehicleDetails!.year} ${vehicleDetails!.make} ${vehicleDetails!.model}`) + : ""); appointmentSummary.push("Duration: " + customerDetails!.apptDuration!); return appointmentSummary; @@ -159,10 +186,11 @@ export class OrderConfirmationPage extends BasePage { @step("OrderConfirmationPage >> Validate order") async verifyOrderConfirmationPage(testData: Partial) { - await this.page.waitForURL(new RegExp('(.+)confirmation'), {timeout: 60000}); + await this.page.waitForURL(new RegExp('(.+)confirmation'), { timeout: 60000 }); await this.validateProgressBar(ProgressBarPercentages.OrderConfirmationPage); await this.validateOrderConfirmationPage(testData); const workOrderNumber = await this.logOrderNumber(); + await this.validateSettledAmountForPia(); await test.step(`Session Storage Work Order Number: ${workOrderNumber}`, async () => { console.log(`Session Storage Work Order Number: ${workOrderNumber}`); });