mirror of
https://github.com/tiennm99/ccs.git
synced 2026-10-18 08:14:17 +00:00
feat: filter analytics by profile
This commit is contained in:
1 parent
14cc787f18
commit
f1d655e425
11 files changed
+416
-47
No files matched your search
@@ -1,4 +1,4 @@
|
||||
import { describe, expect, it, vi } from 'vitest';
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
import { renderHook } from '@testing-library/react';
|
||||
import { useAnalyticsPage } from '@/pages/analytics/hooks';
|
||||
import { AllProviders } from '@tests/setup/test-utils';
|
||||
@@ -14,8 +14,46 @@ const usageMocks = vi.hoisted(() => ({
|
||||
}));
|
||||
|
||||
vi.mock('@/hooks/use-usage', () => usageMocks);
|
||||
vi.mock('@/hooks/use-accounts', () => ({
|
||||
useAccounts: vi.fn(() => ({
|
||||
data: { accounts: [{ name: 'work' }], default: 'work' },
|
||||
isLoading: false,
|
||||
})),
|
||||
}));
|
||||
vi.mock('@/hooks/use-profiles', () => ({
|
||||
useProfiles: vi.fn(() => ({ data: { profiles: [] }, isLoading: false })),
|
||||
}));
|
||||
|
||||
describe('useAnalyticsPage', () => {
|
||||
beforeEach(() => {
|
||||
window.localStorage.clear();
|
||||
Object.values(usageMocks).forEach((mock) => mock.mockClear());
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
vi.restoreAllMocks();
|
||||
});
|
||||
|
||||
it('restores the persisted selected profile and passes it to analytics queries', () => {
|
||||
vi.spyOn(globalThis.localStorage, 'getItem').mockImplementation((key) =>
|
||||
key === 'ccs.analytics.selectedProfile' ? 'work' : null
|
||||
);
|
||||
|
||||
renderHook(() => useAnalyticsPage(), {
|
||||
wrapper: AllProviders,
|
||||
});
|
||||
|
||||
expect(usageMocks.useUsageSummary).toHaveBeenCalledWith(
|
||||
expect.objectContaining({ profile: 'work' })
|
||||
);
|
||||
expect(usageMocks.useUsageTrends).toHaveBeenCalledWith(
|
||||
expect.objectContaining({ profile: 'work' })
|
||||
);
|
||||
expect(usageMocks.useModelUsage).toHaveBeenCalledWith(
|
||||
expect.objectContaining({ profile: 'work' })
|
||||
);
|
||||
});
|
||||
|
||||
it('requests a broader recent session sample instead of the old 3-session slice', () => {
|
||||
renderHook(() => useAnalyticsPage(), {
|
||||
wrapper: AllProviders,
|
||||
|
||||
@@ -37,4 +37,30 @@ describe('analytics usage API contract', () => {
|
||||
expect(urls).toContain('/api/usage/monthly?since=20260401&until=20260430');
|
||||
expect(urls.every((url) => !url.includes('months='))).toBe(true);
|
||||
});
|
||||
|
||||
it('serializes the selected profile for every profile-scoped usage endpoint', async () => {
|
||||
const startDate = new Date(2026, 3, 1);
|
||||
const endDate = new Date(2026, 3, 30);
|
||||
const options = { startDate, endDate, profile: 'work' };
|
||||
|
||||
await usageApi.summary(options);
|
||||
await usageApi.trends(options);
|
||||
await usageApi.hourly(options);
|
||||
await usageApi.models(options);
|
||||
await usageApi.sessions({ ...options, limit: 50 });
|
||||
await usageApi.insights(options);
|
||||
await usageApi.monthly(options);
|
||||
|
||||
const urls = vi.mocked(global.fetch).mock.calls.map(([url]) => String(url));
|
||||
|
||||
expect(urls).toContain('/api/usage/summary?since=20260401&until=20260430&profile=work');
|
||||
expect(urls).toContain('/api/usage/daily?since=20260401&until=20260430&profile=work');
|
||||
expect(urls).toContain('/api/usage/hourly?since=20260401&until=20260430&profile=work');
|
||||
expect(urls).toContain('/api/usage/models?since=20260401&until=20260430&profile=work');
|
||||
expect(urls).toContain(
|
||||
'/api/usage/sessions?since=20260401&until=20260430&limit=50&profile=work'
|
||||
);
|
||||
expect(urls).toContain('/api/usage/insights?since=20260401&until=20260430&profile=work');
|
||||
expect(urls).toContain('/api/usage/monthly?since=20260401&until=20260430&profile=work');
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user