mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Export existing Fantom tests (2nd attempt) (#48118)
Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/48118 Changelog: [internal] This is a re-land of https://github.com/facebook/react-native/pull/48085 Reviewed By: rshest Differential Revision: D66820308 fbshipit-source-id: b0ccd4b52965988015422ebdb8cd1172d1f5e9db
This commit is contained in:
committed by
Facebook GitHub Bot
parent
18ebea533d
commit
1243679fe2
+96
@@ -0,0 +1,96 @@
|
||||
/**
|
||||
* 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
|
||||
* @oncall react_native
|
||||
*/
|
||||
|
||||
import '../../../Core/InitializeCore.js';
|
||||
import * as ReactNativeTester from '../../../../src/private/__tests__/ReactNativeTester';
|
||||
import TextInput from '../TextInput';
|
||||
import * as React from 'react';
|
||||
import {useEffect, useLayoutEffect, useRef} from 'react';
|
||||
|
||||
describe('TextInput', () => {
|
||||
it('creates view before dispatching view command from ref function', () => {
|
||||
const root = ReactNativeTester.createRoot();
|
||||
|
||||
ReactNativeTester.runTask(() => {
|
||||
root.render(
|
||||
<TextInput
|
||||
ref={node => {
|
||||
if (node) {
|
||||
node.focus();
|
||||
}
|
||||
}}
|
||||
/>,
|
||||
);
|
||||
});
|
||||
|
||||
const mountingLogs = root.getMountingLogs();
|
||||
|
||||
expect(mountingLogs.length).toBe(2);
|
||||
expect(mountingLogs[0]).toBe('create view type: `AndroidTextInput`');
|
||||
expect(mountingLogs[1]).toBe(
|
||||
'dispatch command `focus` on component `AndroidTextInput`',
|
||||
);
|
||||
});
|
||||
|
||||
it('creates view before dispatching view command from useLayoutEffect', () => {
|
||||
const root = ReactNativeTester.createRoot();
|
||||
|
||||
function Component() {
|
||||
const textInputRef = useRef<null | React.ElementRef<typeof TextInput>>(
|
||||
null,
|
||||
);
|
||||
|
||||
useLayoutEffect(() => {
|
||||
textInputRef.current?.focus();
|
||||
});
|
||||
|
||||
return <TextInput ref={textInputRef} />;
|
||||
}
|
||||
ReactNativeTester.runTask(() => {
|
||||
root.render(<Component />);
|
||||
});
|
||||
|
||||
const mountingLogs = root.getMountingLogs();
|
||||
|
||||
expect(mountingLogs.length).toBe(2);
|
||||
expect(mountingLogs[0]).toBe('create view type: `AndroidTextInput`');
|
||||
expect(mountingLogs[1]).toBe(
|
||||
'dispatch command `focus` on component `AndroidTextInput`',
|
||||
);
|
||||
});
|
||||
|
||||
it('creates view before dispatching view command from useEffect', () => {
|
||||
const root = ReactNativeTester.createRoot();
|
||||
|
||||
function Component() {
|
||||
const textInputRef = useRef<null | React.ElementRef<typeof TextInput>>(
|
||||
null,
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
textInputRef.current?.focus();
|
||||
});
|
||||
|
||||
return <TextInput ref={textInputRef} />;
|
||||
}
|
||||
ReactNativeTester.runTask(() => {
|
||||
root.render(<Component />);
|
||||
});
|
||||
|
||||
const mountingLogs = root.getMountingLogs();
|
||||
|
||||
expect(mountingLogs.length).toBe(2);
|
||||
expect(mountingLogs[0]).toBe('create view type: `AndroidTextInput`');
|
||||
expect(mountingLogs[1]).toBe(
|
||||
'dispatch command `focus` on component `AndroidTextInput`',
|
||||
);
|
||||
});
|
||||
});
|
||||
+245
@@ -0,0 +1,245 @@
|
||||
/**
|
||||
* 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
|
||||
* @oncall react_native
|
||||
*/
|
||||
|
||||
import '../../Core/InitializeCore.js';
|
||||
import * as ReactNativeTester from '../../../src/private/__tests__/ReactNativeTester';
|
||||
import View from '../../Components/View/View';
|
||||
import * as React from 'react';
|
||||
import {Suspense, startTransition} from 'react';
|
||||
|
||||
let resolveFunction: (() => void) | null = null;
|
||||
|
||||
// This is a workaround for a bug to get the demo running.
|
||||
// TODO: replace with real implementation when the bug is fixed.
|
||||
// $FlowFixMe: [missing-local-annot]
|
||||
function use(promise) {
|
||||
if (promise.status === 'fulfilled') {
|
||||
return promise.value;
|
||||
} else if (promise.status === 'rejected') {
|
||||
throw promise.reason;
|
||||
} else if (promise.status === 'pending') {
|
||||
throw promise;
|
||||
} else {
|
||||
promise.status = 'pending';
|
||||
promise.then(
|
||||
result => {
|
||||
promise.status = 'fulfilled';
|
||||
promise.value = result;
|
||||
},
|
||||
reason => {
|
||||
promise.status = 'rejected';
|
||||
promise.reason = reason;
|
||||
},
|
||||
);
|
||||
throw promise;
|
||||
}
|
||||
}
|
||||
|
||||
type SquareData = {
|
||||
color: 'red' | 'green',
|
||||
};
|
||||
|
||||
enum SquareId {
|
||||
Green = 'green-square',
|
||||
Red = 'red-square',
|
||||
}
|
||||
|
||||
async function getGreenSquareData(): Promise<SquareData> {
|
||||
await new Promise(resolve => {
|
||||
resolveFunction = resolve;
|
||||
});
|
||||
return {
|
||||
color: 'green',
|
||||
};
|
||||
}
|
||||
|
||||
async function getRedSquareData(): Promise<SquareData> {
|
||||
await new Promise(resolve => {
|
||||
resolveFunction = resolve;
|
||||
});
|
||||
return {
|
||||
color: 'red',
|
||||
};
|
||||
}
|
||||
|
||||
const cache = new Map<SquareId, SquareData>();
|
||||
|
||||
async function getData(squareId: SquareId): Promise<SquareData> {
|
||||
switch (squareId) {
|
||||
case SquareId.Green:
|
||||
return await getGreenSquareData();
|
||||
case SquareId.Red:
|
||||
return await getRedSquareData();
|
||||
}
|
||||
}
|
||||
|
||||
async function fetchData(squareId: SquareId): Promise<SquareData> {
|
||||
const data = await getData(squareId);
|
||||
cache.set(squareId, data);
|
||||
return data;
|
||||
}
|
||||
|
||||
function Square(props: {squareId: SquareId}) {
|
||||
let data = cache.get(props.squareId);
|
||||
if (data == null) {
|
||||
data = use(fetchData(props.squareId));
|
||||
}
|
||||
return <View key={data.color} nativeID={'square with data: ' + data.color} />;
|
||||
}
|
||||
|
||||
function GreenSquare() {
|
||||
return <Square squareId={SquareId.Green} />;
|
||||
}
|
||||
|
||||
function RedSquare() {
|
||||
return <Square squareId={SquareId.Red} />;
|
||||
}
|
||||
|
||||
function Fallback() {
|
||||
return <View nativeID="suspense fallback" />;
|
||||
}
|
||||
|
||||
describe('Suspense', () => {
|
||||
it('shows fallback if data is not available', () => {
|
||||
cache.clear();
|
||||
const root = ReactNativeTester.createRoot();
|
||||
|
||||
ReactNativeTester.runTask(() => {
|
||||
root.render(
|
||||
<Suspense fallback={<Fallback />}>
|
||||
<GreenSquare />
|
||||
</Suspense>,
|
||||
);
|
||||
});
|
||||
|
||||
let mountingLogs = root.getMountingLogs();
|
||||
|
||||
expect(mountingLogs.length).toBe(1);
|
||||
expect(mountingLogs[0]).toBe(
|
||||
'create view type: `View` nativeId: `suspense fallback`',
|
||||
);
|
||||
|
||||
expect(resolveFunction).not.toBeNull();
|
||||
ReactNativeTester.runTask(() => {
|
||||
resolveFunction?.();
|
||||
resolveFunction = null;
|
||||
});
|
||||
|
||||
mountingLogs = root.getMountingLogs();
|
||||
|
||||
expect(mountingLogs.length).toBe(1);
|
||||
expect(mountingLogs[0]).toBe(
|
||||
'create view type: `View` nativeId: `square with data: green`',
|
||||
);
|
||||
|
||||
ReactNativeTester.runTask(() => {
|
||||
root.render(
|
||||
<Suspense fallback={<Fallback />}>
|
||||
<RedSquare />
|
||||
</Suspense>,
|
||||
);
|
||||
});
|
||||
|
||||
mountingLogs = root.getMountingLogs();
|
||||
|
||||
expect(mountingLogs.length).toBe(1);
|
||||
expect(mountingLogs[0]).toBe(
|
||||
'create view type: `View` nativeId: `suspense fallback`',
|
||||
);
|
||||
|
||||
expect(resolveFunction).not.toBeNull();
|
||||
ReactNativeTester.runTask(() => {
|
||||
resolveFunction?.();
|
||||
resolveFunction = null;
|
||||
});
|
||||
|
||||
mountingLogs = root.getMountingLogs();
|
||||
|
||||
expect(mountingLogs.length).toBe(1);
|
||||
expect(mountingLogs[0]).toBe(
|
||||
'create view type: `View` nativeId: `square with data: red`',
|
||||
);
|
||||
|
||||
ReactNativeTester.runTask(() => {
|
||||
root.render(
|
||||
<Suspense fallback={<Fallback />}>
|
||||
<GreenSquare />
|
||||
</Suspense>,
|
||||
);
|
||||
});
|
||||
|
||||
mountingLogs = root.getMountingLogs();
|
||||
|
||||
expect(mountingLogs.length).toBe(1);
|
||||
expect(mountingLogs[0]).toBe(
|
||||
'create view type: `View` nativeId: `square with data: green`',
|
||||
);
|
||||
|
||||
expect(resolveFunction).toBeNull();
|
||||
|
||||
root.destroy();
|
||||
});
|
||||
|
||||
// TODO(T207868872): this test only succeeds with enableFabricCompleteRootInCommitPhase enabled.
|
||||
// enableFabricCompleteRootInCommitPhase is hardcoded to true in the testing environment.
|
||||
it('shows stale data while transition is happening', () => {
|
||||
cache.clear();
|
||||
cache.set(SquareId.Green, {color: 'green'});
|
||||
|
||||
const root = ReactNativeTester.createRoot();
|
||||
|
||||
function App(props: {color: 'red' | 'green'}) {
|
||||
return (
|
||||
<Suspense fallback={<Fallback />}>
|
||||
{props.color === 'green' ? <GreenSquare /> : <RedSquare />}
|
||||
</Suspense>
|
||||
);
|
||||
}
|
||||
|
||||
ReactNativeTester.runTask(() => {
|
||||
root.render(<App color="green" />);
|
||||
});
|
||||
|
||||
let mountingLogs = root.getMountingLogs();
|
||||
|
||||
expect(mountingLogs.length).toBe(1);
|
||||
expect(mountingLogs[0]).toBe(
|
||||
'create view type: `View` nativeId: `square with data: green`',
|
||||
);
|
||||
|
||||
expect(resolveFunction).toBeNull();
|
||||
ReactNativeTester.runTask(() => {
|
||||
startTransition(() => {
|
||||
root.render(<App color="red" />);
|
||||
});
|
||||
});
|
||||
|
||||
mountingLogs = root.getMountingLogs();
|
||||
|
||||
// Green square is still mounted. Fallback is not shown to the user.
|
||||
expect(mountingLogs.length).toBe(0);
|
||||
|
||||
expect(resolveFunction).not.toBeNull();
|
||||
ReactNativeTester.runTask(() => {
|
||||
resolveFunction?.();
|
||||
resolveFunction = null;
|
||||
});
|
||||
|
||||
mountingLogs = root.getMountingLogs();
|
||||
|
||||
expect(mountingLogs.length).toBe(1);
|
||||
expect(mountingLogs[0]).toBe(
|
||||
'create view type: `View` nativeId: `square with data: red`',
|
||||
);
|
||||
|
||||
root.destroy();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,515 @@
|
||||
/**
|
||||
* 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
|
||||
* @oncall react_native
|
||||
*/
|
||||
|
||||
function ensureError(fn: () => void): void {
|
||||
try {
|
||||
fn();
|
||||
} catch (e) {
|
||||
return;
|
||||
}
|
||||
|
||||
throw new Error(`Expected function to throw, but it didn't`);
|
||||
}
|
||||
|
||||
describe('expect', () => {
|
||||
test('toThrow', () => {
|
||||
expect(() => {
|
||||
throw new Error();
|
||||
}).toThrow();
|
||||
|
||||
expect(() => {
|
||||
throw new Error('error message');
|
||||
}).toThrow('error message');
|
||||
|
||||
expect(() => {
|
||||
throw new Error('error message');
|
||||
}).not.toThrow('error message 2');
|
||||
|
||||
expect(() => {}).not.toThrow();
|
||||
|
||||
ensureError(() => {
|
||||
expect(() => {}).toThrow();
|
||||
});
|
||||
|
||||
ensureError(() => {
|
||||
expect(() => {
|
||||
throw new Error();
|
||||
}).not.toThrow();
|
||||
});
|
||||
});
|
||||
|
||||
test('toBe', () => {
|
||||
expect(1).toBe(1);
|
||||
expect(1).not.toBe(2);
|
||||
|
||||
const obj = {a: 1};
|
||||
const obj2 = {a: 1};
|
||||
|
||||
expect(obj).toBe(obj);
|
||||
expect(obj).not.toBe(obj2);
|
||||
|
||||
expect(() => {
|
||||
expect(obj).not.toBe(obj);
|
||||
}).toThrow();
|
||||
|
||||
expect(() => {
|
||||
expect(1).not.toBe(1);
|
||||
}).toThrow();
|
||||
});
|
||||
|
||||
test('toEqual', () => {
|
||||
expect(1).toEqual(1);
|
||||
expect(1).not.toEqual(2);
|
||||
|
||||
const obj = {a: 1};
|
||||
const obj2 = {a: 1};
|
||||
const obj3 = {a: 2};
|
||||
|
||||
expect(obj).toEqual(obj);
|
||||
expect(obj).toEqual(obj2);
|
||||
expect(obj).not.toEqual(obj3);
|
||||
|
||||
expect(null).toEqual(null);
|
||||
expect(undefined).toEqual(undefined);
|
||||
expect(null).not.toEqual(undefined);
|
||||
|
||||
expect({a: null}).not.toEqual({a: undefined});
|
||||
expect({a: undefined}).not.toEqual({});
|
||||
|
||||
expect(() => {
|
||||
expect(obj).not.toEqual(obj2);
|
||||
}).toThrow();
|
||||
|
||||
expect(() => {
|
||||
expect(obj).toEqual(obj3);
|
||||
}).toThrow();
|
||||
|
||||
expect(() => {
|
||||
expect(1).not.toEqual(1);
|
||||
}).toThrow();
|
||||
|
||||
expect(() => {
|
||||
expect(null).not.toEqual(null);
|
||||
}).toThrow();
|
||||
|
||||
expect(() => {
|
||||
expect(undefined).not.toEqual(undefined);
|
||||
}).toThrow();
|
||||
|
||||
expect(() => {
|
||||
expect({a: undefined}).toEqual({});
|
||||
}).toThrow();
|
||||
});
|
||||
|
||||
test('toBeInstanceOf', () => {
|
||||
class Class {}
|
||||
|
||||
expect(1).not.toBeInstanceOf(Number);
|
||||
expect(1).not.toBeInstanceOf(Class);
|
||||
|
||||
expect(new Class()).toBeInstanceOf(Class);
|
||||
expect(new Class()).toBeInstanceOf(Object);
|
||||
expect(new Class()).not.toBeInstanceOf(Number);
|
||||
|
||||
expect(() => {
|
||||
expect(1).toBeInstanceOf(Number);
|
||||
}).toThrow();
|
||||
|
||||
expect(() => {
|
||||
expect(new Class()).not.toBeInstanceOf(Class);
|
||||
}).toThrow();
|
||||
});
|
||||
|
||||
test('toBeCloseTo', () => {
|
||||
expect(1).toBeCloseTo(1.001);
|
||||
expect(1).toBeCloseTo(1.01, 1);
|
||||
expect(1).toBeCloseTo(1.1, 0);
|
||||
|
||||
expect(() => {
|
||||
expect(1).toBeCloseTo(1.01);
|
||||
}).toThrow();
|
||||
|
||||
expect(() => {
|
||||
expect(1).toBeCloseTo(1.1, 1);
|
||||
}).toThrow();
|
||||
|
||||
expect(() => {
|
||||
expect(1).toBeCloseTo(2, 0);
|
||||
}).toThrow();
|
||||
});
|
||||
|
||||
test('toHaveBeenCalled', () => {
|
||||
const fn = jest.fn();
|
||||
|
||||
expect(fn).not.toHaveBeenCalled();
|
||||
|
||||
expect(() => {
|
||||
expect(fn).toHaveBeenCalled();
|
||||
}).toThrow();
|
||||
|
||||
fn();
|
||||
|
||||
expect(fn).toHaveBeenCalled();
|
||||
|
||||
expect(() => {
|
||||
expect(fn).not.toHaveBeenCalled();
|
||||
}).toThrow();
|
||||
|
||||
// Passing functions that aren't mocks should always fail
|
||||
expect(() => {
|
||||
expect(() => {}).toHaveBeenCalled();
|
||||
}).toThrow();
|
||||
|
||||
expect(() => {
|
||||
expect(() => {}).not.toHaveBeenCalled();
|
||||
}).toThrow();
|
||||
});
|
||||
|
||||
test('toHaveBeenCalledTimes', () => {
|
||||
const fn = jest.fn();
|
||||
|
||||
expect(fn).toHaveBeenCalledTimes(0);
|
||||
expect(fn).not.toHaveBeenCalledTimes(1);
|
||||
|
||||
expect(() => {
|
||||
expect(fn).not.toHaveBeenCalledTimes(0);
|
||||
}).toThrow();
|
||||
|
||||
expect(() => {
|
||||
expect(fn).toHaveBeenCalledTimes(1);
|
||||
}).toThrow();
|
||||
|
||||
fn();
|
||||
|
||||
expect(fn).not.toHaveBeenCalledTimes(0);
|
||||
expect(fn).toHaveBeenCalledTimes(1);
|
||||
|
||||
expect(() => {
|
||||
expect(fn).toHaveBeenCalledTimes(0);
|
||||
}).toThrow();
|
||||
|
||||
expect(() => {
|
||||
expect(fn).not.toHaveBeenCalledTimes(1);
|
||||
}).toThrow();
|
||||
|
||||
// Passing functions that aren't mocks should always fail
|
||||
expect(() => {
|
||||
expect(() => {}).toHaveBeenCalledTimes(0);
|
||||
}).toThrow();
|
||||
|
||||
expect(() => {
|
||||
expect(() => {}).not.toHaveBeenCalledTimes(1);
|
||||
}).toThrow();
|
||||
});
|
||||
|
||||
describe('jest.fn()', () => {
|
||||
it('tracks execution of functions without implementations', () => {
|
||||
const fn = jest.fn();
|
||||
|
||||
expect(fn).toBeInstanceOf(Function);
|
||||
|
||||
expect(fn.mock.calls).toEqual([]);
|
||||
expect(fn.mock.lastCall).toBe(undefined);
|
||||
expect(fn.mock.instances).toEqual([]);
|
||||
expect(fn.mock.contexts).toEqual([]);
|
||||
expect(fn.mock.results).toEqual([]);
|
||||
|
||||
expect(fn()).toBe(undefined);
|
||||
|
||||
expect(fn.mock.calls).toEqual([[]]);
|
||||
expect(fn.mock.lastCall).toEqual([]);
|
||||
expect(fn.mock.instances).toEqual([undefined]);
|
||||
expect(fn.mock.contexts).toEqual([global]);
|
||||
expect(fn.mock.contexts[0]).toBe(global);
|
||||
expect(fn.mock.results).toEqual([{value: undefined, isThrow: false}]);
|
||||
});
|
||||
|
||||
it('tracks execution of methods without implementations', () => {
|
||||
const fn = jest.fn();
|
||||
|
||||
expect(fn).toBeInstanceOf(Function);
|
||||
|
||||
expect(fn.mock.calls).toEqual([]);
|
||||
expect(fn.mock.lastCall).toBe(undefined);
|
||||
expect(fn.mock.instances).toEqual([]);
|
||||
expect(fn.mock.contexts).toEqual([]);
|
||||
expect(fn.mock.results).toEqual([]);
|
||||
|
||||
const obj = {fn};
|
||||
expect(obj.fn()).toBe(undefined);
|
||||
|
||||
expect(fn.mock.calls).toEqual([[]]);
|
||||
expect(fn.mock.lastCall).toEqual([]);
|
||||
expect(fn.mock.instances).toEqual([undefined]);
|
||||
expect(fn.mock.contexts).toEqual([obj]);
|
||||
expect(fn.mock.contexts[0]).toBe(obj);
|
||||
expect(fn.mock.results).toEqual([{value: undefined, isThrow: false}]);
|
||||
});
|
||||
|
||||
it('tracks constructors without implementations', () => {
|
||||
const fn = jest.fn();
|
||||
|
||||
expect(fn).toBeInstanceOf(Function);
|
||||
|
||||
expect(fn.mock.calls).toEqual([]);
|
||||
expect(fn.mock.lastCall).toBe(undefined);
|
||||
expect(fn.mock.instances).toEqual([]);
|
||||
expect(fn.mock.contexts).toEqual([]);
|
||||
expect(fn.mock.results).toEqual([]);
|
||||
|
||||
// $FlowExpectedError[invalid-constructor]
|
||||
const instance = new fn();
|
||||
expect(instance).toBeInstanceOf(Object);
|
||||
|
||||
expect(fn.mock.calls).toEqual([[]]);
|
||||
expect(fn.mock.lastCall).toEqual([]);
|
||||
expect(fn.mock.instances).toEqual([instance]);
|
||||
expect(fn.mock.instances[0]).toBe(instance);
|
||||
expect(fn.mock.contexts).toEqual([instance]);
|
||||
expect(fn.mock.contexts[0]).toBe(instance);
|
||||
expect(fn.mock.results).toEqual([{value: undefined, isThrow: false}]);
|
||||
});
|
||||
|
||||
it('tracks execution of functions with an implementation', () => {
|
||||
const fn = jest.fn((a, b) => {
|
||||
return a + b;
|
||||
});
|
||||
|
||||
expect(fn).toBeInstanceOf(Function);
|
||||
|
||||
expect(fn.mock.calls).toEqual([]);
|
||||
expect(fn.mock.lastCall).toBe(undefined);
|
||||
expect(fn.mock.instances).toEqual([]);
|
||||
expect(fn.mock.contexts).toEqual([]);
|
||||
expect(fn.mock.results).toEqual([]);
|
||||
|
||||
expect(fn(1, 2)).toBe(3);
|
||||
|
||||
expect(fn.mock.calls).toEqual([[1, 2]]);
|
||||
expect(fn.mock.lastCall).toEqual([1, 2]);
|
||||
expect(fn.mock.instances).toEqual([undefined]);
|
||||
expect(fn.mock.contexts).toEqual([global]);
|
||||
expect(fn.mock.contexts[0]).toBe(global);
|
||||
expect(fn.mock.results).toEqual([{value: 3, isThrow: false}]);
|
||||
});
|
||||
|
||||
it('tracks execution of methods with an implementation', () => {
|
||||
const fn = jest.fn(function (this: {prop: number}): number {
|
||||
return this.prop;
|
||||
});
|
||||
|
||||
expect(fn).toBeInstanceOf(Function);
|
||||
|
||||
expect(fn.mock.calls).toEqual([]);
|
||||
expect(fn.mock.lastCall).toBe(undefined);
|
||||
expect(fn.mock.instances).toEqual([]);
|
||||
expect(fn.mock.contexts).toEqual([]);
|
||||
expect(fn.mock.results).toEqual([]);
|
||||
|
||||
const obj = {fn, prop: 2};
|
||||
expect(obj.fn()).toBe(2);
|
||||
|
||||
expect(fn.mock.calls).toEqual([[]]);
|
||||
expect(fn.mock.lastCall).toEqual([]);
|
||||
expect(fn.mock.instances).toEqual([undefined]);
|
||||
expect(fn.mock.contexts).toEqual([obj]);
|
||||
expect(fn.mock.contexts[0]).toBe(obj);
|
||||
expect(fn.mock.results).toEqual([{value: 2, isThrow: false}]);
|
||||
});
|
||||
|
||||
it('tracks constructors with an implementation', () => {
|
||||
const fn = jest.fn(function (this: {prop: number}) {
|
||||
this.prop = 3;
|
||||
});
|
||||
|
||||
expect(fn).toBeInstanceOf(Function);
|
||||
|
||||
expect(fn.mock.calls).toEqual([]);
|
||||
expect(fn.mock.lastCall).toBe(undefined);
|
||||
expect(fn.mock.instances).toEqual([]);
|
||||
expect(fn.mock.contexts).toEqual([]);
|
||||
expect(fn.mock.results).toEqual([]);
|
||||
|
||||
// $FlowExpectedError[invalid-constructor]
|
||||
const instance = new fn();
|
||||
expect(instance).toBeInstanceOf(Object);
|
||||
|
||||
expect(instance.prop).toBe(3);
|
||||
|
||||
expect(fn.mock.calls).toEqual([[]]);
|
||||
expect(fn.mock.lastCall).toEqual([]);
|
||||
expect(fn.mock.instances).toEqual([instance]);
|
||||
expect(fn.mock.instances[0]).toBe(instance);
|
||||
expect(fn.mock.contexts).toEqual([instance]);
|
||||
expect(fn.mock.contexts[0]).toBe(instance);
|
||||
expect(fn.mock.results).toEqual([{value: undefined, isThrow: false}]);
|
||||
});
|
||||
});
|
||||
|
||||
test('toBeNull()', () => {
|
||||
expect(null).toBeNull();
|
||||
expect('string value').not.toBeNull();
|
||||
|
||||
expect(() => {
|
||||
expect(null).not.toBeNull();
|
||||
}).toThrow();
|
||||
|
||||
expect(() => {
|
||||
expect('string value').toBeNull();
|
||||
}).toThrow();
|
||||
});
|
||||
|
||||
test('toBeLessThan', () => {
|
||||
expect(1).toBeLessThan(2);
|
||||
|
||||
expect(1).not.toBeLessThan(1);
|
||||
|
||||
expect(1).not.toBeLessThan(0);
|
||||
|
||||
expect(() => {
|
||||
expect(1).toBeLessThan(0);
|
||||
}).toThrow();
|
||||
|
||||
expect(() => {
|
||||
expect(1).toBeLessThan(1);
|
||||
}).toThrow();
|
||||
|
||||
expect(() => {
|
||||
expect(1).not.toBeLessThan(2);
|
||||
}).toThrow();
|
||||
|
||||
// Should always throw if the received value isn't a number
|
||||
expect(() => {
|
||||
expect('string value').toBeLessThan(1);
|
||||
}).toThrow();
|
||||
|
||||
expect(() => {
|
||||
expect('string value').not.toBeLessThan(1);
|
||||
}).toThrow();
|
||||
|
||||
// Should always throw if the expected value isn't a number
|
||||
expect(() => {
|
||||
// $FlowExpectedError[incompatible-call]
|
||||
expect(1).toBeLessThan('string value');
|
||||
}).toThrow();
|
||||
|
||||
expect(() => {
|
||||
// $FlowExpectedError[incompatible-call]
|
||||
expect(1).not.toBeLessThan('string value');
|
||||
}).toThrow();
|
||||
});
|
||||
|
||||
test('toBeLessThanOrEqual', () => {
|
||||
expect(1).toBeLessThanOrEqual(1);
|
||||
expect(1).toBeLessThanOrEqual(2);
|
||||
|
||||
expect(1).not.toBeLessThanOrEqual(0.8);
|
||||
|
||||
expect(() => {
|
||||
expect(1).not.toBeLessThanOrEqual(1);
|
||||
}).toThrow();
|
||||
|
||||
expect(() => {
|
||||
expect(1).not.toBeLessThanOrEqual(2);
|
||||
}).toThrow();
|
||||
|
||||
// Should always throw if the received value isn't a number
|
||||
expect(() => {
|
||||
expect('string value').toBeLessThanOrEqual(1);
|
||||
}).toThrow();
|
||||
|
||||
expect(() => {
|
||||
expect('string value').not.toBeLessThanOrEqual(1);
|
||||
}).toThrow();
|
||||
|
||||
// Should always throw if the expected value isn't a number
|
||||
expect(() => {
|
||||
// $FlowExpectedError[incompatible-call]
|
||||
expect(1).toBeLessThanOrEqual('string value');
|
||||
}).toThrow();
|
||||
|
||||
expect(() => {
|
||||
// $FlowExpectedError[incompatible-call]
|
||||
expect(1).not.toBeLessThanOrEqual('string value');
|
||||
}).toThrow();
|
||||
});
|
||||
|
||||
test('toBeGreaterThan', () => {
|
||||
expect(1).toBeGreaterThan(0);
|
||||
|
||||
expect(1).not.toBeGreaterThan(1);
|
||||
|
||||
expect(1).not.toBeGreaterThan(2);
|
||||
|
||||
expect(() => {
|
||||
expect(1).toBeGreaterThan(2);
|
||||
}).toThrow();
|
||||
|
||||
expect(() => {
|
||||
expect(1).not.toBeGreaterThan(0);
|
||||
}).toThrow();
|
||||
|
||||
// Should always throw if the received value isn't a number
|
||||
expect(() => {
|
||||
expect('string value').toBeGreaterThan(1);
|
||||
}).toThrow();
|
||||
|
||||
expect(() => {
|
||||
expect('string value').not.toBeGreaterThan(1);
|
||||
}).toThrow();
|
||||
|
||||
// Should always throw if the expected value isn't a number
|
||||
expect(() => {
|
||||
// $FlowExpectedError[incompatible-call]
|
||||
expect(1).toBeGreaterThan('string value');
|
||||
}).toThrow();
|
||||
|
||||
expect(() => {
|
||||
// $FlowExpectedError[incompatible-call]
|
||||
expect(1).not.toBeGreaterThan('string value');
|
||||
}).toThrow();
|
||||
});
|
||||
|
||||
test('toBeGreaterThanOrEqual', () => {
|
||||
expect(1).toBeGreaterThanOrEqual(0);
|
||||
expect(1).toBeGreaterThanOrEqual(1);
|
||||
|
||||
expect(1).not.toBeGreaterThanOrEqual(2);
|
||||
|
||||
expect(() => {
|
||||
expect(1).not.toBeGreaterThanOrEqual(0);
|
||||
}).toThrow();
|
||||
|
||||
expect(() => {
|
||||
expect(1).not.toBeGreaterThanOrEqual(1);
|
||||
}).toThrow();
|
||||
|
||||
// Should always throw if the received value isn't a number
|
||||
expect(() => {
|
||||
expect('string value').toBeGreaterThanOrEqual(1);
|
||||
}).toThrow();
|
||||
|
||||
expect(() => {
|
||||
expect('string value').not.toBeGreaterThanOrEqual(1);
|
||||
}).toThrow();
|
||||
|
||||
// Should always throw if the expected value isn't a number
|
||||
expect(() => {
|
||||
// $FlowExpectedError[incompatible-call]
|
||||
expect(1).toBeGreaterThanOrEqual('string value');
|
||||
}).toThrow();
|
||||
|
||||
expect(() => {
|
||||
// $FlowExpectedError[incompatible-call]
|
||||
expect(1).not.toBeGreaterThanOrEqual('string value');
|
||||
}).toThrow();
|
||||
});
|
||||
});
|
||||
+1199
File diff suppressed because it is too large
Load Diff
+412
@@ -0,0 +1,412 @@
|
||||
/**
|
||||
* 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
|
||||
* @oncall react_native
|
||||
*/
|
||||
|
||||
import './setUpFeatureFlags';
|
||||
import '../../../../../../Libraries/Core/InitializeCore.js';
|
||||
|
||||
import {NativeText} from '../../../../../../Libraries/Text/TextNativeComponent';
|
||||
import * as ReactNativeTester from '../../../../../../src/private/__tests__/ReactNativeTester';
|
||||
import ReactNativeElement from '../ReactNativeElement';
|
||||
import ReadOnlyNode from '../ReadOnlyNode';
|
||||
import ReadOnlyText from '../ReadOnlyText';
|
||||
import invariant from 'invariant';
|
||||
import * as React from 'react';
|
||||
|
||||
function ensureReadOnlyText(value: mixed): ReadOnlyText {
|
||||
if (!(value instanceof ReadOnlyText)) {
|
||||
throw new Error(
|
||||
`Expected instance of ReactOnlyNode but got ${String(value)}`,
|
||||
);
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
function ensureReadOnlyNode(value: mixed): ReadOnlyNode {
|
||||
if (!(value instanceof ReadOnlyNode)) {
|
||||
throw new Error(
|
||||
`Expected instance of ReactOnlyNode but got ${String(value)}`,
|
||||
);
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
function ensureReactNativeElement(value: mixed): ReactNativeElement {
|
||||
if (!(value instanceof ReactNativeElement)) {
|
||||
throw new Error(
|
||||
`Expected instance of ReactNativeElement but got ${String(value)}`,
|
||||
);
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
describe('ReadOnlyText', () => {
|
||||
it('should be used to create public text instances when the `enableAccessToHostTreeInFabric` feature flag is enabled', () => {
|
||||
let lastParentNode;
|
||||
|
||||
const root = ReactNativeTester.createRoot();
|
||||
|
||||
ReactNativeTester.runTask(() => {
|
||||
root.render(
|
||||
<NativeText
|
||||
ref={node => {
|
||||
lastParentNode = node;
|
||||
}}>
|
||||
Some text
|
||||
</NativeText>,
|
||||
);
|
||||
});
|
||||
|
||||
const parentNode = ensureReadOnlyNode(lastParentNode);
|
||||
const textNode = parentNode.childNodes[0];
|
||||
|
||||
expect(textNode).toBeInstanceOf(ReadOnlyText);
|
||||
});
|
||||
|
||||
describe('extends `ReadOnlyNode`', () => {
|
||||
describe('nodeName', () => {
|
||||
it('returns "#text"', () => {
|
||||
let lastParentNode;
|
||||
|
||||
const root = ReactNativeTester.createRoot();
|
||||
|
||||
ReactNativeTester.runTask(() => {
|
||||
root.render(
|
||||
<NativeText
|
||||
ref={node => {
|
||||
lastParentNode = node;
|
||||
}}>
|
||||
Some text
|
||||
</NativeText>,
|
||||
);
|
||||
});
|
||||
|
||||
const parentNode = ensureReadOnlyNode(lastParentNode);
|
||||
const textNode = parentNode.childNodes[0];
|
||||
|
||||
expect(textNode.nodeName).toBe('#text');
|
||||
});
|
||||
});
|
||||
|
||||
describe('nodeType', () => {
|
||||
it('returns ReadOnlyNode.TEXT_NODE', () => {
|
||||
let lastParentNode;
|
||||
|
||||
const root = ReactNativeTester.createRoot();
|
||||
|
||||
ReactNativeTester.runTask(() => {
|
||||
root.render(
|
||||
<NativeText
|
||||
ref={node => {
|
||||
lastParentNode = node;
|
||||
}}>
|
||||
Some text
|
||||
</NativeText>,
|
||||
);
|
||||
});
|
||||
|
||||
const parentNode = ensureReadOnlyNode(lastParentNode);
|
||||
const textNode = parentNode.childNodes[0];
|
||||
|
||||
expect(textNode.nodeType).toBe(ReadOnlyNode.TEXT_NODE);
|
||||
});
|
||||
});
|
||||
|
||||
describe('nodeValue / textContent', () => {
|
||||
it('returns the string data contained in the node', () => {
|
||||
let lastParentNode;
|
||||
|
||||
const root = ReactNativeTester.createRoot();
|
||||
|
||||
ReactNativeTester.runTask(() => {
|
||||
root.render(
|
||||
<NativeText
|
||||
ref={node => {
|
||||
lastParentNode = node;
|
||||
}}>
|
||||
Some text
|
||||
</NativeText>,
|
||||
);
|
||||
});
|
||||
|
||||
const parentNode = ensureReadOnlyNode(lastParentNode);
|
||||
const textNode = parentNode.childNodes[0];
|
||||
|
||||
expect(textNode.nodeValue).toBe('Some text');
|
||||
expect(textNode.textContent).toBe('Some text');
|
||||
});
|
||||
});
|
||||
|
||||
describe('traversal', () => {
|
||||
it('only preserves text nodes when their contents do not change', () => {
|
||||
let lastParentElement;
|
||||
let lastChildElementA;
|
||||
|
||||
const root = ReactNativeTester.createRoot();
|
||||
|
||||
ReactNativeTester.runTask(() => {
|
||||
root.render(
|
||||
<NativeText
|
||||
key="parent"
|
||||
ref={element => {
|
||||
lastParentElement = element;
|
||||
}}>
|
||||
Text A
|
||||
<NativeText
|
||||
key="childA"
|
||||
ref={element => {
|
||||
lastChildElementA = element;
|
||||
}}
|
||||
/>
|
||||
Text B
|
||||
</NativeText>,
|
||||
);
|
||||
});
|
||||
|
||||
const parentElement: ReactNativeElement =
|
||||
ensureReactNativeElement(lastParentElement);
|
||||
const childElementA: ReactNativeElement =
|
||||
ensureReactNativeElement(lastChildElementA);
|
||||
|
||||
// Get text nodes and refine them as text nodes for Flow
|
||||
const childTextA = parentElement.childNodes[0];
|
||||
invariant(
|
||||
childTextA instanceof ReadOnlyText,
|
||||
'expected instance of ReadOnlyText',
|
||||
);
|
||||
expect(childTextA.textContent).toBe('Text A');
|
||||
const childTextB = parentElement.childNodes[2];
|
||||
invariant(
|
||||
childTextB instanceof ReadOnlyText,
|
||||
'expected instance of ReadOnlyText',
|
||||
);
|
||||
expect(childTextB.textContent).toBe('Text B');
|
||||
|
||||
// Validate structure
|
||||
expect(parentElement.childNodes.length).toBe(3);
|
||||
expect(parentElement.childNodes[0]).toBe(childTextA);
|
||||
expect(parentElement.childNodes[1]).toBe(childElementA);
|
||||
expect(parentElement.childNodes[2]).toBe(childTextB);
|
||||
|
||||
// Change contents of the second text only
|
||||
ReactNativeTester.runTask(() => {
|
||||
root.render(
|
||||
<NativeText
|
||||
key="parent"
|
||||
ref={element => {
|
||||
lastParentElement = element;
|
||||
}}>
|
||||
Text A
|
||||
<NativeText
|
||||
key="childA"
|
||||
ref={element => {
|
||||
lastChildElementA = element;
|
||||
}}
|
||||
/>
|
||||
Text B modified
|
||||
</NativeText>,
|
||||
);
|
||||
});
|
||||
|
||||
expect(parentElement.childNodes.length).toBe(3);
|
||||
expect(parentElement.childNodes[0]).toBe(childTextA);
|
||||
expect(parentElement.childNodes[1]).toBe(childElementA);
|
||||
expect(parentElement.childNodes[2]).not.toBe(childTextB);
|
||||
expect(parentElement.childNodes[2]).toBeInstanceOf(ReadOnlyText);
|
||||
expect(ensureReadOnlyText(parentElement.childNodes[2]).data).toBe(
|
||||
'Text B modified',
|
||||
);
|
||||
expect(childTextB.isConnected).toBe(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('extends `ReadOnlyCharacterData`', () => {
|
||||
describe('data / length', () => {
|
||||
it('returns the string data and its length, respectively', () => {
|
||||
let lastParentNode;
|
||||
|
||||
const root = ReactNativeTester.createRoot();
|
||||
|
||||
ReactNativeTester.runTask(() => {
|
||||
root.render(
|
||||
<NativeText
|
||||
ref={node => {
|
||||
lastParentNode = node;
|
||||
}}>
|
||||
Some text
|
||||
</NativeText>,
|
||||
);
|
||||
});
|
||||
|
||||
const parentNode: ReadOnlyNode = ensureReadOnlyNode(lastParentNode);
|
||||
const textNode = ensureReadOnlyText(parentNode.childNodes[0]);
|
||||
|
||||
expect(textNode.data).toBe('Some text');
|
||||
expect(textNode.length).toBe('Some text'.length);
|
||||
});
|
||||
});
|
||||
|
||||
describe('previousElementSibling / nextElementSibling', () => {
|
||||
it('return updated relative elements', () => {
|
||||
let lastParentElement;
|
||||
let lastChildElementA;
|
||||
let lastChildElementB;
|
||||
let lastChildElementC;
|
||||
|
||||
const root = ReactNativeTester.createRoot();
|
||||
|
||||
ReactNativeTester.runTask(() => {
|
||||
root.render(
|
||||
<NativeText
|
||||
key="parent"
|
||||
ref={element => {
|
||||
lastParentElement = element;
|
||||
}}>
|
||||
Text A
|
||||
<NativeText
|
||||
key="childA"
|
||||
ref={element => {
|
||||
lastChildElementA = element;
|
||||
}}
|
||||
/>
|
||||
Text B
|
||||
<NativeText
|
||||
key="childB"
|
||||
ref={element => {
|
||||
lastChildElementB = element;
|
||||
}}
|
||||
/>
|
||||
Text C
|
||||
<NativeText
|
||||
key="childC"
|
||||
ref={element => {
|
||||
lastChildElementC = element;
|
||||
}}
|
||||
/>
|
||||
Text D
|
||||
</NativeText>,
|
||||
);
|
||||
});
|
||||
|
||||
const parentElement = ensureReactNativeElement(lastParentElement);
|
||||
const childElementA = ensureReactNativeElement(lastChildElementA);
|
||||
const childElementB = ensureReactNativeElement(lastChildElementB);
|
||||
const childElementC = ensureReactNativeElement(lastChildElementC);
|
||||
|
||||
// Get text nodes and refine them as text nodes for Flow
|
||||
const childTextA = parentElement.childNodes[0];
|
||||
invariant(
|
||||
childTextA instanceof ReadOnlyText,
|
||||
'expected instance of ReadOnlyText',
|
||||
);
|
||||
const childTextB = parentElement.childNodes[2];
|
||||
invariant(
|
||||
childTextB instanceof ReadOnlyText,
|
||||
'expected instance of ReadOnlyText',
|
||||
);
|
||||
const childTextC = parentElement.childNodes[4];
|
||||
invariant(
|
||||
childTextC instanceof ReadOnlyText,
|
||||
'expected instance of ReadOnlyText',
|
||||
);
|
||||
const childTextD = parentElement.childNodes[6];
|
||||
invariant(
|
||||
childTextD instanceof ReadOnlyText,
|
||||
'expected instance of ReadOnlyText',
|
||||
);
|
||||
|
||||
// Validate structure
|
||||
expect(parentElement.childNodes.length).toBe(7);
|
||||
expect(parentElement.childNodes[0]).toBe(childTextA);
|
||||
expect(parentElement.childNodes[1]).toBe(childElementA);
|
||||
expect(parentElement.childNodes[2]).toBe(childTextB);
|
||||
expect(parentElement.childNodes[3]).toBe(childElementB);
|
||||
expect(parentElement.childNodes[4]).toBe(childTextC);
|
||||
expect(parentElement.childNodes[5]).toBe(childElementC);
|
||||
expect(parentElement.childNodes[6]).toBe(childTextD);
|
||||
|
||||
expect(childTextA.previousElementSibling).toBe(null);
|
||||
expect(childTextA.nextElementSibling).toBe(childElementA);
|
||||
|
||||
expect(childTextB.previousElementSibling).toBe(childElementA);
|
||||
expect(childTextB.nextElementSibling).toBe(childElementB);
|
||||
|
||||
expect(childTextC.previousElementSibling).toBe(childElementB);
|
||||
expect(childTextC.nextElementSibling).toBe(childElementC);
|
||||
|
||||
expect(childTextD.previousElementSibling).toBe(childElementC);
|
||||
expect(childTextD.nextElementSibling).toBe(null);
|
||||
});
|
||||
});
|
||||
|
||||
describe('substringData', () => {
|
||||
it('returns a slice of the text content', () => {
|
||||
let lastParentElement;
|
||||
|
||||
const root = ReactNativeTester.createRoot();
|
||||
|
||||
ReactNativeTester.runTask(() => {
|
||||
root.render(
|
||||
<NativeText
|
||||
key="parent"
|
||||
ref={element => {
|
||||
lastParentElement = element;
|
||||
}}>
|
||||
Text A
|
||||
</NativeText>,
|
||||
);
|
||||
});
|
||||
|
||||
const parentElement = ensureReactNativeElement(lastParentElement);
|
||||
|
||||
// Get text nodes and refine them as text nodes for Flow
|
||||
const childTextA = parentElement.childNodes[0];
|
||||
invariant(
|
||||
childTextA instanceof ReadOnlyText,
|
||||
'expected instance of ReadOnlyText',
|
||||
);
|
||||
|
||||
expect(childTextA.substringData(0, 1)).toBe('T');
|
||||
expect(childTextA.substringData(0, 5)).toBe('Text ');
|
||||
// Count > length
|
||||
expect(childTextA.substringData(0, 10)).toBe('Text A');
|
||||
// Count = length
|
||||
expect(childTextA.substringData(0, 6)).toBe('Text A');
|
||||
expect(childTextA.substringData(0, 0)).toBe('');
|
||||
// Negative count
|
||||
expect(childTextA.substringData(0, -1)).toBe('Text A');
|
||||
expect(childTextA.substringData(0, -10)).toBe('Text A');
|
||||
|
||||
expect(childTextA.substringData(1, 3)).toBe('ext');
|
||||
expect(childTextA.substringData(5, 1)).toBe('A');
|
||||
// Offset + count > length
|
||||
expect(childTextA.substringData(5, 2)).toBe('A');
|
||||
// Offset = length
|
||||
expect(childTextA.substringData(6, 1)).toBe('');
|
||||
// Offset = length & negative count
|
||||
expect(childTextA.substringData(6, -1)).toBe('');
|
||||
// Negative count
|
||||
expect(childTextA.substringData(5, -1)).toBe('A');
|
||||
|
||||
// Out of bounds offset
|
||||
expect(() => {
|
||||
childTextA.substringData(-1, 0);
|
||||
}).toThrow();
|
||||
expect(() => {
|
||||
childTextA.substringData(7, 0);
|
||||
}).toThrow();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
+16
@@ -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-local
|
||||
* @format
|
||||
* @oncall react_native
|
||||
*/
|
||||
|
||||
import * as ReactNativeFeatureFlags from '../../../../featureflags/ReactNativeFeatureFlags';
|
||||
|
||||
ReactNativeFeatureFlags.override({
|
||||
enableAccessToHostTreeInFabric: () => true,
|
||||
});
|
||||
+1568
File diff suppressed because it is too large
Load Diff
Vendored
+16
@@ -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-local
|
||||
* @format
|
||||
* @oncall react_native
|
||||
*/
|
||||
|
||||
import * as ReactNativeFeatureFlags from '../../../featureflags/ReactNativeFeatureFlags';
|
||||
|
||||
ReactNativeFeatureFlags.override({
|
||||
enableAccessToHostTreeInFabric: () => true,
|
||||
});
|
||||
Vendored
+1074
File diff suppressed because it is too large
Load Diff
+16
@@ -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-local
|
||||
* @format
|
||||
* @oncall react_native
|
||||
*/
|
||||
|
||||
import * as ReactNativeFeatureFlags from '../../../featureflags/ReactNativeFeatureFlags';
|
||||
|
||||
ReactNativeFeatureFlags.override({
|
||||
enableAccessToHostTreeInFabric: () => true,
|
||||
});
|
||||
Reference in New Issue
Block a user