import React, { ComponentProps } from 'react';
import { shallow, mount } from 'enzyme';
import { wait } from 'lib/wait';
import { act } from 'react-dom/test-utils';
import { ArtistProfilesList } from '../artistProfilesList';

type Props = ComponentProps<typeof ArtistProfilesList>;

describe('<ArtistProfilesList>', () => {
    const profiles = [
        { id: 1, name: 'name1' },
        { id: 2, name: 'name2' },
    ];
    const getDefaultProps = (): Props => ({
        id: 'test',
        store: 1,
        titleContent: 'Title',
        emptyProfileContent: 'No items on page',
        profiles,
        isVisible: true,
        onChange: jest.fn(),
        onValidate: jest.fn(),
    });

    const render = (props: Props) => shallow(<ArtistProfilesList {...props} />);
    const mountComponent = async (props: Props) => {
        let component = mount(<ArtistProfilesList {...props} />);

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

        return component;
    };

    it('renders the expected markup', () => {
        const component = render(getDefaultProps());
        expect(component).toMatchSnapshot();
    });

    it('does not render empty profile if content not defined', () => {
        const testProps = {
            ...getDefaultProps(),
            emptyProfileContent: undefined,
        };
        const component = render(testProps);
        expect(component.find('#test-empty').exists()).toBeFalsy();
    });

    it('does not render title if not defined', () => {
        const testProps = { ...getDefaultProps(), titleContent: undefined };
        const component = render(testProps);
        expect(component.find('.ArtistProfilesList-title').exists()).toBeFalsy();
    });

    it('calls validation on init if defined and tab is visible', async () => {
        const testProps = getDefaultProps();
        await mountComponent(testProps);
        expect(testProps.onValidate).toHaveBeenCalledTimes(1);
    });

    it('does not call validation if tab hidden', async () => {
        const testProps = { ...getDefaultProps(), isVisible: false };
        await mountComponent(testProps);
        expect(testProps.onValidate).toHaveBeenCalledTimes(0);
    });

    it('calls onChange if any item selected', async () => {
        const testProps = getDefaultProps();
        const component = await mountComponent(testProps);
        act(() => {
            const onChange = component.find('ArtistProfileCheckable#test-name2').prop('onChange');
            onChange?.({} as React.FormEvent);
            expect(testProps.onChange).toHaveBeenCalledWith({
                id: 'test',
                profile: profiles[1],
            });
        });
    });

    it('changes value without exception if onChange handler not specified', async () => {
        const testProps = { ...getDefaultProps(), onChange: undefined };
        const component = await mountComponent(testProps);
        const onChange = component.find('ArtistProfileCheckable#test-name1').prop('onChange');
        let noErrors = true;
        act(() => {
            try {
                onChange?.({} as React.FormEvent);
            } catch {
                noErrors = false;
            }
        });
        expect(noErrors).toBeTruthy();
    });
});
