fix(webui): complete temporary chat mode

This commit is contained in:
chengyongru
2026-08-08 23:20:59 +08:00
committed by Xubin Ren
parent c9a6145878
commit a5bc3bfbb9
51 changed files with 1285 additions and 945 deletions
+30 -33
View File
@@ -1070,56 +1070,53 @@ describe("ThreadComposer", () => {
}));
});
it("keeps temporary-chat workspace controls on demand", async () => {
const user = userEvent.setup();
const onWorkspaceScopeChange = vi.fn();
it("slides project controls closed without offering a compact replacement", () => {
const defaultScope = {
project_path: "/Users/test/.nanobot/workspace",
project_name: "workspace",
access_mode: "restricted" as const,
restrict_to_workspace: true,
access_mode: "full" as const,
restrict_to_workspace: false,
};
const { rerender } = render(
const composer = (workspaceControlsHidden: boolean) => (
<ThreadComposer
onSend={vi.fn()}
placeholder="Ask anything..."
variant="hero"
compactWorkspaceControls
workspaceControlsHidden={workspaceControlsHidden}
workspaceScope={defaultScope}
workspaceDefaultScope={defaultScope}
workspaceControls={{ can_change_project: true, can_use_full_access: true }}
onWorkspaceScopeChange={onWorkspaceScopeChange}
/>,
onWorkspaceScopeChange={vi.fn()}
/>
);
const { container, rerender } = render(composer(false));
const drawer = container.querySelector("[data-composer-workspace-drawer]");
expect(drawer).toHaveAttribute("data-state", "open");
expect(drawer).not.toHaveAttribute("aria-hidden");
expect(container.querySelector("[data-composer-workspace-compact]")).not.toBeInTheDocument();
rerender(composer(true));
expect(container.querySelector("[data-composer-workspace-drawer]")).toBe(drawer);
expect(drawer).toHaveAttribute("data-state", "closed");
expect(drawer).toHaveAttribute("aria-hidden", "true");
expect(within(drawer as HTMLElement).getByRole("button", {
hidden: true,
name: "Choose project",
})).toBeDisabled();
expect(screen.queryByRole("button", { name: "Choose project" })).not.toBeInTheDocument();
expect(screen.queryByRole("button", {
name: "Workspace access mode: Default Permission",
name: "Workspace access mode: Full Access",
})).not.toBeInTheDocument();
await user.click(screen.getByRole("button", { name: "Choose project" }));
const input = await screen.findByLabelText("Paste path");
fireEvent.change(input, { target: { value: "relative/project" } });
fireEvent.click(screen.getByRole("button", { name: "Use Path" }));
expect(screen.getByRole("alert")).toHaveTextContent(
"Enter an absolute folder path on this machine.",
);
rerender(
<ThreadComposer
onSend={vi.fn()}
placeholder="Ask anything..."
variant="hero"
compactWorkspaceControls
workspaceConnected
workspaceScope={defaultScope}
workspaceDefaultScope={defaultScope}
workspaceControls={{ can_change_project: true, can_use_full_access: true }}
onWorkspaceScopeChange={onWorkspaceScopeChange}
/>,
);
rerender(composer(false));
expect(screen.getByRole("button", {
name: "Workspace access mode: Default Permission",
})).toBeInTheDocument();
expect(container.querySelector("[data-composer-workspace-drawer]")).toBe(drawer);
expect(drawer).toHaveAttribute("data-state", "open");
expect(within(drawer as HTMLElement).getByRole("button", {
name: "Choose project",
})).toBeEnabled();
});
it("uses the native folder picker for project selection on native host", async () => {