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

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

describe('PasswordResponseForm component', () => {
  const onPasswordReset = jest.fn();
  const site = new Site();

  let wrapper;
  const request = {
    setParams: jest.fn().mockReturnThis(),
    create: jest.fn().mockResolvedValue({ search: 'someToken123' }),
    promise: jest.fn().mockReturnThis(),
  };
  const token = 'someToken123';
  const avalidPasswordEvent = {
    target: {
      name: 'password',
      value: '123DDDmmmnm',
    },
  };
  site.login = jest.fn().mockReturnValue({ });

  beforeEach(() => {
    onPasswordReset.mockClear();
    site.login.mockClear();
    wrapper = shallow(
      <PasswordResponseForm
        token={ token }
        onPasswordReset={ onPasswordReset }
        site={ site }
      />
    );
  });

  const submitValidForm = () => {
    wrapper.find('FormInput').simulate('change', avalidPasswordEvent);
    wrapper.find('PasswordStrength').simulate('validate', true);
    wrapper.find('Form').simulate('submit');
  };

  it('renders a field for the password', () => {
    const input = wrapper.find('FormInput');
    expect(input).toExist();
    expect(input).toHaveProp('placeholder', 'Enter a new password');
    expect(input).toHaveProp('type', 'password');
  });

  it('renders a PasswordStrength with password', () => {
    const currPass = 'bu==rr';
    wrapper.setState({ password: currPass });
    expect(wrapper.find('PasswordStrength').props().password)
      .toBe(currPass);
  });

  it('renders an error message if something goes wrong', () => {
    expect(wrapper.find('Message')).toExist();
    wrapper.setState({ error: 'some error' });
    expect(wrapper.find('Message')).toHaveProp('children', 'some error');
  });

  it('renders a submit button', () => {
    const button = wrapper.find('FormButton');
    expect(button).toExist();
    expect(button).toHaveProp('type', 'submit');
  });

  it('disables the button when the password is not valid', () => {
    wrapper.find('PasswordStrength').simulate('validate', false);
    expect(wrapper.find('FormButton')).toHaveProp('disabled', true);
  });

  it('enables the button for a correct password', () => {
    wrapper.find('PasswordStrength').simulate('validate', true);
    expect(wrapper.find('FormButton')).toHaveProp('disabled', false);
  });

  it('calls the right endpoint for submission', () => {
    jest.spyOn(site, 'req').mockReturnValue(request);

    wrapper.find('Form').simulate('submit');
    expect(site.req)
      .toHaveBeenCalledWith('identityprovider/email/resetresponse');
  });

  it('calls api with the right params', () => {
    site.req.mockReturnValue(request);
    submitValidForm();

    expect(site.req().setParams)
      .toHaveBeenCalledWith({
        password: avalidPasswordEvent.target.value,
        token: 'someToken123',
      });
  });

  it('logs you in after submit', async () => {
    site.req.mockReturnValue(request);
    submitValidForm();
    // This instance method is called directly as it runs asynchronously
    await wrapper.instance().handleSubmit();
    expect(site.login).toHaveBeenCalledWith({ jwt: 'someToken123' });
  });

  it('emits event onPasswordReset when finished', async () => {
    site.req.mockReturnValue(request);
    submitValidForm();
    // This instance method is called directly as it runs asynchronously
    await wrapper.instance().handleSubmit();
    expect(onPasswordReset).toHaveBeenCalled();
  });

  it('shows error message if something goes wrong', () => {
    site.req.mockImplementation(() => { throw new Error('Some error'); });
    submitValidForm();
    expect(site.req).toHaveBeenCalled();
    expect(site.login).not.toHaveBeenCalled();
    expect(onPasswordReset).not.toHaveBeenCalled();
    expect(wrapper.find('Message'))
    // eslint-disable-next-line max-len
      .toHaveProp('children', 'An error occurred when trying to reset your password, please try again');
  });
});
