diff --git a/src/iss-components/cart-dropdown/cart-dropdown.spec.js b/src/iss-components/cart-dropdown/cart-dropdown.spec.js index 30ee04a9..ab749535 100644 --- a/src/iss-components/cart-dropdown/cart-dropdown.spec.js +++ b/src/iss-components/cart-dropdown/cart-dropdown.spec.js @@ -8,6 +8,7 @@ import { useMainStore } from '@/store'; import coverageStatuses from '@/constants/coverage-statuses'; import { formatAmountInDollars } from '@/helpers/text-helper.js'; import partTypeStrings from '@/constants/part-type-strings'; +import partNumberStrings from '@/constants/part-number-strings'; import { getHighestFullySatisfiedTier, getPackageContents } from '@/helpers/service-package-helper.js'; import getPriceOfLineItems from '@/helpers/price-calculator.js'; @@ -141,9 +142,42 @@ describe('cart-dropdown component', () => { // Assert expect(servicePackage.exists()).toBeTruthy(); }); - // TODO finish tests - test.skip('non service package cart items', () => { }); - test.skip('recycle cart item label when isRecycle true for some cart item', () => { }); + test('non service package cart items', () => { + // Arrange + const reference = '#non-packaged-cart-items'; + const isExpanded = true; + const initialData = { isExpanded }; + const { wrapper } = getMountedComponent({}, {}, initialData); + + // Act + const nonPackagedCartItems = wrapper.find(reference); + + // Assert + expect(nonPackagedCartItems.exists()).toBeTruthy(); + }); + test('recycle cart item label when isRecycle true for some cart item', () => { + // Arrange + const reference = '#recycle-fee-label'; + const isExpanded = true; + const initialPropsData = { isExpanded }; + const storeData = { + order: { + lineItems: { + supportingItems: [ + { partNumber: partNumberStrings.RECYCLE_FEE } + ] + } + } + }; + const { wrapper } = getMountedComponent(storeData, {}, initialPropsData); + + // Act + const recycleFeeLabel = wrapper.find(reference); + + // Assert + expect(wrapper.vm.recycleFeeCartItem).not.toBeNull(); + expect(recycleFeeLabel.exists()).toBeTruthy(); + }); test('cart footer', () => { // Arrange const reference = '#cart-footer'; @@ -183,47 +217,6 @@ describe('cart-dropdown component', () => { // Assert expect(salesTax.exists()).toBeTruthy(); }); - // TODO remove - test('recycle fee when preset in supported items', () => { - // Arrange - const reference = '#recycle-fee-item'; - const { wrapper } = getMountedComponent({ - order: { - lineItems: { - supportingItems: [{ - partNumber: partTypeStrings.RECYCLE_FEE - }] - } - } - }); - - // Act - const recycleFee = wrapper.find(reference); - - // Assert - expect(wrapper.vm.recycleFeeCartItem).not.toBeNull(); - expect(recycleFee.exists()).toBeTruthy(); - }); - // TODO remove - test('mobile fee when preset', () => { - // Arrange - const reference = '#mobile-fee-item'; - const { wrapper } = getMountedComponent({ - order: { - lineItems: { - supportingItems: [], - mobileFee: {} - } - } - }); - - // Act - const mobileFee = wrapper.find(reference); - - // Assert - expect(wrapper.vm.mobileFeeCartItem).not.toBeNull(); - expect(mobileFee.exists()).toBeTruthy(); - }); test('bottom amount due', () => { // Arrange const reference = '#bottom-amount-due'; @@ -289,46 +282,26 @@ describe('cart-dropdown component', () => { // Assert expect(cartBasePrice.exists()).toBeFalsy(); }); - // TODO finish test - test.skip('recycle cart item label when isRecycle false for all cart items', () => { }); - // TODO remove - test('recycle fee when not in supported items', () => { + test('recycle cart item label when isRecycle false for all cart items', () => { // Arrange - const reference = '#recycle-fee-item'; - const { wrapper } = getMountedComponent({ + const reference = '#recycle-fee-label'; + const isExpanded = true; + const initialPropsData = { isExpanded }; + const storeData = { order: { lineItems: { supportingItems: [] } } - }); + }; + const { wrapper } = getMountedComponent(storeData, {}, initialPropsData); // Act - const recycleFee = wrapper.find(reference); + const recycleFeeLabel = wrapper.find(reference); // Assert expect(wrapper.vm.recycleFeeCartItem).toBeNull(); - expect(recycleFee.exists()).toBeFalsy(); - }); - // TODO remove - test('mobile fee when not in supported items', () => { - // Arrange - const reference = '#mobile-fee-item'; - const { wrapper } = getMountedComponent({ - order: { - lineItems: { - supportingItems: [], - mobileFee: null - } - } - }); - - // Act - const mobileFee = wrapper.find(reference); - - // Assert - expect(wrapper.vm.mobileFeeCartItem).toBeNull(); - expect(mobileFee.exists()).toBeFalsy(); + expect(recycleFeeLabel.exists()).toBeFalsy(); }); }); describe('computed', () => { @@ -459,14 +432,172 @@ describe('cart-dropdown component', () => { // TODO when subTotal and salesTax are finished }); }); - describe.skip('subTotal', () => { - test('when not no comp and not itac, includes deductible price', () => {}); - test('when no comp, includes base service price', () => {}); - test('when ITAC, includes base service price', () => {}); - test('no issue when nonServicePackageCartItems null', () => {}); - test('when nonServicePackageCartItems non empty, sums appropriately', () => {}); - test('when deductible included, sums all prices appropriately', () => {}); - test('when base service price included, sums all prices appropriately', () => {}); + describe('subTotal', () => { + test('when not no comp and not itac, includes deductible price', () => { + // Arrange + const deductiblePrice = 872; + const baseServicePrice = 43; + getPriceOfLineItems.mockImplementation(() => baseServicePrice); + const storeData = { + order: { + policy: { + noCoverage: false, + isITAC: false + }, + currentDeductible: deductiblePrice + } + }; + const { wrapper } = getMountedComponent(storeData); + + // Act + const result = wrapper.vm.subTotal; + + // Assert + expect(result).toBe(deductiblePrice); + }); + test('when no comp, includes base service price', () => { + // Arrange + const deductiblePrice = 872; + const baseServicePrice = 43; + getPriceOfLineItems.mockImplementation(() => baseServicePrice); + const storeData = { + order: { + policy: { + noCoverage: true, + isITAC: false + }, + currentDeductible: deductiblePrice + } + }; + const { wrapper } = getMountedComponent(storeData); + + // Act + const result = wrapper.vm.subTotal; + + // Assert + expect(result).toBe(baseServicePrice); + }); + test('when ITAC, includes base service price', () => { + // Arrange + const deductiblePrice = 872; + const baseServicePrice = 43; + getPriceOfLineItems.mockImplementation(() => baseServicePrice); + const storeData = { + order: { + policy: { + noCoverage: false, + isITAC: true + }, + currentDeductible: deductiblePrice + } + }; + const { wrapper } = getMountedComponent(storeData); + + // Act + const result = wrapper.vm.subTotal; + + // Assert + expect(result).toBe(baseServicePrice); + }); + test('when nonServicePackageCartItems non empty, sums appropriately', () => { + // Arrange + const deductiblePrice = 0; + const subTotal = 34; + getPriceOfLineItems.mockImplementation(() => subTotal); + const storeData = { + order: { + policy: { + noCoverage: false, + isITAC: false + }, + currentDeductible: deductiblePrice, + lineItems: { + vaps: [ + { + partType: partTypeStrings.FRONT_WIPER + }, + { + partType: partTypeStrings.REAR_WIPER + } + ] + } + } + }; + const { wrapper } = getMountedComponent(storeData); + const expectedPrice = 68; + + // Act + const result = wrapper.vm.subTotal; + + // Assert + expect(result).toBe(expectedPrice); + }); + test('when deductible included, sums all prices appropriately', () => { + // Arrange + const deductiblePrice = 54; + const subTotal = 34; + getPriceOfLineItems.mockImplementation(() => subTotal); + const storeData = { + order: { + policy: { + noCoverage: false, + isITAC: false + }, + currentDeductible: deductiblePrice, + lineItems: { + vaps: [ + { + partType: partTypeStrings.FRONT_WIPER + }, + { + partType: partTypeStrings.REAR_WIPER + } + ] + } + } + }; + const { wrapper } = getMountedComponent(storeData); + const expectedPrice = 122; + + // Act + const result = wrapper.vm.subTotal; + + // Assert + expect(result).toBe(expectedPrice); + }); + test('when base service price included, sums all prices appropriately', () => { + // Arrange + const deductiblePrice = 54; + const subTotal = 34; + getPriceOfLineItems.mockImplementation(() => subTotal); + const storeData = { + order: { + policy: { + noCoverage: true, + isITAC: false + }, + currentDeductible: deductiblePrice, + lineItems: { + vaps: [ + { + partType: partTypeStrings.FRONT_WIPER + }, + { + partType: partTypeStrings.REAR_WIPER + } + ] + } + } + }; + const { wrapper } = getMountedComponent(storeData); + const expectedPrice = 102; + + // Act + const result = wrapper.vm.subTotal; + + // Assert + expect(result).toBe(expectedPrice); + }); }); describe.skip('salesTax', () => {}); describe('availableLineItems', () => { @@ -782,17 +913,266 @@ describe('cart-dropdown component', () => { })); }); }); - describe.skip('nonServicePackageCartItems', () => { - test('when recycleFee, includes recycle fee', () => {}); - test('when mobileFee, includes mobile fee', () => {}); - test('front wiper not included when front wiper in service package', () => {}); - test('rear wiper not included when rear wiper in service package', () => {}); - test('rain defense not included when rain defense in service package', () => {}); - test('front wiper included when not in service package and in vaps', () => {}); - test('rear wiper included when not in service package and in vaps', () => {}); - test('rain defense included when not in service package and in vaps', () => {}); - test('item in vaps outside front wiper, rear wiper, and rain defense never included', () => {}); - test('returns expected when multiple variables apply', () => {}); + describe('nonServicePackageCartItems', () => { + test('when recycleFee, includes recycle fee', () => { + // Arrange + const storeData = { + order: { + lineItems: { + supportingItems: [ + { + partNumber: partNumberStrings.RECYCLE_FEE + } + ] + } + } + }; + const { wrapper } = getMountedComponent(storeData); + + // Act + const result = wrapper.vm.nonServicePackageCartItems; + + // Assert + expect(result).toContainEqual(expect.objectContaining({ + isRecycle: true + })); + }); + test('when mobileFee, includes mobile fee', () => { + // Arrange + const storeData = { + order: { + lineItems: { + mobileFee: { + partType: partTypeStrings.MOBILE_FEE + } + } + } + }; + const { wrapper } = getMountedComponent(storeData); + + // Act + const result = wrapper.vm.nonServicePackageCartItems; + + // Assert + expect(result).toContainEqual(expect.objectContaining({ + partType: partTypeStrings.MOBILE_FEE + })); + }); + test('front wiper not included when front wiper in service package', () => { + // Arrange + getPriceOfLineItems.mockImplementation(() => 123); + getPackageContents.mockImplementationOnce(() => [partTypeStrings.FRONT_WIPER]); + const storeData = { + order: { + lineItems: { + vaps: [ + { + partType: partTypeStrings.FRONT_WIPER + } + ] + } + } + }; + const { wrapper } = getMountedComponent(storeData); + + // Act + const result = wrapper.vm.nonServicePackageCartItems; + + // Assert + expect(result).not.toContainEqual(expect.objectContaining({ + partType: partTypeStrings.FRONT_WIPER + })); + }); + test('rear wiper not included when rear wiper in service package', () => { + // Arrange + getPriceOfLineItems.mockImplementation(() => 123); + getPackageContents.mockImplementationOnce(() => [partTypeStrings.REAR_WIPER]); + const storeData = { + order: { + lineItems: { + vaps: [ + { + partType: partTypeStrings.REAR_WIPER + } + ] + } + } + }; + const { wrapper } = getMountedComponent(storeData); + + // Act + const result = wrapper.vm.nonServicePackageCartItems; + + // Assert + expect(result).not.toContainEqual(expect.objectContaining({ + partType: partTypeStrings.REAR_WIPER + })); + }); + test('rain defense not included when rain defense in service package', () => { + // Arrange + getPriceOfLineItems.mockImplementation(() => 123); + getPackageContents.mockImplementationOnce(() => [partTypeStrings.RAIN_DEFENSE]); + const storeData = { + order: { + lineItems: { + vaps: [ + { + partType: partTypeStrings.RAIN_DEFENSE + } + ] + } + } + }; + const { wrapper } = getMountedComponent(storeData); + + // Act + const result = wrapper.vm.nonServicePackageCartItems; + + // Assert + expect(result).not.toContainEqual(expect.objectContaining({ + partType: partTypeStrings.RAIN_DEFENSE + })); + }); + test('front wiper included when not in service package and in vaps', () => { + // Arrange + getPriceOfLineItems.mockImplementation(() => 123); + getPackageContents.mockImplementationOnce(() => []); + const storeData = { + order: { + lineItems: { + vaps: [ + { + partType: partTypeStrings.FRONT_WIPER + } + ] + } + } + }; + const { wrapper } = getMountedComponent(storeData); + + // Act + const result = wrapper.vm.nonServicePackageCartItems; + + // Assert + expect(result).toContainEqual(expect.objectContaining({ + partType: partTypeStrings.FRONT_WIPER + })); + }); + test('rear wiper included when not in service package and in vaps', () => { + // Arrange + getPriceOfLineItems.mockImplementation(() => 123); + getPackageContents.mockImplementationOnce(() => []); + const storeData = { + order: { + lineItems: { + vaps: [ + { + partType: partTypeStrings.REAR_WIPER + } + ] + } + } + }; + const { wrapper } = getMountedComponent(storeData); + + // Act + const result = wrapper.vm.nonServicePackageCartItems; + + // Assert + expect(result).toContainEqual(expect.objectContaining({ + partType: partTypeStrings.REAR_WIPER + })); + }); + test('rain defense included when not in service package and in vaps', () => { + // Arrange + getPriceOfLineItems.mockImplementation(() => 123); + getPackageContents.mockImplementationOnce(() => []); + const storeData = { + order: { + lineItems: { + vaps: [ + { + partType: partTypeStrings.RAIN_DEFENSE + } + ] + } + } + }; + const { wrapper } = getMountedComponent(storeData); + + // Act + const result = wrapper.vm.nonServicePackageCartItems; + + // Assert + expect(result).toContainEqual(expect.objectContaining({ + partType: partTypeStrings.RAIN_DEFENSE + })); + }); + test('item in vaps outside front wiper, rear wiper, and rain defense never included', () => { + // Arrange + getPriceOfLineItems.mockImplementation(() => 123); + getPackageContents.mockImplementationOnce(() => []); + const storeData = { + order: { + lineItems: { + vaps: [ + { + partType: partTypeStrings.RECALIBRATION + } + ] + } + } + }; + const { wrapper } = getMountedComponent(storeData); + + // Act + const result = wrapper.vm.nonServicePackageCartItems; + + // Assert + expect(result).not.toContainEqual(expect.objectContaining({ + partType: partTypeStrings.RECALIBRATION + })); + }); + test('returns expected when multiple variables apply', () => { + // Arrange + getPriceOfLineItems.mockImplementation(() => 123); + getPackageContents.mockImplementationOnce(() => [partTypeStrings.FRONT_WIPER]); + const storeData = { + order: { + lineItems: { + supportingItems: [ + { + partNumber: partNumberStrings.RECYCLE_FEE + } + ], + mobileFee: { + partType: partTypeStrings.MOBILE_FEE + }, + vaps: [ + { partType: partTypeStrings.RECALIBRATION }, + { partType: partTypeStrings.FRONT_WIPER }, + { partType: partTypeStrings.REAR_WIPER } + ] + } + } + }; + const { wrapper } = getMountedComponent(storeData); + + // Act + const result = wrapper.vm.nonServicePackageCartItems; + + // Assert + expect(result.length).toBe(3); + expect(result).toContainEqual(expect.objectContaining({ + isRecycle: true + })); + expect(result).toContainEqual(expect.objectContaining({ + partType: partTypeStrings.MOBILE_FEE + })); + expect(result).toContainEqual(expect.objectContaining({ + partType: partTypeStrings.REAR_WIPER + })); + }); }); describe('servicePackageLabelWidget', () => { test.each([ @@ -941,7 +1321,7 @@ describe('cart-dropdown component', () => { const storeData = { order: { lineItems: { - supportingItems: [{ partNumber: partTypeStrings.RECYCLE_FEE }] + supportingItems: [{ partNumber: partNumberStrings.RECYCLE_FEE }] } } }; @@ -1016,13 +1396,90 @@ describe('cart-dropdown component', () => { expect(result.name).toBe(expectedName); }); }); - describe.only('packagePrice', () => { - test('returns 0 when servicePackageCartItems is null', () => { + describe('packagePrice', () => { + test('returns 0 when servicePackageCartItems is empty', () => { + // Arrange + getPriceOfLineItems.mockImplementation(() => 123); + getPackageContents.mockImplementationOnce(() => []); + const storeData = { + order: { + lineItems: { + vaps: [ + { + partType: partTypeStrings.REAR_WIPER + } + ] + } + } + }; + const { wrapper } = getMountedComponent(storeData); + // Act + const result = wrapper.vm.packagePrice; + + // Assert + expect(result).toBe(0); + }); + test('returns expected when servicePackageCartItems not empty', () => { + // Arrange + const rearPrice = 101; + const frontPrice = 9; + getPriceOfLineItems.mockImplementation((lineItems) => { + if (lineItems.some((item) => item.partType === partTypeStrings.FRONT_WIPER)) { + return frontPrice; + } + if (lineItems.some((item) => item.partType === partTypeStrings.REAR_WIPER)) { + return rearPrice; + } + return 1; + }); + getPackageContents.mockImplementationOnce(() => [partTypeStrings.FRONT_WIPER, partTypeStrings.REAR_WIPER]); + const storeData = { + order: { + lineItems: { + vaps: [ + { partType: partTypeStrings.FRONT_WIPER }, + { partType: partTypeStrings.REAR_WIPER } + ] + } + } + }; + const { wrapper } = getMountedComponent(storeData); + const expectedPrice = 110; + + // Act + const result = wrapper.vm.packagePrice; + + // Assert + expect(result).toBe(expectedPrice); + }); + test('returns expected when servicePackageCartItems has one item', () => { + // Arrange + const frontPrice = 9; + getPriceOfLineItems.mockImplementation((lineItems) => { + if (lineItems.some((item) => item.partType === partTypeStrings.FRONT_WIPER)) { + return frontPrice; + } + return 1; + }); + getPackageContents.mockImplementationOnce(() => [partTypeStrings.FRONT_WIPER, partTypeStrings.REAR_WIPER]); + const storeData = { + order: { + lineItems: { + vaps: [ + { partType: partTypeStrings.FRONT_WIPER } + ] + } + } + }; + const { wrapper } = getMountedComponent(storeData); + + // Act + const result = wrapper.vm.packagePrice; + + // Assert + expect(result).toBe(frontPrice); }); - test('returns 0 when servicePackageCartItems is empty', () => {}); - test('returns expected when servicePackageCartItems not empty', () => {}); - test('returns expected when servicePackageCartItems has one item', () => {}); }); }); describe('method', () => { @@ -1031,12 +1488,8 @@ describe('cart-dropdown component', () => { // Arrange const storeData = { order: { - payment: { - insuranceCoverage: { - coverageStatus: coverageStatuses.VERIFIED - } - }, policy: { + noCoverage: false, isITAC: false }, currentDeductible: null @@ -1055,12 +1508,8 @@ describe('cart-dropdown component', () => { // Arrange const storeData = { order: { - payment: { - insuranceCoverage: { - coverageStatus: coverageStatuses.PENDING - } - }, policy: { + noCoverage: false, isITAC: false }, currentDeductible: 321 diff --git a/src/iss-components/cart-dropdown/cart-dropdown.vue b/src/iss-components/cart-dropdown/cart-dropdown.vue index 02554592..945c8f35 100644 --- a/src/iss-components/cart-dropdown/cart-dropdown.vue +++ b/src/iss-components/cart-dropdown/cart-dropdown.vue @@ -185,7 +185,7 @@ export default { ...(otherParts ?? []) ], deductible: currentDeductible, - isExpanded: true, // false, + isExpanded: false, widget: { amountDue: 'AmountDueTextWidget', deductible: 'DeductibleWidget', @@ -204,7 +204,7 @@ export default { return !useMainStore().isNoComp && !useMainStore().policy.isITAC; }, baseServicePrice() { - return getPriceOfLineItems(this.baseServiceLineItems); + return getPriceOfLineItems(this.baseServiceLineItems) ?? 0; }, isUnverified() { return !useMainStore().isNoComp && !useMainStore().policy.isITAC @@ -215,7 +215,7 @@ export default { ? this.deductible : this.baseServicePrice; const nonPackageCartItemsPrice = this.nonServicePackageCartItems?.reduce( - (accumulator, cartItem) => accumulator + cartItem.subTotal, + (accumulator, cartItem) => accumulator + (cartItem?.subTotal ?? 0), 0 ) ?? 0; return basePrice + nonPackageCartItemsPrice + this.packagePrice; @@ -310,7 +310,7 @@ export default { }, packagePrice() { return this.servicePackageCartItems?.reduce( - (accumulator, cartItem) => accumulator + cartItem.subTotal, + (accumulator, cartItem) => accumulator + (cartItem?.subTotal ?? 0), 0 ) ?? 0; }, @@ -382,8 +382,8 @@ export default { getDisplayed(amount, canBeVerifyingCoverage = true) { return canBeVerifyingCoverage && this.isUnverified - && !this.isNoComp - && !this.isITAC + && !useMainStore().isNoComp + && !useMainStore().policy.isITAC ? VERIFYING_COVERAGE : formatAmountInDollars(amount); }, @@ -410,7 +410,7 @@ export default { getCartItemForVapsPart(partType) { const label = this.getCmsContentForVapsType(partType); const lineItems = this.vapsInOrder - ?.filter((vapsLineItem) => vapsLineItem.partType === partType); + ?.filter((vapsLineItem) => vapsLineItem.partType === partType) ?? []; return this.getCartItem(label, lineItems, true, partType, true, false); }, removeItem(partType, isVap) {