/**
 * @license
 * Copyright 2025 Google LLC
 * SPDX-License-Identifier: Apache-2.0
 */
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
import { OAuthUtils } from './oauth-utils.js';
// Mock fetch globally
const mockFetch = vi.fn();
global.fetch = mockFetch;
describe('OAuthUtils', () => {
    beforeEach(() => {
        vi.clearAllMocks();
        vi.spyOn(console, 'debug').mockImplementation(() => { });
        vi.spyOn(console, 'error').mockImplementation(() => { });
        vi.spyOn(console, 'log').mockImplementation(() => { });
    });
    afterEach(() => {
        vi.restoreAllMocks();
    });
    describe('buildWellKnownUrls', () => {
        it('should build standard root-based URLs by default', () => {
            const urls = OAuthUtils.buildWellKnownUrls('https://example.com/mcp');
            expect(urls.protectedResource).toBe('https://example.com/.well-known/oauth-protected-resource');
            expect(urls.authorizationServer).toBe('https://example.com/.well-known/oauth-authorization-server');
        });
        it('should build path-based URLs when includePathSuffix is true', () => {
            const urls = OAuthUtils.buildWellKnownUrls('https://example.com/mcp', true);
            expect(urls.protectedResource).toBe('https://example.com/.well-known/oauth-protected-resource/mcp');
            expect(urls.authorizationServer).toBe('https://example.com/.well-known/oauth-authorization-server/mcp');
        });
        it('should handle root path correctly', () => {
            const urls = OAuthUtils.buildWellKnownUrls('https://example.com', true);
            expect(urls.protectedResource).toBe('https://example.com/.well-known/oauth-protected-resource');
            expect(urls.authorizationServer).toBe('https://example.com/.well-known/oauth-authorization-server');
        });
        it('should handle trailing slash in path', () => {
            const urls = OAuthUtils.buildWellKnownUrls('https://example.com/mcp/', true);
            expect(urls.protectedResource).toBe('https://example.com/.well-known/oauth-protected-resource/mcp');
            expect(urls.authorizationServer).toBe('https://example.com/.well-known/oauth-authorization-server/mcp');
        });
    });
    describe('fetchProtectedResourceMetadata', () => {
        const mockResourceMetadata = {
            resource: 'https://api.example.com',
            authorization_servers: ['https://auth.example.com'],
            bearer_methods_supported: ['header'],
        };
        it('should fetch protected resource metadata successfully', async () => {
            mockFetch.mockResolvedValueOnce({
                ok: true,
                json: () => Promise.resolve(mockResourceMetadata),
            });
            const result = await OAuthUtils.fetchProtectedResourceMetadata('https://example.com/.well-known/oauth-protected-resource');
            expect(result).toEqual(mockResourceMetadata);
        });
        it('should return null when fetch fails', async () => {
            mockFetch.mockResolvedValueOnce({
                ok: false,
            });
            const result = await OAuthUtils.fetchProtectedResourceMetadata('https://example.com/.well-known/oauth-protected-resource');
            expect(result).toBeNull();
        });
    });
    describe('fetchAuthorizationServerMetadata', () => {
        const mockAuthServerMetadata = {
            issuer: 'https://auth.example.com',
            authorization_endpoint: 'https://auth.example.com/authorize',
            token_endpoint: 'https://auth.example.com/token',
            scopes_supported: ['read', 'write'],
        };
        it('should fetch authorization server metadata successfully', async () => {
            mockFetch.mockResolvedValueOnce({
                ok: true,
                json: () => Promise.resolve(mockAuthServerMetadata),
            });
            const result = await OAuthUtils.fetchAuthorizationServerMetadata('https://auth.example.com/.well-known/oauth-authorization-server');
            expect(result).toEqual(mockAuthServerMetadata);
        });
        it('should return null when fetch fails', async () => {
            mockFetch.mockResolvedValueOnce({
                ok: false,
            });
            const result = await OAuthUtils.fetchAuthorizationServerMetadata('https://auth.example.com/.well-known/oauth-authorization-server');
            expect(result).toBeNull();
        });
    });
    describe('discoverAuthorizationServerMetadata', () => {
        const mockAuthServerMetadata = {
            issuer: 'https://auth.example.com',
            authorization_endpoint: 'https://auth.example.com/authorize',
            token_endpoint: 'https://auth.example.com/token',
            scopes_supported: ['read', 'write'],
        };
        it('should handle URLs without path components correctly', async () => {
            mockFetch
                .mockResolvedValueOnce({
                ok: false,
            })
                .mockResolvedValueOnce({
                ok: true,
                json: () => Promise.resolve(mockAuthServerMetadata),
            });
            const result = await OAuthUtils.discoverAuthorizationServerMetadata('https://auth.example.com/');
            expect(result).toEqual(mockAuthServerMetadata);
            expect(mockFetch).nthCalledWith(1, 'https://auth.example.com/.well-known/oauth-authorization-server');
            expect(mockFetch).nthCalledWith(2, 'https://auth.example.com/.well-known/openid-configuration');
        });
        it('should handle URLs with path components correctly', async () => {
            mockFetch
                .mockResolvedValueOnce({
                ok: false,
            })
                .mockResolvedValueOnce({
                ok: false,
            })
                .mockResolvedValueOnce({
                ok: true,
                json: () => Promise.resolve(mockAuthServerMetadata),
            });
            const result = await OAuthUtils.discoverAuthorizationServerMetadata('https://auth.example.com/mcp');
            expect(result).toEqual(mockAuthServerMetadata);
            expect(mockFetch).nthCalledWith(1, 'https://auth.example.com/.well-known/oauth-authorization-server/mcp');
            expect(mockFetch).nthCalledWith(2, 'https://auth.example.com/.well-known/openid-configuration/mcp');
            expect(mockFetch).nthCalledWith(3, 'https://auth.example.com/mcp/.well-known/openid-configuration');
        });
    });
    describe('metadataToOAuthConfig', () => {
        it('should convert metadata to OAuth config', () => {
            const metadata = {
                issuer: 'https://auth.example.com',
                authorization_endpoint: 'https://auth.example.com/authorize',
                token_endpoint: 'https://auth.example.com/token',
                scopes_supported: ['read', 'write'],
            };
            const config = OAuthUtils.metadataToOAuthConfig(metadata);
            expect(config).toEqual({
                authorizationUrl: 'https://auth.example.com/authorize',
                tokenUrl: 'https://auth.example.com/token',
                scopes: ['read', 'write'],
            });
        });
        it('should handle empty scopes', () => {
            const metadata = {
                issuer: 'https://auth.example.com',
                authorization_endpoint: 'https://auth.example.com/authorize',
                token_endpoint: 'https://auth.example.com/token',
            };
            const config = OAuthUtils.metadataToOAuthConfig(metadata);
            expect(config.scopes).toEqual([]);
        });
    });
    describe('parseWWWAuthenticateHeader', () => {
        it('should parse resource metadata URI from WWW-Authenticate header', () => {
            const header = 'Bearer realm="example", resource_metadata="https://example.com/.well-known/oauth-protected-resource"';
            const result = OAuthUtils.parseWWWAuthenticateHeader(header);
            expect(result).toBe('https://example.com/.well-known/oauth-protected-resource');
        });
        it('should return null when no resource metadata URI is found', () => {
            const header = 'Bearer realm="example"';
            const result = OAuthUtils.parseWWWAuthenticateHeader(header);
            expect(result).toBeNull();
        });
    });
    describe('extractBaseUrl', () => {
        it('should extract base URL from MCP server URL', () => {
            const result = OAuthUtils.extractBaseUrl('https://example.com/mcp/v1');
            expect(result).toBe('https://example.com');
        });
        it('should handle URLs with ports', () => {
            const result = OAuthUtils.extractBaseUrl('https://example.com:8080/mcp/v1');
            expect(result).toBe('https://example.com:8080');
        });
    });
    describe('isSSEEndpoint', () => {
        it('should return true for SSE endpoints', () => {
            expect(OAuthUtils.isSSEEndpoint('https://example.com/sse')).toBe(true);
            expect(OAuthUtils.isSSEEndpoint('https://example.com/api/v1/sse')).toBe(true);
        });
        it('should return true for non-MCP endpoints', () => {
            expect(OAuthUtils.isSSEEndpoint('https://example.com/api')).toBe(true);
        });
        it('should return false for MCP endpoints', () => {
            expect(OAuthUtils.isSSEEndpoint('https://example.com/mcp')).toBe(false);
            expect(OAuthUtils.isSSEEndpoint('https://example.com/api/mcp/v1')).toBe(false);
        });
    });
    describe('buildResourceParameter', () => {
        it('should build resource parameter from endpoint URL', () => {
            const result = OAuthUtils.buildResourceParameter('https://example.com/oauth/token');
            expect(result).toBe('https://example.com');
        });
        it('should handle URLs with ports', () => {
            const result = OAuthUtils.buildResourceParameter('https://example.com:8080/oauth/token');
            expect(result).toBe('https://example.com:8080');
        });
    });
});
//# sourceMappingURL=oauth-utils.test.js.map