From 0ae599c35ebe7fd9b38c04077dbe88dce6142c55 Mon Sep 17 00:00:00 2001 From: Leah Schumann Date: Tue, 31 Oct 2023 06:37:55 -0400 Subject: [PATCH 1/5] Removed LineItemUtilities as it is no longer needed --- src/fmg-components/cart/cart.vue | 2 -- src/layouts/payment-method/payment-method.vue | 2 ++ src/store/index.js | 9 --------- 3 files changed, 2 insertions(+), 11 deletions(-) diff --git a/src/fmg-components/cart/cart.vue b/src/fmg-components/cart/cart.vue index 440823f67..8cf8a2e56 100644 --- a/src/fmg-components/cart/cart.vue +++ b/src/fmg-components/cart/cart.vue @@ -78,7 +78,6 @@ import { getHighestFullySatisfiedTier, getPackageContents } from "@/helpers/serv import textLink from "@/ux-components/text-link/text-link"; import textBlock from "@/digital-components/text-block/text-block"; -import { LineItemUtilities } from "@/store"; import { deepClone } from "@/helpers/object-helper"; import { partTypeStrings } from "@/constants/part-type-strings"; import { cartItemCategories } from "@/constants/cart-item-categories"; @@ -101,7 +100,6 @@ export default { currency: "USD", }), lineItems: deepClone(this.modelValue), - lineItemUtilities: new LineItemUtilities(), }; }, methods: { diff --git a/src/layouts/payment-method/payment-method.vue b/src/layouts/payment-method/payment-method.vue index 25715b39f..ba1424542 100644 --- a/src/layouts/payment-method/payment-method.vue +++ b/src/layouts/payment-method/payment-method.vue @@ -174,6 +174,8 @@ export default { false ); + // Match all available line items to the line items as they are in the store + // and rebuild the original structure. const lineItems = mapTaxedAvailableLineItemsToStoreFormat( availableLineItems, lineItemsFromStore diff --git a/src/store/index.js b/src/store/index.js index 0e556059d..a7e9be549 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -2554,15 +2554,6 @@ function addTaxesToPricedLineItems(pricedLineItems, taxingLineItems = []) { return pricedLineItems; } -export class LineItemUtilities { - constructor() { - this.getArrayOfAllLineItems = getArrayOfAllLineItems; - this.getFlattenedArrayOfLineItemsWithChildParts = - getFlattenedArrayOfLineItemsWithChildParts; - this.addGuidToLineItemsIfNotAlreadyThere = addGuidToLineItemsIfNotAlreadyThere; - } -} - export function mapTaxedAvailableLineItemsToStoreFormat(availableLineItems, storeLineItems) { // clone the lineItems array because what we're passing in is referencing the store directly const lineItems = deepClone(storeLineItems); From 5d926de12fdf2b915fed9ee3dceee205bded6e6f Mon Sep 17 00:00:00 2001 From: Leah Schumann Date: Tue, 31 Oct 2023 10:06:47 -0400 Subject: [PATCH 2/5] Started working on unit tests --- src/fmg-components/cart/cart.spec.js | 345 +++++++++++++++++++++++++++ src/fmg-components/cart/cart.vue | 14 +- 2 files changed, 355 insertions(+), 4 deletions(-) create mode 100644 src/fmg-components/cart/cart.spec.js diff --git a/src/fmg-components/cart/cart.spec.js b/src/fmg-components/cart/cart.spec.js new file mode 100644 index 000000000..1751e1f3f --- /dev/null +++ b/src/fmg-components/cart/cart.spec.js @@ -0,0 +1,345 @@ +// Components +import cart from "@/fmg-components/cart/cart.vue"; + +// Supporting Files +import { shallowMount } from "@vue/test-utils"; +import { getMountOptions } from "@/helpers/unit-test-helper.js"; + +describe("cart.vue", () => { + describe("cartItem computeds", () => { + + test("if there are one or more front wipers on the order, a front wiper cart item should be added to the cart", () => { + // Arrange + const lineItems = { + glassParts: [], + supportingItems: [], + vaps: [ + { + cartItemType: "FRONT WIPERS", + description: "WIPER BLADE STANDARD 18\"", + kitPrice: 0, + laborAmount: 0, + partNumber: "WB18", + partType: "FRONT WIPER", + salesTax: 2.44, + sellingPrice: 32.49 + }, + { + cartItemType: "FRONT WIPERS", + description: "WIPER BLADE STANDARD 26\"", + kitPrice: 0, + laborAmount: 0, + partNumber: "WB26", + partType: "FRONT WIPER", + salesTax: 2.44, + sellingPrice: 32.49 + }], + promos: [], + } + + const availableLineItems = []; + + // Act + const { wrapper } = setupMocks({ + props: { + modelValue: lineItems, + availableLineItems: availableLineItems + }, + }); + + // Assert + expect(wrapper.vm.frontWipersCartItem).not.toBeNull(); + expect(wrapper.vm.frontWipersCartItem.subTotal).toEqual(64.98); + expect(wrapper.vm.frontWipersCartItem.salesTax).toEqual(4.88); + + const found = wrapper.vm.cartItems.findIndex(cartItem => cartItem == wrapper.vm.frontWipersCartItem) >= 0; + expect(found).toBe(true); + }); + + test("if there are one or more rear wipers on the order, a rear wiper cart item should be added to the cart", () => { + // Arrange + const lineItems = { + glassParts: [], + supportingItems: [], + vaps: [ + { + cartItemType: "REAR WIPERS", + description: "REAR WIPER BLADE STANDARD 18\"", + kitPrice: 0, + laborAmount: 0, + partNumber: "EWB18", + partType: "REAR WIPER", + salesTax: 2.44, + sellingPrice: 32.49 + }, + { + cartItemType: "REAR WIPERS", + description: "REAR WIPER BLADE STANDARD 26\"", + kitPrice: 0, + laborAmount: 0, + partNumber: "RWB26", + partType: "REAR WIPER", + salesTax: 2.44, + sellingPrice: 32.49 + }], + promos: [], + } + + const availableLineItems = []; + + // Act + const { wrapper } = setupMocks({ + props: { + modelValue: lineItems, + availableLineItems: availableLineItems + }, + }); + + // Assert + expect(wrapper.vm.rearWipersCartItem).not.toBeNull(); + expect(wrapper.vm.rearWipersCartItem.subTotal).toEqual(64.98); + expect(wrapper.vm.rearWipersCartItem.salesTax).toEqual(4.88); + + const found = wrapper.vm.cartItems.findIndex(cartItem => cartItem == wrapper.vm.rearWipersCartItem) >= 0; + expect(found).toBe(true); + }); + + test("if there is Rain Defense on the order, a rain defense cart item should be added to the cart", () => { + // Arrange + const lineItems = { + glassParts: [], + supportingItems: [], + vaps: [ + { + cartItemType: "RAIN DEFENSE", + description: null, + kitPrice: 0, + laborAmount: 0, + listPrice: "44.99", + partNumber: "RAIN DEFENSE", + partType: "RAIN DEFENSE", + salesTax: 3.37, + sellingPrice: 44.99 + }], + promos: [], + } + + const availableLineItems = []; + + // Act + const { wrapper } = setupMocks({ + props: { + modelValue: lineItems, + availableLineItems: availableLineItems + }, + }); + + // Assert + expect(wrapper.vm.rainDefenseCartItem).not.toBeNull(); + expect(wrapper.vm.rainDefenseCartItem.subTotal).toEqual(44.99); + expect(wrapper.vm.rainDefenseCartItem.salesTax).toEqual(3.37); + + const found = wrapper.vm.cartItems.findIndex(cartItem => cartItem == wrapper.vm.rainDefenseCartItem) >= 0; + expect(found).toBe(true); + }); + + test("if there are glass parts on the order, a glass part cart item should be added to the cart but should not be displayed", () => { + // Arrange + const windshieldWithChildParts = { + canSafeliteRecalibrate: true, + childParts: [ + { + kitPrice: 0, + laborAmount: 23.55, + partNumber: "GGG FW4896", + salesTax: 1.77, + sellingPrice: 0 + } + ], + color: "Green Tint", + description: "solar, soundproofing, lane keep assist, lane departure warning system, w/adaptive cruise control", + id: "db22fd44-10dd-456f-979b-ff88cf68cca6", + kitPrice: 0, + laborAmount: 60, + partNumber: "FW04896GTYN", + partType: "WINDSHIELD", + recalibrationType: "STATIC", + requiresCapabilityQuestions: false, + requiresRecalibration: true, + salesTax: 63.86, + sellingPrice: 791.46 + } + + const lineItems = { + glassParts: [windshieldWithChildParts], + supportingItems: [], + vaps: [], + promos: [], + } + + const availableLineItems = []; + + // Act + const { wrapper } = setupMocks({ + props: { + modelValue: lineItems, + availableLineItems: availableLineItems + }, + }); + + // Assert + expect(wrapper.vm.glassPartsCartItem).not.toBeNull(); + expect(wrapper.vm.glassPartsCartItem.subTotal).toEqual(875.01); + expect(wrapper.vm.glassPartsCartItem.salesTax).toEqual(65.63); + expect(wrapper.vm.glassPartsCartItem.isDisplayed).toEqual(false); + + const found = wrapper.vm.cartItems.findIndex(cartItem => cartItem == wrapper.vm.glassPartsCartItem) >= 0; + expect(found).toBe(true); + }); + + // Recycle Fee Cart Item + test("if there is recycling fee on the order, a recycle fee cart item should be added to the cart", () => { + // Arrange + const lineItems = { + glassParts: [], + supportingItems: [{ + description: null, + id: "9ff98501-03a4-432b-884e-e4e28f884a2f", + kitPrice: 0, + laborAmount: 34.98, + partNumber: "RECYCLE FEE", + partType: "REPLACE FEE", + salesTax: 2.62, + sellingPrice: 0 + }], + vaps: [], + promos: [], + } + + const availableLineItems = []; + + // Act + const { wrapper } = setupMocks({ + props: { + modelValue: lineItems, + availableLineItems: availableLineItems + }, + }); + + // Assert + expect(wrapper.vm.recycleFeeCartItem).not.toBeNull(); + expect(wrapper.vm.recycleFeeCartItem.subTotal).toEqual(34.98); + expect(wrapper.vm.recycleFeeCartItem.salesTax).toEqual(2.62); + + const found = wrapper.vm.cartItems.findIndex(cartItem => cartItem == wrapper.vm.recycleFeeCartItem) >= 0; + expect(found).toBe(true); + }); + + // Mobile Fee Cart Item + test("if there is mobile fee on the order, a mobile fee cart item should be added to the cart", () => { + // Arrange + const lineItems = { + glassParts: [], + supportingItems: [{ + description: null, + id: "9ff98501-03a4-432b-884e-e4e28f884a2f", + kitPrice: 0, + laborAmount: 34.98, + partNumber: "MOBILE FEE", + partType: "REPLACE FEE", + salesTax: 2.62, + sellingPrice: 0 + }], + vaps: [], + promos: [], + } + + const availableLineItems = []; + + // Act + const { wrapper } = setupMocks({ + props: { + modelValue: lineItems, + availableLineItems: availableLineItems + }, + }); + + // Assert + expect(wrapper.vm.mobileFeeCartItem).not.toBeNull(); + expect(wrapper.vm.mobileFeeCartItem.subTotal).toEqual(34.98); + expect(wrapper.vm.mobileFeeCartItem.salesTax).toEqual(2.62); + + const found = wrapper.vm.cartItems.findIndex(cartItem => cartItem == wrapper.vm.mobileFeeCartItem) >= 0; + expect(found).toBe(true); + }); + + // Other Supporting Items Cart Item + test("if there are other supporting items on the order, an other supporting items cart item should be added to the cart but should not be displayed", () => { + // Arrange + const recalibrationLineItem = { + cartItemType: "SUPPORTING ITEMS", + description: null, + id: "8ab6ef9b-8620-430a-8a92-29f7d4bb8b00", + kitPrice: 0, + laborAmount: 450, + partNumber: "RECAL STATIC", + partType: "RECALIBRATION", + salesTax: 33.75, + sellingPrice: 0 + } + + const lineItems = { + glassParts: [], + supportingItems: [recalibrationLineItem], + vaps: [], + promos: [], + } + + const availableLineItems = []; + + // Act + const { wrapper } = setupMocks({ + props: { + modelValue: lineItems, + availableLineItems: availableLineItems + }, + }); + + // Assert + expect(wrapper.vm.otherSupportingItemsCartItem).not.toBeNull(); + expect(wrapper.vm.otherSupportingItemsCartItem.subTotal).toEqual(450); + expect(wrapper.vm.otherSupportingItemsCartItem.salesTax).toEqual(33.75); + expect(wrapper.vm.otherSupportingItemsCartItem.isDisplayed).toEqual(false); + + const found = wrapper.vm.cartItems.findIndex(cartItem => cartItem == wrapper.vm.otherSupportingItemsCartItem) >= 0; + expect(found).toBe(true); + }); + + }); + +}) + +function setupMocks({ + options, + props, +}) { + const mountOptions = getMountOptions({ + ...options, + }); + + const mockBaseMixin = { + methods: { + getTierOnePackagePrice: jest.fn(), + filterOutFees: jest.fn(), + getCmsContent: jest.fn(), + }, + }; + + if (props) mountOptions.propsData = props; + + mountOptions.global.mixins = [mockBaseMixin]; + + const wrapper = shallowMount(cart, mountOptions); + + return { wrapper }; +} \ No newline at end of file diff --git a/src/fmg-components/cart/cart.vue b/src/fmg-components/cart/cart.vue index 8cf8a2e56..0e32ee4b1 100644 --- a/src/fmg-components/cart/cart.vue +++ b/src/fmg-components/cart/cart.vue @@ -73,12 +73,18 @@