From 291eb87cb5a53d1cc65610734ba17582ff47c487 Mon Sep 17 00:00:00 2001 From: Alexey Litvinov Date: Fri, 6 May 2016 18:07:18 +0300 Subject: [PATCH 1/4] internal update --- index.js | 144 ++++++++++++++++----------------------------------- package.json | 15 +++--- test.js | 11 ++-- 3 files changed, 58 insertions(+), 112 deletions(-) diff --git a/index.js b/index.js index c264cba..7fca629 100644 --- a/index.js +++ b/index.js @@ -1,6 +1,7 @@ -const inherits = require('util').inherits; -const EventEmitter = require('events').EventEmitter; -const EOL = require('os').EOL; +'use strict'; + +const { inherits } = require('util'); +const { EventEmitter } = require('events'); const o = msg => console.log(msg); @@ -11,105 +12,52 @@ const o = msg => console.log(msg); function WdioTeamcityReporter() { EventEmitter.call(this); - /** - * @param {object} suite - * @param {string} suite.type - * @param {string} suite.title - * @param {string} suite.parent - * @param {boolean} suite.pending - * @param {string} suite.file - * @param {string[]} suite.specs - * @param {string} suite.event - * @param {object} suite.runner - */ - this.on('suite:start', suite => { - o(`##teamcity[testSuiteStarted name='${escape(suite.title)}']`); - }); - - /** - * @param {object} test - * @param {string} test.type - * @param {string} test.title - * @param {string} test.parent - * @param {boolean} test.pending - * @param {string} test.file - * @param {string[]} test.specs - * @param {string} test.event - * @param {object} test.runner - * @param {string} test.specHash - */ - this.on('test:start', test => { - o(`##teamcity[testStarted name='${escape(test.title)}' captureStandardOutput='true']"`); - }); - - /** - * @param {object} test - * @param {string} test.type - * @param {string} test.title - * @param {string} test.parent - * @param {boolean} test.pending - * @param {string} test.file - * @param {string[]} test.specs - * @param {string} test.event - * @param {object} test.runner - * @param {string} test.specHash - */ - this.on('test:end', test => { - o(`##teamcity[testFinished name='${escape(test.title)}']`); - }); - - /** - * @param {object} test - * @param {string} test.type - * @param {object} test.err - * @param {string} test.title - * @param {string} test.parent - * @param {boolean} test.pending - * @param {string} test.file - * @param {string[]} test.specs - * @param {string} test.event - * @param {object} test.runner - * @param {string} test.specHash - */ - this.on('test:fail', test => { - o(`##teamcity[testFailed name='${escape(test.title)}' message='${escape(test.err.message)}' details='${escape(test.err.stack)}']`); - }); - - /** - * @param {object} test - * @param {string} test.type - * @param {string} test.title - * @param {string} test.parent - * @param {boolean} test.pending - * @param {string} test.file - * @param {string[]} test.specs - * @param {string} test.event - * @param {object} test.runner - * @param {string} test.specHash - */ - this.on('test:pending', test => { - o(`##teamcity[testIgnored name='${escape(test.title)}' message='pending']`); - }); - - /** - * @param {object} suite - * @param {string} suite.type - * @param {string} suite.title - * @param {string} suite.parent - * @param {boolean} suite.pending - * @param {string} suite.file - * @param {string[]} suite.specs - * @param {string} suite.event - * @param {object} suite.runner - * @param {string} suite.specHash - */ - this.on('suite:end', suite => { - o(`##teamcity[testSuiteFinished name='${escape(suite.title)}']`); - }); + this.enableRealTimeOutput(); } inherits(WdioTeamcityReporter, EventEmitter); +/** + * Makes it possible to display test results in real-time. + * + * Suite event handler accepts: + * * @param {object} suite + * * @param {string} suite.type + * * @param {string} suite.title + * * @param {string} suite.parent + * * @param {boolean} suite.pending + * * @param {string} suite.file + * * @param {string[]} suite.specs + * * @param {string} suite.event + * * @param {object} suite.runner + * * @param {string} [suite.specHash] is available for the suite:end event + * + * Each test event handler accepts: + * * @param {object} test + * * @param {string} test.type + * * @param {object} [test.err] is available for the test:fail event + * * @param {string} test.title + * * @param {string} test.parent + * * @param {boolean} test.pending + * * @param {string} test.file + * * @param {string[]} test.specs + * * @param {string} test.event + * * @param {object} test.runner + * * @param {string} test.specHash + */ +WdioTeamcityReporter.prototype.enableRealTimeOutput = function () { + const handlers = { + 'suite:start': suite => o(`##teamcity[testSuiteStarted name='${escape(suite.title)}']`), + 'test:start': test => o(`##teamcity[testStarted name='${escape(test.title)}' captureStandardOutput='true']"`), + 'test:end': test => o(`##teamcity[testFinished name='${escape(test.title)}']`), + 'test:fail': test => o(`##teamcity[testFailed name='${escape(test.title)}' message='${escape(test.err.message)}' details='${escape(test.err.stack)}']`), + 'test:pending': test => o(`##teamcity[testIgnored name='${escape(test.title)}' message='pending']`), + 'suite:end': suite => o(`##teamcity[testSuiteFinished name='${escape(suite.title)}']`), + }; + + Object.keys(handlers).forEach(event => this.on(event, handlers[event])); +}; + module.exports = WdioTeamcityReporter; module.exports.reporterName = 'teamcity'; diff --git a/package.json b/package.json index a3acb89..cc0ea17 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wdio-teamcity-reporter", - "version": "1.0.0", + "version": "1.0.1", "description": "WebdriverIO Teamcity reporter", "main": "index.js", "engines": { @@ -10,9 +10,8 @@ "build": "babel index.js --out-file index.js", "cleanup": "git reset --hard", "prepublish": "in-publish && npm run -s build || in-install", - "test": "ava --require babel-register test.js", - "test:n": "ava test.js", - "test:w": "ava --require babel-register --watch test.js" + "test": "faucet --require babel-register test.js", + "test:raw": "faucet test.js" }, "repository": { "type": "git", @@ -28,10 +27,12 @@ }, "homepage": "https://github.com/sullenor/wdio-teamcity-reporter#readme", "devDependencies": { - "ava": "^0.14.0", "babel-cli": "^6.7.5", "babel-preset-es2015": "^6.6.0", "babel-register": "^6.7.2", - "in-publish": "^2.0.0" - } + "faucet": "0.0.1", + "in-publish": "^2.0.0", + "tape": "^4.5.1" + }, + "dependencies": {} } diff --git a/test.js b/test.js index b410a26..0cb2180 100644 --- a/test.js +++ b/test.js @@ -1,5 +1,5 @@ -import test from 'ava'; -import Reporter from './index'; +const test = require('tape'); +const Reporter = require('./index'); const events = [ 'start', @@ -15,11 +15,7 @@ const events = [ 'end', ]; -var reporter; - -test.before(t => { - reporter = new Reporter(); -}); +var reporter = new Reporter(); events.forEach(event => test(event, t => { const data = { @@ -38,4 +34,5 @@ events.forEach(event => test(event, t => { } reporter.emit(event, data); + t.end(); })); From 55b9c57ed40a50950ee93662ac80a5a73ad532e6 Mon Sep 17 00:00:00 2001 From: Alexey Litvinov Date: Fri, 6 May 2016 18:32:14 +0300 Subject: [PATCH 2/4] Added flowId attribute to distinguish separate processes running in parallel see https://confluence.jetbrains.com/display/TCD65/Build+Script+Interaction+with+TeamCity --- index.js | 20 ++++++++++++++------ package.json | 5 ++--- test.js | 1 + 3 files changed, 17 insertions(+), 9 deletions(-) diff --git a/index.js b/index.js index 7fca629..677e822 100644 --- a/index.js +++ b/index.js @@ -44,15 +44,23 @@ inherits(WdioTeamcityReporter, EventEmitter); * * @param {string} test.event * * @param {object} test.runner * * @param {string} test.specHash + * + * In order to distinguish separate processes running in parallel, + * each message should be signed with the unique identifier, + * which should be provided through the flowId attribute. + * So I use specHash for this. + * + * @see https://github.com/webdriverio/webdriverio/blob/16c9dcc7334e1015c48e07f113f00a6b63d31d7f/lib/utils/ReporterStats.js#L119-L127 + * @see https://confluence.jetbrains.com/display/TCD65/Build+Script+Interaction+with+TeamCity */ WdioTeamcityReporter.prototype.enableRealTimeOutput = function () { const handlers = { - 'suite:start': suite => o(`##teamcity[testSuiteStarted name='${escape(suite.title)}']`), - 'test:start': test => o(`##teamcity[testStarted name='${escape(test.title)}' captureStandardOutput='true']"`), - 'test:end': test => o(`##teamcity[testFinished name='${escape(test.title)}']`), - 'test:fail': test => o(`##teamcity[testFailed name='${escape(test.title)}' message='${escape(test.err.message)}' details='${escape(test.err.stack)}']`), - 'test:pending': test => o(`##teamcity[testIgnored name='${escape(test.title)}' message='pending']`), - 'suite:end': suite => o(`##teamcity[testSuiteFinished name='${escape(suite.title)}']`), + 'suite:start': suite => o(`##teamcity[testSuiteStarted name='${escape(suite.title)}' flowId='${escape(suite.specHash)}']`), + 'test:start': test => o(`##teamcity[testStarted name='${escape(test.title)}' captureStandardOutput='true' flowId='${escape(test.specHash)}']"`), + 'test:end': test => o(`##teamcity[testFinished name='${escape(test.title)}'] flowId='${escape(test.specHash)}'`), + 'test:fail': test => o(`##teamcity[testFailed name='${escape(test.title)}' message='${escape(test.err.message)}' details='${escape(test.err.stack)}' flowId='${escape(test.specHash)}']`), + 'test:pending': test => o(`##teamcity[testIgnored name='${escape(test.title)}' message='pending'] flowId='${escape(test.specHash)}'`), + 'suite:end': suite => o(`##teamcity[testSuiteFinished name='${escape(suite.title)}'] flowId='${escape(suite.specHash)}'`), }; Object.keys(handlers).forEach(event => this.on(event, handlers[event])); diff --git a/package.json b/package.json index cc0ea17..a8846af 100644 --- a/package.json +++ b/package.json @@ -10,8 +10,8 @@ "build": "babel index.js --out-file index.js", "cleanup": "git reset --hard", "prepublish": "in-publish && npm run -s build || in-install", - "test": "faucet --require babel-register test.js", - "test:raw": "faucet test.js" + "test": "tape -r babel-register test.js", + "test:raw": "tape test.js" }, "repository": { "type": "git", @@ -30,7 +30,6 @@ "babel-cli": "^6.7.5", "babel-preset-es2015": "^6.6.0", "babel-register": "^6.7.2", - "faucet": "0.0.1", "in-publish": "^2.0.0", "tape": "^4.5.1" }, diff --git a/test.js b/test.js index 0cb2180..1cc16c5 100644 --- a/test.js +++ b/test.js @@ -27,6 +27,7 @@ events.forEach(event => test(event, t => { specs: [''], event: event, runner: {}, + specHash: '98d5f98abe0e1d6b68d654ead0a9ce77', }; if (event.indexOf('fail') > -1) { From 27ad3a188cbe1157a1e1d4e019d075a4bb510e83 Mon Sep 17 00:00:00 2001 From: Alexey Litvinov Date: Fri, 6 May 2016 18:44:47 +0300 Subject: [PATCH 3/4] eslint added --- .eslintrc.json | 31 +++++++++++++++++++++++++++++++ .npmignore | 1 + index.js | 20 ++++++++++---------- package.json | 2 ++ 4 files changed, 44 insertions(+), 10 deletions(-) create mode 100644 .eslintrc.json diff --git a/.eslintrc.json b/.eslintrc.json new file mode 100644 index 0000000..19f3b94 --- /dev/null +++ b/.eslintrc.json @@ -0,0 +1,31 @@ +{ + "env": { + "es6": true, + "node": true + }, + "extends": "eslint:recommended", + "rules": { + "comma-dangle": [ + "error", + "always-multiline" + ], + "indent": [ + "error", + 2 + ], + "linebreak-style": [ + "error", + "unix" + ], + "no-console": "off", + "no-control-regex": "off", + "quotes": [ + "error", + "single" + ], + "semi": [ + "error", + "always" + ] + } +} diff --git a/.npmignore b/.npmignore index 4b2468b..693634c 100644 --- a/.npmignore +++ b/.npmignore @@ -1,5 +1,6 @@ .babelrc .editorconfig +.eslintrc.json .gitignore .npmignore .travis.yml diff --git a/index.js b/index.js index 677e822..3fbcfdd 100644 --- a/index.js +++ b/index.js @@ -82,14 +82,14 @@ function escape(str) { return str .toString() - .replace(/\x1B.*?m/g, "") - .replace(/\|/g, "||") - .replace(/\n/g, "|n") - .replace(/\r/g, "|r") - .replace(/\[/g, "|[") - .replace(/\]/g, "|]") - .replace(/\u0085/g, "|x") - .replace(/\u2028/g, "|l") - .replace(/\u2029/g, "|p") - .replace(/'/g, "|'"); + .replace(/\x1B.*?m/g, '') + .replace(/\|/g, '||') + .replace(/\n/g, '|n') + .replace(/\r/g, '|r') + .replace(/\[/g, '|[') + .replace(/\]/g, '|]') + .replace(/\u0085/g, '|x') + .replace(/\u2028/g, '|l') + .replace(/\u2029/g, '|p') + .replace(/'/g, '|\''); } diff --git a/package.json b/package.json index a8846af..6c2548f 100644 --- a/package.json +++ b/package.json @@ -10,6 +10,7 @@ "build": "babel index.js --out-file index.js", "cleanup": "git reset --hard", "prepublish": "in-publish && npm run -s build || in-install", + "lint": "eslint *.js", "test": "tape -r babel-register test.js", "test:raw": "tape test.js" }, @@ -30,6 +31,7 @@ "babel-cli": "^6.7.5", "babel-preset-es2015": "^6.6.0", "babel-register": "^6.7.2", + "eslint": "^2.9.0", "in-publish": "^2.0.0", "tape": "^4.5.1" }, From 4943c15d767433ae1317ee0947ca11cb2fcd00de Mon Sep 17 00:00:00 2001 From: Alexey Litvinov Date: Fri, 6 May 2016 18:45:33 +0300 Subject: [PATCH 4/4] added node.js 6 to travis --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index ac16eac..d53cdaa 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,5 +3,6 @@ notifications: language: node_js node_js: + - "6" - "4" - "0.12"