- Removed apiKey from SiteRow type and related forms in Sites component. - Updated site saving logic to handle site creation without apiKey. - Adjusted tests to ensure apiKey is not included in site editor state. - Refactored Tokens component to support embedded mode and redirect logic. - Added migration tests for site apiKey to account migration service. - Implemented siteApiKeyMigrationService to handle migration of apiKey to account tokens. - Enhanced tests for segmented connections in Accounts and redirect logic for Tokens.
132 lines
3.8 KiB
TypeScript
132 lines
3.8 KiB
TypeScript
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
|
|
|
const { fetchMock, fetchJsonWithShieldCookieRetryMock } = vi.hoisted(() => ({
|
|
fetchMock: vi.fn(),
|
|
fetchJsonWithShieldCookieRetryMock: vi.fn(),
|
|
}));
|
|
|
|
vi.mock('undici', () => ({
|
|
fetch: (...args: unknown[]) => fetchMock(...args),
|
|
}));
|
|
|
|
vi.mock('./platforms/newApiShield.js', () => ({
|
|
buildNewApiCookieCandidates: () => [],
|
|
fetchJsonWithShieldCookieRetry: (...args: unknown[]) => fetchJsonWithShieldCookieRetryMock(...args),
|
|
}));
|
|
|
|
vi.mock('./siteProxy.js', () => ({
|
|
withExplicitProxyRequestInit: (_proxyUrl: string | null | undefined, init: RequestInit) => init,
|
|
}));
|
|
|
|
import {
|
|
resolveProxyUsageWithSelfLogFallback,
|
|
shouldLookupSelfLog,
|
|
} from './proxyUsageFallbackService.js';
|
|
|
|
describe('proxyUsageFallbackService sub2api', () => {
|
|
beforeEach(() => {
|
|
fetchMock.mockReset();
|
|
fetchJsonWithShieldCookieRetryMock.mockReset();
|
|
fetchJsonWithShieldCookieRetryMock.mockResolvedValue({ data: null });
|
|
});
|
|
|
|
it('always enables usage lookup for sub2api to recover exact billing cost', () => {
|
|
expect(shouldLookupSelfLog('sub2api', {
|
|
promptTokens: 70354,
|
|
completionTokens: 1148,
|
|
totalTokens: 71502,
|
|
})).toBe(true);
|
|
});
|
|
|
|
it('recovers exact cost from sub2api /api/v1/usage and matches by api key value', async () => {
|
|
fetchMock.mockResolvedValue(new Response(JSON.stringify({
|
|
code: 0,
|
|
message: 'success',
|
|
data: {
|
|
items: [
|
|
{
|
|
id: 1001,
|
|
model: 'gpt-5.4',
|
|
input_tokens: 512,
|
|
output_tokens: 32,
|
|
cache_creation_tokens: 0,
|
|
cache_read_tokens: 0,
|
|
total_cost: 0.001088,
|
|
actual_cost: 0.001088,
|
|
duration_ms: 23000,
|
|
created_at: '2026-03-07T06:12:30.000Z',
|
|
api_key: {
|
|
id: 91,
|
|
key: 'sk-wrong',
|
|
name: 'wrong-key',
|
|
},
|
|
},
|
|
{
|
|
id: 1002,
|
|
model: 'gpt-5.4',
|
|
input_tokens: 70354,
|
|
output_tokens: 1148,
|
|
cache_creation_tokens: 0,
|
|
cache_read_tokens: 0,
|
|
total_cost: 0.143004,
|
|
actual_cost: 0.143004,
|
|
duration_ms: 23000,
|
|
created_at: '2026-03-07T06:12:29.000Z',
|
|
api_key: {
|
|
id: 92,
|
|
key: 'sk-route',
|
|
name: 'upstream-key-name',
|
|
},
|
|
},
|
|
],
|
|
total: 2,
|
|
page: 1,
|
|
page_size: 20,
|
|
pages: 1,
|
|
},
|
|
}), {
|
|
status: 200,
|
|
headers: { 'content-type': 'application/json' },
|
|
}));
|
|
|
|
const result = await resolveProxyUsageWithSelfLogFallback({
|
|
site: {
|
|
url: 'https://sub2api.example.com',
|
|
platform: 'sub2api',
|
|
},
|
|
account: {
|
|
accessToken: 'jwt-access-token',
|
|
apiToken: 'sk-account-level',
|
|
},
|
|
tokenValue: 'sk-route',
|
|
tokenName: 'local-token-name',
|
|
modelName: 'gpt-5.4',
|
|
requestStartedAtMs: Date.parse('2026-03-07T06:12:07.000Z'),
|
|
requestEndedAtMs: Date.parse('2026-03-07T06:12:30.000Z'),
|
|
localLatencyMs: 23000,
|
|
usage: {
|
|
promptTokens: 0,
|
|
completionTokens: 0,
|
|
totalTokens: 0,
|
|
},
|
|
});
|
|
|
|
expect(fetchMock).toHaveBeenCalledTimes(1);
|
|
expect(String(fetchMock.mock.calls[0]?.[0] || '')).toContain('/api/v1/usage?');
|
|
expect(String(fetchMock.mock.calls[0]?.[0] || '')).toContain('model=gpt-5.4');
|
|
expect(fetchMock.mock.calls[0]?.[1]).toMatchObject({
|
|
method: 'GET',
|
|
headers: {
|
|
Authorization: 'Bearer jwt-access-token',
|
|
},
|
|
});
|
|
expect(result).toMatchObject({
|
|
promptTokens: 70354,
|
|
completionTokens: 1148,
|
|
totalTokens: 71502,
|
|
recoveredFromSelfLog: true,
|
|
estimatedCostFromQuota: 0.143004,
|
|
});
|
|
});
|
|
});
|