Files
buzz/desktop/tests/e2e/settings-section-layout.spec.ts
43e53fc349 Standardize settings section layout (#5855)
## Summary

- move Settings section labels outside their framed containers and
centralize the spacing
- apply the shared hierarchy across Appearance, Notifications, Voice,
Agents, Shortcuts, Members, and Profile
- give Identity and Sign out complete section treatments while removing
redundant in-cell labels

## Testing

- desktop pre-push checks, including 4,791 tests
- focused Settings layout and sign-out Playwright coverage

---------

Signed-off-by: kenny lopez <klopez4212@gmail.com>
Signed-off-by: Princess Donut <b238ea756dee4d98afa5883fc7f1de61eeabe65bf700e3a5a5a80db5e42e2c2b@buzz.block.builderlab.xyz>
Co-authored-by: Princess Donut <b238ea756dee4d98afa5883fc7f1de61eeabe65bf700e3a5a5a80db5e42e2c2b@buzz.block.builderlab.xyz>
2026-08-14 16:25:40 +01:00

130 lines
4.3 KiB
TypeScript

import { expect, test } from "@playwright/test";
import { installMockBridge } from "../helpers/bridge";
import { openSettings } from "../helpers/settings";
test("settings sections share the Appearance rhythm", async ({ page }) => {
await installMockBridge(page);
await page.goto("/");
await openSettings(page, "appearance");
const appearanceList = page
.getByTestId("settings-theme")
.locator('[data-slot="settings-section-list"]');
const [referenceGap] = await appearanceList
.locator(":scope > *")
.evaluateAll((elements) =>
elements.slice(1).map((element, index) => {
const previous = elements[index];
return (
element.getBoundingClientRect().top -
previous.getBoundingClientRect().bottom
);
}),
);
expect(referenceGap).toBeGreaterThan(0);
for (const section of [
"notifications",
"voice",
"agents",
"shortcuts",
"profile",
] as const) {
await page.getByTestId(`settings-nav-${section}`).click();
const list = page
.getByTestId(`settings-${section}`)
.locator('[data-slot="settings-section-list"]');
await expect(list).toBeVisible();
const gaps = await list.locator(":scope > *").evaluateAll((elements) =>
elements.slice(1).map((element, index) => {
const previous = elements[index];
return (
element.getBoundingClientRect().top -
previous.getBoundingClientRect().bottom
);
}),
);
expect(gaps.length).toBeGreaterThan(0);
expect(gaps.every((gap) => Math.abs(gap - referenceGap) <= 1)).toBe(true);
}
await page.getByTestId("settings-nav-agents").click();
const headerToCardGap = async (testId: string) => {
const group = page.getByTestId(testId);
return group.evaluate((element) => {
const lastHeaderLine = element.querySelector(
'[data-slot="settings-section-header"] > div:first-child > :last-child',
);
const card = element.querySelector('[data-slot="settings-section-card"]');
if (
!(lastHeaderLine instanceof HTMLElement) ||
!(card instanceof HTMLElement)
) {
throw new Error("Missing section header or card");
}
return (
card.getBoundingClientRect().top -
lastHeaderLine.getBoundingClientRect().bottom
);
});
};
const [titleOnlyGap, subtitleGap] = await Promise.all([
headerToCardGap("agents-preferences-card"),
headerToCardGap("settings-harnesses"),
]);
expect(titleOnlyGap).toBeGreaterThan(0);
expect(Math.abs(titleOnlyGap - subtitleGap)).toBeLessThanOrEqual(1);
});
test("Profile sections keep visible cards and aligned actions", async ({
page,
}) => {
await installMockBridge(page);
await page.goto("/");
await openSettings(page, "profile");
const identity = page.getByTestId("profile-identity-card");
const identityCard = identity.locator(
'xpath=ancestor::*[@data-slot="settings-section-card"][1]',
);
await expect(identityCard).toBeVisible();
await expect(
page.getByText("Identity details", { exact: true }),
).toBeVisible();
await expect(page.getByTestId("profile-identity-details")).toBeHidden();
const signOut = page.getByTestId("settings-signout");
const signOutCard = signOut.locator('[data-slot="settings-section-card"]');
await expect(signOutCard).toBeVisible();
await expect(
signOutCard.getByRole("button", { name: "Delete my data" }),
).toBeVisible();
await expect(signOut.getByText("Sign out", { exact: true })).toHaveCount(1);
await expect(
signOut.getByText("Sign out of Buzz", { exact: true }),
).toHaveCount(0);
const profileInfo = page.getByTestId("profile-metadata-card");
await profileInfo.scrollIntoViewIfNeeded();
const [titleBottom, editBottom] = await Promise.all([
profileInfo
.getByRole("heading", { name: "Profile info" })
.evaluate((element) => element.getBoundingClientRect().bottom),
page
.getByTestId("profile-metadata-edit")
.evaluate((element) => element.getBoundingClientRect().bottom),
]);
expect(Math.abs(titleBottom - editBottom)).toBeLessThanOrEqual(1);
await page.getByTestId("settings-nav-updates").click();
await expect(
page
.getByTestId("settings-updates")
.getByText("Update status", { exact: true }),
).toHaveCount(1);
});