Initial commit

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-15 13:57:10 +08:00
co-authored by Claude Opus 5
commit 8679200f41
1897 changed files with 257900 additions and 0 deletions
+302
View File
@@ -0,0 +1,302 @@
package main
import (
"fmt"
"time"
"91porn-server/common/timeutil"
"91porn-server/models/v/checkinconfigmod"
"91porn-server/models/v/checkinprizemod"
"91porn-server/models/v/usercheckinmod"
fw "git.ruishengces.com/pub_tool/autotest"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/bson/primitive"
)
type CheckinSuite struct {
env *Env
url string // AppBaseURL
prizeIds []primitive.ObjectID
}
func (s *CheckinSuite) Name() string { return "签到功能" }
func (s *CheckinSuite) Setup(ctx *fw.TestContext) error {
// 确保签到功能已启用
cfg, _ := checkinconfigmod.FindOne(bson.M{})
if cfg == nil {
if err := checkinconfigmod.InsertOne(&checkinconfigmod.CheckinConfig{
Enable: true,
Description: "测试签到",
}); err != nil {
return err
}
} else if !cfg.Enable {
if err := checkinconfigmod.UpdateOne(bson.M{"_id": cfg.ID}, bson.M{"$set": bson.M{"enable": true}}); err != nil {
return err
}
}
// 创建测试用签到奖品配置(连续签到第1~3天)
s.prizeIds = make([]primitive.ObjectID, 3)
for i := 0; i < 3; i++ {
id := primitive.NewObjectID()
s.prizeIds[i] = id
if err := checkinprizemod.InsertOne(&checkinprizemod.CheckinPrize{
ID: id,
Title: fmt.Sprintf("测试奖品第%d天", i+1),
CheckinDays: int64(i + 1),
CheckinType: checkinprizemod.CheckinTypeContinuously,
PrizeId: primitive.NewObjectID(), // 故意用不存在的奖品ID
PrizeName: fmt.Sprintf("测试奖品%d", i+1),
Status: true,
BigPrize: false,
}); err != nil {
return err
}
}
return nil
}
func (s *CheckinSuite) Teardown(ctx *fw.TestContext) {
s.cleanCheckins()
s.cleanPrizes()
}
func (s *CheckinSuite) cleanCheckins() {
for {
n, _ := usercheckinmod.DeleteOne(bson.M{"userId": s.env.TestUID})
if n == 0 {
break
}
}
}
func (s *CheckinSuite) cleanPrizes() {
for _, id := range s.prizeIds {
checkinprizemod.DeleteOne(bson.M{"_id": id})
}
}
func (s *CheckinSuite) insertRecord(date time.Time, contDays, cumDays int64) {
s.insertRecordWithGave(date, contDays, cumDays, true)
}
func (s *CheckinSuite) insertRecordWithGave(date time.Time, contDays, cumDays int64, gave bool) {
_ = usercheckinmod.InsertOne(&usercheckinmod.UserCheckin{
ID: primitive.NewObjectID(),
Date: timeutil.BeginOfTime(date),
UserId: s.env.TestUID,
Gave: gave,
ContinuouslyDays: contDays,
CumulativeDays: cumDays,
CreatedAt: date,
})
}
func (s *CheckinSuite) headers() map[string]string {
return map[string]string{
"Authorization": s.env.AppToken,
"User-Agent": "91porn/3.8.0 (Android; test)",
"X-User-Agent": "ver=3.8.0&sysType=android&devType=test&devId=checkin-test-001",
}
}
func (s *CheckinSuite) getPrize() *fw.Resp {
return fw.DoWithHeaders("POST", s.url+"/api/app/checkin/prize", map[string]interface{}{}, s.headers())
}
func (s *CheckinSuite) Run(ctx *fw.TestContext) {
s.testQueryEmpty(ctx)
s.testContinuous3Days(ctx)
s.testBrokenStreak(ctx)
s.testBrokenStreakOneDayGap(ctx)
s.testCrossMonthContinuous(ctx)
s.testTodayChecked(ctx)
s.testDoubleReward(ctx)
s.testCheckinAfterBroken(ctx)
s.testIsCheckedIn(ctx)
}
// 空数据查询
func (s *CheckinSuite) testQueryEmpty(ctx *fw.TestContext) {
s.cleanCheckins()
resp := s.getPrize()
ctx.CodeEqual("空数据查询-code=200", resp, 200)
data := resp.Data()
if data != nil {
checkin, _ := data["checkin"].(map[string]interface{})
if checkin != nil {
ctx.Equal("空数据-todayChecked=false", checkin["todayChecked"], false)
ctx.Equal("空数据-连续=0", fw.Num(checkin, "continuouslyDays"), float64(0))
ctx.Equal("空数据-累计=0", fw.Num(checkin, "cumulativeDays"), float64(0))
}
}
}
// 连续签到3天
func (s *CheckinSuite) testContinuous3Days(ctx *fw.TestContext) {
s.cleanCheckins()
now := time.Now().Local()
today := timeutil.BeginOfTime(now)
s.insertRecord(today.Add(-3*24*time.Hour), 1, 1)
s.insertRecord(today.Add(-2*24*time.Hour), 2, 2)
s.insertRecord(today.Add(-1*24*time.Hour), 3, 3)
resp := s.getPrize()
ctx.CodeEqual("连续3天-code=200", resp, 200)
data := resp.Data()
checkin, _ := data["checkin"].(map[string]interface{})
ctx.Equal("连续3天-todayChecked=false", checkin["todayChecked"], false)
ctx.Equal("连续3天-continuously=3", fw.Num(checkin, "continuouslyDays"), float64(3))
ctx.Equal("连续3天-cumulative=3", fw.Num(checkin, "cumulativeDays"), float64(3))
}
// 断签:4天前、3天前签到,昨天和前天没签
func (s *CheckinSuite) testBrokenStreak(ctx *fw.TestContext) {
s.cleanCheckins()
now := time.Now().Local()
today := timeutil.BeginOfTime(now)
s.insertRecord(today.Add(-4*24*time.Hour), 1, 1)
s.insertRecord(today.Add(-3*24*time.Hour), 2, 2)
resp := s.getPrize()
ctx.CodeEqual("断签-code=200", resp, 200)
checkin, _ := resp.Data()["checkin"].(map[string]interface{})
ctx.Equal("断签-continuously=0", fw.Num(checkin, "continuouslyDays"), float64(0))
ctx.Equal("断签-cumulative=2", fw.Num(checkin, "cumulativeDays"), float64(2))
}
// 中间断一天:3天前签,2天前没签,昨天签
func (s *CheckinSuite) testBrokenStreakOneDayGap(ctx *fw.TestContext) {
s.cleanCheckins()
now := time.Now().Local()
today := timeutil.BeginOfTime(now)
s.insertRecord(today.Add(-3*24*time.Hour), 1, 1)
s.insertRecord(today.Add(-1*24*time.Hour), 1, 2)
resp := s.getPrize()
ctx.CodeEqual("断一天-code=200", resp, 200)
checkin, _ := resp.Data()["checkin"].(map[string]interface{})
ctx.Equal("断一天-continuously=1", fw.Num(checkin, "continuouslyDays"), float64(1))
ctx.Equal("断一天-cumulative=2", fw.Num(checkin, "cumulativeDays"), float64(2))
}
// 跨月:上月记录不计入连续
func (s *CheckinSuite) testCrossMonthContinuous(ctx *fw.TestContext) {
s.cleanCheckins()
now := time.Now().Local()
beginOfMonth := timeutil.BeginningOfMonth(now)
s.insertRecord(beginOfMonth.Add(-3*24*time.Hour), 1, 1)
s.insertRecord(beginOfMonth.Add(-2*24*time.Hour), 2, 2)
s.insertRecord(beginOfMonth.Add(-1*24*time.Hour), 3, 3)
resp := s.getPrize()
ctx.CodeEqual("跨月-code=200", resp, 200)
checkin, _ := resp.Data()["checkin"].(map[string]interface{})
ctx.Equal("跨月-continuously=0", fw.Num(checkin, "continuouslyDays"), float64(0))
ctx.Info(fmt.Sprintf("跨月-cumulative=%v (含上月记录,原版行为)", fw.Num(checkin, "cumulativeDays")))
}
// 今天已签到
func (s *CheckinSuite) testTodayChecked(ctx *fw.TestContext) {
s.cleanCheckins()
now := time.Now().Local()
today := timeutil.BeginOfTime(now)
if now.Day() < 3 {
ctx.Info("月初不足3天,跳过今天已签到测试")
return
}
s.insertRecord(today.Add(-2*24*time.Hour), 1, 1)
s.insertRecord(today.Add(-1*24*time.Hour), 2, 2)
s.insertRecord(today, 3, 3)
resp := s.getPrize()
ctx.CodeEqual("今天已签到-code=200", resp, 200)
checkin, _ := resp.Data()["checkin"].(map[string]interface{})
ctx.Equal("今天已签到-todayChecked=true", checkin["todayChecked"], true)
ctx.Equal("今天已签到-continuously=3", fw.Num(checkin, "continuouslyDays"), float64(3))
}
// 第7天双倍奖励
func (s *CheckinSuite) testDoubleReward(ctx *fw.TestContext) {
s.cleanCheckins()
now := time.Now().Local()
today := timeutil.BeginOfTime(now)
if now.Day() < 7 {
ctx.Info("本月不足7天,跳过双倍奖励测试")
return
}
for i := 6; i >= 1; i-- {
d := today.Add(time.Duration(-i) * 24 * time.Hour)
s.insertRecord(d, int64(7-i), int64(7-i))
}
resp := s.getPrize()
ctx.CodeEqual("双倍奖励-code=200", resp, 200)
checkin, _ := resp.Data()["checkin"].(map[string]interface{})
ctx.Equal("6天连续+未签到-doubleReward=true", checkin["doubleReward"], true)
ctx.Equal("6天连续-continuously=6", fw.Num(checkin, "continuouslyDays"), float64(6))
}
// 断签后恢复
func (s *CheckinSuite) testCheckinAfterBroken(ctx *fw.TestContext) {
s.cleanCheckins()
now := time.Now().Local()
today := timeutil.BeginOfTime(now)
if now.Day() < 5 {
ctx.Info("月初不足5天,跳过断签恢复测试")
return
}
s.insertRecord(today.Add(-5*24*time.Hour), 1, 1)
s.insertRecord(today.Add(-4*24*time.Hour), 2, 2)
// 3天前和2天前断签
s.insertRecord(today.Add(-1*24*time.Hour), 1, 3)
resp := s.getPrize()
ctx.CodeEqual("断签恢复-code=200", resp, 200)
checkin, _ := resp.Data()["checkin"].(map[string]interface{})
ctx.Equal("断签恢复-continuously=1", fw.Num(checkin, "continuouslyDays"), float64(1))
ctx.Equal("断签恢复-cumulative=3", fw.Num(checkin, "cumulativeDays"), float64(3))
}
// isCheckedIn字段:签到但未发奖时isCheckedIn=trueisReceive=false
func (s *CheckinSuite) testIsCheckedIn(ctx *fw.TestContext) {
s.cleanCheckins()
now := time.Now().Local()
today := timeutil.BeginOfTime(now)
if now.Day() < 3 {
ctx.Info("月初不足3天,跳过isCheckedIn测试")
return
}
// 第1天正常发奖,第2天签到但未发奖(Gave=false),第3天正常发奖
s.insertRecord(today.Add(-2*24*time.Hour), 1, 1)
s.insertRecordWithGave(today.Add(-1*24*time.Hour), 2, 2, false) // 签到了但奖品未发放
s.insertRecord(today, 3, 3)
resp := s.getPrize()
ctx.CodeEqual("isCheckedIn-code=200", resp, 200)
data := resp.Data()
prizes, _ := data["prizes"].([]interface{})
if len(prizes) < 3 {
ctx.Info(fmt.Sprintf("prizes数量不足3个(got=%d),跳过isCheckedIn断言", len(prizes)))
return
}
// 第1天:isCheckedIn=true, isReceive=true
p1, _ := prizes[0].(map[string]interface{})
ctx.Equal("第1天-isCheckedIn=true", p1["isCheckedIn"], true)
ctx.Equal("第1天-isReceive=true", p1["isReceive"], true)
// 第2天:签到了但未发奖 → isCheckedIn=true, isReceive=false
p2, _ := prizes[1].(map[string]interface{})
ctx.Equal("第2天-isCheckedIn=true(签到未发奖)", p2["isCheckedIn"], true)
ctx.Equal("第2天-isReceive=false(奖品未发放)", p2["isReceive"], false)
// 第3天:isCheckedIn=true, isReceive=true
p3, _ := prizes[2].(map[string]interface{})
ctx.Equal("第3天-isCheckedIn=true", p3["isCheckedIn"], true)
ctx.Equal("第3天-isReceive=true", p3["isReceive"], true)
}