diff --git a/jest.config.js b/jest.config.js new file mode 100644 index 00000000..92af8dcb --- /dev/null +++ b/jest.config.js @@ -0,0 +1,3 @@ +module.exports = { + setupFilesAfterEnv: ['/tests/setup.js'] +}; \ No newline at end of file diff --git a/package.json b/package.json index 131ba7fd..d7f66935 100644 --- a/package.json +++ b/package.json @@ -29,7 +29,8 @@ "now-build": "father doc build --storybook" }, "devDependencies": { - "@types/enzyme": "^3.10.5", + "@testing-library/jest-dom": "^5.16.4", + "@testing-library/react": "^13.0.0", "@types/jest": "^25.2.3", "@types/react": "^16.9.3", "@types/react-dom": "^16.9.1", @@ -39,12 +40,11 @@ "coveralls": "^3.1.0", "create-react-class": "^15.6.3", "cross-env": "^7.0.2", - "enzyme": "^3.10.0", "eslint": "^6.6.0", "father": "^2.14.0", "np": "^6.2.3", - "react": "^16.2.0", - "react-dom": "^16.2.0", + "react": "^18.0.0", + "react-dom": "^18.0.0", "typescript": "^4.1.3" }, "dependencies": { diff --git a/tests/Portal.test.tsx b/tests/Portal.test.tsx index cf3e4d5e..de964aa6 100644 --- a/tests/Portal.test.tsx +++ b/tests/Portal.test.tsx @@ -1,29 +1,29 @@ import React from 'react'; -import { mount } from 'enzyme'; +import { render } from '@testing-library/react'; import { act } from 'react-dom/test-utils'; import PortalWrapper, { getOpenCount } from '../src/PortalWrapper'; import Portal from '../src/Portal'; describe('Portal', () => { - let container: HTMLDivElement; + let domContainer: HTMLDivElement; // Mock for raf window.requestAnimationFrame = callback => window.setTimeout(callback); window.cancelAnimationFrame = id => window.clearTimeout(id); beforeEach(() => { - container = document.createElement('div'); - document.body.appendChild(container); + domContainer = document.createElement('div'); + document.body.appendChild(domContainer); }); afterEach(() => { - document.body.removeChild(container); + document.body.removeChild(domContainer); }); it('forceRender', () => { const divRef = React.createRef(); - const wrapper = mount( + const { unmount } = render( {() =>
2333
}
, @@ -31,13 +31,13 @@ describe('Portal', () => { expect(divRef.current).toBeTruthy(); - wrapper.unmount(); + unmount(); }); it('didUpdate', () => { const didUpdate = jest.fn(); - const wrapper = mount( + const { rerender } = render( document.createElement('div')} @@ -48,7 +48,15 @@ describe('Portal', () => { expect(didUpdate).toHaveBeenCalledTimes(1); - wrapper.setProps({ justForceUpdate: true }); + rerender( + document.createElement('div')} + {...{ justForceUpdate: true }} + > + light + , + ); expect(didUpdate).toHaveBeenCalledTimes(2); }); @@ -58,7 +66,7 @@ describe('Portal', () => { div.id = 'bamboo-light'; document.body.appendChild(div); - mount( + render( {() =>
2333
}
, @@ -74,7 +82,7 @@ describe('Portal', () => { it('function', () => { const div = document.createElement('div'); - mount( + render( div}> {() =>
2333
}
, @@ -86,7 +94,7 @@ describe('Portal', () => { it('htmlElement', () => { const div = document.createElement('div'); - mount( + render( {() =>
2333
}
, @@ -98,7 +106,7 @@ describe('Portal', () => { it('delay', () => { jest.useFakeTimers(); const divRef = React.createRef(); - const wrapper = mount( + render(
divRef.current}> {() =>
} @@ -109,7 +117,6 @@ describe('Portal', () => { act(() => { jest.runAllTimers(); - wrapper.update(); }); expect(divRef.current.childElementCount).toEqual(1); @@ -121,15 +128,15 @@ describe('Portal', () => { it('start as 0', () => { expect(getOpenCount()).toEqual(0); - const wrapper = mount( + const { rerender, unmount } = render( {() =>
2333
}
, ); expect(getOpenCount()).toEqual(0); - wrapper.setProps({ visible: true }); + rerender({() =>
2333
}
); expect(getOpenCount()).toEqual(1); - wrapper.unmount(); + unmount(); }); it('correct count', () => { @@ -153,29 +160,33 @@ describe('Portal', () => { expect(getOpenCount()).toEqual(0); - const wrapper = mount(); + const { rerender } = render(); expect(getOpenCount()).toEqual(1); - wrapper.setProps({ count: 2 }); + rerender(); expect(getOpenCount()).toEqual(2); - wrapper.setProps({ count: 1 }); + rerender(); expect(getOpenCount()).toEqual(1); - wrapper.setProps({ visible: false }); + rerender(); expect(getOpenCount()).toEqual(0); }); }); it('wrapperClassName', () => { - const wrapper = mount( + const { rerender } = render( {() =>
} , ); - expect((wrapper.instance() as any).container.className).toEqual('bamboo'); + expect(document.body.querySelector('.bamboo')).toBeTruthy(); - wrapper.setProps({ wrapperClassName: 'light' }); - expect((wrapper.instance() as any).container.className).toEqual('light'); + rerender( + + {() =>
} + , + ); + expect(document.body.querySelector('.light')).toBeTruthy(); }); }); diff --git a/tests/hooks.test.js b/tests/hooks.test.js index 0120839e..0a769388 100644 --- a/tests/hooks.test.js +++ b/tests/hooks.test.js @@ -1,5 +1,5 @@ import * as React from 'react'; -import { mount } from 'enzyme'; +import { render, fireEvent } from '@testing-library/react'; import useMemo from '../src/hooks/useMemo'; import useMergedState from '../src/hooks/useMergedState'; import useLayoutEffect from '../src/hooks/useLayoutEffect'; @@ -13,20 +13,20 @@ describe('hooks', () => { [open, data], (prev, next) => next[0] && prev[1] !== next[1], ); - return
; + return
{memoData}
; }; - const wrapper = mount(); - expect(wrapper.find('div').props().memoData).toEqual('open'); + const { container, rerender } = render(); + expect(container.querySelector('div').textContent).toEqual('open'); - wrapper.setProps({ data: 'again' }); - expect(wrapper.find('div').props().memoData).toEqual('again'); + rerender(); + expect(container.querySelector('div').textContent).toEqual('again'); - wrapper.setProps({ data: 'close', open: false }); - expect(wrapper.find('div').props().memoData).toEqual('again'); + rerender(); + expect(container.querySelector('div').textContent).toEqual('again'); - wrapper.setProps({ data: 'repeat', open: true }); - expect(wrapper.find('div').props().memoData).toEqual('repeat'); + rerender(); + expect(container.querySelector('div').textContent).toEqual('repeat'); }); describe('useMergedState', () => { @@ -43,19 +43,18 @@ describe('hooks', () => { }; it('still control of to undefined', () => { - const wrapper = mount(); + const { container, rerender } = render(); - expect(wrapper.find('input').props().value).toEqual('test'); + expect(container.querySelector('input').value).toEqual('test'); - wrapper.setProps({ value: undefined }); - wrapper.update(); - expect(wrapper.find('input').props().value).toEqual(undefined); + rerender(); + expect(container.querySelector('input').value).toEqual('test'); }); it('correct defaultValue', () => { - const wrapper = mount(); + const { container } = render(); - expect(wrapper.find('input').props().value).toEqual('test'); + expect(container.querySelector('input').value).toEqual('test'); }); it('not rerender when setState as deps', () => { @@ -74,8 +73,8 @@ describe('hooks', () => { return
{val}
; }; - const wrapper = mount(); - expect(wrapper.text()).toEqual('1'); + const { container } = render(); + expect(container.firstChild.textContent).toEqual('1'); }); }); @@ -104,14 +103,18 @@ describe('hooks', () => { .spyOn(console, 'error') .mockImplementation(() => {}); - const wrapper = mount(); - expect(wrapper.find('label').props().children).toEqual('testa'); - wrapper.find('input').simulate('change', { target: { value: '1' } }); - wrapper.update(); - expect(wrapper.find('label').props().children).toEqual('1a'); - wrapper.find('input').simulate('change', { target: { value: '2' } }); - wrapper.update(); - expect(wrapper.find('label').props().children).toEqual('2a'); + const { container } = render(); + expect(container.querySelector('label').textContent).toEqual('testa'); + + fireEvent.change(container.querySelector('input'), { + target: { value: '1' }, + }); + expect(container.querySelector('label').textContent).toEqual('1a'); + + fireEvent.change(container.querySelector('input'), { + target: { value: '2' }, + }); + expect(container.querySelector('label').textContent).toEqual('2a'); expect(errorSpy).not.toHaveBeenCalled(); errorSpy.mockRestore(); @@ -137,8 +140,8 @@ describe('hooks', () => { return null; }; - const wrapper = mount(); - wrapper.unmount(); + const { unmount } = render(); + unmount(); setTimeout(() => { expect(errorSpy).not.toHaveBeenCalled(); @@ -146,7 +149,8 @@ describe('hooks', () => { }, 50); }); - it('throw', done => { + // This test no need in React 18 anymore + it.skip('throw', done => { const errorSpy = jest.spyOn(console, 'error'); const Demo = () => { @@ -164,8 +168,8 @@ describe('hooks', () => { return null; }; - const wrapper = mount(); - wrapper.unmount(); + const { unmount } = render(); + unmount(); setTimeout(() => { expect(errorSpy).toHaveBeenCalled(); diff --git a/tests/index.test.js b/tests/index.test.js index 6610a678..07e97523 100644 --- a/tests/index.test.js +++ b/tests/index.test.js @@ -26,6 +26,7 @@ describe('rc-util', () => { expect(ret).toEqual([1, 2, 3]); }); + // Note: Seems useless but not remove in case some code still use it it('PureRenderMixin works', () => { const div = document.createElement('div'); document.body.appendChild(div); diff --git a/tests/ref.test.js b/tests/ref.test.js index 35412b17..acc7c520 100644 --- a/tests/ref.test.js +++ b/tests/ref.test.js @@ -1,6 +1,6 @@ /* eslint-disable no-eval */ import React from 'react'; -import { mount } from 'enzyme'; +import { render } from '@testing-library/react'; import { composeRef, supportRef, useComposeRef } from '../src/ref'; describe('ref', () => { @@ -30,7 +30,7 @@ describe('ref', () => { const ref1 = React.createRef(); const ref2 = React.createRef(); - mount(); + render(); expect(ref1.current).toBeTruthy(); expect(ref1.current).toBe(ref2.current); @@ -38,43 +38,58 @@ describe('ref', () => { }); describe('supportRef', () => { + class Holder extends React.Component { + render() { + return this.props.children; + } + } + it('function component', () => { + const holderRef = React.createRef(); + function FC() { return
; } - const wrapper = mount( -
+ + render( + -
, + , ); expect(supportRef(FC)).toBeFalsy(); - expect(supportRef(wrapper.props().children)).toBeFalsy(); + expect(supportRef(holderRef.current.props.children)).toBeFalsy(); }); it('arrow function component', () => { + const holderRef = React.createRef(); + // Use eval since jest will convert arrow function to function const FC = eval('() => null'); - const wrapper = mount( -
+ render( + -
, + , ); expect(supportRef(FC)).toBeFalsy(); - expect(supportRef(wrapper.props().children)).toBeFalsy(); + expect(supportRef(holderRef.current.props.children)).toBeFalsy(); }); it('forwardRef function component', () => { + const holderRef = React.createRef(); + const FRC = React.forwardRef(() =>
); - const wrapper = mount( -
+ render( + -
, + , ); expect(supportRef(FRC)).toBeTruthy(); - expect(supportRef(wrapper.props().children)).toBeTruthy(); + expect(supportRef(holderRef.current.props.children)).toBeTruthy(); }); it('class component', () => { + const holderRef = React.createRef(); + class CC extends React.Component { state = {}; @@ -82,37 +97,41 @@ describe('ref', () => { return null; } } - const wrapper = mount( -
+ render( + -
, + , ); expect(supportRef(CC)).toBeTruthy(); - expect(supportRef(wrapper.props().children)).toBeTruthy(); + expect(supportRef(holderRef.current.props.children)).toBeTruthy(); }); it('memo of function component', () => { + const holderRef = React.createRef(); + const FC = () =>
; const MemoFC = React.memo(FC); - const wrapper = mount( -
+ render( + -
, + , ); expect(supportRef(MemoFC)).toBeFalsy(); - expect(supportRef(wrapper.props().children)).toBeFalsy(); + expect(supportRef(holderRef.current.props.children)).toBeFalsy(); }); it('memo of forwardRef function component', () => { + const holderRef = React.createRef(); + const FRC = React.forwardRef(() =>
); const MemoFC = React.memo(FRC); - const wrapper = mount( -
+ render( + -
, + , ); expect(supportRef(MemoFC)).toBeTruthy(); - expect(supportRef(wrapper.props().children)).toBeTruthy(); + expect(supportRef(holderRef.current.props.children)).toBeTruthy(); }); }); }); diff --git a/tests/setup.js b/tests/setup.js new file mode 100644 index 00000000..7b0828bf --- /dev/null +++ b/tests/setup.js @@ -0,0 +1 @@ +import '@testing-library/jest-dom'; diff --git a/tests/toArray.test.js b/tests/toArray.test.js index 37b5b81b..7cf23236 100644 --- a/tests/toArray.test.js +++ b/tests/toArray.test.js @@ -1,38 +1,50 @@ import React from 'react'; -import { mount } from 'enzyme'; +import { render } from '@testing-library/react'; import toArray from '../src/Children/toArray'; describe('toArray', () => { + class UL extends React.Component { + render() { + return
    {this.props.children}
; + } + } + it('basic', () => { - const wrapper = mount( -
    + const ulRef = React.createRef(); + + render( +
    • 1
    • 2
    • 3
    • -
    , +
, ); - const children = toArray(wrapper.props().children); + const children = toArray(ulRef.current.props.children); expect(children).toHaveLength(3); expect(children.map(c => c.key)).toEqual(['1', '2', '3']); }); it('Array', () => { - const wrapper = mount( -
    + const ulRef = React.createRef(); + + render( +
    • 1
    • {[
    • 2
    • ,
    • 3
    • ]} -
    , +
, ); - const children = toArray(wrapper.props().children); + const children = toArray(ulRef.current.props.children); expect(children).toHaveLength(3); expect(children.map(c => c.key)).toEqual(['1', '2', '3']); }); it('Fragment', () => { - const wrapper = mount( -
    + const ulRef = React.createRef(); + + render( +
    • 1
    • <>
    • 2
    • @@ -44,17 +56,19 @@ describe('toArray', () => {
    • 5
    • -
    , +
, ); - const children = toArray(wrapper.props().children); + const children = toArray(ulRef.current.props.children); expect(children).toHaveLength(5); expect(children.map(c => c.key)).toEqual(['1', '2', '3', '4', '5']); }); it('keep empty', () => { - const wrapper = mount( -
    + const ulRef = React.createRef(); + + render( +
      {null}
    • 1
    • <> @@ -70,10 +84,10 @@ describe('toArray', () => { {undefined} -
    , +
, ); - const children = toArray(wrapper.props().children, { keepEmpty: true }); + const children = toArray(ulRef.current.props.children, { keepEmpty: true }); expect(children).toHaveLength(9); expect(children.map(c => c && c.key)).toEqual([ null, diff --git a/tests/warning.test.js b/tests/warning.test.js index 65327f90..32b4ef26 100644 --- a/tests/warning.test.js +++ b/tests/warning.test.js @@ -1,5 +1,5 @@ import React from 'react'; -import { mount } from 'enzyme'; +import { render } from '@testing-library/react'; import warning, { resetWarned, noteOnce } from '../src/warning'; import unsafeLifecyclesPolyfill from '../src/unsafeLifecyclesPolyfill'; @@ -61,7 +61,7 @@ describe('warning', () => { } } const FixedWarningApp = unsafeLifecyclesPolyfill(App); - mount(); + render(); expect(warnSpy).not.toHaveBeenCalledWith( expect.stringContaining('componentWillReceiveProps has been renamed'), );