From a22ad4a155074a1b367627f3cadf1b1a1a5d4f3e Mon Sep 17 00:00:00 2001 From: veypi Date: Mon, 16 Feb 2026 16:34:59 +0800 Subject: [PATCH] test(scripts): Fix test scripts and improve curl handling - Fix api request functions to use array-based curl options - Fix token refresh to use refresh_token instead of access_token - Fix string comparison operator from == to = - Add get_refresh_token helper function - Handle empty response in check_http_code - Update README with new functions and correct command syntax - Remove set -e from lib.sh to avoid premature exits --- scripts/tests/01_basic_auth.sh | 21 +++++----- scripts/tests/README.md | 32 ++++++++++---- scripts/tests/lib.sh | 76 +++++++++++++++++++++++----------- 3 files changed, 87 insertions(+), 42 deletions(-) diff --git a/scripts/tests/01_basic_auth.sh b/scripts/tests/01_basic_auth.sh index ff906ba..14e7f7f 100755 --- a/scripts/tests/01_basic_auth.sh +++ b/scripts/tests/01_basic_auth.sh @@ -24,14 +24,14 @@ check_service step "1. 用户注册" REGISTER_RES=$(register_user "$TEST_USER" "$TEST_PASS" "$TEST_EMAIL") echo "注册响应: $REGISTER_RES" -check_http_code "$REGISTER_RES" "200" +check_http_code "$REGISTER_RES" "200" || exit 1 check_success "用户注册成功" # 2. 用户登录 step "2. 用户登录" LOGIN_RES=$(login_user "$TEST_USER" "$TEST_PASS") echo "登录响应: $LOGIN_RES" -check_http_code "$LOGIN_RES" "200" +check_http_code "$LOGIN_RES" "200" || exit 1 TOKEN=$(get_token "$LOGIN_RES") USER_ID=$(get_user_id "$LOGIN_RES") @@ -43,16 +43,16 @@ check_success "用户登录成功" step "3. 获取当前用户信息" ME_RES=$(api_get "/api/auth/me" "$TOKEN") echo "用户信息: $ME_RES" -check_http_code "$ME_RES" "200" +check_http_code "$ME_RES" "200" || exit 1 check_success "获取用户信息成功" # 4. 修改自己的信息 step "4. 修改自己的信息" UPDATE_RES=$(api_patch "/api/users/$USER_ID" '{"nickname": "Updated Nickname"}' "$TOKEN") echo "更新响应: $UPDATE_RES" -check_http_code "$UPDATE_RES" "200" +check_http_code "$UPDATE_RES" "200" || exit 1 NICKNAME=$(echo "$UPDATE_RES" | jq -r '.nickname') -if [ "$NICKNAME" == "Updated Nickname" ]; then +if [ "$NICKNAME" = "Updated Nickname" ]; then check_success "修改用户信息成功" else error "修改用户信息失败" @@ -65,21 +65,22 @@ CHANGE_PW_RES=$(api_post "/api/auth/me/change-password" \ "{\"old_password\": \"$TEST_PASS\", \"new_password\": \"newpassword123\"}" \ "$TOKEN") echo "改密码响应: $CHANGE_PW_RES" -check_http_code "$CHANGE_PW_RES" "200" +check_http_code "$CHANGE_PW_RES" "200" || exit 1 check_success "修改密码成功" # 6. 使用新密码登录 step "6. 使用新密码登录" LOGIN_NEW_RES=$(login_user "$TEST_USER" "newpassword123") -check_http_code "$LOGIN_NEW_RES" "200" +check_http_code "$LOGIN_NEW_RES" "200" || exit 1 TOKEN=$(get_token "$LOGIN_NEW_RES") check_success "新密码登录成功" # 7. Token 刷新 step "7. Token 刷新" -REFRESH_RES=$(api_post "/api/auth/refresh" "{}" "$TOKEN") +REFRESH_TOKEN=$(get_refresh_token "$LOGIN_NEW_RES") +REFRESH_RES=$(api_post "/api/auth/refresh" "{\"refresh_token\": \"$REFRESH_TOKEN\"}" "" ) echo "刷新响应: $REFRESH_RES" -check_http_code "$REFRESH_RES" "200" +check_http_code "$REFRESH_RES" "200" || exit 1 NEW_TOKEN=$(echo "$REFRESH_RES" | jq -r '.access_token') if [ -n "$NEW_TOKEN" ] && [ "$NEW_TOKEN" != "null" ]; then TOKEN="$NEW_TOKEN" @@ -93,7 +94,7 @@ fi step "8. 用户登出" LOGOUT_RES=$(api_post "/api/auth/logout" "{}" "$TOKEN") echo "登出响应: $LOGOUT_RES" -check_http_code "$LOGOUT_RES" "200" +check_http_code "$LOGOUT_RES" "200" || exit 1 check_success "用户登出成功" test_end diff --git a/scripts/tests/README.md b/scripts/tests/README.md index eefb5c2..ab67ed0 100644 --- a/scripts/tests/README.md +++ b/scripts/tests/README.md @@ -17,13 +17,15 @@ scripts/tests/ ## 前置条件 1. 服务必须已启动: + ```bash - go run cli/main.go -db=sqlite -dsn /tmp/vb.sqlite -p 4000 + go run cli/main.go -db.type=sqlite -db.dsn /tmp/vb.sqlite -p 4000 ``` -2. 数据库已初始化: +2. 数据库已初始化(如需要可以删除旧数据库): + ```bash - rm /tmp/vb.sqlite && go run cli/main.go -db=sqlite -dsn /tmp/vb.sqlite db migrate + rm /tmp/vb.sqlite ``` 3. 依赖工具: @@ -33,15 +35,22 @@ scripts/tests/ ## 测试脚本说明 ### lib.sh + 公共函数库,包含: + - `check_success()` / `check_fail()` - 检查结果 - `check_http_code()` - 检查 HTTP 状态码 - `register_user()` - 注册用户 - `login_user()` - 登录用户 - `api_get()` / `api_post()` / `api_patch()` / `api_delete()` - API 请求封装 +- `create_org()` - 创建组织 +- `update_org()` - 更新组织 +- `add_org_member()` - 添加组织成员 ### 01_basic_auth.sh + **测试内容**:基础认证流程 + - 用户注册 - 用户登录 - 获取当前用户信息 @@ -51,7 +60,9 @@ scripts/tests/ - 用户登出 ### 02_user_permission.sh + **测试内容**:用户级权限控制 + - 第一个用户注册(自动成为 admin) - 第二个用户注册(普通 user) - user 可以修改自己的信息 @@ -59,7 +70,9 @@ scripts/tests/ - admin 可以修改任意用户信息 ### 03_org_permission.sh + **测试内容**:组织权限控制 + - admin 创建组织 - user 不能修改他人创建的组织 - admin 邀请 user 加入组织 @@ -67,14 +80,18 @@ scripts/tests/ - 只有 admin/owner 可以修改组织 ### run_all.sh + **功能**:运行所有测试 + - 按顺序执行所有测试脚本 - 遇到错误时停止 - 输出测试摘要 +- 统一时间戳避免冲突 ## 使用方法 ### 运行单个测试 + ```bash # 基础认证测试 cd scripts/tests @@ -88,6 +105,7 @@ bash 03_org_permission.sh ``` ### 运行所有测试 + ```bash cd scripts/tests bash run_all.sh @@ -95,10 +113,10 @@ bash run_all.sh ## 测试环境变量 -| 变量 | 默认值 | 说明 | -|------|--------|------| -| `BASE_URL` | `http://localhost:4000` | API 基础地址 | -| `TEST_TIMESTAMP` | 自动生成 | 测试时间戳,用于生成唯一用户名 | +| 变量 | 默认值 | 说明 | +| ---------------- | ----------------------- | ------------------------------ | +| `BASE_URL` | `http://localhost:4000` | API 基础地址 | +| `TEST_TIMESTAMP` | 自动生成 | 测试时间戳,用于生成唯一用户名 | ## 注意事项 diff --git a/scripts/tests/lib.sh b/scripts/tests/lib.sh index 97f7dc8..2cd2c6f 100755 --- a/scripts/tests/lib.sh +++ b/scripts/tests/lib.sh @@ -3,7 +3,7 @@ # 测试公共函数库 # -set -e +# 注意:不在库文件中设置 set -e,由调用脚本控制 # 配置 BASE_URL="${BASE_URL:-http://localhost:4000}" @@ -37,9 +37,12 @@ warn() { echo -e "${YELLOW}[WARN]${NC} $1" } -# 检查上一个命令是否成功 +# 检查上一个命令是否成功(传递状态码) +# $1: 描述 +# $2: 状态码(可选,默认使用 $?) check_success() { - if [ $? -eq 0 ]; then + local status=${2:-$?} + if [ $status -eq 0 ]; then success "$1" return 0 else @@ -67,10 +70,15 @@ check_http_code() { local expected="${2:-200}" local code - # 提取 code 字段,如果不存在则认为是 200 - code=$(echo "$response" | jq -r '.code // 200') + # 处理空响应(成功时可能返回空体) + if [ -z "$response" ]; then + code="200" + else + # 提取 code 字段,如果不存在则认为是 200 + code=$(echo "$response" | jq -r '.code // 200') + fi - if [ "$code" == "$expected" ]; then + if [ "$code" = "$expected" ]; then return 0 else error "期望状态码: $expected, 实际: $code" @@ -81,9 +89,9 @@ check_http_code() { # 检查服务是否运行 check_service() { - if ! curl -s "$BASE_URL/_api.json" > /dev/null 2>&1; then + if ! curl -s "$BASE_URL/api/auth/login-methods" > /dev/null 2>&1; then error "服务未启动,请先启动服务" - info "运行: go run cli/main.go -db=sqlite -dsn /tmp/vb.sqlite -p 4000" + info "运行: go run cli/main.go -db.type=sqlite -db.dsn /tmp/vb.sqlite -p 4000" exit 1 fi success "服务正在运行" @@ -97,32 +105,38 @@ check_service() { api_get() { local path="$1" local token="${2:-}" - local headers="" + + local curl_opts=("-s" "-X" "GET") if [ -n "$token" ]; then - headers="-H Authorization: Bearer $token" + curl_opts+=("-H" "Authorization: Bearer $token") fi - curl -s -X GET "$BASE_URL$path" $headers + curl "${curl_opts[@]}" "$BASE_URL$path" } + # POST 请求 api_post() { local path="$1" local data="$2" local token="${3:-}" local extra_headers="${4:-}" - local headers="-H Content-Type: application/json" + + local curl_opts=("-s" "-X" "POST" "-H" "Content-Type: application/json") if [ -n "$token" ]; then - headers="$headers -H Authorization: Bearer $token" + curl_opts+=("-H" "Authorization: Bearer $token") fi if [ -n "$extra_headers" ]; then - headers="$headers $extra_headers" + # 将 extra_headers 按空格分割添加到数组 + for header in $extra_headers; do + curl_opts+=("-H" "$header") + done fi - curl -s -X POST "$BASE_URL$path" $headers -d "$data" + curl "${curl_opts[@]}" "$BASE_URL$path" -d "$data" } # PATCH 请求 @@ -131,35 +145,41 @@ api_patch() { local data="$2" local token="${3:-}" local extra_headers="${4:-}" - local headers="-H Content-Type: application/json" + + local curl_opts=("-s" "-X" "PATCH" "-H" "Content-Type: application/json") if [ -n "$token" ]; then - headers="$headers -H Authorization: Bearer $token" + curl_opts+=("-H" "Authorization: Bearer $token") fi if [ -n "$extra_headers" ]; then - headers="$headers $extra_headers" + for header in $extra_headers; do + curl_opts+=("-H" "$header") + done fi - curl -s -X PATCH "$BASE_URL$path" $headers -d "$data" + curl "${curl_opts[@]}" "$BASE_URL$path" -d "$data" } # DELETE 请求 api_delete() { local path="$1" - local token="$2" + local token="${2:-}" local extra_headers="${3:-}" - local headers="" + + local curl_opts=("-s" "-X" "DELETE") if [ -n "$token" ]; then - headers="-H Authorization: Bearer $token" + curl_opts+=("-H" "Authorization: Bearer $token") fi if [ -n "$extra_headers" ]; then - headers="$headers $extra_headers" + for header in $extra_headers; do + curl_opts+=("-H" "$header") + done fi - curl -s -X DELETE "$BASE_URL$path" $headers + curl "${curl_opts[@]}" "$BASE_URL$path" } # ======================================== @@ -187,12 +207,18 @@ login_user() { "{\"username\": \"$username\", \"password\": \"$password\"}" } -# 提取 token +# 提取 access_token get_token() { local login_response="$1" echo "$login_response" | jq -r '.access_token' } +# 提取 refresh_token +get_refresh_token() { + local login_response="$1" + echo "$login_response" | jq -r '.refresh_token' +} + # 提取用户ID get_user_id() { local login_response="$1"