// Rôle : observe le chargement réel de l'application avec des réponses réseau contrôlées sous StrictMode. import { createElement, StrictMode, useLayoutEffect } from "react"; import { createRoot } from "react-dom/client"; import { flushSync } from "react-dom"; import { useAppData } from "../../website/src/hooks/useAppData.js"; export function mountAppDataProbe(element, initialRoute) { const originalFetch = globalThis.fetch; const requests = []; const snapshots = []; const root = createRoot(element); globalThis.fetch = (url, { signal } = {}) => new Promise((resolve) => { // Le double ignore volontairement abort pour tester aussi les réponses déjà en cours. requests.push({ url, signal, resolve, settled: false }); }); function Probe({ route }) { const data = useAppData(route); useLayoutEffect(() => { snapshots.push(data); }); return createElement("pre", { id: "data-state" }, JSON.stringify(data)); } function navigate(route) { snapshots.length = 0; flushSync(() => root.render(createElement(StrictMode, null, createElement(Probe, { route })))); } navigate(initialRoute); return { snapshots, requests: () => requests.map(({ url, signal, settled }) => ({ url, aborted: signal?.aborted, settled })), respond(url, payload, status = 200, aborted = false) { for (const request of requests) { if (request.url !== url || request.settled || request.signal?.aborted !== aborted) continue; request.settled = true; request.resolve({ ok: status >= 200 && status < 300, json: async () => payload }); } }, navigate, unmount() { flushSync(() => root.unmount()); globalThis.fetch = originalFetch; } }; }