Created
December 1, 2011 12:06
-
-
Save garth/1416238 to your computer and use it in GitHub Desktop.
Example Jakefile from ViennaJS meetup
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# This is some example code that executes in the browser and communicates with the jake dev process | |
# to re-run tests and report testing status | |
# The code is taken from a larger application, so just ignore the other bits. If you're not using QUnit | |
# replace the QUnit references with your favourite javascript testing/bdd framework. | |
define ['lib/browserinfo', 'template!testsuite', 'socket.io'], (browserInfo) -> | |
#connect to the test server | |
MyApp.testSocket = io.connect '/' | |
#get info about the current browser to send to the server | |
currentBrowser = "#{browserInfo.name} #{browserInfo.version} (#{browserInfo.OS})" | |
#replace the debug function with one that also notifies the test server | |
MyApp.debug = (message) -> | |
console.log message | |
MyApp.testSocket.emit 'debug', { browserInfo: currentBrowser, message: message } | |
#wait for notification from the server to re-run the test | |
MyApp.testSocket.on 'codeChanged', () -> | |
location.reload() | |
#render the qunit placeholders | |
view = SC.View.create templateName: 'testsuite' | |
#wait until the view is rendered before initialising QUnit | |
view.onReady = () -> | |
#load qunit | |
require ['qunit'], () -> | |
#configure QUnit | |
QUnit.config.urlConfig = [] | |
#send test results to the server | |
currentTest = '' | |
QUnit.testStart = (name) -> currentTest = name | |
QUnit.log = (data) -> | |
if !data.result | |
data.browserInfo = currentBrowser | |
data.test = currentTest | |
MyApp.testSocket.emit 'testFailed', data | |
QUnit.done = (data) -> | |
data.browserInfo = currentBrowser | |
MyApp.testSocket.emit 'testingComplete', data | |
#set test modules to run | |
require [ | |
'test/sometests' | |
'test/moretests' | |
], () -> | |
#run the tests | |
QUnit.load() | |
#return the view to to the router | |
return view |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Jake is like Rake for nodejs https://github.com/mde/jake | |
// | |
// Assumes that Jake will be run in the root of the web app with coffee files in /js/ and | |
// a single app.less file in /css/ that can include references to other .less files | |
// | |
//requires | |
var sys = require('util'); | |
var execute = require('child_process').exec; | |
var fs = require('fs'); | |
var colors = require('colors'); | |
//tasks | |
desc('Build all files'); | |
task({ 'default': ['coffee', 'less'] }, function (params) { | |
}); | |
desc('Watch .coffee and .less files for changes and auto compile on change'); | |
task({ 'dev': ['coffee', 'less'] }, function (params) { | |
watchDir('js', compileCoffeeScript, /\.coffee$/); | |
watchDir('css', compileLessFiles, /\.less$/); | |
console.log('Watching .coffee and .less files for changes...'); | |
startTestServer(); | |
}); | |
desc('Compile all .coffee files'); | |
task('coffee', function (params) { | |
console.log('Compiling all .coffee files'); | |
execOnDirFiles('js', compileCoffeeScript, /\.coffee$/); | |
}); | |
desc('Compile all .less files'); | |
task('less', function (params) { | |
console.log('Compiling all .less files'); | |
compileLessFiles('css/app.less'); | |
}); | |
function compileCoffeeScript(file) { | |
exec("coffee -l -b -c " + file); | |
notifyTestClients(); | |
} | |
function compileLessFiles(file) { | |
//ignore the file and always compile app.less which links in all other files | |
exec('lessc -x css/app.less', function(css) { | |
//replace the image urls with inline base64 image data | |
var files = {}; | |
css = css.replace(/url\((\S*)\.(png|jpg|jpeg|gif)\)/g, function(match, file, type) | |
{ | |
var fileName = file + '.' + type; | |
var base64 = fs.readFileSync(fileName).toString('base64'); | |
if (typeof(files[fileName]) !== 'undefined') { | |
console.log(('Warning: ' + fileName + ' has already been base64 encoded in the css').red); | |
} | |
else { | |
files[fileName] = true; | |
} | |
return 'url("data:image/' + (type === 'jpg' ? 'jpeg' : type) + ';base64,' + base64 + '")'; | |
}); | |
fs.writeFileSync('css/app.css', css, 'utf-8'); | |
}); | |
notifyTestClients(); | |
} | |
function execOnDirFiles(path, callback, match) { | |
fs.readdir(path, function (err, files) { | |
for (var i = 0; i < files.length; i++) { | |
if (!match || match.test(files[i])) { | |
callback(path + '/' + files[i]); | |
} | |
} | |
}); | |
} | |
function watchDir(path, callback, match) { | |
fs.readdir(path, function (err, files) { | |
for (var i = 0; i < files.length; i++) { | |
if (!match || match.test(files[i])) { | |
watchFile(path + '/' + files[i], callback); | |
} | |
} | |
}); | |
} | |
function watchFile(file, callback) { | |
var timeoutId = 0; | |
fs.watch(file, { persistent: true }, function () { | |
clearTimeout(timeoutId); | |
timeoutId = setTimeout(function() { | |
console.log(('File chaged: ' + file).yellow); | |
callback(file); | |
}, 500); | |
}); | |
} | |
function exec(command, onComplete) { | |
execute(command, function (error, stdout, stderr) { | |
if (typeof(onComplete) !== "function" && stdout) { | |
console.log(stdout); | |
} | |
if (stderr) { | |
console.log(stderr); | |
} | |
if (typeof(onComplete) === "function") { | |
onComplete(stdout); | |
} | |
}); | |
} | |
//start a web server with test fixtures for development | |
var testClients = []; | |
function startTestServer() { | |
var express = require('express'); | |
var rewriter = require('express-rewrite'); | |
var app = express.createServer(); | |
var io = require('socket.io').listen(app); | |
io.set('log level', 1); | |
io.set('transports', ['websocket', 'flashsocket', 'htmlfile', 'xhr-polling', 'jsonp-polling']); | |
app.configure(function() { | |
app.use(rewriter); | |
app.use(app.router); | |
app.use(express.static(__dirname)); | |
}); | |
app.configure('development', function() { | |
return app.use(express.errorHandler({ | |
dumpExceptions: true, | |
showStack: true | |
})); | |
}); | |
//load the index.html as root/default | |
app.get('/', rewriter.rewrite('/index.html')); | |
//reroute static test fixtures to emulate the production layout | |
app.get('/data/:a.json', rewriter.rewrite('/js/test/fixture/$1.json')); | |
app.get('/data/:a/:b.json', rewriter.rewrite('/js/test/fixture/$1/$2.json')); | |
app.get('/data/:a/:b/:c.json', rewriter.rewrite('/js/test/fixture/$1/$2/$3.json')); | |
app.get('/data/:a/:b/:c/:d.json', rewriter.rewrite('/js/test/fixture/$1/$2/$3/$4.json')); | |
app.get('/data/:a/:b/:c/:d/:e.json', rewriter.rewrite('/js/test/fixture/$1/$2/$3/$4/$5.json')); | |
app.get('/data/:a/:b/:c/:d/:e/:f.json', rewriter.rewrite('/js/test/fixture/$1/$2/$3/$4/$5/$6.json')); | |
//start the test web server | |
app.listen(3000); | |
console.log("HTTP test server listening on port %d... [ctrl+c to exit]", app.address().port); | |
//keep in contact with the test clients | |
io.sockets.on('connection', function (socket) { | |
testClients.push(socket); | |
//output messages from the test clients | |
socket.on('testFailed', function (data) { | |
var output = data.browserInfo + ' Test Failed'.red + ': ' + data.test.module + ' > ' + data.test.name; | |
if (!data.expected || !data.actual) { | |
if (data.message.indexOf('\n') == -1) { console.log(output + ' > ' + data.message); } | |
else { console.log(output + '\n' + data.message.cyan); } | |
} | |
else { | |
console.log(output + ' > ' + data.message + | |
' ('+ data.expected.toString().green + ':' + data.actual.toString().red + ')'); | |
} | |
if (data.source) { console.log(' ' + data.source.trim().cyan); } | |
}); | |
socket.on('testingComplete', function (data) { | |
var failed = data.failed > 0 ? data.failed.toString().red : data.failed.toString().green | |
console.log(data.browserInfo + ' Testing Complete - failed: ' + failed + | |
', passed: ' + data.passed.toString().green + ', total: ' + data.total + | |
', runtime: ' + data.runtime + 'ms'); | |
}); | |
socket.on('debug', function (data) { | |
console.log(data.browserInfo + ' Debug: ' + data.message.cyan); | |
}); | |
}); | |
} | |
//send change notification messages to connect clients | |
var timeoutId = 0; | |
function notifyTestClients() { | |
if (testClients.length > 0) { | |
//use a timeout so that we don't send multiple messages | |
clearTimeout(timeoutId); | |
timeoutId = setTimeout(function() { | |
console.log('Running client tests...'.yellow); | |
for (var i = 0; i < testClients.length; i++) { | |
testClients[i].emit('codeChanged'); | |
} | |
}, 2000); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment