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:
63
products/06-runbook-automation/saas/tests/unit/api.test.ts
Normal file
63
products/06-runbook-automation/saas/tests/unit/api.test.ts
Normal file
@@ -0,0 +1,63 @@
|
||||
import { describe, it, expect } from 'vitest';
|
||||
|
||||
describe('Runbook API Validation', () => {
|
||||
it('rejects empty runbook name', () => {
|
||||
const name = '';
|
||||
expect(name.length >= 1).toBe(false);
|
||||
});
|
||||
|
||||
it('accepts valid runbook name', () => {
|
||||
const name = 'restart-ecs-service';
|
||||
expect(name.length >= 1 && name.length <= 200).toBe(true);
|
||||
});
|
||||
|
||||
it('requires yaml_content', () => {
|
||||
const body = { name: 'test', description: 'desc' };
|
||||
expect(body).not.toHaveProperty('yaml_content');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Approval Decisions', () => {
|
||||
it('only allows approve or reject', () => {
|
||||
const valid = ['approve', 'reject'];
|
||||
expect(valid.includes('approve')).toBe(true);
|
||||
expect(valid.includes('reject')).toBe(true);
|
||||
expect(valid.includes('maybe')).toBe(false);
|
||||
});
|
||||
|
||||
it('reason is optional and max 500 chars', () => {
|
||||
const shortReason = 'Looks safe';
|
||||
const longReason = 'x'.repeat(501);
|
||||
expect(shortReason.length <= 500).toBe(true);
|
||||
expect(longReason.length <= 500).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Execution Status Machine', () => {
|
||||
const validStatuses = ['pending', 'running', 'awaiting_approval', 'completed', 'failed', 'aborted'];
|
||||
|
||||
it('starts in pending', () => {
|
||||
expect(validStatuses[0]).toBe('pending');
|
||||
});
|
||||
|
||||
it('validates all status values', () => {
|
||||
for (const s of validStatuses) {
|
||||
expect(validStatuses.includes(s)).toBe(true);
|
||||
}
|
||||
expect(validStatuses.includes('cancelled')).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Slack Signature Verification', () => {
|
||||
it('rejects stale timestamps (>5 min)', () => {
|
||||
const now = Math.floor(Date.now() / 1000);
|
||||
const staleTs = now - 301;
|
||||
expect(Math.abs(now - staleTs) > 300).toBe(true);
|
||||
});
|
||||
|
||||
it('accepts fresh timestamps', () => {
|
||||
const now = Math.floor(Date.now() / 1000);
|
||||
const freshTs = now - 10;
|
||||
expect(Math.abs(now - freshTs) > 300).toBe(false);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user