import { describe, it, expect, vi, beforeEach } from 'vitest'; // We test the API module's structure and endpoint definitions // The actual HTTP calls are mocked; we verify correct URL/method/payload patterns vi.mock('axios', () => { const mockAxiosInstance = { get: vi.fn().mockResolvedValue({ data: {} }), post: vi.fn().mockResolvedValue({ data: {} }), put: vi.fn().mockResolvedValue({ data: {} }), patch: vi.fn().mockResolvedValue({ data: {} }), interceptors: { request: { use: vi.fn() }, response: { use: vi.fn() }, }, }; return { default: { create: vi.fn(() => mockAxiosInstance), post: vi.fn(), }, }; }); import { authApi, videoApi, adminApi, profileApi } from '../../src/lib/api'; import api from '../../src/lib/api'; describe('API Client', () => { beforeEach(() => { vi.clearAllMocks(); }); describe('authApi', () => { it('should have register method that posts to /auth/register', async () => { await authApi.register('user1', 'user1@test.com', 'pass123'); expect(api.post).toHaveBeenCalledWith( '/auth/register', { username: 'user1', email: 'user1@test.com', password: 'pass123' } ); }); it('should have login method that posts to /auth/login', async () => { await authApi.login('user1', 'pass123'); expect(api.post).toHaveBeenCalledWith( '/auth/login', { username: 'user1', password: 'pass123' } ); }); it('should have refreshToken method that posts to /auth/token/refresh', async () => { await authApi.refreshToken('my-refresh-token'); expect(api.post).toHaveBeenCalledWith( '/auth/token/refresh', { refresh: 'my-refresh-token' } ); }); it('should have getMe method that gets /auth/me', async () => { await authApi.getMe(); expect(api.get).toHaveBeenCalledWith('/auth/me'); }); }); describe('videoApi', () => { it('should have generate method that posts FormData to /video/generate', async () => { const formData = new FormData(); formData.append('prompt', 'test prompt'); await videoApi.generate(formData); expect(api.post).toHaveBeenCalledWith( '/video/generate', formData, { headers: { 'Content-Type': 'multipart/form-data' } } ); }); }); describe('adminApi', () => { it('should have getStats method that gets /admin/stats', async () => { await adminApi.getStats(); expect(api.get).toHaveBeenCalledWith('/admin/stats'); }); it('should have getUsers with default params', async () => { await adminApi.getUsers(); expect(api.get).toHaveBeenCalledWith('/admin/users', { params: {} }); }); it('should have getUsers with search params', async () => { await adminApi.getUsers({ page: 2, search: 'alice' }); expect(api.get).toHaveBeenCalledWith('/admin/users', { params: { page: 2, search: 'alice' }, }); }); it('should have updateUserQuota that puts /admin/users/:id/quota', async () => { await adminApi.updateUserQuota(42, 600, 6000); expect(api.put).toHaveBeenCalledWith('/admin/users/42/quota', { daily_seconds_limit: 600, monthly_seconds_limit: 6000, }); }); }); }); describe('API Client Configuration', () => { it('should export authApi with all 4 methods', () => { expect(authApi).toBeDefined(); expect(typeof authApi.register).toBe('function'); expect(typeof authApi.login).toBe('function'); expect(typeof authApi.refreshToken).toBe('function'); expect(typeof authApi.getMe).toBe('function'); }); it('should export videoApi with generate method', () => { expect(videoApi).toBeDefined(); expect(typeof videoApi.generate).toBe('function'); }); it('should export adminApi with Phase 3 methods', () => { expect(adminApi).toBeDefined(); expect(typeof adminApi.getStats).toBe('function'); expect(typeof adminApi.getUsers).toBe('function'); expect(typeof adminApi.getUserDetail).toBe('function'); expect(typeof adminApi.updateUserQuota).toBe('function'); expect(typeof adminApi.updateUserStatus).toBe('function'); expect(typeof adminApi.getRecords).toBe('function'); expect(typeof adminApi.getSettings).toBe('function'); expect(typeof adminApi.updateSettings).toBe('function'); }); it('should export profileApi with Phase 3 methods', () => { expect(profileApi).toBeDefined(); expect(typeof profileApi.getOverview).toBe('function'); expect(typeof profileApi.getRecords).toBe('function'); }); }); describe('Admin API Phase 3 — Additional Endpoint Tests', () => { beforeEach(() => { vi.clearAllMocks(); }); it('adminApi.getUserDetail fetches /admin/users/:id', async () => { await adminApi.getUserDetail(7); expect(api.get).toHaveBeenCalledWith('/admin/users/7'); }); it('adminApi.updateUserStatus patches /admin/users/:id/status', async () => { await adminApi.updateUserStatus(5, false); expect(api.patch).toHaveBeenCalledWith('/admin/users/5/status', { is_active: false }); }); it('adminApi.getRecords fetches /admin/records with params', async () => { await adminApi.getRecords({ page: 2, search: 'bob', start_date: '2026-03-01' }); expect(api.get).toHaveBeenCalledWith('/admin/records', { params: { page: 2, search: 'bob', start_date: '2026-03-01' }, }); }); it('adminApi.getSettings fetches /admin/settings', async () => { await adminApi.getSettings(); expect(api.get).toHaveBeenCalledWith('/admin/settings'); }); it('adminApi.updateSettings puts /admin/settings', async () => { const settings = { default_daily_seconds_limit: 900, default_monthly_seconds_limit: 9000, announcement: 'test', announcement_enabled: true, }; await adminApi.updateSettings(settings); expect(api.put).toHaveBeenCalledWith('/admin/settings', settings); }); }); describe('Profile API Phase 3', () => { beforeEach(() => { vi.clearAllMocks(); }); it('profileApi.getOverview fetches /profile/overview with default period', async () => { await profileApi.getOverview(); expect(api.get).toHaveBeenCalledWith('/profile/overview', { params: { period: '7d' } }); }); it('profileApi.getOverview supports 30d period', async () => { await profileApi.getOverview('30d'); expect(api.get).toHaveBeenCalledWith('/profile/overview', { params: { period: '30d' } }); }); it('profileApi.getRecords fetches /profile/records with pagination', async () => { await profileApi.getRecords(2, 10); expect(api.get).toHaveBeenCalledWith('/profile/records', { params: { page: 2, page_size: 10 }, }); }); });