import { describe, it } from "node:test"; import assert from "node:assert/strict"; import React from "react"; import { Sidebar } from "../src/components/Sidebar"; import { TooltipProvider } from "../src/components/ui/tooltip"; import { click, render, screen } from "./render"; describe("Sidebar", () => { it("renders V2 expanded sidebar sections and footer actions", async () => { const events = makeSidebarEvents(); renderSidebar(false, events); assert.equal(Boolean(screen.queryByTitle("刷新")), false, "expanded sidebar should not render refresh"); assert.equal(Boolean(screen.queryByLabelText("设置")), false, "expanded sidebar should not render top settings"); assert.equal(Boolean(screen.queryByText("llm-wiki-agent")), false, "expanded sidebar should not repeat the topbar brand"); assert.ok(screen.getByLabelText("折叠侧栏")); assert.ok(screen.getByText("笔记本")); assert.ok(screen.getByText("会话")); assert.ok(screen.getByRole("button", { name: "图谱活地图" })); assert.ok(screen.getByRole("button", { name: "设置" })); assert.ok(screen.getByRole("button", { name: "新建知识库" })); assert.equal(Boolean(screen.queryByText("添加现有库")), false, "sidebar should rename add-existing flow"); assert.equal(Boolean(document.querySelector(".main-view-switch")), false, "expanded sidebar should not render old view switch"); await click(screen.getByRole("button", { name: "图谱活地图" })); await click(screen.getByRole("button", { name: "设置" })); await click(screen.getByRole("button", { name: "新建知识库" })); assert.deepEqual(events.views, ["graph"]); assert.equal(events.settings, 1); assert.ok(await screen.findByRole("heading", { name: "新建知识库" })); }); it("renders conversations outside the knowledge-base tree", () => { renderSidebar(false); const notebookSection = screen.getByText("笔记本").closest(".sidebar-section"); const conversationSection = screen.getByText("会话").closest(".sidebar-section"); assert.ok(notebookSection); assert.ok(conversationSection); assert.equal(notebookSection?.contains(screen.getByText("Transformer vs Mamba")), false); assert.equal(conversationSection?.contains(screen.getByText("Transformer vs Mamba")), true); assert.equal(Boolean(document.querySelector(".kb-children")), false, "conversations should not be nested under knowledge bases"); }); it("keeps the collapsed rail aligned with V2 actions", async () => { const events = makeSidebarEvents(); renderSidebar(true, events); assert.ok(screen.getByLabelText("展开侧栏")); assert.ok(screen.getByLabelText("当前知识库:AI学习知识库")); assert.ok(screen.getByLabelText("对话")); assert.ok(screen.getByLabelText("图谱活地图")); assert.ok(screen.queryByLabelText("设置")); assert.ok(screen.getByLabelText("新建知识库")); assert.equal(Boolean(screen.queryByLabelText("刷新")), false, "collapsed rail should not render refresh"); assert.equal(Boolean(screen.queryByLabelText("添加现有库")), false, "collapsed rail should not render add-existing"); await click(screen.getByLabelText("新建知识库")); assert.ok(await screen.findByRole("heading", { name: "新建知识库" })); }); }); function makeSidebarEvents() { return { views: [] as string[], settings: 0, }; } function renderSidebar(collapsed: boolean, events = makeSidebarEvents()) { return render( { events.views.push(`conversation:${item.id}`); }} onSelectView={(view) => events.views.push(view)} onNewConversation={noop} onOpenSettings={() => { events.settings += 1; }} onToggleCollapsed={noop} onAddExternal={asyncNoop} /> , ); } function noop() {} async function asyncNoop() {}