diff --git a/src/components/insights/coach-panel/__tests__/chat-bubble-initials.test.tsx b/src/components/insights/coach-panel/__tests__/chat-bubble-initials.test.tsx new file mode 100644 index 000000000..badd7f82c --- /dev/null +++ b/src/components/insights/coach-panel/__tests__/chat-bubble-initials.test.tsx @@ -0,0 +1,52 @@ +import { describe, it, expect, vi } from "vitest"; +import { renderToStaticMarkup } from "react-dom/server"; + +import { I18nProvider } from "@/lib/i18n/context"; + +/** + * The person's bubble falls back to initials of the name the app shows, like + * the top bar, never the login: a managed record's login is a generated + * handle, and "MA" for `managed-…` is nobody's initials. + */ +const auth = vi.hoisted(() => ({ + user: { + id: "u1", + username: "managed-1f2e3d", + displayName: "Alex Example" as string | null, + role: "USER", + avatarUrl: null, + }, +})); + +vi.mock("@/hooks/use-auth", () => ({ + useAuth: () => ({ user: auth.user, isAuthenticated: true, isLoading: false }), +})); +vi.mock("@tanstack/react-query", () => ({ + useQuery: () => ({ data: undefined }), + useMutation: () => ({ mutate: vi.fn(), isPending: false, isError: false }), + useQueryClient: () => ({ invalidateQueries: vi.fn() }), +})); + +import { ChatBubble } from "../chat-bubble"; + +function userBubble(): string { + return renderToStaticMarkup( + + + , + ); +} + +describe("coach bubble initials", () => { + it("spells the display name, not the login", () => { + const html = userBubble(); + expect(html).toContain(">AE<"); + expect(html).not.toContain(">MA<"); + }); + + it("falls back to the login when there is no display name", () => { + auth.user.displayName = null; + auth.user.username = "sam"; + expect(userBubble()).toContain(">S<"); + }); +}); diff --git a/src/components/insights/coach-panel/__tests__/message-thread.test.tsx b/src/components/insights/coach-panel/__tests__/message-thread.test.tsx index f26660ff9..9c28c40b1 100644 --- a/src/components/insights/coach-panel/__tests__/message-thread.test.tsx +++ b/src/components/insights/coach-panel/__tests__/message-thread.test.tsx @@ -551,10 +551,11 @@ describe("", () => { }); it("falls back to initials when no avatar URL is present", () => { - // Default mock returns avatarUrl: null → initials path. + // Default mock returns avatarUrl: null → initials path, spelled like the + // top bar's: one word, one letter. const html = render(); expect(html).toContain('data-slot="coach-bubble-user-avatar"'); - expect(html).toMatch(/data-slot="coach-bubble-user-avatar"[^>]*>TE]*>T