mirror of
https://github.com/ant-design/ant-design.git
synced 2025-06-12 20:43:11 +08:00
fix(modal): Modal.xxx onCancel close argument is not a function (#36600)
* fix(modal): fix the error of `onCancel` parameter of modal returned by `useModal` resolve: 36581 ref: https://github.com/ant-design/ant-design/issues/36581#issuecomment-1189396007 * test(confirm): 补充 modal 测试用例 * test(modal): 添加测试用例 * Revert "fix(modal): fix the error of `onCancel` parameter of modal returned by `useModal`" This reverts commit e4fcb3e62add63193ec9081b2c21e657379bebfb. * fix(modal): fix modal onOk/onCancel method is not a valid function when there is a close parameter closed: #36581 * chore: cancel the introduction of `noop` from third-party library
This commit is contained in:
parent
09de419253
commit
16ecdbb58d
@ -305,7 +305,7 @@ describe('Modal.confirm triggers callbacks correctly', () => {
|
||||
});
|
||||
|
||||
describe('should not close modals when click confirm button when onOk has argument', () => {
|
||||
['info', 'success', 'warning', 'error'].forEach(type => {
|
||||
['confirm', 'info', 'success', 'warning', 'error'].forEach(type => {
|
||||
it(type, async () => {
|
||||
jest.useFakeTimers();
|
||||
Modal[type]({
|
||||
@ -318,7 +318,7 @@ describe('Modal.confirm triggers callbacks correctly', () => {
|
||||
await sleep();
|
||||
});
|
||||
expect($$(`.ant-modal-confirm-${type}`)).toHaveLength(1);
|
||||
$$('.ant-btn')[0].click();
|
||||
$$('.ant-btn-primary')[0].click();
|
||||
|
||||
await act(async () => {
|
||||
jest.runAllTimers();
|
||||
@ -674,4 +674,149 @@ describe('Modal.confirm triggers callbacks correctly', () => {
|
||||
const { width } = $$('.ant-modal-body')[0].style;
|
||||
expect(width).toBe('500px');
|
||||
});
|
||||
|
||||
describe('the callback close should be a method when onCancel has a close parameter', () => {
|
||||
['confirm', 'info', 'success', 'warning', 'error'].forEach(type => {
|
||||
it(`click the close icon to trigger ${type} onCancel`, async () => {
|
||||
jest.useFakeTimers();
|
||||
const mock = jest.fn();
|
||||
|
||||
Modal[type]({
|
||||
closable: true,
|
||||
onCancel: close => mock(close),
|
||||
});
|
||||
|
||||
await act(async () => {
|
||||
jest.runAllTimers();
|
||||
await sleep();
|
||||
});
|
||||
|
||||
expect($$(`.ant-modal-confirm-${type}`)).toHaveLength(1);
|
||||
$$('.ant-modal-close')[0].click();
|
||||
|
||||
await act(async () => {
|
||||
jest.runAllTimers();
|
||||
await sleep();
|
||||
});
|
||||
|
||||
expect($$(`.ant-modal-confirm-${type}`)).toHaveLength(0);
|
||||
expect(mock).toBeCalledWith(expect.any(Function));
|
||||
|
||||
jest.useRealTimers();
|
||||
});
|
||||
});
|
||||
|
||||
['confirm', 'info', 'success', 'warning', 'error'].forEach(type => {
|
||||
it(`press ESC to trigger ${type} onCancel`, async () => {
|
||||
jest.useFakeTimers();
|
||||
const mock = jest.fn();
|
||||
|
||||
Modal[type]({
|
||||
keyboard: true,
|
||||
onCancel: close => mock(close),
|
||||
});
|
||||
|
||||
jest.runAllTimers();
|
||||
await sleep();
|
||||
jest.runAllTimers();
|
||||
|
||||
expect($$(`.ant-modal-confirm-${type}`)).toHaveLength(1);
|
||||
TestUtils.Simulate.keyDown($$('.ant-modal')[0], {
|
||||
keyCode: KeyCode.ESC,
|
||||
});
|
||||
|
||||
jest.runAllTimers();
|
||||
await sleep(0);
|
||||
jest.runAllTimers();
|
||||
|
||||
expect($$(`.ant-modal-confirm-${type}`)).toHaveLength(0);
|
||||
expect(mock).toBeCalledWith(expect.any(Function));
|
||||
|
||||
jest.useRealTimers();
|
||||
});
|
||||
});
|
||||
|
||||
['confirm', 'info', 'success', 'warning', 'error'].forEach(type => {
|
||||
it(`click the mask to trigger ${type} onCancel`, async () => {
|
||||
jest.useFakeTimers();
|
||||
const mock = jest.fn();
|
||||
|
||||
Modal[type]({
|
||||
maskClosable: true,
|
||||
onCancel: close => mock(close),
|
||||
});
|
||||
|
||||
await act(async () => {
|
||||
jest.runAllTimers();
|
||||
await sleep();
|
||||
});
|
||||
|
||||
expect($$('.ant-modal-mask')).toHaveLength(1);
|
||||
expect($$(`.ant-modal-confirm-${type}`)).toHaveLength(1);
|
||||
|
||||
$$('.ant-modal-wrap')[0].click();
|
||||
|
||||
await act(async () => {
|
||||
jest.runAllTimers();
|
||||
await sleep();
|
||||
});
|
||||
|
||||
expect($$(`.ant-modal-confirm-${type}`)).toHaveLength(0);
|
||||
expect(mock).toBeCalledWith(expect.any(Function));
|
||||
|
||||
jest.useRealTimers();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('confirm modal click Cancel button close callback is a function', async () => {
|
||||
jest.useFakeTimers();
|
||||
const mock = jest.fn();
|
||||
|
||||
Modal.confirm({
|
||||
onCancel: close => mock(close),
|
||||
});
|
||||
|
||||
await act(async () => {
|
||||
jest.runAllTimers();
|
||||
await sleep();
|
||||
});
|
||||
|
||||
$$('.ant-modal-confirm-btns > .ant-btn')[0].click();
|
||||
|
||||
await act(async () => {
|
||||
jest.runAllTimers();
|
||||
await sleep();
|
||||
});
|
||||
|
||||
expect(mock).toBeCalledWith(expect.any(Function));
|
||||
|
||||
jest.useRealTimers();
|
||||
});
|
||||
|
||||
it('close can close modal when onCancel has a close parameter', async () => {
|
||||
jest.useFakeTimers();
|
||||
|
||||
Modal.confirm({
|
||||
onCancel: close => close(),
|
||||
});
|
||||
|
||||
await act(async () => {
|
||||
jest.runAllTimers();
|
||||
await sleep();
|
||||
});
|
||||
|
||||
expect($$('.ant-modal-confirm-confirm')).toHaveLength(1);
|
||||
|
||||
$$('.ant-modal-confirm-btns > .ant-btn')[0].click();
|
||||
|
||||
await act(async () => {
|
||||
jest.runAllTimers();
|
||||
await sleep();
|
||||
});
|
||||
|
||||
expect($$('.ant-modal-confirm-confirm')).toHaveLength(0);
|
||||
|
||||
jest.useRealTimers();
|
||||
});
|
||||
});
|
||||
|
@ -1,9 +1,11 @@
|
||||
import CSSMotion from 'rc-motion';
|
||||
import { genCSSMotion } from 'rc-motion/lib/CSSMotion';
|
||||
import KeyCode from 'rc-util/lib/KeyCode';
|
||||
import React from 'react';
|
||||
import { act } from 'react-dom/test-utils';
|
||||
import TestUtils, { act } from 'react-dom/test-utils';
|
||||
|
||||
import Modal from '..';
|
||||
import { fireEvent, render } from '../../../tests/utils';
|
||||
import { fireEvent, render, sleep } from '../../../tests/utils';
|
||||
import Button from '../../button';
|
||||
import ConfigProvider from '../../config-provider';
|
||||
import Input from '../../input';
|
||||
@ -193,4 +195,110 @@ describe('Modal.hook', () => {
|
||||
fireEvent.click(container.querySelectorAll('.open-hook-modal-btn')[0]);
|
||||
expect(document.body.classList.contains('ant-modal-confirm-title')).toBeFalsy();
|
||||
});
|
||||
|
||||
it('the callback close should be a method when onCancel has a close parameter', async () => {
|
||||
jest.useFakeTimers();
|
||||
|
||||
const clear = async function clear() {
|
||||
await act(async () => {
|
||||
jest.runAllTimers();
|
||||
await sleep();
|
||||
});
|
||||
};
|
||||
|
||||
const mockFn = jest.fn();
|
||||
const Demo = () => {
|
||||
const [modal, contextHolder] = Modal.useModal();
|
||||
|
||||
const openBrokenModal = React.useCallback(() => {
|
||||
modal.confirm({
|
||||
closable: true,
|
||||
keyboard: true,
|
||||
maskClosable: true,
|
||||
onCancel: close => mockFn(close),
|
||||
});
|
||||
}, [modal]);
|
||||
|
||||
return (
|
||||
<div className="App">
|
||||
{contextHolder}
|
||||
<div className="open-hook-modal-btn" onClick={openBrokenModal}>
|
||||
Test hook modal
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const { container } = render(<Demo />);
|
||||
|
||||
await clear();
|
||||
|
||||
expect(document.body.querySelectorAll('.ant-modal-confirm-confirm')).toHaveLength(0);
|
||||
// First open
|
||||
fireEvent.click(container.querySelectorAll('.open-hook-modal-btn')[0]);
|
||||
await clear();
|
||||
|
||||
expect(document.body.querySelectorAll('.ant-modal-confirm-confirm')).toHaveLength(1);
|
||||
// Click mask to close
|
||||
fireEvent.click(document.body.querySelectorAll('.ant-modal-wrap')[0]);
|
||||
|
||||
await clear();
|
||||
|
||||
expect(document.body.querySelectorAll('.ant-modal-confirm-confirm')).toHaveLength(0);
|
||||
// Second open
|
||||
fireEvent.click(container.querySelectorAll('.open-hook-modal-btn')[0]);
|
||||
|
||||
await clear();
|
||||
|
||||
expect(document.body.querySelectorAll('.ant-modal-confirm-confirm')).toHaveLength(1);
|
||||
// Press ESC to turn off
|
||||
TestUtils.Simulate.keyDown(document.body.querySelectorAll('.ant-modal')[0], {
|
||||
keyCode: KeyCode.ESC,
|
||||
});
|
||||
|
||||
await clear();
|
||||
|
||||
expect(document.body.querySelectorAll('.ant-modal-confirm-confirm')).toHaveLength(0);
|
||||
// Third open
|
||||
fireEvent.click(container.querySelectorAll('.open-hook-modal-btn')[0]);
|
||||
|
||||
await clear();
|
||||
|
||||
expect(document.body.querySelectorAll('.ant-modal-confirm-confirm')).toHaveLength(1);
|
||||
// Click the close icon to close
|
||||
fireEvent.click(document.body.querySelectorAll('.ant-modal-close')[0]);
|
||||
|
||||
await clear();
|
||||
|
||||
expect(document.body.querySelectorAll('.ant-modal-confirm-confirm')).toHaveLength(0);
|
||||
// Last open
|
||||
fireEvent.click(container.querySelectorAll('.open-hook-modal-btn')[0]);
|
||||
|
||||
await clear();
|
||||
|
||||
expect(document.body.querySelectorAll('.ant-modal-confirm-confirm')).toHaveLength(1);
|
||||
|
||||
// Click the Cancel button to close (invalid)
|
||||
fireEvent.click(document.body.querySelectorAll('.ant-modal-confirm-btns > .ant-btn')[0]);
|
||||
|
||||
await clear();
|
||||
|
||||
expect(document.body.querySelectorAll('.ant-modal-confirm-confirm')).toHaveLength(1);
|
||||
|
||||
mockFn.mockImplementation(close => close());
|
||||
|
||||
// Click the Cancel button to close (valid)
|
||||
fireEvent.click(document.body.querySelectorAll('.ant-modal-confirm-btns > .ant-btn')[0]);
|
||||
|
||||
await clear();
|
||||
|
||||
expect(document.body.querySelectorAll('.ant-modal-confirm-confirm')).toHaveLength(0);
|
||||
|
||||
// Close called 5 times
|
||||
expect(mockFn).toHaveBeenCalledTimes(5);
|
||||
|
||||
expect(mockFn.mock.calls).toEqual(Array.from({ length: 5 }, () => [expect.any(Function)]));
|
||||
|
||||
jest.useRealTimers();
|
||||
});
|
||||
});
|
||||
|
@ -34,7 +34,7 @@ export default function confirm(config: ModalFuncProps) {
|
||||
function destroy(...args: any[]) {
|
||||
const triggerCancel = args.some(param => param && param.triggerCancel);
|
||||
if (config.onCancel && triggerCancel) {
|
||||
config.onCancel(...args);
|
||||
config.onCancel(() => {}, ...args.slice(1));
|
||||
}
|
||||
for (let i = 0; i < destroyFns.length; i++) {
|
||||
const fn = destroyFns[i];
|
||||
|
@ -36,7 +36,7 @@ const HookModal: React.ForwardRefRenderFunction<HookModalRef, HookModalProps> =
|
||||
setVisible(false);
|
||||
const triggerCancel = args.some(param => param && param.triggerCancel);
|
||||
if (innerConfig.onCancel && triggerCancel) {
|
||||
innerConfig.onCancel();
|
||||
innerConfig.onCancel(() => {}, ...args.slice(1));
|
||||
}
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user