diff --git a/playwright-tests/pages/AfterpayPage.ts b/playwright-tests/pages/AfterpayPage.ts index 7f54fe336..75f0ca352 100644 --- a/playwright-tests/pages/AfterpayPage.ts +++ b/playwright-tests/pages/AfterpayPage.ts @@ -10,6 +10,8 @@ export class AfterpayPage extends BasePage { readonly passwordTextBox: Locator; // Card details + readonly paymentOptionsButton: Locator; + readonly continueButtonAfterpay: Locator; readonly cardholderNameTextBox: Locator; readonly cardNumberTextBox: Locator; readonly expirationDateTextBox: Locator; @@ -23,6 +25,8 @@ export class AfterpayPage extends BasePage { this.passwordTextBox = page.getByTestId('login-password-input'); this.submitButton = page.getByRole('button', { name: 'Continue' }); + this.paymentOptionsButton = page.locator('div:has(>input[id*=\'payment-types\']) label').nth(1); + this.continueButtonAfterpay = page.getByRole('button').filter({hasText: 'Continue'}); this.cardholderNameTextBox = page.getByTestId('payment-method-cardHolderName-input'); this.cardNumberTextBox = page.getByTestId('payment-method-cardNumber-input'); this.expirationDateTextBox = page.getByTestId('payment-method-cardExpiry-input'); @@ -46,7 +50,12 @@ export class AfterpayPage extends BasePage { async executeAfterpayPayment(paymentDetails: IPaymentDetails) { await this.login(paymentDetails.password!); - + await this.page.locator('div[data-testid=\'loading-icon-svg\']').filter({ visible: true}).first().waitFor({ state: 'hidden' }); + if (await this.paymentOptionsButton.isVisible()) + { + await this.paymentOptionsButton.click(); + await this.continueButtonAfterpay.click(); + } await this.confirmButton.click(); } diff --git a/playwright-tests/pages/PaymentMethodPage.ts b/playwright-tests/pages/PaymentMethodPage.ts index 2ba68dcc3..7bb4a6fcc 100644 --- a/playwright-tests/pages/PaymentMethodPage.ts +++ b/playwright-tests/pages/PaymentMethodPage.ts @@ -56,7 +56,7 @@ export class PaymentMethodPage extends BasePage { 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.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.paypalPage = new PaypalPage(page); @@ -101,7 +101,7 @@ export class PaymentMethodPage extends BasePage { let expectedAppointmentDetails = new Map(); expectedAppointmentDetails = await this.getExpectedVehicleDetails(testData, expectedAppointmentDetails); expectedAppointmentDetails = await this.getExpectedVehicleDamage(testData, expectedAppointmentDetails); - expectedAppointmentDetails = await this.expectedServicePackageDetails(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); @@ -403,7 +403,7 @@ l const { appointmentDetails } = testData; let serviceLocationTitle = appointmentDetails?.serviceLocation == ServiceLocation.Mobile ? "We're coming to you" - : "You're going to a Safelite shop"; + : "You're coming to us"; let serviceLocation: string[] = []; serviceLocation.push( @@ -443,7 +443,7 @@ l customerDetails?.apptDuration ? "Estimated appointment length: " + customerDetails.apptDuration : "" ); - expectedServicePackageDetails["Appointment date + time"] = appointmentDateText; + expectedServicePackageDetails["Appointment Date + Time"] = appointmentDateText; return expectedServicePackageDetails; } @@ -452,7 +452,7 @@ l let customerDetailsText: string[] = []; customerDetailsText.push( - customerDetails?.firstName.toUpperCase() + " " + customerDetails?.lastName.toUpperCase(), + // customerDetails?.firstName.toUpperCase() + " " + customerDetails?.lastName.toUpperCase(), customerDetails?.email ? customerDetails?.email.toUpperCase() : "", customerDetails?.phoneNumber ? customerDetails?.phoneNumber : "", "Opted out of text message updates" diff --git a/playwright-tests/pages/PaypalPage.ts b/playwright-tests/pages/PaypalPage.ts index 07e2cd1e6..ff2bbd548 100644 --- a/playwright-tests/pages/PaypalPage.ts +++ b/playwright-tests/pages/PaypalPage.ts @@ -24,8 +24,8 @@ export class PaypalPage extends BasePage { this.passwordTextBox = page.getByPlaceholder('Password'); this.paypalLoginButton = page.getByRole('button', { name: 'Log In', exact: true }); this.completePurchaseButton = page.getByTestId('submit-button-initial') - this.payWithRadioButton = page.locator('.py-4').first(); - this.payButton = page.getByRole('button', { name: 'Pay $' }); + this.payWithRadioButton = page.getByRole('button').filter({ hasText: 'Pay with' }); + this.payButton = page.locator('#one-time-cta'); } async completePaypalPurchase(paymentDetails: IPaymentDetails){ @@ -45,7 +45,8 @@ export class PaypalPage extends BasePage { await this.passwordTextBox.fill(paymentDetails.password!); await this.paypalLoginButton.click(); await this.payWithRadioButton.click(); - await this.payButton.click(); + await this.page.waitForTimeout(2000); // wait for 2 seconds to ensure the Pay button is clickable + await this.payButton.dblclick(); } } } diff --git a/playwright-tests/pages/SchedulePage.ts b/playwright-tests/pages/SchedulePage.ts index 312e97b68..a8f01b03a 100644 --- a/playwright-tests/pages/SchedulePage.ts +++ b/playwright-tests/pages/SchedulePage.ts @@ -55,7 +55,7 @@ export class SchedulePage extends BasePage { this.selectAShopOptions = this.page.locator('[class="shop-question"]'); this.yourSafeliteShop = this.page.locator("fieldset:has(#chooseShop) label"); - this.allDayDropOffButton = this.page.locator("label[buttonlabel='Drop off all day']"); + this.allDayDropOffButton = this.page.locator("label[buttonlabel*='Drop']"); this.pickATimeButton = this.page.locator("label[buttonlabel='Pick a time']"); this.firstAvailableDate = this.page.locator('.selectable-day').filter({ visible: true}).locator('nth=0'); this.firstAvailableTime = this.page.locator('label').filter({ hasText: /AM|PM/ }).locator('div').locator('nth=0'); @@ -64,7 +64,7 @@ export class SchedulePage extends BasePage { this.dateText = this.page.locator('label.modal-title'); this.viewMoreDatesLink = this.page.getByText(/View more dates/).first(); this.appointmentDuration = this.page.locator('.duration-text-block'); - this.timeSlots = this.page.locator('fieldset:has(>legend#chooseTimeSlot) label'); + this.timeSlots = this.page.locator('fieldset:has(>legend#chooseTimeSlot) label').filter({ visible: true}); } async selectLocation(testData: Partial) { @@ -82,7 +82,8 @@ export class SchedulePage extends BasePage { } async scheduleInShop(appointmentDetails?: IAppointmentDetails) { - await this.inShopButton.click(); + + await this.inShopButton.isVisible() ? await this.inShopButton.click() : null; if (appointmentDetails && appointmentDetails.shopAddress) { const zipCodeMatch = appointmentDetails.shopAddress.match(/\b\d{5}$/); if (zipCodeMatch) { @@ -97,28 +98,20 @@ export class SchedulePage extends BasePage { await this.saveLocationButton.click(); } - await this.inShopButton.click().then(async () => { - if (appointmentDetails && (appointmentDetails.shopAddress === "" || appointmentDetails.shopAddress === undefined )) { - appointmentDetails.shopAddress = ''; - const elements = await this.storeAddressText.all(); - elements.forEach(async(element) => { - appointmentDetails.shopAddress += await element.textContent() || "" + " "; - }); - appointmentDetails.shopAddress?.trim(); - } - }); + // await this.inShopButton.click(); // await this.selectAShopOptions.locator(`[buttonbodycopy="${appointmentDetails.shopAddress}"]`).scrollIntoViewIfNeeded().then(() => this.selectAShopOptions.locator(`[buttonbodycopy="${appointmentDetails.shopAddress}"]`).click()); } if (appointmentDetails && (appointmentDetails.shopAddress === "" || appointmentDetails.shopAddress === undefined )) { appointmentDetails.shopAddress = ''; + await this.storeAddressText.first().waitFor({ state: 'visible' }); const elements = await this.storeAddressText.all(); - elements.forEach(async(element) => - { - appointmentDetails.shopAddress += await element.textContent() || "" + " "; - } - ) - appointmentDetails.shopAddress?.trim(); + + for (let element of elements) { + let addressLine = await element.textContent() || ""; + appointmentDetails.shopAddress += addressLine + ", " + }; + appointmentDetails.shopAddress = appointmentDetails.shopAddress?.slice(0, -2); } } @@ -170,6 +163,7 @@ export class SchedulePage extends BasePage { const inshopAvailableDates = this.page.locator('.selectable-day').filter({ visible: true}).all(); for (const inshopAvailableDate of await inshopAvailableDates) { await inshopAvailableDate.click(); + await this.page.waitForTimeout(500); if (await this.allDayDropOffButton.isVisible()) { customerDetails!.apptDate = `${await inshopAvailableDate.getAttribute("id")}`; break; @@ -210,13 +204,13 @@ export class SchedulePage extends BasePage { } // appointmentmentDetails.serviceLocation === ServiceLocation.DropOff ? await this.dropOffButton.click() : await this.firstAvailableTime.click(); - customerDetails!.apptDuration = (await this.appointmentDuration.innerText()).replace("Your service will take approximately ", ""); + customerDetails!.apptDuration = (await this.appointmentDuration.innerText()).replace("Your service will take approximately ", "").replace("Duration: ", ""); } - async getFormattedTimeSlot(timeSlot: Locator) { + async getFormattedTimeSlot(timeSlot: Locator) { const selectedTimeSlot = await timeSlot.innerText(); let formattedTimeSlot: string = ""; - if (selectedTimeSlot.toLowerCase().includes("drop off")) + if (selectedTimeSlot.toLowerCase().includes("drop")) { formattedTimeSlot = selectedTimeSlot.includes("overnight") ? "drop off by 5:30 pm on the night of your scheduled appointment. Pick-up time dependent on shop schedule" : "drop off before 9:30 AM"; } diff --git a/playwright-tests/pages/VehicleDamagePage.ts b/playwright-tests/pages/VehicleDamagePage.ts index 5de6cb1d4..465df289d 100644 --- a/playwright-tests/pages/VehicleDamagePage.ts +++ b/playwright-tests/pages/VehicleDamagePage.ts @@ -39,9 +39,9 @@ export class VehicleDamagePage extends BasePage { super(page); this.page = page; this.windshieldChkBox = this.page.locator('[buttonlabel="Windshield"]'); - this.crackButton = this.page.locator('[buttonlabel="Crack"]'); - this.chipButton = this.page.locator('[buttonlabel="Chip(s)"]'); - this.sideDoorButton = this.page.locator('[buttonlabel="Side door"]'); + this.crackButton = this.page.locator('[buttonlabelsubcopy="Replace my windshield"]'); + this.chipButton = this.page.locator('[buttonlabelsubcopy="Repair my windshield"]'); + this.sideDoorButton = this.page.locator('[buttonlabel="Side window"]'); this.driverSideButton = this.page.locator('[buttonlabel="Driver side"]'); this.passengerSideButton = this.page.locator('[buttonlabel="Passenger side"]'); this.driverQuarterPanelChkBox = this.page.locator('[aria-labelledby="driverSideOptions"]').locator('[buttonlabel="Quarter panel"]'); diff --git a/playwright-tests/tests/CashReplaceGlassAddressLookupInshopAfterPay.ts b/playwright-tests/tests/CashReplaceGlassAddressLookupInshopAfterPay.ts index 2cdb254eb..43660fe21 100644 --- a/playwright-tests/tests/CashReplaceGlassAddressLookupInshopAfterPay.ts +++ b/playwright-tests/tests/CashReplaceGlassAddressLookupInshopAfterPay.ts @@ -42,14 +42,6 @@ const cashReplaceGlassAddressLookupInshopAfterPayData: Partial = { vehicleLookupType: VehicleLookupType.Address }, - // No need to override vehicleDamage as it already defaults to WindshieldCrack - - // Override appointment details - appointmentDetails: { - ...getDefaultTestData().appointmentDetails!, - shopAddress: "6826 Sawmill Rd, Columbus, OH 43235" - }, - // Override payment details paymentDetails: ClientData.getDefaultAfterpayDetails() } diff --git a/playwright-tests/tests/CashReplaceMultiSlidingGlassDropoff.ts b/playwright-tests/tests/CashReplaceMultiSlidingGlassDropoff.ts index 2da4c6f5e..f488a3555 100644 --- a/playwright-tests/tests/CashReplaceMultiSlidingGlassDropoff.ts +++ b/playwright-tests/tests/CashReplaceMultiSlidingGlassDropoff.ts @@ -35,7 +35,7 @@ const cashReplaceMultiSlidingGlassDropoffData: Partial = { appointmentDetails: { serviceLocation: ServiceLocation.DropOff, appointmentDate: getDefaultTestData().appointmentDetails?.appointmentDate, - shopAddress: "6826 Sawmill Rd, Columbus, OH 43235" + shopAddress: "6826 sawmill rd, Columbus, OH 43235" }, // Override vehicle details diff --git a/playwright-tests/tests/CashReplaceWiperDropoff.ts b/playwright-tests/tests/CashReplaceWiperDropoff.ts index 8080603f6..09083fcd2 100644 --- a/playwright-tests/tests/CashReplaceWiperDropoff.ts +++ b/playwright-tests/tests/CashReplaceWiperDropoff.ts @@ -20,7 +20,7 @@ const cashReplaceWiperDropoffData: Partial = { servicePackage: ServicePackage.Standard, // Special flags - isSkipEstimatePage: true, + isSkipEstimatePage: false, isRecalVehicle: true, // Override customer postal code @@ -28,7 +28,7 @@ const cashReplaceWiperDropoffData: Partial = { ...getDefaultTestData().customerDetails!, address: { ...getDefaultTestData().customerDetails!.address, - postalCode: '43085' + postalCode: '43235' } },