Skip to content

Instantly share code, notes, and snippets.

@PEZ
Last active November 27, 2024 12:50
Show Gist options
  • Save PEZ/5f1101ee69ccedf042c3bea5116a8cd0 to your computer and use it in GitHub Desktop.
Save PEZ/5f1101ee69ccedf042c3bea5116a8cd0 to your computer and use it in GitHub Desktop.
Baldr, clojure.test and cljs/test with Mocha-inspired positive reporting
(ns pez.baldr
(:require #?(:cljs [cljs.test :as t]
:clj [clojure.test :as t])
[clojure.string :as string]))
(defn- default [text]
(str "\033[39m" text "\033[22m"))
(defn- gray [text]
(str "\033[90m" text "\033[39m"))
(defn- green [text]
(str "\033[1;32m" text "\033[22m"))
(defn- red [text]
(str "\033[31m" text "\033[39m"))
(def ^:private initial-state {:contexts nil
:failure-prints []})
(defonce ^:private !state (atom initial-state))
(defn- indent [level]
(apply str (repeat (* 2 level) " ")))
(defn- get-report [m contexts state {:keys [color bullet bullet-color]}]
(let [seen-contexts (:contexts state)
common-contexts (take-while true? (map = (reverse seen-contexts) (reverse contexts)))
common-prefix-length (count common-contexts)
new-contexts (reverse (take (- (count contexts) common-prefix-length) contexts))
message (or (:message m) (pr-str (:expected m)))]
{:new-state (assoc state :contexts contexts)
:printouts (cond-> []
(seq new-contexts) (into (map-indexed (fn [idx ctx]
(str (indent (+ common-prefix-length idx 2))
(default ctx)))
new-contexts))
:always (conj (str (indent (+ 2 (count contexts)))
(str (bullet-color bullet) " " (color message)))))}))
(defn report! [m config]
(let [contexts #?(:cljs (:testing-contexts (t/get-current-env))
:clj t/*testing-contexts*)
{:keys [new-state printouts]} (get-report m contexts @!state config)]
(reset! !state new-state)
(doseq [printout printouts]
(println printout))))
(defn- dispatch-value [type]
#?(:clj type
:cljs [::t/default type]))
(defmethod t/report (dispatch-value :begin-test-var) [_m]
(swap! !state merge (select-keys initial-state [:contexts])))
(def ^:private original-summary (get-method t/report (dispatch-value :summary)))
(defmethod t/report (dispatch-value :summary) [m]
(when (seq (:failure-prints @!state))
(println))
(doseq [[i failure-print] (map-indexed vector (:failure-prints @!state))]
(println (red (str (inc i) ") " (string/trim failure-print)))))
(reset! !state initial-state)
(original-summary m))
(def ^:private original-pass (get-method t/report (dispatch-value :pass)))
(defmethod t/report (dispatch-value :pass) [m]
(report! m {:color gray
:bullet ""
:bullet-color green})
(original-pass m))
(def ^:private original-fail (get-method t/report (dispatch-value :fail)))
(defmethod t/report (dispatch-value :fail) [m]
(let [failure-printout (with-out-str (original-fail m))]
(swap! !state update :failure-prints conj failure-printout))
(report! m {:color red
:bullet (str (count (:failure-prints @!state)) ")")
:bullet-color red}))
(def ^:private original-error (get-method t/report (dispatch-value :error)))
(defmethod t/report (dispatch-value :error) [m]
(let [error-printout (with-out-str (original-error m))]
(swap! !state update :failure-prints conj error-printout))
(report! m {:color red
:bullet (str (count (:failure-prints @!state)) ")")
:bullet-color red}))
(defmethod t/report (dispatch-value :begin-test-var) [m]
(println (str (indent 1) (default (:var m)))))
@PEZ
Copy link
Author

PEZ commented Nov 25, 2024

Update: Now I understand why I didn't succeed with making it .cljc at first. It wasn't totally obvious. But now Baldr works in both Clojure and ClojureScript. 🎉

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment