120 lines
4.0 KiB
Go
120 lines
4.0 KiB
Go
package sevendaycheckin_test
|
|
|
|
import (
|
|
"context"
|
|
"testing"
|
|
"time"
|
|
|
|
"google.golang.org/grpc"
|
|
walletv1 "hyapp.local/api/proto/wallet/v1"
|
|
"hyapp/pkg/appcode"
|
|
domain "hyapp/services/activity-service/internal/domain/sevendaycheckin"
|
|
service "hyapp/services/activity-service/internal/service/sevendaycheckin"
|
|
"hyapp/services/activity-service/internal/testutil/mysqltest"
|
|
)
|
|
|
|
func TestSevenDayCheckInClaimCycleAndIdempotency(t *testing.T) {
|
|
repository := mysqltest.NewRepository(t)
|
|
wallet := &fakeCheckInWallet{}
|
|
svc := service.New(repository, wallet)
|
|
ctx := appcode.WithContext(context.Background(), "lalu")
|
|
now := time.Date(2026, 5, 16, 10, 0, 0, 0, time.FixedZone("CST", 8*60*60))
|
|
svc.SetClock(func() time.Time { return now })
|
|
|
|
if _, err := svc.UpdateConfig(ctx, domain.Config{
|
|
Enabled: true,
|
|
Rewards: checkInRewards(7000),
|
|
UpdatedByAdminID: 90001,
|
|
}); err != nil {
|
|
t.Fatalf("UpdateConfig failed: %v", err)
|
|
}
|
|
|
|
first, err := svc.Sign(ctx, 10001, "cmd-checkin-1")
|
|
if err != nil {
|
|
t.Fatalf("first Sign failed: %v", err)
|
|
}
|
|
if first.Status != domain.StatusGranted || first.DayIndex != 1 || first.ResourceGroupID != 7001 || first.WalletGrantID != "grant-1" {
|
|
t.Fatalf("first claim mismatch: %+v", first)
|
|
}
|
|
again, err := svc.Sign(ctx, 10001, "cmd-checkin-1")
|
|
if err != nil {
|
|
t.Fatalf("retry Sign failed: %v", err)
|
|
}
|
|
if again.ClaimID != first.ClaimID || wallet.calls != 1 {
|
|
t.Fatalf("idempotency mismatch: first=%+v again=%+v calls=%d", first, again, wallet.calls)
|
|
}
|
|
|
|
status, err := svc.GetStatus(ctx, 10001)
|
|
if err != nil {
|
|
t.Fatalf("GetStatus failed: %v", err)
|
|
}
|
|
if status.CanSign || status.Reason != domain.ReasonAlreadySigned || status.CurrentDayIndex != 1 || status.Rewards[0].Status != domain.RewardStatusGranted {
|
|
t.Fatalf("signed status mismatch: %+v", status)
|
|
}
|
|
|
|
now = now.AddDate(0, 0, 1)
|
|
second, err := svc.Sign(ctx, 10001, "cmd-checkin-2")
|
|
if err != nil {
|
|
t.Fatalf("second Sign failed: %v", err)
|
|
}
|
|
if second.CycleNo != 1 || second.DayIndex != 2 || second.ResourceGroupID != 7002 {
|
|
t.Fatalf("second claim mismatch: %+v", second)
|
|
}
|
|
|
|
now = now.AddDate(0, 0, 2)
|
|
reset, err := svc.Sign(ctx, 10001, "cmd-checkin-reset")
|
|
if err != nil {
|
|
t.Fatalf("reset Sign failed: %v", err)
|
|
}
|
|
if reset.CycleNo != 2 || reset.DayIndex != 1 || reset.ResourceGroupID != 7001 {
|
|
t.Fatalf("reset claim mismatch: %+v", reset)
|
|
}
|
|
}
|
|
|
|
func TestSevenDayCheckInKeepsCycleConfigVersion(t *testing.T) {
|
|
repository := mysqltest.NewRepository(t)
|
|
wallet := &fakeCheckInWallet{}
|
|
svc := service.New(repository, wallet)
|
|
ctx := appcode.WithContext(context.Background(), "lalu")
|
|
now := time.Date(2026, 5, 16, 0, 0, 0, 0, time.UTC)
|
|
svc.SetClock(func() time.Time { return now })
|
|
|
|
if _, err := svc.UpdateConfig(ctx, domain.Config{Enabled: true, Rewards: checkInRewards(1000), UpdatedByAdminID: 90001}); err != nil {
|
|
t.Fatalf("seed config v1 failed: %v", err)
|
|
}
|
|
first, err := svc.Sign(ctx, 20001, "cmd-version-1")
|
|
if err != nil {
|
|
t.Fatalf("sign v1 failed: %v", err)
|
|
}
|
|
if _, err := svc.UpdateConfig(ctx, domain.Config{Enabled: true, Rewards: checkInRewards(2000), UpdatedByAdminID: 90001}); err != nil {
|
|
t.Fatalf("update config v2 failed: %v", err)
|
|
}
|
|
now = now.AddDate(0, 0, 1)
|
|
second, err := svc.Sign(ctx, 20001, "cmd-version-2")
|
|
if err != nil {
|
|
t.Fatalf("sign v1 day 2 failed: %v", err)
|
|
}
|
|
if first.ConfigVersion != second.ConfigVersion || second.ResourceGroupID != 1002 {
|
|
t.Fatalf("cycle should keep original config: first=%+v second=%+v", first, second)
|
|
}
|
|
}
|
|
|
|
func checkInRewards(base int64) []domain.Reward {
|
|
rewards := make([]domain.Reward, 0, domain.DayCount)
|
|
for day := int32(1); day <= domain.DayCount; day++ {
|
|
rewards = append(rewards, domain.Reward{DayIndex: day, ResourceGroupID: base + int64(day)})
|
|
}
|
|
return rewards
|
|
}
|
|
|
|
type fakeCheckInWallet struct {
|
|
calls int
|
|
}
|
|
|
|
func (f *fakeCheckInWallet) GrantResourceGroup(context.Context, *walletv1.GrantResourceGroupRequest, ...grpc.CallOption) (*walletv1.ResourceGrantResponse, error) {
|
|
f.calls++
|
|
return &walletv1.ResourceGrantResponse{
|
|
Grant: &walletv1.ResourceGrant{GrantId: "grant-1"},
|
|
}, nil
|
|
}
|