diff --git a/src/common-components/button-question/button-question.vue b/src/common-components/button-question/button-question.vue index e1fee1e40..d86dcd2ce 100644 --- a/src/common-components/button-question/button-question.vue +++ b/src/common-components/button-question/button-question.vue @@ -10,7 +10,8 @@ {{groupName}} diff --git a/src/constants/store-mutations.js b/src/constants/store-mutations.js index d9292b5f8..c6d8484da 100644 --- a/src/constants/store-mutations.js +++ b/src/constants/store-mutations.js @@ -1,5 +1,7 @@ const storeMutations = { UPDATE_YEAR: "updateYear", + UPDATE_MAKE: "updateMake", + UPDATE_MODEL: "updateModel", }; export { storeMutations }; diff --git a/src/layouts/vehicle-make/vehicle-make.spec.js b/src/layouts/vehicle-make/vehicle-make.spec.js index 120f8de4f..cc2325dfc 100644 --- a/src/layouts/vehicle-make/vehicle-make.spec.js +++ b/src/layouts/vehicle-make/vehicle-make.spec.js @@ -44,6 +44,7 @@ describe("vehicle-make.vue", () => { //Assert const header = await wrapper.find(".Header"); apiPromise.finally(() => { + console.log(header) expect(header.attributes("text")).toEqual("Select a make to get started"); done(); }); diff --git a/src/layouts/vehicle-model/model-question/model-question.spec.js b/src/layouts/vehicle-model/model-question/model-question.spec.js new file mode 100644 index 000000000..d6259eb72 --- /dev/null +++ b/src/layouts/vehicle-model/model-question/model-question.spec.js @@ -0,0 +1,82 @@ +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.setData({ selectedModel: modelToSelect }); + await wrapper.vm.$nextTick(); + + //Assert + expect(wrapper.emitted()["update:modelValue"][0]).toEqual(["Civic"]); + }); +}); + +describe("model-question.vue", () => { + test("CMS question text is used as radio question text.", async () => { + + //Arrange + const { wrapper, cmsContent } = setupMocks({ cmsQuestionText: "What model is your vehicle?" }); + + //Act + modelQuestion.methods.initializeComponent.call(wrapper.vm, cmsContent, null); + + //Assert + const buttonQuestionComponent = await wrapper.findComponent({ name: "buttonQuestion" }); + expect(buttonQuestionComponent.attributes("questiontext")).toBe("What model is your vehicle?"); + }); +}); + +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, cmsContent, 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 + mountOptions.propsData = { + modelValue: modelValueProp, + }; + const wrapper = shallowMount(modelQuestion, mountOptions); + + //Mock CMS content + const cmsContent = { + QuestionText: cmsQuestionText + }; + return { wrapper, cmsContent }; +} \ No newline at end of file diff --git a/src/layouts/vehicle-model/model-question/model-question.vue b/src/layouts/vehicle-model/model-question/model-question.vue new file mode 100644 index 000000000..95b72909b --- /dev/null +++ b/src/layouts/vehicle-model/model-question/model-question.vue @@ -0,0 +1,46 @@ + + + diff --git a/src/layouts/vehicle-model/vehicle-model.spec.js b/src/layouts/vehicle-model/vehicle-model.spec.js new file mode 100644 index 000000000..8ee3885de --- /dev/null +++ b/src/layouts/vehicle-model/vehicle-model.spec.js @@ -0,0 +1,93 @@ +import { shallowMount, flushPromises } from "@vue/test-utils"; +import { getMountOptions } from "@/helpers/unit-test-helper.js"; +import vehicleModel from "@/layouts/vehicle-model/vehicle-model.vue"; +import modelQuestion from "@/layouts/vehicle-model/model-question/model-question"; +import { settleAllPromises } from "@/helpers/layout-helper.js"; +import { nextTick } from "vue"; + +// Mock our module for promises. +jest.mock("@/helpers/layout-helper.js", () => ({ + settleAllPromises: jest.fn(), +})); + +describe("vehicle-model.vue", () => { + test("Model question component is initized with api data", async (done) => { + + //Arange + const radioQuestionCmsContent = { QuestionText: "What model is your vehicle?" }; + const modelQuestionInitialData = ["accord", "civic", "insight"]; + const { wrapper, apiPromise } = setupMocks( { + radioQuestionCmsContent: radioQuestionCmsContent, + 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(radioQuestionCmsContent, modelQuestionInitialData); + done(); + }); + }); +}); + +describe("vehicle-model.vue", () => { + test("Page header is passed data from CMS", async (done) => { + + //Arange + const { wrapper, apiPromise } = setupMocks( { pageHeaderWidgetHeaderText: "Select a model to get started" }); + + //Act + vehicleModel.beforeRouteEnter.call(wrapper.vm, { query: { fmgPage: "vehicle-model" } }, undefined, (c) => c(wrapper.vm)); + + //Assert + const header = await wrapper.find(".Header"); + apiPromise.finally(() => { + expect(header.attributes("text")).toEqual("Select a model to get started"); + done(); + }); + }); +}); + +function setupMocks({ + radioQuestionCmsContent = {}, + modelQuestionInitialData = {}, + pageHeaderWidgetHeaderText = {}, +}) { + + //Mock api responses + const apiResponses = { + cmsContent: { + PageHeaderWidget: [{ HeaderText: pageHeaderWidgetHeaderText }], + RadioQuestionWidget: [radioQuestionCmsContent], + VehicleBannerWidget: [ + { + GenericVehicleImage: + "https://digitalconsumercms-dev.safelite.com/images/default-source/default-album/blurred-image.jpg?sfvrsn=a6ce3034_3", + }, + ], + SiteHeaderWidget: [ + { + 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); + + //Mock model question methods + modelQuestion.methods = { + loadInitialData: jest.fn(), + initializeComponent: jest.fn(), + }; + const mountOptions = getMountOptions({ }); + const wrapper = shallowMount(vehicleModel, mountOptions); + const modelQuestionWrapper = wrapper.findComponent({ name: "modelQuestion" }); + modelQuestionWrapper.vm.initializeComponent = modelQuestion.methods.initializeComponent; + + return { wrapper, apiPromise }; +} \ No newline at end of file diff --git a/src/layouts/vehicle-model/vehicle-model.vue b/src/layouts/vehicle-model/vehicle-model.vue new file mode 100644 index 000000000..1d86c99b4 --- /dev/null +++ b/src/layouts/vehicle-model/vehicle-model.vue @@ -0,0 +1,90 @@ + + + diff --git a/src/store/index.js b/src/store/index.js index 1bf7243b7..5e21f7ce4 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -64,6 +64,12 @@ export default createStore({ updateYear(state, year) { state.order.vehicle.year = year; }, + updateMake(state, make) { + state.order.vehicle.make = make; + }, + updateModel(state, model) { + state.order.vehicle.model = model; + }, }, getters: { vehicle: state => state.order.vehicle