Files
ccs/tests/unit/web-server/cliproxy-usage-syncer.test.ts
T
Tam Nhu Tran 383ac94623 test(usage): add cliproxy sync and integration coverage
- add transformer unit tests for flattening and daily/hourly/monthly rollups

- add syncer tests for snapshot persistence and idempotent interval start

- add aggregator integration test for JSONL + CLIProxy merge behavior
2026-03-03 23:05:24 +07:00

98 lines
2.6 KiB
TypeScript

import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, it, mock, spyOn } from 'bun:test';
import * as fs from 'fs';
import * as os from 'os';
import * as path from 'path';
import type { CliproxyUsageApiResponse } from '../../../src/cliproxy/stats-fetcher';
let ccsDir = '';
let rawResponse: CliproxyUsageApiResponse | null = null;
let fetchCalls = 0;
mock.module('../../../src/utils/config-manager', () => ({
getCcsDir: () => ccsDir,
}));
mock.module('../../../src/cliproxy/stats-fetcher', () => ({
fetchCliproxyUsageRaw: async () => {
fetchCalls++;
return rawResponse;
},
}));
let syncer: typeof import('../../../src/web-server/usage/cliproxy-usage-syncer');
beforeAll(async () => {
syncer = await import('../../../src/web-server/usage/cliproxy-usage-syncer');
});
beforeEach(() => {
ccsDir = fs.mkdtempSync(path.join(os.tmpdir(), 'ccs-cliproxy-syncer-'));
fetchCalls = 0;
rawResponse = {
usage: {
apis: {
gemini: {
models: {
'gemini-2.5-pro': {
details: [
{
timestamp: '2026-03-02T12:00:00.000Z',
source: 'account-a',
auth_index: 0,
tokens: {
input_tokens: 100,
output_tokens: 20,
reasoning_tokens: 0,
cached_tokens: 10,
total_tokens: 130,
},
failed: false,
},
],
},
},
},
},
},
};
syncer.stopCliproxySync();
});
afterEach(() => {
syncer.stopCliproxySync();
fs.rmSync(ccsDir, { recursive: true, force: true });
});
afterAll(() => {
mock.restore();
});
describe('cliproxy usage syncer', () => {
it('writes and loads snapshot data', async () => {
await syncer.syncCliproxyUsage();
const snapshotPath = path.join(ccsDir, 'cache', 'cliproxy-usage', 'latest.json');
expect(fs.existsSync(snapshotPath)).toBe(true);
const cached = await syncer.loadCachedCliproxyData();
expect(cached.daily).toHaveLength(1);
expect(cached.daily[0].source).toBe('cliproxy');
expect(cached.daily[0].inputTokens).toBe(100);
expect(cached.hourly).toHaveLength(1);
expect(cached.monthly).toHaveLength(1);
});
it('startCliproxySync is idempotent and starts only one interval', () => {
const intervalSpy = spyOn(globalThis, 'setInterval');
syncer.startCliproxySync();
syncer.startCliproxySync();
expect(intervalSpy).toHaveBeenCalledTimes(1);
expect(fetchCalls).toBeGreaterThan(0);
syncer.stopCliproxySync();
intervalSpy.mockRestore();
});
});