189 lines
No EOL
9.6 KiB
TypeScript
189 lines
No EOL
9.6 KiB
TypeScript
import { expect, type Locator, type Page } from '@playwright/test';
|
|
import { BasePage } from './BasePage';
|
|
import { test } from '@business-logic/types/Test';
|
|
import { ICustomerDetails, IVehicleDetails } from '@business-logic/types/CustomerDetails';
|
|
import { ServicePackage, PaymentType, PaymentMethod, AppointmentType, ProgressBarPercentages } from '@business-logic/types/Enums';
|
|
import { ITestData } from '@business-logic/types/ITestData';
|
|
import { step } from '@business-logic/types/Step';
|
|
|
|
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-value');
|
|
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, promoCode,
|
|
isPolicyFound, claimDetails, paymentDetails, isUseVehicleOnPolicy, paymentMethod } = testData;
|
|
await this.serviceText.waitFor({ state: "visible" });
|
|
|
|
expect.soft((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
|
|
expect.soft(emailTextValue).toContain(customerDetails!.email);
|
|
|
|
// Service package validations
|
|
await expect.soft(this.cartServicePackageText).toContainText(`${servicePackage}`)
|
|
if (servicePackage === ServicePackage.Premium || servicePackage === ServicePackage.Standard) {
|
|
expect.soft(servicePackageValue).toContain('New wiper blades');
|
|
}
|
|
if (servicePackage === ServicePackage.Premium) {
|
|
expect.soft(servicePackageValue).toContain('Rain Repel Treatment');
|
|
}
|
|
|
|
// Promo Code Validation
|
|
if (promoCode) {
|
|
expect.soft(servicePackageValue).toContain(`Promo code ${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(',', ''));
|
|
|
|
|
|
expect.soft(subtotalAmt).toBeGreaterThan(0);
|
|
// expect.soft(deductibleAmt).toEqual(0);
|
|
|
|
if (paymentDetails!.paymentType === PaymentType.PayAtService && (servicePackageAmt > 0)) {
|
|
// Verify amount due > 0
|
|
expect.soft(amountDueAmt).toBeGreaterThan(0);
|
|
expect.soft(finalAmountDueAmt).toBeGreaterThan(0);
|
|
} else {
|
|
// Verify amount due 0
|
|
expect.soft(amountDueAmt).toEqual(0);
|
|
expect.soft(finalAmountDueAmt).toEqual(0);
|
|
}
|
|
} else {
|
|
// Price validations for insurance users
|
|
if (servicePackage === ServicePackage.GlassOnly) {
|
|
expect.soft(servicePackageAmt).toEqual(0);
|
|
} else {
|
|
expect.soft(servicePackageAmt).toBeGreaterThan(0);
|
|
}
|
|
|
|
// Check for either "Verifying coverage" or "0.00" in price fields
|
|
expect.soft(
|
|
amountDueValue?.includes('Verifying coverage') ||
|
|
amountDueValue?.includes('0.00')
|
|
).toBeTruthy();
|
|
|
|
expect.soft(
|
|
subtotalTextValue?.includes('Verifying coverage') ||
|
|
subtotalTextValue?.includes('0.00')
|
|
).toBeTruthy();
|
|
|
|
expect.soft(
|
|
finalAmountDueValue?.includes('Verifying coverage') ||
|
|
finalAmountDueValue?.includes('0.00')
|
|
).toBeTruthy();
|
|
}
|
|
}
|
|
|
|
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 == AppointmentType.Mobile
|
|
? formattedExpectedAppointmentDate + `${customerDetails!.apptTime?.replace("arriving between", "Between").replaceAll(":00", "")}`
|
|
: appointmentDetails?.serviceLocation == AppointmentType.InShop
|
|
? formattedExpectedAppointmentDate + `${customerDetails!.apptTime}`
|
|
: formattedExpectedAppointmentDate + "Drop off before 9:30 AM"
|
|
);
|
|
appointmentSummary.push("Add to calendar");
|
|
appointmentSummary.push(
|
|
appointmentDetails?.serviceLocation == AppointmentType.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}`);
|
|
});
|
|
}
|
|
} |