diff --git a/src/layouts/contact-details/contact-details.spec.js b/src/layouts/contact-details/contact-details.spec.js index 8a4d4d7b..b56a929b 100644 --- a/src/layouts/contact-details/contact-details.spec.js +++ b/src/layouts/contact-details/contact-details.spec.js @@ -10,11 +10,72 @@ import { getRandomString, getRandomInt, getRandomBoolean } from '@/helpers/data- import navigationScenarios from '@/router/router-constants/navigation-scenarios.js'; import { useMainStore } from '@/store/index.js'; +/** @ignore */ +function setupMocks({ + storeData, + props, + isShallowMount = true, + querySelectorFunction, + geocoderResult = ['1234 Test Street'] +}) { + const mountOptions = getMountOptions({ + router: { + navigate: jest.fn(), + navigateWithSpinner: jest.fn() + }, + loadScript: jest.fn().mockResolvedValue() + }); + + if (storeData) mountOptions.global.plugins = [createTestingPinia({ + initialState: { + main: storeData + } + })]; + + window.google = { + maps: { + event: { + addListener: jest + .fn() + .mockImplementation((element, eventName, callbackFunction) => { + /** @ignore */ + function interceptedCallbackFunction(e) { + callbackFunction(e.detail); + } + // selectedPlace = "Woogly"; + element.addEventListener(eventName, interceptedCallbackFunction); + }), + removeListener: jest.fn(), + clearInstanceListeners: jest.fn() + }, + places: { + Autocomplete: jest.fn().mockImplementation((el) => el), + AutocompleteService: jest.fn().mockImplementation(() => { + return { + getPlacePredictions: (request, callback) => { + // Throwing an error here guarantees that the function that calls it finishes + throw new Error(); + } + }; + }), + PlacesService: jest.fn().mockImplementation(() => {}), + AutocompleteSessionToken: jest.fn().mockImplementation(() => {}) + } + } + }; + + if (props) mountOptions.propsData = props; + + const wrapper = shallowMount(contactDetails, mountOptions); + + return { wrapper }; +} + describe('contactDetails.vue', () => { describe('Rendering', () => { test('Should render site header', () => { // Arrange - const wrapper = shallowMount(contactDetails, getMountOptions()); + const { wrapper } = setupMocks({}); // Act const siteHeader = wrapper.findComponent({ ref: 'siteHeader' }); @@ -24,7 +85,7 @@ describe('contactDetails.vue', () => { }); test('Should render sub title', () => { // Arrange - const wrapper = shallowMount(contactDetails, getMountOptions()); + const { wrapper } = setupMocks({}); // Act const siteSubHeader = wrapper.findComponent({ ref: 'siteSubHeader' }); @@ -34,7 +95,7 @@ describe('contactDetails.vue', () => { }); test('Should render appointment information alert', () => { // Arrange - const wrapper = shallowMount(contactDetails, getMountOptions()); + const { wrapper } = setupMocks({}); // Act const appointmentInformationAlert = wrapper.findComponent({ ref: 'appointmentInformationAlert' }); @@ -44,8 +105,6 @@ describe('contactDetails.vue', () => { }); test('Should render same as policy address question subcomponent if service zip is same as customer zip', async () => { // Arrange - const mountOptions = getMountOptions(); - const customerStreetAddress = getRandomString(10, 50); const customerStreetAddress2 = getRandomString(0, 50); const customerCity = getRandomString(4, 20); @@ -55,7 +114,7 @@ describe('contactDetails.vue', () => { const serviceCity = getRandomString(4, 20); const serviceState = getRandomString(2, 2); const zipCode = getRandomInt(10000, 99999).toString(); - const mainInitialState = { + const storeData = { order: { customer: { address: { @@ -75,12 +134,7 @@ describe('contactDetails.vue', () => { } } }; - mountOptions.global.plugins = [createTestingPinia({ - initialState: { - main: mainInitialState - } - })]; - const wrapper = shallowMount(contactDetails, mountOptions); + const { wrapper } = setupMocks({ storeData }); await wrapper.vm.$nextTick(); @@ -92,8 +146,6 @@ describe('contactDetails.vue', () => { }); test('Should not render same as policy address question subcomponent if service zip is different from customer zip', () => { // Arrange - const mountOptions = getMountOptions(); - const firstName = getRandomString(4, 15); const lastName = getRandomString(4, 15); const emailAddress = getRandomString(10, 20); @@ -101,7 +153,7 @@ describe('contactDetails.vue', () => { const testZipCode = getRandomInt(10000, 99999); const customerZipCode = testZipCode.toString(); const serviceZipCode = (testZipCode + 1).toString(); - const mainInitialState = { + const storeData = { order: { customer: { firstName, @@ -119,12 +171,7 @@ describe('contactDetails.vue', () => { } } }; - mountOptions.global.plugins = [createTestingPinia({ - initialState: { - main: mainInitialState - } - })]; - const wrapper = shallowMount(contactDetails, mountOptions); + const { wrapper } = setupMocks({ storeData }); // Act const sameAsPolicyAddressQuestion = wrapper.findComponent({ ref: 'sameAsPolicyAddressQuestion' }); @@ -134,7 +181,7 @@ describe('contactDetails.vue', () => { }); test('Should render address question subcomponent', () => { // Arrange - const wrapper = shallowMount(contactDetails, getMountOptions()); + const { wrapper } = setupMocks({}); // Act const addressQuestion = wrapper.findComponent({ ref: 'addressQuestion' }); @@ -144,7 +191,7 @@ describe('contactDetails.vue', () => { }); test('Should render apartment question subcomponent', () => { // Arrange - const wrapper = shallowMount(contactDetails, getMountOptions()); + const { wrapper } = setupMocks({}); // Act const address2Question = wrapper.findComponent({ ref: 'address2Question' }); @@ -154,7 +201,7 @@ describe('contactDetails.vue', () => { }); test('Should render city question subcomponent', () => { // Arrange - const wrapper = shallowMount(contactDetails, getMountOptions()); + const { wrapper } = setupMocks({}); // Act const cityQuestion = wrapper.findComponent({ ref: 'cityQuestion' }); @@ -164,7 +211,7 @@ describe('contactDetails.vue', () => { }); test('Should render state question subcomponent', () => { // Arrange - const wrapper = shallowMount(contactDetails, getMountOptions()); + const { wrapper } = setupMocks({}); // Act const stateQuestion = wrapper.findComponent({ ref: 'stateQuestion' }); @@ -174,7 +221,7 @@ describe('contactDetails.vue', () => { }); test('Should render zip code question subcomponent', () => { // Arrange - const wrapper = shallowMount(contactDetails, getMountOptions()); + const { wrapper } = setupMocks({}); // Act const zipCodeQuestion = wrapper.findComponent({ ref: 'zipCodeQuestion' }); @@ -184,7 +231,7 @@ describe('contactDetails.vue', () => { }); test('Should render change zip code alert', () => { // Arrange - const wrapper = shallowMount(contactDetails, getMountOptions()); + const { wrapper } = setupMocks({}); // Act const changeZipCodeAlert = wrapper.findComponent({ ref: 'changeZipCodeAlert' }); @@ -194,7 +241,7 @@ describe('contactDetails.vue', () => { }); test('Should render vehicle protected question subcomponent', () => { // Arrange - const wrapper = shallowMount(contactDetails, getMountOptions()); + const { wrapper } = setupMocks({}); // Act const vehicleProtectedQuestion = wrapper.findComponent({ ref: 'vehicleProtectedQuestion' }); @@ -204,7 +251,7 @@ describe('contactDetails.vue', () => { }); test('Should render technician notes textarea question subcomponent', () => { // Arrange - const wrapper = shallowMount(contactDetails, getMountOptions()); + const { wrapper } = setupMocks({}); // Act const notesQuestion = wrapper.findComponent({ ref: 'notesQuestion' }); @@ -214,7 +261,7 @@ describe('contactDetails.vue', () => { }); test('Should render clearance text subcomponent', () => { // Arrange - const wrapper = shallowMount(contactDetails, getMountOptions()); + const { wrapper } = setupMocks({}); // Act const clearanceText = wrapper.findComponent({ ref: 'clearanceText' }); @@ -224,7 +271,7 @@ describe('contactDetails.vue', () => { }); test('Should render site footer', () => { // Arrange - const wrapper = shallowMount(contactDetails, getMountOptions()); + const { wrapper } = setupMocks({}); // Act const footer = wrapper.findComponent({ ref: 'siteFooter' }); @@ -234,8 +281,6 @@ describe('contactDetails.vue', () => { }); test('Mocked store yields expected data', () => { // Arrange - const mountOptions = getMountOptions(); - const address = getRandomString(10, 50); const address2 = getRandomString(0, 50); const city = getRandomString(4, 20); @@ -243,7 +288,7 @@ describe('contactDetails.vue', () => { const zipCode = getRandomInt(10000, 99999).toString(); const notesForTechnician = getRandomString(1, 100); const isVehicleProtected = getRandomBoolean(); - const mainInitialState = { + const storeData = { order: { serviceLocation: { address, @@ -258,13 +303,8 @@ describe('contactDetails.vue', () => { } } }; - mountOptions.global.plugins = [createTestingPinia({ - initialState: { - main: mainInitialState - } - })]; - const wrapper = shallowMount(contactDetails, mountOptions); + const { wrapper } = setupMocks({ storeData }); // Assert expect(wrapper.vm.address).toBe(address); @@ -280,11 +320,7 @@ describe('contactDetails.vue', () => { describe('Navigation', () => { test('Back button clicked triggers navigation', () => { // Arrange - const wrapper = shallowMount(contactDetails, getMountOptions({ - router: { - navigateWithSpinner: jest.fn() - } - })); + const { wrapper } = setupMocks({}); wrapper.vm.navigateBack = baseMixin.methods.navigateBack; // Act @@ -295,41 +331,25 @@ describe('contactDetails.vue', () => { expect(wrapper.vm.$router.navigateWithSpinner) .toHaveBeenCalledWith(navigationScenarios.CLICKED_BACK, undefined); }); - test('Forward button clicked triggers appropriate navigation', () => { + test('Forward button clicked triggers appropriate navigation', async () => { // Arrange - const mountOptions = getMountOptions({ - router: { - navigate: jest.fn() - }, - navigationScenarios - }); - const mainInitialState = { + const storeData = { order: { serviceLocation: { IsSafeliteProvider: true } } }; - mountOptions.global.plugins = [createTestingPinia({ - initialState: { - main: mainInitialState - } - })]; - const wrapper = shallowMount(contactDetails, mountOptions); + const { wrapper } = setupMocks({ storeData }); // Act - wrapper.vm.forwardButtonAction(); + await wrapper.vm.forwardButtonAction(); // Assert expect(wrapper.vm.$router.navigate).toHaveBeenCalled(); expect(wrapper.vm.$router.navigate) .toHaveBeenCalledWith(navigationScenarios.CLICKED_FORWARD, undefined); }); - test('Forward button click updates service location info', () => { + test('Forward button click updates service location info', async () => { // Arrange - const mountOptions = getMountOptions({ - router: { - navigate: jest.fn() - } - }); const provider = { address: { city: getRandomString(4, 20), @@ -342,19 +362,14 @@ describe('contactDetails.vue', () => { phoneNumber: getRandomInt(1000000000, 9999999999).toString(), providerNumber: getRandomInt(100000, 999999).toString() } - const mainInitialState = { + const storeData = { order: { serviceLocation: { provider } } }; - mountOptions.global.plugins = [createTestingPinia({ - initialState: { - main: mainInitialState - } - })]; - const wrapper = shallowMount(contactDetails, mountOptions); + const { wrapper } = setupMocks({ storeData }); const address = getRandomString(10, 50); const address2 = getRandomString(0, 50); const city = getRandomString(4, 20); @@ -371,7 +386,7 @@ describe('contactDetails.vue', () => { }); // Act - wrapper.vm.forwardButtonAction(); + await wrapper.vm.forwardButtonAction(); // Assert expect(useMainStore().updateServiceLocation).toHaveBeenCalledWith({ @@ -383,21 +398,16 @@ describe('contactDetails.vue', () => { }); }); - test('Forward button click updates notes for technician', () => { + test('Forward button click updates notes for technician', async () => { // Arrange - const mountOptions = getMountOptions({ - router: { - navigate: jest.fn() - } - }); - const wrapper = shallowMount(contactDetails, mountOptions); + const { wrapper } = setupMocks({}); const notesForTechnician = getRandomString(1, 100); wrapper.setData({ notesForTechnician }); // Act - wrapper.vm.forwardButtonAction(); + await wrapper.vm.forwardButtonAction(); // Assert expect(useMainStore().updateContactInfo).toHaveBeenCalledWith({ diff --git a/src/layouts/contact-details/contact-details.vue b/src/layouts/contact-details/contact-details.vue index 8222f36a..8fff6681 100644 --- a/src/layouts/contact-details/contact-details.vue +++ b/src/layouts/contact-details/contact-details.vue @@ -291,36 +291,41 @@ export default { const acSessionToken = new window.google.maps.places.AutocompleteSessionToken(); const addressValue = `${this.address}, ${this.city}, ${this.state} ${this.zipCode}`; - acService.getPlacePredictions( - { - input: addressValue, - type: ['geocode'], - componentRestrictions: { country: ['us'] }, - sessionToken: acSessionToken - }, - (predictions) => { - if (predictions && predictions.length > 0) { - const firstPrediction = predictions[0]; - if (firstPrediction.place_id) { - placeService.getDetails( - { - placeId: firstPrediction.place_id, - fields: ['address_components'], - sessionToken: acSessionToken - }, - (details) => { - this.fillInAddress(details); - resolve(); - } - ); + try { + acService.getPlacePredictions( + { + input: addressValue, + type: ['geocode'], + componentRestrictions: { country: ['us'] }, + sessionToken: acSessionToken + }, + (predictions) => { + if (predictions && predictions.length > 0) { + const firstPrediction = predictions[0]; + if (firstPrediction.place_id) { + placeService.getDetails( + { + placeId: firstPrediction.place_id, + fields: ['address_components'], + sessionToken: acSessionToken + }, + (details) => { + this.fillInAddress(details); + resolve(); + } + ); + } else { + resolve(); + } } else { resolve(); } - } else { - resolve(); } - } - ); + ); + } catch (error) { + window.console.warn('Error initializing Google Places API services', error); + resolve(); + } }); return autoCompletePromise;