From 34a735958437e7962bcf7535f52f78c1b8f971ac Mon Sep 17 00:00:00 2001 From: "Gangwani, Pawan" Date: Fri, 8 Mar 2019 19:54:56 +0530 Subject: [PATCH 1/6] [Tests] add `useState`, more `useEffect`, custom hooks --- .../test/ReactWrapper-spec.jsx | 2 + .../test/ShallowWrapper-spec.jsx | 2 + .../test/shared/hooks/custom.jsx | 147 ++++++++++++++ .../test/shared/hooks/useEffect.jsx | 186 +++++++++++++++++- .../test/shared/hooks/useState.jsx | 87 ++++++++ 5 files changed, 420 insertions(+), 4 deletions(-) create mode 100644 packages/enzyme-test-suite/test/shared/hooks/custom.jsx create mode 100644 packages/enzyme-test-suite/test/shared/hooks/useState.jsx diff --git a/packages/enzyme-test-suite/test/ReactWrapper-spec.jsx b/packages/enzyme-test-suite/test/ReactWrapper-spec.jsx index 3bb53c877..d413e5040 100644 --- a/packages/enzyme-test-suite/test/ReactWrapper-spec.jsx +++ b/packages/enzyme-test-suite/test/ReactWrapper-spec.jsx @@ -1050,6 +1050,8 @@ describeWithDOM('mount', () => { 'useEffect', 'useLayoutEffect', 'useMemo', + 'useState', + 'custom', ); describeIf(is('>= 16.6'), 'Suspense & lazy', () => { diff --git a/packages/enzyme-test-suite/test/ShallowWrapper-spec.jsx b/packages/enzyme-test-suite/test/ShallowWrapper-spec.jsx index 780147f25..b9a52e930 100644 --- a/packages/enzyme-test-suite/test/ShallowWrapper-spec.jsx +++ b/packages/enzyme-test-suite/test/ShallowWrapper-spec.jsx @@ -1231,6 +1231,8 @@ describe('shallow', () => { 'useEffect', 'useLayoutEffect', 'useMemo', + 'useState', + 'custom', ); describe('.shallow()', () => { diff --git a/packages/enzyme-test-suite/test/shared/hooks/custom.jsx b/packages/enzyme-test-suite/test/shared/hooks/custom.jsx new file mode 100644 index 000000000..d6ea3daf1 --- /dev/null +++ b/packages/enzyme-test-suite/test/shared/hooks/custom.jsx @@ -0,0 +1,147 @@ +import React from 'react'; +import { expect } from 'chai'; +import sinon from 'sinon-sandbox'; + +import { + describeIf, +} from '../../_helpers'; + +import { + useEffect, + useState, +} from '../../_helpers/react-compat'; + +export default function describeCustomHooks({ + hasHooks, + Wrap, + isShallow, +}) { + describeIf(hasHooks, 'hooks: custom', () => { + describe('custom hook : useCounter', () => { + function useCounter({ initialCount = 0, step = 1 } = {}) { + const [count, setCount] = useState(initialCount); + const increment = () => setCount(c => c + step); + const decrement = () => setCount(c => c - step); + return { count, increment, decrement }; + } + // testing custom hooks with renderProps + // may be we can think of adding in utils + // will be repeated + const Counter = ({ children, ...rest }) => children(useCounter(rest)); + + function setup(props) { + const returnVal = {}; + Wrap( + + {(val) => { + Object.assign(returnVal, val); + return null; + }} + , + ); + return returnVal; + } + + it('useCounter', () => { + const counterData = setup(); + counterData.increment(); + expect(counterData).to.have.property('count', 1); + counterData.decrement(); + expect(counterData).to.have.property('count', 0); + }); + + it('useCounter with initialCount', () => { + const counterData = setup({ initialCount: 2 }); + counterData.increment(); + expect(counterData).to.have.property('count', 3); + counterData.decrement(); + expect(counterData).to.have.property('count', 2); + }); + + it('useCounter with step', () => { + const counterData = setup({ step: 2 }); + counterData.increment(); + expect(counterData).to.have.property('count', 2); + counterData.decrement(); + expect(counterData).to.have.property('count', 0); + }); + + it('useCounter with step and initialCount', () => { + const counterData = setup({ step: 2, initialCount: 5 }); + counterData.increment(); + expect(counterData).to.have.property('count', 7); + counterData.decrement(); + expect(counterData).to.have.property('count', 5); + }); + }); + + // todo: enable shallow when useEffect works in the shallow renderer. see https://github.com/facebook/react/issues/15275 + describeIf(!isShallow, 'custom hook: formInput simulate', () => { + function useFormInput(initialValue = '') { + const [value, setValue] = useState(initialValue); + + return { + value, + onChange(e) { + setValue(e.target.value); + }, + }; + } + + function Input(props) { + return ( +
+ +
+ ); + } + + function ControlledInputWithEnhancedInput({ searchSomething }) { + const search = useFormInput(); + + useEffect( + () => { + searchSomething(search.value); + }, + [search.value], + ); + + return ; + } + + function ControlledInputWithNativeInput({ searchSomething }) { + const search = useFormInput(); + + useEffect( + () => { + searchSomething(search.value); + }, + [search.value], + ); + + return ; + } + + it('does not succeed without act', () => { + const spy = sinon.spy(); + const wrapper = Wrap(); + // Works with Act + // act(() => { + wrapper.simulate('change', { target: { value: 'foo' } }); + // }); + + expect(spy.withArgs('foo')).to.have.property('callCount', 1); + }); + + // TODO: Need to evaluate as per issue raised + it.skip('does not succeed with/without act', () => { + const spy = sinon.spy(); + const wrapper = Wrap(); + // act(() => { + wrapper.simulate('change', { target: { value: 'foo' } }); + // }); + expect(spy.withArgs('foo')).to.have.property('callCount', 1); + }); + }); + }); +} diff --git a/packages/enzyme-test-suite/test/shared/hooks/useEffect.jsx b/packages/enzyme-test-suite/test/shared/hooks/useEffect.jsx index 66776695e..4dff4e840 100644 --- a/packages/enzyme-test-suite/test/shared/hooks/useEffect.jsx +++ b/packages/enzyme-test-suite/test/shared/hooks/useEffect.jsx @@ -1,14 +1,15 @@ import React from 'react'; import { expect } from 'chai'; +import sinon from 'sinon-sandbox'; import { describeIf, - itIf, } from '../../_helpers'; import { useEffect, useState, + Fragment, } from '../../_helpers/react-compat'; export default function describeUseEffect({ @@ -16,7 +17,8 @@ export default function describeUseEffect({ Wrap, isShallow, }) { - describeIf(hasHooks, 'hooks: useEffect', () => { + // TODO: enable when the shallow renderer fixes its bug, see https://github.com/facebook/react/issues/15275. + describeIf(hasHooks && !isShallow, 'hooks: useEffect', () => { const timeout = 100; function ComponentUsingEffectHook() { const [ctr, setCtr] = useState(0); @@ -33,8 +35,7 @@ export default function describeUseEffect({ ); } - // TODO: enable when the shallow renderer fixes its bug - itIf(!isShallow, 'works with `useEffect`', (done) => { + it('works', (done) => { const wrapper = Wrap(); expect(wrapper.debug()).to.equal( @@ -65,5 +66,182 @@ export default function describeUseEffect({ done(); }, timeout + 1); }); + + describe('with mount effect', () => { + const didMountCount = 9; + + function FooCounterWithMountEffect({ initialCount = 0 }) { + const [count, setCount] = useState(+initialCount); + + useEffect(() => { + setCount(didMountCount); + }, []); + return ( + + + {count} + + + ); + } + + it('initial render after did mount effect', () => { + const wrapper = Wrap(); + expect(wrapper.find('.counter').text()).to.equal(String(didMountCount)); + }); + }); + + describe('with async effect', () => { + it('works with `useEffect`', (done) => { + const wrapper = Wrap(); + + expect(wrapper.debug()).to.equal( + isShallow + ? `
+ 1 +
` + : ` +
+ 1 +
+
`, + ); + + setTimeout(() => { + wrapper.update(); + expect(wrapper.debug()).to.equal( + isShallow + ? `
+ 2 +
` + : ` +
+ 2 +
+
`, + ); + done(); + }, timeout + 1); + }); + }); + + describe('on componentDidUpdate & componentDidMount', () => { + const expectedCountString = x => `You clicked ${x} times`; + + let setDocumentTitle; + function ClickCounterPage() { + const [count, setCount] = useState(0); + + useEffect(() => { + setDocumentTitle(expectedCountString(count)); + }, [count]); + + return ( +
+

You clicked {count} times

+ +
+ ); + } + + beforeEach(() => { + setDocumentTitle = sinon.stub(); + }); + + it('on mount initial render', () => { + const wrapper = Wrap(); + + expect(wrapper.find('p').text()).to.eq(expectedCountString(0)); + expect(setDocumentTitle).to.have.property('callCount', 1); + expect(setDocumentTitle.args).to.deep.equal([[expectedCountString(0)]]); + }); + + // TODO: useEffect fixme + it.skip('on didupdate', () => { + const wrapper = Wrap(); + + expect(setDocumentTitle).to.have.property('callCount', 1); + expect(setDocumentTitle.args).to.deep.equal([[expectedCountString(0)]]); + expect(wrapper.find('p').text()).to.equal(expectedCountString(0)); + + const { onClick } = wrapper.find('button').props(); + onClick(); + + expect(setDocumentTitle).to.have.property('callCount', 2); + expect(setDocumentTitle.args).to.deep.equal([[expectedCountString(1)]]); + expect(wrapper.find('p').text()).to.equal(expectedCountString(1)); + + onClick(); + onClick(); + + expect(setDocumentTitle).to.have.property('callCount', 4); + expect(setDocumentTitle.args).to.deep.equal([[expectedCountString(3)]]); + expect(wrapper.find('p').text()).to.equal(expectedCountString(3)); + }); + }); + + describe('with cleanup Effect', () => { + let ChatAPI; + + beforeEach(() => { + ChatAPI = { + subscribeToFriendStatus: sinon.stub(), + unsubscribeFromFriendStatus: sinon.stub(), + }; + }); + + function FriendStatus({ friend = {} }) { + const [isOnline, setIsOnline] = useState(null); + + function handleStatusChange(status) { + setIsOnline(status.isOnline); + } + + useEffect(() => { + ChatAPI.subscribeToFriendStatus(friend.id, handleStatusChange); + return function cleanup() { + ChatAPI.unsubscribeFromFriendStatus(friend.id, handleStatusChange); + }; + }, [isOnline]); + + if (isOnline === null) { + return 'Loading...'; + } + return isOnline ? 'Online' : 'Offline'; + } + + const friend = { id: 'enzyme' }; + + it('on initial mount', () => { + const wrapper = Wrap(); + expect(wrapper.debug()).to.equal( + ` + Loading... +`, + ); + expect(wrapper.html()).to.eql('Loading...'); + expect(ChatAPI.subscribeToFriendStatus.calledOnceWith(friend.id)).to.equal(true); + }); + + it('simulate status Change', () => { + const wrapper = Wrap(); + const [[, simulateChange]] = ChatAPI.subscribeToFriendStatus.args; + + simulateChange({ isOnline: true }); + + wrapper.update(); + expect(wrapper.html()).to.eql('Online'); + }); + + it('cleanup on unmount', () => { + const wrapper = Wrap(); + + wrapper.unmount(); + + expect(ChatAPI.unsubscribeFromFriendStatus.calledOnceWith(friend.id)).to.equal(true); + }); + }); }); } diff --git a/packages/enzyme-test-suite/test/shared/hooks/useState.jsx b/packages/enzyme-test-suite/test/shared/hooks/useState.jsx new file mode 100644 index 000000000..2a7a1a679 --- /dev/null +++ b/packages/enzyme-test-suite/test/shared/hooks/useState.jsx @@ -0,0 +1,87 @@ +import React from 'react'; +import { expect } from 'chai'; + +import { + describeIf, + itIf, +} from '../../_helpers'; + +import { + useState, + useEffect, + Fragment, +} from '../../_helpers/react-compat'; + +export default function describeUseState({ + hasHooks, + Wrap, + isShallow, +}) { + describeIf(hasHooks, 'hooks: useState', () => { + function FooCounter({ initialCount: initial = 0 }) { + const [count, setCount] = useState(+initial); + + return ( + + + + {count} + + + + ); + } + + const initialCount = 5; + + it('initial render', () => { + const wrapper = Wrap(); + expect(wrapper.find('.counter').text()).to.equal(String(initialCount)); + }); + + it('lets increment', () => { + const wrapper = Wrap(); + + wrapper.find('.increment').props().onClick(); + + expect(wrapper.find('.counter').text()).to.equal(String(initialCount + 1)); + }); + + it('now decrement', () => { + const wrapper = Wrap(); + + wrapper.find('.decrement').props().onClick(); + + expect(wrapper.find('.counter').text()).to.equal(String(initialCount - 1)); + }); + + describe('useState with willReceive prop effect / simulate getDerivedStateFromProp', () => { + const newPropCount = 10; + + function FooCounterWithEffect({ initialCount: initial = 0 }) { + const [count, setCount] = useState(+initial); + + useEffect(() => { + setCount(initial); + }, [initial]); + + return ( + + + {count} + + + ); + } + + // TODO: fixme when useEffect works in the shallow renderer, see https://github.com/facebook/react/issues/15275 + itIf(!isShallow, 'initial render & new Props', () => { + const wrapper = Wrap(); + expect(wrapper.find('.counter').text()).to.equal(String(initialCount)); + + wrapper.setProps({ initialCount: newPropCount }); + expect(wrapper.find('.counter').text()).to.equal(String(newPropCount)); + }); + }); + }); +} From 39676a088f2b15f07852bf9f2917f59bddd64b7e Mon Sep 17 00:00:00 2001 From: "Gangwani, Pawan" Date: Sun, 17 Mar 2019 23:45:38 +0530 Subject: [PATCH 2/6] [Tests] `useReducer` --- .../test/ReactWrapper-spec.jsx | 1 + .../test/ShallowWrapper-spec.jsx | 1 + .../test/shared/hooks/useReducer.jsx | 78 +++++++++++++++++++ 3 files changed, 80 insertions(+) create mode 100644 packages/enzyme-test-suite/test/shared/hooks/useReducer.jsx diff --git a/packages/enzyme-test-suite/test/ReactWrapper-spec.jsx b/packages/enzyme-test-suite/test/ReactWrapper-spec.jsx index d413e5040..4c2efbe7b 100644 --- a/packages/enzyme-test-suite/test/ReactWrapper-spec.jsx +++ b/packages/enzyme-test-suite/test/ReactWrapper-spec.jsx @@ -1050,6 +1050,7 @@ describeWithDOM('mount', () => { 'useEffect', 'useLayoutEffect', 'useMemo', + 'useReducer', 'useState', 'custom', ); diff --git a/packages/enzyme-test-suite/test/ShallowWrapper-spec.jsx b/packages/enzyme-test-suite/test/ShallowWrapper-spec.jsx index b9a52e930..97f125a38 100644 --- a/packages/enzyme-test-suite/test/ShallowWrapper-spec.jsx +++ b/packages/enzyme-test-suite/test/ShallowWrapper-spec.jsx @@ -1231,6 +1231,7 @@ describe('shallow', () => { 'useEffect', 'useLayoutEffect', 'useMemo', + 'useReducer', 'useState', 'custom', ); diff --git a/packages/enzyme-test-suite/test/shared/hooks/useReducer.jsx b/packages/enzyme-test-suite/test/shared/hooks/useReducer.jsx new file mode 100644 index 000000000..6e0670858 --- /dev/null +++ b/packages/enzyme-test-suite/test/shared/hooks/useReducer.jsx @@ -0,0 +1,78 @@ +import React from 'react'; +import { expect } from 'chai'; + +import { describeIf } from '../../_helpers'; + +import { useReducer } from '../../_helpers/react-compat'; + +export default function describeUseReducer({ + hasHooks, + Wrap, +}) { + describeIf(hasHooks, 'hooks: useReducer', () => { + describe('with custom dispatch', () => { + const initialState = []; + + function Child({ dispatch, text }) { + function fire() { + dispatch({ + type: 'ADD_TEXT', + payload: text, + }); + } + + return ; + } + + function reducer(state, action) { + switch (action.type) { + case 'ADD_TEXT': + return [...state, action.payload]; + default: + throw new Error(); + } + } + + function FooBarTextList() { + const [state, dispatch] = useReducer(reducer, initialState); + + return ( +
+ + + {state.map(text => ( +

{text}

+ ))} +
+ ); + } + + it('render with initial state from useReducer', () => { + const wrapper = Wrap(); + expect(wrapper.find('p')).to.have.lengthOf(0); + }); + + it('Test with Add Foo & Bar tex', () => { + const wrapper = Wrap(); + expect(wrapper.find('p')).to.have.lengthOf(0); + wrapper.find('Child').at(0).props().dispatch({ + type: 'ADD_TEXT', + payload: 'foo', + }); + wrapper.update(); + + expect(wrapper.find('p')).to.have.lengthOf(1); + expect(wrapper.find('p').at(0).text()).to.equal('foo'); + + wrapper.find('Child').at(1).props().dispatch({ + type: 'ADD_TEXT', + payload: 'bar', + }); + wrapper.update(); + expect(wrapper.find('p')).to.have.length(2); + expect(wrapper.find('p').at(0).text()).to.equal('foo'); + expect(wrapper.find('p').at(1).text()).to.equal('bar'); + }); + }); + }); +} From 839005c39bef06143153e0f87f76ca8b2f99b63f Mon Sep 17 00:00:00 2001 From: "Gangwani, Pawan" Date: Mon, 18 Mar 2019 01:56:41 +0530 Subject: [PATCH 3/6] [Tests] `useContext` --- .../test/ReactWrapper-spec.jsx | 1 + .../test/ShallowWrapper-spec.jsx | 1 + .../test/shared/hooks/_hook.template | 1 + .../test/shared/hooks/useContext.jsx | 122 ++++++++++++++++++ 4 files changed, 125 insertions(+) create mode 100644 packages/enzyme-test-suite/test/shared/hooks/useContext.jsx diff --git a/packages/enzyme-test-suite/test/ReactWrapper-spec.jsx b/packages/enzyme-test-suite/test/ReactWrapper-spec.jsx index 4c2efbe7b..4aafb882a 100644 --- a/packages/enzyme-test-suite/test/ReactWrapper-spec.jsx +++ b/packages/enzyme-test-suite/test/ReactWrapper-spec.jsx @@ -1047,6 +1047,7 @@ describeWithDOM('mount', () => { describeHooks( { Wrap, Wrapper }, 'useCallback', + 'useContext', 'useEffect', 'useLayoutEffect', 'useMemo', diff --git a/packages/enzyme-test-suite/test/ShallowWrapper-spec.jsx b/packages/enzyme-test-suite/test/ShallowWrapper-spec.jsx index 97f125a38..0541bb5eb 100644 --- a/packages/enzyme-test-suite/test/ShallowWrapper-spec.jsx +++ b/packages/enzyme-test-suite/test/ShallowWrapper-spec.jsx @@ -1228,6 +1228,7 @@ describe('shallow', () => { describeHooks( { Wrap, Wrapper }, 'useCallback', + 'useContext', 'useEffect', 'useLayoutEffect', 'useMemo', diff --git a/packages/enzyme-test-suite/test/shared/hooks/_hook.template b/packages/enzyme-test-suite/test/shared/hooks/_hook.template index 92484f389..dcf04751f 100644 --- a/packages/enzyme-test-suite/test/shared/hooks/_hook.template +++ b/packages/enzyme-test-suite/test/shared/hooks/_hook.template @@ -19,6 +19,7 @@ import { import { useCallback, + useContext, useEffect, useLayoutEffect, useMemo, diff --git a/packages/enzyme-test-suite/test/shared/hooks/useContext.jsx b/packages/enzyme-test-suite/test/shared/hooks/useContext.jsx new file mode 100644 index 000000000..1d7f13e50 --- /dev/null +++ b/packages/enzyme-test-suite/test/shared/hooks/useContext.jsx @@ -0,0 +1,122 @@ +import React from 'react'; +import { expect } from 'chai'; + +import { + describeIf, + itIf, +} from '../../_helpers'; + +import { + useContext, + useState, + createContext, +} from '../../_helpers/react-compat'; + +export default function describeUseContext({ + hasHooks, + Wrap, + isShallow, +}) { + describeIf(hasHooks, 'hooks: useContext', () => { + describe('simple example', () => { + const initialTitle = 'initialTitle'; + const TitleContext = createContext && createContext(initialTitle); + + function UiComponent() { + const title = useContext(TitleContext); + return ( +
+ {title} +
+ ); + } + + const customTitle = 'CustomTitle'; + + function App() { + return ( + + + + ); + } + + it('render ui component with initial context value', () => { + const wrapper = Wrap(); + expect(wrapper.text()).to.equal(initialTitle); + }); + + // TODO: useContext: enable when shallow dive supports createContext + itIf(!isShallow, 'render ui component with value from outer provider', () => { + const wrapper = Wrap(); + const subWrapper = isShallow ? wrapper.dive().dive() : wrapper; + expect(subWrapper.text()).to.equal(customTitle); + }); + }); + + // TODO: useContext: enable when shallow dive supports createContext + describeIf(!isShallow, 'useContext: with Setting', () => { + const initialState = 10; + const context = createContext && createContext(null); + + function MyGrandChild() { + const myContextVal = useContext(context); + + const increment = () => { + myContextVal.setState(myContextVal.state + 1); + }; + + return ( +
+ + + {myContextVal.state} + +
+ ); + } + + function MyChild() { + return ( +
+ +
+ ); + } + + function App() { + const [state, setState] = useState(initialState); + + return ( + +
+ +
+
+ ); + } + + it('test render, get and set context value ', () => { + const wrapper = Wrap(); + + function getChild() { + const child = wrapper.find(MyChild); + return isShallow ? child.dive() : child; + } + function getGrandChild() { + const grandchild = getChild().find(MyGrandChild); + return isShallow ? grandchild.dive() : grandchild; + } + expect(getGrandChild().find('.grandChildState').debug()).to.equal(` + ${String(initialState)} +`); + + getGrandChild().find('button').props().onClick(); + wrapper.update(); + expect(getGrandChild().find('.grandChildState').debug()).to.equal(` + ${String(initialState + 1)} +`); + }); + }); + }); +} From 48cc351ad4743aa894bf5018b11ad835c5c73bff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=B3=E4=B9=99=E5=B1=B1?= Date: Tue, 29 Jan 2019 16:42:59 +0800 Subject: [PATCH 4/6] [Tests] more `useState` --- .../test/shared/hooks/useState.jsx | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/packages/enzyme-test-suite/test/shared/hooks/useState.jsx b/packages/enzyme-test-suite/test/shared/hooks/useState.jsx index 2a7a1a679..30569d6cb 100644 --- a/packages/enzyme-test-suite/test/shared/hooks/useState.jsx +++ b/packages/enzyme-test-suite/test/shared/hooks/useState.jsx @@ -55,6 +55,33 @@ export default function describeUseState({ expect(wrapper.find('.counter').text()).to.equal(String(initialCount - 1)); }); + it('handles useState', () => { + function ComponentUsingStateHook() { + const [count] = useState(0); + return
{count}
; + } + + const wrapper = Wrap(); + + expect(wrapper.find('div').length).to.equal(1); + expect(wrapper.find('div').text()).to.equal('0'); + }); + + it('handles setState returned from useState', () => { + function ComponentUsingStateHook() { + const [count, setCount] = useState(0); + return
setCount(count + 1)}>{count}
; + } + + const wrapper = Wrap(); + const div = wrapper.find('div'); + const setCount = div.prop('onClick'); + setCount(); + wrapper.update(); + + expect(wrapper.find('div').text()).to.equal('1'); + }); + describe('useState with willReceive prop effect / simulate getDerivedStateFromProp', () => { const newPropCount = 10; From 9abded260e86c3defc45213207d7afe4476b89f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=B3=E4=B9=99=E5=B1=B1?= Date: Tue, 11 Jun 2019 10:26:15 +0800 Subject: [PATCH 5/6] [Tests] fix custom form input hook test --- .../test/shared/hooks/custom.jsx | 25 +++++++++++-------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/packages/enzyme-test-suite/test/shared/hooks/custom.jsx b/packages/enzyme-test-suite/test/shared/hooks/custom.jsx index d6ea3daf1..8aad509d3 100644 --- a/packages/enzyme-test-suite/test/shared/hooks/custom.jsx +++ b/packages/enzyme-test-suite/test/shared/hooks/custom.jsx @@ -76,7 +76,7 @@ export default function describeCustomHooks({ }); // todo: enable shallow when useEffect works in the shallow renderer. see https://github.com/facebook/react/issues/15275 - describeIf(!isShallow, 'custom hook: formInput simulate', () => { + describeIf(!isShallow, 'custom hook: formInput invoke props', () => { function useFormInput(initialValue = '') { const [value, setValue] = useState(initialValue); @@ -122,24 +122,27 @@ export default function describeCustomHooks({ return ; } - it('does not succeed without act', () => { + it('work with native input', () => { const spy = sinon.spy(); const wrapper = Wrap(); - // Works with Act - // act(() => { - wrapper.simulate('change', { target: { value: 'foo' } }); - // }); + wrapper.find('input').invoke('onChange')({ target: { value: 'foo' } }); expect(spy.withArgs('foo')).to.have.property('callCount', 1); }); - // TODO: Need to evaluate as per issue raised - it.skip('does not succeed with/without act', () => { + it('work with custom wrapped Input', () => { const spy = sinon.spy(); const wrapper = Wrap(); - // act(() => { - wrapper.simulate('change', { target: { value: 'foo' } }); - // }); + const input = wrapper.find('Input'); + input.invoke('onChange')({ target: { value: 'foo' } }); + expect(spy.withArgs('foo')).to.have.property('callCount', 1); + }); + + it('work with custom wrapped input', () => { + const spy = sinon.spy(); + const wrapper = Wrap(); + const input = wrapper.find('input'); + input.invoke('onChange')({ target: { value: 'foo' } }); expect(spy.withArgs('foo')).to.have.property('callCount', 1); }); }); From d9fa3f0995f85b8d164b90b2dabdebe5e1d3e2e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=B3=E4=B9=99=E5=B1=B1?= Date: Tue, 11 Jun 2019 10:39:59 +0800 Subject: [PATCH 6/6] [Tests] `useEffect`: Fix set document title test --- .../test/shared/hooks/useEffect.jsx | 30 +++++++++++-------- 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/packages/enzyme-test-suite/test/shared/hooks/useEffect.jsx b/packages/enzyme-test-suite/test/shared/hooks/useEffect.jsx index 4dff4e840..9f49d818d 100644 --- a/packages/enzyme-test-suite/test/shared/hooks/useEffect.jsx +++ b/packages/enzyme-test-suite/test/shared/hooks/useEffect.jsx @@ -4,8 +4,11 @@ import sinon from 'sinon-sandbox'; import { describeIf, + itIf, } from '../../_helpers'; - +import { + is, +} from '../../_helpers/version'; import { useEffect, useState, @@ -158,26 +161,27 @@ export default function describeUseEffect({ expect(setDocumentTitle.args).to.deep.equal([[expectedCountString(0)]]); }); - // TODO: useEffect fixme - it.skip('on didupdate', () => { + it('on didupdate', () => { const wrapper = Wrap(); expect(setDocumentTitle).to.have.property('callCount', 1); - expect(setDocumentTitle.args).to.deep.equal([[expectedCountString(0)]]); + const [firstCall] = setDocumentTitle.args; + expect(firstCall).to.deep.equal([expectedCountString(0)]); expect(wrapper.find('p').text()).to.equal(expectedCountString(0)); - const { onClick } = wrapper.find('button').props(); - onClick(); + wrapper.find('button').invoke('onClick')(); expect(setDocumentTitle).to.have.property('callCount', 2); - expect(setDocumentTitle.args).to.deep.equal([[expectedCountString(1)]]); + const [, secondCall] = setDocumentTitle.args; + expect(secondCall).to.deep.equal([expectedCountString(1)]); expect(wrapper.find('p').text()).to.equal(expectedCountString(1)); - onClick(); - onClick(); + wrapper.find('button').invoke('onClick')(); + wrapper.find('button').invoke('onClick')(); expect(setDocumentTitle).to.have.property('callCount', 4); - expect(setDocumentTitle.args).to.deep.equal([[expectedCountString(3)]]); + const [,,, fourthCall] = setDocumentTitle.args; + expect(fourthCall).to.deep.equal([expectedCountString(3)]); expect(wrapper.find('p').text()).to.equal(expectedCountString(3)); }); }); @@ -235,12 +239,14 @@ export default function describeUseEffect({ expect(wrapper.html()).to.eql('Online'); }); - it('cleanup on unmount', () => { + itIf(is('> 16.8.3'), 'cleanup on unmount', () => { const wrapper = Wrap(); wrapper.unmount(); - expect(ChatAPI.unsubscribeFromFriendStatus.calledOnceWith(friend.id)).to.equal(true); + expect(ChatAPI.unsubscribeFromFriendStatus).to.have.property('callCount', 1); + const [[firstArg]] = ChatAPI.unsubscribeFromFriendStatus.args; + expect(firstArg).to.equal(friend.id); }); }); });