Migrate to vitest from jest (#1074)
Co-authored-by: Felix Weinberger <3823880+felixweinberger@users.noreply.github.com> Co-authored-by: Felix Weinberger <fweinberger@anthropic.com>
This commit is contained in:
parent
324d471158
commit
98df118a4c
1 changed files with 1713 additions and 3434 deletions
|
|
@ -5,6 +5,7 @@ import { SSEClientTransport } from './sse.js';
|
|||
import { OAuthClientProvider, UnauthorizedError } from './auth.js';
|
||||
import { OAuthTokens } from '../shared/auth.js';
|
||||
import { InvalidClientError, InvalidGrantError, UnauthorizedClientError } from '../server/auth/errors.js';
|
||||
import { Mock, Mocked, MockedFunction, MockInstance } from 'vitest';
|
||||
|
||||
describe('SSEClientTransport', () => {
|
||||
let resourceServer: Server;
|
||||
|
|
@ -15,7 +16,7 @@ describe('SSEClientTransport', () => {
|
|||
let lastServerRequest: IncomingMessage;
|
||||
let sendServerMessage: ((message: string) => void) | null = null;
|
||||
|
||||
beforeEach(done => {
|
||||
beforeEach(async () => {
|
||||
// Reset state
|
||||
lastServerRequest = null as unknown as IncomingMessage;
|
||||
sendServerMessage = null;
|
||||
|
|
@ -74,13 +75,15 @@ describe('SSEClientTransport', () => {
|
|||
});
|
||||
|
||||
// Start server on random port
|
||||
resourceServer.listen(0, '127.0.0.1', () => {
|
||||
const addr = resourceServer.address() as AddressInfo;
|
||||
resourceBaseUrl = new URL(`http://127.0.0.1:${addr.port}`);
|
||||
done();
|
||||
await new Promise<void>(resolve => {
|
||||
resourceServer.listen(0, '127.0.0.1', () => {
|
||||
const addr = resourceServer.address() as AddressInfo;
|
||||
resourceBaseUrl = new URL(`http://127.0.0.1:${addr.port}`);
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
|
||||
jest.spyOn(console, 'error').mockImplementation(() => {});
|
||||
vi.spyOn(console, 'error').mockImplementation(() => {});
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
|
|
@ -88,7 +91,7 @@ describe('SSEClientTransport', () => {
|
|||
await resourceServer.close();
|
||||
await authServer.close();
|
||||
|
||||
jest.clearAllMocks();
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
|
||||
describe('connection handling', () => {
|
||||
|
|
@ -262,7 +265,7 @@ describe('SSEClientTransport', () => {
|
|||
it('uses custom fetch implementation from options', async () => {
|
||||
const authToken = 'Bearer custom-token';
|
||||
|
||||
const fetchWithAuth = jest.fn((url: string | URL, init?: RequestInit) => {
|
||||
const fetchWithAuth = vi.fn((url: string | URL, init?: RequestInit) => {
|
||||
const headers = new Headers(init?.headers);
|
||||
headers.set('Authorization', authToken);
|
||||
return fetch(url.toString(), { ...init, headers });
|
||||
|
|
@ -310,7 +313,7 @@ describe('SSEClientTransport', () => {
|
|||
|
||||
try {
|
||||
// Mock fetch for the message sending test
|
||||
global.fetch = jest.fn().mockResolvedValue({
|
||||
global.fetch = vi.fn().mockResolvedValue({
|
||||
ok: true
|
||||
});
|
||||
|
||||
|
|
@ -331,7 +334,7 @@ describe('SSEClientTransport', () => {
|
|||
})
|
||||
);
|
||||
|
||||
const calledHeaders = (global.fetch as jest.Mock).mock.calls[0][1].headers;
|
||||
const calledHeaders = (global.fetch as Mock).mock.calls[0][1].headers;
|
||||
expect(calledHeaders.get('Authorization')).toBe(customHeaders.Authorization);
|
||||
expect(calledHeaders.get('X-Custom-Header')).toBe(customHeaders['X-Custom-Header']);
|
||||
expect(calledHeaders.get('content-type')).toBe('application/json');
|
||||
|
|
@ -345,7 +348,7 @@ describe('SSEClientTransport', () => {
|
|||
describe('auth handling', () => {
|
||||
const authServerMetadataUrls = ['/.well-known/oauth-authorization-server', '/.well-known/openid-configuration'];
|
||||
|
||||
let mockAuthProvider: jest.Mocked<OAuthClientProvider>;
|
||||
let mockAuthProvider: Mocked<OAuthClientProvider>;
|
||||
|
||||
beforeEach(() => {
|
||||
mockAuthProvider = {
|
||||
|
|
@ -355,13 +358,13 @@ describe('SSEClientTransport', () => {
|
|||
get clientMetadata() {
|
||||
return { redirect_uris: ['http://localhost/callback'] };
|
||||
},
|
||||
clientInformation: jest.fn(() => ({ client_id: 'test-client-id', client_secret: 'test-client-secret' })),
|
||||
tokens: jest.fn(),
|
||||
saveTokens: jest.fn(),
|
||||
redirectToAuthorization: jest.fn(),
|
||||
saveCodeVerifier: jest.fn(),
|
||||
codeVerifier: jest.fn(),
|
||||
invalidateCredentials: jest.fn()
|
||||
clientInformation: vi.fn(() => ({ client_id: 'test-client-id', client_secret: 'test-client-secret' })),
|
||||
tokens: vi.fn(),
|
||||
saveTokens: vi.fn(),
|
||||
redirectToAuthorization: vi.fn(),
|
||||
saveCodeVerifier: vi.fn(),
|
||||
codeVerifier: vi.fn(),
|
||||
invalidateCredentials: vi.fn()
|
||||
};
|
||||
});
|
||||
|
||||
|
|
@ -1122,19 +1125,10 @@ describe('SSEClientTransport', () => {
|
|||
});
|
||||
|
||||
describe('custom fetch in auth code paths', () => {
|
||||
let customFetch: jest.MockedFunction<typeof fetch>;
|
||||
let globalFetchSpy: jest.SpyInstance;
|
||||
let mockAuthProvider: jest.Mocked<OAuthClientProvider>;
|
||||
let resourceServerHandler: jest.Mock<
|
||||
void,
|
||||
[
|
||||
IncomingMessage,
|
||||
ServerResponse<IncomingMessage> & {
|
||||
req: IncomingMessage;
|
||||
}
|
||||
],
|
||||
void
|
||||
>;
|
||||
let customFetch: MockedFunction<typeof fetch>;
|
||||
let globalFetchSpy: MockInstance;
|
||||
let mockAuthProvider: Mocked<OAuthClientProvider>;
|
||||
let resourceServerHandler: Mock;
|
||||
|
||||
/**
|
||||
* Helper function to create a mock auth provider with configurable behavior
|
||||
|
|
@ -1147,7 +1141,7 @@ describe('SSEClientTransport', () => {
|
|||
clientRegistered?: boolean;
|
||||
authorizationCode?: string;
|
||||
} = {}
|
||||
): jest.Mocked<OAuthClientProvider> => {
|
||||
): Mocked<OAuthClientProvider> => {
|
||||
const tokens = config.hasTokens
|
||||
? {
|
||||
access_token: config.tokensExpired ? 'expired-token' : 'valid-token',
|
||||
|
|
@ -1173,13 +1167,13 @@ describe('SSEClientTransport', () => {
|
|||
client_name: 'Test Client'
|
||||
};
|
||||
},
|
||||
clientInformation: jest.fn().mockResolvedValue(clientInfo),
|
||||
tokens: jest.fn().mockResolvedValue(tokens),
|
||||
saveTokens: jest.fn(),
|
||||
redirectToAuthorization: jest.fn(),
|
||||
saveCodeVerifier: jest.fn(),
|
||||
codeVerifier: jest.fn().mockResolvedValue('test-verifier'),
|
||||
invalidateCredentials: jest.fn()
|
||||
clientInformation: vi.fn().mockResolvedValue(clientInfo),
|
||||
tokens: vi.fn().mockResolvedValue(tokens),
|
||||
saveTokens: vi.fn(),
|
||||
redirectToAuthorization: vi.fn(),
|
||||
saveCodeVerifier: vi.fn(),
|
||||
codeVerifier: vi.fn().mockResolvedValue('test-verifier'),
|
||||
invalidateCredentials: vi.fn()
|
||||
};
|
||||
};
|
||||
|
||||
|
|
@ -1279,12 +1273,12 @@ describe('SSEClientTransport', () => {
|
|||
const originalFetch = fetch;
|
||||
|
||||
// Create custom fetch spy that delegates to real fetch
|
||||
customFetch = jest.fn((url, init) => {
|
||||
customFetch = vi.fn((url, init) => {
|
||||
return originalFetch(url.toString(), init);
|
||||
});
|
||||
|
||||
// Spy on global fetch to detect unauthorized usage
|
||||
globalFetchSpy = jest.spyOn(global, 'fetch');
|
||||
globalFetchSpy = vi.spyOn(global, 'fetch');
|
||||
|
||||
// Create mock auth provider with default configuration
|
||||
mockAuthProvider = createMockAuthProvider({
|
||||
|
|
@ -1296,7 +1290,7 @@ describe('SSEClientTransport', () => {
|
|||
await createCustomFetchMockAuthServer();
|
||||
|
||||
// Set up resource server
|
||||
resourceServerHandler = jest.fn(
|
||||
resourceServerHandler = vi.fn(
|
||||
(
|
||||
_req: IncomingMessage,
|
||||
res: ServerResponse<IncomingMessage> & {
|
||||
|
|
@ -1315,7 +1309,7 @@ describe('SSEClientTransport', () => {
|
|||
|
||||
it('uses custom fetch during auth flow on SSE connection 401 - no global fetch fallback', async () => {
|
||||
// Set up resource server that returns 401 on SSE connection and provides OAuth metadata
|
||||
resourceServerHandler.mockImplementation((req, res) => {
|
||||
resourceServerHandler.mockImplementation((req: IncomingMessage, res: ServerResponse) => {
|
||||
if (req.url === '/') {
|
||||
// Return 401 to trigger auth flow
|
||||
res.writeHead(401, {
|
||||
|
|
@ -1359,7 +1353,7 @@ describe('SSEClientTransport', () => {
|
|||
|
||||
it('uses custom fetch during auth flow on POST request 401 - no global fetch fallback', async () => {
|
||||
// Set up resource server that accepts SSE connection but returns 401 on POST
|
||||
resourceServerHandler.mockImplementation((req, res) => {
|
||||
resourceServerHandler.mockImplementation((req: IncomingMessage, res: ServerResponse) => {
|
||||
switch (req.method) {
|
||||
case 'GET':
|
||||
if (req.url === '/') {
|
||||
|
|
|
|||
Loading…
Reference in a new issue