Stage 17 round 6 (#7): reset the nudge cooldown once the player acts
CI / changes (pull_request) Successful in 2s
CI / unit (pull_request) Successful in 8s
CI / integration (pull_request) Successful in 11s
CI / ui (pull_request) Successful in 30s
CI / gate (pull_request) Successful in 0s
CI / deploy (pull_request) Successful in 1m4s
CI / changes (pull_request) Successful in 2s
CI / unit (pull_request) Successful in 8s
CI / integration (pull_request) Successful in 11s
CI / ui (pull_request) Successful in 30s
CI / gate (pull_request) Successful in 0s
CI / deploy (pull_request) Successful in 1m4s
The hourly nudge cooldown now clears as soon as the sender has moved or posted a chat since their last nudge — engagement lifts the 'don't spam' limit. Backend: Nudge checks game.LastMoveAt + the sender's last non-nudge chat against the last nudge time (GameReader gains LastMoveAt). UI: nudgeOnCooldown mirrors it — a chat reset is read from the message list, a move is tracked client-side (lastActedAt on commit/pass/exchange; the backend stays authoritative across a reload). Integration test covers the reset.
This commit is contained in:
@@ -353,3 +353,33 @@ func TestNudgeRulesAndRateLimit(t *testing.T) {
|
||||
t.Fatalf("nudge after window: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// TestNudgeCooldownResetsOnAction checks the nudge cooldown clears once the player has
|
||||
// acted (moved or chatted) since their last nudge, even within the hour (Stage 17).
|
||||
func TestNudgeCooldownResetsOnAction(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
svc := newSocialService()
|
||||
gsvc := newGameService()
|
||||
gameID, seats := newGameWithSeats(t, 2) // seat 0 to move
|
||||
|
||||
if _, err := svc.Nudge(ctx, gameID, seats[1]); err != nil { // the waiting player nudges
|
||||
t.Fatalf("nudge: %v", err)
|
||||
}
|
||||
if _, err := svc.Nudge(ctx, gameID, seats[1]); !errors.Is(err, social.ErrNudgeTooSoon) {
|
||||
t.Fatalf("rapid nudge = %v, want ErrNudgeTooSoon", err)
|
||||
}
|
||||
// Seat 1 takes a turn: seat 0 passes (-> seat 1's turn), seat 1 chats then passes.
|
||||
if _, err := gsvc.Pass(ctx, gameID, seats[0]); err != nil {
|
||||
t.Fatalf("seat0 pass: %v", err)
|
||||
}
|
||||
if _, err := svc.PostMessage(ctx, gameID, seats[1], "thinking", ""); err != nil {
|
||||
t.Fatalf("seat1 chat: %v", err)
|
||||
}
|
||||
if _, err := gsvc.Pass(ctx, gameID, seats[1]); err != nil {
|
||||
t.Fatalf("seat1 pass: %v", err)
|
||||
}
|
||||
// Back on the opponent's turn, the cooldown is reset by the action since the nudge.
|
||||
if _, err := svc.Nudge(ctx, gameID, seats[1]); err != nil {
|
||||
t.Fatalf("nudge after acting = %v, want allowed (cooldown reset)", err)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user