Skip to content

Commit f1b29d6

Browse files
test(cli): pin the production-reachable producer of the stale-failure override
Review note: the pre-artifact-noise test drives the scenario with an EPIPE, which only reaches 'render validates afterwards' because process.exit is mocked — that sequence can't occur in production. Add a test for the reachable producer: an unhandledRejection before validation (the handler deliberately does not exit), followed by a validated render, must score success:true at exit code 0. Verified red on the pre-override cli.ts.
1 parent 6736e7e commit f1b29d6

1 file changed

Lines changed: 31 additions & 0 deletions

File tree

‎packages/cli/src/cli.lifecycle.test.ts‎

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,37 @@ describe("CLI lifecycle", () => {
134134
}
135135
});
136136

137+
it("does not let a pre-validation unhandledRejection doom a validated render", async () => {
138+
// The production-reachable producer of the stale-failure override: the
139+
// unhandledRejection handler deliberately does NOT exit, so a stray
140+
// rejection mid-render sets commandFailed (and exitCode 1), the render
141+
// then completes and validates, and finalizeCli writes exit code 0.
142+
const trackCommandResult = vi.fn();
143+
// Detach the test runner's own unhandledRejection listeners so the
144+
// synthetic emit reaches only the CLI's handler, then restore them.
145+
const priorListeners = process.listeners("unhandledRejection");
146+
process.removeAllListeners("unhandledRejection");
147+
try {
148+
const successState = await import("./utils/render-success-state.js");
149+
mockInitCommand(() => {
150+
process.emit("unhandledRejection", new Error("stray teardown noise"), Promise.resolve());
151+
successState.markRenderSucceeded();
152+
});
153+
mockTelemetry({ trackCommandResult });
154+
155+
process.argv = ["node", "cli.ts", "init", "--json"];
156+
await import("./cli.js");
157+
158+
expect(trackCommandResult).toHaveBeenCalledWith(
159+
expect.objectContaining({ success: true, exitCode: 0 }),
160+
);
161+
successState._resetRenderSuccessForTests();
162+
} finally {
163+
process.removeAllListeners("unhandledRejection");
164+
for (const listener of priorListeners) process.on("unhandledRejection", listener);
165+
}
166+
});
167+
137168
it("still scores an EPIPE before the artifact is validated as a failure", async () => {
138169
const trackCommandResult = vi.fn();
139170
const exitSpy = vi.spyOn(process, "exit").mockImplementation((() => undefined) as never);

0 commit comments

Comments
 (0)