Spaces:
Runtime error
Runtime error
| import { test, expect } from '@playwright/test' | |
| import { API_KEY_HEADER } from './helpers' | |
| test.describe('Exec Approval Allowlist API', () => { | |
| // ββ GET /api/exec-approvals?action=allowlist ββ | |
| test('GET allowlist returns agents map and hash', async ({ request }) => { | |
| const res = await request.get('/api/exec-approvals?action=allowlist', { | |
| headers: API_KEY_HEADER, | |
| }) | |
| expect(res.status()).toBe(200) | |
| const body = await res.json() | |
| expect(body).toHaveProperty('agents') | |
| expect(typeof body.agents).toBe('object') | |
| expect(body).toHaveProperty('hash') | |
| expect(typeof body.hash).toBe('string') | |
| }) | |
| // ββ PUT /api/exec-approvals (save allowlist) ββ | |
| test('PUT save-allowlist persists and round-trips', async ({ request }) => { | |
| // Read current state to get hash | |
| const getRes = await request.get('/api/exec-approvals?action=allowlist', { | |
| headers: API_KEY_HEADER, | |
| }) | |
| expect(getRes.status()).toBe(200) | |
| const current = await getRes.json() | |
| // Save with a test agent pattern | |
| const testAgent = `e2e-test-agent-${Date.now()}` | |
| const putRes = await request.put('/api/exec-approvals', { | |
| headers: API_KEY_HEADER, | |
| data: { | |
| agents: { [testAgent]: [{ pattern: 'echo *' }] }, | |
| hash: current.hash, | |
| }, | |
| }) | |
| expect(putRes.status()).toBe(200) | |
| const putBody = await putRes.json() | |
| expect(putBody.ok).toBe(true) | |
| expect(putBody.hash).toBeDefined() | |
| // Read back and verify | |
| const verifyRes = await request.get('/api/exec-approvals?action=allowlist', { | |
| headers: API_KEY_HEADER, | |
| }) | |
| expect(verifyRes.status()).toBe(200) | |
| const verifyBody = await verifyRes.json() | |
| expect(verifyBody.agents[testAgent]).toBeDefined() | |
| expect(verifyBody.agents[testAgent]).toEqual([{ pattern: 'echo *' }]) | |
| // Clean up: remove the test agent by saving empty patterns | |
| await request.put('/api/exec-approvals', { | |
| headers: API_KEY_HEADER, | |
| data: { | |
| agents: { [testAgent]: [] }, | |
| hash: verifyBody.hash, | |
| }, | |
| }) | |
| }) | |
| test('PUT save-allowlist with stale hash returns 409', async ({ request }) => { | |
| const res = await request.put('/api/exec-approvals', { | |
| headers: API_KEY_HEADER, | |
| data: { | |
| agents: { 'conflict-agent': [{ pattern: 'test' }] }, | |
| hash: 'stale-hash-value-that-does-not-match', | |
| }, | |
| }) | |
| // 409 if the file exists and hash mismatches; 200 if file doesn't exist (no conflict possible) | |
| if (res.status() === 409) { | |
| const body = await res.json() | |
| expect(body.code).toBe('CONFLICT') | |
| } else { | |
| // File didn't exist, so no conflict β clean up | |
| expect(res.status()).toBe(200) | |
| const body = await res.json() | |
| // Re-read and clean up the test entry | |
| const getRes = await request.get('/api/exec-approvals?action=allowlist', { | |
| headers: API_KEY_HEADER, | |
| }) | |
| const current = await getRes.json() | |
| await request.put('/api/exec-approvals', { | |
| headers: API_KEY_HEADER, | |
| data: { | |
| agents: { 'conflict-agent': [] }, | |
| hash: current.hash, | |
| }, | |
| }) | |
| } | |
| }) | |
| test('PUT save-allowlist rejects missing agents field', async ({ request }) => { | |
| const res = await request.put('/api/exec-approvals', { | |
| headers: API_KEY_HEADER, | |
| data: {}, | |
| }) | |
| expect(res.status()).toBe(400) | |
| const body = await res.json() | |
| expect(body.error).toContain('agents') | |
| }) | |
| // ββ GET /api/exec-approvals (pending approvals) ββ | |
| test('GET pending approvals returns array or empty on gateway unavailable', async ({ request }) => { | |
| const res = await request.get('/api/exec-approvals', { headers: API_KEY_HEADER }) | |
| expect(res.status()).toBe(200) | |
| const body = await res.json() | |
| // Returns { approvals: [] } when gateway is unavailable | |
| expect(body).toHaveProperty('approvals') | |
| expect(Array.isArray(body.approvals)).toBe(true) | |
| }) | |
| // ββ Auth ββββββββββββββββββββββββββββββββββββββ | |
| test('GET without auth is rejected', async ({ request }) => { | |
| const res = await request.get('/api/exec-approvals?action=allowlist') | |
| expect(res.status()).toBe(401) | |
| }) | |
| test('PUT without auth is rejected', async ({ request }) => { | |
| const res = await request.put('/api/exec-approvals', { | |
| data: { agents: {} }, | |
| }) | |
| expect(res.status()).toBe(401) | |
| }) | |
| test('POST without auth is rejected', async ({ request }) => { | |
| const res = await request.post('/api/exec-approvals', { | |
| data: { id: 'test', action: 'approve' }, | |
| }) | |
| expect(res.status()).toBe(401) | |
| }) | |
| }) | |