// Components
import serviceLocation from "@/layouts/service-location/service-location.vue";

// Supporting files
import { shallowMount } from "@vue/test-utils";
import { getMountOptions } from "@/helpers/unit-test-helper";

import store from "@/store";
import baseMixin from "@/mixins/base-mixin";
import { experimentSettings } from "@/constants/experiments";

// Define Mocks
jest.mock("@/helpers/cms-content-helper", () => ({
    fetchCmsContentForPage: jest.fn(() => {
        return Promise.resolve("content");
    }),
}));

jest.mock("./classes/provider");

let mockGetPricedMobileFeePart = (mockServiceZipCode) => {
    let mobileFeePart = {};

    if (mockServiceZipCode === "43235") {
        mobileFeePart = {
            partNumber: "MOBILE FEE",
            description: "MOBILE FEE",
            partType: "FEE",
            laborAmount: 49.99,
            sellingPrice: 0,
            kitPrice: 0,
        };
    }

    return Promise.resolve(mobileFeePart);
};

let mockGetServiceabilityDetails = (mockServiceZipCode) => {
    const serviceabilityDetails = {
        isGlassServiceableInshop: true,
        isRecalibrationServiceableInshop: true,
        isGlassServiceableMobile: true,
        isRecalibrationServiceableMobile: true,
    };

    return Promise.resolve(serviceabilityDetails);
};

let mockGetShopProviderData = (mockServiceZipCode) => {
    const result = {
        data: {
            mobileProviderNumber: "001820",
            shopProviders: [{}],
        },
    };

    return Promise.resolve(result);
};

jest.mock(
    "@/layouts/service-location/helpers/service-location-helper/service-location-helper",
    () => ({
        getPricedMobileFeePart: jest.fn((mockServiceZipCode) => {
            return mockGetPricedMobileFeePart(mockServiceZipCode);
        }),
        getServiceabilityDetails: jest.fn((mockServiceZipCode) => {
            return mockGetServiceabilityDetails(mockServiceZipCode);
        }),
        getShopProviderData: jest.fn((mockServiceZipCode) => {
            return mockGetShopProviderData(mockServiceZipCode);
        }),
        getZipCodeData: jest.fn().mockImplementation(() => {
            return Promise.resolve({
                containsMilitaryBase: false,
                isServiceable: true,
                isValid: true,
                state: "testState",
                zipCodeCtu: "testCTU",
            });
        }),
    })
);

jest.spyOn(baseMixin.methods, "getZipCodeData").mockImplementation((serviceZipCode) => {
    return new Promise((resolve) => {
        let mockContainsMilitaryBase = false;
        if (serviceZipCode === 45433 || serviceZipCode === "45433") {
            mockContainsMilitaryBase = true;
        }
        resolve({
            containsMilitaryBase: mockContainsMilitaryBase,
            isValid: true,
            isServiceable: true,
            state: "OH",
            zipCodeCtu: "01820",
        });
    });
});

jest.mock("@/store", () => ({
    commit: jest.fn(),
    dispatch: jest.fn(),
}));

const mockMixin = {
    methods: {
        getCmsContent: jest.fn((widgetName, cmsFieldName) => {
            if (widgetName === linkWidgetName) {
                return mockLinkCmsContent[cmsFieldName];
            }

            if (widgetName === modalWidgetName) {
                return mockModalCmsContent[cmsFieldName];
            }

            if (widgetName === mobileFeeDisclaimerWidgetName) {
                return mockMobileFeeDisclaimerContent[cmsFieldName];
            }

            return null;
        }),

        getZipCodeData: jest.fn((zip) => {
            if (zip === "43235" || zip === "55555") {
                return Promise.resolve({
                    containsMilitaryBase: false,
                    isValid: true,
                    state: "OH",
                    zipCodeCtu: "01820",
                });
            }

            return Promise.resolve({
                containsMilitaryBase: false,
                isValid: false,
                state: null,
                zipCodeCtu: null,
            });
        }),

        dispatchStoreAction: jest.fn((actionName) => {
            if (actionName === storeActions.GET_MOBILE_FEE_PART) {
                return Promise.resolve({
                    data: {
                        partNumber: "MOBILE FEE",
                        description: "MOBILE FEE",
                        partType: "FEE",
                    },
                });
            }

            if (actionName === storeActions.PRICE_ORDER_ITEMS_AND_SAVE_SERVER_DATA) {
                return Promise.resolve([
                    {
                        partNumber: "MOBILE FEE",
                        description: "MOBILE FEE",
                        partType: "FEE",
                        laborAmount: 49.99,
                        sellingPrice: 0,
                        kitPrice: 0,
                    },
                ]);
            }
        }),

        getTotalLineItemPrice: jest.fn((lineItem) => {
            return 49.99;
        }),

        onSubmit: jest.fn(),
        onInvalidSubmit: jest.fn(),
    },
};

beforeEach(() => {
    store.getters = {
        applicationUser: { experiments: [] },
        lineItems: {
            supportingItems: [
                {
                    description: null,
                    kitPrice: 0,
                    laborAmount: 0,
                    partNumber: "SUPPLIES-REPAIR",
                    partType: "REPAIR FEE",
                    sellingPrice: 7.99,
                },
            ],
        },
        order: {
            serviceLocation: {
                zipCode: "43235",
                state: "OH",
            },
        },
        damage: {
            isRepair: false,
        },
        payment: {
            isInsurance: false,
        },
        vehicle: {
            registration: {
                address: "5555 Sulgrave Dr",
                city: "New Albany",
                state: "OH",
                zipCode: "43054",
            },
        },
        experimentSettings: {
            settingName: experimentSettings.DISPLAY_MSR,
        },
    };
});

describe("service-location.vue", () => {
    describe("beforeRouteEnter", () => {
        test("on load sets the mobile fee part when a service zip code has already been provided", async () => {
            // Arrange
            const { wrapper } = setupMocks({});

            wrapper.vm.$refs.shopQuestion.initializeComponent = jest.fn();

            const mobileFeePart = {
                partNumber: "MOBILE FEE",
                description: "MOBILE FEE",
                partType: "FEE",
                laborAmount: 49.99,
                sellingPrice: 0,
                kitPrice: 0,
            };

            // Act
            await serviceLocation.beforeRouteEnter.call(
                wrapper.vm,
                { query: { fmgPage: "serviceLocation" } },
                undefined,
                (c) => c(wrapper.vm)
            );

            // Assert
            expect(wrapper.vm.mobileFeePart).toStrictEqual(mobileFeePart);
        });
    });

    describe("arePagePrerequisitesValid", () => {
        test("No prerequisites set: Should return false.", () => {
            const { wrapper } = setupMocks({});

            store.getters = {
                lineItems: {
                    supportingItems: null,
                },
                order: {
                    serviceLocation: {
                        zipCode: null,
                    },
                },
                payment: {
                    isInsurance: null,
                },
            };

            let arePagePrerequisitesValid = wrapper.vm.arePagePrerequisitesValid();

            expect(arePagePrerequisitesValid).toBe(false);
        });

        test("All prerequisites set: Should return true.", () => {
            const { wrapper } = setupMocks({});

            let arePagePrerequisitesValid = wrapper.vm.arePagePrerequisitesValid();

            expect(arePagePrerequisitesValid).toBe(true);
        });

        test("Some prerequisites set: Should return false.", () => {
            const { wrapper } = setupMocks({});

            store.getters.order.serviceLocation.zipCode = null;

            let arePagePrerequisitesValid = wrapper.vm.arePagePrerequisitesValid();

            expect(arePagePrerequisitesValid).toBe(false);
        });
    });

    describe("updating service zip", () => {
        test("updates the page model after providing the service zip code", () => {
            // Arrange
            const { wrapper } = setupMocks({
                mixins: [mockMixin],
            });

            const mobileLocationQuestionsComponent = wrapper.findComponent({
                ref: "mobileLocationQuestions",
            });
            mobileLocationQuestionsComponent.resetComponent = jest.fn();

            const newServiceZipCodeQuestion = {
                zipCode: "61606",
                state: "IL",
                zipCodeCtu: "01526",
            };

            const serviceZipCodeComponent = wrapper.findComponent({
                ref: "serviceZipCodeQuestion",
            });

            // Act
            serviceZipCodeComponent.vm.$emit("update:modelValue", newServiceZipCodeQuestion);

            // Assert
            expect(wrapper.vm.serviceZipCodeQuestion).toStrictEqual(newServiceZipCodeQuestion);
        });

        test("resets mobile location when service zip code is updated", () => {
            // Arrange
            const { wrapper } = setupMocks({});

            const mobileLocationQuestionsComponent = wrapper.findComponent({
                ref: "mobileLocationQuestions",
            });
            mobileLocationQuestionsComponent.resetComponent = jest.fn();

            const serviceZipCodeComponent = wrapper.findComponent({
                ref: "serviceZipCodeQuestion",
            });
            serviceZipCodeComponent.resetMobileFeePart = jest.fn();

            const newServiceZipCodeQuestion = {
                zipCode: "61606",
                state: "IL",
                zipCodeCtu: "01526",
            };

            const mobileLocationQuestions = {
                addressQuestions: {
                    streetAddress: "5555 Sulgrave Dr",
                    apartmentNumberOrBusinessName: "Apt 1",
                    city: "New Albany",
                    state: "OH",
                    zipCode: "43054",
                },
                isVehicleProtected: true,
            };
            wrapper.vm.mobileLocationQuestions = mobileLocationQuestions;

            const newMobileLocationQuestions = {
                addressQuestions: {
                    streetAddress: "",
                    apartmentNumberOrBusinessName: "",
                    city: "",
                    state: "IL",
                    zipCode: "61606",
                },
                isVehicleProtected: null,
            };

            // Act
            serviceZipCodeComponent.vm.$emit("update:modelValue", newServiceZipCodeQuestion);

            // Assert
            expect(wrapper.vm.mobileLocationQuestions).toStrictEqual(newMobileLocationQuestions);
        });

        test("resets appointment type selection when service zip code is updated by service zip modal", () => {
            // Arrange
            const { wrapper } = setupMocks({});

            const mobileLocationQuestionsComponent = wrapper.findComponent({
                ref: "mobileLocationQuestions",
            });
            mobileLocationQuestionsComponent.resetComponent = jest.fn();

            const serviceZipCodeComponent = wrapper.findComponent({
                ref: "serviceZipCodeQuestion",
            });
            serviceZipCodeComponent.resetMobileFeePart = jest.fn();

            const newServiceZipCodeQuestion = {
                zipCode: "61606",
                state: "IL",
                zipCodeCtu: "01526",
            };

            wrapper.vm.selectedAppointmentType = "Inshop";

            // Act
            serviceZipCodeComponent.vm.$emit("update:modelValue", newServiceZipCodeQuestion);

            // Assert
            expect(wrapper.vm.selectedAppointmentType).toStrictEqual(null);
        });

        test("displays military zip message when zip is updated", () => {
            // Arrange
            const { wrapper } = setupMocks({});

            const mobileLocationQuestionsComponent = wrapper.findComponent({
                ref: "mobileLocationQuestions",
            });
            mobileLocationQuestionsComponent.resetComponent = jest.fn();

            const serviceZipCodeComponent = wrapper.findComponent({
                ref: "serviceZipCodeQuestion",
            });
            serviceZipCodeComponent.resetMobileFeePart = jest.fn();

            expect(wrapper.vm.zipContainsMilitaryBase).toBe(false);

            const newServiceZipCodeQuestion = {
                zipCode: "45433",
                state: "OH",
                zipCodeCtu: "01526",
            };

            // Act
            serviceZipCodeComponent.vm.$emit("updated-contains-military-base", true);

            // Assert
            expect(wrapper.vm.zipContainsMilitaryBase).toBe(true);
        });
    });

    describe("updating mobile location", () => {
        test("updates the page model after providing the mobile location", async () => {
            // Arrange
            const { wrapper } = setupMocks({});

            await wrapper.setData({
                shopProviderData: {
                    mobileProviderNumber: "001820",
                },
                selectedAppointmentType: "Mobile",
                providerData: { mobileProviderNumber: "01820" },
                isGlassServiceableMobile: true,
            });

            const mobileLocationQuestionsComponent = wrapper.findComponent({
                ref: "mobileLocationQuestions",
            });
            mobileLocationQuestionsComponent.resetComponent = jest.fn();

            const serviceZipCodeComponent = wrapper.findComponent({
                ref: "serviceZipCodeQuestion",
            });
            serviceZipCodeComponent.resetMobileFeePart = jest.fn();
            wrapper.vm.forwardButtonAction = jest.fn();

            const mobileLocationQuestions = {
                addressQuestions: {
                    streetAddress: "",
                    apartmentNumberOrBusinessName: "",
                    city: "",
                    state: "",
                    zipCode: "",
                },
                isVehicleProtected: null,
            };
            wrapper.vm.mobileLocationQuestions = mobileLocationQuestions;
            const newMobileLocationQuestions = {
                addressQuestions: {
                    streetAddress: "5555 Sulgrave Dr",
                    apartmentNumberOrBusinessName: "Apt 1",
                    city: "New Albany",
                    state: "OH",
                    zipCode: "43054",
                },
                isVehicleProtected: true,
            };

            wrapper.vm.closeModalAction = jest.fn();
            // Act

            // Trigger the event
            await mobileLocationQuestionsComponent.vm.$emit(
                "setMobileLocationAndProceed",
                newMobileLocationQuestions
            );

            await wrapper.vm.$nextTick(); // Wait for DOM updates

            // Assert
            expect(wrapper.vm.mobileLocationQuestions).toStrictEqual(newMobileLocationQuestions);
        });

        test("resets service zip code when mobile location is updated", async () => {
            // Arrange
            const { wrapper } = setupMocks({});

            await wrapper.setData({
                shopProviderData: {
                    mobileProviderNumber: "001820",
                },
                selectedAppointmentType: "Mobile",
                providerData: { mobileProviderNumber: "01820" },
                isGlassServiceableMobile: true,
            });

            const mobileLocationQuestionsComponent = wrapper.findComponent({
                ref: "mobileLocationQuestions",
            });
            mobileLocationQuestionsComponent.resetComponent = jest.fn();

            const serviceZipCodeComponent = wrapper.findComponent({
                ref: "serviceZipCodeQuestion",
            });
            serviceZipCodeComponent.resetMobileFeePart = jest.fn();
            wrapper.vm.forwardButtonAction = jest.fn();
            const mobileLocationQuestions = {
                addressQuestions: {
                    streetAddress: "",
                    apartmentNumberOrBusinessName: "",
                    city: "",
                    state: "",
                    zipCode: "",
                },
                isVehicleProtected: null,
                mobileFeePart: null,
            };
            wrapper.vm.mobileLocationQuestions = mobileLocationQuestions;

            const newMobileLocationQuestions = {
                addressQuestions: {
                    streetAddress: "5555 Rustic Dr",
                    apartmentNumberOrBusinessName: "Apt 1",
                    city: "Westerville",
                    state: "OH",
                    zipCode: "43081",
                },
                isVehicleProtected: true,
                mobileFeePart: null,
            };

            wrapper.vm.serviceZipCodeQuestion = {
                zipCode: "61606",
                state: "IL",
                zipCodeCtu: "01526",
            };

            const newServiceZipCodeInfo = {
                state: "OH",
                zipCode: "43081",
                zipCodeCtu: "01526",
            };

            wrapper.vm.closeModalAction = jest.fn();
            // Act

            // Trigger the event
            await mobileLocationQuestionsComponent.vm.$emit(
                "setMobileLocationAndProceed",
                newMobileLocationQuestions
            );

            await wrapper.vm.$nextTick(); // Wait for DOM updates

            // Assert
            expect(wrapper.vm.serviceZipCodeQuestion).toStrictEqual(newServiceZipCodeInfo);
        });

        test("does not reset appointment type selection when service zip code is updated by mobile location modal when Mobile is selected", async () => {
            // Arrange
            const { wrapper } = setupMocks({});

            await wrapper.setData({
                shopProviderData: {
                    mobileProviderNumber: "001820",
                },
                selectedAppointmentType: "Mobile",
                providerData: { mobileProviderNumber: "01820" },
            });

            const mobileLocationQuestionsComponent = wrapper.findComponent({
                ref: "mobileLocationQuestions",
            });
            mobileLocationQuestionsComponent.resetComponent = jest.fn();
            wrapper.vm.forwardButtonAction = jest.fn();
            wrapper.vm.isServiceableMobile = true;

            const serviceZipCodeComponent = wrapper.findComponent({
                ref: "serviceZipCodeQuestion",
            });
            serviceZipCodeComponent.resetMobileFeePart = jest.fn();

            const mobileLocationQuestions = {
                addressQuestions: {
                    streetAddress: "555 Some Street",
                    apartmentNumberOrBusinessName: "",
                    city: "Westerville",
                    state: "OH",
                    zipCode: "43081",
                },
                isVehicleProtected: "YesAnswer",
            };

            wrapper.vm.closeModalAction = jest.fn();
            // Act
            mobileLocationQuestionsComponent.vm.$emit(
                "setMobileLocationAndProceed",
                mobileLocationQuestions
            );

            // Assert
            expect(wrapper.vm.selectedAppointmentType).toStrictEqual("Mobile");
        });
    });

    describe("serviceability logic", () => {
        describe("should be logical AND when recalibration is defined.", () => {
            test("T & T => T", async () => {
                // Arrange
                mockGetServiceabilityDetails = () =>
                    Promise.resolve({
                        isGlassServiceableInshop: true,
                        isRecalibrationServiceableInshop: true,
                        isGlassServiceableMobile: true,
                        isRecalibrationServiceableMobile: true,
                    });

                const { wrapper } = setupMocks({});

                wrapper.vm.$refs.shopQuestion.initializeComponent = jest.fn();

                // Act
                await serviceLocation.beforeRouteEnter.call(
                    wrapper.vm,
                    { query: { fmgPage: "serviceLocation" } },
                    undefined,
                    (c) => c(wrapper.vm)
                );

                // Assert
                expect(wrapper.vm.isServiceableMobile).toEqual(true);
                expect(wrapper.vm.isServiceableInshop).toEqual(true);
            });

            test("T & F => F", async () => {
                // Arrange
                mockGetServiceabilityDetails = () =>
                    Promise.resolve({
                        isGlassServiceableInshop: true,
                        isRecalibrationServiceableInshop: false,
                        isGlassServiceableMobile: true,
                        isRecalibrationServiceableMobile: false,
                    });

                const { wrapper } = setupMocks({});

                wrapper.vm.$refs.shopQuestion.initializeComponent = jest.fn();

                // Act
                await serviceLocation.beforeRouteEnter.call(
                    wrapper.vm,
                    { query: { fmgPage: "serviceLocation" } },
                    undefined,
                    (c) => c(wrapper.vm)
                );

                // Assert
                expect(wrapper.vm.isServiceableMobile).toEqual(false);
                expect(wrapper.vm.isServiceableInshop).toEqual(false);
            });

            test("F & T => F", async () => {
                // Arrange
                mockGetServiceabilityDetails = () =>
                    Promise.resolve({
                        isGlassServiceableInshop: false,
                        isRecalibrationServiceableInshop: true,
                        isGlassServiceableMobile: false,
                        isRecalibrationServiceableMobile: true,
                    });

                const { wrapper } = setupMocks({});

                wrapper.vm.$refs.shopQuestion.initializeComponent = jest.fn();

                // Act
                await serviceLocation.beforeRouteEnter.call(
                    wrapper.vm,
                    { query: { fmgPage: "serviceLocation" } },
                    undefined,
                    (c) => c(wrapper.vm)
                );

                // Assert
                expect(wrapper.vm.isServiceableMobile).toEqual(false);
                expect(wrapper.vm.isServiceableInshop).toEqual(false);
            });

            test("F & F => F", async () => {
                // Arrange
                mockGetServiceabilityDetails = () =>
                    Promise.resolve({
                        isGlassServiceableInshop: false,
                        isRecalibrationServiceableInshop: false,
                        isGlassServiceableMobile: false,
                        isRecalibrationServiceableMobile: false,
                    });

                const { wrapper } = setupMocks({});

                wrapper.vm.$refs.shopQuestion.initializeComponent = jest.fn();

                // Act
                await serviceLocation.beforeRouteEnter.call(
                    wrapper.vm,
                    { query: { fmgPage: "serviceLocation" } },
                    undefined,
                    (c) => c(wrapper.vm)
                );

                // Assert
                expect(wrapper.vm.isServiceableMobile).toEqual(false);
                expect(wrapper.vm.isServiceableInshop).toEqual(false);
            });

            test("displayServiceableMobileOnly should be true if mobile is true and inshop is false.", async () => {
                // Arrange
                mockGetServiceabilityDetails = () =>
                    Promise.resolve({
                        isGlassServiceableInshop: false,
                        isRecalibrationServiceableInshop: false,
                        isGlassServiceableMobile: true,
                        isRecalibrationServiceableMobile: true,
                    });

                const { wrapper } = setupMocks({});

                wrapper.vm.$refs.shopQuestion.initializeComponent = jest.fn();

                // Act
                await serviceLocation.beforeRouteEnter.call(
                    wrapper.vm,
                    { query: { fmgPage: "serviceLocation" } },
                    undefined,
                    (c) => c(wrapper.vm)
                );

                // Assert
                expect(wrapper.vm.isServiceableMobile).toEqual(true);
                expect(wrapper.vm.isServiceableInshop).toEqual(false);
                expect(wrapper.vm.displayServiceableMobileOnly).toEqual(true);
            });

            test("displayServiceableMobileOnly should be false if mobile is false.", async () => {
                // Arrange
                mockGetServiceabilityDetails = () =>
                    Promise.resolve({
                        isGlassServiceableInshop: false,
                        isRecalibrationServiceableInshop: false,
                        isGlassServiceableMobile: false,
                        isRecalibrationServiceableMobile: false,
                    });

                const { wrapper } = setupMocks({});

                wrapper.vm.$refs.shopQuestion.initializeComponent = jest.fn();

                // Act
                await serviceLocation.beforeRouteEnter.call(
                    wrapper.vm,
                    { query: { fmgPage: "serviceLocation" } },
                    undefined,
                    (c) => c(wrapper.vm)
                );

                // Assert
                expect(wrapper.vm.isServiceableMobile).toEqual(false);
                expect(wrapper.vm.isServiceableInshop).toEqual(false);
                expect(wrapper.vm.displayServiceableMobileOnly).toEqual(false);
            });

            test("displayServiceableMobileOnly should be false if inShop is true", async () => {
                // Arrange
                mockGetServiceabilityDetails = () =>
                    Promise.resolve({
                        isGlassServiceableInshop: true,
                        isRecalibrationServiceableInshop: true,
                        isGlassServiceableMobile: true,
                        isRecalibrationServiceableMobile: true,
                    });

                const { wrapper } = setupMocks({});

                wrapper.vm.$refs.shopQuestion.initializeComponent = jest.fn();

                // Act
                await serviceLocation.beforeRouteEnter.call(
                    wrapper.vm,
                    { query: { fmgPage: "serviceLocation" } },
                    undefined,
                    (c) => c(wrapper.vm)
                );

                // Assert
                expect(wrapper.vm.isServiceableMobile).toEqual(true);
                expect(wrapper.vm.isServiceableInshop).toEqual(true);
                expect(wrapper.vm.displayServiceableMobileOnly).toEqual(false);
            });

            test("displayNoShopsAlert should be true if inShop is false and mobile is false", async () => {
                // Arrange
                mockGetServiceabilityDetails = () =>
                    Promise.resolve({
                        isGlassServiceableInshop: false,
                        isRecalibrationServiceableInshop: false,
                        isGlassServiceableMobile: false,
                        isRecalibrationServiceableMobile: false,
                    });

                const { wrapper } = setupMocks({});

                wrapper.vm.$refs.shopQuestion.initializeComponent = jest.fn();

                // Act
                await serviceLocation.beforeRouteEnter.call(
                    wrapper.vm,
                    { query: { fmgPage: "serviceLocation" } },
                    undefined,
                    (c) => c(wrapper.vm)
                );

                // Assert
                expect(wrapper.vm.isServiceableMobile).toEqual(false);
                expect(wrapper.vm.isServiceableInshop).toEqual(false);
                expect(wrapper.vm.displayNoShopsAlert).toEqual(true);
            });

            test("displayNoShopsAlert should be false if inShop is true and mobile is true", async () => {
                // Arrange
                mockGetServiceabilityDetails = () =>
                    Promise.resolve({
                        isGlassServiceableInshop: true,
                        isRecalibrationServiceableInshop: true,
                        isGlassServiceableMobile: true,
                        isRecalibrationServiceableMobile: true,
                    });

                const { wrapper } = setupMocks({});

                wrapper.vm.$refs.shopQuestion.initializeComponent = jest.fn();

                // Act
                await serviceLocation.beforeRouteEnter.call(
                    wrapper.vm,
                    { query: { fmgPage: "serviceLocation" } },
                    undefined,
                    (c) => c(wrapper.vm)
                );

                // Assert
                expect(wrapper.vm.isServiceableMobile).toEqual(true);
                expect(wrapper.vm.isServiceableInshop).toEqual(true);
                expect(wrapper.vm.displayNoShopsAlert).toEqual(false);
            });

            test("displayNoShopsAlert should be false if inShop is true", async () => {
                // Arrange
                mockGetServiceabilityDetails = () =>
                    Promise.resolve({
                        isGlassServiceableInshop: true,
                        isRecalibrationServiceableInshop: true,
                        isGlassServiceableMobile: false,
                        isRecalibrationServiceableMobile: false,
                    });

                const { wrapper } = setupMocks({});

                wrapper.vm.$refs.shopQuestion.initializeComponent = jest.fn();

                // Act
                await serviceLocation.beforeRouteEnter.call(
                    wrapper.vm,
                    { query: { fmgPage: "serviceLocation" } },
                    undefined,
                    (c) => c(wrapper.vm)
                );

                // Assert
                expect(wrapper.vm.isServiceableMobile).toEqual(false);
                expect(wrapper.vm.isServiceableInshop).toEqual(true);
                expect(wrapper.vm.displayNoShopsAlert).toEqual(false);
            });

            test("displayNoShopsAlert should be false if mobile is true", async () => {
                // Arrange
                mockGetServiceabilityDetails = () =>
                    Promise.resolve({
                        isGlassServiceableInshop: false,
                        isRecalibrationServiceableInshop: false,
                        isGlassServiceableMobile: true,
                        isRecalibrationServiceableMobile: true,
                    });

                const { wrapper } = setupMocks({});

                wrapper.vm.$refs.shopQuestion.initializeComponent = jest.fn();

                // Act
                await serviceLocation.beforeRouteEnter.call(
                    wrapper.vm,
                    { query: { fmgPage: "serviceLocation" } },
                    undefined,
                    (c) => c(wrapper.vm)
                );

                // Assert
                expect(wrapper.vm.isServiceableMobile).toEqual(true);
                expect(wrapper.vm.isServiceableInshop).toEqual(false);
                expect(wrapper.vm.displayNoShopsAlert).toEqual(false);
            });

            test("displayServiceableInshopOnly should be true if inshop is true and mobile is false", async () => {
                // Arrange
                mockGetServiceabilityDetails = () =>
                    Promise.resolve({
                        isGlassServiceableInshop: true,
                        isRecalibrationServiceableInshop: true,
                        isGlassServiceableMobile: false,
                        isRecalibrationServiceableMobile: false,
                    });

                const { wrapper } = setupMocks({});

                wrapper.vm.$refs.shopQuestion.initializeComponent = jest.fn();

                // Act
                await serviceLocation.beforeRouteEnter.call(
                    wrapper.vm,
                    { query: { fmgPage: "serviceLocation" } },
                    undefined,
                    (c) => c(wrapper.vm)
                );

                // Assert
                expect(wrapper.vm.isServiceableMobile).toEqual(false);
                expect(wrapper.vm.isServiceableInshop).toEqual(true);
                expect(wrapper.vm.displayServiceableInshopOnly).toEqual(true);
            });

            test("displayServiceableInshopOnly should be false if inshop is false", async () => {
                // Arrange
                mockGetServiceabilityDetails = () =>
                    Promise.resolve({
                        isGlassServiceableInshop: false,
                        isRecalibrationServiceableInshop: false,
                        isGlassServiceableMobile: false,
                        isRecalibrationServiceableMobile: false,
                    });

                const { wrapper } = setupMocks({});

                wrapper.vm.$refs.shopQuestion.initializeComponent = jest.fn();

                // Act
                await serviceLocation.beforeRouteEnter.call(
                    wrapper.vm,
                    { query: { fmgPage: "serviceLocation" } },
                    undefined,
                    (c) => c(wrapper.vm)
                );

                // Assert
                expect(wrapper.vm.isServiceableMobile).toEqual(false);
                expect(wrapper.vm.isServiceableInshop).toEqual(false);
                expect(wrapper.vm.displayServiceableInshopOnly).toEqual(false);
            });

            test("displayServiceableInshopOnly should be false if mobile is true", async () => {
                // Arrange
                mockGetServiceabilityDetails = () =>
                    Promise.resolve({
                        isGlassServiceableInshop: true,
                        isRecalibrationServiceableInshop: true,
                        isGlassServiceableMobile: true,
                        isRecalibrationServiceableMobile: true,
                    });

                const { wrapper } = setupMocks({});

                wrapper.vm.$refs.shopQuestion.initializeComponent = jest.fn();

                // Act
                await serviceLocation.beforeRouteEnter.call(
                    wrapper.vm,
                    { query: { fmgPage: "serviceLocation" } },
                    undefined,
                    (c) => c(wrapper.vm)
                );

                // Assert
                expect(wrapper.vm.isServiceableMobile).toEqual(true);
                expect(wrapper.vm.isServiceableInshop).toEqual(true);
                expect(wrapper.vm.displayServiceableInshopOnly).toEqual(false);
            });

            test("displayServiceableInshopOnly should be false in the dual/static recalibration scenario", async () => {
                // Arrange
                mockGetServiceabilityDetails = () =>
                    Promise.resolve({
                        isGlassServiceableInshop: true,
                        isRecalibrationServiceableInshop: true,
                        isGlassServiceableMobile: true,
                        isRecalibrationServiceableMobile: false,
                    });

                const { wrapper } = setupMocks({});

                wrapper.vm.$refs.shopQuestion.initializeComponent = jest.fn();

                // Act
                await serviceLocation.beforeRouteEnter.call(
                    wrapper.vm,
                    { query: { fmgPage: "serviceLocation" } },
                    undefined,
                    (c) => c(wrapper.vm)
                );

                // Assert
                expect(wrapper.vm.isServiceableMobile).toEqual(false);
                expect(wrapper.vm.isServiceableInshop).toEqual(true);
                expect(wrapper.vm.displayServiceableInshopOnly).toEqual(false);
                expect(wrapper.vm.displayRecalibrationWarning).toEqual(true);
            });
        });

        describe("should be based only on glass serviceability if recalibration is not defined.", () => {
            test("Should return true", async () => {
                // Arrange
                mockGetServiceabilityDetails = () =>
                    Promise.resolve({
                        isGlassServiceableInshop: true,
                        isRecalibrationServiceableInshop: null,
                        isGlassServiceableMobile: true,
                        isRecalibrationServiceableMobile: null,
                    });

                const { wrapper } = setupMocks({});

                wrapper.vm.$refs.shopQuestion.initializeComponent = jest.fn();

                // Act
                await serviceLocation.beforeRouteEnter.call(
                    wrapper.vm,
                    { query: { fmgPage: "serviceLocation" } },
                    undefined,
                    (c) => c(wrapper.vm)
                );

                // Assert
                expect(wrapper.vm.isServiceableMobile).toEqual(true);
                expect(wrapper.vm.isServiceableInshop).toEqual(true);
            });

            test("Should return false", async () => {
                // Arrange
                mockGetServiceabilityDetails = () =>
                    Promise.resolve({
                        isGlassServiceableInshop: false,
                        isRecalibrationServiceableInshop: null,
                        isGlassServiceableMobile: false,
                        isRecalibrationServiceableMobile: null,
                    });

                const { wrapper } = setupMocks({});

                wrapper.vm.$refs.shopQuestion.initializeComponent = jest.fn();

                // Act
                await serviceLocation.beforeRouteEnter.call(
                    wrapper.vm,
                    { query: { fmgPage: "serviceLocation" } },
                    undefined,
                    (c) => c(wrapper.vm)
                );

                // Assert
                expect(wrapper.vm.isServiceableMobile).toEqual(false);
                expect(wrapper.vm.isServiceableInshop).toEqual(false);
            });

            test("displayServiceableMobileOnly should be true if mobile is true and inshop is false.", async () => {
                // Arrange
                mockGetServiceabilityDetails = () =>
                    Promise.resolve({
                        isGlassServiceableInshop: false,
                        isRecalibrationServiceableInshop: null,
                        isGlassServiceableMobile: true,
                        isRecalibrationServiceableMobile: null,
                    });

                const { wrapper } = setupMocks({});

                wrapper.vm.$refs.shopQuestion.initializeComponent = jest.fn();

                // Act
                await serviceLocation.beforeRouteEnter.call(
                    wrapper.vm,
                    { query: { fmgPage: "serviceLocation" } },
                    undefined,
                    (c) => c(wrapper.vm)
                );

                // Assert
                expect(wrapper.vm.isServiceableMobile).toEqual(true);
                expect(wrapper.vm.isServiceableInshop).toEqual(false);
                expect(wrapper.vm.displayServiceableMobileOnly).toEqual(true);
            });

            test("displayServiceableMobileOnly should be false if mobile is false", async () => {
                // Arrange
                mockGetServiceabilityDetails = () =>
                    Promise.resolve({
                        isGlassServiceableInshop: false,
                        isRecalibrationServiceableInshop: null,
                        isGlassServiceableMobile: false,
                        isRecalibrationServiceableMobile: null,
                    });

                const { wrapper } = setupMocks({});

                wrapper.vm.$refs.shopQuestion.initializeComponent = jest.fn();

                // Act
                await serviceLocation.beforeRouteEnter.call(
                    wrapper.vm,
                    { query: { fmgPage: "serviceLocation" } },
                    undefined,
                    (c) => c(wrapper.vm)
                );

                // Assert
                expect(wrapper.vm.isServiceableMobile).toEqual(false);
                expect(wrapper.vm.isServiceableInshop).toEqual(false);
                expect(wrapper.vm.displayServiceableMobileOnly).toEqual(false);
            });

            test("displayServiceableMobileOnly should be false if inShop is true", async () => {
                // Arrange
                mockGetServiceabilityDetails = () =>
                    Promise.resolve({
                        isGlassServiceableInshop: true,
                        isRecalibrationServiceableInshop: null,
                        isGlassServiceableMobile: true,
                        isRecalibrationServiceableMobile: null,
                    });

                const { wrapper } = setupMocks({});

                wrapper.vm.$refs.shopQuestion.initializeComponent = jest.fn();

                // Act
                await serviceLocation.beforeRouteEnter.call(
                    wrapper.vm,
                    { query: { fmgPage: "serviceLocation" } },
                    undefined,
                    (c) => c(wrapper.vm)
                );

                // Assert
                expect(wrapper.vm.isServiceableMobile).toEqual(true);
                expect(wrapper.vm.isServiceableInshop).toEqual(true);
                expect(wrapper.vm.displayServiceableMobileOnly).toEqual(false);
            });

            test("requiresInshopRecalibration should not be true if recalibration info is null.", async () => {
                // Arrange
                mockGetServiceabilityDetails = () =>
                    Promise.resolve({
                        isGlassServiceableInshop: true,
                        isRecalibrationServiceableInshop: null,
                        isGlassServiceableMobile: true,
                        isRecalibrationServiceableMobile: null,
                    });

                const { wrapper } = setupMocks({});

                wrapper.vm.$refs.shopQuestion.initializeComponent = jest.fn();

                // Act
                await serviceLocation.beforeRouteEnter.call(
                    wrapper.vm,
                    { query: { fmgPage: "serviceLocation" } },
                    undefined,
                    (c) => c(wrapper.vm)
                );

                // Assert
                expect(wrapper.vm.isServiceableMobile).toEqual(true);
                expect(wrapper.vm.isServiceableInshop).toEqual(true);
                expect(wrapper.vm.requiresInshopRecalibration).toEqual(false);
            });
        });

        describe("should properly display alerts.", () => {
            test("Should show mobile-only error if only mobile is available.", async () => {
                // Arrange
                mockGetServiceabilityDetails = () =>
                    Promise.resolve({
                        isGlassServiceableInshop: false,
                        isRecalibrationServiceableInshop: false,
                        isGlassServiceableMobile: true,
                        isRecalibrationServiceableMobile: true,
                    });

                const { wrapper } = setupMocks({});

                wrapper.vm.$refs.shopQuestion.initializeComponent = jest.fn();

                // Act
                await serviceLocation.beforeRouteEnter.call(
                    wrapper.vm,
                    { query: { fmgPage: "serviceLocation" } },
                    undefined,
                    (c) => c(wrapper.vm)
                );

                const alertComponent = wrapper.findComponent({ ref: "alertMobileOnly" });

                // Assert
                expect(alertComponent.exists()).toBe(true);
            });

            test("Should not show mobile-only error if not mobile-only.", async () => {
                // Arrange
                mockGetServiceabilityDetails = () =>
                    Promise.resolve({
                        isGlassServiceableInshop: true,
                        isRecalibrationServiceableInshop: true,
                        isGlassServiceableMobile: true,
                        isRecalibrationServiceableMobile: true,
                    });

                const { wrapper } = setupMocks({});

                wrapper.vm.$refs.shopQuestion.initializeComponent = jest.fn();

                // Act
                await serviceLocation.beforeRouteEnter.call(
                    wrapper.vm,
                    { query: { fmgPage: "serviceLocation" } },
                    undefined,
                    (c) => c(wrapper.vm)
                );

                const alertComponent = wrapper.findComponent({ ref: "alertMobileOnly" });

                // Assert
                expect(alertComponent.exists()).toBe(false);
            });

            test("Should show no-shop error if no shops are available.", async () => {
                // Arrange
                mockGetServiceabilityDetails = () =>
                    Promise.resolve({
                        isGlassServiceableInshop: false,
                        isRecalibrationServiceableInshop: false,
                        isGlassServiceableMobile: false,
                        isRecalibrationServiceableMobile: false,
                    });

                const { wrapper } = setupMocks({});

                wrapper.vm.$refs.shopQuestion.initializeComponent = jest.fn();

                // Act
                await serviceLocation.beforeRouteEnter.call(
                    wrapper.vm,
                    { query: { fmgPage: "serviceLocation" } },
                    undefined,
                    (c) => c(wrapper.vm)
                );

                const alertComponent = wrapper.findComponent({ ref: "alertNoShops" });

                // Assert
                expect(alertComponent.exists()).toBe(true);
            });

            test("Should not show no-shop error if shops are available.", async () => {
                // Arrange
                mockGetServiceabilityDetails = () =>
                    Promise.resolve({
                        isGlassServiceableInshop: true,
                        isRecalibrationServiceableInshop: true,
                        isGlassServiceableMobile: true,
                        isRecalibrationServiceableMobile: true,
                    });

                const { wrapper } = setupMocks({});

                wrapper.vm.$refs.shopQuestion.initializeComponent = jest.fn();

                // Act
                await serviceLocation.beforeRouteEnter.call(
                    wrapper.vm,
                    { query: { fmgPage: "serviceLocation" } },
                    undefined,
                    (c) => c(wrapper.vm)
                );

                const alertComponent = wrapper.findComponent({ ref: "alertNoShops" });

                // Assert
                expect(alertComponent.exists()).toBe(false);
            });

            test("Should show inshop-only error if only inshop is available", async () => {
                // Arrange
                mockGetServiceabilityDetails = () =>
                    Promise.resolve({
                        isGlassServiceableInshop: true,
                        isRecalibrationServiceableInshop: true,
                        isGlassServiceableMobile: false,
                        isRecalibrationServiceableMobile: false,
                    });

                const { wrapper } = setupMocks({});

                wrapper.vm.$refs.shopQuestion.initializeComponent = jest.fn();

                // Act
                await serviceLocation.beforeRouteEnter.call(
                    wrapper.vm,
                    { query: { fmgPage: "serviceLocation" } },
                    undefined,
                    (c) => c(wrapper.vm)
                );

                const alertComponent = wrapper.findComponent({ ref: "alertInshopOnly" });

                // Assert
                expect(alertComponent.exists()).toBe(true);
            });

            test("Should not show inshop-only error if not inshop-only", async () => {
                // Arrange
                mockGetServiceabilityDetails = () =>
                    Promise.resolve({
                        isGlassServiceableInshop: false,
                        isRecalibrationServiceableInshop: false,
                        isGlassServiceableMobile: false,
                        isRecalibrationServiceableMobile: false,
                    });

                const { wrapper } = setupMocks({});

                wrapper.vm.$refs.shopQuestion.initializeComponent = jest.fn();

                // Act
                await serviceLocation.beforeRouteEnter.call(
                    wrapper.vm,
                    { query: { fmgPage: "serviceLocation" } },
                    undefined,
                    (c) => c(wrapper.vm)
                );

                const alertComponent = wrapper.findComponent({ ref: "alertInshopOnly" });

                // Assert
                expect(alertComponent.exists()).toBe(false);
            });

            test("Should not show inshop-only error if dual or static recalibration, but should show that error instead.", async () => {
                // Arrange
                mockGetServiceabilityDetails = () =>
                    Promise.resolve({
                        isGlassServiceableInshop: true,
                        isRecalibrationServiceableInshop: true,
                        isGlassServiceableMobile: true,
                        isRecalibrationServiceableMobile: false,
                    });

                const { wrapper } = setupMocks({});

                wrapper.vm.$refs.shopQuestion.initializeComponent = jest.fn();

                // Act
                await serviceLocation.beforeRouteEnter.call(
                    wrapper.vm,
                    { query: { fmgPage: "serviceLocation" } },
                    undefined,
                    (c) => c(wrapper.vm)
                );

                const alertInshopComponent = wrapper.findComponent({ ref: "alertInshopOnly" });
                const alertRecalComponent = wrapper.findComponent({ ref: "alertRecalNoMobile" });

                // Assert
                expect(alertInshopComponent.exists()).toBe(false);
                expect(alertRecalComponent.exists()).toBe(true);
            });

            test("Should not show dual/static recalibration error if not those recalibration types", async () => {
                // Arrange
                mockGetServiceabilityDetails = () =>
                    Promise.resolve({
                        isGlassServiceableInshop: true,
                        isRecalibrationServiceableInshop: true,
                        isGlassServiceableMobile: true,
                        isRecalibrationServiceableMobile: true,
                    });

                const { wrapper } = setupMocks({});

                wrapper.vm.$refs.shopQuestion.initializeComponent = jest.fn();

                // Act
                await serviceLocation.beforeRouteEnter.call(
                    wrapper.vm,
                    { query: { fmgPage: "serviceLocation" } },
                    undefined,
                    (c) => c(wrapper.vm)
                );

                const alertComponent = wrapper.findComponent({ ref: "alertRecalNoMobile" });

                // Assert
                expect(alertComponent.exists()).toBe(false);
            });
        });
    });
});

function setupMocks({ mountOptionsMockData = {} }) {
    const apiResponses = {};

    const apiPromise = Promise.resolve(apiResponses);

    const mountOptions = getMountOptions(mountOptionsMockData);
    const wrapper = shallowMount(serviceLocation, mountOptions);
    wrapper.vm.setCmsContent = baseMixin.methods.setCmsContent;
    return { wrapper, apiPromise };
}
