/* eslint-disable @typescript-eslint/no-explicit-any */

import React from 'react';
import { render } from '@testing-library/react';
import ConfirmLeavePrompt from '../confirm-leave-prompt';

describe('<ConfirmLeavePrompt>', () => {
    let addEventListenerMock: jest.SpyInstance;
    let removeEventListenerMock: jest.SpyInstance;

    beforeEach(() => {
        addEventListenerMock = jest.spyOn(window, 'addEventListener');
        removeEventListenerMock = jest.spyOn(window, 'removeEventListener');
    });

    afterEach(() => {
        addEventListenerMock.mockRestore();
        removeEventListenerMock.mockRestore();
    });

    test('when show is true', () => {
        const { container, unmount } = render(<ConfirmLeavePrompt show={ true } />);

        // Renders nothing
        expect(container).toBeEmptyDOMElement();

        // Registers a single 'beforeunload' event listener
        const beforeUnloadCalls = addEventListenerMock.mock.calls.filter(([type]) => type === 'beforeunload');
        expect(beforeUnloadCalls).toHaveLength(1);

        const [[, beforeUnloadListener]] = beforeUnloadCalls;

        const event: any = {};

        const result = beforeUnloadListener(event);

        // Returns message from listener
        expect(result).toBe('messages.changesNotSaved');

        // Adds message to event
        expect(event.returnValue).toBe('messages.changesNotSaved');

        unmount();

        // Removes event listener
        expect(removeEventListenerMock).toHaveBeenCalledWith('beforeunload', beforeUnloadListener);
    });

    test('when show is false', () => {
        const { container, unmount } = render(<ConfirmLeavePrompt show={ false } />);

        // Renders nothing
        expect(container).toBeEmptyDOMElement();

        // Registers a single 'beforeunload' event listener
        const beforeUnloadCalls = addEventListenerMock.mock.calls.filter(([type]) => type === 'beforeunload');
        expect(beforeUnloadCalls).toHaveLength(1);

        const [[, beforeUnloadListener]] = beforeUnloadCalls;

        const event: any = {};

        const result = beforeUnloadListener(event);

        // Doesn't return message from listener
        expect(result).toBeUndefined();

        // Doesn't add message to event
        expect(event.returnValue).toBeUndefined();

        unmount();

        // Removes event listener
        expect(removeEventListenerMock).toHaveBeenCalledWith('beforeunload', beforeUnloadListener);
    });
});
