bunext/dist/__tests__/hydration/hydration.test.js
2026-03-21 10:14:38 +01:00

63 lines
2.5 KiB
JavaScript

import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import { describe, expect, test, beforeEach, afterEach } from "bun:test";
import React, { useState } from "react";
import { renderToString } from "react-dom/server";
import { hydrateRoot } from "react-dom/client";
import { GlobalWindow } from "happy-dom";
// A mock application component to test hydration
function App() {
const [count, setCount] = useState(0);
return (_jsxs("div", { id: "app-root", children: [_jsx("h1", { children: "Test Hydration" }), _jsxs("p", { "data-testid": "count", children: ["Count: ", count] }), _jsx("button", { "data-testid": "btn", onClick: () => setCount(c => c + 1), children: "Increment" })] }));
}
describe("React Hydration", () => {
let window;
let document;
beforeEach(() => {
window = new GlobalWindow();
document = window.document;
global.window = window;
global.document = document;
global.navigator = { userAgent: "node.js" };
});
afterEach(() => {
// Clean up global mocks
delete global.window;
delete global.document;
delete global.navigator;
window.close();
});
test("hydrates a server-rendered component and binds events", async () => {
// 1. Server-side render
const html = renderToString(_jsx(App, {}));
// 2. Setup DOM as it would be delivered to the client
document.body.innerHTML = `<div id="root">${html}</div>`;
const rootNode = document.getElementById("root");
// 3. Hydrate
let hydrateError = null;
try {
await new Promise((resolve) => {
hydrateRoot(rootNode, _jsx(App, {}), {
onRecoverableError: (err) => {
hydrateError = err;
}
});
setTimeout(resolve, 50); // let React finish hydration
});
}
catch (e) {
hydrateError = e;
}
// Verify no hydration errors
expect(hydrateError).toBeNull();
// 4. Verify client-side interactivity
const button = document.querySelector('[data-testid="btn"]');
const countText = document.querySelector('[data-testid="count"]');
expect(countText.textContent).toBe("Count: 0");
// Simulate click
button.dispatchEvent(new window.Event("click", { bubbles: true }));
// Let async state updates process
await new Promise(r => setTimeout(r, 50));
expect(countText.textContent).toBe("Count: 1");
});
});