import { render, screen, waitFor } from '@testing-library/react';
import user from '@testing-library/user-event';
import FormTestBase from './FormTestBase';
import { Form, StringInputGroup, ValidatedApiResult } from '../';
import { PersonDto } from '../__Tests__/FormTestBase';
import StandardFormActions from '../StandardFormActions';
import { validators } from '../';

const handleSubmitMock = jest.fn((value: PersonDto | FormData) => {
  //return value;
  return new Promise<ValidatedApiResult>((res, rej) => {
    setTimeout(() => {
      res({});
    }, 15);
  });
});

describe('Realistic Form', () => {
  it('Validates, resolves validation, submits values', async () => {
    global.scrollTo = jest.fn();
    const fullForm = (
      <FormTestBase handleSubmit={handleSubmitMock}>
        {({ Field }) => (
          <>
            <Field name="name" label="name" Component={StringInputGroup} />
            <Field
              name="nameWithIcon"
              label="Name with Icon"
              Component={StringInputGroup}
              validate={validators.required}
            />
            <StandardFormActions />
            <Form.DisplayFormState />
          </>
        )}
      </FormTestBase>
    );

    render(fullForm);
    const nameInput = screen.getByLabelText('name');
    const formSubmitButton = screen.getByRole('button', {
      name: 'Submit',
    });
    //The form should start off with the submit button disabled
    expect(formSubmitButton).toBeDisabled();

    //Enter a name into the name input
    user.click(nameInput);
    user.type(nameInput, 'Travis Overmier');
    expect(nameInput).toHaveValue('Travis Overmier');

    //Submit should be enabled, click submit
    expect(formSubmitButton).toBeEnabled();
    user.click(formSubmitButton);

    //Submit should disable while 'submitting' then re-enable
    expect(formSubmitButton).toBeDisabled();
    await waitFor(() => {
      expect(formSubmitButton).toBeEnabled();
    });

    //Validation message should appear
    const nameWithIconInput = screen.getByLabelText('Name with Icon');
    expect(nameWithIconInput).toHaveErrorMessage('Required');

    //Fill in field, error message goes away
    user.type(nameWithIconInput, 'Kyle Joiner');
    user.tab();
    await waitFor(() => {
      expect(nameWithIconInput).not.toHaveErrorMessage();
    });

    //Click the submit button
    user.click(formSubmitButton);
    await waitFor(() => {
      expect(handleSubmitMock).toHaveBeenCalled();
      expect(JSON.stringify(handleSubmitMock.mock.calls[0][0])).toBe(
        `{"name":"Travis Overmier","nameWithIcon":"Kyle Joiner"}`
      );
    });
  });
});
