99 lines
3.2 KiB
TypeScript
99 lines
3.2 KiB
TypeScript
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
|
|
|
const {
|
|
hasProxyLogBillingDetailsColumnMock,
|
|
dbInsertMock,
|
|
dbInsertValuesMock,
|
|
dbInsertRunMock,
|
|
proxyLogsSchema,
|
|
} = vi.hoisted(() => ({
|
|
hasProxyLogBillingDetailsColumnMock: vi.fn(),
|
|
dbInsertMock: vi.fn(),
|
|
dbInsertValuesMock: vi.fn(),
|
|
dbInsertRunMock: vi.fn(),
|
|
proxyLogsSchema: {
|
|
id: 'id',
|
|
routeId: 'route_id',
|
|
channelId: 'channel_id',
|
|
accountId: 'account_id',
|
|
modelRequested: 'model_requested',
|
|
modelActual: 'model_actual',
|
|
status: 'status',
|
|
httpStatus: 'http_status',
|
|
latencyMs: 'latency_ms',
|
|
promptTokens: 'prompt_tokens',
|
|
completionTokens: 'completion_tokens',
|
|
totalTokens: 'total_tokens',
|
|
estimatedCost: 'estimated_cost',
|
|
billingDetails: 'billing_details',
|
|
errorMessage: 'error_message',
|
|
retryCount: 'retry_count',
|
|
createdAt: 'created_at',
|
|
},
|
|
}));
|
|
|
|
vi.mock('../db/index.js', () => ({
|
|
db: {
|
|
insert: (...args: unknown[]) => dbInsertMock(...args),
|
|
},
|
|
schema: {
|
|
proxyLogs: proxyLogsSchema,
|
|
},
|
|
hasProxyLogBillingDetailsColumn: (...args: unknown[]) => hasProxyLogBillingDetailsColumnMock(...args),
|
|
}));
|
|
|
|
import { insertProxyLog, withProxyLogSelectFields } from './proxyLogStore.js';
|
|
|
|
describe('proxyLogStore', () => {
|
|
beforeEach(() => {
|
|
hasProxyLogBillingDetailsColumnMock.mockReset();
|
|
dbInsertMock.mockReset();
|
|
dbInsertValuesMock.mockReset();
|
|
dbInsertRunMock.mockReset();
|
|
|
|
dbInsertMock.mockReturnValue({
|
|
values: (...args: unknown[]) => dbInsertValuesMock(...args),
|
|
});
|
|
dbInsertValuesMock.mockReturnValue({
|
|
run: (...args: unknown[]) => dbInsertRunMock(...args),
|
|
});
|
|
});
|
|
|
|
it('retries proxy log selects without billing details when the column is missing', async () => {
|
|
hasProxyLogBillingDetailsColumnMock.mockResolvedValue(true);
|
|
const runner = vi.fn()
|
|
.mockRejectedValueOnce(new Error('column proxy_logs.billing_details does not exist'))
|
|
.mockResolvedValueOnce([{ id: 1 }]);
|
|
|
|
await expect(withProxyLogSelectFields(runner, { includeBillingDetails: true })).resolves.toEqual([{ id: 1 }]);
|
|
|
|
expect(runner).toHaveBeenCalledTimes(2);
|
|
expect(runner.mock.calls[0][0].includeBillingDetails).toBe(true);
|
|
expect(runner.mock.calls[0][0].fields.billingDetails).toBe('billing_details');
|
|
expect(runner.mock.calls[1][0].includeBillingDetails).toBe(false);
|
|
expect(runner.mock.calls[1][0].fields.billingDetails).toBeUndefined();
|
|
});
|
|
|
|
it('retries proxy log inserts without billing details when the column is missing', async () => {
|
|
hasProxyLogBillingDetailsColumnMock.mockResolvedValue(true);
|
|
dbInsertRunMock
|
|
.mockRejectedValueOnce(new Error('column proxy_logs.billing_details does not exist'))
|
|
.mockResolvedValueOnce(undefined);
|
|
|
|
await insertProxyLog({
|
|
modelRequested: 'gpt-5',
|
|
billingDetails: { total: 1 },
|
|
});
|
|
|
|
expect(dbInsertValuesMock).toHaveBeenCalledTimes(2);
|
|
expect(dbInsertValuesMock.mock.calls[0][0]).toMatchObject({
|
|
modelRequested: 'gpt-5',
|
|
billingDetails: JSON.stringify({ total: 1 }),
|
|
});
|
|
expect(dbInsertValuesMock.mock.calls[1][0]).toMatchObject({
|
|
modelRequested: 'gpt-5',
|
|
});
|
|
expect(dbInsertValuesMock.mock.calls[1][0].billingDetails).toBeUndefined();
|
|
});
|
|
});
|