Ludochaordic
Fantaisies programatico-ludiques

Mimicking testling HTML rendering of TAP javascript tests

This post is only relevant to you if you use browserify. For a good introduction to this powerful Javascript bundling tool, check this doc.

First of all, I'd like to take my hat off to James Hallyday and Peteris Krumins who have built such amazing tools as browserify, testling and browserling.

Now, the problem : I want an HTML page that execute and display the results of my Javascript unit tests.

Actually, when using TAP tests, browserify has a handy companion : testling. With him, we can get such HTML output :

browserify my_test.js | testling --html > tests.html

However, the issue is that testling doesn't provide any option to include custom HTML content in its output. Alas, the Javascript code I was testing in my case relied on some HTML tags to exist.

To get around this limitation, and automate the process, I crafted the following Makefile that mimics the logic of the original testling source code :

HTML_INDEX  := index.html
OUT_BUNDLE  := bundle.js
TESTS_HTML  := tests.html
TESTS_BUNDLE:= tests-bundle.js
PRELUDE     := browserified_testling_prelude.js

TESTS_DIR   := tests/
TESTS_FILES := $(wildcard $(TESTS_DIR)*.js)

print = /bin/echo -e "\x1b[36m\#\# $(1)\x1b[0m"

.PHONY: tests view-tests

tests: $(TESTS_HTML)

$(TESTS_HTML): $(HTML_INDEX) $(TESTS_BUNDLE) $(PRELUDE)
    @$(call print,'Building the HTML file for rendering tests in a browser')
    perl -p -e "s/$(OUT_BUNDLE)/$(TESTS_BUNDLE)/ && print '\
        <pre id=\"__testling_output\">\
        </pre>\
        <script type=\"text/javascript\" src=\"$(PRELUDE)\"defer>\
        </script>\
        '" $(HTML_INDEX) > $(TESTS_HTML)

$(TESTS_BUNDLE): $(TESTS_FILES)
    @$(call print,'Generating JS tests bundle')
    browserify $(TESTS_FILES) > $(TESTS_BUNDLE)

$(PRELUDE):
    @$(call print,'Retrieving & browserifying testling prelude')
    wget https://raw.githubusercontent.com/substack/testling/master/browser/prelude.js
    browserify prelude.js > $(PRELUDE)
    rm prelude.js

view-tests: $(TESTS_HTML)
    @$(call print,'Creating a local server & opening the tests HTML page in a local browser')
    python -m webbrowser http://localhost:8080/$(TESTS_HTML)
    python -m SimpleHTTPServer 8080

Basically, here is what happens when running make tests :

  1. the unit tests files are bundled by browserify into tests-bundle.js.
  2. the script required to display the tests is generated by browserifying testling prelude.js source file.
  3. an ugly sed-like perl one-liner generates the tests viewer HTML file by copying our base HTML index.html and applying one substitution : it replaces the line originally including our bundle.js by 3 others :
    • one including the tests-bundle.js script
    • one including the browserified_testling_prelude.js script
    • one defining a <pre> block where the tests output will be displayed

Et voilà !