UI: fix last-move highlight, localize move history, clamp zoom overscroll
CI / changes (pull_request) Successful in 2s
CI / unit (pull_request) Has been skipped
CI / integration (pull_request) Has been skipped
CI / ui (pull_request) Successful in 41s
CI / gate (pull_request) Successful in 0s
CI / deploy (pull_request) Successful in 57s
CI / changes (pull_request) Successful in 2s
CI / unit (pull_request) Has been skipped
CI / integration (pull_request) Has been skipped
CI / ui (pull_request) Successful in 41s
CI / gate (pull_request) Successful in 0s
CI / deploy (pull_request) Successful in 57s
- Highlight tracks the last move overall (not the last word): a trailing pass/exchange now highlights nothing, so the board no longer lights up the opponent's old word after our own empty move. - Make the highlight event-driven: refreshed only on a real game event (open/refresh, opponent move, our own committed move) and dismissed the moment composing starts, so recalling a just-placed tile never re-triggers it. - Localize non-play move-history labels via new move.* catalog keys (pass/exchange/resign/timeout); the label printed the raw English action. - Clamp the zoomed board's pan at its edge (overscroll-behavior: none), removing the native rubber-band past the content. Tests: lastMoveCells unit coverage (trailing pass/exchange -> empty), i18n RU label assertions, an e2e overscroll-contract check on the zoomed viewport.
This commit is contained in:
@@ -24,3 +24,31 @@ test('zoom enlarges the board labels with the board', async ({ page }) => {
|
||||
const zoomed = await letter.evaluate((el) => parseFloat(getComputedStyle(el).fontSize));
|
||||
expect(zoomed).toBeGreaterThan(base * 1.4);
|
||||
});
|
||||
|
||||
// Item 4 (UX): the zoomed board clamps at its edge — no native rubber-band/overscroll past
|
||||
// the content. We assert the CSS contract on the zoomed scroll container, which is
|
||||
// deterministic across engines (the bounce gesture itself is a native compositor behaviour
|
||||
// Playwright cannot reliably synthesize).
|
||||
test('zoomed board clamps overscroll at the edge', async ({ page }) => {
|
||||
await page.goto('/');
|
||||
await page.getByRole('button', { name: /guest/i }).click();
|
||||
await page.getByRole('button', { name: /Ann/ }).click();
|
||||
|
||||
// Double-tap an empty cell to zoom in.
|
||||
await page
|
||||
.locator('[data-cell]:not(.filled)')
|
||||
.nth(20)
|
||||
.evaluate((el: HTMLElement) => {
|
||||
el.click();
|
||||
el.click();
|
||||
});
|
||||
|
||||
const viewport = page.locator('.viewport.zoomed');
|
||||
await expect(viewport).toBeVisible();
|
||||
const ob = await viewport.evaluate((el) => {
|
||||
const s = getComputedStyle(el);
|
||||
return { x: s.overscrollBehaviorX, y: s.overscrollBehaviorY };
|
||||
});
|
||||
expect(ob.x).toBe('none');
|
||||
expect(ob.y).toBe('none');
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user