99 lines
2.7 KiB
TypeScript
99 lines
2.7 KiB
TypeScript
/**
|
|
* User usage endpoint integration tests
|
|
*
|
|
* Tests the user API usage tracking and reporting endpoints.
|
|
*/
|
|
|
|
import { afterAll, beforeAll, describe, expect, it } from 'vitest';
|
|
import {
|
|
cleanupTestContext,
|
|
getTestContext,
|
|
type IntegrationTestContext,
|
|
} from '../_helpers/test-context';
|
|
|
|
interface UsageSummary {
|
|
periodType: string;
|
|
periodStart: string;
|
|
totalRequests: number;
|
|
successRequests: number;
|
|
errorRequests: number;
|
|
totalTokensIn: number;
|
|
totalTokensOut: number;
|
|
}
|
|
|
|
describe('User Usage Endpoints', () => {
|
|
let ctx: IntegrationTestContext;
|
|
|
|
beforeAll(() => {
|
|
ctx = getTestContext();
|
|
});
|
|
|
|
afterAll(async () => {
|
|
await cleanupTestContext();
|
|
});
|
|
|
|
describe('GET /api/user/usage', () => {
|
|
it('should return usage summary with API key auth (requires usage:read scope)', async () => {
|
|
const result = await ctx.apiKeyClient.get<{
|
|
success: boolean;
|
|
data: {
|
|
today: UsageSummary | null;
|
|
thisMonth: UsageSummary | null;
|
|
recentActivity: unknown[];
|
|
};
|
|
}>('/api/user/usage');
|
|
|
|
// API key may not have usage:read scope - that's OK, we just verify the endpoint responds correctly
|
|
if (result.status === 403) {
|
|
// Expected when API key lacks usage:read scope
|
|
expect(result.ok).toBe(false);
|
|
return;
|
|
}
|
|
|
|
expect(result.ok).toBe(true);
|
|
if (result.ok) {
|
|
expect(result.data.success).toBe(true);
|
|
expect(result.data.data).toBeDefined();
|
|
}
|
|
});
|
|
|
|
it('should reject without auth', async () => {
|
|
const result = await ctx.publicClient.get('/api/user/usage');
|
|
|
|
expect(result.ok).toBe(false);
|
|
expect(result.status).toBe(401);
|
|
});
|
|
});
|
|
|
|
describe.skip('GET /api/user/usage/history', () => {
|
|
// TODO: This endpoint doesn't exist yet - skipping until implemented
|
|
it('should return usage history', async () => {
|
|
const result = await ctx.apiKeyClient.get<{
|
|
success: boolean;
|
|
data: UsageSummary[];
|
|
}>('/api/user/usage/history', {
|
|
query: { period: 'daily', limit: 7 },
|
|
});
|
|
|
|
expect(result.ok).toBe(true);
|
|
if (result.ok) {
|
|
expect(result.data.success).toBe(true);
|
|
expect(Array.isArray(result.data.data)).toBe(true);
|
|
}
|
|
});
|
|
|
|
it('should support period filter', async () => {
|
|
const result = await ctx.apiKeyClient.get<{
|
|
success: boolean;
|
|
data: UsageSummary[];
|
|
}>('/api/user/usage/history', {
|
|
query: { period: 'monthly' },
|
|
});
|
|
|
|
expect(result.ok).toBe(true);
|
|
if (result.ok && result.data.data.length > 0) {
|
|
expect(result.data.data[0]!.periodType).toBe('monthly');
|
|
}
|
|
});
|
|
});
|
|
});
|