refactor(webui): unify floating controls

This commit is contained in:
Xubin Ren
2026-08-04 18:05:34 +08:00
parent faff0ac2fa
commit 7819cef7bd
16 changed files with 777 additions and 257 deletions
+28 -14
View File
@@ -1,4 +1,5 @@
import { act, fireEvent, render, screen, waitFor, within } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import i18n from "@/i18n";
@@ -1715,6 +1716,7 @@ describe("App layout", () => {
});
it("opens the settings view from the sidebar footer", async () => {
const user = userEvent.setup();
mockSessions = [
{
key: "websocket:chat-a",
@@ -1729,6 +1731,18 @@ describe("App layout", () => {
"fetch",
vi.fn(async (input: RequestInfo | URL) => {
const href = String(input);
if (href === "/api/settings/api-service") {
return jsonResponse({
installed: false,
running: false,
managed: false,
host: "127.0.0.1",
port: 8900,
timeout: 120,
endpoint: "http://127.0.0.1:8900/v1",
command: "nanobot serve",
});
}
if (href === "/api/settings/provider-models?provider=openai") {
return jsonResponse({
provider: "openai",
@@ -1996,8 +2010,8 @@ describe("App layout", () => {
.getAllByRole("button", { name: /OpenAI/ })
.some((button) => button.getAttribute("aria-haspopup") === "menu"),
).toBe(true);
fireEvent.pointerDown(screen.getByRole("button", { name: "Select model" }));
fireEvent.click(await screen.findByText("openai/gpt-4o-mini"));
await user.click(screen.getByRole("button", { name: "Select model" }));
await user.click(await screen.findByRole("option", { name: /openai\/gpt-4o-mini/ }));
expect(screen.getByRole("button", { name: "Save preset" })).toBeEnabled();
fireEvent.click(screen.getByRole("button", { name: "Cancel" }));
expect(screen.queryByText("Up to date.")).not.toBeInTheDocument();
@@ -2006,14 +2020,13 @@ describe("App layout", () => {
);
fireEvent.pointerDown(screen.getByRole("button", { name: /Auto/ }));
expect(screen.getAllByTestId("provider-picker-logo-openai").length).toBeGreaterThan(0);
fireEvent.click(screen.getByRole("menuitem", { name: /Auto/ }));
const openModelPicker = () => {
fireEvent.click(screen.getByRole("menuitemradio", { name: /Auto/ }));
const openModelPicker = async () => {
const modelButtons = screen.getAllByRole("button", { name: /openai\/gpt-4o/ });
fireEvent.pointerDown(modelButtons[modelButtons.length - 1]);
await user.click(modelButtons[modelButtons.length - 1]);
};
openModelPicker();
await screen.findByText("openai/gpt-4o-mini");
fireEvent.click(screen.getAllByText("openai/gpt-4o-mini")[0]);
await openModelPicker();
await user.click(await screen.findByRole("option", { name: /openai\/gpt-4o-mini/ }));
expect(screen.queryByText("Unsaved changes.")).not.toBeInTheDocument();
expect(screen.getByText("Model providers")).toBeInTheDocument();
expect(screen.getByRole("button", { name: "Add your own model provider" })).toBeInTheDocument();
@@ -2078,9 +2091,9 @@ describe("App layout", () => {
target: { value: "unsaved-brave-key" },
});
fireEvent.pointerDown(screen.getByRole("button", { name: /Brave Search/ }));
fireEvent.click(screen.getByRole("menuitem", { name: "Tavily" }));
fireEvent.click(screen.getByRole("menuitemradio", { name: "Tavily" }));
fireEvent.pointerDown(screen.getByRole("button", { name: /Tavily/ }));
fireEvent.click(screen.getByRole("menuitem", { name: "Brave Search" }));
fireEvent.click(screen.getByRole("menuitemradio", { name: "Brave Search" }));
expect(screen.getByText("BSAo••••ew20")).toBeInTheDocument();
expect(screen.queryByDisplayValue("unsaved-brave-key")).not.toBeInTheDocument();
@@ -2095,12 +2108,13 @@ describe("App layout", () => {
expect(screen.queryByText("Unified session")).not.toBeInTheDocument();
expect(screen.getByText("Default workspace")).toBeInTheDocument();
expect(screen.getByRole("button", { name: "Save" })).toBeDisabled();
fireEvent.pointerDown(screen.getByRole("button", { name: "UTC" }));
expect(screen.getByPlaceholderText("Search timezone")).toBeInTheDocument();
fireEvent.change(screen.getByPlaceholderText("Search timezone"), {
fireEvent.click(screen.getByRole("button", { name: "UTC" }));
const timezoneSearch = await screen.findByPlaceholderText("Search timezone");
expect(timezoneSearch).toBeInTheDocument();
fireEvent.change(timezoneSearch, {
target: { value: "Shanghai" },
});
fireEvent.click(screen.getByRole("menuitem", { name: /Asia\/Shanghai/ }));
await user.click(screen.getByRole("option", { name: /Asia\/Shanghai/ }));
expect(screen.getByRole("button", { name: "Asia/Shanghai" })).toBeInTheDocument();
expect(screen.getByRole("button", { name: "Save" })).toBeEnabled();
});