Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 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
2 changes: 1 addition & 1 deletion packages/render/src/browser/render-web.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ describe('render on the browser environment', () => {
resolve(
'<p>example content with some multibyte characters: 情報Ⅰ</p>',
),
500,
50,
),
);
const EmailTemplate = () => {
Expand Down
25 changes: 25 additions & 0 deletions packages/render/src/edge/render.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
* @vitest-environment jsdom
*/

import { Suspense, use } from 'react';
import { Preview } from '../shared/utils/testing/preview';
import { Template } from '../shared/utils/testing/template';
import { render } from './render';
Expand Down Expand Up @@ -133,4 +134,28 @@ describe('render on the edge', () => {
`"THIS SHOULD BE RENDERED IN PLAIN TEXT"`,
);
});

// https://github.com/resend/react-email/issues/3090
it('waits for Suspense boundaries to resolve before resolving', async () => {
const htmlPromise = new Promise<string>((resolve) =>
setTimeout(
() => resolve('<p>content rendered after suspension</p>'),
50,
),
);
const EmailTemplate = () => {
const html = use(htmlPromise);
return <div dangerouslySetInnerHTML={{ __html: html }} />;
};

const renderedTemplate = await render(
<Suspense>
<EmailTemplate />
</Suspense>,
);

expect(renderedTemplate).not.toContain('$RC');
expect(renderedTemplate).not.toContain('<!--$?-->');
expect(renderedTemplate).toContain('content rendered after suspension');
});
});
5 changes: 4 additions & 1 deletion packages/render/src/edge/render.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,10 @@ export const render = async (
progressiveChunkSize: Number.POSITIVE_INFINITY,
},
)
.then(readStream)
.then(async (stream) => {
await stream.allReady;
return readStream(stream);
})
.then(resolve)
.catch(reject);
});
Expand Down
25 changes: 25 additions & 0 deletions packages/render/src/node/render-edge.spec.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { Suspense, use } from 'react';
import { Preview } from '../shared/utils/testing/preview';
import { Template } from '../shared/utils/testing/template';
import { render } from './render';
Expand Down Expand Up @@ -146,6 +147,30 @@ describe('render on the edge', () => {
});
});

// https://github.com/resend/react-email/issues/3090
it('waits for Suspense boundaries to resolve before resolving', async () => {
const htmlPromise = new Promise<string>((resolve) =>
setTimeout(
() => resolve('<p>content rendered after suspension</p>'),
50,
),
);
const EmailTemplate = () => {
const html = use(htmlPromise);
return <div dangerouslySetInnerHTML={{ __html: html }} />;
};

const renderedTemplate = await render(
<Suspense>
<EmailTemplate />
</Suspense>,
);

expect(renderedTemplate).not.toContain('$RC');
expect(renderedTemplate).not.toContain('<!--$?-->');
expect(renderedTemplate).toContain('content rendered after suspension');
});

/**
* Create a large email that would trigger React's streaming optimization
* if progressiveChunkSize wasn't set to Infinity
Expand Down
2 changes: 1 addition & 1 deletion packages/render/src/node/render-node.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ describe('render on node environments', () => {
resolve(
'<p>example content with some multibyte characters: 情報Ⅰ</p>',
),
500,
50,
),
);
const EmailTemplate = () => {
Expand Down
5 changes: 4 additions & 1 deletion packages/render/src/node/render.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,10 @@ export const render = async (node: React.ReactNode, options?: Options) => {
},
},
)
.then((stream) => readStream(stream))
.then(async (stream) => {
await stream.allReady;
return readStream(stream);
})
.then((result) => {
html = result;
resolve();
Expand Down
Loading