mirror of
https://github.com/getpaseo/paseo.git
synced 2026-10-31 05:32:58 +00:00
The notice arrived with the terminal worker change (#7644) but is a separate product change. Remove it with the native/compact callout filtering it needed, restoring the sidebar callout slot to web-only. Restart and close terminals in Settings stays.
555 lines
21 KiB
TypeScript
555 lines
21 KiB
TypeScript
import { test, expect } from "../support/fixtures";
|
|
import {
|
|
buildHostWorkspaceRoute,
|
|
buildOpenProjectRoute,
|
|
buildSettingsHostSectionRoute,
|
|
buildSettingsRoute,
|
|
buildSettingsSectionRoute,
|
|
} from "@/utils/host-routes";
|
|
import { gotoAppShell, openSettings } from "../support/helpers/app";
|
|
import { getE2EDaemonPort } from "../support/helpers/daemon-port";
|
|
import {
|
|
closeCompactSettings,
|
|
scrollSettingsSidebarToEnd,
|
|
revealSettingsSidebarSection,
|
|
expectSettingsSidebarScrollSettled,
|
|
scrollSettingsSidebarUp,
|
|
changeSettingsInterfaceFontSize,
|
|
selectSettingsHostSectionsRapidly,
|
|
expectSettingsSidebarScrollOffset,
|
|
scrollSettingsDetailDown,
|
|
expectSettingsDetailScrollOffset,
|
|
openSettingsSection,
|
|
expectSettingsHeader,
|
|
openAddHostFlow,
|
|
selectHostConnectionType,
|
|
toggleHostAdvanced,
|
|
openCompactSettings,
|
|
expectCompactSettingsList,
|
|
expectSettingsSidebarVisible,
|
|
expectSettingsSidebarHidden,
|
|
expectSettingsSidebarSections,
|
|
goBackInSettings,
|
|
expectSettingsBackButton,
|
|
clickSettingsBackToWorkspace,
|
|
verifyLegacyHostSettingsRedirect,
|
|
openCompactSettingsHost,
|
|
expectAddHostMethodOptions,
|
|
fillDirectHostUri,
|
|
expectDirectHostFormValues,
|
|
expectDirectHostSslEnabled,
|
|
expectDirectHostUriValue,
|
|
expectDirectHostUriHidden,
|
|
expectDiagnosticsContent,
|
|
expectAboutContent,
|
|
expectGeneralContent,
|
|
expectAppearanceContent,
|
|
seedSavedSettingsHosts,
|
|
selectSettingsHost,
|
|
expectSettingsHostPickerLabel,
|
|
openSettingsHostSection,
|
|
removeCurrentHostFromSettings,
|
|
} from "../support/helpers/settings";
|
|
import { getServerId } from "../support/helpers/server-id";
|
|
import { expectAppRoute } from "../support/helpers/route-assertions";
|
|
import { clickNewChat, gotoWorkspace } from "../support/helpers/launcher";
|
|
import { openAgentRoute, seedMockAgentWorkspace } from "../support/helpers/mock-agent";
|
|
|
|
async function openWorkspace(
|
|
page: import("@playwright/test").Page,
|
|
workspace: { workspaceId: string },
|
|
) {
|
|
await page.goto(buildHostWorkspaceRoute(getServerId(), workspace.workspaceId));
|
|
await expect(page.getByTestId("menu-button")).toBeVisible();
|
|
}
|
|
|
|
test.describe("Settings sidebar scroll position", () => {
|
|
test.use({ viewport: { width: 1000, height: 500 } });
|
|
|
|
test("clamps after resizing and starts a fresh visit at the top", async ({ page }) => {
|
|
await gotoAppShell(page);
|
|
await openSettings(page);
|
|
await scrollSettingsSidebarToEnd(page);
|
|
await page.setViewportSize({ width: 1000, height: 1100 });
|
|
await expectSettingsSidebarScrollOffset(page, 0);
|
|
await page.setViewportSize({ width: 1000, height: 500 });
|
|
await openSettingsSection(page, "appearance");
|
|
await expectSettingsSidebarScrollOffset(page, 0);
|
|
await scrollSettingsSidebarToEnd(page);
|
|
await clickSettingsBackToWorkspace(page);
|
|
await openSettings(page);
|
|
await expectSettingsSidebarScrollOffset(page, 0);
|
|
});
|
|
|
|
test("keeps the sidebar position through interface font changes", async ({ page }) => {
|
|
await gotoAppShell(page);
|
|
await openSettings(page);
|
|
await openSettingsSection(page, "appearance");
|
|
const offset = await scrollSettingsSidebarToEnd(page);
|
|
await changeSettingsInterfaceFontSize(page, 20);
|
|
await expectSettingsSidebarScrollOffset(page, offset);
|
|
await openSettingsHostSection(page, getServerId(), "providers");
|
|
await expectSettingsSidebarScrollOffset(page, offset);
|
|
});
|
|
|
|
test("scrolls the sidebar and detail pane independently", async ({ page }) => {
|
|
await gotoAppShell(page);
|
|
await openSettings(page);
|
|
const sidebarOffset = await scrollSettingsSidebarToEnd(page);
|
|
await openSettingsHostSection(page, getServerId(), "providers");
|
|
await expect(page.getByTestId("host-page-providers-card")).toBeVisible();
|
|
const detailOffset = await scrollSettingsDetailDown(page);
|
|
await expectSettingsSidebarScrollOffset(page, sidebarOffset);
|
|
|
|
await scrollSettingsSidebarUp(page, 60);
|
|
await expectSettingsSidebarScrollOffset(page, sidebarOffset - 60);
|
|
await expectSettingsDetailScrollOffset(page, detailOffset);
|
|
});
|
|
|
|
test("keeps the sidebar position after rapid consecutive selections", async ({ page }) => {
|
|
await gotoAppShell(page);
|
|
await openSettings(page);
|
|
|
|
const scrollTop = await scrollSettingsSidebarToEnd(page);
|
|
|
|
await selectSettingsHostSectionsRapidly(page);
|
|
await expectSettingsSidebarScrollOffset(page, scrollTop);
|
|
|
|
await expectSettingsSidebarScrollSettled(page, scrollTop);
|
|
});
|
|
|
|
test("keeps the sidebar position when switching between app and host sections", async ({
|
|
page,
|
|
}) => {
|
|
await gotoAppShell(page);
|
|
await openSettings(page);
|
|
|
|
const hostScrollTop = await scrollSettingsSidebarToEnd(page);
|
|
await expect(page.getByTestId("settings-host-section-providers")).toBeInViewport();
|
|
|
|
for (const section of [
|
|
"providers",
|
|
"terminals",
|
|
"providers",
|
|
"terminals",
|
|
"providers",
|
|
] as const) {
|
|
await openSettingsHostSection(page, getServerId(), section);
|
|
await expect(page.getByTestId("page-title")).toHaveText(
|
|
section === "providers" ? "Providers" : "Terminals",
|
|
);
|
|
await expectSettingsSidebarScrollOffset(page, hostScrollTop);
|
|
}
|
|
|
|
const sidebar = page.getByTestId("settings-sidebar");
|
|
const appScrollTop = await revealSettingsSidebarSection(page, "diagnostics");
|
|
await expect(sidebar.getByRole("button", { name: "About", exact: true })).toBeInViewport();
|
|
|
|
await openSettingsSection(page, "about");
|
|
await expectAboutContent(page);
|
|
await expectSettingsSidebarScrollOffset(page, appScrollTop);
|
|
|
|
await openSettingsSection(page, "diagnostics");
|
|
await expectDiagnosticsContent(page);
|
|
await expectSettingsSidebarScrollOffset(page, appScrollTop);
|
|
});
|
|
});
|
|
|
|
test.describe("Settings sidebar navigation", () => {
|
|
test("opening Settings closes the composer model selector until it is opened again", async ({
|
|
page,
|
|
withWorkspace,
|
|
}, testInfo) => {
|
|
const workspace = await withWorkspace({ prefix: "settings-model-selector-" });
|
|
await gotoWorkspace(page, workspace.workspaceId);
|
|
await clickNewChat(page);
|
|
|
|
const selector = page.getByTestId("combined-model-selector").filter({ visible: true });
|
|
const popover = page.getByTestId("combobox-desktop-container");
|
|
await selector.click();
|
|
await expect(popover).toBeVisible();
|
|
|
|
const modifier = process.platform === "darwin" ? "Meta" : "Control";
|
|
await page.keyboard.press(`${modifier}+,`);
|
|
await expect(page).toHaveURL(/\/settings\/general$/);
|
|
await page.screenshot({ path: testInfo.outputPath("settings-after-model-selector.png") });
|
|
await expect(popover).toHaveCount(0);
|
|
|
|
await clickSettingsBackToWorkspace(page);
|
|
await expect(selector).toBeVisible();
|
|
await expect(popover).toHaveCount(0);
|
|
|
|
await selector.click();
|
|
await expect(popover).toBeVisible();
|
|
await page.keyboard.press("Escape");
|
|
await expect(popover).toHaveCount(0);
|
|
});
|
|
|
|
test("opening Settings closes an existing chat's model selector until it is opened again", async ({
|
|
page,
|
|
}, testInfo) => {
|
|
const workspace = await seedMockAgentWorkspace({
|
|
repoPrefix: "settings-existing-model-",
|
|
title: "Settings model selector",
|
|
});
|
|
try {
|
|
await openAgentRoute(page, {
|
|
workspaceId: workspace.workspaceId,
|
|
agentId: workspace.agentId,
|
|
});
|
|
|
|
const selector = page.getByTestId("combined-model-selector").filter({ visible: true });
|
|
const popover = page.getByTestId("combobox-desktop-container");
|
|
await selector.click();
|
|
await expect(popover).toBeVisible();
|
|
|
|
const modifier = process.platform === "darwin" ? "Meta" : "Control";
|
|
await page.keyboard.press(`${modifier}+,`);
|
|
await expect(page).toHaveURL(/\/settings\/general$/);
|
|
await page.screenshot({
|
|
path: testInfo.outputPath("settings-after-existing-model-selector.png"),
|
|
});
|
|
await expect(popover).toHaveCount(0);
|
|
|
|
await clickSettingsBackToWorkspace(page);
|
|
await expect(selector).toBeVisible();
|
|
await expect(popover).toHaveCount(0);
|
|
|
|
await selector.click();
|
|
await expect(popover).toBeVisible();
|
|
await page.keyboard.press("Escape");
|
|
await expect(popover).toHaveCount(0);
|
|
} finally {
|
|
await workspace.cleanup();
|
|
}
|
|
});
|
|
|
|
test("clicking a sidebar section updates the URL and renders the section", async ({ page }) => {
|
|
await gotoAppShell(page);
|
|
await openSettings(page);
|
|
|
|
await openSettingsSection(page, "diagnostics");
|
|
await expectSettingsHeader(page, "Diagnostics");
|
|
await expectDiagnosticsContent(page);
|
|
|
|
await openSettingsSection(page, "about");
|
|
await expectSettingsHeader(page, "About");
|
|
await expectAboutContent(page);
|
|
|
|
await openSettingsSection(page, "general");
|
|
await expectSettingsHeader(page, "General");
|
|
await expectGeneralContent(page);
|
|
|
|
await openSettingsSection(page, "appearance");
|
|
await expectSettingsHeader(page, "Appearance");
|
|
await expectAppearanceContent(page);
|
|
|
|
await clickSettingsBackToWorkspace(page);
|
|
await expect(page).not.toHaveURL(/\/settings(\/|$)/);
|
|
});
|
|
|
|
test("host choice survives app sections and host screen replacements", async ({ page }) => {
|
|
const primaryServerId = getServerId();
|
|
const secondaryServerId = "srv_e2e_settings_secondary";
|
|
const endpoint = `127.0.0.1:${getE2EDaemonPort()}`;
|
|
await seedSavedSettingsHosts(page, [
|
|
{ serverId: primaryServerId, label: "First horse", endpoint },
|
|
{ serverId: secondaryServerId, label: "Stable horse", endpoint },
|
|
]);
|
|
await gotoAppShell(page);
|
|
await openSettings(page);
|
|
await selectSettingsHost(page, secondaryServerId);
|
|
await openSettingsHostSection(page, secondaryServerId, "connections");
|
|
await openSettingsSection(page, "appearance");
|
|
await expectSettingsHostPickerLabel(page, "Stable horse");
|
|
await openSettingsSection(page, "general");
|
|
await expectSettingsHostPickerLabel(page, "Stable horse");
|
|
await openSettingsHostSection(page, secondaryServerId, "connections");
|
|
await selectSettingsHost(page, primaryServerId);
|
|
await openSettingsSection(page, "about");
|
|
await expectSettingsHostPickerLabel(page, "First horse");
|
|
});
|
|
|
|
test("/h/[serverId]/settings redirects to the host connections section", async ({ page }) => {
|
|
await gotoAppShell(page);
|
|
await verifyLegacyHostSettingsRedirect(page);
|
|
});
|
|
|
|
test("direct connection advanced URI round-trips SSL and password into the form", async ({
|
|
page,
|
|
}) => {
|
|
await gotoAppShell(page);
|
|
await openSettings(page);
|
|
await openAddHostFlow(page);
|
|
await expectAddHostMethodOptions(page);
|
|
await selectHostConnectionType(page, "direct");
|
|
|
|
await toggleHostAdvanced(page);
|
|
await fillDirectHostUri(page, "tcp://example.paseo.test:7443?ssl=true&password=shared-secret");
|
|
await toggleHostAdvanced(page);
|
|
|
|
await expectDirectHostFormValues(page, {
|
|
host: "example.paseo.test",
|
|
port: "7443",
|
|
password: "shared-secret",
|
|
});
|
|
await expectDirectHostSslEnabled(page);
|
|
await expectDirectHostUriHidden(page);
|
|
|
|
await toggleHostAdvanced(page);
|
|
await expectDirectHostUriValue(
|
|
page,
|
|
"tcp://example.paseo.test:7443?ssl=true&password=shared-secret",
|
|
);
|
|
await toggleHostAdvanced(page);
|
|
await expectDirectHostUriHidden(page);
|
|
});
|
|
|
|
test("Escape lets settings dropdowns and modals close before leaving settings", async ({
|
|
page,
|
|
}) => {
|
|
await gotoAppShell(page);
|
|
await openSettings(page);
|
|
|
|
await test.step("a dropdown owns Escape", async () => {
|
|
await openSettingsSection(page, "appearance");
|
|
await page.getByLabel(/Theme:/).click();
|
|
await expect(page.getByRole("menuitem", { name: "System", exact: true })).toBeVisible();
|
|
|
|
await page.keyboard.press("Escape");
|
|
|
|
await expect(page.getByRole("menuitem", { name: "System", exact: true })).toHaveCount(0);
|
|
await expect(page).toHaveURL(/\/settings(\/|$)/);
|
|
});
|
|
|
|
await test.step("a modal owns Escape", async () => {
|
|
await openAddHostFlow(page);
|
|
await expect(page.getByText("Add connection", { exact: true })).toBeVisible();
|
|
|
|
await page.keyboard.press("Escape");
|
|
|
|
await expect(page.getByText("Add connection", { exact: true })).toHaveCount(0);
|
|
await expect(page).toHaveURL(/\/settings(\/|$)/);
|
|
});
|
|
|
|
await page.keyboard.press("Escape");
|
|
await expect(page).not.toHaveURL(/\/settings(\/|$)/);
|
|
});
|
|
});
|
|
|
|
test.describe("Settings — compact master-detail", () => {
|
|
test.use({ viewport: { width: 390, height: 844 } });
|
|
|
|
test("the compact tab switcher reopens after Settings hides its workspace", async ({ page }) => {
|
|
const workspace = await seedMockAgentWorkspace({
|
|
repoPrefix: "settings-tab-switcher-",
|
|
title: "Compact tab switcher",
|
|
});
|
|
try {
|
|
await openAgentRoute(page, {
|
|
workspaceId: workspace.workspaceId,
|
|
agentId: workspace.agentId,
|
|
});
|
|
|
|
const switcher = page.getByTestId("workspace-tab-switcher-trigger").filter({ visible: true });
|
|
const newAgent = page.getByTestId("workspace-tab-switcher-new-agent");
|
|
await switcher.click();
|
|
await expect(newAgent).toBeInViewport();
|
|
|
|
// Navigate without dismissing the sheet through its backdrop first.
|
|
await page
|
|
.getByTestId("menu-button")
|
|
.filter({ visible: true })
|
|
.first()
|
|
.dispatchEvent("click");
|
|
await page.getByTestId("sidebar-settings").first().dispatchEvent("click");
|
|
await expectAppRoute(page, buildSettingsRoute());
|
|
await expect(newAgent).toHaveCount(0);
|
|
|
|
await closeCompactSettings(page);
|
|
await expect(switcher).toBeVisible();
|
|
await expect(newAgent).toHaveCount(0);
|
|
await switcher.click();
|
|
await expect(newAgent).toBeInViewport();
|
|
} finally {
|
|
await workspace.cleanup();
|
|
}
|
|
});
|
|
|
|
test("opens compact app and host details and returns through the settings list", async ({
|
|
page,
|
|
}) => {
|
|
await gotoAppShell(page);
|
|
await openCompactSettings(page, buildOpenProjectRoute());
|
|
|
|
await expectSettingsSidebarSections(page, ["general", "diagnostics", "about"]);
|
|
await expectCompactSettingsList(page);
|
|
|
|
await test.step("open app details and return to the list", async () => {
|
|
await openSettingsSection(page, "diagnostics");
|
|
await expectAppRoute(page, buildSettingsSectionRoute("diagnostics"));
|
|
await expectDiagnosticsContent(page);
|
|
await expectSettingsSidebarHidden(page);
|
|
await expectSettingsBackButton(page);
|
|
await goBackInSettings(page);
|
|
await expectCompactSettingsList(page);
|
|
});
|
|
|
|
await test.step("open host details and return through the list", async () => {
|
|
await openCompactSettingsHost(page);
|
|
await expectSettingsBackButton(page);
|
|
await expectSettingsSidebarHidden(page);
|
|
await goBackInSettings(page);
|
|
await expectAppRoute(page, buildSettingsRoute());
|
|
await expectSettingsSidebarVisible(page);
|
|
await expectSettingsBackButton(page);
|
|
await goBackInSettings(page);
|
|
await expect(page).not.toHaveURL(/\/settings(\/|$)/);
|
|
});
|
|
});
|
|
|
|
test("host picker settings opens Overview and backs through the settings list", async ({
|
|
page,
|
|
withWorkspace,
|
|
}) => {
|
|
const workspace = await withWorkspace({ prefix: "host-picker-settings-back-" });
|
|
const workspaceRoute = buildHostWorkspaceRoute(getServerId(), workspace.workspaceId);
|
|
|
|
await openWorkspace(page, workspace);
|
|
await page.getByRole("button", { name: "Open menu", exact: true }).click();
|
|
await page.getByTestId("sidebar-hosts-trigger").click();
|
|
await page.getByRole("button", { name: /Open .* settings/ }).click();
|
|
|
|
await expectAppRoute(page, buildSettingsHostSectionRoute(getServerId(), "host"));
|
|
await expect(page.getByText("Overview", { exact: true })).toBeVisible();
|
|
|
|
await goBackInSettings(page);
|
|
await expectCompactSettingsList(page);
|
|
|
|
await goBackInSettings(page);
|
|
await expectAppRoute(page, workspaceRoute);
|
|
});
|
|
|
|
test("switching the host picker on the settings list scopes host rows without navigating", async ({
|
|
page,
|
|
}) => {
|
|
const primaryServerId = getServerId();
|
|
const secondaryServerId = "srv_e2e_settings_secondary";
|
|
const secondaryHostLabel = "Stable horse";
|
|
const endpoint = `127.0.0.1:${getE2EDaemonPort()}`;
|
|
|
|
await seedSavedSettingsHosts(page, [
|
|
{ serverId: primaryServerId, label: "First horse", endpoint },
|
|
{ serverId: secondaryServerId, label: secondaryHostLabel, endpoint },
|
|
]);
|
|
await gotoAppShell(page);
|
|
await openCompactSettings(page, buildOpenProjectRoute());
|
|
|
|
await selectSettingsHost(page, secondaryServerId);
|
|
|
|
await expectAppRoute(page, buildSettingsRoute());
|
|
await expectSettingsSidebarVisible(page);
|
|
await expectSettingsHostPickerLabel(page, secondaryHostLabel);
|
|
|
|
await openSettingsHostSection(page, secondaryServerId, "connections");
|
|
await goBackInSettings(page);
|
|
await expectSettingsHostPickerLabel(page, secondaryHostLabel);
|
|
|
|
await openSettingsSection(page, "appearance");
|
|
await goBackInSettings(page);
|
|
await expectSettingsHostPickerLabel(page, secondaryHostLabel);
|
|
await openSettingsHostSection(page, secondaryServerId, "connections");
|
|
await goBackInSettings(page);
|
|
await expectSettingsHostPickerLabel(page, secondaryHostLabel);
|
|
});
|
|
|
|
test("removing the last active host returns to welcome after settings closes", async ({
|
|
page,
|
|
withWorkspace,
|
|
}) => {
|
|
const workspace = await withWorkspace({ prefix: "remove-host-compact-" });
|
|
|
|
await openWorkspace(page, workspace);
|
|
await openCompactSettings(page, buildHostWorkspaceRoute(getServerId(), workspace.workspaceId));
|
|
await openSettingsHostSection(page, getServerId(), "host");
|
|
await removeCurrentHostFromSettings(page);
|
|
await closeCompactSettings(page);
|
|
|
|
await expect(page).toHaveURL(/\/welcome$/);
|
|
await expect(page.getByTestId("welcome-direct-connection")).toBeVisible();
|
|
});
|
|
});
|
|
|
|
async function measureDockedNavigation(page: import("@playwright/test").Page, width: number) {
|
|
await page.setViewportSize({ width, height: 951 });
|
|
const history = page.getByRole("button", { name: /^History/ }).filter({ visible: true });
|
|
const settings = page
|
|
.getByRole("button", { name: "Settings", exact: true })
|
|
.filter({ visible: true });
|
|
await expect(history).toBeVisible();
|
|
await expect(settings).toBeVisible();
|
|
return {
|
|
width,
|
|
history: await history.evaluate((el) => el.getBoundingClientRect().height),
|
|
settings: await settings.evaluate((el) => el.getBoundingClientRect().height),
|
|
};
|
|
}
|
|
|
|
async function measureSettingsSplit(page: import("@playwright/test").Page, width: number) {
|
|
await page.setViewportSize({ width, height: 951 });
|
|
const sidebar = page.getByTestId("settings-sidebar");
|
|
const detail = page.getByTestId("settings-detail-pane");
|
|
await expect(sidebar).toBeVisible();
|
|
await expect(detail).toBeVisible();
|
|
return {
|
|
width,
|
|
sidebar: await sidebar.evaluate((el) => el.getBoundingClientRect().width),
|
|
detail: await detail.evaluate((el) => el.getBoundingClientRect().width),
|
|
};
|
|
}
|
|
|
|
async function expectConsistentDockedNavigation(page: import("@playwright/test").Page) {
|
|
const wide = await measureDockedNavigation(page, 951);
|
|
for (const width of [600, 669, 719, 720]) {
|
|
const narrow = await measureDockedNavigation(page, width);
|
|
expect
|
|
.soft(narrow.history, `History keeps its wide-layout density at ${width}`)
|
|
.toBeCloseTo(wide.history, 0);
|
|
expect
|
|
.soft(narrow.settings, `Settings keeps its wide-layout density at ${width}`)
|
|
.toBeCloseTo(wide.settings, 0);
|
|
}
|
|
}
|
|
|
|
async function expectSettingsDetailKeepsReadingWidth(page: import("@playwright/test").Page) {
|
|
const reference = await measureSettingsSplit(page, 720);
|
|
for (const width of [600, 669, 719]) {
|
|
const narrow = await measureSettingsSplit(page, width);
|
|
expect
|
|
.soft(narrow.detail, `Settings preserves its detail budget at ${width}`)
|
|
.toBeGreaterThanOrEqual(reference.detail);
|
|
expect
|
|
.soft(narrow.sidebar, `Settings navigation yields width at ${width}`)
|
|
.toBeLessThan(reference.sidebar);
|
|
}
|
|
const wide = await measureSettingsSplit(page, 951);
|
|
expect(wide.sidebar).toBeCloseTo(reference.sidebar, 0);
|
|
expect(wide.detail).toBeGreaterThan(reference.detail);
|
|
}
|
|
|
|
test("docked navigation keeps its density and Settings preserves reading width", async ({
|
|
page,
|
|
withWorkspace,
|
|
}) => {
|
|
const workspace = await withWorkspace({ prefix: "narrow-wide-layout-" });
|
|
await gotoWorkspace(page, workspace.workspaceId);
|
|
await expectConsistentDockedNavigation(page);
|
|
await openSettings(page);
|
|
await openSettingsSection(page, "appearance");
|
|
await expectAppearanceContent(page);
|
|
await expectSettingsDetailKeepsReadingWidth(page);
|
|
await page.setViewportSize({ width: 599, height: 951 });
|
|
await expectSettingsSidebarHidden(page);
|
|
await expectAppearanceContent(page);
|
|
});
|