testWebUiStopsWithTheServer

tcmts.cli.test.e2e.contributions.testWebUiStopsWithTheServer · #fahq6wsf · term

the web UI stops with the tcm serve that started it, however that ended: killed, its exit handlers never run

import { codebase, env, LIB, uiPage } from "#codebase/tcmts/cli/test/e2e/contributions";
import { strip, tcmBin, tempDir, withChildren } from "#codebase/tcmts/cli/test/e2e/harness";
import assert from "node:assert/strict";
import { execFileSync, spawn } from "node:child_process";

export const testWebUiStopsWithTheServer = async () => {
  const server = codebase(tempDir("contributions stop"), "served");
  server.write(LIB);
  server.tcm("add");
  await withChildren(async (keep) => {
    const child = keep(
      spawn(process.execPath, [tcmBin(), "serve", "--port", "0", "--token", "tok", "--public"], {
        cwd: server.dir,
        env: env(),
      }),
    );
    let out = "";
    child.stdout.setEncoding("utf8").on("data", (d: string) => (out += d));
    child.stderr.setEncoding("utf8").on("data", (d: string) => (out += d));
    const url = await new Promise<string>((resolve) => {
      const look = setInterval(() => {
        const m = /url\s+(https?:\/\/[\d.]+:\d+)/.exec(out);
        if (m) (clearInterval(look), resolve(m[1]!));
      }, 50);
    });
    assert.equal((await uiPage(`${url}/forge/people`)).status, 200);
    const ui = /ui\s+url\s+(https?:\/\/[\d.]+:(\d+))/.exec(strip(out));
    assert.ok(ui, out);
    child.kill("SIGKILL");
    const until = Date.now() + 15_000;
    let answers = true;
    while (answers && Date.now() < until) {
      await new Promise((r) => setTimeout(r, 250));
      answers = await fetch(`${ui[1]}/forge/people`).then(
        () => true,
        () => false,
      );
    }
    if (answers)
      // (left running: stop it, so the failure doesn't outlive the test)
      try {
        execFileSync("pkill", ["-f", `start app --port ${ui[2]}`]);
      } catch {}
    assert.ok(!answers, "the web UI stopped when its server was killed");
  });
}

uses