Skip to content

Add support for apache bench code gen #221

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: develop
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions ADDITIONAL_DEPENDENCIES.md
Original file line number Diff line number Diff line change
@@ -30,6 +30,9 @@
### ruby
1. [ruby](https://www.ruby-lang.org/en/downloads)

### shell-apache-bench
1. [apache-bench](https://httpd.apache.org/docs/2.4/programs/ab.html)

### shell-httpie
1. [httpie](https://httpie.org/#installation)

1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -37,6 +37,7 @@ List of supported code generators:
| PowerShell | RestMethod |
| Ruby | Net:HTTP |
| Shell | Httpie |
| Shell | Apache Bench |
| Shell | wget |
| Swift | URLSession |
## Table of contents
66 changes: 66 additions & 0 deletions codegens/shell-apache-bench/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
.DS_Store
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# Runtime data
pids
*.pid
*.seed
*.pid.lock

# Prevent IDE stuff
.idea
.vscode
*.sublime-*

# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov

# Coverage directory used by tools like istanbul
.coverage

# nyc test coverage
.nyc_output

# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt

# Bower dependency directory (https://bower.io/)
bower_components

# node-waf configuration
.lock-wscript

# Compiled binary addons (http://nodejs.org/api/addons.html)
build/Release

# Dependency directories
node_modules/
jspm_packages/

# Typescript v1 declaration files
typings/

# Optional npm cache directory
.npm

# Optional eslint cache
.eslintcache

# Optional REPL history
.node_repl_history

# Output of 'npm pack'
*.tgz

# Yarn Integrity file
.yarn-integrity

# dotenv environment variables file
.env

out/
34 changes: 34 additions & 0 deletions codegens/shell-apache-bench/.jsdoc-config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
{
"tags": {
"allowUnknownTags": true,
"dictionaries": ["jsdoc", "closure"]
},
"source": {
"include": [ ],
"includePattern": ".+\\.js(doc)?$",
"excludePattern": "(^|\\/|\\\\)_"
},

"plugins": [
"plugins/markdown"
],

"templates": {
"cleverLinks": false,
"monospaceLinks": false,
"highlightTutorialCode" : true
},

"opts": {
"template": "./node_modules/postman-jsdoc-theme",
"encoding": "utf8",
"destination": "./out/docs",
"recurse": true,
"readme": "README.md"
},

"markdown": {
"parser": "gfm",
"hardwrap": false
}
}
74 changes: 74 additions & 0 deletions codegens/shell-apache-bench/.npmignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
### NPM Specific: Disregard recursive project files
### ===============================================
/.editorconfig
/.gitmodules
/test

### Borrowed from .gitignore
### ========================

# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# Runtime data
pids
*.pid
*.seed
*.pid.lock

# Prevent IDE stuff
.idea
.vscode
*.sublime-*

# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov

# Coverage directory used by tools like istanbul
.coverage

# nyc test coverage
.nyc_output

# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt

# Bower dependency directory (https://bower.io/)
bower_components

# node-waf configuration
.lock-wscript

# Compiled binary addons (http://nodejs.org/api/addons.html)
build/Release

# Dependency directories
node_modules/
jspm_packages/

# Typescript v1 declaration files
typings/

# Optional npm cache directory
.npm

# Optional eslint cache
.eslintcache

# Optional REPL history
.node_repl_history

# Output of 'npm pack'
*.tgz

# Yarn Integrity file
.yarn-integrity

# dotenv environment variables file
.env

out/
65 changes: 65 additions & 0 deletions codegens/shell-apache-bench/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# Code-Gen: Postman SDK Request -> Shell-Apache-Bench Snippet Converter

This module is used to convert Postman SDK-Request object in Shell-Apache-Bench variant snippet

#### Prerequisites
To run this repository, ensure that you have NodeJS >= v4. A copy of the NodeJS installable can be downloaded from https://nodejs.org/en/download/package-manager.

## Using the Module
This module exposes two function `convert()` and `getOptions()`

### Convert

Convert function sanitizes the inputs, overrides options with the default ones if not provided and return the code snippet in the desired format.

It requires 3 mandatory parameters `request`, `callback` and `options`

* `request` - postman SDK-request object

* `options` is an object with the following properties

* `indentType` : can be `Tab` or `Space` (default: 'Space')
* `indentCount` : Integer denoting the number of tabs/spaces required for indentation, range 0-8 (default : for indentType Tab : 2, for indentType Space : 4)
* `requestTimeout` : Integer denoting time after which the request will bail out in milli-seconds (default: 0 -> never bail out)
* `trimRequestBody` : Trim request body fields (default: false)

These plugin options will be used if no options are passed to the convert function.

* `callback` : callback function with `error` and `snippet` parameters where snippet is the desired output

#### Example
```javascript
sdk = require('postman-collection');

var request = sdk.Request('http://www.google.com'),
options = {indentType: 'Tab', indentCount: 4, trimRequestBody: true};

convert(request, options, function (err, snippet) {
if (err) {
// perform desired action of logging the error
}
// perform action with the snippet
});
```

### getOptions function

This function returns a list of options supported by this codegen.

#### Example
```js
var options = getOptions();

console.log(options);
// output
// [
// {
// name: 'Set indentation count',
// id: 'indentCount',
// type: 'positiveInteger',
// default: 2,
// description: 'Set the number of indentation characters to add per code level'
// },
// ...
// ]
```
1 change: 1 addition & 0 deletions codegens/shell-apache-bench/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module.exports = require('./lib');
4 changes: 4 additions & 0 deletions codegens/shell-apache-bench/lib/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
module.exports = {
convert: require('./shell-apache-bench').convert,
getOptions: require('./shell-apache-bench').getOptions
};
455 changes: 455 additions & 0 deletions codegens/shell-apache-bench/lib/lodash.js

Large diffs are not rendered by default.

161 changes: 161 additions & 0 deletions codegens/shell-apache-bench/lib/shell-apache-bench.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
var _ = require('./lodash'),
parseBody = require('./util/parseBody'),
sanitize = require('./util/sanitize').sanitize,
sanitizeOptions = require('./util/sanitize').sanitizeOptions,
self;

/**
* Used to parse the request headers
*
* @param {Object} request - postman SDK-request object
* @param {String} indentation - used for indenting snippet's structure
* @returns {String} - request headers in the desired format
*/
function getHeaders (request, indentation) {
var headerArray = request.toJSON().header,
headerMap;

if (!_.isEmpty(headerArray)) {
headerArray = _.reject(headerArray, 'disabled');
headerMap = _.map(headerArray, function (header) {
return `${indentation}-H '${sanitize(header.key, 'header', true)}: ` +
`${sanitize(header.value, 'header')}' \\`;
});
return headerMap.join('\n');
}
return '';
}

self = module.exports = {
/**
* Used to return options which are specific to a particular plugin
*
* @module getOptions
*
* @returns {Array}
*/
getOptions: function () {
// options can be added for this for no certificate check and silent so no output is logged.
// Also, place where to log the output if required.
return [
{
name: 'Set indentation count',
id: 'indentCount',
type: 'positiveInteger',
default: 2,
description: 'Set the number of indentation characters to add per code level'
},
{
name: 'Set indentation type',
id: 'indentType',
type: 'enum',
availableOptions: ['Tab', 'Space'],
default: 'Space',
description: 'Select the character used to indent lines of code'
},
{
name: 'Set request timeout',
id: 'requestTimeout',
type: 'positiveInteger',
default: 0,
description: 'Set number of milliseconds the request should wait for a response' +
' before timing out (use 0 for infinity)'
},
{
name: 'Trim request body fields',
id: 'trimRequestBody',
type: 'boolean',
default: false,
description: 'Remove white space and additional lines that may affect the server\'s response'
}
];
},

/**
* Used to convert the postman sdk-request object in apache bench reuqest snippet
*
* @module convert
*
* @param {Object} request - postman SDK-request object
* @param {Object} options
* @param {String} options.indentType - type of indentation eg: Space / Tab (default: Space)
* @param {Number} options.indentCount - frequency of indent (default: 4 for indentType: Space,
default: 1 for indentType: Tab)
* @param {Number} options.requestTimeout : time in milli-seconds after which request will bail out
(default: 0 -> never bail out)
* @param {Boolean} options.trimRequestBody : whether to trim request body fields (default: false)
* @param {Function} callback - function with parameters (error, snippet)
*/
convert: function (request, options, callback) {
var snippet = '',
indentation = '',
identity = '',
isFormDataFile = false;

if (_.isFunction(options)) {
callback = options;
options = {};
}
else if (!_.isFunction(callback)) {
throw new Error('Shell-Apache-Bench~convert: Callback is not a function');
}

options = sanitizeOptions(options, self.getOptions());

identity = options.indentType === 'Tab' ? '\t' : ' ';
indentation = identity.repeat(options.indentCount);
// concatenation and making up the final string

if (request.body && request.body.mode === 'formdata') {
_.forEach(request.body.toJSON().formdata, (data) => {
if (!data.disabled && data.type === 'file') {
isFormDataFile = true;
}
});
}
if (isFormDataFile) {
snippet = '# apache bench converter doesn\'t support file upload via form data, see apache bench manual \\\n';
}
snippet += 'ab -n 1 -c 1\\\n';
// Apache Bench accepts timeout in seconds(conversion from milli-seconds to seconds)
if (options.requestTimeout > 0) {
snippet += `${indentation}-s ${Math.floor(options.requestTimeout / 1000)} \\\n`;
}
if (request.body && !request.headers.has('Content-Type')) {
if (request.body.mode === 'file') {
request.addHeader({
key: 'Content-Type',
value: 'text/plain'
});
}
else if (request.body.mode === 'graphql') {
request.addHeader({
key: 'Content-Type',
value: 'application/json'
});
}
}
if (!_.isEmpty(request.toJSON().header)) {
snippet += `${getHeaders(request, indentation)}\n`;
}
let body = parseBody(request.toJSON(), options.trimRequestBody, indentation);

// apache benchmark support body only on post and put
if (!_.isEmpty(body)) {
if (request.method === 'POST') {
snippet = `echo ${body} | ${snippet} -p /dev/stdin`;
}
else if (request.method === 'PUT') {
snippet = `echo ${body} | ${snippet} -u /dev/stdin`;
}
else {
snippet = `# apache bench doesn't support body with method ${request.method}, see apache bench manual \\\n`;
}
}
else {
snippet += `${indentation}-m ${request.method} \\\n`;
}
snippet += `${indentation}'${sanitize(request.url.toString(), 'url')}'`;
return callback(null, snippet);
}
};
72 changes: 72 additions & 0 deletions codegens/shell-apache-bench/lib/util/parseBody.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
var _ = require('../lodash'),
sanitize = require('./sanitize').sanitize;

/**
* Used to parse the body of the postman SDK-request and return in the desired format
*
* @param {Object} request - postman SDK-request object
* @param {Boolean} trimRequestBody - whether to trim request body fields
* @returns {String} - request body
*/
module.exports = function (request, trimRequestBody) {
// used to check whether body is present in the request and return accordingly
if (request.body) {
var requestBody = '',
bodyMap = [],
enabledBodyList;

switch (request.body.mode) {
case 'raw':
if (!_.isEmpty(request.body[request.body.mode])) {
requestBody += `'${sanitize(request.body[request.body.mode], request.body.mode, trimRequestBody)}' \\\n`;
}
return requestBody;
// eslint-disable-next-line no-case-declarations
case 'graphql':
let query = request.body[request.body.mode].query,
graphqlVariables;
try {
graphqlVariables = JSON.parse(request.body[request.body.mode].variables);
}
catch (e) {
graphqlVariables = {};
}
requestBody += `'${sanitize(JSON.stringify({
query: query,
variables: graphqlVariables
}), 'raw', trimRequestBody)}' \\\n`;
return requestBody;
case 'urlencoded':
enabledBodyList = _.reject(request.body[request.body.mode], 'disabled');
if (!_.isEmpty(enabledBodyList)) {
bodyMap = _.map(enabledBodyList, function (value) {
return `${sanitize(value.key, request.body.mode, trimRequestBody)}=` +
`${sanitize(value.value, request.body.mode, trimRequestBody)}`;
});
requestBody = `'${bodyMap.join('&')}' \\\n`;
}
return requestBody;
case 'formdata':
enabledBodyList = _.reject(request.body[request.body.mode], 'disabled');
if (!_.isEmpty(enabledBodyList)) {
_.forEach(enabledBodyList, function (value) {
if (value.type === 'text') {
bodyMap.push(`${sanitize(value.key, request.body.mode, trimRequestBody)}=` +
`${sanitize(value.value, request.body.mode, trimRequestBody)}`);
}
});
requestBody = `'${bodyMap.join('&')}' \\\n`;
}
return requestBody;
/* istanbul ignore next */
case 'file':
requestBody += `${sanitize(request.body[request.body.mode].src,
request.body.mode, trimRequestBody)}' \\\n`;
return requestBody;
default:
return requestBody;

}
}
return '';
};
105 changes: 105 additions & 0 deletions codegens/shell-apache-bench/lib/util/sanitize.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
module.exports = {
/**
* sanitization of values : trim, escape characters
*
* @param {String} inputString - input
* @param {String} escapeCharFor - escape for headers, body: raw, formdata etc
* @param {Boolean} [inputTrim] - whether to trim the input
* @returns {String}
*/
sanitize: function (inputString, escapeCharFor, inputTrim) {

if (typeof inputString !== 'string') {
return '';
}
inputString = inputTrim && typeof inputTrim === 'boolean' ? inputString.trim() : inputString;
if (escapeCharFor && typeof escapeCharFor === 'string') {
switch (escapeCharFor) {
case 'raw':
return inputString.replace(/'/g, '\'\\\'\'');
case 'urlencoded':
return encodeURIComponent(inputString).replace(/'/g, '\'\\\'\'');
case 'formdata':
return inputString.replace(/'/g, '\\\'');
/* istanbul ignore next */
case 'file':
return inputString.replace(/\\/g, '\\\\').replace(/'/g, '\\\'');
case 'header':
return inputString.replace(/'/g, '\'\\\'\'');
case 'url':
return inputString.replace(/'/g, '\'\\\'\'');
default:
return inputString.replace(/'/g, '\'');
}
}
return inputString;
},

/**
* sanitizes input options
*
* @param {Object} options - Options provided by the user
* @param {Array} optionsArray - options array received from getOptions function
*
* @returns {Object} - Sanitized options object
*/
sanitizeOptions: function (options, optionsArray) {
var result = {},
defaultOptions = {},
id;
optionsArray.forEach((option) => {
defaultOptions[option.id] = {
default: option.default,
type: option.type
};
if (option.type === 'enum') {
defaultOptions[option.id].availableOptions = option.availableOptions;
}
});

for (id in options) {
if (options.hasOwnProperty(id)) {
if (defaultOptions[id] === undefined) {
continue;
}
switch (defaultOptions[id].type) {
case 'boolean':
if (typeof options[id] !== 'boolean') {
result[id] = defaultOptions[id].default;
}
else {
result[id] = options[id];
}
break;
case 'positiveInteger':
if (typeof options[id] !== 'number' || options[id] < 0) {
result[id] = defaultOptions[id].default;
}
else {
result[id] = options[id];
}
break;
case 'enum':
if (!defaultOptions[id].availableOptions.includes(options[id])) {
result[id] = defaultOptions[id].default;
}
else {
result[id] = options[id];
}
break;
default:
result[id] = options[id];
}
}
}

for (id in defaultOptions) {
if (defaultOptions.hasOwnProperty(id)) {
if (result[id] === undefined) {
result[id] = defaultOptions[id].default;
}
}
}
return result;
}
};
5 changes: 5 additions & 0 deletions codegens/shell-apache-bench/npm-shrinkwrap.json
59 changes: 59 additions & 0 deletions codegens/shell-apache-bench/npm/test-lint.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
#!/usr/bin/env node
require('shelljs/global');

var chalk = require('chalk'),
async = require('async'),
ESLintCLIEngine = require('eslint').CLIEngine,

/**
* The list of source code files / directories to be linted.
*
* @type {Array}
*/
LINT_SOURCE_DIRS = [
'./lib',
'./bin',
'./test',
'./examples/*.js',
'./npm/*.js',
'./index.js'
];

module.exports = function (exit) {
// banner line
console.info(chalk.yellow.bold('\nLinting files using eslint...'));

async.waterfall([

/**
* Instantiates an ESLint CLI engine and runs it in the scope defined within LINT_SOURCE_DIRS.
*
* @param {Function} next - The callback function whose invocation marks the end of the lint test run.
* @returns {*}
*/
function (next) {
next(null, (new ESLintCLIEngine()).executeOnFiles(LINT_SOURCE_DIRS));
},

/**
* Processes a test report from the Lint test runner, and displays meaningful results.
*
* @param {Object} report - The overall test report for the current lint test.
* @param {Object} report.results - The set of test results for the current lint run.
* @param {Function} next - The callback whose invocation marks the completion of the post run tasks.
* @returns {*}
*/
function (report, next) {
var errorReport = ESLintCLIEngine.getErrorResults(report.results);
// log the result to CLI
console.info(ESLintCLIEngine.getFormatter()(report.results));
// log the success of the parser if it has no errors
(errorReport && !errorReport.length) && console.info(chalk.green('eslint ok!'));
// ensure that the exit code is non zero in case there was an error
next(Number(errorReport && errorReport.length) || 0);
}
], exit);
};

// ensure we run this script exports if this is a direct stdin.tty run
!module.parent && module.exports(exit);
59 changes: 59 additions & 0 deletions codegens/shell-apache-bench/npm/test-unit.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
#!/usr/bin/env node
/* eslint-env node, es6 */
// ---------------------------------------------------------------------------------------------------------------------
// This script is intended to execute all unit tests.
// ---------------------------------------------------------------------------------------------------------------------

require('shelljs/global');

// set directories and files for test and coverage report
var path = require('path'),

NYC = require('nyc'),
chalk = require('chalk'),
recursive = require('recursive-readdir'),

COV_REPORT_PATH = '.coverage',
SPEC_SOURCE_DIR = path.join(__dirname, '..', 'test', 'unit');

module.exports = function (exit) {
// banner line
console.info(chalk.yellow.bold('Running unit tests using mocha on node...'));

test('-d', COV_REPORT_PATH) && rm('-rf', COV_REPORT_PATH);
mkdir('-p', COV_REPORT_PATH);

var Mocha = require('mocha'),
nyc = new NYC({
reportDir: COV_REPORT_PATH,
tempDirectory: COV_REPORT_PATH,
reporter: ['text', 'lcov', 'text-summary'],
exclude: ['config', 'test'],
hookRunInContext: true,
hookRunInThisContext: true
});

nyc.wrap();
// add all spec files to mocha
recursive(SPEC_SOURCE_DIR, function (err, files) {
if (err) { console.error(err); return exit(1); }

var mocha = new Mocha({ timeout: 1000 * 60 });

files.filter(function (file) { // extract all test files
return (file.substr(-8) === '.test.js');
}).forEach(mocha.addFile.bind(mocha));

mocha.run(function (runError) {
runError && console.error(runError.stack || runError);

nyc.reset();
nyc.writeCoverageFile();
nyc.report();
exit(runError ? 1 : 0);
});
});
};

// ensure we run this script exports if this is a direct stdin.tty run
!module.parent && module.exports(exit);
17 changes: 17 additions & 0 deletions codegens/shell-apache-bench/npm/test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#!/usr/bin/env node
var chalk = require('chalk'),
exit = require('shelljs').exit,
prettyms = require('pretty-ms'),
startedAt = Date.now(),
name = require('../package.json').name;

require('async').series([
require('./test-lint'),
require('./test-unit')
// require('./test-browser')
// require('./test-integration')
], function (code) {
// eslint-disable-next-line max-len
console.info(chalk[code ? 'red' : 'green'](`\n${name}: duration ${prettyms(Date.now() - startedAt)}\n${name}: ${code ? 'not ok' : 'ok'}!`));
exit(code && (typeof code === 'number' ? code : 1) || 0);
});
33 changes: 33 additions & 0 deletions codegens/shell-apache-bench/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
{
"name": "@postman/codegen-shell-apache-bench",
"version": "0.0.1",
"description": "Generates code snippets for a postman collection",
"com_postman_plugin": {
"type": "code_generator",
"lang": "shell",
"variant": "apache-bench",
"syntax_mode": "powershell"
},
"main": "index.js",
"directories": {
"lib": "lib",
"test": "test"
},
"scripts": {
"test": "node npm/test.js",
"test-lint": "node npm/test-lint.js",
"test-unit": "node npm/test-unit.js"
},
"repository": {
"type": "git",
"url": ""
},
"author": "Postman Labs <help@getpostman.com>",
"license": "Apache-2.0",
"homepage": "https://github.com/postmanlabs/code-generators/tree/master/codegens/shell-apache-bench",
"dependencies": {},
"devDependencies": {},
"engines": {
"node": ">=8"
}
}
30 changes: 30 additions & 0 deletions codegens/shell-apache-bench/test/.eslintrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
{
"plugins": [
"mocha"
],
"env": {
"mocha": true,
"node": true,
"es6": true
},
"rules": {
// Mocha
"mocha/handle-done-callback": "error",
"mocha/max-top-level-suites": "error",
"mocha/no-exclusive-tests": "error",
"mocha/no-global-tests": "error",
"mocha/no-hooks-for-single-case": "off",
"mocha/no-hooks": "off",
"mocha/no-identical-title": "error",
"mocha/no-mocha-arrows": "error",
"mocha/no-nested-tests": "error",
"mocha/no-pending-tests": "error",
"mocha/no-return-and-callback": "error",
"mocha/no-sibling-hooks": "error",
"mocha/no-skipped-tests": "warn",
"mocha/no-synchronous-tests": "off",
"mocha/no-top-level-hooks": "warn",
"mocha/valid-test-description": "off",
"mocha/valid-suite-description": "off"
}
}
Empty file.
194 changes: 194 additions & 0 deletions codegens/shell-apache-bench/test/unit/converter.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,194 @@
var expect = require('chai').expect,
sdk = require('postman-collection'),
sanitize = require('../../lib/util/sanitize').sanitize,
convert = require('../../lib/index').convert,
getOptions = require('../../lib/index').getOptions,
mainCollection = require('../unit/fixtures/sample_collection.json');

describe('Shell-Apache-Bench converter', function () {


describe('convert function', function () {
var request = new sdk.Request(mainCollection.item[0].request),
snippetArray,
options = {
indentType: 'Tab',
indentCount: 2
};

const SINGLE_SPACE = ' ',
SINGLE_TAB = '\t';

it('should return snippet with requestTimeout given option', function () {
convert(request, { requestTimeout: 10000 }, function (error, snippet) {
if (error) {
expect.fail(null, null, error);
return;
}
expect(snippet).to.include('-s 10');
});
});

it('should generate snippet with default options given no options', function () {
convert(request, function (error, snippet) {
if (error) {
expect.fail(null, null, error);
return;
}
snippetArray = snippet.split('\n');
for (var i = 0; i < snippetArray.length; i++) {
if (snippetArray[i].startsWith('ab')) {
expect(snippetArray[i + 1].substr(0, 2)).to.equal(SINGLE_SPACE.repeat(2));
expect(snippetArray[i + 1].charAt(3)).to.not.equal(SINGLE_SPACE);
}
}
});
});

it('should generate snippet with Tab as an indent type with exact indent count', function () {
convert(request, options, function (error, snippet) {
if (error) {
expect.fail(null, null, error);
return;
}
snippetArray = snippet.split('\n');
for (var i = 0; i < snippetArray.length; i++) {
if (snippetArray[i].startsWith('ab')) {
expect(snippetArray[i + 1].substr(0, 2)).to.equal(SINGLE_TAB.repeat(2));
expect(snippetArray[i + 1].charAt(2)).to.not.equal(SINGLE_TAB);
}
}
});
});

it('should trim header keys and not trim header values', function () {
var request = new sdk.Request({
'method': 'GET',
'header': [
{
'key': ' key_containing_whitespaces ',
'value': ' value_containing_whitespaces '
}
],
'url': {
'raw': 'https://google.com',
'protocol': 'https',
'host': [
'google',
'com'
]
}
});
convert(request, {}, function (error, snippet) {
if (error) {
expect.fail(null, null, error);
}
expect(snippet).to.be.a('string');
// one extra space in matching the output because we add key:<space>value in the snippet
expect(snippet).to.include('-H \'key_containing_whitespaces: value_containing_whitespaces \'');
});
});

it('should generate snippet for formdata body mode', function () {
var request = new sdk.Request({
'method': 'POST',
'header': [],
'body': {
'mode': 'formdata',
'formdata': [
{
'key': 'text key',
'type': 'text',
'value': 'text value'

},
{
'key': 'file key',
'type': 'file',
'src': '/path'
}
]
},
'url': {
'raw': 'https://postman-echo.com/post',
'protocol': 'https',
'host': [
'postman-echo',
'com'
],
'path': [
'post'
]
}
});
convert(request, {}, function (error, snippet) {
if (error) {
expect.fail(null, null, error);
}
expect(snippet).to.be.a('string');
expect(snippet).to.include('# apache bench converter doesn\'t support file upload via form data');
expect(snippet).to.not.include('file key');
expect(snippet).to.include('text key=text value');
});
});

it('should generate valid snippet for single/double quotes in url', function () {
var request = new sdk.Request({
'method': 'GET',
'header': [],
'url': {
'raw': 'https://postman-echo.com/get?query1=b\'b&query2=c"c',
'protocol': 'https',
'host': [
'postman-echo',
'com'
],
'path': [
'get'
],
'query': [
{
'key': 'query1',
'value': "b'b" // eslint-disable-line quotes
},
{
'key': 'query2',
'value': 'c"c'
}
]
}
});
convert(request, {}, function (error, snippet) {
if (error) {
expect.fail(null, null, error);
}
expect(snippet).to.be.a('string');
// To escape a single quotes inside a single quoted string, '\'(all 3 characters)
// needs to be added before '(single quote)
// eslint-disable-next-line quotes
expect(snippet).to.include("'https://postman-echo.com/get?query1=b'\\''b&query2=c\"c'");
});
});
});

describe('getOptions function', function () {
it('should return array of options for shell-apache-bench converter', function () {
expect(getOptions()).to.be.an('array');
});

it('should return all the valid options', function () {
expect(getOptions()[0]).to.have.property('id', 'indentCount');
expect(getOptions()[1]).to.have.property('id', 'indentType');
expect(getOptions()[2]).to.have.property('id', 'requestTimeout');
expect(getOptions()[3]).to.have.property('id', 'trimRequestBody');
});
});

describe('sanitize function', function () {
it('should handle invalid parameters', function () {
expect(sanitize(123, 'raw', false)).to.equal('');
expect(sanitize('inputString', 123, false)).to.equal('inputString');
expect(sanitize(' inputString', 'test', true)).to.equal('inputString');
});
});
});
1,231 changes: 1,231 additions & 0 deletions codegens/shell-apache-bench/test/unit/fixtures/sample_collection.json

Large diffs are not rendered by default.

28 changes: 28 additions & 0 deletions codegens/shell-apache-bench/test/unit/package.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
var expect = require('chai').expect,
path = require('path'),
package = require('../../package.json');

describe('package.json', function () {

it('should have com_postman_plugin object with valid properties', function () {
expect(package).to.have.property('com_postman_plugin');
expect(package.com_postman_plugin.type).to.equal('code_generator');
expect(package.com_postman_plugin.lang).to.be.a('string');
expect(package.com_postman_plugin.variant).to.be.a('string');
expect(package.com_postman_plugin.syntax_mode).to.be.a('string');
});

it('should have main property with relative path to object with convert property', function () {
var languageModule;
expect(package.main).to.be.a('string');
try {
languageModule = require(path.resolve('.', package.main));
}
catch (error) {
console.error(error);
}
expect(languageModule).to.be.a('object');
expect(languageModule.convert).to.be.a('function');
});

});