diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/ExplanationWidget/index.jsx b/src/editors/containers/ProblemEditor/components/EditProblemView/ExplanationWidget/index.jsx index d0fe8eb33..86298d5d9 100644 --- a/src/editors/containers/ProblemEditor/components/EditProblemView/ExplanationWidget/index.jsx +++ b/src/editors/containers/ProblemEditor/components/EditProblemView/ExplanationWidget/index.jsx @@ -16,10 +16,12 @@ export const ExplanationWidget = ({ intl, }) => { const { editorRef, refReady, setEditorRef } = prepareEditorRef(); - const solutionContent = replaceStaticWithAsset({ - initialContent: settings?.solutionExplanation || '', + const initialContent = settings?.solutionExplanation || ''; + const newContent = replaceStaticWithAsset({ + initialContent, learningContextId, }); + const solutionContent = newContent || initialContent; if (!refReady) { return null; } return (
diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/ExplanationWidget/index.test.jsx b/src/editors/containers/ProblemEditor/components/EditProblemView/ExplanationWidget/index.test.jsx index 48f784b6a..6e22712c2 100644 --- a/src/editors/containers/ProblemEditor/components/EditProblemView/ExplanationWidget/index.test.jsx +++ b/src/editors/containers/ProblemEditor/components/EditProblemView/ExplanationWidget/index.test.jsx @@ -1,4 +1,3 @@ -/* eslint-disable react/prop-types */ import React from 'react'; import { shallow } from '@edx/react-unit-test-utils'; import { formatMessage } from '../../../../../../testUtils'; @@ -24,11 +23,11 @@ jest.mock('../../../../../data/redux', () => ({ })); jest.mock('../../../../../sharedComponents/TinyMceWidget/hooks', () => ({ + ...jest.requireActual('../../../../../sharedComponents/TinyMceWidget/hooks'), prepareEditorRef: jest.fn(() => ({ refReady: true, setEditorRef: jest.fn().mockName('prepareEditorRef.setEditorRef'), })), - replaceStaticWithAsset: jest.fn(() => 'This is my solution'), })); describe('SolutionWidget', () => { diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/QuestionWidget/index.jsx b/src/editors/containers/ProblemEditor/components/EditProblemView/QuestionWidget/index.jsx index 6be330f5a..5580975bf 100644 --- a/src/editors/containers/ProblemEditor/components/EditProblemView/QuestionWidget/index.jsx +++ b/src/editors/containers/ProblemEditor/components/EditProblemView/QuestionWidget/index.jsx @@ -16,10 +16,12 @@ export const QuestionWidget = ({ intl, }) => { const { editorRef, refReady, setEditorRef } = prepareEditorRef(); - const questionContent = replaceStaticWithAsset({ - initialContent: question, + const initialContent = question; + const newContent = replaceStaticWithAsset({ + initialContent, learningContextId, }); + const questionContent = newContent || initialContent; if (!refReady) { return null; } return (
diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/QuestionWidget/index.test.jsx b/src/editors/containers/ProblemEditor/components/EditProblemView/QuestionWidget/index.test.jsx index d18a6bc38..6602eb1ae 100644 --- a/src/editors/containers/ProblemEditor/components/EditProblemView/QuestionWidget/index.test.jsx +++ b/src/editors/containers/ProblemEditor/components/EditProblemView/QuestionWidget/index.test.jsx @@ -1,4 +1,3 @@ -/* eslint-disable react/prop-types */ import React from 'react'; import { shallow } from '@edx/react-unit-test-utils'; import { formatMessage } from '../../../../../../testUtils'; @@ -29,11 +28,11 @@ jest.mock('../../../../../data/redux', () => ({ })); jest.mock('../../../../../sharedComponents/TinyMceWidget/hooks', () => ({ + ...jest.requireActual('../../../../../sharedComponents/TinyMceWidget/hooks'), prepareEditorRef: jest.fn(() => ({ refReady: true, setEditorRef: jest.fn().mockName('prepareEditorRef.setEditorRef'), })), - replaceStaticWithAsset: jest.fn(() => 'This is my question'), })); describe('QuestionWidget', () => { diff --git a/src/editors/containers/TextEditor/__snapshots__/index.test.jsx.snap b/src/editors/containers/TextEditor/__snapshots__/index.test.jsx.snap index 3273658c8..9a2b33196 100644 --- a/src/editors/containers/TextEditor/__snapshots__/index.test.jsx.snap +++ b/src/editors/containers/TextEditor/__snapshots__/index.test.jsx.snap @@ -191,3 +191,52 @@ exports[`TextEditor snapshots renders as expected with default behavior 1`] = `
`; + +exports[`TextEditor snapshots renders static images with relative paths 1`] = ` + +
+ + + + <[object Object] + editorContentHtml="eDiTablE Text with " + editorRef={ + { + "current": { + "value": "something", + }, + } + } + editorType="text" + height="100%" + initializeEditor={[MockFunction args.intializeEditor]} + minHeight={500} + setEditorRef={[MockFunction hooks.prepareEditorRef.setEditorRef]} + /> +
+
+`; diff --git a/src/editors/containers/TextEditor/index.jsx b/src/editors/containers/TextEditor/index.jsx index a8e0a9286..c349a593e 100644 --- a/src/editors/containers/TextEditor/index.jsx +++ b/src/editors/containers/TextEditor/index.jsx @@ -32,10 +32,12 @@ export const TextEditor = ({ intl, }) => { const { editorRef, refReady, setEditorRef } = prepareEditorRef(); - const editorContent = blockValue ? replaceStaticWithAsset({ - initialContent: blockValue.data.data, + const initialContent = blockValue ? blockValue.data.data : ''; + const newContent = replaceStaticWithAsset({ + initialContent, learningContextId, - }) : ''; + }); + const editorContent = newContent || initialContent; if (!refReady) { return null; } diff --git a/src/editors/containers/TextEditor/index.test.jsx b/src/editors/containers/TextEditor/index.test.jsx index 9268d533e..17e813ac0 100644 --- a/src/editors/containers/TextEditor/index.test.jsx +++ b/src/editors/containers/TextEditor/index.test.jsx @@ -25,12 +25,12 @@ jest.mock('./hooks', () => ({ })); jest.mock('../../sharedComponents/TinyMceWidget/hooks', () => ({ + ...jest.requireActual('../../sharedComponents/TinyMceWidget/hooks'), prepareEditorRef: jest.fn(() => ({ editorRef: { current: { value: 'something' } }, refReady: true, setEditorRef: jest.fn().mockName('hooks.prepareEditorRef.setEditorRef'), })), - replaceStaticWithAsset: jest.fn(() => 'eDiTablE Text'), })); jest.mock('react', () => { @@ -88,6 +88,13 @@ describe('TextEditor', () => { test('renders as expected with default behavior', () => { expect(shallow().snapshot).toMatchSnapshot(); }); + test('renders static images with relative paths', () => { + const updatedProps = { + ...props, + blockValue: { data: { data: 'eDiTablE Text with ' } }, + }; + expect(shallow().snapshot).toMatchSnapshot(); + }); test('not yet loaded, Spinner appears', () => { expect(shallow().snapshot).toMatchSnapshot(); }); diff --git a/src/editors/sharedComponents/RawEditor/__snapshots__/index.test.jsx.snap b/src/editors/sharedComponents/RawEditor/__snapshots__/index.test.jsx.snap deleted file mode 100644 index 6703b20fb..000000000 --- a/src/editors/sharedComponents/RawEditor/__snapshots__/index.test.jsx.snap +++ /dev/null @@ -1,52 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`RawEditor renders as expected with content equal to null 1`] = ` -
- - You are using the raw - html - editor. - -
-`; - -exports[`RawEditor renders as expected with default behavior 1`] = ` -
- - You are using the raw - html - editor. - - -
-`; - -exports[`RawEditor renders as expected with lang equal to xml 1`] = ` -
- -
-`; diff --git a/src/editors/sharedComponents/RawEditor/index.jsx b/src/editors/sharedComponents/RawEditor/index.jsx index cdb6999c3..1f507f3ab 100644 --- a/src/editors/sharedComponents/RawEditor/index.jsx +++ b/src/editors/sharedComponents/RawEditor/index.jsx @@ -3,6 +3,7 @@ import PropTypes from 'prop-types'; import { Alert } from '@openedx/paragon'; import CodeEditor from '../CodeEditor'; +import { setAssetToStaticUrl } from '../TinyMceWidget/hooks'; function getValue(content) { if (!content) { return null; } @@ -15,7 +16,8 @@ export const RawEditor = ({ content, lang, }) => { - const value = getValue(content); + const value = getValue(content) || ''; + const staticUpdate = setAssetToStaticUrl({ editorValue: value }); return (
@@ -27,8 +29,9 @@ export const RawEditor = ({ { value ? ( ) : null} diff --git a/src/editors/sharedComponents/RawEditor/index.test.jsx b/src/editors/sharedComponents/RawEditor/index.test.jsx index 7d3cc3018..848e5070e 100644 --- a/src/editors/sharedComponents/RawEditor/index.test.jsx +++ b/src/editors/sharedComponents/RawEditor/index.test.jsx @@ -1,8 +1,17 @@ import React from 'react'; -import { shallow } from '@edx/react-unit-test-utils'; +import { render, screen } from '@testing-library/react'; +import { IntlProvider } from '@edx/frontend-platform/i18n'; +import '@testing-library/jest-dom/extend-expect'; import { RawEditor } from '.'; +jest.unmock('@openedx/paragon'); + +const renderComponent = (props) => render( + + + , +); describe('RawEditor', () => { const defaultProps = { editorRef: { @@ -10,7 +19,7 @@ describe('RawEditor', () => { value: 'Ref Value', }, }, - content: { data: { data: 'eDiTablE Text' } }, + content: { data: { data: 'eDiTablE Text HtmL' } }, lang: 'html', }; const xmlProps = { @@ -19,7 +28,7 @@ describe('RawEditor', () => { value: 'Ref Value', }, }, - content: { data: { data: 'eDiTablE Text' } }, + content: { data: { data: 'eDiTablE Text XMl' } }, lang: 'xml', }; const noContentProps = { @@ -33,13 +42,39 @@ describe('RawEditor', () => { width: { width: '80%' }, }; - test('renders as expected with default behavior', () => { - expect(shallow().snapshot).toMatchSnapshot(); + it('renders as expected with default behavior', () => { + renderComponent(defaultProps); + expect(screen.getByRole('alert')).toBeVisible(); + + expect(screen.getByText('eDiTablE Text HtmL')).toBeVisible(); }); - test('renders as expected with lang equal to xml', () => { - expect(shallow().snapshot).toMatchSnapshot(); + + it('updates the assets to static srcs', () => { + const updatedProps = { + ...defaultProps, + content: 'pick or ', + }; + renderComponent(updatedProps); + expect(screen.getByText('"/static/img.jpeg"')).toBeVisible(); + + expect(screen.getByText('"/static/img2.jpeg"')).toBeVisible(); + + expect(screen.queryByText('"/asset-v1:org+run+term+type@asset+block@img.jpeg"')).toBeNull(); + + expect(screen.queryByText('"/assets/courseware/v1/hash/asset-v1:org+run+term+type@asset+block/img2.jpeg"')).toBeNull(); }); - test('renders as expected with content equal to null', () => { - expect(shallow().snapshot).toMatchSnapshot(); + + it('renders as expected with lang equal to xml', () => { + renderComponent(xmlProps); + expect(screen.queryByRole('alert')).toBeNull(); + + expect(screen.getByText('eDiTablE Text XMl')).toBeVisible(); + }); + + it('renders as expected with content equal to null', () => { + renderComponent(noContentProps); + expect(screen.getByRole('alert')).toBeVisible(); + + expect(screen.queryByTestId('code-editor')).toBeNull(); }); }); diff --git a/src/editors/sharedComponents/TinyMceWidget/hooks.js b/src/editors/sharedComponents/TinyMceWidget/hooks.js index db67e3109..9a4f1e530 100644 --- a/src/editors/sharedComponents/TinyMceWidget/hooks.js +++ b/src/editors/sharedComponents/TinyMceWidget/hooks.js @@ -403,15 +403,20 @@ export const setAssetToStaticUrl = ({ editorValue, lmsEndpointUrl }) => { let content = editorValue.replace(regExLmsEndpointUrl, ''); const assetSrcs = typeof content === 'string' ? content.split(/(src="|src="|href="|href=")/g) : []; - assetSrcs.forEach(src => { - if (src.startsWith('/asset')) { + assetSrcs.filter(src => src.startsWith('/asset')).forEach(src => { + let nameFromEditorSrc; + if (src.match(/\/assets\/.+\/asset-v1:\S+[+]\S+[@]\S+[+]\S+\//)?.length >= 1) { + const assetBlockName = src.substring(0, src.search(/("|")/)); + const dividedSrc = assetBlockName.split(/\/assets\/.+\/asset-v1:\S+[+]\S+[@]\S+[+]\S+\//); + [, nameFromEditorSrc] = dividedSrc; + } else { const assetBlockName = src.substring(src.indexOf('@') + 1, src.search(/("|")/)); - const nameFromEditorSrc = assetBlockName.substring(assetBlockName.indexOf('@') + 1); - const portableUrl = getStaticUrl({ displayName: nameFromEditorSrc }); - const currentSrc = src.substring(0, src.search(/("|")/)); - const updatedContent = content.replace(currentSrc, portableUrl); - content = updatedContent; + nameFromEditorSrc = assetBlockName.substring(assetBlockName.indexOf('@') + 1); } + const portableUrl = getStaticUrl({ displayName: nameFromEditorSrc }); + const currentSrc = src.substring(0, src.search(/("|")/)); + const updatedContent = content.replace(currentSrc, portableUrl); + content = updatedContent; }); return content; };