Files
ccs/tests/unit/cliproxy/managed-model-prefixes.test.ts
T

201 lines
6.9 KiB
TypeScript

import { afterEach, describe, expect, it, mock } from 'bun:test';
import { ensureManagedModelPrefixes } from '../../../src/cliproxy/managed-model-prefixes';
const originalFetch = global.fetch;
interface MockAuthFileRecord {
account_type?: string;
name: string;
provider?: string;
type?: string;
}
interface DownloadResponse {
body: string;
status?: number;
}
function jsonResponse(body: unknown, status = 200): Response {
return new Response(JSON.stringify(body), {
status,
headers: { 'Content-Type': 'application/json' },
});
}
function textResponse(body: string, status = 200): Response {
return new Response(body, {
status,
headers: { 'Content-Type': 'application/json' },
});
}
function installFetchMock(options: {
files: MockAuthFileRecord[];
downloads?: Record<string, DownloadResponse | Error>;
patchStatuses?: Record<string, number>;
}) {
const requests: Array<{ url: string; method: string; body: string | undefined }> = [];
global.fetch = mock((input: string | URL | Request, init?: RequestInit) => {
const url =
typeof input === 'string' ? input : input instanceof URL ? input.toString() : input.url;
const method = init?.method ?? 'GET';
const body = typeof init?.body === 'string' ? init.body : undefined;
requests.push({ url, method, body });
if (url.endsWith('/v0/management/auth-files') && method === 'GET') {
return Promise.resolve(jsonResponse({ files: options.files }));
}
if (url.includes('/v0/management/auth-files/download') && method === 'GET') {
const name = new URL(url).searchParams.get('name');
if (!name) {
return Promise.reject(new Error(`Missing auth file name for ${url}`));
}
const response = options.downloads?.[name];
if (response instanceof Error) {
return Promise.reject(response);
}
if (!response) {
return Promise.resolve(textResponse('{}', 404));
}
return Promise.resolve(textResponse(response.body, response.status ?? 200));
}
if (url.endsWith('/v0/management/auth-files/fields') && method === 'PATCH') {
const payload = JSON.parse(body ?? '{}') as { name?: string };
const status = (payload.name && options.patchStatuses?.[payload.name]) ?? 200;
return Promise.resolve(jsonResponse({ ok: status < 400 }, status));
}
return Promise.reject(new Error(`Unexpected fetch ${method} ${url}`));
}) as typeof fetch;
return requests;
}
afterEach(() => {
global.fetch = originalFetch;
});
describe('ensureManagedModelPrefixes', () => {
it('patches missing managed prefixes for matching oauth providers', async () => {
const requests = installFetchMock({
files: [
{ account_type: 'oauth', name: 'gemini-main', provider: 'gemini' },
{ account_type: 'oauth', name: 'agy-main', provider: 'antigravity' },
{ account_type: 'apikey', name: 'gemini-key', provider: 'gemini' },
],
downloads: {
'gemini-main': { body: JSON.stringify({ prefix: null, provider: 'gemini' }) },
'agy-main': { body: JSON.stringify({ prefix: null, provider: 'antigravity' }) },
},
});
const result = await ensureManagedModelPrefixes(['gemini']);
expect(result).toEqual({ checked: 1, updated: 1 });
const patchRequest = requests.find(
(request) =>
request.url.endsWith('/v0/management/auth-files/fields') && request.method === 'PATCH'
);
expect(patchRequest?.body).toBe(JSON.stringify({ name: 'gemini-main', prefix: 'gcli' }));
const downloadedNames = requests
.filter((request) => request.url.includes('/v0/management/auth-files/download'))
.map((request) => new URL(request.url).searchParams.get('name'));
expect(downloadedNames).toEqual(['gemini-main']);
});
it('returns immediately when called for providers without managed prefixes', async () => {
const fetchMock = mock(() => Promise.reject(new Error('should not fetch')));
global.fetch = fetchMock as typeof fetch;
const result = await ensureManagedModelPrefixes(['codex']);
expect(result).toEqual({ checked: 0, updated: 0 });
expect(fetchMock).not.toHaveBeenCalled();
});
it('skips files that already have the managed prefix or a different custom prefix', async () => {
const requests = installFetchMock({
files: [
{ account_type: 'oauth', name: 'gemini-managed', provider: 'gemini' },
{ account_type: 'oauth', name: 'gemini-custom', provider: 'gemini' },
],
downloads: {
'gemini-managed': { body: JSON.stringify({ prefix: 'gcli', provider: 'gemini' }) },
'gemini-custom': { body: JSON.stringify({ prefix: 'team-a', provider: 'gemini' }) },
},
});
const result = await ensureManagedModelPrefixes(['gemini']);
expect(result).toEqual({ checked: 2, updated: 0 });
expect(
requests.some(
(request) =>
request.url.endsWith('/v0/management/auth-files/fields') && request.method === 'PATCH'
)
).toBe(false);
});
it('skips patching when the downloaded auth file belongs to a different provider', async () => {
const requests = installFetchMock({
files: [{ account_type: 'oauth', name: 'gemini-shadowed', provider: 'gemini' }],
downloads: {
'gemini-shadowed': {
body: JSON.stringify({ prefix: null, provider: 'antigravity' }),
},
},
});
const result = await ensureManagedModelPrefixes(['gemini']);
expect(result).toEqual({ checked: 1, updated: 0 });
expect(
requests.some(
(request) =>
request.url.endsWith('/v0/management/auth-files/fields') && request.method === 'PATCH'
)
).toBe(false);
});
it('swallows read and patch failures so later files can still be repaired', async () => {
const requests = installFetchMock({
files: [
{ account_type: 'oauth', name: 'gemini-unreadable', provider: 'gemini' },
{ account_type: 'oauth', name: 'gemini-patch-fails', provider: 'gemini' },
{ account_type: 'oauth', name: 'gemini-success', provider: 'gemini' },
],
downloads: {
'gemini-unreadable': new Error('network down'),
'gemini-patch-fails': { body: JSON.stringify({ prefix: null, provider: 'gemini' }) },
'gemini-success': { body: JSON.stringify({ prefix: null, provider: 'gemini' }) },
},
patchStatuses: {
'gemini-patch-fails': 500,
},
});
const result = await ensureManagedModelPrefixes(['gemini']);
expect(result).toEqual({ checked: 3, updated: 1 });
const patchPayloads = requests
.filter(
(request) =>
request.url.endsWith('/v0/management/auth-files/fields') && request.method === 'PATCH'
)
.map((request) => request.body);
expect(patchPayloads).toEqual([
JSON.stringify({ name: 'gemini-patch-fails', prefix: 'gcli' }),
JSON.stringify({ name: 'gemini-success', prefix: 'gcli' }),
]);
});
});