diff --git a/src/editors/containers/TextEditor/__snapshots__/index.test.jsx.snap b/src/editors/containers/TextEditor/__snapshots__/index.test.jsx.snap index e4f956d5d..afc1f02f6 100644 --- a/src/editors/containers/TextEditor/__snapshots__/index.test.jsx.snap +++ b/src/editors/containers/TextEditor/__snapshots__/index.test.jsx.snap @@ -29,6 +29,13 @@ exports[`TextEditor snapshots block failed to load, Toast is shown 1`] = ` }, } } + images={ + Object { + "sOmEuiMAge": Object { + "staTICUrl": "/assets/sOmEuiMAge", + }, + } + } isOpen={false} selection="hooks.selectedImage.selection" setSelection={[MockFunction hooks.selectedImage.setSelection]} @@ -63,6 +70,11 @@ exports[`TextEditor snapshots block failed to load, Toast is shown 1`] = ` }, }, "clearSelection": [MockFunction hooks.selectedImage.clearSelection], + "images": Object { + "sOmEuiMAge": Object { + "staTICUrl": "/assets/sOmEuiMAge", + }, + }, "initializeEditor": [MockFunction args.intializeEditor], "lmsEndpointUrl": "sOmEvaLue.cOm", "openImgModal": [MockFunction modal.openModal], @@ -106,6 +118,13 @@ exports[`TextEditor snapshots loaded, raw editor 1`] = ` }, } } + images={ + Object { + "sOmEuiMAge": Object { + "staTICUrl": "/assets/sOmEuiMAge", + }, + } + } isOpen={false} selection="hooks.selectedImage.selection" setSelection={[MockFunction hooks.selectedImage.setSelection]} @@ -173,6 +192,13 @@ exports[`TextEditor snapshots not yet loaded, Spinner appears 1`] = ` }, } } + images={ + Object { + "sOmEuiMAge": Object { + "staTICUrl": "/assets/sOmEuiMAge", + }, + } + } isOpen={false} selection="hooks.selectedImage.selection" setSelection={[MockFunction hooks.selectedImage.setSelection]} @@ -240,6 +266,13 @@ exports[`TextEditor snapshots renders as expected with default behavior 1`] = ` }, } } + images={ + Object { + "sOmEuiMAge": Object { + "staTICUrl": "/assets/sOmEuiMAge", + }, + } + } isOpen={false} selection="hooks.selectedImage.selection" setSelection={[MockFunction hooks.selectedImage.setSelection]} @@ -274,6 +307,11 @@ exports[`TextEditor snapshots renders as expected with default behavior 1`] = ` }, }, "clearSelection": [MockFunction hooks.selectedImage.clearSelection], + "images": Object { + "sOmEuiMAge": Object { + "staTICUrl": "/assets/sOmEuiMAge", + }, + }, "initializeEditor": [MockFunction args.intializeEditor], "lmsEndpointUrl": "sOmEvaLue.cOm", "openImgModal": [MockFunction modal.openModal], diff --git a/src/editors/containers/TextEditor/components/ImageUploadModal.jsx b/src/editors/containers/TextEditor/components/ImageUploadModal.jsx index 2cba4fea2..9b5eea5a5 100644 --- a/src/editors/containers/TextEditor/components/ImageUploadModal.jsx +++ b/src/editors/containers/TextEditor/components/ImageUploadModal.jsx @@ -52,6 +52,7 @@ export const ImageUploadModal = ({ clearSelection, selection, setSelection, + images, }) => { if (selection) { return ( @@ -78,6 +79,7 @@ export const ImageUploadModal = ({ close, setSelection, clearSelection, + images, }} /> ); @@ -101,5 +103,6 @@ ImageUploadModal.propTypes = { altText: PropTypes.bool, }), setSelection: PropTypes.func.isRequired, + images: PropTypes.shape({}).isRequired, }; export default ImageUploadModal; diff --git a/src/editors/containers/TextEditor/components/SelectImageModal/hooks.js b/src/editors/containers/TextEditor/components/SelectImageModal/hooks.js index 4f098b14f..237b3b013 100644 --- a/src/editors/containers/TextEditor/components/SelectImageModal/hooks.js +++ b/src/editors/containers/TextEditor/components/SelectImageModal/hooks.js @@ -7,7 +7,6 @@ import { sortFunctions, sortKeys } from './utils'; export const state = { highlighted: (val) => React.useState(val), - images: (val) => React.useState(val), showSelectImageError: (val) => React.useState(val), searchString: (val) => React.useState(val), sortBy: (val) => React.useState(val), @@ -36,9 +35,7 @@ export const displayList = ({ sortBy, searchString, images }) => ( imageList: Object.values(images), }).sort(sortFunctions[sortBy in sortKeys ? sortKeys[sortBy] : sortKeys.dateNewest])); -export const imgListHooks = ({ searchSortProps, setSelection }) => { - const dispatch = useDispatch(); - const [images, setImages] = module.state.images({}); +export const imgListHooks = ({ searchSortProps, setSelection, images }) => { const [highlighted, setHighlighted] = module.state.highlighted(null); const [ showSelectImageError, @@ -47,10 +44,6 @@ export const imgListHooks = ({ searchSortProps, setSelection }) => { const [showSizeError, setShowSizeError] = module.state.showSelectImageError(false); const list = module.displayList({ ...searchSortProps, images }); - React.useEffect(() => { - dispatch(thunkActions.app.fetchImages({ setImages })); - }, []); - return { galleryError: { show: showSelectImageError, @@ -126,9 +119,9 @@ export const fileInputHooks = ({ setSelection, clearSelection, imgList }) => { }; }; -export const imgHooks = ({ setSelection, clearSelection }) => { +export const imgHooks = ({ setSelection, clearSelection, images }) => { const searchSortProps = module.searchAndSortHooks(); - const imgList = module.imgListHooks({ setSelection, searchSortProps }); + const imgList = module.imgListHooks({ setSelection, searchSortProps, images }); const fileInput = module.fileInputHooks({ setSelection, clearSelection, diff --git a/src/editors/containers/TextEditor/components/SelectImageModal/hooks.test.js b/src/editors/containers/TextEditor/components/SelectImageModal/hooks.test.js index 84465ec8a..6456cf21e 100644 --- a/src/editors/containers/TextEditor/components/SelectImageModal/hooks.test.js +++ b/src/editors/containers/TextEditor/components/SelectImageModal/hooks.test.js @@ -27,25 +27,6 @@ jest.mock('react-redux', () => { jest.mock('../../../../data/redux', () => ({ thunkActions: { app: { - fetchImages: jest.fn(), - uploadImage: jest.fn(), - }, - }, -})); - -jest.mock('react-redux', () => { - const dispatchFn = jest.fn(); - return { - ...jest.requireActual('react-redux'), - dispatch: dispatchFn, - useDispatch: jest.fn(() => dispatchFn), - }; -}); - -jest.mock('../../../../data/redux', () => ({ - thunkActions: { - app: { - fetchImages: jest.fn(), uploadImage: jest.fn(), }, }, @@ -63,7 +44,6 @@ describe('SelectImageModal hooks', () => { }); describe('state hooks', () => { state.testGetter(state.keys.highlighted); - state.testGetter(state.keys.images); state.testGetter(state.keys.showSelectImageError); state.testGetter(state.keys.searchString); state.testGetter(state.keys.sortBy); @@ -156,6 +136,12 @@ describe('SelectImageModal hooks', () => { const props = { setSelection: jest.fn(), searchSortProps: { searchString: 'Es', sortBy: sortKeys.dateNewest }, + images: { + sOmEuiMAgeURl: { + displayName: 'sOmEuiMAge', + staTICUrl: '/assets/sOmEuiMAge', + }, + }, }; const displayList = (args) => ({ displayList: args }); const load = () => { @@ -165,31 +151,17 @@ describe('SelectImageModal hooks', () => { beforeEach(() => { load(); }); - it('returns images value, initialized to an empty object', () => { - expect(state.stateVals.images).toEqual(hook.images); - expect(state.stateVals.images).toEqual({}); - }); - it('dispatches fetchImages thunkAction once, with setImages as onSuccess param', () => { - expect(React.useEffect.mock.calls.length).toEqual(1); - const [cb, prereqs] = React.useEffect.mock.calls[0]; - expect(prereqs).toEqual([]); - cb(); - expect(dispatch).toHaveBeenCalledWith( - thunkActions.app.fetchImages({ setImages: state.setState.images }), - ); - }); describe('selectBtnProps', () => { test('on click, if sets selection to the image with the same id', () => { - const highlighted = 'id1'; - state.mockVal(state.keys.images, { [highlighted]: testValue }); + const highlighted = 'sOmEuiMAgeURl'; + const highlightedValue = { displayName: 'sOmEuiMAge', staTICUrl: '/assets/sOmEuiMAge' }; state.mockVal(state.keys.highlighted, highlighted); load(); expect(props.setSelection).not.toHaveBeenCalled(); hook.selectBtnProps.onClick(); - expect(props.setSelection).toHaveBeenCalledWith(testValue); + expect(props.setSelection).toHaveBeenCalledWith(highlightedValue); }); test('on click, sets showSelectImageError to true if nothing is highlighted', () => { - state.mockVal(state.keys.images, { }); state.mockVal(state.keys.highlighted, null); load(); hook.selectBtnProps.onClick(); @@ -209,7 +181,7 @@ describe('SelectImageModal hooks', () => { test('displayList returns displayListhook called with searchSortProps and images', () => { expect(hook.galleryProps.displayList).toEqual(displayList({ ...props.searchSortProps, - images: hook.images, + images: props.images, })); }); }); @@ -307,6 +279,7 @@ describe('SelectImageModal hooks', () => { }; const searchAndSortHooks = { search: 'props' }; const fileInputHooks = { file: 'input hooks' }; + const images = { sOmEuiMAge: { staTICUrl: '/assets/sOmEuiMAge' } }; const setSelection = jest.fn(); const clearSelection = jest.fn(); @@ -318,7 +291,7 @@ describe('SelectImageModal hooks', () => { .mockReturnValueOnce(searchAndSortHooks); spies.file = jest.spyOn(hooks, hookKeys.fileInputHooks) .mockReturnValueOnce(fileInputHooks); - hook = hooks.imgHooks({ setSelection, clearSelection }); + hook = hooks.imgHooks({ setSelection, clearSelection, images }); }); it('forwards fileInputHooks as fileInput, called with uploadImage prop', () => { expect(hook.fileInput).toEqual(fileInputHooks); @@ -327,11 +300,12 @@ describe('SelectImageModal hooks', () => { setSelection, clearSelection, imgList: imgListHooks, }); }); - it('initializes imgListHooks with setSelection and searchAndSortHooks', () => { + it('initializes imgListHooks with setSelection,searchAndSortHooks, and images', () => { expect(spies.imgList.mock.calls.length).toEqual(1); expect(spies.imgList).toHaveBeenCalledWith({ setSelection, searchSortProps: searchAndSortHooks, + images, }); }); it('forwards searchAndSortHooks as searchSortProps', () => { diff --git a/src/editors/containers/TextEditor/components/SelectImageModal/index.jsx b/src/editors/containers/TextEditor/components/SelectImageModal/index.jsx index 4619b3917..df077b473 100644 --- a/src/editors/containers/TextEditor/components/SelectImageModal/index.jsx +++ b/src/editors/containers/TextEditor/components/SelectImageModal/index.jsx @@ -27,6 +27,7 @@ export const SelectImageModal = ({ close, setSelection, clearSelection, + images, // injected intl, // redux @@ -39,7 +40,7 @@ export const SelectImageModal = ({ galleryProps, searchSortProps, selectBtnProps, - } = hooks.imgHooks({ setSelection, clearSelection }); + } = hooks.imgHooks({ setSelection, clearSelection, images }); return ( { + const content = editor.getContent(); + const imageSrcs = content.split('img src="'); + imageSrcs.forEach(src => { + if (src.startsWith('/static/') && imageUrls.length > 0) { + const imgName = src.substring(8, src.indexOf('"')); + let staticFullUrl; + imageUrls.forEach((url) => { + if (url.includes(imgName)) { + staticFullUrl = url; + } + }); + const currentSrc = src.substring(0, src.indexOf('"')); + const updatedContent = content.replace(currentSrc, staticFullUrl); + editor.setContent(updatedContent); + } + }); +}; + +export const checkRelativeUrl = (imageUrls) => (editor) => { + editor.on('ExecCommand', (e) => { + if (e.command === 'mceFocus') { + module.replaceStaticwithAsset(editor, imageUrls); + } + }); +}; + // imagetools_cors_hosts needs a protocol-sanatized url export const removeProtocolFromUrl = (url) => url.replace(/^https?:\/\//, ''); @@ -72,6 +99,7 @@ export const editorConfig = ({ setEditorRef, setSelection, studioEndpointUrl, + images, }) => ({ onInit: (evt, editor) => { setEditorRef(editor); @@ -85,6 +113,7 @@ export const editorConfig = ({ content_style: tinyMCEStyles, contextmenu: 'link table', document_base_url: lmsEndpointUrl, + init_instance_callback: module.checkRelativeUrl(module.fetchImageUrls(images)), imagetools_cors_hosts: [removeProtocolFromUrl(lmsEndpointUrl), removeProtocolFromUrl(studioEndpointUrl)], imagetools_toolbar: pluginConfig.imageToolbar, plugins: pluginConfig.plugins, @@ -108,12 +137,15 @@ export const imgModalToggle = () => { }; }; -export const sourceCodeModalToggle = () => { +export const sourceCodeModalToggle = (editorRef) => { const [isSourceCodeOpen, setIsOpen] = module.state.isSourceCodeModalOpen(false); return { isSourceCodeOpen, openSourceCodeModal: () => setIsOpen(true), - closeSourceCodeModal: () => setIsOpen(false), + closeSourceCodeModal: () => { + setIsOpen(false); + editorRef.current.focus(); + }, }; }; @@ -145,6 +177,15 @@ export const getContent = ({ editorRef, isRaw }) => () => { return editorRef.current?.getContent(); }; +export const fetchImageUrls = (images) => { + const imageUrls = []; + const imgsArray = Object.values(images); + imgsArray.forEach(image => { + imageUrls.push(image.staticFullUrl); + }); + return imageUrls; +}; + export const selectedImage = (val) => { const [selection, setSelection] = module.state.imageSelection(val); return { diff --git a/src/editors/containers/TextEditor/hooks.test.jsx b/src/editors/containers/TextEditor/hooks.test.jsx index 760619c8d..ce9e4060e 100644 --- a/src/editors/containers/TextEditor/hooks.test.jsx +++ b/src/editors/containers/TextEditor/hooks.test.jsx @@ -86,11 +86,27 @@ describe('TextEditor hooks', () => { }); }); + describe('replaceStaticwithAsset', () => { + const editor = { getContent: jest.fn(() => ''), setContent: jest.fn() }; + const imageUrls = ['soMEImagEURl1.jpeg']; + module.replaceStaticwithAsset(editor, imageUrls); + expect(editor.getContent).toHaveBeenCalled(); + expect(editor.setContent).toHaveBeenCalled(); + }); + + describe('checkRelativeUrl', () => { + const editor = { on: jest.fn() }; + const imageUrls = ['soMEImagEURl1']; + module.checkRelativeUrl(imageUrls)(editor); + expect(editor.on).toHaveBeenCalled(); + }); + describe('editorConfig', () => { const props = { blockValue: null, lmsEndpointUrl: 'sOmEuRl.cOm', studioEndpointUrl: 'sOmEoThEruRl.cOm', + images: { sOmEuiMAge: { staTICUrl: '/assets/sOmEuiMAge' } }, }; const evt = 'fakeEvent'; const editor = 'myEditor'; @@ -159,9 +175,10 @@ describe('TextEditor hooks', () => { }); describe('sourceCodeModalToggle', () => { + const editorRef = { current: { focus: jest.fn() } }; const hookKey = state.keys.isSourceCodeModalOpen; beforeEach(() => { - hook = module.sourceCodeModalToggle(); + hook = module.sourceCodeModalToggle(editorRef); }); test('isOpen: state value', () => { expect(hook.isSourceCodeOpen).toEqual(state.stateVals[hookKey]); diff --git a/src/editors/containers/TextEditor/index.jsx b/src/editors/containers/TextEditor/index.jsx index 7f73dc1e3..21db092ac 100644 --- a/src/editors/containers/TextEditor/index.jsx +++ b/src/editors/containers/TextEditor/index.jsx @@ -44,14 +44,15 @@ export const TextEditor = ({ lmsEndpointUrl, studioEndpointUrl, blockFailed, - blockFinished, initializeEditor, + images, + imagesFinished, // inject intl, }) => { const { editorRef, refReady, setEditorRef } = hooks.prepareEditorRef(); const { isImgOpen, openImgModal, closeImgModal } = hooks.imgModalToggle(); - const { isSourceCodeOpen, openSourceCodeModal, closeSourceCodeModal } = hooks.sourceCodeModalToggle(); + const { isSourceCodeOpen, openSourceCodeModal, closeSourceCodeModal } = hooks.sourceCodeModalToggle(editorRef); const imageSelection = hooks.selectedImage(null); if (!refReady) { return null; } @@ -75,6 +76,7 @@ export const TextEditor = ({ initializeEditor, lmsEndpointUrl, studioEndpointUrl, + images, setSelection: imageSelection.setSelection, clearSelection: imageSelection.clearSelection, })} @@ -92,6 +94,7 @@ export const TextEditor = ({ isOpen={isImgOpen} close={closeImgModal} editorRef={editorRef} + images={images} {...imageSelection} /> - {(!blockFinished) + {(!imagesFinished) ? (
({ lmsEndpointUrl: selectors.app.lmsEndpointUrl(state), studioEndpointUrl: selectors.app.studioEndpointUrl(state), blockFailed: selectors.requests.isFailed(state, { requestKey: RequestKeys.fetchBlock }), - blockFinished: selectors.requests.isFinished(state, { requestKey: RequestKeys.fetchBlock }), isRaw: selectors.app.isRaw(state), + imagesFinished: selectors.requests.isFinished(state, { requestKey: RequestKeys.fetchImages }), + images: selectors.app.images(state), }); export const mapDispatchToProps = { diff --git a/src/editors/containers/TextEditor/index.test.jsx b/src/editors/containers/TextEditor/index.test.jsx index 256703927..26372dc3b 100644 --- a/src/editors/containers/TextEditor/index.test.jsx +++ b/src/editors/containers/TextEditor/index.test.jsx @@ -70,6 +70,7 @@ jest.mock('../../data/redux', () => ({ lmsEndpointUrl: jest.fn(state => ({ lmsEndpointUrl: state })), studioEndpointUrl: jest.fn(state => ({ studioEndpointUrl: state })), isRaw: jest.fn(state => ({ isRaw: state })), + images: jest.fn(state => ({ images: state })), }, requests: { isFailed: jest.fn((state, params) => ({ isFailed: { state, params } })), @@ -86,9 +87,10 @@ describe('TextEditor', () => { lmsEndpointUrl: 'sOmEvaLue.cOm', studioEndpointUrl: 'sOmEoThERvaLue.cOm', blockFailed: false, - blockFinished: true, initializeEditor: jest.fn().mockName('args.intializeEditor'), isRaw: false, + imagesFinished: true, + images: { sOmEuiMAge: { staTICUrl: '/assets/sOmEuiMAge' } }, // inject intl: { formatMessage }, }; @@ -107,7 +109,7 @@ describe('TextEditor', () => { expect(shallow()).toMatchSnapshot(); }); test('not yet loaded, Spinner appears', () => { - expect(shallow()).toMatchSnapshot(); + expect(shallow()).toMatchSnapshot(); }); test('loaded, raw editor', () => { expect(shallow()).toMatchSnapshot(); @@ -128,15 +130,20 @@ describe('TextEditor', () => { mapStateToProps(testState).lmsEndpointUrl, ).toEqual(selectors.app.lmsEndpointUrl(testState)); }); + test('images from app.images', () => { + expect( + mapStateToProps(testState).images, + ).toEqual(selectors.app.images(testState)); + }); test('blockFailed from requests.isFailed', () => { expect( mapStateToProps(testState).blockFailed, ).toEqual(selectors.requests.isFailed(testState, { requestKey: RequestKeys.fetchBlock })); }); - test('blockFinished from requests.isFinished', () => { + test('imagesFinished from requests.isFinished', () => { expect( - mapStateToProps(testState).blockFinished, - ).toEqual(selectors.requests.isFinished(testState, { requestKey: RequestKeys.fetchBlock })); + mapStateToProps(testState).imagesFinished, + ).toEqual(selectors.requests.isFinished(testState, { requestKey: RequestKeys.fetchImages })); }); }); describe('mapDispatchToProps', () => { diff --git a/src/editors/containers/TextEditor/pluginConfig.js b/src/editors/containers/TextEditor/pluginConfig.js index ba880789b..7bef74375 100644 --- a/src/editors/containers/TextEditor/pluginConfig.js +++ b/src/editors/containers/TextEditor/pluginConfig.js @@ -49,6 +49,7 @@ export default StrictDict({ menubar: false, min_height: 500, toolbar_sticky: true, - relative_urls: false, + relative_urls: true, + convert_urls: false, }, }); diff --git a/src/editors/data/redux/app/reducer.js b/src/editors/data/redux/app/reducer.js index f963df46a..e407669b2 100644 --- a/src/editors/data/redux/app/reducer.js +++ b/src/editors/data/redux/app/reducer.js @@ -8,7 +8,6 @@ const initialState = { blockContent: null, studioView: null, saveResponse: null, - blockId: null, blockTitle: null, blockType: null, @@ -16,6 +15,7 @@ const initialState = { editorInitialized: false, studioEndpointUrl: null, lmsEndpointUrl: null, + images: {}, }; // eslint-disable-next-line no-unused-vars @@ -45,6 +45,7 @@ const app = createSlice({ setBlockTitle: (state, { payload }) => ({ ...state, blockTitle: payload }), setSaveResponse: (state, { payload }) => ({ ...state, saveResponse: payload }), initializeEditor: (state) => ({ ...state, editorInitialized: true }), + setImages: (state, { payload }) => ({ ...state, images: payload }), }, }); diff --git a/src/editors/data/redux/app/reducer.test.js b/src/editors/data/redux/app/reducer.test.js index 767da4be4..218cc62ce 100644 --- a/src/editors/data/redux/app/reducer.test.js +++ b/src/editors/data/redux/app/reducer.test.js @@ -47,6 +47,7 @@ describe('app reducer', () => { ['setBlockContent', 'blockContent'], ['setBlockTitle', 'blockTitle'], ['setSaveResponse', 'saveResponse'], + ['setImages', 'images'], ].map(args => setterTest(...args)); describe('setBlockValue', () => { it('sets blockValue, as well as setting the blockTitle from data.display_name', () => { diff --git a/src/editors/data/redux/app/selectors.js b/src/editors/data/redux/app/selectors.js index 1dbf6c9db..d828a9ec4 100644 --- a/src/editors/data/redux/app/selectors.js +++ b/src/editors/data/redux/app/selectors.js @@ -22,6 +22,7 @@ export const simpleSelectors = { studioEndpointUrl: mkSimpleSelector(app => app.studioEndpointUrl), unitUrl: mkSimpleSelector(app => app.unitUrl), blockTitle: mkSimpleSelector(app => app.blockTitle), + images: mkSimpleSelector(app => app.images), }; export const returnUrl = createSelector( diff --git a/src/editors/data/redux/app/selectors.test.js b/src/editors/data/redux/app/selectors.test.js index 882e0c024..eb05f2375 100644 --- a/src/editors/data/redux/app/selectors.test.js +++ b/src/editors/data/redux/app/selectors.test.js @@ -46,6 +46,7 @@ describe('app selectors unit tests', () => { simpleKeys.unitUrl, simpleKeys.blockTitle, simpleKeys.studioView, + simpleKeys.images, ].map(testSimpleSelector); }); }); diff --git a/src/editors/data/redux/thunkActions/app.js b/src/editors/data/redux/thunkActions/app.js index 7a900cd73..4fabd3388 100644 --- a/src/editors/data/redux/thunkActions/app.js +++ b/src/editors/data/redux/thunkActions/app.js @@ -24,6 +24,12 @@ export const fetchUnit = () => (dispatch) => { })); }; +export const fetchImages = () => (dispatch) => { + dispatch(requests.fetchImages({ + onSuccess: (response) => dispatch(actions.app.setImages(response)), + })); +}; + /** * @param {string} studioEndpointUrl * @param {string} blockId @@ -35,6 +41,7 @@ export const initialize = (data) => (dispatch) => { dispatch(module.fetchBlock()); dispatch(module.fetchUnit()); dispatch(module.fetchStudioView()); + dispatch(module.fetchImages()); }; /** @@ -51,10 +58,6 @@ export const saveBlock = ({ content, returnToUnit }) => (dispatch) => { })); }; -export const fetchImages = ({ setImages }) => (dispatch) => { - dispatch(requests.fetchImages({ onSuccess: setImages })); -}; - export const uploadImage = ({ file, setSelection }) => (dispatch) => { dispatch(requests.uploadImage({ image: file, diff --git a/src/editors/data/redux/thunkActions/app.test.js b/src/editors/data/redux/thunkActions/app.test.js index e11876b87..263e49eb1 100644 --- a/src/editors/data/redux/thunkActions/app.test.js +++ b/src/editors/data/redux/thunkActions/app.test.js @@ -80,20 +80,28 @@ describe('app thunkActions', () => { }); describe('initialize', () => { it('dispatches actions.app.initialize, and then fetches both block and unit', () => { - const { fetchBlock, fetchUnit, fetchStudioView } = thunkActions; + const { + fetchBlock, + fetchUnit, + fetchStudioView, + fetchImages, + } = thunkActions; thunkActions.fetchBlock = () => 'fetchBlock'; thunkActions.fetchUnit = () => 'fetchUnit'; thunkActions.fetchStudioView = () => 'fetchStudioView'; + thunkActions.fetchImages = () => 'fetchImages'; thunkActions.initialize(testValue)(dispatch); expect(dispatch.mock.calls).toEqual([ [actions.app.initialize(testValue)], [thunkActions.fetchBlock()], [thunkActions.fetchUnit()], [thunkActions.fetchStudioView()], + [thunkActions.fetchImages()], ]); thunkActions.fetchBlock = fetchBlock; thunkActions.fetchUnit = fetchUnit; thunkActions.fetchStudioView = fetchStudioView; + thunkActions.fetchImages = fetchImages; }); }); describe('saveBlock', () => { @@ -122,10 +130,11 @@ describe('app thunkActions', () => { }); describe('fetchImages', () => { it('dispatches fetchUnit action with setImages for onSuccess param', () => { - const setImages = jest.fn(); - thunkActions.fetchImages({ setImages })(dispatch); - [[dispatchedAction]] = dispatch.mock.calls; - expect(dispatchedAction.fetchImages).toEqual({ onSuccess: setImages }); + const response = 'testRESPONSE'; + thunkActions.fetchImages()(dispatch); + const [[dispatchCall]] = dispatch.mock.calls; + dispatchCall.fetchImages.onSuccess(response); + expect(dispatch).toHaveBeenCalledWith(actions.app.setImages(response)); }); }); describe('uploadImage', () => {