mirror of
https://github.com/runbear-io/beardrive.git
synced 2026-08-25 08:08:08 +02:00
Project settings at 1440x900 ended at People. Public links — the section that answers "is anything of ours public right now?" — was below the fold of #content, the app's only scroll container, and with macOS overlay scrollbars nothing at rest said there was more. #content now takes a real scrollbar. The plan called for scrollbar-width + scrollbar-color alongside ::-webkit-scrollbar; measured, that combination is a no-op: Chromium drops every ::-webkit-scrollbar rule as soon as either standard property is set on the same element, and the standard properties alone leave the macOS overlay bar, which takes no width and is invisible at rest. So the standard properties sit behind @supports not selector(::-webkit-scrollbar) — Firefox only. Verified: 10px reserved in Chromium, 0 on touch. Public links also moves from fourth card to second (General → Public links → People → About → Danger zone), so the security answer is above the fold even without the cue. browse.spec reached the shares table by .last(), which the reorder would have silently repointed at the members table — both render through AdminTable. It selects .shares-table now. Known gap: Firefox on macOS always uses overlay scrollbars and no CSS overrides it, so the bar there stays hidden at rest — that is an OS setting, not something this can fix.
49 lines
2.0 KiB
TypeScript
49 lines
2.0 KiB
TypeScript
import { Page } from "@playwright/test";
|
|
|
|
export const ADMIN = "e2e@example.com";
|
|
export const MEMBER = "member@example.com";
|
|
// Org member cut back to read-only on "wiki" by the seeded harness.
|
|
export const READER = "reader@example.com";
|
|
export const PASSWORD = "e2e-pass-1";
|
|
|
|
// One real form login per identity per run, then the session cookie is
|
|
// reused — the server rate-limits credential POSTs to 10/min per IP, which
|
|
// a fresh login in every spec would trip.
|
|
type Cookies = Awaited<ReturnType<ReturnType<Page["context"]>["cookies"]>>;
|
|
const sessions = new Map<string, Cookies>();
|
|
|
|
// Signs in (through the server-rendered /auth pages on first use) and waits
|
|
// for the SPA shell to render.
|
|
export async function login(page: Page, email: string = ADMIN) {
|
|
const cached = sessions.get(email);
|
|
if (cached) {
|
|
await page.context().addCookies(cached);
|
|
await page.goto("/");
|
|
await page.waitForSelector("#sidebar");
|
|
return;
|
|
}
|
|
await page.goto("/");
|
|
await page.waitForURL(/auth\/login/);
|
|
await page.fill('input[name="email"]', email);
|
|
await page.fill('input[name="password"]', PASSWORD);
|
|
await page.click("button[type=submit]");
|
|
await page.waitForSelector("#sidebar");
|
|
sessions.set(email, await page.context().cookies());
|
|
}
|
|
|
|
// Note for anything that scrolls or screenshots a route: the document itself
|
|
// never scrolls — #content is the one scroll container. A full-page screenshot
|
|
// stops at the viewport and window.scrollTo does nothing; scroll #content.
|
|
|
|
export async function wikiId(page: Page): Promise<string> {
|
|
const out = await (await page.request.get("/api/projects")).json();
|
|
return out.projects.find((p: { name: string }) => p.name === "wiki").id;
|
|
}
|
|
|
|
// Implementation-agnostic toast assertion: matches the legacy #toast div or
|
|
// a sonner toast, so specs pin BEHAVIOR (text shown) not markup.
|
|
export async function expectToast(page: Page, text: string | RegExp) {
|
|
const { expect } = await import("@playwright/test");
|
|
await expect(page.locator("#toast.show, [data-sonner-toast]").filter({ hasText: text }).first()).toBeVisible();
|
|
}
|