Add unit tests for P2 SaaS, P3 notifications, P4 search, P5 ingestion, P6 API

- P2: nonce validation, severity levels, RLS withTenant
- P3: notification dispatcher severity gating, Slack Block Kit emoji mapping
- P4: Meilisearch fallback, service CRUD validation, staged update actions
- P5: cost ingestion validation, snooze range, optimistic locking
- P6: runbook API validation, approval decisions, execution status machine, Slack signature
This commit is contained in:
2026-03-01 03:15:31 +00:00
parent 3326d9a714
commit bbbea3519e
5 changed files with 276 additions and 0 deletions

View File

@@ -0,0 +1,65 @@
import { describe, it, expect } from 'vitest';
// Mock withTenant for unit tests
const mockQuery = vi.fn();
const mockClient = {
query: mockQuery,
};
vi.mock('../../src/data/db.js', () => ({
pool: {},
withTenant: vi.fn(async (_tenantId: string, fn: any) => fn(mockClient)),
}));
import { vi } from 'vitest';
describe('Ingestion Endpoint', () => {
it('validates nonce format (UUID v4)', () => {
const validNonce = '550e8400-e29b-41d4-a716-446655440000';
const invalidNonce = 'not-a-uuid';
const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
expect(uuidRegex.test(validNonce)).toBe(true);
expect(uuidRegex.test(invalidNonce)).toBe(false);
});
it('rejects duplicate nonces', () => {
const seen = new Set<string>();
const nonce = '550e8400-e29b-41d4-a716-446655440000';
expect(seen.has(nonce)).toBe(false);
seen.add(nonce);
expect(seen.has(nonce)).toBe(true); // Duplicate detected
});
});
describe('Drift Report Schema', () => {
it('validates severity levels', () => {
const validSeverities = ['critical', 'high', 'medium', 'low'];
const invalid = 'extreme';
for (const s of validSeverities) {
expect(['critical', 'high', 'medium', 'low'].includes(s)).toBe(true);
}
expect(['critical', 'high', 'medium', 'low'].includes(invalid)).toBe(false);
});
it('requires tenant_id in report', () => {
const report = { stack_name: 'prod', resources: [] };
expect(report).not.toHaveProperty('tenant_id');
const validReport = { ...report, tenant_id: 'abc-123' };
expect(validReport).toHaveProperty('tenant_id');
});
});
describe('RLS withTenant', () => {
it('sets and resets tenant context', async () => {
const { withTenant } = await import('../../src/data/db.js');
await withTenant('tenant-1', async (client: any) => {
// Inside the transaction, tenant context should be set
expect(client.query).toBeDefined();
});
});
});