├── test ├── fixtures │ ├── files │ │ ├── outside.json │ │ ├── work-dir │ │ │ └── test.json │ │ └── ssl-client-cert-config.json │ ├── run │ │ ├── spaces │ │ │ ├── data.json │ │ │ ├── simple-variables.json │ │ │ ├── simple-cookie-jar.json │ │ │ └── single-get-request.json │ │ ├── test-data.postman_data.json │ │ ├── simple-variables.json │ │ ├── failed-request.json │ │ ├── single-get-request.json │ │ ├── single-request-failing.json │ │ ├── undefined-test-checks.json │ │ ├── ssl-client-cert.json │ │ ├── newman-report-test.json │ │ ├── nested-requests-report-test.json │ │ ├── single-file-inside.json │ │ ├── nested-requests-fail-report-test.json │ │ ├── single-file-outside.json │ │ ├── response-bodies.json │ │ └── ssl-client-cert-list.json │ ├── ssl │ │ ├── client.p12 │ │ ├── v3.ext │ │ ├── SSL.md │ │ ├── sslClientCertList.json │ │ ├── config.cnf │ │ ├── client2.csr │ │ ├── server2.csr │ │ ├── client3.csr │ │ ├── server3.csr │ │ ├── client2.crt │ │ ├── ca3.crt │ │ ├── ca2.crt │ │ ├── server2.crt │ │ ├── client3.crt │ │ ├── server3.crt │ │ ├── ca3.key │ │ ├── client3.key │ │ ├── server3.key │ │ ├── ca2.key │ │ ├── client2.key │ │ ├── server2.key │ │ ├── server.csr │ │ ├── generate-certificates.sh │ │ ├── client.csr │ │ ├── ca.crt │ │ └── ca.key │ └── overrides │ │ ├── env.json │ │ ├── failing-collection.json │ │ └── pmcollection.json ├── integration │ ├── tc4 │ │ ├── upload-file.json │ │ └── tc4.postman_collection.json │ ├── custom-http-method │ │ └── upload-file.csv │ ├── csv-with-bom │ │ ├── csv-with-bom.postman_data.csv │ │ └── csv-with-bom.postman_collection.json │ ├── globals-env-data-files │ │ ├── globals-env-data-files.postman_data.json │ │ ├── globals-env-data-files.postman_globals.json │ │ └── globals-env-data-files.postman_environment.json │ ├── redirect-test │ │ ├── redirect-test.postman_config.json │ │ └── redirect-test.postman_collection.json │ ├── data-file-var-replacement │ │ ├── data-file-var-replacement.postman_data.json │ │ ├── data-file-var-replacement.postman_environment.json │ │ └── data-file-var-replacement.postman_collection.json │ ├── v2-regression-tests │ │ ├── v2-regression-tests.postman_config.json │ │ ├── v2-regression-tests.postman_environment.json │ │ └── v2-regression-tests.postman_collection.json │ ├── steph │ │ ├── steph.postman_data.json │ │ └── steph.postman_collection.json │ ├── timeout │ │ ├── timeout.postman_config.json │ │ └── timeout.postman_collection.json │ ├── bom-and-encoding │ │ ├── utf16-le-encoding-in-env.postman_environment.json │ │ ├── bom-in-environment-file.postman_environment.json │ │ ├── bom-in-environment-file.postman_collection.json │ │ ├── utf16-le-encoding-in-env.postman_collection.json │ │ └── bom-in-collection-file.postman_collection.json │ ├── inherited-entities │ │ └── inherited-entities.postman_environment.json │ ├── comma-test-csv │ │ ├── comma-test-csv.postman_data.csv │ │ └── comma-test-csv.postman_collection.json │ ├── esc-formdata │ │ ├── esc-formdata.postman_environment.json │ │ └── esc-formdata.postman_collection.json │ ├── slashed-variable-names │ │ ├── slashed-variable-names.postman_environment.json │ │ └── slashed-variable-names.postman_collection.json │ ├── disabled-and-duplicate-variables │ │ ├── disabled-and-duplicates.postman_environment.json │ │ └── disabled-and-duplicates.postman_collection.json │ ├── newman-gzip-test.postman_collection.json │ ├── case-insen-header-sandbox.postman_collection.json │ ├── multi-value-data.postman_collection.json │ ├── request-name-in-script.postman_collection.json │ ├── crypto-md5.postman_collection.json │ ├── var-replacement.postman_collection.json │ ├── cookie-jar.postman_collection.json │ ├── semicolon-tests.postman_collection.json │ ├── distinct-random-int.postman_collection.json │ ├── hawk-auth-test.postman_collection.json │ ├── oauth1-var-in-url-params.postman_collection.json │ ├── prototype-check.postman_collection.json │ ├── request-chaining-test.postman_collection.json │ ├── multiple-form-values.postman_collection.json │ ├── head-requests.postman_collection.json │ ├── dynamic-var-replacement.postman_collection.json │ ├── set-next-request.postman_collection.json │ └── helper.postman_collection.json ├── cli │ ├── cli-reporter-show-timestamp.test.js │ ├── cli-reporter-failure-details.test.js │ ├── cli-reporter-no-success-assertsions.test.js │ ├── verbose.test.js │ ├── suppress-exit-code.test.js │ └── working-directory.test.js ├── unit │ ├── externalReporter.test.js │ ├── cli-reporter-symbols.test.js │ └── defaultReporter.test.js ├── system │ ├── npm-publish.test.js │ ├── dockerfiles.test.js │ └── editorconfig.test.js ├── library │ ├── suppress-exit-code.test.js │ ├── requestAgents.test.js │ ├── working-directory.test.js │ └── folder-variants.test.js └── .eslintrc ├── lib ├── index.js ├── config │ ├── process-env.js │ ├── rc-file.js │ └── index.js ├── reporters │ ├── json │ │ └── index.js │ ├── progress.js │ ├── emojitrain.js │ └── cli │ │ └── cli-utils-symbols.js └── node-version-check │ └── index.js ├── .gitattributes ├── .editorconfig ├── .github ├── dependabot.yml ├── ISSUE_TEMPLATE.md └── workflows │ ├── ci.yml │ └── codeql-analysis.yml ├── examples ├── reports │ └── sample-collection-report.xml ├── read-collection-from-file.js ├── ssl-client-cert-list.json ├── run-collections-in-directory.js ├── find-unique-urls-in-run.js ├── v1.postman_collection.json ├── sample-collection.json └── parallel-collection-runs.js ├── index.js ├── SECURITY.md ├── .dockerignore ├── codecov.yml ├── .gitignore ├── .npmignore ├── npm ├── create-release.js ├── test-lint.js ├── test-unit.js ├── test-library.js ├── test-cli.js ├── test-system.js └── docker-publish.sh ├── .nycrc.js ├── docker └── images │ ├── alpine │ ├── Dockerfile │ └── README.md │ └── ubuntu │ ├── README.md │ └── Dockerfile └── package.json /test/fixtures/files/outside.json: -------------------------------------------------------------------------------- 1 | {"some": "json-string"} 2 | -------------------------------------------------------------------------------- /test/fixtures/files/work-dir/test.json: -------------------------------------------------------------------------------- 1 | {"some": "json-string"} 2 | -------------------------------------------------------------------------------- /lib/index.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | run: require('./run') 3 | }; 4 | -------------------------------------------------------------------------------- /test/fixtures/run/spaces/data.json: -------------------------------------------------------------------------------- 1 | [{"key":"value"}, {"key": "value2"}] 2 | -------------------------------------------------------------------------------- /test/integration/tc4/upload-file.json: -------------------------------------------------------------------------------- 1 | { 2 | "key1":"value1", 3 | "key2": 2 4 | } -------------------------------------------------------------------------------- /test/fixtures/run/test-data.postman_data.json: -------------------------------------------------------------------------------- 1 | [{"key":"value"}, {"key": "value2"}] 2 | -------------------------------------------------------------------------------- /test/integration/custom-http-method/upload-file.csv: -------------------------------------------------------------------------------- 1 | key,val 2 | a,1 3 | b,2 4 | c,3 5 | -------------------------------------------------------------------------------- /test/integration/csv-with-bom/csv-with-bom.postman_data.csv: -------------------------------------------------------------------------------- 1 | c1, c2, c3 2 | "123", foo "bar" baz 3 | -------------------------------------------------------------------------------- /test/fixtures/ssl/client.p12: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/postmanlabs/newman/HEAD/test/fixtures/ssl/client.p12 -------------------------------------------------------------------------------- /test/integration/globals-env-data-files/globals-env-data-files.postman_data.json: -------------------------------------------------------------------------------- 1 | [{"dataVar":"dataValue","data":"DATA"}] 2 | -------------------------------------------------------------------------------- /test/integration/redirect-test/redirect-test.postman_config.json: -------------------------------------------------------------------------------- 1 | { 2 | "run": { 3 | "ignoreRedirects": true 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /lib/config/process-env.js: -------------------------------------------------------------------------------- 1 | var envConfig = {}; // todo: read NEWMAN_* variables from process.env 2 | 3 | module.exports = envConfig; 4 | -------------------------------------------------------------------------------- /test/integration/data-file-var-replacement/data-file-var-replacement.postman_data.json: -------------------------------------------------------------------------------- 1 | [{"dataVar":"value1"},{"dataVar":"value2"}] 2 | -------------------------------------------------------------------------------- /test/integration/v2-regression-tests/v2-regression-tests.postman_config.json: -------------------------------------------------------------------------------- 1 | { 2 | "run": { 3 | "insecure": true 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /test/fixtures/ssl/v3.ext: -------------------------------------------------------------------------------- 1 | basicConstraints=CA:FALSE 2 | nsComment = "OpenSSL Generated Certificate" 3 | subjectKeyIdentifier=hash 4 | authorityKeyIdentifier=keyid,issuer -------------------------------------------------------------------------------- /test/integration/steph/steph.postman_data.json: -------------------------------------------------------------------------------- 1 | [{"first": "sampleFirstName1", "last": "sampleLastName1"},{"first": "sampleFirstName2", "last": "sampleLastName2"}] 2 | -------------------------------------------------------------------------------- /test/integration/timeout/timeout.postman_config.json: -------------------------------------------------------------------------------- 1 | { 2 | "run": { 3 | "timeout": 10000, 4 | "timeoutRequest": 3000, 5 | "timeoutScript": 500 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Set the default behavior 2 | * text=auto 3 | 4 | # JavaScript files will always have LF line endings 5 | *.js text eol=lf 6 | 7 | # JSON files always have LF line endings 8 | *.json text eol=lf 9 | -------------------------------------------------------------------------------- /test/integration/bom-and-encoding/utf16-le-encoding-in-env.postman_environment.json: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/postmanlabs/newman/HEAD/test/integration/bom-and-encoding/utf16-le-encoding-in-env.postman_environment.json -------------------------------------------------------------------------------- /test/fixtures/run/simple-variables.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "globals", 3 | "values": [{ 4 | "key": "var-1", 5 | "value": "value-1" 6 | }, { 7 | "key": "var-2", 8 | "value": "value-2" 9 | }] 10 | } 11 | -------------------------------------------------------------------------------- /test/integration/inherited-entities/inherited-entities.postman_environment.json: -------------------------------------------------------------------------------- 1 | { 2 | "values": [{ 3 | "key": "env-var", 4 | "value": "environment value" 5 | }, { 6 | "key": "duplicate-var", 7 | "value": "correct" 8 | }] 9 | } 10 | -------------------------------------------------------------------------------- /test/fixtures/run/spaces/simple-variables.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "globals", 3 | "values": [{ 4 | "key": "var-1", 5 | "type": "any", 6 | "value": "value-1" 7 | }, { 8 | "key": "var-2", 9 | "type": "any", 10 | "value": "value-2" 11 | }] 12 | } 13 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # editorconfig.org 2 | root = true 3 | 4 | [*] 5 | indent_style = space 6 | indent_size = 4 7 | end_of_line = lf 8 | charset = utf-8 9 | max_length = 120 10 | trim_trailing_whitespace = true 11 | insert_final_newline = true 12 | 13 | [*.{json, yml, html, hbs}] 14 | indent_size = 2 15 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: "npm" 4 | directory: "/" 5 | schedule: 6 | interval: "weekly" 7 | day: "saturday" 8 | time: "03:14" 9 | timezone: Asia/Calcutta 10 | rebase-strategy: "disabled" 11 | open-pull-requests-limit: 10 12 | -------------------------------------------------------------------------------- /test/integration/comma-test-csv/comma-test-csv.postman_data.csv: -------------------------------------------------------------------------------- 1 | nameWithComma,nameWithDoubleQuotes,numberWithQuotes,numberWithoutQuotes,negativeNumberWithoutQuotes,nullValue,longNumber, spaceAfterComma ,spaceBeforeComma, nameWithUnescapedQuotes 2 | "Abhijit, Kane","Abhijit ""KDOS"" Kane","00123",7890,-7890,,"89111702272002019559", "foo" ,"bar", Abhijit "KDOS" Kane 3 | -------------------------------------------------------------------------------- /test/fixtures/overrides/env.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "f32a8f2f-bba8-4362-984b-a4c4857bb7a3", 3 | "name": "envTest", 4 | "values": [ 5 | { 6 | "key": "dummyVar", 7 | "value": "bar", 8 | "description": "", 9 | "enabled": false 10 | } 11 | ], 12 | "_postman_variable_scope": "environment", 13 | "_postman_exported_at": "2018-12-27T10:53:52.079Z", 14 | "_postman_exported_using": "Postman/6.6.1" 15 | } -------------------------------------------------------------------------------- /test/integration/timeout/timeout.postman_collection.json: -------------------------------------------------------------------------------- 1 | { 2 | "item": [{ 3 | "event": [{ 4 | "listen": "test", 5 | "script": { 6 | "type": "text/javascript", 7 | "exec": [ 8 | "var now = Date.now(),", 9 | " later = now + 300;", 10 | "while(Date.now() < later);" 11 | ] 12 | } 13 | }], 14 | "request": { 15 | "url": "https://postman-echo.com/delay/2", 16 | "method": "GET" 17 | } 18 | }] 19 | } 20 | -------------------------------------------------------------------------------- /examples/reports/sample-collection-report.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /test/fixtures/run/failed-request.json: -------------------------------------------------------------------------------- 1 | { 2 | "variables": [], 3 | "info": { 4 | "name": "failed-request", 5 | "_postman_id": "2ed7ced1-d834-f473-7d28-aa3a1a7d825f", 6 | "description": "A minimalistic collection with a failing request", 7 | "schema": "https://schema.getpostman.com/json/collection/v2.0.0/collection.json" 8 | }, 9 | "item": [ 10 | { 11 | "name": "Failed request", 12 | "request": { 13 | "url": "https://123.random.z/get", 14 | "method": "GET" 15 | } 16 | } 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /test/fixtures/ssl/SSL.md: -------------------------------------------------------------------------------- 1 | # About these certificates/keys 2 | 3 | These certs are merely used in unit tests. In case that a cert ever has to be regenerated, it can be achieved like this. 4 | All Keys have the passphrase 'password'. 5 | 6 | ## Generate a CSR from a private key 7 | 8 | `openssl req -new -key server.key -out server.csr` 9 | 10 | ## Sign the CSR with the CA 11 | 12 | `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` 13 | -------------------------------------------------------------------------------- /test/integration/esc-formdata/esc-formdata.postman_environment.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "e1e2f391-8c72-c7fe-89c7-d48761e90296", 3 | "name": "e1", 4 | "values": [ 5 | { 6 | "key": "msg", 7 | "value": "hello\\kworld", 8 | "type": "text", 9 | "name": "msg", 10 | "enabled": true 11 | }, 12 | { 13 | "key": "msg1", 14 | "value": "hello", 15 | "type": "text", 16 | "name": "msg", 17 | "enabled": true 18 | } 19 | ], 20 | "timestamp": 1441816736435, 21 | "synced": false, 22 | "syncedFilename": "" 23 | } -------------------------------------------------------------------------------- /examples/read-collection-from-file.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | /** 3 | * @fileOverview 4 | * This sample code illustrates how to read a collection JSON file in NodeJS and run it using Newman 5 | */ 6 | var newman = require('../'); // require('newman') 7 | 8 | // call newman.run to pass `options` object and wait for callback 9 | newman.run({ 10 | collection: require('./sample-collection.json'), 11 | reporters: 'cli' 12 | }, function (err) { 13 | if (err) { throw err; } 14 | console.info('collection run complete!'); 15 | }); 16 | -------------------------------------------------------------------------------- /examples/ssl-client-cert-list.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "domain1", 4 | "matches": ["https://test.domain1.com/*", "https://www.domain1/*"], 5 | "key": {"src": "./client.domain1.key"}, 6 | "cert": {"src": "./client.domain1.crt"}, 7 | "passphrase": "changeme" 8 | }, 9 | { 10 | "name": "domain2", 11 | "matches": ["https://domain2.com/*"], 12 | "key": {"src": "./client.domain2.key"}, 13 | "cert": {"src": "./client.domain2.crt"}, 14 | "passphrase": "changeme" 15 | } 16 | ] 17 | -------------------------------------------------------------------------------- /test/fixtures/run/spaces/simple-cookie-jar.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "tough-cookie@4.1.3-postman.1", 3 | "storeType": "MemoryCookieStore", 4 | "allowSpecialUseDomain": true, 5 | "rejectPublicSuffixes": true, 6 | "enableLooseMode": false, 7 | "prefixSecurity": "silent", 8 | "cookies": [ 9 | { 10 | "key": "foo2", 11 | "value": "baz", 12 | "domain": "postman-echo.com", 13 | "path": "/", 14 | "hostOnly": true, 15 | "creation": "2020-06-09T16:57:46.999Z", 16 | "lastAccessed": "2020-06-09T16:57:48.385Z" 17 | } 18 | ] 19 | } 20 | -------------------------------------------------------------------------------- /test/integration/data-file-var-replacement/data-file-var-replacement.postman_environment.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "426c4896-2d5b-80b8-da5d-ac205502f3c0", 3 | "name": "testEnv", 4 | "values": [ 5 | { 6 | "key": "envKey", 7 | "value": "sampleKey", 8 | "type": "text", 9 | "name": "envKey", 10 | "enabled": true 11 | }, 12 | { 13 | "key": "envFileUrl", 14 | "value": "postman-echo.com", 15 | "type": "text", 16 | "name": "envFileUrl", 17 | "enabled": true 18 | } 19 | ], 20 | "timestamp": 1404119927461, 21 | "synced": false, 22 | "syncedFilename": "" 23 | } 24 | -------------------------------------------------------------------------------- /test/fixtures/ssl/sslClientCertList.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "client1", 4 | "matches": ["https://localhost:3001", "https://localhost:3001/*"], 5 | "key": {"src": "./test/fixtures/ssl/client2.key"}, 6 | "cert": {"src": "./test/fixtures/ssl/client2.crt"}, 7 | "passphrase": "password" 8 | }, 9 | { 10 | "name": "client2", 11 | "matches": ["https://localhost:3002", "https://localhost:3002/*"], 12 | "key": {"src": "./test/fixtures/ssl/client3.key"}, 13 | "cert": {"src": "./test/fixtures/ssl/client3.crt"}, 14 | "passphrase": "password" 15 | } 16 | ] 17 | -------------------------------------------------------------------------------- /test/fixtures/files/ssl-client-cert-config.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "client1", 4 | "matches": ["https://localhost:3001", "https://localhost:3001/*"], 5 | "key": {"src": "./test/fixtures/ssl/client2.key"}, 6 | "cert": {"src": "./test/fixtures/ssl/client2.crt"}, 7 | "passphrase": "password" 8 | }, 9 | { 10 | "name": "client2", 11 | "matches": ["https://localhost:3002", "https://localhost:3002/*"], 12 | "key": {"src": "./test/fixtures/ssl/client3.key"}, 13 | "cert": {"src": "./test/fixtures/ssl/client3.crt"}, 14 | "passphrase": "password" 15 | } 16 | ] 17 | -------------------------------------------------------------------------------- /test/integration/bom-and-encoding/bom-in-environment-file.postman_environment.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "043ddbc2-1fbb-242f-9c39-dc89e08d4a65", 3 | "name": "Variable names with slashes", 4 | "values": [ 5 | { 6 | "key": "fo/o", 7 | "type": "text", 8 | "value": "alpha", 9 | "enabled": true 10 | }, 11 | { 12 | "key": "b\\ar", 13 | "type": "text", 14 | "value": "beta", 15 | "enabled": true 16 | } 17 | ], 18 | "timestamp": 1473255725612, 19 | "_postman_variable_scope": "environment", 20 | "_postman_exported_at": "2016-09-07T13:43:25.578Z", 21 | "_postman_exported_using": "Postman/4.7.0" 22 | } -------------------------------------------------------------------------------- /test/integration/slashed-variable-names/slashed-variable-names.postman_environment.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "043ddbc2-1fbb-242f-9c39-dc89e08d4a65", 3 | "name": "Variable names with slashes", 4 | "values": [ 5 | { 6 | "key": "fo/o", 7 | "type": "text", 8 | "value": "alpha", 9 | "enabled": true 10 | }, 11 | { 12 | "key": "b\\ar", 13 | "type": "text", 14 | "value": "beta", 15 | "enabled": true 16 | } 17 | ], 18 | "timestamp": 1473255725612, 19 | "_postman_variable_scope": "environment", 20 | "_postman_exported_at": "2016-09-07T13:43:25.578Z", 21 | "_postman_exported_using": "Postman/4.7.0" 22 | } -------------------------------------------------------------------------------- /test/fixtures/run/single-get-request.json: -------------------------------------------------------------------------------- 1 | { 2 | "info": { 3 | "name": "Example Collection with a single GET request", 4 | "schema": "https://schema.getpostman.com/json/collection/v2.0.0/collection.json" 5 | }, 6 | 7 | "item": [{ 8 | "name": "A simple GET request", 9 | "event": [{ 10 | "listen": "test", 11 | "script": { 12 | "type": "text/javascript", 13 | "exec": ["tests['response code is 200'] = (responseCode.code === 200);"] 14 | } 15 | }], 16 | "request": { 17 | "url": "https://postman-echo.com/get?source=newman-sample-github-collection", 18 | "method": "GET" 19 | } 20 | }] 21 | } 22 | -------------------------------------------------------------------------------- /test/fixtures/ssl/config.cnf: -------------------------------------------------------------------------------- 1 | [ req ] 2 | default_bits = 1024 3 | days = 3650 4 | distinguished_name = req_distinguished_name 5 | attributes = req_attributes 6 | prompt = no 7 | output_password = password 8 | 9 | [ req_distinguished_name ] 10 | C = US 11 | ST = CA 12 | L = SF 13 | O = Postman 14 | OU = postman@localhost 15 | CN = TestClient 16 | emailAddress = do.not@email.me 17 | 18 | [ req_attributes ] 19 | challengePassword = password challenge 20 | 21 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | /**! 2 | * @license Copyright 2016 Postdot Technologies, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on 11 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and limitations under the License. 13 | */ 14 | module.exports = require('./lib'); 15 | -------------------------------------------------------------------------------- /test/cli/cli-reporter-show-timestamp.test.js: -------------------------------------------------------------------------------- 1 | const expect = require('chai').expect; 2 | 3 | describe('CLI reporter logging timestamp', function () { 4 | const timeRegex = /([01]?[0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9]/; 5 | 6 | it('should log timestamp', function (done) { 7 | exec('node ./bin/newman.js run test/fixtures/run/single-get-request.json --reporter-cli-show-timestamps', 8 | function (code, stdout, stderr) { 9 | expect(code, 'should have exit code of 0').to.equal(0); 10 | expect(stderr).to.be.empty; 11 | expect(stdout).to.match(timeRegex); 12 | 13 | done(code); 14 | }); 15 | }); 16 | }); 17 | -------------------------------------------------------------------------------- /test/integration/disabled-and-duplicate-variables/disabled-and-duplicates.postman_environment.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "466fce1f-6998-4513-8001-74481c37a7ee", 3 | "name": "disabled-and-duplicates", 4 | "values": [ 5 | { 6 | "key": "justDisabled", 7 | "value": "1", 8 | "disabled": true 9 | }, 10 | { 11 | "key": "oneDisabled", 12 | "value": "1" 13 | }, 14 | { 15 | "key": "oneDisabled", 16 | "value": "2", 17 | "disabled": true 18 | }, 19 | { 20 | "key": "duplicate", 21 | "value": "1", 22 | "type": "text" 23 | }, 24 | { 25 | "key": "duplicate", 26 | "value": "2", 27 | "type": "text" 28 | } 29 | ], 30 | "_postman_variable_scope": "environment" 31 | } 32 | -------------------------------------------------------------------------------- /test/integration/csv-with-bom/csv-with-bom.postman_collection.json: -------------------------------------------------------------------------------- 1 | { 2 | "info": { 3 | "name": "CSV with BOM", 4 | "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json" 5 | }, 6 | "item": [{ 7 | "event": [{ 8 | "listen": "prerequest", 9 | "script": { 10 | "exec": [ 11 | "pm.test(\"CSV parsing tests\", function () {", 12 | " pm.expect(data.c1).to.eql('123');", 13 | " pm.expect(data.c2).to.eql('foo \"bar\" baz');", 14 | " pm.expect(data.c3).to.be.undefined;", 15 | "});" 16 | ], 17 | "type": "text/javascript" 18 | } 19 | }], 20 | "request": "postman-echo.com/get" 21 | }] 22 | } 23 | -------------------------------------------------------------------------------- /test/integration/v2-regression-tests/v2-regression-tests.postman_environment.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "03975311-f395-4eb9-91d8-0a15906bdccc", 3 | "name": "regression-tests", 4 | "values": [ 5 | { 6 | "key": "envKey", 7 | "value": "sampleKey", 8 | "type": "text", 9 | "name": "envKey", 10 | "enabled": true 11 | }, 12 | { 13 | "key": "envFileUrl", 14 | "value": "postman-echo.com", 15 | "type": "text", 16 | "name": "envFileUrl", 17 | "enabled": true 18 | }, 19 | { 20 | "key": "dataVar2", 21 | "type": "text", 22 | "value": "1", 23 | "enabled": true 24 | } 25 | ], 26 | "timestamp": 1470909317305, 27 | "synced": false, 28 | "syncedFilename": "", 29 | "team": null, 30 | "isDeleted": false 31 | } 32 | -------------------------------------------------------------------------------- /test/fixtures/run/single-request-failing.json: -------------------------------------------------------------------------------- 1 | { 2 | "info": { 3 | "name": "Example Collection with Failing Tests", 4 | "description": "This collection is to illustrate how a typical collection having failing tests run on Newman", 5 | "schema": "https://schema.getpostman.com/json/collection/v2.0.0/collection.json" 6 | }, 7 | 8 | "item": [{ 9 | "name": "Status Code Test", 10 | "description": "Request that returns 404, but test expects 200 status code", 11 | "event": [{ 12 | "listen": "test", 13 | "script": { 14 | "type": "text/javascript", 15 | "exec": ["tests['response code is 200'] = (responseCode.code === 200);"] 16 | } 17 | }], 18 | "request": { 19 | "url": "https://postman-echo.com/status/404", 20 | "method": "GET" 21 | } 22 | }] 23 | } 24 | -------------------------------------------------------------------------------- /lib/reporters/json/index.js: -------------------------------------------------------------------------------- 1 | var _ = require('lodash'); 2 | 3 | /** 4 | * Reporter that simply dumps the summary object to file (default: newman-run-report.json). 5 | * 6 | * @param {Object} newman - The collection run object, with event hooks for reporting run details. 7 | * @param {Object} options - A set of collection run options. 8 | * @param {String} options.export - The path to which the summary object must be written. 9 | * @returns {*} 10 | */ 11 | module.exports = function (newman, options) { 12 | newman.on('beforeDone', function (err, o) { 13 | if (err) { return; } 14 | 15 | newman.exports.push({ 16 | name: 'json-reporter', 17 | default: 'newman-run-report.json', 18 | path: options.export, 19 | content: JSON.stringify(_.omit(o.summary, 'exports'), 0, 2) 20 | }); 21 | }); 22 | }; 23 | -------------------------------------------------------------------------------- /test/unit/externalReporter.test.js: -------------------------------------------------------------------------------- 1 | const sinon = require('sinon'), 2 | expect = require('chai').expect, 3 | newman = require('../../'); 4 | 5 | describe('External reporter', function () { 6 | beforeEach(function () { 7 | sinon.replace(console, 'warn', sinon.fake()); 8 | }); 9 | 10 | afterEach(function () { 11 | sinon.restore(); 12 | }); 13 | 14 | it('warns when not found', function (done) { 15 | newman.run({ 16 | collection: 'test/fixtures/run/single-get-request.json', 17 | reporters: ['unknownreporter'] 18 | }, function (err) { 19 | expect(err).to.be.null; 20 | expect(console.warn.called).to.be.true; 21 | expect(console.warn.calledWith('newman: could not find "unknownreporter" reporter')).to.be.true; 22 | 23 | done(); 24 | }); 25 | }); 26 | }); 27 | -------------------------------------------------------------------------------- /test/cli/cli-reporter-failure-details.test.js: -------------------------------------------------------------------------------- 1 | const expect = require('chai').expect; 2 | 3 | describe('CLI reporter failure details', function () { 4 | it('should correctly show complete details for the failure list', function (done) { 5 | // eslint-disable-next-line max-len 6 | 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) { 7 | expect(code).be.ok; 8 | expect(stderr).to.be.empty; 9 | expect(stdout).to.contain('1. AssertionError response code is 200'); 10 | expect(stdout).to.contain('expected false to be truthy'); 11 | expect(stdout).to.contain('at assertion:0 in test-script'); 12 | expect(stdout).to.contain('inside "Status Code Test"'); 13 | 14 | done(); 15 | }); 16 | }); 17 | }); 18 | -------------------------------------------------------------------------------- /test/fixtures/run/spaces/single-get-request.json: -------------------------------------------------------------------------------- 1 | { 2 | "info": { 3 | "name": "Example Collection with a single GET request", 4 | "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json" 5 | }, 6 | 7 | "item": [{ 8 | "name": "A simple GET request", 9 | "event": [{ 10 | "listen": "test", 11 | "script": { 12 | "type": "text/javascript", 13 | "exec": ["tests['response code is 200'] = (responseCode.code === 200);"] 14 | } 15 | }], 16 | "request": { 17 | "url": { 18 | "host": [ 19 | "postman-echo", 20 | "com" 21 | ], 22 | "path": ["get"], 23 | "protocol": "https", 24 | "query": [{ 25 | "key": "source", 26 | "value": "newman-sample-github-collection" 27 | }], 28 | "variable": [] 29 | }, 30 | "method": "GET" 31 | } 32 | }] 33 | } 34 | -------------------------------------------------------------------------------- /test/integration/bom-and-encoding/bom-in-environment-file.postman_collection.json: -------------------------------------------------------------------------------- 1 | { 2 | "info": { 3 | "name": "Example Collection with a single GET request", 4 | "schema": "https://schema.getpostman.com/json/collection/v2.0.0/collection.json" 5 | }, 6 | "item": [{ 7 | "name": "A simple GET request", 8 | "event": [{ 9 | "listen": "test", 10 | "script": { 11 | "type": "text/javascript", 12 | "exec": [ 13 | "pm.test('expect response be 200', function () {", 14 | " pm.response.to.be.ok", 15 | "})", 16 | "pm.test('Response Body', function () {", 17 | " var jsonData = pm.response.json();", 18 | " pm.expect(jsonData.args).to.have.property('var', 'alpha')", 19 | "});" 20 | ] 21 | } 22 | }], 23 | "request": { 24 | "url": "https://postman-echo.com/get?var={{fo/o}}", 25 | "method": "GET" 26 | } 27 | }] 28 | } 29 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Reporting a Vulnerability 4 | 5 | If 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. 6 | 7 | If you are a security researcher, please go through the following points for reporting security issues. 8 | 9 | - Mail to security@postman.com and express interest along with a short summary of the nature of issue you want to report. 10 | - We will triage and add your email address to our internal security tracker. 11 | - Subsequently you can report your security issues directly using the tracker. 12 | 13 | 14 | > Read our [security reporting guidelines and policy](https://www.postman.com/vulnerability-reporting) for more details. 15 | -------------------------------------------------------------------------------- /lib/node-version-check/index.js: -------------------------------------------------------------------------------- 1 | var semver = require('semver'), 2 | colors = require('colors/safe'), 3 | pkg = require('../../package.json'), 4 | 5 | /** 6 | * The required node version from package.json. 7 | * 8 | * @type {String} 9 | * @readOnly 10 | */ 11 | requiredNodeVersion = pkg && pkg.engines && pkg.engines.node, 12 | 13 | /** 14 | * The current node version as detected from running process. 15 | * 16 | * @type {String} 17 | * @readOnly 18 | */ 19 | currentNodeVersion = process && process.version; 20 | 21 | // if either current or required version is not detected, we bail out 22 | if (!(requiredNodeVersion && currentNodeVersion)) { 23 | return; 24 | } 25 | 26 | // we check semver satisfaction and throw error on mismatch 27 | if (!semver.satisfies(currentNodeVersion, requiredNodeVersion)) { 28 | console.error([colors.red('newman:'), 'required node version', requiredNodeVersion].join(' ')); 29 | process.exit(1); 30 | } 31 | -------------------------------------------------------------------------------- /test/integration/redirect-test/redirect-test.postman_collection.json: -------------------------------------------------------------------------------- 1 | { 2 | "variables": [], 3 | "info": { 4 | "name": "redirectTest", 5 | "_postman_id": "be3bf661-9803-6712-5f8e-ff5fcf1ba5db", 6 | "description": "A test to check for proper redirection responses", 7 | "schema": "https://schema.getpostman.com/json/collection/v2.0.0/collection.json" 8 | }, 9 | "item": [ 10 | { 11 | "name": "r1", 12 | "event": [ 13 | { 14 | "listen": "test", 15 | "script": { 16 | "type": "text/javascript", 17 | "exec": "return 0; tests[\"Returned 302\"] = responseCode.code===302;" 18 | } 19 | } 20 | ], 21 | "request": { 22 | "url": "https://postman-echo.com/redirect-to?url=https://postman-echo.com/get", 23 | "method": "GET", 24 | "header": [], 25 | "body": { 26 | "mode": "formdata", 27 | "formdata": [] 28 | }, 29 | "description": "" 30 | }, 31 | "response": [] 32 | } 33 | ] 34 | } 35 | -------------------------------------------------------------------------------- /test/fixtures/ssl/client2.csr: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE REQUEST----- 2 | MIICpzCCAY8CAQAwYjELMAkGA1UEBhMCQVUxDDAKBgNVBAgMA05TVzEPMA0GA1UE 3 | BwwGU3lkbmV5MQ8wDQYDVQQKDAZOZXdtYW4xDTALBgNVBAsMBFRlc3QxFDASBgNV 4 | BAMMC3Rlc3QubmV3bWFuMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA 5 | r4gQ2xdoRvKgRzd49uh3WPud/I+npx8QpjkWJVsLVQuWVOCKTMaspVqWLwPZFt05 6 | +wCAUWompX6OI7vqd9nyZkd1odKsHQs1HY3JDlnN3FsLx305+I4QKrPs4NsoqT0U 7 | 5MQ58bZYALS9VOs0ISndq3hMhv7SZKU8bITdeMbJodmEEYerXWvs5qmJ5y7q5nYN 8 | HuHzGmKIxjAsiFzNSL5jv6nNfK41WMgrhlJIsO/jqfYG5S32JJKQY163A4hUJT6C 9 | KJ39QanQZc2d7V+XxiRIquvHwkSRYolEjVHwRvFGQvJRd2D2iVhxaHKC1HQwHefA 10 | 1DM2TYY+wCP1JYlPQeta2wIDAQABoAAwDQYJKoZIhvcNAQELBQADggEBAD0k7TMy 11 | ycno+mUDwpn6MhNTF0BjtOfZWQA0esLY7VCooBXUsUPLj6Vt4l4zhoYrDPeHnEet 12 | LcxMU/MKSmNJJ/M+dEqBJfgw9Z0I7OXa4xNWbJMmkPl6lf1Jiz1aUHzYSD0wXp7r 13 | Q3VYT5uvhBJnmeqOB4syYRRQzOdm7Fr/Vn0btIf+f6bsfCx2OMePPBzSXRorpSFH 14 | zZj/UoUDlexDtNKhmnpYBvF/z4Uy+5PKq1pM0cQvZg3EmRwEmtQ+LepfK6DpXveE 15 | /qev24BOxsUsXmwmDDr39HdOcHp7+mwuyQGSMKc21sod7dfBENg6YAlXN4sq7j+T 16 | RI3x8JX4Qg4AsKM= 17 | -----END CERTIFICATE REQUEST----- 18 | -------------------------------------------------------------------------------- /test/fixtures/ssl/server2.csr: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE REQUEST----- 2 | MIICqTCCAZECAQAwZDELMAkGA1UEBhMCQVUxDDAKBgNVBAgMA05TVzEPMA0GA1UE 3 | BwwGU3lkbmV5MQ8wDQYDVQQKDAZOZXdtYW4xDTALBgNVBAsMBFRlc3QxFjAUBgNV 4 | BAMMDXRlc3Quc2VydmVyLjIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB 5 | AQDUJXMCLksQYalgI1pp/gssebeyeiNklhknHpLF2YnqCA1rofX5F7zGVSaLxhGb 6 | a0UsELoBmNMGTWmTc7dPY+W/Kt+FTjcNDdSJcbWi5rKvHz8IgX6xXGSNSzcjnAl7 7 | eeUbb1eMQNmKDIDV0m961QyuGtbz6yUZAV35yxxZnMwMxtzE2lGNuxsCpBlEbVeO 8 | QveanISpMUn0hOsbRNPLnJNyksARzpI/Uza4QTV8+GH3x+Ftd2d0sCRxR+rdPOae 9 | jPh7OZvZ0G9sCxS5h4Ju3K3Dw5wP/mUhTH3REbw+ALrZqCdi7E6jYwUmi6aWIkdq 10 | TJbFLleqsGhUckbiqz0DHHUPAgMBAAGgADANBgkqhkiG9w0BAQsFAAOCAQEAgCr1 11 | HSrRfEds6G930flXxJBPby+hNElnBtMqvTfuzdGYtY+bJa5uE1AEPm+h+wPUPFWN 12 | WUrEuzHpyI3fk2PW+HTz+vwkNFIKJSJac9fhwH7Eu2N2Dy32EPNRTSLERY6ZqNrp 13 | ivWGwTzjFdSdFGQOjd+LNY5X5BKQ0ai+XDMCbovsBjC9k+mydZQS9ttbms8KViPn 14 | UQVBuNv9vx9/iKoS2cGdqRkeUMAh1U7IPdHYbRorV9tslZO+Ya32Ua15oDjrE3nh 15 | /RyAta3n3FrtwZpO/i/Fgq/btF8mBsUpzZzjPRC8EXE8JWHkbAQdZCePW146qx8q 16 | kweggGc9RXHhpjx6FQ== 17 | -----END CERTIFICATE REQUEST----- 18 | -------------------------------------------------------------------------------- /test/integration/newman-gzip-test.postman_collection.json: -------------------------------------------------------------------------------- 1 | { 2 | "variables": [], 3 | "info": { 4 | "name": "gzip-encoded responses", 5 | "_postman_id": "af5052df-c60d-be62-d098-65b00b03a944", 6 | "description": "A test to check for the correct handling of gzip encoding", 7 | "schema": "https://schema.getpostman.com/json/collection/v2.0.0/collection.json" 8 | }, 9 | "item": [ 10 | { 11 | "name": "https://postman-echo.com/gzip", 12 | "event": [ 13 | { 14 | "listen": "test", 15 | "script": { 16 | "type": "text/javascript", 17 | "exec": "var res = JSON.parse(responseBody); tests['newman handles gzip properly'] = res.gzipped" 18 | } 19 | } 20 | ], 21 | "request": { 22 | "url": "https://postman-echo.com/gzip", 23 | "method": "GET", 24 | "header": [], 25 | "body": { 26 | "mode": "formdata", 27 | "formdata": [] 28 | }, 29 | "description": "" 30 | }, 31 | "response": [] 32 | } 33 | ] 34 | } 35 | -------------------------------------------------------------------------------- /test/system/npm-publish.test.js: -------------------------------------------------------------------------------- 1 | const expect = require('chai').expect, 2 | // eslint-disable-next-line security/detect-child-process 3 | exec = require('child_process').execSync; 4 | 5 | describe('npm publish', function () { 6 | const stdout = exec('npm pack --dry-run --json').toString(), 7 | packageInfo = JSON.parse(stdout.substring(stdout.indexOf('[')))[0], 8 | packagedFiles = packageInfo.files.map(function (file) { return file.path; }); 9 | 10 | it('should have a valid package name', function () { 11 | expect(packageInfo.name).to.equal('newman'); 12 | }); 13 | 14 | it('should not publish unnecessary files', function () { 15 | const allowedFiles = ['index.js', 'package.json', 'LICENSE.md', 16 | 'README.md', 'CHANGELOG.yaml', 'MIGRATION.md', 'SECURITY.md']; 17 | 18 | packagedFiles.forEach(function (path) { 19 | expect(allowedFiles.includes(path) || path.startsWith('lib/') || 20 | path.startsWith('bin/') || path.startsWith('docker/')).to.be.true; 21 | }); 22 | }); 23 | }); 24 | -------------------------------------------------------------------------------- /test/integration/bom-and-encoding/utf16-le-encoding-in-env.postman_collection.json: -------------------------------------------------------------------------------- 1 | { 2 | "info": { 3 | "name": "Sample Postman Collection", 4 | "schema": "https://schema.getpostman.com/json/collection/v2.0.0/collection.json", 5 | "description": "A sample collection to demonstrate collections as a set of related requests" 6 | }, 7 | 8 | "item": [{ 9 | "name": "A simple GET request", 10 | "event": [{ 11 | "listen": "test", 12 | "script": { 13 | "type": "text/javascript", 14 | "exec": [ 15 | "pm.test('expect response be 200', function () {", 16 | " pm.response.to.be.ok", 17 | "})", 18 | "pm.test('Response Body', function () {", 19 | " var jsonData = pm.response.json();", 20 | " pm.expect(jsonData.args).to.have.property('serviceHostName', 'localhost')", 21 | "});" 22 | ] 23 | } 24 | }], 25 | "request": { 26 | "url": "https://postman-echo.com/get?serviceHostName={{serviceHostName}}", 27 | "method": "GET" 28 | } 29 | }] 30 | } 31 | -------------------------------------------------------------------------------- /test/integration/globals-env-data-files/globals-env-data-files.postman_globals.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "key": "full_global_url", 4 | "value": "https://postman-echo.com/get", 5 | "type": "text", 6 | "name": "full_global_url", 7 | "enabled": true 8 | }, 9 | { 10 | "key": "global_resource_get", 11 | "value": "/get", 12 | "type": "text", 13 | "name": "global_resource_get", 14 | "enabled": true 15 | }, 16 | { 17 | "key": "Global Foo", 18 | "value": "Global Bar", 19 | "type": "text", 20 | "name": "Global Foo", 21 | "enabled": true 22 | }, 23 | { 24 | "key": "Global Phew", 25 | "value": "Global Works", 26 | "type": "text", 27 | "name": "Global Phew", 28 | "enabled": true 29 | }, 30 | { 31 | "key": "global", 32 | "value": "global1", 33 | "type": "text", 34 | "name": "global", 35 | "enabled": true 36 | }, 37 | { 38 | "key": "env", 39 | "value": "global1", 40 | "type": "text", 41 | "name": "env", 42 | "enabled": true 43 | }, 44 | { 45 | "key": "data", 46 | "value": "global1", 47 | "type": "text", 48 | "name": "data", 49 | "enabled": true 50 | } 51 | ] 52 | -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | # PLATFORM 2 | # ======== 3 | # All exclusions that are specific to the NPM, GIT, IDE and Operating Systems. 4 | 5 | # - Do not allow installed node modules to be committed. Doing `npm install -d` will bring them in root or other places. 6 | node_modules 7 | 8 | # - Do not commit any log file from anywhere 9 | *.log 10 | *.log.* 11 | 12 | # - Prevent addition of OS specific file explorer files 13 | Thumbs.db 14 | .DS_Store 15 | 16 | # Prevent IDE stuff 17 | .idea 18 | .vscode 19 | 20 | # PROJECT 21 | # ======= 22 | # Configuration pertaining to project specific repository structure. 23 | 24 | # - Prevent Sublime text IDE files from being committed to repository 25 | *.sublime-* 26 | 27 | # - Allow sublime text project file to be committed in the development directory. 28 | !/develop/*.sublime-project 29 | 30 | # - Prevent CI output files from being Added 31 | /out/ 32 | /newman/ 33 | 34 | # - Prevent diff backups from SourceTree from showing as commit. 35 | *.BACKUP.* 36 | *.BASE.* 37 | *.LOCAL.* 38 | *.REMOTE.* 39 | *.orig 40 | 41 | # Prevent unit test coverage reports from being added 42 | .coverage -------------------------------------------------------------------------------- /test/fixtures/run/undefined-test-checks.json: -------------------------------------------------------------------------------- 1 | { 2 | "variables": [], 3 | "info": { 4 | "name": "undefined-test-checks", 5 | "_postman_id": "2ed7ced1-d834-f473-7d28-aa3a1a7d825f", 6 | "description": "A minimalistic collection to ensure that test cases with undefined values do not get ignored.", 7 | "schema": "https://schema.getpostman.com/json/collection/v2.0.0/collection.json" 8 | }, 9 | "item": [ 10 | { 11 | "name": "Simple Echo/get request", 12 | "event": [ 13 | { 14 | "listen": "test", 15 | "script": { 16 | "type": "text/javascript", 17 | "exec": [ 18 | "var body = JSON.parse(responseBody);", 19 | "", 20 | "tests[\"Status code is 200\"] = responseCode.code === 200;", 21 | "tests[\"This test should pass\"] = body.url;", 22 | "tests[\"This test should fail\"] = body.random_unknown_property;" 23 | ] 24 | } 25 | } 26 | ], 27 | "request": { 28 | "url": "https://postman-echo.com/get", 29 | "method": "GET", 30 | "header": [], 31 | "body": {}, 32 | "description": "" 33 | }, 34 | "response": [] 35 | } 36 | ] 37 | } -------------------------------------------------------------------------------- /test/integration/globals-env-data-files/globals-env-data-files.postman_environment.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "426c4896-2d5b-80b8-da5d-ac205502f3c0", 3 | "name": "testEnv", 4 | "values": [ 5 | { 6 | "key": "hKey", 7 | "value": "sampleKey", 8 | "type": "text", 9 | "name": "hKey", 10 | "enabled": true 11 | }, 12 | { 13 | "key": "hburl", 14 | "value": "posts", 15 | "type": "text", 16 | "name": "hburl", 17 | "enabled": true 18 | }, 19 | { 20 | "key": "tempKey", 21 | "value": "sampleKey2", 22 | "type": "text", 23 | "name": "tempKey", 24 | "enabled": true 25 | }, 26 | { 27 | "key": "url", 28 | "value": "https://postman-echo.com", 29 | "type": "text", 30 | "name": "url", 31 | "enabled": true 32 | }, 33 | { 34 | "key": "env", 35 | "value": "env2", 36 | "type": "text", 37 | "name": "env", 38 | "enabled": true 39 | }, 40 | { 41 | "key": "data", 42 | "value": "env2", 43 | "type": "text", 44 | "name": "data", 45 | "enabled": true 46 | } 47 | ], 48 | "timestamp": 1405183029928, 49 | "synced": false, 50 | "syncedFilename": "" 51 | } 52 | -------------------------------------------------------------------------------- /codecov.yml: -------------------------------------------------------------------------------- 1 | coverage: 2 | range: 70..100 # green if 100+, red if 70- 3 | 4 | status: 5 | patch: 6 | # coverage status for pull request diff 7 | default: 8 | target: 100 # any patch should be 100% covered 9 | threshold: 1% # allow a little drop 10 | 11 | project: 12 | # coverage status for whole project 13 | default: 14 | target: auto # use coverage of base commit as target 15 | threshold: 1% # allow a little drop 16 | 17 | # coverage status for unit tests 18 | unit: 19 | target: 75 20 | flags: 21 | - unit 22 | 23 | # coverage status for integration tests 24 | integration: 25 | target: 50 26 | flags: 27 | - integration 28 | 29 | # coverage status for cli tests 30 | cli: 31 | target: 80 32 | flags: 33 | - cli 34 | 35 | # coverage status for library tests 36 | library: 37 | target: 65 38 | flags: 39 | - library 40 | 41 | parsers: 42 | javascript: 43 | enable_partials: yes # use partial line coverage 44 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # PLATFORM 2 | # ======== 3 | # All exclusions that are specific to the NPM, GIT, IDE and Operating Systems. 4 | 5 | # - Do not allow installed node modules to be committed. Doing `npm install -d` will bring them in root or other places. 6 | node_modules 7 | 8 | # - Do not commit any log file from anywhere 9 | *.log 10 | *.log.* 11 | 12 | # - Prevent addition of OS specific file explorer files 13 | Thumbs.db 14 | .DS_Store 15 | 16 | # Prevent IDE stuff 17 | .idea 18 | .vscode 19 | 20 | # PROJECT 21 | # ======= 22 | # Configuration pertaining to project specific repository structure. 23 | 24 | # - Prevent Sublime text IDE files from being committed to repository 25 | *.sublime-* 26 | 27 | # - Allow sublime text project file to be committed in the development directory. 28 | !/develop/*.sublime-project 29 | 30 | # - Prevent CI output files from being Added 31 | /out/ 32 | /newman/ 33 | 34 | # - Prevent diff backups from SourceTree from showing as commit. 35 | *.BACKUP.* 36 | *.BASE.* 37 | *.LOCAL.* 38 | *.REMOTE.* 39 | *.orig 40 | 41 | # - Prevent unit test coverage reports from being committed to the repository 42 | .coverage 43 | .nyc_output 44 | -------------------------------------------------------------------------------- /test/library/suppress-exit-code.test.js: -------------------------------------------------------------------------------- 1 | const expect = require('chai').expect, 2 | newman = require('../../'); 3 | 4 | describe('newman.run suppressExitCode', function () { 5 | it('should accept the suppressExitCode parameter', function (done) { 6 | newman.run({ 7 | collection: 'test/fixtures/run/single-get-request.json', 8 | suppressExitCode: true 9 | }, done); 10 | }); 11 | 12 | it('should fail if suppressExitCode parameter is absent on a failing collection', function (done) { 13 | newman.run({ 14 | collection: 'test/fixtures/run/single-request-failing.json' 15 | }, function (err, summary) { 16 | expect(err).to.be.null; 17 | expect(summary.run.failures, 'should have 1 failure').to.have.lengthOf(1); 18 | done(); 19 | }); 20 | }); 21 | 22 | it('should not fail if suppressExitCode parameter is present on a failing collection', function (done) { 23 | newman.run({ 24 | collection: 'test/fixtures/run/single-request-failing.json', 25 | suppressExitCode: true 26 | }, done); 27 | }); 28 | }); 29 | -------------------------------------------------------------------------------- /test/fixtures/ssl/client3.csr: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE REQUEST----- 2 | MIIC8zCCAdsCAQAwgYoxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTELMAkGA1UE 3 | BwwCU0YxEDAOBgNVBAoMB1Bvc3RtYW4xGjAYBgNVBAsMEXBvc3RtYW5AbG9jYWxo 4 | b3N0MRMwEQYDVQQDDApUZXN0Q2xpZW50MR4wHAYJKoZIhvcNAQkBFg9kby5ub3RA 5 | ZW1haWwubWUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCzcjMkydtC 6 | ONIkKMT8S67GrtEFnfXr4zu/fpWeaBiQBfAzzoKSXwxJlhJJET16THOzFDE2Gz09 7 | r3fEUk9b/XsIbhJEORqAJqkVFrd+d/pzDgOy9bXb8NyfDPu2lIFv0oDUhTxz9AEO 8 | PFj4fsEtB+YZ+TgKK7JvJegSyhgzJ0VTVnoy80ohZ8Wg87a2fEu7JOIUjMB3Yunv 9 | uYi4sSN+DamZycWl6Z3nnOuCqL44t4mPFCoKiJKiD3/jkfMMUR7xLlr7+VoGOx0b 10 | e6U+8Zu5Bu8v4sO20QiWd4ewqeVP/Pp/tgT59Mqlz6vIIaeAVWKXiUBuSOAM0M6Q 11 | sSyGKglyYxYLAgMBAAGgIzAhBgkqhkiG9w0BCQcxFAwScGFzc3dvcmQgY2hhbGxl 12 | bmdlMA0GCSqGSIb3DQEBCwUAA4IBAQASL8p0lXvb9moVT5Tk0iiiIib1Z6rL94Vk 13 | WaP6T6b8E6pubdjPs6sz0rCjuJrYNhKZo6OAGnZSOxy62xivsn82T9ahbg0HQMah 14 | CFqImRW0mZMEQtskp5CKDzZhIaMwWXC026XvOE8ubvr+HLebL5ZzKxIzoLc3fHgh 15 | WqBJjDHbdRLuclcXlH4h17MNihP7ws6WkK7IN5wXExZ5L0NV/v0/z1pXpFSCT9oq 16 | xr8FkGNcTjgly8bfLv2kfz8oPxe5Q27QpNVxa1ytnq9FBHZ+OXJKWPVBa1OEXF0M 17 | y0gGD5P+bbu8OZsdymktiAMHVBFQ7Zx6KtL+GG1oFTTXHQKiuq/f 18 | -----END CERTIFICATE REQUEST----- 19 | -------------------------------------------------------------------------------- /test/fixtures/ssl/server3.csr: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE REQUEST----- 2 | MIIC8zCCAdsCAQAwgYoxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTELMAkGA1UE 3 | BwwCU0YxEDAOBgNVBAoMB1Bvc3RtYW4xGjAYBgNVBAsMEXBvc3RtYW5AbG9jYWxo 4 | b3N0MRMwEQYDVQQDDApUZXN0Q2xpZW50MR4wHAYJKoZIhvcNAQkBFg9kby5ub3RA 5 | ZW1haWwubWUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC2PorKeXjk 6 | RztZTVepKqxdeeHqoEHwyx/ui629kE3v48P6lTQ0Zr2MsH4Z3kwkFEU5eiYPYG86 7 | qcyWsmzbA5X1MC88cpLxQbD9wlZf2QszlLY+XuOqxW6jWFSOSB66Z4n6K4FqBedc 8 | VyNIEWNMQ5Jnr3B0rQpp2KMIoTPrC1WLQ4FnnOrJY2yG/NWVg0fISdTRW3o8NYV0 9 | hKQbH7+LFSdb+JB/YifKhW8oCfeIpoKpKc04e+nJ5xp7Vi/eXWe3D1rCtOvR9mfr 10 | lMTLwPU4YE0p1QUKwduXfDUAmkM/3AGEKa8Rf+UyXltMrwMsz57rtMRiWSQNBdY+ 11 | fk6DWiTVtuxfAgMBAAGgIzAhBgkqhkiG9w0BCQcxFAwScGFzc3dvcmQgY2hhbGxl 12 | bmdlMA0GCSqGSIb3DQEBCwUAA4IBAQBhv+L6nWXpENopJsBTnYPCAP7boyBoI08g 13 | 10ncXcZxcDD2nh4DNna1+vmJ3c5Gv7xIPKVEzaY6V/aaCeW4sAK8Rk3G78yRAfg+ 14 | HYaD+snqLy5O+A4fX4N1T+ajOJramVzrea+MNx4EY8GAVbG/dDwJ042zez319hvE 15 | OGXuBA874dyK5+BwX8kgeJZJ/YMQSsXmW8yQCO3Y/o9+Ut6KykodQmoZMA47nCae 16 | oC3FdQjbGRNWqA7Vgo75JBetBML8pgtIhTN4fj27S48DrPkNttL4A1Iv/zfLXMqA 17 | OS71qTzeS2nUQvZ939Ms7r5KpW7FVvDmAHaK854zC7tgbvsp0rcq 18 | -----END CERTIFICATE REQUEST----- 19 | -------------------------------------------------------------------------------- /test/integration/case-insen-header-sandbox.postman_collection.json: -------------------------------------------------------------------------------- 1 | { 2 | "variables": [], 3 | "info": { 4 | "name": "Sandbox getResponseHeader method should be case insensitive", 5 | "_postman_id": "1153d5ce-29e2-c83f-648c-24e17c4aa852", 6 | "description": "A set of tests to verify the case insensitive nature of response header retrieval", 7 | "schema": "https://schema.getpostman.com/json/collection/v2.0.0/collection.json" 8 | }, 9 | "item": [ 10 | { 11 | "name": "Get json response", 12 | "event": [ 13 | { 14 | "listen": "test", 15 | "script": { 16 | "type": "text/javascript", 17 | "exec": "tests[\"Case-insensitive header checking\"] = postman.getResponseHeader(\"contenT-TypE\")===\"application/json; charset=utf-8\";" 18 | } 19 | } 20 | ], 21 | "request": { 22 | "url": "https://postman-echo.com/get", 23 | "method": "GET", 24 | "header": [], 25 | "body": { 26 | "mode": "formdata", 27 | "formdata": [] 28 | }, 29 | "description": "" 30 | }, 31 | "response": [] 32 | } 33 | ] 34 | } 35 | -------------------------------------------------------------------------------- /test/fixtures/run/ssl-client-cert.json: -------------------------------------------------------------------------------- 1 | { 2 | "info": { 3 | "_postman_id": "1aef0597-d937-47e1-a989-2733f6d9eecf", 4 | "name": "Client cert example", 5 | "description": "A sample collection to demonstrate client SSL certificate handling", 6 | "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json" 7 | }, 8 | "item": [ 9 | { 10 | "name": "A simple GET request", 11 | "event": [ 12 | { 13 | "listen": "test", 14 | "script": { 15 | "id": "b4f95cb4-9219-4e2a-b62c-9055a3958a37", 16 | "exec": [ 17 | "pm.test(\"Status code is 200\", function () {", 18 | " pm.response.to.have.status(200);", 19 | "});" 20 | ], 21 | "type": "text/javascript" 22 | } 23 | } 24 | ], 25 | "request": { 26 | "method": "GET", 27 | "header": [], 28 | "url": { 29 | "raw": "https://localhost:3000", 30 | "protocol": "https", 31 | "host": [ 32 | "localhost" 33 | ], 34 | "port": "3000" 35 | } 36 | } 37 | } 38 | ] 39 | } 40 | -------------------------------------------------------------------------------- /examples/run-collections-in-directory.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | /** 3 | * @fileOverview This sample code illustrates how one can read all collection files within a directory and run them 4 | * in parallel. 5 | */ 6 | var newman = require('../'), // require('newman') 7 | fs = require('fs'); 8 | 9 | fs.readdir('./examples', function (err, files) { 10 | if (err) { throw err; } 11 | 12 | // we filter all files with JSON file extension 13 | files = files.filter(function (file) { 14 | return (/^((?!(package(-lock)?))|.+)\.json/).test(file); 15 | }); 16 | 17 | // now we iterate on each file name and call newman.run using each file name 18 | files.forEach(function (file) { 19 | newman.run({ 20 | // we load collection using require. for better validation and handling 21 | // JSON.parse could be used 22 | collection: require(`${__dirname}/${file}`) 23 | }, function (err) { 24 | // finally, when the collection executes, print the status 25 | console.info(`${file}: ${err ? err.name : 'ok'}!`); 26 | }); 27 | }); // the entire flow can be made more elegant using `async` module 28 | }); 29 | -------------------------------------------------------------------------------- /test/cli/cli-reporter-no-success-assertsions.test.js: -------------------------------------------------------------------------------- 1 | const expect = require('chai').expect; 2 | 3 | 4 | describe('CLI reporter no success assertions', function () { 5 | const noSuccessOutput = /response\s+code\s+is\s+200/; 6 | 7 | it('should produce normal output', function (done) { 8 | exec('node ./bin/newman.js run test/fixtures/run/single-get-request.json', 9 | function (code, stdout, stderr) { 10 | expect(code, 'should have exit code of 0').to.equal(0); 11 | expect(stderr).to.be.empty; 12 | expect(stdout).to.match(noSuccessOutput); 13 | 14 | done(code); 15 | }); 16 | }); 17 | 18 | it('should not contain success output', function (done) { 19 | exec('node ./bin/newman.js run test/fixtures/run/single-get-request.json --reporter-cli-no-success-assertions', 20 | function (code, stdout, stderr) { 21 | expect(code, 'should have exit code of 0').to.equal(0); 22 | expect(stderr).to.be.empty; 23 | expect(stdout).to.not.match(noSuccessOutput); 24 | 25 | done(code); 26 | }); 27 | }); 28 | }); 29 | -------------------------------------------------------------------------------- /test/integration/tc4/tc4.postman_collection.json: -------------------------------------------------------------------------------- 1 | { 2 | "variables": [], 3 | "info": { 4 | "name": "Form data file upload", 5 | "_postman_id": "d1c476fc-b34c-149e-ac26-ffbcb13edc0e", 6 | "description": "A collection to test file upload operations", 7 | "schema": "https://schema.getpostman.com/json/collection/v2.0.0/collection.json" 8 | }, 9 | "item": [ 10 | { 11 | "name": "POST file test", 12 | "event": [ 13 | { 14 | "listen": "test", 15 | "script": { 16 | "type": "text/javascript", 17 | "exec": "var file = JSON.parse(responseBody).files[\"upload-file.json\"];\n\ntests[\"File contents are valid\"] = _.startsWith(file, \"data:application/octet-stream;base64,\");" 18 | } 19 | } 20 | ], 21 | "request": { 22 | "url": "https://postman-echo.com/post", 23 | "method": "POST", 24 | "header": [], 25 | "body": { 26 | "mode": "formdata", 27 | "formdata": [ 28 | { 29 | "key": "file", 30 | "src": "test/integration/tc4/upload-file.json", 31 | "type": "file" 32 | } 33 | ] 34 | }, 35 | "description": "Passes when posted to postman-echo.com/post" 36 | }, 37 | "response": [] 38 | } 39 | ] 40 | } 41 | -------------------------------------------------------------------------------- /lib/reporters/progress.js: -------------------------------------------------------------------------------- 1 | var progress = require('cli-progress'), 2 | ProgressReporter; 3 | 4 | /** 5 | * Little reporter that generates a collection progress status bar on CLI. 6 | * 7 | * @param {Object} newman - A run object with event handler specification methods. 8 | * @param {Function} newman.on - An event setter method that provides hooks for reporting collection run progress. 9 | * @param {Object} reporterOptions - A set of reporter specific run options. 10 | * @param {Object} options - A set of generic collection run options. 11 | * @returns {*} 12 | */ 13 | ProgressReporter = function (newman, reporterOptions, options) { 14 | if (options.silent || reporterOptions.silent) { 15 | return; 16 | } 17 | 18 | var bar = new progress.Bar({}); 19 | 20 | newman.on('start', function (err, o) { 21 | if (err) { return; } 22 | 23 | bar.start(o.cursor.length * o.cursor.cycles, 0); 24 | }); 25 | 26 | newman.on('item', function () { 27 | bar.increment(); 28 | }); 29 | 30 | newman.on('done', function () { 31 | bar.stop(); 32 | }); 33 | }; 34 | 35 | ProgressReporter.prototype.dominant = true; 36 | module.exports = ProgressReporter; 37 | -------------------------------------------------------------------------------- /test/fixtures/ssl/client2.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIDLDCCAhQCBhJxhSchCDANBgkqhkiG9w0BAQsFADBiMQswCQYDVQQGEwJBVTEM 3 | MAoGA1UECAwDTlNXMQ8wDQYDVQQHDAZTeWRuZXkxDzANBgNVBAoMBk5ld21hbjEN 4 | MAsGA1UECwwEVGVzdDEUMBIGA1UEAwwLdGVzdC5uZXdtYW4wHhcNMTkxMTIxMDUw 5 | NzI2WhcNMjkxMTE4MDUwNzI2WjBRMQswCQYDVQQGEwJBVTEMMAoGA1UECAwDTlNX 6 | MQ8wDQYDVQQKDAZOZXdtYW4xDTALBgNVBAsMBFRlc3QxFDASBgNVBAMMC3Rlc3Qu 7 | bmV3bWFuMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAr4gQ2xdoRvKg 8 | Rzd49uh3WPud/I+npx8QpjkWJVsLVQuWVOCKTMaspVqWLwPZFt05+wCAUWompX6O 9 | I7vqd9nyZkd1odKsHQs1HY3JDlnN3FsLx305+I4QKrPs4NsoqT0U5MQ58bZYALS9 10 | VOs0ISndq3hMhv7SZKU8bITdeMbJodmEEYerXWvs5qmJ5y7q5nYNHuHzGmKIxjAs 11 | iFzNSL5jv6nNfK41WMgrhlJIsO/jqfYG5S32JJKQY163A4hUJT6CKJ39QanQZc2d 12 | 7V+XxiRIquvHwkSRYolEjVHwRvFGQvJRd2D2iVhxaHKC1HQwHefA1DM2TYY+wCP1 13 | JYlPQeta2wIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQC/WLksgoIOrfM7sChruXLL 14 | O3rBoBoXGtqzeyqr1LtI35tlOKjqALFg0iyyjIrODXOVOqfx13WlyCzMzHxLd8c9 15 | YOBaqw78Igw4VmrAh8EYj66RI+zW2g13k0QiLHrVlF2KHsYTBE4fpv9GDNTd260Z 16 | VhcO0T6wht/EPHEnU04evLs6kUTB4NRw00B69diwmatsY8vdgWGPj920ILHOyFmo 17 | eqNfY70pK679KXLMd2uev5hJkk+l57NhYZXoD2evprv/9w5JZrTRBxtc5gUYLvTw 18 | AVX2Qtq6peJAAb0TD8IN3Ib3i0IuIQJrx4pg5q6ais6JBVsvonLmLbYW2z3KBVFE 19 | -----END CERTIFICATE----- 20 | -------------------------------------------------------------------------------- /lib/reporters/emojitrain.js: -------------------------------------------------------------------------------- 1 | var SmileyReporter; 2 | 3 | /** 4 | * Fills your collection run (read life) with a bunch of Emojis 😀. 5 | * 6 | * @param {Object} newman - The collection run object with event handling hooks to enable reporting. 7 | * @param {Object} reporterOptions - A set of reporter specific run options. 8 | * @param {Object} options - A set of generic collection run options. 9 | * @returns {*} 10 | */ 11 | SmileyReporter = function (newman, reporterOptions, options) { 12 | if (options.silent || reporterOptions.silent) { 13 | return; 14 | } 15 | 16 | var fails = {}, 17 | noteFailure; 18 | 19 | noteFailure = function (err, args) { 20 | err && (fails[args.cursor.ref] = true); 21 | }; 22 | 23 | newman.on('script', noteFailure); 24 | newman.on('request', noteFailure); 25 | newman.on('assertion', noteFailure); 26 | 27 | newman.on('item', function (err, args) { 28 | process.stdout.write((err || fails[args.cursor.ref]) ? '😢 ' : '😀 '); 29 | }); 30 | 31 | newman.on('done', function (err) { 32 | console.info((err || Object.keys(fails).length) ? ' 😭' : ' 😍'); 33 | }); 34 | }; 35 | 36 | SmileyReporter.prototype.dominant = true; 37 | module.exports = SmileyReporter; 38 | -------------------------------------------------------------------------------- /test/.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "plugins": [ 3 | "mocha" 4 | ], 5 | "env": { 6 | "mocha": true, 7 | "browser": true, 8 | "node": true, 9 | "es6": true 10 | }, 11 | "globals": { 12 | "exec": true 13 | }, 14 | "rules": { 15 | // JSDoc 16 | "jsdoc/require-param-type": "off", 17 | "jsdoc/require-param-description": "off", 18 | 19 | // Mocha 20 | "mocha/handle-done-callback": "error", 21 | "mocha/max-top-level-suites": "error", 22 | "mocha/no-exclusive-tests": "error", 23 | "mocha/no-global-tests": "error", 24 | "mocha/no-hooks-for-single-case": "off", 25 | "mocha/no-hooks": "off", 26 | "mocha/no-identical-title": "error", 27 | "mocha/no-mocha-arrows": "error", 28 | "mocha/no-nested-tests": "error", 29 | "mocha/no-pending-tests": "error", 30 | "mocha/no-return-and-callback": "error", 31 | "mocha/no-sibling-hooks": "error", 32 | "mocha/no-skipped-tests": "off", 33 | "mocha/no-synchronous-tests": "off", 34 | "mocha/no-top-level-hooks": "off", 35 | "mocha/valid-test-description": "off", 36 | "mocha/valid-suite-description": "off" 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /test/integration/slashed-variable-names/slashed-variable-names.postman_collection.json: -------------------------------------------------------------------------------- 1 | { 2 | "variables": [], 3 | "info": { 4 | "name": "slashed variable names", 5 | "_postman_id": "03ff9ad8-cdeb-c03b-ba1f-2076fe3faf50", 6 | "schema": "https://schema.getpostman.com/json/collection/v2.0.0/collection.json" 7 | }, 8 | "item": [ 9 | { 10 | "name": "Slashed variable names test", 11 | "event": [ 12 | { 13 | "listen": "test", 14 | "script": { 15 | "type": "text/javascript", 16 | "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\";" 17 | } 18 | } 19 | ], 20 | "request": { 21 | "url": "https://postman-echo.com/get?foo={{fo/o}}&bar={{b\\ar}}", 22 | "method": "GET", 23 | "header": [], 24 | "body": { 25 | "mode": "formdata", 26 | "formdata": [] 27 | }, 28 | "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." 29 | }, 30 | "response": [] 31 | } 32 | ] 33 | } 34 | -------------------------------------------------------------------------------- /test/fixtures/overrides/failing-collection.json: -------------------------------------------------------------------------------- 1 | { 2 | "info": { 3 | "_postman_id": "64e7cd23-3037-42f5-b36e-51ea6fb5f973", 4 | "name": "env var test", 5 | "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json" 6 | }, 7 | "item": [ 8 | { 9 | "name": "--env-var test", 10 | "event": [ 11 | { 12 | "listen": "test", 13 | "script": { 14 | "id": "ad0b9fd8-b9a7-44d6-a46b-8344aee76b98", 15 | "exec": [ 16 | "pm.test(\"Body matches string\", function () {", 17 | " pm.expect(pm.response.text()).to.include(\"bar2\");", 18 | "});", 19 | "", 20 | "" 21 | ], 22 | "type": "text/javascript" 23 | } 24 | } 25 | ], 26 | "request": { 27 | "method": "GET", 28 | "header": [], 29 | "body": { 30 | "mode": "raw", 31 | "raw": "" 32 | }, 33 | "url": { 34 | "raw": "ostman-echo.com/get?key={{dummyVar}}", 35 | "protocol": "https", 36 | "host": [ 37 | "postman-echo", 38 | "com" 39 | ], 40 | "path": [ 41 | "get" 42 | ], 43 | "query": [ 44 | { 45 | "key": "key", 46 | "value": "{{dummyVar}}" 47 | } 48 | ] 49 | } 50 | }, 51 | "response": [] 52 | } 53 | ] 54 | } -------------------------------------------------------------------------------- /test/fixtures/overrides/pmcollection.json: -------------------------------------------------------------------------------- 1 | { 2 | "info": { 3 | "_postman_id": "64e7cd23-3037-42f5-b36e-51ea6fb5f973", 4 | "name": "env var test", 5 | "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json" 6 | }, 7 | "item": [ 8 | { 9 | "name": "--env-var test", 10 | "event": [ 11 | { 12 | "listen": "test", 13 | "script": { 14 | "id": "ad0b9fd8-b9a7-44d6-a46b-8344aee76b98", 15 | "exec": [ 16 | "pm.test(\"Body matches string\", function () {", 17 | " pm.expect(pm.response.text()).to.include(\"bar2\");", 18 | "});", 19 | "", 20 | "" 21 | ], 22 | "type": "text/javascript" 23 | } 24 | } 25 | ], 26 | "request": { 27 | "method": "GET", 28 | "header": [], 29 | "body": { 30 | "mode": "raw", 31 | "raw": "" 32 | }, 33 | "url": { 34 | "raw": "https://postman-echo.com/get?key={{dummyVar}}", 35 | "protocol": "https", 36 | "host": [ 37 | "postman-echo", 38 | "com" 39 | ], 40 | "path": [ 41 | "get" 42 | ], 43 | "query": [ 44 | { 45 | "key": "key", 46 | "value": "{{dummyVar}}" 47 | } 48 | ] 49 | } 50 | }, 51 | "response": [] 52 | } 53 | ] 54 | } -------------------------------------------------------------------------------- /test/cli/verbose.test.js: -------------------------------------------------------------------------------- 1 | const _ = require('lodash'), 2 | expect = require('chai').expect; 3 | 4 | describe('newman run --verbose', function () { 5 | const verboseStrings = [ 6 | 'prepare', 7 | 'wait', 8 | 'dns-lookup', 9 | 'tcp-handshake', 10 | 'ssl-handshake', 11 | 'transfer-start', 12 | 'download', 13 | 'process', 14 | 'average DNS lookup time:', 15 | 'average first byte time:' 16 | ]; 17 | 18 | it('should include verbose with --verbose option', function (done) { 19 | exec('node ./bin/newman.js run test/fixtures/run/single-get-request.json --verbose', function (code, stdout) { 20 | _.forEach(verboseStrings, function (str) { 21 | expect(stdout).to.contain(str); 22 | }); 23 | 24 | done(); 25 | }); 26 | }); 27 | 28 | it('should not include verbose without --verbose option', function (done) { 29 | exec('node ./bin/newman.js run test/fixtures/run/single-get-request.json', function (code, stdout) { 30 | _.forEach(verboseStrings, function (str) { 31 | expect(stdout).to.not.contain(str); 32 | }); 33 | 34 | done(); 35 | }); 36 | }); 37 | }); 38 | -------------------------------------------------------------------------------- /test/integration/multi-value-data.postman_collection.json: -------------------------------------------------------------------------------- 1 | { 2 | "variables": [], 3 | "info": { 4 | "name": "Mutli-valued formdata props", 5 | "_postman_id": "bd279aba-66c1-a145-5acb-e0e2fcf23465", 6 | "description": "A set of tests checking if multiple formdata props with the same key are sent correctly", 7 | "schema": "https://schema.getpostman.com/json/collection/v2.0.0/collection.json" 8 | }, 9 | "item": [ 10 | { 11 | "name": "r1", 12 | "event": [ 13 | { 14 | "listen": "test", 15 | "script": { 16 | "type": "text/javascript", 17 | "exec": "var data = request.data; tests['request data array correct'] = (_.isArray(data.name))" 18 | } 19 | } 20 | ], 21 | "request": { 22 | "url": "https://postman-echo.com/get?a={{$randomInt}}", 23 | "method": "GET", 24 | "header": [], 25 | "body": { 26 | "mode": "formdata", 27 | "formdata": [ 28 | { 29 | "key": "name", 30 | "value": "sampleName" 31 | }, 32 | { 33 | "key": "name", 34 | "value": "sampleName2" 35 | } 36 | ] 37 | }, 38 | "description": "" 39 | }, 40 | "response": [] 41 | } 42 | ] 43 | } 44 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | # PLATFORM 2 | # ======== 3 | # All exclusions that are specific to the NPM, GIT, IDE and Operating Systems. 4 | 5 | # - Do not allow installed node modules to be committed. Doing `npm install -d` will bring them in root or other places. 6 | node_modules 7 | 8 | # - Do not commit any log file from anywhere 9 | *.log 10 | *.log.* 11 | 12 | # - Prevent addition of OS specific file explorer files 13 | Thumbs.db 14 | .DS_Store 15 | 16 | # Prevent IDE stuff 17 | .idea 18 | .vscode 19 | 20 | # PROJECT 21 | # ======= 22 | # Configuration pertaining to project specific repository structure. 23 | 24 | # - Prevent Sublime text IDE files from being committed to repository 25 | *.sublime-* 26 | 27 | # - Allow sublime text project file to be committed in the development directory. 28 | !/develop/*.sublime-project 29 | 30 | # - Prevent CI output files from being added 31 | /out/ 32 | /newman/ 33 | 34 | # - Prevent diff backups from SourceTree from showing as commit. 35 | *.BACKUP.* 36 | *.BASE.* 37 | *.LOCAL.* 38 | *.REMOTE.* 39 | *.orig 40 | 41 | # - Prevent code coverage reports from being added 42 | .coverage 43 | .nyc_output 44 | 45 | # - Prevent config and test files from being added 46 | .git* 47 | npm/ 48 | test/ 49 | examples/ 50 | codecov.yml 51 | .eslintrc 52 | .nycrc.js 53 | .dockerignore 54 | .editorconfig 55 | .jsdoc-config.json 56 | -------------------------------------------------------------------------------- /test/integration/request-name-in-script.postman_collection.json: -------------------------------------------------------------------------------- 1 | { 2 | "variables": [], 3 | "info": { 4 | "name": "Request Name In Script", 5 | "_postman_id": "ce3bf661-9803-6712-5f8e-ff5fcf1ba5db", 6 | "description": "A test to check for the presence of the request name in the script", 7 | "schema": "https://schema.getpostman.com/json/collection/v2.0.0/collection.json" 8 | }, 9 | "item": [ 10 | { 11 | "name": "r1", 12 | "event": [ 13 | { 14 | "listen": "test", 15 | "script": { 16 | "type": "text/javascript", 17 | "exec": "tests[\"correct request name and description\"] = (request.name===\"r1\" && request.description===\"testDesc\")" 18 | } 19 | }, 20 | { 21 | "listen": "prerequest", 22 | "script": { 23 | "type": "text/javascript", 24 | "exec": "if(request.name!==\"r1\" || request.description!==\"testDesc\") {undefFunction()}" 25 | } 26 | } 27 | ], 28 | "request": { 29 | "url": "postman-echo.com/get", 30 | "method": "GET", 31 | "header": [], 32 | "body": { 33 | "mode": "formdata", 34 | "formdata": [] 35 | }, 36 | "description": "testDesc" 37 | }, 38 | "response": [] 39 | } 40 | ] 41 | } 42 | -------------------------------------------------------------------------------- /test/fixtures/run/newman-report-test.json: -------------------------------------------------------------------------------- 1 | { 2 | "variables": [], 3 | "info": { 4 | "name": "assertion-error-test", 5 | "_postman_id": "bd90e43e-8e25-d630-9098-420853777b21", 6 | "description": "A sanity check for report generation, including a check for failed requests.", 7 | "schema": "https://schema.getpostman.com/json/collection/v2.0.0/collection.json" 8 | }, 9 | "item": [ 10 | { 11 | "name": "Failed request", 12 | "event": [ 13 | { 14 | "listen": "test", 15 | "script": { 16 | "type": "text/javascript", 17 | "exec": [ 18 | "tests[\"Status code is 200\"] = responseCode.code === 200;", 19 | "", 20 | "// deliberate AssertionError to test proper report generation", 21 | "pm.test(\"Status code is 400\", function () {", 22 | " pm.response.to.have.status(400);", 23 | "});", 24 | "// deliberate TypeError to test proper report generation", 25 | "tests[\"Body contains status\"] = undefined.alpha;", 26 | "" 27 | ] 28 | } 29 | } 30 | ], 31 | "request": { 32 | "url": "https://postman-echo.com/status/200", 33 | "method": "GET", 34 | "header": [], 35 | "body": {}, 36 | "description": "A request with a `TypeError` in it's test script" 37 | }, 38 | "response": [] 39 | } 40 | ] 41 | } 42 | -------------------------------------------------------------------------------- /test/integration/crypto-md5.postman_collection.json: -------------------------------------------------------------------------------- 1 | { 2 | "variables": [], 3 | "info": { 4 | "name": "Crypto-MD5 should work in the sandbox", 5 | "_postman_id": "4f085147-6c40-19dc-6250-257d64c261ac", 6 | "description": "A set of tests to verify the crypto.md5 function in the sandbox", 7 | "schema": "https://schema.getpostman.com/json/collection/v2.0.0/collection.json" 8 | }, 9 | "item": [ 10 | { 11 | "name": "r1", 12 | "event": [ 13 | { 14 | "listen": "test", 15 | "script": { 16 | "type": "text/javascript", 17 | "exec": "var data = JSON.parse(responseBody);\ntests[\"Your test name\"] = data.args.a === \"da9ebb087d8e926c503e4909d9203a04\";" 18 | } 19 | }, 20 | { 21 | "listen": "prerequest", 22 | "script": { 23 | "type": "text/javascript", 24 | "exec": "postman.setGlobalVariable(\"a\", CryptoJS.MD5(\"samplePayload\").toString());" 25 | } 26 | } 27 | ], 28 | "request": { 29 | "url": "https://postman-echo.com/get?a={{a}}", 30 | "method": "GET", 31 | "header": [], 32 | "body": { 33 | "mode": "formdata", 34 | "formdata": [] 35 | }, 36 | "description": "" 37 | }, 38 | "response": [] 39 | } 40 | ] 41 | } 42 | -------------------------------------------------------------------------------- /test/system/dockerfiles.test.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @fileoverview This test suite runs tests on the various versions of newman-docker. 3 | */ 4 | 5 | const fs = require('fs'), 6 | path = require('path'), 7 | expect = require('chai').expect, 8 | DockerFileValidator = require('dockerfile_lint'); 9 | 10 | describe('Validate Dockerfiles', function () { 11 | const imagesBaseDirectory = path.join(__dirname, '../../docker/images'), 12 | images = fs.readdirSync(imagesBaseDirectory).filter(function (item) { 13 | return fs.statSync(path.join(imagesBaseDirectory, item)).isDirectory(); 14 | }), 15 | validator = new DockerFileValidator(path.join(__dirname, 'dockerfile_rules.yml')); 16 | 17 | images.forEach(function (version) { 18 | const dockerFilePath = path.join(imagesBaseDirectory, version, 'Dockerfile'), 19 | dockerFileContent = fs.readFileSync(dockerFilePath); 20 | 21 | it('should have valid Docker file for "' + version + '"', function () { 22 | const result = validator.validate(dockerFileContent.toString()), 23 | faults = result.error.count + result.warn.count; 24 | 25 | faults && console.error(JSON.stringify(result, null, 4)); // Helps debugging on the CI 26 | expect(faults, `there are ${faults} error(s)`).to.equal(0); 27 | }); 28 | }); 29 | }); 30 | -------------------------------------------------------------------------------- /test/fixtures/ssl/ca3.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIDkjCCAnoCCQDVmzvauKidhzANBgkqhkiG9w0BAQsFADCBijELMAkGA1UEBhMC 3 | VVMxCzAJBgNVBAgMAkNBMQswCQYDVQQHDAJTRjEQMA4GA1UECgwHUG9zdG1hbjEa 4 | MBgGA1UECwwRcG9zdG1hbkBsb2NhbGhvc3QxEzARBgNVBAMMClRlc3RDbGllbnQx 5 | HjAcBgkqhkiG9w0BCQEWD2RvLm5vdEBlbWFpbC5tZTAeFw0yMDA1MTIxOTUwMTVa 6 | Fw00NzA5MjcxOTUwMTVaMIGKMQswCQYDVQQGEwJVUzELMAkGA1UECAwCQ0ExCzAJ 7 | BgNVBAcMAlNGMRAwDgYDVQQKDAdQb3N0bWFuMRowGAYDVQQLDBFwb3N0bWFuQGxv 8 | Y2FsaG9zdDETMBEGA1UEAwwKVGVzdENsaWVudDEeMBwGCSqGSIb3DQEJARYPZG8u 9 | bm90QGVtYWlsLm1lMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2c3B 10 | 3urKLmkimxO9i1mueVqBzSMn+fygV87DwL8RO899S3SXO2ZtHECxLgCR3qRXUS2R 11 | wY5JYie1L5qJYnOrgBO/mhxuX9KbuUz5xSr7vOWzVPlqCMBbKa24bDfJ/NE036yr 12 | LqIUSx2xeUoUp9z0rqQaXHLezBX5w6DYCwb0/RmY+sWj23/NnMTzDituPGDjUp/6 13 | xIBOYBpolXDYLVCvjoO3UnUJ5ffAMyuanr9Myx1j8lO0rkjUV/IPPZfrv4OQEu3M 14 | dWKOyENWnfQVK7VHsm9RlBf6WcH0XiWGQdmdd3uU7HOMd132QLbco2j1U9IKnX7h 15 | 7Wsi08Af2WStjzpePwIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQDVYYYM1IndsUoZ 16 | VaSSWUPzFdSKY37RYiRYKKz/2hrNyQ95PEv8oDneZAkt2wRR7mG0YGvsoAMu7OLk 17 | sbi2t/PbIRTFe1nWWqVE+05p1OQWuDlK2UZx+d7h3NTn9SvtNPNcF2nejRU6iFjY 18 | /8mg8bLLkcJvlTW6qc3mPZyof+jGc7/JOB+RXsNVf8HKcNDExZlYUjIWBWDhCLCD 19 | 73bn2c1d+Rtdzne1gB2EaEXtATbE2VCnvttwS5XmGK9ur+KBPMDeBla0k4UipbfJ 20 | UMsE//7mGUzMoHpFdyi+Bljw3Z+ORf843THHcB0byaXqLGrAysQpe+kmPm1ZgIp5 21 | vcP1nYu5 22 | -----END CERTIFICATE----- 23 | -------------------------------------------------------------------------------- /test/system/editorconfig.test.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @fileOverview Ensures that editorconfig settings are appropriate 3 | */ 4 | 5 | const editorconfig = require('editorconfig'), 6 | expect = require('chai').expect, 7 | 8 | /** 9 | * The width (in spaces) of tabs used for indentation throughout the project 10 | * 11 | * @type {Number} 12 | */ 13 | TAB_WIDTH = 4; 14 | 15 | describe('.editorconfig', function () { 16 | const config = editorconfig.parseSync('.editorconfig'); // eslint-disable-line no-sync 17 | 18 | it('should have a tab_width of 4', function () { 19 | expect(config.tab_width).to.equal(TAB_WIDTH); 20 | }); 21 | 22 | it('should have a charset of utf-8', function () { 23 | expect(config.charset).to.equal('utf-8'); 24 | }); 25 | 26 | it('should have an indent_size of 4', function () { 27 | expect(config.indent_size).to.equal(TAB_WIDTH); 28 | }); 29 | 30 | it('should have an indent_style of 4', function () { 31 | expect(config.indent_style).to.equal('space'); 32 | }); 33 | 34 | it('should have a truthy insert_final_newline value', function () { 35 | expect(config.insert_final_newline).to.equal(true); 36 | }); 37 | 38 | it('should have a truthy trim_trailing_whitespace', function () { 39 | expect(config.trim_trailing_whitespace).to.equal(true); 40 | }); 41 | }); 42 | -------------------------------------------------------------------------------- /test/fixtures/ssl/ca2.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIDmTCCAoGgAwIBAgIJAJ5DOjshFAqCMA0GCSqGSIb3DQEBCwUAMGIxCzAJBgNV 3 | BAYTAkFVMQwwCgYDVQQIDANOU1cxDzANBgNVBAcMBlN5ZG5leTEPMA0GA1UECgwG 4 | TmV3bWFuMQ0wCwYDVQQLDARUZXN0MRQwEgYDVQQDDAt0ZXN0Lm5ld21hbjAgFw0x 5 | OTExMjEwNDUwNThaGA8yMTE5MTAyODA0NTA1OFowYjELMAkGA1UEBhMCQVUxDDAK 6 | BgNVBAgMA05TVzEPMA0GA1UEBwwGU3lkbmV5MQ8wDQYDVQQKDAZOZXdtYW4xDTAL 7 | BgNVBAsMBFRlc3QxFDASBgNVBAMMC3Rlc3QubmV3bWFuMIIBIjANBgkqhkiG9w0B 8 | AQEFAAOCAQ8AMIIBCgKCAQEA6/6rTsqpiOJDFykvM+jboNutFXE9zIFs8Ka5tHk4 9 | iRrVPjZoKYoUp1rp9cz0StoWnhSLKebeCV4Q54reSO0UITffcGQmQTdyOLj9hhYE 10 | wTwjEW0GBgRab0GqKq0TpdFCe0aPP6sme5ZvBGgzUGM+xBvj9q44FqLv0JoWAk84 11 | J6gCW/SiTHdnwEdLctUmBdjuCbGW/3iSq6KsZ3gWjzkF0DnViayxSHCL8M0T7MD/ 12 | bHp/ZK/ADhYwpqPjcs2Ol5YfOfJp5YEsJpDQGYm5SLt20V2Cq8OX5rM7zGs5g2Wh 13 | AEVoh2U85lDHtUlPTB1eWjxrvXK8ftohlHx+ToDtzs7TEQIDAQABo1AwTjAdBgNV 14 | HQ4EFgQUCH7qfoYd4Eb2BpGOQlhAzezLPZYwHwYDVR0jBBgwFoAUCH7qfoYd4Eb2 15 | BpGOQlhAzezLPZYwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAOLPZ 16 | DXpBKPb6BwANj8vwz8H0NWmmiJaNdqv9XUXFYVU6hsUQRUJutu772C2kqjx03RcA 17 | WHHsQLBZtyAuTSHMKQNwnvUoCFc7a6qwcQJTF8hCvVJARlhH4NdRvj6MabsRruiH 18 | tZMYcbnF4IIsTCt63NNjyCnIDbSs/JtTeIKyFcFgRwWZYTSZd42c4kFROf5aebpk 19 | a1IACSKu1Vx62Hz/zgq1uops3vAwnPXc+8PtwSn8XEEL1pAiZWy9S2xyABeLHCOX 20 | Zad3janI/GyOHAaChKawNAAj3v2ADS6SCpzqQT4ObvTiqioJ9WhBzwb9sFopaL5T 21 | JULygLz1gRJ/AnKVww== 22 | -----END CERTIFICATE----- 23 | -------------------------------------------------------------------------------- /npm/create-release.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | // --------------------------------------------------------------------------------------------------------------------- 3 | // This script is intended to automate the versioning and changelog generation process for a release. 4 | // --------------------------------------------------------------------------------------------------------------------- 5 | 6 | const shipit = require('@postman/shipit'), 7 | 8 | // npm run release [true] [beta] 9 | [pushToOrigin, preReleaseSuffix] = process.argv.splice(2); 10 | 11 | // only support `beta` suffix 12 | if (preReleaseSuffix && preReleaseSuffix !== 'beta') { 13 | throw new Error(`Can't prerelease with \`${preReleaseSuffix}\` suffix.`); 14 | } 15 | 16 | // 🚢 Just Ship It! 17 | shipit({ 18 | mainBranch: 'main', 19 | // don't push to origin unless explicitly set 20 | pushToOrigin: pushToOrigin === 'true', 21 | // prerelease suffix, if any 22 | preReleaseSuffix: preReleaseSuffix, 23 | // make sure that following dependencies are up to date 24 | dependencyList: [ 25 | '@postman/tough-cookie', 'liquid-json', 'postman-collection', 26 | 'postman-collection-transformer', 'postman-request', 'postman-runtime', 27 | 'serialised-error' 28 | ] 29 | }).then((version) => { 30 | console.info('🚀', version); 31 | }).catch((err) => { 32 | console.error('🔥', err); 33 | process.exit(1); 34 | }); 35 | -------------------------------------------------------------------------------- /npm/test-lint.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | // --------------------------------------------------------------------------------------------------------------------- 3 | // This script is intended to contain all actions pertaining to code style checking, linting and normalization. 4 | // --------------------------------------------------------------------------------------------------------------------- 5 | 6 | const colors = require('colors/safe'), 7 | { ESLint } = require('eslint'), 8 | 9 | LINT_SOURCE_DIRS = [ 10 | './lib', 11 | './bin', 12 | './test', 13 | './examples/*.js', 14 | './npm/*.js', 15 | './index.js' 16 | ]; 17 | 18 | module.exports = async function (exit) { 19 | // banner line 20 | console.info(colors.yellow.bold('\nLinting files using eslint...')); 21 | 22 | const eslint = new ESLint(), 23 | results = await eslint.lintFiles(LINT_SOURCE_DIRS), 24 | errorReport = ESLint.getErrorResults(results), 25 | formatter = await eslint.loadFormatter(); 26 | 27 | // log the result to CLI 28 | console.info(formatter.format(results)); 29 | 30 | (errorReport && !errorReport.length) && console.info(colors.green('eslint ok!')); 31 | 32 | exit(Number(errorReport && errorReport.length) || 0); 33 | }; 34 | 35 | // ensure we run this script exports if this is a direct stdin.tty run 36 | !module.parent && module.exports(process.exit); 37 | -------------------------------------------------------------------------------- /test/integration/var-replacement.postman_collection.json: -------------------------------------------------------------------------------- 1 | { 2 | "variables": [], 3 | "info": { 4 | "name": "testCollection", 5 | "_postman_id": "29199569-c73e-da26-69f3-c6e644b00e25", 6 | "description": "A set of tests to check for the proper substitution of blank and non-blank variables", 7 | "schema": "https://schema.getpostman.com/json/collection/v2.0.0/collection.json" 8 | }, 9 | "item": [ 10 | { 11 | "name": "Valid and invalid variables", 12 | "event": [ 13 | { 14 | "listen": "test", 15 | "script": { 16 | "type": "text/javascript", 17 | "exec": "var data = JSON.parse(responseBody);\ntests[\"Variable substitution\"] = (data.args.var===\"replaced\");\ntests[\"No blank variable substitution\"] = (data.args.novar===\"{{novar}}\");" 18 | } 19 | }, 20 | { 21 | "listen": "prerequest", 22 | "script": { 23 | "type": "text/javascript", 24 | "exec": "postman.setEnvironmentVariable(\"var\", \"replaced\");" 25 | } 26 | } 27 | ], 28 | "request": { 29 | "url": "https://postman-echo.com/get?novar={{novar}}&var={{var}}", 30 | "method": "GET", 31 | "header": [], 32 | "body": { 33 | "mode": "formdata", 34 | "formdata": [] 35 | }, 36 | "description": "" 37 | }, 38 | "response": [] 39 | } 40 | ] 41 | } 42 | -------------------------------------------------------------------------------- /.nycrc.js: -------------------------------------------------------------------------------- 1 | const TEST_TYPE = ((argv) => { 2 | let match = argv[argv.length - 1].match(/npm\/test-(\w+).js/); 3 | 4 | return match && match[1] || ''; 5 | })(process.argv); 6 | 7 | function configOverrides (testType) { 8 | switch (testType) { 9 | case 'cli': 10 | return { 11 | statements: 80, 12 | branches: 65, 13 | functions: 85, 14 | lines: 80 15 | }; 16 | case 'integration': 17 | return { 18 | statements: 40, 19 | branches: 20, 20 | functions: 40, 21 | lines: 40 22 | }; 23 | case 'library': 24 | return { 25 | statements: 55, 26 | branches: 40, 27 | functions: 55, 28 | lines: 55 29 | }; 30 | case 'unit': 31 | return { 32 | statements: 70, 33 | branches: 55, 34 | functions: 80, 35 | lines: 70 36 | }; 37 | default: 38 | return {} 39 | } 40 | } 41 | 42 | module.exports = { 43 | all: true, 44 | 'check-coverage': true, 45 | 'report-dir': '.coverage', 46 | 'temp-dir': '.nyc_output', 47 | include: ['lib/**/*.js', 'bin/**/*.js'], 48 | reporter: ['lcov', 'json', 'text', 'text-summary'], 49 | ...configOverrides(TEST_TYPE), 50 | }; 51 | -------------------------------------------------------------------------------- /test/integration/cookie-jar.postman_collection.json: -------------------------------------------------------------------------------- 1 | { 2 | "variables": [], 3 | "info": { 4 | "name": "cookie-jar", 5 | "_postman_id": "6d4f33fe-5c73-f4e0-b3a2-7310ab6b05da", 6 | "description": "", 7 | "schema": "https://schema.getpostman.com/json/collection/v2.0.0/collection.json" 8 | }, 9 | "item": [ 10 | { 11 | "name": "Set Cookie", 12 | "request": { 13 | "url": "https://postman-echo.com/cookies/set?foo=bar", 14 | "method": "GET", 15 | "header": [], 16 | "body": { 17 | "mode": "formdata", 18 | "formdata": [] 19 | }, 20 | "description": "A request to set a cookie `foo` to a value `bar` using Postman Echo as an example." 21 | }, 22 | "response": [] 23 | }, 24 | { 25 | "name": "Verify cookie", 26 | "event": [ 27 | { 28 | "listen": "test", 29 | "script": { 30 | "type": "text/javascript", 31 | "exec": "tests[\"Status code is 200\"] = responseCode.code === 200;\ntests[\"Cookie `foo` exists and has the value bar\"] = postman.getResponseCookie(\"foo\").value === \"bar\";" 32 | } 33 | } 34 | ], 35 | "request": { 36 | "url": "https://postman-echo.com/cookies", 37 | "method": "GET", 38 | "header": [], 39 | "body": { 40 | "mode": "formdata", 41 | "formdata": [] 42 | }, 43 | "description": "A request to validate the presence of the cookie `foo`, with value `bar`, using Postman Echo." 44 | }, 45 | "response": [] 46 | } 47 | ] 48 | } 49 | -------------------------------------------------------------------------------- /test/integration/steph/steph.postman_collection.json: -------------------------------------------------------------------------------- 1 | { 2 | "variables": [], 3 | "info": { 4 | "name": "Basic form data test", 5 | "_postman_id": "b6a53b01-d54e-8501-e7da-74affff4c7fc", 6 | "description": "A set of tests to process piecewise form data", 7 | "schema": "https://schema.getpostman.com/json/collection/v2.0.0/collection.json" 8 | }, 9 | "item": [ 10 | { 11 | "name": "https://postman-echo.com", 12 | "event": [ 13 | { 14 | "listen": "test", 15 | "script": { 16 | "type": "text/javascript", 17 | "exec": "var data = JSON.parse(responseBody);\ntests[\"First name is: \" + data.form.first] = true;\ntests[\"last name is: \" + data.form.last] = true;" 18 | } 19 | } 20 | ], 21 | "request": { 22 | "url": "https://postman-echo.com/post", 23 | "method": "POST", 24 | "header": [], 25 | "body": { 26 | "mode": "formdata", 27 | "formdata": [ 28 | { 29 | "key": "first", 30 | "value": "{{first}}", 31 | "type": "text", 32 | "enabled": true 33 | }, 34 | { 35 | "key": "last", 36 | "value": "{{last}}", 37 | "type": "text", 38 | "enabled": true 39 | } 40 | ] 41 | }, 42 | "description": "" 43 | }, 44 | "response": [] 45 | } 46 | ] 47 | } 48 | -------------------------------------------------------------------------------- /test/cli/suppress-exit-code.test.js: -------------------------------------------------------------------------------- 1 | const expect = require('chai').expect; 2 | 3 | describe('newman run --suppress-exit-code', function () { 4 | it('should accept the --suppress-exit-code parameter', function (done) { 5 | // eslint-disable-next-line max-len 6 | exec('node ./bin/newman.js run test/fixtures/run/single-get-request.json --suppress-exit-code', function (code) { 7 | expect(code, 'should have exit code of 0').to.equal(0); 8 | done(); 9 | }); 10 | }); 11 | 12 | it('should accept the -x parameter', function (done) { 13 | exec('node ./bin/newman.js run test/fixtures/run/single-get-request.json -x', function (code) { 14 | expect(code, 'should have exit code of 0').to.equal(0); 15 | done(); 16 | }); 17 | }); 18 | 19 | it('should exit non-zero if -x parameter is absent on a failing collection', function (done) { 20 | exec('node ./bin/newman.js run test/fixtures/run/single-request-failing.json', function (code) { 21 | expect(code, 'should have non-zero exit code').to.be.greaterThan(0); 22 | done(); 23 | }); 24 | }); 25 | 26 | it('should exit with code zero if -x parameter is present on a failing collection', function (done) { 27 | exec('node ./bin/newman.js run test/fixtures/run/single-request-failing.json -x', function (code) { 28 | expect(code, 'should have exit code of 0').to.equal(0); 29 | done(); 30 | }); 31 | }); 32 | }); 33 | -------------------------------------------------------------------------------- /test/integration/semicolon-tests.postman_collection.json: -------------------------------------------------------------------------------- 1 | { 2 | "variables": [], 3 | "info": { 4 | "name": "Response headers with semicolons are handled correctly", 5 | "_postman_id": "f1639220-14aa-90da-0634-5f6367323dd2", 6 | "description": "A test to check for the proper retrieval of headers from a specified source", 7 | "schema": "https://schema.getpostman.com/json/collection/v2.0.0/collection.json" 8 | }, 9 | "item": [ 10 | { 11 | "name": "Gets a header with a semicolon", 12 | "event": [ 13 | { 14 | "listen": "test", 15 | "script": { 16 | "type": "text/javascript", 17 | "exec": [ 18 | "pm.test(\"Test1: Content-Type is 'application/json; charset=utf-8'\", ()=>{", 19 | " pm.expect(pm.response.headers.get('Content-Type')).equal('application/json; charset=utf-8') ", 20 | "})", 21 | "pm.test(\"Test2: Content-Type is 'application/json; charset=utf-8'\", ()=>{", 22 | " pm.expect(pm.response.headers.get('Content-type')).equal('application/json;\\ charset=utf-8') ", 23 | "})" 24 | ] 25 | } 26 | } 27 | ], 28 | "request": { 29 | "url": "https://postman-echo.com/response-headers?Content-Type=application%2Fjson%3B%20%20charset%3Dutf-8", 30 | "method": "GET", 31 | "header": [], 32 | "description": "Receives a semicolon header from dump.getpost" 33 | }, 34 | "response": [] 35 | } 36 | ] 37 | } 38 | -------------------------------------------------------------------------------- /npm/test-unit.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | // --------------------------------------------------------------------------------------------------------------------- 3 | // This script is intended to execute all unit tests. 4 | // --------------------------------------------------------------------------------------------------------------------- 5 | 6 | const path = require('path'), 7 | 8 | colors = require('colors/safe'), 9 | Mocha = require('mocha'), 10 | recursive = require('recursive-readdir'), 11 | 12 | SPEC_SOURCE_DIR = path.join('test', 'unit'); 13 | 14 | module.exports = function (exit) { 15 | // banner line 16 | console.info(colors.yellow.bold('Running unit tests using mocha on node...')); 17 | 18 | // add all spec files to mocha 19 | recursive(SPEC_SOURCE_DIR, (err, files) => { 20 | if (err) { 21 | console.error(err); 22 | 23 | return exit(1); 24 | } 25 | 26 | const mocha = new Mocha({ timeout: 1000 * 60 }); 27 | 28 | files.filter((file) => { // extract all test files 29 | return (file.substr(-8) === '.test.js'); 30 | }).forEach(mocha.addFile.bind(mocha)); 31 | 32 | // start the mocha run 33 | mocha.run((runError) => { 34 | runError && console.error(runError.stack || runError); 35 | 36 | exit(runError || process.exitCode ? 1 : 0); 37 | }); 38 | }); 39 | }; 40 | 41 | // ensure we run this script exports if this is a direct stdin.tty run 42 | !module.parent && module.exports(process.exit); 43 | -------------------------------------------------------------------------------- /npm/test-library.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | // --------------------------------------------------------------------------------------------------------------------- 3 | // This script is intended to execute all library tests. 4 | // --------------------------------------------------------------------------------------------------------------------- 5 | 6 | const path = require('path'), 7 | 8 | colors = require('colors/safe'), 9 | Mocha = require('mocha'), 10 | recursive = require('recursive-readdir'), 11 | 12 | SPEC_SOURCE_DIR = path.join('test', 'library'); 13 | 14 | module.exports = function (exit) { 15 | // banner line 16 | console.info(colors.yellow.bold('Running library tests using mocha on node...')); 17 | 18 | // add all spec files to mocha 19 | recursive(SPEC_SOURCE_DIR, (err, files) => { 20 | if (err) { 21 | console.error(err); 22 | 23 | return exit(1); 24 | } 25 | 26 | const mocha = new Mocha({ timeout: 1000 * 60 }); 27 | 28 | files.filter((file) => { // extract all test files 29 | return (file.substr(-8) === '.test.js'); 30 | }).forEach(mocha.addFile.bind(mocha)); 31 | 32 | // start the mocha run 33 | mocha.run((runError) => { 34 | runError && console.error(runError.stack || runError); 35 | 36 | exit(runError || process.exitCode ? 1 : 0); 37 | }); 38 | }); 39 | }; 40 | 41 | // ensure we run this script exports if this is a direct stdin.tty run 42 | !module.parent && module.exports(process.exit); 43 | -------------------------------------------------------------------------------- /test/integration/esc-formdata/esc-formdata.postman_collection.json: -------------------------------------------------------------------------------- 1 | { 2 | "variables": [], 3 | "info": { 4 | "name": "Escaped characters in the form body are sent correctly", 5 | "_postman_id": "df4d105a-e01b-b219-9a65-266547e02cd0", 6 | "description": "A set of tests for proper replacement of form key value pairs with escaped characters", 7 | "schema": "https://schema.getpostman.com/json/collection/v2.0.0/collection.json" 8 | }, 9 | "item": [ 10 | { 11 | "name": "r1", 12 | "event": [ 13 | { 14 | "listen": "test", 15 | "script": { 16 | "type": "text/javascript", 17 | "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\";" 18 | } 19 | } 20 | ], 21 | "request": { 22 | "url": "https://postman-echo.com/post?a={{msg}}", 23 | "method": "POST", 24 | "header": [], 25 | "body": { 26 | "mode": "urlencoded", 27 | "urlencoded": [ 28 | { 29 | "key": "{{msg1}}", 30 | "value": "{{msg}}", 31 | "type": "text", 32 | "enabled": true 33 | }, 34 | { 35 | "key": "incollection", 36 | "value": "hello\\world", 37 | "type": "text", 38 | "enabled": true 39 | } 40 | ] 41 | }, 42 | "description": "" 43 | }, 44 | "response": [] 45 | } 46 | ] 47 | } 48 | -------------------------------------------------------------------------------- /docker/images/alpine/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:16-alpine 2 | LABEL maintainer="Postman Labs " 3 | 4 | ARG NEWMAN_VERSION 5 | 6 | # Set environment variables 7 | ENV LC_ALL="en_US.UTF-8" LANG="en_US.UTF-8" LANGUAGE="en_US.UTF-8" ALPINE_NODE_REPO="oznu/alpine-node" 8 | 9 | # Bail out early if NODE_VERSION is not provided 10 | RUN if [ ! $(echo $NEWMAN_VERSION | grep -oE "^[0-9]+\.[0-9]+\.[0-9]+$") ]; then \ 11 | echo "\033[0;31mA valid semver Newman version is required in the NEWMAN_VERSION build-arg\033[0m"; \ 12 | exit 1; \ 13 | fi && \ 14 | # Install Newman globally 15 | npm install --global newman@${NEWMAN_VERSION}; 16 | 17 | # Set workdir to /etc/newman 18 | # When running the image, mount the directory containing your collection to this location 19 | # 20 | # docker run -v :/etc/newman ... 21 | # 22 | # In case you mount your collections directory to a different location, you will need to give absolute paths to any 23 | # collection, environment files you want to pass to newman, and if you want newman reports to be saved to your disk. 24 | # Or you can change the workdir by using the -w or --workdir flag 25 | WORKDIR /etc/newman 26 | 27 | # Set newman as the default container command 28 | # Now you can run the container via 29 | # 30 | # docker run -v /home/collections:/etc/newman -t postman/newman_alpine run YourCollection.json.postman_collection \ 31 | # -e YourEnvironment.postman_environment \ 32 | # -H newman_report.html 33 | ENTRYPOINT ["newman"] 34 | -------------------------------------------------------------------------------- /test/cli/working-directory.test.js: -------------------------------------------------------------------------------- 1 | const path = require('path'), 2 | expect = require('chai').expect, 3 | 4 | workingDir = path.resolve(__dirname, '../fixtures/files/work-dir'); 5 | 6 | describe('newman run --working-dir --no-insecure-file-read', function () { 7 | it('should resolve file present inside working directory', function (done) { 8 | // eslint-disable-next-line max-len 9 | exec(`node ./bin/newman.js run test/fixtures/run/single-file-inside.json --working-dir ${workingDir}`, function (code) { 10 | expect(code, 'should have exit code of 0').to.equal(0); 11 | done(); 12 | }); 13 | }); 14 | 15 | it('should not resolve file present outside working directory with --no-insecure-file-read', function (done) { 16 | // eslint-disable-next-line max-len 17 | exec(`node ./bin/newman.js run test/fixtures/run/single-file-outside.json --working-dir ${workingDir} --no-insecure-file-read`, function (code, stdout) { 18 | expect(code, 'should have exit code of 1').to.equal(1); 19 | expect(stdout).to.have.string('AssertionError'); 20 | done(); 21 | }); 22 | }); 23 | 24 | it('should resolve file present outside working directory by default', function (done) { 25 | // eslint-disable-next-line max-len 26 | exec(`node ./bin/newman.js run test/fixtures/run/single-file-outside.json --working-dir ${workingDir}`, function (code, stdout) { 27 | expect(code, 'should have exit code of 0').to.equal(0); 28 | expect(stdout).to.not.have.string('AssertionError'); 29 | done(); 30 | }); 31 | }); 32 | }); 33 | -------------------------------------------------------------------------------- /test/integration/disabled-and-duplicate-variables/disabled-and-duplicates.postman_collection.json: -------------------------------------------------------------------------------- 1 | { 2 | "info": { 3 | "_postman_id": "72ec18aa-a3cb-450d-ae88-4b6b59f69939", 4 | "name": "disabled-and-duplicates", 5 | "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json" 6 | }, 7 | "item": [ 8 | { 9 | "name": "https://postman-echo.com/get", 10 | "event": [ 11 | { 12 | "listen": "test", 13 | "script": { 14 | "id": "47dc2d0e-2ada-400a-94a0-ed3fd1f4280c", 15 | "exec": [ 16 | "pm.test('Disabled variable', function () {", 17 | " pm.expect(pm.environment.has('justDisabled')).to.be.false;", 18 | " pm.expect(pm.environment.get('justDisabled')).to.be.undefined;", 19 | "});", 20 | "", 21 | "pm.test('1 Enabled and 1 Disabled variable', function () {", 22 | " pm.expect(pm.environment.has('oneDisabled')).to.be.true;", 23 | " pm.expect(pm.environment.get('oneDisabled')).to.equal('1');", 24 | "});", 25 | "", 26 | "pm.test('Duplicate variable', function () {", 27 | " pm.expect(pm.environment.has('duplicate')).to.be.true;", 28 | " pm.expect(pm.environment.get('duplicate')).to.equal('2'); // last enabled", 29 | "});" 30 | ], 31 | "type": "text/javascript" 32 | } 33 | } 34 | ], 35 | "request": { 36 | "method": "GET", 37 | "url": { 38 | "raw": "https://postman-echo.com/get", 39 | "protocol": "https", 40 | "host": [ 41 | "postman-echo", 42 | "com" 43 | ], 44 | "path": [ 45 | "get" 46 | ] 47 | } 48 | } 49 | } 50 | ] 51 | } 52 | -------------------------------------------------------------------------------- /test/fixtures/ssl/server2.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIEaTCCA1GgAwIBAgIGEnGFJyEJMA0GCSqGSIb3DQEBCwUAMGIxCzAJBgNVBAYT 3 | AkFVMQwwCgYDVQQIDANOU1cxDzANBgNVBAcMBlN5ZG5leTEPMA0GA1UECgwGTmV3 4 | bWFuMQ0wCwYDVQQLDARUZXN0MRQwEgYDVQQDDAt0ZXN0Lm5ld21hbjAeFw0xOTEx 5 | MjEwNTExMTBaFw0yOTExMTgwNTExMTBaMFMxCzAJBgNVBAYTAkFVMQwwCgYDVQQI 6 | DANOU1cxDzANBgNVBAoMBk5ld21hbjENMAsGA1UECwwEVGVzdDEWMBQGA1UEAwwN 7 | dGVzdC5zZXJ2ZXIuMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANQl 8 | cwIuSxBhqWAjWmn+Cyx5t7J6I2SWGSceksXZieoIDWuh9fkXvMZVJovGEZtrRSwQ 9 | ugGY0wZNaZNzt09j5b8q34VONw0N1IlxtaLmsq8fPwiBfrFcZI1LNyOcCXt55Rtv 10 | V4xA2YoMgNXSb3rVDK4a1vPrJRkBXfnLHFmczAzG3MTaUY27GwKkGURtV45C95qc 11 | hKkxSfSE6xtE08uck3KSwBHOkj9TNrhBNXz4YffH4W13Z3SwJHFH6t085p6M+Hs5 12 | m9nQb2wLFLmHgm7crcPDnA/+ZSFMfdERvD4AutmoJ2LsTqNjBSaLppYiR2pMlsUu 13 | V6qwaFRyRuKrPQMcdQ8CAwEAAaOCATIwggEuMAkGA1UdEwQCMAAwEQYJYIZIAYb4 14 | QgEBBAQDAgZAMDMGCWCGSAGG+EIBDQQmFiRPcGVuU1NMIEdlbmVyYXRlZCBTZXJ2 15 | ZXIgQ2VydGlmaWNhdGUwHQYDVR0OBBYEFMqtFuQ8CGeKDbSLjMGp9Rx3JtFSMIGU 16 | BgNVHSMEgYwwgYmAFAh+6n6GHeBG9gaRjkJYQM3syz2WoWakZDBiMQswCQYDVQQG 17 | EwJBVTEMMAoGA1UECAwDTlNXMQ8wDQYDVQQHDAZTeWRuZXkxDzANBgNVBAoMBk5l 18 | d21hbjENMAsGA1UECwwEVGVzdDEUMBIGA1UEAwwLdGVzdC5uZXdtYW6CCQCeQzo7 19 | IRQKgjAOBgNVHQ8BAf8EBAMCBaAwEwYDVR0lBAwwCgYIKwYBBQUHAwEwDQYJKoZI 20 | hvcNAQELBQADggEBAAYGPG/dvUo0VHscEQyOjjThtJ6d4kisKAtXW7rPtACJg6nn 21 | gDYgdWHOdZRh/gAF4u6B5Wi86bUgt0Rs3ToDwevV9+FBkxba96+KTh64J8XZF94P 22 | m1FTB5rSeS4SDNQRK+OlBh5POtGVLEO3p7v+iAjAkM9KE8Dl/Z4xVnELbvKImr7Y 23 | yDVPREMEL6PqLPtwVuJfYNB3c2rUi2560us1GxqW/q76rfxiEdv0AEZGk8PTJRZS 24 | ZO7MH2H3naQxomvPuzaGhEWNtSO/tqfBYSMmeqV8QKu/uxoUZ7gDLqMsDFd81QA+ 25 | IAX7dDoLxBFpT7oeMrcj5BRZT/QbjqWw1wxq2qQ= 26 | -----END CERTIFICATE----- 27 | -------------------------------------------------------------------------------- /examples/find-unique-urls-in-run.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | /** 3 | * @fileOverview 4 | * This sample code illustrates how to read a collection JSON file in NodeJS,run it using Newman and then log all the 5 | * unique URLs that were requested. 6 | */ 7 | var newman = require('../'), // require('newman') 8 | uniqueUrls = {}; // here we will maintain the unique URLs 9 | 10 | // call newman.run to pass `options` object and listen to events 11 | newman.run({ collection: require('./sample-collection.json') }) 12 | .on('start', function (err, args) { 13 | if (err) { return; } 14 | 15 | console.info(`Running ${args.cursor.length} request(s) and ${args.cursor.cycles} iteration(s)`); 16 | }) 17 | .on('request', function (err, args) { 18 | if (err) { return; } 19 | 20 | var url = args.request.url.toString(); 21 | 22 | // store the URL string as key of the object so that we can quickly do hashing of unique URLs and add a counter 23 | if (uniqueUrls[url]) { 24 | uniqueUrls[url] += 1; // increment counter if the url was already called 25 | } 26 | else { 27 | uniqueUrls[url] = 1; // otherwise start a new counter 28 | } 29 | }) 30 | .once('done', function (err) { 31 | var urls = Object.keys(uniqueUrls); // get list of all unique urls as an array from the object hash 32 | 33 | // now output the result to console 34 | console.info(`The collection run completed ${err ? 'with' : 'without'} error(s).`); 35 | console.info(`Total ${urls.length} unique URLs requested.`); 36 | 37 | urls.forEach(function (url) { 38 | console.info(`${uniqueUrls[url]}: ${url}`); 39 | }); 40 | }); 41 | -------------------------------------------------------------------------------- /test/fixtures/ssl/client3.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIEmzCCA4OgAwIBAgIBATANBgkqhkiG9w0BAQsFADCBijELMAkGA1UEBhMCVVMx 3 | CzAJBgNVBAgMAkNBMQswCQYDVQQHDAJTRjEQMA4GA1UECgwHUG9zdG1hbjEaMBgG 4 | A1UECwwRcG9zdG1hbkBsb2NhbGhvc3QxEzARBgNVBAMMClRlc3RDbGllbnQxHjAc 5 | BgkqhkiG9w0BCQEWD2RvLm5vdEBlbWFpbC5tZTAeFw0yMDA1MTIxOTUwMTVaFw00 6 | NzA5MjcxOTUwMTVaMIGKMQswCQYDVQQGEwJVUzELMAkGA1UECAwCQ0ExCzAJBgNV 7 | BAcMAlNGMRAwDgYDVQQKDAdQb3N0bWFuMRowGAYDVQQLDBFwb3N0bWFuQGxvY2Fs 8 | aG9zdDETMBEGA1UEAwwKVGVzdENsaWVudDEeMBwGCSqGSIb3DQEJARYPZG8ubm90 9 | QGVtYWlsLm1lMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAs3IzJMnb 10 | QjjSJCjE/Euuxq7RBZ316+M7v36VnmgYkAXwM86Ckl8MSZYSSRE9ekxzsxQxNhs9 11 | Pa93xFJPW/17CG4SRDkagCapFRa3fnf6cw4DsvW12/Dcnwz7tpSBb9KA1IU8c/QB 12 | DjxY+H7BLQfmGfk4CiuybyXoEsoYMydFU1Z6MvNKIWfFoPO2tnxLuyTiFIzAd2Lp 13 | 77mIuLEjfg2pmcnFpemd55zrgqi+OLeJjxQqCoiSog9/45HzDFEe8S5a+/laBjsd 14 | G3ulPvGbuQbvL+LDttEIlneHsKnlT/z6f7YE+fTKpc+ryCGngFVil4lAbkjgDNDO 15 | kLEshioJcmMWCwIDAQABo4IBCDCCAQQwCQYDVR0TBAIwADAsBglghkgBhvhCAQ0E 16 | HxYdT3BlblNTTCBHZW5lcmF0ZWQgQ2VydGlmaWNhdGUwHQYDVR0OBBYEFN15KN+K 17 | dHIry3FADNXXUf3/yIYSMIGpBgNVHSMEgaEwgZ6hgZCkgY0wgYoxCzAJBgNVBAYT 18 | AlVTMQswCQYDVQQIDAJDQTELMAkGA1UEBwwCU0YxEDAOBgNVBAoMB1Bvc3RtYW4x 19 | GjAYBgNVBAsMEXBvc3RtYW5AbG9jYWxob3N0MRMwEQYDVQQDDApUZXN0Q2xpZW50 20 | MR4wHAYJKoZIhvcNAQkBFg9kby5ub3RAZW1haWwubWWCCQDVmzvauKidhzANBgkq 21 | hkiG9w0BAQsFAAOCAQEAg8i445PKv94inwykzazREyGO2vC3k+Sgu6QHfI5kUZmC 22 | wBRogAnrWLmAhY06O7y2XZm0/07wD/e2h5skitGX4wxbwKktiejfbMeEulJXIwG7 23 | 3sYdQ5/aQBTvdCApzh4DobbBFxudokZSR7qPk6P3CgVQgG40a1pgBVSuntgixWRm 24 | Gm4ggjc02ZgcHcu4FVHUFOh0TRvFmbCtOI/x8mOB5pZ+G5c+t3Au7WbVxnyYUysD 25 | RaO6faj/ve0c6COI/KOw4xGlAwkl5W5wIzdzCyYrD35tz3/nqt3/MkxNoM/8vf5B 26 | DvHBT6tlqvMCSdCcyldhkOhy/rYV2HVVp+fGgaIo3A== 27 | -----END CERTIFICATE----- 28 | -------------------------------------------------------------------------------- /test/fixtures/ssl/server3.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIEmzCCA4OgAwIBAgIBATANBgkqhkiG9w0BAQsFADCBijELMAkGA1UEBhMCVVMx 3 | CzAJBgNVBAgMAkNBMQswCQYDVQQHDAJTRjEQMA4GA1UECgwHUG9zdG1hbjEaMBgG 4 | A1UECwwRcG9zdG1hbkBsb2NhbGhvc3QxEzARBgNVBAMMClRlc3RDbGllbnQxHjAc 5 | BgkqhkiG9w0BCQEWD2RvLm5vdEBlbWFpbC5tZTAeFw0yMDA1MTIxOTUwMTVaFw00 6 | NzA5MjcxOTUwMTVaMIGKMQswCQYDVQQGEwJVUzELMAkGA1UECAwCQ0ExCzAJBgNV 7 | BAcMAlNGMRAwDgYDVQQKDAdQb3N0bWFuMRowGAYDVQQLDBFwb3N0bWFuQGxvY2Fs 8 | aG9zdDETMBEGA1UEAwwKVGVzdENsaWVudDEeMBwGCSqGSIb3DQEJARYPZG8ubm90 9 | QGVtYWlsLm1lMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtj6Kynl4 10 | 5Ec7WU1XqSqsXXnh6qBB8Msf7outvZBN7+PD+pU0NGa9jLB+Gd5MJBRFOXomD2Bv 11 | OqnMlrJs2wOV9TAvPHKS8UGw/cJWX9kLM5S2Pl7jqsVuo1hUjkgeumeJ+iuBagXn 12 | XFcjSBFjTEOSZ69wdK0KadijCKEz6wtVi0OBZ5zqyWNshvzVlYNHyEnU0Vt6PDWF 13 | dISkGx+/ixUnW/iQf2InyoVvKAn3iKaCqSnNOHvpyecae1Yv3l1ntw9awrTr0fZn 14 | 65TEy8D1OGBNKdUFCsHbl3w1AJpDP9wBhCmvEX/lMl5bTK8DLM+e67TEYlkkDQXW 15 | Pn5Og1ok1bbsXwIDAQABo4IBCDCCAQQwCQYDVR0TBAIwADAsBglghkgBhvhCAQ0E 16 | HxYdT3BlblNTTCBHZW5lcmF0ZWQgQ2VydGlmaWNhdGUwHQYDVR0OBBYEFMAuJvYg 17 | 8x0AM21MLaQ2GxpYvsv4MIGpBgNVHSMEgaEwgZ6hgZCkgY0wgYoxCzAJBgNVBAYT 18 | AlVTMQswCQYDVQQIDAJDQTELMAkGA1UEBwwCU0YxEDAOBgNVBAoMB1Bvc3RtYW4x 19 | GjAYBgNVBAsMEXBvc3RtYW5AbG9jYWxob3N0MRMwEQYDVQQDDApUZXN0Q2xpZW50 20 | MR4wHAYJKoZIhvcNAQkBFg9kby5ub3RAZW1haWwubWWCCQDVmzvauKidhzANBgkq 21 | hkiG9w0BAQsFAAOCAQEAWubsEkBJ3EfnapHOrD1nP7MT3iqrBdyNmKnNiDnP5yCp 22 | ug6Y0SGZ6/oLoBQu5BTq52qvqx+FWcHOm4Voc90CMpCnRroGmlX/ecXXwYd2icRr 23 | TTC4LU2CccfZ6eZeIbPMJih8CV1n53Jl/TauK80UpsYkVneaStqWalYxqJznejyU 24 | UF6Yo0bclz0mI/59+myI+PXhLta7rvz2DJ2ECKG8oy+Ak8oTFPUOoSs0lam15WwB 25 | ugvatYbi5zc5sBkh6NRKaoZjMf5WemtHG3ruzOlKbPcvEAHnNvQ/5BC5DAkEmDlN 26 | Tq/VVw9d4bpFEGl126ymiwnRCcHv4LxOK8q/wEyKVg== 27 | -----END CERTIFICATE----- 28 | -------------------------------------------------------------------------------- /test/fixtures/ssl/ca3.key: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | MIIEpAIBAAKCAQEA2c3B3urKLmkimxO9i1mueVqBzSMn+fygV87DwL8RO899S3SX 3 | O2ZtHECxLgCR3qRXUS2RwY5JYie1L5qJYnOrgBO/mhxuX9KbuUz5xSr7vOWzVPlq 4 | CMBbKa24bDfJ/NE036yrLqIUSx2xeUoUp9z0rqQaXHLezBX5w6DYCwb0/RmY+sWj 5 | 23/NnMTzDituPGDjUp/6xIBOYBpolXDYLVCvjoO3UnUJ5ffAMyuanr9Myx1j8lO0 6 | rkjUV/IPPZfrv4OQEu3MdWKOyENWnfQVK7VHsm9RlBf6WcH0XiWGQdmdd3uU7HOM 7 | d132QLbco2j1U9IKnX7h7Wsi08Af2WStjzpePwIDAQABAoIBAQDZsNSoGGXR81Ua 8 | SKW3RQCk3DhGL3BCZSRh/xAacx4neKATrcmGHj7J8ULl5r3lGL8JLRG0sqFYELYA 9 | iWXtWA0+6v4ja21KKvdoQq6WSfrod3FBajR34MJ9Ktvclfo1zWgac7t41ZiQ53G9 10 | 97Qjfy2z6+NJKarTstc7l2S3yNFOsdCXeqKLVCPH/s0EqyPRIQauNSBmVfWtJaXD 11 | tiuz/IGH3ICiiaM7cSkKeEQwVmGatco+70yf8bwfCSPRALnnFz8ZqkESgQgGvLZr 12 | 3Cd0U1TzAwtCIKNCxWBX84Roiw5VbRTusqLonGKk9icknJX1SYjyUbiyL1YhIVjn 13 | 16pWSKxBAoGBAP7ReFscvS3OlgAQNy01UD8Ntc7g4XRxlRwJ6/gOwr817XcGx8E3 14 | OMtlxhz4yL/SsSyAzG3svQaJmiGaBkG58qWXq2w1Qy3lsnHpqzG8h7iyAory8/0A 15 | QIGCqxMxmudPV1wvfm7bkkQAz5s9Tz/uEVWhwxhkK1jzZIQy/6qz2bghAoGBANrQ 16 | V5cM5AL/1cR7fUc0l6rdiAmhvf/vUBPF13VZolh1o/aRIfb0IYIF+Hnv4YJQ9Twm 17 | aQxMxGQI8DhrENaCe96T0C/LHjEzpptYQXMpOcFMkJj6FY8Z4pxEfSAMe8MmVZK9 18 | x6ckRv7jb4ncrUPZPhnp49GuZItM0x0E4Z69hcpfAoGAIp/B09eG2ReOCDor1Se+ 19 | XKL3RkIGQHVChonOl2kiCys/tgGk2NsxC2orzjn7xRzS2DI0FOerE51U5SXxnbKv 20 | htKiB1UBaNYiNhpDGcH9SxpdABZdEs6a9T4VEsmVu8JrI2qMqnGJYVYe34AoKY6m 21 | qlUNll3eCfsgeFoZpU9E0SECgYEApg7G6lNWFxCg4mP1RzyafYlx3B1rW/f6BYd3 22 | ZA+KLSfaLx0lcY0EgPCXCbMKqSNXeTaNMlBwGprN84MNXD3aU6hJrnuvhhd0sR/h 23 | S8xVkGTSt8XS5q72UzGG4/OVWRyWhK6R/j6Bwp5H35AhzgPoJTJjOpXmp/C9pqA1 24 | uYqLJnECgYAQoeFRKlwiBPFfONepKdFWkoeqzQGQOvLMjHh+atiAY8X3K45lVZeZ 25 | G2J6ZGKYziBFBfVLkvyRKzvtcFE4qAX35FhWtP4MgCN1pepsfRhUBxRl5NcKIdSh 26 | xa0raTFHSZ8v6LFsRgdCJ3yDP/7r+4y1fF7wzGdhm2YOc4yhTxRbGw== 27 | -----END RSA PRIVATE KEY----- 28 | -------------------------------------------------------------------------------- /test/fixtures/ssl/client3.key: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | MIIEpAIBAAKCAQEAs3IzJMnbQjjSJCjE/Euuxq7RBZ316+M7v36VnmgYkAXwM86C 3 | kl8MSZYSSRE9ekxzsxQxNhs9Pa93xFJPW/17CG4SRDkagCapFRa3fnf6cw4DsvW1 4 | 2/Dcnwz7tpSBb9KA1IU8c/QBDjxY+H7BLQfmGfk4CiuybyXoEsoYMydFU1Z6MvNK 5 | IWfFoPO2tnxLuyTiFIzAd2Lp77mIuLEjfg2pmcnFpemd55zrgqi+OLeJjxQqCoiS 6 | og9/45HzDFEe8S5a+/laBjsdG3ulPvGbuQbvL+LDttEIlneHsKnlT/z6f7YE+fTK 7 | pc+ryCGngFVil4lAbkjgDNDOkLEshioJcmMWCwIDAQABAoIBACWzY41iH3+9QmE4 8 | c5JyMCksB1w/wLArkJz98l9SjX6M0NeBlqs77u/y6KqTRbBRKanBH0m31VkFaYtE 9 | o8m26sdtoMbWnHu6I6H7oNegS20qz5okx22LID8GUkgc0Uj2F/0OdRIDfMlJ4oNq 10 | 1hko5K4mTyDL53Q0qZpw/T6aDJWiZoBH7Tk6kTVEC75581dtX9XYz3T3ijPp6VA7 11 | byJ1YsN8KY/EVWR+NcLwcAGQJem1CEyViTlpbLMgyONEv/6NmyGYQgmtd6krYAxC 12 | IQQLKNDprNQubWuaxy6aEIWB2s891wQbGXmurDqMEYo0Q8OxARulXp8bE68OfXGK 13 | z72I+bkCgYEA1suFS7x49+wLN+PFuyKsopGLqyyl/A8DAPrfbIDcfoGaYTL7Z8BT 14 | P8teYg9MsDvH7JEuhayy0Sw/b8U5XidhupIM35VfenCu/Sylfd+V42/AQRPqOoSi 15 | orahQnGxnauYTKamNHA/RIXjxsjTYjpahZuXfPv1QtTt39ZTuwHzqGUCgYEA1d62 16 | DIDJy95+r3OLOqdxJBCqwKm+5Zh/Zjdv955Xk4fopad0zLM45UaKumz6yHu4Cg3o 17 | qJje9T7oiQpW2eHr1Kepg9TNQdNeGf6WBENN0NRfdhbNaj74cn7kHkZP97iIBu97 18 | U/yhkN1ac+1WMraZHqcQ6QQSUr63QsuJAx1VBa8CgYEAwCoEbuWHNAaxYqccV3eG 19 | C0s7MUEYnpCvl0jaajA/E87PVvZNhVzDHefL4N7fNSvGiRa6EE2ZDRoRBuXjlSCW 20 | hlvzuHPin6AAbfBrfllxt7Bax94RR5kyB3BshQ1CYlUKREkzmOZzM9K1HTq+Irsi 21 | ETZKKT8hBVGKHx+YeU4dtyECgYEAsoFMmWr1A0AVpQNfdflDqcJvgpcrSh7aVsp2 22 | ncp/dhe9ymXWSvRbzKHwMGG9f5Ajr+CkC/RsQ23aUGdczkaOu9Ok3O/E0ehFZpTj 23 | SXOTg3V+p+WoVcFxRL88TziIjk5q2r8PxK3bfDoEwTWa+IEHlFoE9zf6wy2DcDDJ 24 | jtvwlukCgYBI/TOWJiajfg5oPAnovYx/Wxb50mzeY/QCqF5Iw8GYviAXYsyZ7WKy 25 | f65L5/sKPHPcz/pxz/Q+lE+/5LKa3KQ3F9LXYP6+0/rzmlQNR2qTa+7uo4QLM1un 26 | u7acuHEkBOJkhJO5fQFHxiaqjRCNxs+semha3ejmlyzReoyNbPi2xQ== 27 | -----END RSA PRIVATE KEY----- 28 | -------------------------------------------------------------------------------- /test/fixtures/ssl/server3.key: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | MIIEpAIBAAKCAQEAtj6Kynl45Ec7WU1XqSqsXXnh6qBB8Msf7outvZBN7+PD+pU0 3 | NGa9jLB+Gd5MJBRFOXomD2BvOqnMlrJs2wOV9TAvPHKS8UGw/cJWX9kLM5S2Pl7j 4 | qsVuo1hUjkgeumeJ+iuBagXnXFcjSBFjTEOSZ69wdK0KadijCKEz6wtVi0OBZ5zq 5 | yWNshvzVlYNHyEnU0Vt6PDWFdISkGx+/ixUnW/iQf2InyoVvKAn3iKaCqSnNOHvp 6 | yecae1Yv3l1ntw9awrTr0fZn65TEy8D1OGBNKdUFCsHbl3w1AJpDP9wBhCmvEX/l 7 | Ml5bTK8DLM+e67TEYlkkDQXWPn5Og1ok1bbsXwIDAQABAoIBAAlHi/edUcuF2P7G 8 | EmWZt6cW0qsIt/LT1O9ni1QwqddCKLN0r3DPnm0we2tDx2q64X94ucFkrqU1CibO 9 | NP694v/WEUGpr9O6/ZEeORmuSoS42MK6QCts3CJTGBMalv300bC8UF2eqVYpVbGQ 10 | uRakBitjYn1+Zh5Xmo2Q77zTGer6UfBOkLnpZWGuijrqngFRLSCUDQYUhg740GQZ 11 | Gppb4Qm1gGJhHbQGzy/yExiQuPTpZCTAFTGnjHkt7OToUBrtE3Fp+c5gvv7vIIqg 12 | +PsygAEfUhukx1wFcz9GcSyg2vyeP8C6TFxFg3T4KBbvHeIgO4w1H7cnJaYnKrXJ 13 | aRuxW/kCgYEA4+KV/Z8lgxmwBumU/ldsEdXcjW0qJ6nNa49J8MQ6P+9EFA70vblk 14 | j8IFPGQ2w8jcW6jiy2Ee5A5Tfj2l7t7brkr7/zvIGyBoLY02RPe4RAQxSX9mhER8 15 | 5cy+xGNhLX51kYH827bKzYlNBFGCh69exhpD7iDjkEK2beIc7RryP40CgYEAzLp1 16 | jDyRR3ltV2uno0en8y27GcEKSB66pS6qGk5f5f+ml+mZhPuveHcHfVZQygcrrzq7 17 | uMgBgmUnqkai/O40kOOhDHkj1oXQV5bNTrvmxgzCP2vV2w9s6le1Gm9jTljsAz+5 18 | RKnYdxhWLUM8Jo9o95LUPQkklwyE1qkOC6/WupsCgYEApeBQ/YPSclNIZj+wTFKm 19 | P3VETU2g2a4n8JskXzT2kYNAMrmQPGmuYVYBKaxokKqse6u7Kf9P1QD4lXOaTP27 20 | Omsqcua5CcXVDxMy5ZDLd/b1SWKK5MxVfZBDbABKxCrAuWG9BNFRXbsLbJFISivE 21 | +L41pCgcfO2SjPmBxLVQkCECgYBKO3Wx0qhOxT2bTCKttqa0KynDTdZ/jfzZNhFh 22 | lnd5OvhZ7s7GhEf8oxQpIyoKBw2U7PPyLTs235zBRfmFQo3210Km9inDeCOyDrEE 23 | 0mb7+tZYDq6tTmuMkR7OpgLY/q8dAncX6YnerQlaQh3GUYua8TdZpj4JMvXbq9K2 24 | 9Bwk7wKBgQCYZ0H16BZBf4spiKnjKREZvQBKCbcxS5Rne7FTatBKDHG3ZsCcM6aw 25 | pcbVvcjrJqinqOjnvOJA+15OMLKk8ApPibPpB6L3ZC2XSgzgDxhuru2J8dUTqDKO 26 | 2xNI6TCorwfo+Mt3h66+/ldXJw2VdTXLM0k/ivj2h0Bwi3iWEZO9LA== 27 | -----END RSA PRIVATE KEY----- 28 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 9 | 1. Newman Version (can be found via `newman -v`): 10 | 2. OS details (type, version, and architecture): 11 | 3. Are you using Newman as a library, or via the CLI? 12 | 3. Did you encounter this recently, or has this bug always been there: 13 | 4. Expected behaviour: 14 | 5. Command / script used to run Newman: 15 | 6. Sample collection, and auxiliary files (minus the sensitive details): 16 | 7. Screenshots (if applicable): 17 | 18 | 25 | 26 | 27 | 40 | -------------------------------------------------------------------------------- /test/fixtures/run/nested-requests-report-test.json: -------------------------------------------------------------------------------- 1 | { 2 | "info": { 3 | "_postman_id": "eb3db066-938a-4fe9-8d6d-d1d288b1c25c", 4 | "name": "Nested request in test", 5 | "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json" 6 | }, 7 | "item": [ 8 | { 9 | "name": "Nested request test", 10 | "event": [ 11 | { 12 | "listen": "test", 13 | "script": { 14 | "id": "63864333-932a-49b1-8daf-2bfb98650ae6", 15 | "exec": [ 16 | "pm.test(\"Status code is 200\", function () {", 17 | " pm.response.to.have.status(200);", 18 | "});", 19 | "pm.sendRequest({", 20 | " url: 'https://postman-echo.com/get?key2=val2',", 21 | " method: 'GET'", 22 | "}, (err, res) => {", 23 | " if (err) {", 24 | " console.log(err);", 25 | " } else {", 26 | " var resData = JSON.parse(res.stream.toString()).args;", 27 | "", 28 | " pm.test('Nested request JSON response: \"key2\": \"val2\"', () => {", 29 | " pm.expect('val2').to.equal(resData.key2);", 30 | " });", 31 | " }", 32 | "});" 33 | ], 34 | "type": "text/javascript" 35 | } 36 | } 37 | ], 38 | "request": { 39 | "method": "GET", 40 | "header": [], 41 | "body": { 42 | "mode": "raw", 43 | "raw": "" 44 | }, 45 | "url": { 46 | "raw": "https://postman-echo.com/get?foo1=bar1", 47 | "protocol": "https", 48 | "host": [ 49 | "postman-echo", 50 | "com" 51 | ], 52 | "path": [ 53 | "get" 54 | ], 55 | "query": [ 56 | { 57 | "key": "foo1", 58 | "value": "bar1" 59 | } 60 | ] 61 | } 62 | }, 63 | "response": [] 64 | } 65 | ] 66 | } -------------------------------------------------------------------------------- /test/fixtures/run/single-file-inside.json: -------------------------------------------------------------------------------- 1 | { 2 | "info": { 3 | "name": "Example Collection with a single GET request", 4 | "schema": "https://schema.getpostman.com/json/collection/v2.0.0/collection.json" 5 | }, 6 | 7 | "item": [{ 8 | "name": "A Form-data request", 9 | "event": [{ 10 | "listen": "test", 11 | "script": { 12 | "type": "text/javascript", 13 | "exec": [ 14 | "pm.test(\"file uploaded\", function () {", 15 | " var jsonData = pm.response.json();", 16 | " pm.expect(jsonData.files).to.eql({ ", 17 | " \"test.json\": \"data:application/octet-stream;base64,eyJzb21lIjogImpzb24tc3RyaW5nIn0K\"", 18 | "});});" 19 | ] 20 | } 21 | }], 22 | "request": { 23 | "url": "https://postman-echo.com/post", 24 | "method": "POST", 25 | "body": { 26 | "mode": "formdata", 27 | "formdata": [ 28 | { 29 | "type": "file", 30 | "key": "somefile", 31 | "src": "test.json" 32 | } 33 | ] 34 | } 35 | } 36 | }, 37 | { 38 | "name": "A Binary body request", 39 | "event": [{ 40 | "listen": "test", 41 | "script": { 42 | "type": "text/javascript", 43 | "exec": [ 44 | "pm.test(\"file uploaded\", function () {", 45 | " var jsonData = pm.response.json();", 46 | " pm.expect(jsonData.data).to.eql({ some: 'json-string' });", 47 | "});" 48 | ] 49 | } 50 | }], 51 | "request": { 52 | "url": "https://postman-echo.com/post", 53 | "method": "POST", 54 | "body": { 55 | "mode": "file", 56 | "file": { 57 | "src": "test.json" 58 | } 59 | } 60 | } 61 | }] 62 | } 63 | -------------------------------------------------------------------------------- /test/fixtures/ssl/ca2.key: -------------------------------------------------------------------------------- 1 | -----BEGIN PRIVATE KEY----- 2 | MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDr/qtOyqmI4kMX 3 | KS8z6Nug260VcT3MgWzwprm0eTiJGtU+NmgpihSnWun1zPRK2haeFIsp5t4JXhDn 4 | it5I7RQhN99wZCZBN3I4uP2GFgTBPCMRbQYGBFpvQaoqrROl0UJ7Ro8/qyZ7lm8E 5 | aDNQYz7EG+P2rjgWou/QmhYCTzgnqAJb9KJMd2fAR0ty1SYF2O4JsZb/eJKroqxn 6 | eBaPOQXQOdWJrLFIcIvwzRPswP9sen9kr8AOFjCmo+NyzY6Xlh858mnlgSwmkNAZ 7 | iblIu3bRXYKrw5fmszvMazmDZaEARWiHZTzmUMe1SU9MHV5aPGu9crx+2iGUfH5O 8 | gO3OztMRAgMBAAECggEBAJeH+bVo+fzz08JuZmm9bjDWfUfUY6sJu8q2M23HnF6k 9 | xSHiS3XIvMRM4wc6Z+4cJQOyCz2HiTCYnuAd0ecfm5pMxwLiu5GKqaP0XI2ZW8o7 10 | 9AR/bau1ZeAkWMB4S7JgMID5aIeoPNiEWpqI0dIfN7Eye2jsqwUV8EiQd+tZtKP4 11 | yHCRKt4Vh4l5VaVylAnTV7vmHC7dootZkMTn4c3sV8wGe69gdWvqsVw3UEeg2Zb4 12 | fcdmF3n6nyDaz64xZwN5Oa6UJPRa2px2b0oBTiUAuLZlpMV60DN+xvzeXXRLxMn5 13 | Y8uO9fMeImLpQEwECLrb87wJv/++s7Y3AUVNfamKOLUCgYEA/FKlPFWg9bj13dGM 14 | jLEU8GUwjdBxb0HyFwfkRcpk5v4pU0/cMyacnlEjjpqxo9zvzWW0I9iepG+SRTm4 15 | AEvEbNulFKOPT8Z5pvqSsVh2fIaxnpXTbL/EYB9PZRLKXSd4r7ztNYW2NwUsR9i9 16 | miNwgEIebXJoCwvMC3kgf1IMgOsCgYEA728bm1VRdMpctNINvoFFK65cOuwu9V3s 17 | ccgvdrjUvhvcnj9QI1bxNmhEjMFEA+FXEOx4tlAQP8dv1g0hX/V36Mrn59Seh3jW 18 | gCSQczUGqoSYry7Ks8Lrm0jR6c0WK2k3BsN0wLeK6lP/yNAzRfOYEQd6amczgqNq 19 | cuR4qATUXPMCgYASOupjTJB/kGh7KUutUpH/uF/krx2y+yHBljlg7XmS0uQrd8ai 20 | D3UbXyNhhz20aB8PSPzV5i24FbOMutnXc6Hyd4Aa2KJfEijx7oKwu4J8BsNIgOyw 21 | m75Vb42t8MicKGDo2Y6N4mZC3WXQnxE71LmpGp3WLIDl42lPnuXBLS1oFwKBgBMU 22 | 8MdNYmODaSYEA5JmLQQRLkqH3iox5REgWiAFFPddsxRtiU53tFuYrbXmBSyl/dFc 23 | dzZYZSMgGtqdS0ahgn/sA9VnDYdQaw/lWhnEZRab4Ks9eGwhIbPLdudCL/0fsoH4 24 | e8qMFiccsKrpZNyzUDAzP19RgDpuGaK0cKU7VU1fAoGBANJSesEEEpqkvRWcNY7l 25 | kDyE9I2L3wsCAF71bPwRGoZc/fXGYy9qx0faGFWBFGm8VP3r3hqmLbWktak13GQb 26 | kc8ce3LyCeuHnonPNSODmSfx62qQJwlnhz0kSr/CpIV/LoWH79adnFSxtSaZnfqR 27 | z0ATGCvJ4Y8uittsmyGSUUwV 28 | -----END PRIVATE KEY----- 29 | -------------------------------------------------------------------------------- /test/fixtures/run/nested-requests-fail-report-test.json: -------------------------------------------------------------------------------- 1 | { 2 | "info": { 3 | "_postman_id": "eb3db066-938a-4fe9-8d6d-d1d288b1c25c", 4 | "name": "Nested request in test with failing test", 5 | "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json" 6 | }, 7 | "item": [ 8 | { 9 | "name": "Nested request test", 10 | "event": [ 11 | { 12 | "listen": "test", 13 | "script": { 14 | "id": "63864333-932a-49b1-8daf-2bfb98650ae6", 15 | "exec": [ 16 | "pm.test(\"Status code is 200\", function () {", 17 | " pm.response.to.have.status(400);", 18 | "});", 19 | "pm.sendRequest({", 20 | " url: 'https://postman-echo.com/get?key2=val2',", 21 | " method: 'GET'", 22 | "}, (err, res) => {", 23 | " if (err) {", 24 | " console.log(err);", 25 | " } else {", 26 | " var resData = JSON.parse(res.stream.toString()).args;", 27 | "", 28 | " pm.test('Nested request JSON response: \"key2\": \"val2\"', () => {", 29 | " pm.expect('val2').to.equal('wrongValue');", 30 | " });", 31 | " }", 32 | "});" 33 | ], 34 | "type": "text/javascript" 35 | } 36 | } 37 | ], 38 | "request": { 39 | "method": "GET", 40 | "header": [], 41 | "body": { 42 | "mode": "raw", 43 | "raw": "" 44 | }, 45 | "url": { 46 | "raw": "https://postman-echo.com/get?foo1=bar1", 47 | "protocol": "https", 48 | "host": [ 49 | "postman-echo", 50 | "com" 51 | ], 52 | "path": [ 53 | "get" 54 | ], 55 | "query": [ 56 | { 57 | "key": "foo1", 58 | "value": "bar1" 59 | } 60 | ] 61 | } 62 | }, 63 | "response": [] 64 | } 65 | ] 66 | } -------------------------------------------------------------------------------- /test/fixtures/run/single-file-outside.json: -------------------------------------------------------------------------------- 1 | { 2 | "info": { 3 | "name": "Example Collection with a single GET request", 4 | "schema": "https://schema.getpostman.com/json/collection/v2.0.0/collection.json" 5 | }, 6 | 7 | "item": [{ 8 | "name": "A Form-data request", 9 | "event": [{ 10 | "listen": "test", 11 | "script": { 12 | "type": "text/javascript", 13 | "exec": [ 14 | "pm.test(\"file uploaded\", function () {", 15 | " var jsonData = pm.response.json();", 16 | " pm.expect(jsonData.files).to.eql({ ", 17 | " \"outside.json\": \"data:application/octet-stream;base64,eyJzb21lIjogImpzb24tc3RyaW5nIn0K\"", 18 | "});});" 19 | ] 20 | } 21 | }], 22 | "request": { 23 | "url": "https://postman-echo.com/post", 24 | "method": "POST", 25 | "body": { 26 | "mode": "formdata", 27 | "formdata": [ 28 | { 29 | "type": "file", 30 | "key": "somefile", 31 | "src": "../outside.json" 32 | } 33 | ] 34 | } 35 | } 36 | }, 37 | { 38 | "name": "A Binary body request", 39 | "event": [{ 40 | "listen": "test", 41 | "script": { 42 | "type": "text/javascript", 43 | "exec": [ 44 | "pm.test(\"file uploaded\", function () {", 45 | " var jsonData = pm.response.json();", 46 | " pm.expect(jsonData.data).to.eql({ some: 'json-string' });", 47 | "});" 48 | ] 49 | } 50 | }], 51 | "request": { 52 | "url": "https://postman-echo.com/post", 53 | "method": "POST", 54 | "body": { 55 | "mode": "file", 56 | "file": { 57 | "src": "../outside.json" 58 | } 59 | } 60 | } 61 | }] 62 | } 63 | -------------------------------------------------------------------------------- /npm/test-cli.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | // --------------------------------------------------------------------------------------------------------------------- 3 | // This script is intended to execute all cli tests. 4 | // --------------------------------------------------------------------------------------------------------------------- 5 | 6 | const path = require('path'), 7 | 8 | Mocha = require('mocha'), 9 | exec = require('shelljs').exec, 10 | colors = require('colors/safe'), 11 | recursive = require('recursive-readdir'), 12 | 13 | SPEC_SOURCE_DIR = path.join('test', 'cli'); 14 | 15 | module.exports = function (exit) { 16 | // banner line 17 | console.info(colors.yellow.bold('Running CLI integration tests using mocha and shelljs...')); 18 | 19 | // add all spec files to mocha 20 | recursive(SPEC_SOURCE_DIR, (err, files) => { 21 | if (err) { 22 | console.error(err); 23 | 24 | return exit(1); 25 | } 26 | 27 | const mocha = new Mocha({ timeout: 1000 * 60 }); 28 | 29 | files.filter((file) => { // extract all test files 30 | return (file.substr(-8) === '.test.js'); 31 | }).forEach(mocha.addFile.bind(mocha)); 32 | 33 | // override exec for it to become silent by default 34 | global.exec = function (cmd, done) { 35 | return exec(cmd, { silent: true }, done); 36 | }; 37 | 38 | // start the mocha run 39 | mocha.run((runError) => { 40 | delete global.exec; 41 | runError && console.error(runError.stack || runError); 42 | 43 | exit(runError || process.exitCode ? 1 : 0); 44 | }); 45 | }); 46 | }; 47 | 48 | // ensure we run this script exports if this is a direct stdin.tty run 49 | !module.parent && module.exports(process.exit); 50 | -------------------------------------------------------------------------------- /test/fixtures/ssl/client2.key: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | Proc-Type: 4,ENCRYPTED 3 | DEK-Info: AES-256-CBC,0489A6417791B6C643DD22025AE8F938 4 | 5 | uE8ef9A/izPkEWrntX1ZdT5ouYcRlFaaHNU62tJw/K60kibtcDPp4oCKgkmU2KmG 6 | x6EQMqKnUlArZ+xT54GoC/vJTXd5VQsIs7b9xhCm9NB/tIyXOTNOLF87RH9bY5qi 7 | nc+nntHk1eoYQ+xBbg8tnZvjwlEs0wcgaMc783uLFwPE5YgMJGQaiE2WNnehGqPv 8 | s5Y9QAljhF+3KRX1a9bLYbLYdu+haq5TVwz3NW3GpUawzDP7ArvO2aT/w8Kzw/3n 9 | qqtHvQeaJKfUXqhbOlJeHM9AmzGHXWZWQlUxcUXWbrBtMH1KDWa9STDUuSLS1y7k 10 | +gdOrUYw7BFJKy2sckzPHJ8RPLObtmFUijh64cBD51uEgBzRkex6pUU4W2DMoNA3 11 | gZl0Bz4REx15aqsb9oGHqyc1xC0Xg7uqypJfsFIWrIO2hk5ZjwGfuqIQvy/309pt 12 | p1Zko5GobUKQPmY63x3zE45uAeTMV5oEcmUZkMMLWn3frkRCP8rbNBDqy/x97ZkB 13 | sD8SQbZSvWIuccF7/kWBPRwKQjN7vmZDAKvsmujQrdko1ODFmOOwEwwo9nvLdOU4 14 | FrHougwEtAsfCnoZRPVMzMCsh/FB8RMq0cIVk61CeQKczcl1rNpKCw4CR4Lek6rs 15 | st5P20to6YgbBL+Fzt1sFN0vYRm4nAlDK4OZCvz2CLtDt2rptNtWTskDbkqOx7Y4 16 | olruEYFTGnmhmbWFr3ldXZJDSqqlSInvhgfIGEGqF71sPe8s41+58lkQ0A6sWsrV 17 | JSWiA2b7TZYztUc8oUfjM+ZftL1gQHnJN+EOkBz1QgRdSiUARxFPjymxES6iG699 18 | T35MMWWF9MEtLuymnIbyTTN8X1FOQ2RgtCEasxMBEJ3lXTTcU9xuaFSSssjiePpu 19 | w61VeQNas9sOD+mAXbAXx9scU1DYmXC77/ZV5ABi4Ls8ziCFwa4lLG6yfvH1bc6y 20 | FpLLBPt03Dm0ZrkqAlmI1nPDq8UH/my4pPf8dstBhCRJ/6ubQwb2rkI/zvwdFJq3 21 | rSXfVUDkvYj7esN3D67u12qVBxee/aLBah3RFr0AMtbYb2WKYy72/PSYMIdKATWN 22 | qxEt6WdHuoo7TxQow9yb2u7VBiqWsuirI5hVyk9S9k85qOkEempRU0BOseL/0ITk 23 | XywJxrhfg++rtStZQFMYi66MmVzVaYsV916obGOZjgwV8fYtfr3TxJGpEDNMlHtU 24 | ZTZ0J+juQC/GxN0Hhp5XQeRbMRRWKxhqWfkdJThORid62qKTaz1+r4WZ97QW4OxX 25 | MHecrxb9T8bPbxTZbjX/1VBiBr0vc/A28rxzDsRqDDf89+v44GNnBdtmRXfA1Mlk 26 | oZrBjGchOh/J8Q6+trADZEkyqt381doqXcvYasnPH3vt0qRG/s4VKE2nuEmzm1n8 27 | ibqTrb+LgboBFrDFdAWKeCQy1mQSn6EWzp7JQ4eXkerD3kLqo2hT7mBkSy2Gj+ok 28 | Awb3tC4cGzOZ6KmZhoBkiybBvs0sdKR2NzvzNnn15bqV8ZLky5nMLvh9F49CuLBQ 29 | ZNHiVjgG5WTWcVveBIbkcOPp3c9vZd6+R5GQh7QutERbf7VqMKDGxOuZVIBFhQff 30 | -----END RSA PRIVATE KEY----- 31 | -------------------------------------------------------------------------------- /test/fixtures/ssl/server2.key: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | Proc-Type: 4,ENCRYPTED 3 | DEK-Info: AES-256-CBC,7BEC18626B692265F7C18376151A14C3 4 | 5 | sAsNp1MhV4yppCM2SPtpTp1FTkf2vMWSMMEwqVUfZDpGjYcyIQdBpUR6oVVb2oI4 6 | t41UhrENMbWaqZ8g6U0T4QwaHK3JO60Yexiru4lYMbrXpAQpZTlmKsQ9LfzauRhq 7 | hdXd6yztotrtvNjPMjOHF9osw3lyI2PnSL3viDp5zxn+rS6QCDYgsmNNw/Qi4UUU 8 | yEUnPwxJRPeRXoSwG3TW/W5rE2/RPjlC6bGOtOD24CIiut8rXWRhNB1Pqd0KiNX8 9 | G3rlzHPKl4kTAbxwo4JpeLDWCTlBHakJl10S8w9LH3ubd6eJ9JHCkhm0zkJ4O5r7 10 | Vbav1nNeXcyIXVC3HcGP5muF8n3aWNdL/OaZmcVEtt/qFSIktj2dXODOL4XkMMLT 11 | oHtOU6+/TB4Ra8iQtHqE8hvLmVlfbjwjTd8I1t782DHlli15FoTXjmgPEhwQYR6V 12 | /7rnYS0oYQMpLwgMuXOtxpkB9FkC+KwIJtZvGCHGPvSPDXc7i7ZRStNvAwi57ORY 13 | TprSw/AbCCwmNr9MpxpLK1hDtZfAAVWCtkaLTxJOdt+gbtO+OpDSFiI6nSiGazYa 14 | +Zq235ZUIn6C1UoO6NHVYx4Zstv7GC1eaVmGwHmJw30oDxrZMhW3xK8zNDuWzw3K 15 | PJzlVhLHoKmudW0xa6IiQCSOkt+iq9dwuqHv2kZUgCADo5miBVJFrv3jpYoilt7a 16 | SXb6qn7lFmQnCbHx/6rQaXlDGlz2TGwZwmtgR40qyxCMs9BS2bo3xvnc65QnoW8J 17 | ALAd88i67KtrN3byAjWVY/0Uu+kXFVn7xBXty1tX9I/WyM2jnviNMp+8GiKkdtwJ 18 | qPojzcyPnim2kggQWvwS2Jpfo/gYQiWdhD9ZbfFXT40vWgZjFucr645yMTXYr0n0 19 | 6yeCy9VAdskfGIWjkmgleXrQN/69oYtCJJCXw9xh22Lu5wT7stCsBOJhCVYtNJH9 20 | 6j2gCt8jlAl6ZCxoHzfPIp+B3Shtasvrjr5JhWLDeM+1x2wzo+O396wGlas90h3P 21 | Rcx/JhyixNLQ6WBbEQedGORqUlTBTRk0LDQaJ6v2YSm33DJ5VW1gUEJUiuJhA5Fg 22 | 5TGThXxEZfJ3iVQx1dcBjpoN7stYWPfse/MjorZ1r3ubpOSzxEtJJJ3YWgv5K/ji 23 | o/w3R/k17swKy9mCSdb5F6KGW7WOGfqKvEXXu84t4LBQvM3cdCkSbmdrxoP2TTTn 24 | CAb58lPtRAHC8IdL2qOKuxJhzKljeVxWDpk2DZLBvD+socYTVAs48YpL/pichDi3 25 | T+jqISoVbKTYQ6eQ0v7EpdBSA/iPJ2yVPYwPOmV/R/zzagctB6uzEZ8Sq7+HWlWr 26 | vAgpIYf+h92uQbOu0Uvj/xYqKpFKHAGna0YOId3hNiU7HcawK20AlrdHWiIC2UQc 27 | y5VPJy5NNRtIzzGD1cetu2/QoOSVFkADX1ctoCoiA9XdedBVQCZ+grrwCQsn1XF/ 28 | V18koBkMcKxf9oV6A7rc5guBHp2OQ3bdgu/C9GFAkaoBjhf29pz7gy57pD+PPL/A 29 | dyKDP2B1xrDVuwa2Klqy16twtnokk27ouWYcoG7T1VB9W/BoSWevOZaRumS+LxDc 30 | -----END RSA PRIVATE KEY----- 31 | -------------------------------------------------------------------------------- /test/integration/distinct-random-int.postman_collection.json: -------------------------------------------------------------------------------- 1 | { 2 | "variables": [], 3 | "info": { 4 | "name": "Test that {{$randomInt}} gives different values across requests", 5 | "_postman_id": "ad279aba-66c1-a145-5acb-e0e2fcf23465", 6 | "description": "A set of tests to verify the value of seeded environment variables using random data from a remote source", 7 | "schema": "https://schema.getpostman.com/json/collection/v2.0.0/collection.json" 8 | }, 9 | "item": [ 10 | { 11 | "name": "r1", 12 | "event": [ 13 | { 14 | "listen": "test", 15 | "script": { 16 | "type": "text/javascript", 17 | "exec": "var data = JSON.parse(responseBody);\npostman.setEnvironmentVariable(\"randomVar\", parseInt(data.args.a));" 18 | } 19 | } 20 | ], 21 | "request": { 22 | "url": "https://postman-echo.com/get?a={{$randomInt}}", 23 | "method": "GET", 24 | "header": [], 25 | "body": { 26 | "mode": "formdata", 27 | "formdata": [] 28 | }, 29 | "description": "" 30 | }, 31 | "response": [] 32 | }, 33 | { 34 | "name": "r2", 35 | "event": [ 36 | { 37 | "listen": "test", 38 | "script": { 39 | "type": "text/javascript", 40 | "exec": "var data = JSON.parse(responseBody);\nvar newVar = parseInt(data.args.a)\ntests[\"different randoms\"] = newVar!==environment.randomVar;" 41 | } 42 | } 43 | ], 44 | "request": { 45 | "url": "https://postman-echo.com/get?a={{$randomInt}}&b={{$guid}}", 46 | "method": "GET", 47 | "header": [], 48 | "body": { 49 | "mode": "formdata", 50 | "formdata": [] 51 | }, 52 | "description": "" 53 | }, 54 | "response": [] 55 | } 56 | ] 57 | } 58 | -------------------------------------------------------------------------------- /test/fixtures/ssl/server.csr: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE REQUEST----- 2 | MIIE8DCCAtgCAQAwgaoxCzAJBgNVBAYTAklOMRIwEAYDVQQIDAlLYXJuYXRha2Ex 3 | EjAQBgNVBAcMCUJlbmdhbHVydTElMCMGA1UECgwcUG9zdGRvdCBUZWNobm9sb2dp 4 | ZXMgUHZ0IEx0ZDEUMBIGA1UECwwLUG9zdG1hbmxhYnMxEjAQBgNVBAMMCWxvY2Fs 5 | aG9zdDEiMCAGCSqGSIb3DQEJARYTaGVscEBnZXRwb3N0bWFuLmNvbTCCAiIwDQYJ 6 | KoZIhvcNAQEBBQADggIPADCCAgoCggIBAP4xO2r4oUF5hdQN6tt+1c43UnWvLCJ2 7 | dO3IvOtr5irPdM94dm7mEXyZdEVDoIp9fG28Q+J/hKCjiIdFFD0THIUO6sRnMf7p 8 | B6S4rUD8fKNHwgh9k2/ht2ijD/XVsf6eVEePu3KV/gUzlq+DYDe1cpUmvNzIC1as 9 | li+I3HJ2gfpGeZh1JsahAVoqBifa9+7DLmQIBSTbqyZbrnTuN0sgLmyCWhBpgs45 10 | f6drs4YZ0IuSBdmOMP/Bqlm2QBC0Ymx4OK+qrGi7RW0rF13y6gdLs1RADu5TIWVT 11 | RMI6KiULDYqGpznFnxrkj//jdy1iW5hkQ8tDRz9SO6gS+CYibvWWX0upnFA1HQqf 12 | GXARTc+19lUU5mYVY/CMSSsw7Vu1zQKfOG1IYx89MJEvf22es1e99bJS0kL2M8du 13 | pFckHG611qYp/DPh84hQH2XYqPl7aDbDM2kErawYg8YDMUn73VQtw3kXc+LjA15Q 14 | a3nIbQl5jO19H3q/dPkMqxG2K6/S/vRoeXZ9l4iED7n3iv9gH/AVkIXc6iM9c8Qy 15 | fFr5yyQ1C9kMDQQL3JM3QQ52/7ni5evfGCePkwKM8zkrbQPgg3/3UoFKvPg3m3yc 16 | oe3x7t2Pm3ybGM5PtHOV5/TJ1lEwiwH5fzaTJm2QXA/tqI+0/S7AE/zTdcugUwSM 17 | c/4G5EFJTrxbAgMBAAGgADANBgkqhkiG9w0BAQsFAAOCAgEAKRePTLfuwfQ6eYM2 18 | GpyuXt7hqjQUbtSd+ouIK6sdYxgXMt4Q5G8Z7cSw5jah6tIhjMX8OoQUp5+5wcw4 19 | O4nZX/eC8T6E2LyFIgV2/erBDyMRsLq5YcrI5xNVMULDrEMsXRC3sVL41dmIJC98 20 | L/q2fSbDj4hfRVEaz3dZBiUFr8YMTyy+5jK3agoXVDAc1FVEYosrqGB9FjvXNl6h 21 | q0OGZcWqkkcUFMzcWNYC90AHCU+QedoZ+klSQsg4wdwStRnNFQu7FUnZ9gcngroe 22 | Mos7u5f5fAiW21p310Y/QyNpa6vD+D0R0f1TB8zBZjEHIZs1fooQm9k1YOFD89Z7 23 | 8C+hgzDFm+ZO9SKx3tbvyHhxTEYysuEhSK62gPaECEBrwJu0HfydscXP1IrK5hB5 24 | IelEY8LmJ53+ck7J14+2LepG3QZczgo6MLjSij4vXomomdkGKzkhdeHb9+dc8ATd 25 | 5xgGvKQJJDDLT9TzzebzH9d+mzdyyFVXS0/F9QgGP5AGSH2ziXwSZcXi8v5Qhxcd 26 | 8aRMnFFRYbQiMk8KjwoWgMOAfYJnDCcXphU7Gc/x2V03HVFomatCHAZHSFxn07Jc 27 | 7hqrC8tWelKV/1jP0y6anbAdfHP4vBZr+RWI9iQcUxkqChyXUAfHKZWsfVvVKTcJ 28 | /WX9pntSlRddrct7walGvZb0FO0= 29 | -----END CERTIFICATE REQUEST----- 30 | -------------------------------------------------------------------------------- /examples/v1.postman_collection.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "c5f65caa-9e32-6546-ac10-9167d0996723", 3 | "name": "Sample Postman Collection", 4 | "description": "A sample collection to demonstrate collections as a set of related requests", 5 | "order": [ 6 | "3845db20-6952-e442-f3b0-6211e2089b71", 7 | "ec098f7c-4e22-2fe9-e5c5-26f13016be84", 8 | "464bc62d-db90-7c58-1c28-ff0b5eac2f4f" 9 | ], 10 | "folders": [], 11 | "owner": "640245", 12 | "hasRequests": true, 13 | "requests": [ 14 | { 15 | "id": "3845db20-6952-e442-f3b0-6211e2089b71", 16 | "name": "A simple GET request", 17 | "description": "", 18 | "collectionId": "c5f65caa-9e32-6546-ac10-9167d0996723", 19 | "method": "GET", 20 | "headers": "", 21 | "data": [], 22 | "rawModeData": "", 23 | "tests": "tests['response code is 200'] = (responseCode.code === 200);", 24 | "preRequestScript": "", 25 | "url": "https://postman-echo.com/get?source=newman-sample-github-collection" 26 | }, 27 | { 28 | "id": "464bc62d-db90-7c58-1c28-ff0b5eac2f4f", 29 | "name": "A simple POST request with JSON body", 30 | "description": "", 31 | "collectionId": "c5f65caa-9e32-6546-ac10-9167d0996723", 32 | "method": "POST", 33 | "headers": "Content-Type: application/json", 34 | "dataMode": "raw", 35 | "data": [], 36 | "rawModeData": "{\"text\":\"Duis posuere augue vel cursus pharetra. In luctus a ex nec pretium...\"}", 37 | "url": "https://postman-echo.com/post" 38 | }, 39 | { 40 | "id": "ec098f7c-4e22-2fe9-e5c5-26f13016be84", 41 | "name": "A simple POST request", 42 | "description": "", 43 | "collectionId": "c5f65caa-9e32-6546-ac10-9167d0996723", 44 | "method": "POST", 45 | "headers": "Content-Type: text/plain", 46 | "dataMode": "raw", 47 | "data": [], 48 | "rawModeData": "Duis posuere augue vel cursus pharetra. In luctus a ex nec pretium...", 49 | "url": "https://postman-echo.com/post" 50 | } 51 | ] 52 | } -------------------------------------------------------------------------------- /npm/test-system.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | // --------------------------------------------------------------------------------------------------------------------- 3 | // This script is intended to execute all system tests. 4 | // --------------------------------------------------------------------------------------------------------------------- 5 | 6 | const path = require('path'), 7 | 8 | Mocha = require('mocha'), 9 | colors = require('colors/safe'), 10 | recursive = require('recursive-readdir'), 11 | { exec } = require('shelljs'), 12 | 13 | SPEC_SOURCE_DIR = path.join(__dirname, '..', 'test', 'system'); 14 | 15 | module.exports = function (exit) { 16 | // banner line 17 | console.info(colors.yellow.bold('\nRunning system tests using mocha...')); 18 | 19 | // add all spec files to mocha 20 | recursive(SPEC_SOURCE_DIR, (err, files) => { 21 | if (err) { 22 | console.error(err); 23 | 24 | return exit(1); 25 | } 26 | 27 | const mocha = new Mocha({ timeout: 1000 * 60 }); 28 | 29 | files.filter((file) => { // extract all test files 30 | return (file.substr(-8) === '.test.js'); 31 | }).forEach(mocha.addFile.bind(mocha)); 32 | 33 | // start the mocha run 34 | mocha.run((runError) => { 35 | if (runError) { 36 | console.error(runError.stack || runError); 37 | 38 | return exit(1); 39 | } 40 | 41 | // ensure all dependencies are okay 42 | console.info(colors.yellow('checking package dependencies...\n')); 43 | exec('dependency-check ./package.json --extra --no-dev --missing', (code) => { 44 | exit(code ? 1 : 0); 45 | }); 46 | }); 47 | }); 48 | }; 49 | 50 | // ensure we run this script exports if this is a direct stdin.tty run 51 | !module.parent && module.exports(process.exit); 52 | -------------------------------------------------------------------------------- /test/fixtures/ssl/generate-certificates.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # generate/refresh certificates for server, ca and client 4 | 5 | SERVER='server3' 6 | CA='ca3' 7 | CLIENT='client3' 8 | 9 | # generate a private key for the server 10 | if [[ ! -f "$SERVER.key" ]]; then 11 | openssl genrsa -out $SERVER.key 2048 12 | fi 13 | 14 | # generate a CSR with the private key for the server 15 | openssl req -new -key $SERVER.key \ 16 | -config config.cnf \ 17 | -days 9999 \ 18 | -out $SERVER.csr 19 | 20 | # generate a private key for the Certificate Authority 21 | if [[ ! -f "$CA.key" ]]; then 22 | openssl genrsa -out $CA.key 2048 23 | fi 24 | 25 | # generate a certificate for the the CA 26 | openssl req -new -x509 -key $CA.key \ 27 | -config config.cnf \ 28 | -days 9999 \ 29 | -out $CA.crt 30 | 31 | # generate the server certificate signed by the CA 32 | openssl x509 -req -in $SERVER.csr \ 33 | -CA $CA.crt \ 34 | -CAkey $CA.key \ 35 | -out $SERVER.crt \ 36 | -set_serial 1 \ 37 | -outform pem \ 38 | -extfile v3.ext \ 39 | -days 9999 \ 40 | -sha256 41 | 42 | # verify that the certificate was generated correctly 43 | openssl verify -CAfile $CA.crt $SERVER.crt 44 | 45 | # generate a private key for the client 46 | if [[ ! -f "$CLIENT.key" ]]; then 47 | openssl genrsa -out $CLIENT.key 2048 48 | fi 49 | 50 | # generate a CSR with the private key for the client 51 | openssl req -new -key $CLIENT.key \ 52 | -config config.cnf \ 53 | -days 9999 \ 54 | -out $CLIENT.csr 55 | 56 | # generate the client certificate sign by the CA 57 | openssl x509 -req -in $CLIENT.csr \ 58 | -CA $CA.crt \ 59 | -CAkey $CA.key \ 60 | -out $CLIENT.crt \ 61 | -set_serial 1 \ 62 | -outform pem \ 63 | -extfile v3.ext \ 64 | -days 9999 \ 65 | -sha256 66 | 67 | # verify that the certificate was generated correctly 68 | openssl verify -CAfile $CA.crt $CLIENT.crt 69 | -------------------------------------------------------------------------------- /examples/sample-collection.json: -------------------------------------------------------------------------------- 1 | { 2 | "info": { 3 | "name": "Sample Postman Collection", 4 | "schema": "https://schema.getpostman.com/json/collection/v2.0.0/collection.json", 5 | "description": "A sample collection to demonstrate collections as a set of related requests" 6 | }, 7 | 8 | "item": [{ 9 | "name": "A simple GET request", 10 | "event": [{ 11 | "listen": "test", 12 | "script": { 13 | "type": "text/javascript", 14 | "exec": [ 15 | "pm.test('expect response be 200', function () {", 16 | " pm.response.to.be.ok", 17 | "})", 18 | "pm.test('expect response json contain args', function () {", 19 | " pm.expect(pm.response.json().args).to.have.property('source')", 20 | " .and.equal('newman-sample-github-collection')", 21 | "})" 22 | ] 23 | } 24 | }], 25 | "request": { 26 | "url": "https://postman-echo.com/get?source=newman-sample-github-collection", 27 | "method": "GET" 28 | } 29 | }, { 30 | "name": "A simple POST request", 31 | "request": { 32 | "url": "https://postman-echo.com/post", 33 | "method": "POST", 34 | "header": [{ 35 | "key": "Content-Type", 36 | "value": "text/plain" 37 | }], 38 | "body": { 39 | "mode": "raw", 40 | "raw": "Duis posuere augue vel cursus pharetra. In luctus a ex nec pretium..." 41 | } 42 | } 43 | }, { 44 | "name": "A simple POST request with JSON body", 45 | "request": { 46 | "url": "https://postman-echo.com/post", 47 | "method": "POST", 48 | "header": [{ 49 | "key": "Content-Type", 50 | "value": "application/json" 51 | }], 52 | "body": { 53 | "mode": "raw", 54 | "raw": "{\"text\":\"Duis posuere augue vel cursus pharetra. In luctus a ex nec pretium...\"}" 55 | } 56 | } 57 | }] 58 | } 59 | -------------------------------------------------------------------------------- /test/fixtures/ssl/client.csr: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE REQUEST----- 2 | MIIFHjCCAwYCAQAwgacxCzAJBgNVBAYTAklOMRIwEAYDVQQIDAlLYXJuYXRha2Ex 3 | EjAQBgNVBAcMCUJlbmdhbHVydTElMCMGA1UECgwcUG9zdGRvdCBUZWNobm9sb2dp 4 | ZXMgUHZ0IEx0ZDEPMA0GA1UECwwGTmV3bWFuMRQwEgYDVQQDDAtQb3N0bWFubGFi 5 | czEiMCAGCSqGSIb3DQEJARYTaGVscEBnZXRwb3N0bWFuLmNvbTCCAiIwDQYJKoZI 6 | hvcNAQEBBQADggIPADCCAgoCggIBAMUasUBkpb8K84aC9jPNeQ/s7+MNNl1qScJT 7 | +kX2s/bUyydOwM9mj+xHx+H8XmQ/WoWm3b2ksKKsjxsN4TlIxoc1kiA+z+3Y3NJZ 8 | cKMJI6HMQtUl4doH1xvNLtyXwshHGtAEN7dMzFC0ELmOqkZwyc/xAJ1mFQGAOkhj 9 | LvDrEHtWQVOQmzRRTZO1O9DK1qHxcEQ49JHjpGewHdCx55lqLmDVmP2oEXDrzy/V 10 | nxaox9BTL4WrgbTwuJQHGouoPSeSJ9hs+iCKK9KHpG7KNkVSOx5wUJEthvhJyPj0 11 | nO+Sb1QaXVRHMDdv/mm483X8oPLZHX4jjQtVakDnLTILSO38k46obYZhztdPd23r 12 | vbJnWAyV8dSepGyN3Ipd3gxwWdrsA+Y+W6XBklmVIbSgLQl7z5KalgWILIqXARyy 13 | +bFWrOTL3lxpD1hZwiEcSklosKodoIazDAWP6z4zy/paXVEKsKDDwTuaWGE0555d 14 | jE+rLvzqy9QQOW8hlV2FDU/11CZlzdqSwwKWcjSWfx0dV6VOvaB75za6Rt8HsscZ 15 | ta/wXlXuLMYpR2LV6GpraDfo3vA0cTsjsPYqR/EKonogt4Ai81MVk7gak9FUWCpE 16 | LBOX1oiyQjbigd3W1Sl9kk+4ztG9tgJs8rYMuHjiLW+78Q68WHydMKQxxB8gmJcx 17 | xDLdo1xhAgMBAAGgMTAWBgkqhkiG9w0BCQIxCQwHUG9zdG1hbjAXBgkqhkiG9w0B 18 | CQcxCgwIcGFzc3dvcmQwDQYJKoZIhvcNAQELBQADggIBAFrUInIkTw3Er7FdVcj8 19 | cAF2khW31gFLD+ohiGt4b3Thmfx9dnUl+PJv/c4AAHriyr+TdRxQeaiBWRG9qgpL 20 | GYSeKG4Yoy9BSNxS33DxEo0RUjBKSkds9xcxK2unZftWeDav5MHZ04Em1NqWDwzw 21 | FENN3jKJequ+d4+OLwjqjXE9cEpmYcZob8dfxiwrD9TnQCQIJWqAKVqNsUPojQjV 22 | CYRn2KsHZrsHIEclz1OHto/n16XyRMcieryP47CziweSuW+hDGcRso+T2F+BBYe1 23 | Ma/wzwc5VHc82lSduLbcZI92t/q60O47zb9YSJORNSf7FyeAsMs8AjY3LrAIUDli 24 | vLm3nKS0DgTATceb5vY/s1SMkLeSejrNI+PamFrNXu/4o/G+XTG3TvB841z+rSHE 25 | NU6fLeoK/amzLPmP0hKuFWyin25FHY5sXowVud5M+GY+WfeUMQuZQkOBThelLH04 26 | Ww2cuJEJn8m08bl26luJAhkGs739GDy2+94+hXVVicmNgz99MBvszJZ29GvsmZxi 27 | jnlXoCG5q1/BzDpDL2D5Hbvga5M+hdonQQ3pZglneuSyiFZSVhsvWAGXfNB0wqDL 28 | SUb3wq3YJE/cYt2bKI2u2KRtKjFMRRlWaLEkMmAYZHcij3i8pnvmAokwy1T7GkNG 29 | sDlu0WZX8PeksXnzFtyObpR1 30 | -----END CERTIFICATE REQUEST----- 31 | -------------------------------------------------------------------------------- /test/integration/bom-and-encoding/bom-in-collection-file.postman_collection.json: -------------------------------------------------------------------------------- 1 | { 2 | "info": { 3 | "name": "Sample Postman Collection", 4 | "schema": "https://schema.getpostman.com/json/collection/v2.0.0/collection.json", 5 | "description": "A sample collection to demonstrate collections as a set of related requests" 6 | }, 7 | 8 | "item": [{ 9 | "name": "A simple GET request", 10 | "event": [{ 11 | "listen": "test", 12 | "script": { 13 | "type": "text/javascript", 14 | "exec": [ 15 | "pm.test('expect response be 200', function () {", 16 | " pm.response.to.be.ok", 17 | "})", 18 | "pm.test('expect response json contain args', function () {", 19 | " pm.expect(pm.response.json().args).to.have.property('source')", 20 | " .and.equal('newman-sample-github-collection')", 21 | "})" 22 | ] 23 | } 24 | }], 25 | "request": { 26 | "url": "https://postman-echo.com/get?source=newman-sample-github-collection", 27 | "method": "GET" 28 | } 29 | }, { 30 | "name": "A simple POST request", 31 | "request": { 32 | "url": "https://postman-echo.com/post", 33 | "method": "POST", 34 | "header": [{ 35 | "key": "Content-Type", 36 | "value": "text/plain" 37 | }], 38 | "body": { 39 | "mode": "raw", 40 | "raw": "Duis posuere augue vel cursus pharetra. In luctus a ex nec pretium..." 41 | } 42 | } 43 | }, { 44 | "name": "A simple POST request with JSON body", 45 | "request": { 46 | "url": "https://postman-echo.com/post", 47 | "method": "POST", 48 | "header": [{ 49 | "key": "Content-Type", 50 | "value": "application/json" 51 | }], 52 | "body": { 53 | "mode": "raw", 54 | "raw": "{\"text\":\"Duis posuere augue vel cursus pharetra. In luctus a ex nec pretium...\"}" 55 | } 56 | } 57 | }] 58 | } 59 | -------------------------------------------------------------------------------- /test/fixtures/run/response-bodies.json: -------------------------------------------------------------------------------- 1 | { 2 | "info": { 3 | "name": "A collection with ", 4 | "schema": "https://schema.getpostman.com/json/collection/v2.0.0/collection.json" 5 | }, 6 | "item": [{ 7 | "name": "A simple GET request", 8 | "event": [{ 9 | "listen": "test", 10 | "script": { 11 | "type": "text/javascript", 12 | "exec": [ 13 | "pm.test('response code is 200', function () {", 14 | " pm.response.to.be.ok;", 15 | " pm.response.to.have.header('Content-Type', 'application/json; charset=utf-8');", 16 | "});" 17 | ] 18 | } 19 | }], 20 | "request": { 21 | "url": "https://postman-echo.com/get?source=newman-sample-github-collection", 22 | "method": "GET" 23 | } 24 | }, { 25 | "name": "A simple GET request", 26 | "event": [{ 27 | "listen": "test", 28 | "script": { 29 | "type": "text/javascript", 30 | "exec": [ 31 | "pm.test('response code is 200', function () {", 32 | " pm.response.to.be.ok;", 33 | " pm.response.to.have.header('Content-Type', 'application/html; charset=utf-8');", 34 | "});" 35 | ] 36 | } 37 | }], 38 | "request": { 39 | "url": "https://postman-echo.com/type/html?source=newman-sample-github-collection", 40 | "method": "GET" 41 | } 42 | }, { 43 | "name": "A simple GET request", 44 | "event": [{ 45 | "listen": "test", 46 | "script": { 47 | "type": "text/javascript", 48 | "exec": [ 49 | "pm.test('response code is 200', function () {", 50 | " pm.response.to.be.ok;", 51 | " pm.response.to.have.header('Content-Type', 'application/xml; charset=utf-8');", 52 | "});" 53 | ] 54 | } 55 | }], 56 | "request": { 57 | "url": "https://postman-echo.com/type/xml?source=newman-sample-github-collection", 58 | "method": "GET" 59 | } 60 | }] 61 | } 62 | -------------------------------------------------------------------------------- /test/integration/hawk-auth-test.postman_collection.json: -------------------------------------------------------------------------------- 1 | { 2 | "variables": [], 3 | "info": { 4 | "name": "hawkAuthTest", 5 | "_postman_id": "d497d10e-e280-8c83-709a-a4d4ea12ad14", 6 | "description": "A set of tests for the HAWK authentication scheme", 7 | "schema": "https://schema.getpostman.com/json/collection/v2.0.0/collection.json" 8 | }, 9 | "item": [ 10 | { 11 | "name": "test hawk auth success", 12 | "event": [ 13 | { 14 | "listen": "test", 15 | "script": { 16 | "type": "text/javascript", 17 | "exec": [ 18 | "pm.test('should authenticate correctly', function () {", 19 | " pm.response.to.have.jsonBody('message', 'Hawk Authentication Successful');", 20 | "});" 21 | ] 22 | } 23 | } 24 | ], 25 | "request": { 26 | "auth": { 27 | "type": "hawk", 28 | "hawk": { 29 | "authId": "dh37fgj492je", 30 | "authKey": "werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn", 31 | "algorithm": "sha256", 32 | "user": "asda", 33 | "saveHelperData": true, 34 | "nonce": "eFRP2o", 35 | "extraData": "skjdfklsjhdflkjhsdf", 36 | "appId": "", 37 | "delegation": "", 38 | "timestamp": "" 39 | } 40 | }, 41 | "url": "https://postman-echo.com/auth/hawk", 42 | "method": "GET", 43 | "header": [ 44 | { 45 | "key": "Authorization", 46 | "value": "Hawk id=\"dh37fgj492je\", ts=\"1448888081\", nonce=\"HoH6Ay\", ext=\"skjdfklsjhdflkjhsdf\", mac=\"moWleO5f/8QbvIiy7oo2zj1bmezhrYwrCkz4BsXg0M4=\"", 47 | "description": "" 48 | } 49 | ], 50 | "body": { 51 | "mode": "formdata", 52 | "formdata": [] 53 | }, 54 | "description": "" 55 | }, 56 | "response": [] 57 | } 58 | ] 59 | } 60 | -------------------------------------------------------------------------------- /test/unit/cli-reporter-symbols.test.js: -------------------------------------------------------------------------------- 1 | const _ = require('lodash'), 2 | expect = require('chai').expect, 3 | 4 | isDoubleByte = function (str) { 5 | for (var i = 0, n = str.length; i < n; i++) { 6 | if (str.charCodeAt(i) > 255) { return true; } 7 | } 8 | 9 | return false; 10 | }; 11 | 12 | /* eslint-disable */ 13 | /** 14 | * @attribution https://github.com/lodash/lodash/issues/2240#issuecomment-418820848 15 | */ 16 | const flattenKeys = (obj, path = []) => 17 | !_.isObject(obj) 18 | ? { [path.join('.')]: obj } 19 | : _.reduce(obj, (cum, next, key) => _.merge(cum, flattenKeys(next, [...path, key])), {}); 20 | /* eslint-enable */ 21 | 22 | describe('unicode handling of cli symbol utility module', function () { 23 | let cliUtilsSymbols = require('../../lib/reporters/cli/cli-utils-symbols.js'); 24 | 25 | it('should have three symbol classes', function () { 26 | expect(cliUtilsSymbols(true)).to.be.an('object'); 27 | expect(cliUtilsSymbols(false)).to.be.an('object'); 28 | }); 29 | 30 | it('should have appropriate fallback for unicode', function () { 31 | let symbol = cliUtilsSymbols(true), 32 | fallback = cliUtilsSymbols(false), 33 | 34 | flattenedSymbols = flattenKeys(symbol), 35 | flattenedPlainSymbols = flattenKeys(fallback); 36 | 37 | expect(flattenedSymbols).to.contain.keys(flattenedPlainSymbols); 38 | }); 39 | 40 | it('should not have unicode when not requested', function () { 41 | let fallbackSymbols = cliUtilsSymbols(true), 42 | flattenedPlainSymbols = flattenKeys(fallbackSymbols); 43 | 44 | // first compute all double byte checking 45 | for (const [key, value] of Object.entries(flattenedPlainSymbols)) { 46 | // @todo make the assertion better so that failure here says what exactly went wrong 47 | expect(isDoubleByte(value)).to.eql(false, key); 48 | } 49 | }); 50 | }); 51 | -------------------------------------------------------------------------------- /test/integration/oauth1-var-in-url-params.postman_collection.json: -------------------------------------------------------------------------------- 1 | { 2 | "variables": [], 3 | "info": { 4 | "name": "oauth1-params-in-url", 5 | "_postman_id": "3cd655fb-f1e6-e06f-73ad-03cf3792a502", 6 | "description": "A set of sanity tests to check the validity of set and retrieved OAuth1 tokens", 7 | "schema": "https://schema.getpostman.com/json/collection/v2.0.0/collection.json" 8 | }, 9 | "item": [ 10 | { 11 | "name": "https://postman-echo.com/oauth1?a={{vala}}", 12 | "event": [ 13 | { 14 | "listen": "prerequest", 15 | "script": { 16 | "type": "text/javascript", 17 | "exec": "postman.setEnvironmentVariable('vala', 'omg');" 18 | } 19 | } 20 | ], 21 | "request": { 22 | "auth": { 23 | "type": "oauth1", 24 | "oauth1": { 25 | "consumerKey": "RKCGzna7bv9YD57c", 26 | "consumerSecret": "D+EdQ-gs$-%@2Nu7", 27 | "token": "", 28 | "tokenSecret": "", 29 | "signatureMethod": "HMAC-SHA1", 30 | "timeStamp": 1461319769, 31 | "nonce": "ik3oT5", 32 | "version": "1.0", 33 | "realm": "", 34 | "addParamsToHeader": true, 35 | "addEmptyParamsToSign": false 36 | } 37 | }, 38 | "url": "https://postman-echo.com/oauth1?a={{vala}}", 39 | "method": "GET", 40 | "header": [ 41 | { 42 | "key": "Authorization", 43 | "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\"", 44 | "description": "" 45 | } 46 | ], 47 | "body": { 48 | "mode": "formdata", 49 | "formdata": [] 50 | }, 51 | "description": "" 52 | }, 53 | "response": [] 54 | } 55 | ] 56 | } 57 | -------------------------------------------------------------------------------- /examples/parallel-collection-runs.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @fileOverview A sample script to demonstrate parallel collection runs using async. 3 | */ 4 | var path = require('path'), // ensures that the path is consistent, regardless of where the script is run from 5 | 6 | async = require('async'), // https://npmjs.org/package/async 7 | newman = require('../'), // change to require('newman'), if using outside this repository 8 | 9 | /** 10 | * A set of collection run options for the paralle collection runs. For demonstrative purposes in this script, an 11 | * identical set of options has been used. However, different options can be used, so as to actually run different 12 | * collections, with their corresponding run options in parallel. 13 | * 14 | * @type {Object} 15 | */ 16 | options = { 17 | collection: path.join(__dirname, 'sample-collection.json') 18 | }, 19 | 20 | /** 21 | * A collection runner function that runs a collection for a pre-determined options object. 22 | * 23 | * @param {Function} done - A callback function that marks the end of the current collection run, when called. 24 | */ 25 | parallelCollectionRun = function (done) { 26 | newman.run(options, done); 27 | }; 28 | 29 | // Runs the Postman sample collection thrice, in parallel. 30 | async.parallel([ 31 | parallelCollectionRun, 32 | parallelCollectionRun, 33 | parallelCollectionRun 34 | ], 35 | 36 | /** 37 | * The 38 | * 39 | * @param {?Error} err - An Error instance / null that determines whether or not the parallel collection run 40 | * succeeded. 41 | * @param {Array} results - An array of collection run summary objects. 42 | */ 43 | function (err, results) { 44 | err && console.error(err); 45 | 46 | results.forEach(function (result) { 47 | var failures = result.run.failures; 48 | 49 | console.info(failures.length ? JSON.stringify(failures.failures, null, 2) : 50 | `${result.collection.name} ran successfully.`); 51 | }); 52 | }); 53 | -------------------------------------------------------------------------------- /docker/images/alpine/README.md: -------------------------------------------------------------------------------- 1 | # newman:alpine 2 | 3 | This image runs newman on node v16 on Alpine 4 | 5 | Build the image: 6 | 7 | ```terminal 8 | docker build -t postman/newman:alpine --build-arg NEWMAN_VERSION="full semver version" . 9 | ``` 10 | 11 | Or get it from [Docker Hub](https://registry.hub.docker.com/u/postman/newman/): 12 | 13 | ```terminal 14 | docker pull postman/newman:alpine 15 | ``` 16 | 17 | Then run it: 18 | 19 | ```terminal 20 | docker --volume="/home/postman/collections:/etc/newman" -t postman/newman:alpine run JSONBlobCoreAPI.json.postman_collection -r json --reporter-json-export newman-report.json 21 | ``` 22 | For 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: 23 | - You can pass the full path to your collection and environment files to newman. For instance, if you mount to `/etc/newman`, 24 | 25 | ```terminal 26 | docker --volume="/home/postman/collection:/etc/newman" -t postman/newman:alpine run JSONBlobCoreAPI.json.postman_collection" -r json --reporter-json-export newman-report.json 27 | ``` 28 | - You can change the working directory while running the image to the location you mounted to, using the `-w` or `--workdir` flag. 29 | 30 | ```terminal 31 | docker run --volume="/home/postman/collections:/etc/newman" -t postman/newman:alpine run JSONBlobCoreAPI.json.postman_collection -r json --reporter-json-export newman-report.json 32 | ``` 33 | 34 | In 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: 35 | 36 | ```terminal 37 | docker run -t postman/newman:alpine run https://www.getpostman.com/collections/8a0c9bc08f062d12dcda 38 | ``` 39 | -------------------------------------------------------------------------------- /docker/images/ubuntu/README.md: -------------------------------------------------------------------------------- 1 | # newman:ubuntu 2 | 3 | This image runs newman on node v16 on Ubuntu 22.04 4 | 5 | Build the image, 6 | 7 | ```terminal 8 | docker build -t postman/newman:ubuntu --build-arg NEWMAN_VERSION="full semver version" . 9 | ``` 10 | 11 | Or get it from [docker hub](https://registry.hub.docker.com/u/postman/newman:ubuntu/) 12 | 13 | ```terminal 14 | docker pull postman/newman:ubuntu 15 | ``` 16 | 17 | Then run it 18 | 19 | ```terminal 20 | docker --volume="/home/postman/collections:/etc/newman" -t postman/newman:ubuntu run JSONBlobCoreAPI.json.postman_collection -r json --reporter-json-export newman-report.json 21 | ``` 22 | For 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 23 | - You can either pass the full path to your collection and environment files to newman. For instance, if you mount to `/etc/newman`, 24 | 25 | ```terminal 26 | docker --volume="/home/postman/collection:/etc/newman" -t postman/newman:ubuntu run JSONBlobCoreAPI.json.postman_collection -r json --reporter-json-export newman-report.json 27 | ``` 28 | - You can change the working directory while running the image to the location you mounted to, using the `-w` or `--workdir` flag. 29 | 30 | ```terminal 31 | docker run --volume="/home/postman/collections:/etc/newman" -t postman/newman:ubuntu run JSONBlobCoreAPI.json.postman_collection -r json --reporter-json-export newman-report.json 32 | ``` 33 | 34 | In 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 35 | 36 | ```terminal 37 | docker run -t postman/newman:ubuntu run https://www.getpostman.com/collections/8a0c9bc08f062d12dcda 38 | ``` 39 | -------------------------------------------------------------------------------- /test/fixtures/run/ssl-client-cert-list.json: -------------------------------------------------------------------------------- 1 | { 2 | "info": { 3 | "_postman_id": "1f9d323c-5bb0-4885-87d0-ac5522f85d7d", 4 | "name": "Client cert example", 5 | "description": "A sample collection to demonstrate client SSL certificate handling", 6 | "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json" 7 | }, 8 | "item": [ 9 | { 10 | "name": "A simple GET request using client certificate 1 on server", 11 | "event": [ 12 | { 13 | "listen": "test", 14 | "script": { 15 | "id": "f169c71e-6a6c-40d6-92bf-0e99e36d30dd", 16 | "exec": [ 17 | "pm.test(\"Status code is 200\", function () {", 18 | " pm.response.to.have.status(200);", 19 | "});" 20 | ], 21 | "type": "text/javascript" 22 | } 23 | } 24 | ], 25 | "request": { 26 | "method": "GET", 27 | "header": [], 28 | "url": { 29 | "raw": "https://localhost:3001", 30 | "protocol": "https", 31 | "host": [ 32 | "localhost" 33 | ], 34 | "port": "3001" 35 | } 36 | } 37 | }, 38 | { 39 | "name": "A simple GET request using client certificate 2 on server 2", 40 | "event": [ 41 | { 42 | "listen": "test", 43 | "script": { 44 | "id": "c7e8c76f-c590-4fec-94b9-6049e5eb5e59", 45 | "exec": [ 46 | "pm.test(\"Status code is 200\", function () {", 47 | " pm.response.to.have.status(200);", 48 | "});" 49 | ], 50 | "type": "text/javascript" 51 | } 52 | } 53 | ], 54 | "request": { 55 | "method": "GET", 56 | "header": [], 57 | "url": { 58 | "raw": "https://localhost:3002", 59 | "protocol": "https", 60 | "host": [ 61 | "localhost" 62 | ], 63 | "port": "3002" 64 | } 65 | } 66 | } 67 | ] 68 | } 69 | -------------------------------------------------------------------------------- /test/integration/data-file-var-replacement/data-file-var-replacement.postman_collection.json: -------------------------------------------------------------------------------- 1 | { 2 | "variables": [], 3 | "info": { 4 | "name": "{{variable}} works for data file values", 5 | "_postman_id": "dd85194f-bdb3-8ce1-fd25-554cac614f89", 6 | "description": "A set of checks for variable value population via data files", 7 | "schema": "https://schema.getpostman.com/json/collection/v2.0.0/collection.json" 8 | }, 9 | "item": [ 10 | { 11 | "name": "https://postman-echo.com/post", 12 | "event": [ 13 | { 14 | "listen": "test", 15 | "script": { 16 | "type": "text/javascript", 17 | "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);" 18 | } 19 | }, 20 | { 21 | "listen": "prerequest", 22 | "script": { 23 | "type": "text/javascript", 24 | "exec": "postman.setEnvironmentVariable(\"dataVar2\",iteration);" 25 | } 26 | } 27 | ], 28 | "request": { 29 | "url": "https://{{envFileUrl}}/post", 30 | "method": "POST", 31 | "header": [ 32 | { 33 | "key": "h1", 34 | "value": "v1", 35 | "description": "" 36 | } 37 | ], 38 | "body": { 39 | "mode": "formdata", 40 | "formdata": [ 41 | { 42 | "key": "dataFileKey", 43 | "value": "{{dataVar}}", 44 | "type": "text" 45 | }, 46 | { 47 | "key": "envFileKey", 48 | "value": "{{envKey}}", 49 | "type": "text" 50 | }, 51 | { 52 | "key": "prScriptTest", 53 | "value": "{{dataVar2}}", 54 | "type": "text" 55 | } 56 | ] 57 | }, 58 | "description": "" 59 | }, 60 | "response": [] 61 | } 62 | ] 63 | } 64 | -------------------------------------------------------------------------------- /test/integration/prototype-check.postman_collection.json: -------------------------------------------------------------------------------- 1 | { 2 | "variables": [], 3 | "info": { 4 | "name": "SugarJS and native prototypes work", 5 | "_postman_id": "8f31aeff-c5b5-5c42-9540-fae109785538", 6 | "description": "A set of requests to test Array, String, Date, and Function prototypes", 7 | "schema": "https://schema.getpostman.com/json/collection/v2.0.0/collection.json" 8 | }, 9 | "item": [ 10 | { 11 | "name": "objectPrototype", 12 | "event": [ 13 | { 14 | "listen": "test", 15 | "script": { 16 | "type": "text/javascript", 17 | "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';" 18 | } 19 | } 20 | ], 21 | "request": { 22 | "url": "postman-echo.com/get", 23 | "method": "GET", 24 | "header": [], 25 | "body": { 26 | "mode": "formdata", 27 | "formdata": [] 28 | }, 29 | "description": "" 30 | }, 31 | "response": [] 32 | } 33 | ] 34 | } 35 | -------------------------------------------------------------------------------- /lib/config/rc-file.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-process-env */ 2 | var _ = require('lodash'), 3 | fs = require('fs'), 4 | join = require('path').join, 5 | async = require('async'), 6 | util = require('../util'), 7 | liquidJSON = require('liquid-json'), 8 | 9 | /** 10 | * Name of the directory that contains the file denoted by FILE_NAME. 11 | * 12 | * @type {String} 13 | */ 14 | POSTMAN_CONFIG_DIR = 'postman', 15 | 16 | /** 17 | * Name of the file that contains Newman compliant confguration information. 18 | * 19 | * @type {String} 20 | */ 21 | FILE_NAME = 'newmanrc'; 22 | 23 | /** 24 | * Configuration loader to acquire run settings from a file present in the home directory: POSTMAN_CONFIG_DIR/FILE_NAME. 25 | * 26 | * @param {Function} callback - The callback function invoked to mark the completion of the config loading routine. 27 | * @returns {*} 28 | */ 29 | module.exports.load = (callback) => { 30 | var iswin = (/^win/).test(process.platform), 31 | home = iswin ? process.env.USERPROFILE : process.env.HOME, 32 | 33 | configFiles = []; 34 | 35 | !iswin && configFiles.push(join('/etc', POSTMAN_CONFIG_DIR, FILE_NAME)); 36 | home && configFiles.push(join(home, '.' + POSTMAN_CONFIG_DIR, FILE_NAME)); 37 | configFiles.push(join(process.cwd(), '.' + FILE_NAME)); 38 | 39 | async.mapSeries(configFiles, (path, cb) => { 40 | fs.readFile(path, (err, data) => { 41 | if (err) { 42 | return cb(null, {}); // err masked to avoid overpopulating terminal with missing .newmanrc messages 43 | } 44 | data && data.toString && (data = data.toString(util.detectEncoding(data)).trim()); 45 | try { 46 | return cb(null, liquidJSON.parse(data)); 47 | } 48 | catch (e) { 49 | return cb(_.set(e, 'help', `The file at ${path} contains invalid data.`)); 50 | } 51 | }); 52 | }, (err, files) => { 53 | if (err) { 54 | return callback(err); 55 | } 56 | 57 | return callback(null, _.merge.apply(this, files)); 58 | }); 59 | }; 60 | -------------------------------------------------------------------------------- /lib/reporters/cli/cli-utils-symbols.js: -------------------------------------------------------------------------------- 1 | var IS_WINDOWS = (/^win/).test(process.platform), 2 | subsets, 3 | symbols; 4 | 5 | /** 6 | * A set of symbol groups for use in different situations: regular, windows friendly unicode, and plain text. 7 | * 8 | * @type {Object} 9 | */ 10 | subsets = { 11 | regular: { 12 | console: { 13 | top: '┌', 14 | middle: '│', 15 | bottom: '└' 16 | }, 17 | dot: '.', 18 | folder: '❏', 19 | root: '→', 20 | sub: '↳', 21 | ok: '✓', 22 | error: '✖', 23 | star: '★', 24 | up: '↑', 25 | down: '↓' 26 | }, 27 | encoded: { 28 | console: { 29 | top: '\u250C', 30 | middle: '\u2502', 31 | bottom: '\u2514' 32 | }, 33 | dot: '.', 34 | folder: '\u25A1', 35 | root: '\u2192', 36 | sub: '\u2514', 37 | ok: '\u221A', 38 | error: '\u00D7', 39 | star: '\u2605', 40 | up: '\u2191', 41 | down: '\u2193' 42 | }, 43 | plainText: { 44 | console: { 45 | top: '-', 46 | middle: '|', 47 | bottom: '-' 48 | }, 49 | dot: '.', 50 | folder: 'Folder', 51 | root: 'Root', 52 | sub: 'Sub-folder', 53 | ok: 'Pass', 54 | error: 'Fail', 55 | star: '*', 56 | up: '^', 57 | down: 'v' 58 | } 59 | }; 60 | 61 | /** 62 | * A method that picks the appropriate set of CLI report symbols under a given set of run conditions. 63 | * 64 | * @param {Boolean} disableUnicode - A flag to force plain text equivalents for CLI symbols if set to true. 65 | * @returns {Object} - The right set of symbols from subsets for the given conditions. 66 | * @todo Add additional parameter related to temp file read - writes 67 | */ 68 | symbols = function (disableUnicode) { 69 | if (disableUnicode) { 70 | return subsets.plainText; 71 | } 72 | if (IS_WINDOWS) { // modify symbols for windows platforms 73 | return subsets.encoded; 74 | } 75 | 76 | return subsets.regular; 77 | }; 78 | 79 | module.exports = symbols; 80 | -------------------------------------------------------------------------------- /npm/docker-publish.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Bail out on the first error 4 | set -e; 5 | 6 | LATEST="alpine"; 7 | RED="\033[0;31m"; 8 | BLUE="\033[0;34m"; 9 | NO_COLOUR="\033[0m"; 10 | DOCKER_REPO="postman/newman"; 11 | VERSION=${npm_package_version}; 12 | IMAGES_BASE_PATH="./docker/images"; 13 | IMAGES_PLATFORMS="linux/amd64,linux/arm64"; 14 | GIT_BRANCH=$(git rev-parse --abbrev-ref HEAD); 15 | 16 | if [[ ${GIT_BRANCH} != "main" ]]; then 17 | echo -e "$RED Not on main branch! $NO_COLOUR"; 18 | exit 1; 19 | fi 20 | 21 | # It's good to be paranoid 22 | [[ -z "$VERSION" ]] && VERSION=$(jq -r ".version" < package.json); 23 | 24 | MAJOR=$(echo ${VERSION} | grep -oE "^\d+"); 25 | 26 | function build_docker_image { 27 | local TAG=$(basename $1); 28 | 29 | echo ""; 30 | 31 | echo -e "$BLUE Building $DOCKER_REPO:$VERSION-$TAG $NO_COLOUR"; 32 | 33 | if [[ ${TAG} == ${LATEST} ]]; then 34 | docker buildx build \ 35 | --no-cache --file="docker/images/$TAG/Dockerfile" \ 36 | --build-arg NEWMAN_VERSION=${VERSION} --push \ 37 | --platform ${IMAGES_PLATFORMS} \ 38 | --tag ${DOCKER_REPO}:latest \ 39 | --tag ${DOCKER_REPO}:${TAG} \ 40 | --tag ${DOCKER_REPO}:${VERSION} \ 41 | --tag ${DOCKER_REPO}:${MAJOR} \ 42 | --tag ${DOCKER_REPO}:${VERSION}-${TAG} \ 43 | --tag ${DOCKER_REPO}:${MAJOR}-${TAG} \ 44 | . 45 | else 46 | docker buildx build \ 47 | --no-cache --file="docker/images/$TAG/Dockerfile" \ 48 | --build-arg NEWMAN_VERSION=${VERSION} --push \ 49 | --platform ${IMAGES_PLATFORMS} \ 50 | --tag ${DOCKER_REPO}:${TAG} \ 51 | --tag ${DOCKER_REPO}:${VERSION}-${TAG} \ 52 | --tag ${DOCKER_REPO}:${MAJOR}-${TAG} \ 53 | . 54 | fi 55 | 56 | echo -e "$BLUE Running docker image test for $DOCKER_REPO:$VERSION-$TAG, latest $NO_COLOUR"; 57 | 58 | # Test 59 | docker run -v ${PWD}/examples:/etc/newman -t ${DOCKER_REPO}:${VERSION}-${TAG} run "sample-collection.json"; 60 | } 61 | 62 | for image in ${IMAGES_BASE_PATH}/*; do 63 | build_docker_image ${image}; 64 | done 65 | -------------------------------------------------------------------------------- /test/library/requestAgents.test.js: -------------------------------------------------------------------------------- 1 | const sinon = require('sinon'), 2 | http = require('http'), 3 | https = require('https'), 4 | expect = require('chai').expect, 5 | 6 | newman = require('../../'); 7 | 8 | describe('newman.run requestAgents', function () { 9 | let httpAgent = new http.Agent(), 10 | httpsAgent = new https.Agent(), 11 | httpAgentSpy, 12 | httpsAgentSpy; 13 | 14 | before(function () { 15 | httpAgentSpy = sinon.spy(httpAgent, 'createConnection'); 16 | httpsAgentSpy = sinon.spy(httpsAgent, 'createConnection'); 17 | }); 18 | 19 | after(function () { 20 | httpAgentSpy.restore(); 21 | httpsAgentSpy.restore(); 22 | }); 23 | 24 | it('should accept custom requesting agents', function (done) { 25 | newman.run({ 26 | collection: { 27 | name: 'Collection', 28 | item: [{ 29 | request: 'http://postman-echo.com/redirect-to?url=https://httpbin.org/get' 30 | }] 31 | }, 32 | requestAgents: { 33 | http: httpAgent, 34 | https: httpsAgent 35 | } 36 | }, function (err, summary) { 37 | expect(err).to.be.null; 38 | expect(summary).to.be.ok; 39 | expect(summary.run.failures).to.be.empty; 40 | 41 | const httpAgentOpts = httpAgentSpy.getCall(0).args[0], 42 | httpsAgentOpts = httpsAgentSpy.getCall(0).args[0], 43 | response = summary.run.executions[0].response; 44 | 45 | sinon.assert.calledOnce(httpAgentSpy); 46 | sinon.assert.calledOnce(httpsAgentSpy); 47 | 48 | expect(httpsAgentOpts).to.have.property('agent').that.be.an.instanceof(http.Agent); 49 | expect(httpAgentOpts).to.have.property('host').that.equal('postman-echo.com'); 50 | 51 | expect(httpsAgentOpts).to.have.property('agent').that.be.an.instanceof(https.Agent); 52 | expect(httpsAgentOpts).to.have.property('host').that.equal('httpbin.org'); 53 | 54 | expect(response.reason()).to.equal('OK'); 55 | 56 | done(); 57 | }); 58 | }); 59 | }); 60 | -------------------------------------------------------------------------------- /test/unit/defaultReporter.test.js: -------------------------------------------------------------------------------- 1 | const sinon = require('sinon'), 2 | expect = require('chai').expect, 3 | newman = require('../../'); 4 | 5 | describe('Default reporter', function () { 6 | beforeEach(function () { 7 | sinon.replace(console, 'warn', sinon.fake()); 8 | }); 9 | 10 | afterEach(function () { 11 | sinon.restore(); 12 | }); 13 | 14 | it('cli can be loaded', function (done) { 15 | newman.run({ 16 | collection: 'test/fixtures/run/single-get-request.json', 17 | reporters: ['cli'] 18 | }, function (err) { 19 | expect(err).to.be.null; 20 | expect(console.warn.called).to.be.false; 21 | 22 | done(); 23 | }); 24 | }); 25 | 26 | it('json can be loaded', function (done) { 27 | newman.run({ 28 | collection: 'test/fixtures/run/single-get-request.json', 29 | reporters: ['json'] 30 | }, function (err) { 31 | expect(err).to.be.null; 32 | expect(console.warn.called).to.be.false; 33 | 34 | done(); 35 | }); 36 | }); 37 | 38 | it('junit can be loaded', function (done) { 39 | newman.run({ 40 | collection: 'test/fixtures/run/single-get-request.json', 41 | reporters: ['junit'] 42 | }, function (err) { 43 | expect(err).to.be.null; 44 | expect(console.warn.called).to.be.false; 45 | 46 | done(); 47 | }); 48 | }); 49 | 50 | it('progress can be loaded', function (done) { 51 | newman.run({ 52 | collection: 'test/fixtures/run/single-get-request.json', 53 | reporters: ['progress'] 54 | }, function (err) { 55 | expect(err).to.be.null; 56 | expect(console.warn.called).to.be.false; 57 | 58 | done(); 59 | }); 60 | }); 61 | 62 | it('emojitrain can be loaded', function (done) { 63 | newman.run({ 64 | collection: 'test/fixtures/run/single-get-request.json', 65 | reporters: ['emojitrain'] 66 | }, function (err) { 67 | expect(err).to.be.null; 68 | expect(console.warn.called).to.be.false; 69 | 70 | done(); 71 | }); 72 | }); 73 | }); 74 | -------------------------------------------------------------------------------- /docker/images/ubuntu/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:22.04 2 | LABEL maintainer="Postman Labs " 3 | 4 | ARG NODE_MAJOR=16 5 | ARG NEWMAN_VERSION 6 | 7 | # Bail out early if NEWMAN_VERSION is not provided 8 | RUN if [ ! $(echo $NEWMAN_VERSION | grep -oE "^[0-9]+\.[0-9]+\.[0-9]+$") ]; then \ 9 | echo "\033[0;31mA valid semver Newman version is required in the NEWMAN_VERSION build-arg\033[0m"; \ 10 | exit 1; \ 11 | fi 12 | 13 | RUN apt-get update; \ 14 | 15 | # Download and import the Nodesource GPG key 16 | apt-get install -y ca-certificates curl gnupg; \ 17 | mkdir -p /etc/apt/keyrings; \ 18 | curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key \ 19 | | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg; \ 20 | 21 | # Create deb repository 22 | echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_$NODE_MAJOR.x nodistro main" \ 23 | | tee /etc/apt/sources.list.d/nodesource.list; \ 24 | 25 | # Run Update and Install 26 | apt-get update; \ 27 | apt-get install nodejs -y; \ 28 | 29 | # Install Newman globally 30 | npm install --global newman@${NEWMAN_VERSION}; 31 | 32 | # Set environment variables 33 | ENV LC_ALL="en_US.UTF-8" LANG="en_US.UTF-8" LANGUAGE="en_US.UTF-8" 34 | 35 | # Set workdir to /etc/newman 36 | # When running the image, mount the directory containing your collection to this location 37 | # 38 | # docker run -v :/etc/newman ... 39 | # 40 | # In case you mount your collections directory to a different location, you will need to give absolute paths to any 41 | # collection, environment files you want to pass to newman, and if you want newman reports to be saved to your disk. 42 | # Or you can change the workdir by using the -w or --workdir flag 43 | WORKDIR /etc/newman 44 | 45 | # Set newman as the default container command 46 | # Now you can run the container via 47 | # 48 | # docker run -v /home/collections:/etc/newman -t postman/newman_ubuntu run YourCollection.json.postman_collection \ 49 | # -e YourEnvironment.postman_environment \ 50 | # -H newman_report.html 51 | ENTRYPOINT ["newman"] 52 | -------------------------------------------------------------------------------- /test/fixtures/ssl/ca.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIGJTCCBA2gAwIBAgIJANskintnrPWaMA0GCSqGSIb3DQEBCwUAMIGnMQswCQYD 3 | VQQGEwJJTjESMBAGA1UECAwJS2FybmF0YWthMRIwEAYDVQQHDAlCZW5nYWx1cnUx 4 | JTAjBgNVBAoMHFBvc3Rkb3QgVGVjaG5vbG9naWVzIFB2dCBMdGQxFDASBgNVBAsM 5 | C1Bvc3RtYW5sYWJzMQ8wDQYDVQQDDAZOZXdtYW4xIjAgBgkqhkiG9w0BCQEWE2hl 6 | bHBAZ2V0cG9zdG1hbi5jb20wIBcNMTYxMjE1MTQ1NzA4WhgPMjA4NTAxMDIxNDU3 7 | MDhaMIGnMQswCQYDVQQGEwJJTjESMBAGA1UECAwJS2FybmF0YWthMRIwEAYDVQQH 8 | DAlCZW5nYWx1cnUxJTAjBgNVBAoMHFBvc3Rkb3QgVGVjaG5vbG9naWVzIFB2dCBM 9 | dGQxFDASBgNVBAsMC1Bvc3RtYW5sYWJzMQ8wDQYDVQQDDAZOZXdtYW4xIjAgBgkq 10 | hkiG9w0BCQEWE2hlbHBAZ2V0cG9zdG1hbi5jb20wggIiMA0GCSqGSIb3DQEBAQUA 11 | A4ICDwAwggIKAoICAQDiXuPtHr4a+qt5lXVJQUul71DocndC7eKvu3Sr6yrEThjy 12 | BaH45DUKLS9vW0a6TQhdfwatJvkmv3xFFnu+F3anr4vMgGR3jcSr55ipsnGlK2iE 13 | Ua3y3Ikk7Q6TdOIJQ+wqhhtL7Cei/mwegjt6wGOO4bbUqD0dXd7endG4uPRIlMEv 14 | q5kaSZjECohmMAhHwdRfhTwOgCoqG7mdBDA/Lz5WdGUSBVo2fAxWjI3KlTDHOyIQ 15 | sSOr0zPUZUu3kyP+0jqPdzompflSlbYzqbjmD5gZsBL6fMUlheYx4M07Svy4LtZE 16 | 7JaaQ0/zAE7tc5IdS3sw0m6CuCoRODaqEnqRoG45g8GW8eeTz6rhWDs/2q8mU1pp 17 | Q5lpjXPlQ/mEAv0PICeOsFQlBQ/krr1IAx0EhG8aeaxlQ+QcyX2SmbHvlgOB7F4g 18 | nRYp6TsAQILaq6FHRo947Bi9G6OMF7/0ut5HIqZ9nQalxgtO+71xXXJWxa0sCXmD 19 | atdzXw+xh96VAmvqsqXlcYP30k2BVT1jvBaqcYHiG76tmmfT1UqzavUpDF3fQ+tf 20 | lAKW8kTW1SIDr2RZ4BOdvVKaM07MLGIk8tLvCQYpvzhilOjqgiMxzjQ30USPfLdA 21 | gXvAopfghuJrwLTzvbYAsszgNP/1+KrgLcxQO2ejlreJKZHXm8Y0uXbwAZcXyQID 22 | AQABo1AwTjAdBgNVHQ4EFgQUuJZUhNNBWTHQgmJCdrO1YyigjSowHwYDVR0jBBgw 23 | FoAUuJZUhNNBWTHQgmJCdrO1YyigjSowDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0B 24 | AQsFAAOCAgEA4bAWhXFbFJLiaX3Lsj+YWnrVVMrRrHzwfQlRVbRaEu0WsExNwfI/ 25 | 2HV3JrtV2PGYzIRwUBtX4/tg8r8BqPEDRcNtfu5P0Pv0PHlAxGgxLQQvrkbwz47g 26 | tCntZb9qzmROamTFjSxKnmjKSMjWxlCpeSCxG/00ib5tMhhgyMREIGgQvid4mfAD 27 | FY2hoFs1TOTxAFhNxfnt7U3RheTlv5CSFjbhUUWW3DyrJ7SouKIRdecMQCsnF+Ll 28 | qSFmjtMfhfWTudTpoEx/pNlFjAeEkxsMrRyKLDievYUGEiDd7zeTnr/TJt3zEMnB 29 | wqVaxmriBgIhDN5OS4rCPlUw8Xxjkj6vaucjnVaN/lKE/UWzFux8re4CIcENOR/D 30 | u/B03IaDldH2dKW+1qxPm2vaBsatwxJ9qqL3wPNpmshfE9+syjSf+LDZWS4k2wc3 31 | 4a8gjtAQYCXpEscrfJ4Gq2oJVFznW0USfZ167JEf1kx981g4iRl6wL097qZzZKDE 32 | htfQ8agefGjz8Vn+/AYWp9FOUA5extyRJTOApc6QrgUbfNiWj0lwBX4wvDoO1O+X 33 | fhqu5yCfqG1HYQTOPIXdwzBzWPH5VCtHTewXJ64PFFPNV5W+dpeXr0cz9fR8FZ+f 34 | 0GZM6woZ9Cz29RJbBX6dDwONJZLJJaGMWp5w2lAeI6HfUp6bSfmGpSc= 35 | -----END CERTIFICATE----- 36 | -------------------------------------------------------------------------------- /test/integration/request-chaining-test.postman_collection.json: -------------------------------------------------------------------------------- 1 | { 2 | "variables": [], 3 | "info": { 4 | "name": "newman-github-929", 5 | "_postman_id": "23e746e4-669b-c32e-0be5-724a07423a82", 6 | "description": "https://github.com/postmanlabs/newman/issues/929", 7 | "schema": "https://schema.getpostman.com/json/collection/v2.0.0/collection.json" 8 | }, 9 | "item": [ 10 | { 11 | "name": "Preliminary request", 12 | "event": [ 13 | { 14 | "listen": "test", 15 | "script": { 16 | "type": "text/javascript", 17 | "exec": [ 18 | "tests[\"Status code is 200\"] = responseCode.code === 200;", 19 | "tests[\"FOO doesn't exist\"] = !postman.getEnvironmentVariable(\"FOO\");", 20 | "tests[\"BAR doesn't exist\"] = !postman.getEnvironmentVariable(\"BAR\");", 21 | "", 22 | "postman.setEnvironmentVariable(\"FOO\", \"alpha\");", 23 | "postman.setEnvironmentVariable(\"BAR\", \"beta\");", 24 | "" 25 | ] 26 | } 27 | } 28 | ], 29 | "request": { 30 | "url": "https://postman-echo.com/get?val={{FOO}}&val2={{BAR}}", 31 | "method": "GET", 32 | "header": [], 33 | "body": {}, 34 | "description": "A simple GET request to seed environment variables `FOO` and `BAR`." 35 | }, 36 | "response": [] 37 | }, 38 | { 39 | "name": "Secondary request", 40 | "event": [ 41 | { 42 | "listen": "test", 43 | "script": { 44 | "type": "text/javascript", 45 | "exec": [ 46 | "var args = JSON.parse(responseBody).args;", 47 | "tests[\"Status code is 200\"] = responseCode.code === 200;", 48 | "", 49 | "tests[\"FOO exists\"] = postman.getEnvironmentVariable(\"FOO\") === \"alpha\";", 50 | "tests[\"BAR exists\"] = postman.getEnvironmentVariable(\"BAR\") === \"beta\";", 51 | "", 52 | "tests[\"val1 query param was sent correctly\"] = args.val === \"alpha\";", 53 | "tests[\"val1 query param was sent correctly\"] = args.val2 === \"beta\";" 54 | ] 55 | } 56 | } 57 | ], 58 | "request": { 59 | "url": "https://postman-echo.com/get?val={{FOO}}&val2={{BAR}}", 60 | "method": "GET", 61 | "header": [], 62 | "body": {}, 63 | "description": "A simple GET request to use seeded environment variables `FOO` and `BAR`." 64 | }, 65 | "response": [] 66 | } 67 | ] 68 | } 69 | -------------------------------------------------------------------------------- /test/integration/multiple-form-values.postman_collection.json: -------------------------------------------------------------------------------- 1 | { 2 | "variables": [], 3 | "info": { 4 | "name": "multipleFormValues", 5 | "_postman_id": "8feefa71-aa26-c53a-c9bb-069cb688a041", 6 | "description": "A test to check for successful sending of multiple / empty values for form data", 7 | "schema": "https://schema.getpostman.com/json/collection/v2.0.0/collection.json" 8 | }, 9 | "item": [ 10 | { 11 | "name": "multiformvalues", 12 | "event": [ 13 | { 14 | "listen": "test", 15 | "script": { 16 | "type": "text/javascript", 17 | "exec": "var data = JSON.parse(responseBody);\n\n\ntests[\"multiple values for form variable\"] = data.args.hi.length === 2;" 18 | } 19 | } 20 | ], 21 | "request": { 22 | "url": "https://postman-echo.com/get?hi=hello&hi=lolol", 23 | "method": "GET", 24 | "header": [], 25 | "body": { 26 | "mode": "formdata", 27 | "formdata": [] 28 | }, 29 | "description": "" 30 | }, 31 | "response": [] 32 | }, 33 | { 34 | "name": "multiformvalues", 35 | "event": [ 36 | { 37 | "listen": "test", 38 | "script": { 39 | "type": "text/javascript", 40 | "exec": "var data = JSON.parse(responseBody);\n\n\ntests[\"Can send empty urlencoded data\"] = responseCode.code===200;" 41 | } 42 | } 43 | ], 44 | "request": { 45 | "url": "https://postman-echo.com/post", 46 | "method": "POST", 47 | "header": [], 48 | "body": { 49 | "mode": "urlencoded", 50 | "urlencoded": [] 51 | }, 52 | "description": "" 53 | }, 54 | "response": [] 55 | }, 56 | { 57 | "name": "multiformvalues", 58 | "event": [ 59 | { 60 | "listen": "test", 61 | "script": { 62 | "type": "text/javascript", 63 | "exec": "var data = JSON.parse(responseBody);\n\n\ntests[\"Can send empty params data\"] = responseCode.code===200;" 64 | } 65 | } 66 | ], 67 | "request": { 68 | "url": "https://postman-echo.com/post", 69 | "method": "POST", 70 | "header": [], 71 | "body": { 72 | "mode": "formdata", 73 | "formdata": [] 74 | }, 75 | "description": "" 76 | }, 77 | "response": [] 78 | } 79 | ] 80 | } 81 | -------------------------------------------------------------------------------- /test/integration/comma-test-csv/comma-test-csv.postman_collection.json: -------------------------------------------------------------------------------- 1 | { 2 | "info": { 3 | "_postman_id": "ac876a75-22ac-40cf-8abe-27ad079b6a5d", 4 | "name": "CSV parsing test", 5 | "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json" 6 | }, 7 | "item": [ 8 | { 9 | "name": "r1", 10 | "event": [ 11 | { 12 | "listen": "test", 13 | "script": { 14 | "id": "00c12c73-e93f-4ba8-815c-20f6e4b5d137", 15 | "exec": [ 16 | "" 17 | ], 18 | "type": "text/javascript" 19 | } 20 | }, 21 | { 22 | "listen": "prerequest", 23 | "script": { 24 | "id": "8292797c-b676-4a41-966b-c2b92d607425", 25 | "exec": [ 26 | "pm.test(\"CSV parsing tests\", function () {", 27 | " pm.expect(data.nameWithComma).to.eql('Abhijit, Kane');", 28 | " pm.expect(data.nameWithDoubleQuotes).to.eql('Abhijit \"KDOS\" Kane');", 29 | " pm.expect(data.numberWithQuotes).to.eql('00123');", 30 | " pm.expect(data.numberWithoutQuotes).to.eql(7890);", 31 | " pm.expect(data.negativeNumberWithoutQuotes).to.eql(-7890);", 32 | " pm.expect(data.nullValue).to.eql('');", 33 | " pm.expect(data.longNumber).to.eql('89111702272002019559');", 34 | " pm.expect(data.spaceAfterComma).to.eql('foo');", 35 | " pm.expect(data.spaceBeforeComma).to.eql('bar');", 36 | " pm.expect(data.nameWithUnescapedQuotes).to.eql('Abhijit \"KDOS\" Kane');", 37 | "});" 38 | ], 39 | "type": "text/javascript" 40 | } 41 | } 42 | ], 43 | "protocolProfileBehavior": { 44 | "disableBodyPruning": true 45 | }, 46 | "request": { 47 | "method": "GET", 48 | "header": [ 49 | { 50 | "key": "Content-Type", 51 | "name": "Content-Type", 52 | "value": "application/json", 53 | "type": "text" 54 | } 55 | ], 56 | "body": { 57 | "mode": "raw", 58 | "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}" 59 | }, 60 | "url": { 61 | "raw": "postman-echo.com/get", 62 | "host": [ 63 | "postman-echo", 64 | "com" 65 | ], 66 | "path": [ 67 | "get" 68 | ] 69 | } 70 | }, 71 | "response": [] 72 | } 73 | ] 74 | } 75 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | paths-ignore: 6 | - "*.md" 7 | pull_request: 8 | branches: [$default-branch] 9 | schedule: 10 | - cron: "0 12 * * 0" 11 | 12 | concurrency: 13 | group: ${{ github.workflow }}-${{ github.ref }} 14 | cancel-in-progress: true 15 | 16 | jobs: 17 | tests: 18 | name: Tests 19 | runs-on: ${{ matrix.os }} 20 | strategy: 21 | fail-fast: false 22 | matrix: 23 | node-version: [16, 18] 24 | os: [ubuntu-latest, windows-latest] 25 | 26 | steps: 27 | - name: Checkout repository 28 | uses: actions/checkout@v3 29 | 30 | - name: Use Node.js ${{ matrix.node-version }} 31 | uses: actions/setup-node@v3 32 | with: 33 | node-version: ${{ matrix.node-version }} 34 | cache: "npm" 35 | 36 | - name: Install 37 | run: npm ci 38 | 39 | - name: Run tests 40 | run: npm run test 41 | 42 | coverage: 43 | name: Coverage 44 | runs-on: ubuntu-latest 45 | 46 | steps: 47 | - name: Checkout repository 48 | uses: actions/checkout@v3 49 | 50 | - name: Use Node.js 20 51 | uses: actions/setup-node@v3 52 | with: 53 | node-version: 20 54 | cache: "npm" 55 | 56 | - name: Install 57 | run: npm ci 58 | 59 | - name: Run unit tests 60 | run: | 61 | npm run test-unit 62 | bash <(curl -s https://codecov.io/bash) -c -Z -f .coverage/coverage-final.json -F unit -t ${{ secrets.CODECOV_TOKEN }} 63 | 64 | - name: Run integration tests 65 | run: | 66 | npm run test-integration 67 | bash <(curl -s https://codecov.io/bash) -c -Z -f .coverage/coverage-final.json -F integration -t ${{ secrets.CODECOV_TOKEN }} 68 | 69 | - name: Run CLI tests 70 | run: | 71 | npm run test-cli 72 | bash <(curl -s https://codecov.io/bash) -c -Z -f .coverage/coverage-final.json -F cli -t ${{ secrets.CODECOV_TOKEN }} 73 | 74 | - name: Run library tests 75 | run: | 76 | npm run test-library 77 | bash <(curl -s https://codecov.io/bash) -c -Z -f .coverage/coverage-final.json -F library -t ${{ secrets.CODECOV_TOKEN }} 78 | -------------------------------------------------------------------------------- /test/library/working-directory.test.js: -------------------------------------------------------------------------------- 1 | const path = require('path'), 2 | expect = require('chai').expect, 3 | 4 | newman = require('../../'), 5 | workingDir = path.resolve(__dirname, '../fixtures/files/work-dir'); 6 | 7 | describe('newman.run workingDir', function () { 8 | it('should resolve file present inside working directory', function (done) { 9 | newman.run({ 10 | collection: 'test/fixtures/run/single-file-inside.json', 11 | workingDir: workingDir 12 | }, function (err, summary) { 13 | expect(err).to.be.null; 14 | expect(summary.run.stats.iterations.total, 'should have 1 iteration').to.equal(1); 15 | expect(summary.run.stats.assertions.total, 'should have 2 assertions').to.equal(2); 16 | expect(summary.run.stats.assertions.failed, 'should not have failing tests').to.equal(0); 17 | expect(summary.run.executions, 'should have 2 executions').to.have.lengthOf(2); 18 | done(); 19 | }); 20 | }); 21 | 22 | it('should not resolve file present outside working directory with insecureFileRead=false', function (done) { 23 | newman.run({ 24 | collection: 'test/fixtures/run/single-file-outside.json', 25 | workingDir: workingDir, 26 | insecureFileRead: false 27 | }, function (err, summary) { 28 | expect(err).to.be.null; 29 | expect(summary.run.stats.iterations.total, 'should have 1 iteration').to.equal(1); 30 | expect(summary.run.stats.assertions.total, 'should have 2 assertions').to.equal(2); 31 | expect(summary.run.stats.assertions.failed, 'should not 2 failing tests').to.equal(2); 32 | expect(summary.run.executions, 'should have 2 executions').to.have.lengthOf(2); 33 | done(); 34 | }); 35 | }); 36 | 37 | it('should resolve file present outside working directory by default', function (done) { 38 | newman.run({ 39 | collection: 'test/fixtures/run/single-file-outside.json', 40 | workingDir: workingDir 41 | }, function (err, summary) { 42 | expect(err).to.be.null; 43 | expect(summary.run.stats.iterations.total, 'should have 1 iteration').to.equal(1); 44 | expect(summary.run.stats.assertions.total, 'should have 2 assertions').to.equal(2); 45 | expect(summary.run.stats.assertions.failed, 'should not have failing tests').to.equal(0); 46 | expect(summary.run.executions, 'should have 2 executions').to.have.lengthOf(2); 47 | done(); 48 | }); 49 | }); 50 | }); 51 | -------------------------------------------------------------------------------- /test/integration/v2-regression-tests/v2-regression-tests.postman_collection.json: -------------------------------------------------------------------------------- 1 | { 2 | "variables": [], 3 | "info": { 4 | "name": "regression_tests", 5 | "_postman_id": "925beee2-97e5-3122-5067-6bb31e07aad2", 6 | "description": "A collection to help check backward compatibility and keep previously resolved issue from re-surfacing", 7 | "schema": "https://schema.getpostman.com/json/collection/v2.0.0/collection.json" 8 | }, 9 | "item": [ 10 | { 11 | "name": "Variables as query parameters", 12 | "event": [ 13 | { 14 | "listen": "test", 15 | "script": { 16 | "type": "text/javascript", 17 | "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\");" 18 | } 19 | } 20 | ], 21 | "request": { 22 | "url": "https://postman-echo.com/cookies/set?foo1={{envKey}}&foo2=bar", 23 | "method": "GET", 24 | "header": [], 25 | "body": { 26 | "mode": "formdata", 27 | "formdata": [] 28 | }, 29 | "description": "This request checks for the correct handling of variables as query parameters" 30 | }, 31 | "response": [] 32 | }, 33 | { 34 | "name": "Insecurity checks", 35 | "event": [ 36 | { 37 | "listen": "test", 38 | "script": { 39 | "type": "text/javascript", 40 | "exec": "tests[\"Status code is 200\"] = responseCode.code === 200;" 41 | } 42 | } 43 | ], 44 | "request": { 45 | "url": "https://expired.badssl.com", 46 | "method": "GET", 47 | "header": [], 48 | "body": { 49 | "mode": "formdata", 50 | "formdata": [] 51 | }, 52 | "description": "This request validates running with the insecure option set to true" 53 | }, 54 | "response": [] 55 | }, 56 | { 57 | "name": "Disabled header", 58 | "event": [ 59 | { 60 | "listen": "test", 61 | "script": { 62 | "type": "text/javascript", 63 | "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\"];" 64 | } 65 | } 66 | ], 67 | "request": { 68 | "url": "https://postman-echo.com/headers", 69 | "method": "GET", 70 | "header": [ 71 | { 72 | "key": "//disabled-header", 73 | "value": "randomHeaderString", 74 | "description": "", 75 | "disabled": true 76 | } 77 | ], 78 | "body": { 79 | "mode": "formdata", 80 | "formdata": [] 81 | }, 82 | "description": "Checks for the absence of disabled headers in the response object" 83 | }, 84 | "response": [] 85 | } 86 | ] 87 | } 88 | -------------------------------------------------------------------------------- /lib/config/index.js: -------------------------------------------------------------------------------- 1 | var _ = require('lodash'), 2 | async = require('async'), 3 | 4 | env = require('./process-env'), 5 | rcfile = require('./rc-file'); 6 | 7 | /** 8 | * Reads configuration from config file, environment variables and CLI arguments. The CLI arguments override environment 9 | * variables and environment variables override the configuration read from a file. 10 | * 11 | * @param {Object} overrides - Configuration overrides (these usually come from the CLI). 12 | * @param {Object} options - The wrapper object of settings used for selective configuration loading. 13 | * @param {String} options.command - Command name. Used for loading the required options from the config file. 14 | * @param {Boolean=} options.ignoreRcFile - If true, the RC file is ignored. 15 | * @param {Boolean=} options.ignoreProcessEnvironment - If true, the process environment variables are ignored. 16 | * @param {Object=} options.loaders - Custom loaders for specific configuration options. 17 | * @param {Function} callback - Is called after merging values from the overrides with the values from the rc file and 18 | * environment variables. 19 | * @returns {*} 20 | */ 21 | module.exports.get = (overrides, options, callback) => { 22 | !callback && _.isFunction(options) && (callback = options, options = {}); 23 | 24 | var loaders = options.loaders, 25 | commonOptions = _.pick(overrides, ['postmanApiKey']); 26 | 27 | async.waterfall([ 28 | // Load RC Files. 29 | !options.ignoreRcFile ? rcfile.load : (cb) => { 30 | return cb(null, {}); 31 | }, 32 | // Load Process Environment overrides 33 | (fileOptions, cb) => { 34 | fileOptions[options.command] && (fileOptions = fileOptions[options.command]); 35 | 36 | return cb(null, _.merge(fileOptions, options.ignoreProcessEnvironment ? {} : env)); 37 | } 38 | ], (err, options) => { 39 | if (err) { 40 | return callback(err); 41 | } 42 | 43 | options = _.mergeWith({}, options, overrides, (dest, src) => { 44 | // If the newer value is a null, do not override it. 45 | return (src === null) ? dest : undefined; 46 | }); 47 | 48 | if (_.isEmpty(loaders)) { 49 | return callback(null, options); 50 | } 51 | // sanitize environment option 52 | if (!options.environment) { 53 | options.environment = {}; 54 | } 55 | // sanitize globals option 56 | if (!options.globals) { 57 | options.globals = {}; 58 | } 59 | 60 | async.mapValues(options, (value, name, cb) => { 61 | return (value && _.isFunction(loaders[name])) ? loaders[name](value, commonOptions, cb) : cb(null, value); 62 | }, callback); 63 | }); 64 | }; 65 | -------------------------------------------------------------------------------- /test/library/folder-variants.test.js: -------------------------------------------------------------------------------- 1 | const expect = require('chai').expect, 2 | 3 | newman = require('../../'); 4 | 5 | describe('folder variants', function () { 6 | var collection = { 7 | id: 'C1', 8 | name: 'Collection C1', 9 | item: [{ 10 | id: 'ID1', 11 | name: 'R1', 12 | request: 'https://postman-echo.com/get' 13 | }, { 14 | id: 'ID2', 15 | name: 'R2', 16 | request: 'https://postman-echo.com/get' 17 | }, { 18 | id: 'ID3', 19 | name: 'R3', 20 | request: 'https://postman-echo.com/get' 21 | }] 22 | }; 23 | 24 | it('should run the specified request in case folder name is valid', function (done) { 25 | newman.run({ 26 | collection: collection, 27 | folder: 'R1' 28 | }, function (err, summary) { 29 | expect(err).to.be.null; 30 | expect(summary.run.stats.iterations.total, 'should have 1 iteration').to.equal(1); 31 | expect(summary.run.executions, 'should have 1 executions').to.have.lengthOf(1); 32 | expect(summary.run.executions.map((e) => { return e.item.name; })).to.eql(['R1']); 33 | done(); 34 | }); 35 | }); 36 | 37 | it('should skip the collection run in case folder name is invalid', function (done) { 38 | newman.run({ 39 | collection: collection, 40 | folder: 'R123' 41 | }, function (err) { 42 | expect(err).to.be.ok; 43 | expect(err.message) 44 | .to.equal('runtime~extractRunnableItems: Unable to find a folder or request: "R123"'); 45 | done(); 46 | }); 47 | }); 48 | 49 | it('should run the specified requests in case multiple folder names are passed', function (done) { 50 | newman.run({ 51 | collection: collection, 52 | folder: ['R1', 'R3'] 53 | }, function (err, summary) { 54 | expect(err).to.be.null; 55 | expect(summary.run.stats.iterations.total, 'should have 1 iteration').to.equal(1); 56 | expect(summary.run.executions, 'should have 2 executions').to.have.lengthOf(2); 57 | expect(summary.run.executions.map((e) => { return e.item.name; })).to.eql(['R1', 'R3']); 58 | done(); 59 | }); 60 | }); 61 | 62 | it('should skip the collection run in case any of the folder name is invalid', function (done) { 63 | newman.run({ 64 | collection: collection, 65 | folder: ['R1', 'R123'] 66 | }, function (err) { 67 | expect(err).to.be.ok; 68 | expect(err.message) 69 | .to.equal('runtime~extractRunnableItems: Invalid entrypoint'); 70 | done(); 71 | }); 72 | }); 73 | }); 74 | -------------------------------------------------------------------------------- /test/integration/head-requests.postman_collection.json: -------------------------------------------------------------------------------- 1 | { 2 | "variables": [], 3 | "info": { 4 | "name": "Head test", 5 | "_postman_id": "9997428c-5951-3fd2-2a02-88bbe9d91c7f", 6 | "description": "A set of tests for checking HEAD requests", 7 | "schema": "https://schema.getpostman.com/json/collection/v2.0.0/collection.json" 8 | }, 9 | "item": [ 10 | { 11 | "name": "google", 12 | "event": [ 13 | { 14 | "listen": "test", 15 | "script": { 16 | "type": "text/javascript", 17 | "exec": "tests['Status is 200 OK'] = responseCode.code === 200;" 18 | } 19 | } 20 | ], 21 | "request": { 22 | "url": "http://google.com", 23 | "method": "HEAD", 24 | "header": [], 25 | "body": { 26 | "mode": "formdata", 27 | "formdata": [] 28 | }, 29 | "description": "" 30 | }, 31 | "response": [] 32 | }, 33 | { 34 | "name": "github", 35 | "event": [ 36 | { 37 | "listen": "test", 38 | "script": { 39 | "type": "text/javascript", 40 | "exec": "tests['Status is 200 OK'] = responseCode.code === 200;" 41 | } 42 | } 43 | ], 44 | "request": { 45 | "url": "http://github.com", 46 | "method": "HEAD", 47 | "header": [], 48 | "body": { 49 | "mode": "formdata", 50 | "formdata": [] 51 | }, 52 | "description": "" 53 | }, 54 | "response": [] 55 | }, 56 | { 57 | "name": "with request body", 58 | "event": [{ 59 | "listen": "test", 60 | "script": { 61 | "id": "088721b0-c2e6-47fa-85b0-8a4f79c71f82", 62 | "type": "text/javascript", 63 | "exec": [ 64 | "pm.test(\"Response Body\", function () {", 65 | " var response = pm.response.headers.get('raw-request');", 66 | " pm.expect(response).to.contain('HEAD / HTTP/1.1');", 67 | " pm.expect(response).to.contain('Content-Type: multipart/form-data');", 68 | " pm.expect(response).to.contain('Content-Disposition: form-data;');", 69 | " pm.expect(response).to.contain('FormDataValue');", 70 | "});" 71 | ] 72 | } 73 | }], 74 | "request": { 75 | "url": "http://localhost:4041", 76 | "method": "HEAD", 77 | "header": [], 78 | "body": { 79 | "mode": "formdata", 80 | "formdata": [{ 81 | "key": "dataKey", 82 | "value": "FormDataValue", 83 | "type": "text" 84 | }] 85 | }, 86 | "description": "" 87 | }, 88 | "response": [], 89 | "protocolProfileBehavior": { 90 | "disableBodyPruning": true 91 | } 92 | } 93 | ] 94 | } 95 | -------------------------------------------------------------------------------- /test/integration/dynamic-var-replacement.postman_collection.json: -------------------------------------------------------------------------------- 1 | { 2 | "variables": [], 3 | "info": { 4 | "name": "Dynamic variables (guid/timestamp/randomInt)", 5 | "_postman_id": "9543b60e-886a-b820-3f16-7087af71d296", 6 | "description": "Test collection to show bug around dynamic variables with Newman", 7 | "schema": "https://schema.getpostman.com/json/collection/v2.0.0/collection.json" 8 | }, 9 | "item": [ 10 | { 11 | "name": "POST Request copy", 12 | "event": [ 13 | { 14 | "listen": "test", 15 | "script": { 16 | "type": "text/javascript", 17 | "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" 18 | } 19 | } 20 | ], 21 | "request": { 22 | "url": "https://postman-echo.com/post", 23 | "method": "POST", 24 | "header": [], 25 | "body": { 26 | "mode": "urlencoded", 27 | "urlencoded": [ 28 | { 29 | "key": "FriendlyName", 30 | "value": "{{$guid}}", 31 | "type": "text", 32 | "enabled": true 33 | }, 34 | { 35 | "key": "RandomId", 36 | "value": "{{$randomInt}}", 37 | "type": "text", 38 | "enabled": true 39 | }, 40 | { 41 | "key": "TimeCreated", 42 | "value": "{{$timestamp}}", 43 | "type": "text", 44 | "enabled": true 45 | } 46 | ] 47 | }, 48 | "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> \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." 49 | }, 50 | "response": [] 51 | } 52 | ] 53 | } 54 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "newman", 3 | "version": "6.2.1", 4 | "description": "Command-line companion utility for Postman", 5 | "author": "Postman Labs (=)", 6 | "license": "Apache-2.0", 7 | "homepage": "https://github.com/postmanlabs/newman", 8 | "bugs": "https://github.com/postmanlabs/newman/issues", 9 | "repository": { 10 | "type": "git", 11 | "url": "git://github.com/postmanlabs/newman.git" 12 | }, 13 | "keywords": [ 14 | "newman", 15 | "postman", 16 | "api", 17 | "testing", 18 | "ci", 19 | "rest-client", 20 | "rest" 21 | ], 22 | "main": "index.js", 23 | "bin": { 24 | "newman": "./bin/newman.js" 25 | }, 26 | "preferGlobal": true, 27 | "scripts": { 28 | "docker-publish": "./npm/docker-publish.sh", 29 | "release": "node npm/create-release.js", 30 | "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", 31 | "test-cli": "nyc --nycrc-path=.nycrc.js node npm/test-cli.js", 32 | "test-integration": "nyc --nycrc-path=.nycrc.js node npm/test-integration.js", 33 | "test-library": "nyc --nycrc-path=.nycrc.js node npm/test-library.js", 34 | "test-lint": "node npm/test-lint.js", 35 | "test-system": "node npm/test-system.js", 36 | "test-unit": "nyc --nycrc-path=.nycrc.js node npm/test-unit.js" 37 | }, 38 | "dependencies": { 39 | "@postman/tough-cookie": "4.1.3-postman.1", 40 | "async": "3.2.5", 41 | "chardet": "2.0.0", 42 | "cli-progress": "3.12.0", 43 | "cli-table3": "0.6.5", 44 | "colors": "1.4.0", 45 | "commander": "11.1.0", 46 | "csv-parse": "4.16.3", 47 | "filesize": "10.1.4", 48 | "liquid-json": "0.3.1", 49 | "lodash": "4.17.21", 50 | "mkdirp": "3.0.1", 51 | "postman-collection": "4.4.0", 52 | "postman-collection-transformer": "4.1.8", 53 | "postman-request": "2.88.1-postman.34", 54 | "postman-runtime": "7.39.1", 55 | "pretty-ms": "7.0.1", 56 | "semver": "7.6.3", 57 | "serialised-error": "1.1.3", 58 | "word-wrap": "1.2.5", 59 | "xmlbuilder": "15.1.1" 60 | }, 61 | "devDependencies": { 62 | "@postman/shipit": "^0.4.0", 63 | "chai": "^4.4.1", 64 | "dependency-check": "^4.1.0", 65 | "dockerfile_lint": "^0.3.4", 66 | "editorconfig": "^2.0.0", 67 | "eslint": "^8.56.0", 68 | "eslint-plugin-jsdoc": "^46.9.1", 69 | "eslint-plugin-lodash": "^7.4.0", 70 | "eslint-plugin-mocha": "^10.5.0", 71 | "eslint-plugin-security": "^2.1.1", 72 | "js-yaml": "^4.1.0", 73 | "mocha": "^10.7.3", 74 | "nock": "^13.5.4", 75 | "nyc": "^15.1.0", 76 | "parse-gitignore": "^2.0.0", 77 | "recursive-readdir": "^2.2.3", 78 | "server-destroy": "^1.0.1", 79 | "shelljs": "^0.8.5", 80 | "sinon": "^18.0.0", 81 | "xml2js": "^0.6.2" 82 | }, 83 | "engines": { 84 | "node": ">=16" 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /.github/workflows/codeql-analysis.yml: -------------------------------------------------------------------------------- 1 | # For most projects, this workflow file will not need changing; you simply need 2 | # to commit it to your repository. 3 | # 4 | # You may wish to alter this file to override the set of languages analyzed, 5 | # or to provide custom queries or build logic. 6 | # 7 | # ******** NOTE ******** 8 | # We have attempted to detect the languages in your repository. Please check 9 | # the `language` matrix defined below to confirm you have the correct set of 10 | # supported CodeQL languages. 11 | # 12 | name: "CodeQL" 13 | 14 | on: 15 | push: 16 | branches: [ develop, main, release/*.x ] 17 | pull_request: 18 | # The branches below must be a subset of the branches above 19 | branches: [ "develop" ] 20 | schedule: 21 | - cron: '31 14 * * 2' 22 | 23 | jobs: 24 | analyze: 25 | name: Analyze 26 | runs-on: ubuntu-latest 27 | permissions: 28 | actions: read 29 | contents: read 30 | security-events: write 31 | 32 | strategy: 33 | fail-fast: false 34 | matrix: 35 | language: [ 'javascript' ] 36 | # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ] 37 | # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support 38 | 39 | steps: 40 | - name: Checkout repository 41 | uses: actions/checkout@v3 42 | 43 | # Initializes the CodeQL tools for scanning. 44 | - name: Initialize CodeQL 45 | uses: github/codeql-action/init@v2 46 | with: 47 | languages: ${{ matrix.language }} 48 | # If you wish to specify custom queries, you can do so here or in a config file. 49 | # By default, queries listed here will override any specified in a config file. 50 | # Prefix the list here with "+" to use these queries and those in the config file. 51 | 52 | # 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 53 | # queries: security-extended,security-and-quality 54 | 55 | 56 | # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). 57 | # If this step fails, then you should remove it and run the build manually (see below) 58 | - name: Autobuild 59 | uses: github/codeql-action/autobuild@v2 60 | 61 | # ℹ️ Command-line programs to run using the OS shell. 62 | # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun 63 | 64 | # If the Autobuild fails above, remove it and uncomment the following three lines. 65 | # modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance. 66 | 67 | # - run: | 68 | # echo "Run, Build Application using script" 69 | # ./location_of_script_within_repo/buildscript.sh 70 | 71 | - name: Perform CodeQL Analysis 72 | uses: github/codeql-action/analyze@v2 73 | -------------------------------------------------------------------------------- /test/integration/set-next-request.postman_collection.json: -------------------------------------------------------------------------------- 1 | { 2 | "variables": [], 3 | "info": { 4 | "name": "NewmanSetNextRequest", 5 | "_postman_id": "d6f7bb29-2258-4e1b-9576-b2315cf5b77e", 6 | "description": "A set of tests to verify set and get operations on environment variables", 7 | "schema": "https://schema.getpostman.com/json/collection/v2.0.0/collection.json" 8 | }, 9 | "item": [ 10 | { 11 | "name": "post", 12 | "event": [ 13 | { 14 | "listen": "test", 15 | "script": { 16 | "type": "text/javascript", 17 | "exec": "postman.setEnvironmentVariable('method', 'get');\npostman.setEnvironmentVariable('count', '1');\nconsole.log('Environment is now: ', environment);\npostman.setNextRequest('method');" 18 | } 19 | } 20 | ], 21 | "request": { 22 | "url": "https://postman-echo.com/post", 23 | "method": "POST", 24 | "header": [], 25 | "body": { 26 | "mode": "formdata", 27 | "formdata": [] 28 | }, 29 | "description": "" 30 | }, 31 | "response": [] 32 | }, 33 | { 34 | "name": "html", 35 | "event": [ 36 | { 37 | "listen": "test", 38 | "script": { 39 | "type": "text/javascript", 40 | "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}" 41 | } 42 | } 43 | ], 44 | "request": { 45 | "url": "https://postman-echo.com/type/html", 46 | "method": "GET", 47 | "header": [], 48 | "body": { 49 | "mode": "formdata", 50 | "formdata": [] 51 | }, 52 | "description": "" 53 | }, 54 | "response": [] 55 | }, 56 | { 57 | "name": "method", 58 | "event": [ 59 | { 60 | "listen": "test", 61 | "script": { 62 | "type": "text/javascript", 63 | "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}" 64 | } 65 | } 66 | ], 67 | "request": { 68 | "url": "https://postman-echo.com/{{method}}", 69 | "method": "GET", 70 | "header": [], 71 | "body": { 72 | "mode": "formdata", 73 | "formdata": [] 74 | }, 75 | "description": "" 76 | }, 77 | "response": [] 78 | } 79 | ] 80 | } 81 | -------------------------------------------------------------------------------- /test/integration/helper.postman_collection.json: -------------------------------------------------------------------------------- 1 | { 2 | "variables": [], 3 | "info": { 4 | "name": "Helper Tests", 5 | "_postman_id": "34783f86-4a67-d3bd-ba5b-148495fa2f72", 6 | "description": "A set of tests to verify generated OAuth1 and Digest Auth signatures", 7 | "schema": "https://schema.getpostman.com/json/collection/v2.0.0/collection.json" 8 | }, 9 | "item": [ 10 | { 11 | "name": "OAuth", 12 | "event": [ 13 | { 14 | "listen": "test", 15 | "script": { 16 | "type": "text/javascript", 17 | "exec": [ 18 | "pm.test('should authorize correctly', function () {", 19 | " pm.response.to.have.jsonBody({", 20 | " status: 'pass',", 21 | " message: 'OAuth-1.0a signature verification was successful'", 22 | " })", 23 | " pm.request.to.have.header('Authorization');", 24 | "});" 25 | ] 26 | } 27 | } 28 | ], 29 | "request": { 30 | "auth": { 31 | "type": "oauth1", 32 | "oauth1": { 33 | "consumerKey": "RKCGzna7bv9YD57c", 34 | "consumerSecret": "D+EdQ-gs$-%@2Nu7", 35 | "token": "", 36 | "tokenSecret": "", 37 | "signatureMethod": "HMAC-SHA1", 38 | "timeStamp": 1461319769, 39 | "nonce": "ik3oT5", 40 | "version": "1.0", 41 | "realm": "", 42 | "addParamsToHeader": true, 43 | "addEmptyParamsToSign": false 44 | } 45 | }, 46 | "url": "https://postman-echo.com/oauth1", 47 | "method": "GET" 48 | } 49 | }, 50 | { 51 | "name": "basicAuth", 52 | "event": [ 53 | { 54 | "listen": "test", 55 | "script": { 56 | "type": "text/javascript", 57 | "exec": [ 58 | "pm.test('Should authorize correctly', function () {", 59 | " pm.request.to.have.header('Authorization', 'Basic cG9zdG1hbjpwYXNzd29yZA==');", 60 | "});" 61 | ] 62 | } 63 | } 64 | ], 65 | "request": { 66 | "auth": { 67 | "type": "basic", 68 | "basic": { 69 | "username": "postman", 70 | "password": "password" 71 | } 72 | }, 73 | "url": "https://postman-echo.com/basic-auth", 74 | "method": "GET" 75 | }, 76 | "response": [] 77 | }, 78 | { 79 | "name": "DigestAuth", 80 | "event": [ 81 | { 82 | "listen": "test", 83 | "script": { 84 | "type": "text/javascript", 85 | "exec": [ 86 | "pm.test('should authorize correctly', function () {", 87 | " pm.response.to.have.jsonBody({ authenticated: true });", 88 | "});" 89 | ] 90 | } 91 | } 92 | ], 93 | "request": { 94 | "auth": { 95 | "type": "digest", 96 | "digest": { 97 | "algorithm": "MD5", 98 | "username": "postman", 99 | "password": "password" 100 | } 101 | }, 102 | "url": "https://postman-echo.com/digest-auth" 103 | } 104 | } 105 | ] 106 | } 107 | -------------------------------------------------------------------------------- /test/fixtures/ssl/ca.key: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | Proc-Type: 4,ENCRYPTED 3 | DEK-Info: DES-EDE3-CBC,D31E02E0C1169C3B 4 | 5 | vnh9eYeTXMyAjRAEgRBF7geTIrJgs9Ny6W8l5XGEylQH0+hNznChV7FHBhNUrYNn 6 | yW/J9FnBxMaixKISjHSV8ExIN0d7KGQw2LKXr3BzORrBzVk3tHnX3OrzMUUYQK16 7 | TUnV0dKSGjxwxQFffTmWQv3fY+U23dBgjkaAs9EBpeIMivzTxjGWVwA9oOvvseWJ 8 | HzfbFd7OnAT1U+q1xqQ17ECtmeNRj2wPmQ5GE4qMefftmWx6o0w+W85WTwDk+bVM 9 | UBZU7rF5aBUkmtAeY5PwoPbj7uJfZyQEezdklEBOfh65Xet7EII8c5/cqw5ZPQ+A 10 | 0SXK4qZ9Y+gw9y7vMoLBgVuViiZcqOjBvldpVRXGRdX7F9Rth5NnwRNgOXWRGOhx 11 | kPwU36LQ6s8M7uRlOmx3u/iC+YmshGaLQvXIu3DEoAfFkqQAFgWTukBxBcgsz/bd 12 | 0beMvRG5dgsOU7HD8ApeCwwD5/bhA53i7A71wW4jP7KOW+fGhNQNIArnpvQR6mT2 13 | Q+4Eafj9AEZnh0fBFeBGqbXWqc/IJo3c1OjnFfxUYal3sgONezmOcMs8IHbF8egC 14 | aU05fOD65iMdvUlHREeVhQiZqEAOY6B7gG66INDXq8cNIQwYQOw6ocPeCJXXkW49 15 | JN/y0pYVZFY19X/XS9Hp2/+Df/8ChwoxWH3KEIPUKw12EJxjYHBSZ/rbKpE7PYPc 16 | dcuNGhf++mDIGjW2dRagPHF0OVOvOhM3V6CcIh69SyrDb2SiTgHupeF35oL384ut 17 | vBvQDx8eLNpphPDVkImR1/woRD6ZWjgQFycvQuVAJbB01R/u3H01H88Yt0AaLJcl 18 | PZMfytOk3/+hNJiYZxs2UozzRMAGVSJRLH5J9Sv3kDO7VFptG4n3f0mcBFrIB5KJ 19 | O3Se+GD9O0BRO3F2Q82ZEj5c0ikhF/DzJFn72KhzDH3MpgBDlWn3M5mO4qg35swC 20 | jPe7PLCDBAcwbLxetVArnKihSU+XwUVwhsl5y9nyjkY8yTRNqR4LynkG8w5BoTPZ 21 | w18q7ZXXzklma/6Qdpg+WNaIhVZBNAGdA8TaY6gv5fCFXc29DDkjSDG4TR8EbCNN 22 | MErlqBbN7QEOK/P5AuiSMfeifAowCOsNE3UoK99GTbyBlD4j97K0WNlcRKbfrzfB 23 | iGSSO+wq4ncqqnU/+TBgK3CaDkYGYT31SmH+1YH/pKqJKQWIrnUHhb8xmEZYInUY 24 | e5NdIq1h0KJqjDBsdfKNFIuKTvVPJV4Z50oJyi1u1RS0bFWEjEhkFcYWotIjS9T/ 25 | GEFYo7fPQgJd6SOLWhWlbHIkzHYw1zUpg4Y7wiN9ELGgb4oqbQNmgppPnYTnDolA 26 | JZc4ePRA7NVDfbpj90iGUYLlbaJT0iZfUHlxpMYyi8CU8ml7gePtxxKbSZutnNeC 27 | dBj7+//rhAThnin4rZo/fBSam2yHcqS6lrjiyep8bTLe39FIc94gVtvP61Xb0SAx 28 | DGPwtxHB4Sm2C/mxYpuuuSqCsXojbjfw3QLNdfepAyHo/Q7TAV5/RNd09m+qBvUy 29 | D4j9Zdhi5iudTnHHdgM9niD3V7ETakY450ekRLurGg+CD2x7tVT09riTvz5DaYcL 30 | x36ZYV4zrrCIRHZHIi2/LhbWtItuGbWtDhvRpuCddD9vqwqwj9dzurp1xo5V2NE2 31 | ilWKZO/TLF4VSIYnvNo6uRkOYMZ0TI5J0+2/giP6WC0T/borL8PRWX/laTEkUxpO 32 | +yerOS3ZJCqLtI8+zVNz1GBu5iTeu1TXPPyQBiID1VNI6ouS4qAiKuudNmBriCPt 33 | A8S9YsEYLtcESclogYz3cbJZclAT9mgiBF01uH1b4bOuEAB1idbQ6VffX7Iy8lfW 34 | 6neXa2ul8K1yirv1AnjIKIHhv2hXzz/zN6DoamAGuQGgrRSdgii3qHKWmtJCOyjG 35 | YQPR6aCzMiHoSxrv0iFZUsiJRD2/3V6tB7EMkDKF1Ay6CUjZzlIYmbrpA5jsg8WL 36 | TPWH/tInZPIfw1W+1z3zNsTb6fQbJYhH1pe8aPMI3q8g+RUd5htolyNrrFhevw7+ 37 | 5Hs8aexC0FRVjjfbC/gkOVJuBqCMUE8AzvO/Uv1sofdlGCqF7RVRs3P4ruo+EbgT 38 | i1bfu63GaLu0hQfJ2JIHDa7JzcYa7RwrRZVv4m6AlcGMhYQ2u2TtkSroR6hsXBtb 39 | MowzAvn6tlqXz7jf7hDmPa6uQoLgcIgBS/bdwxAUqyMpAddnCZBCbDOGNRngDKBk 40 | OCPGKZ7RCGi1J4cAp9yr+OgIPbMFIhczIPhW2LwYKPfj+gaSh8mNgZ87V1JE8iIg 41 | aLhBfF2mYUVMgg2za2/QBkXLPanhDB2Dqu47g9lCDHRbdNF215lN4HKf/qU0r2DN 42 | vnhrN/ZFdMmDWtgBJG6sNduQ0t3sSKrVuk0y4hT/qJCoyrLEOMzV55ciFusF0tPB 43 | RJly8wnb7G8Q+0JawSGtQm+hG4o5zjZLgEtvP8fA2Yf4oV8d3gvlHVJY9YCao835 44 | 6oNx5lXu9v3wCbMqjJY0S0sdKirUDOGvuxpATQFlTSJJMU2/GXjdCbtWnekQ5pFc 45 | oXfEgwQcudxbbMd9AywEvfPfWH3ERhUhuhdwLC9kr1SKgknpBlE/ktFXzgAyFEsu 46 | k2JsdOiWUUTGRshrVqEYT4C09/NAVmblaojqbubJmeMBerKmoS/X5ytL65g90Srq 47 | hiaIEUSjQQC3b+Y9hxBByLDqZA7NRQs4P30LLLXqtWz105/DOFWtW8u5T9qNxaC8 48 | zY9XqehCE0lJZewSV/KD7X7YRxZNuXwouFIwQCoc90HzPnDfDakYDsdnYNxjoY3P 49 | QFi0une8sXHzxgAEk1kJsvVJCqrr+uDkPZfdIQUTSJ1ZpWnXOVNopejm86HHtaJv 50 | /r6FynapnOsHxGjPtr/6y2pBXQdk5Kuwb9a4NUZxKEcyvFVFBxGs3pLVrC0kDbk2 51 | 5WL61XpFPaBhJZY84s5McAj5b8Cqh1g39Fj5EeIiObKv+CPXmSuhc0rrNns4szoR 52 | 5iEyWfa00qVaP0kc2wIf6U67shS/lyBn3eLelZ+mWn9+F4G+5IXeo7GKWngIM6wp 53 | Ll96TZ/NDGEIKs0NuENZruau/FaCi97rAbHCtx8+YzLpbIFtnk5MvAYwecdtVLkW 54 | -----END RSA PRIVATE KEY----- 55 | --------------------------------------------------------------------------------