// @vitest-environment happy-dom import React, { act } from "react"; import { createRoot, type Root } from "react-dom/client"; import { afterEach, beforeEach, describe, expect, it } from "vitest"; import { MentionItemMedia } from "./MentionItemMedia.js"; import { ComposerRuntimeAdaptersProvider } from "./runtime-adapters.js"; import type { MentionItemMedia as MentionItemMediaValue } from "./types.js"; let container: HTMLDivElement; let root: Root; beforeEach(() => { container = document.createElement("div"); document.body.appendChild(container); root = createRoot(container); }); afterEach(() => { act(() => root.unmount()); container.remove(); }); describe("MentionItemMedia", () => { it("keeps the legacy icon when no media is configured", () => { act(() => root.render()); expect(container.querySelector("svg")).not.toBeNull(); }); it("renders provider-defined text and background", () => { act(() => root.render( , ), ); expect(container.textContent).toBe("🏠"); expect(container.querySelector("svg")).toBeNull(); const frame = container.querySelector("span"); expect(frame?.className).toContain("size-5"); expect(frame?.firstElementChild?.className).toContain("size-3"); expect(frame?.firstElementChild?.className).toContain("text-[9px]"); expect(frame?.style.backgroundColor).toBe("rgb(15, 118, 110)"); }); it("allows providers to omit leading media explicitly", () => { act(() => root.render(), ); expect(container.innerHTML).toBe(""); }); it("falls back to the legacy icon for empty text media", () => { act(() => root.render( , ), ); expect(container.querySelector("svg")).not.toBeNull(); }); it("renders a contained image without leaking a referrer", () => { act(() => root.render( , ), ); const image = container.querySelector("img"); expect(image?.getAttribute("src")).toBe("/agent.png"); expect(image?.getAttribute("referrerpolicy")).toBe("no-referrer"); expect(image?.className).toContain("size-3"); expect(image?.className).toContain("object-contain"); expect(container.querySelector("svg")).toBeNull(); }); it("resolves root-relative images against the app mount", () => { act(() => root.render( `/assets${path}` }} > , ), ); expect(container.querySelector("img")?.getAttribute("src")).toBe( "/assets/agent.png", ); }); it("leaves absolute image URLs unchanged", () => { act(() => root.render( `/assets${path}` }} > , ), ); expect(container.querySelector("img")?.getAttribute("src")).toBe( "https://example.com/agent.png", ); }); it.each([{ type: "text" }, { type: "image", src: null }])( "falls back safely for malformed media", (media) => { act(() => root.render( , ), ); expect(container.querySelector("svg")).not.toBeNull(); }, ); it("preserves the compact clipboard fallback for slot references", () => { act(() => root.render(), ); expect(container.querySelector("svg")?.getAttribute("class")).toContain( "size-3", ); }); });