Skip to content

Commit

Permalink
Introduce update and unmount helpers to `react-native/jest/render…
Browse files Browse the repository at this point in the history
…er`, use in ScrollView-test

Summary:
Add async helpers to the existing `jest/renderer` module to wrap `react-test-renderer`'s `update` and `unmount` in `act`.

Migrate one test `ScrollView-test` as a usage example and to make it compatible with incoming React 19 concurrency requirements.

Changelog: [Internal]

Differential Revision: D58650989
  • Loading branch information
robhogan authored and facebook-github-bot committed Jun 16, 2024
1 parent c56c9b0 commit c39405f
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 17 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,12 @@

'use strict';

const {create, unmount, update} = require('../../../../jest/renderer');
const Text = require('../../../Text/Text');
const ReactNativeTestTools = require('../../../Utilities/ReactNativeTestTools');
const View = require('../../View/View');
const ScrollView = require('../ScrollView');
const React = require('react');
const ReactTestRenderer = require('react-test-renderer');

describe('ScrollView', () => {
beforeEach(() => {
Expand All @@ -39,39 +39,39 @@ describe('ScrollView', () => {
);
});

it('mocks native methods and instance methods', () => {
it('mocks native methods and instance methods', async () => {
jest.mock('../ScrollView');

const ref = React.createRef();
ReactTestRenderer.create(<ScrollView ref={ref} />);
await create(<ScrollView ref={ref} />);

expect(ref.current?.measure).toBeInstanceOf(jest.fn().constructor);
expect(ref.current?.scrollTo).toBeInstanceOf(jest.fn().constructor);
});

describe('ref', () => {
it('receives an instance or null', () => {
it('receives an instance or null', async () => {
jest.dontMock('../ScrollView');

const scrollViewRef = jest.fn();
const testRendererInstance = ReactTestRenderer.create(
const testRendererInstance = await create(
<ScrollView ref={scrollViewRef} />,
);

expect(scrollViewRef).toHaveBeenLastCalledWith(
expect.objectContaining({_nativeTag: expect.any(Number)}),
);

testRendererInstance.unmount();
await unmount(testRendererInstance);

expect(scrollViewRef).toHaveBeenLastCalledWith(null);
});

it('transitions between refs', () => {
it('transitions between refs', async () => {
jest.dontMock('../ScrollView');

const scrollViewRefA = jest.fn();
const testRendererInstance = ReactTestRenderer.create(
const testRendererInstance = await create(
<ScrollView ref={scrollViewRefA} />,
);

Expand All @@ -80,7 +80,7 @@ describe('ScrollView', () => {
);

const scrollViewRefB = jest.fn();
testRendererInstance.update(<ScrollView ref={scrollViewRefB} />);
await update(testRendererInstance, <ScrollView ref={scrollViewRefB} />);

expect(scrollViewRefA).toHaveBeenLastCalledWith(null);
expect(scrollViewRefB).toHaveBeenLastCalledWith(
Expand All @@ -90,28 +90,28 @@ describe('ScrollView', () => {
});

describe('innerViewRef', () => {
it('receives an instance or null', () => {
it('receives an instance or null', async () => {
jest.dontMock('../ScrollView');

const innerViewRef = jest.fn();
const testRendererInstance = ReactTestRenderer.create(
const testRendererInstance = await create(
<ScrollView innerViewRef={innerViewRef} />,
);

expect(innerViewRef).toHaveBeenLastCalledWith(
expect.objectContaining({_nativeTag: expect.any(Number)}),
);

testRendererInstance.unmount();
await unmount(testRendererInstance);

expect(innerViewRef).toHaveBeenLastCalledWith(null);
});

it('transitions between refs', () => {
it('transitions between refs', async () => {
jest.dontMock('../ScrollView');

const innerViewRefA = jest.fn();
const testRendererInstance = ReactTestRenderer.create(
const testRendererInstance = await create(
<ScrollView innerViewRef={innerViewRefA} />,
);

Expand All @@ -120,7 +120,11 @@ describe('ScrollView', () => {
);

const innerViewRefB = jest.fn();
testRendererInstance.update(<ScrollView innerViewRef={innerViewRefB} />);

await update(
testRendererInstance,
<ScrollView innerViewRef={innerViewRefB} />,
);

expect(innerViewRefA).toHaveBeenLastCalledWith(null);
expect(innerViewRefB).toHaveBeenLastCalledWith(
Expand All @@ -130,11 +134,11 @@ describe('ScrollView', () => {
});

describe('getInnerViewRef', () => {
it('returns an instance', () => {
it('returns an instance', async () => {
jest.dontMock('../ScrollView');

const scrollViewRef = React.createRef(null);
ReactTestRenderer.create(<ScrollView ref={scrollViewRef} />);
await create(<ScrollView ref={scrollViewRef} />);
const innerViewRef = scrollViewRef.current.getInnerViewRef();

// This is checking if the ref acts like a host component. If we had an
Expand Down
15 changes: 15 additions & 0 deletions packages/react-native/jest/renderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,18 @@ export async function create(
});
return nullthrows(component);
}

export async function unmount(testRenderer: ReactTestRenderer) {
await TestRenderer.act(async () => {
testRenderer.unmount();
});
}

export async function update(
testRenderer: ReactTestRenderer,
element: React.Element<any>,
) {
await TestRenderer.act(async () => {
testRenderer.update(element);
});
}

0 comments on commit c39405f

Please sign in to comment.