Files
awoooi/apps/web/tests/e2e/action-log.spec.ts
OG T 196d269b92 feat: add all application source code
- apps/api: FastAPI backend with Dockerfile
- apps/web: Next.js frontend with Dockerfile
- apps/sensor: Signal collection agent
- packages: shared packages

Co-Authored-By: Claude <noreply@anthropic.com>
2026-03-22 18:57:44 +08:00

161 lines
5.3 KiB
TypeScript

import { test, expect } from '@playwright/test'
/**
* Action Log 頁面測試
* ====================
* Phase 4: 行動日誌 E2E 測試
*
* 測試項目:
* 1. 頁面正確載入
* 2. i18n 標題顯示正確
* 3. 統計卡片顯示
* 4. 表格結構正確
* 5. 分頁控制項存在
*/
test.describe('Action Log 頁面測試', () => {
test.setTimeout(60000)
test('繁體中文頁面 - 基本元素驗證', async ({ page }) => {
// 1. 導覽至 Action Log 頁面
await page.goto('/zh-TW/action-logs', { waitUntil: 'domcontentloaded' })
// 等待主要內容渲染 (使用 main 作為等待目標,更可靠)
await page.waitForSelector('main', { timeout: 15000 })
await page.waitForTimeout(2000) // 等待 hydration
// 截圖: 初始頁面
await page.screenshot({
path: 'test-results/screenshots/action-log-01-zh-TW-initial.png',
fullPage: true,
})
// 2. 驗證頁面標題為繁體中文「行動日誌」(h2 或 h3)
const pageTitle = page.locator('h2, h3').filter({ hasText: '行動日誌' }).first()
await expect(pageTitle).toBeVisible({ timeout: 10000 })
// 3. 驗證副標題
const subtitle = page.locator('text=K8s 操作執行稽核軌跡')
await expect(subtitle).toBeVisible()
// 4. 驗證頁面結構 - 有 main 內容區域
const mainContent = page.locator('main')
await expect(mainContent).toBeVisible()
// 截圖: 頁面結構
await page.screenshot({
path: 'test-results/screenshots/action-log-02-page-structure.png',
})
})
test('英文頁面 - 基本元素驗證', async ({ page }) => {
// 導覽至英文 Action Log 頁面
await page.goto('/en/action-logs', { waitUntil: 'domcontentloaded' })
await page.waitForSelector('h2', { timeout: 15000 })
await page.waitForTimeout(2000)
// 截圖: 英文頁面
await page.screenshot({
path: 'test-results/screenshots/action-log-03-en-initial.png',
fullPage: true,
})
// 驗證英文標題
const pageTitle = page.locator('h2').filter({ hasText: 'Action Log' })
await expect(pageTitle).toBeVisible({ timeout: 10000 })
// 驗證英文副標題
const subtitle = page.locator('text=K8s Operation Execution Audit Trail')
await expect(subtitle).toBeVisible()
})
test('資料狀態顯示 - 顯示空狀態、表格或錯誤訊息', async ({ page }) => {
// 導覽至 Action Log 頁面
await page.goto('/zh-TW/action-logs', { waitUntil: 'domcontentloaded' })
await page.waitForSelector('main', { timeout: 15000 })
await page.waitForTimeout(3000) // 等待 API 回應
// 截圖: 當前狀態
await page.screenshot({
path: 'test-results/screenshots/action-log-04-data-state.png',
fullPage: true,
})
// 檢查各種可能的狀態
const emptyState = page.locator('text=目前沒有執行紀錄')
const table = page.locator('table')
const errorState = page.locator('text=無法取得稽核日誌')
const loadingState = page.locator('text=載入中')
// 至少一個狀態元素可見 (資料、空、錯誤或載入中)
const hasEmptyState = await emptyState.isVisible()
const hasTable = await table.isVisible()
const hasError = await errorState.isVisible()
const hasLoading = await loadingState.isVisible()
// 驗證頁面正確處理了各種狀態
expect(hasEmptyState || hasTable || hasError || hasLoading).toBeTruthy()
})
test('側邊欄導航 - 行動日誌連結可點擊', async ({ page }) => {
// 先導覽至首頁
await page.goto('/zh-TW/demo', { waitUntil: 'domcontentloaded' })
await page.waitForSelector('h1', { timeout: 15000 })
await page.waitForTimeout(2000)
// 截圖: 首頁
await page.screenshot({
path: 'test-results/screenshots/action-log-05-before-nav.png',
})
// 找到側邊欄中的「行動日誌」連結
const actionLogLink = page.locator('a').filter({ hasText: '行動日誌' })
await expect(actionLogLink).toBeVisible()
// 點擊導航到 Action Log 頁面
await actionLogLink.click()
// 等待導航完成
await page.waitForURL('**/action-logs', { timeout: 15000 })
await page.waitForSelector('h2', { timeout: 15000 })
await page.waitForTimeout(2000)
// 截圖: 導航後
await page.screenshot({
path: 'test-results/screenshots/action-log-06-after-nav.png',
fullPage: true,
})
// 驗證標題
const pageTitle = page.locator('h2').filter({ hasText: '行動日誌' })
await expect(pageTitle).toBeVisible({ timeout: 10000 })
})
test('重新整理按鈕存在且可點擊', async ({ page }) => {
await page.goto('/zh-TW/action-logs', { waitUntil: 'domcontentloaded' })
await page.waitForSelector('h2', { timeout: 15000 })
await page.waitForTimeout(2000)
// 找到重新整理按鈕
const refreshButton = page.locator('button').filter({ hasText: '重新整理' })
await expect(refreshButton).toBeVisible()
// 截圖: 點擊前
await page.screenshot({
path: 'test-results/screenshots/action-log-07-before-refresh.png',
})
// 點擊重新整理
await refreshButton.click()
await page.waitForTimeout(1000)
// 截圖: 點擊後
await page.screenshot({
path: 'test-results/screenshots/action-log-08-after-refresh.png',
})
// 按鈕仍然存在
await expect(refreshButton).toBeVisible()
})
})