Skip to content

Commit

Permalink
Use testing builds for our own tests
Browse files Browse the repository at this point in the history
Following up from facebook#17915 where we generated testing builds for `react-dom`, this PR uses those builds for our own tests.

- fixes `ReactFeatureFlags.testing` to use all the default flags
- changes `ReactFeatureFlags.readonly` to return `isTestEnvironment: true` (this might not strictly be needed)
- with jest, mocks `react-dom` with the testing version, both for source and builds
- uses `ReactDOM.act` in one of these tests to verify it actually works
  • Loading branch information
threepointone committed Feb 7, 2020
1 parent 256d78d commit e25d4e1
Show file tree
Hide file tree
Showing 16 changed files with 263 additions and 44 deletions.
5 changes: 1 addition & 4 deletions fixtures/dom/src/__tests__/nested-act-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,7 @@ let TestRenderer;

global.__DEV__ = process.env.NODE_ENV !== 'production';

jest.mock('react-dom', () =>
require.requireActual('react-dom/cjs/react-dom-testing.development.js')
);
// we'll replace the above with react/testing and react-dom/testing right before the next minor
jest.mock('react-dom', () => require.requireActual('react-dom/testing'));

expect.extend(require('../toWarnDev'));

Expand Down
5 changes: 1 addition & 4 deletions fixtures/dom/src/__tests__/wrong-act-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,7 @@ let ARTTest;
global.__DEV__ = process.env.NODE_ENV !== 'production';
global.__EXPERIMENTAL__ = process.env.RELEASE_CHANNEL === 'experimental';

jest.mock('react-dom', () =>
require.requireActual('react-dom/cjs/react-dom-testing.development.js')
);
// we'll replace the above with react/testing and react-dom/testing right before the next minor
jest.mock('react-dom', () => require.requireActual('react-dom/testing'));

expect.extend(require('../toWarnDev'));

Expand Down
1 change: 1 addition & 0 deletions packages/react-dom/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
"README.md",
"build-info.json",
"index.js",
"testing.js",
"profiling.js",
"server.js",
"server.browser.js",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ let React;
let ReactDOM;
let Suspense;
let ReactCache;
let ReactTestUtils;
let Scheduler;
let TextResource;
let act;
Expand All @@ -26,9 +25,8 @@ describe('ReactDOMSuspensePlaceholder', () => {
React = require('react');
ReactDOM = require('react-dom');
ReactCache = require('react-cache');
ReactTestUtils = require('react-dom/test-utils');
Scheduler = require('scheduler');
act = ReactTestUtils.act;
act = ReactDOM.act;
Suspense = React.Suspense;
container = document.createElement('div');
document.body.appendChild(container);
Expand Down
14 changes: 14 additions & 0 deletions packages/react-dom/testing.fb.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

'use strict';

const ReactDOMFB = require('./src/client/ReactDOMFB');

// TODO: decide on the top-level export form.
// This is hacky but makes it work with both Rollup and Jest.
module.exports = ReactDOMFB.default || ReactDOMFB;
5 changes: 5 additions & 0 deletions packages/shared/ReactFeatureFlags.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@
* @flow strict
*/

/*
SYNC WITH forks/ReactFeatureFlags.testing.js
except isTestEnvironment = true
*/

export const enableUserTimingAPI = __DEV__;

// Helps identify side effects in render-phase lifecycle hooks and setState
Expand Down
2 changes: 1 addition & 1 deletion packages/shared/forks/ReactFeatureFlags.readonly.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,4 @@
// It lets us determine whether we're running in Fire mode without making tests internal.
const ReactFeatureFlags = require('../ReactFeatureFlags');
// Forbid writes because this wouldn't work with bundle tests.
module.exports = Object.freeze({...ReactFeatureFlags});
module.exports = Object.freeze({...ReactFeatureFlags, isTestEnvironment: true});
2 changes: 1 addition & 1 deletion packages/shared/forks/ReactFeatureFlags.test-renderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ export const disableUnstableRenderSubtreeIntoContainer = false;
export const warnUnstableRenderSubtreeIntoContainer = false;
export const disableUnstableCreatePortal = false;
export const deferPassiveEffectCleanupDuringUnmount = false;
export const isTestEnvironment = true; // this should probably *never* change
export const isTestEnvironment = true;

// Only used in www builds.
export function addUserTimingListener() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ export const disableUnstableRenderSubtreeIntoContainer = false;
export const warnUnstableRenderSubtreeIntoContainer = false;
export const disableUnstableCreatePortal = false;
export const deferPassiveEffectCleanupDuringUnmount = false;
export const isTestEnvironment = true; // this should probably *never* change
export const isTestEnvironment = true;

// Only used in www builds.
export function addUserTimingListener() {
Expand Down
127 changes: 100 additions & 27 deletions packages/shared/forks/ReactFeatureFlags.testing.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,58 +4,131 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow
* @flow strict
*/

import invariant from 'shared/invariant';
/*
SYNC WITH ReactFeatureFlags.js
except isTestEnvironment = true
*/

import typeof * as FeatureFlagsType from 'shared/ReactFeatureFlags';
import typeof * as PersistentFeatureFlagsType from './ReactFeatureFlags.persistent';

export const debugRenderPhaseSideEffectsForStrictMode = false;
export const enableUserTimingAPI = __DEV__;

// Helps identify side effects in render-phase lifecycle hooks and setState
// reducers by double invoking them in Strict Mode.
export const debugRenderPhaseSideEffectsForStrictMode = __DEV__;

// To preserve the "Pause on caught exceptions" behavior of the debugger, we
// replay the begin phase of a failed component inside invokeGuardedCallback.
export const replayFailedUnitOfWorkWithInvokeGuardedCallback = __DEV__;

// Warn about deprecated, async-unsafe lifecycles; relates to RFC #6:
export const warnAboutDeprecatedLifecycles = true;
export const replayFailedUnitOfWorkWithInvokeGuardedCallback = false;

// Gather advanced timing metrics for Profiler subtrees.
export const enableProfilerTimer = __PROFILE__;

// Trace which interactions trigger each commit.
export const enableSchedulerTracing = __PROFILE__;
export const enableSuspenseServerRenderer = false;
export const enableSelectiveHydration = false;
export const enableChunksAPI = false;

// SSR experiments
export const enableSuspenseServerRenderer = __EXPERIMENTAL__;
export const enableSelectiveHydration = __EXPERIMENTAL__;

// Flight experiments
export const enableChunksAPI = __EXPERIMENTAL__;

// Only used in www builds.
export const enableSchedulerDebugging = false;

// Only used in www builds.
export function addUserTimingListener() {
throw new Error('Not implemented.');
}

// Disable javascript: URL strings in href for XSS protection.
export const disableJavaScriptURLs = false;
export const disableInputAttributeSyncing = false;

// These APIs will no longer be "unstable" in the upcoming 16.7 release,
// Control this behavior with a flag to support 16.6 minor releases in the meanwhile.
export const exposeConcurrentModeAPIs = __EXPERIMENTAL__;

export const warnAboutShorthandPropertyCollision = false;
export const enableSchedulerDebugging = false;

// Experimental React Flare event system and event components support.
export const enableDeprecatedFlareAPI = false;

// Experimental Host Component support.
export const enableFundamentalAPI = false;

// Experimental Scope support.
export const enableScopeAPI = false;

// New API for JSX transforms to target - https://github.com/reactjs/rfcs/pull/107
export const enableJSXTransformAPI = false;

// We will enforce mocking scheduler with scheduler/unstable_mock at some point. (v17?)
// Till then, we warn about the missing mock, but still fallback to a legacy mode compatible version
export const warnAboutUnmockedScheduler = false;

// For tests, we flush suspense fallbacks in an act scope;
// *except* in some of our own tests, where we test incremental loading states.
export const flushSuspenseFallbacksInTests = true;

// Add a callback property to suspense to notify which promises are currently
// in the update queue. This allows reporting and tracing of what is causing
// the user to see a loading state.
// Also allows hydration callbacks to fire when a dehydrated boundary gets
// hydrated or deleted.
export const enableSuspenseCallback = false;

// Part of the simplification of React.createElement so we can eventually move
// from React.createElement to React.jsx
// https://github.com/reactjs/rfcs/blob/createlement-rfc/text/0000-create-element-changes.md
export const warnAboutDefaultPropsOnFunctionComponents = false;
export const warnAboutStringRefs = false;
export const disableLegacyContext = false;

export const disableSchedulerTimeoutBasedOnReactExpirationTime = false;

export const enableTrainModelFix = true;

export const enableTrustedTypesIntegration = false;

// Flag to turn event.target and event.currentTarget in ReactNative from a reactTag to a component instance
export const enableNativeTargetAsInstance = false;

// Controls behavior of deferred effect destroy functions during unmount.
// Previously these functions were run during commit (along with layout effects).
// Ideally we should delay these until after commit for performance reasons.
// This flag provides a killswitch if that proves to break existing code somehow.
export const deferPassiveEffectCleanupDuringUnmount = false;

export const isTestEnvironment = true;

// --------------------------
// Future APIs to be deprecated
// --------------------------

// Prevent the value and checked attributes from syncing
// with their related DOM properties
export const disableInputAttributeSyncing = false;

export const warnAboutStringRefs = false;

export const disableLegacyContext = false;

// Disables React.createFactory
export const disableCreateFactory = false;

// Disables children for <textarea> elements
export const disableTextareaChildren = false;

// Disables Maps as ReactElement children
export const disableMapsAsChildren = false;

// Disables ReactDOM.unstable_renderSubtreeIntoContainer
export const disableUnstableRenderSubtreeIntoContainer = false;
// We should remove this flag once the above flag becomes enabled
export const warnUnstableRenderSubtreeIntoContainer = false;
export const disableUnstableCreatePortal = false;
export const deferPassiveEffectCleanupDuringUnmount = false;
export const isTestEnvironment = true;

// Only used in www builds.
export function addUserTimingListener() {
invariant(false, 'Not implemented.');
}

// Flow magic to verify the exports of this file match the original version.
// eslint-disable-next-line no-unused-vars
type Check<_X, Y: _X, X: Y = _X> = null;
// eslint-disable-next-line no-unused-expressions
(null: Check<PersistentFeatureFlagsType, FeatureFlagsType>);
// Disables ReactDOM.unstable_createPortal
export const disableUnstableCreatePortal = false;
118 changes: 118 additions & 0 deletions packages/shared/forks/ReactFeatureFlags.testing.www.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow
*/

/*
SYNC WITH forks/ReactFeatureFlags.www.js
except isTestEnvironment = true
*/

import typeof * as FeatureFlagsType from 'shared/ReactFeatureFlags';
import typeof * as FeatureFlagsShimType from './ReactFeatureFlags.www';

// Re-export dynamic flags from the www version.
export const {
debugRenderPhaseSideEffectsForStrictMode,
disableInputAttributeSyncing,
enableTrustedTypesIntegration,
deferPassiveEffectCleanupDuringUnmount,
} = require('ReactFeatureFlags');

// In www, we have experimental support for gathering data
// from User Timing API calls in production. By default, we
// only emit performance.mark/measure calls in __DEV__. But if
// somebody calls addUserTimingListener() which is exposed as an
// experimental FB-only export, we call performance.mark/measure
// as long as there is more than a single listener.
export let enableUserTimingAPI = __DEV__;

export const enableProfilerTimer = __PROFILE__;
export const enableSchedulerTracing = __PROFILE__;
export const enableSchedulerDebugging = true;

export const replayFailedUnitOfWorkWithInvokeGuardedCallback = false;
export const warnAboutDeprecatedLifecycles = true;
export const warnAboutShorthandPropertyCollision = false;
export const disableLegacyContext = false;
export const warnAboutStringRefs = false;
export const warnAboutDefaultPropsOnFunctionComponents = false;
export const disableSchedulerTimeoutBasedOnReactExpirationTime = false;

export const enableTrainModelFix = true;

export const exposeConcurrentModeAPIs = __EXPERIMENTAL__;

export const enableSuspenseServerRenderer = true;
export const enableSelectiveHydration = true;

export const enableChunksAPI = __EXPERIMENTAL__;

export const disableJavaScriptURLs = true;

let refCount = 0;
export function addUserTimingListener() {
if (__DEV__) {
// Noop.
return () => {};
}
refCount++;
updateFlagOutsideOfReactCallStack();
return () => {
refCount--;
updateFlagOutsideOfReactCallStack();
};
}

// The flag is intentionally updated in a timeout.
// We don't support toggling it during reconciliation or
// commit since that would cause mismatching user timing API calls.
let timeout = null;
function updateFlagOutsideOfReactCallStack() {
if (!timeout) {
timeout = setTimeout(() => {
timeout = null;
enableUserTimingAPI = refCount > 0;
});
}
}

export const enableDeprecatedFlareAPI = true;

export const enableFundamentalAPI = false;

export const enableScopeAPI = true;

export const enableJSXTransformAPI = true;

export const warnAboutUnmockedScheduler = true;

export const enableSuspenseCallback = true;

export const flushSuspenseFallbacksInTests = true;

export const enableNativeTargetAsInstance = false;

export const disableCreateFactory = false;

export const disableTextareaChildren = false;

export const disableMapsAsChildren = false;

export const disableUnstableRenderSubtreeIntoContainer = false;

export const warnUnstableRenderSubtreeIntoContainer = false;

export const disableUnstableCreatePortal = false;

export const isTestEnvironment = true;

// Flow magic to verify the exports of this file match the original version.
// eslint-disable-next-line no-unused-vars
type Check<_X, Y: _X, X: Y = _X> = null;
// eslint-disable-next-line no-unused-expressions
(null: Check<FeatureFlagsShimType, FeatureFlagsType>);
5 changes: 5 additions & 0 deletions packages/shared/forks/ReactFeatureFlags.www.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@
* @flow
*/

/*
SYNC WITH forks/ReactFeatureFlags.testing.www.js
except isTestEnvironment = false
*/

import typeof * as FeatureFlagsType from 'shared/ReactFeatureFlags';
import typeof * as FeatureFlagsShimType from './ReactFeatureFlags.www';

Expand Down
Loading

0 comments on commit e25d4e1

Please sign in to comment.