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:
parent
a066873e37
commit
f4b6095719
1 changed files with 3447 additions and 37 deletions
|
|
@ -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);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
Loading…
Reference in a new issue