fix(frontend): isolate administration rail from portal CSS
This commit is contained in:
@@ -0,0 +1,107 @@
|
||||
import { expect, test, type Page, type Route } from "@playwright/test";
|
||||
import { createAuthenticationStack } from "./fixtures/auth-stack.mjs";
|
||||
|
||||
test.describe.configure({ mode: "serial" });
|
||||
test.use({ viewport: { width: 1660, height: 822 } });
|
||||
|
||||
let stack: Awaited<ReturnType<typeof createAuthenticationStack>>;
|
||||
|
||||
function json(route: Route, body: unknown) {
|
||||
return route.fulfill({
|
||||
status: 200,
|
||||
contentType: "application/json",
|
||||
body: JSON.stringify(body),
|
||||
});
|
||||
}
|
||||
|
||||
async function signInAsAdmin(page: Page) {
|
||||
const account = stack.localAccount("admin");
|
||||
await page.getByLabel("Username").fill(account.username);
|
||||
await page.locator('input[name="password"]').fill(account.password);
|
||||
await page.getByRole("button", { name: "Sign in", exact: true }).click();
|
||||
await expect(page.getByTestId("app-shell")).toBeVisible({ timeout: 30_000 });
|
||||
}
|
||||
|
||||
test.beforeAll(async () => {
|
||||
stack = await createAuthenticationStack({ withF1Workspace: true });
|
||||
await stack.useLocalMode();
|
||||
});
|
||||
|
||||
test.afterAll(async () => {
|
||||
await stack?.close();
|
||||
});
|
||||
|
||||
test("Administration stays within its rail when hosted by the Omics portal", async ({ page }) => {
|
||||
await page.route("**/api/settings", (route) => json(route, {
|
||||
workspace: "fixture-workspace",
|
||||
provider: "zai",
|
||||
model: "glm-5.2",
|
||||
thinking: "medium",
|
||||
}));
|
||||
await page.route("**/api/workspaces", (route) => json(route, [{
|
||||
id: "fixture-workspace",
|
||||
name: "fixture-workspace",
|
||||
file: "fixture-workspace/workspace.yaml",
|
||||
displayName: "Fixture workspace",
|
||||
configurationState: "ready",
|
||||
revision: {
|
||||
id: "fixture-workspace",
|
||||
commit: "a".repeat(40),
|
||||
blob: "b".repeat(40),
|
||||
snapshotPath: `/snapshots/${"a".repeat(40)}/fixture-workspace.yaml`,
|
||||
},
|
||||
}]));
|
||||
await page.route("**/api/workspaces/fixture-workspace/preprocessing", (route) => json(route, {
|
||||
schemaVersion: 1,
|
||||
workspaceId: "fixture-workspace",
|
||||
state: "running",
|
||||
actionable: false,
|
||||
clearable: false,
|
||||
detail: "Building schema and LSH.",
|
||||
progress: {
|
||||
stage: "schema_index",
|
||||
step: 2,
|
||||
totalSteps: 4,
|
||||
},
|
||||
}));
|
||||
|
||||
await page.goto(stack.publicUrl);
|
||||
await signInAsAdmin(page);
|
||||
await expect(page.getByRole("combobox", { name: "Workspace" })).toHaveValue("fixture-workspace");
|
||||
|
||||
// Hyper/Bootstrap and Thoth currently share the portal document. These
|
||||
// utility names are therefore resolved with the portal's !important values.
|
||||
await page.addStyleTag({ content: `
|
||||
.px-2 { padding-right: 0.75rem !important; padding-left: 0.75rem !important; }
|
||||
.px-3 { padding-right: 1.5rem !important; padding-left: 1.5rem !important; }
|
||||
.px-4 { padding-right: 2.25rem !important; padding-left: 2.25rem !important; }
|
||||
` });
|
||||
|
||||
const rail = page.getByRole("complementary", { name: "Session navigation" });
|
||||
await rail.getByRole("button", { name: "Administration", exact: true }).click();
|
||||
const administration = rail.getByRole("region", { name: "Administration" });
|
||||
const boundary = rail.getByTestId("administration-boundary");
|
||||
await expect(administration).toBeVisible();
|
||||
await expect(rail.getByText("2 / 4", { exact: true })).toBeVisible();
|
||||
|
||||
const containment = await administration.evaluate((panel) => {
|
||||
const elements = Array.from(panel.querySelectorAll<HTMLElement>('button, [role="progressbar"], span'))
|
||||
.filter((element) => element.matches('button, [role="progressbar"]') || element.textContent?.trim() === "2 / 4");
|
||||
return elements.map((element) => {
|
||||
const box = element.getBoundingClientRect();
|
||||
return {
|
||||
label: element.textContent?.trim() || element.getAttribute("aria-label") || element.tagName,
|
||||
left: box.left,
|
||||
right: box.right,
|
||||
};
|
||||
});
|
||||
});
|
||||
const boundaryBox = await boundary.boundingBox();
|
||||
expect(boundaryBox).not.toBeNull();
|
||||
if (!boundaryBox) return;
|
||||
|
||||
for (const item of containment) {
|
||||
expect.soft(item.left, `${item.label} crosses the Administration left edge`).toBeGreaterThanOrEqual(boundaryBox.x - 1);
|
||||
expect.soft(item.right, `${item.label} crosses the Administration right edge`).toBeLessThanOrEqual(boundaryBox.x + boundaryBox.width + 1);
|
||||
}
|
||||
});
|
||||
Reference in New Issue
Block a user