{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "test-results",
  "title": "Test Results",
  "description": "Pass/fail summary with failing assertions inline.",
  "dependencies": [
    "lucide-react"
  ],
  "registryDependencies": [
    "utils",
    "https://ui.cuelark.com/r/theme.json",
    "https://ui.cuelark.com/r/motion.json"
  ],
  "files": [
    {
      "path": "src/registry/cuelark/ui/test-results.tsx",
      "content": "\"use client\";\n\nimport * as React from \"react\";\nimport { CheckIcon, ChevronRightIcon, MinusIcon, XIcon } from \"lucide-react\";\n\nimport { gsap, motionScale } from \"@/lib/motion\";\nimport { cn } from \"@/lib/utils\";\n\ntype TestCase = { name: string; status: \"pass\" | \"fail\" | \"skip\"; duration?: number; error?: string };\ntype TestSuite = { name: string; tests: TestCase[] };\n\n/**\n * Test results an agent ran: a pass/fail/skip summary bar, suites that open on failures, and the failing assertion\n * shown right under its test.\n */\nfunction TestResults({ suites, className, ...props }: React.ComponentProps<\"div\"> & { suites: TestSuite[] }) {\n  const all = suites.flatMap((s) => s.tests);\n  const count = (st: TestCase[\"status\"]) => all.filter((t) => t.status === st).length;\n  const [open, setOpen] = React.useState(() => new Set(suites.filter((s) => s.tests.some((t) => t.status === \"fail\")).map((s) => s.name)));\n  const bar = React.useRef<HTMLDivElement>(null);\n  React.useLayoutEffect(() => {\n    if (bar.current && motionScale(bar.current)) gsap.fromTo(bar.current.children, { scaleX: 0, transformOrigin: \"left center\" }, { scaleX: 1, stagger: 0.12, duration: 0.6, ease: \"cue\", clearProps: \"transform\" });\n  }, []);\n  const pass = count(\"pass\");\n  const fail = count(\"fail\");\n  const skip = count(\"skip\");\n\n  return (\n    <div data-slot=\"test-results\" className={cn(\"overflow-hidden rounded-xl border border-border bg-card text-sm\", className)} {...props}>\n      <div className=\"grid gap-2 border-b border-border p-3\">\n        <div className=\"flex items-center gap-3 text-xs\">\n          <span className=\"font-medium\">{fail ? `${fail} failing` : \"All passing\"}</span>\n          <span className=\"flex items-center gap-1 text-success\">\n            <CheckIcon className=\"size-3\" /> {pass}\n          </span>\n          {fail > 0 && (\n            <span className=\"flex items-center gap-1 text-destructive\">\n              <XIcon className=\"size-3\" /> {fail}\n            </span>\n          )}\n          {skip > 0 && (\n            <span className=\"flex items-center gap-1 text-muted-foreground\">\n              <MinusIcon className=\"size-3\" /> {skip}\n            </span>\n          )}\n          <span className=\"ms-auto font-mono text-muted-foreground\">{all.reduce((a, t) => a + (t.duration ?? 0), 0)}ms</span>\n        </div>\n        <div ref={bar} className=\"flex h-1.5 gap-0.5 overflow-hidden rounded-full\" aria-hidden=\"true\">\n          <span className=\"bg-success\" style={{ flex: pass }} />\n          <span className=\"bg-destructive\" style={{ flex: fail }} />\n          <span className=\"bg-muted\" style={{ flex: skip }} />\n        </div>\n      </div>\n      <ul>\n        {suites.map((s) => {\n          const isOpen = open.has(s.name);\n          const failed = s.tests.some((t) => t.status === \"fail\");\n          return (\n            <li key={s.name} className=\"border-b border-border last:border-b-0\">\n              <button\n                type=\"button\"\n                aria-expanded={isOpen}\n                onClick={() => setOpen((o) => (o.has(s.name) ? (o.delete(s.name), new Set(o)) : new Set(o).add(s.name)))}\n                className=\"flex w-full items-center gap-2 px-3 py-2 text-left font-mono text-xs outline-none hover:bg-muted/50 focus-visible:ring-3 focus-visible:ring-ring/50 focus-visible:ring-inset\"\n              >\n                <ChevronRightIcon className={cn(\"size-3.5 text-muted-foreground transition-transform duration-200 ease-cue\", isOpen && \"rotate-90\")} />\n                <span className={cn(\"size-1.5 rounded-full\", failed ? \"bg-destructive\" : \"bg-success\")} />\n                {s.name}\n                <span className=\"ms-auto text-muted-foreground\">{s.tests.length}</span>\n              </button>\n              {isOpen && (\n                <ul className=\"pb-1.5\">\n                  {s.tests.map((t) => (\n                    <li key={t.name} className=\"grid gap-1 py-1 ps-9 pe-3 text-xs\">\n                      <span className=\"flex items-center gap-2\">\n                        {t.status === \"pass\" ? <CheckIcon className=\"size-3 text-success\" /> : t.status === \"fail\" ? <XIcon className=\"size-3 text-destructive\" /> : <MinusIcon className=\"size-3 text-muted-foreground\" />}\n                        <span className={cn(t.status === \"skip\" && \"text-muted-foreground\")}>{t.name}</span>\n                        {t.duration != null && <span className=\"ms-auto font-mono text-muted-foreground\">{t.duration}ms</span>}\n                      </span>\n                      {t.error && <pre className=\"ms-5 overflow-x-auto rounded-md bg-destructive/5 px-2 py-1.5 font-mono text-[0.6875rem] whitespace-pre-wrap text-destructive ring-1 ring-destructive/20\">{t.error}</pre>}\n                    </li>\n                  ))}\n                </ul>\n              )}\n            </li>\n          );\n        })}\n      </ul>\n    </div>\n  );\n}\n\nexport { TestResults };\nexport type { TestCase, TestSuite };\n",
      "type": "registry:ui"
    }
  ],
  "docs": "Docs and examples: https://ui.cuelark.com/components/test-results",
  "categories": [
    "agents"
  ],
  "type": "registry:ui"
}