Flatten settings sidebar with a host picker (#1241)
* Flatten settings sidebar with a host picker Settings had two implicit tiers: app-level sections as flat sidebar rows, and per-host settings hidden behind a drill-in to one monolithic host page. This flattens both into a single sidebar with an "App" group and a "Host" group, where the host's settings are top-level rows scoped by a host picker. - Split the monolithic HostPage into four section pages: Connections, Orchestration (was the unnamed inject-tools + system-prompt block), Providers, and Daemon (status, updates, restart, remove). - Host picker reuses the canonical <Combobox> sidebar host switcher; defaults to the local host so a single-local-host user never thinks about "the daemon". - Host sections become real sub-routes (/settings/hosts/[id]/[section]); the old /settings/hosts/[id] redirects to the connections section, so existing deep links (pairing, workspace, open-project) keep working. - "Open providers" from the project screen now lands on the Providers section. * Fix e2e host-settings navigation for the flat sidebar The flat-settings refactor moved host settings onto separate section pages, but three e2e helpers still expected the old monolithic host page: - openDesktopSettings: the daemon-lifecycle card now lives on the Daemon section — navigate there before asserting it. - acp catalog: "Add provider" now lives on the Providers section — open that section before opening the add-provider modal. - openAddHostFlow: "Add host" is now an item inside the host picker (Combobox), not a standalone button — open the picker first. Test-only; no product changes. Fixes the 8 playwright failures on this branch.
This commit is contained in:
@@ -6,12 +6,14 @@ import { getServerId } from "./helpers/server-id";
|
||||
import {
|
||||
expectSettingsHeader,
|
||||
openSettingsHost,
|
||||
openHostSection,
|
||||
expectHostLabelDisplayed,
|
||||
clickEditHostLabel,
|
||||
expectHostLabelEditMode,
|
||||
expectHostConnectionsCard,
|
||||
expectHostInjectMcpCard,
|
||||
expectHostActionCards,
|
||||
expectHostProvidersCard,
|
||||
expectHostNoLocalOnlyRows,
|
||||
expectRetiredSidebarSectionsAbsent,
|
||||
expectHostPageVisible,
|
||||
@@ -19,9 +21,7 @@ import {
|
||||
} from "./helpers/settings";
|
||||
|
||||
test.describe("Settings host page", () => {
|
||||
test("host page shows seeded label, connection endpoint, inject MCP toggle, and all action rows", async ({
|
||||
page,
|
||||
}) => {
|
||||
test("connections section shows the seeded connection endpoint", async ({ page }) => {
|
||||
const serverId = getServerId();
|
||||
const port = getE2EDaemonPort();
|
||||
|
||||
@@ -29,11 +29,44 @@ test.describe("Settings host page", () => {
|
||||
await openSettings(page);
|
||||
await openSettingsHost(page, serverId);
|
||||
|
||||
await expectSettingsHeader(page, TEST_HOST_LABEL);
|
||||
await expectHostLabelDisplayed(page);
|
||||
await expectSettingsHeader(page, "Connections");
|
||||
await expectHostConnectionsCard(page, port);
|
||||
});
|
||||
|
||||
test("orchestration section shows the inject MCP toggle", async ({ page }) => {
|
||||
const serverId = getServerId();
|
||||
|
||||
await gotoAppShell(page);
|
||||
await openSettings(page);
|
||||
await openSettingsHost(page, serverId);
|
||||
|
||||
await openHostSection(page, serverId, "orchestration");
|
||||
await expectSettingsHeader(page, "Orchestration");
|
||||
await expectHostInjectMcpCard(page);
|
||||
await expectHostActionCards(page);
|
||||
});
|
||||
|
||||
test("providers section shows the providers card", async ({ page }) => {
|
||||
const serverId = getServerId();
|
||||
|
||||
await gotoAppShell(page);
|
||||
await openSettings(page);
|
||||
await openSettingsHost(page, serverId);
|
||||
|
||||
await expectHostProvidersCard(page, serverId);
|
||||
await expectSettingsHeader(page, "Providers");
|
||||
});
|
||||
|
||||
test("daemon section shows the host label and restart/remove action cards", async ({ page }) => {
|
||||
const serverId = getServerId();
|
||||
|
||||
await gotoAppShell(page);
|
||||
await openSettings(page);
|
||||
await openSettingsHost(page, serverId);
|
||||
|
||||
await openHostSection(page, serverId, "daemon");
|
||||
await expectSettingsHeader(page, "Daemon");
|
||||
await expectHostLabelDisplayed(page);
|
||||
await expectHostActionCards(page, serverId);
|
||||
});
|
||||
|
||||
test("clicking the label pencil reveals the inline editor", async ({ page }) => {
|
||||
@@ -42,13 +75,14 @@ test.describe("Settings host page", () => {
|
||||
await gotoAppShell(page);
|
||||
await openSettings(page);
|
||||
await openSettingsHost(page, serverId);
|
||||
await openHostSection(page, serverId, "daemon");
|
||||
|
||||
await expectHostLabelDisplayed(page);
|
||||
await clickEditHostLabel(page);
|
||||
await expectHostLabelEditMode(page, TEST_HOST_LABEL);
|
||||
});
|
||||
|
||||
test("host page does not render pair-device or daemon-lifecycle rows for a remote daemon", async ({
|
||||
test("daemon section does not render pair-device or daemon-lifecycle rows for a remote daemon", async ({
|
||||
page,
|
||||
}) => {
|
||||
const serverId = getServerId();
|
||||
@@ -56,19 +90,20 @@ test.describe("Settings host page", () => {
|
||||
await gotoAppShell(page);
|
||||
await openSettings(page);
|
||||
await openSettingsHost(page, serverId);
|
||||
await openHostSection(page, serverId, "daemon");
|
||||
|
||||
// TODO: add local-daemon fixture for positive Pair/Daemon coverage.
|
||||
await expectHostNoLocalOnlyRows(page);
|
||||
});
|
||||
|
||||
test("settings sidebar does not expose retired top-level sections", async ({ page }) => {
|
||||
test("settings sidebar exposes the flat App and Host section rows", async ({ page }) => {
|
||||
await gotoAppShell(page);
|
||||
await openSettings(page);
|
||||
|
||||
await expectRetiredSidebarSectionsAbsent(page);
|
||||
});
|
||||
|
||||
test("navigating to /settings/hosts/[serverId] directly renders the host page", async ({
|
||||
test("navigating to /settings/hosts/[serverId] redirects to the connections section", async ({
|
||||
page,
|
||||
}) => {
|
||||
const serverId = getServerId();
|
||||
@@ -77,9 +112,10 @@ test.describe("Settings host page", () => {
|
||||
await page.goto(`/settings/hosts/${encodeURIComponent(serverId)}`);
|
||||
|
||||
await expectHostPageVisible(page, serverId);
|
||||
await expectSettingsHeader(page, TEST_HOST_LABEL);
|
||||
await expectSettingsHeader(page, "Connections");
|
||||
await openHostSection(page, serverId, "daemon");
|
||||
await expectHostLabelDisplayed(page);
|
||||
await expectHostActionCards(page);
|
||||
await expectHostActionCards(page, serverId);
|
||||
});
|
||||
|
||||
test("sidebar pins the local daemon host first with a Local marker", async ({ page }) => {
|
||||
|
||||
Reference in New Issue
Block a user