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:
150
node_modules/newman/bin/newman.js
generated
vendored
Normal file
150
node_modules/newman/bin/newman.js
generated
vendored
Normal file
@@ -0,0 +1,150 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
require('../lib/node-version-check'); // @note that this should not respect CLI --silent
|
||||
|
||||
const _ = require('lodash'),
|
||||
waterfall = require('async/waterfall'),
|
||||
{ Command } = require('commander'),
|
||||
program = new Command(),
|
||||
version = require('../package.json').version,
|
||||
newman = require('../'),
|
||||
util = require('./util');
|
||||
|
||||
program
|
||||
.name('newman')
|
||||
.addHelpCommand(false)
|
||||
.version(version, '-v, --version');
|
||||
|
||||
// The `run` command allows you to specify a collection to be run with the provided options.
|
||||
program
|
||||
.command('run <collection>')
|
||||
.description('Initiate a Postman Collection run from a given URL or path')
|
||||
.usage('<collection> [options]')
|
||||
.option('-e, --environment <path>', 'Specify a URL or path to a Postman Environment')
|
||||
.option('-g, --globals <path>', 'Specify a URL or path to a file containing Postman Globals')
|
||||
.option('-r, --reporters [reporters]', 'Specify the reporters to use for this run', util.cast.csvParse, ['cli'])
|
||||
.option('-n, --iteration-count <n>', 'Define the number of iterations to run', util.cast.integer)
|
||||
.option('-d, --iteration-data <path>', 'Specify a data file to use for iterations (either JSON or CSV)')
|
||||
.option('--folder <path>',
|
||||
'Specify the folder to run from a collection. Can be specified multiple times to run multiple folders',
|
||||
util.cast.memoize, [])
|
||||
.option('--global-var <value>',
|
||||
'Allows the specification of global variables via the command line, in a key=value format',
|
||||
util.cast.memoizeKeyVal, [])
|
||||
.option('--env-var <value>',
|
||||
'Allows the specification of environment variables via the command line, in a key=value format',
|
||||
util.cast.memoizeKeyVal, [])
|
||||
.option('--export-environment <path>', 'Exports the final environment to a file after completing the run')
|
||||
.option('--export-globals <path>', 'Exports the final globals to a file after completing the run')
|
||||
.option('--export-collection <path>', 'Exports the executed collection to a file after completing the run')
|
||||
.option('--postman-api-key <apiKey>', 'API Key used to load the resources from the Postman API')
|
||||
.option('--bail [modifiers]',
|
||||
'Specify whether or not to gracefully stop a collection run on encountering an error' +
|
||||
' and whether to end the run with an error based on the optional modifier', util.cast.csvParse)
|
||||
.option('--ignore-redirects', 'Prevents Newman from automatically following 3XX redirect responses')
|
||||
.option('-x , --suppress-exit-code', 'Specify whether or not to override the default exit code for the current run')
|
||||
.option('--silent', 'Prevents Newman from showing output to CLI')
|
||||
.option('--disable-unicode', 'Forces Unicode compliant symbols to be replaced by their plain text equivalents')
|
||||
.option('--color <value>', 'Enable/Disable colored output (auto|on|off)', util.cast.colorOptions, 'auto')
|
||||
.option('--delay-request [n]', 'Specify the extent of delay between requests (milliseconds)', util.cast.integer, 0)
|
||||
.option('--timeout [n]', 'Specify a timeout for collection run (milliseconds)', util.cast.integer, 0)
|
||||
.option('--timeout-request [n]', 'Specify a timeout for requests (milliseconds)', util.cast.integer, 0)
|
||||
.option('--timeout-script [n]', 'Specify a timeout for scripts (milliseconds)', util.cast.integer, 0)
|
||||
.option('--working-dir <path>', 'Specify the path to the working directory')
|
||||
.option('--no-insecure-file-read', 'Prevents reading the files situated outside of the working directory')
|
||||
.option('-k, --insecure', 'Disables SSL validations')
|
||||
.option('--ssl-client-cert-list <path>', 'Specify the path to a client certificates configurations (JSON)')
|
||||
.option('--ssl-client-cert <path>', 'Specify the path to a client certificate (PEM)')
|
||||
.option('--ssl-client-key <path>', 'Specify the path to a client certificate private key')
|
||||
.option('--ssl-client-passphrase <passphrase>', 'Specify the client certificate passphrase (for protected key)')
|
||||
.option('--ssl-extra-ca-certs <path>', 'Specify additionally trusted CA certificates (PEM)')
|
||||
.option('--cookie-jar <path>', 'Specify the path to a custom cookie jar (serialized tough-cookie JSON) ')
|
||||
.option('--export-cookie-jar <path>', 'Exports the cookie jar to a file after completing the run')
|
||||
.option('--verbose', 'Show detailed information of collection run and each request sent')
|
||||
.action((collection, command) => {
|
||||
let options = util.commanderToObject(command),
|
||||
|
||||
// parse custom reporter options
|
||||
reporterOptions = util.parseNestedOptions(program._originalArgs, '--reporter-', options.reporters);
|
||||
|
||||
// Inject additional properties into the options object
|
||||
options.collection = collection;
|
||||
options.reporterOptions = reporterOptions._generic;
|
||||
options.reporter = _.transform(_.omit(reporterOptions, '_generic'), (acc, value, key) => {
|
||||
acc[key] = _.assignIn(value, reporterOptions._generic); // overrides reporter options with _generic
|
||||
}, {});
|
||||
|
||||
newman.run(options, function (err, summary) {
|
||||
const runError = err || summary.run.error || summary.run.failures.length;
|
||||
|
||||
if (err) {
|
||||
console.error(`error: ${err.message || err}\n`);
|
||||
err.friendly && console.error(` ${err.friendly}\n`);
|
||||
}
|
||||
runError && !_.get(options, 'suppressExitCode') && process.exit(1);
|
||||
});
|
||||
});
|
||||
|
||||
program.addHelpText('after', `
|
||||
To get available options for a command:
|
||||
newman <command> -h`);
|
||||
|
||||
// Warn on invalid command and then exits.
|
||||
program.on('command:*', (command) => {
|
||||
console.error(`error: invalid command \`${command}\`\n`);
|
||||
program.help();
|
||||
});
|
||||
|
||||
/**
|
||||
* Starts the script execution.
|
||||
* callback is required when this is required as a module in tests.
|
||||
*
|
||||
* @param {String[]} argv - Argument vector.
|
||||
* @param {?Function} callback - The callback function invoked on the completion of execution.
|
||||
*/
|
||||
function run (argv, callback) {
|
||||
waterfall([
|
||||
(next) => {
|
||||
// cache original argv, required to parse nested options later.
|
||||
program._originalArgs = argv;
|
||||
// omit custom nested options, otherwise commander will throw unknown options error
|
||||
next(null, util.omitNestedOptions(argv, '--reporter-'));
|
||||
},
|
||||
(args, next) => {
|
||||
let error = null;
|
||||
|
||||
try {
|
||||
program.parse(args);
|
||||
}
|
||||
catch (err) {
|
||||
error = err;
|
||||
}
|
||||
next(error);
|
||||
},
|
||||
(next) => {
|
||||
// throw error if no argument is provided.
|
||||
next(program.args.length ? null : new Error('no arguments provided'));
|
||||
}
|
||||
], (error) => {
|
||||
// invoke callback if this is required as module, used in tests.
|
||||
if (callback) { return callback(error); }
|
||||
|
||||
// in case of an error, log error message and print help message.
|
||||
if (error) {
|
||||
console.error(`error: ${error.message || error}\n`);
|
||||
program.help();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// This hack has been added from https://github.com/nodejs/node/issues/6456#issue-151760275
|
||||
// @todo: remove when https://github.com/nodejs/node/issues/6456 has been fixed
|
||||
(Number(process.version[1]) >= 6) && [process.stdout, process.stderr].forEach((s) => {
|
||||
s && s.isTTY && s._handle && s._handle.setBlocking && s._handle.setBlocking(true);
|
||||
});
|
||||
|
||||
// Run this script if this is a direct stdin.
|
||||
!module.parent && run(process.argv);
|
||||
|
||||
// Export to allow debugging and testing.
|
||||
module.exports = run;
|
203
node_modules/newman/bin/util.js
generated
vendored
Normal file
203
node_modules/newman/bin/util.js
generated
vendored
Normal file
@@ -0,0 +1,203 @@
|
||||
const _ = require('lodash');
|
||||
|
||||
module.exports = {
|
||||
|
||||
cast: {
|
||||
/**
|
||||
* Helper to coerce number like strings into integers.
|
||||
* Perform safety checks, and return the result.
|
||||
*
|
||||
* @param {String} arg - The stringified number argument.
|
||||
* @returns {Number} - The supplied argument, casted to an integer.
|
||||
*/
|
||||
integer: (arg) => {
|
||||
const num = Number(arg);
|
||||
|
||||
if (!_.isSafeInteger(num) || num <= 0) {
|
||||
throw new Error('The value must be a positive integer.');
|
||||
}
|
||||
|
||||
return num.valueOf();
|
||||
},
|
||||
|
||||
/**
|
||||
* Helper for collecting argument passed multiple times.
|
||||
*
|
||||
* --folder f1 --folder f2
|
||||
*
|
||||
* @param {String} val - The argument value.
|
||||
* @param {String[]} memo - The array that is populated by argument values.
|
||||
* @returns {String[]} - The array of argument values collected.
|
||||
*/
|
||||
memoize: (val, memo) => {
|
||||
memo.push(val);
|
||||
|
||||
return memo;
|
||||
},
|
||||
|
||||
/**
|
||||
* Helper for collecting argument passed multiple times as key=value.
|
||||
*
|
||||
* --global-var "foo=bar" --global-var "alpha=beta"
|
||||
*
|
||||
* @param {String} val - The argument value, passed as key=value.
|
||||
* @param {Array} memo - The array that is populated by key value pairs.
|
||||
* @returns {Array} - [{key, value}] - The object representation of the current CLI variable.
|
||||
*/
|
||||
memoizeKeyVal: (val, memo) => {
|
||||
let arg,
|
||||
eqIndex = val.indexOf('=');
|
||||
|
||||
// This is done instead of splitting by `=` to avoid chopping off `=` that could be present in the value
|
||||
arg = eqIndex !== -1 ? {
|
||||
key: val.slice(0, eqIndex),
|
||||
value: val.slice(eqIndex + 1)
|
||||
} : {
|
||||
key: val,
|
||||
value: undefined
|
||||
};
|
||||
|
||||
memo.push(arg);
|
||||
|
||||
return memo;
|
||||
},
|
||||
|
||||
/**
|
||||
* Helper to coerce comma separated string to an array.
|
||||
*
|
||||
* eg. item1,item2
|
||||
*
|
||||
* @param {String} list - The comma separated string.
|
||||
* @returns {String[]} - [item1, item2] - The array representation of the passed string.
|
||||
*/
|
||||
csvParse: (list) => {
|
||||
return _.split(list, ',');
|
||||
},
|
||||
|
||||
colorOptions: (value) => {
|
||||
if (!(/^(auto|on|off)$/).test(value)) {
|
||||
throw new Error(`invalid value \`${value}\` for --color. Expected: auto|on|off`);
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Extract selected options in the provided command.
|
||||
* Omits commander private variables and other objects.
|
||||
*
|
||||
* @param {Object} command - Commander.Command Instance
|
||||
* @returns {Object} - Extracted options from command
|
||||
*/
|
||||
commanderToObject: (command) => {
|
||||
return _.reduce(command, (result, value, key) => {
|
||||
// Exclude command's private `_` variables and other objects
|
||||
const validProp = !_.startsWith(key, '_') && !_.includes(['commands', 'options', 'parent'], key);
|
||||
|
||||
validProp && (result[key] = value);
|
||||
|
||||
return result;
|
||||
}, {});
|
||||
},
|
||||
|
||||
/**
|
||||
* Remove nested options having the provided prefix from `process.argv`.
|
||||
*
|
||||
* @param {String[]} argv - Argument vector.
|
||||
* @param {String} optionPrefix - Argument prefix to search for.
|
||||
* @returns {String[]} - All arguments without prefixed options and their values
|
||||
*/
|
||||
omitNestedOptions: (argv, optionPrefix) => {
|
||||
let args = [],
|
||||
len,
|
||||
i;
|
||||
|
||||
for (i = 0, len = argv.length; i < len; i++) {
|
||||
if (!_.startsWith(argv[i], optionPrefix)) {
|
||||
args.push(argv[i]);
|
||||
continue;
|
||||
}
|
||||
|
||||
// For prefixed args also omit its value, --prefix-arg value
|
||||
if (argv[i + 1] && !_.startsWith(argv[i + 1], '-')) {
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
return args;
|
||||
},
|
||||
|
||||
/**
|
||||
* Parse nested options having the provided prefix from `process.argv`.
|
||||
*
|
||||
* @param {String[]} argv - Argument vector.
|
||||
* @param {String} optionPrefix - Argument prefix to search for.
|
||||
* @param {String[]} options - Selected options.
|
||||
* @returns {Object} Parsed object with nested options.
|
||||
*
|
||||
* @example
|
||||
* let argv = ['--reporters=json,html', '--reporter-html-template=template.hb', '--reporter-export=path'],
|
||||
* options = ['json', 'html'];
|
||||
* parseNestedOptions(argv, '--reporter-', options);
|
||||
* //returns
|
||||
* {
|
||||
* _generic: { export: path },
|
||||
* html: { template: template.hb },
|
||||
* json: {}
|
||||
* }
|
||||
*
|
||||
*/
|
||||
parseNestedOptions: (argv, optionPrefix, options) => {
|
||||
let args = [],
|
||||
parsed = { _generic: {} },
|
||||
name,
|
||||
path,
|
||||
len,
|
||||
eqIndex,
|
||||
i;
|
||||
|
||||
// Extract prefixed arguments from argv
|
||||
for (i = 0, len = argv.length; i < len; i++) {
|
||||
const arg = argv[i];
|
||||
|
||||
if (!_.startsWith(arg, optionPrefix)) { continue; } // skip non-prefixed args
|
||||
|
||||
eqIndex = arg.indexOf('=');
|
||||
|
||||
if (eqIndex !== -1) {
|
||||
// Split the attribute if its like key=value
|
||||
args.push(arg.slice(0, eqIndex), arg.slice(eqIndex + 1));
|
||||
}
|
||||
else if (argv[i + 1] && !_.startsWith(argv[i + 1], '-')) {
|
||||
// Also push the next parameter if it's not an option.
|
||||
args.push(arg, argv[++i]);
|
||||
}
|
||||
else {
|
||||
args.push(arg);
|
||||
}
|
||||
}
|
||||
|
||||
// ensure that whatever option is provided a blank options object is forwarded
|
||||
_.forEach(options, (option) => { parsed[option] = {}; });
|
||||
// Parse nested options
|
||||
for (i = 0, len = args.length; i < len; i++) {
|
||||
const arg = args[i].replace(optionPrefix, '');
|
||||
|
||||
name = _.split(arg, '-', 1)[0]; // eg. `cli` in --reporter-cli-silent
|
||||
|
||||
// if we have a valid option, the path should be the <name>.camelCaseOfTheRest
|
||||
// otherwise, we add it to the generic options.
|
||||
path = _.includes(options, name) ?
|
||||
[name, _.camelCase(arg.replace(name + '-', ''))].join('.') :
|
||||
['_generic', _.camelCase(arg)].join('.');
|
||||
|
||||
// If the next arg is an option, set the current arg to true,
|
||||
// otherwise set it to the next arg.
|
||||
_.set(parsed, path, (!args[i + 1] || _.startsWith(args[i + 1], '-')) ? true : args[++i]);
|
||||
}
|
||||
|
||||
return parsed;
|
||||
}
|
||||
|
||||
};
|
Reference in New Issue
Block a user