From 5b2298e56fa3b9ce3e97751de992d6f473e09a78 Mon Sep 17 00:00:00 2001 From: Molecule AI App-FE Date: Mon, 11 May 2026 21:23:03 +0000 Subject: [PATCH] test(canvas/ui): add StatusBadge coverage (11 cases) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Covers StatusBadge โ€” secret key connection status indicator: - โœ“ / โœ— / โ—‹ icon per status - aria-label per status - className per status (--valid, --invalid, --unverified) - role="status" set correctly - Exactly one status element rendered ๐Ÿค– Generated with [Claude Code](https://claude.com/claude-code) --- .../ui/__tests__/StatusBadge.test.tsx | 88 +++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 canvas/src/components/ui/__tests__/StatusBadge.test.tsx diff --git a/canvas/src/components/ui/__tests__/StatusBadge.test.tsx b/canvas/src/components/ui/__tests__/StatusBadge.test.tsx new file mode 100644 index 00000000..3e1469e4 --- /dev/null +++ b/canvas/src/components/ui/__tests__/StatusBadge.test.tsx @@ -0,0 +1,88 @@ +// @vitest-environment jsdom +/** + * StatusBadge โ€” secret key connection status indicator. + * + * Per spec ยง4: always icon + color (never colour-only) for colour-blind users. + * Covers: verified / invalid / unverified render branches, icon, aria-label, className. + */ +import { afterEach, describe, expect, it } from "vitest"; +import { render } from "@testing-library/react"; +import React from "react"; + +import { StatusBadge } from "../StatusBadge"; + +afterEach(() => { + // Prevent DOM accumulation across tests (maxWorkers=1 means all test + // files share the same jsdom worker). + const { cleanup } = require("@testing-library/react"); + cleanup(); +}); + +function getBadge(status: "verified" | "invalid" | "unverified") { + const { container } = render(); + return container.querySelector("[role=status]") as HTMLElement; +} + +describe("StatusBadge โ€” icon", () => { + it("renders โœ“ for verified", () => { + expect(getBadge("verified").textContent).toBe("โœ“"); + }); + + it("renders โœ— for invalid", () => { + expect(getBadge("invalid").textContent).toBe("โœ—"); + }); + + it("renders โ—‹ for unverified", () => { + expect(getBadge("unverified").textContent).toBe("โ—‹"); + }); +}); + +describe("StatusBadge โ€” aria-label", () => { + it("sets 'Connection status: verified' for verified", () => { + expect(getBadge("verified").getAttribute("aria-label")).toBe( + "Connection status: verified", + ); + }); + + it("sets 'Connection status: invalid' for invalid", () => { + expect(getBadge("invalid").getAttribute("aria-label")).toBe( + "Connection status: invalid", + ); + }); + + it("sets 'Connection status: unverified' for unverified", () => { + expect(getBadge("unverified").getAttribute("aria-label")).toBe( + "Connection status: unverified", + ); + }); +}); + +describe("StatusBadge โ€” className", () => { + it("applies status-badge--valid for verified", () => { + expect(getBadge("verified").className).toContain("status-badge--valid"); + }); + + it("applies status-badge--invalid for invalid", () => { + expect(getBadge("invalid").className).toContain("status-badge--invalid"); + }); + + it("applies status-badge--unverified for unverified", () => { + expect(getBadge("unverified").className).toContain( + "status-badge--unverified", + ); + }); +}); + +describe("StatusBadge โ€” role", () => { + it("sets role=status", () => { + const el = getBadge("verified"); + expect(el.getAttribute("role")).toBe("status"); + }); +}); + +describe("StatusBadge โ€” structural", () => { + it("renders exactly one status element", () => { + const { container } = render(); + expect(container.querySelectorAll("[role=status]").length).toBe(1); + }); +});