From bcfa12997b49c8d51efbd1beb93e87c94774c40e Mon Sep 17 00:00:00 2001 From: scottkiener-at-safelite Date: Mon, 9 Mar 2026 11:13:16 -0400 Subject: [PATCH 1/2] INSR-8541 | Add OEM bullet point, link, and modal verified deductible only --- .../coverage-statement.spec.js.snap | 1 + .../coverage-statement/coverage-statement.vue | 15 +- .../oem-endorsement-modal.spec.js.snap | 3 + .../oem-endorsement-modal.spec.js | 141 ++++++++++++++++++ .../oem-endorsement-modal.vue | 79 ++++++++++ 5 files changed, 237 insertions(+), 2 deletions(-) create mode 100644 src/layouts/coverage-statement/oem-endorsement-modal/__snapshots__/oem-endorsement-modal.spec.js.snap create mode 100644 src/layouts/coverage-statement/oem-endorsement-modal/oem-endorsement-modal.spec.js create mode 100644 src/layouts/coverage-statement/oem-endorsement-modal/oem-endorsement-modal.vue diff --git a/src/layouts/coverage-statement/__snapshots__/coverage-statement.spec.js.snap b/src/layouts/coverage-statement/__snapshots__/coverage-statement.spec.js.snap index 40af428e..52bab2ae 100644 --- a/src/layouts/coverage-statement/__snapshots__/coverage-statement.spec.js.snap +++ b/src/layouts/coverage-statement/__snapshots__/coverage-statement.spec.js.snap @@ -3,6 +3,7 @@ exports[`coverageStatement.vue returns the initial data 1`] = ` Object { "CANCEL_CLAIM_REF_NAME": "CancelClaimModal", + "OEM_ENDORSEMENT_REF_NAME": "OEMModal", "RECAL_MODAL_REF_NAME": "RecalModal", "baseServiceLineItems": Array [], "isPageLoading": true, diff --git a/src/layouts/coverage-statement/coverage-statement.vue b/src/layouts/coverage-statement/coverage-statement.vue index 4e31fa37..4cc38651 100644 --- a/src/layouts/coverage-statement/coverage-statement.vue +++ b/src/layouts/coverage-statement/coverage-statement.vue @@ -108,6 +108,9 @@ :ref="CANCEL_CLAIM_REF_NAME" @cancelClaimConfirmation="cancelClaim" @returnToClaim="navigateForward" /> + @@ -143,9 +146,11 @@ import showIssLoadingModal from '@/helpers/loading-modal-helper'; import { getPriceOfLineItems } from '@/helpers/price-calculator'; import coverageStatuses from '@/constants/coverage-statuses'; import coverageType from '@/constants/coverage-type'; +import oemEndorsementModal from '@/layouts/coverage-statement/oem-endorsement-modal/oem-endorsement-modal.vue'; const RECAL_MODAL_REF_NAME = 'RecalModal'; const CANCEL_CLAIM_REF_NAME = 'CancelClaimModal'; +const OEM_ENDORSEMENT_REF_NAME = 'OEMModal'; export default { name: 'coverage-statement', @@ -158,7 +163,8 @@ export default { siteFooter, cancelClaimModal, afterpayModalBanner, - recalModal + recalModal, + oemEndorsementModal }, mixins: [baseFormMixin, vehicleQuestionsMixin], async beforeRouteEnter(to, from, next) { @@ -221,7 +227,8 @@ export default { nextStep: 'NextStepsWidget' }, RECAL_MODAL_REF_NAME, - CANCEL_CLAIM_REF_NAME + CANCEL_CLAIM_REF_NAME, + OEM_ENDORSEMENT_REF_NAME }; }, computed: { @@ -356,6 +363,7 @@ export default { nextStepsBody(newValue, oldValue) { if (newValue !== oldValue) { setupModalLink(this, RECAL_MODAL_REF_NAME); + setupModalLink(this, OEM_ENDORSEMENT_REF_NAME); } } }, @@ -424,6 +432,7 @@ export default { }, getCustomValueFromString(str) { const { isRepair } = useMainStore().damage; + switch (str) { case 'coverageUnverified': return this.isUnverifiedVisible; @@ -449,6 +458,8 @@ export default { return !isRepair && this.isDeductibleVisible && this.deductibleValue <= 0; case 'verifiedReplaceDeductibleOverZero': return !isRepair && this.isDeductibleVisible && this.deductibleValue > 0; + case 'hasOEMEndorsement': + return this.mainStore.hasOemEndorsement; default: return null; } diff --git a/src/layouts/coverage-statement/oem-endorsement-modal/__snapshots__/oem-endorsement-modal.spec.js.snap b/src/layouts/coverage-statement/oem-endorsement-modal/__snapshots__/oem-endorsement-modal.spec.js.snap new file mode 100644 index 00000000..dd02d636 --- /dev/null +++ b/src/layouts/coverage-statement/oem-endorsement-modal/__snapshots__/oem-endorsement-modal.spec.js.snap @@ -0,0 +1,3 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`returns the initial data 1`] = `Object {}`; diff --git a/src/layouts/coverage-statement/oem-endorsement-modal/oem-endorsement-modal.spec.js b/src/layouts/coverage-statement/oem-endorsement-modal/oem-endorsement-modal.spec.js new file mode 100644 index 00000000..09ff67d1 --- /dev/null +++ b/src/layouts/coverage-statement/oem-endorsement-modal/oem-endorsement-modal.spec.js @@ -0,0 +1,141 @@ +import { shallowMount } from '@vue/test-utils'; +import oemEndorsementModal from '@/layouts/coverage-statement/oem-endorsement-modal/oem-endorsement-modal.vue'; + +const VEHICLE_MAKE = 'Toyota'; + +const mockDataStrings = { + cmsBodyText: `Some Body Text from CMS for {custom:vehicleMake}`, + cmsHeaderText: 'Some Header Text from CMS', + cmsFooterText: 'Some Footer Text from CMS' +}; + +const mockCmsContent = { + BodyText: mockDataStrings.cmsBodyText, + HeaderText: mockDataStrings.cmsHeaderText, + FooterText: mockDataStrings.cmsFooterText +}; + +const mockMixin = { + methods: { + getCmsContent: jest.fn((_, cmsFieldName) => mockCmsContent[cmsFieldName]) + }, + computed: { + vehicleMake: () => VEHICLE_MAKE + } +}; + +function setupMocks() { + const wrapper = shallowMount(oemEndorsementModal, { + mixins: [mockMixin], + props: { + cmsWidgetName: 'OEMEndorsementModal' + }, + attachTo: document.body + }); + + return { wrapper }; +} + +test('returns the initial data', () => { + // Arrange + const { wrapper } = setupMocks(); + + // Assert + expect(wrapper.vm.$data).toMatchSnapshot(); +}); + +describe('Computed', () => { + test('Should get modal header text from Widget CMS', () => { + // Arrange + const { wrapper } = setupMocks(); + + // Act + const result = wrapper.vm.modalHeaderText; + + // Assert + expect(result).toBe(mockDataStrings.cmsHeaderText); + }); + + test('Should get modal close button text from Widget CMS', () => { + // Arrange + const { wrapper } = setupMocks(); + + // Act + const result = wrapper.vm.modalCloseButtonText; + + // Assert + expect(result).toBe(mockDataStrings.cmsFooterText); + }); + + test('Should get modal body text from Widget CMS and replace vehicle make placeholder', () => { + // Arrange + const { wrapper } = setupMocks(); + + // Act + const result = wrapper.vm.modalBodyText; + + // Assert + expect(result).toBe(mockDataStrings.cmsBodyText.replaceAll('{custom:vehicleMake}', VEHICLE_MAKE)); + }); + + test('Should call getCmsContent with the correct widget name and field name for body text', () => { + // Arrange + const { wrapper } = setupMocks(); + + // Act + wrapper.vm.modalBodyText; + + // Assert + expect(mockMixin.methods.getCmsContent).toHaveBeenCalledWith('OEMEndorsementModal', 'BodyText'); + }); + + test('Should call getCmsContent with the correct widget name and field name for header text', () => { + // Arrange + const { wrapper } = setupMocks(); + + // Act + wrapper.vm.modalHeaderText; + + // Assert + expect(mockMixin.methods.getCmsContent).toHaveBeenCalledWith('OEMEndorsementModal', 'HeaderText'); + }); + + test('Should call getCmsContent with the correct widget name and field name for footer text', () => { + // Arrange + const { wrapper } = setupMocks(); + + // Act + wrapper.vm.modalCloseButtonText; + + // Assert + expect(mockMixin.methods.getCmsContent).toHaveBeenCalledWith('OEMEndorsementModal', 'FooterText'); + }); +}); + +describe('Props', () => { + test('Should use the default cmsWidgetName prop value of OEMEndorsementModal', () => { + // Arrange + const wrapper = shallowMount(oemEndorsementModal, { + mixins: [mockMixin], + attachTo: document.body + }); + + // Assert + expect(wrapper.vm.cmsWidgetName).toBe('OEMEndorsementModal'); + }); + + test('Should accept a custom cmsWidgetName prop', () => { + // Arrange + const customWidgetName = 'CustomOEMModal'; + const wrapper = shallowMount(oemEndorsementModal, { + mixins: [mockMixin], + props: { + cmsWidgetName: customWidgetName + }, + attachTo: document.body + }); + + // Assert + expect(wrapper.vm.cmsWidgetName).toBe(customWidgetName); + }); +}); diff --git a/src/layouts/coverage-statement/oem-endorsement-modal/oem-endorsement-modal.vue b/src/layouts/coverage-statement/oem-endorsement-modal/oem-endorsement-modal.vue new file mode 100644 index 00000000..85ee726b --- /dev/null +++ b/src/layouts/coverage-statement/oem-endorsement-modal/oem-endorsement-modal.vue @@ -0,0 +1,79 @@ + + + + + From 518cb88652ccec7cd08073fd2fa0d328a04585f3 Mon Sep 17 00:00:00 2001 From: scottkiener-at-safelite Date: Mon, 9 Mar 2026 11:32:00 -0400 Subject: [PATCH 2/2] Unit test fix --- .../oem-endorsement-modal.spec.js | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/src/layouts/coverage-statement/oem-endorsement-modal/oem-endorsement-modal.spec.js b/src/layouts/coverage-statement/oem-endorsement-modal/oem-endorsement-modal.spec.js index 09ff67d1..8a2c5d9e 100644 --- a/src/layouts/coverage-statement/oem-endorsement-modal/oem-endorsement-modal.spec.js +++ b/src/layouts/coverage-statement/oem-endorsement-modal/oem-endorsement-modal.spec.js @@ -1,10 +1,9 @@ import { shallowMount } from '@vue/test-utils'; import oemEndorsementModal from '@/layouts/coverage-statement/oem-endorsement-modal/oem-endorsement-modal.vue'; -const VEHICLE_MAKE = 'Toyota'; const mockDataStrings = { - cmsBodyText: `Some Body Text from CMS for {custom:vehicleMake}`, + cmsBodyText: `Some Body Text from CMS`, cmsHeaderText: 'Some Header Text from CMS', cmsFooterText: 'Some Footer Text from CMS' }; @@ -19,9 +18,6 @@ const mockMixin = { methods: { getCmsContent: jest.fn((_, cmsFieldName) => mockCmsContent[cmsFieldName]) }, - computed: { - vehicleMake: () => VEHICLE_MAKE - } }; function setupMocks() { @@ -67,17 +63,6 @@ describe('Computed', () => { expect(result).toBe(mockDataStrings.cmsFooterText); }); - test('Should get modal body text from Widget CMS and replace vehicle make placeholder', () => { - // Arrange - const { wrapper } = setupMocks(); - - // Act - const result = wrapper.vm.modalBodyText; - - // Assert - expect(result).toBe(mockDataStrings.cmsBodyText.replaceAll('{custom:vehicleMake}', VEHICLE_MAKE)); - }); - test('Should call getCmsContent with the correct widget name and field name for body text', () => { // Arrange const { wrapper } = setupMocks();