/**
* mysql-mcp - OAuth Error Classes Unit Tests
*
* Tests for all custom OAuth error classes.
*/
import { describe, it, expect } from "vitest";
import {
OAuthError,
TokenMissingError,
InvalidTokenError,
TokenExpiredError,
InvalidSignatureError,
InsufficientScopeError,
AuthServerDiscoveryError,
JwksFetchError,
ClientRegistrationError,
} from "../errors.js";
describe("OAuth Error Classes", () => {
describe("OAuthError", () => {
it("should create error with correct properties", () => {
const error = new OAuthError("Test error", "TEST_CODE", 400);
expect(error.message).toBe("Test error");
expect(error.code).toBe("TEST_CODE");
expect(error.httpStatus).toBe(400);
expect(error.name).toBe("OAuthError");
expect(error).toBeInstanceOf(Error);
expect(error).toBeInstanceOf(OAuthError);
});
});
describe("TokenMissingError", () => {
it("should create error with default message", () => {
const error = new TokenMissingError();
expect(error.message).toBe("No bearer token provided");
expect(error.code).toBe("TOKEN_MISSING");
expect(error.httpStatus).toBe(401);
expect(error.name).toBe("TokenMissingError");
});
it("should be instanceof OAuthError", () => {
const error = new TokenMissingError();
expect(error).toBeInstanceOf(OAuthError);
});
});
describe("InvalidTokenError", () => {
it("should create error with default message", () => {
const error = new InvalidTokenError();
expect(error.message).toBe("Invalid access token");
expect(error.code).toBe("INVALID_TOKEN");
expect(error.httpStatus).toBe(401);
expect(error.name).toBe("InvalidTokenError");
});
it("should accept custom message", () => {
const error = new InvalidTokenError("Token format invalid");
expect(error.message).toBe("Token format invalid");
});
});
describe("TokenExpiredError", () => {
it("should create error with default message", () => {
const error = new TokenExpiredError();
expect(error.message).toBe("Access token has expired");
expect(error.code).toBe("TOKEN_EXPIRED");
expect(error.httpStatus).toBe(401);
expect(error.name).toBe("TokenExpiredError");
});
it("should accept custom message", () => {
const error = new TokenExpiredError("Token expired 5 minutes ago");
expect(error.message).toBe("Token expired 5 minutes ago");
});
it("should be instanceof OAuthError", () => {
const error = new TokenExpiredError();
expect(error).toBeInstanceOf(OAuthError);
});
});
describe("InvalidSignatureError", () => {
it("should create error with default message", () => {
const error = new InvalidSignatureError();
expect(error.message).toBe("Invalid token signature");
expect(error.code).toBe("INVALID_SIGNATURE");
expect(error.httpStatus).toBe(401);
expect(error.name).toBe("InvalidSignatureError");
});
it("should accept custom message", () => {
const error = new InvalidSignatureError("Signature verification failed");
expect(error.message).toBe("Signature verification failed");
});
it("should be instanceof OAuthError", () => {
const error = new InvalidSignatureError();
expect(error).toBeInstanceOf(OAuthError);
});
});
describe("InsufficientScopeError", () => {
it("should create error with required scopes", () => {
const error = new InsufficientScopeError(["read", "write"]);
expect(error.message).toBe("Insufficient scope. Required: read, write");
expect(error.code).toBe("INSUFFICIENT_SCOPE");
expect(error.httpStatus).toBe(403);
expect(error.name).toBe("InsufficientScopeError");
expect(error.requiredScopes).toEqual(["read", "write"]);
});
it("should accept custom message", () => {
const error = new InsufficientScopeError(
["admin"],
"Admin access required",
);
expect(error.message).toBe("Admin access required");
expect(error.requiredScopes).toEqual(["admin"]);
});
});
describe("AuthServerDiscoveryError", () => {
it("should create error with default message", () => {
const error = new AuthServerDiscoveryError();
expect(error.message).toBe(
"Failed to discover authorization server metadata",
);
expect(error.code).toBe("DISCOVERY_FAILED");
expect(error.httpStatus).toBe(500);
expect(error.name).toBe("AuthServerDiscoveryError");
});
it("should accept custom message", () => {
const error = new AuthServerDiscoveryError("Server unreachable");
expect(error.message).toBe("Server unreachable");
});
});
describe("JwksFetchError", () => {
it("should create error with default message", () => {
const error = new JwksFetchError();
expect(error.message).toBe("Failed to fetch JWKS");
expect(error.code).toBe("JWKS_FETCH_FAILED");
expect(error.httpStatus).toBe(500);
expect(error.name).toBe("JwksFetchError");
});
it("should accept custom message", () => {
const error = new JwksFetchError("JWKS endpoint returned 404");
expect(error.message).toBe("JWKS endpoint returned 404");
});
it("should be instanceof OAuthError", () => {
const error = new JwksFetchError();
expect(error).toBeInstanceOf(OAuthError);
});
});
describe("ClientRegistrationError", () => {
it("should create error with default message", () => {
const error = new ClientRegistrationError();
expect(error.message).toBe("Client registration failed");
expect(error.code).toBe("REGISTRATION_FAILED");
expect(error.httpStatus).toBe(400);
expect(error.name).toBe("ClientRegistrationError");
});
it("should accept custom message", () => {
const error = new ClientRegistrationError("Invalid redirect URI");
expect(error.message).toBe("Invalid redirect URI");
});
it("should be instanceof OAuthError", () => {
const error = new ClientRegistrationError();
expect(error).toBeInstanceOf(OAuthError);
});
});
});