import { test, expect } from '@playwright/test'; /** * Phase 4: Action Timeline 完整流程驗證 * ===================================== * 模擬: AI 提案 ➡️ DevOps 被拒絕 ➡️ CTO 成功批准 */ test('Phase 4: Full Action Timeline Demo Flow', async ({ page }) => { // 增加超時到 60 秒 (互動式 demo 需要更長時間) test.setTimeout(60000) // Set larger viewport await page.setViewportSize({ width: 1920, height: 1200 }); // Navigate to demo page (使用相對路徑,baseURL 由 playwright.config.ts 控制) await page.goto('/zh-TW/demo'); await page.waitForTimeout(4000); // Screenshot 1: Initial state await page.screenshot({ path: 'test-results/phase4-01-initial.png', fullPage: true }); // Step 1: Trigger a CRITICAL alert (AI Decision) - use Chinese text console.log('Step 1: Triggering CRITICAL alert...'); // The button says "+ 嚴重" in Chinese const criticalButton = page.locator('button:has-text("嚴重")').first(); await criticalButton.click({ timeout: 5000 }); await page.waitForTimeout(4000); // Wait for AI thinking animation // Screenshot 2: After AI decision await page.evaluate(() => window.scrollTo(0, 400)); await page.waitForTimeout(500); await page.screenshot({ path: 'test-results/phase4-02-ai-decision.png' }); // Scroll to see approval cards await page.evaluate(() => window.scrollTo(0, 500)); await page.waitForTimeout(1000); // Screenshot 3: Approval cards visible await page.screenshot({ path: 'test-results/phase4-03-approval-cards.png' }); // Step 2: Try to approve as DevOps (should be denied) console.log('Step 2: DevOps attempting to sign CRITICAL...'); // Look for the hold-to-approve button const approveButton = page.locator('button:has-text("長按批准")').first(); // Try to click and hold if (await approveButton.isVisible()) { const box = await approveButton.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); // Hold for 2.5 seconds await page.mouse.up(); } } await page.waitForTimeout(500); // Screenshot 4: Access Denied modal (should be visible) await page.screenshot({ path: 'test-results/phase4-04-access-denied.png' }); // Close the modal if visible const closeButton = page.locator('button:has-text("了解,返回")'); if (await closeButton.isVisible()) { await closeButton.click(); await page.waitForTimeout(500); } // Step 3: Switch to CTO role console.log('Step 3: Switching to CTO role...'); await page.evaluate(() => window.scrollTo(0, document.body.scrollHeight)); await page.waitForTimeout(500); const ctoButton = page.locator('button:has-text("CTO")'); await ctoButton.click(); await page.waitForTimeout(500); // Screenshot 5: Role switched to CTO await page.screenshot({ path: 'test-results/phase4-05-cto-role.png' }); // Scroll back to approval cards await page.evaluate(() => window.scrollTo(0, 500)); await page.waitForTimeout(500); // Step 4: CTO approves (should succeed) console.log('Step 4: CTO signing CRITICAL...'); const approveButtonCTO = page.locator('button:has-text("長按批准")').first(); if (await approveButtonCTO.isVisible()) { const box = await approveButtonCTO.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 6: After CTO signature await page.screenshot({ path: 'test-results/phase4-06-cto-signed.png' }); // Final screenshot with full page showing timeline await page.screenshot({ path: 'test-results/phase4-07-final.png', fullPage: true }); console.log('Phase 4 demo flow completed!'); });