From b5ecac8b5aab179e451b52fad033795fea955a50 Mon Sep 17 00:00:00 2001 From: Alex Humphries Date: Tue, 10 Feb 2026 16:46:39 -0500 Subject: [PATCH 01/11] INSR-7757: Update order confirmation page and cart --- src/constants/endpoints.js | 4 + src/constants/part-type-strings.js | 3 +- src/helpers/damage-helper.js | 20 + .../confirmation-cart.spec.js | 1580 +++++++++++++++++ .../confirmation-cart/confirmation-cart.vue | 478 +++++ .../order-confirmation/order-confirmation.vue | 439 ++++- src/layouts/payment-method/payment-method.vue | 3 +- src/store/index.js | 16 +- 8 files changed, 2444 insertions(+), 99 deletions(-) create mode 100644 src/iss-components/confirmation-cart/confirmation-cart.spec.js create mode 100644 src/iss-components/confirmation-cart/confirmation-cart.vue diff --git a/src/constants/endpoints.js b/src/constants/endpoints.js index c55410da..6e2de5cb 100644 --- a/src/constants/endpoints.js +++ b/src/constants/endpoints.js @@ -125,6 +125,10 @@ const endpoints = Object.freeze({ url: `${PARTS_BASE_URL}/mobile-fee`, method: 'GET' }, + GetSV2GlassTypes: { + url: `${PARTS_BASE_URL}/map-to-sv2-glass-types`, + method: 'POST' + }, GetServiceabilityDetails: { url: `${LOCATION_BASE_URL}/serviceability-details`, method: 'GET' diff --git a/src/constants/part-type-strings.js b/src/constants/part-type-strings.js index 4876b999..040ca6ad 100644 --- a/src/constants/part-type-strings.js +++ b/src/constants/part-type-strings.js @@ -7,7 +7,8 @@ RECALIBRATION: 'RECALIBRATION', REPLACE_FEE: 'REPLACE FEE', MOBILE_FEE: 'MOBILE FEE', - REPAIR_FEE: 'REPAIR FEE' + REPAIR_FEE: 'REPAIR FEE', + WARRANTY: 'WARRANTY' }); export default partTypeStrings; diff --git a/src/helpers/damage-helper.js b/src/helpers/damage-helper.js index 5e886326..34bfc890 100644 --- a/src/helpers/damage-helper.js +++ b/src/helpers/damage-helper.js @@ -71,6 +71,26 @@ export async function isGlassAvailableForCarId(carId) { } } +export function getGlassList(glassPieces) { + let names = ''; + switch (glassPieces.length) + { + case 0: + break; + case 1: + names = glassPieces[0]; + break; + case 2: + names = glassPieces.join(' and '); + break; + default: + names = glassPieces.slice(0, -1).join(', ') + ', and ' + glassPieces.slice(-1); + break; + } + + return names.toLowerCase(); +} + /** * Commented code are copied directly from DigitalConsumer.FixMyGlass * and have not been adjusted for ISS. diff --git a/src/iss-components/confirmation-cart/confirmation-cart.spec.js b/src/iss-components/confirmation-cart/confirmation-cart.spec.js new file mode 100644 index 00000000..7391f3d9 --- /dev/null +++ b/src/iss-components/confirmation-cart/confirmation-cart.spec.js @@ -0,0 +1,1580 @@ +import { shallowMount } from '@vue/test-utils'; +import { createTestingPinia } from '@pinia/testing'; +import confirmationCart from '@/iss-components/confirmation-cart/confirmation-cart.vue'; + +// Supporting Files +import { getEnumName, getMountOptions } from '@/helpers/unit-test-helper.js'; +import { useMainStore, getDefaultState } from '@/store'; +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'; +import coverageStatuses from '@/constants/coverage-statuses'; +import coverageType from '@/constants/coverage-type'; + +const VERIFYING_COVERAGE = 'Verifying coverage'; + +jest.mock('@/helpers/text-helper', () => ({ + formatAmountInDollars: jest.fn() +})); +jest.mock('@/helpers/price-calculator.js', () => ({ + getPriceOfLineItems: jest.fn(), + getTaxOfLineItems: jest.fn(), + getPriceOfLineItem: jest.fn() +})); + +jest.mock('@/helpers/service-package-helper', () => ({ + getHighestFullySatisfiedTier: jest.fn(), + getPackageContents: jest.fn() +})); + +function getMountedComponent(mainInitialState = {}, initialData = {}, propsData = {}) { + const mountOptions = getMountOptions({ + router: { + navigate: jest.fn() + } + }); + + const testingPinia = createTestingPinia({ + initialState: { + main: mainInitialState + } + }); + useMainStore(testingPinia); + + mountOptions.global.mixins[0].methods.getSettingValue = jest.fn(() => 'false'); + mountOptions.global.plugins = [testingPinia]; + mountOptions.data = () => (initialData); + mountOptions.propsData = propsData; + + const wrapper = shallowMount(confirmationCart, mountOptions); + return { wrapper }; +} + +beforeEach(() => { + const store = useMainStore(); + const defaultState = getDefaultState(); + Object.keys(defaultState).forEach((key) => { + store[key] = defaultState[key]; + }); +}); + +describe('confirmation-cart component', () => { + test('initial data rendered as expected', () => { + // Arrange + const { wrapper } = getMountedComponent({ + order: { + availableVaps: [] + } + }); + + // Assert + expect(wrapper.vm.$data).toMatchSnapshot(); + }); + describe('displays', () => { + test('cart dropdown head', () => { + // Arrange + const reference = '#cart-dropdown-head'; + const { wrapper } = getMountedComponent(confirmationCart); + + // Act + const head = wrapper.find(reference); + + // Assert + expect(head.exists()).toBeTruthy(); + }); + test('cart dropdown head is visible', () => { + // Arrange + const reference = '#cart-dropdown-head'; + const { wrapper } = getMountedComponent(confirmationCart, {}, { showDropdownHeader: true }); + + // Act + const head = wrapper.find(reference); + + // Assert + expect(head.exists()).toBeTruthy(); + expect(head.classes()).toContain('cart-toggle'); + }); + test('cart dropdown head is not visible', () => { + // Arrange + const reference = '#cart-dropdown-head'; + const { wrapper } = getMountedComponent(confirmationCart, {}, { showDropdownHeader: false }); + + // Act + const head = wrapper.find(reference); + + // Assert + expect(head.exists()).toBeTruthy(); + expect(head.classes()).not.toContain('cart-toggle'); + }); + test('cart table', () => { + // Arrange + const reference = '#cart-table'; + const isExpanded = true; + const initialData = { isExpanded }; + const { wrapper } = getMountedComponent({}, {}, initialData); + + // Act + const cartTable = wrapper.find(reference); + + // Assert + expect(cartTable.exists()).toBeTruthy(); + }); + test('cart deductible when showDeductibleLineItem is true', () => { + // Arrange + const reference = '#cart-deductible'; + const isExpanded = true; + const initialData = { isExpanded }; + const storeData = { + order: { + insuranceCoverage: { + coverageStatus: coverageStatuses.VERIFIED, + coverageType: coverageType.Deductible + } + } + }; + const { wrapper } = getMountedComponent(storeData, {}, initialData); + + // Act + const cartDeductible = wrapper.find(reference); + + // Assert + expect(cartDeductible.exists()).toBeTruthy(); + }); + test('cart base price when showDeductibleLineItem is false', () => { + // Arrange + const reference = '#cart-base-price'; + const isExpanded = true; + const initialData = { isExpanded }; + const storeData = { + order: { + currentDeductible: 0, + lineItems: { }, + insuranceCoverage: { + coverageStatus: coverageStatuses.VERIFIED, + coverageType: coverageType.ITAC + } + }, + issConfig: { + isClaimRegistrationRequired: true + } + }; + const { wrapper } = getMountedComponent(storeData, {}, initialData); + + // Act + const cartBasePrice = wrapper.find(reference); + + // Assert + expect(cartBasePrice.exists()).toBeTruthy(); + }); + test('service package', () => { + // Arrange + const reference = '#cart-service-package'; + const isExpanded = true; + const initialData = { isExpanded }; + const { wrapper } = getMountedComponent({}, {}, initialData); + + // Act + const servicePackage = wrapper.find(reference); + + // Assert + expect(servicePackage.exists()).toBeTruthy(); + }); + 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: { + feeItems: [ + { 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'; + const isExpanded = true; + const initialData = { isExpanded }; + const { wrapper } = getMountedComponent({}, {}, initialData); + + // Act + const cartFooter = wrapper.find(reference); + + // Assert + expect(cartFooter.exists()).toBeTruthy(); + }); + test('subtotal', () => { + // Arrange + const reference = '#cart-subtotal'; + const isExpanded = true; + const initialData = { isExpanded }; + const { wrapper } = getMountedComponent({}, {}, initialData); + + // Act + const subtotal = wrapper.find(reference); + + // Assert + expect(subtotal.exists()).toBeTruthy(); + }); + test('tax', () => { + // Arrange + const reference = '#cart-sales-tax'; + const isExpanded = true; + const initialData = { isExpanded }; + const { wrapper } = getMountedComponent({}, {}, initialData); + + // Act + const salesTax = wrapper.find(reference); + + // Assert + expect(salesTax.exists()).toBeTruthy(); + }); + test('amount paid when Pay in Advance', () => { + // Arrange + const reference = '#cart-amount-paid'; + const isExpanded = true; + const showAsPaid = true; + const initialPropsData = { isExpanded, showAsPaid }; + const storeData = { + order: { + payment: { + isPayInAdvance: true + } + } + }; + const { wrapper } = getMountedComponent(storeData, {}, initialPropsData); + + // Act + const amountPaid = wrapper.find(reference); + + // Assert + expect(amountPaid.exists()).toBeTruthy(); + }); + test('bottom amount due', () => { + // Arrange + const reference = '#bottom-amount-due'; + const isExpanded = true; + const initialData = { isExpanded }; + const { wrapper } = getMountedComponent({}, {}, initialData); + + // Act + const bottomAmountDue = wrapper.find(reference); + + // Assert + expect(bottomAmountDue.exists()).toBeTruthy(); + }); + }); + describe('does not display', () => { + test('cart deductible when showDeductibleLineItem is false', () => { + // Arrange + const reference = '#cart-deductible'; + const isExpanded = true; + const initialData = { isExpanded }; + const storeData = { + order: { + currentDeductible: 0, + lineItems: { }, + insuranceCoverage: { + coverageStatus: coverageStatuses.VERIFIED, + coverageType: coverageType.ITAC + } + }, + issConfig: { + isClaimRegistrationRequired: true + } + }; + const { wrapper } = getMountedComponent(storeData, {}, initialData); + + // Act + const cartDeductible = wrapper.find(reference); + + // Assert + expect(cartDeductible.exists()).toBeFalsy(); + }); + test('cart base price when showDeductibleLineItem is true', () => { + // Arrange + const reference = '#cart-base-price'; + const isExpanded = true; + const initialData = { isExpanded }; + const storeData = { + order: { + insuranceCoverage: { + coverageStatus: coverageStatuses.VERIFIED, + coverageType: coverageType.Deductible + } + } + }; + const { wrapper } = getMountedComponent(storeData, {}, initialData); + + // Act + const cartBasePrice = wrapper.find(reference); + + // Assert + expect(cartBasePrice.exists()).toBeFalsy(); + }); + test('recycle cart item label when isRecycle false for all cart items', () => { + // Arrange + const reference = '#recycle-fee-label'; + const isExpanded = true; + const initialPropsData = { isExpanded }; + const storeData = { + order: { + lineItems: { + supportingItems: [] + } + } + }; + const { wrapper } = getMountedComponent(storeData, {}, initialPropsData); + + // Act + const recycleFeeLabel = wrapper.find(reference); + + // Assert + expect(wrapper.vm.recycleFeeCartItem).toBeNull(); + expect(recycleFeeLabel.exists()).toBeFalsy(); + }); + }); + describe('computed', () => { + describe('amountDue', () => { + test('returns 0 when showAsPaid is true', () => { + // Arrange + const propsData = { + showAsPaid: true + }; + const { wrapper } = getMountedComponent({}, {}, propsData); + + // Act + const result = wrapper.vm.amountDue; + + // Assert + expect(result).toBe(0); + }); + test('returns sum of subTotal and salesTax when showAsPaid is false', () => { + // TODO when subTotal and salesTax are finished + }); + }); + describe('availableLineItems', () => { + test('returns expected when all null', () => { + // Arrange + const propsData = { availableVaps: null }; + const { wrapper } = getMountedComponent({}, {}, propsData); + + // Act + const result = wrapper.vm.availableLineItems; + + // Assert + expect(result).toStrictEqual([]); + }); + test('returns expected when glassParts not null', async () => { + // Arrange + const glassParts = [{ partNumber: 'glass' }]; + const storeData = { + order: { + lineItems: { glassParts } + } + }; + const propsData = { availableVaps: null }; + const { wrapper } = getMountedComponent(storeData, {}, propsData); + const expected = glassParts; + + // Act + const result = wrapper.vm.availableLineItems; + + // Assert + expect(result).toStrictEqual(expected); + }); + test('returns expected when supportingItems not null', async () => { + // Arrange + const supportingItems = [{ partNumber: 'support' }]; + const storeData = { + order: { + lineItems: { supportingItems } + } + }; + const propsData = { availableVaps: null }; + const { wrapper } = getMountedComponent(storeData, {}, propsData); + const expected = supportingItems; + + // Act + const result = wrapper.vm.availableLineItems; + + // Assert + expect(result).toStrictEqual(expected); + }); + test('returns expected when otherParts not null', () => { + // Arrange + const otherParts = [{ partNumber: 'other' }]; + const storeData = { + order: { + lineItems: { otherParts } + } + }; + const propsData = { availableVaps: null }; + const { wrapper } = getMountedComponent(storeData, {}, propsData); + const expected = otherParts; + + // Act + const result = wrapper.vm.availableLineItems; + + // Assert + expect(result).toStrictEqual(expected); + }); + test('returns expected when mobileFee not null', () => { + // Arrange + const mobileFee = { partNumber: 'mobile' }; + const storeData = { + order: { + lineItems: { + feeItems: [mobileFee] + } + } + }; + const propsData = { availableVaps: null }; + const { wrapper } = getMountedComponent(storeData, {}, propsData); + const expected = [mobileFee]; + + // Act + const result = wrapper.vm.availableLineItems; + + // Assert + expect(result).toStrictEqual(expected); + }); + test('returns expected when availableVaps null', async () => { + // Arrange + const availableVaps = [{ partNumber: 'vaps1' }]; + const initialData = { availableVaps }; + const { wrapper } = getMountedComponent({}, initialData, {}); + const expected = availableVaps; + + // Act + const result = wrapper.vm.availableLineItems; + + // Assert + expect(result).toStrictEqual(expected); + }); + test('returns expected when glassParts, supportingItems, otherParts, mobileFee, and availableVaps have content', async () => { + // Arrange + const part1 = { partType: 'apple' }; + const part2 = { partType: 'banana' }; + const part3 = { partType: 'orange' }; + const part4 = { partType: 'grape' }; + const part5 = { partType: 'raspberry' }; + const mobileFee = { partType: 'mobile' }; + const storeData = { + order: { + lineItems: { + glassParts: [part1], + supportingItems: [part2, part3], + otherParts: [], + feeItems: [mobileFee] + } + } + }; + const initialData = { + availableVaps: [part4, part5] + }; + const { wrapper } = getMountedComponent(storeData, initialData, {}); + const sortByPartType = (a, b) => { + const typeA = a.partType.toUpperCase(); + const typeB = b.partType.toUpperCase(); + if (typeA < typeB) { + return -1; + } + if (typeA > typeB) { + return 1; + } + return 0; + }; + const expected = [part1, part2, part3, part4, part5, mobileFee]; + + // Act + const result = wrapper.vm.availableLineItems; + + // Assert + expect(result.sort(sortByPartType)).toStrictEqual(expected.sort(sortByPartType)); + }); + }); + describe('servicePackageCartItems', () => { + test.each([ + [undefined], [null], [[]] + ])('returns empty list when package contents %p', (packageContents) => { + // Arrange + getPackageContents.mockImplementationOnce(() => packageContents); + const { wrapper } = getMountedComponent(); + const expected = []; + + // Act + const result = wrapper.vm.servicePackageCartItems; + + // Assert + expect(result).toStrictEqual(expected); + }); + test('returns front wiper when front wiper included in types', () => { + // Arrange + const frontWiperPartType = partTypeStrings.FRONT_WIPER; + const packageContents = [frontWiperPartType]; + getPackageContents.mockImplementation(() => packageContents); + + const mountOptions = getMountOptions({ + router: { navigate: jest.fn() } + }); + const expectedName = 'some name'; + const vapsItemDescriptions = [ + { + Name: frontWiperPartType, + Text: expectedName + } + ]; + const widgetName = 'VapsItemDescriptions'; + const mockMixin = { + methods: { + getCmsContent: jest.fn((widget, _) => (widget === widgetName ? vapsItemDescriptions : [])) + } + }; + mountOptions.mixins = [mockMixin]; + const storeData = { + order: { + lineItems: { + vaps: [{ partType: frontWiperPartType }] + } + } + }; + const testingPinia = createTestingPinia({ + initialState: { + main: storeData + } + }); + useMainStore(testingPinia); + mountOptions.global.plugins = [testingPinia]; + + const wrapper = shallowMount(confirmationCart, mountOptions); + + // Act + const result = wrapper.vm.servicePackageCartItems; + + // Assert + expect(result.length).toBe(1); + expect(result[0].name).toBe(expectedName); + }); + test('returns rear wiper when rear wiper included in types', () => { + // Arrange + const rearWiperPartType = partTypeStrings.REAR_WIPER; + const packageContents = [rearWiperPartType]; + getPackageContents.mockImplementationOnce(() => packageContents); + + const mountOptions = getMountOptions({ + router: { navigate: jest.fn() } + }); + const expectedName = 'some other name'; + const vapsItemDescriptions = [ + { + Name: rearWiperPartType, + Text: expectedName + } + ]; + const mockMixin = { + methods: { + getCmsContent: jest.fn(() => vapsItemDescriptions) + } + }; + mountOptions.mixins = [mockMixin]; + const storeData = { + order: { + lineItems: { + vaps: [{ partType: rearWiperPartType }] + } + } + }; + const testingPinia = createTestingPinia({ + initialState: { + main: storeData + } + }); + useMainStore(testingPinia); + mountOptions.global.plugins = [testingPinia]; + + const wrapper = shallowMount(confirmationCart, mountOptions); + + // Act + const result = wrapper.vm.servicePackageCartItems; + + // Assert + expect(result.length).toBe(1); + expect(result[0].name).toBe(expectedName); + }); + test('returns rain defense when rain defense included in types', () => { + // Arrange + const rainDefensePartType = partTypeStrings.RAIN_DEFENSE; + const packageContents = [rainDefensePartType]; + getPackageContents.mockImplementationOnce(() => packageContents); + + const mountOptions = getMountOptions({ + router: { navigate: jest.fn() } + }); + const expectedName = 'different name'; + const vapsItemDescriptions = [ + { + Name: rainDefensePartType, + Text: expectedName + } + ]; + const mockMixin = { + methods: { + getCmsContent: jest.fn(() => vapsItemDescriptions) + } + }; + mountOptions.mixins = [mockMixin]; + const storeData = { + order: { + lineItems: { + vaps: [{ partType: rainDefensePartType }] + } + } + }; + const testingPinia = createTestingPinia({ + initialState: { + main: storeData + } + }); + useMainStore(testingPinia); + mountOptions.global.plugins = [testingPinia]; + + const wrapper = shallowMount(confirmationCart, mountOptions); + + // Act + const result = wrapper.vm.servicePackageCartItems; + + // Assert + expect(result.length).toBe(1); + expect(result[0].name).toBe(expectedName); + }); + test('returns expected when all included in types', () => { + // Arrange + const frontWiperPartType = partTypeStrings.FRONT_WIPER; + const rearWiperPartType = partTypeStrings.REAR_WIPER; + const rainDefensePartType = partTypeStrings.RAIN_DEFENSE; + const packageContents = [frontWiperPartType, rearWiperPartType, rainDefensePartType]; + getPackageContents.mockImplementationOnce(() => packageContents); + + const mountOptions = getMountOptions({ + router: { navigate: jest.fn() } + }); + const expectedFrontWiperName = 'front wiper'; + const expectedRearWiperName = 'rear wiper'; + const expectedRainDefenseName = 'rain repel'; + const vapsItemDescriptions = [ + { + Name: frontWiperPartType, + Text: expectedFrontWiperName + }, + { + Name: rearWiperPartType, + Text: expectedRearWiperName + }, + { + Name: rainDefensePartType, + Text: expectedRainDefenseName + } + ]; + const mockMixin = { + methods: { + getCmsContent: jest.fn(() => vapsItemDescriptions) + } + }; + mountOptions.mixins = [mockMixin]; + const storeData = { + order: { + lineItems: { + vaps: [ + { partType: frontWiperPartType }, + { partType: rearWiperPartType }, + { partType: rainDefensePartType } + ] + } + } + }; + const testingPinia = createTestingPinia({ + initialState: { + main: storeData + } + }); + useMainStore(testingPinia); + mountOptions.global.plugins = [testingPinia]; + + const wrapper = shallowMount(confirmationCart, mountOptions); + + // Act + const result = wrapper.vm.servicePackageCartItems; + + // Assert + expect(result.length).toBe(3); + expect(result).toContainEqual(expect.objectContaining({ + name: expectedFrontWiperName + })); + expect(result).toContainEqual(expect.objectContaining({ + name: expectedRearWiperName + })); + expect(result).toContainEqual(expect.objectContaining({ + name: expectedRainDefenseName + })); + }); + }); + describe('nonServicePackageCartItems', () => { + test('when recycleFee, includes recycle fee', () => { + // Arrange + const storeData = { + order: { + lineItems: { + feeItems: [ + { + partNumber: partNumberStrings.RECYCLE_FEE + } + ] + } + } + }; + const { wrapper } = getMountedComponent(storeData); + + // Act + const result = wrapper.vm.nonServicePackageCartItems; + + // Assert + expect(result).toContainEqual(expect.objectContaining({ + partType: partTypeStrings.REPLACE_FEE + })); + }); + test('when mobileFee, includes mobile fee', () => { + // Arrange + const storeData = { + order: { + lineItems: { + feeItems: [{ 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: { + feeItems: [ + { partType: partTypeStrings.MOBILE_FEE }, + { partNumber: partNumberStrings.RECYCLE_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({ + partType: partTypeStrings.REPLACE_FEE + })); + expect(result).toContainEqual(expect.objectContaining({ + partType: partTypeStrings.MOBILE_FEE + })); + expect(result).toContainEqual(expect.objectContaining({ + partType: partTypeStrings.REAR_WIPER + })); + }); + }); + describe('servicePackageLabelWidget', () => { + test.each([ + [null], + [undefined] + ])('returns "" when servicePackageNames %p', (servicePackageNames) => { + // Arrange + const mountOptions = getMountOptions({ + router: { navigate: jest.fn() } + }); + const mockMixin = { + methods: { + getCmsContent: jest.fn(() => servicePackageNames) + } + }; + mountOptions.mixins = [mockMixin]; + + const wrapper = shallowMount(confirmationCart, mountOptions); + + // Act + const result = wrapper.vm.servicePackageLabelWidget; + + // Assert + expect(result).toBe(''); + }); + test('returns "" when servicePackageTier not found in servicePackageNames', () => { + // Arrange + const mountOptions = getMountOptions({ + router: { navigate: jest.fn() } + }); + getHighestFullySatisfiedTier.mockImplementationOnce(() => 'some other tier'); + const servicePackageNames = [{ Name: 'some tier' }]; + const mockMixin = { + methods: { + getCmsContent: jest.fn(() => servicePackageNames) + } + }; + mountOptions.mixins = [mockMixin]; + const wrapper = shallowMount(confirmationCart, mountOptions); + + // Act + const result = wrapper.vm.servicePackageLabelWidget; + + // Assert + expect(result).toBe(''); + }); + test('returns "" when servicePackageTier has no SubWidgetName', () => { + // Arrange + const mountOptions = getMountOptions({ + router: { navigate: jest.fn() } + }); + const tier = 'tier1'; + getHighestFullySatisfiedTier.mockImplementationOnce(() => tier); + const servicePackageNames = [{ Name: tier }]; + const mockMixin = { + methods: { + getCmsContent: jest.fn(() => servicePackageNames) + } + }; + mountOptions.mixins = [mockMixin]; + const wrapper = shallowMount(confirmationCart, mountOptions); + + // Act + const result = wrapper.vm.servicePackageLabelWidget; + + // Assert + expect(result).toBe(''); + }); + test('returns expected when servicePackageTier has SubWidgetName', () => { + // Arrange + const mountOptions = getMountOptions({ + router: { navigate: jest.fn() } + }); + const tier = 'tier1'; + getHighestFullySatisfiedTier.mockImplementationOnce(() => tier); + const expected = 'name of sub widget'; + const servicePackageNames = [{ + Name: tier, + SubWidgetName: expected + }]; + const mockMixin = { + methods: { + getCmsContent: jest.fn(() => servicePackageNames) + } + }; + mountOptions.mixins = [mockMixin]; + const wrapper = shallowMount(confirmationCart, mountOptions); + + // Act + const result = wrapper.vm.servicePackageLabelWidget; + + // Assert + expect(result).toBe(expected); + }); + }); + describe('recycleFeeCartItem', () => { + test.each([ + [null], [undefined], [[]] + ])('returns null when supporting items %p', (supportingItems) => { + // Arrange + const storeData = { + order: { + lineItems: { supportingItems } + } + }; + const { wrapper } = getMountedComponent(storeData); + const expected = null; + + // Act + const result = wrapper.vm.recycleFeeCartItem; + + // Assert + expect(result).toStrictEqual(expected); + }); + test('returns null when recycle fee not in non empty supporting items', () => { + // Arrange + const storeData = { + order: { + lineItems: { + supportingItems: [{ partNumber: 'not recycle' }] + } + } + }; + const { wrapper } = getMountedComponent(storeData); + const expected = null; + + // Act + const result = wrapper.vm.recycleFeeCartItem; + + // Assert + expect(result).toStrictEqual(expected); + }); + test('returns expected when recycle fee in fee items', () => { + // Arrange + const mountOptions = getMountOptions({ + router: { navigate: jest.fn() } + }); + const expectedName = 'recycling fee'; + const widgetName = 'RecycleFeeWidget'; + const mockMixin = { + methods: { + getCmsContent: jest.fn((widget, _) => (widget === widgetName ? expectedName : [])) + } + }; + mountOptions.mixins = [mockMixin]; + const storeData = { + order: { + lineItems: { + feeItems: [{ partNumber: partNumberStrings.RECYCLE_FEE }] + } + } + }; + const testingPinia = createTestingPinia({ + initialState: { + main: storeData + } + }); + useMainStore(testingPinia); + mountOptions.global.plugins = [testingPinia]; + + const wrapper = shallowMount(confirmationCart, mountOptions); + + // Act + const result = wrapper.vm.recycleFeeCartItem; + + // Assert + expect(result.name).toBe(expectedName); + }); + }); + describe('mobileFeeCartItem', () => { + test.each([[null], [undefined]])('returns null when mobile fee %p', (mobileFee) => { + // Arrange + const storeData = { + order: { + lineItems: { mobileFee } + } + }; + const { wrapper } = getMountedComponent(storeData); + const expected = null; + + // Act + const result = wrapper.vm.mobileFeeCartItem; + + // Assert + expect(result).toStrictEqual(expected); + }); + test('returns expected when mobile fee in fee items', () => { + // Arrange + const mountOptions = getMountOptions({ + router: { navigate: jest.fn() } + }); + const expectedName = 'mobile fee'; + const widgetName = 'MobileServiceWidget'; + const mockMixin = { + methods: { + getCmsContent: jest.fn((widget, _) => (widget === widgetName ? expectedName : [])) + } + }; + mountOptions.mixins = [mockMixin]; + const storeData = { + order: { + lineItems: { + feeItems: [{ partType: partTypeStrings.MOBILE_FEE }] + } + } + }; + const testingPinia = createTestingPinia({ + initialState: { + main: storeData + } + }); + useMainStore(testingPinia); + mountOptions.global.plugins = [testingPinia]; + + const wrapper = shallowMount(confirmationCart, mountOptions); + + // Act + const result = wrapper.vm.mobileFeeCartItem; + + // Assert + expect(result.name).toBe(expectedName); + }); + }); + 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); + }); + }); + }); + describe('method', () => { + const dollarAmount = '$84.00'; + describe.each([ + [VERIFYING_COVERAGE, coverageStatuses.PENDING, coverageType.NONE], + [VERIFYING_COVERAGE, coverageStatuses.PENDING, coverageType.NO_COMP], + [VERIFYING_COVERAGE, coverageStatuses.PENDING, coverageType.ITAC], + [VERIFYING_COVERAGE, coverageStatuses.PENDING, coverageType.Deductible], + [dollarAmount, coverageStatuses.VERIFIED, coverageType.NO_COMP], + [dollarAmount, coverageStatuses.VERIFIED, coverageType.ITAC], + [dollarAmount, coverageStatuses.VERIFIED, coverageType.Deductible], + [VERIFYING_COVERAGE, coverageStatuses.NO_COVERAGE, coverageType.NONE], + [VERIFYING_COVERAGE, coverageStatuses.NO_COVERAGE, coverageType.NO_COMP], + [VERIFYING_COVERAGE, coverageStatuses.NO_COVERAGE, coverageType.ITAC], + [VERIFYING_COVERAGE, coverageStatuses.NO_COVERAGE, coverageType.Deductible] + ])('getDisplayed', (expected, status, type) => { + test(`returns ${expected} when coverage status ${getEnumName(coverageStatuses, status)} and coverageType is ${getEnumName(coverageType, type)}`, () => { + // Arrange + const storeData = { + order: { + insuranceCoverage: { + coverageStatus: status, + coverageType: type + }, + currentDeductible: 321 + } + }; + + const { wrapper } = getMountedComponent(storeData); + formatAmountInDollars.mockReturnValueOnce(dollarAmount); + + // Act + const result = wrapper.vm.getDisplayed(0); + + // Assert + expect(result).toBe(expected); + }); + }); + describe('getCartItemForVapsPart', () => { + test('returns item with no label when no descriptions returned', () => { + // Arrange + const mountOptions = getMountOptions({ + router: { navigate: jest.fn() } + }); + const descriptions = []; + const widgetName = 'VapsItemDescriptions'; + const mockMixin = { + methods: { + getCmsContent: jest.fn((widget, _) => (widget === widgetName ? descriptions : [])) + } + }; + mountOptions.mixins = [mockMixin]; + const part = 'some part'; + const storeData = { + order: { + lineItems: { + vaps: [{ partType: part }] + } + } + }; + const testingPinia = createTestingPinia({ + initialState: { + main: storeData + } + }); + useMainStore(testingPinia); + mountOptions.global.plugins = [testingPinia]; + const wrapper = shallowMount(confirmationCart, mountOptions); + + const expectedName = ''; + + // Act + const result = wrapper.vm.getCartItemForVapsPart(part); + + // Assert + expect(result.name).toBe(expectedName); + }); + test('returns item with no label when type not in descriptions', () => { + // Arrange + const mountOptions = getMountOptions({ + router: { navigate: jest.fn() } + }); + const descriptions = [{ + Name: 'not part name' + }]; + const widgetName = 'VapsItemDescriptions'; + const mockMixin = { + methods: { + getCmsContent: jest.fn((widget, _) => (widget === widgetName ? descriptions : [])) + } + }; + mountOptions.mixins = [mockMixin]; + const part = 'some part'; + const storeData = { + order: { + lineItems: { + vaps: [{ partType: part }] + } + } + }; + const testingPinia = createTestingPinia({ + initialState: { + main: storeData + } + }); + useMainStore(testingPinia); + mountOptions.global.plugins = [testingPinia]; + const wrapper = shallowMount(confirmationCart, mountOptions); + + const expectedName = ''; + + // Act + const result = wrapper.vm.getCartItemForVapsPart(part); + + // Assert + expect(result.name).toBe(expectedName); + }); + test('returns item with no label when description text not defined', () => { + // Arrange + const mountOptions = getMountOptions({ + router: { navigate: jest.fn() } + }); + const part = 'some part'; + const descriptions = [{ + Name: part + }]; + const widgetName = 'VapsItemDescriptions'; + const mockMixin = { + methods: { + getCmsContent: jest.fn((widget, _) => (widget === widgetName ? descriptions : [])) + } + }; + mountOptions.mixins = [mockMixin]; + const storeData = { + order: { + lineItems: { + vaps: [{ partType: part }] + } + } + }; + const testingPinia = createTestingPinia({ + initialState: { + main: storeData + } + }); + useMainStore(testingPinia); + mountOptions.global.plugins = [testingPinia]; + const wrapper = shallowMount(confirmationCart, mountOptions); + const expectedName = ''; + + // Act + const result = wrapper.vm.getCartItemForVapsPart(part); + + // Assert + expect(result.name).toBe(expectedName); + }); + test('returns expected label when vaps description text set', () => { + // Arrange + const mountOptions = getMountOptions({ + router: { navigate: jest.fn() } + }); + const part = 'some part'; + const expectedName = 'name to show up'; + const descriptions = [{ + Name: part, + Text: expectedName + }]; + const widgetName = 'VapsItemDescriptions'; + const mockMixin = { + methods: { + getCmsContent: jest.fn((widget, _) => (widget === widgetName ? descriptions : [])) + } + }; + mountOptions.mixins = [mockMixin]; + const storeData = { + order: { + lineItems: { + vaps: [{ partType: part }] + } + } + }; + const testingPinia = createTestingPinia({ + initialState: { + main: storeData + } + }); + useMainStore(testingPinia); + mountOptions.global.plugins = [testingPinia]; + const wrapper = shallowMount(confirmationCart, mountOptions); + + // Act + const result = wrapper.vm.getCartItemForVapsPart(part); + + // Assert + expect(result.name).toBe(expectedName); + }); + test.each([ + [undefined], [null] + ])('returns null when vapsInOrder %p', async (vapsInOrder) => { + // Arrange + const mountOptions = getMountOptions({ + router: { navigate: jest.fn() } + }); + const part = 'some part'; + const expectedName = 'name to show up'; + const descriptions = [{ + Name: part, + Text: expectedName + }]; + const widgetName = 'VapsItemDescriptions'; + const mockMixin = { + methods: { + getCmsContent: jest.fn((widget, _) => (widget === widgetName ? descriptions : [])) + } + }; + mountOptions.mixins = [mockMixin]; + const storeData = { + order: { + lineItems: { + vaps: vapsInOrder + } + } + }; + const testingPinia = createTestingPinia({ + initialState: { + main: storeData + } + }); + useMainStore(testingPinia); + mountOptions.global.plugins = [testingPinia]; + const wrapper = shallowMount(confirmationCart, mountOptions); + + // Act + const result = wrapper.vm.getCartItemForVapsPart(part); + + // Assert + expect(result).toBe(null); + }); + test('returns item with expected price when part type found in vapsInOrder', () => { + // Arrange + const mountOptions = getMountOptions({ + router: { navigate: jest.fn() } + }); + const part = 'some part'; + const vaps = [{ partType: part }]; + const storeData = { + order: { + lineItems: { vaps } + } + }; + const testingPinia = createTestingPinia({ + initialState: { + main: storeData + } + }); + useMainStore(testingPinia); + mountOptions.global.plugins = [testingPinia]; + const expectedSubtotal = 93; + getPriceOfLineItems.mockImplementation(() => expectedSubtotal); + const wrapper = shallowMount(confirmationCart, mountOptions); + + // Act + const result = wrapper.vm.getCartItemForVapsPart(part); + + // Assert + expect(result.subTotal).toBe(expectedSubtotal); + }); + }); + }); +}); diff --git a/src/iss-components/confirmation-cart/confirmation-cart.vue b/src/iss-components/confirmation-cart/confirmation-cart.vue new file mode 100644 index 00000000..f459cd2a --- /dev/null +++ b/src/iss-components/confirmation-cart/confirmation-cart.vue @@ -0,0 +1,478 @@ + + + + + diff --git a/src/layouts/order-confirmation/order-confirmation.vue b/src/layouts/order-confirmation/order-confirmation.vue index c3514995..fcd9dea5 100644 --- a/src/layouts/order-confirmation/order-confirmation.vue +++ b/src/layouts/order-confirmation/order-confirmation.vue @@ -8,21 +8,34 @@
-
-
-
+
+
+
-
-
-

{{ formatDate(schedule.date) }}

-

- {{ appointmentTimeText }} -

-
+
+ + +
+
+ {{ serviceDescriptionText }} +
+
+ {{ workOrderTitle }} + {{ workOrderNumber }} +
+
+ {{ appointmentWordingText }} + {{ formatDate(schedule.date) }} + {{ appointmentTimeText }} + {{ appointmentLocation }} -
-
-
-
- +
+ {{ wipersTitle }} + {{ description }} +
+
+ {{ rainRepelTitle }} + {{ rainRepelBody }}
-
+
+ {{ contactDetailsTitle }} + {{ contactDetailsBody }} +
+
+
+ {{ cartHeaderText }} +
+ +
@@ -81,7 +108,7 @@ import siteHeader from '@/iss-components/site-header/site-header.vue'; import siteFooter from '@/iss-components/site-footer/site-footer.vue'; import addToCalendar from '@/layouts/order-confirmation/add-to-calendar/add-to-calendar.vue'; -import cartDropdown from '@/iss-components/cart-dropdown/cart-dropdown.vue'; +import confirmationCart from '@/iss-components/confirmation-cart/confirmation-cart.vue'; // Supporting files import { @@ -103,6 +130,9 @@ import { toTitleCase } from '@/helpers/text-helper.js'; import { AppointmentTypeStrings } from '@/constants/schedule-constants'; import applicationConfig from '@/constants/application-config'; import widgetFields from '@/constants/cms-widget-fields.js'; +import { getGlassList } from '@/helpers/damage-helper'; +import partTypeStrings from '@/constants/part-type-strings'; +import coverageType from '@/constants/coverage-type'; export default { name: 'order-confirmation', @@ -112,18 +142,23 @@ export default { siteHeader, siteFooter, addToCalendar, - cartDropdown + confirmationCart }, mixins: [BaseFormMixin], async beforeRouteEnter(to, from, next) { // Call APIs const cmsContentPromise = fetchCmsContentForPage(to.query.issPage); + const glassTypesPromise = useMainStore().getSV2GlassTypes(useMainStore().getSubmittedOrder().damage.glassToReplace); // Settle promises and get results const promiseResultMap = [ { resultKey: 'cmsContent', promise: cmsContentPromise + }, + { + resultKey: 'glassTypes', + promise: glassTypesPromise } ]; // use resultMap to populate layout content. @@ -131,6 +166,9 @@ export default { next((vm) => { vm.setCmsContent(resultMap.cmsContent); + vm.setData({ + glassTypes: resultMap.glassTypes + }) }); }, setup() { @@ -144,18 +182,21 @@ export default { serviceLocation, schedule, customer, + contactInfo, payment, customerPortalLoginToken, damage, - referralNumber + referralNumber, + hasRecalibrationPart } = this.submittedOrder; - const { issConfig, hasRecalibrationPart } = this.mainStore; + const { issConfig } = this.mainStore; return { vehicle, customerEmail: customer?.emailAddress, payment, schedule, serviceLocation, + contactInfo, appointmentType: serviceLocation.appointmentType, providerAddress: serviceLocation?.provider?.address, customerPortalLoginToken, @@ -164,12 +205,24 @@ export default { isRepair: damage.isRepair, hasRecalibrationPart, referralNumber: referralNumber?.toString(), + glassTypes: [], + isNoComp: this.submittedOrder.insuranceCoverage.coverageType === coverageType.NO_COMP, widgets: { siteHeader: 'SiteHeaderWidget', emailConfirmation: 'EmailConfirmationWordingWidget', + emailConfirmationNoComp: 'EmailConfirmationNoCompWordingWidget', orderConfirmation: 'OrderConfirmationContent', + serviceDescription: 'ServiceDescriptionTextWidget', + workOrderNumberTitle: 'WorkOrderNumberTextWidget', mobile: 'MobileWordingWidget', dropOffAndInShop: 'DropOffAndInShopWordingWidget', + wipersText: 'WipersTextWidget', + rainRepel: 'RainRepelWidget', + smsUpdates: 'SmsUpdatesWidget', + contactDetails: 'ContactDetailsWidget', + vapsItemDescriptions: 'VapsItemDescriptions', + payAtAppointment: 'PayAtAppointmentTextWidget', + orderDetails: 'OrderDetailsTextWidget', siteFooter: 'SiteFooterWidget' } }; @@ -182,18 +235,29 @@ export default { vehicleYear: this.vehicle?.year, vehicleMake: this.vehicle?.make, vehicleModel: this.vehicle?.model, + serviceType: this.serviceTypeText, address: this.appointmentLocation, inShopDuration: this.inShopAppointmentDuration, email: this.customerEmail, + phone: this.contactInfo.servicePhone, + workOrderNumber: this.workOrderNumber, CUSTOMER_PORTAL_URL: applicationConfig.CUSTOMER_PORTAL_URL, CUSTOMER_PORTAL_LOGIN_TOKEN: this.customerPortalLoginToken }; }, - confirmationEmailText() { - const content = this.getCmsContentWithCustomValues( - this.widgets.emailConfirmation, - widgetFields.CONTENT_GROUP_WIDGET.BODY_TEXT - ); + orderConfirmationUpdateAppointmentText() { + let content = ''; + if(this.isNoComp) { + content = this.getCmsContentWithCustomValues( + this.widgets.emailConfirmationNoComp, + widgetFields.CONTENT_GROUP_WIDGET.BODY_TEXT + ); + } else { + content = this.getCmsContentWithCustomValues( + this.widgets.emailConfirmation, + widgetFields.CONTENT_GROUP_WIDGET.BODY_TEXT + ); + } return content ?.replaceAll('<', '<') ?.replaceAll('>', '>'); @@ -210,10 +274,50 @@ export default { widgetFields.CONTENT_GROUP_WIDGET.IMAGE ); }, + orderConfirmationSubheaderText() { + return this.getCmsContent( + this.widgets.orderConfirmation, + widgetFields.CONTENT_GROUP_WIDGET.SUBHEADER_TEXT + ); + }, + serviceDescriptionText() { + const content = this.getCmsContentWithCustomValues( + this.widgets.serviceDescription, + widgetFields.TEXT_BLOCK_WIDGET.TEXT + ); + return content; + }, + serviceTypeText() { + let glassList = getGlassList(this.glassTypes); + let workType = ''; + if (this.isRepair) { + workType = 'repair'; + } else { + workType = 'replacement'; + if (this.hasRecalibrationPart) { + if (glassList === 'windshield') { + workType = 'replacement and recalibration'; + } + else { + glassList = glassList.replace('windshield', 'windshield replacement, recalibration'); + } + } + } + return `${glassList} ${workType}`; + }, + workOrderTitle() { + return this.getCmsContent( + this.widgets.workOrderNumberTitle, + widgetFields.TEXT_BLOCK_WIDGET.TEXT + ); + }, + workOrderNumber() { + return this.submittedOrder.workOrderNumber; + }, mobileWordingText() { return this.getCmsContentWithCustomValues( this.widgets.mobile, - widgetFields.CONTENT_GROUP_WIDGET.BODY_TEXT + widgetFields.CONTENT_GROUP_WIDGET.HEADER_TEXT ); }, mobileWordingText2() { @@ -225,7 +329,7 @@ export default { nonMobileWordingText() { return this.getCmsContentWithCustomValues( this.widgets.dropOffAndInShop, - widgetFields.CONTENT_GROUP_WIDGET.BODY_TEXT + widgetFields.CONTENT_GROUP_WIDGET.HEADER_TEXT ); }, nonMobileWordingText2() { @@ -241,12 +345,12 @@ export default { } if (this.isInShopAppointment) { const formattedStartTime = get12HourTimeFormat(startTime); - return `at ${formattedStartTime}`; + return `Your appointment is at ${formattedStartTime}`; } if (this.isMobileAppointment) { const mobileStartTime = get12HourTimeMobileFormat(startTime); const mobileEndTime = get12HourTimeMobileFormat(endTime); - return `Between ${mobileStartTime} - ${mobileEndTime}`; + return `Your appointment is at ${mobileStartTime} - ${mobileEndTime}`; } return null; }, @@ -261,12 +365,12 @@ export default { }, serviceLocationFullAddress() { const { address, address2, city, state, zipCode } = this.serviceLocation; - return `${address ?? ''}, ${address2 ? `${address2},` : ''}
${city ?? ''}, ${state ?? ''} ${zipCode ?? ''}`; + return `${address ?? ''}, ${address2 ? `${address2},` : ''} ${city ?? ''}, ${state ?? ''} ${zipCode ?? ''}`; }, providerFullAddress() { const { streetAddress, city, state, zipCode } = this.providerAddress; return streetAddress - ? `${toTitleCase(streetAddress)},
${toTitleCase(city)}, ${state ?? ''} ${zipCode ?? ''}` + ? `${toTitleCase(streetAddress)}, ${toTitleCase(city)}, ${state ?? ''} ${zipCode ?? ''}` : ''; }, appointmentWordingText() { @@ -317,7 +421,85 @@ export default { // settleTenderAmount always shows 0 via localhost or dev. // Temporarily set return true to see cart in localhost or dev environment - return false; + return true; + }, + displayWipers() { + const hasWiperPart = this.submittedOrder.lineItems.vaps.some((part) => part.partType.toLowerCase().includes('wiper')); + return hasWiperPart; + }, + wipersTitle() { + return this.getCmsContent( + this.widgets.wipersText, + widgetFields.TEXT_BLOCK_WIDGET.TEXT + ); + }, + wipersBody() { + const wiperTypesOnOrder = []; + + const hasFrontWiper = this.submittedOrder.lineItems.vaps.some((part) => part.partType === partTypeStrings.FRONT_WIPER); + const hasRearWiper = this.submittedOrder.lineItems.vaps.some((part) => part.partType === partTypeStrings.REAR_WIPER); + + if (hasFrontWiper) { + wiperTypesOnOrder.push(partTypeStrings.FRONT_WIPER); + } + if (hasRearWiper) { + wiperTypesOnOrder.push(partTypeStrings.REAR_WIPER); + } + + const wiperDescriptions = wiperTypesOnOrder.map((type) => { + return this.getCmsContentForVapsType(type); + }); + + return wiperDescriptions; + }, + displayRainRepel() { + return this.submittedOrder.lineItems.vaps.some((part) => part.partType === partTypeStrings.RAIN_DEFENSE); + }, + rainRepelTitle() { + return this.getCmsContent( + this.widgets.rainRepel, + widgetFields.CONTENT_GROUP_WIDGET.HEADER_TEXT + ); + }, + rainRepelBody() { + return this.getCmsContent( + this.widgets.rainRepel, + widgetFields.CONTENT_GROUP_WIDGET.BODY_TEXT + ); + }, + displaySMSPhone() { + return this.contactInfo.requestTextUpdates && this.contactInfo.servicePhone; + }, + smsTitle() { + return this.getCmsContent( + this.widgets.smsUpdates, + widgetFields.TEXT_BLOCK_WIDGET.TEXT + ); + }, + contactDetailsTitle() { + return this.getCmsContent( + this.widgets.contactDetails, + widgetFields.CONTENT_GROUP_WIDGET.HEADER_TEXT + ); + }, + contactDetailsBody() { + return this.getCmsContentWithCustomValues( + this.widgets.contactDetails, + widgetFields.CONTENT_GROUP_WIDGET.BODY_TEXT + ); + }, + cartHeaderText() { + if (this.payment.isPayInAdvance) { + return this.getCmsContent( + this.widgets.orderDetails, + widgetFields.TEXT_BLOCK_WIDGET.TEXT + ); + } else { + return this.getCmsContent( + this.widgets.payAtAppointment, + widgetFields.TEXT_BLOCK_WIDGET.TEXT + ); + } } }, mounted() { @@ -411,68 +593,135 @@ export default { return dateObject.toLocaleDateString('en-us', { weekday: 'long', month: 'long', - day: 'numeric' + day: 'numeric', + year: 'numeric' }); + }, + setData({ glassTypes }) { + this.glassTypes = glassTypes; + }, + getCmsContentForVapsType(vapsPartType) { + const vapsItemDescriptions = this.getCmsContent( + this.widgets.vapsItemDescriptions, + widgetFields.INPUT_QUESTION_WIDGET.ANSWERS + ); + + if (!vapsItemDescriptions) { + return ''; + } + + const vapsTypeDescription = vapsItemDescriptions?.find((entry) => entry?.Name === vapsPartType); + return vapsTypeDescription?.Text ?? ''; } } }; diff --git a/src/layouts/payment-method/payment-method.vue b/src/layouts/payment-method/payment-method.vue index 195909ec..2ec3d29e 100644 --- a/src/layouts/payment-method/payment-method.vue +++ b/src/layouts/payment-method/payment-method.vue @@ -24,8 +24,7 @@
diff --git a/src/store/index.js b/src/store/index.js index d74067f7..05961894 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -2874,6 +2874,19 @@ export const useMainStore = defineStore({ }); }, + async getSV2GlassTypes(glassPieces) { + const glassArray = convertGlassPieceNamingForApi(glassPieces); + const response = await globalMethods.callHttpClient({ + method: endpoints.GetSV2GlassTypes.method, + endpoint: endpoints.GetSV2GlassTypes.url, + payload: { + glassPieces: glassArray, + formatWithSpaces: true + } + }); + return response.data; + }, + hasSubmittedOrder() { return window.sessionStorage.getItem(webStorageConstants.SUBMITTED_ORDER) !== null; }, @@ -2889,12 +2902,13 @@ export const useMainStore = defineStore({ await this.getCarrierAccountInfo(); const submittedOrder = this.order; const { experiments } = this.applicationUser; - const { issConfig } = this; + const { issConfig, hasRecalibrationPart } = this; submittedOrder.isUnverified = this.isUnverified; submittedOrder.isVerified = this.isVerified; submittedOrder.submitType = submitType; submittedOrder.payment.isPayInAdvance = this.isPayInAdvance; + submittedOrder.hasRecalibrationPart = hasRecalibrationPart; // set to local storage window.sessionStorage.setItem(webStorageConstants.SUBMITTED_ORDER, JSON.stringify(submittedOrder)); From 4dab87bf3fbabde62c00301119164de5c968c895 Mon Sep 17 00:00:00 2001 From: Alex Humphries Date: Wed, 11 Feb 2026 14:08:58 -0500 Subject: [PATCH 02/11] INSR-7757: More cart updates --- src/constants/cart-item-type.js | 3 +- src/constants/part-type-strings.js | 3 +- .../cart-dropdown/cart-dropdown.vue | 410 ++--- .../confirmation-cart.spec.js | 1580 ----------------- .../confirmation-cart/confirmation-cart.vue | 478 ----- .../order-confirmation/order-confirmation.vue | 13 +- src/layouts/payment-method/payment-method.vue | 1 - src/layouts/payment-page/payment-page.vue | 3 +- src/store/index.js | 5 + 9 files changed, 199 insertions(+), 2297 deletions(-) delete mode 100644 src/iss-components/confirmation-cart/confirmation-cart.spec.js delete mode 100644 src/iss-components/confirmation-cart/confirmation-cart.vue diff --git a/src/constants/cart-item-type.js b/src/constants/cart-item-type.js index b3e1ecf4..017e2951 100644 --- a/src/constants/cart-item-type.js +++ b/src/constants/cart-item-type.js @@ -1,7 +1,8 @@ const cartItemType = Object.freeze({ RECYCLE_FEE: 'RECYCLE FEE', MOBILE_FEE: 'MOBILE FEE', - VAP: 'VAP' + VAP: 'VAP', + WARRANTY: 'WARRANTY' }); export default cartItemType; diff --git a/src/constants/part-type-strings.js b/src/constants/part-type-strings.js index 040ca6ad..babee9a8 100644 --- a/src/constants/part-type-strings.js +++ b/src/constants/part-type-strings.js @@ -8,7 +8,8 @@ REPLACE_FEE: 'REPLACE FEE', MOBILE_FEE: 'MOBILE FEE', REPAIR_FEE: 'REPAIR FEE', - WARRANTY: 'WARRANTY' + WARRANTY: 'WARRANTY', + MOLDING: 'MOULDING' }); export default partTypeStrings; diff --git a/src/iss-components/cart-dropdown/cart-dropdown.vue b/src/iss-components/cart-dropdown/cart-dropdown.vue index 34788563..4e039152 100644 --- a/src/iss-components/cart-dropdown/cart-dropdown.vue +++ b/src/iss-components/cart-dropdown/cart-dropdown.vue @@ -1,156 +1,113 @@ @@ -176,28 +133,26 @@ import { isOrderUnverified } from '@/helpers/cart-helper'; import { getPriceOfLineItems, getTaxOfLineItems } from '@/helpers/price-calculator'; +import { processIfStatements } from '@/helpers/cms-content-helper'; const VERIFYING_COVERAGE = 'Verifying coverage'; const RECYCLING_MODAL_REF_NAME = 'RecycleModal'; export default { - name: 'cart-dropdown', + name: 'confirmation-cart', components: { contentGroupModal, textBlock, textLink }, props: { - showAsPaid: Boolean, readOnly: Boolean, + showAsPaid: Boolean, recyclingModalCmsWidgetName: String, - showDropdownHeader: Boolean, - isInitiallyExpanded: Boolean, submittedOrder: Object }, data() { return { - isExpanded: this.isInitiallyExpanded, widget: { amountDue: 'AmountDueTextWidget', amountPaid: 'AmountPaidTextWidget', @@ -208,7 +163,9 @@ export default { recycleFee: 'RecycleFeeWidget', mobileFee: 'MobileServiceWidget', servicePackage: 'ServicePackageTitle', - vapsItemDescriptions: 'VapsItemDescriptions' + vapsItemDescriptions: 'VapsItemDescriptions', + warrantyText: 'WarrantyCartItemTextWidget', + guaranteeText: 'GuaranteeCartItemTextWidget' }, cartItemType, RECYCLING_MODAL_REF_NAME @@ -273,7 +230,7 @@ export default { return result; }, vehicleDamage() { - return this.submittedOrder ? this.submittedOrder.damage : useMainStore().damage; + return this.cartOrder.damage; }, servicePackageTier() { const { glassToReplace, isRepair } = this.vehicleDamage; @@ -333,6 +290,9 @@ export default { if (this.mobileFeeCartItem && !isMobileFeeHidden) { items.push(this.mobileFeeCartItem); } + if (this.isITAC || this.isNoComp) { + items.push(this.warrantyCartItem); + } return items; }, frontWipersCartItem() { @@ -350,12 +310,6 @@ export default { ...this.nonServicePackageCartItems ]; }, - packagePrice() { - return this.servicePackageCartItems?.reduce( - (accumulator, cartItem) => accumulator + (cartItem?.subTotal ?? 0), - 0 - ) ?? 0; - }, amountDueLabel() { return this.getCmsContent(this.widget.amountDue, widgetFields.TEXT_BLOCK_WIDGET.TEXT); }, @@ -366,7 +320,13 @@ export default { return this.getCmsContent(this.widget.deductible, widgetFields.TEXT_BLOCK_WIDGET.TEXT); }, basePriceLabel() { - return this.getCmsContent(this.widget.basePrice, widgetFields.TEXT_BLOCK_WIDGET.TEXT); + const content = this.getCmsContent(this.widget.basePrice, widgetFields.TEXT_BLOCK_WIDGET.TEXT); + console.log('Base Price Label before processing if statements:', content); + return processIfStatements( + content, + 'custom', + this.getCustomValueFromString + ); }, subtotalLabel() { return this.getCmsContent(this.widget.subtotal, widgetFields.TEXT_BLOCK_WIDGET.TEXT); @@ -409,15 +369,29 @@ export default { partTypeStrings.MOBILE_FEE ) : null; + }, + warrantyCartItem() { + const label = this.cartOrder.damage.glassToReplace?.length > 0 + ? this.getCmsContent(this.widget.warrantyText, widgetFields.TEXT_BLOCK_WIDGET.TEXT) + : this.getCmsContent(this.widget.guaranteeText, widgetFields.TEXT_BLOCK_WIDGET.TEXT); + return { + name: label, + cartItemType: cartItemType.WARRANTY, + partType: partTypeStrings.WARRANTY, + subTotal: 0, + salesTax: 0 + } + }, + hasMoldingPart() { + return this.cartOrder.lineItems.glassParts?.some((glassPart) => { + return glassPart.childParts?.some((childPart) => childPart.partType === partTypeStrings.MOLDING); + }); } }, methods: { openModal(modalName) { this.$refs[modalName].openModal(); }, - toggleIsExpanded() { - this.isExpanded = !this.isExpanded; - }, getDisplayed(amount) { return this.isUnverified ? VERIFYING_COVERAGE @@ -461,6 +435,17 @@ export default { const vapsTypeDescription = vapsItemDescriptions?.find((entry) => entry?.Name === vapsPartType); return vapsTypeDescription?.Text ?? ''; }, + getCustomValueFromString(str) { + console.log(this.cartOrder) + switch (str) { + case 'isRepair': + return this.cartOrder.damage.isRepair; + case 'hasMoldingPart': + return this.hasMoldingPart; + default: + return null; + } + }, formatAmountInDollars } }; @@ -471,45 +456,38 @@ export default { $RECYCLING_MODAL_REF_NAME: 'RecycleModal'; -.force-no-top-margin { - margin-top: 0 !important; -} - -.color-black { - color: $black; -} - -.color-green { - color: $green; -} - -.color-darker-gray { - color: $darker-gray; -} - .cart-table { - max-height: 0; - transition: all 350ms ease-in; - overflow: hidden; - visibility: hidden; - margin-top: 1rem; - - :deep(a) { - padding-bottom: 0 !important; - line-height: 1.625rem !important; - text-underline-offset: auto !important; - } - - .non-packaged-cart-item:nth-child(odd){ - background-color: $gray-100; - } + max-height: 50rem; + transition: all 150ms ease-in; + min-width: fit-content; .cart-item { - padding: 0.25rem 1.5rem; - } + display: flex; + flex-direction: column; + padding: .5rem 0rem; + width: 100%; + min-width: fit-content; + &:nth-child(odd) { + background-color: #f4f4f4; + } + + &:last-child { + border-bottom: 1px solid #d4d6d8; + } - .cart-gray { - background-color: $gray-100; + .price-row { + display: flex; + justify-content: space-between; + } + + span, a { + white-space: nowrap; + padding: 0rem 1rem; + } + + a:hover { + color: $heritage-blue-secondary; + } } .cart-footer { @@ -520,13 +498,16 @@ $RECYCLING_MODAL_REF_NAME: 'RecycleModal'; background-color: $green-150; font-weight: $font-weight-bold; color: $black; - padding: 0.25rem 1.5rem; + >div { + padding: .5rem 1rem; + } } .bottom-amount-due { color: $white; + font-weight: 600; background-color: $green; - padding: 0.5rem 1.5rem; + padding: .5rem 1rem; } } @@ -544,39 +525,6 @@ $RECYCLING_MODAL_REF_NAME: 'RecycleModal'; text-align: center; } -.cart-header { - &.cart-toggle { - font-weight: $font-weight-bold; - - &:after { - content: ""; - transition: all 0.5s ease; - background-image: url($svg-payment-method-review-toggle); - background-repeat: no-repeat; - background-position: right center; - width: 1rem; - height: 0.5625rem; - display: inline-flex; - position: relative; - right: 0.75rem; - margin: 0.5rem 0 0.5rem 1rem; - cursor: pointer; - } - &.expanded:after { - transform: rotate(180deg); - } - a { - text-decoration: none; - } - } - &.expanded + .cart-table { - max-height: 50rem; - transition: all 150ms ease-in; - overflow: hidden; - visibility: visible; - } -} - :deep(#recycle-fee-label a){ line-height: initial; } diff --git a/src/iss-components/confirmation-cart/confirmation-cart.spec.js b/src/iss-components/confirmation-cart/confirmation-cart.spec.js deleted file mode 100644 index 7391f3d9..00000000 --- a/src/iss-components/confirmation-cart/confirmation-cart.spec.js +++ /dev/null @@ -1,1580 +0,0 @@ -import { shallowMount } from '@vue/test-utils'; -import { createTestingPinia } from '@pinia/testing'; -import confirmationCart from '@/iss-components/confirmation-cart/confirmation-cart.vue'; - -// Supporting Files -import { getEnumName, getMountOptions } from '@/helpers/unit-test-helper.js'; -import { useMainStore, getDefaultState } from '@/store'; -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'; -import coverageStatuses from '@/constants/coverage-statuses'; -import coverageType from '@/constants/coverage-type'; - -const VERIFYING_COVERAGE = 'Verifying coverage'; - -jest.mock('@/helpers/text-helper', () => ({ - formatAmountInDollars: jest.fn() -})); -jest.mock('@/helpers/price-calculator.js', () => ({ - getPriceOfLineItems: jest.fn(), - getTaxOfLineItems: jest.fn(), - getPriceOfLineItem: jest.fn() -})); - -jest.mock('@/helpers/service-package-helper', () => ({ - getHighestFullySatisfiedTier: jest.fn(), - getPackageContents: jest.fn() -})); - -function getMountedComponent(mainInitialState = {}, initialData = {}, propsData = {}) { - const mountOptions = getMountOptions({ - router: { - navigate: jest.fn() - } - }); - - const testingPinia = createTestingPinia({ - initialState: { - main: mainInitialState - } - }); - useMainStore(testingPinia); - - mountOptions.global.mixins[0].methods.getSettingValue = jest.fn(() => 'false'); - mountOptions.global.plugins = [testingPinia]; - mountOptions.data = () => (initialData); - mountOptions.propsData = propsData; - - const wrapper = shallowMount(confirmationCart, mountOptions); - return { wrapper }; -} - -beforeEach(() => { - const store = useMainStore(); - const defaultState = getDefaultState(); - Object.keys(defaultState).forEach((key) => { - store[key] = defaultState[key]; - }); -}); - -describe('confirmation-cart component', () => { - test('initial data rendered as expected', () => { - // Arrange - const { wrapper } = getMountedComponent({ - order: { - availableVaps: [] - } - }); - - // Assert - expect(wrapper.vm.$data).toMatchSnapshot(); - }); - describe('displays', () => { - test('cart dropdown head', () => { - // Arrange - const reference = '#cart-dropdown-head'; - const { wrapper } = getMountedComponent(confirmationCart); - - // Act - const head = wrapper.find(reference); - - // Assert - expect(head.exists()).toBeTruthy(); - }); - test('cart dropdown head is visible', () => { - // Arrange - const reference = '#cart-dropdown-head'; - const { wrapper } = getMountedComponent(confirmationCart, {}, { showDropdownHeader: true }); - - // Act - const head = wrapper.find(reference); - - // Assert - expect(head.exists()).toBeTruthy(); - expect(head.classes()).toContain('cart-toggle'); - }); - test('cart dropdown head is not visible', () => { - // Arrange - const reference = '#cart-dropdown-head'; - const { wrapper } = getMountedComponent(confirmationCart, {}, { showDropdownHeader: false }); - - // Act - const head = wrapper.find(reference); - - // Assert - expect(head.exists()).toBeTruthy(); - expect(head.classes()).not.toContain('cart-toggle'); - }); - test('cart table', () => { - // Arrange - const reference = '#cart-table'; - const isExpanded = true; - const initialData = { isExpanded }; - const { wrapper } = getMountedComponent({}, {}, initialData); - - // Act - const cartTable = wrapper.find(reference); - - // Assert - expect(cartTable.exists()).toBeTruthy(); - }); - test('cart deductible when showDeductibleLineItem is true', () => { - // Arrange - const reference = '#cart-deductible'; - const isExpanded = true; - const initialData = { isExpanded }; - const storeData = { - order: { - insuranceCoverage: { - coverageStatus: coverageStatuses.VERIFIED, - coverageType: coverageType.Deductible - } - } - }; - const { wrapper } = getMountedComponent(storeData, {}, initialData); - - // Act - const cartDeductible = wrapper.find(reference); - - // Assert - expect(cartDeductible.exists()).toBeTruthy(); - }); - test('cart base price when showDeductibleLineItem is false', () => { - // Arrange - const reference = '#cart-base-price'; - const isExpanded = true; - const initialData = { isExpanded }; - const storeData = { - order: { - currentDeductible: 0, - lineItems: { }, - insuranceCoverage: { - coverageStatus: coverageStatuses.VERIFIED, - coverageType: coverageType.ITAC - } - }, - issConfig: { - isClaimRegistrationRequired: true - } - }; - const { wrapper } = getMountedComponent(storeData, {}, initialData); - - // Act - const cartBasePrice = wrapper.find(reference); - - // Assert - expect(cartBasePrice.exists()).toBeTruthy(); - }); - test('service package', () => { - // Arrange - const reference = '#cart-service-package'; - const isExpanded = true; - const initialData = { isExpanded }; - const { wrapper } = getMountedComponent({}, {}, initialData); - - // Act - const servicePackage = wrapper.find(reference); - - // Assert - expect(servicePackage.exists()).toBeTruthy(); - }); - 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: { - feeItems: [ - { 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'; - const isExpanded = true; - const initialData = { isExpanded }; - const { wrapper } = getMountedComponent({}, {}, initialData); - - // Act - const cartFooter = wrapper.find(reference); - - // Assert - expect(cartFooter.exists()).toBeTruthy(); - }); - test('subtotal', () => { - // Arrange - const reference = '#cart-subtotal'; - const isExpanded = true; - const initialData = { isExpanded }; - const { wrapper } = getMountedComponent({}, {}, initialData); - - // Act - const subtotal = wrapper.find(reference); - - // Assert - expect(subtotal.exists()).toBeTruthy(); - }); - test('tax', () => { - // Arrange - const reference = '#cart-sales-tax'; - const isExpanded = true; - const initialData = { isExpanded }; - const { wrapper } = getMountedComponent({}, {}, initialData); - - // Act - const salesTax = wrapper.find(reference); - - // Assert - expect(salesTax.exists()).toBeTruthy(); - }); - test('amount paid when Pay in Advance', () => { - // Arrange - const reference = '#cart-amount-paid'; - const isExpanded = true; - const showAsPaid = true; - const initialPropsData = { isExpanded, showAsPaid }; - const storeData = { - order: { - payment: { - isPayInAdvance: true - } - } - }; - const { wrapper } = getMountedComponent(storeData, {}, initialPropsData); - - // Act - const amountPaid = wrapper.find(reference); - - // Assert - expect(amountPaid.exists()).toBeTruthy(); - }); - test('bottom amount due', () => { - // Arrange - const reference = '#bottom-amount-due'; - const isExpanded = true; - const initialData = { isExpanded }; - const { wrapper } = getMountedComponent({}, {}, initialData); - - // Act - const bottomAmountDue = wrapper.find(reference); - - // Assert - expect(bottomAmountDue.exists()).toBeTruthy(); - }); - }); - describe('does not display', () => { - test('cart deductible when showDeductibleLineItem is false', () => { - // Arrange - const reference = '#cart-deductible'; - const isExpanded = true; - const initialData = { isExpanded }; - const storeData = { - order: { - currentDeductible: 0, - lineItems: { }, - insuranceCoverage: { - coverageStatus: coverageStatuses.VERIFIED, - coverageType: coverageType.ITAC - } - }, - issConfig: { - isClaimRegistrationRequired: true - } - }; - const { wrapper } = getMountedComponent(storeData, {}, initialData); - - // Act - const cartDeductible = wrapper.find(reference); - - // Assert - expect(cartDeductible.exists()).toBeFalsy(); - }); - test('cart base price when showDeductibleLineItem is true', () => { - // Arrange - const reference = '#cart-base-price'; - const isExpanded = true; - const initialData = { isExpanded }; - const storeData = { - order: { - insuranceCoverage: { - coverageStatus: coverageStatuses.VERIFIED, - coverageType: coverageType.Deductible - } - } - }; - const { wrapper } = getMountedComponent(storeData, {}, initialData); - - // Act - const cartBasePrice = wrapper.find(reference); - - // Assert - expect(cartBasePrice.exists()).toBeFalsy(); - }); - test('recycle cart item label when isRecycle false for all cart items', () => { - // Arrange - const reference = '#recycle-fee-label'; - const isExpanded = true; - const initialPropsData = { isExpanded }; - const storeData = { - order: { - lineItems: { - supportingItems: [] - } - } - }; - const { wrapper } = getMountedComponent(storeData, {}, initialPropsData); - - // Act - const recycleFeeLabel = wrapper.find(reference); - - // Assert - expect(wrapper.vm.recycleFeeCartItem).toBeNull(); - expect(recycleFeeLabel.exists()).toBeFalsy(); - }); - }); - describe('computed', () => { - describe('amountDue', () => { - test('returns 0 when showAsPaid is true', () => { - // Arrange - const propsData = { - showAsPaid: true - }; - const { wrapper } = getMountedComponent({}, {}, propsData); - - // Act - const result = wrapper.vm.amountDue; - - // Assert - expect(result).toBe(0); - }); - test('returns sum of subTotal and salesTax when showAsPaid is false', () => { - // TODO when subTotal and salesTax are finished - }); - }); - describe('availableLineItems', () => { - test('returns expected when all null', () => { - // Arrange - const propsData = { availableVaps: null }; - const { wrapper } = getMountedComponent({}, {}, propsData); - - // Act - const result = wrapper.vm.availableLineItems; - - // Assert - expect(result).toStrictEqual([]); - }); - test('returns expected when glassParts not null', async () => { - // Arrange - const glassParts = [{ partNumber: 'glass' }]; - const storeData = { - order: { - lineItems: { glassParts } - } - }; - const propsData = { availableVaps: null }; - const { wrapper } = getMountedComponent(storeData, {}, propsData); - const expected = glassParts; - - // Act - const result = wrapper.vm.availableLineItems; - - // Assert - expect(result).toStrictEqual(expected); - }); - test('returns expected when supportingItems not null', async () => { - // Arrange - const supportingItems = [{ partNumber: 'support' }]; - const storeData = { - order: { - lineItems: { supportingItems } - } - }; - const propsData = { availableVaps: null }; - const { wrapper } = getMountedComponent(storeData, {}, propsData); - const expected = supportingItems; - - // Act - const result = wrapper.vm.availableLineItems; - - // Assert - expect(result).toStrictEqual(expected); - }); - test('returns expected when otherParts not null', () => { - // Arrange - const otherParts = [{ partNumber: 'other' }]; - const storeData = { - order: { - lineItems: { otherParts } - } - }; - const propsData = { availableVaps: null }; - const { wrapper } = getMountedComponent(storeData, {}, propsData); - const expected = otherParts; - - // Act - const result = wrapper.vm.availableLineItems; - - // Assert - expect(result).toStrictEqual(expected); - }); - test('returns expected when mobileFee not null', () => { - // Arrange - const mobileFee = { partNumber: 'mobile' }; - const storeData = { - order: { - lineItems: { - feeItems: [mobileFee] - } - } - }; - const propsData = { availableVaps: null }; - const { wrapper } = getMountedComponent(storeData, {}, propsData); - const expected = [mobileFee]; - - // Act - const result = wrapper.vm.availableLineItems; - - // Assert - expect(result).toStrictEqual(expected); - }); - test('returns expected when availableVaps null', async () => { - // Arrange - const availableVaps = [{ partNumber: 'vaps1' }]; - const initialData = { availableVaps }; - const { wrapper } = getMountedComponent({}, initialData, {}); - const expected = availableVaps; - - // Act - const result = wrapper.vm.availableLineItems; - - // Assert - expect(result).toStrictEqual(expected); - }); - test('returns expected when glassParts, supportingItems, otherParts, mobileFee, and availableVaps have content', async () => { - // Arrange - const part1 = { partType: 'apple' }; - const part2 = { partType: 'banana' }; - const part3 = { partType: 'orange' }; - const part4 = { partType: 'grape' }; - const part5 = { partType: 'raspberry' }; - const mobileFee = { partType: 'mobile' }; - const storeData = { - order: { - lineItems: { - glassParts: [part1], - supportingItems: [part2, part3], - otherParts: [], - feeItems: [mobileFee] - } - } - }; - const initialData = { - availableVaps: [part4, part5] - }; - const { wrapper } = getMountedComponent(storeData, initialData, {}); - const sortByPartType = (a, b) => { - const typeA = a.partType.toUpperCase(); - const typeB = b.partType.toUpperCase(); - if (typeA < typeB) { - return -1; - } - if (typeA > typeB) { - return 1; - } - return 0; - }; - const expected = [part1, part2, part3, part4, part5, mobileFee]; - - // Act - const result = wrapper.vm.availableLineItems; - - // Assert - expect(result.sort(sortByPartType)).toStrictEqual(expected.sort(sortByPartType)); - }); - }); - describe('servicePackageCartItems', () => { - test.each([ - [undefined], [null], [[]] - ])('returns empty list when package contents %p', (packageContents) => { - // Arrange - getPackageContents.mockImplementationOnce(() => packageContents); - const { wrapper } = getMountedComponent(); - const expected = []; - - // Act - const result = wrapper.vm.servicePackageCartItems; - - // Assert - expect(result).toStrictEqual(expected); - }); - test('returns front wiper when front wiper included in types', () => { - // Arrange - const frontWiperPartType = partTypeStrings.FRONT_WIPER; - const packageContents = [frontWiperPartType]; - getPackageContents.mockImplementation(() => packageContents); - - const mountOptions = getMountOptions({ - router: { navigate: jest.fn() } - }); - const expectedName = 'some name'; - const vapsItemDescriptions = [ - { - Name: frontWiperPartType, - Text: expectedName - } - ]; - const widgetName = 'VapsItemDescriptions'; - const mockMixin = { - methods: { - getCmsContent: jest.fn((widget, _) => (widget === widgetName ? vapsItemDescriptions : [])) - } - }; - mountOptions.mixins = [mockMixin]; - const storeData = { - order: { - lineItems: { - vaps: [{ partType: frontWiperPartType }] - } - } - }; - const testingPinia = createTestingPinia({ - initialState: { - main: storeData - } - }); - useMainStore(testingPinia); - mountOptions.global.plugins = [testingPinia]; - - const wrapper = shallowMount(confirmationCart, mountOptions); - - // Act - const result = wrapper.vm.servicePackageCartItems; - - // Assert - expect(result.length).toBe(1); - expect(result[0].name).toBe(expectedName); - }); - test('returns rear wiper when rear wiper included in types', () => { - // Arrange - const rearWiperPartType = partTypeStrings.REAR_WIPER; - const packageContents = [rearWiperPartType]; - getPackageContents.mockImplementationOnce(() => packageContents); - - const mountOptions = getMountOptions({ - router: { navigate: jest.fn() } - }); - const expectedName = 'some other name'; - const vapsItemDescriptions = [ - { - Name: rearWiperPartType, - Text: expectedName - } - ]; - const mockMixin = { - methods: { - getCmsContent: jest.fn(() => vapsItemDescriptions) - } - }; - mountOptions.mixins = [mockMixin]; - const storeData = { - order: { - lineItems: { - vaps: [{ partType: rearWiperPartType }] - } - } - }; - const testingPinia = createTestingPinia({ - initialState: { - main: storeData - } - }); - useMainStore(testingPinia); - mountOptions.global.plugins = [testingPinia]; - - const wrapper = shallowMount(confirmationCart, mountOptions); - - // Act - const result = wrapper.vm.servicePackageCartItems; - - // Assert - expect(result.length).toBe(1); - expect(result[0].name).toBe(expectedName); - }); - test('returns rain defense when rain defense included in types', () => { - // Arrange - const rainDefensePartType = partTypeStrings.RAIN_DEFENSE; - const packageContents = [rainDefensePartType]; - getPackageContents.mockImplementationOnce(() => packageContents); - - const mountOptions = getMountOptions({ - router: { navigate: jest.fn() } - }); - const expectedName = 'different name'; - const vapsItemDescriptions = [ - { - Name: rainDefensePartType, - Text: expectedName - } - ]; - const mockMixin = { - methods: { - getCmsContent: jest.fn(() => vapsItemDescriptions) - } - }; - mountOptions.mixins = [mockMixin]; - const storeData = { - order: { - lineItems: { - vaps: [{ partType: rainDefensePartType }] - } - } - }; - const testingPinia = createTestingPinia({ - initialState: { - main: storeData - } - }); - useMainStore(testingPinia); - mountOptions.global.plugins = [testingPinia]; - - const wrapper = shallowMount(confirmationCart, mountOptions); - - // Act - const result = wrapper.vm.servicePackageCartItems; - - // Assert - expect(result.length).toBe(1); - expect(result[0].name).toBe(expectedName); - }); - test('returns expected when all included in types', () => { - // Arrange - const frontWiperPartType = partTypeStrings.FRONT_WIPER; - const rearWiperPartType = partTypeStrings.REAR_WIPER; - const rainDefensePartType = partTypeStrings.RAIN_DEFENSE; - const packageContents = [frontWiperPartType, rearWiperPartType, rainDefensePartType]; - getPackageContents.mockImplementationOnce(() => packageContents); - - const mountOptions = getMountOptions({ - router: { navigate: jest.fn() } - }); - const expectedFrontWiperName = 'front wiper'; - const expectedRearWiperName = 'rear wiper'; - const expectedRainDefenseName = 'rain repel'; - const vapsItemDescriptions = [ - { - Name: frontWiperPartType, - Text: expectedFrontWiperName - }, - { - Name: rearWiperPartType, - Text: expectedRearWiperName - }, - { - Name: rainDefensePartType, - Text: expectedRainDefenseName - } - ]; - const mockMixin = { - methods: { - getCmsContent: jest.fn(() => vapsItemDescriptions) - } - }; - mountOptions.mixins = [mockMixin]; - const storeData = { - order: { - lineItems: { - vaps: [ - { partType: frontWiperPartType }, - { partType: rearWiperPartType }, - { partType: rainDefensePartType } - ] - } - } - }; - const testingPinia = createTestingPinia({ - initialState: { - main: storeData - } - }); - useMainStore(testingPinia); - mountOptions.global.plugins = [testingPinia]; - - const wrapper = shallowMount(confirmationCart, mountOptions); - - // Act - const result = wrapper.vm.servicePackageCartItems; - - // Assert - expect(result.length).toBe(3); - expect(result).toContainEqual(expect.objectContaining({ - name: expectedFrontWiperName - })); - expect(result).toContainEqual(expect.objectContaining({ - name: expectedRearWiperName - })); - expect(result).toContainEqual(expect.objectContaining({ - name: expectedRainDefenseName - })); - }); - }); - describe('nonServicePackageCartItems', () => { - test('when recycleFee, includes recycle fee', () => { - // Arrange - const storeData = { - order: { - lineItems: { - feeItems: [ - { - partNumber: partNumberStrings.RECYCLE_FEE - } - ] - } - } - }; - const { wrapper } = getMountedComponent(storeData); - - // Act - const result = wrapper.vm.nonServicePackageCartItems; - - // Assert - expect(result).toContainEqual(expect.objectContaining({ - partType: partTypeStrings.REPLACE_FEE - })); - }); - test('when mobileFee, includes mobile fee', () => { - // Arrange - const storeData = { - order: { - lineItems: { - feeItems: [{ 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: { - feeItems: [ - { partType: partTypeStrings.MOBILE_FEE }, - { partNumber: partNumberStrings.RECYCLE_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({ - partType: partTypeStrings.REPLACE_FEE - })); - expect(result).toContainEqual(expect.objectContaining({ - partType: partTypeStrings.MOBILE_FEE - })); - expect(result).toContainEqual(expect.objectContaining({ - partType: partTypeStrings.REAR_WIPER - })); - }); - }); - describe('servicePackageLabelWidget', () => { - test.each([ - [null], - [undefined] - ])('returns "" when servicePackageNames %p', (servicePackageNames) => { - // Arrange - const mountOptions = getMountOptions({ - router: { navigate: jest.fn() } - }); - const mockMixin = { - methods: { - getCmsContent: jest.fn(() => servicePackageNames) - } - }; - mountOptions.mixins = [mockMixin]; - - const wrapper = shallowMount(confirmationCart, mountOptions); - - // Act - const result = wrapper.vm.servicePackageLabelWidget; - - // Assert - expect(result).toBe(''); - }); - test('returns "" when servicePackageTier not found in servicePackageNames', () => { - // Arrange - const mountOptions = getMountOptions({ - router: { navigate: jest.fn() } - }); - getHighestFullySatisfiedTier.mockImplementationOnce(() => 'some other tier'); - const servicePackageNames = [{ Name: 'some tier' }]; - const mockMixin = { - methods: { - getCmsContent: jest.fn(() => servicePackageNames) - } - }; - mountOptions.mixins = [mockMixin]; - const wrapper = shallowMount(confirmationCart, mountOptions); - - // Act - const result = wrapper.vm.servicePackageLabelWidget; - - // Assert - expect(result).toBe(''); - }); - test('returns "" when servicePackageTier has no SubWidgetName', () => { - // Arrange - const mountOptions = getMountOptions({ - router: { navigate: jest.fn() } - }); - const tier = 'tier1'; - getHighestFullySatisfiedTier.mockImplementationOnce(() => tier); - const servicePackageNames = [{ Name: tier }]; - const mockMixin = { - methods: { - getCmsContent: jest.fn(() => servicePackageNames) - } - }; - mountOptions.mixins = [mockMixin]; - const wrapper = shallowMount(confirmationCart, mountOptions); - - // Act - const result = wrapper.vm.servicePackageLabelWidget; - - // Assert - expect(result).toBe(''); - }); - test('returns expected when servicePackageTier has SubWidgetName', () => { - // Arrange - const mountOptions = getMountOptions({ - router: { navigate: jest.fn() } - }); - const tier = 'tier1'; - getHighestFullySatisfiedTier.mockImplementationOnce(() => tier); - const expected = 'name of sub widget'; - const servicePackageNames = [{ - Name: tier, - SubWidgetName: expected - }]; - const mockMixin = { - methods: { - getCmsContent: jest.fn(() => servicePackageNames) - } - }; - mountOptions.mixins = [mockMixin]; - const wrapper = shallowMount(confirmationCart, mountOptions); - - // Act - const result = wrapper.vm.servicePackageLabelWidget; - - // Assert - expect(result).toBe(expected); - }); - }); - describe('recycleFeeCartItem', () => { - test.each([ - [null], [undefined], [[]] - ])('returns null when supporting items %p', (supportingItems) => { - // Arrange - const storeData = { - order: { - lineItems: { supportingItems } - } - }; - const { wrapper } = getMountedComponent(storeData); - const expected = null; - - // Act - const result = wrapper.vm.recycleFeeCartItem; - - // Assert - expect(result).toStrictEqual(expected); - }); - test('returns null when recycle fee not in non empty supporting items', () => { - // Arrange - const storeData = { - order: { - lineItems: { - supportingItems: [{ partNumber: 'not recycle' }] - } - } - }; - const { wrapper } = getMountedComponent(storeData); - const expected = null; - - // Act - const result = wrapper.vm.recycleFeeCartItem; - - // Assert - expect(result).toStrictEqual(expected); - }); - test('returns expected when recycle fee in fee items', () => { - // Arrange - const mountOptions = getMountOptions({ - router: { navigate: jest.fn() } - }); - const expectedName = 'recycling fee'; - const widgetName = 'RecycleFeeWidget'; - const mockMixin = { - methods: { - getCmsContent: jest.fn((widget, _) => (widget === widgetName ? expectedName : [])) - } - }; - mountOptions.mixins = [mockMixin]; - const storeData = { - order: { - lineItems: { - feeItems: [{ partNumber: partNumberStrings.RECYCLE_FEE }] - } - } - }; - const testingPinia = createTestingPinia({ - initialState: { - main: storeData - } - }); - useMainStore(testingPinia); - mountOptions.global.plugins = [testingPinia]; - - const wrapper = shallowMount(confirmationCart, mountOptions); - - // Act - const result = wrapper.vm.recycleFeeCartItem; - - // Assert - expect(result.name).toBe(expectedName); - }); - }); - describe('mobileFeeCartItem', () => { - test.each([[null], [undefined]])('returns null when mobile fee %p', (mobileFee) => { - // Arrange - const storeData = { - order: { - lineItems: { mobileFee } - } - }; - const { wrapper } = getMountedComponent(storeData); - const expected = null; - - // Act - const result = wrapper.vm.mobileFeeCartItem; - - // Assert - expect(result).toStrictEqual(expected); - }); - test('returns expected when mobile fee in fee items', () => { - // Arrange - const mountOptions = getMountOptions({ - router: { navigate: jest.fn() } - }); - const expectedName = 'mobile fee'; - const widgetName = 'MobileServiceWidget'; - const mockMixin = { - methods: { - getCmsContent: jest.fn((widget, _) => (widget === widgetName ? expectedName : [])) - } - }; - mountOptions.mixins = [mockMixin]; - const storeData = { - order: { - lineItems: { - feeItems: [{ partType: partTypeStrings.MOBILE_FEE }] - } - } - }; - const testingPinia = createTestingPinia({ - initialState: { - main: storeData - } - }); - useMainStore(testingPinia); - mountOptions.global.plugins = [testingPinia]; - - const wrapper = shallowMount(confirmationCart, mountOptions); - - // Act - const result = wrapper.vm.mobileFeeCartItem; - - // Assert - expect(result.name).toBe(expectedName); - }); - }); - 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); - }); - }); - }); - describe('method', () => { - const dollarAmount = '$84.00'; - describe.each([ - [VERIFYING_COVERAGE, coverageStatuses.PENDING, coverageType.NONE], - [VERIFYING_COVERAGE, coverageStatuses.PENDING, coverageType.NO_COMP], - [VERIFYING_COVERAGE, coverageStatuses.PENDING, coverageType.ITAC], - [VERIFYING_COVERAGE, coverageStatuses.PENDING, coverageType.Deductible], - [dollarAmount, coverageStatuses.VERIFIED, coverageType.NO_COMP], - [dollarAmount, coverageStatuses.VERIFIED, coverageType.ITAC], - [dollarAmount, coverageStatuses.VERIFIED, coverageType.Deductible], - [VERIFYING_COVERAGE, coverageStatuses.NO_COVERAGE, coverageType.NONE], - [VERIFYING_COVERAGE, coverageStatuses.NO_COVERAGE, coverageType.NO_COMP], - [VERIFYING_COVERAGE, coverageStatuses.NO_COVERAGE, coverageType.ITAC], - [VERIFYING_COVERAGE, coverageStatuses.NO_COVERAGE, coverageType.Deductible] - ])('getDisplayed', (expected, status, type) => { - test(`returns ${expected} when coverage status ${getEnumName(coverageStatuses, status)} and coverageType is ${getEnumName(coverageType, type)}`, () => { - // Arrange - const storeData = { - order: { - insuranceCoverage: { - coverageStatus: status, - coverageType: type - }, - currentDeductible: 321 - } - }; - - const { wrapper } = getMountedComponent(storeData); - formatAmountInDollars.mockReturnValueOnce(dollarAmount); - - // Act - const result = wrapper.vm.getDisplayed(0); - - // Assert - expect(result).toBe(expected); - }); - }); - describe('getCartItemForVapsPart', () => { - test('returns item with no label when no descriptions returned', () => { - // Arrange - const mountOptions = getMountOptions({ - router: { navigate: jest.fn() } - }); - const descriptions = []; - const widgetName = 'VapsItemDescriptions'; - const mockMixin = { - methods: { - getCmsContent: jest.fn((widget, _) => (widget === widgetName ? descriptions : [])) - } - }; - mountOptions.mixins = [mockMixin]; - const part = 'some part'; - const storeData = { - order: { - lineItems: { - vaps: [{ partType: part }] - } - } - }; - const testingPinia = createTestingPinia({ - initialState: { - main: storeData - } - }); - useMainStore(testingPinia); - mountOptions.global.plugins = [testingPinia]; - const wrapper = shallowMount(confirmationCart, mountOptions); - - const expectedName = ''; - - // Act - const result = wrapper.vm.getCartItemForVapsPart(part); - - // Assert - expect(result.name).toBe(expectedName); - }); - test('returns item with no label when type not in descriptions', () => { - // Arrange - const mountOptions = getMountOptions({ - router: { navigate: jest.fn() } - }); - const descriptions = [{ - Name: 'not part name' - }]; - const widgetName = 'VapsItemDescriptions'; - const mockMixin = { - methods: { - getCmsContent: jest.fn((widget, _) => (widget === widgetName ? descriptions : [])) - } - }; - mountOptions.mixins = [mockMixin]; - const part = 'some part'; - const storeData = { - order: { - lineItems: { - vaps: [{ partType: part }] - } - } - }; - const testingPinia = createTestingPinia({ - initialState: { - main: storeData - } - }); - useMainStore(testingPinia); - mountOptions.global.plugins = [testingPinia]; - const wrapper = shallowMount(confirmationCart, mountOptions); - - const expectedName = ''; - - // Act - const result = wrapper.vm.getCartItemForVapsPart(part); - - // Assert - expect(result.name).toBe(expectedName); - }); - test('returns item with no label when description text not defined', () => { - // Arrange - const mountOptions = getMountOptions({ - router: { navigate: jest.fn() } - }); - const part = 'some part'; - const descriptions = [{ - Name: part - }]; - const widgetName = 'VapsItemDescriptions'; - const mockMixin = { - methods: { - getCmsContent: jest.fn((widget, _) => (widget === widgetName ? descriptions : [])) - } - }; - mountOptions.mixins = [mockMixin]; - const storeData = { - order: { - lineItems: { - vaps: [{ partType: part }] - } - } - }; - const testingPinia = createTestingPinia({ - initialState: { - main: storeData - } - }); - useMainStore(testingPinia); - mountOptions.global.plugins = [testingPinia]; - const wrapper = shallowMount(confirmationCart, mountOptions); - const expectedName = ''; - - // Act - const result = wrapper.vm.getCartItemForVapsPart(part); - - // Assert - expect(result.name).toBe(expectedName); - }); - test('returns expected label when vaps description text set', () => { - // Arrange - const mountOptions = getMountOptions({ - router: { navigate: jest.fn() } - }); - const part = 'some part'; - const expectedName = 'name to show up'; - const descriptions = [{ - Name: part, - Text: expectedName - }]; - const widgetName = 'VapsItemDescriptions'; - const mockMixin = { - methods: { - getCmsContent: jest.fn((widget, _) => (widget === widgetName ? descriptions : [])) - } - }; - mountOptions.mixins = [mockMixin]; - const storeData = { - order: { - lineItems: { - vaps: [{ partType: part }] - } - } - }; - const testingPinia = createTestingPinia({ - initialState: { - main: storeData - } - }); - useMainStore(testingPinia); - mountOptions.global.plugins = [testingPinia]; - const wrapper = shallowMount(confirmationCart, mountOptions); - - // Act - const result = wrapper.vm.getCartItemForVapsPart(part); - - // Assert - expect(result.name).toBe(expectedName); - }); - test.each([ - [undefined], [null] - ])('returns null when vapsInOrder %p', async (vapsInOrder) => { - // Arrange - const mountOptions = getMountOptions({ - router: { navigate: jest.fn() } - }); - const part = 'some part'; - const expectedName = 'name to show up'; - const descriptions = [{ - Name: part, - Text: expectedName - }]; - const widgetName = 'VapsItemDescriptions'; - const mockMixin = { - methods: { - getCmsContent: jest.fn((widget, _) => (widget === widgetName ? descriptions : [])) - } - }; - mountOptions.mixins = [mockMixin]; - const storeData = { - order: { - lineItems: { - vaps: vapsInOrder - } - } - }; - const testingPinia = createTestingPinia({ - initialState: { - main: storeData - } - }); - useMainStore(testingPinia); - mountOptions.global.plugins = [testingPinia]; - const wrapper = shallowMount(confirmationCart, mountOptions); - - // Act - const result = wrapper.vm.getCartItemForVapsPart(part); - - // Assert - expect(result).toBe(null); - }); - test('returns item with expected price when part type found in vapsInOrder', () => { - // Arrange - const mountOptions = getMountOptions({ - router: { navigate: jest.fn() } - }); - const part = 'some part'; - const vaps = [{ partType: part }]; - const storeData = { - order: { - lineItems: { vaps } - } - }; - const testingPinia = createTestingPinia({ - initialState: { - main: storeData - } - }); - useMainStore(testingPinia); - mountOptions.global.plugins = [testingPinia]; - const expectedSubtotal = 93; - getPriceOfLineItems.mockImplementation(() => expectedSubtotal); - const wrapper = shallowMount(confirmationCart, mountOptions); - - // Act - const result = wrapper.vm.getCartItemForVapsPart(part); - - // Assert - expect(result.subTotal).toBe(expectedSubtotal); - }); - }); - }); -}); diff --git a/src/iss-components/confirmation-cart/confirmation-cart.vue b/src/iss-components/confirmation-cart/confirmation-cart.vue deleted file mode 100644 index f459cd2a..00000000 --- a/src/iss-components/confirmation-cart/confirmation-cart.vue +++ /dev/null @@ -1,478 +0,0 @@ - - - - - diff --git a/src/layouts/order-confirmation/order-confirmation.vue b/src/layouts/order-confirmation/order-confirmation.vue index fcd9dea5..fc03df1c 100644 --- a/src/layouts/order-confirmation/order-confirmation.vue +++ b/src/layouts/order-confirmation/order-confirmation.vue @@ -92,9 +92,10 @@
{{ cartHeaderText }}
- @@ -108,7 +109,7 @@ import siteHeader from '@/iss-components/site-header/site-header.vue'; import siteFooter from '@/iss-components/site-footer/site-footer.vue'; import addToCalendar from '@/layouts/order-confirmation/add-to-calendar/add-to-calendar.vue'; -import confirmationCart from '@/iss-components/confirmation-cart/confirmation-cart.vue'; +import cartDropdown from '@/iss-components/cart-dropdown/cart-dropdown.vue'; // Supporting files import { @@ -142,7 +143,7 @@ export default { siteHeader, siteFooter, addToCalendar, - confirmationCart + cartDropdown }, mixins: [BaseFormMixin], async beforeRouteEnter(to, from, next) { @@ -683,6 +684,12 @@ export default { } } + .service-description { + >span:first-child { + font-weight: $font-weight-bold; + } + } + .work-order-title { margin-bottom: .625rem; } diff --git a/src/layouts/payment-method/payment-method.vue b/src/layouts/payment-method/payment-method.vue index 2ec3d29e..aaaa32e5 100644 --- a/src/layouts/payment-method/payment-method.vue +++ b/src/layouts/payment-method/payment-method.vue @@ -24,7 +24,6 @@
diff --git a/src/layouts/payment-page/payment-page.vue b/src/layouts/payment-page/payment-page.vue index 7dd6b673..f4c86f11 100644 --- a/src/layouts/payment-page/payment-page.vue +++ b/src/layouts/payment-page/payment-page.vue @@ -42,8 +42,7 @@
diff --git a/src/store/index.js b/src/store/index.js index 05961894..90f48509 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -299,6 +299,11 @@ export const useMainStore = defineStore({ const nonWindshieldItems = damage.glassToReplace?.filter((glass) => glass.glassLocation !== damageLocationsSelected.WINDSHIELD); return !!nonWindshieldItems?.length; }, + hasMoldingPart: (s) => { + return s.order.lineItems.glassParts?.some((glassPart) => { + return glassPart.childParts?.some((childPart) => childPart.partType === partTypeStrings.MOLDING); + }); + }, isMobileAppointment: (state) => state.order.serviceLocation.appointmentType === AppointmentTypeStrings.MOBILE || state.order.serviceLocation.appointmentType === AppointmentTypeStrings.MOBILE_NOT_ITAC_AND_NOT_NOCOMP, isDropOffAppointment: (state) => state.order.serviceLocation.appointmentType === AppointmentTypeStrings.DROP_OFF, From 1413267f16acbe5b9e7d3efb9b8b725cc309eb0c Mon Sep 17 00:00:00 2001 From: Josh Dassinger Date: Wed, 11 Feb 2026 14:51:46 -0600 Subject: [PATCH 03/11] INSR-6190 Don't show mobile service option for big truck --- .../schedule-page/service-location/service-location.vue | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/layouts/schedule-page/service-location/service-location.vue b/src/layouts/schedule-page/service-location/service-location.vue index e48dddcc..f9c7ef43 100644 --- a/src/layouts/schedule-page/service-location/service-location.vue +++ b/src/layouts/schedule-page/service-location/service-location.vue @@ -243,6 +243,10 @@ export default { return this.isGlassServiceableInshop; }, isServiceableMobile() { + if (this.isBigTruck) { + return false; + } + if (this.isRecalibrationServiceableMobile !== null) { return ( this.isGlassServiceableMobile From 8bf7d282d4f1fcfd36470e023c0815da42271305 Mon Sep 17 00:00:00 2001 From: Alex Humphries Date: Wed, 11 Feb 2026 15:59:48 -0500 Subject: [PATCH 04/11] INSR-7557: Add to calender button fixes --- .eslintrc.js | 9 +- .../cart-dropdown/cart-dropdown.vue | 2 - .../add-to-calendar/add-to-calendar.vue | 80 ++++---- .../calendar-modal-list-button.vue | 81 -------- .../calendar-modal-question.vue | 180 ------------------ .../calendar-option-button.vue | 41 ++++ .../calendar-option-selection.spec.js} | 4 +- .../calendar-option-selection.vue | 54 ++++++ 8 files changed, 142 insertions(+), 309 deletions(-) delete mode 100644 src/layouts/order-confirmation/add-to-calendar/calendar-modal-question/calendar-modal-list-button/calendar-modal-list-button.vue delete mode 100644 src/layouts/order-confirmation/add-to-calendar/calendar-modal-question/calendar-modal-question.vue create mode 100644 src/layouts/order-confirmation/add-to-calendar/calendar-option-selection/calendar-option-button/calendar-option-button.vue rename src/layouts/order-confirmation/add-to-calendar/{calendar-modal-question/calendar-modal-question.spec.js => calendar-option-selection/calendar-option-selection.spec.js} (84%) create mode 100644 src/layouts/order-confirmation/add-to-calendar/calendar-option-selection/calendar-option-selection.vue diff --git a/.eslintrc.js b/.eslintrc.js index 3ced6a6d..95b47ad0 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -7,9 +7,7 @@ module.exports = { ecmaVersion: 'latest' }, extends: [ - 'eslint-config-airbnb-base', - 'plugin:vue/vue3-recommended', - 'plugin:jsdoc/recommended' + 'plugin:vue/vue3-recommended' ], rules: { 'linebreak-style': 'off', @@ -30,10 +28,6 @@ module.exports = { singleline: 'never', multiline: 'never' }], - 'jsdoc/check-tag-names': ['error', { - definedTags: ['store', 'endpoint', 'category', 'subcategory', 'remarks'] - }], - 'jsdoc/require-jsdoc': 0, 'vue/html-self-closing': ['error', { html: { void: 'any', @@ -43,7 +37,6 @@ module.exports = { svg: 'always', math: 'always' }], - 'import/extensions': ['error', 'always', { js: 'ignorePackages' }], 'no-param-reassign': ['error', { props: true, ignorePropertyModificationsFor: ['item'] }], 'no-restricted-syntax': ['off', 'ForOfStatement'], 'no-return-await': 'off' diff --git a/src/iss-components/cart-dropdown/cart-dropdown.vue b/src/iss-components/cart-dropdown/cart-dropdown.vue index 4e039152..61dc8449 100644 --- a/src/iss-components/cart-dropdown/cart-dropdown.vue +++ b/src/iss-components/cart-dropdown/cart-dropdown.vue @@ -321,7 +321,6 @@ export default { }, basePriceLabel() { const content = this.getCmsContent(this.widget.basePrice, widgetFields.TEXT_BLOCK_WIDGET.TEXT); - console.log('Base Price Label before processing if statements:', content); return processIfStatements( content, 'custom', @@ -436,7 +435,6 @@ export default { return vapsTypeDescription?.Text ?? ''; }, getCustomValueFromString(str) { - console.log(this.cartOrder) switch (str) { case 'isRepair': return this.cartOrder.damage.isRepair; diff --git a/src/layouts/order-confirmation/add-to-calendar/add-to-calendar.vue b/src/layouts/order-confirmation/add-to-calendar/add-to-calendar.vue index 502337a6..ae1f5af2 100644 --- a/src/layouts/order-confirmation/add-to-calendar/add-to-calendar.vue +++ b/src/layouts/order-confirmation/add-to-calendar/add-to-calendar.vue @@ -1,7 +1,7 @@ - diff --git a/src/layouts/order-confirmation/add-to-calendar/calendar-modal-question/calendar-modal-question.vue b/src/layouts/order-confirmation/add-to-calendar/calendar-modal-question/calendar-modal-question.vue deleted file mode 100644 index 702abf1b..00000000 --- a/src/layouts/order-confirmation/add-to-calendar/calendar-modal-question/calendar-modal-question.vue +++ /dev/null @@ -1,180 +0,0 @@ - - - diff --git a/src/layouts/order-confirmation/add-to-calendar/calendar-option-selection/calendar-option-button/calendar-option-button.vue b/src/layouts/order-confirmation/add-to-calendar/calendar-option-selection/calendar-option-button/calendar-option-button.vue new file mode 100644 index 00000000..760e3a7a --- /dev/null +++ b/src/layouts/order-confirmation/add-to-calendar/calendar-option-selection/calendar-option-button/calendar-option-button.vue @@ -0,0 +1,41 @@ + + + diff --git a/src/layouts/order-confirmation/add-to-calendar/calendar-modal-question/calendar-modal-question.spec.js b/src/layouts/order-confirmation/add-to-calendar/calendar-option-selection/calendar-option-selection.spec.js similarity index 84% rename from src/layouts/order-confirmation/add-to-calendar/calendar-modal-question/calendar-modal-question.spec.js rename to src/layouts/order-confirmation/add-to-calendar/calendar-option-selection/calendar-option-selection.spec.js index 51b43508..e4f1e332 100644 --- a/src/layouts/order-confirmation/add-to-calendar/calendar-modal-question/calendar-modal-question.spec.js +++ b/src/layouts/order-confirmation/add-to-calendar/calendar-option-selection/calendar-option-selection.spec.js @@ -1,7 +1,7 @@ import { shallowMount } from '@vue/test-utils'; -import calendarModalQuestion from '@/layouts/order-confirmation/add-to-calendar/calendar-modal-question/calendar-modal-question.vue'; +import calendarOptionSelection from '@/layouts/order-confirmation/add-to-calendar/calendar-option-selection/calendar-option-selection.vue'; -describe('calendar-modal-question.vue', () => { +describe('calendar-option-selection.vue', () => { test('When selected calendar option is changed, a correctly selectedCalendarOption should be emitted', async () => { // Arrange const url = 'iCal url'; diff --git a/src/layouts/order-confirmation/add-to-calendar/calendar-option-selection/calendar-option-selection.vue b/src/layouts/order-confirmation/add-to-calendar/calendar-option-selection/calendar-option-selection.vue new file mode 100644 index 00000000..2d9a2513 --- /dev/null +++ b/src/layouts/order-confirmation/add-to-calendar/calendar-option-selection/calendar-option-selection.vue @@ -0,0 +1,54 @@ + + + + From 32bf06ea596b604d989a52a50f09e3630bd9e594 Mon Sep 17 00:00:00 2001 From: Alex Humphries Date: Wed, 11 Feb 2026 16:41:32 -0500 Subject: [PATCH 05/11] INSR-7757: Fix some tests --- .../__snapshots__/cart-dropdown.spec.js.snap | 4 +- .../cart-dropdown/cart-dropdown.spec.js | 205 ++++-------------- .../cart-dropdown/cart-dropdown.vue | 4 +- .../add-to-calendar/add-to-calendar.spec.js | 96 +------- .../add-to-calendar/add-to-calendar.vue | 3 - .../calendar-option-selection.spec.js | 23 +- .../order-confirmation.spec.js | 62 +++--- .../order-confirmation/order-confirmation.vue | 2 +- 8 files changed, 91 insertions(+), 308 deletions(-) diff --git a/src/iss-components/cart-dropdown/__snapshots__/cart-dropdown.spec.js.snap b/src/iss-components/cart-dropdown/__snapshots__/cart-dropdown.spec.js.snap index 8f41a38c..2f061236 100644 --- a/src/iss-components/cart-dropdown/__snapshots__/cart-dropdown.spec.js.snap +++ b/src/iss-components/cart-dropdown/__snapshots__/cart-dropdown.spec.js.snap @@ -7,19 +7,21 @@ Object { "MOBILE_FEE": "MOBILE FEE", "RECYCLE_FEE": "RECYCLE FEE", "VAP": "VAP", + "WARRANTY": "WARRANTY", }, - "isExpanded": false, "widget": Object { "amountDue": "AmountDueTextWidget", "amountPaid": "AmountPaidTextWidget", "basePrice": "BasePriceWidget", "deductible": "DeductibleWidget", + "guaranteeText": "GuaranteeCartItemTextWidget", "mobileFee": "MobileServiceWidget", "recycleFee": "RecycleFeeWidget", "salesTax": "SalesTaxWidget", "servicePackage": "ServicePackageTitle", "subtotal": "SubtotalWidget", "vapsItemDescriptions": "VapsItemDescriptions", + "warrantyText": "WarrantyCartItemTextWidget", }, } `; diff --git a/src/iss-components/cart-dropdown/cart-dropdown.spec.js b/src/iss-components/cart-dropdown/cart-dropdown.spec.js index bab952b4..69fbabb9 100644 --- a/src/iss-components/cart-dropdown/cart-dropdown.spec.js +++ b/src/iss-components/cart-dropdown/cart-dropdown.spec.js @@ -73,47 +73,10 @@ describe('cart-dropdown component', () => { expect(wrapper.vm.$data).toMatchSnapshot(); }); describe('displays', () => { - test('cart dropdown head', () => { - // Arrange - const reference = '#cart-dropdown-head'; - const { wrapper } = getMountedComponent(cartDropdown); - - // Act - const head = wrapper.find(reference); - - // Assert - expect(head.exists()).toBeTruthy(); - }); - test('cart dropdown head is visible', () => { - // Arrange - const reference = '#cart-dropdown-head'; - const { wrapper } = getMountedComponent(cartDropdown, {}, { showDropdownHeader: true }); - - // Act - const head = wrapper.find(reference); - - // Assert - expect(head.exists()).toBeTruthy(); - expect(head.classes()).toContain('cart-toggle'); - }); - test('cart dropdown head is not visible', () => { - // Arrange - const reference = '#cart-dropdown-head'; - const { wrapper } = getMountedComponent(cartDropdown, {}, { showDropdownHeader: false }); - - // Act - const head = wrapper.find(reference); - - // Assert - expect(head.exists()).toBeTruthy(); - expect(head.classes()).not.toContain('cart-toggle'); - }); test('cart table', () => { // Arrange - const reference = '#cart-table'; - const isExpanded = true; - const initialData = { isExpanded }; - const { wrapper } = getMountedComponent({}, {}, initialData); + const reference = '.cart-table'; + const { wrapper } = getMountedComponent({}, {}, {}); // Act const cartTable = wrapper.find(reference); @@ -121,11 +84,9 @@ describe('cart-dropdown component', () => { // Assert expect(cartTable.exists()).toBeTruthy(); }); - test('cart deductible when showDeductibleLineItem is true', () => { + test('cart deductible when showDeductibleCartItem is true', () => { // Arrange - const reference = '#cart-deductible'; - const isExpanded = true; - const initialData = { isExpanded }; + const reference = '#deductible-label'; const storeData = { order: { insuranceCoverage: { @@ -134,7 +95,7 @@ describe('cart-dropdown component', () => { } } }; - const { wrapper } = getMountedComponent(storeData, {}, initialData); + const { wrapper } = getMountedComponent(storeData, {}, {}); // Act const cartDeductible = wrapper.find(reference); @@ -144,9 +105,7 @@ describe('cart-dropdown component', () => { }); test('cart base price when showDeductibleLineItem is false', () => { // Arrange - const reference = '#cart-base-price'; - const isExpanded = true; - const initialData = { isExpanded }; + const reference = '#base-price-label'; const storeData = { order: { currentDeductible: 0, @@ -160,7 +119,7 @@ describe('cart-dropdown component', () => { isClaimRegistrationRequired: true } }; - const { wrapper } = getMountedComponent(storeData, {}, initialData); + const { wrapper } = getMountedComponent(storeData, {}, {}); // Act const cartBasePrice = wrapper.find(reference); @@ -168,25 +127,32 @@ describe('cart-dropdown component', () => { // Assert expect(cartBasePrice.exists()).toBeTruthy(); }); - test('service package', () => { - // Arrange - const reference = '#cart-service-package'; - const isExpanded = true; - const initialData = { isExpanded }; - const { wrapper } = getMountedComponent({}, {}, initialData); - - // Act - const servicePackage = wrapper.find(reference); - - // Assert - expect(servicePackage.exists()).toBeTruthy(); - }); test('non service package cart items', () => { // Arrange - const reference = '#non-packaged-cart-items'; - const isExpanded = true; - const initialData = { isExpanded }; - const { wrapper } = getMountedComponent({}, {}, initialData); + const reference = '.non-packaged.cart-item'; + const part1 = { partType: 'apple' }; + const part2 = { partType: 'banana' }; + const part3 = { partType: 'orange' }; + const mobileFee = { partType: 'mobile' }; + const storeData = { + order: { + currentDeductible: 0, + lineItems: { + glassParts: [part1], + supportingItems: [part2, part3], + otherParts: [], + feeItems: [mobileFee] + }, + insuranceCoverage: { + coverageStatus: coverageStatuses.VERIFIED, + coverageType: coverageType.ITAC + } + }, + issConfig: { + isClaimRegistrationRequired: true + } + }; + const { wrapper } = getMountedComponent(storeData, {}, {}); // Act const nonPackagedCartItems = wrapper.find(reference); @@ -220,9 +186,7 @@ describe('cart-dropdown component', () => { test('cart footer', () => { // Arrange const reference = '#cart-footer'; - const isExpanded = true; - const initialData = { isExpanded }; - const { wrapper } = getMountedComponent({}, {}, initialData); + const { wrapper } = getMountedComponent({}, {}, {}); // Act const cartFooter = wrapper.find(reference); @@ -233,9 +197,7 @@ describe('cart-dropdown component', () => { test('subtotal', () => { // Arrange const reference = '#cart-subtotal'; - const isExpanded = true; - const initialData = { isExpanded }; - const { wrapper } = getMountedComponent({}, {}, initialData); + const { wrapper } = getMountedComponent({}, {}, {}); // Act const subtotal = wrapper.find(reference); @@ -246,9 +208,7 @@ describe('cart-dropdown component', () => { test('tax', () => { // Arrange const reference = '#cart-sales-tax'; - const isExpanded = true; - const initialData = { isExpanded }; - const { wrapper } = getMountedComponent({}, {}, initialData); + const { wrapper } = getMountedComponent({}, {}, {}); // Act const salesTax = wrapper.find(reference); @@ -280,9 +240,7 @@ describe('cart-dropdown component', () => { test('bottom amount due', () => { // Arrange const reference = '#bottom-amount-due'; - const isExpanded = true; - const initialData = { isExpanded }; - const { wrapper } = getMountedComponent({}, {}, initialData); + const { wrapper } = getMountedComponent({}, {}, {}); // Act const bottomAmountDue = wrapper.find(reference); @@ -295,8 +253,6 @@ describe('cart-dropdown component', () => { test('cart deductible when showDeductibleLineItem is false', () => { // Arrange const reference = '#cart-deductible'; - const isExpanded = true; - const initialData = { isExpanded }; const storeData = { order: { currentDeductible: 0, @@ -310,7 +266,7 @@ describe('cart-dropdown component', () => { isClaimRegistrationRequired: true } }; - const { wrapper } = getMountedComponent(storeData, {}, initialData); + const { wrapper } = getMountedComponent(storeData, {}, {}); // Act const cartDeductible = wrapper.find(reference); @@ -321,8 +277,6 @@ describe('cart-dropdown component', () => { test('cart base price when showDeductibleLineItem is true', () => { // Arrange const reference = '#cart-base-price'; - const isExpanded = true; - const initialData = { isExpanded }; const storeData = { order: { insuranceCoverage: { @@ -331,7 +285,7 @@ describe('cart-dropdown component', () => { } } }; - const { wrapper } = getMountedComponent(storeData, {}, initialData); + const { wrapper } = getMountedComponent(storeData, {}, {}); // Act const cartBasePrice = wrapper.find(reference); @@ -1223,91 +1177,6 @@ describe('cart-dropdown component', () => { expect(result.name).toBe(expectedName); }); }); - 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); - }); - }); }); describe('method', () => { const dollarAmount = '$84.00'; diff --git a/src/iss-components/cart-dropdown/cart-dropdown.vue b/src/iss-components/cart-dropdown/cart-dropdown.vue index 61dc8449..da404697 100644 --- a/src/iss-components/cart-dropdown/cart-dropdown.vue +++ b/src/iss-components/cart-dropdown/cart-dropdown.vue @@ -22,7 +22,7 @@
+ class="cart-item non-packaged">
+ class="cart-item packaged">
{{ item?.name ?? '' }} {{ formatAmountInDollars(item?.subTotal ?? 0) }} diff --git a/src/layouts/order-confirmation/add-to-calendar/add-to-calendar.spec.js b/src/layouts/order-confirmation/add-to-calendar/add-to-calendar.spec.js index 92914c3e..285cf934 100644 --- a/src/layouts/order-confirmation/add-to-calendar/add-to-calendar.spec.js +++ b/src/layouts/order-confirmation/add-to-calendar/add-to-calendar.spec.js @@ -2,11 +2,10 @@ import calendarOptions from '@/constants/calendar-options'; // Supporting Files -import { shallowMount, mount } from '@vue/test-utils'; +import { shallowMount } from '@vue/test-utils'; import { getMountOptions } from '@/helpers/unit-test-helper.js'; import { useMainStore } from '@/store'; import addToCalendar from '@/layouts/order-confirmation/add-to-calendar/add-to-calendar.vue'; -import { createTestingPinia } from '@pinia/testing'; const appointmentText = 'Appointment content'; function setupMocks({ customMountOptions }) { @@ -21,49 +20,6 @@ function setupMocks({ customMountOptions }) { } ]; const wrapper = shallowMount(addToCalendar, mountOptions); - wrapper.vm.$refs.calendarModalQuestion.openModal = jest.fn(); - return { wrapper }; -} - -const calendarModalQuestionStub = { - render: () => {} -}; - -const mockMixin = { - methods: { - getCmsContent: jest.fn().mockImplementation(() => appointmentText) - } -}; - -function getMountedComponent(mainInitialState = {}, initialData = {}, methodToRun = () => {}, mixin = mockMixin) { - const mountOptions = getMountOptions({ - router: { - navigate: jest.fn(), - navigateToExternalUrl: jest.fn() - } - }); - - mountOptions.global.stubs = { - calendarModalQuestion: calendarModalQuestionStub - }; - - const testingPinia = createTestingPinia({ - initialState: { - main: mainInitialState - } - }); - useMainStore(testingPinia); - methodToRun(); - - mountOptions.global.mixins[0].methods.getSettingValue = jest.fn(() => 'false'); - mountOptions.global.plugins = [testingPinia]; - mountOptions.mixins = [mixin]; - mountOptions.data = () => ( - initialData - ); - - const wrapper = shallowMount(addToCalendar, mountOptions); - wrapper.vm.$refs.calendarModalQuestion.openModal = jest.fn(); return { wrapper }; } @@ -119,51 +75,8 @@ afterEach(() => { jest.clearAllMocks(); }); -const sessionStorage = { - schedule: { - date: '2019-01-01', - startTime: '09:00', - endTime: '10:00', - routeCode: '000' - }, - lineItems: { - glassParts: [ - { - partNumber: 'ABC123' - } - ], - supportingItems: [] - }, - serviceLocation: { - address: '', - address2: null, - city: '', - state: 'AZ', - appointmentType: 'Inshop', - zipCode: '12345', - zipCodeCtu: '01234', - provider: { - providerNumber: '123', - address: { - streetAddress: 'test1', - city: 'test', - state: 'AZ', - zipCode: '12345', - zipCodeCtu: '01234' - } - } - }, - damage: { - isRepair: false - }, - referralNumber: '1234567', - payment: { - isInsurance: true - } -}; - describe('Add-to-calendar methods...', () => { - test('Add-to-calendar should trigger openModal method', () => { + test('Add-to-calendar should trigger open options', async () => { // Arrange const { wrapper } = setupMocks({ customMountOptions: { @@ -183,10 +96,11 @@ describe('Add-to-calendar methods...', () => { }); // Act - wrapper.vm.openCalendarModal(); + wrapper.vm.openCalendarOptions(); + await wrapper.vm.$nextTick(); // Assert - expect(wrapper.vm.$refs.calendarModalQuestion.openModal).toBeCalled(); + expect(wrapper.vm.$refs.calendarOptions.open).toEqual(true); }); test('getCalendarData should return expected model value.', () => { diff --git a/src/layouts/order-confirmation/add-to-calendar/add-to-calendar.vue b/src/layouts/order-confirmation/add-to-calendar/add-to-calendar.vue index ae1f5af2..0140bad4 100644 --- a/src/layouts/order-confirmation/add-to-calendar/add-to-calendar.vue +++ b/src/layouts/order-confirmation/add-to-calendar/add-to-calendar.vue @@ -209,12 +209,10 @@ export default { } }, openCalendarOptions() { - console.log('Opening calendar options'); this.calendarOptionsOpen = true; window.addEventListener('click', this.clickListener); }, calendarOptionSelected(calendarOptionIndex) { - console.log('Selected calendar option:', calendarOptionIndex); this.setCalendarAppointment(this.calendarValues[calendarOptionIndex]); this.calendarOptionsOpen = false; }, @@ -255,7 +253,6 @@ export default { download('SafeliteAppointment.ics', calBody); }, closeCalendarOptions() { - console.log('Closing calendar options'); this.calendarOptionsOpen = false; window.removeEventListener('click', this.clickListener); }, diff --git a/src/layouts/order-confirmation/add-to-calendar/calendar-option-selection/calendar-option-selection.spec.js b/src/layouts/order-confirmation/add-to-calendar/calendar-option-selection/calendar-option-selection.spec.js index e4f1e332..a833b369 100644 --- a/src/layouts/order-confirmation/add-to-calendar/calendar-option-selection/calendar-option-selection.spec.js +++ b/src/layouts/order-confirmation/add-to-calendar/calendar-option-selection/calendar-option-selection.spec.js @@ -7,35 +7,36 @@ describe('calendar-option-selection.vue', () => { const url = 'iCal url'; const name = 'iCal'; const icon = 'iCal.svg'; + const url2 = 'Google url'; + const name2 = 'Google'; + const icon2 = 'Google.svg'; const expectedEmit = [ [ - { - url, - name, - icon - } + 1 ] ]; - const wrapper = shallowMount(calendarModalQuestion, { + const wrapper = shallowMount(calendarOptionSelection, { propsData: { calendarOptionsData: [ { url, name, icon + }, + { + url: url2, + name: name2, + icon: icon2 } ] } }); - wrapper.vm.$refs.calendarOptions.closeModal = jest.fn(); - wrapper.vm.selectedCalendarOption = name; - // Act - wrapper.vm.setSelectedCalendarOption(); + wrapper.vm.setSelectedCalendarOption(1); // Assert - expect(wrapper.emitted()['update:modelValue']).toEqual(expectedEmit); + expect(wrapper.emitted()['calendar-option-selected']).toEqual(expectedEmit); }); }); diff --git a/src/layouts/order-confirmation/order-confirmation.spec.js b/src/layouts/order-confirmation/order-confirmation.spec.js index 6a06885a..06fda50c 100644 --- a/src/layouts/order-confirmation/order-confirmation.spec.js +++ b/src/layouts/order-confirmation/order-confirmation.spec.js @@ -363,7 +363,7 @@ describe('OrderConfirmation.vue', () => { expect(actualEmail).toBe(emailAddress); }); }); - describe('confirmationEmailText', () => { + describe('orderConfirmationUpdateAppointmentText', () => { const greaterId = '>'; const lessId = '<'; test.each([ @@ -383,7 +383,7 @@ describe('OrderConfirmation.vue', () => { const { wrapper } = getMountedComponent(initialStore, {}, mockStoreActions); // Act - const text = wrapper.vm.confirmationEmailText; + const text = wrapper.vm.orderConfirmationUpdateAppointmentText; // Assert expect(text).toBe(expected); @@ -391,13 +391,13 @@ describe('OrderConfirmation.vue', () => { }); describe('appointmentTimeText', () => { test.each([ - ['Between 9 AM - 10 AM', '09:00', '10:00'], - ['Between 1 PM - 5 PM', '13:00', '17:00'], - ['Between 8:30 AM - 3 PM', '08:30', '15:00'], - ['Between 1 AM - 2 AM', '01:00', '02:00'], - ['Between 12 AM - 2 AM', '00:00', '02:00'], - ['Between 12 PM - 2 AM', '12:00', '02:00'], - ['Between 11 PM - 12 AM', '23:00', '00:00'] + ['Your appointment is at 9 AM - 10 AM', '09:00', '10:00'], + ['Your appointment is at 1 PM - 5 PM', '13:00', '17:00'], + ['Your appointment is at 8:30 AM - 3 PM', '08:30', '15:00'], + ['Your appointment is at 1 AM - 2 AM', '01:00', '02:00'], + ['Your appointment is at 12 AM - 2 AM', '00:00', '02:00'], + ['Your appointment is at 12 PM - 2 AM', '12:00', '02:00'], + ['Your appointment is at 11 PM - 12 AM', '23:00', '00:00'] ])('should return Mobile time in expected format "%p" when start time "%p" and end time "%p"', (expected, startTime, endTime) => { // Arrange const order = deepClone(sessionStorage); @@ -438,12 +438,12 @@ describe('OrderConfirmation.vue', () => { expect(testValue).toEqual('Drop off before 9:30 AM'); }); test.each([ - ['at 9:00 AM', '09:00', '10:00'], - ['at 1:00 PM', '13:00', '17:00'], - ['at 8:30 AM', '08:30', '15:00'], - ['at 1:00 AM', '01:00', '02:00'], - ['at 12:00 AM', '00:00', '02:00'], - ['at 12:00 PM', '12:00', '02:00'] + ['Your appointment is at 9:00 AM', '09:00', '10:00'], + ['Your appointment is at 1:00 PM', '13:00', '17:00'], + ['Your appointment is at 8:30 AM', '08:30', '15:00'], + ['Your appointment is at 1:00 AM', '01:00', '02:00'], + ['Your appointment is at 12:00 AM', '00:00', '02:00'], + ['Your appointment is at 12:00 PM', '12:00', '02:00'] ])('should return In Shop time in expected format "%p" when start time "%p"', (expected, startTime, endTime) => { // Arrange const order = deepClone(sessionStorage); @@ -479,8 +479,8 @@ describe('OrderConfirmation.vue', () => { } } }; - const expectedServiceLocation = '123 Service Rd., Box 4,
Columbus, OH 12345'; - const expectedShopLocation = '304 Provider Ln.,
Pittsburg, PA 16001'; + const expectedServiceLocation = '123 Service Rd., Box 4, Columbus, OH 12345'; + const expectedShopLocation = '304 Provider Ln., Pittsburg, PA 16001'; test.each([ AppointmentTypeStrings.MOBILE, AppointmentTypeStrings.MOBILE_NOT_ITAC_AND_NOT_NOCOMP @@ -554,7 +554,7 @@ describe('OrderConfirmation.vue', () => { useMainStore().getSubmittedOrder = jest.fn().mockImplementation(() => order); }; const { wrapper } = getMountedComponent({}, {}, mockStoreActions); - const expected = '123 Service Rd., Box 4,
Columbus, OH 12345'; + const expected = '123 Service Rd., Box 4, Columbus, OH 12345'; // Act const text = wrapper.vm.serviceLocationFullAddress; @@ -568,7 +568,7 @@ describe('OrderConfirmation.vue', () => { useMainStore().getSubmittedOrder = jest.fn().mockImplementation(() => order); }; const { wrapper } = getMountedComponent({}, {}, mockStoreActions); - const expected = ', Box 4,
Columbus, OH 12345'; + const expected = ', Box 4, Columbus, OH 12345'; // Act const text = wrapper.vm.serviceLocationFullAddress; @@ -582,7 +582,7 @@ describe('OrderConfirmation.vue', () => { useMainStore().getSubmittedOrder = jest.fn().mockImplementation(() => order); }; const { wrapper } = getMountedComponent({}, {}, mockStoreActions); - const expected = '123 Service Rd.,
Columbus, OH 12345'; + const expected = '123 Service Rd., Columbus, OH 12345'; // Act const text = wrapper.vm.serviceLocationFullAddress; @@ -596,7 +596,7 @@ describe('OrderConfirmation.vue', () => { useMainStore().getSubmittedOrder = jest.fn().mockImplementation(() => order); }; const { wrapper } = getMountedComponent({}, {}, mockStoreActions); - const expected = '123 Service Rd., Box 4,
, OH 12345'; + const expected = '123 Service Rd., Box 4, , OH 12345'; // Act const text = wrapper.vm.serviceLocationFullAddress; @@ -610,7 +610,7 @@ describe('OrderConfirmation.vue', () => { useMainStore().getSubmittedOrder = jest.fn().mockImplementation(() => order); }; const { wrapper } = getMountedComponent({}, {}, mockStoreActions); - const expected = '123 Service Rd., Box 4,
Columbus, 12345'; + const expected = '123 Service Rd., Box 4, Columbus, 12345'; // Act const text = wrapper.vm.serviceLocationFullAddress; @@ -624,7 +624,7 @@ describe('OrderConfirmation.vue', () => { useMainStore().getSubmittedOrder = jest.fn().mockImplementation(() => order); }; const { wrapper } = getMountedComponent({}, {}, mockStoreActions); - const expected = '123 Service Rd., Box 4,
Columbus, OH '; + const expected = '123 Service Rd., Box 4, Columbus, OH '; // Act const text = wrapper.vm.serviceLocationFullAddress; @@ -642,7 +642,7 @@ describe('OrderConfirmation.vue', () => { useMainStore().getSubmittedOrder = jest.fn().mockImplementation(() => order); }; const { wrapper } = getMountedComponent({}, {}, mockStoreActions); - const expected = ',
, '; + const expected = ', , '; // Act const text = wrapper.vm.serviceLocationFullAddress; @@ -675,7 +675,7 @@ describe('OrderConfirmation.vue', () => { useMainStore().getSubmittedOrder = jest.fn().mockImplementation(() => order); }; const { wrapper } = getMountedComponent({}, {}, mockStoreActions); - const expected = '304 Provider Ln.,
Pittsburg, PA 16001'; + const expected = '304 Provider Ln., Pittsburg, PA 16001'; // Act const text = wrapper.vm.providerFullAddress; @@ -703,7 +703,7 @@ describe('OrderConfirmation.vue', () => { useMainStore().getSubmittedOrder = jest.fn().mockImplementation(() => order); }; const { wrapper } = getMountedComponent({}, {}, mockStoreActions); - const expected = '304 Provider Ln.,
, PA 16001'; + const expected = '304 Provider Ln., , PA 16001'; // Act const text = wrapper.vm.providerFullAddress; @@ -717,7 +717,7 @@ describe('OrderConfirmation.vue', () => { useMainStore().getSubmittedOrder = jest.fn().mockImplementation(() => order); }; const { wrapper } = getMountedComponent({}, {}, mockStoreActions); - const expected = '304 Provider Ln.,
Pittsburg, 16001'; + const expected = '304 Provider Ln., Pittsburg, 16001'; // Act const text = wrapper.vm.providerFullAddress; @@ -731,7 +731,7 @@ describe('OrderConfirmation.vue', () => { useMainStore().getSubmittedOrder = jest.fn().mockImplementation(() => order); }; const { wrapper } = getMountedComponent({}, {}, mockStoreActions); - const expected = '304 Provider Ln.,
Pittsburg, PA '; + const expected = '304 Provider Ln., Pittsburg, PA '; // Act const text = wrapper.vm.providerFullAddress; @@ -956,9 +956,9 @@ describe('OrderConfirmation.vue', () => { describe('Methods', () => { describe('formatDate', () => { test.each([ - ['Wednesday, April 22', '2020-04-22'], - ['Thursday, February 1', '2018-02-01'], - ['Wednesday, December 30', '2026-12-30'] + ['Wednesday, April 22, 2020', '2020-04-22'], + ['Thursday, February 1, 2018', '2018-02-01'], + ['Wednesday, December 30, 2026', '2026-12-30'] ])('returns %p given %p', (expected, date) => { // Arrange const order = deepClone(sessionStorage); diff --git a/src/layouts/order-confirmation/order-confirmation.vue b/src/layouts/order-confirmation/order-confirmation.vue index fc03df1c..a702cd1a 100644 --- a/src/layouts/order-confirmation/order-confirmation.vue +++ b/src/layouts/order-confirmation/order-confirmation.vue @@ -422,7 +422,7 @@ export default { // settleTenderAmount always shows 0 via localhost or dev. // Temporarily set return true to see cart in localhost or dev environment - return true; + return false; }, displayWipers() { const hasWiperPart = this.submittedOrder.lineItems.vaps.some((part) => part.partType.toLowerCase().includes('wiper')); From 0a9007cc33df380ea856b5d8a696d54dfaf3b150 Mon Sep 17 00:00:00 2001 From: Alex Humphries Date: Wed, 11 Feb 2026 16:50:10 -0500 Subject: [PATCH 06/11] Undo accidental commit of .eslintrc.js --- .eslintrc.js | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index 95b47ad0..65c1caa3 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -7,7 +7,9 @@ module.exports = { ecmaVersion: 'latest' }, extends: [ - 'plugin:vue/vue3-recommended' + 'eslint-config-airbnb-base', + 'plugin:vue/vue3-recommended', + 'plugin:jsdoc/recommended' ], rules: { 'linebreak-style': 'off', @@ -28,6 +30,10 @@ module.exports = { singleline: 'never', multiline: 'never' }], + 'jsdoc/check-tag-names': ['error', { + definedTags: ['store', 'endpoint', 'category', 'subcategory', 'remarks'] + }], + 'jsdoc/require-jsdoc': 0, 'vue/html-self-closing': ['error', { html: { void: 'any', @@ -37,6 +43,7 @@ module.exports = { svg: 'always', math: 'always' }], + 'import/extensions': ['error', 'always', { js: 'ignorePackages' }], 'no-param-reassign': ['error', { props: true, ignorePropertyModificationsFor: ['item'] }], 'no-restricted-syntax': ['off', 'ForOfStatement'], 'no-return-await': 'off' @@ -49,4 +56,4 @@ module.exports = { } } } -}; +}; \ No newline at end of file From 694c274be4a6b2094bef042b0c602f23ce2f1470 Mon Sep 17 00:00:00 2001 From: Alex Humphries Date: Wed, 11 Feb 2026 17:01:43 -0500 Subject: [PATCH 07/11] INSR-7757: Copilot suggestions to fix a couple bugs --- .../order-confirmation/add-to-calendar/add-to-calendar.vue | 5 ++++- .../calendar-option-selection/calendar-option-selection.vue | 5 ++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/layouts/order-confirmation/add-to-calendar/add-to-calendar.vue b/src/layouts/order-confirmation/add-to-calendar/add-to-calendar.vue index 0140bad4..284a34e6 100644 --- a/src/layouts/order-confirmation/add-to-calendar/add-to-calendar.vue +++ b/src/layouts/order-confirmation/add-to-calendar/add-to-calendar.vue @@ -214,7 +214,7 @@ export default { }, calendarOptionSelected(calendarOptionIndex) { this.setCalendarAppointment(this.calendarValues[calendarOptionIndex]); - this.calendarOptionsOpen = false; + this.closeCalendarOptions(); }, getCalendarData(type) { let URL = ''; @@ -262,6 +262,9 @@ export default { this.closeCalendarOptions(); } } + }, + unmounted() { + window.removeEventListener('click', this.clickListener); } }; diff --git a/src/layouts/order-confirmation/add-to-calendar/calendar-option-selection/calendar-option-selection.vue b/src/layouts/order-confirmation/add-to-calendar/calendar-option-selection/calendar-option-selection.vue index 2d9a2513..1c95c555 100644 --- a/src/layouts/order-confirmation/add-to-calendar/calendar-option-selection/calendar-option-selection.vue +++ b/src/layouts/order-confirmation/add-to-calendar/calendar-option-selection/calendar-option-selection.vue @@ -15,14 +15,13 @@