From f85f429d55f3f13bd741b4e4a06e3fcc54f2330c Mon Sep 17 00:00:00 2001 From: Andrew Clark Date: Thu, 8 Jul 2021 22:35:46 -0400 Subject: [PATCH] Use `act()` in ReactFabric tests (#21839) (#21841) Co-authored-by: Timothy Yung --- .../__tests__/ReactFabric-test.internal.js | 461 +++++++++++------- 1 file changed, 273 insertions(+), 188 deletions(-) diff --git a/packages/react-native-renderer/src/__tests__/ReactFabric-test.internal.js b/packages/react-native-renderer/src/__tests__/ReactFabric-test.internal.js index a935da5e4df63..4c5bea872bbd8 100644 --- a/packages/react-native-renderer/src/__tests__/ReactFabric-test.internal.js +++ b/packages/react-native-renderer/src/__tests__/ReactFabric-test.internal.js @@ -16,6 +16,7 @@ let createReactNativeComponentClass; let UIManager; let StrictMode; let TextInputState; +let act; const SET_NATIVE_PROPS_NOT_SUPPORTED_MESSAGE = 'Warning: setNativeProps is not currently supported in Fabric'; @@ -47,6 +48,8 @@ describe('ReactFabric', () => { .ReactNativeViewConfigRegistry.register; TextInputState = require('react-native/Libraries/ReactPrivate/ReactNativePrivateInterface') .TextInputState; + + act = require('jest-react').act; }); it('should be able to create and render a native component', () => { @@ -55,7 +58,9 @@ describe('ReactFabric', () => { uiViewClassName: 'RCTView', })); - ReactFabric.render(, 1); + act(() => { + ReactFabric.render(, 1); + }); expect(nativeFabricUIManager.createNode).toBeCalled(); expect(nativeFabricUIManager.appendChild).not.toBeCalled(); expect(nativeFabricUIManager.completeRoot).toBeCalled(); @@ -71,11 +76,15 @@ describe('ReactFabric', () => { nativeFabricUIManager.createNode.mockReturnValue(firstNode); - ReactFabric.render(, 11); + act(() => { + ReactFabric.render(, 11); + }); expect(nativeFabricUIManager.createNode).toHaveBeenCalledTimes(1); - ReactFabric.render(, 11); + act(() => { + ReactFabric.render(, 11); + }); expect(nativeFabricUIManager.createNode).toHaveBeenCalledTimes(1); expect(nativeFabricUIManager.cloneNodeWithNewProps).toHaveBeenCalledTimes( @@ -97,7 +106,9 @@ describe('ReactFabric', () => { uiViewClassName: 'RCTText', })); - ReactFabric.render(1, 11); + act(() => { + ReactFabric.render(1, 11); + }); expect(nativeFabricUIManager.cloneNode).not.toBeCalled(); expect(nativeFabricUIManager.cloneNodeWithNewChildren).not.toBeCalled(); expect(nativeFabricUIManager.cloneNodeWithNewProps).not.toBeCalled(); @@ -106,7 +117,9 @@ describe('ReactFabric', () => { ).not.toBeCalled(); // If no properties have changed, we shouldn't call cloneNode. - ReactFabric.render(1, 11); + act(() => { + ReactFabric.render(1, 11); + }); expect(nativeFabricUIManager.cloneNode).not.toBeCalled(); expect(nativeFabricUIManager.cloneNodeWithNewChildren).not.toBeCalled(); expect(nativeFabricUIManager.cloneNodeWithNewProps).not.toBeCalled(); @@ -115,7 +128,9 @@ describe('ReactFabric', () => { ).not.toBeCalled(); // Only call cloneNode for the changed property (and not for text). - ReactFabric.render(1, 11); + act(() => { + ReactFabric.render(1, 11); + }); expect(nativeFabricUIManager.cloneNode).not.toBeCalled(); expect(nativeFabricUIManager.cloneNodeWithNewChildren).not.toBeCalled(); expect(nativeFabricUIManager.cloneNodeWithNewProps).toHaveBeenCalledTimes( @@ -126,7 +141,9 @@ describe('ReactFabric', () => { ).not.toBeCalled(); // Only call cloneNode for the changed text (and no other properties). - ReactFabric.render(2, 11); + act(() => { + ReactFabric.render(2, 11); + }); expect(nativeFabricUIManager.cloneNode).not.toBeCalled(); expect( nativeFabricUIManager.cloneNodeWithNewChildren, @@ -139,7 +156,9 @@ describe('ReactFabric', () => { ).not.toBeCalled(); // Call cloneNode for both changed text and properties. - ReactFabric.render(3, 11); + act(() => { + ReactFabric.render(3, 11); + }); expect(nativeFabricUIManager.cloneNode).not.toBeCalled(); expect( nativeFabricUIManager.cloneNodeWithNewChildren, @@ -158,12 +177,14 @@ describe('ReactFabric', () => { uiViewClassName: 'RCTText', })); - ReactFabric.render( - - 1 - , - 11, - ); + act(() => { + ReactFabric.render( + + 1 + , + 11, + ); + }); expect(nativeFabricUIManager.cloneNode).not.toBeCalled(); expect(nativeFabricUIManager.cloneNodeWithNewChildren).not.toBeCalled(); expect(nativeFabricUIManager.cloneNodeWithNewProps).not.toBeCalled(); @@ -171,12 +192,14 @@ describe('ReactFabric', () => { nativeFabricUIManager.cloneNodeWithNewChildrenAndProps, ).not.toBeCalled(); - ReactFabric.render( - - 1 - , - 11, - ); + act(() => { + ReactFabric.render( + + 1 + , + 11, + ); + }); expect( nativeFabricUIManager.cloneNodeWithNewProps.mock.calls[0][1], ).toEqual({ @@ -186,12 +209,14 @@ describe('ReactFabric', () => { nativeFabricUIManager.__dumpHierarchyForJestTestsOnly(), ).toMatchSnapshot(); - ReactFabric.render( - - 2 - , - 11, - ); + act(() => { + ReactFabric.render( + + 2 + , + 11, + ); + }); expect( nativeFabricUIManager.cloneNodeWithNewChildrenAndProps.mock.calls[0][1], ).toEqual({ @@ -211,15 +236,17 @@ describe('ReactFabric', () => { UIManager.updateView.mockReset(); let viewRef; - ReactFabric.render( - { - viewRef = ref; - }} - />, - 11, - ); + act(() => { + ReactFabric.render( + { + viewRef = ref; + }} + />, + 11, + ); + }); expect(UIManager.updateView).not.toBeCalled(); expect(() => { @@ -247,14 +274,16 @@ describe('ReactFabric', () => { nativeFabricUIManager.dispatchCommand.mockClear(); let viewRef; - ReactFabric.render( - { - viewRef = ref; - }} - />, - 11, - ); + act(() => { + ReactFabric.render( + { + viewRef = ref; + }} + />, + 11, + ); + }); expect(nativeFabricUIManager.dispatchCommand).not.toBeCalled(); ReactFabric.dispatchCommand(viewRef, 'updateCommand', [10, 20]); @@ -274,14 +303,16 @@ describe('ReactFabric', () => { nativeFabricUIManager.dispatchCommand.mockReset(); let viewRef; - ReactFabric.render( - { - viewRef = ref; - }} - />, - 11, - ); + act(() => { + ReactFabric.render( + { + viewRef = ref; + }} + />, + 11, + ); + }); expect(nativeFabricUIManager.dispatchCommand).not.toBeCalled(); expect(() => { @@ -302,14 +333,16 @@ describe('ReactFabric', () => { nativeFabricUIManager.sendAccessibilityEvent.mockClear(); let viewRef; - ReactFabric.render( - { - viewRef = ref; - }} - />, - 11, - ); + act(() => { + ReactFabric.render( + { + viewRef = ref; + }} + />, + 11, + ); + }); expect(nativeFabricUIManager.sendAccessibilityEvent).not.toBeCalled(); ReactFabric.sendAccessibilityEvent(viewRef, 'focus'); @@ -332,14 +365,16 @@ describe('ReactFabric', () => { nativeFabricUIManager.sendAccessibilityEvent.mockReset(); let viewRef; - ReactFabric.render( - { - viewRef = ref; - }} - />, - 11, - ); + act(() => { + ReactFabric.render( + { + viewRef = ref; + }} + />, + 11, + ); + }); expect(nativeFabricUIManager.sendAccessibilityEvent).not.toBeCalled(); expect(() => { @@ -360,14 +395,16 @@ describe('ReactFabric', () => { nativeFabricUIManager.measure.mockClear(); let viewRef; - ReactFabric.render( - { - viewRef = ref; - }} - />, - 11, - ); + act(() => { + ReactFabric.render( + { + viewRef = ref; + }} + />, + 11, + ); + }); expect(nativeFabricUIManager.measure).not.toBeCalled(); const successCallback = jest.fn(); @@ -386,14 +423,16 @@ describe('ReactFabric', () => { nativeFabricUIManager.measureInWindow.mockClear(); let viewRef; - ReactFabric.render( - { - viewRef = ref; - }} - />, - 11, - ); + act(() => { + ReactFabric.render( + { + viewRef = ref; + }} + />, + 11, + ); + }); expect(nativeFabricUIManager.measureInWindow).not.toBeCalled(); const successCallback = jest.fn(); @@ -413,22 +452,24 @@ describe('ReactFabric', () => { let viewRef; let otherRef; - ReactFabric.render( - - { - viewRef = ref; - }} - /> - { - otherRef = ref; - }} - /> - , - 11, - ); + act(() => { + ReactFabric.render( + + { + viewRef = ref; + }} + /> + { + otherRef = ref; + }} + /> + , + 11, + ); + }); expect(nativeFabricUIManager.measureLayout).not.toBeCalled(); const successCallback = jest.fn(); @@ -483,12 +524,16 @@ describe('ReactFabric', () => { const before = 'abcdefghijklmnopqrst'; const after = 'mxhpgwfralkeoivcstzy'; - ReactFabric.render(, 11); + act(() => { + ReactFabric.render(, 11); + }); expect( nativeFabricUIManager.__dumpHierarchyForJestTestsOnly(), ).toMatchSnapshot(); - ReactFabric.render(, 11); + act(() => { + ReactFabric.render(, 11); + }); expect( nativeFabricUIManager.__dumpHierarchyForJestTestsOnly(), ).toMatchSnapshot(); @@ -521,12 +566,14 @@ describe('ReactFabric', () => { const ref = React.createRef(); // Wrap in a host node. - ReactFabric.render( - - - , - 11, - ); + act(() => { + ReactFabric.render( + + + , + 11, + ); + }); expect( nativeFabricUIManager.__dumpHierarchyForJestTestsOnly(), ).toMatchSnapshot(); @@ -552,7 +599,9 @@ describe('ReactFabric', () => { } } - ReactFabric.render(, 11); + act(() => { + ReactFabric.render(, 11); + }); expect(mockArgs.length).toEqual(0); }); @@ -572,12 +621,14 @@ describe('ReactFabric', () => { ); }); - ReactFabric.render( - - - , - 22, - ); + act(() => { + ReactFabric.render( + + + , + 22, + ); + }); expect(snapshots).toMatchSnapshot(); }); @@ -595,19 +646,23 @@ describe('ReactFabric', () => { uiViewClassName: 'RCTView', })); - ReactFabric.render( - - - , - 11, - ); + act(() => { + ReactFabric.render( + + + , + 11, + ); + }); - ReactFabric.render( - - - , - 11, - ); + act(() => { + ReactFabric.render( + + + , + 11, + ); + }); }); it('should throw for text not inside of a ancestor', () => { @@ -624,18 +679,22 @@ describe('ReactFabric', () => { uiViewClassName: 'RCTView', })); - expect(() => ReactFabric.render(this should warn, 11)).toThrow( - 'Text strings must be rendered within a component.', - ); + expect(() => { + act(() => { + ReactFabric.render(this should warn, 11); + }); + }).toThrow('Text strings must be rendered within a component.'); - expect(() => - ReactFabric.render( - - hi hello hi - , - 11, - ), - ).toThrow('Text strings must be rendered within a component.'); + expect(() => { + act(() => { + ReactFabric.render( + + hi hello hi + , + 11, + ); + }); + }).toThrow('Text strings must be rendered within a component.'); }); it('should not throw for text inside of an indirect ancestor', () => { @@ -646,12 +705,14 @@ describe('ReactFabric', () => { const Indirection = () => 'Hi'; - ReactFabric.render( - - - , - 11, - ); + act(() => { + ReactFabric.render( + + + , + 11, + ); + }); }); it('dispatches events to the last committed props', () => { @@ -668,7 +729,9 @@ describe('ReactFabric', () => { const touchStart = jest.fn(); const touchStart2 = jest.fn(); - ReactFabric.render(, 11); + act(() => { + ReactFabric.render(, 11); + }); expect(nativeFabricUIManager.createNode.mock.calls.length).toBe(1); expect(nativeFabricUIManager.registerEventHandler.mock.calls.length).toBe( @@ -698,7 +761,9 @@ describe('ReactFabric', () => { expect(touchStart).toBeCalled(); expect(touchStart2).not.toBeCalled(); - ReactFabric.render(, 11); + act(() => { + ReactFabric.render(, 11); + }); // Intentionally dispatch to the same instanceHandle again. dispatchEvent(instanceHandle, 'topTouchStart', touchEvent); @@ -742,33 +807,35 @@ describe('ReactFabric', () => { const ref1 = React.createRef(); const ref2 = React.createRef(); - ReactFabric.render( - - { - expect(ref1.current).not.toBeNull(); - // Check for referential equality - expect(ref1.current).toBe(event.target); - expect(ref1.current).toBe(event.currentTarget); - }} - onStartShouldSetResponder={() => true} - /> - { - expect(ref2.current).not.toBeNull(); - // Check for referential equality - expect(ref2.current).toBe(event.target); - expect(ref2.current).toBe(event.currentTarget); - }} - onStartShouldSetResponder={() => true} - /> - , - 1, - ); + act(() => { + ReactFabric.render( + + { + expect(ref1.current).not.toBeNull(); + // Check for referential equality + expect(ref1.current).toBe(event.target); + expect(ref1.current).toBe(event.currentTarget); + }} + onStartShouldSetResponder={() => true} + /> + { + expect(ref2.current).not.toBeNull(); + // Check for referential equality + expect(ref2.current).toBe(event.target); + expect(ref2.current).toBe(event.currentTarget); + }} + onStartShouldSetResponder={() => true} + /> + , + 1, + ); + }); const [ dispatchEvent, @@ -823,7 +890,12 @@ describe('ReactFabric', () => { } } - ReactFabric.render( (parent = n)} />, 11); + act(() => { + ReactFabric.render( + (parent = n)} />, + 11, + ); + }); let match; expect( @@ -855,12 +927,14 @@ describe('ReactFabric', () => { } } - ReactFabric.render( - - (parent = n)} /> - , - 11, - ); + act(() => { + ReactFabric.render( + + (parent = n)} /> + , + 11, + ); + }); let match; expect( @@ -896,7 +970,12 @@ describe('ReactFabric', () => { } } - ReactFabric.render( (parent = n)} />, 11); + act(() => { + ReactFabric.render( + (parent = n)} />, + 11, + ); + }); let match; expect(() => (match = ReactFabric.findNodeHandle(parent))).toErrorDev([ @@ -926,12 +1005,14 @@ describe('ReactFabric', () => { } } - ReactFabric.render( - - (parent = n)} /> - , - 11, - ); + act(() => { + ReactFabric.render( + + (parent = n)} /> + , + 11, + ); + }); let match; expect(() => (match = ReactFabric.findNodeHandle(parent))).toErrorDev([ @@ -953,7 +1034,9 @@ describe('ReactFabric', () => { })); const viewRef = React.createRef(); - ReactFabric.render(, 11); + act(() => { + ReactFabric.render(, 11); + }); expect(TextInputState.blurTextInput).not.toBeCalled(); @@ -970,7 +1053,9 @@ describe('ReactFabric', () => { })); const viewRef = React.createRef(); - ReactFabric.render(, 11); + act(() => { + ReactFabric.render(, 11); + }); expect(TextInputState.focusTextInput).not.toBeCalled();