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

import { testItemComponent } from '../../../tests/item';
import { ItemField } from './ItemField';

describe('ItemField component', () => {
  const ITEM_FIXTURE = {
    custom: 'field',
    deeper: { path: 'value' },
  };

  let wrapper;

  beforeEach(() => {
    wrapper = shallow(
      <ItemField
        field="custom"
        item={ ITEM_FIXTURE }
      />
    );
  });

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

  it('renders the field value', () => {
    expect(wrapper.text()).toBe('field');
  });

  it('suppresses rendering when the field is missing', () => {
    wrapper.setProps({ item: { } });
    expect(wrapper).toBeEmptyRender();
  });

  it('can render a value from deeper in the tree', () => {
    wrapper.setProps({ field: 'deeper.path' });
    expect(wrapper.text()).toBe('value');
  });

  it('suppresses rendering when a deeper value is missing', () => {
    wrapper.setProps({ field: 'deeper.path', item: { } });
    expect(wrapper).toBeEmptyRender();
  });

  it('can render with a render prop', () => {
    const children = jest.fn().mockReturnValue('rendered');
    wrapper.setProps({ children });

    expect(children).toHaveBeenCalled();
    expect(children).toHaveBeenCalledWith('field');
    expect(wrapper.text()).toBe('rendered');
  });

  it('suppresses render prop rendering when the field is missing', () => {
    const children = jest.fn().mockReturnValue('rendered');
    wrapper.setProps({ children, item: { } });

    expect(children).not.toHaveBeenCalled();
    expect(wrapper).toBeEmptyRender();
  });

  it('can render as a string component', () => {
    wrapper.setProps({ as: 'a' });
    const anchor = wrapper.find('a');
    expect(anchor).toExist();
    expect(anchor.text()).toBe('field');
  });

  it('can render as a functional component', () => {
    wrapper.setProps({ as: Label });
    const label = wrapper.find('Label');
    expect(label).toExist();
    expect(label.children()).toHaveText('field');
  });

  it('suppresses component rendering when the field is missing', () => {
    wrapper.setProps({ as: 'a', item: { } });
    expect(wrapper).toBeEmptyRender();
  });

  it('passes unknown props through to the component', () => {
    wrapper.setProps({ as: Label, unknown: 'value' });
    expect(wrapper.find('Label')).toHaveProp('unknown', 'value');
  });

  it('avoids passing internal props through to the component', () => {
    wrapper.setProps({ as: Label });
    expect(wrapper.find('Label')).not.toHaveProp('item');
  });

  testItemComponent(ItemField);
});
