package service import ( "context" "testing" "time" quitmodel "wx_service/internal/quitcheckin/model" "gorm.io/driver/sqlite" "gorm.io/gorm" "gorm.io/gorm/logger" ) func setupQuitHPTestDB(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.HPChangeLog{}, &quitmodel.RewardGoal{}, &quitmodel.DreamPreset{}, ); err != nil { t.Fatalf("auto migrate: %v", err) } return db } func TestQuitCheckinHomeInitializesHP(t *testing.T) { t.Parallel() db := setupQuitHPTestDB(t) svc := NewService(db) ctx := context.Background() uid := 2001 startDate := time.Date(2026, 4, 10, 0, 0, 0, 0, time.Local) now := time.Date(2026, 4, 10, 9, 0, 0, 0, time.Local) if _, err := svc.UpsertProfile(ctx, uid, UpsertProfileRequest{ QuitStartDate: &startDate, PackPriceCent: intPtr(2500), BaselineCigsPerDay: intPtr(12), }, "测试用户", "", now); err != nil { t.Fatalf("upsert profile: %v", err) } home, err := svc.Home(ctx, uid, now) if err != nil { t.Fatalf("home: %v", err) } if home.Summary.HPCurrent <= 0 { t.Fatalf("hp_current=%d, want > 0", home.Summary.HPCurrent) } if home.Summary.HPChangeToday != 0 { t.Fatalf("hp_change_today=%d, want 0", home.Summary.HPChangeToday) } } func TestQuitCheckinCheckinIncreasesHPAndTracksTodayDelta(t *testing.T) { t.Parallel() db := setupQuitHPTestDB(t) svc := NewService(db) ctx := context.Background() uid := 2002 startDate := time.Date(2026, 4, 10, 0, 0, 0, 0, time.Local) day1 := time.Date(2026, 4, 10, 9, 0, 0, 0, time.Local) if _, err := svc.UpsertProfile(ctx, uid, UpsertProfileRequest{ QuitStartDate: &startDate, PackPriceCent: intPtr(2500), BaselineCigsPerDay: intPtr(10), }, "测试用户", "", day1); err != nil { t.Fatalf("upsert profile: %v", err) } before, err := svc.Home(ctx, uid, day1) if err != nil { t.Fatalf("home before: %v", err) } _, err = svc.Checkin(ctx, uid, CheckinRequest{Date: day1, Note: "day1"}, day1) if err != nil { t.Fatalf("checkin: %v", err) } after, err := svc.Home(ctx, uid, day1) if err != nil { t.Fatalf("home after: %v", err) } if after.Summary.HPCurrent <= before.Summary.HPCurrent { t.Fatalf("hp_current before=%d after=%d, want after > before", before.Summary.HPCurrent, after.Summary.HPCurrent) } if after.Summary.HPChangeToday <= 0 { t.Fatalf("hp_change_today=%d, want > 0", after.Summary.HPChangeToday) } } func TestQuitCheckinSmokeSlipDecreasesHPAndMarksRelapsed(t *testing.T) { t.Parallel() db := setupQuitHPTestDB(t) svc := NewService(db) ctx := context.Background() uid := 2003 startDate := time.Date(2026, 4, 10, 0, 0, 0, 0, time.Local) day1 := time.Date(2026, 4, 10, 9, 0, 0, 0, time.Local) if _, err := svc.UpsertProfile(ctx, uid, UpsertProfileRequest{ QuitStartDate: &startDate, PackPriceCent: intPtr(2500), BaselineCigsPerDay: intPtr(8), }, "测试用户", "", day1); err != nil { t.Fatalf("upsert profile: %v", err) } before, err := svc.Home(ctx, uid, day1) if err != nil { t.Fatalf("home before: %v", err) } slipAt := time.Date(2026, 4, 10, 10, 15, 0, 0, time.Local) if err := svc.RecordSmokeSlip(ctx, uid, slipAt, 1, "slip"); err != nil { t.Fatalf("record slip: %v", err) } after, err := svc.Home(ctx, uid, day1) if err != nil { t.Fatalf("home after: %v", err) } if after.DailyStatus.Status != quitmodel.DailyStatusRelapsed { t.Fatalf("daily status=%s, want=%s", after.DailyStatus.Status, quitmodel.DailyStatusRelapsed) } if after.Summary.HPCurrent >= before.Summary.HPCurrent { t.Fatalf("hp_current before=%d after=%d, want after < before", before.Summary.HPCurrent, after.Summary.HPCurrent) } if after.Summary.HPChangeToday >= 0 { t.Fatalf("hp_change_today=%d, want < 0", after.Summary.HPChangeToday) } if after.Summary.CurrentStreakDays != 0 { t.Fatalf("current_streak_days=%d, want 0", after.Summary.CurrentStreakDays) } }