Open olivergeorge opened 8 years ago
CLJS is definitely in-scope. This seems like something that could go in com.gfredericks.schpec
, and we could change that to be a cljc file.
Could this be reasonably tested? I suppose by setting up testing via node the same as in test.chuck?
It could return some structured data to avoid the need to test side effects.
what does explain
normally do in cljs? (i.e., what's the problem we're trying to solve exactly?)
Context: I typically develop web applications using CLJS and re-frame / om.
The current behaviour is to throw ex-info with a message including (str args)
(throw
(ex-info
(str "Call to " (pr-str v) " did not conform to spec:\n" (with-out-str
(explain-out ed)))
ed))
A few problems arise:
On 28 July 2016 at 09:41, Gary Fredericks notifications@github.com wrote:
what does explain normally do in cljs? (i.e., what's the problem we're trying to solve exactly?)
— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/gfredericks/schpec/issues/2#issuecomment-235754678, or mute the thread https://github.com/notifications/unsubscribe-auth/AAGEd_ax5JAx-_gfgslU4OLBIxKAo6z_ks5qZ-yrgaJpZM4JRaWZ .
cljs-devtools lets you specify custom formatters by extending a protocol (IFormat
):
But it looks like spec can only explain
in the form of a string or a map.
We could have a function that returns a record that satisfies the IFormat
protocol, which cljs-devtools can then use to print in its very pretty way (using Custom Object Formatters).
It would look a little something like this:
(ns user
(:require
[devtools.core :as devtools]
[devtools.protocols :as devtools-protocols]
[devtools.formatters.templating :as template]
[devtools.formatters.markup :as m]
[cljs.spec :as s]))
(defrecord explain-data-record [problems]
devtools-protocols/IFormat
(-header [_]
(let [paths (keys problems)]
(template/render-markup
[["span"] "Spec problems at " (clojure.string/join " and " paths)])))
(-has-body [_] true)
(-body [_]
(template/render-markup
(m/<list>
(for [problem (vals problems)]
(let [{:keys [pred val reason via in] :as prob} problem]
(m/<string> "Insert something here")))
(count problems)))))
(s/def ::email
(s/and string?
#(clojure.string/includes? % "@")))
(set! (.-onload js/window)
(fn []
(enable-console-print!)
(devtools/install! [:formatters :hints])
(let [problems (::s/problems (s/explain-data (s/keys :req [::email ::password])
{::email 123}))]
(.log js/console (->explain-data-record problems)))))
Now what we need is to come up with a pretty representation using either raw JsonML or devtools' own markup language…
I think devtools-specific stuff should go in a special namespace, something like com.gfredericks.schpec.cljs-devtools
, so people who don't depend on it can just avoid requiring that namespace.
@atroche are you saying that the original code posted here is not sufficient to get the pretty output in chrome?
After looking at it I had guessed that it was piggybacking on devtools' printing of generic clojure data structures, which would let us avoid a bunch of custom formatting code I would imagine.
I opened a related cljs-devtools issue: https://github.com/binaryage/cljs-devtools/issues/23
@darwin is looking at a cljs patch to make ExceptionInfo more "normal" so that it's amenable to formatting.
I've updated my util/patch to suit the latest cljs release (instrument things changed/moved). Here's a gist in case it's of interest.
https://gist.github.com/olivergeorge/d73fa855b40f6c8592a37dc8833bf8a7
Hi
Not sure if it's your intend for this to cover both CLJ and CLJS but one early pain point for CLJS is the printing of large datastructures as part of explain-out.
Using Google Chrome and cljs-devtools gives us custom formatters on the console which means we can drill down into maps/vectors, see pretty printed keywords etc. Big step forward!
This is a totally hacky port which vaguely does as described: