/** * 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. * * @emails react-core * @jest-environment ./scripts/jest/ReactDOMServerIntegrationEnvironment */ 'use strict'; const ReactDOMServerIntegrationUtils = require('./utils/ReactDOMServerIntegrationTestUtils'); let React; let ReactDOMClient; let ReactFeatureFlags; let ReactDOMServer; function initModules() { // Reset warning cache. jest.resetModules(); React = require('react'); ReactDOMClient = require('react-dom/client'); ReactDOMServer = require('react-dom/server'); ReactFeatureFlags = require('shared/ReactFeatureFlags'); ReactFeatureFlags.disableLegacyContext = true; // Make them available to the helpers. return { ReactDOMClient, ReactDOMServer, }; } const {resetModules, itRenders} = ReactDOMServerIntegrationUtils(initModules); function formatValue(val) { if (val === null) { return 'null'; } if (val === undefined) { return 'undefined'; } if (typeof val === 'string') { return val; } return JSON.stringify(val); } describe('ReactDOMServerIntegrationLegacyContextDisabled', () => { beforeEach(() => { resetModules(); }); itRenders('undefined legacy context with warning', async render => { class LegacyProvider extends React.Component { static childContextTypes = { foo() {}, }; getChildContext() { return {foo: 10}; } render() { return this.props.children; } } const lifecycleContextLog = []; class LegacyClsConsumer extends React.Component { static contextTypes = { foo() {}, }; shouldComponentUpdate(nextProps, nextState, nextContext) { lifecycleContextLog.push(nextContext); return true; } UNSAFE_componentWillReceiveProps(nextProps, nextContext) { lifecycleContextLog.push(nextContext); } UNSAFE_componentWillUpdate(nextProps, nextState, nextContext) { lifecycleContextLog.push(nextContext); } render() { return formatValue(this.context); } } function LegacyFnConsumer(props, context) { return formatValue(context); } LegacyFnConsumer.contextTypes = {foo() {}}; function RegularFn(props, context) { return formatValue(context); } const e = await render( , 3, ); expect(e.textContent).toBe('{}undefinedundefined'); expect(lifecycleContextLog).toEqual([]); }); itRenders('modern context', async render => { const Ctx = React.createContext(); class Provider extends React.Component { render() { return ( {this.props.children} ); } } class RenderPropConsumer extends React.Component { render() { return {value => formatValue(value)}; } } const lifecycleContextLog = []; class ContextTypeConsumer extends React.Component { static contextType = Ctx; shouldComponentUpdate(nextProps, nextState, nextContext) { lifecycleContextLog.push(nextContext); return true; } UNSAFE_componentWillReceiveProps(nextProps, nextContext) { lifecycleContextLog.push(nextContext); } UNSAFE_componentWillUpdate(nextProps, nextState, nextContext) { lifecycleContextLog.push(nextContext); } render() { return formatValue(this.context); } } function FnConsumer() { return formatValue(React.useContext(Ctx)); } const e = await render( , ); expect(e.textContent).toBe('aaa'); expect(lifecycleContextLog).toEqual([]); }); });