diff --git a/src/assets/img/tints/GlassTint.png b/src/assets/img/tints/GlassTint.png new file mode 100644 index 00000000..b3cf01ba Binary files /dev/null and b/src/assets/img/tints/GlassTint.png differ diff --git a/src/constants/tint-mapper.js b/src/constants/tint-mapper.js deleted file mode 100644 index 91fbd57b..00000000 --- a/src/constants/tint-mapper.js +++ /dev/null @@ -1,91 +0,0 @@ -// TintMap with array keys by location, lowercase to avoid as much string mismatching as possible. -// Src assumes you have a @/assets/img/tints/, making the final value @/assets/img/tints/{Src} in the markup. -// See vehicle-parts for implementation example. -const tintMap = Object.freeze({ - other: [ - // Blue Shade - { name: 'blue tint, blue shade', src: 'Glass-BlueShade-BlueTint.svg' }, - { name: 'brown tint, blue shade', src: 'Glass-BlueShade-BrownTint.svg' }, - { name: 'gray tint, blue shade', src: 'Glass-BlueShade-GrayTint.svg' }, - { name: 'green tint, blue shade', src: 'Glass-BlueShade-GreenTint.svg' }, - { name: 'clear, blue shade', src: 'Glass-BlueShade-NoTint.svg' }, - - // Brown Shade - { name: 'brown tint, brown shade', src: 'Glass-BrownShade-BrownTint.svg' }, - - // Gray Shade - { name: 'blue tint, gray shade', src: 'Glass-GrayShade-BlueTint.svg' }, - { name: 'brown tint, gray shade', src: 'Glass-GrayShade-BrownTint.svg' }, - { name: 'gray tint, gray shade', src: 'Glass-GrayShade-GrayTint.svg' }, - { name: 'green tint, gray shade', src: 'Glass-GrayShade-GreenTint.svg' }, - - // Green Shade - { name: 'blue tint, green shade', src: 'Glass-GreenShade-BlueTint.svg' }, - { name: 'brown tint, green shade', src: 'Glass-GreenShade-BrownTint.svg' }, - { name: 'green tint, green shade', src: 'Glass-GreenShade-GreenTint.svg' }, - - // Tints Only - { name: 'blue tint privacy', src: 'Glass-NoShade-BlueTint.svg' }, - { name: 'bronze tint', src: 'Glass-NoShade-BrownTint.svg' }, - { name: 'dark brown tint', src: 'Glass-NoShade-DarkBrownTint.svg' }, - { name: 'privacy, black frame', src: 'Glass-NoShade-Privacy.svg' }, - { name: 'gray tint', src: 'Glass-NoShade-GrayTint.svg' }, - { name: 'green tint', src: 'Glass-NoShade-GreenTint.svg' }, - { name: 'gray tint privacy', src: 'Glass-NoShade-GrayTint.svg' }, - { name: 'blue tint', src: 'Glass-NoShade-BlueTint.svg' }, - { name: 'green tint privacy', src: 'Glass-NoShade-GreenTint.svg' }, - - // No shade or tint - { name: 'clear', src: 'Glass-NoShade-NoTint.svg' } - ], - - windshield: [ - // Blue Shade - { name: 'blue tint, blue shade', src: 'Windshield-BlueShade-BlueTint.svg' }, - { name: 'bronze tint, blue shade', src: 'Windshield-BlueShade-BrownTint.svg' }, - { name: 'gray tint, blue shade', src: 'Windshield-BlueShade-GrayTint.svg' }, - { name: 'green tint, blue shade', src: 'Windshield-BlueShade-GreenTint.svg' }, - { name: 'clear, blue shade', src: 'Windshield-BlueShade-NoTint.svg' }, - - // Brown Shade - { name: 'bronze tint, bronze shade', src: 'Windshield-BrownShade-BrownTint.svg' }, - - // Gray Shade - { name: 'blue tint, gray shade', src: 'Windshield-GrayShade-BlueTint.svg' }, - { name: 'brown tint, gray shade', src: 'Windshield-GrayShade-BrownTint.svg' }, - { name: 'gray tint, gray shade', src: 'Windshield-GrayShade-GrayTint.svg' }, - { name: 'green tint, gray shade', src: 'Windshield-GrayShade-GreenTint.svg' }, - - // Green Shade - { name: 'blue tint, green shade', src: 'Windshield-GreenShade-BlueTint.svg' }, - { name: 'brown tint, green shade', src: 'Windshield-GreenShade-BrownTint.svg' }, - { name: 'green tint, green shade', src: 'Windshield-GreenShade-GreenTint.svg' }, - - // Tints Only - { name: 'blue tint', src: 'Windshield-NoShade-BlueTint.svg' }, - { name: 'bronze tint', src: 'Windshield-NoShade-BrownTint.svg' }, - { name: 'dark brown tint', src: 'Windshield-NoShade-DarkBrownTint.svg' }, - { name: 'privacy, black frame', src: 'Windshield-NoShade-Privacy.svg' }, - { name: 'gray tint', src: 'Windshield-NoShade-GrayTint.svg' }, - { name: 'green tint', src: 'Windshield-NoShade-GreenTint.svg' }, - { name: 'gray tint privacy', src: 'Windshield-NoShade-GrayTint.svg' }, - - // No shade or tint - { name: 'clear', src: 'Windshield-NoShade-NoTint.svg' } - ] -}); - -// Gets the tint image source string given the glass location, and the tint description (like 'Green Tint') -// Use lowered strings here to try to avoid mismatch. Returns an empty string if array key doesn't exist. -// Returns undefined if no items are found. -const getTintImage = (glassLocation, colorString) => { - // Windshield glass has special images, all other glass uses the same though. - const glassLoc = (glassLocation.toLowerCase() !== 'windshield') ? 'other' : 'windshield'; - if (tintMap[glassLoc] === undefined) { - return ''; - } - - return tintMap[glassLoc].find((item) => item.name.toLowerCase() === colorString.toLowerCase()); -}; - -export default getTintImage; diff --git a/src/helpers/text-helper.js b/src/helpers/text-helper.js index b6fc5184..c05b870a 100644 --- a/src/helpers/text-helper.js +++ b/src/helpers/text-helper.js @@ -46,7 +46,7 @@ export function createUnorderedListFromStringOfParagraphs(stringOfParagraphs) { */ export function toTitleCase(text) { let temp = text?.toLowerCase() ?? ''; - return temp.replace(/(^|\s|-)\S/g, (letter) => letter.toUpperCase()); + return temp.replace(/(^|\s|-|\/)\S/g, (letter) => letter.toUpperCase()); } /** diff --git a/src/layouts/vehicle-parts/glass-part-question/glass-part-question.spec.js b/src/layouts/vehicle-parts/glass-part-question/glass-part-question.spec.js index 41a935b8..fd7afa32 100644 --- a/src/layouts/vehicle-parts/glass-part-question/glass-part-question.spec.js +++ b/src/layouts/vehicle-parts/glass-part-question/glass-part-question.spec.js @@ -41,13 +41,14 @@ function setupMocks({ glassNameProp, glassLocationProp, colorAnswersProp, modelV }; - const wrapper = shallowMount(glassPartQuestion, mountOptions); - // Mock store const partsOrQuestions = pageData ?? { partsOrQuestions: [{ glassName: 'Stationary', glassLocation: 'Rear', parts: [] }] }; useMainStore().pageData = jest.fn(); useMainStore().pageData.mockReturnValue(partsOrQuestions); document.querySelector = jest.fn().mockReturnValue({ clicked: false, click: jest.fn() }); + + const wrapper = shallowMount(glassPartQuestion, mountOptions); + return { wrapper }; } @@ -62,36 +63,23 @@ describe('glass-part-question.vue', () => { window.console.log(wrapper.vm.featureListData['Green Tint'][0].Text); // Assert expect(Object.keys(wrapper.vm.featureListData).length).toBe(2); - expect(wrapper.vm.featureListData['Green Tint'][0].Text).toBe('heated glass, solar, 1 hole'); + expect(wrapper.vm.featureListData['Green Tint'][0].Text).toBe('Heated glass, Solar, 1 Hole'); expect(wrapper.vm.featureListData['Green Tint'][0].Name).toBe('DB12209GTYN'); - expect(wrapper.vm.featureListData['Gray Tint Privacy'][0].Text).toBe('heated glass, solar, 1 hole'); + expect(wrapper.vm.featureListData['Gray Tint Privacy'][0].Text).toBe('Heated glass, Solar, 1 Hole'); expect(wrapper.vm.featureListData['Gray Tint Privacy'][0].Name).toBe('DB12209YPYN'); }); - test('Tint mapper, should get tint image by glassLocation and tintColor', async () => { + test('Tint mapper, should get return css class based on tint color', async () => { // Arrange const { wrapper } = setupMocks(featureListData); // Act await wrapper.vm.$nextTick(); - const tintSourceImage = wrapper.vm.getTintSourceImage('Rear', 'Green Tint'); + const tintClass = wrapper.vm.convertTintToCSSClass('Green Tint'); // Assert - expect(tintSourceImage).toBe('Glass-NoShade-GreenTint.svg'); - }); - - test('Tint mapper, should return empty string if no tint map found', async () => { - // Arrange - - const { wrapper } = setupMocks(featureListData); - - // Act - await wrapper.vm.$nextTick(); - const tintSourceImage = wrapper.vm.getTintSourceImage('Rear', 'Crazy Rainbow Tint'); - - // Assert - expect(tintSourceImage).toBe(''); + expect(tintClass).toBe('green-tint'); }); test('Should emit updateModelValue, and have correct attributes', async () => { @@ -122,7 +110,7 @@ describe('glass-part-question.vue', () => { { partNumber: 'DB12209GTYN', color: 'Green Tint' } ]); expect(listCard.attributes('groupname')).toBe('Rear-Stationary'); - expect(listCard.attributes('validationrules')).toBe('Rear-Stationary-tint-required'); + expect(listCard.attributes('validationrules')).toBe('Rear-Stationary-part-required'); }); test('default is selected if only one option', async () => { @@ -136,58 +124,42 @@ describe('glass-part-question.vue', () => { } ] }; + const updateSpy = jest.spyOn(glassPartQuestion.methods, 'updateSelectedPartNumber'); const { wrapper } = setupMocks(featureListData); - - // Act - await wrapper.vm.$nextTick(); - await wrapper.setData({ selectedTint: 'Green Tint' }); - // take emitted value, pass down as modelValue - // yes, yes, it's not ideal - await wrapper.setProps({ modelValue: wrapper.emitted()['update:modelValue'][0][0] }); await wrapper.vm.$nextTick(); // Assert - expect(wrapper.vm.selectedPartNumber).toBe('DB12209GTYN'); + expect(updateSpy).toHaveBeenCalledWith('DB12209GTYN'); }); - const partsForSelectedTintTestCases = [ + const partsForLocationTestCases = [ [ 'Rear', 'Stationary', - 'Green Tint', [ { partNumber: 'Glass1', color: 'Green Tint' }, + { partNumber: 'Glass2', color: 'Blue Tint' }, { partNumber: 'Glass3', color: 'Green Tint' }, { partNumber: 'Glass4', color: 'Green Tint' }, - { partNumber: 'Glass6', color: 'Green Tint' } + { partNumber: 'Glass5', color: 'Blue Tint' }, + { partNumber: 'Glass6', color: 'Green Tint' }, + { partNumber: 'Glass7', color: 'Red Tint' } ] ], - [ - 'Rear', - 'Stationary', - 'Blue Tint', - [ - { partNumber: 'Glass2', color: 'Blue Tint' }, - { partNumber: 'Glass5', color: 'Blue Tint' } - ] - ], - ['Rear', 'Stationary', 'Red Tint', [{ partNumber: 'Glass7', color: 'Red Tint' }]], [ 'Windshield', 'Single', - 'Green Tint', [ { partNumber: 'Windshield1', color: 'Green Tint' }, { partNumber: 'Windshield2', color: 'Green Tint' } ] ], - ['Windshield', 'Single', 'Blue Tint', []], - ['Driver', 'Quarter', 'Green Tint', []] + ['Driver', 'Quarter', []] ]; - test.each(partsForSelectedTintTestCases)( - 'partsForSelectedTint returns correct parts', - async (glassLocation, glassName, selectedTint, expectedResults) => { + test.each(partsForLocationTestCases)( + 'partsForLocation returns correct parts', + async (glassLocation, glassName, expectedResults) => { // Arrange const pageData = { partsOrQuestions: [ { @@ -219,11 +191,8 @@ describe('glass-part-question.vue', () => { pageData }); - // Act - await wrapper.setData({ selectedTint }); - // Assert - expect(expectedResults).toEqual(wrapper.vm.partsForSelectedTint); + expect(wrapper.vm.partsForLocation).toEqual(expectedResults); } ); }); diff --git a/src/layouts/vehicle-parts/glass-part-question/glass-part-question.vue b/src/layouts/vehicle-parts/glass-part-question/glass-part-question.vue index 0fe2bec3..1d5c2115 100644 --- a/src/layouts/vehicle-parts/glass-part-question/glass-part-question.vue +++ b/src/layouts/vehicle-parts/glass-part-question/glass-part-question.vue @@ -1,44 +1,27 @@ diff --git a/src/layouts/vehicle-parts/vehicle-parts.vue b/src/layouts/vehicle-parts/vehicle-parts.vue index 5ceefd0d..4e75e55f 100644 --- a/src/layouts/vehicle-parts/vehicle-parts.vue +++ b/src/layouts/vehicle-parts/vehicle-parts.vue @@ -11,34 +11,36 @@
- -
- -
- +
+
+ +
+
@@ -51,7 +53,7 @@ import glassPartQuestion from '@/layouts/vehicle-parts/glass-part-question/glass import siteHeader from '@/iss-components/site-header/site-header.vue'; import siteSubHeader from '@/iss-components/site-sub-header/site-sub-header.vue'; import siteFooter from '@/iss-components/site-footer/site-footer.vue'; -import alert from '@/ux-components/alert/alert.vue'; +import textLink from '@/ux-components/text-link/text-link.vue'; // Supporting Files import { fetchCmsContentForPage } from '@/helpers/cms-content-helper'; @@ -61,6 +63,7 @@ import { Form } from 'vee-validate'; import vehicleQuestionsMixin from '@/mixins/vehicle-questions-mixin'; import BaseFormMixin from '@/mixins/base-form-mixin.js'; import { useMainStore } from '@/store'; +import widgetFields from '@/constants/cms-widget-fields'; export default { name: 'vehicle-parts', @@ -71,7 +74,7 @@ export default { siteHeader, siteSubHeader, siteFooter, - alert + textLink }, mixins: [BaseFormMixin, vehicleQuestionsMixin], async beforeRouteEnter(to, from, next) { @@ -88,17 +91,6 @@ export default { // Call the "next" function to complete the transition to this page. next((vm) => { vm.setCmsContent(resultMap.cmsContent); - - // Glass Part Question dynamic component - Object.keys(vm.$refs) - .filter((r) => r.includes(vm.RefPrefix) && vm.$refs[r][0] !== undefined) - .forEach((c) => - vm.$refs[c][0].initializeComponent({ - ColorQuestionWidget: - resultMap.cmsContent.ColorQuestionWidget, - FeatureQuestionWidget: - resultMap.cmsContent.FeatureQuestionWidget - })); }); }, data() { @@ -156,6 +148,9 @@ export default { RefPrefix() { return 'partQuestion'; + }, + needHelpLinkText() { + return this.getCmsContent('NeedHelpLinkWidget', widgetFields.TEXT_BLOCK_WIDGET.TEXT); } }, mounted() { @@ -220,23 +215,47 @@ export default { }); }); }); + }, + requestCallbackBailout() { + this.mainStore.setBailout(bailoutMessage.RequestCallback()); + this.$router.navigate(navigationScenarios.CLICKED_NEED_HELP_WITH_BAILOUT, this.$route); } } }; diff --git a/src/router/router-constants/routing-table.js b/src/router/router-constants/routing-table.js index 2698360f..c3075d3f 100644 --- a/src/router/router-constants/routing-table.js +++ b/src/router/router-constants/routing-table.js @@ -248,6 +248,10 @@ const routingTable = () => [ { scenario: navigationScenarios.CLICKED_FORWARD_WITH_NO_MORE_QUESTIONS, destinationIssPageValue: issPageValues.COVERAGE_STATEMENT + }, + { + scenario: navigationScenarios.CLICKED_NEED_HELP_WITH_BAILOUT, + destinationIssPageValue: issPageValues.BAILOUT_PAGE } ] },