Files
OmniRoute/tests/unit/grok-web-stream-error-boundary.test.ts
Diego Rodrigues de Sa e Souza ca2edfdca8 fix(grok-web): stop streaming errors from reporting false success (#12458)
Validado em lote numa worktree combinada com os 14 PRs desta campanha de error-boundary sobre o tip de `release/v3.8.51`: `typecheck:core` limpo e **120/120** nos 23 arquivos de teste que os PRs trazem.

Um ponto que só apareceu no tree combinado: **#12465 e #12466 criam o mesmo arquivo novo** `open-sse/utils/streamReadiness.ts` (que não existe no tip) com desenhos divergentes de cancelamento — `cancelled` + `releaseLock` imediato num, `readInFlight`/`cancelRequested` com `cancelReader` fire-and-forget no outro. Adotei a versão do #12466, que difere e defere o release do lock para quando a leitura em voo termina, e validei a escolha rodando as suítes dos **dois** PRs contra ela: 21/21 no readiness compartilhado e 22/22 incluindo o boundary do Perplexity.
2026-09-03 20:59:56 -03:00

87 lines
2.7 KiB
TypeScript

import assert from "node:assert/strict";
import { spawn } from "node:child_process";
import { fileURLToPath } from "node:url";
import test from "node:test";
const repoRoot = fileURLToPath(new URL("../../", import.meta.url));
const fixturePath = fileURLToPath(
new URL("../fixtures/grok-web-stream-error-boundary-child.ts", import.meta.url)
);
type FixtureResult = {
code: number | null;
signal: NodeJS.Signals | null;
stdout: string;
stderr: string;
};
function runFixture(): Promise<FixtureResult> {
// Keep the parent process pristine: test:unit:fast runs files with
// --test-isolation=none, so repository imports or env/DB mutations here can
// collide with unrelated tests. All stateful coverage lives in the child.
const childEnv: NodeJS.ProcessEnv = {
PATH: process.env.PATH,
NODE_PATH: process.env.NODE_PATH,
LANG: process.env.LANG,
LC_ALL: process.env.LC_ALL,
TZ: process.env.TZ,
TMPDIR: process.env.TMPDIR,
NODE_ENV: "test",
API_KEY_SECRET: "grok-boundary-test-only-secret-with-32-plus-characters",
DISABLE_SQLITE_AUTO_BACKUP: "true",
NO_COLOR: "1",
};
// An inherited marker makes Node treat this nested --test run as recursive
// and silently skip the fixture instead of executing its seven regressions.
delete childEnv.NODE_TEST_CONTEXT;
return new Promise((resolve, reject) => {
const child = spawn(process.execPath, ["--import", "tsx/esm", "--test", fixturePath], {
cwd: repoRoot,
env: childEnv,
stdio: ["ignore", "pipe", "pipe"],
});
let stdout = "";
let stderr = "";
let timedOut = false;
child.stdout.setEncoding("utf8");
child.stderr.setEncoding("utf8");
child.stdout.on("data", (chunk: string) => {
stdout += chunk;
});
child.stderr.on("data", (chunk: string) => {
stderr += chunk;
});
const timeout = setTimeout(() => {
timedOut = true;
child.kill("SIGKILL");
}, 120_000);
child.once("error", (error) => {
clearTimeout(timeout);
reject(error);
});
child.once("close", (code, signal) => {
clearTimeout(timeout);
if (timedOut) {
reject(new Error("Grok Web stream error boundary fixture timed out after 120 seconds"));
return;
}
resolve({ code, signal, stdout, stderr });
});
});
}
test("Grok Web stream error boundary passes in a process-isolated runtime", async () => {
const result = await runFixture();
const output = `${result.stdout}\n${result.stderr}`;
assert.equal(result.signal, null, output.slice(-12_000));
assert.equal(result.code, 0, output.slice(-12_000));
assert.match(output, /(?:^|\s)tests\s+7(?:\s|$)/m);
assert.match(output, /(?:^|\s)pass\s+7(?:\s|$)/m);
assert.match(output, /(?:^|\s)fail\s+0(?:\s|$)/m);
});