UI: widen the edge-swipe-back activation band
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 40s
CI / gate (pull_request) Successful in 0s
CI / deploy (pull_request) Successful in 58s
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 40s
CI / gate (pull_request) Successful in 0s
CI / deploy (pull_request) Successful in 58s
Replace the very-narrow 24px edge-swipe trigger with a left band of ~20% of the viewport width (EDGE_FRACTION) so the back-swipe is easy to reach, keeping the simple instant-navigate behaviour (the route slide plays the animation). A hit-test keeps the wider band clear of the rack, a draggable pending tile, a zoomed-in board and text inputs, so it never hijacks those drags. Test: e2e (Chromium+WebKit) — the band swipe returns to the lobby; a swipe starting on the rack does not navigate.
This commit is contained in:
@@ -0,0 +1,52 @@
|
||||
import { expect, test, type Page } from './fixtures';
|
||||
|
||||
// The edge-swipe back gesture (Screen.svelte): a rightward drag begun in the left band
|
||||
// returns to the parent. It ignores mouse pointers and the Playwright desktop projects have
|
||||
// no touch input, so these specs dispatch PointerEvents with pointerType:'touch'. A phone
|
||||
// viewport so the band (a fraction of the width) lands on the full-width board / rack.
|
||||
test.use({ viewport: { width: 390, height: 844 } });
|
||||
|
||||
async function openAnnGame(page: Page): Promise<void> {
|
||||
await page.goto('/');
|
||||
await page.getByRole('button', { name: /guest/i }).click();
|
||||
await page.getByRole('button', { name: /Ann/ }).click();
|
||||
await expect(page.locator('[data-cell]').first()).toBeVisible();
|
||||
await page.waitForTimeout(400); // let the open slide settle
|
||||
}
|
||||
|
||||
/** touchDrag dispatches a single-finger touch drag from (x0,y0) to (x1,y1) over the window. */
|
||||
async function touchDrag(page: Page, x0: number, y0: number, x1: number, y1: number): Promise<void> {
|
||||
await page.evaluate(
|
||||
({ x0, y0, x1, y1 }) => {
|
||||
const fire = (type: string, x: number, y: number) =>
|
||||
window.dispatchEvent(
|
||||
new PointerEvent(type, { pointerType: 'touch', clientX: x, clientY: y, bubbles: true, cancelable: true }),
|
||||
);
|
||||
fire('pointerdown', x0, y0);
|
||||
for (let i = 1; i <= 8; i++) fire('pointermove', x0 + ((x1 - x0) * i) / 8, y0 + ((y1 - y0) * i) / 8);
|
||||
fire('pointerup', x1, y1);
|
||||
},
|
||||
{ x0, y0, x1, y1 },
|
||||
);
|
||||
}
|
||||
|
||||
test('a rightward swipe in the left band returns to the lobby', async ({ page }) => {
|
||||
await openAnnGame(page);
|
||||
const board = (await page.locator('.viewport').boundingBox())!;
|
||||
|
||||
await touchDrag(page, 12, board.y + board.height * 0.5, 220, board.y + board.height * 0.5);
|
||||
|
||||
await expect(page).toHaveURL(/#\/$/);
|
||||
await expect(page.getByRole('button', { name: /Ann/ })).toBeVisible();
|
||||
});
|
||||
|
||||
test('a swipe starting on the rack does not navigate (hit-test guard)', async ({ page }) => {
|
||||
await openAnnGame(page);
|
||||
const rack = (await page.locator('[data-rack]').boundingBox())!;
|
||||
|
||||
// Start on the leftmost rack tile (inside the band) — the rack owns its drag, so no back.
|
||||
await touchDrag(page, rack.x + 12, rack.y + rack.height * 0.5, rack.x + 200, rack.y + rack.height * 0.5);
|
||||
|
||||
await page.waitForTimeout(300);
|
||||
expect(page.url()).toContain('/game/');
|
||||
});
|
||||
Reference in New Issue
Block a user