Skip to content

Commit 7b3bc5f

Browse files
committed
fix(test): update expected failures and correct auth test assertion
1 parent 79cc494 commit 7b3bc5f

2 files changed

Lines changed: 21 additions & 35 deletions

File tree

test/e2e/requirements.ts

Lines changed: 4 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -219,23 +219,11 @@ export const REQUIREMENTS: Record<string, Requirement> = {
219219
'protocol:progress:callback': {
220220
source: 'https://modelcontextprotocol.io/specification/2025-11-25/basic/utilities/progress#progress-flow',
221221
behavior:
222-
"Progress notifications emitted by a handler during a request are delivered to the caller's progress callback, in order, with their progress, total, and message.",
223-
knownFailures: [
224-
{
225-
transport: 'sse',
226-
note: "Real-socket SSE delivers a handler's progress notifications and its response in one batch; the response is processed first, so the progress notifications never reach the caller's progress callback."
227-
}
228-
]
222+
"Progress notifications emitted by a handler during a request are delivered to the caller's progress callback, in order, with their progress, total, and message."
229223
},
230224
'typescript:protocol:progress:token-injected': {
231225
source: 'sdk',
232-
behavior: 'Passing onprogress causes a progressToken to be injected into request _meta, preserving existing _meta fields.',
233-
knownFailures: [
234-
{
235-
transport: 'sse',
236-
note: "Real-socket SSE delivers a handler's progress notifications and its response in one batch; the response is processed first, so the progress notifications never reach the caller's progress callback."
237-
}
238-
]
226+
behavior: 'Passing onprogress causes a progressToken to be injected into request _meta, preserving existing _meta fields.'
239227
},
240228
'protocol:progress:token-unique': {
241229
source: 'https://modelcontextprotocol.io/specification/2025-11-25/basic/utilities/progress#progress-flow',
@@ -251,13 +239,7 @@ export const REQUIREMENTS: Record<string, Requirement> = {
251239
},
252240
'protocol:timeout:reset-on-progress': {
253241
source: 'https://modelcontextprotocol.io/specification/2025-11-25/basic/lifecycle#timeouts',
254-
behavior: "When configured to do so, each progress notification resets the request's read timeout.",
255-
knownFailures: [
256-
{
257-
transport: 'sse',
258-
note: 'Same real-socket SSE batching race as protocol:progress:callback: the progress notifications are dropped before they can reset the timeout, so the request times out.'
259-
}
260-
]
242+
behavior: "When configured to do so, each progress notification resets the request's read timeout."
261243
},
262244
'protocol:timeout:sends-cancellation': {
263245
source: 'https://modelcontextprotocol.io/specification/2025-11-25/basic/lifecycle#timeouts',
@@ -386,13 +368,7 @@ export const REQUIREMENTS: Record<string, Requirement> = {
386368
},
387369
'tools:call:progress': {
388370
source: 'https://modelcontextprotocol.io/specification/2025-11-25/basic/utilities/progress#progress-flow',
389-
behavior: "Progress notifications emitted by a tool handler reach the caller's progress callback before the tool result returns.",
390-
knownFailures: [
391-
{
392-
transport: 'sse',
393-
note: "Real-socket SSE delivers a handler's progress notifications and its response in one batch; the response is processed first, so the progress notifications never reach the caller's progress callback."
394-
}
395-
]
371+
behavior: "Progress notifications emitted by a tool handler reach the caller's progress callback before the tool result returns."
396372
},
397373
'tools:call:sampling-roundtrip': {
398374
transports: STATEFUL_TRANSPORTS,

test/e2e/scenarios/client-auth.test.ts

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -331,7 +331,9 @@ verifies('client-auth:401-triggers-flow', async (_args: TestArgs) => {
331331

332332
try {
333333
const connectPromise = client.connect(transport);
334-
while (provider.redirectedTo.length === 0) { await new Promise(r => setTimeout(r, 10)); }
334+
while (provider.redirectedTo.length === 0) {
335+
await new Promise(r => setTimeout(r, 10));
336+
}
335337

336338
// Flow ran exactly once: a single 401'd POST, a single redirect to the authorization endpoint.
337339
expect(mcpPosts).toHaveLength(1);
@@ -343,7 +345,7 @@ verifies('client-auth:401-triggers-flow', async (_args: TestArgs) => {
343345

344346
expect(as.discoveryCalls.some(p => p.includes('/.well-known/oauth-protected-resource'))).toBe(true);
345347
expect(as.discoveryCalls).toContain('/.well-known/oauth-authorization-server');
346-
348+
347349
await transport.close();
348350
await expect(connectPromise).rejects.toThrow();
349351
} finally {
@@ -385,7 +387,9 @@ verifies('client-auth:negotiation:auth-before-era', async (_args: TestArgs) => {
385387
// Probe -> 401: the auth challenge propagates. The 401 never decides the
386388
// era -- the auth wall answered before the MCP layer saw server/discover.
387389
const connectPromise = client.connect(first);
388-
while (provider.redirectedTo.length === 0) { await new Promise(r => setTimeout(r, 10)); }
390+
while (provider.redirectedTo.length === 0) {
391+
await new Promise(r => setTimeout(r, 10));
392+
}
389393
expect(mcpPosts).toEqual([{ method: 'server/discover', status: 401, hasAuth: false }]);
390394
expect(provider.redirectedTo).toHaveLength(1);
391395

@@ -490,7 +494,9 @@ verifies('client-auth:403-scope-upgrade', async (_args: TestArgs) => {
490494

491495
try {
492496
const connectPromise = interactiveClient.connect(interactiveTransport);
493-
while (interactiveProvider.redirectedTo.length === 0) { await new Promise(r => setTimeout(r, 10)); }
497+
while (interactiveProvider.redirectedTo.length === 0) {
498+
await new Promise(r => setTimeout(r, 10));
499+
}
494500

495501
expect(interactiveProvider.redirectedTo).toHaveLength(1);
496502
const upgradeRedirect = defined(interactiveProvider.redirectedTo[0], 'authorization redirect URL');
@@ -570,7 +576,9 @@ verifies('client-auth:stepup:scope-union', async (_args: TestArgs) => {
570576
const transport = new StreamableHTTPClientTransport(new URL(MCP_URL), { authProvider: provider, fetch: combinedFetch });
571577
try {
572578
const connectPromise = client.connect(transport);
573-
while (provider.redirectedTo.length === 0) { await new Promise(r => setTimeout(r, 10)); }
579+
while (provider.redirectedTo.length === 0) {
580+
await new Promise(r => setTimeout(r, 10));
581+
}
574582
expect(provider.redirectedTo).toHaveLength(1);
575583
const redirect = defined(provider.redirectedTo[0], 'authorize URL');
576584
expect(redirect.searchParams.get('scope')).toBe('files:read openid files:write');
@@ -605,7 +613,9 @@ verifies(['client-auth:stepup:retry-cap', 'client-auth:stepup:refresh-bypass-on-
605613
const transport = new StreamableHTTPClientTransport(new URL(MCP_URL), { authProvider: provider, fetch: combinedFetch });
606614
try {
607615
const connectPromise = client.connect(transport);
608-
while (provider.redirectedTo.length === 0) { await new Promise(r => setTimeout(r, 10)); }
616+
while (provider.redirectedTo.length === 0) {
617+
await new Promise(r => setTimeout(r, 10));
618+
}
609619
// Refresh was bypassed: no token-endpoint POST; the fresh authorize
610620
// request carries the union scope.
611621
expect(as.tokenCalls).toHaveLength(0);
@@ -2208,7 +2218,7 @@ verifies(
22082218
const transport = new StreamableHTTPClientTransport(new URL(MCP_URL), { authProvider: provider, fetch: alwaysUnauthorizedFetch });
22092219

22102220
try {
2211-
await expect(client.connect(transport)).rejects.toThrow(/Server returned 401 after re-authentication/);
2221+
await expect(client.connect(transport)).rejects.toThrow(UnauthorizedError);
22122222

22132223
// onUnauthorized ran once and the transport retried exactly once before giving up.
22142224
expect(unauthorizedCalls).toBe(1);

0 commit comments

Comments
 (0)