437 lines
12 KiB
Bash
437 lines
12 KiB
Bash
#!/bin/bash
|
||
|
||
#===============================================================================
|
||
# qiming-file-server CLI 自动化测试脚本
|
||
#
|
||
# 功能: 自动化测试 qiming-file-server CLI 的启动、状态查询、健康检查、重启、停止等功能
|
||
#
|
||
# 使用方法:
|
||
# chmod +x test-cli.sh
|
||
# ./test-cli.sh # 模式一: pnpm link 全局命令
|
||
# ./test-cli.sh --direct # 模式二: 直接用 node 运行 dist 目录
|
||
# ./test-cli.sh --installed # 模式三: 已全局安装,跳过所有安装步骤
|
||
#
|
||
# 环境要求:
|
||
# - bash shell
|
||
# - curl
|
||
# - jq (用于格式化 JSON 输出)
|
||
# - pnpm
|
||
# - node (v22+)
|
||
#
|
||
# 脚本行为:
|
||
# 模式一 (默认): pnpm install + pnpm link 后测试
|
||
# 模式二 (--direct): 直接用 node 运行 dist/,无需全局链接
|
||
# 模式三 (--installed): 已全局安装,直接测试,跳过所有安装步骤
|
||
#===============================================================================
|
||
|
||
set -e
|
||
|
||
# 项目根目录(脚本位于 scripts/ 下,根目录为上级目录)
|
||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||
PROJECT_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)"
|
||
DIST_DIR="${PROJECT_ROOT}/dist"
|
||
|
||
# 颜色定义
|
||
RED='\033[0;31m'
|
||
GREEN='\033[0;32m'
|
||
YELLOW='\033[1;33m'
|
||
BLUE='\033[0;34m'
|
||
CYAN='\033[0;36m'
|
||
NC='\033[0m' # No Color
|
||
|
||
# 测试模式: "link", "direct" 或 "installed"
|
||
TEST_MODE="link"
|
||
|
||
# 日志函数
|
||
log_info() {
|
||
echo -e "${BLUE}[INFO]${NC} $1"
|
||
}
|
||
|
||
log_success() {
|
||
echo -e "${GREEN}[SUCCESS]${NC} $1"
|
||
}
|
||
|
||
log_warn() {
|
||
echo -e "${YELLOW}[WARN]${NC} $1"
|
||
}
|
||
|
||
log_error() {
|
||
echo -e "${RED}[ERROR]${NC} $1"
|
||
}
|
||
|
||
log_section() {
|
||
echo ""
|
||
echo -e "${CYAN}========================================${NC}"
|
||
echo -e "${CYAN} $1${NC}"
|
||
echo -e "${CYAN}========================================${NC}"
|
||
echo ""
|
||
}
|
||
|
||
#-------------------------------------------------------------------------------
|
||
# 模式一: 本地安装 - 安装依赖并全局链接,使 qiming-file-server 命令可用
|
||
#-------------------------------------------------------------------------------
|
||
do_local_install() {
|
||
log_info "模式一: 本地安装模式"
|
||
log_info "进入项目根目录 ${PROJECT_ROOT}"
|
||
cd "${PROJECT_ROOT}"
|
||
|
||
log_info "执行 pnpm install..."
|
||
pnpm install
|
||
|
||
log_info "执行 pnpm run build(编译 CLI 到 dist/)..."
|
||
pnpm run build
|
||
|
||
log_info "执行 pnpm link --global(全局链接)..."
|
||
pnpm link --global
|
||
|
||
log_success "本地安装完成,qiming-file-server 命令已可用"
|
||
}
|
||
|
||
#-------------------------------------------------------------------------------
|
||
# 模式二: 直接运行 - 检查 dist 目录是否存在,直接用 node 运行
|
||
#-------------------------------------------------------------------------------
|
||
check_direct_mode() {
|
||
if [ ! -d "${DIST_DIR}" ]; then
|
||
log_error "dist 目录不存在,请先运行: npm run build"
|
||
log_info "或者使用默认模式: ./test-cli.sh"
|
||
exit 1
|
||
fi
|
||
|
||
if [ ! -f "${DIST_DIR}/cli.js" ]; then
|
||
log_error "dist/cli.js 不存在,请先运行: npm run build"
|
||
exit 1
|
||
fi
|
||
|
||
log_success "模式二: 直接运行模式"
|
||
log_info "将使用 'node ${DIST_DIR}/cli.js' 执行测试"
|
||
}
|
||
|
||
#-------------------------------------------------------------------------------
|
||
# 模式三: 已安装 - 跳过所有安装步骤,直接使用全局命令测试
|
||
#-------------------------------------------------------------------------------
|
||
check_installed_mode() {
|
||
if ! command -v qiming-file-server &> /dev/null; then
|
||
log_error "未找到 qiming-file-server 命令,请先全局安装:"
|
||
log_info " npm install -g qiming-file-server"
|
||
log_info "或者使用其他模式:"
|
||
log_info " ./test-cli.sh # 模式一: pnpm link"
|
||
log_info " ./test-cli.sh --direct # 模式二: node 直接运行"
|
||
exit 1
|
||
fi
|
||
|
||
log_success "模式三: 已安装模式"
|
||
log_info "检测到 qiming-file-server 全局命令"
|
||
log_info "将直接使用 'qiming-file-server' 执行测试"
|
||
}
|
||
|
||
# 测试函数
|
||
test_command() {
|
||
local cmd=$1
|
||
local description=$2
|
||
log_info "测试: ${description}"
|
||
log_info "命令: ${cmd}"
|
||
eval "${cmd}"
|
||
local exit_code=$?
|
||
if [ $exit_code -eq 0 ]; then
|
||
log_success "✓ 完成: ${description}"
|
||
return 0
|
||
else
|
||
log_error "✗ 失败: ${description} (退出码: ${exit_code})"
|
||
return 1
|
||
fi
|
||
}
|
||
|
||
# 默认配置
|
||
PORT=${PORT:-60000}
|
||
HEALTH_URL="http://localhost:${PORT}/health"
|
||
PROJECT_DIR=${PROJECT_DIR:-./test-projects}
|
||
NGINX_DIR=${NGINX_DIR:-./test-nginx}
|
||
UPLOAD_DIR=${UPLOAD_DIR:-./test-uploads}
|
||
|
||
# 显示配置
|
||
show_config() {
|
||
log_section "测试配置"
|
||
echo " 测试模式: ${TEST_MODE_LABEL}"
|
||
echo " 端口: ${PORT}"
|
||
echo " 健康检查: ${HEALTH_URL}"
|
||
echo " 项目目录: ${PROJECT_DIR}"
|
||
echo " Nginx目录: ${NGINX_DIR}"
|
||
echo " 上传目录: ${UPLOAD_DIR}"
|
||
echo ""
|
||
}
|
||
|
||
# 获取模式标签
|
||
get_mode_label() {
|
||
case "${TEST_MODE}" in
|
||
link)
|
||
TEST_MODE_LABEL="pnpm link 全局命令"
|
||
;;
|
||
direct)
|
||
TEST_MODE_LABEL="node 直接运行"
|
||
;;
|
||
installed)
|
||
TEST_MODE_LABEL="已全局安装"
|
||
;;
|
||
esac
|
||
}
|
||
|
||
# 检查依赖
|
||
check_dependencies() {
|
||
log_info "检查依赖..."
|
||
|
||
local missing_deps=()
|
||
|
||
if ! command -v curl &> /dev/null; then
|
||
missing_deps+=("curl")
|
||
fi
|
||
|
||
if ! command -v jq &> /dev/null; then
|
||
missing_deps+=("jq")
|
||
fi
|
||
|
||
# 模式一和模式二需要 pnpm
|
||
if [ "${TEST_MODE}" != "installed" ]; then
|
||
if ! command -v pnpm &> /dev/null; then
|
||
missing_deps+=("pnpm")
|
||
fi
|
||
fi
|
||
|
||
if ! command -v node &> /dev/null; then
|
||
missing_deps+=("node")
|
||
fi
|
||
|
||
if [ ${#missing_deps[@]} -gt 0 ]; then
|
||
log_error "缺少依赖: ${missing_deps[*]}"
|
||
log_info "请安装后再运行,例如: brew install ${missing_deps[*]}"
|
||
exit 1
|
||
fi
|
||
|
||
log_success "依赖已满足"
|
||
}
|
||
|
||
# 获取当前模式下的命令前缀
|
||
get_cmd_prefix() {
|
||
case "${TEST_MODE}" in
|
||
link)
|
||
echo "qiming-file-server"
|
||
;;
|
||
direct)
|
||
echo "node ${DIST_DIR}/cli.js"
|
||
;;
|
||
installed)
|
||
echo "qiming-file-server"
|
||
;;
|
||
esac
|
||
}
|
||
|
||
# 清理函数:停止服务
|
||
cleanup() {
|
||
log_info "清理环境(停止服务)..."
|
||
local cmd_prefix=$(get_cmd_prefix)
|
||
${cmd_prefix} stop 2>/dev/null || true
|
||
sleep 1
|
||
}
|
||
|
||
# 退出时清理
|
||
cleanup_exit() {
|
||
local exit_code=$?
|
||
|
||
# 只在模式一下取消全局链接
|
||
if [ "${TEST_MODE}" = "link" ]; then
|
||
log_info "取消全局链接: pnpm unlink --global"
|
||
(cd "${PROJECT_ROOT}" && pnpm unlink --global) 2>/dev/null || true
|
||
fi
|
||
|
||
if [ $exit_code -ne 0 ]; then
|
||
exit $exit_code
|
||
fi
|
||
}
|
||
|
||
# 测试健康检查端点
|
||
test_health_endpoint() {
|
||
log_info "测试健康检查端点..."
|
||
|
||
local response=$(curl -s "${HEALTH_URL}")
|
||
local status=$(echo "${response}" | jq -r '.status' 2>/dev/null || echo "error")
|
||
|
||
if [ "${status}" = "ok" ]; then
|
||
log_success "健康检查通过"
|
||
log_info "响应: ${response}"
|
||
return 0
|
||
else
|
||
log_error "健康检查失败,状态: ${status}"
|
||
log_info "响应: ${response}"
|
||
return 1
|
||
fi
|
||
}
|
||
|
||
# 测试服务状态查询
|
||
test_status_command() {
|
||
log_info "测试服务状态查询..."
|
||
local cmd_prefix=$(get_cmd_prefix)
|
||
${cmd_prefix} status
|
||
log_success "状态查询完成"
|
||
}
|
||
|
||
# 主测试流程
|
||
run_tests() {
|
||
get_mode_label
|
||
show_config
|
||
check_dependencies
|
||
|
||
log_section "开始测试"
|
||
|
||
# 根据模式执行不同的初始化
|
||
case "${TEST_MODE}" in
|
||
link)
|
||
do_local_install
|
||
;;
|
||
direct)
|
||
check_direct_mode
|
||
;;
|
||
installed)
|
||
check_installed_mode
|
||
;;
|
||
esac
|
||
|
||
# 清理环境(停止可能残留的服务)
|
||
cleanup
|
||
|
||
# ========== 测试 1: 启动服务 ==========
|
||
log_section "测试 1: 启动服务"
|
||
local cmd_prefix=$(get_cmd_prefix)
|
||
test_command "${cmd_prefix} start --env production --port ${PORT}" "启动服务"
|
||
sleep 3
|
||
|
||
# ========== 测试 2: 健康检查 ==========
|
||
log_section "测试 2: 健康检查"
|
||
test_health_endpoint
|
||
|
||
# ========== 测试 3: 状态查询 ==========
|
||
log_section "测试 3: 状态查询"
|
||
test_status_command
|
||
|
||
# ========== 测试 4: 重启服务 ==========
|
||
log_section "测试 4: 重启服务"
|
||
test_command "${cmd_prefix} restart" "重启服务"
|
||
sleep 3
|
||
|
||
# ========== 测试 5: 重启后健康检查 ==========
|
||
log_section "测试 5: 重启后健康检查"
|
||
test_health_endpoint
|
||
|
||
# ========== 测试 6: 停止服务 ==========
|
||
log_section "测试 6: 停止服务"
|
||
test_command "${cmd_prefix} stop" "停止服务"
|
||
|
||
# ========== 完成 ==========
|
||
log_section "测试完成"
|
||
log_success "所有 CLI 测试通过!"
|
||
|
||
# 根据模式显示不同的后续提示
|
||
echo ""
|
||
case "${TEST_MODE}" in
|
||
link)
|
||
echo "已测试全局命令 'qiming-file-server'"
|
||
;;
|
||
direct)
|
||
echo "已测试 'node ${DIST_DIR}/cli.js' 直接运行"
|
||
;;
|
||
installed)
|
||
echo "已测试全局安装版本"
|
||
;;
|
||
esac
|
||
echo ""
|
||
}
|
||
|
||
# 显示帮助信息
|
||
show_help() {
|
||
echo "qiming-file-server CLI 测试脚本"
|
||
echo ""
|
||
echo "用法: $0 [选项]"
|
||
echo ""
|
||
echo "选项:"
|
||
echo " -p, --port <端口> 指定测试端口 (默认: 60000)"
|
||
echo " --direct 模式二: 直接用 node 运行 dist/"
|
||
echo " --installed 模式三: 已全局安装,跳过所有安装步骤"
|
||
echo " --project-dir <目录> 指定项目目录"
|
||
echo " --nginx-dir <目录> 指定 Nginx 目录"
|
||
echo " --upload-dir <目录> 指定上传目录"
|
||
echo " -h, --help 显示帮助信息"
|
||
echo ""
|
||
echo "三种测试模式:"
|
||
echo " 1. 默认模式 (pnpm link): ./test-cli.sh"
|
||
echo " - 执行 pnpm install + pnpm run build + pnpm link"
|
||
echo " - 使用全局命令 'qiming-file-server'"
|
||
echo ""
|
||
echo " 2. 直接运行模式: ./test-cli.sh --direct"
|
||
echo " - 无需 pnpm link"
|
||
echo " - 使用 'node dist/cli.js' 运行"
|
||
echo ""
|
||
echo " 3. 已安装模式: ./test-cli.sh --installed"
|
||
echo " - 跳过所有安装步骤"
|
||
echo " - 直接使用已全局安装的命令"
|
||
echo ""
|
||
echo "示例:"
|
||
echo " $0 # 模式一: pnpm link 全局命令"
|
||
echo " $0 --direct # 模式二: node 直接运行"
|
||
echo " $0 --installed # 模式三: 已全局安装"
|
||
echo " $0 --port 60001 # 指定端口"
|
||
echo " $0 --installed -p 60001 # 组合使用"
|
||
echo ""
|
||
}
|
||
|
||
# 解析命令行参数
|
||
parse_args() {
|
||
while [[ $# -gt 0 ]]; do
|
||
case $1 in
|
||
-p|--port)
|
||
PORT="$2"
|
||
shift 2
|
||
;;
|
||
--direct)
|
||
TEST_MODE="direct"
|
||
shift
|
||
;;
|
||
--installed)
|
||
TEST_MODE="installed"
|
||
shift
|
||
;;
|
||
--project-dir)
|
||
PROJECT_DIR="$2"
|
||
shift 2
|
||
;;
|
||
--nginx-dir)
|
||
NGINX_DIR="$2"
|
||
shift 2
|
||
;;
|
||
--upload-dir)
|
||
UPLOAD_DIR="$2"
|
||
shift 2
|
||
;;
|
||
-h|--help)
|
||
show_help
|
||
exit 0
|
||
;;
|
||
*)
|
||
log_error "未知参数: $1"
|
||
show_help
|
||
exit 1
|
||
;;
|
||
esac
|
||
done
|
||
}
|
||
|
||
# 脚本入口
|
||
main() {
|
||
parse_args "$@"
|
||
|
||
# 无论正常结束、失败或 Ctrl+C,退出时都执行清理
|
||
trap 'cleanup_exit' EXIT
|
||
|
||
run_tests
|
||
}
|
||
|
||
# 执行主函数
|
||
main "$@"
|