Stage 7 polish: game rework + board zoom + tests (Parts D/E/F/I)
- Board: fixed-viewport transform-scale zoom (animated) with counter-scaled cqw labels, corner letters, bonus-label modes (boardlabels), contrasting grid lines
- Game: Screen shell + game tab-bar (Draw/Skip/Hint/Shuffle) via HoldConfirm popovers; MakeMove 🏁 + compact popup; rack collapses used slots; hint places tiles on board (placementFromHint) + no_hint_available toast; Scores:N replaces Hints; history slide-down (swipe/click, scroll-locked); check-word alphabet/length limit + in-memory cache + 5s throttle
- backend: no_hint_available result code split + test
- vitest: banner rotator + linkify, resultBadge, boardlabels, placementFromHint (29 tests); Playwright smoke updated; prod bundle ~74 KB gzip
This commit is contained in:
@@ -51,6 +51,8 @@ func TestStatusForError(t *testing.T) {
|
||||
"code mismatch": {account.ErrCodeMismatch, http.StatusUnauthorized, "code_invalid"},
|
||||
"session gone": {session.ErrNotFound, http.StatusUnauthorized, "session_invalid"},
|
||||
"chat forbidden": {social.ErrForbiddenContent, http.StatusUnprocessableEntity, "chat_rejected"},
|
||||
"no hint move": {game.ErrNoHintAvailable, http.StatusConflict, "no_hint_available"},
|
||||
"no hints left": {game.ErrNoHintsLeft, http.StatusConflict, "hint_unavailable"},
|
||||
"unknown -> 500": {context_deadline, http.StatusInternalServerError, "internal"},
|
||||
}
|
||||
for name, tc := range cases {
|
||||
|
||||
@@ -121,7 +121,11 @@ func statusForError(err error) (int, string) {
|
||||
return http.StatusConflict, "already_queued"
|
||||
case errors.Is(err, game.ErrInvalidConfig):
|
||||
return http.StatusBadRequest, "invalid_config"
|
||||
case errors.Is(err, game.ErrHintsDisabled), errors.Is(err, game.ErrNoHintsLeft), errors.Is(err, game.ErrNoHintAvailable):
|
||||
case errors.Is(err, game.ErrNoHintAvailable):
|
||||
// No legal move for the rack — distinct from a budget/disabled hint so the UI
|
||||
// can say "no options" (and the service spends nothing in this case).
|
||||
return http.StatusConflict, "no_hint_available"
|
||||
case errors.Is(err, game.ErrHintsDisabled), errors.Is(err, game.ErrNoHintsLeft):
|
||||
return http.StatusConflict, "hint_unavailable"
|
||||
case errors.Is(err, engine.ErrIllegalPlay), errors.Is(err, engine.ErrTilesNotOnRack), errors.Is(err, engine.ErrGameOver):
|
||||
return http.StatusUnprocessableEntity, "illegal_play"
|
||||
|
||||
Reference in New Issue
Block a user