Skip to content

Commit

Permalink
[assert helpers] forwardRef-test
Browse files Browse the repository at this point in the history
  • Loading branch information
rickhanlonii committed Dec 18, 2024
1 parent ef979d4 commit 3785469
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 45 deletions.
1 change: 1 addition & 0 deletions packages/internal-test-utils/consoleMock.js
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,7 @@ function normalizeCodeLocInfo(str) {
// We strip that out in our normalization to make it look more like component stacks.
name = name.slice(0, name.length - 7);
}
name = name.replace(/.*\/([^\/]+):\d+:\d+/, '**/$1:**:**');
return '\n in ' + name + ' (at **)';
});
}
Expand Down
104 changes: 59 additions & 45 deletions packages/react/src/__tests__/forwardRef-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ describe('forwardRef', () => {
let React;
let ReactNoop;
let waitForAll;
let assertConsoleErrorDev;

beforeEach(() => {
jest.resetModules();
Expand All @@ -21,6 +22,7 @@ describe('forwardRef', () => {

const InternalTestUtils = require('internal-test-utils');
waitForAll = InternalTestUtils.waitForAll;
assertConsoleErrorDev = InternalTestUtils.assertConsoleErrorDev;
});

it('should update refs when switching between children', async () => {
Expand Down Expand Up @@ -114,25 +116,31 @@ describe('forwardRef', () => {
});

it('should warn if not provided a callback during creation', () => {
expect(() => React.forwardRef(undefined)).toErrorDev(
'forwardRef requires a render function but was given undefined.',
React.forwardRef(undefined);
assertConsoleErrorDev(
['forwardRef requires a render function but was given undefined.'],
{withoutStack: true},
);
expect(() => React.forwardRef(null)).toErrorDev(
'forwardRef requires a render function but was given null.',

React.forwardRef(null);
assertConsoleErrorDev(
['forwardRef requires a render function but was given null.'],
{
withoutStack: true,
},
);
expect(() => React.forwardRef('foo')).toErrorDev(
'forwardRef requires a render function but was given string.',

React.forwardRef('foo');
assertConsoleErrorDev(
['forwardRef requires a render function but was given string.'],
{withoutStack: true},
);
});

it('should warn if no render function is provided', () => {
expect(React.forwardRef).toErrorDev(
'forwardRef requires a render function but was given undefined.',
React.forwardRef();
assertConsoleErrorDev(
['forwardRef requires a render function but was given undefined.'],
{withoutStack: true},
);
});
Expand All @@ -143,9 +151,12 @@ describe('forwardRef', () => {
}
renderWithDefaultProps.defaultProps = {};

expect(() => React.forwardRef(renderWithDefaultProps)).toErrorDev(
'forwardRef render functions do not support defaultProps. ' +
'Did you accidentally pass a React component?',
React.forwardRef(renderWithDefaultProps);
assertConsoleErrorDev(
[
'forwardRef render functions do not support defaultProps. ' +
'Did you accidentally pass a React component?',
],
{withoutStack: true},
);
});
Expand All @@ -159,9 +170,12 @@ describe('forwardRef', () => {
it('should warn if the render function provided does not use the forwarded ref parameter', () => {
const arityOfOne = props => <div {...props} />;

expect(() => React.forwardRef(arityOfOne)).toErrorDev(
'forwardRef render functions accept exactly two parameters: props and ref. ' +
'Did you forget to use the ref parameter?',
React.forwardRef(arityOfOne);
assertConsoleErrorDev(
[
'forwardRef render functions accept exactly two parameters: props and ref. ' +
'Did you forget to use the ref parameter?',
],
{withoutStack: true},
);
});
Expand All @@ -174,9 +188,12 @@ describe('forwardRef', () => {
it('should warn if the render function provided expects to use more than two parameters', () => {
const arityOfThree = (props, ref, x) => <div {...props} ref={ref} x={x} />;

expect(() => React.forwardRef(arityOfThree)).toErrorDev(
'forwardRef render functions accept exactly two parameters: props and ref. ' +
'Any additional parameter will be undefined.',
React.forwardRef(arityOfThree);
assertConsoleErrorDev(
[
'forwardRef render functions accept exactly two parameters: props and ref. ' +
'Any additional parameter will be undefined.',
],
{withoutStack: true},
);
});
Expand All @@ -190,15 +207,16 @@ describe('forwardRef', () => {
<RefForwardingComponent />
</p>,
);
await expect(async () => {
await waitForAll([]);
}).toErrorDev(
await waitForAll([]);
assertConsoleErrorDev([
'Each child in a list should have a unique "key" prop.' +
'\n\nCheck the top-level render call using <ForwardRef>. It was passed a child from ForwardRef. ' +
'See https://react.dev/link/warning-keys for more information.\n' +
' in span (at **)\n' +
' in ',
);
(gate(flags => flags.enableOwnerStacks)
? ' in **/forwardRef-test.js:**:** (at **)'
: ' in p (at **)'),
]);
});

it('should use the inner function name for the stack', async () => {
Expand All @@ -210,16 +228,16 @@ describe('forwardRef', () => {
<RefForwardingComponent />
</p>,
);
await expect(async () => {
await waitForAll([]);
}).toErrorDev(

await waitForAll([]);
assertConsoleErrorDev([
'Each child in a list should have a unique "key" prop.' +
'\n\nCheck the top-level render call using <ForwardRef(Inner)>. It was passed a child from ForwardRef(Inner). ' +
'See https://react.dev/link/warning-keys for more information.\n' +
' in span (at **)\n' +
' in Inner (at **)' +
(gate(flags => flags.enableOwnerStacks) ? '' : '\n in p (at **)'),
);
]);
});

it('should use the inner name in the stack', async () => {
Expand All @@ -233,16 +251,15 @@ describe('forwardRef', () => {
<RefForwardingComponent />
</p>,
);
await expect(async () => {
await waitForAll([]);
}).toErrorDev(
await waitForAll([]);
assertConsoleErrorDev([
'Each child in a list should have a unique "key" prop.' +
'\n\nCheck the top-level render call using <ForwardRef(Inner)>. It was passed a child from ForwardRef(Inner). ' +
'See https://react.dev/link/warning-keys for more information.\n' +
' in span (at **)\n' +
' in Inner (at **)' +
(gate(flags => flags.enableOwnerStacks) ? '' : '\n in p (at **)'),
);
]);
});

it('can use the outer displayName in the stack', async () => {
Expand All @@ -255,16 +272,15 @@ describe('forwardRef', () => {
<RefForwardingComponent />
</p>,
);
await expect(async () => {
await waitForAll([]);
}).toErrorDev(
await waitForAll([]);
assertConsoleErrorDev([
'Each child in a list should have a unique "key" prop.' +
'\n\nCheck the top-level render call using <Outer>. It was passed a child from Outer. ' +
'See https://react.dev/link/warning-keys for more information.\n' +
' in span (at **)\n' +
' in Outer (at **)' +
(gate(flags => flags.enableOwnerStacks) ? '' : '\n in p (at **)'),
);
]);
});

it('should prefer the inner name to the outer displayName in the stack', async () => {
Expand All @@ -279,16 +295,15 @@ describe('forwardRef', () => {
<RefForwardingComponent />
</p>,
);
await expect(async () => {
await waitForAll([]);
}).toErrorDev(
await waitForAll([]);
assertConsoleErrorDev([
'Each child in a list should have a unique "key" prop.' +
'\n\nCheck the top-level render call using <Outer>. It was passed a child from Outer. ' +
'See https://react.dev/link/warning-keys for more information.\n' +
' in span (at **)\n' +
' in Inner (at **)' +
(gate(flags => flags.enableOwnerStacks) ? '' : '\n in p (at **)'),
);
]);
});

it('should not bailout if forwardRef is not wrapped in memo', async () => {
Expand Down Expand Up @@ -419,13 +434,12 @@ describe('forwardRef', () => {
});

it('warns on forwardRef(memo(...))', () => {
expect(() => {
React.forwardRef(
React.memo((props, ref) => {
return null;
}),
);
}).toErrorDev(
React.forwardRef(
React.memo((props, ref) => {
return null;
}),
);
assertConsoleErrorDev(
[
'forwardRef requires a render function but received a `memo` ' +
'component. Instead of forwardRef(memo(...)), use ' +
Expand Down

0 comments on commit 3785469

Please sign in to comment.