Initial commit of the Playwright test framework, including: - Configuration files for Playwright, Docker, and Sauce Labs - Test case structure and page object models - CI/CD pipeline configuration - Utilities and business logic implementations This framework will be used for end-to-end testing of the FMG application.
624 lines
No EOL
30 KiB
TypeScript
624 lines
No EOL
30 KiB
TypeScript
import TestCase from "@business-logic/types/TestCase";
|
|
import { Page } from "@playwright/test";
|
|
import { addSmokeTagToRandomTest, prepareTest, test, TestInfo } from "@business-logic/types/Test";
|
|
import { RuleEngine, ValidationOptions } from "@business-logic/types/RuleEngine";
|
|
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 "@business-logic/types/TestSuccessAlert";
|
|
import { AppointmentType, PaymentMethod, ServicePackage, VehicleLookupType, VehicleDamage, PaymentType } from "@business-logic/types/Enums";
|
|
import cashRepairMobileCCTests from "./CashRepairMobileCreditCard";
|
|
import cashReplaceDynamicRecalMobileTests from "./CashReplaceDynamicRecalMobile";
|
|
import cashReplaceGlassAddressLookupInshopAfterPayTests from "./CashReplaceGlassAddressLookupInshopAfterPay";
|
|
import cashReplaceGlassLicensePlateLookupInshopPaypalTests from "./CashReplaceGlassLicensePlateLookupInshopPaypal";
|
|
import ApiResponseInterceptUtil from "@impl/API/ApiResponseInterceptUtil";
|
|
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 cashRepairInShopAfterPayTests from "./CashRepairInShopAfterPay";
|
|
import cashRepairInShopPayPalTests from "./CashRepairInShopPayPal";
|
|
import cashReplaceMultiSlidingGlassDropoffTests from "./CashReplaceMultiSlidingGlassDropoff";
|
|
import cashReplaceMultiGlassMobileTests from "./CashReplaceMultiGlassMobile";
|
|
|
|
/**
|
|
* 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<TestCase>();
|
|
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: "InsuranceAcuityPaypal", tests: insuranceAcuityPaypalTests},
|
|
{name: "InsuranceITAC21stCentury", tests: insuranceITAC21stCenturyTests},
|
|
// {name: "InsuranceGeico", tests: insuranceGeicoTests},
|
|
// {name: "InsuranceITACOptimizedPriceValidationAllState", tests: insuranceITACOptimizedPriceValidationAllStateTests}
|
|
|
|
];
|
|
|
|
// Alert validation scenarios
|
|
const allAlertTests = [
|
|
{ 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, 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, 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);
|
|
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 {
|
|
servicePackage, paymentMethod, customerDetails, vehicleDetails, vehicleDamage,
|
|
appointmentDetails, paymentDetails, claimDetails, partQuestions, enterFunnelWithZip,
|
|
capabilityQuestions, vehiclePartQuestions, moldingQuestions, isPolicyFound,
|
|
otherVehiclesOnPolicy, isUseVehicleOnPolicy, isDuplicateClaim, isRecalNotification,
|
|
alertFlags, endorsements, isPolicyDriver, skipEstimatePage, isRecalVehicle, canNotRecal,
|
|
dynamicRecal, hasOemEndorsement, promoCode
|
|
} = testCase.testData;
|
|
|
|
// Destructure alert flag data
|
|
const {
|
|
isHeavyTruckVehicle, isRepairReplace, isSplitWindshield, isRepairOnly,
|
|
isUnserviceableZip, isInvalidZip, isVinNotFound
|
|
} = testCase.testData.alertFlags || {};
|
|
|
|
// Define repair damage types (vs. replacement types)
|
|
const repairTypes: VehicleDamage[] = [
|
|
VehicleDamage.WindshieldOneChip,
|
|
VehicleDamage.WindshieldTwoChips,
|
|
VehicleDamage.WindshieldThreeChips
|
|
];
|
|
|
|
// Determine if we're replacing or repairing
|
|
const isReplace = !repairTypes.some(damageType => {
|
|
return vehicleDamage!.includes(damageType);
|
|
});
|
|
|
|
// Check if the insurance policy has endorsements
|
|
const hasEndorsements = endorsements && endorsements.length > 0;
|
|
|
|
// Check if the vehicle damage includes a windshield crack
|
|
const hasWindshieldCrack = vehicleDamage!.some(damage =>
|
|
damage === VehicleDamage.WindshieldCrack
|
|
);
|
|
|
|
//============================= TEST WORKFLOW STEPS =============================
|
|
|
|
// Execute home page for qa and dev environments (skip for sys)
|
|
if (process.env.NODE_ENV !== 'sys') {
|
|
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!, !!enterFunnelWithZip!);
|
|
});
|
|
} else {
|
|
// If enterFunnelWithZip is true, add zip code to url
|
|
if (!!enterFunnelWithZip!) {
|
|
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}`);
|
|
}
|
|
|
|
|
|
await test.step('VehicleSelectionPage >> Select Vehicle', async () => {
|
|
let vehicleSelectionPage = testCase.pages.vehicleSelectionPage;
|
|
await vehicleSelectionPage.selectVehicle(vehicleDetails!);
|
|
|
|
// Handle alert conditions for vehicle selection
|
|
if (isHeavyTruckVehicle || isSplitWindshield) {
|
|
await vehicleSelectionPage.checkForAlertMessages();
|
|
throw new TestSuccessAlert('Both assertions are met successfully.');
|
|
}
|
|
|
|
await vehicleSelectionPage.nextPage();
|
|
});
|
|
|
|
await test.step('VehicleDamagePage >> Select Damage', async () => {
|
|
let vehicleDamagePage = testCase.pages.vehicleDamagePage;
|
|
await vehicleDamagePage.selectDamage(vehicleDamage!);
|
|
|
|
// Handle alert conditions for vehicle damage
|
|
if (isRepairReplace) {
|
|
await vehicleDamagePage.checkForBothRepairReplaceAlertMessage();
|
|
throw new TestSuccessAlert('Both assertions are met successfully.');
|
|
}
|
|
if (isRepairOnly) {
|
|
await vehicleDamagePage.checkForRepairOnlyAlertMessage();
|
|
throw new TestSuccessAlert('Both assertions are met successfully.');
|
|
}
|
|
|
|
await vehicleDamagePage.nextPage();
|
|
});
|
|
|
|
// If the vehicle has a windshield crack as part of its damage, go to estimate page and select lookup type
|
|
if (hasWindshieldCrack && !skipEstimatePage) {
|
|
await test.step('EstimatePage >> Select Lookup Type', async () => {
|
|
let estimatePage = testCase.pages.estimatePage;
|
|
await estimatePage.vehicleLookup(vehicleDetails!);
|
|
});
|
|
|
|
// Handle different vehicle lookup methods
|
|
switch (vehicleDetails!.vehicleLookupType!) {
|
|
case VehicleLookupType.Address:
|
|
await test.step('VehicleLookupAddressPage >> Lookup by address: ' + customerDetails!.address.street, async () => {
|
|
let vehicleLookupAddressPage = testCase.pages.vehicleLookupAddressPage;
|
|
await vehicleLookupAddressPage.lookupVehicleByAddress(customerDetails!, vehicleDetails!);
|
|
await vehicleLookupAddressPage.handleZipValidation(customerDetails!.address.postalCode!, vehicleDetails!.vehicleLookupType!, alertFlags!);
|
|
});
|
|
break;
|
|
|
|
case VehicleLookupType.LicensePlateNumber:
|
|
await test.step('VehicleLookupLicensePage >> Lookup by license plate: ' + vehicleDetails!.licensePlateNumber, async () => {
|
|
let vehicleLookupLicensePage = testCase.pages.vehicleLookupLicensePage;
|
|
await vehicleLookupLicensePage.enterPlateDetails(vehicleDetails!);
|
|
await vehicleLookupLicensePage.enterZip(customerDetails!.address.postalCode!);
|
|
await vehicleLookupLicensePage.handleZipValidation(customerDetails!.address.postalCode!, vehicleDetails!.vehicleLookupType!, alertFlags!);
|
|
});
|
|
break;
|
|
|
|
case VehicleLookupType.Vin:
|
|
await test.step('VinLookupPage >> Lookup by VIN: ' + vehicleDetails!.vin!, async () => {
|
|
let vinLookupPage = testCase.pages.vinLookupPage;
|
|
await vinLookupPage.enterVin(vehicleDetails!.vin!);
|
|
await vinLookupPage.enterZip(customerDetails!.address.postalCode!);
|
|
await vinLookupPage.handleZipValidation(customerDetails!.address.postalCode!, vehicleDetails!.vehicleLookupType!, alertFlags!);
|
|
});
|
|
break;
|
|
|
|
case VehicleLookupType.Zip:
|
|
await test.step('ZipLookupPage >> Lookup by service ZIP: ' + customerDetails!.address.postalCode!, async () => {
|
|
let zipLookupPage = testCase.pages.zipLookupPage;
|
|
let vinLookupPage = testCase.pages.vinLookupPage;
|
|
await vinLookupPage.enterZip(customerDetails!.address.postalCode!);
|
|
await zipLookupPage.handleZipValidation(customerDetails!.address.postalCode!, vehicleDetails!.vehicleLookupType!, alertFlags!);
|
|
});
|
|
}
|
|
} else {
|
|
// Otherwise just use zip lookup
|
|
await test.step('ZipLookupPage >> Lookup by service ZIP: ' + customerDetails!.address.postalCode!, async () => {
|
|
let zipLookupPage = testCase.pages.zipLookupPage;
|
|
let vinLookupPage = testCase.pages.vinLookupPage;
|
|
await vinLookupPage.enterZip(customerDetails!.address.postalCode!);
|
|
await zipLookupPage.handleZipValidation(customerDetails!.address.postalCode!, vehicleDetails!.vehicleLookupType!, alertFlags!);
|
|
});
|
|
}
|
|
|
|
// Handle part questions if applicable
|
|
if (partQuestions && partQuestions.length > 0) {
|
|
await test.step('PartQuestionsPage >> Select Vehicle Part Question Responses', async () => {
|
|
let partQuestionsPage = testCase.pages.partQuestionsPage;
|
|
await partQuestionsPage.validatePartQuestions(partQuestions);
|
|
await partQuestionsPage.selectPartQuestionResponses(partQuestions);
|
|
await partQuestionsPage.nextPage();
|
|
});
|
|
}
|
|
|
|
// Handle molding questions if applicable
|
|
if (moldingQuestions && moldingQuestions.length > 0) {
|
|
await test.step('MoldingQuestionsPage >> Select Molding Question Responses', async () => {
|
|
let moldingQuestionsPage = testCase.pages.moldingQuestionsPage;
|
|
await moldingQuestionsPage.validatePartQuestions(moldingQuestions);
|
|
await moldingQuestionsPage.selectPartQuestionResponses(moldingQuestions);
|
|
await moldingQuestionsPage.nextPage();
|
|
});
|
|
}
|
|
|
|
// Handle vehicle part questions if applicable
|
|
if (vehiclePartQuestions && vehiclePartQuestions.length > 0) {
|
|
await test.step('VehiclePartsPage >> Select Vehicle Part Responses', async () => {
|
|
let vehiclePartsPage = testCase.pages.vehiclePartsPage;
|
|
await vehiclePartsPage.validatePartQuestions(vehiclePartQuestions);
|
|
await vehiclePartsPage.selectPartQuestionResponses(vehiclePartQuestions);
|
|
await vehiclePartsPage.nextPage();
|
|
});
|
|
}
|
|
|
|
// Handle capability questions if applicable
|
|
if (capabilityQuestions && capabilityQuestions.length > 0) {
|
|
await test.step('CapabilityQuestionsPage >> Select Capability Question Responses', async () => {
|
|
let capabilityQuestionsPage = testCase.pages.capabilityQuestionsPage;
|
|
await capabilityQuestionsPage.validatePartQuestions(capabilityQuestions);
|
|
await capabilityQuestionsPage.selectPartQuestionResponses(capabilityQuestions);
|
|
await capabilityQuestionsPage.nextPage();
|
|
});
|
|
}
|
|
|
|
// Select service package and payment method
|
|
await test.step('ServicePackagePage >> Select Payment Method and Service Type', async() => {
|
|
let servicePackagePage = testCase.pages.servicePackagePage;
|
|
await servicePackagePage.handleQuotePopup(customerDetails!.email!);
|
|
await servicePackagePage.selectPaymentMethod(paymentMethod!);
|
|
await servicePackagePage.selectServicePackage(servicePackage!);
|
|
// Enter promo code
|
|
if (promoCode) {
|
|
await servicePackagePage.enterPromo(promoCode);
|
|
}
|
|
|
|
// Backend Validations
|
|
// Validate backend for can not recal if applicable
|
|
if (canNotRecal) {
|
|
await servicePackagePage.verifyCanNotRecal();
|
|
}
|
|
// Validate backend for dynamic recal if applicable
|
|
if (dynamicRecal) {
|
|
await servicePackagePage.verifyDynamicRecal();
|
|
}
|
|
// Validate backend for repair info (including chip verification)
|
|
await servicePackagePage.verifyIsRepair(!isReplace, vehicleDamage!);
|
|
if (isReplace) {
|
|
// Validate backend for parts info
|
|
await servicePackagePage.verifyVehicleParts(vehicleDamage!);
|
|
}
|
|
// Validate backend for OEM endorsement
|
|
if (hasOemEndorsement) {
|
|
await servicePackagePage.verifyOEMPart();
|
|
}
|
|
|
|
await servicePackagePage.nextPage();
|
|
});
|
|
|
|
//============================= INSURANCE FLOW =============================`
|
|
|
|
// Insurance flow - if user selected Insurance as Payment Method
|
|
if (paymentMethod == PaymentMethod.Insurance) {
|
|
await test.step('InsuranceCoveragePage >> Select your insurance', async() => {
|
|
let insuranceCompanyPage = testCase.pages.insuranceCompanyPage;
|
|
await insuranceCompanyPage.enterInsuranceCompany(claimDetails!.client!);
|
|
await insuranceCompanyPage.nextPage();
|
|
});
|
|
|
|
await test.step('CCPolicyInfoPage >> Fill out claim information', async() => {
|
|
let ccPolicyInfoPage = testCase.pages.ccPolicyInfoPage;
|
|
await ccPolicyInfoPage.populatePage(customerDetails!, claimDetails!, await ccPolicyInfoPage.hasCityInfo());
|
|
await ccPolicyInfoPage.nextPage();
|
|
});
|
|
|
|
// Handle duplicate claim case if applicable
|
|
if (isDuplicateClaim) {
|
|
await test.step('DuplicateCheckPage >> Start New Claim', async () => {
|
|
let duplicateCheckPage = testCase.pages.duplicateCheckPage;
|
|
await duplicateCheckPage.startNewClaim();
|
|
await duplicateCheckPage.nextPage();
|
|
});
|
|
}
|
|
|
|
// Handle policy found vs. not found flows
|
|
if (isPolicyFound) {
|
|
await test.step('PolicyVehiclesPage >> Select vehicle', async () => {
|
|
let policyVehiclesPage = testCase.pages.policyVehiclesPage;
|
|
let vehicleSelectionPage = testCase.pages.vehicleSelectionPage;
|
|
|
|
// Validate other vehicles on policy
|
|
if (otherVehiclesOnPolicy && otherVehiclesOnPolicy.length > 0) {
|
|
for (const vehicle of otherVehiclesOnPolicy) {
|
|
await policyVehiclesPage.validateVehicleIsOnPolicy(vehicle);
|
|
}
|
|
}
|
|
|
|
// If vehicle is not on the policy, select new vehicle
|
|
if (!(isUseVehicleOnPolicy ?? true)) {
|
|
await policyVehiclesPage.selectVehicleNotListed();
|
|
await policyVehiclesPage.nextPage();
|
|
await vehicleSelectionPage.selectVehicle(vehicleDetails!);
|
|
await policyVehiclesPage.nextPage();
|
|
} else {
|
|
// Otherwise, select the vehicle entered in Safelite.com
|
|
await policyVehiclesPage.selectVehicle(vehicleDetails!);
|
|
await policyVehiclesPage.nextPage();
|
|
}
|
|
});
|
|
|
|
// Handle policy driver selection if applicable
|
|
if (isPolicyDriver) {
|
|
await test.step('PolicyDriverPage >> Confirm Driver at time of damage', async () => {
|
|
let policyDriverPage = testCase.pages.policyDriverPage;
|
|
await policyDriverPage.selectPolicyDriver(customerDetails!);
|
|
await policyDriverPage.nextPage();
|
|
});
|
|
}
|
|
|
|
// Handle endorsements if applicable
|
|
if (hasEndorsements) {
|
|
await test.step('EndorsementsPage >> Select Endorsements', async () => {
|
|
let endorsementsPage = testCase.pages.endorsementsPage;
|
|
await endorsementsPage.verifyEndorsements(endorsements);
|
|
await endorsementsPage.selectEndorsements(endorsements);
|
|
await endorsementsPage.nextPage();
|
|
});
|
|
}
|
|
} else {
|
|
// Policy not found flow
|
|
await test.step('VerifyDetailsPage >> Verify Details', async () => {
|
|
let verifyDetailsPage = testCase.pages.verifyDetailsPage;
|
|
await verifyDetailsPage.verifyPolicyDetails(customerDetails!, claimDetails!);
|
|
await verifyDetailsPage.nextPage();
|
|
});
|
|
}
|
|
|
|
// Continue with the insurance flow after policy information
|
|
await test.step('PolicyInfoSubmittedPage >> Continue With Safelite Autoglass', async () => {
|
|
let policyInfoSubmittedPage = testCase.pages.policyInfoSubmittedPage;
|
|
await policyInfoSubmittedPage.verifyPolicyInfoSubmitted();
|
|
await policyInfoSubmittedPage.nextPage();
|
|
});
|
|
|
|
// Handle recalibration notification if applicable
|
|
if (isRecalNotification) {
|
|
await test.step('RecallibrationInfoPage >> Continue With Recalibration Information', async () => {
|
|
let recalibrationInfoPage = testCase.pages.recalibrationInfoPage;
|
|
await recalibrationInfoPage.nextPage();
|
|
});
|
|
}
|
|
|
|
// Continue to coverage statement
|
|
await test.step('CoverageStatementPage >> Next page', async () => {
|
|
let coverageStatementPage = testCase.pages.coverageStatementPage;
|
|
await coverageStatementPage.validateDeductibleAmount(claimDetails!);
|
|
await coverageStatementPage.nextPage();
|
|
});
|
|
}
|
|
|
|
//============================= SERVICE SCHEDULING =============================
|
|
|
|
// Select service location
|
|
await test.step('ServiceLocationPage >> Select service location', async () => {
|
|
let serviceLocationPage = testCase.pages.serviceLocationPage;
|
|
await serviceLocationPage.selectLocation(appointmentDetails!);
|
|
await serviceLocationPage.nextPage();
|
|
});
|
|
|
|
// Schedule appointment
|
|
await test.step('SchedulePage >> Select day and time', async () => {
|
|
let schedulePage = testCase.pages.schedulePage;
|
|
customerDetails!.apptDate! = await schedulePage.scheduleFirstAppointment(appointmentDetails!.serviceLocation);
|
|
});
|
|
|
|
// Enter contact details
|
|
await test.step('ContactDetailsPage >> Enter contact details', async () => {
|
|
let contactDetailsPage = testCase.pages.contactDetailsPage;
|
|
await contactDetailsPage.enterContactDetails(customerDetails!);
|
|
await contactDetailsPage.nextPage();
|
|
});
|
|
|
|
//============================= PAYMENT PROCESSING =============================
|
|
|
|
// Handle payment
|
|
await test.step('PaymentMethodPage >> Execute Payment', async () => {
|
|
let paymentMethodPage = testCase.pages.paymentMethodPage;
|
|
await paymentMethodPage.validatePaymentDetailsPage(testCase.testData);
|
|
// Verify VAPS wipers on backend for standard and premium packages
|
|
if (servicePackage === ServicePackage.Standard || servicePackage === ServicePackage.Premium) {
|
|
await paymentMethodPage.verifyVAPS();
|
|
}
|
|
if (paymentDetails?.paymentType) {
|
|
await paymentMethodPage.executePayment(paymentDetails!, isRecalVehicle!);
|
|
} else {
|
|
await paymentMethodPage.nextPage();
|
|
}
|
|
});
|
|
|
|
// If user selected Pay with Insurance as Payment Method, Enter Insurance Flow
|
|
if (paymentDetails?.paymentType === PaymentType.PayWithInsurance) {
|
|
await test.step('InsuranceCoveragePage >> Select your insurance', async() => {
|
|
let insuranceCompanyPage = testCase.pages.insuranceCompanyPage;
|
|
await insuranceCompanyPage.enterInsuranceCompany(claimDetails!.client!);
|
|
await insuranceCompanyPage.nextPage();
|
|
});
|
|
|
|
await test.step('CCPolicyInfoPage >> Fill out claim information', async() => {
|
|
const ccPolicyInfoPage = testCase.pages.ccPolicyInfoPage;
|
|
await ccPolicyInfoPage.populatePage(customerDetails!, claimDetails!, await ccPolicyInfoPage.hasCityInfo());
|
|
await ccPolicyInfoPage.nextPage();
|
|
});
|
|
|
|
// Handle duplicate claim case if applicable
|
|
if (isDuplicateClaim) {
|
|
await test.step('DuplicateCheckPage >> Start New Claim', async () => {
|
|
const duplicateCheckPage = testCase.pages.duplicateCheckPage;
|
|
await duplicateCheckPage.startNewClaim();
|
|
await duplicateCheckPage.nextPage();
|
|
});
|
|
}
|
|
|
|
// Handle policy found vs. not found flows
|
|
if (isPolicyFound) {
|
|
await test.step('PolicyVehiclesPage >> Select vehicle', async () => {
|
|
const policyVehiclesPage = testCase.pages.policyVehiclesPage;
|
|
const vehicleSelectionPage = testCase.pages.vehicleSelectionPage;
|
|
|
|
// Validate other vehicles on policy
|
|
if (otherVehiclesOnPolicy && otherVehiclesOnPolicy.length > 0) {
|
|
for (const vehicle of otherVehiclesOnPolicy) {
|
|
await policyVehiclesPage.validateVehicleIsOnPolicy(vehicle);
|
|
}
|
|
}
|
|
|
|
// If vehicle is not on the policy, select new vehicle
|
|
if (!(isUseVehicleOnPolicy ?? true)) {
|
|
await policyVehiclesPage.selectVehicleNotListed();
|
|
await policyVehiclesPage.nextPage();
|
|
await vehicleSelectionPage.selectVehicle(vehicleDetails!);
|
|
await policyVehiclesPage.nextPage();
|
|
} else {
|
|
// Otherwise, select the vehicle entered in Safelite.com
|
|
await policyVehiclesPage.selectVehicle(vehicleDetails!);
|
|
await policyVehiclesPage.nextPage();
|
|
}
|
|
});
|
|
|
|
// Handle policy driver selection if applicable
|
|
if (isPolicyDriver) {
|
|
await test.step('PolicyDriverPage >> Confirm Driver at time of damage', async () => {
|
|
const policyDriverPage = testCase.pages.policyDriverPage;
|
|
await policyDriverPage.selectPolicyDriver(customerDetails!);
|
|
await policyDriverPage.nextPage();
|
|
});
|
|
}
|
|
|
|
// Handle endorsements if applicable
|
|
if (hasEndorsements) {
|
|
await test.step('EndorsementsPage >> Select Endorsements', async () => {
|
|
const endorsementsPage = testCase.pages.endorsementsPage;
|
|
await endorsementsPage.verifyEndorsements(endorsements);
|
|
await endorsementsPage.selectEndorsements(endorsements);
|
|
await endorsementsPage.nextPage();
|
|
});
|
|
}
|
|
} else {
|
|
// Policy not found flow
|
|
await test.step('VerifyDetailsPage >> Verify Details', async () => {
|
|
const verifyDetailsPage = testCase.pages.verifyDetailsPage;
|
|
await verifyDetailsPage.verifyPolicyDetails(customerDetails!, claimDetails!);
|
|
await verifyDetailsPage.nextPage();
|
|
});
|
|
}
|
|
|
|
// Continue with the insurance flow after policy information
|
|
await test.step('PolicyInfoSubmittedPage >> Continue With Safelite Autoglass', async () => {
|
|
const policyInfoSubmittedPage = testCase.pages.policyInfoSubmittedPage;
|
|
await policyInfoSubmittedPage.verifyPolicyInfoSubmitted();
|
|
await policyInfoSubmittedPage.nextPage();
|
|
});
|
|
|
|
// Handle recalibration notification if applicable
|
|
if (isRecalNotification) {
|
|
await test.step('RecallibrationInfoPage >> Continue With Recalibration Information', async () => {
|
|
const recalibrationInfoPage = testCase.pages.recalibrationInfoPage;
|
|
await recalibrationInfoPage.nextPage();
|
|
});
|
|
}
|
|
|
|
// Continue to coverage statement
|
|
await test.step('CoverageStatementPage >> Next page', async () => {
|
|
const coverageStatementPage = testCase.pages.coverageStatementPage;
|
|
await coverageStatementPage.validateDeductibleAmount(claimDetails!);
|
|
await coverageStatementPage.nextPage();
|
|
});
|
|
}
|
|
|
|
//============================= ORDER CONFIRMATION =============================
|
|
|
|
// Validate order confirmation
|
|
await test.step('OrderConfirmationPage >> Validate order', async () => {
|
|
let orderConfirmationPage = testCase.pages.orderConfirmationPage;
|
|
await orderConfirmationPage.validateOrderConfirmationPage(testCase.testData);
|
|
});
|
|
|
|
// Get the order number and wrap it in a test step
|
|
const workOrderNumber = await testCase.pages.orderConfirmationPage.logOrderNumber();
|
|
await test.step(`Session Storage Work Order Number: ${workOrderNumber}`, async () => {
|
|
console.log(`Session Storage Work Order Number: ${workOrderNumber}`);
|
|
});
|
|
} |