diff --git a/package-lock.json b/package-lock.json index 4569f488..de029cb4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -43,6 +43,7 @@ "eslint-plugin-vue": "^9.15.1", "jest": "^27.0.5", "jest-junit": "^13.0.0", + "jest-serializer-vue": "^3.1.0", "jsdoc": "^4.0.2", "jsdom": "^22.1.0", "sass": "^1.32.7", @@ -4413,6 +4414,15 @@ } } }, + "node_modules/@vue/cli-plugin-unit-jest/node_modules/jest-serializer-vue": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/jest-serializer-vue/-/jest-serializer-vue-2.0.2.tgz", + "integrity": "sha512-nK/YIFo6qe3i9Ge+hr3h4PpRehuPPGZFt8LDBdTHYldMb7ZWlkanZS8Ls7D8h6qmQP2lBQVDLP0DKn5bJ9QApQ==", + "dev": true, + "dependencies": { + "pretty": "2.0.0" + } + }, "node_modules/@vue/cli-plugin-vuex": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/@vue/cli-plugin-vuex/-/cli-plugin-vuex-5.0.8.tgz", @@ -12245,9 +12255,9 @@ } }, "node_modules/jest-serializer-vue": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/jest-serializer-vue/-/jest-serializer-vue-2.0.2.tgz", - "integrity": "sha512-nK/YIFo6qe3i9Ge+hr3h4PpRehuPPGZFt8LDBdTHYldMb7ZWlkanZS8Ls7D8h6qmQP2lBQVDLP0DKn5bJ9QApQ==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jest-serializer-vue/-/jest-serializer-vue-3.1.0.tgz", + "integrity": "sha512-vXz9/3IgBbLhsaVANYLG4ROCQd+Wg3qbB6ICofzFL+fbhSFPlqb0/MMGXcueVsjaovdWlYiRaLQLpdi1PTcoRQ==", "dev": true, "dependencies": { "pretty": "2.0.0" diff --git a/package.json b/package.json index dbbcf42e..bae51414 100644 --- a/package.json +++ b/package.json @@ -50,6 +50,7 @@ "eslint-plugin-vue": "^9.15.1", "jest": "^27.0.5", "jest-junit": "^13.0.0", + "jest-serializer-vue": "^3.1.0", "jsdoc": "^4.0.2", "jsdom": "^22.1.0", "sass": "^1.32.7", diff --git a/src/layouts/bailout-page/__snapshots__/bailout-page.spec.js.snap b/src/layouts/bailout-page/__snapshots__/bailout-page.spec.js.snap new file mode 100644 index 00000000..c2066e76 --- /dev/null +++ b/src/layouts/bailout-page/__snapshots__/bailout-page.spec.js.snap @@ -0,0 +1,24 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Bailout page returns the initial data 1`] = ` +Object { + "bailoutPageModel": Object { + "email": "alexander.hamilton45@gmail.com", + "firstName": "Alexander", + "lastName": "Hamilton", + "phoneNumber": "6145550909", + }, + "notSeeingPreferredShop": false, + "rules": Object { + "email": "email-required|email-address-format", + "firstName": "first-name-required", + "lastName": "last-name-required", + "phoneNumber": "phone-number-required|phone-number-format", + }, + "widget": Object { + "defaultSiteHeader": "SiteSubHeaderWidget", + "noTpa": "ContentGroupNoTPAWidget", + "notSeeingPreferredShop": "ContentGroupNotSeeingPreferredShop", + }, +} +`; diff --git a/src/layouts/bailout-page/bailout-page.spec.js b/src/layouts/bailout-page/bailout-page.spec.js index e69de29b..0131cc8f 100644 --- a/src/layouts/bailout-page/bailout-page.spec.js +++ b/src/layouts/bailout-page/bailout-page.spec.js @@ -0,0 +1,487 @@ +// Components +import { shallowMount } from '@vue/test-utils'; +import { createTestingPinia } from '@pinia/testing'; +import bailoutPage from '@/layouts/bailout-page/bailout-page.vue'; + +// Supporting Files +import { getMountOptions } from '@/helpers/unit-test-helper.js'; +import routerParams from '@/router/router-constants/router-params'; +import { useMainStore } from '@/store'; +import { fetchCmsContentForPage } from '@/helpers/cms-content-helper'; +import settleAllPromises from '@/helpers/layout-helper.js'; + +// Mock fetchCmsContentForPage +jest.mock('@/helpers/cms-content-helper', () => ({ + fetchCmsContentForPage: jest.fn(), + doesCopyContainRouterLink: jest.fn() +})); + +// Mock our module for promises. +jest.mock('@/helpers/layout-helper.js', () => jest.fn()); + +function getMountedComponent(mainInitialState = {}, initialData = {}, methodToRunAfterInitializingStore = () => {}) { + const mountOptions = getMountOptions({ + router: { + navigate: jest.fn() + } + }); + + const testingPinia = createTestingPinia({ + initialState: { + main: mainInitialState + } + }); + useMainStore(testingPinia); + methodToRunAfterInitializingStore(); + + mountOptions.global.plugins = [testingPinia]; + mountOptions.data = () => (initialData); + + const apiResponses = { + cmsContent: {} + }; + + settleAllPromises.mockImplementation(() => apiResponses); + fetchCmsContentForPage.mockImplementation(() => Promise.resolve()); + + const wrapper = shallowMount(bailoutPage, mountOptions); + wrapper.vm.getCmsContent = jest.fn().mockImplementation(() => ''); + wrapper.vm.setCmsContent = jest.fn(); + return { wrapper }; +} + +describe('Bailout page', () => { + test('returns the initial data', () => { + // Arrange + const firstName = 'Alexander'; + const lastName = 'Hamilton'; + const phoneNumber = '6145550909'; + const emailAddress = 'alexander.hamilton45@gmail.com'; + const mainInitialState = { + order: { + customer: { + firstName, + lastName, + phoneNumber, + emailAddress + } + } + }; + const { wrapper } = getMountedComponent(mainInitialState); + + // Assert + expect(wrapper.vm.$data).toMatchSnapshot(); + }); + describe('renders', () => { + test('site header', () => { + // Arrange + const wrapper = shallowMount(bailoutPage, getMountOptions()); + + // Act + const siteHeader = wrapper.findComponent({ ref: 'siteHeader' }); + + // Assert + expect(siteHeader.exists()).toBeTruthy(); + }); + test('sub header', () => { + // Arrange + const wrapper = shallowMount(bailoutPage, getMountOptions()); + + // Act + const siteSubHeader = wrapper.findComponent({ ref: 'siteSubHeader' }); + + // Assert + expect(siteSubHeader.exists()).toBeTruthy(); + }); + test('first name question', () => { + // Arrange + const wrapper = shallowMount(bailoutPage, getMountOptions()); + + // Act + const firstName = wrapper.findComponent({ ref: 'firstName' }); + + // Assert + expect(firstName.exists()).toBeTruthy(); + }); + test('last name question', () => { + // Arrange + const wrapper = shallowMount(bailoutPage, getMountOptions()); + + // Act + const lastName = wrapper.findComponent({ ref: 'lastName' }); + + // Assert + expect(lastName.exists()).toBeTruthy(); + }); + test('phone number name question', () => { + // Arrange + const wrapper = shallowMount(bailoutPage, getMountOptions()); + + // Act + const phoneNumber = wrapper.findComponent({ ref: 'phoneNumber' }); + + // Assert + expect(phoneNumber.exists()).toBeTruthy(); + }); + test('email question', () => { + // Arrange + const wrapper = shallowMount(bailoutPage, getMountOptions()); + + // Act + const email = wrapper.findComponent({ ref: 'emailAddress' }); + + // Assert + expect(email.exists()).toBeTruthy(); + }); + test('footer', () => { + // Arrange + const wrapper = shallowMount(bailoutPage, getMountOptions()); + + // Act + const siteFooter = wrapper.findComponent({ ref: 'siteFooter' }); + + // Assert + expect(siteFooter.exists()).toBeTruthy(); + }); + }); + describe('computed', () => { + describe('subHeaderCmsWidgetName', () => { + test.each([true, false])( + 'returns noTpa widget name when tpa flow not enabled', + (notSeeingPreferredShop) => { + // Arrange + const mainInitialState = { + issConfig: { enableTPAFlow: false } + }; + const initialData = { notSeeingPreferredShop }; + const { wrapper } = getMountedComponent(mainInitialState, initialData); + const expected = 'ContentGroupNoTPAWidget'; + + // Act + const name = wrapper.vm.subHeaderCmsWidgetName; + + // Assert + expect(name).toBe(expected); + } + ); + test('returns notSeeingPreferredShop widget name when tpa enabled and notSeeingPreferredShop true', () => { + // Arrange + const mainInitialState = { + issConfig: { enableTPAFlow: true } + }; + const initialData = { notSeeingPreferredShop: true }; + const { wrapper } = getMountedComponent(mainInitialState, initialData); + const expected = 'ContentGroupNotSeeingPreferredShop'; + + // Act + const name = wrapper.vm.subHeaderCmsWidgetName; + + // Assert + expect(name).toBe(expected); + }); + test('returns default widget name when tpa enabled and notSeeingPreferredShop false', () => { + // Arrange + const mainInitialState = { + issConfig: { enableTPAFlow: true } + }; + const initialData = { notSeeingPreferredShop: false }; + const { wrapper } = getMountedComponent(mainInitialState, initialData); + const expected = 'SiteSubHeaderWidget'; + + // Act + const name = wrapper.vm.subHeaderCmsWidgetName; + + // Assert + expect(name).toBe(expected); + }); + }); + describe('subHeaderContentProperty', () => { + test('returns "SubHeaderText" when tpa flow enabled and not seeing preferred shop flag false', () => { + // Arrange + const mainInitialState = { + issConfig: { enableTPAFlow: true } + }; + const initialData = { notSeeingPreferredShop: false }; + const { wrapper } = getMountedComponent(mainInitialState, initialData); + const expected = 'SubHeaderText'; + + // Act + const name = wrapper.vm.subHeaderContentProperty; + + // Assert + expect(name).toBe(expected); + }); + test.each([true, false])( + 'returns "HeaderText" when tpa flow not enabled', + (notSeeingPreferredShop) => { + // Arrange + const mainInitialState = { + issConfig: { enableTPAFlow: false } + }; + const initialData = { notSeeingPreferredShop }; + const { wrapper } = getMountedComponent(mainInitialState, initialData); + const expected = 'HeaderText'; + + // Act + const name = wrapper.vm.subHeaderContentProperty; + + // Assert + expect(name).toBe(expected); + } + ); + test('returns "HeaderText" when tpa flow enabled and not seeing preferred shop flag true', () => { + // Arrange + const mainInitialState = { + issConfig: { enableTPAFlow: false } + }; + const initialData = { notSeeingPreferredShop: true }; + const { wrapper } = getMountedComponent(mainInitialState, initialData); + const expected = 'HeaderText'; + + // Act + const name = wrapper.vm.subHeaderContentProperty; + + // Assert + expect(name).toBe(expected); + }); + }); + describe('subContentProperty', () => { + test('returns "SecondaryText" when tpa flow enabled and not seeing preferred shop flag false', () => { + // Arrange + const mainInitialState = { + issConfig: { enableTPAFlow: true } + }; + const initialData = { notSeeingPreferredShop: false }; + const { wrapper } = getMountedComponent(mainInitialState, initialData); + const expected = 'SecondaryText'; + + // Act + const name = wrapper.vm.subContentProperty; + + // Assert + expect(name).toBe(expected); + }); + test.each([true, false])( + 'returns "BodyText" when tpa flow not enabled', + (notSeeingPreferredShop) => { + // Arrange + const mainInitialState = { + issConfig: { enableTPAFlow: false } + }; + const initialData = { notSeeingPreferredShop }; + const { wrapper } = getMountedComponent(mainInitialState, initialData); + const expected = 'BodyText'; + + // Act + const name = wrapper.vm.subContentProperty; + + // Assert + expect(name).toBe(expected); + } + ); + test('returns "BodyText" when tpa flow enabled and not seeing preferred shop flag true', () => { + // Arrange + const mainInitialState = { + issConfig: { enableTPAFlow: true } + }; + const initialData = { notSeeingPreferredShop: true }; + const { wrapper } = getMountedComponent(mainInitialState, initialData); + const expected = 'BodyText'; + + // Act + const name = wrapper.vm.subContentProperty; + + // Assert + expect(name).toBe(expected); + }); + }); + describe('stripRteStyle', () => { + test('returns false when tpa flow enabled and not seeing preferred shop flag false', () => { + // Arrange + const mainInitialState = { + issConfig: { enableTPAFlow: true } + }; + const initialData = { notSeeingPreferredShop: false }; + const { wrapper } = getMountedComponent(mainInitialState, initialData); + const expected = false; + + // Act + const flag = wrapper.vm.stripRteStyle; + + // Assert + expect(flag).toBe(expected); + }); + test('returns true when tpa flow not enabled and not seeing preferred shop flag false', () => { + // Arrange + const mainInitialState = { + issConfig: { enableTPAFlow: false } + }; + const initialData = { notSeeingPreferredShop: false }; + const { wrapper } = getMountedComponent(mainInitialState, initialData); + const expected = true; + + // Act + const flag = wrapper.vm.stripRteStyle; + + // Assert + expect(flag).toBe(expected); + }); + test('returns true when tpa flow enabled and not seeing preferred shop flag true', () => { + // Arrange + const mainInitialState = { + issConfig: { enableTPAFlow: true } + }; + const initialData = { notSeeingPreferredShop: true }; + const { wrapper } = getMountedComponent(mainInitialState, initialData); + const expected = true; + + // Act + const flag = wrapper.vm.stripRteStyle; + + // Assert + expect(flag).toBe(expected); + }); + }); + describe('isTpaEnabled', () => { + test.each([true, false])( + 'matches enableTPAFlow in store', + (enableTPAFlow) => { + // Arrange + const mainInitialState = { + issConfig: { enableTPAFlow } + }; + const { wrapper } = getMountedComponent(mainInitialState); + + // Act + const flag = wrapper.vm.isTpaEnabled; + + // Assert + expect(flag).toBe(enableTPAFlow); + } + ); + }); + }); + describe('method', () => { + describe('backButtonAction', () => { + test('should navigate with CLICKED_BACK_PREVIOUS scenario', () => { + // Arrange + const { wrapper } = getMountedComponent(); + + // Act + wrapper.vm.backButtonAction(); + + // Assert + expect(wrapper.vm.$router.navigate).toHaveBeenCalledWith( + wrapper.vm.navigationScenarios.CLICKED_BACK_PREVIOUS, + wrapper.vm.$route + ); + }); + }); + describe('forwardButtonAction', () => { + test('should navigate to the next route', () => { + // Arrange + const { wrapper } = getMountedComponent(); + + // Act + wrapper.vm.forwardButtonAction(); + + // Assert + expect(wrapper.vm.$router.navigate).toHaveBeenCalledWith( + wrapper.vm.navigationScenarios.CLICKED_FORWARD, + wrapper.vm.$route, + {}, + {}, + wrapper.vm.bailoutPageModel + ); + }); + }); + describe('getBailoutPageModelFromStore', () => { + test('should return expected bailout page model', () => { + // Arrange + const firstName = 'Jake'; + const lastName = 'From State Farm'; + const phoneNumber = '4215558234'; + const emailAddress = 'jake.from.state.farm993@yahoo.com'; + const mainInitialState = { + order: { + customer: { + firstName, + lastName, + phoneNumber, + emailAddress + } + } + }; + const { wrapper } = getMountedComponent(mainInitialState); + + // Act + const pageModel = wrapper.vm.getBailoutPageModelFromStore(); + + // Assert + expect(pageModel).toEqual({ + firstName, + lastName, + phoneNumber, + email: emailAddress + }); + }); + }); + describe('setNotSeeingPreferShop', () => { + test.each([true, false])( + 'updates notSeeingPreferredShop value', + (flag) => { + // Arrange + const { wrapper } = getMountedComponent(); + + // Act + wrapper.vm.setNotSeeingPreferShop(flag); + + // Assert + expect(wrapper.vm.notSeeingPreferredShop).toBe(flag); + } + ); + test('sets notSeeingPreferredShop to true when null is passed', () => { + // Arrange + const { wrapper } = getMountedComponent(); + + // Act + wrapper.vm.setNotSeeingPreferShop(null); + + // Assert + expect(wrapper.vm.notSeeingPreferredShop).toBe(false); + }); + }); + }); + + describe('before entering the route', () => { + test.each([true, false])( + 'sets notSeeingPreferredShop flag based value returned by store method pageData', + async (notSeeingPreferredShop) => { + // Arrange + const page = 'bailout-page'; + const initialStoreState = { + applicationUser: { + pageData: { + [page]: { + [routerParams.NOT_SEEING_PREFERRED_SHOP]: notSeeingPreferredShop, + turtle: 5 + } + } + } + }; + const { wrapper } = getMountedComponent(initialStoreState); + + // Act + await bailoutPage.beforeRouteEnter.call( + wrapper.vm, + { query: { issPage: page } }, + undefined, + (c) => c(wrapper.vm) + ); + + // Assert + expect(wrapper.vm.notSeeingPreferredShop).toBe(notSeeingPreferredShop); + } + ); + }); +}); diff --git a/src/layouts/bailout-page/bailout-page.vue b/src/layouts/bailout-page/bailout-page.vue index 82f1bd09..116ce5a8 100644 --- a/src/layouts/bailout-page/bailout-page.vue +++ b/src/layouts/bailout-page/bailout-page.vue @@ -6,9 +6,11 @@ @invalidSubmit="onInvalidSubmit">
{ vm.setCmsContent(resultMap.cmsContent); + console.log(JSON.stringify(pageData[routerParams.NOT_SEEING_PREFERRED_SHOP])); vm.setNotSeeingPreferShop(pageData[routerParams.NOT_SEEING_PREFERRED_SHOP]); }); }, - setup() { - const mainStore = useMainStore(); - return { mainStore }; - }, data() { return { notSeeingPreferredShop: false, @@ -149,7 +150,7 @@ export default { return !this.isTpaEnabled || this.notSeeingPreferredShop; }, isTpaEnabled() { - return this.mainStore.issConfig.enableTPAFlow; + return useMainStore().issConfig.enableTPAFlow; } }, methods: { @@ -158,9 +159,6 @@ export default { this.$router.navigate(this.navigationScenarios.CLICKED_BACK_PREVIOUS, this.$route); }, forwardButtonAction() { - return this.navigateForward(); - }, - navigateForward() { this.$router.navigate( this.navigationScenarios.CLICKED_FORWARD, this.$route, @@ -171,13 +169,14 @@ export default { }, getBailoutPageModelFromStore() { return { - firstName: this.mainStore.order.customer.firstName, - lastName: this.mainStore.order.customer.lastName, - phoneNumber: this.mainStore.order.customer.phoneNumber, - email: this.mainStore.order.customer.emailAddress + firstName: useMainStore().order.customer.firstName, + lastName: useMainStore().order.customer.lastName, + phoneNumber: useMainStore().order.customer.phoneNumber, + email: useMainStore().order.customer.emailAddress }; }, setNotSeeingPreferShop(value) { + console.log(`set flag: ${value}`); this.notSeeingPreferredShop = value ?? false; } }