Bug: `react-test-renderer`'s `createNodeMock` doesn't get called in React Native
See original GitHub issueReact version (latest from the react native template):
“react”: “18.0.0” “react-native”: “0.69.0” “react-test-renderer”: “18.0.0”
Steps To Reproduce
- Create a react native project from the template provided in the docs (I used the typescript template, but I don’t think this will make a difference)
- Try to use
createNodeMock
to mock a ref while testing withreact-test-renderer
- Add some
console.log
s to see thatcreateNodeMock
is never called and the ref isn’t being mocked bycreateNodeMock
.
Example code:
App.tsx
interface Measure {
x: number;
y: number;
width: number;
height: number;
pageX: number;
pageY: number;
}
const App = () => {
const [measure, setMeasure] = useState<Measure>();
const viewRef = useRef<View | null>(null);
const onLayout = () => {
// gets called
console.log('onLayout');
console.log('measure is truthy', !!viewRef.current?.measure); // => true
viewRef.current?.measure((x, y, width, height, pageX, pageY) => {
// never gets called
console.log('measure');
setMeasure({x, y, width, height, pageX, pageY});
});
};
return (
<SafeAreaView>
<View onLayout={onLayout} ref={viewRef}>
<Text>Test Text</Text>
<Text>
{measure
? Object.values(measure).reduce((prev, next) => prev + next)
: ''}
</Text>
</View>
</SafeAreaView>
);
};
App-test.tsx
it('renders correctly', () => {
const [x, y, width, height, pageX, pageY] = [1, 2, 3, 4, 5, 6];
const expectedText = x + y + width + height + pageX + pageY + '';
const {root} = renderer.create(<App />, {
createNodeMock: () => {
// never gets called
console.log('createNodeMock');
return {
measure: (fn: Parameters<NativeMethods['measure']>[0]) => {
// never gets called
console.log('createNodeMock measure');
fn(x, y, width, height, pageX, pageY);
},
};
},
});
// make sure I'm querying text correctly
const testText = root
.findAllByType(Text)
.find(text => text.props.children === 'Test Text');
expect(testText).toBeTruthy();
// trigger onLayout
root.findByType(View).props.onLayout();
act(() => {
// [ 'Test Text', '' ]
console.log(root.findAllByType(Text).map(text => text.props.children));
const measureText = root
.findAllByType(Text)
.find(text => text.props.children === expectedText);
expect(measureText).toBeTruthy(); // => fails
});
});
Link to code example:
I create a repository to show this issue. Just run yarn
and yarn test
to see the test failing and createNodeMock
not being called.
https://github.com/EduVencovsky/CreateNodeMockTest
The current behavior
createNodeMock
is not being called when testing with react-native
. This issue is also related to react-native-testing-library
’s PR#227
The expected behavior
createNodeMock
should work as described in the docs with react-native
too and even if the component’s ref is already mocked, createNodeMock
should be called and replace that mock.
Observations
I realized that viewRef.current?.measure
exits and it’s an actual mocked function, so maybe this could be related somehow with the issue.
My first assumption is that maybe createNodeMock
is only called for components that the ref
s don’t have any value. But react-native
already mocks the View
’s ref and that’s why createNodeMock
doesn’t get called.
If my assumption is true, I personally believe that this shouldn’t happen, because this makes harder to mock the refs in your own way. So I would expect createNodeMock
to override already mocked refs. But if this behavior is expected, then it should be better detailed in the docs.
If my assumption is false, I don’t know what could be causing the issue.
And to clarify, I am aware that there are other ways to mock the refs (and I’m already using it), but as createNodeMock
makes it more convenient, I decided to open this issue.
Issue Analytics
- State:
- Created a year ago
- Comments:7
Sure. It’s not really relevant here. Just shorter to type.
Hm, that’s odd. Checking the repro…
@eps1lon
No, it doesn’t work.
Quick note on that, you probably shouldn’t return inside
act
, as you can see in the typescript definition