import React from 'react';
import { shallow, mount } from 'enzyme';
import { act } from 'react-dom/test-utils';
import { wait } from '../../../../lib/wait';
import * as promiseUtil from '../../../utils/cancelablePromise';
import { pagesContext } from '../__fixtures__/search';
import AddNewArtist, { Props } from '../addNewArtist';

describe('<AddNewArtist>', () => {
    const artistName = 'Bon Jovi';
    const getProps = () => ({
        artist: artistName,
        onClose: jest.fn(),
        onDone: jest.fn(),
        onFetch: jest.fn().mockResolvedValue(pagesContext),
        isCreate: true,
    });
    const renderComponent = (props?: Partial<Props>) =>
        shallow(<AddNewArtist {...getProps()} {...props} />);
    const mountComponent = async (props?: Partial<Props>) => {
        let component = mount(<AddNewArtist {...getProps()} {...props} />);

        // eslint-disable-next-line testing-library/no-unnecessary-act
        await act(async () => {
            await wait();
            component = component.update();
        });

        return component;
    };

    afterEach(() => {
        jest.restoreAllMocks();
    });

    it('renders the initial markup for create mode', () => {
        expect(renderComponent()).toMatchSnapshot();
    });

    it('renders the initial markup for update mode', () => {
        expect(renderComponent({ isCreate: false })).toMatchSnapshot();
    });

    it('renders the component with data', async () => {
        const component = await mountComponent();
        component.update();
        expect(component.find('.ArtistProfilesPagination-content').exists()).toBeTruthy();
    });

    it('cancels fetch on unmount', async () => {
        const testCancelable = {
            promise: Promise.resolve([]),
            cancel: jest.fn(),
        };
        jest.spyOn(promiseUtil, 'makeCancelable').mockReturnValueOnce(testCancelable);
        const component = await mountComponent();
        act(() => {
            component.unmount();
        });
        expect(testCancelable.cancel).toHaveBeenCalled();
    });

    it('skips cancel fetch on unmount in fetch not defined', async () => {
        const testCancelable = {
            promise: Promise.resolve([]),
            cancel: jest.fn(),
        };
        jest.spyOn(promiseUtil, 'makeCancelable').mockReturnValueOnce(testCancelable);
        const component = await mountComponent({ onFetch: undefined });
        act(() => {
            component.unmount();
        });
        expect(testCancelable.cancel).toHaveBeenCalledTimes(0);
    });

    it('renders default component if onFetch no specified', async () => {
        const component = await mountComponent({ onFetch: undefined });
        expect(component.find('#tab_286').exists()).toBeFalsy();
        expect(component.find('#tab_1').exists()).toBeFalsy();
    });

    it('renders the expected tab title', async () => {
        const component = await mountComponent();
        component.update();
        const paginationContent = component.find('ArtistProfilesPagination');
        expect(paginationContent.find('#tab_286').prop('titleContent')).toMatchSnapshot();
    });

    it.skip('sets correct validation context', async () => {
        const testValidationContext = { data: 'test validation context' };
        const component = await mountComponent();

        // eslint-disable-next-line testing-library/no-unnecessary-act
        await act(async () => {
            const paginationContent = component.find('ArtistProfilesPagination');
            const validationHandler = paginationContent.find('#tab_286').prop('onValidate');

            if (typeof validationHandler === 'function') validationHandler(testValidationContext);
            await wait();
            expect(paginationContent.state('validationContext')).toEqual({
                0: testValidationContext,
            });
        });
    });
});
