diff --git a/package-lock.json b/package-lock.json index 8d4b6e08d..91e44113b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,6 +14,7 @@ "canvas-confetti": "^1.4.0", "core-js": "^3.6.5", "http-status-codes": "^2.1.4", + "iframe-resizer": "^4.3.7", "jest-junit": "^13.0.0", "maska": "^1.5.0", "vee-validate": "^4.5.7", @@ -11813,6 +11814,18 @@ "integrity": "sha1-xg7taebY/bazEEofy8ocGS3FtQE=", "dev": true }, + "node_modules/iframe-resizer": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/iframe-resizer/-/iframe-resizer-4.3.7.tgz", + "integrity": "sha512-a3EGVScU9NtUpj6lWvGhVw3EfOw5AopRs5xGsQU385kWdgQt++OsD6PCnTV+8YkgBu/g28rLIh0EztFg9UQr1Q==", + "engines": { + "node": ">=0.8.0" + }, + "funding": { + "type": "individual", + "url": "https://github.com/davidjbradshaw/iframe-resizer/blob/master/FUNDING.md" + } + }, "node_modules/ignore": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", @@ -33845,6 +33858,11 @@ "integrity": "sha1-xg7taebY/bazEEofy8ocGS3FtQE=", "dev": true }, + "iframe-resizer": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/iframe-resizer/-/iframe-resizer-4.3.7.tgz", + "integrity": "sha512-a3EGVScU9NtUpj6lWvGhVw3EfOw5AopRs5xGsQU385kWdgQt++OsD6PCnTV+8YkgBu/g28rLIh0EztFg9UQr1Q==" + }, "ignore": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", diff --git a/package.json b/package.json index a910ad0af..d99b971c2 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,7 @@ "canvas-confetti": "^1.4.0", "core-js": "^3.6.5", "http-status-codes": "^2.1.4", + "iframe-resizer": "^4.3.7", "jest-junit": "^13.0.0", "maska": "^1.5.0", "vee-validate": "^4.5.7", diff --git a/public/css/hop-styling.css b/public/css/hop-styling.css index 1f0b0ddc2..1c0b155a0 100644 --- a/public/css/hop-styling.css +++ b/public/css/hop-styling.css @@ -75,14 +75,11 @@ body .creditCardSpecific div { padding: 8px 0; } body .creditCardSpecific div .headerlinecontainer { - padding: 0; + display: none; } body .creditCardSpecific div label { font-weight: 500; } -body .creditCardSpecific div:first-child { - display: none; -} body .creditCardSpecific #infoRow2 { margin-bottom: 0; } diff --git a/public/scss/hop-styling.scss b/public/scss/hop-styling.scss index 0e646a591..badab0912 100644 --- a/public/scss/hop-styling.scss +++ b/public/scss/hop-styling.scss @@ -88,14 +88,11 @@ body { div { padding: 8px 0; .headerlinecontainer { - padding: 0; + display: none; } label { font-weight: 500; } - &:first-child { - display: none; - } } #infoRow2 { margin-bottom: 0; diff --git a/src/App.vue b/src/App.vue index aef77fcb0..31fb663c3 100644 --- a/src/App.vue +++ b/src/App.vue @@ -5,15 +5,33 @@ + diff --git a/src/constants/store-actions.js b/src/constants/store-actions.js index 847b14477..2cfd08a8e 100644 --- a/src/constants/store-actions.js +++ b/src/constants/store-actions.js @@ -91,6 +91,9 @@ const storeActions = { SAVE_SERVICE_LOCATION_TECH_NOTES: "saveServiceLocationTechNotes", SAVE_CCTOKEN: "saveCCToken", SAVE_PAYPAL_TOKEN: "savePaypalToken", + + CREATE_SUBMITTED_ORDER: "createSubmittedOrder", + RESET_SUBMITTED_ORDER: "resetSubmittedOrder", }; export { storeActions }; diff --git a/src/fmg-components/cart/cart.spec.js b/src/fmg-components/cart/cart.spec.js new file mode 100644 index 000000000..bfe1dbb55 --- /dev/null +++ b/src/fmg-components/cart/cart.spec.js @@ -0,0 +1,369 @@ +// 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.glassPartCartItems[0]).not.toBeNull(); + // expect(wrapper.vm.glassPartCartItems[0].subTotal).toEqual(875.01); + // expect(wrapper.vm.glassPartCartItems[0].salesTax).toEqual(65.63); + // expect(wrapper.vm.glassPartCartItems[0].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 }; +} diff --git a/src/fmg-components/cart/cart.vue b/src/fmg-components/cart/cart.vue index 440823f67..ce43971d8 100644 --- a/src/fmg-components/cart/cart.vue +++ b/src/fmg-components/cart/cart.vue @@ -73,13 +73,18 @@ + + diff --git a/src/layouts/payment/payment-switch/payment-switch.vue b/src/layouts/payment/payment-switch/payment-switch.vue new file mode 100644 index 000000000..5b72ffc39 --- /dev/null +++ b/src/layouts/payment/payment-switch/payment-switch.vue @@ -0,0 +1,99 @@ + + + + + diff --git a/src/layouts/payment/payment.vue b/src/layouts/payment/payment.vue index 2b4121c98..a8780cbc5 100644 --- a/src/layouts/payment/payment.vue +++ b/src/layouts/payment/payment.vue @@ -12,6 +12,7 @@
-
{{ switchPaymentText }}
-
- -
-
or
-
- -
-
or
-
- -
+ { + iframeResize({ checkOrigin: false }, el); + }); + }, + unmounted: function (el) { + el.iFrameResizer.removeListeners(); + }, + }, + }, async beforeRouteEnter(to, from, next) { // Call APIs const cmsContentPromise = fetchCmsContentForPage(to.query.fmgPage); @@ -480,6 +466,7 @@ export default { funnelHeader, navbar, loadingModal, + paymentSwitch, }, }; @@ -487,7 +474,7 @@ export default {