Kaocha-cljs not seeing test cases

Hi,
I’m having trouble getting kaocha-cljs working. My tests.edn is as follows:

#kaocha/v1
{:tests [{:id :unit
          :source-paths ["src/main/clj"]
          :test-paths ["src/test/clj"]}
         {:id :unit-cljs
          :type :kaocha.type/cljs
          :cljs/repl-env cljs.repl.browser/repl-env
          :source-paths ["src/main/clj"]
          :test-paths ["src/test/clj"]}]}

I have only a single file in my source tree, src/test/clj/my_ns/core_test.cljc:

(ns my-ns.core-test
  (:require
    [clojure.test :refer [deftest is]]))

(deftest basic-test
  (is (= 1 1)))

I’m using Leiningen configured as per the docs. Running lein kaocha unit works fine. I get a single test run successfully. But running lein kaocha unit-cljs produces an exception:

No such namespace: my-ns.core-test, could not locate my_ns/core_test.cljs, my_ns/core_test.cljc, or...

Any thoughts on what might be going wrong?

Kaocha is not able to dynamically add directories to the classpath in such a way that ClojureScript “sees” them, so I’m your project.clj you’ll have to add src/test/clj to :test-paths or :source-paths.

Ah, I see, thanks. It does seem weird that CLJS needs source directories on the classpath, especially when CLJ doesn’t. I guess I still have more to learn about how the CLJS compiler works.

On to my second question. My :unit-cljs test now works, but if I add :focus [my-ns.core-test] to the :unit-cljs clause Kaocha does not run the test. The :unit test works fine with or without the same :focus setting. Any thoughts on this one?

ClojureScript test ids are prefixed to distinguish them from CLJ test ids. Try this

bin/kaocha --plugin kaocha.plugin.alpha/info --print-test-ids 

This will show you all the identifiers of the tests you have.

This is a shortcoming of kaocha-cljs. We add the directories you put in tests.edn to the classpath at runtime, but somehow ClojureScript doesn’t pick that up. I haven’t had a chance to look into that, I’m sure it’s fixable, but someone needs to investigate how exactly ClojureScript does its lookup. It might be looking at a different ClassLoader than the one we’re modifying.

Perfect. Changing it to :focus [cljs:my-ns/core-test] does the trick.

One last question, though not directly to do with Kaocha. Running my CLJS unit tests with a Node back-end fails when it runs across something that touches a browser API, e.g. the DOM or xmlhttprequest. I think I can fix that by installing global-jsdom with npm and running something like (js/require "global-jsdom") before my tests. Would a pre-load hook be the best place to run that code?

No, that won’t work as the JS environment won’t be spun up yet by that time.

You could try doing it with a pre-test. This will run before every suite/ns/test. As soon as you have a :kaocha.type.cljs/eval key in your testable you can try using that to eval clojurescript

Something like this (completely untested)

(defn pre-test-hook [testable test-plan]
  (when-let [eval (:kaocha.type.cljs/eval] ;; maybe add some global state to do this only the first time
    (eval '(js/require "global-jsdom"))
  testable)

That said if your tests heavily rely on the DOM you probably should run them against a (headless) browser rather than Node.

Yeah, I suppose you’re right. A headless browser would be better. As far as I could see, Kaocha just uses CLJS to start the REPL, which in turn just uses the default configured browser for the system. Is there a way to configure this?

Not really… this uses clojure.java.browse under the hood, which uses xdg-open (or on mac: /usr/bin/open), which then uses your system default.

Seems like there’s a dynamic binding you can set (*open-url-script*), but it expects an atom, which you can’t readily do with Kaocha’s :bindings because it doesn’t eval its values.

You can try binding it inside a wrap-run hook though, that should work.

Something like this (again, untested)

(defn wrap-run-hook [run test-plan]
  (fn [& args]
    (binding [clojure.java.browse/*open-url-script* (atom "/path/to/your/browser")]
      (apply run args))))

See https://github.com/clojure/clojure/blob/ef00c7cffad10e6104d333f7f71a29163b06cd0a/src/clj/clojure/java/browse.clj#L66

OK, I’ll give that a try. Thanks for your help and thanks for building Kaocha!