Files
observer/server/biz/service/admin_test.go
T
2026-08-25 16:52:55 +08:00

191 lines
6.6 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package service
// 管理端白盒测试:手动授权/撤销、订单分页、套餐更新、账号注册/登录。
// 运行方式同 payment_test.gocd server && GF_GCFG_FILE=biz/service/testdata/config.yml go test ./biz/service/
import (
"strconv"
"testing"
"time"
"github.com/gogf/gf/v2/os/gtime"
"observer-server/biz/consts"
"observer-server/biz/dao"
"observer-server/biz/model/dto"
"observer-server/biz/model/entity"
"observer-server/common"
)
func startOfToday() time.Time {
now := time.Now()
return time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, time.Local)
}
// TestAuthRegisterLogin 注册/登录:注册后可登录、密码错误拒绝、重复注册报错
func TestAuthRegisterLogin(t *testing.T) {
phone := uniquePhone()
if _, err := Auth.Register(ctx(), &dto.RegisterReq{Phone: phone, Password: "pass123456"}); err != nil {
t.Fatalf("register: %v", err)
}
// 登录成功,token 可解析回手机号
res, err := Auth.Login(ctx(), &dto.LoginReq{Phone: phone, Password: "pass123456"})
if err != nil {
t.Fatalf("login: %v", err)
}
got, err := common.ParseToken(ctx(), res.Token)
if err != nil || got != phone {
t.Fatalf("parse token = %q, %v; want %q", got, err, phone)
}
// 密码错误
if _, err := Auth.Login(ctx(), &dto.LoginReq{Phone: phone, Password: "wrong"}); err == nil {
t.Fatal("wrong password should fail")
}
// 重复注册
if _, err := Auth.Register(ctx(), &dto.RegisterReq{Phone: phone, Password: "other123"}); err == nil {
t.Fatal("duplicate register should fail")
}
// 未注册手机号登录失败
if _, err := Auth.Login(ctx(), &dto.LoginReq{Phone: uniquePhone(), Password: "pass123456"}); err == nil {
t.Fatal("login unregistered phone should fail")
}
}
// TestAuthRegisterAfterGrant 运营先手动授权(占位行无密码)→ 用户注册补密码 → 登录成功
func TestAuthRegisterAfterGrant(t *testing.T) {
phone := uniquePhone()
if _, err := License.AdminGrant(ctx(), &dto.AdminGrantReq{PhoneNum: phone, PlanId: "day"}); err != nil {
t.Fatalf("grant: %v", err)
}
if _, err := Auth.Register(ctx(), &dto.RegisterReq{Phone: phone, Password: "pass123456"}); err != nil {
t.Fatalf("register after grant: %v", err)
}
if _, err := Auth.Login(ctx(), &dto.LoginReq{Phone: phone, Password: "pass123456"}); err != nil {
t.Fatalf("login after register: %v", err)
}
// 注册补密码不能清掉已授权
lic, err := dao.License.GetByPhone(ctx(), phone)
if err != nil || lic == nil || lic.ExpiresAt == nil {
t.Fatalf("grant lost after register: %+v, %v", lic, err)
}
}
// TestAdminGrant 手动授权:新账号从今天 0 点起按套餐天数累计
func TestAdminGrant(t *testing.T) {
phone := uniquePhone()
res, err := License.AdminGrant(ctx(), &dto.AdminGrantReq{PhoneNum: phone, PlanId: "week"})
if err != nil {
t.Fatalf("grant: %v", err)
}
want := startOfToday().AddDate(0, 0, 7)
if !res.ExpiresAt.Time.Equal(want) {
t.Fatalf("grant expiresAt = %s, want %s", res.ExpiresAt, want)
}
lic, err := License.Get(common.WithPhone(ctx(), phone), &dto.LicenseReq{})
if err != nil {
t.Fatal(err)
}
if !lic.Active {
t.Fatalf("license res = %+v", lic)
}
}
// TestAdminGrantRenewal 手动授权续期叠加:未过期顺延;无效套餐报错
func TestAdminGrantRenewal(t *testing.T) {
phone := uniquePhone()
if _, err := License.AdminGrant(ctx(), &dto.AdminGrantReq{PhoneNum: phone, PlanId: "week"}); err != nil {
t.Fatalf("grant 1: %v", err)
}
lic, _ := dao.License.GetByPhone(ctx(), phone)
res, err := License.AdminGrant(ctx(), &dto.AdminGrantReq{PhoneNum: phone, PlanId: "month"})
if err != nil {
t.Fatalf("grant 2: %v", err)
}
want := lic.ExpiresAt.Time.AddDate(0, 0, 30)
if !res.ExpiresAt.Time.Equal(want) {
t.Fatalf("renewal expiresAt = %s, want %s (base %s)", res.ExpiresAt, want, lic.ExpiresAt)
}
if _, err := License.AdminGrant(ctx(), &dto.AdminGrantReq{PhoneNum: phone, PlanId: "nope"}); err == nil {
t.Fatal("invalid plan should fail")
}
}
// TestAdminRevoke 撤销授权:清授权字段保留账号(可继续登录),授权查询立即 inactive
func TestAdminRevoke(t *testing.T) {
phone := uniquePhone()
if _, err := Auth.Register(ctx(), &dto.RegisterReq{Phone: phone, Password: "pass123456"}); err != nil {
t.Fatalf("register: %v", err)
}
if _, err := License.AdminGrant(ctx(), &dto.AdminGrantReq{PhoneNum: phone, PlanId: "day"}); err != nil {
t.Fatalf("grant: %v", err)
}
if _, err := License.AdminRevoke(ctx(), &dto.AdminRevokeReq{PhoneNum: phone}); err != nil {
t.Fatalf("revoke: %v", err)
}
lic, err := License.Get(common.WithPhone(ctx(), phone), &dto.LicenseReq{})
if err != nil {
t.Fatal(err)
}
if lic.Active {
t.Fatal("license should be inactive after revoke")
}
row, err := dao.License.GetByPhone(ctx(), phone)
if err != nil {
t.Fatal(err)
}
if row == nil || row.ExpiresAt != nil {
t.Fatalf("account row should be kept with auth cleared: %+v", row)
}
// 账号仍可登录(密码未删)
if _, err := Auth.Login(ctx(), &dto.LoginReq{Phone: phone, Password: "pass123456"}); err != nil {
t.Fatalf("login after revoke: %v", err)
}
}
// TestAdminListOrders 订单分页与筛选:总数、渠道筛选、分页截断
func TestAdminListOrders(t *testing.T) {
phone := uniquePhone()
orderId := uniqueOrderId("O-list-2-")
for i, channel := range []string{consts.ChannelWechat, consts.ChannelWechat, consts.ChannelAlipay} {
insertOrder(t, &entity.PaymentOrder{
OrderId: uniqueOrderId("O-list-" + strconv.Itoa(i) + "-"), PhoneNum: phone, PlanId: "day", Channel: channel,
AmountCents: 1000, Status: consts.OrderStatusCreated, CreatedAt: gtime.Now(),
})
}
insertOrder(t, &entity.PaymentOrder{
OrderId: orderId, PhoneNum: phone, PlanId: "day", Channel: consts.ChannelWechat,
AmountCents: 1000, Status: consts.OrderStatusCreated, CreatedAt: gtime.Now(),
})
res, err := Order.AdminListOrders(ctx(), &dto.AdminOrderListReq{PhoneNum: phone, Size: 2})
if err != nil {
t.Fatalf("list orders: %v", err)
}
if res.Total != 4 || len(res.List) != 2 {
t.Fatalf("total=%d len=%d, want 4/2", res.Total, len(res.List))
}
}
// TestListPlans 套餐列表:来自 testdata/config.yml plans 节点(配置驱动,无数据库表)
func TestListPlans(t *testing.T) {
res, err := Order.ListPlans(ctx(), &dto.ListPlansReq{})
if err != nil {
t.Fatalf("list plans: %v", err)
}
if len(res.List) != 3 {
t.Fatalf("plans = %d, want 3", len(res.List))
}
var week *dto.PlanItem
for _, p := range res.List {
if p.PlanId == "week" {
week = p
}
}
if week == nil || week.Days != 7 || week.PriceCents != 5600 {
t.Fatalf("week plan = %+v, want days=7 priceCents=5600", week)
}
}