From 292fe0aac02d3c17be9752512b5011026cbcf4a6 Mon Sep 17 00:00:00 2001 From: Muthu Kumar Date: Tue, 18 Sep 2018 20:30:33 +0530 Subject: [PATCH] [reporters] Added min and fixed xunit reporter --- package.json | 2 +- sample/sample7.test.js | 5 ++- shrinkwrap.yaml | 66 ++++++++++------------------ src/gunner.js | 2 +- src/lib/testrunner.js | 10 ++++- src/reporters/index.js | 1 + src/reporters/min.js | 52 ++++++++++++++++++++++ src/reporters/xunit.js | 116 ++++++++++++++++++++++--------------------------- src/util/constants.js | 13 ++++-- 9 files changed, 151 insertions(+), 116 deletions(-) create mode 100644 src/reporters/min.js diff --git a/package.json b/package.json index 13963b0..fa5a826 100644 --- a/package.json +++ b/package.json @@ -28,7 +28,7 @@ "@codefeathers/iseq": "^1.2.1", "@codefeathers/promise.object": "^0.9.5", "json-stringify-safe": "^5.0.1", - "tap-xunit": "^2.3.0" + "jsontoxml": "^1.0.0" }, "devDependencies": { "babel-cli": "^6.26.0", diff --git a/sample/sample7.test.js b/sample/sample7.test.js index 2b897de..0066e11 100644 --- a/sample/sample7.test.js +++ b/sample/sample7.test.js @@ -6,7 +6,7 @@ const Gunner = require('../es6'); const expect = Gunner.expect; const expectMany = Gunner.expectMany; -const gunner = new Gunner({ name: 'sample tests' }); +const gunner = new Gunner('sample tests'); const a = 1; // gunner.before(Gunner.Start, () => console.log('Started tests!')); @@ -99,4 +99,5 @@ gunner.test('(should fail) should not resolve to 5', () => const trace = process.argv.slice(2).indexOf('--trace') !== -1; const reporter = process.argv.slice(2).indexOf('--log') !== -1; -gunner.run({ trace, reporter }).then(console.log); +gunner.run({ trace, reporter }); +// gunner.run({ reporter:'xunit' }); diff --git a/shrinkwrap.yaml b/shrinkwrap.yaml index 0c01787..d8d4d2e 100644 --- a/shrinkwrap.yaml +++ b/shrinkwrap.yaml @@ -2,7 +2,7 @@ dependencies: '@codefeathers/iseq': 1.2.1 '@codefeathers/promise.object': 0.9.5 json-stringify-safe: 5.0.1 - tap-xunit: 2.3.0 + jsontoxml: 1.0.0 devDependencies: babel-cli: 6.26.0 babel-plugin-transform-object-rest-spread: 6.26.0 @@ -121,6 +121,7 @@ packages: /argparse/1.0.10: dependencies: sprintf-js: 1.0.3 + dev: true resolution: integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== /arr-diff/2.0.0: @@ -1169,6 +1170,7 @@ packages: resolution: integrity: sha512-RszJCAxg/PP6uzXVXL6BsxSXx/B05oJAQ2vkJRjyjrEcNVycaqOmNb5OTxZPE3xa5gwZduqza6L9JOCenh/Ecw== /core-util-is/1.0.2: + dev: true resolution: integrity: sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= /create-ecdh/4.0.3: @@ -1371,11 +1373,6 @@ packages: npm: '>=1.2' resolution: integrity: sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA== - /duplexer/0.1.1: - dev: false - resolution: - integrity: sha1-rOb/gIwc5mtX0ev5eXessCM0z8E= - tarball: 'http://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz' /duplexer2/0.1.4: dependencies: readable-stream: 2.3.6 @@ -1504,6 +1501,7 @@ packages: resolution: integrity: sha512-kapdTCt1bjmspxStVKX6huolXVV5ZfyZguY1lcfhVVZstce3bqxH9mcLzNn3/mlgW6wQ732+0fuG9v7h0ZQoKg== /esprima/4.0.1: + dev: true engines: node: '>=4' hasBin: true @@ -1537,10 +1535,6 @@ packages: node: '>=0.10.0' resolution: integrity: sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs= - /events-to-array/1.1.2: - dev: false - resolution: - integrity: sha1-LUH1Y+H+QA7Uli/hpNXGp1Od9/Y= /events/2.1.0: dev: true engines: @@ -1997,6 +1991,7 @@ packages: resolution: integrity: sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE= /inherits/2.0.3: + dev: true resolution: integrity: sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= /inline-source-map/0.6.2: @@ -2292,6 +2287,7 @@ packages: resolution: integrity: sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA== /isarray/1.0.0: + dev: true resolution: integrity: sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= /isarray/2.0.4: @@ -2330,6 +2326,7 @@ packages: dependencies: argparse: 1.0.10 esprima: 4.0.1 + dev: true hasBin: true resolution: integrity: sha512-PIt2cnwmPfL4hKNwqeiuz4bKfnzHTBv6HyVgjahA6mPLwPDzjDWrplJBMjHUFxku/N3FlmrbyPclad+I+4mJ3A== @@ -2376,6 +2373,12 @@ packages: '0': node >= 0.2.0 resolution: integrity: sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA= + /jsontoxml/1.0.0: + dev: false + engines: + node: '>=0.2.0' + resolution: + integrity: sha512-oOwlpPl8MIQVEm9ejxMPDfRxdX2vNdWxAmI3n+kXa7rt0C6IEsNONDxTmd1A7Zh+Sq5RM4Lov9wm8t5kA+SSMQ== /kind-of/3.2.2: dependencies: is-buffer: 1.1.6 @@ -2434,6 +2437,7 @@ packages: resolution: integrity: sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg== /lodash/4.17.11: + dev: true resolution: integrity: sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg== /loose-envify/1.4.0: @@ -2547,6 +2551,7 @@ packages: integrity: sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0= tarball: 'http://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz' /minimist/1.2.0: + dev: true resolution: integrity: sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ= tarball: 'http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz' @@ -2883,6 +2888,7 @@ packages: resolution: integrity: sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg== /process-nextick-args/2.0.0: + dev: true resolution: integrity: sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw== /process/0.11.10: @@ -2973,6 +2979,7 @@ packages: safe-buffer: 5.1.2 string_decoder: 1.1.1 util-deprecate: 1.0.2 + dev: true resolution: integrity: sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw== tarball: 'http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz' @@ -3163,6 +3170,7 @@ packages: resolution: integrity: sha512-3bjO7UwWfA2CV7lmwYMBzj4fQ6Cq+ftHc2MvUe+WMS7wcdJ1LosDWmdjPQanYp2dBRj572p7PeU81JUxHKOcBA== /safe-buffer/5.1.2: + dev: true resolution: integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== /safe-regex/1.1.0: @@ -3346,6 +3354,7 @@ packages: resolution: integrity: sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw== /sprintf-js/1.0.3: + dev: true resolution: integrity: sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= /static-extend/0.1.2: @@ -3411,6 +3420,7 @@ packages: /string_decoder/1.1.1: dependencies: safe-buffer: 5.1.2 + dev: true resolution: integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== /strip-ansi/3.0.1: @@ -3480,29 +3490,6 @@ packages: node: '>=4.0.0' resolution: integrity: sha512-S7rnFITmBH1EnyKcvxBh1LjYeQMmnZtCXSEbHcH6S0NoKit24ZuFO/T1vDcLdYsLQkM188PVVhQmzKIuThNkKg== - /tap-parser/1.2.2: - dependencies: - events-to-array: 1.1.2 - inherits: 2.0.3 - js-yaml: 3.12.0 - dev: false - hasBin: true - optionalDependencies: - readable-stream: 2.3.6 - resolution: - integrity: sha1-Xi9pcGEfB5x8+FfeHceqG0gN56U= - /tap-xunit/2.3.0: - dependencies: - duplexer: 0.1.1 - minimist: 1.2.0 - tap-parser: 1.2.2 - through2: 2.0.3 - xmlbuilder: 4.2.1 - xtend: 4.0.1 - dev: false - hasBin: true - resolution: - integrity: sha512-YVsURNvn1wfVUWb5wjansxhfbfeo2hOBTUbVgZoaMO8lyZzpiSi9IiZTZ7JG56m6A49LeWjfJIx/SnAre41V/A== /text-table/0.2.0: dev: true resolution: @@ -3516,6 +3503,7 @@ packages: dependencies: readable-stream: 2.3.6 xtend: 4.0.1 + dev: true resolution: integrity: sha1-AARWmzfHx0ujnEPzzteNGtlBQL4= /timers-browserify/1.4.2: @@ -3667,6 +3655,7 @@ packages: resolution: integrity: sha1-K1viOjK2Onyd640PKNSFcko98ZA= /util-deprecate/1.0.2: + dev: true resolution: integrity: sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= /util/0.10.3: @@ -3716,15 +3705,8 @@ packages: node: '>=0.10.0' resolution: integrity: sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c= - /xmlbuilder/4.2.1: - dependencies: - lodash: 4.17.11 - dev: false - engines: - node: '>=0.8.0' - resolution: - integrity: sha1-qlijBBoGb5DqoWwvU4n/GfP0YaU= /xtend/4.0.1: + dev: true engines: node: '>=0.4' resolution: @@ -3741,4 +3723,4 @@ specifiers: browserify: ^16.2.2 eslint: ^5.2.0 json-stringify-safe: ^5.0.1 - tap-xunit: ^2.3.0 + jsontoxml: ^1.0.0 diff --git a/src/gunner.js b/src/gunner.js index 997c438..6e021a8 100644 --- a/src/gunner.js +++ b/src/gunner.js @@ -100,7 +100,7 @@ class Gunner { ? { [options.request]: reporters[options.request].convert(results), - json: results } + default: results } : results); }); } diff --git a/src/lib/testrunner.js b/src/lib/testrunner.js index 00e161d..6fe6993 100644 --- a/src/lib/testrunner.js +++ b/src/lib/testrunner.js @@ -3,10 +3,10 @@ const Gunner = require('../gunner'); Promise.object = require('@codefeathers/promise.object'); -const { performance } = require('perf_hooks'); - const { last, pipe, pick, assignToObject } = require('../util'); +const { eventMap } = require('../util/constants'); +const emitter = require('./emitter'); const buildTestQueue = require('./buildTestQueue'); const findSkip = (skip, unit) => { @@ -65,6 +65,12 @@ const reduceQueue = || result.rejection || result.description}) }; + + emitter.emit( + eventMap[status], + resultObject + ); + acc.results.push(resultObject); } else { diff --git a/src/reporters/index.js b/src/reporters/index.js index 6e1bdd4..7fc3d0e 100644 --- a/src/reporters/index.js +++ b/src/reporters/index.js @@ -3,5 +3,6 @@ module.exports = { default: require('./default'), tap: require('./tap'), xunit: require('./xunit'), + min: require('./min'), }; diff --git a/src/reporters/min.js b/src/reporters/min.js new file mode 100644 index 0000000..aa33b80 --- /dev/null +++ b/src/reporters/min.js @@ -0,0 +1,52 @@ +const { eventMap, eventVerbs } = require('../util/constants'); + +const convert = x => x; + +const count = { + pass: 0, + fail: 0, + skip: 0, + collapse: function() { + return this.pass + this.fail + this.skip; + } +}; + +const clear = () => { + + // clear screen + process.stdout.write('\u001b[2J'); + // set cursor position to top + process.stdout.write('\u001b[1;1H'); + +}; + +const doneHandler = event => { + + clear(); + const mapEvent = eventMap[event.status]; + count[mapEvent]++; + console.log(`${count[mapEvent]} tests ${eventVerbs[mapEvent][2]}` + + ` (total: ${count.collapse()})`); + +}; + +const Min = runner => { + + runner.on('start', () => console.log('Started tests')); + + runner.on('pass', doneHandler); + runner.on('fail', doneHandler); + runner.on('skip', doneHandler); + + runner.on('end', results => { + + clear(); + console.log(`Test suite ${results.name} has done running.`); + console.log('Success ratio:', results.successPercent, '%'); + + }); + +}; + +module.exports = Min; +module.exports.convert = convert; diff --git a/src/reporters/xunit.js b/src/reporters/xunit.js index f8c35ee..49461fe 100644 --- a/src/reporters/xunit.js +++ b/src/reporters/xunit.js @@ -1,72 +1,58 @@ -const tag = (name, attrs, close, content) => { - const end = close ? "/>" : ">"; - const pairs = []; - let tag; - - Object.keys(attrs).forEach(key => { - if (Object.prototype.hasOwnProperty.call(attrs, key)) { - pairs.push(key + '="' + (attrs[key]) + '"'); - } - }); - - tag = "<" + name + (pairs.length ? " " + pairs.join(" ") : "") + end; - if (content) { - tag += content + " { - - const { count, success, failures, skipped } = results; - - return '' + tag( - 'testsuites', - {}, - false, - tag( - 'testsuite', - { - name: results.name, - tests: count, - success: success.length, - failures: failures.length, - skipped: skipped.length, - timestamp: new Date().toUTCString(), - time: (results.duration / 1000) || 0, - }, - false, - results.reduce((acc, r) => { - const close = r.status === 'ok'; - const content = r.status !== 'ok' && - (r.status === 'skip' - ? tag('skipped', {}, true) - : tag( - 'failure', {}, - !r.reason, r.reason ? r.reason : '')); - acc += tag( - 'testcase', - { - name: r.description, - time: (r.duration / 1000) || 0, - }, - close, - content || '' - ); - return acc; - }, '') - ) - ); +const toXML = require('jsontoxml'); + +const toJSON = resultsArray => { + + return { + testsuites: resultsArray.map(results => { + + const { name, count, success, failures, skipped } = results; + + return { + name: 'testsuite', + attrs: { + name, + tests: count, + success: success.length, + failures: failures.length, + skipped: skipped.length, + timestamp: new Date().toUTCString(), + time: (results.duration / 1000) || 0, + }, + children: results.reduce((acc, r) => { + const content = r.status !== 'ok' && + (r.status === 'skip' + ? 'skipped' + : { + name: 'failure', + text: r.reason + ? (r.reason && r.reason.stack) : '' + }); + acc.push({ + name: 'testcase', + attrs: { + name: r.description, + time: (r.duration / 1000) || 0, + }, + ...(typeof content === 'object' + && { text: content && content.stack }), + ...(typeof content === 'object' + && { children: [ content ]}), + }); + return acc; + }, []), + }; + + }) + }; }; -const xunit = runner => { - runner.on("end", results => { +const convert = results => + toXML(toJSON(results), + { xmlHeader: { standalone: true }}); - console.log(convert(results)); - - }); -}; +const xunit = runner => + runner.on("end", results => console.log(convert([ results ]))); module.exports = xunit; module.exports.convert = convert; diff --git a/src/util/constants.js b/src/util/constants.js index c03051e..a412c05 100644 --- a/src/util/constants.js +++ b/src/util/constants.js @@ -1,8 +1,15 @@ -const chalk = require('chalk'); const { EOL } = require('os'); module.exports = { - greenLine: chalk.green('------------------------------------'), - redLine: chalk.red('------------------------------------'), EOL, + eventMap: { + 'ok': 'pass', + 'notOk': 'fail', + 'skip': 'skip', + }, + eventVerbs: { + pass: [ 'pass', 'passing', 'passed' ], + fail: [ 'fail', 'failing', 'failed' ], + skip: [ 'skip', 'skipping', 'skipped' ], + }, };