@@ -10,6 +10,7 @@ exports[`TextEditor snapshots block failed to load, Toast is shown 1`] = `
|
||||
"value": "something",
|
||||
},
|
||||
},
|
||||
"isRaw": false,
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -64,6 +65,62 @@ exports[`TextEditor snapshots block failed to load, Toast is shown 1`] = `
|
||||
</EditorContainer>
|
||||
`;
|
||||
|
||||
exports[`TextEditor snapshots loaded, raw editor 1`] = `
|
||||
<EditorContainer
|
||||
getContent={
|
||||
Object {
|
||||
"getContent": Object {
|
||||
"editorRef": Object {
|
||||
"current": Object {
|
||||
"value": "something",
|
||||
},
|
||||
},
|
||||
"isRaw": true,
|
||||
},
|
||||
}
|
||||
}
|
||||
onClose={[MockFunction props.onClose]}
|
||||
>
|
||||
<div
|
||||
className="editor-body h-75 overflow-auto"
|
||||
>
|
||||
<ImageUploadModal
|
||||
clearSelection={[MockFunction hooks.selectedImage.clearSelection]}
|
||||
close={[MockFunction modal.closeModal]}
|
||||
editorRef={
|
||||
Object {
|
||||
"current": Object {
|
||||
"value": "something",
|
||||
},
|
||||
}
|
||||
}
|
||||
isOpen={false}
|
||||
selection="hooks.selectedImage.selection"
|
||||
setSelection={[MockFunction hooks.selectedImage.setSelection]}
|
||||
/>
|
||||
<Toast
|
||||
onClose={[MockFunction hooks.nullMethod]}
|
||||
show={false}
|
||||
>
|
||||
<FormattedMessage
|
||||
defaultMessage="Error: Could Not Load Text Content"
|
||||
description="Error Message Dispayed When HTML content fails to Load"
|
||||
id="authoring.texteditor.load.error"
|
||||
/>
|
||||
</Toast>
|
||||
<RawEditor
|
||||
editorRef={
|
||||
Object {
|
||||
"current": Object {
|
||||
"value": "something",
|
||||
},
|
||||
}
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</EditorContainer>
|
||||
`;
|
||||
|
||||
exports[`TextEditor snapshots not yet loaded, Spinner appears 1`] = `
|
||||
<EditorContainer
|
||||
getContent={
|
||||
@@ -74,6 +131,7 @@ exports[`TextEditor snapshots not yet loaded, Spinner appears 1`] = `
|
||||
"value": "something",
|
||||
},
|
||||
},
|
||||
"isRaw": false,
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -129,6 +187,7 @@ exports[`TextEditor snapshots renders as expected with default behavior 1`] = `
|
||||
"value": "something",
|
||||
},
|
||||
},
|
||||
"isRaw": false,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`ImageSettingsModal renders as expected with default behavior 1`] = `
|
||||
<div
|
||||
className="form-group"
|
||||
style={
|
||||
Object {
|
||||
"padding": "10px 30px",
|
||||
}
|
||||
}
|
||||
>
|
||||
<Alert
|
||||
variant="danger"
|
||||
>
|
||||
You are using the raw HTML editor.
|
||||
</Alert>
|
||||
<textarea
|
||||
className="form-control"
|
||||
rows="12"
|
||||
>
|
||||
sOmErAwHtml
|
||||
</textarea>
|
||||
</div>
|
||||
`;
|
||||
@@ -0,0 +1,33 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Alert } from '@edx/paragon';
|
||||
|
||||
export const RawEditor = ({
|
||||
editorRef,
|
||||
text,
|
||||
}) => (
|
||||
<div className="form-group" style={{ padding: '10px 30px' }}>
|
||||
<Alert variant="danger">
|
||||
You are using the raw HTML editor.
|
||||
</Alert>
|
||||
<textarea
|
||||
className="form-control"
|
||||
ref={editorRef}
|
||||
rows="12"
|
||||
>
|
||||
{ text }
|
||||
</textarea>
|
||||
</div>
|
||||
);
|
||||
RawEditor.defaultProps = {
|
||||
editorRef: null,
|
||||
};
|
||||
RawEditor.propTypes = {
|
||||
editorRef: PropTypes.oneOfType([
|
||||
PropTypes.func,
|
||||
PropTypes.shape({ current: PropTypes.any }),
|
||||
]),
|
||||
text: PropTypes.string.isRequired,
|
||||
};
|
||||
|
||||
export default RawEditor;
|
||||
@@ -0,0 +1,18 @@
|
||||
import React from 'react';
|
||||
import { shallow } from 'enzyme';
|
||||
|
||||
import { RawEditor } from '.';
|
||||
|
||||
describe('ImageSettingsModal', () => {
|
||||
const props = {
|
||||
editorRef: {
|
||||
current: {
|
||||
value: 'Ref Value',
|
||||
},
|
||||
},
|
||||
text: 'sOmErAwHtml',
|
||||
};
|
||||
test('renders as expected with default behavior', () => {
|
||||
expect(shallow(<RawEditor {...props} />)).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
@@ -112,7 +112,12 @@ export const prepareEditorRef = () => {
|
||||
return { editorRef, refReady, setEditorRef };
|
||||
};
|
||||
|
||||
export const getContent = ({ editorRef }) => () => editorRef.current?.getContent();
|
||||
export const getContent = ({ editorRef, isRaw }) => () => {
|
||||
if (isRaw && editorRef && editorRef.current) {
|
||||
return editorRef.current.value;
|
||||
}
|
||||
return editorRef.current?.getContent();
|
||||
};
|
||||
|
||||
export const selectedImage = (val) => {
|
||||
const [selection, setSelection] = module.state.imageSelection(val);
|
||||
|
||||
@@ -188,6 +188,21 @@ describe('TextEditor hooks', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('getContent', () => {
|
||||
const visualContent = 'sOmEViSualContent';
|
||||
const rawContent = 'soMeRawContent';
|
||||
const editorRef = {
|
||||
current: {
|
||||
getContent: () => visualContent,
|
||||
value: rawContent,
|
||||
},
|
||||
};
|
||||
test('returns correct ontent based on isRaw', () => {
|
||||
expect(module.getContent({ editorRef, isRaw: false })()).toEqual(visualContent);
|
||||
expect(module.getContent({ editorRef, isRaw: true })()).toEqual(rawContent);
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectedImage hooks', () => {
|
||||
const val = { a: 'VaLUe' };
|
||||
beforeEach(() => {
|
||||
|
||||
@@ -31,12 +31,14 @@ import { RequestKeys } from '../../data/constants/requests';
|
||||
|
||||
import EditorContainer from '../EditorContainer';
|
||||
import ImageUploadModal from './components/ImageUploadModal';
|
||||
import RawEditor from './components/RawEditor';
|
||||
import * as hooks from './hooks';
|
||||
import messages from './messages';
|
||||
|
||||
export const TextEditor = ({
|
||||
onClose,
|
||||
// redux
|
||||
isRaw,
|
||||
blockValue,
|
||||
lmsEndpointUrl,
|
||||
studioEndpointUrl,
|
||||
@@ -52,9 +54,34 @@ export const TextEditor = ({
|
||||
|
||||
if (!refReady) { return null; }
|
||||
|
||||
const selectEditor = () => {
|
||||
if (isRaw) {
|
||||
return (
|
||||
<RawEditor
|
||||
editorRef={editorRef}
|
||||
text={blockValue.data.data}
|
||||
/>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<Editor
|
||||
{...hooks.editorConfig({
|
||||
setEditorRef,
|
||||
blockValue,
|
||||
openModal,
|
||||
initializeEditor,
|
||||
lmsEndpointUrl,
|
||||
studioEndpointUrl,
|
||||
setSelection: imageSelection.setSelection,
|
||||
clearSelection: imageSelection.clearSelection,
|
||||
})}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<EditorContainer
|
||||
getContent={hooks.getContent({ editorRef })}
|
||||
getContent={hooks.getContent({ editorRef, isRaw })}
|
||||
onClose={onClose}
|
||||
>
|
||||
<div className="editor-body h-75 overflow-auto">
|
||||
@@ -78,21 +105,7 @@ export const TextEditor = ({
|
||||
screenreadertext={intl.formatMessage(messages.spinnerScreenReaderText)}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
: (
|
||||
<Editor
|
||||
{...hooks.editorConfig({
|
||||
setEditorRef,
|
||||
blockValue,
|
||||
openModal,
|
||||
initializeEditor,
|
||||
lmsEndpointUrl,
|
||||
studioEndpointUrl,
|
||||
setSelection: imageSelection.setSelection,
|
||||
clearSelection: imageSelection.clearSelection,
|
||||
})}
|
||||
/>
|
||||
)}
|
||||
) : (selectEditor())}
|
||||
</div>
|
||||
|
||||
</EditorContainer>
|
||||
@@ -102,6 +115,7 @@ TextEditor.defaultProps = {
|
||||
blockValue: null,
|
||||
lmsEndpointUrl: null,
|
||||
studioEndpointUrl: null,
|
||||
isRaw: null,
|
||||
};
|
||||
TextEditor.propTypes = {
|
||||
onClose: PropTypes.func.isRequired,
|
||||
@@ -114,6 +128,7 @@ TextEditor.propTypes = {
|
||||
blockFailed: PropTypes.bool.isRequired,
|
||||
blockFinished: PropTypes.bool.isRequired,
|
||||
initializeEditor: PropTypes.func.isRequired,
|
||||
isRaw: PropTypes.bool,
|
||||
// inject
|
||||
intl: intlShape.isRequired,
|
||||
};
|
||||
@@ -124,6 +139,7 @@ export const mapStateToProps = (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),
|
||||
});
|
||||
|
||||
export const mapDispatchToProps = {
|
||||
|
||||
@@ -61,7 +61,8 @@ jest.mock('../../data/redux', () => ({
|
||||
app: {
|
||||
blockValue: jest.fn(state => ({ blockValue: state })),
|
||||
lmsEndpointUrl: jest.fn(state => ({ lmsEndpointUrl: state })),
|
||||
studioEndpointUrl: jest.fn(state => ({ lmsEndpointUrl: state })),
|
||||
studioEndpointUrl: jest.fn(state => ({ studioEndpointUrl: state })),
|
||||
isRaw: jest.fn(state => ({ isRaw: state })),
|
||||
},
|
||||
requests: {
|
||||
isFailed: jest.fn((state, params) => ({ isFailed: { state, params } })),
|
||||
@@ -80,6 +81,7 @@ describe('TextEditor', () => {
|
||||
blockFailed: false,
|
||||
blockFinished: true,
|
||||
initializeEditor: jest.fn().mockName('args.intializeEditor'),
|
||||
isRaw: false,
|
||||
// inject
|
||||
intl: { formatMessage },
|
||||
};
|
||||
@@ -95,6 +97,9 @@ describe('TextEditor', () => {
|
||||
test('not yet loaded, Spinner appears', () => {
|
||||
expect(shallow(<TextEditor {...props} blockFinished={false} />)).toMatchSnapshot();
|
||||
});
|
||||
test('loaded, raw editor', () => {
|
||||
expect(shallow(<TextEditor {...props} isRaw />)).toMatchSnapshot();
|
||||
});
|
||||
test('block failed to load, Toast is shown', () => {
|
||||
expect(shallow(<TextEditor {...props} blockFailed />)).toMatchSnapshot();
|
||||
});
|
||||
|
||||
@@ -9,8 +9,9 @@ export const RequestStates = StrictDict({
|
||||
|
||||
export const RequestKeys = StrictDict({
|
||||
fetchBlock: 'fetchBlock',
|
||||
fetchImages: 'fetchImages',
|
||||
fetchStudioView: 'fetchStudioView',
|
||||
fetchUnit: 'fetchUnit',
|
||||
saveBlock: 'saveBlock',
|
||||
fetchImages: 'fetchImages',
|
||||
uploadImage: 'uploadImage',
|
||||
});
|
||||
|
||||
@@ -6,6 +6,7 @@ const initialState = {
|
||||
blockValue: null,
|
||||
unitUrl: null,
|
||||
blockContent: null,
|
||||
studioView: null,
|
||||
saveResponse: null,
|
||||
|
||||
blockId: null,
|
||||
@@ -36,6 +37,10 @@ const app = createSlice({
|
||||
blockValue: payload,
|
||||
blockTitle: payload.data.display_name,
|
||||
}),
|
||||
setStudioView: (state, { payload }) => ({
|
||||
...state,
|
||||
studioView: payload,
|
||||
}),
|
||||
setBlockContent: (state, { payload }) => ({ ...state, blockContent: payload }),
|
||||
setBlockTitle: (state, { payload }) => ({ ...state, blockTitle: payload }),
|
||||
setSaveResponse: (state, { payload }) => ({ ...state, saveResponse: payload }),
|
||||
|
||||
@@ -43,6 +43,7 @@ describe('app reducer', () => {
|
||||
};
|
||||
[
|
||||
['setUnitUrl', 'unitUrl'],
|
||||
['setStudioView', 'studioView'],
|
||||
['setBlockContent', 'blockContent'],
|
||||
['setBlockTitle', 'blockTitle'],
|
||||
['setSaveResponse', 'saveResponse'],
|
||||
|
||||
@@ -14,6 +14,7 @@ export const simpleSelectors = {
|
||||
blockId: mkSimpleSelector(app => app.blockId),
|
||||
blockType: mkSimpleSelector(app => app.blockType),
|
||||
blockValue: mkSimpleSelector(app => app.blockValue),
|
||||
studioView: mkSimpleSelector(app => app.studioView),
|
||||
learningContextId: mkSimpleSelector(app => app.learningContextId),
|
||||
editorInitialized: mkSimpleSelector(app => app.editorInitialized),
|
||||
saveResponse: mkSimpleSelector(app => app.saveResponse),
|
||||
@@ -55,6 +56,7 @@ export const displayTitle = createSelector(
|
||||
: blockType[0].toUpperCase() + blockType.substring(1);
|
||||
},
|
||||
);
|
||||
|
||||
export const analytics = createSelector(
|
||||
[
|
||||
module.simpleSelectors.blockId,
|
||||
@@ -66,10 +68,24 @@ export const analytics = createSelector(
|
||||
),
|
||||
);
|
||||
|
||||
export const isRaw = createSelector(
|
||||
[module.simpleSelectors.studioView],
|
||||
(studioView) => {
|
||||
if (!studioView || !studioView.data || !studioView.data.html) {
|
||||
return null;
|
||||
}
|
||||
if (studioView.data.html.includes('data-editor="raw"')) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
);
|
||||
|
||||
export default {
|
||||
...simpleSelectors,
|
||||
isInitialized,
|
||||
returnUrl,
|
||||
displayTitle,
|
||||
analytics,
|
||||
isRaw,
|
||||
};
|
||||
|
||||
@@ -45,6 +45,7 @@ describe('app selectors unit tests', () => {
|
||||
simpleKeys.studioEndpointUrl,
|
||||
simpleKeys.unitUrl,
|
||||
simpleKeys.blockTitle,
|
||||
simpleKeys.studioView,
|
||||
].map(testSimpleSelector);
|
||||
});
|
||||
});
|
||||
@@ -111,4 +112,31 @@ describe('app selectors unit tests', () => {
|
||||
expect(selectors.displayTitle.cb('random', null)).toEqual('Random');
|
||||
});
|
||||
});
|
||||
|
||||
describe('isRaw', () => {
|
||||
const studioViewRaw = {
|
||||
data: {
|
||||
html: 'data-editor="raw"',
|
||||
},
|
||||
};
|
||||
const studioViewVisual = {
|
||||
data: {
|
||||
html: 'sOmEthIngElse',
|
||||
},
|
||||
};
|
||||
it('is memoized based on studioView', () => {
|
||||
expect(selectors.isRaw.preSelectors).toEqual([
|
||||
simpleSelectors.studioView,
|
||||
]);
|
||||
});
|
||||
it('returns null if studioView is null', () => {
|
||||
expect(selectors.isRaw.cb(null)).toEqual(null);
|
||||
});
|
||||
it('returns true if studioView is raw', () => {
|
||||
expect(selectors.isRaw.cb(studioViewRaw)).toEqual(true);
|
||||
});
|
||||
it('returns false if the studioView is not Raw', () => {
|
||||
expect(selectors.isRaw.cb(studioViewVisual)).toEqual(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -7,9 +7,11 @@ import { RequestStates, RequestKeys } from '../../constants/requests';
|
||||
const initialState = {
|
||||
[RequestKeys.fetchUnit]: { status: RequestStates.inactive },
|
||||
[RequestKeys.fetchBlock]: { status: RequestStates.inactive },
|
||||
[RequestKeys.fetchStudioView]: { status: RequestStates.inactive },
|
||||
[RequestKeys.saveBlock]: { status: RequestStates.inactive },
|
||||
[RequestKeys.fetchImages]: { status: RequestStates.inactive },
|
||||
[RequestKeys.uploadImage]: { status: RequestStates.inactive },
|
||||
|
||||
};
|
||||
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
|
||||
@@ -10,6 +10,13 @@ export const fetchBlock = () => (dispatch) => {
|
||||
}));
|
||||
};
|
||||
|
||||
export const fetchStudioView = () => (dispatch) => {
|
||||
dispatch(requests.fetchStudioView({
|
||||
onSuccess: (response) => dispatch(actions.app.setStudioView(response)),
|
||||
onFailure: (e) => dispatch(actions.app.setStudioView(e)),
|
||||
}));
|
||||
};
|
||||
|
||||
export const fetchUnit = () => (dispatch) => {
|
||||
dispatch(requests.fetchUnit({
|
||||
onSuccess: (response) => dispatch(actions.app.setUnitUrl(response)),
|
||||
@@ -27,6 +34,7 @@ export const initialize = (data) => (dispatch) => {
|
||||
dispatch(actions.app.initialize(data));
|
||||
dispatch(module.fetchBlock());
|
||||
dispatch(module.fetchUnit());
|
||||
dispatch(module.fetchStudioView());
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -67,4 +75,5 @@ export default StrictDict({
|
||||
fetchImages,
|
||||
uploadImage,
|
||||
fetchVideos,
|
||||
fetchStudioView,
|
||||
});
|
||||
|
||||
@@ -8,6 +8,7 @@ jest.mock('./requests', () => ({
|
||||
saveBlock: (args) => ({ saveBlock: args }),
|
||||
fetchImages: (args) => ({ fetchImages: args }),
|
||||
uploadImage: (args) => ({ uploadImage: args }),
|
||||
fetchStudioView: (args) => ({ fetchStudioView: args }),
|
||||
}));
|
||||
|
||||
jest.mock('../../../utils', () => ({
|
||||
@@ -37,6 +38,27 @@ describe('app thunkActions', () => {
|
||||
expect(dispatch).toHaveBeenCalledWith(actions.app.setBlockValue(testValue));
|
||||
});
|
||||
});
|
||||
|
||||
describe('fetchStudioView', () => {
|
||||
beforeEach(() => {
|
||||
thunkActions.fetchStudioView()(dispatch);
|
||||
[[dispatchedAction]] = dispatch.mock.calls;
|
||||
});
|
||||
it('dispatches fetchStudioView action', () => {
|
||||
expect(dispatchedAction.fetchStudioView).not.toEqual(undefined);
|
||||
});
|
||||
it('dispatches actions.app.setStudioViewe on success', () => {
|
||||
dispatch.mockClear();
|
||||
dispatchedAction.fetchStudioView.onSuccess(testValue);
|
||||
expect(dispatch).toHaveBeenCalledWith(actions.app.setStudioView(testValue));
|
||||
});
|
||||
it('dispatches setStudioView on failure', () => {
|
||||
dispatch.mockClear();
|
||||
dispatchedAction.fetchStudioView.onFailure(testValue);
|
||||
expect(dispatch).toHaveBeenCalledWith(actions.app.setStudioView(testValue));
|
||||
});
|
||||
});
|
||||
|
||||
describe('fetchUnit', () => {
|
||||
beforeEach(() => {
|
||||
thunkActions.fetchUnit()(dispatch);
|
||||
@@ -58,17 +80,20 @@ describe('app thunkActions', () => {
|
||||
});
|
||||
describe('initialize', () => {
|
||||
it('dispatches actions.app.initialize, and then fetches both block and unit', () => {
|
||||
const { fetchBlock, fetchUnit } = thunkActions;
|
||||
const { fetchBlock, fetchUnit, fetchStudioView } = thunkActions;
|
||||
thunkActions.fetchBlock = () => 'fetchBlock';
|
||||
thunkActions.fetchUnit = () => 'fetchUnit';
|
||||
thunkActions.fetchStudioView = () => 'fetchStudioView';
|
||||
thunkActions.initialize(testValue)(dispatch);
|
||||
expect(dispatch.mock.calls).toEqual([
|
||||
[actions.app.initialize(testValue)],
|
||||
[thunkActions.fetchBlock()],
|
||||
[thunkActions.fetchUnit()],
|
||||
[thunkActions.fetchStudioView()],
|
||||
]);
|
||||
thunkActions.fetchBlock = fetchBlock;
|
||||
thunkActions.fetchUnit = fetchUnit;
|
||||
thunkActions.fetchStudioView = fetchStudioView;
|
||||
});
|
||||
});
|
||||
describe('saveBlock', () => {
|
||||
|
||||
@@ -50,6 +50,23 @@ export const fetchBlock = ({ ...rest }) => (dispatch, getState) => {
|
||||
}));
|
||||
};
|
||||
|
||||
/**
|
||||
* Tracked fetchStudioView api method.
|
||||
* Tracked to the `fetchBlock` request key.
|
||||
* @param {[func]} onSuccess - onSuccess method ((response) => { ... })
|
||||
* @param {[func]} onFailure - onFailure method ((error) => { ... })
|
||||
*/
|
||||
export const fetchStudioView = ({ ...rest }) => (dispatch, getState) => {
|
||||
dispatch(module.networkRequest({
|
||||
requestKey: RequestKeys.fetchStudioView,
|
||||
promise: api.fetchStudioView({
|
||||
studioEndpointUrl: selectors.app.studioEndpointUrl(getState()),
|
||||
blockId: selectors.app.blockId(getState()),
|
||||
}),
|
||||
...rest,
|
||||
}));
|
||||
};
|
||||
|
||||
/**
|
||||
* Tracked fetchByUnitId api method.
|
||||
* Tracked to the `fetchUnit` request key.
|
||||
@@ -111,9 +128,10 @@ export const fetchImages = ({ ...rest }) => (dispatch, getState) => {
|
||||
};
|
||||
|
||||
export default StrictDict({
|
||||
uploadImage,
|
||||
fetchImages,
|
||||
fetchUnit,
|
||||
fetchBlock,
|
||||
fetchImages,
|
||||
fetchStudioView,
|
||||
fetchUnit,
|
||||
saveBlock,
|
||||
uploadImage,
|
||||
});
|
||||
|
||||
@@ -18,6 +18,7 @@ jest.mock('../app/selectors', () => ({
|
||||
|
||||
jest.mock('../../services/cms/api', () => ({
|
||||
fetchBlockById: ({ id, url }) => ({ id, url }),
|
||||
fetchStudioView: ({ id, url }) => ({ id, url }),
|
||||
fetchByUnitId: ({ id, url }) => ({ id, url }),
|
||||
saveBlock: (args) => args,
|
||||
fetchImages: ({ id, url }) => ({ id, url }),
|
||||
@@ -191,6 +192,21 @@ describe('requests thunkActions module', () => {
|
||||
},
|
||||
});
|
||||
});
|
||||
describe('fetchStudioView', () => {
|
||||
testNetworkRequestAction({
|
||||
action: requests.fetchStudioView,
|
||||
args: fetchParams,
|
||||
expectedString: 'with fetchStudioView promise',
|
||||
expectedData: {
|
||||
...fetchParams,
|
||||
requestKey: RequestKeys.fetchStudioView,
|
||||
promise: api.fetchStudioView({
|
||||
studioEndpointUrl: selectors.app.studioEndpointUrl(testState),
|
||||
blockId: selectors.app.blockId(testState),
|
||||
}),
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
describe('fetchImages', () => {
|
||||
let fetchImages;
|
||||
|
||||
@@ -11,6 +11,9 @@ export const apiMethods = {
|
||||
fetchByUnitId: ({ blockId, studioEndpointUrl }) => get(
|
||||
urls.blockAncestor({ studioEndpointUrl, blockId }),
|
||||
),
|
||||
fetchStudioView: ({ blockId, studioEndpointUrl }) => get(
|
||||
urls.blockStudioView({ studioEndpointUrl, blockId }),
|
||||
),
|
||||
fetchImages: ({ learningContextId, studioEndpointUrl }) => get(
|
||||
urls.courseImages({ studioEndpointUrl, learningContextId }),
|
||||
),
|
||||
|
||||
@@ -15,6 +15,7 @@ jest.mock('../../../utils', () => {
|
||||
jest.mock('./urls', () => ({
|
||||
block: jest.fn().mockName('urls.block'),
|
||||
blockAncestor: jest.fn().mockName('urls.blockAncestor'),
|
||||
blockStudioView: jest.fn().mockName('urls.StudioView'),
|
||||
courseImages: jest.fn().mockName('urls.courseImages'),
|
||||
courseAssets: jest.fn().mockName('urls.courseAssets'),
|
||||
}));
|
||||
@@ -50,6 +51,13 @@ describe('cms api', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('fetchStudioView', () => {
|
||||
it('should call get with url.blockStudioView', () => {
|
||||
apiMethods.fetchStudioView({ blockId, studioEndpointUrl });
|
||||
expect(get).toHaveBeenCalledWith(urls.blockStudioView({ studioEndpointUrl, blockId }));
|
||||
});
|
||||
});
|
||||
|
||||
describe('fetchImages', () => {
|
||||
it('should call get with url.courseImages', () => {
|
||||
apiMethods.fetchImages({ learningContextId, studioEndpointUrl });
|
||||
|
||||
@@ -13,11 +13,22 @@ export const fetchBlockById = ({ blockId, studioEndpointUrl }) => mockPromise({
|
||||
},
|
||||
});
|
||||
|
||||
// TODO: update to return block data appropriate per block ID, which will equal block type
|
||||
// eslint-disable-next-line
|
||||
export const fetchStudioView = ({ blockId, studioEndpointUrl }) => mockPromise({
|
||||
data: {
|
||||
data_editor: 'raw',
|
||||
data: '<p>Test prompt content</p>',
|
||||
display_name: 'My Text Prompt',
|
||||
},
|
||||
});
|
||||
|
||||
// TODO: update to return block data appropriate per block ID, which will equal block type
|
||||
// eslint-disable-next-line
|
||||
export const fetchByUnitId = ({ blockId, studioEndpointUrl }) => mockPromise({
|
||||
data: { ancestors: [{ id: 'unitUrl' }] },
|
||||
});
|
||||
|
||||
// eslint-disable-next-line
|
||||
export const fetchImages = ({ learningContextId, studioEndpointUrl }) => mockPromise({
|
||||
data: {
|
||||
|
||||
@@ -23,6 +23,10 @@ export const blockAncestor = ({ studioEndpointUrl, blockId }) => (
|
||||
`${block({ studioEndpointUrl, blockId })}?fields=ancestorInfo`
|
||||
);
|
||||
|
||||
export const blockStudioView = ({ studioEndpointUrl, blockId }) => (
|
||||
`${block({ studioEndpointUrl, blockId })}/studio_view`
|
||||
);
|
||||
|
||||
export const courseAssets = ({ studioEndpointUrl, learningContextId }) => (
|
||||
`${studioEndpointUrl}/assets/${learningContextId}/`
|
||||
);
|
||||
|
||||
@@ -4,6 +4,7 @@ import {
|
||||
libraryV1,
|
||||
block,
|
||||
blockAncestor,
|
||||
blockStudioView,
|
||||
courseAssets,
|
||||
courseImages,
|
||||
} from './urls';
|
||||
@@ -57,6 +58,13 @@ describe('cms url methods', () => {
|
||||
.toEqual(`${block({ studioEndpointUrl, blockId })}?fields=ancestorInfo`);
|
||||
});
|
||||
});
|
||||
describe('blockStudioView', () => {
|
||||
it('returns url with studioEndpointUrl, blockId and studio_view query', () => {
|
||||
expect(blockStudioView({ studioEndpointUrl, blockId }))
|
||||
.toEqual(`${block({ studioEndpointUrl, blockId })}/studio_view`);
|
||||
});
|
||||
});
|
||||
|
||||
describe('courseAssets', () => {
|
||||
it('returns url with studioEndpointUrl and learningContextId', () => {
|
||||
expect(courseAssets({ studioEndpointUrl, learningContextId }))
|
||||
|
||||
Reference in New Issue
Block a user