refactor(ssr): full Selmer migration of Transaction Edit; remove the wizard

Squashed Phase-2 SSR work: migrate the Transaction Edit modal's render path
entirely to Selmer templates (zero Hiccup in the render path), rip out the
multi-step wizard abstraction (EditWizard/LinksStep records, MultiStepFormState,
step-params[...] field names, mm/* middleware) in favor of a plain form with
flat derived state, and promote shared UI components to reusable Selmer partials
under resources/templates/components/. Adds the Selmer interop bridge, the
auto-ap.ssr.components.selmer (sc) wrapper library, and the ssr-form-migration
skill capturing the learnings.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-24 08:23:34 -07:00
parent e2ccfc8d2c
commit 70c178de83
62 changed files with 3091 additions and 1006 deletions

View File

@@ -0,0 +1,36 @@
(ns auto-ap.ssr.selmer-test
(:require
[auto-ap.ssr.selmer :as sut]
[clojure.string :as str]
[clojure.test :refer [deftest is testing]]
[hiccup2.core :as h2]))
(deftest hiccup->html
(testing "renders a Hiccup form to an HTML string"
(is (= "<span class=\"label\">A &amp; B</span>"
(sut/hiccup->html [:span.label "A & B"])))))
(deftest selmer-embeds-hiccup
(testing "a Hiccup component renders inside a Selmer template via |safe"
(let [frag (sut/hiccup->html [:span.badge "from hiccup"])
out (sut/render-str "<div>{{frag|safe}}</div>" {:frag frag})]
(is (str/includes? out "<span class=\"badge\">from hiccup</span>"))
;; without |safe the markup would be escaped; |safe keeps it verbatim
(is (not (str/includes? out "&lt;span"))))))
(deftest selmer-fragment-inside-hiccup
(testing "a Selmer fragment renders inside a Hiccup tree without double-escaping"
(let [sel (sut/render-str "<a href=\"{{url}}\">{{label}}</a>" {:url "/x" :label "Go"})
out (str (h2/html {} [:div (sut/raw sel)]))]
(is (= "<div><a href=\"/x\">Go</a></div>" out)))))
(deftest render-file-from-classpath
(testing "render-file resolves a template under resources/templates and keeps plain-HTML Alpine/HTMX attrs"
(let [out (sut/render "templates/interop-smoke.html"
{:title "Interop OK"
:hiccup_frag (sut/hiccup->html [:span.badge "from hiccup"])})]
(is (str/includes? out "Interop OK"))
(is (str/includes? out "from hiccup"))
;; plain-HTML attributes (the whole point of Selmer) survive unambiguously
(is (str/includes? out "x-model=\"value.value\""))
(is (str/includes? out "tippy?.show()")))))