question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Bug: `react-test-renderer`'s `createNodeMock` doesn't get called in React Native

See original GitHub issue

React 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

  1. 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)
  2. Try to use createNodeMock to mock a ref while testing with react-test-renderer
  3. Add some console.logs to see that createNodeMock is never called and the ref isn’t being mocked by createNodeMock.

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 refs 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:open
  • Created a year ago
  • Comments:7

github_iconTop GitHub Comments

1reaction
eps1loncommented, Jul 5, 2022

Quick note on that, you probably shouldn’t return inside act, as you can

Sure. It’s not really relevant here. Just shorter to type.

No, it doesn’t work.

Hm, that’s odd. Checking the repro…

0reactions
EduVencovskycommented, Jul 5, 2022

@eps1lon

What do you mean by that? How exactly would that work?

act(() => renderer.create(<App />, { createNodeMock: ... })
// is `createNodeMock` called at this point?

No, it doesn’t work.

Quick note on that, you probably shouldn’t return inside act, as you can see in the typescript definition

// VoidOrUndefinedOnly is here to forbid any sneaky return values
export function act(callback: () => Promise<VoidOrUndefinedOnly>): Promise<undefined>;
Read more comments on GitHub >

github_iconTop Results From Across the Web

Test Renderer - React
This package provides a React renderer that can be used to render React components to pure JavaScript objects, without depending on the DOM...
Read more >
API | React Native Testing Library - Open Source
This page gathers public API of React Native Testing Library along with usage ... you to pass createNodeMock option to ReactTestRenderer.create() method in ......
Read more >
Jest - Testing modals in React gives error - Stack Overflow
I am using react-test-renderer with Jest to test react components. But if I test a react-mui modal dialog like this:
Read more >
react-test-renderer | Yarn - Package Manager
React package for snapshot testing. react, react-native, react-testing. readme. React · GitHub license npm version ...
Read more >
react-test-renderer - npm
react -test-renderer. This package provides an experimental React renderer that can be used to render React components to pure JavaScript ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found