import baseMixin from "@/mixins/base-mixin";
import { storeActions } from "@/constants/store-actions.js";
import { storeMutations } from "@/constants/store-mutations.js";
import { navigationScenarios } from "@/router/router-constants/navigation-scenarios";
import { vehicleCategories } from "@/constants/vehicle-categories.js";
import { queryStrings } from "@/constants/query-strings";
import { dynamicStrings } from "@/constants/dynamic-strings";
import store from "@/store";

describe("baseMixin.js", () => {
    test("dispatchStoreAction: calls dispatch with type and payload", () => {
        const mixIn = getMixInInstance({});
        const type = "";
        const payload = {};

        mixIn.methods.dispatchStoreAction(type, payload);

        expect(store.dispatch).toBeCalledWith(type, payload);
    });

    test("dispatchStoreAction: calls dispatch with type and payload, handles Uri encode", () => {
        const mixIn = getMixInInstance({});
        const type = "";
        const payload = { make: "Alfa Romeo/Chrysler" };

        mixIn.methods.dispatchStoreAction(type, payload, true);

        expect(store.dispatch).toBeCalledWith(type, payload);
    });

    test("savePageDataToStore, should call store commit", () => {
        const mixIn = getMixInInstance({});

        mixIn.methods.savePageDataToStore("vehicle-year", {});

        expect(store.commit).toBeCalledWith(storeMutations.UPDATE_PAGE_DATA, {
            page: "vehicle-year",
            data: {},
        });
    });

    test("computed: storeActions should be equal to import object", () => {
        // Arrange
        const mixIn = getMixInInstance({});

        // Act
        let storeActionsForTest = mixIn.computed.storeActions();

        // Assert
        expect(storeActionsForTest).toEqual(storeActions);
    });

    test("computed: storeMutations should be equal to import object", () => {
        // Arrange
        const mixIn = getMixInInstance({});

        // Act
        let storeMutationsForTest = mixIn.computed.storeMutations();

        // Assert
        expect(storeMutationsForTest).toEqual(storeMutations);
    });

    test("computed: navigationScenarios should be equal to import object", () => {
        // Arrange
        const mixIn = getMixInInstance({});

        // Act
        let navigationScenariosForTest = mixIn.computed.navigationScenarios();

        // Assert
        expect(navigationScenariosForTest).toEqual(navigationScenarios);
    });
    test("computed: vehicleCategories should be equal to import object", () => {
        // Arrange
        const mixIn = getMixInInstance({});

        // Act
        let vehicleCategoriesForTest = mixIn.computed.vehicleCategories();

        // Assert
        expect(vehicleCategoriesForTest).toEqual(vehicleCategories);
    });

    test("computed: queryStrings should be equal to import object", () => {
        // Arrange
        const mixIn = getMixInInstance({});

        // Act
        let queryStringsForTest = mixIn.computed.queryStrings();

        // Assert
        expect(queryStringsForTest).toEqual(queryStrings);
    });

    test("computed: dynamicStrings should be equal to import object", () => {
        // Arrange
        const mixIn = getMixInInstance({});

        // Act
        let dynamicStringsForTest = mixIn.computed.dynamicStrings();

        // Assert
        expect(dynamicStringsForTest).toEqual(dynamicStrings);
    });

    test("onInvalidSubmit: puts focus on first error", () => {
        // Arrange
        const mixIn = getMixInInstance({});
        const validationData = {
            errors: {
                fieldOne: "error message 1",
                fieldTwo: "error message 2",
            },
        };

        global.document.querySelector = jest.fn();

        // Act
        mixIn.methods.onInvalidSubmit(validationData);

        // Assert
        expect(global.document.querySelector).toBeCalledWith("[data-focus-target='fieldOne']");
    });

    test("getZipCodeData calls dispatch", () => {
        const mixIn = getMixInInstance({});
        mixIn.methods.dispatchStoreActionWithLogging = jest.fn();
        mixIn.methods.dispatchStoreActionWithLogging.mockReturnValue({
            data: { isValid: true, isServiceable: true, state: "OH" },
        });
        const type = "";
        const payload = { zip: 43015 };

        const mockData = {
            actionList: [
                {
                    actionName: storeActions.VALIDATE_ZIP,
                },
            ],
        };

        mixIn.methods.getZipCodeData(type, payload);

        expect(mixIn.methods.dispatchStoreActionWithLogging).toBeCalled();
    });
});

function getMixInInstance({ isDispatchSuccess = true }) {
    // Mock Store
    const storeDispatch = jest.fn();

    if (isDispatchSuccess) {
        storeDispatch.mockReturnValue(Promise.resolve());
    } else {
        storeDispatch.mockReturnValue(Promise.reject());
    }

    // Mock Route
    const route = {
        query: {
            fmgPage: "test-page",
        },
    };

    // Attach mocks to mixin
    const baseMixIn = baseMixin;
    baseMixIn.methods.$route = route;
    baseMixIn.methods.storeActions = storeActions;
    baseMixIn.methods.vehicleCategories = vehicleCategories;
    baseMixIn.methods.queryStrings = queryStrings;
    baseMixIn.methods.dynamicStrings = dynamicStrings;

    store.dispatch = storeDispatch;
    store.commit = jest.fn();

    return baseMixIn;
}
