Skip to content

Commit e0e6b9c

Browse files
authored
Add regression test for facebook#19269 (facebook#19282)
1 parent 77e8722 commit e0e6b9c

File tree

1 file changed

+83
-0
lines changed

1 file changed

+83
-0
lines changed

packages/react-dom/src/__tests__/ReactDOMServerPartialHydration-test.internal.js

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2897,6 +2897,89 @@ describe('ReactDOMServerPartialHydration', () => {
28972897
expect(ref.current).not.toBe(null);
28982898
});
28992899

2900+
// @gate experimental
2901+
it('regression test: does not overfire non-bubbling browser events', async () => {
2902+
let suspend = false;
2903+
let resolve;
2904+
const promise = new Promise(resolvePromise => (resolve = resolvePromise));
2905+
2906+
function Sibling({text}) {
2907+
if (suspend) {
2908+
throw promise;
2909+
} else {
2910+
return 'Hello';
2911+
}
2912+
}
2913+
2914+
let submits = 0;
2915+
2916+
function Form() {
2917+
const [submitted, setSubmitted] = React.useState(false);
2918+
if (submitted) {
2919+
return null;
2920+
}
2921+
return (
2922+
<form
2923+
onSubmit={() => {
2924+
setSubmitted(true);
2925+
submits++;
2926+
}}>
2927+
Click me
2928+
</form>
2929+
);
2930+
}
2931+
2932+
function App() {
2933+
return (
2934+
<div>
2935+
<Suspense fallback="Loading...">
2936+
<Form />
2937+
<Sibling />
2938+
</Suspense>
2939+
</div>
2940+
);
2941+
}
2942+
2943+
suspend = false;
2944+
const finalHTML = ReactDOMServer.renderToString(<App />);
2945+
const container = document.createElement('div');
2946+
container.innerHTML = finalHTML;
2947+
2948+
// We need this to be in the document since we'll dispatch events on it.
2949+
document.body.appendChild(container);
2950+
2951+
const form = container.getElementsByTagName('form')[0];
2952+
2953+
// On the client we don't have all data yet but we want to start
2954+
// hydrating anyway.
2955+
suspend = true;
2956+
const root = ReactDOM.createRoot(container, {hydrate: true});
2957+
root.render(<App />);
2958+
Scheduler.unstable_flushAll();
2959+
jest.runAllTimers();
2960+
2961+
expect(container.textContent).toBe('Click meHello');
2962+
2963+
// We're now partially hydrated.
2964+
form.dispatchEvent(
2965+
new Event('submit', {
2966+
bubbles: true,
2967+
}),
2968+
);
2969+
expect(submits).toBe(0);
2970+
2971+
// Resolving the promise so that rendering can complete.
2972+
suspend = false;
2973+
resolve();
2974+
await promise;
2975+
2976+
Scheduler.unstable_flushAll();
2977+
jest.runAllTimers();
2978+
expect(submits).toBe(1);
2979+
expect(container.textContent).toBe('Hello');
2980+
document.body.removeChild(container);
2981+
});
2982+
29002983
// This test fails, in both forks. Without a boundary, the deferred tree won't
29012984
// re-enter hydration mode. It doesn't come up in practice because there's
29022985
// always a parent Suspense boundary. But it's still a bug. Leaving for a

0 commit comments

Comments
 (0)