fix broken playwright tests. added a new tests
This commit is contained in:
parent
6dda137834
commit
706c29c9d3
11 changed files with 294 additions and 121 deletions
|
|
@ -7,4 +7,5 @@ export interface ITestData extends base {
|
||||||
isOptedInForTextMessages: boolean,
|
isOptedInForTextMessages: boolean,
|
||||||
totalAmount?: number,
|
totalAmount?: number,
|
||||||
isForcedOEM?: boolean
|
isForcedOEM?: boolean
|
||||||
|
mockFirstInshopCallNoSchedule?: boolean
|
||||||
}
|
}
|
||||||
|
|
@ -18,6 +18,7 @@ export class BasePage {
|
||||||
readonly buttonLoadSpin: Locator;
|
readonly buttonLoadSpin: Locator;
|
||||||
readonly hamburgerMenu: Locator;
|
readonly hamburgerMenu: Locator;
|
||||||
readonly progressBar: Locator;
|
readonly progressBar: Locator;
|
||||||
|
readonly loaders: Locator;
|
||||||
|
|
||||||
constructor(page: Page) {
|
constructor(page: Page) {
|
||||||
this.page = page;
|
this.page = page;
|
||||||
|
|
@ -27,6 +28,7 @@ export class BasePage {
|
||||||
this.buttonLoadSpin = page.getByRole('alert');
|
this.buttonLoadSpin = page.getByRole('alert');
|
||||||
this.hamburgerMenu = this.page.getByRole('button', { name: 'Hamburger Menu (modal window)' });
|
this.hamburgerMenu = this.page.getByRole('button', { name: 'Hamburger Menu (modal window)' });
|
||||||
this.progressBar = this.page.locator('.progress-bar-outer .progress-bar-inner');
|
this.progressBar = this.page.locator('.progress-bar-outer .progress-bar-inner');
|
||||||
|
this.loaders = this.page.locator('.spinner-border, .loader');
|
||||||
}
|
}
|
||||||
|
|
||||||
async nextPage() {
|
async nextPage() {
|
||||||
|
|
@ -131,6 +133,47 @@ export class BasePage {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async mockScheduleResponseForFirstInshopCallNoSchedule(customerDetails: ICustomerDetails) {
|
||||||
|
let fistInshopScheduleCall = true;
|
||||||
|
|
||||||
|
const apiUrl = `https://digitalapi.${process.env['PLAYWRIGHT_ENV']!.replace('sys', 'test').toLowerCase()}.safelite.io/schedule/api/v1/schedule/shop-time-slots`;
|
||||||
|
await this.page.route(apiUrl, async (route) => {
|
||||||
|
if (!fistInshopScheduleCall) {
|
||||||
|
return route.continue();
|
||||||
|
}
|
||||||
|
|
||||||
|
// const fmt = (d: Date) => `${d.getFullYear()}-${String(d.getMonth()+1).padStart(2,"0")}-${String(d.getDate()).padStart(2,"0")}`;
|
||||||
|
// const startDate = new Date();
|
||||||
|
//const beginningOfWeek = new Date(startDate.getFullYear(), startDate.getMonth(), startDate.getDate() - startDate.getDay());
|
||||||
|
// const endDate = new Date(beginningOfWeek.getFullYear(), beginningOfWeek.getMonth(), beginningOfWeek.getDate() + 13);
|
||||||
|
// e.g., "2025-07-23"
|
||||||
|
/*if (route.request().postDataJSON().startDate === fmt(startDate) && route.request().postDataJSON().endDate === fmt(endDate)) {
|
||||||
|
const response = await route.fetch();
|
||||||
|
const responseBody = await response.json();
|
||||||
|
|
||||||
|
responseBody.days = [];
|
||||||
|
// Mock the response
|
||||||
|
await route.fulfill({
|
||||||
|
response,
|
||||||
|
body: JSON.stringify(responseBody),
|
||||||
|
});
|
||||||
|
}*/
|
||||||
|
|
||||||
|
const response = await route.fetch();
|
||||||
|
const responseBody = await response.json();
|
||||||
|
|
||||||
|
responseBody.days = [];
|
||||||
|
|
||||||
|
// Mock the response
|
||||||
|
await route.fulfill({
|
||||||
|
response,
|
||||||
|
body: JSON.stringify(responseBody),
|
||||||
|
});
|
||||||
|
fistInshopScheduleCall = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
async getRepairPartsTotal(testData: Partial<ITestData>) {
|
async getRepairPartsTotal(testData: Partial<ITestData>) {
|
||||||
const apiUrl = `https://digitalapi.${process.env['PLAYWRIGHT_ENV']!.replace('sys', 'test').toLowerCase()}.safelite.io/price/api/v1/price/order-items`;
|
const apiUrl = `https://digitalapi.${process.env['PLAYWRIGHT_ENV']!.replace('sys', 'test').toLowerCase()}.safelite.io/price/api/v1/price/order-items`;
|
||||||
await this.page.on('response', async (response) => {
|
await this.page.on('response', async (response) => {
|
||||||
|
|
@ -170,6 +213,21 @@ export class BasePage {
|
||||||
console.log(`Progress Bar Percentage: Actual - ${actualProgressPercentage} vs Expected - ${progressPercentage}`);
|
console.log(`Progress Bar Percentage: Actual - ${actualProgressPercentage} vs Expected - ${progressPercentage}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async waitForPageOrComponentload(): Promise<void> {
|
||||||
|
await Promise.all([
|
||||||
|
(async () => {
|
||||||
|
const loaderCount = await this.loaders.count();
|
||||||
|
if (loaderCount > 0) {
|
||||||
|
for (let i = 0; i < loaderCount; i++) {
|
||||||
|
await this.loaders.nth(i).waitFor({ state: 'hidden' });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})(),
|
||||||
|
this.page.waitForLoadState('load'),
|
||||||
|
this.page.waitForLoadState('networkidle')
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
async validateOEMPart( isOEM: boolean): Promise<void> {
|
async validateOEMPart( isOEM: boolean): Promise<void> {
|
||||||
if (isOEM!) {
|
if (isOEM!) {
|
||||||
// Get Vuex state from localStorage
|
// Get Vuex state from localStorage
|
||||||
|
|
|
||||||
|
|
@ -44,6 +44,7 @@ export class PartQuestionsPage extends BasePage {
|
||||||
} else {
|
} else {
|
||||||
await expect(partQuestionOptions).not.toBeAttached();
|
await expect(partQuestionOptions).not.toBeAttached();
|
||||||
}
|
}
|
||||||
|
await this.selectPartQuestionResponses(partQuestions!);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -65,7 +66,6 @@ export class PartQuestionsPage extends BasePage {
|
||||||
|
|
||||||
await this.validateProgressBar(ProgressBarPercentages.PartQuestionsPage);
|
await this.validateProgressBar(ProgressBarPercentages.PartQuestionsPage);
|
||||||
await this.validatePartQuestions(partQuestions!);
|
await this.validatePartQuestions(partQuestions!);
|
||||||
await this.selectPartQuestionResponses(partQuestions!);
|
|
||||||
await this.nextPage();
|
await this.nextPage();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ export class PaypalPage extends BasePage {
|
||||||
this.paypalLoginButton = page.getByRole('button', { name: 'Log In', exact: true });
|
this.paypalLoginButton = page.getByRole('button', { name: 'Log In', exact: true });
|
||||||
this.completePurchaseButton = page.getByTestId('submit-button-initial')
|
this.completePurchaseButton = page.getByTestId('submit-button-initial')
|
||||||
this.payWithRadioButton = page.getByRole('button').filter({ hasText: 'Pay with' });
|
this.payWithRadioButton = page.getByRole('button').filter({ hasText: 'Pay with' });
|
||||||
this.payButton = page.locator('#one-time-cta');
|
this.payButton = page.locator('footer #one-time-cta');
|
||||||
this.tryAnotherWayButton = page.getByRole('button', { name: 'Try another way' });
|
this.tryAnotherWayButton = page.getByRole('button', { name: 'Try another way' });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -50,8 +50,8 @@ export class PaypalPage extends BasePage {
|
||||||
await this.passwordTextBox.fill(paymentDetails.password!);
|
await this.passwordTextBox.fill(paymentDetails.password!);
|
||||||
await this.paypalLoginButton.click();
|
await this.paypalLoginButton.click();
|
||||||
await this.payWithRadioButton.click();
|
await this.payWithRadioButton.click();
|
||||||
await this.page.waitForTimeout(2000); // wait for 2 seconds to ensure the Pay button is clickable
|
await this.page.waitForTimeout(2000);
|
||||||
await this.payButton.dblclick();
|
await this.payButton.dblclick();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -36,6 +36,9 @@ export class SchedulePage extends BasePage {
|
||||||
readonly allDayDropOffButton: Locator;
|
readonly allDayDropOffButton: Locator;
|
||||||
readonly pickATimeButton: Locator;
|
readonly pickATimeButton: Locator;
|
||||||
readonly mobileFirstModalCloseButton: Locator;
|
readonly mobileFirstModalCloseButton: Locator;
|
||||||
|
readonly yesButtonRecalAckModal: Locator;
|
||||||
|
readonly noButtonRecalAckModal: Locator;
|
||||||
|
readonly continueButtonRecalAckModal: Locator;
|
||||||
|
|
||||||
constructor(page: Page) {
|
constructor(page: Page) {
|
||||||
super(page);
|
super(page);
|
||||||
|
|
@ -66,7 +69,10 @@ export class SchedulePage extends BasePage {
|
||||||
this.viewMoreDatesLink = this.page.getByText(/View more dates/).first();
|
this.viewMoreDatesLink = this.page.getByText(/View more dates/).first();
|
||||||
this.appointmentDuration = this.page.locator('.duration-text-block');
|
this.appointmentDuration = this.page.locator('.duration-text-block');
|
||||||
this.timeSlots = this.page.locator('fieldset:has(>legend#chooseTimeSlot) label').filter({ visible: true});
|
this.timeSlots = this.page.locator('fieldset:has(>legend#chooseTimeSlot) label').filter({ visible: true});
|
||||||
this.mobileFirstModalCloseButton = this.page.getByRole('dialog').getByRole('button', { name: 'Close' });
|
this.mobileFirstModalCloseButton = this.page.locator('#mobile-first-modal-container .btn-close');
|
||||||
|
this.yesButtonRecalAckModal = this.page.locator("label[buttonlabel='Yes']");
|
||||||
|
this.noButtonRecalAckModal = this.page.locator("label[buttonlabel='No']");
|
||||||
|
this.continueButtonRecalAckModal = this.page.locator("#recal-ack-modal-container .modal-footer button");
|
||||||
}
|
}
|
||||||
|
|
||||||
async selectLocation(testData: Partial<ITestData>) {
|
async selectLocation(testData: Partial<ITestData>) {
|
||||||
|
|
@ -98,6 +104,7 @@ export class SchedulePage extends BasePage {
|
||||||
await this.safeliteShopsList.first().click();
|
await this.safeliteShopsList.first().click();
|
||||||
// Click the save location button
|
// Click the save location button
|
||||||
await this.saveLocationButton.click();
|
await this.saveLocationButton.click();
|
||||||
|
await this.waitForPageOrComponentload();
|
||||||
}
|
}
|
||||||
|
|
||||||
// await this.inShopButton.click();
|
// await this.inShopButton.click();
|
||||||
|
|
@ -229,13 +236,25 @@ export class SchedulePage extends BasePage {
|
||||||
|
|
||||||
@step("SchedulePage >> Schedule appointment: ")
|
@step("SchedulePage >> Schedule appointment: ")
|
||||||
async handleSchedulePage(testData: Partial<ITestData>) {
|
async handleSchedulePage(testData: Partial<ITestData>) {
|
||||||
const { appointmentDetails } = testData;
|
const { appointmentDetails, isCanNotRecal } = testData;
|
||||||
|
await this.waitForPageOrComponentload();
|
||||||
await this.validateProgressBar(ProgressBarPercentages.SchedulePage);
|
await this.validateProgressBar(ProgressBarPercentages.SchedulePage);
|
||||||
if (await this.mobileFirstModalCloseButton.isVisible()) {
|
if (await this.mobileFirstModalCloseButton.isVisible()) {
|
||||||
await this.mobileFirstModalCloseButton.click();
|
await this.mobileFirstModalCloseButton.click();
|
||||||
}
|
}
|
||||||
await this.selectLocation(testData);
|
await this.selectLocation(testData);
|
||||||
|
|
||||||
|
if (await this.mobileFirstModalCloseButton.isVisible({timeout: 5000})) {
|
||||||
|
await this.page.waitForTimeout(1000);
|
||||||
|
await this.mobileFirstModalCloseButton.dblclick();
|
||||||
|
}
|
||||||
|
|
||||||
await this.scheduleFirstAppointment(testData);
|
await this.scheduleFirstAppointment(testData);
|
||||||
|
|
||||||
await this.nextPage();
|
await this.nextPage();
|
||||||
|
if (isCanNotRecal) {
|
||||||
|
await this.yesButtonRecalAckModal.click();
|
||||||
|
await this.continueButtonRecalAckModal.click();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -298,6 +298,10 @@ export class ServicePackagesPage extends BasePage {
|
||||||
await this.mockScheduleResponseForEarlyBird(customerDetails!);
|
await this.mockScheduleResponseForEarlyBird(customerDetails!);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (testData.mockFirstInshopCallNoSchedule) {
|
||||||
|
await this.mockScheduleResponseForFirstInshopCallNoSchedule(testData.customerDetails!);
|
||||||
|
}
|
||||||
|
|
||||||
await this.nextPage();
|
await this.nextPage();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { Page } from "@playwright/test";
|
import { Browser, Page } from "@playwright/test";
|
||||||
import { addSmokeTagToRandomTest, Flow, ServiceLocation } from 'safelite-playwright-core';
|
import { addSmokeTagToRandomTest, Flow, ServiceLocation } from 'safelite-playwright-core';
|
||||||
import { ValidationOptions } from 'safelite-playwright-core';
|
import { ValidationOptions } from 'safelite-playwright-core';
|
||||||
import heavyTruckTests from "./alert-validation/alert0001_HeavyTruck";
|
import heavyTruckTests from "./alert-validation/alert0001_HeavyTruck";
|
||||||
|
|
@ -18,6 +18,7 @@ import cashReplaceGlassLicensePlateLookupInshopPaypalTests from "./CashReplaceGl
|
||||||
import { ApiResponseInterceptUtil } from 'safelite-playwright-core';
|
import { ApiResponseInterceptUtil } from 'safelite-playwright-core';
|
||||||
import cashReplaceGlassPromoInshopTests from "./CashReplaceGlassPromoInshop";
|
import cashReplaceGlassPromoInshopTests from "./CashReplaceGlassPromoInshop";
|
||||||
import cashReplaceMultiGlassPromoInshopTests from "./CashReplaceMultiGlassPromoInshop";
|
import cashReplaceMultiGlassPromoInshopTests from "./CashReplaceMultiGlassPromoInshop";
|
||||||
|
import cashReplaceStaticInshopTests from "./CashReplaceStaticInshop";
|
||||||
import cashReplaceRainDefensePromoInshopTests from "./CashReplaceRainDefensePromoInshop";
|
import cashReplaceRainDefensePromoInshopTests from "./CashReplaceRainDefensePromoInshop";
|
||||||
import cashReplaceSafeliteCanNotRecalMobileTests from "./CashReplaceSafeliteCanNotRecalMobile";
|
import cashReplaceSafeliteCanNotRecalMobileTests from "./CashReplaceSafeliteCanNotRecalMobile";
|
||||||
import cashReplaceVinMobileTests from "./CashReplaceVinMobile";
|
import cashReplaceVinMobileTests from "./CashReplaceVinMobile";
|
||||||
|
|
@ -61,33 +62,34 @@ addSmokeTagToRandomTest(splitWindshieldTests);
|
||||||
|
|
||||||
// Standard test scenarios
|
// Standard test scenarios
|
||||||
const allStandardTests = [
|
const allStandardTests = [
|
||||||
{name: "CashRepairMobileCreditCard", tests: cashRepairMobileCCTests},
|
{ name: "CashRepairMobileCreditCard", tests: cashRepairMobileCCTests },
|
||||||
{name: "CashRepairInShopAfterPay", tests: cashRepairInShopAfterPayTests},
|
{ name: "CashRepairInShopAfterPay", tests: cashRepairInShopAfterPayTests },
|
||||||
{name: "CashRepairInShopPayPal", tests: cashRepairInShopPayPalTests},
|
{ name: "CashRepairInShopPayPal", tests: cashRepairInShopPayPalTests },
|
||||||
{name: "CashReplaceDynamicRecalMobile", tests: cashReplaceDynamicRecalMobileTests},
|
{ name: "CashReplaceDynamicRecalMobile", tests: cashReplaceDynamicRecalMobileTests },
|
||||||
{name: "CashReplaceGlassAddressLookupInshopAfterPay", tests: cashReplaceGlassAddressLookupInshopAfterPayTests},
|
{ name: "CashReplaceGlassAddressLookupInshopAfterPay", tests: cashReplaceGlassAddressLookupInshopAfterPayTests },
|
||||||
{name: "CashReplaceGlassLicensePlateLookupInshopPaypal", tests: cashReplaceGlassLicensePlateLookupInshopPaypalTests},
|
{ name: "CashReplaceGlassLicensePlateLookupInshopPaypal", tests: cashReplaceGlassLicensePlateLookupInshopPaypalTests },
|
||||||
{name: "CashReplaceGlassPromoInShop", tests: cashReplaceGlassPromoInshopTests},
|
{ name: "CashReplaceGlassPromoInShop", tests: cashReplaceGlassPromoInshopTests },
|
||||||
{name: "CashReplaceMultiGlassPromoInShop", tests: cashReplaceMultiGlassPromoInshopTests},
|
{ name: "CashReplaceMultiGlassPromoInShop", tests: cashReplaceMultiGlassPromoInshopTests },
|
||||||
{name: "CashReplaceMultiSlidingGlassDropoff",tests: cashReplaceMultiSlidingGlassDropoffTests},
|
{ name: "CashReplaceMultiSlidingGlassDropoff", tests: cashReplaceMultiSlidingGlassDropoffTests },
|
||||||
{name: "CashReplaceMultiGlassMobile",tests: cashReplaceMultiGlassMobileTests},
|
{ name: "CashReplaceMultiGlassMobile", tests: cashReplaceMultiGlassMobileTests },
|
||||||
{name: "CashReplaceRainDefensePromoInshop", tests: cashReplaceRainDefensePromoInshopTests},
|
{ name: "CashReplaceRainDefensePromoInshop", tests: cashReplaceRainDefensePromoInshopTests },
|
||||||
{name: "CashReplaceSafeliteCanNotRecalMobile", tests: cashReplaceSafeliteCanNotRecalMobileTests},
|
{ name: "CashReplaceSafeliteCanNotRecalMobile", tests: cashReplaceSafeliteCanNotRecalMobileTests },
|
||||||
{name: "CashReplaceVinMobile", tests: cashReplaceVinMobileTests},
|
{ name: "CashReplaceVinMobile", tests: cashReplaceVinMobileTests },
|
||||||
{name: "CashReplaceWiperDropoff", tests: cashReplaceWiperDropoffTests},
|
{ name: "CashReplaceWiperDropoff", tests: cashReplaceWiperDropoffTests },
|
||||||
{name: "CashReplaceWiperPromoInshop", tests: cashReplaceWiperPromoInShopTests},
|
{ name: "CashReplaceStaticInshop", tests: cashReplaceStaticInshopTests },
|
||||||
{name: "CashReplaceSwitchToInsuranceProgressiveNoComp", tests: cashReplaceSwitchToInsuranceProgressiveNoCompTests},
|
{ name: "CashReplaceWiperPromoInshop", tests: cashReplaceWiperPromoInShopTests },
|
||||||
|
{ name: "CashReplaceSwitchToInsuranceProgressiveNoComp", tests: cashReplaceSwitchToInsuranceProgressiveNoCompTests },
|
||||||
// TODO: Uncomment when QA is ready to run heavy truck tests
|
// TODO: Uncomment when QA is ready to run heavy truck tests
|
||||||
// {name: "CashReplaceSplitWindshield", tests: CashReplaceSplitWindshieldTests},
|
// {name: "CashReplaceSplitWindshield", tests: CashReplaceSplitWindshieldTests},
|
||||||
{name: "InsuranceAcuityPaypal", tests: insuranceAcuityPaypalTests},
|
{ name: "InsuranceAcuityPaypal", tests: insuranceAcuityPaypalTests },
|
||||||
{name: "InsuranceITAC21stCentury", tests: insuranceITAC21stCenturyTests},
|
{ name: "InsuranceITAC21stCentury", tests: insuranceITAC21stCenturyTests },
|
||||||
{name: "InsuranceNoCompProgressive", tests: insuranceNoCompProgressiveTests},
|
{ name: "InsuranceNoCompProgressive", tests: insuranceNoCompProgressiveTests },
|
||||||
// {name: "InsuranceBigTruckVerified", tests: insuranceBigTruckVerifiedTests},
|
// {name: "InsuranceBigTruckVerified", tests: insuranceBigTruckVerifiedTests},
|
||||||
{name: "InsuranceOEMAllstate", tests: insuranceOEMAllstateTests},
|
{ name: "InsuranceOEMAllstate", tests: insuranceOEMAllstateTests },
|
||||||
{name: "InsuranceUnverified", tests: insuranceUnverifiedTests},
|
{ name: "InsuranceUnverified", tests: insuranceUnverifiedTests },
|
||||||
// {name: "InsuranceGeico", tests: insuranceGeicoTests},
|
// {name: "InsuranceGeico", tests: insuranceGeicoTests},
|
||||||
// {name: "InsuranceITACOptimizedPriceValidationAllState", tests: insuranceITACOptimizedPriceValidationAllStateTests}
|
// {name: "InsuranceITACOptimizedPriceValidationAllState", tests: insuranceITACOptimizedPriceValidationAllStateTests}
|
||||||
{name: "InsuranceMeemicNearSchoolVerified", tests: insuranceMeemicNearSchoolVerifiedTests},
|
{ name: "InsuranceMeemicNearSchoolVerified", tests: insuranceMeemicNearSchoolVerifiedTests },
|
||||||
|
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
@ -146,7 +148,7 @@ async function run(page: Page, testInfo: TestInfo): Promise<void> {
|
||||||
// Catch successful alert tests and log message
|
// Catch successful alert tests and log message
|
||||||
if (error instanceof TestSuccessAlert) {
|
if (error instanceof TestSuccessAlert) {
|
||||||
console.log(error.message);
|
console.log(error.message);
|
||||||
// Catch and throw other errors
|
// Catch and throw other errors
|
||||||
} else {
|
} else {
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
|
|
@ -175,11 +177,11 @@ async function runWorkflow(page: Page, testCase: TestCase) {
|
||||||
page.on('response', apiResponseInterceptUtil.handleInterceptResponse);
|
page.on('response', apiResponseInterceptUtil.handleInterceptResponse);
|
||||||
|
|
||||||
// Destructure test data for easier access
|
// Destructure test data for easier access
|
||||||
const {
|
const {
|
||||||
paymentMethod, customerDetails, vehicleDetails, vehicleDamage,
|
paymentMethod, customerDetails, vehicleDetails, vehicleDamage,
|
||||||
paymentDetails, partQuestions, isEnterFunnelWithZip, capabilityQuestions,
|
paymentDetails, partQuestions, isEnterFunnelWithZip, capabilityQuestions,
|
||||||
vehiclePartQuestions, moldingQuestions, isSkipEstimatePage
|
vehiclePartQuestions, moldingQuestions, isSkipEstimatePage
|
||||||
} = testCase.testData;
|
} = testCase.testData;
|
||||||
|
|
||||||
// Check if the vehicle damage includes a windshield crack
|
// Check if the vehicle damage includes a windshield crack
|
||||||
const hasWindshieldCrack = vehicleDamage!.some(damage =>
|
const hasWindshieldCrack = vehicleDamage!.some(damage =>
|
||||||
|
|
@ -193,7 +195,7 @@ async function runWorkflow(page: Page, testCase: TestCase) {
|
||||||
//============================= TEST WORKFLOW STEPS =============================
|
//============================= TEST WORKFLOW STEPS =============================
|
||||||
|
|
||||||
// Use Environment Variable to decide whether or not we want to skip content site aka home page
|
// Use Environment Variable to decide whether or not we want to skip content site aka home page
|
||||||
if (process.env.SKIP_CONTENT_SITE == "false") {
|
if (process.env.SKIP_CONTENT_SITE == "false") {
|
||||||
await test.step('HomePage >> Lets Get Started', async () => {
|
await test.step('HomePage >> Lets Get Started', async () => {
|
||||||
let homePage = testCase.pages.homePage;
|
let homePage = testCase.pages.homePage;
|
||||||
console.log(`Customer for this test: ${customerDetails?.firstName} ${customerDetails?.lastName}`);
|
console.log(`Customer for this test: ${customerDetails?.firstName} ${customerDetails?.lastName}`);
|
||||||
|
|
@ -211,6 +213,16 @@ async function runWorkflow(page: Page, testCase: TestCase) {
|
||||||
console.log(`Customer for this test: ${customerDetails?.firstName} ${customerDetails?.lastName}`);
|
console.log(`Customer for this test: ${customerDetails?.firstName} ${customerDetails?.lastName}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (page.url().includes('ServiceDetails.aspx')) {
|
||||||
|
// Take a screenshot for diagnostics
|
||||||
|
await page.screenshot({ path: `test-results\\ortoni-data\\service-details-detected-${Date.now()}.png`, fullPage: true });
|
||||||
|
console.log("ServiceDetails.aspx detected");
|
||||||
|
await page.goBack();
|
||||||
|
await page.reload();
|
||||||
|
let homePage = testCase.pages.homePage;
|
||||||
|
await homePage.letsGetStarted(customerDetails?.address.postalCode!, !!isEnterFunnelWithZip!);
|
||||||
|
}
|
||||||
|
|
||||||
// Handle vehicle selection page
|
// Handle vehicle selection page
|
||||||
let vehicleSelectionPage = testCase.pages.vehicleSelectionPage;
|
let vehicleSelectionPage = testCase.pages.vehicleSelectionPage;
|
||||||
await vehicleSelectionPage.handleVehicleSelectionPage(testCase.testData);
|
await vehicleSelectionPage.handleVehicleSelectionPage(testCase.testData);
|
||||||
|
|
@ -223,24 +235,24 @@ async function runWorkflow(page: Page, testCase: TestCase) {
|
||||||
if (hasWindshieldCrack && !isSkipEstimatePage) {
|
if (hasWindshieldCrack && !isSkipEstimatePage) {
|
||||||
let estimatePage = testCase.pages.estimatePage;
|
let estimatePage = testCase.pages.estimatePage;
|
||||||
await estimatePage.handleEstimatePage(testCase.testData);
|
await estimatePage.handleEstimatePage(testCase.testData);
|
||||||
|
|
||||||
// Handle different vehicle lookup methods
|
// Handle different vehicle lookup methods
|
||||||
switch (vehicleDetails!.vehicleLookupType!) {
|
switch (vehicleDetails!.vehicleLookupType!) {
|
||||||
case VehicleLookupType.Address:
|
case VehicleLookupType.Address:
|
||||||
let vehicleLookupAddressPage = testCase.pages.vehicleLookupAddressPage;
|
let vehicleLookupAddressPage = testCase.pages.vehicleLookupAddressPage;
|
||||||
await vehicleLookupAddressPage.handleVehicleLookupAddressPage(testCase.testData);
|
await vehicleLookupAddressPage.handleVehicleLookupAddressPage(testCase.testData);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case VehicleLookupType.LicensePlateNumber:
|
case VehicleLookupType.LicensePlateNumber:
|
||||||
let vehicleLookupLicensePage = testCase.pages.vehicleLookupLicensePage;
|
let vehicleLookupLicensePage = testCase.pages.vehicleLookupLicensePage;
|
||||||
await vehicleLookupLicensePage.handleVehicleLookupLicensePage(testCase.testData);
|
await vehicleLookupLicensePage.handleVehicleLookupLicensePage(testCase.testData);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case VehicleLookupType.Vin:
|
case VehicleLookupType.Vin:
|
||||||
let vinLookupPage = testCase.pages.vinLookupPage;
|
let vinLookupPage = testCase.pages.vinLookupPage;
|
||||||
await vinLookupPage.handleVehicleLookupVinPage(testCase.testData);
|
await vinLookupPage.handleVehicleLookupVinPage(testCase.testData);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case VehicleLookupType.Zip:
|
case VehicleLookupType.Zip:
|
||||||
let serviceZipPage = testCase.pages.serviceZipPage;
|
let serviceZipPage = testCase.pages.serviceZipPage;
|
||||||
await serviceZipPage.handleServiceZipPage(testCase.testData);
|
await serviceZipPage.handleServiceZipPage(testCase.testData);
|
||||||
|
|
@ -257,7 +269,7 @@ async function runWorkflow(page: Page, testCase: TestCase) {
|
||||||
let partQuestionsPage = testCase.pages.partQuestionsPage;
|
let partQuestionsPage = testCase.pages.partQuestionsPage;
|
||||||
await partQuestionsPage.handlePartQuestionsPage(testCase.testData);
|
await partQuestionsPage.handlePartQuestionsPage(testCase.testData);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle molding questions if applicable
|
// Handle molding questions if applicable
|
||||||
if (moldingQuestions && moldingQuestions.length > 0) {
|
if (moldingQuestions && moldingQuestions.length > 0) {
|
||||||
let moldingQuestionsPage = testCase.pages.moldingQuestionsPage;
|
let moldingQuestionsPage = testCase.pages.moldingQuestionsPage;
|
||||||
|
|
@ -281,14 +293,14 @@ async function runWorkflow(page: Page, testCase: TestCase) {
|
||||||
await servicePackagesPage.handleServicePackagePage(testCase.testData);
|
await servicePackagesPage.handleServicePackagePage(testCase.testData);
|
||||||
|
|
||||||
//============================= INSURANCE FLOW =============================`
|
//============================= INSURANCE FLOW =============================`
|
||||||
|
|
||||||
// Insurance flow - if user selected Insurance as Payment Method
|
// Insurance flow - if user selected Insurance as Payment Method
|
||||||
if (paymentMethod == PaymentMethod.Insurance) {
|
if (paymentMethod == PaymentMethod.Insurance) {
|
||||||
await handleInsuranceFlow(testCase);
|
await handleInsuranceFlow(testCase);
|
||||||
}
|
}
|
||||||
|
|
||||||
//============================= SERVICE SCHEDULING =============================
|
//============================= SERVICE SCHEDULING =============================
|
||||||
|
|
||||||
// Select service location
|
// Select service location
|
||||||
// let serviceLocationPage = testCase.pages.serviceLocationPage;
|
// let serviceLocationPage = testCase.pages.serviceLocationPage;
|
||||||
// await serviceLocationPage.handleServiceLocationPage(testCase.testData);
|
// await serviceLocationPage.handleServiceLocationPage(testCase.testData);
|
||||||
|
|
@ -307,7 +319,7 @@ async function runWorkflow(page: Page, testCase: TestCase) {
|
||||||
await contactDetailsPage.handleContactDetailsPage(testCase.testData);
|
await contactDetailsPage.handleContactDetailsPage(testCase.testData);
|
||||||
|
|
||||||
//============================= PAYMENT PROCESSING =============================
|
//============================= PAYMENT PROCESSING =============================
|
||||||
|
|
||||||
// Handle payment
|
// Handle payment
|
||||||
let paymentMethodPage = testCase.pages.paymentMethodPage;
|
let paymentMethodPage = testCase.pages.paymentMethodPage;
|
||||||
await paymentMethodPage.handlePaymentMethodPage(testCase.testData);
|
await paymentMethodPage.handlePaymentMethodPage(testCase.testData);
|
||||||
|
|
@ -318,91 +330,90 @@ async function runWorkflow(page: Page, testCase: TestCase) {
|
||||||
}
|
}
|
||||||
|
|
||||||
//============================= ORDER CONFIRMATION =============================
|
//============================= ORDER CONFIRMATION =============================
|
||||||
|
|
||||||
// Validate order confirmation
|
// Validate order confirmation
|
||||||
let orderConfirmationPage = testCase.pages.orderConfirmationPage;
|
let orderConfirmationPage = testCase.pages.orderConfirmationPage;
|
||||||
await orderConfirmationPage.verifyOrderConfirmationPage(testCase.testData);
|
await orderConfirmationPage.verifyOrderConfirmationPage(testCase.testData);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function handleInsuranceFlow(testCase: TestCase) {
|
async function handleInsuranceFlow(testCase: TestCase) {
|
||||||
const { isPolicyFound, isPolicyDriver, endorsements, isRecalVehicle, isCashInsuranceFlow, isForcedOEM, flow } = testCase.testData;
|
const { isPolicyFound, isPolicyDriver, endorsements, isRecalVehicle, isCashInsuranceFlow, isForcedOEM, flow } = testCase.testData;
|
||||||
|
|
||||||
// Check if the insurance policy has endorsements
|
|
||||||
const hasEndorsements = endorsements && endorsements.length > 0;
|
|
||||||
|
|
||||||
// Handle insurance company page
|
// Check if the insurance policy has endorsements
|
||||||
let insuranceCompanyPage = testCase.pages.insuranceCompanyPage;
|
const hasEndorsements = endorsements && endorsements.length > 0;
|
||||||
await insuranceCompanyPage.handleInsuranceCompanyPage(testCase.testData);
|
|
||||||
|
|
||||||
// Handle OEM scenario
|
// Handle insurance company page
|
||||||
if (isForcedOEM) {
|
let insuranceCompanyPage = testCase.pages.insuranceCompanyPage;
|
||||||
// User should be on heritage problem glass questions page after selecting Allstate on insurance company page
|
await insuranceCompanyPage.handleInsuranceCompanyPage(testCase.testData);
|
||||||
let HeritageProblemGlassQuestionsPage = testCase.pages.heritageProblemGlassQuestionsPage;
|
|
||||||
await HeritageProblemGlassQuestionsPage.handleHeritageProblemGlassQuestionsPage(testCase.testData);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle ccPolicyInfoPage
|
|
||||||
let ccPolicyInfoPage = testCase.pages.ccPolicyInfoPage;
|
|
||||||
await ccPolicyInfoPage.handleCCPolicyInfoPage(testCase.testData);
|
|
||||||
|
|
||||||
let duplicateCheckPage = testCase.pages.duplicateCheckPage;
|
// Handle OEM scenario
|
||||||
if (duplicateCheckPage.page.url().includes('DuplicateCheck.aspx')) {
|
if (isForcedOEM) {
|
||||||
await duplicateCheckPage.handleDuplicateCheckPage(testCase.testData);
|
// User should be on heritage problem glass questions page after selecting Allstate on insurance company page
|
||||||
|
let HeritageProblemGlassQuestionsPage = testCase.pages.heritageProblemGlassQuestionsPage;
|
||||||
|
await HeritageProblemGlassQuestionsPage.handleHeritageProblemGlassQuestionsPage(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);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( flow === Flow.Managed ) {
|
// Handle endorsements if applicable
|
||||||
let policyVehiclesPage = testCase.pages.policyVehiclesPage;
|
if (hasEndorsements) {
|
||||||
await policyVehiclesPage.handlePolicyVehiclesPage(testCase.testData);
|
let endorsementsPage = testCase.pages.endorsementsPage;
|
||||||
|
await endorsementsPage.handleEndorsementsPage(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);
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
|
||||||
// Handle Policy info submitted page
|
//Handle verify details page
|
||||||
let policyInfoSubmittedPage = testCase.pages.policyInfoSubmittedPage;
|
let verifyDetailsPage = testCase.pages.verifyDetailsPage;
|
||||||
await policyInfoSubmittedPage.handlePolicyInfoSubmittedPage();
|
await verifyDetailsPage.handleVerifyDetailsPage(testCase.testData);
|
||||||
|
}
|
||||||
|
|
||||||
if(isRecalVehicle)
|
// Handle Policy info submitted page
|
||||||
{
|
let policyInfoSubmittedPage = testCase.pages.policyInfoSubmittedPage;
|
||||||
let recalibrationInfoPage = testCase.pages.recalibrationInfoPage;
|
await policyInfoSubmittedPage.handlePolicyInfoSubmittedPage();
|
||||||
await recalibrationInfoPage.handleRecalibrationInfoPage();
|
|
||||||
|
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) {
|
||||||
|
// Schedule appointment
|
||||||
|
let schedulePage = testCase.pages.schedulePage;
|
||||||
|
await schedulePage.handleSchedulePage(testCase.testData);
|
||||||
|
|
||||||
|
if (testCase.testData.appointmentDetails?.serviceLocation === ServiceLocation.Mobile) {
|
||||||
|
let mobileDetailsPage = testCase.pages.mobileDetailsPage;
|
||||||
|
await mobileDetailsPage.handleMobileDetailsPage(testCase.testData);
|
||||||
}
|
}
|
||||||
|
//customer dertails
|
||||||
|
let contactDetailsPage = testCase.pages.contactDetailsPage;
|
||||||
|
await contactDetailsPage.nextPage();
|
||||||
|
|
||||||
//handle coveraage statement page
|
//paymentmethods
|
||||||
let coverageStatementPage = testCase.pages.coverageStatementPage;
|
let paymentMethodPage = testCase.pages.paymentMethodPage;
|
||||||
await coverageStatementPage.handleCoverageStatementPage(testCase.testData);
|
await paymentMethodPage.nextPage();
|
||||||
|
}
|
||||||
// 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) {
|
|
||||||
// Schedule appointment
|
|
||||||
let schedulePage = testCase.pages.schedulePage;
|
|
||||||
await schedulePage.handleSchedulePage(testCase.testData);
|
|
||||||
|
|
||||||
if (testCase.testData.appointmentDetails?.serviceLocation === ServiceLocation.Mobile) {
|
|
||||||
let mobileDetailsPage = testCase.pages.mobileDetailsPage;
|
|
||||||
await mobileDetailsPage.handleMobileDetailsPage(testCase.testData);
|
|
||||||
}
|
|
||||||
//customer dertails
|
|
||||||
let contactDetailsPage = testCase.pages.contactDetailsPage;
|
|
||||||
await contactDetailsPage.nextPage();
|
|
||||||
|
|
||||||
//paymentmethods
|
|
||||||
let paymentMethodPage = testCase.pages.paymentMethodPage;
|
|
||||||
await paymentMethodPage.nextPage();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
@ -61,7 +61,8 @@ const cashReplaceDynamicRecalMobileData: Partial<ITestData> = {
|
||||||
// Override payment details
|
// Override payment details
|
||||||
paymentDetails: {
|
paymentDetails: {
|
||||||
paymentType: PaymentType.PayAtService,
|
paymentType: PaymentType.PayAtService,
|
||||||
promoCode: 'digitalrain'
|
// promoCode: 'digitalrain'
|
||||||
|
promoCode: 'rain50'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
78
playwright-tests/tests/CashReplaceStaticInshop.ts
Normal file
78
playwright-tests/tests/CashReplaceStaticInshop.ts
Normal file
|
|
@ -0,0 +1,78 @@
|
||||||
|
//Imports here
|
||||||
|
import { ITestData } from 'framework/TestData'
|
||||||
|
import { ServicePackage, PaymentType, PartQuestionType } from 'safelite-playwright-core';
|
||||||
|
import { ITestCase } from '../framework/Typedefs'
|
||||||
|
import { VehicleLookupType } from 'safelite-playwright-core';
|
||||||
|
import { getDefaultTestData, setFakerSeedFromTestName } from 'safelite-playwright-core';
|
||||||
|
import { PaymentMethod } from 'framework/localTypes/Enums';
|
||||||
|
|
||||||
|
// Set the seed before generating any data
|
||||||
|
setFakerSeedFromTestName("CashReplaceStaticInshop");
|
||||||
|
|
||||||
|
// Now get the test data with the seeded faker
|
||||||
|
const CashReplaceStaticInshopData: Partial<ITestData> = {
|
||||||
|
...getDefaultTestData(), // Get default data with current seed
|
||||||
|
|
||||||
|
// CASH Client
|
||||||
|
paymentMethod: PaymentMethod.SelfPay,
|
||||||
|
|
||||||
|
// Key feature: Premium package with Rain Defense
|
||||||
|
servicePackage: ServicePackage.Standard,
|
||||||
|
|
||||||
|
// Flag for recalibration vehicle
|
||||||
|
isRecalVehicle: true,
|
||||||
|
|
||||||
|
// Override customer details
|
||||||
|
customerDetails: {
|
||||||
|
...getDefaultTestData().customerDetails!,
|
||||||
|
address: {
|
||||||
|
...getDefaultTestData().customerDetails!.address,
|
||||||
|
postalCode: '43085'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// override part questions
|
||||||
|
partQuestions: [
|
||||||
|
{
|
||||||
|
partQuestionType: PartQuestionType.GeneralQuestion1,
|
||||||
|
isOnPage: true,
|
||||||
|
optionToSelect: 'Yes'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
partQuestionType: PartQuestionType.GeneralQuestion2,
|
||||||
|
isOnPage: true,
|
||||||
|
optionToSelect: 'Yes'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
|
||||||
|
// Override vehicle details
|
||||||
|
vehicleDetails: {
|
||||||
|
...getDefaultTestData().vehicleDetails!,
|
||||||
|
year: '2022',
|
||||||
|
make: 'Mazda',
|
||||||
|
model: 'CX-9',
|
||||||
|
style: '4 door utility',
|
||||||
|
vin: '3FA6P0HD8LR234510',
|
||||||
|
vehicleLookupType: VehicleLookupType.Zip
|
||||||
|
},
|
||||||
|
|
||||||
|
mockFirstInshopCallNoSchedule: true,
|
||||||
|
|
||||||
|
// No need to override vehicleDamage as it already defaults to WindshieldCrack
|
||||||
|
|
||||||
|
// Payment at service
|
||||||
|
paymentDetails: {
|
||||||
|
paymentType: PaymentType.PayAtService
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
const cashReplaceStaticInshopTests: ITestCase[] = [];
|
||||||
|
|
||||||
|
const tc = {
|
||||||
|
name: `CashReplaceStaticInshop`,
|
||||||
|
tags: ['@E2E','@CashReplaceStaticInshop', '@test_report', '@CASH'],
|
||||||
|
testData: CashReplaceStaticInshopData
|
||||||
|
};
|
||||||
|
cashReplaceStaticInshopTests.push(tc);
|
||||||
|
|
||||||
|
export default cashReplaceStaticInshopTests;
|
||||||
|
|
@ -66,7 +66,7 @@ const cashReplaceWiperDropoffData: Partial<ITestData> = {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
partQuestionType: PartQuestionType.GeneralQuestion2,
|
partQuestionType: PartQuestionType.GeneralQuestion2,
|
||||||
isOnPage: false,
|
isOnPage: true,
|
||||||
optionToSelect: 'Yes'
|
optionToSelect: 'Yes'
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -32,10 +32,11 @@ const insuranceNoCompProgressiveData: Partial<ITestData> = {
|
||||||
lastName: 'SCHATZ',
|
lastName: 'SCHATZ',
|
||||||
address: {
|
address: {
|
||||||
...getDefaultTestData().customerDetails!.address,
|
...getDefaultTestData().customerDetails!.address,
|
||||||
city: 'Slidell',
|
// city: 'Slidell',
|
||||||
state: 'Louisiana',
|
// state: 'Louisiana',
|
||||||
postalCode: '70458'
|
// postalCode: '70458'
|
||||||
}
|
postalCode: '43085'
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -71,7 +72,7 @@ const insuranceNoCompProgressiveData: Partial<ITestData> = {
|
||||||
// Override for in-shop appointment
|
// Override for in-shop appointment
|
||||||
appointmentDetails: {
|
appointmentDetails: {
|
||||||
serviceLocation: ServiceLocation.InShop,
|
serviceLocation: ServiceLocation.InShop,
|
||||||
shopAddress: '56705 Garrett Road, Slidell, LA 70458',
|
// shopAddress: '56705 Garrett Road, Slidell, LA 70458',
|
||||||
appointmentDate: getDefaultTestData().appointmentDetails?.appointmentDate
|
appointmentDate: getDefaultTestData().appointmentDetails?.appointmentDate
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue