mirror of
https://github.com/multica-ai/multica.git
synced 2026-08-03 03:03:56 +02:00
test(views): fix app-sidebar useWorkspacePaths mock for the new chat nav (MUL-4171)
The AppSidebar personal nav gained a `chat` item, so it calls `useWorkspacePaths().chat()` at render. The app-sidebar.test.tsx mock hadn't been updated, so `p.chat` was undefined and every render threw `TypeError: p[item.key] is not a function`, failing @multica/views#test in CI. - Add `chat: () => "/acme/chat"` to the mocked useWorkspacePaths. - Route the chat-sessions query key through a mutable `chatSessions` fixture. - Add coverage for the Chat nav: renders the link, badges the summed unread_count, and hides the badge when all sessions are read — so this drift is caught next time. Co-authored-by: multica-agent <github@multica.ai>
This commit is contained in:
@@ -3,7 +3,8 @@ import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { ApiError } from "@multica/core/api";
|
||||
import { AppSidebar } from "./app-sidebar";
|
||||
|
||||
const { detail, deletePin, navigation, pins, summary, workspaces } = vi.hoisted(() => ({
|
||||
const { chatSessions, detail, deletePin, navigation, pins, summary, workspaces } = vi.hoisted(() => ({
|
||||
chatSessions: { current: [] as { unread_count?: number }[] },
|
||||
detail: { current: { isPending: false, isError: false, data: null as unknown, error: null as unknown } },
|
||||
deletePin: vi.fn(),
|
||||
navigation: { current: { pathname: "/acme/issues" } },
|
||||
@@ -102,6 +103,7 @@ vi.mock("@multica/core/paths", () => ({
|
||||
useCurrentWorkspace: () => ({ id: "ws-1", name: "Acme", slug: "acme" }),
|
||||
useWorkspacePaths: () => ({
|
||||
inbox: () => "/acme/inbox",
|
||||
chat: () => "/acme/chat",
|
||||
myIssues: () => "/acme/my-issues",
|
||||
issues: () => "/acme/issues",
|
||||
projects: () => "/acme/projects",
|
||||
@@ -161,6 +163,7 @@ vi.mock("@tanstack/react-query", async (importOriginal) => ({
|
||||
if (queryKey[0] === "issue") return detail.current;
|
||||
if (queryKey[0] === "inbox" && queryKey[1] === "unread-summary") return { data: summary.current };
|
||||
if (queryKey[0] === "workspaces") return { data: workspaces.current };
|
||||
if (queryKey[0] === "chat" && queryKey[2] === "sessions") return { data: chatSessions.current };
|
||||
return { data: [] };
|
||||
},
|
||||
useQueryClient: () => ({ fetchQuery: vi.fn(), invalidateQueries: vi.fn() }),
|
||||
@@ -279,3 +282,32 @@ describe("workspace-switcher dropdown per-workspace dot", () => {
|
||||
expect(rowDots(container)).toHaveLength(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe("personal nav — Chat", () => {
|
||||
beforeEach(() => {
|
||||
chatSessions.current = [];
|
||||
navigation.current = { pathname: "/acme/issues" };
|
||||
});
|
||||
|
||||
// The mocked SidebarMenuButton exposes the AppLink target as `data-href`
|
||||
// and renders the label + badge as its children.
|
||||
const chatNav = (container: HTMLElement) =>
|
||||
container.querySelector<HTMLElement>('button[data-href="/acme/chat"]');
|
||||
|
||||
it("renders a Chat nav link to the workspace chat route", () => {
|
||||
const { container } = render(<AppSidebar />);
|
||||
expect(chatNav(container)).not.toBeNull();
|
||||
});
|
||||
|
||||
it("badges the Chat nav with the summed unread_count of chat sessions", () => {
|
||||
chatSessions.current = [{ unread_count: 3 }, { unread_count: 2 }, { unread_count: 0 }];
|
||||
const { container } = render(<AppSidebar />);
|
||||
expect(chatNav(container)?.textContent).toContain("5");
|
||||
});
|
||||
|
||||
it("shows no Chat unread badge when every session is read", () => {
|
||||
chatSessions.current = [{ unread_count: 0 }, {}];
|
||||
const { container } = render(<AppSidebar />);
|
||||
expect(chatNav(container)?.textContent ?? "").not.toMatch(/\d/);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user