diff --git a/playwright-tests/business-logic/types/CustomerDetails.ts b/playwright-tests/business-logic/types/CustomerDetails.ts index 3ac2747a0..3c1f9841d 100644 --- a/playwright-tests/business-logic/types/CustomerDetails.ts +++ b/playwright-tests/business-logic/types/CustomerDetails.ts @@ -61,7 +61,7 @@ export interface IPaymentDetails { export interface IClaimDetails { client: string, policyNumber: string, - policyDeductible: number, + policyDeductible: any, policyZip?: string damageDate: string, damageCause: DamageCause diff --git a/playwright-tests/business-logic/types/IAlertFlags.ts b/playwright-tests/business-logic/types/IAlertFlags.ts index b13f30bbc..7943ed6be 100644 --- a/playwright-tests/business-logic/types/IAlertFlags.ts +++ b/playwright-tests/business-logic/types/IAlertFlags.ts @@ -1,5 +1,5 @@ export default interface IAlertFlags { - isHeavyTruckVehicle?: boolean, + isHeavyTruckVehicleAlert?: boolean, isRepairReplace?: boolean, isSplitWindshield?: boolean, isRepairOnly?: boolean, diff --git a/playwright-tests/business-logic/types/ITestData.ts b/playwright-tests/business-logic/types/ITestData.ts index 7ae8090df..61ed18128 100644 --- a/playwright-tests/business-logic/types/ITestData.ts +++ b/playwright-tests/business-logic/types/ITestData.ts @@ -28,8 +28,11 @@ export interface ITestData { endorsements: IEndorsementDetails[], hasOemEndorsement: boolean, // OEM Endorsement does not appear on endorsements page, so it has a separate flag.s skipEstimatePage: boolean, + isHeavyTruck: boolean, isRecalVehicle: boolean, canNotRecal: boolean, dynamicRecal: boolean, - promoCode: string + promoCode: string, + policyZip: string, + isPolicyUnverified: boolean } \ No newline at end of file diff --git a/playwright-tests/pages/CoverageStatementPage.ts b/playwright-tests/pages/CoverageStatementPage.ts index 7085c6794..b529f21f1 100644 --- a/playwright-tests/pages/CoverageStatementPage.ts +++ b/playwright-tests/pages/CoverageStatementPage.ts @@ -9,7 +9,7 @@ export class CoverageStatementPage extends InsuranceBasePage { readonly scheduleOnlineButton: Locator; readonly cancelMyClaimButton: Locator; readonly deductibleAmount: Locator; - readonly verfiyingCoverageText: Locator; + readonly verifyingCoverageText: Locator; readonly continueButton: Locator; // For ITAC/NoComp url = process.env['BASE_URL']! + '/FixMyGlass/CoverageStatement.aspx'; @@ -19,7 +19,7 @@ export class CoverageStatementPage extends InsuranceBasePage { this.scheduleOnlineButton = this.page.getByText('Continue to schedule online'); this.cancelMyClaimButton = this.page.getByText('Cancel my claim'); this.deductibleAmount = this.page.getByRole('heading', { name: '$' }).locator('span'); - this.verfiyingCoverageText = this.page.getByRole('heading', { name: 'We’re verifying your coverage' }); + this.verifyingCoverageText = this.page.getByRole('heading', { name: 'We\'re verifying your coverage' }); this.continueButton = page.getByRole('button', { name: 'Continue' }); // this.validateURL(this.url); } @@ -46,16 +46,20 @@ export class CoverageStatementPage extends InsuranceBasePage { "span.deductible-text-black[data-bind='text: deductibleFormatted']" ); + const unverifiedDeductibleElement = this.verifyingCoverageText; + // Check if the locator is visible before running the expectation if (await deductibleElement.isVisible()) { // Check if the page contains the properly formatted deductible amount await expect(deductibleElement).toContainText(`$${expectedDeductibleRegex}`); } - } - async validateUnverifiedText(){ - await expect(this.verfiyingCoverageText).toBeEnabled(); + if (await unverifiedDeductibleElement.isVisible()) { + // Click on continue button if unverified header is visible + await this.continueButton.click(); + } } + @step("CoverageStatementPage >> Next page: ") async handleCoverageStatementPage(testData: Partial) { diff --git a/playwright-tests/pages/OrderConfirmationPage.ts b/playwright-tests/pages/OrderConfirmationPage.ts index 74a5a49e1..489ed1678 100644 --- a/playwright-tests/pages/OrderConfirmationPage.ts +++ b/playwright-tests/pages/OrderConfirmationPage.ts @@ -33,7 +33,7 @@ export class OrderConfirmationPage extends BasePage { 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.deductibleText = this.page.locator('.deductible'); this.subtotalText = this.page.locator('.sub-total'); this.finalAmountDue = this.page.locator('div.amount-due'); this.cartServicePackageText = this.cartServicePackageText = this.page.locator('.cart-panel'); @@ -44,7 +44,7 @@ export class OrderConfirmationPage extends BasePage { async validateOrderConfirmationPage(testData: Partial) { // Destructure data we use const { vehicleDetails, customerDetails, servicePackage, promoCode, - isPolicyFound, claimDetails, paymentDetails, isUseVehicleOnPolicy, paymentMethod } = testData; + isPolicyFound, claimDetails, paymentDetails, isUseVehicleOnPolicy, paymentMethod, isPolicyUnverified } = 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())); @@ -87,6 +87,7 @@ export class OrderConfirmationPage extends BasePage { const finalAmountDueAmt = Number.parseFloat(finalAmountDueValue!.split('$')[1].replaceAll(',', '')); + expect.soft(subtotalAmt).toBeGreaterThan(0); // expect.soft(deductibleAmt).toEqual(0); @@ -94,36 +95,17 @@ export class OrderConfirmationPage extends BasePage { // Verify amount due > 0 expect.soft(amountDueAmt).toBeGreaterThan(0); expect.soft(finalAmountDueAmt).toBeGreaterThan(0); + + if (isPolicyUnverified && PaymentType.PayWithInsurance){ + expect.soft(finalAmountDueAmt).toContain('Verifying coverage') + } } 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) { diff --git a/playwright-tests/pages/PaymentMethodPage.ts b/playwright-tests/pages/PaymentMethodPage.ts index 240d0e03e..c57caaeef 100644 --- a/playwright-tests/pages/PaymentMethodPage.ts +++ b/playwright-tests/pages/PaymentMethodPage.ts @@ -357,10 +357,12 @@ l } 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 + let recalRequired = !isRepair && (isInsurance || isCaliforniaState) && hasRecalPart && canSafeliteRecalibrate let stringForRepair: string[] = ["Expert windshield repair", "Exclusive resin sealant", "Nationwide lifetime guarantee"]; let stringIfRecal = isRepair ? "" diff --git a/playwright-tests/pages/VehicleSelectionPage.ts b/playwright-tests/pages/VehicleSelectionPage.ts index 38eaf5e63..c2d638d12 100644 --- a/playwright-tests/pages/VehicleSelectionPage.ts +++ b/playwright-tests/pages/VehicleSelectionPage.ts @@ -12,6 +12,7 @@ export class VehicleSelectionPage extends BasePage { readonly makeDropdown: Locator; readonly modelDropdown: Locator; readonly styleDropdown: Locator; + readonly zipCodeTextBox: Locator; readonly discontinuedServiceAlert: Locator; url = process.env['BASE_URL']! + '/fmg/?fmgPage=vehicle'; @@ -23,6 +24,7 @@ export class VehicleSelectionPage extends BasePage { this.makeDropdown = this.page.locator('#makeQuestionField'); this.modelDropdown = this.page.locator('#modelQuestionField'); this.styleDropdown = this.page.locator('#styleQuestionField'); + this.zipCodeTextBox = this.page.getByRole('textbox', { name: 'Zip code' }); this.discontinuedServiceAlert = this.page.locator('.alert-danger.widget-name-AlertNoServiceWidget'); // this.validateURL(this.url); } @@ -49,13 +51,17 @@ export class VehicleSelectionPage extends BasePage { @step("VehicleSelectionPage >> Select Vehicle: ") async handleVehicleSelectionPage(testData: Partial) { await this.validateProgressBar(ProgressBarPercentages.VehicleSelectionPage); - const { vehicleDetails } = testData; - const { isHeavyTruckVehicle, isSplitWindshield } = testData.alertFlags || {}; + const { vehicleDetails, isHeavyTruck, customerDetails } = testData; + const { isHeavyTruckVehicleAlert, isSplitWindshield } = testData.alertFlags || {}; await this.selectVehicle(vehicleDetails!); + + if (isHeavyTruck) { + await this.zipCodeTextBox.fill(customerDetails?.address.postalCode!); + } // Handle alert conditions for vehicle selection - if (isHeavyTruckVehicle || isSplitWindshield) { + if (isHeavyTruckVehicleAlert || isSplitWindshield) { await this.checkForAlertMessages(); throw new TestSuccessAlert('Both assertions are met successfully.'); } diff --git a/playwright-tests/tests/0000__M.test.ts b/playwright-tests/tests/0000__M.test.ts index 51594cd19..213835484 100644 --- a/playwright-tests/tests/0000__M.test.ts +++ b/playwright-tests/tests/0000__M.test.ts @@ -31,6 +31,8 @@ import cashRepairInShopAfterPayTests from "./CashRepairInShopAfterPay"; import cashRepairInShopPayPalTests from "./CashRepairInShopPayPal"; import cashReplaceMultiSlidingGlassDropoffTests from "./CashReplaceMultiSlidingGlassDropoff"; import cashReplaceMultiGlassMobileTests from "./CashReplaceMultiGlassMobile"; +import insuranceBigTruckVerifiedTests from "./InsuranceBigTruckVerified"; +import insuranceUnverifiedTests from "./InsuranceUnverified"; /** * Master Test Runner @@ -67,6 +69,8 @@ const allStandardTests = [ {name: "CashReplaceWiperPromoInshop", tests: cashReplaceWiperPromoInShopTests}, {name: "InsuranceAcuityPaypal", tests: insuranceAcuityPaypalTests}, {name: "InsuranceITAC21stCentury", tests: insuranceITAC21stCenturyTests}, + {name: "InsuranceBigTruckVerified", tests: insuranceBigTruckVerifiedTests}, + {name: "InsuranceUnverified", tests: insuranceUnverifiedTests}, // {name: "InsuranceGeico", tests: insuranceGeicoTests}, // {name: "InsuranceITACOptimizedPriceValidationAllState", tests: insuranceITACOptimizedPriceValidationAllStateTests} diff --git a/playwright-tests/tests/InsuranceBigTruckVerified.ts b/playwright-tests/tests/InsuranceBigTruckVerified.ts new file mode 100644 index 000000000..f06e9171d --- /dev/null +++ b/playwright-tests/tests/InsuranceBigTruckVerified.ts @@ -0,0 +1,81 @@ +//Imports here +import { ITestData } from "@business-logic/types/ITestData" +import { PaymentMethod, AppointmentType, DamageType, PaymentType } from "@business-logic/types/Enums"; +import TestCase from "@business-logic/types/TestCase"; +import { VehicleLookupType } from "@business-logic/types/Enums"; +import { getDefaultTestData, setFakerSeedFromTestName } from "@business-logic/constants/DefaultTestData"; + +// Set the seed based on test name for consistent but unique data +setFakerSeedFromTestName("InsuranceBigTruckVerified"); + +// Now get the test data with the seeded faker +const insuranceBigTruckVerifiedData: Partial = { + ...getDefaultTestData(), // Get default data with current seed + + // Key feature: Insurance flow with GEICO + paymentMethod: PaymentMethod.Insurance, + + // Insurance claim flags + isDuplicateClaim: true, + isPolicyFound: true, + isUseVehicleOnPolicy: true, + isHeavyTruck: true, + + // Override customer details with specific name and California location + customerDetails: { + ...getDefaultTestData().customerDetails!, + firstName: 'Big', + lastName: 'Truck', + address: { + ...getDefaultTestData().customerDetails!.address, + city: 'Ontario', + state: 'California', + postalCode: '43085' + } + }, + + + // Insurance claim details + claimDetails: { + client: 'USAA', + policyNumber: 'Mock900040BigTruck', + policyDeductible: 2000.00, + policyZip: '55414', + damageDate: new Date(new Date().setDate(new Date().getDate() - 1)).toLocaleDateString('en-US', {month: '2-digit', day: '2-digit', year: 'numeric'}), + damageCause: DamageType.Rock + }, + + // Hyundai vehicle details with VIN lookup + vehicleDetails: { + ...getDefaultTestData().vehicleDetails!, + year: '2025', + make: 'Peterbilt', + model: '579', + style: 'conventional cab', + vin: '1XPBDP9X6SD693446', + vehicleLookupType: VehicleLookupType.Vin, + }, + + // No need to override vehicleDamage as it already defaults to WindshieldCrack + + // Override for in-shop appointment + appointmentDetails: { + serviceLocation: AppointmentType.InShop, + shopAddress: '5719 Brandt Pike, Dayton, OH 45424', + appointmentDate: getDefaultTestData().appointmentDetails?.appointmentDate + }, + + // Override payment details (empty because we skip payment method page in insurance flow) + paymentDetails: {} +} + +const insuranceBigTruckVerifiedTests: TestCase[] = []; + +const tc = new TestCase({ + name: `InsuranceBigTruckVerified`, + tags: ['@E2E','@InsuranceBigTruckVerified', '@test_report', '@Insurance'], + testData: insuranceBigTruckVerifiedData +}, undefined, 'InsuranceBigTruckVerified'); +insuranceBigTruckVerifiedTests.push(tc); + +export default insuranceBigTruckVerifiedTests; \ No newline at end of file diff --git a/playwright-tests/tests/InsuranceUnverified.ts b/playwright-tests/tests/InsuranceUnverified.ts new file mode 100644 index 000000000..f0fcf293a --- /dev/null +++ b/playwright-tests/tests/InsuranceUnverified.ts @@ -0,0 +1,86 @@ +//Imports here +import { ITestData } from "@business-logic/types/ITestData" +import { PaymentMethod, AppointmentType, DamageType, PartQuestionType } from "@business-logic/types/Enums"; +import TestCase from "@business-logic/types/TestCase"; +import { VehicleLookupType } from "@business-logic/types/Enums"; +import { getDefaultTestData, setFakerSeedFromTestName } from "@business-logic/constants/DefaultTestData"; + +// Set the seed based on test name for consistent but unique data +setFakerSeedFromTestName("InsuranceUnverified"); + +// Now get the test data with the seeded faker +const insuranceUnverifiedData: Partial = { + ...getDefaultTestData(), // Get default data with current seed + + // Key feature: Insurance flow with GEICO + paymentMethod: PaymentMethod.Insurance, + + // Insurance claim flags + isPolicyFound: false, + isPolicyUnverified: true, + isRecalNotification: true, + + // Override customer details with specific name and California location + customerDetails: { + ...getDefaultTestData().customerDetails!, + firstName: 'Jane', + lastName: 'Unverified', + address: { + ...getDefaultTestData().customerDetails!.address, + city: 'Richmond', + state: 'Virginia', + postalCode: '23219' + } + }, + + + // Insurance claim details + claimDetails: { + client: '21st Century', + policyNumber: 'UnverifiedMock', + policyDeductible: "Unverified", + policyZip: '43123', + damageDate: new Date(new Date().setDate(new Date().getDate() - 1)).toLocaleDateString('en-US', {month: '2-digit', day: '2-digit', year: 'numeric'}), + damageCause: DamageType.Rock + }, + + // Hyundai vehicle details with VIN lookup + vehicleDetails: { + ...getDefaultTestData().vehicleDetails!, + year: '2014', + make: 'Honda', + model: 'Accord', + style: '4 door sedan', + vehicleLookupType: VehicleLookupType.Zip, + }, + + // Part questions related to recalibration + partQuestions: [ + { + partQuestionType: PartQuestionType.GeneralQuestion1, + isOnPage: true, + optionToSelect: 'Yes' + }, + ], + + // Override for in-shop appointment + appointmentDetails: { + serviceLocation: AppointmentType.InShop, + shopAddress: '5719 Brandt Pike, Dayton, OH 45424', + appointmentDate: getDefaultTestData().appointmentDetails?.appointmentDate + }, + + // Override payment details (empty because we skip payment method page in insurance flow) + paymentDetails: {} +} + +const insuranceUnverifiedTests: TestCase[] = []; + +const tc = new TestCase({ + name: `InsuranceUnverified`, + tags: ['@E2E','@InsuranceUnverified', '@test_report', '@Insurance'], + testData: insuranceUnverifiedData +}, undefined, 'InsuranceUnverified'); +insuranceUnverifiedTests.push(tc); + +export default insuranceUnverifiedTests; \ No newline at end of file diff --git a/playwright-tests/tests/alert-validation/alert0001_HeavyTruck.ts b/playwright-tests/tests/alert-validation/alert0001_HeavyTruck.ts index dad46ecd5..9a881d4e5 100644 --- a/playwright-tests/tests/alert-validation/alert0001_HeavyTruck.ts +++ b/playwright-tests/tests/alert-validation/alert0001_HeavyTruck.ts @@ -18,7 +18,7 @@ const heavyTruckData: Partial = { style: 'conventional cab' }, alertFlags: { - isHeavyTruckVehicle: true + isHeavyTruckVehicleAlert: true }, vehicleDamage: [ VehicleDamage.WindshieldOneChip,