Skip to content

Commit

Permalink
feat: forward modal-close event to children on modal close (#1238)
Browse files Browse the repository at this point in the history
* feat: forward modal-close event to children on modal close

* fix: update tests
  • Loading branch information
muselesscreator authored Nov 21, 2023
1 parent 748e73d commit fe773d1
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 15 deletions.
20 changes: 14 additions & 6 deletions src/courseware/course/sequence/Unit/hooks/useModalIFrameData.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,19 +15,27 @@ const useModalIFrameBehavior = () => {
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;
const handleModalClose = () => {
const rootFrame = document.querySelector('iframe');
setIsOpen(false);
rootFrame.contentWindow.postMessage({ type: 'plugin.modal-close' }, '*');
};

const receiveMessage = React.useCallback((event) => {
const { type, payload } = event.data;
if (!type) {
return;
}
if (type === 'plugin.modal') {
setOptions((current) => ({ ...current, ...payload }));
setIsOpen(true);
}
if (type === 'plugin.modal-close') {
handleModalClose();
}
}, []);
useEventListener('message', receiveMessage);

const handleModalClose = () => {
setIsOpen(false);
};

return {
handleModalClose,
modalOptions: { isOpen, ...options },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,13 @@ describe('useModalIFrameBehavior', () => {
jest.clearAllMocks();
state.mock();
});
const testHandleModalClose = ({ trigger }) => {
const postMessage = jest.fn();
document.querySelector = jest.fn().mockReturnValue({ contentWindow: { postMessage } });
trigger();
state.expectSetStateCalledWith(stateKeys.isOpen, false);
expect(postMessage).toHaveBeenCalledWith({ type: 'plugin.modal-close' }, '*');
};
describe('behavior', () => {
it('initializes isOpen to false', () => {
useModalIFrameBehavior();
Expand All @@ -29,29 +36,51 @@ describe('useModalIFrameBehavior', () => {
state.expectInitializedWith(stateKeys.options, { height: DEFAULT_HEIGHT });
});
describe('eventListener', () => {
const oldOptions = { some: 'old', options: 'yeah' };
const prepareListener = () => {
useModalIFrameBehavior();
expect(useEventListener).toHaveBeenCalled();
const call = useEventListener.mock.calls[0][1];
expect(call.prereqs).toEqual([]);
return call.cb;
};
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 receiveMessage = prepareListener();
const payload = { test: 'values' };
cb({ data: { type: messageTypes.modal, payload } });
receiveMessage({ data: { type: messageTypes.modal, payload } });
expect(state.setState.isOpen).toHaveBeenCalledWith(true);
expect(state.setState.options).toHaveBeenCalled();
const [[setOptionsCb]] = state.setState.options.mock.calls;
expect(setOptionsCb(oldOptions)).toEqual({ ...oldOptions, ...payload });
});
it('ignores events with no type', () => {
state.mockVals({
[stateKeys.isOpen]: false,
[stateKeys.options]: oldOptions,
});
const receiveMessage = prepareListener();
const payload = { test: 'values' };
receiveMessage({ data: { payload } });
expect(state.setState.isOpen).not.toHaveBeenCalled();
expect(state.setState.options).not.toHaveBeenCalled();
});
it('calls handleModalClose behavior when receiving a "plugin.modal-close" event', () => {
const receiveMessage = prepareListener();
testHandleModalClose({
trigger: () => {
receiveMessage({ data: { type: 'plugin.modal-close' } });
},
});
});
});
});
describe('output', () => {
test('handleModalClose sets modal options to closed', () => {
useModalIFrameBehavior().handleModalClose();
state.expectSetStateCalledWith(stateKeys.isOpen, false);
test('returns handleModalClose callback', () => {
testHandleModalClose({ trigger: useModalIFrameBehavior().handleModalClose });
});
it('forwards modalOptions from state values', () => {
const modalOptions = { test: 'options' };
Expand Down

0 comments on commit fe773d1

Please sign in to comment.