import { shallow } from 'enzyme';
import React from 'react';

import { Site } from '../../../tests/storyshare';
import { PasswordRequestForm } from './PasswordRequestForm';

describe('PasswordRequestForm component', () => {
  const onRequested = jest.fn();

  let wrapper;
  const validEmail = 'valid@email.com';

  const site = new Site();

  beforeEach(() => {
    onRequested.mockClear();
    wrapper = shallow(
      <PasswordRequestForm
        onRequested={ onRequested }
        site={ site }
      />
    );
  });

  const emailInput = () => wrapper.find('FormInput');
  const typeEmail = (email) => {
    const value = { name: 'email', value: email };
    emailInput().simulate('change', { target: value });
  };

  const submitForm = () => wrapper.find('Form').simulate('submit');

  const submitValidform = () => {
    typeEmail(validEmail);
    submitForm();
  };

  it('has an email type input with placeholder', () => {
    expect(emailInput()).toHaveProp('placeholder', 'Enter your email address');
    expect(emailInput()).toHaveProp('type', 'email');
  });

  it('displays an error message if invalid/blank email submitted', () => {
    typeEmail('');
    submitForm();
    expect(wrapper.find('Message'))
      .toHaveProp('content', 'An email address must be entered');
  });

  it('calls the correct api endpoint', () => {
    const request = {
      setParams: jest.fn().mockReturnThis(),
      promise: jest.fn().mockReturnThis(),
      create: jest.fn(),
    };
    jest.spyOn(site, 'req').mockReturnValueOnce(request);

    submitValidform();
    expect(site.req)
      .toHaveBeenCalledWith('identityprovider/email/resetrequest');
  });

  it('sends the right params to api', () => {
    const request = {
      setParams: jest.fn().mockReturnThis(),
      promise: jest.fn().mockReturnThis(),
      create: jest.fn(),
    };

    site.req.mockReturnValueOnce(request);
    submitValidform();

    expect(request.setParams)
      .toHaveBeenCalledWith({
        return_to: window.location.href,
        email: validEmail,
      });
  });

  it('displays error if something goes wrong registering', () => {
    site.req.mockImplementation(() => { throw new Error(); });
    submitValidform();
    expect(wrapper.find('Message'))
    // eslint-disable-next-line max-len
      .toHaveProp('content', 'An error occurred when trying to reset your password, please try again');
  });

  it('emits the onRequested event if a handler supplied', async () => {
    const request = {
      setParams: jest.fn().mockReturnThis(),
      create: jest.fn().mockResolvedValue({ token: '' }),
      promise: jest.fn().mockReturnThis(),
    };
    site.req.mockReturnValueOnce(request);
    typeEmail('valid@email.com');
    // This instance method is called directly as it runs asynchronously

    await wrapper.instance().handleSubmit();
    expect(onRequested).toHaveBeenCalled();
  });

  it('renders PasswordResetPending after successful request', async () => {
    const request = {
      setParams: jest.fn().mockReturnThis(),
      create: jest.fn().mockResolvedValue({ token: '' }),
      promise: jest.fn().mockReturnThis(),
    };

    site.req.mockReturnValueOnce(request);

    expect(wrapper.find('PasswordResetPending')).not.toExist();
    typeEmail('valid@email.com');
    // This instance method is called directly as it runs asynchronously

    await wrapper.instance().handleSubmit();
    wrapper.update();
    expect(wrapper.find('PasswordResetPending')).toExist();
  });
});
