feat: allow override of plugin.modal height (#1184)
This commit is contained in:
@@ -74,7 +74,7 @@ const ContentIFrame = ({
|
||||
<iframe title={title} {...contentIFrameProps} data-testid={testIDs.contentIFrame} />
|
||||
</div>
|
||||
)}
|
||||
{modalOptions.open && (
|
||||
{modalOptions.isOpen && (
|
||||
<Modal
|
||||
body={modalOptions.body
|
||||
? <div className="unit-modal">{ modalOptions.body }</div>
|
||||
@@ -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"
|
||||
|
||||
@@ -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(<ContentIFrame {...{ ...props, shouldShowContent: false }} />);
|
||||
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(<ContentIFrame {...props} />);
|
||||
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 }}
|
||||
/>,
|
||||
);
|
||||
});
|
||||
|
||||
@@ -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 },
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -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,
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user