mirror of
https://github.com/zebrajr/react.git
synced 2025-12-06 00:20:04 +01:00
Add xplat test variants (#29734)
## Overview We didn't have any tests that ran in persistent mode with the xplat feature flags (for either variant). As a result, invalid test gating like in https://github.com/facebook/react/pull/29664 were not caught. This PR adds test flavors for `ReactFeatureFlag-native-fb.js` in both variants.
This commit is contained in:
parent
9185b9b1e4
commit
eabb681535
|
|
@ -507,6 +507,10 @@ workflows:
|
|||
- "-r=www-modern --env=production --variant=false"
|
||||
- "-r=www-modern --env=development --variant=true"
|
||||
- "-r=www-modern --env=production --variant=true"
|
||||
- "-r=xplat --env=development --variant=false"
|
||||
- "-r=xplat --env=development --variant=true"
|
||||
- "-r=xplat --env=production --variant=false"
|
||||
- "-r=xplat --env=production --variant=true"
|
||||
|
||||
# TODO: Test more persistent configurations?
|
||||
- '-r=stable --env=development --persistent'
|
||||
|
|
@ -552,6 +556,12 @@ workflows:
|
|||
# - "-r=www-modern --env=development --variant=true"
|
||||
# - "-r=www-modern --env=production --variant=true"
|
||||
|
||||
# TODO: Update test config to support xplat build tests
|
||||
# - "-r=xplat --env=development --variant=false"
|
||||
# - "-r=xplat --env=development --variant=true"
|
||||
# - "-r=xplat --env=production --variant=false"
|
||||
# - "-r=xplat --env=production --variant=true"
|
||||
|
||||
# TODO: Test more persistent configurations?
|
||||
- download_base_build_for_sizebot:
|
||||
filters:
|
||||
|
|
|
|||
|
|
@ -1377,113 +1377,118 @@ describe('ResponderEventPlugin', () => {
|
|||
expect(ResponderEventPlugin._getResponder()).toBe(null);
|
||||
});
|
||||
|
||||
it('should determine the first common ancestor correctly', async () => {
|
||||
// This test was moved here from the ReactTreeTraversal test since only the
|
||||
// ResponderEventPlugin uses `getLowestCommonAncestor`
|
||||
const React = require('react');
|
||||
const ReactDOMClient = require('react-dom/client');
|
||||
const act = require('internal-test-utils').act;
|
||||
const getLowestCommonAncestor =
|
||||
require('react-native-renderer/src/legacy-events/ResponderEventPlugin').getLowestCommonAncestor;
|
||||
// This works by accident and will likely break in the future.
|
||||
const ReactDOMComponentTree = require('react-dom-bindings/src/client/ReactDOMComponentTree');
|
||||
it(
|
||||
'should determine the first common ancestor correctly',
|
||||
async () => {
|
||||
// This test was moved here from the ReactTreeTraversal test since only the
|
||||
// ResponderEventPlugin uses `getLowestCommonAncestor`
|
||||
const React = require('react');
|
||||
const ReactDOMClient = require('react-dom/client');
|
||||
const act = require('internal-test-utils').act;
|
||||
const getLowestCommonAncestor =
|
||||
require('react-native-renderer/src/legacy-events/ResponderEventPlugin').getLowestCommonAncestor;
|
||||
// This works by accident and will likely break in the future.
|
||||
const ReactDOMComponentTree = require('react-dom-bindings/src/client/ReactDOMComponentTree');
|
||||
|
||||
class ChildComponent extends React.Component {
|
||||
divRef = React.createRef();
|
||||
div1Ref = React.createRef();
|
||||
div2Ref = React.createRef();
|
||||
class ChildComponent extends React.Component {
|
||||
divRef = React.createRef();
|
||||
div1Ref = React.createRef();
|
||||
div2Ref = React.createRef();
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div ref={this.divRef} id={this.props.id + '__DIV'}>
|
||||
<div ref={this.div1Ref} id={this.props.id + '__DIV_1'} />
|
||||
<div ref={this.div2Ref} id={this.props.id + '__DIV_2'} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class ParentComponent extends React.Component {
|
||||
pRef = React.createRef();
|
||||
p_P1Ref = React.createRef();
|
||||
p_P1_C1Ref = React.createRef();
|
||||
p_P1_C2Ref = React.createRef();
|
||||
p_OneOffRef = React.createRef();
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div ref={this.pRef} id="P">
|
||||
<div ref={this.p_P1Ref} id="P_P1">
|
||||
<ChildComponent ref={this.p_P1_C1Ref} id="P_P1_C1" />
|
||||
<ChildComponent ref={this.p_P1_C2Ref} id="P_P1_C2" />
|
||||
render() {
|
||||
return (
|
||||
<div ref={this.divRef} id={this.props.id + '__DIV'}>
|
||||
<div ref={this.div1Ref} id={this.props.id + '__DIV_1'} />
|
||||
<div ref={this.div2Ref} id={this.props.id + '__DIV_2'} />
|
||||
</div>
|
||||
<div ref={this.p_OneOffRef} id="P_OneOff" />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class ParentComponent extends React.Component {
|
||||
pRef = React.createRef();
|
||||
p_P1Ref = React.createRef();
|
||||
p_P1_C1Ref = React.createRef();
|
||||
p_P1_C2Ref = React.createRef();
|
||||
p_OneOffRef = React.createRef();
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div ref={this.pRef} id="P">
|
||||
<div ref={this.p_P1Ref} id="P_P1">
|
||||
<ChildComponent ref={this.p_P1_C1Ref} id="P_P1_C1" />
|
||||
<ChildComponent ref={this.p_P1_C2Ref} id="P_P1_C2" />
|
||||
</div>
|
||||
<div ref={this.p_OneOffRef} id="P_OneOff" />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const container = document.createElement('div');
|
||||
const root = ReactDOMClient.createRoot(container);
|
||||
let parent;
|
||||
await act(() => {
|
||||
root.render(<ParentComponent ref={current => (parent = current)} />);
|
||||
});
|
||||
|
||||
const ancestors = [
|
||||
// Common ancestor with self is self.
|
||||
{
|
||||
one: parent.p_P1_C1Ref.current.div1Ref.current,
|
||||
two: parent.p_P1_C1Ref.current.div1Ref.current,
|
||||
com: parent.p_P1_C1Ref.current.div1Ref.current,
|
||||
},
|
||||
// Common ancestor with self is self - even if topmost DOM.
|
||||
{
|
||||
one: parent.pRef.current,
|
||||
two: parent.pRef.current,
|
||||
com: parent.pRef.current,
|
||||
},
|
||||
// Siblings
|
||||
{
|
||||
one: parent.p_P1_C1Ref.current.div1Ref.current,
|
||||
two: parent.p_P1_C1Ref.current.div2Ref.current,
|
||||
com: parent.p_P1_C1Ref.current.divRef.current,
|
||||
},
|
||||
// Common ancestor with parent is the parent.
|
||||
{
|
||||
one: parent.p_P1_C1Ref.current.div1Ref.current,
|
||||
two: parent.p_P1_C1Ref.current.divRef.current,
|
||||
com: parent.p_P1_C1Ref.current.divRef.current,
|
||||
},
|
||||
// Common ancestor with grandparent is the grandparent.
|
||||
{
|
||||
one: parent.p_P1_C1Ref.current.div1Ref.current,
|
||||
two: parent.p_P1Ref.current,
|
||||
com: parent.p_P1Ref.current,
|
||||
},
|
||||
// Grandparent across subcomponent boundaries.
|
||||
{
|
||||
one: parent.p_P1_C1Ref.current.div1Ref.current,
|
||||
two: parent.p_P1_C2Ref.current.div1Ref.current,
|
||||
com: parent.p_P1Ref.current,
|
||||
},
|
||||
// Something deep with something one-off.
|
||||
{
|
||||
one: parent.p_P1_C1Ref.current.div1Ref.current,
|
||||
two: parent.p_OneOffRef.current,
|
||||
com: parent.pRef.current,
|
||||
},
|
||||
];
|
||||
let i;
|
||||
for (i = 0; i < ancestors.length; i++) {
|
||||
const plan = ancestors[i];
|
||||
const firstCommon = getLowestCommonAncestor(
|
||||
ReactDOMComponentTree.getInstanceFromNode(plan.one),
|
||||
ReactDOMComponentTree.getInstanceFromNode(plan.two),
|
||||
);
|
||||
expect(firstCommon).toBe(
|
||||
ReactDOMComponentTree.getInstanceFromNode(plan.com),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const container = document.createElement('div');
|
||||
const root = ReactDOMClient.createRoot(container);
|
||||
let parent;
|
||||
await act(() => {
|
||||
root.render(<ParentComponent ref={current => (parent = current)} />);
|
||||
});
|
||||
|
||||
const ancestors = [
|
||||
// Common ancestor with self is self.
|
||||
{
|
||||
one: parent.p_P1_C1Ref.current.div1Ref.current,
|
||||
two: parent.p_P1_C1Ref.current.div1Ref.current,
|
||||
com: parent.p_P1_C1Ref.current.div1Ref.current,
|
||||
},
|
||||
// Common ancestor with self is self - even if topmost DOM.
|
||||
{
|
||||
one: parent.pRef.current,
|
||||
two: parent.pRef.current,
|
||||
com: parent.pRef.current,
|
||||
},
|
||||
// Siblings
|
||||
{
|
||||
one: parent.p_P1_C1Ref.current.div1Ref.current,
|
||||
two: parent.p_P1_C1Ref.current.div2Ref.current,
|
||||
com: parent.p_P1_C1Ref.current.divRef.current,
|
||||
},
|
||||
// Common ancestor with parent is the parent.
|
||||
{
|
||||
one: parent.p_P1_C1Ref.current.div1Ref.current,
|
||||
two: parent.p_P1_C1Ref.current.divRef.current,
|
||||
com: parent.p_P1_C1Ref.current.divRef.current,
|
||||
},
|
||||
// Common ancestor with grandparent is the grandparent.
|
||||
{
|
||||
one: parent.p_P1_C1Ref.current.div1Ref.current,
|
||||
two: parent.p_P1Ref.current,
|
||||
com: parent.p_P1Ref.current,
|
||||
},
|
||||
// Grandparent across subcomponent boundaries.
|
||||
{
|
||||
one: parent.p_P1_C1Ref.current.div1Ref.current,
|
||||
two: parent.p_P1_C2Ref.current.div1Ref.current,
|
||||
com: parent.p_P1Ref.current,
|
||||
},
|
||||
// Something deep with something one-off.
|
||||
{
|
||||
one: parent.p_P1_C1Ref.current.div1Ref.current,
|
||||
two: parent.p_OneOffRef.current,
|
||||
com: parent.pRef.current,
|
||||
},
|
||||
];
|
||||
let i;
|
||||
for (i = 0; i < ancestors.length; i++) {
|
||||
const plan = ancestors[i];
|
||||
const firstCommon = getLowestCommonAncestor(
|
||||
ReactDOMComponentTree.getInstanceFromNode(plan.one),
|
||||
ReactDOMComponentTree.getInstanceFromNode(plan.two),
|
||||
);
|
||||
expect(firstCommon).toBe(
|
||||
ReactDOMComponentTree.getInstanceFromNode(plan.com),
|
||||
);
|
||||
}
|
||||
});
|
||||
},
|
||||
// TODO: this is a long running test, we should speed it up.
|
||||
60 * 1000,
|
||||
);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -118,7 +118,7 @@ describe('Activity', () => {
|
|||
);
|
||||
});
|
||||
|
||||
// @gate www && !disableLegacyMode
|
||||
// @gate enableLegacyHidden && !disableLegacyMode
|
||||
it('does not defer in legacy mode', async () => {
|
||||
let setState;
|
||||
function Foo() {
|
||||
|
|
@ -163,7 +163,7 @@ describe('Activity', () => {
|
|||
);
|
||||
});
|
||||
|
||||
// @gate www
|
||||
// @gate enableLegacyHidden
|
||||
it('does defer in concurrent mode', async () => {
|
||||
let setState;
|
||||
function Foo() {
|
||||
|
|
|
|||
|
|
@ -140,7 +140,7 @@ describe('Activity Suspense', () => {
|
|||
);
|
||||
});
|
||||
|
||||
// @gate www
|
||||
// @gate enableLegacyHidden
|
||||
test('LegacyHidden does not handle suspense', async () => {
|
||||
const root = ReactNoop.createRoot();
|
||||
|
||||
|
|
@ -174,7 +174,7 @@ describe('Activity Suspense', () => {
|
|||
);
|
||||
});
|
||||
|
||||
// @gate experimental || www
|
||||
// @gate enableActivity
|
||||
test("suspending inside currently hidden tree that's switching to visible", async () => {
|
||||
const root = ReactNoop.createRoot();
|
||||
|
||||
|
|
@ -319,7 +319,7 @@ describe('Activity Suspense', () => {
|
|||
);
|
||||
});
|
||||
|
||||
// @gate experimental || www
|
||||
// @gate enableActivity
|
||||
test('update that suspends inside hidden tree', async () => {
|
||||
let setText;
|
||||
function Child() {
|
||||
|
|
@ -352,7 +352,7 @@ describe('Activity Suspense', () => {
|
|||
});
|
||||
});
|
||||
|
||||
// @gate experimental || www
|
||||
// @gate enableActivity
|
||||
test('updates at multiple priorities that suspend inside hidden tree', async () => {
|
||||
let setText;
|
||||
let setStep;
|
||||
|
|
|
|||
|
|
@ -550,7 +550,7 @@ describe('ReactLazyContextPropagation', () => {
|
|||
expect(root).toMatchRenderedOutput('BB');
|
||||
});
|
||||
|
||||
// @gate www
|
||||
// @gate enableLegacyCache && enableLegacyHidden
|
||||
test('context is propagated through offscreen trees', async () => {
|
||||
const LegacyHidden = React.unstable_LegacyHidden;
|
||||
|
||||
|
|
@ -596,7 +596,7 @@ describe('ReactLazyContextPropagation', () => {
|
|||
expect(root).toMatchRenderedOutput('BB');
|
||||
});
|
||||
|
||||
// @gate www
|
||||
// @gate enableLegacyCache && enableLegacyHidden
|
||||
test('multiple contexts are propagated across through offscreen trees', async () => {
|
||||
// Same as previous test, but with multiple context providers
|
||||
const LegacyHidden = React.unstable_LegacyHidden;
|
||||
|
|
@ -822,7 +822,7 @@ describe('ReactLazyContextPropagation', () => {
|
|||
expect(root).toMatchRenderedOutput('BB');
|
||||
});
|
||||
|
||||
// @gate www
|
||||
// @gate enableLegacyCache && enableLegacyHidden
|
||||
test('nested bailouts through offscreen trees', async () => {
|
||||
// Lazy context propagation will stop propagating when it hits the first
|
||||
// match. If we bail out again inside that tree, we must resume propagating.
|
||||
|
|
|
|||
|
|
@ -239,7 +239,7 @@ describe('ReactIncremental', () => {
|
|||
expect(inst.state).toEqual({text: 'bar', text2: 'baz'});
|
||||
});
|
||||
|
||||
// @gate www
|
||||
// @gate enableLegacyHidden
|
||||
it('can deprioritize unfinished work and resume it later', async () => {
|
||||
function Bar(props) {
|
||||
Scheduler.log('Bar');
|
||||
|
|
@ -279,7 +279,7 @@ describe('ReactIncremental', () => {
|
|||
await waitForAll(['Middle', 'Middle']);
|
||||
});
|
||||
|
||||
// @gate www
|
||||
// @gate enableLegacyHidden
|
||||
it('can deprioritize a tree from without dropping work', async () => {
|
||||
function Bar(props) {
|
||||
Scheduler.log('Bar');
|
||||
|
|
@ -1864,8 +1864,7 @@ describe('ReactIncremental', () => {
|
|||
]);
|
||||
});
|
||||
|
||||
// @gate www
|
||||
// @gate !disableLegacyContext
|
||||
// @gate enableLegacyHidden && !disableLegacyContext
|
||||
it('provides context when reusing work', async () => {
|
||||
class Intl extends React.Component {
|
||||
static childContextTypes = {
|
||||
|
|
|
|||
|
|
@ -289,7 +289,7 @@ describe('ReactIncrementalErrorHandling', () => {
|
|||
);
|
||||
});
|
||||
|
||||
// @gate www
|
||||
// @gate enableLegacyHidden
|
||||
it('does not include offscreen work when retrying after an error', async () => {
|
||||
function App(props) {
|
||||
if (props.isBroken) {
|
||||
|
|
|
|||
|
|
@ -481,7 +481,7 @@ describe('ReactIncrementalSideEffects', () => {
|
|||
);
|
||||
});
|
||||
|
||||
// @gate www
|
||||
// @gate enableLegacyHidden
|
||||
it('preserves a previously rendered node when deprioritized', async () => {
|
||||
function Middle(props) {
|
||||
Scheduler.log('Middle');
|
||||
|
|
@ -530,7 +530,7 @@ describe('ReactIncrementalSideEffects', () => {
|
|||
);
|
||||
});
|
||||
|
||||
// @gate www
|
||||
// @gate enableLegacyHidden
|
||||
it('can reuse side-effects after being preempted', async () => {
|
||||
function Bar(props) {
|
||||
Scheduler.log('Bar');
|
||||
|
|
@ -610,7 +610,7 @@ describe('ReactIncrementalSideEffects', () => {
|
|||
);
|
||||
});
|
||||
|
||||
// @gate www
|
||||
// @gate enableLegacyHidden
|
||||
it('can reuse side-effects after being preempted, if shouldComponentUpdate is false', async () => {
|
||||
class Bar extends React.Component {
|
||||
shouldComponentUpdate(nextProps) {
|
||||
|
|
@ -733,7 +733,7 @@ describe('ReactIncrementalSideEffects', () => {
|
|||
expect(ReactNoop.getChildrenAsJSX()).toEqual(<span prop={3} />);
|
||||
});
|
||||
|
||||
// @gate www
|
||||
// @gate enableLegacyHidden
|
||||
it('updates a child even though the old props is empty', async () => {
|
||||
function Foo(props) {
|
||||
return (
|
||||
|
|
@ -984,7 +984,7 @@ describe('ReactIncrementalSideEffects', () => {
|
|||
expect(ops).toEqual(['Bar', 'Baz', 'Bar', 'Bar']);
|
||||
});
|
||||
|
||||
// @gate www
|
||||
// @gate enableLegacyHidden
|
||||
it('deprioritizes setStates that happens within a deprioritized tree', async () => {
|
||||
const barInstances = [];
|
||||
|
||||
|
|
|
|||
|
|
@ -699,7 +699,7 @@ describe('ReactNewContext', () => {
|
|||
);
|
||||
});
|
||||
|
||||
// @gate www
|
||||
// @gate enableLegacyHidden
|
||||
it("context consumer doesn't bail out inside hidden subtree", async () => {
|
||||
const Context = React.createContext('dark');
|
||||
const Consumer = getConsumer(Context);
|
||||
|
|
|
|||
|
|
@ -131,7 +131,7 @@ describe('ReactSchedulerIntegration', () => {
|
|||
await waitForAll(['D', 'E']);
|
||||
});
|
||||
|
||||
// @gate www
|
||||
// @gate enableLegacyHidden
|
||||
it('idle updates are not blocked by offscreen work', async () => {
|
||||
function Text({text}) {
|
||||
Scheduler.log(text);
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ describe('ReactScope', () => {
|
|||
container = null;
|
||||
});
|
||||
|
||||
// @gate www
|
||||
// @gate enableScopeAPI
|
||||
it('DO_NOT_USE_queryAllNodes() works as intended', async () => {
|
||||
const testScopeQuery = (type, props) => true;
|
||||
const TestScope = React.unstable_Scope;
|
||||
|
|
@ -86,7 +86,7 @@ describe('ReactScope', () => {
|
|||
expect(scopeRef.current).toBe(null);
|
||||
});
|
||||
|
||||
// @gate www
|
||||
// @gate enableScopeAPI
|
||||
it('DO_NOT_USE_queryAllNodes() provides the correct host instance', async () => {
|
||||
const testScopeQuery = (type, props) => type === 'div';
|
||||
const TestScope = React.unstable_Scope;
|
||||
|
|
@ -143,7 +143,7 @@ describe('ReactScope', () => {
|
|||
expect(scopeRef.current).toBe(null);
|
||||
});
|
||||
|
||||
// @gate www
|
||||
// @gate enableScopeAPI
|
||||
it('DO_NOT_USE_queryFirstNode() works as intended', async () => {
|
||||
const testScopeQuery = (type, props) => true;
|
||||
const TestScope = React.unstable_Scope;
|
||||
|
|
@ -188,7 +188,7 @@ describe('ReactScope', () => {
|
|||
expect(scopeRef.current).toBe(null);
|
||||
});
|
||||
|
||||
// @gate www
|
||||
// @gate enableScopeAPI
|
||||
it('containsNode() works as intended', async () => {
|
||||
const TestScope = React.unstable_Scope;
|
||||
const scopeRef = React.createRef();
|
||||
|
|
@ -248,7 +248,7 @@ describe('ReactScope', () => {
|
|||
expect(scopeRef.current.containsNode(emRef.current)).toBe(false);
|
||||
});
|
||||
|
||||
// @gate www
|
||||
// @gate enableScopeAPI
|
||||
it('scopes support server-side rendering and hydration', async () => {
|
||||
const TestScope = React.unstable_Scope;
|
||||
const scopeRef = React.createRef();
|
||||
|
|
@ -281,7 +281,7 @@ describe('ReactScope', () => {
|
|||
expect(nodes).toEqual([divRef.current, spanRef.current, aRef.current]);
|
||||
});
|
||||
|
||||
// @gate www
|
||||
// @gate enableScopeAPI
|
||||
it('getChildContextValues() works as intended', async () => {
|
||||
const TestContext = React.createContext();
|
||||
const TestScope = React.unstable_Scope;
|
||||
|
|
@ -320,7 +320,7 @@ describe('ReactScope', () => {
|
|||
expect(scopeRef.current).toBe(null);
|
||||
});
|
||||
|
||||
// @gate www
|
||||
// @gate enableScopeAPI
|
||||
it('correctly works with suspended boundaries that are hydrated', async () => {
|
||||
let suspend = false;
|
||||
let resolve;
|
||||
|
|
@ -392,7 +392,7 @@ describe('ReactScope', () => {
|
|||
ReactTestRenderer = require('react-test-renderer');
|
||||
});
|
||||
|
||||
// @gate www
|
||||
// @gate enableScopeAPI
|
||||
it('DO_NOT_USE_queryAllNodes() works as intended', async () => {
|
||||
const testScopeQuery = (type, props) => true;
|
||||
const TestScope = React.unstable_Scope;
|
||||
|
|
@ -434,7 +434,7 @@ describe('ReactScope', () => {
|
|||
expect(nodes).toEqual([aRef.current, divRef.current, spanRef.current]);
|
||||
});
|
||||
|
||||
// @gate www
|
||||
// @gate enableScopeAPI
|
||||
it('DO_NOT_USE_queryFirstNode() works as intended', async () => {
|
||||
const testScopeQuery = (type, props) => true;
|
||||
const TestScope = React.unstable_Scope;
|
||||
|
|
@ -477,7 +477,7 @@ describe('ReactScope', () => {
|
|||
expect(node).toEqual(aRef.current);
|
||||
});
|
||||
|
||||
// @gate www
|
||||
// @gate enableScopeAPI
|
||||
it('containsNode() works as intended', async () => {
|
||||
const TestScope = React.unstable_Scope;
|
||||
const scopeRef = React.createRef();
|
||||
|
|
|
|||
|
|
@ -130,7 +130,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
|
|||
|
||||
const resolveText = resolveMostRecentTextCache;
|
||||
|
||||
// @gate www && !disableLegacyMode
|
||||
// @gate enableLegacyCache && !disableLegacyMode
|
||||
it('regression: false positive for legacy suspense', async () => {
|
||||
const Child = ({text}) => {
|
||||
// If text hasn't resolved, this will throw and exit before the passive
|
||||
|
|
|
|||
|
|
@ -2441,7 +2441,7 @@ describe('ReactFresh', () => {
|
|||
}
|
||||
});
|
||||
|
||||
// @gate www && __DEV__
|
||||
// @gate enableLegacyHidden && __DEV__
|
||||
it('can hot reload offscreen components', async () => {
|
||||
const AppV1 = prepare(() => {
|
||||
function Hello() {
|
||||
|
|
|
|||
|
|
@ -170,6 +170,17 @@ describe(`onRender`, () => {
|
|||
'read current time',
|
||||
'read current time',
|
||||
]);
|
||||
} else if (gate(flags => !flags.allowConcurrentByDefault)) {
|
||||
assertLog([
|
||||
'read current time',
|
||||
'read current time',
|
||||
'read current time',
|
||||
'read current time',
|
||||
'read current time',
|
||||
'read current time',
|
||||
'read current time',
|
||||
// TODO: why is there one less in this case?
|
||||
]);
|
||||
} else {
|
||||
assertLog([
|
||||
'read current time',
|
||||
|
|
|
|||
|
|
@ -60,6 +60,7 @@ function getTestFlags() {
|
|||
const schedulerFeatureFlags = require('scheduler/src/SchedulerFeatureFlags');
|
||||
|
||||
const www = global.__WWW__ === true;
|
||||
const xplat = global.__XPLAT__ === true;
|
||||
const releaseChannel = www
|
||||
? __EXPERIMENTAL__
|
||||
? 'modern'
|
||||
|
|
@ -79,8 +80,8 @@ function getTestFlags() {
|
|||
www,
|
||||
|
||||
// These aren't flags, just a useful aliases for tests.
|
||||
enableActivity: releaseChannel === 'experimental' || www,
|
||||
enableSuspenseList: releaseChannel === 'experimental' || www,
|
||||
enableActivity: releaseChannel === 'experimental' || www || xplat,
|
||||
enableSuspenseList: releaseChannel === 'experimental' || www || xplat,
|
||||
enableLegacyHidden: www,
|
||||
|
||||
// This flag is used to determine whether we should run Fizz tests using
|
||||
|
|
|
|||
30
scripts/jest/config.source-xplat.js
Normal file
30
scripts/jest/config.source-xplat.js
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
'use strict';
|
||||
|
||||
const baseConfig = require('./config.base');
|
||||
|
||||
module.exports = Object.assign({}, baseConfig, {
|
||||
modulePathIgnorePatterns: [
|
||||
...baseConfig.modulePathIgnorePatterns,
|
||||
'packages/react-devtools-extensions',
|
||||
'packages/react-devtools-shared',
|
||||
'ReactIncrementalPerf',
|
||||
'ReactIncrementalUpdatesMinimalism',
|
||||
'ReactIncrementalTriangle',
|
||||
'ReactIncrementalReflection',
|
||||
'forwardRef',
|
||||
],
|
||||
// RN configs should not run react-dom tests.
|
||||
// There are many other tests that use react-dom
|
||||
// and for those we will use the www entrypoint,
|
||||
// but those tests should be migrated to Noop renderer.
|
||||
testPathIgnorePatterns: [
|
||||
'node_modules',
|
||||
'packages/react-dom',
|
||||
'packages/react-server-dom-webpack',
|
||||
],
|
||||
setupFiles: [
|
||||
...baseConfig.setupFiles,
|
||||
require.resolve('./setupTests.xplat.js'),
|
||||
require.resolve('./setupHostConfigs.js'),
|
||||
],
|
||||
});
|
||||
|
|
@ -9,6 +9,7 @@ const semver = require('semver');
|
|||
|
||||
const ossConfig = './scripts/jest/config.source.js';
|
||||
const wwwConfig = './scripts/jest/config.source-www.js';
|
||||
const xplatConfig = './scripts/jest/config.source-xplat.js';
|
||||
const devToolsConfig = './scripts/jest/config.build-devtools.js';
|
||||
|
||||
// TODO: These configs are separate but should be rolled into the configs above
|
||||
|
|
@ -46,7 +47,7 @@ const argv = yargs
|
|||
requiresArg: true,
|
||||
type: 'string',
|
||||
default: 'experimental',
|
||||
choices: ['experimental', 'stable', 'www-classic', 'www-modern'],
|
||||
choices: ['experimental', 'stable', 'www-classic', 'www-modern', 'xplat'],
|
||||
},
|
||||
env: {
|
||||
alias: 'e',
|
||||
|
|
@ -124,6 +125,10 @@ function isWWWConfig() {
|
|||
);
|
||||
}
|
||||
|
||||
function isXplatConfig() {
|
||||
return argv.releaseChannel === 'xplat' && argv.project !== 'devtools';
|
||||
}
|
||||
|
||||
function isOSSConfig() {
|
||||
return (
|
||||
argv.releaseChannel === 'stable' || argv.releaseChannel === 'experimental'
|
||||
|
|
@ -189,7 +194,7 @@ function validateOptions() {
|
|||
}
|
||||
}
|
||||
|
||||
if (isWWWConfig()) {
|
||||
if (isWWWConfig() || isXplatConfig()) {
|
||||
if (argv.variant === undefined) {
|
||||
// Turn internal experiments on by default
|
||||
argv.variant = true;
|
||||
|
|
@ -224,6 +229,13 @@ function validateOptions() {
|
|||
success = false;
|
||||
}
|
||||
|
||||
if (argv.build && isXplatConfig()) {
|
||||
logError(
|
||||
'Build targets are only not supported for xplat release channels. Update these options to continue.'
|
||||
);
|
||||
success = false;
|
||||
}
|
||||
|
||||
if (argv.env && argv.env !== 'production' && argv.prod) {
|
||||
logError(
|
||||
'Build type does not match --prod. Update these options to continue.'
|
||||
|
|
@ -277,6 +289,8 @@ function getCommandArgs() {
|
|||
args.push(persistentConfig);
|
||||
} else if (isWWWConfig()) {
|
||||
args.push(wwwConfig);
|
||||
} else if (isXplatConfig()) {
|
||||
args.push(xplatConfig);
|
||||
} else if (isOSSConfig()) {
|
||||
args.push(ossConfig);
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -77,7 +77,7 @@ function mockReact() {
|
|||
jest.mock('react', () => {
|
||||
const resolvedEntryPoint = resolveEntryFork(
|
||||
require.resolve('react'),
|
||||
global.__WWW__
|
||||
global.__WWW__ || global.__XPLAT__
|
||||
);
|
||||
return jest.requireActual(resolvedEntryPoint);
|
||||
});
|
||||
|
|
@ -100,7 +100,7 @@ jest.mock('react/react.react-server', () => {
|
|||
});
|
||||
const resolvedEntryPoint = resolveEntryFork(
|
||||
require.resolve('react/src/ReactServer'),
|
||||
global.__WWW__
|
||||
global.__WWW__ || global.__XPLAT__
|
||||
);
|
||||
return jest.requireActual(resolvedEntryPoint);
|
||||
});
|
||||
|
|
@ -198,7 +198,7 @@ inlinedHostConfigs.forEach(rendererInfo => {
|
|||
mockAllConfigs(rendererInfo);
|
||||
const resolvedEntryPoint = resolveEntryFork(
|
||||
require.resolve(entryPoint),
|
||||
global.__WWW__
|
||||
global.__WWW__ || global.__XPLAT__
|
||||
);
|
||||
return jest.requireActual(resolvedEntryPoint);
|
||||
});
|
||||
|
|
|
|||
33
scripts/jest/setupTests.xplat.js
Normal file
33
scripts/jest/setupTests.xplat.js
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
'use strict';
|
||||
|
||||
jest.mock('shared/ReactFeatureFlags', () => {
|
||||
jest.mock(
|
||||
'ReactNativeInternalFeatureFlags',
|
||||
() =>
|
||||
jest.requireActual('shared/forks/ReactFeatureFlags.native-fb-dynamic.js'),
|
||||
{virtual: true}
|
||||
);
|
||||
const actual = jest.requireActual(
|
||||
'shared/forks/ReactFeatureFlags.native-fb.js'
|
||||
);
|
||||
|
||||
// Lots of tests use these, but we don't want to expose it to RN.
|
||||
// Ideally, tests for xplat wouldn't use react-dom, but many of our tests do.
|
||||
// Since the xplat tests run with the www entry points, some of these flags
|
||||
// need to be set to the www value for the entrypoint, otherwise gating would
|
||||
// fail due to the tests passing. Ideally, the www entry points for these APIs
|
||||
// would be gated, and then these would fail correctly.
|
||||
actual.enableLegacyCache = true;
|
||||
actual.enableLegacyHidden = true;
|
||||
actual.enableScopeAPI = true;
|
||||
actual.enableTaint = false;
|
||||
|
||||
return actual;
|
||||
});
|
||||
|
||||
jest.mock('react-noop-renderer', () =>
|
||||
jest.requireActual('react-noop-renderer/persistent')
|
||||
);
|
||||
|
||||
global.__PERSISTENT__ = true;
|
||||
global.__XPLAT__ = true;
|
||||
Loading…
Reference in New Issue
Block a user