622d3965a7
CI / changes (pull_request) Successful in 3s
CI / unit (pull_request) Has been skipped
CI / integration (pull_request) Has been skipped
CI / ui (pull_request) Successful in 59s
CI / conformance (pull_request) Successful in 9s
CI / gate (pull_request) Successful in 0s
CI / deploy (pull_request) Successful in 2m12s
Landscape fits the whole board, so the coarse-pointer auto-zoom on tile placement, drag hover-hold and hint only hid the rest of the position. Gate all three on portrait; manual double-tap/pinch zoom is unchanged. New e2e lock both sides: landscape placement stays unzoomed, portrait placement still auto-zooms (touch-emulated, both engines).
78 lines
3.8 KiB
TypeScript
78 lines
3.8 KiB
TypeScript
import { expect, test, type Page } from './fixtures';
|
|
|
|
// The landscape (wide) layout: when the viewport is wider than tall, the game switches to a
|
|
// two-column layout — the board fills the right side fitted to the height (no zoom), while the
|
|
// rack, status, scores, the always-open history and the controls stack in a left panel. These
|
|
// lock the key differences from the portrait layout so a future edit surfaces as a failing
|
|
// assertion. The rest of the suite runs portrait (see playwright.config.ts); this spec overrides
|
|
// the viewport to a wide, short one.
|
|
test.use({ viewport: { width: 1100, height: 640 } });
|
|
|
|
async function openGame(page: Page): Promise<void> {
|
|
await page.goto('/');
|
|
await page.getByRole('button', { name: /guest/i }).click();
|
|
await page.getByRole('button', { name: /Ann/ }).click(); // the seeded active game vs Ann
|
|
await expect(page.locator('[data-cell]').first()).toBeVisible();
|
|
}
|
|
|
|
test('landscape lays the game in two columns with the history docked open', async ({ page }) => {
|
|
await openGame(page);
|
|
// The two-column landscape wrapper is mounted instead of the portrait stacking.
|
|
await expect(page.locator('.game-land')).toBeVisible();
|
|
// The history is shown without tapping the score bar — it is docked open in the left panel,
|
|
// not a slide-down drawer.
|
|
await expect(page.locator('.history')).toBeVisible();
|
|
// The controls live in the left panel (no bottom tab bar in landscape).
|
|
await expect(page.locator('.leftpane .tabbar')).toBeVisible();
|
|
});
|
|
|
|
test('landscape zooms the board on a double-tap and the zoomed board overflows the pane', async ({ page }) => {
|
|
await openGame(page);
|
|
// Double-tap an empty cell zooms in, same as portrait. The board is height-driven here, so the
|
|
// zoomed square grows past the wide pane and becomes pannable (scrollWidth exceeds the viewport).
|
|
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();
|
|
await page.waitForTimeout(350); // let the width/height magnify settle
|
|
const overflows = await viewport.evaluate((el) => el.scrollWidth > el.clientWidth + 5);
|
|
expect(overflows).toBe(true);
|
|
});
|
|
|
|
test('landscape still places a tile and commits via the make button', async ({ page }) => {
|
|
await openGame(page);
|
|
// Placement works the same in landscape: tap a rack tile, tap an empty cell adjacent to the
|
|
// seeded word, and the make (✅) control appears next to the rack.
|
|
await page.locator('.rack .tile').first().click();
|
|
await page.locator('[data-cell][data-row="9"][data-col="6"]').click();
|
|
await expect(page.locator('.cell.pending')).toHaveCount(1);
|
|
await expect(page.locator('.make')).toBeVisible();
|
|
});
|
|
|
|
// Placement auto-zoom is portrait-only (Game.svelte gates it on !landscape): landscape fits the
|
|
// whole board, so magnifying on every placed tile would only hide the position. The gate also
|
|
// requires a coarse pointer, so the block emulates touch and skips on an engine whose emulation
|
|
// does not flip `(pointer: coarse)` (desktop WebKit). The portrait counterpart lives in
|
|
// zoom.spec.ts.
|
|
test.describe('touch placement', () => {
|
|
test.use({ hasTouch: true });
|
|
|
|
test('landscape does not auto-zoom when a tile is placed', async ({ page }) => {
|
|
await openGame(page);
|
|
test.skip(
|
|
!(await page.evaluate(() => matchMedia('(pointer: coarse)').matches)),
|
|
'touch emulation does not report a coarse pointer in this engine',
|
|
);
|
|
await page.locator('.rack .tile').first().click();
|
|
await page.locator('[data-cell][data-row="9"][data-col="6"]').click();
|
|
await expect(page.locator('.cell.pending')).toHaveCount(1);
|
|
await page.waitForTimeout(400); // the would-be zoom transition window
|
|
await expect(page.locator('.viewport.zoomed')).toHaveCount(0);
|
|
});
|
|
});
|