Merge pull request #606 from Safelite/feature/digital/SSR-1049

SSR-1049 Heavy Vehicle bailout
This commit is contained in:
Josh Dassinger 2024-04-08 08:16:04 -05:00 committed by GitHub
commit 1ab14d7413
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
17 changed files with 77 additions and 26 deletions

View file

@ -7,7 +7,8 @@ const bailoutCode = Object.freeze({
DoNotSeeMyShop: 5, DoNotSeeMyShop: 5,
PricingResponseError: 6, PricingResponseError: 6,
TPANotEnabled: 7, TPANotEnabled: 7,
RequestCallback: 8 RequestCallback: 8,
HeavyTruckVehicle: 9
}); });
export default bailoutCode; export default bailoutCode;

View file

@ -48,6 +48,10 @@ const bailoutMessage = Object.freeze({
RequestCallback: () => ({ RequestCallback: () => ({
code: bailoutCode.RequestCallback, code: bailoutCode.RequestCallback,
message: 'User selected option to receive callback from Safelite' message: 'User selected option to receive callback from Safelite'
}),
HeavyTruckVehicle: (carId) => ({
code: bailoutCode.HeavyTruckVehicle,
message: `User selected a heavy truck vehicle. Car ID: ${carId} `
}) })
}); });

View file

@ -135,10 +135,6 @@ import { formatAmountInDollars } from '@/helpers/text-helper.js';
const SAFELITE_PROVIDER = 'Safelite'; const SAFELITE_PROVIDER = 'Safelite';
function setBailout(currentRoute, message) {
useMainStore().setBailout(currentRoute, message);
}
export default { export default {
name: 'coverage-statement', name: 'coverage-statement',
components: { components: {
@ -186,7 +182,7 @@ export default {
await useMainStore().getFinalDeductible(); await useMainStore().getFinalDeductible();
pricingResults = await useMainStore().getPriceOrderItems(availableLineItems) pricingResults = await useMainStore().getPriceOrderItems(availableLineItems)
.catch((err) => { .catch((err) => {
setBailout(to, bailoutMessage.pricingResponseError( useMainStore().setBailout(bailoutMessage.pricingResponseError(
availableLineItems.map((li) => li.partNumber), availableLineItems.map((li) => li.partNumber),
{ code: err.code, message: err.message, data: err.data } { code: err.code, message: err.message, data: err.data }
)); ));
@ -397,17 +393,14 @@ export default {
useMainStore().updateSupportingItems(this.supportingItems); useMainStore().updateSupportingItems(this.supportingItems);
this.navigateWithScenario(navigationScenarios.CLICKED_FORWARD_WITH_SAFELITE); this.navigateWithScenario(navigationScenarios.CLICKED_FORWARD_WITH_SAFELITE);
} else { } else {
this.setBailoutWithMessage(bailoutMessage.RequestCallback()); useMainStore().setBailout(bailoutMessage.RequestCallback());
this.navigateWithScenario(navigationScenarios.CLICKED_FORWARD_WITH_NON_SAFELITE_SHOP); this.navigateWithScenario(navigationScenarios.CLICKED_FORWARD_WITH_NON_SAFELITE_SHOP);
} }
} else { } else {
this.setBailoutWithMessage(bailoutMessage.coverageStatementInvalidState()); useMainStore().setBailout(bailoutMessage.coverageStatementInvalidState());
this.navigateWithScenario(navigationScenarios.CLICKED_FORWARD_WITH_INVALID_STATE); this.navigateWithScenario(navigationScenarios.CLICKED_FORWARD_WITH_INVALID_STATE);
} }
}, },
setBailoutWithMessage(message) {
setBailout(this.$router.currentRoute, message);
},
navigateWithScenario(scenario) { navigateWithScenario(scenario) {
this.$router.navigate(scenario, this.$route); this.$router.navigate(scenario, this.$route);
}, },

View file

@ -123,7 +123,6 @@ export default {
const pricedVaps = await useMainStore().getPriceOrderItems(unpricedVaps) const pricedVaps = await useMainStore().getPriceOrderItems(unpricedVaps)
.catch((err) => { .catch((err) => {
useMainStore().setBailout( useMainStore().setBailout(
to,
bailoutMessage.pricingResponseError( bailoutMessage.pricingResponseError(
unpricedVaps.map((li) => li.partNumber), unpricedVaps.map((li) => li.partNumber),
{ code: err.code, message: err.message, data: err.data } { code: err.code, message: err.message, data: err.data }

View file

@ -274,7 +274,7 @@ describe('policy-vehicles.vue', () => {
// Assert // Assert
// eslint-disable-next-line max-len // eslint-disable-next-line max-len
expect(wrapper.vm.mainStore.setBailout).toHaveBeenCalledWith(wrapper.vm.$router.currentRoute, bailoutMessage.vehicleLookupError(vin, lookupReturnValue.data)); expect(wrapper.vm.mainStore.setBailout).toHaveBeenCalledWith(bailoutMessage.vehicleLookupError(vin, lookupReturnValue.data));
expect(wrapper.vm.$router.navigate).toHaveBeenCalledWith( expect(wrapper.vm.$router.navigate).toHaveBeenCalledWith(
navigationScenarios.CLICKED_FORWARD_WITH_BAILOUT, navigationScenarios.CLICKED_FORWARD_WITH_BAILOUT,
undefined, undefined,

View file

@ -195,7 +195,7 @@ export default {
return this.navigateForward(); return this.navigateForward();
} }
this.mainStore.setBailout(this.$router.currentRoute, bailoutMessage.vehicleLookupError(vehicle.vin, vehicleLookupResponse.data)); this.mainStore.setBailout(bailoutMessage.vehicleLookupError(vehicle.vin, vehicleLookupResponse.data));
return this.navigateForward(); return this.navigateForward();
} }

View file

@ -196,7 +196,7 @@ export default {
} }
scenario = this.navigationScenarios.CLICKED_FORWARD_WITH_TPA_ENABLED; scenario = this.navigationScenarios.CLICKED_FORWARD_WITH_TPA_ENABLED;
} else { } else {
this.mainStore.setBailout(this.$router.currentRoute, bailoutMessage.TPANotEnabled()); this.mainStore.setBailout(bailoutMessage.TPANotEnabled());
scenario = this.navigationScenarios.CLICKED_FORWARD_WITH_TPA_DISABLED; scenario = this.navigationScenarios.CLICKED_FORWARD_WITH_TPA_DISABLED;
} }
break; break;

View file

@ -125,7 +125,6 @@ export default {
const pricingResults = await store.getPriceOrderItems(availableLineItems) const pricingResults = await store.getPriceOrderItems(availableLineItems)
.catch((err) => { .catch((err) => {
useMainStore().setBailout( useMainStore().setBailout(
to,
bailoutMessage.pricingResponseError( bailoutMessage.pricingResponseError(
availableLineItems.map((li) => li.partNumber), availableLineItems.map((li) => li.partNumber),
{ code: err.code, message: err.message, data: err.data } { code: err.code, message: err.message, data: err.data }

View file

@ -361,10 +361,7 @@ describe('TPAConfirmation.vue', () => {
await contactCarrierText.trigger('click'); await contactCarrierText.trigger('click');
// Assert // Assert
expect(wrapper.vm.mainStore.setBailout).toHaveBeenCalledWith( expect(wrapper.vm.mainStore.setBailout).toHaveBeenCalledWith(bailoutMessage.RequestCallback);
wrapper.vm.$router.currentRoute,
bailoutMessage.RequestCallback
);
}); });
}); });
describe('Navigation', () => { describe('Navigation', () => {

View file

@ -203,7 +203,7 @@ export default {
} }
}, },
setBailoutInfo() { setBailoutInfo() {
this.mainStore.setBailout(this.$router.currentRoute, bailoutMessage.RequestCallback); this.mainStore.setBailout(bailoutMessage.RequestCallback);
}, },
toDisplayPhoneNumber, toDisplayPhoneNumber,
formatAmountInDollars, formatAmountInDollars,

View file

@ -365,7 +365,7 @@ export default {
return getTpaProvidersResult?.data?.shopProviders ?? []; return getTpaProvidersResult?.data?.shopProviders ?? [];
}, },
doNotSeeMyShopLinkClick() { doNotSeeMyShopLinkClick() {
this.mainStore.setBailout(this.$router.currentRoute, bailoutMessage.doNotSeeMyShop()); this.mainStore.setBailout(bailoutMessage.doNotSeeMyShop());
this.$router.navigate( this.$router.navigate(
this.navigationScenarios.CLICKED_DO_NOT_SEE_MY_SHOP_LINK, this.navigationScenarios.CLICKED_DO_NOT_SEE_MY_SHOP_LINK,
this.$route this.$route

View file

@ -197,6 +197,11 @@ export default {
navigateForward() { navigateForward() {
this.mainStore.setVehicle().then(() => { this.mainStore.setVehicle().then(() => {
if (this.mainStore.isBailout) {
this.$router.navigate(this.navigationScenarios.CLICKED_FORWARD_WITH_BAILOUT, this.$route);
return;
}
this.$router.navigate( this.$router.navigate(
this.navigationScenarios.CLICKED_FORWARD, this.navigationScenarios.CLICKED_FORWARD,
this.$route this.$route

View file

@ -179,7 +179,7 @@ export default {
if (vehicleLookupResponse.error) { if (vehicleLookupResponse.error) {
this.activeVehicleLookupAlertType = vehicleLookupAlertTypes.NOT_FOUND; this.activeVehicleLookupAlertType = vehicleLookupAlertTypes.NOT_FOUND;
this.mainStore.setBailout(this.$router.currentRoute, bailoutMessage.vehicleNotFound(this.vin)); this.mainStore.setBailout(bailoutMessage.vehicleNotFound(this.vin));
this.resetVehicleFromLookup(); this.resetVehicleFromLookup();
this.$refs.siteFooter.removeLoader(); this.$refs.siteFooter.removeLoader();
// Temp solution to turn on 'disabled' style on the Continue button // Temp solution to turn on 'disabled' style on the Continue button

View file

@ -175,7 +175,7 @@ router.afterEach(async (to, from) => {
const saveSessionSynchronous = !!from.params[routerParams.SAVE_SESSION_SYNCHRONOUS]; const saveSessionSynchronous = !!from.params[routerParams.SAVE_SESSION_SYNCHRONOUS];
await saveSession({ shouldAwaitSaveSessionQueue: saveSessionSynchronous }).catch((error) => { await saveSession({ shouldAwaitSaveSessionQueue: saveSessionSynchronous }).catch((error) => {
if (from.name === issPageValues.WELCOME_PAGE) { if (from.name === issPageValues.WELCOME_PAGE) {
store.setBailout(router, bailoutMessage.saveSessionError(error.data)); store.setBailout(bailoutMessage.saveSessionError(error.data));
router.navigate( router.navigate(
navigationScenarios.SAVE_SESSION_FAILED, navigationScenarios.SAVE_SESSION_FAILED,
{ query: { issPage: issPageValues.WELCOME_PAGE } } { query: { issPage: issPageValues.WELCOME_PAGE } }

View file

@ -14,6 +14,10 @@ const routingTable = () => [
{ {
scenario: navigationScenarios.CLICKED_FORWARD, scenario: navigationScenarios.CLICKED_FORWARD,
destinationIssPageValue: issPageValues.VEHICLE_DAMAGE destinationIssPageValue: issPageValues.VEHICLE_DAMAGE
},
{
scenario: navigationScenarios.CLICKED_FORWARD_WITH_BAILOUT,
destinationIssPageValue: issPageValues.BAILOUT_PAGE
} }
] ]
}, },

View file

@ -22,6 +22,8 @@ import {
repairWaivedForSelectedVehicle repairWaivedForSelectedVehicle
} from '@/helpers/policy-vehicle-helper'; } from '@/helpers/policy-vehicle-helper';
import partTypeStrings from '@/constants/part-type-strings'; import partTypeStrings from '@/constants/part-type-strings';
import bailoutMessage from '@/constants/bailoutMessage';
import bailoutCode from "@/constants/bailoutCode";
const storeId = 'main'; const storeId = 'main';
@ -261,6 +263,7 @@ export const useMainStore = defineStore({
isClaimRegistrationRequired: (state) => state.issConfig.isClaimRegistrationRequired, isClaimRegistrationRequired: (state) => state.issConfig.isClaimRegistrationRequired,
isClaimAlreadyRegistered: (state) => state.order.payment.insuranceCoverage.claimNumber !== null, isClaimAlreadyRegistered: (state) => state.order.payment.insuranceCoverage.claimNumber !== null,
isBailout: (state) => state.applicationUser.pageData[issPageValues.BAILOUT_PAGE] != null, isBailout: (state) => state.applicationUser.pageData[issPageValues.BAILOUT_PAGE] != null,
bailoutCode: (state) => state.applicationUser.pageData[issPageValues.BAILOUT_PAGE]?.bailoutCode,
isNoComp: (state) => !!state.order.policy.noCoverage, isNoComp: (state) => !!state.order.policy.noCoverage,
isITAC: (state) => !!state.order.policy.isITAC, isITAC: (state) => !!state.order.policy.isITAC,
isVerifiedCoverageStatus: (state) => state.order.payment.insuranceCoverage.coverageStatus === coverageStatuses.VERIFIED, isVerifiedCoverageStatus: (state) => state.order.payment.insuranceCoverage.coverageStatus === coverageStatuses.VERIFIED,
@ -1588,6 +1591,15 @@ export const useMainStore = defineStore({
this.order.vehicle.imageVifNumber = vehicle.imageVifNumber; this.order.vehicle.imageVifNumber = vehicle.imageVifNumber;
this.order.vehicle.imageColor = vehicle.imageVifColor; this.order.vehicle.imageColor = vehicle.imageVifColor;
if (vehicle.canSafeliteService) {
if (this.isBailout && this.bailoutCode === bailoutCode.HeavyTruckVehicle) {
// reset previously set bailout if vehicle can be serviced.
this.resetBailout();
}
} else {
this.setBailout(bailoutMessage.HeavyTruckVehicle(vehicle.carId));
}
// These could be undefined // These could be undefined
this.order.policy.noCoverage = vehicle.noCoverage; this.order.policy.noCoverage = vehicle.noCoverage;
const currentCoverageStatus = vehicle.noCoverage ? coverageStatuses.NO_COMP : coverageStatuses.PENDING; const currentCoverageStatus = vehicle.noCoverage ? coverageStatuses.NO_COMP : coverageStatuses.PENDING;
@ -2249,12 +2261,15 @@ export const useMainStore = defineStore({
this.updateRegistration(registrationInfo); this.updateRegistration(registrationInfo);
}, },
setBailout(currentRoute, bailoutData) { setBailout(bailoutData) {
const params = new URL(document.location.toString()).searchParams;
const currentPage = params.get('issPage');
this.updatePageData({ this.updatePageData({
page: issPageValues.BAILOUT_PAGE, page: issPageValues.BAILOUT_PAGE,
data: { data: {
url: window.location.href, url: window.location.href,
page: currentRoute.value?.name ?? currentRoute.name, page: currentPage || 'Unknown Page',
bailoutCode: bailoutData.code, bailoutCode: bailoutData.code,
errorMessage: bailoutData.message, errorMessage: bailoutData.message,
submit: false submit: false

View file

@ -6,6 +6,7 @@ import coverageStatuses from '@/constants/coverage-statuses.js';
import { paymentMethods } from '@/constants/payment-method-constants'; import { paymentMethods } from '@/constants/payment-method-constants';
import { endpoints } from '@/constants/endpoints'; import { endpoints } from '@/constants/endpoints';
import { AppointmentTypeStrings } from '@/constants/schedule-constants'; import { AppointmentTypeStrings } from '@/constants/schedule-constants';
import bailoutCode from '@/constants/bailoutCode';
describe('Store', () => { describe('Store', () => {
let store; let store;
@ -228,6 +229,21 @@ describe('Store', () => {
} }
); );
it('setVehicle is bailout if the vehicle cannot be serviced by Safelite', () => {
// Arrange
const vehicle = {
carId: getRandomString(6, 6),
canSafeliteService: false
};
// Act
store.updateVehicle(vehicle);
// Assert
expect(store.isBailout).toBe(true);
expect(store.bailoutCode).toBe(bailoutCode.HeavyTruckVehicle);
});
// TODO update test to work also checking store values // TODO update test to work also checking store values
it('setVehicle should call globalMethods.callHttpClient', () => { it('setVehicle should call globalMethods.callHttpClient', () => {
// Arrange // Arrange
@ -1050,6 +1066,12 @@ describe('Store', () => {
it('sets expected vehicle data', async () => { it('sets expected vehicle data', async () => {
// Arrange // Arrange
globalMethods.callHttpClient = jest.fn().mockReturnValue(Promise.resolve(fullApiResponse)); globalMethods.callHttpClient = jest.fn().mockReturnValue(Promise.resolve(fullApiResponse));
store.lookupVehicleByVin = jest.fn().mockReturnValue(Promise.resolve({
data: {
vin: vehicle.vin,
canSafeliteService: true
}
}));
const duplicate = { const duplicate = {
referralNumber: getRandomString(6, 6), referralNumber: getRandomString(6, 6),
@ -1073,6 +1095,12 @@ describe('Store', () => {
it('sets expected customer data', async () => { it('sets expected customer data', async () => {
// Arrange // Arrange
globalMethods.callHttpClient = jest.fn().mockReturnValue(Promise.resolve(fullApiResponse)); globalMethods.callHttpClient = jest.fn().mockReturnValue(Promise.resolve(fullApiResponse));
store.lookupVehicleByVin = jest.fn().mockReturnValue(Promise.resolve({
data: {
vin: vehicle.vin,
canSafeliteService: true
}
}));
const duplicate = { const duplicate = {
referralNumber: getRandomString(6, 6), referralNumber: getRandomString(6, 6),
@ -1099,6 +1127,12 @@ describe('Store', () => {
it('sets expected remaining order data', async () => { it('sets expected remaining order data', async () => {
// Arrange // Arrange
globalMethods.callHttpClient = jest.fn().mockReturnValue(Promise.resolve(fullApiResponse)); globalMethods.callHttpClient = jest.fn().mockReturnValue(Promise.resolve(fullApiResponse));
store.lookupVehicleByVin = jest.fn().mockReturnValue(Promise.resolve({
data: {
vin: vehicle.vin,
canSafeliteService: true
}
}));
const duplicate = { const duplicate = {
referralNumber: getRandomString(6, 6), referralNumber: getRandomString(6, 6),