nexus/ui/src/components/frame/TopStrip.test.tsx
Nexus Dev c521ae4403 feat(nexus): add TopStrip composite for layout overhaul (phase 8)
48px sticky top strip per docs/specs/2026-04-11-nexus-layout-overhaul.md
§4.2. Composes ModeBreadcrumb (left) + CmdKButton and GlobalMicButton
(right) inside a <header aria-label="Top bar"> landmark.

Completes the frame component set for Phase 8. The next task (task 6)
rewrites Layout.tsx to mount IconRail + TopStrip as the new global
chrome and delete the old sidebar/ChatPanel/PropertiesPanel/
BreadcrumbBar combination.

Part of Phase 8 of the Nexus layout overhaul (task 5 of 7).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 11:17:09 +00:00

76 lines
2.2 KiB
TypeScript

// @vitest-environment jsdom
import { act } from "react";
import { createRoot } from "react-dom/client";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import { MemoryRouter } from "@/lib/router";
import { TopStrip } from "./TopStrip";
// eslint-disable-next-line @typescript-eslint/no-explicit-any
(globalThis as any).IS_REACT_ACT_ENVIRONMENT = true;
// Same stub as IconRail / ModeBreadcrumb tests — @/lib/router's Link
// (and useLocation consumers) trigger CompanyContext resolution.
vi.mock("@/context/CompanyContext", () => ({
useCompany: () => ({
companies: [],
selectedCompany: null,
selectedCompanyId: null,
setSelectedCompanyId: () => {},
selectionSource: null,
loading: false,
}),
}));
describe("TopStrip", () => {
let container: HTMLDivElement;
let root: ReturnType<typeof createRoot> | null = null;
beforeEach(() => {
container = document.createElement("div");
document.body.appendChild(container);
root = null;
});
afterEach(() => {
if (root) {
act(() => { root!.unmount(); });
root = null;
}
if (container.parentNode) container.remove();
});
function render(pathname: string) {
root = createRoot(container);
act(() => {
root!.render(
<MemoryRouter initialEntries={[pathname]}>
<TopStrip />
</MemoryRouter>
);
});
}
it("renders the ModeBreadcrumb with derived segments", () => {
render("/NEX/assistant");
const segment = container.querySelector("[data-testid='mode-breadcrumb-segment']");
expect(segment?.textContent?.trim()).toBe("ASSISTANT");
});
it("renders the CmdK button", () => {
render("/NEX/assistant");
expect(container.querySelector("button[aria-label='Open command palette']")).not.toBeNull();
});
it("renders the global mic button", () => {
render("/NEX/assistant");
expect(container.querySelector("button[aria-label='Voice']")).not.toBeNull();
});
it("is wrapped in a header element for landmark semantics", () => {
render("/NEX/assistant");
const header = container.querySelector("header");
expect(header).not.toBeNull();
expect(header?.getAttribute("aria-label")).toBe("Top bar");
});
});