CASH-2563
This commit is contained in:
parent
1fb36e7ee7
commit
dd291a980c
9 changed files with 172 additions and 34 deletions
|
|
@ -1,5 +1,5 @@
|
||||||
const bailoutCodes = {
|
const bailoutCodes = {
|
||||||
PARTS_NOT_FOUND: "PartsNotFound",
|
PARTS_NOT_FOUND: 10,
|
||||||
};
|
};
|
||||||
|
|
||||||
export { bailoutCodes };
|
export { bailoutCodes };
|
||||||
|
|
|
||||||
|
|
@ -57,15 +57,13 @@ export async function saveSession({
|
||||||
shouldAwaitSaveSessionQueue = false,
|
shouldAwaitSaveSessionQueue = false,
|
||||||
submitAfterSave = false,
|
submitAfterSave = false,
|
||||||
createUnscheduledStatusWorkOrderForPIA = false,
|
createUnscheduledStatusWorkOrderForPIA = false,
|
||||||
bailoutCode = null,
|
|
||||||
}) {
|
}) {
|
||||||
// Add next save session to end of queue
|
// Add next save session to end of queue
|
||||||
const saveSessionPromise = flushSaveSessionQueue().then(() => {
|
const saveSessionPromise = flushSaveSessionQueue().then(() => {
|
||||||
return saveSessionHelper(
|
return saveSessionHelper(
|
||||||
pageNameToLog,
|
pageNameToLog,
|
||||||
submitAfterSave,
|
submitAfterSave,
|
||||||
createUnscheduledStatusWorkOrderForPIA,
|
createUnscheduledStatusWorkOrderForPIA
|
||||||
bailoutCode
|
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -108,12 +106,11 @@ export async function saveQuote({ pageNameToLog }) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function submitBailout({ pageNameToLog, bailoutCode }) {
|
export async function submitBailout({ pageNameToLog }) {
|
||||||
await saveSession({
|
await saveSession({
|
||||||
pageNameToLog: pageNameToLog,
|
pageNameToLog: pageNameToLog,
|
||||||
shouldAwaitSaveSessionQueue: true,
|
shouldAwaitSaveSessionQueue: true,
|
||||||
submitAfterSave: false,
|
submitAfterSave: false,
|
||||||
bailoutCode: bailoutCode,
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -158,15 +155,13 @@ async function loadSession(
|
||||||
async function saveSessionHelper(
|
async function saveSessionHelper(
|
||||||
pageNameToLog,
|
pageNameToLog,
|
||||||
submitAfterSave = false,
|
submitAfterSave = false,
|
||||||
createUnscheduledStatusWorkOrderForPIA = false,
|
createUnscheduledStatusWorkOrderForPIA = false
|
||||||
bailoutCode = null
|
|
||||||
) {
|
) {
|
||||||
const savedSessionInfo = await baseMixin.methods.dispatchStoreActionWithLogging(
|
const savedSessionInfo = await baseMixin.methods.dispatchStoreActionWithLogging(
|
||||||
storeActions.SAVE_SESSION,
|
storeActions.SAVE_SESSION,
|
||||||
{
|
{
|
||||||
submitAfterSave: submitAfterSave,
|
submitAfterSave: submitAfterSave,
|
||||||
createUnscheduledStatusWorkOrderForPIA: createUnscheduledStatusWorkOrderForPIA,
|
createUnscheduledStatusWorkOrderForPIA: createUnscheduledStatusWorkOrderForPIA,
|
||||||
bailoutCode: bailoutCode,
|
|
||||||
},
|
},
|
||||||
pageNameToLog
|
pageNameToLog
|
||||||
);
|
);
|
||||||
|
|
|
||||||
56
src/layouts/bailout-success/bailout-success.spec.js
Normal file
56
src/layouts/bailout-success/bailout-success.spec.js
Normal file
|
|
@ -0,0 +1,56 @@
|
||||||
|
// Components
|
||||||
|
import bailoutSuccess from "@/layouts/bailout-success/bailout-success.vue";
|
||||||
|
|
||||||
|
// Supporting Files
|
||||||
|
import { shallowMount } from "@vue/test-utils";
|
||||||
|
import { getMountOptions } from "@/helpers/unit-test-helper.js";
|
||||||
|
|
||||||
|
// Mock our module for promises.
|
||||||
|
jest.mock("@/helpers/layout-helper.js", () => ({
|
||||||
|
settleAllPromises: jest.fn(),
|
||||||
|
}));
|
||||||
|
|
||||||
|
// Mock fetchCmsContentForPage
|
||||||
|
jest.mock("@/helpers/cms-content-helper", () => ({
|
||||||
|
fetchCmsContentForPage: jest.fn(),
|
||||||
|
}));
|
||||||
|
|
||||||
|
describe("bailout-success.vue", () => {
|
||||||
|
test("renders funnelHeader component", () => {
|
||||||
|
const { wrapper } = setupMocks();
|
||||||
|
expect(wrapper.findComponent({ name: "funnelHeader" }).exists()).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("renders funnelSubHeader component", () => {
|
||||||
|
const { wrapper } = setupMocks();
|
||||||
|
expect(wrapper.findComponent({ name: "funnelSubHeader" }).exists()).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("renders Form component", () => {
|
||||||
|
const { wrapper } = setupMocks();
|
||||||
|
expect(wrapper.findComponent({ name: "Form" }).exists()).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("renders buttonMain component", () => {
|
||||||
|
const { wrapper } = setupMocks();
|
||||||
|
expect(wrapper.findComponent({ name: "buttonMain" }).exists()).toBe(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
function setupMocks() {
|
||||||
|
const mountOptions = getMountOptions({});
|
||||||
|
|
||||||
|
//Mock props
|
||||||
|
const mockMixin = {
|
||||||
|
methods: {
|
||||||
|
getCmsContent: jest.fn(),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
mountOptions.mixins = [mockMixin];
|
||||||
|
const wrapper = shallowMount(bailoutSuccess, mountOptions);
|
||||||
|
|
||||||
|
wrapper.vm.setCmsContent = jest.fn();
|
||||||
|
|
||||||
|
return { wrapper };
|
||||||
|
}
|
||||||
|
|
@ -22,7 +22,7 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import Form from "vee-validate";
|
import { Form } from "vee-validate";
|
||||||
import funnelHeader from "@/fmg-components/funnel-header/funnel-header";
|
import funnelHeader from "@/fmg-components/funnel-header/funnel-header";
|
||||||
import funnelSubHeader from "@/fmg-components/funnel-sub-header/funnel-sub-header";
|
import funnelSubHeader from "@/fmg-components/funnel-sub-header/funnel-sub-header";
|
||||||
import buttonMain from "@/ux-components/button-main/button-main";
|
import buttonMain from "@/ux-components/button-main/button-main";
|
||||||
|
|
@ -62,7 +62,7 @@ export default {
|
||||||
async forwardButtonAction() {
|
async forwardButtonAction() {
|
||||||
this.$router.navigateWithoutSaving(
|
this.$router.navigateWithoutSaving(
|
||||||
this.navigationScenarios.CLICKED_BACK_TO_HOMEPAGE,
|
this.navigationScenarios.CLICKED_BACK_TO_HOMEPAGE,
|
||||||
"bailout-success"
|
this.pageName
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
arePagePrerequisitesValid() {
|
arePagePrerequisitesValid() {
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,26 @@ jest.mock("@/helpers/cms-content-helper", () => ({
|
||||||
}));
|
}));
|
||||||
|
|
||||||
describe("bailout.vue", () => {
|
describe("bailout.vue", () => {
|
||||||
|
test("renders funnelHeader component", () => {
|
||||||
|
const { wrapper } = setupMocks();
|
||||||
|
expect(wrapper.findComponent({ name: "funnelHeader" }).exists()).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("renders funnelSubHeader component", () => {
|
||||||
|
const { wrapper } = setupMocks();
|
||||||
|
expect(wrapper.findComponent({ name: "funnelSubHeader" }).exists()).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("renders Form component", () => {
|
||||||
|
const { wrapper } = setupMocks();
|
||||||
|
expect(wrapper.findComponent({ name: "Form" }).exists()).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("renders navbar component", () => {
|
||||||
|
const { wrapper } = setupMocks();
|
||||||
|
expect(wrapper.findComponent({ name: "navbar" }).exists()).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
test("arePagePrerequisitesValid should be true ", async () => {
|
test("arePagePrerequisitesValid should be true ", async () => {
|
||||||
//Arrange
|
//Arrange
|
||||||
const { wrapper } = setupMocks();
|
const { wrapper } = setupMocks();
|
||||||
|
|
|
||||||
|
|
@ -42,6 +42,23 @@
|
||||||
v-model="phoneNumber"
|
v-model="phoneNumber"
|
||||||
validationRules="phone-number-required" />
|
validationRules="phone-number-required" />
|
||||||
|
|
||||||
|
<textboxQuestion
|
||||||
|
class="mb-4"
|
||||||
|
cmsWidgetName="ServiceZipQuestionWidget"
|
||||||
|
v-model="serviceZipCode"
|
||||||
|
ref="serviceZip"
|
||||||
|
customInputId="serviceZip"
|
||||||
|
mask="#####"
|
||||||
|
validationRules="service-zip-required|service-zip-format" />
|
||||||
|
|
||||||
|
<alert
|
||||||
|
ref="alertInvalidZip"
|
||||||
|
v-if="displayInvalidZipAlert"
|
||||||
|
class="mb-4"
|
||||||
|
cmsWidgetName="AlertInvalidZipWidget"
|
||||||
|
alertClass="alert-danger"
|
||||||
|
v-bind:isDismissible="false" />
|
||||||
|
|
||||||
<checkboxQuestion
|
<checkboxQuestion
|
||||||
class="mb-5"
|
class="mb-5"
|
||||||
cmsWidgetName="TextMeQuestionWidget"
|
cmsWidgetName="TextMeQuestionWidget"
|
||||||
|
|
@ -69,6 +86,7 @@ import { Form, defineRule } from "vee-validate";
|
||||||
import funnelHeader from "@/fmg-components/funnel-header/funnel-header";
|
import funnelHeader from "@/fmg-components/funnel-header/funnel-header";
|
||||||
import navbar from "@/fmg-components/nav-bar/nav-bar";
|
import navbar from "@/fmg-components/nav-bar/nav-bar";
|
||||||
import funnelSubHeader from "@/fmg-components/funnel-sub-header/funnel-sub-header";
|
import funnelSubHeader from "@/fmg-components/funnel-sub-header/funnel-sub-header";
|
||||||
|
import alert from "@/ux-components/alert/alert";
|
||||||
import textboxQuestion from "@/digital-components/textbox-question/textbox-question";
|
import textboxQuestion from "@/digital-components/textbox-question/textbox-question";
|
||||||
import phoneNumberQuestion from "@/digital-components/phone-number-question/phone-number-question";
|
import phoneNumberQuestion from "@/digital-components/phone-number-question/phone-number-question";
|
||||||
import textBlock from "@/digital-components/text-block/text-block";
|
import textBlock from "@/digital-components/text-block/text-block";
|
||||||
|
|
@ -95,6 +113,11 @@ defineRule(
|
||||||
errorMessages.EMAIL_ADDRESS_FORMAT
|
errorMessages.EMAIL_ADDRESS_FORMAT
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
defineRule("service-zip-required", required(errorMessages.SERVICE_ZIP_REQUIRED));
|
||||||
|
defineRule(
|
||||||
|
"service-zip-format",
|
||||||
|
regex(/(^\d{5}$)|(^\d{5}-\d{4}$)/, errorMessages.SERVICE_ZIP_FORMAT)
|
||||||
|
);
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "bailout",
|
name: "bailout",
|
||||||
|
|
@ -106,7 +129,9 @@ export default {
|
||||||
lastName: this.getLastNameFromStore(),
|
lastName: this.getLastNameFromStore(),
|
||||||
emailAddress: this.getEmailAddressFromStore(),
|
emailAddress: this.getEmailAddressFromStore(),
|
||||||
phoneNumber: this.getPhoneNumberFromStore(),
|
phoneNumber: this.getPhoneNumberFromStore(),
|
||||||
|
serviceZipCode: this.getServiceZipFromStore(),
|
||||||
isSmsOptIn: this.getIsSmsOptInFromStore(),
|
isSmsOptIn: this.getIsSmsOptInFromStore(),
|
||||||
|
displayInvalidZipAlert: false,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
@ -146,6 +171,9 @@ export default {
|
||||||
getPhoneNumberFromStore() {
|
getPhoneNumberFromStore() {
|
||||||
return store.getters.order.customer.phoneNumber;
|
return store.getters.order.customer.phoneNumber;
|
||||||
},
|
},
|
||||||
|
getServiceZipFromStore() {
|
||||||
|
return store.getters.order.serviceLocation.zipCode;
|
||||||
|
},
|
||||||
getIsSmsOptInFromStore() {
|
getIsSmsOptInFromStore() {
|
||||||
return store.getters.order.customer.isSmsOptIn;
|
return store.getters.order.customer.isSmsOptIn;
|
||||||
},
|
},
|
||||||
|
|
@ -153,7 +181,17 @@ export default {
|
||||||
this.$router.go(-1);
|
this.$router.go(-1);
|
||||||
},
|
},
|
||||||
async forwardButtonAction() {
|
async forwardButtonAction() {
|
||||||
await this.dispatchStoreAction(
|
this.displayInvalidZipAlert = false;
|
||||||
|
|
||||||
|
const validateZipResponse = this.dispatchStoreActionWithLogging(
|
||||||
|
this.storeActions.VALIDATE_ZIP,
|
||||||
|
{
|
||||||
|
zip: this.serviceZipCode,
|
||||||
|
},
|
||||||
|
this.pageName
|
||||||
|
);
|
||||||
|
|
||||||
|
const saveCustomerDetailsResponse = this.dispatchStoreAction(
|
||||||
this.storeActions.SAVE_CUSTOMER_DETAILS,
|
this.storeActions.SAVE_CUSTOMER_DETAILS,
|
||||||
{
|
{
|
||||||
firstName: this.firstName,
|
firstName: this.firstName,
|
||||||
|
|
@ -163,15 +201,45 @@ export default {
|
||||||
isSmsOptIn: this.isSmsOptIn,
|
isSmsOptIn: this.isSmsOptIn,
|
||||||
},
|
},
|
||||||
false
|
false
|
||||||
).then(() => {
|
);
|
||||||
this.$router.navigateWithPageData(
|
|
||||||
this.navigationScenarios.CLICKED_FORWARD,
|
const promiseResultMap = [
|
||||||
this.pageName,
|
{
|
||||||
|
resultKey: "validateZipResponse",
|
||||||
|
promise: validateZipResponse,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
resultKey: "saveCustomerDetailsResponse",
|
||||||
|
promise: saveCustomerDetailsResponse,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const resultMap = await settleAllPromises(promiseResultMap);
|
||||||
|
const isZipValid = resultMap.validateZipResponse.isValid;
|
||||||
|
|
||||||
|
if (isZipValid) {
|
||||||
|
await this.dispatchStoreActionWithLogging(
|
||||||
|
this.storeActions.SAVE_SERVICE_ZIP_CODE_INFO,
|
||||||
{
|
{
|
||||||
bailoutCode: this.bailoutCode,
|
zipCode: this.serviceZipCode,
|
||||||
}
|
state: resultMap.validateZipResponse.state,
|
||||||
);
|
zipCodeCtu: resultMap.validateZipResponse.zipCodeCtu,
|
||||||
});
|
},
|
||||||
|
false
|
||||||
|
).then(() => {
|
||||||
|
this.$router.navigateWithPageData(
|
||||||
|
this.navigationScenarios.CLICKED_FORWARD,
|
||||||
|
this.pageName,
|
||||||
|
{
|
||||||
|
bailoutCode: this.bailoutCode,
|
||||||
|
submit: true,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this.displayInvalidZipAlert = true;
|
||||||
|
return this.$refs.navbar.removeLoader();
|
||||||
|
}
|
||||||
},
|
},
|
||||||
arePagePrerequisitesValid() {
|
arePagePrerequisitesValid() {
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -192,6 +260,7 @@ export default {
|
||||||
Form,
|
Form,
|
||||||
funnelHeader,
|
funnelHeader,
|
||||||
funnelSubHeader,
|
funnelSubHeader,
|
||||||
|
alert,
|
||||||
navbar,
|
navbar,
|
||||||
textBlock,
|
textBlock,
|
||||||
phoneNumberQuestion,
|
phoneNumberQuestion,
|
||||||
|
|
|
||||||
|
|
@ -816,7 +816,7 @@ const routingTable = function () {
|
||||||
maps: [
|
maps: [
|
||||||
{
|
{
|
||||||
scenario: navigationScenarios.CLICKED_BACK_TO_HOMEPAGE,
|
scenario: navigationScenarios.CLICKED_BACK_TO_HOMEPAGE,
|
||||||
destinationPageData: routeData.VEHICLE,
|
destinationPageData: routeData.RESTART,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -7,13 +7,7 @@ import store from "@/store";
|
||||||
|
|
||||||
import { handleSoftError } from "@/router/methods/error";
|
import { handleSoftError } from "@/router/methods/error";
|
||||||
|
|
||||||
async function navigate(
|
async function navigate(scenario, currentPageName, withSaving = false, forceTopLevelNav = false) {
|
||||||
scenario,
|
|
||||||
currentPageName,
|
|
||||||
withSaving = false,
|
|
||||||
forceTopLevelNav = false,
|
|
||||||
bailoutCode = null
|
|
||||||
) {
|
|
||||||
// Check to see if calling page is same as current page.
|
// Check to see if calling page is same as current page.
|
||||||
// If not, cancel navigation before it begins.
|
// If not, cancel navigation before it begins.
|
||||||
const callingRoute = currentPageName;
|
const callingRoute = currentPageName;
|
||||||
|
|
@ -45,7 +39,7 @@ async function navigate(
|
||||||
store.getters?.applicationUser?.savedSessionId ||
|
store.getters?.applicationUser?.savedSessionId ||
|
||||||
store.getters?.order?.customer?.emailAddress
|
store.getters?.order?.customer?.emailAddress
|
||||||
) {
|
) {
|
||||||
await saveSession({ pageNameToLog: nextPage.name, bailoutCode: bailoutCode });
|
await saveSession({ pageNameToLog: nextPage.name });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -76,13 +70,15 @@ export async function navigateWithSaving(scenario, currentPageName) {
|
||||||
|
|
||||||
export async function navigateWithPageData(scenario, currentPageName, pageData = {}) {
|
export async function navigateWithPageData(scenario, currentPageName, pageData = {}) {
|
||||||
const nextPage = getDestination(currentPageName, scenario);
|
const nextPage = getDestination(currentPageName, scenario);
|
||||||
|
|
||||||
if (pageData && pageData.bailoutCode) {
|
if (pageData && pageData.bailoutCode) {
|
||||||
|
pageData.AppName = "FixMyGlass";
|
||||||
await savePageData(currentPageName, pageData);
|
await savePageData(currentPageName, pageData);
|
||||||
return await navigate(scenario, currentPageName, true, false, pageData.bailoutCode);
|
|
||||||
} else {
|
} else {
|
||||||
await savePageData(nextPage.name, pageData);
|
await savePageData(nextPage.name, pageData);
|
||||||
return await navigate(scenario, currentPageName, true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return await navigate(scenario, currentPageName, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function navigateAndForceTopLevelNavigation(
|
export async function navigateAndForceTopLevelNavigation(
|
||||||
|
|
|
||||||
|
|
@ -462,9 +462,11 @@ export const mutations = {
|
||||||
state.order.vehicle.registration.licensePlate = registrationInfo?.licensePlate;
|
state.order.vehicle.registration.licensePlate = registrationInfo?.licensePlate;
|
||||||
},
|
},
|
||||||
updateServiceZip(state, serviceZipInfo) {
|
updateServiceZip(state, serviceZipInfo) {
|
||||||
state.order.serviceLocation.state = serviceZipInfo.state;
|
state.order.serviceLocation.state = serviceZipInfo.state || serviceZipInfo.payload?.state;
|
||||||
state.order.serviceLocation.zipCode = serviceZipInfo.zipCode;
|
state.order.serviceLocation.zipCode =
|
||||||
state.order.serviceLocation.zipCodeCtu = serviceZipInfo.zipCodeCtu;
|
serviceZipInfo.zipCode || serviceZipInfo.payload?.zipCode;
|
||||||
|
state.order.serviceLocation.zipCodeCtu =
|
||||||
|
serviceZipInfo.zipCodeCtu || serviceZipInfo.payload?.zipCodeCtu;
|
||||||
},
|
},
|
||||||
updateServiceLocation(state, serviceLocationInfo) {
|
updateServiceLocation(state, serviceLocationInfo) {
|
||||||
state.order.serviceLocation.address = serviceLocationInfo.address;
|
state.order.serviceLocation.address = serviceLocationInfo.address;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue