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

import { testItemComponent } from '../../../tests/item';
import { Site } from '../../../tests/storyshare';
import { ItemRating } from './ItemRating';

describe('ItemRating component', () => {
  const ITEM_FIXTURE = {
    id: 42,
    rating: {
      average: 0.85,
      count: 20,
      own: 0.6,
    },
    type: 'type-slug',
  };

  const EMPTY_ITEM_FIXTURE = {
    id: 42,
    rating: {
      average: null,
      count: 0,
      own: null,
    },
    type: 'type-slug',
  };

  const onRate = jest.fn();

  let wrapper;

  beforeEach(() => {
    wrapper = shallow(
      <ItemRating
        item={ ITEM_FIXTURE }
        maxRating={ 5 }
        onRate={ onRate }
        site={ new Site() }
      />
    );
  });

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

  it('renders a Rating', () => {
    const rating = wrapper.find('Rating');
    expect(rating).toExist();
    expect(rating).toHaveProp('maxRating', 5);
    expect(rating).toHaveProp('rating', 3);
  });

  it('passes unknown prop through to the Rating', () => {
    wrapper.setProps({ unknown: 'value' });
    expect(wrapper.find('Rating')).toHaveProp('unknown', 'value');
  });

  it('avoids passing internal props through to the Rating', () => {
    const rating = wrapper.find('Rating');
    expect(rating).not.toHaveProp('item');
    expect(rating).not.toHaveProp('site');
  });

  it('copes if somebody has not rated the post', () => {
    wrapper.setProps({ item: EMPTY_ITEM_FIXTURE });
    const rating = wrapper.find('Rating');
    expect(rating).toExist();
    expect(rating).toHaveProp('rating', null);
  });

  it('copes if no rating data are available', () => {
    wrapper.setProps({ item: { id: 42, type: 'type-slug' } });
    expect(wrapper).toBeEmptyRender();
  });

  it('sends a request to StoryShare to rate a post', () => {
    const request = {
      addParam: jest.fn().mockReturnThis(),
      create: jest.fn(),
    };
    const site = { req: jest.fn().mockReturnValue(request) };
    wrapper.setProps({ site });

    wrapper.find('Rating').simulate('rate', null, { maxRating: 5, rating: 3 });

    expect(site.req).toHaveBeenCalled();
    expect(site.req).toHaveBeenCalledWith('type-slug/42/rating');
    expect(request.addParam).toHaveBeenCalled();
    expect(request.addParam).toHaveBeenCalledWith('rating', 0.6);
    expect(request.create).toHaveBeenCalled();
  });

  it('sends a request to StoryShare to delete a rating', () => {
    const request = { delete: jest.fn() };
    const site = { req: jest.fn().mockReturnValue(request) };
    wrapper.setProps({ site });

    wrapper.find('Rating').simulate('rate', null, { maxRating: 5, rating: 0 });

    expect(site.req).toHaveBeenCalled();
    expect(site.req).toHaveBeenCalledWith('type-slug/42/rating');
    expect(request.delete).toHaveBeenCalled();
  });

  it('propagates rating events to the parent', () => {
    const event = { };
    const rating = { };
    onRate.mockClear();

    wrapper.find('Rating').simulate('rate', event, rating);

    expect(onRate).toHaveBeenCalled();
    expect(onRate).toHaveBeenCalledWith(event, rating);
  });

  testItemComponent(ItemRating);
});
