diff --git a/package-lock.json b/package-lock.json index 93875c8b..f7197f64 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1794,6 +1794,14 @@ "fastq": "^1.6.0" } }, + "@pinia/testing": { + "version": "0.0.14", + "resolved": "https://registry.npmjs.org/@pinia/testing/-/testing-0.0.14.tgz", + "integrity": "sha512-ZmZwVNd/NnKYLIfjfuKl0zlJ3UdiXFpsHzSlL6wCeezSlyrqGMxsIQKv0J6fleu38gyCNTPBEipfxrt8V4+VIg==", + "requires": { + "vue-demi": "*" + } + }, "@polka/url": { "version": "1.0.0-next.21", "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.21.tgz", diff --git a/package.json b/package.json index 9b586f69..e9250297 100644 --- a/package.json +++ b/package.json @@ -9,6 +9,7 @@ "test:unit:lite": "vue-cli-service test:unit --ci" }, "dependencies": { + "@pinia/testing": "0.0.14", "@popperjs/core": "^2.10.2", "axios": "^0.27.2", "bootstrap": "^5.2.2", diff --git a/src/helpers/unit-test-helper.js b/src/helpers/unit-test-helper.js new file mode 100644 index 00000000..87ed9f4c --- /dev/null +++ b/src/helpers/unit-test-helper.js @@ -0,0 +1,46 @@ +import { storeActions } from "@/constants/store-actions"; +import { navigationScenarios } from "@/router/router-constants/navigation-scenarios.js"; +import { vehicleCategories } from "@/constants/vehicle-categories.js"; +import { issPageValues } from "@/router/router-constants/issPage-values"; +import { Form } from "vee-validate"; +import { queryStrings } from "@/constants/query-strings"; +import { useMainStore } from "@/store"; +import { mapStores } from "pinia"; +import { createTestingPinia } from '@pinia/testing'; + +const pinia = createTestingPinia(); +useMainStore(pinia); + +const mockMixin = { + methods: { + getCmsContent: jest.fn() + }, + computed: { + ...mapStores(useMainStore), + } +}; + + +// Common methods +export function getMountOptions(mockData) { + // Define our mocks to attached to the 'global' object for Vue/Jest. + const mocks = {}; + + + // Mock const files + mocks.storeActions = storeActions; + mocks.navigationScenarios = navigationScenarios; + mocks.vehicleCategories = vehicleCategories; + mocks.issPageValues = issPageValues; + mocks.queryStrings = queryStrings; + + + const global = { + mocks: mocks, + mixins: [mockMixin], + plugins: [pinia], + stubs: { Form } + }; + + return { global }; +} diff --git a/src/layouts/vehicle-year/vehicle-year.spec.js b/src/layouts/vehicle-year/vehicle-year.spec.js new file mode 100644 index 00000000..21200c1b --- /dev/null +++ b/src/layouts/vehicle-year/vehicle-year.spec.js @@ -0,0 +1,87 @@ +import { shallowMount } from "@vue/test-utils"; +import { settleAllPromises } from "@/helpers/layout-helper.js"; +import { fetchCmsContentForPage } from "@/helpers/cms-content-helper"; +import vehicleYear from "@/layouts/vehicle-year/vehicle-year.vue"; +import yearQuestion from "@/layouts/vehicle-year/year-question/year-question"; +import baseMixin from "@/mixins/base-mixin.js"; +import { getMountOptions } from "@/helpers/unit-test-helper.js"; + + +// Mock our module for promises. +jest.mock("@/helpers/layout-helper.js", () => ({ + settleAllPromises: jest.fn(), +})); + +// Mock fetchCmsContentForPage +jest.mock("@/helpers/cms-content-helper", () => ({ + fetchCmsContentForPage: jest.fn(), +})); + +describe("vehicle-year.vue", () => { + test("Year question component is initized with api data", async() => { + //Arrange + const yearQuestionInitialData = ["2023", "2022", "2021"]; + const { wrapper, apiPromise } = setupMocks({ + yearQuestionInitialData: yearQuestionInitialData, + }); + + + //Act + vehicleYear.beforeRouteEnter.call( + wrapper.vm, + { query: { issPage: "vehicle-year" } }, + undefined, + (c) => c(wrapper.vm) + ); + + //Assert + apiPromise.finally(() => { + expect(yearQuestion.methods.initializeComponent).toHaveBeenCalledWith( + yearQuestionInitialData + ); + }); + }); +}); + +function setupMocks({ + vehicleYearQuestionCmsContent = {}, + yearQuestionInitialData = {}, + pageHeaderWidgetHeaderText = {}, + mountOptionsMockData = {}, +}) { + //Mock api responses + const apiResponses = { + cmsContent: { + SiteSubHeaderWidget: { HeaderText: pageHeaderWidgetHeaderText }, + VehicleYearQuestion: vehicleYearQuestionCmsContent, + VehicleBannerWidget: { + GenericVehicleImage: + "https://digitalisscms.dev.safelite.io/images/default-source/default-album/blurred-image.jpg", + }, + SiteHeaderWidget: { + LogoImage: + "https://digitalisscms.dev.safelite.io/images/default-source/default-album/logos/insuranceLogo.jpg", + }, + }, + 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 }; +} diff --git a/src/layouts/vehicle-year/year-question/year-question.spec.js b/src/layouts/vehicle-year/year-question/year-question.spec.js new file mode 100644 index 00000000..c6e17547 --- /dev/null +++ b/src/layouts/vehicle-year/year-question/year-question.spec.js @@ -0,0 +1,53 @@ +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 { useMainStore } from "@/store"; + +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 = [], +}) { + + const mountOptions = getMountOptions(); + + const store = useMainStore(); + store.getVehicleYears = jest.fn(() => dataFromStoreApi); + //Mock props + mountOptions.propsData = { + modelValue: modelValueProp, + }; + + const wrapper = shallowMount(yearQuestion, mountOptions); + + //Mock CMS content + const cmsContent = { + QuestionText: cmsQuestionText, + }; + return { wrapper, cmsContent }; +} diff --git a/src/router/router.spec.js b/src/router/router.spec.js index 8c15c36c..521b382e 100644 --- a/src/router/router.spec.js +++ b/src/router/router.spec.js @@ -1,5 +1,5 @@ -import router from "@/router/" -import { navigationScenarios } from "@/router/router-constants/navigation-scenarios" +import router from "@/router/"; +import { navigationScenarios } from "@/router/router-constants/navigation-scenarios"; import { issPageValues } from "@/router/router-constants/issPage-values"; import { createApp } from 'vue';