Adds the `Managed` flow type to the insurance test data. Specifies an empty payment details object for the insurance flow to skip the payment method page.
393 lines
No EOL
18 KiB
TypeScript
393 lines
No EOL
18 KiB
TypeScript
import { Page } from "@playwright/test";
|
|
import { addSmokeTagToRandomTest, Flow } from 'safelite-playwright-core';
|
|
import { ValidationOptions } from 'safelite-playwright-core';
|
|
import heavyTruckTests from "./alert-validation/alert0001_HeavyTruck";
|
|
import repairAndReplaceTests from "./alert-validation/alert0002_RepairAndReplace";
|
|
import splitWindshieldTests from "./alert-validation/alert0003_SplitWindshield";
|
|
import repairOnlyTests from "./alert-validation/alert0004_RepairOnly";
|
|
import unserviceableZipTests from "./alert-validation/alert0005_UnserviceableZip";
|
|
import invalidZipTests from "./alert-validation/alert0006_InvalidZip";
|
|
import vinNotFoundTests from "./alert-validation/alert0007_VinNotFound";
|
|
import { TestSuccessAlert } from 'safelite-playwright-core';
|
|
import { VehicleLookupType, VehicleDamage, PaymentType } from 'safelite-playwright-core';
|
|
import { PaymentMethod } from "framework/localTypes/Enums";
|
|
import cashRepairMobileCCTests from "./CashRepairMobileCreditCard";
|
|
import cashReplaceDynamicRecalMobileTests from "./CashReplaceDynamicRecalMobile";
|
|
import cashReplaceGlassAddressLookupInshopAfterPayTests from "./CashReplaceGlassAddressLookupInshopAfterPay";
|
|
import cashReplaceGlassLicensePlateLookupInshopPaypalTests from "./CashReplaceGlassLicensePlateLookupInshopPaypal";
|
|
import { ApiResponseInterceptUtil } from 'safelite-playwright-core';
|
|
import cashReplaceGlassPromoInshopTests from "./CashReplaceGlassPromoInshop";
|
|
import cashReplaceMultiGlassPromoInshopTests from "./CashReplaceMultiGlassPromoInshop";
|
|
import cashReplaceRainDefensePromoInshopTests from "./CashReplaceRainDefensePromoInshop";
|
|
import cashReplaceSafeliteCanNotRecalMobileTests from "./CashReplaceSafeliteCanNotRecalMobile";
|
|
import cashReplaceVinMobileTests from "./CashReplaceVinMobile";
|
|
import cashReplaceWiperDropoffTests from "./CashReplaceWiperDropoff";
|
|
import cashReplaceWiperPromoInShopTests from "./CashReplaceWiperPromoInshop";
|
|
import insuranceAcuityPaypalTests from "./InsuranceAcuityPaypal";
|
|
import insuranceITAC21stCenturyTests from "./InsuranceITAC21stCentury";
|
|
import insuranceGeicoTests from "./InsuranceGeico";
|
|
import insuranceITACOptimizedPriceValidationAllStateTests from "./InsuranceITACOptimizedPriceValidationAllState";
|
|
import insuranceNoCompProgressiveTests from "./InsuranceNoCompProgressive";
|
|
import cashRepairInShopAfterPayTests from "./CashRepairInShopAfterPay";
|
|
import cashRepairInShopPayPalTests from "./CashRepairInShopPayPal";
|
|
import cashReplaceMultiSlidingGlassDropoffTests from "./CashReplaceMultiSlidingGlassDropoff";
|
|
import cashReplaceMultiGlassMobileTests from "./CashReplaceMultiGlassMobile";
|
|
import { getTestObject, TestCase, prepareTest, RuleEngine, TestInfo } from 'framework/Typedefs';
|
|
import { createTestPages } from "framework/TestPages";
|
|
import cashReplaceSwitchToInsuranceProgressiveNoCompTests from "./CashReplaceSwitchToInsuranceProgressiveNoComp";
|
|
import insuranceBigTruckVerifiedTests from "./InsuranceBigTruckVerified";
|
|
import insuranceUnverifiedTests from "./InsuranceUnverified";
|
|
import CashReplaceSplitWindshieldTests from "./CashReplaceSplitWindshield";
|
|
import insuranceMeemicNearSchoolVerifiedTests from "./InsuranceMeemicNearSchoolVerified";
|
|
|
|
const test = getTestObject();
|
|
|
|
/**
|
|
* Master Test Runner
|
|
*
|
|
* This file orchestrates the execution of all test scenarios and defines the primary test workflow.
|
|
* It imports all test cases and executes them through a common test runner function to ensure
|
|
* consistent behavior across different test scenarios.
|
|
*/
|
|
|
|
// Initialize shared rule engine and validation options
|
|
const ruleEngine = new RuleEngine();
|
|
const options = new ValidationOptions();
|
|
|
|
// Add smoke tag to selected tests for CI/CD pipelines
|
|
addSmokeTagToRandomTest(splitWindshieldTests);
|
|
|
|
|
|
// Standard test scenarios
|
|
const allStandardTests = [
|
|
{name: "CashRepairMobileCreditCard", tests: cashRepairMobileCCTests},
|
|
{name: "CashRepairInShopAfterPay", tests: cashRepairInShopAfterPayTests},
|
|
{name: "CashRepairInShopPayPal", tests: cashRepairInShopPayPalTests},
|
|
{name: "CashReplaceDynamicRecalMobile", tests: cashReplaceDynamicRecalMobileTests},
|
|
{name: "CashReplaceGlassAddressLookupInshopAfterPay", tests: cashReplaceGlassAddressLookupInshopAfterPayTests},
|
|
{name: "CashReplaceGlassLicensePlateLookupInshopPaypal", tests: cashReplaceGlassLicensePlateLookupInshopPaypalTests},
|
|
{name: "CashReplaceGlassPromoInShop", tests: cashReplaceGlassPromoInshopTests},
|
|
{name: "CashReplaceMultiGlassPromoInShop", tests: cashReplaceMultiGlassPromoInshopTests},
|
|
{name: "CashReplaceMultiSlidingGlassDropoff",tests: cashReplaceMultiSlidingGlassDropoffTests},
|
|
{name: "CashReplaceMultiGlassMobile",tests: cashReplaceMultiGlassMobileTests},
|
|
{name: "CashReplaceRainDefensePromoInshop", tests: cashReplaceRainDefensePromoInshopTests},
|
|
{name: "CashReplaceSafeliteCanNotRecalMobile", tests: cashReplaceSafeliteCanNotRecalMobileTests},
|
|
{name: "CashReplaceVinMobile", tests: cashReplaceVinMobileTests},
|
|
{name: "CashReplaceWiperDropoff", tests: cashReplaceWiperDropoffTests},
|
|
{name: "CashReplaceWiperPromoInshop", tests: cashReplaceWiperPromoInShopTests},
|
|
{name: "CashReplaceSwitchToInsuranceProgressiveNoComp", tests: cashReplaceSwitchToInsuranceProgressiveNoCompTests},
|
|
// TODO: Uncomment when QA is ready to run heavy truck tests
|
|
// {name: "CashReplaceSplitWindshield", tests: CashReplaceSplitWindshieldTests},
|
|
{name: "InsuranceAcuityPaypal", tests: insuranceAcuityPaypalTests},
|
|
{name: "InsuranceITAC21stCentury", tests: insuranceITAC21stCenturyTests},
|
|
{name: "InsuranceNoCompProgressive", tests: insuranceNoCompProgressiveTests},
|
|
// {name: "InsuranceBigTruckVerified", tests: insuranceBigTruckVerifiedTests},
|
|
{name: "InsuranceUnverified", tests: insuranceUnverifiedTests},
|
|
// {name: "InsuranceGeico", tests: insuranceGeicoTests},
|
|
// {name: "InsuranceITACOptimizedPriceValidationAllState", tests: insuranceITACOptimizedPriceValidationAllStateTests}
|
|
{name: "InsuranceMeemicNearSchoolVerified", tests: insuranceMeemicNearSchoolVerifiedTests},
|
|
|
|
];
|
|
|
|
// Alert validation scenarios
|
|
const allAlertTests = [
|
|
//TODO: Uncomment when QA is ready to run heavy truck tests
|
|
// { name: "Alert Scenario 1: Heavy Truck", tests: heavyTruckTests },
|
|
{ name: "Alert Scenario 2: Repair and Replace", tests: repairAndReplaceTests },
|
|
// { name: "Alert Scenario 3: Split Windshield", tests: splitWindshieldTests },
|
|
{ name: "Alert Scenario 4: Repair Only", tests: repairOnlyTests },
|
|
{ name: "Alert Scenario 5: Unserviceable Zip", tests: unserviceableZipTests },
|
|
{ name: "Alert Scenario 6: Invalid Zip", tests: invalidZipTests },
|
|
{ name: "Alert Scenario 7: VIN Not Found", tests: vinNotFoundTests }
|
|
];
|
|
|
|
// Standard test cases
|
|
test.describe.parallel('Standard E2E Test Flows', () => {
|
|
allStandardTests.forEach(scenario => {
|
|
scenario.tests.forEach(testCase => {
|
|
test(...prepareTest(testCase, createTestPages, run, options, ruleEngine));
|
|
});
|
|
});
|
|
});
|
|
|
|
// Alert validation test cases
|
|
test.describe.parallel('Alert Validation Tests', () => {
|
|
allAlertTests.forEach(scenario => {
|
|
test.describe(scenario.name, () => {
|
|
scenario.tests.forEach(testCase => {
|
|
test(...prepareTest(testCase, createTestPages, run, options, ruleEngine));
|
|
});
|
|
});
|
|
});
|
|
});
|
|
|
|
|
|
/**
|
|
* After each test, capture screenshot and handle cleanup
|
|
*/
|
|
test.afterEach(async ({ page, testInfo }) => {
|
|
await TestCase.afterEachMethod(page, testInfo);
|
|
});
|
|
|
|
/**
|
|
* Main test runner function that executes each test case
|
|
* @param page - The Playwright page object
|
|
* @param testInfo - Test information and context
|
|
*/
|
|
async function run(page: Page, testInfo: TestInfo): Promise<void> {
|
|
try {
|
|
await testInfo.testCase.setup();
|
|
testInfo.testCase.setupPages(page, createTestPages);
|
|
await testInfo.testCase.pages.homePage.goto();
|
|
await runWorkflow(page, testInfo.testCase);
|
|
} catch (error) {
|
|
// Catch successful alert tests and log message
|
|
if (error instanceof TestSuccessAlert) {
|
|
console.log(error.message);
|
|
// Catch and throw other errors
|
|
} else {
|
|
throw error;
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Main workflow that executes the test steps in sequence
|
|
*
|
|
* This function contains the common test flow for all test scenarios:
|
|
* 1. Start at home page and enter vehicle/damage information
|
|
* 2. Select lookup method and provide details
|
|
* 3. Answer part questions if applicable
|
|
* 4. Select service package and payment method
|
|
* 5. Handle insurance flow if applicable
|
|
* 6. Select service location and schedule appointment
|
|
* 7. Complete order and validate confirmation
|
|
*
|
|
* @param page - The Playwright page object
|
|
* @param testCase - The test case to execute
|
|
*/
|
|
async function runWorkflow(page: Page, testCase: TestCase) {
|
|
|
|
// Intercept API Responses
|
|
const apiResponseInterceptUtil = new ApiResponseInterceptUtil(testCase.testData);
|
|
page.on('response', apiResponseInterceptUtil.handleInterceptResponse);
|
|
|
|
// Destructure test data for easier access
|
|
const {
|
|
paymentMethod, customerDetails, vehicleDetails, vehicleDamage,
|
|
paymentDetails, partQuestions, isEnterFunnelWithZip, capabilityQuestions,
|
|
vehiclePartQuestions, moldingQuestions, isSkipEstimatePage
|
|
} = testCase.testData;
|
|
|
|
// Check if the vehicle damage includes a windshield crack
|
|
const hasWindshieldCrack = vehicleDamage!.some(damage =>
|
|
damage === VehicleDamage.WindshieldCrack ||
|
|
damage === VehicleDamage.DriverSplitWindshield ||
|
|
damage === VehicleDamage.PassengerSplitWindshield ||
|
|
damage === VehicleDamage.SingleSplitWindshield
|
|
);
|
|
|
|
|
|
//============================= TEST WORKFLOW STEPS =============================
|
|
|
|
// Use Environment Variable to decide whether or not we want to skip content site aka home page
|
|
if (process.env.SKIP_CONTENT_SITE == "false") {
|
|
await test.step('HomePage >> Lets Get Started', async () => {
|
|
let homePage = testCase.pages.homePage;
|
|
console.log(`Customer for this test: ${customerDetails?.firstName} ${customerDetails?.lastName}`);
|
|
await homePage.letsGetStarted(customerDetails?.address.postalCode!, !!isEnterFunnelWithZip!);
|
|
});
|
|
} else {
|
|
// If enterFunnelWithZip is true, add zip code to url
|
|
if (!!isEnterFunnelWithZip!) {
|
|
const currentUrl = page.url();
|
|
const zipParam = `&zipCode=${customerDetails?.address.postalCode!}`;
|
|
if (!currentUrl.includes('zipCode=')) {
|
|
await page.goto(currentUrl + zipParam);
|
|
}
|
|
}
|
|
console.log(`Customer for this test: ${customerDetails?.firstName} ${customerDetails?.lastName}`);
|
|
}
|
|
|
|
// Handle vehicle selection page
|
|
let vehicleSelectionPage = testCase.pages.vehicleSelectionPage;
|
|
await vehicleSelectionPage.handleVehicleSelectionPage(testCase.testData);
|
|
|
|
// Handle vehicle damage page
|
|
let vehicleDamagePage = testCase.pages.vehicleDamagePage;
|
|
await vehicleDamagePage.handleVehicleDamagePage(testCase.testData);
|
|
|
|
// If the vehicle has a windshield crack as part of its damage, go to estimate page and select lookup type
|
|
if (hasWindshieldCrack && !isSkipEstimatePage) {
|
|
let estimatePage = testCase.pages.estimatePage;
|
|
await estimatePage.handleEstimatePage(testCase.testData);
|
|
|
|
// Handle different vehicle lookup methods
|
|
switch (vehicleDetails!.vehicleLookupType!) {
|
|
case VehicleLookupType.Address:
|
|
let vehicleLookupAddressPage = testCase.pages.vehicleLookupAddressPage;
|
|
await vehicleLookupAddressPage.handleVehicleLookupAddressPage(testCase.testData);
|
|
break;
|
|
|
|
case VehicleLookupType.LicensePlateNumber:
|
|
let vehicleLookupLicensePage = testCase.pages.vehicleLookupLicensePage;
|
|
await vehicleLookupLicensePage.handleVehicleLookupLicensePage(testCase.testData);
|
|
break;
|
|
|
|
case VehicleLookupType.Vin:
|
|
let vinLookupPage = testCase.pages.vinLookupPage;
|
|
await vinLookupPage.handleVehicleLookupVinPage(testCase.testData);
|
|
break;
|
|
|
|
case VehicleLookupType.Zip:
|
|
let serviceZipPage = testCase.pages.serviceZipPage;
|
|
await serviceZipPage.handleServiceZipPage(testCase.testData);
|
|
break;
|
|
}
|
|
} else {
|
|
// Otherwise just use zip lookup for service zip page
|
|
let serviceZipPage = testCase.pages.serviceZipPage;
|
|
await serviceZipPage.handleServiceZipPage(testCase.testData);
|
|
}
|
|
|
|
// Handle part questions if applicable
|
|
if (partQuestions && partQuestions.length > 0) {
|
|
let partQuestionsPage = testCase.pages.partQuestionsPage;
|
|
await partQuestionsPage.handlePartQuestionsPage(testCase.testData);
|
|
}
|
|
|
|
// Handle molding questions if applicable
|
|
if (moldingQuestions && moldingQuestions.length > 0) {
|
|
let moldingQuestionsPage = testCase.pages.moldingQuestionsPage;
|
|
await moldingQuestionsPage.handleMoldingQuestionsPage(testCase.testData);
|
|
}
|
|
|
|
// Handle vehicle part questions if applicable
|
|
if (vehiclePartQuestions && vehiclePartQuestions.length > 0) {
|
|
let vehiclePartsPage = testCase.pages.vehiclePartsPage;
|
|
await vehiclePartsPage.handleVehiclePartsPage(testCase.testData);
|
|
}
|
|
|
|
// Handle capability questions if applicable
|
|
if (capabilityQuestions && capabilityQuestions.length > 0) {
|
|
let capabilityQuestionsPage = testCase.pages.capabilityQuestionsPage;
|
|
await capabilityQuestionsPage.handleCapabilityQuestionsPage(testCase.testData);
|
|
}
|
|
|
|
// Select service package and payment method
|
|
let servicePackagesPage = testCase.pages.servicePackagesPage;
|
|
await servicePackagesPage.handleServicePackagePage(testCase.testData);
|
|
|
|
//============================= INSURANCE FLOW =============================`
|
|
|
|
// Insurance flow - if user selected Insurance as Payment Method
|
|
if (paymentMethod == PaymentMethod.Insurance) {
|
|
await handleInsuranceFlow(testCase);
|
|
}
|
|
|
|
//============================= SERVICE SCHEDULING =============================
|
|
|
|
// Select service location
|
|
let serviceLocationPage = testCase.pages.serviceLocationPage;
|
|
await serviceLocationPage.handleServiceLocationPage(testCase.testData);
|
|
|
|
|
|
// Schedule appointment
|
|
let schedulePage = testCase.pages.schedulePage;
|
|
await schedulePage.handleSchedulePage(testCase.testData);
|
|
|
|
// Enter contact details
|
|
let contactDetailsPage = testCase.pages.contactDetailsPage;
|
|
await contactDetailsPage.handleContactDetailsPage(testCase.testData);
|
|
|
|
//============================= PAYMENT PROCESSING =============================
|
|
|
|
// Handle payment
|
|
let paymentMethodPage = testCase.pages.paymentMethodPage;
|
|
await paymentMethodPage.handlePaymentMethodPage(testCase.testData);
|
|
|
|
// If user selected Pay with Insurance as Payment Method, Enter Insurance Flow
|
|
if (paymentDetails?.paymentType === PaymentType.PayWithInsurance) {
|
|
await handleInsuranceFlow(testCase);
|
|
}
|
|
|
|
//============================= ORDER CONFIRMATION =============================
|
|
|
|
// Validate order confirmation
|
|
let orderConfirmationPage = testCase.pages.orderConfirmationPage;
|
|
await orderConfirmationPage.verifyOrderConfirmationPage(testCase.testData);
|
|
}
|
|
|
|
export async function handleInsuranceFlow(testCase: TestCase) {
|
|
const { isPolicyFound, isPolicyDriver, endorsements, isRecalVehicle, isCashInsuranceFlow, flow } = testCase.testData;
|
|
|
|
// Check if the insurance policy has endorsements
|
|
const hasEndorsements = endorsements && endorsements.length > 0;
|
|
|
|
// Handle insurance company page
|
|
let insuranceCompanyPage = testCase.pages.insuranceCompanyPage;
|
|
await insuranceCompanyPage.handleInsuranceCompanyPage(testCase.testData);
|
|
|
|
// Handle ccPolicyInfoPage
|
|
let ccPolicyInfoPage = testCase.pages.ccPolicyInfoPage;
|
|
await ccPolicyInfoPage.handleCCPolicyInfoPage(testCase.testData);
|
|
|
|
let duplicateCheckPage = testCase.pages.duplicateCheckPage;
|
|
if (duplicateCheckPage.page.url().includes('DuplicateCheck.aspx')) {
|
|
await duplicateCheckPage.handleDuplicateCheckPage(testCase.testData);
|
|
}
|
|
|
|
if ( flow === Flow.Managed ) {
|
|
let policyVehiclesPage = testCase.pages.policyVehiclesPage;
|
|
await policyVehiclesPage.handlePolicyVehiclesPage(testCase.testData);
|
|
|
|
// Handle policy driver selection if applicable
|
|
if (isPolicyDriver) {
|
|
let policyDriverPage = testCase.pages.policyDriverPage;
|
|
await policyDriverPage.handlePolicyDriverPage(testCase.testData);
|
|
}
|
|
|
|
// Handle endorsements if applicable
|
|
if (hasEndorsements) {
|
|
let endorsementsPage = testCase.pages.endorsementsPage;
|
|
await endorsementsPage.handleEndorsementsPage(testCase.testData);
|
|
}
|
|
} else {
|
|
|
|
//Handle verify details page
|
|
let verifyDetailsPage = testCase.pages.verifyDetailsPage;
|
|
await verifyDetailsPage.handleVerifyDetailsPage(testCase.testData);
|
|
}
|
|
|
|
// Handle Policy info submitted page
|
|
let policyInfoSubmittedPage = testCase.pages.policyInfoSubmittedPage;
|
|
await policyInfoSubmittedPage.handlePolicyInfoSubmittedPage();
|
|
|
|
if(isRecalVehicle)
|
|
{
|
|
let recalibrationInfoPage = testCase.pages.recalibrationInfoPage;
|
|
await recalibrationInfoPage.handleRecalibrationInfoPage();
|
|
}
|
|
|
|
//handle coveraage statement page
|
|
let coverageStatementPage = testCase.pages.coverageStatementPage;
|
|
await coverageStatementPage.handleCoverageStatementPage(testCase.testData);
|
|
|
|
// Handle scenario where user selected Cash to Insurance and needs to go back through the flow
|
|
// right now we are choosing pay at appointment as payment method for this scenario
|
|
if (isCashInsuranceFlow) {
|
|
let serviceLocationPage = testCase.pages.serviceLocationPage;
|
|
await serviceLocationPage.nextPage();
|
|
|
|
//schedule
|
|
let schedulePage = testCase.pages.schedulePage;
|
|
await schedulePage.nextPage();
|
|
//customer dertails
|
|
let contactDetailsPage = testCase.pages.contactDetailsPage;
|
|
await contactDetailsPage.nextPage();
|
|
|
|
//paymentmethods
|
|
let paymentMethodPage = testCase.pages.paymentMethodPage;
|
|
await paymentMethodPage.nextPage();
|
|
}
|
|
} |