import { expect, type Locator, type Page } from '@playwright/test'; import { BasePage } from './BasePage'; import { IPaymentDetails, Soft, waitUntil } from 'safelite-playwright-core'; import { AppointmentTimeslot, ServiceLocation, PaymentType, ServicePackage, VehicleDamage, } from 'safelite-playwright-core'; import { PaymentMethod, ProgressBarPercentages } from 'framework/localTypes/Enums'; import { PaymentPage } from './PaymentPage'; import { AfterpayPage } from './AfterpayPage'; import { PaypalPage } from './PaypalPage'; import { ITestData } from 'framework/TestData'; import { step } from 'framework/localTypes/Step'; import { IExperiments } from 'framework/localTypes/IExperiments'; import { PaymentAdyenPage } from './PaymentAdyenPage'; 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 paymentAdyenPage: PaymentAdyenPage; readonly paypalPage: PaypalPage; readonly afterpayPage: AfterpayPage readonly afterPayBreakoutSection: Locator; readonly afterPayToggle: Locator; // Payment detail page validation locators readonly reviewTable: Locator; readonly serviceDetailsSection: Locator; readonly serviceLocationDateandTimeSection: Locator; readonly vehicleDamageLocationsSection: 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; 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.locator('label:has(>input[name=\'recalAckOptIn\'])'); // this.creditCardButton = page.locator('div').filter({ hasText: /^Credit or Debit$/ }).nth(1); this.paymentPage = new PaymentPage(page); this.paymentAdyenPage = new PaymentAdyenPage(page); this.paypalPage = new PaypalPage(page); this.afterpayPage = new AfterpayPage(page); // Payment details validation locators this.reviewTable = this.page.locator('div.review-table'); // Section locators - find by heading text this.serviceLocationDateandTimeSection = this.page.locator('.review-table').locator('div .service-location'); this.vehicleDamageLocationsSection = this.page.locator('.review-table').locator('div.py-3[damagelocationswidgetname="DamageLocationsWidget"]'); 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'); this.afterPayBreakoutSection = this.page.locator('div.alert-info:has(.after-pay)'); this.afterPayToggle = this.page.locator('.after-pay-toggle'); } async validatePaymentDetailsPage(testData: Partial) { // Destructure data we use const { vehicleDetails, customerDetails, servicePackage, flow, 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().then( async () => { await waitUntil(async () => { return (await this.page.locator('.review-toggle.expanded').evaluate(el => window.getComputedStyle(el, ':after').transform)) === 'matrix(-1, 0, 0, -1, 0, 0)'; }); } ); let expectedAppointmentDetails = new Map(); expectedAppointmentDetails = await this.getExpectedServiceLocationDateAndTimeSection(testData, expectedAppointmentDetails); expectedAppointmentDetails = await this.getExpectedVehicleDamageAndVehicle(testData, expectedAppointmentDetails); expectedAppointmentDetails = await this.getExpectedContactDetails(testData, expectedAppointmentDetails); expectedAppointmentDetails = await this.getExpectedTextServiceUpdatesOptInOrOut(testData, expectedAppointmentDetails); let actualAppointmentDetails = await this.getActualAppointmentDetails(); for (const key in expectedAppointmentDetails) { Soft.expect(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 Soft.expect(subtotalAmount).toBeGreaterThan(0); // Final amount differs based on payment type if (paymentDetails?.paymentType === PaymentType.PayAtService) { Soft.expect(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 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`); }; // Early Bird line item validation if (appointmentDetails?.appointmentTimeSlot == AppointmentTimeslot.EarlyBird) { Soft.expect(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 { 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 { 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(testData: Partial) { const browserContext = this.page.context(); const { paymentDetails, isRecalVehicle, experiments } = testData; switch (paymentDetails!.paymentType) { case PaymentType.Credit: await this.selectCreditCard(); await this.nextPage(); experiments!.isAdyenPayments ? await this.paymentAdyenPage.populateAdyenCreditCardDetails(testData) : await this.paymentPage.populateCreditCardDetails(paymentDetails!); break; case PaymentType.AfterPay: await this.payInFourButton.click(); await this.continueButton.click(); if (experiments?.isAdyenPayments) { await this.paymentAdyenPage.afterPayButton.click(); await this.paymentAdyenPage.navigateToAfterPayButton.click(); await this.afterpayPage.executeAfterpayPayment(paymentDetails!); } else { // 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(); const paypalPage = experiments?.isAdyenPayments ? await this.paymentAdyenPage.navigateToAdyenPaypalCheckout() : await this.paymentPage.navigateToPaypalCheckout(); /*if (experiments?.isAdyenPayments) { // Capture popup const payPalPopup = await this.page.waitForEvent('popup'); const paypalPage = new PaypalPage(payPalPopup); paypalPage.completePaypalPurchase(testData); } else { await this.paypalPage.completePaypalPurchase(testData); }*/ await paypalPage.completePaypalPurchase(testData); 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) { if (await this.recalibrationCheckbox.isVisible()) { await this.recalibrationCheckbox.click(); } } } async verifyVAPS(): Promise { // 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 { let actualAppointmentDetails = new Map(); 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, expectedServicePackageDetails: Map): Promise { const { vehicleDetails } = testdata; expectedServicePackageDetails["Vehicle"] = [vehicleDetails?.year + " " + vehicleDetails?.make + " " + vehicleDetails?.model]; return expectedServicePackageDetails; } async getExpectedVehicleDamageAndVehicle(testdata: Partial, expectedServicePackageDetails: Map): Promise { const { vehicleDetails, vehicleDamage } = testdata; let vehicleDamageText: string = ''; if (vehicleDamage?.find((item: VehicleDamage) => item == VehicleDamage.WindshieldOneChip || item == VehicleDamage.WindshieldTwoChips || item == VehicleDamage.WindshieldThreeChips)) { vehicleDamageText = "Repair the windshield of your"; } if (vehicleDamage?.find((item: VehicleDamage) => item == VehicleDamage.WindshieldCrack)) { vehicleDamageText = vehicleDamage?.length > 1 ? "Replace the Windshield" : "Replace the windshield"; } if (vehicleDamage?.find((item: VehicleDamage) => item == VehicleDamage.DriverVentGlass) && !vehicleDamage?.find((item: VehicleDamage) => item == VehicleDamage.WindshieldCrack)) { vehicleDamageText.includes("Replace") ? vehicleDamageText += ", Driver Vent Glass" : "Replace the Driver Vent Glass"; } if (vehicleDamage?.find((item: VehicleDamage) => item == VehicleDamage.DriverFrontDoor)) { vehicleDamageText.includes("Replace") ? vehicleDamageText += ", Driver Front Glass" : "Replace the Driver Front Glass"; } if (vehicleDamage?.find((item: VehicleDamage) => item == VehicleDamage.DriverRearDoor)) { vehicleDamageText.includes("Replace") ? vehicleDamageText += ", Driver Back Glass" : "Replace the Driver Back Glass"; } if (vehicleDamage?.find((item: VehicleDamage) => item == VehicleDamage.DriverVentGlass) && vehicleDamage?.find((item: VehicleDamage) => item == VehicleDamage.WindshieldCrack)) { vehicleDamageText.includes("Replace") ? vehicleDamageText += ", Driver Vent Glass" : "Replace the Driver Vent Glass"; } if (vehicleDamage?.find((item: VehicleDamage) => item == VehicleDamage.DriverQuarterPanel)) { vehicleDamageText.includes("Replace") ? vehicleDamageText += ", Driver Quarter Glass" : "Replace the Driver Quarter Glass"; } if (vehicleDamage?.find((item: VehicleDamage) => item == VehicleDamage.PassengerVentGlass)) { vehicleDamageText.includes("Replace") ? vehicleDamageText += ", Passenger Vent Glass" : "Replace the Passenger Vent Glass"; } if (vehicleDamage?.find((item: VehicleDamage) => item == VehicleDamage.PassengerFrontDoor)) { vehicleDamageText.includes("Replace") ? vehicleDamageText += ", Passenger Front Glass" : "Replace the Passenger Front Glass"; } if (vehicleDamage?.find((item: VehicleDamage) => item == VehicleDamage.PassengerRearDoor)) { vehicleDamageText.includes("Replace") ? vehicleDamageText += ", Passenger Back Glass" : "Replace the Passenger Back Glass"; } if (vehicleDamage?.find((item: VehicleDamage) => item == VehicleDamage.PassengerQuarterPanel)) { vehicleDamageText.includes("Replace") ? vehicleDamageText += ", Passenger Quarter Glass" : "Replace the Passenger Quarter Glass"; } if (vehicleDamage?.find((item: VehicleDamage) => item == VehicleDamage.RearWindow || item == VehicleDamage.RearSliding)) { vehicleDamageText.includes("Replace") ? vehicleDamageText += ", Back Glass" : "Replace the Back Glass"; } // Replace last comma with " and" if there are multiple damages if (vehicleDamageText.includes(",") && vehicleDamageText !== "Replace the windshield") { vehicleDamageText = vehicleDamageText.replace(/,([^,]*)$/, " and$1") + " of your"; } expectedServicePackageDetails[vehicleDamageText] = [vehicleDetails?.year + " " + vehicleDetails?.make + " " + vehicleDetails?.model]; return expectedServicePackageDetails; } async expectedServicePackageDetails(testData: Partial, expectedServicePackageDetails: Map): Promise { 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; let canSafeliteRecalibrate: boolean = false; if (!isRepair) { hasRecalPart = localStorage.order.lineItems.glassParts.find((item: any) => item.requiresRecalibration === true) ? true : false; canSafeliteRecalibrate = localStorage.order.lineItems.glassParts.find((item: any) => item.canSafeliteRecalibrate === true) ? true : false; } let recalRequired = !isRepair && (isInsurance || isCaliforniaState) && hasRecalPart && canSafeliteRecalibrate 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 getExpectedServiceLocationDateAndTimeSection(testData: Partial, expectedServicePackageDetails: Map): Promise { const { customerDetails, appointmentDetails } = testData; let serviceLocationTitle = appointmentDetails?.serviceLocation == ServiceLocation.Mobile ? "We're coming to you" : "You're coming to us"; let serviceLocationText = appointmentDetails?.serviceLocation == ServiceLocation.Mobile ? appointmentDetails?.serviceAddress ? appointmentDetails.serviceAddress.street + ", " + appointmentDetails.serviceAddress.city + ", " + appointmentDetails.serviceAddress.state + " " + appointmentDetails.serviceAddress.postalCode : "" : appointmentDetails?.shopAddress ? appointmentDetails.shopAddress : ""; serviceLocationText += " on " serviceLocationText += customerDetails?.apptDate ? await this.getFormattedAppointmentDate(customerDetails.apptDate) + " " + customerDetails?.apptTime?.replace("-", "—") : ""; expectedServicePackageDetails[serviceLocationTitle] = [serviceLocationText]; return expectedServicePackageDetails; } async getExpectedVehicleDamageLocations(testData: Partial, expectedServicePackageDetails: Map): Promise { const { customerDetails } = testData; let VehicleDamageLocationsText: string[] = []; if (VehicleDamage.WindshieldCrack) { let VehicleDamageLocationsText: string[] = []; VehicleDamageLocationsText.push("Replace the windshield"); }; expectedServicePackageDetails["VehicleDamageLocationsText"] = VehicleDamageLocationsText; return expectedServicePackageDetails; } async getExpectedContactDetails(testData: Partial, expectedServicePackageDetails: Map): Promise { const { customerDetails } = testData; let customerDetailsText: string[] = []; customerDetailsText.push( // customerDetails?.firstName.toUpperCase() + " " + customerDetails?.lastName.toUpperCase(), customerDetails?.email ? customerDetails?.email.toUpperCase() : "", customerDetails?.phoneNumber ? customerDetails?.phoneNumber : "", ); expectedServicePackageDetails["Contact details"] = customerDetailsText return expectedServicePackageDetails; } async getExpectedTextServiceUpdatesOptInOrOut(testData: Partial, expectedServicePackageDetails: Map): Promise { const { customerDetails } = testData; let isOptedInForTextMessages = testData.isOptedInForTextMessages ?? false; let expectedText = isOptedInForTextMessages ? customerDetails?.phoneNumber : "Not opted in"; expectedServicePackageDetails["We’ll text service updates to"] = [expectedText]; return expectedServicePackageDetails; } async ValidateAfterPayBreakOutSection() { /*const vuexState = JSON.parse(await this.page.evaluate('localStorage.getItem(\'vuex\')')); const isInsurance = vuexState.order.payment.isInsurance; const currentDeductible = vuexState.order.policy.currentDeductible; const isVerified = vuexState.order.payment.insuranceCoverage.isVerified;*/ const amountDueText = await this.amountDueTextField.first().textContent(); const verifyAfterpayBreakout = amountDueText?.includes('$') ? Number.parseFloat(amountDueText.replace(/[^0-9.]/g, '')) > 0 : false if (verifyAfterpayBreakout) { const afterPayAmountString = await this.afterPayBreakoutSection.locator('.afterpay-amount').textContent(); const afterPayAmount = Number.parseFloat(afterPayAmountString!.replace(/[^0-9.]/g, '')); Soft.expect(afterPayAmount, `AfterPayAmount (${afterPayAmount}) is > 0`).toBeGreaterThan(0); await this.afterPayToggle.click().then( async () => { await waitUntil(async () => { return (await this.page.locator('.after-pay-toggle.expanded').evaluate(el => window.getComputedStyle(el, ':after').transform)) === 'matrix(-1, 0, 0, -1, 0, 0)'; }); } ); const afterPayCards = await this.page.locator('.after-pay-details .payment-card').all(); Soft.expect(afterPayCards.length, `There are 4 afterpay cards`).toBe(4); for (const afterPayCard of afterPayCards) { const afterPayAmountWithinCardString = await afterPayCard.locator('.amount-due').textContent(); const afterPayAmountWithinCard = Number.parseFloat(afterPayAmountWithinCardString!.replace(/[^0-9.]/g, '')); Soft.expect(afterPayAmountWithinCard, `AfterPayAmount (${afterPayAmountWithinCard}) > 0`).toBeGreaterThan(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', year: 'numeric', month: 'long', day: 'numeric' }); return updatedAppointmentDate; }*/ async getFormattedAppointmentDate(appointmentDate: string) { let formattedAppointmentDate: Date; const now = new Date(); switch (true) { case /^\d{4}-\d{2}-\d{2}$/.test(appointmentDate): formattedAppointmentDate = new Date(appointmentDate + 'T00:00:00'); break; case /[A-Za-z]+,\s+[A-Za-z]+\s+\d{1,2}/.test(appointmentDate): const [, month, day] = appointmentDate.match(/[A-Za-z]+,\s+([A-Za-z]+)\s+(\d{1,2})/) || []; formattedAppointmentDate = new Date(`${month} ${day}, ${now.getFullYear()}`); if (formattedAppointmentDate < now) formattedAppointmentDate.setFullYear(now.getFullYear() + 1); // rollover break; default: throw new Error('Unsupported date format: ' + appointmentDate); } return formattedAppointmentDate.toLocaleDateString('en-US', { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' }); } @step("PaymentMethodPage >> Select Payment Method: ") async handlePaymentMethodPage(testData: Partial) { const { servicePackage, isRecalVehicle, paymentDetails, isForcedOEM, experiments } = testData; await this.validateProgressBar(ProgressBarPercentages.PaymentMethodPage); await this.validatePaymentDetailsPage(testData); if (testData.isPIAEnabled) { await this.ValidateAfterPayBreakOutSection(); } if (isForcedOEM) { await this.validateOEMPart(isForcedOEM); } // 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!, experiments!); await this.executePayment(testData); } else { await this.nextPage(); } } }