import { shallow } from 'enzyme';
import React from 'react';
import { Button } from 'semantic-ui-react';

import createButtonComponent from './createButtonComponent';

describe('createButtonComponent function', () => {
  const STATE_FIXTURE = {
    isFormValid: jest.fn(),
  };

  const Context = React.createContext();

  let Component;

  let wrapper;

  beforeEach(() => {
    Component = createButtonComponent('DisplayName', Context);
    wrapper = shallow(<Component />);
  });

  const getButton = () => {
    const children = wrapper.find(Context.Consumer).prop('children');
    return shallow(<div>{ children(STATE_FIXTURE) }</div>).find('Button');
  };

  it('renders', () => {
    expect(wrapper).toExist();
  });

  it('renders a Consumer to retrieve the context', () => {
    expect(wrapper.find(Context.Consumer)).toExist();
  });

  it('renders a Button', () => {
    expect(getButton()).toExist();
  });

  it('passes props down to the Button', () => {
    wrapper.setProps({
      children: 'Sign in!',
      size: 'small',
    });

    expect(getButton().children()).toHaveText('Sign in!');
    expect(getButton()).toHaveProp('size', 'small');
  });

  it('copies propTypes from the Button', () => {
    // Check a representative prop
    expect(Component.propTypes.size).toBe(Button.propTypes.size);
  });

  it('does not define a type prop', () => {
    expect(Component.propTypes).not.toHaveProperty('type');
  });

  it('disables the button if the form is not complete', () => {
    STATE_FIXTURE.isFormValid.mockReturnValue(false);
    expect(getButton()).toHaveProp('disabled', true);
  });

  it('enables the button if the form is complete', () => {
    STATE_FIXTURE.isFormValid.mockReturnValue(true);
    expect(getButton()).toHaveProp('disabled', false);
  });

  it('disables the button if requested to by a prop', () => {
    STATE_FIXTURE.isFormValid.mockReturnValue(true);
    wrapper.setProps({ disabled: true });
    expect(getButton()).toHaveProp('disabled', true);
  });

  it('sets the button type to "submit"', () => {
    expect(getButton()).toHaveProp('type', 'submit');
  });

  it('ignores attempts to set the button to another type', () => {
    wrapper.setProps({ type: 'other' });
    expect(getButton()).toHaveProp('type', 'submit');
  });

  it('sets the component display name', () => {
    expect(Component.displayName).toBe('DisplayName');
  });
});
