Files
emdash-cms--emdash/e2e/tests/keyboard-shortcuts.spec.ts
wehub-resource-sync b3a7f98e5a
CI / E2E Cloudflare (4/8) (push) Failing after 0s
CI / E2E Cloudflare (8/8) (push) Failing after 1s
CI / Lint (push) Failing after 1s
Auto Extract / Extract (push) Failing after 4s
CI / Version Check (push) Failing after 9s
CI / Integration Tests (push) Failing after 1s
CI / E2E tests (1/8) (push) Failing after 1s
CI / E2E tests (2/8) (push) Failing after 2s
CI / E2E tests (3/8) (push) Failing after 2s
CI / Browser Tests (push) Failing after 1s
CI / E2E tests (5/8) (push) Failing after 1s
CI / E2E Cloudflare (2/8) (push) Failing after 2s
CI / Typecheck (push) Failing after 1s
CI / Changeset Validation (push) Failing after 2s
CI / E2E Cloudflare (5/8) (push) Failing after 1s
CI / E2E Cloudflare (6/8) (push) Failing after 1s
CI / E2E Cloudflare (7/8) (push) Failing after 1s
CodeQL / Analyze (javascript-typescript) (push) Failing after 1s
Format / Format (push) Failing after 0s
CodeQL / Analyze (actions) (push) Failing after 4s
CI / E2E tests (4/8) (push) Failing after 1s
CI / E2E tests (6/8) (push) Failing after 1s
CI / E2E tests (7/8) (push) Failing after 2s
CI / E2E tests (8/8) (push) Failing after 1s
CI / E2E Cloudflare (1/8) (push) Failing after 1s
CI / E2E Cloudflare (3/8) (push) Failing after 2s
Preview Releases / Publish Preview (push) Failing after 0s
zizmor / Run zizmor (push) Failing after 1s
Release / Release (push) Failing after 2s
CI / Smoke Tests (push) Failing after 5m36s
CI / Tests (push) Failing after 6m36s
Release / Sync Templates (push) Has been skipped
CI / E2E Tests (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:23:53 +08:00

118 lines
3.7 KiB
TypeScript

/**
* Keyboard Shortcuts & Panel Dismiss E2E Tests
*
* Tests that keyboard shortcuts (Escape to close, Cmd+S to save) work
* correctly in slide-out panels, and that the Shell sidebar auto-closes
* on viewport resize.
*
* These verify the useStableCallback pattern — event listeners must
* remain functional across re-renders without churn.
*/
import { test, expect } from "../fixtures";
test.describe("Keyboard Shortcuts", () => {
test.beforeEach(async ({ admin }) => {
await admin.devBypassAuth();
});
test.describe("Media Detail Panel", () => {
test("Escape closes the media detail panel", async ({ admin, page }) => {
await admin.goToMedia();
await admin.waitForLoading();
// Seed data includes uploaded media — click the first grid item (a button)
const mediaItem = page.locator(".grid.gap-4 button").first();
await expect(mediaItem).toBeVisible({ timeout: 10000 });
await mediaItem.click();
// Panel should be visible
const panel = page.locator("text=Media Details");
await expect(panel).toBeVisible({ timeout: 5000 });
// Press Escape
await page.keyboard.press("Escape");
// Panel should be closed
await expect(panel).not.toBeVisible({ timeout: 3000 });
});
test("Cmd+S saves media detail changes", async ({ admin, page }) => {
await admin.goToMedia();
await admin.waitForLoading();
// Click the first media item
const mediaItem = page.locator(".grid.gap-4 button").first();
await expect(mediaItem).toBeVisible({ timeout: 10000 });
await mediaItem.click();
await expect(page.locator("text=Media Details")).toBeVisible({ timeout: 5000 });
// Change alt text (only visible for images)
const altInput = page.getByLabel("Alt Text");
if (await altInput.isVisible({ timeout: 2000 }).catch(() => false)) {
await altInput.fill(`E2E Alt ${Date.now()}`);
// Listen for the update API call
const saveResponse = page.waitForResponse(
(res) =>
res.url().includes("/api/media/") &&
res.request().method() === "PUT" &&
res.status() === 200,
{ timeout: 10000 },
);
// Press Cmd+S (Control on Linux/CI)
const modifier = process.platform === "darwin" ? "Meta" : "Control";
await page.keyboard.press(`${modifier}+s`);
// Should trigger the save
await saveResponse;
}
});
});
test.describe("User Detail Panel", () => {
test("Escape closes the user detail panel", async ({ admin, page }) => {
await admin.goto("/users");
await admin.waitForShell();
await admin.waitForLoading();
// Click a user row to open the detail panel
const userRow = page.locator("table tbody tr").first();
await expect(userRow).toBeVisible({ timeout: 10000 });
await userRow.click();
// Panel should appear
const panel = page.locator("text=User Details");
await expect(panel).toBeVisible({ timeout: 5000 });
// Press Escape
await page.keyboard.press("Escape");
// Panel should be closed
await expect(panel).not.toBeVisible({ timeout: 3000 });
});
});
test.describe("Shell Sidebar", () => {
test("sidebar becomes mobile sheet when viewport shrinks below md breakpoint", async ({
admin,
page,
}) => {
await admin.goToDashboard();
// Start at desktop width — sidebar should be visible as aside
await page.setViewportSize({ width: 1280, height: 720 });
const sidebar = page.locator('aside[aria-label="Admin navigation"]');
await expect(sidebar).toBeVisible();
// Shrink below kumo's mobile breakpoint (768px) — sidebar becomes a dialog sheet
await page.setViewportSize({ width: 600, height: 720 });
// The aside element should no longer be in the viewport
await expect(sidebar).not.toBeInViewport({ timeout: 3000 });
});
});
});