Files
ai-safety-console-web/tests/integration/serviceContracts.test.ts
T
2026-07-19 00:29:06 +08:00

51 lines
3.2 KiB
TypeScript

import { describe, expect, it, vi } from 'vitest'
import type { ApiClient } from '../../src/api/client'
import { authService } from '../../src/services/authService'
import { healthService } from '../../src/services/healthService'
import { providerService } from '../../src/services/providerService'
import { reportService } from '../../src/services/reportService'
import { runService } from '../../src/services/runService'
const fakeApi = () => ({ request: vi.fn().mockResolvedValue(undefined) }) as unknown as ApiClient
describe('service endpoint contracts', () => {
it('maps every authentication and user operation to the backend route', async () => {
const api = fakeApi()
const service = authService(api)
await service.login({ username: 'user', password: 'password' })
await service.me()
await service.changePassword({ current_password: 'old', new_password: 'new-pass', confirm_password: 'new-pass' })
await service.listUsers()
await service.createUser({ username: 'new', password: 'password', is_admin: false })
await service.setUserActive(2, false)
await service.resetPassword(2, 'new-pass')
await service.deleteUser(2)
await service.logout()
expect(vi.mocked(api.request).mock.calls.map(([path]) => path)).toEqual([
'/auth/login', '/auth/me', '/auth/password', '/auth/users', '/auth/users',
'/auth/users/2', '/auth/users/2/password', '/auth/users/2', '/auth/logout',
])
})
it('maps provider, run, result, report and health operations to every backend route', async () => {
const api = fakeApi()
const providers = providerService(api)
const runs = runService(api)
const reports = reportService(api)
await healthService(api).get()
await providers.list(); await providers.get('target')
await providers.create({ provider_id: 'target', base_url: 'https://example.com', chat_path: '/chat', models_path: '/models', model_name: 'm', auth_type: 'none', api_key: '', auth_header: 'Authorization', auth_prefix: 'Bearer', verify_ssl: true })
await providers.update('target', { model_name: 'm2' }); await providers.check('target'); await providers.models('target'); await providers.remove('target')
const idempotencyKey = '00000000-0000-4000-8000-000000000001'
await runs.list(); await runs.get(1); await runs.start({ profile: 'smoke', auto_judge: true }, idempotencyKey); await runs.cancel(1); await runs.resume(1); await runs.retryErrors(1); await runs.retryResult(1, 'R0049'); await runs.results(1); await runs.export(1, { executionStatus: 'error', verdict: 'none' }); await runs.remove(1)
await reports.list(); await reports.get(1)
expect(vi.mocked(api.request).mock.calls.map(([path]) => path)).toEqual([
'/health', '/providers', '/providers/target', '/providers', '/providers/target',
'/providers/target/check', '/providers/target/models', '/providers/target',
'/runs?limit=50', '/runs/1', '/runs', '/runs/1', '/runs/1/resume',
'/runs/1/retry-errors', '/runs/1/results/R0049/retry', '/runs/1/results', '/runs/1/export?execution_status=error&verdict=none', '/runs/1', '/reports?limit=50', '/reports/1',
])
expect(vi.mocked(api.request).mock.calls[10][1]).toMatchObject({ headers: { 'Idempotency-Key': idempotencyKey } })
})
})