import { render } from "@testing-library/react"; import { describe, expect, it } from "vitest"; import { HpoVisualizer } from "../HpoVisualizer"; import type { OrganId } from "../types"; describe("HpoVisualizer rendering order", () => { /** * Helper function to get rendered organ IDs in DOM order. * OrganSvg elements are now elements with aria-label attribute. * Only includes visible organs (opacity !== 0). */ const getRenderedOrganOrder = (container: HTMLElement): string[] => { // Find all OrganSvg elements (they are elements with aria-label) const organElements = container.querySelectorAll("g[aria-label]"); return Array.from(organElements) .filter((el) => { // Filter out hidden organs (opacity: 0) // OrganSvg sets opacity as an attribute, not a style property const opacity = el.getAttribute("opacity"); return opacity !== "0"; }) .map((el) => el.getAttribute("aria-label") || ""); }; it("should render organs in ORGAN_POSITIONS key order regardless of organs array order", () => { // Provide organs in reverse alphabetical order const organs: { id: OrganId }[] = [ { id: "voice" }, { id: "thoracicCavity" }, { id: "lung" }, { id: "heart" }, { id: "head" }, { id: "eye" }, { id: "ear" }, ]; const { container } = render(); const renderedOrder = getRenderedOrganOrder(container); // ORGAN_RENDER_ORDER starts with thoracicCavity -> lung -> ... -> head -> eye -> ear -> voice // Expected order should follow ORGAN_RENDER_ORDER for the given organs expect(renderedOrder).toEqual([ "thoracicCavity", "lung", "heart", "head", "eye", "ear", "voice", ]); }); it("should render selectedOrgan after other organs to appear on top", () => { const organs: { id: OrganId }[] = [ { id: "head" }, { id: "eye" }, { id: "ear" }, { id: "lung" }, { id: "heart" }, ]; // Select 'head' const { container } = render(); const renderedOrder = getRenderedOrganOrder(container); // 'head' should be rendered last since it's selected expect(renderedOrder.at(-1)).toBe("head"); }); it("should render selectedOrgan last even when it would normally be in the middle", () => { const organs: { id: OrganId }[] = [ { id: "head" }, { id: "lung" }, { id: "heart" }, { id: "digestive" }, { id: "kidney" }, ]; // Select 'heart' which is in the middle of ORGAN_POSITIONS order const { container } = render(); const renderedOrder = getRenderedOrganOrder(container); expect(renderedOrder.at(-1)).toBe("heart"); expect(renderedOrder.slice(0, -1)).toEqual(["lung", "digestive", "kidney", "head"]); }); it("should render selected organ last while preserving order for others", () => { const organs: { id: OrganId }[] = [{ id: "head" }, { id: "eye" }, { id: "ear" }]; const { container } = render(); const renderedOrder = getRenderedOrganOrder(container); expect(renderedOrder).toEqual(["head", "ear", "eye"]); }); it("should not render selectedOrgan if it is not in organs array", () => { const organs: { id: OrganId }[] = [{ id: "head" }, { id: "eye" }]; // Select 'heart' which is not in the organs array const { container } = render(); const renderedOrder = getRenderedOrganOrder(container); // 'heart' should not be rendered since it's not in the organs array expect(renderedOrder).toEqual(["head", "eye"]); expect(renderedOrder).not.toContain("heart"); }); it("should maintain correct order with visibleOrgans prop", () => { // Using visibleOrgans instead of organs const visibleOrgans: OrganId[] = ["kidney", "heart", "lung", "head"]; const { container } = render(); const renderedOrder = getRenderedOrganOrder(container); // Should follow ORGAN_RENDER_ORDER: lung, heart, kidney, head expect(renderedOrder).toEqual(["lung", "heart", "kidney", "head"]); }); it("should return deselected organ to normal order immediately", () => { const organs: { id: OrganId }[] = [{ id: "head" }, { id: "eye" }, { id: "ear" }]; const { container, rerender } = render(); expect(getRenderedOrganOrder(container)).toEqual(["head", "ear", "eye"]); rerender(); expect(getRenderedOrganOrder(container)).toEqual(["head", "eye", "ear"]); }); });