2012-11-02 13:03:09 +08:00
|
|
|
/*global window:false, alert:false, jasmine:false, Node:false, */
|
|
|
|
/*jshint curly:false*/
|
|
|
|
|
2013-02-06 06:13:10 +08:00
|
|
|
'use strict';
|
|
|
|
|
|
|
|
var phantom = {};
|
2012-11-02 13:03:09 +08:00
|
|
|
|
2013-02-06 06:13:10 +08:00
|
|
|
if (window._phantom) {
|
|
|
|
console.log = function(){
|
|
|
|
phantom.sendMessage('verbose',Array.prototype.slice.apply(arguments).join(', '));
|
|
|
|
};
|
|
|
|
}
|
2012-11-02 13:03:09 +08:00
|
|
|
|
2013-02-06 06:13:10 +08:00
|
|
|
phantom.sendMessage = function() {
|
|
|
|
var args = [].slice.call( arguments );
|
|
|
|
var payload = JSON.stringify( args );
|
2013-01-09 03:28:26 +08:00
|
|
|
if (window._phantom) {
|
2013-02-06 06:13:10 +08:00
|
|
|
// alerts are the communication bridge to grunt
|
|
|
|
alert( payload );
|
2013-01-09 03:28:26 +08:00
|
|
|
}
|
2013-02-06 06:13:10 +08:00
|
|
|
};
|
2013-01-09 03:28:26 +08:00
|
|
|
|
2013-02-06 06:13:10 +08:00
|
|
|
(function(){
|
2012-11-02 13:03:09 +08:00
|
|
|
|
|
|
|
function PhantomReporter() {
|
|
|
|
this.started = false;
|
|
|
|
this.finished = false;
|
|
|
|
this.suites_ = [];
|
|
|
|
this.results_ = {};
|
|
|
|
this.buffer = '';
|
|
|
|
}
|
|
|
|
|
|
|
|
PhantomReporter.prototype.reportRunnerStarting = function(runner) {
|
|
|
|
this.started = true;
|
|
|
|
|
|
|
|
var suites = runner.topLevelSuites();
|
|
|
|
for (var i = 0; i < suites.length; i++) {
|
|
|
|
var suite = suites[i];
|
|
|
|
this.suites_.push(this.summarize_(suite));
|
|
|
|
}
|
|
|
|
phantom.sendMessage('jasmine.reportRunnerStarting', this.suites_);
|
|
|
|
};
|
|
|
|
|
|
|
|
PhantomReporter.prototype.reportSpecStarting = function(spec) {
|
2013-01-08 05:39:40 +08:00
|
|
|
spec.startTime = (new Date()).getTime();
|
2014-01-15 00:55:36 +08:00
|
|
|
phantom.sendMessage('jasmine.reportSpecStarting', spec.description, this.getSuiteNames(spec));
|
2012-11-02 13:03:09 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
PhantomReporter.prototype.suites = function() {
|
|
|
|
return this.suites_;
|
|
|
|
};
|
|
|
|
|
|
|
|
PhantomReporter.prototype.summarize_ = function(suiteOrSpec) {
|
|
|
|
var isSuite = suiteOrSpec instanceof jasmine.Suite;
|
|
|
|
var summary = {
|
|
|
|
id: suiteOrSpec.id,
|
|
|
|
name: suiteOrSpec.description,
|
|
|
|
type: isSuite ? 'suite' : 'spec',
|
|
|
|
children: []
|
|
|
|
};
|
|
|
|
|
|
|
|
if (isSuite) {
|
|
|
|
var children = suiteOrSpec.children();
|
|
|
|
for (var i = 0; i < children.length; i++) {
|
|
|
|
summary.children.push(this.summarize_(children[i]));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return summary;
|
|
|
|
};
|
|
|
|
|
|
|
|
PhantomReporter.prototype.results = function() {
|
|
|
|
return this.results_;
|
|
|
|
};
|
|
|
|
|
|
|
|
PhantomReporter.prototype.resultsForSpec = function(specId) {
|
|
|
|
return this.results_[specId];
|
|
|
|
};
|
|
|
|
|
2013-03-28 20:59:27 +08:00
|
|
|
function map(values, f) {
|
|
|
|
var result = [];
|
|
|
|
for (var ii = 0; ii < values.length; ii++) {
|
|
|
|
result.push(f(values[ii]));
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2012-11-02 13:03:09 +08:00
|
|
|
PhantomReporter.prototype.reportRunnerResults = function(runner) {
|
|
|
|
this.finished = true;
|
2013-03-28 20:59:27 +08:00
|
|
|
var specIds = map(runner.specs(), function(a){return a.id;});
|
2012-11-02 13:03:09 +08:00
|
|
|
var summary = this.resultsForSpecs(specIds);
|
|
|
|
phantom.sendMessage('jasmine.reportRunnerResults',summary);
|
2013-01-09 03:28:26 +08:00
|
|
|
phantom.sendMessage('jasmine.reportJUnitResults', this.generateJUnitSummary(runner));
|
2012-11-02 13:03:09 +08:00
|
|
|
phantom.sendMessage('jasmine.done.PhantomReporter');
|
|
|
|
};
|
|
|
|
|
|
|
|
PhantomReporter.prototype.reportSuiteResults = function(suite) {
|
2013-01-08 21:19:02 +08:00
|
|
|
if (suite.specs().length) {
|
|
|
|
suite.timestamp = new Date();
|
|
|
|
suite.duration = suite.timestamp.getTime() - suite.specs()[0].startTime;
|
|
|
|
phantom.sendMessage('jasmine.reportSuiteResults',{
|
|
|
|
description : suite.description,
|
|
|
|
results : suite.results()
|
|
|
|
});
|
|
|
|
}
|
2012-11-02 13:03:09 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
function stringify(obj) {
|
|
|
|
if (typeof obj !== 'object') return obj;
|
|
|
|
|
2013-02-27 11:40:20 +08:00
|
|
|
var cache = [], keyMap = [], index;
|
2012-11-02 13:03:09 +08:00
|
|
|
|
|
|
|
var string = JSON.stringify(obj, function(key, value) {
|
|
|
|
// Let json stringify falsy values
|
|
|
|
if (!value) return value;
|
|
|
|
|
|
|
|
// If we're a node
|
2013-12-17 19:05:53 +08:00
|
|
|
if (typeof(Node) !== 'undefined' && !Node.hasOwnProperty("initialized") && value instanceof Node) return '[ Node ]';
|
2012-11-02 13:03:09 +08:00
|
|
|
|
2013-06-14 01:54:50 +08:00
|
|
|
// jasmine-given has expectations on Specs. We intercept to return a
|
|
|
|
// String to avoid stringifying the entire Jasmine environment, which
|
|
|
|
// results in exponential string growth
|
|
|
|
if (value instanceof jasmine.Spec) return '[ Spec: ' + value.description + ' ]';
|
|
|
|
|
2012-11-02 13:03:09 +08:00
|
|
|
// If we're a window (logic stolen from jQuery)
|
|
|
|
if (value.window && value.window === value.window.window) return '[ Window ]';
|
|
|
|
|
|
|
|
// Simple function reporting
|
|
|
|
if (typeof value === 'function') return '[ Function ]';
|
|
|
|
|
|
|
|
if (typeof value === 'object' && value !== null) {
|
|
|
|
|
|
|
|
if (index = cache.indexOf(value) !== -1) {
|
|
|
|
// If we have it in cache, report the circle with the key we first found it in
|
|
|
|
return '[ Circular {' + (keyMap[index] || 'root') + '} ]';
|
|
|
|
}
|
|
|
|
cache.push(value);
|
|
|
|
keyMap.push(key);
|
|
|
|
}
|
|
|
|
return value;
|
|
|
|
});
|
|
|
|
return string;
|
|
|
|
}
|
|
|
|
|
|
|
|
PhantomReporter.prototype.reportSpecResults = function(spec) {
|
2013-01-08 05:39:40 +08:00
|
|
|
spec.duration = (new Date()).getTime() - spec.startTime;
|
2012-11-02 13:03:09 +08:00
|
|
|
var _results = spec.results();
|
|
|
|
var results = {
|
|
|
|
description : _results.description,
|
|
|
|
messages : _results.getItems(),
|
|
|
|
failedCount : _results.failedCount,
|
|
|
|
totalCount : _results.totalCount,
|
|
|
|
passedCount : _results.passedCount,
|
|
|
|
skipped : _results.skipped,
|
|
|
|
passed : _results.passed(),
|
|
|
|
msg : _results.failedCount > 0 ? "failed" : "passed"
|
|
|
|
};
|
|
|
|
this.results_[spec.id] = results;
|
|
|
|
|
|
|
|
// Quick hack to alleviate cyclical object breaking JSONification.
|
2013-03-28 08:04:02 +08:00
|
|
|
for (var ii = 0; ii < results.messages.length; ii++) {
|
|
|
|
var item = results.messages[ii];
|
2012-11-02 13:03:09 +08:00
|
|
|
if (item.expected) {
|
|
|
|
item.expected = stringify(item.expected);
|
|
|
|
}
|
|
|
|
if (item.actual) {
|
|
|
|
item.actual = stringify(item.actual);
|
|
|
|
}
|
2013-03-28 08:04:02 +08:00
|
|
|
}
|
2012-11-02 13:03:09 +08:00
|
|
|
|
2014-01-15 00:55:36 +08:00
|
|
|
phantom.sendMessage( 'jasmine.reportSpecResults', spec.id, results, this.getSuiteNames(spec));
|
2013-02-24 09:14:11 +08:00
|
|
|
};
|
2012-11-02 13:03:09 +08:00
|
|
|
|
2014-01-15 00:55:36 +08:00
|
|
|
PhantomReporter.prototype.getSuiteNames = function(spec) {
|
|
|
|
var suiteNames = [];
|
|
|
|
var suite = spec.suite;
|
|
|
|
while (suite) {
|
|
|
|
suiteNames.unshift(suite.description);
|
|
|
|
suite = suite.parentSuite;
|
|
|
|
}
|
|
|
|
return suiteNames;
|
2012-11-02 13:03:09 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
PhantomReporter.prototype.resultsForSpecs = function(specIds){
|
|
|
|
var results = {};
|
|
|
|
for (var i = 0; i < specIds.length; i++) {
|
|
|
|
var specId = specIds[i];
|
|
|
|
results[specId] = this.summarizeResult_(this.results_[specId]);
|
|
|
|
}
|
|
|
|
return results;
|
|
|
|
};
|
|
|
|
|
|
|
|
PhantomReporter.prototype.summarizeResult_ = function(result){
|
|
|
|
var summaryMessages = [];
|
|
|
|
var messagesLength = result.messages.length;
|
|
|
|
for (var messageIndex = 0; messageIndex < messagesLength; messageIndex++) {
|
|
|
|
var resultMessage = result.messages[messageIndex];
|
|
|
|
summaryMessages.push({
|
|
|
|
text: resultMessage.type === 'log' ? resultMessage.toString() : jasmine.undefined,
|
|
|
|
passed: resultMessage.passed ? resultMessage.passed() : true,
|
|
|
|
type: resultMessage.type,
|
|
|
|
message: resultMessage.message,
|
|
|
|
trace: {
|
|
|
|
stack: resultMessage.passed && !resultMessage.passed() ? resultMessage.trace.stack : jasmine.undefined
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
return {
|
|
|
|
result : result.result,
|
|
|
|
messages : summaryMessages
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
2013-02-24 09:14:11 +08:00
|
|
|
function getNestedSuiteName(suite, sep) {
|
2013-01-08 05:39:40 +08:00
|
|
|
var names = [];
|
|
|
|
while (suite) {
|
|
|
|
names.unshift(suite.description);
|
|
|
|
suite = suite.parentSuite;
|
|
|
|
}
|
2013-02-24 09:14:11 +08:00
|
|
|
return names.join(sep ? sep : ' ');
|
2013-01-08 05:39:40 +08:00
|
|
|
}
|
|
|
|
|
2013-01-09 03:28:26 +08:00
|
|
|
function getTopLevelSuiteId(suite) {
|
2013-01-08 21:09:05 +08:00
|
|
|
var id;
|
|
|
|
while (suite) {
|
|
|
|
id = suite.id;
|
|
|
|
suite = suite.parentSuite;
|
|
|
|
}
|
|
|
|
return id;
|
|
|
|
}
|
|
|
|
|
2013-01-09 03:28:26 +08:00
|
|
|
PhantomReporter.prototype.generateJUnitSummary = function(runner) {
|
2013-01-08 21:09:05 +08:00
|
|
|
var consolidatedSuites = {},
|
2013-03-28 20:59:27 +08:00
|
|
|
suites = map(runner.suites(), function(suite) {
|
2013-01-09 03:28:26 +08:00
|
|
|
var failures = 0;
|
|
|
|
|
2013-03-28 20:59:27 +08:00
|
|
|
var testcases = map(suite.specs(), function(spec) {
|
2013-01-09 03:28:26 +08:00
|
|
|
var failureMessages = [];
|
2013-07-31 11:53:55 +08:00
|
|
|
var specResults = spec.results();
|
|
|
|
var resultsItems = specResults.items_;
|
|
|
|
var resultsItemCount = resultsItems.length;
|
|
|
|
|
|
|
|
if (specResults.failedCount) {
|
2013-01-09 03:28:26 +08:00
|
|
|
failures++;
|
2013-07-31 11:53:55 +08:00
|
|
|
|
|
|
|
for (var ii = 0; ii < resultsItemCount; ii++) {
|
2013-03-28 08:04:02 +08:00
|
|
|
var expectation = resultsItems[ii];
|
2013-01-09 03:28:26 +08:00
|
|
|
if (!expectation.passed()) {
|
|
|
|
failureMessages.push(expectation.message);
|
|
|
|
}
|
2013-03-28 20:54:47 +08:00
|
|
|
}
|
2013-01-08 21:09:05 +08:00
|
|
|
}
|
2013-01-09 03:28:26 +08:00
|
|
|
return {
|
2013-07-31 11:53:55 +08:00
|
|
|
assertions: resultsItemCount,
|
2013-01-09 03:28:26 +08:00
|
|
|
className: getNestedSuiteName(spec.suite),
|
|
|
|
name: spec.description,
|
|
|
|
time: spec.duration / 1000,
|
|
|
|
failureMessages: failureMessages
|
|
|
|
};
|
|
|
|
});
|
|
|
|
|
|
|
|
var data = {
|
|
|
|
name: getNestedSuiteName(suite),
|
|
|
|
time: suite.duration / 1000,
|
|
|
|
timestamp: suite.timestamp,
|
|
|
|
tests: suite.specs().length,
|
|
|
|
errors: 0, // TODO: These exist in the JUnit XML but not sure how they map to jasmine things
|
|
|
|
testcases: testcases,
|
|
|
|
failures: failures
|
|
|
|
};
|
|
|
|
|
|
|
|
if (suite.parentSuite) {
|
|
|
|
consolidatedSuites[getTopLevelSuiteId(suite)].push(data);
|
|
|
|
} else {
|
|
|
|
consolidatedSuites[suite.id] = [data];
|
|
|
|
}
|
|
|
|
return data;
|
|
|
|
});
|
2013-01-08 21:09:05 +08:00
|
|
|
|
|
|
|
return {
|
|
|
|
suites: suites,
|
|
|
|
consolidatedSuites: consolidatedSuites
|
|
|
|
};
|
2013-01-08 05:39:40 +08:00
|
|
|
};
|
|
|
|
|
2012-11-02 13:03:09 +08:00
|
|
|
jasmine.getEnv().addReporter( new PhantomReporter() );
|
|
|
|
}());
|