import { fireEvent, render, screen, waitFor } from "@testing-library/react" import { afterEach, beforeEach, describe, expect, it, vi } from "vitest" import type { Category } from "@/types/navigation" import { AppShell } from "./app-shell" const categories: Category[] = [ { id: "dev", title: "开发工具", description: "开发", icon: "code", sort: 10 }, ] describe("AppShell", () => { beforeEach(() => window.localStorage.clear()) afterEach(() => vi.restoreAllMocks()) it("切换侧栏并持久化状态", () => { render(
首页内容
, ) const toggle = screen.getByRole("button", { name: "折叠侧边栏" }) fireEvent.click(toggle) expect(screen.getByTestId("app-shell")).toHaveAttribute( "data-sidebar-collapsed", "true", ) expect(window.localStorage.getItem("polaris.sidebar.collapsed")).toBe( "true", ) }) it("hydration 后恢复持久化状态", async () => { window.localStorage.setItem("polaris.sidebar.collapsed", "true") render(
首页内容
, ) await waitFor(() => { expect(screen.getByTestId("app-shell")).toHaveAttribute( "data-sidebar-collapsed", "true", ) expect(screen.getByTestId("app-shell")).toHaveAttribute( "data-hydrated", "true", ) }) }) it("写入失败时内存偏好优先于旧持久化值", () => { window.localStorage.setItem("polaris.sidebar.collapsed", "false") vi.spyOn(Storage.prototype, "setItem").mockImplementation(() => { throw new Error("storage unavailable") }) render(
首页内容
, ) fireEvent.click(screen.getByRole("button", { name: "折叠侧边栏" })) expect(screen.getByTestId("app-shell")).toHaveAttribute( "data-sidebar-collapsed", "true", ) }) it("忽略 sessionStorage 的同名 storage 事件", () => { window.localStorage.setItem("polaris.sidebar.collapsed", "false") vi.spyOn(Storage.prototype, "setItem").mockImplementation(() => { throw new Error("storage unavailable") }) render(
首页内容
, ) fireEvent.click(screen.getByRole("button", { name: "折叠侧边栏" })) fireEvent( window, new StorageEvent("storage", { key: "polaris.sidebar.collapsed", storageArea: window.sessionStorage, }), ) expect(screen.getByTestId("app-shell")).toHaveAttribute( "data-sidebar-collapsed", "true", ) }) it("存储不可用时仍保留当前会话内交互", () => { vi.spyOn(Storage.prototype, "getItem").mockImplementation(() => { throw new Error("storage unavailable") }) vi.spyOn(Storage.prototype, "setItem").mockImplementation(() => { throw new Error("storage unavailable") }) render(
首页内容
, ) fireEvent.click(screen.getByRole("button", { name: "折叠侧边栏" })) expect(screen.getByTestId("app-shell")).toHaveAttribute( "data-sidebar-collapsed", "true", ) }) it("首页默认选中并启用分类链接", () => { render(
首页内容
, ) expect(screen.getByRole("link", { name: "首页" })).toHaveAttribute( "aria-current", "page", ) expect(screen.getByRole("link", { name: "开发工具" })).toHaveAttribute( "href", "/categories/dev", ) }) it("分类页只选中当前分类", () => { render(
分类内容
, ) expect(screen.getByRole("link", { name: "首页" })).not.toHaveAttribute( "aria-current", ) expect(screen.getByRole("link", { name: "开发工具" })).toHaveAttribute( "aria-current", "page", ) }) it("折叠状态仍保留分类链接的可访问名称", () => { render(
分类内容
, ) expect(screen.getByRole("link", { name: "开发工具" })).toHaveAttribute( "aria-current", "page", ) }) })