mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
[assert helpers] ReactFlight (#31860)
This commit is contained in:
+474
-166
@@ -1467,13 +1467,12 @@ describe('ReactFlight', () => {
|
||||
|
||||
const transport = ReactNoopFlightServer.render(<App />);
|
||||
|
||||
await expect(async () => {
|
||||
await act(() => {
|
||||
startTransition(() => {
|
||||
ReactNoop.render(ReactNoopFlightClient.read(transport));
|
||||
});
|
||||
await act(() => {
|
||||
startTransition(() => {
|
||||
ReactNoop.render(ReactNoopFlightClient.read(transport));
|
||||
});
|
||||
}).toErrorDev(
|
||||
});
|
||||
assertConsoleErrorDev([
|
||||
'Each child in a list should have a unique "key" prop.\n' +
|
||||
'\n' +
|
||||
'Check the render method of `Component`. See https://react.dev/link/warning-keys for more information.\n' +
|
||||
@@ -1483,7 +1482,7 @@ describe('ReactFlight', () => {
|
||||
? ''
|
||||
: ' in Indirection (at **)\n') +
|
||||
' in App (at **)',
|
||||
);
|
||||
]);
|
||||
});
|
||||
|
||||
it('should trigger the inner most error boundary inside a Client Component', async () => {
|
||||
@@ -1541,17 +1540,47 @@ describe('ReactFlight', () => {
|
||||
return 123;
|
||||
},
|
||||
};
|
||||
expect(() => {
|
||||
const transport = ReactNoopFlightServer.render(<input value={obj} />);
|
||||
ReactNoopFlightClient.read(transport);
|
||||
}).toErrorDev(
|
||||
'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},
|
||||
);
|
||||
const transport = ReactNoopFlightServer.render(<input value={obj} />);
|
||||
if (gate(flags => flags.enableOwnerStacks)) {
|
||||
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},
|
||||
);
|
||||
}
|
||||
|
||||
ReactNoopFlightClient.read(transport);
|
||||
if (gate(flags => flags.enableOwnerStacks)) {
|
||||
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' +
|
||||
' ^^^^^^^^^^^^^^^\n' +
|
||||
' at (<anonymous>)',
|
||||
]);
|
||||
} else {
|
||||
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' +
|
||||
' ^^^^^^^^^^^^^^^',
|
||||
'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},
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
it('should warn in DEV if a toJSON instance is passed to a host component child', () => {
|
||||
@@ -1560,43 +1589,123 @@ describe('ReactFlight', () => {
|
||||
return 123;
|
||||
}
|
||||
}
|
||||
expect(() => {
|
||||
const transport = ReactNoopFlightServer.render(
|
||||
<div>Womp womp: {new MyError('spaghetti')}</div>,
|
||||
);
|
||||
ReactNoopFlightClient.read(transport);
|
||||
}).toErrorDev(
|
||||
'Error objects cannot be rendered as text children. Try formatting it using toString().\n' +
|
||||
' <div>Womp womp: {Error}</div>\n' +
|
||||
' ^^^^^^^',
|
||||
{withoutStack: true},
|
||||
const transport = ReactNoopFlightServer.render(
|
||||
<div>Womp womp: {new MyError('spaghetti')}</div>,
|
||||
);
|
||||
if (gate(flags => flags.enableOwnerStacks)) {
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'Error objects cannot be rendered as text children. Try formatting it using toString().\n' +
|
||||
' <div>Womp womp: {Error}</div>\n' +
|
||||
' ^^^^^^^',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
}
|
||||
|
||||
ReactNoopFlightClient.read(transport);
|
||||
if (gate(flags => flags.enableOwnerStacks)) {
|
||||
assertConsoleErrorDev([
|
||||
'Error objects cannot be rendered as text children. Try formatting it using toString().\n' +
|
||||
' <div>Womp womp: {Error}</div>\n' +
|
||||
' ^^^^^^^\n' +
|
||||
' at (<anonymous>)',
|
||||
]);
|
||||
} else {
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'Error objects cannot be rendered as text children. Try formatting it using toString().\n' +
|
||||
' <div>Womp womp: {Error}</div>\n' +
|
||||
' ^^^^^^^',
|
||||
'Error objects cannot be rendered as text children. Try formatting it using toString().\n' +
|
||||
' <div>Womp womp: {Error}</div>\n' +
|
||||
' ^^^^^^^',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
it('should warn in DEV if a special object is passed to a host component', () => {
|
||||
expect(() => {
|
||||
const transport = ReactNoopFlightServer.render(<input value={Math} />);
|
||||
ReactNoopFlightClient.read(transport);
|
||||
}).toErrorDev(
|
||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||
'Math objects are not supported.\n' +
|
||||
' <input value={Math}>\n' +
|
||||
' ^^^^^^',
|
||||
{withoutStack: true},
|
||||
);
|
||||
const transport = ReactNoopFlightServer.render(<input value={Math} />);
|
||||
if (gate(flags => flags.enableOwnerStacks)) {
|
||||
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},
|
||||
);
|
||||
}
|
||||
|
||||
ReactNoopFlightClient.read(transport);
|
||||
if (gate(flags => flags.enableOwnerStacks)) {
|
||||
assertConsoleErrorDev([
|
||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||
'Math objects are not supported.\n' +
|
||||
' <input value={Math}>\n' +
|
||||
' ^^^^^^\n' +
|
||||
' at (<anonymous>)',
|
||||
]);
|
||||
} else {
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||
'Math objects are not supported.\n' +
|
||||
' <input value={Math}>\n' +
|
||||
' ^^^^^^',
|
||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||
'Math objects are not supported.\n' +
|
||||
' <input value={Math}>\n' +
|
||||
' ^^^^^^',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
it('should warn in DEV if an object with symbols is passed to a host component', () => {
|
||||
expect(() => {
|
||||
const transport = ReactNoopFlightServer.render(
|
||||
<input value={{[Symbol.iterator]: {}}} />,
|
||||
);
|
||||
ReactNoopFlightClient.read(transport);
|
||||
}).toErrorDev(
|
||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||
'Objects with symbol properties like Symbol.iterator are not supported.',
|
||||
{withoutStack: true},
|
||||
const transport = ReactNoopFlightServer.render(
|
||||
<input value={{[Symbol.iterator]: {}}} />,
|
||||
);
|
||||
if (gate(flags => flags.enableOwnerStacks)) {
|
||||
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},
|
||||
);
|
||||
}
|
||||
|
||||
ReactNoopFlightClient.read(transport);
|
||||
if (gate(flags => flags.enableOwnerStacks)) {
|
||||
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' +
|
||||
' ^^^^\n' +
|
||||
' at (<anonymous>)',
|
||||
]);
|
||||
} else {
|
||||
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' +
|
||||
' ^^^^',
|
||||
'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},
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
it('should warn in DEV if a toJSON instance is passed to a Client Component', () => {
|
||||
@@ -1609,14 +1718,47 @@ describe('ReactFlight', () => {
|
||||
return <div>{value}</div>;
|
||||
}
|
||||
const Client = clientReference(ClientImpl);
|
||||
expect(() => {
|
||||
const transport = ReactNoopFlightServer.render(<Client value={obj} />);
|
||||
ReactNoopFlightClient.read(transport);
|
||||
}).toErrorDev(
|
||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||
'Objects with toJSON methods are not supported.',
|
||||
{withoutStack: true},
|
||||
);
|
||||
const transport = ReactNoopFlightServer.render(<Client value={obj} />);
|
||||
if (gate(flags => flags.enableOwnerStacks)) {
|
||||
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},
|
||||
);
|
||||
}
|
||||
|
||||
ReactNoopFlightClient.read(transport);
|
||||
if (gate(flags => flags.enableOwnerStacks)) {
|
||||
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' +
|
||||
' ^^^^^^^^^^^^^^^\n' +
|
||||
' at (<anonymous>)',
|
||||
]);
|
||||
} else {
|
||||
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' +
|
||||
' ^^^^^^^^^^^^^^^',
|
||||
'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},
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
it('should warn in DEV if a toJSON instance is passed to a Client Component child', () => {
|
||||
@@ -1629,19 +1771,49 @@ describe('ReactFlight', () => {
|
||||
return <div>{children}</div>;
|
||||
}
|
||||
const Client = clientReference(ClientImpl);
|
||||
expect(() => {
|
||||
const transport = ReactNoopFlightServer.render(
|
||||
<Client>Current date: {obj}</Client>,
|
||||
);
|
||||
ReactNoopFlightClient.read(transport);
|
||||
}).toErrorDev(
|
||||
'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},
|
||||
const transport = ReactNoopFlightServer.render(
|
||||
<Client>Current date: {obj}</Client>,
|
||||
);
|
||||
if (gate(flags => flags.enableOwnerStacks)) {
|
||||
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},
|
||||
);
|
||||
}
|
||||
|
||||
ReactNoopFlightClient.read(transport);
|
||||
if (gate(flags => flags.enableOwnerStacks)) {
|
||||
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' +
|
||||
' ^^^^^^^^^^^^^^^\n' +
|
||||
' at (<anonymous>)',
|
||||
]);
|
||||
} else {
|
||||
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' +
|
||||
' ^^^^^^^^^^^^^^^',
|
||||
'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},
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
it('should warn in DEV if a special object is passed to a Client Component', () => {
|
||||
@@ -1649,16 +1821,44 @@ describe('ReactFlight', () => {
|
||||
return <div>{value}</div>;
|
||||
}
|
||||
const Client = clientReference(ClientImpl);
|
||||
expect(() => {
|
||||
const transport = ReactNoopFlightServer.render(<Client value={Math} />);
|
||||
ReactNoopFlightClient.read(transport);
|
||||
}).toErrorDev(
|
||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||
'Math objects are not supported.\n' +
|
||||
' <... value={Math}>\n' +
|
||||
' ^^^^^^',
|
||||
{withoutStack: true},
|
||||
);
|
||||
const transport = ReactNoopFlightServer.render(<Client value={Math} />);
|
||||
|
||||
if (gate(flags => flags.enableOwnerStacks)) {
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||
'Math objects are not supported.\n' +
|
||||
' <... value={Math}>\n' +
|
||||
' ^^^^^^',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
}
|
||||
|
||||
ReactNoopFlightClient.read(transport);
|
||||
if (gate(flags => flags.enableOwnerStacks)) {
|
||||
assertConsoleErrorDev([
|
||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||
'Math objects are not supported.\n' +
|
||||
' <... value={Math}>\n' +
|
||||
' ^^^^^^\n' +
|
||||
' at (<anonymous>)',
|
||||
]);
|
||||
} else {
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||
'Math objects are not supported.\n' +
|
||||
' <... value={Math}>\n' +
|
||||
' ^^^^^^',
|
||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||
'Math objects are not supported.\n' +
|
||||
' <... value={Math}>\n' +
|
||||
' ^^^^^^',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
it('should warn in DEV if an object with symbols is passed to a Client Component', () => {
|
||||
@@ -1666,16 +1866,46 @@ describe('ReactFlight', () => {
|
||||
return <div>{value}</div>;
|
||||
}
|
||||
const Client = clientReference(ClientImpl);
|
||||
expect(() => {
|
||||
const transport = ReactNoopFlightServer.render(
|
||||
<Client value={{[Symbol.iterator]: {}}} />,
|
||||
);
|
||||
ReactNoopFlightClient.read(transport);
|
||||
}).toErrorDev(
|
||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||
'Objects with symbol properties like Symbol.iterator are not supported.',
|
||||
{withoutStack: true},
|
||||
assertConsoleErrorDev([]);
|
||||
const transport = ReactNoopFlightServer.render(
|
||||
<Client value={{[Symbol.iterator]: {}}} />,
|
||||
);
|
||||
if (gate(flags => flags.enableOwnerStacks)) {
|
||||
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},
|
||||
);
|
||||
}
|
||||
|
||||
ReactNoopFlightClient.read(transport);
|
||||
|
||||
if (gate(flags => flags.enableOwnerStacks)) {
|
||||
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' +
|
||||
' ^^^^\n',
|
||||
]);
|
||||
} else {
|
||||
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' +
|
||||
' ^^^^',
|
||||
'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},
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
it('should warn in DEV if a special object is passed to a nested object in Client Component', () => {
|
||||
@@ -1683,18 +1913,41 @@ describe('ReactFlight', () => {
|
||||
return <div>{value}</div>;
|
||||
}
|
||||
const Client = clientReference(ClientImpl);
|
||||
expect(() => {
|
||||
const transport = ReactNoopFlightServer.render(
|
||||
<Client value={{hello: Math, title: <h1>hi</h1>}} />,
|
||||
);
|
||||
ReactNoopFlightClient.read(transport);
|
||||
}).toErrorDev(
|
||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||
'Math objects are not supported.\n' +
|
||||
' {hello: Math, title: <h1/>}\n' +
|
||||
' ^^^^',
|
||||
{withoutStack: true},
|
||||
const transport = ReactNoopFlightServer.render(
|
||||
<Client value={{[Symbol.iterator]: {}}} />,
|
||||
);
|
||||
ReactNoopFlightClient.read(transport);
|
||||
|
||||
if (gate(flags => flags.enableOwnerStacks)) {
|
||||
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' +
|
||||
' ^^^^\n' +
|
||||
' at (<anonymous>)',
|
||||
]);
|
||||
} else {
|
||||
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' +
|
||||
' ^^^^',
|
||||
'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},
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
it('should warn in DEV if a special object is passed to a nested array in Client Component', () => {
|
||||
@@ -1702,20 +1955,40 @@ describe('ReactFlight', () => {
|
||||
return <div>{value}</div>;
|
||||
}
|
||||
const Client = clientReference(ClientImpl);
|
||||
expect(() => {
|
||||
const transport = ReactNoopFlightServer.render(
|
||||
<Client
|
||||
value={['looooong string takes up noise', Math, <h1>hi</h1>]}
|
||||
/>,
|
||||
);
|
||||
ReactNoopFlightClient.read(transport);
|
||||
}).toErrorDev(
|
||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||
'Math objects are not supported.\n' +
|
||||
' [..., Math, <h1/>]\n' +
|
||||
' ^^^^',
|
||||
{withoutStack: true},
|
||||
const transport = ReactNoopFlightServer.render(
|
||||
<Client value={['looooong string takes up noise', Math, <h1>hi</h1>]} />,
|
||||
);
|
||||
ReactNoopFlightClient.read(transport);
|
||||
if (gate(flags => flags.enableOwnerStacks)) {
|
||||
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' +
|
||||
' ^^^^\n' +
|
||||
' at (<anonymous>)',
|
||||
]);
|
||||
} else {
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'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' +
|
||||
' ^^^^',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
it('should NOT warn in DEV for key getters', () => {
|
||||
@@ -1729,63 +2002,100 @@ describe('ReactFlight', () => {
|
||||
key: "this has a key but parent doesn't",
|
||||
});
|
||||
}
|
||||
expect(() => {
|
||||
// While we're on the server we need to have the Server version active to track component stacks.
|
||||
jest.resetModules();
|
||||
jest.mock('react', () => ReactServer);
|
||||
const transport = ReactNoopFlightServer.render(
|
||||
ReactServer.createElement(
|
||||
'div',
|
||||
null,
|
||||
Array(6).fill(ReactServer.createElement(NoKey)),
|
||||
),
|
||||
);
|
||||
jest.resetModules();
|
||||
jest.mock('react', () => React);
|
||||
ReactNoopFlightClient.read(transport);
|
||||
}).toErrorDev('Each child in a list should have a unique "key" prop.');
|
||||
// While we're on the server we need to have the Server version active to track component stacks.
|
||||
jest.resetModules();
|
||||
jest.mock('react', () => ReactServer);
|
||||
const transport = ReactNoopFlightServer.render(
|
||||
ReactServer.createElement(
|
||||
'div',
|
||||
null,
|
||||
Array(6).fill(ReactServer.createElement(NoKey)),
|
||||
),
|
||||
);
|
||||
jest.resetModules();
|
||||
jest.mock('react', () => React);
|
||||
ReactNoopFlightClient.read(transport);
|
||||
if (gate(flags => flags.enableOwnerStacks)) {
|
||||
assertConsoleErrorDev([
|
||||
'Each child in a list should have a unique "key" prop. ' +
|
||||
'See https://react.dev/link/warning-keys for more information.\n' +
|
||||
' in NoKey (at **)',
|
||||
'Each child in a list should have a unique "key" prop. ' +
|
||||
'See https://react.dev/link/warning-keys for more information.\n' +
|
||||
' in NoKey (at **)',
|
||||
]);
|
||||
} else {
|
||||
assertConsoleErrorDev([
|
||||
'Each child in a list should have a unique "key" prop.\n\n' +
|
||||
'Check the top-level render call using <div>. ' +
|
||||
'See https://react.dev/link/warning-keys for more information.\n' +
|
||||
' in NoKey (at **)',
|
||||
]);
|
||||
}
|
||||
});
|
||||
|
||||
// @gate !__DEV__ || enableOwnerStacks
|
||||
it('should warn in DEV a child is missing keys on a fragment', () => {
|
||||
expect(() => {
|
||||
// While we're on the server we need to have the Server version active to track component stacks.
|
||||
jest.resetModules();
|
||||
jest.mock('react', () => ReactServer);
|
||||
const transport = ReactNoopFlightServer.render(
|
||||
ReactServer.createElement(
|
||||
'div',
|
||||
null,
|
||||
Array(6).fill(ReactServer.createElement(ReactServer.Fragment)),
|
||||
),
|
||||
);
|
||||
jest.resetModules();
|
||||
jest.mock('react', () => React);
|
||||
ReactNoopFlightClient.read(transport);
|
||||
}).toErrorDev('Each child in a list should have a unique "key" prop.');
|
||||
// While we're on the server we need to have the Server version active to track component stacks.
|
||||
jest.resetModules();
|
||||
jest.mock('react', () => ReactServer);
|
||||
const transport = ReactNoopFlightServer.render(
|
||||
ReactServer.createElement(
|
||||
'div',
|
||||
null,
|
||||
Array(6).fill(ReactServer.createElement(ReactServer.Fragment)),
|
||||
),
|
||||
);
|
||||
jest.resetModules();
|
||||
jest.mock('react', () => React);
|
||||
ReactNoopFlightClient.read(transport);
|
||||
if (gate(flags => flags.enableOwnerStacks)) {
|
||||
assertConsoleErrorDev([
|
||||
'Each child in a list should have a unique "key" prop. ' +
|
||||
'See https://react.dev/link/warning-keys for more information.\n' +
|
||||
' in Fragment (at **)',
|
||||
'Each child in a list should have a unique "key" prop. ' +
|
||||
'See https://react.dev/link/warning-keys for more information.\n' +
|
||||
' in Fragment (at **)',
|
||||
]);
|
||||
} else {
|
||||
assertConsoleErrorDev([
|
||||
'Each child in a list should have a unique "key" prop.\n\n' +
|
||||
'Check the top-level render call using <div>. ' +
|
||||
'See https://react.dev/link/warning-keys for more information.\n' +
|
||||
' in Fragment (at **)',
|
||||
]);
|
||||
}
|
||||
});
|
||||
|
||||
it('should warn in DEV a child is missing keys in client component', async () => {
|
||||
function ParentClient({children}) {
|
||||
return children;
|
||||
}
|
||||
const Parent = clientReference(ParentClient);
|
||||
await expect(async () => {
|
||||
|
||||
await act(async () => {
|
||||
const Parent = clientReference(ParentClient);
|
||||
const transport = ReactNoopFlightServer.render(
|
||||
<Parent>{Array(6).fill(<div>no key</div>)}</Parent>,
|
||||
);
|
||||
ReactNoopFlightClient.read(transport);
|
||||
await act(async () => {
|
||||
ReactNoop.render(await ReactNoopFlightClient.read(transport));
|
||||
});
|
||||
}).toErrorDev(
|
||||
gate(flags => flags.enableOwnerStacks)
|
||||
? 'Each child in a list should have a unique "key" prop.' +
|
||||
'\n\nCheck the top-level render call using <ParentClient>. ' +
|
||||
'See https://react.dev/link/warning-keys for more information.'
|
||||
: 'Each child in a list should have a unique "key" prop. ' +
|
||||
'See https://react.dev/link/warning-keys for more information.',
|
||||
);
|
||||
|
||||
ReactNoop.render(await ReactNoopFlightClient.read(transport));
|
||||
});
|
||||
if (gate(flags => flags.enableOwnerStacks)) {
|
||||
assertConsoleErrorDev([
|
||||
'Each child in a list should have a unique "key" prop.\n\n' +
|
||||
'Check the top-level render call using <ParentClient>. ' +
|
||||
'See https://react.dev/link/warning-keys for more information.\n' +
|
||||
' in div (at **)',
|
||||
]);
|
||||
} else {
|
||||
assertConsoleErrorDev([
|
||||
'Each child in a list should have a unique "key" prop. ' +
|
||||
'See https://react.dev/link/warning-keys for more information.\n' +
|
||||
' in div (at **)',
|
||||
]);
|
||||
}
|
||||
});
|
||||
|
||||
it('should error if a class instance is passed to a host component', () => {
|
||||
@@ -3135,19 +3445,17 @@ describe('ReactFlight', () => {
|
||||
},
|
||||
);
|
||||
|
||||
let transport;
|
||||
expect(() => {
|
||||
// Reset the modules so that we get a new overridden console on top of the
|
||||
// one installed by expect. This ensures that we still emit console.error
|
||||
// calls.
|
||||
jest.resetModules();
|
||||
jest.mock('react', () => require('react/react.react-server'));
|
||||
ReactServer = require('react');
|
||||
ReactNoopFlightServer = require('react-noop-renderer/flight-server');
|
||||
transport = ReactNoopFlightServer.render({
|
||||
root: ReactServer.createElement(App),
|
||||
});
|
||||
}).toErrorDev('err');
|
||||
// Reset the modules so that we get a new overridden console on top of the
|
||||
// one installed by expect. This ensures that we still emit console.error
|
||||
// calls.
|
||||
jest.resetModules();
|
||||
jest.mock('react', () => require('react/react.react-server'));
|
||||
ReactServer = require('react');
|
||||
ReactNoopFlightServer = require('react-noop-renderer/flight-server');
|
||||
const transport = ReactNoopFlightServer.render({
|
||||
root: ReactServer.createElement(App),
|
||||
});
|
||||
assertConsoleErrorDev(['Error: err']);
|
||||
|
||||
expect(mockConsoleLog).toHaveBeenCalledTimes(1);
|
||||
expect(mockConsoleLog.mock.calls[0][0]).toBe('hi');
|
||||
|
||||
Reference in New Issue
Block a user