huridocs/uwazi

View on GitHub
app/react/Metadata/components/specs/MetadataFormFields.spec.js

Summary

Maintainability
A
0 mins
Test Coverage
import React from 'react';
import { shallow } from 'enzyme';
import * as redux from 'redux';
import { fromJS } from 'immutable';
import { actions as formActions } from 'react-redux-form';

import { FormGroup } from 'app/Forms';
import MultipleEditionFieldWarning from '../MultipleEditionFieldWarning';
import { LookupMultiSelect, DatePicker } from '../../../ReactReduxForms';
import { MetadataFormFields, mapDispatchToProps } from '../MetadataFormFields';
import { AddThesauriValueButton } from '../AddThesauriValueButton';

describe('MetadataFormFields with one entity to edit ', () => {
  let component;
  let fieldsTemplate;
  let props;
  let metadata;

  beforeEach(() => {
    fieldsTemplate = [
      { _id: 1, name: 'field1', label: 'label1', type: 'text' },
      { _id: 2, name: 'field2', label: 'label2', type: 'relationship', content: '2' },
      { _id: 3, name: 'field3', label: 'label3', type: 'date' },
      { _id: 4, name: 'field4', label: 'label4', type: 'generatedid' },
      { _id: 5, name: 'field5', label: 'label5', type: 'relationship', content: '2' },
      { _id: 6, name: 'field6', label: 'label6', type: 'image' },
      { _id: 7, name: 'field7', label: 'label7', type: 'media' },
    ];

    metadata = [
      {
        value: {
          field1: 'field1value',
          field2: 'field2value',
        },
      },
    ];
  });

  const render = args => {
    props = {
      metadata: {
        _id: [{ value: 'docId' }],
        template: [{ value: 'templateId' }],
        title: [{ value: 'testTitle' }],
        metadata,
      },
      template: fromJS({
        name: 'template1',
        _id: 'templateId',
        properties: fieldsTemplate,
      }),
      fields: fromJS(fieldsTemplate),
      thesauris: fromJS([
        {
          _id: 2,
          name: 'thesauri',
          values: [
            {
              label: 'option1',
              id: '1',
            },
          ],
        },
      ]),
      dateFormat: '',
      model: 'metadata',
      storeKey: 'library',
      change: jest.fn(),
      push: () => {},
      saveThesaurus: () => {},
    };

    const componentProps = { ...props, ...args };
    // eslint-disable-next-line react/jsx-props-no-spreading
    component = shallow(<MetadataFormFields {...componentProps} />);
  };

  describe('default props', () => {
    it('should pass the field state to every fields and MultipleEditionFieldWarning', () => {
      render();
      const formGroups = component.find(FormGroup);
      expect(formGroups.at(0).props().model).toBe('.metadata.field1');
      expect(formGroups.at(1).props().model).toBe('.metadata.field2');
      expect(formGroups.at(2).props().model).toBe('.metadata.field3');

      const warnings = component.find(MultipleEditionFieldWarning);
      expect(warnings.at(0).props().model).toBe('metadata');
      expect(warnings.at(0).props().field).toBe('metadata.field1');
      expect(warnings.at(1).props().field).toBe('metadata.field2');
      expect(warnings.at(2).props().field).toBe('metadata.field3');
    });

    it('should render dynamic fields based on the template selected', () => {
      render();
      const inputField = component.find('[model=".metadata.field1"]').find('input');
      expect(inputField.length).toBe(1);

      const multiselect = component.find(LookupMultiSelect).at(0);
      expect(multiselect.props().options).toEqual(props.thesauris.toJS()[0].values);
      expect(multiselect.props().optionsValue).toEqual('id');

      const datepicker = component.find(DatePicker);
      expect(datepicker.length).toBe(1);
    });

    it('should render a generatedid property without a default value', () => {
      render();
      const generatedIdInput = component.find('[model=".metadata.field4"]').find('input');
      expect(generatedIdInput.length).toBe(1);
      expect(generatedIdInput.props().defaultValue).toBe(undefined);
    });

    it('should render media components properly', () => {
      render({ model: 'publicform' });
      const imageField = component.find('[model=".metadata.field6"]').at(0);
      const mediaField = component.find('[model=".metadata.field7"]').at(0);

      expect(imageField.props().className).toBe('image');
      expect(mediaField.props().className).toBe('media');
    });
  });

  it('should hide fields with type generatedId if model is publicform', () => {
    render({ model: 'publicform' });
    const generatedIdField = component.find('[model=".metadata.field4"]').at(0);
    expect(generatedIdField.props().className).toBe(' hidden ');
    const generatedIdInput = component.find('[model=".metadata.field4"]').find('input');
    expect(generatedIdInput.props().defaultValue.length).toBe(12);
  });

  it('updating one field should update the others with the same configuration', () => {
    render({ model: 'publicform' });
    const secondRelationshipField = component.find(LookupMultiSelect).at(1);

    secondRelationshipField.simulate('change', ['123', '456']);
    expect(props.change).toHaveBeenCalledWith('publicform.metadata.field2', ['123', '456']);
  });

  it('should render the add thesauri value when not on public form', () => {
    fieldsTemplate = [
      { _id: 1, name: 'text', label: 'Text', type: 'text' },
      { _id: 2, name: 'select', label: 'Select', type: 'select', content: '2' },
    ];
    metadata = [
      {
        value: {
          text: 'text 1',
          select: 'value 1',
        },
      },
    ];

    render();
    expect(component.find(AddThesauriValueButton).length).toBe(1);

    render({ model: 'publicform' });
    expect(component.find(AddThesauriValueButton).length).toBe(0);
  });

  describe('MapDispatchToProps', () => {
    beforeEach(() => {
      spyOn(redux, 'bindActionCreators');
    });

    it('should allow passing an already-bound change (for LocalForm implementations)', () => {
      const dispatch = {};
      const boundChange = () => {};
      mapDispatchToProps(dispatch, {});

      expect(redux.bindActionCreators).toHaveBeenCalledWith(
        expect.objectContaining({ change: formActions.change }),
        dispatch
      );

      redux.bindActionCreators.calls.reset();

      const mappedProps = mapDispatchToProps(dispatch, { boundChange });
      expect(redux.bindActionCreators).not.toHaveBeenCalled();
      expect(mappedProps.change).toBe(boundChange);
    });
  });
});