mirror of
https://github.com/hanzoai/react.git
synced 2026-09-24 17:02:27 +00:00
[tests] remove withoutStack from assertConsole helpers (#35498)
Stacked on https://github.com/facebook/react/pull/35497 ----- Now that the assert helpers require a component stack, we don't need the `{withoutStack: true}` option.
This commit is contained in:
@@ -568,36 +568,6 @@ describe('ReactInternalTestUtils console assertions', () => {
|
||||
`);
|
||||
});
|
||||
|
||||
// @gate __DEV__
|
||||
it('fails if local withoutStack passed to assertConsoleLogDev', () => {
|
||||
const message = expectToThrowFailure(() => {
|
||||
console.log('Hello');
|
||||
assertConsoleLogDev([['Hello', {withoutStack: true}]]);
|
||||
});
|
||||
|
||||
expect(message).toMatchInlineSnapshot(`
|
||||
"assertConsoleLogDev(expected)
|
||||
|
||||
Do not pass withoutStack to assertConsoleLogDev logs, console.log does not have component stacks."
|
||||
`);
|
||||
});
|
||||
|
||||
// @gate __DEV__
|
||||
it('fails if global withoutStack passed to assertConsoleLogDev', () => {
|
||||
const message = expectToThrowFailure(() => {
|
||||
console.log('Hello');
|
||||
assertConsoleLogDev(['Hello'], {withoutStack: true});
|
||||
});
|
||||
|
||||
expect(message).toMatchInlineSnapshot(`
|
||||
"assertConsoleLogDev(expected)
|
||||
|
||||
Do not pass withoutStack to assertConsoleLogDev, console.log does not have component stacks."
|
||||
`);
|
||||
|
||||
assertConsoleLogDev(['Hello']);
|
||||
});
|
||||
|
||||
// @gate __DEV__
|
||||
it('fails if the args is greater than %s argument number', () => {
|
||||
const message = expectToThrowFailure(() => {
|
||||
@@ -1173,23 +1143,6 @@ describe('ReactInternalTestUtils console assertions', () => {
|
||||
`);
|
||||
});
|
||||
|
||||
// @gate __DEV__
|
||||
it('fails if only warning does not contain a stack', () => {
|
||||
const message = expectToThrowFailure(() => {
|
||||
console.warn('Hello');
|
||||
assertConsoleWarnDev(['Hello']);
|
||||
});
|
||||
expect(message).toMatchInlineSnapshot(`
|
||||
"assertConsoleWarnDev(expected)
|
||||
|
||||
Missing component stack for:
|
||||
"Hello"
|
||||
|
||||
If this warning should omit a component stack, pass [log, {withoutStack: true}].
|
||||
If all warnings should omit the component stack, add {withoutStack: true} to the assertConsoleWarnDev call."
|
||||
`);
|
||||
});
|
||||
|
||||
// @gate __DEV__
|
||||
it('fails if first warning does not contain a stack', () => {
|
||||
const message = expectToThrowFailure(() => {
|
||||
@@ -1277,287 +1230,11 @@ describe('ReactInternalTestUtils console assertions', () => {
|
||||
`);
|
||||
});
|
||||
|
||||
describe('global withoutStack', () => {
|
||||
it('passes if warnings without stack explicitly opt out', () => {
|
||||
if (__DEV__) {
|
||||
console.warn('Hello');
|
||||
}
|
||||
assertConsoleWarnDev(['Hello'], {withoutStack: true});
|
||||
|
||||
if (__DEV__) {
|
||||
console.warn('Hello');
|
||||
console.warn('Good day');
|
||||
console.warn('Bye');
|
||||
}
|
||||
|
||||
assertConsoleWarnDev(['Hello', 'Good day', 'Bye'], {
|
||||
withoutStack: true,
|
||||
});
|
||||
});
|
||||
|
||||
// @gate __DEV__
|
||||
it('fails if withoutStack is invalid null value', () => {
|
||||
const message = expectToThrowFailure(() => {
|
||||
console.warn('Hi');
|
||||
assertConsoleWarnDev(['Hi'], {withoutStack: null});
|
||||
});
|
||||
expect(message).toMatchInlineSnapshot(`
|
||||
"assertConsoleWarnDev(expected)
|
||||
|
||||
The second argument must be {withoutStack: true}.
|
||||
|
||||
Instead received {"withoutStack":null}."
|
||||
`);
|
||||
assertConsoleWarnDev(['Hi'], {withoutStack: true});
|
||||
});
|
||||
|
||||
// @gate __DEV__
|
||||
it('fails if withoutStack is invalid {} value', () => {
|
||||
const message = expectToThrowFailure(() => {
|
||||
console.warn('Hi');
|
||||
assertConsoleWarnDev(['Hi'], {withoutStack: {}});
|
||||
});
|
||||
expect(message).toMatchInlineSnapshot(`
|
||||
"assertConsoleWarnDev(expected)
|
||||
|
||||
The second argument must be {withoutStack: true}.
|
||||
|
||||
Instead received {"withoutStack":{}}."
|
||||
`);
|
||||
assertConsoleWarnDev(['Hi'], {withoutStack: true});
|
||||
});
|
||||
|
||||
// @gate __DEV__
|
||||
it('fails if withoutStack is invalid string value', () => {
|
||||
const message = expectToThrowFailure(() => {
|
||||
console.warn('Hi');
|
||||
assertConsoleWarnDev(['Hi'], {withoutStack: 'haha'});
|
||||
});
|
||||
expect(message).toMatchInlineSnapshot(`
|
||||
"assertConsoleWarnDev(expected)
|
||||
|
||||
The second argument must be {withoutStack: true}.
|
||||
|
||||
Instead received {"withoutStack":"haha"}."
|
||||
`);
|
||||
assertConsoleWarnDev(['Hi'], {withoutStack: true});
|
||||
});
|
||||
|
||||
// @gate __DEV__
|
||||
it('fails if only warning is not expected to have a stack, but does', () => {
|
||||
const message = expectToThrowFailure(() => {
|
||||
console.warn('Hello\n in div');
|
||||
assertConsoleWarnDev(['Hello'], {withoutStack: true});
|
||||
});
|
||||
expect(message).toMatchInlineSnapshot(`
|
||||
"assertConsoleWarnDev(expected)
|
||||
|
||||
Unexpected warning(s) recorded.
|
||||
|
||||
- Expected warnings
|
||||
+ Received warnings
|
||||
|
||||
- Hello
|
||||
+ Hello in div (at **)"
|
||||
`);
|
||||
});
|
||||
|
||||
// @gate __DEV__
|
||||
it('fails if warnings are not expected to have a stack, but some do', () => {
|
||||
const message = expectToThrowFailure(() => {
|
||||
console.warn('Hello\n in div');
|
||||
console.warn('Good day');
|
||||
console.warn('Bye\n in div');
|
||||
assertConsoleWarnDev(['Hello', 'Good day', 'Bye'], {
|
||||
withoutStack: true,
|
||||
});
|
||||
});
|
||||
expect(message).toMatchInlineSnapshot(`
|
||||
"assertConsoleWarnDev(expected)
|
||||
|
||||
Unexpected warning(s) recorded.
|
||||
|
||||
- Expected warnings
|
||||
+ Received warnings
|
||||
|
||||
- Hello
|
||||
+ Hello in div (at **)
|
||||
Good day
|
||||
- Bye
|
||||
+ Bye in div (at **)"
|
||||
`);
|
||||
});
|
||||
});
|
||||
describe('local withoutStack', () => {
|
||||
it('passes when expected withoutStack logs matches the actual logs', () => {
|
||||
if (__DEV__) {
|
||||
console.warn('Hello\n in div');
|
||||
console.warn('Good day');
|
||||
console.warn('Bye\n in div');
|
||||
}
|
||||
assertConsoleWarnDev([
|
||||
'Hello\n in div',
|
||||
['Good day', {withoutStack: true}],
|
||||
'Bye\n in div',
|
||||
]);
|
||||
});
|
||||
|
||||
// @gate __DEV__
|
||||
it('fails if withoutStack is invalid null value', () => {
|
||||
const message = expectToThrowFailure(() => {
|
||||
console.warn('Hi');
|
||||
assertConsoleWarnDev([['Hi', {withoutStack: null}]]);
|
||||
});
|
||||
expect(message).toMatchInlineSnapshot(`
|
||||
"assertConsoleWarnDev(expected)
|
||||
|
||||
Log entries that are arrays must be of the form [string, {withoutStack: true}]
|
||||
|
||||
Instead received [string, {"withoutStack":null}]."
|
||||
`);
|
||||
});
|
||||
|
||||
// @gate __DEV__
|
||||
it('fails if withoutStack is invalid {} value', () => {
|
||||
const message = expectToThrowFailure(() => {
|
||||
console.warn('Hi');
|
||||
assertConsoleWarnDev([['Hi', {withoutStack: {}}]]);
|
||||
});
|
||||
expect(message).toMatchInlineSnapshot(`
|
||||
"assertConsoleWarnDev(expected)
|
||||
|
||||
Log entries that are arrays must be of the form [string, {withoutStack: true}]
|
||||
|
||||
Instead received [string, {"withoutStack":{}}]."
|
||||
`);
|
||||
});
|
||||
|
||||
// @gate __DEV__
|
||||
it('fails if withoutStack is invalid string value', () => {
|
||||
const message = expectToThrowFailure(() => {
|
||||
console.warn('Hi');
|
||||
assertConsoleWarnDev([['Hi', {withoutStack: 'haha'}]]);
|
||||
});
|
||||
expect(message).toMatchInlineSnapshot(`
|
||||
"assertConsoleWarnDev(expected)
|
||||
|
||||
Log entries that are arrays must be of the form [string, {withoutStack: true}]
|
||||
|
||||
Instead received [string, {"withoutStack":"haha"}]."
|
||||
`);
|
||||
});
|
||||
|
||||
// @gate __DEV__
|
||||
it('fails if withoutStack is invalid number value', () => {
|
||||
const message = expectToThrowFailure(() => {
|
||||
console.warn('Hi');
|
||||
assertConsoleWarnDev([['Hi', {withoutStack: 4}]]);
|
||||
});
|
||||
expect(message).toMatchInlineSnapshot(`
|
||||
"assertConsoleWarnDev(expected)
|
||||
|
||||
Log entries that are arrays must be of the form [string, {withoutStack: true}]
|
||||
|
||||
Instead received [string, {"withoutStack":4}]."
|
||||
`);
|
||||
});
|
||||
|
||||
// @gate __DEV__
|
||||
it('fails if you forget to wrap local withoutStack in array', () => {
|
||||
const message = expectToThrowFailure(() => {
|
||||
console.warn('Hello\n in div');
|
||||
console.warn('Bye\n in div');
|
||||
assertConsoleWarnDev(['Hello', {withoutStack: true}, 'Bye']);
|
||||
});
|
||||
expect(message).toMatchInlineSnapshot(`
|
||||
"assertConsoleWarnDev(expected)
|
||||
|
||||
Did you forget to wrap a log with withoutStack in an array?
|
||||
|
||||
The expected message for assertConsoleWarnDev() must be a string or an array of length 2.
|
||||
|
||||
Instead received {"withoutStack":true}."
|
||||
`);
|
||||
});
|
||||
|
||||
// @gate __DEV__
|
||||
it('fails if you wrap in an array unnecessarily', () => {
|
||||
const message = expectToThrowFailure(() => {
|
||||
console.warn('Hello');
|
||||
assertConsoleWarnDev([['Hello']]);
|
||||
});
|
||||
expect(message).toMatchInlineSnapshot(`
|
||||
"assertConsoleWarnDev(expected)
|
||||
|
||||
Did you forget to remove the array around the log?
|
||||
|
||||
The expected message for assertConsoleWarnDev() must be a string or an array of length 2, but there's only one item in the array. If this is intentional, remove the extra array."
|
||||
`);
|
||||
});
|
||||
|
||||
// @gate __DEV__
|
||||
it('fails if only warning is not expected to have a stack, but does', () => {
|
||||
const message = expectToThrowFailure(() => {
|
||||
console.warn('Hello\n in div');
|
||||
assertConsoleWarnDev([['Hello', {withoutStack: true}]]);
|
||||
});
|
||||
expect(message).toMatchInlineSnapshot(`
|
||||
"assertConsoleWarnDev(expected)
|
||||
|
||||
Unexpected warning(s) recorded.
|
||||
|
||||
- Expected warnings
|
||||
+ Received warnings
|
||||
|
||||
- Hello
|
||||
+ Hello in div (at **)"
|
||||
`);
|
||||
});
|
||||
|
||||
// @gate __DEV__
|
||||
it('fails if warnings are not expected to have a stack, but some do', () => {
|
||||
const message = expectToThrowFailure(() => {
|
||||
console.warn('Hello\n in div');
|
||||
console.warn('Good day');
|
||||
console.warn('Bye\n in div');
|
||||
assertConsoleWarnDev([
|
||||
[
|
||||
'Hello',
|
||||
{
|
||||
withoutStack: true,
|
||||
},
|
||||
],
|
||||
'Good day',
|
||||
[
|
||||
'Bye',
|
||||
{
|
||||
withoutStack: true,
|
||||
},
|
||||
],
|
||||
]);
|
||||
});
|
||||
expect(message).toMatchInlineSnapshot(`
|
||||
"assertConsoleWarnDev(expected)
|
||||
|
||||
Unexpected warning(s) recorded.
|
||||
|
||||
- Expected warnings
|
||||
+ Received warnings
|
||||
|
||||
- Hello
|
||||
+ Hello in div (at **)
|
||||
Good day
|
||||
- Bye
|
||||
+ Bye in div (at **)"
|
||||
`);
|
||||
});
|
||||
});
|
||||
|
||||
// @gate __DEV__
|
||||
it('fails if the args is greater than %s argument number', () => {
|
||||
const message = expectToThrowFailure(() => {
|
||||
console.warn('Hi %s', 'Sara', 'extra');
|
||||
assertConsoleWarnDev(['Hi'], {withoutStack: true});
|
||||
assertConsoleWarnDev(['Hi']);
|
||||
});
|
||||
expect(message).toMatchInlineSnapshot(`
|
||||
"assertConsoleWarnDev(expected)
|
||||
@@ -1572,7 +1249,7 @@ describe('ReactInternalTestUtils console assertions', () => {
|
||||
const message = expectToThrowFailure(() => {
|
||||
console.warn('Hi %s', 'Sara', 'extra');
|
||||
console.warn('Bye %s', 'Sara', 'extra');
|
||||
assertConsoleWarnDev(['Hi', 'Bye'], {withoutStack: true});
|
||||
assertConsoleWarnDev(['Hi', 'Bye']);
|
||||
});
|
||||
expect(message).toMatchInlineSnapshot(`
|
||||
"assertConsoleWarnDev(expected)
|
||||
@@ -1589,7 +1266,7 @@ describe('ReactInternalTestUtils console assertions', () => {
|
||||
it('fails if the %s argument number is greater than args', () => {
|
||||
const message = expectToThrowFailure(() => {
|
||||
console.warn('Hi %s');
|
||||
assertConsoleWarnDev(['Hi'], {withoutStack: true});
|
||||
assertConsoleWarnDev(['Hi']);
|
||||
});
|
||||
expect(message).toMatchInlineSnapshot(`
|
||||
"assertConsoleWarnDev(expected)
|
||||
@@ -1604,7 +1281,7 @@ describe('ReactInternalTestUtils console assertions', () => {
|
||||
const message = expectToThrowFailure(() => {
|
||||
console.warn('Hi %s');
|
||||
console.warn('Bye %s');
|
||||
assertConsoleWarnDev(['Hi', 'Bye'], {withoutStack: true});
|
||||
assertConsoleWarnDev(['Hi', 'Bye']);
|
||||
});
|
||||
expect(message).toMatchInlineSnapshot(`
|
||||
"assertConsoleWarnDev(expected)
|
||||
@@ -2217,7 +1894,7 @@ describe('ReactInternalTestUtils console assertions', () => {
|
||||
"TypeError: Cannot read properties of undefined (reading 'stack')\n" +
|
||||
' in Foo (at **)'
|
||||
);
|
||||
assertConsoleErrorDev([['Hi', {withoutStack: true}]]);
|
||||
assertConsoleErrorDev(['Hi']);
|
||||
});
|
||||
expect(message).toMatchInlineSnapshot(`
|
||||
"assertConsoleErrorDev(expected)
|
||||
@@ -2254,313 +1931,11 @@ describe('ReactInternalTestUtils console assertions', () => {
|
||||
`);
|
||||
});
|
||||
|
||||
describe('global withoutStack', () => {
|
||||
it('passes if errors without stack explicitly opt out', () => {
|
||||
if (__DEV__) {
|
||||
console.error('Hello');
|
||||
}
|
||||
assertConsoleErrorDev(['Hello'], {withoutStack: true});
|
||||
|
||||
if (__DEV__) {
|
||||
console.error('Hello');
|
||||
console.error('Good day');
|
||||
console.error('Bye');
|
||||
}
|
||||
|
||||
assertConsoleErrorDev(['Hello', 'Good day', 'Bye'], {
|
||||
withoutStack: true,
|
||||
});
|
||||
});
|
||||
|
||||
// @gate __DEV__
|
||||
it('fails if withoutStack is invalid null value', () => {
|
||||
const message = expectToThrowFailure(() => {
|
||||
console.error('Hi');
|
||||
assertConsoleErrorDev(['Hi'], {withoutStack: null});
|
||||
});
|
||||
expect(message).toMatchInlineSnapshot(`
|
||||
"assertConsoleErrorDev(expected)
|
||||
|
||||
The second argument must be {withoutStack: true}.
|
||||
|
||||
Instead received {"withoutStack":null}."
|
||||
`);
|
||||
assertConsoleErrorDev(['Hi'], {withoutStack: true});
|
||||
});
|
||||
|
||||
// @gate __DEV__
|
||||
it('fails if withoutStack is invalid {} value', () => {
|
||||
const message = expectToThrowFailure(() => {
|
||||
console.error('Hi');
|
||||
assertConsoleErrorDev(['Hi'], {withoutStack: {}});
|
||||
});
|
||||
expect(message).toMatchInlineSnapshot(`
|
||||
"assertConsoleErrorDev(expected)
|
||||
|
||||
The second argument must be {withoutStack: true}.
|
||||
|
||||
Instead received {"withoutStack":{}}."
|
||||
`);
|
||||
assertConsoleErrorDev(['Hi'], {withoutStack: true});
|
||||
});
|
||||
|
||||
// @gate __DEV__
|
||||
it('fails if withoutStack is invalid string value', () => {
|
||||
const message = expectToThrowFailure(() => {
|
||||
console.error('Hi');
|
||||
assertConsoleErrorDev(['Hi'], {withoutStack: 'haha'});
|
||||
});
|
||||
expect(message).toMatchInlineSnapshot(`
|
||||
"assertConsoleErrorDev(expected)
|
||||
|
||||
The second argument must be {withoutStack: true}.
|
||||
|
||||
Instead received {"withoutStack":"haha"}."
|
||||
`);
|
||||
assertConsoleErrorDev(['Hi'], {withoutStack: true});
|
||||
});
|
||||
|
||||
// @gate __DEV__
|
||||
it('fails if only error is not expected to have a stack, but does', () => {
|
||||
const message = expectToThrowFailure(() => {
|
||||
console.error('Hello\n in div');
|
||||
assertConsoleErrorDev(['Hello'], {withoutStack: true});
|
||||
});
|
||||
expect(message).toMatchInlineSnapshot(`
|
||||
"assertConsoleErrorDev(expected)
|
||||
|
||||
Unexpected error(s) recorded.
|
||||
|
||||
- Expected errors
|
||||
+ Received errors
|
||||
|
||||
- Hello
|
||||
+ Hello in div (at **)"
|
||||
`);
|
||||
});
|
||||
|
||||
// @gate __DEV__
|
||||
it('fails if errors are not expected to have a stack, but some do', () => {
|
||||
const message = expectToThrowFailure(() => {
|
||||
console.error('Hello\n in div');
|
||||
console.error('Good day');
|
||||
console.error('Bye\n in div');
|
||||
assertConsoleErrorDev(['Hello', 'Good day', 'Bye'], {
|
||||
withoutStack: true,
|
||||
});
|
||||
});
|
||||
expect(message).toMatchInlineSnapshot(`
|
||||
"assertConsoleErrorDev(expected)
|
||||
|
||||
Unexpected error(s) recorded.
|
||||
|
||||
- Expected errors
|
||||
+ Received errors
|
||||
|
||||
- Hello
|
||||
+ Hello in div (at **)
|
||||
Good day
|
||||
- Bye
|
||||
+ Bye in div (at **)"
|
||||
`);
|
||||
});
|
||||
});
|
||||
describe('local withoutStack', () => {
|
||||
it('passes when expected withoutStack logs matches the actual logs', () => {
|
||||
if (__DEV__) {
|
||||
console.error('Hello\n in div');
|
||||
console.error('Good day');
|
||||
console.error('Bye\n in div');
|
||||
}
|
||||
assertConsoleErrorDev([
|
||||
'Hello\n in div',
|
||||
['Good day', {withoutStack: true}],
|
||||
'Bye\n in div',
|
||||
]);
|
||||
});
|
||||
|
||||
// @gate __DEV__
|
||||
it('fails if withoutStack is invalid null value', () => {
|
||||
const message = expectToThrowFailure(() => {
|
||||
console.error('Hi');
|
||||
assertConsoleErrorDev([['Hi', {withoutStack: null}]]);
|
||||
});
|
||||
expect(message).toMatchInlineSnapshot(`
|
||||
"assertConsoleErrorDev(expected)
|
||||
|
||||
Log entries that are arrays must be of the form [string, {withoutStack: true}]
|
||||
|
||||
Instead received [string, {"withoutStack":null}]."
|
||||
`);
|
||||
});
|
||||
|
||||
// @gate __DEV__
|
||||
it('fails if withoutStack is invalid {} value', () => {
|
||||
const message = expectToThrowFailure(() => {
|
||||
console.error('Hi');
|
||||
assertConsoleErrorDev([['Hi', {withoutStack: {}}]]);
|
||||
});
|
||||
expect(message).toMatchInlineSnapshot(`
|
||||
"assertConsoleErrorDev(expected)
|
||||
|
||||
Log entries that are arrays must be of the form [string, {withoutStack: true}]
|
||||
|
||||
Instead received [string, {"withoutStack":{}}]."
|
||||
`);
|
||||
});
|
||||
|
||||
// @gate __DEV__
|
||||
it('fails if withoutStack is invalid string value', () => {
|
||||
const message = expectToThrowFailure(() => {
|
||||
console.error('Hi');
|
||||
assertConsoleErrorDev([['Hi', {withoutStack: 'haha'}]]);
|
||||
});
|
||||
expect(message).toMatchInlineSnapshot(`
|
||||
"assertConsoleErrorDev(expected)
|
||||
|
||||
Log entries that are arrays must be of the form [string, {withoutStack: true}]
|
||||
|
||||
Instead received [string, {"withoutStack":"haha"}]."
|
||||
`);
|
||||
});
|
||||
|
||||
// @gate __DEV__
|
||||
it('fails if withoutStack is invalid number value', () => {
|
||||
const message = expectToThrowFailure(() => {
|
||||
console.error('Hi');
|
||||
assertConsoleErrorDev([['Hi', {withoutStack: 4}]]);
|
||||
});
|
||||
expect(message).toMatchInlineSnapshot(`
|
||||
"assertConsoleErrorDev(expected)
|
||||
|
||||
Log entries that are arrays must be of the form [string, {withoutStack: true}]
|
||||
|
||||
Instead received [string, {"withoutStack":4}]."
|
||||
`);
|
||||
});
|
||||
|
||||
// @gate __DEV__
|
||||
it('fails if you forget to wrap local withoutStack in array', () => {
|
||||
const message = expectToThrowFailure(() => {
|
||||
console.error('Hello\n in div');
|
||||
console.error('Bye\n in div');
|
||||
assertConsoleErrorDev(['Hello', {withoutStack: true}, 'Bye']);
|
||||
});
|
||||
expect(message).toMatchInlineSnapshot(`
|
||||
"assertConsoleErrorDev(expected)
|
||||
|
||||
Did you forget to wrap a log with withoutStack in an array?
|
||||
|
||||
The expected message for assertConsoleErrorDev() must be a string or an array of length 2.
|
||||
|
||||
Instead received {"withoutStack":true}."
|
||||
`);
|
||||
});
|
||||
|
||||
// @gate __DEV__
|
||||
it('fails if you wrap in an array unnecessarily', () => {
|
||||
const message = expectToThrowFailure(() => {
|
||||
console.error('Hello');
|
||||
assertConsoleErrorDev([['Hello']]);
|
||||
});
|
||||
expect(message).toMatchInlineSnapshot(`
|
||||
"assertConsoleErrorDev(expected)
|
||||
|
||||
Did you forget to remove the array around the log?
|
||||
|
||||
The expected message for assertConsoleErrorDev() must be a string or an array of length 2, but there's only one item in the array. If this is intentional, remove the extra array."
|
||||
`);
|
||||
});
|
||||
|
||||
// @gate __DEV__
|
||||
it('fails if only error is not expected to have a stack, but does', () => {
|
||||
const message = expectToThrowFailure(() => {
|
||||
console.error('Hello\n in div');
|
||||
assertConsoleErrorDev([['Hello', {withoutStack: true}]]);
|
||||
});
|
||||
expect(message).toMatchInlineSnapshot(`
|
||||
"assertConsoleErrorDev(expected)
|
||||
|
||||
Unexpected error(s) recorded.
|
||||
|
||||
- Expected errors
|
||||
+ Received errors
|
||||
|
||||
- Hello
|
||||
+ Hello in div (at **)"
|
||||
`);
|
||||
});
|
||||
|
||||
// @gate __DEV__
|
||||
it('fails if errors are not expected to have a stack, but some do', () => {
|
||||
const message = expectToThrowFailure(() => {
|
||||
console.error('Hello\n in div');
|
||||
console.error('Good day');
|
||||
console.error('Bye\n in div');
|
||||
assertConsoleErrorDev([
|
||||
[
|
||||
'Hello',
|
||||
{
|
||||
withoutStack: true,
|
||||
},
|
||||
],
|
||||
'Good day',
|
||||
[
|
||||
'Bye',
|
||||
{
|
||||
withoutStack: true,
|
||||
},
|
||||
],
|
||||
]);
|
||||
});
|
||||
expect(message).toMatchInlineSnapshot(`
|
||||
"assertConsoleErrorDev(expected)
|
||||
|
||||
Unexpected error(s) recorded.
|
||||
|
||||
- Expected errors
|
||||
+ Received errors
|
||||
|
||||
- Hello
|
||||
+ Hello in div (at **)
|
||||
Good day
|
||||
- Bye
|
||||
+ Bye in div (at **)"
|
||||
`);
|
||||
});
|
||||
|
||||
// @gate __DEV__
|
||||
it('fails with a helpful error message if the expected error message mismatches', () => {
|
||||
const message = expectToThrowFailure(() => {
|
||||
console.error('Bye\n in div');
|
||||
assertConsoleErrorDev([
|
||||
[
|
||||
'Hello',
|
||||
{
|
||||
withoutStack: true,
|
||||
},
|
||||
],
|
||||
]);
|
||||
});
|
||||
expect(message).toMatchInlineSnapshot(`
|
||||
"assertConsoleErrorDev(expected)
|
||||
|
||||
Unexpected error(s) recorded.
|
||||
|
||||
- Expected errors
|
||||
+ Received errors
|
||||
|
||||
- Hello
|
||||
+ Bye in div (at **)"
|
||||
`);
|
||||
});
|
||||
});
|
||||
|
||||
// @gate __DEV__
|
||||
it('fails if the args is greater than %s argument number', () => {
|
||||
const message = expectToThrowFailure(() => {
|
||||
console.error('Hi %s', 'Sara', 'extra');
|
||||
assertConsoleErrorDev(['Hi'], {withoutStack: true});
|
||||
assertConsoleErrorDev(['Hi']);
|
||||
});
|
||||
expect(message).toMatchInlineSnapshot(`
|
||||
"assertConsoleErrorDev(expected)
|
||||
@@ -2575,7 +1950,7 @@ describe('ReactInternalTestUtils console assertions', () => {
|
||||
const message = expectToThrowFailure(() => {
|
||||
console.error('Hi %s', 'Sara', 'extra');
|
||||
console.error('Bye %s', 'Sara', 'extra');
|
||||
assertConsoleErrorDev(['Hi', 'Bye'], {withoutStack: true});
|
||||
assertConsoleErrorDev(['Hi', 'Bye']);
|
||||
});
|
||||
expect(message).toMatchInlineSnapshot(`
|
||||
"assertConsoleErrorDev(expected)
|
||||
@@ -2592,7 +1967,7 @@ describe('ReactInternalTestUtils console assertions', () => {
|
||||
it('fails if the %s argument number is greater than args', () => {
|
||||
const message = expectToThrowFailure(() => {
|
||||
console.error('Hi %s');
|
||||
assertConsoleErrorDev(['Hi'], {withoutStack: true});
|
||||
assertConsoleErrorDev(['Hi']);
|
||||
});
|
||||
expect(message).toMatchInlineSnapshot(`
|
||||
"assertConsoleErrorDev(expected)
|
||||
@@ -2607,7 +1982,7 @@ describe('ReactInternalTestUtils console assertions', () => {
|
||||
const message = expectToThrowFailure(() => {
|
||||
console.error('Hi %s');
|
||||
console.error('Bye %s');
|
||||
assertConsoleErrorDev(['Hi', 'Bye'], {withoutStack: true});
|
||||
assertConsoleErrorDev(['Hi', 'Bye']);
|
||||
});
|
||||
expect(message).toMatchInlineSnapshot(`
|
||||
"assertConsoleErrorDev(expected)
|
||||
@@ -2812,27 +2187,21 @@ describe('ReactInternalTestUtils console assertions', () => {
|
||||
it('expands [Server] to ANSI escape sequence for server badge', () => {
|
||||
const badge = '\u001b[0m\u001b[7m Server \u001b[0m';
|
||||
console.error(badge + 'Error: something went wrong');
|
||||
assertConsoleErrorDev([
|
||||
['[Server] Error: something went wrong', {withoutStack: true}],
|
||||
]);
|
||||
assertConsoleErrorDev(['[Server] Error: something went wrong']);
|
||||
});
|
||||
|
||||
// @gate __DEV__
|
||||
it('expands [Prerender] to ANSI escape sequence for server badge', () => {
|
||||
const badge = '\u001b[0m\u001b[7m Prerender \u001b[0m';
|
||||
console.error(badge + 'Error: something went wrong');
|
||||
assertConsoleErrorDev([
|
||||
['[Prerender] Error: something went wrong', {withoutStack: true}],
|
||||
]);
|
||||
assertConsoleErrorDev(['[Prerender] Error: something went wrong']);
|
||||
});
|
||||
|
||||
// @gate __DEV__
|
||||
it('expands [Cache] to ANSI escape sequence for server badge', () => {
|
||||
const badge = '\u001b[0m\u001b[7m Cache \u001b[0m';
|
||||
console.error(badge + 'Error: something went wrong');
|
||||
assertConsoleErrorDev([
|
||||
['[Cache] Error: something went wrong', {withoutStack: true}],
|
||||
]);
|
||||
assertConsoleErrorDev(['[Cache] Error: something went wrong']);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -290,26 +290,11 @@ export function createLogAssertion(
|
||||
}
|
||||
}
|
||||
|
||||
const withoutStack = options.withoutStack;
|
||||
|
||||
if (consoleMethod === 'log' && withoutStack !== undefined) {
|
||||
throwFormattedError(
|
||||
`Do not pass withoutStack to assertConsoleLogDev, console.log does not have component stacks.`,
|
||||
);
|
||||
} else if (withoutStack !== undefined && withoutStack !== true) {
|
||||
throwFormattedError(
|
||||
`The second argument must be {withoutStack: true}.` +
|
||||
`\n\nInstead received ${JSON.stringify(options)}.`,
|
||||
);
|
||||
}
|
||||
|
||||
const observedLogs = clearObservedErrors();
|
||||
const receivedLogs = [];
|
||||
const missingExpectedLogs = Array.from(expectedMessages);
|
||||
|
||||
const unexpectedLogs = [];
|
||||
const unexpectedMissingComponentStack = [];
|
||||
const unexpectedIncludingComponentStack = [];
|
||||
const unexpectedMissingErrorStack = [];
|
||||
const unexpectedIncludingErrorStack = [];
|
||||
const logsMismatchingFormat = [];
|
||||
@@ -334,72 +319,12 @@ export function createLogAssertion(
|
||||
}
|
||||
|
||||
let expectedMessage;
|
||||
let expectedWithoutStack;
|
||||
const expectedMessageOrArray = expectedMessages[index];
|
||||
if (
|
||||
expectedMessageOrArray != null &&
|
||||
Array.isArray(expectedMessageOrArray)
|
||||
) {
|
||||
// Should be in the local form assert([['log', {withoutStack: true}]])
|
||||
|
||||
// Some validations for common mistakes.
|
||||
if (expectedMessageOrArray.length === 1) {
|
||||
throwFormattedError(
|
||||
`Did you forget to remove the array around the log?` +
|
||||
`\n\nThe expected message for ${matcherName}() must be a string or an array of length 2, but there's only one item in the array. If this is intentional, remove the extra array.`,
|
||||
);
|
||||
} else if (expectedMessageOrArray.length !== 2) {
|
||||
throwFormattedError(
|
||||
`The expected message for ${matcherName}() must be a string or an array of length 2. ` +
|
||||
`Instead received ${expectedMessageOrArray}.`,
|
||||
);
|
||||
} else if (consoleMethod === 'log') {
|
||||
// We don't expect any console.log calls to have a stack.
|
||||
throwFormattedError(
|
||||
`Do not pass withoutStack to assertConsoleLogDev logs, console.log does not have component stacks.`,
|
||||
);
|
||||
}
|
||||
|
||||
// Format is correct, check the values.
|
||||
const currentExpectedMessage = expectedMessageOrArray[0];
|
||||
const currentExpectedOptions = expectedMessageOrArray[1];
|
||||
if (
|
||||
typeof currentExpectedMessage !== 'string' ||
|
||||
typeof currentExpectedOptions !== 'object' ||
|
||||
currentExpectedOptions.withoutStack !== true
|
||||
) {
|
||||
throwFormattedError(
|
||||
`Log entries that are arrays must be of the form [string, {withoutStack: true}]` +
|
||||
`\n\nInstead received [${typeof currentExpectedMessage}, ${JSON.stringify(
|
||||
currentExpectedOptions,
|
||||
)}].`,
|
||||
);
|
||||
}
|
||||
|
||||
expectedMessage = normalizeExpectedMessage(currentExpectedMessage);
|
||||
expectedWithoutStack = expectedMessageOrArray[1].withoutStack;
|
||||
} else if (typeof expectedMessageOrArray === 'string') {
|
||||
if (typeof expectedMessageOrArray === 'string') {
|
||||
expectedMessage = normalizeExpectedMessage(expectedMessageOrArray);
|
||||
// withoutStack: inherit from global option - simplify when withoutStack is removed.
|
||||
if (consoleMethod === 'log') {
|
||||
expectedWithoutStack = true;
|
||||
} else {
|
||||
expectedWithoutStack = withoutStack;
|
||||
}
|
||||
} else if (
|
||||
typeof expectedMessageOrArray === 'object' &&
|
||||
expectedMessageOrArray != null &&
|
||||
expectedMessageOrArray.withoutStack != null
|
||||
) {
|
||||
// Special case for common case of a wrong withoutStack value.
|
||||
throwFormattedError(
|
||||
`Did you forget to wrap a log with withoutStack in an array?` +
|
||||
`\n\nThe expected message for ${matcherName}() must be a string or an array of length 2.` +
|
||||
`\n\nInstead received ${JSON.stringify(expectedMessageOrArray)}.`,
|
||||
);
|
||||
} else if (expectedMessageOrArray != null) {
|
||||
throwFormattedError(
|
||||
`The expected message for ${matcherName}() must be a string or an array of length 2. ` +
|
||||
`The expected message for ${matcherName}() must be a string. ` +
|
||||
`Instead received ${JSON.stringify(expectedMessageOrArray)}.`,
|
||||
);
|
||||
}
|
||||
@@ -499,18 +424,6 @@ export function createLogAssertion(
|
||||
}
|
||||
|
||||
if (matchesExpectedMessage) {
|
||||
// withoutStack: Check for unexpected/missing component stacks.
|
||||
// These checks can be simplified when withoutStack is removed.
|
||||
if (isLikelyAComponentStack(normalizedMessage)) {
|
||||
if (expectedWithoutStack === true && !hasErrorStack) {
|
||||
// Only report unexpected component stack if it's not an error stack
|
||||
// (error stacks look like component stacks after normalization)
|
||||
unexpectedIncludingComponentStack.push(normalizedMessage);
|
||||
}
|
||||
} else if (expectedWithoutStack !== true && !expectsErrorStack) {
|
||||
unexpectedMissingComponentStack.push(normalizedMessage);
|
||||
}
|
||||
|
||||
// Check for unexpected/missing error stacks
|
||||
if (hasErrorStack && !expectsErrorStack) {
|
||||
// Error stack is present but \n in <stack> was not in the expected message
|
||||
@@ -538,12 +451,7 @@ export function createLogAssertion(
|
||||
function printDiff() {
|
||||
return `${diff(
|
||||
expectedMessages
|
||||
.map(messageOrTuple => {
|
||||
const message = Array.isArray(messageOrTuple)
|
||||
? messageOrTuple[0]
|
||||
: messageOrTuple;
|
||||
return message.replace('\n', ' ');
|
||||
})
|
||||
.map(message => message.replace('\n', ' '))
|
||||
.join('\n'),
|
||||
receivedLogs.map(message => message.replace('\n', ' ')).join('\n'),
|
||||
{
|
||||
@@ -582,36 +490,6 @@ export function createLogAssertion(
|
||||
);
|
||||
}
|
||||
|
||||
// Any logs that include a component stack but shouldn't.
|
||||
if (unexpectedIncludingComponentStack.length > 0) {
|
||||
throwFormattedError(
|
||||
`${unexpectedIncludingComponentStack
|
||||
.map(
|
||||
stack =>
|
||||
`Unexpected component stack for:\n ${printReceived(stack)}`,
|
||||
)
|
||||
.join(
|
||||
'\n\n',
|
||||
)}\n\nIf this ${logName()} should include a component stack, remove {withoutStack: true} from this ${logName()}.` +
|
||||
`\nIf all ${logName()}s should include the component stack, you may need to remove {withoutStack: true} from the ${matcherName} call.`,
|
||||
);
|
||||
}
|
||||
|
||||
// Any logs that are missing a component stack without withoutStack.
|
||||
if (unexpectedMissingComponentStack.length > 0) {
|
||||
throwFormattedError(
|
||||
`${unexpectedMissingComponentStack
|
||||
.map(
|
||||
stack =>
|
||||
`Missing component stack for:\n ${printReceived(stack)}`,
|
||||
)
|
||||
.join(
|
||||
'\n\n',
|
||||
)}\n\nIf this ${logName()} should omit a component stack, pass [log, {withoutStack: true}].` +
|
||||
`\nIf all ${logName()}s should omit the component stack, add {withoutStack: true} to the ${matcherName} call.`,
|
||||
);
|
||||
}
|
||||
|
||||
// Any logs that include an error stack trace but \n in <stack> wasn't expected.
|
||||
if (unexpectedIncludingErrorStack.length > 0) {
|
||||
throwFormattedError(
|
||||
|
||||
+58
-88
@@ -1514,16 +1514,13 @@ describe('ReactFlight', () => {
|
||||
},
|
||||
};
|
||||
const transport = ReactNoopFlightServer.render(<input value={obj} />);
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||
'Objects with toJSON methods are not supported. ' +
|
||||
'Convert it manually to a simple value before passing it to props.\n' +
|
||||
' <input value={{toJSON: ...}}>\n' +
|
||||
' ^^^^^^^^^^^^^^^',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
assertConsoleErrorDev([
|
||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||
'Objects with toJSON methods are not supported. ' +
|
||||
'Convert it manually to a simple value before passing it to props.\n' +
|
||||
' <input value={{toJSON: ...}}>\n' +
|
||||
' ^^^^^^^^^^^^^^^',
|
||||
]);
|
||||
|
||||
ReactNoopFlightClient.read(transport);
|
||||
assertConsoleErrorDev([
|
||||
@@ -1545,14 +1542,11 @@ describe('ReactFlight', () => {
|
||||
const transport = ReactNoopFlightServer.render(
|
||||
<div>Womp womp: {new MyError('spaghetti')}</div>,
|
||||
);
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'Error objects cannot be rendered as text children. Try formatting it using toString().\n' +
|
||||
' <div>Womp womp: {Error}</div>\n' +
|
||||
' ^^^^^^^',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
assertConsoleErrorDev([
|
||||
'Error objects cannot be rendered as text children. Try formatting it using toString().\n' +
|
||||
' <div>Womp womp: {Error}</div>\n' +
|
||||
' ^^^^^^^',
|
||||
]);
|
||||
|
||||
ReactNoopFlightClient.read(transport);
|
||||
assertConsoleErrorDev([
|
||||
@@ -1565,15 +1559,12 @@ describe('ReactFlight', () => {
|
||||
|
||||
it('should warn in DEV if a special object is passed to a host component', () => {
|
||||
const transport = ReactNoopFlightServer.render(<input value={Math} />);
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||
'Math objects are not supported.\n' +
|
||||
' <input value={Math}>\n' +
|
||||
' ^^^^^^',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
assertConsoleErrorDev([
|
||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||
'Math objects are not supported.\n' +
|
||||
' <input value={Math}>\n' +
|
||||
' ^^^^^^',
|
||||
]);
|
||||
|
||||
ReactNoopFlightClient.read(transport);
|
||||
assertConsoleErrorDev([
|
||||
@@ -1589,15 +1580,12 @@ describe('ReactFlight', () => {
|
||||
const transport = ReactNoopFlightServer.render(
|
||||
<input value={{[Symbol.iterator]: {}}} />,
|
||||
);
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||
'Objects with symbol properties like Symbol.iterator are not supported.\n' +
|
||||
' <input value={{}}>\n' +
|
||||
' ^^^^',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
assertConsoleErrorDev([
|
||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||
'Objects with symbol properties like Symbol.iterator are not supported.\n' +
|
||||
' <input value={{}}>\n' +
|
||||
' ^^^^',
|
||||
]);
|
||||
|
||||
ReactNoopFlightClient.read(transport);
|
||||
assertConsoleErrorDev([
|
||||
@@ -1620,16 +1608,13 @@ describe('ReactFlight', () => {
|
||||
}
|
||||
const Client = clientReference(ClientImpl);
|
||||
const transport = ReactNoopFlightServer.render(<Client value={obj} />);
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||
'Objects with toJSON methods are not supported. ' +
|
||||
'Convert it manually to a simple value before passing it to props.\n' +
|
||||
' <... value={{toJSON: ...}}>\n' +
|
||||
' ^^^^^^^^^^^^^^^',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
assertConsoleErrorDev([
|
||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||
'Objects with toJSON methods are not supported. ' +
|
||||
'Convert it manually to a simple value before passing it to props.\n' +
|
||||
' <... value={{toJSON: ...}}>\n' +
|
||||
' ^^^^^^^^^^^^^^^',
|
||||
]);
|
||||
|
||||
ReactNoopFlightClient.read(transport);
|
||||
assertConsoleErrorDev([
|
||||
@@ -1655,16 +1640,13 @@ describe('ReactFlight', () => {
|
||||
const transport = ReactNoopFlightServer.render(
|
||||
<Client>Current date: {obj}</Client>,
|
||||
);
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||
'Objects with toJSON methods are not supported. ' +
|
||||
'Convert it manually to a simple value before passing it to props.\n' +
|
||||
' <>Current date: {{toJSON: ...}}</>\n' +
|
||||
' ^^^^^^^^^^^^^^^',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
assertConsoleErrorDev([
|
||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||
'Objects with toJSON methods are not supported. ' +
|
||||
'Convert it manually to a simple value before passing it to props.\n' +
|
||||
' <>Current date: {{toJSON: ...}}</>\n' +
|
||||
' ^^^^^^^^^^^^^^^',
|
||||
]);
|
||||
|
||||
ReactNoopFlightClient.read(transport);
|
||||
assertConsoleErrorDev([
|
||||
@@ -1683,15 +1665,12 @@ describe('ReactFlight', () => {
|
||||
}
|
||||
const Client = clientReference(ClientImpl);
|
||||
const transport = ReactNoopFlightServer.render(<Client value={Math} />);
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||
'Math objects are not supported.\n' +
|
||||
' <... value={Math}>\n' +
|
||||
' ^^^^^^',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
assertConsoleErrorDev([
|
||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||
'Math objects are not supported.\n' +
|
||||
' <... value={Math}>\n' +
|
||||
' ^^^^^^',
|
||||
]);
|
||||
|
||||
ReactNoopFlightClient.read(transport);
|
||||
assertConsoleErrorDev([
|
||||
@@ -1712,15 +1691,12 @@ describe('ReactFlight', () => {
|
||||
const transport = ReactNoopFlightServer.render(
|
||||
<Client value={{[Symbol.iterator]: {}}} />,
|
||||
);
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||
'Objects with symbol properties like Symbol.iterator are not supported.\n' +
|
||||
' <... value={{}}>\n' +
|
||||
' ^^^^',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
assertConsoleErrorDev([
|
||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||
'Objects with symbol properties like Symbol.iterator are not supported.\n' +
|
||||
' <... value={{}}>\n' +
|
||||
' ^^^^',
|
||||
]);
|
||||
|
||||
ReactNoopFlightClient.read(transport);
|
||||
|
||||
@@ -1744,13 +1720,10 @@ describe('ReactFlight', () => {
|
||||
ReactNoopFlightClient.read(transport);
|
||||
|
||||
assertConsoleErrorDev([
|
||||
[
|
||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||
'Objects with symbol properties like Symbol.iterator are not supported.\n' +
|
||||
' <... value={{}}>\n' +
|
||||
' ^^^^',
|
||||
{withoutStack: true},
|
||||
],
|
||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||
'Objects with symbol properties like Symbol.iterator are not supported.\n' +
|
||||
' <... value={{}}>\n' +
|
||||
' ^^^^',
|
||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||
'Objects with symbol properties like Symbol.iterator are not supported.\n' +
|
||||
' <... value={{}}>\n' +
|
||||
@@ -1769,13 +1742,10 @@ describe('ReactFlight', () => {
|
||||
);
|
||||
ReactNoopFlightClient.read(transport);
|
||||
assertConsoleErrorDev([
|
||||
[
|
||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||
'Math objects are not supported.\n' +
|
||||
' [..., Math, <h1/>]\n' +
|
||||
' ^^^^',
|
||||
{withoutStack: true},
|
||||
],
|
||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||
'Math objects are not supported.\n' +
|
||||
' [..., Math, <h1/>]\n' +
|
||||
' ^^^^',
|
||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||
'Math objects are not supported.\n' +
|
||||
' [..., Math, <h1/>]\n' +
|
||||
|
||||
+157
-193
@@ -642,35 +642,32 @@ describe('ReactComponentLifeCycle', () => {
|
||||
'https://react.dev/link/unsafe-component-lifecycles\n' +
|
||||
' in Component (at **)',
|
||||
]);
|
||||
assertConsoleWarnDev(
|
||||
[
|
||||
'componentWillMount has been renamed, and is not recommended for use. ' +
|
||||
'See https://react.dev/link/unsafe-component-lifecycles for details.\n\n' +
|
||||
'* Move code with side effects to componentDidMount, and set initial state in the constructor.\n' +
|
||||
'* Rename componentWillMount to UNSAFE_componentWillMount to suppress this warning in non-strict mode. ' +
|
||||
'In React 18.x, only the UNSAFE_ name will work. To rename all deprecated lifecycles to their new names, ' +
|
||||
'you can run `npx react-codemod rename-unsafe-lifecycles` in your project source folder.\n\n' +
|
||||
'Please update the following components: Component',
|
||||
'componentWillReceiveProps has been renamed, and is not recommended for use. ' +
|
||||
'See https://react.dev/link/unsafe-component-lifecycles for details.\n\n' +
|
||||
'* Move data fetching code or side effects to componentDidUpdate.\n' +
|
||||
"* If you're updating state whenever props change, refactor your code to use " +
|
||||
'memoization techniques or move it to static getDerivedStateFromProps. ' +
|
||||
'Learn more at: https://react.dev/link/derived-state\n' +
|
||||
'* Rename componentWillReceiveProps to UNSAFE_componentWillReceiveProps to suppress this warning in non-strict mode. ' +
|
||||
'In React 18.x, only the UNSAFE_ name will work. To rename all deprecated lifecycles to their new names, ' +
|
||||
'you can run `npx react-codemod rename-unsafe-lifecycles` in your project source folder.\n\n' +
|
||||
'Please update the following components: Component',
|
||||
'componentWillUpdate has been renamed, and is not recommended for use. ' +
|
||||
'See https://react.dev/link/unsafe-component-lifecycles for details.\n\n' +
|
||||
'* Move data fetching code or side effects to componentDidUpdate.\n' +
|
||||
'* Rename componentWillUpdate to UNSAFE_componentWillUpdate to suppress this warning in non-strict mode. ' +
|
||||
'In React 18.x, only the UNSAFE_ name will work. To rename all deprecated lifecycles to their new names, ' +
|
||||
'you can run `npx react-codemod rename-unsafe-lifecycles` in your project source folder.\n\n' +
|
||||
'Please update the following components: Component',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
assertConsoleWarnDev([
|
||||
'componentWillMount has been renamed, and is not recommended for use. ' +
|
||||
'See https://react.dev/link/unsafe-component-lifecycles for details.\n\n' +
|
||||
'* Move code with side effects to componentDidMount, and set initial state in the constructor.\n' +
|
||||
'* Rename componentWillMount to UNSAFE_componentWillMount to suppress this warning in non-strict mode. ' +
|
||||
'In React 18.x, only the UNSAFE_ name will work. To rename all deprecated lifecycles to their new names, ' +
|
||||
'you can run `npx react-codemod rename-unsafe-lifecycles` in your project source folder.\n\n' +
|
||||
'Please update the following components: Component',
|
||||
'componentWillReceiveProps has been renamed, and is not recommended for use. ' +
|
||||
'See https://react.dev/link/unsafe-component-lifecycles for details.\n\n' +
|
||||
'* Move data fetching code or side effects to componentDidUpdate.\n' +
|
||||
"* If you're updating state whenever props change, refactor your code to use " +
|
||||
'memoization techniques or move it to static getDerivedStateFromProps. ' +
|
||||
'Learn more at: https://react.dev/link/derived-state\n' +
|
||||
'* Rename componentWillReceiveProps to UNSAFE_componentWillReceiveProps to suppress this warning in non-strict mode. ' +
|
||||
'In React 18.x, only the UNSAFE_ name will work. To rename all deprecated lifecycles to their new names, ' +
|
||||
'you can run `npx react-codemod rename-unsafe-lifecycles` in your project source folder.\n\n' +
|
||||
'Please update the following components: Component',
|
||||
'componentWillUpdate has been renamed, and is not recommended for use. ' +
|
||||
'See https://react.dev/link/unsafe-component-lifecycles for details.\n\n' +
|
||||
'* Move data fetching code or side effects to componentDidUpdate.\n' +
|
||||
'* Rename componentWillUpdate to UNSAFE_componentWillUpdate to suppress this warning in non-strict mode. ' +
|
||||
'In React 18.x, only the UNSAFE_ name will work. To rename all deprecated lifecycles to their new names, ' +
|
||||
'you can run `npx react-codemod rename-unsafe-lifecycles` in your project source folder.\n\n' +
|
||||
'Please update the following components: Component',
|
||||
]);
|
||||
});
|
||||
|
||||
it('should not invoke deprecated lifecycles (cWM/cWRP/cWU) if new getSnapshotBeforeUpdate is present', async () => {
|
||||
@@ -708,35 +705,32 @@ describe('ReactComponentLifeCycle', () => {
|
||||
'https://react.dev/link/unsafe-component-lifecycles\n' +
|
||||
' in Component (at **)',
|
||||
]);
|
||||
assertConsoleWarnDev(
|
||||
[
|
||||
'componentWillMount has been renamed, and is not recommended for use. ' +
|
||||
'See https://react.dev/link/unsafe-component-lifecycles for details.\n\n' +
|
||||
'* Move code with side effects to componentDidMount, and set initial state in the constructor.\n' +
|
||||
'* Rename componentWillMount to UNSAFE_componentWillMount to suppress this warning in non-strict mode. ' +
|
||||
'In React 18.x, only the UNSAFE_ name will work. To rename all deprecated lifecycles to their new names, ' +
|
||||
'you can run `npx react-codemod rename-unsafe-lifecycles` in your project source folder.\n\n' +
|
||||
'Please update the following components: Component',
|
||||
'componentWillReceiveProps has been renamed, and is not recommended for use. ' +
|
||||
'See https://react.dev/link/unsafe-component-lifecycles for details.\n\n' +
|
||||
'* Move data fetching code or side effects to componentDidUpdate.\n' +
|
||||
"* If you're updating state whenever props change, refactor your code to use " +
|
||||
'memoization techniques or move it to static getDerivedStateFromProps. ' +
|
||||
'Learn more at: https://react.dev/link/derived-state\n' +
|
||||
'* Rename componentWillReceiveProps to UNSAFE_componentWillReceiveProps to suppress this warning in non-strict mode. ' +
|
||||
'In React 18.x, only the UNSAFE_ name will work. To rename all deprecated lifecycles to their new names, ' +
|
||||
'you can run `npx react-codemod rename-unsafe-lifecycles` in your project source folder.\n\n' +
|
||||
'Please update the following components: Component',
|
||||
'componentWillUpdate has been renamed, and is not recommended for use. ' +
|
||||
'See https://react.dev/link/unsafe-component-lifecycles for details.\n\n' +
|
||||
'* Move data fetching code or side effects to componentDidUpdate.\n' +
|
||||
'* Rename componentWillUpdate to UNSAFE_componentWillUpdate to suppress this warning in non-strict mode. ' +
|
||||
'In React 18.x, only the UNSAFE_ name will work. To rename all deprecated lifecycles to their new names, ' +
|
||||
'you can run `npx react-codemod rename-unsafe-lifecycles` in your project source folder.\n\n' +
|
||||
'Please update the following components: Component',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
assertConsoleWarnDev([
|
||||
'componentWillMount has been renamed, and is not recommended for use. ' +
|
||||
'See https://react.dev/link/unsafe-component-lifecycles for details.\n\n' +
|
||||
'* Move code with side effects to componentDidMount, and set initial state in the constructor.\n' +
|
||||
'* Rename componentWillMount to UNSAFE_componentWillMount to suppress this warning in non-strict mode. ' +
|
||||
'In React 18.x, only the UNSAFE_ name will work. To rename all deprecated lifecycles to their new names, ' +
|
||||
'you can run `npx react-codemod rename-unsafe-lifecycles` in your project source folder.\n\n' +
|
||||
'Please update the following components: Component',
|
||||
'componentWillReceiveProps has been renamed, and is not recommended for use. ' +
|
||||
'See https://react.dev/link/unsafe-component-lifecycles for details.\n\n' +
|
||||
'* Move data fetching code or side effects to componentDidUpdate.\n' +
|
||||
"* If you're updating state whenever props change, refactor your code to use " +
|
||||
'memoization techniques or move it to static getDerivedStateFromProps. ' +
|
||||
'Learn more at: https://react.dev/link/derived-state\n' +
|
||||
'* Rename componentWillReceiveProps to UNSAFE_componentWillReceiveProps to suppress this warning in non-strict mode. ' +
|
||||
'In React 18.x, only the UNSAFE_ name will work. To rename all deprecated lifecycles to their new names, ' +
|
||||
'you can run `npx react-codemod rename-unsafe-lifecycles` in your project source folder.\n\n' +
|
||||
'Please update the following components: Component',
|
||||
'componentWillUpdate has been renamed, and is not recommended for use. ' +
|
||||
'See https://react.dev/link/unsafe-component-lifecycles for details.\n\n' +
|
||||
'* Move data fetching code or side effects to componentDidUpdate.\n' +
|
||||
'* Rename componentWillUpdate to UNSAFE_componentWillUpdate to suppress this warning in non-strict mode. ' +
|
||||
'In React 18.x, only the UNSAFE_ name will work. To rename all deprecated lifecycles to their new names, ' +
|
||||
'you can run `npx react-codemod rename-unsafe-lifecycles` in your project source folder.\n\n' +
|
||||
'Please update the following components: Component',
|
||||
]);
|
||||
|
||||
await act(() => {
|
||||
root.render(<Component value={2} />);
|
||||
@@ -810,25 +804,22 @@ describe('ReactComponentLifeCycle', () => {
|
||||
'https://react.dev/link/unsafe-component-lifecycles\n' +
|
||||
' in AllLegacyLifecycles (at **)',
|
||||
]);
|
||||
assertConsoleWarnDev(
|
||||
[
|
||||
'componentWillMount has been renamed, and is not recommended for use. ' +
|
||||
'See https://react.dev/link/unsafe-component-lifecycles for details.\n\n' +
|
||||
'* Move code with side effects to componentDidMount, and set initial state in the constructor.\n' +
|
||||
'* Rename componentWillMount to UNSAFE_componentWillMount to suppress this warning in non-strict mode. ' +
|
||||
'In React 18.x, only the UNSAFE_ name will work. To rename all deprecated lifecycles to their new names, ' +
|
||||
'you can run `npx react-codemod rename-unsafe-lifecycles` in your project source folder.\n\n' +
|
||||
'Please update the following components: AllLegacyLifecycles',
|
||||
'componentWillUpdate has been renamed, and is not recommended for use. ' +
|
||||
'See https://react.dev/link/unsafe-component-lifecycles for details.\n\n' +
|
||||
'* Move data fetching code or side effects to componentDidUpdate.\n' +
|
||||
'* Rename componentWillUpdate to UNSAFE_componentWillUpdate to suppress this warning in non-strict mode. ' +
|
||||
'In React 18.x, only the UNSAFE_ name will work. To rename all deprecated lifecycles to their new names, ' +
|
||||
'you can run `npx react-codemod rename-unsafe-lifecycles` in your project source folder.\n\n' +
|
||||
'Please update the following components: AllLegacyLifecycles',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
assertConsoleWarnDev([
|
||||
'componentWillMount has been renamed, and is not recommended for use. ' +
|
||||
'See https://react.dev/link/unsafe-component-lifecycles for details.\n\n' +
|
||||
'* Move code with side effects to componentDidMount, and set initial state in the constructor.\n' +
|
||||
'* Rename componentWillMount to UNSAFE_componentWillMount to suppress this warning in non-strict mode. ' +
|
||||
'In React 18.x, only the UNSAFE_ name will work. To rename all deprecated lifecycles to their new names, ' +
|
||||
'you can run `npx react-codemod rename-unsafe-lifecycles` in your project source folder.\n\n' +
|
||||
'Please update the following components: AllLegacyLifecycles',
|
||||
'componentWillUpdate has been renamed, and is not recommended for use. ' +
|
||||
'See https://react.dev/link/unsafe-component-lifecycles for details.\n\n' +
|
||||
'* Move data fetching code or side effects to componentDidUpdate.\n' +
|
||||
'* Rename componentWillUpdate to UNSAFE_componentWillUpdate to suppress this warning in non-strict mode. ' +
|
||||
'In React 18.x, only the UNSAFE_ name will work. To rename all deprecated lifecycles to their new names, ' +
|
||||
'you can run `npx react-codemod rename-unsafe-lifecycles` in your project source folder.\n\n' +
|
||||
'Please update the following components: AllLegacyLifecycles',
|
||||
]);
|
||||
|
||||
class WillMount extends React.Component {
|
||||
state = {};
|
||||
@@ -877,18 +868,15 @@ describe('ReactComponentLifeCycle', () => {
|
||||
'https://react.dev/link/unsafe-component-lifecycles\n' +
|
||||
' in WillMountAndUpdate (at **)',
|
||||
]);
|
||||
assertConsoleWarnDev(
|
||||
[
|
||||
'componentWillMount has been renamed, and is not recommended for use. ' +
|
||||
'See https://react.dev/link/unsafe-component-lifecycles for details.\n\n' +
|
||||
'* Move code with side effects to componentDidMount, and set initial state in the constructor.\n' +
|
||||
'* Rename componentWillMount to UNSAFE_componentWillMount to suppress this warning in non-strict mode. ' +
|
||||
'In React 18.x, only the UNSAFE_ name will work. To rename all deprecated lifecycles to their new names, ' +
|
||||
'you can run `npx react-codemod rename-unsafe-lifecycles` in your project source folder.\n\n' +
|
||||
'Please update the following components: WillMountAndUpdate',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
assertConsoleWarnDev([
|
||||
'componentWillMount has been renamed, and is not recommended for use. ' +
|
||||
'See https://react.dev/link/unsafe-component-lifecycles for details.\n\n' +
|
||||
'* Move code with side effects to componentDidMount, and set initial state in the constructor.\n' +
|
||||
'* Rename componentWillMount to UNSAFE_componentWillMount to suppress this warning in non-strict mode. ' +
|
||||
'In React 18.x, only the UNSAFE_ name will work. To rename all deprecated lifecycles to their new names, ' +
|
||||
'you can run `npx react-codemod rename-unsafe-lifecycles` in your project source folder.\n\n' +
|
||||
'Please update the following components: WillMountAndUpdate',
|
||||
]);
|
||||
|
||||
class WillReceiveProps extends React.Component {
|
||||
state = {};
|
||||
@@ -912,23 +900,18 @@ describe('ReactComponentLifeCycle', () => {
|
||||
'https://react.dev/link/unsafe-component-lifecycles\n' +
|
||||
' in WillReceiveProps (at **)',
|
||||
]);
|
||||
assertConsoleWarnDev(
|
||||
[
|
||||
'componentWillReceiveProps has been renamed, and is not recommended for use. ' +
|
||||
'See https://react.dev/link/unsafe-component-lifecycles for details.\n\n' +
|
||||
'* Move data fetching code or side effects to componentDidUpdate.\n' +
|
||||
"* If you're updating state whenever props change, refactor your code to use " +
|
||||
'memoization techniques or move it to static getDerivedStateFromProps. ' +
|
||||
'Learn more at: https://react.dev/link/derived-state\n' +
|
||||
'* Rename componentWillReceiveProps to UNSAFE_componentWillReceiveProps to suppress this warning in non-strict mode. ' +
|
||||
'In React 18.x, only the UNSAFE_ name will work. To rename all deprecated lifecycles to their new names, ' +
|
||||
'you can run `npx react-codemod rename-unsafe-lifecycles` in your project source folder.\n\n' +
|
||||
'Please update the following components: WillReceiveProps',
|
||||
],
|
||||
{
|
||||
withoutStack: true,
|
||||
},
|
||||
);
|
||||
assertConsoleWarnDev([
|
||||
'componentWillReceiveProps has been renamed, and is not recommended for use. ' +
|
||||
'See https://react.dev/link/unsafe-component-lifecycles for details.\n\n' +
|
||||
'* Move data fetching code or side effects to componentDidUpdate.\n' +
|
||||
"* If you're updating state whenever props change, refactor your code to use " +
|
||||
'memoization techniques or move it to static getDerivedStateFromProps. ' +
|
||||
'Learn more at: https://react.dev/link/derived-state\n' +
|
||||
'* Rename componentWillReceiveProps to UNSAFE_componentWillReceiveProps to suppress this warning in non-strict mode. ' +
|
||||
'In React 18.x, only the UNSAFE_ name will work. To rename all deprecated lifecycles to their new names, ' +
|
||||
'you can run `npx react-codemod rename-unsafe-lifecycles` in your project source folder.\n\n' +
|
||||
'Please update the following components: WillReceiveProps',
|
||||
]);
|
||||
});
|
||||
|
||||
it('should warn about deprecated lifecycles (cWM/cWRP/cWU) if new getSnapshotBeforeUpdate is present', async () => {
|
||||
@@ -958,25 +941,22 @@ describe('ReactComponentLifeCycle', () => {
|
||||
'https://react.dev/link/unsafe-component-lifecycles\n' +
|
||||
' in AllLegacyLifecycles (at **)',
|
||||
]);
|
||||
assertConsoleWarnDev(
|
||||
[
|
||||
'componentWillMount has been renamed, and is not recommended for use. ' +
|
||||
'See https://react.dev/link/unsafe-component-lifecycles for details.\n\n' +
|
||||
'* Move code with side effects to componentDidMount, and set initial state in the constructor.\n' +
|
||||
'* Rename componentWillMount to UNSAFE_componentWillMount to suppress this warning in non-strict mode. ' +
|
||||
'In React 18.x, only the UNSAFE_ name will work. To rename all deprecated lifecycles to their new names, ' +
|
||||
'you can run `npx react-codemod rename-unsafe-lifecycles` in your project source folder.\n\n' +
|
||||
'Please update the following components: AllLegacyLifecycles',
|
||||
'componentWillUpdate has been renamed, and is not recommended for use. ' +
|
||||
'See https://react.dev/link/unsafe-component-lifecycles for details.\n\n' +
|
||||
'* Move data fetching code or side effects to componentDidUpdate.\n' +
|
||||
'* Rename componentWillUpdate to UNSAFE_componentWillUpdate to suppress this warning in non-strict mode. ' +
|
||||
'In React 18.x, only the UNSAFE_ name will work. To rename all deprecated lifecycles to their new names, ' +
|
||||
'you can run `npx react-codemod rename-unsafe-lifecycles` in your project source folder.\n\n' +
|
||||
'Please update the following components: AllLegacyLifecycles',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
assertConsoleWarnDev([
|
||||
'componentWillMount has been renamed, and is not recommended for use. ' +
|
||||
'See https://react.dev/link/unsafe-component-lifecycles for details.\n\n' +
|
||||
'* Move code with side effects to componentDidMount, and set initial state in the constructor.\n' +
|
||||
'* Rename componentWillMount to UNSAFE_componentWillMount to suppress this warning in non-strict mode. ' +
|
||||
'In React 18.x, only the UNSAFE_ name will work. To rename all deprecated lifecycles to their new names, ' +
|
||||
'you can run `npx react-codemod rename-unsafe-lifecycles` in your project source folder.\n\n' +
|
||||
'Please update the following components: AllLegacyLifecycles',
|
||||
'componentWillUpdate has been renamed, and is not recommended for use. ' +
|
||||
'See https://react.dev/link/unsafe-component-lifecycles for details.\n\n' +
|
||||
'* Move data fetching code or side effects to componentDidUpdate.\n' +
|
||||
'* Rename componentWillUpdate to UNSAFE_componentWillUpdate to suppress this warning in non-strict mode. ' +
|
||||
'In React 18.x, only the UNSAFE_ name will work. To rename all deprecated lifecycles to their new names, ' +
|
||||
'you can run `npx react-codemod rename-unsafe-lifecycles` in your project source folder.\n\n' +
|
||||
'Please update the following components: AllLegacyLifecycles',
|
||||
]);
|
||||
|
||||
class WillMount extends React.Component {
|
||||
state = {};
|
||||
@@ -1023,20 +1003,15 @@ describe('ReactComponentLifeCycle', () => {
|
||||
'https://react.dev/link/unsafe-component-lifecycles\n' +
|
||||
' in WillMountAndUpdate (at **)',
|
||||
]);
|
||||
assertConsoleWarnDev(
|
||||
[
|
||||
'componentWillMount has been renamed, and is not recommended for use. ' +
|
||||
'See https://react.dev/link/unsafe-component-lifecycles for details.\n\n' +
|
||||
'* Move code with side effects to componentDidMount, and set initial state in the constructor.\n' +
|
||||
'* Rename componentWillMount to UNSAFE_componentWillMount to suppress this warning in non-strict mode. ' +
|
||||
'In React 18.x, only the UNSAFE_ name will work. To rename all deprecated lifecycles to their new names, ' +
|
||||
'you can run `npx react-codemod rename-unsafe-lifecycles` in your project source folder.\n\n' +
|
||||
'Please update the following components: WillMountAndUpdate',
|
||||
],
|
||||
{
|
||||
withoutStack: true,
|
||||
},
|
||||
);
|
||||
assertConsoleWarnDev([
|
||||
'componentWillMount has been renamed, and is not recommended for use. ' +
|
||||
'See https://react.dev/link/unsafe-component-lifecycles for details.\n\n' +
|
||||
'* Move code with side effects to componentDidMount, and set initial state in the constructor.\n' +
|
||||
'* Rename componentWillMount to UNSAFE_componentWillMount to suppress this warning in non-strict mode. ' +
|
||||
'In React 18.x, only the UNSAFE_ name will work. To rename all deprecated lifecycles to their new names, ' +
|
||||
'you can run `npx react-codemod rename-unsafe-lifecycles` in your project source folder.\n\n' +
|
||||
'Please update the following components: WillMountAndUpdate',
|
||||
]);
|
||||
|
||||
class WillReceiveProps extends React.Component {
|
||||
state = {};
|
||||
@@ -1059,23 +1034,18 @@ describe('ReactComponentLifeCycle', () => {
|
||||
'https://react.dev/link/unsafe-component-lifecycles\n' +
|
||||
' in WillReceiveProps (at **)',
|
||||
]);
|
||||
assertConsoleWarnDev(
|
||||
[
|
||||
'componentWillReceiveProps has been renamed, and is not recommended for use. ' +
|
||||
'See https://react.dev/link/unsafe-component-lifecycles for details.\n\n' +
|
||||
'* Move data fetching code or side effects to componentDidUpdate.\n' +
|
||||
"* If you're updating state whenever props change, refactor your code to use " +
|
||||
'memoization techniques or move it to static getDerivedStateFromProps. ' +
|
||||
'Learn more at: https://react.dev/link/derived-state\n' +
|
||||
'* Rename componentWillReceiveProps to UNSAFE_componentWillReceiveProps to suppress this warning in non-strict mode. ' +
|
||||
'In React 18.x, only the UNSAFE_ name will work. To rename all deprecated lifecycles to their new names, ' +
|
||||
'you can run `npx react-codemod rename-unsafe-lifecycles` in your project source folder.\n\n' +
|
||||
'Please update the following components: WillReceiveProps',
|
||||
],
|
||||
{
|
||||
withoutStack: true,
|
||||
},
|
||||
);
|
||||
assertConsoleWarnDev([
|
||||
'componentWillReceiveProps has been renamed, and is not recommended for use. ' +
|
||||
'See https://react.dev/link/unsafe-component-lifecycles for details.\n\n' +
|
||||
'* Move data fetching code or side effects to componentDidUpdate.\n' +
|
||||
"* If you're updating state whenever props change, refactor your code to use " +
|
||||
'memoization techniques or move it to static getDerivedStateFromProps. ' +
|
||||
'Learn more at: https://react.dev/link/derived-state\n' +
|
||||
'* Rename componentWillReceiveProps to UNSAFE_componentWillReceiveProps to suppress this warning in non-strict mode. ' +
|
||||
'In React 18.x, only the UNSAFE_ name will work. To rename all deprecated lifecycles to their new names, ' +
|
||||
'you can run `npx react-codemod rename-unsafe-lifecycles` in your project source folder.\n\n' +
|
||||
'Please update the following components: WillReceiveProps',
|
||||
]);
|
||||
});
|
||||
|
||||
it('should warn if getDerivedStateFromProps returns undefined', async () => {
|
||||
@@ -1162,35 +1132,32 @@ describe('ReactComponentLifeCycle', () => {
|
||||
await act(() => {
|
||||
root.render(<MyComponent foo="bar" />);
|
||||
});
|
||||
assertConsoleWarnDev(
|
||||
[
|
||||
'componentWillMount has been renamed, and is not recommended for use. ' +
|
||||
'See https://react.dev/link/unsafe-component-lifecycles for details.\n\n' +
|
||||
'* Move code with side effects to componentDidMount, and set initial state in the constructor.\n' +
|
||||
'* Rename componentWillMount to UNSAFE_componentWillMount to suppress this warning in non-strict mode. ' +
|
||||
'In React 18.x, only the UNSAFE_ name will work. To rename all deprecated lifecycles to their new names, ' +
|
||||
'you can run `npx react-codemod rename-unsafe-lifecycles` in your project source folder.\n\n' +
|
||||
'Please update the following components: MyComponent',
|
||||
'componentWillReceiveProps has been renamed, and is not recommended for use. ' +
|
||||
'See https://react.dev/link/unsafe-component-lifecycles for details.\n\n' +
|
||||
'* Move data fetching code or side effects to componentDidUpdate.\n' +
|
||||
"* If you're updating state whenever props change, refactor your code to use " +
|
||||
'memoization techniques or move it to static getDerivedStateFromProps. ' +
|
||||
'Learn more at: https://react.dev/link/derived-state\n' +
|
||||
'* Rename componentWillReceiveProps to UNSAFE_componentWillReceiveProps to suppress this warning in non-strict mode. ' +
|
||||
'In React 18.x, only the UNSAFE_ name will work. To rename all deprecated lifecycles to their new names, ' +
|
||||
'you can run `npx react-codemod rename-unsafe-lifecycles` in your project source folder.\n\n' +
|
||||
'Please update the following components: MyComponent',
|
||||
'componentWillUpdate has been renamed, and is not recommended for use. ' +
|
||||
'See https://react.dev/link/unsafe-component-lifecycles for details.\n\n' +
|
||||
'* Move data fetching code or side effects to componentDidUpdate.\n' +
|
||||
'* Rename componentWillUpdate to UNSAFE_componentWillUpdate to suppress this warning in non-strict mode. ' +
|
||||
'In React 18.x, only the UNSAFE_ name will work. To rename all deprecated lifecycles to their new names, ' +
|
||||
'you can run `npx react-codemod rename-unsafe-lifecycles` in your project source folder.\n\n' +
|
||||
'Please update the following components: MyComponent',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
assertConsoleWarnDev([
|
||||
'componentWillMount has been renamed, and is not recommended for use. ' +
|
||||
'See https://react.dev/link/unsafe-component-lifecycles for details.\n\n' +
|
||||
'* Move code with side effects to componentDidMount, and set initial state in the constructor.\n' +
|
||||
'* Rename componentWillMount to UNSAFE_componentWillMount to suppress this warning in non-strict mode. ' +
|
||||
'In React 18.x, only the UNSAFE_ name will work. To rename all deprecated lifecycles to their new names, ' +
|
||||
'you can run `npx react-codemod rename-unsafe-lifecycles` in your project source folder.\n\n' +
|
||||
'Please update the following components: MyComponent',
|
||||
'componentWillReceiveProps has been renamed, and is not recommended for use. ' +
|
||||
'See https://react.dev/link/unsafe-component-lifecycles for details.\n\n' +
|
||||
'* Move data fetching code or side effects to componentDidUpdate.\n' +
|
||||
"* If you're updating state whenever props change, refactor your code to use " +
|
||||
'memoization techniques or move it to static getDerivedStateFromProps. ' +
|
||||
'Learn more at: https://react.dev/link/derived-state\n' +
|
||||
'* Rename componentWillReceiveProps to UNSAFE_componentWillReceiveProps to suppress this warning in non-strict mode. ' +
|
||||
'In React 18.x, only the UNSAFE_ name will work. To rename all deprecated lifecycles to their new names, ' +
|
||||
'you can run `npx react-codemod rename-unsafe-lifecycles` in your project source folder.\n\n' +
|
||||
'Please update the following components: MyComponent',
|
||||
'componentWillUpdate has been renamed, and is not recommended for use. ' +
|
||||
'See https://react.dev/link/unsafe-component-lifecycles for details.\n\n' +
|
||||
'* Move data fetching code or side effects to componentDidUpdate.\n' +
|
||||
'* Rename componentWillUpdate to UNSAFE_componentWillUpdate to suppress this warning in non-strict mode. ' +
|
||||
'In React 18.x, only the UNSAFE_ name will work. To rename all deprecated lifecycles to their new names, ' +
|
||||
'you can run `npx react-codemod rename-unsafe-lifecycles` in your project source folder.\n\n' +
|
||||
'Please update the following components: MyComponent',
|
||||
]);
|
||||
expect(log).toEqual(['componentWillMount', 'UNSAFE_componentWillMount']);
|
||||
|
||||
log.length = 0;
|
||||
@@ -1488,30 +1455,27 @@ describe('ReactComponentLifeCycle', () => {
|
||||
await act(() => {
|
||||
root.render(<MyComponent x={1} />);
|
||||
});
|
||||
assertConsoleWarnDev(
|
||||
[
|
||||
`componentWillMount has been renamed, and is not recommended for use. See https://react.dev/link/unsafe-component-lifecycles for details.
|
||||
assertConsoleWarnDev([
|
||||
`componentWillMount has been renamed, and is not recommended for use. See https://react.dev/link/unsafe-component-lifecycles for details.
|
||||
|
||||
* Move code with side effects to componentDidMount, and set initial state in the constructor.
|
||||
* Rename componentWillMount to UNSAFE_componentWillMount to suppress this warning in non-strict mode. In React 18.x, only the UNSAFE_ name will work. To rename all deprecated lifecycles to their new names, you can run \`npx react-codemod rename-unsafe-lifecycles\` in your project source folder.
|
||||
|
||||
Please update the following components: MyComponent`,
|
||||
`componentWillReceiveProps has been renamed, and is not recommended for use. See https://react.dev/link/unsafe-component-lifecycles for details.
|
||||
`componentWillReceiveProps has been renamed, and is not recommended for use. See https://react.dev/link/unsafe-component-lifecycles for details.
|
||||
|
||||
* Move data fetching code or side effects to componentDidUpdate.
|
||||
* If you're updating state whenever props change, refactor your code to use memoization techniques or move it to static getDerivedStateFromProps. Learn more at: https://react.dev/link/derived-state
|
||||
* Rename componentWillReceiveProps to UNSAFE_componentWillReceiveProps to suppress this warning in non-strict mode. In React 18.x, only the UNSAFE_ name will work. To rename all deprecated lifecycles to their new names, you can run \`npx react-codemod rename-unsafe-lifecycles\` in your project source folder.
|
||||
|
||||
Please update the following components: MyComponent`,
|
||||
`componentWillUpdate has been renamed, and is not recommended for use. See https://react.dev/link/unsafe-component-lifecycles for details.
|
||||
`componentWillUpdate has been renamed, and is not recommended for use. See https://react.dev/link/unsafe-component-lifecycles for details.
|
||||
|
||||
* Move data fetching code or side effects to componentDidUpdate.
|
||||
* Rename componentWillUpdate to UNSAFE_componentWillUpdate to suppress this warning in non-strict mode. In React 18.x, only the UNSAFE_ name will work. To rename all deprecated lifecycles to their new names, you can run \`npx react-codemod rename-unsafe-lifecycles\` in your project source folder.
|
||||
|
||||
Please update the following components: MyComponent`,
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
]);
|
||||
|
||||
// Dedupe check (update and instantiate new)
|
||||
await act(() => {
|
||||
|
||||
+24
-42
@@ -195,13 +195,10 @@ describe('ReactDOM', () => {
|
||||
'Invalid argument passed as callback. Expected a function. Instead ' +
|
||||
'received: no',
|
||||
);
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'Expected the last optional `callback` argument to be a function. Instead received: no.',
|
||||
'Expected the last optional `callback` argument to be a function. Instead received: no.',
|
||||
],
|
||||
{withoutStack: 2},
|
||||
);
|
||||
assertConsoleErrorDev([
|
||||
'Expected the last optional `callback` argument to be a function. Instead received: no.',
|
||||
'Expected the last optional `callback` argument to be a function. Instead received: no.',
|
||||
]);
|
||||
|
||||
await expect(async () => {
|
||||
await act(() => {
|
||||
@@ -211,13 +208,10 @@ describe('ReactDOM', () => {
|
||||
'Invalid argument passed as callback. Expected a function. Instead ' +
|
||||
'received: [object Object]',
|
||||
);
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
"Expected the last optional `callback` argument to be a function. Instead received: { foo: 'bar' }",
|
||||
"Expected the last optional `callback` argument to be a function. Instead received: { foo: 'bar' }.",
|
||||
],
|
||||
{withoutStack: 2},
|
||||
);
|
||||
assertConsoleErrorDev([
|
||||
"Expected the last optional `callback` argument to be a function. Instead received: { foo: 'bar' }",
|
||||
"Expected the last optional `callback` argument to be a function. Instead received: { foo: 'bar' }.",
|
||||
]);
|
||||
|
||||
await expect(async () => {
|
||||
await act(() => {
|
||||
@@ -227,13 +221,10 @@ describe('ReactDOM', () => {
|
||||
'Invalid argument passed as callback. Expected a function. Instead ' +
|
||||
'received: [object Object]',
|
||||
);
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'Expected the last optional `callback` argument to be a function. Instead received: Foo { a: 1, b: 2 }.',
|
||||
'Expected the last optional `callback` argument to be a function. Instead received: Foo { a: 1, b: 2 }.',
|
||||
],
|
||||
{withoutStack: 2},
|
||||
);
|
||||
assertConsoleErrorDev([
|
||||
'Expected the last optional `callback` argument to be a function. Instead received: Foo { a: 1, b: 2 }.',
|
||||
'Expected the last optional `callback` argument to be a function. Instead received: Foo { a: 1, b: 2 }.',
|
||||
]);
|
||||
});
|
||||
|
||||
// @gate !disableLegacyMode
|
||||
@@ -261,13 +252,10 @@ describe('ReactDOM', () => {
|
||||
'Invalid argument passed as callback. Expected a function. Instead ' +
|
||||
'received: no',
|
||||
);
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'Expected the last optional `callback` argument to be a function. Instead received: no.',
|
||||
'Expected the last optional `callback` argument to be a function. Instead received: no.',
|
||||
],
|
||||
{withoutStack: 2},
|
||||
);
|
||||
assertConsoleErrorDev([
|
||||
'Expected the last optional `callback` argument to be a function. Instead received: no.',
|
||||
'Expected the last optional `callback` argument to be a function. Instead received: no.',
|
||||
]);
|
||||
|
||||
ReactDOM.render(<A />, myDiv); // Re-mount
|
||||
await expect(async () => {
|
||||
@@ -278,13 +266,10 @@ describe('ReactDOM', () => {
|
||||
'Invalid argument passed as callback. Expected a function. Instead ' +
|
||||
'received: [object Object]',
|
||||
);
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
"Expected the last optional `callback` argument to be a function. Instead received: { foo: 'bar' }.",
|
||||
"Expected the last optional `callback` argument to be a function. Instead received: { foo: 'bar' }.",
|
||||
],
|
||||
{withoutStack: 2},
|
||||
);
|
||||
assertConsoleErrorDev([
|
||||
"Expected the last optional `callback` argument to be a function. Instead received: { foo: 'bar' }.",
|
||||
"Expected the last optional `callback` argument to be a function. Instead received: { foo: 'bar' }.",
|
||||
]);
|
||||
|
||||
ReactDOM.render(<A />, myDiv); // Re-mount
|
||||
await expect(async () => {
|
||||
@@ -295,13 +280,10 @@ describe('ReactDOM', () => {
|
||||
'Invalid argument passed as callback. Expected a function. Instead ' +
|
||||
'received: [object Object]',
|
||||
);
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'Expected the last optional `callback` argument to be a function. Instead received: Foo { a: 1, b: 2 }.',
|
||||
'Expected the last optional `callback` argument to be a function. Instead received: Foo { a: 1, b: 2 }.',
|
||||
],
|
||||
{withoutStack: 2},
|
||||
);
|
||||
assertConsoleErrorDev([
|
||||
'Expected the last optional `callback` argument to be a function. Instead received: Foo { a: 1, b: 2 }.',
|
||||
'Expected the last optional `callback` argument to be a function. Instead received: Foo { a: 1, b: 2 }.',
|
||||
]);
|
||||
});
|
||||
|
||||
it('preserves focus', async () => {
|
||||
|
||||
+9
-24
@@ -3590,14 +3590,11 @@ describe('ReactDOMFizzServer', () => {
|
||||
onRecoverableError(error, errorInfo) {
|
||||
expect(error.digest).toBe('a digest');
|
||||
expect(errorInfo.digest).toBe(undefined);
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'You are accessing "digest" from the errorInfo object passed to onRecoverableError.' +
|
||||
' This property is no longer provided as part of errorInfo but can be accessed as a property' +
|
||||
' of the Error instance itself.',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
assertConsoleErrorDev([
|
||||
'You are accessing "digest" from the errorInfo object passed to onRecoverableError.' +
|
||||
' This property is no longer provided as part of errorInfo but can be accessed as a property' +
|
||||
' of the Error instance itself.',
|
||||
]);
|
||||
},
|
||||
},
|
||||
);
|
||||
@@ -7770,10 +7767,7 @@ describe('ReactDOMFizzServer', () => {
|
||||
</html>,
|
||||
);
|
||||
assertConsoleErrorDev([
|
||||
[
|
||||
'Cannot render a <meta> outside the main document if it has an `itemProp` prop. `itemProp` suggests the tag belongs to an `itemScope` which can appear anywhere in the DOM. If you were intending for React to hoist this <meta> remove the `itemProp` prop. Otherwise, try moving this tag into the <head> or <body> of the Document.',
|
||||
{withoutStack: true},
|
||||
],
|
||||
'Cannot render a <meta> outside the main document if it has an `itemProp` prop. `itemProp` suggests the tag belongs to an `itemScope` which can appear anywhere in the DOM. If you were intending for React to hoist this <meta> remove the `itemProp` prop. Otherwise, try moving this tag into the <head> or <body> of the Document.',
|
||||
'In HTML, <meta> cannot be a child of <html>.\nThis will cause a hydration error.' +
|
||||
'\n' +
|
||||
'\n <App>' +
|
||||
@@ -7788,10 +7782,7 @@ describe('ReactDOMFizzServer', () => {
|
||||
'<html> cannot contain a nested <meta>.\nSee this log for the ancestor stack trace.' +
|
||||
'\n in html (at **)' +
|
||||
'\n in App (at **)',
|
||||
[
|
||||
'Cannot render a <meta> outside the main document if it has an `itemProp` prop. `itemProp` suggests the tag belongs to an `itemScope` which can appear anywhere in the DOM. If you were intending for React to hoist this <meta> remove the `itemProp` prop. Otherwise, try moving this tag into the <head> or <body> of the Document.',
|
||||
{withoutStack: true},
|
||||
],
|
||||
'Cannot render a <meta> outside the main document if it has an `itemProp` prop. `itemProp` suggests the tag belongs to an `itemScope` which can appear anywhere in the DOM. If you were intending for React to hoist this <meta> remove the `itemProp` prop. Otherwise, try moving this tag into the <head> or <body> of the Document.',
|
||||
]);
|
||||
|
||||
await root.unmount();
|
||||
@@ -7886,10 +7877,7 @@ describe('ReactDOMFizzServer', () => {
|
||||
</html>,
|
||||
);
|
||||
assertConsoleErrorDev([
|
||||
[
|
||||
'Cannot render a <meta> outside the main document if it has an `itemProp` prop. `itemProp` suggests the tag belongs to an `itemScope` which can appear anywhere in the DOM. If you were intending for React to hoist this <meta> remove the `itemProp` prop. Otherwise, try moving this tag into the <head> or <body> of the Document.',
|
||||
{withoutStack: true},
|
||||
],
|
||||
'Cannot render a <meta> outside the main document if it has an `itemProp` prop. `itemProp` suggests the tag belongs to an `itemScope` which can appear anywhere in the DOM. If you were intending for React to hoist this <meta> remove the `itemProp` prop. Otherwise, try moving this tag into the <head> or <body> of the Document.',
|
||||
'In HTML, <meta> cannot be a child of <html>.\nThis will cause a hydration error.' +
|
||||
'\n' +
|
||||
'\n <App>' +
|
||||
@@ -7904,10 +7892,7 @@ describe('ReactDOMFizzServer', () => {
|
||||
'<html> cannot contain a nested <meta>.\nSee this log for the ancestor stack trace.' +
|
||||
'\n in html (at **)' +
|
||||
'\n in App (at **)',
|
||||
[
|
||||
'Cannot render a <meta> outside the main document if it has an `itemProp` prop. `itemProp` suggests the tag belongs to an `itemScope` which can appear anywhere in the DOM. If you were intending for React to hoist this <meta> remove the `itemProp` prop. Otherwise, try moving this tag into the <head> or <body> of the Document.',
|
||||
{withoutStack: true},
|
||||
],
|
||||
'Cannot render a <meta> outside the main document if it has an `itemProp` prop. `itemProp` suggests the tag belongs to an `itemScope` which can appear anywhere in the DOM. If you were intending for React to hoist this <meta> remove the `itemProp` prop. Otherwise, try moving this tag into the <head> or <body> of the Document.',
|
||||
]);
|
||||
|
||||
await root.unmount();
|
||||
|
||||
+8
-17
@@ -520,10 +520,7 @@ describe('ReactDOMFloat', () => {
|
||||
);
|
||||
await waitForAll([]);
|
||||
assertConsoleErrorDev([
|
||||
[
|
||||
'Cannot render <noscript> outside the main document. Try moving it into the root <head> tag.',
|
||||
{withoutStack: true},
|
||||
],
|
||||
'Cannot render <noscript> outside the main document. Try moving it into the root <head> tag.',
|
||||
]);
|
||||
|
||||
root.render(
|
||||
@@ -580,11 +577,8 @@ describe('ReactDOMFloat', () => {
|
||||
);
|
||||
await waitForAll([]);
|
||||
assertConsoleErrorDev([
|
||||
[
|
||||
'Cannot render a <link rel="stylesheet" /> outside the main document without knowing its precedence. ' +
|
||||
'Consider adding precedence="default" or moving it into the root <head> tag.',
|
||||
{withoutStack: true},
|
||||
],
|
||||
'Cannot render a <link rel="stylesheet" /> outside the main document without knowing its precedence. ' +
|
||||
'Consider adding precedence="default" or moving it into the root <head> tag.',
|
||||
]);
|
||||
|
||||
root.render(
|
||||
@@ -633,14 +627,11 @@ describe('ReactDOMFloat', () => {
|
||||
</>,
|
||||
);
|
||||
await waitForAll([]);
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'Cannot render a <link> with onLoad or onError listeners outside the main document. ' +
|
||||
'Try removing onLoad={...} and onError={...} or moving it into the root <head> tag or ' +
|
||||
'somewhere in the <body>.',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
assertConsoleErrorDev([
|
||||
'Cannot render a <link> with onLoad or onError listeners outside the main document. ' +
|
||||
'Try removing onLoad={...} and onError={...} or moving it into the root <head> tag or ' +
|
||||
'somewhere in the <body>.',
|
||||
]);
|
||||
return;
|
||||
});
|
||||
|
||||
|
||||
+8
-16
@@ -1505,13 +1505,10 @@ describe('ReactDOMForm', () => {
|
||||
// Dispatch outside of a transition.
|
||||
await act(() => dispatch());
|
||||
assertConsoleErrorDev([
|
||||
[
|
||||
'An async function with useActionState was called outside of a transition. ' +
|
||||
'This is likely not what you intended (for example, isPending will not update ' +
|
||||
'correctly). Either call the returned function inside startTransition, or pass it ' +
|
||||
'to an `action` or `formAction` prop.',
|
||||
{withoutStack: true},
|
||||
],
|
||||
'An async function with useActionState was called outside of a transition. ' +
|
||||
'This is likely not what you intended (for example, isPending will not update ' +
|
||||
'correctly). Either call the returned function inside startTransition, or pass it ' +
|
||||
'to an `action` or `formAction` prop.',
|
||||
]);
|
||||
assertLog([
|
||||
'Suspend! [Count: 1]',
|
||||
@@ -1967,15 +1964,10 @@ describe('ReactDOMForm', () => {
|
||||
|
||||
// This triggers a synchronous requestFormReset, and a warning
|
||||
await act(() => resolveText('Wait 1'));
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'requestFormReset was called outside a transition or action. ' +
|
||||
'To fix, move to an action, or wrap with startTransition.',
|
||||
],
|
||||
{
|
||||
withoutStack: true,
|
||||
},
|
||||
);
|
||||
assertConsoleErrorDev([
|
||||
'requestFormReset was called outside a transition or action. ' +
|
||||
'To fix, move to an action, or wrap with startTransition.',
|
||||
]);
|
||||
assertLog(['Request form reset']);
|
||||
|
||||
// The form was reset even though the action didn't finish.
|
||||
|
||||
@@ -1073,24 +1073,18 @@ describe('FragmentRefs', () => {
|
||||
|
||||
// Warning when there is no attached observer
|
||||
fragmentRef.current.unobserveUsing(observer);
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'You are calling unobserveUsing() with an observer that is not being observed with this fragment ' +
|
||||
'instance. First attach the observer with observeUsing()',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
assertConsoleErrorDev([
|
||||
'You are calling unobserveUsing() with an observer that is not being observed with this fragment ' +
|
||||
'instance. First attach the observer with observeUsing()',
|
||||
]);
|
||||
|
||||
// Warning when the attached observer does not match
|
||||
fragmentRef.current.observeUsing(observer);
|
||||
fragmentRef.current.unobserveUsing(observer2);
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'You are calling unobserveUsing() with an observer that is not being observed with this fragment ' +
|
||||
'instance. First attach the observer with observeUsing()',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
assertConsoleErrorDev([
|
||||
'You are calling unobserveUsing() with an observer that is not being observed with this fragment ' +
|
||||
'instance. First attach the observer with observeUsing()',
|
||||
]);
|
||||
});
|
||||
|
||||
// @gate enableFragmentRefs && enableFragmentRefsInstanceHandles
|
||||
|
||||
@@ -35,15 +35,12 @@ describe('ReactDOMComponentTree', () => {
|
||||
const component = <div />;
|
||||
const node = ReactDOM.render(<div>{component}</div>, container);
|
||||
ReactDOM.unmountComponentAtNode(node);
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
"unmountComponentAtNode(): The node you're attempting to unmount " +
|
||||
'was rendered by React and is not a top-level container. You may ' +
|
||||
'have accidentally passed in a React root node instead of its ' +
|
||||
'container.',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
assertConsoleErrorDev([
|
||||
"unmountComponentAtNode(): The node you're attempting to unmount " +
|
||||
'was rendered by React and is not a top-level container. You may ' +
|
||||
'have accidentally passed in a React root node instead of its ' +
|
||||
'container.',
|
||||
]);
|
||||
});
|
||||
|
||||
// @gate !disableLegacyMode
|
||||
@@ -56,14 +53,11 @@ describe('ReactDOMComponentTree', () => {
|
||||
const anotherComponent = <div />;
|
||||
const instance = ReactDOM.render(component, container);
|
||||
ReactDOM.render(anotherComponent, instance);
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'Replacing React-rendered children with a new root ' +
|
||||
'component. If you intended to update the children of this node, ' +
|
||||
'you should instead have the existing children update their state ' +
|
||||
'and render the new components instead of calling ReactDOM.render.',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
assertConsoleErrorDev([
|
||||
'Replacing React-rendered children with a new root ' +
|
||||
'component. If you intended to update the children of this node, ' +
|
||||
'you should instead have the existing children update their state ' +
|
||||
'and render the new components instead of calling ReactDOM.render.',
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
+21
-30
@@ -1275,16 +1275,13 @@ describe('ReactDOMLegacyFiber', () => {
|
||||
ReactDOM.render(<div key="2">baz</div>, container);
|
||||
});
|
||||
}).rejects.toThrow('The node to be removed is not a child of this node.');
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'' +
|
||||
'It looks like the React-rendered content of this container was ' +
|
||||
'removed without using React. This is not supported and will ' +
|
||||
'cause errors. Instead, call ReactDOM.unmountComponentAtNode ' +
|
||||
'to empty a container.',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
assertConsoleErrorDev([
|
||||
'' +
|
||||
'It looks like the React-rendered content of this container was ' +
|
||||
'removed without using React. This is not supported and will ' +
|
||||
'cause errors. Instead, call ReactDOM.unmountComponentAtNode ' +
|
||||
'to empty a container.',
|
||||
]);
|
||||
});
|
||||
|
||||
// @gate !disableLegacyMode
|
||||
@@ -1296,16 +1293,13 @@ describe('ReactDOMLegacyFiber', () => {
|
||||
// then we mess with the DOM before an update
|
||||
container.innerHTML = '<div>MEOW.</div>';
|
||||
ReactDOM.render(<div>baz</div>, container);
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'' +
|
||||
'It looks like the React-rendered content of this container was ' +
|
||||
'removed without using React. This is not supported and will ' +
|
||||
'cause errors. Instead, call ReactDOM.unmountComponentAtNode ' +
|
||||
'to empty a container.',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
assertConsoleErrorDev([
|
||||
'' +
|
||||
'It looks like the React-rendered content of this container was ' +
|
||||
'removed without using React. This is not supported and will ' +
|
||||
'cause errors. Instead, call ReactDOM.unmountComponentAtNode ' +
|
||||
'to empty a container.',
|
||||
]);
|
||||
});
|
||||
|
||||
// @gate !disableLegacyMode
|
||||
@@ -1317,16 +1311,13 @@ describe('ReactDOMLegacyFiber', () => {
|
||||
// then we mess with the DOM before an update
|
||||
container.innerHTML = '';
|
||||
ReactDOM.render(<div>baz</div>, container);
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'' +
|
||||
'It looks like the React-rendered content of this container was ' +
|
||||
'removed without using React. This is not supported and will ' +
|
||||
'cause errors. Instead, call ReactDOM.unmountComponentAtNode ' +
|
||||
'to empty a container.',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
assertConsoleErrorDev([
|
||||
'' +
|
||||
'It looks like the React-rendered content of this container was ' +
|
||||
'removed without using React. This is not supported and will ' +
|
||||
'cause errors. Instead, call ReactDOM.unmountComponentAtNode ' +
|
||||
'to empty a container.',
|
||||
]);
|
||||
});
|
||||
|
||||
// @gate !disableLegacyMode
|
||||
|
||||
+43
-76
@@ -52,13 +52,10 @@ describe('ReactDOMRoot', () => {
|
||||
const callback = jest.fn();
|
||||
const root = ReactDOMClient.createRoot(container);
|
||||
root.render(<div>Hi</div>, callback);
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'does not support the second callback argument. ' +
|
||||
'To execute a side effect after rendering, declare it in a component body with useEffect().',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
assertConsoleErrorDev([
|
||||
'does not support the second callback argument. ' +
|
||||
'To execute a side effect after rendering, declare it in a component body with useEffect().',
|
||||
]);
|
||||
await waitForAll([]);
|
||||
expect(callback).not.toHaveBeenCalled();
|
||||
});
|
||||
@@ -70,15 +67,10 @@ describe('ReactDOMRoot', () => {
|
||||
|
||||
const root = ReactDOMClient.createRoot(container);
|
||||
root.render(<App />, {});
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'You passed a second argument to root.render(...) but it only accepts ' +
|
||||
'one argument.',
|
||||
],
|
||||
{
|
||||
withoutStack: true,
|
||||
},
|
||||
);
|
||||
assertConsoleErrorDev([
|
||||
'You passed a second argument to root.render(...) but it only accepts ' +
|
||||
'one argument.',
|
||||
]);
|
||||
});
|
||||
|
||||
it('warn if a container is passed to root.render(...)', async () => {
|
||||
@@ -88,16 +80,11 @@ describe('ReactDOMRoot', () => {
|
||||
|
||||
const root = ReactDOMClient.createRoot(container);
|
||||
root.render(<App />, container);
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'You passed a container to the second argument of root.render(...). ' +
|
||||
"You don't need to pass it again since you already passed it to create " +
|
||||
'the root.',
|
||||
],
|
||||
{
|
||||
withoutStack: true,
|
||||
},
|
||||
);
|
||||
assertConsoleErrorDev([
|
||||
'You passed a container to the second argument of root.render(...). ' +
|
||||
"You don't need to pass it again since you already passed it to create " +
|
||||
'the root.',
|
||||
]);
|
||||
});
|
||||
|
||||
it('warns if a callback parameter is provided to unmount', async () => {
|
||||
@@ -105,13 +92,10 @@ describe('ReactDOMRoot', () => {
|
||||
const root = ReactDOMClient.createRoot(container);
|
||||
root.render(<div>Hi</div>);
|
||||
root.unmount(callback);
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'does not support a callback argument. ' +
|
||||
'To execute a side effect after rendering, declare it in a component body with useEffect().',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
assertConsoleErrorDev([
|
||||
'does not support a callback argument. ' +
|
||||
'To execute a side effect after rendering, declare it in a component body with useEffect().',
|
||||
]);
|
||||
await waitForAll([]);
|
||||
expect(callback).not.toHaveBeenCalled();
|
||||
});
|
||||
@@ -216,14 +200,11 @@ describe('ReactDOMRoot', () => {
|
||||
it('warns when creating two roots managing the same container', () => {
|
||||
ReactDOMClient.createRoot(container);
|
||||
ReactDOMClient.createRoot(container);
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'You are calling ReactDOMClient.createRoot() on a container that ' +
|
||||
'has already been passed to createRoot() before. Instead, call ' +
|
||||
'root.render() on the existing root instead if you want to update it.',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
assertConsoleErrorDev([
|
||||
'You are calling ReactDOMClient.createRoot() on a container that ' +
|
||||
'has already been passed to createRoot() before. Instead, call ' +
|
||||
'root.render() on the existing root instead if you want to update it.',
|
||||
]);
|
||||
});
|
||||
|
||||
it('does not warn when creating second root after first one is unmounted', async () => {
|
||||
@@ -413,13 +394,10 @@ describe('ReactDOMRoot', () => {
|
||||
|
||||
it('warn if no children passed to hydrateRoot', async () => {
|
||||
ReactDOMClient.hydrateRoot(container);
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'Must provide initial children as second argument to hydrateRoot. ' +
|
||||
'Example usage: hydrateRoot(domContainer, <App />)',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
assertConsoleErrorDev([
|
||||
'Must provide initial children as second argument to hydrateRoot. ' +
|
||||
'Example usage: hydrateRoot(domContainer, <App />)',
|
||||
]);
|
||||
});
|
||||
|
||||
it('warn if JSX passed to createRoot', async () => {
|
||||
@@ -428,18 +406,13 @@ describe('ReactDOMRoot', () => {
|
||||
}
|
||||
|
||||
ReactDOMClient.createRoot(container, <App />);
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'You passed a JSX element to createRoot. You probably meant to call root.render instead. ' +
|
||||
'Example usage:\n' +
|
||||
'\n' +
|
||||
' let root = createRoot(domContainer);\n' +
|
||||
' root.render(<App />);',
|
||||
],
|
||||
{
|
||||
withoutStack: true,
|
||||
},
|
||||
);
|
||||
assertConsoleErrorDev([
|
||||
'You passed a JSX element to createRoot. You probably meant to call root.render instead. ' +
|
||||
'Example usage:\n' +
|
||||
'\n' +
|
||||
' let root = createRoot(domContainer);\n' +
|
||||
' root.render(<App />);',
|
||||
]);
|
||||
});
|
||||
|
||||
it('warns when given a function', () => {
|
||||
@@ -452,15 +425,12 @@ describe('ReactDOMRoot', () => {
|
||||
ReactDOM.flushSync(() => {
|
||||
root.render(Component);
|
||||
});
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'Functions are not valid as a React child. ' +
|
||||
'This may happen if you return Component instead of <Component /> from render. ' +
|
||||
'Or maybe you meant to call this function rather than return it.\n' +
|
||||
' root.render(Component)',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
assertConsoleErrorDev([
|
||||
'Functions are not valid as a React child. ' +
|
||||
'This may happen if you return Component instead of <Component /> from render. ' +
|
||||
'Or maybe you meant to call this function rather than return it.\n' +
|
||||
' root.render(Component)',
|
||||
]);
|
||||
});
|
||||
|
||||
it('warns when given a symbol', () => {
|
||||
@@ -469,12 +439,9 @@ describe('ReactDOMRoot', () => {
|
||||
ReactDOM.flushSync(() => {
|
||||
root.render(Symbol('foo'));
|
||||
});
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'Symbols are not valid as a React child.\n' +
|
||||
' root.render(Symbol(foo))',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
assertConsoleErrorDev([
|
||||
'Symbols are not valid as a React child.\n' +
|
||||
' root.render(Symbol(foo))',
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
+4
-7
@@ -323,12 +323,9 @@ describe('ReactIdentity', () => {
|
||||
</div>,
|
||||
);
|
||||
}).toThrowError(new TypeError('prod message'));
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'The provided key is an unsupported type TemporalLike.' +
|
||||
' This value must be coerced to a string before using it here.',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
assertConsoleErrorDev([
|
||||
'The provided key is an unsupported type TemporalLike.' +
|
||||
' This value must be coerced to a string before using it here.',
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
+49
-70
@@ -67,15 +67,12 @@ describe('ReactMount', () => {
|
||||
|
||||
const container = document.createElement('div');
|
||||
ReactDOM.render(Component, container);
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'Functions are not valid as a React child. ' +
|
||||
'This may happen if you return Component instead of <Component /> from render. ' +
|
||||
'Or maybe you meant to call this function rather than return it.\n' +
|
||||
' root.render(Component)',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
assertConsoleErrorDev([
|
||||
'Functions are not valid as a React child. ' +
|
||||
'This may happen if you return Component instead of <Component /> from render. ' +
|
||||
'Or maybe you meant to call this function rather than return it.\n' +
|
||||
' root.render(Component)',
|
||||
]);
|
||||
});
|
||||
|
||||
// @gate !disableLegacyMode
|
||||
@@ -172,15 +169,12 @@ describe('ReactMount', () => {
|
||||
const rootNode = container.firstChild;
|
||||
|
||||
ReactDOM.render(<span />, rootNode);
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'Replacing React-rendered children with a new ' +
|
||||
'root component. If you intended to update the children of this node, ' +
|
||||
'you should instead have the existing children update their state and ' +
|
||||
'render the new components instead of calling ReactDOM.render.',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
assertConsoleErrorDev([
|
||||
'Replacing React-rendered children with a new ' +
|
||||
'root component. If you intended to update the children of this node, ' +
|
||||
'you should instead have the existing children update their state and ' +
|
||||
'render the new components instead of calling ReactDOM.render.',
|
||||
]);
|
||||
});
|
||||
|
||||
// @gate !disableLegacyMode
|
||||
@@ -204,13 +198,10 @@ describe('ReactMount', () => {
|
||||
expect(ReactDOM).not.toEqual(ReactDOMOther);
|
||||
|
||||
ReactDOMOther.unmountComponentAtNode(container);
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
"unmountComponentAtNode(): The node you're attempting to unmount " +
|
||||
'was rendered by another copy of React.',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
assertConsoleErrorDev([
|
||||
"unmountComponentAtNode(): The node you're attempting to unmount " +
|
||||
'was rendered by another copy of React.',
|
||||
]);
|
||||
|
||||
// Don't throw a warning if the correct React copy unmounts the node
|
||||
ReactDOM.unmountComponentAtNode(container);
|
||||
@@ -361,20 +352,17 @@ describe('ReactMount', () => {
|
||||
await waitForAll([]);
|
||||
expect(container.textContent).toEqual('Hi');
|
||||
ReactDOM.render(<div>Bye</div>, container);
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
// We care about this warning:
|
||||
'You are calling ReactDOM.render() on a container that was previously ' +
|
||||
'passed to ReactDOMClient.createRoot(). This is not supported. ' +
|
||||
'Did you mean to call root.render(element)?',
|
||||
// This is more of a symptom but restructuring the code to avoid it isn't worth it:
|
||||
'Replacing React-rendered children with a new root component. ' +
|
||||
'If you intended to update the children of this node, ' +
|
||||
'you should instead have the existing children update their state ' +
|
||||
'and render the new components instead of calling ReactDOM.render.',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
assertConsoleErrorDev([
|
||||
// We care about this warning:
|
||||
'You are calling ReactDOM.render() on a container that was previously ' +
|
||||
'passed to ReactDOMClient.createRoot(). This is not supported. ' +
|
||||
'Did you mean to call root.render(element)?',
|
||||
// This is more of a symptom but restructuring the code to avoid it isn't worth it:
|
||||
'Replacing React-rendered children with a new root component. ' +
|
||||
'If you intended to update the children of this node, ' +
|
||||
'you should instead have the existing children update their state ' +
|
||||
'and render the new components instead of calling ReactDOM.render.',
|
||||
]);
|
||||
await waitForAll([]);
|
||||
// This works now but we could disallow it:
|
||||
expect(container.textContent).toEqual('Bye');
|
||||
@@ -388,18 +376,15 @@ describe('ReactMount', () => {
|
||||
await waitForAll([]);
|
||||
expect(container.textContent).toEqual('Hi');
|
||||
const unmounted = ReactDOM.unmountComponentAtNode(container);
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
// We care about this warning:
|
||||
'You are calling ReactDOM.unmountComponentAtNode() on a container that was previously ' +
|
||||
'passed to ReactDOMClient.createRoot(). This is not supported. Did you mean to call root.unmount()?',
|
||||
// This is more of a symptom but restructuring the code to avoid it isn't worth it:
|
||||
'unmountComponentAtNode(): ' +
|
||||
"The node you're attempting to unmount was rendered by React and is not a top-level container. " +
|
||||
'Instead, have the parent component update its state and rerender in order to remove this component.',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
assertConsoleErrorDev([
|
||||
// We care about this warning:
|
||||
'You are calling ReactDOM.unmountComponentAtNode() on a container that was previously ' +
|
||||
'passed to ReactDOMClient.createRoot(). This is not supported. Did you mean to call root.unmount()?',
|
||||
// This is more of a symptom but restructuring the code to avoid it isn't worth it:
|
||||
'unmountComponentAtNode(): ' +
|
||||
"The node you're attempting to unmount was rendered by React and is not a top-level container. " +
|
||||
'Instead, have the parent component update its state and rerender in order to remove this component.',
|
||||
]);
|
||||
expect(unmounted).toBe(false);
|
||||
await waitForAll([]);
|
||||
expect(container.textContent).toEqual('Hi');
|
||||
@@ -419,18 +404,15 @@ describe('ReactMount', () => {
|
||||
await waitForAll([]);
|
||||
expect(container.textContent).toEqual('Hi');
|
||||
const unmounted = ReactDOM.unmountComponentAtNode(container);
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'You are calling ReactDOM.unmountComponentAtNode() on a container ' +
|
||||
'that was previously passed to ReactDOMClient.createRoot(). ' +
|
||||
'This is not supported. Did you mean to call root.unmount()?',
|
||||
// This is more of a symptom but restructuring the code to avoid it isn't worth it:
|
||||
'unmountComponentAtNode(): ' +
|
||||
"The node you're attempting to unmount was rendered by React and is not a top-level container. " +
|
||||
'Instead, have the parent component update its state and rerender in order to remove this component.',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
assertConsoleErrorDev([
|
||||
'You are calling ReactDOM.unmountComponentAtNode() on a container ' +
|
||||
'that was previously passed to ReactDOMClient.createRoot(). ' +
|
||||
'This is not supported. Did you mean to call root.unmount()?',
|
||||
// This is more of a symptom but restructuring the code to avoid it isn't worth it:
|
||||
'unmountComponentAtNode(): ' +
|
||||
"The node you're attempting to unmount was rendered by React and is not a top-level container. " +
|
||||
'Instead, have the parent component update its state and rerender in order to remove this component.',
|
||||
]);
|
||||
expect(unmounted).toBe(false);
|
||||
await waitForAll([]);
|
||||
expect(container.textContent).toEqual('Hi');
|
||||
@@ -444,12 +426,9 @@ describe('ReactMount', () => {
|
||||
const container = document.createElement('div');
|
||||
ReactDOM.render(<div>Hi</div>, container);
|
||||
ReactDOMClient.createRoot(container);
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'You are calling ReactDOMClient.createRoot() on a container that was previously ' +
|
||||
'passed to ReactDOM.render(). This is not supported.',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
assertConsoleErrorDev([
|
||||
'You are calling ReactDOMClient.createRoot() on a container that was previously ' +
|
||||
'passed to ReactDOM.render(). This is not supported.',
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
+16
-28
@@ -916,13 +916,10 @@ describe('ReactLegacyUpdates', () => {
|
||||
'Invalid argument passed as callback. Expected a function. ' +
|
||||
'Instead received: no',
|
||||
);
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'Expected the last optional `callback` argument to be ' +
|
||||
'a function. Instead received: no.',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
assertConsoleErrorDev([
|
||||
'Expected the last optional `callback` argument to be ' +
|
||||
'a function. Instead received: no.',
|
||||
]);
|
||||
|
||||
container = document.createElement('div');
|
||||
component = ReactDOM.render(<A />, container);
|
||||
@@ -934,13 +931,10 @@ describe('ReactLegacyUpdates', () => {
|
||||
'Invalid argument passed as callback. Expected a function. Instead ' +
|
||||
'received: [object Object]',
|
||||
);
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'Expected the last optional `callback` argument to be a function. ' +
|
||||
"Instead received: { foo: 'bar' }.",
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
assertConsoleErrorDev([
|
||||
'Expected the last optional `callback` argument to be a function. ' +
|
||||
"Instead received: { foo: 'bar' }.",
|
||||
]);
|
||||
// Make sure the warning is deduplicated and doesn't fire again
|
||||
container = document.createElement('div');
|
||||
component = ReactDOM.render(<A />, container);
|
||||
@@ -980,13 +974,10 @@ describe('ReactLegacyUpdates', () => {
|
||||
'Invalid argument passed as callback. Expected a function. Instead ' +
|
||||
'received: no',
|
||||
);
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'Expected the last optional `callback` argument to be a function. ' +
|
||||
'Instead received: no.',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
assertConsoleErrorDev([
|
||||
'Expected the last optional `callback` argument to be a function. ' +
|
||||
'Instead received: no.',
|
||||
]);
|
||||
container = document.createElement('div');
|
||||
component = ReactDOM.render(<A />, container);
|
||||
await expect(async () => {
|
||||
@@ -997,13 +988,10 @@ describe('ReactLegacyUpdates', () => {
|
||||
'Invalid argument passed as callback. Expected a function. Instead ' +
|
||||
'received: [object Object]',
|
||||
);
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'Expected the last optional `callback` argument to be a function. ' +
|
||||
"Instead received: { foo: 'bar' }.",
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
assertConsoleErrorDev([
|
||||
'Expected the last optional `callback` argument to be a function. ' +
|
||||
"Instead received: { foo: 'bar' }.",
|
||||
]);
|
||||
// Make sure the warning is deduplicated and doesn't fire again
|
||||
container = document.createElement('div');
|
||||
component = ReactDOM.render(<A />, container);
|
||||
|
||||
+12
-18
@@ -66,15 +66,12 @@ describe('ReactMount', () => {
|
||||
// Test that unmounting at a root node gives a helpful warning
|
||||
const rootDiv = mainContainerDiv.firstChild;
|
||||
ReactDOM.unmountComponentAtNode(rootDiv);
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
"unmountComponentAtNode(): The node you're attempting to " +
|
||||
'unmount was rendered by React and is not a top-level container. You ' +
|
||||
'may have accidentally passed in a React root node instead of its ' +
|
||||
'container.',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
assertConsoleErrorDev([
|
||||
"unmountComponentAtNode(): The node you're attempting to " +
|
||||
'unmount was rendered by React and is not a top-level container. You ' +
|
||||
'may have accidentally passed in a React root node instead of its ' +
|
||||
'container.',
|
||||
]);
|
||||
});
|
||||
|
||||
// @gate !disableLegacyMode
|
||||
@@ -94,14 +91,11 @@ describe('ReactMount', () => {
|
||||
// Test that unmounting at a non-root node gives a different warning
|
||||
const nonRootDiv = mainContainerDiv.firstChild.firstChild;
|
||||
ReactDOM.unmountComponentAtNode(nonRootDiv);
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
"unmountComponentAtNode(): The node you're attempting to " +
|
||||
'unmount was rendered by React and is not a top-level container. ' +
|
||||
'Instead, have the parent component update its state and rerender in ' +
|
||||
'order to remove this component.',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
assertConsoleErrorDev([
|
||||
"unmountComponentAtNode(): The node you're attempting to " +
|
||||
'unmount was rendered by React and is not a top-level container. ' +
|
||||
'Instead, have the parent component update its state and rerender in ' +
|
||||
'order to remove this component.',
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
+14
-20
@@ -606,16 +606,13 @@ describe('ReactDOMServer', () => {
|
||||
|
||||
ReactDOMServer.renderToString(<Foo />);
|
||||
jest.runOnlyPendingTimers();
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'Can only update a mounting component. ' +
|
||||
'This usually means you called setState() outside componentWillMount() on the server. ' +
|
||||
'This is a no-op.\n' +
|
||||
'\n' +
|
||||
'Please check the code for the Foo component.',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
assertConsoleErrorDev([
|
||||
'Can only update a mounting component. ' +
|
||||
'This usually means you called setState() outside componentWillMount() on the server. ' +
|
||||
'This is a no-op.\n' +
|
||||
'\n' +
|
||||
'Please check the code for the Foo component.',
|
||||
]);
|
||||
|
||||
const markup = ReactDOMServer.renderToStaticMarkup(<Foo />);
|
||||
expect(markup).toBe('<div>hello</div>');
|
||||
@@ -639,16 +636,13 @@ describe('ReactDOMServer', () => {
|
||||
|
||||
ReactDOMServer.renderToString(<Baz />);
|
||||
jest.runOnlyPendingTimers();
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'Can only update a mounting component. ' +
|
||||
'This usually means you called forceUpdate() outside componentWillMount() on the server. ' +
|
||||
'This is a no-op.\n' +
|
||||
'\n' +
|
||||
'Please check the code for the Baz component.',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
assertConsoleErrorDev([
|
||||
'Can only update a mounting component. ' +
|
||||
'This usually means you called forceUpdate() outside componentWillMount() on the server. ' +
|
||||
'This is a no-op.\n' +
|
||||
'\n' +
|
||||
'Please check the code for the Baz component.',
|
||||
]);
|
||||
const markup = ReactDOMServer.renderToStaticMarkup(<Baz />);
|
||||
expect(markup).toBe('<div></div>');
|
||||
});
|
||||
|
||||
@@ -377,23 +377,18 @@ describe('ReactDOMServerHydration', () => {
|
||||
await act(() => {
|
||||
ReactDOMClient.hydrateRoot(element, markup);
|
||||
});
|
||||
assertConsoleWarnDev(
|
||||
[
|
||||
'componentWillMount has been renamed, and is not recommended for use. ' +
|
||||
'See https://react.dev/link/unsafe-component-lifecycles for details.\n' +
|
||||
'\n' +
|
||||
'* Move code with side effects to componentDidMount, and set initial state in the constructor.\n' +
|
||||
'* Rename componentWillMount to UNSAFE_componentWillMount to suppress this warning in non-strict mode. ' +
|
||||
'In React 18.x, only the UNSAFE_ name will work. ' +
|
||||
'To rename all deprecated lifecycles to their new names, ' +
|
||||
'you can run `npx react-codemod rename-unsafe-lifecycles` in your project source folder.\n' +
|
||||
'\n' +
|
||||
'Please update the following components: ComponentWithWarning',
|
||||
],
|
||||
{
|
||||
withoutStack: true,
|
||||
},
|
||||
);
|
||||
assertConsoleWarnDev([
|
||||
'componentWillMount has been renamed, and is not recommended for use. ' +
|
||||
'See https://react.dev/link/unsafe-component-lifecycles for details.\n' +
|
||||
'\n' +
|
||||
'* Move code with side effects to componentDidMount, and set initial state in the constructor.\n' +
|
||||
'* Rename componentWillMount to UNSAFE_componentWillMount to suppress this warning in non-strict mode. ' +
|
||||
'In React 18.x, only the UNSAFE_ name will work. ' +
|
||||
'To rename all deprecated lifecycles to their new names, ' +
|
||||
'you can run `npx react-codemod rename-unsafe-lifecycles` in your project source folder.\n' +
|
||||
'\n' +
|
||||
'Please update the following components: ComponentWithWarning',
|
||||
]);
|
||||
expect(element.textContent).toBe('Hi');
|
||||
});
|
||||
|
||||
|
||||
+16
-28
@@ -1063,13 +1063,10 @@ describe('ReactUpdates', () => {
|
||||
'Invalid argument passed as callback. Expected a function. Instead ' +
|
||||
'received: no',
|
||||
);
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'Expected the last optional `callback` argument to be ' +
|
||||
'a function. Instead received: no.',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
assertConsoleErrorDev([
|
||||
'Expected the last optional `callback` argument to be ' +
|
||||
'a function. Instead received: no.',
|
||||
]);
|
||||
container = document.createElement('div');
|
||||
root = ReactDOMClient.createRoot(container);
|
||||
await act(() => {
|
||||
@@ -1084,13 +1081,10 @@ describe('ReactUpdates', () => {
|
||||
'Invalid argument passed as callback. Expected a function. Instead ' +
|
||||
'received: [object Object]',
|
||||
);
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'Expected the last optional `callback` argument to be ' +
|
||||
"a function. Instead received: { foo: 'bar' }.",
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
assertConsoleErrorDev([
|
||||
'Expected the last optional `callback` argument to be ' +
|
||||
"a function. Instead received: { foo: 'bar' }.",
|
||||
]);
|
||||
container = document.createElement('div');
|
||||
root = ReactDOMClient.createRoot(container);
|
||||
await act(() => {
|
||||
@@ -1136,13 +1130,10 @@ describe('ReactUpdates', () => {
|
||||
'Invalid argument passed as callback. Expected a function. Instead ' +
|
||||
'received: no',
|
||||
);
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'Expected the last optional `callback` argument to be ' +
|
||||
'a function. Instead received: no.',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
assertConsoleErrorDev([
|
||||
'Expected the last optional `callback` argument to be ' +
|
||||
'a function. Instead received: no.',
|
||||
]);
|
||||
container = document.createElement('div');
|
||||
root = ReactDOMClient.createRoot(container);
|
||||
await act(() => {
|
||||
@@ -1157,13 +1148,10 @@ describe('ReactUpdates', () => {
|
||||
'Invalid argument passed as callback. Expected a function. Instead ' +
|
||||
'received: [object Object]',
|
||||
);
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'Expected the last optional `callback` argument to be ' +
|
||||
"a function. Instead received: { foo: 'bar' }.",
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
assertConsoleErrorDev([
|
||||
'Expected the last optional `callback` argument to be ' +
|
||||
"a function. Instead received: { foo: 'bar' }.",
|
||||
]);
|
||||
// Make sure the warning is deduplicated and doesn't fire again
|
||||
container = document.createElement('div');
|
||||
root = ReactDOMClient.createRoot(container);
|
||||
|
||||
@@ -15,7 +15,7 @@ const ReactDOMClient = require('react-dom/client');
|
||||
const assertConsoleErrorDev =
|
||||
require('internal-test-utils').assertConsoleErrorDev;
|
||||
|
||||
function expectWarnings(tags, warnings = [], withoutStack = 0) {
|
||||
function expectWarnings(tags, warnings = []) {
|
||||
tags = [...tags];
|
||||
warnings = [...warnings];
|
||||
|
||||
@@ -61,10 +61,7 @@ function expectWarnings(tags, warnings = [], withoutStack = 0) {
|
||||
root.render(element);
|
||||
});
|
||||
if (warnings.length) {
|
||||
assertConsoleErrorDev(
|
||||
warnings,
|
||||
withoutStack > 0 ? {withoutStack} : undefined,
|
||||
);
|
||||
assertConsoleErrorDev(warnings);
|
||||
}
|
||||
root.unmount();
|
||||
}
|
||||
|
||||
@@ -477,9 +477,7 @@ describe('ReactFabric', () => {
|
||||
|
||||
expect(nativeFabricUIManager.dispatchCommand).not.toBeCalled();
|
||||
ReactFabric.dispatchCommand(viewRef, 'updateCommand', [10, 20]);
|
||||
assertConsoleErrorDev([DISPATCH_COMMAND_REQUIRES_HOST_COMPONENT], {
|
||||
withoutStack: true,
|
||||
});
|
||||
assertConsoleErrorDev([DISPATCH_COMMAND_REQUIRES_HOST_COMPONENT]);
|
||||
|
||||
expect(nativeFabricUIManager.dispatchCommand).not.toBeCalled();
|
||||
});
|
||||
@@ -542,9 +540,7 @@ describe('ReactFabric', () => {
|
||||
|
||||
expect(nativeFabricUIManager.sendAccessibilityEvent).not.toBeCalled();
|
||||
ReactFabric.sendAccessibilityEvent(viewRef, 'eventTypeName');
|
||||
assertConsoleErrorDev([SEND_ACCESSIBILITY_EVENT_REQUIRES_HOST_COMPONENT], {
|
||||
withoutStack: true,
|
||||
});
|
||||
assertConsoleErrorDev([SEND_ACCESSIBILITY_EVENT_REQUIRES_HOST_COMPONENT]);
|
||||
|
||||
expect(nativeFabricUIManager.sendAccessibilityEvent).not.toBeCalled();
|
||||
});
|
||||
|
||||
@@ -219,10 +219,9 @@ describe('act warnings', () => {
|
||||
act(() => {
|
||||
setState(1);
|
||||
});
|
||||
assertConsoleErrorDev(
|
||||
['The current testing environment is not configured to support act(...)'],
|
||||
{withoutStack: true},
|
||||
);
|
||||
assertConsoleErrorDev([
|
||||
'The current testing environment is not configured to support act(...)',
|
||||
]);
|
||||
assertLog([1]);
|
||||
expect(root).toMatchRenderedOutput('1');
|
||||
|
||||
@@ -240,12 +239,9 @@ describe('act warnings', () => {
|
||||
act(() => {
|
||||
setState(1);
|
||||
});
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'The current testing environment is not configured to support act(...)',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
assertConsoleErrorDev([
|
||||
'The current testing environment is not configured to support act(...)',
|
||||
]);
|
||||
assertLog([1]);
|
||||
expect(root).toMatchRenderedOutput('1');
|
||||
});
|
||||
@@ -255,24 +251,21 @@ describe('act warnings', () => {
|
||||
await withActEnvironment(true, () => {
|
||||
const root = ReactNoop.createRoot();
|
||||
root.render('Hi');
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
// TODO: Better error message that doesn't make it look like "Root" is
|
||||
// the name of a custom component
|
||||
'An update to Root inside a test was not wrapped in act(...).\n' +
|
||||
'\n' +
|
||||
'When testing, code that causes React state updates should be wrapped into act(...):\n' +
|
||||
'\n' +
|
||||
'act(() => {\n' +
|
||||
' /* fire events that update state */\n' +
|
||||
'});\n' +
|
||||
'/* assert on the output */\n' +
|
||||
'\n' +
|
||||
"This ensures that you're testing the behavior the user would see in the browser. " +
|
||||
'Learn more at https://react.dev/link/wrap-tests-with-act',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
assertConsoleErrorDev([
|
||||
// TODO: Better error message that doesn't make it look like "Root" is
|
||||
// the name of a custom component
|
||||
'An update to Root inside a test was not wrapped in act(...).\n' +
|
||||
'\n' +
|
||||
'When testing, code that causes React state updates should be wrapped into act(...):\n' +
|
||||
'\n' +
|
||||
'act(() => {\n' +
|
||||
' /* fire events that update state */\n' +
|
||||
'});\n' +
|
||||
'/* assert on the output */\n' +
|
||||
'\n' +
|
||||
"This ensures that you're testing the behavior the user would see in the browser. " +
|
||||
'Learn more at https://react.dev/link/wrap-tests-with-act',
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -374,37 +367,33 @@ describe('act warnings', () => {
|
||||
|
||||
// This is a retry, not a ping, because we already showed a fallback.
|
||||
resolveText('Async');
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'A suspended resource finished loading inside a test, but the event was not wrapped in act(...).\n' +
|
||||
'\n' +
|
||||
'When testing, code that resolves suspended data should be wrapped into act(...):\n' +
|
||||
'\n' +
|
||||
'act(() => {\n' +
|
||||
' /* finish loading suspended data */\n' +
|
||||
'});\n' +
|
||||
'/* assert on the output */\n' +
|
||||
'\n' +
|
||||
"This ensures that you're testing the behavior the user would see in the browser. " +
|
||||
'Learn more at https://react.dev/link/wrap-tests-with-act',
|
||||
assertConsoleErrorDev([
|
||||
'A suspended resource finished loading inside a test, but the event was not wrapped in act(...).\n' +
|
||||
'\n' +
|
||||
'When testing, code that resolves suspended data should be wrapped into act(...):\n' +
|
||||
'\n' +
|
||||
'act(() => {\n' +
|
||||
' /* finish loading suspended data */\n' +
|
||||
'});\n' +
|
||||
'/* assert on the output */\n' +
|
||||
'\n' +
|
||||
"This ensures that you're testing the behavior the user would see in the browser. " +
|
||||
'Learn more at https://react.dev/link/wrap-tests-with-act',
|
||||
|
||||
// pre-warming
|
||||
// pre-warming
|
||||
|
||||
'A suspended resource finished loading inside a test, but the event was not wrapped in act(...).\n' +
|
||||
'\n' +
|
||||
'When testing, code that resolves suspended data should be wrapped into act(...):\n' +
|
||||
'\n' +
|
||||
'act(() => {\n' +
|
||||
' /* finish loading suspended data */\n' +
|
||||
'});\n' +
|
||||
'/* assert on the output */\n' +
|
||||
'\n' +
|
||||
"This ensures that you're testing the behavior the user would see in the browser. " +
|
||||
'Learn more at https://react.dev/link/wrap-tests-with-act',
|
||||
],
|
||||
|
||||
{withoutStack: true},
|
||||
);
|
||||
'A suspended resource finished loading inside a test, but the event was not wrapped in act(...).\n' +
|
||||
'\n' +
|
||||
'When testing, code that resolves suspended data should be wrapped into act(...):\n' +
|
||||
'\n' +
|
||||
'act(() => {\n' +
|
||||
' /* finish loading suspended data */\n' +
|
||||
'});\n' +
|
||||
'/* assert on the output */\n' +
|
||||
'\n' +
|
||||
"This ensures that you're testing the behavior the user would see in the browser. " +
|
||||
'Learn more at https://react.dev/link/wrap-tests-with-act',
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -437,22 +426,19 @@ describe('act warnings', () => {
|
||||
|
||||
// This is a ping, not a retry, because no fallback is showing.
|
||||
resolveText('Async');
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'A suspended resource finished loading inside a test, but the event was not wrapped in act(...).\n' +
|
||||
'\n' +
|
||||
'When testing, code that resolves suspended data should be wrapped into act(...):\n' +
|
||||
'\n' +
|
||||
'act(() => {\n' +
|
||||
' /* finish loading suspended data */\n' +
|
||||
'});\n' +
|
||||
'/* assert on the output */\n' +
|
||||
'\n' +
|
||||
"This ensures that you're testing the behavior the user would see in the browser. " +
|
||||
'Learn more at https://react.dev/link/wrap-tests-with-act',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
assertConsoleErrorDev([
|
||||
'A suspended resource finished loading inside a test, but the event was not wrapped in act(...).\n' +
|
||||
'\n' +
|
||||
'When testing, code that resolves suspended data should be wrapped into act(...):\n' +
|
||||
'\n' +
|
||||
'act(() => {\n' +
|
||||
' /* finish loading suspended data */\n' +
|
||||
'});\n' +
|
||||
'/* assert on the output */\n' +
|
||||
'\n' +
|
||||
"This ensures that you're testing the behavior the user would see in the browser. " +
|
||||
'Learn more at https://react.dev/link/wrap-tests-with-act',
|
||||
]);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1237,14 +1237,11 @@ describe('ReactAsyncActions', () => {
|
||||
setLoadingProgress('25%');
|
||||
startTransition(() => setText('B'));
|
||||
});
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'An optimistic state update occurred outside a transition or ' +
|
||||
'action. To fix, move the update to an action, or wrap ' +
|
||||
'with startTransition.',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
assertConsoleErrorDev([
|
||||
'An optimistic state update occurred outside a transition or ' +
|
||||
'action. To fix, move the update to an action, or wrap ' +
|
||||
'with startTransition.',
|
||||
]);
|
||||
assertLog(['Loading... (25%)', 'A', 'B']);
|
||||
expect(root).toMatchRenderedOutput(<div>B</div>);
|
||||
});
|
||||
|
||||
@@ -244,15 +244,12 @@ describe('ReactHooks', () => {
|
||||
throw new Error('Expected to ignore the callback.');
|
||||
}),
|
||||
);
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'State updates from the useState() and useReducer() Hooks ' +
|
||||
"don't support the second callback argument. " +
|
||||
'To execute a side effect after rendering, ' +
|
||||
'declare it in the component body with useEffect().',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
assertConsoleErrorDev([
|
||||
'State updates from the useState() and useReducer() Hooks ' +
|
||||
"don't support the second callback argument. " +
|
||||
'To execute a side effect after rendering, ' +
|
||||
'declare it in the component body with useEffect().',
|
||||
]);
|
||||
assertLog(['Count: 1']);
|
||||
expect(root).toMatchRenderedOutput('1');
|
||||
});
|
||||
@@ -279,15 +276,12 @@ describe('ReactHooks', () => {
|
||||
throw new Error('Expected to ignore the callback.');
|
||||
}),
|
||||
);
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'State updates from the useState() and useReducer() Hooks ' +
|
||||
"don't support the second callback argument. " +
|
||||
'To execute a side effect after rendering, ' +
|
||||
'declare it in the component body with useEffect().',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
assertConsoleErrorDev([
|
||||
'State updates from the useState() and useReducer() Hooks ' +
|
||||
"don't support the second callback argument. " +
|
||||
'To execute a side effect after rendering, ' +
|
||||
'declare it in the component body with useEffect().',
|
||||
]);
|
||||
assertLog(['Count: 1']);
|
||||
expect(root).toMatchRenderedOutput('1');
|
||||
});
|
||||
|
||||
+8
-11
@@ -236,17 +236,14 @@ describe('ReactHooksWithNoopRenderer', () => {
|
||||
expect(() => useState(0)).toThrow(
|
||||
"Cannot read property 'useState' of null",
|
||||
);
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for' +
|
||||
' one of the following reasons:\n' +
|
||||
'1. You might have mismatching versions of React and the renderer (such as React DOM)\n' +
|
||||
'2. You might be breaking the Rules of Hooks\n' +
|
||||
'3. You might have more than one copy of React in the same app\n' +
|
||||
'See https://react.dev/link/invalid-hook-call for tips about how to debug and fix this problem.',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
assertConsoleErrorDev([
|
||||
'Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for' +
|
||||
' one of the following reasons:\n' +
|
||||
'1. You might have mismatching versions of React and the renderer (such as React DOM)\n' +
|
||||
'2. You might be breaking the Rules of Hooks\n' +
|
||||
'3. You might have more than one copy of React in the same app\n' +
|
||||
'See https://react.dev/link/invalid-hook-call for tips about how to debug and fix this problem.',
|
||||
]);
|
||||
});
|
||||
|
||||
describe('useState', () => {
|
||||
|
||||
+8
-14
@@ -375,24 +375,18 @@ describe('memo', () => {
|
||||
|
||||
it('warns if the first argument is undefined', () => {
|
||||
memo();
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'memo: The first argument must be a component. Instead ' +
|
||||
'received: undefined',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
assertConsoleErrorDev([
|
||||
'memo: The first argument must be a component. Instead ' +
|
||||
'received: undefined',
|
||||
]);
|
||||
});
|
||||
|
||||
it('warns if the first argument is null', () => {
|
||||
memo(null);
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'memo: The first argument must be a component. Instead ' +
|
||||
'received: null',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
assertConsoleErrorDev([
|
||||
'memo: The first argument must be a component. Instead ' +
|
||||
'received: null',
|
||||
]);
|
||||
});
|
||||
|
||||
it('does not drop lower priority state updates when bailing out at higher pri (simple)', async () => {
|
||||
|
||||
@@ -862,14 +862,9 @@ describe('ReactNewContext', () => {
|
||||
);
|
||||
|
||||
await waitForAll([]);
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'The `value` prop is required for the `<Context.Provider>`. Did you misspell it or forget to pass it?',
|
||||
],
|
||||
{
|
||||
withoutStack: true,
|
||||
},
|
||||
);
|
||||
assertConsoleErrorDev([
|
||||
'The `value` prop is required for the `<Context.Provider>`. Did you misspell it or forget to pass it?',
|
||||
]);
|
||||
});
|
||||
|
||||
it('warns if multiple renderers concurrently render the same context', async () => {
|
||||
|
||||
+6
-12
@@ -1120,20 +1120,14 @@ describe('ReactFlightDOMEdge', () => {
|
||||
};
|
||||
|
||||
ServerModule.greet.bind({}, 'hi');
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'Cannot bind "this" of a Server Action. Pass null or undefined as the first argument to .bind().',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
assertConsoleErrorDev([
|
||||
'Cannot bind "this" of a Server Action. Pass null or undefined as the first argument to .bind().',
|
||||
]);
|
||||
|
||||
ServerModuleImportedOnClient.greet.bind({}, 'hi');
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'Cannot bind "this" of a Server Action. Pass null or undefined as the first argument to .bind().',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
assertConsoleErrorDev([
|
||||
'Cannot bind "this" of a Server Action. Pass null or undefined as the first argument to .bind().',
|
||||
]);
|
||||
});
|
||||
|
||||
it('should supports ReadableStreams with typed arrays', async () => {
|
||||
|
||||
@@ -189,13 +189,10 @@ describe('ReactFlight', () => {
|
||||
);
|
||||
|
||||
assertConsoleErrorDev([
|
||||
[
|
||||
'Attempted to render <span key="one"> without development properties. This is not supported. It can happen if:' +
|
||||
'\n- The element is created with a production version of React but rendered in development.' +
|
||||
'\n- The element was cloned with a custom function instead of `React.cloneElement`.\n' +
|
||||
"The props of this element may help locate this element: { children: 'Free!', [key]: [Getter] }",
|
||||
{withoutStack: true},
|
||||
],
|
||||
'Attempted to render <span key="one"> without development properties. This is not supported. It can happen if:' +
|
||||
'\n- The element is created with a production version of React but rendered in development.' +
|
||||
'\n- The element was cloned with a custom function instead of `React.cloneElement`.\n' +
|
||||
"The props of this element may help locate this element: { children: 'Free!', [key]: [Getter] }",
|
||||
"TypeError: Cannot read properties of undefined (reading 'stack')" +
|
||||
'\n in <stack>',
|
||||
]);
|
||||
|
||||
@@ -38,17 +38,12 @@ describe('ReactTestRenderer', () => {
|
||||
await act(() => {
|
||||
ReactTestRenderer.create(ReactDOM.createPortal('foo', container));
|
||||
}).catch(e => (error = e));
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'An invalid container has been provided. ' +
|
||||
'This may indicate that another renderer is being used in addition to the test renderer. ' +
|
||||
'(For example, ReactDOM.createPortal inside of a ReactTestRenderer tree.) ' +
|
||||
'This is not supported.',
|
||||
],
|
||||
{
|
||||
withoutStack: true,
|
||||
},
|
||||
);
|
||||
assertConsoleErrorDev([
|
||||
'An invalid container has been provided. ' +
|
||||
'This may indicate that another renderer is being used in addition to the test renderer. ' +
|
||||
'(For example, ReactDOM.createPortal inside of a ReactTestRenderer tree.) ' +
|
||||
'This is not supported.',
|
||||
]);
|
||||
|
||||
// After the update throws, a subsequent render is scheduled to
|
||||
// unmount the whole tree. This update also causes an error, so React
|
||||
|
||||
@@ -539,15 +539,11 @@ describe 'ReactCoffeeScriptClass', ->
|
||||
|
||||
expect(-> ref.current.replaceState {}).toThrow()
|
||||
assertConsoleWarnDev([
|
||||
'replaceState(...) is deprecated in plain JavaScript React classes.
|
||||
Refactor your code to use setState instead (see https://github.com/facebook/react/issues/3236).'
|
||||
], {withoutStack: true})
|
||||
'replaceState(...) is deprecated in plain JavaScript React classes. Refactor your code to use setState instead (see https://github.com/facebook/react/issues/3236).'])
|
||||
|
||||
expect(-> ref.current.isMounted()).toThrow()
|
||||
assertConsoleWarnDev([
|
||||
'isMounted(...) is deprecated in plain JavaScript React classes.
|
||||
Instead, make sure to clean up subscriptions and pending requests in componentWillUnmount to prevent memory leaks.',
|
||||
], {withoutStack: true})
|
||||
'isMounted(...) is deprecated in plain JavaScript React classes. Instead, make sure to clean up subscriptions and pending requests in componentWillUnmount to prevent memory leaks.'])
|
||||
|
||||
if !featureFlags.disableLegacyContext
|
||||
it 'supports this.context passed via getChildContext', ->
|
||||
|
||||
@@ -84,15 +84,12 @@ describe('ReactCreateElement', () => {
|
||||
it('should warn when `key` is being accessed on a host element', () => {
|
||||
const element = React.createElement('div', {key: '3'});
|
||||
void element.props.key;
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'div: `key` is not a prop. Trying to access it will result ' +
|
||||
'in `undefined` being returned. If you need to access the same ' +
|
||||
'value within the child component, you should pass it as a different ' +
|
||||
'prop. (https://react.dev/link/special-props)',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
assertConsoleErrorDev([
|
||||
'div: `key` is not a prop. Trying to access it will result ' +
|
||||
'in `undefined` being returned. If you need to access the same ' +
|
||||
'value within the child component, you should pass it as a different ' +
|
||||
'prop. (https://react.dev/link/special-props)',
|
||||
]);
|
||||
});
|
||||
|
||||
it('allows a string to be passed as the type', () => {
|
||||
@@ -151,16 +148,11 @@ describe('ReactCreateElement', () => {
|
||||
});
|
||||
expect(element.type).toBe(ComponentClass);
|
||||
expect(element.ref).toBe(ref);
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'Accessing element.ref was removed in React 19. ref is now a ' +
|
||||
'regular prop. It will be removed from the JSX Element ' +
|
||||
'type in a future release.',
|
||||
],
|
||||
{
|
||||
withoutStack: true,
|
||||
},
|
||||
);
|
||||
assertConsoleErrorDev([
|
||||
'Accessing element.ref was removed in React 19. ref is now a ' +
|
||||
'regular prop. It will be removed from the JSX Element ' +
|
||||
'type in a future release.',
|
||||
]);
|
||||
const expectation = {foo: '56', ref};
|
||||
Object.freeze(expectation);
|
||||
expect(element.props).toEqual(expectation);
|
||||
@@ -429,16 +421,11 @@ describe('ReactCreateElement', () => {
|
||||
it('warns if outdated JSX transform is detected', async () => {
|
||||
// Warns if __self is detected, because that's only passed by a compiler
|
||||
React.createElement('div', {className: 'foo', __self: this});
|
||||
assertConsoleWarnDev(
|
||||
[
|
||||
'Your app (or one of its dependencies) is using an outdated JSX ' +
|
||||
'transform. Update to the modern JSX transform for ' +
|
||||
'faster performance: https://react.dev/link/new-jsx-transform',
|
||||
],
|
||||
{
|
||||
withoutStack: true,
|
||||
},
|
||||
);
|
||||
assertConsoleWarnDev([
|
||||
'Your app (or one of its dependencies) is using an outdated JSX ' +
|
||||
'transform. Update to the modern JSX transform for ' +
|
||||
'faster performance: https://react.dev/link/new-jsx-transform',
|
||||
]);
|
||||
|
||||
// Only warns the first time. Subsequent elements don't warn.
|
||||
React.createElement('div', {className: 'foo', __self: this});
|
||||
|
||||
@@ -589,22 +589,16 @@ describe('ReactES6Class', () => {
|
||||
runTest(<Inner name="foo" ref={ref} />, 'DIV', 'foo');
|
||||
|
||||
expect(() => ref.current.replaceState({})).toThrow();
|
||||
assertConsoleWarnDev(
|
||||
[
|
||||
'replaceState(...) is deprecated in plain JavaScript React classes. ' +
|
||||
'Refactor your code to use setState instead (see https://github.com/facebook/react/issues/3236).',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
assertConsoleWarnDev([
|
||||
'replaceState(...) is deprecated in plain JavaScript React classes. ' +
|
||||
'Refactor your code to use setState instead (see https://github.com/facebook/react/issues/3236).',
|
||||
]);
|
||||
expect(() => ref.current.isMounted()).toThrow();
|
||||
assertConsoleWarnDev(
|
||||
[
|
||||
'isMounted(...) is deprecated in plain JavaScript React classes. ' +
|
||||
'Instead, make sure to clean up subscriptions and pending requests in ' +
|
||||
'componentWillUnmount to prevent memory leaks.',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
assertConsoleWarnDev([
|
||||
'isMounted(...) is deprecated in plain JavaScript React classes. ' +
|
||||
'Instead, make sure to clean up subscriptions and pending requests in ' +
|
||||
'componentWillUnmount to prevent memory leaks.',
|
||||
]);
|
||||
});
|
||||
|
||||
if (!require('shared/ReactFeatureFlags').disableLegacyContext) {
|
||||
|
||||
@@ -346,16 +346,11 @@ describe('ReactElementClone', () => {
|
||||
expect(clone.key).toBe('12');
|
||||
expect(clone.props.ref).toBe('34');
|
||||
expect(clone.ref).toBe('34');
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'Accessing element.ref was removed in React 19. ref is now a ' +
|
||||
'regular prop. It will be removed from the JSX Element ' +
|
||||
'type in a future release.',
|
||||
],
|
||||
{
|
||||
withoutStack: true,
|
||||
},
|
||||
);
|
||||
assertConsoleErrorDev([
|
||||
'Accessing element.ref was removed in React 19. ref is now a ' +
|
||||
'regular prop. It will be removed from the JSX Element ' +
|
||||
'type in a future release.',
|
||||
]);
|
||||
expect(clone.props).toEqual({foo: 'ef', ref: '34'});
|
||||
if (__DEV__) {
|
||||
expect(Object.isFrozen(element)).toBe(true);
|
||||
|
||||
@@ -225,28 +225,22 @@ describe('ReactJSXRuntime', () => {
|
||||
await act(() => {
|
||||
root.render(JSXRuntime.jsxs('div', {children: 'foo'}, null));
|
||||
});
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'React.jsx: Static children should always be an array. ' +
|
||||
'You are likely explicitly calling React.jsxs or React.jsxDEV. ' +
|
||||
'Use the Babel transform instead.',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
assertConsoleErrorDev([
|
||||
'React.jsx: Static children should always be an array. ' +
|
||||
'You are likely explicitly calling React.jsxs or React.jsxDEV. ' +
|
||||
'Use the Babel transform instead.',
|
||||
]);
|
||||
});
|
||||
|
||||
it('should warn when `key` is being accessed on a host element', () => {
|
||||
const element = JSXRuntime.jsxs('div', {}, '3');
|
||||
void element.props.key;
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'div: `key` is not a prop. Trying to access it will result ' +
|
||||
'in `undefined` being returned. If you need to access the same ' +
|
||||
'value within the child component, you should pass it as a different ' +
|
||||
'prop. (https://react.dev/link/special-props)',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
assertConsoleErrorDev([
|
||||
'div: `key` is not a prop. Trying to access it will result ' +
|
||||
'in `undefined` being returned. If you need to access the same ' +
|
||||
'value within the child component, you should pass it as a different ' +
|
||||
'prop. (https://react.dev/link/special-props)',
|
||||
]);
|
||||
});
|
||||
|
||||
it('should warn when unkeyed children are passed to jsx', async () => {
|
||||
@@ -372,17 +366,14 @@ describe('ReactJSXRuntime', () => {
|
||||
const elementWithSpreadKey = __DEV__
|
||||
? JSXDEVRuntime.jsxDEV('div', configWithKey)
|
||||
: JSXRuntime.jsx('div', configWithKey);
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'A props object containing a "key" prop is being spread into JSX:\n' +
|
||||
' let props = {key: someKey, foo: ..., bar: ...};\n' +
|
||||
' <div {...props} />\n' +
|
||||
'React keys must be passed directly to JSX without using spread:\n' +
|
||||
' let props = {foo: ..., bar: ...};\n' +
|
||||
' <div key={someKey} {...props} />',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
assertConsoleErrorDev([
|
||||
'A props object containing a "key" prop is being spread into JSX:\n' +
|
||||
' let props = {key: someKey, foo: ..., bar: ...};\n' +
|
||||
' <div {...props} />\n' +
|
||||
'React keys must be passed directly to JSX without using spread:\n' +
|
||||
' let props = {foo: ..., bar: ...};\n' +
|
||||
' <div key={someKey} {...props} />',
|
||||
]);
|
||||
expect(elementWithSpreadKey.props).not.toBe(configWithKey);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -114,14 +114,11 @@ describe('ReactJSXTransformIntegration', () => {
|
||||
const element = <Component ref={ref} foo="56" />;
|
||||
expect(element.type).toBe(Component);
|
||||
expect(element.ref).toBe(ref);
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'Accessing element.ref was removed in React 19. ref is now a ' +
|
||||
'regular prop. It will be removed from the JSX Element ' +
|
||||
'type in a future release.',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
assertConsoleErrorDev([
|
||||
'Accessing element.ref was removed in React 19. ref is now a ' +
|
||||
'regular prop. It will be removed from the JSX Element ' +
|
||||
'type in a future release.',
|
||||
]);
|
||||
const expectation = {foo: '56', ref};
|
||||
Object.freeze(expectation);
|
||||
expect(element.props).toEqual(expectation);
|
||||
|
||||
@@ -59,14 +59,9 @@ describe('Profiler', () => {
|
||||
await act(() => {
|
||||
root.render(<React.Profiler />);
|
||||
});
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'Profiler must specify an "id" of type `string` as a prop. Received the type `undefined` instead.',
|
||||
],
|
||||
{
|
||||
withoutStack: true,
|
||||
},
|
||||
);
|
||||
assertConsoleErrorDev([
|
||||
'Profiler must specify an "id" of type `string` as a prop. Received the type `undefined` instead.',
|
||||
]);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -61,14 +61,11 @@ describe('ReactStartTransition', () => {
|
||||
});
|
||||
});
|
||||
});
|
||||
assertConsoleWarnDev(
|
||||
[
|
||||
'Detected a large number of updates inside startTransition. ' +
|
||||
'If this is due to a subscription please re-write it to use React provided hooks. ' +
|
||||
'Otherwise concurrent mode guarantees are off the table.',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
assertConsoleWarnDev([
|
||||
'Detected a large number of updates inside startTransition. ' +
|
||||
'If this is due to a subscription please re-write it to use React provided hooks. ' +
|
||||
'Otherwise concurrent mode guarantees are off the table.',
|
||||
]);
|
||||
|
||||
await act(() => {
|
||||
triggerHookTransition(() => {
|
||||
@@ -77,13 +74,10 @@ describe('ReactStartTransition', () => {
|
||||
});
|
||||
});
|
||||
});
|
||||
assertConsoleWarnDev(
|
||||
[
|
||||
'Detected a large number of updates inside startTransition. ' +
|
||||
'If this is due to a subscription please re-write it to use React provided hooks. ' +
|
||||
'Otherwise concurrent mode guarantees are off the table.',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
assertConsoleWarnDev([
|
||||
'Detected a large number of updates inside startTransition. ' +
|
||||
'If this is due to a subscription please re-write it to use React provided hooks. ' +
|
||||
'Otherwise concurrent mode guarantees are off the table.',
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -624,27 +624,24 @@ describe('Concurrent Mode', () => {
|
||||
const container = document.createElement('div');
|
||||
const root = ReactDOMClient.createRoot(container);
|
||||
await act(() => root.render(<StrictRoot />));
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
`Using UNSAFE_componentWillMount in strict mode is not recommended and may indicate bugs in your code. See https://react.dev/link/unsafe-component-lifecycles for details.
|
||||
assertConsoleErrorDev([
|
||||
`Using UNSAFE_componentWillMount in strict mode is not recommended and may indicate bugs in your code. See https://react.dev/link/unsafe-component-lifecycles for details.
|
||||
|
||||
* Move code with side effects to componentDidMount, and set initial state in the constructor.
|
||||
|
||||
Please update the following components: App`,
|
||||
`Using UNSAFE_componentWillReceiveProps in strict mode is not recommended and may indicate bugs in your code. See https://react.dev/link/unsafe-component-lifecycles for details.
|
||||
`Using UNSAFE_componentWillReceiveProps in strict mode is not recommended and may indicate bugs in your code. See https://react.dev/link/unsafe-component-lifecycles for details.
|
||||
|
||||
* Move data fetching code or side effects to componentDidUpdate.
|
||||
* If you're updating state whenever props change, refactor your code to use memoization techniques or move it to static getDerivedStateFromProps. Learn more at: https://react.dev/link/derived-state
|
||||
|
||||
Please update the following components: Bar, Foo`,
|
||||
`Using UNSAFE_componentWillUpdate in strict mode is not recommended and may indicate bugs in your code. See https://react.dev/link/unsafe-component-lifecycles for details.
|
||||
`Using UNSAFE_componentWillUpdate in strict mode is not recommended and may indicate bugs in your code. See https://react.dev/link/unsafe-component-lifecycles for details.
|
||||
|
||||
* Move data fetching code or side effects to componentDidUpdate.
|
||||
|
||||
Please update the following components: App`,
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
]);
|
||||
|
||||
// Dedupe
|
||||
await act(() => root.render(<App />));
|
||||
@@ -684,51 +681,45 @@ Please update the following components: App`,
|
||||
const root = ReactDOMClient.createRoot(container);
|
||||
|
||||
await act(() => root.render(<StrictRoot />));
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
`Using UNSAFE_componentWillMount in strict mode is not recommended and may indicate bugs in your code. See https://react.dev/link/unsafe-component-lifecycles for details.
|
||||
assertConsoleErrorDev([
|
||||
`Using UNSAFE_componentWillMount in strict mode is not recommended and may indicate bugs in your code. See https://react.dev/link/unsafe-component-lifecycles for details.
|
||||
|
||||
* Move code with side effects to componentDidMount, and set initial state in the constructor.
|
||||
|
||||
Please update the following components: App`,
|
||||
`Using UNSAFE_componentWillReceiveProps in strict mode is not recommended and may indicate bugs in your code. See https://react.dev/link/unsafe-component-lifecycles for details.
|
||||
`Using UNSAFE_componentWillReceiveProps in strict mode is not recommended and may indicate bugs in your code. See https://react.dev/link/unsafe-component-lifecycles for details.
|
||||
|
||||
* Move data fetching code or side effects to componentDidUpdate.
|
||||
* If you're updating state whenever props change, refactor your code to use memoization techniques or move it to static getDerivedStateFromProps. Learn more at: https://react.dev/link/derived-state
|
||||
|
||||
Please update the following components: Child`,
|
||||
`Using UNSAFE_componentWillUpdate in strict mode is not recommended and may indicate bugs in your code. See https://react.dev/link/unsafe-component-lifecycles for details.
|
||||
`Using UNSAFE_componentWillUpdate in strict mode is not recommended and may indicate bugs in your code. See https://react.dev/link/unsafe-component-lifecycles for details.
|
||||
|
||||
* Move data fetching code or side effects to componentDidUpdate.
|
||||
|
||||
Please update the following components: App`,
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
assertConsoleWarnDev(
|
||||
[
|
||||
`componentWillMount has been renamed, and is not recommended for use. See https://react.dev/link/unsafe-component-lifecycles for details.
|
||||
]);
|
||||
assertConsoleWarnDev([
|
||||
`componentWillMount has been renamed, and is not recommended for use. See https://react.dev/link/unsafe-component-lifecycles for details.
|
||||
|
||||
* Move code with side effects to componentDidMount, and set initial state in the constructor.
|
||||
* Rename componentWillMount to UNSAFE_componentWillMount to suppress this warning in non-strict mode. In React 18.x, only the UNSAFE_ name will work. To rename all deprecated lifecycles to their new names, you can run \`npx react-codemod rename-unsafe-lifecycles\` in your project source folder.
|
||||
|
||||
Please update the following components: Parent`,
|
||||
`componentWillReceiveProps has been renamed, and is not recommended for use. See https://react.dev/link/unsafe-component-lifecycles for details.
|
||||
`componentWillReceiveProps has been renamed, and is not recommended for use. See https://react.dev/link/unsafe-component-lifecycles for details.
|
||||
|
||||
* Move data fetching code or side effects to componentDidUpdate.
|
||||
* If you're updating state whenever props change, refactor your code to use memoization techniques or move it to static getDerivedStateFromProps. Learn more at: https://react.dev/link/derived-state
|
||||
* Rename componentWillReceiveProps to UNSAFE_componentWillReceiveProps to suppress this warning in non-strict mode. In React 18.x, only the UNSAFE_ name will work. To rename all deprecated lifecycles to their new names, you can run \`npx react-codemod rename-unsafe-lifecycles\` in your project source folder.
|
||||
|
||||
Please update the following components: Parent`,
|
||||
`componentWillUpdate has been renamed, and is not recommended for use. See https://react.dev/link/unsafe-component-lifecycles for details.
|
||||
`componentWillUpdate has been renamed, and is not recommended for use. See https://react.dev/link/unsafe-component-lifecycles for details.
|
||||
|
||||
* Move data fetching code or side effects to componentDidUpdate.
|
||||
* Rename componentWillUpdate to UNSAFE_componentWillUpdate to suppress this warning in non-strict mode. In React 18.x, only the UNSAFE_ name will work. To rename all deprecated lifecycles to their new names, you can run \`npx react-codemod rename-unsafe-lifecycles\` in your project source folder.
|
||||
|
||||
Please update the following components: Parent`,
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
]);
|
||||
// Dedupe
|
||||
await act(() => root.render(<StrictRoot />));
|
||||
});
|
||||
@@ -753,26 +744,20 @@ Please update the following components: Parent`,
|
||||
const container = document.createElement('div');
|
||||
const root = ReactDOMClient.createRoot(container);
|
||||
await act(() => root.render(<StrictRoot foo={true} />));
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'Using UNSAFE_componentWillMount in strict mode is not recommended and may indicate bugs in your code. ' +
|
||||
'See https://react.dev/link/unsafe-component-lifecycles for details.\n\n' +
|
||||
'* Move code with side effects to componentDidMount, and set initial state in the constructor.\n\n' +
|
||||
'Please update the following components: Foo',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
assertConsoleErrorDev([
|
||||
'Using UNSAFE_componentWillMount in strict mode is not recommended and may indicate bugs in your code. ' +
|
||||
'See https://react.dev/link/unsafe-component-lifecycles for details.\n\n' +
|
||||
'* Move code with side effects to componentDidMount, and set initial state in the constructor.\n\n' +
|
||||
'Please update the following components: Foo',
|
||||
]);
|
||||
|
||||
await act(() => root.render(<StrictRoot foo={false} />));
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'Using UNSAFE_componentWillMount in strict mode is not recommended and may indicate bugs in your code. ' +
|
||||
'See https://react.dev/link/unsafe-component-lifecycles for details.\n\n' +
|
||||
'* Move code with side effects to componentDidMount, and set initial state in the constructor.\n\n' +
|
||||
'Please update the following components: Bar',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
assertConsoleErrorDev([
|
||||
'Using UNSAFE_componentWillMount in strict mode is not recommended and may indicate bugs in your code. ' +
|
||||
'See https://react.dev/link/unsafe-component-lifecycles for details.\n\n' +
|
||||
'* Move code with side effects to componentDidMount, and set initial state in the constructor.\n\n' +
|
||||
'Please update the following components: Bar',
|
||||
]);
|
||||
|
||||
// Dedupe
|
||||
await act(() => root.render(<StrictRoot foo={true} />));
|
||||
@@ -821,19 +806,16 @@ Please update the following components: Parent`,
|
||||
await act(() => {
|
||||
root.render(<SyncRoot />);
|
||||
});
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'Using UNSAFE_componentWillReceiveProps in strict mode is not recommended ' +
|
||||
'and may indicate bugs in your code. ' +
|
||||
'See https://react.dev/link/unsafe-component-lifecycles for details.\n\n' +
|
||||
'* Move data fetching code or side effects to componentDidUpdate.\n' +
|
||||
"* If you're updating state whenever props change, " +
|
||||
'refactor your code to use memoization techniques or move it to ' +
|
||||
'static getDerivedStateFromProps. Learn more at: https://react.dev/link/derived-state\n\n' +
|
||||
'Please update the following components: Bar, Foo',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
assertConsoleErrorDev([
|
||||
'Using UNSAFE_componentWillReceiveProps in strict mode is not recommended ' +
|
||||
'and may indicate bugs in your code. ' +
|
||||
'See https://react.dev/link/unsafe-component-lifecycles for details.\n\n' +
|
||||
'* Move data fetching code or side effects to componentDidUpdate.\n' +
|
||||
"* If you're updating state whenever props change, " +
|
||||
'refactor your code to use memoization techniques or move it to ' +
|
||||
'static getDerivedStateFromProps. Learn more at: https://react.dev/link/derived-state\n\n' +
|
||||
'Please update the following components: Bar, Foo',
|
||||
]);
|
||||
|
||||
// Dedupe
|
||||
await act(() => {
|
||||
|
||||
@@ -694,22 +694,16 @@ describe('ReactTypeScriptClass', function () {
|
||||
const ref = React.createRef();
|
||||
test(React.createElement(Inner, {name: 'foo', ref: ref}), 'DIV', 'foo');
|
||||
expect(() => ref.current.replaceState({})).toThrow();
|
||||
assertConsoleWarnDev(
|
||||
[
|
||||
'replaceState(...) is deprecated in plain JavaScript React classes. ' +
|
||||
'Refactor your code to use setState instead (see https://github.com/facebook/react/issues/3236).',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
assertConsoleWarnDev([
|
||||
'replaceState(...) is deprecated in plain JavaScript React classes. ' +
|
||||
'Refactor your code to use setState instead (see https://github.com/facebook/react/issues/3236).',
|
||||
]);
|
||||
expect(() => ref.current.isMounted()).toThrow();
|
||||
assertConsoleWarnDev(
|
||||
[
|
||||
'isMounted(...) is deprecated in plain JavaScript React classes. ' +
|
||||
'Instead, make sure to clean up subscriptions and pending requests in ' +
|
||||
'componentWillUnmount to prevent memory leaks.',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
assertConsoleWarnDev([
|
||||
'isMounted(...) is deprecated in plain JavaScript React classes. ' +
|
||||
'Instead, make sure to clean up subscriptions and pending requests in ' +
|
||||
'componentWillUnmount to prevent memory leaks.',
|
||||
]);
|
||||
});
|
||||
|
||||
if (!ReactFeatureFlags.disableLegacyContext) {
|
||||
|
||||
@@ -67,13 +67,10 @@ describe('create-react-class-integration', () => {
|
||||
return <span>{this.props.prop}</span>;
|
||||
},
|
||||
});
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'Warning: Component: prop type `prop` is invalid; ' +
|
||||
'it must be a function, usually from React.PropTypes.',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
assertConsoleErrorDev([
|
||||
'Warning: Component: prop type `prop` is invalid; ' +
|
||||
'it must be a function, usually from React.PropTypes.',
|
||||
]);
|
||||
});
|
||||
|
||||
it('should warn on invalid context types', () => {
|
||||
@@ -86,13 +83,10 @@ describe('create-react-class-integration', () => {
|
||||
return <span>{this.props.prop}</span>;
|
||||
},
|
||||
});
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'Warning: Component: context type `prop` is invalid; ' +
|
||||
'it must be a function, usually from React.PropTypes.',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
assertConsoleErrorDev([
|
||||
'Warning: Component: context type `prop` is invalid; ' +
|
||||
'it must be a function, usually from React.PropTypes.',
|
||||
]);
|
||||
});
|
||||
|
||||
it('should throw on invalid child context types', () => {
|
||||
@@ -105,12 +99,9 @@ describe('create-react-class-integration', () => {
|
||||
return <span>{this.props.prop}</span>;
|
||||
},
|
||||
});
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'Warning: Component: child context type `prop` is invalid; it must be a function, usually from React.PropTypes.',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
assertConsoleErrorDev([
|
||||
'Warning: Component: child context type `prop` is invalid; it must be a function, usually from React.PropTypes.',
|
||||
]);
|
||||
});
|
||||
|
||||
it('should warn when misspelling shouldComponentUpdate', () => {
|
||||
@@ -122,14 +113,11 @@ describe('create-react-class-integration', () => {
|
||||
return <div />;
|
||||
},
|
||||
});
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'Warning: A component has a method called componentShouldUpdate(). Did you ' +
|
||||
'mean shouldComponentUpdate()? The name is phrased as a question ' +
|
||||
'because the function is expected to return a value.',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
assertConsoleErrorDev([
|
||||
'Warning: A component has a method called componentShouldUpdate(). Did you ' +
|
||||
'mean shouldComponentUpdate()? The name is phrased as a question ' +
|
||||
'because the function is expected to return a value.',
|
||||
]);
|
||||
|
||||
createReactClass({
|
||||
displayName: 'NamedComponent',
|
||||
@@ -140,14 +128,11 @@ describe('create-react-class-integration', () => {
|
||||
return <div />;
|
||||
},
|
||||
});
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'Warning: NamedComponent has a method called componentShouldUpdate(). Did you ' +
|
||||
'mean shouldComponentUpdate()? The name is phrased as a question ' +
|
||||
'because the function is expected to return a value.',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
assertConsoleErrorDev([
|
||||
'Warning: NamedComponent has a method called componentShouldUpdate(). Did you ' +
|
||||
'mean shouldComponentUpdate()? The name is phrased as a question ' +
|
||||
'because the function is expected to return a value.',
|
||||
]);
|
||||
});
|
||||
|
||||
it('should warn when misspelling componentWillReceiveProps', () => {
|
||||
@@ -159,13 +144,10 @@ describe('create-react-class-integration', () => {
|
||||
return <div />;
|
||||
},
|
||||
});
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'Warning: A component has a method called componentWillRecieveProps(). Did you ' +
|
||||
'mean componentWillReceiveProps()?',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
assertConsoleErrorDev([
|
||||
'Warning: A component has a method called componentWillRecieveProps(). Did you ' +
|
||||
'mean componentWillReceiveProps()?',
|
||||
]);
|
||||
});
|
||||
|
||||
it('should warn when misspelling UNSAFE_componentWillReceiveProps', () => {
|
||||
@@ -177,13 +159,10 @@ describe('create-react-class-integration', () => {
|
||||
return <div />;
|
||||
},
|
||||
});
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'Warning: A component has a method called UNSAFE_componentWillRecieveProps(). ' +
|
||||
'Did you mean UNSAFE_componentWillReceiveProps()?',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
assertConsoleErrorDev([
|
||||
'Warning: A component has a method called UNSAFE_componentWillRecieveProps(). ' +
|
||||
'Did you mean UNSAFE_componentWillReceiveProps()?',
|
||||
]);
|
||||
});
|
||||
|
||||
it('should throw if a reserved property is in statics', () => {
|
||||
@@ -348,11 +327,8 @@ describe('create-react-class-integration', () => {
|
||||
root.render(<Outer />);
|
||||
});
|
||||
assertConsoleErrorDev([
|
||||
[
|
||||
'Component uses the legacy childContextTypes API which will soon be removed. ' +
|
||||
'Use React.createContext() instead. (https://react.dev/link/legacy-context)',
|
||||
{withoutStack: true},
|
||||
],
|
||||
'Component uses the legacy childContextTypes API which will soon be removed. ' +
|
||||
'Use React.createContext() instead. (https://react.dev/link/legacy-context)',
|
||||
'Component uses the legacy contextTypes API which will soon be removed. ' +
|
||||
'Use React.createContext() with static contextType instead. (https://react.dev/link/legacy-context)' +
|
||||
'\n in ReactClassComponent (at **)',
|
||||
@@ -409,13 +385,10 @@ describe('create-react-class-integration', () => {
|
||||
});
|
||||
|
||||
expect(() => Component()).toThrow();
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'Warning: Something is calling a React component directly. Use a ' +
|
||||
'factory or JSX instead. See: https://fb.me/react-legacyfactory',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
assertConsoleErrorDev([
|
||||
'Warning: Something is calling a React component directly. Use a ' +
|
||||
'factory or JSX instead. See: https://fb.me/react-legacyfactory',
|
||||
]);
|
||||
});
|
||||
|
||||
it('replaceState and callback works', async () => {
|
||||
@@ -635,38 +608,35 @@ describe('create-react-class-integration', () => {
|
||||
'https://react.dev/link/unsafe-component-lifecycles\n' +
|
||||
' in Component (at **)',
|
||||
]);
|
||||
assertConsoleWarnDev(
|
||||
[
|
||||
'componentWillMount has been renamed, and is not recommended for use. ' +
|
||||
'See https://react.dev/link/unsafe-component-lifecycles for details.\n\n' +
|
||||
'* Move code with side effects to componentDidMount, and set initial state in the constructor.\n' +
|
||||
'* Rename componentWillMount to UNSAFE_componentWillMount to suppress ' +
|
||||
'this warning in non-strict mode. In React 18.x, only the UNSAFE_ name will work. ' +
|
||||
'To rename all deprecated lifecycles to their new names, you can run ' +
|
||||
'`npx react-codemod rename-unsafe-lifecycles` in your project source folder.\n' +
|
||||
'\nPlease update the following components: Component',
|
||||
'componentWillReceiveProps has been renamed, and is not recommended for use. ' +
|
||||
'See https://react.dev/link/unsafe-component-lifecycles for details.\n\n' +
|
||||
'* Move data fetching code or side effects to componentDidUpdate.\n' +
|
||||
"* If you're updating state whenever props change, refactor your " +
|
||||
'code to use memoization techniques or move it to ' +
|
||||
'static getDerivedStateFromProps. Learn more at: https://react.dev/link/derived-state\n' +
|
||||
'* Rename componentWillReceiveProps to UNSAFE_componentWillReceiveProps to suppress ' +
|
||||
'this warning in non-strict mode. In React 18.x, only the UNSAFE_ name will work. ' +
|
||||
'To rename all deprecated lifecycles to their new names, you can run ' +
|
||||
'`npx react-codemod rename-unsafe-lifecycles` in your project source folder.\n' +
|
||||
'\nPlease update the following components: Component',
|
||||
'componentWillUpdate has been renamed, and is not recommended for use. ' +
|
||||
'See https://react.dev/link/unsafe-component-lifecycles for details.\n\n' +
|
||||
'* Move data fetching code or side effects to componentDidUpdate.\n' +
|
||||
'* Rename componentWillUpdate to UNSAFE_componentWillUpdate to suppress ' +
|
||||
'this warning in non-strict mode. In React 18.x, only the UNSAFE_ name will work. ' +
|
||||
'To rename all deprecated lifecycles to their new names, you can run ' +
|
||||
'`npx react-codemod rename-unsafe-lifecycles` in your project source folder.\n' +
|
||||
'\nPlease update the following components: Component',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
assertConsoleWarnDev([
|
||||
'componentWillMount has been renamed, and is not recommended for use. ' +
|
||||
'See https://react.dev/link/unsafe-component-lifecycles for details.\n\n' +
|
||||
'* Move code with side effects to componentDidMount, and set initial state in the constructor.\n' +
|
||||
'* Rename componentWillMount to UNSAFE_componentWillMount to suppress ' +
|
||||
'this warning in non-strict mode. In React 18.x, only the UNSAFE_ name will work. ' +
|
||||
'To rename all deprecated lifecycles to their new names, you can run ' +
|
||||
'`npx react-codemod rename-unsafe-lifecycles` in your project source folder.\n' +
|
||||
'\nPlease update the following components: Component',
|
||||
'componentWillReceiveProps has been renamed, and is not recommended for use. ' +
|
||||
'See https://react.dev/link/unsafe-component-lifecycles for details.\n\n' +
|
||||
'* Move data fetching code or side effects to componentDidUpdate.\n' +
|
||||
"* If you're updating state whenever props change, refactor your " +
|
||||
'code to use memoization techniques or move it to ' +
|
||||
'static getDerivedStateFromProps. Learn more at: https://react.dev/link/derived-state\n' +
|
||||
'* Rename componentWillReceiveProps to UNSAFE_componentWillReceiveProps to suppress ' +
|
||||
'this warning in non-strict mode. In React 18.x, only the UNSAFE_ name will work. ' +
|
||||
'To rename all deprecated lifecycles to their new names, you can run ' +
|
||||
'`npx react-codemod rename-unsafe-lifecycles` in your project source folder.\n' +
|
||||
'\nPlease update the following components: Component',
|
||||
'componentWillUpdate has been renamed, and is not recommended for use. ' +
|
||||
'See https://react.dev/link/unsafe-component-lifecycles for details.\n\n' +
|
||||
'* Move data fetching code or side effects to componentDidUpdate.\n' +
|
||||
'* Rename componentWillUpdate to UNSAFE_componentWillUpdate to suppress ' +
|
||||
'this warning in non-strict mode. In React 18.x, only the UNSAFE_ name will work. ' +
|
||||
'To rename all deprecated lifecycles to their new names, you can run ' +
|
||||
'`npx react-codemod rename-unsafe-lifecycles` in your project source folder.\n' +
|
||||
'\nPlease update the following components: Component',
|
||||
]);
|
||||
await act(() => {
|
||||
root.render(<Component foo={1} />);
|
||||
});
|
||||
@@ -707,38 +677,35 @@ describe('create-react-class-integration', () => {
|
||||
'https://react.dev/link/unsafe-component-lifecycles\n' +
|
||||
' in Component (at **)',
|
||||
]);
|
||||
assertConsoleWarnDev(
|
||||
[
|
||||
'componentWillMount has been renamed, and is not recommended for use. ' +
|
||||
'See https://react.dev/link/unsafe-component-lifecycles for details.\n\n' +
|
||||
'* Move code with side effects to componentDidMount, and set initial state in the constructor.\n' +
|
||||
'* Rename componentWillMount to UNSAFE_componentWillMount to suppress ' +
|
||||
'this warning in non-strict mode. In React 18.x, only the UNSAFE_ name will work. ' +
|
||||
'To rename all deprecated lifecycles to their new names, you can run ' +
|
||||
'`npx react-codemod rename-unsafe-lifecycles` in your project source folder.\n' +
|
||||
'\nPlease update the following components: Component',
|
||||
'componentWillReceiveProps has been renamed, and is not recommended for use. ' +
|
||||
'See https://react.dev/link/unsafe-component-lifecycles for details.\n\n' +
|
||||
'* Move data fetching code or side effects to componentDidUpdate.\n' +
|
||||
"* If you're updating state whenever props change, refactor your " +
|
||||
'code to use memoization techniques or move it to ' +
|
||||
'static getDerivedStateFromProps. Learn more at: https://react.dev/link/derived-state\n' +
|
||||
'* Rename componentWillReceiveProps to UNSAFE_componentWillReceiveProps to suppress ' +
|
||||
'this warning in non-strict mode. In React 18.x, only the UNSAFE_ name will work. ' +
|
||||
'To rename all deprecated lifecycles to their new names, you can run ' +
|
||||
'`npx react-codemod rename-unsafe-lifecycles` in your project source folder.\n' +
|
||||
'\nPlease update the following components: Component',
|
||||
'componentWillUpdate has been renamed, and is not recommended for use. ' +
|
||||
'See https://react.dev/link/unsafe-component-lifecycles for details.\n\n' +
|
||||
'* Move data fetching code or side effects to componentDidUpdate.\n' +
|
||||
'* Rename componentWillUpdate to UNSAFE_componentWillUpdate to suppress ' +
|
||||
'this warning in non-strict mode. In React 18.x, only the UNSAFE_ name will work. ' +
|
||||
'To rename all deprecated lifecycles to their new names, you can run ' +
|
||||
'`npx react-codemod rename-unsafe-lifecycles` in your project source folder.\n' +
|
||||
'\nPlease update the following components: Component',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
assertConsoleWarnDev([
|
||||
'componentWillMount has been renamed, and is not recommended for use. ' +
|
||||
'See https://react.dev/link/unsafe-component-lifecycles for details.\n\n' +
|
||||
'* Move code with side effects to componentDidMount, and set initial state in the constructor.\n' +
|
||||
'* Rename componentWillMount to UNSAFE_componentWillMount to suppress ' +
|
||||
'this warning in non-strict mode. In React 18.x, only the UNSAFE_ name will work. ' +
|
||||
'To rename all deprecated lifecycles to their new names, you can run ' +
|
||||
'`npx react-codemod rename-unsafe-lifecycles` in your project source folder.\n' +
|
||||
'\nPlease update the following components: Component',
|
||||
'componentWillReceiveProps has been renamed, and is not recommended for use. ' +
|
||||
'See https://react.dev/link/unsafe-component-lifecycles for details.\n\n' +
|
||||
'* Move data fetching code or side effects to componentDidUpdate.\n' +
|
||||
"* If you're updating state whenever props change, refactor your " +
|
||||
'code to use memoization techniques or move it to ' +
|
||||
'static getDerivedStateFromProps. Learn more at: https://react.dev/link/derived-state\n' +
|
||||
'* Rename componentWillReceiveProps to UNSAFE_componentWillReceiveProps to suppress ' +
|
||||
'this warning in non-strict mode. In React 18.x, only the UNSAFE_ name will work. ' +
|
||||
'To rename all deprecated lifecycles to their new names, you can run ' +
|
||||
'`npx react-codemod rename-unsafe-lifecycles` in your project source folder.\n' +
|
||||
'\nPlease update the following components: Component',
|
||||
'componentWillUpdate has been renamed, and is not recommended for use. ' +
|
||||
'See https://react.dev/link/unsafe-component-lifecycles for details.\n\n' +
|
||||
'* Move data fetching code or side effects to componentDidUpdate.\n' +
|
||||
'* Rename componentWillUpdate to UNSAFE_componentWillUpdate to suppress ' +
|
||||
'this warning in non-strict mode. In React 18.x, only the UNSAFE_ name will work. ' +
|
||||
'To rename all deprecated lifecycles to their new names, you can run ' +
|
||||
'`npx react-codemod rename-unsafe-lifecycles` in your project source folder.\n' +
|
||||
'\nPlease update the following components: Component',
|
||||
]);
|
||||
await act(() => {
|
||||
const root2 = ReactDOMClient.createRoot(document.createElement('div'));
|
||||
root2.render(<Component foo={1} />);
|
||||
@@ -781,38 +748,35 @@ describe('create-react-class-integration', () => {
|
||||
await act(() => {
|
||||
root.render(<Component foo="bar" />);
|
||||
});
|
||||
assertConsoleWarnDev(
|
||||
[
|
||||
'componentWillMount has been renamed, and is not recommended for use. ' +
|
||||
'See https://react.dev/link/unsafe-component-lifecycles for details.\n\n' +
|
||||
'* Move code with side effects to componentDidMount, and set initial state in the constructor.\n' +
|
||||
'* Rename componentWillMount to UNSAFE_componentWillMount to suppress ' +
|
||||
'this warning in non-strict mode. In React 18.x, only the UNSAFE_ name will work. ' +
|
||||
'To rename all deprecated lifecycles to their new names, you can run ' +
|
||||
'`npx react-codemod rename-unsafe-lifecycles` in your project source folder.\n' +
|
||||
'\nPlease update the following components: Component',
|
||||
'componentWillReceiveProps has been renamed, and is not recommended for use. ' +
|
||||
'See https://react.dev/link/unsafe-component-lifecycles for details.\n\n' +
|
||||
'* Move data fetching code or side effects to componentDidUpdate.\n' +
|
||||
"* If you're updating state whenever props change, refactor your " +
|
||||
'code to use memoization techniques or move it to ' +
|
||||
'static getDerivedStateFromProps. Learn more at: https://react.dev/link/derived-state\n' +
|
||||
'* Rename componentWillReceiveProps to UNSAFE_componentWillReceiveProps to suppress ' +
|
||||
'this warning in non-strict mode. In React 18.x, only the UNSAFE_ name will work. ' +
|
||||
'To rename all deprecated lifecycles to their new names, you can run ' +
|
||||
'`npx react-codemod rename-unsafe-lifecycles` in your project source folder.\n' +
|
||||
'\nPlease update the following components: Component',
|
||||
'componentWillUpdate has been renamed, and is not recommended for use. ' +
|
||||
'See https://react.dev/link/unsafe-component-lifecycles for details.\n\n' +
|
||||
'* Move data fetching code or side effects to componentDidUpdate.\n' +
|
||||
'* Rename componentWillUpdate to UNSAFE_componentWillUpdate to suppress ' +
|
||||
'this warning in non-strict mode. In React 18.x, only the UNSAFE_ name will work. ' +
|
||||
'To rename all deprecated lifecycles to their new names, you can run ' +
|
||||
'`npx react-codemod rename-unsafe-lifecycles` in your project source folder.\n' +
|
||||
'\nPlease update the following components: Component',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
assertConsoleWarnDev([
|
||||
'componentWillMount has been renamed, and is not recommended for use. ' +
|
||||
'See https://react.dev/link/unsafe-component-lifecycles for details.\n\n' +
|
||||
'* Move code with side effects to componentDidMount, and set initial state in the constructor.\n' +
|
||||
'* Rename componentWillMount to UNSAFE_componentWillMount to suppress ' +
|
||||
'this warning in non-strict mode. In React 18.x, only the UNSAFE_ name will work. ' +
|
||||
'To rename all deprecated lifecycles to their new names, you can run ' +
|
||||
'`npx react-codemod rename-unsafe-lifecycles` in your project source folder.\n' +
|
||||
'\nPlease update the following components: Component',
|
||||
'componentWillReceiveProps has been renamed, and is not recommended for use. ' +
|
||||
'See https://react.dev/link/unsafe-component-lifecycles for details.\n\n' +
|
||||
'* Move data fetching code or side effects to componentDidUpdate.\n' +
|
||||
"* If you're updating state whenever props change, refactor your " +
|
||||
'code to use memoization techniques or move it to ' +
|
||||
'static getDerivedStateFromProps. Learn more at: https://react.dev/link/derived-state\n' +
|
||||
'* Rename componentWillReceiveProps to UNSAFE_componentWillReceiveProps to suppress ' +
|
||||
'this warning in non-strict mode. In React 18.x, only the UNSAFE_ name will work. ' +
|
||||
'To rename all deprecated lifecycles to their new names, you can run ' +
|
||||
'`npx react-codemod rename-unsafe-lifecycles` in your project source folder.\n' +
|
||||
'\nPlease update the following components: Component',
|
||||
'componentWillUpdate has been renamed, and is not recommended for use. ' +
|
||||
'See https://react.dev/link/unsafe-component-lifecycles for details.\n\n' +
|
||||
'* Move data fetching code or side effects to componentDidUpdate.\n' +
|
||||
'* Rename componentWillUpdate to UNSAFE_componentWillUpdate to suppress ' +
|
||||
'this warning in non-strict mode. In React 18.x, only the UNSAFE_ name will work. ' +
|
||||
'To rename all deprecated lifecycles to their new names, you can run ' +
|
||||
'`npx react-codemod rename-unsafe-lifecycles` in your project source folder.\n' +
|
||||
'\nPlease update the following components: Component',
|
||||
]);
|
||||
expect(log).toEqual(['componentWillMount', 'UNSAFE_componentWillMount']);
|
||||
|
||||
log.length = 0;
|
||||
|
||||
@@ -78,32 +78,26 @@ describe('forwardRef', () => {
|
||||
|
||||
it('should warn if not provided a callback during creation', () => {
|
||||
React.forwardRef(undefined);
|
||||
assertConsoleErrorDev(
|
||||
['forwardRef requires a render function but was given undefined.'],
|
||||
{withoutStack: true},
|
||||
);
|
||||
assertConsoleErrorDev([
|
||||
'forwardRef requires a render function but was given undefined.',
|
||||
]);
|
||||
|
||||
React.forwardRef(null);
|
||||
assertConsoleErrorDev(
|
||||
['forwardRef requires a render function but was given null.'],
|
||||
{
|
||||
withoutStack: true,
|
||||
},
|
||||
);
|
||||
assertConsoleErrorDev([
|
||||
'forwardRef requires a render function but was given null.',
|
||||
]);
|
||||
|
||||
React.forwardRef('foo');
|
||||
assertConsoleErrorDev(
|
||||
['forwardRef requires a render function but was given string.'],
|
||||
{withoutStack: true},
|
||||
);
|
||||
assertConsoleErrorDev([
|
||||
'forwardRef requires a render function but was given string.',
|
||||
]);
|
||||
});
|
||||
|
||||
it('should warn if no render function is provided', () => {
|
||||
React.forwardRef();
|
||||
assertConsoleErrorDev(
|
||||
['forwardRef requires a render function but was given undefined.'],
|
||||
{withoutStack: true},
|
||||
);
|
||||
assertConsoleErrorDev([
|
||||
'forwardRef requires a render function but was given undefined.',
|
||||
]);
|
||||
});
|
||||
|
||||
it('should warn if the render function provided has defaultProps attributes', () => {
|
||||
@@ -113,13 +107,10 @@ describe('forwardRef', () => {
|
||||
renderWithDefaultProps.defaultProps = {};
|
||||
|
||||
React.forwardRef(renderWithDefaultProps);
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'forwardRef render functions do not support defaultProps. ' +
|
||||
'Did you accidentally pass a React component?',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
assertConsoleErrorDev([
|
||||
'forwardRef render functions do not support defaultProps. ' +
|
||||
'Did you accidentally pass a React component?',
|
||||
]);
|
||||
});
|
||||
|
||||
it('should not warn if the render function provided does not use any parameter', () => {
|
||||
@@ -132,13 +123,10 @@ describe('forwardRef', () => {
|
||||
const arityOfOne = props => <div {...props} />;
|
||||
|
||||
React.forwardRef(arityOfOne);
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'forwardRef render functions accept exactly two parameters: props and ref. ' +
|
||||
'Did you forget to use the ref parameter?',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
assertConsoleErrorDev([
|
||||
'forwardRef render functions accept exactly two parameters: props and ref. ' +
|
||||
'Did you forget to use the ref parameter?',
|
||||
]);
|
||||
});
|
||||
|
||||
it('should not warn if the render function provided use exactly two parameters', () => {
|
||||
@@ -150,13 +138,10 @@ describe('forwardRef', () => {
|
||||
const arityOfThree = (props, ref, x) => <div {...props} ref={ref} x={x} />;
|
||||
|
||||
React.forwardRef(arityOfThree);
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'forwardRef render functions accept exactly two parameters: props and ref. ' +
|
||||
'Any additional parameter will be undefined.',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
assertConsoleErrorDev([
|
||||
'forwardRef render functions accept exactly two parameters: props and ref. ' +
|
||||
'Any additional parameter will be undefined.',
|
||||
]);
|
||||
});
|
||||
|
||||
it('should skip forwardRef in the stack if neither displayName nor name are present', async () => {
|
||||
@@ -394,13 +379,10 @@ describe('forwardRef', () => {
|
||||
return null;
|
||||
}),
|
||||
);
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'forwardRef requires a render function but received a `memo` ' +
|
||||
'component. Instead of forwardRef(memo(...)), use ' +
|
||||
'memo(forwardRef(...)).',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
assertConsoleErrorDev([
|
||||
'forwardRef requires a render function but received a `memo` ' +
|
||||
'component. Instead of forwardRef(memo(...)), use ' +
|
||||
'memo(forwardRef(...)).',
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -637,17 +637,11 @@ describe('Shared useSyncExternalStore behavior (shim and built-in)', () => {
|
||||
assertConsoleErrorDev(
|
||||
gate(flags => flags.enableUseSyncExternalStoreShim)
|
||||
? [
|
||||
[
|
||||
'The result of getSnapshot should be cached to avoid an infinite loop',
|
||||
{withoutStack: true},
|
||||
],
|
||||
[
|
||||
'Error: Maximum update depth exceeded. ' +
|
||||
'This can happen when a component repeatedly calls setState inside componentWillUpdate or componentDidUpdate. ' +
|
||||
'React limits the number of nested updates to prevent infinite loops.' +
|
||||
'\n in <stack>',
|
||||
{withoutStack: true},
|
||||
],
|
||||
'The result of getSnapshot should be cached to avoid an infinite loop',
|
||||
'Error: Maximum update depth exceeded. ' +
|
||||
'This can happen when a component repeatedly calls setState inside componentWillUpdate or componentDidUpdate. ' +
|
||||
'React limits the number of nested updates to prevent infinite loops.' +
|
||||
'\n in <stack>',
|
||||
'The above error occurred in the <App> component:\n\n' +
|
||||
' in App (at **)\n\n' +
|
||||
'Consider adding an error boundary to your tree to customize error handling behavior.\n' +
|
||||
|
||||
Reference in New Issue
Block a user