8881214213
Mechanical, behaviour-preserving removal of Stage N / TODO-N / phase (RN) references from comments, doc-comments, service READMEs, the current-state docs (ARCHITECTURE, FUNCTIONAL+_ru, TESTING, UI_DESIGN), config-file comments, and the .fbs/.proto schema comments. PLAN.md / PRERELEASE.md / CLAUDE.md keep the stage history. - Rename the only stage-named identifiers: registerStage8 -> registerSocialOps, registerStage11 -> registerLinkOps (gateway transcode). - Split stage6_test.go: TestEmailLoginFlow -> email_test.go, TestGuestAutoMatchLeavesNoStats (+ provisionGuest) -> account_test.go. - Regenerated proto bindings (push.pb.go, telegram_grpc.pb.go) from the de-staged .proto comments; FB Go/TS bindings unchanged (flatc strips schema comments). go build/vet/gofmt clean across modules; integration typecheck and pnpm check green.
68 lines
1.9 KiB
Go
68 lines
1.9 KiB
Go
//go:build integration
|
|
|
|
package inttest
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"testing"
|
|
|
|
"github.com/google/uuid"
|
|
|
|
"scrabble/backend/internal/game"
|
|
)
|
|
|
|
// TestHideFinishedGame covers per-account game hiding: an active game cannot be
|
|
// hidden, a finished game is removed from the hider's own list while staying visible to the
|
|
// other player, an outsider cannot hide it, and the action is idempotent.
|
|
func TestHideFinishedGame(t *testing.T) {
|
|
ctx := context.Background()
|
|
svc, gameID, seats, _ := newDraftGame(t)
|
|
|
|
// Hiding while the game is still active is refused.
|
|
if err := svc.HideGame(ctx, seats[0], gameID); !errors.Is(err, game.ErrGameActive) {
|
|
t.Fatalf("hide active = %v, want ErrGameActive", err)
|
|
}
|
|
|
|
// Finish the game by seat 0 resigning.
|
|
if _, err := svc.Resign(ctx, gameID, seats[0]); err != nil {
|
|
t.Fatalf("resign: %v", err)
|
|
}
|
|
|
|
// A non-player cannot hide it.
|
|
if err := svc.HideGame(ctx, provisionAccount(t), gameID); !errors.Is(err, game.ErrNotAPlayer) {
|
|
t.Fatalf("hide by outsider = %v, want ErrNotAPlayer", err)
|
|
}
|
|
|
|
// Seat 0 hides the finished game; hiding again is a no-op success.
|
|
if err := svc.HideGame(ctx, seats[0], gameID); err != nil {
|
|
t.Fatalf("hide: %v", err)
|
|
}
|
|
if err := svc.HideGame(ctx, seats[0], gameID); err != nil {
|
|
t.Fatalf("hide twice: %v", err)
|
|
}
|
|
|
|
// It is gone from seat 0's list but still in seat 1's (hiding is per-account).
|
|
if containsGame(t, svc, seats[0], gameID) {
|
|
t.Error("hidden game still listed for the hider")
|
|
}
|
|
if !containsGame(t, svc, seats[1], gameID) {
|
|
t.Error("hidden game should remain listed for the other player")
|
|
}
|
|
}
|
|
|
|
// containsGame reports whether the account's lobby list includes gameID.
|
|
func containsGame(t *testing.T, svc *game.Service, accountID, gameID uuid.UUID) bool {
|
|
t.Helper()
|
|
games, err := svc.ListForAccount(context.Background(), accountID)
|
|
if err != nil {
|
|
t.Fatalf("list for account: %v", err)
|
|
}
|
|
for _, g := range games {
|
|
if g.ID == gameID {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|