import { describe, it, expect } from "vitest"
/**
* Response Object Handling Tests
*
* These tests verify that our ESLint configuration allows Response objects
* to be thrown correctly, ensuring that OAuth auto-redirect functionality
* works properly. This is a regression test for our ESLint @typescript-eslint/only-throw-error
* configuration changes.
*/
describe("Response Object Handling", () => {
describe("ESLint Configuration Validation", () => {
it("should allow throwing Response objects without ESLint errors", () => {
// This test verifies that our ESLint configuration properly allows
// Response objects to be thrown, which is required for FastMCP OAuth flows
expect(() => {
// This would previously fail with @typescript-eslint/only-throw-error
// but should now work with our updated configuration
try {
// Simulate the authentication function throwing a Response
throw new Response(
JSON.stringify({
error: "unauthorized",
error_description: "Test authentication error",
}),
{
status: 401,
statusText: "Unauthorized",
headers: {
"Content-Type": "application/json",
"WWW-Authenticate": `Bearer realm="MCP", authorization_uri="http://localhost:3000/oauth/authorize"`,
},
},
)
} catch (error) {
// Verify the Response object was thrown correctly
expect(error).toBeInstanceOf(Response)
if (error instanceof Response) {
expect(error.status).toBe(401)
expect(error.statusText).toBe("Unauthorized")
expect(error.headers.get("Content-Type")).toBe("application/json")
expect(error.headers.get("WWW-Authenticate")).toContain('Bearer realm="MCP"')
expect(error.headers.get("WWW-Authenticate")).toContain("authorization_uri=")
}
}
}).not.toThrow()
})
it("should properly handle Response objects in authentication scenarios", async () => {
// Test various authentication Response scenarios that would occur in OAuth flows
const testCases = [
{
name: "OAuth unauthorized",
response: new Response(
JSON.stringify({
error: "unauthorized",
error_description: "Authorization required. Please authenticate via OAuth.",
}),
{
status: 401,
statusText: "Unauthorized",
headers: {
"Content-Type": "application/json",
"WWW-Authenticate": `Bearer realm="MCP", authorization_uri="http://localhost:3000/oauth/authorize"`,
},
},
),
},
{
name: "Invalid token",
response: new Response(
JSON.stringify({
error: "invalid_token",
error_description: "Invalid or expired token",
}),
{
status: 401,
statusText: "Unauthorized",
headers: {
"Content-Type": "application/json",
"WWW-Authenticate": `Bearer realm="MCP", error="invalid_token"`,
},
},
),
},
{
name: "Basic auth failure",
response: new Response(
JSON.stringify({
error: "unauthorized",
error_description: "Invalid username or password",
}),
{
status: 401,
statusText: "Unauthorized",
headers: {
"Content-Type": "application/json",
"WWW-Authenticate": `Basic realm="MCP"`,
},
},
),
},
]
for (const testCase of testCases) {
// Verify each Response object is properly formed
expect(testCase.response).toBeInstanceOf(Response)
expect(testCase.response.status).toBe(401)
expect(testCase.response.statusText).toBe("Unauthorized")
expect(testCase.response.headers.get("Content-Type")).toBe("application/json")
expect(testCase.response.headers.get("WWW-Authenticate")).toBeTruthy()
// Verify the response body can be read
const body = (await testCase.response.json()) as { error: string; error_description: string }
expect(body).toHaveProperty("error")
expect(body).toHaveProperty("error_description")
expect(typeof body.error).toBe("string")
expect(typeof body.error_description).toBe("string")
}
})
it("should create Response objects with proper headers for MCP Inspector compatibility", () => {
// Test that Response objects have the correct headers for MCP Inspector OAuth flows
const oauthResponse = new Response(
JSON.stringify({
error: "unauthorized",
error_description: "Authorization required. Please authenticate via OAuth.",
}),
{
status: 401,
statusText: "Unauthorized",
headers: {
"Content-Type": "application/json",
"WWW-Authenticate": `Bearer realm="MCP", authorization_uri="http://localhost:3000/oauth/authorize", resource="http://localhost:3000/.well-known/oauth-protected-resource"`,
},
},
)
// Verify all required headers for OAuth discovery are present
expect(oauthResponse.status).toBe(401)
expect(oauthResponse.headers.get("Content-Type")).toBe("application/json")
const wwwAuth = oauthResponse.headers.get("WWW-Authenticate")
expect(wwwAuth).toBeTruthy()
expect(wwwAuth).toContain("Bearer")
expect(wwwAuth).toContain('realm="MCP"')
expect(wwwAuth).toContain("authorization_uri=")
expect(wwwAuth).toContain("resource=")
// These headers are critical for MCP Inspector auto-redirect functionality
expect(wwwAuth).toContain("http://localhost:3000/oauth/authorize")
expect(wwwAuth).toContain(".well-known/oauth-protected-resource")
})
})
describe("OAuth Endpoint Response Format", () => {
it("should verify OAuth endpoints return proper Response format", () => {
// Simulate what the OAuth endpoints should return
// Authorization endpoint should return HTML form
const authResponse = new Response(
`<html><body><form method="post"><input name="username"><input name="password" type="password"><button>Login</button></form></body></html>`,
{
status: 200,
statusText: "OK",
headers: {
"Content-Type": "text/html",
},
},
)
expect(authResponse.status).toBe(200)
expect(authResponse.headers.get("Content-Type")).toBe("text/html")
// JWKS endpoint should return JSON
const jwksResponse = new Response(
JSON.stringify({
keys: [
{
kty: "RSA",
use: "sig",
kid: "test-key-id",
n: "test-modulus",
e: "AQAB",
},
],
}),
{
status: 200,
statusText: "OK",
headers: {
"Content-Type": "application/json",
},
},
)
expect(jwksResponse.status).toBe(200)
expect(jwksResponse.headers.get("Content-Type")).toBe("application/json")
})
})
describe("Error Boundary Testing", () => {
it("should handle Response object errors gracefully", () => {
// Test that throwing and catching Response objects works correctly
const testAuthenticationFlow = () => {
// Simulate FastMCP authentication function
const authHeader = null // No auth header provided
if (!authHeader) {
throw new Response(
JSON.stringify({
error: "unauthorized",
error_description: "Authorization required",
}),
{
status: 401,
statusText: "Unauthorized",
headers: {
"Content-Type": "application/json",
"WWW-Authenticate": `Bearer realm="MCP"`,
},
},
)
}
return { userId: "test", email: "test@example.com" }
}
// Verify the function throws the correct Response
expect(() => testAuthenticationFlow()).toThrow()
try {
testAuthenticationFlow()
} catch (error) {
expect(error).toBeInstanceOf(Response)
if (error instanceof Response) {
expect(error.status).toBe(401)
expect(error.headers.get("WWW-Authenticate")).toBeTruthy()
}
}
})
})
})