feat(lobby): cap simultaneous quick games at 10
CI / changes (pull_request) Successful in 2s
CI / unit (pull_request) Successful in 9s
CI / integration (pull_request) Successful in 15s
CI / ui (pull_request) Successful in 49s
CI / gate (pull_request) Successful in 0s
CI / deploy (pull_request) Successful in 1m8s
CI / changes (pull_request) Successful in 2s
CI / unit (pull_request) Successful in 9s
CI / integration (pull_request) Successful in 15s
CI / ui (pull_request) Successful in 49s
CI / gate (pull_request) Successful in 0s
CI / deploy (pull_request) Successful in 1m8s
Limit a player to 10 active quick games (auto-match + AI); friend games created by invitation are not counted. At the cap the backend refuses both new-game entry points — quick enqueue and invitation creation — with 409 game_limit_reached, while accepting an incoming invitation stays allowed, so friend games are capped from the other end. The lobby disables "New Game" and shows a low-emphasis notice, driven by a new at_game_limit flag on games.list (no per-event payload: a turn change does not move the count, and the lobby already re-fetches games.list on entry and every game event). - game.MaxActiveQuickGames + Store/Service.CountActiveQuickGames (active/open seats, no game_invitations row; hidden games still count -> dedicated count) - Server.ensureUnderGameLimit gating handleEnqueue + handleCreateInvitation; game.ErrGameLimitReached -> 409 game_limit_reached - FB GameList.at_game_limit (regenerated Go + TS) through the gateway transcode and UI codec; gameListDTO + lobbycache snapshot + Lobby.svelte + i18n - tests: integration count rule + HTTP gate + accept bypass; server error map; gateway transcode round-trip; UI codec + lobbycache unit; e2e gamelimit - docs: PRERELEASE (GL), FUNCTIONAL(+ru), ARCHITECTURE 8, UI_DESIGN, backend README
This commit is contained in:
@@ -0,0 +1,31 @@
|
||||
import { expect, test } from './fixtures';
|
||||
|
||||
// The simultaneous quick-game cap. When the backend reports the player is at the limit
|
||||
// (games.list at_game_limit), the lobby disables the "New Game" tab and shows a plain,
|
||||
// low-emphasis notice under the lists; when it clears, the button re-enables and the
|
||||
// notice goes. Driven by the mock transport's __mock.setGameLimit seam (no backend), which
|
||||
// also nudges the lobby to re-fetch (the lobby refreshes on any live event).
|
||||
|
||||
test('lobby: New Game disables and a notice shows at the simultaneous-game limit', async ({ page }) => {
|
||||
await page.goto('/');
|
||||
await page.getByRole('button', { name: /guest/i }).click();
|
||||
|
||||
// Below the limit: the New Game tab is enabled and no notice is shown.
|
||||
const newGame = page.getByRole('button', { name: /New/ });
|
||||
await expect(newGame).toBeEnabled();
|
||||
await expect(page.getByText(/reached the simultaneous games limit/i)).toHaveCount(0);
|
||||
|
||||
// Reach the limit: the button greys out (disabled) and the notice appears under the lists.
|
||||
await page.evaluate(() =>
|
||||
(window as unknown as { __mock: { setGameLimit(v: boolean): void } }).__mock.setGameLimit(true),
|
||||
);
|
||||
await expect(newGame).toBeDisabled();
|
||||
await expect(page.getByText(/reached the simultaneous games limit/i)).toBeVisible();
|
||||
|
||||
// Drop back below the limit (a game finished): the button re-enables and the notice clears.
|
||||
await page.evaluate(() =>
|
||||
(window as unknown as { __mock: { setGameLimit(v: boolean): void } }).__mock.setGameLimit(false),
|
||||
);
|
||||
await expect(newGame).toBeEnabled();
|
||||
await expect(page.getByText(/reached the simultaneous games limit/i)).toHaveCount(0);
|
||||
});
|
||||
Reference in New Issue
Block a user