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>
60 lines
2.1 KiB
TypeScript
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()}`)
|
|
})
|
|
})
|