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>
98 lines
3.5 KiB
TypeScript
98 lines
3.5 KiB
TypeScript
import { test } from '@playwright/test';
|
|
|
|
/**
|
|
* Phase 4: Alpha 版最終火力展示
|
|
* =============================
|
|
* 模擬完整流程:
|
|
* 1. [SYSTEM] 接收告警
|
|
* 2. [AGENT] OpenClaw 分析完成
|
|
* 3. [SECURITY] DevOps Access Denied
|
|
* 4. [HUMAN] CTO 成功簽核
|
|
*/
|
|
|
|
test('Phase 4 Alpha Demo - Full Flow', async ({ page }) => {
|
|
// 增加超時到 60 秒 (互動式 demo 需要更長時間)
|
|
test.setTimeout(60000)
|
|
await page.setViewportSize({ width: 1920, height: 1200 });
|
|
|
|
// Navigate
|
|
await page.goto('http://localhost:3000/zh-TW/demo');
|
|
await page.waitForTimeout(4000);
|
|
|
|
// Screenshot 1: Initial state with approval cards
|
|
await page.screenshot({ path: 'test-results/phase4-alpha-01-initial.png', fullPage: true });
|
|
|
|
// Step 1: Trigger CRITICAL alert (generates SYSTEM + AGENT events)
|
|
console.log('[Demo] Step 1: Triggering CRITICAL alert...');
|
|
const triggerBtn = page.locator('button:has-text("嚴重")').first();
|
|
if (await triggerBtn.isVisible({ timeout: 3000 })) {
|
|
await triggerBtn.click();
|
|
await page.waitForTimeout(5000); // Wait for AI thinking animation
|
|
}
|
|
|
|
// Screenshot 2: After AI analysis
|
|
await page.screenshot({ path: 'test-results/phase4-alpha-02-ai-analysis.png', fullPage: true });
|
|
|
|
// Step 2: DevOps tries to sign CRITICAL (generates SECURITY event)
|
|
console.log('[Demo] Step 2: DevOps attempting CRITICAL sign...');
|
|
await page.evaluate(() => window.scrollTo(0, 500));
|
|
await page.waitForTimeout(500);
|
|
|
|
const approveBtn = page.locator('button:has-text("長按")').first();
|
|
if (await approveBtn.isVisible({ timeout: 3000 })) {
|
|
const box = await approveBtn.boundingBox();
|
|
if (box) {
|
|
await page.mouse.move(box.x + box.width / 2, box.y + box.height / 2);
|
|
await page.mouse.down();
|
|
await page.waitForTimeout(2500);
|
|
await page.mouse.up();
|
|
}
|
|
}
|
|
await page.waitForTimeout(1000);
|
|
|
|
// Screenshot 3: Access Denied
|
|
await page.screenshot({ path: 'test-results/phase4-alpha-03-access-denied.png' });
|
|
|
|
// Close modal
|
|
const closeBtn = page.locator('button:has-text("了解")');
|
|
if (await closeBtn.isVisible({ timeout: 2000 })) {
|
|
await closeBtn.click();
|
|
await page.waitForTimeout(500);
|
|
}
|
|
|
|
// Step 3: Switch to CTO
|
|
console.log('[Demo] Step 3: Switching to CTO...');
|
|
const ctoBtn = page.locator('button:has-text("CTO")').first();
|
|
await ctoBtn.scrollIntoViewIfNeeded();
|
|
await ctoBtn.click();
|
|
await page.waitForTimeout(500);
|
|
|
|
// Screenshot 4: CTO role active
|
|
await page.screenshot({ path: 'test-results/phase4-alpha-04-cto-role.png', fullPage: true });
|
|
|
|
// Step 4: CTO signs (generates HUMAN event)
|
|
console.log('[Demo] Step 4: CTO signing...');
|
|
await page.evaluate(() => window.scrollTo(0, 500));
|
|
const approveBtnCTO = page.locator('button:has-text("長按")').first();
|
|
if (await approveBtnCTO.isVisible({ timeout: 3000 })) {
|
|
const box = await approveBtnCTO.boundingBox();
|
|
if (box) {
|
|
await page.mouse.move(box.x + box.width / 2, box.y + box.height / 2);
|
|
await page.mouse.down();
|
|
await page.waitForTimeout(2500);
|
|
await page.mouse.up();
|
|
}
|
|
}
|
|
await page.waitForTimeout(1500);
|
|
|
|
// Screenshot 5: After CTO signature
|
|
await page.screenshot({ path: 'test-results/phase4-alpha-05-cto-signed.png', fullPage: true });
|
|
|
|
// Final: Full page with timeline
|
|
await page.evaluate(() => window.scrollTo(0, 0));
|
|
await page.waitForTimeout(500);
|
|
await page.screenshot({ path: 'test-results/phase4-alpha-final.png', fullPage: true });
|
|
|
|
console.log('[Demo] Phase 4 Alpha Demo completed!');
|
|
});
|