Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove ReactTestUtils from ReactJSXElementValidator #28335

Merged
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
183 changes: 123 additions & 60 deletions packages/react/src/__tests__/ReactJSXElementValidator-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,9 @@

// TODO: All these warnings should become static errors using Flow instead
// of dynamic errors when using JSX with Flow.
let act;
let React;
let ReactTestUtils;
let ReactDOMClient;

describe('ReactJSXElementValidator', () => {
let Component;
Expand All @@ -21,8 +22,9 @@ describe('ReactJSXElementValidator', () => {
beforeEach(() => {
jest.resetModules();

act = require('internal-test-utils').act;
React = require('react');
ReactTestUtils = require('react-dom/test-utils');
ReactDOMClient = require('react-dom/client');

Component = class extends React.Component {
render() {
Expand All @@ -38,15 +40,18 @@ describe('ReactJSXElementValidator', () => {
RequiredPropComponent.displayName = 'RequiredPropComponent';
});

it('warns for keys for arrays of elements in children position', () => {
expect(() =>
ReactTestUtils.renderIntoDocument(
<Component>{[<Component />, <Component />]}</Component>,
),
).toErrorDev('Each child in a list should have a unique "key" prop.');
it('warns for keys for arrays of elements in children position', async () => {
await expect(async () => {
const container = document.createElement('div');
const root = ReactDOMClient.createRoot(container);

await act(() => {
root.render(<Component>{[<Component />, <Component />]}</Component>);
});
}).toErrorDev('Each child in a list should have a unique "key" prop.');
});

it('warns for keys for arrays of elements with owner info', () => {
it('warns for keys for arrays of elements with owner info', async () => {
class InnerComponent extends React.Component {
render() {
return <Component>{this.props.childSet}</Component>;
Expand All @@ -59,16 +64,20 @@ describe('ReactJSXElementValidator', () => {
}
}

expect(() =>
ReactTestUtils.renderIntoDocument(<ComponentWrapper />),
).toErrorDev(
await expect(async () => {
const container = document.createElement('div');
const root = ReactDOMClient.createRoot(container);
await act(() => {
root.render(<ComponentWrapper />);
});
}).toErrorDev([
'Each child in a list should have a unique "key" prop.' +
'\n\nCheck the render method of `InnerComponent`. ' +
'It was passed a child from ComponentWrapper. ',
);
]);
});

it('warns for keys for iterables of elements in rest args', () => {
it('warns for keys for iterables of elements in rest args', async () => {
const iterable = {
'@@iterator': function () {
let i = 0;
Expand All @@ -81,18 +90,30 @@ describe('ReactJSXElementValidator', () => {
},
};

expect(() =>
ReactTestUtils.renderIntoDocument(<Component>{iterable}</Component>),
).toErrorDev('Each child in a list should have a unique "key" prop.');
await expect(async () => {
const container = document.createElement('div');
const root = ReactDOMClient.createRoot(container);

await act(() => {
root.render(<Component>{iterable}</Component>);
});
}).toErrorDev('Each child in a list should have a unique "key" prop.');
});

it('does not warn for arrays of elements with keys', () => {
ReactTestUtils.renderIntoDocument(
<Component>{[<Component key="#1" />, <Component key="#2" />]}</Component>,
);
it('does not warn for arrays of elements with keys', async () => {
const container = document.createElement('div');
const root = ReactDOMClient.createRoot(container);

await act(() => {
root.render(
<Component>
{[<Component key="#1" />, <Component key="#2" />]}
</Component>,
);
});
});

it('does not warn for iterable elements with keys', () => {
it('does not warn for iterable elements with keys', async () => {
const iterable = {
'@@iterator': function () {
let i = 0;
Expand All @@ -108,10 +129,15 @@ describe('ReactJSXElementValidator', () => {
},
};

ReactTestUtils.renderIntoDocument(<Component>{iterable}</Component>);
const container = document.createElement('div');
const root = ReactDOMClient.createRoot(container);

await act(() => {
root.render(<Component>{iterable}</Component>);
});
});

it('does not warn for numeric keys in entry iterable as a child', () => {
it('does not warn for numeric keys in entry iterable as a child', async () => {
const iterable = {
'@@iterator': function () {
let i = 0;
Expand All @@ -125,23 +151,31 @@ describe('ReactJSXElementValidator', () => {
};
iterable.entries = iterable['@@iterator'];

ReactTestUtils.renderIntoDocument(<Component>{iterable}</Component>);
const container = document.createElement('div');
const root = ReactDOMClient.createRoot(container);
await act(() => {
root.render(<Component>{iterable}</Component>);
});
});

it('does not warn when the element is directly as children', () => {
ReactTestUtils.renderIntoDocument(
<Component>
<Component />
<Component />
</Component>,
);
it('does not warn when the element is directly as children', async () => {
const container = document.createElement('div');
const root = ReactDOMClient.createRoot(container);
await act(() => {
root.render(
<Component>
<Component />
<Component />
</Component>,
);
});
});

it('does not warn when the child array contains non-elements', () => {
void (<Component>{[{}, {}]}</Component>);
});

it('should give context for errors in nested components.', () => {
it('should give context for errors in nested components.', async () => {
class MyComp extends React.Component {
render() {
return [<div />];
Expand All @@ -152,7 +186,14 @@ describe('ReactJSXElementValidator', () => {
return <MyComp />;
}
}
expect(() => ReactTestUtils.renderIntoDocument(<ParentComp />)).toErrorDev(
await expect(async () => {
const container = document.createElement('div');
const root = ReactDOMClient.createRoot(container);

await act(() => {
root.render(<ParentComp />);
});
}).toErrorDev(
'Each child in a list should have a unique "key" prop. ' +
'See https://reactjs.org/link/warning-keys for more information.\n' +
' in MyComp (at **)\n' +
Expand Down Expand Up @@ -189,20 +230,26 @@ describe('ReactJSXElementValidator', () => {
void (<Div />);
});

it('warns for fragments with illegal attributes', () => {
it('warns for fragments with illegal attributes', async () => {
class Foo extends React.Component {
render() {
return <React.Fragment a={1}>hello</React.Fragment>;
}
}

expect(() => ReactTestUtils.renderIntoDocument(<Foo />)).toErrorDev(
await expect(async () => {
const container = document.createElement('div');
const root = ReactDOMClient.createRoot(container);
await act(() => {
root.render(<Foo />);
});
}).toErrorDev(
'Invalid prop `a` supplied to `React.Fragment`. React.Fragment ' +
'can only have `key` and `children` props.',
);
});

it('warns for fragments with refs', () => {
it('warns for fragments with refs', async () => {
class Foo extends React.Component {
render() {
return (
Expand All @@ -217,35 +264,51 @@ describe('ReactJSXElementValidator', () => {
}

if (gate(flags => flags.enableRefAsProp)) {
expect(() => ReactTestUtils.renderIntoDocument(<Foo />)).toErrorDev(
'Invalid prop `ref` supplied to `React.Fragment`.',
);
await expect(async () => {
const container = document.createElement('div');
const root = ReactDOMClient.createRoot(container);
await act(() => {
root.render(<Foo />);
});
}).toErrorDev('Invalid prop `ref` supplied to `React.Fragment`.');
} else {
expect(() => ReactTestUtils.renderIntoDocument(<Foo />)).toErrorDev(
'Invalid attribute `ref` supplied to `React.Fragment`.',
);
await expect(async () => {
const container = document.createElement('div');
const root = ReactDOMClient.createRoot(container);
await act(() => {
root.render(<Foo />);
});
}).toErrorDev('Invalid attribute `ref` supplied to `React.Fragment`.');
}
});

it('does not warn for fragments of multiple elements without keys', () => {
ReactTestUtils.renderIntoDocument(
<>
<span>1</span>
<span>2</span>
</>,
);
});

it('warns for fragments of multiple elements with same key', () => {
expect(() =>
ReactTestUtils.renderIntoDocument(
it('does not warn for fragments of multiple elements without keys', async () => {
const container = document.createElement('div');
const root = ReactDOMClient.createRoot(container);
await act(() => {
root.render(
<>
<span key="a">1</span>
<span key="a">2</span>
<span key="b">3</span>
<span>1</span>
<span>2</span>
</>,
),
).toErrorDev('Encountered two children with the same key, `a`.', {
);
});
});

it('warns for fragments of multiple elements with same key', async () => {
await expect(async () => {
const container = document.createElement('div');
const root = ReactDOMClient.createRoot(container);
await act(() => {
root.render(
<>
<span key="a">1</span>
<span key="a">2</span>
<span key="b">3</span>
</>,
);
});
}).toErrorDev('Encountered two children with the same key, `a`.', {
withoutStack: true,
});
});
Expand Down