Test dashboard: full menu system, all-service tests, filtering
All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 1m11s

- Run tests for all 10 services via per-service pytest subprocesses
- Group results by service with section headers
- Clickable summary cards filter by outcome (passed/failed/errors/skipped)
- Service filter nav using ~nav-link buttons in menu bar
- Full menu integration: ~header-row + ~header-child + ~menu-row
- Show logo image via cart-mini rendering
- Mount full service directories in docker-compose for test access
- Add 24 unit test files across 9 services

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-28 22:54:25 +00:00
parent 81e51ae7bc
commit 3809affcab
41 changed files with 2484 additions and 110 deletions

View File

@@ -17,7 +17,20 @@
:disabled (if running "true" nil)
(if running "Running..." "Run Tests"))))
(defcomp ~test-summary (&key status passed failed errors skipped total duration last-run running csrf)
(defcomp ~test-filter-card (&key href label count colour-border colour-bg colour-text active)
(a :href href
:hx-get href
:hx-target "#main-panel"
:hx-select "#main-panel"
:hx-swap "outerHTML"
:hx-push-url "true"
:class (str "block rounded border p-3 text-center transition-colors no-underline hover:opacity-80 "
colour-border " " colour-bg " "
(if active "ring-2 ring-offset-1 ring-stone-500 " ""))
(div :class (str "text-3xl font-bold " colour-text) count)
(div :class (str "text-sm " colour-text) label)))
(defcomp ~test-summary (&key status passed failed errors skipped total duration last-run running csrf active-filter)
(div :class "space-y-4"
(div :class "flex items-center justify-between flex-wrap gap-3"
(div :class "flex items-center gap-3"
@@ -26,26 +39,38 @@
(~test-run-button :running running :csrf csrf))
(when status
(div :class "grid grid-cols-2 sm:grid-cols-3 md:grid-cols-6 gap-3"
(div :class "rounded border border-stone-200 bg-white p-3 text-center"
(div :class "text-3xl font-bold text-stone-800" total)
(div :class "text-sm text-stone-500" "Total"))
(div :class "rounded border border-emerald-200 bg-emerald-50 p-3 text-center"
(div :class "text-3xl font-bold text-emerald-700" passed)
(div :class "text-sm text-emerald-600" "Passed"))
(div :class "rounded border border-rose-200 bg-rose-50 p-3 text-center"
(div :class "text-3xl font-bold text-rose-700" failed)
(div :class "text-sm text-rose-600" "Failed"))
(div :class "rounded border border-orange-200 bg-orange-50 p-3 text-center"
(div :class "text-3xl font-bold text-orange-700" errors)
(div :class "text-sm text-orange-600" "Errors"))
(div :class "rounded border border-sky-200 bg-sky-50 p-3 text-center"
(div :class "text-3xl font-bold text-sky-700" skipped)
(div :class "text-sm text-sky-600" "Skipped"))
(div :class "rounded border border-stone-200 bg-white p-3 text-center"
(div :class "text-3xl font-bold text-stone-800" (str duration "s"))
(div :class "text-sm text-stone-500" "Duration")))
(~test-filter-card :href "/" :label "Total" :count total
:colour-border "border-stone-200" :colour-bg "bg-white"
:colour-text "text-stone-800"
:active (if (= active-filter nil) "true" nil))
(~test-filter-card :href "/?filter=passed" :label "Passed" :count passed
:colour-border "border-emerald-200" :colour-bg "bg-emerald-50"
:colour-text "text-emerald-700"
:active (if (= active-filter "passed") "true" nil))
(~test-filter-card :href "/?filter=failed" :label "Failed" :count failed
:colour-border "border-rose-200" :colour-bg "bg-rose-50"
:colour-text "text-rose-700"
:active (if (= active-filter "failed") "true" nil))
(~test-filter-card :href "/?filter=errors" :label "Errors" :count errors
:colour-border "border-orange-200" :colour-bg "bg-orange-50"
:colour-text "text-orange-700"
:active (if (= active-filter "errors") "true" nil))
(~test-filter-card :href "/?filter=skipped" :label "Skipped" :count skipped
:colour-border "border-sky-200" :colour-bg "bg-sky-50"
:colour-text "text-sky-700"
:active (if (= active-filter "skipped") "true" nil))
(~test-filter-card :href "/" :label "Duration" :count (str duration "s")
:colour-border "border-stone-200" :colour-bg "bg-white"
:colour-text "text-stone-800" :active nil))
(div :class "text-sm text-stone-400" (str "Last run: " last-run)))))
(defcomp ~test-service-header (&key service total passed failed)
(tr :class "border-b-2 border-stone-300 bg-stone-100"
(td :class "px-3 py-2 text-sm font-bold text-stone-700" :colspan "4"
(span service)
(span :class "ml-2 text-xs font-normal text-stone-500"
(str total " tests, " passed " passed, " failed " failed")))))
(defcomp ~test-row (&key nodeid outcome duration longrepr)
(tr :class (str "border-b border-stone-100 "
(if (= outcome "passed") "bg-white"
@@ -85,4 +110,4 @@
(div :class "flex items-center justify-center py-12 text-stone-400"
(div :class "text-center"
(div :class "text-4xl mb-2" "?")
(div :class "text-sm" "No test results yet. Click \"Run Tests\" to start."))))
(div :class "text-sm" "No test results yet. Click Run Tests to start."))))