From f200258194c735d17a66a6c286651e0d0a275a86 Mon Sep 17 00:00:00 2001 From: Sneha Date: Thu, 30 Mar 2023 19:04:42 +0530 Subject: [PATCH 1/3] SSR274 UI functionality for Provider Preference page --- .../provider-preference.spec.js | 161 ++++++++++++++++++ .../provider-preference.vue | 24 ++- .../shoppreference-modal.spec.js | 41 +++++ .../shoppreference-modal.vue | 10 +- .../service-location/service-location.vue | 71 ++++++++ src/router/router-constants/issPage-values.js | 1 + .../router-constants/navigation-scenarios.js | 2 + src/router/router-constants/routing-table.js | 13 ++ 8 files changed, 310 insertions(+), 13 deletions(-) create mode 100644 src/layouts/provider-preference/provider-preference.spec.js create mode 100644 src/layouts/provider-preference/shoppreference-modal/shoppreference-modal.spec.js create mode 100644 src/layouts/service-location/service-location.vue diff --git a/src/layouts/provider-preference/provider-preference.spec.js b/src/layouts/provider-preference/provider-preference.spec.js new file mode 100644 index 00000000..c51db987 --- /dev/null +++ b/src/layouts/provider-preference/provider-preference.spec.js @@ -0,0 +1,161 @@ +import { mount } from '@vue/test-utils'; +import { navigationScenarios } from '@/router/router-constants/navigation-scenarios'; +import { issPageValues } from '@/router/router-constants/issPage-values'; +import { queryStrings } from '@/constants/query-strings'; +import { GaActions } from "@/constants/analytics"; +import ProviderPreference from "@/layouts/provider-preference/provider-preference.vue" +import { useMainStore } from '../../store'; +import { createTestingPinia } from '@pinia/testing'; +import { mapStores } from "pinia"; + +const pinia = createTestingPinia(); +useMainStore(pinia); + +const ProviderPreferenceMockData = { + QuestionText: 'Which auto glass shop would you like to work with?', + Answers: [ + { + Name: 'Schedule with Safelite', + Text: 'Schedule with Safelite', + SubText: '', + ImageId: '', + SubWidgetName: '', + }, + { + Name: 'Find another shop', + Text: 'Find another shop', + SubText: '', + ImageId: '', + SubWidgetName: '', + }, + ], + }; + + const siteFooterWidgetMockData = { + ForwardButtonText: 'Continue', + }; + + function setupMocks() { + const mockRoute = { + query: { + issPage: 'provider-preference', + }, + }; + + const mockRouter = { + navigate: jest.fn(), + }; + + const wrapper = mount(ProviderPreference, { + data() { + return { + SelectedshopLocation: null, + }; + }, + global: { + mixins: [ + { + computed: { + ...mapStores(useMainStore), + GaActions() { + return GaActions; + }, + queryStrings() { + return queryStrings; + }, + navigationScenarios() { + return navigationScenarios; + }, + }, + methods: { + getCmsContent: jest.fn((cmsWidgetName, fieldName) => { + if (cmsWidgetName === 'SiteFooterWidget') { + if (fieldName === 'ForwardButtonText') { + return siteFooterWidgetMockData.ForwardButtonText; + } + } + + if (cmsWidgetName === 'ProviderPreference') { + if (fieldName === 'QuestionText') { + return ProviderPreferenceMockData.QuestionText; + } + if (fieldName === 'Answers') { + return ProviderPreferenceMockData.Answers; + } + } + + return ''; + }), + getFooterInfoBoxHeight: jest.fn(() => 80), + getPageNameByQueryString: jest.fn(() => "provider-preference"), + pushEventToGA: jest.fn(), + }, + }, + ], + mocks: { + $route: mockRoute, + $router: mockRouter, + }, + stubs: { + SiteHeader: true, + SiteSubHeader: true, + }, + }, + }); + + return { mockRoute, mockRouter, wrapper }; + } +describe('provider-preference.vue', () => { + test('"Continue" button is disabled when no Shop Location is selected.', () => { + const { wrapper } = setupMocks(); + + const continueButton = wrapper.get('[data-test-id="site-footer-main-button"]'); + expect(continueButton.attributes()['aria-disabled']).toBe('true'); + }); + test('"Continue" button is enabled after a Shop Location is selected.', async () => { + const { wrapper } = setupMocks(); + + const ProviderPreferenceWrapper = wrapper.findComponent({ name: 'provider-preference' }); + // Not using initializeComponent() because it doesn't trigger reactivity in test. + await ProviderPreferenceWrapper.setData({ + questionTextFromCms: ProviderPreferenceMockData.QuestionText, + answersFromCms: ProviderPreferenceMockData.Answers, + SelectedshopLocation:"Schedule with Safelite" + }); + + + const continueButton = wrapper.get('[data-test-id="site-footer-main-button"]'); + expect(continueButton.attributes()['aria-disabled']).toBe('false'); + }); + test('Select "Schedule with Safelite" then click "Continue". Navigates to "service-location" page.', async () => { + const { mockRoute, mockRouter, wrapper } = setupMocks(); + + const ProviderPreferenceWrapper = wrapper.findComponent({ name: 'provider-preference' }); + // Not using initializeComponent() because it doesn't trigger reactivity in test. + await ProviderPreferenceWrapper.setData({ + questionTextFromCms: ProviderPreferenceMockData.QuestionText, + answersFromCms: ProviderPreferenceMockData.Answers, + SelectedshopLocation:"Schedule with Safelite" + }); + + const continueButton = wrapper.get('[data-test-id="site-footer-main-button"]'); + await continueButton.trigger('click'); + + expect(mockRouter.navigate).toHaveBeenCalledTimes(1); + expect(mockRouter.navigate) + .toHaveBeenCalledWith(navigationScenarios.CLICKED_FORWARD_WITH_SAFELITE, mockRoute); + /** + * To Do: find a way to confirm that Vue Router really routes to the expected page. + * Currently just trust that our custom navigate() method does its job properly. + */ + }); + + test('Click the back button, trigger navigate function from Vue Router with CLICKED_BACK parameter.', async () => { + const { mockRoute, mockRouter, wrapper } = setupMocks(); + + await wrapper.get('[data-test-id="site-footer-back-button"]').trigger('click'); + expect(mockRouter.navigate).toHaveBeenCalledTimes(1); + expect(mockRouter.navigate) + .toHaveBeenCalledWith(navigationScenarios.CLICKED_BACK, mockRoute); + }); + }); diff --git a/src/layouts/provider-preference/provider-preference.vue b/src/layouts/provider-preference/provider-preference.vue index 637f9f4b..82aa5ad5 100644 --- a/src/layouts/provider-preference/provider-preference.vue +++ b/src/layouts/provider-preference/provider-preference.vue @@ -17,11 +17,12 @@ :answers="answersFromCms" buttonTypeString="listButton" isRequired + v-model="SelectedshopLocation" validationRules="questions-required" /> { + it("Should display header text when HeaderText is defined in the CMS", async () => { + // Act + const wrapper = shallowMount(shoppreferenceModal, { + mixins: [mockMixin], + props: { + cmsWidgetName: "test", + }, + attachTo: document.body, + }); + expect(wrapper.html()).toEqual(expect.stringContaining(mockCmsContent["HeaderText"])); + }); + + it("Should display body text when BodyText is defined in the CMS", async () => { + // Act + const wrapper = shallowMount(shoppreferenceModal, { + mixins: [mockMixin], + props: { + cmsWidgetName: "test", + }, + attachTo: document.body, + }); + expect(wrapper.html()).toEqual(expect.stringContaining(mockCmsContent["BodyText"])); + }); +}); + const mockMixin = { + methods: { + getCmsContent: jest.fn((widgetName, cmsFieldName) => { + return mockCmsContent[cmsFieldName]; + }), + }, + }; + + const mockCmsContent = { + HeaderText: "Sample header text here.", + BodyText: "Sample body text here.", + FooterText: "Sample footer text here.", + }; \ No newline at end of file diff --git a/src/layouts/provider-preference/shoppreference-modal/shoppreference-modal.vue b/src/layouts/provider-preference/shoppreference-modal/shoppreference-modal.vue index 5ea1f8d1..0b7c5824 100644 --- a/src/layouts/provider-preference/shoppreference-modal/shoppreference-modal.vue +++ b/src/layouts/provider-preference/shoppreference-modal/shoppreference-modal.vue @@ -18,7 +18,7 @@