feat: add comprehensive E2E tests with Docker workflow

- Add comprehensive.e2e.test.ts: Full E2E tests covering 25+ converters
- Add format-matrix.e2e.test.ts: Format conversion matrix (70,000+ combinations)
- Add translation.e2e.test.ts: Multi-language translation tests (14 languages)
- Add docker-e2e-tests.yml: GitHub Actions workflow for Docker E2E tests
- Update run-bun-test.yml: Improved basic test workflow
- Add run-e2e-tests.sh: Local test runner script
- Add test scripts to package.json

Tests cover:
- Image formats (Inkscape, ImageMagick, Potrace, etc.)
- Document formats (Pandoc, LibreOffice, Calibre)
- Data formats (Dasel: JSON/YAML/TOML/XML/CSV)
- Translation (PDFMathTranslate, BabelDOC)
- Edge cases (Unicode, long content, special characters)
This commit is contained in:
Your Name 2026-01-23 12:20:52 +08:00
parent 3457311f14
commit e327345ad7
9 changed files with 2954 additions and 3 deletions

326
scripts/run-e2e-tests.sh Normal file
View file

@ -0,0 +1,326 @@
#!/bin/bash
# =============================================================================
# E2E 測試運行腳本
# E2E Test Runner Script
# =============================================================================
#
# 使用方式:
# ./scripts/run-e2e-tests.sh [選項]
#
# 選項:
# --all 運行所有 E2E 測試
# --quick 只運行快速測試(跳過翻譯)
# --matrix 只運行格式矩陣測試
# --translation 只運行翻譯測試
# --comprehensive 運行全面測試
# --report 生成 HTML 報告
#
# =============================================================================
set -e
# 顏色定義
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# 腳本目錄
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(dirname "$SCRIPT_DIR")"
# 輸出目錄
OUTPUT_DIR="$PROJECT_ROOT/tests/e2e/output"
# 確保輸出目錄存在
mkdir -p "$OUTPUT_DIR"
# 打印標題
print_header() {
echo ""
echo -e "${BLUE}================================================================${NC}"
echo -e "${BLUE} $1${NC}"
echo -e "${BLUE}================================================================${NC}"
echo ""
}
# 打印成功訊息
print_success() {
echo -e "${GREEN}$1${NC}"
}
# 打印警告訊息
print_warning() {
echo -e "${YELLOW}$1${NC}"
}
# 打印錯誤訊息
print_error() {
echo -e "${RED}$1${NC}"
}
# 檢查依賴
check_dependencies() {
print_header "檢查測試依賴 Checking Dependencies"
local missing=0
# 檢查 bun
if command -v bun &> /dev/null; then
print_success "bun $(bun --version)"
else
print_error "bun not found"
missing=$((missing + 1))
fi
# 檢查常用轉換工具
local tools=("inkscape" "pandoc" "ffmpeg" "magick" "soffice")
for tool in "${tools[@]}"; do
if command -v "$tool" &> /dev/null; then
print_success "$tool found"
else
print_warning "$tool not found (some tests may be skipped)"
fi
done
# 檢查翻譯工具
local translators=("pdf2zh" "babeldoc")
for translator in "${translators[@]}"; do
if command -v "$translator" &> /dev/null; then
print_success "$translator found"
else
print_warning "$translator not found (translation tests will be skipped)"
fi
done
if [ $missing -gt 0 ]; then
print_error "Missing required dependencies"
exit 1
fi
echo ""
}
# 運行快速測試
run_quick_tests() {
print_header "運行快速 E2E 測試 Running Quick E2E Tests"
cd "$PROJECT_ROOT"
bun test tests/e2e/converters.e2e.test.ts --timeout 120000
}
# 運行格式矩陣測試
run_matrix_tests() {
print_header "運行格式矩陣測試 Running Format Matrix Tests"
cd "$PROJECT_ROOT"
bun test tests/e2e/format-matrix.e2e.test.ts --timeout 300000
}
# 運行翻譯測試
run_translation_tests() {
print_header "運行翻譯測試 Running Translation Tests"
# 檢查 API 金鑰
if [ -z "$OPENAI_API_KEY" ] && [ -z "$GOOGLE_API_KEY" ] && [ -z "$DEEPL_API_KEY" ]; then
print_warning "No translation API keys found. Some tests may fail."
print_warning "Set OPENAI_API_KEY, GOOGLE_API_KEY, or DEEPL_API_KEY"
fi
cd "$PROJECT_ROOT"
bun test tests/e2e/translation.e2e.test.ts --timeout 600000
}
# 運行全面測試
run_comprehensive_tests() {
print_header "運行全面 E2E 測試 Running Comprehensive E2E Tests"
cd "$PROJECT_ROOT"
bun test tests/e2e/comprehensive.e2e.test.ts --timeout 600000
}
# 運行所有測試
run_all_tests() {
print_header "運行所有 E2E 測試 Running All E2E Tests"
cd "$PROJECT_ROOT"
bun test tests/e2e/ --timeout 600000
}
# 生成 HTML 報告
generate_report() {
print_header "生成測試報告 Generating Test Report"
local report_file="$OUTPUT_DIR/test-report.html"
cat > "$report_file" << 'EOF'
<!DOCTYPE html>
<html lang="zh-TW">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>E2E 測試報告</title>
<style>
body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; margin: 40px; background: #f5f5f5; }
.container { max-width: 1200px; margin: 0 auto; background: white; padding: 40px; border-radius: 8px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); }
h1 { color: #333; border-bottom: 2px solid #4285f4; padding-bottom: 10px; }
h2 { color: #666; margin-top: 30px; }
.summary { display: grid; grid-template-columns: repeat(4, 1fr); gap: 20px; margin: 30px 0; }
.stat { background: #f8f9fa; padding: 20px; border-radius: 8px; text-align: center; }
.stat .number { font-size: 36px; font-weight: bold; color: #4285f4; }
.stat .label { color: #666; margin-top: 5px; }
.stat.passed .number { color: #34a853; }
.stat.failed .number { color: #ea4335; }
table { width: 100%; border-collapse: collapse; margin: 20px 0; }
th, td { padding: 12px; text-align: left; border-bottom: 1px solid #eee; }
th { background: #f8f9fa; font-weight: 600; }
.success { color: #34a853; }
.failure { color: #ea4335; }
.skipped { color: #fbbc04; }
.footer { margin-top: 40px; color: #999; font-size: 14px; text-align: center; }
</style>
</head>
<body>
<div class="container">
<h1>🧪 E2E 測試報告</h1>
<p>生成時間: <span id="timestamp"></span></p>
<div class="summary">
<div class="stat">
<div class="number" id="total">-</div>
<div class="label">總測試數</div>
</div>
<div class="stat passed">
<div class="number" id="passed">-</div>
<div class="label">通過</div>
</div>
<div class="stat failed">
<div class="number" id="failed">-</div>
<div class="label">失敗</div>
</div>
<div class="stat">
<div class="number" id="skipped">-</div>
<div class="label">跳過</div>
</div>
</div>
<h2>📊 格式轉換矩陣</h2>
<div id="matrix-content">載入中...</div>
<h2>🌍 翻譯測試結果</h2>
<div id="translation-content">載入中...</div>
<div class="footer">
ConvertX-CN E2E Test Report
</div>
</div>
<script>
document.getElementById('timestamp').textContent = new Date().toLocaleString('zh-TW');
// 嘗試載入測試報告 JSON
async function loadReports() {
try {
// 載入格式矩陣報告
const matrixResp = await fetch('format-matrix/matrix-report.json');
if (matrixResp.ok) {
const matrix = await matrixResp.json();
document.getElementById('total').textContent = matrix.totalCombinations;
document.getElementById('passed').textContent = matrix.passedTests;
document.getElementById('failed').textContent = matrix.failedTests;
document.getElementById('skipped').textContent = matrix.skippedTests;
let html = '<table><tr><th>轉換器</th><th>輸入格式</th><th>輸出格式</th><th>組合數</th></tr>';
for (const conv of matrix.converters) {
html += `<tr><td>${conv.name}</td><td>${conv.from.length}</td><td>${conv.to.length}</td><td>${conv.combinations.length}</td></tr>`;
}
html += '</table>';
document.getElementById('matrix-content').innerHTML = html;
}
} catch (e) {
document.getElementById('matrix-content').innerHTML = '<p>無法載入報告</p>';
}
try {
// 載入翻譯報告
const transResp = await fetch('translation/translation-report.json');
if (transResp.ok) {
const trans = await transResp.json();
let html = '<table><tr><th>翻譯器</th><th>來源</th><th>目標</th><th>狀態</th><th>時間</th></tr>';
for (const result of trans.stats.results) {
const status = result.success ? '<span class="success">✓</span>' : '<span class="failure">✗</span>';
html += `<tr><td>${result.translator}</td><td>${result.sourceLang}</td><td>${result.targetLang}</td><td>${status}</td><td>${(result.duration/1000).toFixed(1)}s</td></tr>`;
}
html += '</table>';
document.getElementById('translation-content').innerHTML = html;
}
} catch (e) {
document.getElementById('translation-content').innerHTML = '<p>無法載入報告</p>';
}
}
loadReports();
</script>
</body>
</html>
EOF
print_success "報告已生成: $report_file"
}
# 主函數
main() {
print_header "ConvertX-CN E2E 測試套件"
# 解析參數
case "${1:-}" in
--all)
check_dependencies
run_all_tests
generate_report
;;
--quick)
check_dependencies
run_quick_tests
;;
--matrix)
check_dependencies
run_matrix_tests
generate_report
;;
--translation)
check_dependencies
run_translation_tests
generate_report
;;
--comprehensive)
check_dependencies
run_comprehensive_tests
generate_report
;;
--report)
generate_report
;;
*)
echo "使用方式: $0 [選項]"
echo ""
echo "選項:"
echo " --all 運行所有 E2E 測試"
echo " --quick 只運行快速測試(跳過翻譯)"
echo " --matrix 只運行格式矩陣測試"
echo " --translation 只運行翻譯測試"
echo " --comprehensive 運行全面測試"
echo " --report 只生成 HTML 報告"
echo ""
echo "範例:"
echo " $0 --quick # 快速測試"
echo " $0 --all # 完整測試"
exit 0
;;
esac
print_header "測試完成 Tests Complete"
}
main "$@"