All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 5m30s
新增功能: - 门店套餐分配管理(shop_package_allocation):支持门店套餐库存管理 - 门店套餐系列分配管理(shop_series_allocation):支持套餐系列分配和佣金层级设置 - 我的套餐查询(my_package):支持门店查询自己的套餐分配情况 测试改进: - 统一集成测试基础设施,新增 testutils.NewIntegrationTestEnv - 重构所有集成测试使用新的测试环境设置 - 移除旧的测试辅助函数和冗余测试文件 - 新增 test_helpers_test.go 统一任务测试辅助 技术细节: - 新增数据库迁移 000025_create_shop_allocation_tables - 新增 3 个 Handler、Service、Store 和对应的单元测试 - 更新 OpenAPI 文档和文档生成器 - 测试覆盖率:Service 层 > 90% Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
246 lines
7.0 KiB
Go
246 lines
7.0 KiB
Go
package integration
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/break/junhong_cmp_fiber/internal/model/dto"
|
|
"github.com/break/junhong_cmp_fiber/pkg/response"
|
|
"github.com/break/junhong_cmp_fiber/tests/testutils"
|
|
"github.com/break/junhong_cmp_fiber/tests/testutils/integ"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
// TestShopManagement_CreateShop 测试创建商户
|
|
func TestShopManagement_CreateShop(t *testing.T) {
|
|
env := integ.NewIntegrationTestEnv(t)
|
|
|
|
// 使用时间戳生成唯一的店铺名和代码
|
|
timestamp := time.Now().UnixNano()
|
|
shopName := fmt.Sprintf("test_shop_%d", timestamp)
|
|
shopCode := fmt.Sprintf("SHOP%d", timestamp%1000000)
|
|
|
|
reqBody := dto.CreateShopRequest{
|
|
ShopName: shopName,
|
|
ShopCode: shopCode,
|
|
InitUsername: "testuser",
|
|
InitPhone: testutils.GenerateUniquePhone(),
|
|
InitPassword: "password123",
|
|
}
|
|
|
|
body, err := json.Marshal(reqBody)
|
|
require.NoError(t, err)
|
|
|
|
resp, err := env.AsSuperAdmin().Request("POST", "/api/admin/shops", body)
|
|
require.NoError(t, err)
|
|
defer resp.Body.Close()
|
|
|
|
t.Logf("HTTP 状态码: %d", resp.StatusCode)
|
|
|
|
var result response.Response
|
|
err = json.NewDecoder(resp.Body).Decode(&result)
|
|
require.NoError(t, err)
|
|
|
|
t.Logf("响应 Code: %d, Message: %s", result.Code, result.Message)
|
|
t.Logf("响应 Data: %+v", result.Data)
|
|
|
|
if result.Code != 0 {
|
|
t.Fatalf("API 返回错误: %s", result.Message)
|
|
}
|
|
|
|
assert.Equal(t, 200, resp.StatusCode)
|
|
assert.Equal(t, 0, result.Code)
|
|
assert.NotNil(t, result.Data)
|
|
|
|
shopData, ok := result.Data.(map[string]interface{})
|
|
require.True(t, ok)
|
|
assert.Equal(t, shopName, shopData["shop_name"])
|
|
assert.Equal(t, shopCode, shopData["shop_code"])
|
|
assert.Equal(t, float64(1), shopData["level"])
|
|
assert.Equal(t, float64(1), shopData["status"])
|
|
}
|
|
|
|
// TestShopManagement_CreateShop_DuplicateCode 测试创建商户 - 商户编码重复
|
|
func TestShopManagement_CreateShop_DuplicateCode(t *testing.T) {
|
|
env := integ.NewIntegrationTestEnv(t)
|
|
|
|
// 使用时间戳生成唯一的店铺代码
|
|
timestamp := time.Now().UnixNano()
|
|
duplicateCode := fmt.Sprintf("DUP%d", timestamp%1000000)
|
|
|
|
firstReq := dto.CreateShopRequest{
|
|
ShopName: fmt.Sprintf("shop1_%d", timestamp),
|
|
ShopCode: duplicateCode,
|
|
InitUsername: fmt.Sprintf("dupuser1_%d", timestamp),
|
|
InitPhone: testutils.GenerateUniquePhone(),
|
|
InitPassword: "password123",
|
|
}
|
|
firstBody, _ := json.Marshal(firstReq)
|
|
firstResp, _ := env.AsSuperAdmin().Request("POST", "/api/admin/shops", firstBody)
|
|
var firstResult response.Response
|
|
json.NewDecoder(firstResp.Body).Decode(&firstResult)
|
|
firstResp.Body.Close()
|
|
|
|
require.Equal(t, 0, firstResult.Code, "第一个商户应该创建成功")
|
|
|
|
reqBody := dto.CreateShopRequest{
|
|
ShopName: fmt.Sprintf("shop2_%d", timestamp),
|
|
ShopCode: duplicateCode,
|
|
InitUsername: fmt.Sprintf("dupuser2_%d", timestamp),
|
|
InitPhone: testutils.GenerateUniquePhone(),
|
|
InitPassword: "password123",
|
|
}
|
|
|
|
body, err := json.Marshal(reqBody)
|
|
require.NoError(t, err)
|
|
|
|
resp, err := env.AsSuperAdmin().Request("POST", "/api/admin/shops", body)
|
|
require.NoError(t, err)
|
|
defer resp.Body.Close()
|
|
|
|
// 应该返回错误
|
|
var result response.Response
|
|
err = json.NewDecoder(resp.Body).Decode(&result)
|
|
require.NoError(t, err)
|
|
|
|
assert.NotEqual(t, 0, result.Code) // 非成功状态
|
|
assert.Contains(t, result.Message, "已存在") // 错误消息应包含"已存在"
|
|
}
|
|
|
|
// TestShopManagement_ListShops 测试查询商户列表
|
|
func TestShopManagement_ListShops(t *testing.T) {
|
|
env := integ.NewIntegrationTestEnv(t)
|
|
|
|
// 创建测试数据
|
|
env.CreateTestShop("商户A", 1, nil)
|
|
env.CreateTestShop("商户B", 1, nil)
|
|
env.CreateTestShop("商户C", 2, nil)
|
|
|
|
resp, err := env.AsSuperAdmin().Request("GET", "/api/admin/shops?page=1&size=10", nil)
|
|
require.NoError(t, err)
|
|
defer resp.Body.Close()
|
|
|
|
assert.Equal(t, 200, resp.StatusCode)
|
|
|
|
var result response.Response
|
|
err = json.NewDecoder(resp.Body).Decode(&result)
|
|
require.NoError(t, err)
|
|
|
|
assert.Equal(t, 0, result.Code)
|
|
|
|
// 解析分页数据
|
|
dataMap, ok := result.Data.(map[string]interface{})
|
|
require.True(t, ok)
|
|
|
|
items, ok := dataMap["items"].([]interface{})
|
|
require.True(t, ok)
|
|
assert.GreaterOrEqual(t, len(items), 3)
|
|
}
|
|
|
|
// TestShopManagement_UpdateShop 测试更新商户
|
|
func TestShopManagement_UpdateShop(t *testing.T) {
|
|
env := integ.NewIntegrationTestEnv(t)
|
|
|
|
// 创建测试商户
|
|
shop := env.CreateTestShop("原始商户", 1, nil)
|
|
|
|
// 更新商户
|
|
reqBody := dto.UpdateShopRequest{
|
|
ShopName: "更新后的商户",
|
|
Status: 1,
|
|
}
|
|
|
|
body, err := json.Marshal(reqBody)
|
|
require.NoError(t, err)
|
|
|
|
resp, err := env.AsSuperAdmin().Request("PUT", fmt.Sprintf("/api/admin/shops/%d", shop.ID), body)
|
|
require.NoError(t, err)
|
|
defer resp.Body.Close()
|
|
|
|
assert.Equal(t, 200, resp.StatusCode)
|
|
|
|
var result response.Response
|
|
err = json.NewDecoder(resp.Body).Decode(&result)
|
|
require.NoError(t, err)
|
|
|
|
assert.Equal(t, 0, result.Code)
|
|
assert.NotNil(t, result.Data)
|
|
|
|
shopData, ok := result.Data.(map[string]interface{})
|
|
require.True(t, ok)
|
|
assert.Equal(t, "更新后的商户", shopData["shop_name"])
|
|
}
|
|
|
|
// TestShopManagement_DeleteShop 测试删除商户
|
|
func TestShopManagement_DeleteShop(t *testing.T) {
|
|
env := integ.NewIntegrationTestEnv(t)
|
|
|
|
// 创建测试商户
|
|
shop := env.CreateTestShop("待删除商户", 1, nil)
|
|
|
|
// 删除商户
|
|
resp, err := env.AsSuperAdmin().Request("DELETE", fmt.Sprintf("/api/admin/shops/%d", shop.ID), nil)
|
|
require.NoError(t, err)
|
|
defer resp.Body.Close()
|
|
|
|
assert.Equal(t, 200, resp.StatusCode)
|
|
|
|
var result response.Response
|
|
err = json.NewDecoder(resp.Body).Decode(&result)
|
|
require.NoError(t, err)
|
|
|
|
assert.Equal(t, 0, result.Code)
|
|
}
|
|
|
|
// TestShopManagement_DeleteShop_WithMultipleAccounts 测试删除商户 - 多个关联账号
|
|
func TestShopManagement_DeleteShop_WithMultipleAccounts(t *testing.T) {
|
|
env := integ.NewIntegrationTestEnv(t)
|
|
|
|
// 创建测试商户
|
|
shop := env.CreateTestShop("多账号商户", 1, nil)
|
|
|
|
// 删除商户
|
|
resp, err := env.AsSuperAdmin().Request("DELETE", fmt.Sprintf("/api/admin/shops/%d", shop.ID), nil)
|
|
require.NoError(t, err)
|
|
defer resp.Body.Close()
|
|
|
|
assert.Equal(t, 200, resp.StatusCode)
|
|
|
|
var result response.Response
|
|
err = json.NewDecoder(resp.Body).Decode(&result)
|
|
require.NoError(t, err)
|
|
|
|
assert.Equal(t, 0, result.Code)
|
|
}
|
|
|
|
// TestShopManagement_Unauthorized 测试未认证访问
|
|
func TestShopManagement_Unauthorized(t *testing.T) {
|
|
env := integ.NewIntegrationTestEnv(t)
|
|
|
|
// 不提供 token
|
|
resp, err := env.ClearAuth().Request("GET", "/api/admin/shops", nil)
|
|
require.NoError(t, err)
|
|
defer resp.Body.Close()
|
|
|
|
// 应该返回 401 未授权
|
|
assert.Equal(t, 401, resp.StatusCode)
|
|
}
|
|
|
|
// TestShopManagement_InvalidToken 测试无效 token
|
|
func TestShopManagement_InvalidToken(t *testing.T) {
|
|
env := integ.NewIntegrationTestEnv(t)
|
|
|
|
// 提供无效 token
|
|
resp, err := env.RequestWithHeaders("GET", "/api/admin/shops", nil, map[string]string{
|
|
"Authorization": "Bearer invalid-token-12345",
|
|
})
|
|
require.NoError(t, err)
|
|
defer resp.Body.Close()
|
|
|
|
// 应该返回 401 未授权
|
|
assert.Equal(t, 401, resp.StatusCode)
|
|
}
|