From 03e700ae2234ca7ddb8f9235343e3b0c80868bbd Mon Sep 17 00:00:00 2001 From: Eldar Jafarov Date: Fri, 21 Dec 2012 22:51:42 +0200 Subject: [PATCH] feat: add Teamcity reporter --- lib/reporter.js | 1 + lib/reporters/Teamcity.js | 125 +++++++++++++++++++++++++++++++++ test/client/testacular.conf.js | 2 +- 3 files changed, 127 insertions(+), 1 deletion(-) create mode 100644 lib/reporters/Teamcity.js diff --git a/lib/reporter.js b/lib/reporter.js index e45f6e4ad..398744b9c 100644 --- a/lib/reporter.js +++ b/lib/reporter.js @@ -65,6 +65,7 @@ exports.DotsColor = require('./reporters/DotsColor'); exports.ProgressColor = require('./reporters/ProgressColor'); exports.JUnit = require('./reporters/JUnit'); exports.Coverage = require('./reporters/Coverage'); +exports.Teamcity = exports.TeamcityColor = require('./reporters/Teamcity'); exports.Growl = require('./reporters/Growl'); exports.createReporters = createReporters; diff --git a/lib/reporters/Teamcity.js b/lib/reporters/Teamcity.js new file mode 100644 index 000000000..afbcf0cdc --- /dev/null +++ b/lib/reporters/Teamcity.js @@ -0,0 +1,125 @@ +var BaseReporter = require('./Base'); +var util = require('util'); + +var escTCString = function (message) { + if(!message) { + return ''; + } + + return message. + replace(/\|/g, '||'). + replace(/\'/g, '|\''). + replace(/\n/g, '|n'). + replace(/\r/g, '|r'). + replace(/\u0085/g, '|x'). + replace(/\u2028/g, '|l'). + replace(/\u2029/g, '|p'). + replace(/\[/g, '|['). + replace(/\]/g, '|]'); +}; + +var getTestName = function (result) { + return result.slice(1).join(' '); +} + +var TeamcityReporter = function(formatError, reportSlow) { + BaseReporter.call(this, formatError, reportSlow); + + this.onRunStart = function(browsers) { + this._browsers = browsers; + this.browserResults = {}; + }; + + this.writeCommonMsg = function(msg) { + this.write('\n' + msg); + this._dotsCount = 0; + }; + + this.specSuccess = function(browser, result) { + var browseResult = this.checkNewSuit(browser, result); + var testName = getTestName(result.suite); + + browseResult.log.push(util.format(this.TEST_START, escTCString(testName))); + browseResult.log.push(util.format(this.TEST_END, + escTCString(testName), result.time)); + }; + + this.specFailure = function(browser, result) { + var browseResult = this.checkNewSuit(browser, result); + var testName = getTestName(result.suite); + + browseResult.log.push(util.format(this.TEST_START, escTCString(testName))); + browseResult.log.push(util.format(this.TEST_FAILED, escTCString(testName), + escTCString(JSON.stringify(result.log)))); + browseResult.log.push(util.format(this.TEST_END, + escTCString(testName), result.time)); + }; + + this.specSkipped = function(browser, result) { + var browseResult = this.checkNewSuit(browser, result); + var testName = getTestName(result.suite); + + browseResult.log.push(util.format(this.TEST_IGNORED, escTCString(testName))); + }; + + this.checkNewSuit = function(browser, result) { + var browserResult = this.checkNewBrowser(browser); + var suiteExists = browserResult.suits.indexOf(result.suite[0]) !== -1; + + if(!suiteExists) { + if(browserResult.suits.length > 0) { + browserResult.log.push(util.format(this.SUITE_END, + escTCString(browserResult.suits[browserResult.suits.length - 1]))); + } + browserResult.suits.push(result.suite[0]); + browserResult.log.push(util.format(this.SUITE_START, escTCString(result.suite[0]))); + } + return browserResult; + }; + + this.checkNewBrowser = function(browser) { + if(!this.browserResults[browser.id]) { + this.browserResults[browser.id] = { + log : [], + suits : [] + }; + } + return this.browserResults[browser.id]; + }; + + this.onRunComplete = function(browsers, results) { + var self = this; + + Object.keys(this.browserResults).forEach(function(key) { + var browserResult = self.browserResults[key]; + if(browserResult.suits.length > 0) { + browserResult.log.push(util.format(self.SUITE_END, + escTCString(browserResult.suits[browserResult.suits.length - 1]))); + } + self.write(self.BROWSER_START, key); + self.write(browserResult.log.join('\n')); + self.write(self.BROWSER_END, key); + }); + + this.writeCommonMsg(browsers.map(this.renderBrowser).join('\n') + '\n'); + + if (browsers.length > 1 && !results.disconnected && !results.error) { + if (!results.failed) { + this.write(this.TOTAL_SUCCESS, results.success); + } else { + this.write(this.TOTAL_FAILED, results.failed, results.success); + } + } + }; + + this.TEST_IGNORED = '##teamcity[testIgnored name=\'%s\']'; + this.SUITE_START = '##teamcity[testSuiteStarted name=\'%s\']'; + this.SUITE_END = '##teamcity[testSuiteFinished name=\'%s\']'; + this.TEST_START = '##teamcity[testStarted name=\'%s\']'; + this.TEST_FAILED = '##teamcity[testFailed name=\'%s\' message=\'FAILED\' details=\'%s\']'; + this.TEST_END = '##teamcity[testFinished name=\'%s\' duration=\'%s\']'; + this.BROWSER_START = '##teamcity[browserStart name=\'%s\']\n'; + this.BROWSER_END = '\n##teamcity[browserEnd name=\'%s\']'; +}; + +module.exports = TeamcityReporter; diff --git a/test/client/testacular.conf.js b/test/client/testacular.conf.js index c0aebda86..7204eb3e8 100644 --- a/test/client/testacular.conf.js +++ b/test/client/testacular.conf.js @@ -25,7 +25,7 @@ exclude = [ ]; // use dots reporter, as travis terminal does not support escaping sequences -// possible values: 'dots', 'progress', 'junit' +// possible values: 'dots', 'progress', 'junit', 'teamcity' // CLI --reporters progress reporters = ['progress', 'junit'];