Last active
December 20, 2015 05:19
-
-
Save starstuck/6077578 to your computer and use it in GitHub Desktop.
Running jasmine tests in phantom while sending results back to mocha on node to have nice console reporter
This file contains 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
#!/usr/bin/env node | |
var server = require('./test-server'), | |
child_process = require('child_process'), | |
port = server.port; | |
console.log(''); | |
console.log('------------------------------------------------------------------------'); | |
console.log('Running jasmine tests in phantomjs'); | |
console.log('------------------------------------------------------------------------'); | |
console.log(''); | |
console.info('Spawning server http://localhost: ' + port); | |
server.listen(port); | |
console.info('Spawning phantomjs browser'); | |
var phantom = child_process.spawn('phantomjs', [__dirname + '/test-phantom-main.js']); | |
// Uncomment to get phantom console beeing printed on screen | |
//phantom.stdout.on('data', function(data) { | |
// console.log('Phantom: ' + data); | |
//}); | |
phantom.stderr.on('data', function (data) { | |
console.error('ERROR: ' + data); | |
}); | |
phantom.on('close', function (code) { | |
if (code !== 0) { | |
console.error('PHANTOM DIED WITH UNEXPECTED RESULT CODE: ' + code); | |
} | |
console.log('Closing server after all tests are done'); | |
server.close(); | |
process.exit(0); | |
}); |
This file contains 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
/** | |
* Jasmine reporter that sends tests through socketio | |
*/ | |
(function(factory) { | |
//if (typeof define !== undefined) { | |
// define('socket-reporter', factory); | |
//} else if (typeof module !== undefined) { | |
// factory(require, exports, module); | |
//} else { | |
window.SocketReporter = factory(null, null, {}); | |
//} | |
}(function(require, exports, module) { | |
var proto; | |
function Reporter(socket) { | |
this.socket = socket; | |
socket.on('close', function () { | |
window.close(); | |
}); | |
} | |
proto = Reporter.prototype; | |
proto.reportRunnerStarting = function(runner) { | |
this.socket.emit('start'); | |
this.lastSuite = null; | |
}; | |
proto.reportRunnerResults = function(runner) { | |
this.socket.emit('end'); | |
}; | |
proto.reportSpecStarting = function(spec) { | |
var socket = this.socket; | |
if (!this.lastSuite || (spec.suite.id !== this.lastSuite.id)) { | |
if (this.lastSuite) { | |
socket.emit('suite end', { | |
title: this.lastSuite.description, | |
root: {} | |
}); | |
} | |
socket.emit('suite', { | |
title: spec.suite.description, | |
root: {} | |
}); | |
this.lastSuite = spec.suite; | |
} | |
socket.emit('test', { | |
title: spec.description | |
}); | |
}; | |
proto.reportSpecResults = function(spec) { | |
var socket = this.socket, | |
results = spec.results(), | |
errors = results.getItems(), | |
test = { | |
title: spec.description | |
}, | |
err; | |
if (results.skipped) { | |
socket.emit('pending', test); | |
} else if (results.passed() || errors[0].message == "Passed.") { // From some strange reason results.passed() was not reliable on windows | |
socket.emit('pass', test); | |
} else { | |
if (errors) { | |
test.err = { | |
message: errors[0].message, | |
stack: errors[0].trace.stack | |
}; | |
} | |
socket.emit('fail', test); | |
} | |
socket.emit('test end', test); | |
}; | |
return exports = module.exports = Reporter; | |
})); |
This file contains 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
/** | |
* Tests runner intended to be executed in phantomjs | |
*/ | |
(function () { | |
var system = require('system'), | |
page = require('webpage').create(); | |
page.onError = function(msg, trace) { | |
console.error('ERROR: ' + msg); | |
}; | |
page.onConsoleMessage = function(msg, lineNum, sourceId) { | |
console.log('CONSOLE: ' + msg + ' (from line #' + lineNum + ' in "' + sourceId + '")'); | |
}; | |
page.onAlert = function(msg) { | |
console.log('ALERT: ' + msg); | |
}; | |
page.onLoadStarted = function() { | |
console.log('Load started'); | |
}; | |
page.onResourceRequested = function(requestData, networkRequest) { | |
//console.log('Request (#' + requestData.id + '): ' + JSON.stringify(requestData)); | |
console.log('Fetching: ' + requestData.url); | |
}; | |
page.onClosing = function() { | |
console.log('Page closing'); | |
// Exit methods apparently needs to be run outside of current event handler, | |
// so phantom has time to cleanup page object | |
setTimeout(function() { | |
phantom.exit(0); | |
}, 0); | |
}; | |
page.onLoadFinished = function(status) { | |
console.log('Load finished: ', status); | |
console.log("Got page on: ", page.evaluate(function() { | |
return window.location.toString(); | |
}) ); | |
}; | |
page.open('http://localhost:9091/headless.html'); | |
}()); |
This file contains 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
#!/usr/bin/env node | |
var http = require('http'), | |
fs = require('fs'), | |
express = require('express'), | |
io = require('socket.io'), | |
SpecReporter = require('mocha').reporters.Spec, | |
Test = require('mocha').Test, | |
app = express(), | |
server = exports = module.exports = http.createServer(app), | |
port = exports.port = 9091, | |
sio = io.listen(server, {log: false}), | |
tests = [], | |
rootPath = __dirname + '/../..', | |
jasmineUrl = '/lib/jasmine-1.3.1', | |
requirejsConfig = { | |
baseUrl: 'src/main/js', | |
paths: { | |
// External libraries | |
'jquery': '//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min', | |
// Internal jQuery plugins | |
'jquery.c4tooltip': 'plugins/jquery.c4tooltip', | |
'jquery.c4carousel': 'plugins/jquery.c4carousel', | |
'jquery.paginate': 'plugins/jquery.paginate', | |
'jquery.splitlines': 'plugins/jquery.splitlines' | |
}, | |
shim: { | |
'jquery': {exports: 'jQuery'} | |
} | |
}; | |
function readTests(path) { | |
var diskPath = rootPath + path, | |
stat = fs.lstatSync(diskPath); | |
if (stat.isFile()) { | |
if (path.match(/\.js$/)) { | |
tests.push(path); | |
} | |
} else { | |
fs.readdir(diskPath, function(err, files) { | |
if (files) { | |
files.forEach(function(f) { | |
readTests(path + '/' + f); | |
}); | |
} | |
}); | |
} | |
} | |
readTests('/src/test'); | |
app.get("/", function(req, res, next) { | |
res.send([ | |
'<!DOCTYPE html>', | |
'<html lang="en"><head><title>Jasine test suite</title></head>', | |
'<body>', | |
' <link rel="stylesheet" href="' + jasmineUrl + '/jasmine.css" type="text/css">', | |
' <script src="' + jasmineUrl + '/jasmine.js"></script>', | |
' <script src="' + jasmineUrl + '/jasmine-html.js"></script>', | |
' <script src="/lib/require-2.1.5.js"></script>', | |
' <script>', | |
' requirejs.config(' + JSON.stringify(requirejsConfig) + ');', | |
'(' + function (tests) { | |
require(tests, function () { | |
jasmine.getEnv().addReporter(new jasmine.TrivialReporter()); | |
jasmine.getEnv().execute(); | |
}); | |
}.toString() + '(' + JSON.stringify(tests) + '));', | |
' </script>', | |
'</body></html>' | |
].join('\n')); | |
}); | |
app.get("/headless.html", function(req, res, next) { | |
res.send([ | |
'<!DOCTYPE html>', | |
'<html lang="en"><head><title>Jasmine test suite</title></head>', | |
'<body>', | |
' <script src="' + jasmineUrl + '/jasmine.js"></script>', | |
' <script src="/socket.io/socket.io.js"></script>', | |
' <script src="/lib/require-2.1.5.js"></script>', | |
' <script src="/src/scripts/test-jasmine-reporter.js"></script>', | |
' <script>', | |
' requirejs.config(' + JSON.stringify(requirejsConfig) + ');', | |
'(' + function (tests) { | |
require(tests, function () { | |
var socket = window.socket = io.connect('http://localhost:9091'); | |
jasmine.getEnv().addReporter(new SocketReporter(socket)); | |
jasmine.getEnv().execute(); | |
}); | |
}.toString() + '(' + JSON.stringify(tests) + '));', | |
' </script>', | |
'</body></html>' | |
].join('\n')); | |
}); | |
app.use("/src", express.static(__dirname + '/..')); | |
app.use("/lib", express.static(__dirname + '/../../lib')); | |
/** | |
* Remote test stub, which provides mocha compatible test interface | |
*/ | |
function TestStub(data) { | |
this.data = data; | |
this.title = data.title; | |
this.err = data.err; | |
}; | |
TestStub.prototype.__proto__ = Test.prototype; | |
TestStub.prototype.fullTitle = function () { | |
//TODO: should include suite titles as well, or have suite stub in this.parent | |
return this.title; | |
}; | |
/** | |
* Pseudo runner which is mimicking mocha runner | |
*/ | |
function SocketRunner(socket) { | |
var me = this; | |
this.socket = socket; | |
this.listeners = {}; | |
['start', 'suite', 'suite end', 'test', 'test end', 'pass', 'fail', 'pending', 'end'].forEach(function (event) { | |
socket.on(event, function(payload) { | |
me.emit(event, payload); | |
}); | |
}); | |
// TODO: do not send close signal if tool called for long running session | |
me.on('end', function() { | |
// Give time to reported to print out summary | |
setTimeout(function() { | |
socket.emit('close'); | |
}, 0); | |
}); | |
} | |
SocketRunner.prototype.emit = function(event, payload) { | |
var callbacks = this.listeners[event], | |
i, l; | |
if (callbacks) { | |
if (event.match(/^(test|pass|fail|pending)( end)?$/)) { | |
payload = new TestStub(payload); | |
} | |
for (i = 0; i < callbacks.length; i++) { | |
callbacks[i](payload, payload && payload.err); | |
} | |
} | |
}; | |
SocketRunner.prototype.on = function(event, callback) { | |
var listeners = this.listeners; | |
if (! listeners[event]) { | |
listeners[event] = []; | |
} | |
listeners[event].push(callback); | |
}; | |
sio.on('connection', function(socket) { | |
var runner = new SocketRunner(socket), | |
reporter = new SpecReporter(runner); | |
}); | |
if(require.main === module) { | |
server.listen(port); | |
console.log('Test server lisening on http://localhost:' + port + '/'); | |
console.log('Press Ctrl+C to close server'); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment