import { shallowMount } from '@vue/test-utils';
import { createTestingPinia } from '@pinia/testing';
import cartDropdown from '@/iss-components/cart-dropdown/cart-dropdown.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(cartDropdown, mountOptions);
    return { wrapper };
}

beforeEach(() => {
    const store = useMainStore();
    const defaultState = getDefaultState();
    Object.keys(defaultState).forEach((key) => {
        store[key] = defaultState[key];
    });
});

describe('cart-dropdown 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(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);

            // 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(cartDropdown, 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(cartDropdown, 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(cartDropdown, 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(cartDropdown, 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(cartDropdown, 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(cartDropdown, 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(cartDropdown, 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(cartDropdown, 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(cartDropdown, 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(cartDropdown, 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(cartDropdown, 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(cartDropdown, 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(cartDropdown, 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(cartDropdown, 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(cartDropdown, 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(cartDropdown, mountOptions);

                // Act
                const result = wrapper.vm.getCartItemForVapsPart(part);

                // Assert
                expect(result.subTotal).toBe(expectedSubtotal);
            });
        });
    });
});
