diff --git a/src/constants/part-type-strings.js b/src/constants/part-type-strings.js index 786a069d..62d5452c 100644 --- a/src/constants/part-type-strings.js +++ b/src/constants/part-type-strings.js @@ -1,4 +1,5 @@ const partTypeStrings = Object.freeze({ + WINDSHIELD: 'WINDSHIELD', FRONT_WIPER: 'FRONT WIPER', REAR_WIPER: 'REAR WIPER', RAIN_DEFENSE: 'RAIN DEFENSE', diff --git a/src/helpers/cart-helper.js b/src/helpers/cart-helper.js index 0875c5b6..724496fd 100644 --- a/src/helpers/cart-helper.js +++ b/src/helpers/cart-helper.js @@ -56,7 +56,7 @@ export function getAllLineItems(order) { * @param {object} order order object * @returns {{}|undefined} recycle fee line item or undefined */ -export function getRecycleFee(order) { +export function getRecycleFeeLineItem(order) { return getLineItems(order).feeItems?.find((lineItem) => lineItem.partNumber === partNumberStrings.RECYCLE_FEE); } @@ -65,17 +65,17 @@ export function getRecycleFee(order) { * @param {object} order order object * @returns {{}|undefined} mobile fee line item or undefined */ -export function getMobileFee(order) { +export function getMobileFeeLineItem(order) { return getLineItems(order).feeItems?.find((lineItem) => lineItem.partType === partTypeStrings.MOBILE_FEE); } /** * Returns the current deductible on the order * @param {object} order order object - * @returns {number} current deductible + * @returns {number|undefined|null} current deductible */ export function getDeductible(order) { - return order.currentDeductible ?? 0; + return order.currentDeductible; } /** @@ -111,11 +111,11 @@ export function isOrderITAC(order) { * @returns {number} sub total for the order */ export function getSubtotal(order) { - if (!isOrderNoComp(order) && !isOrderITAC(order)) { - return getDeductible(order) + getPriceOfLineItems(getNonServiceLineItems(order), false); + if (!isOrderUnverified(order) && !isOrderNoComp(order) && !isOrderITAC(order)) { + return getDeductible(order) + getPriceOfLineItems(getNonServiceLineItems(order)); } - return getPriceOfLineItems(getAllLineItems(order), false); + return getPriceOfLineItems(getAllLineItems(order)); } /** @@ -125,7 +125,7 @@ export function getSubtotal(order) { */ export function getSalesTax(order) { let tax = 0; - if (isOrderITAC(order) || isOrderNoComp(order)) { + if (!isOrderUnverified(order) && (isOrderITAC(order) || isOrderNoComp(order))) { tax += getTaxOfLineItems(getServiceLineItems(order)); } diff --git a/src/helpers/cart-helper.spec.js b/src/helpers/cart-helper.spec.js index b978f5ec..6d0898a6 100644 --- a/src/helpers/cart-helper.spec.js +++ b/src/helpers/cart-helper.spec.js @@ -3,8 +3,8 @@ import { getCartTotal, getDeductible, getLineItems, - getMobileFee, getNonServiceLineItems, - getRecycleFee, getSalesTax, + getMobileFeeLineItem, getNonServiceLineItems, + getRecycleFeeLineItem, getSalesTax, getServiceLineItems, getSubtotal, isOrderITAC, isOrderNoComp, isOrderUnverified } from '@/helpers/cart-helper'; @@ -183,7 +183,7 @@ describe('cart-helper', () => { }; // Act - const result = getRecycleFee(order); + const result = getRecycleFeeLineItem(order); // Assert expect(result).not.toBeNull(); @@ -197,7 +197,7 @@ describe('cart-helper', () => { }; // Act - const result = getRecycleFee(order); + const result = getRecycleFeeLineItem(order); // Assert expect(result).toBeUndefined(); @@ -212,7 +212,7 @@ describe('cart-helper', () => { }; // Act - const result = getMobileFee(order); + const result = getMobileFeeLineItem(order); // Assert expect(result).not.toBeNull(); @@ -226,7 +226,7 @@ describe('cart-helper', () => { }; // Act - const result = getMobileFee(order); + const result = getMobileFeeLineItem(order); // Assert expect(result).toBeUndefined(); @@ -251,35 +251,22 @@ describe('cart-helper', () => { }); describe('isOrderUnverified', () => { - test('Returns true if order has isUnverified field and is true', () => { + test.each([[false, false], [true, true]])('Returns %p when policy.isUnverified is %p', (expected, isUnverified) => { // Arrange const order = { - isUnverified: true + isUnverified }; // Act const result = isOrderUnverified(order); // Assert - expect(result).toBeTruthy(); - }); - - test('Returns false if order has isUnverified field and is false', () => { - // Arrange - const order = { - isUnverified: true - }; - - // Act - const result = isOrderUnverified(order); - - // Assert - expect(result).toBeTruthy(); + expect(result).toBe(expected); }); }); describe('isOrderNoComp', () => { - test('Returns null when policy is null', () => { + test('Returns false when policy is null', () => { // Arrange const order = {}; @@ -290,11 +277,11 @@ describe('cart-helper', () => { expect(result).toBeFalsy(); }); - test('Returns true when policy.NoCoverage is true', () => { + test.each([[false, false], [true, true]])('Returns %p when policy.NoCoverage is %p', (expected, noCoverage) => { // Arrange const order = { policy: { - noCoverage: true + noCoverage } }; @@ -302,27 +289,12 @@ describe('cart-helper', () => { const result = isOrderNoComp(order); // Assert - expect(result).toBeTruthy(); - }); - - test('Returns false when policy.NoCoverage is false', () => { - // Arrange - const order = { - policy: { - noCoverage: false - } - }; - - // Act - const result = isOrderNoComp(order); - - // Assert - expect(result).toBeFalsy(); + expect(result).toBe(expected); }); }); describe('isOrderITAC', () => { - test('Returns null when policy is null', () => { + test('Returns false when policy is null', () => { // Arrange const order = {}; @@ -333,11 +305,11 @@ describe('cart-helper', () => { expect(result).toBeFalsy(); }); - test('Returns true when policy.isITAC is true', () => { + test.each([[false, false], [true, true]])('Returns %p when policy.isITAC is %p', (expected, isITAC) => { // Arrange const order = { policy: { - isITAC: true + isITAC } }; @@ -345,22 +317,7 @@ describe('cart-helper', () => { const result = isOrderITAC(order); // Assert - expect(result).toBeTruthy(); - }); - - test('Returns false when policy.isITAC is false', () => { - // Arrange - const order = { - policy: { - isITAC: false - } - }; - - // Act - const result = isOrderITAC(order); - - // Assert - expect(result).toBeFalsy(); + expect(result).toBe(expected); }); }); @@ -368,6 +325,7 @@ describe('cart-helper', () => { test('Returns 0 when there are null items', () => { // Arrange const order = { + isUnverified: false, policy: { noCoverage: true }, @@ -384,6 +342,7 @@ describe('cart-helper', () => { test('Returns 0 when there are no items', () => { // Arrange const order = { + isUnverified: false, policy: { noCoverage: true }, @@ -397,9 +356,10 @@ describe('cart-helper', () => { expect(result).toBe(0); }); - test('Returns sub total of deductible + vaps + fee line items', () => { + test('Returns sub total of deductible + vaps + fee line items when verified deductible', () => { // Arrange const order = { + isUnverified: false, policy: { noCoverage: false, isITAC: false @@ -415,9 +375,10 @@ describe('cart-helper', () => { expect(result).toBe(310); }); - test('Returns sub total of all line items when no comp', () => { + test('Returns sub total of all line items when verified no comp', () => { // Arrange const order = { + isUnverified: false, policy: { noCoverage: true, isITAC: false @@ -433,9 +394,10 @@ describe('cart-helper', () => { expect(result).toBe(330); }); - test('Returns sub total of all line items when ITAC', () => { + test('Returns sub total of all line items when verified ITAC', () => { // Arrange const order = { + isUnverified: false, policy: { noCoverage: false, isITAC: true @@ -456,6 +418,7 @@ describe('cart-helper', () => { test('Returns 0 when there are null items', () => { // Arrange const order = { + isUnverified: false, policy: { noCoverage: true }, @@ -472,6 +435,7 @@ describe('cart-helper', () => { test('Returns 0 when there are no items', () => { // Arrange const order = { + isUnverified: false, policy: { noCoverage: true }, @@ -485,9 +449,10 @@ describe('cart-helper', () => { expect(result).toBe(0); }); - test('Returns sales tax vaps + fee line items', () => { + test('Returns sales tax vaps + fee line items when verified', () => { // Arrange const order = { + isUnverified: false, policy: { noCoverage: false, isITAC: false @@ -503,9 +468,10 @@ describe('cart-helper', () => { expect(result).toBe(15); }); - test('Returns sales tax of all line items when no comp', () => { + test('Returns sales tax of all line items when verified no comp', () => { // Arrange const order = { + isUnverified: false, policy: { noCoverage: true, isITAC: false @@ -521,9 +487,10 @@ describe('cart-helper', () => { expect(result).toBe(21); }); - test('Returns sales tax of all line items when ITAC', () => { + test('Returns sales tax of all line items when verified ITAC', () => { // Arrange const order = { + isUnverified: false, policy: { noCoverage: false, isITAC: true @@ -544,6 +511,7 @@ describe('cart-helper', () => { test('Returns 0 when there are null items', () => { // Arrange const order = { + isUnverified: false, policy: { noCoverage: true }, @@ -560,6 +528,7 @@ describe('cart-helper', () => { test('Returns 0 when there are no items', () => { // Arrange const order = { + isUnverified: false, policy: { noCoverage: true }, @@ -573,9 +542,10 @@ describe('cart-helper', () => { expect(result).toBe(0); }); - test('Returns total of vaps + fee line items', () => { + test('Returns total of vaps + fee line items when verified', () => { // Arrange const order = { + isUnverified: false, policy: { noCoverage: false, isITAC: false @@ -591,9 +561,10 @@ describe('cart-helper', () => { expect(result).toBe(325); }); - test('Returns total of all line items when no comp', () => { + test('Returns total of all line items when verified no comp', () => { // Arrange const order = { + isUnverified: false, policy: { noCoverage: true, isITAC: false @@ -609,9 +580,10 @@ describe('cart-helper', () => { expect(result).toBe(351); }); - test('Returns total of all line items when ITAC', () => { + test('Returns total of all line items when verified ITAC', () => { // Arrange const order = { + isUnverified: false, policy: { noCoverage: false, isITAC: true diff --git a/src/helpers/price-calculator.js b/src/helpers/price-calculator.js index 72634df7..de4cb7e9 100644 --- a/src/helpers/price-calculator.js +++ b/src/helpers/price-calculator.js @@ -1,17 +1,13 @@ /** * Returns the price of a single line item. Will include sales tax if includeTax is true * @param {object} lineItem line item to price - * @param {boolean} includeTax if sales tax should be included * @returns {number} price of the line item */ -export function getPriceOfLineItem(lineItem, includeTax = false) { +export function getPriceOfLineItem(lineItem) { let price = (lineItem.kitPrice ?? 0) + (lineItem.laborAmount ?? 0) + (lineItem.sellingPrice ?? 0); - if (includeTax) { - price += lineItem.salesTax ?? 0; - } if (lineItem.childParts && lineItem.childParts.length !== 0) { // eslint-disable-next-line no-use-before-define - price += getPriceOfLineItems(lineItem.childParts, includeTax); + price += getPriceOfLineItems(lineItem.childParts); } return price; } @@ -19,11 +15,10 @@ export function getPriceOfLineItem(lineItem, includeTax = false) { /** * Returns the price for the given array of line items. Will include sales tax if includeTax is true * @param {Array} lineItems array of line items to be priced - * @param {boolean} includeTax if sales tax should be included * @returns {number} price of the lines items */ -export function getPriceOfLineItems(lineItems, includeTax = false) { - return lineItems?.reduce((accumulator, lineItem) => accumulator + getPriceOfLineItem(lineItem, includeTax), 0) ?? 0; +export function getPriceOfLineItems(lineItems) { + return lineItems?.reduce((accumulator, lineItem) => accumulator + getPriceOfLineItem(lineItem), 0) ?? 0; } /** diff --git a/src/helpers/price-calculator.spec.js b/src/helpers/price-calculator.spec.js index b415d0ab..0150ef96 100644 --- a/src/helpers/price-calculator.spec.js +++ b/src/helpers/price-calculator.spec.js @@ -11,24 +11,13 @@ describe('price-calculator', () => { const lineItem = {}; // Act - const result = getPriceOfLineItem(lineItem, false); + const result = getPriceOfLineItem(lineItem); // Assert expect(result).toBe(0); }); - test('Empty lineItem with salesTax returns 0', () => { - // Arrange - const lineItem = {}; - - // Act - const result = getPriceOfLineItem(lineItem, true); - - // Assert - expect(result).toBe(0); - }); - - test('Returns kit, labor, sellingPrice total when salesTax is false', () => { + test('Returns kit, labor, sellingPrice total', () => { // Arrange const lineItem = { kitPrice: 1, @@ -38,27 +27,11 @@ describe('price-calculator', () => { }; // Act - const result = getPriceOfLineItem(lineItem, false); + const result = getPriceOfLineItem(lineItem); // Assert expect(result).toBe(6); }); - - test('Returns kit, labor, sellingPrice, salesTax total when salesTax is true', () => { - // Arrange - const lineItem = { - kitPrice: 1, - laborAmount: 2, - sellingPrice: 3, - salesTax: 4 - }; - - // Act - const result = getPriceOfLineItem(lineItem, true); - - // Assert - expect(result).toBe(10); - }); }); describe('getPriceOfLineItems', () => { @@ -67,7 +40,7 @@ describe('price-calculator', () => { const lineItems = null; // Act - const result = getPriceOfLineItems(lineItems, true); + const result = getPriceOfLineItems(lineItems); // Assert expect(result).toBe(0); @@ -78,7 +51,7 @@ describe('price-calculator', () => { const lineItems = []; // Act - const result = getPriceOfLineItems(lineItems, true); + const result = getPriceOfLineItems(lineItems); // Assert expect(result).toBe(0); @@ -95,12 +68,12 @@ describe('price-calculator', () => { const expected = 6; // Act - const result = getPriceOfLineItems(lineItems, false); + const result = getPriceOfLineItems(lineItems); // Assert expect(result).toBe(expected); }); - test('Returns expected when multiple line items', () => { + test('Returns expected when multiple line items and child parts', () => { // Arrange const lineItems = [ { @@ -111,44 +84,30 @@ describe('price-calculator', () => { { kitPrice: 1 }, - { - kitPrice: 10, - laborAmount: 100, - sellingPrice: 1000 - } - ]; - const expected = 1117; - - // Act - const result = getPriceOfLineItems(lineItems, false); - - // Assert - expect(result).toBe(expected); - }); - test('Returns expected when multiple line items with sales tax', () => { - // Arrange - const lineItems = [ - { - kitPrice: 1, - laborAmount: 2, - sellingPrice: 3, - salesTax: 4 - }, - { - kitPrice: 1, - salesTax: 2 - }, { kitPrice: 10, laborAmount: 100, sellingPrice: 1000, - salesTax: 50 + childParts: [ + { + kitPrice: 1, + laborAmount: 2, + sellingPrice: 3, + salesTax: 4 + }, + { + kitPrice: 2, + laborAmount: 3, + sellingPrice: 4, + salesTax: 5 + } + ] } ]; - const expected = 1173; + const expected = 1132; // Act - const result = getPriceOfLineItems(lineItems, true); + const result = getPriceOfLineItems(lineItems); // Assert expect(result).toBe(expected); @@ -222,5 +181,34 @@ describe('price-calculator', () => { // Assert expect(result).toBe(expected); }); + + test('Returns expected when multiple line items', () => { + // Arrange + const lineItems = [ + { + kitPrice: 1, + laborAmount: 2, + sellingPrice: 3, + salesTax: 4 + }, + { + kitPrice: 1, + salesTax: 2 + }, + { + kitPrice: 10, + laborAmount: 100, + sellingPrice: 1000, + salesTax: 50 + } + ]; + const expected = 56; + + // Act + const result = getTaxOfLineItems(lineItems); + + // Assert + expect(result).toBe(expected); + }); }); }); diff --git a/src/iss-components/cart-dropdown/cart-dropdown.vue b/src/iss-components/cart-dropdown/cart-dropdown.vue index b2e0e337..d6565c22 100644 --- a/src/iss-components/cart-dropdown/cart-dropdown.vue +++ b/src/iss-components/cart-dropdown/cart-dropdown.vue @@ -169,12 +169,12 @@ import widgetFields from '@/constants/cms-widget-fields.js'; import { getCartTotal, getDeductible, - getLineItems, getMobileFee, - getRecycleFee, getSalesTax, + getLineItems, getMobileFeeLineItem, + getRecycleFeeLineItem, getSalesTax, getServiceLineItems, getSubtotal, isOrderITAC, isOrderNoComp, isOrderUnverified } from '@/helpers/cart-helper'; -import {getPriceOfLineItems, getTaxOfLineItems} from '@/helpers/price-calculator'; +import { getPriceOfLineItems, getTaxOfLineItems } from '@/helpers/price-calculator'; const VERIFYING_COVERAGE = 'Verifying coverage'; @@ -226,10 +226,10 @@ export default { return getLineItems(this.cartOrder); }, recycleFeeLineItem() { - return getRecycleFee(this.cartOrder); + return getRecycleFeeLineItem(this.cartOrder); }, servicePrice() { - return getPriceOfLineItems(getServiceLineItems(this.cartOrder), false) ?? 0; + return getPriceOfLineItems(getServiceLineItems(this.cartOrder)) ?? 0; }, isUnverified() { return isOrderUnverified(this.cartOrder); @@ -393,7 +393,7 @@ export default { : null; }, mobileFeeCartItem() { - const mobileFeeLineItem = getMobileFee(this.cartOrder); + const mobileFeeLineItem = getMobileFeeLineItem(this.cartOrder); return mobileFeeLineItem ? this.getCartItem( this.getCmsContent(this.widget.mobileFee, widgetFields.TEXT_BLOCK_WIDGET.TEXT), @@ -424,7 +424,7 @@ export default { name: label, cartItemType: cartItemTypeString, partType, - subTotal: getPriceOfLineItems(lineItems, false), + subTotal: getPriceOfLineItems(lineItems), salesTax: getTaxOfLineItems(lineItems) }; } diff --git a/src/layouts/coverage-statement/coverage-statement.vue b/src/layouts/coverage-statement/coverage-statement.vue index 0bc42c12..aa34079b 100644 --- a/src/layouts/coverage-statement/coverage-statement.vue +++ b/src/layouts/coverage-statement/coverage-statement.vue @@ -344,7 +344,7 @@ export default { ); }, totalServicePrice() { - return getPriceOfLineItems(this.baseServiceLineItems, false); + return getPriceOfLineItems(this.baseServiceLineItems); }, serviceProviderQuestionText() { return this.getCmsContent( diff --git a/src/layouts/payment-page/payment-page.spec.js b/src/layouts/payment-page/payment-page.spec.js index b2bdc2e4..ef3ffc04 100644 --- a/src/layouts/payment-page/payment-page.spec.js +++ b/src/layouts/payment-page/payment-page.spec.js @@ -8,6 +8,10 @@ import { useMainStore } from '@/store'; import { paymentMethods, hopPaymentMethods } from '@/constants/payment-method-constants.js'; import queryStrings from '@/constants/query-strings'; import CartDropdown from '@/iss-components/cart-dropdown/cart-dropdown.vue'; +import { createTestingPinia } from '@pinia/testing'; +import settleAllPromises from '@/helpers/layout-helper'; +import { fetchCmsContentForPage } from '@/helpers/cms-content-helper'; +import baseMixin from '@/mixins/base-mixin'; // Constants const parts = { @@ -105,123 +109,124 @@ const taxedParts = { }; // Setup global mocks -let mockCmsContent = {}; - +// Mock fetchCmsContentForPage jest.mock('@/helpers/cms-content-helper', () => ({ - fetchCmsContentForPage: () => Promise.resolve('content') + fetchCmsContentForPage: jest.fn(), + doesCopyContainRouterLink: jest.fn() })); -function setupMocks({ customMountOptions = {}, queryString }) { +// Mock our module for promises. +jest.mock('@/helpers/layout-helper.js', () => jest.fn()); + +function getMountedComponent(mainInitialState = {}, initialData = {}, methodToRunAfterInitializingStore = () => {}, queryString = {}) { const mountOptions = getMountOptions({ - ...customMountOptions, + router: { + navigate: jest.fn() + }, route: { query: { issPage: 'page-name', ...queryString }, params: {} } }); - // set all mock stuff - mountOptions.mixins = [ - { - methods: { - getCmsContent: jest.fn().mockImplementation((widgetName, fieldName) => { - if (mockCmsContent[widgetName] && mockCmsContent[widgetName][fieldName]) { - return mockCmsContent[widgetName][fieldName]; - } - return undefined; - }), - setCmsContent: jest.fn() - } + const testingPinia = createTestingPinia({ + initialState: { + main: mainInitialState } - ]; + }); + useMainStore(testingPinia); + methodToRunAfterInitializingStore(); + + mountOptions.global.plugins = [testingPinia]; + mountOptions.data = () => (initialData); + + const apiResponses = { cmsContent: {} }; + + settleAllPromises.mockImplementation(() => apiResponses); + fetchCmsContentForPage.mockImplementation(() => Promise.resolve()); const wrapper = shallowMount(payment, mountOptions); + wrapper.vm.getCmsContent = jest.fn().mockImplementation(() => {}); + wrapper.vm.setCmsContent = jest.fn(); + wrapper.vm.$router.navigateWithSpinner = jest.fn(); + wrapper.vm.navigateBack = baseMixin.methods.navigateBack; - // act on vm - - return wrapper; + return { wrapper }; } -describe('payment-page.vue', () => { - beforeEach(() => { - useMainStore().order = - { - vehicle: { - year: '2020', - make: 'acura', - model: 'mdx', - style: '4-door sedan', - carId: 'dummyCarId', - category: 'dummyCategory', - vin: 'dummyVin' - }, - serviceLocation: { - address: 'add1', - address2: 'add2', - city: 'city', - state: 'state', - zipCode: 'zip', - zipCodeCtu: 'zipCtu', - appointmentType: 'IN_SHOP', - isVehicleProtected: true, - provider: { - providerNumber: 2, - address: { - streetAddress: 'add3', - city: 'city2', - state: 'state2', - zipCode: 'zip2', - zipCodeCtu: 'zipCtu2' - } - }, - techNotes: '' - }, - contactInfo: { - firstName: 'first', - lastName: 'last', - emailAddress: 'builddigitaltest@safelite.com', - servicePhone: '555-555-5555' - }, - damage: { - isRepair: false, - numberOfChips: null, - glassToReplace: [{ location: 'windshield' }] - }, - lineItems: { - glassParts: [parts.windshield], - supportingItems: [], - vaps: [parts.frontWipers], - promos: [] - }, - payment: { - isInsurance: false, - insuranceCoverage: { - isVerified: null, - coverageStatus: null, - coverageVerificationType: null - }, - isPayInAdvance: true, - payInAdvanceType: 'Afterpay', - inactivePromos: [] - }, - schedule: { - date: 'date', - startTime: 'start', - endTime: 'end', - jobMinMinutes: '30', - jobMaxMinutes: '45' +const defaultOrder = { + order: { + vehicle: { + year: '2020', + make: 'acura', + model: 'mdx', + style: '4-door sedan', + carId: 'dummyCarId', + category: 'dummyCategory', + vin: 'dummyVin' + }, + serviceLocation: { + address: 'add1', + address2: 'add2', + city: 'city', + state: 'state', + zipCode: 'zip', + zipCodeCtu: 'zipCtu', + appointmentType: 'IN_SHOP', + isVehicleProtected: true, + provider: { + providerNumber: 2, + address: { + streetAddress: 'add3', + city: 'city2', + state: 'state2', + zipCode: 'zip2', + zipCodeCtu: 'zipCtu2' } - }; - - mockCmsContent = {}; - }); - - afterEach(() => { - jest.clearAllMocks(); - }); + }, + techNotes: '' + }, + contactInfo: { + firstName: 'first', + lastName: 'last', + emailAddress: 'builddigitaltest@safelite.com', + servicePhone: '555-555-5555' + }, + damage: { + isRepair: false, + numberOfChips: null, + glassToReplace: [{location: 'windshield'}] + }, + lineItems: { + glassParts: [parts.windshield], + supportingItems: [], + vaps: [parts.frontWipers], + promos: [] + }, + payment: { + isInsurance: false, + insuranceCoverage: { + isVerified: null, + coverageStatus: null, + coverageVerificationType: null + }, + isPayInAdvance: true, + payInAdvanceType: 'Afterpay', + inactivePromos: [] + }, + schedule: { + date: 'date', + startTime: 'start', + endTime: 'end', + jobMinMinutes: '30', + jobMaxMinutes: '45' + } + } +}; +describe('payment-page.vue', () => { describe('arePagePrerequisitesValid', () => { test('Returns true in nominal conditions', () => { // Arrange // Store defaults are valid - const wrapper = setupMocks({}); + const { wrapper } = getMountedComponent(defaultOrder); // Act const result = wrapper.vm.arePagePrerequisitesValid(); @@ -233,9 +238,9 @@ describe('payment-page.vue', () => { describe('Payment method cases', () => { test('Returns false if pia options are not valid', () => { // Arrange + const { wrapper } = getMountedComponent(defaultOrder); useMainStore().order.payment.isPayInAdvance = null; useMainStore().order.payment.payInAdvanceType = null; - const wrapper = setupMocks({}); // Act const result = wrapper.vm.arePagePrerequisitesValid(); @@ -246,9 +251,9 @@ describe('payment-page.vue', () => { test('Returns false if pay at time of service', () => { // Arrange + const { wrapper } = getMountedComponent(defaultOrder); useMainStore().order.payment.isPayInAdvance = false; useMainStore().order.payment.payInAdvanceType = null; - const wrapper = setupMocks({}); // Act const result = wrapper.vm.arePagePrerequisitesValid(); @@ -263,8 +268,8 @@ describe('payment-page.vue', () => { describe('getPaymentType', () => { test('Maps AFTERPAY -> hopPaymentMethods.AFTERPAY', () => { // Arrange + const { wrapper } = getMountedComponent(defaultOrder); useMainStore().order.payment.payInAdvanceType = paymentMethods.AFTERPAY; - const wrapper = setupMocks({}); // Act const mapped = wrapper.vm.getPaymentType(); @@ -275,8 +280,8 @@ describe('payment-page.vue', () => { test('Maps CREDIT_CARD -> hopPaymentMethods.CREDIT_CARD', () => { // Arrange + const { wrapper } = getMountedComponent(defaultOrder); useMainStore().order.payment.payInAdvanceType = paymentMethods.CREDIT_CARD; - const wrapper = setupMocks({}); // Act const mapped = wrapper.vm.getPaymentType(); @@ -287,8 +292,8 @@ describe('payment-page.vue', () => { test('Maps PAYPAL -> hopPaymentMethods.PAYPAL', () => { // Arrange + const { wrapper } = getMountedComponent(defaultOrder); useMainStore().order.payment.payInAdvanceType = paymentMethods.PAYPAL; - const wrapper = setupMocks({}); // Act const mapped = wrapper.vm.getPaymentType(); @@ -299,8 +304,8 @@ describe('payment-page.vue', () => { test('Maps other values to self', () => { // Arrange + const { wrapper } = getMountedComponent(defaultOrder); useMainStore().order.payment.payInAdvanceType = 'SomeOtherText'; - const wrapper = setupMocks({}); // Act const mapped = wrapper.vm.getPaymentType(); @@ -312,7 +317,7 @@ describe('payment-page.vue', () => { describe('cart-dropdown', () => { test('Show cart dropdown if credit card', async () => { - const wrapper = setupMocks({}); + const { wrapper } = getMountedComponent(defaultOrder); wrapper.vm.paymentType = hopPaymentMethods.CREDIT_CARD; // Act @@ -324,7 +329,7 @@ describe('payment-page.vue', () => { }); test('show cart dropdown if afterpay', async () => { - const wrapper = setupMocks({}); + const { wrapper } = getMountedComponent(defaultOrder); wrapper.vm.paymentType = hopPaymentMethods.AFTERPAY; // Act @@ -336,7 +341,7 @@ describe('payment-page.vue', () => { }); test('Hide cart dropdown if paypal', async () => { - const wrapper = setupMocks({}); + const { wrapper } = getMountedComponent(defaultOrder); wrapper.vm.paymentType = hopPaymentMethods.PAYPAL; // Act @@ -352,7 +357,7 @@ describe('payment-page.vue', () => { test('Is responsive if initial data changes', async () => { // Arrange // note: begins with payment-type = afterpay - const wrapper = setupMocks({}); + const { wrapper } = getMountedComponent(defaultOrder); // Act const preVal = wrapper.vm.isPaypal; @@ -377,7 +382,7 @@ describe('payment-page.vue', () => { signature: 'SIGNATURE', startDate: 'STARTDATE' }; - const wrapper = setupMocks({}); + const { wrapper } = getMountedComponent(defaultOrder); wrapper.vm.submitHopForm = jest.fn(); @@ -396,7 +401,7 @@ describe('payment-page.vue', () => { describe('submitHopForm', () => { test('Submits form', async () => { // Arrange - const wrapper = setupMocks({}); + const { wrapper } = getMountedComponent(defaultOrder); wrapper.vm.$refs.hopForm.submit = jest.fn(); wrapper.vm.$refs.paymentFrame = null; @@ -418,7 +423,7 @@ describe('payment-page.vue', () => { data: 'afterpayClosed' }; - const wrapper = setupMocks({}); + const { wrapper } = getMountedComponent(defaultOrder); wrapper.vm.backButtonAction = jest.fn(); @@ -435,7 +440,7 @@ describe('payment-page.vue', () => { data: 'creditCardSubmit' }; - const wrapper = setupMocks({}); + const { wrapper } = getMountedComponent(defaultOrder); // Act wrapper.vm.handleIFrameContentWindowMessage(event); @@ -449,7 +454,7 @@ describe('payment-page.vue', () => { describe('UI Blocking', () => { test('UI block appears when toggled', async () => { // Arrange - const wrapper = setupMocks({}); + const { wrapper } = getMountedComponent(defaultOrder); // Act wrapper.vm.setUIBlock(true); @@ -464,7 +469,7 @@ describe('payment-page.vue', () => { test("Don't propogate clicks from UI block", async () => { // Arrange - const wrapper = setupMocks({}); + const { wrapper } = getMountedComponent(defaultOrder); const outerDiv = wrapper.find('.container-fluid'); const clickFn = jest.fn(); @@ -490,7 +495,7 @@ describe('payment-page.vue', () => { const queryString = { [queryStrings.DISPLAY_PAY_IN_ADVANCE_ALERT]: paymentMethods.CREDIT_CARD }; - const wrapper = setupMocks({ queryString }); + const { wrapper } = getMountedComponent(defaultOrder, {}, () => {}, queryString); // Act @@ -507,7 +512,7 @@ describe('payment-page.vue', () => { const queryString = { [queryStrings.DISPLAY_PAY_IN_ADVANCE_ALERT]: paymentMethods.AFTERPAY }; - const wrapper = setupMocks({ queryString }); + const { wrapper } = getMountedComponent(defaultOrder, {}, () => {}, queryString); // Act diff --git a/src/layouts/schedule-page/time-slot-modal-question/time-slot-modal-question.vue b/src/layouts/schedule-page/time-slot-modal-question/time-slot-modal-question.vue index c26e739b..6f44e2d5 100644 --- a/src/layouts/schedule-page/time-slot-modal-question/time-slot-modal-question.vue +++ b/src/layouts/schedule-page/time-slot-modal-question/time-slot-modal-question.vue @@ -423,7 +423,7 @@ export default { }, getPremiumAppointmentTimeSlot(timeSlotData) { const formattedPrice = - `+${formatAmountInDollars(getPriceOfLineItem(this.premiumAppointmentFee, false))}`; + `+${formatAmountInDollars(getPriceOfLineItem(this.premiumAppointmentFee))}`; return { // Unique value is required for each and the premium appoinment shares an id diff --git a/src/layouts/service-packages/service-package-question/service-package-question.vue b/src/layouts/service-packages/service-package-question/service-package-question.vue index 5092d581..06a97fdf 100644 --- a/src/layouts/service-packages/service-package-question/service-package-question.vue +++ b/src/layouts/service-packages/service-package-question/service-package-question.vue @@ -187,7 +187,7 @@ export default { && item.partType.toUpperCase() === partTypeStrings.FRONT_WIPER) || (priceRearWipers && item.partType.toUpperCase() === partTypeStrings.REAR_WIPER) ) { - vapsPrice += getPriceOfLineItem(item, false); + vapsPrice += getPriceOfLineItem(item); } }); return vapsPrice; @@ -206,7 +206,7 @@ export default { || (priceRainDefense && item.partType.toUpperCase() === partTypeStrings.RAIN_DEFENSE) ) { - vapsPrice += getPriceOfLineItem(item, false); + vapsPrice += getPriceOfLineItem(item); } }); return vapsPrice; diff --git a/src/store/index.js b/src/store/index.js index f9029ea1..8c6c5c7b 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -24,7 +24,7 @@ import { import partTypeStrings from '@/constants/part-type-strings'; import bailoutMessage from '@/constants/bailoutMessage'; import bailoutCode from '@/constants/bailoutCode'; -import partNumberStrings from "@/constants/part-number-strings"; +import partNumberStrings from '@/constants/part-number-strings'; const storeId = 'main'; @@ -276,17 +276,9 @@ export const useMainStore = defineStore({ hasExactlyOneChip: () => state.order.damage.numberOfChips === 1, isPolicyVehicle: () => state.order.vehicle.policyVehicleId != null, hasWindshieldReplacement: (s) => { - const { damage } = s.order; - if (damage.isRepair) { - return false; - } - - const { glassParts } = s.order.lineItems; - if (!glassParts || glassParts.length === 0) { - return false; - } - - return glassParts.findIndex((gp) => gp.partType === 'WINDSHIELD') !== -1; + const { damage, lineItems } = s.order; + return !damage.isRepair + && (lineItems.glassParts?.some((gp) => gp.partType === partTypeStrings.WINDSHIELD) ?? false); }, hasAnyNonWindshieldGlassParts: (s) => !s.order.policy.isDamageGlassOnly, isMobileAppointment: (state) => state.order.serviceLocation.appointmentType === AppointmentTypeStrings.MOBILE @@ -1630,7 +1622,7 @@ export const useMainStore = defineStore({ updateMobileFee(fee) { // Mobile Fee is only added for NO COMP or ITAC - if (fee && (this.isNoComp || this.isITAC)) { + if (fee && !this.isUnverified && (this.isNoComp || this.isITAC)) { this.addPartTypeFeeItem(fee, partTypeStrings.MOBILE_FEE); } else { this.addPartTypeFeeItem(null, partTypeStrings.MOBILE_FEE); @@ -1639,7 +1631,7 @@ export const useMainStore = defineStore({ updateRecycleFee(fee) { // Recycle Fee is only added for NO COMP or ITAC and has Windshield Replacement - if (fee && (this.isNoComp || this.isITAC) && this.hasWindshieldReplacement) { + if (fee && !this.isUnverified && (this.isNoComp || this.isITAC) && this.hasWindshieldReplacement) { this.addPartNumberFeeItem(fee, partNumberStrings.RECYCLE_FEE); } else { this.addPartNumberFeeItem(null, partNumberStrings.RECYCLE_FEE);