Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .flowconfig
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ module.name_mapper='^react-native/\(.*\)$' -> '<PROJECT_ROOT>/packages/react-nat
module.name_mapper='^@react-native/dev-middleware$' -> '<PROJECT_ROOT>/packages/dev-middleware'
module.name_mapper='^@?[./a-zA-Z0-9$_-]+\.\(bmp\|gif\|jpg\|jpeg\|png\|psd\|svg\|webp\|m4v\|mov\|mp4\|mpeg\|mpg\|webm\|aac\|aiff\|caf\|m4a\|mp3\|wav\|html\|pdf\|xml\)$' -> '<PROJECT_ROOT>/packages/react-native/Libraries/Image/RelativeImageStub'

module.system.haste.module_ref_prefix=m#

react.runtime=automatic

suppress_type=$FlowIssue
Expand Down
39 changes: 39 additions & 0 deletions packages/react-native/jest/mock.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict
* @format
* @oncall react_native
*/

/**
* Mocks the module referenced by `moduleRef` (expected to begin with `m#`)
* while enforcing type safety of mock factories.
*
* If `factoryRef` is provided, it is expected to reference a module that
* exports the same type signature as the module referenced by `moduleRef`.
*/
export default function mock<TModuleRef: $Flow$ModuleRef<mixed>>(
moduleRef: TModuleRef,
factoryRef?: NoInfer<TModuleRef>,
): void {
// NOTE: Jest's `babel-plugin-jest-hoist` requires that the second argument to
// `jest.mock` be an inline function, so structure this code accordingly.
if (factoryRef === undefined) {
jest.mock(deref(moduleRef));
} else {
// NOTE: Jest's `babel-plugin-jest-hoist` requires that module factories
// only reference local variables or variables starting with "mock", so be
// careful when renaming this `mockFactory` variable.
const mockFactory = deref(factoryRef);
jest.mock(deref(moduleRef), () => jest.requireActual(mockFactory));
}
}

function deref(ref: $Flow$ModuleRef<mixed>): string {
// $FlowIgnore[incompatible-cast]
return (ref as string).substring(2);
}
9 changes: 7 additions & 2 deletions packages/react-native/jest/mockComponent.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,20 @@ import {createElement} from 'react';
type Modulish<T> = T | $ReadOnly<{default: T}>;
type ModuleDefault<T> = T['default'];

type TComponentType = React.ComponentType<$ReadOnly<{children?: React.Node}>>;
type TComponentType = React.ComponentType<{...}>;

/**
* WARNING: The `moduleName` must be relative to this file's directory, which is
* a major footgun. Be careful when using this function!
*/
export default function mockComponent<
TComponentModule: Modulish<TComponentType>,
>(
moduleName: string,
instanceMethods: ?interface {},
isESModule: boolean,
): typeof isESModule extends true
? ModuleDefault<TComponentModule>
? ModuleDefault<TComponentModule & typeof instanceMethods>
: TComponentModule & typeof instanceMethods {
const RealComponent: TComponentType = isESModule
? // $FlowIgnore[prop-missing]
Expand Down Expand Up @@ -71,6 +75,7 @@ export default function mockComponent<
}

// $FlowIgnore[not-a-function]
// $FlowIgnore[prop-missing]
return createElement(nameWithoutPrefix, props, this.props.children);
}
};
Expand Down
31 changes: 0 additions & 31 deletions packages/react-native/jest/mockModal.js

This file was deleted.

15 changes: 9 additions & 6 deletions packages/react-native/jest/mockNativeComponent.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,20 @@ import {createElement} from 'react';

let nativeTag = 1;

type MockNativeComponent<TProps: $ReadOnly<{children?: React.Node}>> =
component(ref?: ?React.RefSetter<HostInstance>, ...props: TProps);

export default function mockNativeComponent<
TProps: $ReadOnly<{children?: React.Node}>,
>(viewName: string): MockNativeComponent<TProps> {
type MockNativeComponent<TProps: {...}> = component(
ref?: ?React.RefSetter<HostInstance>,
...props: TProps
);

export default function mockNativeComponent<TProps: {...}>(
viewName: string,
): MockNativeComponent<TProps> {
const Component = class extends React.Component<TProps> {
_nativeTag: number = nativeTag++;

render(): React.Node {
// $FlowIgnore[not-a-function]
// $FlowIgnore[prop-missing]
return createElement(viewName, this.props, this.props.children);
}

Expand Down
37 changes: 0 additions & 37 deletions packages/react-native/jest/mockScrollView.js

This file was deleted.

62 changes: 62 additions & 0 deletions packages/react-native/jest/mocks/AccessibilityInfo.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict
* @format
*/

const AccessibilityInfo = {
addEventListener: jest.fn(() => ({
remove: jest.fn(),
})) as JestMockFn<$FlowFixMe, {remove: JestMockFn<[], void>}>,
announceForAccessibility: jest.fn() as JestMockFn<$FlowFixMe, $FlowFixMe>,
announceForAccessibilityWithOptions: jest.fn() as JestMockFn<
$FlowFixMe,
$FlowFixMe,
>,
isAccessibilityServiceEnabled: jest.fn(() =>
Promise.resolve(false),
) as JestMockFn<$FlowFixMe, $FlowFixMe>,
isBoldTextEnabled: jest.fn(() => Promise.resolve(false)) as JestMockFn<
$FlowFixMe,
$FlowFixMe,
>,
isGrayscaleEnabled: jest.fn(() => Promise.resolve(false)) as JestMockFn<
$FlowFixMe,
$FlowFixMe,
>,
isInvertColorsEnabled: jest.fn(() => Promise.resolve(false)) as JestMockFn<
$FlowFixMe,
$FlowFixMe,
>,
isReduceMotionEnabled: jest.fn(() => Promise.resolve(false)) as JestMockFn<
$FlowFixMe,
$FlowFixMe,
>,
isHighTextContrastEnabled: jest.fn(() =>
Promise.resolve(false),
) as JestMockFn<$FlowFixMe, $FlowFixMe>,
isDarkerSystemColorsEnabled: jest.fn(() =>
Promise.resolve(false),
) as JestMockFn<$FlowFixMe, $FlowFixMe>,
prefersCrossFadeTransitions: jest.fn(() =>
Promise.resolve(false),
) as JestMockFn<$FlowFixMe, $FlowFixMe>,
isReduceTransparencyEnabled: jest.fn(() =>
Promise.resolve(false),
) as JestMockFn<$FlowFixMe, $FlowFixMe>,
isScreenReaderEnabled: jest.fn(() => Promise.resolve(false)) as JestMockFn<
$FlowFixMe,
$FlowFixMe,
>,
setAccessibilityFocus: jest.fn() as JestMockFn<$FlowFixMe, $FlowFixMe>,
sendAccessibilityEvent: jest.fn() as JestMockFn<$FlowFixMe, $FlowFixMe>,
getRecommendedTimeoutMillis: jest.fn(() =>
Promise.resolve(false),
) as JestMockFn<$FlowFixMe, $FlowFixMe>,
};

export default AccessibilityInfo;
23 changes: 23 additions & 0 deletions packages/react-native/jest/mocks/ActivityIndicator.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict-local
* @format
*/

import typeof TActivityIndicator from '../../Libraries/Components/ActivityIndicator/ActivityIndicator';
import typeof * as TmockComponent from '../mockComponent';

const mockComponent =
jest.requireActual<TmockComponent>('../mockComponent').default;

const ActivityIndicator = mockComponent(
'../Libraries/Components/ActivityIndicator/ActivityIndicator',
null, // instanceMethods
true, // isESModule
) as TActivityIndicator;

export default ActivityIndicator;
19 changes: 19 additions & 0 deletions packages/react-native/jest/mocks/AppState.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict
* @format
*/

const AppState = {
addEventListener: jest.fn(() => ({
remove: jest.fn(),
})) as JestMockFn<$FlowFixMe, $FlowFixMe>,
removeEventListener: jest.fn() as JestMockFn<$FlowFixMe, $FlowFixMe>,
currentState: jest.fn() as JestMockFn<$FlowFixMe, $FlowFixMe>,
};

export default AppState;
16 changes: 16 additions & 0 deletions packages/react-native/jest/mocks/Clipboard.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict
* @format
*/

const Clipboard = {
getString: jest.fn(async () => '') as JestMockFn<[], Promise<string>>,
setString: jest.fn() as JestMockFn<[string], void>,
};

export default Clipboard;
23 changes: 23 additions & 0 deletions packages/react-native/jest/mocks/Image.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict-local
* @format
*/

import typeof TImage from '../../Libraries/Image/Image';
import typeof * as TmockComponent from '../mockComponent';

const mockComponent =
jest.requireActual<TmockComponent>('../mockComponent').default;

const Image = mockComponent(
'../Libraries/Image/Image',
null, // instanceMethods
true, // isESModule
) as TImage;

export default Image;
9 changes: 9 additions & 0 deletions packages/react-native/jest/mocks/InitializeCore.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict
* @format
*/
28 changes: 28 additions & 0 deletions packages/react-native/jest/mocks/Linking.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict
* @format
*/

const Linking = {
openURL: jest.fn() as JestMockFn<$FlowFixMe, $FlowFixMe>,
canOpenURL: jest.fn(() => Promise.resolve(true)) as JestMockFn<
$FlowFixMe,
$FlowFixMe,
>,
openSettings: jest.fn() as JestMockFn<$FlowFixMe, $FlowFixMe>,
addEventListener: jest.fn(() => ({
remove: jest.fn(),
})) as JestMockFn<$FlowFixMe, $FlowFixMe>,
getInitialURL: jest.fn(() => Promise.resolve()) as JestMockFn<
$FlowFixMe,
$FlowFixMe,
>,
sendIntent: jest.fn() as JestMockFn<$FlowFixMe, $FlowFixMe>,
};

export default Linking;
33 changes: 33 additions & 0 deletions packages/react-native/jest/mocks/Modal.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict-local
* @format
*/

import type {ModalProps} from '../../Libraries/Modal/Modal';
import typeof * as TmockComponent from '../mockComponent';

const mockComponent =
jest.requireActual<TmockComponent>('../mockComponent').default;

type TModal = component(...ModalProps);

const BaseComponent = mockComponent(
'../Libraries/Modal/Modal',
null, // instanceMethods
true, // isESModule
) as TModal;

// $FlowIgnore[incompatible-use]
export default class Modal extends BaseComponent {
render(): React.Node {
if (this.props.visible === false) {
return null;
}
return <BaseComponent {...this.props}>{this.props.children}</BaseComponent>;
}
}
Loading
Loading