mirror of
https://github.com/router-for-me/Cli-Proxy-API-Management-Center.git
synced 2026-10-16 14:57:05 +08:00
- Updated test cases in `providerWeightTransformers.test.ts` to reflect changes in API key structure from 'api-key-entries' to 'keys'. - Introduced new tests in `providerWorkbenchUi.test.ts` to verify the editing surface of provider workbench. - Modified `sponsorCustomEndpoint.test.ts` to adapt to the new API key structure. - Adjusted `visualConfigAntigravitySensitiveWords.test.ts` and `visualConfigConcurrency.test.ts` to accommodate new YAML structure for sensitive words and concurrency settings. - Enhanced `visualConfigDefaults.test.ts` to ensure proper handling of boolean defaults and YAML structure. - Updated `visualConfigDevinSensitiveWords.test.ts` to reflect changes in the YAML structure for sensitive words. - Refined `visualConfigDisableImageGeneration.test.ts` to align with new multimedia settings. - Added comprehensive tests in `visualConfigV8.test.ts` to validate the v8 visual config contract and ensure scalar read/write path parity. - Improved validation tests in `visualConfigValidation.test.ts` to handle new routing and requests structure. - Cleaned up `xaiApiKeyProvider.test.ts` by removing unnecessary API client mocks and focusing on normalization of the xAI API key contract.
108 lines
3.8 KiB
TypeScript
108 lines
3.8 KiB
TypeScript
import { describe, expect, spyOn, test } from 'bun:test';
|
|
import { apiClient } from '@/services/api/client';
|
|
import { oauthApi, type BuiltInOAuthProvider } from '@/services/api/oauth';
|
|
|
|
describe('Devin Management OAuth v8 contract', () => {
|
|
test('starts a built-in Devin flow with web UI mode', async () => {
|
|
const provider: BuiltInOAuthProvider = 'devin';
|
|
const response = {
|
|
status: 'ok',
|
|
url: 'https://app.devin.ai/auth/cli/continue',
|
|
state: 'test-state',
|
|
};
|
|
const get = spyOn(apiClient, 'get').mockResolvedValue(response);
|
|
try {
|
|
expect(await oauthApi.startAuth(provider)).toEqual(response);
|
|
expect(get).toHaveBeenCalledWith('/oauth/auth-url', {
|
|
params: { provider: 'devin', is_webui: true },
|
|
});
|
|
} finally {
|
|
get.mockRestore();
|
|
}
|
|
});
|
|
|
|
test('submits the complete remote callback without rewriting its port or TLS mode', async () => {
|
|
const post = spyOn(apiClient, 'post').mockResolvedValue({ status: 'ok' });
|
|
const redirectUrl = 'https://127.0.0.1:9443/devin/callback?code=fixture-code&state=test-state';
|
|
try {
|
|
await oauthApi.submitCallback('devin', redirectUrl);
|
|
expect(post).toHaveBeenCalledWith(
|
|
'/oauth/callback',
|
|
{ provider: 'devin', redirect_url: redirectUrl },
|
|
undefined
|
|
);
|
|
} finally {
|
|
post.mockRestore();
|
|
}
|
|
});
|
|
|
|
test('polls using only the original attempt state', async () => {
|
|
const get = spyOn(apiClient, 'get').mockResolvedValue({ status: 'wait' });
|
|
try {
|
|
expect(await oauthApi.getAuthStatus('test-state')).toEqual({ status: 'wait' });
|
|
expect(get).toHaveBeenCalledWith('/oauth/status', { params: { state: 'test-state' } });
|
|
} finally {
|
|
get.mockRestore();
|
|
}
|
|
});
|
|
|
|
for (const cancelled of [true, false]) {
|
|
test(`preserves the server cancellation result (${cancelled})`, async () => {
|
|
const remove = spyOn(apiClient, 'delete').mockResolvedValue({ status: 'ok', cancelled });
|
|
try {
|
|
expect(await oauthApi.cancelSession('test-state')).toEqual({ status: 'ok', cancelled });
|
|
expect(remove).toHaveBeenCalledWith('/oauth/session', { params: { state: 'test-state' } });
|
|
} finally {
|
|
remove.mockRestore();
|
|
}
|
|
});
|
|
}
|
|
|
|
test('forwards attempt abort signals to every OAuth request', async () => {
|
|
const signal = new AbortController().signal;
|
|
const get = spyOn(apiClient, 'get').mockResolvedValue({});
|
|
const post = spyOn(apiClient, 'post').mockResolvedValue({});
|
|
const remove = spyOn(apiClient, 'delete').mockResolvedValue({});
|
|
try {
|
|
await oauthApi.startAuth('devin', signal);
|
|
expect(get).toHaveBeenLastCalledWith('/oauth/auth-url', {
|
|
params: { provider: 'devin', is_webui: true },
|
|
signal,
|
|
});
|
|
await oauthApi.getAuthStatus('test-state', signal);
|
|
expect(get).toHaveBeenLastCalledWith('/oauth/status', {
|
|
params: { state: 'test-state' },
|
|
signal,
|
|
});
|
|
await oauthApi.submitCallback('devin', 'fixture-callback', signal);
|
|
expect(post).toHaveBeenCalledWith(
|
|
'/oauth/callback',
|
|
{
|
|
provider: 'devin',
|
|
redirect_url: 'fixture-callback',
|
|
},
|
|
{ signal }
|
|
);
|
|
await oauthApi.cancelSession('test-state', signal);
|
|
expect(remove).toHaveBeenCalledWith('/oauth/session', {
|
|
params: { state: 'test-state' },
|
|
signal,
|
|
});
|
|
} finally {
|
|
get.mockRestore();
|
|
post.mockRestore();
|
|
remove.mockRestore();
|
|
}
|
|
});
|
|
|
|
test('propagates cancellation failures instead of claiming success', async () => {
|
|
const error = new Error('connection lost');
|
|
const remove = spyOn(apiClient, 'delete').mockRejectedValue(error);
|
|
try {
|
|
await expect(oauthApi.cancelSession('test-state')).rejects.toBe(error);
|
|
} finally {
|
|
remove.mockRestore();
|
|
}
|
|
});
|
|
});
|