From 3ce1854153c5f3ee890596034cc272f2b0c719de Mon Sep 17 00:00:00 2001 From: Leah Schumann Date: Tue, 14 Jun 2022 16:54:26 -0400 Subject: [PATCH 1/5] Set backButtonAccessibleText to come from CMS --- .../funnel-sub-header/funnel-sub-header.vue | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/common-components/funnel-sub-header/funnel-sub-header.vue b/src/common-components/funnel-sub-header/funnel-sub-header.vue index f8ac3134a..3ad7c71d3 100644 --- a/src/common-components/funnel-sub-header/funnel-sub-header.vue +++ b/src/common-components/funnel-sub-header/funnel-sub-header.vue @@ -29,20 +29,22 @@ export default { name: "FunnelSubHeader", props: { hasBackButton: Boolean, - backButtonAccessibleText: String, cmsWidgetName: String, }, components: { buttonBack, }, computed: { - text(){ + text() { return this.getCmsContent(this.cmsWidgetName, 'HeaderText'); }, - subText(){ + subText() { return this.getCmsContent(this.cmsWidgetName, 'HeaderSubText'); }, - headerColor(){ + backButtonAccessibleText() { + return this.getCmsContent(this.cmsWidgetName, 'BackButtonAccessibleText'); + }, + headerColor() { return this.subText ? 'dark-header' : 'light-header'; } }, From 67ba6a1e0cbb6c94a0e7c2cb70099c5101d4f6a5 Mon Sep 17 00:00:00 2001 From: Bryan Mauger Date: Thu, 16 Jun 2022 15:21:37 -0400 Subject: [PATCH 2/5] CSR-465 Add validation to parts page. --- .../glass-part-question.vue | 8 + src/layouts/vehicle-parts/vehicle-parts.vue | 359 +++++++++--------- 2 files changed, 198 insertions(+), 169 deletions(-) diff --git a/src/layouts/vehicle-parts/glass-part-question/glass-part-question.vue b/src/layouts/vehicle-parts/glass-part-question/glass-part-question.vue index 7d936c5bf..d0def364d 100644 --- a/src/layouts/vehicle-parts/glass-part-question/glass-part-question.vue +++ b/src/layouts/vehicle-parts/glass-part-question/glass-part-question.vue @@ -29,7 +29,11 @@ :buttonID="`${glassLocation}-${glassName}-${name}`" :groupName="`${glassLocation}-${glassName}`" @isCheckedChanged="ResetTintAndPartSelections()" + :validationRules="validationRules" /> +
+ +
@@ -53,6 +57,7 @@ :loaderEnabled="false" isRequired :groupName="`${glassLocation}-${glassName}-${name}`" + :validationRules="validationRules" /> @@ -68,6 +73,7 @@ import buttonQuestion from "@/common-components/button-question/button-question" // Supporting files import { getTintImage } from "@/constants/tint-mapper"; import { getCustomTransformValue } from "@/constants/dynamictext-mapper"; +import { ErrorMessage } from 'vee-validate'; export default { name: "glass-part-question", @@ -84,6 +90,7 @@ export default { glassLocation: String, colorAnswers: Array, modelValue: Object, + validationRules: String, }, mounted() { this.LoadPreselectedValues(); @@ -91,6 +98,7 @@ export default { components: { listCard, buttonQuestion, + ErrorMessage, }, computed: { colorQuestionText() { diff --git a/src/layouts/vehicle-parts/vehicle-parts.vue b/src/layouts/vehicle-parts/vehicle-parts.vue index d876f132f..a16d0b0a8 100644 --- a/src/layouts/vehicle-parts/vehicle-parts.vue +++ b/src/layouts/vehicle-parts/vehicle-parts.vue @@ -1,5 +1,11 @@ From e9af0c64a511753306a82e30737491a9d10999d0 Mon Sep 17 00:00:00 2001 From: Adam Caouette Date: Fri, 17 Jun 2022 09:24:52 -0400 Subject: [PATCH 3/5] CSR-480: add unit tests --- jest.config.js | 3 - .../question-chain/question-chain.spec.js | 241 ++++++++++++++++++ .../question-chain/question-chain.vue | 10 +- .../address-vehicles-question.spec.js | 1 - 4 files changed, 247 insertions(+), 8 deletions(-) create mode 100644 src/common-components/question-chain/question-chain.spec.js diff --git a/jest.config.js b/jest.config.js index 017648108..b66199733 100644 --- a/jest.config.js +++ b/jest.config.js @@ -20,11 +20,8 @@ module.exports = { "!src/layouts/reveal/**/*.vue", "!src/layouts/estimate/**/*.vue", // TODO REMOVE THESE AFTER WRITING UNIT TESTS - "!src/layouts/address-vehicles/address-vehicles.vue", - "!src/layouts/address-vehicles/address-vehicles-question/address-vehicles-question.vue", "!src/ux-components/alert\alert.vue", "!src/helpers/validation-rules.js", - "!src/common-components/question-chain/question-chain", // END ], // ! means exclude from coverage. testMatch: ["**/*.spec.(js|jsx|ts|tsx)|**/__tests__/*.(js|jsx|ts|tsx)"], diff --git a/src/common-components/question-chain/question-chain.spec.js b/src/common-components/question-chain/question-chain.spec.js new file mode 100644 index 000000000..84795fac0 --- /dev/null +++ b/src/common-components/question-chain/question-chain.spec.js @@ -0,0 +1,241 @@ +import { shallowMount } from "@vue/test-utils"; +import questionChain from "@/common-components/question-chain/question-chain.vue"; +import { getMountOptions } from "@/helpers/unit-test-helper.js"; +import store from "@/store"; +jest.mock("@/store",()=>{return{};},{virtual:true}); + +describe("Question Chain component", () => { + + it("Should not emit a modelValue change when setting selectedValue if isNewModelValueComplete is false", () => { + + //Arrange + const { wrapper } = setupMocks({ modelValueProp: [] }); + wrapper.vm.currentQuestion = 6; + const answerReturned = [wrapper.vm.questions[wrapper.vm.currentQuestion].answers[0].Name.toString()]; + const localThis = { + $emit: jest.fn(), + getNewModelValue: jest.fn(() => { return false }) + } + + //Act + questionChain.computed.selectedValue.set.call(localThis, answerReturned); + + //Assert + expect(localThis.$emit).not.toBeCalled(); + }); + + it("Should emit a modelValue change when setting selectedValue if isNewModelValueComplete is true", () => { + + //Arrange + const { wrapper } = setupMocks({ modelValueProp: [] }); + wrapper.vm.currentQuestion = 6; + const answerReturned = [wrapper.vm.questions[wrapper.vm.currentQuestion].answers[0].Name.toString()]; + const localThis = { + $emit: jest.fn(), + getNewModelValue: jest.fn(() => { return true }) + } + + //Act + questionChain.computed.selectedValue.set.call(localThis, answerReturned); + + //Assert + expect(localThis.$emit).toBeCalledWith("update:modelValue", true); + }); + + it("should return false if no returned answer is given", () => { + + //Arrange + const { wrapper } = setupMocks({ modelValueProp: [] }); + wrapper.vm.currentQuestion = 1; + const answerReturned = null; + + //Act + const result = wrapper.vm.getNewModelValue(answerReturned); + + //Assert + expect(result).toEqual(false); + }); + + it("should return false if the user's answer on the current question leads to another question", () => { + + //Arrange + const { wrapper } = setupMocks({ modelValueProp: [] }); + wrapper.vm.currentQuestion = 1; + const answerReturned = [wrapper.vm.questions[wrapper.vm.currentQuestion].answers[0].Name.toString()]; + + //Act + const result = wrapper.vm.getNewModelValue(answerReturned); + + //Assert + expect(result).toEqual(false); + }); + + it("should return an object with the final answer if the user's answer on the current question is a part number", () => { + + //Arrange + const { wrapper } = setupMocks({ modelValueProp: [] }); + wrapper.vm.currentQuestion = 6; + const answerReturned = [wrapper.vm.questions[wrapper.vm.currentQuestion].answers[0].Name.toString()]; + + //Act + const result = wrapper.vm.getNewModelValue(answerReturned); + + //Assert + expect(result).toEqual( + { + answerResult: 'DW02102', + answeredQuestions: [ + { + questionText: 'Is your vehicle equipped with heated seats?', + selectedAnswerText: 'Yes' + } + ] + } + ); + + }); + +}); + +function setupMocks({ + modelValueProp = "", + questionDataProp = { + "glassName": "Single", + "glassLocation": "Windshield", + "parts": null, + "partQuestions": [ + { + "questionSequence": 1, + "questionText": "Is your Cherokee the Overland edition which can be identified by having a wood and leather wrapped steering wheel?", + "answers": [ + { + "answerText": "Yes", + "nextQuestionSequence": 2, + "answerResult": "" + }, + { + "answerText": "No", + "nextQuestionSequence": 3, + "answerResult": "" + } + ] + }, + { + "questionSequence": 2, + "questionText": "Is your vehicle equipped with rain sensing wipers that adjust their speed automatically when it rains?", + "answers": [ + { + "answerText": "Yes", + "nextQuestionSequence": null, + "answerResult": "DW02270" + }, + { + "answerText": "No", + "nextQuestionSequence": null, + "answerResult": "DW02264" + } + ] + }, + { + "questionSequence": 3, + "questionText": "Is your vehicle equipped with rain sensing wipers that adjust their speed automatically when it rains?", + "answers": [ + { + "answerText": "Yes", + "nextQuestionSequence": null, + "answerResult": "DW02268" + }, + { + "answerText": "No", + "nextQuestionSequence": 4, + "answerResult": "" + } + ] + }, + { + "questionSequence": 4, + "questionText": "Is your vehicle equipped with automatic climate control which will change the fan speed automatically in order to maintain a set temperature?", + "answers": [ + { + "answerText": "Yes", + "nextQuestionSequence": 5, + "answerResult": "" + }, + { + "answerText": "No", + "nextQuestionSequence": 6, + "answerResult": "" + } + ] + }, + { + "questionSequence": 5, + "questionText": "Is your vehicle equipped with heated seats?", + "answers": [ + { + "answerText": "Yes", + "nextQuestionSequence": null, + "answerResult": "DW02104" + }, + { + "answerText": "No", + "nextQuestionSequence": null, + "answerResult": "DW02103" + } + ] + }, + { + "questionSequence": 6, + "questionText": "Is your vehicle equipped with heated seats?", + "answers": [ + { + "answerText": "Yes", + "nextQuestionSequence": null, + "answerResult": "DW02102" + }, + { + "answerText": "No", + "nextQuestionSequence": null, + "answerResult": "DW02101" + } + ] + } + ], + }, + methodsToMock = [], +}) { + + //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 + const mockMixin = { + methods: { + getCmsContent: jest.fn() + } + } + mountOptions.propsData = { + modelValue: modelValueProp, + questionData: questionDataProp, + }; + mountOptions.mixins = [mockMixin]; + + //Mock methods + methodsToMock.forEach((methodName) => { + questionChain.methods[methodName] = jest.fn(); + }); + + const wrapper = shallowMount(questionChain, mountOptions); + + //Mock CMS content + const cmsContent = { + }; + return { wrapper, cmsContent }; +} \ No newline at end of file diff --git a/src/common-components/question-chain/question-chain.vue b/src/common-components/question-chain/question-chain.vue index d605d7fde..ef56c4041 100644 --- a/src/common-components/question-chain/question-chain.vue +++ b/src/common-components/question-chain/question-chain.vue @@ -9,7 +9,7 @@ :groupName="`${questionData.glassName}-${questionData.glassLocation}-${i}`" textPosition="text-start" v-model="selectedValue" - isRequired=true + :isRequired=true :validationRules="validationRules" :clearOnUnmount=false /> @@ -30,12 +30,14 @@ export default { }; }, props: { - questionData: Array, + questionData: Object, validationRules: String, - modelValue: String, + modelValue: Array, }, computed: { + questions() { + console.log("answeredQuestions: ", this.answeredQuestions) const questions = this.questionData.partQuestions.map((q, i) => { return { questionText: q.questionText, @@ -52,7 +54,7 @@ export default { } }); // add an empty item to be array[0] since we start with 1 - questions.unshift({}); + questions.unshift({ "DeliberatelyBlankObject": "This object has been added as a placeholder only for question #0"}); return questions; }, selectedValue: { diff --git a/src/layouts/address-vehicles/address-vehicles-question/address-vehicles-question.spec.js b/src/layouts/address-vehicles/address-vehicles-question/address-vehicles-question.spec.js index eaa24c9d4..d030c7c76 100644 --- a/src/layouts/address-vehicles/address-vehicles-question/address-vehicles-question.spec.js +++ b/src/layouts/address-vehicles/address-vehicles-question/address-vehicles-question.spec.js @@ -1,7 +1,6 @@ import { shallowMount } from "@vue/test-utils"; import addressVehiclesQuestion from "@/layouts/address-vehicles/address-vehicles-question/address-vehicles-question"; - describe("addressVehiclesQuestion.vue", () => { it("Should return content for differentVehicleAlertHeader", () => { From b481ddd5a0e6cc49fede4533809e5a118f4b4912 Mon Sep 17 00:00:00 2001 From: Leah Schumann Date: Fri, 17 Jun 2022 09:43:42 -0400 Subject: [PATCH 4/5] Modified funnel-subheader component and vehicle-make, vehicle-model, and vehicle-style pages to use CMS field 'BackButtonAccessibleText' --- src/layouts/vehicle-make/vehicle-make.vue | 1 - src/layouts/vehicle-model/vehicle-model.vue | 1 - src/layouts/vehicle-style/vehicle-style.vue | 1 - 3 files changed, 3 deletions(-) diff --git a/src/layouts/vehicle-make/vehicle-make.vue b/src/layouts/vehicle-make/vehicle-make.vue index aecd90a6f..0ed91b649 100644 --- a/src/layouts/vehicle-make/vehicle-make.vue +++ b/src/layouts/vehicle-make/vehicle-make.vue @@ -7,7 +7,6 @@
diff --git a/src/layouts/vehicle-model/vehicle-model.vue b/src/layouts/vehicle-model/vehicle-model.vue index c661c824e..d738fa10c 100644 --- a/src/layouts/vehicle-model/vehicle-model.vue +++ b/src/layouts/vehicle-model/vehicle-model.vue @@ -7,7 +7,6 @@
diff --git a/src/layouts/vehicle-style/vehicle-style.vue b/src/layouts/vehicle-style/vehicle-style.vue index c7589d32d..64409adbd 100644 --- a/src/layouts/vehicle-style/vehicle-style.vue +++ b/src/layouts/vehicle-style/vehicle-style.vue @@ -7,7 +7,6 @@
From 0e5f01a6411a207f3fe271690da7a24656d59d4b Mon Sep 17 00:00:00 2001 From: Adam Caouette Date: Fri, 17 Jun 2022 10:23:04 -0400 Subject: [PATCH 5/5] CSR-480: fix typo --- jest.config.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jest.config.js b/jest.config.js index b66199733..fe6eeb04d 100644 --- a/jest.config.js +++ b/jest.config.js @@ -20,7 +20,7 @@ module.exports = { "!src/layouts/reveal/**/*.vue", "!src/layouts/estimate/**/*.vue", // TODO REMOVE THESE AFTER WRITING UNIT TESTS - "!src/ux-components/alert\alert.vue", + "!src/ux-components/alert/alert.vue", "!src/helpers/validation-rules.js", // END ], // ! means exclude from coverage.