test: close ≥90% per-file coverage gaps for mid-session auth

The mid-session auth work passed `validate`/CI but failed the local-only
`npm run test:coverage` per-file gate (≥90% lines/statements/functions/
branches) on 12 files. Add targeted unit/integration tests so every changed
file clears the gate; annotate provably-dead defensive branches with justified
`/* v8 ignore */` comments rather than relaxing the gate.

Files brought to ≥90 on all four dimensions:
- core/auth: mcpAuth, oauthUx, utils, challenge, node/runner-interactive-oauth
- core/mcp: oauthManager, inspectorClient, node/authChallengeFetch,
  remote/remoteClientTransport, remote/node/{remote-session,server}
- clients/web/src/utils: oauthResume, browserTabVisibility

`npm run test:coverage` now passes (3575 tests, 0 threshold failures);
`npm run validate` green across all four clients.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DZyeWManYTvcXxjcrhxSQc
This commit is contained in:
cliffhall 2026-07-03 12:54:37 -04:00
commit f4b6095719

View file

@ -788,4 +788,113 @@ describe("server.ts supplemental coverage", () => {
}
});
});
describe("keychain-unavailable 503 on PUT/DELETE", () => {
class UnavailableOnWriteStore implements SecretStore {
async get(): Promise<string | null> {
return null;
}
async set(): Promise<void> {
throw new KeychainUnavailableError(new Error("libsecret missing"));
}
async delete(): Promise<void> {
/* no-op */
}
async deleteAllForServer(): Promise<void> {
throw new KeychainUnavailableError(new Error("libsecret missing"));
}
}
it("PUT returns 503 when the keychain write is unavailable", async () => {
const h = await start({
secretStore: new UnavailableOnWriteStore(),
seedConfig: JSON.stringify({
mcpServers: {
srv: {
type: "streamable-http",
url: "https://x.test/mcp",
oauth: { clientId: "cid", clientSecret: "shh" },
},
},
}),
});
try {
const res = await fetch(`${h.baseUrl}/api/servers/srv`, {
method: "PUT",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
config: { type: "streamable-http", url: "https://x.test/mcp" },
settings: {
headers: [],
metadata: [],
connectionTimeout: 0,
requestTimeout: 0,
oauthClientSecret: "new-secret",
},
}),
});
expect(res.status).toBe(503);
expect((await res.json()).error).toMatch(/libsecret missing/);
} finally {
await stop(h);
}
});
it("DELETE returns 503 when the keychain sweep is unavailable", async () => {
const h = await start({
secretStore: new UnavailableOnWriteStore(),
seedConfig: JSON.stringify({
mcpServers: { srv: { type: "stdio", command: "node" } },
}),
});
try {
const res = await fetch(`${h.baseUrl}/api/servers/srv`, {
method: "DELETE",
});
expect(res.status).toBe(503);
expect((await res.json()).error).toMatch(/libsecret missing/);
} finally {
await stop(h);
}
});
});
describe("migratePlaintextSecrets rethrows a non-keychain error", () => {
class ThrowingOnGetStore implements SecretStore {
async get(): Promise<string | null> {
throw new Error("disk full");
}
async set(): Promise<void> {
/* unreachable in this test */
}
async delete(): Promise<void> {
/* no-op */
}
async deleteAllForServer(): Promise<void> {
/* no-op */
}
}
it("GET /api/servers returns 500 when migration hits a non-KeychainUnavailableError", async () => {
const h = await start({
secretStore: new ThrowingOnGetStore(),
seedConfig: JSON.stringify({
mcpServers: {
srv: {
type: "streamable-http",
url: "https://x.test/mcp",
oauth: { clientId: "cid", clientSecret: "shh" },
},
},
}),
});
try {
const res = await fetch(`${h.baseUrl}/api/servers`);
expect(res.status).toBe(500);
expect((await res.json()).error).toMatch(/Failed to read server list/);
} finally {
await stop(h);
}
});
});
});