From ffa313a2894e0b0c0e64570687acdc673dc161b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BA=8C=E8=B4=A7=E7=88=B1=E5=90=83=E7=99=BD=E8=90=9D?= =?UTF-8?q?=E5=8D=9C?= Date: Fri, 10 Jan 2025 17:09:44 +0800 Subject: [PATCH] test: replace enzyme test code with @testing-library/react. (#471) * Update test case. Replace enzyme test code with @testing-library/react. Update test cases in `tests/index.spec.tsx` to use `@testing-library/react` instead of `enzyme`. * Replace `enzyme` imports with `@testing-library/react` imports. * Update test cases to use `render`, `fireEvent`, and other utilities from `@testing-library/react`. * Remove `mount` and `ReactWrapper` imports. * Change code `props.style` with `toHaveStyle({ key: value })` style. * Change `style.display` check to be `toHaveStyle("display: block")` or `display: none`. --- For more details, open the [Copilot Workspace session](https://copilot-workspace.githubnext.com/react-component/dialog?shareId=XXXX-XXXX-XXXX-XXXX). * test: fix part * test: fix lint * test: fix test case * chore: adjust package.json --- jest.config.js | 1 - package.json | 14 +- tests/index.spec.tsx | 411 +++++++++++++++++++++--------------------- tests/portal.spec.tsx | 25 +-- tests/setup.js | 7 +- 5 files changed, 220 insertions(+), 238 deletions(-) diff --git a/jest.config.js b/jest.config.js index 2778c10e..97443ee3 100644 --- a/jest.config.js +++ b/jest.config.js @@ -1,5 +1,4 @@ module.exports = { setupFiles: ["./tests/setup.js"], setupFilesAfterEnv: ["./tests/setupFilesAfterEnv.ts"], - snapshotSerializers: [require.resolve("enzyme-to-json/serializer")], }; diff --git a/package.json b/package.json index 48d02ce8..35225444 100644 --- a/package.json +++ b/package.json @@ -58,8 +58,7 @@ "devDependencies": { "@rc-component/father-plugin": "^2.0.1", "@testing-library/jest-dom": "^6.1.6", - "@testing-library/react": "^12.0.0", - "@types/enzyme": "^3.10.7", + "@testing-library/react": "^13.0.0", "@types/jest": "^29.4.0", "@types/keyv": "3.1.4", "@types/react": "^18.0.24", @@ -69,9 +68,6 @@ "cheerio": "1.0.0-rc.12", "cross-env": "^7.0.0", "dumi": "^2.1.3", - "enzyme": "^3.1.1", - "enzyme-adapter-react-16": "^1.0.1", - "enzyme-to-json": "^3.1.2", "eslint": "^7.1.0", "eslint-config-airbnb": "^19.0.4", "eslint-plugin-react": "^7.20.6", @@ -86,13 +82,13 @@ "rc-drawer": "^7.0.0", "rc-select": "^14.11.0", "rc-test": "^7.0.14", - "react": "^16.9.0", - "react-dom": "^16.9.0", + "react": "^18.0.0", + "react-dom": "^18.0.0", "react-draggable": "^4.4.3", "typescript": "^5.4.3" }, "peerDependencies": { - "react": ">=16.9.0", - "react-dom": ">=16.9.0" + "react": ">=18.0.0", + "react-dom": ">=18.0.0" } } diff --git a/tests/index.spec.tsx b/tests/index.spec.tsx index 455637f6..f160d3ac 100644 --- a/tests/index.spec.tsx +++ b/tests/index.spec.tsx @@ -1,14 +1,29 @@ /* eslint-disable react/no-render-return-value, max-classes-per-file, func-names, no-console */ -import { fireEvent, render } from '@testing-library/react'; -import type { ReactWrapper } from 'enzyme'; -import { mount } from 'enzyme'; +import { fireEvent, render, act } from '@testing-library/react'; import { Provider } from 'rc-motion'; import KeyCode from '@rc-component/util/lib/KeyCode'; import React, { cloneElement, useEffect } from 'react'; -import { act } from 'react-dom/test-utils'; import type { DialogProps } from '../src'; import Dialog from '../src'; +jest.mock('rc-motion', () => { + const OriReact = jest.requireActual('react'); + const origin = jest.requireActual('rc-motion'); + const OriCSSMotion = origin.default; + + const ProxyCSSMotion = OriReact.forwardRef((props: any, ref: any) => { + global.onAppearPrepare = props.onAppearPrepare; + + return ; + }); + + return { + ...origin, + default: ProxyCSSMotion, + __esModule: true, + }; +}); + describe('dialog', () => { async function runFakeTimer() { for (let i = 0; i < 100; i += 1) { @@ -29,16 +44,15 @@ describe('dialog', () => { }); it('should render correct', () => { - const wrapper = mount(); + render(); jest.runAllTimers(); - wrapper.update(); - expect(wrapper.render()).toMatchSnapshot(); + expect(document.querySelector('.rc-dialog-root')).toMatchSnapshot(); }); it('add rootClassName and rootStyle should render correct', () => { const spy = jest.spyOn(console, 'error').mockImplementation(() => {}); - const wrapper = mount( + render( { />, ); jest.runAllTimers(); - wrapper.update(); - expect(wrapper.render()).toMatchSnapshot(); + expect(document.querySelector('.rc-dialog-root')).toMatchSnapshot(); expect(spy).toHaveBeenCalledWith( `Warning: wrapStyle is deprecated, please use styles instead.`, ); - expect(wrapper.find('.customize-root-class').length).toBeTruthy(); - expect(wrapper.find('.rc-dialog-wrap').props().style.fontSize).toBe(10); - expect(wrapper.find('.rc-dialog-root').props().style.fontSize).toBe(20); - expect(wrapper.find('.rc-dialog').props().style.height).toEqual(903); - expect(wrapper.find('.rc-dialog').props().style.width).toEqual(600); + expect(document.querySelector('.customize-root-class')).toBeTruthy(); + expect(document.querySelector('.rc-dialog-wrap')).toHaveStyle('fontSize: 10px'); + expect(document.querySelector('.rc-dialog-root')).toHaveStyle('fontSize: 20px'); + expect(document.querySelector('.rc-dialog')).toHaveStyle('height: 903px'); + expect(document.querySelector('.rc-dialog')).toHaveStyle('width: 600px'); }); it('show', () => { - const wrapper = mount(); + render(); jest.runAllTimers(); - wrapper.update(); - expect(wrapper.find('.rc-dialog-wrap').props().style.display).toBeFalsy(); + + expect(document.querySelector('.rc-dialog-wrap')).toHaveStyle('display: block'); }); it('close', () => { - const wrapper = mount(); + const { rerender } = render(); jest.runAllTimers(); - wrapper.setProps({ visible: false }); + rerender(); jest.runAllTimers(); - wrapper.update(); - expect(wrapper.find('.rc-dialog-wrap').props().style.display).toEqual('none'); + expect(document.querySelector('.rc-dialog-wrap')).toHaveStyle('display: none'); }); it('create & root & mask', () => { - const wrapper = mount(); + render(); jest.runAllTimers(); - wrapper.update(); - expect(wrapper.find('.rc-dialog-root').length).toBeTruthy(); - expect(wrapper.find('.rc-dialog-mask').length).toBeTruthy(); + expect(document.querySelector('.rc-dialog-root')).toBeTruthy(); + expect(document.querySelector('.rc-dialog-mask')).toBeTruthy(); }); it('click close', () => { const onClose = jest.fn(); - const wrapper = mount(); + render(); jest.runAllTimers(); - wrapper.update(); - const btn = wrapper.find('.rc-dialog-close'); - expect(btn.text()).toBe('test'); - btn.simulate('click'); + const btn = document.querySelector('.rc-dialog-close'); + expect(btn.textContent).toBe('test'); + fireEvent.click(btn); jest.runAllTimers(); - wrapper.update(); expect(onClose).toHaveBeenCalledTimes(1); }); describe('destroyOnClose', () => { it('default is false', () => { - const wrapper = mount( + const { rerender } = render( , - { attachTo: document.body }, ); - act(() => { - wrapper.setProps({ visible: false }); - jest.runAllTimers(); - wrapper.update(); - }); + rerender(); + jest.runAllTimers(); expect(document.querySelectorAll('.test-destroy')).toHaveLength(1); - - wrapper.unmount(); }); it('destroy on hide should unmount child components on close', () => { - const wrapper = mount( - + const Demo = (props?: Partial) => ( + - , - { attachTo: document.body }, + ); - // Show - wrapper.setProps({ visible: true }); - jest.runAllTimers(); - wrapper.update(); + const { rerender } = render(); - (document.getElementsByClassName('.test-input') as unknown as HTMLInputElement).value = - 'test'; - expect( - (document.getElementsByClassName('.test-input') as unknown as HTMLInputElement).value, - ).toBe('test'); + // Show + rerender(); + act(() => { + jest.runAllTimers(); + }); + document.querySelector('.test-input').value = 'test'; + expect(document.querySelector('.test-input')).toHaveValue('test'); // Hide - wrapper.setProps({ visible: false }); - jest.runAllTimers(); - wrapper.update(); + rerender(); + act(() => { + jest.runAllTimers(); + }); + expect(document.querySelector('.test-input')).toBeFalsy(); // Show - wrapper.setProps({ visible: true }); - jest.runAllTimers(); - wrapper.update(); + rerender(); + act(() => { + jest.runAllTimers(); + }); - expect( - (document.getElementsByClassName('.test-input') as unknown as HTMLInputElement).value, - ).toBeUndefined(); - wrapper.unmount(); + expect(document.querySelector('.test-input')).toHaveValue(''); }); }); it('esc to close', () => { const onClose = jest.fn(); - const wrapper = mount(); + render(); jest.runAllTimers(); - wrapper.update(); - wrapper.find('.rc-dialog').simulate('keyDown', { keyCode: KeyCode.ESC }); + fireEvent.keyDown(document.querySelector('.rc-dialog'), { keyCode: KeyCode.ESC }); jest.runAllTimers(); - wrapper.update(); expect(onClose).toHaveBeenCalled(); }); it('mask to close', () => { const onClose = jest.fn(); - const wrapper = mount(); + const { rerender } = render(); // Mask close - wrapper.find('.rc-dialog-wrap').simulate('click'); + fireEvent.click(document.querySelector('.rc-dialog-wrap')); jest.runAllTimers(); - wrapper.update(); expect(onClose).toHaveBeenCalled(); onClose.mockReset(); // Mask can not close - wrapper.setProps({ maskClosable: false }); - wrapper.find('.rc-dialog-wrap').simulate('click'); + rerender(); + fireEvent.click(document.querySelector('.rc-dialog-wrap')); jest.runAllTimers(); - wrapper.update(); expect(onClose).not.toHaveBeenCalled(); }); it('renderToBody', () => { const container = document.createElement('div'); document.body.appendChild(container); - const wrapper = mount( - + render( +

1

, - { attachTo: container }, + { container }, ); - expect(wrapper.find('.renderToBody')).toHaveLength(0); - expect(wrapper.find('.rc-dialog-wrap')).toHaveLength(0); - - // Visible - wrapper.setProps({ visible: true }); - jest.runAllTimers(); - wrapper.update(); + act(() => { + jest.runAllTimers(); + }); - expect(wrapper.find('.rc-dialog-wrap')).toHaveLength(1); - expect(wrapper.find('.renderToBody')).toHaveLength(1); - expect(container.contains(wrapper.find('.rc-dialog-wrap').getDOMNode())).toBeFalsy(); + expect(container.querySelector('.rc-dialog')).toBeFalsy(); + expect(document.body.querySelector('.rc-dialog')).toBeTruthy(); - wrapper.unmount(); document.body.removeChild(container); }); it('getContainer', () => { const returnedContainer = document.createElement('div'); - const wrapper = mount( + render( returnedContainer}>

Hello world!

, ); - expect(returnedContainer.contains(wrapper.find('.rc-dialog-wrap').getDOMNode())).toBeTruthy(); - wrapper.unmount(); + expect(returnedContainer.querySelector('.rc-dialog')).toBeTruthy(); }); it('render title correctly', () => { - const wrapper = mount(); - expect(wrapper.find('.rc-dialog-header').text()).toBe('bamboo'); + render(); + expect(document.querySelector('.rc-dialog-header').textContent).toBe('bamboo'); }); it('render footer correctly', () => { - const wrapper = mount(); - expect(wrapper.find('.rc-dialog-footer').text()).toBe('test'); + render(); + expect(document.querySelector('.rc-dialog-footer').textContent).toBe('test'); }); // 失效了,需要修复 @@ -251,28 +241,24 @@ describe('dialog', () => { describe('Tab should keep focus in dialog', () => { it('basic tabbing', () => { - const wrapper = mount(, { attachTo: document.body }); - const sentinelEnd = document.querySelector( - '.rc-dialog > div:last-child', - ) as unknown as HTMLDivElement; + render(); + const sentinelEnd = document.querySelector('.rc-dialog > div:last-child'); sentinelEnd.focus(); - wrapper.find('.rc-dialog-wrap').simulate('keyDown', { + fireEvent.keyDown(document.querySelector('.rc-dialog-wrap'), { keyCode: KeyCode.TAB, }); const sentinelStart = document.querySelector('.rc-dialog > div:first-child'); expect(document.activeElement).toBe(sentinelStart); - - wrapper.unmount(); }); it('trap focus after shift-tabbing', () => { render(); - document.querySelector('.rc-dialog > div:first-child')?.focus(); + document.querySelector('.rc-dialog > div:first-child').focus(); - fireEvent.keyDown(document.querySelector('.rc-dialog-wrap')!, { + fireEvent.keyDown(document.querySelector('.rc-dialog-wrap'), { keyCode: KeyCode.TAB, key: 'Tab', shiftKey: true, @@ -284,7 +270,7 @@ describe('dialog', () => { describe('mousePosition', () => { function prepareModal(mousePosition: { x: number; y: number }) { - const wrapper = mount( + const { container } = render(

the dialog

, @@ -292,47 +278,46 @@ describe('dialog', () => { // Trigger position align act(() => { - wrapper - .find('Content CSSMotion' as any) - .props() - .onAppearPrepare(); + global.onAppearPrepare?.(); }); - return wrapper; + return container; } it('sets transform-origin when property mousePosition is set', () => { - const wrapper = prepareModal({ x: 100, y: 100 }); + prepareModal({ x: 100, y: 100 }); expect( - (wrapper.find('.rc-dialog').at(0).getDOMNode() as HTMLDivElement).style['transform-origin'], + document.querySelector('.rc-dialog').style['transform-origin'], ).toBeTruthy(); }); it('both undefined', () => { - const wrapper = prepareModal({ x: undefined, y: undefined }); + prepareModal({ x: undefined, y: undefined }); expect( - (wrapper.find('.rc-dialog').at(0).getDOMNode() as HTMLDivElement).style['transform-origin'], + document.querySelector('.rc-dialog').style['transform-origin'], ).toBeFalsy(); }); it('one valid', () => { - const wrapper = prepareModal({ x: 10, y: 0 }); + prepareModal({ x: 10, y: 0 }); expect( - (wrapper.find('.rc-dialog').at(0).getDOMNode() as HTMLDivElement).style['transform-origin'], + document.querySelector('.rc-dialog').style['transform-origin'], ).toBeTruthy(); }); }); it('can get dom element before dialog first show when forceRender is set true ', () => { - const wrapper = mount( + render(
forceRender element
, ); - expect(wrapper.find('.rc-dialog-body > div').text()).toEqual('forceRender element'); + expect(document.querySelector('.rc-dialog-body > div').textContent).toEqual( + 'forceRender element', + ); }); describe('getContainer is false', () => { @@ -360,14 +345,14 @@ describe('dialog', () => { it('should not close if mouse down in dialog', () => { const onClose = jest.fn(); - const wrapper = mount(); - wrapper.find('.rc-dialog-body').simulate('click'); + render(); + fireEvent.click(document.querySelector('.rc-dialog-body')); expect(onClose).not.toHaveBeenCalled(); }); it('zIndex', () => { - const wrapper = mount(); - expect(wrapper.find('.rc-dialog-wrap').props().style.zIndex).toBe(903); + render(); + expect(document.querySelector('.rc-dialog-wrap')).toHaveStyle('z-index: 903'); }); it('should show dialog when initialize dialog, given forceRender and visible is true', () => { @@ -382,18 +367,21 @@ describe('dialog', () => { } } - const wrapper = mount( + render(
Show dialog with forceRender and visible is true
, ); - jest.runAllTimers(); - wrapper.update(); - expect(wrapper.find('.rc-dialog-wrap').props().style.display).toEqual(null); + + act(() => { + jest.runAllTimers(); + }); + + expect(document.querySelector('.rc-dialog-wrap')).toHaveStyle('display: block'); }); it('modalRender', () => { - const modalRender = mount( + render( @@ -401,7 +389,7 @@ describe('dialog', () => { } />, ); - expect(modalRender.find('.rc-dialog-section').props().style.background).toEqual('#1890ff'); + expect(document.querySelector('.rc-dialog-section')).toHaveStyle('background: #1890ff'); }); describe('focusTriggerAfterClose', () => { @@ -417,16 +405,15 @@ describe('dialog', () => { ); }; - const wrapper = mount(, { attachTo: document.body }); - const trigger = wrapper.find('button').at(0); - (trigger.getDOMNode() as any).focus(); - trigger.simulate('click'); + render(); + const trigger = document.querySelector('button'); + trigger.focus(); + fireEvent.click(trigger); jest.runAllTimers(); - const closeButton = wrapper.find('.rc-dialog-close'); - closeButton.simulate('click'); + const closeButton = document.querySelector('.rc-dialog-close'); + fireEvent.click(closeButton); jest.runAllTimers(); - expect(document.activeElement).toBe(trigger.getDOMNode()); - wrapper.unmount(); + expect(document.activeElement).toBe(trigger); }); it('should focus trigger after close dialog when contains focusable element', () => { @@ -445,33 +432,38 @@ describe('dialog', () => { ); }; - const wrapper = mount(, { attachTo: document.body }); - const trigger = wrapper.find('button').at(0); - (trigger.getDOMNode() as any).focus(); - trigger.simulate('click'); + render(); + const trigger = document.querySelector('button'); + trigger.focus(); + fireEvent.click(trigger); jest.runAllTimers(); - const closeButton = wrapper.find('.rc-dialog-close'); - closeButton.simulate('click'); + const closeButton = document.querySelector('.rc-dialog-close'); + fireEvent.click(closeButton); jest.runAllTimers(); - expect(document.activeElement).toBe(trigger.getDOMNode()); - wrapper.unmount(); + expect(document.activeElement).toBe(trigger); }); }); describe('size should work', () => { it('width', () => { - const wrapper = mount(); - expect(wrapper.find('.rc-dialog').props().style.width).toEqual(1128); + render(); + expect(document.querySelector('.rc-dialog')).toHaveStyle('width: 1128px'); }); it('height', () => { - const wrapper = mount(); - expect(wrapper.find('.rc-dialog').props().style.height).toEqual(903); + render(); + expect(document.querySelector('.rc-dialog')).toHaveStyle('height: 903px'); }); }); describe('re-render', () => { - function createWrapper(props?: Partial): [ReactWrapper, () => number] { + function createWrapper( + props?: Partial, + ): [ + container: HTMLElement, + getRenderTimes: () => number, + updateProps: (props?: Partial) => void, + ] { let renderTimes = 0; const RenderChecker = () => { renderTimes += 1; @@ -486,27 +478,35 @@ describe('dialog', () => { ); }; - const wrapper = mount(); + const { container, rerender } = render(); - return [wrapper, () => renderTimes]; + return [ + container, + () => renderTimes, + (nextProps) => { + rerender(); + }, + ]; } it('should not re-render when visible changed', () => { - const [wrapper, getRenderTimes] = createWrapper(); - expect(getRenderTimes()).toEqual(1); + const [, getRenderTimes, updateProps] = createWrapper(); + const lastRenderTimes = getRenderTimes(); + expect(getRenderTimes()).toBeGreaterThan(0); // Hidden should not trigger render - wrapper.setProps({ visible: false }); - expect(getRenderTimes()).toEqual(1); + updateProps({ visible: false }); + expect(getRenderTimes()).toEqual(lastRenderTimes); }); it('should re-render when forceRender', () => { - const [wrapper, getRenderTimes] = createWrapper({ forceRender: true }); - expect(getRenderTimes()).toEqual(1); + const [, getRenderTimes, updateProps] = createWrapper({ forceRender: true }); + const lastRenderTimes = getRenderTimes(); + expect(getRenderTimes()).toBeGreaterThan(0); // Hidden should not trigger render - wrapper.setProps({ visible: false }); - expect(getRenderTimes()).toEqual(2); + updateProps({ visible: false }); + expect(getRenderTimes()).toBeGreaterThan(lastRenderTimes); }); }); @@ -514,10 +514,10 @@ describe('dialog', () => { it('should trigger afterClose when set visible to false', () => { const afterClose = jest.fn(); - const wrapper = mount(); + const { rerender } = render(); jest.runAllTimers(); - wrapper.setProps({ visible: false }); + rerender(); jest.runAllTimers(); expect(afterClose).toHaveBeenCalledTimes(1); @@ -526,10 +526,12 @@ describe('dialog', () => { it('should not trigger afterClose when mount dialog of getContainer={false}', () => { const afterClose = jest.fn(); - const wrapper = mount(); + const { container } = render(); jest.runAllTimers(); - wrapper.setProps({ visible: false }); + render(, { + container, + }); jest.runAllTimers(); expect(afterClose).toHaveBeenCalledTimes(0); @@ -538,10 +540,10 @@ describe('dialog', () => { it('should not trigger afterClose when mount dialog of forceRender={true}', () => { const afterClose = jest.fn(); - const wrapper = mount(); + const { container } = render(); jest.runAllTimers(); - wrapper.setProps({ visible: false }); + render(, { container }); jest.runAllTimers(); expect(afterClose).toHaveBeenCalledTimes(0); @@ -572,7 +574,7 @@ describe('dialog', () => { expect(afterOpenChange).toHaveBeenCalledWith(true); expect(afterOpenChange).toHaveBeenCalledTimes(1); - rerender(); + rerender(); await runFakeTimer(); expect(afterOpenChange).toHaveBeenCalledWith(false); expect(afterOpenChange).toHaveBeenCalledTimes(2); @@ -580,7 +582,7 @@ describe('dialog', () => { }); it('should support classNames', () => { - const wrapper = mount( + render( { />, ); jest.runAllTimers(); - wrapper.update(); - expect(wrapper.render()).toMatchSnapshot(); - expect(wrapper.find('.rc-dialog-wrap').props().className).toContain('custom-wrapper'); - expect(wrapper.find('.rc-dialog-body').props().className).toContain('custom-body'); - expect(wrapper.find('.rc-dialog-header').props().className).toContain('custom-header'); - expect(wrapper.find('.rc-dialog-footer').props().className).toContain('custom-footer'); - expect(wrapper.find('.rc-dialog-mask').props().className).toContain('custom-mask'); - expect(wrapper.find('.rc-dialog-section').props().className).toContain('custom-section'); + expect(document.querySelector('.rc-dialog-root')).toMatchSnapshot(); + expect(document.querySelector('.rc-dialog-wrap').className).toContain('custom-wrapper'); + expect(document.querySelector('.rc-dialog-body').className).toContain('custom-body'); + expect(document.querySelector('.rc-dialog-header').className).toContain('custom-header'); + expect(document.querySelector('.rc-dialog-footer').className).toContain('custom-footer'); + expect(document.querySelector('.rc-dialog-mask').className).toContain('custom-mask'); + expect(document.querySelector('.rc-dialog-section').className).toContain('custom-section'); }); it('should support styles', () => { - const wrapper = mount( + render( { />, ); jest.runAllTimers(); - wrapper.update(); - expect(wrapper.render()).toMatchSnapshot(); - expect(wrapper.find('.rc-dialog-wrap').props().style.background).toBe('pink'); - expect(wrapper.find('.rc-dialog-body').props().style.background).toBe('green'); - expect(wrapper.find('.rc-dialog-header').props().style.background).toBe('red'); - expect(wrapper.find('.rc-dialog-footer').props().style.background).toBe('blue'); - expect(wrapper.find('.rc-dialog-mask').props().style.background).toBe('yellow'); - expect(wrapper.find('.rc-dialog-section').props().style.background).toBe('orange'); - expect(wrapper.find('.rc-dialog-title').props().style.background).toBe('orange'); + expect(document.querySelector('.rc-dialog-root')).toMatchSnapshot(); + expect(document.querySelector('.rc-dialog-wrap')).toHaveStyle('background: pink'); + expect(document.querySelector('.rc-dialog-body')).toHaveStyle('background: green'); + expect(document.querySelector('.rc-dialog-header')).toHaveStyle('background: red'); + expect(document.querySelector('.rc-dialog-footer')).toHaveStyle('background: blue'); + expect(document.querySelector('.rc-dialog-mask')).toHaveStyle('background: yellow'); + expect(document.querySelector('.rc-dialog-section')).toHaveStyle('background: orange'); + expect(document.querySelector('.rc-dialog-title')).toHaveStyle('background: orange'); }); + it('should warning', () => { const spy = jest.spyOn(console, 'error').mockImplementation(() => {}); - const wrapper = mount( + render( { />, ); jest.runAllTimers(); - wrapper.update(); expect(spy).toHaveBeenCalledWith( `Warning: bodyStyle is deprecated, please use styles instead.`, @@ -671,7 +671,7 @@ describe('dialog', () => { it('support aria-* in closable', () => { const onClose = jest.fn(); - const wrapper = mount( + render( { />, ); jest.runAllTimers(); - wrapper.update(); - const btn = wrapper.find('.rc-dialog-close'); - expect(btn.text()).toBe('test'); - expect(btn.getDOMNode().getAttribute('aria-label')).toBe('test aria-label'); - btn.simulate('click'); + const btn = document.querySelector('.rc-dialog-close'); + expect(btn.textContent).toBe('test'); + expect(btn.getAttribute('aria-label')).toBe('test aria-label'); + fireEvent.click(btn); jest.runAllTimers(); - wrapper.update(); expect(onClose).toHaveBeenCalledTimes(1); }); it('support disable button in closable', () => { const onClose = jest.fn(); - const wrapper = mount( + render( { />, ); jest.runAllTimers(); - wrapper.update(); - const btn = wrapper.find('.rc-dialog-close'); - expect(btn.prop('disabled')).toBe(true); - btn.simulate('click'); + const btn = document.querySelector('.rc-dialog-close'); + expect(btn.disabled).toBeTruthy(); + fireEvent.click(btn); jest.runAllTimers(); - wrapper.update(); expect(onClose).not.toHaveBeenCalled(); - btn.simulate('keydown', { key: 'Enter' }); + fireEvent.keyDown(btn, { key: 'Enter' }); jest.runAllTimers(); - wrapper.update(); expect(onClose).not.toHaveBeenCalled(); }); it('should not display closeIcon when closable is false', () => { const onClose = jest.fn(); - const wrapper = mount(); - jest.runAllTimers(); - wrapper.update(); + render(); + + act(() => { + jest.runAllTimers(); + }); - const btn = wrapper.find('.rc-dialog-close'); - expect(btn.find('.rc-dialog-close-x')).not.toBeNull(); + expect(document.querySelector('.rc-dialog')).toBeTruthy(); + expect(document.querySelector('.rc-dialog-close')).toBeFalsy(); }); }); diff --git a/tests/portal.spec.tsx b/tests/portal.spec.tsx index 7a665fef..4079cbc7 100644 --- a/tests/portal.spec.tsx +++ b/tests/portal.spec.tsx @@ -1,8 +1,7 @@ /* eslint-disable react/no-render-return-value, max-classes-per-file, func-names, no-console */ import React from 'react'; import Select from 'rc-select'; -import { act } from 'react-dom/test-utils'; -import { mount } from 'enzyme'; +import { render, fireEvent } from '@testing-library/react'; import Dialog from '../src'; /** @@ -21,7 +20,7 @@ describe('Dialog.Portal', () => { it('event should bubble', () => { const onClose = jest.fn(); - const wrapper = mount( + render(