diff --git a/src/courseware/course/sequence/Unit.jsx b/src/courseware/course/sequence/Unit.jsx index 1e80ff70..2c11e000 100644 --- a/src/courseware/course/sequence/Unit.jsx +++ b/src/courseware/course/sequence/Unit.jsx @@ -70,6 +70,15 @@ function useLoadBearingHook(id) { }, [id]); } +export function sendUrlHashToFrame(frame) { + const { hash } = window.location; + if (hash) { + // The url hash will be sent to LMS-served iframe in order to find the location of the + // hash within the iframe. + frame.contentWindow.postMessage({ hashName: hash }, `${getConfig().LMS_BASE_URL}`); + } +} + function Unit({ courseId, format, @@ -98,13 +107,13 @@ function Unit({ } = course; const dispatch = useDispatch(); - // Do not remove this hook. See function description. useLoadBearingHook(id); // We use this ref so that we can hold a reference to the currently active event listener. const messageEventListenerRef = useRef(null); useEffect(() => { + sendUrlHashToFrame(document.getElementById('unit-iframe')); function receiveMessage(event) { const { type, payload } = event.data; if (type === 'plugin.resize') { @@ -120,7 +129,7 @@ function Unit({ setModalOptions(payload); } else if (event.data.offset) { // We listen for this message from LMS to know when the page needs to - // be scroll to another location on the page. + // be scrolled to another location on the page. window.scrollTo(0, event.data.offset); } } diff --git a/src/courseware/course/sequence/Unit.test.jsx b/src/courseware/course/sequence/Unit.test.jsx index 02ba79a7..e3ee3149 100644 --- a/src/courseware/course/sequence/Unit.test.jsx +++ b/src/courseware/course/sequence/Unit.test.jsx @@ -3,7 +3,7 @@ import { Factory } from 'rosie'; import { initializeTestStore, loadUnit, messageEvent, render, screen, waitFor, } from '../../../setupTest'; -import Unit from './Unit'; +import Unit, { sendUrlHashToFrame } from './Unit'; describe('Unit', () => { let mockData; @@ -38,7 +38,6 @@ describe('Unit', () => { it('renders correctly', () => { render(); - expect(screen.getByText('Loading learning sequence...')).toBeInTheDocument(); const renderedUnit = screen.getByTitle(unit.display_name); expect(renderedUnit).toHaveAttribute('height', String(0)); @@ -49,7 +48,6 @@ describe('Unit', () => { it('renders proper message for gated content', () => { render(); - expect(screen.getByText('Loading learning sequence...')).toBeInTheDocument(); expect(screen.getByText('Loading locked content messaging...')).toBeInTheDocument(); }); @@ -75,7 +73,6 @@ describe('Unit', () => { it('handles receiving MessageEvent', async () => { render(); loadUnit(); - // Loading message is gone now. await waitFor(() => expect(screen.queryByText('Loading learning sequence...')).not.toBeInTheDocument()); // Iframe's height is set via message. @@ -125,4 +122,37 @@ describe('Unit', () => { { timeout: 100 }, )).rejects.toThrowError(/Expected the element to have attribute/); }); + + it('scrolls to correct place onLoad', () => { + document.body.innerHTML = "