Files
awoooi/apps/web/tests/e2e/approval-card-verify.spec.ts
OG T 9bff46a1b0 feat: integrate Sentry + fix CI/CD issues
Sentry Integration (補強 SignOz):
- Add @sentry/nextjs for frontend error tracking + session replay
- Add sentry-sdk[fastapi] for backend error tracking
- Create sentry.client/server/edge.config.ts
- Integrate with next.config.js + instrumentation.ts
- Add Sentry exception capture in FastAPI error handler
- Create deployment scripts for Self-Hosted @ 192.168.0.110

CI/CD Fixes:
- Fix F821 Undefined name 'Field' in incidents.py
- Add NEXT_PUBLIC_API_URL env var to CI build step
- Add build-arg to Docker build verification

E2E Test Improvements:
- Fix strict mode violations in dashboard-acceptance tests
- Add timeout increase for Phase 4 demo tests
- Make tests more resilient to UI variations

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-24 15:19:52 +08:00

60 lines
2.1 KiB
TypeScript

/**
* AWOOOI 自動化 QA - ApprovalCard 渲染驗證
* =========================================
* 驗證待簽核卡片是否正確顯示在戰情室
*/
import { test, expect } from '@playwright/test'
test.describe('ApprovalCard 即時驗證', () => {
test('待簽核卡片應顯示在右側 AI 面板', async ({ page }) => {
// Navigate to dashboard (skip networkidle due to SSE)
await page.goto('/zh-TW')
await page.waitForLoadState('domcontentloaded')
// Wait for OpenClaw state machine to fetch data (max 10s)
await page.waitForTimeout(3000)
// Take screenshot for evidence
await page.screenshot({
path: 'test-results/approval-card-check.png',
fullPage: true,
})
// Check machine state
const stateLabel = page.locator('text=STATE:')
await expect(stateLabel).toBeVisible()
// Look for approval-related elements
const aiPanel = page.locator('[class*="DataPincerPanel"]').last()
// Check if approval card is visible (look for key indicators)
const hasApprovalCard =
(await page.locator('text=/PostgreSQL|重新啟動|CRITICAL/i').count()) > 0 ||
(await page.locator('text=/awaiting_approval/i').count()) > 0
// Log findings
const stateText = await page.locator('text=/idle|thinking|awaiting_approval/').first().textContent()
console.log(`[QA] Machine State: ${stateText}`)
console.log(`[QA] ApprovalCard visible: ${hasApprovalCard}`)
// If no card, try manual refresh
if (!hasApprovalCard) {
console.log('[QA] Clicking REFRESH button...')
const refreshBtn = page.locator('button:has-text("REFRESH")')
if (await refreshBtn.isVisible()) {
await refreshBtn.click()
await page.waitForTimeout(2000)
await page.screenshot({
path: 'test-results/approval-card-after-refresh.png',
fullPage: true,
})
}
}
// Final state check
const finalState = await page.locator('[class*="uppercase"]').filter({ hasText: /idle|thinking|awaiting_approval/ }).first().textContent()
console.log(`[QA] Final Machine State: ${finalState?.trim()}`)
})
})