diff --git a/src/courseware/course/sequence/Unit/ContentIFrame.jsx b/src/courseware/course/sequence/Unit/ContentIFrame.jsx
index db60630f77..ab2652fdcd 100644
--- a/src/courseware/course/sequence/Unit/ContentIFrame.jsx
+++ b/src/courseware/course/sequence/Unit/ContentIFrame.jsx
@@ -74,7 +74,7 @@ const ContentIFrame = ({
)}
- {modalOptions.open && (
+ {modalOptions.isOpen && (
{ modalOptions.body }
@@ -84,7 +84,7 @@ const ContentIFrame = ({
allow={IFRAME_FEATURE_POLICY}
frameBorder="0"
src={modalOptions.url}
- style={{ width: '100%', height: '100vh' }}
+ style={{ width: '100%', height: modalOptions.height }}
/>
)}
dialogClassName="modal-lti"
diff --git a/src/courseware/course/sequence/Unit/ContentIFrame.test.jsx b/src/courseware/course/sequence/Unit/ContentIFrame.test.jsx
index eaf540cf82..32f36ccf0b 100644
--- a/src/courseware/course/sequence/Unit/ContentIFrame.test.jsx
+++ b/src/courseware/course/sequence/Unit/ContentIFrame.test.jsx
@@ -29,16 +29,17 @@ const iframeBehavior = {
const modalOptions = {
closed: {
- open: false,
+ isOpen: false,
},
withBody: {
body: 'test-body',
- open: true,
+ isOpen: true,
},
withUrl: {
- open: true,
+ isOpen: true,
title: 'test-modal-title',
url: 'test-modal-url',
+ height: 'test-height',
},
};
@@ -83,7 +84,7 @@ describe('ContentIFrame Component', () => {
});
describe('output', () => {
let component;
- describe('shouldShowContent', () => {
+ describe('if shouldShowContent', () => {
describe('if not hasLoaded', () => {
it('displays errorPage if showError', () => {
hooks.useIFrameBehavior.mockReturnValueOnce({ ...iframeBehavior, showError: true });
@@ -121,7 +122,7 @@ describe('ContentIFrame Component', () => {
});
});
});
- describe('not shouldShowContent', () => {
+ describe('if not shouldShowContent', () => {
it('does not show PageLoading, ErrorPage, or unit-iframe-wrapper', () => {
el = shallow();
expect(el.instance.findByType(PageLoading).length).toEqual(0);
@@ -129,13 +130,13 @@ describe('ContentIFrame Component', () => {
expect(el.instance.findByTestId(testIDs.contentIFrame).length).toEqual(0);
});
});
- it('does not display modal if modalOptions returns open: false', () => {
+ it('does not display modal if modalOptions returns isOpen: false', () => {
el = shallow();
expect(el.instance.findByType(Modal).length).toEqual(0);
});
- describe('if modalOptions.open', () => {
+ describe('if modalOptions.isOpen', () => {
const testModalOpenAndHandleClose = () => {
- test('Modal component is open, with handleModalClose from hook', () => {
+ test('Modal component isOpen, with handleModalClose from hook', () => {
expect(component.props.onClose).toEqual(modalIFrameData.handleModalClose);
});
};
@@ -164,7 +165,7 @@ describe('ContentIFrame Component', () => {
allow={IFRAME_FEATURE_POLICY}
frameBorder="0"
src={modalOptions.withUrl.url}
- style={{ width: '100%', height: '100vh' }}
+ style={{ width: '100%', height: modalOptions.withUrl.height }}
/>,
);
});
diff --git a/src/courseware/course/sequence/Unit/hooks/useModalIFrameData.js b/src/courseware/course/sequence/Unit/hooks/useModalIFrameData.js
index 3d12220f7e..e340ea34ac 100644
--- a/src/courseware/course/sequence/Unit/hooks/useModalIFrameData.js
+++ b/src/courseware/course/sequence/Unit/hooks/useModalIFrameData.js
@@ -5,28 +5,32 @@ import { StrictDict, useKeyedState } from '@edx/react-unit-test-utils/dist';
import { useEventListener } from '../../../../../generic/hooks';
export const stateKeys = StrictDict({
- modalOptions: 'modalOptions',
+ isOpen: 'isOpen',
+ options: 'options',
});
+export const DEFAULT_HEIGHT = '100vh';
+
const useModalIFrameBehavior = () => {
- const [modalOptions, setModalOptions] = useKeyedState(stateKeys.modalOptions, ({ open: false }));
+ const [isOpen, setIsOpen] = useKeyedState(stateKeys.isOpen, false);
+ const [options, setOptions] = useKeyedState(stateKeys.options, { height: DEFAULT_HEIGHT });
const receiveMessage = React.useCallback(({ data }) => {
const { type, payload } = data;
if (type === 'plugin.modal') {
- payload.open = true;
- setModalOptions(payload);
+ setOptions((current) => ({ ...current, ...payload }));
+ setIsOpen(true);
}
}, []);
useEventListener('message', receiveMessage);
const handleModalClose = () => {
- setModalOptions({ open: false });
+ setIsOpen(false);
};
return {
handleModalClose,
- modalOptions,
+ modalOptions: { isOpen, ...options },
};
};
diff --git a/src/courseware/course/sequence/Unit/hooks/useModalIFrameData.test.js b/src/courseware/course/sequence/Unit/hooks/useModalIFrameData.test.js
index 4c6bd9f7cf..d1788847c0 100644
--- a/src/courseware/course/sequence/Unit/hooks/useModalIFrameData.test.js
+++ b/src/courseware/course/sequence/Unit/hooks/useModalIFrameData.test.js
@@ -2,7 +2,7 @@ import { mockUseKeyedState } from '@edx/react-unit-test-utils';
import { useEventListener } from '../../../../../generic/hooks';
import { messageTypes } from '../constants';
-import useModalIFrameBehavior, { stateKeys } from './useModalIFrameData';
+import useModalIFrameBehavior, { stateKeys, DEFAULT_HEIGHT } from './useModalIFrameData';
jest.mock('react', () => ({
...jest.requireActual('react'),
@@ -20,31 +20,49 @@ describe('useModalIFrameBehavior', () => {
state.mock();
});
describe('behavior', () => {
- it('initializes modalOptions to closed', () => {
+ it('initializes isOpen to false', () => {
useModalIFrameBehavior();
- state.expectInitializedWith(stateKeys.modalOptions, { open: false });
+ state.expectInitializedWith(stateKeys.isOpen, false);
+ });
+ it('initializes options with default height', () => {
+ useModalIFrameBehavior();
+ state.expectInitializedWith(stateKeys.options, { height: DEFAULT_HEIGHT });
});
describe('eventListener', () => {
it('consumes modal events and opens sets modal options with open: true', () => {
+ const oldOptions = { some: 'old', options: 'yeah' };
+ state.mockVals({
+ [stateKeys.isOpen]: false,
+ [stateKeys.options]: oldOptions,
+ });
useModalIFrameBehavior();
expect(useEventListener).toHaveBeenCalled();
const { cb, prereqs } = useEventListener.mock.calls[0][1];
expect(prereqs).toEqual([]);
const payload = { test: 'values' };
cb({ data: { type: messageTypes.modal, payload } });
- expect(state.setState.modalOptions).toHaveBeenCalledWith({ ...payload, open: true });
+ expect(state.setState.isOpen).toHaveBeenCalledWith(true);
+ expect(state.setState.options).toHaveBeenCalled();
+ const [[setOptionsCb]] = state.setState.options.mock.calls;
+ expect(setOptionsCb(oldOptions)).toEqual({ ...oldOptions, ...payload });
});
});
});
describe('output', () => {
test('handleModalClose sets modal options to closed', () => {
useModalIFrameBehavior().handleModalClose();
- state.expectSetStateCalledWith(stateKeys.modalOptions, { open: false });
+ state.expectSetStateCalledWith(stateKeys.isOpen, false);
});
- it('forwards modalOptions from state value', () => {
+ it('forwards modalOptions from state values', () => {
const modalOptions = { test: 'options' };
- state.mockVal(stateKeys.modalOptions, modalOptions);
- expect(useModalIFrameBehavior().modalOptions).toEqual(modalOptions);
+ state.mockVals({
+ [stateKeys.options]: modalOptions,
+ [stateKeys.isOpen]: true,
+ });
+ expect(useModalIFrameBehavior().modalOptions).toEqual({
+ ...modalOptions,
+ isOpen: true,
+ });
});
});
});