testPagesKeepAndRenderAhead
The react library's Pages: the page left stays mounted, hidden, so going back shows it as it was; and a page a link to is pointed at is rendered ahead, hidden, before it's followed
import { CHROME, hydrated, withPage } from "#codebase/tcmts/cli/test/browser"; import { okIn, plainEnv, tcmBin, tempDir, withChildren } from "#codebase/tcmts/cli/test/e2e/harness"; import { KEPT_PAGES } from "#codebase/tcmts/cli/test/e2e/react"; import assert from "node:assert/strict"; import { spawn } from "node:child_process"; import fs from "node:fs"; import path from "node:path"; export const testPagesKeepAndRenderAhead = () => withChildren(async (keep) => { if (!CHROME) return console.log("skipped: no Chrome"); const dir = tempDir("kept pages"); const tcm = (...args: string[]) => okIn(dir, ...args); tcm("init"); fs.rmSync(path.join(dir, "scratch.ts")); tcm("lib", "add", "tcm", "react", "--at", "kept.lib.react"); fs.writeFileSync(path.join(dir, "kept.tsx"), KEPT_PAGES); tcm("add", "kept.tsx"); const url = await new Promise<string>((resolve, reject) => { const child = keep( spawn(process.execPath, [tcmBin(), "start", "kept.App", "--port", "0"], { cwd: dir, env: plainEnv(), }), ); let out = ""; child.stdout.setEncoding("utf8").on("data", (d: string) => { out += d; const m = /url\s+(http:\/\/\S+)/.exec(out); if (m) resolve(m[1]!); }); child.on("exit", (code) => reject(new Error(`tcm start exited ${code}:\n${out}`))); }); await withPage(url, async (p) => { assert.ok(await hydrated(p)); // what's shown: the sections not hidden; and all of them, hidden ones too const shown = `[...document.querySelectorAll("section")].filter((s) => s.offsetParent !== null).map((s) => s.textContent).join(",")`; const all = `[...document.querySelectorAll("section")].map((s) => s.querySelector("h1").textContent).sort().join(",")`; const link = (text: string) => `[...document.querySelectorAll("a")].find((a) => a.textContent === ${JSON.stringify(text)})`; await p.evaluate(`document.querySelector("button").click()`); await p.waitFor<string>(shown, (t) => t === "home1"); await p.evaluate(`document.querySelector("button").click()`); assert.equal(await p.waitFor<string>(shown, (t) => t === "home2"), "home2"); await p.evaluate(`${link("one")}.click()`); assert.equal(await p.waitFor<string>(shown, (t) => t === "one0"), "one0"); assert.equal(await p.evaluate<string>(all), "home,one", "the page left, kept"); await p.evaluate("history.back()"); assert.equal( await p.waitFor<string>(shown, (t) => t.startsWith("home")), "home2", "as it was", ); // pointed at: rendered ahead, hidden await p.evaluate( `${link("two")}.dispatchEvent(new PointerEvent("pointerover", { bubbles: true }))`, ); assert.equal( await p.waitFor<string>(all, (t) => t.includes("two")), "home,one,two", "rendered ahead", ); assert.equal(await p.evaluate<string>(shown), "home2", "and not shown"); await p.evaluate(`${link("two")}.click()`); assert.equal(await p.waitFor<string>(shown, (t) => t === "two0"), "two0"); assert.deepEqual(p.errors, []); }); })