From b234dfa4ca90a194e70bf62f62b8006abfa6df8a Mon Sep 17 00:00:00 2001 From: bmauger Date: Fri, 21 Jan 2022 14:42:40 -0500 Subject: [PATCH 01/23] CSR-266 create text link variations. --- src/layouts/component-test/component-test.vue | 31 ++++++--- src/styles/common-styles.scss | 35 ---------- src/ux-components/text-link/text-link.spec.js | 1 + src/ux-components/text-link/text-link.vue | 69 +++++++++++++++++++ 4 files changed, 91 insertions(+), 45 deletions(-) create mode 100644 src/ux-components/text-link/text-link.spec.js create mode 100644 src/ux-components/text-link/text-link.vue diff --git a/src/layouts/component-test/component-test.vue b/src/layouts/component-test/component-test.vue index 2ac9f56c6..06ce8a1dc 100644 --- a/src/layouts/component-test/component-test.vue +++ b/src/layouts/component-test/component-test.vue @@ -631,18 +631,27 @@
- Text Link (default text link behavior) -

- Text Link Small (.small) -

- Footer Link (.footer-link) -

- Navigation Link (.navigation-link) +

+

+

+
-

Typogrophy

+

Typography

@@ -888,7 +897,8 @@ import vehicleBanner from "@/common-components/vehicle-banner/vehicle-banner"; import funnelHeader from "@/common-components/funnel-header/funnel-header"; import listButtonHorizontal from "@/ux-components/list-button-horizontal/list-button-horizontal"; import checkbox from "@/ux-components/checkbox/checkbox"; -import buttonQuestion from "@/common-components/button-question/button-question" +import buttonQuestion from "@/common-components/button-question/button-question"; +import textLink from "@/ux-components/text-link/text-link"; export default { name: "App", components: { @@ -902,7 +912,8 @@ export default { listButtonHorizontal, checkbox, funnelHeader, - buttonQuestion + buttonQuestion, + textLink }, data() { return { diff --git a/src/styles/common-styles.scss b/src/styles/common-styles.scss index ba18099ff..a4915049b 100644 --- a/src/styles/common-styles.scss +++ b/src/styles/common-styles.scss @@ -10,41 +10,6 @@ body { box-shadow: 0px 0px 6px 0px rgba(0,0,0,0.15); //Use instead of Bootstrap's helper } } - a { - color: $blue; - text-decoration: none; - border-bottom: 1px solid $blue; - line-height: 26px; - padding: 0 0 4px 0; - font-weight: 500; - &:hover { - color: $blue-700; - } - &.small { - line-height: 24px; - &:hover { - color: $blue-700; - } - } - &.navigation-link { - color: $black; - border-bottom: 1px solid $black; - line-height: 26px; - } - &.footer-link { - color: $gray-500; - text-decoration: none; - border-bottom: 1px solid transparent; - line-height: 20px; - padding: 0 0 2px 0; - font-weight: 400; - font-size: .75rem; - &:hover { - border-bottom: 1px solid $gray-500; - padding: 0 0 2px 0; - } - } - } .pointer { cursor: pointer; } diff --git a/src/ux-components/text-link/text-link.spec.js b/src/ux-components/text-link/text-link.spec.js new file mode 100644 index 000000000..3d0843e10 --- /dev/null +++ b/src/ux-components/text-link/text-link.spec.js @@ -0,0 +1 @@ +test.todo("some test to be written in the future"); diff --git a/src/ux-components/text-link/text-link.vue b/src/ux-components/text-link/text-link.vue new file mode 100644 index 000000000..15d677c9f --- /dev/null +++ b/src/ux-components/text-link/text-link.vue @@ -0,0 +1,69 @@ + + + + + From 365d2b68e8d34159cf084c73d3bae3f2ec9f3cab Mon Sep 17 00:00:00 2001 From: Adam Caouette Date: Fri, 21 Jan 2022 16:19:33 -0500 Subject: [PATCH 02/23] CSR-314: changes to back button to allow specialty focus outline --- .../button-back/button-back.vue | 89 +++++++------------ .../funnel-sub-header/funnel-sub-header.vue | 4 +- 2 files changed, 34 insertions(+), 59 deletions(-) diff --git a/src/common-components/button-back/button-back.vue b/src/common-components/button-back/button-back.vue index 657795dee..44db0038c 100644 --- a/src/common-components/button-back/button-back.vue +++ b/src/common-components/button-back/button-back.vue @@ -1,13 +1,25 @@ @@ -31,59 +43,24 @@ export default { 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 a764c7fb5..4c901b0d4 100644 --- a/src/common-components/funnel-sub-header/funnel-sub-header.vue +++ b/src/common-components/funnel-sub-header/funnel-sub-header.vue @@ -55,6 +55,7 @@ export default { From 612e2096461f753c6cf48eb4e2f47bd7e758cafc Mon Sep 17 00:00:00 2001 From: Adam Caouette Date: Fri, 21 Jan 2022 17:05:35 -0500 Subject: [PATCH 03/23] CSR-314: minor style fix --- src/common-components/button-back/button-back.vue | 1 + 1 file changed, 1 insertion(+) diff --git a/src/common-components/button-back/button-back.vue b/src/common-components/button-back/button-back.vue index 44db0038c..18ebc3f6b 100644 --- a/src/common-components/button-back/button-back.vue +++ b/src/common-components/button-back/button-back.vue @@ -46,6 +46,7 @@ export default { padding: 0; position: relative; top: -1px; + margin-left: 2px; &:focus { outline: none; From 616db70e3efce4f47e0306b2bc795ceb5f1d98ec Mon Sep 17 00:00:00 2001 From: bmauger Date: Sat, 22 Jan 2022 12:07:40 -0500 Subject: [PATCH 04/23] CSR-266 add unit tests. --- src/ux-components/text-link/text-link.spec.js | 69 ++++++++++++++++++- 1 file changed, 68 insertions(+), 1 deletion(-) diff --git a/src/ux-components/text-link/text-link.spec.js b/src/ux-components/text-link/text-link.spec.js index 3d0843e10..4c3458137 100644 --- a/src/ux-components/text-link/text-link.spec.js +++ b/src/ux-components/text-link/text-link.spec.js @@ -1 +1,68 @@ -test.todo("some test to be written in the future"); +import { shallowMount } from "@vue/test-utils"; +import textLink from "./text-link"; +import { nextTick } from "vue"; + +describe("text-link.vue", () => { + + it("Should return text-link type is navigation if prop navigation is true", async () => { + // Act + const wrapper = shallowMount(textLink, { + propsData: { + navigation: true, + }, + }); + + // Assert + const paragraph = wrapper.find("a"); + + // Expect + expect(paragraph.attributes('class')).toContain("navigation-link"); + }); + + it("Should return text-link type is footer if prop footer is true", async () => { + // Act + const wrapper = shallowMount(textLink, { + propsData: { + footer: true, + }, + }); + + // Assert + const paragraph = wrapper.find("a"); + + // Expect + expect(paragraph.attributes('class')).toContain("footer-link"); + }); + + it("Should return text-link type is textSmall if prop textSmall is true", async () => { + // Act + const wrapper = shallowMount(textLink, { + propsData: { + textSmall: true, + }, + }); + + // Assert + const paragraph = wrapper.find("a"); + + // Expect + expect(paragraph.attributes('class')).toContain("small"); + }); + + it("Should return text for href", async () => { + // Act + const wrapper = shallowMount(textLink, { + propsData: { + text: "This is link text" + }, + }); + + // Assert + const paragraph = wrapper.find("a"); + + // Expect + expect(paragraph.text()).toEqual("This is link text"); + + }); + +}); From 3cfd3b14aa1f16c656d110c16698a6cfc0651574 Mon Sep 17 00:00:00 2001 From: bmauger Date: Mon, 24 Jan 2022 09:38:32 -0500 Subject: [PATCH 05/23] Add unit test for checkbox.vue. To raise global percentage. --- src/ux-components/checkbox/checkbox.spec.js | 86 ++++++++++++++++++++- 1 file changed, 85 insertions(+), 1 deletion(-) diff --git a/src/ux-components/checkbox/checkbox.spec.js b/src/ux-components/checkbox/checkbox.spec.js index 3d0843e10..e5536f97c 100644 --- a/src/ux-components/checkbox/checkbox.spec.js +++ b/src/ux-components/checkbox/checkbox.spec.js @@ -1 +1,85 @@ -test.todo("some test to be written in the future"); +import { shallowMount } from "@vue/test-utils"; +import checkbox from "./checkbox"; +import { nextTick } from "vue"; + +describe("checkbox.vue", () => { + + it("Should return checkbox name", async () => { + // Act + const wrapper = shallowMount(checkbox, { + propsData: { + checkboxName: "Checkbox" + }, + }); + + // Assert + const input = wrapper.find("input"); + + // Expect + expect(input.attributes().name).toEqual("Checkbox"); + + }); + + it("Should return checkbox id", async () => { + // Act + const wrapper = shallowMount(checkbox, { + propsData: { + buttonID: "Checkbox ID" + }, + }); + + // Assert + const input = wrapper.find("input"); + + // Expect + expect(input.attributes().id).toEqual("Checkbox ID"); + + }); + + it("Should return tabindex value", async () => { + // Act + const wrapper = shallowMount(checkbox, { + propsData: { + tabIndex: "1" + }, + }); + + // Assert + const input = wrapper.find("input"); + + // Expect + expect(input.attributes().tabindex).toEqual("1"); + + }); + + it("Should return label text", async () => { + // Act + const wrapper = shallowMount(checkbox, { + propsData: { + checkboxLabel: "label text" + }, + }); + + // Assert + const paragraph = wrapper.find("p"); + + expect(paragraph.text()).toEqual("label text"); + + }); + + it("Should return label text", async () => { + // Act + const wrapper = shallowMount(checkbox, { + propsData: { + screenReaderOnlyText: "screenreader text" + }, + }); + + // Assert + const paragraph = wrapper.find("span"); + + expect(paragraph.text()).toEqual("screenreader text"); + + }); + +}); From a2f24336a94ba715fe0ebcb2ac1401f48dfc9cfc Mon Sep 17 00:00:00 2001 From: bmauger Date: Mon, 24 Jan 2022 13:52:05 -0500 Subject: [PATCH 06/23] Add unit tests to components. --- src/App.vue | 3 +- src/styles/common-button-styles.scss | 56 ----------- .../button-primary/button-primary.spec.js | 93 ++++++++++++++++++- .../button-primary/button-primary.vue | 33 +++++++ .../button-secondary/button-secondary.spec.js | 93 ++++++++++++++++++- .../button-secondary/button-secondary.vue | 34 ++++++- 6 files changed, 251 insertions(+), 61 deletions(-) delete mode 100644 src/styles/common-button-styles.scss diff --git a/src/App.vue b/src/App.vue index 3d665312e..e6380a315 100644 --- a/src/App.vue +++ b/src/App.vue @@ -5,7 +5,6 @@ \ No newline at end of file + diff --git a/src/styles/common-button-styles.scss b/src/styles/common-button-styles.scss deleted file mode 100644 index abaf94879..000000000 --- a/src/styles/common-button-styles.scss +++ /dev/null @@ -1,56 +0,0 @@ -//Custom button styles -.btn { - &.btn-primary { - position: relative; - background: $blue-700; - @include blue-gradient; - border: none; - border-radius: $border-radius-lg; - color: $white; - transition: all 150ms linear; - &:hover { - background: linear-gradient(270deg, rgba(6,87,124,1) 0%, rgba(6,87,124,1) 100%); - } - &:focus, // Mouse, touch, stylus focus - &:focus-visible { // Keyboard focus for accessibility - outline: none; - box-shadow: 0 0 0 3px, 0 0 0 5.5px $blue-700; - color: $white; - @include blue-gradient; - } - &:disabled { - background: $gray-100 !important; - background: linear-gradient(270deg, $gray-100 0%, $gray-100 100%) !important; - color: $gray !important; - height: 48px; - border: none; - border-radius: $border-radius-lg; - } - } - &.btn-secondary { - position: relative; - background: transparent; - border: 1px solid $blue; - border-radius: $border-radius-lg; - color: $blue; - transition: all 150ms linear; - &:hover { - color: $white; - @include blue-gradient; - } - &:focus, // Mouse, touch, stylus focus - &:focus-visible { // Keyboard focus for accessibility - outline: none; - box-shadow: 0 0 0 3px $white, 0 0 0 5.5px $blue-700; - color: $white; - @include blue-gradient; - } - &:disabled { - background: transparent; - color: $gray !important; - height: 48px; - border: 1px solid $gray-300; - border-radius: $border-radius-lg; - } - } -} diff --git a/src/ux-components/button-primary/button-primary.spec.js b/src/ux-components/button-primary/button-primary.spec.js index 3d0843e10..39f64111c 100644 --- a/src/ux-components/button-primary/button-primary.spec.js +++ b/src/ux-components/button-primary/button-primary.spec.js @@ -1 +1,92 @@ -test.todo("some test to be written in the future"); +import { shallowMount } from "@vue/test-utils"; +import buttonPrimary from "./button-primary"; +import { nextTick } from "vue"; + +describe("buttonPrimary.vue", () => { + + it("Should return aria-disabled state", async () => { + // Act + const wrapper = shallowMount(buttonPrimary, { + propsData: { + isDisabled: true + }, + }); + + // Assert + const button = wrapper.find("button"); + + // Expect + expect(button.attributes()["aria-disabled"]).toEqual("true"); + + }); + + it("Should return loader color", async () => { + // Act + const wrapper = shallowMount(buttonPrimary, { + propsData: { + loaderColor: "blue", + loaderEnabled: true + }, + }); + + // Assert + + const label = wrapper.find("label"); + + wrapper.vm.displayComponent(); + + await nextTick(); + + const loader = wrapper.find("loader-stub"); + + expect(loader.attributes('class')).toContain("blue"); + + }); + + it("Should return loader position", async () => { + // Act + const wrapper = shallowMount(buttonPrimary, { + propsData: { + loaderPosition: "right", + loaderEnabled: true + }, + }); + + // Assert + + const label = wrapper.find("label"); + + wrapper.vm.displayComponent(); + + await nextTick(); + + const loader = wrapper.find("loader-stub"); + + expect(loader.attributes('class')).toContain("right"); + + }); + + it("Should return loader size in rem", async () => { + // Act + const wrapper = shallowMount(buttonPrimary, { + propsData: { + sizeInRem: 1, + loaderEnabled: true + }, + }); + + // Assert + + const label = wrapper.find("label"); + + wrapper.vm.displayComponent(); + + await nextTick(); + + const loader = wrapper.find("loader-stub"); + + expect(loader.attributes('style')).toContain("1rem"); + + }); + +}); diff --git a/src/ux-components/button-primary/button-primary.vue b/src/ux-components/button-primary/button-primary.vue index ca0cc8505..4b1003f32 100644 --- a/src/ux-components/button-primary/button-primary.vue +++ b/src/ux-components/button-primary/button-primary.vue @@ -41,3 +41,36 @@ export default { }, }; + + diff --git a/src/ux-components/button-secondary/button-secondary.spec.js b/src/ux-components/button-secondary/button-secondary.spec.js index 3d0843e10..b10134228 100644 --- a/src/ux-components/button-secondary/button-secondary.spec.js +++ b/src/ux-components/button-secondary/button-secondary.spec.js @@ -1 +1,92 @@ -test.todo("some test to be written in the future"); +import { shallowMount } from "@vue/test-utils"; +import buttonSecondary from "./button-secondary"; +import { nextTick } from "vue"; + +describe("buttonSecondary.vue", () => { + + it("Should return aria-disabled state", async () => { + // Act + const wrapper = shallowMount(buttonSecondary, { + propsData: { + isDisabled: true + }, + }); + + // Assert + const button = wrapper.find("button"); + + // Expect + expect(button.attributes()["aria-disabled"]).toEqual("true"); + + }); + + it("Should return loader color", async () => { + // Act + const wrapper = shallowMount(buttonSecondary, { + propsData: { + loaderColor: "blue", + loaderEnabled: true + }, + }); + + // Assert + + const label = wrapper.find("label"); + + wrapper.vm.displayComponent(); + + await nextTick(); + + const loader = wrapper.find("loader-stub"); + + expect(loader.attributes('class')).toContain("blue"); + + }); + + it("Should return loader position", async () => { + // Act + const wrapper = shallowMount(buttonSecondary, { + propsData: { + loaderPosition: "right", + loaderEnabled: true + }, + }); + + // Assert + + const label = wrapper.find("label"); + + wrapper.vm.displayComponent(); + + await nextTick(); + + const loader = wrapper.find("loader-stub"); + + expect(loader.attributes('class')).toContain("right"); + + }); + + it("Should return loader size in rem", async () => { + // Act + const wrapper = shallowMount(buttonSecondary, { + propsData: { + sizeInRem: 1, + loaderEnabled: true + }, + }); + + // Assert + + const label = wrapper.find("label"); + + wrapper.vm.displayComponent(); + + await nextTick(); + + const loader = wrapper.find("loader-stub"); + + expect(loader.attributes('style')).toContain("1rem"); + + }); + +}); diff --git a/src/ux-components/button-secondary/button-secondary.vue b/src/ux-components/button-secondary/button-secondary.vue index ec4d7ec0c..c50876387 100644 --- a/src/ux-components/button-secondary/button-secondary.vue +++ b/src/ux-components/button-secondary/button-secondary.vue @@ -18,7 +18,7 @@ + + From 99701dcea285d83f7e995d0f68b26e33cc7546ff Mon Sep 17 00:00:00 2001 From: Adam Caouette Date: Tue, 25 Jan 2022 09:16:26 -0500 Subject: [PATCH 07/23] CSR-314: move styles into component itself --- src/common-components/button-back/button-back.vue | 2 ++ src/common-components/funnel-sub-header/funnel-sub-header.vue | 2 -- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/common-components/button-back/button-back.vue b/src/common-components/button-back/button-back.vue index 18ebc3f6b..7f06dfcec 100644 --- a/src/common-components/button-back/button-back.vue +++ b/src/common-components/button-back/button-back.vue @@ -47,6 +47,8 @@ export default { position: relative; top: -1px; margin-left: 2px; + border: none; + background: none; &:focus { outline: none; 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 4c901b0d4..b0bca0cae 100644 --- a/src/common-components/funnel-sub-header/funnel-sub-header.vue +++ b/src/common-components/funnel-sub-header/funnel-sub-header.vue @@ -58,8 +58,6 @@ export default { line-height: 32px; button { - border: none; - background: none; color: inherit; } } From 5f3f6c717525fd294024644d1d487368968c6259 Mon Sep 17 00:00:00 2001 From: bmauger Date: Tue, 25 Jan 2022 17:08:28 -0500 Subject: [PATCH 08/23] CSR-266 WIP --- src/ux-components/button/button.spec.js | 0 src/ux-components/button/button.vue | 93 +++++++++++++++++++++++++ 2 files changed, 93 insertions(+) create mode 100644 src/ux-components/button/button.spec.js create mode 100644 src/ux-components/button/button.vue diff --git a/src/ux-components/button/button.spec.js b/src/ux-components/button/button.spec.js new file mode 100644 index 000000000..e69de29bb diff --git a/src/ux-components/button/button.vue b/src/ux-components/button/button.vue new file mode 100644 index 000000000..15e2bb98f --- /dev/null +++ b/src/ux-components/button/button.vue @@ -0,0 +1,93 @@ + + + + + From 076f2af50107b313fea9c870e848a662518c002c Mon Sep 17 00:00:00 2001 From: Mark Harris Date: Wed, 26 Jan 2022 08:49:46 -0500 Subject: [PATCH 09/23] Removed not-yet-used fields (many of which our out-of-sync with confluence) --- src/store/index.js | 26 -------------------------- 1 file changed, 26 deletions(-) diff --git a/src/store/index.js b/src/store/index.js index f3937726a..ad4a9f388 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -19,42 +19,16 @@ export default createStore({ make: null, model: null, style: null, - vin: null, - licensePlate: null, carId: null, category: null, - evoxImageId: null, - hasSplitWindshieldOption: null, - hasBackglassSliderOption: null, - registration: { - rawAddress: null, - zipCode: null, - firstName: null, - lastName: null, - licensePlate: null, - }, damage: { isRepair: null, - isReplacement: null, numberOfChips: null, glassToReplace: null, - problemGlassQuestionAnswers: null, - problemMoldingQuestionAnswers: null, - problemPropertyQuestionAnswers: null, }, - lineItems: null, - customer: { - emailAddress: null, - }, - payment: { - isInsurance: null, - isCash: null, - }, - referralSeqNum: null, }, }, applicationUser: { - experiments: null, eventBus: [] }, }, From ec3c18dbefa96db06353331d96ba85b929ddb6bc Mon Sep 17 00:00:00 2001 From: bmauger Date: Wed, 26 Jan 2022 09:03:17 -0500 Subject: [PATCH 10/23] CSR-266 create button-main component. --- src/layouts/component-test/component-test.vue | 7 ++++--- .../button-main.spec.js} | 0 .../button.vue => button-main/button-main.vue} | 15 ++++++++------- 3 files changed, 12 insertions(+), 10 deletions(-) rename src/ux-components/{button/button.spec.js => button-main/button-main.spec.js} (100%) rename src/ux-components/{button/button.vue => button-main/button-main.vue} (84%) diff --git a/src/layouts/component-test/component-test.vue b/src/layouts/component-test/component-test.vue index c0a33561a..fbc9f0133 100644 --- a/src/layouts/component-test/component-test.vue +++ b/src/layouts/component-test/component-test.vue @@ -22,7 +22,8 @@
- @@ -887,7 +888,7 @@ - - diff --git a/src/ux-components/button-secondary/button-secondary.spec.js b/src/ux-components/button-secondary/button-secondary.spec.js deleted file mode 100644 index b10134228..000000000 --- a/src/ux-components/button-secondary/button-secondary.spec.js +++ /dev/null @@ -1,92 +0,0 @@ -import { shallowMount } from "@vue/test-utils"; -import buttonSecondary from "./button-secondary"; -import { nextTick } from "vue"; - -describe("buttonSecondary.vue", () => { - - it("Should return aria-disabled state", async () => { - // Act - const wrapper = shallowMount(buttonSecondary, { - propsData: { - isDisabled: true - }, - }); - - // Assert - const button = wrapper.find("button"); - - // Expect - expect(button.attributes()["aria-disabled"]).toEqual("true"); - - }); - - it("Should return loader color", async () => { - // Act - const wrapper = shallowMount(buttonSecondary, { - propsData: { - loaderColor: "blue", - loaderEnabled: true - }, - }); - - // Assert - - const label = wrapper.find("label"); - - wrapper.vm.displayComponent(); - - await nextTick(); - - const loader = wrapper.find("loader-stub"); - - expect(loader.attributes('class')).toContain("blue"); - - }); - - it("Should return loader position", async () => { - // Act - const wrapper = shallowMount(buttonSecondary, { - propsData: { - loaderPosition: "right", - loaderEnabled: true - }, - }); - - // Assert - - const label = wrapper.find("label"); - - wrapper.vm.displayComponent(); - - await nextTick(); - - const loader = wrapper.find("loader-stub"); - - expect(loader.attributes('class')).toContain("right"); - - }); - - it("Should return loader size in rem", async () => { - // Act - const wrapper = shallowMount(buttonSecondary, { - propsData: { - sizeInRem: 1, - loaderEnabled: true - }, - }); - - // Assert - - const label = wrapper.find("label"); - - wrapper.vm.displayComponent(); - - await nextTick(); - - const loader = wrapper.find("loader-stub"); - - expect(loader.attributes('style')).toContain("1rem"); - - }); - -}); diff --git a/src/ux-components/button-secondary/button-secondary.vue b/src/ux-components/button-secondary/button-secondary.vue deleted file mode 100644 index c50876387..000000000 --- a/src/ux-components/button-secondary/button-secondary.vue +++ /dev/null @@ -1,75 +0,0 @@ - - - - - From b71b24e9c5ee94e87768f4307ee1d2e3d82e0c6e Mon Sep 17 00:00:00 2001 From: FrankRua Date: Wed, 26 Jan 2022 15:19:43 -0500 Subject: [PATCH 13/23] Updated readme --- README.md | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 65e8bfb95..535976602 100644 --- a/README.md +++ b/README.md @@ -6,11 +6,8 @@ This Repository is for Fix My Glass front end Vue and documentation associated w #### Routing We are using [Vue Router](https://next.router.vuejs.org/) 4.x for our front end routing. We are using a runtime dynamic routing solution. Some more information about dynamic routing can be found on the [official Vue Router documentation](https://next.router.vuejs.org/guide/advanced/dynamic-routing.html). -Here is a high level overview of how our routing works: -![FixMyGlass - Routing](https://user-images.githubusercontent.com/44780237/139876801-7d5c495a-f361-4234-a8ec-69126a357f80.png) - -`RetainStructureAndGoTo404(to, next)` - Since our 404 path on our router is `path: '/:pathMatch(.*)*'` (meaning that we don't have a dedicated 404 route) we retain the information entered by the user in the url bar and just serve back our `NotFound` component on Vue. For example if a user was to type in `.../fmg/fmgPage=junkPage` Vue will retain this url in the browser and return our `NotFound` component. This could be especially useful for analytics and reporting. - `Next()` - Is a function that is native to Vue Router in which we call in order to send the user where want them to go based on some logic we have[. You can read more about Navigation Guards and the `Next()` function on the Vue Router documentation. ](https://next.router.vuejs.org/guide/advanced/navigation-guards.html) -`GetRouteInfoFromPageName(PageName)` - This method typically takes the query string value of `fmgPage` and passes it into a call to our Content Service. The service will pull information on the page; matching page name passed to page name in our Cms. If we have a match, we will compile the route information and send it to our router to process. If we do not have a that page in our Cms, the user will be served back a 404 page while retaining the structure. \ No newline at end of file +`GetRouteInfoFromPageName(PageName)` - This method typically takes the query string value of `fmgPage` and passes it into a call to our Content Service. The service will pull information on the page; matching page name passed to page name in our Cms. If we have a match, we will compile the route information and send it to our router to process. If we do not have a that page in our Cms, the user will be served back a 404 page while retaining the structure. + +`GoToFunnelStartOn404(next)` - When a user tries to go to a page that doesn't exist in the CMS, they will be put back to the 'Start' of the funnel which is whatever page is marked as the homepage on Sitefinity. \ No newline at end of file From 8e45c1c99bfa8561f2a069816ad4d0d137b2ae39 Mon Sep 17 00:00:00 2001 From: bmauger Date: Wed, 26 Jan 2022 15:35:21 -0500 Subject: [PATCH 14/23] CSR-266 add has-error css styling for validation. --- src/App.vue | 1 + src/layouts/form-test/form-test.vue | 11 +++++------ src/styles/error-styles.scss | 10 ++++++++++ 3 files changed, 16 insertions(+), 6 deletions(-) create mode 100644 src/styles/error-styles.scss diff --git a/src/App.vue b/src/App.vue index e6380a315..f64aad6aa 100644 --- a/src/App.vue +++ b/src/App.vue @@ -7,4 +7,5 @@ @import "@/styles/common-styles.scss"; @import "@/styles/common-list-styles.scss"; @import "@/styles/common-typography-styles.scss"; + @import "@/styles/error-styles.scss"; diff --git a/src/layouts/form-test/form-test.vue b/src/layouts/form-test/form-test.vue index 2df7ee70f..33a7e6a70 100644 --- a/src/layouts/form-test/form-test.vue +++ b/src/layouts/form-test/form-test.vue @@ -9,10 +9,11 @@

FORM VALIDATION TEST

NOTE: This page is testing functionality only; styling will not match Figma mocks.

-
+

How many chips are we repairing? (Required)

+
+
@@ -292,7 +294,7 @@ export default { // passwordConfirmation: Yup.string() // .required() // .oneOf([Yup.ref("password")], "Passwords do not match"), - }).test('repair-replace-conflict', + }).test('repair-replace-conflict', null, // need to pass null as error message so it won't get added to list of errors function(value) { // whole form test @@ -352,7 +354,4 @@ export default { .form-test-invalid { opacity: 0.5; } - .has-error { - border: 1px solid red; - } - \ No newline at end of file + diff --git a/src/styles/error-styles.scss b/src/styles/error-styles.scss new file mode 100644 index 000000000..c2c6c3fea --- /dev/null +++ b/src/styles/error-styles.scss @@ -0,0 +1,10 @@ +.has-error { + .list-button, + .list-card, + .list-button-horizontal { + color: $red; + label { + border: 1px solid $red; + } + } +} From 4ae9f1fe266a4a088ee3a7bb31f356e88f6a773a Mon Sep 17 00:00:00 2001 From: bmauger Date: Thu, 27 Jan 2022 14:17:40 -0500 Subject: [PATCH 15/23] Set aria-required to true for Bindu test. --- src/layouts/vehicle-year/year-question/year-question.vue | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/layouts/vehicle-year/year-question/year-question.vue b/src/layouts/vehicle-year/year-question/year-question.vue index d189bb54a..792e6d848 100644 --- a/src/layouts/vehicle-year/year-question/year-question.vue +++ b/src/layouts/vehicle-year/year-question/year-question.vue @@ -7,6 +7,7 @@ textPosition="text-start" :loaderEnabled="true" v-model="modelValue" + isRequired=true /> @@ -44,4 +45,4 @@ export default { } }, }; - \ No newline at end of file + From 30fcdbefce7c0494cdbbf6aa228d4f7e75a01fa8 Mon Sep 17 00:00:00 2001 From: bmauger Date: Thu, 27 Jan 2022 14:41:55 -0500 Subject: [PATCH 16/23] CSR-262 update file name per Mark's request. --- src/App.vue | 2 +- src/styles/{error-styles.scss => common-error-styles.scss} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename src/styles/{error-styles.scss => common-error-styles.scss} (100%) diff --git a/src/App.vue b/src/App.vue index f64aad6aa..a11e5a9f7 100644 --- a/src/App.vue +++ b/src/App.vue @@ -7,5 +7,5 @@ @import "@/styles/common-styles.scss"; @import "@/styles/common-list-styles.scss"; @import "@/styles/common-typography-styles.scss"; - @import "@/styles/error-styles.scss"; + @import "@/styles/common-error-styles.scss"; diff --git a/src/styles/error-styles.scss b/src/styles/common-error-styles.scss similarity index 100% rename from src/styles/error-styles.scss rename to src/styles/common-error-styles.scss From 21d2ba883d9e6afc632b7ad19aa1adf3720b8602 Mon Sep 17 00:00:00 2001 From: bmauger Date: Thu, 27 Jan 2022 14:54:10 -0500 Subject: [PATCH 17/23] Move list-button styles to component. Delete common-list-styles.scss. --- src/App.vue | 1 - src/styles/common-list-styles.scss | 44 ------------------- src/ux-components/list-button/list-button.vue | 34 ++++++++++++++ 3 files changed, 34 insertions(+), 45 deletions(-) delete mode 100644 src/styles/common-list-styles.scss diff --git a/src/App.vue b/src/App.vue index a11e5a9f7..76a01d29c 100644 --- a/src/App.vue +++ b/src/App.vue @@ -5,7 +5,6 @@ diff --git a/src/styles/common-list-styles.scss b/src/styles/common-list-styles.scss deleted file mode 100644 index 9e232f54d..000000000 --- a/src/styles/common-list-styles.scss +++ /dev/null @@ -1,44 +0,0 @@ -.list-group { - &.list-button { - input[type="radio"], - input[type="checkbox"] { - opacity: 0; - position: fixed; - width: 0; - &:focus-visible + label { - box-shadow: 0 0 0 2.5px $blue inset; - } - &:focus + label { - box-shadow: 0 0 0 2.5px $blue inset; - } - &:checked + label { - color: $black; - font-weight: 500; - background: $blue-100; - box-shadow: 0 0 0 1px $blue; - } - &:checked + label p:first-child { - font-weight: 500; - } - } - label { - color: $gray-600; - position: relative; - background: $white; - transition: all 150ms linear; - border-radius: $border-radius-lg; - border: 1px solid $gray-500; - width: 100%; - - &:hover { - @include media-breakpoint-up(sm) { - box-shadow: 0 0 0 4px $blue-100; - } - cursor: pointer; - } - + p { - display: none; - } - } - } -} diff --git a/src/ux-components/list-button/list-button.vue b/src/ux-components/list-button/list-button.vue index 5fa285c31..7349ee6b3 100644 --- a/src/ux-components/list-button/list-button.vue +++ b/src/ux-components/list-button/list-button.vue @@ -77,6 +77,40 @@ export default { position: static; //override bootstrap height: 0; } + &:focus-visible + label { + box-shadow: 0 0 0 2.5px $blue inset; + } + &:focus + label { + box-shadow: 0 0 0 2.5px $blue inset; + } + &:checked + label { + color: $black; + font-weight: 500; + background: $blue-100; + box-shadow: 0 0 0 1px $blue; + } + &:checked + label p:first-child { + font-weight: 500; + } + } + label { + color: $gray-600; + position: relative; + background: $white; + transition: all 150ms linear; + border-radius: $border-radius-lg; + border: 1px solid $gray-500; + width: 100%; + + &:hover { + @include media-breakpoint-up(sm) { + box-shadow: 0 0 0 4px $blue-100; + } + cursor: pointer; + } + + p { + display: none; + } } } From 209850826c792cdf2d59a8c23a99093437401539 Mon Sep 17 00:00:00 2001 From: Mark Harris Date: Thu, 27 Jan 2022 15:35:21 -0500 Subject: [PATCH 18/23] trying to fix params --- src/router/index.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/router/index.js b/src/router/index.js index 2a80032f6..978157016 100644 --- a/src/router/index.js +++ b/src/router/index.js @@ -35,6 +35,7 @@ const routes = [ }, { path: "/", + name: "root", async beforeEnter(to, from, next) { // If we have no query string, or we don't have the FmgPage query string. if (to.query.fmgPage === undefined) { @@ -97,7 +98,7 @@ router.navigate = ( if (matchingScenarioMap.destinationFmgPageValue !== undefined) { // We're always pushing the same path, just changing query strings. Make sure our optional query strings get combined with our fmgPage one. router.push({ - path: "/", + name: "root", query: Object.assign(optionalQuery, { fmgPage: matchingScenarioMap.destinationFmgPageValue, }), From 19136a04c08755cc39945f58b720e34400fa85a8 Mon Sep 17 00:00:00 2001 From: Mark Harris Date: Thu, 27 Jan 2022 15:58:35 -0500 Subject: [PATCH 19/23] transmitting params in router --- src/router/index.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/router/index.js b/src/router/index.js index 978157016..79894066e 100644 --- a/src/router/index.js +++ b/src/router/index.js @@ -45,7 +45,7 @@ const routes = [ try { // If we already have our route, go to it. if (router.hasRoute(to.query.fmgPage)) { - return next({ name: to.query.fmgPage, query: to.query }); + return next({ name: to.query.fmgPage, query: to.query, params: to.params }); } // Get route info for the given url. Names will have a 1:1 relationship with names in the Cms. @@ -59,7 +59,7 @@ const routes = [ }); // Assign current query string parameters, as well as our fmgPage one. - next({ name: routeData[0].name, query: Object.assign(to.query, { fmgPage: routeData[0].name }) }); + next({ name: routeData[0].name, query: Object.assign(to.query, { fmgPage: routeData[0].name }), params: to.params }); } catch (error) { console.log(error); From 915cfd5a215f33b539317e4fe060d995c33ba5f5 Mon Sep 17 00:00:00 2001 From: FrankRua Date: Thu, 27 Jan 2022 17:23:09 -0500 Subject: [PATCH 20/23] Added logic to validate pages --- src/layouts/vehicle-damage/vehicle-damage.vue | 58 ++++++------ src/layouts/vehicle-make/vehicle-make.spec.js | 89 ++++++++++++++----- src/layouts/vehicle-make/vehicle-make.vue | 16 ++-- src/layouts/vehicle-model/vehicle-model.vue | 5 ++ src/layouts/vehicle-style/vehicle-style.vue | 24 ++++- src/layouts/vehicle-year/vehicle-year.vue | 9 +- src/router/index.js | 18 +++- 7 files changed, 157 insertions(+), 62 deletions(-) diff --git a/src/layouts/vehicle-damage/vehicle-damage.vue b/src/layouts/vehicle-damage/vehicle-damage.vue index c00669245..e18b594e0 100644 --- a/src/layouts/vehicle-damage/vehicle-damage.vue +++ b/src/layouts/vehicle-damage/vehicle-damage.vue @@ -1,11 +1,9 @@ diff --git a/src/layouts/vehicle-make/vehicle-make.spec.js b/src/layouts/vehicle-make/vehicle-make.spec.js index 83a7f1862..41a7939ad 100644 --- a/src/layouts/vehicle-make/vehicle-make.spec.js +++ b/src/layouts/vehicle-make/vehicle-make.spec.js @@ -7,23 +7,40 @@ import vehicleBanner from "@/common-components/vehicle-banner/vehicle-banner"; import funnelSubHeader from "@/common-components/funnel-sub-header/funnel-sub-header"; import { settleAllPromises } from "@/helpers/layout-helper.js"; import { nextTick } from "vue"; +import { fetchCmsContentForPage } from "@/helpers/cms-content-helper"; + +// Mock Store +jest.mock("@/store", () => ({ + getters: { + vehicle: { + year: 2019, + } + } +})); + +// Mock fetchCmsContentForPage +jest.mock("@/helpers/cms-content-helper", () => ({ + fetchCmsContentForPage: jest.fn(), +})); // Mock our module for promises. jest.mock("@/helpers/layout-helper.js", () => ({ settleAllPromises: jest.fn(), })); + describe("vehicle-make.vue", () => { test("Make question component is initized with api data", async (done) => { //Arrange const vehicleMakeQuestionCmsContent = { QuestionText: "What make is your vehicle?" }; const makeQuestionInitialData = ["honda", "ford", "dodge"]; - const { wrapper, apiPromise } = setupMocks( { - vehicleMakeQuestionCmsContent: vehicleMakeQuestionCmsContent, + const { wrapper, apiPromise } = setupMocks({ + vehicleMakeQuestionCmsContent: vehicleMakeQuestionCmsContent, makeQuestionInitialData: makeQuestionInitialData, - } ); + }); + //Act vehicleMake.beforeRouteEnter.call(wrapper.vm, { query: { fmgPage: "vehicle-make" } }, undefined, (c) => c(wrapper.vm)); @@ -40,8 +57,8 @@ describe("vehicle-make.vue", () => { //Arrange const pageHeaderWidgetHeaderText = "Select a make to get started"; - const { wrapper, apiPromise } = setupMocks( { pageHeaderWidgetHeaderText: pageHeaderWidgetHeaderText }); - + const { wrapper, apiPromise } = setupMocks({ pageHeaderWidgetHeaderText: pageHeaderWidgetHeaderText }); + //Act vehicleMake.beforeRouteEnter.call(wrapper.vm, { query: { fmgPage: "vehicle-make" } }, undefined, (c) => c(wrapper.vm)); @@ -61,8 +78,8 @@ describe("vehicle-make.vue", () => { LogoImage: "https://digitalconsumercms-dev.safelite.com/images/default-source/default-album/safelite-logo.svg?sfvrsn=45e7ed06_3", } - const { wrapper, apiPromise } = setupMocks( { SiteHeaderWidget: SiteHeaderWidget}); - + const { wrapper, apiPromise } = setupMocks({ SiteHeaderWidget: SiteHeaderWidget }); + //Act vehicleMake.beforeRouteEnter.call(wrapper.vm, { query: { fmgPage: "vehicle-make" } }, undefined, (c) => c(wrapper.vm)); @@ -82,8 +99,8 @@ describe("vehicle-make.vue", () => { GenericVehicleImage: "https://digitalconsumercms-dev.safelite.com/images/default-source/default-album/blurred-image.jpg?sfvrsn=a6ce3034_3", } - const { wrapper, apiPromise } = setupMocks( { VehicleBannerWidget: VehicleBannerWidget}); - + const { wrapper, apiPromise } = setupMocks({ VehicleBannerWidget: VehicleBannerWidget }); + //Act vehicleMake.beforeRouteEnter.call(wrapper.vm, { query: { fmgPage: "vehicle-make" } }, undefined, (c) => c(wrapper.vm)); @@ -97,9 +114,9 @@ describe("vehicle-make.vue", () => { describe("vehicle-make.vue", () => { test("BackButtonAction triggers a router.navigate change", async (done) => { - + //Arrange - const { wrapper, apiPromise } = setupMocks( { + const { wrapper, apiPromise } = setupMocks({ pageHeaderWidgetHeaderText: "Select a make to get started", mountOptionsMockData: { router: { @@ -121,32 +138,59 @@ describe("vehicle-make.vue", () => { }); }); +describe("vehicle-make.vue", () => { + test("arePagePrerequisitesValid", async (done) => { + + //Arrange + const { wrapper, apiPromise } = setupMocks({ + pageHeaderWidgetHeaderText: "Select a make to get started", + mountOptionsMockData: {}, + }); + + //Act + vehicleMake.beforeRouteEnter.call(wrapper.vm, { query: { fmgPage: "vehicle-make" } }, undefined, (c) => c(wrapper.vm)); + + let arePagePrerequisitesValid = wrapper.vm.arePagePrerequisitesValid(); + await nextTick(); + + //Assert + apiPromise.finally(() => { + expect(arePagePrerequisitesValid).toBe(true); + done(); + }); + }); +}); + + function setupMocks({ vehicleMakeQuestionCmsContent = {}, makeQuestionInitialData = {}, pageHeaderWidgetHeaderText = {}, mountOptionsMockData = {}, }) { - + //Mock api responses const apiResponses = { cmsContent: { FunnelSubHeaderWidget: pageHeaderWidgetHeaderText, VehicleMakeQuestion: vehicleMakeQuestionCmsContent, - VehicleBannerWidget: - { - GenericVehicleImage: - "https://digitalconsumercms-dev.safelite.com/images/default-source/default-album/blurred-image.jpg?sfvrsn=a6ce3034_3", - }, - FunnelHeaderWidget: - { - LogoImage: - "https://digitalconsumercms-dev.safelite.com/images/default-source/default-album/safelite-logo.svg?sfvrsn=45e7ed06_3", - }, + VehicleBannerWidget: + { + GenericVehicleImage: + "https://digitalconsumercms-dev.safelite.com/images/default-source/default-album/blurred-image.jpg?sfvrsn=a6ce3034_3", + }, + FunnelHeaderWidget: + { + LogoImage: + "https://digitalconsumercms-dev.safelite.com/images/default-source/default-album/safelite-logo.svg?sfvrsn=45e7ed06_3", + }, }, makeQuestionInitialData: makeQuestionInitialData, }; + const apiPromise = Promise.resolve(apiResponses); + + fetchCmsContentForPage.mockImplementation(() => Promise.resolve()); settleAllPromises.mockImplementation(() => apiPromise); //Mock make question methods @@ -163,6 +207,7 @@ function setupMocks({ funnelSubHeader.methods = { initializeComponent: jest.fn(), }; + const mountOptions = getMountOptions(mountOptionsMockData); const wrapper = shallowMount(vehicleMake, mountOptions); const makeQuestionWrapper = wrapper.findComponent({ name: "makeQuestion" }); diff --git a/src/layouts/vehicle-make/vehicle-make.vue b/src/layouts/vehicle-make/vehicle-make.vue index 91fe4c9d5..ee90b2d36 100644 --- a/src/layouts/vehicle-make/vehicle-make.vue +++ b/src/layouts/vehicle-make/vehicle-make.vue @@ -4,11 +4,11 @@
-
@@ -25,6 +25,7 @@ import funnelSubHeader from "@/common-components/funnel-sub-header/funnel-sub-he // Supporting files import { fetchCmsContentForPage } from "@/helpers/cms-content-helper"; import { settleAllPromises } from "@/helpers/layout-helper"; +import store from "@/store"; export default { name: "vehicle-make", data() { @@ -53,7 +54,6 @@ export default { ]; const resultMap = await settleAllPromises(promiseResultMap); - // Call the "next" function to complete the transition to this page. next((vm) => { vm.$refs.funnelSubHeader.initializeComponent( @@ -77,6 +77,10 @@ export default { // route to move backwards this.$router.navigate(this.navigationScenarios.CLICKED_BACK, this.$route); }, + arePagePrerequisitesValid() { + console.log(store.getters.vehicle); + return store.getters.vehicle.year !== null; + }, }, watch: { diff --git a/src/layouts/vehicle-model/vehicle-model.vue b/src/layouts/vehicle-model/vehicle-model.vue index b06486c74..b27b98d40 100644 --- a/src/layouts/vehicle-model/vehicle-model.vue +++ b/src/layouts/vehicle-model/vehicle-model.vue @@ -25,6 +25,8 @@ import vehicleBanner from "@/common-components/vehicle-banner/vehicle-banner"; // Supporting files import { fetchCmsContentForPage } from "@/helpers/cms-content-helper"; import { settleAllPromises } from "@/helpers/layout-helper"; +import store from "@/store"; + export default { name: "vehicle-model", data() { @@ -77,6 +79,9 @@ export default { // route to move backwards this.$router.navigate(this.navigationScenarios.CLICKED_BACK, this.$route); }, + arePagePrerequisitesValid() { + return store.getters.vehicle.make !== null; + }, }, watch: { diff --git a/src/layouts/vehicle-style/vehicle-style.vue b/src/layouts/vehicle-style/vehicle-style.vue index 3c0023db1..7193c9e39 100644 --- a/src/layouts/vehicle-style/vehicle-style.vue +++ b/src/layouts/vehicle-style/vehicle-style.vue @@ -25,6 +25,8 @@ import vehicleBanner from "@/common-components/vehicle-banner/vehicle-banner"; // Supporting files import { fetchCmsContentForPage } from "@/helpers/cms-content-helper"; import { settleAllPromises } from "@/helpers/layout-helper"; +import store from "@/store"; + export default { name: "vehicle-style", data() { @@ -78,17 +80,31 @@ export default { this.$router.navigate(this.navigationScenarios.CLICKED_BACK, this.$route); }, setVehicle() { - return this.dispatchNonBlockingStoreAction(this.storeActions.SET_VEHICLE, {year: this.$store.getters.vehicle.year, make: this.$store.getters.vehicle.make, model: this.$store.getters.vehicle.model, style: this.$store.getters.vehicle.style}); - } + return this.dispatchNonBlockingStoreAction( + this.storeActions.SET_VEHICLE, + { + year: this.$store.getters.vehicle.year, + make: this.$store.getters.vehicle.make, + model: this.$store.getters.vehicle.model, + style: this.$store.getters.vehicle.style, + } + ); + }, + arePagePrerequisitesValid() { + return store.getters.vehicle.model !== null; + }, }, watch: { selectedStyle(style) { this.$store.commit(this.storeMutations.UPDATE_STYLE, style); this.setVehicle().then(() => { - this.$router.navigate(this.navigationScenarios.SELECTED_STYLE, this.$route); + this.$router.navigate( + this.navigationScenarios.SELECTED_STYLE, + this.$route + ); }); - } + }, }, components: { diff --git a/src/layouts/vehicle-year/vehicle-year.vue b/src/layouts/vehicle-year/vehicle-year.vue index dbf488ea2..ddef0d5a8 100644 --- a/src/layouts/vehicle-year/vehicle-year.vue +++ b/src/layouts/vehicle-year/vehicle-year.vue @@ -4,9 +4,7 @@
- +
@@ -80,6 +78,11 @@ export default { ); }, }, + methods: { + arePagePrerequisitesValid() { + return true; + }, + }, components: { yearQuestion, funnelHeader, diff --git a/src/router/index.js b/src/router/index.js index 2a80032f6..7482a3d50 100644 --- a/src/router/index.js +++ b/src/router/index.js @@ -44,6 +44,13 @@ const routes = [ try { // If we already have our route, go to it. if (router.hasRoute(to.query.fmgPage)) { + // Since our route is already in scope, we can grab the component from it and call the arePagePrerequisitesValid function. + let arePagePrerequisitesValid = router.getRoutes().filter(x => x.name === to.query.fmgPage)[0].components.default.methods.arePagePrerequisitesValid(); + + if (!arePagePrerequisitesValid) { + await GoToFunnelStartOn404(next); + } + return next({ name: to.query.fmgPage, query: to.query }); } @@ -57,9 +64,17 @@ const routes = [ component: routeData[0].component, }); + // Call the next components arePagePrerequisitesValid method before load. + // If it returns false, use the 404 logic. + let nextComponent = await router.getRoutes().filter(x => x.name === routeData[0].name)[0].components.default(); + + if (!nextComponent.default.methods.arePagePrerequisitesValid()) { + await GoToFunnelStartOn404(next); + } + // Assign current query string parameters, as well as our fmgPage one. next({ name: routeData[0].name, query: Object.assign(to.query, { fmgPage: routeData[0].name }) }); - + } catch (error) { console.log(error); @@ -79,6 +94,7 @@ const router = createRouter({ //---------------------------------------------------------- Router Functions ---------------------------------------------------------- + // Navigate to the next route, depending on the scenario. router.navigate = ( scenario, From 0fc7ea8d67781930676b17995ed6bb0490dd63c1 Mon Sep 17 00:00:00 2001 From: FrankRua Date: Fri, 28 Jan 2022 10:19:51 -0500 Subject: [PATCH 21/23] added tests, increased code coverage --- jest.config.js | 2 +- .../vehicle-damage/vehicle-damage.spec.js | 222 +++++++++++------- src/layouts/vehicle-make/vehicle-make.spec.js | 33 ++- src/layouts/vehicle-make/vehicle-make.vue | 1 - .../vehicle-model/vehicle-model.spec.js | 83 +++++-- .../vehicle-style/vehicle-style.spec.js | 51 +++- src/layouts/vehicle-year/vehicle-year.spec.js | 18 ++ src/mixins/base-mixin.spec.js | 49 ++++ 8 files changed, 328 insertions(+), 131 deletions(-) diff --git a/jest.config.js b/jest.config.js index 7a6fcbc01..f4355ef93 100644 --- a/jest.config.js +++ b/jest.config.js @@ -18,7 +18,7 @@ module.exports = { testMatch: ["**/*.spec.(js|jsx|ts|tsx)|**/__tests__/*.(js|jsx|ts|tsx)"], coverageThreshold: { global: { - statements: 85, + statements: 87, }, }, }; diff --git a/src/layouts/vehicle-damage/vehicle-damage.spec.js b/src/layouts/vehicle-damage/vehicle-damage.spec.js index a6688a9af..02a50023c 100644 --- a/src/layouts/vehicle-damage/vehicle-damage.spec.js +++ b/src/layouts/vehicle-damage/vehicle-damage.spec.js @@ -1,16 +1,34 @@ -import { shallowMount, flushPromises } from "@vue/test-utils"; -import { getMountOptions } from "@/helpers/unit-test-helper.js"; +// Components 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"; + +// Supporting Files import { settleAllPromises } from "@/helpers/layout-helper.js"; import baseMixin from "@/mixins/base-mixin"; +import { fetchCmsContentForPage } from "@/helpers/cms-content-helper"; +import { shallowMount } from "@vue/test-utils"; +import { getMountOptions } from "@/helpers/unit-test-helper.js"; import { nextTick } from "vue"; // Mock our module for promises. jest.mock("@/helpers/layout-helper.js", () => ({ - settleAllPromises: jest.fn(), + settleAllPromises: jest.fn(), +})); + +// Mock fetchCmsContentForPage +jest.mock("@/helpers/cms-content-helper", () => ({ + fetchCmsContentForPage: jest.fn(), +})); + +// Mock Store +jest.mock("@/store", () => ({ + getters: { + vehicle: { + carId: "C00000000" + } + } })); describe("vehicle-damage.vue", () => { @@ -18,7 +36,7 @@ describe("vehicle-damage.vue", () => { //Arrange const pageHeaderWidgetHeaderText = "Select Damage"; - const { wrapper, apiPromise } = setupMocks( { pageHeaderWidgetHeaderText: pageHeaderWidgetHeaderText }); + const { wrapper, apiPromise } = setupMocks({ pageHeaderWidgetHeaderText: pageHeaderWidgetHeaderText }); //Act vehicleDamage.beforeRouteEnter.call(wrapper.vm, { query: { fmgPage: "vehicle-damage" } }, undefined, (c) => c(wrapper.vm)); @@ -32,94 +50,120 @@ describe("vehicle-damage.vue", () => { }); describe("vehicle-damage.vue", () => { - test("Page logo image is initailized with api data", async (done) => { - - //Arrange - const SiteHeaderWidget = { - LogoImage: - "https://digitalconsumercms-dev.safelite.com/images/default-source/default-album/safelite-logo.svg?sfvrsn=45e7ed06_3", - } - const { wrapper, apiPromise } = setupMocks( { SiteHeaderWidget: SiteHeaderWidget}); - - //Act - vehicleDamage.beforeRouteEnter.call(wrapper.vm, { query: { fmgPage: "vehicle-damage" } }, undefined, (c) => c(wrapper.vm)); - - //Assert - apiPromise.finally(() => { - expect(funnelHeader.methods.initializeComponent).toHaveBeenCalledWith(SiteHeaderWidget); - done(); - }); - }); - }); + test("Page logo image is initailized with api data", async (done) => { - describe("vehicle-damage.vue", () => { - test("Vehicle image is initailized with api data", async (done) => { - - //Arrange - const VehicleBannerWidget = { - GenericVehicleImage: - "https://digitalconsumercms-dev.safelite.com/images/default-source/default-album/blurred-image.jpg?sfvrsn=a6ce3034_3", - } - const { wrapper, apiPromise } = setupMocks( { VehicleBannerWidget: VehicleBannerWidget}); - - //Act - vehicleDamage.beforeRouteEnter.call(wrapper.vm, { query: { fmgPage: "vehicle-damage" } }, undefined, (c) => c(wrapper.vm)); - - //Assert - apiPromise.finally(() => { - expect(vehicleBanner.methods.initializeComponent).toHaveBeenCalledWith(VehicleBannerWidget); - done(); - }); + //Arrange + const SiteHeaderWidget = { + LogoImage: + "https://digitalconsumercms-dev.safelite.com/images/default-source/default-album/safelite-logo.svg?sfvrsn=45e7ed06_3", + } + const { wrapper, apiPromise } = setupMocks({ SiteHeaderWidget: SiteHeaderWidget }); + + //Act + vehicleDamage.beforeRouteEnter.call(wrapper.vm, { query: { fmgPage: "vehicle-damage" } }, undefined, (c) => c(wrapper.vm)); + + //Assert + apiPromise.finally(() => { + expect(funnelHeader.methods.initializeComponent).toHaveBeenCalledWith(SiteHeaderWidget); + done(); }); }); +}); + +describe("vehicle-damage.vue", () => { + test("Vehicle image is initailized with api data", async (done) => { + + //Arrange + const VehicleBannerWidget = { + GenericVehicleImage: + "https://digitalconsumercms-dev.safelite.com/images/default-source/default-album/blurred-image.jpg?sfvrsn=a6ce3034_3", + } + const { wrapper, apiPromise } = setupMocks({ VehicleBannerWidget: VehicleBannerWidget }); + + //Act + vehicleDamage.beforeRouteEnter.call(wrapper.vm, { query: { fmgPage: "vehicle-damage" } }, undefined, (c) => c(wrapper.vm)); + + //Assert + apiPromise.finally(() => { + expect(vehicleBanner.methods.initializeComponent).toHaveBeenCalledWith(VehicleBannerWidget); + done(); + }); + }); +}); + +describe("vehicle-damage.vue", () => { + test("CarId set, arePagePrerequisitesValid should be true ", async () => { + + //Arrange + const { wrapper } = setupMocks({}); + + //Act + vehicleDamage.beforeRouteEnter.call(wrapper.vm, { query: { fmgPage: "vehicle-damage" } }, undefined, (c) => c(wrapper.vm)); + + let arePagePrerequisitesValid = wrapper.vm.arePagePrerequisitesValid(); + await nextTick(); + + //Assert + expect(arePagePrerequisitesValid).toBe(true); + }); +}); function setupMocks({ - pageHeaderWidgetHeaderText = {}, - mountOptionsMockData = {}, - }) { - - //Mock api responses - baseMixin.methods.dispatchNonBlockingStoreAction = jest.fn(); - baseMixin.methods.dispatchNonBlockingStoreAction.mockImplementation(() => { - return Promise.resolve({ data: ['Front Window', 'Back Window', 'Side Window'] }); - }); - const apiResponses = { - cmsContent: { - FunnelSubHeaderWidget: pageHeaderWidgetHeaderText, - VehicleBannerWidget: - { - GenericVehicleImage: - "https://digitalconsumercms-dev.safelite.com/images/default-source/default-album/blurred-image.jpg?sfvrsn=a6ce3034_3", - }, - FunnelHeaderWidget: - { - LogoImage: - "https://digitalconsumercms-dev.safelite.com/images/default-source/default-album/safelite-logo.svg?sfvrsn=45e7ed06_3", - }, + pageHeaderWidgetHeaderText = {}, + mountOptionsMockData = {}, +}) { + + //Mock api responses + baseMixin.methods.dispatchNonBlockingStoreAction = jest.fn(); + baseMixin.methods.dispatchNonBlockingStoreAction.mockImplementation(() => { + return Promise.resolve({ data: ['Front Window', 'Back Window', 'Side Window'] }); + }); + const apiResponses = { + cmsContent: { + FunnelSubHeaderWidget: pageHeaderWidgetHeaderText, + VehicleBannerWidget: + { + GenericVehicleImage: + "https://digitalconsumercms-dev.safelite.com/images/default-source/default-album/blurred-image.jpg?sfvrsn=a6ce3034_3", }, - damageOptions: ['Front Window', 'Back Window', 'Side Window'], - }; - const apiPromise = Promise.resolve(apiResponses); - settleAllPromises.mockImplementation(() => apiPromise); - - //Mock damage initialize methods - funnelHeader.methods = { - initializeComponent: jest.fn(), - }; - vehicleBanner.methods = { - initializeComponent: jest.fn(), - }; - funnelSubHeader.methods = { - initializeComponent: jest.fn(), - }; - const mountOptions = getMountOptions(mountOptionsMockData); - const wrapper = shallowMount(vehicleDamage, mountOptions); - const funnelHeaderWrapper = wrapper.findComponent({ name: "funnelHeader" }); - funnelHeaderWrapper.vm.initializeComponent = funnelHeader.methods.initializeComponent; - const vehicleBannerWrapper = wrapper.findComponent({ name: "vehicleBanner" }); - vehicleBannerWrapper.vm.initializeComponent = vehicleBanner.methods.initializeComponent; - const funnelSubHeaderWrapper = wrapper.findComponent({ name: "funnelSubHeader" }); - funnelSubHeaderWrapper.vm.initializeComponent = funnelSubHeader.methods.initializeComponent; - - return { wrapper, apiPromise }; - } \ No newline at end of file + FunnelHeaderWidget: + { + LogoImage: + "https://digitalconsumercms-dev.safelite.com/images/default-source/default-album/safelite-logo.svg?sfvrsn=45e7ed06_3", + }, + }, + damageOptions: ['Front Window', 'Back Window', 'Side Window'], + }; + + const apiPromise = Promise.resolve(apiResponses); + + settleAllPromises.mockImplementation(() => apiPromise); + fetchCmsContentForPage.mockImplementation(() => Promise.resolve()); + + //Mock damage initialize methods + funnelHeader.methods = { + initializeComponent: jest.fn(), + }; + + vehicleBanner.methods = { + initializeComponent: jest.fn(), + }; + + funnelSubHeader.methods = { + initializeComponent: jest.fn(), + }; + + const mountOptions = getMountOptions(mountOptionsMockData); + const wrapper = shallowMount(vehicleDamage, mountOptions); + + const funnelHeaderWrapper = wrapper.findComponent({ name: "funnelHeader" }); + funnelHeaderWrapper.vm.initializeComponent = funnelHeader.methods.initializeComponent; + + const vehicleBannerWrapper = wrapper.findComponent({ name: "vehicleBanner" }); + vehicleBannerWrapper.vm.initializeComponent = vehicleBanner.methods.initializeComponent; + + const funnelSubHeaderWrapper = wrapper.findComponent({ name: "funnelSubHeader" }); + funnelSubHeaderWrapper.vm.initializeComponent = funnelSubHeader.methods.initializeComponent; + + return { wrapper, apiPromise }; +} \ No newline at end of file diff --git a/src/layouts/vehicle-make/vehicle-make.spec.js b/src/layouts/vehicle-make/vehicle-make.spec.js index 41a7939ad..8043b94d7 100644 --- a/src/layouts/vehicle-make/vehicle-make.spec.js +++ b/src/layouts/vehicle-make/vehicle-make.spec.js @@ -9,11 +9,11 @@ import { settleAllPromises } from "@/helpers/layout-helper.js"; import { nextTick } from "vue"; import { fetchCmsContentForPage } from "@/helpers/cms-content-helper"; -// Mock Store + jest.mock("@/store", () => ({ getters: { - vehicle: { - year: 2019, + vehicle: { + year: 2019 } } })); @@ -28,6 +28,9 @@ jest.mock("@/helpers/layout-helper.js", () => ({ settleAllPromises: jest.fn(), })); +beforeEach(() => { + jest.resetModules(); +}); describe("vehicle-make.vue", () => { test("Make question component is initized with api data", async (done) => { @@ -40,7 +43,7 @@ describe("vehicle-make.vue", () => { makeQuestionInitialData: makeQuestionInitialData, }); - + //Act vehicleMake.beforeRouteEnter.call(wrapper.vm, { query: { fmgPage: "vehicle-make" } }, undefined, (c) => c(wrapper.vm)); @@ -58,7 +61,7 @@ describe("vehicle-make.vue", () => { //Arrange const pageHeaderWidgetHeaderText = "Select a make to get started"; const { wrapper, apiPromise } = setupMocks({ pageHeaderWidgetHeaderText: pageHeaderWidgetHeaderText }); - + //Act vehicleMake.beforeRouteEnter.call(wrapper.vm, { query: { fmgPage: "vehicle-make" } }, undefined, (c) => c(wrapper.vm)); @@ -79,7 +82,7 @@ describe("vehicle-make.vue", () => { "https://digitalconsumercms-dev.safelite.com/images/default-source/default-album/safelite-logo.svg?sfvrsn=45e7ed06_3", } const { wrapper, apiPromise } = setupMocks({ SiteHeaderWidget: SiteHeaderWidget }); - + //Act vehicleMake.beforeRouteEnter.call(wrapper.vm, { query: { fmgPage: "vehicle-make" } }, undefined, (c) => c(wrapper.vm)); @@ -100,7 +103,7 @@ describe("vehicle-make.vue", () => { "https://digitalconsumercms-dev.safelite.com/images/default-source/default-album/blurred-image.jpg?sfvrsn=a6ce3034_3", } const { wrapper, apiPromise } = setupMocks({ VehicleBannerWidget: VehicleBannerWidget }); - + //Act vehicleMake.beforeRouteEnter.call(wrapper.vm, { query: { fmgPage: "vehicle-make" } }, undefined, (c) => c(wrapper.vm)); @@ -124,7 +127,7 @@ describe("vehicle-make.vue", () => { }, }, }); - + //Act vehicleMake.beforeRouteEnter.call(wrapper.vm, { query: { fmgPage: "vehicle-make" } }, undefined, (c) => c(wrapper.vm)); wrapper.vm.backButtonAction(); @@ -139,13 +142,10 @@ describe("vehicle-make.vue", () => { }); describe("vehicle-make.vue", () => { - test("arePagePrerequisitesValid", async (done) => { + test("Year set, arePagePrerequisitesValid should be true ", async () => { //Arrange - const { wrapper, apiPromise } = setupMocks({ - pageHeaderWidgetHeaderText: "Select a make to get started", - mountOptionsMockData: {}, - }); + const { wrapper } = setupMocks({}); //Act vehicleMake.beforeRouteEnter.call(wrapper.vm, { query: { fmgPage: "vehicle-make" } }, undefined, (c) => c(wrapper.vm)); @@ -154,10 +154,7 @@ describe("vehicle-make.vue", () => { await nextTick(); //Assert - apiPromise.finally(() => { - expect(arePagePrerequisitesValid).toBe(true); - done(); - }); + expect(arePagePrerequisitesValid).toBe(true); }); }); @@ -187,7 +184,7 @@ function setupMocks({ }, makeQuestionInitialData: makeQuestionInitialData, }; - + const apiPromise = Promise.resolve(apiResponses); fetchCmsContentForPage.mockImplementation(() => Promise.resolve()); diff --git a/src/layouts/vehicle-make/vehicle-make.vue b/src/layouts/vehicle-make/vehicle-make.vue index ee90b2d36..111b16e5f 100644 --- a/src/layouts/vehicle-make/vehicle-make.vue +++ b/src/layouts/vehicle-make/vehicle-make.vue @@ -78,7 +78,6 @@ export default { this.$router.navigate(this.navigationScenarios.CLICKED_BACK, this.$route); }, arePagePrerequisitesValid() { - console.log(store.getters.vehicle); return store.getters.vehicle.year !== null; }, }, diff --git a/src/layouts/vehicle-model/vehicle-model.spec.js b/src/layouts/vehicle-model/vehicle-model.spec.js index 861303ac8..1187220b7 100644 --- a/src/layouts/vehicle-model/vehicle-model.spec.js +++ b/src/layouts/vehicle-model/vehicle-model.spec.js @@ -1,25 +1,45 @@ -import { shallowMount, flushPromises } from "@vue/test-utils"; -import { getMountOptions } from "@/helpers/unit-test-helper.js"; +// Components import vehicleModel from "@/layouts/vehicle-model/vehicle-model.vue"; import modelQuestion from "@/layouts/vehicle-model/model-question/model-question"; 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"; + +// Supporting files import { settleAllPromises } from "@/helpers/layout-helper.js"; +import { shallowMount, flushPromises } from "@vue/test-utils"; +import { getMountOptions } from "@/helpers/unit-test-helper.js"; import { nextTick } from "vue"; +import { fetchCmsContentForPage } from "@/helpers/cms-content-helper"; + // 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(), +})); + +// Mock Store +jest.mock("@/store", () => ({ + getters: { + vehicle: { + make: "Acura" + } + } +})); + describe("vehicle-model.vue", () => { test("Model question component is initized with api data", async (done) => { //Arange const buttonQuestionContent = { QuestionText: "What model is your vehicle?" }; const modelQuestionInitialData = ["accord", "civic", "insight"]; - const { wrapper, apiPromise } = setupMocks( { - buttonQuestionContent: buttonQuestionContent, + const { wrapper, apiPromise } = setupMocks({ + buttonQuestionContent: buttonQuestionContent, modelQuestionInitialData: modelQuestionInitialData, - } ); + }); //Act vehicleModel.beforeRouteEnter.call(wrapper.vm, { query: { fmgPage: "vehicle-model" } }, undefined, (c) => c(wrapper.vm)); //Assert @@ -33,7 +53,7 @@ describe("vehicle-model.vue", () => { test("Page header is initailized with api data", async (done) => { //Arrange const pageHeaderWidgetHeaderText = "Select a model to get started"; - const { wrapper, apiPromise } = setupMocks( { pageHeaderWidgetHeaderText: pageHeaderWidgetHeaderText }); + const { wrapper, apiPromise } = setupMocks({ pageHeaderWidgetHeaderText: pageHeaderWidgetHeaderText }); //Act vehicleModel.beforeRouteEnter.call(wrapper.vm, { query: { fmgPage: "vehicle-model" } }, undefined, (c) => c(wrapper.vm)); //Assert @@ -50,7 +70,7 @@ describe("vehicle-model.vue", () => { LogoImage: "https://digitalconsumercms-dev.safelite.com/images/default-source/default-album/safelite-logo.svg?sfvrsn=45e7ed06_3", } - const { wrapper, apiPromise } = setupMocks( { SiteHeaderWidget: SiteHeaderWidget}); + const { wrapper, apiPromise } = setupMocks({ SiteHeaderWidget: SiteHeaderWidget }); //Act vehicleModel.beforeRouteEnter.call(wrapper.vm, { query: { fmgPage: "vehicle-model" } }, undefined, (c) => c(wrapper.vm)); //Assert @@ -67,7 +87,7 @@ describe("vehicle-model.vue", () => { GenericVehicleImage: "https://digitalconsumercms-dev.safelite.com/images/default-source/default-album/blurred-image.jpg?sfvrsn=a6ce3034_3", } - const { wrapper, apiPromise } = setupMocks( { VehicleBannerWidget: VehicleBannerWidget}); + const { wrapper, apiPromise } = setupMocks({ VehicleBannerWidget: VehicleBannerWidget }); //Act vehicleModel.beforeRouteEnter.call(wrapper.vm, { query: { fmgPage: "vehicle-model" } }, undefined, (c) => c(wrapper.vm)); //Assert @@ -80,7 +100,7 @@ describe("vehicle-model.vue", () => { describe("vehicle-model.vue", () => { test("BackButtonAction triggers a router.navigate change", async (done) => { //Arrange - const { wrapper, apiPromise } = setupMocks( { + const { wrapper, apiPromise } = setupMocks({ pageHeaderWidgetHeaderText: "Select a model to get started", mountOptionsMockData: { router: { @@ -99,6 +119,23 @@ describe("vehicle-model.vue", () => { }); }); }); +describe("vehicle-model.vue", () => { + test("Make set, arePagePrerequisitesValid should be true ", async () => { + + //Arrange + const { wrapper } = setupMocks({}); + + //Act + vehicleModel.beforeRouteEnter.call(wrapper.vm, { query: { fmgPage: "vehicle-model" } }, undefined, (c) => c(wrapper.vm)); + + let arePagePrerequisitesValid = wrapper.vm.arePagePrerequisitesValid(); + await nextTick(); + + //Assert + expect(arePagePrerequisitesValid).toBe(true); + }); +}); + function setupMocks({ buttonQuestionContent = {}, modelQuestionInitialData = {}, @@ -110,21 +147,24 @@ function setupMocks({ cmsContent: { FunnelSubHeaderWidget: pageHeaderWidgetHeaderText, VehicleModelQuestion: buttonQuestionContent, - VehicleBannerWidget: - { - GenericVehicleImage: - "https://digitalconsumercms-dev.safelite.com/images/default-source/default-album/blurred-image.jpg?sfvrsn=a6ce3034_3", - }, - FunnelHeaderWidget: - { - LogoImage: - "https://digitalconsumercms-dev.safelite.com/images/default-source/default-album/safelite-logo.svg?sfvrsn=45e7ed06_3", - }, + VehicleBannerWidget: + { + GenericVehicleImage: + "https://digitalconsumercms-dev.safelite.com/images/default-source/default-album/blurred-image.jpg?sfvrsn=a6ce3034_3", + }, + FunnelHeaderWidget: + { + 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); + fetchCmsContentForPage.mockImplementation(() => Promise.resolve()); + //Mock model question methods modelQuestion.methods = { loadInitialData: jest.fn(), @@ -141,13 +181,18 @@ function setupMocks({ }; const mountOptions = getMountOptions(mountOptionsMockData); const wrapper = shallowMount(vehicleModel, mountOptions); + const modelQuestionWrapper = wrapper.findComponent({ name: "modelQuestion" }); modelQuestionWrapper.vm.initializeComponent = modelQuestion.methods.initializeComponent; + const funnelHeaderWrapper = wrapper.findComponent({ name: "funnelHeader" }); funnelHeaderWrapper.vm.initializeComponent = funnelHeader.methods.initializeComponent; + const vehicleBannerWrapper = wrapper.findComponent({ name: "vehicleBanner" }); vehicleBannerWrapper.vm.initializeComponent = vehicleBanner.methods.initializeComponent; + const funnelSubHeaderWrapper = wrapper.findComponent({ name: "funnelSubHeader" }); funnelSubHeaderWrapper.vm.initializeComponent = funnelSubHeader.methods.initializeComponent; + return { wrapper, apiPromise }; } \ No newline at end of file diff --git a/src/layouts/vehicle-style/vehicle-style.spec.js b/src/layouts/vehicle-style/vehicle-style.spec.js index 31c1b2487..d408ceb9d 100644 --- a/src/layouts/vehicle-style/vehicle-style.spec.js +++ b/src/layouts/vehicle-style/vehicle-style.spec.js @@ -1,19 +1,37 @@ -import { shallowMount, flushPromises } from "@vue/test-utils"; -import { getMountOptions } from "@/helpers/unit-test-helper.js"; -import { storeActions } from "@/constants/store-actions"; +// Components import vehicleStyle from "@/layouts/vehicle-style/vehicle-style.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 styleQuestion from "@/layouts/vehicle-style/style-question/style-question"; + +// Supporting files import { settleAllPromises } from "@/helpers/layout-helper.js"; import { nextTick } from "vue"; +import { shallowMount } from "@vue/test-utils"; +import { getMountOptions } from "@/helpers/unit-test-helper.js"; +import { storeActions } from "@/constants/store-actions"; +import { fetchCmsContentForPage } from "@/helpers/cms-content-helper"; // 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(), +})); + +// Mock Store +jest.mock("@/store", () => ({ + getters: { + vehicle: { + model: "TL" + } + } +})); + describe("vehicle-style.vue", () => { test("Style question component is initized with api data", async (done) => { @@ -162,6 +180,22 @@ describe("vehicle-style.vue", () => { }); }); +describe("vehicle-style.vue", () => { + test("Model set, arePagePrerequisitesValid should be true ", async () => { + + //Arrange + const { wrapper } = setupMocks({}); + + //Act + vehicleStyle.beforeRouteEnter.call(wrapper.vm, { query: { fmgPage: "vehicle-style" } }, undefined, (c) => c(wrapper.vm)); + + let arePagePrerequisitesValid = wrapper.vm.arePagePrerequisitesValid(); + await nextTick(); + + //Assert + expect(arePagePrerequisitesValid).toBe(true); + }); +}); function setupMocks({ vehicleStyleQuestionCmsContent = {}, styleQuestionInitialData = {}, @@ -187,31 +221,42 @@ function setupMocks({ }, styleQuestionInitialData: styleQuestionInitialData, }; + const apiPromise = Promise.resolve(apiResponses); + settleAllPromises.mockImplementation(() => apiPromise); + fetchCmsContentForPage.mockImplementation(() => Promise.resolve()); //Mock style question methods styleQuestion.methods = { loadInitialData: jest.fn(), initializeComponent: jest.fn(), }; + funnelHeader.methods = { initializeComponent: jest.fn(), }; + vehicleBanner.methods = { initializeComponent: jest.fn(), }; + funnelSubHeader.methods = { initializeComponent: jest.fn(), }; + const mountOptions = getMountOptions(mountOptionsMockData); const wrapper = shallowMount(vehicleStyle, mountOptions); + const styleQuestionWrapper = wrapper.findComponent({ name: "styleQuestion" }); styleQuestionWrapper.vm.initializeComponent = styleQuestion.methods.initializeComponent; + const funnelHeaderWrapper = wrapper.findComponent({ name: "funnelHeader" }); funnelHeaderWrapper.vm.initializeComponent = funnelHeader.methods.initializeComponent; + const vehicleBannerWrapper = wrapper.findComponent({ name: "vehicleBanner" }); vehicleBannerWrapper.vm.initializeComponent = vehicleBanner.methods.initializeComponent; + const funnelSubHeaderWrapper = wrapper.findComponent({ name: "funnelSubHeader" }); funnelSubHeaderWrapper.vm.initializeComponent = funnelSubHeader.methods.initializeComponent; diff --git a/src/layouts/vehicle-year/vehicle-year.spec.js b/src/layouts/vehicle-year/vehicle-year.spec.js index df0668c31..c386bf4d4 100644 --- a/src/layouts/vehicle-year/vehicle-year.spec.js +++ b/src/layouts/vehicle-year/vehicle-year.spec.js @@ -77,6 +77,24 @@ describe("vehicle-year.vue", () => { }); }); + +describe("vehicle-year.vue", () => { + test("arePagePrerequisitesValid should be true ", async () => { + + //Arrange + const { wrapper } = setupMocks({}); + + //Act + vehicleYear.beforeRouteEnter.call(wrapper.vm, { query: { fmgPage: "vehicle-make" } }, undefined, (c) => c(wrapper.vm)); + + let arePagePrerequisitesValid = wrapper.vm.arePagePrerequisitesValid(); + await nextTick(); + + //Assert + expect(arePagePrerequisitesValid).toBe(true); + }); +}); + function setupMocks({ vehicleYearQuestionCmsContent = {}, yearQuestionInitialData = {}, diff --git a/src/mixins/base-mixin.spec.js b/src/mixins/base-mixin.spec.js index e9ccbdc5b..42281c4d7 100644 --- a/src/mixins/base-mixin.spec.js +++ b/src/mixins/base-mixin.spec.js @@ -1,6 +1,8 @@ import baseMixin from "@/mixins/base-mixin"; import { storeActions } from "@/constants/store-actions.js"; import { widgetNames } from "@/constants/widget-names.js"; +import { storeMutations } from "@/constants/store-mutations.js"; +import { navigationScenarios } from "@/router/router-constants/navigation-scenarios"; import store from "@/store"; describe("baseMixin.js", () => { @@ -23,7 +25,54 @@ describe("baseMixin.js", () => { expect(store.dispatch).toBeCalledWith(type, payload); }); + + test("computed: storeActions should be equal to import object", () => { + // Arrange + const mixIn = getMixInInstance({}); + + // Act + let storeActionsForTest = mixIn.computed.storeActions(); + + // Assert + expect(storeActionsForTest).toEqual(storeActions); + }); + + test("computed: storeMutations should be equal to import object", () => { + // Arrange + const mixIn = getMixInInstance({}); + + // Act + let storeMutationsForTest = mixIn.computed.storeMutations(); + + // Assert + expect(storeMutationsForTest).toEqual(storeMutations); + }); + + test("computed: navigationScenarios should be equal to import object", () => { + // Arrange + const mixIn = getMixInInstance({}); + + // Act + let navigationScenariosForTest = mixIn.computed.navigationScenarios(); + + // Assert + expect(navigationScenariosForTest).toEqual(navigationScenarios); + }); + + test("computed: widgetNames should be equal to import object", () => { + // Arrange + const mixIn = getMixInInstance({}); + + // Act + let widgetNamesForTest = mixIn.computed.widgetNames(); + + // Assert + expect(widgetNamesForTest).toEqual(widgetNames); + }); + }); + + function getMixInInstance({ isDispatchSuccess = true }) { // Mock Store const storeDispatch = jest.fn(); From b92c425fb45e7f9332e62d915f8ad8328e49c5ab Mon Sep 17 00:00:00 2001 From: FrankRua Date: Fri, 28 Jan 2022 10:22:33 -0500 Subject: [PATCH 22/23] Linter --- jest.config.js | 2 +- src/App.vue | 10 +- .../button-back/button-back.spec.js | 4 +- .../button-back/button-back.vue | 35 +- .../button-question/button-question.spec.js | 4 +- .../button-question/button-question.vue | 104 +- .../funnel-header/funnel-header.spec.js | 4 +- .../funnel-header/funnel-header.vue | 91 +- .../funnel-sub-header.spec.js | 6 +- .../funnel-sub-header/funnel-sub-header.vue | 34 +- .../text-input/text-input.spec.js | 7 +- .../text-input/text-input.vue | 20 +- .../vehicle-banner/vehicle-banner.spec.js | 6 +- .../vehicle-banner/vehicle-banner.vue | 6 +- src/constants/events.js | 26 +- src/helpers/cms-content-helper.js | 53 +- src/helpers/cms-helper.spec.js | 52 +- src/helpers/event-bus/event-bus.js | 39 +- src/helpers/event-bus/event-bus.spec.js | 83 +- src/layouts/address-poc/address-poc.vue | 57 +- src/layouts/component-test/component-test.vue | 1168 +++++++++-------- src/layouts/form-test/form-test.vue | 426 +++--- .../vehicle-damage/vehicle-damage.spec.js | 94 +- .../make-question/make-question.spec.js | 55 +- .../make-question/make-question.vue | 14 +- src/layouts/vehicle-make/vehicle-make.spec.js | 121 +- .../model-question/model-question.spec.js | 61 +- .../model-question/model-question.vue | 14 +- .../vehicle-model/vehicle-model.spec.js | 112 +- .../style-question/style-question.spec.js | 57 +- .../style-question/style-question.vue | 18 +- .../vehicle-style/vehicle-style.spec.js | 168 ++- src/layouts/vehicle-year/vehicle-year.spec.js | 105 +- .../year-question/year-question.spec.js | 53 +- .../year-question/year-question.vue | 16 +- src/main.js | 1 - src/mixins/base-mixin.js | 3 +- src/mixins/base-mixin.spec.js | 8 +- src/router/index.js | 34 +- src/router/router-constants/routing-table.js | 8 +- src/store/index.js | 49 +- src/store/store.spec.js | 67 +- .../button-main/button-main.spec.js | 25 +- src/ux-components/button-main/button-main.vue | 38 +- src/ux-components/checkbox/checkbox.spec.js | 17 +- src/ux-components/checkbox/checkbox.vue | 25 +- .../list-button-horizontal.spec.js | 34 +- .../list-button-horizontal.vue | 66 +- .../list-button/list-button.spec.js | 34 +- src/ux-components/list-button/list-button.vue | 69 +- src/ux-components/list-card/list-card.spec.js | 17 +- src/ux-components/list-card/list-card.vue | 105 +- src/ux-components/loader/loader.vue | 11 +- src/ux-components/text-link/text-link.spec.js | 11 +- src/ux-components/text-link/text-link.vue | 35 +- 55 files changed, 2158 insertions(+), 1624 deletions(-) diff --git a/jest.config.js b/jest.config.js index f4355ef93..bce302e5a 100644 --- a/jest.config.js +++ b/jest.config.js @@ -13,7 +13,7 @@ module.exports = { "!src/helpers/unit-test-helper.js", "!src/layouts/component-test/component-test.vue", "!src/layouts/form-test/form-test.vue", - "!src/layouts/address-poc/address-poc.vue" + "!src/layouts/address-poc/address-poc.vue", ], //! means exclude from coverage. testMatch: ["**/*.spec.(js|jsx|ts|tsx)|**/__tests__/*.(js|jsx|ts|tsx)"], coverageThreshold: { diff --git a/src/App.vue b/src/App.vue index f64aad6aa..e529f225a 100644 --- a/src/App.vue +++ b/src/App.vue @@ -3,9 +3,9 @@ diff --git a/src/common-components/button-back/button-back.spec.js b/src/common-components/button-back/button-back.spec.js index b8bc3256d..c7bff87f0 100644 --- a/src/common-components/button-back/button-back.spec.js +++ b/src/common-components/button-back/button-back.spec.js @@ -2,7 +2,6 @@ import { shallowMount } from "@vue/test-utils"; import buttonBack from "./button-back"; describe("back button", () => { - test("renders a button", () => { // Arrange const myFunction = () => {}; @@ -14,10 +13,9 @@ describe("back button", () => { backButtonAccessibleText: "something", }, }); - + // Assert expect(wrapper.find("button").exists()).toBe(true); wrapper.unmount(); }); - }); diff --git a/src/common-components/button-back/button-back.vue b/src/common-components/button-back/button-back.vue index 7f06dfcec..cf3a630bf 100644 --- a/src/common-components/button-back/button-back.vue +++ b/src/common-components/button-back/button-back.vue @@ -1,23 +1,36 @@ diff --git a/src/layouts/component-test/component-test.vue b/src/layouts/component-test/component-test.vue index 7363ec3d4..2f5dc0308 100644 --- a/src/layouts/component-test/component-test.vue +++ b/src/layouts/component-test/component-test.vue @@ -8,10 +8,10 @@
@@ -23,27 +23,21 @@
- +
- +
@@ -56,31 +50,31 @@ Functioning as Checkbox
@@ -95,13 +89,13 @@
Functioning as Checkbox
@@ -112,13 +106,13 @@
Checkbox no Description
@@ -129,13 +123,13 @@
Functioning as Radio Button
@@ -146,13 +140,13 @@
Radio Button no Description
@@ -163,14 +157,14 @@
Horizontal Checkbox
@@ -181,14 +175,14 @@
Checkbox no Description
@@ -199,13 +193,13 @@
Horizontal Radio Button
@@ -216,13 +210,13 @@
Radio Button no Description
@@ -235,93 +229,99 @@
-
+
-

- Select Vehicle Year -

+

Select Vehicle Year

- @@ -333,187 +333,205 @@
-
+

Select Vehicle Year

Functioning as Radio Buttons
-
+

Select Vehicle Year

-

List Button - Multi-Line Centered

+

+ List Button - Multi-Line Centered +

Functioning as Checkboxes
-
+

Multi-Line Centered

Functioning as Radio Buttons
-
+

Multi-Line Centered

@@ -525,104 +543,108 @@
-
+
-

- Select Vehicle Year -

+

Select Vehicle Year

Functioning as Radio Buttons
-
+
-

- Select Vehicle Year -

+

Select Vehicle Year

@@ -633,22 +655,10 @@
-

-

-

- +

+

+

+
@@ -710,60 +720,60 @@
@@ -775,7 +785,7 @@
@@ -787,7 +797,7 @@
@@ -797,94 +807,94 @@
- + :answers="checkboxAnswers" + :isMultiSelect="true" + ariaLabelBy="checkbox" + groupName="checkbox-list" + questionText="List Button as checkbox" + /> - - - - - - - - + :answers="radioAnswers" + ariaLabelBy="radio" + groupName="radio-list" + questionText="List Button as radio" + /> + + + + + + + + +
@@ -913,75 +923,97 @@ export default { checkbox, funnelHeader, buttonQuestion, - textLink + textLink, }, data() { return { years: [2023, 2022, 2021, 2020], - checkboxAnswers: ['Checkbox Answer 1', 'Checkbox Answer 2', 'Checkbox Answer 3'], - radioAnswers: ['Radio Answer 1', 'Radio Answer 2', 'Radio Answer 3'], - horizontalCheckboxAnswers: ['HCB Answer 1', 'HCB Answer 2', 'HCB Answer 3'], - horizontalRadioAnswers: ['HR Answer 1', 'HR Answer 2', 'HR Answer 3'], - listCardCheckBox: [{ - Name: 'List-Card-CB', - Text: "List Card CB", - SubText: "checkbox", - ImageId: '53343ce4-5b6a-46aa-a80a-f948c1723955', - AnswerImageUrl: "side-window-damage-right-all.svg" - }], - listCardRadio: [{ - Name: 'List-Card-R', - Text: "List Card R", - SubText: "Radio", - ImageId: '53343ce4-5b6a-46aa-a80a-f948c1723955', - AnswerImageUrl: "side-window-damage-right-all.svg" - }], - listCardCheckBoxHorizontalSubText: [{ - Name: 'List-Card-CBHst', - Text: "List Card CBHst", - SubText: "With Subtext", - ImageId: '53343ce4-5b6a-46aa-a80a-f948c1723955', - AnswerImageUrl: "side-window-damage-right-all.svg" - }], - listCardCheckBoxHorizontal: [{ - Name: 'List-Card-CBH', - Text: "List Card CBH", - ImageId: '53343ce4-5b6a-46aa-a80a-f948c1723955', - AnswerImageUrl: "side-window-damage-right-all.svg" - }], - listRadioHorizontalSubText: [{ - Name: 'List-Card-RHst', - Text: "List Card RHst", - SubText: "With Subtext", - ImageId: '53343ce4-5b6a-46aa-a80a-f948c1723955', - AnswerImageUrl: "side-window-damage-right-all.svg" - }], - listRadioHorizontal: [{ - Name: 'List-Card-RH', - Text: "List Card RH", - ImageId: '53343ce4-5b6a-46aa-a80a-f948c1723955', - AnswerImageUrl: "side-window-damage-right-all.svg" - }], - listCardGroup: [{ - Name: 'Side-Window-1', - Text: "Side Window", - SubText: "With Subtext", - ImageId: '53343ce4-5b6a-46aa-a80a-f948c1723955', - AnswerImageUrl: "side-window-damage-right-all.svg" - }, - { - Name: 'Side-Window-2', - Text: "Side Window", - SubText: "With Subtext that is more than one line", - ImageId: '53343ce4-5b6a-46aa-a80a-f948c1723955', - AnswerImageUrl: "side-window-damage-right-all.svg" - }, - { - Name: 'Side-Window-3', - Text: "Side Window", - ImageId: '53343ce4-5b6a-46aa-a80a-f948c1723955', - AnswerImageUrl: "side-window-damage-right-all.svg" - }], + checkboxAnswers: [ + "Checkbox Answer 1", + "Checkbox Answer 2", + "Checkbox Answer 3", + ], + radioAnswers: ["Radio Answer 1", "Radio Answer 2", "Radio Answer 3"], + horizontalCheckboxAnswers: [ + "HCB Answer 1", + "HCB Answer 2", + "HCB Answer 3", + ], + horizontalRadioAnswers: ["HR Answer 1", "HR Answer 2", "HR Answer 3"], + listCardCheckBox: [ + { + Name: "List-Card-CB", + Text: "List Card CB", + SubText: "checkbox", + ImageId: "53343ce4-5b6a-46aa-a80a-f948c1723955", + AnswerImageUrl: "side-window-damage-right-all.svg", + }, + ], + listCardRadio: [ + { + Name: "List-Card-R", + Text: "List Card R", + SubText: "Radio", + ImageId: "53343ce4-5b6a-46aa-a80a-f948c1723955", + AnswerImageUrl: "side-window-damage-right-all.svg", + }, + ], + listCardCheckBoxHorizontalSubText: [ + { + Name: "List-Card-CBHst", + Text: "List Card CBHst", + SubText: "With Subtext", + ImageId: "53343ce4-5b6a-46aa-a80a-f948c1723955", + AnswerImageUrl: "side-window-damage-right-all.svg", + }, + ], + listCardCheckBoxHorizontal: [ + { + Name: "List-Card-CBH", + Text: "List Card CBH", + ImageId: "53343ce4-5b6a-46aa-a80a-f948c1723955", + AnswerImageUrl: "side-window-damage-right-all.svg", + }, + ], + listRadioHorizontalSubText: [ + { + Name: "List-Card-RHst", + Text: "List Card RHst", + SubText: "With Subtext", + ImageId: "53343ce4-5b6a-46aa-a80a-f948c1723955", + AnswerImageUrl: "side-window-damage-right-all.svg", + }, + ], + listRadioHorizontal: [ + { + Name: "List-Card-RH", + Text: "List Card RH", + ImageId: "53343ce4-5b6a-46aa-a80a-f948c1723955", + AnswerImageUrl: "side-window-damage-right-all.svg", + }, + ], + listCardGroup: [ + { + Name: "Side-Window-1", + Text: "Side Window", + SubText: "With Subtext", + ImageId: "53343ce4-5b6a-46aa-a80a-f948c1723955", + AnswerImageUrl: "side-window-damage-right-all.svg", + }, + { + Name: "Side-Window-2", + Text: "Side Window", + SubText: "With Subtext that is more than one line", + ImageId: "53343ce4-5b6a-46aa-a80a-f948c1723955", + AnswerImageUrl: "side-window-damage-right-all.svg", + }, + { + Name: "Side-Window-3", + Text: "Side Window", + ImageId: "53343ce4-5b6a-46aa-a80a-f948c1723955", + AnswerImageUrl: "side-window-damage-right-all.svg", + }, + ], }; }, }; diff --git a/src/layouts/form-test/form-test.vue b/src/layouts/form-test/form-test.vue index 33a7e6a70..d56b764b3 100644 --- a/src/layouts/form-test/form-test.vue +++ b/src/layouts/form-test/form-test.vue @@ -1,119 +1,126 @@ diff --git a/src/layouts/vehicle-damage/vehicle-damage.spec.js b/src/layouts/vehicle-damage/vehicle-damage.spec.js index 02a50023c..81c7c8b7a 100644 --- a/src/layouts/vehicle-damage/vehicle-damage.spec.js +++ b/src/layouts/vehicle-damage/vehicle-damage.spec.js @@ -26,24 +26,32 @@ jest.mock("@/helpers/cms-content-helper", () => ({ jest.mock("@/store", () => ({ getters: { vehicle: { - carId: "C00000000" - } - } + carId: "C00000000", + }, + }, })); describe("vehicle-damage.vue", () => { test("Page header is initailized with api data", async (done) => { - //Arrange const pageHeaderWidgetHeaderText = "Select Damage"; - const { wrapper, apiPromise } = setupMocks({ pageHeaderWidgetHeaderText: pageHeaderWidgetHeaderText }); + const { wrapper, apiPromise } = setupMocks({ + pageHeaderWidgetHeaderText: pageHeaderWidgetHeaderText, + }); //Act - vehicleDamage.beforeRouteEnter.call(wrapper.vm, { query: { fmgPage: "vehicle-damage" } }, undefined, (c) => c(wrapper.vm)); + vehicleDamage.beforeRouteEnter.call( + wrapper.vm, + { query: { fmgPage: "vehicle-damage" } }, + undefined, + (c) => c(wrapper.vm) + ); //Assert apiPromise.finally(() => { - expect(funnelSubHeader.methods.initializeComponent).toHaveBeenCalledWith(pageHeaderWidgetHeaderText); + expect(funnelSubHeader.methods.initializeComponent).toHaveBeenCalledWith( + pageHeaderWidgetHeaderText + ); done(); }); }); @@ -51,20 +59,28 @@ describe("vehicle-damage.vue", () => { describe("vehicle-damage.vue", () => { test("Page logo image is initailized with api data", async (done) => { - //Arrange const SiteHeaderWidget = { LogoImage: "https://digitalconsumercms-dev.safelite.com/images/default-source/default-album/safelite-logo.svg?sfvrsn=45e7ed06_3", - } - const { wrapper, apiPromise } = setupMocks({ SiteHeaderWidget: SiteHeaderWidget }); + }; + const { wrapper, apiPromise } = setupMocks({ + SiteHeaderWidget: SiteHeaderWidget, + }); //Act - vehicleDamage.beforeRouteEnter.call(wrapper.vm, { query: { fmgPage: "vehicle-damage" } }, undefined, (c) => c(wrapper.vm)); + vehicleDamage.beforeRouteEnter.call( + wrapper.vm, + { query: { fmgPage: "vehicle-damage" } }, + undefined, + (c) => c(wrapper.vm) + ); //Assert apiPromise.finally(() => { - expect(funnelHeader.methods.initializeComponent).toHaveBeenCalledWith(SiteHeaderWidget); + expect(funnelHeader.methods.initializeComponent).toHaveBeenCalledWith( + SiteHeaderWidget + ); done(); }); }); @@ -72,20 +88,28 @@ describe("vehicle-damage.vue", () => { describe("vehicle-damage.vue", () => { test("Vehicle image is initailized with api data", async (done) => { - //Arrange const VehicleBannerWidget = { GenericVehicleImage: "https://digitalconsumercms-dev.safelite.com/images/default-source/default-album/blurred-image.jpg?sfvrsn=a6ce3034_3", - } - const { wrapper, apiPromise } = setupMocks({ VehicleBannerWidget: VehicleBannerWidget }); + }; + const { wrapper, apiPromise } = setupMocks({ + VehicleBannerWidget: VehicleBannerWidget, + }); //Act - vehicleDamage.beforeRouteEnter.call(wrapper.vm, { query: { fmgPage: "vehicle-damage" } }, undefined, (c) => c(wrapper.vm)); + vehicleDamage.beforeRouteEnter.call( + wrapper.vm, + { query: { fmgPage: "vehicle-damage" } }, + undefined, + (c) => c(wrapper.vm) + ); //Assert apiPromise.finally(() => { - expect(vehicleBanner.methods.initializeComponent).toHaveBeenCalledWith(VehicleBannerWidget); + expect(vehicleBanner.methods.initializeComponent).toHaveBeenCalledWith( + VehicleBannerWidget + ); done(); }); }); @@ -93,12 +117,16 @@ describe("vehicle-damage.vue", () => { describe("vehicle-damage.vue", () => { test("CarId set, arePagePrerequisitesValid should be true ", async () => { - //Arrange const { wrapper } = setupMocks({}); //Act - vehicleDamage.beforeRouteEnter.call(wrapper.vm, { query: { fmgPage: "vehicle-damage" } }, undefined, (c) => c(wrapper.vm)); + vehicleDamage.beforeRouteEnter.call( + wrapper.vm, + { query: { fmgPage: "vehicle-damage" } }, + undefined, + (c) => c(wrapper.vm) + ); let arePagePrerequisitesValid = wrapper.vm.arePagePrerequisitesValid(); await nextTick(); @@ -112,27 +140,26 @@ function setupMocks({ pageHeaderWidgetHeaderText = {}, mountOptionsMockData = {}, }) { - //Mock api responses baseMixin.methods.dispatchNonBlockingStoreAction = jest.fn(); baseMixin.methods.dispatchNonBlockingStoreAction.mockImplementation(() => { - return Promise.resolve({ data: ['Front Window', 'Back Window', 'Side Window'] }); + return Promise.resolve({ + data: ["Front Window", "Back Window", "Side Window"], + }); }); const apiResponses = { cmsContent: { FunnelSubHeaderWidget: pageHeaderWidgetHeaderText, - VehicleBannerWidget: - { + VehicleBannerWidget: { GenericVehicleImage: "https://digitalconsumercms-dev.safelite.com/images/default-source/default-album/blurred-image.jpg?sfvrsn=a6ce3034_3", }, - FunnelHeaderWidget: - { + FunnelHeaderWidget: { LogoImage: "https://digitalconsumercms-dev.safelite.com/images/default-source/default-album/safelite-logo.svg?sfvrsn=45e7ed06_3", }, }, - damageOptions: ['Front Window', 'Back Window', 'Side Window'], + damageOptions: ["Front Window", "Back Window", "Side Window"], }; const apiPromise = Promise.resolve(apiResponses); @@ -157,13 +184,18 @@ function setupMocks({ const wrapper = shallowMount(vehicleDamage, mountOptions); const funnelHeaderWrapper = wrapper.findComponent({ name: "funnelHeader" }); - funnelHeaderWrapper.vm.initializeComponent = funnelHeader.methods.initializeComponent; + funnelHeaderWrapper.vm.initializeComponent = + funnelHeader.methods.initializeComponent; const vehicleBannerWrapper = wrapper.findComponent({ name: "vehicleBanner" }); - vehicleBannerWrapper.vm.initializeComponent = vehicleBanner.methods.initializeComponent; + vehicleBannerWrapper.vm.initializeComponent = + vehicleBanner.methods.initializeComponent; - const funnelSubHeaderWrapper = wrapper.findComponent({ name: "funnelSubHeader" }); - funnelSubHeaderWrapper.vm.initializeComponent = funnelSubHeader.methods.initializeComponent; + const funnelSubHeaderWrapper = wrapper.findComponent({ + name: "funnelSubHeader", + }); + funnelSubHeaderWrapper.vm.initializeComponent = + funnelSubHeader.methods.initializeComponent; return { wrapper, apiPromise }; -} \ No newline at end of file +} diff --git a/src/layouts/vehicle-make/make-question/make-question.spec.js b/src/layouts/vehicle-make/make-question/make-question.spec.js index 6a811459f..469be6d24 100644 --- a/src/layouts/vehicle-make/make-question/make-question.spec.js +++ b/src/layouts/vehicle-make/make-question/make-question.spec.js @@ -2,11 +2,16 @@ import makeQuestion from "@/layouts/vehicle-make/make-question/make-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}); +jest.mock( + "@/store", + () => { + return {}; + }, + { virtual: true } +); describe("make-question.vue", () => { test("Selected make is emitted upon selection.", async () => { - //Arrange const { wrapper } = setupMocks({ modelValueProp: "honda" }); const makeToSelect = "ford"; @@ -16,51 +21,65 @@ describe("make-question.vue", () => { await wrapper.vm.$nextTick(); //Assert - expect(wrapper.emitted()["update:modelValue"][0]).toEqual([{selectedMake: "ford"}]); + expect(wrapper.emitted()["update:modelValue"][0]).toEqual([ + { selectedMake: "ford" }, + ]); }); }); describe("make-question.vue", () => { test("CMS question text is used as radio question text.", async () => { - //Arrange - const { wrapper, cmsContent } = setupMocks({ cmsQuestionText: "What make is your vehicle?" }); + const { wrapper, cmsContent } = setupMocks({ + cmsQuestionText: "What make is your vehicle?", + }); //Act makeQuestion.methods.initializeComponent.call(wrapper.vm, cmsContent, null); //Assert - const buttonQuestionComponent = await wrapper.findComponent({ name: "buttonQuestion" }); - expect(buttonQuestionComponent.attributes("questiontext")).toBe("What make is your vehicle?"); + const buttonQuestionComponent = await wrapper.findComponent({ + name: "buttonQuestion", + }); + expect(buttonQuestionComponent.attributes("questiontext")).toBe( + "What make is your vehicle?" + ); }); }); describe("make-question.vue", () => { test("Data from store api are used as radio question answers.", async () => { - //Arrange - const { wrapper, cmsContent } = setupMocks({ dataFromStoreApi: ["honda", "ford", "dodge"] }); + const { wrapper, cmsContent } = setupMocks({ + dataFromStoreApi: ["honda", "ford", "dodge"], + }); //Act const initialData = makeQuestion.methods.loadInitialData.call(wrapper.vm); - makeQuestion.methods.initializeComponent.call(wrapper.vm, cmsContent, initialData); + makeQuestion.methods.initializeComponent.call( + wrapper.vm, + cmsContent, + initialData + ); //Assert - const buttonQuestionComponent = await wrapper.findComponent({ name: "buttonQuestion" }); - expect(buttonQuestionComponent.attributes("answers")).toBe("honda,ford,dodge"); + const buttonQuestionComponent = await wrapper.findComponent({ + name: "buttonQuestion", + }); + expect(buttonQuestionComponent.attributes("answers")).toBe( + "honda,ford,dodge" + ); }); }); - function setupMocks({ modelValueProp = "1900", cmsQuestionText = "CMS text goes here", dataFromStoreApi = [], }) { - //Mock store store.dispatch = jest.fn(() => dataFromStoreApi); - store.getters = { vehicle: {year: 2019} }; + store.getters = { vehicle: { year: 2019 } }; const mountOptions = getMountOptions({ store: { dispatch: store.dispatch, @@ -76,7 +95,7 @@ function setupMocks({ //Mock CMS content const cmsContent = { - QuestionText: cmsQuestionText - }; + QuestionText: cmsQuestionText, + }; return { wrapper, cmsContent }; -} \ No newline at end of file +} diff --git a/src/layouts/vehicle-make/make-question/make-question.vue b/src/layouts/vehicle-make/make-question/make-question.vue index 0276f1a67..2a94deafe 100644 --- a/src/layouts/vehicle-make/make-question/make-question.vue +++ b/src/layouts/vehicle-make/make-question/make-question.vue @@ -1,5 +1,6 @@