mirror of
https://github.com/morluto/rea
synced 2026-10-26 14:25:49 -04:00
10f1994fe1
Serve retained capture Evidence as a bounded MCP replay environment with discovery. Preserve default stdio, caller-selected facts and complete source Evidence. Fix numeric fidelity, argument identity, startup cancellation and bounded discovery, query/path matching and output metadata. Verify real recorded API data and public CLI/MCP workflows; preserve explicit gaps for Windows and third-party hosts. Co-authored-by: Edgar Arakelyan <edgar.arakelyan@scale.com> Co-authored-by: gensokyo-dev <gensokyo-dev@users.noreply.github.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
53 lines
2.1 KiB
TypeScript
53 lines
2.1 KiB
TypeScript
import { once } from "node:events";
|
|
import { describe, expect } from "vitest";
|
|
|
|
import { MCP_SHUTDOWN_FAILED } from "../../../src/main/messages.js";
|
|
import { rawHttpRequest } from "../../support/http/rawRequest.js";
|
|
import { startMcpHttpProcess } from "../../support/mcp/streamableHttpProcess.js";
|
|
import { processTest } from "../../support/process/processFixture.js";
|
|
|
|
const SHUTDOWN_TIMEOUT_MS = 90_000;
|
|
|
|
const shutdownSignals: readonly (readonly [NodeJS.Signals, number])[] = [
|
|
["SIGTERM", 143],
|
|
["SIGINT", 130],
|
|
];
|
|
|
|
// Windows child.kill() force-terminates even for SIGINT; it does not deliver a console interrupt.
|
|
describe.skipIf(process.platform === "win32")("rea mcp --http shutdown", () => {
|
|
for (const [signal, status] of shutdownSignals)
|
|
processTest(
|
|
`releases the listener and exits ${String(status)} on ${signal}`,
|
|
async ({ processes }) => {
|
|
const started = await startMcpHttpProcess(processes);
|
|
// The live transport refuses a GET that does not accept an event stream.
|
|
const before = await rawHttpRequest(started.url);
|
|
expect(before.status).toBe(406);
|
|
started.child.kill(signal);
|
|
const [code, signalCode] = await once(started.child, "close");
|
|
expect(code).toBe(status);
|
|
expect(signalCode).toBeNull();
|
|
expect(started.stderr()).not.toContain(MCP_SHUTDOWN_FAILED);
|
|
await expect(rawHttpRequest(started.url)).rejects.toMatchObject({
|
|
code: "ECONNREFUSED",
|
|
});
|
|
},
|
|
SHUTDOWN_TIMEOUT_MS,
|
|
);
|
|
|
|
processTest(
|
|
"exits with the signal status when the signal lands as startup completes",
|
|
async ({ processes }) => {
|
|
const started = await startMcpHttpProcess(processes);
|
|
// No request first: the signal arrives at the edge between startup and the lifecycle owner.
|
|
const [signal, status] = shutdownSignals[0]!;
|
|
started.child.kill(signal);
|
|
const [code, signalCode] = await once(started.child, "close");
|
|
expect(code).toBe(status);
|
|
expect(signalCode).toBeNull();
|
|
expect(started.stderr()).not.toContain(MCP_SHUTDOWN_FAILED);
|
|
},
|
|
SHUTDOWN_TIMEOUT_MS,
|
|
);
|
|
});
|