From 5682987c066ee951c925959ad8b910ce4568f6f8 Mon Sep 17 00:00:00 2001 From: JennyNou Date: Sun, 22 Mar 2026 22:49:25 -0400 Subject: [PATCH] Wip for order confirmation validations --- .../pages/OrderConfirmationPage.ts | 119 ++++++++++++------ 1 file changed, 83 insertions(+), 36 deletions(-) diff --git a/playwright-tests/pages/OrderConfirmationPage.ts b/playwright-tests/pages/OrderConfirmationPage.ts index 1c4a5962..9a776587 100644 --- a/playwright-tests/pages/OrderConfirmationPage.ts +++ b/playwright-tests/pages/OrderConfirmationPage.ts @@ -14,14 +14,15 @@ export class OrderConfirmationPage extends BasePage { readonly serviceText: Locator; readonly workOrderNumberText: Locator; readonly emailText: Locator; - - readonly apptDateText: Locator; - //readonly amountDueText: Locator; + readonly appointmentTypeText: Locator; + readonly apptDetailsText: Locator; readonly deductibleText: Locator; readonly subtotalText: Locator; + readonly totalAmountDueText: Locator; + readonly amountPaidText: Locator; readonly finalAmountDue: Locator; readonly cartServicePackageText: Locator; - readonly VerifiyingCoverageDeductibleText: Locator; + readonly unverifiedCoverageDeductibleText: Locator; issPageValue = 'order-confirmation'; @@ -35,14 +36,17 @@ export class OrderConfirmationPage extends BasePage { this.emailText = this.page.locator('[class="subheader-text"]', { hasText: 'Your appointment is on Safelite\'s schedule and your confirmation email is on the way.' }); this.serviceText = this.page.locator('[class="service-description confirmation-section"]'); this.workOrderNumberText = this.page.locator('[class="work-order-description"]'); + this.appointmentTypeText = this.page.locator('[class="appointment-title"]'); + this.apptDetailsText = this.page.locator('[class="appointment-details confirmation-section"]'); - this.apptDateText = this.page.locator('[class="appointment-details confirmation-section"]'); - + // Order details section this.deductibleText = this.page.locator('span#deductible-value, span.deductible-value'); - this.subtotalText = this.page.locator("#subtotal-value"); + this.subtotalText = this.page.locator('#subtotal-value'); + this.totalAmountDueText = this.page.locator('#total-value'); + this.amountPaidText = this.page.locator('#amount-paid-value'); this.finalAmountDue = this.page.locator('#bottom-amount-due-value'); this.cartServicePackageText = this.page.locator('.cart-item-list'); - this.VerifiyingCoverageDeductibleText = this.page.locator('span.price cart-item', { hasText: 'Verifying coverage' }); + this.unverifiedCoverageDeductibleText = this.page.locator('span#deductible-value', { hasText: 'Verifying coverage' }); } async validateOrderConfirmationPage(testData: Partial) { @@ -51,36 +55,58 @@ export class OrderConfirmationPage extends BasePage { isNoComp, isPolicyFound, claimDetails, paymentDetails, isUseVehicleOnPolicy } = testData; await expect.soft(this.successHeader).toBeVisible(); - - await this.serviceText.waitFor({ state: "visible" }); await this.logOrderNumber(); // Grab text const serviceTextValue = await this.serviceText.textContent(); - const apptDateValue = await this.apptDateText.textContent(); - const emailTextValue = await this.emailText.textContent(); - const servicePackageValue = (claimDetails!.policyDeductible >= 0) ? await this.cartServicePackageText.textContent(): null; - //const amountDueValue = await this.amountDueText.textContent(); - const deductibleTextValue = (isItac || isNoComp) ? null : await this.deductibleText.textContent(); - const subtotalTextValue = (claimDetails!.policyDeductible >= 0) ? await this.subtotalText.textContent() : null; - const finalAmountDueValue = (claimDetails!.policyDeductible >= 0) ? await this.finalAmountDue.textContent() : null; + const apptDetailsValue = await this.apptDetailsText.textContent(); + const appointmentTypeValue = await this.appointmentTypeText.textContent(); - // Extract service package price - // const servicePackageAmt = Number.parseFloat(servicePackageValue!.split('$')[1].replaceAll(',', '')); + // Validate header for appointment details matches inshop or mobile + await this.validateAppointmentTypeHeader(); + // Derived conditions + const isItacOrNoComp = !!(isItac || isNoComp); + const isUnverified = !isPolicyFound; + const hasPremiumOrStandard = + claimDetails!.policyDeductible >= 0 && + (servicePackage === ServicePackage.Premium || servicePackage === ServicePackage.Standard); + + const payAtService = + claimDetails!.policyDeductible >= 0 && + paymentDetails?.paymentType === PaymentType.PayAtService; + + const paidWithPIA = + claimDetails!.policyDeductible >= 0 && + paymentDetails?.paymentType !== PaymentType.PayAtService; + + // Helper: grab textContent only when the element is expected on-screen + const textIf = async (condition: boolean, locator: Locator) => + condition ? await locator.textContent() : null; + + // Grab text content for elements that are expected on-screen + const servicePackageValue = await textIf(hasPremiumOrStandard, this.cartServicePackageText); + const deductibleTextValue = await textIf(!isItacOrNoComp, this.deductibleText); + const subtotalTextValue = await textIf(hasPremiumOrStandard || isItacOrNoComp, this.subtotalText); + const totalAmountDueValue = await textIf((hasPremiumOrStandard && !payAtService) || (isItacOrNoComp && !payAtService), this.totalAmountDueText); + const amountPaidTextValue = await textIf((hasPremiumOrStandard && !payAtService) || (isItacOrNoComp && !payAtService), this.totalAmountDueText); + const finalAmountDueValue = await textIf(hasPremiumOrStandard || isItacOrNoComp || isUnverified, this.finalAmountDue); + + // General Validations expect.soft(serviceTextValue).toContain(`${vehicleDetails!.year} ${vehicleDetails!.make} ${vehicleDetails!.model}`); //expect.soft(apptDateValue).toContain(customerDetails!.apptDate); //expect.soft(emailTextValue).toContain(customerDetails!.email); // Service package validations - if ((servicePackage === ServicePackage.Premium && testData.isReplace === true) || servicePackage === ServicePackage.Standard) { + /* if ((servicePackage === ServicePackage.Premium && testData.isReplace === true) || (servicePackage === ServicePackage.Standard && testData.isReplace === true)) { expect.soft(servicePackageValue).toContain('Front advanced beam blades'); - } - if (servicePackage === ServicePackage.Premium) { + } else if (servicePackage === ServicePackage.Premium) { expect.soft(servicePackageValue).toContain('Safelite Rain Repellent Treatment'); - } + } else { + expect.soft(Number.parseFloat(deductibleTextValue!.split('$')[1].replaceAll(',', ''))).toEqual(claimDetails!.policyDeductible); + } commenting out needs reworked for ITAC/no comp flows*/ // Price validations /*if (servicePackage === ServicePackage.GlassOnly) { @@ -92,34 +118,40 @@ export class OrderConfirmationPage extends BasePage { if (isPolicyFound && (claimDetails!.policyDeductible === 0 && (servicePackage === ServicePackage.GlassOnly))) { const zeroDeductibleText = await this.deductibleText.textContent(); expect.soft(zeroDeductibleText).toEqual('$0.00'); - } else if (isPolicyFound && (finalAmountDueValue !== null && subtotalTextValue !== null)) { - // Extract numbers - //const amountDueAmt = Number.parseFloat(amountDueValue!.split('$')[1].replaceAll(',', '')); + } else if (isPolicyFound && claimDetails!.policyDeductible > 0 && !(isItac || isNoComp) && servicePackage === ServicePackage.GlassOnly){ + expect.soft(deductibleTextValue).not.toBeNull(); 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(deductibleAmt).toEqual(claimDetails!.policyDeductible); + + } else if ((isPolicyFound || (isItac || isNoComp && paymentDetails!.paymentType === PaymentType.PayAtService) && (finalAmountDueValue !== null && subtotalTextValue !== null))) { + // Extract numbers + const deductibleAmt = deductibleTextValue ? Number.parseFloat(deductibleTextValue.split('$')[1].replaceAll(',', '')) : null; + + const subtotalAmt = subtotalTextValue ? Number.parseFloat(subtotalTextValue!.split('$')[1].replaceAll(',', '')) : null; + //subtotalTextValue?.replaceAll(',', '') + + //const totalAmountDueAmt = Number.parseFloat(totalAmountDueValue!.split('$')[1].replaceAll(',', '')); + const finalAmountDueAmt = finalAmountDueValue ? Number.parseFloat(finalAmountDueValue!.split('$')[1].replaceAll(',', '')) : null; if (!(isItac || isNoComp)) { - //expect.soft(subtotalAmt).toEqual(claimDetails!.policyDeductible + servicePackageAmt); expect.soft(deductibleAmt).toEqual(claimDetails!.policyDeductible); } else { expect.soft(subtotalAmt).toBeGreaterThan(0); - expect.soft(deductibleAmt).toEqual(0); + //expect.soft(deductibleAmt).toEqual(0); } if ((paymentDetails!.paymentType === PaymentType.PayAtService) && (claimDetails!.policyDeductible >= 0 && (servicePackage === ServicePackage.Standard || servicePackage === ServicePackage.Premium))) { - // Verify amount due > 0 - //expect.soft(amountDueAmt).toBeGreaterThan(0); expect.soft(finalAmountDueAmt).toBeGreaterThan(0); } else { - // Verify amount due 0 - //expect.soft(amountDueAmt).toEqual(0); + const totalAmountDueAmt = Number.parseFloat(totalAmountDueValue!.split('$')[1].replaceAll(',', '')); + const amountPaidValue = Number.parseFloat(amountPaidTextValue!.split('$')[1].replaceAll(',', '')); + // Verify amount due 0 usually when PIA is selected + expect.soft(amountPaidValue).toEqual(totalAmountDueAmt); expect.soft(finalAmountDueAmt).toEqual(0); } } else { // essential flows will have deductible and amount due as "Verifying coverage" - const verifyingCoverageText = this.VerifiyingCoverageDeductibleText; + const verifyingCoverageText = this.unverifiedCoverageDeductibleText; expect.soft(verifyingCoverageText).toContainText('Verifying coverage'); expect.soft(finalAmountDueValue).toEqual('Verifying coverage'); @@ -133,6 +165,21 @@ export class OrderConfirmationPage extends BasePage { console.log(`SessionStorage Work Order Number:${workOrderNumber}`); }); } + + async validateAppointmentTypeHeader() { + const sessionStorage = JSON.parse(await this.page.evaluate('sessionStorage.getItem(\'submittedOrder\')')); + const appointmentType = sessionStorage.serviceLocation.appointmentType; + const appointmentTypeValue = await this.appointmentTypeText.textContent(); + const apptDetailsValue = await this.apptDetailsText.textContent(); + + if (appointmentTypeValue?.includes('going to a Safelite shop') && apptDetailsValue?.includes('Drop off before 9:30 AM')) { + expect.soft(appointmentType).toEqual('Dropoff'); + } else if (appointmentTypeValue?.includes('going to a Safelite shop')) { + expect.soft(appointmentType).toEqual('Inshop'); + } else { + expect.soft(appointmentType).toEqual('Mobile'); + } + } async validateURL() { let pass = false;