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

import Collection from '.';
import { CollectionRadios } from './CollectionRadios';

describe('CollectionRadios component', () => {
  let wrapper;

  const onChange = jest.fn();

  beforeEach(() => {
    wrapper = shallow(
      <CollectionRadios typeSlug="type-slug" onChange={ onChange } />
    );
  });

  const triggerUpdate = () =>
    wrapper.find(Collection).simulate('update', { total: 42 });

  const getRadio = (item) => {
    triggerUpdate();
    const render = wrapper.find(Collection).prop('children');
    return shallow(<div>{ render(item) }</div>).find('FormRadio');
  };

  const triggerChange = (item) =>
    getRadio(item).simulate('change', { event: {} }, {}, item);

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

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

  it('passes props through to the Collection', () => {
    const collection = wrapper.find(Collection);
    expect(collection).toHaveProp('params', { per_page: 100 });
    expect(collection).toHaveProp('typeSlug', 'type-slug');
  });

  it('passes extra request params to the Collection', () => {
    wrapper.setProps({ params: { test: 'param' } });
    expect(wrapper.find(Collection))
      .toHaveProp('params', { per_page: 100, test: 'param' });
  });

  it('starts out rendering a placeholder', () => {
    expect(wrapper.find('Loader')).toExist();
  });

  it('allows the placeholder to be customised', () => {
    const placeholder = <div>Loading ...</div>;
    wrapper.setProps({ placeholder });
    expect(wrapper.find('Loader')).not.toExist();
    expect(wrapper).toContainReact(placeholder);
  });

  it('removes the placeholder when data loads', () => {
    triggerUpdate();
    expect(wrapper.find('Loader')).not.toExist();
  });

  it('converts a post to a radio button', () => {
    const item = getRadio({ id: 42, title: { rendered: 'Title' } });
    expect(item).toExist();
    expect(item).toHaveProp('checked', false);
    expect(item).toHaveProp('label', 'Title');
    expect(item).toHaveProp('value', 42);
  });

  it('converts a term to a radio button', () => {
    const item = getRadio({ id: 42, name: 'Name' });
    expect(item).toExist();
    expect(item).toHaveProp('checked', false);
    expect(item).toHaveProp('label', 'Name');
    expect(item).toHaveProp('value', 42);
  });

  it('passes unknown props to the radio buttons', () => {
    wrapper.setProps({ unknown: 'prop' });
    const item = getRadio({ id: 42 });
    expect(item).toHaveProp('unknown', 'prop');
  });

  it('can check the selected radio button', () => {
    wrapper.setProps({ value: 42 });
    expect(getRadio({ id: 42 })).toHaveProp('checked', true);
    expect(getRadio({ id: 43 })).toHaveProp('checked', false);
  });

  it('can filter radio buttons', () => {
    const filterPredicate = () => false;
    wrapper.setProps({ filterPredicate });
    const item = getRadio({ id: 42 });
    expect(item).not.toExist();
  });

  it('calls onChange in response to a change', () => {
    onChange.mockClear();
    triggerChange({ id: 23, name: 'Test' });

    expect(onChange).toHaveBeenCalled();
  });

  it('passes the event through to onChange', () => {
    onChange.mockClear();
    triggerChange({ id: 23, name: 'Test' });

    expect(onChange.mock.calls[0][0]).toEqual({ event: {} });
  });

  it('copes if no onChange is provided', () => {
    wrapper.setProps({ onChange: undefined });
    triggerChange({ id: 23, name: 'Test' });
    // Test succeeds if no errors
  });

  it('passes the item to onChange', () => {
    onChange.mockClear();
    triggerChange({ id: 23, name: 'Test' });

    expect(onChange.mock.calls[0][2]).toEqual({ id: 23, name: 'Test' });
  });
});
