Merge branch 'develop' into feature/CSR-1373

This commit is contained in:
Chloe Herd 2023-08-22 15:39:32 -04:00
commit 8445e7fd4e
32 changed files with 167 additions and 2191 deletions

View file

@ -0,0 +1 @@
export const payWithInsuranceStates = ["AZ", "CT", "FL", "KY", "MA", "MN", "NY", "SC"];

View file

@ -58,10 +58,6 @@ const storeActions = {
RESET_STATE: "resetState",
// SAVE COMPONENT STATE
SAVE_VEHICLE_YEAR: "saveVehicleYear",
SAVE_VEHICLE_MAKE: "saveVehicleMake",
SAVE_VEHICLE_MODEL: "saveVehicleModel",
SAVE_VEHICLE_STYLE: "saveVehicleStyle",
SAVE_VEHICLE: "saveVehicle",
SAVE_VEHICLE_DAMAGE: "saveVehicleDamage",
SAVE_VIN_LOOKUP: "saveVinLookup",
@ -87,6 +83,7 @@ const storeActions = {
SAVE_VAPS: "saveVaps",
SAVE_CUSTOMER_DETAILS: "saveCustomerDetails",
SAVE_SERVICE_LOCATION_TECH_NOTES: "saveServiceLocationTechNotes",
SAVE_WORK_ORDER_FLAG: "saveWorkOrderFlag",
};
export { storeActions };

View file

@ -1,4 +1,6 @@
const storeMutations = {
UPDATE_WORK_ORDER_FLAG: "updateWorkOrderFlag",
// VEHICLE MUTATIONS
UPDATE_YEAR: "updateYear",
UPDATE_MAKE: "updateMake",

View file

@ -18,6 +18,7 @@ describe("vehicleBanner", () => {
const { wrapper } = setupMocks({
displayGenericVehicleImageProp: true,
imageUrlValue: "NULL",
displayUnmatchedVehicleIconProp: true,
});
// Assert
@ -87,7 +88,12 @@ describe("vehicleBanner", () => {
);
});
function setupMocks({ displayGenericVehicleImageProp, imageUrlValue, categoryValue = "CAR" }) {
function setupMocks({
displayGenericVehicleImageProp,
displayUnmatchedVehicleIconProp,
imageUrlValue,
categoryValue = "CAR",
}) {
const mockGetCmsContent = jest.fn();
mockGetCmsContent((cmsWidget, field) => {
return field;
@ -108,7 +114,10 @@ function setupMocks({ displayGenericVehicleImageProp, imageUrlValue, categoryVal
});
//Mock props
mountOptions.propsData = { displayGenericVehicleImage: displayGenericVehicleImageProp };
mountOptions.propsData = {
displayGenericVehicleImage: displayGenericVehicleImageProp,
displayUnmatchedVehicleIconProp: displayUnmatchedVehicleIconProp,
};
mountOptions.mixins = [mockMixin];
const wrapper = shallowMount(vehicleBanner, mountOptions);

View file

@ -18,6 +18,16 @@ export default {
required: false,
default: null,
},
displayUnmatchedVehicleIcon: {
type: Boolean,
required: false,
default: false,
},
vehicleCategory: {
type: String,
required: false,
default: null,
},
},
computed: {
vehicleImageToDisplay() {
@ -29,7 +39,8 @@ export default {
}
if (
this.$store.getters.vehicle.imageUrl === null ||
this.$store.getters.vehicle.imageUrl === "NULL"
this.$store.getters.vehicle.imageUrl === "NULL" ||
this.displayUnmatchedVehicleIcon
) {
return this.getUnmatchedVehicleIcon();
}
@ -57,7 +68,8 @@ export default {
},
methods: {
getUnmatchedVehicleIcon() {
switch (this.$store.getters.vehicle.category) {
const category = this.vehicleCategory ?? this.$store.getters.vehicle.category;
switch (category) {
case this.vehicleCategories.CAR:
return this.carUnmatchedVehicleIcon;
case this.vehicleCategories.SUV:

View file

@ -103,9 +103,6 @@ async function getLatestPageForRedirection() {
// If this is a non-CTA navigation, determine where to send the user based on page prerequisites.
// This also works if a user has a 'fmg' start_type query string but no current order.
// That shouldn't happen, but it's possible.
const vehicleMakeComponent = await getLazyLoadedComponent(fmgPageValues.VEHICLE_MAKE);
const vehicleModelComponent = await getLazyLoadedComponent(fmgPageValues.VEHICLE_MODEL);
const vehicleStyleComponent = await getLazyLoadedComponent(fmgPageValues.VEHICLE_STYLE);
const vehicleDamageComponent = await getLazyLoadedComponent(fmgPageValues.VEHICLE_DAMAGE);
const estimateComponent = await getLazyLoadedComponent(fmgPageValues.ESTIMATE);
const vinLookupComponent = await getLazyLoadedComponent(fmgPageValues.VIN_LOOKUP);
@ -121,14 +118,8 @@ async function getLatestPageForRedirection() {
const skipVin = await skipVinLookup();
if (!vehicleMakeComponent.methods.arePagePrerequisitesValid()) {
return fmgPageValues.VEHICLE_YEAR;
} else if (!vehicleModelComponent.methods.arePagePrerequisitesValid()) {
return fmgPageValues.VEHICLE_MAKE;
} else if (!vehicleStyleComponent.methods.arePagePrerequisitesValid()) {
return fmgPageValues.VEHICLE_MODEL;
} else if (!vehicleDamageComponent.methods.arePagePrerequisitesValid()) {
return fmgPageValues.VEHICLE_STYLE;
if (!vehicleDamageComponent.methods.arePagePrerequisitesValid()) {
return fmgPageValues.VEHICLE;
} else if (!estimateComponent.methods.arePagePrerequisitesValid()) {
return fmgPageValues.VEHICLE_DAMAGE;
} else {
@ -170,10 +161,7 @@ function overrideYmmsDirectionIfNeeded(toRoute) {
if (store.getters.payment.insuranceCoverage.isVerified) {
switch (fmgPageValue) {
case fmgPageValues.VEHICLE_YEAR:
case fmgPageValues.VEHICLE_MAKE:
case fmgPageValues.VEHICLE_MODEL:
case fmgPageValues.VEHICLE_STYLE: {
case fmgPageValues.VEHICLE: {
return fmgPageValues.VEHICLE_DAMAGE;
}
default: {

View file

@ -20,7 +20,7 @@ jest.mock("@/router/dynamic-routing/component-loader.js", () => ({
}));
describe("getPageToRouteExistingOrderTo", () => {
test("should return vehicle-year", async () => {
test("should return vehicle", async () => {
// Arrange
const toRoute = {
query: {},
@ -31,75 +31,7 @@ describe("getPageToRouteExistingOrderTo", () => {
// Mock out the lazy load calls for all components.
mockLazyLoadComponentReturnValues({
[fmgPageValues.VEHICLE_MAKE]: false,
});
// Act
const result = await getPageToRouteExistingOrderTo(toRoute, false);
//Assert
expect(result).toBe(fmgPageValues.VEHICLE_YEAR);
});
test("should return vehicle-make", async () => {
// Arrange
const toRoute = {
query: {},
};
store.commit(storeMutations.UPDATE_IS_REPAIR, false);
store.commit(storeMutations.UPDATE_MAKE, "acura");
// Mock out the lazy load calls for all components.
mockLazyLoadComponentReturnValues({
[fmgPageValues.VEHICLE_MAKE]: true,
[fmgPageValues.VEHICLE_MODEL]: false,
});
// Act
const result = await getPageToRouteExistingOrderTo(toRoute, false);
//Assert
expect(result).toBe(fmgPageValues.VEHICLE_MAKE);
});
test("should return vehicle-model", async () => {
// Arrange
const toRoute = {
query: {},
};
store.commit(storeMutations.UPDATE_IS_REPAIR, false);
store.commit(storeMutations.UPDATE_MAKE, "acura");
// Mock out the lazy load calls for all components.
mockLazyLoadComponentReturnValues({
[fmgPageValues.VEHICLE_MAKE]: true,
[fmgPageValues.VEHICLE_MODEL]: true,
[fmgPageValues.VEHICLE_STYLE]: false,
});
// Act
const result = await getPageToRouteExistingOrderTo(toRoute, false);
//Assert
expect(result).toBe(fmgPageValues.VEHICLE_MODEL);
});
test("should return vehicle-style", async () => {
// Arrange
const toRoute = {
query: {},
};
store.commit(storeMutations.UPDATE_IS_REPAIR, false);
store.commit(storeMutations.UPDATE_MAKE, "acura");
// Mock out the lazy load calls for all components.
mockLazyLoadComponentReturnValues({
[fmgPageValues.VEHICLE_MAKE]: true,
[fmgPageValues.VEHICLE_MODEL]: true,
[fmgPageValues.VEHICLE_STYLE]: true,
[fmgPageValues.VEHICLE]: true,
[fmgPageValues.VEHICLE_DAMAGE]: false,
});
@ -107,7 +39,7 @@ describe("getPageToRouteExistingOrderTo", () => {
const result = await getPageToRouteExistingOrderTo(toRoute, false);
//Assert
expect(result).toBe(fmgPageValues.VEHICLE_STYLE);
expect(result).toBe(fmgPageValues.VEHICLE);
});
test("should return vehicle-damage", async () => {
@ -121,9 +53,7 @@ describe("getPageToRouteExistingOrderTo", () => {
// Mock out the lazy load calls for all components.
mockLazyLoadComponentReturnValues({
[fmgPageValues.VEHICLE_MAKE]: true,
[fmgPageValues.VEHICLE_MODEL]: true,
[fmgPageValues.VEHICLE_STYLE]: true,
[fmgPageValues.VEHICLE]: true,
[fmgPageValues.VEHICLE_DAMAGE]: true,
[fmgPageValues.ESTIMATE]: false,
});
@ -156,9 +86,7 @@ describe("getPageToRouteExistingOrderTo", () => {
// Mock out the lazy load calls for all components.
mockLazyLoadComponentReturnValues({
[fmgPageValues.VEHICLE_MAKE]: true,
[fmgPageValues.VEHICLE_MODEL]: true,
[fmgPageValues.VEHICLE_STYLE]: true,
[fmgPageValues.VEHICLE]: true,
[fmgPageValues.VEHICLE_DAMAGE]: true,
[fmgPageValues.ESTIMATE]: true,
[fmgPageValues.CAPABILITY_QUESTIONS]: false,
@ -186,9 +114,7 @@ describe("getPageToRouteExistingOrderTo", () => {
// Mock out the lazy load calls for all components.
mockLazyLoadComponentReturnValues({
[fmgPageValues.VEHICLE_MAKE]: true,
[fmgPageValues.VEHICLE_MODEL]: true,
[fmgPageValues.VEHICLE_STYLE]: true,
[fmgPageValues.VEHICLE]: true,
[fmgPageValues.VEHICLE_DAMAGE]: true,
[fmgPageValues.ESTIMATE]: true,
[fmgPageValues.CAPABILITY_QUESTIONS]: false,
@ -216,9 +142,7 @@ describe("getPageToRouteExistingOrderTo", () => {
// Mock out the lazy load calls for all components.
mockLazyLoadComponentReturnValues({
[fmgPageValues.VEHICLE_MAKE]: true,
[fmgPageValues.VEHICLE_MODEL]: true,
[fmgPageValues.VEHICLE_STYLE]: true,
[fmgPageValues.VEHICLE]: true,
[fmgPageValues.VEHICLE_DAMAGE]: true,
[fmgPageValues.ESTIMATE]: true,
[fmgPageValues.CAPABILITY_QUESTIONS]: true,
@ -246,9 +170,7 @@ describe("getPageToRouteExistingOrderTo", () => {
// Mock out the lazy load calls for all components.
mockLazyLoadComponentReturnValues({
[fmgPageValues.VEHICLE_MAKE]: true,
[fmgPageValues.VEHICLE_MODEL]: true,
[fmgPageValues.VEHICLE_STYLE]: true,
[fmgPageValues.VEHICLE]: true,
[fmgPageValues.VEHICLE_DAMAGE]: true,
[fmgPageValues.ESTIMATE]: true,
[fmgPageValues.CAPABILITY_QUESTIONS]: false,
@ -276,9 +198,7 @@ describe("getPageToRouteExistingOrderTo", () => {
// Mock out the lazy load calls for all components.
mockLazyLoadComponentReturnValues({
[fmgPageValues.VEHICLE_MAKE]: true,
[fmgPageValues.VEHICLE_MODEL]: true,
[fmgPageValues.VEHICLE_STYLE]: true,
[fmgPageValues.VEHICLE]: true,
[fmgPageValues.VEHICLE_DAMAGE]: true,
[fmgPageValues.ESTIMATE]: true,
[fmgPageValues.CAPABILITY_QUESTIONS]: false,
@ -306,9 +226,7 @@ describe("getPageToRouteExistingOrderTo", () => {
// Mock out the lazy load calls for all components.
mockLazyLoadComponentReturnValues({
[fmgPageValues.VEHICLE_MAKE]: true,
[fmgPageValues.VEHICLE_MODEL]: true,
[fmgPageValues.VEHICLE_STYLE]: true,
[fmgPageValues.VEHICLE]: true,
[fmgPageValues.VEHICLE_DAMAGE]: true,
[fmgPageValues.ESTIMATE]: true,
[fmgPageValues.CAPABILITY_QUESTIONS]: false,

View file

@ -163,6 +163,7 @@ export default {
false
);
this.dispatchStoreAction(this.storeActions.SAVE_WORK_ORDER_FLAG, true, false);
this.$router.navigateWithSaving(this.navigationScenarios.CLICKED_FORWARD, this.$route);
},
},

View file

@ -263,6 +263,9 @@ describe("quote.vue", () => {
payment: {
isInsurance: null,
},
serviceLocation: {
state: null,
},
},
};
wrapper.vm.$route = { query: { isInsurance: "true" } };
@ -290,6 +293,9 @@ describe("quote.vue", () => {
payment: {
isInsurance: null,
},
serviceLocation: {
state: null,
},
},
};
wrapper.vm.$route = { query: { isInsurance: "false" } };
@ -317,6 +323,9 @@ describe("quote.vue", () => {
payment: {
isInsurance: true,
},
serviceLocation: {
state: null,
},
},
};
// Ensure that query param isn't overriding selection
@ -345,6 +354,9 @@ describe("quote.vue", () => {
payment: {
isInsurance: false,
},
serviceLocation: {
state: null,
},
},
};
// Ensure that query param isn't overriding selection
@ -374,6 +386,9 @@ describe("quote.vue", () => {
payment: {
isInsurance: null, // Ensure that previous selection isn't overriding selection
},
serviceLocation: {
state: null,
},
},
};
mockTierOnePrice = 200;
@ -404,6 +419,9 @@ describe("quote.vue", () => {
payment: {
isInsurance: null, // Ensure that previous selection isn't overriding selection
},
serviceLocation: {
state: null,
},
},
};
mockTierOnePrice = 505;
@ -421,6 +439,33 @@ describe("quote.vue", () => {
//Assert
expect(wrapper.vm.isInsuranceSelected).toBe(true);
});
test("Should default to insurence if user Service zip is from certain States", async () => {
//Arrange
const { wrapper } = setupMocks({});
store.getters = {
order: {
lineItems: {
glassParts: ["item", "item2"],
},
payment: {
isInsurance: null,
},
serviceLocation: {
state: "AZ",
},
},
};
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 }) {

View file

@ -67,7 +67,7 @@ import { errorMessages } from "@/constants/error-messages";
import { Form, defineRule } from "vee-validate";
import { navigateToHeritageFunnel } from "@/helpers/heritage-integration/navigation-helper";
import { applicationConfig } from "@/constants/application-config";
import { payWithInsuranceStates } from "@/constants/pay-with-insurance-states";
defineRule("option-required", required(errorMessages.OPTION_REQUIRED));
export default {
@ -154,11 +154,18 @@ export default {
);
},
getDefaultIsInsuranceSelectedValue(availableLineItems) {
const serviceLocationState = store.getters.order.serviceLocation.state;
// Override if coming back from QuoteDetails. Remove override after Quote release
const isInsuranceOverrideValue = this.$route.query?.isInsurance;
const defaultIsInsuranceSelectedValue = this.$store.getters.order.payment.isInsurance;
if (isInsuranceOverrideValue != null) {
//Default to Insurance Tab if user Service zip is from certain States
if (
serviceLocationState != null &&
payWithInsuranceStates.find((item) => item === serviceLocationState)
)
return true;
else if (isInsuranceOverrideValue != null) {
return isInsuranceOverrideValue == "true";
} else if (defaultIsInsuranceSelectedValue != null) {
return defaultIsInsuranceSelectedValue;

View file

@ -1,79 +0,0 @@
import makeQuestion from "@/layouts/vehicle-make/make-question/make-question";
import { shallowMount } from "@vue/test-utils";
import { getMountOptions } from "@/helpers/unit-test-helper.js";
import store from "@/store";
jest.mock(
"@/store",
() => {
return {};
},
{ virtual: true }
);
describe("make-question.vue", () => {
test("Selected make is emitted upon selection.", async () => {
//Arrange
const { wrapper } = setupMocks({ modelValueProp: "honda" });
const makeToSelect = "ford";
//Act
wrapper.setValue({ selectedMake: makeToSelect });
await wrapper.vm.$nextTick();
//Assert
expect(wrapper.emitted()["update:modelValue"][0]).toEqual([{ selectedMake: "ford" }]);
});
});
describe("make-question.vue", () => {
test("Data from store api are used as radio question answers.", async () => {
//Arrange
const { wrapper, cmsContent } = setupMocks({
dataFromStoreApi: ["honda", "ford", "dodge"],
});
//Act
const initialData = makeQuestion.methods.loadInitialData.call(wrapper.vm);
makeQuestion.methods.initializeComponent.call(wrapper.vm, initialData);
//Assert
const buttonQuestionComponent = await wrapper.findComponent({
name: "buttonQuestion",
});
expect(buttonQuestionComponent.attributes("answers")).toBe("honda,ford,dodge");
});
});
function setupMocks({
modelValueProp = "1900",
cmsQuestionText = "CMS text goes here",
dataFromStoreApi = [],
}) {
//Mock store
store.dispatch = jest.fn(() => dataFromStoreApi);
store.getters = { vehicle: { year: 2019 } };
const mountOptions = getMountOptions({
store: {
dispatch: store.dispatch,
getters: store.getters,
},
});
//Mock props
const mockMixin = {
methods: {
getCmsContent: jest.fn(),
},
};
mountOptions.propsData = {
modelValue: modelValueProp,
};
mountOptions.mixins = [mockMixin];
const wrapper = shallowMount(makeQuestion, mountOptions);
//Mock CMS content
const cmsContent = {
QuestionText: cmsQuestionText,
};
return { wrapper, cmsContent };
}

View file

@ -1,59 +0,0 @@
<template>
<buttonQuestion
class="radioQuestion"
isOverflowScrollable
selectingInitiatesLoad
:questionText="questionText"
:answers="makes"
groupName="ChooseVehicleMake"
textPosition="text-start"
v-model="selectedValue"
isRequired />
</template>
<script>
import buttonQuestion from "@/digital-components/button-question/button-question";
// Supporting files
import store from "@/store";
import { storeActions } from "@/constants/store-actions.js";
import baseMixin from "@/mixins/base-mixin.js";
export default {
name: "make-question",
data() {
return {
makes: [],
};
},
props: {
modelValue: String,
cmsWidgetName: String,
},
computed: {
questionText() {
return this.getCmsContent(this.cmsWidgetName, "QuestionText");
},
selectedValue: {
get: function () {
return this.modelValue;
},
set: function (newValue) {
this.$emit("update:modelValue", newValue);
},
},
},
components: {
buttonQuestion,
},
methods: {
loadInitialData() {
return baseMixin.methods.dispatchStoreAction(storeActions.GET_VEHICLE_MAKES, {
year: store.getters.vehicle.year,
});
},
initializeComponent(initialData) {
this.makes = initialData;
},
},
};
</script>

View file

@ -1,228 +0,0 @@
// Supporting Files
import { shallowMount } from "@vue/test-utils";
import { getMountOptions } from "@/helpers/unit-test-helper.js";
import { settleAllPromises } from "@/helpers/layout-helper.js";
import { nextTick } from "vue";
import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
import baseMixin from "@/mixins/base-mixin.js";
import store from "@/store";
// Components
import vehicleMake from "@/layouts/vehicle-make/vehicle-make.vue";
import makeQuestion from "@/layouts/vehicle-make/make-question/make-question";
jest.mock("@/store", () => ({
commit: jest.fn(),
dispatch: jest.fn(),
// getters: jest.fn().mockImplementation(() => ({
// vehicle: {
// year: 2019,
// },
// })),
}));
// Mock fetchCmsContentForPage
jest.mock("@/helpers/cms-content-helper", () => ({
fetchCmsContentForPage: jest.fn(),
}));
// Mock our module for promises.
jest.mock("@/helpers/layout-helper.js", () => ({
settleAllPromises: jest.fn(),
}));
describe("vehicle-make.vue", () => {
test("Make question component is initized with api data", async (done) => {
//Arrange
const makeQuestionInitialData = ["honda", "ford", "dodge"];
const { wrapper, apiPromise } = setupMocks({
makeQuestionInitialData: makeQuestionInitialData,
});
//Act
vehicleMake.beforeRouteEnter.call(
wrapper.vm,
{ query: { fmgPage: "vehicle-make" } },
undefined,
(c) => c(wrapper.vm)
);
//Assert
apiPromise.finally(() => {
expect(makeQuestion.methods.initializeComponent).toHaveBeenCalledWith(
makeQuestionInitialData
);
done();
});
});
});
describe("vehicle-make.vue", () => {
test("BackButtonAction triggers a router.navigateWithoutSaving change", async (done) => {
//Arrange
const { wrapper, apiPromise } = setupMocks({
pageHeaderWidgetHeaderText: "Select a make to get started",
mountOptionsMockData: {
router: {
navigate: jest.fn(),
navigateWithoutSaving: jest.fn(),
},
},
});
//Act
vehicleMake.beforeRouteEnter.call(
wrapper.vm,
{ query: { fmgPage: "vehicle-make" } },
undefined,
(c) => c(wrapper.vm)
);
wrapper.vm.backButtonAction();
await nextTick();
//Assert
apiPromise.finally(() => {
expect(wrapper.vm.$router.navigateWithoutSaving).toHaveBeenCalled();
done();
});
});
});
describe("vehicle-make.vue", () => {
describe("arePagePrerequisitesValue", () => {
test("Year set, arePagePrerequisitesValid should be true", async () => {
//Arrange
const { wrapper } = setupMocks({
vehicleData: {
year: 2019,
},
});
//Act
vehicleMake.beforeRouteEnter.call(
wrapper.vm,
{ query: { fmgPage: "vehicle-make" } },
undefined,
(c) => c(wrapper.vm)
);
let arePagePrerequisitesValid = wrapper.vm.arePagePrerequisitesValid();
//Assert
expect(arePagePrerequisitesValid).toBe(true);
});
test("Year not set, arePagePrerequisitesValid should be false", async () => {
//Arrange
store.getters.vehicle.year = jest.fn().mockReturnValueOnce(undefined);
const { wrapper } = setupMocks({});
//Act
let arePagePrerequisitesValid = wrapper.vm.arePagePrerequisitesValid();
//Assert
expect(arePagePrerequisitesValid).toBe(false);
});
});
test("selectedMake changes => save make in store", async () => {
//Arrange
const { wrapper } = setupMocks({
mountOptionsMockData: {
router: {
navigate: jest.fn(),
navigateWithSaving: jest.fn(),
},
},
});
// Act
await wrapper.setData({
selectedMake: "Make",
});
await wrapper.vm.$nextTick();
// Assert
expect(wrapper.vm.dispatchStoreAction).toHaveBeenCalledTimes(1);
expect(wrapper.vm.dispatchStoreAction).toHaveBeenCalledWith(
"saveVehicleMake",
"Make",
false
);
});
test("selectedMake changes => navigate with saving", async () => {
//Arrange
const { wrapper } = setupMocks({
mountOptionsMockData: {
router: {
navigate: jest.fn(),
navigateWithSaving: jest.fn(),
},
route: {
fmgPage: "test",
},
},
});
// Act
await wrapper.setData({
selectedMake: "Make",
});
// Assert
expect(wrapper.vm.$router.navigateWithSaving).toHaveBeenCalledTimes(1);
expect(wrapper.vm.$router.navigateWithSaving).toHaveBeenCalledWith(
"SELECTED_MAKE",
expect.anything()
);
});
});
function setupMocks({
vehicleMakeQuestionCmsContent = {},
makeQuestionInitialData = {},
pageHeaderWidgetHeaderText = {},
mountOptionsMockData = {},
vehicleData = {},
}) {
//Mock api responses
const apiResponses = {
cmsContent: {
FunnelSubHeaderWidget: pageHeaderWidgetHeaderText,
VehicleMakeQuestion: vehicleMakeQuestionCmsContent,
VehicleBannerWidget: {
GenericVehicleImage:
"https://digitalconsumercms-dev.safelite.com/images/default-source/default-album/blurred-image.jpg?sfvrsn=a6ce3034_3",
},
FunnelHeaderWidget: {
LogoImage:
"https://digitalconsumercms-dev.safelite.com/images/default-source/default-album/safelite-logo.svg?sfvrsn=45e7ed06_3",
},
},
makeQuestionInitialData: makeQuestionInitialData,
};
const apiPromise = Promise.resolve(apiResponses);
store.getters = {
vehicle: vehicleData,
};
fetchCmsContentForPage.mockImplementation(() => Promise.resolve());
settleAllPromises.mockImplementation(() => apiPromise);
//Mock make question methods
makeQuestion.methods = {
loadInitialData: jest.fn(),
initializeComponent: jest.fn(),
};
const mountOptions = getMountOptions(mountOptionsMockData);
const wrapper = shallowMount(vehicleMake, mountOptions);
const makeQuestionWrapper = wrapper.findComponent({ name: "makeQuestion" });
makeQuestionWrapper.vm.initializeComponent = makeQuestion.methods.initializeComponent;
wrapper.vm.setCmsContent = baseMixin.methods.setCmsContent;
return { wrapper, apiPromise };
}

View file

@ -1,95 +0,0 @@
<template>
<div class="page-container-grouped-styles">
<funnelHeader cmsWidgetName="FunnelHeaderWidget" />
<div class="select-car">
<div class="select-car-form rounded text-center">
<vehicleBanner cmsWidgetName="VehicleBannerWidget" displayGenericVehicleImage />
<funnelSubHeader
cmsWidgetName="FunnelSubHeaderWidget"
:hasBackButton="true"
@click-event="backButtonAction"
headerColor="light-header" />
<div class="fade-on-route-transition">
<makeQuestion
v-model="selectedMake"
ref="makeQuestion"
cmsWidgetName="VehicleMakeQuestion" />
</div>
</div>
</div>
</div>
</template>
<script>
// Components
import makeQuestion from "@/layouts/vehicle-make/make-question/make-question";
import funnelHeader from "@/fmg-components/funnel-header/funnel-header";
import vehicleBanner from "@/fmg-components/vehicle-banner/vehicle-banner";
import funnelSubHeader from "@/fmg-components/funnel-sub-header/funnel-sub-header";
// Supporting files
import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
import { settleAllPromises } from "@/helpers/layout-helper";
import { storeActions } from "@/constants/store-actions";
import store from "@/store";
export default {
name: "vehicle-make",
data() {
return {
selectedMake: null,
};
},
computed: {},
async beforeRouteEnter(to, from, next) {
// Call APIs
const cmsContentPromise = fetchCmsContentForPage(to.query.fmgPage);
const makeQuestionInitialDataPromise = makeQuestion.methods.loadInitialData();
// Settle promises and get results
const promiseResultMap = [
{
resultKey: "cmsContent",
promise: cmsContentPromise,
},
{
resultKey: "makeQuestionInitialData",
promise: makeQuestionInitialDataPromise,
},
];
const resultMap = await settleAllPromises(promiseResultMap);
// Call the "next" function to complete the transition to this page.
next((vm) => {
vm.setCmsContent(resultMap.cmsContent);
vm.$refs.makeQuestion.initializeComponent(resultMap.makeQuestionInitialData);
});
},
methods: {
backButtonAction() {
// route to move backwards
this.$router.navigateWithoutSaving(this.navigationScenarios.CLICKED_BACK, this.$route);
},
arePagePrerequisitesValid() {
if (store.getters.vehicle.year) {
return true;
}
return false;
},
},
watch: {
selectedMake(make) {
this.dispatchStoreAction(storeActions.SAVE_VEHICLE_MAKE, make, false);
this.$router.navigateWithSaving(this.navigationScenarios.SELECTED_MAKE, this.$route);
},
},
components: {
makeQuestion,
funnelHeader,
vehicleBanner,
funnelSubHeader,
},
};
</script>

View file

@ -1,79 +0,0 @@
import modelQuestion from "@/layouts/vehicle-model/model-question/model-question";
import { shallowMount } from "@vue/test-utils";
import { getMountOptions } from "@/helpers/unit-test-helper.js";
import store from "@/store";
jest.mock(
"@/store",
() => {
return {};
},
{ virtual: true }
);
describe("model-question.vue", () => {
test("Selected model is emitted upon selection.", async () => {
//Arrange
const { wrapper } = setupMocks({ modelValueProp: "Accord" });
const modelToSelect = "Civic";
//Act
wrapper.setValue({ selectedModel: modelToSelect });
await wrapper.vm.$nextTick();
//Assert
expect(wrapper.emitted()["update:modelValue"][0]).toEqual([{ selectedModel: "Civic" }]);
});
});
describe("model-question.vue", () => {
test("Data from store api are used as radio question answers.", async () => {
//Arrange
const { wrapper, cmsContent } = setupMocks({
dataFromStoreApi: ["accord", "civic", "insight"],
});
//Act
const initialData = modelQuestion.methods.loadInitialData.call(wrapper.vm);
modelQuestion.methods.initializeComponent.call(wrapper.vm, initialData);
//Assert
const buttonQuestionComponent = await wrapper.findComponent({
name: "buttonQuestion",
});
expect(buttonQuestionComponent.attributes("answers")).toBe("accord,civic,insight");
});
});
function setupMocks({
modelValueProp = "1900",
cmsQuestionText = "CMS text goes here",
dataFromStoreApi = [],
}) {
//Mock store
store.dispatch = jest.fn(() => dataFromStoreApi);
store.getters = { vehicle: { year: 2019, make: "honda" } };
const mountOptions = getMountOptions({
store: {
dispatch: store.dispatch,
getters: store.getters,
},
});
//Mock props
const mockMixin = {
methods: {
getCmsContent: jest.fn(),
},
};
mountOptions.propsData = {
modelValue: modelValueProp,
};
mountOptions.mixins = [mockMixin];
const wrapper = shallowMount(modelQuestion, mountOptions);
//Mock CMS content
const cmsContent = {
QuestionText: cmsQuestionText,
};
return { wrapper, cmsContent };
}

View file

@ -1,60 +0,0 @@
<template>
<buttonQuestion
class="radioQuestion"
isOverflowScrollable
selectingInitiatesLoad
:questionText="questionText"
:answers="models"
groupName="ChooseVehicleModel"
textPosition="text-start"
v-model="selectedValue"
isRequired />
</template>
<script>
import buttonQuestion from "@/digital-components/button-question/button-question";
// Supporting files
import store from "@/store";
import { storeActions } from "@/constants/store-actions.js";
import baseMixin from "@/mixins/base-mixin.js";
export default {
name: "model-question",
data() {
return {
models: [],
};
},
props: {
modelValue: String,
cmsWidgetName: String,
},
computed: {
questionText() {
return this.getCmsContent(this.cmsWidgetName, "QuestionText");
},
selectedValue: {
get: function () {
return this.modelValue;
},
set: function (newValue) {
this.$emit("update:modelValue", newValue);
},
},
},
components: {
buttonQuestion,
},
methods: {
loadInitialData() {
return baseMixin.methods.dispatchStoreAction(storeActions.GET_VEHICLE_MODELS, {
year: store.getters.vehicle.year,
make: store.getters.vehicle.make,
});
},
initializeComponent(initialData) {
this.models = initialData;
},
},
};
</script>

View file

@ -1,147 +0,0 @@
// Components
import vehicleModel from "@/layouts/vehicle-model/vehicle-model.vue";
import modelQuestion from "@/layouts/vehicle-model/model-question/model-question";
// Supporting files
import { settleAllPromises } from "@/helpers/layout-helper.js";
import { shallowMount } from "@vue/test-utils";
import { getMountOptions } from "@/helpers/unit-test-helper.js";
import { nextTick } from "vue";
import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
import baseMixin from "@/mixins/base-mixin.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(),
}));
// Mock Store
jest.mock("@/store", () => ({
commit: jest.fn(),
dispatch: jest.fn(),
getters: {
vehicle: {
make: "Acura",
},
},
}));
describe("vehicle-model.vue", () => {
test("Model question component is initized with api data", async (done) => {
//Arange
const modelQuestionInitialData = ["accord", "civic", "insight"];
const { wrapper, apiPromise } = setupMocks({
modelQuestionInitialData: modelQuestionInitialData,
});
//Act
vehicleModel.beforeRouteEnter.call(
wrapper.vm,
{ query: { fmgPage: "vehicle-model" } },
undefined,
(c) => c(wrapper.vm)
);
//Assert
apiPromise.finally(() => {
expect(modelQuestion.methods.initializeComponent).toHaveBeenCalledWith(
modelQuestionInitialData
);
done();
});
});
});
describe("vehicle-model.vue", () => {
test("BackButtonAction triggers a router.navigateWithoutSaving change", async (done) => {
//Arrange
const { wrapper, apiPromise } = setupMocks({
pageHeaderWidgetHeaderText: "Select a model to get started",
mountOptionsMockData: {
router: {
navigate: jest.fn(),
navigateWithoutSaving: jest.fn(),
},
},
});
//Act
vehicleModel.beforeRouteEnter.call(
wrapper.vm,
{ query: { fmgPage: "vehicle-model" } },
undefined,
(c) => c(wrapper.vm)
);
wrapper.vm.backButtonAction();
await nextTick();
//Assert
apiPromise.finally(() => {
expect(wrapper.vm.$router.navigateWithoutSaving).toHaveBeenCalled();
done();
});
});
});
describe("vehicle-model.vue", () => {
test("Make set, arePagePrerequisitesValid should be true ", async () => {
//Arrange
const { wrapper } = setupMocks({});
//Act
vehicleModel.beforeRouteEnter.call(
wrapper.vm,
{ query: { fmgPage: "vehicle-model" } },
undefined,
(c) => c(wrapper.vm)
);
let arePagePrerequisitesValid = wrapper.vm.arePagePrerequisitesValid();
await nextTick();
//Assert
expect(arePagePrerequisitesValid).toBe(true);
});
});
function setupMocks({
buttonQuestionContent = {},
modelQuestionInitialData = {},
pageHeaderWidgetHeaderText = {},
mountOptionsMockData = {},
}) {
//Mock api responses
const apiResponses = {
cmsContent: {
FunnelSubHeaderWidget: pageHeaderWidgetHeaderText,
VehicleModelQuestion: buttonQuestionContent,
VehicleBannerWidget: {
GenericVehicleImage:
"https://digitalconsumercms-dev.safelite.com/images/default-source/default-album/blurred-image.jpg?sfvrsn=a6ce3034_3",
},
FunnelHeaderWidget: {
LogoImage:
"https://digitalconsumercms-dev.safelite.com/images/default-source/default-album/safelite-logo.svg?sfvrsn=45e7ed06_3",
},
},
modelQuestionInitialData: modelQuestionInitialData,
};
const apiPromise = Promise.resolve(apiResponses);
settleAllPromises.mockImplementation(() => apiPromise);
fetchCmsContentForPage.mockImplementation(() => Promise.resolve());
//Mock model question methods
modelQuestion.methods = {
loadInitialData: jest.fn(),
initializeComponent: jest.fn(),
};
const mountOptions = getMountOptions(mountOptionsMockData);
const wrapper = shallowMount(vehicleModel, mountOptions);
wrapper.vm.setCmsContent = baseMixin.methods.setCmsContent;
const modelQuestionWrapper = wrapper.findComponent({ name: "modelQuestion" });
modelQuestionWrapper.vm.initializeComponent = modelQuestion.methods.initializeComponent;
return { wrapper, apiPromise };
}

View file

@ -1,98 +0,0 @@
<template>
<div class="page-container-grouped-styles">
<funnelHeader cmsWidgetName="FunnelHeaderWidget" />
<div class="select-car">
<div class="select-car-form rounded text-center">
<vehicleBanner cmsWidgetName="VehicleBannerWidget" displayGenericVehicleImage />
<funnelSubHeader
cmsWidgetName="FunnelSubHeaderWidget"
:hasBackButton="true"
@click-event="backButtonAction"
headerColor="light-header" />
<div class="fade-on-route-transition">
<modelQuestion
v-model="selectedModel"
ref="modelQuestion"
cmsWidgetName="VehicleModelQuestion" />
</div>
</div>
</div>
</div>
</template>
<script>
// Components
import modelQuestion from "@/layouts/vehicle-model/model-question/model-question";
import funnelHeader from "@/fmg-components/funnel-header/funnel-header";
import funnelSubHeader from "@/fmg-components/funnel-sub-header/funnel-sub-header";
import vehicleBanner from "@/fmg-components/vehicle-banner/vehicle-banner";
// Supporting files
import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
import { storeMutations } from "@/constants/store-mutations";
import { storeActions } from "@/constants/store-actions";
import { settleAllPromises } from "@/helpers/layout-helper";
import store from "@/store";
export default {
name: "vehicle-model",
data() {
return {
selectedModel: null,
};
},
computed: {},
async beforeRouteEnter(to, from, next) {
// Call APIs
const cmsContentPromise = fetchCmsContentForPage(to.query.fmgPage);
const modelQuestionInitialDataPromise = modelQuestion.methods.loadInitialData();
// Settle promises and get results
const promiseResultMap = [
{
resultKey: "cmsContent",
promise: cmsContentPromise,
},
{
resultKey: "modelQuestionInitialData",
promise: modelQuestionInitialDataPromise,
},
];
const resultMap = await settleAllPromises(promiseResultMap);
// Call the "next" function to complete the transition to this page.
next((vm) => {
vm.setCmsContent(resultMap.cmsContent);
vm.$refs.modelQuestion.initializeComponent(resultMap.modelQuestionInitialData);
});
},
methods: {
backButtonAction() {
// route to move backwards
this.$router.navigateWithoutSaving(this.navigationScenarios.CLICKED_BACK, this.$route);
},
arePagePrerequisitesValid() {
if (store.getters.vehicle.make) {
return true;
}
return false;
},
},
watch: {
selectedModel(model) {
this.dispatchStoreAction(storeActions.SAVE_VEHICLE_MODEL, model, false);
this.$router.navigateWithSaving(this.navigationScenarios.SELECTED_MODEL, this.$route);
},
},
components: {
modelQuestion,
funnelHeader,
funnelSubHeader,
vehicleBanner,
},
};
</script>

View file

@ -1,79 +0,0 @@
import styleQuestion from "@/layouts/vehicle-style/style-question/style-question";
import { shallowMount } from "@vue/test-utils";
import { getMountOptions } from "@/helpers/unit-test-helper.js";
import store from "@/store";
jest.mock(
"@/store",
() => {
return {};
},
{ virtual: true }
);
describe("style-question.vue", () => {
test("Selected style is emitted upon selection.", async () => {
//Arrange
const { wrapper } = setupMocks({ modelValueProp: "2 Door" });
const styleToSelect = "4 Door";
//Act
wrapper.setValue({ selectedStyle: styleToSelect });
await wrapper.vm.$nextTick();
//Assert
expect(wrapper.emitted()["update:modelValue"][0]).toEqual([{ selectedStyle: "4 Door" }]);
});
});
describe("style-question.vue", () => {
test("Data from store api are used as radio question answers.", async () => {
//Arrange
const { wrapper, cmsContent } = setupMocks({
dataFromStoreApi: ["2 Door", "4 Door"],
});
//Act
const initialData = styleQuestion.methods.loadInitialData.call(wrapper.vm);
styleQuestion.methods.initializeComponent.call(wrapper.vm, initialData);
//Assert
const buttonQuestionComponent = await wrapper.findComponent({
name: "buttonQuestion",
});
expect(buttonQuestionComponent.attributes("answers")).toBe("2 Door,4 Door");
});
});
function setupMocks({
modelValueProp = "1900",
cmsQuestionText = "CMS text goes here",
dataFromStoreApi = [],
}) {
//Mock store
store.dispatch = jest.fn(() => dataFromStoreApi);
store.getters = { vehicle: { year: 2019, make: "honda", model: "civc" } };
const mountOptions = getMountOptions({
store: {
dispatch: store.dispatch,
getters: store.getters,
},
});
//Mock props
const mockMixin = {
methods: {
getCmsContent: jest.fn(),
},
};
mountOptions.propsData = {
modelValue: modelValueProp,
};
mountOptions.mixins = [mockMixin];
const wrapper = shallowMount(styleQuestion, mountOptions);
//Mock CMS content
const cmsContent = {
QuestionText: cmsQuestionText,
};
return { wrapper, cmsContent };
}

View file

@ -1,61 +0,0 @@
<template>
<buttonQuestion
class="radioQuestion"
isOverflowScrollable
selectingInitiatesLoad
:questionText="questionText"
:answers="styles"
groupName="ChooseVehicleStyle"
textPosition="text-start"
v-model="selectedValue"
isRequired />
</template>
<script>
import buttonQuestion from "@/digital-components/button-question/button-question";
// Supporting files
import store from "@/store";
import { storeActions } from "@/constants/store-actions.js";
import baseMixin from "@/mixins/base-mixin.js";
export default {
name: "style-question",
data() {
return {
styles: [],
};
},
props: {
modelValue: String,
cmsWidgetName: String,
},
computed: {
questionText() {
return this.getCmsContent(this.cmsWidgetName, "QuestionText");
},
selectedValue: {
get: function () {
return this.modelValue;
},
set: function (newValue) {
this.$emit("update:modelValue", newValue);
},
},
},
components: {
buttonQuestion,
},
methods: {
loadInitialData() {
return baseMixin.methods.dispatchStoreAction(storeActions.GET_VEHICLE_STYLES, {
year: store.getters.vehicle.year,
make: store.getters.vehicle.make,
model: store.getters.vehicle.model,
});
},
initializeComponent(initialData) {
this.styles = initialData;
},
},
};
</script>

View file

@ -1,256 +0,0 @@
// Components
import vehicleStyle from "@/layouts/vehicle-style/vehicle-style.vue";
import styleQuestion from "@/layouts/vehicle-style/style-question/style-question";
// Supporting files
import { settleAllPromises } from "@/helpers/layout-helper.js";
import { nextTick } from "vue";
import { shallowMount } from "@vue/test-utils";
import { getMountOptions } from "@/helpers/unit-test-helper.js";
import { storeActions } from "@/constants/store-actions";
import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
import baseMixin from "@/mixins/base-mixin.js";
import router from "@/router";
import store from "@/store";
import { storeMutations } from "@/constants/store-mutations";
// 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(),
}));
// Mock fetchCmsContentForPage
jest.mock("@/router", () => ({
overrideNavigation: jest.fn(),
}));
describe("vehicle-style.vue", () => {
beforeEach(() => {
jest.clearAllMocks();
});
test("Style question component is initized with api data", async (done) => {
//Arrange
const styleQuestionInitialData = ["2 Door", "4 Door"];
const { wrapper, apiPromise } = setupMocks({
styleQuestionInitialData: styleQuestionInitialData,
});
//Act
vehicleStyle.beforeRouteEnter.call(
wrapper.vm,
{ query: { fmgPage: "vehicle-style" } },
undefined,
(c) => c(wrapper.vm)
);
//Assert
apiPromise.finally(() => {
expect(styleQuestion.methods.initializeComponent).toHaveBeenCalledWith(
styleQuestionInitialData
);
done();
});
});
test("BackButtonAction triggers a router.navigateWithoutSaving change", async (done) => {
//Arrange
const { wrapper, apiPromise } = setupMocks({
pageHeaderWidgetHeaderText: "Select a style to get started",
mountOptionsMockData: {
router: {
navigate: jest.fn(),
navigateWithSaving: jest.fn(),
navigateWithoutSaving: jest.fn(),
},
},
});
//Act
vehicleStyle.beforeRouteEnter.call(
wrapper.vm,
{ query: { fmgPage: "vehicle-style" } },
undefined,
(c) => c(wrapper.vm)
);
wrapper.vm.backButtonAction();
await nextTick();
//Assert
apiPromise.finally(() => {
expect(wrapper.vm.$router.navigateWithoutSaving).toHaveBeenCalled();
done();
});
});
test("setVehicle triggers a dispatchStoreAction commit", async (done) => {
//Arrange
const { wrapper, apiPromise } = setupMocks({
pageHeaderWidgetHeaderText: "Select a style to get started",
mountOptionsMockData: {
actionList: [
{
actionName: storeActions.SET_VEHICLE,
data: "mockData",
},
],
},
});
//Act
vehicleStyle.beforeRouteEnter.call(
wrapper.vm,
{ query: { fmgPage: "vehicle-style" } },
undefined,
(c) => c(wrapper.vm)
);
wrapper.vm.setVehicle();
await nextTick();
//Assert
apiPromise.finally(() => {
expect(wrapper.vm.dispatchStoreAction).toHaveBeenCalled();
done();
});
});
test("Model set, arePagePrerequisitesValid should be true ", async () => {
//Arrange
const { wrapper } = setupMocks({});
//Act
vehicleStyle.beforeRouteEnter.call(
wrapper.vm,
{ query: { fmgPage: "vehicle-style" } },
undefined,
(c) => c(wrapper.vm)
);
let arePagePrerequisitesValid = wrapper.vm.arePagePrerequisitesValid();
await nextTick();
//Assert
expect(arePagePrerequisitesValid).toBe(true);
});
test("there is only one vehicle style => autoselect and move to vehicle damage", async () => {
//Arrange
const { wrapper } = setupMocks({
styleQuestionInitialData: ["2 door sedan"],
});
// Act
await vehicleStyle.beforeRouteEnter.call(
wrapper.vm,
{ query: { fmgPage: "vehicle-style" } },
undefined,
(c) => c(wrapper.vm)
);
// Assert
expect(store.commit).toHaveBeenCalledWith(storeMutations.UPDATE_STYLE, "2 door sedan");
expect(router.overrideNavigation).toHaveBeenCalled();
});
test("there is only one vehicle style and vehicle-damage was visited => don't autoselect or move to vehicle damage", async () => {
//Arrange
const { wrapper } = setupMocks({
styleQuestionInitialData: ["2 door sedan"],
mountOptionsMockData: {
store: {
getters: {
applicationUser: {
pageData: {
"part-questions": null,
"vehicle-make": {},
"vehicle-model": {},
"vehicle-style": {},
"vehicle-damage": {},
},
},
},
},
},
});
// Act
await vehicleStyle.beforeRouteEnter.call(
wrapper.vm,
{ query: { fmgPage: "vehicle-style" } },
undefined,
(c) => c(wrapper.vm)
);
// Assert
expect(store.commit).not.toHaveBeenCalledWith(storeMutations.UPDATE_STYLE, "2 door sedan");
expect(router.overrideNavigation).not.toHaveBeenCalled();
});
});
function setupMocks({
vehicleStyleQuestionCmsContent = {},
styleQuestionInitialData = {},
pageHeaderWidgetHeaderText = {},
mountOptionsMockData = {},
}) {
//Mock api responses
const apiResponses = {
cmsContent: {
FunnelSubHeaderWidget: pageHeaderWidgetHeaderText,
VehicleStyleQuestion: vehicleStyleQuestionCmsContent,
VehicleBannerWidget: {
GenericVehicleImage:
"https://digitalconsumercms-dev.safelite.com/images/default-source/default-album/blurred-image.jpg?sfvrsn=a6ce3034_3",
},
FunnelHeaderWidget: {
LogoImage:
"https://digitalconsumercms-dev.safelite.com/images/default-source/default-album/safelite-logo.svg?sfvrsn=45e7ed06_3",
},
},
styleQuestionInitialData: styleQuestionInitialData,
};
const apiPromise = Promise.resolve(apiResponses);
settleAllPromises.mockImplementation(() => apiPromise);
fetchCmsContentForPage.mockImplementation(() => Promise.resolve());
//Mock style question methods
styleQuestion.methods = {
loadInitialData: jest.fn(),
initializeComponent: jest.fn(),
};
store.commit = jest.fn();
store.dispatch = jest.fn();
store.getters = mountOptionsMockData.store?.getters ?? {
vehicle: {
model: "TL",
},
applicationUser: {
pageData: {
"part-questions": null,
"vehicle-make": {},
"vehicle-model": {},
"vehicle-style": {},
},
},
};
const mountOptions = getMountOptions({
...mountOptionsMockData,
store,
});
const wrapper = shallowMount(vehicleStyle, mountOptions);
wrapper.vm.setCmsContent = baseMixin.methods.setCmsContent;
const styleQuestionWrapper = wrapper.findComponent({ name: "styleQuestion" });
styleQuestionWrapper.vm.initializeComponent = styleQuestion.methods.initializeComponent;
return { wrapper, apiPromise };
}

View file

@ -1,137 +0,0 @@
<template>
<div class="page-container-grouped-styles">
<funnelHeader cmsWidgetName="FunnelHeaderWidget" />
<div class="select-car">
<div class="select-car-form rounded text-center">
<vehicleBanner cmsWidgetName="VehicleBannerWidget" displayGenericVehicleImage />
<funnelSubHeader
cmsWidgetName="FunnelSubHeaderWidget"
:hasBackButton="true"
@click-event="backButtonAction"
headerColor="light-header" />
<div class="fade-on-route-transition">
<styleQuestion
v-model="selectedStyle"
ref="styleQuestion"
cmsWidgetName="VehicleStyleQuestion" />
</div>
</div>
</div>
</div>
</template>
<script>
// Components
import baseMixin from "@/mixins/base-mixin.js";
import styleQuestion from "@/layouts/vehicle-style/style-question/style-question";
import funnelHeader from "@/fmg-components/funnel-header/funnel-header";
import funnelSubHeader from "@/fmg-components/funnel-sub-header/funnel-sub-header";
import vehicleBanner from "@/fmg-components/vehicle-banner/vehicle-banner";
// Supporting files
import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
import { settleAllPromises } from "@/helpers/layout-helper";
import { storeActions } from "@/constants/store-actions";
import store from "@/store";
import { storeMutations } from "@/constants/store-mutations";
import { fmgPageValues } from "@/router/router-constants/fmgPage-values";
import router from "@/router";
import { navigationScenarios } from "@/router/router-constants/navigation-scenarios";
export default {
name: "vehicle-style",
data() {
return {
selectedStyle: null,
};
},
computed: {},
async beforeRouteEnter(to, from, next) {
// Call APIs
const cmsContentPromise = fetchCmsContentForPage(to.query.fmgPage);
const styleQuestionInitialDataPromise = styleQuestion.methods.loadInitialData();
// Settle promises and get results
const promiseResultMap = [
{
resultKey: "cmsContent",
promise: cmsContentPromise,
},
{
resultKey: "styleQuestionInitialData",
promise: styleQuestionInitialDataPromise,
},
];
const resultMap = await settleAllPromises(promiseResultMap);
const visitedVehicleDamage =
JSON.stringify(store.getters.applicationUser.pageData).indexOf(
fmgPageValues.VEHICLE_DAMAGE
) < 0
? false
: true;
// If we have exactly one style then navigate directly to vehicle-damage
if (resultMap.styleQuestionInitialData.length === 1 && !visitedVehicleDamage) {
store.commit(storeMutations.UPDATE_STYLE, resultMap.styleQuestionInitialData[0]);
await baseMixin.methods.dispatchStoreAction(storeActions.SET_VEHICLE, {
year: store.getters.vehicle.year,
make: store.getters.vehicle.make,
model: store.getters.vehicle.model,
style: store.getters.vehicle.style,
});
//emulate selecting the vehicle style
router.overrideNavigation(navigationScenarios.SELECTED_STYLE, to, next, true);
} else {
next((vm) => {
vm.setCmsContent(resultMap.cmsContent);
vm.$refs.styleQuestion.initializeComponent(resultMap.styleQuestionInitialData);
});
}
},
methods: {
backButtonAction() {
// route to move backwards
this.$router.navigateWithoutSaving(this.navigationScenarios.CLICKED_BACK, this.$route);
},
setVehicle() {
return this.dispatchStoreAction(this.storeActions.SET_VEHICLE, {
year: this.$store.getters.vehicle.year,
make: this.$store.getters.vehicle.make,
model: this.$store.getters.vehicle.model,
style: this.$store.getters.vehicle.style,
});
},
arePagePrerequisitesValid() {
if (store.getters.vehicle.model) {
return true;
}
return false;
},
},
watch: {
selectedStyle(style) {
this.dispatchStoreAction(storeActions.SAVE_VEHICLE_STYLE, style, false);
this.setVehicle().then(() => {
this.$router.navigateWithSaving(
this.navigationScenarios.SELECTED_STYLE,
this.$route
);
});
},
},
components: {
styleQuestion,
funnelHeader,
funnelSubHeader,
vehicleBanner,
},
};
</script>

View file

@ -1,122 +0,0 @@
import { shallowMount, flushPromises } from "@vue/test-utils";
import { getMountOptions } from "@/helpers/unit-test-helper.js";
import { settleAllPromises } from "@/helpers/layout-helper.js";
import { nextTick } from "vue";
import { storeMutations } from "@/constants/store-mutations";
import { storeActions } from "@/constants/store-actions";
import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
import baseMixin from "@/mixins/base-mixin.js";
import vehicleYear from "@/layouts/vehicle-year/vehicle-year.vue";
import yearQuestion from "@/layouts/vehicle-year/year-question/year-question";
import store from "@/store";
jest.mock("@/store", () => ({
commit: jest.fn(),
dispatch: jest.fn(),
getters: {
applicationUser: {
experiments: [],
},
},
}));
// 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("vehicle-year.vue", () => {
test("Year question component is initized with api data", async (done) => {
//Arrange
const yearQuestionInitialData = ["2023", "2022", "2021"];
const { wrapper, apiPromise } = setupMocks({
yearQuestionInitialData: yearQuestionInitialData,
});
//Act
vehicleYear.beforeRouteEnter.call(
wrapper.vm,
{ query: { fmgPage: "vehicle-year" } },
undefined,
(c) => c(wrapper.vm)
);
//Assert
apiPromise.finally(() => {
expect(yearQuestion.methods.initializeComponent).toHaveBeenCalledWith(
yearQuestionInitialData
);
done();
});
});
});
describe("vehicle-year.vue", () => {
test("arePagePrerequisitesValid should be true ", async () => {
//Arrange
const { wrapper } = setupMocks({});
//Act
vehicleYear.beforeRouteEnter.call(
wrapper.vm,
{ query: { fmgPage: "vehicle-make" } },
undefined,
(c) => c(wrapper.vm)
);
let arePagePrerequisitesValid = wrapper.vm.arePagePrerequisitesValid();
await nextTick();
//Assert
expect(arePagePrerequisitesValid).toBe(true);
});
});
function setupMocks({
vehicleYearQuestionCmsContent = {},
yearQuestionInitialData = {},
pageHeaderWidgetHeaderText = {},
mountOptionsMockData = {},
}) {
//Mock api responses
const apiResponses = {
cmsContent: {
FunnelSubHeaderWidget: { HeaderText: pageHeaderWidgetHeaderText },
VehicleYearQuestion: vehicleYearQuestionCmsContent,
VehicleBannerWidget: {
GenericVehicleImage:
"https://digitalconsumercms-dev.safelite.com/images/default-source/default-album/blurred-image.jpg?sfvrsn=a6ce3034_3",
},
FunnelHeaderWidget: {
LogoImage:
"https://digitalconsumercms-dev.safelite.com/images/default-source/default-album/safelite-logo.svg?sfvrsn=45e7ed06_3",
},
},
yearQuestionInitialData: yearQuestionInitialData,
};
const apiPromise = Promise.resolve(apiResponses);
settleAllPromises.mockImplementation(() => apiPromise);
fetchCmsContentForPage.mockImplementation(() => Promise.resolve());
//Mock year question methods
yearQuestion.methods = {
loadInitialData: jest.fn(),
initializeComponent: jest.fn(),
};
const mountOptions = getMountOptions(mountOptionsMockData);
const wrapper = shallowMount(vehicleYear, mountOptions);
const yearQuestionWrapper = wrapper.findComponent({ name: "yearQuestion" });
yearQuestionWrapper.vm.initializeComponent = yearQuestion.methods.initializeComponent;
wrapper.vm.setCmsContent = baseMixin.methods.setCmsContent;
return { wrapper, apiPromise };
}

View file

@ -1,110 +0,0 @@
<template>
<div class="page-container-grouped-styles">
<funnelHeader cmsWidgetName="FunnelHeaderWidget" />
<div class="select-car">
<div class="select-car-form rounded text-center">
<vehicleBanner cmsWidgetName="VehicleBannerWidget" displayGenericVehicleImage />
<funnelSubHeader cmsWidgetName="FunnelSubHeaderWidget" headerColor="light-header" />
<div class="fade-on-route-transition">
<yearQuestion
class="fade-on-route-transition"
v-model="selectedYear"
ref="yearQuestion"
cmsWidgetName="VehicleYearQuestion" />
</div>
</div>
</div>
</div>
</template>
<script>
// Components
import yearQuestion from "@/layouts/vehicle-year/year-question/year-question";
import funnelHeader from "@/fmg-components/funnel-header/funnel-header";
import vehicleBanner from "@/fmg-components/vehicle-banner/vehicle-banner";
import funnelSubHeader from "@/fmg-components/funnel-sub-header/funnel-sub-header";
// Supporting files
import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
import { settleAllPromises } from "@/helpers/layout-helper";
import { storeActions } from "@/constants/store-actions";
import { experimentUniverses } from "@/constants/experiments";
import { getDeviceIdValue, getSessionKeyValue } from "@/helpers/heritage-integration/cookie-helper";
import store from "@/store";
import baseMixin from "@/mixins/base-mixin";
export default {
name: "vehicle-year",
data() {
return {
selectedYear: null,
};
},
computed: {},
async beforeRouteEnter(to, from, next) {
// Call APIs
const cmsContentPromise = fetchCmsContentForPage(to.query.fmgPage);
const yearQuestionInitialDataPromise = yearQuestion.methods.loadInitialData();
const experimentForLogging = store.getters.applicationUser.experiments.find(
(e) => e.universeName === experimentUniverses.CONCEPT_FUNNEL
);
// If the concept funnel experiment is found, as it should be when coming from safelite.com, then log the experiment exposure.
if (experimentForLogging !== undefined) {
// Log experiment exposure
baseMixin.methods.dispatchStoreAction(
storeActions.LOG_EXPERIMENT_EXPOSURE,
{
userId: getDeviceIdValue(),
sessionKey: getSessionKeyValue(),
pageName: to.query.fmgPage,
experiment: experimentForLogging,
},
false
);
}
// Settle promises and get results
const promiseResultMap = [
{
resultKey: "cmsContent",
promise: cmsContentPromise,
},
{
resultKey: "yearQuestionInitialData",
promise: yearQuestionInitialDataPromise,
},
];
let resultMap = await settleAllPromises(promiseResultMap);
// Call the "next" function to complete the transition to this page.
next((vm) => {
vm.setCmsContent(resultMap.cmsContent);
vm.$refs.yearQuestion.initializeComponent(resultMap.yearQuestionInitialData);
});
},
watch: {
selectedYear(year) {
const parsedYear = parseInt(year);
this.dispatchStoreAction(storeActions.SAVE_VEHICLE_YEAR, parsedYear);
this.$router.navigateWithSaving(this.navigationScenarios.SELECTED_YEAR, this.$route);
},
},
methods: {
arePagePrerequisitesValid() {
return true;
},
},
components: {
yearQuestion,
funnelHeader,
vehicleBanner,
funnelSubHeader,
},
};
</script>

View file

@ -1,78 +0,0 @@
import yearQuestion from "@/layouts/vehicle-year/year-question/year-question";
import { shallowMount } from "@vue/test-utils";
import { getMountOptions } from "@/helpers/unit-test-helper.js";
import store from "@/store";
jest.mock(
"@/store",
() => {
return {};
},
{ virtual: true }
);
describe("year-question.vue", () => {
test("Selected year is emitted upon selection.", async () => {
//Arrange
const { wrapper } = setupMocks({ modelValueProp: "2020" });
const yearToSelect = "2021";
//Act
wrapper.setValue({ modelValue: yearToSelect });
await wrapper.vm.$nextTick();
//Assert
expect(wrapper.emitted()["update:modelValue"][0]).toEqual([{ modelValue: "2021" }]);
});
});
describe("year-question.vue", () => {
test("Data from store api are used as radio question answers.", async () => {
//Arrange
const { wrapper, cmsContent } = setupMocks({
dataFromStoreApi: ["2023", "2022", "2021"],
});
//Act
const initialData = yearQuestion.methods.loadInitialData.call(wrapper.vm);
yearQuestion.methods.initializeComponent.call(wrapper.vm, initialData);
//Assert
const buttonQuestionComponent = await wrapper.findComponent({
name: "buttonQuestion",
});
expect(buttonQuestionComponent.attributes("answers")).toBe("2023,2022,2021");
});
});
function setupMocks({
modelValueProp = "1900",
cmsQuestionText = "CMS text goes here",
dataFromStoreApi = [],
}) {
//Mock store
store.dispatch = jest.fn(() => dataFromStoreApi);
const mountOptions = getMountOptions({
store: {
dispatch: store.dispatch,
},
});
//Mock props
const mockMixin = {
methods: {
getCmsContent: jest.fn(),
},
};
mountOptions.propsData = {
modelValue: modelValueProp,
};
mountOptions.mixins = [mockMixin];
const wrapper = shallowMount(yearQuestion, mountOptions);
//Mock CMS content
const cmsContent = {
QuestionText: cmsQuestionText,
};
return { wrapper, cmsContent };
}

View file

@ -1,55 +0,0 @@
<template>
<buttonQuestion
class="radioQuestion"
isOverflowScrollable
selectingInitiatesLoad
:questionText="questionText"
:answers="years"
groupName="ChooseVehicleYear"
textPosition="text-start"
v-model="selectedValue"
isRequired />
</template>
<script>
import buttonQuestion from "@/digital-components/button-question/button-question";
// Supporting files
import { storeActions } from "@/constants/store-actions.js";
import baseMixin from "@/mixins/base-mixin.js";
export default {
name: "year-question",
data() {
return {
years: [],
};
},
props: {
modelValue: String,
cmsWidgetName: String,
},
components: {
buttonQuestion,
},
computed: {
questionText() {
return this.getCmsContent(this.cmsWidgetName, "QuestionText");
},
selectedValue: {
get: function () {
return this.modelValue;
},
set: function (newValue) {
this.$emit("update:modelValue", newValue);
},
},
},
methods: {
loadInitialData() {
return baseMixin.methods.dispatchStoreAction(storeActions.GET_VEHICLE_YEARS, {});
},
initializeComponent(initialData) {
this.years = initialData;
},
},
};
</script>

View file

@ -58,7 +58,9 @@
<vehicleBanner
cmsWidgetName="VehicleBannerWidget"
:displayGenericVehicleImage="displayGeneric"
:displayVehicleImage="vehicle.imageUrl"
:displayVehicleImage="imageUrl"
:vehicleCategory="category"
:displayUnmatchedVehicleIcon="unmatchedVehicleIcon"
class="mt-5 mb-3"
ref="banner" />
@ -110,17 +112,17 @@ export default {
selectedMake: this.selectedMakefromStore(),
selectedModel: this.selectedModelfromStore(),
selectedStyle: this.selectedStylefromStore(),
vehicle: {
carId: null,
category: null,
imageUrl: null,
imageVifNumber: null,
imageVifColor: null,
},
carId: null,
category: null,
imageUrl: null,
imageVifNumber: null,
imageVifColor: null,
yearOptions: [],
makeOptions: [],
modelOptions: [],
styleOptions: [],
displayGeneric: this.displayGenericFromStore(),
unmatchedVehicleIcon: false,
};
},
@ -279,7 +281,18 @@ export default {
this.selectedModel,
style
);
this.vehicle = result?.data;
this.carId = result?.data.carId;
this.category = result?.data.category;
this.imageUrl = result?.data.imageUrl;
this.imageVifNumber = result?.data.imageVifNumber;
this.imageVifColor = result?.data.imageVifColor;
if (this.imageUrl == null) {
this.displayGeneric = false;
this.unmatchedVehicleIcon = true;
} else this.unmatchedVehicleIcon = false;
} else {
this.imageUrl = null;
this.displayGeneric = true;
}
},
},
@ -293,6 +306,15 @@ export default {
style: style,
});
},
displayGenericFromStore() {
if (store.getters.vehicle.imageUrl !== null) return false;
else if (
store.getters.vehicle.imageUrl === null &&
store.getters.vehicle.carId !== null
)
return false;
else return true;
},
arePagePrerequisitesValid() {
return true;
},
@ -305,7 +327,11 @@ export default {
make: this.selectedMake,
model: this.selectedModel,
style: this.selectedStyle,
vehicle: this.vehicle,
carId: this.carId,
category: this.category,
imageUrl: this.imageUrl,
imageVifNumber: this.imageVifNumber,
imageVifColor: this.imageVifColor,
},
false
);
@ -353,12 +379,6 @@ export default {
},
},
computed: {
displayGeneric() {
return !this.selectedStyle;
},
},
components: {
funnelHeader,
funnelFooter,

View file

@ -1,8 +1,4 @@
const fmgPageValues = {
VEHICLE_YEAR: "vehicle-year",
VEHICLE_MAKE: "vehicle-make",
VEHICLE_MODEL: "vehicle-model",
VEHICLE_STYLE: "vehicle-style",
VEHICLE: "vehicle",
VEHICLE_DAMAGE: "vehicle-damage",
ADDRESS_LOOKUP: "address-lookup",

View file

@ -12,12 +12,6 @@ const navigationScenarios = {
CLICKED_FORWARD: "CLICKED_FORWARD",
CLICKED_FORWARD_WITH_CASH: "CLICKED_FORWARD_WITH_CASH",
// YMMS
SELECTED_YEAR: "SELECTED_YEAR",
SELECTED_MODEL: "SELECTED_MODEL",
SELECTED_MAKE: "SELECTED_MAKE",
SELECTED_STYLE: "SELECTED_STYLE",
// Vin selection
CLICKED_BACK_WITH_VIN: "CLICKED_BACK_WITH_VIN",
CLICKED_FORWARD_WITH_VIN: "CLICKED_FORWARD_WITH_VIN",

View file

@ -13,54 +13,7 @@ const routingTable = function (store) {
},
],
},
{
fmgPageValue: fmgPageValues.VEHICLE_YEAR,
maps: [
{
scenario: navigationScenarios.SELECTED_YEAR,
destinationFmgPageValue: fmgPageValues.VEHICLE_MAKE,
},
],
},
{
fmgPageValue: fmgPageValues.VEHICLE_MAKE,
maps: [
{
scenario: navigationScenarios.SELECTED_MAKE,
destinationFmgPageValue: fmgPageValues.VEHICLE_MODEL,
},
{
scenario: navigationScenarios.CLICKED_BACK,
destinationFmgPageValue: fmgPageValues.VEHICLE_YEAR,
},
],
},
{
fmgPageValue: fmgPageValues.VEHICLE_MODEL,
maps: [
{
scenario: navigationScenarios.SELECTED_MODEL,
destinationFmgPageValue: fmgPageValues.VEHICLE_STYLE,
},
{
scenario: navigationScenarios.CLICKED_BACK,
destinationFmgPageValue: fmgPageValues.VEHICLE_MAKE,
},
],
},
{
fmgPageValue: fmgPageValues.VEHICLE_STYLE,
maps: [
{
scenario: navigationScenarios.SELECTED_STYLE,
destinationFmgPageValue: fmgPageValues.VEHICLE_DAMAGE,
},
{
scenario: navigationScenarios.CLICKED_BACK,
destinationFmgPageValue: fmgPageValues.VEHICLE_MODEL,
},
],
},
{
fmgPageValue: fmgPageValues.VEHICLE_DAMAGE,
maps: [

View file

@ -25,6 +25,7 @@ import {
// Export State
const getDefaultState = () => {
return {
submitAfterSave: false,
order: {
vehicle: {
year: null,
@ -123,6 +124,10 @@ export const state = getDefaultState();
// Export Mutations
export const mutations = {
updateWorkOrderFlag(state, submitAfterSave) {
state.submitAfterSave = submitAfterSave;
},
// VEHICLE MUTATIONS
updateYear(state, year) {
state.order.vehicle.year = year;
@ -1400,6 +1405,7 @@ export const actions = {
method: endpoints.SaveSession.method,
endpoint: endpoints.SaveSession.url,
payload: {
submitAfterSave: context.state.submitAfterSave,
applicationUser: {
crmCustomerId: applicationUser.crmCustomerId,
experiments: applicationUser.experiments,
@ -1552,93 +1558,19 @@ export const actions = {
);
},
saveWorkOrderFlag(context, submitAfterSave) {
context.commit(storeMutations.UPDATE_WORK_ORDER_FLAG, submitAfterSave);
},
// Business domain actions
// Vehicle
saveVehicleYear(context, year) {
//Reset dependent state when changing
if (context.state.order.vehicle.year !== year) {
context.commit(storeMutations.UPDATE_MAKE, null);
context.commit(storeMutations.UPDATE_MODEL, null);
context.commit(storeMutations.UPDATE_STYLE, null);
context.commit(storeMutations.UPDATE_CAR_ID, null);
context.commit(storeMutations.UPDATE_VEHICLE_CATEGORY, null);
context.commit(storeMutations.UPDATE_VEHICLE_VIN, null);
context.commit(storeMutations.UPDATE_VEHICLE_IMAGE_URL, null);
context.commit(storeMutations.UPDATE_VEHICLE_IMAGE_VIF_NUMBER, null);
context.commit(storeMutations.UPDATE_VEHICLE_IMAGE_COLOR, null);
context.dispatch(storeActions.RESET_DAMAGE_STATE_AND_DEPENDENCIES);
context.dispatch(storeActions.RESET_REGISTRATION_STATE_AND_DEPENDENCIES);
context.dispatch(storeActions.RESET_PARTS_STATE_AND_DEPENDENCIES);
//Save new values
context.commit(storeMutations.UPDATE_YEAR, year);
}
},
saveVehicleMake(context, make) {
//Reset dependent state when changing
if (context.state.order.vehicle.make !== make) {
context.commit(storeMutations.UPDATE_MODEL, null);
context.commit(storeMutations.UPDATE_STYLE, null);
context.commit(storeMutations.UPDATE_CAR_ID, null);
context.commit(storeMutations.UPDATE_VEHICLE_CATEGORY, null);
context.commit(storeMutations.UPDATE_VEHICLE_VIN, null);
context.commit(storeMutations.UPDATE_VEHICLE_IMAGE_URL, null);
context.commit(storeMutations.UPDATE_VEHICLE_IMAGE_VIF_NUMBER, null);
context.commit(storeMutations.UPDATE_VEHICLE_IMAGE_COLOR, null);
context.dispatch(storeActions.RESET_DAMAGE_STATE_AND_DEPENDENCIES);
context.dispatch(storeActions.RESET_REGISTRATION_STATE_AND_DEPENDENCIES);
context.dispatch(storeActions.RESET_PARTS_STATE_AND_DEPENDENCIES);
//Save new values
context.commit(storeMutations.UPDATE_MAKE, make);
}
},
saveVehicleModel(context, model) {
//Reset dependent state when changing
if (context.state.order.vehicle.model !== model) {
context.commit(storeMutations.UPDATE_STYLE, null);
context.commit(storeMutations.UPDATE_CAR_ID, null);
context.commit(storeMutations.UPDATE_VEHICLE_CATEGORY, null);
context.commit(storeMutations.UPDATE_VEHICLE_VIN, null);
context.commit(storeMutations.UPDATE_VEHICLE_IMAGE_URL, null);
context.commit(storeMutations.UPDATE_VEHICLE_IMAGE_VIF_NUMBER, null);
context.commit(storeMutations.UPDATE_VEHICLE_IMAGE_COLOR, null);
context.dispatch(storeActions.RESET_DAMAGE_STATE_AND_DEPENDENCIES);
context.dispatch(storeActions.RESET_REGISTRATION_STATE_AND_DEPENDENCIES);
context.dispatch(storeActions.RESET_PARTS_STATE_AND_DEPENDENCIES);
//Save new values
context.commit(storeMutations.UPDATE_MODEL, model);
}
},
saveVehicleStyle(context, style) {
//Reset dependent state when changing
if (context.state.order.vehicle.style !== style) {
context.commit(storeMutations.UPDATE_CAR_ID, null);
context.commit(storeMutations.UPDATE_VEHICLE_CATEGORY, null);
context.commit(storeMutations.UPDATE_VEHICLE_VIN, null);
context.commit(storeMutations.UPDATE_VEHICLE_IMAGE_URL, null);
context.commit(storeMutations.UPDATE_VEHICLE_IMAGE_VIF_NUMBER, null);
context.commit(storeMutations.UPDATE_VEHICLE_IMAGE_COLOR, null);
context.dispatch(storeActions.RESET_DAMAGE_STATE_AND_DEPENDENCIES);
context.dispatch(storeActions.RESET_REGISTRATION_STATE_AND_DEPENDENCIES);
context.dispatch(storeActions.RESET_PARTS_STATE_AND_DEPENDENCIES);
//Save new values
context.commit(storeMutations.UPDATE_STYLE, style);
}
},
saveVehicle(context, { year, make, model, style, vehicle }) {
context.dispatch(storeActions.RESET_PARTS_STATE_AND_DEPENDENCIES);
saveVehicle(
context,
{ year, make, model, style, carId, category, imageUrl, imageVifNumber, imageVifColor }
) {
context.dispatch(storeActions.RESET_DAMAGE_STATE_AND_DEPENDENCIES);
context.dispatch(storeActions.RESET_REGISTRATION_STATE_AND_DEPENDENCIES);
if (context.state.order.vehicle.year !== year) {
context.commit(storeMutations.UPDATE_YEAR, year);
@ -1652,11 +1584,11 @@ export const actions = {
if (context.state.order.vehicle.style !== style) {
context.commit(storeMutations.UPDATE_STYLE, style);
}
context.commit(storeMutations.UPDATE_CAR_ID, vehicle.carId);
context.commit(storeMutations.UPDATE_VEHICLE_CATEGORY, vehicle.category);
context.commit(storeMutations.UPDATE_VEHICLE_IMAGE_URL, vehicle.imageUrl);
context.commit(storeMutations.UPDATE_VEHICLE_IMAGE_VIF_NUMBER, vehicle.imageVifNumber);
context.commit(storeMutations.UPDATE_VEHICLE_IMAGE_COLOR, vehicle.imageVifColor);
context.commit(storeMutations.UPDATE_CAR_ID, carId);
context.commit(storeMutations.UPDATE_VEHICLE_CATEGORY, category);
context.commit(storeMutations.UPDATE_VEHICLE_IMAGE_URL, imageUrl);
context.commit(storeMutations.UPDATE_VEHICLE_IMAGE_VIF_NUMBER, imageVifNumber);
context.commit(storeMutations.UPDATE_VEHICLE_IMAGE_COLOR, imageVifColor);
},
saveVehicleDamage(

View file

@ -1573,168 +1573,6 @@ describe("Actions", () => {
expect(commit).toBeCalledWith(storeMutations.UPDATE_REGISTRATION, payload.registrationInfo);
});
it("saveVehicleYear, should wipe out vehicle info if year changes", () => {
// Arrange
const context = state;
context.state = {
order: {
vehicle: {
year: "2015",
},
},
};
const commit = jest.fn();
const dispatch = jest.fn();
context.commit = commit;
context.dispatch = dispatch;
// Act
actions.saveVehicleYear(context, "2016");
// Assert
expect(dispatch).toHaveBeenNthCalledWith(
1,
storeActions.RESET_DAMAGE_STATE_AND_DEPENDENCIES
);
expect(dispatch).toHaveBeenNthCalledWith(
2,
storeActions.RESET_REGISTRATION_STATE_AND_DEPENDENCIES
);
expect(commit).toBeCalledWith(storeMutations.UPDATE_MAKE, null);
expect(commit).toBeCalledWith(storeMutations.UPDATE_MODEL, null);
expect(commit).toBeCalledWith(storeMutations.UPDATE_STYLE, null);
expect(commit).toBeCalledWith(storeMutations.UPDATE_CAR_ID, null);
expect(commit).toBeCalledWith(storeMutations.UPDATE_VEHICLE_CATEGORY, null);
expect(commit).toBeCalledWith(storeMutations.UPDATE_VEHICLE_VIN, null);
expect(commit).toBeCalledWith(storeMutations.UPDATE_VEHICLE_IMAGE_URL, null);
expect(commit).toBeCalledWith(storeMutations.UPDATE_VEHICLE_IMAGE_VIF_NUMBER, null);
expect(commit).toBeCalledWith(storeMutations.UPDATE_VEHICLE_IMAGE_COLOR, null);
});
it("saveVehicleMake, should wipe out vehicle info if make changes", () => {
// Arrange
const context = state;
context.state = {
order: {
vehicle: {
make: "Honda",
},
},
};
const commit = jest.fn();
const dispatch = jest.fn();
context.commit = commit;
context.dispatch = dispatch;
// Act
actions.saveVehicleMake(context, "Toyota");
// Assert
expect(dispatch).toHaveBeenNthCalledWith(
1,
storeActions.RESET_DAMAGE_STATE_AND_DEPENDENCIES
);
expect(dispatch).toHaveBeenNthCalledWith(
2,
storeActions.RESET_REGISTRATION_STATE_AND_DEPENDENCIES
);
expect(commit).toBeCalledWith(storeMutations.UPDATE_MODEL, null);
expect(commit).toBeCalledWith(storeMutations.UPDATE_STYLE, null);
expect(commit).toBeCalledWith(storeMutations.UPDATE_CAR_ID, null);
expect(commit).toBeCalledWith(storeMutations.UPDATE_VEHICLE_CATEGORY, null);
expect(commit).toBeCalledWith(storeMutations.UPDATE_VEHICLE_VIN, null);
expect(commit).toBeCalledWith(storeMutations.UPDATE_VEHICLE_IMAGE_URL, null);
expect(commit).toBeCalledWith(storeMutations.UPDATE_VEHICLE_IMAGE_VIF_NUMBER, null);
expect(commit).toBeCalledWith(storeMutations.UPDATE_VEHICLE_IMAGE_COLOR, null);
});
it("saveVehicle model, should wipe out vehicle info if model changes", () => {
// Arrange
const context = state;
context.state = {
order: {
vehicle: {
model: "Civic",
},
},
};
const commit = jest.fn();
const dispatch = jest.fn();
context.commit = commit;
context.dispatch = dispatch;
// Act
actions.saveVehicleModel(context, "Accord");
// Assert
expect(dispatch).toHaveBeenNthCalledWith(
1,
storeActions.RESET_DAMAGE_STATE_AND_DEPENDENCIES
);
expect(dispatch).toHaveBeenNthCalledWith(
2,
storeActions.RESET_REGISTRATION_STATE_AND_DEPENDENCIES
);
expect(commit).toBeCalledWith(storeMutations.UPDATE_STYLE, null);
expect(commit).toBeCalledWith(storeMutations.UPDATE_CAR_ID, null);
expect(commit).toBeCalledWith(storeMutations.UPDATE_VEHICLE_CATEGORY, null);
expect(commit).toBeCalledWith(storeMutations.UPDATE_VEHICLE_VIN, null);
expect(commit).toBeCalledWith(storeMutations.UPDATE_VEHICLE_IMAGE_URL, null);
expect(commit).toBeCalledWith(storeMutations.UPDATE_VEHICLE_IMAGE_VIF_NUMBER, null);
expect(commit).toBeCalledWith(storeMutations.UPDATE_VEHICLE_IMAGE_COLOR, null);
});
it("saveVehicleStyle, should wipe out vehicle info if style changes", () => {
// Arrange
const context = state;
context.state = {
order: {
vehicle: {
style: "Sedan",
},
},
};
const commit = jest.fn();
const dispatch = jest.fn();
context.commit = commit;
context.dispatch = dispatch;
// Act
actions.saveVehicleStyle(context, "SUV");
// Assert
expect(dispatch).toHaveBeenNthCalledWith(
1,
storeActions.RESET_DAMAGE_STATE_AND_DEPENDENCIES
);
expect(dispatch).toHaveBeenNthCalledWith(
2,
storeActions.RESET_REGISTRATION_STATE_AND_DEPENDENCIES
);
expect(commit).toBeCalledWith(storeMutations.UPDATE_CAR_ID, null);
expect(commit).toBeCalledWith(storeMutations.UPDATE_VEHICLE_CATEGORY, null);
expect(commit).toBeCalledWith(storeMutations.UPDATE_VEHICLE_VIN, null);
expect(commit).toBeCalledWith(storeMutations.UPDATE_VEHICLE_IMAGE_URL, null);
expect(commit).toBeCalledWith(storeMutations.UPDATE_VEHICLE_IMAGE_VIF_NUMBER, null);
expect(commit).toBeCalledWith(storeMutations.UPDATE_VEHICLE_IMAGE_COLOR, null);
});
it("saveVehicle, should save vehicle info", () => {
// Arrange
const context = state;
@ -1762,14 +1600,20 @@ describe("Actions", () => {
make: "Honda",
model: "Civic",
style: "Sedan",
vehicle: {
carId: "C00000000",
category: "CAR",
},
carId: "C00000000",
category: "CAR",
};
actions.saveVehicle(context, payload);
//Assert
expect(dispatch).toHaveBeenNthCalledWith(
1,
storeActions.RESET_DAMAGE_STATE_AND_DEPENDENCIES
);
expect(dispatch).toHaveBeenNthCalledWith(
2,
storeActions.RESET_REGISTRATION_STATE_AND_DEPENDENCIES
);
if (context.state.order.vehicle.year !== payload.year) {
expect(commit).toBeCalledWith(storeMutations.UPDATE_YEAR, payload.year);
}
@ -1782,8 +1626,8 @@ describe("Actions", () => {
if (context.state.order.vehicle.style !== payload.style) {
expect(commit).toBeCalledWith(storeMutations.UPDATE_STYLE, payload.style);
}
context.commit(storeMutations.UPDATE_CAR_ID, payload.vehicle.carId);
context.commit(storeMutations.UPDATE_VEHICLE_CATEGORY, payload.vehicle.category);
context.commit(storeMutations.UPDATE_CAR_ID, payload.carId);
context.commit(storeMutations.UPDATE_VEHICLE_CATEGORY, payload.category);
});
it("saveVehicleDamage, should wipe out damage if different", () => {