diff --git a/src/constants/coverage-statement-page-variations.js b/src/constants/coverage-statement-page-variations.js new file mode 100644 index 00000000..1f2039e2 --- /dev/null +++ b/src/constants/coverage-statement-page-variations.js @@ -0,0 +1,8 @@ +const coverageStatementPageVariations = Object.freeze({ + DEDUCTIBLE: 0, + ITAC: 1, + NO_COMP: 2, + UNVERIFIED: 3 +}); + +export default coverageStatementPageVariations; diff --git a/src/iss-components/cart-dropdown/cart-dropdown.spec.js b/src/iss-components/cart-dropdown/cart-dropdown.spec.js index 69be39a8..80ee78d9 100644 --- a/src/iss-components/cart-dropdown/cart-dropdown.spec.js +++ b/src/iss-components/cart-dropdown/cart-dropdown.spec.js @@ -313,115 +313,6 @@ describe('cart-dropdown component', () => { }); }); describe('computed', () => { - describe('isUnverified', () => { - test('returns false when no comp', () => { - // Arrange - const storeData = { - order: { - policy: { - isITAC: false, - noCoverage: true - }, - currentDeductible: null - } - }; - const { wrapper } = getMountedComponent(storeData); - - // Act - const result = wrapper.vm.isUnverified; - - // Assert - expect(result).toBeFalsy(); - }); - test('returns false when itac', () => { - // Arrange - const storeData = { - order: { - payment: { - insuranceCoverage: { - coverageStatus: coverageStatuses.PENDING - } - }, - policy: { - isITAC: true - }, - currentDeductible: null - } - }; - const { wrapper } = getMountedComponent(storeData); - - // Act - const result = wrapper.vm.isUnverified; - - // Assert - expect(result).toBeFalsy(); - }); - test('returns false when deductible not null and verified coverage status', () => { - // Arrange - const storeData = { - order: { - payment: { - insuranceCoverage: { - coverageStatus: coverageStatuses.VERIFIED - } - }, - policy: { - isITAC: false - }, - currentDeductible: 23 - } - }; - const { wrapper } = getMountedComponent(storeData); - - // Act - const result = wrapper.vm.isUnverified; - - // Assert - expect(result).toBeFalsy(); - }); - test('returns true when not no comp, not itac, and deductible is null', () => { - // Arrange - const storeData = { - order: { - policy: { - isITAC: false, - noCoverage: false - }, - currentDeductible: null - } - }; - const { wrapper } = getMountedComponent(storeData); - - // Act - const result = wrapper.vm.isUnverified; - - // Assert - expect(result).toBeTruthy(); - }); - test('returns true when not no comp, not itac, and coverage status is not verified', () => { - // Arrange - const storeData = { - order: { - payment: { - insuranceCoverage: { - coverageStatus: coverageStatuses.PENDING - } - }, - policy: { - isITAC: false - }, - currentDeductible: 12 - } - }; - const { wrapper } = getMountedComponent(storeData); - - // Act - const result = wrapper.vm.isUnverified; - - // Assert - expect(result).toBeTruthy(); - }); - }); describe('amountDue', () => { test('returns 0 when showAsPaid is true', () => { // Arrange @@ -556,15 +447,22 @@ describe('cart-dropdown component', () => { // Arrange const storeData = { order: { + policyLookupSuccessful: true, + currentDeductible: 250, lineItems: { glassParts: null, otherParts: null, supportingItems: null, vaps: null + }, + payment: { + insuranceCoverage: { isVerified: true } } + }, + issConfig: { + isClaimRegistrationRequired: true } }; - const { wrapper } = getMountedComponent(storeData); // Act @@ -578,6 +476,8 @@ describe('cart-dropdown component', () => { // Arrange const storeData = { order: { + policyLookupSuccessful: true, + currentDeductible: 250, lineItems: { glassParts: [ { partType: 'mock', salesTax: null }, @@ -591,7 +491,13 @@ describe('cart-dropdown component', () => { { partType: 'mock', salesTax: null }, { partType: 'mock', salesTax: undefined } ] + }, + payment: { + insuranceCoverage: { isVerified: true } } + }, + issConfig: { + isClaimRegistrationRequired: true } }; const { wrapper } = getMountedComponent(storeData); @@ -606,6 +512,8 @@ describe('cart-dropdown component', () => { // Arrange const storeData = { order: { + policyLookupSuccessful: true, + currentDeductible: 250, lineItems: { glassParts: [{ partType: 'mock', salesTax: 10 }], supportingItems: [ @@ -619,10 +527,11 @@ describe('cart-dropdown component', () => { vaps: [] }, payment: { - insuranceCoverage: { - isVerified: false - } + insuranceCoverage: { isVerified: false } } + }, + issConfig: { + isClaimRegistrationRequired: true } }; const { wrapper } = getMountedComponent(storeData); @@ -636,15 +545,25 @@ describe('cart-dropdown component', () => { test('Returns sum of vaps sales tax when coverage is unverified and order has vaps.', () => { // Arrange - const storeData = useMainStore().$state; - storeData.order.lineItems.glassParts = [ - { partType: 'mock', salesTax: 10 } - ]; - storeData.order.lineItems.vaps = [ - { partType: 'mock', salesTax: 1 }, - { partType: 'mock', salesTax: 2 } - ]; - storeData.order.payment.insuranceCoverage.isVerified = false; + const storeData = { + order: { + policyLookupSuccessful: true, + currentDeductible: 250, + lineItems: { + glassParts: [{ partType: 'mock', salesTax: 10 }], + vaps: [ + { partType: 'mock', salesTax: 1 }, + { partType: 'mock', salesTax: 2 } + ] + }, + payment: { + insuranceCoverage: { isVerified: false } + } + }, + issConfig: { + isClaimRegistrationRequired: true + } + }; const { wrapper } = getMountedComponent(storeData); @@ -657,16 +576,30 @@ describe('cart-dropdown component', () => { test('Returns Recycle Fee tax when coverage is Verified-Deductible, replace service, and no vaps.', () => { // Arrange - const storeData = useMainStore().$state; - storeData.order.currentDeductible = 250; - storeData.order.lineItems.glassParts = [ - { partType: 'mock', salesTax: 10, sellingPrice: 150 } - ]; - storeData.order.lineItems.supportingItems = [ - { partNumber: partNumberStrings.RECYCLE_FEE, partType: 'mock', salesTax: 10, sellingPrice: 39.99 } - ]; - storeData.order.lineItems.vaps = null; - storeData.order.payment.insuranceCoverage.isVerified = true; + const storeData = { + order: { + policyLookupSuccessful: true, + currentDeductible: 250, + lineItems: { + glassParts: [{ partType: 'mock', salesTax: 10, sellingPrice: 150 }], + supportingItems: [ + { + partNumber: partNumberStrings.RECYCLE_FEE, + partType: 'mock', + salesTax: 10, + sellingPrice: 39.99 + } + ], + vaps: null + }, + payment: { + insuranceCoverage: { isVerified: true } + } + }, + issConfig: { + isClaimRegistrationRequired: true + } + }; const { wrapper } = getMountedComponent(storeData); @@ -679,24 +612,30 @@ describe('cart-dropdown component', () => { test('Returns sum of vaps + recycle fee sales tax when Verified-Deductible, replace service, and has vaps.', () => { // Arrange - const storeData = useMainStore().$state; - storeData.order.currentDeductible = 250; - storeData.order.lineItems.glassParts = [ - { partType: 'mock', salesTax: 10, sellingPrice: 100 } - ]; - storeData.order.lineItems.otherParts = [ - { partType: 'mock', salesTax: 10, kitPrice: 100 } - ]; - storeData.order.lineItems.supportingItems = [ - { partNumber: partNumberStrings.RECYCLE_FEE, partType: 'mock', salesTax: 10, sellingPrice: 39.99 }, - { partType: 'mock', salesTax: 10, kitPrice: 100 } - ]; - storeData.order.lineItems.vaps = [ - { partType: 'mock', salesTax: 2 }, - { partType: 'mock', salesTax: 3 } - ]; - storeData.order.payment.insuranceCoverage.isVerified = true; - + const storeData = { + order: { + policyLookupSuccessful: true, + currentDeductible: 250, + lineItems: { + glassParts: [{ partType: 'mock', salesTax: 10, sellingPrice: 100 }], + otherParts: [{ partType: 'mock', salesTax: 10, kitPrice: 100 }], + supportingItems: [ + { partNumber: partNumberStrings.RECYCLE_FEE, partType: 'mock', salesTax: 10, sellingPrice: 39.99 }, + { partType: 'mock', salesTax: 10, kitPrice: 100 } + ], + vaps: [ + { partType: 'mock', salesTax: 2 }, + { partType: 'mock', salesTax: 3 } + ] + }, + payment: { + insuranceCoverage: { isVerified: true } + } + }, + issConfig: { + isClaimRegistrationRequired: true + } + }; const { wrapper } = getMountedComponent(storeData); // Act @@ -708,23 +647,27 @@ describe('cart-dropdown component', () => { test('Returns sum of sales tax when Verified-ITAC.', () => { // Arrange - const storeData = useMainStore().$state; - storeData.order.currentDeductible = 0; - storeData.order.lineItems.glassParts = [ - { partType: 'mock', salesTax: 10, sellingPrice: 100 } - ]; - storeData.order.lineItems.otherParts = [ - { partType: 'mock', salesTax: 10, kitPrice: 100 } - ]; - storeData.order.lineItems.supportingItems = [ - { partType: 'mock', salesTax: 10, kitPrice: 100 } - ]; - storeData.order.lineItems.vaps = [ - { partType: 'mock', salesTax: 5 } - ]; - storeData.order.payment.insuranceCoverage.isVerified = true; - storeData.order.policy.isITAC = true; - + const storeData = { + order: { + policyLookupSuccessful: true, + currentDeductible: 0, + lineItems: { + glassParts: [{ partType: 'mock', salesTax: 10, sellingPrice: 100 }], + otherParts: [{ partType: 'mock', salesTax: 10, kitPrice: 100 }], + supportingItems: [{ partType: 'mock', salesTax: 10, kitPrice: 100 }], + vaps: [{ partType: 'mock', salesTax: 5 }] + }, + payment: { + insuranceCoverage: { isVerified: true } + }, + policy: { + isITAC: true + } + }, + issConfig: { + isClaimRegistrationRequired: true + } + }; const { wrapper } = getMountedComponent(storeData); // Act @@ -736,23 +679,28 @@ describe('cart-dropdown component', () => { test('Returns sum of sales tax when Verified-NoComp.', () => { // Arrange - const storeData = useMainStore().$state; - storeData.order.currentDeductible = 0; - storeData.order.lineItems.glassParts = [ - { partType: 'mock', salesTax: 10, sellingPrice: 100 } - ]; - storeData.order.lineItems.otherParts = [ - { partType: 'mock', salesTax: 10, kitPrice: 100 } - ]; - storeData.order.lineItems.supportingItems = [ - { partType: 'mock', salesTax: 10, kitPrice: 100 } - ]; - storeData.order.lineItems.vaps = [ - { partType: 'mock', salesTax: 5 } - ]; - storeData.order.payment.insuranceCoverage.isVerified = true; - storeData.order.policy.noCoverage = true; - + const storeData = { + order: { + policyLookupSuccessful: true, + currentDeductible: 0, + lineItems: { + glassParts: [{ partType: 'mock', salesTax: 10, sellingPrice: 100 }], + otherParts: [{ partType: 'mock', salesTax: 10, kitPrice: 100 }], + supportingItems: [{ partType: 'mock', salesTax: 10, kitPrice: 100 }], + vaps: [{ partType: 'mock', salesTax: 5 }] + }, + payment: { + insuranceCoverage: { isVerified: true } + }, + policy: { + noCoverage: true + } + }, + issConfig: { + isClaimRegistrationRequired: true, + enableNoCompQuote: true + } + }; const { wrapper } = getMountedComponent(storeData); // Act @@ -1791,21 +1739,19 @@ describe('cart-dropdown component', () => { // Arrange const storeData = { order: { - payment: { - insuranceCoverage: { - coverageStatus: coverageStatuses.VERIFIED - } - }, policy: { - isITAC: false + isITAC: false, + isNoComp: false }, - currentDeductible: 321 + currentDeductible: 321, + policyLookupSuccessful: true } }; const { wrapper } = getMountedComponent(storeData); const amount = 123; const dollarAmount = '$84.00'; - formatAmountInDollars.mockImplementationOnce(() => dollarAmount); + formatAmountInDollars + .mockImplementationOnce((value) => (value === amount ? dollarAmount : 1)); // Act const result = wrapper.vm.getDisplayed(amount); diff --git a/src/iss-components/cart-dropdown/cart-dropdown.vue b/src/iss-components/cart-dropdown/cart-dropdown.vue index c1d148bd..5d1505e0 100644 --- a/src/iss-components/cart-dropdown/cart-dropdown.vue +++ b/src/iss-components/cart-dropdown/cart-dropdown.vue @@ -212,10 +212,6 @@ export default { baseServicePrice() { return getPriceOfLineItems(this.baseServiceLineItems) ?? 0; }, - isUnverified() { - return !useMainStore().isNoComp && !useMainStore().isITAC - && (this.deductible == null || !useMainStore().isVerifiedCoverageStatus); - }, subTotal() { const { supportingItems, glassParts, otherParts, vaps, mobileFee } = useMainStore().lineItems; const allLineItems = [ @@ -247,7 +243,7 @@ export default { let result = 0; - if (useMainStore().payment.insuranceCoverage.isVerified) { + if (!useMainStore().isUnverified) { if (useMainStore().isITAC || useMainStore().isNoComp) { result += sumTax(this.baseServiceLineItems); } else { @@ -411,7 +407,7 @@ export default { this.isExpanded = !this.isExpanded; }, getDisplayed(amount) { - return this.isUnverified + return useMainStore().isUnverified && !useMainStore().isNoComp && !useMainStore().isITAC ? VERIFYING_COVERAGE 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 c16fcaf5..660043a6 100644 --- a/src/layouts/coverage-statement/__snapshots__/coverage-statement.spec.js.snap +++ b/src/layouts/coverage-statement/__snapshots__/coverage-statement.spec.js.snap @@ -4,14 +4,11 @@ exports[`coverageStatement.vue-working returns the initial data 1`] = ` Object { "baseServiceLineItems": Array [], "deductibleText": "Your deductible is", - "isNoComp": false, - "isRepair": true, "loadingText": Array [ "Connecting to your insurance company", "Nearly there", "Finishing up", ], - "policyLookupSuccessful": true, "rules": Object { "selectionRequired": "option-required", }, diff --git a/src/layouts/coverage-statement/coverage-statement.spec.js b/src/layouts/coverage-statement/coverage-statement.spec.js index 91ac7ab7..de23cd1b 100644 --- a/src/layouts/coverage-statement/coverage-statement.spec.js +++ b/src/layouts/coverage-statement/coverage-statement.spec.js @@ -10,7 +10,7 @@ import navigationScenarios from '@/router/router-constants/navigation-scenarios. import { getRandomString, getRandomInt } from '@/helpers/data-generation.js'; import settleAllPromises from '@/helpers/layout-helper.js'; import { fetchCmsContentForPage } from '@/helpers/cms-content-helper'; -import { useMainStore } from '@/store/index.js'; +import { useMainStore, getDefaultState } from '@/store'; import getPriceOfLineItems from '@/helpers/price-calculator.js'; jest.mock('@/helpers/layout-helper.js', () => jest.fn()); @@ -90,6 +90,14 @@ function getMountedComponent(mainInitialState = {}, initialData = {}, methodToRu return { wrapper }; } +beforeEach(() => { + const store = useMainStore(); + const defaultState = getDefaultState(); + Object.keys(defaultState).forEach((key) => { + store[key] = defaultState[key]; + }); +}); + describe('coverageStatement.vue-working', () => { test('returns the initial data', () => { // Arrange @@ -99,8 +107,8 @@ describe('coverageStatement.vue-working', () => { isRepair: true }, policy: { - policyLookupSuccessful: true, - noCoverage: false + noCoverage: false, + policyLookupSuccessful: true } } }; @@ -164,43 +172,67 @@ describe('coverageStatement.vue-working', () => { }); describe('Computed', () => { describe('verifiedNoComp', () => { - test.each([true, false])('returns false when policyLookupSuccessful false', (isNoComp) => { - // Arrange - const mainInitialState = { - order: { - policy: { - noCoverage: isNoComp, - policyLookupSuccessful: false - } - } - }; - const { wrapper } = getMountedComponent(mainInitialState); + describe('isNoCompQuoteVisible true', () => { + const enableNoCompQuote = true; + test.each([true, false])('returns false when policyLookupSuccessful false', (isNoComp) => { + // Arrange + const mainInitialState = { + order: { + policy: { + noCoverage: isNoComp, + policyLookupSuccessful: false + } + }, + issConfig: { enableNoCompQuote } + }; + const { wrapper } = getMountedComponent(mainInitialState); - // Act - const result = wrapper.vm.verifiedNoComp; + // Act + const result = wrapper.vm.isNoCompQuoteVisible; - // Assert - expect(result).toBeFalsy(); + // Assert + expect(result).toBeFalsy(); + }); + test.each([true, false])('returns false when isNoComp false', (policyLookupSuccessful) => { + // Arrange + const mainInitialState = { + order: { + policy: { + noCoverage: false, + policyLookupSuccessful + } + }, + issConfig: { enableNoCompQuote } + }; + const { wrapper } = getMountedComponent(mainInitialState); + + // Act + const result = wrapper.vm.isNoCompQuoteVisible; + + // Assert + expect(result).toBeFalsy(); + }); + test('returns true when policyLookupSuccessful true, noCoverage true, and enableNoCompQuote true', () => { + // Arrange + const mainInitialState = { + order: { + policy: { + noCoverage: true, + policyLookupSuccessful: true + } + }, + issConfig: { enableNoCompQuote } + }; + const { wrapper } = getMountedComponent(mainInitialState); + + // Act + const result = wrapper.vm.isNoCompQuoteVisible; + + // Assert + expect(result).toBeTruthy(); + }); }); - test.each([true, false])('returns false when isNoComp false', (policyLookupSuccessful) => { - // Arrange - const mainInitialState = { - order: { - policy: { - noCoverage: false, - policyLookupSuccessful - } - } - }; - const { wrapper } = getMountedComponent(mainInitialState); - - // Act - const result = wrapper.vm.verifiedNoComp; - - // Assert - expect(result).toBeFalsy(); - }); - test('returns true when policyLookupSuccessful true and policyLookupSuccessful true', () => { + test('returns false when policyLookupSuccessful true, noCoverage true and enableNoCompQuote false', () => { // Arrange const mainInitialState = { order: { @@ -208,18 +240,21 @@ describe('coverageStatement.vue-working', () => { noCoverage: true, policyLookupSuccessful: true } + }, + issConfig: { + enableNoCompQuote: false } }; const { wrapper } = getMountedComponent(mainInitialState); // Act - const result = wrapper.vm.verifiedNoComp; + const result = wrapper.vm.isNoCompQuoteVisible; // Assert - expect(result).toBeTruthy(); + expect(result).toBeFalsy(); }); }); - describe('verifiedITAC', () => { + describe('isITACQuoteVisible', () => { const priceOfLineItems = 213; test.each([true, false])('returns false when policyLookupSuccessful false', (isNoComp) => { // Arrange @@ -236,7 +271,7 @@ describe('coverageStatement.vue-working', () => { const { wrapper } = getMountedComponent(mainInitialState); // Act - const result = wrapper.vm.verifiedITAC; + const result = wrapper.vm.isITACQuoteVisible; // Assert expect(result).toBeFalsy(); @@ -256,7 +291,7 @@ describe('coverageStatement.vue-working', () => { const { wrapper } = getMountedComponent(mainInitialState); // Act - const result = wrapper.vm.verifiedITAC; + const result = wrapper.vm.isITACQuoteVisible; // Assert expect(result).toBeFalsy(); @@ -281,7 +316,7 @@ describe('coverageStatement.vue-working', () => { const { wrapper } = getMountedComponent(mainInitialState); // Act - const result = wrapper.vm.verifiedITAC; + const result = wrapper.vm.isITACQuoteVisible; // Assert expect(result).toBeFalsy(); @@ -308,7 +343,7 @@ describe('coverageStatement.vue-working', () => { const { wrapper } = getMountedComponent(mainInitialState); // Act - const result = wrapper.vm.verifiedITAC; + const result = wrapper.vm.isITACQuoteVisible; // Assert expect(result).toBeFalsy(); @@ -329,13 +364,13 @@ describe('coverageStatement.vue-working', () => { const { wrapper } = getMountedComponent(mainInitialState); // Act - const result = wrapper.vm.verifiedITAC; + const result = wrapper.vm.isITACQuoteVisible; // Assert expect(result).toBeTruthy(); }); }); - describe('verifiedDeductible', () => { + describe('isDeductibleVisible', () => { const servicePrice = 123; describe('claim registration required', () => { const issConfig = { isClaimRegistrationRequired: true }; @@ -351,7 +386,7 @@ describe('coverageStatement.vue-working', () => { }, policy: { noCoverage: false, - policyLookupSuccessful: false + policyLookupSuccessful: true }, currentDeductible: servicePrice - 1 } @@ -365,7 +400,7 @@ describe('coverageStatement.vue-working', () => { const { wrapper } = getMountedComponent(mainInitialState); // Act - const result = wrapper.vm.verifiedDeductible; + const result = wrapper.vm.isDeductibleVisible; // Assert expect(result).toBeFalsy(); @@ -377,7 +412,7 @@ describe('coverageStatement.vue-working', () => { const { wrapper } = getMountedComponent(mainInitialState); // Act - const result = wrapper.vm.verifiedDeductible; + const result = wrapper.vm.isDeductibleVisible; // Assert expect(result).toBeFalsy(); @@ -387,7 +422,7 @@ describe('coverageStatement.vue-working', () => { const { wrapper } = getMountedComponent(verifiedDeductibleStoreState); // Act - const result = wrapper.vm.verifiedDeductible; + const result = wrapper.vm.isDeductibleVisible; // Assert expect(result).toBeTruthy(); @@ -420,7 +455,7 @@ describe('coverageStatement.vue-working', () => { const { wrapper } = getMountedComponent(mainInitialState); // Act - const result = wrapper.vm.verifiedDeductible; + const result = wrapper.vm.isDeductibleVisible; // Assert expect(result).toBeFalsy(); @@ -430,7 +465,7 @@ describe('coverageStatement.vue-working', () => { const { wrapper } = getMountedComponent(verifiedDeductibleStoreState); // Act - const result = wrapper.vm.verifiedDeductible; + const result = wrapper.vm.isDeductibleVisible; // Assert expect(result).toBeTruthy(); @@ -459,7 +494,7 @@ describe('coverageStatement.vue-working', () => { const { wrapper } = getMountedComponent(storeState); // Act - const result = wrapper.vm.verifiedDeductible; + const result = wrapper.vm.isDeductibleVisible; // Assert expect(result).toBeFalsy(); @@ -486,7 +521,7 @@ describe('coverageStatement.vue-working', () => { const { wrapper } = getMountedComponent(storeState); // Act - const result = wrapper.vm.verifiedDeductible; + const result = wrapper.vm.isDeductibleVisible; // Assert expect(result).toBeFalsy(); @@ -683,7 +718,7 @@ describe('coverageStatement.vue-working', () => { // Assert expect(result).toBeFalsy(); }); - test('returns true when isNoComp true', () => { + test('returns false when isNoComp true and enableNoCompQuote false', () => { // Arrange const mainInitialState = { order: { @@ -692,6 +727,32 @@ describe('coverageStatement.vue-working', () => { noCoverage: true }, currentDeductible: priceOfLineItems + }, + issConfig: { + enableNoCompQuote: false + } + }; + getPriceOfLineItems.mockImplementationOnce(() => priceOfLineItems); + const { wrapper } = getMountedComponent(mainInitialState); + + // Act + const result = wrapper.vm.isQuoteDisplayed; + + // Assert + expect(result).toBeFalsy(); + }); + test('returns true when isNoComp true and enableNoCompQuote true', () => { + // Arrange + const mainInitialState = { + order: { + policy: { + policyLookupSuccessful: true, + noCoverage: true + }, + currentDeductible: priceOfLineItems + }, + issConfig: { + enableNoCompQuote: true } }; getPriceOfLineItems.mockImplementationOnce(() => priceOfLineItems); @@ -712,7 +773,10 @@ describe('coverageStatement.vue-working', () => { shouldRegisterClaimStoreStateItac = { order: { payment: { - insuranceCoverage: { claimNumber: null } + insuranceCoverage: { + claimNumber: null, + isVerified: true // Added + } }, policy: { policyLookupSuccessful: true, @@ -801,6 +865,7 @@ describe('coverageStatement.vue-working', () => { // Assert expect(result).toBeFalsy(); }); + test('returns false when insuranceCoverage not verified', () => {}); describe('returns true when policy lookup success, vehicleId set to %p, claim reg req, claim not yet reg', () => { test('and itac', () => { // Arrange @@ -1010,6 +1075,9 @@ describe('coverageStatement.vue-working', () => { noCoverage: true, policyLookupSuccessful: true } + }, + issConfig: { + enableNoCompQuote: true } }; const { wrapper } = getMountedComponent(mainInitialState); @@ -1038,6 +1106,9 @@ describe('coverageStatement.vue-working', () => { noCoverage: true, policyLookupSuccessful: true } + }, + issConfig: { + enableNoCompQuote: true } }; const { wrapper } = getMountedComponent(mainInitialState); @@ -1166,11 +1237,15 @@ describe('coverageStatement.vue-working', () => { const initialStore = { order: { payment: { - insuranceCoverage: { claimNumber: null } + insuranceCoverage: { + claimNumber: null, + isVerified: true + } }, policy: { - policyLookupSuccessful: true, - noCoverage: false + noCoverage: false, + isITAC: false, + policyLookupSuccessful: true }, vehicle: { policyVehicleId: 1 @@ -1191,6 +1266,8 @@ describe('coverageStatement.vue-working', () => { const { wrapper } = getMountedComponent(initialStore, {}, mockStoreActions); const next = (method) => { method(wrapper.vm); }; + console.log(wrapper.vm.pageVariation); + // Act coverageStatement.beforeRouteEnter.call(wrapper.vm, undefined, undefined, next); for (let i = 0; i < 7; i++) { diff --git a/src/layouts/coverage-statement/coverage-statement.vue b/src/layouts/coverage-statement/coverage-statement.vue index bd1e0162..b0cba354 100644 --- a/src/layouts/coverage-statement/coverage-statement.vue +++ b/src/layouts/coverage-statement/coverage-statement.vue @@ -33,23 +33,23 @@ v-html="secondaryText">
- {{ deductibleForDisplay }} + {{ formatAmountInDollars(deductibleValue) }}
- {{ servicePriceForDisplay }} + {{ formatAmountInDollars(totalServicePrice) }}
{{ deductibleText }}  - {{ deductibleForDisplay }} + {{ formatAmountInDollars(deductibleValue) }}
= 0) { + const { policy, vehicle } = useMainStore(); + if (policy.policyLookupSuccessful && vehicle.policyVehicleId >= 0) { await useMainStore().getFinalDeductible(); pricingResults = await useMainStore().getPriceOrderItems(availableLineItems) .catch((err) => { @@ -207,12 +210,7 @@ export default { } }, data() { - const { isRepair } = useMainStore().damage; - const { policyLookupSuccessful, noCoverage } = useMainStore().policy; return { - isRepair, - policyLookupSuccessful, - isNoComp: noCoverage ?? false, baseServiceLineItems: [], selectedProvider: '', deductibleText: 'Your deductible is', @@ -236,6 +234,46 @@ export default { }; }, computed: { + pageVariation() { + const { + isNoComp, + issConfig, + policy, + payment, + isClaimRegistrationRequired + } = useMainStore(); + const registerClaimSuccessful = payment.insuranceCoverage.isVerified; + + if (!policy.policyLookupSuccessful) { + return pageVariations.UNVERIFIED; + } + + if (isNoComp) { + if (issConfig.enableNoCompQuote) { + return pageVariations.NO_COMP; + } + return pageVariations.UNVERIFIED; + } + + if (this.deductibleValue == null) { + return pageVariations.UNVERIFIED; + } + + // TODO this should be determined based on the result of the ITAC price call + // TODO it seems that ITAC now requires claim registration calls. If this call fails + // should the page become unverified? + if (this.deductibleValue > this.totalServicePrice) { + return pageVariations.ITAC; + } + + if (isClaimRegistrationRequired) { + if (registerClaimSuccessful) { + return pageVariations.DEDUCTIBLE; + } + return pageVariations.UNVERIFIED; + } + return pageVariations.DEDUCTIBLE; + }, coverageStatementSubHeader() { return this.getTextFromCmsWithCustomIfStatements( this.widget.subheader, @@ -249,10 +287,14 @@ export default { ); }, verifiedItacAlertBody() { + const itacCostSavings = this.deductibleValue - this.totalServicePrice; return this.getCmsContent( this.widget.verifiedItacAlert, widgetFields.ALERT_WIDGET.BODY_TEXT - )?.replaceAll('{custom:costSavings}', this.itacCostSavingsForDisplay); + )?.replaceAll( + '{custom:costSavings}', + formatAmountInDollars(itacCostSavings) + ); }, secondaryText() { return this.getTextFromCmsWithCustomIfStatements( @@ -285,50 +327,25 @@ export default { deductibleValue() { return useMainStore().order.currentDeductible; }, - deductibleForDisplay() { - return formatAmountInDollars(this.deductibleValue); + isNoCompQuoteVisible() { + return this.pageVariation === pageVariations.NO_COMP; }, - registerClaimSuccessful() { - return useMainStore().payment.insuranceCoverage.isVerified; + isITACQuoteVisible() { + return this.pageVariation === pageVariations.ITAC; }, - verifiedNoComp() { - return this.policyLookupSuccessful && this.isNoComp; + isDeductibleVisible() { + return this.pageVariation === pageVariations.DEDUCTIBLE; }, - verifiedITAC() { - return this.policyLookupSuccessful - && !this.isNoComp - && this.deductibleValue > this.totalServicePrice; - }, - coveredAndServicePriceAboveOrEqualDeductible() { - return !this.verifiedNoComp && this.totalServicePrice >= this.deductibleValue; - }, - verifiedDeductible() { - return useMainStore().isClaimRegistrationRequired - ? this.registerClaimSuccessful - && this.coveredAndServicePriceAboveOrEqualDeductible - && this.deductibleValue !== null - : this.policyLookupSuccessful - && this.coveredAndServicePriceAboveOrEqualDeductible; - }, - unverified() { - return !this.verifiedDeductible && !this.verifiedITAC && !this.verifiedNoComp; + isUnverifiedVisible() { + return this.pageVariation === pageVariations.UNVERIFIED; }, isADAS() { - const parts = useMainStore().order.lineItems.glassParts; - return parts !== null && !!parts.find((part) => part.requiresRecalibration); + const { glassParts } = useMainStore().order.lineItems; + return glassParts !== null && !!glassParts.find((part) => part.requiresRecalibration); }, totalServicePrice() { return getPriceOfLineItems(this.baseServiceLineItems); }, - servicePriceForDisplay() { - return formatAmountInDollars(this.totalServicePrice); - }, - itacCostSavings() { - return this.deductibleValue - this.totalServicePrice; - }, - itacCostSavingsForDisplay() { - return formatAmountInDollars(this.itacCostSavings); - }, serviceProviderQuestionText() { return this.getCmsContent( this.widget.serviceProviderQuestion, @@ -342,15 +359,22 @@ export default { ); }, isQuoteDisplayed() { - return this.verifiedITAC || this.verifiedNoComp; + return this.isITACQuoteVisible || this.isNoCompQuoteVisible; }, shouldRegisterClaim() { - return this.policyLookupSuccessful - && useMainStore().vehicle.policyVehicleId != null - && useMainStore().vehicle.policyVehicleId >= 0 - && useMainStore().isClaimRegistrationRequired - && !useMainStore().isClaimAlreadyRegistered - && (this.coveredAndServicePriceAboveOrEqualDeductible || this.verifiedITAC); + const { + policy, + vehicle, + isClaimRegistrationRequired, + isClaimAlreadyRegistered + } = useMainStore(); + const { policyVehicleId } = vehicle; + return policy.policyLookupSuccessful + && policyVehicleId != null + && policyVehicleId >= 0 + && isClaimRegistrationRequired + && !isClaimAlreadyRegistered + && (this.isDeductibleVisible || this.isITACQuoteVisible); } }, watch: { @@ -373,8 +397,9 @@ export default { return !!useMainStore().vehicle.carId; }, async initializeComponent() { - useMainStore().updatePolicyITACFlag(this.verifiedITAC); - const coverageStatus = this.verifiedITAC || this.verifiedNoComp + useMainStore().updatePolicyITACFlag(this.isITACQuoteVisible); + // TODO how should coverage status be updated + const coverageStatus = this.isITACQuoteVisible || this.isNoCompQuoteVisible ? coverageStatuses.VERIFIED : coverageStatuses.PENDING; useMainStore().updateCoverageStatus(coverageStatus); @@ -384,10 +409,10 @@ export default { this.$refs.loadingModal.hideModal(); }, async navigateForward() { - if (this.unverified || this.verifiedDeductible) { + if (this.isUnverifiedVisible || this.isDeductibleVisible) { useMainStore().updateSupportingItems(this.supportingItems); this.navigateWithScenario(navigationScenarios.CLICKED_FORWARD); - } else if (this.verifiedITAC || this.verifiedNoComp) { + } else if (this.isITACQuoteVisible || this.isNoCompQuoteVisible) { useMainStore().updateIsSafeliteProvider(this.selectedProvider === SAFELITE_PROVIDER); if (this.selectedProvider === SAFELITE_PROVIDER) { useMainStore().updateSupportingItems(this.supportingItems); @@ -409,25 +434,26 @@ export default { return processIfStatements(rawText, 'custom', this.getCustomValueFromString); }, getCustomValueFromString(str) { + const { isRepair } = useMainStore().damage; switch (str) { case 'coverageUnverified': - return this.unverified; + return this.isUnverifiedVisible; case 'verifiedDeductible': - return this.verifiedDeductible; + return this.isDeductibleVisible; case 'verifiedITAC': - return this.verifiedITAC; + return this.isITACQuoteVisible; case 'verifiedNoComp': - return this.verifiedNoComp; + return this.isNoCompQuoteVisible; case 'ADASReplace': - return !this.isRepair && this.isADAS; + return !isRepair && this.isADAS; case 'nonADASReplace': - return !this.isRepair && !this.isADAS; + return !isRepair && !this.isADAS; case 'nonADASRepair': - return this.isRepair; + return isRepair; case 'deductibleOverZero': - return this.verifiedDeductible && this.deductibleValue !== 0; // TODO what if deductible is negative? + return this.isDeductibleVisible && this.deductibleValue !== 0; // TODO what if deductible is negative? case 'isDeductibleZero': - return this.verifiedDeductible && this.deductibleValue === 0; + return this.isDeductibleVisible && this.deductibleValue === 0; default: return null; } @@ -437,7 +463,8 @@ export default { }, setBaseServiceLineItems(lineItems) { this.baseServiceLineItems = lineItems; - } + }, + formatAmountInDollars } }; diff --git a/src/layouts/entry-page/entry-page.vue b/src/layouts/entry-page/entry-page.vue index 76eaee1a..29475742 100644 --- a/src/layouts/entry-page/entry-page.vue +++ b/src/layouts/entry-page/entry-page.vue @@ -123,6 +123,10 @@ export default { if (clientFlags.ClaimRegistrationRequired) { this.mainStore.issConfig.isClaimRegistrationRequired = true; } + + if (clientFlags.EnableNoCompQuote) { + this.mainStore.issConfig.enableNoCompQuote = true; + } } } catch (e) { console.error(`Error parsing client flags: ${e}`); diff --git a/src/layouts/payment-method/payment-method.spec.js b/src/layouts/payment-method/payment-method.spec.js index 9967aeb7..5d1c4eaf 100644 --- a/src/layouts/payment-method/payment-method.spec.js +++ b/src/layouts/payment-method/payment-method.spec.js @@ -3,20 +3,28 @@ import paymentMethod from '@/layouts/payment-method/payment-method.vue'; // Supporting Files import { shallowMount } from '@vue/test-utils'; +import { createTestingPinia } from '@pinia/testing'; import { getMountOptions } from '@/helpers/unit-test-helper.js'; -import { useMainStore } from '@/store'; +import { useMainStore, getDefaultState } from '@/store'; import issPageValues from '@/router/router-constants/issPage-values'; import { paymentMethods } from '@/constants/payment-method-constants'; import queryStrings from '@/constants/query-strings'; import { experimentSettings } from '@/constants/experiments'; -function setupMocks({ customMountOptions = {}, queryString }) { +function setupMocks({ customMountOptions = {}, queryString }, mainInitialState = {}, customMixin = null) { const mountOptions = getMountOptions({ ...customMountOptions, route: { query: { issPage: issPageValues.PAYMENT_METHOD, ...queryString }, params: {} } }); - const mockMixin = { + const testingPinia = createTestingPinia({ + initialState: { + main: mainInitialState + } + }); + useMainStore(testingPinia); + + const mockMixin = customMixin ?? { methods: { getSettingValue: jest.fn((settingName) => { if (settingName === experimentSettings.ISS_DISPLAY_PAY_IN_ADVANCE) { @@ -28,6 +36,7 @@ function setupMocks({ customMountOptions = {}, queryString }) { } }; + mountOptions.global.plugins = [testingPinia]; mountOptions.global.mixins = [mockMixin]; const wrapper = shallowMount(paymentMethod, mountOptions); @@ -35,31 +44,53 @@ function setupMocks({ customMountOptions = {}, queryString }) { return wrapper; } +beforeEach(() => { + const store = useMainStore(); + const defaultState = getDefaultState(); + Object.keys(defaultState).forEach((key) => { + store[key] = defaultState[key]; + }); +}); + describe('payment-method.vue', () => { describe('Payment Method Type', () => { test('getting payment method when method is pay later', async () => { - // Arrange - const wrapper = setupMocks({}); - const payLaterPaymentMethod = paymentMethods.PAY_AT_TIME_OF_SERVICE; - useMainStore().savePaymentMethodChoice(payLaterPaymentMethod); + // Arrange + const payLaterMethod = paymentMethods.PAY_AT_TIME_OF_SERVICE; + const store = { + order: { + payment: { + isPayInAdvance: false, + payInAdvanceType: null + } + } + }; + const wrapper = setupMocks({}, store); // Act const paymethod = wrapper.vm.getPaymentMethodFromStore(); // Assert - expect(paymethod).toBe(payLaterPaymentMethod); + expect(paymethod).toBe(payLaterMethod); }); test('getting payment method when method is pay in advance', async () => { - // Arrange - const wrapper = setupMocks({}); - const payInAdvancePaymentMethod = paymentMethods.CREDIT_CARD; - useMainStore().savePaymentMethodChoice(payInAdvancePaymentMethod); + // Arrange + const payInAdvanceMethod = paymentMethods.CREDIT_CARD; + const store = { + order: { + payment: { + isPayInAdvance: true, + payInAdvanceType: payInAdvanceMethod + } + } + }; + const wrapper = setupMocks({}, store); // Act const paymethod = wrapper.vm.getPaymentMethodFromStore(); // Assert - expect(paymethod).not.toBe(payInAdvancePaymentMethod); + expect(paymethod).toBe(payInAdvanceMethod); }); }); @@ -86,4 +117,138 @@ describe('payment-method.vue', () => { expect(payInAdvanceErrorAlert.exists()).toBeFalsy(); }); }); + + describe('isPayInAdvanceDisabled', () => { + let store = {}; + let mixin = { + methods: { + getSettingValue: jest.fn((settingName) => { + if (settingName === experimentSettings.ISS_DISPLAY_PAY_IN_ADVANCE) { + return 'true'; + } + return 'false'; + }) + } + }; + beforeEach(() => { + store = { + order: { + policy: { + isITAC: false, + noCoverage: false + }, + payment: { + insuranceCoverage: { + isVerified: true + } + }, + currentDeductible: 123, + policyLookupSuccessful: true + }, + issConfig: { + isClaimRegistrationRequired: true, + enableNoCompQuote: true + }, + applicationUser: { + experiments: [ + { + settings: { + ISSDisplayPIAInsurance_ISS: 'true' + } + } + ] + } + }; + }); + test('returns true when policyLookupSuccessful false', () => { + // Arrange + store.order.policyLookupSuccessful = false; + const wrapper = setupMocks({}, store, mixin); + + // Act + const result = wrapper.vm.isPayInAdvanceDisabled; + + // Assert + expect(result).toBeTruthy(); + }); + test('returns true when no comp and enableNoCompQuote false', () => { + // Arrange + store.order.policy.noCoverage = true; + store.issConfig.enableNoCompQuote = false; + const wrapper = setupMocks({}, store, mixin); + + // Act + const result = wrapper.vm.isPayInAdvanceDisabled; + + // Assert + expect(result).toBeTruthy(); + }); + test('returns true when not no comp and currentDeductible null', () => { + // Arrange + store.order.policy.noCoverage = false; + store.order.currentDeductible = null; + const wrapper = setupMocks({}, store, mixin); + + // Act + const result = wrapper.vm.isPayInAdvanceDisabled; + + // Assert + expect(result).toBeTruthy(); + }); + test('returns true when isClaimRegistrationRequired true and insurance coverage not verified', () => { + // Arrange + store.order.payment.insuranceCoverage.isVerified = false; + store.issConfig.isClaimRegistrationRequired = true; + const wrapper = setupMocks({}, store, mixin); + + // Act + const result = wrapper.vm.isPayInAdvanceDisabled; + + // Assert + expect(result).toBeTruthy(); + }); + test('returns false when no comp, enableNoCompQuote true, and currentDeductible null and pia enabled', () => { + // Arrange + store.order.policy.noCoverage = true; + store.issConfig.enableNoCompQuote = true; + store.order.currentDeductible = null; + const wrapper = setupMocks({}, store, mixin); + + // Act + const result = wrapper.vm.isPayInAdvanceDisabled; + + // Assert + expect(result).toBeFalsy(); + }); + test('returns false when not no comp, currentDeductible not null and pia enabled', () => { + // Arrange + const wrapper = setupMocks({}, store, mixin); + + // Act + const result = wrapper.vm.isPayInAdvanceDisabled; + + // Assert + expect(result).toBeFalsy(); + }); + test('returns true when pia not enabled', () => { + // Arrange + mixin = { + methods: { + getSettingValue: jest.fn((settingName) => { + if (settingName === experimentSettings.ISS_DISPLAY_PAY_IN_ADVANCE) { + return 'false'; + } + return 'true'; + }) + } + }; + const wrapper = setupMocks({}, store, mixin); + + // Act + const result = wrapper.vm.isPayInAdvanceDisabled; + + // Assert + expect(result).toBeTruthy(); + }); + }); }); diff --git a/src/layouts/payment-method/payment-method.vue b/src/layouts/payment-method/payment-method.vue index f6ca964f..cb5605a5 100644 --- a/src/layouts/payment-method/payment-method.vue +++ b/src/layouts/payment-method/payment-method.vue @@ -129,12 +129,10 @@ export default { let hasBailedOut = false; const pricedVaps = await useMainStore().getPriceOrderItems(unpricedVaps) .catch((err) => { - useMainStore().setBailout( - bailoutMessage.pricingResponseError( - unpricedVaps.map((li) => li.partNumber), - { code: err.code, message: err.message, data: err.data } - ) - ); + useMainStore().setBailout(bailoutMessage.pricingResponseError( + unpricedVaps.map((li) => li.partNumber), + { code: err.code, message: err.message, data: err.data } + )); hasBailedOut = true; next(`/?issPage=${issPageValues.BAILOUT_PAGE}`); }); @@ -179,11 +177,7 @@ export default { const piaExperience = this.getSettingValue(experimentSettings.ISS_DISPLAY_PAY_IN_ADVANCE); const isEnabled = piaExperience === 'true'; - return !isEnabled || this.isUnverified; - }, - isUnverified() { - return !useMainStore().isNoComp && !useMainStore().isITAC - && (useMainStore().order.currentDeductible == null || !useMainStore().isVerifiedCoverageStatus); + return !isEnabled || useMainStore().isUnverified; }, paymentMethod() { return this.paymentMethodInternalModel; diff --git a/src/store/index.js b/src/store/index.js index d6d8fa39..9e06815c 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -242,7 +242,8 @@ export const getDefaultState = () => ({ policyZipCode: null, dateOfLoss: null }, - siteType: null + siteType: null, + enableNoCompQuote: false } }); @@ -280,8 +281,26 @@ export const useMainStore = defineStore({ isClaimAlreadyRegistered: (state) => state.order.payment.insuranceCoverage.claimNumber !== null, isBailout: (state) => state.applicationUser.pageData[issPageValues.BAILOUT_PAGE] != null, bailoutCode: (state) => state.applicationUser.pageData[issPageValues.BAILOUT_PAGE]?.bailoutCode, - isNoComp: (state) => !!state.order.policy.noCoverage, + isNoComp: (s) => !!s.order.policy.noCoverage, isITAC: (state) => !!state.order.policy.isITAC, + isUnverified: (s) => { + const { policyLookupSuccessful, payment, currentDeductible } = s.order; + const registerClaimSuccessful = !!payment.insuranceCoverage.isVerified; + if (!policyLookupSuccessful) { + return true; + } + if (s.isNoComp && !s.issConfig.enableNoCompQuote) { + return true; + } + if (!s.isNoComp && currentDeductible == null) { + return true; + } + if (s.isClaimRegistrationRequired && !registerClaimSuccessful) { + return true; + } + return false; + }, + // TODO condense verification logic isVerifiedCoverageStatus: (state) => state.order.payment.insuranceCoverage.coverageStatus === coverageStatuses.VERIFIED, eventBusItem: (state) => (eventCategory, eventSubCategory) => { const matchedEvent = state.applicationUser.eventBus.find(({ category, subCategory }) => category === eventCategory && subCategory === eventSubCategory); @@ -1691,6 +1710,7 @@ export const useMainStore = defineStore({ this.issConfig.disabledFields.policyZipCode = false; this.issConfig.disabledFields.dateOfLoss = false; this.issConfig.siteType = null; + this.issConfig.enableNoCompQuote = false; this.issConfig.billToAccountNumber = null; this.issConfig.itacCashBillToNumber = null; this.issConfig.itacFnrBillToNumber = null; @@ -2251,13 +2271,13 @@ export const useMainStore = defineStore({ setBailout(bailoutData) { const params = new URL(document.location.toString()).searchParams; - const currentPage = params.get('issPage'); + const currentPage = params.get('issPage'); this.updatePageData({ page: issPageValues.BAILOUT_PAGE, data: { url: window.location.href, - page: currentPage || 'Unknown Page', + page: currentPage || 'Unknown Page', bailoutCode: bailoutData.code, errorMessage: bailoutData.message, submit: false diff --git a/src/store/store.spec.js b/src/store/store.spec.js index 6499d98a..c08b9dcf 100644 --- a/src/store/store.spec.js +++ b/src/store/store.spec.js @@ -1465,6 +1465,79 @@ describe('Store', () => { }); }); + describe('isUnverified', () => { + beforeEach(() => { + store.order.policy.isITAC = false; + store.order.policy.noCoverage = false; + store.order.payment.insuranceCoverage.isVerified = true; + store.order.currentDeductible = 123; + store.order.policyLookupSuccessful = true; + store.issConfig.isClaimRegistrationRequired = true; + store.issConfig.enableNoCompQuote = true; + }); + it('returns true when policyLookupSuccessful false', () => { + // Arrange + store.order.policyLookupSuccessful = false; + + // Act + const result = store.isUnverified; + + // Assert + expect(result).toBeTruthy(); + }); + it('returns true when no comp and enableNoCompQuote false', () => { + // Arrange + store.order.policy.noCoverage = true; + store.issConfig.enableNoCompQuote = false; + + // Act + const result = store.isUnverified; + + // Assert + expect(result).toBeTruthy(); + }); + it('returns true when not no comp and currentDeductible null', () => { + // Arrange + store.order.policy.noCoverage = false; + store.order.currentDeductible = null; + + // Act + const result = store.isUnverified; + + // Assert + expect(result).toBeTruthy(); + }); + it('returns true when isClaimRegistrationRequired true and insurance coverage not verified', () => { + // Arrange + store.order.payment.insuranceCoverage.isVerified = false; + + // Act + const result = store.isUnverified; + + // Assert + expect(result).toBeTruthy(); + }); + it('returns false when no comp, enableNoCompQuote true, and currentDeductible null', () => { + // Arrange + store.order.policy.noCoverage = true; + store.order.currentDeductible = null; + store.issConfig.enableNoCompQuote = true; + + // Act + const result = store.isUnverified; + + // Assert + expect(result).toBeFalsy(); + }); + it('returns false when not no comp, currentDeductible not null', () => { + // Act + const result = store.isUnverified; + + // Assert + expect(result).toBeFalsy(); + }); + }); + describe('isMobileAppointment', () => { it('Should return true for mobile appointments', () => { // Arrange