- Add comprehensive database migrations (001-024) for schema evolution - Enhance API schema with expanded type definitions and resolvers - Add new middleware: audit logging, rate limiting, MFA enforcement, security, tenant auth - Implement new services: AI optimization, billing, blockchain, compliance, marketplace - Add adapter layer for cloud integrations (Cloudflare, Kubernetes, Proxmox, storage) - Update Crossplane provider with enhanced VM management capabilities - Add comprehensive test suite for API endpoints and services - Update frontend components with improved GraphQL subscriptions and real-time updates - Enhance security configurations and headers (CSP, CORS, etc.) - Update documentation and configuration files - Add new CI/CD workflows and validation scripts - Implement design system improvements and UI enhancements
115 lines
3.1 KiB
TypeScript
115 lines
3.1 KiB
TypeScript
/**
|
|
* Anomaly Detection Service Tests
|
|
*/
|
|
|
|
import { describe, it, expect, beforeEach, vi } from 'vitest'
|
|
import { detectAnomalies, getAnomalies } from '../anomaly-detection'
|
|
import type { Context } from '../../types/context'
|
|
|
|
describe('Anomaly Detection Service', () => {
|
|
let mockContext: Context
|
|
let mockDb: any
|
|
|
|
beforeEach(() => {
|
|
mockDb = {
|
|
query: vi.fn(),
|
|
}
|
|
|
|
mockContext = {
|
|
db: mockDb as any,
|
|
user: {
|
|
id: 'user-1',
|
|
email: 'test@example.com',
|
|
name: 'Test User',
|
|
role: 'ADMIN',
|
|
},
|
|
} as Context
|
|
})
|
|
|
|
describe('detectAnomalies', () => {
|
|
it('should detect spikes in metrics', async () => {
|
|
// Mock metrics data with a spike
|
|
const baseValue = 50
|
|
const spikeValue = 200
|
|
const metrics = Array.from({ length: 20 }, (_, i) => ({
|
|
timestamp: new Date(Date.now() - (20 - i) * 60000),
|
|
value: i === 15 ? spikeValue.toString() : baseValue.toString(),
|
|
labels: {},
|
|
}))
|
|
|
|
mockDb.query
|
|
.mockResolvedValueOnce({ rows: metrics })
|
|
.mockResolvedValue({ rows: [] }) // For storing anomalies
|
|
|
|
const anomalies = await detectAnomalies(mockContext, {
|
|
resourceId: 'resource-1',
|
|
metricType: 'CPU_USAGE',
|
|
sensitivity: 'MEDIUM',
|
|
})
|
|
|
|
expect(anomalies.length).toBeGreaterThan(0)
|
|
expect(anomalies.some((a) => a.anomalyType === 'SPIKE')).toBe(true)
|
|
})
|
|
|
|
it('should detect drops in metrics', async () => {
|
|
const baseValue = 50
|
|
const dropValue = 5
|
|
const metrics = Array.from({ length: 20 }, (_, i) => ({
|
|
timestamp: new Date(Date.now() - (20 - i) * 60000),
|
|
value: i === 15 ? dropValue.toString() : baseValue.toString(),
|
|
labels: {},
|
|
}))
|
|
|
|
mockDb.query
|
|
.mockResolvedValueOnce({ rows: metrics })
|
|
.mockResolvedValue({ rows: [] })
|
|
|
|
const anomalies = await detectAnomalies(mockContext, {
|
|
resourceId: 'resource-1',
|
|
metricType: 'CPU_USAGE',
|
|
})
|
|
|
|
expect(anomalies.some((a) => a.anomalyType === 'DROP')).toBe(true)
|
|
})
|
|
|
|
it('should return empty array when insufficient data', async () => {
|
|
mockDb.query.mockResolvedValue({ rows: Array.from({ length: 5 }) })
|
|
|
|
const anomalies = await detectAnomalies(mockContext, {
|
|
resourceId: 'resource-1',
|
|
metricType: 'CPU_USAGE',
|
|
})
|
|
|
|
expect(anomalies).toEqual([])
|
|
})
|
|
})
|
|
|
|
describe('getAnomalies', () => {
|
|
it('should retrieve stored anomalies', async () => {
|
|
const mockAnomalies = [
|
|
{
|
|
id: 'anomaly-1',
|
|
resource_id: 'resource-1',
|
|
metric_type: 'CPU_USAGE',
|
|
severity: 'HIGH',
|
|
anomaly_type: 'SPIKE',
|
|
value: '200',
|
|
expected_value: '50',
|
|
deviation: '300',
|
|
timestamp: new Date(),
|
|
description: 'CPU spike detected',
|
|
recommendation: 'Scale up resources',
|
|
},
|
|
]
|
|
|
|
mockDb.query.mockResolvedValue({ rows: mockAnomalies })
|
|
|
|
const anomalies = await getAnomalies(mockContext, 'resource-1')
|
|
|
|
expect(anomalies).toHaveLength(1)
|
|
expect(anomalies[0].severity).toBe('HIGH')
|
|
})
|
|
})
|
|
})
|
|
|