diff --git a/src/assets/img/icons/back-forward.svg b/src/assets/img/icons/back-forward.svg new file mode 100644 index 000000000..3835f94cc --- /dev/null +++ b/src/assets/img/icons/back-forward.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/img/icons/close.svg b/src/assets/img/icons/close.svg new file mode 100644 index 000000000..e660dc6b8 --- /dev/null +++ b/src/assets/img/icons/close.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/commonComponents/baseTemplate/baseTemplate.spec.js b/src/commonComponents/baseTemplate/baseTemplate.spec.js deleted file mode 100644 index c308fd2f7..000000000 --- a/src/commonComponents/baseTemplate/baseTemplate.spec.js +++ /dev/null @@ -1,6 +0,0 @@ - -describe("baseTemplate.vue", () => { - it("Is a test", () => { - expect(true).toBe(true); - }); -}); diff --git a/src/commonComponents/baseTemplate/baseTemplate.vue b/src/commonComponents/baseTemplate/baseTemplate.vue deleted file mode 100644 index 0263616b0..000000000 --- a/src/commonComponents/baseTemplate/baseTemplate.vue +++ /dev/null @@ -1,56 +0,0 @@ - - - diff --git a/src/commonComponents/carAttributes/carAttributes.vue b/src/commonComponents/carAttributes/carAttributes.vue deleted file mode 100644 index 0297654ee..000000000 --- a/src/commonComponents/carAttributes/carAttributes.vue +++ /dev/null @@ -1,24 +0,0 @@ - - - diff --git a/src/commonComponents/radioQuestion/radioQuestion.spec.js b/src/commonComponents/radioQuestion/radioQuestion.spec.js new file mode 100644 index 000000000..a9ba7476e --- /dev/null +++ b/src/commonComponents/radioQuestion/radioQuestion.spec.js @@ -0,0 +1,22 @@ +import { shallowMount } from '@vue/test-utils'; +import radioQuestion from './radioQuestion'; + +describe('radioQuestion.vue', () => { + it("Should render the 'questionText' prop value as a span value for the radio question and the 'answer' values should render as text values for radio components.", () => { + // Act + const wrapper = shallowMount(radioQuestion, { + propsData: { + questionText: 'Question Text', + answers: ['2023', '2022', '2021'], + chooseAnswer: function(test){ console.log(test) } + } + }); + + // Assert + expect(wrapper.find('.needed_car_info-text').text()).toEqual('Question Text'); + const radioButtons = wrapper.findAllComponents('[data-test="radio"]'); + expect(radioButtons[0].attributes('text')).toEqual('2023'); + expect(radioButtons[2].attributes('text')).toEqual('2021'); + expect(typeof wrapper.props().chooseAnswer).toBe('function'); + }) +}) \ No newline at end of file diff --git a/src/commonComponents/radioQuestion/radioQuestion.vue b/src/commonComponents/radioQuestion/radioQuestion.vue new file mode 100644 index 000000000..7e8b16c55 --- /dev/null +++ b/src/commonComponents/radioQuestion/radioQuestion.vue @@ -0,0 +1,27 @@ + + + diff --git a/src/constants/endpoints.js b/src/constants/endpoints.js index 504a55c46..a390db3ec 100644 --- a/src/constants/endpoints.js +++ b/src/constants/endpoints.js @@ -2,6 +2,25 @@ const endpoints = { GetRouteInfoEndpoint: { url: '/content/api/v1/content/RouteInfo', method: 'POST' + }, + GetYears: { + url: '/vehicle/api/v1/vehicle/years', + method: 'GET' + }, + GetMakes: { + url: '/vehicle/api/v1/vehicle/Makes', + method: 'POST' + }, + GetModels: { + url: '/vehicle/api/v1/vehicle/Models', + method: 'POST' + }, + GetStyles: { + url: '/vehicle/api/v1/vehicle/Styles', + method: 'POST' + }, + GetPageData: { + method: 'GET' } } diff --git a/src/constants/storeActions.js b/src/constants/storeActions.js index e358e4dab..5ef5a3157 100644 --- a/src/constants/storeActions.js +++ b/src/constants/storeActions.js @@ -1,5 +1,7 @@ const storeActions = { GET_ROUTE_INFO_ACTION: "getRouteInfo", + GET_YEARS: 'getYears', + GET_PAGE_DATA: 'getMockPageData', } export { storeActions } \ No newline at end of file diff --git a/src/global-methods.js b/src/global-methods.js index 824a87266..0b33cf613 100644 --- a/src/global-methods.js +++ b/src/global-methods.js @@ -11,7 +11,7 @@ export default { axios({ method: method, - url: `${apiGatewayUrl}${endpoint}`, + url: apiGatewayUrl + endpoint, data: payloadAndAnalyticsData, crossDomain: true, responseType: {}, @@ -29,4 +29,30 @@ export default { ); }); }, + + + /* istanbul ignore next */ + callMockHttpClient({ method, endpoint}) { + // For Mock use only! + return new Promise((resolve, reject) => { + + axios({ + method: method, + url: endpoint, + crossDomain: true, + responseType: {}, + }).then((response) => { + + if (response.status == httpStatusCodes.OK) { + resolve(response); + } else { + reject(response); + } + }, + (error) => { + return reject(error.response); + } + ); + }); + } }; diff --git a/src/global-methods.spec.js b/src/global-methods.spec.js new file mode 100644 index 000000000..6885a23e0 --- /dev/null +++ b/src/global-methods.spec.js @@ -0,0 +1,73 @@ +import globalMethods from "@/global-methods"; +import axios from 'axios'; + +//Mock external dependencies +jest.mock('axios'); + +it("Global Methods - Call Http Client - Should Resolve Promise", () => { + //Arrange + const endpoint = 'https://mock.safelite.com'; + const httpArgs = setupMocksForHttpClient({ endpoint: endpoint }); + + //Act + globalMethods.callHttpClient(httpArgs) + .then((response) => { + + //Assert + expect(axios.mock.calls[0][0].url).toContain(endpoint); + expect(response.data.message).toContain('Success'); + expect(response.status).toEqual(200); + }); +}); + +it("Global Methods - Call Http Client - Should Reject Promise", () => { + //Arrange + const endpoint = 'https://mock.safelite.com'; + const httpArgs = setupMocksForHttpClient({ endpoint: endpoint, isError: true }); + + //Act + globalMethods.callHttpClient(httpArgs) + .catch((err) => { + //Assert + expect(axios.mock.calls[0][0].url).toContain(endpoint); + expect(err.data.message).toContain('Error'); + expect(err.status).toEqual(500); + }); +}); + +function setupMocksForHttpClient({ endpoint = null, isError = false, additionalData = null }) { + + //Clear node module + axios.mockClear(); + + // Success Response + const response = { + status: 200, + data: { + message: 'Success', + additionalData: additionalData + } + }; + + // Error Response + const error = { + response: { + status: 500, + data: { + message: 'Error', + additionalData: additionalData + } + } + } + + // Error interceptor on Axios returns a different object, so we need to mimic that. + if (isError) { + axios.mockRejectedValue(error); + } else { + axios.mockResolvedValue(response); + } + + return { + endpoint: endpoint + } +} \ No newline at end of file diff --git a/src/helpers/unitTestHelper.js b/src/helpers/unitTestHelper.js new file mode 100644 index 000000000..417b47e43 --- /dev/null +++ b/src/helpers/unitTestHelper.js @@ -0,0 +1,26 @@ +import { storeActions } from "@/constants/storeActions"; + +export function getMountOptions(mockData) { + // Define our mocks to attached to the 'global' object for Vue/Jest. + const mocks = {}; + + mocks.dispatchNonBlockingStoreAction = jest.fn(); + mocks.dispatchNonBlockingStoreAction.mockImplementation((actionName) => { + + let actionFilterResult = mockData.actionList.filter(x => x.actionName == actionName); + + if (actionFilterResult.length > 0 && actionFilterResult.length === 1) { + + return Promise.resolve({ + data: actionFilterResult[0].data + }); + } + }); + // Mock store actions from js file + mocks.storeActions = storeActions; + const global = { + mocks: mocks + }; + + return { global } +} \ No newline at end of file diff --git a/src/layouts/componentTest/componentTest.vue b/src/layouts/componentTest/componentTest.vue index c0a8f9b93..ab1d6fd23 100644 --- a/src/layouts/componentTest/componentTest.vue +++ b/src/layouts/componentTest/componentTest.vue @@ -1,55 +1,110 @@ -