Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit a4c2007

Browse files
yungstersfacebook-github-bot
authored andcommittedMay 28, 2025·
RN: Flowify packages/react-native/jest (#51652)
Summary: Adds `flow` (or `noflow`) to all files in this directory and ensures that Flow succeeds (by adding type annotations, using minor refactors, or suppressing errors due to intentionally dynamic logic). This will help improve type safety when making changes both in these files as well as files that these depend on. Changelog: [Internal] Pull Request resolved: #51652 Test Plan: Ran Flow and Jest tests successfully: ``` $ yarn flow $ yarn test ``` Ran a Jest unit test internally to make sure they work with our internal environment setup: ``` $ cd ~/fbsource $ js1 test /View-test.js ``` Reviewed By: javache Differential Revision: D75488160 Pulled By: yungsters fbshipit-source-id: 536cef9699acfa1edcd3dcf61c53ebcd92f560f9
1 parent 14a1152 commit a4c2007

File tree

13 files changed

+578
-438
lines changed

13 files changed

+578
-438
lines changed
 

‎flow-typed/npm/jest.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -853,6 +853,10 @@ type JestObjectType = {
853853
* Returns the number of fake timers still left to run.
854854
*/
855855
getTimerCount(): number,
856+
/**
857+
* Returns the time in ms of the current clock.
858+
*/
859+
now(): number,
856860
/**
857861
* Set the current system time used by fake timers.
858862
* Simulates a user changing the system clock while your program is running.

‎packages/react-native/jest/MockNativeMethods.js

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,24 @@
44
* This source code is licensed under the MIT license found in the
55
* LICENSE file in the root directory of this source tree.
66
*
7+
* @flow strict
78
* @format
89
*/
910

10-
'use strict';
11-
1211
const MockNativeMethods = {
1312
measure: jest.fn(),
1413
measureInWindow: jest.fn(),
1514
measureLayout: jest.fn(),
1615
setNativeProps: jest.fn(),
1716
focus: jest.fn(),
1817
blur: jest.fn(),
18+
} as {
19+
measure: () => void,
20+
measureInWindow: () => void,
21+
measureLayout: () => void,
22+
setNativeProps: () => void,
23+
focus: () => void,
24+
blur: () => void,
1925
};
2026

21-
module.exports = MockNativeMethods;
27+
export default MockNativeMethods;

‎packages/react-native/jest/RefreshControlMock.js

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,12 @@ const RCTRefreshControl: HostComponent<{}> = requireNativeComponent<{}>(
2121

2222
export default class RefreshControlMock extends React.Component<{...}> {
2323
static latestRef: ?RefreshControlMock;
24+
25+
render(): React.Node {
26+
return <RCTRefreshControl />;
27+
}
28+
2429
componentDidMount() {
2530
RefreshControlMock.latestRef = this;
2631
}
27-
render(): React.MixedElement {
28-
return <RCTRefreshControl />;
29-
}
3032
}

‎packages/react-native/jest/assetFileTransformer.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
* This source code is licensed under the MIT license found in the
55
* LICENSE file in the root directory of this source tree.
66
*
7+
* @noflow
78
* @format
89
*/
910

‎packages/react-native/jest/local-setup.js

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,24 +4,25 @@
44
* This source code is licensed under the MIT license found in the
55
* LICENSE file in the root directory of this source tree.
66
*
7+
* @flow strict-local
78
* @format
89
*/
910

1011
// Global setup for tests local to the react-native repo. This setup is not
1112
// included in the react-native Jest preset.
1213

13-
'use strict';
14-
15-
require('./setup');
14+
import './setup';
1615

1716
const consoleError = console.error;
1817
const consoleWarn = console.warn;
1918

19+
// $FlowIgnore[cannot-write]
2020
console.error = (...args) => {
2121
consoleError(...args);
2222
throw new Error('console.error() was called (see error above)');
2323
};
2424

25+
// $FlowIgnore[cannot-write]
2526
console.warn = (...args) => {
2627
consoleWarn(...args);
2728
throw new Error('console.warn() was called (see warning above)');

‎packages/react-native/jest/mockComponent.js

Lines changed: 42 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -4,37 +4,58 @@
44
* This source code is licensed under the MIT license found in the
55
* LICENSE file in the root directory of this source tree.
66
*
7+
* @flow strict
78
* @format
89
*/
910

10-
'use strict';
11+
import * as React from 'react';
12+
import {createElement} from 'react';
1113

12-
module.exports = (moduleName, instanceMethods, isESModule) => {
13-
const RealComponent = isESModule
14-
? jest.requireActual(moduleName).default
15-
: jest.requireActual(moduleName);
16-
const React = require('react');
14+
type Modulish<T> = T | $ReadOnly<{default: T}>;
15+
type ModuleDefault<T> = T['default'];
1716

18-
const SuperClass =
17+
type TComponentType = React.ComponentType<$ReadOnly<{children?: React.Node}>>;
18+
19+
export default function mockComponent<
20+
TComponentModule: Modulish<TComponentType>,
21+
>(
22+
moduleName: string,
23+
instanceMethods: ?interface {},
24+
isESModule: boolean,
25+
): typeof isESModule extends true
26+
? ModuleDefault<TComponentModule>
27+
: TComponentModule & typeof instanceMethods {
28+
const RealComponent: TComponentType = isESModule
29+
? // $FlowIgnore[prop-missing]
30+
jest.requireActual<TComponentModule>(moduleName).default
31+
: // $FlowIgnore[incompatible-type]
32+
jest.requireActual<TComponentModule>(moduleName);
33+
34+
const SuperClass: typeof React.Component<
35+
React.ElementProps<typeof RealComponent>,
36+
> =
1937
typeof RealComponent === 'function' &&
2038
RealComponent.prototype.constructor instanceof React.Component
2139
? RealComponent
2240
: React.Component;
2341

2442
const name =
25-
RealComponent.displayName ||
26-
RealComponent.name ||
27-
(RealComponent.render // handle React.forwardRef
28-
? RealComponent.render.displayName || RealComponent.render.name
29-
: 'Unknown');
43+
RealComponent.displayName ??
44+
RealComponent.name ??
45+
// $FlowFixMe[prop-missing] - Checking for `forwardRef` values.
46+
(RealComponent.render == null
47+
? 'Unknown'
48+
: // $FlowFixMe[incompatible-use]
49+
RealComponent.render.displayName ?? RealComponent.render.name);
3050

3151
const nameWithoutPrefix = name.replace(/^(RCT|RK)/, '');
3252

3353
const Component = class extends SuperClass {
34-
static displayName = 'Component';
54+
static displayName: ?string = 'Component';
3555

36-
render() {
37-
const props = Object.assign({}, RealComponent.defaultProps);
56+
render(): React.Node {
57+
// $FlowIgnore[prop-missing]
58+
const props = {...RealComponent.defaultProps};
3859

3960
if (this.props) {
4061
Object.keys(this.props).forEach(prop => {
@@ -49,7 +70,8 @@ module.exports = (moduleName, instanceMethods, isESModule) => {
4970
});
5071
}
5172

52-
return React.createElement(nameWithoutPrefix, props, this.props.children);
73+
// $FlowIgnore[not-a-function]
74+
return createElement(nameWithoutPrefix, props, this.props.children);
5375
}
5476
};
5577

@@ -62,13 +84,16 @@ module.exports = (moduleName, instanceMethods, isESModule) => {
6284

6385
Component.displayName = nameWithoutPrefix;
6486

87+
// $FlowIgnore[not-an-object]
6588
Object.keys(RealComponent).forEach(classStatic => {
6689
Component[classStatic] = RealComponent[classStatic];
6790
});
6891

6992
if (instanceMethods != null) {
93+
// $FlowIgnore[unsafe-object-assign]
7094
Object.assign(Component.prototype, instanceMethods);
7195
}
7296

97+
// $FlowIgnore[incompatible-return]
7398
return Component;
74-
};
99+
}

‎packages/react-native/jest/mockModal.js

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,21 @@
44
* This source code is licensed under the MIT license found in the
55
* LICENSE file in the root directory of this source tree.
66
*
7-
* @flow strict-local
7+
* @flow strict
88
* @format
99
*/
1010

11-
/* eslint-env jest */
11+
import * as React from 'react';
1212

13-
'use strict';
14-
15-
const React = require('react');
16-
17-
function mockModal(BaseComponent: $FlowFixMe) {
18-
class ModalMock extends BaseComponent {
19-
render(): React.MixedElement | null {
13+
export default function mockModal(
14+
BaseComponent: React.ComponentType<{children?: React.Node}>,
15+
): React.ComponentType<{
16+
...React.ElementConfig<typeof BaseComponent>,
17+
visible?: ?boolean,
18+
}> {
19+
// $FlowIgnore[incompatible-use]
20+
return class ModalMock extends BaseComponent {
21+
render(): React.Node {
2022
if (this.props.visible === false) {
2123
return null;
2224
}
@@ -25,8 +27,5 @@ function mockModal(BaseComponent: $FlowFixMe) {
2527
<BaseComponent {...this.props}>{this.props.children}</BaseComponent>
2628
);
2729
}
28-
}
29-
return ModalMock;
30+
};
3031
}
31-
32-
module.exports = (mockModal: $FlowFixMe);

‎packages/react-native/jest/mockNativeComponent.js

Lines changed: 21 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,31 +4,38 @@
44
* This source code is licensed under the MIT license found in the
55
* LICENSE file in the root directory of this source tree.
66
*
7+
* @flow strict
78
* @format
89
*/
910

10-
'use strict';
11+
import type {HostInstance} from '../src/private/types/HostInstance';
1112

12-
const React = require('react');
13-
const {createElement} = require('react');
13+
import * as React from 'react';
14+
import {createElement} from 'react';
1415

1516
let nativeTag = 1;
1617

17-
export default viewName => {
18-
const Component = class extends React.Component {
19-
_nativeTag = nativeTag++;
18+
type MockNativeComponent<TProps: $ReadOnly<{children?: React.Node}>> =
19+
component(ref?: ?React.RefSetter<HostInstance>, ...props: TProps);
2020

21-
render() {
21+
export default function mockNativeComponent<
22+
TProps: $ReadOnly<{children?: React.Node}>,
23+
>(viewName: string): MockNativeComponent<TProps> {
24+
const Component = class extends React.Component<TProps> {
25+
_nativeTag: number = nativeTag++;
26+
27+
render(): React.Node {
28+
// $FlowIgnore[not-a-function]
2229
return createElement(viewName, this.props, this.props.children);
2330
}
2431

2532
// The methods that exist on host components
26-
blur = jest.fn();
27-
focus = jest.fn();
28-
measure = jest.fn();
29-
measureInWindow = jest.fn();
30-
measureLayout = jest.fn();
31-
setNativeProps = jest.fn();
33+
blur: () => void = jest.fn();
34+
focus: () => void = jest.fn();
35+
measure: () => void = jest.fn();
36+
measureInWindow: () => void = jest.fn();
37+
measureLayout: () => void = jest.fn();
38+
setNativeProps: () => void = jest.fn();
3239
};
3340

3441
if (viewName === 'RCTView') {
@@ -38,4 +45,4 @@ export default viewName => {
3845
}
3946

4047
return Component;
41-
};
48+
}

‎packages/react-native/jest/mockScrollView.js

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -8,28 +8,30 @@
88
* @format
99
*/
1010

11-
/* eslint-env jest */
11+
import type {ScrollViewNativeProps} from '../Libraries/Components/ScrollView/ScrollViewNativeComponentType';
1212

13-
'use strict';
13+
import View from '../Libraries/Components/View/View';
14+
import requireNativeComponent from '../Libraries/ReactNative/requireNativeComponent';
15+
import * as React from 'react';
1416

15-
const View = require('../Libraries/Components/View/View').default;
16-
const requireNativeComponent =
17-
require('../Libraries/ReactNative/requireNativeComponent').default;
18-
const React = require('react');
19-
const RCTScrollView: $FlowFixMe = requireNativeComponent('RCTScrollView');
17+
const RCTScrollView =
18+
requireNativeComponent<ScrollViewNativeProps>('RCTScrollView');
2019

21-
function mockScrollView(BaseComponent: $FlowFixMe) {
22-
class ScrollViewMock extends BaseComponent {
23-
render(): React.MixedElement {
20+
export default function mockScrollView(
21+
BaseComponent: React.ComponentType<{children?: React.Node}>,
22+
): React.ComponentType<{
23+
...React.ElementConfig<typeof BaseComponent>,
24+
refreshControl?: ?React.MixedElement,
25+
}> {
26+
// $FlowIgnore[incompatible-use]
27+
return class ScrollViewMock extends BaseComponent {
28+
render(): React.Node {
2429
return (
2530
<RCTScrollView {...this.props}>
2631
{this.props.refreshControl}
2732
<View>{this.props.children}</View>
2833
</RCTScrollView>
2934
);
3035
}
31-
}
32-
return ScrollViewMock;
36+
};
3337
}
34-
35-
module.exports = (mockScrollView: $FlowFixMe);

‎packages/react-native/jest/react-native-env.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
* This source code is licensed under the MIT license found in the
55
* LICENSE file in the root directory of this source tree.
66
*
7+
* @noflow
78
* @format
89
*/
910

‎packages/react-native/jest/renderer.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
* This source code is licensed under the MIT license found in the
55
* LICENSE file in the root directory of this source tree.
66
*
7-
* @flow
7+
* @flow strict
88
* @format
99
*/
1010

‎packages/react-native/jest/resolver.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
* This source code is licensed under the MIT license found in the
55
* LICENSE file in the root directory of this source tree.
66
*
7+
* @noflow
78
* @format
89
*/
910

There was a problem loading the remainder of the diff.

0 commit comments

Comments
 (0)
Please sign in to comment.