huridocs/uwazi

View on GitHub
app/react/Metadata/components/specs/MediaModal.spec.tsx

Summary

Maintainability
C
1 day
Test Coverage
/**
 * @jest-environment jsdom
 */
import { ReactWrapper } from 'enzyme';
import ReactModal from 'react-modal';
import ReactPlayer from 'react-player';
import { actions as formActions } from 'react-redux-form';
import { renderConnectedMount } from 'app/utils/test/renderConnected';
import { RenderAttachment } from 'app/Attachments/components/RenderAttachment';
import { WebMediaResourceForm } from 'app/Attachments/components/WebMediaResourceForm';
import * as supportingFileActions from 'app/Metadata/actions/supportingFilesActions';
import { MediaModal, MediaModalProps, MediaModalType } from '../MediaModal';

const store = {
  library: {
    sidepanel: {
      metadata: {
        _id: '1',
        sharedId: 'entity1',
        attachments: [],
        metadata: { image: '' },
      },
    },
  },
};

describe('Media Modal', () => {
  let component: ReactWrapper;
  let props: MediaModalProps;

  beforeEach(() => {
    spyOn(formActions, 'change').and.returnValue({ type: 'rrf/change' });
    spyOn(supportingFileActions, 'uploadLocalAttachment').and.returnValue({
      type: 'ATTACHMENT_PROGRESSe',
    });
    props = {
      onClose: jasmine.createSpy('onClose'),
      onChange: jasmine.createSpy('onChange'),
      isOpen: true,
      attachments: [],
      formModel: 'library.sidepanel.metadata',
      formField: 'library.sidepanel.metadata.metadata.image',
      type: MediaModalType.Image,
      multipleEdition: false,
    };
  });

  const render = (otherProps = {}) => {
    component = renderConnectedMount(MediaModal, store, { ...props, ...otherProps }, true);
  };

  it('Should pass isOpen props to Media modal.', () => {
    render({ isOpen: false });
    expect(component.find(ReactModal).props().isOpen).toBe(false);
    render({ isOpen: true });
    expect(component.find(ReactModal).props().isOpen).toBe(true);
  });

  it('Should call onClose', () => {
    render();

    const closeButton = component.find('.attachments-modal__close');
    closeButton.simulate('click');

    expect(props.onClose).toHaveBeenCalled();
  });

  it('Should select attachment with filename', () => {
    const jpgAttachment = { _id: 123, filename: 'test.jpg', size: 1234, mimetype: 'image/jpg' };
    render({ attachments: [jpgAttachment] });

    const firstAttachment = component.find('.media-grid-item');
    firstAttachment.simulate('click');

    expect(props.onChange).toHaveBeenCalledWith('/api/files/test.jpg');
    expect(props.onClose).toHaveBeenCalled();
  });

  it('Should select attachment with url', () => {
    const testUrl = 'http://test.test/test.jpg';
    const jpgAttachment = { _id: 123, url: testUrl, size: 1234 };
    render({ attachments: [jpgAttachment] });

    const firstAttachment = component.find('.media-grid-item');
    firstAttachment.simulate('click');

    expect(props.onChange).toHaveBeenCalledWith(testUrl);
    expect(props.onClose).toHaveBeenCalled();
  });

  it('Should select a video attachment with url', () => {
    const testUrl = 'www.externalresource.com/video';
    jest.spyOn(ReactPlayer, 'canPlay').mockReturnValue(true);
    const videoAttachment = { _id: 123, url: testUrl, name: 'short video' };
    render({ attachments: [videoAttachment], type: MediaModalType.Media });

    const firstAttachment = component.find('.media-grid-item');
    firstAttachment.simulate('click');

    expect(props.onChange).toHaveBeenCalledWith(testUrl);
    expect(props.onClose).toHaveBeenCalled();
  });

  it('Should show only images', () => {
    const videoAttachment = { _id: 123, filename: 'video.mp4', size: 1234, mimetype: 'video/mp4' };
    const jpgAttachment = { _id: 456, filename: 'test.jpg', size: 1234, mimetype: 'image/jpg' };

    render({ attachments: [jpgAttachment, videoAttachment], type: MediaModalType.Image });

    const attachments = component.find(RenderAttachment);
    expect(attachments.at(0).props().attachment).toEqual(jpgAttachment);

    expect(attachments.length).toBe(1);
  });

  it('Should show only media', () => {
    const videoAttachment = { _id: 123, filename: 'video.mp4', size: 1234, mimetype: 'video/mp4' };
    const jpgAttachment = { _id: 456, filename: 'test.jpg', size: 1234, mimetype: 'image/jpg' };

    render({ attachments: [jpgAttachment, videoAttachment], type: MediaModalType.Media });

    const attachments = component.find(RenderAttachment);
    expect(attachments.at(0).props().attachment).toEqual(videoAttachment);

    expect(attachments.length).toBe(1);
  });

  it('Should show empty message', () => {
    render();

    const msg = component.find('.empty-attachments-message');

    expect(msg.length).toBe(1);
  });

  it('Should have selected attachment', () => {
    const jpgAttachment = { _id: 456, filename: 'test.jpg', size: 1234, mimetype: 'image/jpg' };

    render({ attachments: [jpgAttachment], selectedUrl: '/api/files/test.jpg' });

    const selectedAttachment = component.find('.media-grid .active');

    expect(selectedAttachment.length).toBe(1);
  });

  describe('Upload file', () => {
    it('Should upload file from url', () => {
      render();

      const testAttachment = 'http://test.test/test.jpg';
      const form = component.find(WebMediaResourceForm).at(0);
      const formData = { url: testAttachment };
      form.props().handleSubmit(formData);
      expect(props.onChange).toHaveBeenCalledWith(testAttachment);
      expect(props.onClose).toHaveBeenCalled();
    });

    it('Should upload and select a new file', () => {
      const newFile = new File([Buffer.from('image').toString('base64')], 'image.jpg', {
        type: 'image/jpg',
      });
      render();
      component.find('input[type="file"]').simulate('change', {
        target: {
          files: [newFile],
        },
      });
      expect(supportingFileActions.uploadLocalAttachment).toHaveBeenCalledWith(
        'entity1',
        newFile,
        {
          __reducerKey: 'library',
          model: 'library.sidepanel.metadata',
        },
        expect.stringMatching(/^[a-zA-Z\d_]*$/)
      );
      expect(formActions.change).toHaveBeenCalledWith(
        'library.sidepanel.metadata.metadata.image',
        expect.stringMatching(/^[a-zA-Z\d_]*$/)
      );
      expect(props.onClose).toHaveBeenCalled();
    });

    it('should not display the button to upload from local files in multiedit forms', () => {
      props.multipleEdition = true;
      render();
      expect(component.find('input[type="file"]').length).toBe(0);
    });
  });
});