fix(ssr): stop parse-sort leaking a render fn into wizard snapshots
Sorting a grid before opening a bulk wizard 500'd the submit with "No reader function for tag object". parse-sort returned the grid's whole :matching-header map, which carries a :render fn. That sort rides along in :query-params, which the bulk wizards copy verbatim into their form snapshot (bulk_code.clj:88, invoices.clj:1437). The snapshot is serialized with pr-str into a hidden field and read back with clojure.edn/read-string on submit; a fn pr-strs as #object[...], which edn has no reader for, so wrap-decode-multi-form-state threw before the handler ran. :matching-header was only ever read inside parse-sort itself - nothing downstream consumes it, and apply-toggle-sort in this same namespace already builds entries without it. Keep it as a local binding to derive :name and to drop unknown columns, and leave it out of the result. Fixes transaction bulk-code (11 production 500s over 2026-08-10/11) and the same latent bug in invoice bulk-edit. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
40
test/clj/auto_ap/query_params_test.clj
Normal file
40
test/clj/auto_ap/query_params_test.clj
Normal file
@@ -0,0 +1,40 @@
|
||||
(ns auto-ap.query-params-test
|
||||
(:require
|
||||
[auto-ap.query-params :as sut]
|
||||
[auto-ap.ssr.invoices :as invoices]
|
||||
[auto-ap.ssr.transaction.common :as transaction]
|
||||
[clojure.edn :as edn]
|
||||
[clojure.test :refer [deftest is testing]]))
|
||||
|
||||
(defn- sortable-keys [grid]
|
||||
(->> (:headers grid) (keep :sort-key)))
|
||||
|
||||
(deftest parse-sort-round-trips-through-edn
|
||||
;; The bulk wizards copy :query-params into their form snapshot, serialize it with
|
||||
;; pr-str into a hidden field, and read it back with clojure.edn/read-string on
|
||||
;; submit. Anything parse-sort puts in :query-params has to survive that trip --
|
||||
;; a bare fn or other unprintable object pr-strs as #object[...], which edn cannot
|
||||
;; read, and the submit 500s before the handler ever runs.
|
||||
(doseq [[label grid] [["transactions" transaction/grid-page]
|
||||
["invoices" invoices/grid-page]]
|
||||
sort-key (sortable-keys grid)
|
||||
direction ["asc" "desc"]]
|
||||
(testing (str label " sorted by " sort-key ":" direction)
|
||||
(let [parsed (sut/parse-sort grid (str sort-key ":" direction))]
|
||||
(is (seq parsed) "should produce a sort entry")
|
||||
(is (= parsed (edn/read-string (pr-str parsed)))
|
||||
"parsed sort must survive a pr-str / edn round trip")))))
|
||||
|
||||
(deftest parse-sort-behaviour
|
||||
(testing "Unknown columns are dropped"
|
||||
(is (= [] (sut/parse-sort transaction/grid-page "not-a-column:asc"))))
|
||||
(testing "An empty sort query yields no sort"
|
||||
(is (= [] (sut/parse-sort transaction/grid-page ""))))
|
||||
(testing "Multiple sort keys are preserved in order"
|
||||
(is (= ["client" "vendor"]
|
||||
(mapv :sort-key (sut/parse-sort transaction/grid-page "client:asc,vendor:desc")))))
|
||||
(testing "Direction is parsed per key"
|
||||
(is (= [true false]
|
||||
(mapv :asc (sut/parse-sort transaction/grid-page "client:asc,vendor:desc")))))
|
||||
(testing "The display name is carried over from the matching header"
|
||||
(is (= "Date" (:name (first (sut/parse-sort transaction/grid-page "date:asc")))))))
|
||||
Reference in New Issue
Block a user