diff options
-rw-r--r-- | Makefile | 8 | ||||
-rw-r--r-- | README.md | 3 | ||||
-rw-r--r-- | js/tests/index.html | 3 | ||||
-rw-r--r-- | js/tests/phantom.js | 65 | ||||
-rw-r--r-- | js/tests/server.js | 18 | ||||
-rw-r--r-- | js/tests/unit/bootstrap-phantom.js | 21 | ||||
-rw-r--r-- | package.json | 1 |
7 files changed, 117 insertions, 2 deletions
@@ -5,6 +5,7 @@ BOOTSTRAP_RESPONSIVE_LESS = ./less/responsive.less DATE=$(shell date +%I:%M%p) CHECK=\033[32m✔\033[39m + # # BUILD DOCS # @@ -37,13 +38,16 @@ build: @echo "<3 @mdo and @fat\n" # -# RUN JSHINT -# TODO: run unittests +# RUN JSHINT & QUNIT TESTS IN PHANTOMJS # test: jshint js/*.js --config js/.jshintrc jshint js/tests/unit/*.js --config js/.jshintrc + node js/tests/server.js & + phantomjs js/tests/phantom.js "http://localhost:3000/js/tests" + kill -9 `cat js/tests/pid.txt` + rm js/tests/pid.txt # # BUILD SIMPLE BOOTSTRAP DIRECTORY @@ -91,6 +91,9 @@ $ npm install recess uglify-js jshint -g + **build** - `make` Runs the recess compiler to rebuild the `/less` files and compiles the docs pages. Requires recess and uglify-js. <a href="http://twitter.github.com/bootstrap/less.html#compiling">Read more in our docs »</a> ++ **test** - `make test` +Runs jshint and qunit tests headlessly in phantom js (used for ci). Depends on having phatomjs installed. + + **watch** - `make watch` This is a convenience method for watching just Less files and automatically building them whenever you save. Requires the Watchr gem. diff --git a/js/tests/index.html b/js/tests/index.html index 3e6cb9777c..2f8f71b12e 100644 --- a/js/tests/index.html +++ b/js/tests/index.html @@ -11,6 +11,9 @@ <link rel="stylesheet" href="vendor/qunit.css" type="text/css" media="screen" /> <script src="vendor/qunit.js"></script> + <!-- phantomjs logging script--> + <script src="unit/bootstrap-phantom.js"></script> + <!-- plugin sources --> <script src="../../js/bootstrap-transition.js"></script> <script src="../../js/bootstrap-alert.js"></script> diff --git a/js/tests/phantom.js b/js/tests/phantom.js new file mode 100644 index 0000000000..f172e7cbc3 --- /dev/null +++ b/js/tests/phantom.js @@ -0,0 +1,65 @@ +/* + * Simple phantom.js integration script + * Adapted from Modernizr + */ + +function waitFor(testFx, onReady, timeOutMillis) { + var maxtimeOutMillis = timeOutMillis ? timeOutMillis : 3001, //< Default Max Timout is 3s + start = new Date().getTime(), + condition = false, + interval = setInterval(function() { + if ( (new Date().getTime() - start < maxtimeOutMillis) && !condition ) { + // If not time-out yet and condition not yet fulfilled + condition = (typeof(testFx) === "string" ? eval(testFx) : testFx()); //< defensive code + } else { + if(!condition) { + // If condition still not fulfilled (timeout but condition is 'false') + console.log("'waitFor()' timeout"); + phantom.exit(1); + } else { + // Condition fulfilled (timeout and/or condition is 'true') + typeof(onReady) === "string" ? eval(onReady) : onReady(); //< Do what it's supposed to do once the condition is fulfilled + clearInterval(interval); //< Stop this interval + } + } + }, 100); //< repeat check every 250ms +}; + + +if (phantom.args.length === 0 || phantom.args.length > 2) { + console.log('Usage: phantom.js URL'); + phantom.exit(); +} + +var page = new WebPage(); + +// Route "console.log()" calls from within the Page context to the main Phantom context (i.e. current "this") +page.onConsoleMessage = function(msg) { + console.log(msg); +}; + +page.open(phantom.args[0], function(status){ + if (status !== "success") { + console.log("Unable to access network"); + phantom.exit(); + } else { + waitFor(function(){ + return page.evaluate(function(){ + var el = document.getElementById('qunit-testresult'); + if (el && el.innerText.match('completed')) { + return true; + } + return false; + }); + }, function(){ + var failedNum = page.evaluate(function(){ + var el = document.getElementById('qunit-testresult'); + try { + return el.getElementsByClassName('failed')[0].innerHTML; + } catch (e) { } + return 10000; + }); + phantom.exit((parseInt(failedNum, 10) > 0) ? 1 : 0); + }); + } +});
\ No newline at end of file diff --git a/js/tests/server.js b/js/tests/server.js new file mode 100644 index 0000000000..27d1bf24b3 --- /dev/null +++ b/js/tests/server.js @@ -0,0 +1,18 @@ +/* + * Simple connect server for phantom.js + * Adapted from Modernizr + */ + +var connect = require('connect') + , args = process.argv.slice(2) + , fs = require('fs') + , folder = '/../../' + , port = '3000' + +var server = connect.createServer( + connect.static(__dirname + folder) +).listen(port) + +fs.writeFileSync(__dirname + '/pid.txt', process.pid, 'utf-8') + +console.log("Server started on port %s in %s", port, folder)
\ No newline at end of file diff --git a/js/tests/unit/bootstrap-phantom.js b/js/tests/unit/bootstrap-phantom.js new file mode 100644 index 0000000000..8bed5f6035 --- /dev/null +++ b/js/tests/unit/bootstrap-phantom.js @@ -0,0 +1,21 @@ +// Logging setup for phantom integration +// adapted from Modernizr + +QUnit.begin = function() { + console.log("Starting test suite"); + console.log("================================================\n"); +}; + +QUnit.moduleDone = function(opts) { + if(opts.failed === 0) { + console.log("\u2714 All tests passed in '"+opts.name+"' module"); + } else { + console.log("\u2716 "+ opts.failed +" tests failed in '"+opts.name+"' module"); + } +}; + +QUnit.done = function(opts) { + console.log("\n================================================"); + console.log("Tests completed in "+opts.runtime+" milliseconds"); + console.log(opts.passed + " tests of "+opts.total+" passed, "+opts.failed+" failed."); +};
\ No newline at end of file diff --git a/package.json b/package.json index c32979e53d..5f54d5c78a 100644 --- a/package.json +++ b/package.json @@ -20,5 +20,6 @@ "uglify-js": "*" , "jshint": "*" , "recess": "*" + , "connect": "*" } }
\ No newline at end of file |