134 lines
5.0 KiB
TypeScript
134 lines
5.0 KiB
TypeScript
import { test, expect } from "../../fixtures/test-base";
|
|
import {
|
|
WIDE_VIEWPORT,
|
|
openWideTask,
|
|
expectApproxWidth,
|
|
getDockviewGroupWidth,
|
|
resizeColumnViaSplitview,
|
|
} from "../../helpers/dockview-resize";
|
|
import { KanbanPage } from "../../pages/kanban-page";
|
|
import { SessionPage } from "../../pages/session-page";
|
|
|
|
test.describe("Right pane resize — viewport-proportional cap", () => {
|
|
test("resizes past the old 450px hard cap", async ({ testPage, apiClient, seedData }) => {
|
|
await openWideTask(testPage, apiClient, seedData, "Right resize past old cap");
|
|
const actual = await resizeColumnViaSplitview(testPage, "right", 700);
|
|
expect(actual).toBeGreaterThan(600);
|
|
});
|
|
|
|
test("respects the viewport-proportional cap (max(800, vw*0.7))", async ({
|
|
testPage,
|
|
apiClient,
|
|
seedData,
|
|
}) => {
|
|
await openWideTask(testPage, apiClient, seedData, "Right cap respect");
|
|
const actual = await resizeColumnViaSplitview(testPage, "right", 5000);
|
|
const cap = Math.round(WIDE_VIEWPORT.width * 0.7);
|
|
expect(actual).toBeLessThanOrEqual(cap + 10);
|
|
});
|
|
|
|
test("user width survives reload (localStorage dockview-layout-v3 round-trip)", async ({
|
|
testPage,
|
|
apiClient,
|
|
seedData,
|
|
}) => {
|
|
const session = await openWideTask(testPage, apiClient, seedData, "Right resize reload");
|
|
const before = await resizeColumnViaSplitview(testPage, "right", 600);
|
|
|
|
await testPage.reload();
|
|
await session.waitForLoad();
|
|
await session.waitForDockviewReady();
|
|
|
|
const after = await getDockviewGroupWidth(testPage, "files");
|
|
expectApproxWidth(after, before, 12);
|
|
});
|
|
|
|
test("viewport shrink re-clamps an over-cap pinned width", async ({
|
|
testPage,
|
|
apiClient,
|
|
seedData,
|
|
}) => {
|
|
await openWideTask(testPage, apiClient, seedData, "Right viewport shrink");
|
|
const wideWidth = await resizeColumnViaSplitview(testPage, "right", 900);
|
|
expect(wideWidth).toBeGreaterThan(700);
|
|
|
|
await testPage.setViewportSize({ width: 1100, height: 800 });
|
|
// Allow ResizeObserver tick + applyDynamicConstraints to fire, then attempt
|
|
// a re-resize that would exceed the new cap.
|
|
await testPage.waitForTimeout(300);
|
|
const narrowWidth = await resizeColumnViaSplitview(testPage, "right", 1500);
|
|
|
|
const newCap = Math.max(800, Math.round(1100 * 0.7));
|
|
expect(narrowWidth).toBeLessThanOrEqual(newCap + 10);
|
|
});
|
|
});
|
|
|
|
test.describe("Right pane width — per-task isolation", () => {
|
|
test("a narrow resize in Task A does not leak into Task B", async ({
|
|
testPage,
|
|
apiClient,
|
|
seedData,
|
|
}) => {
|
|
test.setTimeout(120_000);
|
|
await testPage.setViewportSize(WIDE_VIEWPORT);
|
|
|
|
// Two tasks, same default layout. Each gets its own env id and its own
|
|
// persisted dockview layout in sessionStorage.
|
|
await apiClient.createTaskWithAgent(
|
|
seedData.workspaceId,
|
|
"Right Width Task A",
|
|
seedData.agentProfileId,
|
|
{
|
|
description: "/e2e:simple-message",
|
|
workflow_id: seedData.workflowId,
|
|
workflow_step_id: seedData.startStepId,
|
|
repository_ids: [seedData.repositoryId],
|
|
},
|
|
);
|
|
const taskB = await apiClient.createTaskWithAgent(
|
|
seedData.workspaceId,
|
|
"Right Width Task B",
|
|
seedData.agentProfileId,
|
|
{
|
|
description: "/e2e:simple-message",
|
|
workflow_id: seedData.workflowId,
|
|
workflow_step_id: seedData.startStepId,
|
|
repository_ids: [seedData.repositoryId],
|
|
},
|
|
);
|
|
|
|
const kanban = new KanbanPage(testPage);
|
|
await kanban.goto();
|
|
await kanban.taskCardByTitle("Right Width Task A").click();
|
|
await expect(testPage).toHaveURL(/\/t\//, { timeout: 15_000 });
|
|
const session = new SessionPage(testPage);
|
|
await session.waitForLoad();
|
|
await session.waitForDockviewReady();
|
|
|
|
// Resize Task A's right column to a deliberately narrow width. The default
|
|
// is ~450 on a 1600px viewport, so 240 is unambiguously a user override.
|
|
const narrowedA = await resizeColumnViaSplitview(testPage, "right", 240);
|
|
expect(narrowedA).toBeLessThan(300);
|
|
|
|
// Switch to Task B (no prior resize, default width). Regression: a stale
|
|
// global "right" pinned target from Task A's drag used to leak through
|
|
// captureRightTarget / enforcePinnedTargets after fromJSON, snapping
|
|
// Task B's right column to Task A's narrow width — and the next
|
|
// debounced persist would overwrite Task B's saved layout with the
|
|
// narrow width, making the leak sticky.
|
|
await session.clickTaskInSidebar("Right Width Task B");
|
|
await expect(testPage).toHaveURL((url) => url.pathname.includes(taskB.id), {
|
|
timeout: 15_000,
|
|
});
|
|
await expect(testPage.locator(".dv-dockview")).toBeVisible({ timeout: 15_000 });
|
|
// Allow fromJSON + fixups-capture + enforcePinnedTargets to settle.
|
|
await testPage.waitForTimeout(500);
|
|
|
|
const widthB = await getDockviewGroupWidth(testPage, "files");
|
|
expect(
|
|
widthB,
|
|
`Task B right width ${widthB} should be the default (>350), not Task A's narrow ${narrowedA}`,
|
|
).toBeGreaterThan(350);
|
|
});
|
|
});
|