Adds a new environment variable to skip content site checks, improving test environment flexibility. Improves the "nextPage" function in BasePage to handle loader elements and button states more reliably. Adds support for selecting loss location in CCPolicyInfoPage to reflect claim details accurately. Updates assertion methods to use Soft assertions for smoother test execution. Adds a new test case "InsuranceMeemicNearSchoolVerified" to expand test coverage.
173 lines
No EOL
8.9 KiB
TypeScript
173 lines
No EOL
8.9 KiB
TypeScript
import { expect, type Locator, type Page } from '@playwright/test';
|
|
import { BasePage } from './BasePage';
|
|
import { getTestObject } from 'framework/Typedefs';
|
|
import { ServicePackage, PaymentType, ServiceLocation } 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;
|
|
|
|
url = process.env['BASE_URL']! + '/fmg/?fmgPage=confirmation';
|
|
|
|
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');
|
|
// this.validateURL(this.url);
|
|
}
|
|
|
|
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| /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}`);
|
|
});
|
|
}
|
|
} |