14
let ReactDOMClient;
15
let ReactDOMServer;
16
let act;
17
+let assertConsoleErrorDev;
18
19
describe('ReactComponent', () => {
20
beforeEach(() => {
25
ReactDOMClient = require('react-dom/client');
26
ReactDOMServer = require('react-dom/server');
27
act = require('internal-test-utils').act;
28
+ assertConsoleErrorDev =
29
+ require('internal-test-utils').assertConsoleErrorDev;
30
});
31
32
// @gate !disableLegacyMode
134
135
// @gate !disableStringRefs
136
it('string refs do not detach and reattach on every render', async () => {
134
- spyOnDev(console, 'error').mockImplementation(() => {});
135
-
137
let refVal;
138
class Child extends React.Component {
139
componentDidUpdate() {
172
root.render(<Parent />);
173
});
174
175
+ assertConsoleErrorDev(['contains the string ref']);
176
+
177
expect(refVal).toBe(undefined);
178
await act(() => {
179
root.render(<Parent showChild={true} />);
514
});
515
516
it('throws usefully when rendering badly-typed elements', async () => {
517
+ const container = document.createElement('div');
518
+ const root = ReactDOMClient.createRoot(container);
519
+
520
const X = undefined;
515
- let container = document.createElement('div');
516
- let root = ReactDOMClient.createRoot(container);
517
- await expect(
518
- expect(async () => {
519
- await act(() => {
520
- root.render(<X />);
521
- });
522
- }).toErrorDev(
523
- 'React.jsx: type is invalid -- expected a string (for built-in components) ' +
524
- 'or a class/function (for composite components) but got: undefined.',
525
- ),
526
- ).rejects.toThrowError(
521
+ const XElement = <X />;
522
+ if (gate(flags => !flags.enableOwnerStacks)) {
523
+ assertConsoleErrorDev(
524
+ [
525
+ 'React.jsx: type is invalid -- expected a string (for built-in components) ' +
526
+ 'or a class/function (for composite components) but got: undefined.',
527
+ ],
528
+ {withoutStack: true},
529
+ );
530
+ }
531
+ await expect(async () => {
532
+ await act(() => {
533
+ root.render(XElement);
534
+ });
535
+ }).rejects.toThrowError(
536
'Element type is invalid: expected a string (for built-in components) ' +
537
'or a class/function (for composite components) but got: undefined.' +
538
(__DEV__
542
);
543
544
const Y = null;
536
- container = document.createElement('div');
537
- root = ReactDOMClient.createRoot(container);
538
- await expect(
539
- expect(async () => {
540
- await act(() => {
541
- root.render(<Y />);
542
- });
543
- }).toErrorDev(
544
- 'React.jsx: type is invalid -- expected a string (for built-in components) ' +
545
- 'or a class/function (for composite components) but got: null.',
546
- ),
547
- ).rejects.toThrowError(
545
+ const YElement = <Y />;
546
+ if (gate(flags => !flags.enableOwnerStacks)) {
547
+ assertConsoleErrorDev(
548
+ [
549
+ 'React.jsx: type is invalid -- expected a string (for built-in components) ' +
550
+ 'or a class/function (for composite components) but got: null.',
551
+ ],
552
+ {withoutStack: true},
553
+ );
554
+ }
555
+ await expect(async () => {
556
+ await act(() => {
557
+ root.render(YElement);
558
+ });
559
+ }).rejects.toThrowError(
560
'Element type is invalid: expected a string (for built-in components) ' +
561
'or a class/function (for composite components) but got: null.',
562
);
563
+
564
+ const Z = true;
565
+ const ZElement = <Z />;
566
+ if (gate(flags => !flags.enableOwnerStacks)) {
567
+ assertConsoleErrorDev(
568
+ [
569
+ 'React.jsx: type is invalid -- expected a string (for built-in components) ' +
570
+ 'or a class/function (for composite components) but got: boolean.',
571
+ ],
572
+ {withoutStack: true},
573
+ );
574
+ }
575
+ await expect(async () => {
576
+ await act(() => {
577
+ root.render(ZElement);
578
+ });
579
+ }).rejects.toThrowError(
580
+ 'Element type is invalid: expected a string (for built-in components) ' +
581
+ 'or a class/function (for composite components) but got: boolean.',
582
+ );
583
});
584
585
it('includes owner name in the error about badly-typed elements', async () => {