diff --git a/.eslintrc.js b/.eslintrc.js index 2f5f8378..c9deb6a3 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -19,10 +19,10 @@ module.exports = { 'vue/v-on-event-hyphenation': ['warn', 'never'], 'object-curly-newline': ['error', { consistent: true }], 'function-paren-newline': ['error', 'never'], - 'operator-linebreak': ['error', 'before'], + 'operator-linebreak': ['error', 'before', { overrides: { '=': 'after' }}], 'implicit-arrow-linebreak': ['off'], 'comma-dangle': ['error', 'never'], - indent: ['error', 4], + indent: ['error', 4, { SwitchCase: 1 }], 'max-len': ['error', { code: 140 }], 'no-plusplus': ['error', { allowForLoopAfterthoughts: true }], 'vue/html-indent': 'off', @@ -30,6 +30,9 @@ module.exports = { singleline: 'never', multiline: 'never' }], + 'jsdoc/check-tag-names': ['error', { + definedTags: ['store', 'endpoint', 'category', 'subcategory', 'remarks'] + }], 'vue/html-self-closing': ['error', { html: { void: 'any', @@ -39,7 +42,8 @@ module.exports = { svg: 'always', math: 'always' }], - 'import/extensions': ['error', 'always', { js: 'ignorePackages' }] + 'import/extensions': ['error', 'always', { js: 'ignorePackages' }], + 'no-param-reassign': ['error', { props: true, ignorePropertyModificationsFor: ['item'] }] }, settings: { 'import/resolver': { diff --git a/src/constants/application-config.js b/src/constants/application-config.js index f83efafa..06fd28b5 100644 --- a/src/constants/application-config.js +++ b/src/constants/application-config.js @@ -3,7 +3,7 @@ * @author T-Wrecks Team * @copyright Safelite */ -const applicationConfig = { +const applicationConfig = Object.freeze({ CURRENT_ENVIRONMENT: process.env.VUE_APP_CURRENT_ENVIRONMENT, // "Localhost", "Dev", "QA", and "Prod" CONSUMER_CF_DISTRO: process.env.VUE_APP_CONSUMER_CF_DISTRO, ANALYTICS_SESSION_TIMEOUT_MINUTES: 30, @@ -17,6 +17,6 @@ const applicationConfig = { GOOGLE_PLACES_API_KEY: process.env.VUE_APP_GOOGLE_PLACES_API_KEY, ISS_DEV_CMS_DOMAIN: 'https://digitalisscms.dev.safelite.io', CASH_PARENT_ACCOUNT_NUMBER: 167132 -}; +}); -export default Object.freeze(applicationConfig); +export default applicationConfig; diff --git a/src/constants/cookie-names.js b/src/constants/cookie-names.js index a9f87a36..df42423f 100644 --- a/src/constants/cookie-names.js +++ b/src/constants/cookie-names.js @@ -6,13 +6,13 @@ import applicationConfig from '@/constants/application-config.js'; * @author T-Wrecks Team * @copyright Safelite */ -const cookieNames = { +const cookieNames = Object.freeze({ ISS_SESSION_INFO: `ISSSessionInfo-${applicationConfig.CURRENT_ENVIRONMENT}`, // Existing Safelite.com cookies DXDEV: 'dxdev', SESSION_ID: 'sid', SESSION_KEY: 'skey' -}; +}); -export default Object.freeze(cookieNames); +export default cookieNames; diff --git a/src/constants/endpoints.js b/src/constants/endpoints.js index 9a612b1e..955ccb08 100644 --- a/src/constants/endpoints.js +++ b/src/constants/endpoints.js @@ -1,4 +1,4 @@ -const endpoints = { +const endpoints = Object.freeze({ GetRouteInfo: { url: (applicationAbbreviation) => `/content/api/v1/content/${applicationAbbreviation}/RouteInfo`, method: 'POST' @@ -130,6 +130,6 @@ const endpoints = { url: '/coverage/api/v1/coverage/register-claim', method: 'POST' } -}; +}); export { endpoints }; diff --git a/src/constants/header-keys.js b/src/constants/header-keys.js index f466a663..20d0cc1b 100644 --- a/src/constants/header-keys.js +++ b/src/constants/header-keys.js @@ -1,3 +1,5 @@ -export const headerKeys = { +const headerKeys = Object.freeze({ EXPERIMENT: 'X-Experiment-Data' -}; +}); + +export default headerKeys; diff --git a/src/constants/mock-endpoints.js b/src/constants/mock-endpoints.js index 89286267..2cd03e45 100644 --- a/src/constants/mock-endpoints.js +++ b/src/constants/mock-endpoints.js @@ -1,11 +1,11 @@ // used until real services are available -const endpoints = { +const endpoints = Object.seal({ GetRouteInfo: { url: 'https://mockey.qa.sagaws.net/service/ISS/Content/RouteInfo', method: 'GET' } -}; +}); export { endpoints }; diff --git a/src/digital-components/base-input-button/button-functionality-props.js b/src/digital-components/base-input-button/button-functionality-props.js index b62a67e8..7bffd26e 100644 --- a/src/digital-components/base-input-button/button-functionality-props.js +++ b/src/digital-components/base-input-button/button-functionality-props.js @@ -1,4 +1,4 @@ -const inputButtonProps = { +const inputButtonProps = Object.seal({ value: { type: [String, Number], required: true @@ -35,6 +35,6 @@ const inputButtonProps = { default: false }, suppressError: Boolean -}; +}); export default inputButtonProps; diff --git a/src/digital-components/question-chain/question-chain.vue b/src/digital-components/question-chain/question-chain.vue index 98ef4d7a..5f72221f 100644 --- a/src/digital-components/question-chain/question-chain.vue +++ b/src/digital-components/question-chain/question-chain.vue @@ -97,6 +97,7 @@ export default { "1|answer|DD11132|Yes" */ + // TODO: Assignment to parm question.answerSelected = returnedAnswer; const isQuestionChainComplete = this.getQuestionChainAnswerIfComplete(returnedAnswer); @@ -121,6 +122,7 @@ export default { const questionAnswerText = returnedAnswerArray[3]; const answeredQuestions = []; + // TODO: This forEach could probably be converted into something more reactive this.questions.forEach((q) => { // find this question and mark it as "answered" by populating answerSelected if (q.questionSequence === questionNum) { diff --git a/src/digital-components/textbox-question/textbox-question.vue b/src/digital-components/textbox-question/textbox-question.vue index 26299c87..90088784 100644 --- a/src/digital-components/textbox-question/textbox-question.vue +++ b/src/digital-components/textbox-question/textbox-question.vue @@ -164,12 +164,12 @@ export default { const words = this.questionText.toString().split(/[ ]+/); words.forEach((word) => { const position = 1; - word = [ + const newWord = [ word.toString().slice(0, position), noBreakChar, word.toString().slice(position) ].join(''); - questionText += `${word} `; + questionText += `${newWord} `; }); questionText = questionText.trimEnd(); diff --git a/src/global-methods.js b/src/global-methods.js index 779d53dc..4d333918 100644 --- a/src/global-methods.js +++ b/src/global-methods.js @@ -4,7 +4,7 @@ import { useMainStore } from '@/store'; import applicationConfig from '@/constants/application-config.js'; import { GaCategories, GaActions, GaLabels } from '@/constants/analytics'; -import { headerKeys } from '@/constants/header-keys'; +import headerKeys from '@/constants/header-keys'; export default { callHttpClient({ method, endpoint, payload, logApiCall = true}) { diff --git a/src/iss-components/address-questions/address-questions.vue b/src/iss-components/address-questions/address-questions.vue index 78f6d640..83346b51 100644 --- a/src/iss-components/address-questions/address-questions.vue +++ b/src/iss-components/address-questions/address-questions.vue @@ -342,7 +342,7 @@ export default { }) .catch(() => { // Failed to fetch script - window.console.log('Unable to load Google Places API script'); + window.console.warn('Unable to load Google Places API script'); }); } } diff --git a/src/iss-components/button-question-modal/button-question-modal.vue b/src/iss-components/button-question-modal/button-question-modal.vue index 3863e3b0..dcdb6539 100644 --- a/src/iss-components/button-question-modal/button-question-modal.vue +++ b/src/iss-components/button-question-modal/button-question-modal.vue @@ -38,7 +38,7 @@ suppressLoader :buttonText="ModalSelectButtonText" data-bs-dismiss="modal" - @click-event="buttonClick" /> + @clickEvent="buttonClick" /> diff --git a/src/layouts/address-lookup/address-lookup.spec.js b/src/layouts/address-lookup/address-lookup.spec.js index 971a99c6..6c4bce4d 100644 --- a/src/layouts/address-lookup/address-lookup.spec.js +++ b/src/layouts/address-lookup/address-lookup.spec.js @@ -1,5 +1,5 @@ // Components -import addressLookup from '@/layouts/address-lookup/address-lookup'; +import addressLookup from '@/layouts/address-lookup/address-lookup.vue'; // Supporting Files import { settleAllPromises } from '@/helpers/layout-helper.js'; @@ -18,6 +18,7 @@ jest.mock('@/helpers/layout-helper.js', () => ({ settleAllPromises: jest.fn() })); +/** @ignore */ function setupMocks({ lookupVinbyAddressResponse, partsOrQuestions = [], @@ -162,51 +163,52 @@ describe('address-lookup.vue', () => { expect(wrapper.findComponent({ ref: 'alertMatchedTwoIdenticalYMMVehicle' }).isVisible()).toBe(true); }); - test('if the looking up VIN by address is not allowed in the state selected display the Vin Lookup By HomeAddress Not Allowed Alert', async () => { + test('if the looking up VIN by address is not allowed in the state selected display the Vin Lookup By HomeAddress Not Allowed Alert', + async () => { // Arrange - const mockRegistrationAddress = { - streetAddress: '1234 Main St', - city: 'Columbus', - state: 'OH', - zipCode: '43215' - }; + const mockRegistrationAddress = { + streetAddress: '1234 Main St', + city: 'Columbus', + state: 'OH', + zipCode: '43215' + }; - const { wrapper } = setupMocks({ - isStatePermissible: false, - lookupVinbyAddressResponse: { + const { wrapper } = setupMocks({ isStatePermissible: false, - vinVehicles: [ - { - vin: 'TEST_VIN', - vehicle: { - carId: 'CARID' + lookupVinbyAddressResponse: { + isStatePermissible: false, + vinVehicles: [ + { + vin: 'TEST_VIN', + vehicle: { + carId: 'CARID' + } + }, + { + vin: 'TEST_VIN2', + vehicle: { + carId: 'CARID2' + } } - }, - { - vin: 'TEST_VIN2', - vehicle: { - carId: 'CARID2' - } - } - ] - } + ] + } + }); + + useMainStore().order.vehicle.carId = 'CARID'; + + await wrapper.setData({ + customerQuestions: { + addressQuestions: mockRegistrationAddress + } + }); + + // Act + await wrapper.vm.forwardButtonAction(); + + // Assert + expect(wrapper.findComponent({ ref: 'alertVinLookupsByHomeAddressNotAllowed' }).isVisible()).toBe(true); }); - useMainStore().order.vehicle.carId = 'CARID'; - - await wrapper.setData({ - customerQuestions: { - addressQuestions: mockRegistrationAddress - } - }); - - // Act - await wrapper.vm.forwardButtonAction(); - - // Assert - expect(wrapper.findComponent({ ref: 'alertVinLookupsByHomeAddressNotAllowed' }).isVisible()).toBe(true); - }); - test('if no vehicles found, display Vin Not Found alert', async () => { // Arrange const mockRegistrationAddress = { @@ -352,47 +354,48 @@ describe('address-lookup.vue', () => { carsFound); }); - test('if a different vehicle is found than the one entered and the selected glass is not available for that vehicle, navigate back to vehicle-damage page', async () => { + test('if a different vehicle is found than the one entered and the selected glass is not available for that vehicle, navigate back to vehicle-damage page', + async () => { // Arrange - const mockRegistrationAddress = { - streetAddress: '1234 Main St', - city: 'Columbus', - state: 'OH', - zipCode: '43215' - }; + const mockRegistrationAddress = { + streetAddress: '1234 Main St', + city: 'Columbus', + state: 'OH', + zipCode: '43215' + }; - const { wrapper } = setupMocks({ - isStatePermissible: true - }); + const { wrapper } = setupMocks({ + isStatePermissible: true + }); - await wrapper.setData({ - customerQuestions: { - addressQuestions: mockRegistrationAddress - }, - isCarIdDifferent: true, - isSelectedGlassAvailableForVehicle: false - }); + await wrapper.setData({ + customerQuestions: { + addressQuestions: mockRegistrationAddress + }, + isCarIdDifferent: true, + isSelectedGlassAvailableForVehicle: false + }); - useMainStore().order.vehicle.carId = 'CARID'; + useMainStore().order.vehicle.carId = 'CARID'; - const carsFound = [ - { - vin: 'TEST_VIN2', - vehicle: { - carId: 'C0000' + const carsFound = [ + { + vin: 'TEST_VIN2', + vehicle: { + carId: 'C0000' + } } - } - ]; + ]; - // Act - await wrapper.vm.navigateForward(carsFound); + // Act + await wrapper.vm.navigateForward(carsFound); - // Assert - expect(wrapper.vm.$router.navigate).toHaveBeenCalledWith(navigationScenarios.SELECTED_VIN_WITH_MISMATCHED_GLASS, - undefined, - {}, - { displayVehicleChangeAlert: true }); - }); + // Assert + expect(wrapper.vm.$router.navigate).toHaveBeenCalledWith(navigationScenarios.SELECTED_VIN_WITH_MISMATCHED_GLASS, + undefined, + {}, + { displayVehicleChangeAlert: true }); + }); test('single car was found and matches entered vehicle => navigateForwardWithSingleCarMatch', async () => { // Arrange diff --git a/src/layouts/address-lookup/address-lookup.vue b/src/layouts/address-lookup/address-lookup.vue index b69f99ce..47ce282a 100644 --- a/src/layouts/address-lookup/address-lookup.vue +++ b/src/layouts/address-lookup/address-lookup.vue @@ -3,7 +3,7 @@ ref="theForm" v-slot="{ meta }" @submit="onSubmit" - @invalid-submit="onInvalidSubmit"> + @invalidSubmit="onInvalidSubmit">