170 lines
7.0 KiB
Go
170 lines
7.0 KiB
Go
package main
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"path/filepath"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
"github.com/glebarez/sqlite"
|
|
"gorm.io/gorm"
|
|
businessbiz "kra/internal/biz/business"
|
|
"kra/internal/biz/system"
|
|
businessdata "kra/internal/data/business"
|
|
systemdata "kra/internal/data/system"
|
|
"kra/internal/server/handler"
|
|
"kra/internal/server/router"
|
|
businessservice "kra/internal/service/business"
|
|
)
|
|
|
|
type businessHTTPData struct{ db *gorm.DB }
|
|
|
|
func (d businessHTTPData) DB() *gorm.DB { return d.db }
|
|
|
|
type httpPlatformAccounts struct{}
|
|
|
|
func (httpPlatformAccounts) FindByAccount(context.Context, string, string) (*businessbiz.PlatformAccount, error) {
|
|
return &businessbiz.PlatformAccount{ID: 77, Status: 1}, nil
|
|
}
|
|
|
|
type httpPlatformPasswords struct{}
|
|
|
|
func (httpPlatformPasswords) Verify(string, string) (bool, error) { return true, nil }
|
|
|
|
func TestBusinessHTTPListWithSystemOnlyAndCompleteDatabase(t *testing.T) {
|
|
db, err := gorm.Open(sqlite.Open(filepath.Join(t.TempDir(), "http.db")), &gorm.Config{})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
sqlDB, err := db.DB()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
t.Cleanup(func() { _ = sqlDB.Close() })
|
|
for _, step := range append(systemdata.Migrations(), businessdata.Migrations()...) {
|
|
if err := step.Migrate(db); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
for _, statement := range []string{
|
|
"INSERT INTO sys_users(id,uuid,username,authority_id,level,id_path) VALUES (1,'admin','admin',888,0,'0'),(2,'child','child',901,1,'0'),(3,'empty','empty',903,3,'0,2')",
|
|
"INSERT INTO sys_authorities(authority_id,authority_name) VALUES (901,'一级商务')",
|
|
"INSERT INTO sys_user_bind_platform(user_id,source_db,platform_busier_id,status) VALUES (2,'lx',9,'0')",
|
|
} {
|
|
if err := db.Exec(statement).Error; err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
provider := businessHTTPData{db}
|
|
accountUsecase := businessbiz.NewAccountUsecase(businessdata.NewAccountRepo(provider))
|
|
accounts := businessservice.NewAccountService(accountUsecase)
|
|
bindings := businessservice.NewBindingService(businessbiz.NewBindingUsecase(businessdata.NewBindingRepo(provider), accountUsecase, httpPlatformAccounts{}, httpPlatformPasswords{}))
|
|
prefs := businessservice.NewUserPreferenceService(businessbiz.NewUserPreferenceUsecase(businessdata.NewUserPreferenceRepo(provider)))
|
|
engine := gin.New()
|
|
// 此契约测试固定已认证身份;真实登录另通过运行实例验证。
|
|
engine.Use(func(c *gin.Context) {
|
|
actor := system.Actor{UserID: 1, AuthorityID: 888}
|
|
if c.GetHeader("X-Test-Actor") == "3" {
|
|
actor = system.Actor{UserID: 3, AuthorityID: 903}
|
|
}
|
|
c.Request = c.Request.WithContext(system.NewActorContext(c.Request.Context(), actor))
|
|
c.Next()
|
|
})
|
|
router.RegisterBusiness(engine.Group(""), handler.NewBusiness(prefs, accounts, bindings))
|
|
promotes := handler.NewBusinessPromote(businessservice.NewBusinessPromoteService(businessbiz.NewBusinessPromoteUsecase(businessdata.NewBusinessPromoteRepo(provider), accountUsecase)))
|
|
engine.GET("/sw/business/:userId/promotes", promotes.List)
|
|
server := httptest.NewServer(engine)
|
|
defer server.Close()
|
|
requestList := func() map[string]any {
|
|
t.Helper()
|
|
req, _ := http.NewRequestWithContext(context.Background(), http.MethodGet, server.URL+"/sw/business/list?pageNum=1&pageSize=10", nil)
|
|
response, err := server.Client().Do(req)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
defer response.Body.Close()
|
|
var body map[string]any
|
|
if err := json.NewDecoder(response.Body).Decode(&body); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if response.StatusCode != 200 || body["code"] != float64(0) {
|
|
t.Fatalf("真实 HTTP 列表请求失败: %+v", body)
|
|
}
|
|
return body["data"].(map[string]any)
|
|
}
|
|
data := requestList()
|
|
rows := data["rows"].([]any)
|
|
if data["total"] != float64(3) || len(rows) != 3 {
|
|
t.Fatalf("系统数据未完整返回: %+v", data)
|
|
}
|
|
child := rows[1].(map[string]any)
|
|
if child["promoteCount"] != nil || child["bindCount"] != float64(1) {
|
|
t.Fatalf("未接入统计不能伪装为零: %+v", child)
|
|
}
|
|
if rows[2].(map[string]any)["promoteCount"] != float64(0) {
|
|
t.Fatal("无绑定账号的直属渠道应明确为零")
|
|
}
|
|
if err := db.Exec("CREATE TABLE tab_promote(id INTEGER,source_db TEXT,busier_id INTEGER,promote_level INTEGER,account TEXT)").Error; err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := db.Exec("INSERT INTO tab_promote VALUES(1,'lx',9,1,'测试渠道'),(2,'lx',9,2,'下级渠道'),(1,'hw',9,1,'其他平台')").Error; err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
data = requestList()
|
|
child = data["rows"].([]any)[1].(map[string]any)
|
|
if child["promoteCount"] != float64(1) {
|
|
t.Fatalf("完整数据应恢复真实且按平台隔离的渠道数: %+v", child)
|
|
}
|
|
call := func(method, path, body, actor string) map[string]any {
|
|
t.Helper()
|
|
req, _ := http.NewRequest(method, server.URL+path, strings.NewReader(body))
|
|
req.Header.Set("Content-Type", "application/json")
|
|
req.Header.Set("X-Test-Actor", actor)
|
|
response, err := server.Client().Do(req)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
defer response.Body.Close()
|
|
var value map[string]any
|
|
if err := json.NewDecoder(response.Body).Decode(&value); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if value["code"] != float64(0) {
|
|
t.Fatalf("%s %s 失败: %+v", method, path, value)
|
|
}
|
|
return value
|
|
}
|
|
created := call("POST", "/sw/business", `{"userName":"http_child","realName":"接口测试","password":"abc123"}`, "")["data"].(map[string]any)
|
|
channels := call("GET", "/sw/business/2/promotes", "", "")["data"].(map[string]any)
|
|
if channels["total"] != float64(1) || channels["rows"].([]any)[0].(map[string]any)["promoteName"] != "测试渠道" {
|
|
t.Fatalf("HTTP 旗下渠道范围错误: %+v", channels)
|
|
}
|
|
if created["userId"] != float64(4) || created["level"] != float64(1) || created["authorityId"] != float64(901) {
|
|
t.Fatalf("HTTP 新增层级或角色不正确: %+v", created)
|
|
}
|
|
call("PUT", "/sw/business", `{"userId":4,"realName":"更新姓名"}`, "")
|
|
updated := call("GET", "/sw/business/4", "", "")["data"].(map[string]any)
|
|
if updated["realName"] != "更新姓名" || updated["status"] != "0" {
|
|
t.Fatalf("HTTP 部分编辑不正确: %+v", updated)
|
|
}
|
|
call("PUT", "/sw/user/preference", `{"includeSubPromote":false,"idcardDedup":false}`, "")
|
|
preference := call("GET", "/sw/user/preference", "", "")["data"].(map[string]any)
|
|
if preference["includeSubPromote"] != false || preference["idcardDedup"] != false {
|
|
t.Fatalf("HTTP 偏好关闭未保存: %+v", preference)
|
|
}
|
|
call("POST", "/sw/business/bindPlatform", `{"sourceDb":"lx","account":"sdk-test","password":"test-only"}`, "3")
|
|
bound := call("GET", "/sw/business/bindPlatform", "", "3")["data"].(map[string]any)
|
|
if bound["total"] != float64(1) || bound["rows"].([]any)[0].(map[string]any)["status"] != "3" {
|
|
t.Fatalf("HTTP 绑定未进入待审核: %+v", bound)
|
|
}
|
|
call("DELETE", "/sw/business/bindPlatform", `{"sourceDb":"lx","platformBusierId":77}`, "3")
|
|
bound = call("GET", "/sw/business/bindPlatform", "", "3")["data"].(map[string]any)
|
|
if bound["total"] != float64(0) {
|
|
t.Fatalf("HTTP 解绑未删除当前账号绑定: %+v", bound)
|
|
}
|
|
}
|