diff --git a/.gitignore b/.gitignore index 4086ceec52..2b1ffbfeb8 100644 --- a/.gitignore +++ b/.gitignore @@ -32,4 +32,5 @@ nbproject .hg .svn .CVS -.idea \ No newline at end of file +.idea +node_modules diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000000..b8e1f17207 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,3 @@ +language: node_js +node_js: + - 0.6 \ No newline at end of file diff --git a/Makefile b/Makefile index f99b2303f5..9a4ffa4536 100644 --- a/Makefile +++ b/Makefile @@ -5,6 +5,7 @@ BOOTSTRAP_RESPONSIVE_LESS = ./less/responsive.less DATE=$(shell date +%I:%M%p) CHECK=\033[32m✔\033[39m + # # BUILD DOCS # @@ -36,6 +37,17 @@ build: @echo "Thanks for using Bootstrap," @echo "<3 @mdo and @fat\n" +# +# 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 diff --git a/README.md b/README.md index cab1d7afde..54ea40577f 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -[Twitter Bootstrap](http://twitter.github.com/bootstrap) +[Twitter Bootstrap](http://twitter.github.com/bootstrap) [![Build Status](https://secure.travis-ci.org/twitter/bootstrap.png)](http://travis-ci.org/twitter/bootstrap) ================= Bootstrap provides simple and flexible HTML, CSS, and Javascript for popular user interface components and interactions. In other words, it's a front-end toolkit for faster, more beautiful web development. It's created and maintained by [Mark Otto](http://twitter.com/mdo) and [Jacob Thornton](http://twitter.com/fat) at Twitter. @@ -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. Read more in our docs » ++ **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 @@ + + + diff --git a/js/tests/phantom.js b/js/tests/phantom.js new file mode 100644 index 0000000000..5173ba9a19 --- /dev/null +++ b/js/tests/phantom.js @@ -0,0 +1,63 @@ +// 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 100ms +} + + +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..a04aeaa878 --- /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 new file mode 100644 index 0000000000..5f54d5c78a --- /dev/null +++ b/package.json @@ -0,0 +1,25 @@ +{ + "name": "bootstrap" + , "description": "HTML, CSS, and JS toolkit from Twitter." + , "version": "2.0.3" + , "keywords": ["bootstrap", "css"] + , "homepage": "http://twitter.github.com/bootstrap/" + , "author": "Twitter Inc." + , "scripts": { "test": "make test" } + , "repository": { + "type": "git" + , "url": "https://github.com/twitter/bootstrap.git" + } + , "licenses": [ + { + "type": "Apache-2.0" + , "url": "http://www.apache.org/licenses/LICENSE-2.0" + } + ] + , "devDependencies": { + "uglify-js": "*" + , "jshint": "*" + , "recess": "*" + , "connect": "*" + } +} \ No newline at end of file