Merge branch 'develop' into feature/humphries/INSR-7775.1

This commit is contained in:
Alex Humphries 2026-02-20 10:31:31 -05:00
commit fd4434f48d
37 changed files with 520 additions and 835 deletions

View file

@ -94,10 +94,11 @@ export default {
}
if (error.response.status !== 404) {
global.$logger.logError(`${method}: ${endpoint}: ${error.message}`, error.response);
const errorData = { method, url, payload, error };
global.$logger.logError(`${method}: ${endpoint}`, errorData);
if (bailoutOnError && global.bailoutOnAxiosError !== undefined)
{
global.bailoutOnAxiosError({ url, error });
global.bailoutOnAxiosError(errorData);
}
}
return reject(error.response);

View file

@ -21,7 +21,8 @@ global.$logger = {
function setupMocksForHttpClient({
endpoint = null,
isError = false,
additionalData = null
additionalData = null,
bailoutOnError = false
}) {
// Clear node module
axios.mockClear();
@ -57,7 +58,8 @@ function setupMocksForHttpClient({
return {
endpoint,
logApiCall: true
logApiCall: true,
bailoutOnError
};
}
@ -92,3 +94,21 @@ it('Global Methods - Call Http Client - Should Reject Promise', () => {
expect(err.status).toEqual(500);
});
});
it('Global Methods - Call Http Client - Rejected Promised - bailoutOnError: true - Calls global.bailoutOnAxiosError', () => {
// Arrange
const endpoint = 'https://mock.safelite.com';
const httpArgs = setupMocksForHttpClient({
endpoint,
isError: true,
bailoutOnError: true
});
analyticsMixIn.methods.pushEventToGA = jest.fn();
global.bailoutOnAxiosError = jest.fn();
// Act
globalMethods.callHttpClient(httpArgs).catch((err) => {
// Assert
expect(global.bailoutOnAxiosError).toHaveBeenCalledTimes(1);
});
});

View file

@ -4,8 +4,8 @@ import submitType from '@/constants/submit-type';
/*
Encapsulates asynchronous Save Session logic inside a promise to allow for Save Session queuing
*/
async function saveSessionHelper(store, { submitAfterSave, createWorkOrderNumberForPIA }) {
const savedSessionInfo = await store.saveSession({ submitAfterSave, createWorkOrderNumberForPIA });
async function saveSessionHelper(store, { submitAfterSave, createWorkOrderNumberForPIA, bailoutOnError }) {
const savedSessionInfo = await store.saveSession({ submitAfterSave, createWorkOrderNumberForPIA, bailoutOnError });
if (savedSessionInfo) {
store.setSaveSessionInfo(savedSessionInfo.data);
}
@ -16,11 +16,11 @@ async function saveSessionHelper(store, { submitAfterSave, createWorkOrderNumber
This will also set Referral information in the store after saving, and then
update the cookie. To force synchronous behavior pass in 'true' for shouldAwaitSaveSessionQueue
*/
export async function saveSession({ shouldAwaitSaveSessionQueue = false, submitAfterSave = false, createWorkOrderNumberForPIA = false }) {
export async function saveSession({ shouldAwaitSaveSessionQueue = false, submitAfterSave = false, createWorkOrderNumberForPIA = false, bailoutOnError = false }) {
const store = useMainStore();
const saveSessionPromise = store.applicationUser.saveSessionPromise
? store.applicationUser.saveSessionPromise.then(() => saveSessionHelper(store, { submitAfterSave, createWorkOrderNumberForPIA }))
: saveSessionHelper(store, { submitAfterSave, createWorkOrderNumberForPIA });
? store.applicationUser.saveSessionPromise.then(() => saveSessionHelper(store, { submitAfterSave, createWorkOrderNumberForPIA, bailoutOnError }))
: saveSessionHelper(store, { submitAfterSave, createWorkOrderNumberForPIA, bailoutOnError });
store.setSaveSessionPromise(saveSessionPromise);
@ -38,7 +38,8 @@ export async function submitWorkOrder({ submitType }) {
store.resetSubmittedOrder();
await saveSession({
shouldAwaitSaveSessionQueue: true,
submitAfterSave: true
submitAfterSave: true,
bailoutOnError: true
});
await store.createSubmittedOrder(submitType);
}

View file

@ -157,8 +157,7 @@ export default {
this.navigateForward(this.partsOrQuestionsData, null);
},
requestCallbackBailout() {
this.mainStore.setBailout(bailoutMessage.RequestCallback());
this.$router.navigate(navigationScenarios.CLICKED_NEED_HELP_WITH_BAILOUT, this.$route);
this.$router.navigateBailout(bailoutMessage.RequestCallback());
}
}
};

View file

@ -63,7 +63,8 @@ const loadingModalStub = {
function getMountedComponent(mainInitialState = {}, initialData = {}, methodToRun = () => {}) {
const mountOptions = getMountOptions({
router: {
navigate: jest.fn()
navigate: jest.fn(),
navigateBailout: jest.fn()
}
});
@ -690,7 +691,7 @@ describe('coverageStatement.vue', () => {
undefined
);
});
test('If Verified ITAC, selected Cancel, navigate forward w/ CLICKED_FORWARD_WITH_NON_SAFELITE_SHOP', () => {
test('If Verified ITAC, selected Cancel, navigateBailout', () => {
// Arrange
const deductible = servicePrice + 1;
const mainInitialState = {
@ -716,11 +717,7 @@ describe('coverageStatement.vue', () => {
wrapper.vm.cancelClaim();
// Assert
expect(wrapper.vm.$router.navigate)
.toHaveBeenCalledWith(
navigationScenarios.CLICKED_FORWARD_WITH_NON_SAFELITE_SHOP,
undefined
);
expect(wrapper.vm.$router.navigateBailout).toHaveBeenCalled();
});
test('If No Comp and selected Safelite, navigate forward with CLICKED_FORWARD_WITH_SAFELITE scenario', () => {
// Arrange
@ -753,7 +750,7 @@ describe('coverageStatement.vue', () => {
undefined
);
});
test('If No comp and selected other shop, navigate forward with CLICKED_FORWARD_WITH_NON_SAFELITE_SHOP ', () => {
test('If No comp and selected other shop, navigateBailout ', () => {
// Arrange
const mainInitialState = {
order: {
@ -778,11 +775,7 @@ describe('coverageStatement.vue', () => {
wrapper.vm.cancelClaim();
// Assert
expect(wrapper.vm.$router.navigate)
.toHaveBeenCalledWith(
navigationScenarios.CLICKED_FORWARD_WITH_NON_SAFELITE_SHOP,
undefined
);
expect(wrapper.vm.$router.navigateBailout).toHaveBeenCalled();
});
});
describe('openCancelClaimModal', () => {

View file

@ -397,18 +397,7 @@ export default {
// We only call the ITAC pricing endpoint if we are not repair or we are NoComp
if (!this.isRepair || this.mainStore.isNoComp) {
const pricingResults = await useMainStore().getITACPriceOrderItems(availableLineItems)
.catch((err) => {
useMainStore().setBailout(bailoutMessage.pricingResponseError(
availableLineItems.map((li) => li.partNumber),
{
code: err.code,
message: err.message,
data: err.data
}
));
this.navigateWithScenario(navigationScenarios.PRICING_LOOKUP_ERROR);
});
const pricingResults = await useMainStore().getITACPriceOrderItems(availableLineItems);
this.setBaseServiceLineItems(pricingResults);
}
},
@ -419,8 +408,7 @@ export default {
this.mainStore.updateIsSafeliteProvider(true);
this.navigateWithScenario(navigationScenarios.CLICKED_FORWARD_WITH_SAFELITE);
} else {
this.mainStore.setBailout(bailoutMessage.coverageStatementInvalidState());
this.navigateWithScenario(navigationScenarios.CLICKED_FORWARD_WITH_INVALID_STATE);
this.$router.navigateBailout(bailoutMessage.coverageStatementInvalidState());
}
},
navigateWithScenario(scenario) {
@ -474,8 +462,7 @@ export default {
},
cancelClaim() {
this.mainStore.updateIsSafeliteProvider(false);
this.mainStore.setBailout(bailoutMessage.RequestCallback());
this.navigateWithScenario(navigationScenarios.CLICKED_FORWARD_WITH_NON_SAFELITE_SHOP);
this.$router.navigateBailout(bailoutMessage.RequestCallback());
}
}
};

View file

@ -357,11 +357,15 @@ describe('duplicateCheck.vue', () => {
useMainStore().loadSession = jest.fn().mockImplementation(() => Promise.reject(error));
// Act
await wrapper.vm.forwardButtonAction();
// Assert
expect.assertions(2);
try {
await wrapper.vm.forwardButtonAction();
} catch (e) {
expect(e).toMatch(error);
}
expect(wrapper.vm.mainStore.loadSession).toHaveBeenCalledTimes(1);
expect(wrapper.vm.$router.navigate).toHaveBeenCalledTimes(1);
});
test('coverageType deductible and policy vehicles returned => CLICKED_FORWARD_POLICY_VERIFIED_WITH_VEHICLES', async () => {
// Arrange

View file

@ -140,18 +140,14 @@ export default {
return;
}
try {
const selectedReferral =
this.mainStore.applicationUser.duplicateOrders.find((o) => o.correlationId === this.selectedAnswer);
const selectedReferral =
this.mainStore.applicationUser.duplicateOrders.find((o) => o.correlationId === this.selectedAnswer);
if (selectedReferral) {
await this.mainStore.loadSession(selectedReferral);
}
} catch (err) {
console.error(`Error on loading session from duplicate check ${err}`);
} finally {
this.navigateForward();
if (selectedReferral) {
await this.mainStore.loadSession(selectedReferral);
}
this.navigateForward();
},
navigateForward() {
this.mainStore.updateDuplicateCheckVisited(true);

View file

@ -34,44 +34,51 @@ export default {
computed: {
},
async mounted() {
const queryStringParams = this.parseQueryParms();
const { isAuthorized, clientData, decryptedParams } = await this.validateClientTagOnEntry(queryStringParams);
this.unauthorized = !isAuthorized;
if (!isAuthorized) {
// Remove the loading animation if client tag validation fails so users can see the Unauthorized Access message.
showIssLoadingModal(false);
return;
}
this.populateISSConfigValues(clientData);
try {
// Check cookie
const issCookie = getISSCookie();
if (issCookie !== null && issCookie.VehicleMake && issCookie.VehicleModel) {
const clientParentAccountNumber = clientData.parentAccountNumber;
const cookieParentAccountNumber = issCookie.ReferralParentAccountNumber;
const queryStringParams = this.parseQueryParms();
if (clientParentAccountNumber === cookieParentAccountNumber) {
const savedSessionTimeStamp = new Date(issCookie.SavedSessionTimeoutDate);
const isSavedSessionTimedOut = new Date(new Date().toUTCString()) > savedSessionTimeStamp;
const { isAuthorized, clientData, decryptedParams } = await this.validateClientTagOnEntry(queryStringParams);
if (!isSavedSessionTimedOut) {
this.mainStore.issConfig.enableContinueFromCookie = true;
this.unauthorized = !isAuthorized;
if (!isAuthorized) {
// Remove the loading animation if client tag validation fails so users can see the Unauthorized Access message.
showIssLoadingModal(false);
return;
}
this.populateISSConfigValues(clientData);
try {
// Check cookie
const issCookie = getISSCookie();
if (issCookie !== null && issCookie.VehicleMake && issCookie.VehicleModel) {
const clientParentAccountNumber = clientData.parentAccountNumber;
const cookieParentAccountNumber = issCookie.ReferralParentAccountNumber;
if (clientParentAccountNumber === cookieParentAccountNumber) {
const savedSessionTimeStamp = new Date(issCookie.SavedSessionTimeoutDate);
const isSavedSessionTimedOut = new Date(new Date().toUTCString()) > savedSessionTimeStamp;
if (!isSavedSessionTimedOut) {
this.mainStore.issConfig.enableContinueFromCookie = true;
}
}
} else {
updateOrCreateISSCookie(true);
}
} else {
} catch {
updateOrCreateISSCookie(true);
}
} catch {
updateOrCreateISSCookie(true);
}
if (clientData.parameters?.length > 0) {
const finalParams = this.combineClientParameters(clientData.parameters, { ...queryStringParams, ...decryptedParams });
this.populateStoreItemsFromParams(finalParams);
if (clientData.parameters?.length > 0) {
const finalParams = this.combineClientParameters(clientData.parameters, { ...queryStringParams, ...decryptedParams });
this.populateStoreItemsFromParams(finalParams);
}
} catch (e) {
global.$logger.logError('[Entry Page] Client Setup Error:', e);
this.unauthorized = true;
showIssLoadingModal(false);
return;
}
this.mainStore.applicationUser.coverageAttempts = 0;
@ -151,37 +158,33 @@ export default {
this.mainStore.issConfig.isCoverageEnabled = data.coverageEnabled;
this.mainStore.issConfig.siteType = data.siteType;
try {
if (data.clientFlags) {
const clientFlags = JSON.parse(data.clientFlags);
if (data.clientFlags) {
const clientFlags = JSON.parse(data.clientFlags);
if (clientFlags.TPAEnabled) {
this.mainStore.issConfig.enableTPAFlow = true;
}
if (clientFlags.ClientFullName != null) {
this.mainStore.issConfig.clientFullName = clientFlags.ClientFullName;
}
if (clientFlags.ClientDisplayName != null) {
this.mainStore.issConfig.clientDisplayName = clientFlags.ClientDisplayName;
this.mainStore.issConfig.clientPossessiveName = toPossessive(clientFlags.ClientDisplayName);
}
if (clientFlags.ClientPossessiveName != null) {
this.mainStore.issConfig.clientPossessiveName = clientFlags.ClientPossessiveName;
}
if (clientFlags.ClaimRegistrationRequired) {
this.mainStore.issConfig.isClaimRegistrationRequired = true;
}
if (clientFlags.EnableNoCompQuote) {
this.mainStore.issConfig.enableNoCompQuote = true;
}
if (clientFlags.TPAEnabled) {
this.mainStore.issConfig.enableTPAFlow = true;
}
if (clientFlags.ClientFullName != null) {
this.mainStore.issConfig.clientFullName = clientFlags.ClientFullName;
}
if (clientFlags.ClientDisplayName != null) {
this.mainStore.issConfig.clientDisplayName = clientFlags.ClientDisplayName;
this.mainStore.issConfig.clientPossessiveName = toPossessive(clientFlags.ClientDisplayName);
}
if (clientFlags.ClientPossessiveName != null) {
this.mainStore.issConfig.clientPossessiveName = clientFlags.ClientPossessiveName;
}
if (clientFlags.ClaimRegistrationRequired) {
this.mainStore.issConfig.isClaimRegistrationRequired = true;
}
if (clientFlags.EnableNoCompQuote) {
this.mainStore.issConfig.enableNoCompQuote = true;
}
} catch (e) {
console.error(`Error parsing client flags: ${e}`);
}
},
combineClientParameters(configParams, queryStringParams) {

View file

@ -148,8 +148,7 @@ export default {
this.navigateForward(partsOrQuestions, null);
},
requestCallbackBailout() {
this.mainStore.setBailout(bailoutMessage.RequestCallback());
this.$router.navigate(navigationScenarios.CLICKED_NEED_HELP_WITH_BAILOUT, this.$route);
this.$router.navigateBailout(bailoutMessage.RequestCallback());
}
}
};

View file

@ -148,8 +148,7 @@ export default {
this.navigateForward(glassPartsForStore, null);
},
requestCallbackBailout() {
this.mainStore.setBailout(bailoutMessage.RequestCallback());
this.$router.navigate(navigationScenarios.CLICKED_NEED_HELP_WITH_BAILOUT, this.$route);
this.$router.navigateBailout(bailoutMessage.RequestCallback());
}
},
};

View file

@ -260,25 +260,16 @@ export default {
async forwardButtonAction() {
useMainStore().savePaymentMethodChoice(this.paymentMethod);
if (this.paymentMethod === paymentMethods.PAY_AT_TIME_OF_SERVICE) {
try {
await submitWorkOrder({ submitType: submitType.SAFELITE });
this.$router.navigate(
this.navigationScenarios.CLICKED_FORWARD,
this.$route
);
} catch (error) {
useMainStore().setBailout(bailoutMessage.saveSessionError(error.data));
this.$router.navigate(
this.navigationScenarios.SAVE_SESSION_FAILED,
this.$route,
{ issPage: issPageValues.PAYMENT_METHOD }
);
console.error(`error: response from submit work order:${error.message}`);
}
await submitWorkOrder({ submitType: submitType.SAFELITE });
this.$router.navigate(
this.navigationScenarios.CLICKED_FORWARD,
this.$route
);
} else {
await saveSession({
createWorkOrderNumberForPIA: true,
shouldAwaitSaveSessionQueue: true
shouldAwaitSaveSessionQueue: true,
bailoutOnError: true
});
this.$router.navigate(

View file

@ -124,13 +124,7 @@ export default {
},
async saveAndSubmitWorkOrder() {
// Final work order submit after returning from pay in advance.
try {
await submitWorkOrder({ submitType: submitType.SAFELITE });
} catch (error) {
console.error(`error: response from submit work order:${error.message}`);
this.navigateOnPayInAdvanceError();
return;
}
await submitWorkOrder({ submitType: submitType.SAFELITE });
this.$router.navigate(
this.navigationScenarios.PAY_IN_ADVANCE_SUCCESS,

View file

@ -252,12 +252,12 @@ describe('policy-vehicles.vue', () => {
);
test(
'Error in lookupVehicleByVin call => bailout true and navigate forward with CLICKED_FORWARD_WITH_BAILOUT scenario.',
'Error in lookupVehicleByVin call => error thrown in forwardButtonAction.',
async () => {
// Arrange
const { wrapper } = setupMocks({});
const lookupReturnValue = { error: true, status: 500, data: 'error' };
wrapper.vm.lookupVehicleByVin = jest.fn().mockReturnValue(lookupReturnValue);
wrapper.vm.lookupVehicleByVin = jest.fn().mockReturnValue(Promise.reject(lookupReturnValue));
const vin = getRandomString(17, 17);
await wrapper.setData({
@ -270,21 +270,14 @@ describe('policy-vehicles.vue', () => {
});
// Act
wrapper.vm.mainStore.applicationUser.pageData[issPageValues.BAILOUT_PAGE] = {
'bailout-page': {
bailoutCode: bailoutCode.VehicleVinLookupError
}
};
await wrapper.vm.forwardButtonAction();
// Assert
expect(wrapper.vm.mainStore.setBailout).toHaveBeenCalledWith(bailoutMessage.vehicleVinLookupError(vin, lookupReturnValue.data));
expect(wrapper.vm.$router.navigate).toHaveBeenCalledWith(
navigationScenarios.CLICKED_FORWARD_WITH_BAILOUT,
undefined,
{},
{}
);
expect.assertions(1);
try {
await wrapper.vm.forwardButtonAction();
} catch (e) {
expect(e).toBe(lookupReturnValue);
}
}
);
@ -292,7 +285,7 @@ describe('policy-vehicles.vue', () => {
async () => {
// Arrange
const { wrapper } = setupMocks({});
wrapper.vm.lookupVehicleByVin = jest.fn().mockReturnValue({ error: true, status: 404 });
wrapper.vm.lookupVehicleByVin = jest.fn().mockRejectedValue({ isAxiosError: true, status: 404 });
const vin = getRandomString(17, 17);
await wrapper.setData({

View file

@ -59,7 +59,6 @@ import vehicleSelectionOptions from '@/constants/vehicle-selection-options.js';
import endorsementOptions from '@/constants/endorsement-options.js';
import globalRules from '@/constants/global-rules.js';
import { useMainStore } from '@/store/index.js';
import bailoutMessage from '@/constants/bailoutMessage';
import {
deductibleForSelectedVehicle,
endorsementsForSelectedVehicle,
@ -144,10 +143,6 @@ export default {
},
repairWaivedForSelectedVehicle() {
return repairWaivedForSelectedVehicle(this.selectedPolicyVehicle);
},
selectedVehicle() {
const vehicle = this.mainStore.lookupVehicleByVin(this.selectedVehicleVin);
return vehicle;
}
},
watch: {
@ -156,15 +151,12 @@ export default {
if (value === vehicleSelectionOptions.VEHICLE_NOT_LISTED) {
// clear previously selected vehicle and image
this.mainStore.resetVehicleState();
} else {
// get vehicle details from selected VIN
const vehicle = await this.lookupVehicleByVin(value);
return;
}
// handle error in case vehicle info doesn't come back for selected VIN
if (vehicle?.error === true) {
this.mainStore.resetVehicleState();
return;
}
// get vehicle details from selected VIN
try {
const vehicle = await this.lookupVehicleByVin(value);
if (!vehicle?.data.canSafeliteService) {
this.displayNoServiceAlert = true;
return;
@ -177,6 +169,8 @@ export default {
vin: value
});
}
} catch (e) {
this.mainStore.resetVehicleState();
}
}
},
@ -196,33 +190,16 @@ export default {
);
},
async forwardButtonAction() {
if (this.selectedVehicleVin !== vehicleSelectionOptions.VEHICLE_NOT_LISTED) {
if (this.selectedVehicleVin === vehicleSelectionOptions.VEHICLE_NOT_LISTED) {
useMainStore().updateCoverageType(coverageType.NONE);
useMainStore().updateCoverageStatus(coverageStatuses.NO_COVERAGE);
this.navigateForward();
return;
}
const vehicle = this.policyVehicles.find((pv) => pv.vin === this.selectedVehicleVin);
try {
const vehicleLookupResponse = await this.lookupVehicleByVin(this.selectedVehicleVin);
const vehicle = this.policyVehicles.find((pv) => pv.vin === this.selectedVehicleVin);
if (vehicleLookupResponse.error) {
if (vehicleLookupResponse.status === 404) {
this.mainStore.resetVehicleState();
useMainStore().updateVehicle({
policyVehicleId: vehicle.id,
carId: '0',
category: '',
year: vehicle.vehicleYear || '',
make: vehicle.vehicleMake || '',
model: vehicle.vehicleModel || '',
style: vehicle.vehicleStyle || '',
vin: vehicle.vin
});
this.policyVinFound = false;
return this.navigateForward();
}
this.mainStore.setBailout(bailoutMessage.vehicleVinLookupError(
vehicle.vin,
vehicleLookupResponse.data
));
return this.navigateForward();
}
useMainStore().updateVehicle({
...vehicleLookupResponse.data,
@ -235,21 +212,30 @@ export default {
repairWaived: this.repairWaivedForSelectedVehicle,
endorsements: this.endorsementsForSelectedVehicle
});
} else {
useMainStore().updateCoverageType(coverageType.NONE);
useMainStore().updateCoverageStatus(coverageStatuses.NO_COVERAGE);
this.navigateForward();
} catch (e) {
if (e.isAxiosError && e.status === 404) {
this.mainStore.resetVehicleState();
useMainStore().updateVehicle({
policyVehicleId: vehicle.id,
carId: '0',
category: '',
year: vehicle.vehicleYear || '',
make: vehicle.vehicleMake || '',
model: vehicle.vehicleModel || '',
style: vehicle.vehicleStyle || '',
vin: vehicle.vin
});
this.policyVinFound = false;
this.navigateForward();
return;
}
throw e;
}
return this.navigateForward();
},
navigateForward() {
if (this.mainStore.isBailout) {
this.$router.navigate(
this.navigationScenarios.CLICKED_FORWARD_WITH_BAILOUT,
this.$route,
{},
{}
);
} else if (this.selectedVehicleVin === vehicleSelectionOptions.VEHICLE_NOT_LISTED) {
if (this.selectedVehicleVin === vehicleSelectionOptions.VEHICLE_NOT_LISTED) {
this.$router.navigate(
this.navigationScenarios.CLICKED_FORWARD_NON_LISTED_VEHICLE,
this.$route,
@ -281,15 +267,7 @@ export default {
}
},
async lookupVehicleByVin(vin) {
try {
return await useMainStore().lookupVehicleByVin(vin);
} catch (responseError) {
return {
error: true,
status: responseError.status,
data: responseError.data
};
}
return useMainStore().lookupVehicleByVin(vin);
},
async addAnotherVehicle() {
this.selectedVehicleVin = vehicleSelectionOptions.VEHICLE_NOT_LISTED;

View file

@ -20,7 +20,8 @@ jest.mock('@/helpers/cms-content-helper', () => ({
function setupMocks(mockApiResponses) {
const mountOptions = getMountOptions({
router: {
navigate: jest.fn()
navigate: jest.fn(),
navigateBailout: jest.fn()
},
route: 'provider-preference'
});
@ -43,7 +44,7 @@ function setupMocks(mockApiResponses) {
}
describe('provider-preference.vue', () => {
test('Should navigate to tpa disabled route page when TPAOption selected and TPA Flow disabled', () => {
test('Should navigateBailout when TPAOption selected and TPA Flow disabled', () => {
// Arrange
const { wrapper } = setupMocks();
@ -52,7 +53,7 @@ describe('provider-preference.vue', () => {
wrapper.vm.findAnotherShopClicked();
// Test
expect(wrapper.vm.$router.navigate).toBeCalledWith(navigationScenarios.CLICKED_FORWARD_WITH_TPA_DISABLED, 'provider-preference');
expect(wrapper.vm.$router.navigateBailout).toBeCalled();
});
test('Should navigate to safelite flow when navigateWithTPARecalAnswer is called with SafeliteOption', () => {

View file

@ -186,9 +186,7 @@ export default {
this.scheduleWithTPA();
}
} else {
this.mainStore.setBailout(bailoutMessage.TPANotEnabled());
const scenario = this.navigationScenarios.CLICKED_FORWARD_WITH_TPA_DISABLED;
this.navigateForward(scenario);
this.$router.navigateBailout(bailoutMessage.TPANotEnabled());
}
},
openStateSteeringModal() {

View file

@ -53,7 +53,8 @@ const loaderStub = {
function getMountedComponent(mainInitialState = {}, initialData = {}, methodToRun = () => {}) {
const mountOptions = getMountOptions({
router: {
navigate: jest.fn()
navigate: jest.fn(),
navigateBailout: jest.fn()
},
route: {
query: { issPage: 'tpa-search' }
@ -787,7 +788,7 @@ describe('tpa-search.vue', () => {
});
describe('needHelpLinkClick', () => {
test('sets bailout and navigates', () => {
test('navigatesBailout', () => {
// Arrange
const { wrapper } = getMountedComponent();
@ -795,11 +796,7 @@ describe('tpa-search.vue', () => {
wrapper.vm.needHelpLinkClick();
// Assert
expect(wrapper.vm.mainStore.setBailout).toHaveBeenCalled();
expect(wrapper.vm.$router.navigate).toHaveBeenCalledWith(
navigationScenarios.CLICKED_NEED_HELP,
expect.anything()
);
expect(wrapper.vm.$router.navigateBailout).toBeCalled();
});
});

View file

@ -360,11 +360,7 @@ export default {
return getTpaProvidersResult?.data ?? [];
},
needHelpLinkClick() {
this.mainStore.setBailout(bailoutMessage.RequestCallback());
this.$router.navigate(
this.navigationScenarios.CLICKED_NEED_HELP,
this.$route
);
this.$router.navigateBailout(bailoutMessage.RequestCallback());
},
async searchClick() {
if (isNaN(this.tpaSearchValue)) {

View file

@ -315,20 +315,8 @@ export default {
};
},
async forwardButtonAction() {
try {
await submitWorkOrder({ submitType: submitType.TPA }).then(() => {
this.navigate(this.navigationScenarios.CLICKED_FORWARD);
}).catch((submitError) => {
this.mainStore.setBailout(bailoutMessage.saveSessionError(submitError.data));
this.navigate(
this.navigationScenarios.SAVE_SESSION_FAILED,
this.$route,
{ issPage: this.issPageValues.TPA_SUBMIT }
);
});
} catch (error) {
console.error(`error: response from submit work order:${error.message}`);
}
await submitWorkOrder({ submitType: submitType.TPA })
this.navigate(this.navigationScenarios.CLICKED_FORWARD);
},
navigate(scenario) {
this.$router.navigate(scenario, this.$route);

View file

@ -139,7 +139,7 @@ describe('vehicle-damage.vue', () => {
expect(vehicleQuestionsMixin.methods.getPartsOrQuestions).toHaveBeenCalledTimes(1);
expect(vehicleQuestionsMixin.methods.navigateForward).toHaveBeenCalledTimes(1);
});
test('Error in getPartsOrQuestions call => bailout true and navigate forward with CLICKED_FORWARD_WITH_BAILOUT scenario', async () => {
test('Error in getPartsOrQuestions call => error thrown in forwardButtonAction', async () => {
mountOptions.global.plugins = [createTestingPinia({
initialState: {
main: {
@ -154,23 +154,21 @@ describe('vehicle-damage.vue', () => {
}
}
})];
mountOptions.data = () => ({
hasBailedOut: true
});
mountOptions.data = () => ({});
const wrapper = mount(VehicleDamageComponent, mountOptions);
const siteFooterWrapper = wrapper.getComponent({ ref: 'siteFooter' });
const partsQuestionsErrorResponse = {
error: 'Error getting parts'
};
vehicleQuestionsMixin.methods.getPartsOrQuestions.mockImplementation(() => (
partsQuestionsErrorResponse
Promise.reject(partsQuestionsErrorResponse)
));
siteFooterWrapper.vm.$emit('forwardClicked');
await flushPromises();
expect(mockRouter.navigate).toHaveBeenCalledTimes(1);
expect(mockRouter.navigate)
.toHaveBeenCalledWith(navigationScenarios.CLICKED_FORWARD_WITH_BAILOUT, mockRoute);
expect.assertions(1);
try {
await wrapper.vm.forwardButtonAction();
} catch (e) {
expect(e).toBe(partsQuestionsErrorResponse);
}
});
});

View file

@ -189,8 +189,7 @@ export default {
this.getPassengerSideReplaceOptionsFromStore()
},
selectedWindshieldOptions: this.getWindshieldOptionsFromStore(),
selectedRearReplaceOptions: this.getRearReplaceOptionsFromStore(),
hasBailedOut: false
selectedRearReplaceOptions: this.getRearReplaceOptionsFromStore()
};
},
computed: {
@ -429,23 +428,12 @@ export default {
// If vin already exists or not replacing windshield, get parts/questions and navigate forward
const partsOrQuestionsResponse = await this.getPartsOrQuestions();
if (partsOrQuestionsResponse.error) {
this.mainStore.setBailout(bailoutMessage.PartsServiceError(partsOrQuestionsResponse.error.data));
window.console.error('Error on retrieving PartsOrQuestions');
this.hasBailedOut = true;
this.$router.navigate(
this.navigationScenarios.CLICKED_FORWARD_WITH_BAILOUT,
this.$route
);
}
// Comes from vehicleQuestionsMixin.navigateForward()
if (!this.hasBailedOut) {
await this.navigateForward(
partsOrQuestionsResponse.data.partsOrQuestions,
this
);
}
await this.navigateForward(
partsOrQuestionsResponse.data.partsOrQuestions,
this
);
} else {
this.$router.navigate(
this.navigationScenarios.CLICKED_FORWARD_WITHOUT_VIN,

View file

@ -113,21 +113,10 @@ export default {
break;
case vinLookupMethodSelections.NOVIN:
const partsOrQuestionsResponse = await this.getPartsOrQuestions();
if (partsOrQuestionsResponse.error) {
this.mainStore.setBailout(bailoutMessage.PartsServiceError(partsOrQuestionsResponse.error.data));
window.console.error('Error on retrieving PartsOrQuestions');
this.hasBailedOut = true;
this.$router.navigate(
this.navigationScenarios.CLICKED_FORWARD_WITH_BAILOUT,
this.$route
);
}
else {
await this.navigateForward(
partsOrQuestionsResponse.data.partsOrQuestions,
this
);
}
await this.navigateForward(
partsOrQuestionsResponse.data.partsOrQuestions,
this
);
break;
default:
break;

View file

@ -65,7 +65,6 @@ import BaseFormMixin from '@/mixins/base-form-mixin.js';
import { useMainStore } from '@/store';
import widgetFields from '@/constants/cms-widget-fields';
import bailoutMessage from '@/constants/bailoutMessage';
import navigationScenarios from '@/router/router-constants/navigation-scenarios';
export default {
name: 'vehicle-parts',
@ -215,8 +214,7 @@ export default {
});
},
requestCallbackBailout() {
this.mainStore.setBailout(bailoutMessage.RequestCallback());
this.$router.navigate(navigationScenarios.CLICKED_NEED_HELP_WITH_BAILOUT, this.$route);
this.$router.navigateBailout(bailoutMessage.RequestCallback());
}
}
};

View file

@ -163,16 +163,18 @@ export default {
}
},
selectedStyle(value) {
this.resetAlert();
this.mainStore.updateVehicleStyle(value);
this.mainStore.setVehicle(
this.selectedYear,
this.selectedMake,
this.selectedModel,
this.selectedStyle
).then((result) => {
this.displayNoServiceAlert = !result.data.canSafeliteService;
});
if (value) {
this.resetAlert();
this.mainStore.updateVehicleStyle(value);
this.mainStore.setVehicle(
this.selectedYear,
this.selectedMake,
this.selectedModel,
this.selectedStyle
).then((result) => {
this.displayNoServiceAlert = !result.data.canSafeliteService;
});
}
}
},
mounted() {
@ -206,77 +208,25 @@ export default {
},
navigateForward() {
this.mainStore.setVehicle().then(
() => {
if (this.mainStore.isBailout) {
this.$router.navigate(
this.navigationScenarios.CLICKED_FORWARD_WITH_BAILOUT,
this.$route
);
return;
}
this.mainStore.setVehicle().then(() => {
this.$router.navigate(
this.navigationScenarios.CLICKED_FORWARD,
this.$route
);
},
(error) => {
this.mainStore.setBailout(bailoutMessage.vehicleYMMSLookupError(this.mainStore.vehicle.year, this.mainStore.vehicle.make, this.mainStore.vehicle.model, this.mainStore.vehicle.style, error));
this.$router.navigate(
this.navigationScenarios.CLICKED_FORWARD_WITH_BAILOUT,
this.$route
);
}
);
},
async updateYearValues() {
return this.mainStore.getVehicleYears().then(
(response) => response,
(error) => {
this.mainStore.setBailout(bailoutMessage.vehicleYMMSLookupError(null, null, null, null, error));
this.$router.navigate(
this.navigationScenarios.CLICKED_FORWARD_WITH_BAILOUT,
this.$route
);
}
);
return this.mainStore.getVehicleYears();
},
async updateMakeValues() {
return this.mainStore.getVehicleMakes().then(
(response) => response,
(error) => {
this.mainStore.setBailout(bailoutMessage.vehicleYMMSLookupError(this.mainStore.vehicle.year, null, null, null, error));
this.$router.navigate(
this.navigationScenarios.CLICKED_FORWARD_WITH_BAILOUT,
this.$route
);
}
);
return this.mainStore.getVehicleMakes();
},
async updateModelValues() {
return this.mainStore.getVehicleModels().then(
(response) => response,
(error) => {
this.mainStore.setBailout(bailoutMessage.vehicleYMMSLookupError(this.mainStore.vehicle.year, this.mainStore.vehicle.make, null, null, error));
this.$router.navigate(
this.navigationScenarios.CLICKED_FORWARD_WITH_BAILOUT,
this.$route
);
}
);
return this.mainStore.getVehicleModels();
},
async updateStyleValues() {
return this.mainStore.getVehicleStyles().then(
(response) => response,
(error) => {
this.mainStore.setBailout(bailoutMessage.vehicleYMMSLookupError(this.mainStore.vehicle.year, this.mainStore.vehicle.make, this.mainStore.vehicle.model, null, error));
this.$router.navigate(
this.navigationScenarios.CLICKED_FORWARD_WITH_BAILOUT,
this.$route
);
}
);
return this.mainStore.getVehicleStyles();
},
resetAlert() {
this.displayNoServiceAlert = false;

View file

@ -148,7 +148,8 @@ const mockRoute = {
};
const mockRouter = {
navigate: jest.fn(),
navigateWithSpinner: jest.fn()
navigateWithSpinner: jest.fn(),
navigateBailout: jest.fn()
};
const maska = jest.fn();
jest.mock('@/helpers/damage-helper', () => ({
@ -553,45 +554,6 @@ describe('vin-lookup.vue', () => {
);
});
});
test(
'Error in getPartsOrQuestions call => bailout true and navigate forward with CLICKED_FORWARD_WITH_BAILOUT scenario',
async () => {
const user = userEvent.setup();
mountOptions.global.stubs.vinQuestion = false;
mountOptions.data = () => ({
vinWithNonMatchingCarId: false,
isCarIdDifferentFromTheStore: false,
vin: mockValidVin,
hasBailedOut: true
});
getPartsOrQuestions.mockResponse = partsOrQuestionsErrorMockResponse;
jest.spyOn(VinLookupComponent.methods, lookupVehicleByVin.methodName)
.mockResolvedValue(lookupVehicleByVin.mockResponse);
jest.spyOn(vehicleQuestionsMixin.methods, getPartsOrQuestions.methodName)
.mockResolvedValue(getPartsOrQuestions.mockResponse);
const { container } = render(VinLookupComponent, mountOptions);
const vinInput = container.querySelector(vinInputSelector);
await user.type(vinInput, mockValidVin);
const continueButton = container.querySelector(continueButtonQuerySelector);
await user.click(continueButton);
await flushPromises();
await waitFor(() => {
expect(mockRouter.navigate).toHaveBeenCalledTimes(1);
expect(mockRouter.navigate)
.toHaveBeenCalledWith(
navigationScenarios.CLICKED_FORWARD_WITH_BAILOUT,
mockRoute
);
});
}
);
});
});
});

View file

@ -112,8 +112,7 @@ export default {
vinWithNonMatchingCarId: vin?.length > 0 && !this.hasValidCarId(),
vin,
forwardButtonCarStyle: '',
vinPopulatedOnPageLoad: vin?.length > 0 && this.hasValidCarId(),
hasBailedOut: false
vinPopulatedOnPageLoad: vin?.length > 0 && this.hasValidCarId()
};
},
computed: {
@ -176,35 +175,37 @@ export default {
showIssLoadingModal(true);
if (this.needToLookupVehicle) {
const vehicleLookupResponse = await this.lookupVehicleByVin(this.vin);
try {
const vehicleLookupResponse = await this.lookupVehicleByVin(this.vin);
if (vehicleLookupResponse.error) {
this.activeVehicleLookupAlertType = vehicleLookupAlertTypes.NOT_FOUND;
this.mainStore.setBailout(bailoutMessage.vehicleNotFound(this.vin));
this.resetVehicleFromLookup();
// Temp solution to turn on 'disabled' style on the Continue button
// because the form itself actually passes its client-side validation.
// SSR-189 Scenario #4.
this.$refs.siteFooter.enableForwardAction();
showIssLoadingModal(false);
return;
}
if (!vehicleLookupResponse.data.canSafeliteService) {
this.activeVehicleLookupAlertType = vehicleLookupAlertTypes.NO_SERVICE;
this.resetVehicleFromLookup();
this.$refs.siteFooter.disableForwardButton();
showIssLoadingModal(false);
return;
}
// Add vin bcs the response from the service doesn't contain vin
this.vehicleFromLookup = Object.assign(
vehicleLookupResponse.data,
{
vin: this.vin
if (!vehicleLookupResponse.data.canSafeliteService) {
this.activeVehicleLookupAlertType = vehicleLookupAlertTypes.NO_SERVICE;
this.resetVehicleFromLookup();
this.$refs.siteFooter.disableForwardButton();
showIssLoadingModal(false);
return;
}
);
// Add vin bcs the response from the service doesn't contain vin
this.vehicleFromLookup = Object.assign(
vehicleLookupResponse.data,
{
vin: this.vin
}
);
} catch (e) {
if (e.status === 404) {
this.activeVehicleLookupAlertType = vehicleLookupAlertTypes.NOT_FOUND;
this.resetVehicleFromLookup();
// Temp solution to turn on 'disabled' style on the Continue button
// because the form itself actually passes its client-side validation.
// SSR-189 Scenario #4.
this.$refs.siteFooter.enableForwardAction();
showIssLoadingModal(false);
return;
}
throw e;
}
}
if (this.needToLookupVehicle && this.isCarIdDifferentFromTheStore) {
@ -259,34 +260,15 @@ export default {
}
const partsOrQuestionsResponse = await this.getPartsOrQuestions();
if (partsOrQuestionsResponse.error) {
this.mainStore.setBailout(bailoutMessage.PartsServiceError(partsOrQuestionsResponse.error.data));
window.console.error('Error on retrieving PartsOrQuestions');
this.hasBailedOut = true;
this.$router.navigate(
this.navigationScenarios.CLICKED_FORWARD_WITH_BAILOUT,
this.$route
);
}
// Comes from vehicleQuestionsMixin.navigateForward()
if (!this.hasBailedOut) {
await this.navigateForward(
partsOrQuestionsResponse.data.partsOrQuestions,
this
);
}
await this.navigateForward(
partsOrQuestionsResponse.data.partsOrQuestions,
this
);
},
async lookupVehicleByVin(vin) {
try {
return await this.mainStore.lookupVehicleByVin(vin);
} catch (responseError) {
return {
error: {
status: responseError.status
}
};
}
return this.mainStore.lookupVehicleByVin(vin);
},
resetActiveAlert() {
this.activeVehicleLookupAlertType = null;

View file

@ -72,7 +72,8 @@ function setupMocks({
const mockDataMountOptions = {
...mountOptionsMockData,
router: {
navigate: jest.fn()
navigate: jest.fn(),
navigateBailout: jest.fn()
}
};
@ -166,7 +167,7 @@ describe('navigation', () => {
const { wrapper } = setupMocks({});
wrapper.vm.mainStore.getDuplicateReferrals = jest.fn().mockImplementation(() => Promise.resolve({}));
wrapper.vm.mainStore.applicationUser.duplicateOrders = [{ test: 'a' }];
wrapper.vm.mainStore.validateZip = jest.fn().mockImplementation(() => Promise.reject());
wrapper.vm.mainStore.validateZip = jest.fn().mockImplementation(() => Promise.reject({ isAxiosError: false }));
// Act
await wrapper.vm.forwardButtonAction();
@ -316,10 +317,14 @@ describe('navigation', () => {
}));
// Act
await wrapper.vm.forwardButtonAction();
// Assert
expect(wrapper.vm.$router.navigate).toHaveBeenCalled();
expect.assertions(1);
try {
await wrapper.vm.forwardButtonAction();
} catch (e) {
expect(e).toMatch(error);
}
});
});
});

View file

@ -177,6 +177,7 @@ import { getPropertyCaseInsensitive } from '@/helpers/object-helper';
import { saveSession } from '@/helpers/order-helper';
import { getISSCookie } from '@/helpers/cookie-helper.js';
import bailoutMessage from '@/constants/bailoutMessage';
import showIssLoadingModal from '@/helpers/loading-modal-helper';
// define validation rules
defineRule(
@ -303,54 +304,46 @@ export default {
},
methods: {
async forwardButtonAction() {
try {
this.mainStore.updatePolicyData(this.welcomePageModel);
const promises = [];
promises.push(this.configureZip().then(async () => await this.mainStore.getBillToInfo()));
this.mainStore.updatePolicyData(this.welcomePageModel);
// Clear duplicate orders if navigating away from the welcome page after visiting duplicate check page.
if (this.mainStore.order.visitedDuplicateCheckPage) {
this.mainStore.clearDuplicateOrders();
}
// Skip duplicate check if loaded from cookie or already visited duplicate check page.
if (!this.mainStore.order.loadedFromCookie && !this.mainStore.order.visitedDuplicateCheckPage) {
promises.push(this.mainStore.getDuplicateReferrals());
}
promises.push(this.mainStore.getCoveragePolicyInfo());
await Promise.allSettled(promises);
} catch (e) {
console.error(e);
// TODO: Bailout?
} finally {
if (!this.displayInvalidZipAlert) {
await saveSession({ shouldAwaitSaveSessionQueue: true })
.catch((error) => {
this.mainStore.setBailout(bailoutMessage.saveSessionError(error.data));
})
.finally(() => this.navigateForward());
}
// We want to await this separately. It's quick and if this has an invalid zip we don't want to be waiting on the slower API calls
await this.configureZip();
if (this.displayInvalidZipAlert) {
showIssLoadingModal(false);
return;
}
// Clear duplicate orders if navigating away from the welcome page after visiting duplicate check page.
if (this.mainStore.order.visitedDuplicateCheckPage) {
this.mainStore.clearDuplicateOrders();
}
const promises = [
// Suppress error from API call we can try again later in the flow
this.mainStore.getBillToInfo()
];
// Skip duplicate check if loaded from cookie or already visited duplicate check page.
if (!this.mainStore.order.loadedFromCookie && !this.mainStore.order.visitedDuplicateCheckPage) {
promises.push(this.mainStore.getDuplicateReferrals());
}
promises.push(this.mainStore.getCoveragePolicyInfo());
await Promise.all(promises);
await saveSession({ shouldAwaitSaveSessionQueue: true, bailoutOnError: true })
this.navigateForward();
},
async configureZip() {
try {
this.displayInvalidZipAlert = false;
await this.mainStore.validateZip({ zip: this.welcomePageModel.policyZipCode });
return Promise.resolve();
} catch (e) {
if (e.isAxiosError) {
throw e;
}
this.displayInvalidZipAlert = true;
return Promise.reject(e);
}
},
navigateForward() {
if (this.mainStore.isBailout) {
this.$router.navigate(
this.navigationScenarios.SAVE_SESSION_FAILED,
this.$route,
{},
{ [routerParams.SKIP_SAVE_SESSION]: true }
);
} else if ((this.mainStore.applicationUser.duplicateOrders?.length > 0 ?? false)
if ((this.mainStore.applicationUser.duplicateOrders?.length > 0 ?? false)
&& !this.answeredContinueModal) {
this.$router.navigate(
this.navigationScenarios.CLICKED_FORWARD_WITH_DUPLICATES,
@ -445,12 +438,7 @@ export default {
.then((response) => {
this.answeredContinueModal = true;
if (response && !response.provider?.isSafeliteProvider) {
this.mainStore.setBailout(bailoutMessage.SafeliteNotTheProvider());
this.hasBailedOut = true;
this.$router.navigate(
this.navigationScenarios.CLICKED_FORWARD_WITH_BAILOUT,
this.$route
);
this.$router.navigateBailout(bailoutMessage.SafeliteNotTheProvider());
} else {
this.updateWelcomePageModel(response);
}

View file

@ -48,7 +48,7 @@ function getPageName(vm) {
// Vue Error Handling
vueApp.config.errorHandler = (err, vm, info) => {
const pageName = getPageName(vm);
global.$logger.logError(`Page Name - ${pageName} - ${info}: ${err.message}\n${err.stack}`);
global.$logger.logError(`[${pageName}] ${info}`, err);
if (applicationConfig.BAILOUT_ON_APPLICATION_ERROR) {
router.navigateBailout(bailoutMessage.applicationError(`[${pageName}] ${info}: ${err.message}\n${err.stack}`));
}
@ -56,7 +56,7 @@ vueApp.config.errorHandler = (err, vm, info) => {
// Vue Router Error Handling
router.onError((err) => {
global.$logger.logError(err.message, err.cause);
global.$logger.logError('Router Error:', err);
if (applicationConfig.BAILOUT_ON_ROUTER_ERROR) {
router.navigateBailout(bailoutMessage.routerError(`${err.message}\n${err.stack}`));
}

View file

@ -353,16 +353,7 @@ export default {
},
async getPartsOrQuestions() {
try {
return await useMainStore().getPartsOrQuestions();
} catch (responseError) {
return {
error: {
status: responseError.status,
data: responseError.data
}
};
}
return useMainStore().getPartsOrQuestions();
},
// Can't use `this` because navigateForward is also called from vin-pages-mixin

View file

@ -25,100 +25,95 @@ const routes = [
path: '/',
name: 'root',
async beforeEnter(to, from, next) {
try {
const issPageToUse = !to.query.issPage ? issPageValues.WELCOME_PAGE : to.query.issPage;
const fromQueryPage = from.query?.issPage;
const issPageToUse = !to.query.issPage ? issPageValues.WELCOME_PAGE : to.query.issPage;
const fromQueryPage = from.query?.issPage;
if ((issPageToUse === issPageValues.ACCESS_DENIED
if ((issPageToUse === issPageValues.ACCESS_DENIED
|| (issPageToUse !== issPageValues.ENTRY_PAGE && !useMainStore().issConfig.parentAccountNumber))
&& process.env.VUE_APP_CURRENT_ENVIRONMENT !== 'Localhost'
) {
return await GoToAccessIsDenied(next);
&& process.env.VUE_APP_CURRENT_ENVIRONMENT !== 'Localhost'
) {
return await GoToAccessIsDenied(next);
}
// Do not run these for the main entry page - as it is not part of the user flow.
if (issPageToUse !== issPageValues.ENTRY_PAGE) {
if (analyticsMixin.methods.noSession()) {
await analyticsMixin.methods.initSession();
} else {
updateSessionIdCookie();
}
// Do not run these for the main entry page - as it is not part of the user flow.
if (issPageToUse !== issPageValues.ENTRY_PAGE) {
if (analyticsMixin.methods.noSession()) {
await analyticsMixin.methods.initSession();
} else {
updateSessionIdCookie();
}
await runExperiments(issPageToUse); // fmg has this further down
}
await runExperiments(issPageToUse); // fmg has this further down
// Intercept all navigation if a submitted order exists in storage
if (useMainStore().hasSubmittedOrder()) {
if (to.query.issPage !== issPageValues.ENTRY_PAGE) {
return await GoToConfirmationPage(next, useMainStore().getSubmittedOrder());
}
}
// If the saved session has timed out, clear the session, execute 404 logic.
if (getISSCookie() !== null && !isSavedSessionStillActive()) {
// await baseMixin.methods.dispatchStoreAction(storeActions.RESET_STATE);
await GoToStartOn404(next);
}
// Process ISS cookie.
// Skip if Entry Page or Refreshing Welcome page
if (issPageToUse !== issPageValues.ENTRY_PAGE
&& !(issPageToUse === issPageValues.WELCOME_PAGE && fromQueryPage === undefined)) {
updateOrCreateISSCookie();
}
if (router.hasRoute(issPageToUse)) {
// Since our route is already in scope, we can grab the component and call the arePagePrerequisitesValid function.
let component = router.getRoutes().filter((x) => x.name === issPageToUse)[0].components;
// If the component hasn't been loaded fully, load it before we check prerequisites.
if (component.default.methods === undefined) {
component = await component.default();
}
// Intercept all navigation if a submitted order exists in storage
if (useMainStore().hasSubmittedOrder()) {
if (to.query.issPage !== issPageValues.ENTRY_PAGE) {
return await GoToConfirmationPage(next, useMainStore().getSubmittedOrder());
}
}
// If the saved session has timed out, clear the session, execute 404 logic.
if (getISSCookie() !== null && !isSavedSessionStillActive()) {
// await baseMixin.methods.dispatchStoreAction(storeActions.RESET_STATE);
if (!arePagePrerequisitesValid(component)) {
await GoToStartOn404(next);
}
// Process ISS cookie.
// Skip if Entry Page or Refreshing Welcome page
if (issPageToUse !== issPageValues.ENTRY_PAGE
&& !(issPageToUse === issPageValues.WELCOME_PAGE && fromQueryPage === undefined)) {
updateOrCreateISSCookie();
}
if (router.hasRoute(issPageToUse)) {
// Since our route is already in scope, we can grab the component and call the arePagePrerequisitesValid function.
let component = router.getRoutes().filter((x) => x.name === issPageToUse)[0].components;
// If the component hasn't been loaded fully, load it before we check prerequisites.
if (component.default.methods === undefined) {
component = await component.default();
}
if (!arePagePrerequisitesValid(component)) {
await GoToStartOn404(next);
}
return next({ name: issPageToUse, query: to.query, params: to.params });
}
const routeData = await GetRouteInfoFromPageName(issPageToUse);
if (routeData[0].name.toLowerCase() === 'error') {
throw new Error('Page not found!');
}
// Add our dynamic route.
router.addRoute({
path: routeData[0].path, // Always the same path, because we control it with query strings.
name: routeData[0].name,
component: routeData[0].component
});
// Call the next components arePagePrerequisitesValid method before load.
// If it returns false, use the 404 logic.
const nextComponent = await router
.getRoutes()
.filter((x) => x.name === routeData[0].name)[0]
.components.default();
if (!arePagePrerequisitesValid(nextComponent)) {
const tempMsgCopy = 'Pre Requisites failed, need to handle. Default is Welcome Page.';
const tempMsgHeadline = `${issPageToUse}: pre-req failed...`;
await GoToStartOn404(next, tempMsgCopy, tempMsgHeadline);
}
// Assign current query string parameters, as well as our issPage one.
next({
name: routeData[0].name,
query: Object.assign(to.query, { issPage: routeData[0].name }),
params: to.params
});
} catch (error) {
window.console.warn(error);
await GoToStartOn404(next);
return next({name: issPageToUse, query: to.query, params: to.params});
}
const routeData = await GetRouteInfoFromPageName(issPageToUse);
if (routeData[0].name.toLowerCase() === 'error') {
throw new Error('Page not found!');
}
// Add our dynamic route.
router.addRoute({
path: routeData[0].path, // Always the same path, because we control it with query strings.
name: routeData[0].name,
component: routeData[0].component
});
// Call the next components arePagePrerequisitesValid method before load.
// If it returns false, use the 404 logic.
const nextComponent = await router
.getRoutes()
.filter((x) => x.name === routeData[0].name)[0]
.components.default();
if (!arePagePrerequisitesValid(nextComponent)) {
const tempMsgCopy = 'Pre Requisites failed, need to handle. Default is Welcome Page.';
const tempMsgHeadline = `${issPageToUse}: pre-req failed...`;
await GoToStartOn404(next, tempMsgCopy, tempMsgHeadline);
}
// Assign current query string parameters, as well as our issPage one.
next({
name: routeData[0].name,
query: Object.assign(to.query, {issPage: routeData[0].name}),
params: to.params
});
return null;
}
}
@ -177,7 +172,7 @@ router.afterEach(async (to, from) => {
const skipSaveSession = !!router.options.history.state[routerParams.SKIP_SAVE_SESSION];
if (from.name !== undefined && !skipSaveSession && !store.hasSubmittedOrder()) {
await saveSession({});
await saveSession({ bailoutOnError: from.name === issPageValues.ENTRY_PAGE});
}
if (to.query.issPage !== issPageValues.ENTRY_PAGE) {
@ -350,17 +345,12 @@ router.navigateBailout = (bailoutData = null) => {
// Get navigation map depending on the scenario and the current 'page' you're on.
function getNavigationMap(scenario, currentRoute) {
const issPageValue = currentRoute.query.issPage;
try {
const matchedQueryValue = routingTable(useMainStore())
.filter((item) => item.issPageValue === issPageValue && item.maps.filter((map) => map.scenario === scenario).length > 0);
const matchedQueryValue = routingTable(useMainStore())
.filter((item) => item.issPageValue === issPageValue && item.maps.filter((map) => map.scenario === scenario).length > 0);
const maps = matchedQueryValue ? matchedQueryValue.map((m) => m.maps.filter((map) => map.scenario === scenario))[0] : undefined;
const maps = matchedQueryValue ? matchedQueryValue.map((m) => m.maps.filter((map) => map.scenario === scenario))[0] : undefined;
return maps ? maps.filter((x) => x.filter === true || x.filter === undefined)[0] : undefined;
} catch (e) {
window.console.error(e);
return undefined;
}
return maps ? maps.filter((x) => x.filter === true || x.filter === undefined)[0] : undefined;
}
async function GoToAccessIsDenied(next) {

View file

@ -12,7 +12,6 @@ const navigationScenarios = Object.freeze({
CLICKED_FORWARD_POLICY_UNVERIFIED: 'CLICKED_FORWARD_POLICY_UNVERIFIED',
CLICKED_FORWARD_POLICY_VERIFIED_NO_VEHICLES: 'CLICKED_FORWARD_POLICY_VERIFIED_NO_VEHICLES',
CLICKED_FORWARD_POLICY_VERIFIED_WITH_VEHICLES: 'CLICKED_FORWARD_POLICY_VERIFIED_WITH_VEHICLES',
SAVE_SESSION_FAILED: 'SAVE_SESSION_FAILED',
// Duplicate Check
CLICKED_FORWARD_LOADED_DUPLICATE_WITH_POLICY_VEHICLE: 'CLICKED_FORWARD_LOADED_DUPLICATE_WITH_POLICY_VEHICLE',
@ -70,11 +69,8 @@ const navigationScenarios = Object.freeze({
// Coverage Statement
CLICKED_BACK_WITH_REPAIR: 'CLICKED_BACK_WITH_REPAIR',
CLICKED_FORWARD_WITH_INVALID_STATE: 'CLICKED_FORWARD_WITH_INVALID_STATE',
PRICING_LOOKUP_ERROR: 'PRICING_LOOKUP_ERROR',
// TPA Search
CLICKED_NEED_HELP: 'CLICKED_NEED_HELP',
CLICKED_FORWARD_WITH_SAFELITE_SHOP: 'CLICKED_FORWARD_WITH_SAFELITE_SHOP',
CLICKED_FORWARD_WITH_NON_SAFELITE_SHOP: 'CLICKED_FORWARD_WITH_NON_SAFELITE_SHOP',
@ -88,7 +84,6 @@ const navigationScenarios = Object.freeze({
// Provider Preference
CLICKED_FORWARD_WITH_SAFELITE: 'CLICKED_FORWARD_WITH_SAFELITE',
CLICKED_FORWARD_WITH_TPA_ENABLED: 'CLICKED_FORWARD_WITH_TPA_ENABLED',
CLICKED_FORWARD_WITH_TPA_DISABLED: 'CLICKED_FORWARD_WITH_TPA_DISABLED',
CLICKED_FORWARD_WITH_POLICY_AND_VEHICLES: 'CLICKED_FORWARD_WITH_POLICY_AND_VEHICLES',
// Service Package
@ -112,8 +107,6 @@ const navigationScenarios = Object.freeze({
PAY_IN_ADVANCE_SUCCESS: 'PAY_IN_ADVANCE_SUCCESS',
// Bailout
CLICKED_FORWARD_WITH_BAILOUT: 'CLICKED_FORWARD_WITH_BAILOUT',
CLICKED_NEED_HELP_WITH_BAILOUT: 'CLICKED_NEED_HELP_WITH_BAILOUT',
BAILOUT: 'BAILOUT'
});

View file

@ -14,10 +14,6 @@ const routingTable = () => [
{
scenario: navigationScenarios.CLICKED_FORWARD,
destinationIssPageValue: issPageValues.POLICY_HOLDER_DETAILS
},
{
scenario: navigationScenarios.CLICKED_FORWARD_WITH_BAILOUT,
destinationIssPageValue: issPageValues.BAILOUT_PAGE
}
]
},
@ -55,10 +51,6 @@ const routingTable = () => [
{
scenario: navigationScenarios.CLICKED_FORWARD_WITHOUT_VIN,
destinationIssPageValue: issPageValues.VEHICLE_LOOKUP
},
{
scenario: navigationScenarios.CLICKED_FORWARD_WITH_BAILOUT,
destinationIssPageValue: issPageValues.BAILOUT_PAGE
}
]
},
@ -141,14 +133,6 @@ const routingTable = () => [
{
scenario: issPageValues.VEHICLE_LOOKUP,
destinationIssPageValue: issPageValues.VEHICLE_LOOKUP
},
{
scenario: issPageValues.BAILOUT_PAGE, // TODO is this a bug
destinationIssPageValue: issPageValues.BAILOUT_PAGE
},
{
scenario: navigationScenarios.CLICKED_FORWARD_WITH_BAILOUT,
destinationIssPageValue: issPageValues.BAILOUT_PAGE
}
]
},
@ -215,10 +199,6 @@ const routingTable = () => [
{
scenario: navigationScenarios.CLICKED_FORWARD_WITH_NO_MORE_QUESTIONS,
destinationIssPageValue: issPageValues.COVERAGE_STATEMENT
},
{
scenario: navigationScenarios.CLICKED_NEED_HELP_WITH_BAILOUT,
destinationIssPageValue: issPageValues.BAILOUT_PAGE
}
]
},
@ -256,10 +236,6 @@ const routingTable = () => [
{
scenario: navigationScenarios.CLICKED_FORWARD_WITH_NO_MORE_QUESTIONS,
destinationIssPageValue: issPageValues.COVERAGE_STATEMENT
},
{
scenario: navigationScenarios.CLICKED_NEED_HELP_WITH_BAILOUT,
destinationIssPageValue: issPageValues.BAILOUT_PAGE
}
]
},
@ -293,10 +269,6 @@ const routingTable = () => [
{
scenario: navigationScenarios.CLICKED_FORWARD_WITH_NO_MORE_QUESTIONS,
destinationIssPageValue: issPageValues.COVERAGE_STATEMENT
},
{
scenario: navigationScenarios.CLICKED_NEED_HELP_WITH_BAILOUT,
destinationIssPageValue: issPageValues.BAILOUT_PAGE
}
]
},
@ -455,14 +427,6 @@ const routingTable = () => [
{
scenario: navigationScenarios.CLICKED_FORWARD_POLICY_VERIFIED_WITH_VEHICLES,
destinationIssPageValue: issPageValues.POLICY_VEHICLES
},
{
scenario: navigationScenarios.CLICKED_FORWARD_WITH_BAILOUT,
destinationIssPageValue: issPageValues.BAILOUT_PAGE
},
{
scenario: navigationScenarios.SAVE_SESSION_FAILED,
destinationIssPageValue: issPageValues.BAILOUT_PAGE
}
]
},
@ -539,10 +503,6 @@ const routingTable = () => [
scenario: navigationScenarios.CLICKED_FORWARD_WITH_CAR_ID_NOT_FOUND,
destinationIssPageValue: issPageValues.VIN_LOOKUP
},
{
scenario: navigationScenarios.CLICKED_FORWARD_WITH_BAILOUT,
destinationIssPageValue: issPageValues.BAILOUT_PAGE
},
{
scenario: navigationScenarios.CLICKED_FORWARD_WITH_ENDORSEMENTS,
destinationIssPageValue: issPageValues.POLICY_ENDORSEMENTS
@ -591,18 +551,6 @@ const routingTable = () => [
{
scenario: navigationScenarios.CLICKED_FORWARD_WITH_SAFELITE,
destinationIssPageValue: issPageValues.SCHEDULE_PAGE
},
{
scenario: navigationScenarios.CLICKED_FORWARD_WITH_NON_SAFELITE_SHOP,
destinationIssPageValue: issPageValues.BAILOUT_PAGE
},
{
scenario: navigationScenarios.CLICKED_FORWARD_WITH_INVALID_STATE,
destinationIssPageValue: issPageValues.BAILOUT_PAGE
},
{
scenario: navigationScenarios.PRICING_LOOKUP_ERROR,
destinationIssPageValue: issPageValues.BAILOUT_PAGE
}
]
},
@ -620,10 +568,6 @@ const routingTable = () => [
{
scenario: navigationScenarios.CLICKED_FORWARD_WITH_TPA_ENABLED,
destinationIssPageValue: issPageValues.TPA_SEARCH
},
{
scenario: navigationScenarios.CLICKED_FORWARD_WITH_TPA_DISABLED,
destinationIssPageValue: issPageValues.BAILOUT_PAGE
}
]
},
@ -692,10 +636,6 @@ const routingTable = () => [
{
scenario: navigationScenarios.CLICKED_PAY_NOW,
destinationIssPageValue: issPageValues.PAYMENT_PAGE
},
{
scenario: navigationScenarios.SAVE_SESSION_FAILED,
destinationIssPageValue: issPageValues.BAILOUT_PAGE
}
]
},
@ -768,10 +708,6 @@ const routingTable = () => [
{
scenario: navigationScenarios.CLICKED_FORWARD,
destinationIssPageValue: issPageValues.TPA_CONFIRMATION
},
{
scenario: navigationScenarios.SAVE_SESSION_FAILED,
destinationIssPageValue: issPageValues.BAILOUT_PAGE
}
]
},
@ -798,10 +734,6 @@ const routingTable = () => [
{
scenario: navigationScenarios.CLICKED_FORWARD_WITH_NON_SAFELITE_SHOP,
destinationIssPageValue: issPageValues.TPA_SUBMIT
},
{
scenario: navigationScenarios.CLICKED_NEED_HELP,
destinationIssPageValue: issPageValues.BAILOUT_PAGE
}
]
},

View file

@ -4,6 +4,8 @@ import issPageValues from '@/router/router-constants/issPage-values';
import { createApp } from 'vue';
import { createPinia } from 'pinia';
import App from '@/App.vue';
import bailoutMessage from '@/constants/bailoutMessage';
import { useMainStore } from '@/store';
describe('Router', () => {
beforeAll(() => {
@ -37,18 +39,15 @@ describe('Router', () => {
expect(router.push.mock.calls[0][0].state).toBe(parameters);
});
it('Should route from CAPABILITY_QUESTIONS to BAILOUT_PAGE on CLICKED_NEED_HELP_WITH_BAILOUT', () => {
const scenario = navigationScenarios.CLICKED_NEED_HELP_WITH_BAILOUT;
const currentRoute = { query: { issPage: issPageValues.CAPABILITY_QUESTIONS } };
it('Should set bailout and navigate to bailout page when calling navigateBailout', () => {
// Arrange
router.push = jest.fn();
// Act
router.navigate(scenario, currentRoute);
router.navigateBailout(bailoutMessage.unknown({}));
// Assert
expect(router.push).toHaveBeenCalled();
expect(router.push.mock.calls[0][0].query.issPage).toBe(issPageValues.BAILOUT_PAGE);
expect(useMainStore().isBailout).toBeTruthy();
});
});

View file

@ -1,7 +1,6 @@
import { defineStore } from 'pinia';
import applicationConfig from '@/constants/application-config';
import bailoutCode from '@/constants/bailoutCode';
import bailoutMessage from '@/constants/bailoutMessage';
import coverageStatuses from '@/constants/coverage-statuses';
import coverageType from '@/constants/coverage-type';
import damageLocationsSelected from '@/constants/damage-locations-selected';
@ -22,14 +21,11 @@ import {
noCoverageForSelectedVehicle,
repairWaivedForSelectedVehicle
} from '@/helpers/policy-vehicle-helper';
import {
buildURLSearchParams,
getPartNumbersListForQueryString,
getTaxLineItemQueryString
} from '@/helpers/querystring-helper';
import { buildURLSearchParams, getPartNumbersListForQueryString } from '@/helpers/querystring-helper';
import { getTopLevelGlassPartsWithRecal } from '@/helpers/recal-helper';
import { getDateForSavedSessionTimeout } from '@/helpers/session-helper';
import issPageValues from '@/router/router-constants/issPage-values';
import CoverageStatuses from '@/constants/coverage-statuses';
const storeId = 'main';
@ -533,20 +529,15 @@ export const useMainStore = defineStore({
payload: {}
});
},
getIsVinbyAddressPermissible() {
async getIsVinbyAddressPermissible() {
try {
const response = globalMethods.callHttpClient({
return globalMethods.callHttpClient({
method: endpoints.IsVinbyAddressPermissible.method,
endpoint: `${endpoints.IsVinbyAddressPermissible.url}?state=${this.order.customer.address.state}`,
payload: {}
});
return response;
} catch (responseError) {
return {
error: {
status: responseError.status
}
};
});
} catch (e) {
return false;
}
},
async getCoveragePolicyInfo() {
@ -555,7 +546,7 @@ export const useMainStore = defineStore({
if (!issConfig.isCoverageEnabled || applicationUser.coverageLookupAttempts > 10) {
this.updateCoverageType(coverageType.NONE);
return Promise.resolve();
return;
}
this.applicationUser.coverageAttempts += 1;
@ -571,7 +562,8 @@ export const useMainStore = defineStore({
dateOfLoss: policy.dateOfLoss,
zipCode: policy.policyZipCode,
referralCorrelationId: order.referralCorrelationId
}
},
bailoutOnError: false
});
const responsePolicy = response?.data?.policies?.[0];
@ -600,10 +592,8 @@ export const useMainStore = defineStore({
} else {
this.updateCoverageType(coverageType.NONE);
}
return Promise.resolve();
} catch (e) {
this.updateCoverageType(coverageType.NONE);
return Promise.reject(e);
}
},
clearDuplicateOrders() {
@ -621,82 +611,81 @@ export const useMainStore = defineStore({
updateIsItacOptimized(isItacOptimized) {
this.order.insuranceCoverage.isItacOptimized = isItacOptimized || false;
},
registerClaim() {
async registerClaim() {
const nonNumberCharRegex = /[^0-9]/g;
const { order, isITAC } = this;
return new Promise((resolve, reject) => {
globalMethods.callHttpClient({
const { isITAC } = this;
try {
const response = await globalMethods.callHttpClient({
method: endpoints.RegisterClaim.method,
endpoint: endpoints.RegisterClaim.url,
payload:
{
referralCorrelationId: this.order.referralCorrelationId,
accountNumber: this.order.parentAccountNumber?.toString() ?? '',
policyData: this.order.policy.policyData,
isItac: isITAC,
insured: {
firstName: this.order.customer.firstName,
lastName: this.order.customer.lastName,
address: {
addressLine1: this.order.customer.address.streetAddress,
addressLine2: this.order.customer.address.streetAddress2,
city: this.order.customer.address.city,
state: this.order.customer.address.state,
zipCode: this.order.customer.address.zipCode,
country: 'US' // TODO set from store
{
referralCorrelationId: this.order.referralCorrelationId,
accountNumber: this.order.parentAccountNumber?.toString() ?? '',
policyData: this.order.policy.policyData,
isItac: isITAC,
insured: {
firstName: this.order.customer.firstName,
lastName: this.order.customer.lastName,
address: {
addressLine1: this.order.customer.address.streetAddress,
addressLine2: this.order.customer.address.streetAddress2,
city: this.order.customer.address.city,
state: this.order.customer.address.state,
zipCode: this.order.customer.address.zipCode,
country: 'US' // TODO set from store
},
homePhone: {
number: this.contactInfo.homePhone?.replaceAll(nonNumberCharRegex, '') ?? ''
}
},
homePhone: {
number: this.contactInfo.homePhone?.replaceAll(nonNumberCharRegex, '') ?? ''
driver: {
firstName: this.order.customer.firstName,
lastName: this.order.customer.lastName
},
caller: {
homePhone: {}
},
policyInfo: {
policyNumber: this.order.policy.policyNumber,
safelitePolicy: {
policies: []
},
actualDeductible: this.currentDeductible.toString() ?? ''
},
lossInfo: {
dateOfLoss: this.order.policy.dateOfLoss,
location: {
city: this.order.policy.damageCity,
state: this.order.policy.damageState,
country: 'US' // TODO set from store
},
vehicle: {
id: this.order.vehicle.policyVehicleId?.toString() ?? '',
year: this.order.vehicle.year?.toString() ?? '',
make: this.order.vehicle.make,
model: this.order.vehicle.model,
vin: this.order.vehicle.vin
},
cause: this.order.policy.damageCause,
damageDescription: this.order.policy.damageCause
}
},
driver: {
firstName: this.order.customer.firstName,
lastName: this.order.customer.lastName
},
caller: {
homePhone: {}
},
policyInfo: {
policyNumber: this.order.policy.policyNumber,
safelitePolicy: {
policies: []
},
actualDeductible: this.currentDeductible.toString() ?? ''
},
lossInfo: {
dateOfLoss: this.order.policy.dateOfLoss,
location: {
city: this.order.policy.damageCity,
state: this.order.policy.damageState,
country: 'US' // TODO set from store
},
vehicle: {
id: this.order.vehicle.policyVehicleId?.toString() ?? '',
year: this.order.vehicle.year?.toString() ?? '',
make: this.order.vehicle.make,
model: this.order.vehicle.model,
vin: this.order.vehicle.vin
},
cause: this.order.policy.damageCause,
damageDescription: this.order.policy.damageCause
}
}
}).then((response) => {
this.order.insuranceCoverage.claimNumber = response.data.claimNumber;
if (response.data.isSuccess) {
this.updateCoverageStatus(coverageStatuses.VERIFIED);
} else {
this.updateCoverageStatus(coverageStatuses.NO_COVERAGE);
}
return resolve(response);
}, (error) => {
this.updateCoverageStatus(coverageStatuses.NO_COVERAGE);
this.order.insuranceCoverage.claimNumber = null;
return reject(error);
bailoutOnError: false
});
});
this.order.insuranceCoverage.claimNumber = response.data.claimNumber;
if (response.data.isSuccess) {
this.updateCoverageStatus(coverageStatuses.VERIFIED);
} else {
this.updateCoverageStatus(coverageStatuses.NO_COVERAGE);
}
} catch (e) {
this.updateCoverageStatus(coverageStatuses.NO_COVERAGE);
this.order.insuranceCoverage.claimNumber = null;
}
},
getFinalDeductible() {
async getFinalDeductible() {
const endorsementAnswersForPayload = [];
const endorsementAnswers = this.order.policy.endorsementQuestionAnswers;
if (endorsementAnswers) {
@ -712,9 +701,9 @@ export const useMainStore = defineStore({
glassInformation?.forEach((glassPiece) => {
manualGlassNamesArray.push(glassPiece?.glassLocation?.toUpperCase());
});
return new Promise((resolve, reject) => {
globalMethods.callHttpClient({
try {
const r = await globalMethods.callHttpClient({
method: endpoints.FinalDeductible.method,
endpoint: endpoints.FinalDeductible.url,
payload: {
@ -736,16 +725,18 @@ export const useMainStore = defineStore({
vehicleVin: this.order.vehicle.vin,
policyData: this.order.policy.policyData,
isItac: this.isITAC
}
}).then((r) => {
this.order.policy.policyData = r.data.policyData;
this.updateDeductible(r.data);
return resolve(r);
}).catch((error) => reject(error));
});
},
bailoutOnError: false
});
this.order.policy.policyData = r.data.policyData;
this.updateDeductible(r.data);
return r;
} catch (e) {
this.updateCoverageStatus(CoverageStatuses.PENDING);
}
},
getDuplicateReferrals() {
async getDuplicateReferrals() {
const params = new URLSearchParams({
parentAccountNumber: this.order.parentAccountNumber,
customerPhoneNumber: this.order.contactInfo.servicePhone,
@ -754,18 +745,16 @@ export const useMainStore = defineStore({
dateOfLoss: this.order.policy.dateOfLoss
});
return new Promise((resolve, reject) => {
globalMethods.callHttpClient({
try {
const duplicates = await globalMethods.callHttpClient({
method: endpoints.DuplicateSearch.method,
endpoint: `${endpoints.DuplicateSearch.url}?${params.toString()}`
}).then((r) => {
this.applicationUser.duplicateOrders = r.data ?? [];
return resolve(r.data);
}).catch((error) => {
this.applicationUser.duplicateOrders = [];
return reject(error);
endpoint: `${endpoints.DuplicateSearch.url}?${params.toString()}`,
bailoutOnError: false
});
});
this.applicationUser.duplicateOrders = duplicates.data ?? [];
} catch (e) {
this.applicationUser.duplicateOrders = [];
}
},
async lookupVinByPlate(licensePlate, licenseState) {
try {
@ -1219,9 +1208,6 @@ export const useMainStore = defineStore({
IsOEMRequest: this.hasOemEndorsement
}
}
}).catch((error) => {
console.error(error);
throw error;
});
const { lineItems, serverData, isItac, primaryBillToNumber, partsWerePriced, isItacOptimized } = response.data;
@ -1361,7 +1347,8 @@ export const useMainStore = defineStore({
endpoint: endpoints.LookupVehicleByVin.url,
payload: {
vin
}
},
bailoutOnError: false
});
},
@ -1393,7 +1380,7 @@ export const useMainStore = defineStore({
this.applicationUser.crmCustomerId = response.crmCustomerId.toString();
},
saveSession({ submitAfterSave, createWorkOrderNumberForPIA }) {
saveSession({ submitAfterSave, createWorkOrderNumberForPIA, bailoutOnError }) {
const { vehicle, damage, policy, customer, contactInfo, payment,
lineItems, serviceLocation, schedule, insuranceCoverage } = this.order;
@ -1545,7 +1532,7 @@ export const useMainStore = defineStore({
method: endpoints.SaveSession.method,
endpoint: endpoints.SaveSession.url,
payload,
bailoutOnError: false
bailoutOnError
}).then((response) => {
if (loadedFromDupeCheck) {
this.order.loadedSessionClearedPreviousData = true;
@ -2462,6 +2449,7 @@ export const useMainStore = defineStore({
populateInitialState(forceReset) {
if (!sessionStorage.getItem(storeId) || forceReset) {
this.$state = getDefaultState();
this.resetSubmittedOrder();
}
},
@ -2700,34 +2688,26 @@ export const useMainStore = defineStore({
async getBillToInfo(componentProviderNumber = null) {
const { order, issConfig } = this;
try {
const params = new URLSearchParams({
parentAccountNumber: order.parentAccountNumber.toString(),
providerNumber: componentProviderNumber || this.providerNumber,
typeOfClaim: 'GLASS ONLY',
lineOfBusiness: 'PERSONAL',
isItac: this.isITAC
});
const params = new URLSearchParams({
parentAccountNumber: order.parentAccountNumber.toString(),
providerNumber: componentProviderNumber || this.providerNumber,
typeOfClaim: 'GLASS ONLY',
lineOfBusiness: 'PERSONAL',
isItac: this.isITAC
});
const response = await globalMethods.callHttpClient({
method: endpoints.GetBillToInfo.method,
endpoint: `${endpoints.GetBillToInfo.url}?${params.toString()}`
});
const response = await globalMethods.callHttpClient({
method: endpoints.GetBillToInfo.method,
endpoint: `${endpoints.GetBillToInfo.url}?${params.toString()}`,
bailoutOnError: false
});
const billToInfo = response.data;
if (billToInfo != null) {
issConfig.billToAccountNumber = billToInfo.toString();
return Promise.resolve();
}
return Promise.reject(new Error('Invalid billToInfo'));
} catch (e) {
return Promise.reject(e);
}
const billToInfo = response.data;
issConfig.billToAccountNumber = billToInfo.toString();
},
async validateClientTag(clientTag) {
return await globalMethods.callHttpClient({
return globalMethods.callHttpClient({
method: endpoints.ValidateClientTag.method,
endpoint: `${endpoints.ValidateClientTag.url}/${clientTag}`
});

View file

@ -459,9 +459,9 @@ describe('Store', () => {
expect(store.order.insuranceCoverage.claimNumber).not.toBeNull();
});
it('Call to client returns exception, resulting in object with error property being returned', async () => {
it('Call to client returns exception, and no error is returned from registerClaim method', async () => {
// Arrange
expect.assertions(4);
expect.assertions(3);
const error = 'register claim error';
globalMethods.callHttpClient = jest.fn().mockReturnValue(Promise.reject(error));
store.order.insuranceCoverage.coverageStatus = coverageStatuses.PENDING;
@ -1494,8 +1494,8 @@ describe('Store', () => {
// Assert
expect(globalMethods.callHttpClient).toHaveBeenCalled();
});
it('api call throws exception => insuranceCoverage.coverageType is NONE', async () => {
expect.assertions(3);
it('api call throws exception => no error is thrown from getCoveragePolicyInfo and insuranceCoverage.coverageType is NONE', async () => {
expect.assertions(2);
const error = 'get coverage policy info error';
store.issConfig.isCoverageEnabled = true;
store.applicationUser.coverageLookupAttempts = 0;
@ -1567,9 +1567,9 @@ describe('Store', () => {
expect(globalMethods.callHttpClient).toHaveBeenCalled();
expect(store.applicationUser.duplicateOrders).toEqual(expected);
});
it('Call to client returns exception => object with error property returned and duplicateReferrals set to []', async () => {
it('Call to client returns exception => object with error property returned and duplicateReferrals set to [] and no error is returned from getDuplicateReferrals', async () => {
// Arrange
expect.assertions(3);
expect.assertions(2);
const error = 'get duplicate referrals error';
globalMethods.callHttpClient = jest.fn().mockReturnValue(Promise.reject(error));
@ -1807,7 +1807,8 @@ describe('Store', () => {
vehicleVin,
policyData,
isItac: store.isITAC
})
}),
bailoutOnError: false
}));
});
it('only "Yes" endorsement answers are added to payload', () => {
@ -1912,14 +1913,15 @@ describe('Store', () => {
vehicleVin,
policyData,
isItac: store.isITAC
})
}),
bailoutOnError: false
}));
});
});
describe('unsuccessful api call', () => {
it('api call throws exception', async () => {
it('api call throws exception. no error from getFinalDeductible', async () => {
// Arrange
expect.assertions(2);
expect.assertions(1);
const error = 'final deductible error';
globalMethods.callHttpClient = jest.fn().mockReturnValue(Promise.reject(error));
@ -2078,8 +2080,8 @@ describe('Store', () => {
expect(result.data.shopProviders[1]).toBe(provider2);
});
});
it('api call throws exception => coverageType none', async () => {
expect.assertions(3);
it('api call throws exception => coverageType none and no error from getCoveragePolicyInfo', async () => {
expect.assertions(2);
const error = 'get coverage policy info error';
store.issConfig.isCoverageEnabled = true;