diff --git a/src/course-home/outline-tab/LmsHtmlFragment.jsx b/src/course-home/outline-tab/LmsHtmlFragment.jsx index a07c06548b..778e7d79d8 100644 --- a/src/course-home/outline-tab/LmsHtmlFragment.jsx +++ b/src/course-home/outline-tab/LmsHtmlFragment.jsx @@ -30,7 +30,7 @@ const LmsHtmlFragment = ({ const iframe = useRef(null); function resetIframeHeight() { if (iframe?.current?.contentWindow?.document?.body) { - iframe.current.height = iframe.current.contentWindow.document.body.scrollHeight; + iframe.current.height = iframe.current.contentWindow.document.body.parentNode.scrollHeight; } } diff --git a/src/course-home/outline-tab/OutlineTab.test.jsx b/src/course-home/outline-tab/OutlineTab.test.jsx index ba536adaa0..47ceed621d 100644 --- a/src/course-home/outline-tab/OutlineTab.test.jsx +++ b/src/course-home/outline-tab/OutlineTab.test.jsx @@ -282,6 +282,22 @@ describe('Outline Tab', () => { }); }); + it('ignores comments and misformatted HTML', async () => { + setTabData({ + welcome_message_html: '

' + + '' + + '' + + 'Test welcome message that happens to be longer than one hundred words because of comments but displayed content is less.' + + 'It should not be shortened.' + + '' + + '' + + '

', + }); + await fetchAndRender(); + const showMoreButton = screen.queryByRole('button', { name: 'Show More' }); + expect(showMoreButton).not.toBeInTheDocument(); + }); + it('does not display if no update available', async () => { setTabData({ welcome_message_html: null }); await fetchAndRender(); diff --git a/src/course-home/outline-tab/widgets/WelcomeMessage.jsx b/src/course-home/outline-tab/widgets/WelcomeMessage.jsx index eeee2568ab..cca757d666 100644 --- a/src/course-home/outline-tab/widgets/WelcomeMessage.jsx +++ b/src/course-home/outline-tab/widgets/WelcomeMessage.jsx @@ -1,4 +1,4 @@ -import React, { useState } from 'react'; +import React, { useState, useMemo } from 'react'; import PropTypes from 'prop-types'; import { injectIntl, intlShape } from '@edx/frontend-platform/i18n'; @@ -18,8 +18,22 @@ const WelcomeMessage = ({ courseId, intl }) => { const [display, setDisplay] = useState(true); - const shortWelcomeMessageHtml = truncate(welcomeMessageHtml, 100, { byWords: true, keepWhitespaces: true }); - const messageCanBeShortened = shortWelcomeMessageHtml.length < welcomeMessageHtml.length; + // welcomeMessageHtml can contain comments or malformatted HTML which can impact the length that determines + // messageCanBeShortened. We clean it by calling truncate with a length of welcomeMessageHtml.length which + // will not result in a truncation but a formatting into 'truncate-html' canonical format. + const cleanedWelcomeMessageHtml = useMemo( + () => truncate(welcomeMessageHtml, welcomeMessageHtml.length, { keepWhitespaces: true }), + [welcomeMessageHtml], + ); + const shortWelcomeMessageHtml = useMemo( + () => truncate(cleanedWelcomeMessageHtml, 100, { byWords: true, keepWhitespaces: true }), + [cleanedWelcomeMessageHtml], + ); + const messageCanBeShortened = useMemo( + () => (shortWelcomeMessageHtml.length < cleanedWelcomeMessageHtml.length), + [cleanedWelcomeMessageHtml, shortWelcomeMessageHtml], + ); + const [showShortMessage, setShowShortMessage] = useState(messageCanBeShortened); const dispatch = useDispatch(); @@ -63,7 +77,7 @@ const WelcomeMessage = ({ courseId, intl }) => { className="inline-link" data-testid="long-welcome-message-iframe" key="full-html" - html={welcomeMessageHtml} + html={cleanedWelcomeMessageHtml} title={intl.formatMessage(messages.welcomeMessage)} /> )}