Circleci, Phantomjs
Another quick tip.
I use the excellent cljsbuild to compile and test our ClojureScript projects (and I can’t believe how difficult it is to wire this stuff together in 2016!). To support continuous integration I use phantomjs to provide the JavaScript environment.
Unfortunately circleci’s environment doesn’t have phantomjs
v2 available to it and v1 has some troubling properties. It turns out, after much googling and dead ends, that it is pretty trivial to get phantomjs
in your circleci environment, simply add:
machine:
pre:
- sudo curl --output /usr/local/bin/phantomjs https://s3.amazonaws.com/circle-downloads/phantomjs-2.1.1
to your circle.yml
- thanks kimh@circleci.
lein-cljsbuild
The documentation on github is sufficient and the advanced project contains all you need.
However, in brief (and note, this isn’t exactly the same as the advanced project):
project.clj
:
(defproject <YOUR-COMPANY>/<YOUR-COMPANY>.util "0.4.1-SNAPSHOT"
:description "FIXME: write description"
:url "http://example.com/FIXME"
:license {:name "Eclipse Public License"
:url "http://www.eclipse.org/legal/epl-v10.html"}
:dependencies [[org.clojure/clojure "1.8.0"]
[org.clojure/clojurescript "1.9.216"]
[org.clojure/tools.logging "0.3.1"]
[ch.qos.logback/logback-classic "1.1.7"]
[net.sourceforge.jtds/jtds "1.3.1"]
[com.mchange/c3p0 "0.9.5.2"]
[environ "1.1.0"]
[com.lucasbradstreet/instaparse-cljs "1.4.1.2"]
[prismatic/schema "1.1.3"]
[org.clojure/java.jdbc "0.4.2"]
[clj-time "0.12.0"]
[com.andrewmcveigh/cljs-time "0.4.0"]]
:plugins [[lein-environ "1.1.0"]
[lein-wagon-ssh-external "0.1.0"]
[lein-cljsbuild "1.1.4"]]
:cljsbuild {:test-commands
{"unit" ["phantomjs"
"phantom/unit-test.js"
"resources/private/html/unit-test.html"]}
:builds {
:prod
{:source-paths ["src"]
:compiler {:output-to "resources/public/js/main.js"
:optimizations :advanced
:pretty-print false}}
:test
{:source-paths ["src" "test" "test-cljs"]
:compiler {:output-to "resources/private/js/unit-test.js"
:optimizations :advanced
:pretty-print false}}}}
; Clean JS directories
:clean-targets ^{:protect false} ["resources/private/js"
"resources/public/js"
:target-path]
:aliases {"clj-tests!" ["do" "test"]
"cljs-tests!" ["do" ["cljsbuild" "test"]]
"all-tests!" ["do" "clj-tests!," "cljs-tests!"]
"full-build-no-tests!" ["do" "clean"]
"full-build-cljs!" ["do" "clean," "cljs-tests!"]
"full-build!" ["do" "clean," "all-tests!"]
;; TODO - circleci cannot access a MS SQL database so run as many tests as we can
"deploy!" ["do" "full-build-cljs!"]})
phantom/unit-test.js
:
var system = require('system');
var url,args;
if (phantom.version.major > 1) {
args = system.args;
if (args.length < 2) {
system.stderr.write('Expected a target URL parameter.');
phantom.exit(1);
}
url = args[1];
} else {
args = phantom.args;
if (args.length < 1) {
system.stderr.write('Expected a target URL parameter.');
phantom.exit(1);
}
url = args[0];
}
var page = require('webpage').create();
page.onConsoleMessage = function (message) {
console.log("Test console: " + message);
};
console.log("Loading URL: " + url);
page.open(url, function (status) {
if (status !== "success") {
console.log('Failed to open ' + url);
setTimeout(function() { // https://github.com/ariya/phantomjs/issues/12697
phantom.exit(1);
}, 0);
}
page.evaluate(function() {
<YOUR-COMPANY>.util.test.run();
});
setTimeout(function() { // https://github.com/ariya/phantomjs/issues/12697
phantom.exit(0);
}, 0);
});
test-cljs/<YOUR-COMPANY>.util.test
:
(ns <YOUR-COMPANY>.util.test
(:require [clojure.test :as t]
[<YOUR-COMPANY>.util.common-test]
[<YOUR-COMPANY>.util.hierarchy-test]
[<YOUR-COMPANY>.util.parser.time-test]))
(enable-console-print!)
(defn ^:export run []
(.log js/console "Testing <YOUR-COMPANY>.util")
(t/run-all-tests #"<YOUR-COMPANY>.util.*-test"))