File: lib/loader/junit.js
// Copyright 2014, Yahoo! Inc.
// Copyrights licensed under the Mit License. See the accompanying LICENSE file for terms.
var AbstractLoader = require('../abstractLoader');
var sax = require('sax');
var fs = require('fs');
var Promise = require('promise');
/**
* @class JUnitLoader
* @extends AbstractLoader
* @constructor
*
* @property {object} _childNode
*/
var JUnitLoader = AbstractLoader.extend(
{
/**
* Starts the current entry
*
* @method _startEntry
* @param {EventReporter} reporter
* @param {object} entry
* @param {string[]} parentIds
* @private
*/
_startEntry: function (reporter, entry, parentIds) {
var parentId = parentIds[parentIds.length - 1];
if (['testsuites', 'testsuite'].indexOf(entry.name) !== -1) {
reporter.suiteStart(entry.id, parentId, entry.attributes.name || 'Untitled Suite');
}
else if ('testcase' === entry.name) {
this._childNode = null;
reporter.testStart(entry.id, parentId, entry.attributes.name || 'Untitled Test');
}
parentIds.push(entry.id);
},
/**
* Completes the current entry
*
* @method _completeEntry
* @param {EventReporter} reporter
* @param {object[]} stack
* @param {string[]} parentIds
* @private
*/
_completeEntry: function (reporter, stack, parentIds) {
var entry = stack.pop();
parentIds.pop();
if (['testsuites', 'testsuite'].indexOf(entry.name) !== -1) {
reporter.suiteEnd(entry.id);
} else if (entry.name === 'testcase') {
if (this._childNode && (['failure', 'error', 'skipped'].indexOf(this._childNode.name) !== -1)) {
if (this._childNode.name === 'failure') {
reporter.testFailed(entry.id, this._childNode.attributes.type, this._childNode.attributes.message);
} else if (this._childNode.name === 'error') {
reporter.testError(entry.id, this._childNode.attributes.type, this._childNode.attributes.message);
} else if (this._childNode.name === 'skipped') {
if (this._childNode.attributes.type === 'undefined') {
reporter.testUndefined(entry.id);
} else if (this._childNode.attributes.type === 'incomplete') {
reporter.testIncomplete(entry.id);
} else {
reporter.testSkipped(entry.id, this._childNode.attributes.message || this._childNode.attributes.type);
}
}
} else {
reporter.testPassed(entry.id);
}
} else {
this._childNode = entry;
}
},
/**
* Creates a new stub
*
* @method _createNewStub
* @return {object}
* @private
*/
_createNewStub: function () {
return {
id: this.newId() + '',
attributes: {},
name: null
};
},
/**
* Processes a single file
*
* @method _processFile
* @param {string} parentId
* @param {string} file
* @return {Promise}
* @private
*/
_processFile: function (parentId, file) {
var reporter = this.getReporter();
this._childNode = null;
return new Promise(function (resolve, reject) {
fs.readFile(file, function (err, data) {
var parser,
stack = [],
parentIds = [parentId],
entry = this._createNewStub();
if (err) {
reject(err);
} else {
parser = sax.parser(true);
parser.onerror = function (e) {
reject(e);
}.bind(this);
parser.onopentag = function (node) {
entry = this._createNewStub();
stack.push(entry);
entry.name = node.name;
entry.attributes = node.attributes;
this._startEntry(reporter, entry, parentIds);
}.bind(this);
parser.onclosetag = function () {
this._completeEntry(reporter, stack, parentIds);
}.bind(this);
parser.onend = function () {
resolve();
}.bind(this);
parser.write(data.toString('utf-8')).close();
}
}.bind(this));
}.bind(this));
}
});
module.exports = JUnitLoader;