import { shallow } from 'enzyme';
import { propEq } from 'ramda';
import React from 'react';
import { Placeholder } from 'semantic-ui-react';

import { ItemRadios, mapStateToProps } from './ItemRadios';
import { Site } from '../../../tests/storyshare';

/* eslint-disable no-console */

describe('mapStateToProps', () => {
  const site = {
    getCollectionByRoute: jest.fn().mockReturnValue('test items'),
  };

  beforeEach(() => {
    site.getCollectionByRoute.mockClear();
  });

  it('retrieves items from the DataLayer cache', () => {
    mapStateToProps(null, { site, typeSlug: 'test-slug' });
    expect(site.getCollectionByRoute).toHaveBeenCalled();
    expect(site.getCollectionByRoute)
      .toHaveBeenCalledWith('test-slug', { per_page: 100 });
  });

  it('can pass additional parameters to the DataLayer', () => {
    const requestParams = { extra: 'param' };
    mapStateToProps(null, { requestParams, site, typeSlug: 'test-slug' });
    expect(site.getCollectionByRoute)
      .toHaveBeenCalledWith('test-slug', { extra: 'param', per_page: 100 });
  });

  it('passes retrieved items to the component', () => {
    expect(mapStateToProps(null, { site }).items).toBe('test items');
  });
});

describe('ItemRadios component', () => {
  const POSTS_FIXTURE = [
    { id: 2827, title: { rendered: 'Corporate' } },
    { id: 2828, title: { rendered: 'Employment' } },
    { id: 2829, title: { rendered: 'Finance' } },
  ];

  const TERMS_FIXTURE = [
    { id: 2827, name: 'Corporate' },
    { id: 2828, name: 'Employment' },
    { id: 2829, name: 'Finance' },
  ];

  let wrapper;

  beforeAll(() => {
    jest.spyOn(console, 'warn').mockReturnValue();
  });

  beforeEach(() => {
    wrapper = shallow(
      <ItemRadios
        items={ POSTS_FIXTURE }
        site={ new Site() }
        typeSlug="test-slug"
      />
    );
  });

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

  it('renders SUI radio buttons', () => {
    const radios = wrapper.find('FormRadio');
    expect(radios).toExist();
    expect(radios.length).toBe(3);
  });

  it('sets up the buttons correctly', () => {
    const radios = wrapper.find('FormRadio');
    expect(radios.at(0)).toHaveProp('label', 'Corporate');
    expect(radios.at(1)).toHaveProp('label', 'Employment');
    expect(radios.at(2)).toHaveProp('label', 'Finance');
    expect(radios.at(0)).toHaveProp('value', 2827);
    expect(radios.at(1)).toHaveProp('value', 2828);
    expect(radios.at(2)).toHaveProp('value', 2829);
  });

  it('starts with no buttons selected', () => {
    const radios = wrapper.find('FormRadio');
    expect(radios.at(0)).toHaveProp('checked', false);
    expect(radios.at(1)).toHaveProp('checked', false);
    expect(radios.at(2)).toHaveProp('checked', false);
  });

  it('can select a button', () => {
    let radios;

    wrapper.setProps({ value: 2827 });
    radios = wrapper.find('FormRadio');
    expect(radios.at(0)).toHaveProp('checked', true);
    expect(radios.at(1)).toHaveProp('checked', false);
    expect(radios.at(2)).toHaveProp('checked', false);

    wrapper.setProps({ value: 2828 });
    radios = wrapper.find('FormRadio');
    expect(radios.at(0)).toHaveProp('checked', false);
    expect(radios.at(1)).toHaveProp('checked', true);
    expect(radios.at(2)).toHaveProp('checked', false);

    wrapper.setProps({ value: 2829 });
    radios = wrapper.find('FormRadio');
    expect(radios.at(0)).toHaveProp('checked', false);
    expect(radios.at(1)).toHaveProp('checked', false);
    expect(radios.at(2)).toHaveProp('checked', true);
  });

  it('can render terms as well as posts', () => {
    wrapper.setProps({ items: TERMS_FIXTURE });
    const radios = wrapper.find('FormRadio');
    expect(radios.at(0)).toHaveProp('label', 'Corporate');
    expect(radios.at(1)).toHaveProp('label', 'Employment');
    expect(radios.at(2)).toHaveProp('label', 'Finance');
    expect(radios.at(0)).toHaveProp('value', 2827);
    expect(radios.at(1)).toHaveProp('value', 2828);
    expect(radios.at(2)).toHaveProp('value', 2829);
  });

  it('can filter items', () => {
    wrapper.setProps({ filterPredicate: propEq('id', 2828) });
    const radio = wrapper.find('FormRadio');
    expect(radio.length).toBe(1);
    expect(radio).toHaveProp('value', 2828);
  });

  it('passes unknown props through to the buttons', () => {
    wrapper.setProps({ unknown: 'value' });
    const radios = wrapper.find('FormRadio');
    expect(radios.at(0)).toHaveProp('unknown', 'value');
    expect(radios.at(1)).toHaveProp('unknown', 'value');
    expect(radios.at(2)).toHaveProp('unknown', 'value');
  });

  it('avoids passing react-redux dispatch to the buttons', () => {
    wrapper.setProps({ dispatch: () => null });
    const radios = wrapper.find('FormRadio');
    expect(radios.at(0)).not.toHaveProp('dispatch');
    expect(radios.at(1)).not.toHaveProp('dispatch');
    expect(radios.at(2)).not.toHaveProp('dispatch');
  });

  it('renders a Loader if items have not yet loaded', () => {
    wrapper.setProps({ items: undefined });
    expect(wrapper.find('FormRadio')).not.toExist();
    const loader = wrapper.find('Loader');
    expect(loader).toExist();
    expect(loader).toHaveProp('active');
    expect(loader).toHaveProp('inline');
  });

  it('renders a Loader if no items are defined', () => {
    wrapper.setProps({ items: [] });
    expect(wrapper.find('FormRadio')).not.toExist();
    const loader = wrapper.find('Loader');
    expect(loader).toExist();
    expect(loader).toHaveProp('active');
    expect(loader).toHaveProp('inline');
  });

  it('allows the placeholder to be customised', () => {
    wrapper.setProps({ items: undefined, placeholder: <Placeholder /> });
    expect(wrapper.find('Loader')).not.toExist();
    expect(wrapper.find('Placeholder')).toExist();
  });

  it('displays a deprecation warning', () => {
    console.warn.mockClear();
    shallow(<ItemRadios site={ new Site() } typeSlug="test-slug" />);
    expect(console.warn).toHaveBeenCalled();
  });
});
