feat(ui): vs-AI comms trim, overlay confirm button, recall-to-slot drag
CI / changes (pull_request) Successful in 1s
CI / unit (pull_request) Successful in 10s
CI / integration (pull_request) Successful in 14s
CI / ui (pull_request) Successful in 51s
CI / gate (pull_request) Successful in 0s
CI / deploy (pull_request) Successful in 1m8s

- vs-AI: the comms hub drops the Chat tab (Dictionary only); a finished AI
  game has no comms at all, so its 💬 history-header entry is hidden too.
- Confirm-move : redone as an absolute overlay pinned to the right edge (its
  right edge sits under the preview caption), so the rack keeps a fixed tile
  size — this reverts the tile-shrink that resized the letters at 6 tiles.
- Recall: dragging a placed tile back to the rack now drops it at the slot the
  pointer is over (drag-to-position, a gap opens), instead of snapping to its
  original slot; double-tap still recalls to the origin. New pure recallToSlot.

Tests: placement recallToSlot units; e2e recall-to-position; vs-AI comms e2e
updated. Docs: UI_DESIGN + FUNCTIONAL (+ru).
This commit is contained in:
Ilia Denisov
2026-06-19 09:54:30 +02:00
parent b5688d4848
commit 4adb608ad1
10 changed files with 179 additions and 45 deletions
+22
View File
@@ -284,6 +284,28 @@ test('a placed tile drags from one board cell to another (relocation)', async ({
expect(to).not.toBe(from);
});
test('a placed tile drags back to a chosen rack slot (recall-to-position)', async ({ page }) => {
await openGame(page);
// Place the first rack tile (slot 0) on the board, remembering its letter.
await page.locator('.rack .tile').first().click();
const placed = (await page.locator('.rack .tile .letter').first().textContent()) ?? '';
await page.locator('[data-cell]:not(.filled)').nth(30).click();
const pending = page.locator('[data-cell].pending');
await expect(pending).toHaveCount(1);
// Drag it from the board back onto a later rack slot (the 4th visible tile), not its origin.
const fb = await pending.first().boundingBox();
const slot = await page.locator('[data-rack] .tile').nth(3).boundingBox();
await page.mouse.move(fb!.x + fb!.width / 2, fb!.y + fb!.height / 2);
await page.mouse.down();
await page.mouse.move(slot!.x + 2, slot!.y + slot!.height / 2, { steps: 10 });
await page.mouse.up();
// Recalled (no pending) and reinserted at the drop slot — slot 3, not its origin slot 0.
await expect(pending).toHaveCount(0);
await expect(page.locator('[data-rack] .tile .letter').nth(3)).toHaveText(placed);
});
test('comms hub: chat and dictionary share a screen, back returns to the game', async ({ page }) => {
await openGame(page);
await page.locator('.scoreboard').click(); // open the history