fix(windows): fenêtres de panneau détachées suivent le projet en focus côté UI (#47)
Partie frontend. Ajoute un adaptateur focusedProject et un port dédié : la ViewWindow détachée n'est plus liée à un project_id figé, elle s'abonne à l'event focused-project émis par la fenêtre principale et affiche le panneau du projet courant. ProjectsView propage le focus ; le détachement crée une fenêtre panel-only. Couvert par les tests window/ViewWindow/focusedProject/ ProjectsView.focus. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@ -12,6 +12,7 @@ import {
|
||||
MockAgentGateway,
|
||||
MockGitGateway,
|
||||
MockProfileGateway,
|
||||
MockFocusedProjectGateway,
|
||||
MockProjectGateway,
|
||||
MockSystemGateway,
|
||||
MockTemplateGateway,
|
||||
@ -24,7 +25,7 @@ import { ProjectsView } from "./ProjectsView";
|
||||
|
||||
async function renderWithProject() {
|
||||
const project = new MockProjectGateway();
|
||||
const created = await project.createProject("alpha", "/p/a");
|
||||
await project.createProject("alpha", "/p/a");
|
||||
const agentGateway = new MockAgentGateway();
|
||||
const windowGateway = new MockWindowGateway();
|
||||
const gateways = {
|
||||
@ -36,6 +37,7 @@ async function renderWithProject() {
|
||||
git: new MockGitGateway(),
|
||||
workState: new MockWorkStateGateway(),
|
||||
window: windowGateway,
|
||||
focusedProject: new MockFocusedProjectGateway(),
|
||||
} as unknown as Gateways;
|
||||
render(
|
||||
<DIProvider gateways={gateways}>
|
||||
@ -46,7 +48,7 @@ async function renderWithProject() {
|
||||
await waitFor(() =>
|
||||
expect(within(screen.getByRole("tablist")).getAllByRole("tab")).toHaveLength(1),
|
||||
);
|
||||
return { windowGateway, projectId: created.id };
|
||||
return { windowGateway };
|
||||
}
|
||||
|
||||
/**
|
||||
@ -62,7 +64,7 @@ function pickPlacement(panelTitle: string, placementLabel: string) {
|
||||
|
||||
describe("ProjectsView detach to OS window (#23)", () => {
|
||||
it("« Fenêtre détachée » detaches a view: opens the OS window and marks the slot detached", async () => {
|
||||
const { windowGateway, projectId } = await renderWithProject();
|
||||
const { windowGateway } = await renderWithProject();
|
||||
|
||||
// A docked view is visible in the main window first…
|
||||
pickPlacement("Git", "Ancré à gauche");
|
||||
@ -72,7 +74,7 @@ describe("ProjectsView detach to OS window (#23)", () => {
|
||||
pickPlacement("Git", "Fenêtre détachée");
|
||||
|
||||
await waitFor(() =>
|
||||
expect(windowGateway.open.has(`git|${projectId}`)).toBe(true),
|
||||
expect(windowGateway.open.has("git")).toBe(true),
|
||||
);
|
||||
// The slot is detached ⇒ nothing renders for Git in the main window.
|
||||
await waitFor(() =>
|
||||
@ -82,11 +84,11 @@ describe("ProjectsView detach to OS window (#23)", () => {
|
||||
});
|
||||
|
||||
it("re-toggles the placement out of detached when the OS window closes", async () => {
|
||||
const { windowGateway, projectId } = await renderWithProject();
|
||||
const { windowGateway } = await renderWithProject();
|
||||
|
||||
pickPlacement("Git", "Fenêtre détachée");
|
||||
await waitFor(() =>
|
||||
expect(windowGateway.open.has(`git|${projectId}`)).toBe(true),
|
||||
expect(windowGateway.open.has("git")).toBe(true),
|
||||
);
|
||||
|
||||
// The « Fenêtre détachée » submenu leaf shows the active marker (●) while
|
||||
@ -103,7 +105,7 @@ describe("ProjectsView detach to OS window (#23)", () => {
|
||||
fireEvent.click(screen.getByRole("button", { name: "Panneaux" })); // close
|
||||
|
||||
// The backend reports the OS window closed ⇒ the slot leaves "detached".
|
||||
windowGateway.simulateOsClose("git", projectId);
|
||||
windowGateway.simulateOsClose("git");
|
||||
openGitSubmenu();
|
||||
await waitFor(() =>
|
||||
expect(detachedLeaf().textContent).not.toContain("●"),
|
||||
|
||||
Reference in New Issue
Block a user