From cbb44d5b3f5dec41feda759c0839f2da0b3cd528 Mon Sep 17 00:00:00 2001 From: zombiej Date: Wed, 6 Apr 2022 17:05:49 +0800 Subject: [PATCH 1/6] test: part test --- package.json | 6 ++-- tests/hooks.test.js | 69 ++++++++++++++++++++++++--------------------- 2 files changed, 41 insertions(+), 34 deletions(-) diff --git a/package.json b/package.json index 131ba7fd..42996c43 100644 --- a/package.json +++ b/package.json @@ -29,7 +29,6 @@ "now-build": "father doc build --storybook" }, "devDependencies": { - "@types/enzyme": "^3.10.5", "@types/jest": "^25.2.3", "@types/react": "^16.9.3", "@types/react-dom": "^16.9.1", @@ -39,7 +38,6 @@ "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", @@ -49,6 +47,10 @@ }, "dependencies": { "@babel/runtime": "^7.12.5", + "@testing-library/jest-dom": "^5.16.4", + "@testing-library/react": "^13.0.0", + "react": "^18.0.0", + "react-dom": "^18.0.0", "react-is": "^16.12.0", "shallowequal": "^1.1.0" }, diff --git a/tests/hooks.test.js b/tests/hooks.test.js index 0120839e..4239c3b3 100644 --- a/tests/hooks.test.js +++ b/tests/hooks.test.js @@ -1,5 +1,6 @@ import * as React from 'react'; -import { mount } from 'enzyme'; +import { render, fireEvent } from '@testing-library/react'; +import '@testing-library/jest-dom'; import useMemo from '../src/hooks/useMemo'; import useMergedState from '../src/hooks/useMergedState'; import useLayoutEffect from '../src/hooks/useLayoutEffect'; @@ -13,20 +14,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 +44,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 +74,8 @@ describe('hooks', () => { return
{val}
; }; - const wrapper = mount(); - expect(wrapper.text()).toEqual('1'); + const { container } = render(); + expect(container.firstChild.textContent).toEqual('1'); }); }); @@ -104,14 +104,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 +141,8 @@ describe('hooks', () => { return null; }; - const wrapper = mount(); - wrapper.unmount(); + const { unmount } = render(); + unmount(); setTimeout(() => { expect(errorSpy).not.toHaveBeenCalled(); @@ -146,7 +150,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 +169,8 @@ describe('hooks', () => { return null; }; - const wrapper = mount(); - wrapper.unmount(); + const { unmount } = render(); + unmount(); setTimeout(() => { expect(errorSpy).toHaveBeenCalled(); From 283a8c83e08a83decf05700018f6331e949e4f6b Mon Sep 17 00:00:00 2001 From: zombiej Date: Wed, 6 Apr 2022 17:30:30 +0800 Subject: [PATCH 2/6] test: all test case convert --- tests/Portal.test.tsx | 62 ++++++++++++++++++++++--------------- tests/ref.test.js | 72 +++++++++++++++++++++++++++---------------- tests/toArray.test.js | 49 +++++++++++++++++++---------- tests/warning.test.js | 5 +-- 4 files changed, 118 insertions(+), 70 deletions(-) diff --git a/tests/Portal.test.tsx b/tests/Portal.test.tsx index cf3e4d5e..0d97c407 100644 --- a/tests/Portal.test.tsx +++ b/tests/Portal.test.tsx @@ -1,29 +1,30 @@ import React from 'react'; -import { mount } from 'enzyme'; +import { render } from '@testing-library/react'; +import '@testing-library/jest-dom'; 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 +32,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 +49,15 @@ describe('Portal', () => { expect(didUpdate).toHaveBeenCalledTimes(1); - wrapper.setProps({ justForceUpdate: true }); + rerender( + document.createElement('div')} + {...{ justForceUpdate: true }} + > + light + , + ); expect(didUpdate).toHaveBeenCalledTimes(2); }); @@ -58,7 +67,7 @@ describe('Portal', () => { div.id = 'bamboo-light'; document.body.appendChild(div); - mount( + render( {() =>
2333
}
, @@ -74,7 +83,7 @@ describe('Portal', () => { it('function', () => { const div = document.createElement('div'); - mount( + render( div}> {() =>
2333
}
, @@ -86,7 +95,7 @@ describe('Portal', () => { it('htmlElement', () => { const div = document.createElement('div'); - mount( + render( {() =>
2333
}
, @@ -98,7 +107,7 @@ describe('Portal', () => { it('delay', () => { jest.useFakeTimers(); const divRef = React.createRef(); - const wrapper = mount( + render(
divRef.current}> {() =>
} @@ -109,7 +118,6 @@ describe('Portal', () => { act(() => { jest.runAllTimers(); - wrapper.update(); }); expect(divRef.current.childElementCount).toEqual(1); @@ -121,15 +129,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 +161,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/ref.test.js b/tests/ref.test.js index 35412b17..3de0509a 100644 --- a/tests/ref.test.js +++ b/tests/ref.test.js @@ -1,6 +1,7 @@ /* eslint-disable no-eval */ import React from 'react'; -import { mount } from 'enzyme'; +import { render } from '@testing-library/react'; +import '@testing-library/jest-dom'; import { composeRef, supportRef, useComposeRef } from '../src/ref'; describe('ref', () => { @@ -30,7 +31,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 +39,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 +98,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/toArray.test.js b/tests/toArray.test.js index 37b5b81b..20ee170a 100644 --- a/tests/toArray.test.js +++ b/tests/toArray.test.js @@ -1,38 +1,51 @@ import React from 'react'; -import { mount } from 'enzyme'; +import { render } from '@testing-library/react'; +import '@testing-library/jest-dom'; 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 +57,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 +85,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..af007286 100644 --- a/tests/warning.test.js +++ b/tests/warning.test.js @@ -1,5 +1,6 @@ import React from 'react'; -import { mount } from 'enzyme'; +import { render } from '@testing-library/react'; +import '@testing-library/jest-dom'; import warning, { resetWarned, noteOnce } from '../src/warning'; import unsafeLifecyclesPolyfill from '../src/unsafeLifecyclesPolyfill'; @@ -61,7 +62,7 @@ describe('warning', () => { } } const FixedWarningApp = unsafeLifecyclesPolyfill(App); - mount(); + render(); expect(warnSpy).not.toHaveBeenCalledWith( expect.stringContaining('componentWillReceiveProps has been renamed'), ); From 5e01a1f304cb463573c1e999c4c49d2afc24372b Mon Sep 17 00:00:00 2001 From: zombiej Date: Wed, 6 Apr 2022 17:33:49 +0800 Subject: [PATCH 3/6] chore: comment --- tests/index.test.js | 1 + 1 file changed, 1 insertion(+) 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); From e980fd816f95ce327c55e08ec439bcf330c115a3 Mon Sep 17 00:00:00 2001 From: zombiej Date: Wed, 6 Apr 2022 17:35:07 +0800 Subject: [PATCH 4/6] chore: pkg deps --- package.json | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 42996c43..c6628540 100644 --- a/package.json +++ b/package.json @@ -41,16 +41,14 @@ "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": { "@babel/runtime": "^7.12.5", "@testing-library/jest-dom": "^5.16.4", "@testing-library/react": "^13.0.0", - "react": "^18.0.0", - "react-dom": "^18.0.0", "react-is": "^16.12.0", "shallowequal": "^1.1.0" }, From 377c58dd75cdd688fdf6d41c7cae87c92bd3ee45 Mon Sep 17 00:00:00 2001 From: zombiej Date: Wed, 6 Apr 2022 17:35:29 +0800 Subject: [PATCH 5/6] chore: pkg deps --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index c6628540..d7f66935 100644 --- a/package.json +++ b/package.json @@ -29,6 +29,8 @@ "now-build": "father doc build --storybook" }, "devDependencies": { + "@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", @@ -47,8 +49,6 @@ }, "dependencies": { "@babel/runtime": "^7.12.5", - "@testing-library/jest-dom": "^5.16.4", - "@testing-library/react": "^13.0.0", "react-is": "^16.12.0", "shallowequal": "^1.1.0" }, From c827a0df610be57d08642e40110854355ad2407a Mon Sep 17 00:00:00 2001 From: zombiej Date: Wed, 6 Apr 2022 17:48:06 +0800 Subject: [PATCH 6/6] chore: move config --- jest.config.js | 3 +++ tests/Portal.test.tsx | 1 - tests/hooks.test.js | 1 - tests/ref.test.js | 1 - tests/setup.js | 1 + tests/toArray.test.js | 1 - tests/warning.test.js | 1 - 7 files changed, 4 insertions(+), 5 deletions(-) create mode 100644 jest.config.js create mode 100644 tests/setup.js 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/tests/Portal.test.tsx b/tests/Portal.test.tsx index 0d97c407..de964aa6 100644 --- a/tests/Portal.test.tsx +++ b/tests/Portal.test.tsx @@ -1,6 +1,5 @@ import React from 'react'; import { render } from '@testing-library/react'; -import '@testing-library/jest-dom'; import { act } from 'react-dom/test-utils'; import PortalWrapper, { getOpenCount } from '../src/PortalWrapper'; import Portal from '../src/Portal'; diff --git a/tests/hooks.test.js b/tests/hooks.test.js index 4239c3b3..0a769388 100644 --- a/tests/hooks.test.js +++ b/tests/hooks.test.js @@ -1,6 +1,5 @@ import * as React from 'react'; import { render, fireEvent } from '@testing-library/react'; -import '@testing-library/jest-dom'; import useMemo from '../src/hooks/useMemo'; import useMergedState from '../src/hooks/useMergedState'; import useLayoutEffect from '../src/hooks/useLayoutEffect'; diff --git a/tests/ref.test.js b/tests/ref.test.js index 3de0509a..acc7c520 100644 --- a/tests/ref.test.js +++ b/tests/ref.test.js @@ -1,7 +1,6 @@ /* eslint-disable no-eval */ import React from 'react'; import { render } from '@testing-library/react'; -import '@testing-library/jest-dom'; import { composeRef, supportRef, useComposeRef } from '../src/ref'; describe('ref', () => { 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 20ee170a..7cf23236 100644 --- a/tests/toArray.test.js +++ b/tests/toArray.test.js @@ -1,6 +1,5 @@ import React from 'react'; import { render } from '@testing-library/react'; -import '@testing-library/jest-dom'; import toArray from '../src/Children/toArray'; describe('toArray', () => { diff --git a/tests/warning.test.js b/tests/warning.test.js index af007286..32b4ef26 100644 --- a/tests/warning.test.js +++ b/tests/warning.test.js @@ -1,6 +1,5 @@ import React from 'react'; import { render } from '@testing-library/react'; -import '@testing-library/jest-dom'; import warning, { resetWarned, noteOnce } from '../src/warning'; import unsafeLifecyclesPolyfill from '../src/unsafeLifecyclesPolyfill';