154 lines
3.6 KiB
Go
154 lines
3.6 KiB
Go
package service
|
|
|
|
import (
|
|
"context"
|
|
"testing"
|
|
"time"
|
|
|
|
quitmodel "wx_service/internal/quitcheckin/model"
|
|
|
|
"gorm.io/driver/sqlite"
|
|
"gorm.io/gorm"
|
|
"gorm.io/gorm/logger"
|
|
)
|
|
|
|
func setupReminderTestDB(t *testing.T) *gorm.DB {
|
|
t.Helper()
|
|
|
|
db, err := gorm.Open(sqlite.Open(":memory:"), &gorm.Config{
|
|
Logger: logger.Default.LogMode(logger.Silent),
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("open sqlite: %v", err)
|
|
}
|
|
|
|
if err := db.AutoMigrate(
|
|
&quitmodel.Profile{},
|
|
&quitmodel.DailyStatus{},
|
|
&quitmodel.RelapseEvent{},
|
|
&quitmodel.RewardGoal{},
|
|
&quitmodel.DreamPreset{},
|
|
&quitmodel.SupervisorBinding{},
|
|
&quitmodel.SupervisorInvite{},
|
|
&quitmodel.SupervisorReminderSetting{},
|
|
&quitmodel.SupervisorReminderLog{},
|
|
&quitmodel.HPChangeLog{},
|
|
); err != nil {
|
|
t.Fatalf("auto migrate: %v", err)
|
|
}
|
|
|
|
return db
|
|
}
|
|
|
|
func TestReminderRunCreatesLogAfterNotifyTime(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
db := setupReminderTestDB(t)
|
|
svc := NewService(db)
|
|
ctx := context.Background()
|
|
|
|
ownerUID := 4001
|
|
supervisorUID := 4002
|
|
|
|
startDate := time.Date(2026, 4, 10, 0, 0, 0, 0, time.Local)
|
|
now := time.Date(2026, 4, 16, 21, 30, 0, 0, time.Local)
|
|
|
|
// seed quit profile
|
|
if err := db.Create(&quitmodel.Profile{
|
|
UID: ownerUID,
|
|
QuitStartDate: startDate,
|
|
PackPriceCent: 2500,
|
|
BaselineCigsPerDay: 10,
|
|
NotifyTime: "21:00",
|
|
ResetRule: "relapse_clears_streak",
|
|
}).Error; err != nil {
|
|
t.Fatalf("seed profile: %v", err)
|
|
}
|
|
|
|
// seed binding
|
|
if err := db.Create(&quitmodel.SupervisorBinding{
|
|
OwnerUID: ownerUID,
|
|
SupervisorUID: supervisorUID,
|
|
Status: "active",
|
|
}).Error; err != nil {
|
|
t.Fatalf("seed binding: %v", err)
|
|
}
|
|
|
|
// enable reminder
|
|
if err := db.Create(&quitmodel.SupervisorReminderSetting{
|
|
OwnerUID: ownerUID,
|
|
Enabled: true,
|
|
NotifyTime: "21:00",
|
|
MaxPerDay: 1,
|
|
ChannelHint: "stub",
|
|
}).Error; err != nil {
|
|
t.Fatalf("seed setting: %v", err)
|
|
}
|
|
|
|
res, err := svc.RunMissedCheckinRemindersForSupervisor(ctx, supervisorUID, now)
|
|
if err != nil {
|
|
t.Fatalf("run: %v", err)
|
|
}
|
|
if res.Created != 1 {
|
|
t.Fatalf("created=%d want=1", res.Created)
|
|
}
|
|
|
|
// run again should be rate-limited
|
|
res2, err := svc.RunMissedCheckinRemindersForSupervisor(ctx, supervisorUID, now.Add(10*time.Minute))
|
|
if err != nil {
|
|
t.Fatalf("run2: %v", err)
|
|
}
|
|
if res2.Created != 0 {
|
|
t.Fatalf("created2=%d want=0", res2.Created)
|
|
}
|
|
}
|
|
|
|
func TestReminderRunSkipsBeforeNotifyTime(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
db := setupReminderTestDB(t)
|
|
svc := NewService(db)
|
|
ctx := context.Background()
|
|
|
|
ownerUID := 4011
|
|
supervisorUID := 4012
|
|
|
|
startDate := time.Date(2026, 4, 10, 0, 0, 0, 0, time.Local)
|
|
now := time.Date(2026, 4, 16, 20, 50, 0, 0, time.Local)
|
|
|
|
if err := db.Create(&quitmodel.Profile{
|
|
UID: ownerUID,
|
|
QuitStartDate: startDate,
|
|
PackPriceCent: 2500,
|
|
BaselineCigsPerDay: 10,
|
|
NotifyTime: "21:00",
|
|
ResetRule: "relapse_clears_streak",
|
|
}).Error; err != nil {
|
|
t.Fatalf("seed profile: %v", err)
|
|
}
|
|
if err := db.Create(&quitmodel.SupervisorBinding{
|
|
OwnerUID: ownerUID,
|
|
SupervisorUID: supervisorUID,
|
|
Status: "active",
|
|
}).Error; err != nil {
|
|
t.Fatalf("seed binding: %v", err)
|
|
}
|
|
if err := db.Create(&quitmodel.SupervisorReminderSetting{
|
|
OwnerUID: ownerUID,
|
|
Enabled: true,
|
|
NotifyTime: "21:00",
|
|
MaxPerDay: 1,
|
|
ChannelHint: "stub",
|
|
}).Error; err != nil {
|
|
t.Fatalf("seed setting: %v", err)
|
|
}
|
|
|
|
res, err := svc.RunMissedCheckinRemindersForSupervisor(ctx, supervisorUID, now)
|
|
if err != nil {
|
|
t.Fatalf("run: %v", err)
|
|
}
|
|
if res.Created != 0 {
|
|
t.Fatalf("created=%d want=0", res.Created)
|
|
}
|
|
}
|