UNPKG

decap-cms-core

Version:

Decap CMS core application, see decap-cms package for the main distribution.

328 lines (282 loc) 9.04 kB
import configureMockStore from 'redux-mock-store'; import thunk from 'redux-thunk'; import { List, Map } from 'immutable'; import { insertMedia, persistMedia, deleteMedia } from '../mediaLibrary'; jest.mock('../../backend'); jest.mock('../waitUntil'); jest.mock('decap-cms-lib-util', () => { const lib = jest.requireActual('decap-cms-lib-util'); return { ...lib, getBlobSHA: jest.fn(), }; }); const middlewares = [thunk]; const mockStore = configureMockStore(middlewares); describe('mediaLibrary', () => { describe('insertMedia', () => { it('should return mediaPath as string when string is given', () => { const store = mockStore({ config: { public_folder: '/media', }, collections: Map({ posts: Map({ name: 'posts' }), }), entryDraft: Map({ entry: Map({ isPersisting: false, collection: 'posts' }), }), }); store.dispatch(insertMedia('foo.png')); expect(store.getActions()[0]).toEqual({ type: 'MEDIA_INSERT', payload: { mediaPath: '/media/foo.png' }, }); }); it('should return mediaPath as array of strings when array of strings is given', () => { const store = mockStore({ config: { public_folder: '/media', }, collections: Map({ posts: Map({ name: 'posts' }), }), entryDraft: Map({ entry: Map({ isPersisting: false, collection: 'posts' }), }), }); store.dispatch(insertMedia(['foo.png'])); expect(store.getActions()[0]).toEqual({ type: 'MEDIA_INSERT', payload: { mediaPath: ['/media/foo.png'] }, }); }); }); const { currentBackend } = require('../../backend'); const backend = { persistMedia: jest.fn(() => ({ id: 'id' })), deleteMedia: jest.fn(), }; currentBackend.mockReturnValue(backend); describe('persistMedia', () => { global.URL = { createObjectURL: jest.fn().mockReturnValue('displayURL') }; beforeEach(() => { jest.clearAllMocks(); }); it('should not persist media when editing draft', () => { const { getBlobSHA } = require('decap-cms-lib-util'); getBlobSHA.mockReturnValue('000000000000000'); const store = mockStore({ config: { media_folder: 'static/media', slug: { encoding: 'unicode', clean_accents: false, sanitize_replacement: '-', }, }, collections: Map({ posts: Map({ name: 'posts' }), }), integrations: Map(), mediaLibrary: Map({ files: List(), }), entryDraft: Map({ entry: Map({ isPersisting: false, collection: 'posts' }), }), }); const file = new File([''], 'name.png'); return store.dispatch(persistMedia(file)).then(() => { const actions = store.getActions(); expect(actions).toHaveLength(2); expect(actions[0].type).toEqual('ADD_ASSET'); expect(actions[0].payload).toEqual( expect.objectContaining({ path: 'static/media/name.png', }), ); expect(actions[1].type).toEqual('ADD_DRAFT_ENTRY_MEDIA_FILE'); expect(actions[1].payload).toEqual( expect.objectContaining({ draft: true, id: '000000000000000', path: 'static/media/name.png', size: file.size, name: file.name, }), ); expect(getBlobSHA).toHaveBeenCalledTimes(1); expect(getBlobSHA).toHaveBeenCalledWith(file); expect(backend.persistMedia).toHaveBeenCalledTimes(0); }); }); it('should persist media when not editing draft', () => { const store = mockStore({ config: { media_folder: 'static/media', slug: { encoding: 'unicode', clean_accents: false, sanitize_replacement: '-', }, }, collections: Map({ posts: Map({ name: 'posts' }), }), integrations: Map(), mediaLibrary: Map({ files: List(), }), entryDraft: Map({ entry: Map(), }), }); const file = new File([''], 'name.png'); return store.dispatch(persistMedia(file)).then(() => { const actions = store.getActions(); expect(actions).toHaveLength(3); expect(actions).toHaveLength(3); expect(actions[0]).toEqual({ type: 'MEDIA_PERSIST_REQUEST' }); expect(actions[1].type).toEqual('ADD_ASSET'); expect(actions[1].payload).toEqual( expect.objectContaining({ path: 'static/media/name.png', }), ); expect(actions[2]).toEqual({ type: 'MEDIA_PERSIST_SUCCESS', payload: { file: { id: 'id' }, }, }); expect(backend.persistMedia).toHaveBeenCalledTimes(1); expect(backend.persistMedia).toHaveBeenCalledWith( store.getState().config, expect.objectContaining({ path: 'static/media/name.png', }), ); }); }); it('should sanitize media name if needed when persisting', () => { const store = mockStore({ config: { media_folder: 'static/media', slug: { encoding: 'ascii', clean_accents: true, sanitize_replacement: '_', }, }, collections: Map({ posts: Map({ name: 'posts' }), }), integrations: Map(), mediaLibrary: Map({ files: List(), }), entryDraft: Map({ entry: Map(), }), }); const file = new File([''], 'abc DEF éâçÖ $;, .png'); return store.dispatch(persistMedia(file)).then(() => { const actions = store.getActions(); expect(actions).toHaveLength(3); expect(actions[0]).toEqual({ type: 'MEDIA_PERSIST_REQUEST' }); expect(actions[1].type).toEqual('ADD_ASSET'); expect(actions[1].payload).toEqual( expect.objectContaining({ path: 'static/media/abc_def_eaco_.png', }), ); expect(actions[2]).toEqual({ type: 'MEDIA_PERSIST_SUCCESS', payload: { file: { id: 'id' }, }, }); expect(backend.persistMedia).toHaveBeenCalledTimes(1); expect(backend.persistMedia).toHaveBeenCalledWith( store.getState().config, expect.objectContaining({ path: 'static/media/abc_def_eaco_.png', }), ); }); }); }); describe('deleteMedia', () => { beforeEach(() => { jest.clearAllMocks(); }); it('should delete non draft file', () => { const store = mockStore({ config: { publish_mode: 'editorial_workflow', }, collections: Map(), integrations: Map(), mediaLibrary: Map({ files: List(), }), entryDraft: Map({ entry: Map({ isPersisting: false }), }), }); const file = { name: 'name.png', id: 'id', path: 'static/media/name.png', draft: false }; return store.dispatch(deleteMedia(file)).then(() => { const actions = store.getActions(); expect(actions).toHaveLength(4); expect(actions[0]).toEqual({ type: 'MEDIA_DELETE_REQUEST' }); expect(actions[1]).toEqual({ type: 'REMOVE_ASSET', payload: 'static/media/name.png', }); expect(actions[2]).toEqual({ type: 'MEDIA_DELETE_SUCCESS', payload: { file }, }); expect(actions[3]).toEqual({ type: 'REMOVE_DRAFT_ENTRY_MEDIA_FILE', payload: { id: 'id' }, }); expect(backend.deleteMedia).toHaveBeenCalledTimes(1); expect(backend.deleteMedia).toHaveBeenCalledWith( store.getState().config, 'static/media/name.png', ); }); }); it('should not delete a draft file', () => { const store = mockStore({ config: { publish_mode: 'editorial_workflow', }, collections: Map(), integrations: Map(), mediaLibrary: Map({ files: List(), }), entryDraft: Map({ entry: Map({ isPersisting: false }), }), }); const file = { name: 'name.png', id: 'id', path: 'static/media/name.png', draft: true }; return store.dispatch(deleteMedia(file)).then(() => { const actions = store.getActions(); expect(actions).toHaveLength(2); expect(actions[0]).toEqual({ type: 'REMOVE_ASSET', payload: 'static/media/name.png', }); expect(actions[1]).toEqual({ type: 'REMOVE_DRAFT_ENTRY_MEDIA_FILE', payload: { id: 'id' }, }); expect(backend.deleteMedia).toHaveBeenCalledTimes(0); }); }); }); });