import assert from "node:assert/strict"; import { existsSync, readFileSync } from "node:fs"; import test from "node:test"; const projectFile = (path: string) => new URL(`../${path}`, import.meta.url); const readProjectFile = (path: string) => readFileSync(projectFile(path), "utf8"); const globalStyles = readProjectFile("src/app/globals.css"); function cssBlock(selector: string) { const start = globalStyles.indexOf(`${selector} {`); assert.notEqual(start, -1, `missing CSS selector: ${selector}`); const end = globalStyles.indexOf("}", start); assert.notEqual(end, -1, `unterminated CSS selector: ${selector}`); return globalStyles.slice(start, end); } test("provides the generic composable sidebar primitive", () => { assert.equal(existsSync(projectFile("src/components/ui/sidebar.tsx")), true); }); test("exports only the retained sidebar composition surface", () => { const sidebar = readProjectFile("src/components/ui/sidebar.tsx"); for (const name of [ "SidebarProvider", "Sidebar", "SidebarHeader", "SidebarContent", "SidebarGroup", "SidebarGroupLabel", "SidebarGroupContent", "SidebarMenu", "SidebarMenuItem", "SidebarMenuButton", "SidebarFooter", "SidebarInset", "SidebarTrigger", "SidebarRail", "useSidebar", ]) { assert.match(sidebar, new RegExp(`export (?:function|const) ${name}\\b`)); } assert.doesNotMatch(sidebar, /SidebarMenuBadge|SidebarMenuSkeleton|SidebarMenuSub|side\?:|variant\?:/); }); test("keeps sidebar behavior in the generic primitive", () => { const sidebar = readProjectFile("src/components/ui/sidebar.tsx"); assert.match(sidebar, /useSidebarViewport/); assert.match(sidebar, /defaultSidebarOpen/); assert.match(sidebar, /shouldHandleSidebarShortcut/); assert.match(sidebar, /data-state/); assert.match(sidebar, /data-viewport/); assert.match(sidebar, /data-mobile-open/); assert.match(sidebar, /addEventListener\("keydown"/); assert.match(sidebar, /preventDefault\(\)/); assert.match(sidebar, /viewport === "mobile" \|\| !openMobile\) return;[\s\S]*setOpenMobile\(false\)/); assert.match(sidebar, /@base-ui\/react\/tooltip/); assert.doesNotMatch(sidebar, /Sheet/); assert.match(sidebar, /cn\(/); assert.doesNotMatch(sidebar, /#[0-9a-fA-F]{3,8}|hsl\(/); }); test("provides the mobile drawer closing surface", () => { const sidebar = readProjectFile("src/components/ui/sidebar.tsx"); assert.match(sidebar, /data-sidebar="scrim"/); assert.match(sidebar, /data-slot="sidebar-scrim"/); assert.match(sidebar, /aria-label="关闭聊天记录"/); assert.match(sidebar, /onClick=\{\(\) => setOpenMobile\(false\)\}/); assert.match(sidebar, /isMobile && openMobile \?