DigitalConsumer.FixMyGlass/playwright-tests/pages/OrderConfirmationPage.ts
maguire-arman 458e552d6b Removes URL declaration from page classes
Removes the explicit URL declaration from the page classes.

The URL validation and navigation are now handled directly within the tests, providing greater flexibility and control over test execution and removing the need to manage URLs within each page object.
2025-07-14 16:13:56 -04:00

170 lines
No EOL
8.8 KiB
TypeScript

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 { PaymentMethod, ProgressBarPercentages } from "framework/localTypes/Enums";
import { ITestData } from 'framework/TestData';
import { step } from 'framework/localTypes/Step';
const test = getTestObject();
export class OrderConfirmationPage extends BasePage {
readonly page: Page;
readonly serviceText: Locator;
readonly emailText: Locator;
readonly apptDateText: Locator;
readonly amountDueText: Locator;
readonly viewCartButton: Locator;
readonly deductibleText: Locator;
readonly subtotalText: Locator;
readonly finalAmountDue: Locator;
readonly cartServicePackageText: Locator;
readonly winshieldWiper: Locator;
readonly rainDefense: Locator;
readonly appointmentSummarySection: Locator;
constructor(page: Page) {
super(page);
this.page = page;
this.serviceText = this.page.locator('p', {
hasText: /to service your/
});
this.emailText = this.emailText = this.page.getByText('A confirmation email was sent');
this.apptDateText = this.page.locator('[class="scheduleText"]');
this.amountDueText = this.page.getByLabel('expand cart');
this.viewCartButton = this.page.locator('#cart-dropdown-head');
this.deductibleText = this.page.locator('.deductible');
this.subtotalText = this.page.locator('.sub-total');
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');
}
async validateOrderConfirmationPage(testData: Partial<ITestData>) {
// Destructure data we use
const { vehicleDetails, customerDetails, servicePackage, isCashInsuranceFlow,
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
const emailTextValue = await this.emailText.textContent();
const servicePackageValue = await this.cartServicePackageText.textContent();
const amountDueValue = await this.amountDueText.textContent();
// const deductibleTextValue = await this.deductibleText.textContent();
const subtotalTextValue = await this.subtotalText.textContent();
const finalAmountDueValue = await this.finalAmountDue.textContent();
// Extract service package price
const servicePackageAmt = Number.parseFloat(servicePackageValue!.split('$')[1].replaceAll(',', ''));
// General Validations
Soft.expect(emailTextValue?.toLowerCase()).toContain(customerDetails!.email);
// Service package validations
await Soft.expect(servicePackageValue).toContain(`${servicePackage}`)
if (servicePackage === ServicePackage.Premium || servicePackage === ServicePackage.Standard) {
Soft.expect(servicePackageValue).toContain('New wiper blades');
}
if (servicePackage === ServicePackage.Premium) {
Soft.expect(servicePackageValue).toContain('Rain Repel Treatment');
}
// Promo Code Validation
if (paymentDetails!.promoCode) {
expect.soft(servicePackageValue).toContain(`Promo code ${paymentDetails!.promoCode} applied`);
};
if (paymentMethod === PaymentMethod.SelfPay || (paymentDetails?.paymentType && paymentDetails?.paymentType !== PaymentType.PayWithInsurance)) {
// Cart validation for non insurance users
// Extract numbers
const amountDueAmt = Number.parseFloat(amountDueValue!.split('$')[1].replaceAll(',', ''));
// const deductibleAmt = deductibleTextValue? Number.parseFloat(deductibleTextValue.split('$')[1].replaceAll(',', '')): 0;
const subtotalAmt = Number.parseFloat(subtotalTextValue!.split('$')[1].replaceAll(',', ''));
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)) {
// Verify amount due > 0
Soft.expect(amountDueAmt).toBeGreaterThan(0);
Soft.expect(finalAmountDueAmt).toBeGreaterThan(0);
if (isPolicyUnverified && PaymentType.PayWithInsurance){
Soft.expect(finalAmountDueAmt).toContain('Verifying coverage')
}
} else {
// Verify amount due 0
Soft.expect(amountDueAmt).toEqual(0);
Soft.expect(finalAmountDueAmt).toEqual(0);
}
}
}
async getFormattedAppointmentDate(appointmentDate: string) {
// Parse the original date
let parsedAppointmentDate = new Date(`${appointmentDate}` + 'T00:00:00');
// Format the new date as a string
let updatedAppointmentDate = parsedAppointmentDate.toLocaleDateString('en-US', { weekday: 'long', month: 'long', day: 'numeric' });
return updatedAppointmentDate;
}
async logOrderNumber() {
const sessionStorage = JSON.parse(await this.page.evaluate('sessionStorage.getItem(\'submittedState\')'));
return sessionStorage.order.workOrderNumber;
}
async getActualAppointmentSummary(): Promise<string[]> {
let appointmentSummary: string[] = [];
for (let element of await this.appointmentSummarySection.all()){
let text = (await element.textContent() || "").replaceAll(/\u00A0|&nbsp;/g, ' ');
appointmentSummary.push(text.trim());
}
return appointmentSummary;
}
async getExpectedAppointmentSummary(testData: Partial<ITestData>): Promise<string[]> {
const { appointmentDetails, customerDetails, vehicleDetails } = testData;
let appointmentSummary: string[] = [];
// Format the expected appointment date
const formattedExpectedAppointmentDate = await this.getFormattedAppointmentDate(customerDetails!.apptDate!);
appointmentSummary.push(
appointmentDetails?.serviceLocation == ServiceLocation.Mobile
? formattedExpectedAppointmentDate + `${customerDetails!.apptTime?.replace("arriving between", "Between").replaceAll(":00", "")}`
: appointmentDetails?.serviceLocation == ServiceLocation.InShop
? formattedExpectedAppointmentDate + `${customerDetails!.apptTime}`
: formattedExpectedAppointmentDate + "Drop off before 9:30 AM"
);
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}`)
: "");
appointmentSummary.push("Duration: " + customerDetails!.apptDuration!);
return appointmentSummary;
}
@step("OrderConfirmationPage >> Validate order")
async verifyOrderConfirmationPage(testData: Partial<ITestData>) {
await this.page.waitForURL(new RegExp('(.+)confirmation'), {timeout: 60000});
await this.validateProgressBar(ProgressBarPercentages.OrderConfirmationPage);
await this.validateOrderConfirmationPage(testData);
const workOrderNumber = await this.logOrderNumber();
await test.step(`Session Storage Work Order Number: ${workOrderNumber}`, async () => {
console.log(`Session Storage Work Order Number: ${workOrderNumber}`);
});
}
}