Merge branch 'issue/11' of https://github.com/vitch/grunt-contrib-jasmine
This commit is contained in:
commit
81d45689d0
@ -62,6 +62,14 @@ Default: `{}`
|
|||||||
|
|
||||||
These options will be passed to your template as an 'options' hash so that you can provide settings to your template.
|
These options will be passed to your template as an 'options' hash so that you can provide settings to your template.
|
||||||
|
|
||||||
|
## options.junit
|
||||||
|
Type: `Object`
|
||||||
|
Default: `{}`
|
||||||
|
|
||||||
|
Set `options.junit.path` to generate JUnit compatible XML from the task (for use in a CI system such as Jenkins).
|
||||||
|
|
||||||
|
Set `options.junit.consolidate` to consolidate the generated XML files so that there is one file per top level suite.
|
||||||
|
|
||||||
# Flags
|
# Flags
|
||||||
|
|
||||||
Name: `build`
|
Name: `build`
|
||||||
|
@ -32,7 +32,8 @@ module.exports = function(grunt) {
|
|||||||
|
|
||||||
var runners = {
|
var runners = {
|
||||||
default : __dirname + '/jasmine/templates/DefaultRunner.tmpl',
|
default : __dirname + '/jasmine/templates/DefaultRunner.tmpl',
|
||||||
requirejs : __dirname + '/jasmine/templates/RequireJSRunner.tmpl'
|
requirejs : __dirname + '/jasmine/templates/RequireJSRunner.tmpl',
|
||||||
|
junit : __dirname + '/jasmine/templates/JUnit.tmpl'
|
||||||
};
|
};
|
||||||
|
|
||||||
var runnerOptions = {
|
var runnerOptions = {
|
||||||
@ -53,7 +54,8 @@ module.exports = function(grunt) {
|
|||||||
host : '',
|
host : '',
|
||||||
template: 'default',
|
template: 'default',
|
||||||
templateOptions : {},
|
templateOptions : {},
|
||||||
phantomjs : {}
|
phantomjs : {},
|
||||||
|
junit: {}
|
||||||
});
|
});
|
||||||
|
|
||||||
grunt.util._.defaults(options.templateOptions, runnerOptions[options.template] || {});
|
grunt.util._.defaults(options.templateOptions, runnerOptions[options.template] || {});
|
||||||
@ -143,13 +145,14 @@ module.exports = function(grunt) {
|
|||||||
grunt.event.emit.apply(grunt.event, args);
|
grunt.event.emit.apply(grunt.event, args);
|
||||||
});
|
});
|
||||||
|
|
||||||
phantomjs.on('jasmine.writeFile',function(type,filename, xml){
|
// Not used?
|
||||||
var dir = options[type] && options[type].output;
|
// phantomjs.on('jasmine.writeFile',function(type,filename, xml){
|
||||||
if (dir) {
|
// var dir = options[type] && options[type].output;
|
||||||
grunt.file.mkdir(dir);
|
// if (dir) {
|
||||||
grunt.file.write(path.join(dir, filename), xml);
|
// grunt.file.mkdir(dir);
|
||||||
}
|
// grunt.file.write(path.join(dir, filename), xml);
|
||||||
});
|
// }
|
||||||
|
// });
|
||||||
|
|
||||||
|
|
||||||
phantomjs.on('jasmine.reportRunnerStarting',function(suites) {
|
phantomjs.on('jasmine.reportRunnerStarting',function(suites) {
|
||||||
@ -203,6 +206,46 @@ module.exports = function(grunt) {
|
|||||||
status.skipped += skippedAssertions;
|
status.skipped += skippedAssertions;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
phantomjs.on('jasmine.reportJUnitResults',function(junitData){
|
||||||
|
if (options.junit && options.junit.path) {
|
||||||
|
|
||||||
|
if (options.junit.consolidate) {
|
||||||
|
|
||||||
|
grunt.util._(junitData.consolidatedSuites).each(
|
||||||
|
function(suites)
|
||||||
|
{
|
||||||
|
grunt.file.copy(runners.junit, path.join(options.junit.path, 'TEST-' + suites[0].name.replace(/[^\w]/g, '') + '.xml'), {
|
||||||
|
process: function(src) {
|
||||||
|
return grunt.util._.template(
|
||||||
|
src,
|
||||||
|
{
|
||||||
|
testsuites: suites
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
junitData.suites.forEach(
|
||||||
|
function(suiteData)
|
||||||
|
{
|
||||||
|
grunt.file.copy(runners.junit, path.join(options.junit.path, 'TEST-' + suiteData.name.replace(/[^\w]/g, '') + '.xml'), {
|
||||||
|
process: function(src) {
|
||||||
|
return grunt.util._.template(
|
||||||
|
src,
|
||||||
|
{
|
||||||
|
testsuites: [suiteData]
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
phantomjs.on('jasmine.done',function(elapsed){
|
phantomjs.on('jasmine.done',function(elapsed){
|
||||||
phantomjs.halt();
|
phantomjs.halt();
|
||||||
status.duration = elapsed;
|
status.duration = elapsed;
|
||||||
@ -219,6 +262,3 @@ module.exports = function(grunt) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
94
tasks/jasmine/reporters/JUnitDataReporter.js
Normal file
94
tasks/jasmine/reporters/JUnitDataReporter.js
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
/*global jasmine */
|
||||||
|
(function()
|
||||||
|
{
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
function getNestedSuiteName(suite)
|
||||||
|
{
|
||||||
|
var names = [];
|
||||||
|
while (suite) {
|
||||||
|
names.unshift(suite.description);
|
||||||
|
suite = suite.parentSuite;
|
||||||
|
}
|
||||||
|
return names.join(' ');
|
||||||
|
}
|
||||||
|
|
||||||
|
function getTopLevelSuiteId(suite)
|
||||||
|
{
|
||||||
|
var id;
|
||||||
|
while (suite) {
|
||||||
|
id = suite.id;
|
||||||
|
suite = suite.parentSuite;
|
||||||
|
}
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
jasmine.JUnitDataReporter = function()
|
||||||
|
{
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
jasmine.JUnitDataReporter.prototype = {
|
||||||
|
reportRunnerStarting: function(runner) {
|
||||||
|
},
|
||||||
|
reportRunnerResults: function(runner) {
|
||||||
|
var suitesById = {},
|
||||||
|
suites = runner.suites().map(
|
||||||
|
function(suite)
|
||||||
|
{
|
||||||
|
var failures = 0,
|
||||||
|
data = {
|
||||||
|
topLevelSuiteId: getTopLevelSuiteId(suite),
|
||||||
|
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: suite.specs().map(
|
||||||
|
function(spec)
|
||||||
|
{
|
||||||
|
var failureMessages = [];
|
||||||
|
if (spec.results().failedCount) {
|
||||||
|
failures ++;
|
||||||
|
spec.results().items_.forEach(
|
||||||
|
function(expectation)
|
||||||
|
{
|
||||||
|
if (!expectation.passed()) {
|
||||||
|
failureMessages.push(expectation.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
assertions: spec.results().items_.length,
|
||||||
|
className: getNestedSuiteName(spec.suite),
|
||||||
|
name: spec.description,
|
||||||
|
time: spec.duration / 1000,
|
||||||
|
failureMessages: failureMessages
|
||||||
|
};
|
||||||
|
}
|
||||||
|
)
|
||||||
|
};
|
||||||
|
data.failures = failures;
|
||||||
|
suitesById[suite.id] = data;
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
console.log('Suites:', suites);
|
||||||
|
},
|
||||||
|
reportSuiteResults: function(suite) {
|
||||||
|
suite.timestamp = new Date();
|
||||||
|
suite.duration = suite.timestamp.getTime() - suite.specs()[0].startTime;
|
||||||
|
},
|
||||||
|
reportSpecStarting: function(spec) {
|
||||||
|
spec.startTime = (new Date()).getTime();
|
||||||
|
},
|
||||||
|
reportSpecResults: function(spec) {
|
||||||
|
spec.duration = (new Date()).getTime() - spec.startTime;
|
||||||
|
},
|
||||||
|
log: function(str) {
|
||||||
|
console.log(str);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}());
|
@ -40,6 +40,7 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
PhantomReporter.prototype.reportSpecStarting = function(spec) {
|
PhantomReporter.prototype.reportSpecStarting = function(spec) {
|
||||||
|
spec.startTime = (new Date()).getTime();
|
||||||
var message = {
|
var message = {
|
||||||
suite : {
|
suite : {
|
||||||
description : spec.suite.description
|
description : spec.suite.description
|
||||||
@ -84,14 +85,19 @@
|
|||||||
var specIds = runner.specs().map(function(a){return a.id;});
|
var specIds = runner.specs().map(function(a){return a.id;});
|
||||||
var summary = this.resultsForSpecs(specIds);
|
var summary = this.resultsForSpecs(specIds);
|
||||||
phantom.sendMessage('jasmine.reportRunnerResults',summary);
|
phantom.sendMessage('jasmine.reportRunnerResults',summary);
|
||||||
|
phantom.sendMessage('jasmine.reportJUnitResults', this.generateJUnitSummary_(runner));
|
||||||
phantom.sendMessage('jasmine.done.PhantomReporter');
|
phantom.sendMessage('jasmine.done.PhantomReporter');
|
||||||
};
|
};
|
||||||
|
|
||||||
PhantomReporter.prototype.reportSuiteResults = function(suite) {
|
PhantomReporter.prototype.reportSuiteResults = function(suite) {
|
||||||
|
if (suite.specs().length) {
|
||||||
|
suite.timestamp = new Date();
|
||||||
|
suite.duration = suite.timestamp.getTime() - suite.specs()[0].startTime;
|
||||||
phantom.sendMessage('jasmine.reportSuiteResults',{
|
phantom.sendMessage('jasmine.reportSuiteResults',{
|
||||||
description : suite.description,
|
description : suite.description,
|
||||||
results : suite.results()
|
results : suite.results()
|
||||||
});
|
});
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
function stringify(obj) {
|
function stringify(obj) {
|
||||||
@ -130,6 +136,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
PhantomReporter.prototype.reportSpecResults = function(spec) {
|
PhantomReporter.prototype.reportSpecResults = function(spec) {
|
||||||
|
spec.duration = (new Date()).getTime() - spec.startTime;
|
||||||
var _results = spec.results();
|
var _results = spec.results();
|
||||||
var results = {
|
var results = {
|
||||||
description : _results.description,
|
description : _results.description,
|
||||||
@ -189,5 +196,78 @@
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function getNestedSuiteName(suite)
|
||||||
|
{
|
||||||
|
var names = [];
|
||||||
|
while (suite) {
|
||||||
|
names.unshift(suite.description);
|
||||||
|
suite = suite.parentSuite;
|
||||||
|
}
|
||||||
|
return names.join(' ');
|
||||||
|
}
|
||||||
|
|
||||||
|
function getTopLevelSuiteId(suite)
|
||||||
|
{
|
||||||
|
var id;
|
||||||
|
while (suite) {
|
||||||
|
id = suite.id;
|
||||||
|
suite = suite.parentSuite;
|
||||||
|
}
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
PhantomReporter.prototype.generateJUnitSummary_ = function(runner) {
|
||||||
|
var consolidatedSuites = {},
|
||||||
|
suites = runner.suites().map(
|
||||||
|
function(suite)
|
||||||
|
{
|
||||||
|
var failures = 0,
|
||||||
|
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: suite.specs().map(
|
||||||
|
function(spec)
|
||||||
|
{
|
||||||
|
var failureMessages = [];
|
||||||
|
if (spec.results().failedCount) {
|
||||||
|
failures ++;
|
||||||
|
spec.results().items_.forEach(
|
||||||
|
function(expectation)
|
||||||
|
{
|
||||||
|
if (!expectation.passed()) {
|
||||||
|
failureMessages.push(expectation.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
assertions: spec.results().items_.length,
|
||||||
|
className: getNestedSuiteName(spec.suite),
|
||||||
|
name: spec.description,
|
||||||
|
time: spec.duration / 1000,
|
||||||
|
failureMessages: failureMessages
|
||||||
|
};
|
||||||
|
}
|
||||||
|
)
|
||||||
|
};
|
||||||
|
data.failures = failures;
|
||||||
|
if (suite.parentSuite) {
|
||||||
|
consolidatedSuites[getTopLevelSuiteId(suite)].push(data);
|
||||||
|
} else {
|
||||||
|
consolidatedSuites[suite.id] = [data];
|
||||||
|
}
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
return {
|
||||||
|
suites: suites,
|
||||||
|
consolidatedSuites: consolidatedSuites
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
jasmine.getEnv().addReporter( new PhantomReporter() );
|
jasmine.getEnv().addReporter( new PhantomReporter() );
|
||||||
}());
|
}());
|
||||||
|
14
tasks/jasmine/templates/JUnit.tmpl
Normal file
14
tasks/jasmine/templates/JUnit.tmpl
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
|
<testsuites>
|
||||||
|
<% testsuites.forEach(function(testsuite) { %>
|
||||||
|
<testsuite name="<%- testsuite.name %>" errors="<%= testsuite.errors %>" tests="<%= testsuite.tests %>" failures="<%= testsuite.failures %>" time="<%= testsuite.time %>" timestamp="<%= testsuite.timestamp %>">
|
||||||
|
<% testsuite.testcases.forEach(function(testcase) { %>
|
||||||
|
<testcase assertions="<%= testcase.assertions %>" classname="<%- testcase.className %>" name="<%- testcase.name %>" time="<%= testcase.time %>">
|
||||||
|
<% testcase.failureMessages.forEach(function(message) { %>
|
||||||
|
<failure><%= message %></failure>
|
||||||
|
<% }) %>
|
||||||
|
</testcase>
|
||||||
|
<% }) %>
|
||||||
|
</testsuite>
|
||||||
|
<% }) %>
|
||||||
|
</testsuites>
|
Loading…
Reference in New Issue
Block a user