Corrects the premium service package description to align with the updated service offering. The text "Rain Defense™" is replaced with "Rain repel treatment" for accuracy and consistency.
486 lines
No EOL
24 KiB
TypeScript
486 lines
No EOL
24 KiB
TypeScript
import { expect, type Locator, type Page } from '@playwright/test';
|
|
import { BasePage } from './BasePage';
|
|
import { IPaymentDetails } from '@business-logic/types/CustomerDetails';
|
|
import { AppointmentTimeslot, AppointmentType, PaymentMethod, PaymentType, ServicePackage, VehicleDamage } from '@business-logic/types/Enums';
|
|
import { PaymentPage } from './PaymentPage';
|
|
import { AfterpayPage } from './AfterpayPage';
|
|
import { PaypalPage } from './PaypalPage';
|
|
import { ITestData } from '@business-logic/types/ITestData';
|
|
import { step } from '@business-logic/types/Step';
|
|
|
|
export class PaymentMethodPage extends BasePage {
|
|
readonly page: Page;
|
|
readonly payAtServiceButton: Locator;
|
|
// readonly paypalButton: Locator;
|
|
// readonly creditCardButton: Locator;
|
|
readonly payNowButton: Locator;
|
|
readonly payWithInsuranceButton: Locator;
|
|
readonly payInFourButton: Locator;
|
|
readonly amountDueTextField: Locator;
|
|
readonly amountDueDropDown: Locator;
|
|
readonly appointmentDetailsSection: Locator;
|
|
readonly appointmentDetailsDropdown: Locator;
|
|
readonly subtotalAmountTextField: Locator;
|
|
readonly submitButton: Locator;
|
|
readonly recalibrationCheckbox: Locator;
|
|
readonly paymentPage: PaymentPage;
|
|
readonly paypalPage: PaypalPage;
|
|
|
|
// Payment detail page validation locators
|
|
readonly reviewTable: Locator;
|
|
readonly vehicleSection: Locator;
|
|
readonly damageSection: Locator;
|
|
readonly serviceDetailsSection: Locator;
|
|
readonly serviceLocationSection: Locator;
|
|
readonly appointmentDateSection: Locator;
|
|
readonly contactDetailsSection: Locator;
|
|
readonly cartPanelDetails: Locator;
|
|
readonly subtotalText: Locator;
|
|
readonly finalAmountDueText: Locator;
|
|
readonly glassServiceText: Locator;
|
|
readonly wiperBladesText: Locator;
|
|
readonly rainDefenseText: Locator;
|
|
readonly deductibleText: Locator;
|
|
|
|
url = process.env['BASE_URL']! + '/fmg/?fmgPage=payment-method';
|
|
|
|
constructor(page: Page) {
|
|
super(page);
|
|
this.page = page;
|
|
this.payAtServiceButton = this.page.locator('[buttonlabel="Pay at my appointment"]'); //this.page.getByText('Pay at time of service');
|
|
this.amountDueTextField = this.page.getByLabel('expand cart').locator('.amount-due');
|
|
this.amountDueDropDown = this.page.getByLabel('expand cart');
|
|
this.appointmentDetailsSection = this.page.locator('div .appt-details-snapshot');
|
|
this.appointmentDetailsDropdown = this.page.getByLabel('expand appointment details');
|
|
this.payWithInsuranceButton = this.page.locator('div').filter({ hasText: /^Pay with insurance$/ }).nth(1);
|
|
this.subtotalAmountTextField = this.page.locator('.sub-total span').nth(1);
|
|
this.payNowButton = this.page.locator('[buttonlabel="Pay now"]');
|
|
this.payInFourButton = this.page.locator('[buttonlabel="Pay in 4 installments"]');
|
|
this.submitButton = this.page.locator('[data-test-id="nav-bar-main-button"]');
|
|
this.recalibrationCheckbox = this.page.getByLabel('I understand after windshield');
|
|
// this.creditCardButton = page.locator('div').filter({ hasText: /^Credit or Debit$/ }).nth(1);
|
|
this.paymentPage = new PaymentPage(page);
|
|
this.paypalPage = new PaypalPage(page);
|
|
|
|
// Payment details validation locators
|
|
this.reviewTable = this.page.locator('div.review-table');
|
|
|
|
// Section locators - find by heading text
|
|
this.vehicleSection = this.page.locator('.review-table').locator('div', { hasText: 'Vehicle' }).first();
|
|
this.damageSection = this.page.locator('.review-table').locator('div', { hasText: 'Damage' }).first();
|
|
this.serviceDetailsSection = this.page.locator('.review-table').locator('div', { hasText: 'Glass service only' }).first();
|
|
this.serviceLocationSection = this.page.locator('.review-table').locator('div', { hasText: "We're coming to you" }).first();
|
|
this.appointmentDateSection = this.page.locator('.review-table').locator('div', { hasText: 'Appointment date + time' }).first();
|
|
this.contactDetailsSection = this.page.locator('.review-table').locator('div', { hasText: 'Contact details' }).first();
|
|
|
|
// Cart panel elements
|
|
this.cartPanelDetails = this.page.locator('.cart-panel');
|
|
this.subtotalText = this.page.locator('.sub-total');
|
|
this.finalAmountDueText = this.cartPanelDetails.locator('div.amount-due');
|
|
this.glassServiceText = this.page.locator('div', { hasText: /^Glass service only$/ });
|
|
this.wiperBladesText = this.page.locator('div', { hasText: /^New wiper blades$/ });
|
|
this.rainDefenseText = this.page.locator('div', { hasText: /^Rain Defense™$/ });
|
|
this.deductibleText = this.page.locator('#deductible-value');
|
|
}
|
|
|
|
async validatePaymentDetailsPage(testData: Partial<ITestData>) {
|
|
// Destructure data we use
|
|
const { vehicleDetails, customerDetails, servicePackage, promoCode,
|
|
isPolicyFound, claimDetails, paymentDetails, appointmentDetails,
|
|
isUseVehicleOnPolicy, paymentMethod, vehicleDamage } = testData;
|
|
|
|
// Wait for review table to be visible to ensure page is loaded
|
|
await this.appointmentDetailsDropdown.waitFor({state: "visible"});
|
|
await this.appointmentDetailsDropdown.click();
|
|
|
|
let expectedAppointmentDetails = new Map<string, string[]>();
|
|
expectedAppointmentDetails = await this.getExpectedVehicleDetails(testData, expectedAppointmentDetails);
|
|
expectedAppointmentDetails = await this.getExpectedVehicleDamage(testData, expectedAppointmentDetails);
|
|
expectedAppointmentDetails = await this.expectedServicePackageDetails(testData, expectedAppointmentDetails);
|
|
expectedAppointmentDetails = await this.getExpectedServiceLocation(testData, expectedAppointmentDetails);
|
|
expectedAppointmentDetails = await this.getExpectedAppointmentDate(testData, expectedAppointmentDetails);
|
|
expectedAppointmentDetails = await this.getExpectedCustomerDetails(testData, expectedAppointmentDetails);
|
|
|
|
let actualAppointmentDetails = await this.getActualAppointmentDetails();
|
|
|
|
for (const key in expectedAppointmentDetails) {
|
|
expect.soft(actualAppointmentDetails[key]?.map(item => item.toLowerCase()))
|
|
.toEqual(expectedAppointmentDetails[key].map(item => item.toLowerCase()));
|
|
}
|
|
|
|
// Expand cart to see all details
|
|
await this.amountDueDropDown.click();
|
|
await this.reviewTable.waitFor({ state: "visible" });
|
|
|
|
// Cart Validation
|
|
// Get pricing information from cart panel
|
|
if (await this.subtotalText.isVisible()) {
|
|
const subtotalValue = await this.subtotalText.innerText();
|
|
const finalAmountDueValue = await this.finalAmountDueText.innerText();
|
|
|
|
// Pricing validations differ by payment method
|
|
if (paymentMethod === PaymentMethod.SelfPay && paymentDetails?.paymentType !== PaymentType.PayWithInsurance) {
|
|
// Extract amounts for self-pay customers
|
|
const subtotalAmount = this.extractAmount(subtotalValue);
|
|
const finalAmountDueAmount = this.extractAmount(finalAmountDueValue);
|
|
|
|
// Subtotal should be greater than 0
|
|
expect.soft(subtotalAmount).toBeGreaterThan(0);
|
|
|
|
// Final amount differs based on payment type
|
|
if (paymentDetails?.paymentType === PaymentType.PayAtService) {
|
|
expect.soft(finalAmountDueAmount).toBeGreaterThan(0);
|
|
} else if (paymentDetails?.paymentType === PaymentType.Credit ||
|
|
paymentDetails?.paymentType === PaymentType.Paypal ||
|
|
paymentDetails?.paymentType === PaymentType.AfterPay) {
|
|
// For payment types that charge immediately, amount due could be 0
|
|
// This logic might need adjusting based on actual business rules
|
|
}
|
|
} else {
|
|
// For insurance payments, check for proper indicators
|
|
// TODO: Apply logic for deductible and insurance payment logic
|
|
}
|
|
|
|
// Service package validations
|
|
const servicePackageValue = await this.cartPanelDetails.textContent();
|
|
await expect.soft(this.cartPanelDetails).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`);
|
|
};
|
|
|
|
// Early Bird line item validation
|
|
if (appointmentDetails?.appointmentTimeSlot == AppointmentTimeslot.EarlyBird) {
|
|
|
|
expect.soft(servicePackageValue).toContain('Early Bird');
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Helper method to extract numeric amount from price strings like "$123.45"
|
|
*/
|
|
private extractAmount(valueString: string): number {
|
|
const matches = valueString.match(/\$([0-9,]+(\.[0-9]{2})?)/);
|
|
if (matches && matches[1]) {
|
|
return parseFloat(matches[1].replace(/,/g, ''));
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
async getAmountDue(): Promise<string> {
|
|
await expect(this.amountDueTextField).toBeVisible();
|
|
const text = await this.amountDueTextField.textContent();
|
|
if (!text) throw new Error("Amount due text is empty");
|
|
return text;
|
|
}
|
|
|
|
async getSubtotal(): Promise<string> {
|
|
await this.amountDueDropDown.click();
|
|
await expect(this.subtotalAmountTextField).toBeVisible();
|
|
const text = await this.subtotalAmountTextField.textContent();
|
|
if (!text) throw new Error("Subtotal text is empty");
|
|
return text;
|
|
}
|
|
|
|
async executePayment(paymentDetails: IPaymentDetails, isRecalVehicle: boolean) {
|
|
const browserContext = this.page.context();
|
|
|
|
switch(paymentDetails.paymentType) {
|
|
case PaymentType.Credit:
|
|
await this.selectCreditCard();
|
|
await this.nextPage();
|
|
await this.paymentPage.populateCreditCardDetails(paymentDetails);
|
|
await this.nextPage();
|
|
break;
|
|
case PaymentType.AfterPay:
|
|
await this.payInFourButton.click();
|
|
await this.nextPage();
|
|
|
|
// Capture popup
|
|
const afterpayPopup = await browserContext.waitForEvent('page');
|
|
const afterpayPage = new AfterpayPage(afterpayPopup);
|
|
|
|
// Execute payment
|
|
await afterpayPage.executeAfterpayPayment(paymentDetails);
|
|
break;
|
|
case PaymentType.Paypal:
|
|
await this.selectPaypal();
|
|
// TODO: Click paypal button
|
|
await this.nextPage();
|
|
await this.paymentPage.navigateToPaypalCheckout();
|
|
await this.paypalPage.completePaypalPurchase(paymentDetails);
|
|
break;
|
|
case PaymentType.PayAtService:
|
|
await this.selectPayAtService(isRecalVehicle);
|
|
await this.nextPage();
|
|
break;
|
|
case PaymentType.PayWithInsurance:
|
|
await this.payWithInsuranceButton.click();
|
|
await this.nextPage();
|
|
break;
|
|
default:
|
|
console.error('PaymentMethodPage >> Logic for this payment method unimplemented');
|
|
break;
|
|
}
|
|
}
|
|
|
|
async selectPaypal(){
|
|
await this.payNowButton.click();
|
|
}
|
|
l
|
|
async selectCreditCard(){
|
|
await this.payNowButton.click();
|
|
}
|
|
|
|
async selectPayAtService(isRecalVehicle: boolean){
|
|
if (await this.payAtServiceButton.isVisible()) {
|
|
await this.payAtServiceButton.click();
|
|
} else if (isRecalVehicle) {
|
|
await this.recalibrationCheckbox.click();
|
|
}
|
|
|
|
}
|
|
|
|
async verifyVAPS(): Promise<void> {
|
|
// Get Vuex state from localStorage
|
|
const vuexState = JSON.parse(await this.page.evaluate('localStorage.getItem(\'vuex\')'));
|
|
|
|
// Validate the count of FRONT WIPER parts
|
|
if (vuexState.order?.lineItems?.vaps?.length > 0) {
|
|
const frontWiperPartsCount = vuexState.order.lineItems.vaps.filter(vap =>
|
|
vap.partType === "FRONT WIPER"
|
|
).length;
|
|
|
|
await expect(frontWiperPartsCount).toBe(2);
|
|
} else {
|
|
throw new Error("No VAPS found in the order");
|
|
}
|
|
}
|
|
|
|
async getActualAppointmentDetails(): Promise<any> {
|
|
let actualAppointmentDetails = new Map<string, string[]>();
|
|
let appointmentDetailsSubSections = await this.appointmentDetailsSection.locator('.review-table .py-3').all();
|
|
|
|
for (let element of appointmentDetailsSubSections) {
|
|
let label = await element.locator('div .text-block').innerText();
|
|
//added to trim the text to remove any leading or trailing spaces (example: "expert installation " to "expert installation")
|
|
let value = (await element.locator('.review-block-content').allInnerTexts() as string[]).map(item => item.trim());
|
|
actualAppointmentDetails[label] = value;
|
|
}
|
|
return actualAppointmentDetails;
|
|
}
|
|
|
|
async getExpectedVehicleDetails(testdata: Partial<ITestData>, expectedServicePackageDetails: Map<string, string[]>): Promise<any> {
|
|
const { vehicleDetails } = testdata;
|
|
expectedServicePackageDetails["Vehicle"] = [vehicleDetails?.year + " " + vehicleDetails?.make + " " + vehicleDetails?.model];
|
|
return expectedServicePackageDetails;
|
|
}
|
|
|
|
async getExpectedVehicleDamage(testdata: Partial<ITestData>, expectedServicePackageDetails: Map<string, string[]>): Promise<any> {
|
|
|
|
const {vehicleDamage} = testdata;
|
|
|
|
let vehicleDamageText: string[] = [];
|
|
if (vehicleDamage?.find((item: VehicleDamage) => item == VehicleDamage.WindshieldOneChip)) {
|
|
vehicleDamageText.push("Windshield repair - 1 chip");
|
|
}
|
|
|
|
else if (vehicleDamage?.find((item: VehicleDamage) => item == VehicleDamage.WindshieldTwoChips)) {
|
|
vehicleDamageText.push("Windshield repair - 2 chips");
|
|
}
|
|
|
|
else if (vehicleDamage?.find((item: VehicleDamage) => item == VehicleDamage.WindshieldThreeChips)) {
|
|
vehicleDamageText.push("Windshield repair - 3 chips");
|
|
}
|
|
|
|
if (vehicleDamage?.find((item: VehicleDamage) => item == VehicleDamage.WindshieldCrack)) {
|
|
vehicleDamageText.push("Windshield crack");
|
|
}
|
|
|
|
if (vehicleDamage?.find((item: VehicleDamage) => item == VehicleDamage.DriverVentGlass)) {
|
|
vehicleDamageText.includes("Side door - Driver side") ? vehicleDamageText[vehicleDamageText.length - 1 ] += "\nVent glass" : vehicleDamageText.push("Side door - Driver side", "Vent glass");
|
|
}
|
|
|
|
if (vehicleDamage?.find((item: VehicleDamage) => item == VehicleDamage.DriverFrontDoor)) {
|
|
vehicleDamageText.includes("Side door - Driver side") ? vehicleDamageText[vehicleDamageText.length - 1 ] += "\nFront door" : vehicleDamageText.push("Side door - Driver side", "Front door");
|
|
}
|
|
|
|
if (vehicleDamage?.find((item: VehicleDamage) => item == VehicleDamage.DriverRearDoor)) {
|
|
vehicleDamageText.includes("Side door - Driver side") ? vehicleDamageText[vehicleDamageText.length - 1 ] += "\nBack door" : vehicleDamageText.push("Side door - Driver side", "Back door");
|
|
}
|
|
|
|
if (vehicleDamage?.find((item: VehicleDamage) => item == VehicleDamage.DriverQuarterPanel)) {
|
|
vehicleDamageText.includes("Side door - Driver side") ? vehicleDamageText[vehicleDamageText.length - 1 ] += "\nQuarter panel" : vehicleDamageText.push("Side door - Driver side", "Quarter panel");
|
|
}
|
|
|
|
if (vehicleDamage?.find((item: VehicleDamage) => item == VehicleDamage.PassengerVentGlass)) {
|
|
vehicleDamageText.includes("Side door - Passenger side") ? vehicleDamageText[vehicleDamageText.length - 1 ] += "\nVent glass" : vehicleDamageText.push("Side door - Passenger side", "Vent glass");
|
|
}
|
|
|
|
if (vehicleDamage?.find((item: VehicleDamage) => item == VehicleDamage.PassengerFrontDoor)) {
|
|
vehicleDamageText.includes("Side door - Passenger side") ? vehicleDamageText[vehicleDamageText.length - 1 ] += "\nFront door" : vehicleDamageText.push("Side door - Passenger side", "Front door");
|
|
}
|
|
|
|
if (vehicleDamage?.find((item: VehicleDamage) => item == VehicleDamage.PassengerRearDoor)) {
|
|
vehicleDamageText.includes("Side door - Passenger side") ? vehicleDamageText[vehicleDamageText.length - 1 ] += "\nBack door" : vehicleDamageText.push("Side door - Passenger side", "Back door");
|
|
}
|
|
|
|
if (vehicleDamage?.find((item: VehicleDamage) => item == VehicleDamage.PassengerQuarterPanel)) {
|
|
vehicleDamageText.includes("Side door - Passenger side") ? vehicleDamageText[vehicleDamageText.length - 1 ] += "\nQuarter panel" : vehicleDamageText.push("Side door - Passenger side", "Quarter panel");
|
|
}
|
|
|
|
if (vehicleDamage?.find((item: VehicleDamage) => item == VehicleDamage.RearWindow || item == VehicleDamage.RearSliding)) {
|
|
vehicleDamageText.push("Rear window");
|
|
}
|
|
|
|
expectedServicePackageDetails["Damage"] = vehicleDamageText;
|
|
return expectedServicePackageDetails;
|
|
}
|
|
|
|
async expectedServicePackageDetails(testData: Partial<ITestData>, expectedServicePackageDetails: Map<string, string[]>): Promise<any> {
|
|
const {servicePackage} = testData;
|
|
|
|
let localStorage= JSON.parse(await this.page.evaluate('localStorage.getItem(\'vuex\')'));
|
|
let isRepair = localStorage.order.damage.isRepair as boolean;
|
|
let isInsurance = localStorage.order.payment.isInsurance as boolean;
|
|
let hasNonWindshieldGlass: boolean = false;
|
|
if (!isRepair) {
|
|
hasNonWindshieldGlass = localStorage.order.lineItems.glassParts.find((item: any) => item.partType !== "WINDSHIELD") ? true : false;
|
|
}
|
|
let isCaliforniaState = localStorage.order.serviceLocation.state as string == 'CA' ? true : false;
|
|
let hasRecalPart: boolean = false;
|
|
if (!isRepair) {
|
|
hasRecalPart = localStorage.order.lineItems.glassParts.find((item: any) => item.requiresRecalibration === true) ? true : false;
|
|
}
|
|
let recalRequired = !isRepair && (isInsurance || isCaliforniaState) && hasRecalPart
|
|
let stringForRepair: string[] = ["Expert windshield repair", "Exclusive resin sealant", "Nationwide lifetime guarantee"];
|
|
let stringIfRecal = isRepair
|
|
? ""
|
|
: recalRequired
|
|
? " and recalibration"
|
|
: "";
|
|
let stringForReplace: string[] = [hasNonWindshieldGlass ? "New replacement glass" : "New replacement windshield", "Expert installation" + `${stringIfRecal}`, "Nationwide lifetime warranty"];
|
|
switch (servicePackage)
|
|
{
|
|
case ServicePackage.GlassOnly:
|
|
expectedServicePackageDetails["Glass service only"] = isRepair
|
|
? stringForRepair
|
|
: stringForReplace;
|
|
break;
|
|
case ServicePackage.Standard:
|
|
stringForRepair.push("New wiper blades");
|
|
stringForReplace.push("New wiper blades");
|
|
expectedServicePackageDetails["Standard service"] = isRepair
|
|
? stringForRepair
|
|
: stringForReplace;
|
|
break;
|
|
case ServicePackage.Premium:
|
|
stringForRepair.push("New wiper blades", "Rain repel treatment");
|
|
stringForReplace.push("New wiper blades", "Rain repel treatment");
|
|
expectedServicePackageDetails["Premium service"] = isRepair
|
|
? stringForRepair
|
|
: stringForReplace;
|
|
break;
|
|
}
|
|
return expectedServicePackageDetails;
|
|
}
|
|
|
|
async getExpectedServiceLocation(testData: Partial<ITestData>, expectedServicePackageDetails: Map<string, string[]>): Promise<any> {
|
|
const { appointmentDetails } = testData;
|
|
let serviceLocationTitle = appointmentDetails?.serviceLocation == AppointmentType.Mobile
|
|
? "We're coming to you"
|
|
: "You're going to a Safelite shop";
|
|
let serviceLocation: string[] = [];
|
|
|
|
serviceLocation.push(
|
|
appointmentDetails?.serviceLocation == AppointmentType.Mobile
|
|
? appointmentDetails?.serviceAddress
|
|
? appointmentDetails.serviceAddress.street + ", " + appointmentDetails.serviceAddress.city + ", " + appointmentDetails.serviceAddress.state + " " + appointmentDetails.serviceAddress.postalCode
|
|
: ""
|
|
: appointmentDetails?.shopAddress
|
|
? appointmentDetails.shopAddress
|
|
: ""
|
|
);
|
|
|
|
expectedServicePackageDetails[serviceLocationTitle] = serviceLocation;
|
|
return expectedServicePackageDetails;
|
|
}
|
|
|
|
async getExpectedAppointmentDate(testData: Partial<ITestData>, expectedServicePackageDetails: Map<string, string[]>): Promise<any> {
|
|
const { customerDetails, appointmentDetails } = testData;
|
|
let appointmentDateText: string[] = [];
|
|
const isMobileAppointment = appointmentDetails?.serviceLocation == AppointmentType.Mobile
|
|
if (isMobileAppointment) {
|
|
let localStorage= JSON.parse(await this.page.evaluate('localStorage.getItem(\'vuex\')'));
|
|
let jobMinMinutes = localStorage.order.schedule.jobMinMinutes as number;
|
|
let jobMaxMinutes = localStorage.order.schedule.jobMaxMinutes as number;
|
|
|
|
if (jobMinMinutes < 60) {
|
|
customerDetails!.apptDuration = `${jobMinMinutes} - ${jobMaxMinutes} minutes`;
|
|
} else {
|
|
const minHours = Math.floor(jobMinMinutes / 60);
|
|
const maxHours = Math.floor(jobMaxMinutes / 60);
|
|
customerDetails!.apptDuration = `${minHours} - ${maxHours} hours`;
|
|
}
|
|
}
|
|
|
|
appointmentDateText.push(
|
|
customerDetails?.apptDate ? await this.getFormattedAppointmentDate(customerDetails.apptDate) + " " + customerDetails?.apptTime?.replace("-", "—") : "",
|
|
customerDetails?.apptDuration ? "Estimated appointment length: " + customerDetails.apptDuration : ""
|
|
);
|
|
|
|
expectedServicePackageDetails["Appointment date + time"] = appointmentDateText;
|
|
return expectedServicePackageDetails;
|
|
}
|
|
|
|
async getExpectedCustomerDetails(testData: Partial<ITestData>, expectedServicePackageDetails: Map<string, string[]>): Promise<any> {
|
|
const { customerDetails } = testData;
|
|
let customerDetailsText: string[] = [];
|
|
|
|
customerDetailsText.push(
|
|
customerDetails?.firstName.toUpperCase() + " " + customerDetails?.lastName.toUpperCase(),
|
|
customerDetails?.email ? customerDetails?.email.toUpperCase() : "",
|
|
customerDetails?.phoneNumber ? customerDetails?.phoneNumber : "",
|
|
"Opted out of text message updates"
|
|
);
|
|
|
|
expectedServicePackageDetails["Contact details"] = customerDetailsText;
|
|
return expectedServicePackageDetails;
|
|
}
|
|
|
|
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', year: 'numeric', month: 'long', day: 'numeric' });
|
|
return updatedAppointmentDate;
|
|
}
|
|
|
|
@step("PaymentMethodPage >> Select Payment Method: ")
|
|
async handlePaymentMethodPage(testData: Partial<ITestData>) {
|
|
const { servicePackage, isRecalVehicle, paymentDetails } = testData;
|
|
|
|
await this.validateProgressBar("92");
|
|
await this.validatePaymentDetailsPage(testData);
|
|
|
|
// Verify VAPS wipers on backend for standard and premium packages
|
|
if (servicePackage === ServicePackage.Standard || servicePackage === ServicePackage.Premium) {
|
|
await this.verifyVAPS();
|
|
}
|
|
if (paymentDetails?.paymentType) {
|
|
await this.executePayment(paymentDetails!, isRecalVehicle!);
|
|
} else {
|
|
await this.nextPage();
|
|
}
|
|
}
|
|
} |