diff --git a/src/digital-components/textbox-question/textbox-question.vue b/src/digital-components/textbox-question/textbox-question.vue
index 2443d67a..e74b1708 100644
--- a/src/digital-components/textbox-question/textbox-question.vue
+++ b/src/digital-components/textbox-question/textbox-question.vue
@@ -47,7 +47,7 @@
:data-bs-toggle="includeSelectIcon ? 'modal' : ''"
:data-bs-target="'#' + cmsWidgetName"
@change="handleChange"
- @blur="handleChange"
+ @blur="blurPlus"
@focus="$emit('focus', $event.target.value)"
@paste="trimOnPaste"
@drop="trimOnPaste" />
@@ -92,6 +92,10 @@ export default {
buttonMain
},
props: {
+ alwaysEmitFieldErrorOnEvent: {
+ type: Boolean,
+ default: false
+ },
type: {
type: String,
default: 'text'
@@ -136,7 +140,7 @@ export default {
default: () => {}
}
},
- emits: ['focus', 'update:modelValue', 'textboxQuestionEvent.inputIdAssigned', 'click-event'],
+ emits: ['focus', 'update:modelValue', 'textboxQuestionEvent.inputIdAssigned', 'click-event', 'field-has-error'],
setup(props) {
const propsClone = { ...props };
const { modelValue } = propsClone;
@@ -218,6 +222,12 @@ export default {
this.$emit('textboxQuestionEvent.inputIdAssigned', this.inputId);
},
methods: {
+ blurPlus() {
+ this.handleChange(this.value);
+ if (this.alwaysEmitFieldErrorOnEvent) {
+ this.$emit('field-has-error', !this.meta.valid);
+ }
+ },
trimOnPaste(evt) {
evt.stopPropagation();
evt.preventDefault();
@@ -254,6 +264,8 @@ export default {
if (result.valid) {
this.handleChange(this.value);
this.$emit('click-event');
+ } else if (this.alwaysEmitFieldErrorOnEvent) {
+ this.$emit('field-has-error', true);
}
}
}
@@ -291,6 +303,18 @@ input::-webkit-date-and-time-value {
}
.textbox-question {
+ &.has-error {
+ .input-wrapper.has-search-icon {
+ input.form-control[type='text'] {
+ border-color: #db0020;
+ }
+ button[type='submit'] {
+ border-color: #db0020;
+ background-color: #fbe5e9;
+ background-image: url($svg-error-search-icon);
+ }
+ }
+ }
label {
color: $black;
font-weight: 600;
diff --git a/src/global-methods.js b/src/global-methods.js
index 280f318d..7f7ad72b 100644
--- a/src/global-methods.js
+++ b/src/global-methods.js
@@ -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);
diff --git a/src/global-methods.spec.js b/src/global-methods.spec.js
index fbb084ff..e5e82e45 100644
--- a/src/global-methods.spec.js
+++ b/src/global-methods.spec.js
@@ -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);
+ });
+});
\ No newline at end of file
diff --git a/src/helpers/order-helper.js b/src/helpers/order-helper.js
index f1ab7c72..cbc5c890 100644
--- a/src/helpers/order-helper.js
+++ b/src/helpers/order-helper.js
@@ -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);
}
diff --git a/src/layouts/capability-questions/capability-questions.vue b/src/layouts/capability-questions/capability-questions.vue
index c322a54b..e6dfd7bf 100644
--- a/src/layouts/capability-questions/capability-questions.vue
+++ b/src/layouts/capability-questions/capability-questions.vue
@@ -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());
}
}
};
diff --git a/src/layouts/coverage-statement/__snapshots__/coverage-statement.spec.js.snap b/src/layouts/coverage-statement/__snapshots__/coverage-statement.spec.js.snap
index 26f60304..40af428e 100644
--- a/src/layouts/coverage-statement/__snapshots__/coverage-statement.spec.js.snap
+++ b/src/layouts/coverage-statement/__snapshots__/coverage-statement.spec.js.snap
@@ -5,6 +5,7 @@ Object {
"CANCEL_CLAIM_REF_NAME": "CancelClaimModal",
"RECAL_MODAL_REF_NAME": "RecalModal",
"baseServiceLineItems": Array [],
+ "isPageLoading": true,
"widget": Object {
"disclaimerText": "DisclaimerWidget",
"explanatoryText": "ExplanatoryTextWidget",
diff --git a/src/layouts/coverage-statement/afterpay-modal-banner/afterpay-modal-banner.vue b/src/layouts/coverage-statement/afterpay-modal-banner/afterpay-modal-banner.vue
new file mode 100644
index 00000000..232cf329
--- /dev/null
+++ b/src/layouts/coverage-statement/afterpay-modal-banner/afterpay-modal-banner.vue
@@ -0,0 +1,116 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/layouts/coverage-statement/coverage-statement.spec.js b/src/layouts/coverage-statement/coverage-statement.spec.js
index aa9c3058..a8b77aa5 100644
--- a/src/layouts/coverage-statement/coverage-statement.spec.js
+++ b/src/layouts/coverage-statement/coverage-statement.spec.js
@@ -63,7 +63,8 @@ const loadingModalStub = {
function getMountedComponent(mainInitialState = {}, initialData = {}, methodToRun = () => {}) {
const mountOptions = getMountOptions({
router: {
- navigate: jest.fn()
+ navigate: jest.fn(),
+ navigateBailout: jest.fn()
}
});
@@ -134,7 +135,10 @@ describe('coverageStatement.vue', () => {
});
test('Should render site subheader', () => {
// Arrange
- const { wrapper } = getMountedComponent({});
+ const initialDataForTest = {
+ isPageLoading: false
+ };
+ const { wrapper } = getMountedComponent({}, initialDataForTest);
// Act
const subheader = wrapper.find({ ref: 'siteSubHeader' });
@@ -145,7 +149,10 @@ describe('coverageStatement.vue', () => {
test('Should render explanatory text', () => {
// Arrange
- const { wrapper } = getMountedComponent({});
+ const initialDataForTest = {
+ isPageLoading: false
+ };
+ const { wrapper } = getMountedComponent({}, initialDataForTest);
// Act
const explanatoryText = wrapper.find({ ref: 'explanatoryText' });
@@ -155,7 +162,10 @@ describe('coverageStatement.vue', () => {
});
test('Should render secondary text', () => {
// Arrange
- const { wrapper } = getMountedComponent({});
+ const initialDataForTest = {
+ isPageLoading: false
+ };
+ const { wrapper } = getMountedComponent({}, initialDataForTest);
// Act
const secondaryText = wrapper.find({ ref: 'secondaryText' });
@@ -430,6 +440,109 @@ describe('coverageStatement.vue', () => {
expect(result).toBe(expected);
});
});
+ describe('displayAfterpayBanner', () => {
+ test('returns true if ITAC', () => {
+ // Arrange
+ const mainInitialState = {
+ order: {
+ insuranceCoverage: {
+ coverageStatus: coverageStatuses.VERIFIED,
+ coverageType: coverageType.ITAC
+ }
+ }
+ };
+ const { wrapper } = getMountedComponent(mainInitialState);
+
+ // Act
+ const result = wrapper.vm.displayAfterpayBanner;
+
+ // Assert
+ expect(result).toBeTruthy();
+ });
+ test('returns true if No Comp', () => {
+ // Arrange
+ const mainInitialState = {
+ order: {
+ insuranceCoverage: {
+ coverageStatus: coverageStatuses.VERIFIED,
+ coverageType: coverageType.NO_COMP
+ }
+ }
+ };
+ const { wrapper } = getMountedComponent(mainInitialState);
+
+ // Act
+ const result = wrapper.vm.displayAfterpayBanner;
+
+ // Assert
+ expect(result).toBeTruthy();
+ });
+ test('returns true if deductible is > $0', () => {
+ // Arrange
+ const mainInitialState = {
+ order: {
+ insuranceCoverage: {
+ coverageStatus: coverageStatuses.VERIFIED,
+ coverageType: coverageType.Deductible
+ },
+ damage: {
+ isRepair: false
+ },
+ currentDeductible: {
+ replace: 500
+ }
+ }
+ };
+ const { wrapper } = getMountedComponent(mainInitialState);
+
+ // Act
+ const result = wrapper.vm.displayAfterpayBanner;
+
+ // Assert
+ expect(result).toBeTruthy();
+ });
+ test('returns false if deductible is <= $0', () => {
+ // Arrange
+ const mainInitialState = {
+ order: {
+ insuranceCoverage: {
+ coverageStatus: coverageStatuses.VERIFIED,
+ coverageType: coverageType.Deductible
+ },
+ damage: {
+ isRepair: false
+ },
+ currentDeductible: {
+ replace: 0
+ }
+ }
+ };
+ const { wrapper } = getMountedComponent(mainInitialState);
+
+ // Act
+ const result = wrapper.vm.displayAfterpayBanner;
+
+ // Assert
+ expect(result).toBeFalsy();
+ });
+ test('returns false if Unverified', () => {
+ // Arrange
+ const mainInitialState = {
+ order: {
+ insuranceCoverage: {
+ coverageStatus: coverageStatuses.UNVERIFIED,
+ }
+ }
+ };
+ const { wrapper } = getMountedComponent(mainInitialState);
+
+ // Act
+ const result = wrapper.vm.displayAfterpayBanner;
+
+ // Assert
+ expect(result).toBeFalsy();
+ });
+ });
});
describe('methods', () => {
describe('arePagePrerequisitesValid', () => {
@@ -578,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 = {
@@ -604,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
@@ -641,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: {
@@ -666,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', () => {
diff --git a/src/layouts/coverage-statement/coverage-statement.vue b/src/layouts/coverage-statement/coverage-statement.vue
index c1c7abbd..832d9219 100644
--- a/src/layouts/coverage-statement/coverage-statement.vue
+++ b/src/layouts/coverage-statement/coverage-statement.vue
@@ -10,7 +10,8 @@
cmsWidgetName="SiteHeaderWidget" />
-
+
+
0);
}
},
watch: {
@@ -347,6 +360,9 @@ export default {
}
},
mounted() {
+ if (this.isPageLoading) {
+ showIssLoadingModal(true);
+ }
setupModalLinks(this);
},
methods: {
@@ -370,6 +386,7 @@ export default {
}
showIssLoadingModal(false);
+ this.isPageLoading = false;
},
async getPricedParts() {
const { glassParts, supportingItems } = this.mainStore.order.lineItems;
@@ -380,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);
}
},
@@ -402,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) {
@@ -457,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());
}
}
};
diff --git a/src/layouts/duplicate-check/duplicate-check.spec.js b/src/layouts/duplicate-check/duplicate-check.spec.js
index 10be35e2..95346c26 100644
--- a/src/layouts/duplicate-check/duplicate-check.spec.js
+++ b/src/layouts/duplicate-check/duplicate-check.spec.js
@@ -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
diff --git a/src/layouts/duplicate-check/duplicate-check.vue b/src/layouts/duplicate-check/duplicate-check.vue
index 1cac5a1e..3c4ead5f 100644
--- a/src/layouts/duplicate-check/duplicate-check.vue
+++ b/src/layouts/duplicate-check/duplicate-check.vue
@@ -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);
diff --git a/src/layouts/entry-page/entry-page.vue b/src/layouts/entry-page/entry-page.vue
index e9880117..47031709 100644
--- a/src/layouts/entry-page/entry-page.vue
+++ b/src/layouts/entry-page/entry-page.vue
@@ -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) {
diff --git a/src/layouts/molding-questions/molding-questions.vue b/src/layouts/molding-questions/molding-questions.vue
index cb0f4f04..44d6af81 100644
--- a/src/layouts/molding-questions/molding-questions.vue
+++ b/src/layouts/molding-questions/molding-questions.vue
@@ -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());
}
}
};
diff --git a/src/layouts/part-questions/part-questions.vue b/src/layouts/part-questions/part-questions.vue
index 1230016a..9bed6345 100644
--- a/src/layouts/part-questions/part-questions.vue
+++ b/src/layouts/part-questions/part-questions.vue
@@ -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());
}
},
};
diff --git a/src/layouts/payment-method/payment-method.vue b/src/layouts/payment-method/payment-method.vue
index c93c429e..fee96d3a 100644
--- a/src/layouts/payment-method/payment-method.vue
+++ b/src/layouts/payment-method/payment-method.vue
@@ -410,25 +410,16 @@ export default {
}
}
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(
diff --git a/src/layouts/payment-return/payment-return.vue b/src/layouts/payment-return/payment-return.vue
index 09860d17..d4ba19a4 100644
--- a/src/layouts/payment-return/payment-return.vue
+++ b/src/layouts/payment-return/payment-return.vue
@@ -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,
diff --git a/src/layouts/policy-vehicles/policy-vehicles.spec.js b/src/layouts/policy-vehicles/policy-vehicles.spec.js
index a4670b55..62c6b526 100644
--- a/src/layouts/policy-vehicles/policy-vehicles.spec.js
+++ b/src/layouts/policy-vehicles/policy-vehicles.spec.js
@@ -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({
diff --git a/src/layouts/policy-vehicles/policy-vehicles.vue b/src/layouts/policy-vehicles/policy-vehicles.vue
index c459cefd..9cedd58d 100644
--- a/src/layouts/policy-vehicles/policy-vehicles.vue
+++ b/src/layouts/policy-vehicles/policy-vehicles.vue
@@ -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;
diff --git a/src/layouts/provider-preference/provider-preference.spec.js b/src/layouts/provider-preference/provider-preference.spec.js
index 3fdcb495..0d93ed3a 100644
--- a/src/layouts/provider-preference/provider-preference.spec.js
+++ b/src/layouts/provider-preference/provider-preference.spec.js
@@ -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', () => {
diff --git a/src/layouts/provider-preference/provider-preference.vue b/src/layouts/provider-preference/provider-preference.vue
index 4400174e..27e38ff8 100644
--- a/src/layouts/provider-preference/provider-preference.vue
+++ b/src/layouts/provider-preference/provider-preference.vue
@@ -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() {
diff --git a/src/layouts/schedule-page/schedule-page.vue b/src/layouts/schedule-page/schedule-page.vue
index 3a74877e..28b73548 100644
--- a/src/layouts/schedule-page/schedule-page.vue
+++ b/src/layouts/schedule-page/schedule-page.vue
@@ -171,20 +171,20 @@ const getAvailableDates = async (
await Promise.all(storeActionConfigs.map(async (storeAction) => {
let timeSlotsResponse = null;
if (storeAction.storeAction === GET_SHOP_TIME_SLOTS) {
- timeSlotsResponse = await useMainStore().getShopTimeSlots(
- storeAction.payload.startDate,
- storeAction.payload.endDate,
- storeAction.payload.shopAppointmentType,
- storeAction.payload.providerNumber
- );
+ if (storeAction.payload.providerNumber) {
+ timeSlotsResponse = await useMainStore().getShopTimeSlots(
+ storeAction.payload.startDate,
+ storeAction.payload.endDate,
+ storeAction.payload.shopAppointmentType,
+ storeAction.payload.providerNumber
+ );
+ }
} else if (storeAction.payload?.zipCodeOverride) {
timeSlotsResponse = await useMainStore().getMobileTimeSlots(
storeAction.payload.startDate,
storeAction.payload.endDate,
storeAction.payload.zipCodeOverride
- ).catch(() => {
- console.warn('Error fetching mobile time slots...');
- });
+ );
}
if (!timeSlotsResponse || !timeSlotsResponse.data) {
@@ -204,6 +204,9 @@ const getAvailableDates = async (
// sort days chronologically
timeSlotsResponsesData.days.sort(compareDayStrings);
return timeSlotsResponsesData;
+ })
+ .catch(() => {
+ return timeSlotsResponsesData;
});
};
diff --git a/src/layouts/schedule-page/service-location/service-zip-question/service-zip-question.vue b/src/layouts/schedule-page/service-location/service-zip-question/service-zip-question.vue
index e9671f9f..4f401049 100644
--- a/src/layouts/schedule-page/service-location/service-zip-question/service-zip-question.vue
+++ b/src/layouts/schedule-page/service-location/service-zip-question/service-zip-question.vue
@@ -2,6 +2,7 @@
+ @clickEvent="updateModelValue"
+ @fieldHasError="handleFieldError" />