@samitouri / QOS-React-2 / commits / 6334614860

Add disableLegacyContext test gates where needed (#26371)

The www builds include disableLegacyContext as a dynamic flag, so we should be running the tests in that mode, too. Previously we were overriding the flag during the test run. This strategy usually doesn't work because the flags get compiled out in the final build, but we happen to not test www in build mode, only source. To get of this hacky override, I added a test gate to every test that uses legacy context. When we eventually remove legacy context from the codebase, this should make it slightly easier to find which tests are affected. And removes one more hack from our hack-ridden test config. Given that sometimes www has features enabled that aren't on in other builds, we might want to consider testing its build artifacts in CI, rather than just source. That would have forced this cleanup to happen sooner. Currently we only test the public builds in CI.

Andrew Clark committed Mar 11, 2023 at 15:32 UTC 63346148603675f5d03509969007b7937cfddff2
21 files changed +326 -245
packages/react-dom/src/__tests__/ReactCompositeComponent-test.js
+8
@@ -587,6 +587,7 @@ describe('ReactCompositeComponent', () => {
587 );
588 });
589
590 + // @gate !disableLegacyContext
591 it('should pass context to children when not owner', () => {
592 class Parent extends React.Component {
593 render() {
@@ -652,6 +653,7 @@ describe('ReactCompositeComponent', () => {
653 expect(childRenders).toBe(1);
654 });
655
656 + // @gate !disableLegacyContext
657 it('should pass context when re-rendered for static child', () => {
658 let parentInstance = null;
659 let childInstance = null;
@@ -712,6 +714,7 @@ describe('ReactCompositeComponent', () => {
714 expect(childInstance.context).toEqual({foo: 'bar', flag: true});
715 });
716
717 + // @gate !disableLegacyContext
718 it('should pass context when re-rendered for static child within a composite component', () => {
719 class Parent extends React.Component {
720 static childContextTypes = {
@@ -768,6 +771,7 @@ describe('ReactCompositeComponent', () => {
771 expect(wrapper.childRef.current.context).toEqual({flag: false});
772 });
773
774 + // @gate !disableLegacyContext
775 it('should pass context transitively', () => {
776 let childInstance = null;
777 let grandchildInstance = null;
@@ -829,6 +833,7 @@ describe('ReactCompositeComponent', () => {
833 expect(grandchildInstance.context).toEqual({foo: 'bar', depth: 1});
834 });
835
836 + // @gate !disableLegacyContext
837 it('should pass context when re-rendered', () => {
838 let parentInstance = null;
839 let childInstance = null;
@@ -883,6 +888,7 @@ describe('ReactCompositeComponent', () => {
888 expect(childInstance.context).toEqual({foo: 'bar', depth: 0});
889 });
890
891 + // @gate !disableLegacyContext
892 it('unmasked context propagates through updates', () => {
893 class Leaf extends React.Component {
894 static contextTypes = {
@@ -946,6 +952,7 @@ describe('ReactCompositeComponent', () => {
952 expect(div.children[0].id).toBe('aliens');
953 });
954
955 + // @gate !disableLegacyContext
956 it('should trigger componentWillReceiveProps for context changes', () => {
957 let contextChanges = 0;
958 let propChanges = 0;
@@ -1219,6 +1226,7 @@ describe('ReactCompositeComponent', () => {
1226 expect(a).toBe(b);
1227 });
1228
1229 + // @gate !disableLegacyContext || !__DEV__
1230 it('context should be passed down from the parent', () => {
1231 class Parent extends React.Component {
1232 static childContextTypes = {
packages/react-dom/src/__tests__/ReactDOMFiber-test.js
+3
@@ -718,6 +718,7 @@ describe('ReactDOMFiber', () => {
718 );
719 });
720
721 + // @gate !disableLegacyContext
722 it('should pass portal context when rendering subtree elsewhere', () => {
723 const portalContainer = document.createElement('div');
724
@@ -752,6 +753,7 @@ describe('ReactDOMFiber', () => {
753 expect(portalContainer.innerHTML).toBe('<div>bar</div>');
754 });
755
756 + // @gate !disableLegacyContext
757 it('should update portal context if it changes due to setState', () => {
758 const portalContainer = document.createElement('div');
759
@@ -796,6 +798,7 @@ describe('ReactDOMFiber', () => {
798 expect(container.innerHTML).toBe('');
799 });
800
801 + // @gate !disableLegacyContext
802 it('should update portal context if it changes due to re-render', () => {
803 const portalContainer = document.createElement('div');
804
packages/react-dom/src/__tests__/ReactDOMFizzServer-test.js
+1
@@ -1624,6 +1624,7 @@ describe('ReactDOMFizzServer', () => {
1624 }
1625 });
1626
1627 + // @gate !disableLegacyContext
1628 it('should can suspend in a class component with legacy context', async () => {
1629 class TestProvider extends React.Component {
1630 static childContextTypes = {
packages/react-dom/src/__tests__/ReactDOMServerIntegrationLegacyContext-test.js
+7
@@ -44,6 +44,13 @@ describe('ReactDOMServerIntegration', () => {
44 });
45
46 describe('legacy context', function () {
47 + // The `itRenders` test abstraction doesn't work with @gate so we have
48 + // to do this instead.
49 + if (gate(flags => flags.disableLegacyContext)) {
50 + test('empty test to stop Jest from being a complainy complainer', () => {});
51 + return;
52 + }
53 +
54 let PurpleContext, RedContext;
55 beforeEach(() => {
56 class Parent extends React.Component {
packages/react-dom/src/__tests__/ReactErrorBoundaries-test.internal.js
+37 -36
@@ -775,6 +775,7 @@ describe('ReactErrorBoundaries', () => {
775 assertLog(['ErrorBoundary componentWillUnmount']);
776 });
777
778 + // @gate !disableLegacyContext || !__DEV__
779 it('renders an error state if context provider throws in componentWillMount', () => {
780 class BrokenComponentWillMountWithContext extends React.Component {
781 static childContextTypes = {foo: PropTypes.number};
@@ -799,45 +800,45 @@ describe('ReactErrorBoundaries', () => {
800 expect(container.firstChild.textContent).toBe('Caught an error: Hello.');
801 });
802
802 - if (!require('shared/ReactFeatureFlags').disableModulePatternComponents) {
803 - it('renders an error state if module-style context provider throws in componentWillMount', () => {
804 - function BrokenComponentWillMountWithContext() {
805 - return {
806 - getChildContext() {
807 - return {foo: 42};
808 - },
809 - render() {
810 - return <div>{this.props.children}</div>;
811 - },
812 - UNSAFE_componentWillMount() {
813 - throw new Error('Hello');
814 - },
815 - };
816 - }
817 - BrokenComponentWillMountWithContext.childContextTypes = {
818 - foo: PropTypes.number,
803 + // @gate !disableModulePatternComponents
804 + // @gate !disableLegacyContext
805 + it('renders an error state if module-style context provider throws in componentWillMount', () => {
806 + function BrokenComponentWillMountWithContext() {
807 + return {
808 + getChildContext() {
809 + return {foo: 42};
810 + },
811 + render() {
812 + return <div>{this.props.children}</div>;
813 + },
814 + UNSAFE_componentWillMount() {
815 + throw new Error('Hello');
816 + },
817 };
818 + }
819 + BrokenComponentWillMountWithContext.childContextTypes = {
820 + foo: PropTypes.number,
821 + };
822
821 - const container = document.createElement('div');
822 - expect(() =>
823 - ReactDOM.render(
824 - <ErrorBoundary>
825 - <BrokenComponentWillMountWithContext />
826 - </ErrorBoundary>,
827 - container,
828 - ),
829 - ).toErrorDev(
830 - 'Warning: The <BrokenComponentWillMountWithContext /> component appears to be a function component that ' +
831 - 'returns a class instance. ' +
832 - 'Change BrokenComponentWillMountWithContext to a class that extends React.Component instead. ' +
833 - "If you can't use a class try assigning the prototype on the function as a workaround. " +
834 - '`BrokenComponentWillMountWithContext.prototype = React.Component.prototype`. ' +
835 - "Don't use an arrow function since it cannot be called with `new` by React.",
836 - );
823 + const container = document.createElement('div');
824 + expect(() =>
825 + ReactDOM.render(
826 + <ErrorBoundary>
827 + <BrokenComponentWillMountWithContext />
828 + </ErrorBoundary>,
829 + container,
830 + ),
831 + ).toErrorDev(
832 + 'Warning: The <BrokenComponentWillMountWithContext /> component appears to be a function component that ' +
833 + 'returns a class instance. ' +
834 + 'Change BrokenComponentWillMountWithContext to a class that extends React.Component instead. ' +
835 + "If you can't use a class try assigning the prototype on the function as a workaround. " +
836 + '`BrokenComponentWillMountWithContext.prototype = React.Component.prototype`. ' +
837 + "Don't use an arrow function since it cannot be called with `new` by React.",
838 + );
839
838 - expect(container.firstChild.textContent).toBe('Caught an error: Hello.');
839 - });
840 - }
840 + expect(container.firstChild.textContent).toBe('Caught an error: Hello.');
841 + });
842
843 it('mounts the error message if mounting fails', () => {
844 function renderError(error) {
packages/react-dom/src/__tests__/ReactFunctionComponent-test.js
+3
@@ -59,6 +59,7 @@ describe('ReactFunctionComponent', () => {
59 expect(container.textContent).toBe('');
60 });
61
62 + // @gate !disableLegacyContext
63 it('should pass context thru stateless component', () => {
64 class Child extends React.Component {
65 static contextTypes = {
@@ -305,6 +306,7 @@ describe('ReactFunctionComponent', () => {
306
307 // This guards against a regression caused by clearing the current debug fiber.
308 // https://github.com/facebook/react/issues/10831
309 + // @gate !disableLegacyContext || !__DEV__
310 it('should warn when giving a function ref with context', () => {
311 function Child() {
312 return null;
@@ -375,6 +377,7 @@ describe('ReactFunctionComponent', () => {
377 ]);
378 });
379
380 + // @gate !disableLegacyContext
381 it('should receive context', () => {
382 class Parent extends React.Component {
383 static childContextTypes = {
packages/react-dom/src/__tests__/ReactLegacyErrorBoundaries-test.internal.js
+1
@@ -800,6 +800,7 @@ describe('ReactLegacyErrorBoundaries', () => {
800 expect(log).toEqual(['ErrorBoundary componentWillUnmount']);
801 });
802
803 + // @gate !disableLegacyContext || !__DEV__
804 it('renders an error state if context provider throws in componentWillMount', () => {
805 class BrokenComponentWillMountWithContext extends React.Component {
806 static childContextTypes = {foo: PropTypes.number};
packages/react-dom/src/__tests__/ReactServerRendering-test.js
+1
@@ -340,6 +340,7 @@ describe('ReactDOMServer', () => {
340 expect(markup).toContain('hello, world');
341 });
342
343 + // @gate !disableLegacyContext
344 it('renders with context when using custom constructor', () => {
345 class Component extends React.Component {
346 constructor() {
packages/react-dom/src/__tests__/renderSubtreeIntoContainer-test.js
+5
@@ -17,6 +17,7 @@ const renderSubtreeIntoContainer =
17 require('react-dom').unstable_renderSubtreeIntoContainer;
18
19 describe('renderSubtreeIntoContainer', () => {
20 + // @gate !disableLegacyContext
21 it('should pass context when rendering subtree elsewhere', () => {
22 const portal = document.createElement('div');
23
@@ -99,6 +100,7 @@ describe('renderSubtreeIntoContainer', () => {
100 }
101 });
102
103 + // @gate !disableLegacyContext
104 it('should update context if it changes due to setState', () => {
105 const container = document.createElement('div');
106 document.body.appendChild(container);
@@ -159,6 +161,7 @@ describe('renderSubtreeIntoContainer', () => {
161 expect(portal.firstChild.innerHTML).toBe('changed-changed');
162 });
163
164 + // @gate !disableLegacyContext
165 it('should update context if it changes due to re-render', () => {
166 const container = document.createElement('div');
167 document.body.appendChild(container);
@@ -238,6 +241,7 @@ describe('renderSubtreeIntoContainer', () => {
241 expect(portal.firstChild.innerHTML).toBe('hello');
242 });
243
244 + // @gate !disableLegacyContext
245 it('should get context through non-context-provider parent', () => {
246 const container = document.createElement('div');
247 document.body.appendChild(container);
@@ -281,6 +285,7 @@ describe('renderSubtreeIntoContainer', () => {
285 expect(portal.textContent).toBe('foo');
286 });
287
288 + // @gate !disableLegacyContext
289 it('should get context through middle non-context-provider layer', () => {
290 const container = document.createElement('div');
291 document.body.appendChild(container);
packages/react-native-renderer/src/__tests__/ReactNativeEvents-test.internal.js
+1
@@ -197,6 +197,7 @@ it('handles events', () => {
197 ]);
198 });
199
200 +// @gate !disableLegacyContext || !__DEV__
201 it('handles events on text nodes', () => {
202 expect(RCTEventEmitter.register).toHaveBeenCalledTimes(1);
203 const EventEmitter = RCTEventEmitter.register.mock.calls[0][0];
packages/react-reconciler/src/__tests__/ReactIncremental-test.js
+55 -39
@@ -1683,6 +1683,7 @@ describe('ReactIncremental', () => {
1683 expect(instance.state.n).toEqual(3);
1684 });
1685
1686 + // @gate !disableLegacyContext
1687 it('merges and masks context', async () => {
1688 class Intl extends React.Component {
1689 static childContextTypes = {
@@ -1830,7 +1831,11 @@ describe('ReactIncremental', () => {
1831 ]);
1832 });
1833
1834 + // @gate !disableLegacyContext
1835 it('does not leak own context into context provider', async () => {
1836 + if (gate(flags => flags.disableLegacyContext)) {
1837 + throw new Error('This test infinite loops when context is disabled.');
1838 + }
1839 class Recurse extends React.Component {
1840 static contextTypes = {
1841 n: PropTypes.number,
@@ -1859,49 +1864,50 @@ describe('ReactIncremental', () => {
1864 ]);
1865 });
1866
1862 - if (!require('shared/ReactFeatureFlags').disableModulePatternComponents) {
1863 - it('does not leak own context into context provider (factory components)', async () => {
1864 - function Recurse(props, context) {
1865 - return {
1866 - getChildContext() {
1867 - return {n: (context.n || 3) - 1};
1868 - },
1869 - render() {
1870 - Scheduler.log('Recurse ' + JSON.stringify(context));
1871 - if (context.n === 0) {
1872 - return null;
1873 - }
1874 - return <Recurse />;
1875 - },
1876 - };
1877 - }
1878 - Recurse.contextTypes = {
1879 - n: PropTypes.number,
1880 - };
1881 - Recurse.childContextTypes = {
1882 - n: PropTypes.number,
1867 + // @gate !disableModulePatternComponents
1868 + // @gate !disableLegacyContext
1869 + it('does not leak own context into context provider (factory components)', async () => {
1870 + function Recurse(props, context) {
1871 + return {
1872 + getChildContext() {
1873 + return {n: (context.n || 3) - 1};
1874 + },
1875 + render() {
1876 + Scheduler.log('Recurse ' + JSON.stringify(context));
1877 + if (context.n === 0) {
1878 + return null;
1879 + }
1880 + return <Recurse />;
1881 + },
1882 };
1883 + }
1884 + Recurse.contextTypes = {
1885 + n: PropTypes.number,
1886 + };
1887 + Recurse.childContextTypes = {
1888 + n: PropTypes.number,
1889 + };
1890
1885 - ReactNoop.render(<Recurse />);
1886 - await expect(
1887 - async () =>
1888 - await waitForAll([
1889 - 'Recurse {}',
1890 - 'Recurse {"n":2}',
1891 - 'Recurse {"n":1}',
1892 - 'Recurse {"n":0}',
1893 - ]),
1894 - ).toErrorDev([
1895 - 'Warning: The <Recurse /> component appears to be a function component that returns a class instance. ' +
1896 - 'Change Recurse to a class that extends React.Component instead. ' +
1897 - "If you can't use a class try assigning the prototype on the function as a workaround. " +
1898 - '`Recurse.prototype = React.Component.prototype`. ' +
1899 - "Don't use an arrow function since it cannot be called with `new` by React.",
1900 - ]);
1901 - });
1902 - }
1891 + ReactNoop.render(<Recurse />);
1892 + await expect(
1893 + async () =>
1894 + await waitForAll([
1895 + 'Recurse {}',
1896 + 'Recurse {"n":2}',
1897 + 'Recurse {"n":1}',
1898 + 'Recurse {"n":0}',
1899 + ]),
1900 + ).toErrorDev([
1901 + 'Warning: The <Recurse /> component appears to be a function component that returns a class instance. ' +
1902 + 'Change Recurse to a class that extends React.Component instead. ' +
1903 + "If you can't use a class try assigning the prototype on the function as a workaround. " +
1904 + '`Recurse.prototype = React.Component.prototype`. ' +
1905 + "Don't use an arrow function since it cannot be called with `new` by React.",
1906 + ]);
1907 + });
1908
1909 // @gate www
1910 + // @gate !disableLegacyContext
1911 it('provides context when reusing work', async () => {
1912 class Intl extends React.Component {
1913 static childContextTypes = {
@@ -1955,6 +1961,7 @@ describe('ReactIncremental', () => {
1961 ]);
1962 });
1963
1964 + // @gate !disableLegacyContext
1965 it('reads context when setState is below the provider', async () => {
1966 let statefulInst;
1967
@@ -2041,6 +2048,7 @@ describe('ReactIncremental', () => {
2048 assertLog([]);
2049 });
2050
2051 + // @gate !disableLegacyContext
2052 it('reads context when setState is above the provider', async () => {
2053 let statefulInst;
2054
@@ -2135,6 +2143,7 @@ describe('ReactIncremental', () => {
2143 ]);
2144 });
2145
2146 + // @gate !disableLegacyContext || !__DEV__
2147 it('maintains the correct context when providers bail out due to low priority', async () => {
2148 class Root extends React.Component {
2149 render() {
@@ -2178,6 +2187,7 @@ describe('ReactIncremental', () => {
2187 await waitForAll([]);
2188 });
2189
2190 + // @gate !disableLegacyContext || !__DEV__
2191 it('maintains the correct context when unwinding due to an error in render', async () => {
2192 class Root extends React.Component {
2193 componentDidCatch(error) {
@@ -2229,6 +2239,7 @@ describe('ReactIncremental', () => {
2239 );
2240 });
2241
2242 + // @gate !disableLegacyContext || !__DEV__
2243 it('should not recreate masked context unless inputs have changed', async () => {
2244 let scuCounter = 0;
2245
@@ -2354,6 +2365,7 @@ describe('ReactIncremental', () => {
2365 expect(cduNextProps).toEqual([{children: 'B'}]);
2366 });
2367
2368 + // @gate !disableLegacyContext
2369 it('updates descendants with new context values', async () => {
2370 let instance;
2371
@@ -2403,6 +2415,7 @@ describe('ReactIncremental', () => {
2415 await waitForAll(['count:1']);
2416 });
2417
2418 + // @gate !disableLegacyContext
2419 it('updates descendants with multiple context-providing ancestors with new context values', async () => {
2420 let instance;
2421
@@ -2458,6 +2471,7 @@ describe('ReactIncremental', () => {
2471 await waitForAll(['count:1']);
2472 });
2473
2474 + // @gate !disableLegacyContext
2475 it('should not update descendants with new context values if shouldComponentUpdate returns false', async () => {
2476 let instance;
2477
@@ -2522,6 +2536,7 @@ describe('ReactIncremental', () => {
2536 await waitForAll([]);
2537 });
2538
2539 + // @gate !disableLegacyContext
2540 it('should update descendants with new context values if setState() is called in the middle of the tree', async () => {
2541 let middleInstance;
2542 let topInstance;
@@ -2667,6 +2682,7 @@ describe('ReactIncremental', () => {
2682 });
2683
2684 // We sometimes use Maps with Fibers as keys.
2685 + // @gate !disableLegacyContext || !__DEV__
2686 it('does not break with a bad Map polyfill', async () => {
2687 const realMapSet = Map.prototype.set;
2688
packages/react-reconciler/src/__tests__/ReactIncrementalErrorHandling-test.internal.js
+6
@@ -1159,6 +1159,12 @@ describe('ReactIncrementalErrorHandling', () => {
1159 expect(ReactNoop.getChildrenAsJSX('f')).toEqual(null);
1160 });
1161
1162 + // NOTE: When legacy context is removed, it's probably fine to just delete
1163 + // this test. There's plenty of test coverage of stack unwinding in general
1164 + // because it's used for new context, suspense, and many other features.
1165 + // It has to be tested independently for each feature anyway. So although it
1166 + // doesn't look like it, this test is specific to legacy context.
1167 + // @gate !disableLegacyContext
1168 it('unwinds the context stack correctly on error', async () => {
1169 class Provider extends React.Component {
1170 static childContextTypes = {message: PropTypes.string};
packages/react-reconciler/src/__tests__/ReactNewContext-test.js
+1
@@ -984,6 +984,7 @@ describe('ReactNewContext', () => {
984 expect(ReactNoop).toMatchRenderedOutput(<span prop="Child" />);
985 });
986
987 + // @gate !disableLegacyContext
988 it('provider does not bail out if legacy context changed above', async () => {
989 const Context = React.createContext(0);
990
packages/react/src/__tests__/ReactCoffeeScriptClass-test.coffee
+73 -68
@@ -11,6 +11,8 @@ ReactDOM = null
11 ReactDOMClient = null
12 act = null
13
14 +featureFlags = require 'shared/ReactFeatureFlags'
15 +
16 describe 'ReactCoffeeScriptClass', ->
17 container = null
18 root = null
@@ -216,36 +218,37 @@ describe 'ReactCoffeeScriptClass', ->
218 test React.createElement(Foo, update: false), 'DIV', 'initial'
219 test React.createElement(Foo, update: true), 'DIV', 'updated'
220
219 - it 'renders based on context in the constructor', ->
220 - class Foo extends React.Component
221 - @contextTypes:
222 - tag: PropTypes.string
223 - className: PropTypes.string
221 + if !featureFlags.disableLegacyContext
222 + it 'renders based on context in the constructor', ->
223 + class Foo extends React.Component
224 + @contextTypes:
225 + tag: PropTypes.string
226 + className: PropTypes.string
227
225 - constructor: (props, context) ->
226 - super props, context
227 - @state =
228 - tag: context.tag
229 - className: @context.className
228 + constructor: (props, context) ->
229 + super props, context
230 + @state =
231 + tag: context.tag
232 + className: @context.className
233
231 - render: ->
232 - Tag = @state.tag
233 - React.createElement Tag,
234 - className: @state.className
234 + render: ->
235 + Tag = @state.tag
236 + React.createElement Tag,
237 + className: @state.className
238
236 - class Outer extends React.Component
237 - @childContextTypes:
238 - tag: PropTypes.string
239 - className: PropTypes.string
239 + class Outer extends React.Component
240 + @childContextTypes:
241 + tag: PropTypes.string
242 + className: PropTypes.string
243
241 - getChildContext: ->
242 - tag: 'span'
243 - className: 'foo'
244 + getChildContext: ->
245 + tag: 'span'
246 + className: 'foo'
247
245 - render: ->
246 - React.createElement Foo
248 + render: ->
249 + React.createElement Foo
250
248 - test React.createElement(Outer), 'SPAN', 'foo'
251 + test React.createElement(Outer), 'SPAN', 'foo'
252
253 it 'renders only once when setting state in componentWillMount', ->
254 renderCount = 0
@@ -395,40 +398,41 @@ describe 'ReactCoffeeScriptClass', ->
398 root.unmount()
399 expect(lifeCycles).toEqual ['will-unmount']
400
398 - it 'warns when classic properties are defined on the instance,
399 - but does not invoke them.', ->
400 - getInitialStateWasCalled = false
401 - getDefaultPropsWasCalled = false
402 - class Foo extends React.Component
403 - constructor: ->
404 - @contextTypes = {}
405 - @contextType = {}
406 - @propTypes = {}
401 + if !featureFlags.disableLegacyContext
402 + it 'warns when classic properties are defined on the instance,
403 + but does not invoke them.', ->
404 + getInitialStateWasCalled = false
405 + getDefaultPropsWasCalled = false
406 + class Foo extends React.Component
407 + constructor: ->
408 + @contextTypes = {}
409 + @contextType = {}
410 + @propTypes = {}
411
408 - getInitialState: ->
409 - getInitialStateWasCalled = true
410 - {}
412 + getInitialState: ->
413 + getInitialStateWasCalled = true
414 + {}
415
412 - getDefaultProps: ->
413 - getDefaultPropsWasCalled = true
414 - {}
416 + getDefaultProps: ->
417 + getDefaultPropsWasCalled = true
418 + {}
419
416 - render: ->
417 - React.createElement('span',
418 - className: 'foo'
419 - )
420 + render: ->
421 + React.createElement('span',
422 + className: 'foo'
423 + )
424
421 - expect(->
422 - test React.createElement(Foo), 'SPAN', 'foo'
423 - ).toErrorDev([
424 - 'getInitialState was defined on Foo, a plain JavaScript class.',
425 - 'getDefaultProps was defined on Foo, a plain JavaScript class.',
426 - 'propTypes was defined as an instance property on Foo.',
427 - 'contextTypes was defined as an instance property on Foo.',
428 - 'contextType was defined as an instance property on Foo.',
429 - ])
430 - expect(getInitialStateWasCalled).toBe false
431 - expect(getDefaultPropsWasCalled).toBe false
425 + expect(->
426 + test React.createElement(Foo), 'SPAN', 'foo'
427 + ).toErrorDev([
428 + 'getInitialState was defined on Foo, a plain JavaScript class.',
429 + 'getDefaultProps was defined on Foo, a plain JavaScript class.',
430 + 'propTypes was defined as an instance property on Foo.',
431 + 'contextTypes was defined as an instance property on Foo.',
432 + 'contextType was defined as an instance property on Foo.',
433 + ])
434 + expect(getInitialStateWasCalled).toBe false
435 + expect(getDefaultPropsWasCalled).toBe false
436
437 it 'does not warn about getInitialState() on class components
438 if state is also defined.', ->
@@ -515,22 +519,23 @@ describe 'ReactCoffeeScriptClass', ->
519 {withoutStack: true}
520 )
521
518 - it 'supports this.context passed via getChildContext', ->
519 - class Bar extends React.Component
520 - @contextTypes:
521 - bar: PropTypes.string
522 - render: ->
523 - React.createElement('div', className: @context.bar)
522 + if !featureFlags.disableLegacyContext
523 + it 'supports this.context passed via getChildContext', ->
524 + class Bar extends React.Component
525 + @contextTypes:
526 + bar: PropTypes.string
527 + render: ->
528 + React.createElement('div', className: @context.bar)
529
525 - class Foo extends React.Component
526 - @childContextTypes:
527 - bar: PropTypes.string
528 - getChildContext: ->
529 - bar: 'bar-through-context'
530 - render: ->
531 - React.createElement Bar
530 + class Foo extends React.Component
531 + @childContextTypes:
532 + bar: PropTypes.string
533 + getChildContext: ->
534 + bar: 'bar-through-context'
535 + render: ->
536 + React.createElement Bar
537
533 - test React.createElement(Foo), 'DIV', 'bar-through-context'
538 + test React.createElement(Foo), 'DIV', 'bar-through-context'
539
540 it 'supports string refs', ->
541 class Foo extends React.Component
packages/react/src/__tests__/ReactContextValidator-test.js
+7
@@ -35,6 +35,7 @@ describe('ReactContextValidator', () => {
35 // TODO: This behavior creates a runtime dependency on propTypes. We should
36 // ensure that this is not required for ES6 classes with Flow.
37
38 + // @gate !disableLegacyContext
39 it('should filter out context not in contextTypes', () => {
40 class Component extends React.Component {
41 render() {
@@ -70,6 +71,7 @@ describe('ReactContextValidator', () => {
71 expect(instance.childRef.current.context).toEqual({foo: 'abc'});
72 });
73
74 + // @gate !disableLegacyContext
75 it('should pass next context to lifecycles', () => {
76 let componentDidMountContext;
77 let componentDidUpdateContext;
@@ -148,6 +150,7 @@ describe('ReactContextValidator', () => {
150 expect(componentDidUpdateContext).toEqual({foo: 'def'});
151 });
152
153 + // @gate !disableLegacyContext || !__DEV__
154 it('should check context types', () => {
155 class Component extends React.Component {
156 render() {
@@ -213,6 +216,7 @@ describe('ReactContextValidator', () => {
216 );
217 });
218
219 + // @gate !disableLegacyContext || !__DEV__
220 it('should check child context types', () => {
221 class Component extends React.Component {
222 getChildContext() {
@@ -278,6 +282,7 @@ describe('ReactContextValidator', () => {
282
283 // TODO (bvaughn) Remove this test and the associated behavior in the future.
284 // It has only been added in Fiber to match the (unintentional) behavior in Stack.
285 + // @gate !disableLegacyContext || !__DEV__
286 it('should warn (but not error) if getChildContext method is missing', () => {
287 class ComponentA extends React.Component {
288 static childContextTypes = {
@@ -314,6 +319,7 @@ describe('ReactContextValidator', () => {
319
320 // TODO (bvaughn) Remove this test and the associated behavior in the future.
321 // It has only been added in Fiber to match the (unintentional) behavior in Stack.
322 + // @gate !disableLegacyContext
323 it('should pass parent context if getChildContext method is missing', () => {
324 class ParentContextProvider extends React.Component {
325 static childContextTypes = {
@@ -474,6 +480,7 @@ describe('ReactContextValidator', () => {
480 expect(renderedContext).toBe(secondContext);
481 });
482
483 + // @gate !disableLegacyContext || !__DEV__
484 it('should warn if both contextType and contextTypes are defined', () => {
485 const Context = React.createContext();
486
packages/react/src/__tests__/ReactES6Class-test.js
+80 -74
@@ -246,36 +246,38 @@ describe('ReactES6Class', () => {
246 test(<Foo update={true} />, 'DIV', 'updated');
247 });
248
249 - it('renders based on context in the constructor', () => {
250 - class Foo extends React.Component {
251 - constructor(props, context) {
252 - super(props, context);
253 - this.state = {tag: context.tag, className: this.context.className};
254 - }
255 - render() {
256 - const Tag = this.state.tag;
257 - return <Tag className={this.state.className} />;
249 + if (!require('shared/ReactFeatureFlags').disableLegacyContext) {
250 + it('renders based on context in the constructor', () => {
251 + class Foo extends React.Component {
252 + constructor(props, context) {
253 + super(props, context);
254 + this.state = {tag: context.tag, className: this.context.className};
255 + }
256 + render() {
257 + const Tag = this.state.tag;
258 + return <Tag className={this.state.className} />;
259 + }
260 }
259 - }
260 - Foo.contextTypes = {
261 - tag: PropTypes.string,
262 - className: PropTypes.string,
263 - };
261 + Foo.contextTypes = {
262 + tag: PropTypes.string,
263 + className: PropTypes.string,
264 + };
265
265 - class Outer extends React.Component {
266 - getChildContext() {
267 - return {tag: 'span', className: 'foo'};
268 - }
269 - render() {
270 - return <Foo />;
266 + class Outer extends React.Component {
267 + getChildContext() {
268 + return {tag: 'span', className: 'foo'};
269 + }
270 + render() {
271 + return <Foo />;
272 + }
273 }
272 - }
273 - Outer.childContextTypes = {
274 - tag: PropTypes.string,
275 - className: PropTypes.string,
276 - };
277 - test(<Outer />, 'SPAN', 'foo');
278 - });
274 + Outer.childContextTypes = {
275 + tag: PropTypes.string,
276 + className: PropTypes.string,
277 + };
278 + test(<Outer />, 'SPAN', 'foo');
279 + });
280 + }
281
282 it('renders only once when setting state in componentWillMount', () => {
283 let renderCount = 0;
@@ -439,39 +441,41 @@ describe('ReactES6Class', () => {
441 expect(lifeCycles).toEqual(['will-unmount']);
442 });
443
442 - it('warns when classic properties are defined on the instance, but does not invoke them.', () => {
443 - let getDefaultPropsWasCalled = false;
444 - let getInitialStateWasCalled = false;
445 - class Foo extends React.Component {
446 - constructor() {
447 - super();
448 - this.contextTypes = {};
449 - this.contextType = {};
450 - this.propTypes = {};
451 - }
452 - getInitialState() {
453 - getInitialStateWasCalled = true;
454 - return {};
455 - }
456 - getDefaultProps() {
457 - getDefaultPropsWasCalled = true;
458 - return {};
459 - }
460 - render() {
461 - return <span className="foo" />;
444 + if (!require('shared/ReactFeatureFlags').disableLegacyContext) {
445 + it('warns when classic properties are defined on the instance, but does not invoke them.', () => {
446 + let getDefaultPropsWasCalled = false;
447 + let getInitialStateWasCalled = false;
448 + class Foo extends React.Component {
449 + constructor() {
450 + super();
451 + this.contextTypes = {};
452 + this.contextType = {};
453 + this.propTypes = {};
454 + }
455 + getInitialState() {
456 + getInitialStateWasCalled = true;
457 + return {};
458 + }
459 + getDefaultProps() {
460 + getDefaultPropsWasCalled = true;
461 + return {};
462 + }
463 + render() {
464 + return <span className="foo" />;
465 + }
466 }
463 - }
467
465 - expect(() => test(<Foo />, 'SPAN', 'foo')).toErrorDev([
466 - 'getInitialState was defined on Foo, a plain JavaScript class.',
467 - 'getDefaultProps was defined on Foo, a plain JavaScript class.',
468 - 'propTypes was defined as an instance property on Foo.',
469 - 'contextType was defined as an instance property on Foo.',
470 - 'contextTypes was defined as an instance property on Foo.',
471 - ]);
472 - expect(getInitialStateWasCalled).toBe(false);
473 - expect(getDefaultPropsWasCalled).toBe(false);
474 - });
468 + expect(() => test(<Foo />, 'SPAN', 'foo')).toErrorDev([
469 + 'getInitialState was defined on Foo, a plain JavaScript class.',
470 + 'getDefaultProps was defined on Foo, a plain JavaScript class.',
471 + 'propTypes was defined as an instance property on Foo.',
472 + 'contextType was defined as an instance property on Foo.',
473 + 'contextTypes was defined as an instance property on Foo.',
474 + ]);
475 + expect(getInitialStateWasCalled).toBe(false);
476 + expect(getDefaultPropsWasCalled).toBe(false);
477 + });
478 + }
479
480 it('does not warn about getInitialState() on class components if state is also defined.', () => {
481 class Foo extends React.Component {
@@ -553,24 +557,26 @@ describe('ReactES6Class', () => {
557 );
558 });
559
556 - it('supports this.context passed via getChildContext', () => {
557 - class Bar extends React.Component {
558 - render() {
559 - return <div className={this.context.bar} />;
560 - }
561 - }
562 - Bar.contextTypes = {bar: PropTypes.string};
563 - class Foo extends React.Component {
564 - getChildContext() {
565 - return {bar: 'bar-through-context'};
560 + if (!require('shared/ReactFeatureFlags').disableLegacyContext) {
561 + it('supports this.context passed via getChildContext', () => {
562 + class Bar extends React.Component {
563 + render() {
564 + return <div className={this.context.bar} />;
565 + }
566 }
567 - render() {
568 - return <Bar />;
567 + Bar.contextTypes = {bar: PropTypes.string};
568 + class Foo extends React.Component {
569 + getChildContext() {
570 + return {bar: 'bar-through-context'};
571 + }
572 + render() {
573 + return <Bar />;
574 + }
575 }
570 - }
571 - Foo.childContextTypes = {bar: PropTypes.string};
572 - test(<Foo />, 'DIV', 'bar-through-context');
573 - });
576 + Foo.childContextTypes = {bar: PropTypes.string};
577 + test(<Foo />, 'DIV', 'bar-through-context');
578 + });
579 + }
580
581 it('supports string refs', () => {
582 class Foo extends React.Component {
packages/react/src/__tests__/ReactJSXElementValidator-test.js
+1
@@ -302,6 +302,7 @@ describe('ReactJSXElementValidator', () => {
302 );
303 });
304
305 + // @gate !disableLegacyContext || !__DEV__
306 it('should warn on invalid context types', () => {
307 class NullContextTypeComponent extends React.Component {
308 render() {
packages/react/src/__tests__/ReactStrictMode-test.js
+1
@@ -985,6 +985,7 @@ describe('context legacy', () => {
985 jest.restoreAllMocks();
986 });
987
988 + // @gate !disableLegacyContext || !__DEV__
989 it('should warn if the legacy context API have been used in strict mode', () => {
990 class LegacyContextProvider extends React.Component {
991 getChildContext() {
packages/react/src/__tests__/ReactTypeScriptClass-test.ts
+34 -27
@@ -16,6 +16,7 @@ import ReactDOM = require('react-dom');
16 import ReactDOMClient = require('react-dom/client');
17 import ReactDOMTestUtils = require('react-dom/test-utils');
18 import PropTypes = require('prop-types');
19 +import ReactFeatureFlags = require('shared/ReactFeatureFlags');
20
21 // Before Each
22
@@ -511,9 +512,11 @@ describe('ReactTypeScriptClass', function() {
512 test(React.createElement(Foo, {update: true}), 'DIV', 'updated');
513 });
514
514 - it('renders based on context in the constructor', function() {
515 - test(React.createElement(ProvideChildContextTypes), 'SPAN', 'foo');
516 - });
515 + if (!ReactFeatureFlags.disableLegacyContext) {
516 + it('renders based on context in the constructor', function() {
517 + test(React.createElement(ProvideChildContextTypes), 'SPAN', 'foo');
518 + });
519 + }
520
521 it('renders only once when setting state in componentWillMount', function() {
522 renderCount = 0;
@@ -592,27 +595,29 @@ describe('ReactTypeScriptClass', function() {
595 expect(lifeCycles).toEqual(['will-unmount']);
596 });
597
595 - it(
596 - 'warns when classic properties are defined on the instance, ' +
597 - 'but does not invoke them.',
598 - function() {
599 - getInitialStateWasCalled = false;
600 - getDefaultPropsWasCalled = false;
601 - expect(() =>
602 - test(React.createElement(ClassicProperties), 'SPAN', 'foo')
603 - ).toErrorDev([
604 - 'getInitialState was defined on ClassicProperties, ' +
605 - 'a plain JavaScript class.',
606 - 'getDefaultProps was defined on ClassicProperties, ' +
607 - 'a plain JavaScript class.',
608 - 'propTypes was defined as an instance property on ClassicProperties.',
609 - 'contextTypes was defined as an instance property on ClassicProperties.',
610 - 'contextType was defined as an instance property on ClassicProperties.',
611 - ]);
612 - expect(getInitialStateWasCalled).toBe(false);
613 - expect(getDefaultPropsWasCalled).toBe(false);
614 - }
615 - );
598 + if (!ReactFeatureFlags.disableLegacyContext) {
599 + it(
600 + 'warns when classic properties are defined on the instance, ' +
601 + 'but does not invoke them.',
602 + function() {
603 + getInitialStateWasCalled = false;
604 + getDefaultPropsWasCalled = false;
605 + expect(() =>
606 + test(React.createElement(ClassicProperties), 'SPAN', 'foo')
607 + ).toErrorDev([
608 + 'getInitialState was defined on ClassicProperties, ' +
609 + 'a plain JavaScript class.',
610 + 'getDefaultProps was defined on ClassicProperties, ' +
611 + 'a plain JavaScript class.',
612 + 'propTypes was defined as an instance property on ClassicProperties.',
613 + 'contextTypes was defined as an instance property on ClassicProperties.',
614 + 'contextType was defined as an instance property on ClassicProperties.',
615 + ]);
616 + expect(getInitialStateWasCalled).toBe(false);
617 + expect(getDefaultPropsWasCalled).toBe(false);
618 + }
619 + );
620 + }
621
622 it(
623 'does not warn about getInitialState() on class components ' +
@@ -680,9 +685,11 @@ describe('ReactTypeScriptClass', function() {
685 );
686 });
687
683 - it('supports this.context passed via getChildContext', function() {
684 - test(React.createElement(ProvideContext), 'DIV', 'bar-through-context');
685 - });
688 + if (!ReactFeatureFlags.disableLegacyContext) {
689 + it('supports this.context passed via getChildContext', function() {
690 + test(React.createElement(ProvideContext), 'DIV', 'bar-through-context');
691 + });
692 + }
693
694 it('supports string refs', function() {
695 const ref = React.createRef();
packages/react/src/__tests__/createReactClassIntegration-test.js
+1
@@ -291,6 +291,7 @@ describe('create-react-class-integration', () => {
291 expect(instance.state.occupation).toEqual('clown');
292 });
293
294 + // @gate !disableLegacyContext
295 it('renders based on context getInitialState', () => {
296 const Foo = createReactClass({
297 contextTypes: {
scripts/jest/setupTests.www.js
-1
@@ -13,7 +13,6 @@ jest.mock('shared/ReactFeatureFlags', () => {
13 // TODO: Many tests were written before we started running them against the
14 // www configuration. Update those tests so that they work against the www
15 // configuration, too. Then remove these overrides.
16 - wwwFlags.disableLegacyContext = defaultFlags.disableLegacyContext;
16 wwwFlags.disableJavaScriptURLs = defaultFlags.disableJavaScriptURLs;
17
18 return wwwFlags;