feat: ✨ Created a mini nodeJS server with NewMan for testing without PostMan GUI.
This will mimic a run in a CD/CI environment or docker container.
This commit is contained in:
79
node_modules/newman/lib/reporters/cli/cli-utils-symbols.js
generated
vendored
Normal file
79
node_modules/newman/lib/reporters/cli/cli-utils-symbols.js
generated
vendored
Normal file
@@ -0,0 +1,79 @@
|
||||
var IS_WINDOWS = (/^win/).test(process.platform),
|
||||
subsets,
|
||||
symbols;
|
||||
|
||||
/**
|
||||
* A set of symbol groups for use in different situations: regular, windows friendly unicode, and plain text.
|
||||
*
|
||||
* @type {Object}
|
||||
*/
|
||||
subsets = {
|
||||
regular: {
|
||||
console: {
|
||||
top: '┌',
|
||||
middle: '│',
|
||||
bottom: '└'
|
||||
},
|
||||
dot: '.',
|
||||
folder: '❏',
|
||||
root: '→',
|
||||
sub: '↳',
|
||||
ok: '✓',
|
||||
error: '✖',
|
||||
star: '★',
|
||||
up: '↑',
|
||||
down: '↓'
|
||||
},
|
||||
encoded: {
|
||||
console: {
|
||||
top: '\u250C',
|
||||
middle: '\u2502',
|
||||
bottom: '\u2514'
|
||||
},
|
||||
dot: '.',
|
||||
folder: '\u25A1',
|
||||
root: '\u2192',
|
||||
sub: '\u2514',
|
||||
ok: '\u221A',
|
||||
error: '\u00D7',
|
||||
star: '\u2605',
|
||||
up: '\u2191',
|
||||
down: '\u2193'
|
||||
},
|
||||
plainText: {
|
||||
console: {
|
||||
top: '-',
|
||||
middle: '|',
|
||||
bottom: '-'
|
||||
},
|
||||
dot: '.',
|
||||
folder: 'Folder',
|
||||
root: 'Root',
|
||||
sub: 'Sub-folder',
|
||||
ok: 'Pass',
|
||||
error: 'Fail',
|
||||
star: '*',
|
||||
up: '^',
|
||||
down: 'v'
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* A method that picks the appropriate set of CLI report symbols under a given set of run conditions.
|
||||
*
|
||||
* @param {Boolean} disableUnicode - A flag to force plain text equivalents for CLI symbols if set to true.
|
||||
* @returns {Object} - The right set of symbols from subsets for the given conditions.
|
||||
* @todo Add additional parameter related to temp file read - writes
|
||||
*/
|
||||
symbols = function (disableUnicode) {
|
||||
if (disableUnicode) {
|
||||
return subsets.plainText;
|
||||
}
|
||||
if (IS_WINDOWS) { // modify symbols for windows platforms
|
||||
return subsets.encoded;
|
||||
}
|
||||
|
||||
return subsets.regular;
|
||||
};
|
||||
|
||||
module.exports = symbols;
|
185
node_modules/newman/lib/reporters/cli/cli-utils.js
generated
vendored
Normal file
185
node_modules/newman/lib/reporters/cli/cli-utils.js
generated
vendored
Normal file
@@ -0,0 +1,185 @@
|
||||
var inspect = require('util').inspect,
|
||||
wrap = require('word-wrap'),
|
||||
symbols = require('./cli-utils-symbols'),
|
||||
|
||||
cliUtils;
|
||||
|
||||
// set styling for inspect options
|
||||
inspect.styles.string = 'grey';
|
||||
inspect.styles.name = 'white';
|
||||
|
||||
cliUtils = {
|
||||
|
||||
/**
|
||||
* A helper method that picks the right set of symbols for the given set of run conditions.
|
||||
*
|
||||
* @type {Function}
|
||||
*/
|
||||
symbols: symbols,
|
||||
|
||||
/**
|
||||
* A set of blank CLI table symbols (default).
|
||||
*
|
||||
* @type {Object}
|
||||
*/
|
||||
cliTableTemplate_Blank: {
|
||||
top: '',
|
||||
'top-mid': '',
|
||||
'top-left': '',
|
||||
'top-right': '',
|
||||
bottom: '',
|
||||
'bottom-mid': '',
|
||||
'bottom-left': '',
|
||||
'bottom-right': '',
|
||||
middle: '',
|
||||
mid: ' ',
|
||||
'mid-mid': '',
|
||||
'mid-left': '',
|
||||
'mid-right': '',
|
||||
left: '',
|
||||
'left-mid': '',
|
||||
'left-left': '',
|
||||
'left-right': '',
|
||||
right: '',
|
||||
'right-mid': '',
|
||||
'right-left': '',
|
||||
'right-right': ''
|
||||
},
|
||||
|
||||
/**
|
||||
* A set of fallback CLI table construction symbols, used when unicode has been disabled.
|
||||
*
|
||||
* @type {Object}
|
||||
*/
|
||||
cliTableTemplateFallback: {
|
||||
top: '-',
|
||||
'top-mid': '-',
|
||||
'top-left': '-',
|
||||
'top-right': '-',
|
||||
bottom: '-',
|
||||
'bottom-mid': '-',
|
||||
'bottom-left': '-',
|
||||
'bottom-right': '-',
|
||||
middle: '|',
|
||||
mid: '-',
|
||||
'mid-mid': '+',
|
||||
'mid-left': '-',
|
||||
'mid-right': '-',
|
||||
left: '|',
|
||||
'left-mid': '-',
|
||||
'left-left': '-',
|
||||
'left-right': '-',
|
||||
right: '|',
|
||||
'right-mid': '-',
|
||||
'right-left': '-',
|
||||
'right-right': '-'
|
||||
},
|
||||
|
||||
/**
|
||||
* A CLI utility helper method that perfoms left padding on an input string.
|
||||
*
|
||||
* @param {String} nr - The string to be padded.
|
||||
* @param {Number} n - The length of the field, in which to left pad the input string.
|
||||
* @param {String=} str - An optional string used for padding the input string. Defaults to '0'.
|
||||
* @returns {String} - The resultant left padded string.
|
||||
*/
|
||||
padLeft: function (nr, n, str) {
|
||||
return Array(n - String(nr).length + 1).join(str || '0') + nr;
|
||||
},
|
||||
|
||||
/**
|
||||
* A CLI utility helper method that checks for the non TTY compliance of the current run environment.
|
||||
*
|
||||
* color: | noTTY:
|
||||
* 'on' -> false
|
||||
* 'off' -> true
|
||||
* otherwise -> Based on isTTY.
|
||||
*
|
||||
* @param {String} color - A flag to indicate usage of the --color option.
|
||||
* @returns {Boolean} - A boolean value depicting the result of the noTTY check.
|
||||
*/
|
||||
noTTY: function (color) {
|
||||
return (color === 'off') || (color !== 'on') && (!process.stdout.isTTY);
|
||||
},
|
||||
|
||||
/**
|
||||
* A CLI utility helper method that generates a color inspector function for CLI reports.
|
||||
*
|
||||
* @param {Object} runOptions - The set of run options acquired via the runner.
|
||||
* @returns {Function} - A function to perform utils.inspect, given a sample item, under pre-existing options.
|
||||
*/
|
||||
inspector: function (runOptions) {
|
||||
var dimension = cliUtils.dimension(),
|
||||
options = {
|
||||
depth: 25,
|
||||
|
||||
maxArrayLength: 100, // only supported in Node v6.1.0 and up: https://github.com/nodejs/node/pull/6334
|
||||
|
||||
colors: !cliUtils.noTTY(runOptions.color),
|
||||
|
||||
// note that similar dimension calculation is in utils.wrapper
|
||||
// only supported in Node v6.3.0 and above: https://github.com/nodejs/node/pull/7499
|
||||
breakLength: ((dimension.exists && (dimension.width > 20)) ? dimension.width : 60) - 16
|
||||
};
|
||||
|
||||
return function (item) {
|
||||
return inspect(item, options);
|
||||
};
|
||||
},
|
||||
|
||||
/**
|
||||
* A CLI utility helper method to provide content wrapping functionality for CLI reports.
|
||||
*
|
||||
* @returns {Function} - A sub-method to wrap content, given a piece of text, and indent value.
|
||||
*/
|
||||
wrapper: function () {
|
||||
var dimension = cliUtils.dimension(),
|
||||
// note that similar dimension calculation is in utils.wrapper
|
||||
width = ((dimension.exists && (dimension.width > 20)) ? dimension.width : 60) - 6;
|
||||
|
||||
return function (text, indent) {
|
||||
return wrap(text, {
|
||||
indent: indent,
|
||||
width: width,
|
||||
cut: true
|
||||
});
|
||||
};
|
||||
},
|
||||
|
||||
/**
|
||||
* A CLI utility helper method to compute and scae the size of the CLI table to be displayed.
|
||||
*
|
||||
* @returns {Object} - A set of properties: width, height, and TTY existence.
|
||||
*/
|
||||
dimension: function () {
|
||||
var tty,
|
||||
width,
|
||||
height;
|
||||
|
||||
try { tty = require('tty'); }
|
||||
catch (e) { tty = null; }
|
||||
|
||||
if (tty && tty.isatty(1) && tty.isatty(2)) {
|
||||
if (process.stdout.getWindowSize) {
|
||||
width = process.stdout.getWindowSize(1)[0];
|
||||
height = process.stdout.getWindowSize(1)[1];
|
||||
}
|
||||
else if (tty.getWindowSize) {
|
||||
width = tty.getWindowSize()[1];
|
||||
height = tty.getWindowSize()[0];
|
||||
}
|
||||
else if (process.stdout.columns && process.stdout.rows) {
|
||||
height = process.stdout.rows;
|
||||
width = process.stdout.columns;
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
exists: !(Boolean(process.env.CI) || !process.stdout.isTTY), // eslint-disable-line no-process-env
|
||||
width: width,
|
||||
height: height
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = cliUtils;
|
566
node_modules/newman/lib/reporters/cli/index.js
generated
vendored
Normal file
566
node_modules/newman/lib/reporters/cli/index.js
generated
vendored
Normal file
@@ -0,0 +1,566 @@
|
||||
var _ = require('lodash'),
|
||||
sdk = require('postman-collection'),
|
||||
colors = require('colors/safe'),
|
||||
Table = require('cli-table3'),
|
||||
format = require('util').format,
|
||||
|
||||
util = require('../../util'),
|
||||
cliUtils = require('./cli-utils'),
|
||||
print = require('../../print'),
|
||||
pad = cliUtils.padLeft,
|
||||
|
||||
LF = '\n',
|
||||
SPC = ' ',
|
||||
DOT = '.',
|
||||
E = '',
|
||||
|
||||
CACHED_TIMING_PHASE = '(cache)',
|
||||
TIMING_TABLE_HEADERS = {
|
||||
prepare: 'prepare',
|
||||
wait: 'wait',
|
||||
dns: 'dns-lookup',
|
||||
tcp: 'tcp-handshake',
|
||||
secureHandshake: 'ssl-handshake',
|
||||
firstByte: 'transfer-start',
|
||||
download: 'download',
|
||||
process: 'process',
|
||||
total: 'total'
|
||||
},
|
||||
BODY_CLIP_SIZE = 2048,
|
||||
|
||||
PostmanCLIReporter,
|
||||
timestamp,
|
||||
extractSNR;
|
||||
|
||||
// sets theme for colors for console logging
|
||||
colors.setTheme({
|
||||
log: 'grey',
|
||||
info: 'cyan',
|
||||
warn: 'yellow',
|
||||
debug: 'blue',
|
||||
error: 'red'
|
||||
});
|
||||
|
||||
extractSNR = function (executions) {
|
||||
var snr;
|
||||
|
||||
// eslint-disable-next-line lodash/collection-method-value
|
||||
_.isArray(executions) && _.forEachRight(executions, function (execution) {
|
||||
var nextReq = _.get(execution, 'result.return.nextRequest');
|
||||
|
||||
if (nextReq) {
|
||||
snr = nextReq;
|
||||
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
return snr;
|
||||
};
|
||||
|
||||
/**
|
||||
* CLI reporter
|
||||
*
|
||||
* @param {EventEmitter} emitter - An EventEmitter instance with event handler attachers to trigger reporting.
|
||||
* @param {Object} reporterOptions - CLI reporter options object.
|
||||
* @param {Boolean=} reporterOptions.silent - Boolean flag to turn off CLI reporting altogether, if set to true.
|
||||
* @param {Boolean=} reporterOptions.noAssertions - Boolean flag to turn off assertion reporting, if set to true.
|
||||
* @param {Boolean=} reporterOptions.noSuccessAssertions - Boolean flag, if true, turn off report successful assertions.
|
||||
* @param {Boolean=} reporterOptions.noSummary - Boolean flag to turn off summary reporting altogether, if set to true.
|
||||
* @param {Boolean=} reporterOptions.noFailures - Boolean flag to turn off failure reporting altogether, if set to true.
|
||||
* @param {Boolean=} reporterOptions.noConsole - Boolean flag to turn off console logging, if set to true.
|
||||
* @param {Boolean=} reporterOptions.noBanner - Boolean flag to turn off newman banner, if set to true.
|
||||
* @param {Object} options - A set of generic collection run options.
|
||||
* @returns {*}
|
||||
*/
|
||||
PostmanCLIReporter = function (emitter, reporterOptions, options) {
|
||||
var currentGroup = options.collection,
|
||||
inspect = cliUtils.inspector(options),
|
||||
wrap = cliUtils.wrapper(),
|
||||
symbols = cliUtils.symbols(options.disableUnicode);
|
||||
|
||||
// respect silent option to not report anything
|
||||
if (reporterOptions.silent || options.silent) {
|
||||
return; // we simply do not register anything!
|
||||
}
|
||||
|
||||
// disable colors based on `noTTY`.
|
||||
cliUtils.noTTY(options.color) && colors.disable();
|
||||
|
||||
// we register the `done` listener first so that in case user does not want to show results of collection run, we
|
||||
// simply do not register the other events
|
||||
emitter.on('done', function () {
|
||||
// for some reason, if there is no run summary, it is unexpected and hence don't validate this
|
||||
var run = this.summary.run;
|
||||
|
||||
// show the summary table (provided option does not say it is not to be shown)
|
||||
if (!reporterOptions.noSummary) {
|
||||
print(LF + PostmanCLIReporter.parseStatistics(run.stats, run.timings, run.transfers, options) + LF);
|
||||
}
|
||||
|
||||
// show the failures table (provided option does not say it is not to be shown)
|
||||
if (!reporterOptions.noFailures && run.failures && run.failures.length) {
|
||||
print(LF + PostmanCLIReporter.parseFailures(run.failures) + LF);
|
||||
}
|
||||
});
|
||||
|
||||
emitter.on('start', function () {
|
||||
var collectionIdentifier = currentGroup && (currentGroup.name || currentGroup.id);
|
||||
|
||||
if (!reporterOptions.noBanner) {
|
||||
// print the newman banner
|
||||
print('%s\n\n', colors.reset('newman'));
|
||||
}
|
||||
|
||||
// print the collection name and newman info line
|
||||
collectionIdentifier && print.lf('%s', colors.reset(collectionIdentifier));
|
||||
});
|
||||
|
||||
emitter.on('beforeIteration', function (err, o) {
|
||||
if (err || o.cursor.cycles <= 1) {
|
||||
return; // do not print iteration banner if it is a single iteration run
|
||||
}
|
||||
|
||||
// print the iteration info line
|
||||
print.lf(LF + colors.gray.underline('Iteration %d/%d'), o.cursor.iteration + 1, o.cursor.cycles);
|
||||
});
|
||||
|
||||
emitter.on('test', function (err, o) {
|
||||
if (err) {
|
||||
return;
|
||||
}
|
||||
var snr = extractSNR(o.executions);
|
||||
|
||||
if (snr) {
|
||||
print.lf(LF + colors.gray('Attempting to set next request to', snr));
|
||||
}
|
||||
});
|
||||
|
||||
emitter.on('beforeItem', function (err, o) {
|
||||
if (err) { return; }
|
||||
|
||||
var itemGroup = o.item.parent(),
|
||||
root = !itemGroup || (itemGroup === options.collection);
|
||||
|
||||
// in case this item belongs to a separate folder, print that folder name
|
||||
if (itemGroup && (currentGroup !== itemGroup)) {
|
||||
!root && print('\n%s %s', symbols.folder, colors.reset(util.getFullName(itemGroup)));
|
||||
|
||||
// set the flag that keeps track of the currently running group
|
||||
currentGroup = itemGroup;
|
||||
}
|
||||
|
||||
// we print the item name. the symbol prefix denotes if the item is in root or under folder.
|
||||
// @todo - when we do indentation, we would not need symbolic representation
|
||||
o.item && print.lf('\n%s %s', (root ?
|
||||
symbols.root : symbols.sub), colors.reset(o.item.name || E));
|
||||
});
|
||||
|
||||
// print out the request name to be executed and start a spinner
|
||||
emitter.on('beforeRequest', function (err, o) {
|
||||
if (err || !o.request) { return; }
|
||||
|
||||
if (reporterOptions.showTimestamps) {
|
||||
var currentTime = new Date();
|
||||
|
||||
timestamp = '[' + currentTime.toLocaleString() + ']';
|
||||
print(' %s %s %s ',
|
||||
colors.gray(timestamp),
|
||||
colors.gray(o.request.method),
|
||||
colors.gray(o.request.url.toString()));
|
||||
}
|
||||
else {
|
||||
print(' %s %s ',
|
||||
colors.gray(o.request.method),
|
||||
colors.gray(o.request.url.toString()));
|
||||
}
|
||||
|
||||
!options.disableUnicode && print().wait(colors.gray);
|
||||
});
|
||||
|
||||
// output the response code, reason and time
|
||||
emitter.on('request', function (err, o) {
|
||||
if (err) {
|
||||
print.lf(colors.red('[errored]'));
|
||||
print.lf(colors.red(' %s'), err.message);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(o.request && o.response)) {
|
||||
print.lf(colors.red('[errored]'));
|
||||
print.lf(colors.red(' %s'), 'Internal error! Could not read response data.');
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// quickly print out basic non verbose response meta and exit
|
||||
if (!options.verbose) {
|
||||
print.lf(colors.gray('[%d %s, %s, %s]'), o.response.code, o.response.reason(),
|
||||
util.filesize(o.response.size().total), util.prettyms(o.response.responseTime));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// this point onwards the output is verbose. a tonne of variables are created here for
|
||||
// keeping the output clean and readable
|
||||
|
||||
let req = o.request,
|
||||
res = o.response,
|
||||
|
||||
// set values here with abundance of caution to avoid erroring out
|
||||
reqSize = util.filesize(req.size().total),
|
||||
resSize = util.filesize(res.size().total),
|
||||
code = res.code,
|
||||
reason = res.reason(),
|
||||
mime = res.contentInfo() || {},
|
||||
timings = _.last(_.get(o, 'history.execution.data')),
|
||||
|
||||
reqHeadersLen = _.get(req, 'headers.members.length'),
|
||||
resHeadersLen = _.get(res, 'headers.members.length'),
|
||||
|
||||
resTime = util.prettyms(res.responseTime || 0),
|
||||
|
||||
reqText = (options.verbose && req.body) ? req.body.toString() : E,
|
||||
reqTextLen = req.size().body || Buffer.byteLength(reqText),
|
||||
|
||||
resText = options.verbose ? res.text() : E,
|
||||
resTextLen = res.size().body || Buffer.byteLength(resText),
|
||||
|
||||
reqBodyMode = _.get(req, 'body.mode', ''),
|
||||
resSummary = [
|
||||
`${mime.contentType}`,
|
||||
`${mime.mimeType}`,
|
||||
`${mime.mimeFormat}`,
|
||||
`${mime.charset}`
|
||||
].join(` ${colors.gray(symbols.star)} `);
|
||||
|
||||
|
||||
print.lf(SPC); // also flushes out the circling progress icon
|
||||
|
||||
// for clean readability of code. this section compiles the cli string for one line of
|
||||
// req-res combined summary. this looks somewhat like below:
|
||||
// >> 200 OK ★ 979ms time ★ 270B↑ 793B↓ size ★ 7↑ 7↓ headers ★ 0 cookies
|
||||
print.lf(SPC + SPC + [
|
||||
`${code} ${reason}`,
|
||||
`${resTime} ${colors.gray('time')}`,
|
||||
`${reqSize}${colors.gray(symbols.up)} ${resSize}${colors.gray(symbols.down)} ${colors.gray('size')}`,
|
||||
`${reqHeadersLen}${colors.gray(symbols.up)} ` +
|
||||
`${resHeadersLen}${colors.gray(symbols.down)} ${colors.gray('headers')}`,
|
||||
`${_.get(res, 'cookies.members.length')} ${colors.gray('cookies')}`
|
||||
].join(` ${colors.gray(symbols.star)} `));
|
||||
|
||||
// print request body
|
||||
if (reqTextLen) {
|
||||
// truncate very large request (is 2048 large enough?)
|
||||
if (reqTextLen > BODY_CLIP_SIZE) {
|
||||
reqText = reqText.substr(0, BODY_CLIP_SIZE) +
|
||||
colors.brightWhite(`\n(showing ${util.filesize(BODY_CLIP_SIZE)}/${util.filesize(reqTextLen)})`);
|
||||
}
|
||||
|
||||
reqText = wrap(reqText, ` ${colors.white(symbols.console.middle)} `);
|
||||
// eslint-disable-next-line max-len
|
||||
print.buffer(` ${colors.white(symbols.console.top)} ${colors.white(symbols.up)} ${reqBodyMode} ${colors.gray(symbols.star)} ${util.filesize(reqTextLen)}\n`,
|
||||
colors.white(` ${symbols.console.bottom}`))
|
||||
// tweak the message to ensure that its surrounding is not brightly coloured.
|
||||
// also ensure to remove any blank lines generated due to util.inspect
|
||||
.nobuffer(colors.gray(reqText.replace(/\n\s*\n/g, LF) + LF));
|
||||
|
||||
print.lf(SPC); // visual tweak: flushes out the buffer of wrapping body above
|
||||
}
|
||||
|
||||
// print response body
|
||||
if (resTextLen) {
|
||||
// truncate very large response (is 2048 large enough?)
|
||||
if (resTextLen > BODY_CLIP_SIZE) {
|
||||
resText = resText.substr(0, BODY_CLIP_SIZE) +
|
||||
colors.brightWhite(`\n(showing ${util.filesize(BODY_CLIP_SIZE)}/${util.filesize(resTextLen)})`);
|
||||
}
|
||||
|
||||
resText = wrap(resText, ` ${colors.white(symbols.console.middle)} `);
|
||||
// eslint-disable-next-line max-len
|
||||
print.buffer(` ${colors.white(symbols.console.top)} ${colors.white(symbols.down)} ${resSummary} ${colors.gray(symbols.star)} ${util.filesize(resTextLen)}\n`,
|
||||
colors.white(` ${symbols.console.bottom}`))
|
||||
// tweak the message to ensure that its surrounding is not brightly coloured.
|
||||
// also ensure to remove any blank lines generated due to util.inspect
|
||||
.nobuffer(colors.gray(resText.replace(/\n\s*\n/g, LF) + LF));
|
||||
}
|
||||
// print the line of response body meta one liner if there is no response body
|
||||
// if there is one, we would already print it across the body braces above.
|
||||
else {
|
||||
// we need to do some newline related shenanigans here so that the output looks clean
|
||||
// in the absence of the request body block
|
||||
print.lf(` ${symbols.down} ${resSummary}`);
|
||||
}
|
||||
|
||||
// print timing info of the request
|
||||
timings = timings && timings.timings; // if there are redirects, get timings for the last request sent
|
||||
if (timings) {
|
||||
// adds nice units to all time data in the object
|
||||
let timingPhases = util.beautifyTime(sdk.Response.timingPhases(timings)),
|
||||
timingTable = new Table({
|
||||
chars: _.defaults({ mid: '', middle: '' }, cliUtils.cliTableTemplate_Blank),
|
||||
colAligns: _.fill(Array(_.size(timingPhases)), 'left'),
|
||||
style: { 'padding-left': 2 }
|
||||
});
|
||||
|
||||
timingPhases = _.transform(TIMING_TABLE_HEADERS, (result, header, key) => {
|
||||
if (_.has(timingPhases, key)) {
|
||||
result.headers.push(colors.white(header));
|
||||
result.values.push(colors.log(timingPhases[key] || CACHED_TIMING_PHASE));
|
||||
}
|
||||
}, { headers: [], values: [] });
|
||||
|
||||
|
||||
timingTable.push(timingPhases.headers); // add name of phases in the table
|
||||
timingTable.push(timingPhases.values); // add time of phases in the table
|
||||
|
||||
print(LF + timingTable + LF + LF);
|
||||
}
|
||||
});
|
||||
|
||||
// Print script errors in real time
|
||||
emitter.on('script', function (err, o) {
|
||||
err && print.lf(colors.red.bold('%s⠄ %s in %s-script'), pad(this.summary.run.failures.length, 3, SPC), err.name,
|
||||
o.event && o.event.listen || 'unknown');
|
||||
});
|
||||
|
||||
!reporterOptions.noAssertions && emitter.on('assertion', function (err, o) {
|
||||
var passed = !err;
|
||||
|
||||
// handle skipped test display
|
||||
if (o.skipped && !reporterOptions.noSuccessAssertions) {
|
||||
print.lf('%s %s', colors.cyan(' - '), colors.cyan('[skipped] ' + o.assertion));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (passed && reporterOptions.noSuccessAssertions) {
|
||||
return;
|
||||
}
|
||||
|
||||
// print each test assertions
|
||||
if (reporterOptions.showTimestamps) {
|
||||
timestamp = '[' + new Date().toLocaleTimeString() + ']';
|
||||
print.lf(' %s%s %s', colors.gray(timestamp), passed ? colors.green(` ${symbols.ok} `) :
|
||||
colors.red.bold(pad(this.summary.run.failures.length, 2, SPC) + symbols.dot), passed ?
|
||||
colors.gray(o.assertion) : colors.red.bold(o.assertion));
|
||||
}
|
||||
else {
|
||||
print.lf('%s %s', passed ? colors.green(` ${symbols.ok} `) :
|
||||
colors.red.bold(pad(this.summary.run.failures.length, 3, SPC) + symbols.dot), passed ?
|
||||
colors.gray(o.assertion) : colors.red.bold(o.assertion));
|
||||
}
|
||||
});
|
||||
|
||||
// show user console logs in a neatly formatted way (provided user has not disabled the same)
|
||||
!reporterOptions.noConsole && emitter.on('console', function (err, o) {
|
||||
if (err) { return; }
|
||||
|
||||
var color = colors[o.level] || colors.gray,
|
||||
message;
|
||||
|
||||
// we first merge all messages to a string. while merging we run the values to util.inspect to colour code the
|
||||
// messages based on data type
|
||||
message = wrap(_.reduce(o.messages, function (log, message) { // wrap the whole message to the window size
|
||||
return (log += (log ? colors.white(', ') : '') + inspect(message));
|
||||
}, E), ` ${color(symbols.console.middle)} `); // add an indentation line at the beginning
|
||||
|
||||
// print the timestamp if the falg is present
|
||||
if (reporterOptions.showTimestamps) {
|
||||
print(LF + ' %s', colors.gray('[' + new Date().toLocaleTimeString() + ']' + LF));
|
||||
}
|
||||
|
||||
print.buffer(color(` ${symbols.console.top}\n`), color(` ${symbols.console.bottom}\n`))
|
||||
// tweak the message to ensure that its surrounding is not brightly coloured.
|
||||
// also ensure to remove any blank lines generated due to util.inspect
|
||||
.nobuffer(colors.gray(message.replace(/\n\s*\n/g, LF) + LF));
|
||||
});
|
||||
};
|
||||
|
||||
_.assignIn(PostmanCLIReporter, {
|
||||
|
||||
// @todo: change function signature to accept run object and options, thereby reducing parameters
|
||||
/**
|
||||
* A CLI reporter method to parse collection run statistics into a CLI table.
|
||||
*
|
||||
* @param {Object} stats - The cumulative collection run status object.
|
||||
* @param {Object} stats.iterations - A set of values for total, pending, and failed iterations.
|
||||
* @param {Number} stats.iterations.total - Total iterations in the current collection run.
|
||||
* @param {Number} stats.iterations.pending - Pending iterations in the current collection run.
|
||||
* @param {Number} stats.iterations.failed - Failed iterations in the current collection run.
|
||||
* @param {Object} stats.requests - A set of values for total, pending, and failed requests.
|
||||
* @param {Number} stats.requests.total - Total requests in the current collection run.
|
||||
* @param {Number} stats.requests.pending - Pending requests in the current collection run.
|
||||
* @param {Number} stats.requests.failed - Failed requests in the current collection run.
|
||||
* @param {Object} stats.testScripts - A set of values for total, pending, and failed testScripts.
|
||||
* @param {Number} stats.testScripts.total - Total testScripts in the current collection run.
|
||||
* @param {Number} stats.testScripts.pending - Pending testScripts in the current collection run.
|
||||
* @param {Number} stats.testScripts.failed - Failed testScripts in the current collection run.
|
||||
* @param {Object} stats.prerequestScripts - A set of values for total, pending, and failed prerequestScripts.
|
||||
* @param {Number} stats.prerequestScripts.total - Total prerequestScripts in the current collection run.
|
||||
* @param {Number} stats.prerequestScripts.pending - Pending prerequestScripts in the current collection run.
|
||||
* @param {Number} stats.prerequestScripts.failed - Failed prerequestScripts in the current collection run.
|
||||
* @param {Object} stats.assertions - A set of values for total, pending, and failed assertions.
|
||||
* @param {Number} stats.assertions.total - Total assertions in the current collection run.
|
||||
* @param {Number} stats.assertions.pending - Pending assertions in the current collection run.
|
||||
* @param {Number} stats.assertions.failed - Failed assertions in the current collection run.
|
||||
* @param {Object} timings - A set of values for the timings of the current collection run.
|
||||
* @param {Number} timings.completed - The end timestamp for the current collection run.
|
||||
* @param {Number} timings.started - The start timestamp for the current collection run
|
||||
* @param {String} timings.responseAverage - The average response time across all requests
|
||||
* @param {String} timings.responseMin - The minimum response time across all requests
|
||||
* @param {String} timings.responseMax - The maximum response time across all requests
|
||||
* @param {String} timings.responseSd - Standard deviation of response time across all requests
|
||||
* @param {String} timings.dnsAverage - The average DNS lookup time of the run
|
||||
* @param {String} timings.dnsMin - The minimum DNS lookup time of the run
|
||||
* @param {String} timings.dnsMax - The maximum DNS lookup time of the run
|
||||
* @param {String} timings.dnsSd - Standard deviation of DNS lookup time of the run
|
||||
* @param {String} timings.firstByteAverage - The average first byte time of the run
|
||||
* @param {String} timings.firstByteMin - The minimum first byte time of the run
|
||||
* @param {String} timings.firstByteMax - The maximum first byte time of the run
|
||||
* @param {String} timings.firstByteSd - Standard deviation of first byte time of the run
|
||||
* @param {Object} transfers - A set of details on the network usage for the current collection run.
|
||||
* @param {String} transfers.responseTotal - The net extent of the data transfer achieved during the collection run.
|
||||
* @param {Object} options - The set of generic collection run options.
|
||||
* @returns {Table} - The constructed collection run statistics table.
|
||||
*/
|
||||
parseStatistics (stats, timings, transfers, options) {
|
||||
var summaryTable;
|
||||
|
||||
// create the summary table
|
||||
summaryTable = new Table({
|
||||
chars: options.disableUnicode && cliUtils.cliTableTemplateFallback,
|
||||
style: { head: [] },
|
||||
head: [E, 'executed', ' failed'],
|
||||
colAligns: ['right', 'right', 'right'],
|
||||
colWidths: [25]
|
||||
});
|
||||
|
||||
// add specific rows to show in summary
|
||||
stats && _.forEach([{
|
||||
source: 'iterations',
|
||||
label: 'iterations'
|
||||
}, {
|
||||
source: 'requests',
|
||||
label: 'requests'
|
||||
}, {
|
||||
source: 'testScripts',
|
||||
label: 'test-scripts'
|
||||
}, {
|
||||
source: 'prerequestScripts',
|
||||
label: 'prerequest-scripts'
|
||||
}, {
|
||||
source: 'assertions',
|
||||
label: 'assertions'
|
||||
}], function (row) {
|
||||
var metric = stats[row.source],
|
||||
label = row.label;
|
||||
|
||||
// colour the label based on the failure or pending count of the metric
|
||||
label = metric.failed ? colors.red(label) : (metric.pending ? label : colors.green(label));
|
||||
|
||||
// push the statistics
|
||||
summaryTable.push([
|
||||
label,
|
||||
metric.total,
|
||||
(metric.failed ? colors.red(metric.failed) : metric.failed)
|
||||
// @todo - add information of pending scripts
|
||||
// (metric.failed ? colors.red(metric.failed) : metric.failed) +
|
||||
// (metric.pending ? format(' (%d pending)', metric.pending) : E)
|
||||
]);
|
||||
});
|
||||
|
||||
// add the total execution time to summary
|
||||
timings && summaryTable.push([{
|
||||
colSpan: 3,
|
||||
content: format('total run duration: %s', util.prettyms(timings.completed - timings.started)),
|
||||
hAlign: 'left' // since main style was set to right
|
||||
}]);
|
||||
|
||||
// add row to show total data received
|
||||
transfers && summaryTable.push([{
|
||||
colSpan: 3,
|
||||
content: format('total data received: %s (approx)', util.filesize(transfers.responseTotal)),
|
||||
hAlign: 'left'
|
||||
}]);
|
||||
|
||||
// add rows containing average time of different request phases
|
||||
timings && _.forEach({
|
||||
response: 'average response time:',
|
||||
dns: 'average DNS lookup time:',
|
||||
firstByte: 'average first byte time:'
|
||||
}, (value, key) => {
|
||||
timings[`${key}Average`] && summaryTable.push([{
|
||||
colSpan: 3,
|
||||
content: format(`${value} %s [min: %s, max: %s, s.d.: %s]`,
|
||||
util.prettyms(timings[`${key}Average`]),
|
||||
util.prettyms(timings[`${key}Min`]),
|
||||
util.prettyms(timings[`${key}Max`]),
|
||||
util.prettyms(timings[`${key}Sd`])),
|
||||
hAlign: 'left'
|
||||
}]);
|
||||
});
|
||||
|
||||
return summaryTable;
|
||||
},
|
||||
|
||||
/**
|
||||
* A CLI reporter method to parse collection run failure statistics into a CLI table.
|
||||
*
|
||||
* @param {Array} failures - An array of failure objects.
|
||||
* @returns {Table} - The constructed CLI failure Table object.
|
||||
*/
|
||||
parseFailures (failures) {
|
||||
var failureTable = new Table({
|
||||
head: [{
|
||||
hAlign: 'right',
|
||||
content: colors.red.underline('#')
|
||||
}, colors.red.underline('failure'),
|
||||
colors.red.underline('detail')],
|
||||
chars: cliUtils.cliTableTemplate_Blank,
|
||||
wordWrap: true,
|
||||
colAligns: ['right'],
|
||||
colWidths: cliUtils.noTTY() ? [] : (function (size, indexOrder) {
|
||||
var colWidths = [];
|
||||
|
||||
if (size.exists && size.width && (size.width > 20)) {
|
||||
colWidths[0] = indexOrder + 3;
|
||||
colWidths[1] = parseInt((size.width - colWidths[0]) * 0.2, 10);
|
||||
colWidths[2] = parseInt(size.width - (colWidths[0] + colWidths[1] + 5), 10);
|
||||
}
|
||||
|
||||
return colWidths;
|
||||
}(cliUtils.dimension(), Number(failures.length.toString().length)))
|
||||
});
|
||||
|
||||
_.forEach(failures, function (failure, index) {
|
||||
var name = failure.error && failure.error.name || E,
|
||||
message = failure.error && failure.error.test || E;
|
||||
|
||||
// augment name with iteration information
|
||||
failure.cursor && (failure.cursor.cycles > 1) &&
|
||||
(name += LF + colors.gray('iteration: ' + (failure.cursor.iteration + 1)));
|
||||
|
||||
// include the assertion error message in the failure details
|
||||
failure.error && (message += LF + colors.gray(failure.error.message || E));
|
||||
|
||||
// augment the message with stack information
|
||||
failure.at && (message += LF + colors.gray('at ' + failure.at));
|
||||
|
||||
// augment message with item information
|
||||
failure.source &&
|
||||
(message += format(colors.gray('\ninside "%s"'), util.getFullName(failure.source)));
|
||||
|
||||
failureTable.push([pad(Number(index + 1), Number(failures.length.toString().length)).toString() +
|
||||
DOT, name, message]);
|
||||
});
|
||||
|
||||
return failureTable;
|
||||
}
|
||||
});
|
||||
|
||||
// Mark the CLI reporter as dominant, so that no two dominant reporters are together
|
||||
PostmanCLIReporter.prototype.dominant = true;
|
||||
|
||||
module.exports = PostmanCLIReporter;
|
37
node_modules/newman/lib/reporters/emojitrain.js
generated
vendored
Normal file
37
node_modules/newman/lib/reporters/emojitrain.js
generated
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
var SmileyReporter;
|
||||
|
||||
/**
|
||||
* Fills your collection run (read life) with a bunch of Emojis 😀.
|
||||
*
|
||||
* @param {Object} newman - The collection run object with event handling hooks to enable reporting.
|
||||
* @param {Object} reporterOptions - A set of reporter specific run options.
|
||||
* @param {Object} options - A set of generic collection run options.
|
||||
* @returns {*}
|
||||
*/
|
||||
SmileyReporter = function (newman, reporterOptions, options) {
|
||||
if (options.silent || reporterOptions.silent) {
|
||||
return;
|
||||
}
|
||||
|
||||
var fails = {},
|
||||
noteFailure;
|
||||
|
||||
noteFailure = function (err, args) {
|
||||
err && (fails[args.cursor.ref] = true);
|
||||
};
|
||||
|
||||
newman.on('script', noteFailure);
|
||||
newman.on('request', noteFailure);
|
||||
newman.on('assertion', noteFailure);
|
||||
|
||||
newman.on('item', function (err, args) {
|
||||
process.stdout.write((err || fails[args.cursor.ref]) ? '😢 ' : '😀 ');
|
||||
});
|
||||
|
||||
newman.on('done', function (err) {
|
||||
console.info((err || Object.keys(fails).length) ? ' 😭' : ' 😍');
|
||||
});
|
||||
};
|
||||
|
||||
SmileyReporter.prototype.dominant = true;
|
||||
module.exports = SmileyReporter;
|
22
node_modules/newman/lib/reporters/json/index.js
generated
vendored
Normal file
22
node_modules/newman/lib/reporters/json/index.js
generated
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
var _ = require('lodash');
|
||||
|
||||
/**
|
||||
* Reporter that simply dumps the summary object to file (default: newman-run-report.json).
|
||||
*
|
||||
* @param {Object} newman - The collection run object, with event hooks for reporting run details.
|
||||
* @param {Object} options - A set of collection run options.
|
||||
* @param {String} options.export - The path to which the summary object must be written.
|
||||
* @returns {*}
|
||||
*/
|
||||
module.exports = function (newman, options) {
|
||||
newman.on('beforeDone', function (err, o) {
|
||||
if (err) { return; }
|
||||
|
||||
newman.exports.push({
|
||||
name: 'json-reporter',
|
||||
default: 'newman-run-report.json',
|
||||
path: options.export,
|
||||
content: JSON.stringify(_.omit(o.summary, 'exports'), 0, 2)
|
||||
});
|
||||
});
|
||||
};
|
164
node_modules/newman/lib/reporters/junit/index.js
generated
vendored
Normal file
164
node_modules/newman/lib/reporters/junit/index.js
generated
vendored
Normal file
@@ -0,0 +1,164 @@
|
||||
var _ = require('lodash'),
|
||||
xml = require('xmlbuilder'),
|
||||
|
||||
util = require('../../util'),
|
||||
JunitReporter;
|
||||
|
||||
/**
|
||||
* A function that creates raw XML to be written to Newman JUnit reports.
|
||||
*
|
||||
* @param {Object} newman - The collection run object, with a event handler setter, used to enable event wise reporting.
|
||||
* @param {Object} reporterOptions - A set of JUnit reporter run options.
|
||||
* @param {String=} reporterOptions.export - Optional custom path to create the XML report at.
|
||||
* @returns {*}
|
||||
*/
|
||||
JunitReporter = function (newman, reporterOptions) {
|
||||
newman.on('beforeDone', function () {
|
||||
var report = _.get(newman, 'summary.run.executions'),
|
||||
collection = _.get(newman, 'summary.collection'),
|
||||
cache,
|
||||
root,
|
||||
testSuitesExecutionTime = 0,
|
||||
executionTime = 0,
|
||||
timestamp,
|
||||
classname;
|
||||
|
||||
if (!report) {
|
||||
return;
|
||||
}
|
||||
|
||||
classname = _.upperFirst(_.camelCase(collection.name).replace(/\W/g, ''));
|
||||
|
||||
root = xml.create('testsuites', { version: '1.0', encoding: 'UTF-8' });
|
||||
root.att('name', collection.name);
|
||||
root.att('tests', _.get(newman, 'summary.run.stats.tests.total', 'unknown'));
|
||||
|
||||
cache = _.transform(report, function (accumulator, execution) {
|
||||
accumulator[execution.item.id] = accumulator[execution.id] || [];
|
||||
accumulator[execution.item.id].push(execution);
|
||||
}, {});
|
||||
|
||||
timestamp = new Date(_.get(newman, 'summary.run.timings.started')).toISOString();
|
||||
|
||||
_.forEach(cache, function (executions, itemId) {
|
||||
var suite = root.ele('testsuite'),
|
||||
currentItem,
|
||||
tests = {},
|
||||
errors = 0,
|
||||
failures = 0,
|
||||
errorMessages;
|
||||
|
||||
collection.forEachItem(function (item) {
|
||||
(item.id === itemId) && (currentItem = item);
|
||||
});
|
||||
|
||||
if (!currentItem) { return; }
|
||||
|
||||
suite.att('name', util.getFullName(currentItem));
|
||||
suite.att('id', currentItem.id);
|
||||
|
||||
suite.att('timestamp', timestamp);
|
||||
|
||||
_.forEach(executions, function (execution) {
|
||||
var iteration = execution.cursor.iteration,
|
||||
errored,
|
||||
msg = `Iteration: ${iteration}\n`;
|
||||
|
||||
// Process errors
|
||||
if (execution.requestError) {
|
||||
++errors;
|
||||
errored = true;
|
||||
msg += ('RequestError: ' + (execution.requestError.stack) + '\n');
|
||||
}
|
||||
msg += '\n---\n';
|
||||
_.forEach(['testScript', 'prerequestScript'], function (prop) {
|
||||
_.forEach(execution[prop], function (err) {
|
||||
if (err.error) {
|
||||
++errors;
|
||||
errored = true;
|
||||
msg = (msg + prop + 'Error: ' + (err.error.stack || err.error.message));
|
||||
msg += '\n---\n';
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
if (errored) {
|
||||
errorMessages = _.isString(errorMessages) ? (errorMessages + msg) : msg;
|
||||
}
|
||||
|
||||
// Process assertions
|
||||
_.forEach(execution.assertions, function (assertion) {
|
||||
var name = assertion.assertion,
|
||||
err = assertion.error;
|
||||
|
||||
if (err) {
|
||||
++failures;
|
||||
(_.isArray(tests[name]) ? tests[name].push(err) : (tests[name] = [err]));
|
||||
}
|
||||
else {
|
||||
tests[name] = [];
|
||||
}
|
||||
});
|
||||
if (execution.assertions) {
|
||||
suite.att('tests', execution.assertions.length);
|
||||
}
|
||||
else {
|
||||
suite.att('tests', 0);
|
||||
}
|
||||
|
||||
suite.att('failures', failures);
|
||||
suite.att('errors', errors);
|
||||
});
|
||||
|
||||
suite.att('time', _.mean(_.map(executions, function (execution) {
|
||||
executionTime = _.get(execution, 'response.responseTime') / 1000 || 0;
|
||||
testSuitesExecutionTime += executionTime;
|
||||
|
||||
return executionTime;
|
||||
})).toFixed(3));
|
||||
errorMessages && suite.ele('system-err').dat(errorMessages);
|
||||
|
||||
_.forOwn(tests, function (failures, name) {
|
||||
var testcase = suite.ele('testcase'),
|
||||
failure;
|
||||
|
||||
testcase.att('name', name);
|
||||
testcase.att('time', executionTime.toFixed(3));
|
||||
|
||||
// Set the same classname for all the tests
|
||||
testcase.att('classname', _.get(testcase.up(), 'attributes.name.value',
|
||||
classname));
|
||||
|
||||
if (failures && failures.length) {
|
||||
failure = testcase.ele('failure');
|
||||
failure.att('type', 'AssertionFailure');
|
||||
failure.dat('Failed ' + failures.length + ' times.');
|
||||
failure.dat('Collection JSON ID: ' + collection.id + '.');
|
||||
failure.dat('Collection name: ' + collection.name + '.');
|
||||
failure.dat('Request name: ' + util.getFullName(currentItem) + '.');
|
||||
failure.dat('Test description: ' + name + '.');
|
||||
if (failures.length !== 0) {
|
||||
failure.att('message', failures[0].message);
|
||||
failure.dat('Error message: ' + failures[0].message + '.');
|
||||
failure.dat('Stacktrace: ' + failures[0].stack + '.');
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
root.att('time', testSuitesExecutionTime.toFixed(3));
|
||||
newman.exports.push({
|
||||
name: 'junit-reporter',
|
||||
default: 'newman-run-report.xml',
|
||||
path: reporterOptions.export,
|
||||
content: root.end({
|
||||
pretty: true,
|
||||
indent: ' ',
|
||||
newline: '\n',
|
||||
allowEmpty: false
|
||||
})
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
module.exports = JunitReporter;
|
36
node_modules/newman/lib/reporters/progress.js
generated
vendored
Normal file
36
node_modules/newman/lib/reporters/progress.js
generated
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
var progress = require('cli-progress'),
|
||||
ProgressReporter;
|
||||
|
||||
/**
|
||||
* Little reporter that generates a collection progress status bar on CLI.
|
||||
*
|
||||
* @param {Object} newman - A run object with event handler specification methods.
|
||||
* @param {Function} newman.on - An event setter method that provides hooks for reporting collection run progress.
|
||||
* @param {Object} reporterOptions - A set of reporter specific run options.
|
||||
* @param {Object} options - A set of generic collection run options.
|
||||
* @returns {*}
|
||||
*/
|
||||
ProgressReporter = function (newman, reporterOptions, options) {
|
||||
if (options.silent || reporterOptions.silent) {
|
||||
return;
|
||||
}
|
||||
|
||||
var bar = new progress.Bar({});
|
||||
|
||||
newman.on('start', function (err, o) {
|
||||
if (err) { return; }
|
||||
|
||||
bar.start(o.cursor.length * o.cursor.cycles, 0);
|
||||
});
|
||||
|
||||
newman.on('item', function () {
|
||||
bar.increment();
|
||||
});
|
||||
|
||||
newman.on('done', function () {
|
||||
bar.stop();
|
||||
});
|
||||
};
|
||||
|
||||
ProgressReporter.prototype.dominant = true;
|
||||
module.exports = ProgressReporter;
|
Reference in New Issue
Block a user