From 6c40c291d9502c1ef5795264a1f29f27cccd2522 Mon Sep 17 00:00:00 2001 From: DongHyeonka Date: Tue, 18 Aug 2026 00:51:50 +0900 Subject: [PATCH] test: cover Studio error mapping's remaining outcome branches and CSRF rejection recovery --- .../tech-log/studio-error-mapping.test.ts | 124 ++++++++++++++++++ 1 file changed, 124 insertions(+) diff --git a/tests/features/tech-log/studio-error-mapping.test.ts b/tests/features/tech-log/studio-error-mapping.test.ts index b106b49..105712c 100644 --- a/tests/features/tech-log/studio-error-mapping.test.ts +++ b/tests/features/tech-log/studio-error-mapping.test.ts @@ -58,6 +58,99 @@ test("maps UNAUTHENTICATED onto AUTHENTICATION_REQUIRED", () => { assert.equal(error.status, 401); }); +test("falls back to STUDIO_UNAVAILABLE and drops an uncontracted problem code", () => { + const error = toStudioGatewayError( + { + kind: "PROBLEM", + problem: { + type: "https://techlog.local/problems/bogus", + title: "BOGUS", + status: 418, + detail: "server sent a code outside the contract", + code: "TOTALLY_MADE_UP_CODE", + }, + metadata: { status: 418 }, + effect: "NOT_APPLIED", + } as never, + "saveStudioDocument", + ); + + assert.equal(error.code, "STUDIO_UNAVAILABLE"); + assert.equal(error.status, 418); + // The unrecognised code must not survive into the resulting error anywhere, + // not just be absent from `.code` — otherwise a caller reading `.problem` + // could still observe it. + assert.ok( + !JSON.stringify(error.problem).includes("TOTALLY_MADE_UP_CODE"), + "the bogus code leaked into the synthesized problem", + ); +}); + +test("maps FORBIDDEN onto STUDIO_ACCESS_DENIED", () => { + const error = toStudioGatewayError( + { kind: "FORBIDDEN", effect: "NOT_APPLIED" } as never, + "getStudioDashboard", + ); + + assert.equal(error.code, "STUDIO_ACCESS_DENIED"); + assert.equal(error.status, 403); + assert.equal(error.retryable, false); +}); + +test("maps RATE_LIMITED onto a retryable STUDIO_UNAVAILABLE", () => { + const error = toStudioGatewayError( + { kind: "RATE_LIMITED", effect: "NOT_APPLIED" } as never, + "getStudioDashboard", + ); + + assert.equal(error.code, "STUDIO_UNAVAILABLE"); + assert.equal(error.status, 429); + assert.equal(error.retryable, true); +}); + +test("maps CANCELLED onto a non-retryable STUDIO_UNAVAILABLE", () => { + const error = toStudioGatewayError( + { kind: "CANCELLED", effect: "NOT_STARTED" } as never, + "getStudioDashboard", + ); + + assert.equal(error.code, "STUDIO_UNAVAILABLE"); + assert.equal(error.status, 499); + assert.equal(error.retryable, false); +}); + +test("maps CONTRACT_VIOLATION and AUTH_INTEGRATION_FAILURE onto the same non-retryable STUDIO_UNAVAILABLE", () => { + const contractViolation = toStudioGatewayError( + { + kind: "CONTRACT_VIOLATION", + violation: { kind: "UNEXPECTED_STATUS", operation: "RESPONSE" }, + effect: "NOT_APPLICABLE", + } as never, + "getStudioDashboard", + ); + const authIntegrationFailure = toStudioGatewayError( + { kind: "AUTH_INTEGRATION_FAILURE", reason: "UNKNOWN_AUTH_PROFILE", effect: "NOT_APPLICABLE" } as never, + "getStudioDashboard", + ); + + for (const error of [contractViolation, authIntegrationFailure]) { + assert.equal(error.code, "STUDIO_UNAVAILABLE"); + assert.equal(error.status, 502); + assert.equal(error.retryable, false); + } +}); + +test("throws for a SUCCESS outcome instead of returning a fabricated error", () => { + assert.throws( + () => + toStudioGatewayError( + { kind: "SUCCESS", value: undefined, metadata: { status: 200 }, effect: "NOT_APPLICABLE" } as never, + "getStudioDashboard", + ), + /success outcome is not an error/, + ); +}); + test("fetches the CSRF token once and reuses it until invalidated", async () => { let calls = 0; const provider = createCsrfTokenProvider({ @@ -89,3 +182,34 @@ test("does not stampede concurrent CSRF requests", async () => { await Promise.all([provider.token(), provider.token(), provider.token()]); assert.equal(calls, 1); }); + +test("resolves the header name from the same cached snapshot as the token", async () => { + let calls = 0; + const provider = createCsrfTokenProvider({ + async execute() { + calls += 1; + return { csrfToken: "token", csrfHeaderName: "X-CSRF-TOKEN" }; + }, + }); + + assert.equal(await provider.headerName(), "X-CSRF-TOKEN"); + assert.equal(await provider.token(), "token"); + assert.equal(calls, 1); +}); + +test("does not cache a rejected CSRF fetch and retries cleanly on the next call", async () => { + let calls = 0; + const provider = createCsrfTokenProvider({ + async execute() { + calls += 1; + if (calls === 1) throw new Error("network failure"); + return { csrfToken: "token", csrfHeaderName: "X-CSRF-TOKEN" }; + }, + }); + + await assert.rejects(provider.token()); + assert.equal(calls, 1); + + assert.equal(await provider.token(), "token"); + assert.equal(calls, 2); +});