adding settlementamount validation and progress bar validation

This commit is contained in:
kpatel8hs4io 2025-10-01 10:39:29 -04:00
parent 1f668526b0
commit f8935312ad
3 changed files with 74 additions and 46 deletions

View file

@ -5,23 +5,23 @@ export enum PaymentMethod {
} }
export enum ProgressBarPercentages { export enum ProgressBarPercentages {
VehicleSelectionPage = '8%', VehicleSelectionPage = '5%',
VehicleDamagePage = '11%', VehicleDamagePage = '9%',
EstimatePage = '18%', EstimatePage = '12%',
ServiceZipPage = '22%', ServiceZipPage = '20%',
VehicleLookupAddressPage = '22%', VehicleLookupAddressPage = '20%',
VehicleLookupLicensePage = '22%', VehicleLookupLicensePage = '20%',
VinLookupPage = '22%', VinLookupPage = '15%',
PartQuestionsPage = '30%', PartQuestionsPage = '15%',
MoldingQuestionsPage = '30%', MoldingQuestionsPage = '30%',
CapabilityQuestionsPage = '30%', CapabilityQuestionsPage = '30%',
VehiclePartsPage = '30%', VehiclePartsPage = '20%',
ServicePackagePage = '62%', ServicePackagePage = '60%',
InsuranceCompanyPage = '52%', InsuranceCompanyPage = '60%',
ServiceLocationPage = '76%', ServiceLocationPage = '76%',
SchedulePage = '76%', SchedulePage = '76%',
MobileDetailsPage = '76%', MobileDetailsPage = '76%',
ContactDetailsPage = '84%', ContactDetailsPage = '85%',
PaymentMethodPage = '97%', PaymentMethodPage = '98.5%',
OrderConfirmationPage = '100%' OrderConfirmationPage = '100%'
} }

View file

@ -25,7 +25,7 @@ export class BasePage {
this.pageSpinner = page.getByRole('status'); this.pageSpinner = page.getByRole('status');
this.buttonLoadSpin = page.getByRole('alert'); this.buttonLoadSpin = page.getByRole('alert');
this.hamburgerMenu = this.page.getByRole('button', { name: 'Hamburger Menu (modal window)' }); 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() { async nextPage() {
@ -133,22 +133,22 @@ export class BasePage {
async validateProgressBar(progressPercentage: string, timeout: number = 60000) { async validateProgressBar(progressPercentage: string, timeout: number = 60000) {
// This section has been commented out until progress bar work is completed for parity. // This section has been commented out until progress bar work is completed for parity.
// await waitUntil(async () => { await waitUntil(async () => {
// let loaderElements = await this.page.locator('button .loader, .buy-loader, timeout, .modal-loader').all(); 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)); return !(await Promise.any(loaderElements.map(el => el.isVisible())).catch(() => false));
// }); });
// // Take a screenshot of the page before validating the progress bar // 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 }); 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 // Wait until the progress bar element is attached and visible
// const actualProgressPercentage = await this.progressBar.evaluate( const actualProgressPercentage = await this.progressBar.evaluate(
// async (element) => { async (element) => {
// await new Promise(resolve => setTimeout(resolve, 200)); await new Promise(resolve => setTimeout(resolve, 200));
// return element.style.width || "Not Found"; return element.style.width || "Not Found";
// } }
// ); );
// Soft.expect(actualProgressPercentage).toBe(progressPercentage); Soft.expect(actualProgressPercentage).toBe(progressPercentage);
// console.log(`Progress Bar Percentage: Actual - ${actualProgressPercentage} vs Expected - ${progressPercentage}`); console.log(`Progress Bar Percentage: Actual - ${actualProgressPercentage} vs Expected - ${progressPercentage}`);
} }
} }

View file

@ -1,7 +1,7 @@
import { expect, type Locator, type Page } from '@playwright/test'; import { expect, type Locator, type Page } from '@playwright/test';
import { BasePage } from './BasePage'; import { BasePage } from './BasePage';
import { getTestObject } from 'framework/Typedefs'; 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 { PaymentMethod, ProgressBarPercentages } from "framework/localTypes/Enums";
import { ITestData } from 'framework/TestData'; import { ITestData } from 'framework/TestData';
import { step } from 'framework/localTypes/Step'; import { step } from 'framework/localTypes/Step';
@ -22,6 +22,8 @@ export class OrderConfirmationPage extends BasePage {
readonly winshieldWiper: Locator; readonly winshieldWiper: Locator;
readonly rainDefense: Locator; readonly rainDefense: Locator;
readonly appointmentSummarySection: Locator; readonly appointmentSummarySection: Locator;
readonly orderDetailsSection: Locator;
readonly amountPaid: Locator;
constructor(page: Page) { constructor(page: Page) {
super(page); super(page);
@ -38,14 +40,16 @@ export class OrderConfirmationPage extends BasePage {
this.finalAmountDue = this.page.locator('div.amount-due'); this.finalAmountDue = this.page.locator('div.amount-due');
this.cartServicePackageText = this.cartServicePackageText = this.page.locator('.cart-panel'); 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.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<ITestData>) { async validateOrderConfirmationPage(testData: Partial<ITestData>) {
// Destructure data we use // Destructure data we use
const { vehicleDetails, customerDetails, servicePackage, isCashInsuranceFlow, 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" }); await this.serviceText.waitFor({ state: "visible" });
Soft.expect((await this.getActualAppointmentSummary()).map(item => item.toLowerCase())).toEqual((await this.getExpectedAppointmentSummary(testData)).map(item => item.toLowerCase())); Soft.expect((await this.getActualAppointmentSummary()).map(item => item.toLowerCase())).toEqual((await this.getExpectedAppointmentSummary(testData)).map(item => item.toLowerCase()));
// Grab text // Grab text
@ -85,17 +89,15 @@ export class OrderConfirmationPage extends BasePage {
subtotalTextValue?.replaceAll(',', '') subtotalTextValue?.replaceAll(',', '')
const finalAmountDueAmt = Number.parseFloat(finalAmountDueValue!.split('$')[1].replaceAll(',', '')); const finalAmountDueAmt = Number.parseFloat(finalAmountDueValue!.split('$')[1].replaceAll(',', ''));
Soft.expect(subtotalAmt).toBeGreaterThan(0); Soft.expect(subtotalAmt).toBeGreaterThan(0);
// Soft.expect(deductibleAmt).toEqual(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 // Verify amount due > 0
Soft.expect(amountDueAmt).toBeGreaterThan(0); Soft.expect(amountDueAmt).toBeGreaterThan(0);
Soft.expect(finalAmountDueAmt).toBeGreaterThan(0); Soft.expect(finalAmountDueAmt).toBeGreaterThan(0);
if (isPolicyUnverified && PaymentType.PayWithInsurance){ if (isPolicyUnverified && PaymentType.PayWithInsurance) {
Soft.expect(finalAmountDueAmt).toContain('Verifying coverage') Soft.expect(finalAmountDueAmt).toContain('Verifying coverage')
} }
} else { } else {
@ -103,8 +105,8 @@ export class OrderConfirmationPage extends BasePage {
Soft.expect(amountDueAmt).toEqual(0); Soft.expect(amountDueAmt).toEqual(0);
Soft.expect(finalAmountDueAmt).toEqual(0); Soft.expect(finalAmountDueAmt).toEqual(0);
} }
}
} }
}
async getFormattedAppointmentDate(appointmentDate: string) { async getFormattedAppointmentDate(appointmentDate: string) {
@ -116,14 +118,39 @@ export class OrderConfirmationPage extends BasePage {
return updatedAppointmentDate; 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() { async logOrderNumber() {
const sessionStorage = JSON.parse(await this.page.evaluate('sessionStorage.getItem(\'submittedState\')')); const sessionStorage = JSON.parse(await this.page.evaluate('sessionStorage.getItem(\'submittedState\')'));
return sessionStorage.order.workOrderNumber; 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<string[]> { async getActualAppointmentSummary(): Promise<string[]> {
let appointmentSummary: string[] = []; 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|&nbsp;/g, ' '); let text = (await element.textContent() || "").replaceAll(/\u00A0|&nbsp;/g, ' ');
appointmentSummary.push(text.trim()); appointmentSummary.push(text.trim());
} }
@ -146,12 +173,12 @@ export class OrderConfirmationPage extends BasePage {
appointmentSummary.push("Add to calendar"); appointmentSummary.push("Add to calendar");
appointmentSummary.push( appointmentSummary.push(
appointmentDetails?.serviceLocation == ServiceLocation.Mobile appointmentDetails?.serviceLocation == ServiceLocation.Mobile
? appointmentDetails?.serviceAddress ? 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}`) ? ("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 : appointmentDetails?.shopAddress
? ("You're going to a Safelite shop at" + appointmentDetails.shopAddress + "to service your " + `${vehicleDetails!.year} ${vehicleDetails!.make} ${vehicleDetails!.model}`) ? ("You're going to a Safelite shop at" + appointmentDetails.shopAddress + "to service your " + `${vehicleDetails!.year} ${vehicleDetails!.make} ${vehicleDetails!.model}`)
: ""); : "");
appointmentSummary.push("Duration: " + customerDetails!.apptDuration!); appointmentSummary.push("Duration: " + customerDetails!.apptDuration!);
return appointmentSummary; return appointmentSummary;
@ -159,10 +186,11 @@ export class OrderConfirmationPage extends BasePage {
@step("OrderConfirmationPage >> Validate order") @step("OrderConfirmationPage >> Validate order")
async verifyOrderConfirmationPage(testData: Partial<ITestData>) { async verifyOrderConfirmationPage(testData: Partial<ITestData>) {
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.validateProgressBar(ProgressBarPercentages.OrderConfirmationPage);
await this.validateOrderConfirmationPage(testData); await this.validateOrderConfirmationPage(testData);
const workOrderNumber = await this.logOrderNumber(); const workOrderNumber = await this.logOrderNumber();
await this.validateSettledAmountForPia();
await test.step(`Session Storage Work Order Number: ${workOrderNumber}`, async () => { await test.step(`Session Storage Work Order Number: ${workOrderNumber}`, async () => {
console.log(`Session Storage Work Order Number: ${workOrderNumber}`); console.log(`Session Storage Work Order Number: ${workOrderNumber}`);
}); });