testReactCacheLastsARequest

tcmts.cli.test.e2e.prod.testReactCacheLastsARequest · #lp26bju2 · term

React's cache in server components tcm renders: what one keeps is kept for the request, shared by everything it renders, and asked again in the next; cacheSignal is the request's

import { okIn, plainEnv, tcmBin, tempDir, withChildren } from "#codebase/tcmts/cli/test/e2e/harness";
import { CACHED_CALLS } from "#codebase/tcmts/cli/test/e2e/prod";
import assert from "node:assert/strict";
import { spawn } from "node:child_process";
import fs from "node:fs";
import path from "node:path";

export const testReactCacheLastsARequest = () =>
  withChildren(async (keep) => {
    const dir = tempDir("react cache");
    const tcm = (...args: string[]) => okIn(dir, ...args);
    tcm("init");
    fs.rmSync(path.join(dir, "scratch.ts"));
    fs.writeFileSync(path.join(dir, "counted.tsx"), CACHED_CALLS);
    tcm("add", "counted.tsx");
    const url = await new Promise<string>((resolve, reject) => {
      const child = keep(
        spawn(process.execPath, [tcmBin(), "start", "counted.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}`)));
    });
    const page = async () =>
      (await (await fetch(url, { headers: { accept: "text/html" } })).text()).replaceAll(
        "<!-- -->",
        "",
      );
    const first = await page();
    assert.match(
      first,
      /<p class="a">x1<\/p><p class="b">x1:true<\/p>/,
      "asked once for the page, and the request's signal",
    );
    assert.match(
      await page(),
      /<p class="a">x2<\/p><p class="b">x2:true<\/p>/,
      "and again for the next",
    );
  })

uses