Files
kandev/apps/web/components/kanban/kanban-header-mobile.test.tsx
T
José Almeida 9c16d337a2 feat(web): add global app status surface (#1869)
* feat(web): add app status bar

* feat(web): add app status bar visibility toggle

* feat(web): persist status bar item order

* fix(web): refine app status bar behavior

* fix(web): polish app status bar presentation

* test(web): split plugin slot coverage groups

* fix(web): address status surface review feedback

* fix(web): stabilize status bar overlay tests
2026-07-23 12:28:54 +01:00

101 lines
3.0 KiB
TypeScript

import { cleanup, fireEvent, render, screen } from "@testing-library/react";
import type { ReactNode } from "react";
import { afterEach, describe, expect, it, vi } from "vitest";
import { StateProvider } from "@/components/state-provider";
import { KanbanHeaderMobile } from "./kanban-header-mobile";
vi.mock("@/components/page-topbar", () => ({
PageTopbar: ({
backLabel,
leading,
leftActions,
actions,
}: {
backLabel?: string;
leading?: ReactNode;
leftActions?: ReactNode;
actions?: ReactNode;
}) => (
<header>
{leading}
<span>{backLabel}</span>
<div data-testid="topbar-left-actions">{leftActions}</div>
<div>{actions}</div>
</header>
),
}));
vi.mock("./mobile-menu-sheet", () => ({
MobileMenuSheet: () => null,
}));
const quickChatMocks = vi.hoisted(() => ({ openQuickChat: vi.fn() }));
vi.mock("@/hooks/use-quick-chat-launcher", () => ({
useQuickChatLauncher: () => quickChatMocks.openQuickChat,
}));
const LEFT_ACTIONS_TEST_ID = "topbar-left-actions";
const QUICK_CHAT_TEST_ID = "mobile-quick-chat-button";
afterEach(() => {
cleanup();
quickChatMocks.openQuickChat.mockClear();
});
function renderHeader(title: string, workspaceId?: string, onSearchChange?: () => void) {
return render(
<StateProvider>
<KanbanHeaderMobile
title={title}
workspaceId={workspaceId}
onSearchChange={onSearchChange}
workspaceLabel="/root/kandev"
showHealthIndicator={false}
onOpenHealthDialog={() => undefined}
/>
</StateProvider>,
);
}
describe("KanbanHeaderMobile", () => {
it("links the Kandev brand home and omits the redundant Home title", () => {
renderHeader("Home", "workspace-1");
expect(screen.getByRole("link", { name: "Kandev home" }).getAttribute("href")).toBe(
"/?workspaceId=workspace-1",
);
expect(screen.getByTestId(LEFT_ACTIONS_TEST_ID).textContent).toBe("");
});
it("renders page title and workspace label for non-Home pages", () => {
renderHeader("Tasks");
const leftActions = screen.getByTestId(LEFT_ACTIONS_TEST_ID);
expect(leftActions.textContent).toContain("Tasks");
expect(leftActions.textContent).toContain("/root/kandev");
expect(leftActions.firstElementChild?.className).toContain("max-w-[38vw]");
});
it("opens quick chat from the header action when a workspace is active", () => {
renderHeader("Home", "workspace-1");
fireEvent.click(screen.getByTestId(QUICK_CHAT_TEST_ID));
expect(quickChatMocks.openQuickChat).toHaveBeenCalledTimes(1);
});
it("hides the quick chat action without an active workspace", () => {
renderHeader("Home");
expect(screen.queryByTestId(QUICK_CHAT_TEST_ID)).toBeNull();
});
it("places quick chat immediately before search", () => {
renderHeader("Home", "workspace-1", vi.fn());
const quickChat = screen.getByTestId(QUICK_CHAT_TEST_ID);
const search = screen.getByTestId("mobile-search-toggle");
expect(quickChat.nextElementSibling).toBe(search);
});
});