Stage 7: regression tests for the polished UI (logic + behaviour)
Lock the polish branch's behaviour so a future UI edit surfaces as a failing
assertion to re-agree or fix.
Unit (vitest, node env):
- placement: recallIndex, cellOccupied/isBlankSlot, non-linear direction, the
single-tile submit default, and placementFromHint blank-fallback / rack-exhausted.
- banner: the marquee scroll-cycle repeat-then-advance, stop(), root-relative and
multiple links.
- client.GatewayError. Extract the check-word constraints out of Game.svelte into a
pure lib/checkword.ts (sanitize + canCheck) and cover them.
E2E (playwright mock, Chromium + WebKit):
- commit via the 🏁 control, history slide-down + close, the exchange dialog,
check-word input sanitising + verdict, resign-to-finished, and the Settings
board-label mode changing the on-board labels.
This commit is contained in:
@@ -0,0 +1,31 @@
|
||||
// Pure helpers for the in-game "check a word" panel: input sanitising and the gate on
|
||||
// when a check may be sent. Kept separate from Game.svelte so the constraints (the
|
||||
// variant alphabet, the length bounds, the answered-word cache and the cool-down
|
||||
// throttle) are unit-testable and stay in lockstep with the UI.
|
||||
|
||||
/** The longest word that fits on a standard 15-cell board line. */
|
||||
export const MAX_WORD_LEN = 15;
|
||||
/** The shortest word worth checking. */
|
||||
export const MIN_WORD_LEN = 2;
|
||||
|
||||
/**
|
||||
* sanitizeCheckWord upper-cases the raw input and keeps only characters of the active
|
||||
* variant's alphabet, capped at MAX_WORD_LEN — so the field can never hold something the
|
||||
* dictionary could not contain.
|
||||
*/
|
||||
export function sanitizeCheckWord(raw: string, alphabet: string[]): string {
|
||||
const allowed = new Set(alphabet);
|
||||
return Array.from(raw.toUpperCase())
|
||||
.filter((ch) => allowed.has(ch))
|
||||
.slice(0, MAX_WORD_LEN)
|
||||
.join('');
|
||||
}
|
||||
|
||||
/**
|
||||
* canCheckWord gates the Check action: the trimmed word must be of valid length, must not
|
||||
* have been answered already (cached), and must not fall inside the cool-down window.
|
||||
*/
|
||||
export function canCheckWord(word: string, alreadyChecked: boolean, cooling: boolean): boolean {
|
||||
const w = word.trim();
|
||||
return w.length >= MIN_WORD_LEN && w.length <= MAX_WORD_LEN && !alreadyChecked && !cooling;
|
||||
}
|
||||
Reference in New Issue
Block a user