feat(ops): protect metrics, rate-limit auth, agent secret timing, e2e smoke
Bearer для /metrics (EVOBGP_METRICS_TOKEN); rate limit /v1/auth/config; constant-time agent secret; OTel stub; Playwright smoke; HTTP_PROXY note; checklist обновлён. Co-authored-by: Cursor <[email protected]>
This commit is contained in:
@@ -0,0 +1,32 @@
|
||||
import { test, expect } from '@playwright/test'
|
||||
|
||||
/**
|
||||
* Smoke against local API (+ optional UI). Profile: compose microvps-full.
|
||||
*
|
||||
* Env:
|
||||
* - EVOBGP_E2E_API_URL (default http://127.0.0.1:8080)
|
||||
* - EVOBGP_E2E_BASE_URL (default http://127.0.0.1:5173)
|
||||
* - EVOBGP_E2E_TOKEN (default dev)
|
||||
*/
|
||||
const apiBase = process.env.EVOBGP_E2E_API_URL ?? 'http://127.0.0.1:8080'
|
||||
const uiBase = process.env.EVOBGP_E2E_BASE_URL ?? 'http://127.0.0.1:5173'
|
||||
const token = process.env.EVOBGP_E2E_TOKEN ?? 'dev'
|
||||
|
||||
test.describe('EvoBGP smoke', () => {
|
||||
test('API health and modules list', async ({ request }) => {
|
||||
const health = await request.get(`${apiBase}/v1/health`)
|
||||
expect(health.ok()).toBeTruthy()
|
||||
|
||||
const mods = await request.get(`${apiBase}/v1/modules?limit=10`, {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
})
|
||||
expect([200, 401]).toContain(mods.status())
|
||||
})
|
||||
|
||||
test('UI loads when available', async ({ page }) => {
|
||||
test.skip(!process.env.EVOBGP_E2E_UI, 'set EVOBGP_E2E_UI=1 to enable UI smoke')
|
||||
await page.goto(uiBase)
|
||||
await page.waitForLoadState('domcontentloaded')
|
||||
await expect(page.locator('body')).toBeVisible()
|
||||
})
|
||||
})
|
||||
@@ -10,6 +10,7 @@
|
||||
"typecheck": "tsr generate && tsc --noEmit",
|
||||
"lint": "eslint .",
|
||||
"test": "vitest run",
|
||||
"test:e2e": "playwright test",
|
||||
"openapi:gen": "openapi-typescript ../../docs/openapi.yaml -o src/types/api.gen.ts",
|
||||
"openapi:check": "openapi-typescript ../../docs/openapi.yaml -o src/types/api.gen.check.ts && diff -q src/types/api.gen.ts src/types/api.gen.check.ts && rm -f src/types/api.gen.check.ts"
|
||||
},
|
||||
@@ -43,6 +44,7 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint/js": "^9.0.0",
|
||||
"@playwright/test": "^1.62.1",
|
||||
"@tailwindcss/vite": "^4.1.0",
|
||||
"@tanstack/router-cli": "^1.130.0",
|
||||
"@tanstack/router-plugin": "^1.130.0",
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
import { defineConfig, devices } from '@playwright/test'
|
||||
|
||||
export default defineConfig({
|
||||
testDir: './e2e',
|
||||
timeout: 60_000,
|
||||
fullyParallel: false,
|
||||
forbidOnly: !!process.env.CI,
|
||||
retries: process.env.CI ? 1 : 0,
|
||||
use: {
|
||||
baseURL: process.env.EVOBGP_E2E_BASE_URL ?? 'http://127.0.0.1:5173',
|
||||
trace: 'on-first-retry',
|
||||
},
|
||||
projects: [{ name: 'chromium', use: { ...devices['Desktop Chrome'] } }],
|
||||
})
|
||||
File diff suppressed because one or more lines are too long
@@ -35,5 +35,6 @@ export default defineConfig({
|
||||
test: {
|
||||
environment: 'happy-dom',
|
||||
globals: true,
|
||||
exclude: ['**/node_modules/**', '**/e2e/**', '**/dist/**'],
|
||||
},
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user