From eef641b807d7b6f446854c4bea0f5d1a887bd71a Mon Sep 17 00:00:00 2001 From: fc-franz Date: Fri, 4 Nov 2016 19:01:28 +0100 Subject: [PATCH] feat: add flowId to avoid unstable teamcity output --- index.js | 37 ++++++++++++++++++++++++++++--------- test/reporter.spec.js | 26 ++++++++++++++++---------- 2 files changed, 44 insertions(+), 19 deletions(-) diff --git a/index.js b/index.js index c6aa519..e1abd83 100644 --- a/index.js +++ b/index.js @@ -18,12 +18,28 @@ var escapeMessage = function (message) { .replace(/\]/g, '|]') } +var hashString = function (s) { + var hash = 0 + var i + var chr + var len + + if (s === 0) return hash + for (i = 0, len = s.length; i < len; i++) { + chr = s.charCodeAt(i) + hash = ((hash << 5) - hash) + chr + hash |= 0 + } + return hash +} + var formatMessage = function () { var args = Array.prototype.slice.call(arguments) for (var i = args.length - 1; i > 0; i--) { args[i] = escapeMessage(args[i]) } + return util.format.apply(null, args) + '\n' } @@ -33,21 +49,22 @@ var TeamcityReporter = function (baseReporterDecorator) { this.adapters = [fs.writeSync.bind(fs.writeSync, 1)] - 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.BLOCK_OPENED = "##teamcity[blockOpened name='%s']" - this.BLOCK_CLOSED = "##teamcity[blockClosed name='%s']" + this.TEST_IGNORED = "##teamcity[testIgnored name='%s' flowId='']" + this.SUITE_START = "##teamcity[testSuiteStarted name='%s' flowId='']" + this.SUITE_END = "##teamcity[testSuiteFinished name='%s' flowId='']" + this.TEST_START = "##teamcity[testStarted name='%s' flowId='']" + this.TEST_FAILED = "##teamcity[testFailed name='%s' message='FAILED' details='%s' flowId='']" + this.TEST_END = "##teamcity[testFinished name='%s' duration='%s' flowId='']" + this.BLOCK_OPENED = "##teamcity[blockOpened name='%s' flowId='']" + this.BLOCK_CLOSED = "##teamcity[blockClosed name='%s' flowId='']" var reporter = this var initializeBrowser = function (browser) { reporter.browserResults[browser.id] = { name: browser.name, log: [], - lastSuite: null + lastSuite: null, + flowId: 'karmaTC' + hashString(browser.name + ((new Date()).getTime())) + browser.id } } @@ -124,6 +141,8 @@ var TeamcityReporter = function (baseReporterDecorator) { this.flushLogs = function (browserResult) { while (browserResult.log.length > 0) { var line = browserResult.log.shift() + line = line.replace("flowId=''", "flowId='" + browserResult.flowId + "'") + self.write(line) if (browserResult.log.length > 0) { self.write(' ') diff --git a/test/reporter.spec.js b/test/reporter.spec.js index 114812a..2eae43d 100644 --- a/test/reporter.spec.js +++ b/test/reporter.spec.js @@ -1,6 +1,7 @@ var chai = require('chai') var expect = require('chai').expect var sinon = require('sinon') +var clock chai.use(require('sinon-chai')) var TeamCityReporter = require('./../index')['reporter:teamcity'][1] @@ -13,39 +14,44 @@ describe('TeamCity reporter', function () { reporter = new TeamCityReporter(function (instance) { instance.write = sinon.spy() }) + clock = sinon.useFakeTimers(new Date(2050, 9, 1, 0, 0, 0, 0).getTime()) + }) + + afterEach(function () { + clock.restore() }) it('should produce 2 standard messages without browsers', function () { reporter.onRunStart([]) reporter.onRunComplete([]) - expect(reporter.write).to.have.been.calledWith("##teamcity[blockOpened name='JavaScript Unit Tests']\n") - expect(reporter.write).to.have.been.calledWith("##teamcity[blockClosed name='JavaScript Unit Tests']\n") + expect(reporter.write).to.have.been.calledWith("##teamcity[blockOpened name='JavaScript Unit Tests' flowId='']\n") + expect(reporter.write).to.have.been.calledWith("##teamcity[blockClosed name='JavaScript Unit Tests' flowId='']\n") }) it('should produce 2 standard messages without tests', function () { reporter.onRunStart([mosaic]) reporter.onRunComplete([]) - expect(reporter.write).to.have.been.calledWith("##teamcity[blockOpened name='JavaScript Unit Tests']\n") - expect(reporter.write).to.have.been.calledWith("##teamcity[blockClosed name='JavaScript Unit Tests']\n") + expect(reporter.write).to.have.been.calledWith("##teamcity[blockOpened name='JavaScript Unit Tests' flowId='']\n") + expect(reporter.write).to.have.been.calledWith("##teamcity[blockClosed name='JavaScript Unit Tests' flowId='']\n") }) it('should produce messages with one test', function () { reporter.onRunStart([mosaic]) reporter.specSuccess(mosaic, {description: 'SampleTest', time: 2, suite: ['Suite 1']}) reporter.onRunComplete([]) - expect(reporter.write).to.have.been.calledWith("##teamcity[blockOpened name='JavaScript Unit Tests']\n") - expect(reporter.write).to.have.been.calledWith("##teamcity[blockClosed name='JavaScript Unit Tests']\n") + expect(reporter.write).to.have.been.calledWith("##teamcity[blockOpened name='JavaScript Unit Tests' flowId='']\n") + expect(reporter.write).to.have.been.calledWith("##teamcity[blockClosed name='JavaScript Unit Tests' flowId='']\n") expect(reporter.write).to.have.been.calledWith( - "##teamcity[testSuiteStarted name='Suite 1.Mosaic']\n" + "##teamcity[testSuiteStarted name='Suite 1.Mosaic' flowId='karmaTC-1448140806id']\n" ) expect(reporter.write).to.have.been.calledWith( - "##teamcity[testStarted name='SampleTest']\n" + "##teamcity[testStarted name='SampleTest' flowId='karmaTC-1448140806id']\n" ) expect(reporter.write).to.have.been.calledWith( - "##teamcity[testFinished name='SampleTest' duration='2']\n" + "##teamcity[testFinished name='SampleTest' duration='2' flowId='karmaTC-1448140806id']\n" ) expect(reporter.write).to.have.been.calledWith( - "##teamcity[testSuiteFinished name='Suite 1.Mosaic']\n" + "##teamcity[testSuiteFinished name='Suite 1.Mosaic' flowId='karmaTC-1448140806id']\n" ) }) })