fix: add oauth retry regression coverage (#48) (thanks @caseyg)

This commit is contained in:
Peter Steinberger 2026-03-03 00:01:41 +00:00
parent 8940d13605
commit aaac0e2618
3 changed files with 32 additions and 0 deletions

View File

@ -10,6 +10,7 @@
- OAuth wait/redirect now share one deferred to eliminate authorization race windows and preserve stable close-path errors, including wait-before-redirect and repeated-redirect flows. (PR #70, thanks @monotykamary)
- Added `--raw-strings` (numeric coercion off) and `--no-coerce` (all coercion off) for `mcporter call` argument parsing so IDs/codes can stay literal strings. (PR #59, thanks @nobrainer-tech)
- Added `CallResult.images()` plus opt-in `mcporter call --save-images <dir>` so image content blocks can be persisted without changing existing stdout output contracts. (PR #61, thanks @daniella-11ways)
- OAuth transport retries now classify HTTP 405 as HTTP (not auth) and OAuth promotion applies to configured HTTP servers too, so post-auth fallback flows no longer drop credentials on 405-only endpoints. (PR #48, thanks @caseyg)
### Tooling / Dependencies
- Updated dependencies to latest releases (including MCP SDK, Rolldown RC, Zod, Biome, Oxlint, Vitest, Bun types).

View File

@ -26,6 +26,18 @@ describe('analyzeConnectionError', () => {
expect(issue.statusCode).toBe(429);
});
it.each([401, 403] as const)('keeps %s classified as auth', (status) => {
const issue = analyzeConnectionError(new Error(`SSE error: Non-200 status code (${status})`));
expect(issue.kind).toBe('auth');
expect(issue.statusCode).toBe(status);
});
it('classifies HTTP 405 as transport/http instead of auth', () => {
const issue = analyzeConnectionError(new Error('SSE error: Non-200 status code (405)'));
expect(issue.kind).toBe('http');
expect(issue.statusCode).toBe(405);
});
it('extracts HTTP status codes from JSON payloads', () => {
const issue = analyzeConnectionError(new Error('{"error":{"status":503}}'));
expect(issue.kind).toBe('http');

View File

@ -35,6 +35,25 @@ describe('maybeEnableOAuth', () => {
expect(updated).toBeDefined();
expect(updated?.auth).toBe('oauth');
});
it('does not mutate stdio servers', () => {
const def: ServerDefinition = {
name: 'stdio-server',
command: { kind: 'stdio', command: 'echo', args: [], cwd: process.cwd() },
};
const updated = maybeEnableOAuth(def, logger as never);
expect(updated).toBeUndefined();
});
it('does not re-promote servers already configured for oauth', () => {
const def: ServerDefinition = {
name: 'oauth-server',
auth: 'oauth',
command: { kind: 'http', url: new URL('https://example.com') },
};
const updated = maybeEnableOAuth(def, logger as never);
expect(updated).toBeUndefined();
});
});
describe('isUnauthorizedError helper', () => {