diff --git a/test/components/connect.spec.tsx b/test/components/connect.spec.tsx index a63660e99..07110b402 100644 --- a/test/components/connect.spec.tsx +++ b/test/components/connect.spec.tsx @@ -3,7 +3,6 @@ import React, { Component, MouseEvent } from 'react' import createClass from 'create-react-class' import PropTypes from 'prop-types' -import ReactDOM from 'react-dom' import { createStore, applyMiddleware } from 'redux' import { Provider as ProviderMock, connect } from '../../src/index' import * as rtl from '@testing-library/react' @@ -402,7 +401,9 @@ describe('React', () => { expect(tester.getByTestId('x')).toHaveTextContent('true') props = {} - container.current!.forceUpdate() + rtl.act(() => { + container.current!.forceUpdate() + }) expect(tester.queryByTestId('x')).toBe(null) }) @@ -440,7 +441,9 @@ describe('React', () => { expect(tester.getByTestId('x')).toHaveTextContent('true') props = {} - container.current!.forceUpdate() + rtl.act(() => { + container.current!.forceUpdate() + }) expect(tester.getAllByTitle('prop').length).toBe(1) expect(tester.getByTestId('dispatch')).toHaveTextContent( @@ -888,8 +891,14 @@ describe('React', () => { ) - outerComponent.current!.setFoo('BAR') - outerComponent.current!.setFoo('DID') + expect(invocationCount).toEqual(1) + rtl.act(() => { + outerComponent.current!.setFoo('BAR') + }) + rtl.act(() => { + outerComponent.current!.setFoo('BAZ') + outerComponent.current!.setFoo('DID') + }) expect(invocationCount).toEqual(3) }) @@ -937,8 +946,16 @@ describe('React', () => { ) - outerComponent.current!.setFoo('BAR') - outerComponent.current!.setFoo('BAZ') + expect(invocationCount).toEqual(1) + rtl.act(() => { + outerComponent.current!.setFoo('QUUX') + }) + + expect(invocationCount).toEqual(2) + rtl.act(() => { + outerComponent.current!.setFoo('BAR') + outerComponent.current!.setFoo('BAZ') + }) expect(invocationCount).toEqual(3) expect(propsPassedIn).toEqual({ @@ -988,8 +1005,12 @@ describe('React', () => { ) - outerComponent.current!.setFoo('BAR') - outerComponent.current!.setFoo('DID') + rtl.act(() => { + outerComponent.current!.setFoo('BAR') + }) + rtl.act(() => { + outerComponent.current!.setFoo('DID') + }) expect(invocationCount).toEqual(1) }) @@ -1034,9 +1055,17 @@ describe('React', () => { ) + expect(invocationCount).toEqual(1) + rtl.act(() => { + outerComponent.current!.setFoo('BAR') + }) - outerComponent.current!.setFoo('BAR') - outerComponent.current!.setFoo('DID') + expect(invocationCount).toEqual(2) + + rtl.act(() => { + outerComponent.current!.setFoo('DID') + outerComponent.current!.setFoo('QUUX') + }) expect(invocationCount).toEqual(3) }) @@ -1084,12 +1113,22 @@ describe('React', () => { ) - outerComponent.current!.setFoo('BAR') - outerComponent.current!.setFoo('BAZ') + expect(invocationCount).toEqual(1) + rtl.act(() => { + outerComponent.current!.setFoo('BAR') + }) + + expect(invocationCount).toEqual(2) + + rtl.act(() => { + outerComponent.current!.setFoo('DID') + outerComponent.current!.setFoo('QUUX') + }) expect(invocationCount).toEqual(3) + expect(propsPassedIn).toEqual({ - foo: 'BAZ', + foo: 'QUUX', }) }) }) @@ -1160,12 +1199,10 @@ describe('React', () => { string >((state) => ({ state }))(Child) - const div = document.createElement('div') - ReactDOM.render( + const { unmount } = rtl.render( - , - div + ) try { @@ -1173,7 +1210,7 @@ describe('React', () => { store.dispatch({ type: 'APPEND', body: 'A' }) }) } finally { - ReactDOM.unmountComponentAtNode(div) + unmount() } }) @@ -1212,6 +1249,7 @@ describe('React', () => { const A = () =>

A

function mapState(state: {}) { const calls = ++mapStateToPropsCalls + console.trace('Call: ', calls) return { calls, state } } const ConnectedA = connect(mapState)(A) @@ -1252,28 +1290,27 @@ describe('React', () => { } } - const div = document.createElement('div') - document.body.appendChild(div) - ReactDOM.render( + const { unmount } = rtl.render( - , - div + ) - const spy = jest.spyOn(console, 'error').mockImplementation(() => {}) - linkA.current!.click() - linkB.current!.click() - linkB.current!.click() - document.body.removeChild(div) + // const spy = jest.spyOn(console, 'error').mockImplementation(() => {}) + rtl.act(() => { + linkA.current!.click() + linkB.current!.click() + linkB.current!.click() + unmount() + }) // Called 3 times: // - Initial mount - // - After first link click, stil mounted + // - After first link click, still mounted // - After second link click, but the queued state update is discarded due to batching as it's unmounted expect(mapStateToPropsCalls).toBe(3) - expect(spy).toHaveBeenCalledTimes(0) - spy.mockRestore() + // expect(spy).toHaveBeenCalledTimes(0) + // spy.mockRestore() }) it('should not attempt to set state when dispatching in componentWillUnmount', () => { @@ -1297,17 +1334,16 @@ describe('React', () => { (state) => ({ calls: mapStateToPropsCalls++ }), (dispatch) => ({ dispatch }) )(Container) - const div = document.createElement('div') - ReactDOM.render( + + const { unmount } = rtl.render( - , - div + ) expect(mapStateToPropsCalls).toBe(1) const spy = jest.spyOn(console, 'error').mockImplementation(() => {}) - ReactDOM.unmountComponentAtNode(div) + unmount() expect(spy).toHaveBeenCalledTimes(0) expect(mapStateToPropsCalls).toBe(1) spy.mockRestore() @@ -1327,18 +1363,17 @@ describe('React', () => { (dispatch) => ({ dispatch }) )(Inner) - const div = document.createElement('div') + let unmount: ReturnType['unmount'] store.subscribe(() => { - ReactDOM.unmountComponentAtNode(div) + unmount() }) rtl.act(() => { - ReactDOM.render( + unmount = rtl.render( - , - div - ) + + ).unmount }) expect(mapStateToPropsCalls).toBe(1) @@ -1405,15 +1440,13 @@ describe('React', () => { store.dispatch({ type: 'fetch' }) }) - const div = document.createElement('div') - ReactDOM.render( + const { unmount } = rtl.render( - , - div + ) - ReactDOM.unmountComponentAtNode(div) + unmount() }) }) @@ -2114,9 +2147,13 @@ describe('React', () => { ) expect(mapStateToProps).toHaveBeenCalledTimes(0) - store.dispatch({ type: 'INC' }) + rtl.act(() => { + store.dispatch({ type: 'INC' }) + }) expect(mapStateToProps).toHaveBeenCalledTimes(1) - store.dispatch({ type: 'INC' }) + rtl.act(() => { + store.dispatch({ type: 'INC' }) + }) expect(mapStateToProps).toHaveBeenCalledTimes(1) }) }) @@ -2516,7 +2553,7 @@ describe('React', () => { }) describe('Refs', () => { - it('should return the instance of the wrapped component for use in calling child methods', async (done) => { + it('should return the instance of the wrapped component for use in calling child methods', async () => { const store = createStore(() => ({})) const someData = { @@ -2555,7 +2592,6 @@ describe('React', () => { await tester.findByTestId('loaded') expect(ref.current!.someInstanceMethod()).toBe(someData) - done() }) it('should correctly separate and pass through props to the wrapped component with a forwarded ref', () => { @@ -2601,7 +2637,7 @@ describe('React', () => { }) describe('Impure behavior', () => { - it('should return the instance of the wrapped component for use in calling child methods, impure component', async (done) => { + it('should return the instance of the wrapped component for use in calling child methods, impure component', async () => { const store = createStore(() => ({})) const someData = { @@ -2641,7 +2677,6 @@ describe('React', () => { await tester.findByTestId('loaded') expect(ref.current!.someInstanceMethod()).toBe(someData) - done() }) it('should wrap impure components without supressing updates', () => { @@ -2695,8 +2730,10 @@ describe('React', () => { ) expect(tester.getByTestId('statefulValue')).toHaveTextContent('0') - //@ts-ignore - externalSetState({ value: 1 }) + rtl.act(() => { + //@ts-ignore + externalSetState({ value: 1 }) + }) expect(tester.getByTestId('statefulValue')).toHaveTextContent('1') }) @@ -2744,7 +2781,7 @@ describe('React', () => { ) const Decorated = decorator(ImpureComponent) - let externalSetState + let externalSetState: any let storeGetter = { storeKey: 'foo' } type StatefulWrapperStateType = { storeGetter: typeof storeGetter @@ -2785,8 +2822,10 @@ describe('React', () => { // Impure update storeGetter.storeKey = 'bar' - //@ts-ignore - externalSetState({ storeGetter }) + rtl.act(() => { + //@ts-ignore + externalSetState({ storeGetter }) + }) // 4) After the the impure update expect(mapStateSpy).toHaveBeenCalledTimes(3) @@ -3317,8 +3356,14 @@ describe('React', () => { ) - outerComponent.current!.setState(({ count }) => ({ count: count + 1 })) - store.dispatch({ type: '' }) + rtl.act(() => { + outerComponent.current!.setState(({ count }) => ({ + count: count + 1, + })) + + store.dispatch({ type: '' }) + }) + //@ts-ignore expect(propsPassedIn.count).toEqual(1) //@ts-ignore @@ -3429,7 +3474,9 @@ describe('React', () => { expect(rendered.getByTestId('child').dataset.prop).toEqual('a') // Force the multi-update sequence by running this bound action creator - parent.current!.inc1() + rtl.act(() => { + parent.current!.inc1() + }) // The connected child component _should_ have rendered with the latest Redux // store value (3) _and_ the latest wrapper prop ('b'). diff --git a/test/hooks/useSelector.spec.tsx b/test/hooks/useSelector.spec.tsx index a9d48f11c..2327c8ea1 100644 --- a/test/hooks/useSelector.spec.tsx +++ b/test/hooks/useSelector.spec.tsx @@ -102,7 +102,9 @@ describe('React', () => { expect(renderedItems).toEqual([1]) - store.dispatch({ type: '' }) + act(() => { + store.dispatch({ type: '' }) + }) expect(renderedItems).toEqual([1, 2]) }) @@ -130,7 +132,10 @@ describe('React', () => { // @ts-ignore ts(2454) expect(rootSubscription.getListeners().get().length).toBe(1) - normalStore.dispatch({ type: '' }) + act(() => { + normalStore.dispatch({ type: '' }) + }) + // @ts-ignore ts(2454) expect(rootSubscription.getListeners().get().length).toBe(2) }) @@ -158,7 +163,10 @@ describe('React', () => { // @ts-ignore ts(2454) expect(rootSubscription.getListeners().get().length).toBe(2) - normalStore.dispatch({ type: '' }) + act(() => { + normalStore.dispatch({ type: '' }) + }) + // @ts-ignore ts(2454) expect(rootSubscription.getListeners().get().length).toBe(1) }) @@ -246,7 +254,9 @@ describe('React', () => { expect(renderedItems.length).toBe(1) - store.dispatch({ type: '' }) + act(() => { + store.dispatch({ type: '' }) + }) expect(renderedItems.length).toBe(1) }) @@ -279,7 +289,9 @@ describe('React', () => { expect(renderedItems.length).toBe(1) - store.dispatch({ type: '' }) + act(() => { + store.dispatch({ type: '' }) + }) expect(renderedItems.length).toBe(1) }) @@ -381,9 +393,11 @@ describe('React', () => { rtl.render() - expect(() => store.dispatch({ type: '' })).toThrow( - /The error may be correlated/ - ) + expect(() => { + act(() => { + store.dispatch({ type: '' }) + }) + }).toThrow(/The error may be correlated/) spy.mockRestore() }) @@ -414,7 +428,11 @@ describe('React', () => { ) - expect(() => normalStore.dispatch({ type: '' })).toThrowError() + expect(() => { + act(() => { + normalStore.dispatch({ type: '' }) + }) + }).toThrowError() spy.mockRestore() }) @@ -484,7 +502,9 @@ describe('React', () => { expect(renderedItems.length).toBe(1) - normalStore.dispatch({ type: '' }) + act(() => { + normalStore.dispatch({ type: '' }) + }) expect(renderedItems.length).toBe(2) expect(renderedItems[0]).toBe(renderedItems[1])