Fork me on GitHub

Right, I just have heard about how hooks could be used in the clojurescdipt space but it seems like a small abstraction that isn't as necessary since atoms seem natural to clojure

Lone Ranger01:08:26

ah, yes. Well we have some very fancy atoms that do very fancy things! for instance, reagent.core/atom is a very special atom, because when the value of that atom changes, it causes the react component to rerender. This is more than a normal clojure atom does!

Robert Brotherus08:08:57

I defined my re-frame app version in the leiningen project.clj file: (defproject posti-kioski-gui "1.6.3" ... ). In my GUI (in a view-function) I would like to show to the users this version. How can I get this version number to propagate all the way to GUI?


Not sure if this is the best way, but what we did was add (def props {:version "0.9.9-SNAPSHOT"}) above the defproject, and use closure-defines in the cljsbuild profile:

:closure-defines  {yourproject.core/version ~(:version props)}

Robert Brotherus10:08:48

Thank you for your reply @UCW9TUDNK! I am attempting this approach now with

:closure-defines {posti-kioski-gui.settings/version "1.0"}
How should I refer to this value in the re-frame component? Simply referring to the symbol does not seem to work (undeclared Var warning):
(defn- version []  [:span "(v. " posti-kioski-gui.settings/version ])


A long shot, but try without the slash maybe? As in, posti-kioski-gui.version, or something like that.


Or maybe you need to require the posti-kioski-gui.settings namespace.


hmm, no, that looks fine.


@UM54X8VTM I think I forgot to mention that the :closure-defines key needs to be inside :compiler, so it's full path inside project.clj would be :cljsbuild :builds :min :compiler :closure-defines. you also have to have it present in any other cljsbuild profiles (like :dev) where you also want the version string.


is $(document).ready(function(){}) run once ?


is there a good way to move this js to clojurescript ?


jQuery’s $(document).ready(function () {}); is short-hand for the built-in content-loaded handler:

document.addEventListener("DOMContentLoaded", function(event) { 
  //do work


Fairly trivial to port to CLJS.


I use a pretty vanilla cljs setup for a library, with cljsbuild. No web stuff, it's CLI/Node oriented. Now, whenever my tests fail, no stacktrace is printed:

Compiling ClojureScript...
Compiling ["target/out/tests.js"] from ["modules" "libs" "main" "test"]...
Successfully compiled ["target/out/tests.js"] in 5.807 seconds.

Testing some-ns

ERROR in (with-system-tests) (Error:NaN:NaN)
Uncaught exception, not in assertion.
expected: nil
  actual: #object[Error Error: No protocol method IAssociative.-assoc defined for type xxxxx: [object Object]]

Ran 3 tests containing 3 assertions.
0 failures, 1 errors.
What should I setup for it to happen?


(using clojure.test)


I do not know, but can confirm that I see the same behavior when using deps.edn and ClojureScript and clojure.test

👍 4

So, at least it is not specific to cljsbuild


From looking at clojure.test implementation from Clojure/Java and ClojureScript, I believe it is a difference in cljs's clojure.test implementation. It simply does not print the stack trace in this case, whereas Clojure/Java clojure.test does.


Perhaps without any changes to cljs code, it might be possible to change this behavior by redefining a defmethod that cljs clojure.test uses to report errors when exceptions are thrown. Will try it out and let you know.


Fantastic, cheers 🍻


There is probably an easier way, but if you put these in your cljs test namespace, before the first deftest:

;; fn handle-error is copied from file
;; src/test/self/self_parity/test.cljs in ClojureScript source code.

(defn handle-error
  [error sms]
  (loop [error error]
    (let [message (if (instance? ExceptionInfo error)
                    (ex-message error)
                    (.-message error))
          parsed-stacktrace (st/parse-stacktrace {}
                              (.-stack error)
                              {:ua-product :nodejs}
      (println message)
      (print (st/mapped-stacktrace-str parsed-stacktrace sms))
      (when-some [cause (.-cause error)]
        (print "caused by: ")
        (recur cause)))))

(defn pr-str-plus-stack-trace-if-error [x]
    (if (instance? js/Error x)
        (prn x)
        ;; second arg passed to handle-error in ClojureScript source
        ;; file src/test/self/self_parity/test.cljs is @st.  This is
        ;; some kind of source-map thing, but I do not know how to
        ;; pass a useful value for that parameter yet.
        (handle-error x {}))   
      (pr x))))


Then inside of the deftest expression, put this first, before any is statements: (set-env! (assoc (empty-env) :formatter pr-str-plus-stack-trace-if-error))


That doesn't give correct line numbers in cljs source code, because I do not yet know how to pass a correct source map argument to the handle-error function


If that works for you, those two functions could be put into a common "test helper functions" test namespace that is require'd from all of your other test namespaces.


Also I know how to avoid putting that set-env! into every deftest individually, by writing a bit of code that lets you execute a function at the beginning of every deftest


I forget to mention that you also need a require of [clojure.stacktrace :as st] for that code above to work.


That's a comprehensive answer 😄 thanks so much


It lgtm, very likely I'll incorporate it to projects


by writing a bit of code that lets you execute a function at the beginning of every deftest do you mean fixtures?


I have not used that technique, although it may work as well or better than what I have tried, which is to defmethod clojure.test/report multimethod for a particular kind of report event with keyword :begin-test-var. I can point you at some sample code if you want to try it.


I noticed that a down side of the method suggested above is that it seems to forget the pass/fail count tests between deftests, which is certainly not ideal.


There is probably a way to tweak that code so that no longer happens.


rather, it is not "forgetting", but starting over with a 0 count for each deftest


likely I can work it out armed with this info 🙂


thanks for everything! ...needless to say, it seems optimal that this was fixed upstream. Would appreciate if you created an issue -given you could observe the fault as well- probably mine would be worse-filled


I will certainly consider it, and maybe even propose a patch, although will hope to get some expert help improving the source map behavior there.


Created a ticket here, in case you want to follow along:




Has anyone expriences on cordova ?


yes, cordova is something I would avoid at all cost. At least when I was using it for TV-app development. Cordova tries to make cross-platform framework, at a terrible cost of badly clunked dependencies and horrible build tools.


if you want to do native platform function calls, just do (case (platform) :samsung ... :firetv ... etc...)