Merge branch 'feature/CSR-1088' into feature/CSR-1012
This commit is contained in:
commit
823e45f054
10 changed files with 524 additions and 53 deletions
12
package-lock.json
generated
12
package-lock.json
generated
|
|
@ -19150,9 +19150,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/qs": {
|
"node_modules/qs": {
|
||||||
"version": "6.5.2",
|
"version": "6.5.3",
|
||||||
"resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz",
|
"resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz",
|
||||||
"integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==",
|
"integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=0.6"
|
"node": ">=0.6"
|
||||||
|
|
@ -39784,9 +39784,9 @@
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"qs": {
|
"qs": {
|
||||||
"version": "6.5.2",
|
"version": "6.5.3",
|
||||||
"resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz",
|
"resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz",
|
||||||
"integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==",
|
"integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"query-string": {
|
"query-string": {
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,7 @@ const storeActions = {
|
||||||
LOAD_SESSION: "loadSession",
|
LOAD_SESSION: "loadSession",
|
||||||
UPDATE_STORE_WITH_SAVE_SESSION_RESPONSE: "updateStoreWithSaveSessionResponse",
|
UPDATE_STORE_WITH_SAVE_SESSION_RESPONSE: "updateStoreWithSaveSessionResponse",
|
||||||
VALIDATE_ZIP: "validateZip",
|
VALIDATE_ZIP: "validateZip",
|
||||||
PRICE_ORDER_ITEMS: "priceOrderItems",
|
PRICE_ORDER_ITEMS_AND_SAVE_SERVER_DATA: "priceOrderItemsAndSaveServerData",
|
||||||
LOG_EXPERIMENT_EXPOSURE: "logExperimentExposure",
|
LOG_EXPERIMENT_EXPOSURE: "logExperimentExposure",
|
||||||
LOG_PAGE_VIEW: "logPageView",
|
LOG_PAGE_VIEW: "logPageView",
|
||||||
LOG_CUSTOM_EVENT: "logCustomEvent",
|
LOG_CUSTOM_EVENT: "logCustomEvent",
|
||||||
|
|
|
||||||
|
|
@ -1,23 +1,20 @@
|
||||||
import { shallowMount, flushPromises } from "@vue/test-utils";
|
import { shallowMount, flushPromises } from "@vue/test-utils";
|
||||||
import { getMountOptions } from "@/helpers/unit-test-helper.js";
|
import { getMountOptions } from "@/helpers/unit-test-helper.js";
|
||||||
import { applicationConfig } from "@/constants/application-config";
|
import { applicationConfig } from "@/constants/application-config";
|
||||||
|
import { storeActions } from "@/constants/store-actions";
|
||||||
import quote from "@/layouts/quote/quote.vue";
|
import quote from "@/layouts/quote/quote.vue";
|
||||||
import store from "@/store";
|
import store from "@/store";
|
||||||
import * as navigateToHeritage from "@/helpers/heritage-integration/navigation-helper";
|
import * as navigateToHeritage from "@/helpers/heritage-integration/navigation-helper";
|
||||||
|
import { nextTick } from "vue";
|
||||||
|
|
||||||
jest.mock("@/store", () => ({
|
jest.mock("@/store", () => ({
|
||||||
commit: jest.fn(),
|
commit: jest.fn(),
|
||||||
dispatch: jest.fn(),
|
dispatch: jest.fn(),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
// Mock our module for promises.
|
|
||||||
jest.mock("@/helpers/layout-helper.js", () => ({
|
|
||||||
settleAllPromises: jest.fn(),
|
|
||||||
}));
|
|
||||||
|
|
||||||
// Mock fetchCmsContentForPage
|
// Mock fetchCmsContentForPage
|
||||||
jest.mock("@/helpers/cms-content-helper", () => ({
|
jest.mock("@/helpers/cms-content-helper", () => ({
|
||||||
fetchCmsContentForPage: jest.fn(),
|
fetchCmsContentForPage: () => Promise.resolve("content"),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
jest.mock("@/helpers/heritage-integration/navigation-helper", () => ({
|
jest.mock("@/helpers/heritage-integration/navigation-helper", () => ({
|
||||||
|
|
@ -32,6 +29,38 @@ jest.mock(
|
||||||
{ virtual: true }
|
{ virtual: true }
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// START beforeRouteEnter mock arranging //
|
||||||
|
jest.mock("@/mixins/base-mixin", () => ({
|
||||||
|
methods: {
|
||||||
|
dispatchStoreAction(action, items, encode) {
|
||||||
|
if (action === mockPriceOrderStoreAction) return items;
|
||||||
|
else return mockStoreActionResults[action];
|
||||||
|
},
|
||||||
|
getTierOnePackagePrice() {
|
||||||
|
return mockTierOnePrice;
|
||||||
|
},
|
||||||
|
filterOutFees() {
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
let mockTierOnePrice = 501;
|
||||||
|
|
||||||
|
const mockPriceOrderStoreAction = storeActions.PRICE_ORDER_ITEMS_AND_SAVE_SERVER_DATA;
|
||||||
|
const mockStoreActionResults = {};
|
||||||
|
|
||||||
|
mockStoreActionResults[storeActions.GET_WIPERS] = Promise.resolve([
|
||||||
|
{ partNumber: "SBB24", partType: "FRONT WIPER" },
|
||||||
|
]);
|
||||||
|
mockStoreActionResults[storeActions.GET_RAIN_DEFENSE] = Promise.resolve({
|
||||||
|
partNumber: "RAIN DEFENSE",
|
||||||
|
partType: "RAIN DEFENSE",
|
||||||
|
});
|
||||||
|
mockStoreActionResults[storeActions.GET_SUPPORTING_ITEMS] = Promise.resolve([
|
||||||
|
{ partNumber: "WSREPAIR", partType: "WSREPAIR" },
|
||||||
|
]);
|
||||||
|
// END beforeRouteEnter mock arranging
|
||||||
|
|
||||||
store.getters = {
|
store.getters = {
|
||||||
order: {
|
order: {
|
||||||
accountNumber: applicationConfig.CASH_ACCOUNT_NUMBER,
|
accountNumber: applicationConfig.CASH_ACCOUNT_NUMBER,
|
||||||
|
|
@ -117,6 +146,269 @@ describe("quote.vue", () => {
|
||||||
//Assert
|
//Assert
|
||||||
expect(navigateToHeritage.navigateToHeritageFunnel).toHaveBeenCalled();
|
expect(navigateToHeritage.navigateToHeritageFunnel).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
test("should pass arePagePrerequisitesValid with a repair order", () => {
|
||||||
|
//Arrange
|
||||||
|
const { wrapper } = setupMocks({});
|
||||||
|
store.getters = {
|
||||||
|
order: {
|
||||||
|
serviceLocation: {
|
||||||
|
zipCode: "12345",
|
||||||
|
zipCodeCtu: "value",
|
||||||
|
},
|
||||||
|
damage: {
|
||||||
|
isRepair: true,
|
||||||
|
},
|
||||||
|
referralNumber: "1234567",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
let arePagePrerequisitesValid = wrapper.vm.arePagePrerequisitesValid();
|
||||||
|
|
||||||
|
expect(arePagePrerequisitesValid).toBe(true);
|
||||||
|
});
|
||||||
|
test("should pass arePagePrerequisitesValid with a replace order", () => {
|
||||||
|
//Arrange
|
||||||
|
const { wrapper } = setupMocks({});
|
||||||
|
store.getters = {
|
||||||
|
order: {
|
||||||
|
serviceLocation: {
|
||||||
|
zipCode: "12345",
|
||||||
|
zipCodeCtu: "value",
|
||||||
|
},
|
||||||
|
damage: {
|
||||||
|
isRepair: false,
|
||||||
|
},
|
||||||
|
referralNumber: "1234567",
|
||||||
|
lineItems: {
|
||||||
|
glassParts: ["item", "item2"],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
let arePagePrerequisitesValid = wrapper.vm.arePagePrerequisitesValid();
|
||||||
|
|
||||||
|
expect(arePagePrerequisitesValid).toBe(true);
|
||||||
|
});
|
||||||
|
test("should fail arePagePrerequisitesValid without glass parts or flagged as repair", () => {
|
||||||
|
//Arrange
|
||||||
|
const { wrapper } = setupMocks({});
|
||||||
|
store.getters = {
|
||||||
|
order: {
|
||||||
|
serviceLocation: {
|
||||||
|
zipCode: "12345",
|
||||||
|
zipCodeCtu: "value",
|
||||||
|
},
|
||||||
|
damage: {
|
||||||
|
isRepair: false,
|
||||||
|
},
|
||||||
|
referralNumber: "1234567",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
let arePagePrerequisitesValid = wrapper.vm.arePagePrerequisitesValid();
|
||||||
|
|
||||||
|
expect(arePagePrerequisitesValid).toBe(false);
|
||||||
|
});
|
||||||
|
test("should have non-null values for necessary data members after 'beforeRouteEnter'", async () => {
|
||||||
|
//Arrange
|
||||||
|
const { wrapper } = setupMocks({});
|
||||||
|
|
||||||
|
store.getters = {
|
||||||
|
order: {
|
||||||
|
lineItems: {
|
||||||
|
glassParts: ["item", "item2"],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
//mock this to avoid needing to populate this.$route in an unrelated test
|
||||||
|
wrapper.vm.getDefaultIsInsuranceSelectedValue = jest.fn();
|
||||||
|
|
||||||
|
//Act
|
||||||
|
await quote.beforeRouteEnter.call(
|
||||||
|
wrapper.vm,
|
||||||
|
{ query: { fmgPage: "quote" } },
|
||||||
|
undefined,
|
||||||
|
(c) => c(wrapper.vm)
|
||||||
|
);
|
||||||
|
|
||||||
|
//Assert
|
||||||
|
expect(wrapper.vm.pricedGlassParts !== null).toBe(true);
|
||||||
|
expect(wrapper.vm.supportingItems !== null).toBe(true);
|
||||||
|
expect(wrapper.vm.availableLineItems !== null).toBe(true);
|
||||||
|
// This should have its own test
|
||||||
|
//expect(vm.isInsuranceSelected !== null).toBe(true);
|
||||||
|
});
|
||||||
|
test("should default to insurance if query param 'isInsurance' is true", async () => {
|
||||||
|
//Arrange
|
||||||
|
const { wrapper } = setupMocks({});
|
||||||
|
|
||||||
|
store.getters = {
|
||||||
|
order: {
|
||||||
|
lineItems: {
|
||||||
|
glassParts: ["item", "item2"],
|
||||||
|
},
|
||||||
|
payment: {
|
||||||
|
isInsurance: null,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
wrapper.vm.$route = { query: { isInsurance: "true" } };
|
||||||
|
|
||||||
|
//Act
|
||||||
|
await quote.beforeRouteEnter.call(
|
||||||
|
wrapper.vm,
|
||||||
|
{ query: { fmgPage: "quote" } },
|
||||||
|
undefined,
|
||||||
|
(c) => c(wrapper.vm)
|
||||||
|
);
|
||||||
|
|
||||||
|
//Assert
|
||||||
|
expect(wrapper.vm.isInsuranceSelected).toBe(true);
|
||||||
|
});
|
||||||
|
test("should default to cash if query param 'isInsurance' is false", async () => {
|
||||||
|
//Arrange
|
||||||
|
const { wrapper } = setupMocks({});
|
||||||
|
|
||||||
|
store.getters = {
|
||||||
|
order: {
|
||||||
|
lineItems: {
|
||||||
|
glassParts: ["item", "item2"],
|
||||||
|
},
|
||||||
|
payment: {
|
||||||
|
isInsurance: null,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
wrapper.vm.$route = { query: { isInsurance: "false" } };
|
||||||
|
|
||||||
|
//Act
|
||||||
|
await quote.beforeRouteEnter.call(
|
||||||
|
wrapper.vm,
|
||||||
|
{ query: { fmgPage: "quote" } },
|
||||||
|
undefined,
|
||||||
|
(c) => c(wrapper.vm)
|
||||||
|
);
|
||||||
|
|
||||||
|
//Assert
|
||||||
|
expect(wrapper.vm.isInsuranceSelected).toBe(false);
|
||||||
|
});
|
||||||
|
test("should default to insurance if insurance selection is saved to store", async () => {
|
||||||
|
//Arrange
|
||||||
|
const { wrapper } = setupMocks({});
|
||||||
|
|
||||||
|
store.getters = {
|
||||||
|
order: {
|
||||||
|
lineItems: {
|
||||||
|
glassParts: ["item", "item2"],
|
||||||
|
},
|
||||||
|
payment: {
|
||||||
|
isInsurance: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
// Ensure that query param isn't overriding selection
|
||||||
|
wrapper.vm.$route = { query: null };
|
||||||
|
|
||||||
|
//Act
|
||||||
|
await quote.beforeRouteEnter.call(
|
||||||
|
wrapper.vm,
|
||||||
|
{ query: { fmgPage: "quote" } },
|
||||||
|
undefined,
|
||||||
|
(c) => c(wrapper.vm)
|
||||||
|
);
|
||||||
|
|
||||||
|
//Assert
|
||||||
|
expect(wrapper.vm.isInsuranceSelected).toBe(true);
|
||||||
|
});
|
||||||
|
test("should default to cash if cash selection is saved to store", async () => {
|
||||||
|
//Arrange
|
||||||
|
const { wrapper } = setupMocks({});
|
||||||
|
|
||||||
|
store.getters = {
|
||||||
|
order: {
|
||||||
|
lineItems: {
|
||||||
|
glassParts: ["item", "item2"],
|
||||||
|
},
|
||||||
|
payment: {
|
||||||
|
isInsurance: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
// Ensure that query param isn't overriding selection
|
||||||
|
wrapper.vm.$route = { query: null };
|
||||||
|
|
||||||
|
//Act
|
||||||
|
await quote.beforeRouteEnter.call(
|
||||||
|
wrapper.vm,
|
||||||
|
{ query: { fmgPage: "quote" } },
|
||||||
|
undefined,
|
||||||
|
(c) => c(wrapper.vm)
|
||||||
|
);
|
||||||
|
|
||||||
|
//Assert
|
||||||
|
expect(wrapper.vm.isInsuranceSelected).toBe(false);
|
||||||
|
});
|
||||||
|
test("should default to cash if total economy package price is under $500", async () => {
|
||||||
|
// Also needs no query parameter or previous selection in store to be present
|
||||||
|
//Arrange
|
||||||
|
const { wrapper } = setupMocks({});
|
||||||
|
|
||||||
|
store.getters = {
|
||||||
|
order: {
|
||||||
|
lineItems: {
|
||||||
|
glassParts: ["item", "item2"],
|
||||||
|
},
|
||||||
|
payment: {
|
||||||
|
isInsurance: null, // Ensure that previous selection isn't overriding selection
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
mockTierOnePrice = 200;
|
||||||
|
// Ensure that query param isn't overriding selection
|
||||||
|
wrapper.vm.$route = { query: null };
|
||||||
|
|
||||||
|
//Act
|
||||||
|
await quote.beforeRouteEnter.call(
|
||||||
|
wrapper.vm,
|
||||||
|
{ query: { fmgPage: "quote" } },
|
||||||
|
undefined,
|
||||||
|
(c) => c(wrapper.vm)
|
||||||
|
);
|
||||||
|
|
||||||
|
//Assert
|
||||||
|
expect(wrapper.vm.isInsuranceSelected).toBe(false);
|
||||||
|
});
|
||||||
|
test("should default to insurance if total economy package price is over $500", async () => {
|
||||||
|
// Also needs no query parameter or previous selection in store to be present
|
||||||
|
//Arrange
|
||||||
|
const { wrapper } = setupMocks({});
|
||||||
|
|
||||||
|
store.getters = {
|
||||||
|
order: {
|
||||||
|
lineItems: {
|
||||||
|
glassParts: ["item", "item2"],
|
||||||
|
},
|
||||||
|
payment: {
|
||||||
|
isInsurance: null, // Ensure that previous selection isn't overriding selection
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
mockTierOnePrice = 505;
|
||||||
|
// Ensure that query param isn't overriding selection
|
||||||
|
wrapper.vm.$route = { query: null };
|
||||||
|
|
||||||
|
//Act
|
||||||
|
await quote.beforeRouteEnter.call(
|
||||||
|
wrapper.vm,
|
||||||
|
{ query: { fmgPage: "quote" } },
|
||||||
|
undefined,
|
||||||
|
(c) => c(wrapper.vm)
|
||||||
|
);
|
||||||
|
|
||||||
|
//Assert
|
||||||
|
expect(wrapper.vm.isInsuranceSelected).toBe(true);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
function setupMocks({ customMountOptions }) {
|
function setupMocks({ customMountOptions }) {
|
||||||
|
|
@ -128,5 +420,6 @@ function setupMocks({ customMountOptions }) {
|
||||||
mountOptions["attachTo"] = document.body;
|
mountOptions["attachTo"] = document.body;
|
||||||
|
|
||||||
const wrapper = shallowMount(quote, mountOptions);
|
const wrapper = shallowMount(quote, mountOptions);
|
||||||
|
wrapper.vm.setCmsContent = jest.fn();
|
||||||
return { wrapper };
|
return { wrapper };
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -114,7 +114,7 @@ export default {
|
||||||
];
|
];
|
||||||
|
|
||||||
const pricingResults = await baseMixin.methods.dispatchStoreAction(
|
const pricingResults = await baseMixin.methods.dispatchStoreAction(
|
||||||
storeActions.PRICE_ORDER_ITEMS,
|
storeActions.PRICE_ORDER_ITEMS_AND_SAVE_SERVER_DATA,
|
||||||
availableLineItems,
|
availableLineItems,
|
||||||
false
|
false
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,6 @@
|
||||||
for="mobileLocationLinkPromptId"
|
for="mobileLocationLinkPromptId"
|
||||||
:aria-label="mobileLocationLinkPromptText"
|
:aria-label="mobileLocationLinkPromptText"
|
||||||
class="form-label fw-bold w-100 ps-4 pe-4 pt-4"
|
class="form-label fw-bold w-100 ps-4 pe-4 pt-4"
|
||||||
:class="[questionAlignment === 'center' ? 'text-center w-100 mb-5' : '']"
|
|
||||||
v-html="mobileLocationLinkPromptText"></label>
|
v-html="mobileLocationLinkPromptText"></label>
|
||||||
<div class="update-mobile-location-text-link">
|
<div class="update-mobile-location-text-link">
|
||||||
<textLink
|
<textLink
|
||||||
|
|
@ -63,7 +62,8 @@ export default {
|
||||||
return {
|
return {
|
||||||
internalModel: this.copyModel(this.modelValue),
|
internalModel: this.copyModel(this.modelValue),
|
||||||
displayInvalidZipAlert: false,
|
displayInvalidZipAlert: false,
|
||||||
mobileFee: "",
|
modalName: "MobileLocationModalWidget",
|
||||||
|
mobileFee: "",
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
|
|
@ -78,26 +78,22 @@ export default {
|
||||||
zipCode: "",
|
zipCode: "",
|
||||||
},
|
},
|
||||||
isVehicleProtected: null,
|
isVehicleProtected: null,
|
||||||
}),
|
serviceZipCode: ""
|
||||||
|
}),
|
||||||
},
|
},
|
||||||
isZipServiceableMobile: Boolean,
|
isZipServiceableMobile: Boolean,
|
||||||
isZipServiceableInShop: Boolean,
|
isZipServiceableInShop: Boolean,
|
||||||
serviceZipCode: String,
|
|
||||||
linkWidgetName: String,
|
linkWidgetName: String,
|
||||||
modalWidgetName: String,
|
modalWidgetName: String,
|
||||||
mobileFeeDisclaimerWidgetName: String,
|
|
||||||
workspaceRequirementsWidgetName: String,
|
|
||||||
alertNonServiceableZipWidgetName: String,
|
alertNonServiceableZipWidgetName: String,
|
||||||
alertInvalidZipWidgetName: String,
|
alertInvalidZipWidgetName: String,
|
||||||
},
|
},
|
||||||
async mounted() {
|
mounted() {
|
||||||
this.mobileFee = await this.getMobileFee();
|
this.getMobileFee().then((result) => {
|
||||||
|
this.mobileFee = result;
|
||||||
|
});
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
mobileFeeText() {
|
|
||||||
const cmsContentText = this.getCmsContent("MobileFeeDisclaimerWidget", "Text");
|
|
||||||
return cmsContentText.replaceAll("{custom:mobileFee}", this.mobileFee);
|
|
||||||
},
|
|
||||||
mobileLocationLinkPromptText() {
|
mobileLocationLinkPromptText() {
|
||||||
return this.getCmsContent(this.linkWidgetName, "HeaderText");
|
return this.getCmsContent(this.linkWidgetName, "HeaderText");
|
||||||
},
|
},
|
||||||
|
|
@ -119,12 +115,13 @@ export default {
|
||||||
modalHeaderText() {
|
modalHeaderText() {
|
||||||
return this.getCmsContent(this.modalWidgetName, "HeaderText");
|
return this.getCmsContent(this.modalWidgetName, "HeaderText");
|
||||||
},
|
},
|
||||||
|
mobileFeeText() {
|
||||||
|
const cmsContentText = this.getCmsContent("MobileFeeDisclaimerWidget", "Text");
|
||||||
|
return cmsContentText.replaceAll("{custom:mobileFee}", this.mobileFee);
|
||||||
|
},
|
||||||
modalFooterText() {
|
modalFooterText() {
|
||||||
return this.getCmsContent(this.modalWidgetName, "FooterText");
|
return this.getCmsContent(this.modalWidgetName, "FooterText");
|
||||||
},
|
},
|
||||||
modalName() {
|
|
||||||
return this.modalWidgetName;
|
|
||||||
},
|
|
||||||
addressModel: {
|
addressModel: {
|
||||||
get: function () {
|
get: function () {
|
||||||
return this.modelValue.addressQuestions;
|
return this.modelValue.addressQuestions;
|
||||||
|
|
@ -143,12 +140,25 @@ export default {
|
||||||
zipCode: modelToCopy.addressQuestions.zipCode,
|
zipCode: modelToCopy.addressQuestions.zipCode,
|
||||||
},
|
},
|
||||||
isVehicleProtected: modelToCopy.isVehicleProtected,
|
isVehicleProtected: modelToCopy.isVehicleProtected,
|
||||||
isZipServiceableMobile: modelToCopy.isZipServiceableMobile,
|
serviceZipCode: modelToCopy.serviceZipCode
|
||||||
isZipServiceableInShop: modelToCopy.isZipServiceableInShop,
|
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
|
setServiceZipCode(serviceZipCode) {
|
||||||
|
this.internalModel.serviceZipCode = serviceZipCode;
|
||||||
|
},
|
||||||
|
|
||||||
|
getServiceZipCodeFromStore() {
|
||||||
|
return this.$store.getters.order.serviceLocation.zipCode;
|
||||||
|
},
|
||||||
|
|
||||||
async getMobileFee() {
|
async getMobileFee() {
|
||||||
|
if (!this.internalModel.serviceZipCode) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
const zipCodeData = await this.getZipCodeData(this.internalModel.serviceZipCode);
|
||||||
|
|
||||||
// Get the Mobile Fee Part
|
// Get the Mobile Fee Part
|
||||||
const mobileFeePart = await baseMixin.methods.dispatchStoreAction(
|
const mobileFeePart = await baseMixin.methods.dispatchStoreAction(
|
||||||
storeActions.GET_MOBILE_FEE_PART,
|
storeActions.GET_MOBILE_FEE_PART,
|
||||||
|
|
@ -159,7 +169,11 @@ export default {
|
||||||
// Get the Mobile Fee Part Price
|
// Get the Mobile Fee Part Price
|
||||||
const pricingResults = await baseMixin.methods.dispatchStoreAction(
|
const pricingResults = await baseMixin.methods.dispatchStoreAction(
|
||||||
storeActions.PRICE_ORDER_ITEMS,
|
storeActions.PRICE_ORDER_ITEMS,
|
||||||
[mobileFeePart.data],
|
{
|
||||||
|
availableLineItems: [mobileFeePart.data],
|
||||||
|
serviceZipCode: zipCodeData.zipCode,
|
||||||
|
zipCodeCtu: zipCodeData.zipCodeCtu
|
||||||
|
},
|
||||||
false
|
false
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -206,7 +220,15 @@ export default {
|
||||||
this.displayInvalidZipAlert = true;
|
this.displayInvalidZipAlert = true;
|
||||||
} else {
|
} else {
|
||||||
// Update the page level model
|
// Update the page level model
|
||||||
|
this.internalModel.serviceZipCode = this.internalModel.addressQuestions.zipCode;
|
||||||
this.$emit("update:modelValue", this.internalModel);
|
this.$emit("update:modelValue", this.internalModel);
|
||||||
|
|
||||||
|
// Emit the update service zip code information to the parent to update the service zipcode details
|
||||||
|
this.$emit("updated-zip-code", {
|
||||||
|
zipCode: this.internalModel.addressQuestions.zipCode,
|
||||||
|
state: zipCodeData.state,
|
||||||
|
isServiceable: zipCodeData.isServiceable
|
||||||
|
});
|
||||||
|
|
||||||
this.closeModal();
|
this.closeModal();
|
||||||
}
|
}
|
||||||
|
|
@ -216,6 +238,11 @@ export default {
|
||||||
modelValue(newValue) {
|
modelValue(newValue) {
|
||||||
this.internalModel = this.copyModel(newValue);
|
this.internalModel = this.copyModel(newValue);
|
||||||
},
|
},
|
||||||
|
"modelValue.serviceZipCode": {
|
||||||
|
async handler(newValue) {
|
||||||
|
this.mobileFee = await this.getMobileFee(newValue);
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
textLink,
|
textLink,
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,131 @@
|
||||||
describe("service-location.vue", () => {
|
// Components
|
||||||
test.todo("test this");
|
import serviceLocation from "@/layouts/service-location/service-location.vue";
|
||||||
|
|
||||||
|
// Supporting files
|
||||||
|
import { shallowMount } from "@vue/test-utils";
|
||||||
|
import { getMountOptions } from "@/helpers/unit-test-helper";
|
||||||
|
import baseMixin from "@/mixins/base-mixin";
|
||||||
|
import { nextTick } from "vue";
|
||||||
|
import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
|
||||||
|
import { settleAllPromises } from "@/helpers/layout-helper.js";
|
||||||
|
import store from "@/store";
|
||||||
|
|
||||||
|
// Define Mocks
|
||||||
|
jest.mock("@/helpers/layout-helper.js", () => ({
|
||||||
|
settleAllPromises: jest.fn(),
|
||||||
|
}));
|
||||||
|
|
||||||
|
jest.mock("@/helpers/cms-content-helper", () => ({
|
||||||
|
fetchCmsContentForPage: jest.fn(),
|
||||||
|
}));
|
||||||
|
|
||||||
|
jest.mock("@/store", () => ({
|
||||||
|
commit: jest.fn(),
|
||||||
|
dispatch: jest.fn(),
|
||||||
|
getters: {
|
||||||
|
lineItems: {
|
||||||
|
supportingItems: [
|
||||||
|
{
|
||||||
|
description: null,
|
||||||
|
kitPrice: 0,
|
||||||
|
laborAmount: 0,
|
||||||
|
partNumber: "SUPPLIES-REPAIR",
|
||||||
|
partType: "REPAIR FEE",
|
||||||
|
sellingPrice: 7.99,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
order: {
|
||||||
|
serviceLocation: {
|
||||||
|
zipCode: "43235",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
payment: {
|
||||||
|
isInsurance: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
store.getters = {
|
||||||
|
lineItems: {
|
||||||
|
supportingItems: [
|
||||||
|
{
|
||||||
|
description: null,
|
||||||
|
kitPrice: 0,
|
||||||
|
laborAmount: 0,
|
||||||
|
partNumber: "SUPPLIES-REPAIR",
|
||||||
|
partType: "REPAIR FEE",
|
||||||
|
sellingPrice: 7.99,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
order: {
|
||||||
|
serviceLocation: {
|
||||||
|
zipCode: "43235",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
payment: {
|
||||||
|
isInsurance: false,
|
||||||
|
},
|
||||||
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("service-location.vue", () => {
|
||||||
|
describe("arePagePrerequisitesValid", () => {
|
||||||
|
test("No prerequisites set: Should return false.", () => {
|
||||||
|
const { wrapper } = setupMocks({});
|
||||||
|
|
||||||
|
store.getters = {
|
||||||
|
lineItems: {
|
||||||
|
supportingItems: null,
|
||||||
|
},
|
||||||
|
order: {
|
||||||
|
serviceLocation: {
|
||||||
|
zipCode: null,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
payment: {
|
||||||
|
isInsurance: null,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
let arePagePrerequisitesValid = wrapper.vm.arePagePrerequisitesValid();
|
||||||
|
|
||||||
|
expect(arePagePrerequisitesValid).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("All prerequisites set: Should return true.", () => {
|
||||||
|
const { wrapper } = setupMocks({});
|
||||||
|
|
||||||
|
let arePagePrerequisitesValid = wrapper.vm.arePagePrerequisitesValid();
|
||||||
|
|
||||||
|
expect(arePagePrerequisitesValid).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Some prerequisites set: Should return false.", () => {
|
||||||
|
const { wrapper } = setupMocks({});
|
||||||
|
|
||||||
|
store.getters.order.serviceLocation.zipCode = null;
|
||||||
|
|
||||||
|
let arePagePrerequisitesValid = wrapper.vm.arePagePrerequisitesValid();
|
||||||
|
|
||||||
|
expect(arePagePrerequisitesValid).toBe(false);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
function setupMocks({ mountOptionsMockData = {} }) {
|
||||||
|
const apiResponses = {};
|
||||||
|
|
||||||
|
const apiPromise = Promise.resolve(apiResponses);
|
||||||
|
|
||||||
|
settleAllPromises.mockImplementation(() => apiPromise);
|
||||||
|
fetchCmsContentForPage.mockImplementation(() => Promise.resolve());
|
||||||
|
|
||||||
|
const mountOptions = getMountOptions(mountOptionsMockData);
|
||||||
|
const wrapper = shallowMount(serviceLocation, mountOptions);
|
||||||
|
wrapper.vm.setCmsContent = baseMixin.methods.setCmsContent;
|
||||||
|
|
||||||
|
return { wrapper, apiPromise };
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,16 +6,15 @@
|
||||||
<funnelSubHeader cmsWidgetName="FunnelSubHeaderWidget" />
|
<funnelSubHeader cmsWidgetName="FunnelSubHeaderWidget" />
|
||||||
<serviceZipModalQuestion
|
<serviceZipModalQuestion
|
||||||
v-model="serviceZipCodeQuestion"
|
v-model="serviceZipCodeQuestion"
|
||||||
@service-zip-updated="resetMobileLocation"
|
ref="serviceZipCodeQuestion"
|
||||||
linkWidgetName="ServiceZipLinkWidget"
|
linkWidgetName="ServiceZipLinkWidget"
|
||||||
modalWidgetName="ServiceZipModalWidget" />
|
modalWidgetName="ServiceZipModalWidget" />
|
||||||
<mobileLocationModalQuestions
|
<mobileLocationModalQuestions
|
||||||
v-model="mobileLocationQuestions"
|
v-model="mobileLocationQuestions"
|
||||||
|
@updated-zip-code="resetServiceZipCode"
|
||||||
ref="mobileLocationModalQuestions"
|
ref="mobileLocationModalQuestions"
|
||||||
linkWidgetName="MobileLocationLinkWidget"
|
linkWidgetName="MobileLocationLinkWidget"
|
||||||
modalWidgetName="MobileLocationModalWidget"
|
modalWidgetName="MobileLocationModalWidget" />
|
||||||
mobileFeeDisclaimerWidgetName="MobileFeeDisclaimerWidget"
|
|
||||||
workspaceRequirementsWidgetName="WorkspaceRequirementsWidget" />
|
|
||||||
<funnel-footer
|
<funnel-footer
|
||||||
cmsWidgetName="FunnelFooterWidget"
|
cmsWidgetName="FunnelFooterWidget"
|
||||||
ref="funnelFooter"
|
ref="funnelFooter"
|
||||||
|
|
@ -60,6 +59,7 @@ export default {
|
||||||
zipCode: this.getRegistrationZipFromStore(),
|
zipCode: this.getRegistrationZipFromStore(),
|
||||||
},
|
},
|
||||||
isVehicleProtected: null,
|
isVehicleProtected: null,
|
||||||
|
serviceZipCode: this.getServiceZipCodeFromStore(),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
@ -86,7 +86,11 @@ export default {
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
arePagePrerequisitesValid() {
|
arePagePrerequisitesValid() {
|
||||||
return true;
|
return (
|
||||||
|
store.getters.lineItems.supportingItems !== null &&
|
||||||
|
store.getters.order.serviceLocation.zipCode !== null &&
|
||||||
|
store.getters.payment.isInsurance !== null
|
||||||
|
);
|
||||||
},
|
},
|
||||||
getRegistrationAddressFromStore() {
|
getRegistrationAddressFromStore() {
|
||||||
return this.$store.getters.vehicle.registration.address;
|
return this.$store.getters.vehicle.registration.address;
|
||||||
|
|
@ -109,7 +113,7 @@ export default {
|
||||||
getIsServiceableFromStore() {
|
getIsServiceableFromStore() {
|
||||||
return this.$store.getters.order.serviceLocation.isServiceable;
|
return this.$store.getters.order.serviceLocation.isServiceable;
|
||||||
},
|
},
|
||||||
resetMobileLocation() {
|
resetMobileLocation(updatedServiceZipCode) {
|
||||||
this.mobileLocationQuestions = {
|
this.mobileLocationQuestions = {
|
||||||
addressQuestions: {
|
addressQuestions: {
|
||||||
streetAddress: "",
|
streetAddress: "",
|
||||||
|
|
@ -119,10 +123,16 @@ export default {
|
||||||
zipCode: "",
|
zipCode: "",
|
||||||
},
|
},
|
||||||
isVehicleProtected: null,
|
isVehicleProtected: null,
|
||||||
|
serviceZipCode: updatedServiceZipCode,
|
||||||
};
|
};
|
||||||
|
|
||||||
this.$refs.mobileLocationModalQuestions.resetComponent();
|
this.$refs.mobileLocationModalQuestions.resetComponent();
|
||||||
},
|
},
|
||||||
|
resetServiceZipCode(newValue) {
|
||||||
|
this.serviceZipCodeQuestion.state = newValue.state;
|
||||||
|
this.serviceZipCodeQuestion.zipCode = newValue.zipCode;
|
||||||
|
this.serviceZipCodeQuestion.isServiceable = newValue.isServiceable;
|
||||||
|
},
|
||||||
backButtonAction() {
|
backButtonAction() {
|
||||||
this.$router.navigateWithoutSaving(this.navigationScenarios.CLICKED_BACK, this.$route);
|
this.$router.navigateWithoutSaving(this.navigationScenarios.CLICKED_BACK, this.$route);
|
||||||
},
|
},
|
||||||
|
|
@ -130,6 +140,15 @@ export default {
|
||||||
navigateToHeritageFunnel({ loadingModal: this.$refs.loadingModal });
|
navigateToHeritageFunnel({ loadingModal: this.$refs.loadingModal });
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
watch: {
|
||||||
|
serviceZipCodeQuestion: {
|
||||||
|
handler(newValue, oldValue) {
|
||||||
|
if (newValue !== oldValue) {
|
||||||
|
this.resetMobileLocation(newValue.zipCode);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
components: {
|
components: {
|
||||||
serviceZipModalQuestion,
|
serviceZipModalQuestion,
|
||||||
mobileLocationModalQuestions,
|
mobileLocationModalQuestions,
|
||||||
|
|
|
||||||
|
|
@ -139,11 +139,6 @@ export default {
|
||||||
this.internalModel.state = zipCodeData.state;
|
this.internalModel.state = zipCodeData.state;
|
||||||
this.internalModel.isServiceable = zipCodeData.isServiceable;
|
this.internalModel.isServiceable = zipCodeData.isServiceable;
|
||||||
|
|
||||||
// Notify the page that the service zip has been updated to clear Mobile Location form
|
|
||||||
if (this.internalModel.zipCode !== this.modelValue.zipCode) {
|
|
||||||
this.$emit("service-zip-updated");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update the page level model
|
// Update the page level model
|
||||||
this.$emit("update:modelValue", this.internalModel);
|
this.$emit("update:modelValue", this.internalModel);
|
||||||
|
|
||||||
|
|
@ -152,14 +147,14 @@ export default {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
|
modelValue(newValue) {
|
||||||
|
this.internalModel = this.copyModel(newValue);
|
||||||
|
},
|
||||||
"internalModel.zipCode": {
|
"internalModel.zipCode": {
|
||||||
handler() {
|
handler() {
|
||||||
this.resetsOnZipInput();
|
this.resetsOnZipInput();
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
modelValue(newValue) {
|
|
||||||
this.internalModel = this.copyModel(newValue);
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
textLink,
|
textLink,
|
||||||
|
|
|
||||||
|
|
@ -1423,24 +1423,34 @@ export const actions = {
|
||||||
context.commit(storeMutations.UPDATE_VAPS, vaps);
|
context.commit(storeMutations.UPDATE_VAPS, vaps);
|
||||||
},
|
},
|
||||||
// Price order actions
|
// Price order actions
|
||||||
async priceOrderItems(context, availableLineItems) {
|
async priceOrderItemsAndSaveServerData(context, { availableLineItems, serviceZipCode, ctu }) {
|
||||||
|
const zipCodeToUse = serviceZipCode
|
||||||
|
? serviceZipCode
|
||||||
|
: context.getters.order.serviceLocation.zipCode;
|
||||||
|
const ctuToUse = ctu ? ctu : context.getters.order.serviceLocation.zipCodeCtu;
|
||||||
|
|
||||||
const availableLineItemsFormattedForRequest =
|
const availableLineItemsFormattedForRequest =
|
||||||
getLineItemQueryStringForPricing(availableLineItems);
|
getLineItemQueryStringForPricing(availableLineItems);
|
||||||
|
|
||||||
const vehicle = context.getters.order.vehicle;
|
const vehicle = context.getters.order.vehicle;
|
||||||
|
|
||||||
let queryString =
|
let queryString =
|
||||||
`ParentAccountNumber=${applicationConfig.CASH_ACCOUNT_NUMBER}` +
|
`ParentAccountNumber=${applicationConfig.CASH_ACCOUNT_NUMBER}` +
|
||||||
`&CTU=${context.getters.order.serviceLocation.zipCodeCtu}` +
|
`&CTU=${ctuToUse}` +
|
||||||
`&CarId=${vehicle.carId}` +
|
`&CarId=${vehicle.carId}` +
|
||||||
`&Make=${vehicle.make}` +
|
`&Make=${vehicle.make}` +
|
||||||
`&Model=${vehicle.model}` +
|
`&Model=${vehicle.model}` +
|
||||||
`&Year=${vehicle.year}` +
|
`&Year=${vehicle.year}` +
|
||||||
`&EON=${context.getters.order.eon}` +
|
`&EON=${context.getters.order.eon}` +
|
||||||
`&ZipCode=${context.getters.order.serviceLocation.zipCode}` +
|
`&ZipCode=${zipCodeToUse}` +
|
||||||
`${availableLineItemsFormattedForRequest}`;
|
`${availableLineItemsFormattedForRequest}`;
|
||||||
|
|
||||||
const lineItemServerData = context.getters.order.lineItems.serverData;
|
const lineItemServerData = context.getters.order.lineItems.serverData;
|
||||||
|
|
||||||
if (lineItemServerData) {
|
if (lineItemServerData) {
|
||||||
queryString += `&ServerData=${encodeURIComponent(lineItemServerData)}`;
|
queryString += `&ServerData=${encodeURIComponent(lineItemServerData)}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
const response = await globalMethods.callHttpClient({
|
const response = await globalMethods.callHttpClient({
|
||||||
method: endpoints.PriceOrderItems.method,
|
method: endpoints.PriceOrderItems.method,
|
||||||
endpoint: `${endpoints.PriceOrderItems.url}?${queryString}`,
|
endpoint: `${endpoints.PriceOrderItems.url}?${queryString}`,
|
||||||
|
|
|
||||||
|
|
@ -47,7 +47,6 @@ export default {
|
||||||
true
|
true
|
||||||
);
|
);
|
||||||
if (!this.isDisabled) {
|
if (!this.isDisabled) {
|
||||||
console.log("I'm here");
|
|
||||||
this.isLoaderDisplayed = true;
|
this.isLoaderDisplayed = true;
|
||||||
this.$emit("click-event");
|
this.$emit("click-event");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue