Ctrl K
ComunidadGuías…

tests/e2e/settings-navigation.spec.ts

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
import {
  test,
  expect,
  fulfillJson,
  mockTeamSettings,
  TEAM,
  TEAM_SETTINGS_PATH,
} from "./helpers/run-checks-fixtures";
import { enableScopedE2EAuth, scopedPath } from "./helpers/auth";
import { capacitySummary } from "./helpers/billing";

test.beforeEach(async ({ page }) => {
  await enableScopedE2EAuth(page);
  await page.route("**/api/settings/decision-checks", (route) =>
    fulfillJson(route, { enabled: true, viewer: { canManage: true } })
  );
  await page.route("**/api/settings/keys", (route) =>
    fulfillJson(route, { keys: [] })
  );
  await page.route("**/api/settings/api-keys", (route) =>
    fulfillJson(route, { keys: [] })
  );
  await page.route("**/api/mcp-servers", (route) =>
    fulfillJson(route, { servers: [] })
  );
});

test("Settings drills into page navigation and back restores the main menu", async ({
  page,
}) => {
  await page.goto(scopedPath("settings/account"));
  const nav = page.getByRole("navigation", { name: "Settings", exact: true });
  await expect(nav).toBeVisible();
  await expect(page.getByRole("tab")).toHaveCount(0);
  await page.getByRole("button", { name: "Back to main navigation" }).click();
  await expect(page.getByTestId("app-nav-connections")).toBeVisible();
  await expect(page).toHaveURL(scopedPath("settings/account"));
  await page.getByTestId("app-nav-settings").click();
  await expect(nav).toBeVisible();
  for (const [label, route] of [
    ["Teams", "teams"],
    ["Provider Keys", "keys"],
    ["Mogplex Keys", "mogplex-keys"],
    ["Account", "account"],
  ]) {
    await nav.getByRole("link", { name: label, exact: true }).click();
    await expect(page).toHaveURL(scopedPath(`settings/${route}`));
    await expect(
      page.getByRole("heading", { name: label, exact: true }).first()
    ).toBeVisible();
    await expect(
      nav.getByRole("link", { name: label, exact: true })
    ).toHaveAttribute("aria-current", "page");
    await expect(page.getByRole("tab")).toHaveCount(0);
  }
  await page.reload();
  await expect(
    nav.getByRole("link", { name: "Account", exact: true })
  ).toHaveAttribute("aria-current", "page");
});

test("Billing has separate settings and usage, with history and reload support", async ({
  page,
}) => {
  const summary = capacitySummary();
  summary.recentCosts = [
    {
      operationId: "usage-1",
      description: "Repository review",
      status: "settled",
      occurredAt: "2026-09-22T12:00:00Z",
      totalCents: 125,
      items: [],
    },
  ];
  await page.route("**/api/billing/capacity", (route) =>
    fulfillJson(route, summary)
  );
  await page.goto(scopedPath("settings/billing"));
  await expect(
    page.getByRole("tab", { name: "Billing Settings", exact: true })
  ).toHaveAttribute("aria-selected", "true");
  await expect(
    page.getByRole("heading", { name: "Add inference credit" })
  ).toBeVisible();
  await expect(
    page.getByRole("heading", { name: "Recent usage costs" })
  ).toHaveCount(0);
  await page.getByRole("tab", { name: "Usage", exact: true }).click();
  await expect(page).toHaveURL(scopedPath("settings/billing?tab=usage"));
  await expect(
    page.getByText("Repository review", { exact: true })
  ).toBeVisible();
  await expect(page.getByText("$1.25", { exact: true })).toBeVisible();
  await expect(
    page.getByRole("heading", { name: "Add inference credit" })
  ).toHaveCount(0);
  await page.reload();
  await expect(
    page.getByRole("tab", { name: "Usage", exact: true })
  ).toHaveAttribute("aria-selected", "true");
  await page.goBack();
  await expect(
    page.getByRole("tab", { name: "Billing Settings", exact: true })
  ).toHaveAttribute("aria-selected", "true");
  await page.goForward();
  await expect(
    page.getByText("Repository review", { exact: true })
  ).toBeVisible();
});

test("mobile Settings navigation opens, selects a page and closes", async ({
  page,
}) => {
  await page.setViewportSize({ width: 390, height: 844 });
  await page.route("**/api/billing/capacity", (route) =>
    fulfillJson(route, { ...capacitySummary(), recentCosts: [] })
  );
  await page.goto(scopedPath("settings/account"));
  const menuButton = page.getByRole("button", { name: "Open navigation" });
  await expect(menuButton.locator("svg")).toBeVisible();
  const menuBounds = await menuButton.boundingBox();
  expect(menuBounds?.width).toBeGreaterThanOrEqual(36);
  expect(menuBounds?.height).toBeGreaterThanOrEqual(36);
  await menuButton.click();
  const dialog = page.getByRole("dialog", { name: "Navigation" });
  await dialog.getByRole("button", { name: "Back to main navigation" }).click();
  await expect(
    dialog.getByRole("link", { name: "Settings", exact: true })
  ).toBeFocused();
  await dialog.getByRole("link", { name: "Settings", exact: true }).click();
  await dialog.getByRole("link", { name: "Billing", exact: true }).click();
  await expect(dialog).not.toBeVisible();
  await expect(page).toHaveURL(scopedPath("settings/billing"));
  await page.getByRole("tab", { name: "Usage", exact: true }).click();
  await expect(page.getByText("No usage costs yet.")).toBeVisible();
  expect(
    await page.evaluate(
      () => document.documentElement.scrollWidth <= window.innerWidth
    )
  ).toBe(true);
  await page.getByRole("button", { name: "Open navigation" }).click();
  await expect(
    page
      .getByRole("dialog", { name: "Navigation" })
      .getByRole("link", { name: "Billing", exact: true })
  ).toBeVisible();
});

for (const width of [320, 390, 640, 700, 768, 1280]) {
  test(`team icon content stays readable at ${width}px`, async ({ page }) => {
    await page.setViewportSize({ width, height: 900 });
    await mockTeamSettings(page, "owner");
    await page.route(`**/api/teams/${TEAM.id}/members`, (route) =>
      fulfillJson(route, {
        team: { ...TEAM, iconUrl: "/icon.png" },
        viewer: { role: "owner", canManage: true },
        members: [],
        invites: [],
      })
    );
    await page.goto(`${TEAM_SETTINGS_PATH}/members`);
    const section = page.locator("section").filter({
      has: page.getByText("Team icon", { exact: true }),
    });
    const caption = section.getByText("PNG, JPG, WEBP, or GIF", {
      exact: false,
    });
    await expect(caption).toBeVisible();
    const captionBounds = await caption.boundingBox();
    expect(captionBounds?.width).toBeGreaterThanOrEqual(140);
    const replace = section.getByRole("button", {
      name: "Replace",
      exact: true,
    });
    const remove = section.getByRole("button", { name: "Remove", exact: true });
    await expect(replace).toBeVisible();
    await expect(remove).toBeVisible();
    const replaceBounds = await replace.boundingBox();
    const removeBounds = await remove.boundingBox();
    expect(replaceBounds).not.toBeNull();
    expect(removeBounds).not.toBeNull();
    expect(replaceBounds!.y).toBe(removeBounds!.y);
    const sectionBounds = await section.boundingBox();
    expect(sectionBounds?.height).toBeLessThan(230);
    if (width < 640) {
      expect(replaceBounds!.y).toBeGreaterThanOrEqual(
        captionBounds!.y + captionBounds!.height
      );
    }
    expect(
      await page.evaluate(
        () => document.documentElement.scrollWidth <= window.innerWidth
      )
    ).toBe(true);
    await page.screenshot({ path: test.info().outputPath("team-icon.png") });
  });
}

test("team Settings has team pages and limits Audit access", async ({
  page,
}) => {
  await mockTeamSettings(page, "viewer");
  await page.goto(TEAM_SETTINGS_PATH);
  await expect(page).toHaveURL(`${TEAM_SETTINGS_PATH}/members`);
  const nav = page.getByRole("navigation", { name: "Settings", exact: true });
  await expect(
    nav.getByRole("link", { name: "Members", exact: true })
  ).toBeVisible();
  await expect(
    nav.getByRole("link", { name: "Account", exact: true })
  ).toHaveCount(0);
  await expect(
    nav.getByRole("link", { name: "Audit", exact: true })
  ).toHaveCount(0);
  await expect(page.getByRole("tab")).toHaveCount(0);
  await page.goto(`${TEAM_SETTINGS_PATH}/audit`);
  await expect(
    page.getByText("Only a team owner or admin can view the audit log.")
  ).toBeVisible();
});

test("old key links open the right page and preserve unrelated query values", async ({
  page,
}) => {
  await page.goto(scopedPath("settings?tab=keys&sub=cli&keep=1"));
  await expect(page).toHaveURL(scopedPath("settings/mogplex-keys?keep=1"));
  await expect(
    page.getByRole("heading", { name: "Mogplex Keys", exact: true })
  ).toBeVisible();
  await page.goto(scopedPath("settings#teams"));
  await expect(page).toHaveURL(scopedPath("settings/teams"));
});

test("Settings expands a compact sidebar and preserves the main menu width", async ({
  page,
}) => {
  await page.addInitScript(() => {
    localStorage.setItem("mogplex.appSidebar.width", "64");
    localStorage.setItem("mogplex.appSidebar.collapsed", "true");
    localStorage.setItem("mogplex-theme", "dark");
  });
  await page.emulateMedia({ colorScheme: "dark" });
  await page.route(/\/api\/settings(?:\?.*)?$/, (route) =>
    fulfillJson(route, { theme: "dark" })
  );
  await page.goto(scopedPath("settings/billing"));
  const sidebar = page.getByTestId("app-sidebar");
  await expect(sidebar).toHaveAttribute("data-compact", "false");
  await expect(page.getByTestId("settings-nav-billing")).toBeVisible();
  await page
    .getByRole("button", { name: "Back to main navigation" })
    .press("Enter");
  await expect(sidebar).toHaveAttribute("data-compact", "true");
  await page.getByTestId("app-nav-settings").press("Enter");
  await expect(sidebar).toHaveAttribute("data-compact", "false");
  await expect(page.getByTestId("settings-nav-account")).toHaveAttribute(
    "aria-current",
    "page"
  );
  await expect(
    page.getByRole("heading", { name: "Account", exact: true })
  ).toBeVisible();
  await expect(page.getByRole("switch", { name: "Run checks" })).toBeEnabled();
});

test("team owners can open Keys and Audit as pages", async ({ page }) => {
  await mockTeamSettings(page, "owner");
  await page.goto(`${TEAM_SETTINGS_PATH}/members`);
  const nav = page.getByRole("navigation", { name: "Settings", exact: true });
  await nav.getByRole("link", { name: "Provider Keys", exact: true }).click();
  await expect(page).toHaveURL(`${TEAM_SETTINGS_PATH}/keys`);
  await expect(
    page.getByRole("heading", { name: "Provider Keys", exact: true })
  ).toBeVisible();
  await nav.getByRole("link", { name: "Audit", exact: true }).click();
  await expect(page).toHaveURL(`${TEAM_SETTINGS_PATH}/audit`);
  await expect(
    page.getByRole("heading", { name: "Audit", exact: true })
  ).toBeVisible();
  await expect(page.getByRole("tab")).toHaveCount(0);
  await page.reload();
  await expect(
    nav.getByRole("link", { name: "Audit", exact: true })
  ).toHaveAttribute("aria-current", "page");
});

test("Back restores focus and reentering Billing opens its Settings menu", async ({
  page,
}) => {
  await page.route("**/api/skills/catalog", (route) =>
    fulfillJson(route, { skills: [] })
  );
  await page.route("**/api/observability/calls**", (route) =>
    fulfillJson(route, { calls: [] })
  );
  await page.goto(scopedPath("settings/billing"));
  await page
    .getByRole("button", { name: "Back to main navigation" })
    .press("Enter");
  await expect(page.getByTestId("app-nav-settings")).toBeFocused();
  await page.getByTestId("app-nav-connections").click();
  await expect(page).toHaveURL(scopedPath("connections"));
  await page.getByRole("link", { name: "Manage billing", exact: true }).click();
  await expect(
    page.getByRole("navigation", { name: "Settings", exact: true })
  ).toBeVisible();
  await expect(page.getByTestId("settings-nav-billing")).toHaveAttribute(
    "aria-current",
    "page"
  );
  await expect(
    page.getByRole("separator", { name: "Resize app navigation" })
  ).toHaveCount(0);
});