Skip to content

Commit 94867f3

Browse files
authored
[asserts helpers] react package (facebook#31853)
Based off facebook#31844 Commit to review: facebook@11aa104 Converts the rest of the `react` package.
1 parent 6907aa2 commit 94867f3

18 files changed

+1431
-1013
lines changed

packages/react-reconciler/src/__tests__/ReactLazy-test.internal.js

Lines changed: 37 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -233,8 +233,28 @@ describe('ReactLazy', () => {
233233
expect(error.message).toMatch('Element type is invalid');
234234
assertLog(['Loading...']);
235235
assertConsoleErrorDev([
236-
'Expected the result of a dynamic import() call',
237-
'Expected the result of a dynamic import() call',
236+
'lazy: Expected the result of a dynamic import() call. ' +
237+
'Instead received: function Text(props) {\n' +
238+
' Scheduler.log(props.text);\n' +
239+
' return props.text;\n' +
240+
' }\n\n' +
241+
'Your code should look like: \n ' +
242+
"const MyComponent = lazy(() => import('./MyComponent'))\n" +
243+
(gate('enableOwnerStacks')
244+
? ''
245+
: ' in Lazy (at **)\n' + ' in Suspense (at **)\n') +
246+
' in App (at **)',
247+
'lazy: Expected the result of a dynamic import() call. ' +
248+
'Instead received: function Text(props) {\n' +
249+
' Scheduler.log(props.text);\n' +
250+
' return props.text;\n' +
251+
' }\n\n' +
252+
'Your code should look like: \n ' +
253+
"const MyComponent = lazy(() => import('./MyComponent'))\n" +
254+
(gate('enableOwnerStacks')
255+
? ''
256+
: ' in Lazy (at **)\n' + ' in Suspense (at **)\n') +
257+
' in App (at **)',
238258
]);
239259
expect(root).not.toMatchRenderedOutput('Hi');
240260
});
@@ -852,19 +872,21 @@ describe('ReactLazy', () => {
852872
expect(root).not.toMatchRenderedOutput('22');
853873

854874
// Mount
855-
await expect(async () => {
856-
await act(() => resolveFakeImport(Add));
857-
}).toErrorDev(
858-
shouldWarnAboutFunctionDefaultProps
859-
? [
860-
'Add: Support for defaultProps will be removed from function components in a future major release. Use JavaScript default parameters instead.',
861-
]
862-
: shouldWarnAboutMemoDefaultProps
863-
? [
864-
'Add: Support for defaultProps will be removed from memo components in a future major release. Use JavaScript default parameters instead.',
865-
]
866-
: [],
867-
);
875+
await act(() => resolveFakeImport(Add));
876+
877+
if (shouldWarnAboutFunctionDefaultProps) {
878+
assertConsoleErrorDev([
879+
'Add: Support for defaultProps will be removed from function components in a future major release. Use JavaScript default parameters instead.\n' +
880+
' in Add (at **)\n' +
881+
' in Suspense (at **)',
882+
]);
883+
} else if (shouldWarnAboutMemoDefaultProps) {
884+
assertConsoleErrorDev([
885+
'Add: Support for defaultProps will be removed from memo components in a future major release. Use JavaScript default parameters instead.\n' +
886+
' in Suspense (at **)',
887+
]);
888+
}
889+
868890
expect(root).toMatchRenderedOutput('22');
869891

870892
// Update

packages/react/src/__tests__/ReactCoffeeScriptClass-test.coffee

Lines changed: 132 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ PropTypes = null
99
React = null
1010
ReactDOM = null
1111
ReactDOMClient = null
12+
assertConsoleErrorDev = null
13+
assertConsoleWarnDev = null
1214

1315
featureFlags = require 'shared/ReactFeatureFlags'
1416

@@ -28,6 +30,9 @@ describe 'ReactCoffeeScriptClass', ->
2830
root = ReactDOMClient.createRoot container
2931
attachedListener = null
3032
renderedName = null
33+
TestUtils = require 'internal-test-utils'
34+
assertConsoleErrorDev = TestUtils.assertConsoleErrorDev
35+
assertConsoleWarnDev = TestUtils.assertConsoleWarnDev
3136
InnerComponent = class extends React.Component
3237
getName: -> this.props.name
3338
render: ->
@@ -53,14 +58,15 @@ describe 'ReactCoffeeScriptClass', ->
5358
event.preventDefault()
5459
caughtErrors.push(event.error)
5560
window.addEventListener 'error', errorHandler;
56-
expect(->
57-
ReactDOM.flushSync ->
58-
root.render React.createElement(Foo)
59-
).toErrorDev([
60-
# A failed component renders twice in DEV in concurrent mode
61-
'No `render` method found on the Foo instance',
62-
'No `render` method found on the Foo instance',
63-
])
61+
ReactDOM.flushSync ->
62+
root.render React.createElement(Foo)
63+
assertConsoleErrorDev [
64+
# A failed component renders twice in DEV in concurrent mode
65+
'No `render` method found on the Foo instance: you may have forgotten to define `render`.\n' +
66+
' in Foo (at **)',
67+
'No `render` method found on the Foo instance: you may have forgotten to define `render`.\n' +
68+
' in Foo (at **)',
69+
]
6470
window.removeEventListener 'error', errorHandler;
6571
expect(caughtErrors).toEqual([
6672
expect.objectContaining(
@@ -136,35 +142,39 @@ describe 'ReactCoffeeScriptClass', ->
136142
React.createElement('div')
137143
getDerivedStateFromProps: ->
138144
{}
139-
expect(->
140-
ReactDOM.flushSync ->
141-
root.render React.createElement(Foo, foo: 'foo')
142-
return
143-
).toErrorDev 'Foo: getDerivedStateFromProps() is defined as an instance method and will be ignored. Instead, declare it as a static method.'
145+
ReactDOM.flushSync ->
146+
root.render React.createElement(Foo, foo: 'foo')
147+
assertConsoleErrorDev [
148+
'Foo: getDerivedStateFromProps() is defined as an instance method and will be ignored. Instead, declare it as a static method.\n' +
149+
' in Foo (at **)']
144150

145151
it 'warns if getDerivedStateFromError is not static', ->
146152
class Foo extends React.Component
147153
render: ->
148154
React.createElement('div')
149155
getDerivedStateFromError: ->
150156
{}
151-
expect(->
152-
ReactDOM.flushSync ->
153-
root.render React.createElement(Foo, foo: 'foo')
154-
return
155-
).toErrorDev 'Foo: getDerivedStateFromError() is defined as an instance method and will be ignored. Instead, declare it as a static method.'
157+
ReactDOM.flushSync ->
158+
root.render React.createElement(Foo, foo: 'foo')
159+
160+
assertConsoleErrorDev [
161+
'Foo: getDerivedStateFromError() is defined as an instance method and will be ignored. Instead, declare it as a static method.\n' +
162+
' in Foo (at **)'
163+
]
156164

157165
it 'warns if getSnapshotBeforeUpdate is static', ->
158166
class Foo extends React.Component
159167
render: ->
160168
React.createElement('div')
161169
Foo.getSnapshotBeforeUpdate = () ->
162170
{}
163-
expect(->
164-
ReactDOM.flushSync ->
165-
root.render React.createElement(Foo, foo: 'foo')
166-
return
167-
).toErrorDev 'Foo: getSnapshotBeforeUpdate() is defined as a static method and will be ignored. Instead, declare it as an instance method.'
171+
ReactDOM.flushSync ->
172+
root.render React.createElement(Foo, foo: 'foo')
173+
174+
assertConsoleErrorDev [
175+
'Foo: getSnapshotBeforeUpdate() is defined as a static method and will be ignored. Instead, declare it as an instance method.\n' +
176+
' in Foo (at **)'
177+
]
168178

169179
it 'warns if state not initialized before static getDerivedStateFromProps', ->
170180
class Foo extends React.Component
@@ -177,16 +187,16 @@ describe 'ReactCoffeeScriptClass', ->
177187
foo: nextProps.foo
178188
bar: 'bar'
179189
}
180-
expect(->
181-
ReactDOM.flushSync ->
182-
root.render React.createElement(Foo, foo: 'foo')
183-
return
184-
).toErrorDev (
185-
'`Foo` uses `getDerivedStateFromProps` but its initial state is ' +
186-
'undefined. This is not recommended. Instead, define the initial state by ' +
187-
'assigning an object to `this.state` in the constructor of `Foo`. ' +
188-
'This ensures that `getDerivedStateFromProps` arguments have a consistent shape.'
189-
)
190+
ReactDOM.flushSync ->
191+
root.render React.createElement(Foo, foo: 'foo')
192+
193+
assertConsoleErrorDev [
194+
'`Foo` uses `getDerivedStateFromProps` but its initial state is
195+
undefined. This is not recommended. Instead, define the initial state by
196+
assigning an object to `this.state` in the constructor of `Foo`.
197+
This ensures that `getDerivedStateFromProps` arguments have a consistent shape.\n' +
198+
' in Foo (at **)'
199+
]
190200

191201
it 'updates initial state with values returned by static getDerivedStateFromProps', ->
192202
class Foo extends React.Component
@@ -254,12 +264,28 @@ describe 'ReactCoffeeScriptClass', ->
254264
render: ->
255265
React.createElement Foo
256266

257-
expect(->
258-
test React.createElement(Outer), 'SPAN', 'foo'
259-
).toErrorDev([
260-
'Outer uses the legacy childContextTypes API which will soon be removed. Use React.createContext() instead.',
261-
'Foo uses the legacy contextTypes API which will soon be removed. Use React.createContext() with static contextType instead.',
262-
])
267+
test React.createElement(Outer), 'SPAN', 'foo'
268+
269+
if featureFlags.enableOwnerStacks
270+
assertConsoleErrorDev([
271+
'Outer uses the legacy childContextTypes API which will soon be removed.
272+
Use React.createContext() instead. (https://react.dev/link/legacy-context)\n' +
273+
' in Outer (at **)',
274+
'Foo uses the legacy contextTypes API which will soon be removed.
275+
Use React.createContext() with static contextType instead. (https://react.dev/link/legacy-context)\n' +
276+
' in Outer (at **)',
277+
]);
278+
else
279+
assertConsoleErrorDev([
280+
'Outer uses the legacy childContextTypes API which will soon be removed.
281+
Use React.createContext() instead. (https://react.dev/link/legacy-context)\n' +
282+
' in Outer (at **)',
283+
'Foo uses the legacy contextTypes API which will soon be removed.
284+
Use React.createContext() with static contextType instead. (https://react.dev/link/legacy-context)\n' +
285+
' in Foo (at **)\n' +
286+
' in Outer (at **)',
287+
]);
288+
263289

264290
it 'renders only once when setting state in componentWillMount', ->
265291
renderCount = 0
@@ -286,9 +312,11 @@ describe 'ReactCoffeeScriptClass', ->
286312
render: ->
287313
React.createElement('span')
288314

289-
expect(->
290-
test React.createElement(Foo), 'SPAN', ''
291-
).toErrorDev('Foo.state: must be set to an object or null')
315+
test React.createElement(Foo), 'SPAN', ''
316+
assertConsoleErrorDev [
317+
'Foo.state: must be set to an object or null\n' +
318+
' in Foo (at **)'
319+
]
292320

293321
it 'should render with null in the initial state property', ->
294322
class Foo extends React.Component
@@ -430,14 +458,21 @@ describe 'ReactCoffeeScriptClass', ->
430458
className: 'foo'
431459
)
432460

433-
expect(->
434-
test React.createElement(Foo), 'SPAN', 'foo'
435-
).toErrorDev([
436-
'getInitialState was defined on Foo, a plain JavaScript class.',
437-
'getDefaultProps was defined on Foo, a plain JavaScript class.',
438-
'contextTypes was defined as an instance property on Foo.',
439-
'contextType was defined as an instance property on Foo.',
440-
])
461+
test React.createElement(Foo), 'SPAN', 'foo'
462+
assertConsoleErrorDev [
463+
'getInitialState was defined on Foo, a plain JavaScript class.
464+
This is only supported for classes created using React.createClass.
465+
Did you mean to define a state property instead?\n' +
466+
' in Foo (at **)',
467+
'getDefaultProps was defined on Foo, a plain JavaScript class.
468+
This is only supported for classes created using React.createClass.
469+
Use a static property to define defaultProps instead.\n' +
470+
' in Foo (at **)',
471+
'contextType was defined as an instance property on Foo. Use a static property to define contextType instead.\n' +
472+
' in Foo (at **)',
473+
'contextTypes was defined as an instance property on Foo. Use a static property to define contextTypes instead.\n' +
474+
' in Foo (at **)',
475+
]
441476
expect(getInitialStateWasCalled).toBe false
442477
expect(getDefaultPropsWasCalled).toBe false
443478

@@ -468,13 +503,13 @@ describe 'ReactCoffeeScriptClass', ->
468503
className: 'foo'
469504
)
470505

471-
expect(->
472-
test React.createElement(NamedComponent), 'SPAN', 'foo'
473-
).toErrorDev(
506+
test React.createElement(NamedComponent), 'SPAN', 'foo'
507+
assertConsoleErrorDev [
474508
'NamedComponent has a method called componentShouldUpdate().
475509
Did you mean shouldComponentUpdate()? The name is phrased as a
476-
question because the function is expected to return a value.'
477-
)
510+
question because the function is expected to return a value.\n' +
511+
' in NamedComponent (at **)'
512+
]
478513

479514
it 'should warn when misspelling componentWillReceiveProps', ->
480515
class NamedComponent extends React.Component
@@ -486,12 +521,12 @@ describe 'ReactCoffeeScriptClass', ->
486521
className: 'foo'
487522
)
488523

489-
expect(->
490-
test React.createElement(NamedComponent), 'SPAN', 'foo'
491-
).toErrorDev(
524+
test React.createElement(NamedComponent), 'SPAN', 'foo'
525+
assertConsoleErrorDev [
492526
'NamedComponent has a method called componentWillRecieveProps().
493-
Did you mean componentWillReceiveProps()?'
494-
)
527+
Did you mean componentWillReceiveProps()?\n' +
528+
' in NamedComponent (at **)'
529+
]
495530

496531
it 'should warn when misspelling UNSAFE_componentWillReceiveProps', ->
497532
class NamedComponent extends React.Component
@@ -503,28 +538,28 @@ describe 'ReactCoffeeScriptClass', ->
503538
className: 'foo'
504539
)
505540

506-
expect(->
507-
test React.createElement(NamedComponent), 'SPAN', 'foo'
508-
).toErrorDev(
541+
test React.createElement(NamedComponent), 'SPAN', 'foo'
542+
assertConsoleErrorDev [
509543
'NamedComponent has a method called UNSAFE_componentWillRecieveProps().
510-
Did you mean UNSAFE_componentWillReceiveProps()?'
511-
)
544+
Did you mean UNSAFE_componentWillReceiveProps()?\n' +
545+
' in NamedComponent (at **)'
546+
]
512547

513548
it 'should throw AND warn when trying to access classic APIs', ->
514549
ref = React.createRef()
515550
test React.createElement(InnerComponent, name: 'foo', ref: ref), 'DIV', 'foo'
516-
expect(->
517-
expect(-> ref.current.replaceState {}).toThrow()
518-
).toWarnDev(
519-
'replaceState(...) is deprecated in plain JavaScript React classes',
520-
{withoutStack: true}
521-
)
522-
expect(->
523-
expect(-> ref.current.isMounted()).toThrow()
524-
).toWarnDev(
525-
'isMounted(...) is deprecated in plain JavaScript React classes',
526-
{withoutStack: true}
527-
)
551+
552+
expect(-> ref.current.replaceState {}).toThrow()
553+
assertConsoleWarnDev([
554+
'replaceState(...) is deprecated in plain JavaScript React classes.
555+
Refactor your code to use setState instead (see https://github.com/facebook/react/issues/3236).'
556+
], {withoutStack: true})
557+
558+
expect(-> ref.current.isMounted()).toThrow()
559+
assertConsoleWarnDev([
560+
'isMounted(...) is deprecated in plain JavaScript React classes.
561+
Instead, make sure to clean up subscriptions and pending requests in componentWillUnmount to prevent memory leaks.',
562+
], {withoutStack: true})
528563

529564
if !featureFlags.disableLegacyContext
530565
it 'supports this.context passed via getChildContext', ->
@@ -542,13 +577,25 @@ describe 'ReactCoffeeScriptClass', ->
542577
render: ->
543578
React.createElement Bar
544579

545-
expect(->
546-
test React.createElement(Foo), 'DIV', 'bar-through-context'
547-
).toErrorDev(
548-
[
549-
'Foo uses the legacy childContextTypes API which will soon be removed. Use React.createContext() instead.',
550-
'Bar uses the legacy contextTypes API which will soon be removed. Use React.createContext() with static contextType instead.',
551-
],
552-
)
580+
test React.createElement(Foo), 'DIV', 'bar-through-context'
581+
if featureFlags.enableOwnerStacks
582+
assertConsoleErrorDev [
583+
'Foo uses the legacy childContextTypes API which will soon be removed. Use React.createContext() instead.
584+
(https://react.dev/link/legacy-context)\n' +
585+
' in Foo (at **)',
586+
'Bar uses the legacy contextTypes API which will soon be removed. Use React.createContext() with static contextType instead.
587+
(https://react.dev/link/legacy-context)\n' +
588+
' in Foo (at **)'
589+
]
590+
else
591+
assertConsoleErrorDev [
592+
'Foo uses the legacy childContextTypes API which will soon be removed. Use React.createContext() instead.
593+
(https://react.dev/link/legacy-context)\n' +
594+
' in Foo (at **)',
595+
'Bar uses the legacy contextTypes API which will soon be removed. Use React.createContext() with static contextType instead.
596+
(https://react.dev/link/legacy-context)\n' +
597+
' in Bar (at **)\n' +
598+
' in Foo (at **)'
599+
]
553600

554601
undefined

0 commit comments

Comments
 (0)