big UI changes

This commit is contained in:
KingKDot
2026-08-19 11:40:36 -05:00
parent 82d6864afe
commit d2c343b2b7
18 changed files with 1045 additions and 137 deletions
@@ -0,0 +1,68 @@
import { expect, test } from "@playwright/test";
import { collectBrowserIssues, login } from "./helpers";
test.describe("concise UI conventions", () => {
test("removes redundant page copy and promotes section help", async ({ page }) => {
const browserIssues = collectBrowserIssues(page);
await login(page);
await page.goto("/logs");
await expect(page.getByRole("heading", { name: "Client Connection Logs" })).toBeVisible();
await expect(page.getByText("Review connection lifecycle activity across enrolled clients.")).toHaveCount(0);
const filterHelp = page.locator("h2", { hasText: "Filter activity" }).locator(".ui-help");
await expect(filterHelp).toHaveAttribute("title", "Narrow results by client, time range, or event type.");
await expect(page.getByText("Narrow results by client, time range, or event type.")).toHaveClass("sr-only");
await page.goto("/plugins");
await expect(page.getByRole("heading", { name: "Plugins", exact: true })).toBeVisible();
await expect(page.getByText("Upload zip bundles and manage client plugins or server extensions")).toHaveCount(0);
await expect(page.locator("h2", { hasText: "Upload" }).locator(".ui-help")).toHaveAttribute(
"title",
"Drag a plugin zip here or click to browse",
);
await page.goto("/settings");
await expect(page.getByRole("heading", { name: "Settings", exact: true })).toBeVisible();
await expect(page.getByText("Manage your account preferences, operational tools, and admin configuration.")).toHaveCount(0);
await expect(page.locator("#section-account h2 .ui-help")).toHaveAttribute(
"title",
"View your account info and update your password.",
);
await expect(page.locator("#chat-retention-days")).toHaveAttribute(
"title",
"Messages older than this will be automatically deleted. Set to 0 to keep messages forever. Max 365 days.",
);
await page.waitForLoadState("networkidle");
await page.goto("/build");
await expect(page.getByText("Build customized Overlord client agents")).toHaveCount(0);
const obfuscateOption = page.locator('label:has(input[name="obfuscate"])').first();
await expect(obfuscateOption).toHaveAttribute("title", "Build with garble for code obfuscation");
await expect(obfuscateOption.locator("span.sr-only")).toContainText("Build with garble");
await page.waitForLoadState("networkidle");
await page.goto("/purgatory");
await page.locator("#auto-accept-toggle").click({ force: true });
await expect(page.getByText("This disables all enrollment security.")).toBeVisible();
await page.locator("#auto-accept-modal-cancel").click();
expect(browserIssues).toEqual([]);
});
test("keeps compact help and controls usable at phone width", async ({ page }) => {
await page.setViewportSize({ width: 390, height: 844 });
const browserIssues = collectBrowserIssues(page);
await login(page);
await page.goto("/settings");
await expect(page.locator("#section-account h2 .ui-help")).toBeVisible();
await page.locator("#section-account h2 .ui-help").focus();
const overflow = await page.evaluate(() => ({
body: document.body.scrollWidth - document.body.clientWidth,
root: document.documentElement.scrollWidth - document.documentElement.clientWidth,
}));
expect(overflow.body).toBeLessThanOrEqual(1);
expect(overflow.root).toBeLessThanOrEqual(1);
expect(browserIssues).toEqual([]);
});
});
+5 -1
View File
@@ -18,7 +18,11 @@ export async function login(
export async function navigateFromMenu(page: Page, linkId: string): Promise<void> {
const link = page.locator(`#${linkId}`);
const wrapper = link.locator("xpath=ancestor::*[contains(@class, 'nav-dd-wrapper')][1]");
await wrapper.locator(":scope > .nav-dd-group-btn").click();
const groupButton = wrapper.locator(":scope > .nav-dd-group-btn");
if (!(await groupButton.isVisible())) {
await page.locator("#topbar-nav-toggle").click();
}
await groupButton.click();
await expect(link).toBeVisible();
await link.click();
}
@@ -0,0 +1,54 @@
import { expect, test } from "@playwright/test";
import { collectBrowserIssues, login } from "./helpers";
test.describe("compact notifications layout", () => {
test("keeps common settings visible and advanced delivery collapsed", async ({ page }) => {
const browserIssues = collectBrowserIssues(page);
await login(page);
await page.goto("/notifications");
await expect(page.getByRole("heading", { name: "Keywords" })).toBeVisible();
await expect(page.locator("#keyword-input")).toBeVisible();
await expect(page.getByRole("heading", { name: "Desktop alerts" })).toBeVisible();
await expect(page.getByRole("heading", { name: "Event delivery" })).toBeVisible();
const deliverySections = page.locator("details.notification-section");
await expect(deliverySections).toHaveCount(2);
await expect(deliverySections.nth(0)).not.toHaveAttribute("open", "");
await expect(deliverySections.nth(1)).not.toHaveAttribute("open", "");
await expect(page.locator("#save-webhook")).not.toBeVisible();
await expect(page.locator("#save-telegram")).not.toBeVisible();
await deliverySections.nth(0).locator(":scope > summary").click();
await expect(page.locator("#save-webhook")).toBeVisible();
await expect(page.locator("#webhook-url")).toBeVisible();
await expect(page.locator("#webhook-template")).not.toBeVisible();
await deliverySections.nth(0).locator("details.notification-advanced > summary").click();
await expect(page.getByRole("textbox", { name: "Editor content" })).toBeVisible();
await expect(page.locator(".ui-help[title]")).toHaveCount(9);
await expect(page.getByText("Fire when a client connects")).toHaveCount(0);
await expect(page.getByText("Your personal webhook")).toHaveCount(0);
expect(browserIssues).toEqual([]);
});
test("fits opened settings on a phone viewport", async ({ page }) => {
await page.setViewportSize({ width: 390, height: 844 });
const browserIssues = collectBrowserIssues(page);
await login(page);
await page.goto("/notifications");
const webhook = page.locator("details.notification-section").first();
await webhook.locator(":scope > summary").click();
await webhook.locator("details.notification-advanced > summary").click();
await expect(page.getByRole("textbox", { name: "Editor content" })).toBeVisible();
const overflow = await page.evaluate(() => ({
body: document.body.scrollWidth - document.body.clientWidth,
root: document.documentElement.scrollWidth - document.documentElement.clientWidth,
}));
expect(overflow.body).toBeLessThanOrEqual(1);
expect(overflow.root).toBeLessThanOrEqual(1);
expect(browserIssues).toEqual([]);
});
});
+66
View File
@@ -0,0 +1,66 @@
import { expect, test } from "@playwright/test";
import { collectBrowserIssues, login } from "./helpers";
test.describe("cross-page UI polish", () => {
test("rounds notification panels and normalizes graph fields", async ({ page }) => {
const browserIssues = collectBrowserIssues(page);
await login(page);
await page.goto("/notifications");
const notificationRadius = await page.locator("#keyword-section").evaluate((element) =>
Number.parseFloat(getComputedStyle(element).borderTopLeftRadius),
);
const deliveryRadius = await page.locator("details.notification-section").first().evaluate((element) =>
Number.parseFloat(getComputedStyle(element).borderTopLeftRadius),
);
expect(notificationRadius).toBeGreaterThanOrEqual(14);
expect(deliveryRadius).toBeGreaterThanOrEqual(14);
await page.goto("/graph");
const graphColors = await page.evaluate(() => {
const field = document.querySelector(".graph-field");
const input = document.querySelector("#graph-search");
const select = document.querySelector("#graph-status");
if (!field || !input || !select) throw new Error("Graph controls are missing");
return {
field: getComputedStyle(field).backgroundColor,
input: getComputedStyle(input).backgroundColor,
select: getComputedStyle(select).backgroundColor,
};
});
expect(graphColors.input).toBe("rgba(0, 0, 0, 0)");
expect(graphColors.field).toBe(graphColors.select);
await page.locator("#graph-search").fill("example");
await expect(page.locator("#graph-search")).toHaveValue("example");
expect(browserIssues).toEqual([]);
});
test("spaces the File Share empty state and fits on mobile", async ({ page }) => {
await page.setViewportSize({ width: 390, height: 844 });
const browserIssues = collectBrowserIssues(page);
await login(page);
await page.goto("/file-share");
const emptyState = page.locator(".file-share-empty");
await expect(emptyState).toBeVisible();
const filePickerColors = await page.locator("#upload-file").evaluate((element) => ({
field: getComputedStyle(element).backgroundColor,
button: getComputedStyle(element, "::file-selector-button").backgroundColor,
}));
expect(filePickerColors.button).toBe("rgba(0, 0, 0, 0)");
expect(filePickerColors.field).not.toBe(filePickerColors.button);
await page.locator("#upload-file").hover();
const iconBox = await emptyState.locator("i").boundingBox();
const labelBox = await emptyState.locator("span").boundingBox();
expect(iconBox).not.toBeNull();
expect(labelBox).not.toBeNull();
expect(labelBox!.y - (iconBox!.y + iconBox!.height)).toBeGreaterThanOrEqual(11);
const overflow = await page.evaluate(() =>
document.documentElement.scrollWidth - document.documentElement.clientWidth,
);
expect(overflow).toBeLessThanOrEqual(1);
expect(browserIssues).toEqual([]);
});
});