Using ClojureScript for Cordova app development is described in a previous post. This post will expand on how to do live reloading when code changes and also writing JavaScript unit tests with QUnit. Sample code structure is given below.
example-cordova-app
├── Gruntfile.js
├── config.xml
├── hooks
├── node_modules
├── package-lock.json
├── package.json
├── platforms
│ └── browser
│ ├── browser.json
│ ├── ...
├── plugins
├── res
├── example-cordova-cljs
│ ├── out
│ ├── project.clj
│ ├── resources
│ ├── src
│ │ └── my_app
│ │ └── core.cljs
│ ├── target
│ └── test
│ └── my_app
│ └── core_test.clj
└── www
├── css
│ └── style.css
├── img
├── index.html
├── js
│ ├── app.js
│ ├── libs
│ ├── main.js
└── test
├── qunit.css
├── qunit.js
├── test.html
└── tests.js
We can use browser
platform to do quick testing during development and cordova-plugin-browsersync
to do live reloading of www
folder.
1. Install cordova-plugin-browsersync
.
cordova plugins add cordova-plugin-browsersync
2. Once the plugin is installed, we can start the watcher from terminal.
cordova run browser -- --live-reload
When ClojureScript changes, it compiles and places the file into www
, and the above plugin will detect the change and do a reload. Refresh the browser and the latest code changes will be reflected. This is also useful when we mix JavaScript and ClojureScript.
Unit Testing with QUnit
We can write ClojureScript test, which is a different workflow. Place test scripts under www/test
folder. A sample test.html
is shown below.
<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" href="qunit.css">
<script type="text/javascript" src="qunit.js"></script>
<script type="text/javascript" src="tests.js"></script>
<title>Testsuite</title>
</head>
<body>
<div id="qunit"></div>
<div id="qunit-fixture"></div>
</body>
</html>
Test scripts can go to test.js
.
// test.js
if (document.loaded) {
test();
} else {
window.addEventListener('load', test, false);
}
function test() {
QUnit.module("test");
QUnit.test("Example", function (assert) {
assert.ok(true, "ok is for boolean test");
assert.equal(1, "1", "comparison");
});
}
We will use grunt
to run these tasks. Add both live reload and unit test tasks in Gruntfile.js
.
module.exports = function(grunt) {
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
qunit: {
files: ['www/test/**/*.html']
},
exec: {
start: {
command: 'cordova run browser -- --live-reload'
}
}
});
grunt.loadNpmTasks('grunt-contrib-qunit');
grunt.loadNpmTasks('grunt-exec');
grunt.registerTask('test', ['qunit']);
grunt.registerTask('start', ['exec:start']);
};
The required dependencies added to package.json
follows.
{
"name": "net.jsloop.example.app",
// ...
"main": "main.js",
"scripts": {
"start": "cordova run browser -- --live-reload",
"test": "grunt test"
},
"dependencies": {
"browser-sync": "^2.23.6",
"cordova-browser": "^5.0.3",
"cordova-plugin-browsersync": "^1.1.0",
"cordova-plugin-whitelist": "^1.3.3",
// ...
},
"cordova": {
"plugins": {
"cordova-plugin-whitelist": {},
"cordova-plugin-browsersync": {}
},
"platforms": [
"browser"
]
},
"devDependencies": {
"grunt": "^1.0.2",
"grunt-contrib-qunit": "^2.0.0",
"grunt-exec": "^3.0.0"
}
}
The tasks start
, test
are available as grunt
task and we can link main ones to npm
as well.
# grunt
grunt start # start watcher
grunt test # run testsuite
# npm
npm start
npm test