diff --git a/jest.config.js b/jest.config.js
index fd7713966..720237d10 100644
--- a/jest.config.js
+++ b/jest.config.js
@@ -16,7 +16,7 @@ module.exports = {
testMatch: ["**/*.spec.(js|jsx|ts|tsx)|**/__tests__/*.(js|jsx|ts|tsx)"],
coverageThreshold: {
global: {
- statements: 80,
+ statements: 85,
},
},
};
diff --git a/src/constants/store-mutations.js b/src/constants/store-mutations.js
index c6d8484da..d2ccd28f4 100644
--- a/src/constants/store-mutations.js
+++ b/src/constants/store-mutations.js
@@ -2,6 +2,7 @@ const storeMutations = {
UPDATE_YEAR: "updateYear",
UPDATE_MAKE: "updateMake",
UPDATE_MODEL: "updateModel",
+ UPDATE_STYLE: "updateStyle",
};
export { storeMutations };
diff --git a/src/layouts/vehicle-make/vehicle-make.spec.js b/src/layouts/vehicle-make/vehicle-make.spec.js
index cc2325dfc..120f8de4f 100644
--- a/src/layouts/vehicle-make/vehicle-make.spec.js
+++ b/src/layouts/vehicle-make/vehicle-make.spec.js
@@ -44,7 +44,6 @@ 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-style/style-question/style-question.spec.js b/src/layouts/vehicle-style/style-question/style-question.spec.js
new file mode 100644
index 000000000..f03ce5e96
--- /dev/null
+++ b/src/layouts/vehicle-style/style-question/style-question.spec.js
@@ -0,0 +1,82 @@
+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.setData({ selectedStyle: styleToSelect });
+ await wrapper.vm.$nextTick();
+
+ //Assert
+ expect(wrapper.emitted()["update:modelValue"][0]).toEqual(["4 Door"]);
+ });
+});
+
+describe("style-question.vue", () => {
+ test("CMS question text is used as radio question text.", async () => {
+
+ //Arrange
+ const { wrapper, cmsContent } = setupMocks({ cmsQuestionText: "What style is your vehicle?" });
+
+ //Act
+ styleQuestion.methods.initializeComponent.call(wrapper.vm, cmsContent, null);
+
+ //Assert
+ const buttonQuestionComponent = await wrapper.findComponent({ name: "buttonQuestion" });
+ expect(buttonQuestionComponent.attributes("questiontext")).toBe("What style is your vehicle?");
+ });
+});
+
+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, cmsContent, 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
+ mountOptions.propsData = {
+ modelValue: modelValueProp,
+ };
+ const wrapper = shallowMount(styleQuestion, mountOptions);
+
+ //Mock CMS content
+ const cmsContent = {
+ QuestionText: cmsQuestionText
+ };
+ return { wrapper, cmsContent };
+}
\ No newline at end of file
diff --git a/src/layouts/vehicle-style/style-question/style-question.vue b/src/layouts/vehicle-style/style-question/style-question.vue
new file mode 100644
index 000000000..17a008473
--- /dev/null
+++ b/src/layouts/vehicle-style/style-question/style-question.vue
@@ -0,0 +1,46 @@
+
+
+
+
+
diff --git a/src/layouts/vehicle-style/vehicle-style.spec.js b/src/layouts/vehicle-style/vehicle-style.spec.js
new file mode 100644
index 000000000..90dd6e926
--- /dev/null
+++ b/src/layouts/vehicle-style/vehicle-style.spec.js
@@ -0,0 +1,120 @@
+import { shallowMount, flushPromises } from "@vue/test-utils";
+import { getMountOptions } from "@/helpers/unit-test-helper.js";
+import vehicleStyle from "@/layouts/vehicle-style/vehicle-style.vue";
+import styleQuestion from "@/layouts/vehicle-style/style-question/style-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-style.vue", () => {
+ test("Style question component is initized with api data", async (done) => {
+
+ //Arrange
+ const radioQuestionCmsContent = { QuestionText: "What style is your vehicle?" };
+ const styleQuestionInitialData = ["2 Door", "4 Door"];
+ const { wrapper, apiPromise } = setupMocks( {
+ radioQuestionCmsContent: radioQuestionCmsContent,
+ 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(radioQuestionCmsContent, styleQuestionInitialData);
+ done();
+ });
+ });
+});
+
+describe("vehicle-style.vue", () => {
+ test("Page header is passed data from CMS", async (done) => {
+
+ //Arrange
+ const { wrapper, apiPromise } = setupMocks( { pageHeaderWidgetHeaderText: "Select a style to get started" });
+
+ //Act
+ vehicleStyle.beforeRouteEnter.call(wrapper.vm, { query: { fmgPage: "vehicle-style" } }, undefined, (c) => c(wrapper.vm));
+
+ //Assert
+ const header = await wrapper.find(".Header");
+ apiPromise.finally(() => {
+ expect(header.attributes("text")).toEqual("Select a style to get started");
+ done();
+ });
+ });
+});
+
+describe("vehicle-style.vue", () => {
+ test("BackButtonAction triggers a router.navigate change", async (done) => {
+
+ //Arrange
+ const { wrapper, apiPromise } = setupMocks( {
+ pageHeaderWidgetHeaderText: "Select a style to get started",
+ mountOptionsMockData: {
+ router: {
+ navigate: 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.navigate).toHaveBeenCalled();
+ done();
+ });
+ });
+});
+
+function setupMocks({
+ radioQuestionCmsContent = {},
+ styleQuestionInitialData = {},
+ pageHeaderWidgetHeaderText = {},
+ mountOptionsMockData = {},
+}) {
+
+ //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",
+ },
+ ],
+ },
+ styleQuestionInitialData: styleQuestionInitialData,
+ };
+ const apiPromise = Promise.resolve(apiResponses);
+ settleAllPromises.mockImplementation(() => apiPromise);
+
+ //Mock style question methods
+ styleQuestion.methods = {
+ loadInitialData: jest.fn(),
+ initializeComponent: jest.fn(),
+ };
+ const mountOptions = getMountOptions(mountOptionsMockData);
+ const wrapper = shallowMount(vehicleStyle, mountOptions);
+ const styleQuestionWrapper = wrapper.findComponent({ name: "styleQuestion" });
+ styleQuestionWrapper.vm.initializeComponent = styleQuestion.methods.initializeComponent;
+
+ return { wrapper, apiPromise };
+}
\ No newline at end of file
diff --git a/src/layouts/vehicle-style/vehicle-style.vue b/src/layouts/vehicle-style/vehicle-style.vue
new file mode 100644
index 000000000..6b5d4bf86
--- /dev/null
+++ b/src/layouts/vehicle-style/vehicle-style.vue
@@ -0,0 +1,90 @@
+
+
+
+
+
diff --git a/src/router/router-constants/navigation-scenarios.js b/src/router/router-constants/navigation-scenarios.js
index 65947744e..48e36996b 100644
--- a/src/router/router-constants/navigation-scenarios.js
+++ b/src/router/router-constants/navigation-scenarios.js
@@ -2,6 +2,7 @@ const navigationScenarios = {
SELECTED_YEAR: "SELECTED_YEAR",
SELECTED_MODEL: "SELECTED_MODEL",
SELECTED_MAKE: "SELECTED_MAKE",
+ SELECTED_STYLE: "SELECTED_STYLE",
CLICKED_BACK: "CLICKED_BACK",
};
diff --git a/src/router/router-constants/routing-table.js b/src/router/router-constants/routing-table.js
index 34f4c5579..21dc6ca65 100644
--- a/src/router/router-constants/routing-table.js
+++ b/src/router/router-constants/routing-table.js
@@ -37,6 +37,19 @@ const routingTable = [
}
],
},
+ {
+ fmgPageValue: fmgPageValues.VEHICLE_STYLE,
+ maps: [
+ {
+ scenario: navigationScenarios.SELECTED_STYLE,
+ destinationFmgPageValue: fmgPageValues.VEHICLE_STYLE,
+ },
+ {
+ scenario: navigationScenarios.CLICKED_BACK,
+ destinationFmgPageValue: fmgPageValues.VEHICLE_MODEL,
+ }
+ ],
+ },
];
export { routingTable };
\ No newline at end of file
diff --git a/src/store/index.js b/src/store/index.js
index 5e21f7ce4..daf34e38c 100644
--- a/src/store/index.js
+++ b/src/store/index.js
@@ -70,6 +70,9 @@ export default createStore({
updateModel(state, model) {
state.order.vehicle.model = model;
},
+ updateStyle(state, style) {
+ state.order.vehicle.style = style;
+ },
},
getters: {
vehicle: state => state.order.vehicle
diff --git a/src/store/store.spec.js b/src/store/store.spec.js
index 76acc0dbf..fcfca4576 100644
--- a/src/store/store.spec.js
+++ b/src/store/store.spec.js
@@ -118,6 +118,73 @@ describe("Actions", () => {
// Assert
expect(pageData).toBe("Page Info Data");
});
+
+ it("Should return data from url retrieved", async () => {
+ // Arrange
+ let returnData = [];
+
+ // Act
+ globalMethods.callHttpClient.mockImplementation(() => {
+ return Promise.resolve({
+ data: {
+ Result: "2018 Honda Civic",
+ },
+ });
+ });
+ await store
+ .dispatch("lookupVehicleByYmms", { year: "2018", make: "Honda", model: "Civic", style: "2 Door"})
+ .then((response) => {
+ returnData = response.data.Result;
+ });
+
+ // Assert
+ expect(returnData).toBe("2018 Honda Civic");
+ });
+
+ it("Should return vehicle data from url retrieved", async () => {
+ // Arrange
+ let returnData = [];
+
+ // Act
+ globalMethods.callHttpClient.mockImplementation(() => {
+ return Promise.resolve({
+ data: {
+ Result: "2021 Honda Civic",
+ },
+ });
+ });
+ await store
+ .dispatch("lookupVehicleByVin", { vin: "12345678"})
+ .then((response) => {
+ returnData = response.data.Result;
+ });
+
+ // Assert
+ expect(returnData).toBe("2021 Honda Civic");
+ });
+
+ it("Should return vehicle image data from url retrieved", async () => {
+ // Arrange
+ let returnData = [];
+
+ // Act
+ globalMethods.callMockHttpClient = jest.fn();
+ globalMethods.callMockHttpClient.mockImplementation(() => {
+ return Promise.resolve({
+ data: {
+ Result: "2008_honda_civic.jpg",
+ },
+ });
+ });
+ await store
+ .dispatch("getEvoxImage", { relativeUrl: "evox_image.com"})
+ .then((response) => {
+ returnData = response.data.Result;
+ });
+
+ // Assert
+ expect(returnData).toBe("2008_honda_civic.jpg");
+ });
});
describe("Mutations", () => {
@@ -128,4 +195,34 @@ describe("Mutations", () => {
// Assert
expect(store.state.order.vehicle.year).toBe(2020);
});
+
+ it("Should update the make property in the store", () => {
+ // Act
+ store.commit("updateMake", "Honda");
+
+ // Assert
+ expect(store.state.order.vehicle.make).toBe("Honda");
+ });
+
+ it("Should update the model property in the store", () => {
+ // Act
+ store.commit("updateModel", "Civic");
+
+ // Assert
+ expect(store.state.order.vehicle.model).toBe("Civic");
+ });
+
+ it("Should update the style property in the store", () => {
+ // Act
+ store.commit("updateStyle", "2 Door");
+
+ // Assert
+ expect(store.state.order.vehicle.style).toBe("2 Door");
+ });
+});
+
+describe("Getters", () => {
+ const vehicle = store.getters.vehicle;
+
+ expect(typeof vehicle).toBe('object');
});