diff --git a/src/common-components/button-question/button-question.spec.js b/src/common-components/button-question/button-question.spec.js index e59b6da39..67e2f010e 100644 --- a/src/common-components/button-question/button-question.spec.js +++ b/src/common-components/button-question/button-question.spec.js @@ -1,25 +1,6 @@ import { shallowMount } from "@vue/test-utils"; import buttonQuestion from "@/common-components/button-question/button-question"; -describe("buttonQuestion.vue", () => { - it("Should render the 'questionText' prop value as a span value for the button question and the 'answer' values should render as text values for button components.", async () => { - // Act - const wrapper = shallowMount(buttonQuestion); - await wrapper.setProps({ - questionText: "Question Text", - answers: ["2023", "2022", "2021"], - modelValue: "2020", - }); - wrapper.vm.chooseAnswer("2021"); - - // Assert - expect(wrapper.find(".text-center").text()).toEqual("Question Text"); - const buttonButtons = wrapper.findAllComponents('[data-test="button"]'); - expect(buttonButtons.length).toBe(3); - expect(wrapper.props().modelValue).toBe("2020"); - }); -}); - describe("buttonQuestion.vue", () => { it("Should show overflow classes on fieldset if isOverflowScrollable is true", async () => { // Act @@ -34,7 +15,7 @@ describe("buttonQuestion.vue", () => { }); describe("buttonQuestion.vue", () => { - it("Should show appropriate classes for button type", async () => { + it("Fieldset classes should contain row if button type is listCard", async () => { // Act const wrapper = shallowMount(buttonQuestion); await wrapper.setProps({ @@ -46,6 +27,19 @@ describe("buttonQuestion.vue", () => { }); }); +describe("buttonQuestion.vue", () => { + it("Fieldset classes should contain d-flex if button type is listButtonHorizontal", async () => { + // Act + const wrapper = shallowMount(buttonQuestion); + await wrapper.setProps({ + buttonType: "listButtonHorizontal", + }); + // Assert + const Div = wrapper.find('fieldset div'); + expect(Div.classes()).toContain("d-flex"); + }); +}); + describe("buttonQuestion.vue", () => { it("Should trigger event modelValue change on select", async () => { // Act @@ -68,7 +62,7 @@ describe("buttonQuestion.vue", () => { await wrapper.setData({ modelValueAnswers: ["Windshield", "BackDoor"] }); - wrapper.vm.isItemChecked(true); + wrapper.vm.handleCheckedChanged(true); // Assert expect(typeof wrapper.emitted()["update:modelValue"][0]).toEqual('object'); }); @@ -78,8 +72,13 @@ describe("buttonQuestion.vue", () => { it("Should not trigger event modelValue change on select if checked is false", async () => { // Act const wrapper = shallowMount(buttonQuestion); - wrapper.vm.isItemChecked(false); + wrapper.setData({ + modelValueAnswers: ["Front-door"] + }) + const val = {isChecked : false, buttonId: "Front-door"} + wrapper.vm.handleCheckedChanged(val); // Assert expect(wrapper.emitted()["update:modelValue"][0]).toEqual([undefined]); }); -}); \ No newline at end of file +}); + diff --git a/src/common-components/button-question/button-question.vue b/src/common-components/button-question/button-question.vue index 857e3e621..22756d683 100644 --- a/src/common-components/button-question/button-question.vue +++ b/src/common-components/button-question/button-question.vue @@ -11,9 +11,7 @@ :is="buttonType" v-for="answer in answers" :key="answer.Name ? answer.Name : answer" - @mouseup="chooseAnswer(answer.Name ? answer.Name : answer)" - @keyup.space="chooseAnswer(answer.Name ? answer.Name : answer)" - @isChecked="isItemChecked" + @isChecked="handleCheckedChanged" :buttonID="answer.Name ? answer.Name : answer" :value="answer.Name ? answer.Name : answer" :buttonLabel="answer.Text ? answer.Text : answer" @@ -32,6 +30,7 @@ :altText="answer.Name ? answer.Name : answer" screenReaderOnlyText="(opens new window)" :colLength="this.answers.length < 3 ? '' : '-4'" + v-model="modelValue" data-test="button" /> @@ -76,7 +75,7 @@ export default { isRequired: Boolean, isOverflowScrollable: Boolean, isWide: Boolean, - modelValue: [Array, String], + modelValue: Array, }, computed: { getFieldSetClasses() { @@ -103,23 +102,19 @@ export default { data(){ return { modelValueAnswers: [], - chosenAnswer: String } }, created(){ if(Array.isArray(this.answers) && this.answers.length === 1) { - const onlyAnswer = typeof(this.answers[0]) === 'object' ? this.answers[0].Name : this.answers[0]; - this.$emit("update:modelValue", onlyAnswer); - } + this.modelValueAnswers.push(typeof(this.answers[0]) === 'object' ? this.answers[0].Name : this.answers[0]); + this.$emit("update:modelValue", this.modelValueAnswers); + }; + this.modelValueAnswers = this.modelValue; }, methods: { - chooseAnswer(answer) { - this.chosenAnswer = answer; - }, - isItemChecked(val) { + handleCheckedChanged(val) { // Add or remove item to array of data to emit - val ? this.modelValueAnswers.push(this.chosenAnswer) : this.modelValueAnswers.splice(this.modelValueAnswers.indexOf(this.chosenAnswer), 1); - + val.isChecked ? this.modelValueAnswers.push(val.buttonId) : this.modelValueAnswers.splice(this.modelValueAnswers.indexOf(val.buttonId), 1); this.$emit("update:modelValue", this.modelValueAnswers.length ? this.modelValueAnswers : undefined); }, }, diff --git a/src/layouts/vehicle-damage/damage-location-question/damage-location-question.spec.js b/src/layouts/vehicle-damage/damage-location-question/damage-location-question.spec.js new file mode 100644 index 000000000..01f063eef --- /dev/null +++ b/src/layouts/vehicle-damage/damage-location-question/damage-location-question.spec.js @@ -0,0 +1,83 @@ +import { shallowMount } from "@vue/test-utils"; +import damageLocationQuestion from "@/layouts/vehicle-damage/damage-location-question/damage-location-question"; +import { getMountOptions } from "@/helpers/unit-test-helper.js"; +import store from "@/store"; +jest.mock("@/store", () => { return {}; }, {virtual: true}); + +describe("damage-location-question.vue", () => { + test("Selected location option is emitted upon selection.", async () => { + + //Arrange + const { wrapper } = setupMocks({ modelValueProp: ["Windshield"] }); + const locationToSelect = ["Backseat"]; + + //Act + wrapper.setValue({ modelValue: locationToSelect }); + await wrapper.vm.$nextTick(); + + //Assert + expect(wrapper.emitted()["update:modelValue"][0]).toEqual([{modelValue: ["Backseat"]}]); + }); + }); + + describe("damage-location-question.vue", () => { + test("Answers to display filtered by data from api.", async () => { + + //Arrange + const { wrapper, cmsContent, damageOptions } = setupMocks({ dataFromStoreApi: { + driverSideOptions: { + availableReplacementOptions: ['Quarter', 'Front'] + }, + windshieldOptions: { + availableReplacementOptions: ['Single'] + }, + backGlassOptions: { + availableReplacementOptions: [] + } + } + }); + + //Act + damageLocationQuestion.methods.initializeComponent.call(wrapper.vm, cmsContent, damageOptions, "car-group"); + + //Assert + expect(wrapper.vm.answersToDisplay).toStrictEqual([ { Name: 'car-Windshield' }, { Name: 'car-SideDoor' } ]) + }); + }); + + function setupMocks({ + modelValueProp = ["Windshield", "SideDoor"], + isMultiSelect = false, + groupName = "damageQuestion", + cmsQuestionText = "CMS text goes here", + cmsAnswers = [{Name: "car-Windshield"}, {Name: "car-SideDoor"}, {Name: "car-RearWindow"}], + dataFromStoreApi = [], + }) { + + //Mock store + store.dispatch = jest.fn(() => dataFromStoreApi); + store.getters = { vehicle: {year: 2019, make: 'honda', model: 'civc', style: '2 Door', category: 'CAR'} }; + const mountOptions = getMountOptions({ + store: { + dispatch: store.dispatch, + getters: store.getters, + }, + }); + + //Mock props + mountOptions.propsData = { + modelValue: modelValueProp, + isMultiSelect: isMultiSelect, + }; + + const wrapper = shallowMount(damageLocationQuestion, mountOptions); + + //Mock CMS content + const cmsContent = { + groupName: groupName, + QuestionText: cmsQuestionText, + Answers: cmsAnswers, + }; + const damageOptions = dataFromStoreApi; + return { wrapper, cmsContent, damageOptions }; + } \ No newline at end of file diff --git a/src/layouts/vehicle-damage/damage-location-question/damage-location-question.vue b/src/layouts/vehicle-damage/damage-location-question/damage-location-question.vue new file mode 100644 index 000000000..97c08c3b8 --- /dev/null +++ b/src/layouts/vehicle-damage/damage-location-question/damage-location-question.vue @@ -0,0 +1,68 @@ + + + \ No newline at end of file diff --git a/src/layouts/vehicle-damage/vehicle-damage.spec.js b/src/layouts/vehicle-damage/vehicle-damage.spec.js index caf008b78..7817d743c 100644 --- a/src/layouts/vehicle-damage/vehicle-damage.spec.js +++ b/src/layouts/vehicle-damage/vehicle-damage.spec.js @@ -3,7 +3,8 @@ import vehicleDamage from "@/layouts/vehicle-damage/vehicle-damage.vue"; import funnelHeader from "@/common-components/funnel-header/funnel-header"; import vehicleBanner from "@/common-components/vehicle-banner/vehicle-banner"; import funnelSubHeader from "@/common-components/funnel-sub-header/funnel-sub-header"; -import replaceOptionsQuestion from"@/layouts/vehicle-damage/replace-options-question/replace-options-question"; +import replaceOptionsQuestion from "@/layouts/vehicle-damage/replace-options-question/replace-options-question"; +import damageLocationQuestion from "@/layouts/vehicle-damage/damage-location-question/damage-location-question"; // Supporting Files import { settleAllPromises } from "@/helpers/layout-helper.js"; @@ -192,6 +193,10 @@ function setupMocks({ initializeComponent: jest.fn(), }; + damageLocationQuestion.methods = { + initializeComponent: jest.fn(), + } + const mountOptions = getMountOptions(mountOptionsMockData); const wrapper = shallowMount(vehicleDamage, mountOptions); @@ -215,5 +220,11 @@ function setupMocks({ driverSideOptionsWrapper.vm.initializeComponent = replaceOptionsQuestion.methods.initializeComponent; + const damageLocationQuestionWrapper = wrapper.findComponent({ + name: "damageLocationQuestion", + }); + damageLocationQuestionWrapper.vm.initializeComponent = + damageLocationQuestion.methods.initializeComponent; + return { wrapper, apiPromise }; } diff --git a/src/layouts/vehicle-damage/vehicle-damage.vue b/src/layouts/vehicle-damage/vehicle-damage.vue index ba46df331..c820832de 100644 --- a/src/layouts/vehicle-damage/vehicle-damage.vue +++ b/src/layouts/vehicle-damage/vehicle-damage.vue @@ -5,7 +5,8 @@ - + + @@ -15,6 +16,7 @@ import funnelHeader from "@/common-components/funnel-header/funnel-header"; import vehicleBanner from "@/common-components/vehicle-banner/vehicle-banner"; import funnelSubHeader from "@/common-components/funnel-sub-header/funnel-sub-header"; import replaceOptionsQuestion from"@/layouts/vehicle-damage/replace-options-question/replace-options-question"; +import damageLocationQuestion from"@/layouts/vehicle-damage/damage-location-question/damage-location-question"; // Supporting files import { fetchCmsContentForPage } from "@/helpers/cms-content-helper"; import { settleAllPromises } from "@/helpers/layout-helper"; @@ -61,10 +63,20 @@ export default { vm.$refs.driverSideOptions.initializeComponent( resultMap.cmsContent.DriverSideReplaceOptionsQuestion, resultMap.damageOptions.driverSideOptions.availableReplacementOptions, 'DriverSideReplaceOptionsQuestion' ); + vm.$refs.damageLocation.initializeComponent( + resultMap.cmsContent.DamageLocationQuestion, resultMap.damageOptions, 'DamageLocationQuestion' + ); - //console.log(resultMap) for damageOptions and cms content data + // for damageOptions and cms content data + //console.log(resultMap) }); }, + data(){ + return { + damageLocationQuestionData: [], + driverSideOptionsData: [], + } + }, methods: { arePagePrerequisitesValid() { return store.getters.vehicle.carId !== null; @@ -75,6 +87,7 @@ export default { vehicleBanner, funnelSubHeader, replaceOptionsQuestion, + damageLocationQuestion, }, }; diff --git a/src/layouts/vehicle-make/make-question/make-question.vue b/src/layouts/vehicle-make/make-question/make-question.vue index 2a94deafe..70ba0f909 100644 --- a/src/layouts/vehicle-make/make-question/make-question.vue +++ b/src/layouts/vehicle-make/make-question/make-question.vue @@ -27,7 +27,7 @@ export default { }; }, props: { - modelValue: String, + modelValue: Array, }, components: { buttonQuestion, diff --git a/src/layouts/vehicle-make/vehicle-make.vue b/src/layouts/vehicle-make/vehicle-make.vue index 111b16e5f..087a10d8b 100644 --- a/src/layouts/vehicle-make/vehicle-make.vue +++ b/src/layouts/vehicle-make/vehicle-make.vue @@ -30,7 +30,7 @@ export default { name: "vehicle-make", data() { return { - selectedMake: null, + selectedMake: [], }; }, computed: {}, diff --git a/src/layouts/vehicle-model/model-question/model-question.vue b/src/layouts/vehicle-model/model-question/model-question.vue index 34a811e27..312d6c45f 100644 --- a/src/layouts/vehicle-model/model-question/model-question.vue +++ b/src/layouts/vehicle-model/model-question/model-question.vue @@ -27,7 +27,7 @@ export default { }; }, props: { - modelValue: String, + modelValue: Array, }, components: { buttonQuestion, diff --git a/src/layouts/vehicle-model/vehicle-model.vue b/src/layouts/vehicle-model/vehicle-model.vue index b27b98d40..917fcd348 100644 --- a/src/layouts/vehicle-model/vehicle-model.vue +++ b/src/layouts/vehicle-model/vehicle-model.vue @@ -31,7 +31,7 @@ export default { name: "vehicle-model", data() { return { - selectedModel: null, + selectedModel: [], }; }, computed: {}, diff --git a/src/layouts/vehicle-style/style-question/style-question.vue b/src/layouts/vehicle-style/style-question/style-question.vue index f82ac6981..2af223011 100644 --- a/src/layouts/vehicle-style/style-question/style-question.vue +++ b/src/layouts/vehicle-style/style-question/style-question.vue @@ -27,7 +27,7 @@ export default { }; }, props: { - modelValue: String, + modelValue: Array, }, components: { buttonQuestion, diff --git a/src/layouts/vehicle-style/vehicle-style.vue b/src/layouts/vehicle-style/vehicle-style.vue index 7193c9e39..7adff0b73 100644 --- a/src/layouts/vehicle-style/vehicle-style.vue +++ b/src/layouts/vehicle-style/vehicle-style.vue @@ -31,7 +31,7 @@ export default { name: "vehicle-style", data() { return { - selectedStyle: null, + selectedStyle: [], }; }, computed: {}, diff --git a/src/layouts/vehicle-year/vehicle-year.vue b/src/layouts/vehicle-year/vehicle-year.vue index ddef0d5a8..afcece898 100644 --- a/src/layouts/vehicle-year/vehicle-year.vue +++ b/src/layouts/vehicle-year/vehicle-year.vue @@ -26,7 +26,7 @@ export default { name: "vehicle-year", data() { return { - selectedYear: null, + selectedYear: [], }; }, computed: {}, diff --git a/src/layouts/vehicle-year/year-question/year-question.vue b/src/layouts/vehicle-year/year-question/year-question.vue index 3fa7de233..36af97bca 100644 --- a/src/layouts/vehicle-year/year-question/year-question.vue +++ b/src/layouts/vehicle-year/year-question/year-question.vue @@ -26,7 +26,7 @@ export default { }; }, props: { - modelValue: String, + modelValue: Array, }, emits: ['update:modelValue'], components: { diff --git a/src/ux-components/list-button-horizontal/list-button-horizontal.vue b/src/ux-components/list-button-horizontal/list-button-horizontal.vue index aa574c559..ece75e042 100644 --- a/src/ux-components/list-button-horizontal/list-button-horizontal.vue +++ b/src/ux-components/list-button-horizontal/list-button-horizontal.vue @@ -11,7 +11,7 @@ :value="buttonID" :aria-required="isRequired" :data-focus-target="groupName" - v-model="modelValue" + v-model="checkValue" />