feat: add stickers
This commit is contained in:
@@ -0,0 +1,140 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/joho/godotenv"
|
||||
"github.com/prabhupadasays/spsays-bff/internal/repository"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
func testRewardRepo(t *testing.T) (*repository.RewardRepo, *repository.Postgres) {
|
||||
t.Helper()
|
||||
uri := os.Getenv("POSTGRES_URI")
|
||||
if uri == "" {
|
||||
_ = godotenv.Load(filepath.Join("..", "..", ".env"))
|
||||
uri = os.Getenv("POSTGRES_URI")
|
||||
}
|
||||
if uri == "" {
|
||||
t.Skip("POSTGRES_URI not set")
|
||||
}
|
||||
pg, err := repository.NewPostgres(context.Background(), uri, zap.NewNop())
|
||||
if err != nil {
|
||||
t.Skipf("postgres unreachable: %v", err)
|
||||
}
|
||||
t.Cleanup(pg.Close)
|
||||
return repository.NewRewardRepo(pg), pg
|
||||
}
|
||||
|
||||
func giftUser(t *testing.T, pg *repository.Postgres) string {
|
||||
t.Helper()
|
||||
id := uuid.NewString()
|
||||
suffix := id[:8]
|
||||
if _, err := pg.Pool.Exec(context.Background(), `
|
||||
INSERT INTO users (id, email, password_hash, name, handle)
|
||||
VALUES ($1, $2, 'x', 'Gift User', $3)`,
|
||||
id, "gift-"+suffix+"@example.invalid", "gift_"+suffix); err != nil {
|
||||
t.Fatalf("create user: %v", err)
|
||||
}
|
||||
t.Cleanup(func() {
|
||||
_, _ = pg.Pool.Exec(context.Background(), `DELETE FROM users WHERE id = $1`, id)
|
||||
})
|
||||
return id
|
||||
}
|
||||
|
||||
func giftReward(t *testing.T, pg *repository.Postgres) string {
|
||||
t.Helper()
|
||||
key := "gift_" + uuid.NewString()[:8]
|
||||
if _, err := pg.Pool.Exec(context.Background(), `
|
||||
INSERT INTO sadhna_rewards (key, name, image_url)
|
||||
VALUES ($1, 'Occasional Gift', 'https://example.invalid/g.png')`, key); err != nil {
|
||||
t.Fatalf("create reward: %v", err)
|
||||
}
|
||||
t.Cleanup(func() {
|
||||
_, _ = pg.Pool.Exec(context.Background(), `DELETE FROM sadhna_rewards WHERE key = $1`, key)
|
||||
})
|
||||
return key
|
||||
}
|
||||
|
||||
// A gift arrives wrapped, opens once, and lands in the vault — and re-gifting
|
||||
// must not duplicate it.
|
||||
func TestGift_ArrivesWrappedAndOpensOnce(t *testing.T) {
|
||||
rewards, pg := testRewardRepo(t)
|
||||
ctx := context.Background()
|
||||
user := giftUser(t, pg)
|
||||
key := giftReward(t, pg)
|
||||
|
||||
reward, err := rewards.ByKey(ctx, key)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if _, err := rewards.GrantGiftToEveryone(ctx, reward.ID); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
find := func() (found bool, opened bool) {
|
||||
grants, err := rewards.GrantsByUser(ctx, user)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
for _, g := range grants {
|
||||
if g.Reward.Key == key {
|
||||
if g.Source != "gift" {
|
||||
t.Errorf("source = %q, want gift", g.Source)
|
||||
}
|
||||
if g.Milestone != nil {
|
||||
t.Errorf("milestone = %v, want nil — a gift isn't a streak day", *g.Milestone)
|
||||
}
|
||||
return true, g.Opened
|
||||
}
|
||||
}
|
||||
return false, false
|
||||
}
|
||||
|
||||
found, opened := find()
|
||||
if !found {
|
||||
t.Fatal("the gift did not reach an existing account")
|
||||
}
|
||||
if opened {
|
||||
t.Error("a new gift should arrive wrapped")
|
||||
}
|
||||
|
||||
// It must NOT hijack the streak confetti — that stays for streak rewards.
|
||||
if pending, _ := rewards.PendingGrant(ctx, user); pending != nil {
|
||||
t.Errorf("a gift appeared as a pending streak celebration: %+v", pending)
|
||||
}
|
||||
|
||||
if err := rewards.OpenGift(ctx, user, key); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if _, opened = find(); !opened {
|
||||
t.Error("opening the gift did not un-blur it")
|
||||
}
|
||||
// Opening twice is harmless.
|
||||
if err := rewards.OpenGift(ctx, user, key); err != nil {
|
||||
t.Errorf("second open should be a no-op: %v", err)
|
||||
}
|
||||
|
||||
// Re-gifting tops up newcomers without duplicating anyone's tile.
|
||||
if _, err := rewards.GrantGiftToEveryone(ctx, reward.ID); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
grants, _ := rewards.GrantsByUser(ctx, user)
|
||||
n := 0
|
||||
for _, g := range grants {
|
||||
if g.Reward.Key == key {
|
||||
n++
|
||||
}
|
||||
}
|
||||
if n != 1 {
|
||||
t.Errorf("holdings of the gift = %d, want 1", n)
|
||||
}
|
||||
// ...and it must not silently re-wrap what was already opened.
|
||||
if _, opened = find(); !opened {
|
||||
t.Error("re-gifting re-wrapped an already opened gift")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user