Files
kandev/apps/web/e2e/tests/layout/changes-panel-focus.spec.ts
T
2026-04-23 09:54:06 +01:00

162 lines
5.5 KiB
TypeScript

import { test, expect } from "../../fixtures/test-base";
import { SessionPage } from "../../pages/session-page";
import { makeGitEnv } from "../../helpers/git-helper";
import fs from "node:fs";
import path from "node:path";
import { execSync } from "node:child_process";
/** Minimal git helper for E2E tests - runs git commands in the test repository. */
class GitHelper {
constructor(
private repoDir: string,
private env: NodeJS.ProcessEnv,
) {}
exec(cmd: string): string {
return execSync(cmd, { cwd: this.repoDir, env: this.env, encoding: "utf8" });
}
createFile(name: string, content: string) {
fs.writeFileSync(path.join(this.repoDir, name), content);
}
stageAll() {
this.exec("git add -A");
}
commit(message: string) {
this.exec(`git commit -m "${message}"`);
}
}
test.describe("Changes panel focus behavior", () => {
/**
* Verifies the changes panel does NOT steal focus from the chat tab
* on page refresh when the task has existing git changes/commits.
*
* Root cause of the bug: the changes-tab component auto-activated the
* changes panel whenever totalCount went from 0 → N. On page refresh,
* hooks start with totalCount=0 (no data loaded), then async git data
* arrives making totalCount > 0 — triggering the auto-activate.
*/
test("changes panel does not auto-focus on page refresh", async ({
testPage,
apiClient,
seedData,
backend,
}) => {
test.setTimeout(90_000);
const repoDir = path.join(backend.tmpDir, "repos", "e2e-repo");
const gitEnv = makeGitEnv(backend.tmpDir);
const git = new GitHelper(repoDir, gitEnv);
// Create a task and wait for the agent to be ready
const task = await apiClient.createTaskWithAgent(
seedData.workspaceId,
"Focus test task",
seedData.agentProfileId,
{
workflow_id: seedData.workflowId,
workflow_step_id: seedData.startStepId,
repository_ids: [seedData.repositoryId],
},
);
await testPage.goto(`/t/${task.id}`);
const session = new SessionPage(testPage);
await session.waitForLoad();
await expect(session.idleInput()).toBeVisible({ timeout: 30_000 });
// Create a file and commit so there are existing changes
git.createFile("test-file.txt", "hello world");
git.stageAll();
git.commit("test commit");
// Wait for the changes panel to show the commit
await session.clickTab("Changes");
await expect(session.changes).toBeVisible({ timeout: 10_000 });
await expect(session.changes.getByText("test commit")).toBeVisible({ timeout: 10_000 });
// Switch back to chat tab — this is the tab that should be active after refresh
await session.clickSessionChatTab();
await expect(session.chat).toBeVisible({ timeout: 5_000 });
// Refresh the page
await testPage.reload();
await session.waitForLoad();
// Wait for the git data to load (changes tab should show count)
await expect(testPage.locator(".dv-default-tab:has-text('Changes')")).toBeVisible({
timeout: 15_000,
});
// The chat/session panel should be the active tab, NOT changes
const changesTab = testPage.locator(".dv-default-tab:has-text('Changes')");
await expect(changesTab).not.toHaveClass(/dv-active-tab/, { timeout: 5_000 });
// Chat should be visible (active in center group)
await expect(session.chat).toBeVisible({ timeout: 5_000 });
});
/**
* Verifies the changes panel does NOT auto-focus when it is in the center
* group (e.g. plan mode layout). Even when new changes appear, the chat
* panel should stay focused.
*/
test("changes panel does not auto-focus when in center group", async ({
testPage,
apiClient,
seedData,
backend,
}) => {
test.setTimeout(90_000);
const repoDir = path.join(backend.tmpDir, "repos", "e2e-repo");
const gitEnv = makeGitEnv(backend.tmpDir);
const git = new GitHelper(repoDir, gitEnv);
const task = await apiClient.createTaskWithAgent(
seedData.workspaceId,
"Center group focus test",
seedData.agentProfileId,
{
workflow_id: seedData.workflowId,
workflow_step_id: seedData.startStepId,
repository_ids: [seedData.repositoryId],
},
);
await testPage.goto(`/t/${task.id}`);
const session = new SessionPage(testPage);
await session.waitForLoad();
await expect(session.idleInput()).toBeVisible({ timeout: 30_000 });
// Toggle plan mode — this moves changes into the center group
await session.togglePlanMode();
await expect(session.planPanel).toBeVisible({ timeout: 10_000 });
await expect(session.chat).toBeVisible();
// Verify the chat/session tab is active, not changes
const changesTab = testPage.locator(".dv-default-tab:has-text('Changes')");
await expect(changesTab).not.toHaveClass(/dv-active-tab/, { timeout: 5_000 });
// Create new changes — this would previously trigger auto-activate
git.createFile("new-file.txt", "new content");
git.stageAll();
git.commit("new commit");
// Wait for the changes badge to update
await expect(testPage.locator(".dv-default-tab:has-text('Changes')")).toBeVisible({
timeout: 15_000,
});
// Wait a bit for any async auto-activate to fire
await testPage.waitForTimeout(2_000);
// Changes tab should NOT have stolen focus
await expect(changesTab).not.toHaveClass(/dv-active-tab/, { timeout: 5_000 });
// Chat should still be visible (active)
await expect(session.chat).toBeVisible();
});
});