Unverified Commit d7ae1e66 authored by Lemon-miaow's avatar Lemon-miaow
Browse files

fix(panel): unify fixed headers and collapsible auth sources

parent 34b450bf
Loading
Loading
Loading
Loading
+1 −0
Changes for panel/e2e/a11y.spec.ts: 1 added line, 0 removed lines.
Original line number Diff line number Diff line
@@ -31,6 +31,7 @@ for (const [account, path] of [
  ["owner", "/"],
  ["owner", "/servers"],
  ["owner", "/admin/lobby?space=login"],
  ["owner", "/admin/auth-sources"],
  ["owner", "/admin/images"],
  ["owner", "/admin/builds"],
  ["owner", "/admin/submissions"],
+3 −2
Changes for panel/e2e/auth-sources.smoke.spec.ts: 3 added lines, 2 removed lines.
Original line number Diff line number Diff line
@@ -7,6 +7,7 @@ test("Owner manages durable authentication sources from the sidebar", async ({ p
  await expect(page).toHaveURL(/\/admin\/auth-sources$/);
  await expect(page.getByLabel(t("authSources:tag"))).toHaveValue("littleskin");
  await expect(page.getByLabel(t("authSources:tag"))).toHaveAttribute("readonly", "");
  await page.getByRole("button", { name: t("authSources:expand", { name: "littleskin" }) }).click();
  await page.getByRole("button", { name: t("authSources:add"), exact: true }).click();
  await page.getByLabel(t("authSources:tag")).nth(1).fill("custom");
  await page.getByLabel(t("authSources:prefix")).nth(1).fill("CS");
@@ -14,12 +15,12 @@ test("Owner manages durable authentication sources from the sidebar", async ({ p
  await page.getByRole("button", { name: t("authSources:test"), exact: true }).nth(1).click();
  await expect(page.getByText(t("authSources:test_ok", { ms: 20 }), { exact: true })).toBeVisible();
  await page.getByRole("button", { name: t("authSources:move_up"), exact: true }).nth(1).click();
  await page.getByRole("checkbox", { name: t("authSources:enabled"), exact: true }).nth(1).uncheck();
  await page.getByRole("switch", { name: t("authSources:enabled"), exact: true }).nth(1).uncheck();
  await page.getByRole("button", { name: t("authSources:save"), exact: true }).click();
  await expect(page.getByText(t("authSources:saved"), { exact: true })).toBeVisible();
  await page.reload();
  await expect(page.getByLabel(t("authSources:tag")).nth(0)).toHaveValue("custom");
  await expect(page.getByRole("checkbox", { name: t("authSources:enabled"), exact: true }).nth(1)).not.toBeChecked();
  await expect(page.getByRole("switch", { name: t("authSources:enabled"), exact: true }).nth(1)).not.toBeChecked();
  await expect(page.getByRole("button", { name: t("authSources:remove"), exact: true })).toHaveCount(0);
  const available = await page.request.get("/api/v1/account/link/sources");
  expect((await available.json()).sources.map((source: { tag: string }) => source.tag)).toEqual(["mojang", "custom"]);
+12 −0
Changes for panel/e2e/fixtures.ts: 12 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -36,6 +36,18 @@ export const test = base.extend<{ signIn: (account: Account) => Promise<void> }>

export { expect };

export async function expectPinnedHeading(page: Page, title: string, top: number) {
  const heading = page.getByRole("heading", { name: title, exact: true });
  const before = (await heading.boundingBox())!;
  const pane = page.getByRole("main");
  await pane.evaluate((el) => { el.scrollTop = el.scrollHeight; });
  await expect.poll(() => pane.evaluate((el) => el.scrollTop)).toBeGreaterThan(100);
  const after = (await heading.boundingBox())!;
  expect(after.y).toBeCloseTo(before.y, 0);
  expect(after.y).toBeGreaterThanOrEqual(top);
  await expect(heading).toBeInViewport({ ratio: 1 });
}

/** expectFitsScreen fails when anything scrolls sideways or a visible element
 *  pokes past the viewport edge (an overflow-hidden parent would just cut it
 *  off). The shell scrolls in an overflow-y-auto pane, whose computed
+10 −1
Changes for panel/e2e/mobile.spec.ts: 10 added lines, 1 removed line.
Original line number Diff line number Diff line
import { test, expect, t, expectFitsScreen } from "./fixtures";
import { test, expect, t, expectFitsScreen, expectPinnedHeading } from "./fixtures";

test("the menu drawer reaches the other sections", async ({ page, signIn }) => {
  await signIn("linked");
@@ -71,3 +71,12 @@ test("authentication source drafts with long IDs fit a phone", async ({ page, si
  await expectFitsScreen(page);
  await expect(page.getByRole("button", { name: t("authSources:remove"), exact: true })).toBeVisible();
});

test("the mobile navigation and page heading stay visible above a scrolling form", async ({ page, signIn }) => {
  await signIn("owner");
  await page.goto("/admin/lobby");
  await expect(page.getByLabel(t("lobby:bookTitle"))).toBeEnabled();
  await expectPinnedHeading(page, t("lobby:title"), 56);
  await expect(page.getByRole("button", { name: t("common:open_menu") })).toBeInViewport({ ratio: 1 });
  await expectFitsScreen(page);
});
+54 −1
Changes for panel/e2e/smoke.spec.ts: 54 added lines, 1 removed line.
Original line number Diff line number Diff line
import { test, expect, t, expectFitsScreen } from "./fixtures";
import { test, expect, t, expectFitsScreen, expectPinnedHeading } from "./fixtures";

test("admin headings share their size and gutters and stay pinned while content scrolls", async ({ page, signIn }) => {
  await signIn("owner");
  await page.setViewportSize({ width: 1440, height: 600 });
  const metrics = [];
  for (const [path, title] of [
    ["/admin/submissions", "admin:submissions_title"],
    ["/admin/lobby", "lobby:title"],
    ["/admin/auth-sources", "authSources:title"],
  ]) {
    await page.goto(path);
    const heading = page.getByRole("heading", { name: t(title), exact: true });
    await expect(heading).toBeVisible();
    metrics.push(await heading.evaluate((el) => ({ x: el.getBoundingClientRect().x, y: el.getBoundingClientRect().y, size: getComputedStyle(el).fontSize })));
    expect(await page.getByRole("main").getByRole("heading", { level: 1 }).count()).toBe(0);
    if (path === "/admin/auth-sources") {
      await page.getByRole("button", { name: t("authSources:expand", { name: "littleskin" }) }).click();
      await expectPinnedHeading(page, t(title), 0);
    } else if (path === "/admin/lobby") {
      await expect(page.getByLabel(t("lobby:bookTitle"))).toBeEnabled();
      await expectPinnedHeading(page, t(title), 0);
    }
  }
  expect(metrics[1]).toEqual(metrics[0]);
  expect(metrics[2]).toEqual(metrics[0]);
});

test("saved authentication sources start closed and switches leave them closed", async ({ page, signIn }) => {
  await signIn("owner");
  await page.goto("/admin/auth-sources");
  const expand = page.getByRole("button", { name: t("authSources:expand", { name: "littleskin" }) });
  await expect(expand).toHaveAttribute("aria-expanded", "false");
  await expect(page.getByLabel(t("authSources:prefix"))).toBeHidden();
  const enabled = page.getByRole("switch", { name: t("authSources:enabled"), exact: true });
  await enabled.focus();
  await page.keyboard.press("Space");
  await expect(enabled).toHaveAttribute("aria-checked", "false");
  await expect(expand).toHaveAttribute("aria-expanded", "false");
  await page.getByRole("button", { name: t("authSources:save"), exact: true }).click();
  await expect(page.getByText(t("authSources:saved"), { exact: true })).toBeVisible();
  await expand.click();
  await expect(page.getByLabel(t("authSources:prefix"))).toBeVisible();
});

test("the console keeps a bounded log pane below the fixed heading", async ({ page, signIn }) => {
  await signIn("owner");
  await page.setViewportSize({ width: 1440, height: 960 });
  await page.goto("/servers/lobby");
  await expect(page.getByRole("textbox", { name: t("servers:command_label") })).toBeInViewport({ ratio: 1 });
  await expect(page.getByRole("button", { name: t("servers:log_clear_btn") })).toBeInViewport({ ratio: 1 });
  await expect(page.getByRole("heading", { name: "Hub Lobby", exact: true })).toBeInViewport({ ratio: 1 });
  expect(await page.getByRole("main").evaluate((el) => el.scrollTop)).toBe(0);
});

test("space settings keep the form visible while reading configuration", async ({ page, signIn }) => {
  await signIn("owner");
Loading