Files
huangguo_server/tests/checkin/suite_checkin.go
T
rootandClaude Opus 5 8679200f41 Initial commit
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-15 13:57:10 +08:00

303 lines
9.9 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 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)
}