Some checks failed
Tests / Go Tests (push) Has been cancelled
Tests / Python Tests (push) Has been cancelled
Tests / Integration Tests (push) Has been cancelled
Tests / Go Lint (push) Has been cancelled
Tests / Python Lint (push) Has been cancelled
Tests / Security Scan (push) Has been cancelled
Tests / All Checks Passed (push) Has been cancelled
Security Scanning / Secret Scanning (push) Has been cancelled
Security Scanning / Dependency Vulnerability Scan (push) Has been cancelled
Security Scanning / Go Security Scan (push) Has been cancelled
Security Scanning / Python Security Scan (push) Has been cancelled
Security Scanning / Node.js Security Scan (push) Has been cancelled
Security Scanning / Docker Image Security (push) Has been cancelled
Security Scanning / Security Summary (push) Has been cancelled
CI/CD Pipeline / Go Tests (push) Has been cancelled
CI/CD Pipeline / Python Tests (push) Has been cancelled
CI/CD Pipeline / Website Tests (push) Has been cancelled
CI/CD Pipeline / Linting (push) Has been cancelled
CI/CD Pipeline / Security Scan (push) Has been cancelled
CI/CD Pipeline / Docker Build & Push (push) Has been cancelled
CI/CD Pipeline / Integration Tests (push) Has been cancelled
CI/CD Pipeline / Deploy to Staging (push) Has been cancelled
CI/CD Pipeline / Deploy to Production (push) Has been cancelled
CI/CD Pipeline / CI Summary (push) Has been cancelled
ci/woodpecker/manual/build-ci-image Pipeline was successful
ci/woodpecker/manual/main Pipeline failed
All services: admin-v2, studio-v2, website, ai-compliance-sdk, consent-service, klausur-service, voice-service, and infrastructure. Large PDFs and compiled binaries excluded via .gitignore.
356 lines
9.2 KiB
TypeScript
356 lines
9.2 KiB
TypeScript
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'
|
|
|
|
// Mock fetch globally
|
|
const mockFetch = vi.fn()
|
|
global.fetch = mockFetch
|
|
|
|
describe('DSFA API Client', () => {
|
|
beforeEach(() => {
|
|
mockFetch.mockClear()
|
|
})
|
|
|
|
afterEach(() => {
|
|
vi.restoreAllMocks()
|
|
})
|
|
|
|
describe('listDSFAs', () => {
|
|
it('should fetch DSFAs without status filter', async () => {
|
|
const mockDSFAs = [
|
|
{ id: 'dsfa-1', name: 'Test DSFA 1', status: 'draft' },
|
|
{ id: 'dsfa-2', name: 'Test DSFA 2', status: 'approved' },
|
|
]
|
|
|
|
mockFetch.mockResolvedValueOnce({
|
|
ok: true,
|
|
json: () => Promise.resolve({ dsfas: mockDSFAs }),
|
|
})
|
|
|
|
const { listDSFAs } = await import('../api')
|
|
const result = await listDSFAs()
|
|
|
|
expect(mockFetch).toHaveBeenCalledTimes(1)
|
|
expect(result).toHaveLength(2)
|
|
expect(result[0].name).toBe('Test DSFA 1')
|
|
})
|
|
|
|
it('should fetch DSFAs with status filter', async () => {
|
|
const mockDSFAs = [{ id: 'dsfa-1', name: 'Draft DSFA', status: 'draft' }]
|
|
|
|
mockFetch.mockResolvedValueOnce({
|
|
ok: true,
|
|
json: () => Promise.resolve({ dsfas: mockDSFAs }),
|
|
})
|
|
|
|
const { listDSFAs } = await import('../api')
|
|
const result = await listDSFAs('draft')
|
|
|
|
expect(mockFetch).toHaveBeenCalledTimes(1)
|
|
const calledUrl = mockFetch.mock.calls[0][0]
|
|
expect(calledUrl).toContain('status=draft')
|
|
})
|
|
|
|
it('should return empty array when no DSFAs', async () => {
|
|
mockFetch.mockResolvedValueOnce({
|
|
ok: true,
|
|
json: () => Promise.resolve({ dsfas: null }),
|
|
})
|
|
|
|
const { listDSFAs } = await import('../api')
|
|
const result = await listDSFAs()
|
|
|
|
expect(result).toEqual([])
|
|
})
|
|
})
|
|
|
|
describe('getDSFA', () => {
|
|
it('should fetch a single DSFA by ID', async () => {
|
|
const mockDSFA = {
|
|
id: 'dsfa-123',
|
|
name: 'Test DSFA',
|
|
status: 'draft',
|
|
risks: [],
|
|
mitigations: [],
|
|
}
|
|
|
|
mockFetch.mockResolvedValueOnce({
|
|
ok: true,
|
|
json: () => Promise.resolve(mockDSFA),
|
|
})
|
|
|
|
const { getDSFA } = await import('../api')
|
|
const result = await getDSFA('dsfa-123')
|
|
|
|
expect(mockFetch).toHaveBeenCalledTimes(1)
|
|
expect(result.id).toBe('dsfa-123')
|
|
expect(result.name).toBe('Test DSFA')
|
|
})
|
|
|
|
it('should throw error for non-existent DSFA', async () => {
|
|
mockFetch.mockResolvedValueOnce({
|
|
ok: false,
|
|
status: 404,
|
|
text: () => Promise.resolve('{"error": "DSFA not found"}'),
|
|
})
|
|
|
|
const { getDSFA } = await import('../api')
|
|
|
|
await expect(getDSFA('non-existent')).rejects.toThrow()
|
|
})
|
|
})
|
|
|
|
describe('createDSFA', () => {
|
|
it('should create a new DSFA', async () => {
|
|
const newDSFA = {
|
|
name: 'New DSFA',
|
|
description: 'Test description',
|
|
processing_purpose: 'Testing',
|
|
}
|
|
|
|
const createdDSFA = {
|
|
id: 'dsfa-new',
|
|
...newDSFA,
|
|
status: 'draft',
|
|
}
|
|
|
|
mockFetch.mockResolvedValueOnce({
|
|
ok: true,
|
|
json: () => Promise.resolve(createdDSFA),
|
|
})
|
|
|
|
const { createDSFA } = await import('../api')
|
|
const result = await createDSFA(newDSFA)
|
|
|
|
expect(mockFetch).toHaveBeenCalledTimes(1)
|
|
expect(result.id).toBe('dsfa-new')
|
|
expect(result.name).toBe('New DSFA')
|
|
})
|
|
})
|
|
|
|
describe('updateDSFA', () => {
|
|
it('should update an existing DSFA', async () => {
|
|
const updates = {
|
|
name: 'Updated DSFA Name',
|
|
processing_purpose: 'Updated purpose',
|
|
}
|
|
|
|
const updatedDSFA = {
|
|
id: 'dsfa-123',
|
|
...updates,
|
|
status: 'draft',
|
|
}
|
|
|
|
mockFetch.mockResolvedValueOnce({
|
|
ok: true,
|
|
json: () => Promise.resolve(updatedDSFA),
|
|
})
|
|
|
|
const { updateDSFA } = await import('../api')
|
|
const result = await updateDSFA('dsfa-123', updates)
|
|
|
|
expect(mockFetch).toHaveBeenCalledTimes(1)
|
|
expect(result.name).toBe('Updated DSFA Name')
|
|
})
|
|
})
|
|
|
|
describe('deleteDSFA', () => {
|
|
it('should delete a DSFA', async () => {
|
|
mockFetch.mockResolvedValueOnce({
|
|
ok: true,
|
|
})
|
|
|
|
const { deleteDSFA } = await import('../api')
|
|
await deleteDSFA('dsfa-123')
|
|
|
|
expect(mockFetch).toHaveBeenCalledTimes(1)
|
|
const calledConfig = mockFetch.mock.calls[0][1]
|
|
expect(calledConfig.method).toBe('DELETE')
|
|
})
|
|
|
|
it('should throw error when deletion fails', async () => {
|
|
mockFetch.mockResolvedValueOnce({
|
|
ok: false,
|
|
statusText: 'Not Found',
|
|
})
|
|
|
|
const { deleteDSFA } = await import('../api')
|
|
|
|
await expect(deleteDSFA('non-existent')).rejects.toThrow()
|
|
})
|
|
})
|
|
|
|
describe('updateDSFASection', () => {
|
|
it('should update a specific section', async () => {
|
|
const sectionData = {
|
|
processing_purpose: 'Updated purpose',
|
|
data_categories: ['personal_data', 'contact_data'],
|
|
}
|
|
|
|
const updatedDSFA = {
|
|
id: 'dsfa-123',
|
|
section_progress: {
|
|
section_1_complete: true,
|
|
},
|
|
}
|
|
|
|
mockFetch.mockResolvedValueOnce({
|
|
ok: true,
|
|
json: () => Promise.resolve(updatedDSFA),
|
|
})
|
|
|
|
const { updateDSFASection } = await import('../api')
|
|
const result = await updateDSFASection('dsfa-123', 1, sectionData)
|
|
|
|
expect(mockFetch).toHaveBeenCalledTimes(1)
|
|
const calledUrl = mockFetch.mock.calls[0][0]
|
|
expect(calledUrl).toContain('/sections/1')
|
|
})
|
|
})
|
|
|
|
describe('submitDSFAForReview', () => {
|
|
it('should submit DSFA for review', async () => {
|
|
const response = {
|
|
message: 'DSFA submitted for review',
|
|
dsfa: {
|
|
id: 'dsfa-123',
|
|
status: 'in_review',
|
|
},
|
|
}
|
|
|
|
mockFetch.mockResolvedValueOnce({
|
|
ok: true,
|
|
json: () => Promise.resolve(response),
|
|
})
|
|
|
|
const { submitDSFAForReview } = await import('../api')
|
|
const result = await submitDSFAForReview('dsfa-123')
|
|
|
|
expect(mockFetch).toHaveBeenCalledTimes(1)
|
|
expect(result.dsfa.status).toBe('in_review')
|
|
})
|
|
})
|
|
|
|
describe('approveDSFA', () => {
|
|
it('should approve a DSFA', async () => {
|
|
mockFetch.mockResolvedValueOnce({
|
|
ok: true,
|
|
json: () => Promise.resolve({ message: 'DSFA approved' }),
|
|
})
|
|
|
|
const { approveDSFA } = await import('../api')
|
|
const result = await approveDSFA('dsfa-123', {
|
|
dpo_opinion: 'Approved after review',
|
|
approved: true,
|
|
})
|
|
|
|
expect(mockFetch).toHaveBeenCalledTimes(1)
|
|
expect(result.message).toBe('DSFA approved')
|
|
})
|
|
|
|
it('should reject a DSFA', async () => {
|
|
mockFetch.mockResolvedValueOnce({
|
|
ok: true,
|
|
json: () => Promise.resolve({ message: 'DSFA rejected' }),
|
|
})
|
|
|
|
const { approveDSFA } = await import('../api')
|
|
const result = await approveDSFA('dsfa-123', {
|
|
dpo_opinion: 'Needs more details',
|
|
approved: false,
|
|
})
|
|
|
|
expect(result.message).toBe('DSFA rejected')
|
|
})
|
|
})
|
|
|
|
describe('getDSFAStats', () => {
|
|
it('should fetch DSFA statistics', async () => {
|
|
const stats = {
|
|
total: 10,
|
|
status_stats: {
|
|
draft: 4,
|
|
in_review: 2,
|
|
approved: 3,
|
|
rejected: 1,
|
|
},
|
|
risk_stats: {
|
|
low: 3,
|
|
medium: 4,
|
|
high: 2,
|
|
very_high: 1,
|
|
},
|
|
}
|
|
|
|
mockFetch.mockResolvedValueOnce({
|
|
ok: true,
|
|
json: () => Promise.resolve(stats),
|
|
})
|
|
|
|
const { getDSFAStats } = await import('../api')
|
|
const result = await getDSFAStats()
|
|
|
|
expect(mockFetch).toHaveBeenCalledTimes(1)
|
|
expect(result.total).toBe(10)
|
|
expect(result.status_stats.approved).toBe(3)
|
|
})
|
|
})
|
|
|
|
describe('createDSFAFromAssessment', () => {
|
|
it('should create DSFA from UCCA assessment', async () => {
|
|
const response = {
|
|
dsfa: {
|
|
id: 'dsfa-new',
|
|
name: 'AI Chatbot DSFA',
|
|
status: 'draft',
|
|
},
|
|
prefilled: true,
|
|
message: 'DSFA created from assessment',
|
|
}
|
|
|
|
mockFetch.mockResolvedValueOnce({
|
|
ok: true,
|
|
json: () => Promise.resolve(response),
|
|
})
|
|
|
|
const { createDSFAFromAssessment } = await import('../api')
|
|
const result = await createDSFAFromAssessment('assessment-123')
|
|
|
|
expect(mockFetch).toHaveBeenCalledTimes(1)
|
|
expect(result.prefilled).toBe(true)
|
|
expect(result.dsfa.id).toBe('dsfa-new')
|
|
})
|
|
})
|
|
|
|
describe('getDSFAByAssessment', () => {
|
|
it('should return DSFA linked to assessment', async () => {
|
|
const dsfa = {
|
|
id: 'dsfa-123',
|
|
assessment_id: 'assessment-123',
|
|
name: 'Linked DSFA',
|
|
}
|
|
|
|
mockFetch.mockResolvedValueOnce({
|
|
ok: true,
|
|
json: () => Promise.resolve(dsfa),
|
|
})
|
|
|
|
const { getDSFAByAssessment } = await import('../api')
|
|
const result = await getDSFAByAssessment('assessment-123')
|
|
|
|
expect(result?.id).toBe('dsfa-123')
|
|
})
|
|
|
|
it('should return null when no DSFA exists for assessment', async () => {
|
|
mockFetch.mockResolvedValueOnce({
|
|
ok: false,
|
|
status: 404,
|
|
text: () => Promise.resolve('Not found'),
|
|
})
|
|
|
|
const { getDSFAByAssessment } = await import('../api')
|
|
const result = await getDSFAByAssessment('no-dsfa-assessment')
|
|
|
|
expect(result).toBeNull()
|
|
})
|
|
})
|
|
})
|