[
  {
    "path": ".dockerignore",
    "content": "# PLATFORM\n# ========\n# All exclusions that are specific to the NPM, GIT, IDE and Operating Systems.\n\n# - Do not allow installed node modules to be committed. Doing `npm install -d` will bring them in root or other places.\nnode_modules\n\n# - Do not commit any log file from anywhere\n*.log\n*.log.*\n\n# - Prevent addition of OS specific file explorer files\nThumbs.db\n.DS_Store\n\n# Prevent IDE stuff\n.idea\n.vscode\n\n# PROJECT\n# =======\n# Configuration pertaining to project specific repository structure.\n\n# - Prevent Sublime text IDE files from being committed to repository\n*.sublime-*\n\n# - Allow sublime text project file to be committed in the development directory.\n!/develop/*.sublime-project\n\n# - Prevent CI output files from being Added\n/out/\n/newman/\n\n# - Prevent diff backups from SourceTree from showing as commit.\n*.BACKUP.*\n*.BASE.*\n*.LOCAL.*\n*.REMOTE.*\n*.orig\n\n# Prevent unit test coverage reports from being added\n.coverage"
  },
  {
    "path": ".editorconfig",
    "content": "# editorconfig.org\nroot = true\n\n[*]\nindent_style = space\nindent_size = 4\nend_of_line = lf\ncharset = utf-8\nmax_length = 120\ntrim_trailing_whitespace = true\ninsert_final_newline = true\n\n[*.{json, yml, html, hbs}]\nindent_size = 2\n"
  },
  {
    "path": ".eslintrc",
    "content": "{\n    \"plugins\": [\"jsdoc\", \"lodash\", \"security\"],\n    \"env\": {\n        \"browser\": false,\n        \"node\": true,\n        \"es6\": true\n    },\n    \"globals\": {},\n    \"settings\": {\n        \"lodash\": {\n            \"pragma\": \"_\"\n        }\n    },\n    \"parserOptions\": {\n        \"ecmaVersion\": 2018\n    },\n    \"rules\": {\n        // Possible Errors\n        \"for-direction\": \"error\",\n        \"default-param-last\": \"error\",\n        \"function-call-argument-newline\": \"off\",\n        \"getter-return\": \"error\",\n        \"no-async-promise-executor\": \"error\",\n        \"no-await-in-loop\": \"error\",\n        \"no-compare-neg-zero\": \"error\",\n        \"no-cond-assign\": \"error\",\n        \"no-console\": [\n            \"error\",\n            {\n                \"allow\": [\"info\", \"warn\", \"error\"]\n            }\n        ],\n        \"no-constant-condition\": \"error\",\n        \"no-control-regex\": \"error\",\n        \"no-constructor-return\": \"error\",\n        \"no-debugger\": \"error\",\n        \"no-dupe-args\": \"error\",\n        \"no-dupe-else-if\": \"error\",\n        \"no-dupe-keys\": \"error\",\n        \"no-duplicate-case\": \"error\",\n        \"no-empty\": \"error\",\n        \"no-empty-character-class\": \"error\",\n        \"no-ex-assign\": \"error\",\n        \"no-extra-boolean-cast\": \"error\",\n        \"no-extra-parens\": \"off\",\n        \"no-extra-semi\": \"error\",\n        \"no-func-assign\": \"error\",\n        \"no-import-assign\": \"error\",\n        \"no-inner-declarations\": \"error\",\n        \"no-invalid-regexp\": \"error\",\n        \"no-irregular-whitespace\": \"error\",\n        \"no-loss-of-precision\": \"error\",\n        \"no-misleading-character-class\": \"error\",\n        \"no-nonoctal-decimal-escape\": \"error\",\n        \"no-obj-calls\": \"error\",\n        \"no-prototype-builtins\": \"error\",\n        \"no-regex-spaces\": \"error\",\n        \"no-sparse-arrays\": \"error\",\n        \"no-template-curly-in-string\": \"error\",\n        \"no-unexpected-multiline\": \"error\",\n        \"no-unreachable\": \"error\",\n        \"no-unsafe-finally\": \"error\",\n        \"no-unsafe-negation\": \"error\",\n        \"no-unsafe-optional-chaining\": \"error\",\n        \"prefer-regex-literals\": \"error\",\n        \"require-atomic-updates\": \"error\",\n        \"require-unicode-regexp\": \"off\",\n        \"use-isnan\": \"error\",\n        \"valid-typeof\": \"error\",\n\n        // Best Practices\n        \"accessor-pairs\": \"error\",\n        \"array-callback-return\": \"off\",\n        \"block-scoped-var\": \"error\",\n        \"class-methods-use-this\": \"error\",\n        \"complexity\": \"off\",\n        \"consistent-return\": \"off\",\n        \"curly\": \"error\",\n        \"default-case\": \"error\",\n        \"default-case-last\": \"error\",\n        \"dot-location\": [\"error\", \"property\"],\n        \"dot-notation\": \"error\",\n        \"eqeqeq\": \"error\",\n        \"grouped-accessor-pairs\": \"warn\",\n        \"guard-for-in\": \"warn\",\n        \"id-denylist\": \"warn\",\n        \"max-classes-per-file\": [\"error\", 1],\n        \"max-lines-per-function\": \"off\",\n        \"no-alert\": \"error\",\n        \"no-caller\": \"error\",\n        \"no-case-declarations\": \"error\",\n        \"no-div-regex\": \"error\",\n        \"no-else-return\": \"error\",\n        \"no-empty-function\": \"error\",\n        \"no-empty-pattern\": \"error\",\n        \"no-eq-null\": \"error\",\n        \"no-eval\": \"error\",\n        \"no-extend-native\": \"error\",\n        \"no-extra-bind\": \"error\",\n        \"no-extra-label\": \"error\",\n        \"no-fallthrough\": \"error\",\n        \"no-floating-decimal\": \"error\",\n        \"no-global-assign\": \"error\",\n        \"no-implicit-coercion\": \"error\",\n        \"no-implicit-globals\": \"error\",\n        \"no-implied-eval\": \"error\",\n        \"no-invalid-this\": \"error\",\n        \"no-iterator\": \"error\",\n        \"no-labels\": \"error\",\n        \"no-lone-blocks\": \"error\",\n        \"no-loop-func\": \"error\",\n        \"no-magic-numbers\": \"off\",\n        \"no-multi-spaces\": \"error\",\n        \"no-multi-str\": \"error\",\n        \"no-new\": \"error\",\n        \"no-new-func\": \"error\",\n        \"no-new-wrappers\": \"error\",\n        \"no-octal\": \"error\",\n        \"no-octal-escape\": \"error\",\n        \"no-param-reassign\": \"off\",\n        \"no-promise-executor-return\": \"error\",\n        \"no-proto\": \"error\",\n        \"no-redeclare\": \"error\",\n        \"no-restricted-exports\": \"error\",\n        \"no-restricted-properties\": \"error\",\n        \"no-return-assign\": \"error\",\n        \"no-return-await\": \"error\",\n        \"no-script-url\": \"error\",\n        \"no-self-assign\": \"error\",\n        \"no-self-compare\": \"error\",\n        \"no-sequences\": \"error\",\n        \"no-setter-return\": \"error\",\n        \"no-throw-literal\": \"error\",\n        \"no-unmodified-loop-condition\": \"error\",\n        \"no-unreachable-loop\": \"error\",\n        \"no-unused-expressions\": \"off\",\n        \"no-unused-labels\": \"error\",\n        \"no-useless-call\": \"error\",\n        \"no-useless-concat\": \"error\",\n        \"no-useless-backreference\": \"error\",\n        \"no-useless-escape\": \"error\",\n        \"no-useless-return\": \"error\",\n        \"no-void\": \"error\",\n        \"no-warning-comments\": \"off\",\n        \"no-with\": \"error\",\n        \"prefer-named-capture-group\": \"off\",\n        \"prefer-exponentiation-operator\": \"warn\",\n        \"prefer-object-spread\": \"error\",\n        \"prefer-promise-reject-errors\": \"error\",\n        \"radix\": \"error\",\n        \"require-await\": \"error\",\n        \"vars-on-top\": \"off\",\n        \"wrap-iife\": \"error\",\n        \"yoda\": \"error\",\n\n        // Strict Mode\n        \"strict\": \"off\",\n\n        // Variables\n        \"init-declarations\": \"off\",\n        \"no-delete-var\": \"error\",\n        \"no-label-var\": \"error\",\n        \"no-restricted-globals\": \"error\",\n        \"no-shadow\": \"off\",\n        \"no-shadow-restricted-names\": \"error\",\n        \"no-undef\": \"error\",\n        \"no-undef-init\": \"error\",\n        \"no-undefined\": \"off\",\n        \"no-unused-vars\": \"error\",\n        \"no-use-before-define\": \"error\",\n\n        // Node.js and CommonJS\n        \"callback-return\": \"error\",\n        \"global-require\": \"off\",\n        \"handle-callback-err\": \"error\",\n        \"no-buffer-constructor\": \"error\",\n        \"no-mixed-requires\": \"off\",\n        \"no-new-require\": \"off\",\n        \"no-path-concat\": \"error\",\n        \"no-process-env\": \"error\",\n        \"no-process-exit\": \"off\",\n        \"no-restricted-modules\": \"error\",\n        \"no-sync\": \"off\",\n\n        // Stylistic Issues\n        \"array-bracket-newline\": \"off\",\n        \"array-bracket-spacing\": \"error\",\n        \"array-element-newline\": \"off\",\n        \"block-spacing\": \"error\",\n        \"brace-style\": [\n            \"error\",\n            \"stroustrup\",\n            {\n                \"allowSingleLine\": true\n            }\n        ],\n        \"camelcase\": \"off\",\n        \"capitalized-comments\": \"off\",\n        \"comma-dangle\": [\"error\", \"never\"],\n        \"comma-spacing\": [\n            \"error\",\n            {\n                \"before\": false,\n                \"after\": true\n            }\n        ],\n        \"comma-style\": [\"error\", \"last\"],\n        \"computed-property-spacing\": \"error\",\n        \"consistent-this\": \"off\",\n        \"eol-last\": \"error\",\n        \"func-call-spacing\": \"error\",\n        \"func-name-matching\": \"off\",\n        \"func-names\": \"off\",\n        \"func-style\": \"off\",\n        \"function-paren-newline\": [\"error\", \"never\"],\n        \"id-blacklist\": \"error\",\n        \"id-length\": \"off\",\n        \"id-match\": \"error\",\n        \"implicit-arrow-linebreak\": [\"error\", \"beside\"],\n        \"indent\": [\n            \"error\",\n            4,\n            {\n                \"VariableDeclarator\": {\n                    \"var\": 1,\n                    \"let\": 1,\n                    \"const\": 1\n                },\n                \"SwitchCase\": 1\n            }\n        ],\n        \"jsx-quotes\": [\"error\", \"prefer-single\"],\n        \"key-spacing\": \"error\",\n        \"keyword-spacing\": \"error\",\n        \"line-comment-position\": \"off\",\n        \"linebreak-style\": [\"error\", \"unix\"],\n        \"lines-around-comment\": [\n            \"error\",\n            {\n                \"beforeBlockComment\": true,\n                \"afterBlockComment\": false,\n                \"beforeLineComment\": false,\n                \"afterLineComment\": false,\n                \"allowBlockStart\": true,\n                \"allowBlockEnd\": false,\n                \"allowObjectStart\": true,\n                \"allowObjectEnd\": false,\n                \"allowArrayStart\": true,\n                \"allowArrayEnd\": false\n            }\n        ],\n        \"lines-between-class-members\": [\n            \"error\",\n            \"always\",\n            {\n                \"exceptAfterSingleLine\": true\n            }\n        ],\n        \"max-depth\": \"error\",\n        \"max-len\": [\n            \"error\",\n            {\n                \"code\": 120\n            }\n        ],\n        \"max-lines\": \"off\",\n        \"max-nested-callbacks\": \"error\",\n        \"max-params\": \"off\",\n        \"max-statements\": \"off\",\n        \"max-statements-per-line\": [\n            \"error\",\n            {\n                \"max\": 2\n            }\n        ],\n        \"multiline-comment-style\": \"off\",\n        \"multiline-ternary\": \"off\",\n        \"new-cap\": \"off\",\n        \"new-parens\": \"error\",\n        \"newline-per-chained-call\": [\n            \"error\",\n            {\n                \"ignoreChainWithDepth\": 4\n            }\n        ],\n        \"no-array-constructor\": \"error\",\n        \"no-bitwise\": \"off\",\n        \"no-continue\": \"off\",\n        \"no-inline-comments\": \"off\",\n        \"no-lonely-if\": \"error\",\n        \"no-mixed-operators\": \"off\",\n        \"no-mixed-spaces-and-tabs\": \"error\",\n        \"no-multi-assign\": \"off\",\n        \"no-multiple-empty-lines\": \"error\",\n        \"no-negated-condition\": \"off\",\n        \"no-nested-ternary\": \"off\",\n        \"no-new-object\": \"error\",\n        \"no-plusplus\": \"off\",\n        \"no-restricted-syntax\": \"error\",\n        \"no-tabs\": \"error\",\n        \"no-ternary\": \"off\",\n        \"no-trailing-spaces\": \"error\",\n        \"no-underscore-dangle\": \"off\",\n        \"no-unneeded-ternary\": \"error\",\n        \"no-whitespace-before-property\": \"error\",\n        \"nonblock-statement-body-position\": \"error\",\n        \"object-curly-newline\": \"off\",\n        \"object-curly-spacing\": [\"error\", \"always\"],\n        \"object-property-newline\": \"off\",\n        \"one-var\": [\"error\", \"always\"],\n        \"one-var-declaration-per-line\": \"error\",\n        \"operator-assignment\": \"error\",\n        \"operator-linebreak\": [\"error\", \"after\"],\n        \"padded-blocks\": [\"error\", \"never\"],\n        \"padding-line-between-statements\": [\n            \"error\",\n            {\n                \"blankLine\": \"always\",\n                \"prev\": \"*\",\n                \"next\": \"return\"\n            },\n            {\n                \"blankLine\": \"always\",\n                \"prev\": [\"const\", \"let\", \"var\"],\n                \"next\": \"*\"\n            },\n            {\n                \"blankLine\": \"any\",\n                \"prev\": [\"const\", \"let\", \"var\"],\n                \"next\": [\"const\", \"let\", \"var\"]\n            }\n        ],\n        \"quote-props\": [\"error\", \"as-needed\"],\n        \"quotes\": [\"error\", \"single\"],\n        \"semi\": \"error\",\n        \"semi-spacing\": \"error\",\n        \"semi-style\": [\"error\", \"last\"],\n        \"sort-keys\": \"off\",\n        \"sort-vars\": \"off\",\n        \"space-before-blocks\": \"error\",\n        \"space-before-function-paren\": \"error\",\n        \"space-in-parens\": \"error\",\n        \"space-infix-ops\": \"error\",\n        \"space-unary-ops\": \"error\",\n        \"spaced-comment\": [\n            \"error\",\n            \"always\",\n            {\n                \"block\": {\n                    \"exceptions\": [\"!\"]\n                }\n            }\n        ],\n        \"switch-colon-spacing\": \"error\",\n        \"template-tag-spacing\": \"error\",\n        \"unicode-bom\": \"error\",\n        \"wrap-regex\": \"error\",\n\n        // ECMAScript 6\n        \"arrow-body-style\": [\"error\", \"always\"],\n        \"arrow-parens\": [\"error\", \"always\"],\n        \"arrow-spacing\": \"error\",\n        \"constructor-super\": \"error\",\n        \"generator-star-spacing\": \"error\",\n        \"no-class-assign\": \"error\",\n        \"no-confusing-arrow\": \"error\",\n        \"no-const-assign\": \"error\",\n        \"no-dupe-class-members\": \"error\",\n        \"no-duplicate-imports\": \"error\",\n        \"no-new-symbol\": \"error\",\n        \"no-restricted-imports\": \"error\",\n        \"no-this-before-super\": \"error\",\n        \"no-useless-catch\": \"error\",\n        \"no-useless-computed-key\": \"error\",\n        \"no-useless-constructor\": \"error\",\n        \"no-useless-rename\": \"error\",\n        \"no-var\": \"off\",\n        \"object-shorthand\": [\"error\", \"consistent-as-needed\"],\n        \"prefer-arrow-callback\": \"off\",\n        \"prefer-const\": \"off\",\n        \"prefer-destructuring\": \"off\",\n        \"prefer-numeric-literals\": \"off\",\n        \"prefer-rest-params\": \"off\",\n        \"prefer-spread\": \"error\",\n        \"prefer-template\": \"off\",\n        \"require-yield\": \"error\",\n        \"rest-spread-spacing\": \"error\",\n        \"sort-imports\": \"off\",\n        \"symbol-description\": \"off\",\n        \"template-curly-spacing\": \"error\",\n        \"yield-star-spacing\": \"error\",\n\n        // Lodash\n        \"lodash/callback-binding\": \"error\",\n        \"lodash/collection-method-value\": \"off\",\n        \"lodash/collection-return\": \"error\",\n        \"lodash/no-double-unwrap\": \"error\",\n        \"lodash/no-extra-args\": \"error\",\n        \"lodash/no-unbound-this\": \"error\",\n        \"lodash/unwrap\": \"error\",\n\n        \"lodash/chain-style\": [\"error\", \"as-needed\"],\n        \"lodash/chaining\": [\"error\", \"always\", 3],\n        \"lodash/consistent-compose\": [\"error\", \"flow\"],\n        \"lodash/identity-shorthand\": [\"error\", \"always\"],\n        \"lodash/import-scope\": \"off\",\n        \"lodash/matches-prop-shorthand\": [\"error\", \"always\"],\n        \"lodash/matches-shorthand\": [\"error\", \"always\", 3],\n        \"lodash/no-commit\": \"error\",\n        \"lodash/path-style\": [\"error\", \"as-needed\"],\n        \"lodash/prefer-compact\": \"error\",\n        \"lodash/prefer-filter\": [\"off\", 3],\n        \"lodash/prefer-flat-map\": \"error\",\n        \"lodash/prefer-invoke-map\": \"error\",\n        \"lodash/prefer-map\": \"error\",\n        \"lodash/prefer-reject\": [\"error\", 3],\n        \"lodash/prefer-thru\": \"error\",\n        \"lodash/prefer-wrapper-method\": \"error\",\n        \"lodash/preferred-alias\": \"error\",\n        \"lodash/prop-shorthand\": [\"error\", \"always\"],\n\n        \"lodash/prefer-constant\": \"off\",\n        \"lodash/prefer-get\": [\"warn\", 4],\n        \"lodash/prefer-includes\": [\n            \"error\",\n            {\n                \"includeNative\": true\n            }\n        ],\n        \"lodash/prefer-is-nil\": \"error\",\n        \"lodash/prefer-lodash-chain\": \"error\",\n        \"lodash/prefer-lodash-method\": \"off\",\n        \"lodash/prefer-lodash-typecheck\": \"off\",\n        \"lodash/prefer-matches\": [\"off\", 3],\n        \"lodash/prefer-noop\": \"off\",\n        \"lodash/prefer-over-quantifier\": \"warn\",\n        \"lodash/prefer-some\": \"off\",\n        \"lodash/prefer-startswith\": \"off\",\n        \"lodash/prefer-times\": \"off\",\n\n        // JsDoc\n        \"jsdoc/check-param-names\": \"error\",\n        \"jsdoc/check-tag-names\": \"off\",\n        \"jsdoc/check-types\": \"off\",\n        \"jsdoc/require-description-complete-sentence\": \"off\",\n        \"jsdoc/require-example\": \"off\",\n        \"jsdoc/require-hyphen-before-param-description\": \"off\",\n        \"jsdoc/require-param\": \"error\",\n        \"jsdoc/require-param-description\": \"error\",\n        \"jsdoc/require-param-type\": \"error\",\n        \"jsdoc/require-returns-description\": \"off\",\n        \"jsdoc/require-returns-type\": \"error\",\n\n        // Security\n        \"security/detect-unsafe-regex\": \"error\",\n        \"security/detect-buffer-noassert\": \"error\",\n        \"security/detect-child-process\": \"error\",\n        \"security/detect-disable-mustache-escape\": \"error\",\n        \"security/detect-eval-with-expression\": \"error\",\n        \"security/detect-no-csrf-before-method-override\": \"error\",\n        \"security/detect-non-literal-fs-filename\": \"off\",\n        \"security/detect-non-literal-regexp\": \"error\",\n        \"security/detect-non-literal-require\": \"off\",\n        \"security/detect-object-injection\": \"off\",\n        \"security/detect-possible-timing-attacks\": \"error\",\n        \"security/detect-pseudoRandomBytes\": \"error\"\n    }\n}\n"
  },
  {
    "path": ".gitattributes",
    "content": "# Set the default behavior\n* text=auto\n\n# JavaScript files will always have LF line endings\n*.js text eol=lf\n\n# JSON files always have LF line endings\n*.json text eol=lf\n"
  },
  {
    "path": ".github/CONTRIBUTING.md",
    "content": "# Contributing to Postman Newman\n\n  - [Getting Started Quick](#getting-started-quick)\n  - [NPM Command Reference](#npm-command-reference)\n      - [`npm install`](#npm-install)\n      - [`npm test`](#npm-test)\n      - [`npm run test-system`](#npm-run-test-system)\n      - [`npm run test-lint`](#npm-run-test-lint)\n      - [`npm run test-unit`](#npm-run-test-unit)\n      - [`npm run test-integration`](#npm-run-test-integration)\n  - [Repository](#repository)\n      - [Structure](#structure)\n      - [Branching and Tagging Policy](#branching-and-tagging-policy)\n  - [Preferred IDE](#preferred-ide)\n  - [Commit Guidelines](#commit-guidelines)\n      - [Check for errors before committing](#check-for-errors-before-committing)\n      - [Atomic commits](#atomic-commits)\n      - [Clean commit message](#clean-commit-message)\n      - [Writing tests](#writing-tests)\n  - [Guidelines for sending a Pull Request](#guidelines-for-sending-a-pull-request)\n  - [Documentation guidelines](#documentation-guidelines)\n  - [The CI Platform](#the-ci-platform)\n      - [Ensuring your commits will not fail build](#ensuring-your-commits-will-not-fail-build)\n      - [Accessing build log on CI server](#accessing-build-log-on-ci-server)\n  - [Security](#security)\n\n## Getting Started Quick\n\nIn order to contribute to this project, you should:\n\n1. Clone this repository / your fork of this repository using `git`\n2. If not on `develop`, switch to the `develop` branch with `git checkout develop`\n3. Run `npm install` in the project directory\n4. Make sure everything is working by running `npm test`.\n5. Create a new feature branch from `develop` with `feature/your-feature-name`.\n6. Make the necessary changes in line with the objective(s) of the pull request\n7. You can debug newman locally by running `node ./bin/newman <command-name>`.\n8. Ensure that you have added unit and integration tests for any new features added / bugs fixed\n9. Run `npm test`. If any tests fail, resolve the issue with the code, and re-try\n10. Once the tests pass, commit and push. **Do not** alter the `version` in `package.json`\n11. Create a pull request to `develop`\n\n## NPM Command Reference\n\n### `npm install`\n\nInstalls all `dependencies` listed in `package.json`\n\n### `npm test`\n\nThe script associated with `npm test` will run all tests that ensures that your commit does not break anything in the\nrepository. As such run `npm test` before you push. In addition to performing a few logging and pre-test configuration\nactions, this test bootstrap script will also trigger the various sub test tasks, which include code lint checks, unit\nand integration tests. At present, the following sub tests can be run on a standalone basis:\n\n* `npm run test-system`: Runs system tests\n* `npm run test-lint`: Performs code style checks, flagging inconsistencies and other miscellaneous anomalies\n* `npm run test-unit`: Runs unit tests to verify the correctness of various methods used within the project\n* `npm run test-integration`: Checks Newman sanity with a sample requests categorized by collection\n* `npm run test-cli`: Runs CLI integration tests\n* `npm run test-library`: Runs library integration tests\n\n## Repository\n\n### Structure\n\nDirectory               | Summary\n------------------------|-----------------------------------------------------------------------------------------------\n`bin`                   | Contains scripts that wrap around all the other methods provided within the project\n`examples`              | A sample script to demonstrate collection file parsing within Newman\n`lib`                   | Houses the core logic and configuration sets for Newman, including reporters, and the runtime\n`npm`                   | All CI scripts (triggered by NPM run-script)\n`test`                  | Contains all the test scripts for Newman\n`test/unit`             | Method wise tests for Newman\n`test/system`           | Erstwhile `infra` tests, checks for proper code structuring and division across the project\n`test/integration`      | Contains the integration test runner, validates Newman as a library\n\n### Branching and Tagging Policy\n\nThis repository uses standard `git-flow` branch management policy/strategy. If you want to learn more on `git-flow`,\nrefer  to [tutorial from Atlassian](https://www.atlassian.com/git/workflows#!workflow-gitflow) and more details at\n[http://nvie.com/posts/a-successful-git-branching-model/](http://nvie.com/posts/a-successful-git-branching-model).\n\n> Deletion of `main` and `develop`.\n> Rebasing on `main` is blocked.\n\n## Preferred IDE\nIt is advised to use an IDE that provides [EditorConfig](http://editorconfig.org) support via `.editorconfig` files,\neither natively, or through plugins. In addition, the `.gitignore` file has been populated with entries to support\nignoring metadata / manifest files for various IDEs.\n\n## Commit Guidelines\n\nThe following best practices, coupled with a pinch of common-sense will keep the repository clean and usable in future.\nThe idea is that everything that goes into the repository is not for an individual, but someone else who will be\ndirectly or indirectly affected by it.\n\n### Check for errors before committing\n\nChecking for errors should be done for each commit whether it is being pushed to remote or not.\n\nFirst, you don't want to submit any whitespace errors. Git provides an easy way to check for this before you commit,\nrun `git diff --check`, which identifies possible whitespace errors and lists them for you. If you run that command\nbefore committing, you can tell if you're about to commit whitespace issues that may annoy other developers.\n\nSecondly, you should ensure that your commit does not break builds. Run `npm test` on the repository to execute all\nsanity and smoke tests. If any test fail, do not change the test to pass your commit. The tests were there with a\npurpose. Discuss within your team to ensure that the changes that you do to test specs are valid. If you are adding a\nnew feature, accompanying them with new tests are a good practice.\n\n### Atomic commits\n\nTry to make each commit a logically separate change set. If you can, try to make your changes digestible don't code\nfor a whole weekend on five different issues and then submit them all as one massive commit on Monday. Even if you don't\ncommit during the weekend, use the staging area on Monday to split your work into at least one commit per issue, with a\nuseful message per commit. If some of the changes modify the same file, try to use `git add --patch` to partially stage\nfiles. The project snapshot at the tip of the branch is identical whether you do one commit or five, as long as all the\nchanges are added at some point, so try to make things easier on your fellow developers when they have to review your\nchanges. This approach also makes it easier to pull out or revert one of the change sets if you need to later. There are\na number of useful Git tricks for rewriting history and interactively staging files use these tools to help craft a\nclean and understandable history.\n\n### Clean commit message\n\n*More detailed explanation include your motivation for the change and contrast its implementation with previous\nbehavior this is a good guideline to follow.*\n\nGetting in the habit of creating quality commit messages makes using and collaborating with Git a lot easier. As a\ngeneral rule, your messages should start with a single line that is no more than 50 characters and that describes\nthe change set concisely, followed by a blank line, followed by a more detailed explanation.\n\nIt's also a good idea to use the imperative present tense in these messages. In other words, use commands. Instead of\n\"I added tests for\" or \"Adding tests for,\" use \"Add tests for.\"\n\nYou should see if your commit message answers the following questions:\nAnswer the following questions:\n\n1. **Why is this change necessary?**\n2. **How does it address the issue?**\n3. **What side effects does this change have?**\n\nThe first question tells reviewers of your pull request what to expect in the commit, allowing them to more easily\nidentify and point out unrelated changes.\n\nThe second question describes, at a high level, what was done to affect change. If your change is obvious, you may be\nable to omit addressing this question.\n\nThe third is the most important question to answer, as it can point out problems where you are making too many changes\nin one commit or branch. One or two bullet points for related changes may be okay, but five or six are likely indicators\nof a commit that is doing too many things.\n\nA good commit message template\n\n```\nShort (50 chars or less) summary of changes with relevant project management issue ID.\n\nMore detailed explanatory text, if necessary.  Wrap it to about 72 characters or so.  In some contexts, the first line\nis treated as the subject of an email and the rest of the text as the body.  The blank line separating the summary from\nthe body is critical (unless you omit the body entirely); tools like rebase can get confused if you run the two\ntogether.\n\nFurther paragraphs come after blank lines.\n\n - Bullet points are okay, too\n\n - Typically a hyphen or asterisk is used for the bullet, preceded by a single space, with blank lines in between, but\n conventions vary here\n```\n\nRun `git log --no-merges` to see what a nicely formatted project-commit history looks like.\n\n### Writing tests\n\nOver the course of contributing to Newman, several new features will be added and discovered bugs / glitches will be\nfixed. It is important to ensure that all of these changes are cross-checked via their respective tests. Two\nimportant points in this context are `unit` and `integration` tests.\n\n#### Unit tests\n\nUnit tests are focused toward validating one method, and one method only. These tests are to be added to `test/unit`.\nEach unit test file contains a `describe` block, which may or may not contain describe blocks within itself. Any given\ndescribe block is meant to group together tests for one particular purpose or section of code.\n\nAll unit test files must conform to the following standard:\n\n* The file name must end with `.test.js`\n* The file must be named using lower case characters exclusively\n* Should the first part of the file name need multiple words, they must be separated with dashes `(-)`.\n\nTaking up the [existing test files](https://github.com/postmanlabs/newman/tree/feature/v3/test/unit) as an example, we\ncan see that all tests for cli options are grouped together in one file, while tests for the collection runner reside\nin their own file.\n\nWithin each `describe` block, individual tests are denoted by distinct `it` blocks. Each `it` block will test exactly\none method, with a given set of parameters. Note that multiple `it` blocks can effectively map to one method, as a\nmethod may need to be assessed for a variety of runtime conditions.\n\nWithin each `it` block, correctness checks for expected method behaviour are done using `expect` calls. For more on\n`expect`, check out [Chai Expect](http://www.chaijs.com/api/bdd)\n\nLastly, the information provided within `describe` and `it` blocks should form a cogent sentence when combined.\n\nFor instance:\n\n```javascript\n    describe('Logic tests', function () {\n        it('should throw an error if parameters are missing', function () {});\n        it('should pass when valid values are provided', function () {});\n    });\n```\n\nThe result sentence derived by combining the descriptions in the `describe` and `it` blocks are:\n\n**Logic tests** should throw an error if parameters are missing\n**Logic tests** should pass when valid values are provided\n\n#### Integration tests\n\nIntegration tests test Newman from the outside, and as a whole. As you might have already guessed, these tests don't\ntest one method at a time. With regard to Newman, each integration test consists of a postman collection, and optional\nset of environment, data, and globals files.\n\nAll these files are arranged without any directory segregation, as can be seen in [test/integration](https://github.com/postmanlabs/newman/tree/feature/v3/test/integration).\nEach of these file names should follow the convention outlined below:\n\n* File names with multiple words must have `-` as a separator, not `_`.\n* Under no circumstances do file names involve `camelCase`.\n* The type of the file must be designated with `postman_{{type}}` in the file name, where `type` is one of `collection`,\n  `data`, `environment`, or `globals`. See examples below for clarity.\n* All postman_collection files must be in the *V2* format.\n* `.json` is a common file extension across all files, data files can have `.csv` as an extension as well.\n\nFor instance:\n>\n\nfile-name.postman_collection.json\n\nfile-name.postman_environment.json\n\nfile-name.postman_globals.json\n\nfile-name.postman_data.json\n\nfile-name.postman_data.csv\n\n## Guidelines for sending a Pull Request\n\nCommit to `main` branch and `develop` branch is locked. As such, `git-flow` for feature completion and release will not\nwork. Thus, the last steps of feature completion in `git-flow` will happen as a Pull Request from website. Avoid\nchanging the `version` field in `package.json` for feature pull requests, as `version` bumps are handled separately.\n\n1. Pull Request comment and commit comments should explicitly discuss what changes were made. The Pull Request reviewer\n   should not need to communicate out of scope of issue tracker and the pull request description in order to understand\n   what changes has been done.\n\n2. Pull Requests with build failures will not be merged. Ensure that `npm test` passes on the `head` of your feature\n   branch. The same goes for pull requests with untested new features / resolved bugs.\n\n3. Ensure that your feature branch has been tested and if it is associated with issues from corresponding issue-tracker,\n   the issue must be in a \"resolved\" state, implying that the issue has been fully tested, and accepted for inclusion.\n\n4. Pull Requests with merge conflict are very difficult to review, and are at a higher likelihood of being rejected.\n   Ensure that the `head` of your feature branch is either already merged with `develop` or has no conflict when it is\n   merged with `develop`.\n\n5. The turn around time to close a Pull Request is directly proportional to the delta of changes done - more the change\n   in files, more time it would take. As such, if you anticipate a feature branch to have a large delta on feature\n   completion, break it into sub-issues of the issue-tracker, test them, close them, and then send PR for that branch.\n\n6. In addition, the turn around time for Pull Request would get affected if commit messages are unclear.\n\n7. If you have deadlines to ensure feature completion, send Pull Request ahead of time. Better still, ensure that your\n   feature development time window accounts for PR acceptance time as well.\n\n8. If you have mentioned issue tracker references in Pull Request description, the severity and priority of those issues\n   will be taken into account. Otherwise, no Pull Request will take priority over others already in queue - it is\n   first-pull first-merge!\n\n## Documentation guidelines\n\nDetails on usage, sample use cases, licensing and current project status, and community support are to be specified\nwithin `README.md`. All information related to contribution is to be added to `CONTRIBUTING.md`. More in depth\ninformation on aspects like project architecture, design, and so on is to be added to the project [wiki](https://github.com/postmanlabs/newman/wiki)\n\n## The CI Platform\n\nThe CI system is built as a bunch of bash scripts to execute a set of tasks. These scripts are meant to execute tasks\nthat can run on every local machine. In general, knowledge about these scripts are not necessary for development\n\n**The scripts are to be only accessed using `npm run <script name>`.** This ensures that the execution point of the\nscripts (`pwd`) is always the repository root.\n\n### Ensuring your commits will not fail build\n\n> `npm test`\n\nThe script associated with `npm test` will run all tests that ensures that your commit does not break anything in the\nrepository. As such run `npm test` before you push\n\n### Security\n\nSecurity concerns are always treated with high priority. Should you come across a security vulnerability, please report\nit via email to <security@postman.com>. While reporting a potential security vulnerability, include all relevant\ndetails, including but not limited to:\n\n1. The project version(s) involved\n2. The operating system(s) to which the bug is relevant\n3. Bug description\n\nPlease **refrain** from publicly posting about the security vulnerability in **any** form, until it's corresponding fix\nhas been released\n\n---\n*Sections of this document use excerpts from various books and the Internet, among whom, [this](http://git-scm.com/book)\nis a dominating influence.*\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE.md",
    "content": "<!--\nWelcome to the Newman Issue tracker. Any feature requests / bug reports can be posted here.\nAny security-related bugs should be reported directly to security@postman.com\n\nThis issue reporting template should guide you to effectively report issues for fastest resolution. Please provide all relevant details in the list below.\n\nVersion and environment information:\n-->\n 1. Newman Version (can be found via `newman -v`):\n 2. OS details (type, version, and architecture):\n 3. Are you using Newman as a library, or via the CLI?\n 3. Did you encounter this recently, or has this bug always been there:\n 4. Expected behaviour:\n 5. Command / script used to run Newman:\n 6. Sample collection, and auxiliary files (minus the sensitive details):\n 7. Screenshots (if applicable):\n\n<!--\nSteps to reproduce the problem:\n\n1. {{add step 1}}\n2. {{add step 2}}\n3. {{add step 3}}\n-->\n\n\n<!--\nBefore proceeding, please consider the following:\n\n1. If this is a Postman Client App issue, go to https://github.com/postmanlabs/postman-app-support/issues/new\n\n2. Report security issues directly to security@postman.com. Please refrain from publicly disclosing any details about security issues in any form, until a fix has been rolled out.\n\n3. For Postman Cloud / personal information related issues, send an email to: [help@postman.com](mailto:help@postman.com)\n\n4. Verify that you have checked the documentation at https://learning.postman.com/docs/running-collections/using-newman-cli, and searched through previously closed issues.\n\n5. Please ensure that all supporting files (collections or screenshots) do not contain any sensitive information.\n-->\n"
  },
  {
    "path": ".github/dependabot.yml",
    "content": "version: 2\nupdates:\n  - package-ecosystem: \"npm\"\n    directory: \"/\"\n    schedule:\n      interval: \"weekly\"\n      day: \"saturday\"\n      time: \"03:14\"\n      timezone: Asia/Calcutta\n    rebase-strategy: \"disabled\"\n    open-pull-requests-limit: 10\n"
  },
  {
    "path": ".github/workflows/ci.yml",
    "content": "name: CI\n\non:\n    push:\n        paths-ignore:\n            - \"*.md\"\n    pull_request:\n        branches: [$default-branch]\n    schedule:\n        - cron: \"0 12 * * 0\"\n\nconcurrency:\n    group: ${{ github.workflow }}-${{ github.ref }}\n    cancel-in-progress: true\n\njobs:\n    tests:\n        name: Tests\n        runs-on: ${{ matrix.os }}\n        strategy:\n            fail-fast: false\n            matrix:\n                node-version: [16, 18]\n                os: [ubuntu-latest, windows-latest]\n\n        steps:\n            - name: Checkout repository\n              uses: actions/checkout@v3\n\n            - name: Use Node.js ${{ matrix.node-version }}\n              uses: actions/setup-node@v3\n              with:\n                  node-version: ${{ matrix.node-version }}\n                  cache: \"npm\"\n\n            - name: Install\n              run: npm ci\n\n            - name: Run tests\n              run: npm run test\n\n    coverage:\n        name: Coverage\n        runs-on: ubuntu-latest\n\n        steps:\n            - name: Checkout repository\n              uses: actions/checkout@v3\n\n            - name: Use Node.js 20\n              uses: actions/setup-node@v3\n              with:\n                  node-version: 20\n                  cache: \"npm\"\n\n            - name: Install\n              run: npm ci\n\n            - name: Run unit tests\n              run: |\n                  npm run test-unit\n                  bash <(curl -s https://codecov.io/bash) -c -Z -f .coverage/coverage-final.json -F unit -t ${{ secrets.CODECOV_TOKEN }}\n\n            - name: Run integration tests\n              run: |\n                  npm run test-integration\n                  bash <(curl -s https://codecov.io/bash) -c -Z -f .coverage/coverage-final.json -F integration -t ${{ secrets.CODECOV_TOKEN }}\n\n            - name: Run CLI tests\n              run: |\n                  npm run test-cli\n                  bash <(curl -s https://codecov.io/bash) -c -Z -f .coverage/coverage-final.json -F cli -t ${{ secrets.CODECOV_TOKEN }}\n\n            - name: Run library tests\n              run: |\n                  npm run test-library\n                  bash <(curl -s https://codecov.io/bash) -c -Z -f .coverage/coverage-final.json -F library -t ${{ secrets.CODECOV_TOKEN }}\n"
  },
  {
    "path": ".github/workflows/codeql-analysis.yml",
    "content": "# For most projects, this workflow file will not need changing; you simply need\n# to commit it to your repository.\n#\n# You may wish to alter this file to override the set of languages analyzed,\n# or to provide custom queries or build logic.\n#\n# ******** NOTE ********\n# We have attempted to detect the languages in your repository. Please check\n# the `language` matrix defined below to confirm you have the correct set of\n# supported CodeQL languages.\n#\nname: \"CodeQL\"\n\non:\n  push:\n    branches: [ develop, main, release/*.x ]\n  pull_request:\n    # The branches below must be a subset of the branches above\n    branches: [ \"develop\" ]\n  schedule:\n    - cron: '31 14 * * 2'\n\njobs:\n  analyze:\n    name: Analyze\n    runs-on: ubuntu-latest\n    permissions:\n      actions: read\n      contents: read\n      security-events: write\n\n    strategy:\n      fail-fast: false\n      matrix:\n        language: [ 'javascript' ]\n        # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]\n        # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support\n\n    steps:\n    - name: Checkout repository\n      uses: actions/checkout@v3\n\n    # Initializes the CodeQL tools for scanning.\n    - name: Initialize CodeQL\n      uses: github/codeql-action/init@v2\n      with:\n        languages: ${{ matrix.language }}\n        # If you wish to specify custom queries, you can do so here or in a config file.\n        # By default, queries listed here will override any specified in a config file.\n        # Prefix the list here with \"+\" to use these queries and those in the config file.\n\n        # Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs\n        # queries: security-extended,security-and-quality\n\n\n    # Autobuild attempts to build any compiled languages  (C/C++, C#, or Java).\n    # If this step fails, then you should remove it and run the build manually (see below)\n    - name: Autobuild\n      uses: github/codeql-action/autobuild@v2\n\n    # ℹ️ Command-line programs to run using the OS shell.\n    # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun\n\n    #   If the Autobuild fails above, remove it and uncomment the following three lines.\n    #   modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance.\n\n    # - run: |\n    #   echo \"Run, Build Application using script\"\n    #   ./location_of_script_within_repo/buildscript.sh\n\n    - name: Perform CodeQL Analysis\n      uses: github/codeql-action/analyze@v2\n"
  },
  {
    "path": ".gitignore",
    "content": "# PLATFORM\n# ========\n# All exclusions that are specific to the NPM, GIT, IDE and Operating Systems.\n\n# - Do not allow installed node modules to be committed. Doing `npm install -d` will bring them in root or other places.\nnode_modules\n\n# - Do not commit any log file from anywhere\n*.log\n*.log.*\n\n# - Prevent addition of OS specific file explorer files\nThumbs.db\n.DS_Store\n\n# Prevent IDE stuff\n.idea\n.vscode\n\n# PROJECT\n# =======\n# Configuration pertaining to project specific repository structure.\n\n# - Prevent Sublime text IDE files from being committed to repository\n*.sublime-*\n\n# - Allow sublime text project file to be committed in the development directory.\n!/develop/*.sublime-project\n\n# - Prevent CI output files from being Added\n/out/\n/newman/\n\n# - Prevent diff backups from SourceTree from showing as commit.\n*.BACKUP.*\n*.BASE.*\n*.LOCAL.*\n*.REMOTE.*\n*.orig\n\n# - Prevent unit test coverage reports from being committed to the repository\n.coverage\n.nyc_output\n"
  },
  {
    "path": ".npmignore",
    "content": "# PLATFORM\n# ========\n# All exclusions that are specific to the NPM, GIT, IDE and Operating Systems.\n\n# - Do not allow installed node modules to be committed. Doing `npm install -d` will bring them in root or other places.\nnode_modules\n\n# - Do not commit any log file from anywhere\n*.log\n*.log.*\n\n# - Prevent addition of OS specific file explorer files\nThumbs.db\n.DS_Store\n\n# Prevent IDE stuff\n.idea\n.vscode\n\n# PROJECT\n# =======\n# Configuration pertaining to project specific repository structure.\n\n# - Prevent Sublime text IDE files from being committed to repository\n*.sublime-*\n\n# - Allow sublime text project file to be committed in the development directory.\n!/develop/*.sublime-project\n\n# - Prevent CI output files from being added\n/out/\n/newman/\n\n# - Prevent diff backups from SourceTree from showing as commit.\n*.BACKUP.*\n*.BASE.*\n*.LOCAL.*\n*.REMOTE.*\n*.orig\n\n# - Prevent code coverage reports from being added\n.coverage\n.nyc_output\n\n# - Prevent config and test files from being added\n.git*\nnpm/\ntest/\nexamples/\ncodecov.yml\n.eslintrc\n.nycrc.js\n.dockerignore\n.editorconfig\n.jsdoc-config.json\n"
  },
  {
    "path": ".nycrc.js",
    "content": "const TEST_TYPE = ((argv) => {\n    let match = argv[argv.length - 1].match(/npm\\/test-(\\w+).js/);\n\n    return match && match[1] || '';\n})(process.argv);\n\nfunction configOverrides (testType) {\n    switch (testType) {\n        case 'cli':\n            return {\n                statements: 80,\n                branches: 65,\n                functions: 85,\n                lines: 80\n            };\n        case 'integration':\n            return {\n                statements: 40,\n                branches: 20,\n                functions: 40,\n                lines: 40\n            };\n        case 'library':\n            return {\n                statements: 55,\n                branches: 40,\n                functions: 55,\n                lines: 55\n            };\n        case 'unit':\n            return {\n                statements: 70,\n                branches: 55,\n                functions: 80,\n                lines: 70\n            };\n        default:\n            return {}\n    }\n}\n\nmodule.exports = {\n    all: true,\n    'check-coverage': true,\n    'report-dir': '.coverage',\n    'temp-dir': '.nyc_output',\n    include: ['lib/**/*.js', 'bin/**/*.js'],\n    reporter: ['lcov', 'json', 'text', 'text-summary'],\n    ...configOverrides(TEST_TYPE),\n};\n"
  },
  {
    "path": "CHANGELOG.yaml",
    "content": "6.2.2:\n  date: 2026-01-16\n  chores:\n    - Update dependencies\n\n6.2.1:\n  date: 2024-08-20\n  fixed bugs:\n    - Reverted GH-3263\n\n6.2.0:\n  date: 2024-08-16\n  new features:\n    - GH-3263 Added support for HTTP/2\n  fixed bugs:\n    - GH-3231 Fixed a bug where JUnit reporter sets the wrong classname\n  chores:\n    - >-\n      GH-3258 Converted the deprecated `apikey` parameter in Postman API urls to\n      `x-api-key` header\n    - Updated dependencies\n\n6.1.3:\n  date: 2024-06-10\n  chores:\n    - Updated dependencies\n\n6.1.2:\n  date: 2024-03-14\n  fixed bugs:\n    - GH-3212 Fixed a bug where `--color off` was not respected in summary table\n  chores:\n    - Updated dependencies\n\n6.1.1:\n  date: 2024-02-05\n  chores:\n    - Updated dependencies\n\n6.1.0:\n  date: 2023-12-27\n  new features:\n    - |\n      GH-3183 Uses the latest Postman Runtime, which adds support for:\n        -> Skipping request execution via pm.execution.skipRequest()\n        -> Fetching execution location via using pm.execution.location\n        -> Atlassian's ASAP authentication\n  chores:\n    - GH-3183 Updated dependencies\n\n6.0.0:\n  date: 2023-09-15\n  new features:\n    - |\n      GH-3146 Uses the latest Postman Runtime, which adds support for:\n        -> JWT authentication\n        -> NTLMv2 authentication\n        -> Promise execution in scripts\n        -> Stripping JSON comments in the raw mode body\n        -> ...and several improvements and bug fixes\n    - Multi-platform Docker images\n  fixed bugs:\n    - GH-3146 Fixed a bug where an invalid `folder` input used to exit silently\n  breaking changes:\n    - GH-3145 Dropped support for Node < v16\n    - GH-3148 Dropped support for deprecated docker images\n  chores:\n    - GH-3146 Updated dependencies\n    - GH-3146 Updated ESLint rules\n    - GH-3145 Migrate to GitHub Actions\n\n5.3.2:\n  date: 2022-03-03\n  fixed bugs:\n    - Allow the process to exit naturally in CLI mode\n  chores:\n    - Updated dependencies\n\n5.3.1:\n  date: 2022-01-10\n  chores:\n    - Updated dependencies\n\n5.3.0:\n  date: 2021-09-07\n  new features:\n    - >-\n      GH-2806 Exposed the runner on newman and the runtime run object in start\n      event\n    - >-\n      Added ability to see request and responses in CLI reporter `--verbose`\n      mode. Also added ability to see additional meta such as header count,\n      cookie count and body mime-types in verbose mode.\n  chores:\n    - Updated dependencies\n\n5.2.4:\n  date: 2021-06-24\n  chores:\n    - Updated dependencies\n\n5.2.3:\n  date: 2021-05-03\n  chores:\n    - Updated dependencies\n\n5.2.2:\n  date: 2021-01-03\n  chores:\n    - Updated dependencies\n\n5.2.1:\n  date: 2020-11-02\n  chores:\n    - Updated dependencies\n\n5.2.0:\n  date: 2020-09-01\n  new features:\n    - GH-2393 Added support for providing custom Cookie Jar\n  chores:\n    - Updated dependencies\n\n5.1.2:\n  date: 2020-07-13\n  chores:\n    - Updated dependencies\n\n5.1.1:\n  date: 2020-07-08\n  chores:\n    - Updated dependencies\n\n5.1.0:\n  date: 2020-06-09\n  new features:\n    - >-\n      GH-2392 Added a new `requestAgents` option to define custom requesting\n      agents\n  chores:\n    - Updated dependencies\n\n5.0.1:\n  date: 2020-05-18\n  fixed bugs:\n    - GH-2335 Improved error messages on file load error\n  chores:\n    - GH-2354 Updated dependencies\n\n5.0.0:\n  date: 2020-04-08\n  new features:\n    - GH-2299 Uses next-generation URL processor\n  breaking changes:\n    - GH-2297 Dropped support for Node < v10\n    - GH-2251 Changed escape character for CSV to double-quotes\n    - GH-2303 Trimmed incoming CSV string to remove byte order mark\n  chores:\n    - >-\n      GH-2308 Updated .npmignore to prevent the addition of tests and config\n      files in the published package\n    - GH-2301 Updated nyc configuration\n    - GH-2298 Updated ESLint rules\n    - GH-2298 Updated dependencies\n\n4.6.1:\n  date: 2020-04-06\n  chores:\n    - Updated dependencies\n\n4.6.0:\n  date: 2020-02-24\n  new features:\n    - >-\n      GH-2235 Added a new option `--ssl-client-cert-list` to allow setting\n      different certificates for different URLs in the collection\n    - >-\n      GH-2208 Added a new option `--ssl-extra-ca-certs` to extend well known\n      \"root\" CAs with the extra certificates in the file\n  chores:\n    - GH-2209 Added `nyc` and `codecov` for test coverage\n    - GH-2236 Updated dependencies\n\n4.5.7:\n  date: 2019-12-06\n  chores:\n    - Updated dependencies\n\n4.5.6:\n  date: 2019-11-18\n  chores:\n    - Updated dependencies\n\n4.5.5:\n  fixed bugs:\n    - Fixed a bug where runtime execution crashes on Node v12\n    - >-\n      GH-2062 Added warnings for \"reporter not found\" and \"reporter could not be\n      loaded\"\n  chores:\n    - Updated dependencies\n\n4.5.4:\n  date: 2019-08-14\n  chores:\n    - Updated dependencies\n\n4.5.3:\n  date: 2019-08-02\n  chores:\n    - Updated dependencies\n\n4.5.2:\n  date: 2019-08-01\n  chores:\n    - Updated dependencies\n\n4.5.1:\n  date: 2019-06-19\n  chores:\n    - Updated dependencies\n\n4.5.0:\n  date: 2019-05-16\n  new features:\n    - Added support for the working directory using SecureFS\n    - Added --working-dir and --no-insecure-file-read CLI options\n  fixed bugs:\n    - >-\n      Fixed a bug that caused fetching collection from HTTPS URL crashes on Node\n      v12\n  chores:\n    - Updated dependencies\n\n4.4.1:\n  date: 2019-03-25\n  chores:\n    - Updated dependencies\n  fixed bugs:\n    - >-\n      GH-1932 Removed classname from JUnit reports and add it to both passed and\n      failed tests\n\n4.4.0:\n  date: 2019-02-20\n  chores:\n    - Updated dependencies\n  fixed bugs:\n    - >-\n      GH-1871 Trimmed incoming JSON string to remove byte order marks and other\n      such artifacts.\n    - Contextual help messages for newman -h\n    - Fixed JUnit report generation for nested requests/tests\n    - Corrected disabled variable behavior\n  new features:\n    - Added automatic (best guess) encoding detection of UTF-16LE and ISO-8859-1\n    - Added --verbose flag for detailed CLI output\n\n4.3.1:\n  date: 2018-12-26\n  fixed bugs:\n    - >-\n      Added start timestamp, classname and failure message to JUnit reporter for\n      Azure DevOps\n\n4.3.0:\n  date: 2018-12-26\n  new features:\n    - Added AJV to the script sandbox\n  fixed bugs:\n    - Respected form data field ordering\n    - >-\n      Fixed a bug that caused requests to fail when the URL protocol is not in\n      lowercase\n\n4.2.3:\n  date: 2018-12-15\n  fixed bugs:\n    - GH-1823 Added missing skipped flag to assertion information aggregator\n\n4.2.2:\n  date: 2018-11-07\n  fixed bugs:\n    - >-\n      GH-1784 Updated postman-runtime to v7.4.2, which fixes a hawk security\n      vulnerability\n\n4.2.1:\n  date: 2018-11-04\n  fixed bugs:\n    - GH-1779 Updated postman-runtime to v7.4.1\n\n4.2.0:\n  date: 2018-11-03\n  new features:\n    - >-\n      GH-1776 Introduced the generic postman/newman Docker image, bumped Node\n      version to 10\n    - GH-1731 Added support for custom HTTP verbs\n  docs:\n    - GH-1717 Updated Docker image documentation\n  chores:\n    - GH-1770 Shifted to Travis for Windows builds\n    - >-\n      GH-1769 Added .gitattributes to enforce consistent line endings for .js\n      files\n    - >-\n      GH-1743 Updated CLI reporter left padding to account for commander v2.19\n      changes\n    - Updated dependencies\n\n4.1.0:\n  date: 2018-08-29\n  new features:\n    - GH-1654 Added ability to select multiple folders for collection run\n  chores:\n    - GH-1687 Added `newmanVersion` in collection run options\n    - GH-1684 Fixed flaky tests\n    - Updated Dependencies\n\n4.0.2:\n  date: 2018-08-09\n  fixed bugs:\n    - >-\n      GH-1673 Fixed a bug that prevented request errors from showing up in CLI\n      reports\n\n4.0.1:\n  date: 2018-08-08\n  fixed bugs:\n    - GH-1669 Deprecated support for the v1 Postman Collection format\n    - GH-1670 Throw proper error message for invalid --color values\n\n4.0.0:\n  date: 2018-08-06\n  new features:\n    - GH-1633 Added ability to run collection via Postman API UID reference\n  breaking changes:\n    - GH-1605 Dropped support for Node < v6\n    - GH-1610 Dropped support for v2 CLI options\n    - GH-1660 Dropped support for the v1 Postman Collection format\n    - >-\n      GH-1616 Moved inbuilt HTML reporter to a standalone reporter:\n      https://github.com/postmanlabs/newman-reporter-html\n    - GH-1653 Updated `color` option behaviour, dropped support for --no-color\n  fixed bugs:\n    - GH-1609 Fixed CSV auto parse, to avoid parsing numbers inside quotes\n    - GH-1630 Updated default timeout values to Infinity\n  chores:\n    - GH-1623 Refactored Newman CLI\n    - GH-1608 Updated ESLint rules\n    - GH-1618 Reformatted README\n    - Updated Dependencies\n\n3.10.0:\n  date: 2018-07-04\n  new features:\n    - GH-1596 Added --reporter-cli-no-banner option\n    - GH-1551 Bumped Alpine Docker image Node version to v8\n    - GH-1555 Added failure list to HTML reports\n  fixed bugs:\n    - GH-1612 Fixed JUnit reports for failed cases\n    - >-\n      GH-1576 Accounted for cases where the export path is a pre-existing\n      directory\n    - GH-1601 Reversed reporter lookup logic\n    - GH-1584 Improved timeout messaging in HTML reports\n    - GH-1594 Fixed a bug that caused reporter flags to break with `=`\n    - GH-1592 Added a link to the Alpine Docker image\n    - GH-1583 Capped JUnit timing precision to 3 decimal places\n    - GH-1563 Ensured that all exported variable files have a valid name\n    - GH-1578 Switched to cli-table3\n    - GH-1575 Fixed typo in directory collection runner example\n    - >-\n      GH-1553 Fixed a bug that caused HTML reports to incorrectly duplicate\n      requests across multiple iterations\n\n3.9.4:\n  date: 2018-05-25\n  fixed bugs:\n    - GH-1390 Improved failure table reporting details\n    - GH-1389 Fixed no-assertions behavior for the CLI reporter\n    - GH-1428 Corrected help text for missing arguments\n    - GH-1397 Added postpublish script for automated Docker image pushing\n    - GH-1416 Corrected Postman API reference link\n    - Switched to a YAML changelog 1448\n    - GH-1443 Corrected error representation in JUnit reports\n    - >-\n      GH-1496 Removed wait spinner from CLI output when --disable-unicode is\n      present\n    - GH-1450 Added support for --no-success-assertions\n    - GH-1528 Made folder and request IDs unique in generated HTML reports\n    - Updated dependencies\n\n3.9.3:\n  date: 2018-01-19\n  fixed bugs:\n    - Updated dependencies\n    - GH-1385 Fixed minor formatting issues in the readme.\n    - >-\n      GH-1368 Updated folder collection runner example to exclude package*.json\n      files\n\n3.9.2:\n  date: 2018-01-11\n  fixed bugs:\n    - Updated dependencies\n    - >-\n      GH-1366 Replaced deprecated Slack community link in the readme with the\n      shiny new Postman community\n    - GH-1350 Added setNextRequest information to the CLI reporter\n    - >-\n      GH-1331 Fixed a bug that caused legacy arguments to be processed out of\n      order\n\n3.9.1:\n  date: 2017-12-08\n  fixed bugs:\n    - GH-1326 Fixed folder option handling\n    - GH-1323 Updated documentation for --bail and options.bail\n    - GH-1325 Fixed typographical error in issue template\n\n3.9.0:\n  date: 2017-12-05\n  new features:\n    - GH-1320 Extended --bail`` to work with afolder` option\n    - GH-1298 Improved help text for incorrect usage\n    - GH-1292 Added a name field to all applicable errors\n    - GH-1278 Migrated from argparse to commander\n    - GH-1277 Added support for a global timeout option\n    - GH-1275 Migrated from istanbul to nyc\n    - GH-1273 Tests now run on Node v8 as well\n\n3.8.3:\n  date: 2017-10-04\n  fixed bugs:\n    - Updated dependencies\n    - >-\n      GH-1227 Added timeout-script to extend default sandbox script execution\n      timeouts\n    - GH-1206 Corrected failure table handle in non TTY environments\n    - GH-1218 Made JSON parsing more robust\n\n3.8.2:\n  date: 2017-09-18\n  fixed bugs:\n    - Updated dependencies.\n    - >-\n      GH-1202 Fixed a bug that caused csv files with comma spaces to be\n      processed incorrectly.\n    - GH-1191 Corrected programmatic iterationData usage in README.\n    - GH-1197 Fixed broken link in parallel-collection-runs.js\n\n3.8.1:\n  date: 2017-08-18\n  fixed bugs:\n    - GH-1173 Updated postman-runtime to v6.2.6\n    - GH-1172 Updated postman-collection to v2.1.1\n\n3.8.0:\n  date: 2017-06-25\n  new features:\n    - GH-1142 Added support for global variable specification via the CLI\n\n3.7.6:\n  date: 2017-06-19\n  fixed bugs:\n    - >-\n      Bumped postman-runtime to v6.2.5, which contains a critical cookie\n      handling bugfix.\n    - Updated other dependencies.\n\n3.7.5:\n  date: 2017-06-10\n  fixed bugs:\n    - >-\n      GH-1110 Bumped Collection SDK to v2.0.2, which contains ProxyConfig\n      improvements.\n    - >-\n      GH-1115 Ensured that failed fetches from resource URLs result in a\n      non-zero exit code.\n    - >-\n      GH-1105 Fixed a backward compatibility bug related to Buffer construction\n      in the HTML reporter.\n\n3.7.4:\n  date: 2017-06-29\n  fixed bugs:\n    - GH-1099 Corrected response.body reference in the HTML reporter\n\n3.7.3:\n  date: 2017-06-28\n  fixed bugs:\n    - Updated dependencies.\n    - >-\n      GH-1098 Restored response.body in the data supplied to the HTML reporter\n      template.\n\n3.7.2:\n  date: 2017-06-23\n  fixed bugs:\n    - >-\n      Updated postman-runtime to v6.2.1, which contains a critical bugfix for\n      authorization with variables\n\n3.7.1:\n  date: 2017-06-19\n  fixed bugs:\n    - GH-1082 Updated postman-collection-transformer to v2.1.4\n\n3.7.0:\n  date: 2017-06-19\n  new features:\n    - >-\n      GH-1080 Fixed a bug that caused empty results in response.json() and\n      response.text()\n    - >-\n      Support for second generation scripting sandbox with support for limited\n      require.\n    - Addition of assertion functions on request and response.\n    - Added momentjs to the sandbox.\n    - Added support for authorization mechanisms and IO events.\n\n3.6.1:\n  date: 2017-06-09\n  fixed bugs:\n    - Updated dependencies\n    - GH-1026 Ensured that stdout is flushed on process.exit in CLI mode\n    - GH-1062 Fixed type error for failed requests in the HTML reporter\n    - >-\n      GH-1039 Updated JUnit reporter to add time attribute to testsuites and\n      testcase elements\n\n3.6.0:\n  date: 2017-03-12\n  new features:\n    - Updated dependencies\n    - Introduced all new pm.* API.\n\n3.5.2:\n  date: 2017-03-17\n  fixed bugs:\n    - >-\n      Update postman-runtime to v5.0.0, which uses CertificateList for client\n      side SSL\n\n3.5.1:\n  date: 2017-03-14\n  fixed bugs:\n    - GH-949 Fixed a bug which caused some test results to not be displayed\n    - Merged aggregation partial into base HTML reporter template\n    - >-\n      Allowed options.iterationData to be specified as an array of objects in\n      programmatic usage\n\n3.5.0:\n  date: 2017-03-07\n  new features:\n    - Added support for multi level folders in the cli, html and junit reporters\n    - >-\n      Updated postman-collection to v1.0.0, which contains helper methods for\n      dealing with multi-level folders\n    - Updated many other non-critical packages\n\n3.4.3:\n  date: 2017-01-31\n  fixed bugs:\n    - >-\n      Updated postman-runtime to v4.0.3, which contains fixed bugs for URL\n      parameter encoding\n    - >-\n      Updated postman-collection to v0.5.11, which contains fixed bugs for UTF-8\n      encoded responses, and variables in URL hosts\n\n3.4.2:\n  date: 2017-01-09\n  fixed bugs:\n    - GH-859 Fixed a bug in the CLI reporter for Newman programmatic usage\n\n3.4.1:\n  date: 2017-01-06\n  fixed bugs:\n    - Fixed Buffer compatibility issue for Node v4\n    - HTML reporter works correctly for failed requests\n\n3.4.0:\n  date: 2016-12-29\n  new features:\n    - >-\n      Updated postman-runtime to v4.0, which has a lot of memory usage\n      improvements\n    - HTML reporter now contains folder information\n    - Added --color option to force colored output in non-TTY environments\n\n3.3.1:\n  date: 2016-12-14\n  fixed bugs:\n    - Added more details to the HTML reporter\n    - >-\n      Updated postman-collection to the latest version which contains a bugfix\n      for OAuth1 with realms\n    - Updated postman-runtime which has a few fixes for browser based workflows\n\n3.3.0:\n  date: 2016-11-21\n  new features:\n    - Added options to provide client-side SSL certificates on the command line\n    - Updated the versions of postman-runtime and postman-collection libraries\n\n3.2.0:\n  date: 2016-10-18\n  new features:\n    - Ensure that environment exports are consistent with the app\n    - Simplified the importing logic for environment and globals\n\n3.1.2:\n  date: 2016-08-25\n  fixed bugs:\n    - >-\n      Updated postman-runtime, postman-collection and\n      postman-collection-transformer dependencies\n\n3.1.1:\n  date: 2016-08-25\n  fixed bugs:\n    - Fixed a bug which caused HTML reporter statistics to be incorrect\n    - >-\n      Added an option --disable-unicode to forcibly disable unicode symbols in\n      the output\n    - >-\n      File based options in newman.run (environments, data, globals) can now be\n      specified as JSON objects as well\n    - >-\n      Updated to the latest version of Postman Runtime, which contains a number\n      of memory optimizations\n    - >-\n      Specifying an iteration data file now results in the correct number of\n      iteration runs\n\n3.1.0:\n  date: 2016-08-25\n  new features:\n    - >-\n      GH-553 Fixed issue with environment and globals export format was using\n      wrong property names\n    - Fixed issue where --export-* CLI option did not work with no parameters\n    - Added support for postman.getResponseCookie in the script sandbox\n    - Prettified HTML report template\n    - >-\n      Added support for custom HTML report templates via\n      --reporter-html-template flag\n    - Added file upload support\n    - GH-547 Fixed a bug in the timeout request flag\n    - Updated runtime dependency to 2.4.4\n    - Fixed a bug that caused incorrect iterationCount detection\n    - Better error messages\n    - Fixed a bug that caused incorrect exports of environment and global values\n    - The export parameters now default to /newman/*\n    - >-\n      Added a new CLI option, --silent which ensures Newman does not write\n      anything to the terminal\n\n3.0.1:\n  date: 2016-08-09\n  fixed bugs:\n    - Updated Postman Runtime to v2.4.1\n    - Newman now exits with a non-zero status code on test failures or errors\n\n3.0.0:\n  date: 2016-08-09\n  fixed bugs:\n    - First stable release of Newman v3.0\n    - Added ability to suppress exit code on failures\n    - >-\n      Renamed the \"--stop-on-error\" option to \"--bail\", which ensures that\n      Newman stops on test failures or errors\n\n3.0.0-rc.1:\n  date: 2016-08-08\n  initial release:\n    - Initial release of Newman v3. Migration Guide\n"
  },
  {
    "path": "LICENSE.md",
    "content": "                                 Apache License\n                           Version 2.0, January 2004\n                        http://www.apache.org/licenses/\n\n   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n   1. Definitions.\n\n      \"License\" shall mean the terms and conditions for use, reproduction,\n      and distribution as defined by Sections 1 through 9 of this document.\n\n      \"Licensor\" shall mean the copyright owner or entity authorized by\n      the copyright owner that is granting the License.\n\n      \"Legal Entity\" shall mean the union of the acting entity and all\n      other entities that control, are controlled by, or are under common\n      control with that entity. For the purposes of this definition,\n      \"control\" means (i) the power, direct or indirect, to cause the\n      direction or management of such entity, whether by contract or\n      otherwise, or (ii) ownership of fifty percent (50%) or more of the\n      outstanding shares, or (iii) beneficial ownership of such entity.\n\n      \"You\" (or \"Your\") shall mean an individual or Legal Entity\n      exercising permissions granted by this License.\n\n      \"Source\" form shall mean the preferred form for making modifications,\n      including but not limited to software source code, documentation\n      source, and configuration files.\n\n      \"Object\" form shall mean any form resulting from mechanical\n      transformation or translation of a Source form, including but\n      not limited to compiled object code, generated documentation,\n      and conversions to other media types.\n\n      \"Work\" shall mean the work of authorship, whether in Source or\n      Object form, made available under the License, as indicated by a\n      copyright notice that is included in or attached to the work\n      (an example is provided in the Appendix below).\n\n      \"Derivative Works\" shall mean any work, whether in Source or Object\n      form, that is based on (or derived from) the Work and for which the\n      editorial revisions, annotations, elaborations, or other modifications\n      represent, as a whole, an original work of authorship. For the purposes\n      of this License, Derivative Works shall not include works that remain\n      separable from, or merely link (or bind by name) to the interfaces of,\n      the Work and Derivative Works thereof.\n\n      \"Contribution\" shall mean any work of authorship, including\n      the original version of the Work and any modifications or additions\n      to that Work or Derivative Works thereof, that is intentionally\n      submitted to Licensor for inclusion in the Work by the copyright owner\n      or by an individual or Legal Entity authorized to submit on behalf of\n      the copyright owner. For the purposes of this definition, \"submitted\"\n      means any form of electronic, verbal, or written communication sent\n      to the Licensor or its representatives, including but not limited to\n      communication on electronic mailing lists, source code control systems,\n      and issue tracking systems that are managed by, or on behalf of, the\n      Licensor for the purpose of discussing and improving the Work, but\n      excluding communication that is conspicuously marked or otherwise\n      designated in writing by the copyright owner as \"Not a Contribution.\"\n\n      \"Contributor\" shall mean Licensor and any individual or Legal Entity\n      on behalf of whom a Contribution has been received by Licensor and\n      subsequently incorporated within the Work.\n\n   2. Grant of Copyright License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      copyright license to reproduce, prepare Derivative Works of,\n      publicly display, publicly perform, sublicense, and distribute the\n      Work and such Derivative Works in Source or Object form.\n\n   3. Grant of Patent License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      (except as stated in this section) patent license to make, have made,\n      use, offer to sell, sell, import, and otherwise transfer the Work,\n      where such license applies only to those patent claims licensable\n      by such Contributor that are necessarily infringed by their\n      Contribution(s) alone or by combination of their Contribution(s)\n      with the Work to which such Contribution(s) was submitted. If You\n      institute patent litigation against any entity (including a\n      cross-claim or counterclaim in a lawsuit) alleging that the Work\n      or a Contribution incorporated within the Work constitutes direct\n      or contributory patent infringement, then any patent licenses\n      granted to You under this License for that Work shall terminate\n      as of the date such litigation is filed.\n\n   4. Redistribution. You may reproduce and distribute copies of the\n      Work or Derivative Works thereof in any medium, with or without\n      modifications, and in Source or Object form, provided that You\n      meet the following conditions:\n\n      (a) You must give any other recipients of the Work or\n          Derivative Works a copy of this License; and\n\n      (b) You must cause any modified files to carry prominent notices\n          stating that You changed the files; and\n\n      (c) You must retain, in the Source form of any Derivative Works\n          that You distribute, all copyright, patent, trademark, and\n          attribution notices from the Source form of the Work,\n          excluding those notices that do not pertain to any part of\n          the Derivative Works; and\n\n      (d) If the Work includes a \"NOTICE\" text file as part of its\n          distribution, then any Derivative Works that You distribute must\n          include a readable copy of the attribution notices contained\n          within such NOTICE file, excluding those notices that do not\n          pertain to any part of the Derivative Works, in at least one\n          of the following places: within a NOTICE text file distributed\n          as part of the Derivative Works; within the Source form or\n          documentation, if provided along with the Derivative Works; or,\n          within a display generated by the Derivative Works, if and\n          wherever such third-party notices normally appear. The contents\n          of the NOTICE file are for informational purposes only and\n          do not modify the License. You may add Your own attribution\n          notices within Derivative Works that You distribute, alongside\n          or as an addendum to the NOTICE text from the Work, provided\n          that such additional attribution notices cannot be construed\n          as modifying the License.\n\n      You may add Your own copyright statement to Your modifications and\n      may provide additional or different license terms and conditions\n      for use, reproduction, or distribution of Your modifications, or\n      for any such Derivative Works as a whole, provided Your use,\n      reproduction, and distribution of the Work otherwise complies with\n      the conditions stated in this License.\n\n   5. Submission of Contributions. Unless You explicitly state otherwise,\n      any Contribution intentionally submitted for inclusion in the Work\n      by You to the Licensor shall be under the terms and conditions of\n      this License, without any additional terms or conditions.\n      Notwithstanding the above, nothing herein shall supersede or modify\n      the terms of any separate license agreement you may have executed\n      with Licensor regarding such Contributions.\n\n   6. Trademarks. This License does not grant permission to use the trade\n      names, trademarks, service marks, or product names of the Licensor,\n      except as required for reasonable and customary use in describing the\n      origin of the Work and reproducing the content of the NOTICE file.\n\n   7. Disclaimer of Warranty. Unless required by applicable law or\n      agreed to in writing, Licensor provides the Work (and each\n      Contributor provides its Contributions) on an \"AS IS\" BASIS,\n      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n      implied, including, without limitation, any warranties or conditions\n      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n      PARTICULAR PURPOSE. You are solely responsible for determining the\n      appropriateness of using or redistributing the Work and assume any\n      risks associated with Your exercise of permissions under this License.\n\n   8. Limitation of Liability. In no event and under no legal theory,\n      whether in tort (including negligence), contract, or otherwise,\n      unless required by applicable law (such as deliberate and grossly\n      negligent acts) or agreed to in writing, shall any Contributor be\n      liable to You for damages, including any direct, indirect, special,\n      incidental, or consequential damages of any character arising as a\n      result of this License or out of the use or inability to use the\n      Work (including but not limited to damages for loss of goodwill,\n      work stoppage, computer failure or malfunction, or any and all\n      other commercial damages or losses), even if such Contributor\n      has been advised of the possibility of such damages.\n\n   9. Accepting Warranty or Additional Liability. While redistributing\n      the Work or Derivative Works thereof, You may choose to offer,\n      and charge a fee for, acceptance of support, warranty, indemnity,\n      or other liability obligations and/or rights consistent with this\n      License. However, in accepting such obligations, You may act only\n      on Your own behalf and on Your sole responsibility, not on behalf\n      of any other Contributor, and only if You agree to indemnify,\n      defend, and hold each Contributor harmless for any liability\n      incurred by, or claims asserted against, such Contributor by reason\n      of your accepting any such warranty or additional liability.\n\n   END OF TERMS AND CONDITIONS\n\n\n   APPENDIX: How to apply the Apache License to your work.\n\n      To apply the Apache License to your work, attach the following\n      boilerplate notice, with the fields enclosed by brackets \"{}\"\n      replaced with your own identifying information. (Don't include\n      the brackets!)  The text should be enclosed in the appropriate\n      comment syntax for the file format. We also recommend that a\n      file or class name and description of purpose be included on the\n      same \"printed page\" as the copyright notice for easier\n      identification within third-party archives.\n\n   Copyright 2016 Postdot Technologies, Inc\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n\n"
  },
  {
    "path": "MIGRATION.md",
    "content": "# Newman\n\n## Table of contents\n\n1. [Updating to the latest version](#updating-to-the-latest-version)\n2. [Migrating from V5 to V6](#migrating-from-v5-to-v6)\n3. [Migrating from V4 to V5](#migrating-from-v4-to-v5)\n4. [Migrating from V3 to V4](#migrating-from-v3-to-v4)\n5. [Migrating from V2 to V3](#migrating-from-v2-to-v3)\n\n## Updating to the latest version\n\nIf you're updating from an older version of Newman, make sure you read the rest of this document, to understand the changes.\n\n#### 1. Update Newman\n```console\n$ npm update -g newman\n```\n\n#### 2. Check Installation\n```console\n$ newman --version          # Should show the latest version of Newman\n$ npm show newman version   # Should show the same version as of above\n```\n\n---\n\n## Migrating from V5 to V6\n\nNewman v6.0 requires Node.js v16 or higher. Also, the runtime dependencies are upgraded to their latest versions.\n\n### Upgrading Node.js\nNewman v6 requires Node.js >= v16. [Install Node.js via package manager](https://nodejs.org/en/download/package-manager/).\n\n### Latest Postman Runtime\nNewman v6 uses the latest version of the Postman Runtime dependencies. This brings in several improvements and bug fixes.\nHere are some of the notable additions:\n* JWT authentication\n* NTLMv2 authentication\n* Promise execution in scripts\n* Stripping JSON comments in the raw mode body\n\n### Docker Images\nNewman v6 drops support for deprecated `postman/newman_alpine33` and `postman/newman_ubuntu1404` Docker images.\n\nThe two available Docker images, `postman/newman:alpine` and `postman/newman:ubuntu` are upgraded to Node.js v16.\n\n---\n\n## Migrating from V4 to V5\n\nNewman v5.0 drops support for Node v6 and v8. Also, the inbuilt URL and CSV processor are upgraded.\n\n### Upgrading Node.js\nNewman v5 requires Node.js >= v10. [Install Node.js via package manager](https://nodejs.org/en/download/package-manager/).\n\n### Next-Generation URL Processor\nNewman v5 introduces an improved URL processing system that fixes several limitations of the present URL processor around the aspects of parsing and encoding.\nKnow more about the changes in [this GitHub issue](https://github.com/postmanlabs/postman-app-support/issues/8154) and [this blog post](https://blog.postman.com/2020/04/06/introducing-the-next-generation-postman-url-processor/).\n\n### CSV parser\nThe longstanding [disparity](https://github.com/postmanlabs/postman-app-support/issues/8024) between the Newman and Postman app's CSV parser is fixed.\n\n#### Changed escape character to double-quotes\n\nThe default escape character is changed to `\"` (double quote) from `\\` (backslash).\n\n##### V4 CSV input\n```csv\nid, name\n\"\\\"1\\\"\", \"foo \\\"bar\\\" baz\"\n```\n\n##### V5 equivalent\n```csv\nid, name\n\"\"\"1\"\"\", \"foo \"\"bar\"\" baz\"\n```\n\n#### Relaxed parsing\n\n1. Preserve quotes inside unquoted field\n2. Discard inconsistent columns count\n3. Detect and exclude the byte order mark (BOM)\n\n---\n\n## Migrating from V3 to V4\n\nNewman v4.0 drops support for Node v4 and dropped support for v2 CLI options. Also, the inbuilt HTML reporter has been moved to a standalone reporter.\n\n### Upgrading Node.js\nNewman v4 requires Node.js >= v6. [Install Node.js via package manager](https://nodejs.org/en/download/package-manager/).\n\n### Discontinued CLI Options\nNewman v4 drops support for all the deprecated v2 CLI options, check [V2 to V3 Migration Guide](#v2-to-v3-migration-guide).<br/>\nFor the complete list of supported options, see the [README](README.md)\n\n#### --no-color\nThis option is dropped because of the changes made to the `color` option. See the section below for more details.\n\n### Using `color` option\nThe behaviour of this option is changed in both CLI and Library. Unlike Newman v3.x, this option alone can be used to enable\nor disable colored CLI output.\n\n#### CLI\n\n##### 1. Enabling colored output\n\n###### V3 command\n```console\n$ newman run collection.json --color\n```\n\n###### V4 equivalent\n```console\n$ newman run collection.json --color on\n```\n\n##### 2. Disabling colored output\n\n###### V3 command\n```console\n$ newman run collection.json --no-color\n```\n\n###### V4 equivalent\n```console\n$ newman run collection.json --color off\n```\n\n#### Library\n\n##### 1. Enabling colored output\n\n###### Using V3\n```javascript\nnewman.run({\n    collection: 'collection.json',\n    reporters: ['cli'],\n    color: true\n}, callback);\n```\n\n###### V4 equivalent\n```javascript\nnewman.run({\n    collection: 'collection.json',\n    reporters: ['cli'],\n    color: 'on'\n}, callback);\n```\n\n##### 2. Disabling colored output\n\n###### Using V3\n```javascript\nnewman.run({\n    collection: 'collection.json',\n    reporters: ['cli'],\n    noColor: true\n}, callback);\n```\n\n###### V4 equivalent\n```javascript\nnewman.run({\n    collection: 'collection.json',\n    reporters: ['cli'],\n    color: 'off'\n}, callback);\n```\n\n**Note:**\nThe default behavior is to detect color support for the terminal and act accordingly.\nThis behavior can be modified by setting the color option to `on` or `off` respectively.\n\n### Using HTML Reporter\nThe inbuilt HTML reporter has been moved to a standalone reporter. Install it with:\n```console\n$ npm install -g newman-reporter-html\n```\nInstallation should be global if newman is installed globally, local otherwise. (Remove `-g` flag from the above command for a local installation.)\n\nThe complete installation and usage guide is available here: https://github.com/postmanlabs/newman-reporter-html\n\n### Deprecated support for the v1 collection format\nNewman >= v4 deprecates support for the v1 collection format.<br/>\nUse the [Postman Native app](https://postman.com/downloads) to export collections in the v2 format.\n\n### CSV auto parse\nA [fix][pr1609] has been made to avoid parsing numbers inside quotes.<br/>\nExample, `\"000123\"` will not be parsed to `123` like before.\n\nFixes issues: [#1100][i1100], [#1215][i1215] & [#1346][i1346]\n\n### Default timeouts\nAll timeouts now have the default value of infinity. [#1630](pr1630)\n\n[pr1609]: https://github.com/postmanlabs/newman/pull/1609\n[pr1630]: https://github.com/postmanlabs/newman/pull/1630\n[i1100]: https://github.com/postmanlabs/newman/issues/1100\n[i1215]: https://github.com/postmanlabs/newman/issues/1215\n[i1346]: https://github.com/postmanlabs/newman/issues/1346\n\n---\n\n## Migrating from V2 to V3\n\nNewman v3.0 is a complete rewrite of Newman from the ground up, which works well with other Node libraries, and\nallows flexibility for future features such as parallel collection runs, or performing parallel requests within the\nsame run. Above all, Newman now uses [Postman Runtime](https://github.com/postmanlabs/postman-runtime/) in order to\nprovide a consistent experience on Postman Apps and on CLI.\n\n### General overview of features\n\n1. Newman collection runs now happen with the `run` command. See sections below for more examples.\n2. More informative terminal output with colourful details of what went wrong, and most importantly, where it went\n   wrong.\n3. Ability to load environment, globals, collections as well as iteration data from urls.\n4. Friendlier usage as a library. A lot of use-cases depend on the use of Newman as a Node library, and v3.0 is written\n   with a library-first mindset.\n5. Internally things (by things, we usually mean code) have been better organised to allow faster implementation of\n   features.\n\n### Changes since v2.x\n\nMigrating to Newman v3.x for most simple use cases is a trivial affair. We have taken care to support older CLI options.\nWhich means, if you upgrade, it should just work! Having said that, we would soon discontinue the older CLI options and\nyou should start using the new ones. Furthermore, the new features are only available via the new CLI options.\n\nSince Newman 3.x is a complete rewrite, expect it to have subtle behavioural differences when compared with Newman v2.x,\nyour reports will look a bit different, the CLI output is a complete overhaul, your collection runs will inherit all the\nqualities of the new Postman Runtime (jQuery deprecation, discontinuation of DOM), etc. For a comprehensive list of\nusage changes across Newman V2 and V3, look at the table provided below.\n\nAs such, if there is something specific that not working with respect to v2.x or any workaround that you were doing,\nwe will be glad to chat and find out if they can still be done. You can find us on our [Community Forum](https://community.postman.com).\n\n### HTML, XML and other outputs are now \"reporters\"\nNewman v3 adopts a \"reporter\" model and as such features that were previously part of Newman core has now been moved\ninto reporters. Consequently, the CLI options for these features are now accessible via `--reporter-*` options. You\nmight also notice that some of the functionalities of reporters have been reduced even though the reporter outputs have\nbecome more detailed. This is to offload non-essential codebase away from Newman core and be later made pluggable into\nexternal reporter plugins.\n\n### --no-color is automated\nNewman now automatically detects lack of colour support and as such this flag does not need to be explicitly provided\nany more. However, `--no-color` is still available to force not to use colors in terminal output.\n\n### Discontinued CLI Options\n\n#### -S --noTestSymbols\nThis switch no longer has any effect. Newman v3 effectively handles unicode output on Windows Platform.\n\n#### -p, --pretty\nThis switch used to render exported JSON files in newman v2 in a pretty format. Newman v3 always exports in pretty\nformat and as such, this switch is now not needed. If you want to use compressed export formats, run the exported files\nthrough some JSON minifier.\n\n## V2 to V3 Migration Guide\n\nThe following tables enumerate the options that have either been deprecated / discontinued, or renamed in Newman V3. The\nV3 equivalents provided in the second column are intended for use with the `run` command (described below), and will not\nwork in V2 mode. The original options from V2, still work (without `run`, of course) however, but will be removed in the\nnext major Newman release.\n\nIn the V2 option status column, deprecated implies that the corresponding CLi option has been left for backward\ncompatibility and will be removed in the next major Newman release. A status of discontinued implies that the option is\nno longer supported, or is implemented by default.\n\nOptions missing from the migration tables have been left as they were from Newman V2. For the complete list of supported\noptions, see [README.md](https://github.com/postmanlabs/newman/blob/release/3.x/README.md)\n\n### CLI\n\n#### Sample use cases\n\n##### 1. A collection run with all basic options configured, excluding reporter actions\n\n###### V2 command\n```terminal\nnewman --collection collection.json --environment env.json --data data.csv --globals globals.json --number 2 --exportGlobals globalOut.json --exportEnvironment envOut.json --delay 10 --requestTimeout 5000 --noTestSymbols --tls --exitCode --whiteScreen --avoidRedirects --stopOnError\n```\n###### V3 equivalent\n```terminal\nnewman run collection.json --environment env.json --iteration-data data.csv --globals globals.json --iteration-count 2 --export-globals globalOut.json --export-environment envOut.json --delay-request 10 --timeout-request 5000 --disable-unicode --suppress-exit-code --ignore-redirects --bail\n```\n\n##### 2. A collection run with various reporter tasks\n\n###### V2 command\n```terminal\nnewman --url https://a.com/collection.json --environment-url https://a.com/env.json --noColor --outputFile jsonOut.json --testReportFile xmlOut.xml --html htmlOutput.html --outputFileVerbose verboseOut.log\n```\n###### V3 equivalent\n```terminal\nnewman run https://a.com/collection.json --environment https://a.com/env.json --reporters cli,html,json,junit --reporter-json-export jsonOut.json --reporter-junit-export xmlOut.xml --reporter-html-export htmlOutput.html\n```\n\n#### CLI migration table\n| V2 CLI option | V3 equivalent | V2 option Status |\n|---------------|---------------|------------------|\n| -c --collection | N.A | Deprecated (Pass the collection file path without the collection flag) |\n| -u --url | N.A | Deprecated (Pass the collection file URL without the collection flag) |\n| --environment-url | N.A | Deprecated (Pass the environment file URL to -e --environment) |\n| -f --folder | --folder | Deprecated. The V3 folder option has been reduced to --folder |\n| -d --data | -d --iteration-data | Deprecated |\n| -n --number | -n --iteration-count | Deprecated |\n| -i --import | N.A | Deprecated |\n| -p --pretty | N.A | Discontinued |\n| -G --exportGlobals | --export-globals | Deprecated |\n| -E --exportEnvironment | --export-environment | Deprecated |\n| -y --delay | --delay-request | Deprecated |\n| -r --requestTimeout | --timeout-request | Deprecated |\n| -s --stopOnError | --bail | Deprecated |\n| -j --noSummary | --reporter-cli-no-summary | Deprecated |\n| -C --noColour | --no-color | Deprecated |\n| -S --noTestSymbols | --disable-unicode | **Discontinued** |\n| -l --tls | N.A | **Discontinued** |\n| -x --exitCode | -x --suppress-exit-code | Deprecated (The V3 option takes no arguments, and forces an exit code of 0)|\n| -w --whiteScreen | N.A | **Discontinued** |\n| -o --outputFile | --reporter-json-export | Deprecated |\n| -t --testReportFile | --reporter-junit-export | Deprecated |\n| -H --html | --reporter-html-export | Deprecated |\n| -O --outputFileVerbose | N.A | **Discontinued** |\n| -R --avoidRedirects | --ignore-redirects | Deprecated |\n\n### Library usage\n\n#### Sample use cases\n\n##### 1. A collection run with all basic options configured, excluding reporter actions\n\n###### V2 command\n```javascript\nnewman.execute({\n    collection: 'collection.json',\n    environment: 'env.json',\n    data: 'data.csv',\n    globals: 'globals.json',\n    number: 2,\n    exportGlobals: 'globalOut.json',\n    exportEnvironment: 'envOut.json',\n    delay: 10,\n    stopOnError: true,\n    requestTimeout: 5000,\n    noTestSymbols: true,\n    tls: true,\n    exitCode: true,\n    whiteScreen: true,\n    avoidRedirects: true\n}, callback);\n```\n\n###### V3 equivalent\n```javascript\nnewman.run({\n    collection: 'collection.json',\n    environment: 'env.json',\n    iterationData: 'data.csv',\n    globals: 'globals.json',\n    iterationCount: 2,\n    exportGlobals: 'globalOut.json',\n    exportEnvironment: 'envOut.json',\n    delayRequest: 10,\n    bail: true,\n    timeoutRequest: 5000,\n    disableUnicode: true,\n    suppressExitCode: true,\n    ignoreRedirects: true\n}, callback);\n```\n\n##### 2 A collection run with various reporter tasks\n\n###### V2 command\n```javascript\nnewman.execute({\n    collection: 'https://a.com/collection.json',\n    environment: {\n        \"id\": \"my-id\",\n        \"name\": \"testEnv\",\n        \"values\": [\n            {\n                \"key\": \"env\",\n                \"value\": \"env2\",\n            },\n            {\n                \"key\": \"data\",\n                \"value\": \"env2\",\n            }\n        ]\n    },\n    globals: [\n        {\n            key: \"var1\",\n            value: \"/get\",\n            enabled: true\n        },\n        {\n            key: \"var2\",\n            value: \"Global Bar\",\n        }\n    ],\n    outputFile: 'jsonOut.json',\n    testReportFile: 'xmlOut.xml',\n    html: 'htmlOutput.html',\n    outputFileVerbose: 'verboseOut.log'\n}, callback);\n```\n\n###### V3 equivalent\n```javascript\nnewman.run({\n    collection: 'https://a.com/collection.json',\n    environment: {\n        \"id\": \"my-id\",\n        \"name\": \"testEnv\",\n        \"values\": [\n            {\n             \"key\": \"env\",\n             \"value\": \"env2\",\n            },\n            {\n             \"key\": \"data\",\n             \"value\": \"env2\",\n            }\n        ]\n    },\n    iterationData: [ {a: 1}, {a: 2} ],\n    globals: [\n        {\n            key: \"var1\",\n            value: \"/get\",\n            enabled: true\n        },\n        {\n            key: \"var2\",\n            value: \"Global Bar\",\n        }\n    ],\n    reporters: ['html', 'junit', 'json'],\n    reporter: {\n        html: {\n            export: 'htmlOutput.html'\n        },\n        junit: {\n            export: 'xmlOut.xml'\n        },\n        json: {\n            export: 'jsonOut.json'\n        }\n    }\n}, callback);\n```\n\n#### Library migration table\n| V2 `options` | V3 equivalent | V2 option Status |\n|---------------|---------------|------------------|\n| data | iterationData | Deprecated |\n| number | iterationCount | Deprecated |\n| delay | delayRequest | Deprecated |\n| requestTimeout | timeoutRequest | Deprecated |\n| noTestSymbols | disableUnicode | **Discontinued** |\n| stopOnError | bail | Deprecated |\n| exitCode | suppressExitCode | Deprecated |\n| avoidRedirects | ignoreRedirects | Deprecated |\n"
  },
  {
    "path": "README.md",
    "content": "<a href=\"https://www.postman.com/\"><img src=\"https://assets.getpostman.com/common-share/postman-logo-horizontal-320x132.png\" /></a><br />\n_Manage all of your organization's APIs in Postman, with the industry's most complete API development environment._\n\n# newman <sub>_the cli companion for postman_</sub> [![Build Status](https://github.com/postmanlabs/newman/actions/workflows/ci.yml/badge.svg?branch=develop)](https://github.com/postmanlabs/newman/actions/workflows/ci.yml) [![codecov](https://codecov.io/gh/postmanlabs/newman/branch/develop/graph/badge.svg)](https://codecov.io/gh/postmanlabs/newman)\n\nNewman is a command-line collection runner for Postman. It allows you to effortlessly run and test a Postman collection directly from the command-line. It is built with extensibility in mind so that you can easily integrate it with your continuous integration servers and build systems.\n\n\n## Table of contents\n\n1. [Getting Started](#getting-started)\n2. [Usage](#usage)\n    1. [Using Newman CLI](#using-newman-cli)\n    2. [Using Newman as a Library](#using-newman-as-a-library)\n    3. [Using Reporters with Newman](#using-reporters-with-newman)\n3. [Command Line Options](#command-line-options)\n    1. [newman-options](#newman-options)\n    2. [newman-run](#newman-run-collection-file-source-options)\n    3. [SSL](#ssl)\n    4. [Configuring Proxy](#configuring-proxy)\n4. [API Reference](#api-reference)\n    1. [newman run](#newmanrunoptions-object--callback-function--run-eventemitter)\n    2. [Run summary object](#newmanruncallbackerror-object--summary-object)\n    3. [Events emitted during a collection run](#newmanrunevents)\n5. [Reporters](#reporters)\n    1. [Configuring Reporters](#configuring-reporters)\n    2. [CLI Reporter](#cli-reporter)\n    3. [JSON Reporter](#json-reporter)\n    4. [JUnit Reporter](#junitxml-reporter)\n    5. [HTML Reporter](#html-reporter)\n6. [External Reporters](#external-reporters)\n    1. [Using External Reporters](#using-external-reporters)\n    2. [Creating Your Own Reporter](#creating-your-own-reporter)\n7. [File Uploads](#file-uploads)\n8. [Using Newman with the Postman API](#using-newman-with-the-postman-api)\n9. [Using Newman in Docker](#using-newman-in-docker)\n10. [Using Socks Proxy](#using-socks-proxy)\n11. [Migration Guide](#migration-guide)\n12. [Compatibility](#compatibility)\n13. [Contributing](#contributing)\n14. [Community Support](#community-support)\n15. [License](#license)\n\n\n## Getting started\n\nTo run Newman, ensure that you have Node.js >= v16. [Install Node.js via package manager](https://nodejs.org/en/download/package-manager/).\n\n### Installation\nThe easiest way to install Newman is using NPM. If you have Node.js installed, it is most likely that you have NPM installed as well.\n\n```console\n$ npm install -g newman\n```\nThis installs Newman globally on your system allowing you to run it from anywhere. If you want to install it locally, Just remove the `-g` flag.\n\n#### Using Homebrew\nInstall Newman globally on your system using Homebrew.\n```console\n$ brew install newman\n```\n\n[back to top](#table-of-contents)\n\n## Usage\n\n### Using Newman CLI\nThe `newman run` command allows you to specify a collection to be run. You can easily export your Postman\nCollection as a json file from the [Postman App](https://www.postman.com/downloads/) and run it using Newman.\n\n```console\n$ newman run examples/sample-collection.json\n```\n\nIf your collection file is available as an URL (such as from our [Cloud API service](https://api.getpostman.com)),\nNewman can fetch your file and run it as well.\n\n```console\n$ newman run https://www.getpostman.com/collections/631643-f695cab7-6878-eb55-7943-ad88e1ccfd65-JsLv\n```\n\nFor the complete list of options, refer the [Command Line Options](#command-line-options) section below.\n\n![terminal-demo](https://raw.githubusercontent.com/postmanlabs/postmanlabs.github.io/develop/global-artefacts/newman-terminal.gif)\n\n### Using Newman as a Library\nNewman can be easily used within your JavaScript projects as a Node.js module. The entire set of Newman CLI functionality is available for programmatic use as well. The following example runs a collection by reading a JSON collection file stored on disk.\n\n```javascript\nconst newman = require('newman'); // require newman in your project\n\n// call newman.run to pass `options` object and wait for callback\nnewman.run({\n    collection: require('./sample-collection.json'),\n    reporters: 'cli'\n}, function (err) {\n\tif (err) { throw err; }\n    console.log('collection run complete!');\n});\n```\n\nFor the complete list of options, refer the [API Reference](#api-reference) section below.\n\n### Using Reporters with Newman\nReporters provide information about the current collection run in a format that is easy to both: disseminate and assimilate.\nReporters can be configured using the `-r` or `--reporters` options. Inbuilt reporters in newman are: `cli`, `json`, `junit`, `progress` and `emojitrain`.\n\nCLI reporter is enabled by default when Newman is used as a CLI, you do not need to specifically provide the same as part of reporters option. However, enabling one or more of the other reporters will result in no CLI output. Explicitly enable the CLI option in such a scenario. Check the example given below using the CLI and JSON reporters:\n\n```console\n$ newman run examples/sample-collection.json -r cli,json\n```\n\nFor more details on [Reporters](#reporters) and writing your own [External Reporters](#external-reporters) refer to their corresponding sections below.\n\n[back to top](#table-of-contents)\n\n## Command Line Options\n\n### `newman [options]`\n\n- `-h`, `--help`<br />\n  Show command line help, including a list of options, and sample use cases.\n\n- `-v`, `--version`<br />\n  Displays the current Newman version, taken from [package.json](https://github.com/postmanlabs/newman/blob/main/package.json)\n\n\n### `newman run <collection-file-source> [options]`\n\n- `-e <source>`, `--environment <source>`<br />\n  Specify an environment file path or URL. Environments provide a set of variables that one can use within collections.\n  [Read More](https://learning.postman.com/docs/postman/variables-and-environments/managing-environments/)\n\n- `-g <source>`, `--globals <source>`<br />\n  Specify the file path or URL for global variables. Global variables are similar to environment variables but have a lower\n  precedence and can be overridden by environment variables having the same name.\n\n- `-d <source>`, `--iteration-data <source>`<br />\n  Specify a data source file (JSON or CSV) to be used for iteration as a path to a file or as a URL.\n  [Read More](https://learning.postman.com/docs/postman/collection-runs/working-with-data-files/)\n\n- `-n <number>`, `--iteration-count <number>`<br />\n  Specifies the number of times the collection has to be run when used in conjunction with iteration data file.\n\n- `--folder <name>`<br />\n  Run requests within a particular folder/folders or specific requests in a collection. Multiple folders or requests can be specified by using\n  --folder multiple times, like so: --folder f1 --folder f2 --folder r1 --folder r2.\n\n\n- `--working-dir <path>`<br />\n  Set the path of the working directory to use while reading files with relative paths. Default to current directory.\n\n- `--no-insecure-file-read`<br />\n  Prevents reading of files situated outside of the working directory.\n\n- `--export-environment <path>`<br />\n  The path to the file where Newman will output the final environment variables file before completing a run.\n\n- `--export-globals <path>`<br />\n  The path to the file where Newman will output the final global variables file before completing a run.\n\n- `--export-collection <path>`<br />\n  The path to the file where Newman will output the final collection file before completing a run.\n\n- `--timeout <ms>`<br />\n  Specify the time (in milliseconds) to wait for the entire collection run to complete execution.\n\n- `--timeout-request <ms>`<br />\n  Specify the time (in milliseconds) to wait for requests to return a response.\n\n- `--timeout-script <ms>`<br />\n  Specify the time (in milliseconds) to wait for scripts to complete execution.\n\n- `-k`, `--insecure`<br />\n  Disables SSL verification checks and allows self-signed SSL certificates.\n\n- `--ignore-redirects`<br />\n  Prevents newman from automatically following 3XX redirect responses.\n\n- `--delay-request`<br />\n  Specify the extent of delay between requests (milliseconds).\n\n- `--cookie-jar <path>`<br />\n  Specify the file path for a JSON Cookie Jar. Uses [`tough-cookie`](https://github.com/salesforce/tough-cookie) to deserialize the file.\n\n- `--export-cookie-jar <path>`<br />\n  The path to the file where Newman will output the final cookie jar file before completing a run. Uses `tough-cookie`'s serialize method.\n\n- `--bail [optional modifiers]`<br />\n  Specify whether or not to stop a collection run on encountering the first test script error.<br />\n  Can optionally accept modifiers, currently include `folder` and `failure`.<br />\n  `folder` allows you to skip the entire collection run in case an invalid folder\n  was specified using the `--folder` option or an error was encountered in general.<br />\n  On the failure of a test, `failure` would gracefully stop a collection run after completing the current test script.\n\n- `-x`, `--suppress-exit-code`<br />\n  Specify whether or not to override the default exit code for the current run.\n\n- `--color <value>`<br />\n  Enable or Disable colored CLI output. The color value can be any of the three: `on`, `off` or `auto`*(default)*.<br/>\n  With `auto`, Newman attempts to automatically turn color on or off based on the color support in the terminal.\n  This behaviour can be modified by using the `on` or `off` value accordingly.\n\n- `--disable-unicode`<br />\n  Specify whether or not to force the unicode disable option. When supplied, all symbols in the output will be replaced\n  by their plain text equivalents.\n\n- `--global-var \"<global-variable-name>=<global-variable-value>\"`<br />\n  Allows the specification of global variables via the command line, in a key=value format. Multiple CLI global variables\n  can be added by using `--global-var` multiple times, like so: `--global-var \"foo=bar\" --global-var \"alpha=beta\"`.\n\n- `--env-var \"<environment-variable-name>=<environment-variable-value>\"`<br />\n  Allows the specification of environment variables via the command line, in a key=value format. Multiple CLI environment variables\n  can be added by using `--env-var` multiple times, like so: `--env-var \"foo=bar\" --env-var \"alpha=beta\"`.\n\n- `--verbose`<br />\n  Show detailed information of collection run and each request sent.\n\n### SSL\n\n#### Client Certificates\n\nClient certificates are an alternative to traditional authentication mechanisms. These allow their users to make authenticated requests to a server, using a public certificate, and an optional private key that verifies certificate ownership. In some cases, the private key may also be protected by a secret passphrase, providing an additional layer of authentication security.\n\nNewman supports SSL client certificates, via the following CLI options:\n\n#### Using a single SSL client certificate\n- `--ssl-client-cert`<br/>\nThe path to the public client certificate file.\n\n- `--ssl-client-key`<br/>\nThe path to the private client key (optional).\n\n- `--ssl-client-passphrase`<br/>\nThe secret passphrase used to protect the private client key (optional).\n\n\n#### Using SSL client certificates configuration file (supports multiple certificates per run)\n\n- `--ssl-client-cert-list`<br/>\nThe path to the SSL client certificate list configuration file (JSON format). See [examples/ssl-client-cert-list.json](https://github.com/postmanlabs/newman/blob/develop/examples/ssl-client-cert-list.json).\n\nThis option allows setting different SSL client certificate according to URL or hostname.\nThis option takes precedence over `--ssl-client-cert`, `--ssl-client-key` and `--ssl-client-passphrase` options. If there is no match for the URL in the list, these options are used as fallback.\n\n\n#### Trusted CA\n\nWhen it is not wanted to use the `--insecure` option, additionally trusted CA certificates can be provided like this:\n\n- `--ssl-extra-ca-certs`<br/>\nThe path to the file, that holds one or more trusted CA certificates in PEM format\n\n### Configuring Proxy\n\nNewman can also be configured to work with proxy settings via the following environment variables:\n\n * `HTTP_PROXY` / `http_proxy`\n * `HTTPS_PROXY` / `https_proxy`\n * `NO_PROXY` / `no_proxy`\n\nFor more details on using these variables, [refer here](https://github.com/postmanlabs/postman-request/blob/master/README.md#controlling-proxy-behaviour-using-environment-variables).\n\n[back to top](#table-of-contents)\n\n## API Reference\n\n### newman.run(options: _object_ , callback: _function_) => run: EventEmitter\nThe `run` function executes a collection and returns the run result to a callback function provided as parameter. The\nreturn of the `newman.run` function is a run instance, which emits run events that can be listened to.\n\n| Parameter | Description   |\n|-----------|---------------|\n| options                   | This is a required argument and it contains all information pertaining to running a collection.<br /><br />_Required_<br />Type: `object` |\n| options.collection        | The collection is a required property of the `options` argument. It accepts an object representation of a Postman Collection which should resemble the schema mentioned at [https://schema.getpostman.com/](https://schema.getpostman.com/). The value of this property could also be an instance of Collection Object from the [Postman Collection SDK](https://github.com/postmanlabs/postman-collection).<br /><br />As `string`, one can provide a URL where the Collection JSON can be found (e.g. [Postman Cloud API](https://api.getpostman.com/) service) or path to a local JSON file.<br /><br />_Required_<br />Type: `object\\|string` [PostmanCollection](https://github.com/postmanlabs/postman-collection/wiki#Collection) |\n| options.environment       | One can optionally pass an environment file path or URL as `string` to this property and that will be used to read Postman Environment Variables from. This property also accepts environment variables as an `object`. Environment files exported from Postman App can be directly used here.<br /><br />_Optional_<br />Type: `object\\|string` |\n| options.envVar            | One can optionally pass environment variables as an array of key-value string object pairs. It will be used to read Postman Environment Variables as well as overwrite environment variables from `options.environments`. <br /><br />_Optional_<br />Type: `array\\|object` |\n| options.globals           | Postman Global Variables can be optionally passed on to a collection run in form of path to a file or URL. It also accepts variables as an `object`.<br /><br />_Optional_<br />Type: `object\\|string` |\n| options.globalVar         | One can optionally pass global environment variables as an array of key-value string object pairs. It will be used to read Postman Global Environment Variables as well as overwrite global environment variables from `options.globals`. <br /><br />_Optional_<br />Type: `array\\|object` |\n| options.iterationCount    | Specify the number of iterations to run on the collection. This is usually accompanied by providing a data file reference as `options.iterationData`.<br /><br />_Optional_<br />Type: `number`, Default value: `1` |\n| options.iterationData     | Path to the JSON or CSV file or URL to be used as data source when running multiple iterations on a collection.<br /><br />_Optional_<br />Type: `string` |\n| options.folder            | The name or ID of the folder/folders (ItemGroup) in the collection which would be run instead of the entire collection.<br /><br />_Optional_<br />Type: `string\\|array` |\n| options.workingDir        | The path of the directory to be used as working directory.<br /><br />_Optional_<br />Type: `string`, Default value: `Current Directory` |\n| options.insecureFileRead  | Allow reading files outside of working directory.<br /><br />_Optional_<br />Type: `boolean`, Default value: `true` |\n| options.timeout           | Specify the time (in milliseconds) to wait for the entire collection run to complete execution.<br /><br />_Optional_<br />Type: `number`, Default value: `Infinity` |\n| options.timeoutRequest    | Specify the time (in milliseconds) to wait for requests to return a response.<br /><br />_Optional_<br />Type: `number`, Default value: `Infinity` |\n| options.timeoutScript     | Specify the time (in milliseconds) to wait for scripts to return a response.<br /><br />_Optional_<br />Type: `number`, Default value: `Infinity` |\n| options.delayRequest      | Specify the time (in milliseconds) to wait for between subsequent requests.<br /><br />_Optional_<br />Type: `number`, Default value: `0` |\n| options.ignoreRedirects   | This specifies whether newman would automatically follow 3xx responses from servers.<br /><br />_Optional_<br />Type: `boolean`, Default value: `false` |\n| options.insecure          | Disables SSL verification checks and allows self-signed SSL certificates.<br /><br />_Optional_<br />Type: `boolean`, Default value: `false` |\n| options.bail              | A switch to specify whether or not to gracefully stop a collection run (after completing the current test script) on encountering the first error. Takes additional modifiers as arguments to specify whether to end the run with an error for invalid name or path.<br /><br/>Available modifiers: `folder` and `failure`.<br />eg. `bail : ['folder']`<br /><br />_Optional_<br />Type: `boolean\\|object`, Default value: `false` |\n| options.suppressExitCode  | If present, allows overriding the default exit code from the current collection run, useful for bypassing collection result failures. Takes no arguments.<br /><br />_Optional_<br />Type: `boolean`, Default value: `false` |\n| options.reporters         | Specify one reporter name as `string` or provide more than one reporter name as an `array`.<br /><br />Available reporters: `cli`, `json`, `junit`, `progress` and `emojitrain`.<br /><br />_Optional_<br />Type: `string\\|array` |\n| options.reporter          | Specify options for the reporter(s) declared in `options.reporters`. <br /> e.g. `reporter : { junit : { export : './xmlResults.xml' } }` <br /> e.g. `reporter : { html : { export : './htmlResults.html', template: './customTemplate.hbs' } }` <br /><br />_Optional_<br />Type: `object` |\n| options.color             | Enable or Disable colored CLI output.<br/><br/>Available options: `on`, `off` and `auto`<br /><br />_Optional_<br />Type: `string`, Default value: `auto` |\n| options.sslClientCert     | The path to the public client certificate file.<br /><br />_Optional_<br />Type: `string` |\n| options.sslClientKey      | The path to the private client key file.<br /><br />_Optional_<br />Type: `string` |\n| options.sslClientPassphrase | The secret client key passphrase.<br /><br />_Optional_<br />Type: `string` |\n| options.sslClientCertList | The path to the client certificate configuration list file. This option takes precedence over `sslClientCert`, `sslClientKey` and `sslClientPassphrase`. When there is no match in this configuration list, `sslClientCert` is used as fallback.<br /><br />_Optional_<br />Type: `string\\|array` |\n| options.sslExtraCaCerts   | The path to the file, that holds one or more trusted CA certificates in PEM format.<br /><br />_Optional_<br />Type: `string` |\n| options.requestAgents     | Specify the custom requesting agents to be used when performing HTTP and HTTPS requests respectively. Example: [Using Socks Proxy](#using-socks-proxy)<br /><br />_Optional_<br />Type: `object` |\n| options.cookieJar     | One can optionally pass a CookieJar file path as `string` to this property and that will be deserialized using [`tough-cookie`](https://github.com/salesforce/tough-cookie). This property also accepts a `tough-cookie` CookieJar instance.<br /><br />_Optional_<br />Type: `object\\|string` |\n| options.newmanVersion     | The Newman version used for the collection run.<br /><br />_This will be set by Newman_ |\n| callback                  | Upon completion of the run, this callback is executed with the `error`, `summary` argument.<br /><br />_Required_<br />Type: `function` |\n\n### newman.run~callback(error: _object_ , summary: _object_)\n\nThe `callback` parameter of the `newman.run` function receives two arguments: (1) `error` and (2) `summary`\n\n| Argument  | Description   |\n|-----------|---------------|\n| error                     | In case newman faces an error during the run, the error is passed on to this argument of callback. By default, only fatal errors, such as the ones caused by any fault inside Newman is passed on to this argument. However, setting `abortOnError:true` or `abortOnFailure:true` as part of run options will cause newman to treat collection script syntax errors and test failures as fatal errors and be passed down here while stopping the run abruptly at that point.<br /><br />Type: `object` |\n| summary                   | The run summary will contain information pertaining to the run.<br /><br />Type: `object` |\n| summary.error             | An error object which if exists, contains an error message describing the message <br /><br />Type: `object` |\n| summary.collection        | This object contains information about the collection being run, it's requests, and their associated pre-request scripts and tests.<br /><br />Type: `object` |\n| summary.environment       | An object with environment variables used for the current run, and the usage status for each of those variables.<br /><br />Type: `object` |\n| summary.globals           | This object holds details about the globals used within the collection run namespace.<br /><br />Type: `object` |\n| summary.run               | A cumulative run summary object that provides information on .<br /><br />Type: `object` |\n| summary.run.stats         | An object which provides details about the total, failed, and pending counts for pre request scripts, tests, assertions, requests, and more.<br /><br />Type: `object` |\n| summary.run.failures      | An array of failure objects, with each element holding details, including the assertion that failed, and the request.<br /><br />Type: `array.<object>` |\n| summary.run.executions    | This object contains information about each request, along with it's associated activities within the scope of the current collection run.<br /><br />Type: `array.<object>` |\n\n### newman.run~events\n\nNewman triggers a whole bunch of events during the run.\n\n```javascript\nnewman.run({\n    collection: require('./sample-collection.json'),\n    iterationData: [{ \"var\": \"data\", \"var_beta\": \"other_val\" }],\n    globals: {\n        \"id\": \"5bfde907-2a1e-8c5a-2246-4aff74b74236\",\n        \"name\": \"test-env\",\n        \"values\": [\n            {\n                \"key\": \"alpha\",\n                \"value\": \"beta\",\n                \"type\": \"text\",\n                \"enabled\": true\n            }\n        ],\n        \"timestamp\": 1404119927461,\n        \"_postman_variable_scope\": \"globals\",\n        \"_postman_exported_at\": \"2016-10-17T14:31:26.200Z\",\n        \"_postman_exported_using\": \"Postman/4.8.0\"\n    },\n    globalVar: [\n        { \"key\":\"glboalSecret\", \"value\":\"globalSecretValue\" },\n        { \"key\":\"globalAnotherSecret\", \"value\":`${process.env.GLOBAL_ANOTHER_SECRET}`}\n    ],\n    environment: {\n        \"id\": \"4454509f-00c3-fd32-d56c-ac1537f31415\",\n        \"name\": \"test-env\",\n        \"values\": [\n            {\n                \"key\": \"foo\",\n                \"value\": \"bar\",\n                \"type\": \"text\",\n                \"enabled\": true\n            }\n        ],\n        \"timestamp\": 1404119927461,\n        \"_postman_variable_scope\": \"environment\",\n        \"_postman_exported_at\": \"2016-10-17T14:26:34.940Z\",\n        \"_postman_exported_using\": \"Postman/4.8.0\"\n    },\n    envVar: [\n        { \"key\":\"secret\", \"value\":\"secretValue\" },\n        { \"key\":\"anotherSecret\", \"value\":`${process.env.ANOTHER_SECRET}`}\n    ],\n}).on('start', function (err, args) { // on start of run, log to console\n    console.log('running a collection...');\n}).on('done', function (err, summary) {\n    if (err || summary.error) {\n        console.error('collection run encountered an error.');\n    }\n    else {\n        console.log('collection run completed.');\n    }\n});\n```\n\nAll events receive two arguments (1) `error` and (2) `args`. The list below describes the properties of the second\nargument object. [Learn more](https://github.com/postmanlabs/newman/wiki/Newman-Run-Events)\n\n| Event     | Description   |\n|-----------|---------------|\n| start                     | The start of a collection run |\n| beforeIteration           | Before an iteration commences |\n| beforeItem                | Before an item execution begins (the set of prerequest->request->test) |\n| beforePrerequest          | Before `prerequest` script is execution starts |\n| prerequest                | After `prerequest` script execution completes |\n| beforeRequest             | Before an HTTP request is sent |\n| request                   | After response of the request is received |\n| beforeTest                | Before `test` script is execution starts |\n| test                      | After `test` script execution completes |\n| beforeScript              | Before any script (of type `test` or `prerequest`) is executed |\n| script                    | After any script (of type `test` or `prerequest`) is executed |\n| item                      | When an item (the whole set of prerequest->request->test) completes |\n| iteration                 | After an iteration completes |\n| assertion                 | This event is triggered for every test assertion done within `test` scripts |\n| console                   | Every time a `console` function is called from within any script, this event is propagated |\n| exception                 | When any asynchronous error happen in `scripts` this event is triggered |\n| beforeDone                | An event that is triggered prior to the completion of the run |\n| done                      | This event is emitted when a collection run has completed, with or without errors |\n\n[back to top](#table-of-contents)\n\n## Reporters\n\n### Configuring Reporters\n\n- `-r <reporter-name>`, `--reporters <reporter-name>`<br />\n  Specify one reporter name as `string` or provide more than one reporter name as a comma separated list of reporter names. Available reporters are: `cli`, `json`, `junit`, `progress` and `emojitrain`.<br/><br/>\n  Spaces should **not** be used between reporter names / commas whilst specifying a comma separated list of reporters. For instance:<br/><br/>\n  :white_check_mark: `-r cli,json,junit`<br/>\n  :x: `-r cli , json,junit`\n\n- `--reporter-{{reporter-name}}-{{reporter-option}}`<br />\n  When multiple reporters are provided, if one needs to specifically override or provide an option to one reporter, this\n  is achieved by prefixing the option with `--reporter-{{reporter-name}}-`.<br /><br />\n  For example, `... --reporters cli,json --reporter-cli-silent` would silence the CLI reporter only.\n\n- `--reporter-{{reporter-options}}`<br />\n  If more than one reporter accepts the same option name, they can be provided using the common reporter option syntax.\n  <br /><br />\n  For example, `... --reporters cli,json --reporter-silent` passes the `silent: true` option to both JSON and CLI\n  reporter.\n\n**Note:** Sample collection reports have been provided in [examples/reports](https://github.com/postmanlabs/newman/blob/develop/examples/reports).\n\n### CLI Reporter\nThe built-in CLI reporter supports the following options, use them with appropriate argument switch prefix. For example, the\noption `no-summary` can be passed as `--reporter-no-summary` or `--reporter-cli-no-summary`.\n\nCLI reporter is enabled by default when Newman is used as a CLI, you do not need to specifically provide the same as part of `--reporters` option.\nHowever, enabling one or more of the other reporters will result in no CLI output. Explicitly enable the CLI option in\nsuch a scenario.\n\n| CLI Option  | Description       |\n|-------------|-------------------|\n| `--reporter-cli-silent`         | The CLI reporter is internally disabled and you see no output to terminal. |\n\n| `--reporter-cli-show-timestamps` | This prints the local time for each request made. |\n| `--reporter-cli-no-summary`     | The statistical summary table is not shown. |\n| `--reporter-cli-no-failures`    | This prevents the run failures from being separately printed. |\n| `--reporter-cli-no-assertions`  | This turns off the output for request-wise assertions as they happen. |\n| `--reporter-cli-no-success-assertions`  | This turns off the output for successful assertions as they happen. |\n| `--reporter-cli-no-console`     | This turns off the output of `console.log` (and other console calls) from collection's scripts. |\n| `--reporter-cli-no-banner`      | This turns off the `newman` banner shown at the beginning of each collection run. |\n\n### JSON Reporter\nThe built-in JSON reporter is useful in producing a comprehensive output of the run summary. It takes the path to the\nfile where to write the report. The content of this file is exactly the same as the `summary` parameter sent to the callback\nwhen Newman is used as a library.\n\nTo enable JSON reporter, provide `--reporters json` as a CLI option.\n\n| CLI Option  | Description       |\n|-------------|-------------------|\n| `--reporter-json-export <path>` | Specify a path where the output JSON file will be written to disk. If not specified, the file will be written to `newman/` in the current working directory. If the specified path does not exist, it will be created. However, if the specified path is a pre-existing directory, the report will be generated in that directory. |\n\n### JUNIT/XML Reporter\nThe built-in JUnit reporter can output a summary of the collection run to a JUnit compatible XML file. To enable the JUNIT reporter, provide\n`--reporters junit` as a CLI option.\n\n| CLI Option  | Description       |\n|-------------|-------------------|\n| `--reporter-junit-export <path>` | Specify a path where the output XML file will be written to disk. If not specified, the file will be written to `newman/` in the current working directory. If the specified path does not exist, it will be created. However, if the specified path is a pre-existing directory, the report will be generated in that directory. |\n\n### HTML Reporter\nAn external reporter, maintained by Postman, which can be installed via `npm install -g newman-reporter-html`. This reporter was part of the Newman project but was separated out into its own project in V4.\n\nThe complete installation and usage guide is available at [newman-reporter-html](https://github.com/postmanlabs/newman-reporter-html#readme). Once the HTML reporter is installed you can provide `--reporters html` as a CLI option.\n\n[back to top](#table-of-contents)\n\n## External Reporters\n\n### Using External Reporters\nNewman also supports external reporters, provided that the reporter works with Newman's event sequence. Working examples of\nhow Newman reporters work can be found in [lib/reporters](https://github.com/postmanlabs/newman/tree/develop/lib/reporters).\n\nFor instance, to use the [Newman HTML Reporter](https://github.com/postmanlabs/newman-reporter-html):\n\n- Install the reporter package. Note that the name of the package is of the form `newman-reporter-<name>`. The installation should be global if Newman is installed globally, local otherwise. (Remove `-g` flag from the command below for a local installation.)\n```console\n$ npm install -g newman-reporter-html\n```\n\n- Use the installed reporter, either via the CLI, or programmatic usage. Here, the `newman-reporter` prefix is **not** required while specifying the reporter name in the options.<br/>\n```console\n$ newman run /path/to/collection.json -r cli,html\n```\n```javascript\nconst newman = require('newman');\n\nnewman.run({\n    collection: '/path/to/collection.json',\n    reporters: ['cli', 'html']\n}, process.exit);\n```\n\n#### Community Maintained Reporters\n\nSeveral members of the Postman community have created custom reporters offering different option to output the data coming from Newman. Listed below is a selection of these but more can be found [here](https://www.npmjs.com/search?q=newman-reporter) on NPM.\n\nOnce the custom reporter NPM package has been installed either globally or locally, this can be then used with Newman in the following ways:\n\n```console\n$ newman run /path/to/collection.json -r htmlextra,csv\n```\n\n```javascript\nconst newman = require('newman');\n\nnewman.run({\n    collection: '/path/to/collection.json',\n    reporters: ['htmlextra', 'csv']\n}, process.exit);\n```\n\n- [allure](https://github.com/allure-framework/allure-js/tree/master/packages/newman-reporter-allure) -\nThis reporter allow to create fully-featured allure reports that can allow you to have easy to understand HTML reports with features like historical data, link tests to the JIRA and all other benefits of using [allure framework](https://allurereport.org/).\n- [htmlextra](https://github.com/DannyDainton/newman-reporter-htmlextra) -\nThis is an updated version of the standard HTML reporter containing a more in-depth data output and a few helpful extras\n- [csv](https://github.com/matt-ball/newman-reporter-csv) -\nThis reporter creates a `csv` file containing the high level summary of the Collection run\n- [json-summary](https://github.com/spenceclark/newman-reporter-json-summary) -\nA Newman JSON Reporter that strips the results down to a minimum\n- [teamcity](https://github.com/leafle/newman-reporter-teamcity) -\nA reporter built to be used with the [Team City](https://www.jetbrains.com/teamcity/) CI server\n- [testrail](https://github.com/billylam/newman-reporter-testrail) -\nA reporter built for [Test Rail](https://www.gurock.com/testrail/), the test case management tool\n- [statsd](https://github.com/gsorry/newman-reporter-statsd) -\nThis reporter can be used to send the Collection run data to `statsd` and used on time series analytic tools like [Grafana](https://grafana.com/)\n- [confluence](https://github.com/OmbraDiFenice/newman-reporter-confluence) -\nConfluence reporter for Newman that uploads a Newman report on a Confluence page\n- [influxdb](https://github.com/vs4vijay/newman-reporter-influxdb) -\nThis reporter sends the test results information to InfluxDB which can be used from [Grafana](https://grafana.com/) to build dashboards\n\n### Creating Your Own Reporter\nA custom reporter is a Node module with a name of the form `newman-reporter-<name>`. To create a custom reporter:\n1. Navigate to a directory of your choice, and create a blank npm package with `npm init`.\n2. Add an `index.js` file, that exports a function of the following form:\n```javascript\nfunction CustomNewmanReporter (emitter, reporterOptions, collectionRunOptions) {\n  // emitter is an event emitter that triggers the following events: https://github.com/postmanlabs/newman#newmanrunevents\n  // reporterOptions is an object of the reporter specific options. See usage examples below for more details.\n  // collectionRunOptions is an object of all the collection run options: https://github.com/postmanlabs/newman#newmanrunoptions-object--callback-function--run-eventemitter\n}\nmodule.exports = CustomNewmanReporter\n```\n3. To use your reporter locally, use the `npm pack` command to create a `.tgz` file. Once created, this can be installed using the `npm i -g newman-reporter-<name>.<version>.tgz` command.\n\nOnce you're happy with your reporter, it can be published to `npm` using `npm publish`. This will then be made available for other people to download.\n\nScoped reporter package names like `@myorg/newman-reporter-<name>` are also supported. Working reporter examples can be found in [lib/reporters](lib/reporters).\n\n[back to top](#table-of-contents)\n\n## File uploads\n\nNewman also supports file uploads for request form data. The files must be present in the\ncurrent working directory. Your collection must also contain the filename in\nthe \"src\" attribute of the request.\n\nIn this collection, `sample-file.txt` should be present in the current working directory.\n```json\n{\n    \"info\": {\n        \"name\": \"file-upload\"\n    },\n    \"item\": [\n        {\n            \"request\": {\n                \"url\": \"https://postman-echo.com/post\",\n                \"method\": \"POST\",\n                \"body\": {\n                    \"mode\": \"formdata\",\n                    \"formdata\": [\n                        {\n                            \"key\": \"file\",\n                            \"type\": \"file\",\n                            \"enabled\": true,\n                            \"src\": \"sample-file.txt\"\n                        }\n                    ]\n                }\n            }\n        }\n    ]\n}\n```\n\n```console\n$ ls\nfile-upload.postman_collection.json  sample-file.txt\n\n$ newman run file-upload.postman_collection.json\n```\n\n[back to top](#table-of-contents)\n\n## Using Newman with the Postman API\n\n1 [Generate an API key](https://learning.postman.com/docs/developer/intro-api/#generating-a-postman-api-key)<br/>\n2 Fetch a list of your collections from: `https://api.getpostman.com/collections?apikey=$apiKey`<br/>\n3 Get the collection link via it's `uid`: `https://api.getpostman.com/collections/$uid?apikey=$apiKey`<br/>\n4 Obtain the environment URI from: `https://api.getpostman.com/environments?apikey=$apiKey`<br/>\n5 Using the collection and environment URIs acquired in steps 3 and 4, run the collection as follows:\n```console\n$ newman run \"https://api.getpostman.com/collections/$uid?apikey=$apiKey\" \\\n    --environment \"https://api.getpostman.com/environments/$uid?apikey=$apiKey\"\n```\n\n[back to top](#table-of-contents)\n\n## Using Newman in Docker\nTo use Newman in Docker check our [docker documentation](https://learning.postman.com/docs/postman/collection-runs/newman-with-docker/).\n\n## Using Socks Proxy\n\nWhen using Newman as a library, you can pass a custom HTTP(S) agent which will be used for making the requests. Here's an example of how to setup socks proxy using a custom agent.\n\n```js\nconst newman = require('newman');\nconst SocksProxyAgent = require('socks-proxy-agent');\nconst requestAgent = new SocksProxyAgent({ host: 'localhost', port: '1080' });\n\nnewman.run({\n    collection: require('./sample-collection.json'),\n    requestAgents: {\n        http: requestAgent, // agent used for HTTP requests\n        https: requestAgent, // agent used for HTTPS requests\n    }\n}, function (err) {\n    if (err) { throw err; }\n    console.log('collection run complete!');\n});\n```\n\n[back to top](#table-of-contents)\n\n## Migration Guide\n\n- [Newman v5 to v6 Migration Guide](MIGRATION.md)\n- [Newman v5.x Documentation](https://github.com/postmanlabs/newman/blob/release/5.x/README.md)\n\n\n## Compatibility\n\n### NodeJS\n\n|      Newman       |    Node    |\n|:-----------------:|:----------:|\n|       v3.x        |  >= v4.x   |\n|       v4.x        |  >= v6.x   |\n|       v5.x        |  >= v10.x  |\n|       v6.x        |  >= v16.x  |\n\nThe current Node version compatibility can also be seen from the `engines.node` property in [package.json](https://github.com/postmanlabs/newman/blob/develop/package.json)\n\n### File Encoding\n\nNewman attempts to detect file encoding for files that are provided as\ncommand line input. However, it mostly relies on NodeJS and the underlying\noperating system to do the heavy lifting. Currently, `ASCII`, `UTF-8`, `UTF-16LE`\nand `ISO-8859-1` are the only ones that are detection assisted.\n\n[back to top](#table-of-contents)\n\n## Contributing\nPlease take a moment to read our [contributing guide](.github/CONTRIBUTING.md) to learn about our development process.\nOpen an [issue](https://github.com/postmanlabs/newman/issues) first to discuss potential changes/additions.\n\n## Community Support\n\n<img src=\"https://avatars1.githubusercontent.com/u/3220138?v=3&s=120\" align=\"right\" />\nIf you are interested in talking to the Postman team and fellow Newman users, you can find us on our <a href=\"https://community.postman.com\">Postman Community Forum</a>. Feel free to drop by and say hello. You'll find us posting about upcoming features and beta releases, answering technical support questions, and contemplating world peace.\n\nSign in using your Postman account to participate in the discussions and don't forget to take advantage of the <a href=\"https://community.postman.com/search?q=newman\">search bar</a> - the answer to your question might already be waiting for you! Don’t want to log in? Then lurk on the sidelines and absorb all the knowledge.\n\n\n## License\nThis software is licensed under Apache-2.0. Copyright Postdot Technologies, Inc. See the [LICENSE.md](LICENSE.md) file for more information.\n\n[![Analytics](https://ga-beacon.appspot.com/UA-43979731-9/newman/readme)](https://postman.com)\n"
  },
  {
    "path": "SECURITY.md",
    "content": "# Security Policy\n\n## Reporting a Vulnerability\n\nIf you've found a vulnerability in our service or website, or want additional information regarding how we manage security, please send an email to security@postman.com. We will review it and respond to you within 24 hours. Please use our [PGP public key](https://assets.getpostman.com/getpostman/documents/publickey.txt) to encrypt your communications with us.\n\nIf you are a security researcher, please go through the following points for reporting security issues.\n\n- Mail to security@postman.com and express interest along with a short summary of the nature of issue you want to report.\n- We will triage and add your email address to our internal security tracker.\n- Subsequently you can report your security issues directly using the tracker.\n\n\n> Read our [security reporting guidelines and policy](https://www.postman.com/vulnerability-reporting) for more details.\n"
  },
  {
    "path": "bin/newman.js",
    "content": "#!/usr/bin/env node\n\nrequire('../lib/node-version-check'); // @note that this should not respect CLI --silent\n\nconst _ = require('lodash'),\n    waterfall = require('async/waterfall'),\n    { Command } = require('commander'),\n    program = new Command(),\n    version = require('../package.json').version,\n    newman = require('../'),\n    util = require('./util');\n\nprogram\n    .name('newman')\n    .addHelpCommand(false)\n    .version(version, '-v, --version');\n\n// The `run` command allows you to specify a collection to be run with the provided options.\nprogram\n    .command('run <collection>')\n    .description('Initiate a Postman Collection run from a given URL or path')\n    .usage('<collection> [options]')\n    .option('-e, --environment <path>', 'Specify a URL or path to a Postman Environment')\n    .option('-g, --globals <path>', 'Specify a URL or path to a file containing Postman Globals')\n    .option('-r, --reporters [reporters]', 'Specify the reporters to use for this run', util.cast.csvParse, ['cli'])\n    .option('-n, --iteration-count <n>', 'Define the number of iterations to run', util.cast.integer)\n    .option('-d, --iteration-data <path>', 'Specify a data file to use for iterations (either JSON or CSV)')\n    .option('--folder <path>',\n        'Specify the folder to run from a collection. Can be specified multiple times to run multiple folders',\n        util.cast.memoize, [])\n    .option('--global-var <value>',\n        'Allows the specification of global variables via the command line, in a key=value format',\n        util.cast.memoizeKeyVal, [])\n    .option('--env-var <value>',\n        'Allows the specification of environment variables via the command line, in a key=value format',\n        util.cast.memoizeKeyVal, [])\n    .option('--export-environment <path>', 'Exports the final environment to a file after completing the run')\n    .option('--export-globals <path>', 'Exports the final globals to a file after completing the run')\n    .option('--export-collection <path>', 'Exports the executed collection to a file after completing the run')\n    .option('--postman-api-key <apiKey>', 'API Key used to load the resources from the Postman API')\n    .option('--bail [modifiers]',\n        'Specify whether or not to gracefully stop a collection run on encountering an error' +\n        ' and whether to end the run with an error based on the optional modifier', util.cast.csvParse)\n    .option('--ignore-redirects', 'Prevents Newman from automatically following 3XX redirect responses')\n    .option('-x , --suppress-exit-code', 'Specify whether or not to override the default exit code for the current run')\n    .option('--silent', 'Prevents Newman from showing output to CLI')\n    .option('--disable-unicode', 'Forces Unicode compliant symbols to be replaced by their plain text equivalents')\n    .option('--color <value>', 'Enable/Disable colored output (auto|on|off)', util.cast.colorOptions, 'auto')\n    .option('--delay-request [n]', 'Specify the extent of delay between requests (milliseconds)', util.cast.integer, 0)\n    .option('--timeout [n]', 'Specify a timeout for collection run (milliseconds)', util.cast.integer, 0)\n    .option('--timeout-request [n]', 'Specify a timeout for requests (milliseconds)', util.cast.integer, 0)\n    .option('--timeout-script [n]', 'Specify a timeout for scripts (milliseconds)', util.cast.integer, 0)\n    .option('--working-dir <path>', 'Specify the path to the working directory')\n    .option('--no-insecure-file-read', 'Prevents reading the files situated outside of the working directory')\n    .option('-k, --insecure', 'Disables SSL validations')\n    .option('--ssl-client-cert-list <path>', 'Specify the path to a client certificates configurations (JSON)')\n    .option('--ssl-client-cert <path>', 'Specify the path to a client certificate (PEM)')\n    .option('--ssl-client-key <path>', 'Specify the path to a client certificate private key')\n    .option('--ssl-client-passphrase <passphrase>', 'Specify the client certificate passphrase (for protected key)')\n    .option('--ssl-extra-ca-certs <path>', 'Specify additionally trusted CA certificates (PEM)')\n    .option('--cookie-jar <path>', 'Specify the path to a custom cookie jar (serialized tough-cookie JSON) ')\n    .option('--export-cookie-jar <path>', 'Exports the cookie jar to a file after completing the run')\n    .option('--verbose', 'Show detailed information of collection run and each request sent')\n    .action((collection, command) => {\n        let options = util.commanderToObject(command),\n\n            // parse custom reporter options\n            reporterOptions = util.parseNestedOptions(program._originalArgs, '--reporter-', options.reporters);\n\n        // Inject additional properties into the options object\n        options.collection = collection;\n        options.reporterOptions = reporterOptions._generic;\n        options.reporter = _.transform(_.omit(reporterOptions, '_generic'), (acc, value, key) => {\n            acc[key] = _.assignIn(value, reporterOptions._generic); // overrides reporter options with _generic\n        }, {});\n\n        newman.run(options, function (err, summary) {\n            const runError = err || summary.run.error || summary.run.failures.length;\n\n            if (err) {\n                console.error(`error: ${err.message || err}\\n`);\n                err.friendly && console.error(`  ${err.friendly}\\n`);\n            }\n            runError && !_.get(options, 'suppressExitCode') && (process.exitCode = 1);\n        });\n    });\n\nprogram.addHelpText('after', `\nTo get available options for a command:\n  newman <command> -h`);\n\n// Warn on invalid command and then exits.\nprogram.on('command:*', (command) => {\n    console.error(`error: invalid command \\`${command}\\`\\n`);\n    program.help();\n});\n\n/**\n * Starts the script execution.\n * callback is required when this is required as a module in tests.\n *\n * @param {String[]} argv - Argument vector.\n * @param {?Function} callback - The callback function invoked on the completion of execution.\n */\nfunction run (argv, callback) {\n    waterfall([\n        (next) => {\n            // cache original argv, required to parse nested options later.\n            program._originalArgs = argv;\n            // omit custom nested options, otherwise commander will throw unknown options error\n            next(null, util.omitNestedOptions(argv, '--reporter-'));\n        },\n        (args, next) => {\n            let error = null;\n\n            try {\n                program.parse(args);\n            }\n            catch (err) {\n                error = err;\n            }\n            next(error);\n        },\n        (next) => {\n            // throw error if no argument is provided.\n            next(program.args.length ? null : new Error('no arguments provided'));\n        }\n    ], (error) => {\n        // invoke callback if this is required as module, used in tests.\n        if (callback) { return callback(error); }\n\n        // in case of an error, log error message and print help message.\n        if (error) {\n            console.error(`error: ${error.message || error}\\n`);\n            program.help();\n        }\n    });\n}\n\n// Run this script if this is a direct stdin.\n!module.parent && run(process.argv);\n\n// Export to allow debugging and testing.\nmodule.exports = run;\n"
  },
  {
    "path": "bin/util.js",
    "content": "const _ = require('lodash');\n\nmodule.exports = {\n\n    cast: {\n        /**\n         * Helper to coerce number like strings into integers.\n         * Perform safety checks, and return the result.\n         *\n         * @param {String} arg - The stringified number argument.\n         * @returns {Number} - The supplied argument, casted to an integer.\n         */\n        integer: (arg) => {\n            const num = Number(arg);\n\n            if (!_.isSafeInteger(num) || num <= 0) {\n                throw new Error('The value must be a positive integer.');\n            }\n\n            return num.valueOf();\n        },\n\n        /**\n         * Helper for collecting argument passed multiple times.\n         *\n         * --folder f1 --folder f2\n         *\n         * @param {String} val - The argument value.\n         * @param {String[]} memo - The array that is populated by argument values.\n         * @returns {String[]} - The array of argument values collected.\n         */\n        memoize: (val, memo) => {\n            memo.push(val);\n\n            return memo;\n        },\n\n        /**\n         * Helper for collecting argument passed multiple times as key=value.\n         *\n         * --global-var \"foo=bar\" --global-var \"alpha=beta\"\n         *\n         * @param {String} val - The argument value, passed as key=value.\n         * @param {Array} memo - The array that is populated by key value pairs.\n         * @returns {Array} - [{key, value}] - The object representation of the current CLI variable.\n         */\n        memoizeKeyVal: (val, memo) => {\n            let arg,\n                eqIndex = val.indexOf('=');\n\n            // This is done instead of splitting by `=` to avoid chopping off `=` that could be present in the value\n            arg = eqIndex !== -1 ? {\n                key: val.slice(0, eqIndex),\n                value: val.slice(eqIndex + 1)\n            } : {\n                key: val,\n                value: undefined\n            };\n\n            memo.push(arg);\n\n            return memo;\n        },\n\n        /**\n         * Helper to coerce comma separated string to an array.\n         *\n         * eg. item1,item2\n         *\n         * @param {String} list - The comma separated string.\n         * @returns {String[]} - [item1, item2] - The array representation of the passed string.\n         */\n        csvParse: (list) => {\n            return _.split(list, ',');\n        },\n\n        colorOptions: (value) => {\n            if (!(/^(auto|on|off)$/).test(value)) {\n                throw new Error(`invalid value \\`${value}\\` for --color. Expected: auto|on|off`);\n            }\n\n            return value;\n        }\n    },\n\n    /**\n     * Extract selected options in the provided command.\n     * Omits commander private variables and other objects.\n     *\n     * @param {Object} command - Commander.Command Instance\n     * @returns {Object} - Extracted options from command\n     */\n    commanderToObject: (command) => {\n        return _.reduce(command, (result, value, key) => {\n            // Exclude command's private `_` variables and other objects\n            const validProp = !_.startsWith(key, '_') && !_.includes(['commands', 'options', 'parent'], key);\n\n            validProp && (result[key] = value);\n\n            return result;\n        }, {});\n    },\n\n    /**\n     * Remove nested options having the provided prefix from `process.argv`.\n     *\n     * @param {String[]} argv - Argument vector.\n     * @param {String} optionPrefix - Argument prefix to search for.\n     * @returns {String[]} - All arguments without prefixed options and their values\n     */\n    omitNestedOptions: (argv, optionPrefix) => {\n        let args = [],\n            len,\n            i;\n\n        for (i = 0, len = argv.length; i < len; i++) {\n            if (!_.startsWith(argv[i], optionPrefix)) {\n                args.push(argv[i]);\n                continue;\n            }\n\n            // For prefixed args also omit its value, --prefix-arg value\n            if (argv[i + 1] && !_.startsWith(argv[i + 1], '-')) {\n                ++i;\n            }\n        }\n\n        return args;\n    },\n\n    /**\n     * Parse nested options having the provided prefix from `process.argv`.\n     *\n     * @param {String[]} argv - Argument vector.\n     * @param {String} optionPrefix - Argument prefix to search for.\n     * @param {String[]} options - Selected options.\n     * @returns {Object} Parsed object with nested options.\n     *\n     * @example\n     * let argv = ['--reporters=json,html', '--reporter-html-template=template.hb', '--reporter-export=path'],\n     *     options = ['json', 'html'];\n     * parseNestedOptions(argv, '--reporter-', options);\n     * //returns\n     * {\n     *   _generic: { export: path },\n     *   html: { template: template.hb },\n     *   json: {}\n     * }\n     *\n     */\n    parseNestedOptions: (argv, optionPrefix, options) => {\n        let args = [],\n            parsed = { _generic: {} },\n            name,\n            path,\n            len,\n            eqIndex,\n            i;\n\n        // Extract prefixed arguments from argv\n        for (i = 0, len = argv.length; i < len; i++) {\n            const arg = argv[i];\n\n            if (!_.startsWith(arg, optionPrefix)) { continue; } // skip non-prefixed args\n\n            eqIndex = arg.indexOf('=');\n\n            if (eqIndex !== -1) {\n                // Split the attribute if its like key=value\n                args.push(arg.slice(0, eqIndex), arg.slice(eqIndex + 1));\n            }\n            else if (argv[i + 1] && !_.startsWith(argv[i + 1], '-')) {\n                // Also push the next parameter if it's not an option.\n                args.push(arg, argv[++i]);\n            }\n            else {\n                args.push(arg);\n            }\n        }\n\n        // ensure that whatever option is provided a blank options object is forwarded\n        _.forEach(options, (option) => { parsed[option] = {}; });\n        // Parse nested options\n        for (i = 0, len = args.length; i < len; i++) {\n            const arg = args[i].replace(optionPrefix, '');\n\n            name = _.split(arg, '-', 1)[0]; // eg. `cli` in --reporter-cli-silent\n\n            // if we have a valid option, the path should be the <name>.camelCaseOfTheRest\n            // otherwise, we add it to the generic options.\n            path = _.includes(options, name) ?\n                [name, _.camelCase(arg.replace(name + '-', ''))].join('.') :\n                ['_generic', _.camelCase(arg)].join('.');\n\n            // If the next arg is an option, set the current arg to true,\n            // otherwise set it to the next arg.\n            _.set(parsed, path, (!args[i + 1] || _.startsWith(args[i + 1], '-')) ? true : args[++i]);\n        }\n\n        return parsed;\n    }\n\n};\n"
  },
  {
    "path": "codecov.yml",
    "content": "coverage:\n  range: 70..100         # green if 100+, red if 70-\n\n  status:\n    patch:\n      # coverage status for pull request diff\n      default:\n        target: 100     # any patch should be 100% covered\n        threshold: 1%   # allow a little drop\n\n    project:\n      # coverage status for whole project\n      default:\n        target: auto    # use coverage of base commit as target\n        threshold: 1%   # allow a little drop\n\n      # coverage status for unit tests\n      unit:\n        target: 75\n        flags:\n            - unit\n\n      # coverage status for integration tests\n      integration:\n        target: 50\n        flags:\n            - integration\n\n      # coverage status for cli tests\n      cli:\n        target: 80\n        flags:\n            - cli\n\n      # coverage status for library tests\n      library:\n        target: 65\n        flags:\n            - library\n\nparsers:\n  javascript:\n    enable_partials: yes    # use partial line coverage\n"
  },
  {
    "path": "docker/README.md",
    "content": "<img src=\"https://s3.amazonaws.com/web-artefacts/cartoon-whale-8.gif+(400%C3%97225).png\">\n\n# newman-docker\n\nThis repository contains docker images for Newman.\n\n<a href=\"https://github.com/postmanlabs/newman\" target=\"_blank\">Newman</a> is a command-line collection runner for\n<a href=\"https://postman.com\" target=\"_blank\">Postman</a>. It allows you to effortlessly run and test a\n<a href=\"https://learning.postman.com/docs/sending-requests/intro-to-collections\" target=\"_blank\">Postman Collections<a/> directly from the\ncommand-line. It is built with extensibility in mind so that you can easily integrate it with your continuous\nintegration servers and build systems.\n\n**New to Docker?** Docker allows you to package an application with all of its dependencies into a standardised unit for\nsoftware development. Visit\n<a href=\"https://www.docker.com/whatisdocker\" target=\"_blank\">https://www.docker.com/whatisdocker</a> to read more about\nhow docker can drastically simplify development and deployment.\n\n## There are two available Docker images for Newman\n### postman/newman:alpine (lightweight):\n   * <a href=\"https://hub.docker.com/r/postman/newman/\">DockerHub</a>\n   * <a href=\"https://github.com/postmanlabs/newman/tree/develop/docker/images/alpine\">Documentation</a>\n\n### postman/newman:ubuntu:\n   * <a href=\"https://hub.docker.com/r/postman/newman/\">DockerHub</a>\n   * <a href=\"https://github.com/postmanlabs/newman/tree/develop/docker/images/ubuntu\">Documentation</a>\n\n## Using the docker image\n\nThe docker image for Newman is available for download from our docker hub. You must have Docker installed in your\nsystem. Docker has extensive <a href=\"https://docs.docker.com/installation/\" target=\"_blank\">installation guideline for\npopular operating systems</a>. Choose your operating system and follow the instructions.\n\n> Ensure you that you have docker installed and running in your system before proceeding with next steps. A quick test\n> to see if docker is installed correctly is to execute the command `docker run hello-world` and it should run without\n> errors.\n\n**Step 1:**\n\nPull the <a href=\"https://registry.hub.docker.com/u/postman/newman:ubuntu/\" target=\"_blank\">newman docker\nimage</a> from docker hub:\n\n```terminal\ndocker pull postman/newman:ubuntu\n```\n\n**Step 2:**\n\nRun newman commands on the image:\n\n```terminal\ndocker run -t postman/newman:ubuntu run https://www.getpostman.com/collections/8a0c9bc08f062d12dcda\n```\n\n### Build the docker image from this repository\n\n\n**Step 1:**\n\nClone this repository:\n\n```terminal\ngit clone https://github.com/postmanlabs/newman.git\n```\n\n**Step 2:**\n\nBuild the image:\n\n```terminal\ndocker build -t postman/newman:ubuntu --build-arg NEWMAN_VERSION=\"full semver version\" .;\n```\n\n**Step 3:**\n\nRun a collection using the newman image:\n\n```terminal\ndocker run -t postman/newman:ubuntu run https://www.getpostman.com/collections/8a0c9bc08f062d12dcda\n```\n\n\n## Running local collection files\n\nThis docker image is designed to pick files from the `/etc/newman` directory within the image. You may mount the\ndirectory of your collection files into that location and provide the file references in standard newman parameters.\n\n\n```terminal\n# Mount host collections folder ~/collections, onto /etc/newman on the docker image, so that newman\n# has access to collections\ndocker run -v ~/collections:/etc/newman -t postman/newman:ubuntu run \"HTTPBinNewmanTestNoEnv.json.postman_collection\"\n```\n\nYou are not required to mount a volume if you do not need to save newman report to the host, and your collection is\navailable online, unless your collection requires an environment(as environments cannot be passed as URLs).\n\nTo know more about mounting volumes, visit\n<a href=\"https://docs.docker.com/userguide/dockervolumes/\" target=\"_blank\">docker documentation on shared data volumes</a>.\n\n\n## Examples\n\nRun a local collection, pass an environment to it, and save the JSON report on the host.\n\n```terminal\ndocker run -v ~/collections:/etc/newman -t postman/newman:ubuntu \\\n    run \"HTTPBinNewmanTest.json.postman_collection\" \\\n    --environment=\"HTTPBinNewmanTestEnv.json.postman_environment\" \\\n    --reporters=\"json,cli\" --reporter-json-export=\"newman-results.json\"\n```\n\n<br />Run a remote collection, pass it a local environment, and save JUnit XML test report on the host\n\n```terminal\ndocker run -v ~/collections:/etc/newman -t postman/newman:ubuntu \\\n    run https://www.getpostman.com/collections/8a0c9bc08f062d12dcda \\\n    --environment=\"HTTPBinNewmanTestEnv.json.postman_environment\" \\\n    --reporters=\"junit,cli\" --reporter-junit-export=\"newman-report.xml\"\n```\n\n<br />Use a script to run a collection and do something, for example deploy the build, if all the tests pass\n\n```bash\n#/bin/bash\n\n# stop on first error\nset -e;\n\nfunction onExit {\n    if [ \"$?\" != \"0\" ]; then\n        echo \"Tests failed\";\n        # build failed, don't deploy\n        exit 1;\n    else\n        echo \"Tests passed\";\n        # deploy build\n    fi\n}\n\n# call onExit when the script exits\ntrap onExit EXIT;\n\ndocker run --entrypoint -t postman/newman:ubuntu run https://www.getpostman.com/collections/8a0c9bc08f062d12dcda --suppress-exit-code;\n```\n\n## Using Newman Docker images with custom reporters\nNewman Docker images can also be used with custom Newman reporters, as follows:\n```console\ndocker run -v \"<collection-directory>:/etc/newman\" --entrypoint /bin/<bash-or-sh> <image:tag> -c \"npm i -g newman-reporter-<reporter-name>; newman run sample-collection.json -r <reporter-name>\"\n```\n\nIn the above example,\n* `<collection-directory>` is the source directory for collections. This directory will also be used to write Newman reports.\n* `<image>` is a combination of the image name (and optional tag). For instance, `postman/newman:ubuntu` or `postman/newman:alpine`\n* `<reporter-name>` is the reporter that has to be installed and loaded for the `newman run ...`\n\n### Alpine\nNote that the entrypoint here is `/bin/sh`, and **not** `/bin/bash`\n```console\ndocker run -v \"~/collections:/etc/newman\" --entrypoint /bin/sh postman/newman:alpine -c \"npm i -g newman-reporter-html; newman run sample-collection.json -r html\"\n```\n\n### Ubuntu\n```console\ndocker run -v \"~/collections:/etc/newman\" --entrypoint /bin/bash postman/newman:ubuntu -c \"npm i -g newman-reporter-html; newman run sample-collection.json -r html\"\n```\n\n## Node version\nAll official Newman Docker images will be shipped with the current Node LTS (Long Term Support) version. To learn more\nabout the Node release schedule, see https://github.com/nodejs/Release#release-schedule. More details about individual\nDocker images can be found in their individual READMEs in this folder.\n\n[![Analytics](https://ga-beacon.appspot.com/UA-43979731-9/newman-docker/readme)](https://postman.com)\n"
  },
  {
    "path": "docker/images/alpine/Dockerfile",
    "content": "FROM node:16-alpine\nLABEL maintainer=\"Postman Labs <help@postman.com>\"\n\nARG NEWMAN_VERSION\n\n# Set environment variables\nENV LC_ALL=\"en_US.UTF-8\" LANG=\"en_US.UTF-8\" LANGUAGE=\"en_US.UTF-8\" ALPINE_NODE_REPO=\"oznu/alpine-node\"\n\n# Bail out early if NODE_VERSION is not provided\nRUN if [ ! $(echo $NEWMAN_VERSION | grep -oE \"^[0-9]+\\.[0-9]+\\.[0-9]+$\") ]; then \\\n        echo \"\\033[0;31mA valid semver Newman version is required in the NEWMAN_VERSION build-arg\\033[0m\"; \\\n        exit 1; \\\n    fi && \\\n    # Install Newman globally\n    npm install --global newman@${NEWMAN_VERSION};\n\n# Set workdir to /etc/newman\n# When running the image, mount the directory containing your collection to this location\n#\n# docker run -v <path to collections directory>:/etc/newman ...\n#\n# In case you mount your collections directory to a different location, you will need to give absolute paths to any\n# collection, environment files you want to pass to newman, and if you want newman reports to be saved to your disk.\n# Or you can change the workdir by using the -w or --workdir flag\nWORKDIR /etc/newman\n\n# Set newman as the default container command\n# Now you can run the container via\n#\n# docker run -v /home/collections:/etc/newman -t postman/newman_alpine run YourCollection.json.postman_collection \\\n#                                                                        -e YourEnvironment.postman_environment \\\n#                                                                        -H newman_report.html\nENTRYPOINT [\"newman\"]\n"
  },
  {
    "path": "docker/images/alpine/README.md",
    "content": "# newman:alpine\n\nThis image runs newman on node v16 on Alpine\n\nBuild the image:\n\n```terminal\ndocker build -t postman/newman:alpine --build-arg NEWMAN_VERSION=\"full semver version\" .\n```\n\nOr get it from [Docker Hub](https://registry.hub.docker.com/u/postman/newman/):\n\n```terminal\ndocker pull postman/newman:alpine\n```\n\nThen run it:\n\n```terminal\ndocker --volume=\"/home/postman/collections:/etc/newman\" -t postman/newman:alpine run JSONBlobCoreAPI.json.postman_collection -r json --reporter-json-export newman-report.json\n```\nFor newman-docker to be able to use collections and environment files saved on the host machine, and to save reports generated by newman, a directory containing the collection and environment needs to be mounted on to the docker instance on run time, preferably at `/etc/newman`, which is the default working directory. If you mount to a different location, then:\n  - You can pass the full path to your collection and environment files to newman. For instance, if you mount to `/etc/newman`,\n\n```terminal\ndocker --volume=\"/home/postman/collection:/etc/newman\" -t postman/newman:alpine run JSONBlobCoreAPI.json.postman_collection\" -r json --reporter-json-export newman-report.json\n```\n  - You can change the working directory while running the image to the location you mounted to, using the `-w` or `--workdir` flag.\n\n```terminal\ndocker run --volume=\"/home/postman/collections:/etc/newman\" -t postman/newman:alpine run JSONBlobCoreAPI.json.postman_collection -r json --reporter-json-export newman-report.json\n```\n\nIn case you don't need to save newman's report to the host, and your collection is available online and does not require any environment, then you can forgo mounting your collections directory and directly pass the collection URL to newman:\n\n```terminal\ndocker run -t postman/newman:alpine run https://www.getpostman.com/collections/8a0c9bc08f062d12dcda\n```\n"
  },
  {
    "path": "docker/images/ubuntu/Dockerfile",
    "content": "FROM ubuntu:22.04\nLABEL maintainer=\"Postman Labs <help@postman.com>\"\n\nARG NODE_MAJOR=16\nARG NEWMAN_VERSION\n\n# Bail out early if NEWMAN_VERSION is not provided\nRUN if [ ! $(echo $NEWMAN_VERSION | grep -oE \"^[0-9]+\\.[0-9]+\\.[0-9]+$\") ]; then \\\n        echo \"\\033[0;31mA valid semver Newman version is required in the NEWMAN_VERSION build-arg\\033[0m\"; \\\n        exit 1; \\\n    fi\n\nRUN apt-get update; \\\n\n    # Download and import the Nodesource GPG key\n    apt-get install -y ca-certificates curl gnupg; \\\n    mkdir -p /etc/apt/keyrings; \\\n    curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key \\\n     | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg; \\\n\n    # Create deb repository\n    echo \"deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_$NODE_MAJOR.x nodistro main\" \\\n     | tee /etc/apt/sources.list.d/nodesource.list; \\\n\n    # Run Update and Install\n    apt-get update; \\\n    apt-get install nodejs -y; \\\n\n    # Install Newman globally\n    npm install --global newman@${NEWMAN_VERSION};\n\n# Set environment variables\nENV LC_ALL=\"en_US.UTF-8\" LANG=\"en_US.UTF-8\" LANGUAGE=\"en_US.UTF-8\"\n\n# Set workdir to /etc/newman\n# When running the image, mount the directory containing your collection to this location\n#\n# docker run -v <path to collections directory>:/etc/newman ...\n#\n# In case you mount your collections directory to a different location, you will need to give absolute paths to any\n# collection, environment files you want to pass to newman, and if you want newman reports to be saved to your disk.\n# Or you can change the workdir by using the -w or --workdir flag\nWORKDIR /etc/newman\n\n# Set newman as the default container command\n# Now you can run the container via\n#\n# docker run -v /home/collections:/etc/newman -t postman/newman_ubuntu run YourCollection.json.postman_collection \\\n#                                                                          -e YourEnvironment.postman_environment \\\n#                                                                          -H newman_report.html\nENTRYPOINT [\"newman\"]\n"
  },
  {
    "path": "docker/images/ubuntu/README.md",
    "content": "# newman:ubuntu\n\nThis image runs newman on node v16 on Ubuntu 22.04\n\nBuild the image,\n\n```terminal\ndocker build -t postman/newman:ubuntu --build-arg NEWMAN_VERSION=\"full semver version\" .\n```\n\nOr get it from [docker hub](https://registry.hub.docker.com/u/postman/newman:ubuntu/)\n\n```terminal\ndocker pull postman/newman:ubuntu\n```\n\nThen run it\n\n```terminal\ndocker --volume=\"/home/postman/collections:/etc/newman\" -t postman/newman:ubuntu run JSONBlobCoreAPI.json.postman_collection -r json --reporter-json-export newman-report.json\n```\nFor newman-docker to be able to use collections and environment files saved on the host machine, and to save reports generated by newman, a directory containing the collection and environment needs to be mounted on to the docker instance on run time, preferably at `/etc/newman`, which is the default working directory. If you mount to a different location, then\n  - You can either pass the full path to your collection and environment files to newman. For instance, if you mount to `/etc/newman`,\n\n```terminal\ndocker --volume=\"/home/postman/collection:/etc/newman\" -t postman/newman:ubuntu run JSONBlobCoreAPI.json.postman_collection -r json --reporter-json-export newman-report.json\n```\n  - You can change the working directory while running the image to the location you mounted to, using the `-w` or `--workdir` flag.\n\n```terminal\ndocker run --volume=\"/home/postman/collections:/etc/newman\" -t postman/newman:ubuntu run JSONBlobCoreAPI.json.postman_collection -r json --reporter-json-export newman-report.json\n```\n\nIn case you don't need to save newman's report to the host, and your collection is available online and it does not require any environment, then you can forgo mounting your collections directory, and directly pass the collection url to newman\n\n```terminal\ndocker run -t postman/newman:ubuntu run https://www.getpostman.com/collections/8a0c9bc08f062d12dcda\n```\n"
  },
  {
    "path": "examples/find-unique-urls-in-run.js",
    "content": "#!/usr/bin/env node\n/**\n * @fileOverview\n * This sample code illustrates how to read a collection JSON file in NodeJS,run it using Newman and then log all the\n * unique URLs that were requested.\n */\nvar newman = require('../'), // require('newman')\n    uniqueUrls = {}; // here we will maintain the unique URLs\n\n// call newman.run to pass `options` object and listen to events\nnewman.run({ collection: require('./sample-collection.json') })\n    .on('start', function (err, args) {\n        if (err) { return; }\n\n        console.info(`Running ${args.cursor.length} request(s) and ${args.cursor.cycles} iteration(s)`);\n    })\n    .on('request', function (err, args) {\n        if (err) { return; }\n\n        var url = args.request.url.toString();\n\n        // store the URL string as key of the object so that we can quickly do hashing of unique URLs and add a counter\n        if (uniqueUrls[url]) {\n            uniqueUrls[url] += 1; // increment counter if the url was already called\n        }\n        else {\n            uniqueUrls[url] = 1; // otherwise start a new counter\n        }\n    })\n    .once('done', function (err) {\n        var urls = Object.keys(uniqueUrls); // get list of all unique urls as an array from the object hash\n\n        // now output the result to console\n        console.info(`The collection run completed ${err ? 'with' : 'without'} error(s).`);\n        console.info(`Total ${urls.length} unique URLs requested.`);\n\n        urls.forEach(function (url) {\n            console.info(`${uniqueUrls[url]}: ${url}`);\n        });\n    });\n"
  },
  {
    "path": "examples/parallel-collection-runs.js",
    "content": "/**\n * @fileOverview A sample script to demonstrate parallel collection runs using async.\n */\nvar path = require('path'), // ensures that the path is consistent, regardless of where the script is run from\n\n    async = require('async'), // https://npmjs.org/package/async\n    newman = require('../'), // change to require('newman'), if using outside this repository\n\n    /**\n     * A set of collection run options for the paralle collection runs. For demonstrative purposes in this script, an\n     * identical set of options has been used. However, different options can be used, so as to actually run different\n     * collections, with their corresponding run options in parallel.\n     *\n     * @type {Object}\n     */\n    options = {\n        collection: path.join(__dirname, 'sample-collection.json')\n    },\n\n    /**\n     * A collection runner function that runs a collection for a pre-determined options object.\n     *\n     * @param {Function} done - A callback function that marks the end of the current collection run, when called.\n     */\n    parallelCollectionRun = function (done) {\n        newman.run(options, done);\n    };\n\n// Runs the Postman sample collection thrice, in parallel.\nasync.parallel([\n    parallelCollectionRun,\n    parallelCollectionRun,\n    parallelCollectionRun\n],\n\n/**\n * The\n *\n * @param {?Error} err - An Error instance / null that determines whether or not the parallel collection run\n * succeeded.\n * @param {Array} results - An array of collection run summary objects.\n */\nfunction (err, results) {\n    err && console.error(err);\n\n    results.forEach(function (result) {\n        var failures = result.run.failures;\n\n        console.info(failures.length ? JSON.stringify(failures.failures, null, 2) :\n            `${result.collection.name} ran successfully.`);\n    });\n});\n"
  },
  {
    "path": "examples/read-collection-from-file.js",
    "content": "#!/usr/bin/env node\n/**\n * @fileOverview\n * This sample code illustrates how to read a collection JSON file in NodeJS and run it using Newman\n */\nvar newman = require('../'); // require('newman')\n\n// call newman.run to pass `options` object and wait for callback\nnewman.run({\n    collection: require('./sample-collection.json'),\n    reporters: 'cli'\n}, function (err) {\n    if (err) { throw err; }\n    console.info('collection run complete!');\n});\n"
  },
  {
    "path": "examples/reports/sample-collection-report.json",
    "content": "{\n  \"collection\": {\n    \"info\": {\n      \"id\": \"6d031f42-a134-4dba-86c5-ce154f352f33\",\n      \"name\": \"Sample Postman Collection\",\n      \"schema\": \"https://schema.getpostman.com/json/collection/v2.0.0/collection.json\"\n    },\n    \"item\": [\n      {\n        \"id\": \"17d87a3b-fdc8-4b18-9815-950a42d87f59\",\n        \"name\": \"A simple GET request\",\n        \"request\": {\n          \"url\": \"https://postman-echo.com/get?source=newman-sample-github-collection\",\n          \"method\": \"GET\"\n        },\n        \"event\": [\n          {\n            \"listen\": \"test\",\n            \"script\": {\n              \"type\": \"text/javascript\",\n              \"exec\": [\n                \"tests['response code is 200'] = (responseCode.code === 200);\"\n              ]\n            }\n          }\n        ]\n      },\n      {\n        \"id\": \"45805ccf-86f6-44d1-b1fa-18431f4025e5\",\n        \"name\": \"A simple POST request\",\n        \"request\": {\n          \"url\": \"https://postman-echo.com/post\",\n          \"method\": \"POST\",\n          \"header\": [\n            {\n              \"key\": \"Content-Type\",\n              \"value\": \"text/plain\"\n            }\n          ],\n          \"body\": {\n            \"mode\": \"raw\",\n            \"raw\": \"Duis posuere augue vel cursus pharetra. In luctus a ex nec pretium...\"\n          }\n        }\n      },\n      {\n        \"id\": \"0d5736de-0cf1-46a9-b057-3997c275af4b\",\n        \"name\": \"A simple POST request with JSON body\",\n        \"request\": {\n          \"url\": \"https://postman-echo.com/post\",\n          \"method\": \"POST\",\n          \"header\": [\n            {\n              \"key\": \"Content-Type\",\n              \"value\": \"application/json\"\n            }\n          ],\n          \"body\": {\n            \"mode\": \"raw\",\n            \"raw\": \"{\\\"text\\\":\\\"Duis posuere augue vel cursus pharetra. In luctus a ex nec pretium...\\\"}\"\n          }\n        }\n      }\n    ]\n  },\n  \"environment\": {\n    \"values\": []\n  },\n  \"globals\": {\n    \"values\": []\n  },\n  \"run\": {\n    \"stats\": {\n      \"iterations\": {\n        \"total\": 1,\n        \"pending\": 0,\n        \"failed\": 0\n      },\n      \"items\": {\n        \"total\": 3,\n        \"pending\": 0,\n        \"failed\": 0\n      },\n      \"scripts\": {\n        \"total\": 1,\n        \"pending\": 0,\n        \"failed\": 0\n      },\n      \"prerequests\": {\n        \"total\": 3,\n        \"pending\": 0,\n        \"failed\": 0\n      },\n      \"requests\": {\n        \"total\": 3,\n        \"pending\": 0,\n        \"failed\": 0\n      },\n      \"tests\": {\n        \"total\": 3,\n        \"pending\": 0,\n        \"failed\": 0\n      },\n      \"assertions\": {\n        \"total\": 1,\n        \"pending\": 0,\n        \"failed\": 0\n      },\n      \"testScripts\": {\n        \"total\": 1,\n        \"pending\": 0,\n        \"failed\": 0\n      },\n      \"prerequestScripts\": {\n        \"total\": 0,\n        \"pending\": 0,\n        \"failed\": 0\n      }\n    },\n    \"timings\": {\n      \"responseAverage\": 849,\n      \"started\": 1472134919325,\n      \"completed\": 1472134922455\n    },\n    \"executions\": [\n      {\n        \"cursor\": {\n          \"position\": 0,\n          \"iteration\": 0,\n          \"length\": 3,\n          \"cycles\": 1,\n          \"empty\": false,\n          \"eof\": false,\n          \"bof\": true,\n          \"cr\": false,\n          \"ref\": \"25eb69fd-1b89-441c-8dfe-5471bf15d02e\"\n        },\n        \"item\": {\n          \"id\": \"17d87a3b-fdc8-4b18-9815-950a42d87f59\",\n          \"name\": \"A simple GET request\",\n          \"request\": {\n            \"url\": \"https://postman-echo.com/get?source=newman-sample-github-collection\",\n            \"method\": \"GET\"\n          },\n          \"event\": [\n            {\n              \"listen\": \"test\",\n              \"script\": {\n                \"type\": \"text/javascript\",\n                \"exec\": [\n                  \"tests['response code is 200'] = (responseCode.code === 200);\"\n                ]\n              }\n            }\n          ]\n        },\n        \"request\": {\n          \"url\": \"https://postman-echo.com/get?source=newman-sample-github-collection\",\n          \"method\": \"GET\",\n          \"header\": [\n            {\n              \"key\": \"User-Agent\",\n              \"value\": \"PostmanRuntime/2.4.3\"\n            },\n            {\n              \"key\": \"Accept\",\n              \"value\": \"*/*\"\n            },\n            {\n              \"key\": \"Host\",\n              \"value\": \"postman-echo.com\"\n            },\n            {\n              \"key\": \"accept-encoding\",\n              \"value\": \"gzip, deflate\"\n            }\n          ],\n          \"body\": {},\n          \"description\": {}\n        },\n        \"response\": {\n          \"status\": \"OK\",\n          \"code\": 200,\n          \"header\": [\n            {\n              \"key\": \"Access-Control-Allow-Credentials\",\n              \"value\": \"\"\n            },\n            {\n              \"key\": \"Access-Control-Allow-Headers\",\n              \"value\": \"\"\n            },\n            {\n              \"key\": \"Access-Control-Allow-Methods\",\n              \"value\": \"\"\n            },\n            {\n              \"key\": \"Access-Control-Allow-Origin\",\n              \"value\": \"\"\n            },\n            {\n              \"key\": \"Access-Control-Expose-Headers\",\n              \"value\": \"\"\n            },\n            {\n              \"key\": \"Content-Encoding\",\n              \"value\": \"gzip\"\n            },\n            {\n              \"key\": \"Content-Type\",\n              \"value\": \"application/json; charset=utf-8\"\n            },\n            {\n              \"key\": \"Date\",\n              \"value\": \"Thu, 25 Aug 2016 14:22:01 GMT\"\n            },\n            {\n              \"key\": \"ETag\",\n              \"value\": \"W/\\\"137-PVrRGQ6/XWPrd95mL9VLkA\\\"\"\n            },\n            {\n              \"key\": \"Server\",\n              \"value\": \"nginx/1.8.1\"\n            },\n            {\n              \"key\": \"set-cookie\",\n              \"value\": \"sails.sid=s%3AKWkP8x3Zi5Dw8iEGxf4rtsVeadIVITil.kefDILpoX6Yda98kJa7ksUS8M5y1tUnu4S7yjKZN5Dg; Path=/; HttpOnly\"\n            },\n            {\n              \"key\": \"Vary\",\n              \"value\": \"Accept-Encoding\"\n            },\n            {\n              \"key\": \"Content-Length\",\n              \"value\": \"203\"\n            },\n            {\n              \"key\": \"Connection\",\n              \"value\": \"keep-alive\"\n            }\n          ],\n          \"body\": \"{\\\"args\\\":{\\\"source\\\":\\\"newman-sample-github-collection\\\"},\\\"headers\\\":{\\\"host\\\":\\\"postman-echo.com\\\",\\\"accept\\\":\\\"*/*\\\",\\\"accept-encoding\\\":\\\"gzip, deflate\\\",\\\"user-agent\\\":\\\"PostmanRuntime/2.4.3\\\",\\\"x-forwarded-port\\\":\\\"443\\\",\\\"x-forwarded-proto\\\":\\\"https\\\"},\\\"url\\\":\\\"https://postman-echo.com/get?source=newman-sample-github-collection\\\"}\",\n          \"responseTime\": 1965,\n          \"responseSize\": 311\n        },\n        \"id\": \"17d87a3b-fdc8-4b18-9815-950a42d87f59\",\n        \"assertions\": [\n          {\n            \"assertion\": \"response code is 200\"\n          }\n        ]\n      },\n      {\n        \"cursor\": {\n          \"ref\": \"5b16b008-5b98-4a0e-95ba-e5944936a61c\",\n          \"length\": 3,\n          \"cycles\": 1,\n          \"position\": 1,\n          \"iteration\": 0\n        },\n        \"item\": {\n          \"id\": \"45805ccf-86f6-44d1-b1fa-18431f4025e5\",\n          \"name\": \"A simple POST request\",\n          \"request\": {\n            \"url\": \"https://postman-echo.com/post\",\n            \"method\": \"POST\",\n            \"header\": [\n              {\n                \"key\": \"Content-Type\",\n                \"value\": \"text/plain\"\n              }\n            ],\n            \"body\": {\n              \"mode\": \"raw\",\n              \"raw\": \"Duis posuere augue vel cursus pharetra. In luctus a ex nec pretium...\"\n            }\n          }\n        },\n        \"request\": {\n          \"url\": \"https://postman-echo.com/post\",\n          \"method\": \"POST\",\n          \"header\": [\n            {\n              \"key\": \"Content-Type\",\n              \"value\": \"text/plain\"\n            },\n            {\n              \"key\": \"User-Agent\",\n              \"value\": \"PostmanRuntime/2.4.3\"\n            },\n            {\n              \"key\": \"Accept\",\n              \"value\": \"*/*\"\n            },\n            {\n              \"key\": \"Host\",\n              \"value\": \"postman-echo.com\"\n            },\n            {\n              \"key\": \"cookie\",\n              \"value\": \"sails.sid=s%3AKWkP8x3Zi5Dw8iEGxf4rtsVeadIVITil.kefDILpoX6Yda98kJa7ksUS8M5y1tUnu4S7yjKZN5Dg\"\n            },\n            {\n              \"key\": \"accept-encoding\",\n              \"value\": \"gzip, deflate\"\n            },\n            {\n              \"key\": \"content-length\",\n              \"value\": 69\n            }\n          ],\n          \"body\": {\n            \"mode\": \"raw\",\n            \"raw\": \"Duis posuere augue vel cursus pharetra. In luctus a ex nec pretium...\"\n          },\n          \"description\": {}\n        },\n        \"response\": {\n          \"status\": \"OK\",\n          \"code\": 200,\n          \"header\": [\n            {\n              \"key\": \"Access-Control-Allow-Credentials\",\n              \"value\": \"\"\n            },\n            {\n              \"key\": \"Access-Control-Allow-Headers\",\n              \"value\": \"\"\n            },\n            {\n              \"key\": \"Access-Control-Allow-Methods\",\n              \"value\": \"\"\n            },\n            {\n              \"key\": \"Access-Control-Allow-Origin\",\n              \"value\": \"\"\n            },\n            {\n              \"key\": \"Access-Control-Expose-Headers\",\n              \"value\": \"\"\n            },\n            {\n              \"key\": \"Content-Encoding\",\n              \"value\": \"gzip\"\n            },\n            {\n              \"key\": \"Content-Type\",\n              \"value\": \"application/json; charset=utf-8\"\n            },\n            {\n              \"key\": \"Date\",\n              \"value\": \"Thu, 25 Aug 2016 14:22:02 GMT\"\n            },\n            {\n              \"key\": \"ETag\",\n              \"value\": \"W/\\\"1ef-XCjjHFaJKcRm3YHSPLLNSQ\\\"\"\n            },\n            {\n              \"key\": \"Server\",\n              \"value\": \"nginx/1.8.1\"\n            },\n            {\n              \"key\": \"Vary\",\n              \"value\": \"X-HTTP-Method-Override, Accept-Encoding\"\n            },\n            {\n              \"key\": \"Content-Length\",\n              \"value\": \"359\"\n            },\n            {\n              \"key\": \"Connection\",\n              \"value\": \"keep-alive\"\n            }\n          ],\n          \"body\": \"{\\\"args\\\":{},\\\"data\\\":\\\"Duis posuere augue vel cursus pharetra. In luctus a ex nec pretium...\\\",\\\"files\\\":{},\\\"form\\\":{},\\\"headers\\\":{\\\"host\\\":\\\"postman-echo.com\\\",\\\"content-length\\\":\\\"69\\\",\\\"accept\\\":\\\"*/*\\\",\\\"accept-encoding\\\":\\\"gzip, deflate\\\",\\\"content-type\\\":\\\"text/plain\\\",\\\"cookie\\\":\\\"sails.sid=s%3AKWkP8x3Zi5Dw8iEGxf4rtsVeadIVITil.kefDILpoX6Yda98kJa7ksUS8M5y1tUnu4S7yjKZN5Dg\\\",\\\"user-agent\\\":\\\"PostmanRuntime/2.4.3\\\",\\\"x-forwarded-port\\\":\\\"443\\\",\\\"x-forwarded-proto\\\":\\\"https\\\"},\\\"json\\\":null,\\\"url\\\":\\\"https://postman-echo.com/post\\\"}\",\n          \"responseTime\": 273,\n          \"responseSize\": 495\n        },\n        \"id\": \"45805ccf-86f6-44d1-b1fa-18431f4025e5\"\n      },\n      {\n        \"cursor\": {\n          \"ref\": \"e6098562-1dfa-470c-a4ff-2e65636f7c27\",\n          \"length\": 3,\n          \"cycles\": 1,\n          \"position\": 2,\n          \"iteration\": 0\n        },\n        \"item\": {\n          \"id\": \"0d5736de-0cf1-46a9-b057-3997c275af4b\",\n          \"name\": \"A simple POST request with JSON body\",\n          \"request\": {\n            \"url\": \"https://postman-echo.com/post\",\n            \"method\": \"POST\",\n            \"header\": [\n              {\n                \"key\": \"Content-Type\",\n                \"value\": \"application/json\"\n              }\n            ],\n            \"body\": {\n              \"mode\": \"raw\",\n              \"raw\": \"{\\\"text\\\":\\\"Duis posuere augue vel cursus pharetra. In luctus a ex nec pretium...\\\"}\"\n            }\n          }\n        },\n        \"request\": {\n          \"url\": \"https://postman-echo.com/post\",\n          \"method\": \"POST\",\n          \"header\": [\n            {\n              \"key\": \"Content-Type\",\n              \"value\": \"application/json\"\n            },\n            {\n              \"key\": \"User-Agent\",\n              \"value\": \"PostmanRuntime/2.4.3\"\n            },\n            {\n              \"key\": \"Accept\",\n              \"value\": \"*/*\"\n            },\n            {\n              \"key\": \"Host\",\n              \"value\": \"postman-echo.com\"\n            },\n            {\n              \"key\": \"cookie\",\n              \"value\": \"sails.sid=s%3AKWkP8x3Zi5Dw8iEGxf4rtsVeadIVITil.kefDILpoX6Yda98kJa7ksUS8M5y1tUnu4S7yjKZN5Dg\"\n            },\n            {\n              \"key\": \"accept-encoding\",\n              \"value\": \"gzip, deflate\"\n            },\n            {\n              \"key\": \"content-length\",\n              \"value\": 80\n            }\n          ],\n          \"body\": {\n            \"mode\": \"raw\",\n            \"raw\": \"{\\\"text\\\":\\\"Duis posuere augue vel cursus pharetra. In luctus a ex nec pretium...\\\"}\"\n          },\n          \"description\": {}\n        },\n        \"response\": {\n          \"status\": \"OK\",\n          \"code\": 200,\n          \"header\": [\n            {\n              \"key\": \"Access-Control-Allow-Credentials\",\n              \"value\": \"\"\n            },\n            {\n              \"key\": \"Access-Control-Allow-Headers\",\n              \"value\": \"\"\n            },\n            {\n              \"key\": \"Access-Control-Allow-Methods\",\n              \"value\": \"\"\n            },\n            {\n              \"key\": \"Access-Control-Allow-Origin\",\n              \"value\": \"\"\n            },\n            {\n              \"key\": \"Access-Control-Expose-Headers\",\n              \"value\": \"\"\n            },\n            {\n              \"key\": \"Content-Encoding\",\n              \"value\": \"gzip\"\n            },\n            {\n              \"key\": \"Content-Type\",\n              \"value\": \"application/json; charset=utf-8\"\n            },\n            {\n              \"key\": \"Date\",\n              \"value\": \"Thu, 25 Aug 2016 14:22:02 GMT\"\n            },\n            {\n              \"key\": \"ETag\",\n              \"value\": \"W/\\\"24a-RFanBswLWTX2fy8gBq4Fug\\\"\"\n            },\n            {\n              \"key\": \"Server\",\n              \"value\": \"nginx/1.8.1\"\n            },\n            {\n              \"key\": \"Vary\",\n              \"value\": \"X-HTTP-Method-Override, Accept-Encoding\"\n            },\n            {\n              \"key\": \"Content-Length\",\n              \"value\": \"366\"\n            },\n            {\n              \"key\": \"Connection\",\n              \"value\": \"keep-alive\"\n            }\n          ],\n          \"body\": \"{\\\"args\\\":{},\\\"data\\\":{\\\"text\\\":\\\"Duis posuere augue vel cursus pharetra. In luctus a ex nec pretium...\\\"},\\\"files\\\":{},\\\"form\\\":{},\\\"headers\\\":{\\\"host\\\":\\\"postman-echo.com\\\",\\\"content-length\\\":\\\"80\\\",\\\"accept\\\":\\\"*/*\\\",\\\"accept-encoding\\\":\\\"gzip, deflate\\\",\\\"content-type\\\":\\\"application/json\\\",\\\"cookie\\\":\\\"sails.sid=s%3AKWkP8x3Zi5Dw8iEGxf4rtsVeadIVITil.kefDILpoX6Yda98kJa7ksUS8M5y1tUnu4S7yjKZN5Dg\\\",\\\"user-agent\\\":\\\"PostmanRuntime/2.4.3\\\",\\\"x-forwarded-port\\\":\\\"443\\\",\\\"x-forwarded-proto\\\":\\\"https\\\"},\\\"json\\\":{\\\"text\\\":\\\"Duis posuere augue vel cursus pharetra. In luctus a ex nec pretium...\\\"},\\\"url\\\":\\\"https://postman-echo.com/post\\\"}\",\n          \"responseTime\": 309,\n          \"responseSize\": 586\n        },\n        \"id\": \"0d5736de-0cf1-46a9-b057-3997c275af4b\"\n      }\n    ],\n    \"transfers\": {\n      \"responseTotal\": 928\n    },\n    \"failures\": [],\n    \"error\": null\n  }\n}\n"
  },
  {
    "path": "examples/reports/sample-collection-report.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<testsuites name=\"Sample Postman Collection\">\n  <testsuite name=\"A simple GET request\" id=\"17d87a3b-fdc8-4b18-9815-950a42d87f59\" time=\"1965\">\n    <testcase name=\"response code is 200\"/>\n  </testsuite>\n  <testsuite name=\"A simple POST request\" id=\"45805ccf-86f6-44d1-b1fa-18431f4025e5\" time=\"273\"/>\n  <testsuite name=\"A simple POST request with JSON body\" id=\"0d5736de-0cf1-46a9-b057-3997c275af4b\" time=\"309\"/>\n</testsuites>"
  },
  {
    "path": "examples/run-collections-in-directory.js",
    "content": "#!/usr/bin/env node\n/**\n * @fileOverview This sample code illustrates how one can read all collection files within a directory and run them\n * in parallel.\n */\nvar newman = require('../'), // require('newman')\n    fs = require('fs');\n\nfs.readdir('./examples', function (err, files) {\n    if (err) { throw err; }\n\n    // we filter all files with JSON file extension\n    files = files.filter(function (file) {\n        return (/^((?!(package(-lock)?))|.+)\\.json/).test(file);\n    });\n\n    // now we iterate on each file name and call newman.run using each file name\n    files.forEach(function (file) {\n        newman.run({\n            // we load collection using require. for better validation and handling\n            // JSON.parse could be used\n            collection: require(`${__dirname}/${file}`)\n        }, function (err) {\n            // finally, when the collection executes, print the status\n            console.info(`${file}: ${err ? err.name : 'ok'}!`);\n        });\n    }); // the entire flow can be made more elegant using `async` module\n});\n"
  },
  {
    "path": "examples/sample-collection.json",
    "content": "{\n  \"info\": {\n    \"name\": \"Sample Postman Collection\",\n    \"schema\": \"https://schema.getpostman.com/json/collection/v2.0.0/collection.json\",\n    \"description\": \"A sample collection to demonstrate collections as a set of related requests\"\n  },\n\n  \"item\": [{\n    \"name\": \"A simple GET request\",\n    \"event\": [{\n      \"listen\": \"test\",\n      \"script\": {\n        \"type\": \"text/javascript\",\n        \"exec\": [\n          \"pm.test('expect response be 200', function () {\",\n          \"    pm.response.to.be.ok\",\n          \"})\",\n          \"pm.test('expect response json contain args', function () {\",\n          \"    pm.expect(pm.response.json().args).to.have.property('source')\",\n          \"      .and.equal('newman-sample-github-collection')\",\n          \"})\"\n        ]\n      }\n    }],\n    \"request\": {\n      \"url\": \"https://postman-echo.com/get?source=newman-sample-github-collection\",\n      \"method\": \"GET\"\n    }\n  }, {\n    \"name\": \"A simple POST request\",\n    \"request\": {\n      \"url\": \"https://postman-echo.com/post\",\n      \"method\": \"POST\",\n      \"header\": [{\n        \"key\": \"Content-Type\",\n        \"value\": \"text/plain\"\n      }],\n      \"body\": {\n        \"mode\": \"raw\",\n        \"raw\": \"Duis posuere augue vel cursus pharetra. In luctus a ex nec pretium...\"\n      }\n    }\n  }, {\n    \"name\": \"A simple POST request with JSON body\",\n    \"request\": {\n      \"url\": \"https://postman-echo.com/post\",\n      \"method\": \"POST\",\n      \"header\": [{\n        \"key\": \"Content-Type\",\n        \"value\": \"application/json\"\n      }],\n      \"body\": {\n        \"mode\": \"raw\",\n        \"raw\": \"{\\\"text\\\":\\\"Duis posuere augue vel cursus pharetra. In luctus a ex nec pretium...\\\"}\"\n      }\n    }\n  }]\n}\n"
  },
  {
    "path": "examples/ssl-client-cert-list.json",
    "content": "[\n    {\n        \"name\": \"domain1\",\n        \"matches\": [\"https://test.domain1.com/*\", \"https://www.domain1/*\"],\n        \"key\": {\"src\": \"./client.domain1.key\"},\n        \"cert\": {\"src\": \"./client.domain1.crt\"},\n        \"passphrase\": \"changeme\"\n    },\n    {\n        \"name\": \"domain2\",\n        \"matches\": [\"https://domain2.com/*\"],\n        \"key\": {\"src\": \"./client.domain2.key\"},\n        \"cert\": {\"src\": \"./client.domain2.crt\"},\n        \"passphrase\": \"changeme\"\n    }\n]\n"
  },
  {
    "path": "examples/v1.postman_collection.json",
    "content": "{\n\t\"id\": \"c5f65caa-9e32-6546-ac10-9167d0996723\",\n\t\"name\": \"Sample Postman Collection\",\n\t\"description\": \"A sample collection to demonstrate collections as a set of related requests\",\n\t\"order\": [\n\t\t\"3845db20-6952-e442-f3b0-6211e2089b71\",\n\t\t\"ec098f7c-4e22-2fe9-e5c5-26f13016be84\",\n\t\t\"464bc62d-db90-7c58-1c28-ff0b5eac2f4f\"\n\t],\n\t\"folders\": [],\n\t\"owner\": \"640245\",\n\t\"hasRequests\": true,\n\t\"requests\": [\n\t\t{\n\t\t\t\"id\": \"3845db20-6952-e442-f3b0-6211e2089b71\",\n\t\t\t\"name\": \"A simple GET request\",\n\t\t\t\"description\": \"\",\n\t\t\t\"collectionId\": \"c5f65caa-9e32-6546-ac10-9167d0996723\",\n\t\t\t\"method\": \"GET\",\n\t\t\t\"headers\": \"\",\n\t\t\t\"data\": [],\n\t\t\t\"rawModeData\": \"\",\n\t\t\t\"tests\": \"tests['response code is 200'] = (responseCode.code === 200);\",\n\t\t\t\"preRequestScript\": \"\",\n\t\t\t\"url\": \"https://postman-echo.com/get?source=newman-sample-github-collection\"\n\t\t},\n\t\t{\n\t\t\t\"id\": \"464bc62d-db90-7c58-1c28-ff0b5eac2f4f\",\n\t\t\t\"name\": \"A simple POST request with JSON body\",\n\t\t\t\"description\": \"\",\n\t\t\t\"collectionId\": \"c5f65caa-9e32-6546-ac10-9167d0996723\",\n\t\t\t\"method\": \"POST\",\n\t\t\t\"headers\": \"Content-Type: application/json\",\n\t\t\t\"dataMode\": \"raw\",\n\t\t\t\"data\": [],\n\t\t\t\"rawModeData\": \"{\\\"text\\\":\\\"Duis posuere augue vel cursus pharetra. In luctus a ex nec pretium...\\\"}\",\n\t\t\t\"url\": \"https://postman-echo.com/post\"\n\t\t},\n\t\t{\n\t\t\t\"id\": \"ec098f7c-4e22-2fe9-e5c5-26f13016be84\",\n\t\t\t\"name\": \"A simple POST request\",\n\t\t\t\"description\": \"\",\n\t\t\t\"collectionId\": \"c5f65caa-9e32-6546-ac10-9167d0996723\",\n\t\t\t\"method\": \"POST\",\n\t\t\t\"headers\": \"Content-Type: text/plain\",\n\t\t\t\"dataMode\": \"raw\",\n\t\t\t\"data\": [],\n\t\t\t\"rawModeData\": \"Duis posuere augue vel cursus pharetra. In luctus a ex nec pretium...\",\n\t\t\t\"url\": \"https://postman-echo.com/post\"\n\t\t}\n\t]\n}"
  },
  {
    "path": "index.js",
    "content": "/**!\n * @license Copyright 2016 Postdot Technologies, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on\n * an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and limitations under the License.\n */\nmodule.exports = require('./lib');\n"
  },
  {
    "path": "lib/config/index.js",
    "content": "var _ = require('lodash'),\n    async = require('async'),\n\n    env = require('./process-env'),\n    rcfile = require('./rc-file');\n\n/**\n * Reads configuration from config file, environment variables and CLI arguments. The CLI arguments override environment\n * variables and environment variables override the configuration read from a file.\n *\n * @param {Object} overrides - Configuration overrides (these usually come from the CLI).\n * @param {Object} options - The wrapper object of settings used for selective configuration loading.\n * @param {String} options.command - Command name. Used for loading the required options from the config file.\n * @param {Boolean=} options.ignoreRcFile - If true, the RC file is ignored.\n * @param {Boolean=} options.ignoreProcessEnvironment - If true, the process environment variables are ignored.\n * @param {Object=} options.loaders - Custom loaders for specific configuration options.\n * @param {Function} callback - Is called after merging values from the overrides with the values from the rc file and\n * environment variables.\n * @returns {*}\n */\nmodule.exports.get = (overrides, options, callback) => {\n    !callback && _.isFunction(options) && (callback = options, options = {});\n\n    var loaders = options.loaders,\n        commonOptions = _.pick(overrides, ['postmanApiKey']);\n\n    async.waterfall([\n        // Load RC Files.\n        !options.ignoreRcFile ? rcfile.load : (cb) => {\n            return cb(null, {});\n        },\n        // Load Process Environment overrides\n        (fileOptions, cb) => {\n            fileOptions[options.command] && (fileOptions = fileOptions[options.command]);\n\n            return cb(null, _.merge(fileOptions, options.ignoreProcessEnvironment ? {} : env));\n        }\n    ], (err, options) => {\n        if (err) {\n            return callback(err);\n        }\n\n        options = _.mergeWith({}, options, overrides, (dest, src) => {\n            // If the newer value is a null, do not override it.\n            return (src === null) ? dest : undefined;\n        });\n\n        if (_.isEmpty(loaders)) {\n            return callback(null, options);\n        }\n        // sanitize environment option\n        if (!options.environment) {\n            options.environment = {};\n        }\n        // sanitize globals option\n        if (!options.globals) {\n            options.globals = {};\n        }\n\n        async.mapValues(options, (value, name, cb) => {\n            return (value && _.isFunction(loaders[name])) ? loaders[name](value, commonOptions, cb) : cb(null, value);\n        }, callback);\n    });\n};\n"
  },
  {
    "path": "lib/config/process-env.js",
    "content": "var envConfig = {}; // todo: read NEWMAN_* variables from process.env\n\nmodule.exports = envConfig;\n"
  },
  {
    "path": "lib/config/rc-file.js",
    "content": "/* eslint-disable no-process-env */\nvar _ = require('lodash'),\n    fs = require('fs'),\n    join = require('path').join,\n    async = require('async'),\n    util = require('../util'),\n    liquidJSON = require('liquid-json'),\n\n    /**\n     * Name of the directory that contains the file denoted by FILE_NAME.\n     *\n     * @type {String}\n     */\n    POSTMAN_CONFIG_DIR = 'postman',\n\n    /**\n     * Name of the file that contains Newman compliant confguration information.\n     *\n     * @type {String}\n     */\n    FILE_NAME = 'newmanrc';\n\n/**\n * Configuration loader to acquire run settings from a file present in the home directory: POSTMAN_CONFIG_DIR/FILE_NAME.\n *\n * @param {Function} callback - The callback function invoked to mark the completion of the config loading routine.\n * @returns {*}\n */\nmodule.exports.load = (callback) => {\n    var iswin = (/^win/).test(process.platform),\n        home = iswin ? process.env.USERPROFILE : process.env.HOME,\n\n        configFiles = [];\n\n    !iswin && configFiles.push(join('/etc', POSTMAN_CONFIG_DIR, FILE_NAME));\n    home && configFiles.push(join(home, '.' + POSTMAN_CONFIG_DIR, FILE_NAME));\n    configFiles.push(join(process.cwd(), '.' + FILE_NAME));\n\n    async.mapSeries(configFiles, (path, cb) => {\n        fs.readFile(path, (err, data) => {\n            if (err) {\n                return cb(null, {}); // err masked to avoid overpopulating terminal with missing .newmanrc messages\n            }\n            data && data.toString && (data = data.toString(util.detectEncoding(data)).trim());\n            try {\n                return cb(null, liquidJSON.parse(data));\n            }\n            catch (e) {\n                return cb(_.set(e, 'help', `The file at ${path} contains invalid data.`));\n            }\n        });\n    }, (err, files) => {\n        if (err) {\n            return callback(err);\n        }\n\n        return callback(null, _.merge.apply(this, files));\n    });\n};\n"
  },
  {
    "path": "lib/index.js",
    "content": "module.exports = {\n    run: require('./run')\n};\n"
  },
  {
    "path": "lib/node-version-check/index.js",
    "content": "var semver = require('semver'),\n    colors = require('colors/safe'),\n    pkg = require('../../package.json'),\n\n    /**\n     * The required node version from package.json.\n     *\n     * @type {String}\n     * @readOnly\n     */\n    requiredNodeVersion = pkg && pkg.engines && pkg.engines.node,\n\n    /**\n     * The current node version as detected from running process.\n     *\n     * @type {String}\n     * @readOnly\n     */\n    currentNodeVersion = process && process.version;\n\n// if either current or required version is not detected, we bail out\nif (!(requiredNodeVersion && currentNodeVersion)) {\n    return;\n}\n\n// we check semver satisfaction and throw error on mismatch\nif (!semver.satisfies(currentNodeVersion, requiredNodeVersion)) {\n    console.error([colors.red('newman:'), 'required node version', requiredNodeVersion].join(' '));\n    process.exit(1);\n}\n"
  },
  {
    "path": "lib/print/index.js",
    "content": "var format = require('util').format,\n    cliUtils = require('../reporters/cli/cli-utils'),\n    SPC = ' ',\n    BS = '\\b',\n    LF = '\\n',\n    WAIT_FRAMES = (/^win/).test(process.platform) ?\n        ['\\u2015', '\\\\', '|', '/'] :\n        ['⠄', '⠆', '⠇', '⠋', '⠙', '⠸', '⠰', '⠠', '⠰', '⠸', '⠙', '⠋', '⠇', '⠆'],\n    WAIT_FRAMES_SIZE = WAIT_FRAMES.length - 1,\n    WAIT_FRAMERATE = 100,\n    print;\n\n/**\n * Function that prints to stdout using standard NodeJS util.format, without end newline.\n *\n * @returns {print} - The result of context bound call to the run context, with all arguments passed.\n * @chainable\n */\nprint = function () {\n    return print.print.apply(this, arguments);\n};\n\n/**\n * Function that prints to stdout using standard NodeJS util.format, without end newline.\n *\n * @returns {print} - The updated print module wrapper, with unwait and unbuffer methods invoked.\n * @chainable\n */\nprint.print = function () {\n    print.waiting && print.unwait();\n    print._buffer && print.unbuffer();\n    process.stdout.write(format.apply(this, arguments));\n\n    return print;\n};\n\n/**\n * Print with a line feed at the end.\n *\n * @returns {print} - The updated print module wrapper, with unwait and unbuffer methods invoked.\n * @chainable\n */\nprint.lf = function () {\n    print.waiting && print.unwait();\n    print._buffer && print.unbuffer();\n    process.stdout.write(format.apply(this, arguments) + LF);\n\n    return print;\n};\n\n// store the starting frame during wait\nprint._waitPosition = 0;\n\n/**\n * Draw a spinner until next print statement is received.\n *\n * @param {Function=} color - Optional color function from `colors` module.\n * @returns {print} - The print module wrapper, with a key set as a setInterval label.\n * @chainable\n */\nprint.wait = function (color) {\n    print.unwait();\n\n    if (cliUtils.noTTY()) {\n        return print;\n    }\n\n    process.stdout.write(SPC);\n    print.waiting = setInterval(function () {\n        process.stdout.write(BS +\n            (color ? color(WAIT_FRAMES[print._waitPosition++]) : WAIT_FRAMES[print._waitPosition++]));\n        (print._waitPosition > WAIT_FRAMES_SIZE) && (print._waitPosition = 0); // move frame\n    }, WAIT_FRAMERATE);\n\n    return print;\n};\n\n/**\n * Stops a running spinner on CLI. It is automatically taken care of in most cases.\n *\n * @returns {print} - Returns the updated print module wrapper, with the cleared waiting label.\n * @chainable\n * @see print.wait\n */\nprint.unwait = function () {\n    if (print.waiting) {\n        print.waiting = clearInterval(print.waiting);\n        print._waitPosition = 0;\n        process.stdout.write('\\b');\n    }\n\n    return print;\n};\n\nprint._buffer = undefined;\n\n/**\n * Prints a message between start and end text. Consequent buffer calls does not print the start text and any other\n * unbuffered call or a delay of time prints the end text.\n *\n * @param {String} startText - The text to begin printing with.\n * @param {String} endText - The text that marks the end of the print routine.\n * @returns {print} - The update print module wrapper with internal buffer and buffering members redefined.\n * @chainable\n */\nprint.buffer = function (startText, endText) {\n    (print._buffer === undefined) && process.stdout.write(startText);\n    print._buffer = endText;\n\n    print._buferring && (print._buferring = clearTimeout(print._buferring));\n    print._buferring = setTimeout(print.unbuffer, 500);\n\n    process.stdout.write(format.apply(this, Array.prototype.splice.call(arguments, 2)));\n\n    return print;\n};\n\n/**\n * Prints text without flushing the buffer.\n *\n * @returns {print} - The update print module wrapper with unwait called.\n * @chainable\n * @see print.buffer\n */\nprint.nobuffer = function () {\n    print.unwait();\n    process.stdout.write(format.apply(this, arguments));\n\n    return print;\n};\n\n/**\n * Flushes the buffer.\n *\n * @returns {print} - The print module wrapper with internal private members: buffer, and buffering redefined.\n * @chainable\n * @see print.buffer\n */\nprint.unbuffer = function () {\n    print._buferring && (print._buferring = clearTimeout(print._buferring));\n    if (print._buffer) {\n        process.stdout.write(print._buffer);\n        print._buffer = undefined;\n    }\n\n    return print;\n};\n\nmodule.exports = print;\n"
  },
  {
    "path": "lib/reporters/cli/cli-utils-symbols.js",
    "content": "var IS_WINDOWS = (/^win/).test(process.platform),\n    subsets,\n    symbols;\n\n/**\n * A set of symbol groups for use in different situations: regular, windows friendly unicode, and plain text.\n *\n * @type {Object}\n */\nsubsets = {\n    regular: {\n        console: {\n            top: '┌',\n            middle: '│',\n            bottom: '└'\n        },\n        dot: '.',\n        folder: '❏',\n        root: '→',\n        sub: '↳',\n        ok: '✓',\n        error: '✖',\n        star: '★',\n        up: '↑',\n        down: '↓'\n    },\n    encoded: {\n        console: {\n            top: '\\u250C',\n            middle: '\\u2502',\n            bottom: '\\u2514'\n        },\n        dot: '.',\n        folder: '\\u25A1',\n        root: '\\u2192',\n        sub: '\\u2514',\n        ok: '\\u221A',\n        error: '\\u00D7',\n        star: '\\u2605',\n        up: '\\u2191',\n        down: '\\u2193'\n    },\n    plainText: {\n        console: {\n            top: '-',\n            middle: '|',\n            bottom: '-'\n        },\n        dot: '.',\n        folder: 'Folder',\n        root: 'Root',\n        sub: 'Sub-folder',\n        ok: 'Pass',\n        error: 'Fail',\n        star: '*',\n        up: '^',\n        down: 'v'\n    }\n};\n\n/**\n * A method that picks the appropriate set of CLI report symbols under a given set of run conditions.\n *\n * @param  {Boolean} disableUnicode - A flag to force plain text equivalents for CLI symbols if set to true.\n * @returns {Object} - The right set of symbols from subsets for the given conditions.\n * @todo Add additional parameter related to temp file read - writes\n */\nsymbols = function (disableUnicode) {\n    if (disableUnicode) {\n        return subsets.plainText;\n    }\n    if (IS_WINDOWS) { // modify symbols for windows platforms\n        return subsets.encoded;\n    }\n\n    return subsets.regular;\n};\n\nmodule.exports = symbols;\n"
  },
  {
    "path": "lib/reporters/cli/cli-utils.js",
    "content": "var inspect = require('util').inspect,\n    wrap = require('word-wrap'),\n    symbols = require('./cli-utils-symbols'),\n\n    cliUtils;\n\n// set styling for inspect options\ninspect.styles.string = 'grey';\ninspect.styles.name = 'white';\n\ncliUtils = {\n\n    /**\n     * A helper method that picks the right set of symbols for the given set of run conditions.\n     *\n     * @type {Function}\n     */\n    symbols: symbols,\n\n    /**\n     * A set of blank CLI table symbols (default).\n     *\n     * @type {Object}\n     */\n    cliTableTemplate_Blank: {\n        top: '',\n        'top-mid': '',\n        'top-left': '',\n        'top-right': '',\n        bottom: '',\n        'bottom-mid': '',\n        'bottom-left': '',\n        'bottom-right': '',\n        middle: '',\n        mid: ' ',\n        'mid-mid': '',\n        'mid-left': '',\n        'mid-right': '',\n        left: '',\n        'left-mid': '',\n        'left-left': '',\n        'left-right': '',\n        right: '',\n        'right-mid': '',\n        'right-left': '',\n        'right-right': ''\n    },\n\n    /**\n     * A set of fallback CLI table construction symbols, used when unicode has been disabled.\n     *\n     * @type {Object}\n     */\n    cliTableTemplateFallback: {\n        top: '-',\n        'top-mid': '-',\n        'top-left': '-',\n        'top-right': '-',\n        bottom: '-',\n        'bottom-mid': '-',\n        'bottom-left': '-',\n        'bottom-right': '-',\n        middle: '|',\n        mid: '-',\n        'mid-mid': '+',\n        'mid-left': '-',\n        'mid-right': '-',\n        left: '|',\n        'left-mid': '-',\n        'left-left': '-',\n        'left-right': '-',\n        right: '|',\n        'right-mid': '-',\n        'right-left': '-',\n        'right-right': '-'\n    },\n\n    /**\n     * A CLI utility helper method that perfoms left padding on an input string.\n     *\n     * @param {String} nr - The string to be padded.\n     * @param {Number} n - The length of the field, in which to left pad the input string.\n     * @param {String=} str - An optional string used for padding the input string. Defaults to '0'.\n     * @returns {String} - The resultant left padded string.\n     */\n    padLeft: function (nr, n, str) {\n        return Array(n - String(nr).length + 1).join(str || '0') + nr;\n    },\n\n    /**\n     * A CLI utility helper method that checks for the non TTY compliance of the current run environment.\n     *\n     * color:     |  noTTY:\n     * 'on'      -> false\n     * 'off'     -> true\n     * otherwise -> Based on isTTY.\n     *\n     * @param {String} color - A flag to indicate usage of the --color option.\n     * @returns {Boolean} - A boolean value depicting the result of the noTTY check.\n     */\n    noTTY: function (color) {\n        return (color === 'off') || (color !== 'on') && (!process.stdout.isTTY);\n    },\n\n    /**\n     * A CLI utility helper method that generates a color inspector function for CLI reports.\n     *\n     * @param {Object} runOptions - The set of run options acquired via the runner.\n     * @returns {Function} - A function to perform utils.inspect, given a sample item, under pre-existing options.\n     */\n    inspector: function (runOptions) {\n        var dimension = cliUtils.dimension(),\n            options = {\n                depth: 25,\n\n                maxArrayLength: 100, // only supported in Node v6.1.0 and up: https://github.com/nodejs/node/pull/6334\n\n                colors: !cliUtils.noTTY(runOptions.color),\n\n                // note that similar dimension calculation is in utils.wrapper\n                // only supported in Node v6.3.0 and above: https://github.com/nodejs/node/pull/7499\n                breakLength: ((dimension.exists && (dimension.width > 20)) ? dimension.width : 60) - 16\n            };\n\n        return function (item) {\n            return inspect(item, options);\n        };\n    },\n\n    /**\n     * A CLI utility helper method to provide content wrapping functionality for CLI reports.\n     *\n     * @returns {Function} - A sub-method to wrap content, given a piece of text, and indent value.\n     */\n    wrapper: function () {\n        var dimension = cliUtils.dimension(),\n            // note that similar dimension calculation is in utils.wrapper\n            width = ((dimension.exists && (dimension.width > 20)) ? dimension.width : 60) - 6;\n\n        return function (text, indent) {\n            return wrap(text, {\n                indent: indent,\n                width: width,\n                cut: true\n            });\n        };\n    },\n\n    /**\n     * A CLI utility helper method to compute and scae the size of the CLI table to be displayed.\n     *\n     * @returns {Object} - A set of properties: width, height, and TTY existence.\n     */\n    dimension: function () {\n        var tty,\n            width,\n            height;\n\n        try { tty = require('tty'); }\n        catch (e) { tty = null; }\n\n        if (tty && tty.isatty(1) && tty.isatty(2)) {\n            if (process.stdout.getWindowSize) {\n                width = process.stdout.getWindowSize(1)[0];\n                height = process.stdout.getWindowSize(1)[1];\n            }\n            else if (tty.getWindowSize) {\n                width = tty.getWindowSize()[1];\n                height = tty.getWindowSize()[0];\n            }\n            else if (process.stdout.columns && process.stdout.rows) {\n                height = process.stdout.rows;\n                width = process.stdout.columns;\n            }\n        }\n\n        return {\n            exists: !(Boolean(process.env.CI) || !process.stdout.isTTY), // eslint-disable-line no-process-env\n            width: width,\n            height: height\n        };\n    }\n};\n\nmodule.exports = cliUtils;\n"
  },
  {
    "path": "lib/reporters/cli/index.js",
    "content": "var _ = require('lodash'),\n    sdk = require('postman-collection'),\n    colors = require('colors/safe'),\n    Table = require('cli-table3'),\n    format = require('util').format,\n\n    util = require('../../util'),\n    cliUtils = require('./cli-utils'),\n    print = require('../../print'),\n    pad = cliUtils.padLeft,\n\n    LF = '\\n',\n    SPC = ' ',\n    DOT = '.',\n    E = '',\n\n    CACHED_TIMING_PHASE = '(cache)',\n    TIMING_TABLE_HEADERS = {\n        prepare: 'prepare',\n        wait: 'wait',\n        dns: 'dns-lookup',\n        tcp: 'tcp-handshake',\n        secureHandshake: 'ssl-handshake',\n        firstByte: 'transfer-start',\n        download: 'download',\n        process: 'process',\n        total: 'total'\n    },\n    BODY_CLIP_SIZE = 2048,\n\n    PostmanCLIReporter,\n    timestamp,\n    extractSNR;\n\n// sets theme for colors for console logging\ncolors.setTheme({\n    log: 'grey',\n    info: 'cyan',\n    warn: 'yellow',\n    debug: 'blue',\n    error: 'red'\n});\n\nextractSNR = function (executions) {\n    var snr;\n\n    // eslint-disable-next-line lodash/collection-method-value\n    _.isArray(executions) && _.forEachRight(executions, function (execution) {\n        var nextReq = _.get(execution, 'result.return.nextRequest');\n\n        if (nextReq) {\n            snr = nextReq;\n\n            return false;\n        }\n    });\n\n    return snr;\n};\n\n/**\n * CLI reporter\n *\n * @param {EventEmitter} emitter - An EventEmitter instance with event handler attachers to trigger reporting.\n * @param {Object} reporterOptions - CLI reporter options object.\n * @param {Boolean=} reporterOptions.silent - Boolean flag to turn off CLI reporting altogether, if set to true.\n * @param {Boolean=} reporterOptions.noAssertions - Boolean flag to turn off assertion reporting, if set to true.\n * @param {Boolean=} reporterOptions.noSuccessAssertions - Boolean flag, if true, turn off report successful assertions.\n * @param {Boolean=} reporterOptions.noSummary - Boolean flag to turn off summary reporting altogether, if set to true.\n * @param {Boolean=} reporterOptions.noFailures - Boolean flag to turn off failure reporting altogether, if set to true.\n * @param {Boolean=} reporterOptions.noConsole - Boolean flag to turn off console logging, if set to true.\n * @param {Boolean=} reporterOptions.noBanner - Boolean flag to turn off newman banner, if set to true.\n * @param {Object} options - A set of generic collection run options.\n * @returns {*}\n */\nPostmanCLIReporter = function (emitter, reporterOptions, options) {\n    var currentGroup = options.collection,\n        inspect = cliUtils.inspector(options),\n        wrap = cliUtils.wrapper(),\n        symbols = cliUtils.symbols(options.disableUnicode);\n\n    // respect silent option to not report anything\n    if (reporterOptions.silent || options.silent) {\n        return; // we simply do not register anything!\n    }\n\n    // disable colors based on `noTTY`.\n    cliUtils.noTTY(options.color) && colors.disable();\n\n    // we register the `done` listener first so that in case user does not want to show results of collection run, we\n    // simply do not register the other events\n    emitter.on('done', function () {\n        // for some reason, if there is no run summary, it is unexpected and hence don't validate this\n        var run = this.summary.run;\n\n        // show the summary table (provided option does not say it is not to be shown)\n        if (!reporterOptions.noSummary) {\n            print(LF + PostmanCLIReporter.parseStatistics(run.stats, run.timings, run.transfers, options) + LF);\n        }\n\n        // show the failures table (provided option does not say it is not to be shown)\n        if (!reporterOptions.noFailures && run.failures && run.failures.length) {\n            print(LF + PostmanCLIReporter.parseFailures(run.failures) + LF);\n        }\n    });\n\n    emitter.on('start', function () {\n        var collectionIdentifier = currentGroup && (currentGroup.name || currentGroup.id);\n\n        if (!reporterOptions.noBanner) {\n            // print the newman banner\n            print('%s\\n\\n', colors.reset('newman'));\n        }\n\n        // print the collection name and newman info line\n        collectionIdentifier && print.lf('%s', colors.reset(collectionIdentifier));\n    });\n\n    emitter.on('beforeIteration', function (err, o) {\n        if (err || o.cursor.cycles <= 1) {\n            return; // do not print iteration banner if it is a single iteration run\n        }\n\n        // print the iteration info line\n        print.lf(LF + colors.gray.underline('Iteration %d/%d'), o.cursor.iteration + 1, o.cursor.cycles);\n    });\n\n    emitter.on('test', function (err, o) {\n        if (err) {\n            return;\n        }\n        var snr = extractSNR(o.executions);\n\n        if (snr) {\n            print.lf(LF + colors.gray('Attempting to set next request to', snr));\n        }\n    });\n\n    emitter.on('beforeItem', function (err, o) {\n        if (err) { return; }\n\n        var itemGroup = o.item.parent(),\n            root = !itemGroup || (itemGroup === options.collection);\n\n        // in case this item belongs to a separate folder, print that folder name\n        if (itemGroup && (currentGroup !== itemGroup)) {\n            !root && print('\\n%s %s', symbols.folder, colors.reset(util.getFullName(itemGroup)));\n\n            // set the flag that keeps track of the currently running group\n            currentGroup = itemGroup;\n        }\n\n        // we print the item name. the symbol prefix denotes if the item is in root or under folder.\n        // @todo - when we do indentation, we would not need symbolic representation\n        o.item && print.lf('\\n%s %s', (root ?\n            symbols.root : symbols.sub), colors.reset(o.item.name || E));\n    });\n\n    // print out the request name to be executed and start a spinner\n    emitter.on('beforeRequest', function (err, o) {\n        if (err || !o.request) { return; }\n\n        if (reporterOptions.showTimestamps) {\n            var currentTime = new Date();\n\n            timestamp = '[' + currentTime.toLocaleString() + ']';\n            print('  %s  %s %s ',\n                colors.gray(timestamp),\n                colors.gray(o.request.method),\n                colors.gray(o.request.url.toString()));\n        }\n        else {\n            print('  %s %s ',\n                colors.gray(o.request.method),\n                colors.gray(o.request.url.toString()));\n        }\n\n        !options.disableUnicode && print().wait(colors.gray);\n    });\n\n    // output the response code, reason and time\n    emitter.on('request', function (err, o) {\n        if (err) {\n            print.lf(colors.red('[errored]'));\n            print.lf(colors.red('     %s'), err.message);\n\n            return;\n        }\n\n        if (!(o.request && o.response)) {\n            print.lf(colors.red('[errored]'));\n            print.lf(colors.red('     %s'), 'Internal error! Could not read response data.');\n\n            return;\n        }\n\n        // quickly print out basic non verbose response meta and exit\n        if (!options.verbose) {\n            print.lf(colors.gray('[%d %s, %s, %s]'), o.response.code, o.response.reason(),\n                util.filesize(o.response.size().total), util.prettyms(o.response.responseTime));\n\n            return;\n        }\n\n        // this point onwards the output is verbose. a tonne of variables are created here for\n        // keeping the output clean and readable\n\n        let req = o.request,\n            res = o.response,\n\n            // set values here with abundance of caution to avoid erroring out\n            reqSize = util.filesize(req.size().total),\n            resSize = util.filesize(res.size().total),\n            code = res.code,\n            reason = res.reason(),\n            mime = res.contentInfo() || {},\n            timings = _.last(_.get(o, 'history.execution.data')),\n\n            reqHeadersLen = _.get(req, 'headers.members.length'),\n            resHeadersLen = _.get(res, 'headers.members.length'),\n\n            resTime = util.prettyms(res.responseTime || 0),\n\n            reqText = (options.verbose && req.body) ? req.body.toString() : E,\n            reqTextLen = req.size().body || Buffer.byteLength(reqText),\n\n            resText = options.verbose ? res.text() : E,\n            resTextLen = res.size().body || Buffer.byteLength(resText),\n\n            reqBodyMode = _.get(req, 'body.mode', ''),\n            resSummary = [\n                `${mime.contentType}`,\n                `${mime.mimeType}`,\n                `${mime.mimeFormat}`,\n                `${mime.charset}`\n            ].join(` ${colors.gray(symbols.star)} `);\n\n\n        print.lf(SPC); // also flushes out the circling progress icon\n\n        // for clean readability of code. this section compiles the cli string for one line of\n        // req-res combined summary. this looks somewhat like below:\n        // >> 200 OK ★ 979ms time ★ 270B↑ 793B↓ size ★ 7↑ 7↓ headers ★ 0 cookies\n        print.lf(SPC + SPC + [\n            `${code} ${reason}`,\n            `${resTime} ${colors.gray('time')}`,\n            `${reqSize}${colors.gray(symbols.up)} ${resSize}${colors.gray(symbols.down)} ${colors.gray('size')}`,\n            `${reqHeadersLen}${colors.gray(symbols.up)} ` +\n                `${resHeadersLen}${colors.gray(symbols.down)} ${colors.gray('headers')}`,\n            `${_.get(res, 'cookies.members.length')} ${colors.gray('cookies')}`\n        ].join(` ${colors.gray(symbols.star)} `));\n\n        // print request body\n        if (reqTextLen) {\n            // truncate very large request (is 2048 large enough?)\n            if (reqTextLen > BODY_CLIP_SIZE) {\n                reqText = reqText.substr(0, BODY_CLIP_SIZE) +\n                    colors.brightWhite(`\\n(showing ${util.filesize(BODY_CLIP_SIZE)}/${util.filesize(reqTextLen)})`);\n            }\n\n            reqText = wrap(reqText, `  ${colors.white(symbols.console.middle)} `);\n            // eslint-disable-next-line max-len\n            print.buffer(`  ${colors.white(symbols.console.top)} ${colors.white(symbols.up)} ${reqBodyMode} ${colors.gray(symbols.star)} ${util.filesize(reqTextLen)}\\n`,\n                colors.white(`  ${symbols.console.bottom}`))\n                // tweak the message to ensure that its surrounding is not brightly coloured.\n                // also ensure to remove any blank lines generated due to util.inspect\n                .nobuffer(colors.gray(reqText.replace(/\\n\\s*\\n/g, LF) + LF));\n\n            print.lf(SPC); // visual tweak: flushes out the buffer of wrapping body above\n        }\n\n        // print response body\n        if (resTextLen) {\n            // truncate very large response (is 2048 large enough?)\n            if (resTextLen > BODY_CLIP_SIZE) {\n                resText = resText.substr(0, BODY_CLIP_SIZE) +\n                    colors.brightWhite(`\\n(showing ${util.filesize(BODY_CLIP_SIZE)}/${util.filesize(resTextLen)})`);\n            }\n\n            resText = wrap(resText, `  ${colors.white(symbols.console.middle)} `);\n            // eslint-disable-next-line max-len\n            print.buffer(`  ${colors.white(symbols.console.top)} ${colors.white(symbols.down)} ${resSummary} ${colors.gray(symbols.star)} ${util.filesize(resTextLen)}\\n`,\n                colors.white(`  ${symbols.console.bottom}`))\n                // tweak the message to ensure that its surrounding is not brightly coloured.\n                // also ensure to remove any blank lines generated due to util.inspect\n                .nobuffer(colors.gray(resText.replace(/\\n\\s*\\n/g, LF) + LF));\n        }\n        // print the line of response body meta one liner if there is no response body\n        // if there is one, we would already print it across the body braces above.\n        else {\n            // we need to do some newline related shenanigans here so that the output looks clean\n            // in the absence of the request body block\n            print.lf(`  ${symbols.down} ${resSummary}`);\n        }\n\n        // print timing info of the request\n        timings = timings && timings.timings; // if there are redirects, get timings for the last request sent\n        if (timings) {\n            // adds nice units to all time data in the object\n            let timingPhases = util.beautifyTime(sdk.Response.timingPhases(timings)),\n                timingTable = new Table({\n                    chars: _.defaults({ mid: '', middle: '' }, cliUtils.cliTableTemplate_Blank),\n                    colAligns: _.fill(Array(_.size(timingPhases)), 'left'),\n                    style: { 'padding-left': 2 }\n                });\n\n            timingPhases = _.transform(TIMING_TABLE_HEADERS, (result, header, key) => {\n                if (_.has(timingPhases, key)) {\n                    result.headers.push(colors.white(header));\n                    result.values.push(colors.log(timingPhases[key] || CACHED_TIMING_PHASE));\n                }\n            }, { headers: [], values: [] });\n\n\n            timingTable.push(timingPhases.headers); // add name of phases in the table\n            timingTable.push(timingPhases.values); // add time of phases in the table\n\n            print(LF + timingTable + LF + LF);\n        }\n    });\n\n    // Print script errors in real time\n    emitter.on('script', function (err, o) {\n        err && print.lf(colors.red.bold('%s⠄ %s in %s-script'), pad(this.summary.run.failures.length, 3, SPC), err.name,\n            o.event && o.event.listen || 'unknown');\n    });\n\n    !reporterOptions.noAssertions && emitter.on('assertion', function (err, o) {\n        var passed = !err;\n\n        // handle skipped test display\n        if (o.skipped && !reporterOptions.noSuccessAssertions) {\n            print.lf('%s %s', colors.cyan('  - '), colors.cyan('[skipped] ' + o.assertion));\n\n            return;\n        }\n\n        if (passed && reporterOptions.noSuccessAssertions) {\n            return;\n        }\n\n        // print each test assertions\n        if (reporterOptions.showTimestamps) {\n            timestamp = '[' + new Date().toLocaleTimeString() + ']';\n            print.lf('  %s%s %s', colors.gray(timestamp), passed ? colors.green(`  ${symbols.ok} `) :\n                colors.red.bold(pad(this.summary.run.failures.length, 2, SPC) + symbols.dot), passed ?\n                colors.gray(o.assertion) : colors.red.bold(o.assertion));\n        }\n        else {\n            print.lf('%s %s', passed ? colors.green(`  ${symbols.ok} `) :\n                colors.red.bold(pad(this.summary.run.failures.length, 3, SPC) + symbols.dot), passed ?\n                colors.gray(o.assertion) : colors.red.bold(o.assertion));\n        }\n    });\n\n    // show user console logs in a neatly formatted way (provided user has not disabled the same)\n    !reporterOptions.noConsole && emitter.on('console', function (err, o) {\n        if (err) { return; }\n\n        var color = colors[o.level] || colors.gray,\n            message;\n\n        // we first merge all messages to a string. while merging we run the values to util.inspect to colour code the\n        // messages based on data type\n        message = wrap(_.reduce(o.messages, function (log, message) { // wrap the whole message to the window size\n            return (log += (log ? colors.white(', ') : '') + inspect(message));\n        }, E), `  ${color(symbols.console.middle)} `); // add an indentation line at the beginning\n\n        // print the timestamp if the falg is present\n        if (reporterOptions.showTimestamps) {\n            print(LF + '  %s', colors.gray('[' + new Date().toLocaleTimeString() + ']' + LF));\n        }\n\n        print.buffer(color(`  ${symbols.console.top}\\n`), color(`  ${symbols.console.bottom}\\n`))\n            // tweak the message to ensure that its surrounding is not brightly coloured.\n            // also ensure to remove any blank lines generated due to util.inspect\n            .nobuffer(colors.gray(message.replace(/\\n\\s*\\n/g, LF) + LF));\n    });\n};\n\n_.assignIn(PostmanCLIReporter, {\n\n    // @todo: change function signature to accept run object and options, thereby reducing parameters\n    /**\n     * A CLI reporter method to parse collection run statistics into a CLI table.\n     *\n     * @param {Object} stats - The cumulative collection run status object.\n     * @param {Object} stats.iterations - A set of values for total, pending, and failed iterations.\n     * @param {Number} stats.iterations.total - Total iterations in the current collection run.\n     * @param {Number} stats.iterations.pending - Pending iterations in the current collection run.\n     * @param {Number} stats.iterations.failed - Failed iterations in the current collection run.\n     * @param {Object} stats.requests - A set of values for total, pending, and failed requests.\n     * @param {Number} stats.requests.total - Total requests in the current collection run.\n     * @param {Number} stats.requests.pending - Pending requests in the current collection run.\n     * @param {Number} stats.requests.failed - Failed requests in the current collection run.\n     * @param {Object} stats.testScripts - A set of values for total, pending, and failed testScripts.\n     * @param {Number} stats.testScripts.total - Total testScripts in the current collection run.\n     * @param {Number} stats.testScripts.pending - Pending testScripts in the current collection run.\n     * @param {Number} stats.testScripts.failed - Failed testScripts in the current collection run.\n     * @param {Object} stats.prerequestScripts - A set of values for total, pending, and failed prerequestScripts.\n     * @param {Number} stats.prerequestScripts.total - Total prerequestScripts in the current collection run.\n     * @param {Number} stats.prerequestScripts.pending - Pending prerequestScripts in the current collection run.\n     * @param {Number} stats.prerequestScripts.failed - Failed prerequestScripts in the current collection run.\n     * @param {Object} stats.assertions - A set of values for total, pending, and failed assertions.\n     * @param {Number} stats.assertions.total - Total assertions in the current collection run.\n     * @param {Number} stats.assertions.pending - Pending assertions in the current collection run.\n     * @param {Number} stats.assertions.failed - Failed assertions in the current collection run.\n     * @param {Object} timings - A set of values for the timings of the current collection run.\n     * @param {Number} timings.completed - The end timestamp for the current collection run.\n     * @param {Number} timings.started - The start timestamp for the current collection run\n     * @param {String} timings.responseAverage - The average response time across all requests\n     * @param {String} timings.responseMin - The minimum response time across all requests\n     * @param {String} timings.responseMax - The maximum response time across all requests\n     * @param {String} timings.responseSd - Standard deviation of response time across all requests\n     * @param {String} timings.dnsAverage - The average DNS lookup time of the run\n     * @param {String} timings.dnsMin - The minimum DNS lookup time of the run\n     * @param {String} timings.dnsMax - The maximum DNS lookup time of the run\n     * @param {String} timings.dnsSd - Standard deviation of DNS lookup time of the run\n     * @param {String} timings.firstByteAverage - The average first byte time of the run\n     * @param {String} timings.firstByteMin - The minimum first byte time of the run\n     * @param {String} timings.firstByteMax - The maximum first byte time of the run\n     * @param {String} timings.firstByteSd - Standard deviation of first byte time of the run\n     * @param {Object} transfers - A set of details on the network usage for the current collection run.\n     * @param {String} transfers.responseTotal - The net extent of the data transfer achieved during the collection run.\n     * @param {Object} options - The set of generic collection run options.\n     * @returns {Table} - The constructed collection run statistics table.\n     */\n    parseStatistics (stats, timings, transfers, options) {\n        var summaryTable,\n            style = { head: [] };\n\n        if (cliUtils.noTTY(options.color)) {\n            style.border = [];\n        }\n\n        // create the summary table\n        summaryTable = new Table({\n            chars: options.disableUnicode && cliUtils.cliTableTemplateFallback,\n            style: style,\n            head: [E, 'executed', '  failed'],\n            colAligns: ['right', 'right', 'right'],\n            colWidths: [25]\n        });\n\n        // add specific rows to show in summary\n        stats && _.forEach([{\n            source: 'iterations',\n            label: 'iterations'\n        }, {\n            source: 'requests',\n            label: 'requests'\n        }, {\n            source: 'testScripts',\n            label: 'test-scripts'\n        }, {\n            source: 'prerequestScripts',\n            label: 'prerequest-scripts'\n        }, {\n            source: 'assertions',\n            label: 'assertions'\n        }], function (row) {\n            var metric = stats[row.source],\n                label = row.label;\n\n            // colour the label based on the failure or pending count of the metric\n            label = metric.failed ? colors.red(label) : (metric.pending ? label : colors.green(label));\n\n            // push the statistics\n            summaryTable.push([\n                label,\n                metric.total,\n                (metric.failed ? colors.red(metric.failed) : metric.failed)\n                // @todo - add information of pending scripts\n                // (metric.failed ? colors.red(metric.failed) : metric.failed) +\n                //     (metric.pending ? format(' (%d pending)', metric.pending) : E)\n            ]);\n        });\n\n        // add the total execution time to summary\n        timings && summaryTable.push([{\n            colSpan: 3,\n            content: format('total run duration: %s', util.prettyms(timings.completed - timings.started)),\n            hAlign: 'left' // since main style was set to right\n        }]);\n\n        // add row to show total data received\n        transfers && summaryTable.push([{\n            colSpan: 3,\n            content: format('total data received: %s (approx)', util.filesize(transfers.responseTotal)),\n            hAlign: 'left'\n        }]);\n\n        // add rows containing average time of different request phases\n        timings && _.forEach({\n            response: 'average response time:',\n            dns: 'average DNS lookup time:',\n            firstByte: 'average first byte time:'\n        }, (value, key) => {\n            timings[`${key}Average`] && summaryTable.push([{\n                colSpan: 3,\n                content: format(`${value} %s [min: %s, max: %s, s.d.: %s]`,\n                    util.prettyms(timings[`${key}Average`]),\n                    util.prettyms(timings[`${key}Min`]),\n                    util.prettyms(timings[`${key}Max`]),\n                    util.prettyms(timings[`${key}Sd`])),\n                hAlign: 'left'\n            }]);\n        });\n\n        return summaryTable;\n    },\n\n    /**\n     * A CLI reporter method to parse collection run failure statistics into a CLI table.\n     *\n     * @param  {Array} failures - An array of failure objects.\n     * @returns {Table} - The constructed CLI failure Table object.\n     */\n    parseFailures (failures) {\n        var failureTable = new Table({\n            head: [{\n                hAlign: 'right',\n                content: colors.red.underline('#')\n            }, colors.red.underline('failure'),\n            colors.red.underline('detail')],\n            chars: cliUtils.cliTableTemplate_Blank,\n            wordWrap: true,\n            colAligns: ['right'],\n            colWidths: cliUtils.noTTY() ? [] : (function (size, indexOrder) {\n                var colWidths = [];\n\n                if (size.exists && size.width && (size.width > 20)) {\n                    colWidths[0] = indexOrder + 3;\n                    colWidths[1] = parseInt((size.width - colWidths[0]) * 0.2, 10);\n                    colWidths[2] = parseInt(size.width - (colWidths[0] + colWidths[1] + 5), 10);\n                }\n\n                return colWidths;\n            }(cliUtils.dimension(), Number(failures.length.toString().length)))\n        });\n\n        _.forEach(failures, function (failure, index) {\n            var name = failure.error && failure.error.name || E,\n                message = failure.error && failure.error.test || E;\n\n            // augment name with iteration information\n            failure.cursor && (failure.cursor.cycles > 1) &&\n                (name += LF + colors.gray('iteration: ' + (failure.cursor.iteration + 1)));\n\n            // include the assertion error message in the failure details\n            failure.error && (message += LF + colors.gray(failure.error.message || E));\n\n            // augment the message with stack information\n            failure.at && (message += LF + colors.gray('at ' + failure.at));\n\n            // augment message with item information\n            failure.source &&\n                (message += format(colors.gray('\\ninside \"%s\"'), util.getFullName(failure.source)));\n\n            failureTable.push([pad(Number(index + 1), Number(failures.length.toString().length)).toString() +\n                DOT, name, message]);\n        });\n\n        return failureTable;\n    }\n});\n\n// Mark the CLI reporter as dominant, so that no two dominant reporters are together\nPostmanCLIReporter.prototype.dominant = true;\n\nmodule.exports = PostmanCLIReporter;\n"
  },
  {
    "path": "lib/reporters/emojitrain.js",
    "content": "var SmileyReporter;\n\n/**\n * Fills your collection run (read life) with a bunch of Emojis 😀.\n *\n * @param {Object} newman - The collection run object with event handling hooks to enable reporting.\n * @param {Object} reporterOptions - A set of reporter specific run options.\n * @param {Object} options - A set of generic collection run options.\n * @returns {*}\n */\nSmileyReporter = function (newman, reporterOptions, options) {\n    if (options.silent || reporterOptions.silent) {\n        return;\n    }\n\n    var fails = {},\n        noteFailure;\n\n    noteFailure = function (err, args) {\n        err && (fails[args.cursor.ref] = true);\n    };\n\n    newman.on('script', noteFailure);\n    newman.on('request', noteFailure);\n    newman.on('assertion', noteFailure);\n\n    newman.on('item', function (err, args) {\n        process.stdout.write((err || fails[args.cursor.ref]) ? '😢 ' : '😀 ');\n    });\n\n    newman.on('done', function (err) {\n        console.info((err || Object.keys(fails).length) ? ' 😭' : ' 😍');\n    });\n};\n\nSmileyReporter.prototype.dominant = true;\nmodule.exports = SmileyReporter;\n"
  },
  {
    "path": "lib/reporters/json/index.js",
    "content": "var _ = require('lodash');\n\n/**\n * Reporter that simply dumps the summary object to file (default: newman-run-report.json).\n *\n * @param {Object} newman - The collection run object, with event hooks for reporting run details.\n * @param {Object} options - A set of collection run options.\n * @param {String} options.export - The path to which the summary object must be written.\n * @returns {*}\n */\nmodule.exports = function (newman, options) {\n    newman.on('beforeDone', function (err, o) {\n        if (err) { return; }\n\n        newman.exports.push({\n            name: 'json-reporter',\n            default: 'newman-run-report.json',\n            path: options.export,\n            content: JSON.stringify(_.omit(o.summary, 'exports'), 0, 2)\n        });\n    });\n};\n"
  },
  {
    "path": "lib/reporters/junit/index.js",
    "content": "var _ = require('lodash'),\n    xml = require('xmlbuilder'),\n\n    util = require('../../util'),\n    JunitReporter,\n\n    /**\n     * Normalizes the name of a test suite to a valid class name.\n     *\n     * @private\n     * @param {String} name - The name of the test suite.\n     * @returns {String} - The class name for the test suite.\n     */\n    getClassName = (name) => {\n        return _.upperFirst(_.camelCase(name).replace(/\\W/g, ''));\n    };\n\n/**\n * A function that creates raw XML to be written to Newman JUnit reports.\n *\n * @param {Object} newman - The collection run object, with a event handler setter, used to enable event wise reporting.\n * @param {Object} reporterOptions - A set of JUnit reporter run options.\n * @param {String=} reporterOptions.export - Optional custom path to create the XML report at.\n * @returns {*}\n */\nJunitReporter = function (newman, reporterOptions) {\n    newman.on('beforeDone', function () {\n        var report = _.get(newman, 'summary.run.executions'),\n            collection = _.get(newman, 'summary.collection'),\n            cache,\n            root,\n            testSuitesExecutionTime = 0,\n            executionTime = 0,\n            timestamp,\n            classname;\n\n        if (!report) {\n            return;\n        }\n\n        classname = getClassName(collection.name);\n\n        root = xml.create('testsuites', { version: '1.0', encoding: 'UTF-8' });\n        root.att('name', collection.name);\n        root.att('tests', _.get(newman, 'summary.run.stats.tests.total', 'unknown'));\n\n        cache = _.transform(report, function (accumulator, execution) {\n            accumulator[execution.item.id] = accumulator[execution.id] || [];\n            accumulator[execution.item.id].push(execution);\n        }, {});\n\n        timestamp = new Date(_.get(newman, 'summary.run.timings.started')).toISOString();\n\n        _.forEach(cache, function (executions, itemId) {\n            var suite = root.ele('testsuite'),\n                currentItem,\n                tests = {},\n                errors = 0,\n                failures = 0,\n                errorMessages;\n\n            collection.forEachItem(function (item) {\n                (item.id === itemId) && (currentItem = item);\n            });\n\n            if (!currentItem) { return; }\n\n            suite.att('name', util.getFullName(currentItem));\n            suite.att('id', currentItem.id);\n\n            suite.att('timestamp', timestamp);\n\n            _.forEach(executions, function (execution) {\n                var iteration = execution.cursor.iteration,\n                    errored,\n                    msg = `Iteration: ${iteration}\\n`;\n\n                // Process errors\n                if (execution.requestError) {\n                    ++errors;\n                    errored = true;\n                    msg += ('RequestError: ' + (execution.requestError.stack) + '\\n');\n                }\n                msg += '\\n---\\n';\n                _.forEach(['testScript', 'prerequestScript'], function (prop) {\n                    _.forEach(execution[prop], function (err) {\n                        if (err.error) {\n                            ++errors;\n                            errored = true;\n                            msg = (msg + prop + 'Error: ' + (err.error.stack || err.error.message));\n                            msg += '\\n---\\n';\n                        }\n                    });\n                });\n\n                if (errored) {\n                    errorMessages = _.isString(errorMessages) ? (errorMessages + msg) : msg;\n                }\n\n                // Process assertions\n                _.forEach(execution.assertions, function (assertion) {\n                    var name = assertion.assertion,\n                        err = assertion.error;\n\n                    if (err) {\n                        ++failures;\n                        (_.isArray(tests[name]) ? tests[name].push(err) : (tests[name] = [err]));\n                    }\n                    else {\n                        tests[name] = [];\n                    }\n                });\n                if (execution.assertions) {\n                    suite.att('tests', execution.assertions.length);\n                }\n                else {\n                    suite.att('tests', 0);\n                }\n\n                suite.att('failures', failures);\n                suite.att('errors', errors);\n            });\n\n            suite.att('time', _.mean(_.map(executions, function (execution) {\n                executionTime = _.get(execution, 'response.responseTime') / 1000 || 0;\n                testSuitesExecutionTime += executionTime;\n\n                return executionTime;\n            })).toFixed(3));\n            errorMessages && suite.ele('system-err').dat(errorMessages);\n\n            _.forOwn(tests, function (failures, name) {\n                var testcase = suite.ele('testcase'),\n                    failure;\n\n                testcase.att('name', name);\n                testcase.att('time', executionTime.toFixed(3));\n\n                // Set the same classname for all the tests\n                testcase.att('classname',\n                    getClassName(_.get(testcase.up(), 'attribs.name.value')) || classname);\n\n                if (failures && failures.length) {\n                    failure = testcase.ele('failure');\n                    failure.att('type', 'AssertionFailure');\n                    failure.dat('Failed ' + failures.length + ' times.');\n                    failure.dat('Collection JSON ID: ' + collection.id + '.');\n                    failure.dat('Collection name: ' + collection.name + '.');\n                    failure.dat('Request name: ' + util.getFullName(currentItem) + '.');\n                    failure.dat('Test description: ' + name + '.');\n                    if (failures.length !== 0) {\n                        failure.att('message', failures[0].message);\n                        failure.dat('Error message: ' + failures[0].message + '.');\n                        failure.dat('Stacktrace: ' + failures[0].stack + '.');\n                    }\n                }\n            });\n        });\n\n        root.att('time', testSuitesExecutionTime.toFixed(3));\n        newman.exports.push({\n            name: 'junit-reporter',\n            default: 'newman-run-report.xml',\n            path: reporterOptions.export,\n            content: root.end({\n                pretty: true,\n                indent: '  ',\n                newline: '\\n',\n                allowEmpty: false\n            })\n        });\n    });\n};\n\nmodule.exports = JunitReporter;\n"
  },
  {
    "path": "lib/reporters/progress.js",
    "content": "var progress = require('cli-progress'),\n    ProgressReporter;\n\n/**\n * Little reporter that generates a collection progress status bar on CLI.\n *\n * @param {Object} newman - A run object with event handler specification methods.\n * @param {Function} newman.on - An event setter method that provides hooks for reporting collection run progress.\n * @param {Object} reporterOptions - A set of reporter specific run options.\n * @param {Object} options - A set of generic collection run options.\n * @returns {*}\n */\nProgressReporter = function (newman, reporterOptions, options) {\n    if (options.silent || reporterOptions.silent) {\n        return;\n    }\n\n    var bar = new progress.Bar({});\n\n    newman.on('start', function (err, o) {\n        if (err) { return; }\n\n        bar.start(o.cursor.length * o.cursor.cycles, 0);\n    });\n\n    newman.on('item', function () {\n        bar.increment();\n    });\n\n    newman.on('done', function () {\n        bar.stop();\n    });\n};\n\nProgressReporter.prototype.dominant = true;\nmodule.exports = ProgressReporter;\n"
  },
  {
    "path": "lib/run/export-file.js",
    "content": "var fs = require('fs'),\n    {\n        join: joinPath,\n        parse: parsePath,\n        resolve: resolvePath\n    } = require('path'),\n\n    _ = require('lodash'),\n    async = require('async'),\n    { mkdirp } = require('mkdirp'),\n\n    /**\n     * The root path specifier\n     *\n     * @const\n     * @private\n     * @type {string}\n     */\n    E = '',\n\n    /**\n     * Default timestamp separator.\n     *\n     * @const\n     * @private\n     * @type {string}\n     */\n    TS_SEP = '-',\n\n    /**\n     * Writes the specified content to a file at the provided path.\n     *\n     * @param {Object} path - A set of path details for file writing.\n     * @param {String|Buffer} content - The content to be written to the file.\n     * @param {Object} options - A set of options for the current file write.\n     * @param {Function} cb - The callback invoked when the file writing operation has completed, with/without errors.\n     */\n    writeFile = function (path, content, options, cb) {\n        fs.writeFile(path.unparsed, content, function (err) {\n            cb(_.set(err, 'help',\n                `error writing file \"${path.unparsed}\" for ${options.name || 'unknown-source'}`), path);\n        });\n    },\n\n    /**\n     * Generate a timestamp from date\n     *\n     * @param {Date=} date - The timestamp used to mark the exported file.\n     * @param {String=} separator - The optional string with which to separate different sections of the timestamp,\n     * defaults to TS_SEP\n     * @returns {String} - yyyy-mm-dd-HH-MM-SS-MS-0\n     */\n    timestamp = function (date, separator) {\n        // use the iso string to ensure left padding and other stuff is taken care of\n        return (date || new Date()).toISOString().replace(/[^\\d]+/g, _.isString(separator) ? separator : TS_SEP);\n    };\n\n/**\n * Module whose job is to export a file which is in an export format.\n *\n * @param {Object} options - The set of file export options.\n * @param {String} options.path - The path to the exported file.\n * @param {String|Object} options.content - The JSON / stringified content that is to be written to the file.\n * @param {Function} done - The callback whose invocation marks the end of the file export routine.\n * @returns {*}\n */\nmodule.exports = function (options, done) {\n    // parse the path if one is available as string\n    var path = _.isString(options.path) && parsePath(resolvePath(options.path)),\n        content = _.isPlainObject(options.content) ? JSON.stringify(options.content, 0, 2) : (options.content || E);\n\n    // if a path was not provided by user, we need to prepare the default path. but create the default path only if one\n    // is provided.\n    if (!path && _.isString(options.default)) {\n        path = parsePath(options.default);\n        // delete the path and directory if one is detected when parsing defaults\n        path.root = E;\n        path.dir = 'newman';\n\n        // append timestamp\n        path.name = `${path.name}-${timestamp()}0`; // @todo make -0 become incremental if file name exists\n        path.base = path.name + path.ext;\n    }\n    // final check that path is valid\n    if (!(path && path.base)) {\n        return;\n    }\n\n    // now sore the unparsed result back for quick re-use during writing and a single place for unparsing\n    path.unparsed = joinPath(path.dir, path.base);\n\n    // in case the path has a directory, ensure that the directory is available\n    if (path.dir) {\n        async.waterfall([\n            function (next) {\n                mkdirp(path.dir)\n                    .then(() => {\n                        return next();\n                    })\n                    .catch((err) => {\n                        return next(_.set(err, 'help',\n                            `error creating path for file \"${path.unparsed}\" for ${options.name || 'unknown-source'}`));\n                    });\n            },\n            function (next) {\n                fs.stat(path.unparsed, function (err, stat) { // eslint-disable-line handle-callback-err\n                    next(null, stat);\n                });\n            },\n            function (stat, next) {\n                var target;\n\n                // handle cases where the specified export path is a pre-existing directory\n                if (stat && stat.isDirectory()) {\n                    target = parsePath(options.default);\n\n                    // append timestamp\n                    // @todo make -0 become incremental if file name exists\n                    target.name += '-' + timestamp() + '0';\n                    target.base = target.name + target.ext;\n\n                    path.unparsed = joinPath(path.unparsed, target.base);\n                }\n\n                next(null, path);\n            },\n            function (path, next) {\n                writeFile(path, content, options, next);\n            }\n        ], done);\n    }\n    else {\n        writeFile(path, content, options, done);\n    }\n};\n"
  },
  {
    "path": "lib/run/index.js",
    "content": "var _ = require('lodash'),\n    EventEmitter = require('events'),\n    asyncEach = require('async/each'),\n    sdk = require('postman-collection'),\n    runtime = require('postman-runtime'),\n    request = require('postman-request'),\n    SecureFS = require('./secure-fs'),\n    RunSummary = require('./summary'),\n    getOptions = require('./options'),\n    exportFile = require('./export-file'),\n    util = require('../util'),\n\n    /**\n     * This object describes the various events raised by Newman, and what each event argument contains.\n     * Error and cursor are present in all events.\n     *\n     * @type {Object}\n     */\n    runtimeEvents = {\n        beforeIteration: [],\n        beforeItem: ['item'],\n        beforePrerequest: ['events', 'item'],\n        prerequest: ['executions', 'item'],\n        beforeRequest: ['request', 'item'],\n        request: ['response', 'request', 'item', 'cookies', 'history'],\n        beforeTest: ['events', 'item'],\n        test: ['executions', 'item'],\n        item: ['item'],\n        iteration: [],\n        beforeScript: ['script', 'event', 'item'],\n        script: ['execution', 'script', 'event', 'item']\n    },\n\n    /**\n     * load all the default reporters here. if you have new reporter, add it to this list\n     * we know someone, who does not like dynamic requires\n     *\n     * @type {Object}\n     */\n    defaultReporters = {\n        cli: require('../reporters/cli'),\n        json: require('../reporters/json'),\n        junit: require('../reporters/junit'),\n        progress: require('../reporters/progress'),\n        emojitrain: require('../reporters/emojitrain')\n    },\n\n    /**\n     * The object of known reporters and their install instruction in case the reporter is not loaded.\n     * Pad message with two spaces since its a follow-up message for reporter warning.\n     *\n     * @private\n     * @type {Object}\n     */\n    knownReporterErrorMessages = {\n        html: '  run `npm install newman-reporter-html`\\n',\n        teamcity: '  run `npm install newman-reporter-teamcity`\\n'\n    },\n\n    /**\n     * Multiple ids or names entrypoint lookup strategy.\n     *\n     * @private\n     * @type {String}\n     */\n    MULTIENTRY_LOOKUP_STRATEGY = 'multipleIdOrName';\n\n/**\n * Runs the collection, with all the provided options, returning an EventEmitter.\n *\n * @param {Object} options - The set of wrapped options, passed by the CLI parser.\n * @param {Collection|Object|String} options.collection - A JSON / Collection / String representing the collection.\n * @param {Object|String} options.environment - An environment JSON / file path for the current collection run.\n * @param {Object|String} options.globals - A globals JSON / file path for the current collection run.\n * @param {String} options.workingDir - Path of working directory that contains files needed for the collection run.\n * @param {String} options.insecureFileRead - If true, allow reading files outside of working directory.\n * @param {Object|String} options.iterationData - An iterationData JSON / file path for the current collection run.\n * @param {Object|String} options.reporters - A set of reporter names and their associated options for the current run.\n * @param {Object|String} options.cookieJar - A tough-cookie cookieJar / file path for the current collection run.\n * @param {String} options.exportGlobals - The relative path to export the globals file from the current run to.\n * @param {String} options.exportEnvironment - The relative path to export the environment file from the current run to.\n * @param {String} options.exportCollection - The relative path to export the collection from the current run to.\n * @param {String} options.exportCookieJar - The relative path to export the cookie jar from the current run to.\n * @param {Function} callback - The callback function invoked to mark the end of the collection run.\n * @returns {EventEmitter} - An EventEmitter instance with done and error event attachments.\n */\nmodule.exports = function (options, callback) {\n    // validate all options. it is to be noted that `options` parameter is option and is polymorphic\n    (!callback && _.isFunction(options)) && (\n        (callback = options),\n        (options = {})\n    );\n    !_.isFunction(callback) && (callback = _.noop);\n\n    var emitter = new EventEmitter(), // @todo: create a new inherited constructor\n        runner = new runtime.Runner(),\n        stopOnFailure,\n        entrypoint;\n\n    // get the configuration from various sources\n    getOptions(options, function (err, options) {\n        if (err) {\n            return callback(err);\n        }\n\n        // ensure that the collection option is present before starting a run\n        if (!_.isObject(options.collection)) {\n            return callback(new Error('expecting a collection to run'));\n        }\n\n        // use client certificate list to allow different ssl certificates for\n        // different URLs\n        var sslClientCertList = options.sslClientCertList || [],\n            // allow providing custom cookieJar\n            cookieJar = options.cookieJar || request.jar();\n\n        // if sslClientCert option is set, put it at the end of the list to\n        // match all URLs that didn't match in the list\n        if (options.sslClientCert) {\n            sslClientCertList.push({\n                name: 'client-cert',\n                matches: [sdk.UrlMatchPattern.MATCH_ALL_URLS],\n                key: { src: options.sslClientKey },\n                cert: { src: options.sslClientCert },\n                passphrase: options.sslClientPassphrase\n            });\n        }\n\n        // iterates over the bail array and sets each item as an obj key with a value of boolean true\n        // [item1, item2] => {item1: true, item2: true}\n        if (_.isArray(options.bail)) {\n            options.bail = _.transform(options.bail, function (result, value) {\n                result[value] = true;\n            }, {});\n        }\n\n        // sets entrypoint to execute if options.folder is specified.\n        if (options.folder) {\n            entrypoint = { execute: options.folder };\n\n            // uses `multipleIdOrName` lookupStrategy in case of multiple folders.\n            _.isArray(entrypoint.execute) && (entrypoint.lookupStrategy = MULTIENTRY_LOOKUP_STRATEGY);\n        }\n\n        // sets stopOnFailure to true in case bail is used without any modifiers or with failure\n        // --bail => stopOnFailure = true\n        // --bail failure => stopOnFailure = true\n        (typeof options.bail !== 'undefined' &&\n            (options.bail === true || (_.isObject(options.bail) && options.bail.failure))) ?\n            stopOnFailure = true : stopOnFailure = false;\n\n        // store summary object and other relevant information inside the emitter\n        emitter.summary = new RunSummary(emitter, options);\n\n        // to store the exported content from reporters\n        emitter.exports = [];\n\n        // expose the runner object for reporter and programmatic use\n        emitter.runner = runner;\n\n        // now start the run!\n        runner.run(options.collection, {\n            stopOnFailure: stopOnFailure, // LOL, you just got trolled ¯\\_(ツ)_/¯\n            abortOnFailure: options.abortOnFailure, // used in integration tests, to be considered for a future release\n            abortOnError: _.get(options, 'bail.folder'),\n            iterationCount: options.iterationCount,\n            environment: options.environment,\n            globals: options.globals,\n            entrypoint: entrypoint,\n            data: options.iterationData,\n            delay: {\n                item: options.delayRequest\n            },\n            timeout: {\n                global: options.timeout || 0,\n                request: options.timeoutRequest || 0,\n                script: options.timeoutScript || 0\n            },\n            fileResolver: new SecureFS(options.workingDir, options.insecureFileRead),\n            requester: {\n                useWhatWGUrlParser: true,\n                cookieJar: cookieJar,\n                followRedirects: _.has(options, 'ignoreRedirects') ? !options.ignoreRedirects : undefined,\n                strictSSL: _.has(options, 'insecure') ? !options.insecure : undefined,\n                timings: Boolean(options.verbose),\n                extendedRootCA: options.sslExtraCaCerts,\n                agents: _.isObject(options.requestAgents) ? options.requestAgents : undefined\n            },\n            certificates: sslClientCertList.length && new sdk.CertificateList({}, sslClientCertList)\n        }, function (err, run) {\n            if (err) { return callback(err); }\n\n            var callbacks = {},\n                // ensure that the reporter option type polymorphism is handled\n                reporters = _.isString(options.reporters) ? [options.reporters] : options.reporters,\n                // keep a track of start assertion indices of legacy assertions\n                legacyAssertionIndices = {};\n\n            // emit events for all the callbacks triggered by the runtime\n            _.forEach(runtimeEvents, function (definition, eventName) {\n                // intercept each runtime.* callback and expose a global object based event\n                callbacks[eventName] = function (err, cursor) {\n                    var args = arguments,\n                        obj = { cursor };\n\n                    // convert the arguments into an object by taking the key name reference from the definition\n                    // object\n                    _.forEach(definition, function (key, index) {\n                        obj[key] = args[index + 2]; // first two are err, cursor\n                    });\n\n                    args = [eventName, err, obj];\n                    emitter.emit.apply(emitter, args); // eslint-disable-line prefer-spread\n                };\n            });\n\n            // add non generic callback handling\n            _.assignIn(callbacks, {\n\n                /**\n                 * Emits event for start of the run. It injects/exposes additional objects useful for\n                 * programmatic usage and reporters\n                 *\n                 * @param {?Error} err - An Error instance / null object.\n                 * @param {Object} cursor - The run cursor instance.\n                 * @returns {*}\n                 */\n                start (err, cursor) {\n                    emitter.emit('start', err, {\n                        cursor,\n                        run\n                    });\n                },\n\n                /**\n                 * Bubbles up console messages.\n                 *\n                 * @param {Object} cursor - The run cursor instance.\n                 * @param {String} level - The level of console logging [error, silent, etc].\n                 * @returns {*}\n                 */\n                console (cursor, level) {\n                    emitter.emit('console', null, {\n                        cursor: cursor,\n                        level: level,\n                        messages: _.slice(arguments, 2)\n                    });\n                },\n\n                /**\n                 * The exception handler for the current run instance.\n                 *\n                 * @todo Fix bug of arg order in runtime.\n                 * @param {Object} cursor - The run cursor.\n                 * @param {?Error} err - An Error instance / null object.\n                 * @returns {*}\n                 */\n                exception (cursor, err) {\n                    emitter.emit('exception', null, {\n                        cursor: cursor,\n                        error: err\n                    });\n                },\n\n                assertion (cursor, assertions) {\n                    _.forEach(assertions, function (assertion) {\n                        var errorName = _.get(assertion, 'error.name', 'AssertionError');\n\n                        !assertion && (assertion = {});\n\n                        // store the legacy assertion index\n                        assertion.index && (legacyAssertionIndices[cursor.ref] = assertion.index);\n\n                        emitter.emit('assertion', (assertion.passed ? null : {\n                            name: errorName,\n                            index: assertion.index,\n                            test: assertion.name,\n                            message: _.get(assertion, 'error.message', assertion.name || ''),\n\n                            stack: errorName + ': ' + _.get(assertion, 'error.message', '') + '\\n' +\n                                '   at Object.eval sandbox-script.js:' + (assertion.index + 1) + ':' +\n                                ((cursor && cursor.position || 0) + 1) + ')'\n                        }), {\n                            cursor: cursor,\n                            assertion: assertion.name,\n                            skipped: assertion.skipped,\n                            error: assertion.error,\n                            item: run.resolveCursor(cursor)\n                        });\n                    });\n                },\n\n                /**\n                 * Custom callback to override the `done` event to fire the end callback.\n                 *\n                 * @todo Do some memory cleanup here?\n                 * @param {?Error} err - An error instance / null passed from the done event handler.\n                 * @param {Object} cursor - The run instance cursor.\n                 * @returns {*}\n                 */\n                done (err, cursor) {\n                    // in case runtime faced an error during run, we do not process any other event and emit `done`.\n                    // we do it this way since, an error in `done` callback would have anyway skipped any intermediate\n                    // events or callbacks\n                    if (err) {\n                        emitter.emit('done', err, emitter.summary);\n                        callback(err, emitter.summary);\n\n                        return;\n                    }\n\n                    // we emit a `beforeDone` event so that reporters and other such addons can do computation before\n                    // the run is marked as done\n                    emitter.emit('beforeDone', null, {\n                        cursor: cursor,\n                        summary: emitter.summary\n                    });\n\n                    _.forEach(['environment', 'globals', 'collection', 'cookie-jar'], function (item) {\n                        // fetch the path name from options if one is provided\n                        var path = _.get(options, _.camelCase(`export-${item}`));\n\n                        // if the options have an export path, then add the item to export queue\n                        path && emitter.exports.push({\n                            name: item,\n                            default: `newman-${item}.json`,\n                            path: path,\n                            content: item === 'cookie-jar' ?\n                                cookieJar.toJSON() :\n                                _(emitter.summary[item].toJSON())\n                                    .defaults({\n                                        name: item\n                                    })\n                                    .merge({\n                                        _postman_variable_scope: item,\n                                        _postman_exported_at: (new Date()).toISOString(),\n                                        _postman_exported_using: util.userAgent\n                                    })\n                                    .value()\n                        });\n                    });\n\n                    asyncEach(emitter.exports, exportFile, function (err) {\n                        // we now trigger actual done event which we had overridden\n                        emitter.emit('done', err, emitter.summary);\n                        callback(err, emitter.summary);\n                    });\n                }\n            });\n\n            emitter.on('script', function (err, o) {\n                // bubble special script name based events\n                o && o.event && emitter.emit(o.event.listen + 'Script', err, o);\n            });\n\n            emitter.on('beforeScript', function (err, o) {\n                // bubble special script name based events\n                o && o.event && emitter.emit(_.camelCase('before-' + o.event.listen + 'Script'), err, o);\n            });\n\n            // initialise all the reporters\n            !emitter.reporters && (emitter.reporters = {});\n            _.isArray(reporters) && _.forEach(reporters, function (reporterName) {\n                // disallow duplicate reporter initialisation\n                if (_.has(emitter.reporters, reporterName)) { return; }\n\n                var Reporter;\n\n                try {\n                    // check if the reporter is an external reporter\n                    Reporter = require((function (name) { // ensure scoped packages are loaded\n                        var prefix = '',\n                            scope = (name.charAt(0) === '@') && name.substr(0, name.indexOf('/') + 1);\n\n                        if (scope) {\n                            prefix = scope;\n                            name = name.substr(scope.length);\n                        }\n\n                        return prefix + 'newman-reporter-' + name;\n                    }(reporterName)));\n                }\n                // @todo - maybe have a debug mode and log error there\n                catch (error) {\n                    if (!defaultReporters[reporterName]) {\n                        // @todo: route this via print module to respect silent flags\n                        console.warn(`newman: could not find \"${reporterName}\" reporter`);\n                        console.warn('  ensure that the reporter is installed in the same directory as newman');\n\n                        // print install instruction in case a known reporter is missing\n                        if (knownReporterErrorMessages[reporterName]) {\n                            console.warn(knownReporterErrorMessages[reporterName]);\n                        }\n                        else {\n                            console.warn('  please install reporter using npm\\n');\n                        }\n                    }\n                }\n\n                // load local reporter if its not an external reporter\n                !Reporter && (Reporter = defaultReporters[reporterName]);\n\n                try {\n                    // we could have checked _.isFunction(Reporter), here, but we do not do that so that the nature of\n                    // reporter error can be bubbled up\n                    Reporter && (emitter.reporters[reporterName] = new Reporter(emitter,\n                        _.get(options, ['reporter', reporterName], {}), options));\n                }\n                catch (error) {\n                    // if the reporter errored out during initialisation, we should not stop the run simply log\n                    // the error stack trace for debugging\n                    console.warn(`newman: could not load \"${reporterName}\" reporter`);\n\n                    if (!defaultReporters[reporterName]) {\n                        // @todo: route this via print module to respect silent flags\n                        console.warn(`  this seems to be a problem in the \"${reporterName}\" reporter.\\n`);\n                    }\n                    console.warn(error);\n                }\n            });\n\n            // raise warning when more than one dominant reporters are used\n            (function (reporters) {\n                // find all reporters whose `dominant` key is set to true\n                var conflicts = _.keys(_.transform(reporters, function (conflicts, reporter, name) {\n                    reporter.dominant && (conflicts[name] = true);\n                }));\n\n                (conflicts.length > 1) && // if more than one dominant, raise a warning\n                    console.warn(`newman: ${conflicts.join(', ')} reporters might not work well together.`);\n            }(emitter.reporters));\n\n            // we ensure that everything is async to comply with event paradigm and start the run\n            setImmediate(function () {\n                run.start(callbacks);\n            });\n        });\n    });\n\n    return emitter;\n};\n"
  },
  {
    "path": "lib/run/options.js",
    "content": "var _ = require('lodash'),\n    fs = require('fs'),\n    async = require('async'),\n    Collection = require('postman-collection').Collection,\n    VariableScope = require('postman-collection').VariableScope,\n    CookieJar = require('@postman/tough-cookie').CookieJar,\n    transformer = require('postman-collection-transformer'),\n    liquidJSON = require('liquid-json'),\n    parseCsv = require('csv-parse'),\n    util = require('../util'),\n    config = require('../config'),\n\n    /**\n     * The message displayed when the specified collection file can't be loaded.\n     *\n     * @const\n     * @type {String}\n     */\n    COLLECTION_LOAD_ERROR_MESSAGE = 'collection could not be loaded',\n\n    /**\n     * The message displayed when the specified iteration data file can't be loaded.\n     *\n     * @const\n     * @type {String}\n     */\n    ITERATION_DATA_LOAD_ERROR_MESSAGE = 'iteration data could not be loaded',\n\n    /**\n     * The message displayed when the specified environment or globals file can't be loaded.\n     *\n     * @const\n     * @type {String}\n     */\n    LOAD_ERROR_MESSAGE = 'could not load ',\n\n    /**\n     * The set of postman collection transformer options, to convert collection v1 to collection v2.\n     *\n     * @const\n     * @type {Object}\n     */\n    COLLECTION_TRANSFORMER_OPTION = { inputVersion: '1.0.0', outputVersion: '2.1.0' },\n\n    /**\n     * Accepts an object, and extracts the property inside an object which is supposed to contain the required data.\n     * In case of variables, it also extracts them into plain JS objects.\n     *\n     * @param {Object} source - The source wrapper object that may or may not contain inner wrapped properties.\n     * @param {String} type - \"environment\" or \"globals\", etc.\n     * @returns {Object} - The object representation of the current extracted property.\n     */\n    extractModel = function (source, type) {\n        source = source[type] || source; // extract object that holds variable. these usually come from cloud API\n        if (!_.isObject(source)) {\n            return undefined;\n        }\n\n        // ensure we un-box the JSON if it comes from cloud-api or similar sources\n        !source.values && _.isObject(source[type]) && (source = source[type]);\n\n        // we ensure that environment passed as array is converted to plain object. runtime does this too, but we do it\n        // here for consistency of options passed to reporters\n        return source;\n    },\n\n    /**\n     * Loads the given data of type from a specified external location\n     *\n     * @param {String} type - The type of data to load.\n     * @param {String} location - The location to load from (file path or URL).\n     * @param {Object} options - The set of wrapped options.\n     * @param {function} cb - The callback function whose invocation marks the end of the external load routine.\n     * @returns {*}\n     */\n    externalLoader = function (type, location, options, cb) {\n        return _.isString(location) ? util.fetchJson(type, location, options, function (err, data) {\n            if (err) {\n                return cb(err);\n            }\n\n            return cb(null, extractModel(data, type));\n        }) : cb(null, extractModel(location, type));\n    },\n\n    /**\n     * A helper method to process a collection and convert it to a V2 equivalent if necessary, and return it.\n     *\n     * @todo Drop support for the v1 collection format in Newman v7?\n     * Reference: https://github.com/postmanlabs/newman/pull/1660\n     *\n     * @param {Object} collection The input collection, specified as a JSON object.\n     * @param {Function} callback A handler function that consumes an error object and the processed collection.\n     * @returns {*}\n     */\n    processCollection = function (collection, callback) {\n        if (util.isV1Collection(collection)) {\n            // @todo: route this via print module to respect silent flags\n            console.warn('newman: Newman v4 deprecates support for the v1 collection format');\n            console.warn('  Use the Postman Native app to export collections in the v2 format\\n');\n\n            return transformer.convert(collection, COLLECTION_TRANSFORMER_OPTION, callback);\n        }\n\n        callback(null, collection);\n    },\n\n    /**\n     * Helper function that manages the load of environments and globals\n     *\n     * @private\n     * @param {String} type - The type of resource to load: collection, environment, etc.\n     * @param {String|Object} value - The value derived from the CLI or run command.\n     * @param {Object} options - The set of wrapped options.\n     * @param {Function} callback - The function invoked when the scope has been loaded.\n     */\n    loadScopes = function (type, value, options, callback) {\n        var done = function (err, scope) {\n            if (err) { return callback(new Error(LOAD_ERROR_MESSAGE + `${type}\\n  ${err.message || err}`)); }\n\n            if (!_.isObject(scope)) {\n                return done(new Error(LOAD_ERROR_MESSAGE + type));\n            }\n\n            callback(null, new VariableScope(VariableScope.isVariableScope(scope) ? scope.toJSON() : scope));\n        };\n\n        if (_.isObject(value)) {\n            return done(null, value);\n        }\n\n        externalLoader(type, value, options, done);\n    },\n\n    /**\n     * Custom method to auto parse CSV values\n     *\n     * @private\n     * @param {String} value - CSV field value\n     * @param {Object} context - Context of field value\n     * @param {Boolean} context.quoting - A boolean indicating if the field was surrounded by quotes.\n     * @returns {String|Number|Date}\n     */\n    csvAutoParse = function (value, context) {\n        if (context.quoting) {\n            // avoid parsing quoted values\n            return value;\n        }\n\n        if (util.isInt(value)) {\n            return parseInt(value, 10);\n        }\n\n        if (util.isFloat(value)) {\n            return parseFloat(value);\n        }\n\n        return value;\n    },\n\n    /**\n     * Custom configuration loaders for the required configuration keys.\n     *\n     * @type {Object}\n     */\n    configLoaders = {\n\n        /**\n         * The collection file load helper for the current run.\n         *\n         * @param {Object|String} value - The collection, specified as a JSON object, or the path to it's file.\n         * @param {Object} options - The set of wrapped options.\n         * @param {Function} callback - The callback function invoked to mark the end of the collection load routine.\n         * @returns {*}\n         */\n        collection: function (value, options, callback) {\n            /**\n             * The post collection load handler.\n             *\n             * @param {?Error} err - An Error instance / null, passed from the collection loader.\n             * @param {Object} collection - The collection / raw JSON object, passed from the collection loader.\n             * @returns {*}\n             */\n            var done = function (err, collection) {\n                if (err) {\n                    return callback(err);\n                }\n\n                // ensure that the collection option is present before starting a run\n                if (!_.isObject(collection)) {\n                    return callback(new Error(COLLECTION_LOAD_ERROR_MESSAGE));\n                }\n\n                // ensure that the collection reference is an SDK instance\n                // @todo - should this be handled by config loaders?\n                collection = new Collection(Collection.isCollection(collection) ?\n                    // if the option contain an instance of collection, we simply clone it for future use\n                    // create a collection in case it is not one. user can send v2 JSON as a source and that will be\n                    // converted to a collection\n                    collection.toJSON() : collection);\n\n                callback(null, collection);\n            };\n\n            // if the collection has been specified as an object, convert to V2 if necessary and return the result\n            if (_.isObject(value)) {\n                return processCollection(value, done);\n            }\n\n            externalLoader('collection', value, options, function (err, data) {\n                if (err) {\n                    return done(new Error(COLLECTION_LOAD_ERROR_MESSAGE +\n                        (err.help ? `\\n  ${err.help}` : '') +\n                        `\\n  ${err.message || err}`));\n                }\n                if (!_.isObject(data)) {\n                    return done(new Error(COLLECTION_LOAD_ERROR_MESSAGE));\n                }\n\n                return processCollection(data, done);\n            });\n        },\n\n        /**\n         * The environment configuration object, loaded for the current collection run.\n         *\n         * @type {Object}\n         */\n        environment: loadScopes.bind(this, 'environment'),\n\n        /**\n         * The object of globals, loaded for the collection run.\n         *\n         * @type {Object}\n         */\n        globals: loadScopes.bind(this, 'globals'),\n\n        /**\n         * Helper function to sanitize folder option.\n         *\n         * @param {String[]|String} value - The list of folders to execute\n         * @param {Object} options - The set of wrapped options.\n         * @param {Function} callback - The callback function invoked to mark the end of the folder load routine.\n         * @returns {*}\n         */\n        folder: function (value, options, callback) {\n            if (!value.length) {\n                return callback(); // avoids empty string or array\n            }\n\n            if (Array.isArray(value) && value.length === 1) {\n                return callback(null, value[0]); // avoids using multipleIdOrName strategy for a single item array\n            }\n\n            callback(null, value);\n        },\n\n        /**\n         * The iterationData loader module, with support for JSON or CSV data files.\n         *\n         * @param {String|Object[]} location - The path to the iteration data file for the current collection run, or\n         * the array of iteration data objects.\n         * @param {Object} options - The set of wrapped options.\n         * @param {Function} callback - The function invoked to indicate the end of the iteration data loading routine.\n         * @returns {*}\n         */\n        iterationData: function (location, options, callback) {\n            if (_.isArray(location)) { return callback(null, location); }\n\n            util.fetch(location, function (err, data) {\n                if (err) {\n                    return callback(new Error(ITERATION_DATA_LOAD_ERROR_MESSAGE + `\\n  ${err.message || err}`));\n                }\n\n                // Try loading as a JSON, fall-back to CSV.\n                async.waterfall([\n                    (cb) => {\n                        try {\n                            return cb(null, liquidJSON.parse(data.trim()));\n                        }\n                        catch (e) {\n                            return cb(null, undefined); // e masked to avoid displaying JSON parse errors for CSV files\n                        }\n                    },\n                    (json, cb) => {\n                        if (json) {\n                            return cb(null, json);\n                        }\n                        // Wasn't JSON\n                        parseCsv(data, {\n                            columns: true, // infer the columns names from the first row\n                            escape: '\"', // escape character\n                            cast: csvAutoParse, // function to cast values of individual fields\n                            trim: true, // ignore whitespace immediately around the delimiter\n                            relax: true, // allow using quotes without escaping inside unquoted string\n                            relax_column_count: true, // ignore inconsistent columns count\n                            bom: true // strip the byte order mark (BOM) from the input string\n                        }, cb);\n                    }\n                ], (err, parsed) => {\n                    if (err) {\n                        return callback(new Error(ITERATION_DATA_LOAD_ERROR_MESSAGE + `\\n ${err.message || err}`));\n                    }\n\n                    callback(null, parsed);\n                });\n            });\n        },\n\n        sslClientCertList: function (location, options, callback) {\n            if (Array.isArray(location)) {\n                return callback(null, location);\n            }\n\n            if (typeof location !== 'string') {\n                return callback(new Error('path for ssl client certificates list file must be a string'));\n            }\n\n            fs.readFile(location, function (err, value) {\n                if (err) {\n                    return callback(new Error(`unable to read the ssl client certificates file \"${location}\"`));\n                }\n\n                try {\n                    value = liquidJSON.parse(value.toString(util.detectEncoding(value)).trim());\n                }\n                catch (e) {\n                    return callback(new Error(`the file at ${location} does not contain valid JSON data.`));\n                }\n\n                // ensure that `sslClientCertList` is an array\n                if (!Array.isArray(value)) {\n                    return callback(new Error('expected ssl client certificates list to be an array.'));\n                }\n\n                return callback(null, value);\n            });\n        },\n\n        cookieJar: function (location, options, callback) {\n            if (_.isObject(location) && location.constructor.name === 'CookieJar') {\n                return callback(null, location);\n            }\n\n            if (typeof location !== 'string') {\n                return callback(new Error('cookieJar must be a path to a JSON file or a CookieJar instance'));\n            }\n\n            fs.readFile(location, function (err, value) {\n                if (err) {\n                    return callback(new Error(`unable to read the cookie jar file \"${location}\"`));\n                }\n\n                try {\n                    value = CookieJar.fromJSON(value.toString());\n                }\n                catch (e) {\n                    return callback(new Error(`the file at ${location} does not contain valid JSON data.`));\n                }\n\n                return callback(null, value);\n            });\n        }\n    };\n\n/**\n * The helper function to load all file based information for the current collection run.\n *\n * @param {Object} options - The set of generic collection run options.\n * @param {Function} callback - The function called to mark the completion of the configuration load routine.\n * @returns {*}\n */\nmodule.exports = function (options, callback) {\n    // set newman version used for collection run\n    options.newmanVersion = util.version;\n\n    // set working directory if not provided\n    options.workingDir = options.workingDir || process.cwd();\n\n    // allow insecure file read by default\n    options.insecureFileRead = Boolean(_.get(options, 'insecureFileRead', true));\n\n    config.get(options, { loaders: configLoaders, command: 'run' }, function (err, result) {\n        if (err) { return callback(err); }\n\n        !_.isEmpty(options.globalVar) && _.forEach(options.globalVar, function (variable) {\n            variable && (result.globals.set(variable.key, variable.value));\n        });\n\n        !_.isEmpty(options.envVar) && _.forEach(options.envVar, function (variable) {\n            variable && (result.environment.set(variable.key, variable.value));\n        });\n\n        callback(null, result);\n    });\n};\n"
  },
  {
    "path": "lib/run/secure-fs.js",
    "content": "const fs = require('fs'),\n    _ = require('lodash'),\n    path = require('path'),\n    util = require('util'),\n    Readable = require('stream').Readable,\n\n    PPERM_ERR = 'PPERM: insecure file access outside working directory',\n    FUNCTION = 'function',\n    DEPRECATED_SYNC_WRITE_STREAM = 'SyncWriteStream',\n    EXPERIMENTAL_PROMISE = 'promises',\n\n    // Use simple character check instead of regex to prevent regex attack\n    /*\n     * Windows root directory can be of the following from\n     *\n     * | File System | Actual           | Modified          |\n     * |-------------|------------------|-------------------|\n     * | LFS (Local) | C:\\Program       | /C:/Program       |\n     * | UNC         | \\\\Server\\Program | ///Server/Program |\n     */\n    isWindowsRoot = function (path) {\n        const drive = path.charAt(1);\n\n        return ((path.charAt(0) === '/') &&\n            ((drive >= 'A' && drive <= 'Z') || (drive >= 'a' && drive <= 'z')) &&\n            (path.charAt(2) === ':')) ||\n            path.slice(0, 3) === '///'; // Modified UNC path\n    },\n\n    stripTrailingSep = function (thePath) {\n        if (thePath[thePath.length - 1] === path.sep) {\n            return thePath.slice(0, -1);\n        }\n\n        return thePath;\n    },\n\n    pathIsInside = function (thePath, potentialParent) {\n        // For inside-directory checking, we want to allow trailing slashes, so normalize.\n        thePath = stripTrailingSep(thePath);\n        potentialParent = stripTrailingSep(potentialParent);\n\n        // Node treats only Windows as case-insensitive in its path module; we follow those conventions.\n        if (global.process.platform === 'win32') {\n            thePath = thePath.toLowerCase();\n            potentialParent = potentialParent.toLowerCase();\n        }\n\n        return thePath.lastIndexOf(potentialParent, 0) === 0 &&\n            (\n                thePath[potentialParent.length] === path.sep ||\n                thePath[potentialParent.length] === undefined\n            );\n    };\n\n/**\n * Secure file resolver wrapper over fs. It only allow access to files inside working directory unless specified.\n *\n * @param {*} workingDir - Path of working directory\n * @param {*} [insecureFileRead=false] - If true, allow reading files outside working directory\n * @param {*} [fileWhitelist=[]] - List of allowed files outside of working directory\n */\nfunction SecureFS (workingDir, insecureFileRead = false, fileWhitelist = []) {\n    this._fs = fs;\n    this._path = path;\n    this.constants = this._fs.constants;\n\n    this.workingDir = workingDir;\n    this.insecureFileRead = insecureFileRead;\n    this.fileWhitelist = fileWhitelist;\n\n    this.isWindows = global.process.platform === 'win32';\n}\n\n/**\n * Private method to resole the path based based on working directory\n *\n * @param {String} relOrAbsPath - Relative or absolute path to resolve\n * @param {Array} whiteList - A list of absolute path to whitelist\n *\n * @returns {String} The resolved path\n */\nSecureFS.prototype._resolve = function (relOrAbsPath, whiteList) {\n    // Special handling for windows absolute paths to work cross platform\n    this.isWindows && isWindowsRoot(relOrAbsPath) && (relOrAbsPath = relOrAbsPath.substring(1));\n\n    // Resolve the path from the working directory. The file should always be resolved so that\n    // cross os variations are mitigated\n    let resolvedPath = this._path.resolve(this.workingDir, relOrAbsPath);\n\n    // Check file is within working directory\n    if (!this.insecureFileRead && // insecureFile read disabled\n        !pathIsInside(resolvedPath, this.workingDir) && // File not inside working directory\n        !_.includes(whiteList, resolvedPath)) { // File not in whitelist\n        // Exit\n        return undefined;\n    }\n\n    return resolvedPath;\n};\n\n/**\n * Asynchronous path resolver function\n *\n * @param {String} relOrAbsPath - Relative or absolute path to resolve\n * @param {Array} [whiteList] - A optional list of additional absolute path to whitelist\n * @param {Function} callback -\n */\nSecureFS.prototype.resolvePath = function (relOrAbsPath, whiteList, callback) {\n    if (!callback && typeof whiteList === FUNCTION) {\n        callback = whiteList;\n        whiteList = [];\n    }\n\n    let resolvedPath = this._resolve(relOrAbsPath, _.concat(this.fileWhitelist, whiteList));\n\n    if (!resolvedPath) {\n        return callback(new Error(PPERM_ERR));\n    }\n\n    return callback(null, resolvedPath);\n};\n\n/**\n * Synchronous path resolver function\n *\n * @param {String} relOrAbsPath - Relative or absolute path to resolve\n * @param {Array} [whiteList] - A optional list of additional absolute path to whitelist\n *\n * @returns {String} The resolved path\n */\nSecureFS.prototype.resolvePathSync = function (relOrAbsPath, whiteList) {\n    // Resolve the path from the working directory\n    const resolvedPath = this._resolve(relOrAbsPath, _.concat(this.fileWhitelist, whiteList));\n\n    if (!resolvedPath) {\n        throw new Error(PPERM_ERR);\n    }\n\n    return resolvedPath;\n};\n\n// Attach all functions in fs to postman-fs\nObject.getOwnPropertyNames(fs).map((prop) => {\n    // Bail-out early to prevent fs module from logging warning for deprecated and experimental methods\n    if (prop === DEPRECATED_SYNC_WRITE_STREAM || prop === EXPERIMENTAL_PROMISE || typeof fs[prop] !== FUNCTION) {\n        return;\n    }\n\n    SecureFS.prototype[prop] = fs[prop];\n});\n\n// Override the required functions\nSecureFS.prototype.stat = function (path, callback) {\n    this.resolvePath(path, (err, resolvedPath) => {\n        if (err) {\n            return callback(err);\n        }\n\n        return this._fs.stat(resolvedPath, callback);\n    });\n};\n\nSecureFS.prototype.createReadStream = function (path, options) {\n    try {\n        return this._fs.createReadStream(this.resolvePathSync(path), options);\n    }\n    catch (err) {\n        // Create a fake read steam that emits and error and\n        const ErrorReadStream = function () {\n            // Replicating behavior of fs module of disabling emitClose on destroy\n            Readable.call(this, { emitClose: false });\n\n            // Emit the error event with insure file access error\n            this.emit('error', new Error(PPERM_ERR));\n\n            // Options exists and disables autoClose then don't destroy\n            (options && !options.autoClose) || this.destroy();\n        };\n\n        util.inherits(ErrorReadStream, Readable);\n\n        return new ErrorReadStream();\n    }\n};\n\nmodule.exports = SecureFS;\n"
  },
  {
    "path": "lib/run/summary.js",
    "content": "var _ = require('lodash'),\n    sdk = require('postman-collection'),\n    SerialiseError = require('serialised-error'),\n    RunSummary;\n\n/**\n * Creates and returns a RunSummary instance for the current collection run.\n *\n * @constructor\n * @param {EventEmitter} emitter - An EventEmitter instance with event handler attachments to add run information to.\n * @param {Object} options - A set of run summary creation options.\n */\nRunSummary = function RunSummary (emitter, options) {\n    // keep a copy of this instance since, we need to refer to this from various events\n    var summary = this;\n\n    // and store the trackers and failures in the summary object itself\n    _.assign(summary, /** @lends RunSummary.prototype */ {\n        /**\n         * The collection that is being executed.\n         *\n         * @type {Collection}\n         */\n        collection: _.get(options, 'collection'),\n\n        /**\n         * The environment that is being used during the run\n         *\n         * @type {VariableScope}\n         *\n         */\n        environment: _.get(options, 'environment'),\n\n        /**\n         * Global variables being used during the run\n         *\n         * @type {VariableScope}\n         */\n        globals: _.get(options, 'globals'),\n\n        /**\n         * Holds information related to the run.\n         */\n        run: {\n            /**\n             * Holds the statistics of the run. Each property in it is the item being tracked and has three numeric\n             * properties - total, failed, pending\n             *\n             * @type {Object.<Object>}\n             */\n            stats: {\n                iterations: {},\n                items: {},\n                scripts: {},\n                prerequests: {},\n                requests: {},\n                tests: {},\n                assertions: {},\n                testScripts: {},\n                prerequestScripts: {}\n            },\n\n            /**\n             * Stores all generic timing information\n             *\n             * @type {Object}\n             */\n            timings: {\n                /**\n                 * The average response time of the run\n                 *\n                 * @type {number}\n                 */\n                responseAverage: 0,\n\n                /**\n                 * The miminum response time of the run\n                 *\n                 * @type {number}\n                 */\n                responseMin: 0,\n\n                /**\n                 * The maximum response time of the run\n                 *\n                 * @type {number}\n                 */\n                responseMax: 0,\n\n                /**\n                 * Standard deviation of response time of the run\n                 *\n                 * @type {number}\n                 */\n                responseSd: 0,\n\n                /**\n                 * The average DNS lookup time of the run\n                 *\n                 * @type {number}\n                 */\n                dnsAverage: 0,\n\n                /**\n                 * The minimum DNS lookup time of the run\n                 *\n                 * @type {number}\n                 */\n                dnsMin: 0,\n\n                /**\n                 * The maximum DNS lookup time of the run\n                 *\n                 * @type {number}\n                 */\n                dnsMax: 0,\n\n                /**\n                 * Standard deviation of DNS lookup time of the run\n                 *\n                 * @type {number}\n                 */\n                dnsSd: 0,\n\n                /**\n                 * The average first byte time of the run\n                 *\n                 * @type {number}\n                 */\n                firstByteAverage: 0,\n\n                /**\n                 * The minimum first byte time of the run\n                 *\n                 * @type {number}\n                 */\n                firstByteMin: 0,\n\n                /**\n                 * The maximum first byte time of the run\n                 *\n                 * @type {number}\n                 */\n                firstByteMax: 0,\n\n                /**\n                 * Standard deviation of first byte time of the run\n                 *\n                 * @type {number}\n                 */\n                firstByteSd: 0\n            },\n\n            /**\n             * Stores detailed information about the order of execution, request, response and assertions\n             *\n             * @type {Array<Object>}\n             */\n            executions: [],\n\n            /**\n             * Stores information on data transfer made during the collection\n             *\n             * @type {Object}\n             */\n            transfers: {\n                /**\n                 * The total data received as response to every request\n                 *\n                 * @type {number}\n                 */\n                responseTotal: 0\n            },\n\n            /**\n             * An array of all errors encountered during the run\n             *\n             * @type {Array.<Error>}\n             */\n            failures: [],\n\n            /**\n             * This stores any fatal error during the run that caused the run to abort prematurely.\n             *\n             * @type {Error}\n             */\n            error: null\n        }\n    });\n\n    // track run timings (start and end)\n    RunSummary.attachTimingTrackers(this, emitter);\n\n    // accumulate statistics on all event\n    // for all types of events track the counters for the event and its corresponding \"before\" counterpart\n    RunSummary.attachStatisticTrackers(this, emitter);\n\n    // accumulate statistics on requests - such as size and time\n    RunSummary.attachRequestTracker(this, emitter);\n\n    // accumulate errors (failures) from all events\n    RunSummary.attachFailureTrackers(this, emitter);\n\n    // accumulate all execution specific data in collection\n    RunSummary.attachReportingTrackers(this, emitter);\n};\n\n_.assign(RunSummary, {\n    attachReportingTrackers (summary, emitter) {\n        var cache = {},\n            executions = summary.run.executions;\n\n        emitter.on('beforeItem', function (err, o) {\n            if (err || !_.get(o, 'cursor.ref')) { return; }\n\n            cache[o.cursor.ref] = _.assignIn(cache[o.cursor.ref] || {}, {\n                cursor: o.cursor,\n                item: o.item\n            });\n        });\n\n        // save all responses in executions array\n        emitter.on('request', function (err, o) {\n            if (!_.get(o, 'cursor.ref')) { return; }\n\n            var execution = cache[o.cursor.ref] = (cache[o.cursor.ref] || {});\n\n            executions.push(_.assignIn(execution, {\n                cursor: o.cursor,\n                request: o.request,\n                response: o.response,\n                id: _.get(o, 'item.id')\n            }, err && {\n                requestError: err || undefined\n            }));\n        });\n\n        // save all script execution errors in each execution\n        emitter.on('script', function (err, o) {\n            if (!_.get(o, 'cursor.ref')) { return; }\n\n            var execution = cache[o.cursor.ref] = (cache[o.cursor.ref] || {}),\n                eventName = o && o.event && (o.event.listen + 'Script');\n\n            // store the script error corresponding to the script event name\n            err && (execution && eventName) && (execution[eventName] || (execution[eventName] = [])).push({\n                error: err\n            });\n        });\n\n        // save all assertions in each execution\n        emitter.on('assertion', function (err, o) {\n            if (!_.get(o, 'cursor.ref')) { return; }\n\n            var execution = cache[o.cursor.ref] = (cache[o.cursor.ref] || {});\n\n            if (!execution) { return; }\n\n            (execution.assertions || (execution.assertions = [])).push({\n                assertion: o.assertion,\n                skipped: o.skipped,\n                error: err || undefined\n            });\n        });\n    },\n\n    attachTimingTrackers (summary, emitter) {\n        // mark the point when the run started\n        // also mark the point when run completed and also store error if needed\n        emitter.on('start', function () { summary.run.timings.started = Date.now(); });\n        emitter.on('beforeDone', function () {\n            summary.run.timings.completed = Date.now();\n        });\n        emitter.on('done', function (err) {\n            err && (summary.error = err);\n        });\n    },\n    attachStatisticTrackers (summary, emitter) {\n        // accumulate statistics on all event\n        // for all types of events track the counters for the event and its corresponding \"before\" counterpart\n        _.forEach(summary.run.stats, function (tracker, name) {\n            // the actual event names are singular than their plural trackers, so we make the name singular\n            name = name.slice(0, -1); // remove last character\n\n            // populate initial values of trackers\n            _.assign(tracker, { total: 0, pending: 0, failed: 0 });\n\n            // Set up common listeners for a set of events, which tracks how many times they were executed and records\n            // the ones which had an error passed as first argument\n            emitter.on(_.camelCase('before-' + name), function () {\n                tracker.pending += 1;\n            });\n\n            emitter.on(name, function (err) {\n                // check pending so that, it does not negate for items that do not have a `before` counterpart\n                tracker.pending && (tracker.pending -= 1);\n                err && (tracker.failed += 1);\n                tracker.total += 1;\n            });\n        });\n    },\n\n    attachRequestTracker (summary, emitter) {\n        // accumulate statistics on requests\n        emitter.on('request', function (err, o) {\n            if (err || !(o && o.response)) { return; }\n\n            var size = _.isFunction(o.response.size) && o.response.size(),\n                time = o.response.responseTime,\n                requestCount = summary.run.stats.requests.total,\n                timings,\n                timingPhases;\n\n            // compute the response size total\n            size && (summary.run.transfers.responseTotal += (size.body || 0 + size.headers || 0));\n\n            // if there are redirects, get timings for the last request sent\n            timings = _.last(_.get(o, 'history.execution.data'));\n            timings = timings && timings.timings;\n            timingPhases = timings && sdk.Response.timingPhases(timings);\n\n            (timingPhases || time) && _.forEach([\n                'dns',\n                'firstByte',\n                'response'\n            ], (value) => {\n                var currentValue = (value === 'response') ? time : (timingPhases && timingPhases[value]),\n                    previousAverage = summary.run.timings[`${value}Average`],\n                    previousVariance = summary.run.timings[`${value}Sd`] ** 2,\n                    delta1 = currentValue - previousAverage,\n                    delta2,\n                    currentVariance;\n\n                if (!currentValue) { return; }\n\n                // compute average time for the given phase of request\n                summary.run.timings[`${value}Average`] =\n                    (previousAverage * (requestCount - 1) + currentValue) / requestCount;\n\n                // compute minimum time for the given phase of request\n                if (!summary.run.timings[`${value}Min`]) {\n                    summary.run.timings[`${value}Min`] = currentValue;\n                }\n                else {\n                    summary.run.timings[`${value}Min`] =\n                        Math.min(summary.run.timings[`${value}Min`], currentValue);\n                }\n\n                // compute maximum time the given phase of request\n                summary.run.timings[`${value}Max`] = Math.max(summary.run.timings[`${value}Max`], currentValue);\n\n                // compute standard deviation for the given phase of request\n                // refer Welford's online algorithm from\n                // https://en.wikipedia.org/wiki/Algorithms_for_calculating_variance\n                delta2 = currentValue - summary.run.timings[`${value}Average`];\n                currentVariance = (previousVariance * (requestCount - 1) + (delta1 * delta2)) / requestCount;\n                summary.run.timings[`${value}Sd`] = Math.sqrt(currentVariance);\n            });\n        });\n    },\n\n    attachFailureTrackers (summary, emitter) {\n        var eventsToTrack = ['beforeIteration', 'iteration', 'beforeItem', 'item', 'beforeScript', 'script',\n            'beforePrerequest', 'prerequest', 'beforeRequest', 'request', 'beforeTest', 'test', 'beforeAssertion',\n            'assertion'];\n\n        // accumulate failures of all events\n        // NOTE that surrogate events (which throw duplicate arguments) are not recorded\n        _.forEach(eventsToTrack, function (event) {\n            // push failures sent from \"before\" events\n            emitter.on(event, function (err, o) {\n                if (!err) { return; }\n\n                var item = o && o.item,\n                    source = event;\n\n                // in case of user script error, point to the line and column of the script and its type\n                if (event === 'script') {\n                    o.event && (source = o.event.listen + '-script');\n                    if (err.stacktrace && err.stacktrace[0] && err.stacktrace[0].lineNumber) {\n                        source += (':' + (err.stacktrace[0].lineNumber - 2));\n                        err.stacktrace[0].columnNumber && (source += (':' + err.stacktrace[0].columnNumber));\n                    }\n                }\n                // assertion errors need to know which assertion in the test was this\n                else if (event === 'assertion') {\n                    _.has(err, 'index') && (source += (':' + err.index));\n                    source += ' in test-script';\n                }\n\n                // if this is a plain error, convert it to serialised error\n                if (err.stack && !err.stacktrace) {\n                    err = new SerialiseError(err, true);\n                }\n\n                summary.run.failures.push({\n                    error: err,\n                    at: source,\n                    source: item || undefined,\n                    parent: item && item.__parent && item.__parent.__parent || undefined,\n                    cursor: o.cursor || {}\n                });\n            });\n        });\n    }\n});\n\nmodule.exports = RunSummary;\n"
  },
  {
    "path": "lib/util.js",
    "content": "var fs = require('fs'),\n    { Url } = require('postman-collection'),\n\n    _ = require('lodash'),\n    chardet = require('chardet'),\n    prettyms = require('pretty-ms'),\n    { filesize } = require('filesize'),\n    liquidJSON = require('liquid-json'),\n    request = require('postman-request'),\n\n    util,\n    version = require('../package.json').version,\n\n    SEP = ' / ',\n\n    /**\n     * The auxiliary character used to prettify file sizes from raw byte counts.\n     *\n     * @type {Object}\n     */\n    FILESIZE_OPTIONS = { spacer: '' },\n\n    /**\n     * Maps the charset returned by chardet to node buffer ones\n     *\n     * @constant\n     * @type {Object}\n     */\n    CHARDET_BUFF_MAP = {\n        ASCII: 'ascii',\n        'UTF-8': 'utf8',\n        'UTF-16LE': 'utf16le',\n        'ISO-8859-1': 'latin1'\n    },\n\n    POSTMAN_API_HOSTS = {\n        'api.postman.com': true,\n        'api.getpostman.com': true\n    },\n\n    POSTMAN_API_URL = 'https://api.postman.com',\n\n    /**\n     * Map of resource type and its equivalent API pathname.\n     *\n     * @type {Object}\n     */\n    POSTMAN_API_PATH_MAP = {\n        collection: 'collections',\n        environment: 'environments'\n    },\n\n    API_KEY_HEADER = 'X-Api-Key',\n\n    USER_AGENT_VALUE = 'Newman/' + version,\n\n    // Matches valid Postman UID, case insensitive.\n    // Same used for validation on the Postman API side.\n    UID_REGEX = /^[0-9A-Z]+-[0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}$/i;\n\nutil = {\n\n    /**\n     * The raw newman version, taken from package.json in the root directory\n     *\n     * @type {String}\n     */\n    version: version,\n\n    /**\n     * The user agent that this newman identifies as.\n     *\n     * @type {String}\n     */\n    userAgent: USER_AGENT_VALUE,\n\n    /**\n     * A utility helper method that prettifies and returns raw millisecond counts.\n     *\n     * @param {Number} ms - The raw millisecond count, usually from response times.\n     * @returns {String} - The prettified time, scaled to units of time, depending on the input value.\n     */\n    prettyms: function (ms) {\n        if (ms < 1) {\n            return `${parseInt(ms * 1000, 10)}µs`;\n        }\n\n        return (ms < 1998) ? `${parseInt(ms, 10)}ms` : prettyms(ms || 0);\n    },\n\n    /**\n     * Returns the time  object with all values in largest time unit possible as strings.\n     *\n     * @param {Object} obj - {event1: time1, event2: time2, ...} (time in milliseconds)\n     * @returns {Object} - {event1: time1, event2: time2, ...} (time in string with appropriate unit)\n     */\n    beautifyTime: function (obj) {\n        return _.forEach(obj, (value, key) => {\n            // convert only non-zero values\n            value && (obj[key] = this.prettyms(value));\n        });\n    },\n\n    /**\n     * A utility helper method to prettify byte counts into human readable strings.\n     *\n     * @param {Number} bytes - The raw byte count, usually from computed response sizes.\n     * @returns {String} - The prettified size, suffixed with scaled units, depending on the actual value provided.\n     */\n    filesize: function (bytes) {\n        return filesize(bytes || 0, FILESIZE_OPTIONS);\n    },\n\n    /**\n     * Resolves the fully qualified name for the provided item\n     *\n     * @param {PostmanItem|PostmanItemGroup} item The item for which to resolve the full name\n     * @param {?String} [separator=SEP] The separator symbol to join path name entries with\n     * @returns {String} The full name of the provided item, including prepended parent item names\n     * @private\n     */\n    getFullName: function (item, separator) {\n        if (_.isEmpty(item) || !_.isFunction(item.parent) || !_.isFunction(item.forEachParent)) { return; }\n\n        var chain = [];\n\n        item.forEachParent(function (parent) { chain.unshift(parent.name || parent.id); });\n\n        item.parent() && chain.push(item.name || item.id); // Add the current item only if it is not the collection\n\n        return chain.join(_.isString(separator) ? separator : SEP);\n    },\n\n    /**\n     * Given a buffer, it tries to match relevant encoding of the buffer.\n     *\n     * @param {Buffer} buff - Buffer for which encoding needs to be determined\n     * @returns {String|undefined} - Detected encoding of the given buffer\n     */\n    detectEncoding: function (buff) {\n        return CHARDET_BUFF_MAP[chardet.detect(buff)];\n    },\n\n    /**\n     * Loads JSON data from the given location.\n     *\n     * @param {String} type - The type of data to load.\n     * @param {String} location - Can be an HTTP URL, a local file path or an UID.\n     * @param {Object=} options - A set of options for JSON data loading.\n     * @param {Object} options.postmanApiKey - API Key used to load the resources via UID from the Postman API.\n     * @param {Function} callback - The function whose invocation marks the end of the JSON fetch routine.\n     * @returns {*}\n     */\n\n    fetchJson: function (type, location, options, callback) {\n        !callback && _.isFunction(options) && (callback = options, options = {});\n\n        const postmanApiKey = _.get(options, 'postmanApiKey'),\n            headers = { 'User-Agent': USER_AGENT_VALUE },\n            urlObj = new Url(location),\n            isPostmanHost = urlObj && POSTMAN_API_HOSTS[urlObj.getHost().toLowerCase()];\n\n        // build API URL if `location` is a valid UID and api key is provided.\n        // Fetch from file in case a file with valid UID name is present.\n        if (!fs.existsSync(location) && POSTMAN_API_PATH_MAP[type] && postmanApiKey && UID_REGEX.test(location)) {\n            location = `${POSTMAN_API_URL}/${POSTMAN_API_PATH_MAP[type]}/${location}`;\n            headers[API_KEY_HEADER] = postmanApiKey;\n        }\n\n        if (isPostmanHost) {\n            const apikey = urlObj.query.get('apikey') || postmanApiKey;\n\n            apikey && (headers[API_KEY_HEADER] = apikey);\n\n            urlObj.query.remove('apikey');\n            location = urlObj.toString();\n        }\n\n        return (/^https?:\\/\\/.*/).test(location) ?\n            request.get({\n                url: location,\n                json: true,\n                headers: headers\n            }, (err, response, body) => {\n                if (err) {\n                    return callback(_.set(err, 'help', `unable to fetch data from url \"${location}\"`));\n                }\n\n                try {\n                    _.isString(body) && (body = liquidJSON.parse(body.trim()));\n                }\n                catch (e) {\n                    return callback(_.set(e, 'help', `the url \"${location}\" did not provide valid JSON data`));\n                }\n\n                if (response.statusCode !== 200) {\n                    const resource = isPostmanHost ? _(urlObj.getPath()).split('/').get(1).slice(0, -1) : 'resource',\n                        error = new Error(_.get(body, 'error.message',\n                            // eslint-disable-next-line max-len\n                            `Error fetching ${resource}, the provided URL returned status code: ${response.statusCode}`));\n\n                    return callback(_.assign(error, {\n                        name: _.get(body, 'error.name', _.capitalize(resource) + 'FetchError'),\n                        help: `Error fetching the ${resource} from the provided URL. Ensure that the URL is valid.`\n                    }));\n                }\n\n                return callback(null, body);\n            }) :\n            fs.readFile(location, function (err, value) {\n                if (err) {\n                    return callback(_.set(err, 'help', `unable to read data from file \"${location}\"`));\n                }\n\n                try {\n                    value = liquidJSON.parse(value.toString(util.detectEncoding(value)).trim());\n                }\n                catch (e) {\n                    return callback(_.set(e, 'help', `the file at \"${location}\" does not contain valid JSON data`));\n                }\n\n                return callback(null, value);\n            });\n    },\n\n    /**\n     * Loads raw data from a location, useful for working with non JSON data such as CSV files.\n     *\n     * @param {String} location - The relative path / URL to the raw data file.\n     * @param {Object=} options - A set of load options for the raw data file.\n     * @param {Function} callback - The callback function whose invocation marks the end of the fetch routine.\n     * @returns {*}\n     */\n    fetch: function (location, options, callback) {\n        !callback && _.isFunction(options) && (callback = options, options = {});\n\n        return (/^https?:\\/\\/.*/).test(location) ?\n            // Load from URL\n            request.get({ url: location }, (err, response, body) => {\n                if (err) {\n                    return callback(err);\n                }\n\n                return callback(null, body);\n            }) :\n            fs.readFile(String(location), function (err, value) {\n                if (err) {\n                    return callback(err);\n                }\n\n                return callback(null, value.toString(util.detectEncoding(value)));\n            });\n    },\n\n    /**\n     * Checks whether the given object is a v1 collection\n     *\n     * Reference: https://github.com/postmanlabs/postman-collection-transformer/blob/v2.6.2/lib/index.js#L44\n     *\n     * @param {Object} object - The Object to check for v1 collection compliance.\n     * @returns {Boolean} - A boolean result indicating whether or not the passed object was a v1 collection.\n     */\n    isV1Collection: function (object) {\n        return Boolean(object && object.name && object.order && object.requests);\n    },\n\n    /**\n     * Helper function to test if a given string is an integer.\n     * Reference: [node-csv-parse]: https://github.com/adaltas/node-csv-parse/blob/v2.5.0/lib/index.js#L207\n     *\n     * @param {String} value - The string to test for.\n     * @returns {Boolean}\n     */\n    isInt: function (value) {\n        return (/^(-|\\+)?([1-9]+[0-9]*)$/).test(value);\n    },\n\n    /**\n     * Helper function to test if a given string is a float.\n     * Reference: [node-csv-parse]: https://github.com/adaltas/node-csv-parse/blob/v2.5.0/lib/index.js#L210\n     *\n     * @param {String} value - The string to test for.\n     * @returns {Boolean}\n     */\n    isFloat: function (value) {\n        return (value - parseFloat(value) + 1) >= 0;\n    }\n};\n\nmodule.exports = util;\n"
  },
  {
    "path": "npm/create-release.js",
    "content": "#!/usr/bin/env node\n// ---------------------------------------------------------------------------------------------------------------------\n// This script is intended to automate the versioning and changelog generation process for a release.\n// ---------------------------------------------------------------------------------------------------------------------\n\nconst shipit = require('@postman/shipit'),\n\n    // npm run release [true] [beta]\n    [pushToOrigin, preReleaseSuffix] = process.argv.splice(2);\n\n// only support `beta` suffix\nif (preReleaseSuffix && preReleaseSuffix !== 'beta') {\n    throw new Error(`Can't prerelease with \\`${preReleaseSuffix}\\` suffix.`);\n}\n\n// 🚢 Just Ship It!\nshipit({\n    mainBranch: 'main',\n    // don't push to origin unless explicitly set\n    pushToOrigin: pushToOrigin === 'true',\n    // prerelease suffix, if any\n    preReleaseSuffix: preReleaseSuffix,\n    // make sure that following dependencies are up to date\n    dependencyList: [\n        '@postman/tough-cookie', 'liquid-json', 'postman-collection',\n        'postman-collection-transformer', 'postman-request', 'postman-runtime',\n        'serialised-error'\n    ]\n}).then((version) => {\n    console.info('🚀', version);\n}).catch((err) => {\n    console.error('🔥', err);\n    process.exit(1);\n});\n"
  },
  {
    "path": "npm/docker-publish.sh",
    "content": "#!/bin/bash\n\n# Bail out on the first error\nset -e;\n\nLATEST=\"alpine\";\nRED=\"\\033[0;31m\";\nBLUE=\"\\033[0;34m\";\nNO_COLOUR=\"\\033[0m\";\nDOCKER_REPO=\"postman/newman\";\nVERSION=${npm_package_version};\nIMAGES_BASE_PATH=\"./docker/images\";\nIMAGES_PLATFORMS=\"linux/amd64,linux/arm64\";\nGIT_BRANCH=$(git rev-parse --abbrev-ref HEAD);\n\nif [[ ${GIT_BRANCH} != \"main\" ]]; then\n    echo -e \"$RED Not on main branch! $NO_COLOUR\";\n    exit 1;\nfi\n\n# It's good to be paranoid\n[[ -z \"$VERSION\" ]] && VERSION=$(jq -r \".version\" < package.json);\n\nMAJOR=$(echo ${VERSION} | grep -oE \"^\\d+\");\n\nfunction build_docker_image {\n    local TAG=$(basename $1);\n\n    echo \"\";\n\n    echo -e \"$BLUE Building $DOCKER_REPO:$VERSION-$TAG $NO_COLOUR\";\n\n    if [[ ${TAG} == ${LATEST} ]]; then\n        docker buildx build \\\n            --no-cache --file=\"docker/images/$TAG/Dockerfile\" \\\n            --build-arg NEWMAN_VERSION=${VERSION} --push \\\n            --platform ${IMAGES_PLATFORMS} \\\n            --tag ${DOCKER_REPO}:latest \\\n            --tag ${DOCKER_REPO}:${TAG} \\\n            --tag ${DOCKER_REPO}:${VERSION} \\\n            --tag ${DOCKER_REPO}:${MAJOR} \\\n            --tag ${DOCKER_REPO}:${VERSION}-${TAG} \\\n            --tag ${DOCKER_REPO}:${MAJOR}-${TAG} \\\n            .\n    else\n        docker buildx build \\\n            --no-cache --file=\"docker/images/$TAG/Dockerfile\" \\\n            --build-arg NEWMAN_VERSION=${VERSION} --push \\\n            --platform ${IMAGES_PLATFORMS} \\\n            --tag ${DOCKER_REPO}:${TAG} \\\n            --tag ${DOCKER_REPO}:${VERSION}-${TAG} \\\n            --tag ${DOCKER_REPO}:${MAJOR}-${TAG} \\\n            .\n    fi\n\n    echo -e \"$BLUE Running docker image test for $DOCKER_REPO:$VERSION-$TAG, latest $NO_COLOUR\";\n\n    # Test\n    docker run -v ${PWD}/examples:/etc/newman -t ${DOCKER_REPO}:${VERSION}-${TAG} run \"sample-collection.json\";\n}\n\nfor image in ${IMAGES_BASE_PATH}/*; do\n    build_docker_image ${image};\ndone\n"
  },
  {
    "path": "npm/server.js",
    "content": "const net = require('net'),\n    http = require('http'),\n    enableServerDestroy = require('server-destroy');\n\n/**\n * Echo raw request message to test\n *  - Body for HTTP methods like GET, HEAD\n *  - Custom HTTP methods\n *\n * @example\n * var s = createRawEchoServer();\n *\n * s.listen(3000, function() {\n *   console.log(s.port);\n *   s.close();\n * });\n *\n * @note For HEAD request, read body from `raw-request` response header\n */\nfunction createRawEchoServer () {\n    var server;\n\n    server = net.createServer(function (socket) {\n        socket.on('data', function (chunk) {\n            if (this.data === undefined) {\n                this.data = '';\n\n                setTimeout(() => {\n                    // Status Line\n                    socket.write('HTTP/1.1 200 ok\\r\\n');\n\n                    // Response Headers\n                    socket.write('connection: close\\r\\n');\n                    socket.write('content-type: text/plain\\r\\n');\n                    socket.write('raw-request: ' + JSON.stringify(this.data) + '\\r\\n');\n\n                    // CRLF\n                    socket.write('\\r\\n');\n\n                    // Response Body\n                    if (!this.data.startsWith('HEAD / HTTP/1.1')) {\n                        socket.write(this.data);\n                    }\n\n                    socket.end();\n                }, 1000);\n            }\n\n            this.data += chunk.toString();\n        });\n    });\n\n    server.on('listening', function () {\n        server.port = this.address().port;\n    });\n\n    enableServerDestroy(server);\n\n    return server;\n}\n\n/**\n * Redirect + Echo Server\n *  - Follows specified redirects -> /<redirects-count>\n *  - Redirects with specified response code -> /status/<response-code>\n *  - Echos final request URL, Method, Headers and Body\n *\n * @example\n * var s = createRedirectServer();\n *\n * s.listen(3000, function() {\n *   console.log(s.port);\n *   s.close();\n * });\n */\nfunction createRedirectServer () {\n    var server;\n\n    server = http.createServer(function (req, res) {\n        var hops,\n            data = '';\n\n        // path: /{n}\n        if ((/^\\/\\d+$/).test(req.url)) {\n            hops = parseInt(req.url.substring(1), 10) - 1;\n\n            // redirect until all hops are covered\n            res.writeHead(302, {\n                location: hops > 0 ? `/${hops}` : '/'\n            });\n\n            return res.end();\n        }\n        // path: /status/<responseCode>\n        else if ((/^\\/status\\/(\\d{3})$/).test(req.url)) {\n            res.writeHead(parseInt(req.url.substr(-3), 10), { location: '/' });\n\n            return res.end();\n        }\n\n        req.on('data', function (d) { data += d; });\n\n        req.once('end', function () {\n            res.writeHead(200, { connection: 'close', 'Content-Type': 'application/json' });\n            res.end(JSON.stringify({\n                url: req.url,\n                method: req.method,\n                headers: req.headers,\n                data: data\n            }));\n        });\n    });\n\n    server.on('listening', function () {\n        server.port = this.address().port;\n    });\n\n    enableServerDestroy(server);\n\n    return server;\n}\n\nmodule.exports = {\n    createRawEchoServer,\n    createRedirectServer\n};\n"
  },
  {
    "path": "npm/test-cli.js",
    "content": "#!/usr/bin/env node\n// ---------------------------------------------------------------------------------------------------------------------\n// This script is intended to execute all cli tests.\n// ---------------------------------------------------------------------------------------------------------------------\n\nconst path = require('path'),\n\n    Mocha = require('mocha'),\n    exec = require('shelljs').exec,\n    colors = require('colors/safe'),\n    recursive = require('recursive-readdir'),\n\n    SPEC_SOURCE_DIR = path.join('test', 'cli');\n\nmodule.exports = function (exit) {\n    // banner line\n    console.info(colors.yellow.bold('Running CLI integration tests using mocha and shelljs...'));\n\n    // add all spec files to mocha\n    recursive(SPEC_SOURCE_DIR, (err, files) => {\n        if (err) {\n            console.error(err);\n\n            return exit(1);\n        }\n\n        const mocha = new Mocha({ timeout: 1000 * 60 });\n\n        files.filter((file) => { // extract all test files\n            return (file.substr(-8) === '.test.js');\n        }).forEach(mocha.addFile.bind(mocha));\n\n        // override exec for it to become silent by default\n        global.exec = function (cmd, done) {\n            return exec(cmd, { silent: true }, done);\n        };\n\n        // start the mocha run\n        mocha.run((runError) => {\n            delete global.exec;\n            runError && console.error(runError.stack || runError);\n\n            exit(runError || process.exitCode ? 1 : 0);\n        });\n    });\n};\n\n// ensure we run this script exports if this is a direct stdin.tty run\n!module.parent && module.exports(process.exit);\n"
  },
  {
    "path": "npm/test-integration.js",
    "content": "#!/usr/bin/env node\n// ---------------------------------------------------------------------------------------------------------------------\n// This script is intended to execute all integration tests.\n// ---------------------------------------------------------------------------------------------------------------------\n\nconst fs = require('fs'),\n    path = require('path'),\n\n    _ = require('lodash'),\n    async = require('async'),\n    colors = require('colors/safe'),\n    recursive = require('recursive-readdir'),\n    newman = require(path.join(__dirname, '..', 'index')),\n\n    echoServer = require('./server').createRawEchoServer(),\n    redirectServer = require('./server').createRedirectServer(),\n\n    LOCAL_TEST_ECHO_PORT = 4041,\n    LOCAL_TEST_REDIRECT_PORT = 4042,\n\n    SPEC_SOURCE_DIR = path.join(__dirname, '..', 'test', 'integration');\n\nmodule.exports = function (exit) {\n    // banner line\n    console.info(colors.yellow.bold('Running integration tests using local newman as node module...'));\n\n    async.waterfall([\n\n        /**\n         * Fetch all files within SPEC_SOURCE_DIR.\n         *\n         * @param {Function} next - A callback function that is invoked after the files have been fetched.\n         * @returns {*}\n         */\n        function (next) {\n            recursive(SPEC_SOURCE_DIR, next);\n        },\n\n        /**\n         * Ensures that we proceed only if files exist and has appropriate name conventions.\n         *\n         * @param {Array} files - An array of strings, each of which represents the path to an integration test file.\n         * @param {Function} next - A callback function whose invocation marks the end of the file processing routine.\n         * @returns {*}\n         */\n        function (files, next) {\n            next(null, _.reduce(files, function (suites, path) {\n                // regex: [0:path, 1:test, 2:syntax, 3:skipped, 4: file-format]\n                const parts = path.match(/(.+)\\.postman_([^.]+)(\\.skip)?\\.([^.]{3,})$/i);\n\n                if (!parts) { // if a spec file did not match the pattern, log warning and move on\n                    return (console.warn(colors.gray(` - ignored: ${path}`)), suites);\n                }\n                else if (parts[3]) { // do not parse skipped files\n                    return (console.warn(colors.cyan(` - skipped: ${path}`)), suites);\n                }\n\n                // add the test to the tracking object\n                (suites[parts[1]] || (suites[parts[1]] = {\n                    name: parts[1]\n                }))[`${parts[2]}${parts[4].toUpperCase()}`] = path;\n\n                return suites;\n            }, {}));\n        },\n\n        /**\n         * Start local server used in collections\n         *   - echoServer = custom HTTP method, body with GET\n         *   - redirectServer = protocol profile behavior\n         *\n         * @param {Object} suites - An set of tests, arranged by test group names as keys.\n         * @param {Function} next - A callback function whose invocation marks the end of the integration test run.\n         * @returns {*}\n         */\n        function (suites, next) {\n            // start echoServer first\n            echoServer.listen(LOCAL_TEST_ECHO_PORT, function (err) {\n                if (err) { return next(err); }\n                // start redirectServer once echoServer is started\n                redirectServer.listen(LOCAL_TEST_REDIRECT_PORT, function (err) {\n                    next(err, suites);\n                });\n            });\n        },\n\n        /**\n         * Execute each integration test suite using newman.\n         *\n         * @param {Object} suites - An set of tests, arranged by test group names as keys.\n         * @param {Function} next - A callback function whose invocation marks the end of the integration test run.\n         * @returns {*}\n         */\n        function (suites, next) {\n            if (_.isEmpty(suites)) { // if no test files found, it is an error\n                return next(new Error(`No test files found in ${SPEC_SOURCE_DIR}`));\n            }\n\n            console.info(`\\nexecuting ${Object.keys(suites).length} tests in parallel (might take a while)...\\n`);\n\n            // run tests using the consolidated test set as a guide\n            async.mapLimit(suites, 10, function (test, next) {\n                console.info(` - ${test.name}`);\n\n                // load configuration JSON object if it is provided. We do this since this is not part of newman\n                // standard API\n                const config = test.configJSON ? JSON.parse(fs.readFileSync(test.configJSON).toString()) : {};\n\n                newman.run(_.merge({\n                    collection: test.collectionJSON,\n                    environment: test.environmentJSON,\n                    globals: test.globalsJSON,\n                    iterationData: test.dataCSV || test.dataJSON,\n                    abortOnFailure: true\n                }, config.run), function (err, summary) {\n                    err && (err.source = test); // store the meta in error\n                    next(err, summary);\n                });\n            }, next);\n        }\n    ],\n\n    /**\n     * The integration test exit handler. Receives the error (if at all) from the integration test runner and exits\n     * accordingly, displaying either a success message or an error message and it's corresponding stacktrace.\n     *\n     * @param {?Error} err - An object that is either null or a standard error object.\n     * @param {Array} results - An array of integration test result objects, one per integration test collection run.\n     * @returns {*}\n     */\n    function (err, results) {\n        if (!err) {\n            console.info(colors.green(`\\n${results.length} integrations ok!\\n`));\n        }\n        else {\n            console.error(colors.red('\\nintegration test failed:'));\n            console.error(_.omit(err, ['stacktrace', 'stack']), { colors: true });\n        }\n\n        // destroy echoServer\n        echoServer.destroy(function () {\n            // destroy redirectServer\n            redirectServer.destroy(function () {\n                // exit once both the local server are stopped\n                exit(err || process.exitCode ? 1 : 0, results);\n            });\n        });\n    });\n};\n\n// ensure we run this script exports if this is a direct stdin.tty run\n!module.parent && module.exports(process.exit);\n"
  },
  {
    "path": "npm/test-library.js",
    "content": "#!/usr/bin/env node\n// ---------------------------------------------------------------------------------------------------------------------\n// This script is intended to execute all library tests.\n// ---------------------------------------------------------------------------------------------------------------------\n\nconst path = require('path'),\n\n    colors = require('colors/safe'),\n    Mocha = require('mocha'),\n    recursive = require('recursive-readdir'),\n\n    SPEC_SOURCE_DIR = path.join('test', 'library');\n\nmodule.exports = function (exit) {\n    // banner line\n    console.info(colors.yellow.bold('Running library tests using mocha on node...'));\n\n    // add all spec files to mocha\n    recursive(SPEC_SOURCE_DIR, (err, files) => {\n        if (err) {\n            console.error(err);\n\n            return exit(1);\n        }\n\n        const mocha = new Mocha({ timeout: 1000 * 60 });\n\n        files.filter((file) => { // extract all test files\n            return (file.substr(-8) === '.test.js');\n        }).forEach(mocha.addFile.bind(mocha));\n\n        // start the mocha run\n        mocha.run((runError) => {\n            runError && console.error(runError.stack || runError);\n\n            exit(runError || process.exitCode ? 1 : 0);\n        });\n    });\n};\n\n// ensure we run this script exports if this is a direct stdin.tty run\n!module.parent && module.exports(process.exit);\n"
  },
  {
    "path": "npm/test-lint.js",
    "content": "#!/usr/bin/env node\n// ---------------------------------------------------------------------------------------------------------------------\n// This script is intended to contain all actions pertaining to code style checking, linting and normalization.\n// ---------------------------------------------------------------------------------------------------------------------\n\nconst colors = require('colors/safe'),\n    { ESLint } = require('eslint'),\n\n    LINT_SOURCE_DIRS = [\n        './lib',\n        './bin',\n        './test',\n        './examples/*.js',\n        './npm/*.js',\n        './index.js'\n    ];\n\nmodule.exports = async function (exit) {\n    // banner line\n    console.info(colors.yellow.bold('\\nLinting files using eslint...'));\n\n    const eslint = new ESLint(),\n        results = await eslint.lintFiles(LINT_SOURCE_DIRS),\n        errorReport = ESLint.getErrorResults(results),\n        formatter = await eslint.loadFormatter();\n\n    // log the result to CLI\n    console.info(formatter.format(results));\n\n    (errorReport && !errorReport.length) && console.info(colors.green('eslint ok!'));\n\n    exit(Number(errorReport && errorReport.length) || 0);\n};\n\n// ensure we run this script exports if this is a direct stdin.tty run\n!module.parent && module.exports(process.exit);\n"
  },
  {
    "path": "npm/test-system.js",
    "content": "#!/usr/bin/env node\n// ---------------------------------------------------------------------------------------------------------------------\n// This script is intended to execute all system tests.\n// ---------------------------------------------------------------------------------------------------------------------\n\nconst path = require('path'),\n\n    Mocha = require('mocha'),\n    colors = require('colors/safe'),\n    recursive = require('recursive-readdir'),\n    { exec } = require('shelljs'),\n\n    SPEC_SOURCE_DIR = path.join(__dirname, '..', 'test', 'system');\n\nmodule.exports = function (exit) {\n    // banner line\n    console.info(colors.yellow.bold('\\nRunning system tests using mocha...'));\n\n    // add all spec files to mocha\n    recursive(SPEC_SOURCE_DIR, (err, files) => {\n        if (err) {\n            console.error(err);\n\n            return exit(1);\n        }\n\n        const mocha = new Mocha({ timeout: 1000 * 60 });\n\n        files.filter((file) => { // extract all test files\n            return (file.substr(-8) === '.test.js');\n        }).forEach(mocha.addFile.bind(mocha));\n\n        // start the mocha run\n        mocha.run((runError) => {\n            if (runError) {\n                console.error(runError.stack || runError);\n\n                return exit(1);\n            }\n\n            // ensure all dependencies are okay\n            console.info(colors.yellow('checking package dependencies...\\n'));\n            exec('dependency-check ./package.json --extra --no-dev --missing', (code) => {\n                exit(code ? 1 : 0);\n            });\n        });\n    });\n};\n\n// ensure we run this script exports if this is a direct stdin.tty run\n!module.parent && module.exports(process.exit);\n"
  },
  {
    "path": "npm/test-unit.js",
    "content": "#!/usr/bin/env node\n// ---------------------------------------------------------------------------------------------------------------------\n// This script is intended to execute all unit tests.\n// ---------------------------------------------------------------------------------------------------------------------\n\nconst path = require('path'),\n\n    colors = require('colors/safe'),\n    Mocha = require('mocha'),\n    recursive = require('recursive-readdir'),\n\n    SPEC_SOURCE_DIR = path.join('test', 'unit');\n\nmodule.exports = function (exit) {\n    // banner line\n    console.info(colors.yellow.bold('Running unit tests using mocha on node...'));\n\n    // add all spec files to mocha\n    recursive(SPEC_SOURCE_DIR, (err, files) => {\n        if (err) {\n            console.error(err);\n\n            return exit(1);\n        }\n\n        const mocha = new Mocha({ timeout: 1000 * 60 });\n\n        files.filter((file) => { // extract all test files\n            return (file.substr(-8) === '.test.js');\n        }).forEach(mocha.addFile.bind(mocha));\n\n        // start the mocha run\n        mocha.run((runError) => {\n            runError && console.error(runError.stack || runError);\n\n            exit(runError || process.exitCode ? 1 : 0);\n        });\n    });\n};\n\n// ensure we run this script exports if this is a direct stdin.tty run\n!module.parent && module.exports(process.exit);\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"newman\",\n  \"version\": \"6.2.2\",\n  \"description\": \"Command-line companion utility for Postman\",\n  \"author\": \"Postman Labs <help@postman.com> (=)\",\n  \"license\": \"Apache-2.0\",\n  \"homepage\": \"https://github.com/postmanlabs/newman\",\n  \"bugs\": \"https://github.com/postmanlabs/newman/issues\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git://github.com/postmanlabs/newman.git\"\n  },\n  \"keywords\": [\n    \"newman\",\n    \"postman\",\n    \"api\",\n    \"testing\",\n    \"ci\",\n    \"rest-client\",\n    \"rest\"\n  ],\n  \"main\": \"index.js\",\n  \"bin\": {\n    \"newman\": \"./bin/newman.js\"\n  },\n  \"preferGlobal\": true,\n  \"scripts\": {\n    \"docker-publish\": \"./npm/docker-publish.sh\",\n    \"release\": \"node npm/create-release.js\",\n    \"test\": \"npm run test-lint && npm run test-system && npm run test-unit && npm run test-integration && npm run test-cli && npm run test-library\",\n    \"test-cli\": \"nyc --nycrc-path=.nycrc.js node npm/test-cli.js\",\n    \"test-integration\": \"nyc --nycrc-path=.nycrc.js node npm/test-integration.js\",\n    \"test-library\": \"nyc --nycrc-path=.nycrc.js node npm/test-library.js\",\n    \"test-lint\": \"node npm/test-lint.js\",\n    \"test-system\": \"node npm/test-system.js\",\n    \"test-unit\": \"nyc --nycrc-path=.nycrc.js node npm/test-unit.js\"\n  },\n  \"dependencies\": {\n    \"@postman/tough-cookie\": \"4.1.3-postman.1\",\n    \"async\": \"3.2.5\",\n    \"chardet\": \"2.0.0\",\n    \"cli-progress\": \"3.12.0\",\n    \"cli-table3\": \"0.6.5\",\n    \"colors\": \"1.4.0\",\n    \"commander\": \"11.1.0\",\n    \"csv-parse\": \"4.16.3\",\n    \"filesize\": \"10.1.4\",\n    \"liquid-json\": \"0.3.1\",\n    \"lodash\": \"4.17.21\",\n    \"mkdirp\": \"3.0.1\",\n    \"postman-collection\": \"4.4.0\",\n    \"postman-collection-transformer\": \"4.1.8\",\n    \"postman-request\": \"2.88.1-postman.48\",\n    \"postman-runtime\": \"7.39.1\",\n    \"pretty-ms\": \"7.0.1\",\n    \"semver\": \"7.6.3\",\n    \"serialised-error\": \"1.1.3\",\n    \"word-wrap\": \"1.2.5\",\n    \"xmlbuilder\": \"15.1.1\"\n  },\n  \"devDependencies\": {\n    \"@postman/shipit\": \"^0.4.0\",\n    \"chai\": \"^4.4.1\",\n    \"dependency-check\": \"^4.1.0\",\n    \"dockerfile_lint\": \"^0.3.4\",\n    \"editorconfig\": \"^2.0.0\",\n    \"eslint\": \"^8.56.0\",\n    \"eslint-plugin-jsdoc\": \"^46.9.1\",\n    \"eslint-plugin-lodash\": \"^7.4.0\",\n    \"eslint-plugin-mocha\": \"^10.5.0\",\n    \"eslint-plugin-security\": \"^2.1.1\",\n    \"js-yaml\": \"^4.1.0\",\n    \"mocha\": \"^10.7.3\",\n    \"nock\": \"^13.5.4\",\n    \"nyc\": \"^15.1.0\",\n    \"parse-gitignore\": \"^2.0.0\",\n    \"recursive-readdir\": \"^2.2.3\",\n    \"server-destroy\": \"^1.0.1\",\n    \"shelljs\": \"^0.8.5\",\n    \"sinon\": \"^18.0.0\",\n    \"xml2js\": \"^0.6.2\"\n  },\n  \"engines\": {\n    \"node\": \">=16\"\n  },\n  \"overrides\": {\n    \"postman-request\": \"2.88.1-postman.48\",\n    \"node-forge\": \"1.3.3\",\n    \"jose\": \"5.10.0\"\n  }\n}\n"
  },
  {
    "path": "test/.eslintrc",
    "content": "{\n    \"plugins\": [\n        \"mocha\"\n    ],\n    \"env\": {\n        \"mocha\": true,\n        \"browser\": true,\n        \"node\": true,\n        \"es6\": true\n    },\n    \"globals\": {\n        \"exec\": true\n    },\n    \"rules\": {\n        // JSDoc\n        \"jsdoc/require-param-type\": \"off\",\n        \"jsdoc/require-param-description\": \"off\",\n\n        // Mocha\n        \"mocha/handle-done-callback\": \"error\",\n        \"mocha/max-top-level-suites\": \"error\",\n        \"mocha/no-exclusive-tests\": \"error\",\n        \"mocha/no-global-tests\": \"error\",\n        \"mocha/no-hooks-for-single-case\": \"off\",\n        \"mocha/no-hooks\": \"off\",\n        \"mocha/no-identical-title\": \"error\",\n        \"mocha/no-mocha-arrows\": \"error\",\n        \"mocha/no-nested-tests\": \"error\",\n        \"mocha/no-pending-tests\": \"error\",\n        \"mocha/no-return-and-callback\": \"error\",\n        \"mocha/no-sibling-hooks\": \"error\",\n        \"mocha/no-skipped-tests\": \"off\",\n        \"mocha/no-synchronous-tests\": \"off\",\n        \"mocha/no-top-level-hooks\": \"off\",\n        \"mocha/valid-test-description\": \"off\",\n        \"mocha/valid-suite-description\": \"off\"\n    }\n  }\n"
  },
  {
    "path": "test/cli/cli-reporter-failure-details.test.js",
    "content": "const expect = require('chai').expect;\n\ndescribe('CLI reporter failure details', function () {\n    it('should correctly show complete details for the failure list', function (done) {\n        // eslint-disable-next-line max-len\n        exec('node ./bin/newman.js run test/fixtures/run/single-request-failing.json --reporter-cli-no-assertion --reporter-cli-no-summary', function (code, stdout, stderr) {\n            expect(code).be.ok;\n            expect(stderr).to.be.empty;\n            expect(stdout).to.contain('1.  AssertionError  response code is 200');\n            expect(stdout).to.contain('expected false to be truthy');\n            expect(stdout).to.contain('at assertion:0 in test-script');\n            expect(stdout).to.contain('inside \"Status Code Test\"');\n\n            done();\n        });\n    });\n});\n"
  },
  {
    "path": "test/cli/cli-reporter-no-success-assertsions.test.js",
    "content": "const expect = require('chai').expect;\n\n\ndescribe('CLI reporter no success assertions', function () {\n    const noSuccessOutput = /response\\s+code\\s+is\\s+200/;\n\n    it('should produce normal output', function (done) {\n        exec('node ./bin/newman.js run test/fixtures/run/single-get-request.json',\n            function (code, stdout, stderr) {\n                expect(code, 'should have exit code of 0').to.equal(0);\n                expect(stderr).to.be.empty;\n                expect(stdout).to.match(noSuccessOutput);\n\n                done(code);\n            });\n    });\n\n    it('should not contain success output', function (done) {\n        exec('node ./bin/newman.js run test/fixtures/run/single-get-request.json --reporter-cli-no-success-assertions',\n            function (code, stdout, stderr) {\n                expect(code, 'should have exit code of 0').to.equal(0);\n                expect(stderr).to.be.empty;\n                expect(stdout).to.not.match(noSuccessOutput);\n\n                done(code);\n            });\n    });\n});\n"
  },
  {
    "path": "test/cli/cli-reporter-show-timestamp.test.js",
    "content": "const expect = require('chai').expect;\n\ndescribe('CLI reporter logging timestamp', function () {\n    const timeRegex = /([01]?[0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9]/;\n\n    it('should log timestamp', function (done) {\n        exec('node ./bin/newman.js run test/fixtures/run/single-get-request.json --reporter-cli-show-timestamps',\n            function (code, stdout, stderr) {\n                expect(code, 'should have exit code of 0').to.equal(0);\n                expect(stderr).to.be.empty;\n                expect(stdout).to.match(timeRegex);\n\n                done(code);\n            });\n    });\n});\n"
  },
  {
    "path": "test/cli/color-tty.test.js",
    "content": "const fs = require('fs'),\n    expect = require('chai').expect;\n\ndescribe('CLI output', function () {\n    // eslint-disable-next-line no-control-regex\n    const coloredOutput = /\\u001b/;\n\n    describe('TTY', function () {\n        // @todo: Change to assert colored output after https://github.com/shelljs/shelljs/pull/524 is released\n        // figure out a way to have `process.stdout.isTTY` true for the child process.\n        it.skip('should produce colored output without any options', function (done) {\n            exec('node ./bin/newman.js run test/fixtures/run/single-get-request.json', function (code, stdout, stderr) {\n                expect(code, 'should have exit code of 0').to.equal(0);\n                expect(stderr).to.be.empty;\n                expect(stdout).to.match(coloredOutput);\n\n                done(code);\n            });\n        });\n\n        it('should produce colored output with `--color on`', function (done) {\n            // eslint-disable-next-line max-len\n            exec('node ./bin/newman.js run test/fixtures/run/single-get-request.json --color on', function (code, stdout, stderr) {\n                expect(code, 'should have exit code of 0').to.equal(0);\n                expect(stderr).to.be.empty;\n                expect(stdout).to.match(coloredOutput);\n\n                done(code);\n            });\n        });\n\n        it('should not produce colored output with `--color off`', function (done) {\n            // eslint-disable-next-line max-len\n            exec('node ./bin/newman.js run test/fixtures/run/single-get-request.json --color off', function (code, stdout, stderr) {\n                expect(code, 'should have exit code of 0').to.equal(0);\n                expect(stderr).to.be.empty;\n                expect(stdout).to.not.match(coloredOutput);\n\n                done(code);\n            });\n        });\n    });\n\n    describe('noTTY', function () {\n        var encoding = 'utf-8',\n            outFile = 'out/color-tty-test.txt';\n\n        beforeEach(function (done) {\n            fs.stat('out', function (err) {\n                if (err) {\n                    return fs.mkdir('out', done);\n                }\n\n                done();\n            });\n        });\n\n        afterEach(function (done) {\n            fs.stat(outFile, function (err) {\n                if (err) {\n                    return done();\n                }\n\n                fs.unlink(outFile, done);\n            });\n        });\n\n        // @todo figure out a way to have `process.stdout.isTTY` true for the child process.\n        // using `tty.WriteStream` might solve the problem.\n        it.skip('should produce colored output without any options', function (done) {\n            exec(`node ./bin/newman.js run test/fixtures/run/single-get-request.json > ${outFile}`,\n                function (code, stdout, stderr) {\n                    expect(code, 'should have exit code of 0').to.equal(0);\n                    expect(stderr).to.be.empty;\n                    expect(stdout).to.be.empty;\n\n                    fs.readFile(outFile, encoding, function (err, data) {\n                        if (err) { return done(err); }\n\n                        expect(data).to.match(coloredOutput);\n                        done();\n                    });\n                });\n        });\n\n        it('should produce colored output with `--color on`', function (done) {\n            exec(`node ./bin/newman.js run test/fixtures/run/single-get-request.json --color on > ${outFile}`,\n                function (code, stdout, stderr) {\n                    expect(code, 'should have exit code of 0').to.equal(0);\n                    expect(stderr).to.be.empty;\n                    expect(stdout).to.be.empty;\n\n                    fs.readFile(outFile, encoding, function (err, data) {\n                        if (err) { return done(err); }\n\n                        expect(data).to.match(coloredOutput);\n                        done();\n                    });\n                });\n        });\n\n        it('should not produce colored output with `--color off`', function (done) {\n            exec(`node ./bin/newman.js run test/fixtures/run/single-get-request.json --color off > ${outFile}`,\n                function (code, stdout, stderr) {\n                    expect(code, 'should have exit code of 0').to.equal(0);\n                    expect(stderr).to.be.empty;\n                    expect(stdout).to.be.empty;\n\n                    fs.readFile(outFile, encoding, function (err, data) {\n                        if (err) { return done(err); }\n\n                        expect(data).to.not.match(coloredOutput);\n                        done();\n                    });\n                });\n        });\n    });\n});\n"
  },
  {
    "path": "test/cli/export-environment.test.js",
    "content": "const fs = require('fs'),\n    path = require('path'),\n\n    sh = require('shelljs'),\n    expect = require('chai').expect,\n\n    outDir = 'out',\n    exportedEnvironmentPath = path.join(__dirname, '..', '..', outDir, 'test-environment.json');\n\ndescribe('newman run --export-environment', function () {\n    beforeEach(function () {\n        sh.test('-d', outDir) && sh.rm('-rf', outDir);\n        sh.mkdir('-p', outDir);\n    });\n\n    afterEach(function () {\n        sh.rm('-rf', outDir);\n    });\n\n    it('should export environment to a file', function (done) {\n        // eslint-disable-next-line max-len\n        exec('node ./bin/newman.js run test/fixtures/run/single-get-request.json -e test/fixtures/run/simple-variables.json --export-environment out/test-environment.json', function (code) {\n            var environment;\n\n            try { environment = JSON.parse(fs.readFileSync(exportedEnvironmentPath).toString()); }\n            catch (e) { console.error(e); }\n\n            expect(code, 'should have exit code of 0').to.equal(0);\n            expect(environment).to.be.ok;\n            expect(environment).to.have.property('_postman_exported_at');\n            expect(environment).to.have.property('values');\n            expect(environment.values).to.eql([\n                { key: 'var-1', value: 'value-1', type: 'any' },\n                { key: 'var-2', value: 'value-2', type: 'any' }\n            ]);\n            expect(environment).to.have.property('_postman_variable_scope', 'environment');\n            done();\n        });\n    });\n\n    it('should export environment to a file even if collection is failing', function (done) {\n        // eslint-disable-next-line max-len\n        exec('node ./bin/newman.js run test/fixtures/run/single-request-failing.json -e test/fixtures/run/simple-variables.json --export-environment out/test-environment.json', function (code) {\n            var environment;\n\n            try { environment = JSON.parse(fs.readFileSync(exportedEnvironmentPath).toString()); }\n            catch (e) { console.error(e); }\n\n            expect(code, 'should not have exit code of 0').not.to.equal(0);\n            expect(environment).to.be.ok;\n            expect(environment).to.have.property('_postman_exported_at');\n            expect(environment).to.have.property('values');\n            expect(environment.values).to.eql([\n                { key: 'var-1', value: 'value-1', type: 'any' },\n                { key: 'var-2', value: 'value-2', type: 'any' }\n            ]);\n            expect(environment).to.have.property('_postman_variable_scope', 'environment');\n            done();\n        });\n    });\n\n    it('`newman run` should export environment to a file in a pre-existing directory', function (done) {\n        // eslint-disable-next-line max-len\n        exec('node ./bin/newman.js run test/fixtures/run/single-get-request.json -e test/fixtures/run/simple-variables.json --export-environment out', function (code) {\n            var environment,\n                dir = fs.readdirSync(outDir),\n                file = dir[0];\n\n            expect(dir).to.have.length(1);\n\n            try { environment = JSON.parse(fs.readFileSync(outDir + '/' + file).toString()); }\n            catch (e) { console.error(e); }\n\n            expect(code).to.equal(0);\n            expect(environment).to.be.ok;\n            expect(environment).have.property('_postman_exported_at');\n            expect(environment).have.property('values');\n            expect(environment.values).eql([\n                { key: 'var-1', value: 'value-1', type: 'any' },\n                { key: 'var-2', value: 'value-2', type: 'any' }\n            ]);\n            expect(environment).have.property('_postman_variable_scope', 'environment');\n            done();\n        });\n    });\n\n    it('should override exported environment with those provided via --env-var', function (done) {\n        // eslint-disable-next-line max-len\n        exec('node ./bin/newman.js run test/fixtures/overrides/pmcollection.json --env-var dummyVar=bar2 --export-environment out/test-environment.json', function (code) {\n            var environment;\n\n            try { environment = JSON.parse(fs.readFileSync(exportedEnvironmentPath).toString()); }\n            catch (e) { console.error(e); }\n\n            expect(code, 'should have exit code of 0').to.eql(0);\n            expect(environment).to.be.ok;\n            expect(environment).to.have.property('_postman_exported_at');\n            expect(environment).to.have.property('values');\n            expect(environment.values).eql([\n                { key: 'dummyVar', value: 'bar2', type: 'any' }\n            ]);\n            expect(environment).to.have.property('_postman_variable_scope', 'environment');\n            done();\n        });\n    });\n\n    it('should override exported environment with those provided via --env-var even when run fails', function (done) {\n        // eslint-disable-next-line max-len\n        exec('node ./bin/newman.js run test/fixtures/overrides/failing-collection.json --env-var dummyVar=bar3 --export-environment out/test-environment.json', function (code) {\n            var environment;\n\n            try { environment = JSON.parse(fs.readFileSync(exportedEnvironmentPath).toString()); }\n            catch (e) { console.error(e); }\n\n            expect(code, 'should not have exit code of 0').to.not.be.eql(0);\n            expect(environment).to.be.ok;\n            expect(environment).to.have.property('_postman_exported_at');\n            expect(environment).to.have.property('values');\n            expect(environment.values).eql([\n                { key: 'dummyVar', value: 'bar3', type: 'any' }\n            ]);\n            expect(environment).to.have.property('_postman_variable_scope', 'environment');\n            done();\n        });\n    });\n});\n"
  },
  {
    "path": "test/cli/export-globals.test.js",
    "content": "const fs = require('fs'),\n    path = require('path'),\n\n    sh = require('shelljs'),\n    expect = require('chai').expect,\n\n\n    outDir = 'out',\n    exportedGlobalsPath = path.join(__dirname, '..', '..', 'out', 'test-globals.json');\n\ndescribe('newman run --export-globals', function () {\n    beforeEach(function () {\n        sh.test('-d', outDir) && sh.rm('-rf', outDir);\n        sh.mkdir('-p', outDir);\n    });\n\n    afterEach(function () {\n        sh.rm('-rf', outDir);\n    });\n\n    it('should export globals to a file', function (done) {\n        // eslint-disable-next-line max-len\n        exec('node ./bin/newman.js run test/fixtures/run/single-get-request.json -g test/fixtures/run/simple-variables.json --export-globals out/test-globals.json', function (code) {\n            var globals;\n\n            try { globals = JSON.parse(fs.readFileSync(exportedGlobalsPath).toString()); }\n            catch (e) { console.error(e); }\n\n            expect(code, 'should have exit code of 0').to.equal(0);\n            expect(globals).to.be.ok;\n            expect(globals).to.have.property('_postman_exported_at');\n            expect(globals).to.have.property('values');\n            expect(globals.values).eql([\n                { key: 'var-1', value: 'value-1', type: 'any' },\n                { key: 'var-2', value: 'value-2', type: 'any' }\n            ]);\n            expect(globals).to.have.property('_postman_variable_scope', 'globals');\n            done();\n        });\n    });\n\n    it('should export globals to a file even if collection is failing', function (done) {\n        // eslint-disable-next-line max-len\n        exec('node ./bin/newman.js run test/fixtures/run/single-request-failing.json -g test/fixtures/run/simple-variables.json --export-globals out/test-globals.json', function (code) {\n            var globals;\n\n            try { globals = JSON.parse(fs.readFileSync(exportedGlobalsPath).toString()); }\n            catch (e) { console.error(e); }\n\n            expect(code, 'should not have exit code of 0').not.to.equal(0);\n            expect(globals).to.be.ok;\n            expect(globals).to.have.property('_postman_exported_at');\n            expect(globals).to.have.property('values');\n            expect(globals.values).eql([\n                { key: 'var-1', value: 'value-1', type: 'any' },\n                { key: 'var-2', value: 'value-2', type: 'any' }\n            ]);\n            expect(globals).to.have.property('_postman_variable_scope', 'globals');\n            done();\n        });\n    });\n\n    it('should override exported globals with those provided via --global-var', function (done) {\n        // eslint-disable-next-line max-len\n        exec('node ./bin/newman.js run test/fixtures/run/single-request-failing.json -g test/fixtures/run/simple-variables.json --global-var foo=bar --export-globals out/test-globals.json', function (code) {\n            var globals;\n\n            try { globals = JSON.parse(fs.readFileSync(exportedGlobalsPath).toString()); }\n            catch (e) { console.error(e); }\n\n            expect(code, 'should not have exit code of 0').not.to.equal(0);\n            expect(globals).to.be.ok;\n            expect(globals).to.have.property('_postman_exported_at');\n            expect(globals).to.have.property('values');\n            expect(globals.values).eql([\n                { key: 'var-1', value: 'value-1', type: 'any' },\n                { key: 'var-2', value: 'value-2', type: 'any' },\n                { key: 'foo', value: 'bar', type: 'any' }\n            ]);\n            expect(globals).to.have.property('_postman_variable_scope', 'globals');\n            done();\n        });\n    });\n\n    it('`newman run` should export globals to a file in a pre-existing directory', function (done) {\n        // eslint-disable-next-line max-len\n        exec('node ./bin/newman.js run test/fixtures/run/single-get-request.json -g test/fixtures/run/simple-variables.json --export-globals out', function (code) {\n            var globals,\n                dir = fs.readdirSync(outDir),\n                file = dir[0];\n\n            expect(dir).to.have.length(1);\n\n            try { globals = JSON.parse(fs.readFileSync(outDir + '/' + file).toString()); }\n            catch (e) { console.error(e); }\n\n            expect(code).to.equal(0);\n            expect(globals).to.be.ok;\n            expect(globals).have.property('_postman_exported_at');\n            expect(globals).have.property('values');\n            expect(globals.values).eql([\n                { key: 'var-1', value: 'value-1', type: 'any' },\n                { key: 'var-2', value: 'value-2', type: 'any' }\n            ]);\n            expect(globals).have.property('_postman_variable_scope', 'globals');\n            done();\n        });\n    });\n\n    it('should export globals with a name when provided under --global-var', function (done) {\n        // eslint-disable-next-line max-len\n        exec('node ./bin/newman.js run test/fixtures/run/single-request-failing.json --global-var foo=bar --export-globals out/test-globals.json', function (code) {\n            var globals;\n\n            try { globals = JSON.parse(fs.readFileSync(exportedGlobalsPath).toString()); }\n            catch (e) { console.error(e); }\n\n            expect(code, 'should not have exit code of 0').not.to.equal(0);\n            expect(globals).to.be.ok;\n            expect(globals).to.have.property('_postman_exported_at');\n            expect(globals).to.have.property('values');\n            expect(globals).to.have.property('name', 'globals');\n            expect(globals.values).eql([\n                { key: 'foo', value: 'bar', type: 'any' }\n            ]);\n            expect(globals).to.have.property('_postman_variable_scope', 'globals');\n            done();\n        });\n    });\n});\n"
  },
  {
    "path": "test/cli/iteration-count.test.js",
    "content": "var fs = require('fs'),\n    path = require('path'),\n\n    _ = require('lodash'),\n    expect = require('chai').expect,\n\n\n    ITERATION_PROPERTY = 'run.stats.iterations.total',\n\n    collectionRunPath = path.join(__dirname, '..', '..', 'out', 'iteration-count-test.json');\n\ndescribe('iterationCount vs iterationData.length conflicts', function () {\n    afterEach(function () {\n        try { fs.unlinkSync(collectionRunPath); }\n        catch (e) { console.error(e); }\n    });\n\n    it('should iterate exactly once when no options are specified', function (done) {\n        // eslint-disable-next-line max-len\n        exec('node ./bin/newman.js run test/fixtures/run/single-get-request.json -r json --reporter-json-export out/iteration-count-test.json', function (code) {\n            var collectionRun;\n\n            try { collectionRun = JSON.parse(fs.readFileSync(collectionRunPath).toString()); }\n            catch (e) { console.error(e); }\n\n            expect(code, 'should have exit code of 0').to.equal(0);\n            expect(_.get(collectionRun, ITERATION_PROPERTY), 'should have 1 iteration').to.equal(1);\n            done();\n        });\n    });\n\n    it('should iterate according to iterationData.length when specified', function (done) {\n        // eslint-disable-next-line max-len\n        exec('node ./bin/newman.js run test/integration/steph/steph.postman_collection.json -d test/integration/steph/steph.postman_data.json -r json --reporter-json-export out/iteration-count-test.json', function (code) {\n            var collectionRun;\n\n            try { collectionRun = JSON.parse(fs.readFileSync(collectionRunPath).toString()); }\n            catch (e) { console.error(e); }\n\n            expect(code, 'should have exit code of 0').to.equal(0);\n            expect(_.get(collectionRun, ITERATION_PROPERTY), 'should have 2 iterations').to.equal(2);\n            done();\n        });\n    });\n\n    it('should iterate according to iterationCount when specified', function (done) {\n        // eslint-disable-next-line max-len\n        exec('node ./bin/newman.js run test/fixtures/run/single-get-request.json --iteration-count 3 -r json --reporter-json-export out/iteration-count-test.json', function (code) {\n            var collectionRun;\n\n            try { collectionRun = JSON.parse(fs.readFileSync(collectionRunPath).toString()); }\n            catch (e) { console.error(e); }\n\n            expect(code, 'should have exit code of 0').to.equal(0);\n            expect(_.get(collectionRun, ITERATION_PROPERTY), 'should have 3 iterations').to.equal(3);\n            done();\n        });\n    });\n\n    it('should iterate according to iterationCount when BOTH options are specified', function (done) {\n        // eslint-disable-next-line max-len\n        exec('node ./bin/newman.js run test/integration/steph/steph.postman_collection.json -d test/integration/steph/steph.postman_data.json --iteration-count 3 -r json --reporter-json-export out/iteration-count-test.json', function (code) {\n            var collectionRun;\n\n            try { collectionRun = JSON.parse(fs.readFileSync(collectionRunPath).toString()); }\n            catch (e) { console.error(e); }\n\n            expect(code, 'should have exit code of 0').to.equal(0);\n            expect(_.get(collectionRun, ITERATION_PROPERTY), 'should have 3 iterations').to.equal(3);\n            done();\n        });\n    });\n});\n"
  },
  {
    "path": "test/cli/run-options.test.js",
    "content": "const expect = require('chai').expect,\n\n    newmanVersion = require('../../package.json').version;\n\ndescribe('CLI run options', function () {\n    it('should work correctly without any extra options', function (done) {\n        exec('node ./bin/newman.js run test/fixtures/run/single-get-request.json', done);\n    });\n\n    it('should display the current Newman version with `--version`', function (done) {\n        exec('node ./bin/newman.js --version', function (code, stdout, stderr) {\n            expect(code, 'should have exit code of 0').to.equal(0);\n            expect(stdout).to.equal(`${newmanVersion}\\n`);\n            expect(stderr).to.equal('');\n            done();\n        });\n    });\n\n    it('should display the current Newman version with `-v`', function (done) {\n        exec('node ./bin/newman.js -v', function (code, stdout, stderr) {\n            expect(code, 'should have exit code of 0').to.equal(0);\n            expect(stdout).to.equal(`${newmanVersion}\\n`);\n            expect(stderr).to.equal('');\n            done();\n        });\n    });\n\n    it('should display help message if no arguments are provided', function (done) {\n        exec('node ./bin/newman.js', function (code, stdout, stderr) {\n            expect(code, 'should have exit code of 1').to.equal(1);\n            expect(stderr).to.match(/Usage: newman*/);\n            expect(stdout).to.equal('');\n            done();\n        });\n    });\n\n    it('should not work without a collection', function (done) {\n        exec('node ./bin/newman.js run -e test/fixtures/run/simple-variables.json',\n            function (code) {\n                expect(code, 'should have exit code of 1').to.equal(1);\n                done();\n            });\n    });\n\n    it('should not work without any options', function (done) {\n        exec('node ./bin/newman.js run', function (code) {\n            expect(code, 'should have exit code of 1').to.equal(1);\n            done();\n        });\n    });\n\n    it('should fail a collection run with undefined test cases', function (done) {\n        exec('node ./bin/newman.js run test/fixtures/run/undefined-test-checks.json', function (code) {\n            expect(code, 'should have exit code of 1').to.equal(1);\n            done();\n        });\n    });\n\n    it('should handle invalid collection URLs correctly', function (done) {\n        // eslint-disable-next-line max-len\n        exec('node ./bin/newman.js run https://api.getpostman.com/collections/my-collection-uuid?apikey=my-secret-api-key', function (code) {\n            expect(code, 'should have exit code of 1').to.equal(1);\n            done();\n        });\n    });\n\n    it('should correctly work with global variable overrides passed with --global-var', function (done) {\n        // eslint-disable-next-line max-len\n        exec('node ./bin/newman.js run test/integration/steph/steph.postman_collection.json --global-var first=James --global-var last=Bond', function (code) {\n            expect(code, 'should have exit code of 0').to.equal(0);\n            done();\n        });\n    });\n\n    it('should throw an error for missing --global-var values', function (done) {\n        // eslint-disable-next-line max-len\n        exec('node ./bin/newman.js run test/integration/steph/steph.postman_collection.json --global-var', function (code, stdout, stderr) {\n            expect(code, 'should have exit code of 1').to.equal(1);\n            expect(stderr).to.equal('error: option \\'--global-var <value>\\' argument missing\\n');\n            done();\n        });\n    });\n\n    it('should correctly work with environment variable overrides passed with --env-var', function (done) {\n        // eslint-disable-next-line max-len\n        exec('node ./bin/newman.js run test/fixtures/overrides/pmcollection.json --env-var dummyVar=bar2', function (code) {\n            expect(code, 'should have exit code of 0').to.equal(0);\n            done();\n        });\n    });\n\n    it('should throw an error for missing --env-var values', function (done) {\n        // eslint-disable-next-line max-len\n        exec('node ./bin/newman.js run test/fixtures/overrides/pmcollection.json --env-var', function (code, stdout, stderr) {\n            expect(code, 'should have exit code of 1').to.equal(1);\n            expect(stderr).to.equal('error: option \\'--env-var <value>\\' argument missing\\n');\n            done();\n        });\n    });\n\n    it('should log a warning if the v1 collection format is used', function (done) {\n        // eslint-disable-next-line max-len\n        exec('node ./bin/newman.js run test/integration/multi-level-folders-v1.postman_collection.json', function (code, stdout, stderr) {\n            expect(code, 'should have exit code of 0').to.equal(0);\n            expect(stderr).to.equal('newman: Newman v4 deprecates support for the v1 collection format\\n' +\n                '  Use the Postman Native app to export collections in the v2 format\\n\\n');\n\n            done();\n        });\n    });\n\n    describe('script timeouts', function () {\n        it('should be handled correctly when breached', function (done) {\n            // eslint-disable-next-line max-len\n            exec('node ./bin/newman.js run test/integration/timeout/timeout.postman_collection.json --timeout-script 5', function (code) {\n                // .to.be.(1) is not used as the windows exit code can be an arbitrary non-zero value\n                expect(code, 'should have non-zero exit code').to.be.above(0);\n                done();\n            });\n        });\n\n        it('should be handled correctly when not breached', function (done) {\n            // eslint-disable-next-line max-len\n            exec('node ./bin/newman.js run test/integration/timeout/timeout.postman_collection.json --timeout-script 500', function (code) {\n                expect(code, 'should have exit code of 0').to.equal(0);\n                done();\n            });\n        });\n    });\n});\n"
  },
  {
    "path": "test/cli/shallow-junit-reporter.test.js",
    "content": "const fs = require('fs'),\n\n    _ = require('lodash'),\n    sh = require('shelljs'),\n    expect = require('chai').expect,\n    parseXml = require('xml2js').parseString;\n\ndescribe('JUnit reporter', function () {\n    var outDir = 'out',\n        outFile = outDir + '/newman-report.xml';\n\n    beforeEach(function () {\n        sh.test('-d', outDir) && sh.rm('-rf', outDir);\n        sh.mkdir('-p', outDir);\n    });\n\n    afterEach(function () {\n        sh.rm('-rf', outDir);\n    });\n\n    it('should correctly generate the junit report for a successful run', function (done) {\n        // eslint-disable-next-line max-len\n        exec(`node ./bin/newman.js run test/fixtures/run/single-get-request.json -r junit --reporter-junit-export ${outFile}`,\n            function (code) {\n                expect(code, 'should have exit code of 0').to.equal(0);\n                fs.readFile(outFile, function (err, data) {\n                    expect(err).to.not.be.ok;\n\n                    parseXml(data, function (error, result) {\n                        expect(error).to.not.be.ok;\n\n                        var testcase,\n                            suite = _.get(result.testsuites, 'testsuite.0');\n\n                        expect(result.testsuites.$).to.not.be.empty;\n                        expect(result.testsuites.$.time).to.match(/^\\d+\\.\\d{3}$/);\n\n                        expect(suite).to.not.be.empty;\n                        expect(suite.$).to.not.be.empty;\n                        expect(suite.$.time).to.match(/^\\d+\\.\\d{3}$/);\n\n                        testcase = suite.testcase[0];\n                        expect(testcase).to.not.be.empty;\n\n                        expect(testcase.$).to.have.property('classname', 'ASimpleGetRequest');\n\n                        expect(suite.$).to.have.property('tests', '1');\n                        expect(suite.$).to.have.property('failures', '0');\n                        expect(suite.$).to.have.property('errors', '0');\n\n                        done();\n                    });\n                });\n            });\n    });\n\n    it('should correctly generate the junit report for a failed run', function (done) {\n        // eslint-disable-next-line max-len\n        exec(`node ./bin/newman.js run test/fixtures/run/single-request-failing.json -r junit --reporter-junit-export ${outFile}`,\n            function (code) {\n                expect(code, 'should have exit code of 1').to.equal(1);\n                fs.readFile(outFile, function (err, data) {\n                    expect(err).to.not.be.ok;\n\n                    parseXml(data, function (error, result) {\n                        expect(error).to.not.be.ok;\n\n                        var testcase,\n                            suite = _.get(result.testsuites, 'testsuite.0');\n\n                        expect(result.testsuites.$).to.not.be.empty;\n                        expect(result.testsuites.$.time).to.match(/^\\d+\\.\\d{3}$/);\n\n                        expect(suite).to.not.be.empty;\n                        expect(suite.$).to.not.be.empty;\n                        expect(suite.$.time).to.match(/^\\d+\\.\\d{3}$/);\n                        expect(suite.testcase).to.not.be.empty;\n\n                        expect(suite.$).to.have.property('tests', '1');\n                        expect(suite.$).to.have.property('failures', '1');\n                        expect(suite.$).to.have.property('errors', '0');\n\n                        testcase = suite.testcase[0];\n                        expect(testcase).to.not.be.empty;\n\n                        expect(testcase.$).to.have.property('classname', 'StatusCodeTest');\n                        expect(testcase.$.time).to.match(/^\\d+\\.\\d{3}$/);\n                        expect(testcase.failure).to.not.be.empty;\n                        expect(testcase.failure[0]._).to.not.be.empty;\n                        expect(testcase.failure[0].$).to.have.property('type', 'AssertionFailure');\n\n                        expect(testcase.failure).to.not.be.empty;\n\n                        done();\n                    });\n                });\n            });\n    });\n\n    it('should correctly produce the junit report for a run with TypeError', function (done) {\n        // eslint-disable-next-line max-len\n        exec(`node ./bin/newman.js run test/fixtures/run/newman-report-test.json -r junit --reporter-junit-export ${outFile}`,\n            function (code) {\n                expect(code, 'should have exit code of 1').to.equal(1);\n                fs.readFile(outFile, function (err, data) {\n                    expect(err).to.not.be.ok;\n\n                    parseXml(data, function (error, result) {\n                        expect(error).to.not.be.ok;\n\n                        var testcase,\n                            suite = _.get(result.testsuites, 'testsuite.0');\n\n                        expect(suite).to.not.be.empty;\n                        expect(suite.$).to.not.be.empty;\n                        expect(suite.$.time).to.match(/^\\d+\\.\\d{3}$/);\n                        expect(suite.testcase).to.not.be.empty;\n                        expect(suite['system-err']).to.not.be.empty;\n\n                        expect(suite.$).to.have.property('tests', '2');\n                        expect(suite.$).to.have.property('failures', '1');\n                        expect(suite.$).to.have.property('errors', '1');\n\n                        testcase = suite.testcase[0];\n                        expect(testcase).to.not.be.empty;\n\n                        expect(testcase.$).to.have.property('classname', 'FailedRequest');\n                        expect(testcase.$.time).to.match(/^\\d+\\.\\d{3}$/);\n                        expect(testcase.failure).to.not.be.empty;\n                        expect(testcase.failure[0]._).to.not.be.empty;\n                        expect(testcase.failure[0].$).to.have.property('type', 'AssertionFailure');\n\n                        done();\n                    });\n                });\n            });\n    });\n\n    it('should correctly produce the JUnit report in a pre-existing directory', function (done) {\n        // eslint-disable-next-line max-len\n        exec('node ./bin/newman.js run test/fixtures/run/single-get-request.json -r junit --reporter-junit-export out',\n            function (code) {\n                expect(code).to.equal(0);\n\n                var dir = fs.readdirSync(outDir),\n                    file = dir[0];\n\n                expect(dir).to.have.property('length', 1);\n                fs.stat(outDir + '/' + file, done);\n            });\n    });\n\n    it('should correctly handle the `--reporter-junit-export=` argument', function (done) {\n        // eslint-disable-next-line max-len\n        exec(`node ./bin/newman.js run test/fixtures/run/single-get-request.json -r junit --reporter-junit-export=${outFile}`,\n            function (code) {\n                expect(code, 'should have exit code of 0').to.equal(0);\n                fs.stat(outFile, done);\n            });\n    });\n\n    it('should correctly generate the junit report for a run with nested requests', function (done) {\n        // eslint-disable-next-line max-len\n        exec(`node ./bin/newman.js run test/fixtures/run/nested-requests-report-test.json -r junit --reporter-junit-export ${outFile}`,\n            function (code) {\n                expect(code, 'should have exit code of 0').to.equal(0);\n                fs.readFile(outFile, function (err, data) {\n                    expect(err).to.not.be.ok;\n\n                    parseXml(data, function (error, result) {\n                        expect(error).to.not.be.ok;\n\n                        var testcase,\n                            suite = _.get(result.testsuites, 'testsuite.0');\n\n                        expect(result.testsuites.$).to.not.be.empty;\n                        expect(result.testsuites.$.time).to.match(/^\\d+\\.\\d{3}$/);\n\n                        expect(suite).to.not.be.empty;\n                        expect(suite.$).to.not.be.empty;\n                        expect(suite.$.time).to.match(/^\\d+\\.\\d{3}$/);\n\n                        testcase = suite.testcase[0];\n                        expect(testcase).to.not.be.empty;\n\n                        expect(testcase.$).to.have.property('classname', 'NestedRequestTest');\n\n                        expect(suite.$).to.have.property('tests', '2');\n                        expect(suite.$).to.have.property('failures', '0');\n                        expect(suite.$).to.have.property('errors', '0');\n\n                        done();\n                    });\n                });\n            });\n    });\n\n    it('should correctly generate the junit report for a failed run with nested requests', function (done) {\n        // eslint-disable-next-line max-len\n        exec(`node ./bin/newman.js run test/fixtures/run/nested-requests-fail-report-test.json -r junit --reporter-junit-export ${outFile}`,\n            function (code) {\n                expect(code, 'should have exit code of 0').to.equal(1);\n                fs.readFile(outFile, function (err, data) {\n                    expect(err).to.not.be.ok;\n\n                    parseXml(data, function (error, result) {\n                        expect(error).to.not.be.ok;\n\n                        var testcase,\n                            suite = _.get(result.testsuites, 'testsuite.0');\n\n                        expect(result.testsuites.$).to.not.be.empty;\n                        expect(result.testsuites.$.time).to.match(/^\\d+\\.\\d{3}$/);\n\n                        expect(suite).to.not.be.empty;\n                        expect(suite.$).to.not.be.empty;\n                        expect(suite.$.time).to.match(/^\\d+\\.\\d{3}$/);\n                        expect(suite.testcase).to.not.be.empty;\n\n                        expect(suite.$).to.have.property('tests', '2');\n                        expect(suite.$).to.have.property('failures', '2');\n                        expect(suite.$).to.have.property('errors', '0');\n\n                        testcase = suite.testcase[0];\n                        expect(testcase).to.not.be.empty;\n\n                        expect(testcase.$).to.have.property('classname', 'NestedRequestTest');\n                        expect(testcase.$.time).to.match(/^\\d+\\.\\d{3}$/);\n                        expect(testcase.failure).to.not.be.empty;\n                        expect(testcase.failure[0]._).to.not.be.empty;\n                        expect(testcase.failure[0].$).to.have.property('type', 'AssertionFailure');\n\n                        expect(testcase.failure).to.not.be.empty;\n\n                        testcase = suite.testcase[1];\n                        expect(testcase).to.not.be.empty;\n\n                        expect(testcase.$).to.have.property('classname', 'NestedRequestTest');\n                        expect(testcase.$.time).to.match(/^\\d+\\.\\d{3}$/);\n                        expect(testcase.failure).to.not.be.empty;\n                        expect(testcase.failure[0]._).to.not.be.empty;\n                        expect(testcase.failure[0].$).to.have.property('type', 'AssertionFailure');\n\n                        expect(testcase.failure).to.not.be.empty;\n\n                        done();\n                    });\n                });\n            });\n    });\n});\n"
  },
  {
    "path": "test/cli/ssl-client-cert.test.js",
    "content": "const fs = require('fs'),\n    async = require('async'),\n    https = require('https'),\n    expect = require('chai').expect;\n\ndescribe('SSL Client certificates', function () {\n    var server1, server2, server3;\n\n    function createHttpsServerWithCerts (certs) {\n        return https.createServer({\n            key: fs.readFileSync(certs.key, 'utf8'),\n            cert: fs.readFileSync(certs.cert, 'utf8'),\n            ca: fs.readFileSync(certs.ca, 'utf8'),\n            passphrase: 'password',\n            requestCert: true,\n            rejectUnauthorized: false\n        }, function (req, res) {\n            if (req.client.authorized) {\n                res.writeHead(200, { 'Content-Type': 'text/plain' });\n                res.end('authorized\\n');\n            }\n            else {\n                res.writeHead(401, { 'Content-Type': 'text/plain' });\n                res.end('unauthorized\\n');\n            }\n        });\n    }\n\n    before(function (done) {\n        server1 = createHttpsServerWithCerts({\n            key: 'test/fixtures/ssl/server.key',\n            cert: 'test/fixtures/ssl/server.crt',\n            ca: 'test/fixtures/ssl/ca.crt'\n        });\n\n        server2 = createHttpsServerWithCerts({\n            key: 'test/fixtures/ssl/server2.key',\n            cert: 'test/fixtures/ssl/server2.crt',\n            ca: 'test/fixtures/ssl/ca2.crt'\n        });\n\n        server3 = createHttpsServerWithCerts({\n            key: 'test/fixtures/ssl/server3.key',\n            cert: 'test/fixtures/ssl/server3.crt',\n            ca: 'test/fixtures/ssl/ca3.crt'\n        });\n\n        async.parallel([\n            function (cb) {\n                server1.listen(3000, cb);\n            },\n            function (cb) {\n                server2.listen(3001, cb);\n            },\n            function (cb) {\n                server3.listen(3002, cb);\n            }\n        ], function (err) {\n            done(err);\n        });\n    });\n\n    after(function (done) {\n        async.parallel([\n            function (cb) {\n                server1.close(cb);\n            },\n            function (cb) {\n                server2.close(cb);\n            },\n            function (cb) {\n                server3.close(cb);\n            }\n        ], function (err) {\n            done(err);\n        });\n    });\n\n    // @todo: add .pfx, .pem tests as well\n    it('should work correctly with standalone client certificates', function (done) {\n        // eslint-disable-next-line max-len\n        exec('node ./bin/newman.js run test/fixtures/run/ssl-client-cert.json --ssl-client-cert test/fixtures/ssl/client.crt --ssl-client-key test/fixtures/ssl/client.key --ssl-client-passphrase password -k', function (code) {\n            expect(code, 'should have exit code of 0').to.equal(0);\n            done();\n        });\n    });\n\n    it('should work correctly with a trusted CA certificate provided', function (done) {\n        // eslint-disable-next-line max-len\n        exec('node ./bin/newman.js run test/fixtures/run/ssl-client-cert.json --ssl-client-cert test/fixtures/ssl/client.crt --ssl-client-key test/fixtures/ssl/client.key --ssl-client-passphrase password --ssl-extra-ca-certs test/fixtures/ssl/ca.crt', function (code) {\n            expect(code, 'should have exit code of 0').to.equal(0);\n            done();\n        });\n    });\n\n    it('should work correctly with multiple client certificates', function (done) {\n        // eslint-disable-next-line max-len\n        exec('node ./bin/newman.js run test/fixtures/run/ssl-client-cert-list.json --verbose --ssl-client-cert-list ./test/fixtures/files/ssl-client-cert-config.json -k', function (code) {\n            expect(code, 'should have exit code of 0').to.equal(0);\n            done();\n        });\n    });\n\n    it('should use certificate from list when both client certificates options are used', function (done) {\n        var cmd = 'node ./bin/newman.js run test/fixtures/run/ssl-client-cert-list.json' +\n            ' --ssl-client-cert-list test/fixtures/files/ssl-client-cert-config.json' +\n            ' --ssl-client-cert test/fixtures/ssl/client.crt' +\n            ' --ssl-client-key test/fixtures/ssl/client.key' +\n            ' --ssl-client-passphrase password -k';\n\n        exec(cmd, function (code) {\n            expect(code, 'should have exit code of 0').to.equal(0);\n            done();\n        });\n    });\n\n    it('should fallback to individual client cert when no cert from list match', function (done) {\n        var cmd = 'node ./bin/newman.js run test/fixtures/run/ssl-client-cert.json' +\n            ' --ssl-client-cert-list test/fixtures/files/ssl-client-cert-config.json' +\n            ' --ssl-client-cert test/fixtures/ssl/client.crt' +\n            ' --ssl-client-key test/fixtures/ssl/client.key' +\n            ' --ssl-client-passphrase password -k';\n\n        exec(cmd, function (code) {\n            expect(code, 'should have exit code of 0').to.equal(0);\n            done();\n        });\n    });\n\n    it('should bail out if client certificate list file does not exist', function (done) {\n        var cmd = 'node ./bin/newman.js run test/fixtures/run/ssl-client-cert-list.json' +\n            ' --ssl-client-cert-list invalid-cert-file.json' + // using an invalid cert list\n            ' --ssl-client-cert test/fixtures/ssl/client.crt' +\n            ' --ssl-client-key test/fixtures/ssl/client.key' +\n            ' --ssl-client-passphrase password -k';\n\n        exec(cmd, function (code) {\n            expect(code, 'should not have exit code 0').to.not.equal(0);\n            done();\n        });\n    });\n\n    it('should bail out if unable to parse client certificate list', function (done) {\n        var cmd = 'node ./bin/newman.js run test/fixtures/run/ssl-client-cert-list.json' +\n            ' --ssl-client-cert-list test/cli/ssl-client-cert-test.js' + // using an invalid cert list\n            ' --ssl-client-cert test/fixtures/ssl/client.crt' +\n            ' --ssl-client-key test/fixtures/ssl/client.key' +\n            ' --ssl-client-passphrase password -k';\n\n        exec(cmd, function (code) {\n            expect(code, 'should not have exit code 0').to.not.equal(0);\n            done();\n        });\n    });\n\n    it('should bail out if client certificate list is not an array', function (done) {\n        var cmd = 'node ./bin/newman.js run test/fixtures/run/ssl-client-cert-list.json' +\n            ' --ssl-client-cert-list test/fixtures/run/ssl-client-cert.json' + // using an invalid cert list\n            ' --ssl-client-cert test/fixtures/ssl/client.crt' +\n            ' --ssl-client-key test/fixtures/ssl/client.key' +\n            ' --ssl-client-passphrase password -k';\n\n        exec(cmd, function (code) {\n            expect(code, 'should not have exit code 0').to.not.equal(0);\n            done();\n        });\n    });\n});\n"
  },
  {
    "path": "test/cli/suppress-exit-code.test.js",
    "content": "const expect = require('chai').expect;\n\ndescribe('newman run --suppress-exit-code', function () {\n    it('should accept the --suppress-exit-code parameter', function (done) {\n        // eslint-disable-next-line max-len\n        exec('node ./bin/newman.js run test/fixtures/run/single-get-request.json --suppress-exit-code', function (code) {\n            expect(code, 'should have exit code of 0').to.equal(0);\n            done();\n        });\n    });\n\n    it('should accept the -x parameter', function (done) {\n        exec('node ./bin/newman.js run test/fixtures/run/single-get-request.json -x', function (code) {\n            expect(code, 'should have exit code of 0').to.equal(0);\n            done();\n        });\n    });\n\n    it('should exit non-zero if -x parameter is absent on a failing collection', function (done) {\n        exec('node ./bin/newman.js run test/fixtures/run/single-request-failing.json', function (code) {\n            expect(code, 'should have non-zero exit code').to.be.greaterThan(0);\n            done();\n        });\n    });\n\n    it('should exit with code zero if -x parameter is present on a failing collection', function (done) {\n        exec('node ./bin/newman.js run test/fixtures/run/single-request-failing.json -x', function (code) {\n            expect(code, 'should have exit code of 0').to.equal(0);\n            done();\n        });\n    });\n});\n"
  },
  {
    "path": "test/cli/verbose.test.js",
    "content": "const _ = require('lodash'),\n    expect = require('chai').expect;\n\ndescribe('newman run --verbose', function () {\n    const verboseStrings = [\n        'prepare',\n        'wait',\n        'dns-lookup',\n        'tcp-handshake',\n        'ssl-handshake',\n        'transfer-start',\n        'download',\n        'process',\n        'average DNS lookup time:',\n        'average first byte time:'\n    ];\n\n    it('should include verbose with --verbose option', function (done) {\n        exec('node ./bin/newman.js run test/fixtures/run/single-get-request.json --verbose', function (code, stdout) {\n            _.forEach(verboseStrings, function (str) {\n                expect(stdout).to.contain(str);\n            });\n\n            done();\n        });\n    });\n\n    it('should not include verbose without --verbose option', function (done) {\n        exec('node ./bin/newman.js run test/fixtures/run/single-get-request.json', function (code, stdout) {\n            _.forEach(verboseStrings, function (str) {\n                expect(stdout).to.not.contain(str);\n            });\n\n            done();\n        });\n    });\n});\n"
  },
  {
    "path": "test/cli/working-directory.test.js",
    "content": "const path = require('path'),\n    expect = require('chai').expect,\n\n    workingDir = path.resolve(__dirname, '../fixtures/files/work-dir');\n\ndescribe('newman run --working-dir --no-insecure-file-read', function () {\n    it('should resolve file present inside working directory', function (done) {\n        // eslint-disable-next-line max-len\n        exec(`node ./bin/newman.js run test/fixtures/run/single-file-inside.json --working-dir ${workingDir}`, function (code) {\n            expect(code, 'should have exit code of 0').to.equal(0);\n            done();\n        });\n    });\n\n    it('should not resolve file present outside working directory with --no-insecure-file-read', function (done) {\n        // eslint-disable-next-line max-len\n        exec(`node ./bin/newman.js run test/fixtures/run/single-file-outside.json --working-dir ${workingDir} --no-insecure-file-read`, function (code, stdout) {\n            expect(code, 'should have exit code of 1').to.equal(1);\n            expect(stdout).to.have.string('AssertionError');\n            done();\n        });\n    });\n\n    it('should resolve file present outside working directory by default', function (done) {\n        // eslint-disable-next-line max-len\n        exec(`node ./bin/newman.js run test/fixtures/run/single-file-outside.json --working-dir ${workingDir}`, function (code, stdout) {\n            expect(code, 'should have exit code of 0').to.equal(0);\n            expect(stdout).to.not.have.string('AssertionError');\n            done();\n        });\n    });\n});\n"
  },
  {
    "path": "test/fixtures/files/outside.json",
    "content": "{\"some\": \"json-string\"}\n"
  },
  {
    "path": "test/fixtures/files/ssl-client-cert-config.json",
    "content": "[\n    {\n        \"name\": \"client1\",\n        \"matches\": [\"https://localhost:3001\", \"https://localhost:3001/*\"],\n        \"key\": {\"src\": \"./test/fixtures/ssl/client2.key\"},\n        \"cert\": {\"src\": \"./test/fixtures/ssl/client2.crt\"},\n        \"passphrase\": \"password\"\n    },\n    {\n        \"name\": \"client2\",\n        \"matches\": [\"https://localhost:3002\", \"https://localhost:3002/*\"],\n        \"key\": {\"src\": \"./test/fixtures/ssl/client3.key\"},\n        \"cert\": {\"src\": \"./test/fixtures/ssl/client3.crt\"},\n        \"passphrase\": \"password\"\n    }\n]\n"
  },
  {
    "path": "test/fixtures/files/work-dir/test.json",
    "content": "{\"some\": \"json-string\"}\n"
  },
  {
    "path": "test/fixtures/overrides/env.json",
    "content": "{\n\t\"id\": \"f32a8f2f-bba8-4362-984b-a4c4857bb7a3\",\n\t\"name\": \"envTest\",\n\t\"values\": [\n\t\t{\n\t\t\t\"key\": \"dummyVar\",\n\t\t\t\"value\": \"bar\",\n\t\t\t\"description\": \"\",\n\t\t\t\"enabled\": false\n\t\t}\n\t],\n\t\"_postman_variable_scope\": \"environment\",\n\t\"_postman_exported_at\": \"2018-12-27T10:53:52.079Z\",\n\t\"_postman_exported_using\": \"Postman/6.6.1\"\n}"
  },
  {
    "path": "test/fixtures/overrides/failing-collection.json",
    "content": "{\n\t\"info\": {\n\t\t\"_postman_id\": \"64e7cd23-3037-42f5-b36e-51ea6fb5f973\",\n\t\t\"name\": \"env var test\",\n\t\t\"schema\": \"https://schema.getpostman.com/json/collection/v2.1.0/collection.json\"\n\t},\n\t\"item\": [\n\t\t{\n\t\t\t\"name\": \"--env-var test\",\n\t\t\t\"event\": [\n\t\t\t\t{\n\t\t\t\t\t\"listen\": \"test\",\n\t\t\t\t\t\"script\": {\n\t\t\t\t\t\t\"id\": \"ad0b9fd8-b9a7-44d6-a46b-8344aee76b98\",\n\t\t\t\t\t\t\"exec\": [\n\t\t\t\t\t\t\t\"pm.test(\\\"Body matches string\\\", function () {\",\n\t\t\t\t\t\t\t\"    pm.expect(pm.response.text()).to.include(\\\"bar2\\\");\",\n\t\t\t\t\t\t\t\"});\",\n\t\t\t\t\t\t\t\"\",\n\t\t\t\t\t\t\t\"\"\n\t\t\t\t\t\t],\n\t\t\t\t\t\t\"type\": \"text/javascript\"\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t],\n\t\t\t\"request\": {\n\t\t\t\t\"method\": \"GET\",\n\t\t\t\t\"header\": [],\n\t\t\t\t\"body\": {\n\t\t\t\t\t\"mode\": \"raw\",\n\t\t\t\t\t\"raw\": \"\"\n\t\t\t\t},\n\t\t\t\t\"url\": {\n\t\t\t\t\t\"raw\": \"ostman-echo.com/get?key={{dummyVar}}\",\n\t\t\t\t\t\"protocol\": \"https\",\n\t\t\t\t\t\"host\": [\n\t\t\t\t\t\t\"postman-echo\",\n\t\t\t\t\t\t\"com\"\n\t\t\t\t\t],\n\t\t\t\t\t\"path\": [\n\t\t\t\t\t\t\"get\"\n\t\t\t\t\t],\n\t\t\t\t\t\"query\": [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"key\": \"key\",\n\t\t\t\t\t\t\t\"value\": \"{{dummyVar}}\"\n\t\t\t\t\t\t}\n\t\t\t\t\t]\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"response\": []\n\t\t}\n\t]\n}"
  },
  {
    "path": "test/fixtures/overrides/pmcollection.json",
    "content": "{\n\t\"info\": {\n\t\t\"_postman_id\": \"64e7cd23-3037-42f5-b36e-51ea6fb5f973\",\n\t\t\"name\": \"env var test\",\n\t\t\"schema\": \"https://schema.getpostman.com/json/collection/v2.1.0/collection.json\"\n\t},\n\t\"item\": [\n\t\t{\n\t\t\t\"name\": \"--env-var test\",\n\t\t\t\"event\": [\n\t\t\t\t{\n\t\t\t\t\t\"listen\": \"test\",\n\t\t\t\t\t\"script\": {\n\t\t\t\t\t\t\"id\": \"ad0b9fd8-b9a7-44d6-a46b-8344aee76b98\",\n\t\t\t\t\t\t\"exec\": [\n\t\t\t\t\t\t\t\"pm.test(\\\"Body matches string\\\", function () {\",\n\t\t\t\t\t\t\t\"    pm.expect(pm.response.text()).to.include(\\\"bar2\\\");\",\n\t\t\t\t\t\t\t\"});\",\n\t\t\t\t\t\t\t\"\",\n\t\t\t\t\t\t\t\"\"\n\t\t\t\t\t\t],\n\t\t\t\t\t\t\"type\": \"text/javascript\"\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t],\n\t\t\t\"request\": {\n\t\t\t\t\"method\": \"GET\",\n\t\t\t\t\"header\": [],\n\t\t\t\t\"body\": {\n\t\t\t\t\t\"mode\": \"raw\",\n\t\t\t\t\t\"raw\": \"\"\n\t\t\t\t},\n\t\t\t\t\"url\": {\n\t\t\t\t\t\"raw\": \"https://postman-echo.com/get?key={{dummyVar}}\",\n\t\t\t\t\t\"protocol\": \"https\",\n\t\t\t\t\t\"host\": [\n\t\t\t\t\t\t\"postman-echo\",\n\t\t\t\t\t\t\"com\"\n\t\t\t\t\t],\n\t\t\t\t\t\"path\": [\n\t\t\t\t\t\t\"get\"\n\t\t\t\t\t],\n\t\t\t\t\t\"query\": [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"key\": \"key\",\n\t\t\t\t\t\t\t\"value\": \"{{dummyVar}}\"\n\t\t\t\t\t\t}\n\t\t\t\t\t]\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"response\": []\n\t\t}\n\t]\n}"
  },
  {
    "path": "test/fixtures/run/failed-request.json",
    "content": "{\n\t\"variables\": [],\n\t\"info\": {\n\t\t\"name\": \"failed-request\",\n\t\t\"_postman_id\": \"2ed7ced1-d834-f473-7d28-aa3a1a7d825f\",\n\t\t\"description\": \"A minimalistic collection with a failing request\",\n\t\t\"schema\": \"https://schema.getpostman.com/json/collection/v2.0.0/collection.json\"\n\t},\n\t\"item\": [\n\t\t{\n\t\t\t\"name\": \"Failed request\",\n\t\t\t\"request\": {\n\t\t\t\t\"url\": \"https://123.random.z/get\",\n\t\t\t\t\"method\": \"GET\"\n\t\t\t}\n    }\n\t]\n}\n"
  },
  {
    "path": "test/fixtures/run/nested-requests-fail-report-test.json",
    "content": "{\n\t\"info\": {\n\t\t\"_postman_id\": \"eb3db066-938a-4fe9-8d6d-d1d288b1c25c\",\n\t\t\"name\": \"Nested request in test with failing test\",\n\t\t\"schema\": \"https://schema.getpostman.com/json/collection/v2.1.0/collection.json\"\n\t},\n\t\"item\": [\n\t\t{\n\t\t\t\"name\": \"Nested request test\",\n\t\t\t\"event\": [\n\t\t\t\t{\n\t\t\t\t\t\"listen\": \"test\",\n\t\t\t\t\t\"script\": {\n\t\t\t\t\t\t\"id\": \"63864333-932a-49b1-8daf-2bfb98650ae6\",\n\t\t\t\t\t\t\"exec\": [\n\t\t\t\t\t\t\t\"pm.test(\\\"Status code is 200\\\", function () {\",\n\t\t\t\t\t\t\t\"    pm.response.to.have.status(400);\",\n\t\t\t\t\t\t\t\"});\",\n\t\t\t\t\t\t\t\"pm.sendRequest({\",\n\t\t\t\t\t\t\t\"    url: 'https://postman-echo.com/get?key2=val2',\",\n\t\t\t\t\t\t\t\"    method: 'GET'\",\n\t\t\t\t\t\t\t\"}, (err, res) => {\",\n\t\t\t\t\t\t\t\"    if (err) {\",\n\t\t\t\t\t\t\t\"        console.log(err);\",\n\t\t\t\t\t\t\t\"    } else {\",\n\t\t\t\t\t\t\t\"        var resData = JSON.parse(res.stream.toString()).args;\",\n\t\t\t\t\t\t\t\"\",\n\t\t\t\t\t\t\t\"        pm.test('Nested request JSON response: \\\"key2\\\": \\\"val2\\\"', () => {\",\n\t\t\t\t\t\t\t\"            pm.expect('val2').to.equal('wrongValue');\",\n\t\t\t\t\t\t\t\"        });\",\n\t\t\t\t\t\t\t\"    }\",\n\t\t\t\t\t\t\t\"});\"\n\t\t\t\t\t\t],\n\t\t\t\t\t\t\"type\": \"text/javascript\"\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t],\n\t\t\t\"request\": {\n\t\t\t\t\"method\": \"GET\",\n\t\t\t\t\"header\": [],\n\t\t\t\t\"body\": {\n\t\t\t\t\t\"mode\": \"raw\",\n\t\t\t\t\t\"raw\": \"\"\n\t\t\t\t},\n\t\t\t\t\"url\": {\n\t\t\t\t\t\"raw\": \"https://postman-echo.com/get?foo1=bar1\",\n\t\t\t\t\t\"protocol\": \"https\",\n\t\t\t\t\t\"host\": [\n\t\t\t\t\t\t\"postman-echo\",\n\t\t\t\t\t\t\"com\"\n\t\t\t\t\t],\n\t\t\t\t\t\"path\": [\n\t\t\t\t\t\t\"get\"\n\t\t\t\t\t],\n\t\t\t\t\t\"query\": [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"key\": \"foo1\",\n\t\t\t\t\t\t\t\"value\": \"bar1\"\n\t\t\t\t\t\t}\n\t\t\t\t\t]\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"response\": []\n\t\t}\n\t]\n}"
  },
  {
    "path": "test/fixtures/run/nested-requests-report-test.json",
    "content": "{\n\t\"info\": {\n\t\t\"_postman_id\": \"eb3db066-938a-4fe9-8d6d-d1d288b1c25c\",\n\t\t\"name\": \"Nested request in test\",\n\t\t\"schema\": \"https://schema.getpostman.com/json/collection/v2.1.0/collection.json\"\n\t},\n\t\"item\": [\n\t\t{\n\t\t\t\"name\": \"Nested request test\",\n\t\t\t\"event\": [\n\t\t\t\t{\n\t\t\t\t\t\"listen\": \"test\",\n\t\t\t\t\t\"script\": {\n\t\t\t\t\t\t\"id\": \"63864333-932a-49b1-8daf-2bfb98650ae6\",\n\t\t\t\t\t\t\"exec\": [\n\t\t\t\t\t\t\t\"pm.test(\\\"Status code is 200\\\", function () {\",\n\t\t\t\t\t\t\t\"    pm.response.to.have.status(200);\",\n\t\t\t\t\t\t\t\"});\",\n\t\t\t\t\t\t\t\"pm.sendRequest({\",\n\t\t\t\t\t\t\t\"    url: 'https://postman-echo.com/get?key2=val2',\",\n\t\t\t\t\t\t\t\"    method: 'GET'\",\n\t\t\t\t\t\t\t\"}, (err, res) => {\",\n\t\t\t\t\t\t\t\"    if (err) {\",\n\t\t\t\t\t\t\t\"        console.log(err);\",\n\t\t\t\t\t\t\t\"    } else {\",\n\t\t\t\t\t\t\t\"        var resData = JSON.parse(res.stream.toString()).args;\",\n\t\t\t\t\t\t\t\"\",\n\t\t\t\t\t\t\t\"        pm.test('Nested request JSON response: \\\"key2\\\": \\\"val2\\\"', () => {\",\n\t\t\t\t\t\t\t\"            pm.expect('val2').to.equal(resData.key2);\",\n\t\t\t\t\t\t\t\"        });\",\n\t\t\t\t\t\t\t\"    }\",\n\t\t\t\t\t\t\t\"});\"\n\t\t\t\t\t\t],\n\t\t\t\t\t\t\"type\": \"text/javascript\"\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t],\n\t\t\t\"request\": {\n\t\t\t\t\"method\": \"GET\",\n\t\t\t\t\"header\": [],\n\t\t\t\t\"body\": {\n\t\t\t\t\t\"mode\": \"raw\",\n\t\t\t\t\t\"raw\": \"\"\n\t\t\t\t},\n\t\t\t\t\"url\": {\n\t\t\t\t\t\"raw\": \"https://postman-echo.com/get?foo1=bar1\",\n\t\t\t\t\t\"protocol\": \"https\",\n\t\t\t\t\t\"host\": [\n\t\t\t\t\t\t\"postman-echo\",\n\t\t\t\t\t\t\"com\"\n\t\t\t\t\t],\n\t\t\t\t\t\"path\": [\n\t\t\t\t\t\t\"get\"\n\t\t\t\t\t],\n\t\t\t\t\t\"query\": [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"key\": \"foo1\",\n\t\t\t\t\t\t\t\"value\": \"bar1\"\n\t\t\t\t\t\t}\n\t\t\t\t\t]\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"response\": []\n\t\t}\n\t]\n}"
  },
  {
    "path": "test/fixtures/run/newman-report-test.json",
    "content": "{\n\t\"variables\": [],\n\t\"info\": {\n\t\t\"name\": \"assertion-error-test\",\n\t\t\"_postman_id\": \"bd90e43e-8e25-d630-9098-420853777b21\",\n\t\t\"description\": \"A sanity check for report generation, including a check for failed requests.\",\n\t\t\"schema\": \"https://schema.getpostman.com/json/collection/v2.0.0/collection.json\"\n\t},\n\t\"item\": [\n\t\t{\n\t\t\t\"name\": \"Failed request\",\n\t\t\t\"event\": [\n\t\t\t\t{\n\t\t\t\t\t\"listen\": \"test\",\n\t\t\t\t\t\"script\": {\n\t\t\t\t\t\t\"type\": \"text/javascript\",\n\t\t\t\t\t\t\"exec\": [\n              \"tests[\\\"Status code is 200\\\"] = responseCode.code === 200;\",\n              \"\",\n              \"// deliberate AssertionError to test proper report generation\",\n              \"pm.test(\\\"Status code is 400\\\", function () {\",\n              \"    pm.response.to.have.status(400);\",\n              \"});\",\n\t\t\t\t\t\t\t\"// deliberate TypeError to test proper report generation\",\n\t\t\t\t\t\t\t\"tests[\\\"Body contains status\\\"] = undefined.alpha;\",\n\t\t\t\t\t\t\t\"\"\n\t\t\t\t\t\t]\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t],\n\t\t\t\"request\": {\n\t\t\t\t\"url\": \"https://postman-echo.com/status/200\",\n\t\t\t\t\"method\": \"GET\",\n\t\t\t\t\"header\": [],\n\t\t\t\t\"body\": {},\n\t\t\t\t\"description\": \"A request with a `TypeError` in it's test script\"\n\t\t\t},\n\t\t\t\"response\": []\n\t\t}\n\t]\n}\n"
  },
  {
    "path": "test/fixtures/run/response-bodies.json",
    "content": "{\n  \"info\": {\n    \"name\": \"A collection with \",\n    \"schema\": \"https://schema.getpostman.com/json/collection/v2.0.0/collection.json\"\n  },\n  \"item\": [{\n    \"name\": \"A simple GET request\",\n    \"event\": [{\n      \"listen\": \"test\",\n      \"script\": {\n        \"type\": \"text/javascript\",\n        \"exec\": [\n          \"pm.test('response code is 200', function () {\",\n          \"  pm.response.to.be.ok;\",\n          \"  pm.response.to.have.header('Content-Type', 'application/json; charset=utf-8');\",\n          \"});\"\n        ]\n      }\n    }],\n    \"request\": {\n      \"url\": \"https://postman-echo.com/get?source=newman-sample-github-collection\",\n      \"method\": \"GET\"\n    }\n  }, {\n    \"name\": \"A simple GET request\",\n    \"event\": [{\n      \"listen\": \"test\",\n      \"script\": {\n        \"type\": \"text/javascript\",\n        \"exec\": [\n          \"pm.test('response code is 200', function () {\",\n          \"  pm.response.to.be.ok;\",\n          \"  pm.response.to.have.header('Content-Type', 'application/html; charset=utf-8');\",\n          \"});\"\n        ]\n      }\n    }],\n    \"request\": {\n      \"url\": \"https://postman-echo.com/type/html?source=newman-sample-github-collection\",\n      \"method\": \"GET\"\n    }\n  }, {\n    \"name\": \"A simple GET request\",\n    \"event\": [{\n      \"listen\": \"test\",\n      \"script\": {\n        \"type\": \"text/javascript\",\n        \"exec\": [\n          \"pm.test('response code is 200', function () {\",\n          \"  pm.response.to.be.ok;\",\n          \"  pm.response.to.have.header('Content-Type', 'application/xml; charset=utf-8');\",\n          \"});\"\n        ]\n      }\n    }],\n    \"request\": {\n      \"url\": \"https://postman-echo.com/type/xml?source=newman-sample-github-collection\",\n      \"method\": \"GET\"\n    }\n  }]\n}\n"
  },
  {
    "path": "test/fixtures/run/simple-variables.json",
    "content": "{\n  \"name\": \"globals\",\n  \"values\": [{\n    \"key\": \"var-1\",\n    \"value\": \"value-1\"\n  }, {\n    \"key\": \"var-2\",\n    \"value\": \"value-2\"\n  }]\n}\n"
  },
  {
    "path": "test/fixtures/run/single-file-inside.json",
    "content": "{\n  \"info\": {\n    \"name\": \"Example Collection with a single GET request\",\n    \"schema\": \"https://schema.getpostman.com/json/collection/v2.0.0/collection.json\"\n  },\n\n  \"item\": [{\n    \"name\": \"A Form-data request\",\n    \"event\": [{\n      \"listen\": \"test\",\n      \"script\": {\n        \"type\": \"text/javascript\",\n        \"exec\": [\n          \"pm.test(\\\"file uploaded\\\", function () {\",\n          \"   var jsonData = pm.response.json();\",\n          \"   pm.expect(jsonData.files).to.eql({ \",\n          \"     \\\"test.json\\\": \\\"data:application/octet-stream;base64,eyJzb21lIjogImpzb24tc3RyaW5nIn0K\\\"\",\n          \"});});\"\n          ]\n      }\n    }],\n    \"request\": {\n      \"url\": \"https://postman-echo.com/post\",\n      \"method\": \"POST\",\n      \"body\": {\n        \"mode\": \"formdata\",\n        \"formdata\": [\n          {\n            \"type\": \"file\",\n            \"key\": \"somefile\",\n            \"src\": \"test.json\"\n          }\n        ]\n      }\n    }\n  },\n  {\n    \"name\": \"A Binary body request\",\n    \"event\": [{\n      \"listen\": \"test\",\n      \"script\": {\n        \"type\": \"text/javascript\",\n        \"exec\": [\n          \"pm.test(\\\"file uploaded\\\", function () {\",\n          \"   var jsonData = pm.response.json();\",\n          \"    pm.expect(jsonData.data).to.eql({ some: 'json-string' });\",\n          \"});\"\n          ]\n      }\n    }],\n    \"request\": {\n      \"url\": \"https://postman-echo.com/post\",\n      \"method\": \"POST\",\n      \"body\": {\n        \"mode\": \"file\",\n        \"file\": {\n            \"src\": \"test.json\"\n        }\n      }\n    }\n  }]\n}\n"
  },
  {
    "path": "test/fixtures/run/single-file-outside.json",
    "content": "{\n  \"info\": {\n    \"name\": \"Example Collection with a single GET request\",\n    \"schema\": \"https://schema.getpostman.com/json/collection/v2.0.0/collection.json\"\n  },\n\n  \"item\": [{\n    \"name\": \"A Form-data request\",\n    \"event\": [{\n      \"listen\": \"test\",\n      \"script\": {\n        \"type\": \"text/javascript\",\n        \"exec\": [\n          \"pm.test(\\\"file uploaded\\\", function () {\",\n          \"   var jsonData = pm.response.json();\",\n          \"   pm.expect(jsonData.files).to.eql({ \",\n          \"     \\\"outside.json\\\": \\\"data:application/octet-stream;base64,eyJzb21lIjogImpzb24tc3RyaW5nIn0K\\\"\",\n          \"});});\"\n          ]\n      }\n    }],\n    \"request\": {\n      \"url\": \"https://postman-echo.com/post\",\n      \"method\": \"POST\",\n      \"body\": {\n        \"mode\": \"formdata\",\n        \"formdata\": [\n          {\n            \"type\": \"file\",\n            \"key\": \"somefile\",\n            \"src\": \"../outside.json\"\n          }\n        ]\n      }\n    }\n  },\n  {\n    \"name\": \"A Binary body request\",\n    \"event\": [{\n      \"listen\": \"test\",\n      \"script\": {\n        \"type\": \"text/javascript\",\n        \"exec\": [\n          \"pm.test(\\\"file uploaded\\\", function () {\",\n          \"   var jsonData = pm.response.json();\",\n          \"    pm.expect(jsonData.data).to.eql({ some: 'json-string' });\",\n          \"});\"\n          ]\n      }\n    }],\n    \"request\": {\n      \"url\": \"https://postman-echo.com/post\",\n      \"method\": \"POST\",\n      \"body\": {\n        \"mode\": \"file\",\n        \"file\": {\n            \"src\": \"../outside.json\"\n        }\n      }\n    }\n  }]\n}\n"
  },
  {
    "path": "test/fixtures/run/single-get-request.json",
    "content": "{\n  \"info\": {\n    \"name\": \"Example Collection with a single GET request\",\n    \"schema\": \"https://schema.getpostman.com/json/collection/v2.0.0/collection.json\"\n  },\n\n  \"item\": [{\n    \"name\": \"A simple GET request\",\n    \"event\": [{\n      \"listen\": \"test\",\n      \"script\": {\n        \"type\": \"text/javascript\",\n        \"exec\": [\"tests['response code is 200'] = (responseCode.code === 200);\"]\n      }\n    }],\n    \"request\": {\n      \"url\": \"https://postman-echo.com/get?source=newman-sample-github-collection\",\n      \"method\": \"GET\"\n    }\n  }]\n}\n"
  },
  {
    "path": "test/fixtures/run/single-request-failing.json",
    "content": "{\n  \"info\": {\n    \"name\": \"Example Collection with Failing Tests\",\n    \"description\": \"This collection is to illustrate how a typical collection having failing tests run on Newman\",\n    \"schema\": \"https://schema.getpostman.com/json/collection/v2.0.0/collection.json\"\n  },\n\n  \"item\": [{\n    \"name\": \"Status Code Test\",\n    \"description\": \"Request that returns 404, but test expects 200 status code\",\n    \"event\": [{\n      \"listen\": \"test\",\n      \"script\": {\n        \"type\": \"text/javascript\",\n        \"exec\": [\"tests['response code is 200'] = (responseCode.code === 200);\"]\n      }\n    }],\n    \"request\": {\n      \"url\": \"https://postman-echo.com/status/404\",\n      \"method\": \"GET\"\n    }\n  }]\n}\n"
  },
  {
    "path": "test/fixtures/run/spaces/data.json",
    "content": " [{\"key\":\"value\"}, {\"key\": \"value2\"}]\n"
  },
  {
    "path": "test/fixtures/run/spaces/simple-cookie-jar.json",
    "content": "{\n  \"version\": \"tough-cookie@4.1.3-postman.1\",\n  \"storeType\": \"MemoryCookieStore\",\n  \"allowSpecialUseDomain\": true,\n  \"rejectPublicSuffixes\": true,\n  \"enableLooseMode\": false,\n  \"prefixSecurity\": \"silent\",\n  \"cookies\": [\n    {\n      \"key\": \"foo2\",\n      \"value\": \"baz\",\n      \"domain\": \"postman-echo.com\",\n      \"path\": \"/\",\n      \"hostOnly\": true,\n      \"creation\": \"2020-06-09T16:57:46.999Z\",\n      \"lastAccessed\": \"2020-06-09T16:57:48.385Z\"\n    }\n  ]\n}\n"
  },
  {
    "path": "test/fixtures/run/spaces/simple-variables.json",
    "content": " {\n  \"name\": \"globals\",\n  \"values\": [{\n    \"key\": \"var-1\",\n    \"type\": \"any\",\n    \"value\": \"value-1\"\n  }, {\n    \"key\": \"var-2\",\n    \"type\": \"any\",\n    \"value\": \"value-2\"\n  }]\n}\n"
  },
  {
    "path": "test/fixtures/run/spaces/single-get-request.json",
    "content": " {\n   \"info\": {\n     \"name\": \"Example Collection with a single GET request\",\n     \"schema\": \"https://schema.getpostman.com/json/collection/v2.1.0/collection.json\"\n   },\n\n   \"item\": [{\n     \"name\": \"A simple GET request\",\n     \"event\": [{\n       \"listen\": \"test\",\n       \"script\": {\n         \"type\": \"text/javascript\",\n         \"exec\": [\"tests['response code is 200'] = (responseCode.code === 200);\"]\n       }\n     }],\n     \"request\": {\n       \"url\": {\n         \"host\": [\n           \"postman-echo\",\n           \"com\"\n         ],\n         \"path\": [\"get\"],\n         \"protocol\": \"https\",\n         \"query\": [{\n           \"key\": \"source\",\n           \"value\": \"newman-sample-github-collection\"\n         }],\n         \"variable\": []\n       },\n       \"method\": \"GET\"\n     }\n   }]\n }\n"
  },
  {
    "path": "test/fixtures/run/ssl-client-cert-list.json",
    "content": "{\n  \"info\": {\n    \"_postman_id\": \"1f9d323c-5bb0-4885-87d0-ac5522f85d7d\",\n    \"name\": \"Client cert example\",\n    \"description\": \"A sample collection to demonstrate client SSL certificate handling\",\n    \"schema\": \"https://schema.getpostman.com/json/collection/v2.1.0/collection.json\"\n  },\n  \"item\": [\n    {\n      \"name\": \"A simple GET request using client certificate 1 on server\",\n      \"event\": [\n        {\n          \"listen\": \"test\",\n          \"script\": {\n            \"id\": \"f169c71e-6a6c-40d6-92bf-0e99e36d30dd\",\n            \"exec\": [\n              \"pm.test(\\\"Status code is 200\\\", function () {\",\n              \"    pm.response.to.have.status(200);\",\n              \"});\"\n            ],\n            \"type\": \"text/javascript\"\n          }\n        }\n      ],\n      \"request\": {\n        \"method\": \"GET\",\n        \"header\": [],\n        \"url\": {\n          \"raw\": \"https://localhost:3001\",\n          \"protocol\": \"https\",\n          \"host\": [\n            \"localhost\"\n          ],\n          \"port\": \"3001\"\n        }\n      }\n    },\n    {\n      \"name\": \"A simple GET request using client certificate 2 on server 2\",\n      \"event\": [\n        {\n          \"listen\": \"test\",\n          \"script\": {\n            \"id\": \"c7e8c76f-c590-4fec-94b9-6049e5eb5e59\",\n            \"exec\": [\n              \"pm.test(\\\"Status code is 200\\\", function () {\",\n              \"    pm.response.to.have.status(200);\",\n              \"});\"\n            ],\n            \"type\": \"text/javascript\"\n          }\n        }\n      ],\n      \"request\": {\n        \"method\": \"GET\",\n        \"header\": [],\n        \"url\": {\n          \"raw\": \"https://localhost:3002\",\n          \"protocol\": \"https\",\n          \"host\": [\n            \"localhost\"\n          ],\n          \"port\": \"3002\"\n        }\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": "test/fixtures/run/ssl-client-cert.json",
    "content": "{\n  \"info\": {\n    \"_postman_id\": \"1aef0597-d937-47e1-a989-2733f6d9eecf\",\n    \"name\": \"Client cert example\",\n    \"description\": \"A sample collection to demonstrate client SSL certificate handling\",\n    \"schema\": \"https://schema.getpostman.com/json/collection/v2.1.0/collection.json\"\n  },\n  \"item\": [\n    {\n      \"name\": \"A simple GET request\",\n      \"event\": [\n        {\n          \"listen\": \"test\",\n          \"script\": {\n            \"id\": \"b4f95cb4-9219-4e2a-b62c-9055a3958a37\",\n            \"exec\": [\n              \"pm.test(\\\"Status code is 200\\\", function () {\",\n              \"    pm.response.to.have.status(200);\",\n              \"});\"\n            ],\n            \"type\": \"text/javascript\"\n          }\n        }\n      ],\n      \"request\": {\n        \"method\": \"GET\",\n        \"header\": [],\n        \"url\": {\n          \"raw\": \"https://localhost:3000\",\n          \"protocol\": \"https\",\n          \"host\": [\n            \"localhost\"\n          ],\n          \"port\": \"3000\"\n        }\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": "test/fixtures/run/test-data.postman_data.json",
    "content": "[{\"key\":\"value\"}, {\"key\": \"value2\"}]\n"
  },
  {
    "path": "test/fixtures/run/undefined-test-checks.json",
    "content": "{\n\t\"variables\": [],\n\t\"info\": {\n\t\t\"name\": \"undefined-test-checks\",\n\t\t\"_postman_id\": \"2ed7ced1-d834-f473-7d28-aa3a1a7d825f\",\n\t\t\"description\": \"A minimalistic collection to ensure that test cases with undefined values do not get ignored.\",\n\t\t\"schema\": \"https://schema.getpostman.com/json/collection/v2.0.0/collection.json\"\n\t},\n\t\"item\": [\n\t\t{\n\t\t\t\"name\": \"Simple Echo/get request\",\n\t\t\t\"event\": [\n\t\t\t\t{\n\t\t\t\t\t\"listen\": \"test\",\n\t\t\t\t\t\"script\": {\n\t\t\t\t\t\t\"type\": \"text/javascript\",\n\t\t\t\t\t\t\"exec\": [\n\t\t\t\t\t\t\t\"var body = JSON.parse(responseBody);\",\n\t\t\t\t\t\t\t\"\",\n\t\t\t\t\t\t\t\"tests[\\\"Status code is 200\\\"] = responseCode.code === 200;\",\n\t\t\t\t\t\t\t\"tests[\\\"This test should pass\\\"] = body.url;\",\n\t\t\t\t\t\t\t\"tests[\\\"This test should fail\\\"] = body.random_unknown_property;\"\n\t\t\t\t\t\t]\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t],\n\t\t\t\"request\": {\n\t\t\t\t\"url\": \"https://postman-echo.com/get\",\n\t\t\t\t\"method\": \"GET\",\n\t\t\t\t\"header\": [],\n\t\t\t\t\"body\": {},\n\t\t\t\t\"description\": \"\"\n\t\t\t},\n\t\t\t\"response\": []\n\t\t}\n\t]\n}"
  },
  {
    "path": "test/fixtures/ssl/SSL.md",
    "content": "# About these certificates/keys\n\nThese certs are merely used in unit tests. In case that a cert ever has to be regenerated, it can be achieved like this.\nAll Keys have the passphrase 'password'.\n\n## Generate a CSR from a private key\n\n`openssl req -new -key server.key -out server.csr`\n\n## Sign the CSR with the CA\n\n`openssl x509 -req -days 10000 -in server.csr -CA ca.crt -CAkey ca.key -out server.crt -set_serial 1 -outform pem -extfile v3.ext -sha256`\n"
  },
  {
    "path": "test/fixtures/ssl/ca.crt",
    "content": "-----BEGIN CERTIFICATE-----\nMIIGJTCCBA2gAwIBAgIJANskintnrPWaMA0GCSqGSIb3DQEBCwUAMIGnMQswCQYD\nVQQGEwJJTjESMBAGA1UECAwJS2FybmF0YWthMRIwEAYDVQQHDAlCZW5nYWx1cnUx\nJTAjBgNVBAoMHFBvc3Rkb3QgVGVjaG5vbG9naWVzIFB2dCBMdGQxFDASBgNVBAsM\nC1Bvc3RtYW5sYWJzMQ8wDQYDVQQDDAZOZXdtYW4xIjAgBgkqhkiG9w0BCQEWE2hl\nbHBAZ2V0cG9zdG1hbi5jb20wIBcNMTYxMjE1MTQ1NzA4WhgPMjA4NTAxMDIxNDU3\nMDhaMIGnMQswCQYDVQQGEwJJTjESMBAGA1UECAwJS2FybmF0YWthMRIwEAYDVQQH\nDAlCZW5nYWx1cnUxJTAjBgNVBAoMHFBvc3Rkb3QgVGVjaG5vbG9naWVzIFB2dCBM\ndGQxFDASBgNVBAsMC1Bvc3RtYW5sYWJzMQ8wDQYDVQQDDAZOZXdtYW4xIjAgBgkq\nhkiG9w0BCQEWE2hlbHBAZ2V0cG9zdG1hbi5jb20wggIiMA0GCSqGSIb3DQEBAQUA\nA4ICDwAwggIKAoICAQDiXuPtHr4a+qt5lXVJQUul71DocndC7eKvu3Sr6yrEThjy\nBaH45DUKLS9vW0a6TQhdfwatJvkmv3xFFnu+F3anr4vMgGR3jcSr55ipsnGlK2iE\nUa3y3Ikk7Q6TdOIJQ+wqhhtL7Cei/mwegjt6wGOO4bbUqD0dXd7endG4uPRIlMEv\nq5kaSZjECohmMAhHwdRfhTwOgCoqG7mdBDA/Lz5WdGUSBVo2fAxWjI3KlTDHOyIQ\nsSOr0zPUZUu3kyP+0jqPdzompflSlbYzqbjmD5gZsBL6fMUlheYx4M07Svy4LtZE\n7JaaQ0/zAE7tc5IdS3sw0m6CuCoRODaqEnqRoG45g8GW8eeTz6rhWDs/2q8mU1pp\nQ5lpjXPlQ/mEAv0PICeOsFQlBQ/krr1IAx0EhG8aeaxlQ+QcyX2SmbHvlgOB7F4g\nnRYp6TsAQILaq6FHRo947Bi9G6OMF7/0ut5HIqZ9nQalxgtO+71xXXJWxa0sCXmD\natdzXw+xh96VAmvqsqXlcYP30k2BVT1jvBaqcYHiG76tmmfT1UqzavUpDF3fQ+tf\nlAKW8kTW1SIDr2RZ4BOdvVKaM07MLGIk8tLvCQYpvzhilOjqgiMxzjQ30USPfLdA\ngXvAopfghuJrwLTzvbYAsszgNP/1+KrgLcxQO2ejlreJKZHXm8Y0uXbwAZcXyQID\nAQABo1AwTjAdBgNVHQ4EFgQUuJZUhNNBWTHQgmJCdrO1YyigjSowHwYDVR0jBBgw\nFoAUuJZUhNNBWTHQgmJCdrO1YyigjSowDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0B\nAQsFAAOCAgEA4bAWhXFbFJLiaX3Lsj+YWnrVVMrRrHzwfQlRVbRaEu0WsExNwfI/\n2HV3JrtV2PGYzIRwUBtX4/tg8r8BqPEDRcNtfu5P0Pv0PHlAxGgxLQQvrkbwz47g\ntCntZb9qzmROamTFjSxKnmjKSMjWxlCpeSCxG/00ib5tMhhgyMREIGgQvid4mfAD\nFY2hoFs1TOTxAFhNxfnt7U3RheTlv5CSFjbhUUWW3DyrJ7SouKIRdecMQCsnF+Ll\nqSFmjtMfhfWTudTpoEx/pNlFjAeEkxsMrRyKLDievYUGEiDd7zeTnr/TJt3zEMnB\nwqVaxmriBgIhDN5OS4rCPlUw8Xxjkj6vaucjnVaN/lKE/UWzFux8re4CIcENOR/D\nu/B03IaDldH2dKW+1qxPm2vaBsatwxJ9qqL3wPNpmshfE9+syjSf+LDZWS4k2wc3\n4a8gjtAQYCXpEscrfJ4Gq2oJVFznW0USfZ167JEf1kx981g4iRl6wL097qZzZKDE\nhtfQ8agefGjz8Vn+/AYWp9FOUA5extyRJTOApc6QrgUbfNiWj0lwBX4wvDoO1O+X\nfhqu5yCfqG1HYQTOPIXdwzBzWPH5VCtHTewXJ64PFFPNV5W+dpeXr0cz9fR8FZ+f\n0GZM6woZ9Cz29RJbBX6dDwONJZLJJaGMWp5w2lAeI6HfUp6bSfmGpSc=\n-----END CERTIFICATE-----\n"
  },
  {
    "path": "test/fixtures/ssl/ca.key",
    "content": "-----BEGIN RSA PRIVATE KEY-----\nProc-Type: 4,ENCRYPTED\nDEK-Info: DES-EDE3-CBC,D31E02E0C1169C3B\n\nvnh9eYeTXMyAjRAEgRBF7geTIrJgs9Ny6W8l5XGEylQH0+hNznChV7FHBhNUrYNn\nyW/J9FnBxMaixKISjHSV8ExIN0d7KGQw2LKXr3BzORrBzVk3tHnX3OrzMUUYQK16\nTUnV0dKSGjxwxQFffTmWQv3fY+U23dBgjkaAs9EBpeIMivzTxjGWVwA9oOvvseWJ\nHzfbFd7OnAT1U+q1xqQ17ECtmeNRj2wPmQ5GE4qMefftmWx6o0w+W85WTwDk+bVM\nUBZU7rF5aBUkmtAeY5PwoPbj7uJfZyQEezdklEBOfh65Xet7EII8c5/cqw5ZPQ+A\n0SXK4qZ9Y+gw9y7vMoLBgVuViiZcqOjBvldpVRXGRdX7F9Rth5NnwRNgOXWRGOhx\nkPwU36LQ6s8M7uRlOmx3u/iC+YmshGaLQvXIu3DEoAfFkqQAFgWTukBxBcgsz/bd\n0beMvRG5dgsOU7HD8ApeCwwD5/bhA53i7A71wW4jP7KOW+fGhNQNIArnpvQR6mT2\nQ+4Eafj9AEZnh0fBFeBGqbXWqc/IJo3c1OjnFfxUYal3sgONezmOcMs8IHbF8egC\naU05fOD65iMdvUlHREeVhQiZqEAOY6B7gG66INDXq8cNIQwYQOw6ocPeCJXXkW49\nJN/y0pYVZFY19X/XS9Hp2/+Df/8ChwoxWH3KEIPUKw12EJxjYHBSZ/rbKpE7PYPc\ndcuNGhf++mDIGjW2dRagPHF0OVOvOhM3V6CcIh69SyrDb2SiTgHupeF35oL384ut\nvBvQDx8eLNpphPDVkImR1/woRD6ZWjgQFycvQuVAJbB01R/u3H01H88Yt0AaLJcl\nPZMfytOk3/+hNJiYZxs2UozzRMAGVSJRLH5J9Sv3kDO7VFptG4n3f0mcBFrIB5KJ\nO3Se+GD9O0BRO3F2Q82ZEj5c0ikhF/DzJFn72KhzDH3MpgBDlWn3M5mO4qg35swC\njPe7PLCDBAcwbLxetVArnKihSU+XwUVwhsl5y9nyjkY8yTRNqR4LynkG8w5BoTPZ\nw18q7ZXXzklma/6Qdpg+WNaIhVZBNAGdA8TaY6gv5fCFXc29DDkjSDG4TR8EbCNN\nMErlqBbN7QEOK/P5AuiSMfeifAowCOsNE3UoK99GTbyBlD4j97K0WNlcRKbfrzfB\niGSSO+wq4ncqqnU/+TBgK3CaDkYGYT31SmH+1YH/pKqJKQWIrnUHhb8xmEZYInUY\ne5NdIq1h0KJqjDBsdfKNFIuKTvVPJV4Z50oJyi1u1RS0bFWEjEhkFcYWotIjS9T/\nGEFYo7fPQgJd6SOLWhWlbHIkzHYw1zUpg4Y7wiN9ELGgb4oqbQNmgppPnYTnDolA\nJZc4ePRA7NVDfbpj90iGUYLlbaJT0iZfUHlxpMYyi8CU8ml7gePtxxKbSZutnNeC\ndBj7+//rhAThnin4rZo/fBSam2yHcqS6lrjiyep8bTLe39FIc94gVtvP61Xb0SAx\nDGPwtxHB4Sm2C/mxYpuuuSqCsXojbjfw3QLNdfepAyHo/Q7TAV5/RNd09m+qBvUy\nD4j9Zdhi5iudTnHHdgM9niD3V7ETakY450ekRLurGg+CD2x7tVT09riTvz5DaYcL\nx36ZYV4zrrCIRHZHIi2/LhbWtItuGbWtDhvRpuCddD9vqwqwj9dzurp1xo5V2NE2\nilWKZO/TLF4VSIYnvNo6uRkOYMZ0TI5J0+2/giP6WC0T/borL8PRWX/laTEkUxpO\n+yerOS3ZJCqLtI8+zVNz1GBu5iTeu1TXPPyQBiID1VNI6ouS4qAiKuudNmBriCPt\nA8S9YsEYLtcESclogYz3cbJZclAT9mgiBF01uH1b4bOuEAB1idbQ6VffX7Iy8lfW\n6neXa2ul8K1yirv1AnjIKIHhv2hXzz/zN6DoamAGuQGgrRSdgii3qHKWmtJCOyjG\nYQPR6aCzMiHoSxrv0iFZUsiJRD2/3V6tB7EMkDKF1Ay6CUjZzlIYmbrpA5jsg8WL\nTPWH/tInZPIfw1W+1z3zNsTb6fQbJYhH1pe8aPMI3q8g+RUd5htolyNrrFhevw7+\n5Hs8aexC0FRVjjfbC/gkOVJuBqCMUE8AzvO/Uv1sofdlGCqF7RVRs3P4ruo+EbgT\ni1bfu63GaLu0hQfJ2JIHDa7JzcYa7RwrRZVv4m6AlcGMhYQ2u2TtkSroR6hsXBtb\nMowzAvn6tlqXz7jf7hDmPa6uQoLgcIgBS/bdwxAUqyMpAddnCZBCbDOGNRngDKBk\nOCPGKZ7RCGi1J4cAp9yr+OgIPbMFIhczIPhW2LwYKPfj+gaSh8mNgZ87V1JE8iIg\naLhBfF2mYUVMgg2za2/QBkXLPanhDB2Dqu47g9lCDHRbdNF215lN4HKf/qU0r2DN\nvnhrN/ZFdMmDWtgBJG6sNduQ0t3sSKrVuk0y4hT/qJCoyrLEOMzV55ciFusF0tPB\nRJly8wnb7G8Q+0JawSGtQm+hG4o5zjZLgEtvP8fA2Yf4oV8d3gvlHVJY9YCao835\n6oNx5lXu9v3wCbMqjJY0S0sdKirUDOGvuxpATQFlTSJJMU2/GXjdCbtWnekQ5pFc\noXfEgwQcudxbbMd9AywEvfPfWH3ERhUhuhdwLC9kr1SKgknpBlE/ktFXzgAyFEsu\nk2JsdOiWUUTGRshrVqEYT4C09/NAVmblaojqbubJmeMBerKmoS/X5ytL65g90Srq\nhiaIEUSjQQC3b+Y9hxBByLDqZA7NRQs4P30LLLXqtWz105/DOFWtW8u5T9qNxaC8\nzY9XqehCE0lJZewSV/KD7X7YRxZNuXwouFIwQCoc90HzPnDfDakYDsdnYNxjoY3P\nQFi0une8sXHzxgAEk1kJsvVJCqrr+uDkPZfdIQUTSJ1ZpWnXOVNopejm86HHtaJv\n/r6FynapnOsHxGjPtr/6y2pBXQdk5Kuwb9a4NUZxKEcyvFVFBxGs3pLVrC0kDbk2\n5WL61XpFPaBhJZY84s5McAj5b8Cqh1g39Fj5EeIiObKv+CPXmSuhc0rrNns4szoR\n5iEyWfa00qVaP0kc2wIf6U67shS/lyBn3eLelZ+mWn9+F4G+5IXeo7GKWngIM6wp\nLl96TZ/NDGEIKs0NuENZruau/FaCi97rAbHCtx8+YzLpbIFtnk5MvAYwecdtVLkW\n-----END RSA PRIVATE KEY-----\n"
  },
  {
    "path": "test/fixtures/ssl/ca2.crt",
    "content": "-----BEGIN CERTIFICATE-----\nMIIDmTCCAoGgAwIBAgIJAJ5DOjshFAqCMA0GCSqGSIb3DQEBCwUAMGIxCzAJBgNV\nBAYTAkFVMQwwCgYDVQQIDANOU1cxDzANBgNVBAcMBlN5ZG5leTEPMA0GA1UECgwG\nTmV3bWFuMQ0wCwYDVQQLDARUZXN0MRQwEgYDVQQDDAt0ZXN0Lm5ld21hbjAgFw0x\nOTExMjEwNDUwNThaGA8yMTE5MTAyODA0NTA1OFowYjELMAkGA1UEBhMCQVUxDDAK\nBgNVBAgMA05TVzEPMA0GA1UEBwwGU3lkbmV5MQ8wDQYDVQQKDAZOZXdtYW4xDTAL\nBgNVBAsMBFRlc3QxFDASBgNVBAMMC3Rlc3QubmV3bWFuMIIBIjANBgkqhkiG9w0B\nAQEFAAOCAQ8AMIIBCgKCAQEA6/6rTsqpiOJDFykvM+jboNutFXE9zIFs8Ka5tHk4\niRrVPjZoKYoUp1rp9cz0StoWnhSLKebeCV4Q54reSO0UITffcGQmQTdyOLj9hhYE\nwTwjEW0GBgRab0GqKq0TpdFCe0aPP6sme5ZvBGgzUGM+xBvj9q44FqLv0JoWAk84\nJ6gCW/SiTHdnwEdLctUmBdjuCbGW/3iSq6KsZ3gWjzkF0DnViayxSHCL8M0T7MD/\nbHp/ZK/ADhYwpqPjcs2Ol5YfOfJp5YEsJpDQGYm5SLt20V2Cq8OX5rM7zGs5g2Wh\nAEVoh2U85lDHtUlPTB1eWjxrvXK8ftohlHx+ToDtzs7TEQIDAQABo1AwTjAdBgNV\nHQ4EFgQUCH7qfoYd4Eb2BpGOQlhAzezLPZYwHwYDVR0jBBgwFoAUCH7qfoYd4Eb2\nBpGOQlhAzezLPZYwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAOLPZ\nDXpBKPb6BwANj8vwz8H0NWmmiJaNdqv9XUXFYVU6hsUQRUJutu772C2kqjx03RcA\nWHHsQLBZtyAuTSHMKQNwnvUoCFc7a6qwcQJTF8hCvVJARlhH4NdRvj6MabsRruiH\ntZMYcbnF4IIsTCt63NNjyCnIDbSs/JtTeIKyFcFgRwWZYTSZd42c4kFROf5aebpk\na1IACSKu1Vx62Hz/zgq1uops3vAwnPXc+8PtwSn8XEEL1pAiZWy9S2xyABeLHCOX\nZad3janI/GyOHAaChKawNAAj3v2ADS6SCpzqQT4ObvTiqioJ9WhBzwb9sFopaL5T\nJULygLz1gRJ/AnKVww==\n-----END CERTIFICATE-----\n"
  },
  {
    "path": "test/fixtures/ssl/ca2.key",
    "content": "-----BEGIN PRIVATE KEY-----\nMIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDr/qtOyqmI4kMX\nKS8z6Nug260VcT3MgWzwprm0eTiJGtU+NmgpihSnWun1zPRK2haeFIsp5t4JXhDn\nit5I7RQhN99wZCZBN3I4uP2GFgTBPCMRbQYGBFpvQaoqrROl0UJ7Ro8/qyZ7lm8E\naDNQYz7EG+P2rjgWou/QmhYCTzgnqAJb9KJMd2fAR0ty1SYF2O4JsZb/eJKroqxn\neBaPOQXQOdWJrLFIcIvwzRPswP9sen9kr8AOFjCmo+NyzY6Xlh858mnlgSwmkNAZ\niblIu3bRXYKrw5fmszvMazmDZaEARWiHZTzmUMe1SU9MHV5aPGu9crx+2iGUfH5O\ngO3OztMRAgMBAAECggEBAJeH+bVo+fzz08JuZmm9bjDWfUfUY6sJu8q2M23HnF6k\nxSHiS3XIvMRM4wc6Z+4cJQOyCz2HiTCYnuAd0ecfm5pMxwLiu5GKqaP0XI2ZW8o7\n9AR/bau1ZeAkWMB4S7JgMID5aIeoPNiEWpqI0dIfN7Eye2jsqwUV8EiQd+tZtKP4\nyHCRKt4Vh4l5VaVylAnTV7vmHC7dootZkMTn4c3sV8wGe69gdWvqsVw3UEeg2Zb4\nfcdmF3n6nyDaz64xZwN5Oa6UJPRa2px2b0oBTiUAuLZlpMV60DN+xvzeXXRLxMn5\nY8uO9fMeImLpQEwECLrb87wJv/++s7Y3AUVNfamKOLUCgYEA/FKlPFWg9bj13dGM\njLEU8GUwjdBxb0HyFwfkRcpk5v4pU0/cMyacnlEjjpqxo9zvzWW0I9iepG+SRTm4\nAEvEbNulFKOPT8Z5pvqSsVh2fIaxnpXTbL/EYB9PZRLKXSd4r7ztNYW2NwUsR9i9\nmiNwgEIebXJoCwvMC3kgf1IMgOsCgYEA728bm1VRdMpctNINvoFFK65cOuwu9V3s\nccgvdrjUvhvcnj9QI1bxNmhEjMFEA+FXEOx4tlAQP8dv1g0hX/V36Mrn59Seh3jW\ngCSQczUGqoSYry7Ks8Lrm0jR6c0WK2k3BsN0wLeK6lP/yNAzRfOYEQd6amczgqNq\ncuR4qATUXPMCgYASOupjTJB/kGh7KUutUpH/uF/krx2y+yHBljlg7XmS0uQrd8ai\nD3UbXyNhhz20aB8PSPzV5i24FbOMutnXc6Hyd4Aa2KJfEijx7oKwu4J8BsNIgOyw\nm75Vb42t8MicKGDo2Y6N4mZC3WXQnxE71LmpGp3WLIDl42lPnuXBLS1oFwKBgBMU\n8MdNYmODaSYEA5JmLQQRLkqH3iox5REgWiAFFPddsxRtiU53tFuYrbXmBSyl/dFc\ndzZYZSMgGtqdS0ahgn/sA9VnDYdQaw/lWhnEZRab4Ks9eGwhIbPLdudCL/0fsoH4\ne8qMFiccsKrpZNyzUDAzP19RgDpuGaK0cKU7VU1fAoGBANJSesEEEpqkvRWcNY7l\nkDyE9I2L3wsCAF71bPwRGoZc/fXGYy9qx0faGFWBFGm8VP3r3hqmLbWktak13GQb\nkc8ce3LyCeuHnonPNSODmSfx62qQJwlnhz0kSr/CpIV/LoWH79adnFSxtSaZnfqR\nz0ATGCvJ4Y8uittsmyGSUUwV\n-----END PRIVATE KEY-----\n"
  },
  {
    "path": "test/fixtures/ssl/ca3.crt",
    "content": "-----BEGIN CERTIFICATE-----\nMIIDkjCCAnoCCQDVmzvauKidhzANBgkqhkiG9w0BAQsFADCBijELMAkGA1UEBhMC\nVVMxCzAJBgNVBAgMAkNBMQswCQYDVQQHDAJTRjEQMA4GA1UECgwHUG9zdG1hbjEa\nMBgGA1UECwwRcG9zdG1hbkBsb2NhbGhvc3QxEzARBgNVBAMMClRlc3RDbGllbnQx\nHjAcBgkqhkiG9w0BCQEWD2RvLm5vdEBlbWFpbC5tZTAeFw0yMDA1MTIxOTUwMTVa\nFw00NzA5MjcxOTUwMTVaMIGKMQswCQYDVQQGEwJVUzELMAkGA1UECAwCQ0ExCzAJ\nBgNVBAcMAlNGMRAwDgYDVQQKDAdQb3N0bWFuMRowGAYDVQQLDBFwb3N0bWFuQGxv\nY2FsaG9zdDETMBEGA1UEAwwKVGVzdENsaWVudDEeMBwGCSqGSIb3DQEJARYPZG8u\nbm90QGVtYWlsLm1lMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2c3B\n3urKLmkimxO9i1mueVqBzSMn+fygV87DwL8RO899S3SXO2ZtHECxLgCR3qRXUS2R\nwY5JYie1L5qJYnOrgBO/mhxuX9KbuUz5xSr7vOWzVPlqCMBbKa24bDfJ/NE036yr\nLqIUSx2xeUoUp9z0rqQaXHLezBX5w6DYCwb0/RmY+sWj23/NnMTzDituPGDjUp/6\nxIBOYBpolXDYLVCvjoO3UnUJ5ffAMyuanr9Myx1j8lO0rkjUV/IPPZfrv4OQEu3M\ndWKOyENWnfQVK7VHsm9RlBf6WcH0XiWGQdmdd3uU7HOMd132QLbco2j1U9IKnX7h\n7Wsi08Af2WStjzpePwIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQDVYYYM1IndsUoZ\nVaSSWUPzFdSKY37RYiRYKKz/2hrNyQ95PEv8oDneZAkt2wRR7mG0YGvsoAMu7OLk\nsbi2t/PbIRTFe1nWWqVE+05p1OQWuDlK2UZx+d7h3NTn9SvtNPNcF2nejRU6iFjY\n/8mg8bLLkcJvlTW6qc3mPZyof+jGc7/JOB+RXsNVf8HKcNDExZlYUjIWBWDhCLCD\n73bn2c1d+Rtdzne1gB2EaEXtATbE2VCnvttwS5XmGK9ur+KBPMDeBla0k4UipbfJ\nUMsE//7mGUzMoHpFdyi+Bljw3Z+ORf843THHcB0byaXqLGrAysQpe+kmPm1ZgIp5\nvcP1nYu5\n-----END CERTIFICATE-----\n"
  },
  {
    "path": "test/fixtures/ssl/ca3.key",
    "content": "-----BEGIN RSA PRIVATE KEY-----\nMIIEpAIBAAKCAQEA2c3B3urKLmkimxO9i1mueVqBzSMn+fygV87DwL8RO899S3SX\nO2ZtHECxLgCR3qRXUS2RwY5JYie1L5qJYnOrgBO/mhxuX9KbuUz5xSr7vOWzVPlq\nCMBbKa24bDfJ/NE036yrLqIUSx2xeUoUp9z0rqQaXHLezBX5w6DYCwb0/RmY+sWj\n23/NnMTzDituPGDjUp/6xIBOYBpolXDYLVCvjoO3UnUJ5ffAMyuanr9Myx1j8lO0\nrkjUV/IPPZfrv4OQEu3MdWKOyENWnfQVK7VHsm9RlBf6WcH0XiWGQdmdd3uU7HOM\nd132QLbco2j1U9IKnX7h7Wsi08Af2WStjzpePwIDAQABAoIBAQDZsNSoGGXR81Ua\nSKW3RQCk3DhGL3BCZSRh/xAacx4neKATrcmGHj7J8ULl5r3lGL8JLRG0sqFYELYA\niWXtWA0+6v4ja21KKvdoQq6WSfrod3FBajR34MJ9Ktvclfo1zWgac7t41ZiQ53G9\n97Qjfy2z6+NJKarTstc7l2S3yNFOsdCXeqKLVCPH/s0EqyPRIQauNSBmVfWtJaXD\ntiuz/IGH3ICiiaM7cSkKeEQwVmGatco+70yf8bwfCSPRALnnFz8ZqkESgQgGvLZr\n3Cd0U1TzAwtCIKNCxWBX84Roiw5VbRTusqLonGKk9icknJX1SYjyUbiyL1YhIVjn\n16pWSKxBAoGBAP7ReFscvS3OlgAQNy01UD8Ntc7g4XRxlRwJ6/gOwr817XcGx8E3\nOMtlxhz4yL/SsSyAzG3svQaJmiGaBkG58qWXq2w1Qy3lsnHpqzG8h7iyAory8/0A\nQIGCqxMxmudPV1wvfm7bkkQAz5s9Tz/uEVWhwxhkK1jzZIQy/6qz2bghAoGBANrQ\nV5cM5AL/1cR7fUc0l6rdiAmhvf/vUBPF13VZolh1o/aRIfb0IYIF+Hnv4YJQ9Twm\naQxMxGQI8DhrENaCe96T0C/LHjEzpptYQXMpOcFMkJj6FY8Z4pxEfSAMe8MmVZK9\nx6ckRv7jb4ncrUPZPhnp49GuZItM0x0E4Z69hcpfAoGAIp/B09eG2ReOCDor1Se+\nXKL3RkIGQHVChonOl2kiCys/tgGk2NsxC2orzjn7xRzS2DI0FOerE51U5SXxnbKv\nhtKiB1UBaNYiNhpDGcH9SxpdABZdEs6a9T4VEsmVu8JrI2qMqnGJYVYe34AoKY6m\nqlUNll3eCfsgeFoZpU9E0SECgYEApg7G6lNWFxCg4mP1RzyafYlx3B1rW/f6BYd3\nZA+KLSfaLx0lcY0EgPCXCbMKqSNXeTaNMlBwGprN84MNXD3aU6hJrnuvhhd0sR/h\nS8xVkGTSt8XS5q72UzGG4/OVWRyWhK6R/j6Bwp5H35AhzgPoJTJjOpXmp/C9pqA1\nuYqLJnECgYAQoeFRKlwiBPFfONepKdFWkoeqzQGQOvLMjHh+atiAY8X3K45lVZeZ\nG2J6ZGKYziBFBfVLkvyRKzvtcFE4qAX35FhWtP4MgCN1pepsfRhUBxRl5NcKIdSh\nxa0raTFHSZ8v6LFsRgdCJ3yDP/7r+4y1fF7wzGdhm2YOc4yhTxRbGw==\n-----END RSA PRIVATE KEY-----\n"
  },
  {
    "path": "test/fixtures/ssl/client.crt",
    "content": "Certificate:\n    Data:\n        Version: 3 (0x2)\n        Serial Number: 2 (0x2)\n    Signature Algorithm: sha256WithRSAEncryption\n        Issuer: C=IN, ST=Karnataka, L=Bengaluru, O=Postdot Technologies Pvt Ltd, OU=Postmanlabs, CN=Newman/emailAddress=help@getpostman.com\n        Validity\n            Not Before: Dec 15 15:12:29 2016 GMT\n            Not After : Jan  2 15:12:29 2085 GMT\n        Subject: C=IN, ST=Karnataka, L=Bengaluru, O=Postdot Technologies Pvt Ltd, OU=Newman, CN=Postmanlabs/emailAddress=help@getpostman.com\n        Subject Public Key Info:\n            Public Key Algorithm: rsaEncryption\n                Public-Key: (4096 bit)\n                Modulus:\n                    00:c5:1a:b1:40:64:a5:bf:0a:f3:86:82:f6:33:cd:\n                    79:0f:ec:ef:e3:0d:36:5d:6a:49:c2:53:fa:45:f6:\n                    b3:f6:d4:cb:27:4e:c0:cf:66:8f:ec:47:c7:e1:fc:\n                    5e:64:3f:5a:85:a6:dd:bd:a4:b0:a2:ac:8f:1b:0d:\n                    e1:39:48:c6:87:35:92:20:3e:cf:ed:d8:dc:d2:59:\n                    70:a3:09:23:a1:cc:42:d5:25:e1:da:07:d7:1b:cd:\n                    2e:dc:97:c2:c8:47:1a:d0:04:37:b7:4c:cc:50:b4:\n                    10:b9:8e:aa:46:70:c9:cf:f1:00:9d:66:15:01:80:\n                    3a:48:63:2e:f0:eb:10:7b:56:41:53:90:9b:34:51:\n                    4d:93:b5:3b:d0:ca:d6:a1:f1:70:44:38:f4:91:e3:\n                    a4:67:b0:1d:d0:b1:e7:99:6a:2e:60:d5:98:fd:a8:\n                    11:70:eb:cf:2f:d5:9f:16:a8:c7:d0:53:2f:85:ab:\n                    81:b4:f0:b8:94:07:1a:8b:a8:3d:27:92:27:d8:6c:\n                    fa:20:8a:2b:d2:87:a4:6e:ca:36:45:52:3b:1e:70:\n                    50:91:2d:86:f8:49:c8:f8:f4:9c:ef:92:6f:54:1a:\n                    5d:54:47:30:37:6f:fe:69:b8:f3:75:fc:a0:f2:d9:\n                    1d:7e:23:8d:0b:55:6a:40:e7:2d:32:0b:48:ed:fc:\n                    93:8e:a8:6d:86:61:ce:d7:4f:77:6d:eb:bd:b2:67:\n                    58:0c:95:f1:d4:9e:a4:6c:8d:dc:8a:5d:de:0c:70:\n                    59:da:ec:03:e6:3e:5b:a5:c1:92:59:95:21:b4:a0:\n                    2d:09:7b:cf:92:9a:96:05:88:2c:8a:97:01:1c:b2:\n                    f9:b1:56:ac:e4:cb:de:5c:69:0f:58:59:c2:21:1c:\n                    4a:49:68:b0:aa:1d:a0:86:b3:0c:05:8f:eb:3e:33:\n                    cb:fa:5a:5d:51:0a:b0:a0:c3:c1:3b:9a:58:61:34:\n                    e7:9e:5d:8c:4f:ab:2e:fc:ea:cb:d4:10:39:6f:21:\n                    95:5d:85:0d:4f:f5:d4:26:65:cd:da:92:c3:02:96:\n                    72:34:96:7f:1d:1d:57:a5:4e:bd:a0:7b:e7:36:ba:\n                    46:df:07:b2:c7:19:b5:af:f0:5e:55:ee:2c:c6:29:\n                    47:62:d5:e8:6a:6b:68:37:e8:de:f0:34:71:3b:23:\n                    b0:f6:2a:47:f1:0a:a2:7a:20:b7:80:22:f3:53:15:\n                    93:b8:1a:93:d1:54:58:2a:44:2c:13:97:d6:88:b2:\n                    42:36:e2:81:dd:d6:d5:29:7d:92:4f:b8:ce:d1:bd:\n                    b6:02:6c:f2:b6:0c:b8:78:e2:2d:6f:bb:f1:0e:bc:\n                    58:7c:9d:30:a4:31:c4:1f:20:98:97:31:c4:32:dd:\n                    a3:5c:61\n                Exponent: 65537 (0x10001)\n        X509v3 extensions:\n            X509v3 Basic Constraints: \n                CA:FALSE\n            Netscape Comment: \n                OpenSSL Generated Certificate\n            X509v3 Subject Key Identifier: \n                6F:E2:A6:F5:18:C0:D9:BF:5A:B4:4C:48:3E:C2:AA:8F:7B:C1:A3:54\n            X509v3 Authority Key Identifier: \n                keyid:B8:96:54:84:D3:41:59:31:D0:82:62:42:76:B3:B5:63:28:A0:8D:2A\n\n    Signature Algorithm: sha256WithRSAEncryption\n         a3:75:b9:5b:c5:12:6a:7a:98:03:40:98:99:46:15:50:4a:82:\n         9f:ca:fe:9d:72:f8:71:de:0d:2c:98:fc:2d:84:c8:c7:0e:5a:\n         d8:8f:de:87:76:aa:fe:8a:b6:28:cf:ff:cb:83:9a:fa:5f:53:\n         d5:9e:3d:cd:31:53:ed:10:c1:f1:04:de:02:85:fe:6c:ee:4d:\n         79:79:94:23:58:a3:11:f4:ee:10:cb:c0:7c:a8:9d:ca:0f:02:\n         ba:37:a7:bb:bd:88:3a:ec:67:9a:a7:3c:68:c6:25:04:29:2d:\n         66:f0:17:1d:ce:29:3d:48:c8:32:c9:5f:c2:f8:a1:62:f5:50:\n         8c:11:79:cf:b7:eb:80:21:1e:ab:e5:26:ca:58:fe:35:5f:a8:\n         4f:b9:41:d7:fb:0e:28:02:63:86:95:59:6d:22:9f:d8:db:fb:\n         d3:c9:be:30:46:4f:b7:7e:f1:d7:7a:23:f8:0e:8f:b2:14:09:\n         9f:77:f6:10:0f:02:8b:23:dd:48:f2:9c:b7:7e:9f:7a:4d:69:\n         76:16:64:42:5f:02:37:bc:f6:de:89:25:1a:1c:90:12:21:38:\n         e1:09:82:53:78:bd:3b:a7:62:28:80:f4:3e:6e:1a:9f:42:1d:\n         05:71:c4:e5:fd:72:49:3a:b8:7a:2f:f0:e8:42:28:8d:04:f6:\n         e7:ae:9e:60:72:e0:51:46:64:5d:e8:86:86:e5:99:66:26:43:\n         86:00:80:5a:a4:15:8b:43:b1:0e:08:54:6b:69:30:fd:5a:48:\n         c6:39:30:60:cd:1e:cc:9f:44:10:07:5d:93:cd:f4:97:1b:c9:\n         8c:53:be:26:07:80:f9:57:eb:10:76:b2:c4:dd:66:8c:c6:57:\n         7b:83:67:e2:00:6b:d6:90:2a:3d:00:74:f2:1d:ca:46:48:06:\n         ac:c7:76:92:78:c0:62:60:10:86:53:0a:b8:6e:ff:41:10:d6:\n         9f:e3:99:25:90:9c:a9:0b:e8:36:af:d3:33:d2:97:35:4a:7b:\n         aa:6c:4b:a9:7e:b8:4a:af:79:8e:00:88:be:9b:7a:0e:6d:63:\n         9a:71:28:b3:6b:ef:54:84:ef:2f:61:c9:8a:f5:ef:cc:70:0b:\n         67:21:a3:fa:1d:ee:85:f0:26:29:85:ad:06:7f:21:ba:3a:96:\n         ac:85:05:4a:73:58:fa:e2:c7:34:c7:a9:6c:44:8e:15:20:62:\n         f1:33:4b:98:46:d9:8f:20:ad:44:7f:96:30:a6:31:ea:09:65:\n         88:62:a5:8d:91:77:82:5b:58:19:4d:1f:4d:34:88:29:1d:82:\n         db:3c:9f:7c:34:c1:b9:46:65:96:e9:1b:8d:f5:40:9c:83:62:\n         c1:64:70:c8:e8:0b:6c:b9\n-----BEGIN CERTIFICATE-----\nMIIGSDCCBDCgAwIBAgIBAjANBgkqhkiG9w0BAQsFADCBpzELMAkGA1UEBhMCSU4x\nEjAQBgNVBAgMCUthcm5hdGFrYTESMBAGA1UEBwwJQmVuZ2FsdXJ1MSUwIwYDVQQK\nDBxQb3N0ZG90IFRlY2hub2xvZ2llcyBQdnQgTHRkMRQwEgYDVQQLDAtQb3N0bWFu\nbGFiczEPMA0GA1UEAwwGTmV3bWFuMSIwIAYJKoZIhvcNAQkBFhNoZWxwQGdldHBv\nc3RtYW4uY29tMCAXDTE2MTIxNTE1MTIyOVoYDzIwODUwMTAyMTUxMjI5WjCBpzEL\nMAkGA1UEBhMCSU4xEjAQBgNVBAgMCUthcm5hdGFrYTESMBAGA1UEBwwJQmVuZ2Fs\ndXJ1MSUwIwYDVQQKDBxQb3N0ZG90IFRlY2hub2xvZ2llcyBQdnQgTHRkMQ8wDQYD\nVQQLDAZOZXdtYW4xFDASBgNVBAMMC1Bvc3RtYW5sYWJzMSIwIAYJKoZIhvcNAQkB\nFhNoZWxwQGdldHBvc3RtYW4uY29tMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIIC\nCgKCAgEAxRqxQGSlvwrzhoL2M815D+zv4w02XWpJwlP6Rfaz9tTLJ07Az2aP7EfH\n4fxeZD9ahabdvaSwoqyPGw3hOUjGhzWSID7P7djc0llwowkjocxC1SXh2gfXG80u\n3JfCyEca0AQ3t0zMULQQuY6qRnDJz/EAnWYVAYA6SGMu8OsQe1ZBU5CbNFFNk7U7\n0MrWofFwRDj0keOkZ7Ad0LHnmWouYNWY/agRcOvPL9WfFqjH0FMvhauBtPC4lAca\ni6g9J5In2Gz6IIor0oekbso2RVI7HnBQkS2G+EnI+PSc75JvVBpdVEcwN2/+abjz\ndfyg8tkdfiONC1VqQOctMgtI7fyTjqhthmHO1093beu9smdYDJXx1J6kbI3cil3e\nDHBZ2uwD5j5bpcGSWZUhtKAtCXvPkpqWBYgsipcBHLL5sVas5MveXGkPWFnCIRxK\nSWiwqh2ghrMMBY/rPjPL+lpdUQqwoMPBO5pYYTTnnl2MT6su/OrL1BA5byGVXYUN\nT/XUJmXN2pLDApZyNJZ/HR1XpU69oHvnNrpG3weyxxm1r/BeVe4sxilHYtXoamto\nN+je8DRxOyOw9ipH8QqieiC3gCLzUxWTuBqT0VRYKkQsE5fWiLJCNuKB3dbVKX2S\nT7jO0b22Amzytgy4eOItb7vxDrxYfJ0wpDHEHyCYlzHEMt2jXGECAwEAAaN7MHkw\nCQYDVR0TBAIwADAsBglghkgBhvhCAQ0EHxYdT3BlblNTTCBHZW5lcmF0ZWQgQ2Vy\ndGlmaWNhdGUwHQYDVR0OBBYEFG/ipvUYwNm/WrRMSD7Cqo97waNUMB8GA1UdIwQY\nMBaAFLiWVITTQVkx0IJiQnaztWMooI0qMA0GCSqGSIb3DQEBCwUAA4ICAQCjdblb\nxRJqepgDQJiZRhVQSoKfyv6dcvhx3g0smPwthMjHDlrYj96Hdqr+irYoz//Lg5r6\nX1PVnj3NMVPtEMHxBN4Chf5s7k15eZQjWKMR9O4Qy8B8qJ3KDwK6N6e7vYg67Gea\npzxoxiUEKS1m8Bcdzik9SMgyyV/C+KFi9VCMEXnPt+uAIR6r5SbKWP41X6hPuUHX\n+w4oAmOGlVltIp/Y2/vTyb4wRk+3fvHXeiP4Do+yFAmfd/YQDwKLI91I8py3fp96\nTWl2FmRCXwI3vPbeiSUaHJASITjhCYJTeL07p2IogPQ+bhqfQh0FccTl/XJJOrh6\nL/DoQiiNBPbnrp5gcuBRRmRd6IaG5ZlmJkOGAIBapBWLQ7EOCFRraTD9WkjGOTBg\nzR7Mn0QQB12TzfSXG8mMU74mB4D5V+sQdrLE3WaMxld7g2fiAGvWkCo9AHTyHcpG\nSAasx3aSeMBiYBCGUwq4bv9BENaf45klkJypC+g2r9Mz0pc1SnuqbEupfrhKr3mO\nAIi+m3oObWOacSiza+9UhO8vYcmK9e/McAtnIaP6He6F8CYpha0GfyG6OpashQVK\nc1j64sc0x6lsRI4VIGLxM0uYRtmPIK1Ef5YwpjHqCWWIYqWNkXeCW1gZTR9NNIgp\nHYLbPJ98NMG5RmWW6RuN9UCcg2LBZHDI6AtsuQ==\n-----END CERTIFICATE-----\n"
  },
  {
    "path": "test/fixtures/ssl/client.csr",
    "content": "-----BEGIN CERTIFICATE REQUEST-----\nMIIFHjCCAwYCAQAwgacxCzAJBgNVBAYTAklOMRIwEAYDVQQIDAlLYXJuYXRha2Ex\nEjAQBgNVBAcMCUJlbmdhbHVydTElMCMGA1UECgwcUG9zdGRvdCBUZWNobm9sb2dp\nZXMgUHZ0IEx0ZDEPMA0GA1UECwwGTmV3bWFuMRQwEgYDVQQDDAtQb3N0bWFubGFi\nczEiMCAGCSqGSIb3DQEJARYTaGVscEBnZXRwb3N0bWFuLmNvbTCCAiIwDQYJKoZI\nhvcNAQEBBQADggIPADCCAgoCggIBAMUasUBkpb8K84aC9jPNeQ/s7+MNNl1qScJT\n+kX2s/bUyydOwM9mj+xHx+H8XmQ/WoWm3b2ksKKsjxsN4TlIxoc1kiA+z+3Y3NJZ\ncKMJI6HMQtUl4doH1xvNLtyXwshHGtAEN7dMzFC0ELmOqkZwyc/xAJ1mFQGAOkhj\nLvDrEHtWQVOQmzRRTZO1O9DK1qHxcEQ49JHjpGewHdCx55lqLmDVmP2oEXDrzy/V\nnxaox9BTL4WrgbTwuJQHGouoPSeSJ9hs+iCKK9KHpG7KNkVSOx5wUJEthvhJyPj0\nnO+Sb1QaXVRHMDdv/mm483X8oPLZHX4jjQtVakDnLTILSO38k46obYZhztdPd23r\nvbJnWAyV8dSepGyN3Ipd3gxwWdrsA+Y+W6XBklmVIbSgLQl7z5KalgWILIqXARyy\n+bFWrOTL3lxpD1hZwiEcSklosKodoIazDAWP6z4zy/paXVEKsKDDwTuaWGE0555d\njE+rLvzqy9QQOW8hlV2FDU/11CZlzdqSwwKWcjSWfx0dV6VOvaB75za6Rt8HsscZ\nta/wXlXuLMYpR2LV6GpraDfo3vA0cTsjsPYqR/EKonogt4Ai81MVk7gak9FUWCpE\nLBOX1oiyQjbigd3W1Sl9kk+4ztG9tgJs8rYMuHjiLW+78Q68WHydMKQxxB8gmJcx\nxDLdo1xhAgMBAAGgMTAWBgkqhkiG9w0BCQIxCQwHUG9zdG1hbjAXBgkqhkiG9w0B\nCQcxCgwIcGFzc3dvcmQwDQYJKoZIhvcNAQELBQADggIBAFrUInIkTw3Er7FdVcj8\ncAF2khW31gFLD+ohiGt4b3Thmfx9dnUl+PJv/c4AAHriyr+TdRxQeaiBWRG9qgpL\nGYSeKG4Yoy9BSNxS33DxEo0RUjBKSkds9xcxK2unZftWeDav5MHZ04Em1NqWDwzw\nFENN3jKJequ+d4+OLwjqjXE9cEpmYcZob8dfxiwrD9TnQCQIJWqAKVqNsUPojQjV\nCYRn2KsHZrsHIEclz1OHto/n16XyRMcieryP47CziweSuW+hDGcRso+T2F+BBYe1\nMa/wzwc5VHc82lSduLbcZI92t/q60O47zb9YSJORNSf7FyeAsMs8AjY3LrAIUDli\nvLm3nKS0DgTATceb5vY/s1SMkLeSejrNI+PamFrNXu/4o/G+XTG3TvB841z+rSHE\nNU6fLeoK/amzLPmP0hKuFWyin25FHY5sXowVud5M+GY+WfeUMQuZQkOBThelLH04\nWw2cuJEJn8m08bl26luJAhkGs739GDy2+94+hXVVicmNgz99MBvszJZ29GvsmZxi\njnlXoCG5q1/BzDpDL2D5Hbvga5M+hdonQQ3pZglneuSyiFZSVhsvWAGXfNB0wqDL\nSUb3wq3YJE/cYt2bKI2u2KRtKjFMRRlWaLEkMmAYZHcij3i8pnvmAokwy1T7GkNG\nsDlu0WZX8PeksXnzFtyObpR1\n-----END CERTIFICATE REQUEST-----\n"
  },
  {
    "path": "test/fixtures/ssl/client.key",
    "content": "-----BEGIN RSA PRIVATE KEY-----\nProc-Type: 4,ENCRYPTED\nDEK-Info: DES-EDE3-CBC,05DC011909D47B71\n\nhLVwvgtfXSYuCYLG/6yVLkkoufji8EmOKrKwYLZ13hUNBNWXVdtcJphBDCter9Ty\nWMuUSBQFkWfTcbIY+VKhmjXWFAs58Q2g6Q59hROrypRK2H9k/Qh8zTeSHgv1q9jz\nCYyEi12CRjDhgn/SwAW6Jgvv2MJltlidwXQcvbRMRZH2DNYs56Uq5hT5T7OXSW28\nCCMK8L0WN0fS3lKZZLp68X//axsjfDcYkAs7o5ClCR2h5Ncrc+4qRRKakrRedk4J\ng/IrlLEob3n/UKUdg90g8jdKUMiolIVUjw/FlqNTYN2U4/GsaTB96CpzBSa+cG/4\nEfzxP+YjmUVRwrl7mb6sQhXJtHCwQn0OgBhFJZVIMUbfp48vNV64LEmwOhSzZhBG\n0CEyiyPAByQsH7EM8w3QdfYu8uCgmQH8VKTfgLErL1MLiCNmzCEERroUo1YMn3wp\nL35VF1/ht7HjMK+X25SuL1SOzpzvqRrpl3h4ITUm/lVxDU1TxReEZJIY3PwWZUQ8\nzbtWCa4T+GaNc6QkgpwLYUJSoMqC6WpE4q+jy16ogoD9jT0cA/Z3WQxgbJSLb1zx\nApRIOW5h8R9VCVY69Rt+zxc5jTIzYX1CMD+Gru10esHQOwt21/3qd1+N6SdMaX1W\nCw6yiJRQ3RqU7ffSFJ33zYI9QzWhEvmglzZ6/xAAmwvDbIA8vYuEJUhPuo49gBrg\ntfrjse5jqAmw3bQgBc440VfBEunX0lJoEcpyzy3P8o+In2F/1vvmv2DAIb6G5J5C\no8iYnCkHg1cet74fX+piz00NpHSw/LKgM8urohVB3QvfgPiQ3vzUutotlEMcAeMs\n/lWyLZ1r7zz3MnkXBH9BzUc4RILOvEmmwO6O9FpyGFCnXt5Y2BKJP1uTUZjhGIAK\nOzIBHYlVe0ef1SOzw3eo+NbJfrtP6AOK0+OYkQlcZpVvc3yl3dgoLzJf36xePhZf\nRV9WORIv0XTTpuolsEioLRaLT53fXWHB7LOJ6nRd38mX0tgayj+o/ryrsauXn40W\nYXA3cql4S7Coxu1OwJgBweXPAs5axXLBKrjzKZU6NZ4W9tRx12OHTfMxA0o/vEw2\nGHoV9tj7dcJ1wrBjmDh0vVxu4tfTn1TMkUy23y40AI00VgYoCInYKcK1PQM/2Ef7\n/CvHvP0tpD0SJavxc7TkVvDtGn5GXCt2J2zOJYzjVrtMgfpQ1TJP6EgoTCPkeir9\nJsSETzFYM6zKIhWdGUF2hSWWrh7KMgEvSYx82EjbppKNqTT4F7X4xMz5aHR8BbjD\nL8BAN93Fgd7u1j+fFP2wdxzf3gCR1vpluvvYFXIy+m+5BQIgC8FWy/tLHzSvE8Gg\nPg/LqeLjUvZ53obRy7R0F6vjEzZ3uR8chtV2mcSeh//1btYUtJ9nwl7XqNyemf7H\nR8k81kLfleRMLdI3BFEWOE31XF5UH5LKFSfF7q/q66Ut+6eZGa0aUJojyH2E1iyf\n7CFFdl2ZpWUepqFhvPokLFWnc1S4PgPjNEY6K3CJYimNNKihpFgs+ilfSUdg6uPA\nsx2t0fuqtCKynqfB9AnXxAUoLjUpOznIBBNSzq0ku39JF3GY5FDqNuyGOBv8M+pf\nkF21GtZFIClMKK8JEBvDh4OoJWFw2vXKcrlWJLju3DPQx6pbl3fuSPAa5IY8VrzL\nYCheHXBasxSLEgNaMY3HYMOVPyDPs+cGdN5u414gsQrkk8svZCtkcWEe4WcOaSTX\nl/zZ6PAVx7egCDNyvWcLrh3mDxXa8p+MLOHfUBKT+dFBTQNtFjMGxXsV8TT/r90Q\nmQ0Qwb0c/vEscKaoPPqepBoLabjxltxvPj/7jTe+3CdR5l+oC93JcASNv0ub4v98\nvGAe6JHe7zCyDgYlq7ryo7ZUE1Sf3fhGD4MZVDYWNnMw4cw2Cg0B7OyLNnslRhMt\nIw956xK5uDn1YQQjQJ6I3W/TgFMZKPPV+vVcDJheZhMV8vvDxXjSGqfJ0imrG5IM\nuZuuxwUNDlxfwC5kII13eZXUebzRoSL2xhxKVK6GbFjrINXT6oAai3H5SHNm+8uh\n8a9jOxceE2mVoYpDqOrYzBKZaJAx2qYCyByGbCQxmm3laTdXRy0s9njIu7nfAhvL\nV/Anz8iEU44+mrmK2rBXJKJBakc2D67YSxV9WMW7ftmdZMbSztdTpflYUe6tQn5E\nDfeCLiUigtqFTyvEap0h+48daXfGIfbE+cQU5o93fqRvIJtyXlQUEgGzsfnyWasR\nz1VuUSU7e1x+3whxrdgevR22bBKBC2wMPz8HLLHSTWxZVzpmwds1xEKXwVaoSVKS\nj7k9oERV5QQlDrwSSnwEbG9tsoIJ3a0B+sKOf4ibJM4F6nm0sUj8AMnvwjPfzjYZ\nL1ARV2VZXFwNO7dgsGYXwnFSBKIB+cyXdtfnWnz68ZpgvYAy/7902gzQAADdNkrm\nbe46T55zqFTyE6M1TfHiXhfcEhTitjOO+LME91EIuTVwGExbS38cLnvG0XDMJxQ9\nCplFCa0ATj5Kk3B20tq2TyYLOBTLsbOsZAipnh++ugszyHltjkecZW6BTP6GaQrv\ne6m1BMV6WEVZFkhAcUuWKn5+srol2nZXBswVqjxswr2OetNgxlpSZmqpMQj8slrg\niOMVZldwqlegMWJKWkg0F/8c6jdstP4wMBJ+Evd4/M+5HXHurZQLOaEcVbSLnNKn\nvobPBezG/p8zlHWgEoUNNMVUJ3jb3GuZ837Okmn5yNeu/za34MoHSlbOWT5hw5OS\njF8YQQ/pGOcCh0k9Goyj/R4EEuBWkOkyh4+QDwJdVJZZGqkyaASHIVIeVbL0zRld\nTiiXDz5nE59PSRwLQd8GauPBSKzPxsqlexVKCZkoFjNy97CxVnzgiN5zD9G5AjdI\nelhxx4Cj2RlX6H40HfECwJ/wZxs/ZAdS1Rak3++D58AcwgjDUjPfLmrOYvUun1Vl\nPtPHkAWSUlNYm+hVj3mbESq/JT5+tEhU2t5mazns4fu9iWfIzDTquB0RwBvqxfr2\nffr6sLJWVniwtZqVZEdml7GBWgyu4ydsXn3RXUtFUt0DSipOFCv4esp/T0KihBZA\nC9CujkdSbxWB98P3nhhUXcZvrr0hN9nq9DcVBac/PdjG3KD2cQGCT1U8EbM02DHe\n-----END RSA PRIVATE KEY-----\n"
  },
  {
    "path": "test/fixtures/ssl/client2.crt",
    "content": "-----BEGIN CERTIFICATE-----\nMIIDLDCCAhQCBhJxhSchCDANBgkqhkiG9w0BAQsFADBiMQswCQYDVQQGEwJBVTEM\nMAoGA1UECAwDTlNXMQ8wDQYDVQQHDAZTeWRuZXkxDzANBgNVBAoMBk5ld21hbjEN\nMAsGA1UECwwEVGVzdDEUMBIGA1UEAwwLdGVzdC5uZXdtYW4wHhcNMTkxMTIxMDUw\nNzI2WhcNMjkxMTE4MDUwNzI2WjBRMQswCQYDVQQGEwJBVTEMMAoGA1UECAwDTlNX\nMQ8wDQYDVQQKDAZOZXdtYW4xDTALBgNVBAsMBFRlc3QxFDASBgNVBAMMC3Rlc3Qu\nbmV3bWFuMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAr4gQ2xdoRvKg\nRzd49uh3WPud/I+npx8QpjkWJVsLVQuWVOCKTMaspVqWLwPZFt05+wCAUWompX6O\nI7vqd9nyZkd1odKsHQs1HY3JDlnN3FsLx305+I4QKrPs4NsoqT0U5MQ58bZYALS9\nVOs0ISndq3hMhv7SZKU8bITdeMbJodmEEYerXWvs5qmJ5y7q5nYNHuHzGmKIxjAs\niFzNSL5jv6nNfK41WMgrhlJIsO/jqfYG5S32JJKQY163A4hUJT6CKJ39QanQZc2d\n7V+XxiRIquvHwkSRYolEjVHwRvFGQvJRd2D2iVhxaHKC1HQwHefA1DM2TYY+wCP1\nJYlPQeta2wIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQC/WLksgoIOrfM7sChruXLL\nO3rBoBoXGtqzeyqr1LtI35tlOKjqALFg0iyyjIrODXOVOqfx13WlyCzMzHxLd8c9\nYOBaqw78Igw4VmrAh8EYj66RI+zW2g13k0QiLHrVlF2KHsYTBE4fpv9GDNTd260Z\nVhcO0T6wht/EPHEnU04evLs6kUTB4NRw00B69diwmatsY8vdgWGPj920ILHOyFmo\neqNfY70pK679KXLMd2uev5hJkk+l57NhYZXoD2evprv/9w5JZrTRBxtc5gUYLvTw\nAVX2Qtq6peJAAb0TD8IN3Ib3i0IuIQJrx4pg5q6ais6JBVsvonLmLbYW2z3KBVFE\n-----END CERTIFICATE-----\n"
  },
  {
    "path": "test/fixtures/ssl/client2.csr",
    "content": "-----BEGIN CERTIFICATE REQUEST-----\nMIICpzCCAY8CAQAwYjELMAkGA1UEBhMCQVUxDDAKBgNVBAgMA05TVzEPMA0GA1UE\nBwwGU3lkbmV5MQ8wDQYDVQQKDAZOZXdtYW4xDTALBgNVBAsMBFRlc3QxFDASBgNV\nBAMMC3Rlc3QubmV3bWFuMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA\nr4gQ2xdoRvKgRzd49uh3WPud/I+npx8QpjkWJVsLVQuWVOCKTMaspVqWLwPZFt05\n+wCAUWompX6OI7vqd9nyZkd1odKsHQs1HY3JDlnN3FsLx305+I4QKrPs4NsoqT0U\n5MQ58bZYALS9VOs0ISndq3hMhv7SZKU8bITdeMbJodmEEYerXWvs5qmJ5y7q5nYN\nHuHzGmKIxjAsiFzNSL5jv6nNfK41WMgrhlJIsO/jqfYG5S32JJKQY163A4hUJT6C\nKJ39QanQZc2d7V+XxiRIquvHwkSRYolEjVHwRvFGQvJRd2D2iVhxaHKC1HQwHefA\n1DM2TYY+wCP1JYlPQeta2wIDAQABoAAwDQYJKoZIhvcNAQELBQADggEBAD0k7TMy\nycno+mUDwpn6MhNTF0BjtOfZWQA0esLY7VCooBXUsUPLj6Vt4l4zhoYrDPeHnEet\nLcxMU/MKSmNJJ/M+dEqBJfgw9Z0I7OXa4xNWbJMmkPl6lf1Jiz1aUHzYSD0wXp7r\nQ3VYT5uvhBJnmeqOB4syYRRQzOdm7Fr/Vn0btIf+f6bsfCx2OMePPBzSXRorpSFH\nzZj/UoUDlexDtNKhmnpYBvF/z4Uy+5PKq1pM0cQvZg3EmRwEmtQ+LepfK6DpXveE\n/qev24BOxsUsXmwmDDr39HdOcHp7+mwuyQGSMKc21sod7dfBENg6YAlXN4sq7j+T\nRI3x8JX4Qg4AsKM=\n-----END CERTIFICATE REQUEST-----\n"
  },
  {
    "path": "test/fixtures/ssl/client2.key",
    "content": "-----BEGIN RSA PRIVATE KEY-----\nProc-Type: 4,ENCRYPTED\nDEK-Info: AES-256-CBC,0489A6417791B6C643DD22025AE8F938\n\nuE8ef9A/izPkEWrntX1ZdT5ouYcRlFaaHNU62tJw/K60kibtcDPp4oCKgkmU2KmG\nx6EQMqKnUlArZ+xT54GoC/vJTXd5VQsIs7b9xhCm9NB/tIyXOTNOLF87RH9bY5qi\nnc+nntHk1eoYQ+xBbg8tnZvjwlEs0wcgaMc783uLFwPE5YgMJGQaiE2WNnehGqPv\ns5Y9QAljhF+3KRX1a9bLYbLYdu+haq5TVwz3NW3GpUawzDP7ArvO2aT/w8Kzw/3n\nqqtHvQeaJKfUXqhbOlJeHM9AmzGHXWZWQlUxcUXWbrBtMH1KDWa9STDUuSLS1y7k\n+gdOrUYw7BFJKy2sckzPHJ8RPLObtmFUijh64cBD51uEgBzRkex6pUU4W2DMoNA3\ngZl0Bz4REx15aqsb9oGHqyc1xC0Xg7uqypJfsFIWrIO2hk5ZjwGfuqIQvy/309pt\np1Zko5GobUKQPmY63x3zE45uAeTMV5oEcmUZkMMLWn3frkRCP8rbNBDqy/x97ZkB\nsD8SQbZSvWIuccF7/kWBPRwKQjN7vmZDAKvsmujQrdko1ODFmOOwEwwo9nvLdOU4\nFrHougwEtAsfCnoZRPVMzMCsh/FB8RMq0cIVk61CeQKczcl1rNpKCw4CR4Lek6rs\nst5P20to6YgbBL+Fzt1sFN0vYRm4nAlDK4OZCvz2CLtDt2rptNtWTskDbkqOx7Y4\nolruEYFTGnmhmbWFr3ldXZJDSqqlSInvhgfIGEGqF71sPe8s41+58lkQ0A6sWsrV\nJSWiA2b7TZYztUc8oUfjM+ZftL1gQHnJN+EOkBz1QgRdSiUARxFPjymxES6iG699\nT35MMWWF9MEtLuymnIbyTTN8X1FOQ2RgtCEasxMBEJ3lXTTcU9xuaFSSssjiePpu\nw61VeQNas9sOD+mAXbAXx9scU1DYmXC77/ZV5ABi4Ls8ziCFwa4lLG6yfvH1bc6y\nFpLLBPt03Dm0ZrkqAlmI1nPDq8UH/my4pPf8dstBhCRJ/6ubQwb2rkI/zvwdFJq3\nrSXfVUDkvYj7esN3D67u12qVBxee/aLBah3RFr0AMtbYb2WKYy72/PSYMIdKATWN\nqxEt6WdHuoo7TxQow9yb2u7VBiqWsuirI5hVyk9S9k85qOkEempRU0BOseL/0ITk\nXywJxrhfg++rtStZQFMYi66MmVzVaYsV916obGOZjgwV8fYtfr3TxJGpEDNMlHtU\nZTZ0J+juQC/GxN0Hhp5XQeRbMRRWKxhqWfkdJThORid62qKTaz1+r4WZ97QW4OxX\nMHecrxb9T8bPbxTZbjX/1VBiBr0vc/A28rxzDsRqDDf89+v44GNnBdtmRXfA1Mlk\noZrBjGchOh/J8Q6+trADZEkyqt381doqXcvYasnPH3vt0qRG/s4VKE2nuEmzm1n8\nibqTrb+LgboBFrDFdAWKeCQy1mQSn6EWzp7JQ4eXkerD3kLqo2hT7mBkSy2Gj+ok\nAwb3tC4cGzOZ6KmZhoBkiybBvs0sdKR2NzvzNnn15bqV8ZLky5nMLvh9F49CuLBQ\nZNHiVjgG5WTWcVveBIbkcOPp3c9vZd6+R5GQh7QutERbf7VqMKDGxOuZVIBFhQff\n-----END RSA PRIVATE KEY-----\n"
  },
  {
    "path": "test/fixtures/ssl/client3.crt",
    "content": "-----BEGIN CERTIFICATE-----\nMIIEmzCCA4OgAwIBAgIBATANBgkqhkiG9w0BAQsFADCBijELMAkGA1UEBhMCVVMx\nCzAJBgNVBAgMAkNBMQswCQYDVQQHDAJTRjEQMA4GA1UECgwHUG9zdG1hbjEaMBgG\nA1UECwwRcG9zdG1hbkBsb2NhbGhvc3QxEzARBgNVBAMMClRlc3RDbGllbnQxHjAc\nBgkqhkiG9w0BCQEWD2RvLm5vdEBlbWFpbC5tZTAeFw0yMDA1MTIxOTUwMTVaFw00\nNzA5MjcxOTUwMTVaMIGKMQswCQYDVQQGEwJVUzELMAkGA1UECAwCQ0ExCzAJBgNV\nBAcMAlNGMRAwDgYDVQQKDAdQb3N0bWFuMRowGAYDVQQLDBFwb3N0bWFuQGxvY2Fs\naG9zdDETMBEGA1UEAwwKVGVzdENsaWVudDEeMBwGCSqGSIb3DQEJARYPZG8ubm90\nQGVtYWlsLm1lMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAs3IzJMnb\nQjjSJCjE/Euuxq7RBZ316+M7v36VnmgYkAXwM86Ckl8MSZYSSRE9ekxzsxQxNhs9\nPa93xFJPW/17CG4SRDkagCapFRa3fnf6cw4DsvW12/Dcnwz7tpSBb9KA1IU8c/QB\nDjxY+H7BLQfmGfk4CiuybyXoEsoYMydFU1Z6MvNKIWfFoPO2tnxLuyTiFIzAd2Lp\n77mIuLEjfg2pmcnFpemd55zrgqi+OLeJjxQqCoiSog9/45HzDFEe8S5a+/laBjsd\nG3ulPvGbuQbvL+LDttEIlneHsKnlT/z6f7YE+fTKpc+ryCGngFVil4lAbkjgDNDO\nkLEshioJcmMWCwIDAQABo4IBCDCCAQQwCQYDVR0TBAIwADAsBglghkgBhvhCAQ0E\nHxYdT3BlblNTTCBHZW5lcmF0ZWQgQ2VydGlmaWNhdGUwHQYDVR0OBBYEFN15KN+K\ndHIry3FADNXXUf3/yIYSMIGpBgNVHSMEgaEwgZ6hgZCkgY0wgYoxCzAJBgNVBAYT\nAlVTMQswCQYDVQQIDAJDQTELMAkGA1UEBwwCU0YxEDAOBgNVBAoMB1Bvc3RtYW4x\nGjAYBgNVBAsMEXBvc3RtYW5AbG9jYWxob3N0MRMwEQYDVQQDDApUZXN0Q2xpZW50\nMR4wHAYJKoZIhvcNAQkBFg9kby5ub3RAZW1haWwubWWCCQDVmzvauKidhzANBgkq\nhkiG9w0BAQsFAAOCAQEAg8i445PKv94inwykzazREyGO2vC3k+Sgu6QHfI5kUZmC\nwBRogAnrWLmAhY06O7y2XZm0/07wD/e2h5skitGX4wxbwKktiejfbMeEulJXIwG7\n3sYdQ5/aQBTvdCApzh4DobbBFxudokZSR7qPk6P3CgVQgG40a1pgBVSuntgixWRm\nGm4ggjc02ZgcHcu4FVHUFOh0TRvFmbCtOI/x8mOB5pZ+G5c+t3Au7WbVxnyYUysD\nRaO6faj/ve0c6COI/KOw4xGlAwkl5W5wIzdzCyYrD35tz3/nqt3/MkxNoM/8vf5B\nDvHBT6tlqvMCSdCcyldhkOhy/rYV2HVVp+fGgaIo3A==\n-----END CERTIFICATE-----\n"
  },
  {
    "path": "test/fixtures/ssl/client3.csr",
    "content": "-----BEGIN CERTIFICATE REQUEST-----\nMIIC8zCCAdsCAQAwgYoxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTELMAkGA1UE\nBwwCU0YxEDAOBgNVBAoMB1Bvc3RtYW4xGjAYBgNVBAsMEXBvc3RtYW5AbG9jYWxo\nb3N0MRMwEQYDVQQDDApUZXN0Q2xpZW50MR4wHAYJKoZIhvcNAQkBFg9kby5ub3RA\nZW1haWwubWUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCzcjMkydtC\nONIkKMT8S67GrtEFnfXr4zu/fpWeaBiQBfAzzoKSXwxJlhJJET16THOzFDE2Gz09\nr3fEUk9b/XsIbhJEORqAJqkVFrd+d/pzDgOy9bXb8NyfDPu2lIFv0oDUhTxz9AEO\nPFj4fsEtB+YZ+TgKK7JvJegSyhgzJ0VTVnoy80ohZ8Wg87a2fEu7JOIUjMB3Yunv\nuYi4sSN+DamZycWl6Z3nnOuCqL44t4mPFCoKiJKiD3/jkfMMUR7xLlr7+VoGOx0b\ne6U+8Zu5Bu8v4sO20QiWd4ewqeVP/Pp/tgT59Mqlz6vIIaeAVWKXiUBuSOAM0M6Q\nsSyGKglyYxYLAgMBAAGgIzAhBgkqhkiG9w0BCQcxFAwScGFzc3dvcmQgY2hhbGxl\nbmdlMA0GCSqGSIb3DQEBCwUAA4IBAQASL8p0lXvb9moVT5Tk0iiiIib1Z6rL94Vk\nWaP6T6b8E6pubdjPs6sz0rCjuJrYNhKZo6OAGnZSOxy62xivsn82T9ahbg0HQMah\nCFqImRW0mZMEQtskp5CKDzZhIaMwWXC026XvOE8ubvr+HLebL5ZzKxIzoLc3fHgh\nWqBJjDHbdRLuclcXlH4h17MNihP7ws6WkK7IN5wXExZ5L0NV/v0/z1pXpFSCT9oq\nxr8FkGNcTjgly8bfLv2kfz8oPxe5Q27QpNVxa1ytnq9FBHZ+OXJKWPVBa1OEXF0M\ny0gGD5P+bbu8OZsdymktiAMHVBFQ7Zx6KtL+GG1oFTTXHQKiuq/f\n-----END CERTIFICATE REQUEST-----\n"
  },
  {
    "path": "test/fixtures/ssl/client3.key",
    "content": "-----BEGIN RSA PRIVATE KEY-----\nMIIEpAIBAAKCAQEAs3IzJMnbQjjSJCjE/Euuxq7RBZ316+M7v36VnmgYkAXwM86C\nkl8MSZYSSRE9ekxzsxQxNhs9Pa93xFJPW/17CG4SRDkagCapFRa3fnf6cw4DsvW1\n2/Dcnwz7tpSBb9KA1IU8c/QBDjxY+H7BLQfmGfk4CiuybyXoEsoYMydFU1Z6MvNK\nIWfFoPO2tnxLuyTiFIzAd2Lp77mIuLEjfg2pmcnFpemd55zrgqi+OLeJjxQqCoiS\nog9/45HzDFEe8S5a+/laBjsdG3ulPvGbuQbvL+LDttEIlneHsKnlT/z6f7YE+fTK\npc+ryCGngFVil4lAbkjgDNDOkLEshioJcmMWCwIDAQABAoIBACWzY41iH3+9QmE4\nc5JyMCksB1w/wLArkJz98l9SjX6M0NeBlqs77u/y6KqTRbBRKanBH0m31VkFaYtE\no8m26sdtoMbWnHu6I6H7oNegS20qz5okx22LID8GUkgc0Uj2F/0OdRIDfMlJ4oNq\n1hko5K4mTyDL53Q0qZpw/T6aDJWiZoBH7Tk6kTVEC75581dtX9XYz3T3ijPp6VA7\nbyJ1YsN8KY/EVWR+NcLwcAGQJem1CEyViTlpbLMgyONEv/6NmyGYQgmtd6krYAxC\nIQQLKNDprNQubWuaxy6aEIWB2s891wQbGXmurDqMEYo0Q8OxARulXp8bE68OfXGK\nz72I+bkCgYEA1suFS7x49+wLN+PFuyKsopGLqyyl/A8DAPrfbIDcfoGaYTL7Z8BT\nP8teYg9MsDvH7JEuhayy0Sw/b8U5XidhupIM35VfenCu/Sylfd+V42/AQRPqOoSi\norahQnGxnauYTKamNHA/RIXjxsjTYjpahZuXfPv1QtTt39ZTuwHzqGUCgYEA1d62\nDIDJy95+r3OLOqdxJBCqwKm+5Zh/Zjdv955Xk4fopad0zLM45UaKumz6yHu4Cg3o\nqJje9T7oiQpW2eHr1Kepg9TNQdNeGf6WBENN0NRfdhbNaj74cn7kHkZP97iIBu97\nU/yhkN1ac+1WMraZHqcQ6QQSUr63QsuJAx1VBa8CgYEAwCoEbuWHNAaxYqccV3eG\nC0s7MUEYnpCvl0jaajA/E87PVvZNhVzDHefL4N7fNSvGiRa6EE2ZDRoRBuXjlSCW\nhlvzuHPin6AAbfBrfllxt7Bax94RR5kyB3BshQ1CYlUKREkzmOZzM9K1HTq+Irsi\nETZKKT8hBVGKHx+YeU4dtyECgYEAsoFMmWr1A0AVpQNfdflDqcJvgpcrSh7aVsp2\nncp/dhe9ymXWSvRbzKHwMGG9f5Ajr+CkC/RsQ23aUGdczkaOu9Ok3O/E0ehFZpTj\nSXOTg3V+p+WoVcFxRL88TziIjk5q2r8PxK3bfDoEwTWa+IEHlFoE9zf6wy2DcDDJ\njtvwlukCgYBI/TOWJiajfg5oPAnovYx/Wxb50mzeY/QCqF5Iw8GYviAXYsyZ7WKy\nf65L5/sKPHPcz/pxz/Q+lE+/5LKa3KQ3F9LXYP6+0/rzmlQNR2qTa+7uo4QLM1un\nu7acuHEkBOJkhJO5fQFHxiaqjRCNxs+semha3ejmlyzReoyNbPi2xQ==\n-----END RSA PRIVATE KEY-----\n"
  },
  {
    "path": "test/fixtures/ssl/config.cnf",
    "content": "[ req ]\ndefault_bits           = 1024\ndays                   = 3650\ndistinguished_name     = req_distinguished_name\nattributes             = req_attributes\nprompt                 = no\noutput_password        = password\n\n[ req_distinguished_name ]\nC                      = US\nST                     = CA\nL                      = SF\nO                      = Postman\nOU                     = postman@localhost\nCN                     = TestClient\nemailAddress           = do.not@email.me\n\n[ req_attributes ]\nchallengePassword              = password challenge\n\n"
  },
  {
    "path": "test/fixtures/ssl/generate-certificates.sh",
    "content": "#!/usr/bin/env sh\n\n# generate/refresh certificates for server, ca and client\n\nSERVER='server3'\nCA='ca3'\nCLIENT='client3'\n\n# generate a private key for the server\nif [[ ! -f \"$SERVER.key\" ]]; then\n    openssl genrsa -out $SERVER.key 2048\nfi\n\n# generate a CSR with the private key for the server\nopenssl req -new -key $SERVER.key \\\n    -config config.cnf \\\n    -days 9999 \\\n    -out $SERVER.csr\n\n# generate a private key for the Certificate Authority\nif [[ ! -f \"$CA.key\" ]]; then\n    openssl genrsa -out $CA.key 2048\nfi\n\n# generate a certificate for the the CA\nopenssl req -new -x509 -key $CA.key \\\n    -config config.cnf \\\n    -days 9999 \\\n    -out $CA.crt\n\n# generate the server certificate signed by the CA\nopenssl x509 -req -in $SERVER.csr \\\n    -CA $CA.crt \\\n    -CAkey $CA.key \\\n    -out $SERVER.crt \\\n    -set_serial 1 \\\n    -outform pem \\\n    -extfile v3.ext \\\n    -days 9999 \\\n    -sha256\n\n# verify that the certificate was generated correctly\nopenssl verify -CAfile $CA.crt $SERVER.crt\n\n# generate a private key for the client\nif [[ ! -f \"$CLIENT.key\" ]]; then\n    openssl genrsa -out $CLIENT.key 2048\nfi\n\n# generate a CSR with the private key for the client\nopenssl req -new -key $CLIENT.key \\\n    -config config.cnf \\\n    -days 9999 \\\n    -out $CLIENT.csr\n\n# generate the client certificate sign by the CA\nopenssl x509 -req -in $CLIENT.csr \\\n    -CA $CA.crt \\\n    -CAkey $CA.key \\\n    -out $CLIENT.crt \\\n    -set_serial 1 \\\n    -outform pem \\\n    -extfile v3.ext \\\n    -days 9999 \\\n    -sha256\n\n# verify that the certificate was generated correctly\nopenssl verify -CAfile $CA.crt $CLIENT.crt\n"
  },
  {
    "path": "test/fixtures/ssl/server.crt",
    "content": "Certificate:\n    Data:\n        Version: 3 (0x2)\n        Serial Number: 1 (0x1)\n    Signature Algorithm: sha256WithRSAEncryption\n        Issuer: C=IN, ST=Karnataka, L=Bengaluru, O=Postdot Technologies Pvt Ltd, OU=Postmanlabs, CN=Newman/emailAddress=help@getpostman.com\n        Validity\n            Not Before: Jan 15 10:12:30 2020 GMT\n            Not After : Jun  2 10:12:30 2047 GMT\n        Subject: C=IN, ST=Karnataka, L=Bengaluru, O=Postdot Technologies Pvt Ltd, OU=Postmanlabs, CN=localhost/emailAddress=help@getpostman.com\n        Subject Public Key Info:\n            Public Key Algorithm: rsaEncryption\n                Public-Key: (4096 bit)\n                Modulus:\n                    00:fe:31:3b:6a:f8:a1:41:79:85:d4:0d:ea:db:7e:\n                    d5:ce:37:52:75:af:2c:22:76:74:ed:c8:bc:eb:6b:\n                    e6:2a:cf:74:cf:78:76:6e:e6:11:7c:99:74:45:43:\n                    a0:8a:7d:7c:6d:bc:43:e2:7f:84:a0:a3:88:87:45:\n                    14:3d:13:1c:85:0e:ea:c4:67:31:fe:e9:07:a4:b8:\n                    ad:40:fc:7c:a3:47:c2:08:7d:93:6f:e1:b7:68:a3:\n                    0f:f5:d5:b1:fe:9e:54:47:8f:bb:72:95:fe:05:33:\n                    96:af:83:60:37:b5:72:95:26:bc:dc:c8:0b:56:ac:\n                    96:2f:88:dc:72:76:81:fa:46:79:98:75:26:c6:a1:\n                    01:5a:2a:06:27:da:f7:ee:c3:2e:64:08:05:24:db:\n                    ab:26:5b:ae:74:ee:37:4b:20:2e:6c:82:5a:10:69:\n                    82:ce:39:7f:a7:6b:b3:86:19:d0:8b:92:05:d9:8e:\n                    30:ff:c1:aa:59:b6:40:10:b4:62:6c:78:38:af:aa:\n                    ac:68:bb:45:6d:2b:17:5d:f2:ea:07:4b:b3:54:40:\n                    0e:ee:53:21:65:53:44:c2:3a:2a:25:0b:0d:8a:86:\n                    a7:39:c5:9f:1a:e4:8f:ff:e3:77:2d:62:5b:98:64:\n                    43:cb:43:47:3f:52:3b:a8:12:f8:26:22:6e:f5:96:\n                    5f:4b:a9:9c:50:35:1d:0a:9f:19:70:11:4d:cf:b5:\n                    f6:55:14:e6:66:15:63:f0:8c:49:2b:30:ed:5b:b5:\n                    cd:02:9f:38:6d:48:63:1f:3d:30:91:2f:7f:6d:9e:\n                    b3:57:bd:f5:b2:52:d2:42:f6:33:c7:6e:a4:57:24:\n                    1c:6e:b5:d6:a6:29:fc:33:e1:f3:88:50:1f:65:d8:\n                    a8:f9:7b:68:36:c3:33:69:04:ad:ac:18:83:c6:03:\n                    31:49:fb:dd:54:2d:c3:79:17:73:e2:e3:03:5e:50:\n                    6b:79:c8:6d:09:79:8c:ed:7d:1f:7a:bf:74:f9:0c:\n                    ab:11:b6:2b:af:d2:fe:f4:68:79:76:7d:97:88:84:\n                    0f:b9:f7:8a:ff:60:1f:f0:15:90:85:dc:ea:23:3d:\n                    73:c4:32:7c:5a:f9:cb:24:35:0b:d9:0c:0d:04:0b:\n                    dc:93:37:41:0e:76:ff:b9:e2:e5:eb:df:18:27:8f:\n                    93:02:8c:f3:39:2b:6d:03:e0:83:7f:f7:52:81:4a:\n                    bc:f8:37:9b:7c:9c:a1:ed:f1:ee:dd:8f:9b:7c:9b:\n                    18:ce:4f:b4:73:95:e7:f4:c9:d6:51:30:8b:01:f9:\n                    7f:36:93:26:6d:90:5c:0f:ed:a8:8f:b4:fd:2e:c0:\n                    13:fc:d3:75:cb:a0:53:04:8c:73:fe:06:e4:41:49:\n                    4e:bc:5b\n                Exponent: 65537 (0x10001)\n        X509v3 extensions:\n            X509v3 Basic Constraints: \n                CA:FALSE\n            Netscape Comment: \n                OpenSSL Generated Certificate\n            X509v3 Subject Key Identifier: \n                24:85:1D:DB:2D:16:70:30:8D:08:11:EE:BB:C1:97:95:70:E4:1B:CC\n            X509v3 Authority Key Identifier: \n                keyid:B8:96:54:84:D3:41:59:31:D0:82:62:42:76:B3:B5:63:28:A0:8D:2A\n\n    Signature Algorithm: sha256WithRSAEncryption\n         95:27:6d:09:f0:78:d2:cf:bf:05:c2:9a:f7:b5:80:ff:2c:ab:\n         36:60:82:58:92:30:79:81:05:87:75:f9:c4:7f:77:c2:79:dc:\n         16:3d:2b:00:6e:45:e7:a2:bb:c9:97:47:f0:b4:31:7d:c0:bb:\n         17:f0:d8:3b:01:cc:69:ca:38:ae:88:4b:60:e3:1e:0e:22:90:\n         0f:3d:da:79:f9:2b:7e:04:c0:00:00:69:7d:6b:6a:1d:4a:58:\n         e6:a9:85:a3:2e:19:69:00:fe:98:24:f4:46:11:9a:5b:f5:5e:\n         6a:f0:14:8d:71:10:7c:0e:9b:f3:36:57:c6:c9:57:c2:ff:a0:\n         56:e8:29:22:59:22:10:45:5f:3e:f2:29:31:b5:2b:ca:93:32:\n         f0:2f:ad:48:80:3b:5a:07:7c:d9:74:e2:d8:0f:2f:48:4f:12:\n         02:95:ab:f5:59:67:d3:64:7a:3e:35:5d:a6:55:48:c0:29:94:\n         08:0e:f3:5e:2b:61:99:dd:4e:e7:49:43:9b:29:3d:ee:ae:3d:\n         f5:d7:11:42:b3:27:7d:dd:db:2b:72:8d:7c:96:10:03:57:1e:\n         6c:cc:ef:0a:58:88:28:b1:a5:23:dd:84:37:37:03:af:29:95:\n         de:2b:e2:75:fb:1f:cd:ca:c1:f9:1a:31:02:60:af:7b:14:a9:\n         57:4a:15:a1:e2:00:8c:60:ff:f8:50:47:7a:e6:f2:a5:c7:e7:\n         35:4a:ac:0a:f8:2f:fd:a7:50:69:5d:ad:6f:39:3b:f3:8f:12:\n         0d:93:97:a3:d3:24:df:42:b4:bf:e2:59:15:53:52:34:18:81:\n         2b:c9:82:7f:47:20:48:04:62:24:5e:b8:47:0b:e5:98:e4:c2:\n         6b:73:e1:7f:7a:ec:59:ff:ff:87:49:35:33:24:12:50:4a:89:\n         4f:5e:02:af:89:31:88:b8:2e:2d:de:f0:82:00:6e:15:62:7a:\n         2e:a8:e2:b2:1e:ed:0c:52:f1:52:cf:2d:d8:bb:16:9f:87:3a:\n         07:3b:90:d4:96:cf:07:33:32:7b:25:e8:a3:6e:38:fd:b7:96:\n         a3:6a:e5:44:6f:82:88:78:e8:fa:ed:81:ff:11:36:e6:94:cf:\n         f9:a1:c7:29:fb:24:1e:dc:35:37:32:82:b9:24:1c:b1:05:7f:\n         a5:60:b8:db:21:b2:09:42:0a:95:8d:e0:13:ea:21:ed:d2:1b:\n         b4:94:71:f1:ee:2d:e8:a5:f1:e5:59:73:a4:f3:ce:cf:ae:9e:\n         44:79:c5:6e:bd:74:27:43:ff:01:9c:0b:a1:16:80:03:51:a1:\n         72:c8:d0:0b:bf:5e:6c:89:b5:c1:47:83:18:13:9d:5e:0e:2a:\n         ab:1f:8f:36:fb:a7:9f:e1\n-----BEGIN CERTIFICATE-----\nMIIGSTCCBDGgAwIBAgIBATANBgkqhkiG9w0BAQsFADCBpzELMAkGA1UEBhMCSU4x\nEjAQBgNVBAgMCUthcm5hdGFrYTESMBAGA1UEBwwJQmVuZ2FsdXJ1MSUwIwYDVQQK\nDBxQb3N0ZG90IFRlY2hub2xvZ2llcyBQdnQgTHRkMRQwEgYDVQQLDAtQb3N0bWFu\nbGFiczEPMA0GA1UEAwwGTmV3bWFuMSIwIAYJKoZIhvcNAQkBFhNoZWxwQGdldHBv\nc3RtYW4uY29tMB4XDTIwMDExNTEwMTIzMFoXDTQ3MDYwMjEwMTIzMFowgaoxCzAJ\nBgNVBAYTAklOMRIwEAYDVQQIDAlLYXJuYXRha2ExEjAQBgNVBAcMCUJlbmdhbHVy\ndTElMCMGA1UECgwcUG9zdGRvdCBUZWNobm9sb2dpZXMgUHZ0IEx0ZDEUMBIGA1UE\nCwwLUG9zdG1hbmxhYnMxEjAQBgNVBAMMCWxvY2FsaG9zdDEiMCAGCSqGSIb3DQEJ\nARYTaGVscEBnZXRwb3N0bWFuLmNvbTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCC\nAgoCggIBAP4xO2r4oUF5hdQN6tt+1c43UnWvLCJ2dO3IvOtr5irPdM94dm7mEXyZ\ndEVDoIp9fG28Q+J/hKCjiIdFFD0THIUO6sRnMf7pB6S4rUD8fKNHwgh9k2/ht2ij\nD/XVsf6eVEePu3KV/gUzlq+DYDe1cpUmvNzIC1asli+I3HJ2gfpGeZh1JsahAVoq\nBifa9+7DLmQIBSTbqyZbrnTuN0sgLmyCWhBpgs45f6drs4YZ0IuSBdmOMP/Bqlm2\nQBC0Ymx4OK+qrGi7RW0rF13y6gdLs1RADu5TIWVTRMI6KiULDYqGpznFnxrkj//j\ndy1iW5hkQ8tDRz9SO6gS+CYibvWWX0upnFA1HQqfGXARTc+19lUU5mYVY/CMSSsw\n7Vu1zQKfOG1IYx89MJEvf22es1e99bJS0kL2M8dupFckHG611qYp/DPh84hQH2XY\nqPl7aDbDM2kErawYg8YDMUn73VQtw3kXc+LjA15Qa3nIbQl5jO19H3q/dPkMqxG2\nK6/S/vRoeXZ9l4iED7n3iv9gH/AVkIXc6iM9c8QyfFr5yyQ1C9kMDQQL3JM3QQ52\n/7ni5evfGCePkwKM8zkrbQPgg3/3UoFKvPg3m3ycoe3x7t2Pm3ybGM5PtHOV5/TJ\n1lEwiwH5fzaTJm2QXA/tqI+0/S7AE/zTdcugUwSMc/4G5EFJTrxbAgMBAAGjezB5\nMAkGA1UdEwQCMAAwLAYJYIZIAYb4QgENBB8WHU9wZW5TU0wgR2VuZXJhdGVkIENl\ncnRpZmljYXRlMB0GA1UdDgQWBBQkhR3bLRZwMI0IEe67wZeVcOQbzDAfBgNVHSME\nGDAWgBS4llSE00FZMdCCYkJ2s7VjKKCNKjANBgkqhkiG9w0BAQsFAAOCAgEAlSdt\nCfB40s+/BcKa97WA/yyrNmCCWJIweYEFh3X5xH93wnncFj0rAG5F56K7yZdH8LQx\nfcC7F/DYOwHMaco4rohLYOMeDiKQDz3aefkrfgTAAABpfWtqHUpY5qmFoy4ZaQD+\nmCT0RhGaW/VeavAUjXEQfA6b8zZXxslXwv+gVugpIlkiEEVfPvIpMbUrypMy8C+t\nSIA7Wgd82XTi2A8vSE8SApWr9Vln02R6PjVdplVIwCmUCA7zXithmd1O50lDmyk9\n7q499dcRQrMnfd3bK3KNfJYQA1cebMzvCliIKLGlI92ENzcDrymV3ividfsfzcrB\n+RoxAmCvexSpV0oVoeIAjGD/+FBHeubypcfnNUqsCvgv/adQaV2tbzk7848SDZOX\no9Mk30K0v+JZFVNSNBiBK8mCf0cgSARiJF64RwvlmOTCa3Phf3rsWf//h0k1MyQS\nUEqJT14Cr4kxiLguLd7wggBuFWJ6Lqjish7tDFLxUs8t2LsWn4c6BzuQ1JbPBzMy\neyXoo244/beWo2rlRG+CiHjo+u2B/xE25pTP+aHHKfskHtw1NzKCuSQcsQV/pWC4\n2yGyCUIKlY3gE+oh7dIbtJRx8e4t6KXx5VlzpPPOz66eRHnFbr10J0P/AZwLoRaA\nA1GhcsjQC79ebIm1wUeDGBOdXg4qqx+PNvunn+E=\n-----END CERTIFICATE-----\n"
  },
  {
    "path": "test/fixtures/ssl/server.csr",
    "content": "-----BEGIN CERTIFICATE REQUEST-----\nMIIE8DCCAtgCAQAwgaoxCzAJBgNVBAYTAklOMRIwEAYDVQQIDAlLYXJuYXRha2Ex\nEjAQBgNVBAcMCUJlbmdhbHVydTElMCMGA1UECgwcUG9zdGRvdCBUZWNobm9sb2dp\nZXMgUHZ0IEx0ZDEUMBIGA1UECwwLUG9zdG1hbmxhYnMxEjAQBgNVBAMMCWxvY2Fs\naG9zdDEiMCAGCSqGSIb3DQEJARYTaGVscEBnZXRwb3N0bWFuLmNvbTCCAiIwDQYJ\nKoZIhvcNAQEBBQADggIPADCCAgoCggIBAP4xO2r4oUF5hdQN6tt+1c43UnWvLCJ2\ndO3IvOtr5irPdM94dm7mEXyZdEVDoIp9fG28Q+J/hKCjiIdFFD0THIUO6sRnMf7p\nB6S4rUD8fKNHwgh9k2/ht2ijD/XVsf6eVEePu3KV/gUzlq+DYDe1cpUmvNzIC1as\nli+I3HJ2gfpGeZh1JsahAVoqBifa9+7DLmQIBSTbqyZbrnTuN0sgLmyCWhBpgs45\nf6drs4YZ0IuSBdmOMP/Bqlm2QBC0Ymx4OK+qrGi7RW0rF13y6gdLs1RADu5TIWVT\nRMI6KiULDYqGpznFnxrkj//jdy1iW5hkQ8tDRz9SO6gS+CYibvWWX0upnFA1HQqf\nGXARTc+19lUU5mYVY/CMSSsw7Vu1zQKfOG1IYx89MJEvf22es1e99bJS0kL2M8du\npFckHG611qYp/DPh84hQH2XYqPl7aDbDM2kErawYg8YDMUn73VQtw3kXc+LjA15Q\na3nIbQl5jO19H3q/dPkMqxG2K6/S/vRoeXZ9l4iED7n3iv9gH/AVkIXc6iM9c8Qy\nfFr5yyQ1C9kMDQQL3JM3QQ52/7ni5evfGCePkwKM8zkrbQPgg3/3UoFKvPg3m3yc\noe3x7t2Pm3ybGM5PtHOV5/TJ1lEwiwH5fzaTJm2QXA/tqI+0/S7AE/zTdcugUwSM\nc/4G5EFJTrxbAgMBAAGgADANBgkqhkiG9w0BAQsFAAOCAgEAKRePTLfuwfQ6eYM2\nGpyuXt7hqjQUbtSd+ouIK6sdYxgXMt4Q5G8Z7cSw5jah6tIhjMX8OoQUp5+5wcw4\nO4nZX/eC8T6E2LyFIgV2/erBDyMRsLq5YcrI5xNVMULDrEMsXRC3sVL41dmIJC98\nL/q2fSbDj4hfRVEaz3dZBiUFr8YMTyy+5jK3agoXVDAc1FVEYosrqGB9FjvXNl6h\nq0OGZcWqkkcUFMzcWNYC90AHCU+QedoZ+klSQsg4wdwStRnNFQu7FUnZ9gcngroe\nMos7u5f5fAiW21p310Y/QyNpa6vD+D0R0f1TB8zBZjEHIZs1fooQm9k1YOFD89Z7\n8C+hgzDFm+ZO9SKx3tbvyHhxTEYysuEhSK62gPaECEBrwJu0HfydscXP1IrK5hB5\nIelEY8LmJ53+ck7J14+2LepG3QZczgo6MLjSij4vXomomdkGKzkhdeHb9+dc8ATd\n5xgGvKQJJDDLT9TzzebzH9d+mzdyyFVXS0/F9QgGP5AGSH2ziXwSZcXi8v5Qhxcd\n8aRMnFFRYbQiMk8KjwoWgMOAfYJnDCcXphU7Gc/x2V03HVFomatCHAZHSFxn07Jc\n7hqrC8tWelKV/1jP0y6anbAdfHP4vBZr+RWI9iQcUxkqChyXUAfHKZWsfVvVKTcJ\n/WX9pntSlRddrct7walGvZb0FO0=\n-----END CERTIFICATE REQUEST-----\n"
  },
  {
    "path": "test/fixtures/ssl/server.key",
    "content": "-----BEGIN RSA PRIVATE KEY-----\nProc-Type: 4,ENCRYPTED\nDEK-Info: DES-EDE3-CBC,D785301B65FDBBAD\n\nfj5hlZgM15J5W6QEWQl1wt+4A3pg2fNeONUfJkkNnJ95PyCWx6emfrWqPBHm3q84\nx/8zIIuDIpxYsAmP8qh/cfp0wQ4fY6sTO5qiHikJHPOMc24Rc4nufrtn3NgOTc/T\nep+b1teJMp20M4ZYjHUicOC5j0k0RAcJGpDssuoRfg3aUMk7s+J0bjKgR4SfP9aJ\n73I0lGrZ48AruDFqMX4z1RHaWUU617wmm590bsimVVIYoYeLoRqtRbQAkMh9SzrD\nr98nDPtIPoWlqBoRnaEAGRchlT6QnUsFFFKo6l2J3mny5FxxV7ntRgymZ4dS8CAK\nLaN1SqE6fxiQoTAgWz6FlAdu1hD6eW0vWmTRx392x4hmxqSgrUA0uDX1Twe4MFxf\n50VwDlT6W3YZGCC7RTqtVQtV3lKahw8jLklGdk21pDiQUoFpiScTuQygcgmTkZoq\nqu6FIf8KkABVElHzn79CGZbqq7UtoZEwTzM8VrwZ8ql6UVv8+GXYJhNte5eSNhyv\nBqhoGLL+/iffXB7dmNssiT6W8l9F0zxHSUSoyJXLfP/bwyFG8sDZxLyiCKhR/rYr\nxaxMRPl/1TkTUmHDInfZJwEsjgz3Ar5pOuncmoZ9K88CIoizqP/HPWylurUCp2kJ\n7PHybKWomvC6bI1TFWF3Asp/lVXNCTkf8fWhJZJr57w5s5eWtmw2k0KwRTW1kRAE\nAaBtr4Mu/HIIf966eZSjgbX1n0V+omKHomtRBRztE2hLHXiH0ZihFPuqjE608S1w\nMMTY68IEM6AgnKvIJhnZnp0+IFgLQ0O4uG7Utt1EzEUbwcThzfgTB47WxKMDB5FZ\nTqsnPyX2dP1UM91rBo4wJtrmcLzIPtNrzCo8fYwsk4ro+ocMjTP+hoJjQZvDjvoF\nzSK+zFtmbGm/GUfe7Y/SpBxXIQ/pDavheQX+jz+h6XXI2xztHErs2kNk1ZOkaSfV\nwle4CNyTG26KmzldhokYjSRCZYcDLWuZzuSXIZebxCk6B27iBfahC+UP3TmxRJPF\n5Ncj/H6KxDc176OE2qPeT1KATY8cuUNTSf8BUajHjl0tw5phLeWEYHtSrDW/invK\nN1LdAjAiILoHaWIm5LcKn6Jh14hdPs8N+iWD4jpU1GXxhU5rAa+gR421dNmKw2BV\nYdyzhhWFVXNLkj5UxBOxQg0a5twQIo6hX0IMgk2GxYPgJZCehP/3CNE52AEDuF2V\njHjrhcFuvxPpeA0TFj6ERHYD/YXbxyGtYQxygb/mUypGIwRv0pWCkEMQzdpIB0zY\ndihTyR9W3rmejW8fCtw0m5y/m+TNvjKjp1Xy2g9rZCNd/Yj9JbsordjkhrLnn3Kv\nv1ny2sUmHDYPuZFkg4WM8EC7waxo8UXCbMlF/B9E2LRat+0AWgZXoA3go5f9Asmc\nnZFAQRv3fridKzn9cSW94ImMbizNWBfj8/yPlTQ4TRHVSR/0txy3Ni/K/QH+fZLm\nzJHYv17sos3ZC+grIq1WiD+zVgJkhxuDRt8R9QN29QGo6Nv78qDLn2fm3jy6Wd4l\nhqzcAF0lyCvkp6kU4p5ElogcHwBwuE0f+eU4IK+f0N6cC/YX/14dOBcsXARslVx6\nBrYyY4D9PG8UIbv0kSyd6RFuao3tvZYIoFscGXtgrfnYLFVnY7ue4E06HpY+9zCM\n1/TNYanXHKHB2ZY5WOUBYSmPwtr4vXIqMqlSg9mHNPI5lxYslLQob5nnfswZLno/\nme3fl+ENIazAdBpQuLLpLybh3Ll2uokxYpy94Tma9XTO0XiXB+95zIXSJlUX+rzY\n9ddCLhTwZtlpfXmRo4wbEebXg9yQ6p6ynKKSSPaUgeXLan5LSTYuRj/it2FBeKjM\nUuf2uUFxFsJ84QNZOJuoxkyT17LemhUrlk5NPYMg3vZMexfTfpRlMB9vz2BVfXRT\n+H9fc6xRrLda2od6izTyt2OTDmorfjkHx9FuO3PNvIwJ7Mb0Sg+foMjF0DQwwhwP\nk4gWScbfasFlI8EkC4ljJClWXx8VWE2zb2dB0YRhBBoSUWVwqXrsKEqL/iJwZ+SK\nObE265uqF6S/V4/wymuUqFxZz9YG5kwSBW+dGgs2cD7EE0AdGRLI5X2daWGBRqAi\nmUUdl/d22k/eqbIswkE0CKC7ZKzdcPrfo/eK8ZTR2AfV/kxvZQK+ZTnlZReefxkt\n9I1NnfXA65eiK9rjNMBdHvJjOJWi/TRg647OSb+XyC4IZ5qNlD3o4l0NAUHbsxEV\nyxqC2j1ohbAWb7giJmZ+xEoLFNCYwbc9hECN6VD90RtBxkebLeVaLxhpIGfIHsOE\ngAvHv79olHf0ifuYldehVWiYZ9EVf5O5m/0g1o8KDuuVcI1Da3rTR1BlE5wv5Hef\ntg5aC+VVT4zqp2HnYJ7kgIAlXdDoqx9jJcWY/cOTnJf7orJEYfBTlW9HSiyDaDft\nZNzsAXTP7vXv9fHD3aA+dqzoE9NFWBLVJIu3IcD/Ha8Ll8H82MP6zm27d8uOGJza\nDKlQ7RMRibwusyMOCperpcZC2vk/LHb7yMMUf9h+JDQ3lSeEvN4J8xJQUlg8+/ch\nNwxzQZ6mc1/DVQdddYMUnfTSxF4R3RI8BQrH/9a0ACGT4qlYXk4igCMCuxE/NtB6\naHQZHnSgTnzBZJ7VhoCnuaaCx5myk+fkh8kAU2xmPaYoNQrdqf+6JrWcuN5sc5dF\nNSr5CBAIQCBdwWWJadarWE44BafSypDebEYwl5AmdFrpNafBbbqMmh3tw1ArWQYs\ncfKgaAYoPgbJD+zgSGtY5vG0gfqDZwhw4UvjYSZ44ve5GAvRtODNZETt4CJYzM3k\nhPtQG8le4xQ2RMmsuESqLdN7+mi2+oS9X7uFphtTvUNKwQT7eeVnyw040gxpU3bd\n7B9AgHTu6quqxoTo61/rLp/AJeKerXKEjL7IaDmo0PyFKeGtiz4JXbUJEtbhwyaT\nuRZHXxMGE6fjMx02lxGPr17cTw/NOs7NUjLCQ1bBtFlsldqAuVHR7T2zIvFja1hw\nSMjnt8MDktrbrPhR3LGbyp7ICy5rGK2/M9BFdMk4mKdK1N703fJMppKlWyDU1IPM\nKk7lJEXKSpggrNLaF5lyy0AwIjUMmvGh5TKf1Fbz/76UwxAimZBxrnSXuC7elFjL\n-----END RSA PRIVATE KEY-----\n"
  },
  {
    "path": "test/fixtures/ssl/server2.crt",
    "content": "-----BEGIN CERTIFICATE-----\nMIIEaTCCA1GgAwIBAgIGEnGFJyEJMA0GCSqGSIb3DQEBCwUAMGIxCzAJBgNVBAYT\nAkFVMQwwCgYDVQQIDANOU1cxDzANBgNVBAcMBlN5ZG5leTEPMA0GA1UECgwGTmV3\nbWFuMQ0wCwYDVQQLDARUZXN0MRQwEgYDVQQDDAt0ZXN0Lm5ld21hbjAeFw0xOTEx\nMjEwNTExMTBaFw0yOTExMTgwNTExMTBaMFMxCzAJBgNVBAYTAkFVMQwwCgYDVQQI\nDANOU1cxDzANBgNVBAoMBk5ld21hbjENMAsGA1UECwwEVGVzdDEWMBQGA1UEAwwN\ndGVzdC5zZXJ2ZXIuMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANQl\ncwIuSxBhqWAjWmn+Cyx5t7J6I2SWGSceksXZieoIDWuh9fkXvMZVJovGEZtrRSwQ\nugGY0wZNaZNzt09j5b8q34VONw0N1IlxtaLmsq8fPwiBfrFcZI1LNyOcCXt55Rtv\nV4xA2YoMgNXSb3rVDK4a1vPrJRkBXfnLHFmczAzG3MTaUY27GwKkGURtV45C95qc\nhKkxSfSE6xtE08uck3KSwBHOkj9TNrhBNXz4YffH4W13Z3SwJHFH6t085p6M+Hs5\nm9nQb2wLFLmHgm7crcPDnA/+ZSFMfdERvD4AutmoJ2LsTqNjBSaLppYiR2pMlsUu\nV6qwaFRyRuKrPQMcdQ8CAwEAAaOCATIwggEuMAkGA1UdEwQCMAAwEQYJYIZIAYb4\nQgEBBAQDAgZAMDMGCWCGSAGG+EIBDQQmFiRPcGVuU1NMIEdlbmVyYXRlZCBTZXJ2\nZXIgQ2VydGlmaWNhdGUwHQYDVR0OBBYEFMqtFuQ8CGeKDbSLjMGp9Rx3JtFSMIGU\nBgNVHSMEgYwwgYmAFAh+6n6GHeBG9gaRjkJYQM3syz2WoWakZDBiMQswCQYDVQQG\nEwJBVTEMMAoGA1UECAwDTlNXMQ8wDQYDVQQHDAZTeWRuZXkxDzANBgNVBAoMBk5l\nd21hbjENMAsGA1UECwwEVGVzdDEUMBIGA1UEAwwLdGVzdC5uZXdtYW6CCQCeQzo7\nIRQKgjAOBgNVHQ8BAf8EBAMCBaAwEwYDVR0lBAwwCgYIKwYBBQUHAwEwDQYJKoZI\nhvcNAQELBQADggEBAAYGPG/dvUo0VHscEQyOjjThtJ6d4kisKAtXW7rPtACJg6nn\ngDYgdWHOdZRh/gAF4u6B5Wi86bUgt0Rs3ToDwevV9+FBkxba96+KTh64J8XZF94P\nm1FTB5rSeS4SDNQRK+OlBh5POtGVLEO3p7v+iAjAkM9KE8Dl/Z4xVnELbvKImr7Y\nyDVPREMEL6PqLPtwVuJfYNB3c2rUi2560us1GxqW/q76rfxiEdv0AEZGk8PTJRZS\nZO7MH2H3naQxomvPuzaGhEWNtSO/tqfBYSMmeqV8QKu/uxoUZ7gDLqMsDFd81QA+\nIAX7dDoLxBFpT7oeMrcj5BRZT/QbjqWw1wxq2qQ=\n-----END CERTIFICATE-----\n"
  },
  {
    "path": "test/fixtures/ssl/server2.csr",
    "content": "-----BEGIN CERTIFICATE REQUEST-----\nMIICqTCCAZECAQAwZDELMAkGA1UEBhMCQVUxDDAKBgNVBAgMA05TVzEPMA0GA1UE\nBwwGU3lkbmV5MQ8wDQYDVQQKDAZOZXdtYW4xDTALBgNVBAsMBFRlc3QxFjAUBgNV\nBAMMDXRlc3Quc2VydmVyLjIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB\nAQDUJXMCLksQYalgI1pp/gssebeyeiNklhknHpLF2YnqCA1rofX5F7zGVSaLxhGb\na0UsELoBmNMGTWmTc7dPY+W/Kt+FTjcNDdSJcbWi5rKvHz8IgX6xXGSNSzcjnAl7\neeUbb1eMQNmKDIDV0m961QyuGtbz6yUZAV35yxxZnMwMxtzE2lGNuxsCpBlEbVeO\nQveanISpMUn0hOsbRNPLnJNyksARzpI/Uza4QTV8+GH3x+Ftd2d0sCRxR+rdPOae\njPh7OZvZ0G9sCxS5h4Ju3K3Dw5wP/mUhTH3REbw+ALrZqCdi7E6jYwUmi6aWIkdq\nTJbFLleqsGhUckbiqz0DHHUPAgMBAAGgADANBgkqhkiG9w0BAQsFAAOCAQEAgCr1\nHSrRfEds6G930flXxJBPby+hNElnBtMqvTfuzdGYtY+bJa5uE1AEPm+h+wPUPFWN\nWUrEuzHpyI3fk2PW+HTz+vwkNFIKJSJac9fhwH7Eu2N2Dy32EPNRTSLERY6ZqNrp\nivWGwTzjFdSdFGQOjd+LNY5X5BKQ0ai+XDMCbovsBjC9k+mydZQS9ttbms8KViPn\nUQVBuNv9vx9/iKoS2cGdqRkeUMAh1U7IPdHYbRorV9tslZO+Ya32Ua15oDjrE3nh\n/RyAta3n3FrtwZpO/i/Fgq/btF8mBsUpzZzjPRC8EXE8JWHkbAQdZCePW146qx8q\nkweggGc9RXHhpjx6FQ==\n-----END CERTIFICATE REQUEST-----\n"
  },
  {
    "path": "test/fixtures/ssl/server2.key",
    "content": "-----BEGIN RSA PRIVATE KEY-----\nProc-Type: 4,ENCRYPTED\nDEK-Info: AES-256-CBC,7BEC18626B692265F7C18376151A14C3\n\nsAsNp1MhV4yppCM2SPtpTp1FTkf2vMWSMMEwqVUfZDpGjYcyIQdBpUR6oVVb2oI4\nt41UhrENMbWaqZ8g6U0T4QwaHK3JO60Yexiru4lYMbrXpAQpZTlmKsQ9LfzauRhq\nhdXd6yztotrtvNjPMjOHF9osw3lyI2PnSL3viDp5zxn+rS6QCDYgsmNNw/Qi4UUU\nyEUnPwxJRPeRXoSwG3TW/W5rE2/RPjlC6bGOtOD24CIiut8rXWRhNB1Pqd0KiNX8\nG3rlzHPKl4kTAbxwo4JpeLDWCTlBHakJl10S8w9LH3ubd6eJ9JHCkhm0zkJ4O5r7\nVbav1nNeXcyIXVC3HcGP5muF8n3aWNdL/OaZmcVEtt/qFSIktj2dXODOL4XkMMLT\noHtOU6+/TB4Ra8iQtHqE8hvLmVlfbjwjTd8I1t782DHlli15FoTXjmgPEhwQYR6V\n/7rnYS0oYQMpLwgMuXOtxpkB9FkC+KwIJtZvGCHGPvSPDXc7i7ZRStNvAwi57ORY\nTprSw/AbCCwmNr9MpxpLK1hDtZfAAVWCtkaLTxJOdt+gbtO+OpDSFiI6nSiGazYa\n+Zq235ZUIn6C1UoO6NHVYx4Zstv7GC1eaVmGwHmJw30oDxrZMhW3xK8zNDuWzw3K\nPJzlVhLHoKmudW0xa6IiQCSOkt+iq9dwuqHv2kZUgCADo5miBVJFrv3jpYoilt7a\nSXb6qn7lFmQnCbHx/6rQaXlDGlz2TGwZwmtgR40qyxCMs9BS2bo3xvnc65QnoW8J\nALAd88i67KtrN3byAjWVY/0Uu+kXFVn7xBXty1tX9I/WyM2jnviNMp+8GiKkdtwJ\nqPojzcyPnim2kggQWvwS2Jpfo/gYQiWdhD9ZbfFXT40vWgZjFucr645yMTXYr0n0\n6yeCy9VAdskfGIWjkmgleXrQN/69oYtCJJCXw9xh22Lu5wT7stCsBOJhCVYtNJH9\n6j2gCt8jlAl6ZCxoHzfPIp+B3Shtasvrjr5JhWLDeM+1x2wzo+O396wGlas90h3P\nRcx/JhyixNLQ6WBbEQedGORqUlTBTRk0LDQaJ6v2YSm33DJ5VW1gUEJUiuJhA5Fg\n5TGThXxEZfJ3iVQx1dcBjpoN7stYWPfse/MjorZ1r3ubpOSzxEtJJJ3YWgv5K/ji\no/w3R/k17swKy9mCSdb5F6KGW7WOGfqKvEXXu84t4LBQvM3cdCkSbmdrxoP2TTTn\nCAb58lPtRAHC8IdL2qOKuxJhzKljeVxWDpk2DZLBvD+socYTVAs48YpL/pichDi3\nT+jqISoVbKTYQ6eQ0v7EpdBSA/iPJ2yVPYwPOmV/R/zzagctB6uzEZ8Sq7+HWlWr\nvAgpIYf+h92uQbOu0Uvj/xYqKpFKHAGna0YOId3hNiU7HcawK20AlrdHWiIC2UQc\ny5VPJy5NNRtIzzGD1cetu2/QoOSVFkADX1ctoCoiA9XdedBVQCZ+grrwCQsn1XF/\nV18koBkMcKxf9oV6A7rc5guBHp2OQ3bdgu/C9GFAkaoBjhf29pz7gy57pD+PPL/A\ndyKDP2B1xrDVuwa2Klqy16twtnokk27ouWYcoG7T1VB9W/BoSWevOZaRumS+LxDc\n-----END RSA PRIVATE KEY-----\n"
  },
  {
    "path": "test/fixtures/ssl/server3.crt",
    "content": "-----BEGIN CERTIFICATE-----\nMIIEmzCCA4OgAwIBAgIBATANBgkqhkiG9w0BAQsFADCBijELMAkGA1UEBhMCVVMx\nCzAJBgNVBAgMAkNBMQswCQYDVQQHDAJTRjEQMA4GA1UECgwHUG9zdG1hbjEaMBgG\nA1UECwwRcG9zdG1hbkBsb2NhbGhvc3QxEzARBgNVBAMMClRlc3RDbGllbnQxHjAc\nBgkqhkiG9w0BCQEWD2RvLm5vdEBlbWFpbC5tZTAeFw0yMDA1MTIxOTUwMTVaFw00\nNzA5MjcxOTUwMTVaMIGKMQswCQYDVQQGEwJVUzELMAkGA1UECAwCQ0ExCzAJBgNV\nBAcMAlNGMRAwDgYDVQQKDAdQb3N0bWFuMRowGAYDVQQLDBFwb3N0bWFuQGxvY2Fs\naG9zdDETMBEGA1UEAwwKVGVzdENsaWVudDEeMBwGCSqGSIb3DQEJARYPZG8ubm90\nQGVtYWlsLm1lMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtj6Kynl4\n5Ec7WU1XqSqsXXnh6qBB8Msf7outvZBN7+PD+pU0NGa9jLB+Gd5MJBRFOXomD2Bv\nOqnMlrJs2wOV9TAvPHKS8UGw/cJWX9kLM5S2Pl7jqsVuo1hUjkgeumeJ+iuBagXn\nXFcjSBFjTEOSZ69wdK0KadijCKEz6wtVi0OBZ5zqyWNshvzVlYNHyEnU0Vt6PDWF\ndISkGx+/ixUnW/iQf2InyoVvKAn3iKaCqSnNOHvpyecae1Yv3l1ntw9awrTr0fZn\n65TEy8D1OGBNKdUFCsHbl3w1AJpDP9wBhCmvEX/lMl5bTK8DLM+e67TEYlkkDQXW\nPn5Og1ok1bbsXwIDAQABo4IBCDCCAQQwCQYDVR0TBAIwADAsBglghkgBhvhCAQ0E\nHxYdT3BlblNTTCBHZW5lcmF0ZWQgQ2VydGlmaWNhdGUwHQYDVR0OBBYEFMAuJvYg\n8x0AM21MLaQ2GxpYvsv4MIGpBgNVHSMEgaEwgZ6hgZCkgY0wgYoxCzAJBgNVBAYT\nAlVTMQswCQYDVQQIDAJDQTELMAkGA1UEBwwCU0YxEDAOBgNVBAoMB1Bvc3RtYW4x\nGjAYBgNVBAsMEXBvc3RtYW5AbG9jYWxob3N0MRMwEQYDVQQDDApUZXN0Q2xpZW50\nMR4wHAYJKoZIhvcNAQkBFg9kby5ub3RAZW1haWwubWWCCQDVmzvauKidhzANBgkq\nhkiG9w0BAQsFAAOCAQEAWubsEkBJ3EfnapHOrD1nP7MT3iqrBdyNmKnNiDnP5yCp\nug6Y0SGZ6/oLoBQu5BTq52qvqx+FWcHOm4Voc90CMpCnRroGmlX/ecXXwYd2icRr\nTTC4LU2CccfZ6eZeIbPMJih8CV1n53Jl/TauK80UpsYkVneaStqWalYxqJznejyU\nUF6Yo0bclz0mI/59+myI+PXhLta7rvz2DJ2ECKG8oy+Ak8oTFPUOoSs0lam15WwB\nugvatYbi5zc5sBkh6NRKaoZjMf5WemtHG3ruzOlKbPcvEAHnNvQ/5BC5DAkEmDlN\nTq/VVw9d4bpFEGl126ymiwnRCcHv4LxOK8q/wEyKVg==\n-----END CERTIFICATE-----\n"
  },
  {
    "path": "test/fixtures/ssl/server3.csr",
    "content": "-----BEGIN CERTIFICATE REQUEST-----\nMIIC8zCCAdsCAQAwgYoxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTELMAkGA1UE\nBwwCU0YxEDAOBgNVBAoMB1Bvc3RtYW4xGjAYBgNVBAsMEXBvc3RtYW5AbG9jYWxo\nb3N0MRMwEQYDVQQDDApUZXN0Q2xpZW50MR4wHAYJKoZIhvcNAQkBFg9kby5ub3RA\nZW1haWwubWUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC2PorKeXjk\nRztZTVepKqxdeeHqoEHwyx/ui629kE3v48P6lTQ0Zr2MsH4Z3kwkFEU5eiYPYG86\nqcyWsmzbA5X1MC88cpLxQbD9wlZf2QszlLY+XuOqxW6jWFSOSB66Z4n6K4FqBedc\nVyNIEWNMQ5Jnr3B0rQpp2KMIoTPrC1WLQ4FnnOrJY2yG/NWVg0fISdTRW3o8NYV0\nhKQbH7+LFSdb+JB/YifKhW8oCfeIpoKpKc04e+nJ5xp7Vi/eXWe3D1rCtOvR9mfr\nlMTLwPU4YE0p1QUKwduXfDUAmkM/3AGEKa8Rf+UyXltMrwMsz57rtMRiWSQNBdY+\nfk6DWiTVtuxfAgMBAAGgIzAhBgkqhkiG9w0BCQcxFAwScGFzc3dvcmQgY2hhbGxl\nbmdlMA0GCSqGSIb3DQEBCwUAA4IBAQBhv+L6nWXpENopJsBTnYPCAP7boyBoI08g\n10ncXcZxcDD2nh4DNna1+vmJ3c5Gv7xIPKVEzaY6V/aaCeW4sAK8Rk3G78yRAfg+\nHYaD+snqLy5O+A4fX4N1T+ajOJramVzrea+MNx4EY8GAVbG/dDwJ042zez319hvE\nOGXuBA874dyK5+BwX8kgeJZJ/YMQSsXmW8yQCO3Y/o9+Ut6KykodQmoZMA47nCae\noC3FdQjbGRNWqA7Vgo75JBetBML8pgtIhTN4fj27S48DrPkNttL4A1Iv/zfLXMqA\nOS71qTzeS2nUQvZ939Ms7r5KpW7FVvDmAHaK854zC7tgbvsp0rcq\n-----END CERTIFICATE REQUEST-----\n"
  },
  {
    "path": "test/fixtures/ssl/server3.key",
    "content": "-----BEGIN RSA PRIVATE KEY-----\nMIIEpAIBAAKCAQEAtj6Kynl45Ec7WU1XqSqsXXnh6qBB8Msf7outvZBN7+PD+pU0\nNGa9jLB+Gd5MJBRFOXomD2BvOqnMlrJs2wOV9TAvPHKS8UGw/cJWX9kLM5S2Pl7j\nqsVuo1hUjkgeumeJ+iuBagXnXFcjSBFjTEOSZ69wdK0KadijCKEz6wtVi0OBZ5zq\nyWNshvzVlYNHyEnU0Vt6PDWFdISkGx+/ixUnW/iQf2InyoVvKAn3iKaCqSnNOHvp\nyecae1Yv3l1ntw9awrTr0fZn65TEy8D1OGBNKdUFCsHbl3w1AJpDP9wBhCmvEX/l\nMl5bTK8DLM+e67TEYlkkDQXWPn5Og1ok1bbsXwIDAQABAoIBAAlHi/edUcuF2P7G\nEmWZt6cW0qsIt/LT1O9ni1QwqddCKLN0r3DPnm0we2tDx2q64X94ucFkrqU1CibO\nNP694v/WEUGpr9O6/ZEeORmuSoS42MK6QCts3CJTGBMalv300bC8UF2eqVYpVbGQ\nuRakBitjYn1+Zh5Xmo2Q77zTGer6UfBOkLnpZWGuijrqngFRLSCUDQYUhg740GQZ\nGppb4Qm1gGJhHbQGzy/yExiQuPTpZCTAFTGnjHkt7OToUBrtE3Fp+c5gvv7vIIqg\n+PsygAEfUhukx1wFcz9GcSyg2vyeP8C6TFxFg3T4KBbvHeIgO4w1H7cnJaYnKrXJ\naRuxW/kCgYEA4+KV/Z8lgxmwBumU/ldsEdXcjW0qJ6nNa49J8MQ6P+9EFA70vblk\nj8IFPGQ2w8jcW6jiy2Ee5A5Tfj2l7t7brkr7/zvIGyBoLY02RPe4RAQxSX9mhER8\n5cy+xGNhLX51kYH827bKzYlNBFGCh69exhpD7iDjkEK2beIc7RryP40CgYEAzLp1\njDyRR3ltV2uno0en8y27GcEKSB66pS6qGk5f5f+ml+mZhPuveHcHfVZQygcrrzq7\nuMgBgmUnqkai/O40kOOhDHkj1oXQV5bNTrvmxgzCP2vV2w9s6le1Gm9jTljsAz+5\nRKnYdxhWLUM8Jo9o95LUPQkklwyE1qkOC6/WupsCgYEApeBQ/YPSclNIZj+wTFKm\nP3VETU2g2a4n8JskXzT2kYNAMrmQPGmuYVYBKaxokKqse6u7Kf9P1QD4lXOaTP27\nOmsqcua5CcXVDxMy5ZDLd/b1SWKK5MxVfZBDbABKxCrAuWG9BNFRXbsLbJFISivE\n+L41pCgcfO2SjPmBxLVQkCECgYBKO3Wx0qhOxT2bTCKttqa0KynDTdZ/jfzZNhFh\nlnd5OvhZ7s7GhEf8oxQpIyoKBw2U7PPyLTs235zBRfmFQo3210Km9inDeCOyDrEE\n0mb7+tZYDq6tTmuMkR7OpgLY/q8dAncX6YnerQlaQh3GUYua8TdZpj4JMvXbq9K2\n9Bwk7wKBgQCYZ0H16BZBf4spiKnjKREZvQBKCbcxS5Rne7FTatBKDHG3ZsCcM6aw\npcbVvcjrJqinqOjnvOJA+15OMLKk8ApPibPpB6L3ZC2XSgzgDxhuru2J8dUTqDKO\n2xNI6TCorwfo+Mt3h66+/ldXJw2VdTXLM0k/ivj2h0Bwi3iWEZO9LA==\n-----END RSA PRIVATE KEY-----\n"
  },
  {
    "path": "test/fixtures/ssl/sslClientCertList.json",
    "content": "[\n    {\n        \"name\": \"client1\",\n        \"matches\": [\"https://localhost:3001\", \"https://localhost:3001/*\"],\n        \"key\": {\"src\": \"./test/fixtures/ssl/client2.key\"},\n        \"cert\": {\"src\": \"./test/fixtures/ssl/client2.crt\"},\n        \"passphrase\": \"password\"\n    },\n    {\n        \"name\": \"client2\",\n        \"matches\": [\"https://localhost:3002\", \"https://localhost:3002/*\"],\n        \"key\": {\"src\": \"./test/fixtures/ssl/client3.key\"},\n        \"cert\": {\"src\": \"./test/fixtures/ssl/client3.crt\"},\n        \"passphrase\": \"password\"\n    }\n]\n"
  },
  {
    "path": "test/fixtures/ssl/v3.ext",
    "content": "basicConstraints=CA:FALSE\nnsComment = \"OpenSSL Generated Certificate\"\nsubjectKeyIdentifier=hash\nauthorityKeyIdentifier=keyid,issuer"
  },
  {
    "path": "test/integration/bom-and-encoding/bom-in-collection-file.postman_collection.json",
    "content": "﻿{\n  \"info\": {\n    \"name\": \"Sample Postman Collection\",\n    \"schema\": \"https://schema.getpostman.com/json/collection/v2.0.0/collection.json\",\n    \"description\": \"A sample collection to demonstrate collections as a set of related requests\"\n  },\n\n  \"item\": [{\n    \"name\": \"A simple GET request\",\n    \"event\": [{\n      \"listen\": \"test\",\n      \"script\": {\n        \"type\": \"text/javascript\",\n        \"exec\": [\n          \"pm.test('expect response be 200', function () {\",\n          \"    pm.response.to.be.ok\",\n          \"})\",\n          \"pm.test('expect response json contain args', function () {\",\n          \"    pm.expect(pm.response.json().args).to.have.property('source')\",\n          \"      .and.equal('newman-sample-github-collection')\",\n          \"})\"\n        ]\n      }\n    }],\n    \"request\": {\n      \"url\": \"https://postman-echo.com/get?source=newman-sample-github-collection\",\n      \"method\": \"GET\"\n    }\n  }, {\n    \"name\": \"A simple POST request\",\n    \"request\": {\n      \"url\": \"https://postman-echo.com/post\",\n      \"method\": \"POST\",\n      \"header\": [{\n        \"key\": \"Content-Type\",\n        \"value\": \"text/plain\"\n      }],\n      \"body\": {\n        \"mode\": \"raw\",\n        \"raw\": \"Duis posuere augue vel cursus pharetra. In luctus a ex nec pretium...\"\n      }\n    }\n  }, {\n    \"name\": \"A simple POST request with JSON body\",\n    \"request\": {\n      \"url\": \"https://postman-echo.com/post\",\n      \"method\": \"POST\",\n      \"header\": [{\n        \"key\": \"Content-Type\",\n        \"value\": \"application/json\"\n      }],\n      \"body\": {\n        \"mode\": \"raw\",\n        \"raw\": \"{\\\"text\\\":\\\"Duis posuere augue vel cursus pharetra. In luctus a ex nec pretium...\\\"}\"\n      }\n    }\n  }]\n}\n"
  },
  {
    "path": "test/integration/bom-and-encoding/bom-in-environment-file.postman_collection.json",
    "content": "{\n  \"info\": {\n    \"name\": \"Example Collection with a single GET request\",\n    \"schema\": \"https://schema.getpostman.com/json/collection/v2.0.0/collection.json\"\n  },\n  \"item\": [{\n    \"name\": \"A simple GET request\",\n    \"event\": [{\n      \"listen\": \"test\",\n      \"script\": {\n        \"type\": \"text/javascript\",\n        \"exec\": [\n          \"pm.test('expect response be 200', function () {\",\n          \"    pm.response.to.be.ok\",\n          \"})\",\n          \"pm.test('Response Body', function () {\",\n          \"    var jsonData = pm.response.json();\",\n          \"    pm.expect(jsonData.args).to.have.property('var', 'alpha')\",\n          \"});\"\n        ]\n      }\n    }],\n    \"request\": {\n      \"url\": \"https://postman-echo.com/get?var={{fo/o}}\",\n      \"method\": \"GET\"\n    }\n  }]\n}\n"
  },
  {
    "path": "test/integration/bom-and-encoding/bom-in-environment-file.postman_environment.json",
    "content": "﻿{\n  \"id\": \"043ddbc2-1fbb-242f-9c39-dc89e08d4a65\",\n  \"name\": \"Variable names with slashes\",\n  \"values\": [\n    {\n      \"key\": \"fo/o\",\n      \"type\": \"text\",\n      \"value\": \"alpha\",\n      \"enabled\": true\n    },\n    {\n      \"key\": \"b\\\\ar\",\n      \"type\": \"text\",\n      \"value\": \"beta\",\n      \"enabled\": true\n    }\n  ],\n  \"timestamp\": 1473255725612,\n  \"_postman_variable_scope\": \"environment\",\n  \"_postman_exported_at\": \"2016-09-07T13:43:25.578Z\",\n  \"_postman_exported_using\": \"Postman/4.7.0\"\n}"
  },
  {
    "path": "test/integration/bom-and-encoding/utf16-le-encoding-in-env.postman_collection.json",
    "content": "﻿{\n  \"info\": {\n    \"name\": \"Sample Postman Collection\",\n    \"schema\": \"https://schema.getpostman.com/json/collection/v2.0.0/collection.json\",\n    \"description\": \"A sample collection to demonstrate collections as a set of related requests\"\n  },\n\n  \"item\": [{\n    \"name\": \"A simple GET request\",\n    \"event\": [{\n      \"listen\": \"test\",\n      \"script\": {\n        \"type\": \"text/javascript\",\n        \"exec\": [\n          \"pm.test('expect response be 200', function () {\",\n          \"    pm.response.to.be.ok\",\n          \"})\",\n          \"pm.test('Response Body', function () {\",\n          \"    var jsonData = pm.response.json();\",\n          \"    pm.expect(jsonData.args).to.have.property('serviceHostName', 'localhost')\",\n          \"});\"\n        ]\n      }\n    }],\n    \"request\": {\n      \"url\": \"https://postman-echo.com/get?serviceHostName={{serviceHostName}}\",\n      \"method\": \"GET\"\n    }\n  }]\n}\n"
  },
  {
    "path": "test/integration/case-insen-header-sandbox.postman_collection.json",
    "content": "{\n  \"variables\": [],\n  \"info\": {\n    \"name\": \"Sandbox getResponseHeader method should be case insensitive\",\n    \"_postman_id\": \"1153d5ce-29e2-c83f-648c-24e17c4aa852\",\n    \"description\": \"A set of tests to verify the case insensitive nature of response header retrieval\",\n    \"schema\": \"https://schema.getpostman.com/json/collection/v2.0.0/collection.json\"\n  },\n  \"item\": [\n    {\n      \"name\": \"Get json response\",\n      \"event\": [\n        {\n          \"listen\": \"test\",\n          \"script\": {\n            \"type\": \"text/javascript\",\n            \"exec\": \"tests[\\\"Case-insensitive header checking\\\"] = postman.getResponseHeader(\\\"contenT-TypE\\\")===\\\"application/json; charset=utf-8\\\";\"\n          }\n        }\n      ],\n      \"request\": {\n        \"url\": \"https://postman-echo.com/get\",\n        \"method\": \"GET\",\n        \"header\": [],\n        \"body\": {\n          \"mode\": \"formdata\",\n          \"formdata\": []\n        },\n        \"description\": \"\"\n      },\n      \"response\": []\n    }\n  ]\n}\n"
  },
  {
    "path": "test/integration/clear-vars-sandbox.postman_collection.json",
    "content": "{\n  \"variables\": [],\n  \"info\": {\n    \"name\": \"clearEnvironmentVariable and clearGlobalVariable should work\",\n    \"_postman_id\": \"29199569-c73e-da26-69f3-c6e644b00e25\",\n    \"description\": \"A set of tests to check for proper clearing of environment/global variables in the sandbox\",\n    \"schema\": \"https://schema.getpostman.com/json/collection/v2.0.0/collection.json\"\n  },\n  \"item\": [\n    {\n      \"name\": \"Before clearing\",\n      \"event\": [\n        {\n          \"listen\": \"test\",\n          \"script\": {\n            \"type\": \"text/javascript\",\n            \"exec\": \"console.log(environment);var data = JSON.parse(responseBody);\\ntests[\\\"Variable substitution from env\\\"] = (data.args.a===\\\"2\\\");\\ntests[\\\"Variable substitution from global\\\"] = (data.args.b===\\\"3\\\");\\npostman.clearEnvironmentVariables();\\npostman.clearGlobalVariables();\"\n          }\n        },\n        {\n          \"listen\": \"prerequest\",\n          \"script\": {\n            \"type\": \"text/javascript\",\n            \"exec\": \"postman.setEnvironmentVariable(\\\"e\\\", \\\"2\\\");\\npostman.setGlobalVariable(\\\"g\\\",\\\"3\\\");\"\n          }\n        }\n      ],\n      \"request\": {\n        \"url\": \"https://postman-echo.com/get?a={{e}}&b={{g}}\",\n        \"method\": \"GET\",\n        \"header\": [],\n        \"body\": {\n          \"mode\": \"formdata\",\n          \"formdata\": []\n        },\n        \"description\": \"rd\"\n      },\n      \"response\": []\n    },\n    {\n      \"name\": \"After clearing\",\n      \"event\": [\n        {\n          \"listen\": \"test\",\n          \"script\": {\n            \"type\": \"text/javascript\",\n            \"exec\": \"var data = JSON.parse(responseBody);\\ntests[\\\"Variable substitution from env not working after clearing\\\"] = (data.args.a===\\\"{{e}}\\\");\\ntests[\\\"Variable substitution from global not working after clearing\\\"] = (data.args.b===\\\"{{g}}\\\");\\npostman.setEnvironmentVariable(\\\"e\\\", \\\"2\\\");\\npostman.setGlobalVariable(\\\"g\\\",\\\"3\\\");\\ntests[\\\"Recreated vars\\\"]=environment.e===\\\"2\\\" && globals.g===\\\"3\\\"\\npostman.clearEnvironmentVariable(\\\"e\\\");\\npostman.clearGlobalVariable(\\\"g\\\");\"\n          }\n        }\n      ],\n      \"request\": {\n        \"url\": \"https://postman-echo.com/get?a={{e}}&b={{g}}\",\n        \"method\": \"GET\",\n        \"header\": [],\n        \"body\": {\n          \"mode\": \"formdata\",\n          \"formdata\": []\n        },\n        \"description\": \"rd\"\n      },\n      \"response\": []\n    },\n    {\n      \"name\": \"After clearing\",\n      \"event\": [\n        {\n          \"listen\": \"test\",\n          \"script\": {\n            \"type\": \"text/javascript\",\n            \"exec\": \"console.log(environment);console.log(globals);var data = JSON.parse(responseBody);\\ntests[\\\"Variable substitution from env not working after clearing individually\\\"] = (data.args.a===\\\"{{e}}\\\");\\ntests[\\\"Variable substitution from global not working after clearing individually\\\"] = (data.args.b===\\\"{{g}}\\\");\"\n          }\n        }\n      ],\n      \"request\": {\n        \"url\": \"https://postman-echo.com/get?a={{e}}&b={{g}}\",\n        \"method\": \"GET\",\n        \"header\": [],\n        \"body\": {\n          \"mode\": \"formdata\",\n          \"formdata\": []\n        },\n        \"description\": \"rd\"\n      },\n      \"response\": []\n    }\n  ]\n}\n"
  },
  {
    "path": "test/integration/comma-test-csv/comma-test-csv.postman_collection.json",
    "content": "{\n\t\"info\": {\n\t\t\"_postman_id\": \"ac876a75-22ac-40cf-8abe-27ad079b6a5d\",\n\t\t\"name\": \"CSV parsing test\",\n\t\t\"schema\": \"https://schema.getpostman.com/json/collection/v2.1.0/collection.json\"\n\t},\n\t\"item\": [\n\t\t{\n\t\t\t\"name\": \"r1\",\n\t\t\t\"event\": [\n\t\t\t\t{\n\t\t\t\t\t\"listen\": \"test\",\n\t\t\t\t\t\"script\": {\n\t\t\t\t\t\t\"id\": \"00c12c73-e93f-4ba8-815c-20f6e4b5d137\",\n\t\t\t\t\t\t\"exec\": [\n\t\t\t\t\t\t\t\"\"\n\t\t\t\t\t\t],\n\t\t\t\t\t\t\"type\": \"text/javascript\"\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"listen\": \"prerequest\",\n\t\t\t\t\t\"script\": {\n\t\t\t\t\t\t\"id\": \"8292797c-b676-4a41-966b-c2b92d607425\",\n\t\t\t\t\t\t\"exec\": [\n\t\t\t\t\t\t\t\"pm.test(\\\"CSV parsing tests\\\", function () {\",\n\t\t\t\t\t\t\t\"    pm.expect(data.nameWithComma).to.eql('Abhijit, Kane');\",\n\t\t\t\t\t\t\t\"    pm.expect(data.nameWithDoubleQuotes).to.eql('Abhijit \\\"KDOS\\\" Kane');\",\n\t\t\t\t\t\t\t\"    pm.expect(data.numberWithQuotes).to.eql('00123');\",\n\t\t\t\t\t\t\t\"    pm.expect(data.numberWithoutQuotes).to.eql(7890);\",\n\t\t\t\t\t\t\t\"    pm.expect(data.negativeNumberWithoutQuotes).to.eql(-7890);\",\n\t\t\t\t\t\t\t\"    pm.expect(data.nullValue).to.eql('');\",\n\t\t\t\t\t\t\t\"    pm.expect(data.longNumber).to.eql('89111702272002019559');\",\n\t\t\t\t\t\t\t\"    pm.expect(data.spaceAfterComma).to.eql('foo');\",\n\t\t\t\t\t\t\t\"    pm.expect(data.spaceBeforeComma).to.eql('bar');\",\n\t\t\t\t\t\t\t\"    pm.expect(data.nameWithUnescapedQuotes).to.eql('Abhijit \\\"KDOS\\\" Kane');\",\n\t\t\t\t\t\t\t\"});\"\n\t\t\t\t\t\t],\n\t\t\t\t\t\t\"type\": \"text/javascript\"\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t],\n\t\t\t\"protocolProfileBehavior\": {\n\t\t\t\t\"disableBodyPruning\": true\n\t\t\t},\n\t\t\t\"request\": {\n\t\t\t\t\"method\": \"GET\",\n\t\t\t\t\"header\": [\n\t\t\t\t\t{\n\t\t\t\t\t\t\"key\": \"Content-Type\",\n\t\t\t\t\t\t\"name\": \"Content-Type\",\n\t\t\t\t\t\t\"value\": \"application/json\",\n\t\t\t\t\t\t\"type\": \"text\"\n\t\t\t\t\t}\n\t\t\t\t],\n\t\t\t\t\"body\": {\n\t\t\t\t\t\"mode\": \"raw\",\n\t\t\t\t\t\"raw\": \"{\\n\\t\\\"nameWithComma\\\": \\\"{{nameWithComma}}\\\",\\n\\t\\\"nameWithoutComma\\\": \\\"{{nameWithoutComma}}\\\",\\n\\t\\\"numberWithQuotes\\\": \\\"{{numberWithQuotes}}\\\",\\n\\t\\\"numberWithoutQuotes\\\": \\\"{{numberWithoutQuotes}}\\\",\\n\\t\\\"longNumber\\\": \\\"{{longNumber}}\\\",\\n\\t\\\"spaceAfterComma\\\": \\\"{{spaceAfterComma}}\\\",\\n\\t\\\"spaceBeforeComma\\\": \\\"{{spaceBeforeComma}}\\\"\\n}\"\n\t\t\t\t},\n\t\t\t\t\"url\": {\n\t\t\t\t\t\"raw\": \"postman-echo.com/get\",\n\t\t\t\t\t\"host\": [\n\t\t\t\t\t\t\"postman-echo\",\n\t\t\t\t\t\t\"com\"\n\t\t\t\t\t],\n\t\t\t\t\t\"path\": [\n\t\t\t\t\t\t\"get\"\n\t\t\t\t\t]\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"response\": []\n\t\t}\n\t]\n}\n"
  },
  {
    "path": "test/integration/comma-test-csv/comma-test-csv.postman_data.csv",
    "content": "nameWithComma,nameWithDoubleQuotes,numberWithQuotes,numberWithoutQuotes,negativeNumberWithoutQuotes,nullValue,longNumber, spaceAfterComma ,spaceBeforeComma, nameWithUnescapedQuotes\n\"Abhijit, Kane\",\"Abhijit \"\"KDOS\"\" Kane\",\"00123\",7890,-7890,,\"89111702272002019559\", \"foo\" ,\"bar\", Abhijit \"KDOS\" Kane\n"
  },
  {
    "path": "test/integration/cookie-jar.postman_collection.json",
    "content": "{\n\t\"variables\": [],\n\t\"info\": {\n\t\t\"name\": \"cookie-jar\",\n\t\t\"_postman_id\": \"6d4f33fe-5c73-f4e0-b3a2-7310ab6b05da\",\n\t\t\"description\": \"\",\n\t\t\"schema\": \"https://schema.getpostman.com/json/collection/v2.0.0/collection.json\"\n\t},\n\t\"item\": [\n\t\t{\n\t\t\t\"name\": \"Set Cookie\",\n\t\t\t\"request\": {\n\t\t\t\t\"url\": \"https://postman-echo.com/cookies/set?foo=bar\",\n\t\t\t\t\"method\": \"GET\",\n\t\t\t\t\"header\": [],\n\t\t\t\t\"body\": {\n\t\t\t\t\t\"mode\": \"formdata\",\n\t\t\t\t\t\"formdata\": []\n\t\t\t\t},\n\t\t\t\t\"description\": \"A request to set a cookie `foo` to a value `bar` using Postman Echo as an example.\"\n\t\t\t},\n\t\t\t\"response\": []\n\t\t},\n\t\t{\n\t\t\t\"name\": \"Verify cookie\",\n\t\t\t\"event\": [\n\t\t\t\t{\n\t\t\t\t\t\"listen\": \"test\",\n\t\t\t\t\t\"script\": {\n\t\t\t\t\t\t\"type\": \"text/javascript\",\n\t\t\t\t\t\t\"exec\": \"tests[\\\"Status code is 200\\\"] = responseCode.code === 200;\\ntests[\\\"Cookie `foo` exists and has the value bar\\\"] = postman.getResponseCookie(\\\"foo\\\").value === \\\"bar\\\";\"\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t],\n\t\t\t\"request\": {\n\t\t\t\t\"url\": \"https://postman-echo.com/cookies\",\n\t\t\t\t\"method\": \"GET\",\n\t\t\t\t\"header\": [],\n\t\t\t\t\"body\": {\n\t\t\t\t\t\"mode\": \"formdata\",\n\t\t\t\t\t\"formdata\": []\n\t\t\t\t},\n\t\t\t\t\"description\": \"A request to validate the presence of the cookie `foo`, with value `bar`, using Postman Echo.\"\n\t\t\t},\n\t\t\t\"response\": []\n\t\t}\n\t]\n}\n"
  },
  {
    "path": "test/integration/crypto-md5.postman_collection.json",
    "content": "{\n  \"variables\": [],\n  \"info\": {\n    \"name\": \"Crypto-MD5 should work in the sandbox\",\n    \"_postman_id\": \"4f085147-6c40-19dc-6250-257d64c261ac\",\n    \"description\": \"A set of tests to verify the crypto.md5 function in the sandbox\",\n    \"schema\": \"https://schema.getpostman.com/json/collection/v2.0.0/collection.json\"\n  },\n  \"item\": [\n    {\n      \"name\": \"r1\",\n      \"event\": [\n        {\n          \"listen\": \"test\",\n          \"script\": {\n            \"type\": \"text/javascript\",\n            \"exec\": \"var data = JSON.parse(responseBody);\\ntests[\\\"Your test name\\\"] = data.args.a === \\\"da9ebb087d8e926c503e4909d9203a04\\\";\"\n          }\n        },\n        {\n          \"listen\": \"prerequest\",\n          \"script\": {\n            \"type\": \"text/javascript\",\n            \"exec\": \"postman.setGlobalVariable(\\\"a\\\", CryptoJS.MD5(\\\"samplePayload\\\").toString());\"\n          }\n        }\n      ],\n      \"request\": {\n        \"url\": \"https://postman-echo.com/get?a={{a}}\",\n        \"method\": \"GET\",\n        \"header\": [],\n        \"body\": {\n          \"mode\": \"formdata\",\n          \"formdata\": []\n        },\n        \"description\": \"\"\n      },\n      \"response\": []\n    }\n  ]\n}\n"
  },
  {
    "path": "test/integration/csv-with-bom/csv-with-bom.postman_collection.json",
    "content": "{\n  \"info\": {\n    \"name\": \"CSV with BOM\",\n    \"schema\": \"https://schema.getpostman.com/json/collection/v2.1.0/collection.json\"\n  },\n  \"item\": [{\n    \"event\": [{\n      \"listen\": \"prerequest\",\n      \"script\": {\n        \"exec\": [\n          \"pm.test(\\\"CSV parsing tests\\\", function () {\",\n          \"    pm.expect(data.c1).to.eql('123');\",\n          \"    pm.expect(data.c2).to.eql('foo \\\"bar\\\" baz');\",\n          \"    pm.expect(data.c3).to.be.undefined;\",\n          \"});\"\n        ],\n        \"type\": \"text/javascript\"\n      }\n    }],\n    \"request\": \"postman-echo.com/get\"\n  }]\n}\n"
  },
  {
    "path": "test/integration/csv-with-bom/csv-with-bom.postman_data.csv",
    "content": "﻿c1, c2, c3\n\"123\", foo \"bar\" baz\n"
  },
  {
    "path": "test/integration/custom-http-method/custom-http-method.postman_collection.json",
    "content": "{\n\t\"info\": {\n\t\t\"_postman_id\": \"ace7fe4a-c765-48b6-b578-02aa634ad5d0\",\n\t\t\"name\": \"custom-http-method\",\n\t\t\"schema\": \"https://schema.getpostman.com/json/collection/v2.1.0/collection.json\"\n\t},\n\t\"item\": [\n\t\t{\n\t\t\t\"name\": \"form-data\",\n\t\t\t\"event\": [\n\t\t\t\t{\n\t\t\t\t\t\"listen\": \"test\",\n\t\t\t\t\t\"script\": {\n\t\t\t\t\t\t\"id\": \"088721b0-c2e6-47fa-85b0-8a4f79c71f82\",\n\t\t\t\t\t\t\"type\": \"text/javascript\",\n\t\t\t\t\t\t\"exec\": [\n\t\t\t\t\t\t\t\"pm.test(\\\"Response Body: form-data\\\", function () {\",\n\t\t\t\t\t\t\t\"    var response = pm.response.text();\",\n\t\t\t\t\t\t\t\"    pm.expect(response).to.contain('POSTMAN / HTTP/1.1');\",\n\t\t\t\t\t\t\t\"    pm.expect(response).to.contain('Content-Type: multipart/form-data');\",\n\t\t\t\t\t\t\t\"    pm.expect(response).to.contain('Content-Disposition: form-data; name=\\\"dataKey\\\"');\",\n\t\t\t\t\t\t\t\"    pm.expect(response).to.contain('Content-Disposition: form-data; name=\\\"dataFile\\\"');\",\n\t\t\t\t\t\t\t\"});\"\n\t\t\t\t\t\t]\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t],\n\t\t\t\"request\": {\n\t\t\t\t\"method\": \"POSTMAN\",\n\t\t\t\t\"header\": [],\n\t\t\t\t\"body\": {\n\t\t\t\t\t\"mode\": \"formdata\",\n\t\t\t\t\t\"formdata\": [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"key\": \"dataKey\",\n\t\t\t\t\t\t\t\"value\": \"dataValue\",\n\t\t\t\t\t\t\t\"type\": \"text\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"key\": \"dataFile\",\n\t\t\t\t\t\t\t\"src\": \"test/integration/custom-http-method/upload-file.csv\",\n\t\t\t\t\t\t\t\"type\": \"file\"\n\t\t\t\t\t\t}\n\t\t\t\t\t]\n\t\t\t\t},\n\t\t\t\t\"url\": {\n\t\t\t\t\t\"raw\": \"localhost:4041\",\n\t\t\t\t\t\"host\": [\n\t\t\t\t\t\t\"localhost\"\n\t\t\t\t\t],\n\t\t\t\t\t\"port\": \"4041\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"response\": []\n\t\t},\n\t\t{\n\t\t\t\"name\": \"raw\",\n\t\t\t\"event\": [\n\t\t\t\t{\n\t\t\t\t\t\"listen\": \"test\",\n\t\t\t\t\t\"script\": {\n\t\t\t\t\t\t\"id\": \"36aee6c6-7565-412b-ad9b-0b48a1e3271f\",\n\t\t\t\t\t\t\"type\": \"text/javascript\",\n\t\t\t\t\t\t\"exec\": [\n\t\t\t\t\t\t\t\"pm.test(\\\"Response Body: raw\\\", function () {\",\n\t\t\t\t\t\t\t\"    var response = pm.response.text();\",\n\t\t\t\t\t\t\t\"    pm.expect(response).to.contain('POSTMAN / HTTP/1.1');\",\n\t\t\t\t\t\t\t\"    pm.expect(response).to.contain('Content-Type: application/json');\",\n\t\t\t\t\t\t\t\"    pm.expect(response).to.contain('Content-Length: 16');\",\n\t\t\t\t\t\t\t\"    pm.expect(response).to.contain('{ \\\"foo\\\": \\\"bar\\\" }');\",\n\t\t\t\t\t\t\t\"});\"\n\t\t\t\t\t\t]\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t],\n\t\t\t\"request\": {\n\t\t\t\t\"method\": \"POSTMAN\",\n\t\t\t\t\"header\": [\n\t\t\t\t\t{\n\t\t\t\t\t\t\"key\": \"Content-Type\",\n\t\t\t\t\t\t\"value\": \"application/json\"\n\t\t\t\t\t}\n\t\t\t\t],\n\t\t\t\t\"body\": {\n\t\t\t\t\t\"mode\": \"raw\",\n\t\t\t\t\t\"raw\": \"{ \\\"foo\\\": \\\"bar\\\" }\"\n\t\t\t\t},\n\t\t\t\t\"url\": {\n\t\t\t\t\t\"raw\": \"localhost:4041\",\n\t\t\t\t\t\"host\": [\n\t\t\t\t\t\t\"localhost\"\n\t\t\t\t\t],\n\t\t\t\t\t\"port\": \"4041\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"response\": []\n\t\t},\n\t\t{\n\t\t\t\"name\": \"body disabled\",\n\t\t\t\"event\": [\n\t\t\t\t{\n\t\t\t\t\t\"listen\": \"test\",\n\t\t\t\t\t\"script\": {\n\t\t\t\t\t\t\"id\": \"7ddebe16-dce1-487e-8558-161704d9bb8d\",\n\t\t\t\t\t\t\"type\": \"text/javascript\",\n\t\t\t\t\t\t\"exec\": [\n\t\t\t\t\t\t\t\"pm.test(\\\"Response Body: body disabled\\\", function () {\",\n\t\t\t\t\t\t\t\"    var response = pm.response.text();\",\n\t\t\t\t\t\t\t\"    pm.expect(response).to.contain('POSTMAN / HTTP/1.1');\",\n\t\t\t\t\t\t\t\"    pm.expect(response).to.not.contain('Content-Type');\",\n\t\t\t\t\t\t\t\"    pm.expect(response).to.contain('Content-Length: 0');\",\n\t\t\t\t\t\t\t\"});\"\n\t\t\t\t\t\t]\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t],\n\t\t\t\"request\": {\n\t\t\t\t\"method\": \"POSTMAN\",\n\t\t\t\t\"header\": [],\n\t\t\t\t\"body\": {\n          \"disabled\": true,\n\t\t\t\t\t\"mode\": \"raw\",\n\t\t\t\t\t\"raw\": \"foo=bar\"\n\t\t\t\t},\n\t\t\t\t\"url\": {\n\t\t\t\t\t\"raw\": \"localhost:4041\",\n\t\t\t\t\t\"host\": [\n\t\t\t\t\t\t\"localhost\"\n\t\t\t\t\t],\n\t\t\t\t\t\"port\": \"4041\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"response\": []\n\t\t}\n\t]\n}\n"
  },
  {
    "path": "test/integration/custom-http-method/upload-file.csv",
    "content": "key,val\na,1\nb,2\nc,3\n"
  },
  {
    "path": "test/integration/data-file-var-replacement/data-file-var-replacement.postman_collection.json",
    "content": "{\n  \"variables\": [],\n  \"info\": {\n    \"name\": \"{{variable}} works for data file values\",\n    \"_postman_id\": \"dd85194f-bdb3-8ce1-fd25-554cac614f89\",\n    \"description\": \"A set of checks for variable value population via data files\",\n    \"schema\": \"https://schema.getpostman.com/json/collection/v2.0.0/collection.json\"\n  },\n  \"item\": [\n    {\n      \"name\": \"https://postman-echo.com/post\",\n      \"event\": [\n        {\n          \"listen\": \"test\",\n          \"script\": {\n            \"type\": \"text/javascript\",\n            \"exec\": \"var data = JSON.parse(responseBody);\\ntests[\\\"form data populated through env file\\\"] = (data.form.envFileKey===\\\"sampleKey\\\");\\ntests[\\\"form-data populated through prScript\\\"] = (data.form.prScriptTest==iteration);\"\n          }\n        },\n        {\n          \"listen\": \"prerequest\",\n          \"script\": {\n            \"type\": \"text/javascript\",\n            \"exec\": \"postman.setEnvironmentVariable(\\\"dataVar2\\\",iteration);\"\n          }\n        }\n      ],\n      \"request\": {\n        \"url\": \"https://{{envFileUrl}}/post\",\n        \"method\": \"POST\",\n        \"header\": [\n          {\n            \"key\": \"h1\",\n            \"value\": \"v1\",\n            \"description\": \"\"\n          }\n        ],\n        \"body\": {\n          \"mode\": \"formdata\",\n          \"formdata\": [\n            {\n              \"key\": \"dataFileKey\",\n              \"value\": \"{{dataVar}}\",\n              \"type\": \"text\"\n            },\n            {\n              \"key\": \"envFileKey\",\n              \"value\": \"{{envKey}}\",\n              \"type\": \"text\"\n            },\n            {\n              \"key\": \"prScriptTest\",\n              \"value\": \"{{dataVar2}}\",\n              \"type\": \"text\"\n            }\n          ]\n        },\n        \"description\": \"\"\n      },\n      \"response\": []\n    }\n  ]\n}\n"
  },
  {
    "path": "test/integration/data-file-var-replacement/data-file-var-replacement.postman_data.json",
    "content": "[{\"dataVar\":\"value1\"},{\"dataVar\":\"value2\"}]\n"
  },
  {
    "path": "test/integration/data-file-var-replacement/data-file-var-replacement.postman_environment.json",
    "content": "{\n\t\"id\": \"426c4896-2d5b-80b8-da5d-ac205502f3c0\",\n\t\"name\": \"testEnv\",\n\t\"values\": [\n\t\t{\n\t\t\t\"key\": \"envKey\",\n\t\t\t\"value\": \"sampleKey\",\n\t\t\t\"type\": \"text\",\n\t\t\t\"name\": \"envKey\",\n\t\t\t\"enabled\": true\n\t\t},\n\t\t{\n\t\t\t\"key\": \"envFileUrl\",\n\t\t\t\"value\": \"postman-echo.com\",\n\t\t\t\"type\": \"text\",\n\t\t\t\"name\": \"envFileUrl\",\n\t\t\t\"enabled\": true\n\t\t}\n\t],\n\t\"timestamp\": 1404119927461,\n\t\"synced\": false,\n\t\"syncedFilename\": \"\"\n}\n"
  },
  {
    "path": "test/integration/disabled-and-duplicate-variables/disabled-and-duplicates.postman_collection.json",
    "content": "{\n\t\"info\": {\n\t\t\"_postman_id\": \"72ec18aa-a3cb-450d-ae88-4b6b59f69939\",\n\t\t\"name\": \"disabled-and-duplicates\",\n\t\t\"schema\": \"https://schema.getpostman.com/json/collection/v2.1.0/collection.json\"\n\t},\n\t\"item\": [\n\t\t{\n\t\t\t\"name\": \"https://postman-echo.com/get\",\n\t\t\t\"event\": [\n\t\t\t\t{\n\t\t\t\t\t\"listen\": \"test\",\n\t\t\t\t\t\"script\": {\n\t\t\t\t\t\t\"id\": \"47dc2d0e-2ada-400a-94a0-ed3fd1f4280c\",\n\t\t\t\t\t\t\"exec\": [\n\t\t\t\t\t\t\t\"pm.test('Disabled variable', function () {\",\n\t\t\t\t\t\t\t\"    pm.expect(pm.environment.has('justDisabled')).to.be.false;\",\n\t\t\t\t\t\t\t\"    pm.expect(pm.environment.get('justDisabled')).to.be.undefined;\",\n\t\t\t\t\t\t\t\"});\",\n\t\t\t\t\t\t\t\"\",\n\t\t\t\t\t\t\t\"pm.test('1 Enabled and 1 Disabled variable', function () {\",\n\t\t\t\t\t\t\t\"    pm.expect(pm.environment.has('oneDisabled')).to.be.true;\",\n\t\t\t\t\t\t\t\"    pm.expect(pm.environment.get('oneDisabled')).to.equal('1');\",\n\t\t\t\t\t\t\t\"});\",\n\t\t\t\t\t\t\t\"\",\n\t\t\t\t\t\t\t\"pm.test('Duplicate variable', function () {\",\n\t\t\t\t\t\t\t\"    pm.expect(pm.environment.has('duplicate')).to.be.true;\",\n\t\t\t\t\t\t\t\"    pm.expect(pm.environment.get('duplicate')).to.equal('2'); // last enabled\",\n\t\t\t\t\t\t\t\"});\"\n\t\t\t\t\t\t],\n\t\t\t\t\t\t\"type\": \"text/javascript\"\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t],\n\t\t\t\"request\": {\n\t\t\t\t\"method\": \"GET\",\n\t\t\t\t\"url\": {\n\t\t\t\t\t\"raw\": \"https://postman-echo.com/get\",\n\t\t\t\t\t\"protocol\": \"https\",\n\t\t\t\t\t\"host\": [\n\t\t\t\t\t\t\"postman-echo\",\n\t\t\t\t\t\t\"com\"\n\t\t\t\t\t],\n\t\t\t\t\t\"path\": [\n\t\t\t\t\t\t\"get\"\n\t\t\t\t\t]\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t]\n}\n"
  },
  {
    "path": "test/integration/disabled-and-duplicate-variables/disabled-and-duplicates.postman_environment.json",
    "content": "{\n\t\"id\": \"466fce1f-6998-4513-8001-74481c37a7ee\",\n\t\"name\": \"disabled-and-duplicates\",\n\t\"values\": [\n\t\t{\n\t\t\t\"key\": \"justDisabled\",\n\t\t\t\"value\": \"1\",\n\t\t\t\"disabled\": true\n\t\t},\n\t\t{\n\t\t\t\"key\": \"oneDisabled\",\n\t\t\t\"value\": \"1\"\n\t\t},\n\t\t{\n\t\t\t\"key\": \"oneDisabled\",\n\t\t\t\"value\": \"2\",\n\t\t\t\"disabled\": true\n\t\t},\n\t\t{\n\t\t\t\"key\": \"duplicate\",\n\t\t\t\"value\": \"1\",\n\t\t\t\"type\": \"text\"\n\t\t},\n\t\t{\n\t\t\t\"key\": \"duplicate\",\n\t\t\t\"value\": \"2\",\n\t\t\t\"type\": \"text\"\n\t\t}\n\t],\n\t\"_postman_variable_scope\": \"environment\"\n}\n"
  },
  {
    "path": "test/integration/distinct-random-int.postman_collection.json",
    "content": "{\n  \"variables\": [],\n  \"info\": {\n    \"name\": \"Test that {{$randomInt}} gives different values across requests\",\n    \"_postman_id\": \"ad279aba-66c1-a145-5acb-e0e2fcf23465\",\n    \"description\": \"A set of tests to verify the value of seeded environment variables using random data from a remote source\",\n    \"schema\": \"https://schema.getpostman.com/json/collection/v2.0.0/collection.json\"\n  },\n  \"item\": [\n    {\n      \"name\": \"r1\",\n      \"event\": [\n        {\n          \"listen\": \"test\",\n          \"script\": {\n            \"type\": \"text/javascript\",\n            \"exec\": \"var data = JSON.parse(responseBody);\\npostman.setEnvironmentVariable(\\\"randomVar\\\", parseInt(data.args.a));\"\n          }\n        }\n      ],\n      \"request\": {\n        \"url\": \"https://postman-echo.com/get?a={{$randomInt}}\",\n        \"method\": \"GET\",\n        \"header\": [],\n        \"body\": {\n          \"mode\": \"formdata\",\n          \"formdata\": []\n        },\n        \"description\": \"\"\n      },\n      \"response\": []\n    },\n    {\n      \"name\": \"r2\",\n      \"event\": [\n        {\n          \"listen\": \"test\",\n          \"script\": {\n            \"type\": \"text/javascript\",\n            \"exec\": \"var data = JSON.parse(responseBody);\\nvar newVar = parseInt(data.args.a)\\ntests[\\\"different randoms\\\"] = newVar!==environment.randomVar;\"\n          }\n        }\n      ],\n      \"request\": {\n        \"url\": \"https://postman-echo.com/get?a={{$randomInt}}&b={{$guid}}\",\n        \"method\": \"GET\",\n        \"header\": [],\n        \"body\": {\n          \"mode\": \"formdata\",\n          \"formdata\": []\n        },\n        \"description\": \"\"\n      },\n      \"response\": []\n    }\n  ]\n}\n"
  },
  {
    "path": "test/integration/dynamic-var-replacement.postman_collection.json",
    "content": "{\n  \"variables\": [],\n  \"info\": {\n    \"name\": \"Dynamic variables (guid/timestamp/randomInt)\",\n    \"_postman_id\": \"9543b60e-886a-b820-3f16-7087af71d296\",\n    \"description\": \"Test collection to show bug around dynamic variables with Newman\",\n    \"schema\": \"https://schema.getpostman.com/json/collection/v2.0.0/collection.json\"\n  },\n  \"item\": [\n    {\n      \"name\": \"POST Request copy\",\n      \"event\": [\n        {\n          \"listen\": \"test\",\n          \"script\": {\n            \"type\": \"text/javascript\",\n            \"exec\": \"var responseJSON;\\ntry { responseJSON = JSON.parse(responseBody); }\\ncatch (e) { \\n    console.log(e);\\n}\\n\\ntests['FriendlyName should be a GUID'] = /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/i.test(responseJSON.form['FriendlyName']);\\n\\ntests['RandomId should be an integer'] = (_.parseInt(responseJSON.form['RandomId']) % 1) === 0;\\ntests['TimeCreated should be an integer'] = (_.parseInt(responseJSON.form['TimeCreated']) % 1) === 0;\\n\"\n          }\n        }\n      ],\n      \"request\": {\n        \"url\": \"https://postman-echo.com/post\",\n        \"method\": \"POST\",\n        \"header\": [],\n        \"body\": {\n          \"mode\": \"urlencoded\",\n          \"urlencoded\": [\n            {\n              \"key\": \"FriendlyName\",\n              \"value\": \"{{$guid}}\",\n              \"type\": \"text\",\n              \"enabled\": true\n            },\n            {\n              \"key\": \"RandomId\",\n              \"value\": \"{{$randomInt}}\",\n              \"type\": \"text\",\n              \"enabled\": true\n            },\n            {\n              \"key\": \"TimeCreated\",\n              \"value\": \"{{$timestamp}}\",\n              \"type\": \"text\",\n              \"enabled\": true\n            }\n          ]\n        },\n        \"description\": \"The HTTP `POST` request method is meant to transfer data to a server \\n(and elicit a response). What data is returned depends on the implementation\\nof the server.\\n\\nA `POST` request can pass parameters to the server using \\\"Query String \\nParameters\\\", as well as the Request Body. For example, in the following request,\\n\\n> POST /hi/there?hand=wave\\n>\\n> <request-body>\\n\\nThe parameter \\\"hand\\\" has the value \\\"wave\\\". The request body can be in multiple\\nformats. These formats are defined by the MIME type of the request. The MIME \\nType can be set using the ``Content-Type`` HTTP header. The most commonly used \\nMIME types are:\\n\\n* `multipart/form-data`\\n* `application/x-www-form-urlencoded`\\n* `application/json`\\n\\nThis endpoint echoes the HTTP headers, request parameters, the contents of\\nthe request body and the complete URI requested.\"\n      },\n      \"response\": []\n    }\n  ]\n}\n"
  },
  {
    "path": "test/integration/echo-v2.postman_collection.json",
    "content": "{\n  \"variables\": [],\n  \"info\": {\n    \"name\": \"Postman Echo (V2)\",\n    \"_postman_id\": \"2228fc32-fbaf-015d-0b93-692a80d62019\",\n    \"description\": \"Postman Echo is service you can use to test your REST clients and make sample API calls. It provides endpoints for `GET`, `POST`, `PUT`, various auth mechanisms and other utility endpoints.\",\n    \"schema\": \"https://schema.getpostman.com/json/collection/v2.0.0/collection.json\"\n  },\n  \"item\": [\n    {\n      \"_postman_id\": \"e372e924-c66a-fdb0-0363-cc55944206f7\",\n      \"name\": \"Auth: Digest\",\n      \"description\": \"Digest authentication protects an endpoint with a username and password without actually transmitting the password over network.\\nOne has to apply a hash function (like MD5, etc) to the username and password before sending them over the network.\\n\\n> Username: `postman`\\n>\\n> Password: `password`\\n\\nUnlike Basic-Auth, authentication happens using two consecutive requests where the first request returns `401 Unauthorised` along with `WWW-Authenticate` header containing information that needs to be used to authenticate subsequent calls.\\n\\nTo know more about digest authentication, refer to the [Digest Access Authentication](https://en.wikipedia.org/wiki/Digest_access_authentication) wikipedia article.\\nThe article on [authentication helpers](https://www.getpostman.com/docs/helpers#digest-auth) elaborates how to use the same within the Postman app.\",\n      \"item\": [\n        {\n          \"id\": \"0e5181dc-1baf-02ec-d105-0c94e4463b2a\",\n          \"name\": \"DigestAuth Request\",\n          \"event\": [\n            {\n              \"listen\": \"test\",\n              \"script\": {\n                \"type\": \"text/javascript\",\n                \"exec\": \"tests[\\\"response code is 401\\\"] = responseCode.code === 401;\\ntests[\\\"response has WWW-Authenticate header\\\"] = (postman.getResponseHeader('WWW-Authenticate'));\\n\\nvar authenticateHeader = postman.getResponseHeader('WWW-Authenticate'),\\n    realmStart = authenticateHeader.indexOf('\\\"',authenticateHeader.indexOf(\\\"realm\\\")) + 1 ,\\n    realmEnd = authenticateHeader.indexOf('\\\"',realmStart),\\n    realm = authenticateHeader.slice(realmStart,realmEnd),\\n    nonceStart = authenticateHeader.indexOf('\\\"',authenticateHeader.indexOf(\\\"nonce\\\")) + 1,\\n    nonceEnd = authenticateHeader.indexOf('\\\"',nonceStart),\\n    nonce = authenticateHeader.slice(nonceStart,nonceEnd);\\n    \\npostman.setGlobalVariable('echo_digest_realm', realm);\\npostman.setGlobalVariable('echo_digest_nonce', nonce);\"\n              }\n            }\n          ],\n          \"request\": {\n            \"url\": \"https://postman-echo.com/digest-auth\",\n            \"method\": \"GET\",\n            \"header\": [],\n            \"body\": {\n              \"mode\": \"formdata\",\n              \"formdata\": [\n                {\n                  \"key\": \"code\",\n                  \"value\": \"xWnkliVQJURqB2x1\",\n                  \"type\": \"text\",\n                  \"enabled\": true\n                },\n                {\n                  \"key\": \"grant_type\",\n                  \"value\": \"authorization_code\",\n                  \"type\": \"text\",\n                  \"enabled\": true\n                },\n                {\n                  \"key\": \"redirect_uri\",\n                  \"value\": \"https://www.getpostman.com/oauth2/callback\",\n                  \"type\": \"text\",\n                  \"enabled\": true\n                },\n                {\n                  \"key\": \"client_id\",\n                  \"value\": \"abc123\",\n                  \"type\": \"text\",\n                  \"enabled\": true\n                },\n                {\n                  \"key\": \"client_secret\",\n                  \"value\": \"ssh-secret\",\n                  \"type\": \"text\",\n                  \"enabled\": true\n                }\n              ]\n            },\n            \"description\": \"Performing a simple `GET` request to this endpoint returns status code `401 Unauthorized` with `WWW-Authenticate` header containing information to successfully authenticate subsequent requests.\\nThe `WWW-Authenticate` header must be processed to extract `realm` and `nonce` values to hash subsequent requests.\\n\\nWhen this request is executed within Postman, the script attached with this request does the hard work of extracting realm and nonce from the header and set it as [global variables](https://www.getpostman.com/docs/environments#global-variables) named `echo_digest_nonce` and `echo_digest_realm`.\\nThese variables are re-used in subsequent request for seamless integration of the two requests.\"\n          },\n          \"response\": []\n        },\n        {\n          \"id\": \"5206c7ad-b9b4-a314-0f4a-03772e8e15f8\",\n          \"name\": \"DigestAuth Success\",\n          \"event\": [\n            {\n              \"listen\": \"test\",\n              \"script\": {\n                \"type\": \"text/javascript\",\n                \"exec\": \"tests[\\\"response code is 200\\\"] = responseCode.code === 200;\\ntests[\\\"body contains authenticated\\\"] = responseBody.has(\\\"authenticated\\\");\"\n              }\n            }\n          ],\n          \"request\": {\n            \"auth\": {\n              \"type\": \"digest\",\n              \"digest\": {\n                \"algorithm\": \"MD5\",\n                \"username\": \"postman\",\n                \"realm\": \"{{echo_digest_realm}}\",\n                \"password\": \"password\",\n                \"nonce\": \"{{echo_digest_nonce}}\",\n                \"nonceCount\": \"\",\n                \"clientNonce\": \"\",\n                \"opaque\": \"\",\n                \"qop\": \"\"\n              }\n            },\n            \"url\": \"https://postman-echo.com/digest-auth\",\n            \"method\": \"GET\",\n            \"header\": [\n              {\n                \"key\": \"Authorization\",\n                \"value\": \"Digest username=\\\"postman\\\", realm=\\\"Users\\\", nonce=\\\"ni1LiL0O37PRRhofWdCLmwFsnEtH1lew\\\", uri=\\\"/digest-auth\\\", response=\\\"254679099562cf07df9b6f5d8d15db44\\\", opaque=\\\"\\\"\",\n                \"description\": \"\"\n              }\n            ],\n            \"body\": {\n              \"mode\": \"formdata\",\n              \"formdata\": []\n            },\n            \"description\": \"This endpoint sends a hashed Digest Authorization header to gain access to a valid `200 Ok` response code. In Postman, it uses the stored [global variables](https://www.getpostman.com/docs/environments#gloval-variables), `echo_digest_realm` and `echo_digest_nonce`, to generate the hashed authorisation header.\\n\\nWithin Postman, for this request to successfully authenticate, running the previous request \\\"DigestAuth Request\\\" stores the relevant information within the global variables.\"\n          },\n          \"response\": [\n            {\n              \"name\": \"200\",\n              \"status\": \"OK\",\n              \"code\": 200,\n              \"header\": [\n                {\n                  \"name\": \"Access-Control-Allow-Credentials\",\n                  \"key\": \"Access-Control-Allow-Credentials\",\n                  \"value\": \"\",\n                  \"description\": \"\"\n                },\n                {\n                  \"name\": \"Access-Control-Allow-Headers\",\n                  \"key\": \"Access-Control-Allow-Headers\",\n                  \"value\": \"\",\n                  \"description\": \"\"\n                },\n                {\n                  \"name\": \"Access-Control-Allow-Methods\",\n                  \"key\": \"Access-Control-Allow-Methods\",\n                  \"value\": \"\",\n                  \"description\": \"\"\n                },\n                {\n                  \"name\": \"Access-Control-Allow-Origin\",\n                  \"key\": \"Access-Control-Allow-Origin\",\n                  \"value\": \"\",\n                  \"description\": \"\"\n                },\n                {\n                  \"name\": \"Connection\",\n                  \"key\": \"Connection\",\n                  \"value\": \"keep-alive\",\n                  \"description\": \"\"\n                },\n                {\n                  \"name\": \"Content-Encoding\",\n                  \"key\": \"Content-Encoding\",\n                  \"value\": \"gzip\",\n                  \"description\": \"\"\n                },\n                {\n                  \"name\": \"Content-Length\",\n                  \"key\": \"Content-Length\",\n                  \"value\": \"42\",\n                  \"description\": \"\"\n                },\n                {\n                  \"name\": \"Content-Type\",\n                  \"key\": \"Content-Type\",\n                  \"value\": \"application/json; charset=utf-8\",\n                  \"description\": \"\"\n                },\n                {\n                  \"name\": \"Date\",\n                  \"key\": \"Date\",\n                  \"value\": \"Thu, 29 Oct 2015 06:17:51 GMT\",\n                  \"description\": \"\"\n                },\n                {\n                  \"name\": \"Server\",\n                  \"key\": \"Server\",\n                  \"value\": \"nginx/1.6.2\",\n                  \"description\": \"\"\n                },\n                {\n                  \"name\": \"Vary\",\n                  \"key\": \"Vary\",\n                  \"value\": \"Accept-Encoding\",\n                  \"description\": \"\"\n                },\n                {\n                  \"name\": \"X-Powered-By\",\n                  \"key\": \"X-Powered-By\",\n                  \"value\": \"Sails <sailsjs.org>\",\n                  \"description\": \"\"\n                }\n              ],\n              \"cookie\": [],\n              \"responseTime\": \"9843\",\n              \"body\": \"{\\\"authenticated\\\":true}\"\n            }\n          ]\n        }\n      ]\n    },\n    {\n      \"_postman_id\": \"e6842700-03cb-2df4-ecb5-23a1c4b1a8ae\",\n      \"name\": \"Auth: Others\",\n      \"description\": \"\",\n      \"item\": [\n        {\n          \"id\": \"2924e4d9-7f5d-23b4-03fd-1a8d3ae69a22\",\n          \"name\": \"Basic Auth\",\n          \"event\": [\n            {\n              \"listen\": \"test\",\n              \"script\": {\n                \"type\": \"text/javascript\",\n                \"exec\": \"tests[\\\"response code is 200\\\"] = responseCode.code === 200;\\ntests[\\\"Body contains authenticated\\\"] = responseBody.has(\\\"authenticated\\\");\"\n              }\n            }\n          ],\n          \"request\": {\n            \"auth\": {\n              \"type\": \"basic\",\n              \"basic\": {\n                \"username\": \"postman\",\n                \"password\": \"password\",\n                \"saveHelperData\": true,\n                \"showPassword\": false\n              }\n            },\n            \"url\": \"https://postman-echo.com/basic-auth\",\n            \"method\": \"GET\",\n            \"header\": [\n              {\n                \"key\": \"Authorization\",\n                \"value\": \"Basic cG9zdG1hbjpwYXNzd29yZA==\",\n                \"description\": \"\"\n              }\n            ],\n            \"body\": {\n              \"mode\": \"formdata\",\n              \"formdata\": []\n            },\n            \"description\": \"This endpoint simulates a **basic-auth** protected endpoint. \\nThe endpoint accepts a default username and password and returns a status code of `200 ok` only if the same is provided. \\nOtherwise it will return a status code `401 unauthorized`.\\n\\n> Username: `postman`\\n> \\n> Password: `password`\\n\\nTo use this endpoint, send a request with the header `Authorization: Basic cG9zdG1hbjpwYXNzd29yZA==`. \\nThe cryptic latter half of the header value is a base64 encoded concatenation of the default username and password. \\nUsing Postman, to send this request, you can simply fill in the username and password in the \\\"Authorization\\\" tab and Postman will do the rest for you.\\n\\nTo know more about basic authentication, refer to the [Basic Access Authentication](https://en.wikipedia.org/wiki/Basic_access_authentication) wikipedia article.\\nThe article on [authentication helpers](https://www.getpostman.com/docs/helpers#basic-auth) elaborates how to use the same within the Postman app.\"\n          },\n          \"response\": [\n            {\n              \"name\": \"401\",\n              \"status\": \"Unauthorized\",\n              \"code\": 401,\n              \"header\": [\n                {\n                  \"name\": \"Access-Control-Allow-Credentials\",\n                  \"key\": \"Access-Control-Allow-Credentials\",\n                  \"value\": \"\",\n                  \"description\": \"\"\n                },\n                {\n                  \"name\": \"Access-Control-Allow-Headers\",\n                  \"key\": \"Access-Control-Allow-Headers\",\n                  \"value\": \"\",\n                  \"description\": \"\"\n                },\n                {\n                  \"name\": \"Access-Control-Allow-Methods\",\n                  \"key\": \"Access-Control-Allow-Methods\",\n                  \"value\": \"\",\n                  \"description\": \"\"\n                },\n                {\n                  \"name\": \"Access-Control-Allow-Origin\",\n                  \"key\": \"Access-Control-Allow-Origin\",\n                  \"value\": \"\",\n                  \"description\": \"\"\n                },\n                {\n                  \"name\": \"Connection\",\n                  \"key\": \"Connection\",\n                  \"value\": \"keep-alive\",\n                  \"description\": \"\"\n                },\n                {\n                  \"name\": \"Date\",\n                  \"key\": \"Date\",\n                  \"value\": \"Sat, 31 Oct 2015 06:38:51 GMT\",\n                  \"description\": \"\"\n                },\n                {\n                  \"name\": \"Server\",\n                  \"key\": \"Server\",\n                  \"value\": \"nginx/1.6.2\",\n                  \"description\": \"\"\n                },\n                {\n                  \"name\": \"WWW-Authenticate\",\n                  \"key\": \"WWW-Authenticate\",\n                  \"value\": \"Basic realm=\\\"Users\\\"\",\n                  \"description\": \"\"\n                },\n                {\n                  \"name\": \"X-Powered-By\",\n                  \"key\": \"X-Powered-By\",\n                  \"value\": \"Sails <sailsjs.org>\",\n                  \"description\": \"\"\n                },\n                {\n                  \"name\": \"transfer-encoding\",\n                  \"key\": \"transfer-encoding\",\n                  \"value\": \"chunked\",\n                  \"description\": \"\"\n                }\n              ],\n              \"cookie\": [],\n              \"responseTime\": \"276\",\n              \"body\": \"Unauthorized\"\n            },\n            {\n              \"name\": \"200\",\n              \"status\": \"OK\",\n              \"code\": 200,\n              \"header\": [\n                {\n                  \"name\": \"Access-Control-Allow-Credentials\",\n                  \"key\": \"Access-Control-Allow-Credentials\",\n                  \"value\": \"\",\n                  \"description\": \"\"\n                },\n                {\n                  \"name\": \"Access-Control-Allow-Headers\",\n                  \"key\": \"Access-Control-Allow-Headers\",\n                  \"value\": \"\",\n                  \"description\": \"\"\n                },\n                {\n                  \"name\": \"Access-Control-Allow-Methods\",\n                  \"key\": \"Access-Control-Allow-Methods\",\n                  \"value\": \"\",\n                  \"description\": \"\"\n                },\n                {\n                  \"name\": \"Access-Control-Allow-Origin\",\n                  \"key\": \"Access-Control-Allow-Origin\",\n                  \"value\": \"\",\n                  \"description\": \"\"\n                },\n                {\n                  \"name\": \"Connection\",\n                  \"key\": \"Connection\",\n                  \"value\": \"keep-alive\",\n                  \"description\": \"\"\n                },\n                {\n                  \"name\": \"Content-Encoding\",\n                  \"key\": \"Content-Encoding\",\n                  \"value\": \"gzip\",\n                  \"description\": \"\"\n                },\n                {\n                  \"name\": \"Content-Length\",\n                  \"key\": \"Content-Length\",\n                  \"value\": \"42\",\n                  \"description\": \"\"\n                },\n                {\n                  \"name\": \"Content-Type\",\n                  \"key\": \"Content-Type\",\n                  \"value\": \"application/json; charset=utf-8\",\n                  \"description\": \"\"\n                },\n                {\n                  \"name\": \"Date\",\n                  \"key\": \"Date\",\n                  \"value\": \"Sat, 31 Oct 2015 06:38:25 GMT\",\n                  \"description\": \"\"\n                },\n                {\n                  \"name\": \"Server\",\n                  \"key\": \"Server\",\n                  \"value\": \"nginx/1.6.2\",\n                  \"description\": \"\"\n                },\n                {\n                  \"name\": \"Vary\",\n                  \"key\": \"Vary\",\n                  \"value\": \"Accept-Encoding\",\n                  \"description\": \"\"\n                },\n                {\n                  \"name\": \"X-Powered-By\",\n                  \"key\": \"X-Powered-By\",\n                  \"value\": \"Sails <sailsjs.org>\",\n                  \"description\": \"\"\n                }\n              ],\n              \"cookie\": [],\n              \"responseTime\": \"377\",\n              \"body\": \"{\\\"authenticated\\\":true}\"\n            }\n          ]\n        },\n        {\n          \"id\": \"36314ffc-e6cc-d277-a3ce-1ecf1b35573f\",\n          \"name\": \"OAuth1.0 Verify Signature\",\n          \"event\": [\n            {\n              \"listen\": \"test\",\n              \"script\": {\n                \"type\": \"text/javascript\",\n                \"exec\": \"tests[\\\"response code is 200\\\"] = responseCode.code === 200;\\nvar body = JSON.parse(responseBody);\\ntests[\\\"Body contains status pass\\\"] = body[\\\"status\\\"] == \\\"pass\\\"\"\n              }\n            }\n          ],\n          \"request\": {\n            \"url\": \"https://postman-echo.com/oauth1\",\n            \"method\": \"GET\",\n            \"auth\": {\n              \"type\": \"oauth1\",\n              \"oauth1\": {\n                \"consumerKey\": \"RKCGzna7bv9YD57c\",\n                \"consumerSecret\": \"D+EdQ-gs$-%@2Nu7\",\n                \"signatureMethod\": \"HMAC-SHA1\",\n                \"version\": \"1.0\",\n                \"addParamsToHeader\": true,\n                \"addEmptyParamsToSign\": false\n              }\n            },\n            \"body\": {\n              \"mode\": \"formdata\",\n              \"formdata\": [\n                {\n                  \"key\": \"code\",\n                  \"value\": \"xWnkliVQJURqB2x1\",\n                  \"type\": \"text\",\n                  \"enabled\": true\n                },\n                {\n                  \"key\": \"grant_type\",\n                  \"value\": \"authorization_code\",\n                  \"type\": \"text\",\n                  \"enabled\": true\n                },\n                {\n                  \"key\": \"redirect_uri\",\n                  \"value\": \"https://www.getpostman.com/oauth2/callback\",\n                  \"type\": \"text\",\n                  \"enabled\": true\n                },\n                {\n                  \"key\": \"client_id\",\n                  \"value\": \"abc123\",\n                  \"type\": \"text\",\n                  \"enabled\": true\n                },\n                {\n                  \"key\": \"client_secret\",\n                  \"value\": \"ssh-secret\",\n                  \"type\": \"text\",\n                  \"enabled\": true\n                }\n              ]\n            },\n            \"description\": \"OAuth1.0a is a specification that defines a protocol that can be used by one\\nservice to access \\\"protected\\\" resources (endpoints) on another service. A\\nmajor part of OAuth1.0 is HTTP Request Signing. This endpoint allows you to \\ncheck whether the request calculation works properly in the client. \\n\\nThe endpoint supports the HTTP ``Authorization`` header. In case the signature\\nverification fails, the endpoint provides the four debug values,\\n\\n* ``base_uri``\\n* ``normalized_param_string``\\n* ``base_string``\\n* ``signing_key``\\n\\nFor more details about these parameters, check the [OAuth1.0a Specification](http://oauth.net/core/1.0a/)\\n\\nIn order to use this endpoint, you can set the following values:\\n\\n> Consumer Key: ``RKCGzna7bv9YD57c``\\n>\\n> Consumer Secret: ``D+EdQ-gs$-%@2Nu7``\\n\\nIf you are using Postman, also check the \\\"Add params to header\\\" and \\n\\\"Auto add parameters\\\" boxes.\"\n          },\n          \"response\": []\n        }\n      ]\n    },\n    {\n      \"_postman_id\": \"086c2ad2-522d-5ab9-59b5-b9ed56883a64\",\n      \"name\": \"Cookies\",\n      \"description\": \"The cookie related endpoints allow one to get, set and delete simple cookies.\\n\\nCookies are small snippets of information that is stored in the browser and sent back to the server with every subsequent requests in order to store useful information between requests.\\nIf you want to know more about cookies, read the [HTTP Cookie](https://en.wikipedia.org/wiki/HTTP_cookie) article on wikipedia.\",\n      \"item\": [\n        {\n          \"id\": \"9c2ef092-5e81-a934-3d8a-a16f2bd7f262\",\n          \"name\": \"Set Cookies\",\n          \"event\": [\n            {\n              \"listen\": \"test\",\n              \"script\": {\n                \"type\": \"text/javascript\",\n                \"exec\": \"tests[\\\"Status code is 200\\\"] = responseCode.code === 200;\\ntests[\\\"Body contains cookies\\\"] = responseBody.has(\\\"cookies\\\");\\nvar body = JSON.parse(responseBody);\\ntests[\\\"Body contains cookie foo1\\\"] = 'foo1' in body.cookies;\\ntests[\\\"Body contains cookie foo2\\\"] = 'foo2' in body.cookies;\\n\\n\"\n              }\n            }\n          ],\n          \"request\": {\n            \"url\": \"https://postman-echo.com/cookies/set?foo1=bar1&foo2=bar2\",\n            \"method\": \"GET\",\n            \"header\": [],\n            \"body\": {\n              \"mode\": \"formdata\",\n              \"formdata\": []\n            },\n            \"description\": \"The cookie setter endpoint accepts a list of cookies and their values as part of URL parameters of a `GET` request. These cookies are saved and can be subsequently retrieved or deleted. The response of this request returns a JSON with all cookies listed.\\n\\nTo set your own set of cookies, simply replace the URL parameters \\\"foo1=bar1&foo2=bar2\\\" with your own set of key-value pairs.\"\n          },\n          \"response\": [\n            {\n              \"name\": \"Cookies\",\n              \"status\": \"OK\",\n              \"code\": 200,\n              \"header\": [\n                {\n                  \"name\": \"Access-Control-Allow-Credentials\",\n                  \"key\": \"Access-Control-Allow-Credentials\",\n                  \"value\": \"\",\n                  \"description\": \"\"\n                },\n                {\n                  \"name\": \"Access-Control-Allow-Headers\",\n                  \"key\": \"Access-Control-Allow-Headers\",\n                  \"value\": \"\",\n                  \"description\": \"\"\n                },\n                {\n                  \"name\": \"Access-Control-Allow-Methods\",\n                  \"key\": \"Access-Control-Allow-Methods\",\n                  \"value\": \"\",\n                  \"description\": \"\"\n                },\n                {\n                  \"name\": \"Access-Control-Allow-Origin\",\n                  \"key\": \"Access-Control-Allow-Origin\",\n                  \"value\": \"\",\n                  \"description\": \"\"\n                },\n                {\n                  \"name\": \"Connection\",\n                  \"key\": \"Connection\",\n                  \"value\": \"keep-alive\",\n                  \"description\": \"\"\n                },\n                {\n                  \"name\": \"Content-Encoding\",\n                  \"key\": \"Content-Encoding\",\n                  \"value\": \"gzip\",\n                  \"description\": \"\"\n                },\n                {\n                  \"name\": \"Content-Length\",\n                  \"key\": \"Content-Length\",\n                  \"value\": \"51\",\n                  \"description\": \"\"\n                },\n                {\n                  \"name\": \"Content-Type\",\n                  \"key\": \"Content-Type\",\n                  \"value\": \"application/json; charset=utf-8\",\n                  \"description\": \"\"\n                },\n                {\n                  \"name\": \"Date\",\n                  \"key\": \"Date\",\n                  \"value\": \"Thu, 29 Oct 2015 06:15:28 GMT\",\n                  \"description\": \"\"\n                },\n                {\n                  \"name\": \"Server\",\n                  \"key\": \"Server\",\n                  \"value\": \"nginx/1.6.2\",\n                  \"description\": \"\"\n                },\n                {\n                  \"name\": \"Vary\",\n                  \"key\": \"Vary\",\n                  \"value\": \"Accept-Encoding\",\n                  \"description\": \"\"\n                },\n                {\n                  \"name\": \"X-Powered-By\",\n                  \"key\": \"X-Powered-By\",\n                  \"value\": \"Sails <sailsjs.org>\",\n                  \"description\": \"\"\n                }\n              ],\n              \"cookie\": [],\n              \"responseTime\": \"3063\",\n              \"body\": \"{\\\"cookies\\\":{\\\"foo1\\\":\\\"bar\\\",\\\"foo2\\\":\\\"bar\\\"}}\"\n            }\n          ]\n        },\n        {\n          \"id\": \"a317d5a1-7ad5-0eb0-889d-bfe9c34f1787\",\n          \"name\": \"Get Cookies\",\n          \"event\": [\n            {\n              \"listen\": \"test\",\n              \"script\": {\n                \"type\": \"text/javascript\",\n                \"exec\": \"tests[\\\"Status code is 200\\\"] = responseCode.code === 200;\\ntests[\\\"Body contains cookies\\\"] = responseBody.has(\\\"cookies\\\");\\nvar body = JSON.parse(responseBody);\\ntests[\\\"Body contains cookie foo2\\\"] = 'foo2' in body.cookies;\"\n              }\n            }\n          ],\n          \"request\": {\n            \"url\": \"https://postman-echo.com/cookies\",\n            \"method\": \"GET\",\n            \"header\": [],\n            \"body\": {\n              \"mode\": \"formdata\",\n              \"formdata\": []\n            },\n            \"description\": \"Use this endpoint to get a list of all cookies that are stored with respect to this domain. Whatever key-value pairs that has been previously set by calling the \\\"Set Cookies\\\" endpoint, will be returned as response JSON.\"\n          },\n          \"response\": [\n            {\n              \"name\": \"Cookies\",\n              \"status\": \"OK\",\n              \"code\": 200,\n              \"header\": [\n                {\n                  \"name\": \"Access-Control-Allow-Credentials\",\n                  \"key\": \"Access-Control-Allow-Credentials\",\n                  \"value\": \"\",\n                  \"description\": \"\"\n                },\n                {\n                  \"name\": \"Access-Control-Allow-Headers\",\n                  \"key\": \"Access-Control-Allow-Headers\",\n                  \"value\": \"\",\n                  \"description\": \"\"\n                },\n                {\n                  \"name\": \"Access-Control-Allow-Methods\",\n                  \"key\": \"Access-Control-Allow-Methods\",\n                  \"value\": \"\",\n                  \"description\": \"\"\n                },\n                {\n                  \"name\": \"Access-Control-Allow-Origin\",\n                  \"key\": \"Access-Control-Allow-Origin\",\n                  \"value\": \"\",\n                  \"description\": \"\"\n                },\n                {\n                  \"name\": \"Connection\",\n                  \"key\": \"Connection\",\n                  \"value\": \"keep-alive\",\n                  \"description\": \"\"\n                },\n                {\n                  \"name\": \"Content-Encoding\",\n                  \"key\": \"Content-Encoding\",\n                  \"value\": \"gzip\",\n                  \"description\": \"\"\n                },\n                {\n                  \"name\": \"Content-Length\",\n                  \"key\": \"Content-Length\",\n                  \"value\": \"46\",\n                  \"description\": \"\"\n                },\n                {\n                  \"name\": \"Content-Type\",\n                  \"key\": \"Content-Type\",\n                  \"value\": \"application/json; charset=utf-8\",\n                  \"description\": \"\"\n                },\n                {\n                  \"name\": \"Date\",\n                  \"key\": \"Date\",\n                  \"value\": \"Thu, 29 Oct 2015 06:16:29 GMT\",\n                  \"description\": \"\"\n                },\n                {\n                  \"name\": \"Server\",\n                  \"key\": \"Server\",\n                  \"value\": \"nginx/1.6.2\",\n                  \"description\": \"\"\n                },\n                {\n                  \"name\": \"Vary\",\n                  \"key\": \"Vary\",\n                  \"value\": \"Accept-Encoding\",\n                  \"description\": \"\"\n                },\n                {\n                  \"name\": \"X-Powered-By\",\n                  \"key\": \"X-Powered-By\",\n                  \"value\": \"Sails <sailsjs.org>\",\n                  \"description\": \"\"\n                }\n              ],\n              \"cookie\": [],\n              \"responseTime\": \"462\",\n              \"body\": \"{\\\"cookies\\\":{\\\"foo2\\\":\\\"bar\\\"}}\"\n            }\n          ]\n        },\n        {\n          \"id\": \"2dccf8a7-7729-6acf-6888-ef04cbb178fd\",\n          \"name\": \"Delete Cookies\",\n          \"event\": [\n            {\n              \"listen\": \"test\",\n              \"script\": {\n                \"type\": \"text/javascript\",\n                \"exec\": \"tests[\\\"Status code is 200\\\"] = responseCode.code === 200;\\ntests[\\\"Body contains key cookies\\\"] = responseBody.has(\\\"cookies\\\");\\nvar body = JSON.parse(responseBody);\\ntests[\\\"Body does not contain cookie foo2\\\"] = !('foo1' in body.cookies);\"\n              }\n            }\n          ],\n          \"request\": {\n            \"url\": \"https://postman-echo.com/cookies/delete?foo1&foo2\",\n            \"method\": \"GET\",\n            \"header\": [],\n            \"body\": {\n              \"mode\": \"formdata\",\n              \"formdata\": []\n            },\n            \"description\": \"One or more cookies that has been set for this domain can be deleted by providing the cookie names as part of the URL parameter. The response of this request is a JSON containing the list of currently set cookies.\"\n          },\n          \"response\": [\n            {\n              \"name\": \"Cookies Response\",\n              \"status\": \"OK\",\n              \"code\": 200,\n              \"header\": [\n                {\n                  \"name\": \"Access-Control-Allow-Credentials\",\n                  \"key\": \"Access-Control-Allow-Credentials\",\n                  \"value\": \"\",\n                  \"description\": \"\"\n                },\n                {\n                  \"name\": \"Access-Control-Allow-Headers\",\n                  \"key\": \"Access-Control-Allow-Headers\",\n                  \"value\": \"\",\n                  \"description\": \"\"\n                },\n                {\n                  \"name\": \"Access-Control-Allow-Methods\",\n                  \"key\": \"Access-Control-Allow-Methods\",\n                  \"value\": \"\",\n                  \"description\": \"\"\n                },\n                {\n                  \"name\": \"Access-Control-Allow-Origin\",\n                  \"key\": \"Access-Control-Allow-Origin\",\n                  \"value\": \"\",\n                  \"description\": \"\"\n                },\n                {\n                  \"name\": \"Connection\",\n                  \"key\": \"Connection\",\n                  \"value\": \"keep-alive\",\n                  \"description\": \"\"\n                },\n                {\n                  \"name\": \"Content-Encoding\",\n                  \"key\": \"Content-Encoding\",\n                  \"value\": \"gzip\",\n                  \"description\": \"\"\n                },\n                {\n                  \"name\": \"Content-Length\",\n                  \"key\": \"Content-Length\",\n                  \"value\": \"46\",\n                  \"description\": \"\"\n                },\n                {\n                  \"name\": \"Content-Type\",\n                  \"key\": \"Content-Type\",\n                  \"value\": \"application/json; charset=utf-8\",\n                  \"description\": \"\"\n                },\n                {\n                  \"name\": \"Date\",\n                  \"key\": \"Date\",\n                  \"value\": \"Thu, 29 Oct 2015 06:16:00 GMT\",\n                  \"description\": \"\"\n                },\n                {\n                  \"name\": \"Server\",\n                  \"key\": \"Server\",\n                  \"value\": \"nginx/1.6.2\",\n                  \"description\": \"\"\n                },\n                {\n                  \"name\": \"Vary\",\n                  \"key\": \"Vary\",\n                  \"value\": \"Accept-Encoding\",\n                  \"description\": \"\"\n                },\n                {\n                  \"name\": \"X-Powered-By\",\n                  \"key\": \"X-Powered-By\",\n                  \"value\": \"Sails <sailsjs.org>\",\n                  \"description\": \"\"\n                }\n              ],\n              \"cookie\": [],\n              \"responseTime\": \"1417\",\n              \"body\": \"{\\\"cookies\\\":{\\\"foo2\\\":\\\"bar\\\"}}\"\n            }\n          ]\n        }\n      ]\n    },\n    {\n      \"_postman_id\": \"9847133e-9424-bf2c-be77-db510b2fdbba\",\n      \"name\": \"Headers\",\n      \"description\": \"The following set of endpoints allow one to see the headers being sent as part of a request and to get a custom set of headers as part of response.\\n\\nHTTP header fields provide required information about the request or response, or about the object sent in the message body. Both request headers and response headers can be controlled using these endpoints.\",\n      \"item\": [\n        {\n          \"id\": \"1b462a0b-8f0d-2b90-7f3b-b956985904d1\",\n          \"name\": \"Request Headers\",\n          \"event\": [\n            {\n              \"listen\": \"test\",\n              \"script\": {\n                \"type\": \"text/javascript\",\n                \"exec\": \"tests[\\\"Body contains headers\\\"] = responseBody.has(\\\"headers\\\");\\n\\nvar data = JSON.parse(responseBody).headers;\\n\\ntests[\\\"Header contains host\\\"] = \\\"host\\\" in data;\"\n              }\n            }\n          ],\n          \"request\": {\n            \"url\": \"https://postman-echo.com/headers\",\n            \"method\": \"GET\",\n            \"header\": [],\n            \"body\": {\n              \"mode\": \"formdata\",\n              \"formdata\": []\n            },\n            \"description\": \"A `GET` request to this endpoint returns the list of all request headers as part of the response JSON.\\nIn Postman, sending your own set of headers through the [Headers tab](https://www.getpostman.com/docs/requests#headers) will reveal the headers as part of the response.\"\n          },\n          \"response\": []\n        },\n        {\n          \"id\": \"7c21464f-607c-5ca4-729f-a233faa5b180\",\n          \"name\": \"Response Headers\",\n          \"event\": [\n            {\n              \"listen\": \"test\",\n              \"script\": {\n                \"type\": \"text/javascript\",\n                \"exec\": \"tests[\\\"Body contains Content-Type\\\"] = responseBody.has(\\\"Content-Type\\\");\\ntests[\\\"Body contains Server\\\"] = responseBody.has(\\\"Server\\\");\"\n              }\n            }\n          ],\n          \"request\": {\n            \"url\": \"https://postman-echo.com/response-headers?Content-Type=text/html&Server=apibin\",\n            \"method\": \"GET\",\n            \"header\": [],\n            \"body\": {\n              \"mode\": \"formdata\",\n              \"formdata\": [\n                {\n                  \"key\": \"code\",\n                  \"value\": \"xWnkliVQJURqB2x1\",\n                  \"type\": \"text\",\n                  \"enabled\": true\n                },\n                {\n                  \"key\": \"grant_type\",\n                  \"value\": \"authorization_code\",\n                  \"type\": \"text\",\n                  \"enabled\": true\n                },\n                {\n                  \"key\": \"redirect_uri\",\n                  \"value\": \"https://www.getpostman.com/oauth2/callback\",\n                  \"type\": \"text\",\n                  \"enabled\": true\n                },\n                {\n                  \"key\": \"client_id\",\n                  \"value\": \"abc123\",\n                  \"type\": \"text\",\n                  \"enabled\": true\n                },\n                {\n                  \"key\": \"client_secret\",\n                  \"value\": \"ssh-secret\",\n                  \"type\": \"text\",\n                  \"enabled\": true\n                }\n              ]\n            },\n            \"description\": \"This endpoint causes the server to send custom set of response headers. Providing header values as part of the URL parameters of a `GET` request to this endpoint returns the same as part of response header.\\n\\nTo send your own set of headers, simply add or replace the the URL parameters with your own set.\"\n          },\n          \"response\": []\n        }\n      ]\n    },\n    {\n      \"_postman_id\": \"6a8fe6da-b3ca-1c4e-e096-550b501a3e91\",\n      \"name\": \"Request Methods\",\n      \"description\": \"HTTP has multiple request \\\"verbs\\\", such as `GET`, `PUT`, `POST`, `DELETE`,\\n`PATCH`, `HEAD`, etc. \\n\\nAn HTTP Method (verb) defines how a request should be interpreted by a server. \\nThe endpoints in this section demonstrate various HTTP Verbs. Postman supports \\nall the HTTP Verbs, including some rarely used ones, such as `PROPFIND`, `UNLINK`, \\netc.\\n\\nFor details about HTTP Verbs, refer to [RFC 2616](http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9)\\n\",\n      \"item\": [\n        {\n          \"id\": \"e9f4387b-5b32-ae3c-cae3-f8470d1c6b1f\",\n          \"name\": \"GET Request \",\n          \"event\": [\n            {\n              \"listen\": \"test\",\n              \"script\": {\n                \"type\": \"text/javascript\",\n                \"exec\": \"tests[\\\"Body contains headers\\\"] = responseBody.has(\\\"headers\\\");\\ntests[\\\"Body contains args\\\"] = responseBody.has(\\\"args\\\");\\ntests[\\\"Body contains url\\\"] = responseBody.has(\\\"url\\\");\\n\\nvar data = JSON.parse(responseBody)\\n\\ntests[\\\"Args key contains argument passed as url parameter\\\"] = 'test' in data.args\"\n              }\n            }\n          ],\n          \"request\": {\n            \"url\": \"https://postman-echo.com/get?test=123\",\n            \"method\": \"GET\",\n            \"header\": [],\n            \"body\": {\n              \"mode\": \"formdata\",\n              \"formdata\": [\n                {\n                  \"key\": \"code\",\n                  \"value\": \"xWnkliVQJURqB2x1\",\n                  \"type\": \"text\",\n                  \"enabled\": true\n                },\n                {\n                  \"key\": \"grant_type\",\n                  \"value\": \"authorization_code\",\n                  \"type\": \"text\",\n                  \"enabled\": true\n                },\n                {\n                  \"key\": \"redirect_uri\",\n                  \"value\": \"https://www.getpostman.com/oauth2/callback\",\n                  \"type\": \"text\",\n                  \"enabled\": true\n                },\n                {\n                  \"key\": \"client_id\",\n                  \"value\": \"abc123\",\n                  \"type\": \"text\",\n                  \"enabled\": true\n                },\n                {\n                  \"key\": \"client_secret\",\n                  \"value\": \"ssh-secret\",\n                  \"type\": \"text\",\n                  \"enabled\": true\n                }\n              ]\n            },\n            \"description\": \"The HTTP `GET` request method is meant to retrieve data from a server. The data\\nis identified by a unique URI (Uniform Resource Identifier). \\n\\nA `GET` request can pass parameters to the server using \\\"Query String \\nParameters\\\". For example, in the following request,\\n\\n> http://example.com/hi/there?hand=wave\\n\\nThe parameter \\\"hand\\\" has the value \\\"wave\\\".\\n\\nThis endpoint echoes the HTTP headers, request parameters and the complete\\nURI requested.\"\n          },\n          \"response\": []\n        },\n        {\n          \"id\": \"4dbb1437-dd69-7ead-d072-656c0cf303e8\",\n          \"name\": \"POST Request\",\n          \"event\": [\n            {\n              \"listen\": \"test\",\n              \"script\": {\n                \"type\": \"text/javascript\",\n                \"exec\": \"var responseJSON;\\n\\ntry { responseJSON = JSON.parse(responseBody); }\\ncatch (e) { }\\n\\n\\ntests[\\\"response has data\\\"] = responseJSON && responseJSON.data && (responseJSON.data.length === 256);\\ntests[\\\"content-type equals text/plain\\\"] = responseJSON && responseJSON.headers && (responseJSON.headers[\\\"content-type\\\"] === 'text/plain');\"\n              }\n            }\n          ],\n          \"request\": {\n            \"url\": \"https://postman-echo.com/post\",\n            \"method\": \"POST\",\n            \"header\": [\n              {\n                \"key\": \"Content-Type\",\n                \"value\": \"text/plain\",\n                \"description\": \"\"\n              }\n            ],\n            \"body\": {\n              \"mode\": \"raw\",\n              \"raw\": \"Duis posuere augue vel cursus pharetra. In luctus a ex nec pretium. Praesent neque quam, tincidunt nec leo eget, rutrum vehicula magna.\\nMaecenas consequat elementum elit, id semper sem tristique et. Integer pulvinar enim quis consectetur interdum volutpat.\"\n            },\n            \"description\": \"The HTTP `POST` request method is meant to transfer data to a server \\n(and elicit a response). What data is returned depends on the implementation\\nof the server.\\n\\nA `POST` request can pass parameters to the server using \\\"Query String \\nParameters\\\", as well as the Request Body. For example, in the following request,\\n\\n> POST /hi/there?hand=wave\\n>\\n> <request-body>\\n\\nThe parameter \\\"hand\\\" has the value \\\"wave\\\". The request body can be in multiple\\nformats. These formats are defined by the MIME type of the request. The MIME \\nType can be set using the ``Content-Type`` HTTP header. The most commonly used \\nMIME types are:\\n\\n* `multipart/form-data`\\n* `application/x-www-form-urlencoded`\\n* `application/json`\\n\\nThis endpoint echoes the HTTP headers, request parameters, the contents of\\nthe request body and the complete URI requested.\"\n          },\n          \"response\": []\n        },\n        {\n          \"id\": \"21400a93-c64f-87ad-adae-76e06408fa89\",\n          \"name\": \"PUT Request\",\n          \"event\": [\n            {\n              \"listen\": \"test\",\n              \"script\": {\n                \"type\": \"text/javascript\",\n                \"exec\": \"var data;\\n\\ntry { responseJSON = JSON.parse(responseBody); }\\ncatch (e) {}\\n\\ntests[\\\"Body contains files\\\"] = responseBody.has(\\\"files\\\");\\ntests[\\\"Body contains args\\\"] = responseBody.has(\\\"args\\\");\\ntests[\\\"Body contains form\\\"] = responseBody.has(\\\"form\\\");\\ntests[\\\"Body contains headers\\\"] = responseBody.has(\\\"headers\\\");\\ntests[\\\"Body contains url\\\"] = responseBody.has(\\\"url\\\");\\n\\n\\n\\ntests[\\\"Data has been passed\\\"] = (responseJSON && responseJSON.data && responseJSON.data.length)\"\n              }\n            }\n          ],\n          \"request\": {\n            \"url\": \"https://postman-echo.com/put\",\n            \"method\": \"PUT\",\n            \"header\": [\n              {\n                \"key\": \"Content-Type\",\n                \"value\": \"text/plain\"\n              }\n            ],\n            \"body\": {\n              \"mode\": \"raw\",\n              \"raw\": \"Etiam mi lacus, cursus vitae felis et, blandit pellentesque neque. Vestibulum eget nisi a tortor commodo dignissim.\\nQuisque ipsum ligula, faucibus a felis a, commodo elementum nisl. Mauris vulputate sapien et tincidunt viverra. Donec vitae velit nec metus.\"\n            },\n            \"description\": \"The HTTP `PUT` request method is similar to HTTP `POST`. It too is meant to \\ntransfer data to a server (and elicit a response). What data is returned depends on the implementation\\nof the server.\\n\\nA `PUT` request can pass parameters to the server using \\\"Query String \\nParameters\\\", as well as the Request Body. For example, in the following \\nraw HTTP request,\\n\\n> PUT /hi/there?hand=wave\\n>\\n> <request-body>\\n\\n\\n\"\n          },\n          \"response\": []\n        },\n        {\n          \"id\": \"fdf95beb-6939-9cfa-f1f5-00756a09e067\",\n          \"name\": \"PATCH Request\",\n          \"event\": [\n            {\n              \"listen\": \"test\",\n              \"script\": {\n                \"type\": \"text/javascript\",\n                \"exec\": \"tests[\\\"Body contains files\\\"] = responseBody.has(\\\"files\\\");\\ntests[\\\"Body contains args\\\"] = responseBody.has(\\\"args\\\");\\ntests[\\\"Body contains form\\\"] = responseBody.has(\\\"form\\\");\\ntests[\\\"Body contains headers\\\"] = responseBody.has(\\\"headers\\\");\\ntests[\\\"Body contains url\\\"] = responseBody.has(\\\"url\\\");\\n\\nvar data = JSON.parse(responseBody)\\n\"\n              }\n            }\n          ],\n          \"request\": {\n            \"url\": \"https://postman-echo.com/patch\",\n            \"method\": \"PATCH\",\n            \"header\": [],\n            \"body\": {\n              \"mode\": \"raw\",\n              \"raw\": \"Curabitur auctor, elit nec pulvinar porttitor, ex augue condimentum enim, eget suscipit urna felis quis neque.\\nSuspendisse sit amet luctus massa, nec venenatis mi. Suspendisse tincidunt massa at nibh efficitur fringilla. Nam quis congue mi. Etiam volutpat.\"\n            },\n            \"description\": \"The HTTP `PATCH` method is used to update resources on a server. The exact\\nuse of `PATCH` requests depends on the server in question. There are a number\\nof server implementations which handle `PATCH` differently. Technically, \\n`PATCH` supports both Query String parameters and a Request Body.\\n\\nThis endpoint accepts an HTTP `PATCH` request and provides debug information\\nsuch as the HTTP headers, Query String arguments, and the Request Body.\"\n          },\n          \"response\": []\n        },\n        {\n          \"id\": \"8509cbff-f490-6ac8-7201-489c7a65322d\",\n          \"name\": \"DELETE Request\",\n          \"event\": [\n            {\n              \"listen\": \"test\",\n              \"script\": {\n                \"type\": \"text/javascript\",\n                \"exec\": \"tests[\\\"Body contains files\\\"] = responseBody.has(\\\"files\\\");\\ntests[\\\"Body contains args\\\"] = responseBody.has(\\\"args\\\");\\ntests[\\\"Body contains form\\\"] = responseBody.has(\\\"form\\\");\\ntests[\\\"Body contains headers\\\"] = responseBody.has(\\\"headers\\\");\\ntests[\\\"Body contains url\\\"] = responseBody.has(\\\"url\\\");\\n\\nvar data = JSON.parse(responseBody)\"\n              }\n            }\n          ],\n          \"request\": {\n            \"url\": \"https://postman-echo.com/delete\",\n            \"method\": \"DELETE\",\n            \"header\": [],\n            \"body\": {\n              \"mode\": \"raw\",\n              \"raw\": \"Donec fermentum, nisi sed cursus eleifend, nulla tortor ultricies tellus, ut vehicula orci arcu ut velit. In volutpat egestas dapibus. \\nMorbi condimentum vestibulum sapien. Etiam dignissim diam quis eros lobortis gravida vel lobortis est. Etiam gravida sed.\"\n            },\n            \"description\": \"The HTTP `DELETE` method is used to delete resources on a server. The exact\\nuse of `DELETE` requests depends on the server implementation. In general, \\n`DELETE` requests support both, Query String parameters as well as a Request \\nBody.\\n\\nThis endpoint accepts an HTTP `DELETE` request and provides debug information\\nsuch as the HTTP headers, Query String arguments, and the Request Body.\"\n          },\n          \"response\": []\n        }\n      ]\n    },\n    {\n      \"_postman_id\": \"7fbb0592-7cad-ff7e-500c-790965163a57\",\n      \"name\": \"Utilities\",\n      \"description\": \"\",\n      \"item\": [\n        {\n          \"id\": \"709d6b48-c254-3005-7265-d5d337b91983\",\n          \"name\": \"Response Status Code\",\n          \"event\": [\n            {\n              \"listen\": \"test\",\n              \"script\": {\n                \"type\": \"text/javascript\",\n                \"exec\": \"tests[\\\"Body contains status\\\"] = responseBody.has(\\\"status\\\");\\n\\nvar data = JSON.parse(responseBody);\\n\\ntests[\\\"Status equals 200\\\"] = data.status === 200;\\n\"\n              }\n            }\n          ],\n          \"request\": {\n            \"url\": \"https://postman-echo.com/status/200\",\n            \"method\": \"GET\",\n            \"header\": [],\n            \"body\": {\n              \"mode\": \"formdata\",\n              \"formdata\": [\n                {\n                  \"key\": \"test\",\n                  \"value\": \"123\",\n                  \"type\": \"text\",\n                  \"enabled\": true\n                }\n              ]\n            },\n            \"description\": \"This endpoint allows one to instruct the server which status code to respond with.\\n\\nEvery response is accompanied by a status code. The status code provides a summary of the nature of response sent by the server. For example, a status code of `200` means everything is okay with the response and a code of `404` implies that the requested URL does not exist on server. \\nA list of all valid HTTP status code can be found at the [List of Status Codes](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes) wikipedia article. When using Postman, the response status code is described for easy reference.\\n\\nNote that if an invalid status code is requested to be sent, the server returns a status code of `400 Bad Request`.\"\n          },\n          \"response\": []\n        },\n        {\n          \"id\": \"23a34378-602b-0a40-252c-5555b5f72000\",\n          \"name\": \"Streamed Response\",\n          \"event\": [\n            {\n              \"listen\": \"test\",\n              \"script\": {\n                \"type\": \"text/javascript\",\n                \"exec\": \"tests[\\\"response code is 200\\\"] = responseCode.code === 200;\\n\\n\"\n              }\n            }\n          ],\n          \"request\": {\n            \"url\": \"https://postman-echo.com/stream/10\",\n            \"method\": \"GET\",\n            \"header\": [],\n            \"body\": {\n              \"mode\": \"formdata\",\n              \"formdata\": []\n            },\n            \"description\": \"This endpoint allows one to receive streaming http response using [chunked transfer encoding](https://en.wikipedia.org/wiki/Chunked_transfer_encoding) of a configurable length.\\n\\nA streaming response does not wait for the entire response to be generated on server before flushing it out. This implies that for a fairly large response, parts of it can be streamed to the requestee as and when it is generated on server. The client can then take actions of processing this partially received data.\"\n          },\n          \"response\": []\n        },\n        {\n          \"id\": \"2942065c-eee1-2140-2801-d12f78cf67ac\",\n          \"name\": \"Delay Response\",\n          \"event\": [\n            {\n              \"listen\": \"test\",\n              \"script\": {\n                \"type\": \"text/javascript\",\n                \"exec\": \"tests[\\\"response code is 200\\\"] = responseCode.code === 200;\\n\\nvar data = JSON.parse(responseBody);\\n\\ntests[\\\"response body has key delay\\\"] = 'delay' in data;\"\n              }\n            }\n          ],\n          \"request\": {\n            \"url\": \"https://postman-echo.com/delay/3\",\n            \"method\": \"GET\",\n            \"header\": [],\n            \"body\": {\n              \"mode\": \"formdata\",\n              \"formdata\": [\n                {\n                  \"key\": \"test\",\n                  \"value\": \"123\",\n                  \"type\": \"text\",\n                  \"enabled\": true\n                }\n              ]\n            },\n            \"description\": \"Using this endpoint one can configure how long it takes for the server to come back with a response. Appending a number to the URL defines the time (in seconds) the server will wait before responding.\\n\\nNote that a maximum delay of 10 seconds is accepted by the server.\"\n          },\n          \"response\": []\n        },\n        {\n          \"id\": \"6c5607e2-7021-27f4-64e8-9f7b87d34c25\",\n          \"name\": \"Get UTF8 Encoded Response\",\n          \"event\": [\n            {\n              \"listen\": \"test\",\n              \"script\": {\n                \"type\": \"text/javascript\",\n                \"exec\": \"tests[\\\"response code is 200\\\"] = responseCode.code === 200;\"\n              }\n            }\n          ],\n          \"request\": {\n            \"url\": \"https://postman-echo.com/encoding/utf8\",\n            \"method\": \"GET\",\n            \"header\": [],\n            \"body\": {\n              \"mode\": \"formdata\",\n              \"formdata\": []\n            },\n            \"description\": \"If a response of an endpoint requires to send data beyond the basic English / ASCII character set, the `charset` parameter in the `Content-Type` response header defines the character encoding policy.\\n\\nThis endpoint returns an `UTF8` character encoded response body with text in various languages such as Greek, Latin, East Asian, etc. Postman can interpret the character encoding and use appropriate methods to display the character set in responses.\"\n          },\n          \"response\": []\n        },\n        {\n          \"id\": \"95ade4e4-9b25-1e11-b8c5-e88be95d87eb\",\n          \"name\": \"GZip Compressed Response\",\n          \"event\": [\n            {\n              \"listen\": \"test\",\n              \"script\": {\n                \"type\": \"text/javascript\",\n                \"exec\": \"tests[\\\"response code is 200\\\"] = responseCode.code === 200;\\n\\ntry {\\n    var data = JSON.parse(responseBody);\\n    tests[\\\"Body contains gzipped\\\"] = responseBody.has(\\\"gzipped\\\");\\n    tests[\\\"Body contains headers\\\"] = responseBody.has(\\\"headers\\\");\\n    tests[\\\"Body contains method\\\"] = responseBody.has(\\\"method\\\");\\n}\\ncatch(e) {\\n    console.log('Cannot parse response,probably not a JSON');\\n}\"\n              }\n            }\n          ],\n          \"request\": {\n            \"url\": \"https://postman-echo.com/gzip\",\n            \"method\": \"GET\",\n            \"header\": [],\n            \"body\": {\n              \"mode\": \"formdata\",\n              \"formdata\": [\n                {\n                  \"key\": \"code\",\n                  \"value\": \"xWnkliVQJURqB2x1\",\n                  \"type\": \"text\",\n                  \"enabled\": true\n                },\n                {\n                  \"key\": \"grant_type\",\n                  \"value\": \"authorization_code\",\n                  \"type\": \"text\",\n                  \"enabled\": true\n                },\n                {\n                  \"key\": \"redirect_uri\",\n                  \"value\": \"https://www.getpostman.com/oauth2/callback\",\n                  \"type\": \"text\",\n                  \"enabled\": true\n                },\n                {\n                  \"key\": \"client_id\",\n                  \"value\": \"abc123\",\n                  \"type\": \"text\",\n                  \"enabled\": true\n                },\n                {\n                  \"key\": \"client_secret\",\n                  \"value\": \"ssh-secret\",\n                  \"type\": \"text\",\n                  \"enabled\": true\n                }\n              ]\n            },\n            \"description\": \"This endpoint returns the response using [gzip compression algorithm](https://en.wikipedia.org/wiki/Gzip).\\nThe uncompressed response is a JSON string containing the details of the request sent by the client. For this endpoint to work, one should request with `Accept-encoding` header containing `gzip` as part of its value. Postman supports gzip, deflate and SDCH decoding and automatically sends them as part of the request.\\n\\nHTTP Compression allows the server to send responses in a compressed format, which is uncompressed by the client before processing. This reduces network bandwidth consumption at the cost of increase in CPU usage.\\nTo know more about this, refer the [HTTP Compression](https://en.wikipedia.org/wiki/HTTP_compression) wikipedia article.\"\n          },\n          \"response\": []\n        },\n        {\n          \"id\": \"c5f60ab4-e497-690a-dd2f-b2b34628bd8c\",\n          \"name\": \"Deflate Compressed Response\",\n          \"event\": [\n            {\n              \"listen\": \"test\",\n              \"script\": {\n                \"type\": \"text/javascript\",\n                \"exec\": \"tests[\\\"response code is 200\\\"] = responseCode.code === 200;\\n\\ntry {\\n    var data = JSON.parse(responseBody);\\n    tests[\\\"Body contains deflated\\\"] = responseBody.has(\\\"deflated\\\");\\n    tests[\\\"Body contains headers\\\"] = responseBody.has(\\\"headers\\\");\\n    tests[\\\"Body contains method\\\"] = responseBody.has(\\\"method\\\");\\n}\\ncatch(e) {\\n    console.log('Cannot parse response,probably not a JSON'); tests['response is parsed properly'] = false;\\n}\\n\"\n              }\n            }\n          ],\n          \"request\": {\n            \"url\": \"https://postman-echo.com/deflate\",\n            \"method\": \"GET\",\n            \"header\": [],\n            \"body\": {\n              \"mode\": \"formdata\",\n              \"formdata\": []\n            },\n            \"description\": \"This endpoint returns the response using [deflate compression algorithm](https://en.wikipedia.org/wiki/DEFLATE). \\nThe uncompressed response is a JSON string containing the details of the request sent by the client. For this endpoint to work, one should request with `Accept-encoding` header containing `deflate` as part of its value. Postman supports gzip, deflate and SDCH decoding and automatically sends them as part of the request.\\n\\nHTTP Compression allows the server to send responses in a compressed format, which is uncompressed by the client before processing. This reduces network bandwidth consumption at the cost of increase in CPU usage.\\nTo know more about this, refer the [HTTP Compression](https://en.wikipedia.org/wiki/HTTP_compression) wikipedia article.\"\n          },\n          \"response\": []\n        }\n      ]\n    },\n    {\n      \"_postman_id\": \"73cdf1ab-aaf1-c1a1-df67-fd87d441b3a9\",\n      \"name\": \"[draft] Auth: OAuth2.0\",\n      \"description\": \"OAuth 2.0 allows a client to access a resource owners(user) protected resources without direct access to the users credentials.\\nThe client obtains an access token which can be used to access the resource owners resources.\\nOAuth 2.0 implements 4 different types of grant flows. Postman Echo has implemented the [Authorization Code](https://tools.ietf.org/html/rfc6749#section-1.3.1) grant flow.\\n\\nThe OAuth flow typically consists of three steps. \\nIn the first step the client requests an authentication code from the server implementing the OAuth flow.\\nThe authentication code along with other client credentials is then used to get the access token.\\nThe access token can be used by the client to access users resources.\\n\",\n      \"item\": [\n        {\n          \"id\": \"c1edd601-f55f-4edf-9885-374242b617d1\",\n          \"name\": \"OAuth2.0 Get Access Token\",\n          \"event\": [\n            {\n              \"listen\": \"test\",\n              \"script\": {\n                \"type\": \"text/javascript\",\n                \"exec\": \"tests[\\\"response code is 200\\\"] = responseCode.code === 200;\\nvar body = JSON.parse(responseBody);\\ntests[\\\"body has access token\\\"] = \\\"access_token\\\" in body;\\ntests[\\\"body has bearer type\\\"] = \\\"token_type\\\" in body;\"\n              }\n            }\n          ],\n          \"request\": {\n            \"url\": \"https://postman-echo.com/oauth2/token\",\n            \"method\": \"POST\",\n            \"header\": [],\n            \"body\": {\n              \"mode\": \"formdata\",\n              \"formdata\": [\n                {\n                  \"key\": \"code\",\n                  \"value\": \"xWnkliVQJURqB2x1\",\n                  \"type\": \"text\",\n                  \"enabled\": true\n                },\n                {\n                  \"key\": \"grant_type\",\n                  \"value\": \"authorization_code\",\n                  \"type\": \"text\",\n                  \"enabled\": true\n                },\n                {\n                  \"key\": \"redirect_uri\",\n                  \"value\": \"https://www.getpostman.com/oauth2/callback\",\n                  \"type\": \"text\",\n                  \"enabled\": true\n                },\n                {\n                  \"key\": \"client_id\",\n                  \"value\": \"abc123\",\n                  \"type\": \"text\",\n                  \"enabled\": true\n                },\n                {\n                  \"key\": \"client_secret\",\n                  \"value\": \"ssh-secret\",\n                  \"type\": \"text\",\n                  \"enabled\": true\n                }\n              ]\n            },\n            \"description\": \"This endpoint is used to get the `access_token`\\n\\nIt requires the following secret client credentials to be sent as part of the form body along with the `authentication code` obtained as part of the `redirect_uri` from the previous request.\\n\\n> code: xWnkliVQJURqB2x1\\n>\\n> grant_type: authorization_code\\n>\\n> redirect_uri: https://www.getpostman.com/oauth2/callback\\n>\\n> client_id: abc123\\n>\\n> client_secret: ssh-secret\\n\\nIf the correct credentials are not passed, the server returns with a `401 Unauthorized` response.\"\n          },\n          \"response\": [\n            {\n              \"name\": \"401\",\n              \"originalRequest\": {\n                \"url\": \"https://postman-echo.com/oauth2/token\",\n                \"method\": \"POST\",\n                \"header\": [],\n                \"body\": {\n                  \"mode\": \"formdata\",\n                  \"formdata\": [\n                    {\n                      \"key\": \"code\",\n                      \"value\": \"xWnkliVQJURqB2x1\",\n                      \"type\": \"text\",\n                      \"enabled\": true\n                    },\n                    {\n                      \"key\": \"grant_type\",\n                      \"value\": \"authorization_code\",\n                      \"type\": \"text\",\n                      \"enabled\": true\n                    },\n                    {\n                      \"key\": \"redirect_uri\",\n                      \"value\": \"https://www.getpostman.com/oauth2/callback\",\n                      \"type\": \"text\",\n                      \"enabled\": true\n                    },\n                    {\n                      \"key\": \"client_id\",\n                      \"value\": \"abc123\",\n                      \"type\": \"text\",\n                      \"enabled\": true\n                    },\n                    {\n                      \"key\": \"client_secret\",\n                      \"value\": \"ssh-secret\",\n                      \"type\": \"text\",\n                      \"enabled\": true\n                    }\n                  ]\n                },\n                \"description\": \"Tries to get the access token by passing the clientId , clientSecret,\\nauthentication code, redirect URI and grant type.\\n\"\n              },\n              \"status\": \"Unauthorized\",\n              \"code\": 401,\n              \"header\": [\n                {\n                  \"name\": \"Access-Control-Allow-Credentials\",\n                  \"key\": \"Access-Control-Allow-Credentials\",\n                  \"value\": \"\",\n                  \"description\": \"\"\n                },\n                {\n                  \"name\": \"Access-Control-Allow-Headers\",\n                  \"key\": \"Access-Control-Allow-Headers\",\n                  \"value\": \"\",\n                  \"description\": \"\"\n                },\n                {\n                  \"name\": \"Access-Control-Allow-Methods\",\n                  \"key\": \"Access-Control-Allow-Methods\",\n                  \"value\": \"\",\n                  \"description\": \"\"\n                },\n                {\n                  \"name\": \"Access-Control-Allow-Origin\",\n                  \"key\": \"Access-Control-Allow-Origin\",\n                  \"value\": \"\",\n                  \"description\": \"\"\n                },\n                {\n                  \"name\": \"Connection\",\n                  \"key\": \"Connection\",\n                  \"value\": \"keep-alive\",\n                  \"description\": \"\"\n                },\n                {\n                  \"name\": \"Content-Length\",\n                  \"key\": \"Content-Length\",\n                  \"value\": \"2\",\n                  \"description\": \"\"\n                },\n                {\n                  \"name\": \"Content-Type\",\n                  \"key\": \"Content-Type\",\n                  \"value\": \"application/json; charset=utf-8\",\n                  \"description\": \"\"\n                },\n                {\n                  \"name\": \"Date\",\n                  \"key\": \"Date\",\n                  \"value\": \"Sat, 31 Oct 2015 06:43:44 GMT\",\n                  \"description\": \"\"\n                },\n                {\n                  \"name\": \"Server\",\n                  \"key\": \"Server\",\n                  \"value\": \"nginx/1.6.2\",\n                  \"description\": \"\"\n                },\n                {\n                  \"name\": \"Vary\",\n                  \"key\": \"Vary\",\n                  \"value\": \"X-HTTP-Method-Override, Accept-Encoding\",\n                  \"description\": \"\"\n                },\n                {\n                  \"name\": \"X-Powered-By\",\n                  \"key\": \"X-Powered-By\",\n                  \"value\": \"Sails <sailsjs.org>\",\n                  \"description\": \"\"\n                }\n              ],\n              \"cookie\": [],\n              \"responseTime\": \"287\",\n              \"body\": \"{}\"\n            },\n            {\n              \"name\": \"200\",\n              \"originalRequest\": {\n                \"url\": \"https://postman-echo.com/oauth2/token\",\n                \"method\": \"POST\",\n                \"header\": [],\n                \"body\": {\n                  \"mode\": \"formdata\",\n                  \"formdata\": [\n                    {\n                      \"key\": \"code\",\n                      \"value\": \"xWnkliVQJURqB2x1\",\n                      \"type\": \"text\",\n                      \"enabled\": true\n                    },\n                    {\n                      \"key\": \"grant_type\",\n                      \"value\": \"authorization_code\",\n                      \"type\": \"text\",\n                      \"enabled\": true\n                    },\n                    {\n                      \"key\": \"redirect_uri\",\n                      \"value\": \"https://www.getpostman.com/oauth2/callback\",\n                      \"type\": \"text\",\n                      \"enabled\": true\n                    },\n                    {\n                      \"key\": \"client_id\",\n                      \"value\": \"abc123\",\n                      \"type\": \"text\",\n                      \"enabled\": true\n                    },\n                    {\n                      \"key\": \"client_secret\",\n                      \"value\": \"ssh-secret\",\n                      \"type\": \"text\",\n                      \"enabled\": true\n                    }\n                  ]\n                },\n                \"description\": \"Tries to get the access token by passing the clientId , clientSecret,\\nauthentication code, redirect URI and grant type.\\n\"\n              },\n              \"status\": \"OK\",\n              \"code\": 200,\n              \"header\": [\n                {\n                  \"name\": \"Access-Control-Allow-Credentials\",\n                  \"key\": \"Access-Control-Allow-Credentials\",\n                  \"value\": \"\",\n                  \"description\": \"\"\n                },\n                {\n                  \"name\": \"Access-Control-Allow-Headers\",\n                  \"key\": \"Access-Control-Allow-Headers\",\n                  \"value\": \"\",\n                  \"description\": \"\"\n                },\n                {\n                  \"name\": \"Access-Control-Allow-Methods\",\n                  \"key\": \"Access-Control-Allow-Methods\",\n                  \"value\": \"\",\n                  \"description\": \"\"\n                },\n                {\n                  \"name\": \"Access-Control-Allow-Origin\",\n                  \"key\": \"Access-Control-Allow-Origin\",\n                  \"value\": \"\",\n                  \"description\": \"\"\n                },\n                {\n                  \"name\": \"Connection\",\n                  \"key\": \"Connection\",\n                  \"value\": \"keep-alive\",\n                  \"description\": \"\"\n                },\n                {\n                  \"name\": \"Content-Encoding\",\n                  \"key\": \"Content-Encoding\",\n                  \"value\": \"gzip\",\n                  \"description\": \"\"\n                },\n                {\n                  \"name\": \"Content-Length\",\n                  \"key\": \"Content-Length\",\n                  \"value\": \"153\",\n                  \"description\": \"\"\n                },\n                {\n                  \"name\": \"Content-Type\",\n                  \"key\": \"Content-Type\",\n                  \"value\": \"application/json; charset=utf-8\",\n                  \"description\": \"\"\n                },\n                {\n                  \"name\": \"Date\",\n                  \"key\": \"Date\",\n                  \"value\": \"Sat, 31 Oct 2015 06:43:34 GMT\",\n                  \"description\": \"\"\n                },\n                {\n                  \"name\": \"Server\",\n                  \"key\": \"Server\",\n                  \"value\": \"nginx/1.6.2\",\n                  \"description\": \"\"\n                },\n                {\n                  \"name\": \"Vary\",\n                  \"key\": \"Vary\",\n                  \"value\": \"X-HTTP-Method-Override, Accept-Encoding\",\n                  \"description\": \"\"\n                },\n                {\n                  \"name\": \"X-Powered-By\",\n                  \"key\": \"X-Powered-By\",\n                  \"value\": \"Sails <sailsjs.org>\",\n                  \"description\": \"\"\n                }\n              ],\n              \"cookie\": [],\n              \"responseTime\": \"303\",\n              \"body\": \"{\\\"access_token\\\":\\\"vp7jxTwqgczoFHs0uIdOvv4VdBWmvCkbVbNBCuaTQ3JZplPS40BaNV47HD1zt7MztQPILJvqYsOs6PfJpFYBgwbaE3CVEKOj\\\",\\\"token_type\\\":\\\"Bearer\\\"}\"\n            }\n          ]\n        },\n        {\n          \"id\": \"ecc2a4a0-c910-608f-59f0-ffb007f9c088\",\n          \"name\": \"OAuth2.0 Get Resource\",\n          \"event\": [\n            {\n              \"listen\": \"test\",\n              \"script\": {\n                \"type\": \"text/javascript\",\n                \"exec\": \"tests[\\\"response code is 401\\\"] = (responseCode.code === 200);\\nvar body = JSON.parse(responseBody);\\ntests[\\\"body has user_id\\\"] = \\\"user_id\\\" in body;\\ntests[\\\"body has name\\\"] = \\\"name\\\" in body;\"\n              }\n            }\n          ],\n          \"request\": {\n            \"url\": \"https://postman-echo.com/oauth2/user/info\",\n            \"method\": \"GET\",\n            \"header\": [\n              {\n                \"key\": \"Authorization\",\n                \"value\": \"Bearer vp7jxTwqgczoFHs0uIdOvv4VdBWmvCkbVbNBCuaTQ3JZplPS40BaNV47HD1zt7MztQPILJvqYsOs6PfJpFYBgwbaE3CVEKOj\",\n                \"description\": \"\"\n              }\n            ],\n            \"body\": {\n              \"mode\": \"formdata\",\n              \"formdata\": [\n                {\n                  \"key\": \"code\",\n                  \"value\": \"xWnkliVQJURqB2x1\",\n                  \"type\": \"text\",\n                  \"enabled\": true\n                },\n                {\n                  \"key\": \"grant_type\",\n                  \"value\": \"authorization_code\",\n                  \"type\": \"text\",\n                  \"enabled\": true\n                },\n                {\n                  \"key\": \"redirect_uri\",\n                  \"value\": \"https://www.getpostman.com/oauth2/callback\",\n                  \"type\": \"text\",\n                  \"enabled\": true\n                },\n                {\n                  \"key\": \"client_id\",\n                  \"value\": \"abc123\",\n                  \"type\": \"text\",\n                  \"enabled\": true\n                },\n                {\n                  \"key\": \"client_secret\",\n                  \"value\": \"ssh-secret\",\n                  \"type\": \"text\",\n                  \"enabled\": true\n                }\n              ]\n            },\n            \"description\": \"Once the bearer token has been obtained, it can be passed as `Authorization` header to access user's resources.\\n\\n> Authorization: Bearer vp7jx...\\n\\nIf the `Authorization` header is not passed the endpoint returns `401 Unauthorized`.\\n\"\n          },\n          \"response\": [\n            {\n              \"name\": \"401\",\n              \"status\": \"Unauthorized\",\n              \"code\": 401,\n              \"header\": [\n                {\n                  \"name\": \"Access-Control-Allow-Credentials\",\n                  \"key\": \"Access-Control-Allow-Credentials\",\n                  \"value\": \"\",\n                  \"description\": \"\"\n                },\n                {\n                  \"name\": \"Access-Control-Allow-Headers\",\n                  \"key\": \"Access-Control-Allow-Headers\",\n                  \"value\": \"\",\n                  \"description\": \"\"\n                },\n                {\n                  \"name\": \"Access-Control-Allow-Methods\",\n                  \"key\": \"Access-Control-Allow-Methods\",\n                  \"value\": \"\",\n                  \"description\": \"\"\n                },\n                {\n                  \"name\": \"Access-Control-Allow-Origin\",\n                  \"key\": \"Access-Control-Allow-Origin\",\n                  \"value\": \"\",\n                  \"description\": \"\"\n                },\n                {\n                  \"name\": \"Connection\",\n                  \"key\": \"Connection\",\n                  \"value\": \"keep-alive\",\n                  \"description\": \"\"\n                },\n                {\n                  \"name\": \"Date\",\n                  \"key\": \"Date\",\n                  \"value\": \"Sat, 31 Oct 2015 06:44:16 GMT\",\n                  \"description\": \"\"\n                },\n                {\n                  \"name\": \"Server\",\n                  \"key\": \"Server\",\n                  \"value\": \"nginx/1.6.2\",\n                  \"description\": \"\"\n                },\n                {\n                  \"name\": \"WWW-Authenticate\",\n                  \"key\": \"WWW-Authenticate\",\n                  \"value\": \"Bearer realm=\\\"Users\\\"\",\n                  \"description\": \"\"\n                },\n                {\n                  \"name\": \"X-Powered-By\",\n                  \"key\": \"X-Powered-By\",\n                  \"value\": \"Sails <sailsjs.org>\",\n                  \"description\": \"\"\n                },\n                {\n                  \"name\": \"transfer-encoding\",\n                  \"key\": \"transfer-encoding\",\n                  \"value\": \"chunked\",\n                  \"description\": \"\"\n                }\n              ],\n              \"cookie\": [],\n              \"responseTime\": \"303\",\n              \"body\": \"Unauthorized\"\n            },\n            {\n              \"name\": \"200\",\n              \"status\": \"OK\",\n              \"code\": 200,\n              \"header\": [\n                {\n                  \"name\": \"Access-Control-Allow-Credentials\",\n                  \"key\": \"Access-Control-Allow-Credentials\",\n                  \"value\": \"\",\n                  \"description\": \"\"\n                },\n                {\n                  \"name\": \"Access-Control-Allow-Headers\",\n                  \"key\": \"Access-Control-Allow-Headers\",\n                  \"value\": \"\",\n                  \"description\": \"\"\n                },\n                {\n                  \"name\": \"Access-Control-Allow-Methods\",\n                  \"key\": \"Access-Control-Allow-Methods\",\n                  \"value\": \"\",\n                  \"description\": \"\"\n                },\n                {\n                  \"name\": \"Access-Control-Allow-Origin\",\n                  \"key\": \"Access-Control-Allow-Origin\",\n                  \"value\": \"\",\n                  \"description\": \"\"\n                },\n                {\n                  \"name\": \"Connection\",\n                  \"key\": \"Connection\",\n                  \"value\": \"keep-alive\",\n                  \"description\": \"\"\n                },\n                {\n                  \"name\": \"Content-Encoding\",\n                  \"key\": \"Content-Encoding\",\n                  \"value\": \"gzip\",\n                  \"description\": \"\"\n                },\n                {\n                  \"name\": \"Content-Length\",\n                  \"key\": \"Content-Length\",\n                  \"value\": \"50\",\n                  \"description\": \"\"\n                },\n                {\n                  \"name\": \"Content-Type\",\n                  \"key\": \"Content-Type\",\n                  \"value\": \"application/json; charset=utf-8\",\n                  \"description\": \"\"\n                },\n                {\n                  \"name\": \"Date\",\n                  \"key\": \"Date\",\n                  \"value\": \"Sat, 31 Oct 2015 06:44:49 GMT\",\n                  \"description\": \"\"\n                },\n                {\n                  \"name\": \"Server\",\n                  \"key\": \"Server\",\n                  \"value\": \"nginx/1.6.2\",\n                  \"description\": \"\"\n                },\n                {\n                  \"name\": \"Vary\",\n                  \"key\": \"Vary\",\n                  \"value\": \"Accept-Encoding\",\n                  \"description\": \"\"\n                },\n                {\n                  \"name\": \"X-Powered-By\",\n                  \"key\": \"X-Powered-By\",\n                  \"value\": \"Sails <sailsjs.org>\",\n                  \"description\": \"\"\n                }\n              ],\n              \"cookie\": [],\n              \"responseTime\": \"323\",\n              \"body\": \"{\\\"user_id\\\":1,\\\"name\\\":\\\"postman\\\"}\"\n            }\n          ]\n        }\n      ]\n    }\n  ]\n}\n"
  },
  {
    "path": "test/integration/esc-formdata/esc-formdata.postman_collection.json",
    "content": "{\n  \"variables\": [],\n  \"info\": {\n    \"name\": \"Escaped characters in the form body are sent correctly\",\n    \"_postman_id\": \"df4d105a-e01b-b219-9a65-266547e02cd0\",\n    \"description\": \"A set of tests for proper replacement of form key value pairs with escaped characters\",\n    \"schema\": \"https://schema.getpostman.com/json/collection/v2.0.0/collection.json\"\n  },\n  \"item\": [\n    {\n      \"name\": \"r1\",\n      \"event\": [\n        {\n          \"listen\": \"test\",\n          \"script\": {\n            \"type\": \"text/javascript\",\n            \"exec\": \"console.log(responseBody);var data=JSON.parse(responseBody);tests[\\\"Form Key Replaced\\\"]=data.form.hasOwnProperty(\\\"hello\\\"); tests[\\\"Form val replaced from env\\\"]=data.form.hello===\\\"hello\\\\\\\\kworld\\\";\"\n          }\n        }\n      ],\n      \"request\": {\n        \"url\": \"https://postman-echo.com/post?a={{msg}}\",\n        \"method\": \"POST\",\n        \"header\": [],\n        \"body\": {\n          \"mode\": \"urlencoded\",\n          \"urlencoded\": [\n            {\n              \"key\": \"{{msg1}}\",\n              \"value\": \"{{msg}}\",\n              \"type\": \"text\",\n              \"enabled\": true\n            },\n            {\n              \"key\": \"incollection\",\n              \"value\": \"hello\\\\world\",\n              \"type\": \"text\",\n              \"enabled\": true\n            }\n          ]\n        },\n        \"description\": \"\"\n      },\n      \"response\": []\n    }\n  ]\n}\n"
  },
  {
    "path": "test/integration/esc-formdata/esc-formdata.postman_environment.json",
    "content": "{\n\t\"id\": \"e1e2f391-8c72-c7fe-89c7-d48761e90296\",\n\t\"name\": \"e1\",\n\t\"values\": [\n\t\t{\n\t\t\t\"key\": \"msg\",\n\t\t\t\"value\": \"hello\\\\kworld\",\n\t\t\t\"type\": \"text\",\n\t\t\t\"name\": \"msg\",\n\t\t\t\"enabled\": true\n\t\t},\n\t\t{\n\t\t\t\"key\": \"msg1\",\n\t\t\t\"value\": \"hello\",\n\t\t\t\"type\": \"text\",\n\t\t\t\"name\": \"msg\",\n\t\t\t\"enabled\": true\n\t\t}\n\t],\n\t\"timestamp\": 1441816736435,\n\t\"synced\": false,\n\t\"syncedFilename\": \"\"\n}"
  },
  {
    "path": "test/integration/globals-env-data-files/globals-env-data-files.postman_collection.json",
    "content": "{\n  \"variables\": [],\n  \"info\": {\n    \"name\": \"globals+env+data tests\",\n    \"_postman_id\": \"dcc7e181-766f-e7ef-4b94-efbfe57189a9\",\n    \"description\": \"A set of tests for global and data variable operations\",\n    \"schema\": \"https://schema.getpostman.com/json/collection/v2.0.0/collection.json\"\n  },\n  \"item\": [\n    {\n      \"name\": \"GET\",\n      \"event\": [\n        {\n          \"listen\": \"test\",\n          \"script\": {\n            \"type\": \"text/javascript\",\n            \"exec\": [\n              \"pm.test(\\\"Content-Type is present\\\", () => {\",\n              \"    pm.expect(pm.response.headers.has(\\\"content-type\\\")).true;\",\n              \"})\",\n              \"var data1 = pm.response.json();\",\n              \"pm.test(\\\"testGlobalSetFromPRScript\\\", () => {\",\n              \"    pm.expect(data1.args.prsG).equal('prsG');\",\n              \"})\",\n              \"pm.test(\\\"Read global var correctly\\\", () => {\",\n              \"    pm.expect(pm.globals.get(\\\"prsG\\\")).equal('prsG');\",\n              \"})\",\n              \"pm.test(\\\"testEnvSetFromPRScript\\\", () => {\",\n              \"    pm.expect(data1.args.prsE).equal('prsE');\",\n              \"})\",\n              \"pm.test(\\\"Read env var correctly\\\", () => {\",\n              \"    pm.expect(pm.environment.get(\\\"prsE\\\")).equal('prsE');\",\n              \"})\",\n              \"pm.test(\\\"Read data var correctly\\\", () => {\",\n              \"    pm.expect(pm.variables.get(\\\"prsE\\\")).equal('prsE');\",\n              \"})\",\n              \"pm.globals.set(\\\"prsG\\\", \\\"prsG\\\");\",\n              \"pm.environment.set(\\\"prsE\\\", \\\"prsE\\\");\"\n            ]\n          }\n        },\n        {\n          \"listen\": \"prerequest\",\n          \"script\": {\n            \"type\": \"text/javascript\",\n            \"exec\": [\n              \"pm.globals.set(\\\"prsG\\\", \\\"prsG\\\");\",\n              \"pm.globals.set(\\\"prsE\\\", \\\"prsEaRDDDROR\\\");\",\n              \"pm.environment.set(\\\"prsE\\\", \\\"prsE\\\");\",\n              \"\"\n            ]\n          }\n        }\n      ],\n      \"request\": {\n        \"url\": \"{{url}}/get?global={{global}}&env={{env}}&data={{data}}&prsE={{prsE}}&prsG={{prsG}}\",\n        \"method\": \"GET\",\n        \"header\": [],\n        \"body\": {\n          \"mode\": \"formdata\",\n          \"formdata\": []\n        },\n        \"description\": \"Similar to postman-echo.com/get. Return GET data.\"\n      },\n      \"response\": []\n    },\n    {\n      \"name\": \"GET copy\",\n      \"event\": [\n        {\n          \"listen\": \"test\",\n          \"script\": {\n            \"type\": \"text/javascript\",\n            \"exec\": [\n              \"var data1 = pm.response.json();\",\n              \"\",\n              \"pm.test(\\\"Read global var correctly\\\", () => {\",\n              \"    pm.expect(pm.globals.get(\\\"prsG\\\")).equal('prsG');\",\n              \"})\",\n              \"pm.test(\\\"Read env var correctly\\\", () => {\",\n              \"    pm.expect(pm.environment.get(\\\"prsE\\\")).equal('prsE');\",\n              \"})\",\n              \"pm.test(\\\"Read data var correctly\\\", () => {\",\n              \"    pm.expect(pm.variables.get(\\\"prsE\\\")).equal('prsE');\",\n              \"})\"\n            ]\n          }\n        }\n      ],\n      \"request\": {\n        \"url\": \"{{url}}/get?global={{global}}&env={{env}}&data={{data}}\",\n        \"method\": \"GET\",\n        \"header\": [],\n        \"body\": {\n          \"mode\": \"formdata\",\n          \"formdata\": []\n        },\n        \"description\": \"Similar to postman-echo.com/get. Return GET data.\"\n      },\n      \"response\": []\n    }\n  ]\n}\n"
  },
  {
    "path": "test/integration/globals-env-data-files/globals-env-data-files.postman_data.json",
    "content": "[{\"dataVar\":\"dataValue\",\"data\":\"DATA\"}]\n"
  },
  {
    "path": "test/integration/globals-env-data-files/globals-env-data-files.postman_environment.json",
    "content": "{\n\t\"id\": \"426c4896-2d5b-80b8-da5d-ac205502f3c0\",\n\t\"name\": \"testEnv\",\n\t\"values\": [\n\t\t{\n\t\t\t\"key\": \"hKey\",\n\t\t\t\"value\": \"sampleKey\",\n\t\t\t\"type\": \"text\",\n\t\t\t\"name\": \"hKey\",\n\t\t\t\"enabled\": true\n\t\t},\n\t\t{\n\t\t\t\"key\": \"hburl\",\n\t\t\t\"value\": \"posts\",\n\t\t\t\"type\": \"text\",\n\t\t\t\"name\": \"hburl\",\n\t\t\t\"enabled\": true\n\t\t},\n\t\t{\n\t\t\t\"key\": \"tempKey\",\n\t\t\t\"value\": \"sampleKey2\",\n\t\t\t\"type\": \"text\",\n\t\t\t\"name\": \"tempKey\",\n\t\t\t\"enabled\": true\n\t\t},\n\t\t{\n\t\t\t\"key\": \"url\",\n\t\t\t\"value\": \"https://postman-echo.com\",\n\t\t\t\"type\": \"text\",\n\t\t\t\"name\": \"url\",\n\t\t\t\"enabled\": true\n\t\t},\n\t\t{\n\t\t\t\"key\": \"env\",\n\t\t\t\"value\": \"env2\",\n\t\t\t\"type\": \"text\",\n\t\t\t\"name\": \"env\",\n\t\t\t\"enabled\": true\n\t\t},\n\t\t{\n\t\t\t\"key\": \"data\",\n\t\t\t\"value\": \"env2\",\n\t\t\t\"type\": \"text\",\n\t\t\t\"name\": \"data\",\n\t\t\t\"enabled\": true\n\t\t}\n\t],\n\t\"timestamp\": 1405183029928,\n\t\"synced\": false,\n\t\"syncedFilename\": \"\"\n}\n"
  },
  {
    "path": "test/integration/globals-env-data-files/globals-env-data-files.postman_globals.json",
    "content": "[\n\t{\n\t\t\"key\": \"full_global_url\",\n\t\t\"value\": \"https://postman-echo.com/get\",\n\t\t\"type\": \"text\",\n\t\t\"name\": \"full_global_url\",\n\t\t\"enabled\": true\n\t},\n\t{\n\t\t\"key\": \"global_resource_get\",\n\t\t\"value\": \"/get\",\n\t\t\"type\": \"text\",\n\t\t\"name\": \"global_resource_get\",\n\t\t\"enabled\": true\n\t},\n\t{\n\t\t\"key\": \"Global Foo\",\n\t\t\"value\": \"Global Bar\",\n\t\t\"type\": \"text\",\n\t\t\"name\": \"Global Foo\",\n\t\t\"enabled\": true\n\t},\n\t{\n\t\t\"key\": \"Global Phew\",\n\t\t\"value\": \"Global Works\",\n\t\t\"type\": \"text\",\n\t\t\"name\": \"Global Phew\",\n\t\t\"enabled\": true\n\t},\n\t{\n\t\t\"key\": \"global\",\n\t\t\"value\": \"global1\",\n\t\t\"type\": \"text\",\n\t\t\"name\": \"global\",\n\t\t\"enabled\": true\n\t},\n\t{\n\t\t\"key\": \"env\",\n\t\t\"value\": \"global1\",\n\t\t\"type\": \"text\",\n\t\t\"name\": \"env\",\n\t\t\"enabled\": true\n\t},\n\t{\n\t\t\"key\": \"data\",\n\t\t\"value\": \"global1\",\n\t\t\"type\": \"text\",\n\t\t\"name\": \"data\",\n\t\t\"enabled\": true\n\t}\n]\n"
  },
  {
    "path": "test/integration/hawk-auth-test.postman_collection.json",
    "content": "{\n  \"variables\": [],\n  \"info\": {\n    \"name\": \"hawkAuthTest\",\n    \"_postman_id\": \"d497d10e-e280-8c83-709a-a4d4ea12ad14\",\n    \"description\": \"A set of tests for the HAWK authentication scheme\",\n    \"schema\": \"https://schema.getpostman.com/json/collection/v2.0.0/collection.json\"\n  },\n  \"item\": [\n    {\n      \"name\": \"test hawk auth success\",\n      \"event\": [\n        {\n          \"listen\": \"test\",\n          \"script\": {\n            \"type\": \"text/javascript\",\n            \"exec\": [\n              \"pm.test('should authenticate correctly', function () {\",\n              \" pm.response.to.have.jsonBody('message', 'Hawk Authentication Successful');\",\n              \"});\"\n            ]\n          }\n        }\n      ],\n      \"request\": {\n        \"auth\": {\n          \"type\": \"hawk\",\n          \"hawk\": {\n            \"authId\": \"dh37fgj492je\",\n            \"authKey\": \"werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn\",\n            \"algorithm\": \"sha256\",\n            \"user\": \"asda\",\n            \"saveHelperData\": true,\n            \"nonce\": \"eFRP2o\",\n            \"extraData\": \"skjdfklsjhdflkjhsdf\",\n            \"appId\": \"\",\n            \"delegation\": \"\",\n            \"timestamp\": \"\"\n          }\n        },\n        \"url\": \"https://postman-echo.com/auth/hawk\",\n        \"method\": \"GET\",\n        \"header\": [\n          {\n            \"key\": \"Authorization\",\n            \"value\": \"Hawk id=\\\"dh37fgj492je\\\", ts=\\\"1448888081\\\", nonce=\\\"HoH6Ay\\\", ext=\\\"skjdfklsjhdflkjhsdf\\\", mac=\\\"moWleO5f/8QbvIiy7oo2zj1bmezhrYwrCkz4BsXg0M4=\\\"\",\n            \"description\": \"\"\n          }\n        ],\n        \"body\": {\n          \"mode\": \"formdata\",\n          \"formdata\": []\n        },\n        \"description\": \"\"\n      },\n      \"response\": []\n    }\n  ]\n}\n"
  },
  {
    "path": "test/integration/head-requests.postman_collection.json",
    "content": "{\n  \"variables\": [],\n  \"info\": {\n    \"name\": \"Head test\",\n    \"_postman_id\": \"9997428c-5951-3fd2-2a02-88bbe9d91c7f\",\n    \"description\": \"A set of tests for checking HEAD requests\",\n    \"schema\": \"https://schema.getpostman.com/json/collection/v2.0.0/collection.json\"\n  },\n  \"item\": [\n    {\n      \"name\": \"google\",\n      \"event\": [\n        {\n          \"listen\": \"test\",\n          \"script\": {\n            \"type\": \"text/javascript\",\n            \"exec\": \"tests['Status is 200 OK'] = responseCode.code === 200;\"\n          }\n        }\n      ],\n      \"request\": {\n        \"url\": \"http://google.com\",\n        \"method\": \"HEAD\",\n        \"header\": [],\n        \"body\": {\n          \"mode\": \"formdata\",\n          \"formdata\": []\n        },\n        \"description\": \"\"\n      },\n      \"response\": []\n    },\n    {\n      \"name\": \"github\",\n      \"event\": [\n        {\n          \"listen\": \"test\",\n          \"script\": {\n            \"type\": \"text/javascript\",\n            \"exec\": \"tests['Status is 200 OK'] = responseCode.code === 200;\"\n          }\n        }\n      ],\n      \"request\": {\n        \"url\": \"http://github.com\",\n        \"method\": \"HEAD\",\n        \"header\": [],\n        \"body\": {\n          \"mode\": \"formdata\",\n          \"formdata\": []\n        },\n        \"description\": \"\"\n      },\n      \"response\": []\n    },\n    {\n      \"name\": \"with request body\",\n      \"event\": [{\n        \"listen\": \"test\",\n        \"script\": {\n          \"id\": \"088721b0-c2e6-47fa-85b0-8a4f79c71f82\",\n          \"type\": \"text/javascript\",\n          \"exec\": [\n            \"pm.test(\\\"Response Body\\\", function () {\",\n            \"    var response = pm.response.headers.get('raw-request');\",\n            \"    pm.expect(response).to.contain('HEAD / HTTP/1.1');\",\n            \"    pm.expect(response).to.contain('Content-Type: multipart/form-data');\",\n            \"    pm.expect(response).to.contain('Content-Disposition: form-data;');\",\n            \"    pm.expect(response).to.contain('FormDataValue');\",\n            \"});\"\n          ]\n        }\n      }],\n      \"request\": {\n        \"url\": \"http://localhost:4041\",\n        \"method\": \"HEAD\",\n        \"header\": [],\n        \"body\": {\n          \"mode\": \"formdata\",\n          \"formdata\": [{\n            \"key\": \"dataKey\",\n            \"value\": \"FormDataValue\",\n            \"type\": \"text\"\n          }]\n        },\n        \"description\": \"\"\n      },\n      \"response\": [],\n      \"protocolProfileBehavior\": {\n        \"disableBodyPruning\": true\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": "test/integration/helper.postman_collection.json",
    "content": "{\n  \"variables\": [],\n  \"info\": {\n    \"name\": \"Helper Tests\",\n    \"_postman_id\": \"34783f86-4a67-d3bd-ba5b-148495fa2f72\",\n    \"description\": \"A set of tests to verify generated OAuth1 and Digest Auth signatures\",\n    \"schema\": \"https://schema.getpostman.com/json/collection/v2.0.0/collection.json\"\n  },\n  \"item\": [\n    {\n      \"name\": \"OAuth\",\n      \"event\": [\n        {\n          \"listen\": \"test\",\n          \"script\": {\n            \"type\": \"text/javascript\",\n            \"exec\": [\n              \"pm.test('should authorize correctly', function () {\",\n              \"  pm.response.to.have.jsonBody({\",\n              \"    status: 'pass',\",\n              \"    message: 'OAuth-1.0a signature verification was successful'\",\n              \"  })\",\n              \"  pm.request.to.have.header('Authorization');\",\n              \"});\"\n            ]\n          }\n        }\n      ],\n      \"request\": {\n        \"auth\": {\n          \"type\": \"oauth1\",\n          \"oauth1\": {\n            \"consumerKey\": \"RKCGzna7bv9YD57c\",\n            \"consumerSecret\": \"D+EdQ-gs$-%@2Nu7\",\n            \"token\": \"\",\n            \"tokenSecret\": \"\",\n            \"signatureMethod\": \"HMAC-SHA1\",\n            \"timeStamp\": 1461319769,\n            \"nonce\": \"ik3oT5\",\n            \"version\": \"1.0\",\n            \"realm\": \"\",\n            \"addParamsToHeader\": true,\n            \"addEmptyParamsToSign\": false\n          }\n        },\n        \"url\": \"https://postman-echo.com/oauth1\",\n        \"method\": \"GET\"\n      }\n    },\n    {\n      \"name\": \"basicAuth\",\n      \"event\": [\n        {\n          \"listen\": \"test\",\n          \"script\": {\n            \"type\": \"text/javascript\",\n            \"exec\": [\n              \"pm.test('Should authorize correctly', function () {\",\n              \"  pm.request.to.have.header('Authorization', 'Basic cG9zdG1hbjpwYXNzd29yZA==');\",\n              \"});\"\n            ]\n          }\n        }\n      ],\n      \"request\": {\n        \"auth\": {\n          \"type\": \"basic\",\n          \"basic\": {\n            \"username\": \"postman\",\n            \"password\": \"password\"\n          }\n        },\n        \"url\": \"https://postman-echo.com/basic-auth\",\n        \"method\": \"GET\"\n      },\n      \"response\": []\n    },\n    {\n      \"name\": \"DigestAuth\",\n      \"event\": [\n        {\n          \"listen\": \"test\",\n          \"script\": {\n            \"type\": \"text/javascript\",\n            \"exec\": [\n              \"pm.test('should authorize correctly', function () {\",\n              \"  pm.response.to.have.jsonBody({ authenticated: true });\",\n              \"});\"\n            ]\n          }\n        }\n      ],\n      \"request\": {\n        \"auth\": {\n          \"type\": \"digest\",\n          \"digest\": {\n            \"algorithm\": \"MD5\",\n            \"username\": \"postman\",\n            \"password\": \"password\"\n          }\n        },\n        \"url\": \"https://postman-echo.com/digest-auth\"\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": "test/integration/inherited-entities/inherited-entities.postman_collection.json",
    "content": "{\n  \"variable\": [{\n      \"key\": \"collection-var\",\n      \"value\": \"collection level variable\"\n    },\n    {\n      \"key\": \"collectionVariablesURL\",\n      \"value\": \"https://postman-echo.com/get?test=collection_variable\"\n    },\n    {\n      \"key\": \"duplicate-var\",\n      \"value\": \"incorrect\"\n    }\n  ],\n  \"auth\": {\n    \"type\": \"basic\",\n    \"basic\": [{\n      \"key\": \"username\",\n      \"value\": \"postman\"\n    }, {\n      \"key\": \"password\",\n      \"value\": \"password\"\n    }]\n  },\n  \"event\": [{\n    \"listen\": \"prerequest\",\n    \"script\": {\n      \"exec\": [\n        \"pm.environment.set('collectionScriptURL', 'https://postman-echo.com/get?test=collection_script');\"\n      ]\n    }\n  }],\n  \"name\": \"Inherited Entities\",\n  \"item\": [{\n      \"name\": \"Collection level stuff\",\n      \"item\": [{\n          \"name\": \"Variables\",\n          \"request\": \"{{collectionVariablesURL}}\",\n          \"event\": [{\n            \"listen\": \"test\",\n            \"script\": {\n              \"exec\": [\n                \"pm.test('request should get collection level variables', function() {\",\n                \"  pm.expect(pm.request.url.toString()).to.equal('https://postman-echo.com/get?test=collection_variable');\",\n                \"  pm.expect(pm.variables.get('collection-var')).to.equal('collection level variable');\",\n                \"  pm.expect(pm.variables.get('env-var')).to.equal('environment value');\",\n                \"});\"\n              ]\n            }\n          }]\n        }, {\n          \"name\": \"Auth\",\n          \"request\": \"https://postman-echo.com/basic-auth\",\n          \"event\": [{\n            \"listen\": \"test\",\n            \"script\": {\n              \"exec\": [\n                \"pm.test('request can be authenticated with collection level auth', function() {\",\n                \"  pm.expect(pm.response.code).to.equal(200);\",\n                \"});\"\n              ]\n            }\n          }]\n        },\n        {\n          \"name\": \"Events\",\n          \"request\": \"{{collectionScriptURL}}\",\n          \"event\": [{\n            \"listen\": \"test\",\n            \"script\": {\n              \"exec\": [\n                \"pm.test('request should have run collection level prerequest script', function() {\",\n                \"  pm.expect(pm.request.url.toString()).to.equal('https://postman-echo.com/get?test=collection_script');\",\n                \"});\",\n                \"pm.environment.unset('collectionScriptURL');\"\n              ]\n            }\n          }]\n        }\n      ]\n    },\n    {\n      \"name\": \"Folder level stuff\",\n      \"auth\": {\n        \"type\": \"digest\",\n        \"digest\": [{\n          \"key\": \"username\",\n          \"value\": \"postman\"\n        }, {\n          \"key\": \"password\",\n          \"value\": \"password\"\n        }]\n      },\n      \"event\": [{\n        \"listen\": \"prerequest\",\n        \"script\": {\n          \"exec\": [\n            \"pm.environment.set('folderScriptURL', 'https://postman-echo.com/get?test=folder_script')\"\n          ]\n        }\n      }],\n      \"item\": [{\n          \"request\": \"https://postman-echo.com/digest-auth\",\n          \"name\": \"Auth\",\n          \"event\": {\n            \"listen\": \"test\",\n            \"script\": {\n              \"exec\": [\n                \"pm.test('request should use folder level auth, over collection level auth', function() {\",\n                \"  pm.response.to.have.status(200);\",\n                \"});\"\n              ]\n            }\n          }\n        },\n        {\n          \"request\": \"{{folderScriptURL}}\",\n          \"name\": \"Event\",\n          \"event\": [{\n            \"listen\": \"test\",\n            \"script\": {\n              \"exec\": [\n                \"pm.test('request should have run folder level prerequest script', function() {\",\n                \"  pm.expect(pm.request.url.toString()).to.equal('https://postman-echo.com/get?test=folder_script');\",\n                \"});\",\n                \"pm.environment.unset('folderScriptURL');\"\n              ]\n            }\n          }]\n        }\n      ]\n    },\n    {\n      \"name\": \"Request level stuff\",\n      \"item\": [{\n        \"name\": \"Auth\",\n        \"request\": {\n          \"url\": \"https://postman-echo.com/digest-auth\",\n          \"auth\": {\n            \"type\": \"digest\",\n            \"digest\": [{\n              \"key\": \"username\",\n              \"value\": \"postman\"\n            }, {\n              \"key\": \"password\",\n              \"value\": \"password\"\n            }]\n          },\n          \"event\": [{\n            \"listen\": \"test\",\n            \"script\": {\n              \"exec\": [\n                \"pm.test('request should use request level auth, over collection level auth', function () {\",\n                \"  pm.response.to.have.status(200);\",\n                \"});\"\n              ]\n            }\n          }]\n        }\n      }]\n    },\n    {\n      \"name\": \"Auth override\",\n      \"request\": {\n        \"url\": \"https://postman-echo.com/basic-auth\",\n        \"auth\": {\n          \"type\": \"noauth\"\n        }\n      },\n      \"event\": [{\n        \"listen\": \"test\",\n        \"script\": {\n          \"exec\": [\n            \"pm.test('request should be able disable collection auth by setting noauth', function () {\",\n            \"  pm.response.to.have.status(401);\",\n            \"  pm.expect(pm.response.headers.has('Authorization')).to.equal(false);\",\n            \"});\"\n          ]\n        }\n      }]\n    },\n    {\n      \"name\": \"Environment override\",\n      \"request\": \"https://postman-echo.com/get\",\n      \"event\": [{\n        \"listen\": \"test\",\n        \"script\": {\n          \"exec\": [\n            \"pm.test('environment variables should override collection variables', function () {\",\n            \"  pm.expect(pm.variables.get('duplicate-var')).to.equal('correct');\",\n            \"});\"\n          ]\n        }\n      }]\n    }\n  ]\n}\n"
  },
  {
    "path": "test/integration/inherited-entities/inherited-entities.postman_environment.json",
    "content": "{\n  \"values\": [{\n    \"key\": \"env-var\",\n    \"value\": \"environment value\"\n  }, {\n    \"key\": \"duplicate-var\",\n    \"value\": \"correct\"\n  }]\n}\n"
  },
  {
    "path": "test/integration/multi-level-folders-v1.postman_collection.json",
    "content": "{\n  \"id\": \"e5f2e9cf-173b-c60a-7336-ac804a87d762\",\n  \"name\": \"multi-level-folders\",\n  \"description\": \"A simple V1 collection to test out multi level folder flows\",\n  \"order\": [\n    \"b7b3ea2c-85e1-43bb-99e4-bb0a7b3bdfe1\"\n  ],\n  \"folders_order\": [\n    \"5b5b57f0-0b87-42d6-8268-e1550e13e1f0\",\n    \"78d5c3d9-e2bf-456a-a0e7-847f7cabcefd\"\n  ],\n  \"folders\": [\n    {\n      \"id\": \"5b5b57f0-0b87-42d6-8268-e1550e13e1f0\",\n      \"name\": \"F1\",\n      \"description\": \"\",\n      \"order\": [\n        \"73d22bec-5403-4fc8-bd1b-f5ec237c5d16\",\n        \"f78296f9-baf2-446b-8450-fe6b982ba784\",\n        \"59b9a846-af89-45ad-85bf-1d5163c64747\"\n      ],\n      \"folders_order\": []\n    },\n    {\n      \"id\": \"78d5c3d9-e2bf-456a-a0e7-847f7cabcefd\",\n      \"name\": \"F2\",\n      \"description\": \"\",\n      \"order\": [\n        \"aacf3ebd-6c2b-4452-a6ba-a298f951f334\"\n      ],\n      \"folders_order\": [\n        \"b8b259fc-5e88-4aac-88b3-1adf205f7af2\",\n        \"2f003cb9-2fc3-479b-9aa5-9b254c581de9\"\n      ]\n    },\n    {\n      \"id\": \"b8b259fc-5e88-4aac-88b3-1adf205f7af2\",\n      \"name\": \"F2.F3\",\n      \"description\": \"\",\n      \"order\": [\n        \"072721f4-c04f-4172-a86b-b07fdfe5b8ee\"\n      ],\n      \"folders_order\": []\n    },\n    {\n      \"id\": \"2f003cb9-2fc3-479b-9aa5-9b254c581de9\",\n      \"name\": \"F4\",\n      \"description\": \"\",\n      \"order\": [],\n      \"folders_order\": []\n    }\n  ],\n  \"requests\": [\n    {\n      \"id\": \"73d22bec-5403-4fc8-bd1b-f5ec237c5d16\",\n      \"name\": \"F1.R1\",\n      \"description\": \"\",\n      \"collectionId\": \"e5f2e9cf-173b-c60a-7336-ac804a87d762\",\n      \"method\": \"GET\",\n      \"headers\": \"\",\n      \"data\": [],\n      \"rawModeData\": \"\",\n      \"tests\": \"tests[\\\"Status code is 200\\\"] = responseCode.code === 200;\\ntests[\\\"Request executed in correct order\\\"] = postman.getEnvironmentVariable(\\\"count\\\") === 0;\",\n      \"preRequestScript\": \"var count = parseInt(postman.getEnvironmentVariable(\\\"count\\\"));\\npostman.setEnvironmentVariable(\\\"count\\\", isNaN(count) ? 0 : count + 1);\",\n      \"url\": \"https://postman-echo.com/get\",\n      \"responses\": []\n    },\n    {\n      \"id\": \"f78296f9-baf2-446b-8450-fe6b982ba784\",\n      \"name\": \"F1.R2\",\n      \"description\": \"\",\n      \"collectionId\": \"e5f2e9cf-173b-c60a-7336-ac804a87d762\",\n      \"method\": \"GET\",\n      \"headers\": \"\",\n      \"data\": [],\n      \"rawModeData\": \"\",\n      \"tests\": \"tests[\\\"Status code is 200\\\"] = responseCode.code === 200;\\ntests[\\\"Request executed in correct order\\\"] = postman.getEnvironmentVariable(\\\"count\\\") === \\\"1\\\";\",\n      \"preRequestScript\": \"var count = parseInt(postman.getEnvironmentVariable(\\\"count\\\"));\\npostman.setEnvironmentVariable(\\\"count\\\", isNaN(count) ? 0 : count + 1);\",\n      \"url\": \"https://postman-echo.com/get\",\n      \"responses\": []\n    },\n    {\n      \"id\": \"59b9a846-af89-45ad-85bf-1d5163c64747\",\n      \"name\": \"F1.R3\",\n      \"description\": \"\",\n      \"collectionId\": \"e5f2e9cf-173b-c60a-7336-ac804a87d762\",\n      \"method\": \"GET\",\n      \"headers\": \"\",\n      \"data\": [],\n      \"rawModeData\": \"\",\n      \"tests\": \"tests[\\\"Status code is 200\\\"] = responseCode.code === 200;\\ntests[\\\"Request executed in correct order\\\"] = postman.getEnvironmentVariable(\\\"count\\\") === \\\"2\\\"\",\n      \"preRequestScript\": \"var count = parseInt(postman.getEnvironmentVariable(\\\"count\\\"));\\npostman.setEnvironmentVariable(\\\"count\\\", isNaN(count) ? 0 : count + 1);\",\n      \"url\": \"https://postman-echo.com/get\",\n      \"responses\": []\n    },\n    {\n      \"id\": \"072721f4-c04f-4172-a86b-b07fdfe5b8ee\",\n      \"name\": \"F2.F3.R1\",\n      \"description\": \"\",\n      \"collectionId\": \"e5f2e9cf-173b-c60a-7336-ac804a87d762\",\n      \"method\": \"GET\",\n      \"headers\": \"\",\n      \"data\": [],\n      \"rawModeData\": \"\",\n      \"tests\": \"tests[\\\"Status code is 200\\\"] = responseCode.code === 200;\\ntests[\\\"Request executed in correct order\\\"] = postman.getEnvironmentVariable(\\\"count\\\") === \\\"3\\\";\",\n      \"preRequestScript\": \"var count = parseInt(postman.getEnvironmentVariable(\\\"count\\\"));\\npostman.setEnvironmentVariable(\\\"count\\\", isNaN(count) ? 0 : count + 1);\",\n      \"url\": \"https://postman-echo.com/get\",\n      \"responses\": []\n    },\n    {\n      \"id\": \"aacf3ebd-6c2b-4452-a6ba-a298f951f334\",\n      \"name\": \"F2.R1\",\n      \"description\": \"\",\n      \"collectionId\": \"e5f2e9cf-173b-c60a-7336-ac804a87d762\",\n      \"method\": \"GET\",\n      \"headers\": \"\",\n      \"data\": [],\n      \"rawModeData\": \"\",\n      \"tests\": \"tests[\\\"Status code is 200\\\"] = responseCode.code === 200;\\ntests[\\\"Request executed in correct order\\\"] = postman.getEnvironmentVariable(\\\"count\\\") === \\\"4\\\";\",\n      \"preRequestScript\": \"var count = parseInt(postman.getEnvironmentVariable(\\\"count\\\"));\\npostman.setEnvironmentVariable(\\\"count\\\", isNaN(count) ? 0 : count + 1);\",\n      \"url\": \"https://postman-echo.com/get\",\n      \"responses\": []\n    },\n    {\n      \"id\": \"b7b3ea2c-85e1-43bb-99e4-bb0a7b3bdfe1\",\n      \"name\": \"R1\",\n      \"description\": \"\",\n      \"collectionId\": \"e5f2e9cf-173b-c60a-7336-ac804a87d762\",\n      \"method\": \"GET\",\n      \"headers\": \"\",\n      \"data\": [],\n      \"rawModeData\": \"\",\n      \"tests\": \"tests[\\\"Status code is 200\\\"] = responseCode.code === 200;\\ntests[\\\"Request executed in correct order\\\"] = postman.getEnvironmentVariable(\\\"count\\\") === \\\"5\\\";\",\n      \"preRequestScript\": \"var count = parseInt(postman.getEnvironmentVariable(\\\"count\\\"));\\npostman.setEnvironmentVariable(\\\"count\\\", isNaN(count) ? 0 : count + 1);\",\n      \"url\": \"https://postman-echo.com/get\",\n      \"responses\": []\n    }\n  ]\n}\n"
  },
  {
    "path": "test/integration/multi-level-folders-v2.postman_collection.json",
    "content": "{\n  \"variables\": [],\n  \"info\": {\n    \"name\": \"multi-level-folders-v2\",\n    \"_postman_id\": \"e5f2e9cf-173b-c60a-7336-ac804a87d762\",\n    \"description\": \"A simple V2 collection to test out multi level folder flows\",\n    \"schema\": \"https://schema.getpostman.com/json/collection/v2.0.0/collection.json\"\n  },\n  \"item\": [\n    {\n      \"name\": \"F1\",\n      \"description\": \"\",\n      \"item\": [\n        {\n          \"name\": \"F1.R1\",\n          \"event\": [\n            {\n              \"listen\": \"prerequest\",\n              \"script\": {\n                \"type\": \"text/javascript\",\n                \"exec\": [\n                  \"var count = parseInt(postman.getEnvironmentVariable(\\\"count\\\"));\",\n                  \"postman.setEnvironmentVariable(\\\"count\\\", isNaN(count) ? 0 : count + 1);\"\n                ]\n              }\n            },\n            {\n              \"listen\": \"test\",\n              \"script\": {\n                \"type\": \"text/javascript\",\n                \"exec\": [\n                  \"tests[\\\"Status code is 200\\\"] = responseCode.code === 200;\",\n                  \"tests[\\\"Request executed in correct order\\\"] = postman.getEnvironmentVariable(\\\"count\\\") === 0;\"\n                ]\n              }\n            }\n          ],\n          \"request\": {\n            \"url\": \"https://postman-echo.com/get\",\n            \"method\": \"GET\",\n            \"header\": [],\n            \"body\": {},\n            \"description\": \"\"\n          },\n          \"response\": []\n        },\n        {\n          \"name\": \"F1.R2\",\n          \"event\": [\n            {\n              \"listen\": \"prerequest\",\n              \"script\": {\n                \"type\": \"text/javascript\",\n                \"exec\": [\n                  \"var count = parseInt(postman.getEnvironmentVariable(\\\"count\\\"));\",\n                  \"postman.setEnvironmentVariable(\\\"count\\\", isNaN(count) ? 0 : count + 1);\"\n                ]\n              }\n            },\n            {\n              \"listen\": \"test\",\n              \"script\": {\n                \"type\": \"text/javascript\",\n                \"exec\": [\n                  \"tests[\\\"Status code is 200\\\"] = responseCode.code === 200;\",\n                  \"tests[\\\"Request executed in correct order\\\"] = postman.getEnvironmentVariable(\\\"count\\\") === \\\"1\\\";\"\n                ]\n              }\n            }\n          ],\n          \"request\": {\n            \"url\": \"https://postman-echo.com/get\",\n            \"method\": \"GET\",\n            \"header\": [],\n            \"body\": {},\n            \"description\": \"\"\n          },\n          \"response\": []\n        },\n        {\n          \"name\": \"F1.R3\",\n          \"event\": [\n            {\n              \"listen\": \"prerequest\",\n              \"script\": {\n                \"type\": \"text/javascript\",\n                \"exec\": [\n                  \"var count = parseInt(postman.getEnvironmentVariable(\\\"count\\\"));\",\n                  \"postman.setEnvironmentVariable(\\\"count\\\", isNaN(count) ? 0 : count + 1);\"\n                ]\n              }\n            },\n            {\n              \"listen\": \"test\",\n              \"script\": {\n                \"type\": \"text/javascript\",\n                \"exec\": [\n                  \"tests[\\\"Status code is 200\\\"] = responseCode.code === 200;\",\n                  \"tests[\\\"Request executed in correct order\\\"] = postman.getEnvironmentVariable(\\\"count\\\") === \\\"2\\\";\"\n                ]\n              }\n            }\n          ],\n          \"request\": {\n            \"url\": \"https://postman-echo.com/get\",\n            \"method\": \"GET\",\n            \"header\": [],\n            \"body\": {},\n            \"description\": \"\"\n          },\n          \"response\": []\n        }\n      ]\n    },\n    {\n      \"name\": \"F2\",\n      \"description\": \"\",\n      \"item\": [\n        {\n          \"name\": \"F2.F3\",\n          \"description\": \"\",\n          \"item\": [\n            {\n              \"name\": \"F2.F3.R1\",\n              \"event\": [\n                {\n                  \"listen\": \"prerequest\",\n                  \"script\": {\n                    \"type\": \"text/javascript\",\n                    \"exec\": [\n                      \"var count = parseInt(postman.getEnvironmentVariable(\\\"count\\\"));\",\n                      \"postman.setEnvironmentVariable(\\\"count\\\", isNaN(count) ? 0 : count + 1);\"\n                    ]\n                  }\n                },\n                {\n                  \"listen\": \"test\",\n                  \"script\": {\n                    \"type\": \"text/javascript\",\n                    \"exec\": [\n                      \"tests[\\\"Status code is 200\\\"] = responseCode.code === 200;\",\n                      \"tests[\\\"Request executed in correct order\\\"] = postman.getEnvironmentVariable(\\\"count\\\") === \\\"3\\\";\"\n                    ]\n                  }\n                }\n              ],\n              \"request\": {\n                \"url\": \"https://postman-echo.com/get\",\n                \"method\": \"GET\",\n                \"header\": [],\n                \"body\": {},\n                \"description\": \"\"\n              },\n              \"response\": []\n            }\n          ]\n        },\n        {\n          \"name\": \"F4\",\n          \"description\": \"\",\n          \"item\": []\n        },\n        {\n          \"name\": \"F2.R1\",\n          \"event\": [\n            {\n              \"listen\": \"prerequest\",\n              \"script\": {\n                \"type\": \"text/javascript\",\n                \"exec\": [\n                  \"var count = parseInt(postman.getEnvironmentVariable(\\\"count\\\"));\",\n                  \"postman.setEnvironmentVariable(\\\"count\\\", isNaN(count) ? 0 : count + 1);\"\n                ]\n              }\n            },\n            {\n              \"listen\": \"test\",\n              \"script\": {\n                \"type\": \"text/javascript\",\n                \"exec\": [\n                  \"tests[\\\"Status code is 200\\\"] = responseCode.code === 200;\",\n                  \"tests[\\\"Request executed in correct order\\\"] = postman.getEnvironmentVariable(\\\"count\\\") === \\\"4\\\";\"\n                ]\n              }\n            }\n          ],\n          \"request\": {\n            \"url\": \"https://postman-echo.com/get\",\n            \"method\": \"GET\",\n            \"header\": [],\n            \"body\": {},\n            \"description\": \"\"\n          },\n          \"response\": []\n        }\n      ]\n    },\n    {\n      \"name\": \"R1\",\n      \"event\": [\n        {\n          \"listen\": \"prerequest\",\n          \"script\": {\n            \"type\": \"text/javascript\",\n            \"exec\": [\n              \"var count = parseInt(postman.getEnvironmentVariable(\\\"count\\\"));\",\n              \"postman.setEnvironmentVariable(\\\"count\\\", isNaN(count) ? 0 : count + 1);\"\n            ]\n          }\n        },\n        {\n          \"listen\": \"test\",\n          \"script\": {\n            \"type\": \"text/javascript\",\n            \"exec\": [\n              \"tests[\\\"Status code is 200\\\"] = responseCode.code === 200;\",\n              \"tests[\\\"Request executed in correct order\\\"] = postman.getEnvironmentVariable(\\\"count\\\") === \\\"5\\\";\"\n            ]\n          }\n        }\n      ],\n      \"request\": {\n        \"url\": \"https://postman-echo.com/get\",\n        \"method\": \"GET\",\n        \"header\": [],\n        \"body\": {},\n        \"description\": \"\"\n      },\n      \"response\": []\n    }\n  ]\n}\n"
  },
  {
    "path": "test/integration/multi-value-data.postman_collection.json",
    "content": "{\n  \"variables\": [],\n  \"info\": {\n    \"name\": \"Mutli-valued formdata props\",\n    \"_postman_id\": \"bd279aba-66c1-a145-5acb-e0e2fcf23465\",\n    \"description\": \"A set of tests checking if multiple formdata props with the same key are sent correctly\",\n    \"schema\": \"https://schema.getpostman.com/json/collection/v2.0.0/collection.json\"\n  },\n  \"item\": [\n    {\n      \"name\": \"r1\",\n      \"event\": [\n        {\n          \"listen\": \"test\",\n          \"script\": {\n            \"type\": \"text/javascript\",\n            \"exec\": \"var data = request.data; tests['request data array correct'] = (_.isArray(data.name))\"\n          }\n        }\n      ],\n      \"request\": {\n        \"url\": \"https://postman-echo.com/get?a={{$randomInt}}\",\n        \"method\": \"GET\",\n        \"header\": [],\n        \"body\": {\n          \"mode\": \"formdata\",\n          \"formdata\": [\n            {\n              \"key\": \"name\",\n              \"value\": \"sampleName\"\n            },\n            {\n              \"key\": \"name\",\n              \"value\": \"sampleName2\"\n            }\n          ]\n        },\n        \"description\": \"\"\n      },\n      \"response\": []\n    }\n  ]\n}\n"
  },
  {
    "path": "test/integration/multiple-form-values.postman_collection.json",
    "content": "{\n  \"variables\": [],\n  \"info\": {\n    \"name\": \"multipleFormValues\",\n    \"_postman_id\": \"8feefa71-aa26-c53a-c9bb-069cb688a041\",\n    \"description\": \"A test to check for successful sending of multiple / empty values for form data\",\n    \"schema\": \"https://schema.getpostman.com/json/collection/v2.0.0/collection.json\"\n  },\n  \"item\": [\n    {\n      \"name\": \"multiformvalues\",\n      \"event\": [\n        {\n          \"listen\": \"test\",\n          \"script\": {\n            \"type\": \"text/javascript\",\n            \"exec\": \"var data = JSON.parse(responseBody);\\n\\n\\ntests[\\\"multiple values for form variable\\\"] = data.args.hi.length === 2;\"\n          }\n        }\n      ],\n      \"request\": {\n        \"url\": \"https://postman-echo.com/get?hi=hello&hi=lolol\",\n        \"method\": \"GET\",\n        \"header\": [],\n        \"body\": {\n          \"mode\": \"formdata\",\n          \"formdata\": []\n        },\n        \"description\": \"\"\n      },\n      \"response\": []\n    },\n    {\n      \"name\": \"multiformvalues\",\n      \"event\": [\n        {\n          \"listen\": \"test\",\n          \"script\": {\n            \"type\": \"text/javascript\",\n            \"exec\": \"var data = JSON.parse(responseBody);\\n\\n\\ntests[\\\"Can send empty urlencoded data\\\"] = responseCode.code===200;\"\n          }\n        }\n      ],\n      \"request\": {\n        \"url\": \"https://postman-echo.com/post\",\n        \"method\": \"POST\",\n        \"header\": [],\n        \"body\": {\n          \"mode\": \"urlencoded\",\n          \"urlencoded\": []\n        },\n        \"description\": \"\"\n      },\n      \"response\": []\n    },\n    {\n      \"name\": \"multiformvalues\",\n      \"event\": [\n        {\n          \"listen\": \"test\",\n          \"script\": {\n            \"type\": \"text/javascript\",\n            \"exec\": \"var data = JSON.parse(responseBody);\\n\\n\\ntests[\\\"Can send empty params data\\\"] = responseCode.code===200;\"\n          }\n        }\n      ],\n      \"request\": {\n        \"url\": \"https://postman-echo.com/post\",\n        \"method\": \"POST\",\n        \"header\": [],\n        \"body\": {\n          \"mode\": \"formdata\",\n          \"formdata\": []\n        },\n        \"description\": \"\"\n      },\n      \"response\": []\n    }\n  ]\n}\n"
  },
  {
    "path": "test/integration/newman-gzip-test.postman_collection.json",
    "content": "{\n  \"variables\": [],\n  \"info\": {\n    \"name\": \"gzip-encoded responses\",\n    \"_postman_id\": \"af5052df-c60d-be62-d098-65b00b03a944\",\n    \"description\": \"A test to check for the correct handling of gzip encoding\",\n    \"schema\": \"https://schema.getpostman.com/json/collection/v2.0.0/collection.json\"\n  },\n  \"item\": [\n    {\n      \"name\": \"https://postman-echo.com/gzip\",\n      \"event\": [\n        {\n          \"listen\": \"test\",\n          \"script\": {\n            \"type\": \"text/javascript\",\n            \"exec\": \"var res = JSON.parse(responseBody); tests['newman handles gzip properly'] = res.gzipped\"\n          }\n        }\n      ],\n      \"request\": {\n        \"url\": \"https://postman-echo.com/gzip\",\n        \"method\": \"GET\",\n        \"header\": [],\n        \"body\": {\n          \"mode\": \"formdata\",\n          \"formdata\": []\n        },\n        \"description\": \"\"\n      },\n      \"response\": []\n    }\n  ]\n}\n"
  },
  {
    "path": "test/integration/oauth1-var-in-url-params.postman_collection.json",
    "content": "{\n  \"variables\": [],\n  \"info\": {\n    \"name\": \"oauth1-params-in-url\",\n    \"_postman_id\": \"3cd655fb-f1e6-e06f-73ad-03cf3792a502\",\n    \"description\": \"A set of sanity tests to check the validity of set and retrieved OAuth1 tokens\",\n    \"schema\": \"https://schema.getpostman.com/json/collection/v2.0.0/collection.json\"\n  },\n  \"item\": [\n    {\n      \"name\": \"https://postman-echo.com/oauth1?a={{vala}}\",\n      \"event\": [\n        {\n          \"listen\": \"prerequest\",\n          \"script\": {\n            \"type\": \"text/javascript\",\n            \"exec\": \"postman.setEnvironmentVariable('vala', 'omg');\"\n          }\n        }\n      ],\n      \"request\": {\n        \"auth\": {\n          \"type\": \"oauth1\",\n          \"oauth1\": {\n            \"consumerKey\": \"RKCGzna7bv9YD57c\",\n            \"consumerSecret\": \"D+EdQ-gs$-%@2Nu7\",\n            \"token\": \"\",\n            \"tokenSecret\": \"\",\n            \"signatureMethod\": \"HMAC-SHA1\",\n            \"timeStamp\": 1461319769,\n            \"nonce\": \"ik3oT5\",\n            \"version\": \"1.0\",\n            \"realm\": \"\",\n            \"addParamsToHeader\": true,\n            \"addEmptyParamsToSign\": false\n          }\n        },\n        \"url\": \"https://postman-echo.com/oauth1?a={{vala}}\",\n        \"method\": \"GET\",\n        \"header\": [\n          {\n            \"key\": \"Authorization\",\n            \"value\": \"OAuth oauth_consumer_key=\\\"RKCGzna7bv9YD57c\\\",oauth_signature_method=\\\"HMAC-SHA1\\\",oauth_timestamp=\\\"1461319769\\\",oauth_nonce=\\\"ik3oT5\\\",oauth_version=\\\"1.0\\\",oauth_signature=\\\"x0gnkYdST73FwY8oAqtV2O9MzGc%3D\\\"\",\n            \"description\": \"\"\n          }\n        ],\n        \"body\": {\n          \"mode\": \"formdata\",\n          \"formdata\": []\n        },\n        \"description\": \"\"\n      },\n      \"response\": []\n    }\n  ]\n}\n"
  },
  {
    "path": "test/integration/protocol-profile-behavior.postman_collection.json",
    "content": "{\n  \"info\": {\n    \"_postman_id\": \"5732ca26-4afb-4257-b793-f35ed4dcc46f\",\n    \"name\": \"protocol-profile-behavior\",\n    \"schema\": \"https://schema.getpostman.com/json/collection/v2.1.0/collection.json\"\n  },\n  \"item\": [{\n      \"name\": \"followRedirects\",\n      \"item\": [{\n          \"name\": \"followRedirects: true\",\n          \"event\": [{\n            \"listen\": \"test\",\n            \"script\": {\n              \"id\": \"540f949d-5861-4067-8211-b17d51fba726\",\n              \"exec\": [\n                \"const responseJSON = pm.response.json();\",\n                \"\",\n                \"pm.test(\\\"Status code is 200\\\", function () {\",\n                \"    pm.response.to.have.status(200);\",\n                \"});\",\n                \"\",\n                \"pm.test(\\\"Response body sanity\\\", function () {\",\n                \"    pm.expect(responseJSON).to.have.property('url', '/');\",\n                \"    pm.expect(responseJSON).to.have.property('method', 'GET');\",\n                \"    pm.expect(responseJSON).to.have.property('data', '');\",\n                \"});\"\n              ],\n              \"type\": \"text/javascript\"\n            }\n          }],\n          \"request\": {\n            \"method\": \"GET\",\n            \"header\": [],\n            \"body\": {\n              \"mode\": \"raw\",\n              \"raw\": \"\"\n            },\n            \"url\": {\n              \"raw\": \"localhost:4042/1\",\n              \"host\": [\n                \"localhost\"\n              ],\n              \"port\": \"4042\",\n              \"path\": [\n                \"1\"\n              ]\n            }\n          },\n          \"response\": []\n        },\n        {\n          \"name\": \"followRedirects: false\",\n          \"event\": [{\n            \"listen\": \"test\",\n            \"script\": {\n              \"id\": \"540f949d-5861-4067-8211-b17d51fba726\",\n              \"exec\": [\n                \"pm.test(\\\"Status code is 302\\\", function () {\",\n                \"    pm.response.to.have.status(302);\",\n                \"});\",\n                \"\",\n                \"pm.test(\\\"Location header is present\\\", function () {\",\n                \"    pm.response.to.have.header(\\\"location\\\");\",\n                \"});\"\n              ],\n              \"type\": \"text/javascript\"\n            }\n          }],\n          \"request\": {\n            \"method\": \"GET\",\n            \"header\": [],\n            \"body\": {\n              \"mode\": \"raw\",\n              \"raw\": \"\"\n            },\n            \"url\": {\n              \"raw\": \"localhost:4042/1\",\n              \"host\": [\n                \"localhost\"\n              ],\n              \"port\": \"4042\",\n              \"path\": [\n                \"1\"\n              ]\n            }\n          },\n          \"response\": [],\n          \"protocolProfileBehavior\": {\n            \"followRedirects\": false\n          }\n        }\n      ],\n      \"protocolProfileBehavior\": {\n        \"followRedirects\": true\n      }\n    },\n    {\n      \"name\": \"followOriginalHttpMethod\",\n      \"item\": [{\n          \"name\": \"followOriginalHttpMethod: true\",\n          \"event\": [{\n            \"listen\": \"test\",\n            \"script\": {\n              \"id\": \"540f949d-5861-4067-8211-b17d51fba726\",\n              \"exec\": [\n                \"const responseJSON = pm.response.json();\",\n                \"\",\n                \"pm.test(\\\"Status code is 200\\\", function () {\",\n                \"    pm.response.to.have.status(200);\",\n                \"});\",\n                \"\",\n                \"pm.test(\\\"Response body sanity\\\", function () {\",\n                \"    pm.expect(responseJSON).to.have.property('url', '/');\",\n                \"    pm.expect(responseJSON).to.have.property('method', 'DELETE');\",\n                \"    pm.expect(responseJSON).to.have.property('data', '');\",\n                \"});\"\n              ],\n              \"type\": \"text/javascript\"\n            }\n          }],\n          \"request\": {\n            \"method\": \"DELETE\",\n            \"header\": [],\n            \"body\": {\n              \"mode\": \"raw\",\n              \"raw\": \"\"\n            },\n            \"url\": {\n              \"raw\": \"localhost:4042/1\",\n              \"host\": [\n                \"localhost\"\n              ],\n              \"port\": \"4042\",\n              \"path\": [\n                \"1\"\n              ]\n            }\n          },\n          \"response\": []\n        },\n        {\n          \"name\": \"followOriginalHttpMethod: false\",\n          \"event\": [{\n            \"listen\": \"test\",\n            \"script\": {\n              \"id\": \"540f949d-5861-4067-8211-b17d51fba726\",\n              \"exec\": [\n                \"const responseJSON = pm.response.json();\",\n                \"\",\n                \"pm.test(\\\"Status code is 200\\\", function () {\",\n                \"    pm.response.to.have.status(200);\",\n                \"});\",\n                \"\",\n                \"pm.test(\\\"Response body sanity\\\", function () {\",\n                \"    pm.expect(responseJSON).to.have.property('url', '/');\",\n                \"    pm.expect(responseJSON).to.have.property('method', 'GET');\",\n                \"    pm.expect(responseJSON).to.have.property('data', '');\",\n                \"});\"\n              ],\n              \"type\": \"text/javascript\"\n            }\n          }],\n          \"request\": {\n            \"method\": \"DELETE\",\n            \"header\": [],\n            \"body\": {\n              \"mode\": \"raw\",\n              \"raw\": \"\"\n            },\n            \"url\": {\n              \"raw\": \"localhost:4042/1\",\n              \"host\": [\n                \"localhost\"\n              ],\n              \"port\": \"4042\",\n              \"path\": [\n                \"1\"\n              ]\n            }\n          },\n          \"response\": [],\n          \"protocolProfileBehavior\": {\n            \"followOriginalHttpMethod\": false\n          }\n        }\n      ],\n      \"protocolProfileBehavior\": {\n        \"followRedirects\": true,\n        \"followOriginalHttpMethod\": true\n      }\n    },\n    {\n      \"name\": \"removeRefererHeaderOnRedirect\",\n      \"item\": [{\n          \"name\": \"removeRefererHeaderOnRedirect: false\",\n          \"event\": [{\n            \"listen\": \"test\",\n            \"script\": {\n              \"id\": \"540f949d-5861-4067-8211-b17d51fba726\",\n              \"exec\": [\n                \"const responseJSON = pm.response.json();\",\n                \"\",\n                \"pm.test(\\\"Status code is 200\\\", function () {\",\n                \"    pm.response.to.have.status(200);\",\n                \"});\",\n                \"\",\n                \"pm.test(\\\"Response body sanity\\\", function () {\",\n                \"    pm.expect(responseJSON).to.have.property('url', '/');\",\n                \"    pm.expect(responseJSON).to.have.property('method', 'GET');\",\n                \"    pm.expect(responseJSON).to.have.property('headers')\",\n                \"        .that.have.property('referer', 'http://localhost:4042/1');\",\n                \"});\"\n              ],\n              \"type\": \"text/javascript\"\n            }\n          }],\n          \"request\": {\n            \"method\": \"GET\",\n            \"header\": [],\n            \"body\": {\n              \"mode\": \"raw\",\n              \"raw\": \"\"\n            },\n            \"url\": {\n              \"raw\": \"localhost:4042/1\",\n              \"host\": [\n                \"localhost\"\n              ],\n              \"port\": \"4042\",\n              \"path\": [\n                \"1\"\n              ]\n            }\n          },\n          \"response\": [],\n          \"protocolProfileBehavior\": {\n            \"followRedirects\": true\n          }\n        },\n        {\n          \"name\": \"removeRefererHeaderOnRedirect: true\",\n          \"event\": [{\n            \"listen\": \"test\",\n            \"script\": {\n              \"id\": \"540f949d-5861-4067-8211-b17d51fba726\",\n              \"exec\": [\n                \"const responseJSON = pm.response.json();\",\n                \"\",\n                \"pm.test(\\\"Status code is 200\\\", function () {\",\n                \"    pm.response.to.have.status(200);\",\n                \"});\",\n                \"\",\n                \"pm.test(\\\"Response body sanity\\\", function () {\",\n                \"    pm.expect(responseJSON).to.have.property('url', '/');\",\n                \"    pm.expect(responseJSON).to.have.property('method', 'GET');\",\n                \"    pm.expect(responseJSON).to.have.property('headers')\",\n                \"        .that.not.have.property('referer');\",\n                \"});\"\n              ],\n              \"type\": \"text/javascript\"\n            }\n          }],\n          \"request\": {\n            \"method\": \"GET\",\n            \"header\": [],\n            \"body\": {\n              \"mode\": \"raw\",\n              \"raw\": \"\"\n            },\n            \"url\": {\n              \"raw\": \"localhost:4042/1\",\n              \"host\": [\n                \"localhost\"\n              ],\n              \"port\": \"4042\",\n              \"path\": [\n                \"1\"\n              ]\n            }\n          },\n          \"response\": [],\n          \"protocolProfileBehavior\": {\n            \"followRedirects\": true,\n            \"removeRefererHeaderOnRedirect\": true\n          }\n        },\n        {\n          \"name\": \"removeRefererHeaderOnRedirect: true + initial referer\",\n          \"event\": [{\n            \"listen\": \"test\",\n            \"script\": {\n              \"id\": \"540f949d-5861-4067-8211-b17d51fba726\",\n              \"exec\": [\n                \"const responseJSON = pm.response.json();\",\n                \"\",\n                \"pm.test(\\\"Status code is 200\\\", function () {\",\n                \"    pm.response.to.have.status(200);\",\n                \"});\",\n                \"\",\n                \"pm.test(\\\"Response body sanity\\\", function () {\",\n                \"    pm.expect(responseJSON).to.have.property('url', '/');\",\n                \"    pm.expect(responseJSON).to.have.property('method', 'GET');\",\n                \"    pm.expect(responseJSON).to.have.property('headers')\",\n                \"        .that.have.property('referer', 'INITIAL_REFERER');\",\n                \"});\"\n              ],\n              \"type\": \"text/javascript\"\n            }\n          }],\n          \"request\": {\n            \"method\": \"GET\",\n            \"header\": [{\n              \"key\": \"referer\",\n              \"value\": \"INITIAL_REFERER\",\n              \"type\": \"text\"\n            }],\n            \"body\": {\n              \"mode\": \"raw\",\n              \"raw\": \"\"\n            },\n            \"url\": {\n              \"raw\": \"localhost:4042/1\",\n              \"host\": [\n                \"localhost\"\n              ],\n              \"port\": \"4042\",\n              \"path\": [\n                \"1\"\n              ]\n            }\n          },\n          \"response\": [],\n          \"protocolProfileBehavior\": {\n            \"followRedirects\": true,\n            \"removeRefererHeaderOnRedirect\": true\n          }\n        }\n      ],\n      \"protocolProfileBehavior\": {\n        \"removeRefererHeaderOnRedirect\": false\n      }\n    },\n    {\n      \"name\": \"maxRedirects\",\n      \"event\": [{\n        \"listen\": \"test\",\n        \"script\": {\n          \"id\": \"540f949d-5861-4067-8211-b17d51fba726\",\n          \"exec\": [\n            \"const responseJSON = pm.response.json();\",\n            \"\",\n            \"pm.test(\\\"Status code is 200\\\", function () {\",\n            \"    pm.response.to.have.status(200);\",\n            \"});\",\n            \"\",\n            \"pm.test(\\\"Response body sanity\\\", function () {\",\n            \"    pm.expect(responseJSON).to.have.property('url', '/');\",\n            \"    pm.expect(responseJSON).to.have.property('method', 'GET');\",\n            \"    pm.expect(responseJSON).to.have.property('data', '');\",\n            \"});\"\n          ],\n          \"type\": \"text/javascript\"\n        }\n      }],\n      \"request\": {\n        \"method\": \"POST\",\n        \"header\": [],\n        \"body\": {\n          \"mode\": \"raw\",\n          \"raw\": \"\"\n        },\n        \"url\": {\n          \"raw\": \"localhost:4042/11\",\n          \"host\": [\n            \"localhost\"\n          ],\n          \"port\": \"4042\",\n          \"path\": [\n            \"11\"\n          ]\n        }\n      },\n      \"response\": [],\n      \"protocolProfileBehavior\": {\n        \"followRedirects\": true,\n        \"maxRedirects\": 11\n      }\n    }\n  ],\n  \"protocolProfileBehavior\": {\n    \"maxRedirects\": 10,\n    \"followRedirects\": false,\n    \"followOriginalHttpMethod\": false,\n    \"removeRefererHeaderOnRedirect\": false\n  }\n}\n"
  },
  {
    "path": "test/integration/prototype-check.postman_collection.json",
    "content": "{\n\t\"variables\": [],\n\t\"info\": {\n\t\t\"name\": \"SugarJS and native prototypes work\",\n\t\t\"_postman_id\": \"8f31aeff-c5b5-5c42-9540-fae109785538\",\n\t\t\"description\": \"A set of requests to test Array, String, Date, and Function prototypes\",\n\t\t\"schema\": \"https://schema.getpostman.com/json/collection/v2.0.0/collection.json\"\n\t},\n\t\"item\": [\n\t\t{\n\t\t\t\"name\": \"objectPrototype\",\n\t\t\t\"event\": [\n\t\t\t\t{\n\t\t\t\t\t\"listen\": \"test\",\n\t\t\t\t\t\"script\": {\n\t\t\t\t\t\t\"type\": \"text/javascript\",\n\t\t\t\t\t\t\"exec\": \"// Extended Array prototype tests\\ntests[\\\"Array prototype none\\\"] = ['a', 'b', 'c'].none('d');\\ntests[\\\"Array prototype any\\\"] = [ [1,2], [2,3] ].any([2,3]);\\ntests[\\\"Array prototype average\\\"] = [ 1, 2, 3, 4, 5 ].average() === 3;\\n\\n// Extended Date prototype tests\\ntests[\\\"Date prototype getTime\\\"] = Date.now()==(new Date()).getTime();\\n\\n// Extended Function prototype tests\\nvar fCount = 0;\\nvar fn = (function() {\\n  fCount++;\\n}).once(); fn(); fn(); fn();\\ntests[\\\"Function prototype once\\\"] = fCount===1;\\n\\n// Extended Number prototype tests\\ntests[\\\"Number prototype hex\\\"] = (56).hex() === '38';\\ntests[\\\"Number prototype isEven\\\"] = (56).isEven() === true;\\ntests[\\\"Number prototype ordinalize\\\"] = (56).ordinalize() === '56th';\\ntests[\\\"Number prototype format\\\"] = (56789.10).format() === '56,789.1';\\n\\n// Extended String prototype tests\\ntests[\\\"String prototype endsWith\\\"] = 'jumpy'.endsWith('py');\\ntests[\\\"String prototype negated endsWith\\\"] = !('jumpy'.endsWith('MPY'));\\ntests[\\\"String prototype camelize\\\"] = 'a-beta'.camelize() === 'ABeta';\\ntests[\\\"String prototype repeat\\\"] = 'a'.repeat(5) === 'aaaaa';\\ntests[\\\"String prototype shift\\\"] = 'abc'.shift(5) === 'fgh';\\ntests[\\\"String prototype spacify\\\"] = 'a-b_cD'.spacify() === 'a b c d';\"\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t],\n\t\t\t\"request\": {\n\t\t\t\t\"url\": \"postman-echo.com/get\",\n\t\t\t\t\"method\": \"GET\",\n\t\t\t\t\"header\": [],\n\t\t\t\t\"body\": {\n\t\t\t\t\t\"mode\": \"formdata\",\n\t\t\t\t\t\"formdata\": []\n\t\t\t\t},\n\t\t\t\t\"description\": \"\"\n\t\t\t},\n\t\t\t\"response\": []\n\t\t}\n\t]\n}\n"
  },
  {
    "path": "test/integration/redirect-test/redirect-test.postman_collection.json",
    "content": "{\n  \"variables\": [],\n  \"info\": {\n    \"name\": \"redirectTest\",\n    \"_postman_id\": \"be3bf661-9803-6712-5f8e-ff5fcf1ba5db\",\n    \"description\": \"A test to check for proper redirection responses\",\n    \"schema\": \"https://schema.getpostman.com/json/collection/v2.0.0/collection.json\"\n  },\n  \"item\": [\n    {\n      \"name\": \"r1\",\n      \"event\": [\n        {\n          \"listen\": \"test\",\n          \"script\": {\n            \"type\": \"text/javascript\",\n            \"exec\": \"return 0; tests[\\\"Returned 302\\\"] = responseCode.code===302;\"\n          }\n        }\n      ],\n      \"request\": {\n        \"url\": \"https://postman-echo.com/redirect-to?url=https://postman-echo.com/get\",\n        \"method\": \"GET\",\n        \"header\": [],\n        \"body\": {\n          \"mode\": \"formdata\",\n          \"formdata\": []\n        },\n        \"description\": \"\"\n      },\n      \"response\": []\n    }\n  ]\n}\n"
  },
  {
    "path": "test/integration/redirect-test/redirect-test.postman_config.json",
    "content": "{\n  \"run\": {\n    \"ignoreRedirects\": true\n  }\n}\n"
  },
  {
    "path": "test/integration/redirect-test/redirect-with-body.postman_collection.json",
    "content": "{\n  \"info\": {\n    \"_postman_id\": \"9f20bc41-541b-420c-a0dc-0e25d019e241\",\n    \"name\": \"redirect-with-body\",\n    \"schema\": \"https://schema.getpostman.com/json/collection/v2.1.0/collection.json\"\n  },\n  \"item\": [{\n      \"name\": \"PUT 307 + FormData\",\n      \"event\": [{\n        \"listen\": \"test\",\n        \"script\": {\n          \"id\": \"05db1385-6c2d-4432-998c-3dfd60f06102\",\n          \"exec\": [\n            \"const responseJSON = pm.response.json();\",\n            \"\",\n            \"pm.test(\\\"Status code is 200\\\", function () {\",\n            \"    pm.response.to.have.status(200);\",\n            \"});\",\n            \"\",\n            \"\",\n            \"pm.test(\\\"Response body sanity\\\", function () {\",\n            \"    pm.expect(responseJSON).to.have.property('url', '/');\",\n            \"    pm.expect(responseJSON).to.have.property('method', 'PUT');\",\n            \"    pm.expect(responseJSON).to.have.property('data');\",\n            \"    pm.expect(responseJSON.data)\",\n            \"        .to.include('Content-Disposition: form-data; name=\\\"key1\\\"')\",\n            \"        .and.include('POSTMAN');\",\n            \"});\"\n          ],\n          \"type\": \"text/javascript\"\n        }\n      }],\n      \"request\": {\n        \"method\": \"PUT\",\n        \"header\": [],\n        \"body\": {\n          \"mode\": \"formdata\",\n          \"formdata\": [{\n            \"key\": \"key1\",\n            \"value\": \"POSTMAN\",\n            \"type\": \"text\"\n          }]\n        },\n        \"url\": {\n          \"raw\": \"localhost:4042/status/307\",\n          \"host\": [\n            \"localhost\"\n          ],\n          \"port\": \"4042\",\n          \"path\": [\n            \"status\",\n            \"307\"\n          ]\n        }\n      },\n      \"response\": []\n    },\n    {\n      \"name\": \"POST 307 + Raw\",\n      \"event\": [{\n        \"listen\": \"test\",\n        \"script\": {\n          \"id\": \"05db1385-6c2d-4432-998c-3dfd60f06102\",\n          \"exec\": [\n            \"const responseJSON = pm.response.json();\",\n            \"\",\n            \"pm.test(\\\"Status code is 200\\\", function () {\",\n            \"    pm.response.to.have.status(200);\",\n            \"});\",\n            \"\",\n            \"\",\n            \"pm.test(\\\"Response body sanity\\\", function () {\",\n            \"    pm.expect(responseJSON).to.have.property('url', '/');\",\n            \"    pm.expect(responseJSON).to.have.property('method', 'POST');\",\n            \"    pm.expect(responseJSON).to.have.property('data', 'POSTMAN');\",\n            \"});\"\n          ],\n          \"type\": \"text/javascript\"\n        }\n      }],\n      \"request\": {\n        \"method\": \"POST\",\n        \"header\": [],\n        \"body\": {\n          \"mode\": \"raw\",\n          \"raw\": \"POSTMAN\"\n        },\n        \"url\": {\n          \"raw\": \"localhost:4042/status/307\",\n          \"host\": [\n            \"localhost\"\n          ],\n          \"port\": \"4042\",\n          \"path\": [\n            \"status\",\n            \"307\"\n          ]\n        }\n      },\n      \"response\": []\n    },\n    {\n      \"name\": \"POST 308 + FormData\",\n      \"event\": [{\n        \"listen\": \"test\",\n        \"script\": {\n          \"id\": \"05db1385-6c2d-4432-998c-3dfd60f06102\",\n          \"exec\": [\n            \"const responseJSON = pm.response.json();\",\n            \"\",\n            \"pm.test(\\\"Status code is 200\\\", function () {\",\n            \"    pm.response.to.have.status(200);\",\n            \"});\",\n            \"\",\n            \"\",\n            \"pm.test(\\\"Response body sanity\\\", function () {\",\n            \"    pm.expect(responseJSON).to.have.property('url', '/');\",\n            \"    pm.expect(responseJSON).to.have.property('method', 'POST');\",\n            \"    pm.expect(responseJSON).to.have.property('data');\",\n            \"    pm.expect(responseJSON.data)\",\n            \"        .to.include('Content-Disposition: form-data; name=\\\"key1\\\"')\",\n            \"        .and.include('POSTMAN');\",\n            \"});\"\n          ],\n          \"type\": \"text/javascript\"\n        }\n      }],\n      \"request\": {\n        \"method\": \"POST\",\n        \"header\": [],\n        \"body\": {\n          \"mode\": \"formdata\",\n          \"formdata\": [{\n            \"key\": \"key1\",\n            \"value\": \"POSTMAN\",\n            \"type\": \"text\"\n          }]\n        },\n        \"url\": {\n          \"raw\": \"localhost:4042/status/308\",\n          \"host\": [\n            \"localhost\"\n          ],\n          \"port\": \"4042\",\n          \"path\": [\n            \"status\",\n            \"308\"\n          ]\n        }\n      },\n      \"response\": []\n    },\n    {\n      \"name\": \"PUT 308 + Raw\",\n      \"event\": [{\n        \"listen\": \"test\",\n        \"script\": {\n          \"id\": \"05db1385-6c2d-4432-998c-3dfd60f06102\",\n          \"exec\": [\n            \"const responseJSON = pm.response.json();\",\n            \"\",\n            \"pm.test(\\\"Status code is 200\\\", function () {\",\n            \"    pm.response.to.have.status(200);\",\n            \"});\",\n            \"\",\n            \"\",\n            \"pm.test(\\\"Response body sanity\\\", function () {\",\n            \"    pm.expect(responseJSON).to.have.property('url', '/');\",\n            \"    pm.expect(responseJSON).to.have.property('method', 'PUT');\",\n            \"    pm.expect(responseJSON).to.have.property('data', 'POSTMAN');\",\n            \"});\"\n          ],\n          \"type\": \"text/javascript\"\n        }\n      }],\n      \"request\": {\n        \"method\": \"PUT\",\n        \"header\": [],\n        \"body\": {\n          \"mode\": \"raw\",\n          \"raw\": \"POSTMAN\"\n        },\n        \"url\": {\n          \"raw\": \"localhost:4042/status/308\",\n          \"host\": [\n            \"localhost\"\n          ],\n          \"port\": \"4042\",\n          \"path\": [\n            \"status\",\n            \"308\"\n          ]\n        }\n      },\n      \"response\": []\n    }\n  ]\n}\n"
  },
  {
    "path": "test/integration/request-body-with-get.postman_collection.json",
    "content": "{\n  \"info\": {\n    \"_postman_id\": \"ecb63307-fc41-4180-a0f9-fc3d2abb5103\",\n    \"name\": \"request-body-with-get\",\n    \"schema\": \"https://schema.getpostman.com/json/collection/v2.1.0/collection.json\"\n  },\n  \"item\": [{\n      \"name\": \"default\",\n      \"event\": [{\n        \"listen\": \"test\",\n        \"script\": {\n          \"id\": \"b1617a42-0135-40e7-b7c1-d8e6cba90bf8\",\n          \"type\": \"text/javascript\",\n          \"exec\": [\n            \"pm.test(\\\"Response Body: default\\\", function () {\",\n            \"    var response = pm.response.text();\",\n            \"    pm.expect(response).to.contain('GET / HTTP/1.1');\",\n            \"    pm.expect(response).to.not.contain('Content-Type');\",\n            \"});\"\n          ]\n        }\n      }],\n      \"request\": {\n        \"method\": \"GET\",\n        \"header\": [],\n        \"body\": {\n          \"mode\": \"raw\",\n          \"raw\": \"{ \\\"foo\\\": \\\"bar\\\" }\"\n        },\n        \"url\": {\n          \"raw\": \"localhost:4041\",\n          \"host\": [\n            \"localhost\"\n          ],\n          \"port\": \"4041\"\n        }\n      },\n      \"response\": []\n    },\n    {\n      \"name\": \"form-data\",\n      \"event\": [{\n        \"listen\": \"test\",\n        \"script\": {\n          \"id\": \"540f949d-5861-4067-8211-b17d51fba726\",\n          \"type\": \"text/javascript\",\n          \"exec\": [\n            \"pm.test(\\\"Response Body: form-data\\\", function () {\",\n            \"    var response = pm.response.text();\",\n            \"    pm.expect(response).to.contain('GET / HTTP/1.1');\",\n            \"    pm.expect(response).to.contain('Content-Type: multipart/form-data');\",\n            \"    pm.expect(response).to.contain('Content-Disposition: form-data; name=\\\"dataKey\\\"');\",\n            \"});\"\n          ]\n        }\n      }],\n      \"request\": {\n        \"method\": \"GET\",\n        \"header\": [],\n        \"body\": {\n          \"mode\": \"formdata\",\n          \"formdata\": [{\n            \"key\": \"dataKey\",\n            \"value\": \"dataValue\",\n            \"type\": \"text\"\n          }]\n        },\n        \"url\": {\n          \"raw\": \"localhost:4041\",\n          \"host\": [\n            \"localhost\"\n          ],\n          \"port\": \"4041\"\n        }\n      },\n      \"response\": [],\n      \"protocolProfileBehavior\": {\n        \"disableBodyPruning\": true\n      }\n    },\n    {\n      \"name\": \"raw\",\n      \"event\": [{\n        \"listen\": \"test\",\n        \"script\": {\n          \"id\": \"36aee6c6-7565-412b-ad9b-0b48a1e3271f\",\n          \"type\": \"text/javascript\",\n          \"exec\": [\n            \"pm.test(\\\"Response Body: raw\\\", function () {\",\n            \"    var response = pm.response.text();\",\n            \"    pm.expect(response).to.contain('GET / HTTP/1.1');\",\n            \"    pm.expect(response).to.contain('Content-Type: application/json');\",\n            \"    pm.expect(response).to.contain('Content-Length: 16');\",\n            \"    pm.expect(response).to.contain('{ \\\"foo\\\": \\\"bar\\\" }');\",\n            \"});\"\n          ]\n        }\n      }],\n      \"request\": {\n        \"method\": \"GET\",\n        \"header\": [{\n          \"key\": \"Content-Type\",\n          \"value\": \"application/json\"\n        }],\n        \"body\": {\n          \"mode\": \"raw\",\n          \"raw\": \"{ \\\"foo\\\": \\\"bar\\\" }\"\n        },\n        \"url\": {\n          \"raw\": \"localhost:4041\",\n          \"host\": [\n            \"localhost\"\n          ],\n          \"port\": \"4041\"\n        }\n      },\n      \"response\": [],\n      \"protocolProfileBehavior\": {\n        \"disableBodyPruning\": true\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": "test/integration/request-chaining-test.postman_collection.json",
    "content": "{\n\t\"variables\": [],\n\t\"info\": {\n\t\t\"name\": \"newman-github-929\",\n\t\t\"_postman_id\": \"23e746e4-669b-c32e-0be5-724a07423a82\",\n\t\t\"description\": \"https://github.com/postmanlabs/newman/issues/929\",\n\t\t\"schema\": \"https://schema.getpostman.com/json/collection/v2.0.0/collection.json\"\n\t},\n\t\"item\": [\n\t\t{\n\t\t\t\"name\": \"Preliminary request\",\n\t\t\t\"event\": [\n\t\t\t\t{\n\t\t\t\t\t\"listen\": \"test\",\n\t\t\t\t\t\"script\": {\n\t\t\t\t\t\t\"type\": \"text/javascript\",\n\t\t\t\t\t\t\"exec\": [\n\t\t\t\t\t\t\t\"tests[\\\"Status code is 200\\\"] = responseCode.code === 200;\",\n\t\t\t\t\t\t\t\"tests[\\\"FOO doesn't exist\\\"] = !postman.getEnvironmentVariable(\\\"FOO\\\");\",\n\t\t\t\t\t\t\t\"tests[\\\"BAR doesn't exist\\\"] = !postman.getEnvironmentVariable(\\\"BAR\\\");\",\n\t\t\t\t\t\t\t\"\",\n\t\t\t\t\t\t\t\"postman.setEnvironmentVariable(\\\"FOO\\\", \\\"alpha\\\");\",\n\t\t\t\t\t\t\t\"postman.setEnvironmentVariable(\\\"BAR\\\", \\\"beta\\\");\",\n\t\t\t\t\t\t\t\"\"\n\t\t\t\t\t\t]\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t],\n\t\t\t\"request\": {\n\t\t\t\t\"url\": \"https://postman-echo.com/get?val={{FOO}}&val2={{BAR}}\",\n\t\t\t\t\"method\": \"GET\",\n\t\t\t\t\"header\": [],\n\t\t\t\t\"body\": {},\n\t\t\t\t\"description\": \"A simple GET request to seed environment variables `FOO` and `BAR`.\"\n\t\t\t},\n\t\t\t\"response\": []\n\t\t},\n\t\t{\n\t\t\t\"name\": \"Secondary request\",\n\t\t\t\"event\": [\n\t\t\t\t{\n\t\t\t\t\t\"listen\": \"test\",\n\t\t\t\t\t\"script\": {\n\t\t\t\t\t\t\"type\": \"text/javascript\",\n\t\t\t\t\t\t\"exec\": [\n              \"var args = JSON.parse(responseBody).args;\",\n\t\t\t\t\t\t\t\"tests[\\\"Status code is 200\\\"] = responseCode.code === 200;\",\n\t\t\t\t\t\t\t\"\",\n\t\t\t\t\t\t\t\"tests[\\\"FOO exists\\\"] = postman.getEnvironmentVariable(\\\"FOO\\\") === \\\"alpha\\\";\",\n\t\t\t\t\t\t\t\"tests[\\\"BAR exists\\\"] = postman.getEnvironmentVariable(\\\"BAR\\\") === \\\"beta\\\";\",\n              \"\",\n              \"tests[\\\"val1 query param was sent correctly\\\"] = args.val === \\\"alpha\\\";\",\n              \"tests[\\\"val1 query param was sent correctly\\\"] = args.val2 === \\\"beta\\\";\"\n\t\t\t\t\t\t]\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t],\n\t\t\t\"request\": {\n\t\t\t\t\"url\": \"https://postman-echo.com/get?val={{FOO}}&val2={{BAR}}\",\n\t\t\t\t\"method\": \"GET\",\n\t\t\t\t\"header\": [],\n\t\t\t\t\"body\": {},\n\t\t\t\t\"description\": \"A simple GET request to use seeded environment variables `FOO` and `BAR`.\"\n\t\t\t},\n\t\t\t\"response\": []\n\t\t}\n\t]\n}\n"
  },
  {
    "path": "test/integration/request-name-in-script.postman_collection.json",
    "content": "{\n  \"variables\": [],\n  \"info\": {\n    \"name\": \"Request Name In Script\",\n    \"_postman_id\": \"ce3bf661-9803-6712-5f8e-ff5fcf1ba5db\",\n    \"description\": \"A test to check for the presence of the request name in the script\",\n    \"schema\": \"https://schema.getpostman.com/json/collection/v2.0.0/collection.json\"\n  },\n  \"item\": [\n    {\n      \"name\": \"r1\",\n      \"event\": [\n        {\n          \"listen\": \"test\",\n          \"script\": {\n            \"type\": \"text/javascript\",\n            \"exec\": \"tests[\\\"correct request name and description\\\"] = (request.name===\\\"r1\\\" && request.description===\\\"testDesc\\\")\"\n          }\n        },\n        {\n          \"listen\": \"prerequest\",\n          \"script\": {\n            \"type\": \"text/javascript\",\n            \"exec\": \"if(request.name!==\\\"r1\\\" || request.description!==\\\"testDesc\\\") {undefFunction()}\"\n          }\n        }\n      ],\n      \"request\": {\n        \"url\": \"postman-echo.com/get\",\n        \"method\": \"GET\",\n        \"header\": [],\n        \"body\": {\n          \"mode\": \"formdata\",\n          \"formdata\": []\n        },\n        \"description\": \"testDesc\"\n      },\n      \"response\": []\n    }\n  ]\n}\n"
  },
  {
    "path": "test/integration/sandbox-libraries.postman_collection.json",
    "content": "{\n  \"info\": {\n    \"_postman_id\": \"6ff067bf-fe1b-4acd-b519-bd8a1cceb911\",\n    \"name\": \"sandbox-libraries\",\n    \"schema\": \"https://schema.getpostman.com/json/collection/v2.1.0/collection.json\"\n  },\n  \"item\": [{\n      \"name\": \"AJV\",\n      \"event\": [{\n        \"listen\": \"test\",\n        \"script\": {\n          \"id\": \"3d39684d-ee0d-4ac7-8dd7-226fe87321bf\",\n          \"exec\": [\n            \"var Ajv = require('ajv'),\",\n            \"    schema = {\",\n            \"        \\\"properties\\\": {\",\n            \"            \\\"alpha\\\": {\",\n            \"                \\\"type\\\": \\\"boolean\\\"\",\n            \"            }\",\n            \"        }\",\n            \"    };\",\n            \"\",\n            \"pm.test(\\\"ajv.validate\\\", function() {\",\n            \"    var ajv = new Ajv({\",\n            \"        logger: false\",\n            \"    });\",\n            \"\",\n            \"    pm.expect(ajv.validate(schema, {\",\n            \"        alpha: true\",\n            \"    })).to.be.true;\",\n            \"    pm.expect(ajv.validate(schema, {\",\n            \"        alpha: 123\",\n            \"    })).to.be.false;\",\n            \"});\",\n            \"\",\n            \"pm.test(\\\"ajv.compile\\\", function() {\",\n            \"    var ajv = new Ajv({\",\n            \"            logger: false\",\n            \"        }),\",\n            \"        validate = ajv.compile(schema);\",\n            \"\",\n            \"    pm.expect(validate({\",\n            \"        alpha: true\",\n            \"    })).to.be.true;\",\n            \"    pm.expect(validate({\",\n            \"        alpha: 123\",\n            \"    })).to.be.false;\",\n            \"});\"\n          ],\n          \"type\": \"text/javascript\"\n        }\n      }],\n      \"request\": {\n        \"method\": \"GET\",\n        \"url\": {\n          \"raw\": \"https://postman-echo.com/get\",\n          \"protocol\": \"https\",\n          \"host\": [\n            \"postman-echo\",\n            \"com\"\n          ],\n          \"path\": [\n            \"get\"\n          ]\n        }\n      }\n    },\n    {\n      \"name\": \"chai-postman\",\n      \"event\": [{\n        \"listen\": \"test\",\n        \"script\": {\n          \"id\": \"feee8d53-6799-4d75-84a8-e87a379f32f8\",\n          \"exec\": [\n            \"var schema = {\",\n            \"    properties: {\",\n            \"        alpha: {\",\n            \"            type: 'boolean'\",\n            \"        }\",\n            \"    }\",\n            \"};\",\n            \"\",\n            \"pm.test(\\\"0: valid schema\\\", function() {\",\n            \"    pm.expect({\",\n            \"        alpha: true\",\n            \"    }).to.be.jsonSchema(schema);\",\n            \"    pm.expect('POSTMAN').to.be.jsonSchema({\",\n            \"        \\\"type\\\": \\\"string\\\"\",\n            \"    });\",\n            \"});\",\n            \"\",\n            \"pm.test(\\\"1: negated assertions\\\", function() {\",\n            \"    pm.expect({\",\n            \"        alpha: 123\",\n            \"    }).to.not.be.jsonSchema(schema);\",\n            \"    pm.expect(123).to.not.be.jsonSchema({\",\n            \"        \\\"type\\\": \\\"string\\\"\",\n            \"    });\",\n            \"});\",\n            \"\",\n            \"pm.test(\\\"2: incorrect assertions\\\", function() {\",\n            \"    pm.expect(function() {\",\n            \"        pm.expect({\",\n            \"            alpha: 123\",\n            \"        }).to.be.jsonSchema(schema);\",\n            \"    }).to.throw('expected data to satisfy schema but found following errors: \\\\ndata.alpha should be boolean');\",\n            \"});\",\n            \"\",\n            \"pm.test(\\\"3: incorrect negated assertions\\\", function() {\",\n            \"    pm.expect(function() {\",\n            \"        pm.expect({\",\n            \"            alpha: true\",\n            \"        }).to.not.be.jsonSchema(schema);\",\n            \"    }).to.throw('expected data to not satisfy schema');\",\n            \"});\",\n            \"\",\n            \"pm.test(\\\"4: pm.response.to\\\", function() {\",\n            \"    pm.response.to.have.jsonSchema({\",\n            \"        properties: {\",\n            \"            url: {\",\n            \"                type: 'string'\",\n            \"            }\",\n            \"        }\",\n            \"    });\",\n            \"});\",\n            \"\",\n            \"pm.test(\\\"5: pm.response.to.not\\\", function() {\",\n            \"    pm.response.to.not.have.jsonSchema({\",\n            \"        properties: {\",\n            \"            url: {\",\n            \"                type: 'number'\",\n            \"            }\",\n            \"        }\",\n            \"    });\",\n            \"});\"\n          ],\n          \"type\": \"text/javascript\"\n        }\n      }],\n      \"request\": {\n        \"method\": \"GET\",\n        \"url\": {\n          \"raw\": \"https://postman-echo.com/get\",\n          \"protocol\": \"https\",\n          \"host\": [\n            \"postman-echo\",\n            \"com\"\n          ],\n          \"path\": [\n            \"get\"\n          ]\n        }\n      }\n    },\n    {\n      \"name\": \"pm api\",\n      \"event\": [{\n        \"listen\": \"test\",\n        \"script\": {\n          \"id\": \"feee8d53-6799-4d75-84a8-e87a379f32f8\",\n          \"exec\": [\n            \"pm.test(\\\"pre-assert request\\\", function() {\",\n            \"    pm.expect(pm.request).to.have.property('to');\",\n            \"    pm.expect(pm.request.to).to.be.an('object');\",\n            \"    pm.request.to.be.ok;\",\n            \"    pm.request.to.not.be.a.postmanResponse;\",\n            \"    pm.request.to.not.have.header('Foo-Bar');\",\n            \"    pm.request.to.have.header('host');\",\n            \"    pm.request.to.be.a.postmanRequestOrResponse;\",\n            \"});\",\n            \"\",\n            \"pm.test(\\\"pre-assert response\\\", function() {\",\n            \"    pm.response.to.be.ok;\",\n            \"    pm.response.to.not.be.a.postmanRequest;\",\n            \"    pm.response.to.not.be.serverError;\",\n            \"    pm.response.to.not.have.statusCode(400);\",\n            \"    pm.response.to.have.statusCode(200);\",\n            \"    pm.response.to.have.statusReason('OK');\",\n            \"});\"\n          ],\n          \"type\": \"text/javascript\"\n        }\n      }],\n      \"request\": {\n        \"method\": \"GET\",\n        \"url\": {\n          \"raw\": \"https://postman-echo.com/get\",\n          \"protocol\": \"https\",\n          \"host\": [\n            \"postman-echo\",\n            \"com\"\n          ],\n          \"path\": [\n            \"get\"\n          ]\n        }\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": "test/integration/semicolon-tests.postman_collection.json",
    "content": "{\n  \"variables\": [],\n  \"info\": {\n    \"name\": \"Response headers with semicolons are handled correctly\",\n    \"_postman_id\": \"f1639220-14aa-90da-0634-5f6367323dd2\",\n    \"description\": \"A test to check for the proper retrieval of headers from a specified source\",\n    \"schema\": \"https://schema.getpostman.com/json/collection/v2.0.0/collection.json\"\n  },\n  \"item\": [\n    {\n      \"name\": \"Gets a header with a semicolon\",\n      \"event\": [\n        {\n          \"listen\": \"test\",\n          \"script\": {\n            \"type\": \"text/javascript\",\n            \"exec\": [\n              \"pm.test(\\\"Test1: Content-Type is 'application/json;  charset=utf-8'\\\", ()=>{\",\n              \"    pm.expect(pm.response.headers.get('Content-Type')).equal('application/json; charset=utf-8')    \",\n              \"})\",\n              \"pm.test(\\\"Test2: Content-Type is 'application/json; charset=utf-8'\\\", ()=>{\",\n              \"    pm.expect(pm.response.headers.get('Content-type')).equal('application/json;\\\\ charset=utf-8')    \",\n              \"})\"\n            ]\n          }\n        }\n      ],\n      \"request\": {\n        \"url\": \"https://postman-echo.com/response-headers?Content-Type=application%2Fjson%3B%20%20charset%3Dutf-8\",\n        \"method\": \"GET\",\n        \"header\": [],\n        \"description\": \"Receives a semicolon header from dump.getpost\"\n      },\n      \"response\": []\n    }\n  ]\n}\n"
  },
  {
    "path": "test/integration/set-next-request.postman_collection.json",
    "content": "{\n  \"variables\": [],\n  \"info\": {\n    \"name\": \"NewmanSetNextRequest\",\n    \"_postman_id\": \"d6f7bb29-2258-4e1b-9576-b2315cf5b77e\",\n    \"description\": \"A set of tests to verify set and get operations on environment variables\",\n    \"schema\": \"https://schema.getpostman.com/json/collection/v2.0.0/collection.json\"\n  },\n  \"item\": [\n    {\n      \"name\": \"post\",\n      \"event\": [\n        {\n          \"listen\": \"test\",\n          \"script\": {\n            \"type\": \"text/javascript\",\n            \"exec\": \"postman.setEnvironmentVariable('method', 'get');\\npostman.setEnvironmentVariable('count', '1');\\nconsole.log('Environment is now: ', environment);\\npostman.setNextRequest('method');\"\n          }\n        }\n      ],\n      \"request\": {\n        \"url\": \"https://postman-echo.com/post\",\n        \"method\": \"POST\",\n        \"header\": [],\n        \"body\": {\n          \"mode\": \"formdata\",\n          \"formdata\": []\n        },\n        \"description\": \"\"\n      },\n      \"response\": []\n    },\n    {\n      \"name\": \"html\",\n      \"event\": [\n        {\n          \"listen\": \"test\",\n          \"script\": {\n            \"type\": \"text/javascript\",\n            \"exec\": \"var count = _.parseInt(postman.getEnvironmentVariable('count'));\\ncount++;\\npostman.setEnvironmentVariable('count', String(count));\\n\\nif (responseCode.code === 200) {\\n    postman.setEnvironmentVariable('method', 'headers');\\n    console.log('Setting next request to \\\"method\\\"');\\n    postman.setNextRequest('method');\\n}\"\n          }\n        }\n      ],\n      \"request\": {\n        \"url\": \"https://postman-echo.com/type/html\",\n        \"method\": \"GET\",\n        \"header\": [],\n        \"body\": {\n          \"mode\": \"formdata\",\n          \"formdata\": []\n        },\n        \"description\": \"\"\n      },\n      \"response\": []\n    },\n    {\n      \"name\": \"method\",\n      \"event\": [\n        {\n          \"listen\": \"test\",\n          \"script\": {\n            \"type\": \"text/javascript\",\n            \"exec\": \"var jsonData = JSON.parse(responseBody);\\nvar count = _.parseInt(postman.getEnvironmentVariable('count'));\\ncount++;\\npostman.setEnvironmentVariable('count', String(count));\\n\\nif (jsonData.url === 'https://postman-echo.com/get') {\\n    console.log('Setting next request to \\\"html\\\"');\\n    postman.setNextRequest('html');\\n}\\nelse if (!jsonData.url && jsonData.headers) {\\n    console.log('Ending shit here.'); tests['Success'] = _.parseInt(postman.getEnvironmentVariable('count')) === 4\\n    postman.setNextRequest(null);\\n}\\nelse {\\n    console.log('Not setting next request.. ', responseBody);\\n}\"\n          }\n        }\n      ],\n      \"request\": {\n        \"url\": \"https://postman-echo.com/{{method}}\",\n        \"method\": \"GET\",\n        \"header\": [],\n        \"body\": {\n          \"mode\": \"formdata\",\n          \"formdata\": []\n        },\n        \"description\": \"\"\n      },\n      \"response\": []\n    }\n  ]\n}\n"
  },
  {
    "path": "test/integration/slashed-variable-names/slashed-variable-names.postman_collection.json",
    "content": "{\n\t\"variables\": [],\n\t\"info\": {\n\t\t\"name\": \"slashed variable names\",\n\t\t\"_postman_id\": \"03ff9ad8-cdeb-c03b-ba1f-2076fe3faf50\",\n\t\t\"schema\": \"https://schema.getpostman.com/json/collection/v2.0.0/collection.json\"\n\t},\n\t\"item\": [\n\t\t{\n\t\t\t\"name\": \"Slashed variable names test\",\n\t\t\t\"event\": [\n\t\t\t\t{\n\t\t\t\t\t\"listen\": \"test\",\n\t\t\t\t\t\"script\": {\n\t\t\t\t\t\t\"type\": \"text/javascript\",\n\t\t\t\t\t\t\"exec\": \"var args = JSON.parse(responseBody).args;\\n\\ntests[\\\"Status code is 200\\\"] = responseCode.code === 200;\\ntests[\\\"Forward slash was handled correctly\\\"] = args[\\\"foo\\\"] === \\\"alpha\\\";\\ntests[\\\"Backslash was handled correctly\\\"] = args[\\\"bar\\\"] === \\\"beta\\\";\"\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t],\n\t\t\t\"request\": {\n\t\t\t\t\"url\": \"https://postman-echo.com/get?foo={{fo/o}}&bar={{b\\\\ar}}\",\n\t\t\t\t\"method\": \"GET\",\n\t\t\t\t\"header\": [],\n\t\t\t\t\"body\": {\n\t\t\t\t\t\"mode\": \"formdata\",\n\t\t\t\t\t\"formdata\": []\n\t\t\t\t},\n\t\t\t\t\"description\": \"A GET request to Postman echo with two query parameters, whose values should correctly resolve to environment variables that have slashes in their names.\"\n\t\t\t},\n\t\t\t\"response\": []\n\t\t}\n\t]\n}\n"
  },
  {
    "path": "test/integration/slashed-variable-names/slashed-variable-names.postman_environment.json",
    "content": "{\n  \"id\": \"043ddbc2-1fbb-242f-9c39-dc89e08d4a65\",\n  \"name\": \"Variable names with slashes\",\n  \"values\": [\n    {\n      \"key\": \"fo/o\",\n      \"type\": \"text\",\n      \"value\": \"alpha\",\n      \"enabled\": true\n    },\n    {\n      \"key\": \"b\\\\ar\",\n      \"type\": \"text\",\n      \"value\": \"beta\",\n      \"enabled\": true\n    }\n  ],\n  \"timestamp\": 1473255725612,\n  \"_postman_variable_scope\": \"environment\",\n  \"_postman_exported_at\": \"2016-09-07T13:43:25.578Z\",\n  \"_postman_exported_using\": \"Postman/4.7.0\"\n}"
  },
  {
    "path": "test/integration/steph/steph.postman_collection.json",
    "content": "{\n  \"variables\": [],\n  \"info\": {\n    \"name\": \"Basic form data test\",\n    \"_postman_id\": \"b6a53b01-d54e-8501-e7da-74affff4c7fc\",\n    \"description\": \"A set of tests to process piecewise form data\",\n    \"schema\": \"https://schema.getpostman.com/json/collection/v2.0.0/collection.json\"\n  },\n  \"item\": [\n    {\n      \"name\": \"https://postman-echo.com\",\n      \"event\": [\n        {\n          \"listen\": \"test\",\n          \"script\": {\n            \"type\": \"text/javascript\",\n            \"exec\": \"var data = JSON.parse(responseBody);\\ntests[\\\"First name is: \\\" + data.form.first] = true;\\ntests[\\\"last name is: \\\" + data.form.last] = true;\"\n          }\n        }\n      ],\n      \"request\": {\n        \"url\": \"https://postman-echo.com/post\",\n        \"method\": \"POST\",\n        \"header\": [],\n        \"body\": {\n          \"mode\": \"formdata\",\n          \"formdata\": [\n            {\n              \"key\": \"first\",\n              \"value\": \"{{first}}\",\n              \"type\": \"text\",\n              \"enabled\": true\n            },\n            {\n              \"key\": \"last\",\n              \"value\": \"{{last}}\",\n              \"type\": \"text\",\n              \"enabled\": true\n            }\n          ]\n        },\n        \"description\": \"\"\n      },\n      \"response\": []\n    }\n  ]\n}\n"
  },
  {
    "path": "test/integration/steph/steph.postman_data.json",
    "content": "[{\"first\": \"sampleFirstName1\", \"last\": \"sampleLastName1\"},{\"first\": \"sampleFirstName2\", \"last\": \"sampleLastName2\"}]\n"
  },
  {
    "path": "test/integration/super-sandbox-test.postman_collection.json",
    "content": "{\n\t\"variables\": [],\n\t\"info\": {\n\t\t\"name\": \"Testing general sandbox functionality\",\n\t\t\"_postman_id\": \"5c94a9d9-b0de-2a5c-9bd9-debadf2d89ad\",\n\t\t\"description\": \"\",\n\t\t\"schema\": \"https://schema.getpostman.com/json/collection/v2.0.0/collection.json\"\n\t},\n\t\"item\": [\n\t\t{\n\t\t\t\"name\": \"r1\",\n\t\t\t\"event\": [\n\t\t\t\t{\n\t\t\t\t\t\"listen\": \"test\",\n\t\t\t\t\t\"script\": {\n\t\t\t\t\t\t\"type\": \"text/javascript\",\n\t\t\t\t\t\t\"exec\": \"try {\\n    var jsonObject = xml2Json(responseBody);\\n    console.log(jsonObject);\\n    tests[\\\"xml2Json\\\"]=!!jsonObject;\\n}\\ncatch(e) {\\n    console.log(\\\"xml2Json not supported\\\");\\n    tests[\\\"xml2Json\\\"]=false;\\n}\\n\\n\\ntry {\\n    console.log(postman.getResponseHeader(\\\"Content-Length\\\"));\\n    tests[\\\"GetResponseHeader\\\"]=true;\\n} catch(e) {\\n    console.log(\\\"getResponseHeader not supported\\\");\\n    tests[\\\"GetResponseHeader\\\"]=false;\\n}\\n\\n\\ntry {\\n    console.log(postman.getResponseCookie(\\\"Content-Length\\\"));\\n    tests[\\\"GetResponseCookie\\\"]=true;\\n} catch(e) {\\n    console.log(\\\"getResponseCookie not supported\\\");\\n    tests[\\\"GetResponseCookie\\\"]=false;\\n}\\n\\ntry {\\n    console.log(\\\"RESCOOK: \\\" , responseCookies);\\n} catch(e) {\\n    console.log(\\\"responseCookies not supported\\\");\\n}\\n\\ntests[\\\"Correct global\\\"] = globals.g1==\\\"0\\\";\\n\\nconsole.log(\\\"Request: \\\" + JSON.stringify(request));\\nconsole.log(\\\"Environment: \\\" + JSON.stringify(environment));\\nconsole.log(\\\"Globals: \\\" + JSON.stringify(globals));\\nconsole.log(\\\"Response hedaers: \\\" + JSON.stringify(responseHeaders));\\nconsole.log(\\\"Response body: \\\" + JSON.stringify(responseBody));\\nconsole.log(\\\"Response time: \\\" + JSON.stringify(responseTime));\\nconsole.log(\\\"Response code: \\\" + JSON.stringify(responseCode));\\n\\n\\ntry {\\n    console.log(postman.clearEnvironmentVariables());\\n} catch(e) {\\n    console.log(\\\"clearEnvironmentVariables not supported\\\");\\n}\\n\\ntry {\\n    console.log(postman.clearGlobalVariables());\\n} catch(e) {\\n    console.log(\\\"clearGlobalVariables not supported\\\");\\n}\\n\\npostman.setGlobalVariable(\\\"g1\\\", \\\"0\\\");\\npostman.setEnvironmentVariable(\\\"e1\\\", \\\"0\\\");\\n\\ntry {\\n    _.each([1], function(v) {tests['Lodash working'] = true;});\\n}\\ncatch(e) {\\n    tests['Lodash working'] = false;\\n}\\n\\n\\nvar newString=\\\"diabetes\\\";\\ntests[\\\"SugarJS working\\\"]=newString.has(\\\"betes\\\");\\n\\ntests[\\\"tv4 present\\\"] = (typeof tv4.validate === \\\"function\\\");\\n\\ntests[\\\"CryptoJS md5\\\"] = (CryptoJS.MD5(\\\"jasonpurse\\\") == \\\"288d14f08b5ad40da43dbe06467729c9\\\");\"\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"listen\": \"prerequest\",\n\t\t\t\t\t\"script\": {\n\t\t\t\t\t\t\"type\": \"text/javascript\",\n\t\t\t\t\t\t\"exec\": \"postman.setGlobalVariable(\\\"g1\\\", \\\"0\\\");\"\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t],\n\t\t\t\"request\": {\n\t\t\t\t\"url\": \"https://postman-echo.com/type/xml\",\n\t\t\t\t\"method\": \"GET\",\n\t\t\t\t\"header\": [],\n\t\t\t\t\"body\": {\n\t\t\t\t\t\"mode\": \"formdata\",\n\t\t\t\t\t\"formdata\": []\n\t\t\t\t},\n\t\t\t\t\"description\": \"\"\n\t\t\t},\n\t\t\t\"response\": []\n\t\t},\n\t\t{\n\t\t\t\"name\": \"r2\",\n\t\t\t\"event\": [\n\t\t\t\t{\n\t\t\t\t\t\"listen\": \"test\",\n\t\t\t\t\t\"script\": {\n\t\t\t\t\t\t\"type\": \"text/javascript\",\n\t\t\t\t\t\t\"exec\": \"tests[\\\"Status code is 200\\\"] = responseCode.code === 200;\\n\\nconsole.log(\\\"Request for Post: \\\" + JSON.stringify(request));\\n\\nvar jsonData = JSON.parse(responseBody);\\ntests[\\\"Correct GUID: \\\" + jsonData.form.guid] = jsonData.form.guid.length === 36;\\ntests[\\\"Correct Random: \\\" + jsonData.form.randomInt] = parseInt(jsonData.form.randomInt)>=0;\\ntests[\\\"Correct Timestamp: \\\" + jsonData.form.timestamp] = parseInt(jsonData.form.timestamp)>1000\\n\\ntests[\\\"Correct global\\\"] = jsonData.form.global == \\\"0\\\";\\ntests[\\\"Correct global2\\\"] = jsonData.form.global == globals.g1;\\ntests[\\\"Correct envVar\\\"] = jsonData.form.envValue == \\\"0\\\";\\ntests[\\\"Correct envVar2\\\"] = jsonData.form.envValue == environment.e1;\"\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t],\n\t\t\t\"request\": {\n\t\t\t\t\"url\": \"https://postman-echo.com/post\",\n\t\t\t\t\"method\": \"POST\",\n\t\t\t\t\"header\": [],\n\t\t\t\t\"body\": {\n\t\t\t\t\t\"mode\": \"formdata\",\n\t\t\t\t\t\"formdata\": [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"key\": \"k1\",\n\t\t\t\t\t\t\t\"value\": \"v1\",\n\t\t\t\t\t\t\t\"type\": \"text\",\n\t\t\t\t\t\t\t\"enabled\": true\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"key\": \"k2\",\n\t\t\t\t\t\t\t\"value\": \"v2\",\n\t\t\t\t\t\t\t\"type\": \"text\",\n\t\t\t\t\t\t\t\"enabled\": true\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"key\": \"guid\",\n\t\t\t\t\t\t\t\"value\": \"{{$guid}}\",\n\t\t\t\t\t\t\t\"type\": \"text\",\n\t\t\t\t\t\t\t\"enabled\": true\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"key\": \"timestamp\",\n\t\t\t\t\t\t\t\"value\": \"{{$timestamp}}\",\n\t\t\t\t\t\t\t\"type\": \"text\",\n\t\t\t\t\t\t\t\"enabled\": true\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"key\": \"randomInt\",\n\t\t\t\t\t\t\t\"value\": \"{{$randomInt}}\",\n\t\t\t\t\t\t\t\"type\": \"text\",\n\t\t\t\t\t\t\t\"enabled\": true\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"key\": \"global\",\n\t\t\t\t\t\t\t\"value\": \"{{g1}}\",\n\t\t\t\t\t\t\t\"type\": \"text\",\n\t\t\t\t\t\t\t\"enabled\": true\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"key\": \"envValue\",\n\t\t\t\t\t\t\t\"value\": \"{{e1}}\",\n\t\t\t\t\t\t\t\"type\": \"text\",\n\t\t\t\t\t\t\t\"enabled\": true\n\t\t\t\t\t\t}\n\t\t\t\t\t]\n\t\t\t\t},\n\t\t\t\t\"description\": \"\"\n\t\t\t},\n\t\t\t\"response\": []\n\t\t},\n\t\t{\n\t\t\t\"name\": \"r3\",\n\t\t\t\"event\": [\n\t\t\t\t{\n\t\t\t\t\t\"listen\": \"test\",\n\t\t\t\t\t\"script\": {\n\t\t\t\t\t\t\"type\": \"text/javascript\",\n\t\t\t\t\t\t\"exec\": \"tests[\\\"Status code is 200\\\"] = responseCode.code === 200;\"\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t],\n\t\t\t\"request\": {\n\t\t\t\t\"url\": \"https://postman-echo.com/put\",\n\t\t\t\t\"method\": \"PUT\",\n\t\t\t\t\"header\": [],\n\t\t\t\t\"body\": {\n\t\t\t\t\t\"mode\": \"formdata\",\n\t\t\t\t\t\"formdata\": []\n\t\t\t\t},\n\t\t\t\t\"description\": \"\"\n\t\t\t},\n\t\t\t\"response\": []\n\t\t},\n\t\t{\n\t\t\t\"name\": \"r4\",\n\t\t\t\"event\": [\n\t\t\t\t{\n\t\t\t\t\t\"listen\": \"test\",\n\t\t\t\t\t\"script\": {\n\t\t\t\t\t\t\"type\": \"text/javascript\",\n\t\t\t\t\t\t\"exec\": \"tests[\\\"Status code is 200\\\"] = responseCode.code === 200;\"\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t],\n\t\t\t\"request\": {\n\t\t\t\t\"url\": \"https://postman-echo.com/patch\",\n\t\t\t\t\"method\": \"PATCH\",\n\t\t\t\t\"header\": [],\n\t\t\t\t\"body\": {\n\t\t\t\t\t\"mode\": \"formdata\",\n\t\t\t\t\t\"formdata\": []\n\t\t\t\t},\n\t\t\t\t\"description\": \"\"\n\t\t\t},\n\t\t\t\"response\": []\n\t\t},\n\t\t{\n\t\t\t\"name\": \"delete\",\n\t\t\t\"event\": [\n\t\t\t\t{\n\t\t\t\t\t\"listen\": \"test\",\n\t\t\t\t\t\"script\": {\n\t\t\t\t\t\t\"type\": \"text/javascript\",\n\t\t\t\t\t\t\"exec\": \"tests[\\\"Status code is 200\\\"] = responseCode.code === 200;\"\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t],\n\t\t\t\"request\": {\n\t\t\t\t\"url\": \"https://postman-echo.com/delete\",\n\t\t\t\t\"method\": \"DELETE\",\n\t\t\t\t\"header\": [],\n\t\t\t\t\"body\": {\n\t\t\t\t\t\"mode\": \"formdata\",\n\t\t\t\t\t\"formdata\": []\n\t\t\t\t},\n\t\t\t\t\"description\": \"\"\n\t\t\t},\n\t\t\t\"response\": []\n\t\t},\n\t\t{\n\t\t\t\"name\": \"head\",\n\t\t\t\"event\": [\n\t\t\t\t{\n\t\t\t\t\t\"listen\": \"test\",\n\t\t\t\t\t\"script\": {\n\t\t\t\t\t\t\"type\": \"text/javascript\",\n\t\t\t\t\t\t\"exec\": \"tests[\\\"Status code is 200\\\"] = responseCode.code === 200;\\ntests[\\\"Body is correct\\\"] = responseBody === \\\"\\\";\"\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t],\n\t\t\t\"request\": {\n\t\t\t\t\"url\": \"https://postman-echo.com/get\",\n\t\t\t\t\"method\": \"HEAD\",\n\t\t\t\t\"header\": [],\n\t\t\t\t\"body\": {\n\t\t\t\t\t\"mode\": \"formdata\",\n\t\t\t\t\t\"formdata\": []\n\t\t\t\t},\n\t\t\t\t\"description\": \"\"\n\t\t\t},\n\t\t\t\"response\": []\n\t\t},\n\t\t{\n\t\t\t\"name\": \"options\",\n\t\t\t\"event\": [\n\t\t\t\t{\n\t\t\t\t\t\"listen\": \"test\",\n\t\t\t\t\t\"script\": {\n\t\t\t\t\t\t\"type\": \"text/javascript\",\n\t\t\t\t\t\t\"exec\": \"tests[\\\"Status code is 200\\\"] = responseCode.code === 200;\\ntests[\\\"Body is correct\\\"] = !_.isEmpty(responseBody.split(\\\",\\\"));\"\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t],\n\t\t\t\"request\": {\n\t\t\t\t\"url\": \"https://postman-echo.com/get\",\n\t\t\t\t\"method\": \"OPTIONS\",\n\t\t\t\t\"header\": [],\n\t\t\t\t\"body\": {\n\t\t\t\t\t\"mode\": \"formdata\",\n\t\t\t\t\t\"formdata\": []\n\t\t\t\t},\n\t\t\t\t\"description\": \"\"\n\t\t\t},\n\t\t\t\"response\": []\n\t\t},\n\t\t{\n\t\t\t\"name\": \"r2 copy\",\n\t\t\t\"event\": [\n\t\t\t\t{\n\t\t\t\t\t\"listen\": \"test\",\n\t\t\t\t\t\"script\": {\n\t\t\t\t\t\t\"type\": \"text/javascript\",\n\t\t\t\t\t\t\"exec\": \"tests[\\\"Status code is 200\\\"] = responseCode.code === 200;\\n\\nconsole.log(\\\"Request for RAW Post: \\\" + JSON.stringify(request));\\n\"\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t],\n\t\t\t\"request\": {\n\t\t\t\t\"url\": \"https://postman-echo.com/post\",\n\t\t\t\t\"method\": \"POST\",\n\t\t\t\t\"header\": [],\n\t\t\t\t\"body\": {\n\t\t\t\t\t\"mode\": \"raw\",\n\t\t\t\t\t\"raw\": \"RAWDATA\"\n\t\t\t\t},\n\t\t\t\t\"description\": \"\"\n\t\t\t},\n\t\t\t\"response\": []\n\t\t},\n\t\t{\n\t\t\t\"name\": \"BasicAuth\",\n\t\t\t\"event\": [\n\t\t\t\t{\n\t\t\t\t\t\"listen\": \"test\",\n\t\t\t\t\t\"script\": {\n\t\t\t\t\t\t\"type\": \"text/javascript\",\n\t\t\t\t\t\t\"exec\": \"console.log(request.headers);\\nvar jsonData = JSON.parse(responseBody);\\ntests[\\\"Correct auth header\\\"] = jsonData.headers.authorization === \\\"Basic cG9zdG1hbjpwYXNzd29yZA==\\\";\"\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t],\n\t\t\t\"request\": {\n\t\t\t\t\"auth\": {\n\t\t\t\t\t\"type\": \"basic\",\n\t\t\t\t\t\"basic\": {\n\t\t\t\t\t\t\"username\": \"postman\",\n\t\t\t\t\t\t\"password\": \"password\",\n\t\t\t\t\t\t\"saveHelperData\": true,\n\t\t\t\t\t\t\"showPassword\": false\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\t\"url\": \"https://postman-echo.com/post\",\n\t\t\t\t\"method\": \"POST\",\n\t\t\t\t\"header\": [],\n\t\t\t\t\"body\": {\n\t\t\t\t\t\"mode\": \"formdata\",\n\t\t\t\t\t\"formdata\": []\n\t\t\t\t},\n\t\t\t\t\"description\": \"\"\n\t\t\t},\n\t\t\t\"response\": []\n\t\t},\n\t\t{\n\t\t\t\"name\": \"DigestAuth\",\n\t\t\t\"event\": [\n\t\t\t\t{\n\t\t\t\t\t\"listen\": \"test\",\n\t\t\t\t\t\"script\": {\n\t\t\t\t\t\t\"type\": \"text/javascript\",\n\t\t\t\t\t\t\"exec\": \"console.log(request.headers);\\nvar jsonData = JSON.parse(responseBody);\\ntests[\\\"Authenticated\\\"] = jsonData.authenticated === true;\"\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t],\n\t\t\t\"request\": {\n\t\t\t\t\"auth\": {\n\t\t\t\t\t\"type\": \"digest\",\n\t\t\t\t\t\"digest\": {\n\t\t\t\t\t\t\"algorithm\": \"\",\n\t\t\t\t\t\t\"username\": \"postman\",\n\t\t\t\t\t\t\"realm\": \"Users\",\n\t\t\t\t\t\t\"password\": \"password\",\n\t\t\t\t\t\t\"nonce\": \"ni1LiL0O37PRRhofWdCLmwFsnEtH1lew\",\n\t\t\t\t\t\t\"nonceCount\": \"\",\n\t\t\t\t\t\t\"clientNonce\": \"\",\n\t\t\t\t\t\t\"opaque\": \"\",\n\t\t\t\t\t\t\"qop\": \"\"\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\t\"url\": \"https://postman-echo.com/digest-auth\",\n\t\t\t\t\"method\": \"GET\",\n\t\t\t\t\"header\": [],\n\t\t\t\t\"body\": {\n\t\t\t\t\t\"mode\": \"formdata\",\n\t\t\t\t\t\"formdata\": []\n\t\t\t\t},\n\t\t\t\t\"description\": \"\"\n\t\t\t},\n\t\t\t\"response\": []\n\t\t},\n\t\t{\n\t\t\t\"name\": \"Recursive Res\",\n\t\t\t\"event\": [\n\t\t\t\t{\n\t\t\t\t\t\"listen\": \"test\",\n\t\t\t\t\t\"script\": {\n\t\t\t\t\t\t\"type\": \"text/javascript\",\n\t\t\t\t\t\t\"exec\": \"var jsonData = JSON.parse(responseBody);\\n//tests[\\\"Recur. res. working\\\"] = jsonData.args.a == \\\"sampleName\\\";\"\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"listen\": \"prerequest\",\n\t\t\t\t\t\"script\": {\n\t\t\t\t\t\t\"type\": \"text/javascript\",\n\t\t\t\t\t\t\"exec\": \"postman.setGlobalVariable(\\\"name1\\\", \\\"sampleName\\\");\\npostman.setGlobalVariable(\\\"i\\\", \\\"1\\\");\"\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t],\n\t\t\t\"request\": {\n\t\t\t\t\"url\": \"https://postman-echo.com/get?a={{name{{i}}}}\",\n\t\t\t\t\"method\": \"GET\",\n\t\t\t\t\"header\": [],\n\t\t\t\t\"body\": {\n\t\t\t\t\t\"mode\": \"formdata\",\n\t\t\t\t\t\"formdata\": []\n\t\t\t\t},\n\t\t\t\t\"description\": \"\"\n\t\t\t},\n\t\t\t\"response\": []\n\t\t}\n\t]\n}\n"
  },
  {
    "path": "test/integration/tc4/tc4.postman_collection.json",
    "content": "{\n\t\"variables\": [],\n\t\"info\": {\n\t\t\"name\": \"Form data file upload\",\n\t\t\"_postman_id\": \"d1c476fc-b34c-149e-ac26-ffbcb13edc0e\",\n\t\t\"description\": \"A collection to test file upload operations\",\n\t\t\"schema\": \"https://schema.getpostman.com/json/collection/v2.0.0/collection.json\"\n\t},\n\t\"item\": [\n\t\t{\n\t\t\t\"name\": \"POST file test\",\n\t\t\t\"event\": [\n\t\t\t\t{\n\t\t\t\t\t\"listen\": \"test\",\n\t\t\t\t\t\"script\": {\n\t\t\t\t\t\t\"type\": \"text/javascript\",\n\t\t\t\t\t\t\"exec\": \"var file = JSON.parse(responseBody).files[\\\"upload-file.json\\\"];\\n\\ntests[\\\"File contents are valid\\\"] = _.startsWith(file, \\\"data:application/octet-stream;base64,\\\");\"\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t],\n\t\t\t\"request\": {\n\t\t\t\t\"url\": \"https://postman-echo.com/post\",\n\t\t\t\t\"method\": \"POST\",\n\t\t\t\t\"header\": [],\n\t\t\t\t\"body\": {\n\t\t\t\t\t\"mode\": \"formdata\",\n\t\t\t\t\t\"formdata\": [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"key\": \"file\",\n\t\t\t\t\t\t\t\"src\": \"test/integration/tc4/upload-file.json\",\n\t\t\t\t\t\t\t\"type\": \"file\"\n\t\t\t\t\t\t}\n\t\t\t\t\t]\n\t\t\t\t},\n\t\t\t\t\"description\": \"Passes when posted to postman-echo.com/post\"\n\t\t\t},\n\t\t\t\"response\": []\n\t\t}\n\t]\n}\n"
  },
  {
    "path": "test/integration/tc4/upload-file.json",
    "content": "{\n\t\"key1\":\"value1\",\n\t\"key2\": 2\n}"
  },
  {
    "path": "test/integration/timeout/timeout.postman_collection.json",
    "content": "{\n  \"item\": [{\n    \"event\": [{\n      \"listen\": \"test\",\n      \"script\": {\n        \"type\": \"text/javascript\",\n        \"exec\": [\n          \"var now = Date.now(),\",\n          \"    later = now + 300;\",\n          \"while(Date.now() < later);\"\n        ]\n      }\n    }],\n    \"request\": {\n      \"url\": \"https://postman-echo.com/delay/2\",\n      \"method\": \"GET\"\n    }\n  }]\n}\n"
  },
  {
    "path": "test/integration/timeout/timeout.postman_config.json",
    "content": "{\n  \"run\": {\n    \"timeout\": 10000,\n    \"timeoutRequest\": 3000,\n    \"timeoutScript\": 500\n  }\n}\n"
  },
  {
    "path": "test/integration/v2-regression-tests/v2-regression-tests.postman_collection.json",
    "content": "{\n\t\"variables\": [],\n\t\"info\": {\n\t\t\"name\": \"regression_tests\",\n\t\t\"_postman_id\": \"925beee2-97e5-3122-5067-6bb31e07aad2\",\n\t\t\"description\": \"A collection to help check backward compatibility and keep previously resolved issue from re-surfacing\",\n\t\t\"schema\": \"https://schema.getpostman.com/json/collection/v2.0.0/collection.json\"\n\t},\n\t\"item\": [\n\t\t{\n\t\t\t\"name\": \"Variables as query parameters\",\n\t\t\t\"event\": [\n\t\t\t\t{\n\t\t\t\t\t\"listen\": \"test\",\n\t\t\t\t\t\"script\": {\n\t\t\t\t\t\t\"type\": \"text/javascript\",\n\t\t\t\t\t\t\"exec\": \"var cookies = JSON.parse(responseBody).cookies;\\n\\ntests[\\\"Status code is 200\\\"] = responseCode.code === 200;\\ntests[\\\"foo1 cookie is present in the response body\\\"] = cookies[\\\"foo1\\\"] === postman.getEnvironmentVariable(\\\"envKey\\\");\"\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t],\n\t\t\t\"request\": {\n\t\t\t\t\"url\": \"https://postman-echo.com/cookies/set?foo1={{envKey}}&foo2=bar\",\n\t\t\t\t\"method\": \"GET\",\n\t\t\t\t\"header\": [],\n\t\t\t\t\"body\": {\n\t\t\t\t\t\"mode\": \"formdata\",\n\t\t\t\t\t\"formdata\": []\n\t\t\t\t},\n\t\t\t\t\"description\": \"This request checks for the correct handling of variables as query parameters\"\n\t\t\t},\n\t\t\t\"response\": []\n\t\t},\n\t\t{\n\t\t\t\"name\": \"Insecurity checks\",\n\t\t\t\"event\": [\n\t\t\t\t{\n\t\t\t\t\t\"listen\": \"test\",\n\t\t\t\t\t\"script\": {\n\t\t\t\t\t\t\"type\": \"text/javascript\",\n\t\t\t\t\t\t\"exec\": \"tests[\\\"Status code is 200\\\"] = responseCode.code === 200;\"\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t],\n\t\t\t\"request\": {\n\t\t\t\t\"url\": \"https://expired.badssl.com\",\n\t\t\t\t\"method\": \"GET\",\n\t\t\t\t\"header\": [],\n\t\t\t\t\"body\": {\n\t\t\t\t\t\"mode\": \"formdata\",\n\t\t\t\t\t\"formdata\": []\n\t\t\t\t},\n\t\t\t\t\"description\": \"This request validates running with the insecure option set to true\"\n\t\t\t},\n\t\t\t\"response\": []\n\t\t},\n\t\t{\n\t\t\t\"name\": \"Disabled header\",\n\t\t\t\"event\": [\n\t\t\t\t{\n\t\t\t\t\t\"listen\": \"test\",\n\t\t\t\t\t\"script\": {\n\t\t\t\t\t\t\"type\": \"text/javascript\",\n\t\t\t\t\t\t\"exec\": \"var headers = JSON.parse(responseBody).headers;\\ntests[\\\"Status code is 200\\\"] = responseCode.code === 200;\\n\\n\\ntests[\\\"Disabled header is absent\\\"] = !headers[\\\"disabled-header\\\"];\"\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t],\n\t\t\t\"request\": {\n\t\t\t\t\"url\": \"https://postman-echo.com/headers\",\n\t\t\t\t\"method\": \"GET\",\n\t\t\t\t\"header\": [\n\t\t\t\t\t{\n\t\t\t\t\t\t\"key\": \"//disabled-header\",\n\t\t\t\t\t\t\"value\": \"randomHeaderString\",\n\t\t\t\t\t\t\"description\": \"\",\n\t\t\t\t\t\t\"disabled\": true\n\t\t\t\t\t}\n\t\t\t\t],\n\t\t\t\t\"body\": {\n\t\t\t\t\t\"mode\": \"formdata\",\n\t\t\t\t\t\"formdata\": []\n\t\t\t\t},\n\t\t\t\t\"description\": \"Checks for the absence of disabled headers in the response object\"\n\t\t\t},\n\t\t\t\"response\": []\n\t\t}\n\t]\n}\n"
  },
  {
    "path": "test/integration/v2-regression-tests/v2-regression-tests.postman_config.json",
    "content": "{\n  \"run\": {\n    \"insecure\": true\n  }\n}\n"
  },
  {
    "path": "test/integration/v2-regression-tests/v2-regression-tests.postman_environment.json",
    "content": "{\n\t\"id\": \"03975311-f395-4eb9-91d8-0a15906bdccc\",\n\t\"name\": \"regression-tests\",\n\t\"values\": [\n\t\t{\n\t\t\t\"key\": \"envKey\",\n\t\t\t\"value\": \"sampleKey\",\n\t\t\t\"type\": \"text\",\n\t\t\t\"name\": \"envKey\",\n\t\t\t\"enabled\": true\n\t\t},\n\t\t{\n\t\t\t\"key\": \"envFileUrl\",\n\t\t\t\"value\": \"postman-echo.com\",\n\t\t\t\"type\": \"text\",\n\t\t\t\"name\": \"envFileUrl\",\n\t\t\t\"enabled\": true\n\t\t},\n\t\t{\n\t\t\t\"key\": \"dataVar2\",\n\t\t\t\"type\": \"text\",\n\t\t\t\"value\": \"1\",\n\t\t\t\"enabled\": true\n\t\t}\n\t],\n\t\"timestamp\": 1470909317305,\n\t\"synced\": false,\n\t\"syncedFilename\": \"\",\n\t\"team\": null,\n\t\"isDeleted\": false\n}\n"
  },
  {
    "path": "test/integration/var-replacement.postman_collection.json",
    "content": "{\n  \"variables\": [],\n  \"info\": {\n    \"name\": \"testCollection\",\n    \"_postman_id\": \"29199569-c73e-da26-69f3-c6e644b00e25\",\n    \"description\": \"A set of tests to check for the proper substitution of blank and non-blank variables\",\n    \"schema\": \"https://schema.getpostman.com/json/collection/v2.0.0/collection.json\"\n  },\n  \"item\": [\n    {\n      \"name\": \"Valid and invalid variables\",\n      \"event\": [\n        {\n          \"listen\": \"test\",\n          \"script\": {\n            \"type\": \"text/javascript\",\n            \"exec\": \"var data = JSON.parse(responseBody);\\ntests[\\\"Variable substitution\\\"] = (data.args.var===\\\"replaced\\\");\\ntests[\\\"No blank variable substitution\\\"] = (data.args.novar===\\\"{{novar}}\\\");\"\n          }\n        },\n        {\n          \"listen\": \"prerequest\",\n          \"script\": {\n            \"type\": \"text/javascript\",\n            \"exec\": \"postman.setEnvironmentVariable(\\\"var\\\", \\\"replaced\\\");\"\n          }\n        }\n      ],\n      \"request\": {\n        \"url\": \"https://postman-echo.com/get?novar={{novar}}&var={{var}}\",\n        \"method\": \"GET\",\n        \"header\": [],\n        \"body\": {\n          \"mode\": \"formdata\",\n          \"formdata\": []\n        },\n        \"description\": \"\"\n      },\n      \"response\": []\n    }\n  ]\n}\n"
  },
  {
    "path": "test/integration/whatwg-url.postman_collection.json",
    "content": "{\n  \"info\": {\n    \"name\": \"whatwg-url\",\n    \"schema\": \"https://schema.getpostman.com/json/collection/v2.1.0/collection.json\"\n  },\n  \"item\": [{\n      \"name\": \"Parsing\",\n      \"item\": [{\n          \"name\": \"nested variables\",\n          \"event\": [{\n              \"listen\": \"prerequest\",\n              \"script\": {\n                \"id\": \"c53eca57-615d-457f-8f45-58b8151a4b91\",\n                \"exec\": [\n                  \"pm.variables.set(\\\"one\\\", \\\"1\\\");\",\n                  \"pm.variables.set(\\\"host.1\\\", \\\"postman-echo.com\\\");\"\n                ],\n                \"type\": \"text/javascript\"\n              }\n            },\n            {\n              \"listen\": \"test\",\n              \"script\": {\n                \"id\": \"69e16939-24c9-40ba-a3e2-9ff6f98668ff\",\n                \"exec\": [\n                  \"pm.test(\\\"Request URL\\\", function () {\",\n                  \"    const {url} =  pm.response.json();\",\n                  \"\",\n                  \"    pm.expect(url).to.equal('https://postman-echo.com/get');\",\n                  \"});\"\n                ],\n                \"type\": \"text/javascript\"\n              }\n            }\n          ],\n          \"request\": {\n            \"method\": \"GET\",\n            \"url\": {\n              \"raw\": \"https://{{host.{{one}}}}/get\",\n              \"protocol\": \"https\",\n              \"host\": [\n                \"{{host\",\n                \"{{one}}}}\"\n              ],\n              \"path\": [\n                \"get\"\n              ]\n            }\n          }\n        },\n        {\n          \"name\": \"reserved chars in variables\",\n          \"event\": [{\n              \"listen\": \"prerequest\",\n              \"script\": {\n                \"id\": \"c53eca57-615d-457f-8f45-58b8151a4b91\",\n                \"exec\": [\n                  \"pm.variables.set(\\\"p://\\\", \\\"https\\\");\",\n                  \"pm.variables.set(\\\"@\\\", \\\"root\\\");\",\n                  \"pm.variables.set(\\\"###\\\", \\\"password\\\");\",\n                  \"pm.variables.set(\\\"host.name\\\", \\\"postman-echo.com\\\");\",\n                  \"pm.variables.set(\\\":p\\\", \\\"443\\\");\",\n                  \"pm.variables.set(\\\"f/o/o\\\", \\\"get\\\");\",\n                  \"pm.variables.set(\\\"?\\\", \\\"foo\\\");\",\n                  \"pm.variables.set(\\\"&\\\", \\\"bar\\\");\",\n                  \"\"\n                ],\n                \"type\": \"text/javascript\"\n              }\n            },\n            {\n              \"listen\": \"test\",\n              \"script\": {\n                \"id\": \"69e16939-24c9-40ba-a3e2-9ff6f98668ff\",\n                \"exec\": [\n                  \"pm.test(\\\"Request URL\\\", function () {\",\n                  \"    const {url} =  pm.response.json();\",\n                  \"\",\n                  \"    pm.expect(url).to.equal('https://postman-echo.com/get?foo=bar');\",\n                  \"});\"\n                ],\n                \"type\": \"text/javascript\"\n              }\n            }\n          ],\n          \"request\": {\n            \"method\": \"GET\",\n            \"url\": {\n              \"raw\": \"{{p://}}://{{@}}:{{###}}@{{host.name}}:{{:p}}/{{f/o/o}}?{{?}}={{&}}\",\n              \"protocol\": \"{{p://}}\",\n              \"auth\": {\n                \"user\": \"{{@}}\",\n                \"password\": \"{{###}}\"\n              },\n              \"host\": [\n                \"{{host.name}}\"\n              ],\n              \"port\": \"{{:p}}\",\n              \"path\": [\n                \"{{f/o/o}}\"\n              ],\n              \"query\": [{\n                \"key\": \"{{?}}\",\n                \"value\": \"{{&}}\"\n              }]\n            }\n          }\n        },\n        {\n          \"name\": \"newlines\",\n          \"event\": [{\n            \"listen\": \"test\",\n            \"script\": {\n              \"id\": \"69e16939-24c9-40ba-a3e2-9ff6f98668ff\",\n              \"exec\": [\n                \"pm.test(\\\"Request URL\\\", function () {\",\n                \"    const {url} =  pm.response.json();\",\n                \"\",\n                \"    pm.expect(url).to.equal('https://postman-echo.com/get?foo=%0Abar%0A');\",\n                \"});\"\n              ],\n              \"type\": \"text/javascript\"\n            }\n          }],\n          \"request\": {\n            \"method\": \"GET\",\n            \"url\": {\n              \"raw\": \"https://postman-echo.com/get?foo=\\nbar\\n\",\n              \"protocol\": \"https\",\n              \"host\": [\n                \"postman-echo\",\n                \"com\"\n              ],\n              \"path\": [\n                \"get\"\n              ],\n              \"query\": [{\n                \"key\": \"foo\",\n                \"value\": \"\\nbar\\n\"\n              }]\n            }\n          }\n        },\n        {\n          \"name\": \"\\\\\\\\ in path\",\n          \"event\": [{\n            \"listen\": \"test\",\n            \"script\": {\n              \"id\": \"69e16939-24c9-40ba-a3e2-9ff6f98668ff\",\n              \"exec\": [\n                \"pm.test(\\\"Request URL\\\", function () {\",\n                \"    const {url} =  pm.response.json();\",\n                \"\",\n                \"    pm.expect(url).to.equal('https://httpbin.org/get');\",\n                \"});\"\n              ],\n              \"type\": \"text/javascript\"\n            }\n          }],\n          \"request\": {\n            \"method\": \"GET\",\n            \"url\": {\n              \"raw\": \"  \",\n              \"protocol\": \"https\",\n              \"host\": [\n                \"httpbin\",\n                \"org\"\n              ],\n              \"path\": [\n                \"\",\n                \"get\"\n              ]\n            }\n          }\n        },\n        {\n          \"name\": \"// in protocol\",\n          \"event\": [{\n            \"listen\": \"test\",\n            \"script\": {\n              \"id\": \"69e16939-24c9-40ba-a3e2-9ff6f98668ff\",\n              \"exec\": [\n                \"pm.test(\\\"Request URL\\\", function () {\",\n                \"    const {url} =  pm.response.json();\",\n                \"\",\n                \"    pm.expect(url).to.equal('https://postman-echo.com/get');\",\n                \"});\"\n              ],\n              \"type\": \"text/javascript\"\n            }\n          }],\n          \"request\": {\n            \"method\": \"GET\",\n            \"url\": {\n              \"raw\": \"https:\\\\\\\\postman-echo.com/get\",\n              \"protocol\": \"https\",\n              \"host\": [\n                \"postman-echo\",\n                \"com\"\n              ],\n              \"path\": [\n                \"get\"\n              ]\n            }\n          }\n        },\n        {\n          \"name\": \"multiple ???\",\n          \"event\": [{\n            \"listen\": \"test\",\n            \"script\": {\n              \"id\": \"69e16939-24c9-40ba-a3e2-9ff6f98668ff\",\n              \"exec\": [\n                \"pm.test(\\\"Request URL\\\", function () {\",\n                \"    const {url} =  pm.response.json();\",\n                \"\",\n                \"    pm.expect(url).to.equal('https://postman-echo.com/get???&hl=en&src=api&x=2&y=2&z=3&s=');\",\n                \"});\"\n              ],\n              \"type\": \"text/javascript\"\n            }\n          }],\n          \"request\": {\n            \"method\": \"GET\",\n            \"url\": {\n              \"raw\": \"https://postman-echo.com/get???&hl=en&src=api&x=2&y=2&z=3&s=\",\n              \"protocol\": \"https\",\n              \"host\": [\n                \"postman-echo\",\n                \"com\"\n              ],\n              \"path\": [\n                \"get\"\n              ],\n              \"query\": [{\n                  \"key\": \"??\",\n                  \"value\": null\n                },\n                {\n                  \"key\": \"hl\",\n                  \"value\": \"en\"\n                },\n                {\n                  \"key\": \"src\",\n                  \"value\": \"api\"\n                },\n                {\n                  \"key\": \"x\",\n                  \"value\": \"2\"\n                },\n                {\n                  \"key\": \"y\",\n                  \"value\": \"2\"\n                },\n                {\n                  \"key\": \"z\",\n                  \"value\": \"3\"\n                },\n                {\n                  \"key\": \"s\",\n                  \"value\": \"\"\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"name\": \"multiple &&&\",\n          \"event\": [{\n            \"listen\": \"test\",\n            \"script\": {\n              \"id\": \"69e16939-24c9-40ba-a3e2-9ff6f98668ff\",\n              \"exec\": [\n                \"pm.test(\\\"Request URL\\\", function () {\",\n                \"    const {url} =  pm.response.json();\",\n                \"\",\n                \"    pm.expect(url).to.equal('https://postman-echo.com/get?foo=bar&&&bar=baz');\",\n                \"});\"\n              ],\n              \"type\": \"text/javascript\"\n            }\n          }],\n          \"request\": {\n            \"method\": \"GET\",\n            \"url\": {\n              \"raw\": \"https://postman-echo.com/get?foo=bar&&&bar=baz\",\n              \"protocol\": \"https\",\n              \"host\": [\n                \"postman-echo\",\n                \"com\"\n              ],\n              \"path\": [\n                \"get\"\n              ],\n              \"query\": [{\n                  \"key\": \"foo\",\n                  \"value\": \"bar\"\n                },\n                {\n                  \"key\": null,\n                  \"value\": null\n                },\n                {\n                  \"key\": null,\n                  \"value\": null\n                },\n                {\n                  \"key\": \"bar\",\n                  \"value\": \"baz\"\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"name\": \"multiple : and @ in auth\",\n          \"event\": [{\n            \"listen\": \"test\",\n            \"script\": {\n              \"id\": \"69e16939-24c9-40ba-a3e2-9ff6f98668ff\",\n              \"exec\": [\n                \"pm.test(\\\"Request URL\\\", function () {\",\n                \"    const {url, headers: {authorization} } =  pm.response.json();\",\n                \"\",\n                \"    pm.expect(authorization).to.equal('Basic ' + Buffer.from('us@r:p@ssword').toString('base64'));\",\n                \"    pm.expect(url).to.equal('https://postman-echo.com/get');\",\n                \"});\"\n              ],\n              \"type\": \"text/javascript\"\n            }\n          }],\n          \"request\": {\n            \"method\": \"GET\",\n            \"url\": {\n              \"raw\": \"https://us@r:p@ssword@postman-echo.com/get\",\n              \"protocol\": \"https\",\n              \"auth\": {\n                \"user\": \"us@r\",\n                \"password\": \"p@ssword\"\n              },\n              \"host\": [\n                \"postman-echo\",\n                \"com\"\n              ],\n              \"path\": [\n                \"get\"\n              ]\n            }\n          }\n        },\n        {\n          \"name\": \"retain ? in empty query param\",\n          \"event\": [{\n            \"listen\": \"test\",\n            \"script\": {\n              \"id\": \"69e16939-24c9-40ba-a3e2-9ff6f98668ff\",\n              \"exec\": [\n                \"pm.test(\\\"Request URL\\\", function () {\",\n                \"    const {url} =  pm.response.json();\",\n                \"\",\n                \"    pm.expect(url).to.equal('https://postman-echo.com/get?');\",\n                \"});\"\n              ],\n              \"type\": \"text/javascript\"\n            }\n          }],\n          \"request\": {\n            \"method\": \"GET\",\n            \"url\": {\n              \"raw\": \"https://postman-echo.com/get?\",\n              \"protocol\": \"https\",\n              \"host\": [\n                \"postman-echo\",\n                \"com\"\n              ],\n              \"path\": [\n                \"get\"\n              ],\n              \"query\": [{\n                \"key\": null,\n                \"value\": null\n              }]\n            }\n          }\n        },\n        {\n          \"name\": \"retain & in empty query params\",\n          \"event\": [{\n            \"listen\": \"test\",\n            \"script\": {\n              \"id\": \"69e16939-24c9-40ba-a3e2-9ff6f98668ff\",\n              \"exec\": [\n                \"pm.test(\\\"Request URL\\\", function () {\",\n                \"    const {url} =  pm.response.json();\",\n                \"\",\n                \"    pm.expect(url).to.equal('https://postman-echo.com/get?&');\",\n                \"});\"\n              ],\n              \"type\": \"text/javascript\"\n            }\n          }],\n          \"request\": {\n            \"method\": \"GET\",\n            \"url\": {\n              \"raw\": \"https://postman-echo.com/get?&\",\n              \"protocol\": \"https\",\n              \"host\": [\n                \"postman-echo\",\n                \"com\"\n              ],\n              \"path\": [\n                \"get\"\n              ],\n              \"query\": [{\n                  \"key\": null,\n                  \"value\": null\n                },\n                {\n                  \"key\": null,\n                  \"value\": null\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"name\": \"retain && in empty query params\",\n          \"event\": [{\n            \"listen\": \"test\",\n            \"script\": {\n              \"id\": \"69e16939-24c9-40ba-a3e2-9ff6f98668ff\",\n              \"exec\": [\n                \"pm.test(\\\"Request URL\\\", function () {\",\n                \"    const {url} =  pm.response.json();\",\n                \"\",\n                \"    pm.expect(url).to.equal('https://postman-echo.com/get?&&');\",\n                \"});\"\n              ],\n              \"type\": \"text/javascript\"\n            }\n          }],\n          \"request\": {\n            \"method\": \"GET\",\n            \"url\": {\n              \"raw\": \"https://postman-echo.com/get?&&\",\n              \"protocol\": \"https\",\n              \"host\": [\n                \"postman-echo\",\n                \"com\"\n              ],\n              \"path\": [\n                \"get\"\n              ],\n              \"query\": [{\n                  \"key\": null,\n                  \"value\": null\n                },\n                {\n                  \"key\": null,\n                  \"value\": null\n                },\n                {\n                  \"key\": null,\n                  \"value\": null\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"name\": \"retain &foo in query param\",\n          \"event\": [{\n            \"listen\": \"test\",\n            \"script\": {\n              \"id\": \"69e16939-24c9-40ba-a3e2-9ff6f98668ff\",\n              \"exec\": [\n                \"pm.test(\\\"Request URL\\\", function () {\",\n                \"    const {url} =  pm.response.json();\",\n                \"\",\n                \"    pm.expect(url).to.equal('https://postman-echo.com/get?&foo');\",\n                \"});\"\n              ],\n              \"type\": \"text/javascript\"\n            }\n          }],\n          \"request\": {\n            \"method\": \"GET\",\n            \"url\": {\n              \"raw\": \"https://postman-echo.com/get?&foo\",\n              \"protocol\": \"https\",\n              \"host\": [\n                \"postman-echo\",\n                \"com\"\n              ],\n              \"path\": [\n                \"get\"\n              ],\n              \"query\": [{\n                  \"key\": null,\n                  \"value\": null\n                },\n                {\n                  \"key\": \"foo\",\n                  \"value\": null\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"name\": \"retain foo& in query param\",\n          \"event\": [{\n            \"listen\": \"test\",\n            \"script\": {\n              \"id\": \"69e16939-24c9-40ba-a3e2-9ff6f98668ff\",\n              \"exec\": [\n                \"pm.test(\\\"Request URL\\\", function () {\",\n                \"    const {url} =  pm.response.json();\",\n                \"\",\n                \"    pm.expect(url).to.equal('https://postman-echo.com/get?foo&');\",\n                \"});\"\n              ],\n              \"type\": \"text/javascript\"\n            }\n          }],\n          \"request\": {\n            \"method\": \"GET\",\n            \"url\": {\n              \"raw\": \"https://postman-echo.com/get?foo&\",\n              \"protocol\": \"https\",\n              \"host\": [\n                \"postman-echo\",\n                \"com\"\n              ],\n              \"path\": [\n                \"get\"\n              ],\n              \"query\": [{\n                  \"key\": \"foo\",\n                  \"value\": null\n                },\n                {\n                  \"key\": \"\",\n                  \"value\": null\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"name\": \"params with & and #\",\n          \"event\": [{\n              \"listen\": \"prerequest\",\n              \"script\": {\n                \"id\": \"c53eca57-615d-457f-8f45-58b8151a4b91\",\n                \"exec\": [\n                  \"pm.variables.set(\\\"foo&bar\\\", \\\"1\\\");\",\n                  \"\",\n                  \"pm.variables.set(\\\"#foo#\\\", \\\"2\\\");\"\n                ],\n                \"type\": \"text/javascript\"\n              }\n            },\n            {\n              \"listen\": \"test\",\n              \"script\": {\n                \"id\": \"69e16939-24c9-40ba-a3e2-9ff6f98668ff\",\n                \"exec\": [\n                  \"pm.test(\\\"Request URL\\\", function () {\",\n                  \"    const {url} =  pm.response.json();\",\n                  \"\",\n                  \"    pm.expect(url).to.equal('https://postman-echo.com/get?q=%231%23&x%26y=2&b%23a%26r');\",\n                  \"});\"\n                ],\n                \"type\": \"text/javascript\"\n              }\n            }\n          ],\n          \"request\": {\n            \"method\": \"GET\",\n            \"url\": {\n              \"raw\": \"https://postman-echo.com/get?q=%23{{foo&bar}}%23&x%26y={{#foo#}}&b%23a%26r=\",\n              \"protocol\": \"https\",\n              \"host\": [\n                \"postman-echo\",\n                \"com\"\n              ],\n              \"path\": [\n                \"get\"\n              ],\n              \"query\": [{\n                  \"key\": \"q\",\n                  \"value\": \"%23{{foo&bar}}%23\"\n                },\n                {\n                  \"key\": \"x%26y\",\n                  \"value\": \"{{#foo#}}\"\n                },\n                {\n                  \"key\": \"b#a&r\",\n                  \"value\": null\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"name\": \"disabled query param\",\n          \"event\": [{\n            \"listen\": \"test\",\n            \"script\": {\n              \"id\": \"69e16939-24c9-40ba-a3e2-9ff6f98668ff\",\n              \"exec\": [\n                \"pm.test(\\\"Request URL\\\", function () {\",\n                \"    const {url} =  pm.response.json();\",\n                \"\",\n                \"    pm.expect(url).to.equal('https://postman-echo.com/get');\",\n                \"});\"\n              ],\n              \"type\": \"text/javascript\"\n            }\n          }],\n          \"request\": {\n            \"method\": \"GET\",\n            \"url\": {\n              \"raw\": \"https://postman-echo.com/get\",\n              \"protocol\": \"https\",\n              \"host\": [\n                \"postman-echo\",\n                \"com\"\n              ],\n              \"path\": [\n                \"get\"\n              ],\n              \"query\": [{\n                \"key\": \"foo\",\n                \"value\": null,\n                \"disabled\": true\n              }]\n            }\n          }\n        },\n        {\n          \"name\": \"params with empty key or value\",\n          \"event\": [{\n            \"listen\": \"test\",\n            \"script\": {\n              \"id\": \"7a927d59-4786-4ae4-80db-fe8bc841bb95\",\n              \"exec\": [\n                \"pm.test(\\\"Request URL\\\", function () {\",\n                \"    const {url} =  pm.response.json();\",\n                \"\",\n                \"    pm.expect(url).to.equal('https://postman-echo.com/get?get&=bar&=&baz=&&');\",\n                \"});\"\n              ],\n              \"type\": \"text/javascript\"\n            }\n          }],\n          \"request\": {\n            \"method\": \"GET\",\n            \"url\": {\n              \"raw\": \"https://postman-echo.com/get?get&=bar&=&baz=&&\",\n              \"protocol\": \"https\",\n              \"host\": [\n                \"postman-echo\",\n                \"com\"\n              ],\n              \"path\": [\n                \"get\"\n              ],\n              \"query\": [{\n                  \"key\": \"get\",\n                  \"value\": null\n                },\n                {\n                  \"key\": \"\",\n                  \"value\": \"bar\"\n                },\n                {\n                  \"key\": \"\",\n                  \"value\": \"\"\n                },\n                {\n                  \"key\": \"baz\",\n                  \"value\": \"\"\n                },\n                {\n                  \"key\": null,\n                  \"value\": null\n                },\n                {\n                  \"key\": \"\",\n                  \"value\": null\n                }\n              ]\n            }\n          }\n        }\n      ]\n    },\n    {\n      \"name\": \"Encoding\",\n      \"item\": [{\n          \"name\": \"IP shorthands\",\n          \"event\": [{\n            \"listen\": \"test\",\n            \"script\": {\n              \"id\": \"e56f053c-2462-4b34-a63d-af9011a87345\",\n              \"exec\": [\n                \"pm.test(\\\"Request Payload\\\", function () {\",\n                \"    const response = pm.response.text();\",\n                \"    \",\n                \"    pm.expect(response).to.include('Host: 127.0.0.1:4041'); // should be 127.0.0.1\",\n                \"});\"\n              ],\n              \"type\": \"text/javascript\"\n            }\n          }],\n          \"request\": {\n            \"method\": \"GET\",\n            \"url\": {\n              \"raw\": \"127.1:4041\",\n              \"host\": [\n                \"127\",\n                \"1\"\n              ],\n              \"port\": \"4041\"\n            }\n          }\n        },\n        {\n          \"name\": \"path encoding\",\n          \"event\": [{\n            \"listen\": \"test\",\n            \"script\": {\n              \"id\": \"4ea0fa54-dec1-4a87-b9ee-081209f38903\",\n              \"exec\": [\n                \"var encode = [' ', '\\\"', '<', '>', '`', '#', '?', '{', '}'],\",\n                \"    chars = [],\",\n                \"    char;\",\n                \"\",\n                \"for (var i = 32; i < 127; i++) {\",\n                \"    char = String.fromCharCode(i);\",\n                \"    if (char === '#' || char === '?' || char === '\\\\\\\\') {\",\n                \"        continue;\",\n                \"    }\",\n                \"\",\n                \"    chars.push(encode.includes(char) ? encodeURIComponent(char) : char);\",\n                \"}\",\n                \"\",\n                \"pm.test(\\\"Request Payload\\\", function() {\",\n                \"    const response = pm.response.text();\",\n                \"\",\n                \"    pm.expect(response).to.include(`GET /${chars.join('/')}`);\",\n                \"});\"\n              ],\n              \"type\": \"text/javascript\"\n            }\n          }],\n          \"request\": {\n            \"method\": \"GET\",\n            \"url\": {\n              \"raw\": \"http://localhost:4041/ /!/\\\"/$/%/&/'/(/)/*/+/,/-/.///0/1/2/3/4/5/6/7/8/9/:/;/</=/>/@/A/B/C/D/E/F/G/H/I/J/K/L/M/N/O/P/Q/R/S/T/U/V/W/X/Y/Z/[/]/^/_/`/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/{/|/}/~\",\n              \"protocol\": \"http\",\n              \"host\": [\n                \"localhost\"\n              ],\n              \"port\": \"4041\",\n              \"path\": [\n                \" \",\n                \"!\",\n                \"\\\"\",\n                \"$\",\n                \"%\",\n                \"&\",\n                \"'\",\n                \"(\",\n                \")\",\n                \"*\",\n                \"+\",\n                \",\",\n                \"-\",\n                \".\",\n                \"\",\n                \"\",\n                \"0\",\n                \"1\",\n                \"2\",\n                \"3\",\n                \"4\",\n                \"5\",\n                \"6\",\n                \"7\",\n                \"8\",\n                \"9\",\n                \":\",\n                \";\",\n                \"<\",\n                \"=\",\n                \">\",\n                \"@\",\n                \"A\",\n                \"B\",\n                \"C\",\n                \"D\",\n                \"E\",\n                \"F\",\n                \"G\",\n                \"H\",\n                \"I\",\n                \"J\",\n                \"K\",\n                \"L\",\n                \"M\",\n                \"N\",\n                \"O\",\n                \"P\",\n                \"Q\",\n                \"R\",\n                \"S\",\n                \"T\",\n                \"U\",\n                \"V\",\n                \"W\",\n                \"X\",\n                \"Y\",\n                \"Z\",\n                \"[\",\n                \"]\",\n                \"^\",\n                \"_\",\n                \"`\",\n                \"a\",\n                \"b\",\n                \"c\",\n                \"d\",\n                \"e\",\n                \"f\",\n                \"g\",\n                \"h\",\n                \"i\",\n                \"j\",\n                \"k\",\n                \"l\",\n                \"m\",\n                \"n\",\n                \"o\",\n                \"p\",\n                \"q\",\n                \"r\",\n                \"s\",\n                \"t\",\n                \"u\",\n                \"v\",\n                \"w\",\n                \"x\",\n                \"y\",\n                \"z\",\n                \"{\",\n                \"|\",\n                \"}\",\n                \"~\"\n              ]\n            }\n          }\n        },\n        {\n          \"name\": \"path unicode characters\",\n          \"event\": [{\n            \"listen\": \"test\",\n            \"script\": {\n              \"id\": \"4ea0fa54-dec1-4a87-b9ee-081209f38903\",\n              \"exec\": [\n                \"pm.test(\\\"Request Payload\\\", function() {\",\n                \"    const response = pm.response.text();\",\n                \"\",\n                \"    pm.expect(response).to.include('GET /%F0%9D%8C%86/%D0%B9/%E4%BD%A0/%E3%82%B9/%F0%9F%8D%AA');\",\n                \"});\"\n              ],\n              \"type\": \"text/javascript\"\n            }\n          }],\n          \"request\": {\n            \"method\": \"GET\",\n            \"url\": {\n              \"raw\": \"http://localhost:4041/𝌆/й/你/ス/🍪\",\n              \"protocol\": \"http\",\n              \"host\": [\n                \"localhost\"\n              ],\n              \"port\": \"4041\",\n              \"path\": [\n                \"𝌆\",\n                \"й\",\n                \"你\",\n                \"ス\",\n                \"🍪\"\n              ]\n            }\n          }\n        },\n        {\n          \"name\": \"path pre-encoded\",\n          \"event\": [{\n            \"listen\": \"test\",\n            \"script\": {\n              \"id\": \"4ea0fa54-dec1-4a87-b9ee-081209f38903\",\n              \"exec\": [\n                \"pm.test(\\\"Request Payload\\\", function() {\",\n                \"    const response = pm.response.text();\",\n                \"\",\n                \"    pm.expect(response).to.include('GET /foo/%2a/%F0%9F%8D%AA');\",\n                \"});\"\n              ],\n              \"type\": \"text/javascript\"\n            }\n          }],\n          \"request\": {\n            \"method\": \"GET\",\n            \"url\": {\n              \"raw\": \"http://localhost:4041/foo/%2a/%F0%9F%8D%AA\",\n              \"protocol\": \"http\",\n              \"host\": [\n                \"localhost\"\n              ],\n              \"port\": \"4041\",\n              \"path\": [\n                \"foo\",\n                \"%2a\",\n                \"%F0%9F%8D%AA\"\n              ]\n            }\n          }\n        },\n        {\n          \"name\": \"query unicode characters\",\n          \"event\": [{\n            \"listen\": \"test\",\n            \"script\": {\n              \"id\": \"4ea0fa54-dec1-4a87-b9ee-081209f38903\",\n              \"exec\": [\n                \"pm.test(\\\"Request Payload\\\", function() {\",\n                \"    const response = pm.response.text();\",\n                \"\",\n                \"    pm.expect(response).to.include('GET /?q=%F0%9D%8C%86%D0%B9%E4%BD%A0%E3%82%B9%F0%9F%8D%AA');\",\n                \"});\"\n              ],\n              \"type\": \"text/javascript\"\n            }\n          }],\n          \"request\": {\n            \"method\": \"GET\",\n            \"url\": {\n              \"raw\": \"http://localhost:4041?q=𝌆й你ス🍪\",\n              \"protocol\": \"http\",\n              \"host\": [\n                \"localhost\"\n              ],\n              \"port\": \"4041\",\n              \"query\": [{\n                \"key\": \"q\",\n                \"value\": \"𝌆й你ス🍪\"\n              }]\n            }\n          }\n        },\n        {\n          \"name\": \"query pre-encoded\",\n          \"event\": [{\n            \"listen\": \"test\",\n            \"script\": {\n              \"id\": \"4ea0fa54-dec1-4a87-b9ee-081209f38903\",\n              \"exec\": [\n                \"pm.test(\\\"Request Payload\\\", function() {\",\n                \"    const response = pm.response.text();\",\n                \"\",\n                \"    pm.expect(response).to.include('GET /?q=%F0%9F%8D%AA');\",\n                \"});\"\n              ],\n              \"type\": \"text/javascript\"\n            }\n          }],\n          \"request\": {\n            \"method\": \"GET\",\n            \"url\": {\n              \"raw\": \"http://localhost:4041/?q=%F0%9F%8D%AA\",\n              \"protocol\": \"http\",\n              \"host\": [\n                \"localhost\"\n              ],\n              \"port\": \"4041\",\n              \"path\": [\n                \"\"\n              ],\n              \"query\": [{\n                \"key\": \"q\",\n                \"value\": \"%F0%9F%8D%AA\"\n              }]\n            }\n          }\n        }\n      ]\n    },\n    {\n      \"name\": \"On Redirect\",\n      \"item\": [{\n          \"name\": \"encoding\",\n          \"event\": [{\n            \"listen\": \"test\",\n            \"script\": {\n              \"id\": \"e7fd6405-21f0-4a2a-a207-91d8862846d6\",\n              \"exec\": [\n                \"pm.test.skip(\\\"Request URL\\\", function () {\",\n                \"    const {url} =  pm.response.json();\",\n                \"\",\n                \"    pm.expect(url).to.equal('https://postman-echo.com/get?q={abc}');\",\n                \"});\"\n              ],\n              \"type\": \"text/javascript\"\n            }\n          }],\n          \"protocolProfileBehavior\": {\n            \"followRedirects\": true\n          },\n          \"request\": {\n            \"method\": \"GET\",\n            \"url\": {\n              \"raw\": \"https://httpbin.org/redirect-to?url=https://postman-echo.com/get?q={abc}\",\n              \"protocol\": \"https\",\n              \"host\": [\n                \"httpbin\",\n                \"org\"\n              ],\n              \"path\": [\n                \"redirect-to\"\n              ],\n              \"query\": [{\n                \"key\": \"url\",\n                \"value\": \"https://postman-echo.com/get?q={abc}\"\n              }]\n            }\n          }\n        },\n        {\n          \"name\": \"with disable encoding\",\n          \"event\": [{\n            \"listen\": \"test\",\n            \"script\": {\n              \"id\": \"da3fbbaf-91c8-4986-896c-d1cf68a57c73\",\n              \"exec\": [\n                \"pm.test.skip(\\\"Request URL\\\", function () {\",\n                \"    const {url} =  pm.response.json();\",\n                \"\",\n                \"    pm.expect(url).to.equal('https://postman-echo.com/get?q={\\\"abc\\\"}');\",\n                \"});\"\n              ],\n              \"type\": \"text/javascript\"\n            }\n          }],\n          \"protocolProfileBehavior\": {\n            \"followRedirects\": true,\n            \"disableUrlEncoding\": true\n          },\n          \"request\": {\n            \"method\": \"GET\",\n            \"url\": {\n              \"raw\": \"https://httpbin.org/redirect-to?url=https://postman-echo.com/get?q={\\\"abc\\\"}\",\n              \"protocol\": \"https\",\n              \"host\": [\n                \"httpbin\",\n                \"org\"\n              ],\n              \"path\": [\n                \"redirect-to\"\n              ],\n              \"query\": [{\n                \"key\": \"url\",\n                \"value\": \"https://postman-echo.com/get?q={\\\"abc\\\"}\"\n              }]\n            }\n          }\n        }\n      ]\n    },\n    {\n      \"name\": \"Disabled Encoding\",\n      \"item\": [{\n          \"name\": \"path encoding\",\n          \"event\": [{\n            \"listen\": \"test\",\n            \"script\": {\n              \"id\": \"4ea0fa54-dec1-4a87-b9ee-081209f38903\",\n              \"exec\": [\n                \"pm.test(\\\"Request Payload\\\", function() {\",\n                \"    const response = pm.response.text();\",\n                \"\",\n                \"    pm.expect(response).to.include('GET /!/\\\"/$/%/&/\\\\'/(/)/*/+/,/-/.///0/1/2/3/4/5/6/7/8/9/:/;/</=/>/@/A/B/C/D/E/F/G/H/I/J/K/L/M/N/O/P/Q/R/S/T/U/V/W/X/Y/Z/[/]/^/_/`/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/{/|/}/~');\",\n                \"});\"\n              ],\n              \"type\": \"text/javascript\"\n            }\n          }],\n          \"protocolProfileBehavior\": {\n            \"disableUrlEncoding\": true\n          },\n          \"request\": {\n            \"method\": \"GET\",\n            \"url\": {\n              \"raw\": \"http://localhost:4041/!/\\\"/$/%/&/'/(/)/*/+/,/-/.///0/1/2/3/4/5/6/7/8/9/:/;/</=/>/@/A/B/C/D/E/F/G/H/I/J/K/L/M/N/O/P/Q/R/S/T/U/V/W/X/Y/Z/[/]/^/_/`/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/{/|/}/~\",\n              \"protocol\": \"http\",\n              \"host\": [\n                \"localhost\"\n              ],\n              \"port\": \"4041\",\n              \"path\": [\n                \"!\",\n                \"\\\"\",\n                \"$\",\n                \"%\",\n                \"&\",\n                \"'\",\n                \"(\",\n                \")\",\n                \"*\",\n                \"+\",\n                \",\",\n                \"-\",\n                \".\",\n                \"\",\n                \"\",\n                \"0\",\n                \"1\",\n                \"2\",\n                \"3\",\n                \"4\",\n                \"5\",\n                \"6\",\n                \"7\",\n                \"8\",\n                \"9\",\n                \":\",\n                \";\",\n                \"<\",\n                \"=\",\n                \">\",\n                \"@\",\n                \"A\",\n                \"B\",\n                \"C\",\n                \"D\",\n                \"E\",\n                \"F\",\n                \"G\",\n                \"H\",\n                \"I\",\n                \"J\",\n                \"K\",\n                \"L\",\n                \"M\",\n                \"N\",\n                \"O\",\n                \"P\",\n                \"Q\",\n                \"R\",\n                \"S\",\n                \"T\",\n                \"U\",\n                \"V\",\n                \"W\",\n                \"X\",\n                \"Y\",\n                \"Z\",\n                \"[\",\n                \"]\",\n                \"^\",\n                \"_\",\n                \"`\",\n                \"a\",\n                \"b\",\n                \"c\",\n                \"d\",\n                \"e\",\n                \"f\",\n                \"g\",\n                \"h\",\n                \"i\",\n                \"j\",\n                \"k\",\n                \"l\",\n                \"m\",\n                \"n\",\n                \"o\",\n                \"p\",\n                \"q\",\n                \"r\",\n                \"s\",\n                \"t\",\n                \"u\",\n                \"v\",\n                \"w\",\n                \"x\",\n                \"y\",\n                \"z\",\n                \"{\",\n                \"|\",\n                \"}\",\n                \"~\"\n              ]\n            }\n          }\n        },\n        {\n          \"name\": \"query encoding\",\n          \"event\": [{\n            \"listen\": \"test\",\n            \"script\": {\n              \"id\": \"4ea0fa54-dec1-4a87-b9ee-081209f38903\",\n              \"exec\": [\n                \"var encode = [' ', '\\\"', '#', '&', '\\\\'', '<', '=', '>'],\",\n                \"    chars = [],\",\n                \"    char;\",\n                \"\",\n                \"for (var i = 32; i < 127; i++) {\",\n                \"    char = String.fromCharCode(i);\",\n                \"    !encode.includes(char) && chars.push(char);\",\n                \"}\",\n                \"\",\n                \"pm.test(\\\"Request Payload\\\", function() {\",\n                \"    const response = pm.response.text();\",\n                \"\",\n                \"    pm.expect(response).to.include('GET /?q=\\\"\\\\'<=>!$%()*+,-./0123456789:;?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\\\\\\\]^_`abcdefghijklmnopqrstuvwxyz{|}~');\",\n                \"});\"\n              ],\n              \"type\": \"text/javascript\"\n            }\n          }],\n          \"protocolProfileBehavior\": {\n            \"disableUrlEncoding\": true\n          },\n          \"request\": {\n            \"method\": \"GET\",\n            \"url\": {\n              \"raw\": \"http://localhost:4041?q=\\\"'<=>!$%()*+,-./0123456789:;?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\",\n              \"protocol\": \"http\",\n              \"host\": [\n                \"localhost\"\n              ],\n              \"port\": \"4041\",\n              \"query\": [{\n                \"key\": \"q\",\n                \"value\": \"\\\"'<=>!$%()*+,-./0123456789:;?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\"\n              }]\n            }\n          }\n        }\n      ]\n    }\n  ],\n  \"event\": [{\n    \"listen\": \"test\",\n    \"script\": {\n      \"id\": \"0bee6b62-8946-41dc-a1c1-bf5113c46e32\",\n      \"type\": \"text/javascript\",\n      \"exec\": [\n        \"pm.test.skip(`Status code is 200 for \\\"${pm.info.requestName}\\\"`, function () {\",\n        \"    pm.response.to.have.status(200);\",\n        \"});\"\n      ]\n    }\n  }]\n}\n"
  },
  {
    "path": "test/library/cookie-jar.test.js",
    "content": "const path = require('path'),\n    fs = require('fs'),\n    sh = require('shelljs'),\n    expect = require('chai').expect,\n    CookieJar = require('@postman/tough-cookie').CookieJar,\n\n    newman = require('../../');\n\ndescribe('newman.run cookieJar', function () {\n    var cookieJar = new CookieJar(),\n        cookieJarPath = 'test/fixtures/run/spaces/simple-cookie-jar.json',\n        collection = 'test/integration/cookie-jar.postman_collection.json';\n\n    it('should correctly persist cookies across requests in a run', function (done) {\n        newman.run({\n            collection\n        }, function (err, summary) {\n            expect(err).to.be.null;\n            expect(summary.run.failures).to.be.empty;\n\n            done();\n        });\n    });\n\n    it('should persist cookies in custom cookie jar', function (done) {\n        newman.run({\n            collection,\n            cookieJar\n        }, function (err) {\n            expect(err).to.be.null;\n\n            var cookies = cookieJar.getCookieStringSync('http://postman-echo.com/');\n\n            expect(cookies).to.match(/foo=bar;/);\n\n            done();\n        });\n    });\n\n    it('should load cookies from cookie jar file', function (done) {\n        newman.run({\n            collection: collection,\n            cookieJar: cookieJarPath\n        }, function (err, summary) {\n            expect(err).to.be.null;\n\n            expect(summary.run.executions[1].response.json().cookies).to.be.ok;\n\n            expect(summary.run.executions[1].response.json().cookies).to.include({\n                foo: 'bar', // new cookie\n                foo2: 'baz' // existing cookie\n            });\n\n            done();\n        });\n    });\n\n    it('should throw on path to invalid json', function (done) {\n        newman.run({\n            collection: collection,\n            cookieJar: collection\n        }, function (err) {\n            expect(err).to.be.ok;\n            expect(err).to.have.property('message',\n                'the file at ' + collection + ' does not contain valid JSON data.');\n            done();\n        });\n    });\n\n    it('should throw on passing invalid cookie jar', function (done) {\n        newman.run({\n            collection: collection,\n            cookieJar: {}\n        }, function (err) {\n            expect(err).to.be.ok;\n            expect(err).to.have.property('message',\n                'cookieJar must be a path to a JSON file or a CookieJar instance');\n            done();\n        });\n    });\n\n    describe('export cookieJar', function () {\n        var outDir = 'out',\n            exportedCookieJarPath = path.join(__dirname, '..', '..', outDir, 'test-cookie-jar.json');\n\n        beforeEach(function () {\n            sh.test('-d', outDir) && sh.rm('-rf', outDir);\n            sh.mkdir('-p', outDir);\n        });\n\n        afterEach(function () {\n            sh.rm('-rf', outDir);\n        });\n\n        it('should export cookie jar to a file', function (done) {\n            newman.run({\n                collection: collection,\n                exportCookieJar: exportedCookieJarPath\n            }, function (err) {\n                expect(err).to.be.null;\n\n                var exportedCookieJar,\n                    cookies;\n\n                try { exportedCookieJar = CookieJar.fromJSON(fs.readFileSync(exportedCookieJarPath).toString()); }\n                catch (e) { console.error(e); }\n\n                expect(exportedCookieJar).to.be.ok;\n\n                cookies = exportedCookieJar.getCookieStringSync('http://postman-echo.com/');\n\n                expect(cookies).to.match(/foo=bar;/);\n\n                done();\n            });\n        });\n    });\n});\n"
  },
  {
    "path": "test/library/export-environment.test.js",
    "content": "const fs = require('fs'),\n    path = require('path'),\n\n    sh = require('shelljs'),\n    expect = require('chai').expect,\n\n    newman = require('../../');\n\ndescribe('newman.run exportEnvironment', function () {\n    var outDir = 'out',\n        environment = 'test/fixtures/run/simple-variables.json',\n        exportedEnvironmentPath = path.join(__dirname, '..', '..', outDir, 'test-environment.json');\n\n    beforeEach(function () {\n        sh.test('-d', outDir) && sh.rm('-rf', outDir);\n        sh.mkdir('-p', outDir);\n    });\n\n    afterEach(function () {\n        sh.rm('-rf', outDir);\n    });\n\n    it('should export environment to a file', function (done) {\n        newman.run({\n            collection: 'test/fixtures/run/single-get-request.json',\n            environment: environment,\n            exportEnvironment: exportedEnvironmentPath\n        }, function (err) {\n            if (err) { return done(err); }\n\n            var environment;\n\n            try { environment = JSON.parse(fs.readFileSync(exportedEnvironmentPath).toString()); }\n            catch (e) { console.error(e); }\n\n            expect(environment).to.be.ok;\n            expect(environment).to.have.property('_postman_exported_at');\n            expect(environment).to.have.property('values');\n            expect(environment.values).to.eql([\n                { key: 'var-1', value: 'value-1', type: 'any' },\n                { key: 'var-2', value: 'value-2', type: 'any' }\n            ]);\n            expect(environment).to.have.property('_postman_variable_scope', 'environment');\n            done();\n        });\n    });\n\n    it('should export environment to a file even if collection is failing', function (done) {\n        newman.run({\n            collection: 'test/fixtures/run/single-request-failing.json',\n            environment: environment,\n            exportEnvironment: exportedEnvironmentPath\n        }, function (err) {\n            if (err) { return done(err); }\n\n            var environment;\n\n            try { environment = JSON.parse(fs.readFileSync(exportedEnvironmentPath).toString()); }\n            catch (e) { console.error(e); }\n\n            expect(environment).to.be.ok;\n            expect(environment).to.have.property('_postman_exported_at');\n            expect(environment).to.have.property('values');\n            expect(environment.values).to.eql([\n                { key: 'var-1', value: 'value-1', type: 'any' },\n                { key: 'var-2', value: 'value-2', type: 'any' }\n            ]);\n            expect(environment).to.have.property('_postman_variable_scope', 'environment');\n            done();\n        });\n    });\n\n    it('`newman run` should export environment to a file in a pre-existing directory', function (done) {\n        newman.run({\n            collection: 'test/fixtures/run/single-get-request.json',\n            environment: environment,\n            exportEnvironment: outDir\n        }, function (err) {\n            if (err) { return done(err); }\n\n            var dir = fs.readdirSync(outDir),\n                file = dir[0],\n                environment;\n\n            expect(dir).to.have.length(1);\n\n            try { environment = JSON.parse(fs.readFileSync(outDir + '/' + file).toString()); }\n            catch (e) { console.error(e); }\n\n            expect(environment).to.be.ok;\n            expect(environment).have.property('_postman_exported_at');\n            expect(environment).have.property('values');\n            expect(environment.values).eql([\n                { key: 'var-1', value: 'value-1', type: 'any' },\n                { key: 'var-2', value: 'value-2', type: 'any' }\n            ]);\n            expect(environment).have.property('_postman_variable_scope', 'environment');\n            done();\n        });\n    });\n\n    it('should export environment with a name if the input file doesn\\'t have one', function (done) {\n        newman.run({\n            collection: 'test/fixtures/run/single-request-failing.json',\n            environment: {\n                values: [{ key: 'var-1', value: 'value-1' }]\n            },\n            exportEnvironment: exportedEnvironmentPath\n        }, function (err) {\n            if (err) { return done(err); }\n\n            var environment;\n\n            try { environment = JSON.parse(fs.readFileSync(exportedEnvironmentPath).toString()); }\n            catch (e) { console.error(e); }\n\n            expect(environment).to.be.ok;\n            expect(environment).to.have.property('_postman_exported_at');\n            expect(environment).to.have.property('values');\n            expect(environment).to.have.property('name', 'environment');\n            expect(environment.values).to.eql([\n                { key: 'var-1', value: 'value-1', type: 'any' }\n            ]);\n            expect(environment).to.have.property('_postman_variable_scope', 'environment');\n            done();\n        });\n    });\n\n    it('should export environment with a name when no input file is provided', function (done) {\n        newman.run({\n            collection: {\n                item: [{\n                    event: [{\n                        listen: 'test',\n                        script: 'pm.environment.set(\"var-1\", \"value-1\");'\n                    }],\n                    request: 'https://postman-echo.com/get?source=newman-sample-github-collection'\n                }]\n            },\n            exportEnvironment: exportedEnvironmentPath\n        }, function (err) {\n            if (err) { return done(err); }\n\n            var environment;\n\n            try { environment = JSON.parse(fs.readFileSync(exportedEnvironmentPath).toString()); }\n            catch (e) { console.error(e); }\n\n            expect(environment).to.be.ok;\n            expect(environment).to.have.property('_postman_exported_at');\n            expect(environment).to.have.property('values');\n            expect(environment).to.have.property('name', 'environment');\n            expect(environment.values).to.eql([\n                { key: 'var-1', value: 'value-1', type: 'any' }\n            ]);\n            expect(environment).to.have.property('_postman_variable_scope', 'environment');\n            done();\n        });\n    });\n});\n"
  },
  {
    "path": "test/library/export-globals.test.js",
    "content": "const fs = require('fs'),\n    path = require('path'),\n\n    sh = require('shelljs'),\n    expect = require('chai').expect,\n\n    newman = require('../../');\n\ndescribe('newman.run exportGlobals', function () {\n    var outDir = 'out',\n        globals = 'test/fixtures/run/simple-variables.json',\n        exportedGlobalsPath = path.join(__dirname, '..', '..', outDir, 'test-globals.json');\n\n    beforeEach(function () {\n        sh.test('-d', outDir) && sh.rm('-rf', outDir);\n        sh.mkdir('-p', outDir);\n    });\n\n    afterEach(function () {\n        sh.rm('-rf', outDir);\n    });\n\n    it('should export globals to a file', function (done) {\n        newman.run({\n            collection: 'test/fixtures/run/single-get-request.json',\n            globals: globals,\n            exportGlobals: exportedGlobalsPath\n        }, function (err) {\n            if (err) { return done(err); }\n\n            var globals;\n\n            try { globals = JSON.parse(fs.readFileSync(exportedGlobalsPath).toString()); }\n            catch (e) { console.error(e); }\n\n            expect(globals).to.be.ok;\n            expect(globals).to.have.property('_postman_exported_at');\n            expect(globals).to.have.property('values');\n            expect(globals.values).to.eql([\n                { key: 'var-1', value: 'value-1', type: 'any' },\n                { key: 'var-2', value: 'value-2', type: 'any' }\n            ]);\n            expect(globals).to.have.property('_postman_variable_scope', 'globals');\n            done();\n        });\n    });\n\n    it('should export globals to a file even if collection is failing', function (done) {\n        newman.run({\n            collection: 'test/fixtures/run/single-request-failing.json',\n            globals: globals,\n            exportGlobals: exportedGlobalsPath\n        }, function (err) {\n            if (err) { return done(err); }\n\n            var globals;\n\n            try { globals = JSON.parse(fs.readFileSync(exportedGlobalsPath).toString()); }\n            catch (e) { console.error(e); }\n\n            expect(globals).to.be.ok;\n            expect(globals).to.have.property('_postman_exported_at');\n            expect(globals).to.have.property('values');\n            expect(globals.values).to.eql([\n                { key: 'var-1', value: 'value-1', type: 'any' },\n                { key: 'var-2', value: 'value-2', type: 'any' }\n            ]);\n            expect(globals).to.have.property('_postman_variable_scope', 'globals');\n            done();\n        });\n    });\n\n    it('`newman run` should export globals to a file in a pre-existing directory', function (done) {\n        newman.run({\n            collection: 'test/fixtures/run/single-get-request.json',\n            globals: globals,\n            exportGlobals: outDir\n        }, function (err) {\n            if (err) { return done(err); }\n\n            var dir = fs.readdirSync(outDir),\n                file = dir[0],\n                globals;\n\n            expect(dir).to.have.length(1);\n\n            try { globals = JSON.parse(fs.readFileSync(outDir + '/' + file).toString()); }\n            catch (e) { console.error(e); }\n\n            expect(globals).to.be.ok;\n            expect(globals).have.property('_postman_exported_at');\n            expect(globals).have.property('values');\n            expect(globals.values).eql([\n                { key: 'var-1', value: 'value-1', type: 'any' },\n                { key: 'var-2', value: 'value-2', type: 'any' }\n            ]);\n            expect(globals).have.property('_postman_variable_scope', 'globals');\n            done();\n        });\n    });\n\n    it('should export globals with a name if the input file doesn\\'t have one', function (done) {\n        newman.run({\n            collection: 'test/fixtures/run/single-request-failing.json',\n            globals: {\n                values: [{ key: 'var-1', value: 'value-1' }]\n            },\n            exportGlobals: exportedGlobalsPath\n        }, function (err) {\n            if (err) { return done(err); }\n\n            var globals;\n\n            try { globals = JSON.parse(fs.readFileSync(exportedGlobalsPath).toString()); }\n            catch (e) { console.error(e); }\n\n            expect(globals).to.be.ok;\n            expect(globals).to.have.property('_postman_exported_at');\n            expect(globals).to.have.property('values');\n            expect(globals).to.have.property('name', 'globals');\n            expect(globals.values).eql([\n                { key: 'var-1', value: 'value-1', type: 'any' }\n            ]);\n            expect(globals).to.have.property('_postman_variable_scope', 'globals');\n            done();\n        });\n    });\n\n    it('should export globals with a name when no input file is provided', function (done) {\n        newman.run({\n            collection: {\n                item: [{\n                    event: [{\n                        listen: 'test',\n                        script: 'pm.globals.set(\"var-1\", \"value-1\");'\n                    }],\n                    request: 'https://postman-echo.com/get?source=newman-sample-github-collection'\n                }]\n            },\n            exportGlobals: exportedGlobalsPath\n        }, function (err) {\n            if (err) { return done(err); }\n\n            var globals;\n\n            try { globals = JSON.parse(fs.readFileSync(exportedGlobalsPath).toString()); }\n            catch (e) { console.error(e); }\n\n            expect(globals).to.be.ok;\n            expect(globals).to.have.property('_postman_exported_at');\n            expect(globals).to.have.property('values');\n            expect(globals).to.have.property('name', 'globals');\n            expect(globals.values).to.eql([\n                { key: 'var-1', value: 'value-1', type: 'any' }\n            ]);\n            expect(globals).to.have.property('_postman_variable_scope', 'globals');\n            done();\n        });\n    });\n});\n"
  },
  {
    "path": "test/library/folder-variants.test.js",
    "content": "const expect = require('chai').expect,\n\n    newman = require('../../');\n\ndescribe('folder variants', function () {\n    var collection = {\n        id: 'C1',\n        name: 'Collection C1',\n        item: [{\n            id: 'ID1',\n            name: 'R1',\n            request: 'https://postman-echo.com/get'\n        }, {\n            id: 'ID2',\n            name: 'R2',\n            request: 'https://postman-echo.com/get'\n        }, {\n            id: 'ID3',\n            name: 'R3',\n            request: 'https://postman-echo.com/get'\n        }]\n    };\n\n    it('should run the specified request in case folder name is valid', function (done) {\n        newman.run({\n            collection: collection,\n            folder: 'R1'\n        }, function (err, summary) {\n            expect(err).to.be.null;\n            expect(summary.run.stats.iterations.total, 'should have 1 iteration').to.equal(1);\n            expect(summary.run.executions, 'should have 1 executions').to.have.lengthOf(1);\n            expect(summary.run.executions.map((e) => { return e.item.name; })).to.eql(['R1']);\n            done();\n        });\n    });\n\n    it('should skip the collection run in case folder name is invalid', function (done) {\n        newman.run({\n            collection: collection,\n            folder: 'R123'\n        }, function (err) {\n            expect(err).to.be.ok;\n            expect(err.message)\n                .to.equal('runtime~extractRunnableItems: Unable to find a folder or request: \"R123\"');\n            done();\n        });\n    });\n\n    it('should run the specified requests in case multiple folder names are passed', function (done) {\n        newman.run({\n            collection: collection,\n            folder: ['R1', 'R3']\n        }, function (err, summary) {\n            expect(err).to.be.null;\n            expect(summary.run.stats.iterations.total, 'should have 1 iteration').to.equal(1);\n            expect(summary.run.executions, 'should have 2 executions').to.have.lengthOf(2);\n            expect(summary.run.executions.map((e) => { return e.item.name; })).to.eql(['R1', 'R3']);\n            done();\n        });\n    });\n\n    it('should skip the collection run in case any of the folder name is invalid', function (done) {\n        newman.run({\n            collection: collection,\n            folder: ['R1', 'R123']\n        }, function (err) {\n            expect(err).to.be.ok;\n            expect(err.message)\n                .to.equal('runtime~extractRunnableItems: Invalid entrypoint');\n            done();\n        });\n    });\n});\n"
  },
  {
    "path": "test/library/iteration-count.test.js",
    "content": "var fs = require('fs'),\n    path = require('path'),\n\n    _ = require('lodash'),\n    expect = require('chai').expect,\n\n    newman = require('../../');\n\ndescribe('iterationCount vs iterationData.length conflicts', function () {\n    var iterationProperty = 'run.stats.iterations.total',\n        collectionRunPath = path.join(__dirname, '..', '..', 'out', 'iteration-count-test.json');\n\n    beforeEach(function (done) {\n        fs.stat('out', function (err) {\n            if (err) { return fs.mkdir('out', done); }\n\n            done();\n        });\n    });\n\n    afterEach(function (done) {\n        fs.stat(collectionRunPath, function (err) {\n            if (err) { return done(); }\n\n            fs.unlink(collectionRunPath, done);\n        });\n    });\n\n    it('should iterate exactly once when no options are specified', function (done) {\n        newman.run({\n            collection: 'test/fixtures/run/single-get-request.json',\n            reporters: ['json'],\n            reporter: { json: { export: collectionRunPath } }\n        }, function (err) {\n            if (err) { return done(err); }\n\n            var collectionRun;\n\n            try { collectionRun = JSON.parse(fs.readFileSync(collectionRunPath).toString()); }\n            catch (e) { console.error(e); }\n\n            expect(_.get(collectionRun, iterationProperty), 'should have 1 iteration').to.equal(1);\n            done();\n        });\n    });\n\n    it('should iterate according to iterationData.length when specified', function (done) {\n        newman.run({\n            collection: 'test/integration/steph/steph.postman_collection.json',\n            iterationData: 'test/integration/steph/steph.postman_data.json',\n            reporters: ['json'],\n            reporter: { json: { export: collectionRunPath } }\n        }, function (err) {\n            if (err) { return done(err); }\n\n            var collectionRun;\n\n            try { collectionRun = JSON.parse(fs.readFileSync(collectionRunPath).toString()); }\n            catch (e) { console.error(e); }\n\n            expect(_.get(collectionRun, iterationProperty), 'should have 2 iterations').to.equal(2);\n            done();\n        });\n    });\n\n    it('should iterate according to iterationCount when specified', function (done) {\n        newman.run({\n            collection: 'test/fixtures/run/single-get-request.json',\n            iterationCount: 3,\n            reporters: ['json'],\n            reporter: { json: { export: collectionRunPath } }\n        }, function (err) {\n            if (err) { return done(err); }\n\n            var collectionRun;\n\n            try { collectionRun = JSON.parse(fs.readFileSync(collectionRunPath).toString()); }\n            catch (e) { console.error(e); }\n\n            expect(_.get(collectionRun, iterationProperty), 'should have 3 iterations').to.equal(3);\n            done();\n        });\n    });\n\n    it('should iterate according to iterationCount when BOTH options are specified', function (done) {\n        newman.run({\n            collection: 'test/integration/steph/steph.postman_collection.json',\n            iterationCount: 3,\n            iterationData: 'test/integration/steph/steph.postman_data.json',\n            reporters: ['json'],\n            reporter: { json: { export: collectionRunPath } }\n        }, function (err) {\n            if (err) { return done(err); }\n\n            var collectionRun;\n\n            try { collectionRun = JSON.parse(fs.readFileSync(collectionRunPath).toString()); }\n            catch (e) { console.error(e); }\n\n            expect(_.get(collectionRun, iterationProperty), 'should have 3 iteration').to.equal(3);\n            done();\n        });\n    });\n});\n"
  },
  {
    "path": "test/library/postman-api-key.test.js",
    "content": "const fs = require('fs'),\n    nock = require('nock'),\n    sinon = require('sinon'),\n    request = require('postman-request'),\n    expect = require('chai').expect,\n\n    newman = require('../../'),\n\n    COLLECTION = {\n        id: 'C1',\n        name: 'Collection',\n        item: [{\n            id: 'ID1',\n            name: 'R1',\n            request: 'https://postman-echo.com/get'\n        }]\n    },\n    VARIABLE = {\n        id: 'E1',\n        name: 'Environment',\n        values: [{\n            key: 'foo',\n            value: 'bar'\n        }]\n    };\n\ndescribe('newman.run postmanApiKey', function () {\n    before(function () {\n        nock('https://api.getpostman.com')\n            .persist()\n            .get(/^\\/collections/)\n            .reply(200, COLLECTION);\n\n        nock('https://api.postman.com')\n            .persist()\n            .get(/^\\/collections/)\n            .reply(200, COLLECTION);\n\n        nock('https://api.getpostman.com')\n            .persist()\n            .get(/^\\/environments/)\n            .reply(200, VARIABLE);\n\n        nock('https://api.postman.com')\n            .persist()\n            .get(/^\\/environments/)\n            .reply(200, VARIABLE);\n\n        nock('https://example.com')\n            .persist()\n            .get('/collection.json?apikey=12345678')\n            .reply(200, COLLECTION);\n    });\n\n    after(function () {\n        nock.restore();\n    });\n\n    beforeEach(function () {\n        sinon.spy(request, 'get');\n    });\n\n    afterEach(function () {\n        request.get.restore();\n    });\n\n    it('should fetch collection via UID', function (done) {\n        newman.run({\n            collection: '1234-588025f9-2497-46f7-b849-47f58b865807',\n            postmanApiKey: '12345678'\n        }, function (err, summary) {\n            expect(err).to.be.null;\n            sinon.assert.calledOnce(request.get);\n\n            let requestArg = request.get.firstCall.args[0];\n\n            expect(requestArg).to.be.an('object').and.include.keys(['url', 'json', 'headers']);\n\n            expect(requestArg.url)\n                .to.equal('https://api.postman.com/collections/1234-588025f9-2497-46f7-b849-47f58b865807');\n\n            expect(requestArg.headers).to.be.an('object')\n                .that.has.property('X-Api-Key', '12345678');\n\n            expect(summary).to.be.an('object')\n                .that.has.property('collection').to.be.an('object')\n                .and.include({ id: 'C1', name: 'Collection' });\n\n            expect(summary.run.failures).to.be.empty;\n            expect(summary.run.executions, 'should have 1 execution').to.have.lengthOf(1);\n\n            done();\n        });\n    });\n\n    it('should fetch environment via UID', function (done) {\n        newman.run({\n            collection: 'test/fixtures/run/single-get-request.json',\n            environment: '1234-931c1484-fd1e-4ceb-81d0-2aa102ca8b5f',\n            postmanApiKey: '12345678'\n        }, function (err, summary) {\n            expect(err).to.be.null;\n            sinon.assert.calledOnce(request.get);\n\n            let requestArg = request.get.firstCall.args[0];\n\n            expect(requestArg).to.be.an('object').and.include.keys(['url', 'json', 'headers']);\n\n            expect(requestArg.url)\n                .to.equal('https://api.postman.com/environments/1234-931c1484-fd1e-4ceb-81d0-2aa102ca8b5f');\n\n            expect(requestArg.headers).to.be.an('object')\n                .that.has.property('X-Api-Key', '12345678');\n\n            expect(summary).to.be.an('object')\n                .that.has.property('environment').to.be.an('object')\n                .and.include({ id: 'E1', name: 'Environment' });\n\n            expect(summary.run.failures).to.be.empty;\n            expect(summary.run.executions, 'should have 1 execution').to.have.lengthOf(1);\n\n            done();\n        });\n    });\n\n    it('should fetch all resources via UID', function (done) {\n        newman.run({\n            collection: '1234-588025f9-2497-46f7-b849-47f58b865807',\n            environment: '1234-931c1484-fd1e-4ceb-81d0-2aa102ca8b5f',\n            postmanApiKey: '12345678'\n        }, function (err, summary) {\n            expect(err).to.be.null;\n            sinon.assert.calledTwice(request.get);\n\n            expect(summary).to.be.an('object').and.include.keys(['collection', 'environment', 'globals', 'run']);\n\n            expect(summary.collection).to.include({ id: 'C1', name: 'Collection' });\n            expect(summary.environment).to.include({ id: 'E1', name: 'Environment' });\n\n            expect(summary.run.failures).to.be.empty;\n            expect(summary.run.executions, 'should have 1 execution').to.have.lengthOf(1);\n\n            done();\n        });\n    });\n\n    it('should end with an error if UID is passed without postmanApiKey and no such file exists', function (done) {\n        newman.run({\n            collection: '1234-588025f9-2497-46f7-b849-47f58b865807'\n        }, function (err) {\n            expect(err).to.be.ok.that.match(/no such file or directory/);\n            sinon.assert.notCalled(request.get);\n\n            done();\n        });\n    });\n\n    it('should pass API Key header for Postman API URLs', function (done) {\n        newman.run({\n            collection: 'https://api.postman.com/collections/1234',\n            postmanApiKey: '12345678'\n        }, function (err, summary) {\n            expect(err).to.be.null;\n            sinon.assert.calledOnce(request.get);\n\n            let requestArg = request.get.firstCall.args[0];\n\n            expect(requestArg).to.be.an('object').and.include.keys(['url', 'json', 'headers']);\n\n            expect(requestArg.url).to.equal('https://api.postman.com/collections/1234');\n\n            expect(requestArg.headers).to.have.property('X-Api-Key');\n\n            expect(summary.run.failures).to.be.empty;\n            expect(summary.run.executions, 'should have 1 execution').to.have.lengthOf(1);\n\n            done();\n        });\n    });\n\n    it('should pass API Key header for Postman API URLs instead of apikey query parameter', function (done) {\n        newman.run({\n            collection: 'https://api.getpostman.com/collections?apikey=12345678'\n        }, function (err, summary) {\n            expect(err).to.be.null;\n            sinon.assert.calledOnce(request.get);\n\n            let requestArg = request.get.firstCall.args[0];\n\n            expect(requestArg).to.be.an('object').and.include.keys(['url', 'json', 'headers']);\n\n            expect(requestArg.url).to.equal('https://api.getpostman.com/collections');\n\n            expect(requestArg.headers).to.have.property('X-Api-Key');\n\n            expect(summary.run.failures).to.be.empty;\n            expect(summary.run.executions, 'should have 1 execution').to.have.lengthOf(1);\n\n            done();\n        });\n    });\n\n    it('should not pass API Key header for non Postman API URLs', function (done) {\n        newman.run({\n            collection: 'https://example.com/collection.json?apikey=12345678',\n            postmanApiKey: '12345678'\n        }, function (err, summary) {\n            expect(err).to.be.null;\n            sinon.assert.calledOnce(request.get);\n\n            let requestArg = request.get.firstCall.args[0];\n\n            expect(requestArg).to.be.an('object').and.include.keys(['url', 'json', 'headers']);\n\n            expect(requestArg.url).to.equal('https://example.com/collection.json?apikey=12345678');\n\n            expect(requestArg.headers).to.not.have.property('X-Api-Key');\n\n            expect(summary.run.failures).to.be.empty;\n            expect(summary.run.executions, 'should have 1 execution').to.have.lengthOf(1);\n\n            done();\n        });\n    });\n\n    describe('read file', function () {\n        const UID = '1234-96771253-046f-4ad7-81f9-a2d3c433492b';\n\n        beforeEach(function (done) {\n            fs.stat(UID, function (err) {\n                if (err) {\n                    return fs.writeFile(UID, JSON.stringify(COLLECTION), done);\n                }\n\n                done();\n            });\n        });\n\n        afterEach(function (done) {\n            fs.stat(UID, function (err) {\n                if (err) { return done(); }\n\n                fs.unlink(UID, done);\n            });\n        });\n\n        it('should fetch from file having UID name', function (done) {\n            newman.run({\n                collection: UID,\n                postmanApiKey: '12345678'\n            }, function (err, summary) {\n                expect(err).to.be.null;\n                sinon.assert.notCalled(request.get);\n\n                expect(summary).to.be.an('object')\n                    .that.has.property('collection').to.be.an('object')\n                    .and.include({ id: 'C1', name: 'Collection' });\n\n                expect(summary.run.failures).to.be.empty;\n                expect(summary.run.executions, 'should have 1 execution').to.have.lengthOf(1);\n\n                done();\n            });\n        });\n    });\n});\n"
  },
  {
    "path": "test/library/requestAgents.test.js",
    "content": "const sinon = require('sinon'),\n    http = require('http'),\n    https = require('https'),\n    expect = require('chai').expect,\n\n    newman = require('../../');\n\ndescribe('newman.run requestAgents', function () {\n    let httpAgent = new http.Agent(),\n        httpsAgent = new https.Agent(),\n        httpAgentSpy,\n        httpsAgentSpy;\n\n    before(function () {\n        httpAgentSpy = sinon.spy(httpAgent, 'createConnection');\n        httpsAgentSpy = sinon.spy(httpsAgent, 'createConnection');\n    });\n\n    after(function () {\n        httpAgentSpy.restore();\n        httpsAgentSpy.restore();\n    });\n\n    it('should accept custom requesting agents', function (done) {\n        newman.run({\n            collection: {\n                name: 'Collection',\n                item: [{\n                    request: 'http://postman-echo.com/redirect-to?url=https://httpbin.org/get'\n                }]\n            },\n            requestAgents: {\n                http: httpAgent,\n                https: httpsAgent\n            }\n        }, function (err, summary) {\n            expect(err).to.be.null;\n            expect(summary).to.be.ok;\n            expect(summary.run.failures).to.be.empty;\n\n            const httpAgentOpts = httpAgentSpy.getCall(0).args[0],\n                httpsAgentOpts = httpsAgentSpy.getCall(0).args[0],\n                response = summary.run.executions[0].response;\n\n            sinon.assert.calledOnce(httpAgentSpy);\n            sinon.assert.calledOnce(httpsAgentSpy);\n\n            expect(httpsAgentOpts).to.have.property('agent').that.be.an.instanceof(http.Agent);\n            expect(httpAgentOpts).to.have.property('host').that.equal('postman-echo.com');\n\n            expect(httpsAgentOpts).to.have.property('agent').that.be.an.instanceof(https.Agent);\n            expect(httpsAgentOpts).to.have.property('host').that.equal('httpbin.org');\n\n            expect(response.reason()).to.equal('OK');\n\n            done();\n        });\n    });\n});\n"
  },
  {
    "path": "test/library/run-options.test.js",
    "content": "const _ = require('lodash'),\n    expect = require('chai').expect,\n\n    newman = require('../../'),\n    runtimeVersion = require('../../package.json').dependencies['postman-runtime'];\n\ndescribe('Newman run options', function () {\n    var collection = 'test/fixtures/run/single-get-request.json';\n\n    it('should work correctly without any extra options', function (done) {\n        newman.run({\n            collection\n        }, done);\n    });\n\n    it('should correctly send the test name as a part of error information for failed assertions', function (done) {\n        newman\n            .run({\n                collection: 'test/fixtures/run/single-request-failing.json'\n            }, done)\n            .on('assertion', function (err) {\n                expect(err).to.be.ok;\n                expect(err).to.have.property('name', 'AssertionError');\n                expect(err).to.have.property('index', 0);\n                expect(err).to.have.property('test', 'response code is 200');\n                expect(err).to.have.property('message', 'expected false to be truthy');\n                expect(err).to.have.property('stack');\n            });\n    });\n\n    it('should not work without a collection', function (done) {\n        newman.run({\n            environment: 'test/fixtures/run/simple-variables.json'\n        }, function (err) {\n            expect(err).to.be.ok;\n            expect(err.message).to.eql('expecting a collection to run');\n            done();\n        });\n    });\n\n    it('should not work with empty options', function (done) {\n        newman.run({}, function (err) {\n            expect(err).to.be.ok;\n            expect(err.message).to.eql('expecting a collection to run');\n            done();\n        });\n    });\n\n    it('should fail a collection run with undefined test cases', function (done) {\n        newman.run({\n            collection: 'test/fixtures/run/undefined-test-checks.json'\n        }, function (err, summary) {\n            if (err) { return done(err); }\n\n            expect(summary.run.failures, 'should have 1 failure').to.have.a.lengthOf(1);\n            expect(summary.run.failures[0].error).to.have.property('name', 'AssertionError');\n\n            done();\n        });\n    });\n\n    it('should accept iterationData as an array of objects', function (done) {\n        newman.run({\n            collection: 'test/integration/steph/steph.postman_collection.json',\n            iterationData: require('../integration/steph/steph.postman_data.json')\n        }, function (err, summary) {\n            expect(err).to.not.be.ok;\n            expect(summary.run.failures).to.be.empty;\n            done();\n        });\n    });\n\n    it('should correctly handle a multitude of responses', function (done) {\n        newman.run({\n            collection: 'test/fixtures/run/response-bodies.json'\n        }, function (err, summary) {\n            expect(err).to.not.be.ok;\n            expect(summary.run.failures).to.be.empty;\n\n            var executions = summary.run.executions,\n                response = executions[0].response.json(),\n                postmanToken = _.get(response, 'headers.postman-token');\n\n            expect(executions, 'should have 3 executions').to.have.lengthOf(3);\n            expect(response).to.have.property('args')\n                .that.eql({ source: 'newman-sample-github-collection' });\n            expect(response).to.have.property('url')\n                .that.eql('https://postman-echo.com/get?source=newman-sample-github-collection');\n            expect(response).to.have.property('headers').that.include({\n                host: 'postman-echo.com',\n                accept: '*/*',\n                'cache-control': 'no-cache',\n                'postman-token': postmanToken,\n                'accept-encoding': 'gzip, br',\n                'user-agent': `PostmanRuntime/${runtimeVersion}` // change this when runtime is bumped\n            });\n            // eslint-disable-next-line max-len\n            expect(executions[1].response.text()).to.equal('<!DOCTYPE html><html><head><title>Hello World!</title></head><body><h1>Hello World!</h1></body></html>');\n            // eslint-disable-next-line max-len\n            expect(executions[2].response.text()).to.eql('<?xml version=\"1.0\" encoding=\"utf-8\"?><food><key>Homestyle Breakfast</key><value>950</value></food>');\n\n            done();\n        });\n    });\n\n    it('should correctly handle invalid collection URLs', function (done) {\n        newman.run({\n            collection: 'https://api.getpostman.com/collections/my-collection-uuid?apikey=my-secret-api-key'\n        }, function (err, summary) {\n            expect(err).to.be.ok;\n            expect(err.message).to.equal('collection could not be loaded\\n' +\n                '  Error fetching the collection from the provided URL. Ensure that the URL is valid.\\n' +\n                '  Invalid API Key. Every request requires a valid API Key to be sent.');\n            expect(summary).to.not.be.ok;\n\n            done();\n        });\n    });\n\n    it('should correctly handle invalid iteration data', function (done) {\n        newman.run({\n            collection: 'test/fixtures/run/failed-request.json',\n            iterationData: 3.14\n        }, function (err, summary) {\n            expect(err).to.be.ok;\n            expect(err.message).to.include('iteration data could not be loaded\\n' +\n                '  ENOENT: no such file or directory, open \\'');\n            expect(summary).to.not.be.ok;\n\n            done();\n        });\n    });\n\n    describe('bail modifiers', function () {\n        it('should skip collection run in case of error when folder is specified', function (done) {\n            newman.run({\n                collection: 'test/fixtures/run/failed-request.json',\n                bail: ['folder']\n            }, function (err) {\n                expect(err).to.be.ok;\n                expect(err.message).to.include('getaddrinfo ENOTFOUND 123.random.z');\n\n                done();\n            });\n        });\n\n        it('should gracefully stop a collection run in case of error with no additional modifiers', function (done) {\n            newman.run({\n                collection: 'test/fixtures/run/failed-request.json',\n                bail: true\n            }, function (err) {\n                expect(err).to.not.be.ok;\n\n                done();\n            });\n        });\n\n        it('should skip collection run in case of error when both folder and failure are specified', function (done) {\n            newman.run({\n                collection: 'test/fixtures/run/failed-request.json',\n                folder: 'invalidName',\n                bail: ['folder', 'failure']\n            }, function (err) {\n                expect(err).to.be.ok;\n                expect(err.message)\n                    .to.equal('runtime~extractRunnableItems: Unable to find a folder or request: \"invalidName\"');\n\n                done();\n            });\n        });\n    });\n\n    // @todo: failing on windows\n    (process.platform.startsWith('win') ? describe.skip : describe)('script timeouts', function () {\n        // @todo: failing since Node.js v20.10.0\n        it.skip('should be handled correctly when breached', function (done) {\n            newman.run({\n                collection: 'test/integration/timeout/timeout.postman_collection.json',\n                timeoutScript: 5\n            }, function (err, summary) {\n                expect(err.message).to.equal('Script execution timed out after 5ms');\n                expect(summary).to.be.ok;\n                done();\n            });\n        });\n\n        it('should be handled correctly when not breached', function (done) {\n            newman.run({\n                collection: 'test/integration/timeout/timeout.postman_collection.json',\n                timeoutScript: 500\n            }, function (err, summary) {\n                expect(err).to.be.null;\n                expect(summary).to.be.ok;\n                done();\n            });\n        });\n    });\n\n    describe('request timeouts', function () {\n        it('should be handled correctly when breached', function (done) {\n            newman.run({\n                collection: 'test/integration/timeout/timeout.postman_collection.json',\n                timeoutRequest: 10\n            }, function (err, summary) {\n                expect(err).to.be.null;\n                expect(summary.run.failures).to.be.an('array').that.has.lengthOf(1);\n                expect(summary.run.failures[0].error.message).to.equal('ESOCKETTIMEDOUT');\n                done();\n            });\n        });\n\n        it('should be handled correctly when not breached', function (done) {\n            newman.run({\n                collection: 'test/integration/timeout/timeout.postman_collection.json',\n                timeoutRequest: 5000\n            }, function (err, summary) {\n                expect(err).to.be.null;\n                expect(summary).to.be.ok;\n                done();\n            });\n        });\n    });\n\n    describe('global timeouts', function () {\n        it('should be handled correctly when breached', function (done) {\n            newman.run({\n                collection: 'test/integration/timeout/timeout.postman_collection.json',\n                timeout: 1000\n            }, function (err, summary) {\n                expect(err.message).to.equal('callback timed out');\n                expect(summary).to.be.ok;\n                done();\n            });\n        });\n\n        it('should be handled correctly when not breached', function (done) {\n            newman.run({\n                collection: 'test/integration/timeout/timeout.postman_collection.json',\n                timeout: 10000\n            }, function (err, summary) {\n                expect(err).to.be.null;\n                expect(summary).to.be.ok;\n                done();\n            });\n        });\n    });\n});\n"
  },
  {
    "path": "test/library/shallow-junit-reporter.test.js",
    "content": "const fs = require('fs'),\n\n    _ = require('lodash'),\n    sh = require('shelljs'),\n    parseXml = require('xml2js').parseString,\n    expect = require('chai').expect,\n\n    newman = require('../../');\n\ndescribe('JUnit reporter', function () {\n    var outDir = 'out',\n        outFile = outDir + '/newman-report.xml';\n\n    beforeEach(function () {\n        sh.test('-d', outDir) && sh.rm('-rf', outDir);\n        sh.mkdir('-p', outDir);\n    });\n\n    afterEach(function () {\n        sh.rm('-rf', outDir);\n    });\n\n    it('should correctly generate the JUnit report for a successful run', function (done) {\n        newman.run({\n            collection: 'test/fixtures/run/single-get-request.json',\n            reporters: ['junit'],\n            reporter: { junit: { export: outFile } }\n        }, function (err) {\n            if (err) { return done(err); }\n\n            fs.readFile(outFile, function (err, data) {\n                expect(err).to.not.be.ok;\n\n                parseXml(data, function (error, result) {\n                    expect(error).to.not.be.ok;\n\n                    var testcase,\n                        suite = _.get(result.testsuites, 'testsuite.0');\n\n                    expect(result.testsuites.$).to.not.be.empty;\n                    expect(result.testsuites.$.time).to.match(/^\\d+\\.\\d{3}$/);\n\n                    expect(suite).to.not.be.empty;\n                    expect(suite.$).to.not.be.empty;\n                    expect(suite.$.time).to.match(/^\\d+\\.\\d{3}$/);\n\n                    testcase = suite.testcase[0];\n                    expect(testcase).to.not.be.empty;\n\n                    expect(testcase.$).to.have.property('classname', 'ASimpleGetRequest');\n\n                    expect(suite.$).to.have.property('tests', '1');\n                    expect(suite.$).to.have.property('failures', '0');\n                    expect(suite.$).to.have.property('errors', '0');\n\n                    done();\n                });\n            });\n        });\n    });\n\n    it('should correctly generate the JUnit report for a failed run', function (done) {\n        newman.run({\n            collection: 'test/fixtures/run/single-request-failing.json',\n            reporters: ['junit'],\n            reporter: { junit: { export: outFile } }\n        }, function (err, summary) {\n            expect(err).to.be.null;\n            expect(summary.run.failures, 'should have 1 failure').to.have.lengthOf(1);\n            fs.readFile(outFile, function (err, data) {\n                expect(err).to.not.be.ok;\n\n                parseXml(data, function (error, result) {\n                    expect(error).to.not.be.ok;\n\n                    var testcase,\n                        suite = _.get(result.testsuites, 'testsuite.0');\n\n                    expect(result.testsuites.$).to.not.be.empty;\n                    expect(result.testsuites.$.time).to.match(/^\\d+\\.\\d{3}$/);\n\n                    expect(suite).to.not.be.empty;\n                    expect(suite.$).to.not.be.empty;\n                    expect(suite.$.time).to.match(/^\\d+\\.\\d{3}$/);\n                    expect(suite.testcase).to.not.be.empty;\n\n                    expect(suite.$).to.have.property('tests', '1');\n                    expect(suite.$).to.have.property('failures', '1');\n                    expect(suite.$).to.have.property('errors', '0');\n\n                    testcase = suite.testcase[0];\n                    expect(testcase).to.not.be.empty;\n\n                    expect(testcase.$).to.have.property('classname', 'StatusCodeTest');\n                    expect(testcase.$.time).to.match(/^\\d+\\.\\d{3}$/);\n                    expect(testcase.failure).to.not.be.empty;\n                    expect(testcase.failure[0]._).to.not.be.empty;\n                    expect(testcase.failure[0].$).to.have.property('type', 'AssertionFailure');\n\n                    expect(testcase.failure).to.not.be.empty;\n                    done();\n                });\n            });\n        });\n    });\n\n    it('should correctly produce the JUnit report for a run with AssertionError/TypeError', function (done) {\n        newman.run({\n            collection: 'test/fixtures/run/newman-report-test.json',\n            reporters: ['junit'],\n            reporter: { junit: { export: outFile } }\n        }, function (err, summary) {\n            expect(err).to.be.null;\n            expect(summary.run.failures, 'should have 2 failures').to.have.lengthOf(2);\n            fs.readFile(outFile, function (err, data) {\n                expect(err).to.not.be.ok;\n\n                parseXml(data, function (error, result) {\n                    expect(error).to.not.be.ok;\n\n                    var testcase,\n                        suite = _.get(result.testsuites, 'testsuite.0');\n\n                    expect(result.testsuites.$).to.not.be.empty;\n                    expect(result.testsuites.$.time).to.match(/^\\d+\\.\\d{3}$/);\n\n                    expect(suite).to.not.be.empty;\n                    expect(suite.$).to.not.be.empty;\n                    expect(suite.$.time).to.match(/^\\d+\\.\\d{3}$/);\n                    expect(suite.testcase).to.not.be.empty;\n                    expect(suite['system-err']).to.not.be.empty;\n\n                    expect(suite.$).to.have.property('tests', '2');\n                    expect(suite.$).to.have.property('failures', '1');\n                    expect(suite.$).to.have.property('errors', '1');\n\n                    testcase = suite.testcase[0];\n                    expect(testcase).to.not.be.empty;\n\n                    expect(testcase.$).to.have.property('classname', 'FailedRequest');\n                    expect(testcase.$.time).to.match(/^\\d+\\.\\d{3}$/);\n                    expect(testcase.failure).to.not.be.empty;\n                    expect(testcase.failure[0]._).to.not.be.empty;\n                    expect(testcase.failure[0].$).to.have.property('type', 'AssertionFailure');\n\n                    done();\n                });\n            });\n        });\n    });\n\n    it('should correctly produce the JUnit report in a pre-existing directory', function (done) {\n        newman.run({\n            collection: 'test/fixtures/run/single-get-request.json',\n            reporters: ['junit'],\n            reporter: { junit: { export: outDir } }\n        }, function (err) {\n            expect(err).to.be.null;\n\n            var dir = fs.readdirSync(outDir),\n                file = dir[0];\n\n            expect(dir).to.have.length(1);\n            fs.stat(outDir + '/' + file, done);\n        });\n    });\n});\n"
  },
  {
    "path": "test/library/ssl-client-cert.test.js",
    "content": "const fs = require('fs'),\n    async = require('async'),\n    expect = require('chai').expect,\n    https = require('https'),\n\n    newman = require('../../');\n\ndescribe('SSL Client certificates', function () {\n    var server1, server2, server3;\n\n    function createHttpsServerWithCerts (certs) {\n        return https.createServer({\n            key: fs.readFileSync(certs.key, 'utf8'),\n            cert: fs.readFileSync(certs.cert, 'utf8'),\n            ca: fs.readFileSync(certs.ca, 'utf8'),\n            passphrase: 'password',\n            requestCert: true,\n            rejectUnauthorized: false\n        }, function (req, res) {\n            if (req.client.authorized) {\n                res.writeHead(200, { 'Content-Type': 'text/plain' });\n                res.end('authorized\\n');\n            }\n            else {\n                res.writeHead(401, { 'Content-Type': 'text/plain' });\n                res.end('unauthorized\\n');\n            }\n        });\n    }\n\n    before(function (done) {\n        server1 = createHttpsServerWithCerts({\n            key: 'test/fixtures/ssl/server.key',\n            cert: 'test/fixtures/ssl/server.crt',\n            ca: 'test/fixtures/ssl/ca.crt'\n        });\n\n        server2 = createHttpsServerWithCerts({\n            key: 'test/fixtures/ssl/server2.key',\n            cert: 'test/fixtures/ssl/server2.crt',\n            ca: 'test/fixtures/ssl/ca2.crt'\n        });\n\n        server3 = createHttpsServerWithCerts({\n            key: 'test/fixtures/ssl/server3.key',\n            cert: 'test/fixtures/ssl/server3.crt',\n            ca: 'test/fixtures/ssl/ca3.crt'\n        });\n\n        async.parallel([\n            function (cb) {\n                server1.listen(3000, cb);\n            },\n            function (cb) {\n                server2.listen(3001, cb);\n            },\n            function (cb) {\n                server3.listen(3002, cb);\n            }\n        ], function (err) {\n            done(err);\n        });\n    });\n\n    after(function (done) {\n        async.parallel([\n            function (cb) {\n                server1.close(cb);\n            },\n            function (cb) {\n                server2.close(cb);\n            },\n            function (cb) {\n                server3.close(cb);\n            }\n        ], function (err) {\n            done(err);\n        });\n    });\n\n    // @todo: add .pfx, .pem tests as well\n    it('should work correctly with standalone client certificates', function (done) {\n        newman.run({\n            collection: 'test/fixtures/run/ssl-client-cert.json',\n            sslClientCert: 'test/fixtures/ssl/client.crt',\n            sslClientKey: 'test/fixtures/ssl/client.key',\n            sslClientPassphrase: 'password',\n            insecure: true\n        }, done);\n    });\n\n    it('should work correctly with multiple client certificates', function (done) {\n        newman.run({\n            collection: 'test/fixtures/run/ssl-client-cert-list.json',\n            sslClientCertList: 'test/fixtures/files/ssl-client-cert-config.json',\n            insecure: true\n        }, done);\n    });\n\n    it('should give precedence to client cert list when both client cert options present', function (done) {\n        newman.run({\n            collection: 'test/fixtures/run/ssl-client-cert-list.json',\n            sslClientCertList: 'test/fixtures/files/ssl-client-cert-config.json',\n            sslClientCert: 'test/fixtures/ssl/client.crt',\n            sslClientKey: 'test/fixtures/ssl/client.key',\n            sslClientPassphrase: 'password',\n            insecure: true\n        }, done);\n    });\n\n    it('should fallback to individual client cert when multiple client cert don\\'t match', function (done) {\n        newman.run({\n            collection: 'test/fixtures/run/ssl-client-cert.json',\n            sslClientCertList: 'test/fixtures/files/ssl-client-cert-config.json',\n            sslClientCert: 'test/fixtures/ssl/client.crt',\n            sslClientKey: 'test/fixtures/ssl/client.key',\n            sslClientPassphrase: 'password',\n            insecure: true\n        }, done);\n    });\n\n    it('should bail out if client certificate list file does not exist', function (done) {\n        newman.run({\n            collection: 'test/fixtures/run/ssl-client-cert-list.json',\n            sslClientCertList: 'invalid-cert-file.json', // using an invalid cert list\n            insecure: true\n        }, function (err) {\n            expect(err).to.exist;\n            expect(err.message)\n                .to.equal('unable to read the ssl client certificates file \"invalid-cert-file.json\"');\n            done();\n        });\n    });\n\n    it('should bail out if unable to parse client certificate list', function (done) {\n        newman.run({\n            collection: 'test/fixtures/run/ssl-client-cert-list.json',\n            sslClientCertList: './ssl-client-cert-test.js', // using an invalid cert list\n            insecure: true\n        }, function (err) {\n            expect(err).to.exist;\n            expect(err.message)\n                .to.equal('unable to read the ssl client certificates file \"./ssl-client-cert-test.js\"');\n            done();\n        });\n    });\n\n    it('should bail out if client certificate list is not array', function (done) {\n        newman.run({\n            collection: 'test/fixtures/run/ssl-client-cert-list.json',\n            sslClientCertList: 'test/fixtures/run/ssl-client-cert.json', // using an invalid cert list\n            insecure: true\n        }, function (err) {\n            expect(err).to.exist;\n            expect(err.message).to.equal('expected ssl client certificates list to be an array.');\n            done();\n        });\n    });\n\n    it('should use list if list is an array', function (done) {\n        newman.run({\n            collection: 'test/fixtures/run/ssl-client-cert-list.json',\n            sslClientCertList: [{\n                name: 'client1',\n                matches: ['https://localhost:3001', 'https://localhost:3001/*'],\n                key: { src: './test/fixtures/ssl/client2.key' },\n                cert: { src: './test/fixtures/ssl/client2.crt' },\n                passphrase: 'password'\n            }],\n            insecure: true\n        }, done);\n    });\n\n    it('should bail if client certificate list file path is invalid', function (done) {\n        newman.run({\n            collection: 'test/fixtures/run/ssl-client-cert-list.json',\n            sslClientCertList: {},\n            insecure: true\n        }, function (err) {\n            expect(err).to.exist;\n            expect(err.message).to.equal('path for ssl client certificates list file must be a string');\n            done();\n        });\n    });\n});\n"
  },
  {
    "path": "test/library/suppress-exit-code.test.js",
    "content": "const expect = require('chai').expect,\n    newman = require('../../');\n\ndescribe('newman.run suppressExitCode', function () {\n    it('should accept the suppressExitCode parameter', function (done) {\n        newman.run({\n            collection: 'test/fixtures/run/single-get-request.json',\n            suppressExitCode: true\n        }, done);\n    });\n\n    it('should fail if suppressExitCode parameter is absent on a failing collection', function (done) {\n        newman.run({\n            collection: 'test/fixtures/run/single-request-failing.json'\n        }, function (err, summary) {\n            expect(err).to.be.null;\n            expect(summary.run.failures, 'should have 1 failure').to.have.lengthOf(1);\n            done();\n        });\n    });\n\n    it('should not fail if suppressExitCode parameter is present on a failing collection', function (done) {\n        newman.run({\n            collection: 'test/fixtures/run/single-request-failing.json',\n            suppressExitCode: true\n        }, done);\n    });\n});\n"
  },
  {
    "path": "test/library/working-directory.test.js",
    "content": "const path = require('path'),\n    expect = require('chai').expect,\n\n    newman = require('../../'),\n    workingDir = path.resolve(__dirname, '../fixtures/files/work-dir');\n\ndescribe('newman.run workingDir', function () {\n    it('should resolve file present inside working directory', function (done) {\n        newman.run({\n            collection: 'test/fixtures/run/single-file-inside.json',\n            workingDir: workingDir\n        }, function (err, summary) {\n            expect(err).to.be.null;\n            expect(summary.run.stats.iterations.total, 'should have 1 iteration').to.equal(1);\n            expect(summary.run.stats.assertions.total, 'should have 2 assertions').to.equal(2);\n            expect(summary.run.stats.assertions.failed, 'should not have failing tests').to.equal(0);\n            expect(summary.run.executions, 'should have 2 executions').to.have.lengthOf(2);\n            done();\n        });\n    });\n\n    it('should not resolve file present outside working directory with insecureFileRead=false', function (done) {\n        newman.run({\n            collection: 'test/fixtures/run/single-file-outside.json',\n            workingDir: workingDir,\n            insecureFileRead: false\n        }, function (err, summary) {\n            expect(err).to.be.null;\n            expect(summary.run.stats.iterations.total, 'should have 1 iteration').to.equal(1);\n            expect(summary.run.stats.assertions.total, 'should have 2 assertions').to.equal(2);\n            expect(summary.run.stats.assertions.failed, 'should not 2 failing tests').to.equal(2);\n            expect(summary.run.executions, 'should have 2 executions').to.have.lengthOf(2);\n            done();\n        });\n    });\n\n    it('should resolve file present outside working directory by default', function (done) {\n        newman.run({\n            collection: 'test/fixtures/run/single-file-outside.json',\n            workingDir: workingDir\n        }, function (err, summary) {\n            expect(err).to.be.null;\n            expect(summary.run.stats.iterations.total, 'should have 1 iteration').to.equal(1);\n            expect(summary.run.stats.assertions.total, 'should have 2 assertions').to.equal(2);\n            expect(summary.run.stats.assertions.failed, 'should not have failing tests').to.equal(0);\n            expect(summary.run.executions, 'should have 2 executions').to.have.lengthOf(2);\n            done();\n        });\n    });\n});\n"
  },
  {
    "path": "test/system/dockerfile_rules.yml",
    "content": "---\n  profile:\n    name: \"Default\"\n    description: \"Default Profile. Checks basic syntax.\"\n  general:\n    ref_url_base: \"https://docs.docker.com/reference/builder/\"\n    valid_instructions:\n      - \"FROM\"\n      - \"MAINTAINER\"\n      - \"RUN\"\n      - \"CMD\"\n      - \"EXPOSE\"\n      - \"ENV\"\n      - \"ADD\"\n      - \"COPY\"\n      - \"ENTRYPOINT\"\n      - \"VOLUME\"\n      - \"USER\"\n      - \"WORKDIR\"\n      - \"ONBUILD\"\n    instruction_regex: /(\\\\w+)\\\\s(.+$)/\n    valid_instruction_regex: /^(CMD|FROM|MAINTAINER|RUN|EXPOSE|ENV|ADD|COPY|ENTRYPOINT|VOLUME|USER|WORKDIR|ONBUILD)(\\s)?/i\n    ignore_regex: /^#/\n    multiline_regex: /\\\\$/\n  line_rules:\n    FROM:\n      paramSyntaxRegex: /^[a-z0-9./-]+(:[a-z0-9.-]+)?$/\n      rules:\n        -\n          label: \"is_latest_tag\"\n          regex: /latest/\n          level: \"info\"\n          message: \"base image uses 'latest' tag\"\n          description: \"using the 'latest' tag may cause unpredictable builds. It is recommended that a specific tag is used in the FROM line.\"\n          reference_url:\n            - \"https://docs.docker.com/reference/builder/\"\n            - \"#from\"\n        -\n          label: \"no_tag\"\n          regex: /^[:]/\n          level: \"warn\"\n          message: \"No tag is used\"\n          description: \"lorem ipsum tar\"\n          reference_url:\n            - \"https://docs.docker.com/reference/builder/\"\n            - \"#from\"\n    RUN:\n      paramSyntaxRegex: /.+/\n      rules:\n        -\n          label: \"no_yum_clean_all\"\n          regex: /yum ((?!clean all).)* .+/\n          level: \"warn\"\n          message: \"yum clean all is not used\"\n          description: \"the yum cache will remain in this layer making the layer unnecessarily large\"\n          reference_url: \"None\"\n        -\n          label: \"installing_ssh\"\n          regex: /ssh/\n          level: \"warn\"\n          message: \"installing SSH in a container is not recommended\"\n          description: \"Do you really need SSH in this image?\"\n          reference_url: \"https://github.com/jpetazzo/nsenter\"\n    CMD:\n      paramSyntaxRegex: /.+/\n      rules: []\n    EXPOSE:\n      paramSyntaxRegex: /^[0-9]+([0-9\\s]+)?$/\n      rules: []\n    ENV:\n      paramSyntaxRegex: /^(\\s?[a-zA-Z_]+[a-zA-Z0-9_]*=?.+)+$/\n      rules: []\n    ADD:\n      paramSyntaxRegex: /^(~?[A-z0-9\\/_.-]+|https?:\\/\\/(www\\.)?[-a-zA-Z0-9@:%._\\+~#=]{2,256}\\.[a-z]{2,6}\\b([-a-zA-Z0-9@$:%_\\+.~#?&\\/\\/=]*))\\s~?[A-z0-9\\/_.-]+$/\n    COPY:\n      paramSyntaxRegex: /.+/\n      rules: []\n    ENTRYPOINT:\n      paramSyntaxRegex: /.+/\n      rules: []\n    VOLUME:\n      paramSyntaxRegex: /^~?([A-z0-9\\/_.-]+|\\[\"[A-z0-9\\/_.-]+\"\\])$/\n      rules: []\n    USER:\n      paramSyntaxRegex: /^[a-z_][a-z0-9_]{0,30}$/\n      rules: []\n    WORKDIR:\n      paramSyntaxRegex: /^~?[A-z0-9\\/_.-]+$/\n      rules: []\n    ONBUILD:\n      paramSyntaxRegex: /.+/\n      rules: []\n  required_instructions:\n    -\n      instruction: \"MAINTAINER\"\n      count: 1\n      level: \"info\"\n      message: \"Maintainer is not defined\"\n      description: \"The MAINTAINER line is useful for identifying the author in the form of MAINTAINER Joe Smith <joe.smith@example.com>\"\n      reference_url:\n        - \"https://docs.docker.com/reference/builder/\"\n        - \"#maintainer\"\n    -\n      instruction: \"ENTRYPOINT\"\n      count: 1\n      level: \"info\"\n      message: \"There is no 'ENTRYPOINT' instruction\"\n      description: \"None\"\n      reference_url:\n        - \"https://docs.docker.com/reference/builder/\"\n        - \"#entrypoint\"\n"
  },
  {
    "path": "test/system/dockerfiles.test.js",
    "content": "/**\n * @fileoverview This test suite runs tests on the various versions of newman-docker.\n */\n\nconst fs = require('fs'),\n    path = require('path'),\n    expect = require('chai').expect,\n    DockerFileValidator = require('dockerfile_lint');\n\ndescribe('Validate Dockerfiles', function () {\n    const imagesBaseDirectory = path.join(__dirname, '../../docker/images'),\n        images = fs.readdirSync(imagesBaseDirectory).filter(function (item) {\n            return fs.statSync(path.join(imagesBaseDirectory, item)).isDirectory();\n        }),\n        validator = new DockerFileValidator(path.join(__dirname, 'dockerfile_rules.yml'));\n\n    images.forEach(function (version) {\n        const dockerFilePath = path.join(imagesBaseDirectory, version, 'Dockerfile'),\n            dockerFileContent = fs.readFileSync(dockerFilePath);\n\n        it('should have valid Docker file for \"' + version + '\"', function () {\n            const result = validator.validate(dockerFileContent.toString()),\n                faults = result.error.count + result.warn.count;\n\n            faults && console.error(JSON.stringify(result, null, 4)); // Helps debugging on the CI\n            expect(faults, `there are ${faults} error(s)`).to.equal(0);\n        });\n    });\n});\n"
  },
  {
    "path": "test/system/editorconfig.test.js",
    "content": "/**\n * @fileOverview Ensures that editorconfig settings are appropriate\n */\n\nconst editorconfig = require('editorconfig'),\n    expect = require('chai').expect,\n\n    /**\n     * The width (in spaces) of tabs used for indentation throughout the project\n     *\n     * @type {Number}\n     */\n    TAB_WIDTH = 4;\n\ndescribe('.editorconfig', function () {\n    const config = editorconfig.parseSync('.editorconfig'); // eslint-disable-line no-sync\n\n    it('should have a tab_width of 4', function () {\n        expect(config.tab_width).to.equal(TAB_WIDTH);\n    });\n\n    it('should have a charset of utf-8', function () {\n        expect(config.charset).to.equal('utf-8');\n    });\n\n    it('should have an indent_size of 4', function () {\n        expect(config.indent_size).to.equal(TAB_WIDTH);\n    });\n\n    it('should have an indent_style of 4', function () {\n        expect(config.indent_style).to.equal('space');\n    });\n\n    it('should have a truthy insert_final_newline value', function () {\n        expect(config.insert_final_newline).to.equal(true);\n    });\n\n    it('should have a truthy trim_trailing_whitespace', function () {\n        expect(config.trim_trailing_whitespace).to.equal(true);\n    });\n});\n"
  },
  {
    "path": "test/system/npm-publish.test.js",
    "content": "const expect = require('chai').expect,\n    // eslint-disable-next-line security/detect-child-process\n    exec = require('child_process').execSync;\n\ndescribe('npm publish', function () {\n    const stdout = exec('npm pack --dry-run --json').toString(),\n        packageInfo = JSON.parse(stdout.substring(stdout.indexOf('[')))[0],\n        packagedFiles = packageInfo.files.map(function (file) { return file.path; });\n\n    it('should have a valid package name', function () {\n        expect(packageInfo.name).to.equal('newman');\n    });\n\n    it('should not publish unnecessary files', function () {\n        const allowedFiles = ['index.js', 'package.json', 'LICENSE.md',\n            'README.md', 'CHANGELOG.yaml', 'MIGRATION.md', 'SECURITY.md'];\n\n        packagedFiles.forEach(function (path) {\n            expect(allowedFiles.includes(path) || path.startsWith('lib/') ||\n            path.startsWith('bin/') || path.startsWith('docker/')).to.be.true;\n        });\n    });\n});\n"
  },
  {
    "path": "test/system/repository.test.js",
    "content": "/**\n * @fileOverview This test specs runs tests on the package.json file of repository. It has a set of strict tests on the\n * content of the file as well. Any change to package.json must be accompanied by valid test case in this spec-sheet.\n */\nconst fs = require('fs'),\n    _ = require('lodash'),\n    yml = require('js-yaml'),\n    semver = require('semver'),\n    expect = require('chai').expect,\n    parseIgnore = require('parse-gitignore');\n\ndescribe('project repository', function () {\n    describe('package.json', function () {\n        let content,\n            json;\n\n        try {\n            content = fs.readFileSync('./package.json').toString();\n            json = JSON.parse(content);\n        }\n        catch (e) {\n            console.error(e);\n            content = '';\n            json = {};\n        }\n\n        it('should have readable JSON content', function () {\n            expect(content).to.be.ok;\n            expect(json).to.not.eql({});\n        });\n\n        describe('package.json JSON data', function () {\n            it('should have valid name, description and author', function () {\n                expect(json).to.have.property('name', 'newman');\n                expect(json).to.have.property('description', 'Command-line companion utility for Postman');\n                expect(json).to.have.property('author', 'Postman Labs <help@postman.com> (=)');\n                expect(json).to.have.property('license', 'Apache-2.0');\n                expect(json).to.have.property('homepage', 'https://github.com/postmanlabs/newman');\n                expect(json).to.have.property('bugs', 'https://github.com/postmanlabs/newman/issues');\n\n                expect(json).to.have.property('repository');\n                expect(json.repository).to.eql({\n                    type: 'git',\n                    url: 'git://github.com/postmanlabs/newman.git'\n                });\n\n                expect(json).to.have.property('keywords');\n                expect(json.keywords).to.eql(['newman', 'postman', 'api', 'testing', 'ci', 'rest-client', 'rest']);\n\n                expect(json).to.have.property('engines');\n                expect(json.engines).to.eql({ node: '>=16' });\n            });\n\n            it('should have a valid version string in form of <major>.<minor>.<revision>', function () {\n                expect(semver.valid(json.version), `version:${json.version} should be a valid semver`).to.not.be.null;\n            });\n        });\n\n        describe('binary definitions', function () {\n            it('should exist', function () {\n                expect(json.bin).be.ok;\n                expect(json.bin).to.eql({ newman: './bin/newman.js' });\n            });\n\n            it('should have valid node shebang', function () {\n                json.bin && Object.keys(json.bin).forEach(function (scriptName) {\n                    const fileContent = fs.readFileSync(json.bin[scriptName]).toString();\n\n                    expect((/^#!\\/(bin\\/bash|usr\\/bin\\/env\\snode)[\\r\\n][\\W\\w]*$/g).test(fileContent),\n                        `invalid or missing shebang in ${json.bin[scriptName]}`).to.be.ok;\n                });\n            });\n        });\n\n        describe('dependencies', function () {\n            it('should exist', function () {\n                expect(json.dependencies).to.be.an('object');\n            });\n\n            it('should point to a valid and precise (no * or ^) semver', function () {\n                json.dependencies && Object.keys(json.dependencies).forEach(function (item) {\n                    expect(semver.valid(json.dependencies[item]),\n                        `${item}:${json.dependencies[item]} should be a valid semver`).to.not.be.null;\n                });\n            });\n        });\n\n        describe('devDependencies', function () {\n            it('should exist', function () {\n                expect(json.devDependencies).to.be.an('object');\n            });\n\n            it('should not overlap devDependencies', function () {\n                const clean = [];\n\n                json.devDependencies && Object.keys(json.devDependencies).forEach(function (item) {\n                    !json.dependencies[item] && clean.push(item);\n                });\n\n                expect(Object.keys(json.devDependencies)).to.eql(clean);\n            });\n        });\n\n        describe('main entry script', function () {\n            it('should point to a valid file', function (done) {\n                expect(json.main).to.equal('index.js');\n                fs.stat(json.main, done);\n            });\n        });\n    });\n\n    describe('README.md', function () {\n        it('should exist', function (done) {\n            fs.stat('./README.md', done);\n        });\n\n        it('should have readable content', function () {\n            expect(fs.readFileSync('./README.md').toString()).to.be.ok;\n        });\n    });\n\n    describe('LICENSE.md', function () {\n        it('should exist', function (done) {\n            fs.stat('./LICENSE.md', done);\n        });\n\n        it('should have readable content', function () {\n            expect(fs.readFileSync('./LICENSE.md').toString()).to.be.ok;\n        });\n    });\n\n    describe('.ignore files', function () {\n        const gitignorePath = '.gitignore',\n            npmignorePath = '.npmignore',\n            npmignore = parseIgnore(fs.readFileSync(npmignorePath)).patterns,\n            gitignore = parseIgnore(fs.readFileSync(gitignorePath)).patterns;\n\n        describe(gitignorePath, function () {\n            it('should exist', function (done) {\n                fs.stat(gitignorePath, done);\n            });\n\n            it('should have valid content', function () {\n                expect(gitignore).to.not.be.empty;\n            });\n        });\n\n        describe(npmignorePath, function () {\n            it('should exist', function (done) {\n                fs.stat(npmignorePath, done);\n            });\n\n            it('should have valid content', function () {\n                expect(npmignore).to.not.be.empty;\n            });\n        });\n\n        it('should have .gitignore coverage to be a subset of .npmignore coverage', function () {\n            expect(_.intersection(gitignore, npmignore)).to.eql(gitignore);\n        });\n    });\n\n    describe('.eslintrc', function () {\n        it('should exist', function (done) {\n            fs.stat('./.eslintrc', done);\n        });\n\n        it('should have readable content', function () {\n            expect(fs.readFileSync('./.eslintrc').toString()).to.be.ok;\n        });\n    });\n\n    describe('.gitattributes', function () {\n        it('should exist', function (done) {\n            fs.stat('./.gitattributes', done);\n        });\n\n        it('should have readable content', function () {\n            expect(fs.readFileSync('./.gitattributes').toString()).to.be.ok;\n        });\n    });\n\n    describe('CHANGELOG.yaml', function () {\n        it('should exist', function (done) {\n            fs.stat('./CHANGELOG.yaml', done);\n        });\n\n        it('should have readable content', function () {\n            expect(yml.load(fs.readFileSync('./CHANGELOG.yaml')), 'not a valid yaml').to.be.ok;\n        });\n    });\n});\n"
  },
  {
    "path": "test/unit/cli-reporter-symbols.test.js",
    "content": "const _ = require('lodash'),\n    expect = require('chai').expect,\n\n    isDoubleByte = function (str) {\n        for (var i = 0, n = str.length; i < n; i++) {\n            if (str.charCodeAt(i) > 255) { return true; }\n        }\n\n        return false;\n    };\n\n/* eslint-disable */\n/**\n * @attribution https://github.com/lodash/lodash/issues/2240#issuecomment-418820848\n */\nconst flattenKeys = (obj, path = []) =>\n    !_.isObject(obj)\n        ? { [path.join('.')]: obj }\n        : _.reduce(obj, (cum, next, key) => _.merge(cum, flattenKeys(next, [...path, key])), {});\n/* eslint-enable */\n\ndescribe('unicode handling of cli symbol utility module', function () {\n    let cliUtilsSymbols = require('../../lib/reporters/cli/cli-utils-symbols.js');\n\n    it('should have three symbol classes', function () {\n        expect(cliUtilsSymbols(true)).to.be.an('object');\n        expect(cliUtilsSymbols(false)).to.be.an('object');\n    });\n\n    it('should have appropriate fallback for unicode', function () {\n        let symbol = cliUtilsSymbols(true),\n            fallback = cliUtilsSymbols(false),\n\n            flattenedSymbols = flattenKeys(symbol),\n            flattenedPlainSymbols = flattenKeys(fallback);\n\n        expect(flattenedSymbols).to.contain.keys(flattenedPlainSymbols);\n    });\n\n    it('should not have unicode when not requested', function () {\n        let fallbackSymbols = cliUtilsSymbols(true),\n            flattenedPlainSymbols = flattenKeys(fallbackSymbols);\n\n        // first compute all double byte checking\n        for (const [key, value] of Object.entries(flattenedPlainSymbols)) {\n            // @todo make the assertion better so that failure here says what exactly went wrong\n            expect(isDoubleByte(value)).to.eql(false, key);\n        }\n    });\n});\n"
  },
  {
    "path": "test/unit/cli.test.js",
    "content": "const _ = require('lodash'),\n    sinon = require('sinon'),\n    expect = require('chai').expect,\n\n    newman = require('../../');\n\ndescribe('cli parser', function () {\n    let newmanCLI,\n\n        /**\n         * Wrap newmanCLI callback to extract options passed to sinon `newman` stub.\n         *\n         * @param {String[]} argv - Argument vector.\n         * @param {String} command - Newman command name, used for `sinon` result lookup.\n         * @param {Function} callback - The callback function invoked on the completion of commander parsing.\n         */\n        cli = (argv, command, callback) => {\n            newmanCLI(argv, (err) => {\n                callback(err, _.get(newman, [command, 'lastCall', 'returnValue']));\n            });\n        };\n\n    beforeEach(function () {\n        // delete require cache to use program instance for consecutive runs.\n        delete require.cache[require.resolve('../../bin/newman')];\n        newmanCLI = require('../../bin/newman');\n    });\n\n    describe('Run Command', function () {\n        // stub `newman.run`, directly return options passed to `newman.run` in newmanCLI.\n        before(function () {\n            sinon.stub(newman, 'run').callsFake((options) => {\n                return options;\n            });\n        });\n\n        // restore original `newman.run` function.\n        after(function () {\n            newman.run.restore();\n        });\n\n        it('should pass default options correctly', function (done) {\n            cli('node newman.js run collection.json'.split(' '), 'run',\n                function (err, opts) {\n                    expect(err).to.be.null;\n\n                    // explicitly match object to track addition/deletion of properties.\n                    expect(opts).to.eql({\n                        collection: 'collection.json',\n                        reporters: ['cli'],\n                        delayRequest: 0,\n                        globalVar: [],\n                        envVar: [],\n                        folder: [],\n                        insecureFileRead: true,\n                        color: 'auto',\n                        timeout: 0,\n                        timeoutRequest: 0,\n                        timeoutScript: 0,\n                        reporterOptions: {},\n                        reporter: { cli: {} }\n                    });\n\n                    done();\n                });\n        });\n\n        it('should handle standard run command (run collection.json and -e)', function (done) {\n            cli('node newman.js run myCollection.json --environment env.json -n 2'.split(' '), 'run',\n                function (err, opts) {\n                    expect(err).to.be.null;\n                    expect(opts).to.be.ok;\n                    expect(opts.iterationCount, 'should have iterationCount of 2').to.equal(2);\n                    expect(opts.collection).to.equal('myCollection.json');\n                    expect(opts.environment).to.equal('env.json');\n\n                    done();\n                });\n        });\n\n        it('should throw an error for invalid --iteration-count values', function (done) {\n            cli('node newman.js run myCollection.json -n -3.14'.split(' '), 'run', function (err) {\n                expect(err).to.have.property('message', 'The value must be a positive integer.');\n\n                done();\n            });\n        });\n\n        describe('--global-var', function () {\n            // test for 'should throw an error for missing --global-var values' has been moved to\n            // cli/run-options.test.js since commander throws custom error in case of argument\n            //  mismatch and that is better handled through exec and stderr check.\n            it('should handle --global-var values without an `=`', function (done) {\n                cli('node newman.js run myCollection.json --global-var foo'.split(' '), 'run', function (err, opts) {\n                    expect(err).to.be.null;\n                    expect(opts.globalVar).to.eql([\n                        { key: 'foo', value: undefined }\n                    ]);\n\n                    done();\n                });\n            });\n        });\n\n        describe('--color', function () {\n            it('should have color `auto` by default', function (done) {\n                cli('node newman.js run myCollection.json'.split(' '), 'run',\n                    function (err, opts) {\n                        expect(err).to.be.null;\n                        expect(opts.color).to.equal('auto');\n                        done();\n                    });\n            });\n\n            it('should have color enabled with `--color on`', function (done) {\n                cli('node newman.js run myCollection.json --color on'.split(' '), 'run',\n                    function (err, opts) {\n                        expect(err).to.be.null;\n                        expect(opts.color).to.equal('on');\n                        done();\n                    });\n            });\n\n            it('should have color disabled with `--color off`', function (done) {\n                cli('node newman.js run myCollection.json --color off'.split(' '), 'run',\n                    function (err, opts) {\n                        expect(err).to.be.null;\n                        expect(opts.color).to.equal('off');\n                        done();\n                    });\n            });\n\n            it('should throw an error for invalid --color values', function (done) {\n                cli('node newman.js run myCollection.json --color --disable-unicode'.split(' '), 'run', function (err) {\n                    expect(err).to.have.property('message',\n                        'invalid value `--disable-unicode` for --color. Expected: auto|on|off');\n\n                    done();\n                });\n            });\n        });\n\n        it('should load all arguments (except reporters)', function (done) {\n            cli(('node newman.js run ' +\n                'myCollection.json ' +\n                '-e myEnv.json ' +\n                '-g myGlobals.json ' +\n                '-d path/to/csv.csv ' +\n                '--folder myFolder ' +\n                '--working-dir /Users/postman ' +\n                '--no-insecure-file-read ' +\n                '--cookie-jar myCookie.json ' +\n                '--export-cookie-jar exported_cookie.json ' +\n                '--export-environment exported_env.json ' +\n                '--export-globals exported_glob.json ' +\n                '--postman-api-key POSTMAN_API_KEY ' +\n                '--reporter-cli-no-summary ' +\n                '--iteration-count 23 ' +\n                '--reporters json ' +\n                '--global-var foo=bar --global-var alpha==beta= ' +\n                '--color off ' +\n                '--delay-request 12000 ' +\n                '--timeout 10000 ' +\n                '--timeout-request 5000 ' +\n                '--timeout-script 5000 ' +\n                '--ignore-redirects ' +\n                '--bail ' +\n                '--suppress-exit-code ' +\n                '-k ' +\n                '--verbose').split(' '), 'run', function (err, opts) {\n                expect(err).to.be.null;\n\n                expect(opts).to.be.ok;\n                expect(opts.collection).to.equal('myCollection.json');\n                expect(opts.environment).to.equal('myEnv.json');\n                expect(opts.folder).to.eql(['myFolder']);\n                expect(opts.workingDir).to.eql('/Users/postman');\n                expect(opts.cookieJar).to.eql('myCookie.json');\n                expect(opts.exportCookieJar).to.eql('exported_cookie.json');\n                expect(opts.insecureFileRead).to.be.false;\n                expect(opts.exportEnvironment).to.equal('exported_env.json');\n                expect(opts.iterationData).to.equal('path/to/csv.csv');\n                expect(opts.globals).to.equal('myGlobals.json');\n                expect(opts.exportGlobals).to.equal('exported_glob.json');\n                expect(opts.postmanApiKey).to.equal('POSTMAN_API_KEY');\n                expect(opts.delayRequest, 'should have delayRequest of 12000').to.equal(12000);\n                expect(opts.timeout, 'should have timeout of 10000').to.equal(10000);\n                expect(opts.timeoutRequest, 'should have timeoutRequest of 5000').to.equal(5000);\n                expect(opts.timeoutScript, 'should have timeoutScript of 5000').to.equal(5000);\n                expect(opts.ignoreRedirects, 'should have ignoreRedirects to be true').to.equal(true);\n                expect(opts.insecure, 'shoudl have insecure to be true').to.equal(true);\n\n                expect(opts.color).to.equal('off');\n\n                expect(opts.reporters).to.contain('json');\n                expect(opts.reporters).to.not.contain('junit');\n\n                expect(opts.globalVar).to.eql([\n                    { key: 'foo', value: 'bar' },\n                    { key: 'alpha', value: '=beta=' }\n                ]);\n\n                expect(opts.bail, 'should have bail to be true').to.equal(true);\n                expect(opts.suppressExitCode, 'should have suppressExitCode to be true').to.equal(true);\n                expect(opts.verbose, 'should have verbose to be true').to.equal(true);\n\n                done();\n            });\n        });\n\n        it('should load all arguments (including reporters)', function (done) {\n            cli(('node newman.js run ' +\n                'myCollection.json ' +\n                '-e myEnv.json ' +\n                '-g myGlobals.json ' +\n                '-d /path/to/csv.csv ' +\n                '--folder myFolder1 ' +\n                '--folder myFolder2 ' +\n                '--working-dir /Users/postman ' +\n                '--no-insecure-file-read ' +\n                '--disable-unicode ' +\n                '--export-environment exported_env.json ' +\n                '--export-globals exported_glob.json ' +\n                '--reporter-cli-no-summary ' +\n                '--reporter-cli-no-success-assertions ' +\n                '--iteration-count 23 ' +\n                '--reporters json ' +\n                '--color on ' +\n                '--delay-request 12000 ' +\n                '--timeout 10000 ' +\n                '--timeout-request 5000 ' +\n                '--timeout-script 5000 ' +\n                '--ignore-redirects ' +\n                '-k ' +\n                '--verbose ' +\n                '--bail folder,failure ' +\n                '--global-var foo=bar --global-var alpha==beta= ' +\n                '--reporter-json-output ./omg.txt ' +\n                '--reporter-use everything').split(' '), 'run', function (err, opts) {\n                expect(err).to.be.null;\n\n                expect(opts).to.be.ok;\n                expect(opts.collection).to.equal('myCollection.json');\n                expect(opts.environment).to.equal('myEnv.json');\n                expect(opts.folder).to.eql(['myFolder1', 'myFolder2']);\n                expect(opts.workingDir).to.eql('/Users/postman');\n                expect(opts.insecureFileRead).to.be.false;\n                expect(opts.disableUnicode, 'should have disableUnicode to be true').to.equal(true);\n\n                expect(opts.exportEnvironment).to.equal('exported_env.json');\n                expect(opts.iterationData).to.equal('/path/to/csv.csv');\n                expect(opts.globals).to.equal('myGlobals.json');\n\n                expect(opts.exportGlobals).to.equal('exported_glob.json');\n                expect(opts.delayRequest, 'should have delayRequest of 12000').to.equal(12000);\n                expect(opts.timeout, 'should have timeout of 10000').to.equal(10000);\n                expect(opts.timeoutRequest, 'should have timeoutRequest of 5000').to.equal(5000);\n                expect(opts.timeoutScript, 'should have timeoutScript of 5000').to.equal(5000);\n                expect(opts.ignoreRedirects, 'should have ignoreRedirects to be true').to.equal(true);\n                expect(opts.insecure, 'should have insecure to be true').to.equal(true);\n                expect(opts.verbose, 'should have verbose to be true').to.equal(true);\n\n                expect(opts.globalVar).to.eql([\n                    { key: 'foo', value: 'bar' },\n                    { key: 'alpha', value: '=beta=' }\n                ]);\n                expect(opts.bail).to.eql([\n                    'folder',\n                    'failure'\n                ]);\n\n                expect(opts.color).to.equal('on');\n\n                expect(opts.reporters).to.contain('json');\n                expect(opts.reporters).to.not.contain('verbose');\n                expect(opts.reporters).to.not.contain('junit');\n\n                // Generic reporter options\n                expect(opts.reporterOptions).to.be.ok;\n                expect(opts.reporterOptions.use).to.equal('everything');\n                expect(opts.reporterOptions.cliNoSuccessAssertions\n                    , 'should have cliNoSuccessAssertions to be true').to.equal(true);\n\n                // Individual reporter options\n                expect(opts.reporter).to.be.ok;\n\n                // Validate JSON reporter configuration\n                expect(opts.reporter.json).to.be.ok;\n                expect(opts.reporter.json.output).to.equal('./omg.txt');\n                expect(opts.reporter.json.use).to.equal('everything');\n\n                done();\n            });\n        });\n\n        it('should turn off newman banner if --reporter-cli-no-banner is set', function (done) {\n            cli('node newman.js run myCollection.json --reporter-cli-no-banner'.split(' '), 'run',\n                function (err, opts) {\n                    expect(err).to.be.null;\n                    expect(opts).to.be.ok;\n                    expect(opts.reporter.cli.noBanner, 'should have noBanner to be true').to.equal(true);\n\n                    done();\n                });\n        });\n    });\n});\n"
  },
  {
    "path": "test/unit/defaultReporter.test.js",
    "content": "const sinon = require('sinon'),\n    expect = require('chai').expect,\n    newman = require('../../');\n\ndescribe('Default reporter', function () {\n    beforeEach(function () {\n        sinon.replace(console, 'warn', sinon.fake());\n    });\n\n    afterEach(function () {\n        sinon.restore();\n    });\n\n    it('cli can be loaded', function (done) {\n        newman.run({\n            collection: 'test/fixtures/run/single-get-request.json',\n            reporters: ['cli']\n        }, function (err) {\n            expect(err).to.be.null;\n            expect(console.warn.called).to.be.false;\n\n            done();\n        });\n    });\n\n    it('json can be loaded', function (done) {\n        newman.run({\n            collection: 'test/fixtures/run/single-get-request.json',\n            reporters: ['json']\n        }, function (err) {\n            expect(err).to.be.null;\n            expect(console.warn.called).to.be.false;\n\n            done();\n        });\n    });\n\n    it('junit can be loaded', function (done) {\n        newman.run({\n            collection: 'test/fixtures/run/single-get-request.json',\n            reporters: ['junit']\n        }, function (err) {\n            expect(err).to.be.null;\n            expect(console.warn.called).to.be.false;\n\n            done();\n        });\n    });\n\n    it('progress can be loaded', function (done) {\n        newman.run({\n            collection: 'test/fixtures/run/single-get-request.json',\n            reporters: ['progress']\n        }, function (err) {\n            expect(err).to.be.null;\n            expect(console.warn.called).to.be.false;\n\n            done();\n        });\n    });\n\n    it('emojitrain can be loaded', function (done) {\n        newman.run({\n            collection: 'test/fixtures/run/single-get-request.json',\n            reporters: ['emojitrain']\n        }, function (err) {\n            expect(err).to.be.null;\n            expect(console.warn.called).to.be.false;\n\n            done();\n        });\n    });\n});\n"
  },
  {
    "path": "test/unit/externalReporter.test.js",
    "content": "const sinon = require('sinon'),\n    expect = require('chai').expect,\n    newman = require('../../');\n\ndescribe('External reporter', function () {\n    beforeEach(function () {\n        sinon.replace(console, 'warn', sinon.fake());\n    });\n\n    afterEach(function () {\n        sinon.restore();\n    });\n\n    it('warns when not found', function (done) {\n        newman.run({\n            collection: 'test/fixtures/run/single-get-request.json',\n            reporters: ['unknownreporter']\n        }, function (err) {\n            expect(err).to.be.null;\n            expect(console.warn.called).to.be.true;\n            expect(console.warn.calledWith('newman: could not find \"unknownreporter\" reporter')).to.be.true;\n\n            done();\n        });\n    });\n});\n"
  },
  {
    "path": "test/unit/options.test.js",
    "content": "const _ = require('lodash'),\n    expect = require('chai').expect,\n    { VariableScope } = require('postman-collection'),\n    options = require('../../lib/run/options');\n\ndescribe('options', function () {\n    describe('JSON with spaces', function () {\n        it('should be handled correctly for collections', function (done) {\n            var collection = require('../../test/fixtures/run/spaces/single-get-request.json');\n\n            options({\n                collection: './test/fixtures/run/spaces/single-get-request.json'\n            }, function (err, result) {\n                expect(err).to.be.null;\n\n                // remove undefined properties\n                result = JSON.parse(JSON.stringify(result.collection.toJSON()));\n                expect(_.omit(result,\n                    // eslint-disable-next-line max-len\n                    ['event', 'info._postman_id', 'variable', 'item.0.id', 'item.0.response', 'item.0.event.0.script.id']))\n                    .to.eql(collection);\n                done();\n            });\n        });\n\n        it('should be handled correctly for environments', function (done) {\n            var environment = require('../../test/fixtures/run/spaces/simple-variables.json');\n\n            options({\n                environment: './test/fixtures/run/spaces/simple-variables.json'\n            }, function (err, result) {\n                expect(err).to.be.null;\n\n                expect(_.omit(result.environment.toJSON(), 'id')).to.eql(environment);\n                done();\n            });\n        });\n\n        it('should apply directly specified env variables to environment list', function (done) {\n            options({\n                envVar: [{ key: 'test', value: 'data' }]\n            }, function (err, result) {\n                expect(err).to.be.null;\n                expect(result).to.have.property('environment');\n                expect(result.environment).to.be.an.instanceof(VariableScope);\n                expect(result.environment.get('test')).to.equal('data');\n                done();\n            });\n        });\n\n        it('should be handled correctly for globals', function (done) {\n            var globals = require('../../test/fixtures/run/spaces/simple-variables.json');\n\n            options({\n                globals: './test/fixtures/run/spaces/simple-variables.json'\n            }, function (err, result) {\n                expect(err).to.be.null;\n\n                expect(_.omit(result.globals.toJSON(), 'id')).to.eql(globals);\n                done();\n            });\n        });\n\n        it('should apply directly specified global variables to globals list', function (done) {\n            options({\n                globalVar: [{ key: 'test', value: 'data' }]\n            }, function (err, result) {\n                expect(err).to.be.null;\n                expect(result).to.have.property('globals');\n                expect(result.globals).to.be.an.instanceof(VariableScope);\n                expect(result.globals.get('test')).to.equal('data');\n                done();\n            });\n        });\n\n        it('should be handled correctly for iterationData', function (done) {\n            var data = require('../../test/fixtures/run/spaces/data.json');\n\n            options({\n                iterationData: './test/fixtures/run/spaces/data.json'\n            }, function (err, result) {\n                expect(err).to.be.null;\n                expect(result.iterationData).to.eql(data);\n                done();\n            });\n        });\n\n        it('should be handled correctly for cookieJar', function (done) {\n            var data = require('../../test/fixtures/run/spaces/simple-cookie-jar.json');\n\n            options({\n                cookieJar: './test/fixtures/run/spaces/simple-cookie-jar.json'\n            }, function (err, result) {\n                expect(err).to.be.null;\n                expect(result.cookieJar.toJSON()).to.eql(data);\n                done();\n            });\n        });\n    });\n\n    it('should have newmanVersion property by default', function (done) {\n        var newmanVersion = require('../../package.json').version;\n\n        options({}, function (err, result) {\n            expect(err).to.be.null;\n            expect(result).to.have.property('newmanVersion', newmanVersion);\n            done();\n        });\n    });\n\n    it('should set current directory as workingDir if not given', function (done) {\n        options({}, function (err, result) {\n            expect(err).to.be.null;\n            expect(result).to.have.property('workingDir', process.cwd());\n            done();\n        });\n    });\n\n    it('should set insecureFileRead to true if not given', function (done) {\n        options({}, function (err, result) {\n            expect(err).to.be.null;\n            expect(result).to.have.property('insecureFileRead', true);\n            done();\n        });\n    });\n});\n"
  },
  {
    "path": "test/unit/run-summary.test.js",
    "content": "const _ = require('lodash'),\n    expect = require('chai').expect;\n\ndescribe('run summary', function () {\n    // @todo add test for computation of timings, transfer sizes and average response time\n    var Summary = require('../../lib/run/summary'),\n        EventEmitter = require('events'),\n        sdk = require('postman-collection'),\n\n        TRACKED_EVENTS = ['iteration', 'item', 'script', 'prerequest', 'request', 'test', 'assertion',\n            'testScript', 'prerequestScript'],\n        SURROGATE_EVENTS = ['testScript', 'prerequestScript'];\n\n    it('should require only an EventEmitter during construction', function () {\n        expect(function () {\n            var summary = new Summary();\n\n            expect(summary).not.be.ok;\n        }).to.throw();\n\n        expect(function () {\n            var summary = new Summary(new EventEmitter());\n\n            expect(summary).be.ok;\n        }).to.not.throw();\n\n        expect(function () {\n            var summary = new Summary(new EventEmitter(), {});\n\n            expect(summary).be.ok;\n        }).to.not.throw();\n    });\n\n    it('should have the relevant top-level data structures', function () {\n        var summary = new Summary(new EventEmitter());\n\n        expect(_.keys(summary).sort()).to.eql(['collection', 'environment', 'globals', 'run'].sort());\n    });\n\n    it('should have run related properties', function () {\n        var summary = new Summary(new EventEmitter());\n\n        expect(summary).to.have.property('run');\n        expect(_.keys(summary.run).sort())\n            .to.eql(['stats', 'timings', 'executions', 'transfers', 'failures', 'error'].sort());\n        expect(summary.run.failures).to.be.an('array');\n        expect(summary.run.stats).to.be.an('object');\n        expect(summary.run.timings).to.be.an('object');\n        expect(summary.run.transfers).to.be.an('object');\n    });\n\n    describe('runtime event statistics', function () {\n        it('should track relevant events', function () {\n            var emitter = new EventEmitter(),\n                summary = new Summary(emitter);\n\n            expect(_.keys(summary.run.stats)).to.eql(_.map(TRACKED_EVENTS, function (name) {\n                return name + 's';\n            }));\n        });\n\n        TRACKED_EVENTS.forEach(function (eventName) {\n            describe(`${eventName} event`, function () {\n                var beforeEventName = _.camelCase(`before-${eventName}`),\n                    emitter,\n                    summary,\n                    tracker,\n                    options;\n\n                beforeEach(function () {\n                    emitter = new EventEmitter();\n                    summary = new Summary(emitter);\n                    options = {\n                        cursor: { ref: 'fake-ref' }\n                    };\n                    tracker = summary.run.stats[eventName + 's'];\n                });\n                afterEach(function () {\n                    emitter = null;\n                    summary = null;\n                    options = null;\n                    tracker = null;\n                });\n\n                it('should have initial counters', function () {\n                    expect(tracker).to.eql({ total: 0, pending: 0, failed: 0 });\n                });\n\n                it(`should bump pending counters when a ${beforeEventName} is fired`, function () {\n                    emitter.emit(beforeEventName, null, options);\n                    expect(tracker).to.eql({ total: 0, pending: 1, failed: 0 });\n                });\n\n                it(`should unbump pending counters when a ${eventName} is fired and add total`, function () {\n                    emitter.emit(beforeEventName, null, options);\n                    emitter.emit(eventName, null, options);\n\n                    expect(tracker).to.eql({ total: 1, pending: 0, failed: 0 });\n                });\n\n                it(`should directly bump total ${eventName} with no pending ${beforeEventName} event`, function () {\n                    emitter.emit(eventName, null, options);\n                    emitter.emit(eventName, null, options);\n                    expect(tracker).to.eql({ total: 2, pending: 0, failed: 0 });\n                });\n\n                it(`should bump failure count when ${eventName} has error (1st) argument`, function () {\n                    emitter.emit(beforeEventName, new Error(`faux error on ${beforeEventName}`), options);\n                    emitter.emit(eventName, new Error(`faux error on ${eventName}`), options);\n                    expect(tracker).to.eql({ total: 1, pending: 0, failed: 1 });\n                });\n            });\n        });\n    });\n\n    describe('failure logging', function () {\n        describe('surrogate (pseudo) event', function () {\n            _.forEach(SURROGATE_EVENTS, function (eventName) {\n                var beforeEventName = _.camelCase(`before-${eventName}`),\n                    emitter,\n                    summary;\n\n                beforeEach(function () {\n                    emitter = new EventEmitter();\n                    summary = new Summary(emitter);\n                });\n                afterEach(function () {\n                    emitter = null;\n                    summary = null;\n                });\n\n                it(`should not track errors in ${eventName}`, function () {\n                    emitter.emit(beforeEventName, new Error(`faux ${beforeEventName} error`), {});\n                    emitter.emit(eventName, new Error(`faux ${eventName} error`), {});\n\n                    expect(summary.run.failures, 'should have 0 failures').to.have.lengthOf(0);\n                });\n            });\n        });\n\n        _(TRACKED_EVENTS).difference(SURROGATE_EVENTS).forEach(function (eventName) {\n            describe(`${eventName} event`, function () {\n                var beforeEventName = _.camelCase(`before-${eventName}`),\n                    emitter,\n                    summary;\n\n                beforeEach(function () {\n                    emitter = new EventEmitter();\n                    summary = new Summary(emitter);\n                });\n\n                afterEach(function () {\n                    emitter = null;\n                    summary = null;\n                });\n\n                it('should append event failure arguments to failures array', function () {\n                    emitter.emit(beforeEventName, new Error(`faux ${beforeEventName} error`), {});\n                    emitter.emit(eventName, new Error(`faux ${eventName} error`), {});\n\n                    expect(summary.run.failures, 'should have 2 failures').to.have.lengthOf(2);\n                    expect(summary.run.failures[0].error.message).to.equal(`faux ${beforeEventName} error`);\n                    expect(summary.run.failures[1].error.message).to.equal(`faux ${eventName} error`);\n                });\n\n                it('should have relevant data in object of \"before-*\"', function () {\n                    emitter.emit(beforeEventName, new Error(`faux ${beforeEventName} error`), {});\n                    emitter.emit(eventName, new Error(`faux ${eventName} error`), {});\n\n                    expect(summary.run.failures, 'should have 2 failures').to.have.lengthOf(2);\n                    var failure = summary.run.failures[0];\n\n                    expect(failure.error.message).to.equal(`faux ${beforeEventName} error`);\n                    expect(_.keys(failure)).to.eql(['error', 'at', 'source', 'parent', 'cursor']);\n\n                    expect(failure).to.have.property('at');\n                    expect(failure.at).to.equal(beforeEventName);\n\n                    expect(failure).to.have.property('source');\n                    expect(failure.source).to.be.undefined;\n\n                    expect(failure).to.have.property('cursor');\n                    expect(failure.cursor).to.be.an('object');\n                });\n            });\n        });\n\n        describe('execution tracking', function () {\n            var emitter,\n                collection,\n                summary;\n\n            beforeEach(function () {\n                collection = new sdk.Collection({\n                    item: [{\n                        id: 'i1', request: 'http://localhost/1'\n                    }, {\n                        id: 'i2', request: 'http://localhost/1'\n                    }]\n                });\n                emitter = new EventEmitter();\n                summary = new Summary(emitter, {\n                    collection\n                });\n            });\n\n            afterEach(function () {\n                collection = null;\n                emitter = null;\n                summary = null;\n            });\n\n            it('should add to the executions array', function () {\n                var executions = summary.run.executions,\n                    item = collection.items.one('i1');\n\n                emitter.emit('request', null, {\n                    item: item,\n                    cursor: { ref: '1', iteration: 0 }\n                });\n                emitter.emit('request', null, {\n                    item: item,\n                    cursor: { ref: '2', iteration: 1 }\n                });\n\n                expect(executions, 'should have 2 executions').to.have.lengthOf(2);\n                expect(executions[0].cursor).to.eql({ ref: '1', iteration: 0 });\n                expect(executions[1].cursor).to.eql({ ref: '2', iteration: 1 });\n            });\n\n            it('should store request and response', function () {\n                var executions = summary.run.executions,\n                    item = collection.items.one('i1');\n\n                emitter.emit('request', null, {\n                    item: item,\n                    request: { id: 'request-1' },\n                    response: { id: 'response-1' },\n                    cursor: { ref: '1', iteration: 0 }\n                });\n\n                expect(executions, 'should have 1 executions').to.have.lengthOf(1);\n                expect(executions[0]).to.eql({\n                    cursor: { ref: '1', iteration: 0 },\n                    request: { id: 'request-1' },\n                    response: { id: 'response-1' },\n                    id: item.id\n                });\n            });\n\n            it('should store request error with response info even if request is missing', function () {\n                var executions = summary.run.executions,\n                    item = collection.items.one('i1');\n\n                emitter.emit('request', { message: 'failed' }, {\n                    item: item,\n                    request: { id: 'request-1' },\n                    response: { id: 'response-1' },\n                    cursor: { ref: '1', iteration: 0 }\n                });\n\n                expect(executions, 'should have 1 executions').to.have.lengthOf(1);\n                expect(executions[0]).to.eql({\n                    cursor: { ref: '1', iteration: 0 },\n                    request: { id: 'request-1' },\n                    response: { id: 'response-1' },\n                    id: item.id,\n                    requestError: { message: 'failed' }\n                });\n            });\n        });\n    });\n});\n"
  },
  {
    "path": "test/unit/run.test.js",
    "content": "const _ = require('lodash'),\n    path = require('path'),\n    async = require('async'),\n    sinon = require('sinon'),\n    expect = require('chai').expect,\n    sdk = require('postman-collection'),\n    runtime = require('postman-runtime');\n\ndescribe('run module', function () {\n    var run = require('../../lib/run');\n\n    it('should export a function', function () {\n        expect(run).to.be.a('function');\n    });\n\n    it('should start a run with no options and return error in callback', function (done) {\n        expect(function () {\n            run(function (err) {\n                expect(err).to.be.ok;\n                expect(err.message).to.equal('expecting a collection to run');\n                done();\n            });\n        }).to.not.throw();\n    });\n\n    it('should error out if collection is absent in options', function (done) {\n        expect(function () {\n            run({}, function (err) {\n                expect(err).be.ok;\n                expect(err && err.message).to.equal('expecting a collection to run');\n\n                done();\n            });\n        }).to.not.throw();\n    });\n\n    // @todo enable when the v1 collection format support is dropped in Newman v7?\n    it.skip('should error out if v1 collection is passed', function (done) {\n        const v1Collection = {\n            id: 'a4f4a069-00a2-4f70-a792-513877241083',\n            name: 'C1',\n            order: ['3e5349fa-a259-4ac2-a920-b694e6f8c1e6'],\n            requests: [{\n                id: '3e5349fa-a259-4ac2-a920-b694e6f8c1e6',\n                name: 'R1',\n                collectionId: '5adbd3b7-80cb-43cc-bf1e-8578ab3c9b15',\n                method: 'GET',\n                url: 'https://postman-echo.com/get',\n                responses: [],\n                pathVariableData: [],\n                queryParams: [],\n                headerData: []\n            }]\n        };\n\n        run({\n            collection: v1Collection\n        }, function (err) {\n            expect(err).be.ok;\n            expect(err).to.have.property('message', 'Newman >= v5 does not support the v1 collection format');\n            expect(err).to.have.property('friendly',\n                'Use the Postman Native app to export collections in the v2 format');\n            done();\n        });\n    });\n\n    it('should start a run with empty collection as plain object', function (done) {\n        expect(function () {\n            run({\n                collection: {}\n            }, done);\n        }).to.not.throw();\n    });\n\n    it('should start a run with empty collection as SDK instance', function (done) {\n        expect(function () {\n            run({\n                collection: new sdk.Collection()\n            }, done);\n        }).to.not.throw();\n    });\n\n    it('should provide sdk instances as part of the run', function (done) {\n        expect(function () {\n            run({\n                collection: {}\n            }, function (err, newman) {\n                if (err) {\n                    return done(err);\n                }\n\n                expect(newman).to.be.an('object');\n                expect(newman).to.have.property('collection');\n                expect(newman).to.have.property('environment');\n                expect(newman).to.have.property('globals');\n\n                expect(newman.collection,\n                    'should be an instance of PostmanCollection').to.be.an.instanceof(sdk.Collection);\n                expect(newman.environment,\n                    'should be an instance of PostmanVariableScope').to.be.an.instanceof(sdk.VariableScope);\n                expect(newman.globals,\n                    'should be an instance of PostmanVariableScope').to.be.an.instanceof(sdk.VariableScope);\n\n                done();\n            });\n        }).to.not.throw();\n    });\n\n    it('should retain sdk references from options', function (done) {\n        var options = {\n            collection: new sdk.Collection(),\n            environment: new sdk.VariableScope(),\n            globals: new sdk.VariableScope()\n        };\n\n        expect(function () {\n            run(options, function (err, newman) {\n                if (err) {\n                    return done(err);\n                }\n\n                expect(_.omit(newman.collection.toJSON(), '_')).to.eql(options.collection.toJSON());\n                expect(newman.environment).to.eql(options.environment);\n                expect(newman.globals).to.eql(options.globals);\n\n                done();\n            });\n        }).to.not.throw();\n    });\n\n    it('should gracefully send error to callback on garbage collection', function (done) {\n        async.parallel([\n            function (next) {\n                expect(function () {\n                    run({\n                        collection: null\n                    }, function (err) {\n                        expect(err).be.ok;\n                        expect(err && err.message).to.equal('expecting a collection to run');\n                        next();\n                    });\n                }).to.not.throw();\n            },\n            function (next) {\n                expect(function () {\n                    run({\n                        collection: 3.14\n                    }, function (err) {\n                        expect(err).be.ok;\n                        expect(err && err.message).to.equal('collection could not be loaded');\n                        next();\n                    });\n                }).to.not.throw();\n            },\n            function (next) {\n                expect(function () {\n                    run({\n                        collection: 'abcd'\n                    }, function (err) {\n                        expect(err).be.ok;\n                        expect(err && err.message).to.include('collection could not be loaded\\n' +\n                            '  unable to read data from file \"abcd\"\\n' +\n                            '  ENOENT: no such file or directory, open \\'');\n                        next();\n                    });\n                }).to.not.throw();\n            }\n        ], done);\n    });\n\n    it('should gracefully send error to callback on garbage iterationData', function (done) {\n        async.parallel([\n            function (next) {\n                expect(function () {\n                    run({\n                        collection: {},\n                        iterationData: 'xyz'\n                    }, function (err) {\n                        expect(err).be.ok;\n                        expect(err && err.message).to.include('iteration data could not be loaded\\n' +\n                            '  ENOENT: no such file or directory, open \\'');\n                        next();\n                    });\n                }).to.not.throw();\n            },\n            function (next) {\n                expect(function () {\n                    run({\n                        collection: {},\n                        iterationData: 'http://'\n                    }, function (err) {\n                        expect(err).be.ok;\n                        expect(err && err.message).to.equal('iteration data could not be loaded\\n' +\n                            '  Invalid URI \"http:///\"');\n                        next();\n                    });\n                }).to.not.throw();\n            }\n        ], done);\n    });\n\n    // @todo: run tests with exec and nock instead\n    it('should correctly resolve conflicts between iterationData.length and iterationCount', function (done) {\n        this.timeout(10000); // set 10s timeout\n\n        var testData = path.join(__dirname, '..', 'fixtures', 'run', 'test-data.postman_data.json'),\n            testCollection = path.join(__dirname, '..', 'fixtures', 'run', 'single-get-request.json');\n\n        async.parallel([\n            // collection run with neither iterationData, nor iterationCount specified\n            function (next) {\n                expect(function () {\n                    run({\n                        collection: testCollection\n                    }, function (err, summary) {\n                        expect(err).to.be.null;\n                        expect(summary.run.stats.iterations.total).to.equal(1);\n                        next();\n                    });\n                }).to.not.throw();\n            },\n            // collection run with iterationData, but no iterationCount specified\n            function (next) {\n                expect(function () {\n                    run({\n                        collection: testCollection,\n                        iterationData: testData\n                    }, function (err, summary) {\n                        expect(err).to.be.null;\n                        expect(summary.run.stats.iterations.total).to.equal(2);\n                        next();\n                    });\n                }).to.not.throw();\n            },\n            // collection run with iterationCount, but no iterationData specified\n            function (next) {\n                expect(function () {\n                    run({\n                        collection: testCollection,\n                        iterationCount: 2\n                    }, function (err, summary) {\n                        expect(err).to.be.null;\n                        expect(summary.run.stats.iterations.total).to.equal(2);\n                        next();\n                    });\n                }).to.not.throw();\n            },\n            // collection run with both iterationData and iterationCount specified\n            function (next) {\n                expect(function () {\n                    run({\n                        collection: testCollection,\n                        iterationData: testData,\n                        iterationCount: 3\n                    }, function (err, summary) {\n                        expect(err).to.be.null;\n                        expect(summary.run.stats.iterations.total).to.equal(3);\n                        next();\n                    });\n                }).to.not.throw();\n            }\n        ], done);\n    });\n\n    describe('Runner.run options', function () {\n        before(function () {\n            // stub runtime.Runner and override `run` to return options argument as error to stop further execution.\n            sinon.stub(runtime, 'Runner').prototype.run = (collection, options, callback) => {\n                callback(options);\n            };\n        });\n\n        after(function () {\n            runtime.Runner.restore();\n        });\n\n        describe('entrypoint', function () {\n            it('should be undefined by default', function (done) {\n                run({ collection: {} }, function (options) {\n                    expect(options).to.have.property('entrypoint').to.be.undefined;\n                    done();\n                });\n            });\n\n            it('should handle options.folder passed as string correctly', function (done) {\n                run({ collection: {}, folder: 'f1' }, function (options) {\n                    expect(options).to.have.deep.property('entrypoint', { execute: 'f1' });\n                    done();\n                });\n            });\n\n            it('should use multipleIdOrName strategy if options.folder is passed as an array', function (done) {\n                run({ collection: {}, folder: ['f1', 'f2'] }, function (options) {\n                    expect(options).to.have.deep.property('entrypoint', {\n                        execute: ['f1', 'f2'],\n                        lookupStrategy: 'multipleIdOrName'\n                    });\n                    done();\n                });\n            });\n\n            it('should not use multipleIdOrName strategy if options.folder is a single item array', function (done) {\n                run({ collection: {}, folder: ['f1'] }, function (options) {\n                    expect(options).to.have.property('entrypoint').to.eql({ execute: 'f1' });\n                    done();\n                });\n            });\n        });\n    });\n});\n"
  },
  {
    "path": "test/unit/secure-fs.test.js",
    "content": "const path = require('path'),\n    expect = require('chai').expect,\n    SecureFs = require('../../lib/run/secure-fs'),\n\n    POSIX_WORKING_DIR = '/Postman/files',\n    WIN32_WORKING_DIR = 'C:\\\\Postman\\\\files';\n\n/**\n * The posix file system supports only / as valid path separators. \\\\ is treated as valid folder or\n * file name.\n */\ndescribe('Postman Filesystem', function () {\n    describe('sanity', function () {\n        it('should not crash with empty construction', function () {\n            // eslint-disable-next-line no-unused-vars\n            const fs = new SecureFs();\n        });\n\n        it('should not crash with proper construction', function () {\n            // eslint-disable-next-line no-unused-vars\n            const fs = new SecureFs(POSIX_WORKING_DIR, false, []);\n        });\n    });\n\n    describe('posix resolver', function () {\n        let fs;\n\n        before(function () {\n            process.platform === 'win32' && this.skip();\n        });\n\n        describe('with default working dir', function () {\n            before(function () {\n                fs = new SecureFs(POSIX_WORKING_DIR, false);\n            });\n\n            it('should resolve a posix relative path', function (done) {\n                fs.resolvePath('directory/file.json', (err, path) => {\n                    expect(err).to.not.be.ok;\n\n                    expect(path).to.eql(POSIX_WORKING_DIR + '/directory/file.json');\n\n                    return done();\n                });\n            });\n\n            it('should resolve an absolute path within working dir', function (done) {\n                fs.resolvePath('/Postman/files/directory/outside.json', (err, path) => {\n                    expect(err).to.not.be.ok;\n\n                    expect(path).to.eql(POSIX_WORKING_DIR + '/directory/outside.json');\n\n                    return done();\n                });\n            });\n\n            it('should not resolve an absolute path outside working dir', function (done) {\n                fs.resolvePath('/Postman/outside/directory/outside.json', (err) => {\n                    expect(err).to.be.ok;\n\n                    expect(err.message).to.eql('PPERM: insecure file access outside working directory');\n\n                    return done();\n                });\n            });\n\n            it('should resolve relative path with space character', function (done) {\n                fs.resolvePath('Dir Space/file.json', (err, path) => {\n                    expect(err).to.not.be.ok;\n\n                    expect(path).to.eql(POSIX_WORKING_DIR + '/Dir Space/file.json');\n\n                    return done();\n                });\n            });\n        });\n\n        describe('with file whitelist', function () {\n            before(function () {\n                fs = new SecureFs(POSIX_WORKING_DIR, false, ['/Postman/cache/morepath/file.json']);\n            });\n\n            it('should resolve an absolute path outside working dir if cached', function (done) {\n                fs.resolvePath('/Postman/cache/morepath/file.json', (err, path) => {\n                    expect(err).to.not.be.ok;\n\n                    expect(path).to.eql('/Postman/cache/morepath/file.json');\n\n                    return done();\n                });\n            });\n        });\n\n        describe('with insecureFileRead', function () {\n            before(function () {\n                fs = new SecureFs(POSIX_WORKING_DIR, true);\n            });\n\n            it('should resolve an absolute path outside working dir if cached', function (done) {\n                fs.resolvePath('/Postman/insecure/morepath/file.json', (err, path) => {\n                    expect(err).to.not.be.ok;\n\n                    expect(path).to.eql('/Postman/insecure/morepath/file.json');\n\n                    return done();\n                });\n            });\n        });\n\n        describe('with cross os paths', function () {\n            before(function () {\n                fs = new SecureFs(POSIX_WORKING_DIR, true);\n            });\n\n            it('should resolve a windows relative path', function (done) {\n                fs.resolvePath('directory\\\\file.json', (err, path) => {\n                    expect(err).to.not.be.ok;\n\n                    expect(path).to.eql(POSIX_WORKING_DIR + '/directory\\\\file.json');\n\n                    return done();\n                });\n            });\n\n            it('should resolve a windows absolute path', function (done) {\n                fs.resolvePath('C:\\\\Postman\\\\files\\\\directory\\\\file.json', (err, path) => {\n                    expect(err).to.not.be.ok;\n\n                    expect(path).to.eql(POSIX_WORKING_DIR + '/C:\\\\Postman\\\\files\\\\directory\\\\file.json');\n\n                    return done();\n                });\n            });\n        });\n    });\n\n    /**\n     * The windows file system supports both / and \\\\ as valid path separators\n     */\n    describe('win32 resolver', function () {\n        let fs;\n\n        before(function () {\n            process.platform !== 'win32' && this.skip();\n        });\n\n        describe('with default working dir', function () {\n            before(function () {\n                fs = new SecureFs(WIN32_WORKING_DIR, false);\n\n                // Override the internal path to use win32 variant\n                fs._path = path.win32;\n            });\n\n            it('should resolve a windows relative path', function (done) {\n                fs.resolvePath('directory\\\\file.json', (err, path) => {\n                    expect(err).to.not.be.ok;\n\n                    expect(path).to.eql(WIN32_WORKING_DIR + '\\\\directory\\\\file.json');\n\n                    return done();\n                });\n            });\n\n            it('should resolve an absolute path within working dir', function (done) {\n                fs.resolvePath('C:\\\\Postman\\\\files\\\\directory\\\\outside.json', (err, path) => {\n                    expect(err).to.not.be.ok;\n\n                    expect(path).to.eql(WIN32_WORKING_DIR + '\\\\directory\\\\outside.json');\n\n                    return done();\n                });\n            });\n\n            it('should not resolve an absolute path outside working dir', function (done) {\n                fs.resolvePath('C:\\\\Postman\\\\outside\\\\directory\\\\outside.json', (err) => {\n                    expect(err).to.be.ok;\n\n                    expect(err.message).to.eql('PPERM: insecure file access outside working directory');\n\n                    return done();\n                });\n            });\n\n            it('should resolve relative path with space character', function (done) {\n                fs.resolvePath('Dir Space\\\\file.json', (err, path) => {\n                    expect(err).to.not.be.ok;\n\n                    expect(path).to.eql(WIN32_WORKING_DIR + '\\\\Dir Space\\\\file.json');\n\n                    return done();\n                });\n            });\n        });\n\n        describe('with file whitelist', function () {\n            const CACHE_FILE = 'C:\\\\Postman\\\\cache\\\\morepath\\\\file.json';\n\n            before(function () {\n                fs = new SecureFs(WIN32_WORKING_DIR, false, [CACHE_FILE]);\n\n                // Override the internal path to use win32 variant\n                fs._path = path.win32;\n            });\n\n            it('should resolve an absolute path outside working dir if cached', function (done) {\n                fs.resolvePath(CACHE_FILE, (err, path) => {\n                    expect(err).to.not.be.ok;\n\n                    expect(path).to.eql(CACHE_FILE);\n\n                    return done();\n                });\n            });\n        });\n\n        describe('with insecureFileRead', function () {\n            const FILE_OUTSIDE = 'C:\\\\Postman\\\\insecure\\\\morepath\\\\file.json';\n\n            before(function () {\n                fs = new SecureFs(WIN32_WORKING_DIR, true);\n\n                // Override the internal path to use win32 variant\n                fs._path = path.win32;\n            });\n\n            it('should resolve an absolute path outside working dir if cached', function (done) {\n                fs.resolvePath(FILE_OUTSIDE, (err, path) => {\n                    expect(err).to.not.be.ok;\n\n                    expect(path).to.eql(FILE_OUTSIDE);\n\n                    return done();\n                });\n            });\n        });\n\n        describe('with cross os paths', function () {\n            before(function () {\n                fs = new SecureFs(WIN32_WORKING_DIR, true);\n\n                // Override the internal path to use win32 variant\n                fs._path = path.win32;\n            });\n\n            it('should resolve a posix relative path', function (done) {\n                fs.resolvePath('directory/file.json', (err, path) => {\n                    expect(err).to.not.be.ok;\n\n                    expect(path).to.eql(WIN32_WORKING_DIR + '\\\\directory\\\\file.json');\n\n                    return done();\n                });\n            });\n\n            it('should resolve a posix absolute path', function (done) {\n                fs.resolvePath('/Postman/files/directory/file.json', (err, path) => {\n                    expect(err).to.not.be.ok;\n\n                    expect(path).to.eql(WIN32_WORKING_DIR + '\\\\directory\\\\file.json');\n\n                    return done();\n                });\n            });\n\n            it('should resolve a posix postman modified LFS absolute path', function (done) {\n                fs.resolvePath('/C:/Postman/files/directory/file.json', (err, path) => {\n                    expect(err).to.not.be.ok;\n\n                    expect(path).to.eql(WIN32_WORKING_DIR + '\\\\directory\\\\file.json');\n\n                    return done();\n                });\n            });\n\n            it('should resolve a posix postman modified UNC absolute path', function (done) {\n                fs.resolvePath('///Server/Postman/files/directory/file.json', (err, path) => {\n                    expect(err).to.not.be.ok;\n\n                    expect(path).to.eql('\\\\\\\\Server\\\\Postman\\\\files\\\\directory\\\\file.json');\n\n                    return done();\n                });\n            });\n        });\n    });\n});\n"
  },
  {
    "path": "test/unit/util.test.js",
    "content": "const sdk = require('postman-collection'),\n    expect = require('chai').expect,\n\n    util = require('../../lib/util');\n\ndescribe('utility helpers', function () {\n    describe('getFullName', function () {\n        var collection = new sdk.Collection({\n                variables: [],\n                info: {\n                    name: 'multi-level-folders',\n                    _postman_id: 'e5f2e9cf-173b-c60a-7336-ac804a87d762',\n                    description: 'A simple V2 collection to test out multi level folder flows',\n                    schema: 'https://schema.getpostman.com/json/collection/v2.0.0/collection.json'\n                },\n                item: [{\n                    name: 'F1',\n                    item: [{ name: 'F1.R1' }, { name: 'F1.R2' }, { name: 'F1.R3' }]\n                }, {\n                    name: 'F2',\n                    item: [{\n                        name: 'F2.F3',\n                        item: [{ name: 'F2.F3.R1' }]\n                    },\n                    { name: 'F4', item: [] },\n                    { name: 'F2.R1' }]\n                }, { name: 'R1' }]\n            }),\n            fullNames = {\n                'F1.R1': 'F1 / F1.R1',\n                'F1.R2': 'F1 / F1.R2',\n                'F1.R3': 'F1 / F1.R3',\n                'F2.F3.R1': 'F2 / F2.F3 / F2.F3.R1',\n                'F2.R1': 'F2 / F2.R1',\n                R1: 'R1',\n                F1: 'F1',\n                'F2.F3': 'F2 / F2.F3',\n                F4: 'F2 / F4',\n                F2: 'F2'\n            };\n\n        it('should handle empty input correctly', function () {\n            expect(util.getFullName(), 'should handle empty input correctly').to.not.be.ok;\n            expect(util.getFullName(false), 'should handle `false` input correctly').to.not.be.ok;\n            expect(util.getFullName(0), 'should handle `0` input correctly').to.not.be.ok;\n            expect(util.getFullName(''), 'should handle `\\'\\'` input correctly').to.not.be.ok;\n            expect(util.getFullName([]), 'should handle `[]` input correctly').to.not.be.ok;\n            expect(util.getFullName({}), 'should handle `{}` input correctly').to.not.be.ok;\n        });\n\n        it('should handle items correctly', function () {\n            collection.forEachItem(function (item) {\n                expect(util.getFullName(item)).to.equal(fullNames[item.name]);\n            });\n        });\n\n        it('should handle item groups correctly', function () {\n            collection.forEachItemGroup(function (itemGroup) {\n                expect(util.getFullName(itemGroup)).to.equal(fullNames[itemGroup.name]);\n            });\n        });\n    });\n\n    describe('type checkers', function () {\n        it('should validate integers', function () {\n            expect(util.isInt('123')).to.be.true;\n            expect(util.isInt('123.5')).to.be.false;\n        });\n\n        it('should validate floating point', function () {\n            expect(util.isFloat('123.5')).to.be.true;\n        });\n    });\n\n    describe('beautifyTime', function () {\n        var timings = {\n                wait: 1.4010989999997037,\n                dns: 0.20460100000036618,\n                tcp: 43.05270100000007,\n                firstByte: 225.52159900000015,\n                download: 7.652700000000095,\n                total: 277.628099\n            },\n            beautifiedTimings = {\n                wait: '1ms',\n                dns: '204µs',\n                tcp: '43ms',\n                firstByte: '225ms',\n                download: '7ms',\n                total: '277ms'\n            };\n\n        it('should correctly beautify given timeings object', function () {\n            expect(util.beautifyTime(timings)).to.eql(beautifiedTimings);\n        });\n    });\n});\n"
  }
]