Skip to content

Commit be82e96

Browse files
authored
feat: add xblockScroll event handler to iframeMessageTypes (#2363)
* fix: new message type to scroll outer window to xblock location * fix: reset after testing * fix: formatting * test: add test coverage * fix: fix test mocks * fix: formatting * fix: add smooth to scroll
1 parent b2203f0 commit be82e96

File tree

3 files changed

+47
-1
lines changed

3 files changed

+47
-1
lines changed

src/constants.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,4 +105,5 @@ export const iframeMessageTypes = {
105105
resize: 'plugin.resize',
106106
videoFullScreen: 'plugin.videoFullScreen',
107107
xblockEvent: 'xblock-event',
108+
xblockScroll: 'xblock-scroll',
108109
};

src/generic/hooks/tests/hooks.test.tsx

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,8 +122,42 @@ describe('useIframeBehavior', () => {
122122
expect(setWindowTopOffset).toHaveBeenCalledWith(window.scrollY);
123123
});
124124

125+
it('handles xblockScroll message correctly', () => {
126+
const iframeElement = document.createElement('iframe');
127+
iframeElement.setAttribute('name', 'xblock-iframe');
128+
Object.defineProperty(iframeElement, 'offsetTop', { writable: true, configurable: true, value: 50 });
129+
130+
const iframeParentElement = document.createElement('div');
131+
iframeParentElement.setAttribute('id', 'div0');
132+
Object.defineProperty(iframeParentElement, 'offsetTop', { writable: true, configurable: true, value: 25 });
133+
134+
iframeParentElement.appendChild(iframeElement);
135+
document.body.appendChild(iframeParentElement);
136+
137+
renderHook(() => useIframeBehavior({ id, iframeUrl, iframeRef }));
138+
139+
const message = {
140+
data: {
141+
type: iframeMessageTypes.xblockScroll,
142+
offset: 100,
143+
},
144+
};
145+
146+
act(() => {
147+
window.dispatchEvent(new MessageEvent('message', message));
148+
});
149+
150+
expect(window.scrollTo).toHaveBeenCalledWith({ top: 175, left: 0, behavior: 'smooth' });
151+
expect(window.scrollY).toBe(100 + document.getElementsByName('xblock-iframe')[0].offsetTop + document.getElementsByName('xblock-iframe')[0]!.parentElement!.offsetTop);
152+
});
153+
125154
it('handles offset message correctly', () => {
126-
document.body.innerHTML = '<div id="unit-iframe" style="position: absolute; top: 50px;"></div>';
155+
const iframeElement = document.createElement('iframe');
156+
iframeElement.setAttribute('id', 'unit-iframe');
157+
Object.defineProperty(iframeElement, 'offsetTop', { writable: true, configurable: true, value: 50 });
158+
159+
document.body.appendChild(iframeElement);
160+
127161
renderHook(() => useIframeBehavior({ id, iframeUrl, iframeRef }));
128162

129163
const message = {
@@ -134,6 +168,7 @@ describe('useIframeBehavior', () => {
134168
window.dispatchEvent(new MessageEvent('message', message));
135169
});
136170

171+
expect(window.scrollTo).toHaveBeenCalledWith(0, 150);
137172
expect(window.scrollY).toBe(100 + (document.getElementById('unit-iframe') as HTMLElement).offsetTop);
138173
});
139174

src/generic/hooks/useIframeBehavior.tsx

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,16 @@ export const useIframeBehavior = ({
8383
});
8484
}
8585
break;
86+
case iframeMessageTypes.xblockScroll:
87+
if (document.getElementsByName('xblock-iframe')) {
88+
const iframeElement = document.getElementsByName('xblock-iframe')[0];
89+
window.scrollTo({
90+
top: data.offset + iframeElement!.offsetTop + iframeElement.parentElement!.offsetTop,
91+
left: 0,
92+
behavior: 'smooth',
93+
});
94+
}
95+
break;
8696
default:
8797
if (data.offset) {
8898
// We listen for this message from LMS to know when the page needs to

0 commit comments

Comments
 (0)