├── .editorconfig ├── .eslintrc ├── .gitattributes ├── .github ├── dependabot.yml └── workflows │ └── ci.yml ├── .gitignore ├── .gitmodules ├── .npmignore ├── .nycrc.js ├── CHANGELOG.yaml ├── LICENSE.md ├── README.md ├── bin └── transform-collection.js ├── docs └── request-body.md ├── examples ├── v1.0.0 │ ├── binary-upload.json │ ├── box.json │ ├── disabledheaders.json │ ├── echo.json │ ├── emptydata.json │ ├── emptydatamode.json │ ├── github.json │ ├── hackernews.json │ ├── helpers.json │ ├── httpbin.json │ ├── malformed.json │ ├── multi-level-folders-2.json │ ├── multi-level-folders.json │ ├── nestedEntities.json │ ├── no-body.json │ ├── proper-url-parsing.json │ ├── rawjsonbody.json │ ├── simplest.json │ ├── twitter.json │ └── urlencoded-post-data.json ├── v2.0.0 │ ├── binary-upload.json │ ├── box.json │ ├── echo.json │ ├── github.json │ ├── hackernews.json │ ├── helpers.json │ ├── httpbin.json │ ├── multi-level-folders.json │ ├── nestedEntities.json │ ├── no-body.json │ ├── proper-url-parsing.json │ ├── rawjsonbody.json │ ├── twitter.json │ └── urlencoded-post-data.json └── v2.1.0 │ ├── binary-upload.json │ ├── box.json │ ├── echo.json │ ├── github.json │ ├── hackernews.json │ ├── helpers.json │ ├── httpbin.json │ ├── nestedEntities.json │ ├── proper-description-parsing.json │ ├── proper-url-parsing.json │ ├── rawjsonbody.json │ ├── twitter.json │ └── urlencoded-post-data.json ├── index.js ├── lib ├── common │ ├── v1.js │ └── v2.js ├── constants.js ├── converters │ ├── index.js │ ├── v1.0.0 │ │ ├── converter-v1-to-v2.js │ │ └── converter-v1-to-v21.js │ ├── v2.0.0 │ │ └── converter-v2-to-v1.js │ └── v2.1.0 │ │ └── converter-v21-to-v1.js ├── index.js ├── normalizers │ ├── index.js │ └── v1.js ├── url.js └── util.js ├── npm ├── release.js ├── test-browser.js ├── test-lint.js ├── test-schema.js ├── test-system.js └── test-unit.js ├── package-lock.json ├── package.json └── test ├── .eslintrc ├── karma.conf.js ├── schema ├── example-validity.test.js ├── url-parse.test.js ├── v1.0.0 │ ├── converter-v1-to-v2.test.js │ └── converter-v1-to-v21.test.js ├── v2.0.0 │ └── converter-v2-to-v1.test.js └── v2.1.0 │ └── converter-v21-to-v1.test.js ├── system ├── npm-publish.test.js └── repository.test.js └── unit ├── converter.test.js ├── export-regression.test.js ├── fixtures ├── graphql-payload-in-both-key.json ├── graphql-payload-in-data-key.json ├── multi-level.v2.json ├── multi-level.v21.json ├── nested-entities.js ├── normalizer │ └── v1 │ │ ├── sample-collection.js │ │ ├── single-request.js │ │ └── single-response.js ├── request-body-file.js ├── sample-auth.js ├── sample-collection.js ├── sample-description.js ├── single-request.js └── single-response.js ├── lib.test.js ├── url.test.js ├── util.test.js ├── v1.0.0 ├── converter-v1-to-v2.test.js ├── converter-v1-to-v21.test.js └── normalize-v1.test.js ├── v2.0.0 └── converter-v2-to-v1.test.js └── v2.1.0 └── converter-v21-to-v1.test.js /.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 | -------------------------------------------------------------------------------- /.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 | -------------------------------------------------------------------------------- /.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 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | paths-ignore: 6 | - 'docs/**' 7 | - '*.md' 8 | pull_request: 9 | branches: [$default-branch] 10 | schedule: 11 | - cron: '0 12 * * 0' 12 | 13 | concurrency: 14 | group: ${{ github.workflow }}-${{ github.ref }} 15 | cancel-in-progress: true 16 | 17 | jobs: 18 | lint: 19 | name: Lint 20 | runs-on: ubuntu-latest 21 | 22 | steps: 23 | - name: Checkout repository 24 | uses: actions/checkout@v3 25 | 26 | - name: Use Node.js 16.x 27 | uses: actions/setup-node@v3 28 | with: 29 | node-version: 16.x 30 | cache: 'npm' 31 | 32 | - name: Install 33 | run: npm ci 34 | 35 | - name: Run lint tests 36 | run: npm run test-lint 37 | 38 | browser-tests: 39 | name: Browser Tests 40 | runs-on: ubuntu-latest 41 | 42 | steps: 43 | - name: Checkout repository 44 | uses: actions/checkout@v3 45 | 46 | - name: Use Node.js 16.x 47 | uses: actions/setup-node@v3 48 | with: 49 | node-version: 16.x 50 | cache: 'npm' 51 | 52 | - name: Install 53 | run: npm ci 54 | 55 | - name: Run browser tests 56 | run: npm run test-browser 57 | 58 | tests: 59 | name: Tests 60 | runs-on: ${{ matrix.os }} 61 | strategy: 62 | fail-fast: false 63 | matrix: 64 | node-version: [10, 12] 65 | os: [ubuntu-latest, windows-latest] 66 | 67 | steps: 68 | - name: Checkout repository 69 | uses: actions/checkout@v3 70 | 71 | - name: Use Node.js ${{ matrix.node-version }} 72 | uses: actions/setup-node@v3 73 | with: 74 | node-version: ${{ matrix.node-version }} 75 | cache: 'npm' 76 | 77 | - name: Install 78 | run: npm ci 79 | 80 | - name: Run system tests 81 | run: npm run test-system 82 | 83 | - name: Run unit tests 84 | run: npm run test-unit 85 | 86 | - name: Run schema tests 87 | run: npm run test-schema 88 | -------------------------------------------------------------------------------- /.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 | 33 | # - Prevent diff backups from SourceTree from showing as commit. 34 | *.BACKUP.* 35 | *.BASE.* 36 | *.LOCAL.* 37 | *.REMOTE.* 38 | *.orig 39 | 40 | # - Prevent unit test coverage reports from being committed to the repository 41 | .coverage 42 | .nyc_output 43 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/postmanlabs/postman-collection-transformer/322c4c5df9c1a5895a2e41a77958d35a9163487b/.gitmodules -------------------------------------------------------------------------------- /.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 | 33 | # - Prevent diff backups from SourceTree from showing as commit. 34 | *.BACKUP.* 35 | *.BASE.* 36 | *.LOCAL.* 37 | *.REMOTE.* 38 | *.orig 39 | 40 | # - Prevent code coverage reports from being added 41 | .coverage 42 | .nyc_output 43 | 44 | # - Prevent config and test files from being added 45 | .git* 46 | npm/ 47 | docs/ 48 | test/ 49 | examples/ 50 | .eslintrc 51 | .nycrc.js 52 | .editorconfig 53 | -------------------------------------------------------------------------------- /.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 'unit': 10 | return { 11 | statements: 95, 12 | branches: 94, 13 | functions: 95, 14 | lines: 95 15 | }; 16 | default: 17 | return {} 18 | } 19 | } 20 | 21 | module.exports = { 22 | // @todo cover `all` files by writing unit test for bundled lib/sandbox files 23 | // all: true, 24 | 'check-coverage': true, 25 | 'report-dir': '.coverage', 26 | 'temp-dir': '.nyc_output', 27 | include: ['lib/**/*.js'], 28 | reporter: ['lcov', 'json', 'text', 'text-summary'], 29 | ...configOverrides(TEST_TYPE), 30 | }; 31 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Postman Collection Transformer [![Build Status](https://github.com/postmanlabs/postman-collection-transformer/actions/workflows/ci.yml/badge.svg?branch=develop)](https://github.com/postmanlabs/postman-collection-transformer/actions/workflows/ci.yml) 2 | 3 | Perform rapid conversion of JSON structure between Postman Collection Format v1 and v2. 4 | 5 | The formats are documented at https://schema.postman.com 6 | 7 | ## Installation 8 | 9 | For CLI usage: 10 | 11 | $ npm install -g postman-collection-transformer 12 | 13 | As a library: 14 | 15 | $ npm install --save postman-collection-transformer 16 | 17 | ## Usage 18 | 19 | #### Converting Entire Collections 20 | 21 | The transformer provides a Command line API to convert collections. 22 | 23 | Example: 24 | 25 | $ postman-collection-transformer convert \ 26 | --input ./v1-collection.json \ 27 | --input-version 2.0.0 \ 28 | --output ./v2-collection.json \ 29 | --output-version 1.0.0 \ 30 | --pretty \ 31 | --overwrite 32 | 33 | All options: 34 | 35 | $ postman-collection-transformer convert -h 36 | 37 | Usage: convert [options] 38 | 39 | Convert Postman Collection from one format to another 40 | 41 | Options: 42 | 43 | -h, --help output usage information 44 | -i, --input path to the input postman collection file 45 | -j, --input-version [version] the version of the input collection format standard (v1 or v2) 46 | -o, --output target file path where the converted collection will be written 47 | -p, --output-version [version] required version to which the collection is needed to be converted to 48 | -P, --pretty Pretty print the output 49 | --retain-ids Retain the request and folder IDs during conversion (collection ID is always retained) 50 | -w, --overwrite Overwrite the output file if it exists 51 | 52 | If you'd rather use the transformer as a library: 53 | ```javascript 54 | var transformer = require('postman-collection-transformer'), 55 | collection = require('./path/to/collection.json'), 56 | inspect = require('util').inspect, 57 | 58 | options = { 59 | inputVersion: '1.0.0', 60 | outputVersion: '2.0.0', 61 | retainIds: true // the transformer strips request-ids etc by default. 62 | }; 63 | 64 | transformer.convert(collection, options, function (error, result) { 65 | if (error) { 66 | return console.error(error); 67 | } 68 | 69 | // result <== the converted collection as a raw Javascript object 70 | console.log(inspect(result, {colors: true, depth: 10000})); 71 | }); 72 | ``` 73 | 74 | #### Converting Individual Requests 75 | 76 | The transformer also allows you to convert individual requests (only supported when used as a library): 77 | 78 | ###### Example 79 | ```javascript 80 | 81 | var transformer = require('postman-collection-transformer'), 82 | 83 | objectToConvert = { /* A valid collection v1 Request or a collection v2 Item */ }, 84 | 85 | options = { 86 | inputVersion: '1.0.0', 87 | outputVersion: '2.0.0', 88 | retainIds: true // the transformer strips request-ids etc by default. 89 | }; 90 | 91 | transformer.convertSingle(objectToConvert, options, function (err, converted) { 92 | console.log(converted); 93 | }); 94 | ``` 95 | 96 | #### Converting Individual Responses 97 | 98 | You can convert individual responses too if needed: 99 | 100 | ###### Example 101 | ```javascript 102 | 103 | var transformer = require('postman-collection-transformer'), 104 | 105 | objectToConvert = { /* A v1 Response or a v2 Response */ }, 106 | 107 | options = { 108 | inputVersion: '1.0.0', 109 | outputVersion: '2.0.0', 110 | retainIds: true // the transformer strips request-ids etc by default. 111 | }; 112 | 113 | transformer.convertResponse(objectToConvert, options, function (err, converted) { 114 | console.log(converted); 115 | }); 116 | ``` 117 | 118 | #### Normalizing v1 collections 119 | 120 | The transformer also provides a Command line API to normalize collections for full forward compatibility. 121 | 122 | Example: 123 | 124 | $ postman-collection-transformer normalize \ 125 | --input ./v1-collection.json \ 126 | --normalize-version 1.0.0 \ 127 | --output ./v1-norm-collection.json \ 128 | --pretty \ 129 | --overwrite 130 | 131 | All options: 132 | 133 | $ postman-collection-transformer normalize -h 134 | 135 | Usage: normalize [options] 136 | 137 | Normalizes a postman collection according to the provided version 138 | 139 | 140 | Options: 141 | 142 | -i, --input Path to the collection JSON file to be normalized 143 | -n, --normalize-version The version to normalizers the provided collection on 144 | -o, --output Path to the target file, where the normalized collection will be written 145 | -P, --pretty Pretty print the output 146 | --retain-ids Retain the request and folder IDs during conversion (collection ID is always retained) 147 | -w, --overwrite Overwrite the output file if it exists 148 | -h, --help Output usage information 149 | 150 | 151 | If you'd rather use the transformer as a library: 152 | ```javascript 153 | var transformer = require('postman-collection-transformer'), 154 | collection = require('./path/to/collection.json'), 155 | inspect = require('util').inspect, 156 | 157 | options = { 158 | normalizeVersion: '1.0.0', 159 | mutate: false, // performs in-place normalization, false by default. 160 | noDefaults: false, // when set to true, sensible defaults for missing properties are skipped. Default: false 161 | prioritizeV2: false, // when set to true, v2 attributes are used as the source of truth for normalization. 162 | retainEmptyValues: false, // when set to true, empty values are set to '', not removed. False by default. 163 | retainIds: true // the transformer strips request-ids etc by default. 164 | }; 165 | 166 | transformer.normalize(collection, options, function (error, result) { 167 | if (error) { 168 | return console.error(error); 169 | } 170 | 171 | // result <== the converted collection as a raw Javascript object 172 | console.log(inspect(result, {colors: true, depth: 10000})); 173 | }); 174 | ``` 175 | -------------------------------------------------------------------------------- /bin/transform-collection.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | const fs = require('fs'), 3 | 4 | { Command } = require('commander'), 5 | stripJSONComments = require('strip-json-comments'), 6 | 7 | transformer = require('..'), 8 | program = new Command(), 9 | 10 | FSWF_FLAG_W = { flag: 'w' }, 11 | FSWF_FLAG_WX = { flag: 'wx' }, 12 | 13 | /** 14 | * Loads a JSON in a safe and compatible way from a file 15 | * 16 | * @param {String} path - The file path to read JSON content from. 17 | */ 18 | loadJSON = function (path) { 19 | const data = fs.readFileSync(path); // eslint-disable-line security/detect-non-literal-fs-filename 20 | 21 | return JSON.parse(stripJSONComments(data.toString())); 22 | }, 23 | 24 | /** 25 | * Writes a JSON blob to the given path. 26 | * ``options.path`` must contain the path to the output file. 27 | * If ``options.pretty`` is true, output will be pretty printed. (Default false) 28 | * If ``options.overwrite`` is false, output file will be overwritten (Default true) 29 | * 30 | * @param {Object} data - The JSON data to be written. 31 | * @param {Object} options - The options for JSON data writing. 32 | * @param {Boolean} [options.pretty=false] - When set to true, indents JSON data by 4 spaces. 33 | * @param {String} options.output - The file to write data to. 34 | * @param {Boolean} [options.overwrite=false] - When set to true, allows overwriting files that exist. 35 | * @param {Function} callback - A function to be invoked after writing is complete , 36 | */ 37 | writeJSON = function (data, options, callback) { 38 | let json; 39 | 40 | try { 41 | json = JSON.stringify(data, null, options.pretty ? 4 : 0); 42 | } 43 | catch (e) { 44 | return callback(e); 45 | } 46 | 47 | // eslint-disable-next-line security/detect-non-literal-fs-filename 48 | return fs.writeFile(options.output, json, options.overwrite ? FSWF_FLAG_W : FSWF_FLAG_WX, callback); 49 | }; 50 | 51 | program 52 | .usage('[command] [options]') 53 | .version(require('../package.json').version); 54 | 55 | // Describe the options and usage instruction for the `convert` command 56 | program 57 | .command('convert') 58 | .description('Convert Postman Collection from one format to another') 59 | .option('-e, --env ', 'optional path to the associated postman environment file to be used') 60 | .option('-i, --input ', 'path to the input postman collection file') 61 | .option('-j, --input-version [version]', 'the version of the input collection format standard (v1 or v2)') 62 | .option('-o, --output ', 'target file path where the converted collection will be written') 63 | .option('-p, --output-version [version]', 'required version to which the collection is needed to be converted to') 64 | .option('-P, --pretty', 'Pretty print the output') 65 | .option('--retain-ids', 'Retain the request and folder IDs during conversion (collection ID is always retained)') 66 | .option('-w, --overwrite', 'Overwrite the output file if it exists') 67 | .action((options) => { 68 | let input; 69 | 70 | if (!options.output) { 71 | return console.error('Output file must be specified!'); 72 | } 73 | if (!options.input) { 74 | return console.error('Input file must be specified!'); 75 | } 76 | 77 | try { 78 | input = loadJSON(options.input); 79 | } 80 | catch (e) { 81 | return console.error('Unable to load the input file!', e); 82 | } 83 | 84 | return transformer.convert(input, options, (err, result) => { 85 | if (err) { 86 | return console.error('Unable to convert the input:', err); 87 | } 88 | 89 | return writeJSON(result, options, (error) => { 90 | if (error) { 91 | console.error('Could not create output file %s', options.output, error); 92 | } 93 | }); 94 | }); 95 | }); 96 | 97 | program 98 | .command('normalize') 99 | .description('Normalizes a postman collection according to the provided version') 100 | .option('-i, --input ', 'Path to the collection JSON file to be normalized') 101 | .option('-n, --normalize-version ', 'The version to normalize the provided collection on') 102 | .option('-o, --output ', 'Path to the target file, where the normalized collection will be written') 103 | .option('-P, --pretty', 'Pretty print the output') 104 | .option('--retain-ids', 'Retain the request and folder IDs during conversion (collection ID is always retained)') 105 | .option('-w, --overwrite', 'Overwrite the output file if it exists') 106 | .action((options) => { 107 | if (!options.input) { return console.error('Input file must be specified!'); } 108 | if (!options.output) { return console.error('Output file must be specified!'); } 109 | 110 | let input; 111 | 112 | try { input = loadJSON(options.input); } 113 | catch (e) { return console.error('Unable to load the input file!', e); } 114 | 115 | return transformer.normalize(input, options, (err, result) => { 116 | if (err) { return console.error('Unable to convert the input: ', err); } 117 | 118 | return writeJSON(result, options, (error) => { 119 | error && console.error('Could not create output file %s', options.output, error); 120 | }); 121 | }); 122 | }); 123 | 124 | // Describe the options and usage instructions for the `validate` command 125 | program 126 | .command('validate') 127 | .description('Verify whether a postman collection adheres to version specifications') 128 | .option('-i, --input ', 'path to the input postman collection file') 129 | .option('-s, --schema [version]', 'the version of the input collection format standard') 130 | .action((options) => { 131 | console.warn('yet to be implemented', options); 132 | // @todo implement with as little and concise code as possible with least external dependencies 133 | }); 134 | 135 | // Warn on invalid command and then exits. 136 | program.on('command:*', (command) => { 137 | console.error(`error: invalid command \`${command}\`\n`); 138 | program.help(); 139 | }); 140 | 141 | program.parse(process.argv); 142 | -------------------------------------------------------------------------------- /docs/request-body.md: -------------------------------------------------------------------------------- 1 | # Transforming Request Body (v1 -> v2.x) 2 | 3 | ### Request Body Mode 4 | 5 | > v1 property: requests.dataMode 6 | v2 property: request.body.mode 7 | 8 | 9 | **`mode` is set based on the following conversion table:** 10 | 11 | | v1 | v2 | 12 | |------------|------------| 13 | | binary | file | 14 | | graphql | graphql | 15 | | params | formdata | 16 | | raw | raw | 17 | | urlencoded | urlencoded | 18 | 19 | **Note** 20 | 1. If `dataMode` is explicitly set to null then `body` will be set to `null` 21 | 2. If `dataMode` is not set or invalid then `mode` is inferred from `rawModeData` or `data` or `graphqlModeData` 22 | 3. If multiple types of body are set e.g, both `rawModeData` and `graphqlModeData` are set. Then mode selection priority will be: `raw → formdata → graphql` (pre-graphql behavior). 23 | 24 | - `formdata`: if `isRawModeData` is false AND `data` is an array 25 | - `graphql`: if `isRawModeData` is false AND `graphqlModeData` is non empty 26 | - `raw`: otherwise 27 | 28 | ``` 29 | isRawModeData: 30 | - `rawModeData` is not null `AND` 31 | - `rawModeData` is of type string `OR` 32 | - `rawModeData` is an array of length 1 and the element is of type string 33 | ``` 34 | 35 | --- 36 | 37 | ### Request Body Data 38 | 39 | > v1 property: requests.data or requests.rawModeData 40 | v2 property: request.body[request.body.mode] 41 | 42 | **Mode: raw** 43 | ```javascript 44 | if (isRawModeData) { 45 | body.raw = Array.isArray(v1.rawModeData) ? v1.rawModeData[0] : v1.rawModeData; 46 | } 47 | else if (typeof v1.data === 'string') { 48 | body.raw = v1.data; 49 | } 50 | ``` 51 | 52 | **Mode: file** 53 | ```javascript 54 | body.file = { src: v1.rawModeData } 55 | ``` 56 | 57 | **Mode: graphql** 58 | ```javascript 59 | body.graphql = v1.graphqlModeData; 60 | ``` 61 | 62 | **Mode: formdata** 63 | ```javascript 64 | body.formdata = parseFormData (v1.data || v1.rawModeData, retainEmpty); 65 | ``` 66 | 67 | **Mode: urlencoded** 68 | ```javascript 69 | body.urlencoded = parseFormData (v1.data || v1.rawModeData, retainEmpty); 70 | ``` 71 | 72 | **parseFormData**: [source](https://github.com/postmanlabs/postman-collection-transformer/blob/v3.0.0/lib/converters/v1.0.0/converter-v1-to-v2.js#L30) -------------------------------------------------------------------------------- /examples/v1.0.0/binary-upload.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "70fa9b38-91c0-7e67-0ead-b31622bdc152", 3 | "name": "asdasdasdasdasdasd", 4 | "description": "Description", 5 | "order": [ 6 | "cc0e1894-bad7-aeeb-e91c-e74635371614" 7 | ], 8 | "folders": [], 9 | "hasRequests": true, 10 | "requests": [ 11 | { 12 | "folder": null, 13 | "id": "cc0e1894-bad7-aeeb-e91c-e74635371614", 14 | "name": "http://httpbin.org/post", 15 | "dataMode": "binary", 16 | "data": [], 17 | "rawModeData": "sample.txt", 18 | "descriptionFormat": "html", 19 | "description": "Description", 20 | "headers": "", 21 | "method": "POST", 22 | "pathVariables": {}, 23 | "url": "http://echo.postman.com/post", 24 | "preRequestScript": null, 25 | "tests": "console.log(responseBody)", 26 | "currentHelper": "normal", 27 | "helperAttributes": "{}", 28 | "responses": [], 29 | "collectionId": "70fa9b38-91c0-7e67-0ead-b31622bdc152" 30 | } 31 | ] 32 | } 33 | -------------------------------------------------------------------------------- /examples/v1.0.0/disabledheaders.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "d3ac3ec4-8f23-2f3a-5215-aa33d781ca21", 3 | "name": "disabledheaders", 4 | "description": "Description", 5 | "order": [ 6 | "6a795cee-c9a7-9cbc-32cd-9125337d6d7b" 7 | ], 8 | "folders": [], 9 | "requests": [ 10 | { 11 | "id": "6a795cee-c9a7-9cbc-32cd-9125337d6d7b", 12 | "headers": "A:B\n//C:D", 13 | "url": "echo.postman.com/post", 14 | "preRequestScript": null, 15 | "pathVariables": {}, 16 | "method": "POST", 17 | "data": "something", 18 | "dataMode": "raw", 19 | "tests": "tests[\"Body matches string\"] = responseBody.has(\"OMG\");\ntests[\"Status code is 200\"] = responseCode.code === 200;", 20 | "currentHelper": "normal", 21 | "helperAttributes": {}, 22 | "name": "echo.postman.com/post", 23 | "description": "OMG I AM description", 24 | "responses": [] 25 | } 26 | ] 27 | } 28 | -------------------------------------------------------------------------------- /examples/v1.0.0/emptydata.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "5b99a43f-b73a-9b61-deb3-61bc639b9a17", 3 | "name": "hello", 4 | "description": "Description", 5 | "order": [ 6 | "e800d19c-0660-e2d6-ebc8-cfda8a56cddd" 7 | ], 8 | "folders": [], 9 | "requests": [ 10 | { 11 | "owner": "4", 12 | "lastUpdatedBy": "4", 13 | "lastRevision": 6188817, 14 | "folder": null, 15 | "id": "e800d19c-0660-e2d6-ebc8-cfda8a56cddd", 16 | "name": "httpbin.org/get", 17 | "dataMode": null, 18 | "data": null, 19 | "rawModeData": null, 20 | "descriptionFormat": "html", 21 | "description": "Description", 22 | "headers": "helo: \n", 23 | "method": "GET", 24 | "pathVariables": {}, 25 | "url": "httpbin.org/get", 26 | "preRequestScript": null, 27 | "tests": null, 28 | "currentHelper": "normal", 29 | "helperAttributes": {}, 30 | "createdAt": "2016-11-30T13:40:09.000Z", 31 | "updatedAt": "2016-11-30T18:31:36.000Z", 32 | "responses": [], 33 | "collectionId": "5b99a43f-b73a-9b61-deb3-61bc639b9a17" 34 | } 35 | ], 36 | "timestamp": 0, 37 | "synced": true, 38 | "syncedFilename": "", 39 | "remote_id": "0", 40 | "remoteLink": null, 41 | "remoteLinkUpdatedAt": null, 42 | "public": false, 43 | "owner": "4", 44 | "subscribed": false, 45 | "createdAt": "2016-11-30T13:39:56.000Z", 46 | "updatedAt": "2016-11-30T18:31:54.000Z", 47 | "write": true, 48 | "isDeleted": false, 49 | "published": false, 50 | "favorite": false, 51 | "permissions": {}, 52 | "syncedPermissions": {}, 53 | "lastUpdatedBy": "4", 54 | "lastRevision": 6188821, 55 | "team": null, 56 | "shared": false, 57 | "sharedWithTeam": false, 58 | "hasRequests": true 59 | } -------------------------------------------------------------------------------- /examples/v1.0.0/emptydatamode.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "5b99a43f-b73a-9b61-deb3-61bc639b9a17", 3 | "name": "hello", 4 | "description": "Description", 5 | "order": [ 6 | "e800d19c-0660-e2d6-ebc8-cfda8a56cddd" 7 | ], 8 | "folders": [], 9 | "requests": [ 10 | { 11 | "owner": "4", 12 | "lastUpdatedBy": "4", 13 | "lastRevision": 6188817, 14 | "folder": null, 15 | "id": "e800d19c-0660-e2d6-ebc8-cfda8a56cddd", 16 | "name": "httpbin.org/get", 17 | "dataMode": null, 18 | "data": [], 19 | "rawModeData": "{\n \"asd\": \"tyyy\"\n}", 20 | "descriptionFormat": "html", 21 | "description": "Description", 22 | "headers": "helo: \n", 23 | "method": "GET", 24 | "pathVariables": {}, 25 | "url": "httpbin.org/get", 26 | "preRequestScript": null, 27 | "tests": null, 28 | "currentHelper": "normal", 29 | "helperAttributes": {}, 30 | "createdAt": "2016-11-30T13:40:09.000Z", 31 | "updatedAt": "2016-11-30T18:31:36.000Z", 32 | "responses": [], 33 | "collectionId": "5b99a43f-b73a-9b61-deb3-61bc639b9a17" 34 | } 35 | ], 36 | "timestamp": 0, 37 | "synced": true, 38 | "syncedFilename": "", 39 | "remote_id": "0", 40 | "remoteLink": null, 41 | "remoteLinkUpdatedAt": null, 42 | "public": false, 43 | "owner": "4", 44 | "subscribed": false, 45 | "createdAt": "2016-11-30T13:39:56.000Z", 46 | "updatedAt": "2016-11-30T18:31:54.000Z", 47 | "write": true, 48 | "isDeleted": false, 49 | "published": false, 50 | "favorite": false, 51 | "permissions": {}, 52 | "syncedPermissions": {}, 53 | "lastUpdatedBy": "4", 54 | "lastRevision": 6188821, 55 | "team": null, 56 | "shared": false, 57 | "sharedWithTeam": false, 58 | "hasRequests": true 59 | } -------------------------------------------------------------------------------- /examples/v1.0.0/helpers.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "34783f86-4a67-d3bd-ba5b-148495fa2f72", 3 | "name": "c1", 4 | "description": "Description", 5 | "order": [ 6 | "51e6ecc7-ff3c-9bc0-8aea-b417c4723f68", 7 | "51e6ecc7-ff3c-9bc0-8aea-b417c4723f69", 8 | "35c535b1-7e0f-fba7-ce6c-71162ce45dec", 9 | "16f05b20-6d85-7bcd-e236-d2fa85cc811f" 10 | ], 11 | "folders": [], 12 | "timestamp": 1415470379814, 13 | "synced": false, 14 | "requests": [ 15 | { 16 | "id": "16f05b20-6d85-7bcd-e236-d2fa85cc811f", 17 | "headers": "", 18 | "url": "httpbin.org/get", 19 | "preRequestScript": "", 20 | "pathVariables": {}, 21 | "method": "GET", 22 | "data": [], 23 | "dataMode": "params", 24 | "version": 2, 25 | "tests": "var data = JSON.parse(responseBody);\ntests[\"DigestAuth\"] = data.headers.Authorization.has(\"Digest\");tests[\"Correct response signature generated\"]=data.headers.Authorization.has(\"8ef925a22b7fa71b5f63d2f210d0f669\");", 26 | "currentHelper": "digestAuth", 27 | "helperAttributes": { 28 | "id": "digest", 29 | "time": 1415541054386, 30 | "algorithm": "MD5", 31 | "username": "abhijit", 32 | "realm": "me@kennethreitz.com", 33 | "password": "kane", 34 | "nonce": "b595d63333715eaf0737e4255c288dc1", 35 | "nonceCount": "000001", 36 | "clientNonce": "abcfd", 37 | "opaque": "03a268317fb5ee47794496820f0bb4fd", 38 | "qop": "auth" 39 | }, 40 | "time": 1415541064613, 41 | "name": "DigestAuth", 42 | "description": "Description", 43 | "collectionId": "34783f86-4a67-d3bd-ba5b-148495fa2f72", 44 | "responses": [], 45 | "synced": false 46 | }, 47 | { 48 | "id": "35c535b1-7e0f-fba7-ce6c-71162ce45dec", 49 | "headers": "", 50 | "url": "httpbin.org/get", 51 | "preRequestScript": "", 52 | "pathVariables": {}, 53 | "method": "GET", 54 | "data": [], 55 | "dataMode": "params", 56 | "version": 2, 57 | "tests": "var data = JSON.parse(responseBody);\ntests[\"Correct Basic Signature generated\"] = data.headers.Authorization.has(\"Basic YWJoaWppdDprYW5l\");", 58 | "currentHelper": "basicAuth", 59 | "helperAttributes": { 60 | "username": "abhijit", 61 | "password": "kane", 62 | "id": "basic", 63 | "timestamp": 1415540254342 64 | }, 65 | "time": 1415541373790, 66 | "name": "basicAuth", 67 | "description": "Description", 68 | "collectionId": "34783f86-4a67-d3bd-ba5b-148495fa2f72", 69 | "responses": [], 70 | "synced": false 71 | }, 72 | { 73 | "id": "951fc3e8-c6b6-5c19-9f69-4e7499b3127f", 74 | "url": "http://echo.postman.com/auth/bearer", 75 | "preRequestScript": "", 76 | "pathVariables": {}, 77 | "method": "GET", 78 | "data": [], 79 | "dataMode": "params", 80 | "version": 2, 81 | "tests": "var response = JSON.parse(responseBody); tests['Bearer auth should pass'] = response.status === 'pass';", 82 | "currentHelper": "bearerAuth", 83 | "helperAttributes": { 84 | "id": "bearer", 85 | "token": "wkjehbxoqnunc2k3" 86 | }, 87 | "time": 1448888108375, 88 | "name": "test bearer auth success", 89 | "description": "", 90 | "collectionId": "d497d10e-e280-8c83-709a-a4d4ea12ad14", 91 | "responses": [] 92 | }, 93 | { 94 | "id": "51e6ecc7-ff3c-9bc0-8aea-b417c4723f68", 95 | "headers": "", 96 | "url": "httpbin.org/post", 97 | "preRequestScript": "", 98 | "pathVariables": {}, 99 | "method": "POST", 100 | "data": [], 101 | "dataMode": "params", 102 | "version": 2, 103 | "tests": "var data = JSON.parse(responseBody);\nvar oldNonce = environment.oldNonce;\nvar newNonce = data.form.oauth_nonce;\ntests[\"NewNonce\"]=(oldNonce != newNonce);\npostman.setEnvironmentVariable(\"oldNonce\", newNonce);\ntests[\"HasNonce\"]=data.form.oauth_nonce;console.log('oldNonce: '+oldNonce+', newNonce='+newNonce);console.log('Signature: '+data.form.oauth_signature);", 104 | "currentHelper": "oAuth1", 105 | "helperAttributes": { 106 | "id": "oAuth1", 107 | "time": 1415541588569, 108 | "consumerKey": "ds", 109 | "consumerSecret": "asdgf", 110 | "token": "", 111 | "tokenSecret": "", 112 | "signatureMethod": "HMAC-SHA1", 113 | "timestamp": "1415542860", 114 | "nonce": "yPmTxQ", 115 | "version": "1.0", 116 | "realm": "", 117 | "header": false, 118 | "auto": true, 119 | "includeEmpty": false 120 | }, 121 | "time": 1415542891315, 122 | "name": "OAuth", 123 | "description": "Description", 124 | "collectionId": "34783f86-4a67-d3bd-ba5b-148495fa2f72", 125 | "responses": [], 126 | "synced": false 127 | }, 128 | { 129 | "id": "51e6ecc7-ff3c-9bc0-8aea-b417c4723f69", 130 | "headers": "", 131 | "url": "httpbin.org/post", 132 | "preRequestScript": "", 133 | "pathVariables": {}, 134 | "method": "POST", 135 | "data": [], 136 | "dataMode": "params", 137 | "version": 2, 138 | "tests": "var data = JSON.parse(responseBody);\nvar oldNonce = environment.oldNonce;\nvar newNonce = data.form.oauth_nonce;\ntests[\"NewNonce\"]=(oldNonce != newNonce);\npostman.setEnvironmentVariable(\"oldNonce\", newNonce);\ntests[\"HasNonce\"]=data.form.oauth_nonce;console.log('oldNonce: '+oldNonce+', newNonce='+newNonce);console.log('Signature: '+data.form.oauth_signature);", 139 | "currentHelper": "oAuth2", 140 | "helperAttributes": { 141 | "id": "oAuth2", 142 | "accessToken": "secretToken", 143 | "addTokenTo": "header", 144 | "callBackUrl": "https://foo.com/cb", 145 | "authUrl": "https://foo.com/au", 146 | "accessTokenUrl": "https://foo.com/at", 147 | "clientId": "uniqueClientIdentifier", 148 | "clientSecret": "secretClientValue", 149 | "clientAuth": "body", 150 | "grantType": "implicit", 151 | "scope": "all", 152 | "username": "postman", 153 | "password": "randomSecretString", 154 | "tokenType": "bearer", 155 | "redirectUri": "https://foo.com/rd", 156 | "refreshToken": "refreshToken" 157 | }, 158 | "time": 1415542891315, 159 | "name": "OAuth2", 160 | "description": "", 161 | "collectionId": "34783f86-4a67-d3bd-ba5b-148495fa2f72", 162 | "responses": [], 163 | "synced": false 164 | } 165 | ] 166 | } 167 | -------------------------------------------------------------------------------- /examples/v1.0.0/malformed.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "e5f2e9cf-173b-c60a-7336-ac804a87d762", 3 | "name": "multi-level-folders", 4 | "description": "A simple V1 collection to test out multi level folder flows", 5 | "order": [ 6 | "b7b3ea2c-85e1-43bb-99e4-bb0a7b3bdfe1", 7 | "b7b3ea2c-85e1-43bb-99e4-bb0a7b3bdfe1", 8 | "random-non-existent-uuid" 9 | ], 10 | "folders_order": [ 11 | "5b5b57f0-0b87-42d6-8268-e1550e13e1f0", 12 | "78d5c3d9-e2bf-456a-a0e7-847f7cabcefd", 13 | "78d5c3d9-e2bf-456a-a0e7-847f7cabcefd", 14 | "another-random-non-existent-uuid" 15 | ], 16 | "folders": [ 17 | { 18 | "id": "5b5b57f0-0b87-42d6-8268-e1550e13e1f0", 19 | "name": "F1", 20 | "description": "Description", 21 | "order": [ 22 | "73d22bec-5403-4fc8-bd1b-f5ec237c5d16", 23 | "f78296f9-baf2-446b-8450-fe6b982ba784", 24 | "59b9a846-af89-45ad-85bf-1d5163c64747" 25 | ], 26 | "folders_order": [] 27 | }, 28 | { 29 | "id": "78d5c3d9-e2bf-456a-a0e7-847f7cabcefd", 30 | "name": "F2", 31 | "description": "Description", 32 | "order": [ 33 | "aacf3ebd-6c2b-4452-a6ba-a298f951f334" 34 | ], 35 | "folders_order": [ 36 | "b8b259fc-5e88-4aac-88b3-1adf205f7af2", 37 | "2f003cb9-2fc3-479b-9aa5-9b254c581de9" 38 | ] 39 | }, 40 | { 41 | "id": "b8b259fc-5e88-4aac-88b3-1adf205f7af2", 42 | "name": "F2.F3", 43 | "description": "Description", 44 | "order": [ 45 | "072721f4-c04f-4172-a86b-b07fdfe5b8ee", 46 | "072721f4-c04f-4172-a86b-b07fdfe5b8ee" 47 | ], 48 | "folders_order": [] 49 | }, 50 | { 51 | "id": "2f003cb9-2fc3-479b-9aa5-9b254c581de9", 52 | "name": "F4", 53 | "description": "Description", 54 | "order": [], 55 | "folders_order": ["non-existent-folder-id"] 56 | }, 57 | { 58 | "id": "78d5c3d9-e2bf-456a-a0e7-847f7cabcefd", 59 | "name": "F5", 60 | "description": "Description", 61 | "order": [ 62 | "807727a4-4fd2-4b91-ab73-3ff414bd8681" 63 | ], 64 | "folders_order": [ 65 | "080b8420-bd81-423c-a346-d348560e24fe", 66 | "bf5076bf-e357-45ca-9771-16fe39cd7df5" 67 | ] 68 | }, 69 | { 70 | "id": "080b8420-bd81-423c-a346-d348560e24fe", 71 | "name": "F5.F1", 72 | "description": "Description", 73 | "order": [], 74 | "folders_order": [] 75 | }, 76 | { 77 | "id": "bf5076bf-e357-45ca-9771-16fe39cd7df5", 78 | "name": "F5.F2", 79 | "description": "Description", 80 | "order": [], 81 | "folders_order": [] 82 | } 83 | ], 84 | "requests": [ 85 | { 86 | "id": "73d22bec-5403-4fc8-bd1b-f5ec237c5d16", 87 | "name": "F1.R1", 88 | "description": "Description", 89 | "collectionId": "e5f2e9cf-173b-c60a-7336-ac804a87d762", 90 | "method": "GET", 91 | "headers": "", 92 | "data": [], 93 | "rawModeData": "", 94 | "tests": "", 95 | "preRequestScript": "", 96 | "url": "https://postman-echo.com/get", 97 | "responses": [] 98 | }, 99 | { 100 | "id": "f78296f9-baf2-446b-8450-fe6b982ba784", 101 | "name": "F1.R2", 102 | "description": "Description", 103 | "collectionId": "e5f2e9cf-173b-c60a-7336-ac804a87d762", 104 | "method": "GET", 105 | "headers": "", 106 | "data": [], 107 | "rawModeData": "", 108 | "tests": "", 109 | "preRequestScript": "", 110 | "url": "https://postman-echo.com/get", 111 | "responses": [] 112 | }, 113 | { 114 | "id": "59b9a846-af89-45ad-85bf-1d5163c64747", 115 | "name": "F1.R3", 116 | "description": "Description", 117 | "collectionId": "e5f2e9cf-173b-c60a-7336-ac804a87d762", 118 | "method": "GET", 119 | "headers": "", 120 | "data": [], 121 | "rawModeData": "", 122 | "tests": "", 123 | "preRequestScript": "", 124 | "url": "https://postman-echo.com/get", 125 | "responses": [] 126 | }, 127 | { 128 | "id": "072721f4-c04f-4172-a86b-b07fdfe5b8ee", 129 | "name": "F2.F3.R1", 130 | "description": "Description", 131 | "collectionId": "e5f2e9cf-173b-c60a-7336-ac804a87d762", 132 | "method": "GET", 133 | "headers": "", 134 | "data": [], 135 | "rawModeData": "", 136 | "tests": "", 137 | "preRequestScript": "", 138 | "url": "https://postman-echo.com/get", 139 | "responses": [] 140 | }, 141 | { 142 | "id": "aacf3ebd-6c2b-4452-a6ba-a298f951f334", 143 | "name": "F2.R1", 144 | "description": "Description", 145 | "collectionId": "e5f2e9cf-173b-c60a-7336-ac804a87d762", 146 | "method": "GET", 147 | "headers": "", 148 | "data": [], 149 | "rawModeData": "", 150 | "tests": "", 151 | "preRequestScript": "", 152 | "url": "https://postman-echo.com/get", 153 | "responses": [] 154 | }, 155 | { 156 | "id": "b7b3ea2c-85e1-43bb-99e4-bb0a7b3bdfe1", 157 | "name": "R1", 158 | "description": "Description", 159 | "collectionId": "e5f2e9cf-173b-c60a-7336-ac804a87d762", 160 | "method": "GET", 161 | "headers": "", 162 | "data": [], 163 | "rawModeData": "", 164 | "tests": "", 165 | "preRequestScript": "", 166 | "url": "https://postman-echo.com/get", 167 | "responses": [] 168 | }, 169 | { 170 | "id": "69ca91c0-c399-4847-abac-38db847add22", 171 | "name": "R2", 172 | "description": "Description", 173 | "collectionId": "e5f2e9cf-173b-c60a-7336-ac804a87d762", 174 | "method": "GET", 175 | "headers": "", 176 | "data": [], 177 | "rawModeData": "", 178 | "tests": "", 179 | "preRequestScript": "", 180 | "url": "https://postman-echo.com/get", 181 | "responses": [] 182 | }, 183 | { 184 | "id": "807727a4-4fd2-4b91-ab73-3ff414bd8681", 185 | "name": "F5.R1", 186 | "description": "Description", 187 | "collectionId": "e5f2e9cf-173b-c60a-7336-ac804a87d762", 188 | "method": "GET", 189 | "headers": "", 190 | "data": [], 191 | "rawModeData": "", 192 | "tests": "", 193 | "preRequestScript": "", 194 | "url": "https://postman-echo.com/get", 195 | "responses": [] 196 | }, 197 | { 198 | "id": "9bcff6ab-ba00-43a7-8b29-536205ac7b80", 199 | "name": "F5.F1.R1", 200 | "description": "Description", 201 | "folder": "080b8420-bd81-423c-a346-d348560e24fe", 202 | "collectionId": "e5f2e9cf-173b-c60a-7336-ac804a87d762", 203 | "method": "GET", 204 | "headers": "", 205 | "data": [], 206 | "rawModeData": "", 207 | "tests": "", 208 | "preRequestScript": "", 209 | "url": "https://postman-echo.com/get", 210 | "responses": [] 211 | }, 212 | { 213 | "id": "1e9b259e-3b03-4bde-acfb-474dd9247f60", 214 | "name": "F5.F2.R1", 215 | "description": "Description", 216 | "folder": "bf5076bf-e357-45ca-9771-16fe39cd7df5", 217 | "collectionId": "e5f2e9cf-173b-c60a-7336-ac804a87d762", 218 | "method": "GET", 219 | "headers": "", 220 | "data": [], 221 | "rawModeData": "", 222 | "tests": "", 223 | "preRequestScript": "", 224 | "url": "https://postman-echo.com/get", 225 | "responses": [] 226 | } 227 | ] 228 | } 229 | -------------------------------------------------------------------------------- /examples/v1.0.0/multi-level-folders.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "e5f2e9cf-173b-c60a-7336-ac804a87d762", 3 | "name": "multi-level-folders", 4 | "description": "A simple V1 collection to test out multi level folder flows", 5 | "order": [ 6 | "R1" 7 | ], 8 | "folders_order": [ 9 | "F1", 10 | "F2" 11 | ], 12 | "folders": [ 13 | { 14 | "id": "F1", 15 | "name": "F1", 16 | "description": "Description", 17 | "order": [ 18 | "F1.R1", 19 | "F1.R2", 20 | "F1.R3" 21 | ], 22 | "owner": "640245" 23 | }, 24 | { 25 | "id": "F2", 26 | "name": "F2", 27 | "description": "Description", 28 | "order": [ 29 | "F2.R1" 30 | ], 31 | "folders_order": [ 32 | "F2.F3", 33 | "F2.F4" 34 | ], 35 | "owner": "640245" 36 | }, 37 | { 38 | "id": "F2.F3", 39 | "name": "F2.F3", 40 | "folder": "F2", 41 | "description": "Description", 42 | "order": [ 43 | "F2.F3.R1" 44 | ], 45 | "owner": "640245" 46 | }, 47 | { 48 | "id": "F2.F4", 49 | "name": "F2.F4", 50 | "folder": "F2", 51 | "description": "Description", 52 | "order": [], 53 | "owner": "640245" 54 | } 55 | ], 56 | "timestamp": 1486026507417, 57 | "owner": "640245", 58 | "public": false, 59 | "requests": [ 60 | { 61 | "id": "F1.R1", 62 | "folder": "F1", 63 | "headers": "", 64 | "url": "https://postman-echo.com/get", 65 | "preRequestScript": null, 66 | "pathVariables": {}, 67 | "method": "GET", 68 | "data": null, 69 | "dataMode": "params", 70 | "version": 2, 71 | "tests": "tests[\"Status code is 200\"] = responseCode.code === 200;", 72 | "currentHelper": "normal", 73 | "helperAttributes": {}, 74 | "time": 1486026610011, 75 | "name": "F1.R1", 76 | "description": "Description", 77 | "collectionId": "e5f2e9cf-173b-c60a-7336-ac804a87d762", 78 | "responses": [] 79 | }, 80 | { 81 | "id": "F1.R2", 82 | "folder": "F1", 83 | "headers": "", 84 | "url": "https://postman-echo.com/get", 85 | "preRequestScript": null, 86 | "pathVariables": {}, 87 | "method": "GET", 88 | "data": null, 89 | "dataMode": "params", 90 | "version": 2, 91 | "tests": "tests[\"Status code is 200\"] = responseCode.code === 200;", 92 | "currentHelper": "normal", 93 | "helperAttributes": {}, 94 | "time": 1486026628312, 95 | "name": "F1.R2", 96 | "description": "Description", 97 | "collectionId": "e5f2e9cf-173b-c60a-7336-ac804a87d762", 98 | "responses": [] 99 | }, 100 | { 101 | "id": "F1.R3", 102 | "folder": "F1", 103 | "headers": "", 104 | "url": "https://postman-echo.com/get", 105 | "preRequestScript": null, 106 | "pathVariables": {}, 107 | "method": "GET", 108 | "data": null, 109 | "dataMode": "params", 110 | "version": 2, 111 | "tests": "tests[\"Status code is 200\"] = responseCode.code === 200;", 112 | "currentHelper": "normal", 113 | "helperAttributes": {}, 114 | "time": 1486026625352, 115 | "name": "F1.R3", 116 | "description": "Description", 117 | "collectionId": "e5f2e9cf-173b-c60a-7336-ac804a87d762", 118 | "responses": [] 119 | }, 120 | { 121 | "id": "F2.F3.R1", 122 | "folder": "F2.F3", 123 | "headers": "", 124 | "url": "https://postman-echo.com/get", 125 | "preRequestScript": null, 126 | "pathVariables": {}, 127 | "method": "GET", 128 | "data": null, 129 | "dataMode": "params", 130 | "version": 2, 131 | "tests": "tests[\"Status code is 200\"] = responseCode.code === 200;", 132 | "currentHelper": "normal", 133 | "helperAttributes": {}, 134 | "time": 1486026633384, 135 | "name": "F2.F3.R1", 136 | "description": "Description", 137 | "collectionId": "e5f2e9cf-173b-c60a-7336-ac804a87d762", 138 | "responses": [] 139 | }, 140 | { 141 | "id": "F2.R1", 142 | "folder": "F2", 143 | "headers": "", 144 | "url": "https://postman-echo.com/get", 145 | "preRequestScript": null, 146 | "pathVariables": {}, 147 | "method": "GET", 148 | "data": null, 149 | "dataMode": "params", 150 | "version": 2, 151 | "tests": "tests[\"Status code is 200\"] = responseCode.code === 200;", 152 | "currentHelper": "normal", 153 | "helperAttributes": {}, 154 | "time": 1486026633384, 155 | "name": "F2.R1", 156 | "description": "Description", 157 | "collectionId": "e5f2e9cf-173b-c60a-7336-ac804a87d762", 158 | "responses": [] 159 | }, 160 | { 161 | "id": "R1", 162 | "headers": "", 163 | "url": "https://postman-echo.com/get", 164 | "preRequestScript": null, 165 | "pathVariables": {}, 166 | "method": "GET", 167 | "data": null, 168 | "dataMode": "params", 169 | "version": 2, 170 | "tests": "tests[\"Status code is 200\"] = responseCode.code === 200;", 171 | "currentHelper": "normal", 172 | "helperAttributes": {}, 173 | "time": 1486026637544, 174 | "name": "R1", 175 | "description": "Description", 176 | "collectionId": "e5f2e9cf-173b-c60a-7336-ac804a87d762", 177 | "responses": [] 178 | } 179 | ] 180 | } 181 | -------------------------------------------------------------------------------- /examples/v1.0.0/nestedEntities.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "371e9fa3-97d3-ca11-07c0-836a72a325c2", 3 | "name": "auth-v1", 4 | "description": "A simple V1 collection to elucidate nested auth helpers, variables, and scripts", 5 | "order": [ 6 | "32435cc1-e185-cdc8-be08-1f08d37280da", 7 | "f619a417-7ab7-d28b-e75e-f110b5862eb6", 8 | "1a4530d5-21d3-d7a9-e923-ccdf2b0f97a0" 9 | ], 10 | "folders": [ 11 | { 12 | "name": "F1", 13 | "description": "Folder 1", 14 | "collectionId": "371e9fa3-97d3-ca11-07c0-836a72a325c2", 15 | "order": [ 16 | "a742022f-ff24-18c5-6e8b-0c4e7d7aee08", 17 | "95b3bde0-96a2-7f91-8e65-e007bb28ae62", 18 | "fd20f294-3f94-c979-3440-4934c89c353d" 19 | ], 20 | "auth": { 21 | "type": "digest", 22 | "digest": [ 23 | { 24 | "key": "algorithm", 25 | "value": "MD5", 26 | "type": "string" 27 | }, 28 | { 29 | "key": "username", 30 | "value": "postman", 31 | "type": "string" 32 | }, 33 | { 34 | "key": "realm", 35 | "value": "{{echo_digest_realm}}", 36 | "type": "string" 37 | }, 38 | { 39 | "key": "password", 40 | "value": "password", 41 | "type": "string" 42 | }, 43 | { 44 | "key": "nonce", 45 | "value": "{{echo_digest_nonce}}", 46 | "type": "string" 47 | }, 48 | { 49 | "key": "nonceCount", 50 | "value": "", 51 | "type": "string" 52 | }, 53 | { 54 | "key": "clientNonce", 55 | "value": "", 56 | "type": "string" 57 | }, 58 | { 59 | "key": "opaque", 60 | "value": "", 61 | "type": "string" 62 | }, 63 | { 64 | "key": "qop", 65 | "value": "", 66 | "type": "string" 67 | }, 68 | { 69 | "key": "saveToRequest", 70 | "value": true, 71 | "type": "boolean" 72 | } 73 | ] 74 | }, 75 | "variables": [{ 76 | "key": "folder", 77 | "value": "variable", 78 | "type": "string", 79 | "description": "This is a folder level variable" 80 | }], 81 | "owner": "640245", 82 | "folders_order": [], 83 | "id": "5be148b3-0081-5a59-5273-9014161b0292" 84 | } 85 | ], 86 | "folders_order": [ 87 | "5be148b3-0081-5a59-5273-9014161b0292" 88 | ], 89 | "variables": [{ 90 | "key": "collection", 91 | "value": "variable", 92 | "type": "string", 93 | "description": "This is a collection level variable" 94 | }], 95 | "timestamp": 1504507037786, 96 | "owner": "640245", 97 | "public": false, 98 | "events": [{ 99 | "listen": "prerequest", 100 | "script": { 101 | "type": "text/javascript", 102 | "exec": ["console.log('Collection level pre request script');"] 103 | } 104 | }, { 105 | "listen": "test", 106 | "script": { 107 | "type": "text/javascript", 108 | "exec": ["console.log('Collection level test script');"] 109 | } 110 | }], 111 | "auth": { 112 | "type": "awsv4", 113 | "awsv4": [ 114 | { 115 | "key": "accessKey", 116 | "value": "{{id}}", 117 | "type": "string" 118 | }, 119 | { 120 | "key": "secretKey", 121 | "value": "{{key}}", 122 | "type": "string" 123 | }, 124 | { 125 | "key": "region", 126 | "value": "us-east-1", 127 | "type": "string" 128 | }, 129 | { 130 | "key": "service", 131 | "value": "iam", 132 | "type": "string" 133 | }, 134 | { 135 | "key": "sessionToken", 136 | "value": "", 137 | "type": "string" 138 | }, 139 | { 140 | "key": "saveToRequest", 141 | "value": true, 142 | "type": "boolean" 143 | } 144 | ] 145 | }, 146 | "requests": [ 147 | { 148 | "id": "a742022f-ff24-18c5-6e8b-0c4e7d7aee08", 149 | "headers": "", 150 | "headerData": [], 151 | "url": "https://postman-echo.com/get", 152 | "folder": "5be148b3-0081-5a59-5273-9014161b0292", 153 | "queryParams": [], 154 | "preRequestScript": "console.log('Request level pre request script');", 155 | "pathVariables": {}, 156 | "pathVariableData": [], 157 | "method": "GET", 158 | "data": null, 159 | "dataMode": "params", 160 | "version": 2, 161 | "tests": "console.log('Request level test script');", 162 | "auth": { 163 | "type": "basic", 164 | "basic": [ 165 | { 166 | "key": "username", 167 | "value": "{{username}}", 168 | "type": "string" 169 | }, 170 | { 171 | "key": "password", 172 | "value": "{{token}}", 173 | "type": "string" 174 | } 175 | ] 176 | }, 177 | "currentHelper": "basicAuth", 178 | "helperAttributes": { 179 | "id": "basic", 180 | "username": "{{username}}", 181 | "password": "{{token}}", 182 | "saveToRequest": true 183 | }, 184 | "time": 1504507088801, 185 | "name": "Basic", 186 | "description": "", 187 | "collectionId": "371e9fa3-97d3-ca11-07c0-836a72a325c2", 188 | "responses": [], 189 | "variables": [{ 190 | "key": "request", 191 | "value": "variable", 192 | "type": "string", 193 | "description": "This is a request level variable" 194 | }], 195 | "isFromCollection": true, 196 | "collectionRequestId": "a742022f-ff24-18c5-6e8b-0c4e7d7aee08" 197 | }, 198 | { 199 | "id": "f619a417-7ab7-d28b-e75e-f110b5862eb6", 200 | "headers": "", 201 | "headerData": [], 202 | "url": "https://postman-echo.com/get", 203 | "queryParams": [], 204 | "preRequestScript": "console.log('Request level pre request script');", 205 | "pathVariables": {}, 206 | "pathVariableData": [], 207 | "method": "GET", 208 | "data": null, 209 | "dataMode": "params", 210 | "version": 2, 211 | "tests": "console.log('Request level test script');", 212 | "auth": { 213 | "type": "oauth1", 214 | "oauth1": [ 215 | { 216 | "key": "consumerKey", 217 | "value": "RKCGzna7bv9YD57c", 218 | "type": "string" 219 | }, 220 | { 221 | "key": "consumerSecret", 222 | "value": "D+EdQ-gs$-%@2Nu7", 223 | "type": "string" 224 | }, 225 | { 226 | "key": "token", 227 | "value": "", 228 | "type": "string" 229 | }, 230 | { 231 | "key": "tokenSecret", 232 | "value": "", 233 | "type": "string" 234 | }, 235 | { 236 | "key": "signatureMethod", 237 | "value": "HMAC-SHA1", 238 | "type": "string" 239 | }, 240 | { 241 | "key": "timestamp", 242 | "value": "1500452534", 243 | "type": "string" 244 | }, 245 | { 246 | "key": "nonce", 247 | "value": "S0kXloMHurS", 248 | "type": "string" 249 | }, 250 | { 251 | "key": "version", 252 | "value": "1.0", 253 | "type": "string" 254 | }, 255 | { 256 | "key": "realm", 257 | "value": "", 258 | "type": "string" 259 | }, 260 | { 261 | "key": "encodeSignature", 262 | "value": true, 263 | "type": "boolean" 264 | }, 265 | { 266 | "key": "header", 267 | "value": false, 268 | "type": "boolean" 269 | }, 270 | { 271 | "key": "includeEmpty", 272 | "value": false, 273 | "type": "boolean" 274 | }, 275 | { 276 | "key": "saveToRequest", 277 | "value": true, 278 | "type": "boolean" 279 | } 280 | ] 281 | }, 282 | "currentHelper": "oAuth1", 283 | "helperAttributes": { 284 | "id": "oAuth1", 285 | "consumerKey": "RKCGzna7bv9YD57c", 286 | "consumerSecret": "D+EdQ-gs$-%@2Nu7", 287 | "token": "", 288 | "tokenSecret": "", 289 | "signatureMethod": "HMAC-SHA1", 290 | "timestamp": "1500452534", 291 | "nonce": "S0kXloMHurS", 292 | "version": "1.0", 293 | "realm": "", 294 | "encodeSignature": true, 295 | "header": false, 296 | "includeEmpty": false, 297 | "saveToRequest": true 298 | }, 299 | "time": 1504507141155, 300 | "name": "OAuth1", 301 | "description": "", 302 | "variables": [{ 303 | "key": "request", 304 | "value": "variable", 305 | "type": "string", 306 | "description": "This is a request level variable" 307 | }], 308 | "collectionId": "371e9fa3-97d3-ca11-07c0-836a72a325c2", 309 | "responses": [] 310 | } 311 | ] 312 | } 313 | -------------------------------------------------------------------------------- /examples/v1.0.0/no-body.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "A collection", 3 | "order": [ 4 | "d66ea01e-803d-4827-91dc-adf1f379d508" 5 | ], 6 | "folders": [], 7 | "requests": [ 8 | { 9 | "id": "d66ea01e-803d-4827-91dc-adf1f379d508", 10 | "name": "Request", 11 | "collectionId": "5aff34b9-a2af-4579-8b05-8f3dfea35fe1", 12 | "method": "GET", 13 | "headers": "", 14 | "data": [], 15 | "rawModeData": "", 16 | "tests": "", 17 | "preRequestScript": "", 18 | "url": "http://echo.postman.com", 19 | "responses": [] 20 | } 21 | ] 22 | } 23 | -------------------------------------------------------------------------------- /examples/v1.0.0/proper-url-parsing.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "7ea31a30-8377-0e56-d11f-5943e6527bca", 3 | "name": "proper-url-parsing", 4 | "description": "Description", 5 | "order": [ 6 | "2c03f359-f259-bb30-d14c-ea278056e95f" 7 | ], 8 | "folders": [], 9 | "timestamp": 1448955280503, 10 | "owner": "61671", 11 | "remoteLink": "", 12 | "public": false, 13 | "requests": [ 14 | { 15 | "id": "2c03f359-f259-bb30-d14c-ea278056e95f", 16 | "headers": "", 17 | "url": "https://ani{{yo}}ket:{{asd}}@{{hellohost}}:2002/crazyvar/{{yo}}/:awesome?a=b&c=d#/awesomeshit", 18 | "pathVariables": {}, 19 | "preRequestScript": "", 20 | "method": "GET", 21 | "collectionId": "7ea31a30-8377-0e56-d11f-5943e6527bca", 22 | "data": [], 23 | "dataMode": "params", 24 | "name": "request with hostname as variable", 25 | "description": "Description", 26 | "descriptionFormat": "html", 27 | "time": 1448955336367, 28 | "version": 2, 29 | "responses": [], 30 | "tests": "", 31 | "currentHelper": "normal", 32 | "helperAttributes": {} 33 | } 34 | ] 35 | } 36 | -------------------------------------------------------------------------------- /examples/v1.0.0/rawjsonbody.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "c96a1f4e-f2e8-ed1f-3421-e16568f4b471", 3 | "name": "rawjsonbody", 4 | "description": "Description", 5 | "order": [ 6 | "8f444706-d8cc-9196-ee18-e0c7c3627df3" 7 | ], 8 | "folders": [], 9 | "timestamp": 1455198074086, 10 | "owner": "61671", 11 | "remoteLink": "", 12 | "public": false, 13 | "requests": [ 14 | { 15 | "id": "8f444706-d8cc-9196-ee18-e0c7c3627df3", 16 | "headers": "Content-Type: application/json\n", 17 | "url": "httpbin.org/:method", 18 | "pathVariables": { 19 | "method": "post" 20 | }, 21 | "preRequestScript": "", 22 | "method": "POST", 23 | "collectionId": "c96a1f4e-f2e8-ed1f-3421-e16568f4b471", 24 | "data": [], 25 | "dataMode": "raw", 26 | "name": "httpbin.org/post", 27 | "description": "Description", 28 | "descriptionFormat": "html", 29 | "time": 1455198431632, 30 | "version": 2, 31 | "responses": [], 32 | "tests": "", 33 | "currentHelper": "normal", 34 | "helperAttributes": {}, 35 | "rawModeData": "{\n \"asd\": \"tyyy\"\n}" 36 | } 37 | ] 38 | } -------------------------------------------------------------------------------- /examples/v1.0.0/simplest.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "c3ac3ec4-8f23-2f3a-5215-aa33d781ca21", 3 | "name": "simplest", 4 | "description": "Description", 5 | "order": [ 6 | "5a795cee-c9a7-9cbc-32cd-9125337d6d7b" 7 | ], 8 | "folders": [], 9 | "requests": [ 10 | { 11 | "id": "5a795cee-c9a7-9cbc-32cd-9125337d6d7b", 12 | "headers": "Content-Type: text/plain\n", 13 | "url": "echo.postman.com/post", 14 | "preRequestScript": null, 15 | "pathVariables": {}, 16 | "method": "POST", 17 | "data": "something", 18 | "dataMode": "raw", 19 | "tests": "tests[\"Body matches string\"] = responseBody.has(\"OMG\");\ntests[\"Status code is 200\"] = responseCode.code === 200;", 20 | "currentHelper": "normal", 21 | "helperAttributes": {}, 22 | "name": "echo.postman.com/post", 23 | "description": "OMG I AM description", 24 | "responses": [] 25 | } 26 | ] 27 | } 28 | -------------------------------------------------------------------------------- /examples/v1.0.0/urlencoded-post-data.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "551c1361-2b81-68c7-677e-ec2efdd8322e", 3 | "name": "urlencodeddata", 4 | "description": "Description", 5 | "order": [ 6 | "b7fe1cf7-22bb-93f2-f058-3b4cdbf965b7" 7 | ], 8 | "folders": [], 9 | "timestamp": 1455197245454, 10 | "owner": "61671", 11 | "remoteLink": "", 12 | "public": false, 13 | "requests": [ 14 | { 15 | "id": "b7fe1cf7-22bb-93f2-f058-3b4cdbf965b7", 16 | "headers": "", 17 | "url": "http://httpbin.org/post", 18 | "pathVariables": {}, 19 | "preRequestScript": "", 20 | "method": "POST", 21 | "collectionId": "551c1361-2b81-68c7-677e-ec2efdd8322e", 22 | "data": [ 23 | { 24 | "key": "akshay", 25 | "value": "bald", 26 | "type": "text", 27 | "enabled": true 28 | }, 29 | { 30 | "key": "yakshay", 31 | "value": "ybald", 32 | "type": "text", 33 | "enabled": true 34 | } 35 | ], 36 | "dataMode": "urlencoded", 37 | "name": "http://httpbin.org/post", 38 | "description": "Description", 39 | "descriptionFormat": "html", 40 | "time": 1455197245454, 41 | "version": 2, 42 | "responses": [ 43 | { 44 | "status": "", 45 | "responseCode": { 46 | "code": 200, 47 | "name": "OK", 48 | "detail": "Standard response for successful HTTP requests. The actual response will depend on the request method used. In a GET request, the response will contain an entity corresponding to the requested resource. In a POST request the response will contain an entity describing or containing the result of the action." 49 | }, 50 | "time": 925, 51 | "headers": [ 52 | { 53 | "name": "Access-Control-Allow-Credentials", 54 | "key": "Access-Control-Allow-Credentials", 55 | "value": "true", 56 | "description": "Indicates whether or not the response to the request can be exposed when the credentials flag is true. When used as part of a response to a preflight request, this indicates whether or not the actual request can be made using credentials." 57 | }, 58 | { 59 | "name": "Access-Control-Allow-Origin", 60 | "key": "Access-Control-Allow-Origin", 61 | "value": "chrome-extension://aicmkgpgakddgnaphhhpliifpcfhicfo", 62 | "description": "Specifies a URI that may access the resource. For requests without credentials, the server may specify '*' as a wildcard, thereby allowing any origin to access the resource." 63 | }, 64 | { 65 | "name": "Connection", 66 | "key": "Connection", 67 | "value": "keep-alive", 68 | "description": "Options that are desired for the connection" 69 | }, 70 | { 71 | "name": "Content-Length", 72 | "key": "Content-Length", 73 | "value": "768", 74 | "description": "The length of the response body in octets (8-bit bytes)" 75 | }, 76 | { 77 | "name": "Content-Type", 78 | "key": "Content-Type", 79 | "value": "application/json", 80 | "description": "The mime type of this content" 81 | }, 82 | { 83 | "name": "Date", 84 | "key": "Date", 85 | "value": "Thu, 11 Feb 2016 13:27:33 GMT", 86 | "description": "The date and time that the message was sent" 87 | }, 88 | { 89 | "name": "Server", 90 | "key": "Server", 91 | "value": "nginx", 92 | "description": "A name for the server" 93 | } 94 | ], 95 | "mime": "", 96 | "text": "{\n \"args\": {}, \n \"data\": \"\", \n \"files\": {}, \n \"form\": {\n \"akshay\": \"bald\", \n \"yakshay\": \"ybald\"\n }, \n \"headers\": {\n \"Accept\": \"*/*\", \n \"Accept-Encoding\": \"gzip\", \n \"Accept-Language\": \"en-US,en;q=0.8\", \n \"Cache-Control\": \"no-cache\", \n \"Content-Length\": \"25\", \n \"Content-Type\": \"application/x-www-form-urlencoded\", \n \"Cookie\": \"_ga=GA1.2.113558537.1435817423\", \n \"Host\": \"httpbin.org\", \n \"Origin\": \"chrome-extension://aicmkgpgakddgnaphhhpliifpcfhicfo\", \n \"Postman-Token\": \"e8826f9c-70fa-0957-fe12-265257861623\", \n \"User-Agent\": \"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/48.0.2564.109 Safari/537.36\"\n }, \n \"json\": null, \n \"origin\": \"106.51.38.69\", \n \"url\": \"http://httpbin.org/post\"\n}\n", 97 | "language": "javascript", 98 | "rawDataType": "text", 99 | "state": { 100 | "size": "normal" 101 | }, 102 | "previewType": "html", 103 | "searchResultScrolledTo": -1, 104 | "forceNoPretty": false, 105 | "write": true, 106 | "empty": false, 107 | "failed": false, 108 | "isSample": true, 109 | "scrollToResult": true, 110 | "runTests": true, 111 | "id": "727942c4-f951-6531-b0d3-0e178887c3e7", 112 | "name": "samplerespose", 113 | "request": { 114 | "url": "http://httpbin.org/post", 115 | "headers": [ 116 | { 117 | "key": "Cache-Control", 118 | "name": "Cache-Control", 119 | "value": "no-cache" 120 | }, 121 | { 122 | "key": "Postman-Token", 123 | "name": "Postman-Token", 124 | "value": "e8826f9c-70fa-0957-fe12-265257861623" 125 | }, 126 | { 127 | "key": "Content-Type", 128 | "name": "Content-Type", 129 | "value": "application/x-www-form-urlencoded" 130 | } 131 | ], 132 | "data": [ 133 | { 134 | "key": "akshay", 135 | "value": "bald" 136 | }, 137 | { 138 | "key": "yakshay", 139 | "value": "ybald" 140 | } 141 | ], 142 | "method": "POST", 143 | "dataMode": "urlencoded" 144 | } 145 | } 146 | ], 147 | "tests": "", 148 | "currentHelper": "normal", 149 | "helperAttributes": {} 150 | } 151 | ] 152 | } 153 | -------------------------------------------------------------------------------- /examples/v2.0.0/binary-upload.json: -------------------------------------------------------------------------------- 1 | { 2 | "variable": [], 3 | "info": { 4 | "name": "asdasdasdasdasdasd", 5 | "_postman_id": "70fa9b38-91c0-7e67-0ead-b31622bdc152", 6 | "description": "Description", 7 | "schema": "https://schema.getpostman.com/json/collection/v2.0.0/collection.json" 8 | }, 9 | "item": [ 10 | { 11 | "_postman_id": "cc0e1894-bad7-aeeb-e91c-e74635371614", 12 | "name": "http://httpbin.org/post", 13 | "event": [ 14 | { 15 | "listen": "test", 16 | "script": { 17 | "type": "text/javascript", 18 | "exec": [ 19 | "console.log(responseBody)" 20 | ] 21 | } 22 | } 23 | ], 24 | "request": { 25 | "url": "http://echo.postman.com/post", 26 | "method": "POST", 27 | "header": [], 28 | "body": { 29 | "mode": "file", 30 | "file": { 31 | "src": "sample.txt" 32 | } 33 | }, 34 | "description": "Description" 35 | }, 36 | "response": [] 37 | } 38 | ] 39 | } 40 | -------------------------------------------------------------------------------- /examples/v2.0.0/multi-level-folders.json: -------------------------------------------------------------------------------- 1 | { 2 | "variable": [], 3 | "info": { 4 | "name": "multi-level-folders", 5 | "_postman_id": "e5f2e9cf-173b-c60a-7336-ac804a87d762", 6 | "description": "A simple V2 collection to test out multi level folder flows", 7 | "schema": "https://schema.getpostman.com/json/collection/v2.0.0/collection.json" 8 | }, 9 | "item": [ 10 | { 11 | "name": "F1", 12 | "id": "F1", 13 | "description": "Description", 14 | "item": [ 15 | { 16 | "name": "F1.R1", 17 | "id": "F1.R1", 18 | "event": [ 19 | { 20 | "listen": "test", 21 | "script": { 22 | "type": "text/javascript", 23 | "exec": [ 24 | "tests[\"Status code is 200\"] = responseCode.code === 200;" 25 | ] 26 | } 27 | } 28 | ], 29 | "request": { 30 | "url": "https://postman-echo.com/get", 31 | "method": "GET", 32 | "header": [], 33 | "body": {}, 34 | "description": "Description" 35 | }, 36 | "response": [] 37 | }, 38 | { 39 | "name": "F1.R2", 40 | "id": "F1.R2", 41 | "event": [ 42 | { 43 | "listen": "test", 44 | "script": { 45 | "type": "text/javascript", 46 | "exec": [ 47 | "tests[\"Status code is 200\"] = responseCode.code === 200;" 48 | ] 49 | } 50 | } 51 | ], 52 | "request": { 53 | "url": "https://postman-echo.com/get", 54 | "method": "GET", 55 | "header": [], 56 | "body": {}, 57 | "description": "Description" 58 | }, 59 | "response": [] 60 | }, 61 | { 62 | "name": "F1.R3", 63 | "id": "F1.R3", 64 | "event": [ 65 | { 66 | "listen": "test", 67 | "script": { 68 | "type": "text/javascript", 69 | "exec": [ 70 | "tests[\"Status code is 200\"] = responseCode.code === 200;" 71 | ] 72 | } 73 | } 74 | ], 75 | "request": { 76 | "url": "https://postman-echo.com/get", 77 | "method": "GET", 78 | "header": [], 79 | "body": {}, 80 | "description": "Description" 81 | }, 82 | "response": [] 83 | } 84 | ] 85 | }, 86 | { 87 | "name": "F2", 88 | "id": "F2", 89 | "description": "Description", 90 | "item": [ 91 | { 92 | "name": "F2.F3", 93 | "id": "F2.F3", 94 | "description": "Description", 95 | "item": [ 96 | { 97 | "name": "F2.F3.R1", 98 | "id": "F2.F3.R1", 99 | "event": [ 100 | { 101 | "listen": "test", 102 | "script": { 103 | "type": "text/javascript", 104 | "exec": [ 105 | "tests[\"Status code is 200\"] = responseCode.code === 200;" 106 | ] 107 | } 108 | } 109 | ], 110 | "request": { 111 | "url": "https://postman-echo.com/get", 112 | "method": "GET", 113 | "header": [], 114 | "body": {}, 115 | "description": "Description" 116 | }, 117 | "response": [] 118 | } 119 | ] 120 | }, 121 | { 122 | "name": "F2.F4", 123 | "id": "F2.F4", 124 | "description": "Description", 125 | "item": [] 126 | }, 127 | { 128 | "name": "F2.R1", 129 | "id": "F2.R1", 130 | "event": [ 131 | { 132 | "listen": "test", 133 | "script": { 134 | "type": "text/javascript", 135 | "exec": [ 136 | "tests[\"Status code is 200\"] = responseCode.code === 200;" 137 | ] 138 | } 139 | } 140 | ], 141 | "request": { 142 | "url": "https://postman-echo.com/get", 143 | "method": "GET", 144 | "header": [], 145 | "body": {}, 146 | "description": "Description" 147 | }, 148 | "response": [] 149 | } 150 | ] 151 | }, 152 | { 153 | "name": "R1", 154 | "id": "R1", 155 | "event": [ 156 | { 157 | "listen": "test", 158 | "script": { 159 | "type": "text/javascript", 160 | "exec": [ 161 | "tests[\"Status code is 200\"] = responseCode.code === 200;" 162 | ] 163 | } 164 | } 165 | ], 166 | "request": { 167 | "url": "https://postman-echo.com/get", 168 | "method": "GET", 169 | "header": [], 170 | "body": {}, 171 | "description": "Description" 172 | }, 173 | "response": [] 174 | } 175 | ] 176 | } 177 | -------------------------------------------------------------------------------- /examples/v2.0.0/nestedEntities.json: -------------------------------------------------------------------------------- 1 | { 2 | "info": { 3 | "name": "auth-v1", 4 | "_postman_id": "46da69ac-9035-50c4-fcab-44d9167e06f4", 5 | "description": "A simple V1 collection to elucidate nested auth helpers, variables, and scripts", 6 | "schema": "https://schema.getpostman.com/json/collection/v2.0.0/collection.json" 7 | }, 8 | "variable": [{ 9 | "key": "collection", 10 | "value": "variable", 11 | "type": "string", 12 | "description": "This is a collection level variable" 13 | }], 14 | "auth": { 15 | "type": "basic", 16 | "basic": { 17 | "username": "{{username}}", 18 | "password": "{{token}}" 19 | } 20 | }, 21 | "event": [ 22 | { 23 | "listen": "test", 24 | "script": { 25 | "type": "text/javascript", 26 | "exec": [ 27 | "console.log('Collection level test script');" 28 | ] 29 | } 30 | }, 31 | { 32 | "listen": "prerequest", 33 | "script": { 34 | "type": "text/javascript", 35 | "exec": [ 36 | "console.log('Collection level pre request script');" 37 | ] 38 | } 39 | } 40 | ], 41 | "item": [ 42 | { 43 | "name": "F1", 44 | "description": "Folder 1", 45 | "variable": [{ 46 | "key": "folder", 47 | "value": "variable", 48 | "type": "string", 49 | "description": "This is a folder level variable" 50 | }], 51 | "auth": { 52 | "type": "basic", 53 | "basic": { 54 | "username": "{{username}}", 55 | "password": "{{token}}" 56 | } 57 | }, 58 | "event": [ 59 | { 60 | "listen": "test", 61 | "script": { 62 | "type": "text/javascript", 63 | "exec": [ 64 | "console.log('Folder level test script');" 65 | ] 66 | } 67 | }, 68 | { 69 | "listen": "prerequest", 70 | "script": { 71 | "type": "text/javascript", 72 | "exec": [ 73 | "console.log('Folder level pre request script');" 74 | ] 75 | } 76 | } 77 | ], 78 | "item": [ 79 | { 80 | "name": "Basic", 81 | "variable": [{ 82 | "key": "request", 83 | "value": "variable", 84 | "type": "string", 85 | "description": "This is a request level variable" 86 | }], 87 | "event": [ 88 | { 89 | "listen": "test", 90 | "script": { 91 | "type": "text/javascript", 92 | "exec": [ 93 | "console.log('Request level test script');" 94 | ] 95 | } 96 | }, 97 | { 98 | "listen": "prerequest", 99 | "script": { 100 | "type": "text/javascript", 101 | "exec": [ 102 | "console.log('Request level pre request script');" 103 | ] 104 | } 105 | } 106 | ], 107 | "request": { 108 | "auth": { 109 | "type": "basic", 110 | "basic": { 111 | "username": "{{username}}", 112 | "password": "{{token}}" 113 | } 114 | }, 115 | "method": "GET", 116 | "header": [], 117 | "body": {}, 118 | "url": "https://postman-echo.com/get", 119 | "description": "" 120 | }, 121 | "response": [] 122 | } 123 | ] 124 | }, 125 | { 126 | "name": "OAuth1", 127 | "variable": [{ 128 | "key": "request", 129 | "value": "variable", 130 | "type": "string", 131 | "description": "This is a request level variable" 132 | }], 133 | "event": [ 134 | { 135 | "listen": "test", 136 | "script": { 137 | "type": "text/javascript", 138 | "exec": [ 139 | "console.log('Request level test script');" 140 | ] 141 | } 142 | }, 143 | { 144 | "listen": "prerequest", 145 | "script": { 146 | "type": "text/javascript", 147 | "exec": [ 148 | "console.log('Request level pre request script');" 149 | ] 150 | } 151 | } 152 | ], 153 | "request": { 154 | "auth": { 155 | "type": "oauth1", 156 | "oauth1": { 157 | "consumerKey": "RKCGzna7bv9YD57c", 158 | "consumerSecret": "D+EdQ-gs$-%@2Nu7", 159 | "token": "", 160 | "tokenSecret": "", 161 | "signatureMethod": "HMAC-SHA1", 162 | "timestamp": "1500452534", 163 | "nonce": "S0kXloMHurS", 164 | "version": "1.0", 165 | "realm": "", 166 | "addParamsToHeader": false, 167 | "addEmptyParamsToSign": false 168 | } 169 | }, 170 | "method": "GET", 171 | "header": [], 172 | "body": {}, 173 | "url": "https://postman-echo.com/get", 174 | "description": "" 175 | }, 176 | "response": [] 177 | } 178 | ] 179 | } 180 | -------------------------------------------------------------------------------- /examples/v2.0.0/no-body.json: -------------------------------------------------------------------------------- 1 | { 2 | "info": { 3 | "id": "5aff34b9-a2af-4579-8b05-8f3dfea35fe1", 4 | "name": "A collection", 5 | "schema": "https://schema.getpostman.com/json/collection/v2.0.0/collection.json" 6 | }, 7 | "event": [], 8 | "variable": [], 9 | "item": [ 10 | { 11 | "id": "d66ea01e-803d-4827-91dc-adf1f379d508", 12 | "name": "Request", 13 | "request": { 14 | "url": "http://echo.postman.com", 15 | "method": "GET" 16 | }, 17 | "response": [], 18 | "event": [] 19 | } 20 | ] 21 | } 22 | -------------------------------------------------------------------------------- /examples/v2.0.0/proper-url-parsing.json: -------------------------------------------------------------------------------- 1 | { 2 | "variable": [], 3 | "info": { 4 | "name": "proper-url-parsing", 5 | "_postman_id": "7ea31a30-8377-0e56-d11f-5943e6527bca", 6 | "description": "Description", 7 | "schema": "https://schema.getpostman.com/json/collection/v2.0.0/collection.json" 8 | }, 9 | "item": [ 10 | { 11 | "id": "2c03f359-f259-bb30-d14c-ea278056e95f", 12 | "name": "request with hostname as variable", 13 | "request": { 14 | "url": { 15 | "raw": "https://ani{{yo}}ket:{{asd}}@{{hellohost}}:2002/crazyvar/{{yo}}/:awesome?a=b&c=d#/awesomeshit", 16 | "protocol": "https", 17 | "auth": { 18 | "user": "ani{{yo}}ket", 19 | "password": "{{asd}}" 20 | }, 21 | "host": [ 22 | "{{hellohost}}" 23 | ], 24 | "port": "2002", 25 | "path": [ 26 | "crazyvar", 27 | "{{yo}}", 28 | ":awesome" 29 | ], 30 | "query": [ 31 | { 32 | "key": "a", 33 | "value": "b" 34 | }, 35 | { 36 | "key": "c", 37 | "value": "d" 38 | } 39 | ], 40 | "hash": "/awesomeshit", 41 | "variable": [] 42 | }, 43 | "method": "GET", 44 | "header": [], 45 | "body": { 46 | "mode": "formdata", 47 | "formdata": [] 48 | }, 49 | "description": "Description" 50 | }, 51 | "response": [] 52 | } 53 | ] 54 | } 55 | -------------------------------------------------------------------------------- /examples/v2.0.0/rawjsonbody.json: -------------------------------------------------------------------------------- 1 | { 2 | "variable": [], 3 | "info": { 4 | "name": "rawjsonbody", 5 | "_postman_id": "c96a1f4e-f2e8-ed1f-3421-e16568f4b471", 6 | "description": "Description", 7 | "schema": "https://schema.getpostman.com/json/collection/v2.0.0/collection.json" 8 | }, 9 | "item": [ 10 | { 11 | "id": "8f444706-d8cc-9196-ee18-e0c7c3627df3", 12 | "name": "httpbin.org/post", 13 | "request": { 14 | "url": { 15 | "raw": "httpbin.org/:method", 16 | "auth": {}, 17 | "host": [ 18 | "httpbin", 19 | "org" 20 | ], 21 | "path": [ 22 | ":method" 23 | ], 24 | "variable": [ 25 | { 26 | "value": "post", 27 | "id": "method" 28 | } 29 | ] 30 | }, 31 | "method": "POST", 32 | "header": [ 33 | { 34 | "key": "Content-Type", 35 | "value": "application/json", 36 | "description": "Description" 37 | } 38 | ], 39 | "body": { 40 | "mode": "raw", 41 | "raw": "{\n \"asd\": \"tyyy\"\n}" 42 | }, 43 | "description": "Description" 44 | }, 45 | "response": [] 46 | } 47 | ] 48 | } 49 | -------------------------------------------------------------------------------- /examples/v2.0.0/urlencoded-post-data.json: -------------------------------------------------------------------------------- 1 | { 2 | "variable": [], 3 | "info": { 4 | "name": "urlencodeddata", 5 | "_postman_id": "551c1361-2b81-68c7-677e-ec2efdd8322e", 6 | "description": "Description", 7 | "schema": "https://schema.getpostman.com/json/collection/v2.0.0/collection.json" 8 | }, 9 | "item": [ 10 | { 11 | "id": "b7fe1cf7-22bb-93f2-f058-3b4cdbf965b7", 12 | "name": "http://httpbin.org/post", 13 | "request": { 14 | "url": { 15 | "raw": "http://httpbin.org/post", 16 | "protocol": "http", 17 | "auth": {}, 18 | "host": [ 19 | "httpbin", 20 | "org" 21 | ], 22 | "path": [ 23 | "post" 24 | ], 25 | "variable": [] 26 | }, 27 | "method": "POST", 28 | "header": [], 29 | "body": { 30 | "mode": "urlencoded", 31 | "urlencoded": [ 32 | { 33 | "key": "akshay", 34 | "value": "bald", 35 | "type": "text", 36 | "enabled": true 37 | }, 38 | { 39 | "key": "yakshay", 40 | "value": "ybald", 41 | "type": "text", 42 | "enabled": true 43 | } 44 | ] 45 | }, 46 | "description": "Description" 47 | }, 48 | "response": [ 49 | { 50 | "name": "samplerespose", 51 | "originalRequest": { 52 | "url": "http://httpbin.org/post", 53 | "method": "POST", 54 | "header": [ 55 | { 56 | "key": "Cache-Control", 57 | "name": "Cache-Control", 58 | "value": "no-cache" 59 | }, 60 | { 61 | "key": "Postman-Token", 62 | "name": "Postman-Token", 63 | "value": "e8826f9c-70fa-0957-fe12-265257861623" 64 | }, 65 | { 66 | "key": "Content-Type", 67 | "name": "Content-Type", 68 | "value": "application/x-www-form-urlencoded" 69 | } 70 | ], 71 | "body": { 72 | "mode": "urlencoded", 73 | "urlencoded": [ 74 | { 75 | "key": "akshay", 76 | "value": "bald" 77 | }, 78 | { 79 | "key": "yakshay", 80 | "value": "ybald" 81 | } 82 | ] 83 | } 84 | }, 85 | "status": "OK", 86 | "code": 200, 87 | "header": [ 88 | { 89 | "name": "Access-Control-Allow-Credentials", 90 | "key": "Access-Control-Allow-Credentials", 91 | "value": "true", 92 | "description": "Indicates whether or not the response to the request can be exposed when the credentials flag is true. When used as part of a response to a preflight request, this indicates whether or not the actual request can be made using credentials." 93 | }, 94 | { 95 | "name": "Access-Control-Allow-Origin", 96 | "key": "Access-Control-Allow-Origin", 97 | "value": "chrome-extension://aicmkgpgakddgnaphhhpliifpcfhicfo", 98 | "description": "Specifies a URI that may access the resource. For requests without credentials, the server may specify '*' as a wildcard, thereby allowing any origin to access the resource." 99 | }, 100 | { 101 | "name": "Connection", 102 | "key": "Connection", 103 | "value": "keep-alive", 104 | "description": "Options that are desired for the connection" 105 | }, 106 | { 107 | "name": "Content-Length", 108 | "key": "Content-Length", 109 | "value": "768", 110 | "description": "The length of the response body in octets (8-bit bytes)" 111 | }, 112 | { 113 | "name": "Content-Type", 114 | "key": "Content-Type", 115 | "value": "application/json", 116 | "description": "The mime type of this content" 117 | }, 118 | { 119 | "name": "Date", 120 | "key": "Date", 121 | "value": "Thu, 11 Feb 2016 13:27:33 GMT", 122 | "description": "The date and time that the message was sent" 123 | }, 124 | { 125 | "name": "Server", 126 | "key": "Server", 127 | "value": "nginx", 128 | "description": "A name for the server" 129 | } 130 | ], 131 | "cookie": [], 132 | "responseTime": 925, 133 | "body": "{\n \"args\": {}, \n \"data\": \"\", \n \"files\": {}, \n \"form\": {\n \"akshay\": \"bald\", \n \"yakshay\": \"ybald\"\n }, \n \"headers\": {\n \"Accept\": \"*/*\", \n \"Accept-Encoding\": \"gzip\", \n \"Accept-Language\": \"en-US,en;q=0.8\", \n \"Cache-Control\": \"no-cache\", \n \"Content-Length\": \"25\", \n \"Content-Type\": \"application/x-www-form-urlencoded\", \n \"Cookie\": \"_ga=GA1.2.113558537.1435817423\", \n \"Host\": \"httpbin.org\", \n \"Origin\": \"chrome-extension://aicmkgpgakddgnaphhhpliifpcfhicfo\", \n \"Postman-Token\": \"e8826f9c-70fa-0957-fe12-265257861623\", \n \"User-Agent\": \"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/48.0.2564.109 Safari/537.36\"\n }, \n \"json\": null, \n \"origin\": \"106.51.38.69\", \n \"url\": \"http://httpbin.org/post\"\n}\n" 134 | } 135 | ] 136 | } 137 | ] 138 | } 139 | -------------------------------------------------------------------------------- /examples/v2.1.0/binary-upload.json: -------------------------------------------------------------------------------- 1 | { 2 | "variable": [], 3 | "info": { 4 | "name": "asdasdasdasdasdasd", 5 | "_postman_id": "70fa9b38-91c0-7e67-0ead-b31622bdc152", 6 | "description": "Description", 7 | "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json" 8 | }, 9 | "item": [ 10 | { 11 | "_postman_id": "cc0e1894-bad7-aeeb-e91c-e74635371614", 12 | "name": "http://httpbin.org/post", 13 | "event": [ 14 | { 15 | "listen": "test", 16 | "script": { 17 | "type": "text/javascript", 18 | "exec": [ 19 | "console.log(responseBody)" 20 | ] 21 | } 22 | } 23 | ], 24 | "request": { 25 | "url": "http://echo.postman.com/post", 26 | "method": "POST", 27 | "header": [], 28 | "body": { 29 | "mode": "file", 30 | "file": { 31 | "src": "sample.txt" 32 | } 33 | }, 34 | "description": "Description" 35 | }, 36 | "response": [] 37 | } 38 | ] 39 | } 40 | -------------------------------------------------------------------------------- /examples/v2.1.0/nestedEntities.json: -------------------------------------------------------------------------------- 1 | { 2 | "info": { 3 | "name": "auth-v1", 4 | "_postman_id": "46da69ac-9035-50c4-fcab-44d9167e06f4", 5 | "description": "A simple V1 collection to elucidate nested auth helpers, variables, and scripts", 6 | "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json" 7 | }, 8 | "variable": [{ 9 | "key": "collection", 10 | "value": "variable", 11 | "type": "string", 12 | "description": "This is a collection level variable" 13 | }], 14 | "auth": { 15 | "type": "basic", 16 | "basic": [ 17 | { 18 | "key": "username", 19 | "value": "{{username}}", 20 | "type": "string" 21 | }, 22 | { 23 | "key": "password", 24 | "value": "{{token}}", 25 | "type": "string" 26 | } 27 | ] 28 | }, 29 | "event": [ 30 | { 31 | "listen": "test", 32 | "script": { 33 | "type": "text/javascript", 34 | "exec": [ 35 | "console.log('Collection level test script');" 36 | ] 37 | } 38 | }, 39 | { 40 | "listen": "prerequest", 41 | "script": { 42 | "type": "text/javascript", 43 | "exec": [ 44 | "console.log('Collection level pre request script');" 45 | ] 46 | } 47 | } 48 | ], 49 | "item": [ 50 | { 51 | "name": "F1", 52 | "description": "Folder 1", 53 | "variable": [{ 54 | "key": "folder", 55 | "value": "variable", 56 | "type": "string", 57 | "description": "This is a folder level variable" 58 | }], 59 | "auth": { 60 | "type": "basic", 61 | "basic": [ 62 | { 63 | "key": "username", 64 | "value": "{{username}}", 65 | "type": "string" 66 | }, 67 | { 68 | "key": "password", 69 | "value": "{{token}}", 70 | "type": "string" 71 | } 72 | ] 73 | }, 74 | "event": [ 75 | { 76 | "listen": "test", 77 | "script": { 78 | "type": "text/javascript", 79 | "exec": [ 80 | "console.log('Folder level test script');" 81 | ] 82 | } 83 | }, 84 | { 85 | "listen": "prerequest", 86 | "script": { 87 | "type": "text/javascript", 88 | "exec": [ 89 | "console.log('Folder level pre request script');" 90 | ] 91 | } 92 | } 93 | ], 94 | "item": [ 95 | { 96 | "name": "Basic", 97 | "variable": [{ 98 | "key": "request", 99 | "value": "variable", 100 | "type": "string", 101 | "description": "This is a request level variable" 102 | }], 103 | "event": [ 104 | { 105 | "listen": "test", 106 | "script": { 107 | "type": "text/javascript", 108 | "exec": [ 109 | "console.log('Request level test script');" 110 | ] 111 | } 112 | }, 113 | { 114 | "listen": "prerequest", 115 | "script": { 116 | "type": "text/javascript", 117 | "exec": [ 118 | "console.log('Request level pre request script');" 119 | ] 120 | } 121 | } 122 | ], 123 | "request": { 124 | "auth": { 125 | "type": "basic", 126 | "basic": [ 127 | { 128 | "key": "username", 129 | "value": "{{username}}", 130 | "type": "string" 131 | }, 132 | { 133 | "key": "password", 134 | "value": "{{token}}", 135 | "type": "string" 136 | } 137 | ] 138 | }, 139 | "method": "GET", 140 | "header": [], 141 | "body": {}, 142 | "url": "https://postman-echo.com/get", 143 | "description": "" 144 | }, 145 | "response": [] 146 | } 147 | ] 148 | }, 149 | { 150 | "name": "OAuth1", 151 | "variable": [{ 152 | "key": "request", 153 | "value": "variable", 154 | "type": "string", 155 | "description": "This is a request level variable" 156 | }], 157 | "event": [ 158 | { 159 | "listen": "test", 160 | "script": { 161 | "type": "text/javascript", 162 | "exec": [ 163 | "console.log('Request level test script');" 164 | ] 165 | } 166 | }, 167 | { 168 | "listen": "prerequest", 169 | "script": { 170 | "type": "text/javascript", 171 | "exec": [ 172 | "console.log('Request level pre request script');" 173 | ] 174 | } 175 | } 176 | ], 177 | "request": { 178 | "auth": { 179 | "type": "oauth1", 180 | "oauth1": [ 181 | { 182 | "key": "consumerKey", 183 | "value": "RKCGzna7bv9YD57c", 184 | "type": "string" 185 | }, 186 | { 187 | "key": "consumerSecret", 188 | "value": "D+EdQ-gs$-%@2Nu7", 189 | "type": "string" 190 | }, 191 | { 192 | "key": "token", 193 | "value": "", 194 | "type": "string" 195 | }, 196 | { 197 | "key": "tokenSecret", 198 | "value": "", 199 | "type": "string" 200 | }, 201 | { 202 | "key": "signatureMethod", 203 | "value": "HMAC-SHA1", 204 | "type": "string" 205 | }, 206 | { 207 | "key": "timestamp", 208 | "value": "1500452534", 209 | "type": "string" 210 | }, 211 | { 212 | "key": "nonce", 213 | "value": "S0kXloMHurS", 214 | "type": "string" 215 | }, 216 | { 217 | "key": "version", 218 | "value": "1.0", 219 | "type": "string" 220 | }, 221 | { 222 | "key": "realm", 223 | "value": "", 224 | "type": "string" 225 | } 226 | ] 227 | }, 228 | "method": "GET", 229 | "header": [], 230 | "body": {}, 231 | "url": "https://postman-echo.com/get", 232 | "description": "" 233 | }, 234 | "response": [] 235 | } 236 | ] 237 | } 238 | -------------------------------------------------------------------------------- /examples/v2.1.0/proper-description-parsing.json: -------------------------------------------------------------------------------- 1 | { 2 | "variable": [], 3 | "info": { 4 | "name": "proper-description-parsing", 5 | "_postman_id": "7ea31a30-8377-0e56-d11f-5943e6527bca", 6 | "description": { 7 | "content": "V2 supported collection description in object format", 8 | "type": "text/plain" 9 | }, 10 | "schema": "https://schema.getpostman.com/json/collection/v2.0.0/collection.json" 11 | }, 12 | "item": [ 13 | { 14 | "id": "2c03f359-f259-bb30-d14c-ea278056e95f", 15 | "name": "request with hostname as variable", 16 | "request": { 17 | "url": { 18 | "raw": "https://ani{{yo}}ket:{{asd}}@{{hellohost}}:2002/crazyvar/{{yo}}/:awesome?a=b&c=d#/awesomeshit", 19 | "protocol": "https", 20 | "auth": { 21 | "user": "ani{{yo}}ket", 22 | "password": "{{asd}}" 23 | }, 24 | "host": [ 25 | "{{hellohost}}" 26 | ], 27 | "port": "2002", 28 | "path": [ 29 | "crazyvar", 30 | "{{yo}}", 31 | ":awesome" 32 | ], 33 | "query": [ 34 | { 35 | "key": "a", 36 | "value": "b" 37 | }, 38 | { 39 | "key": "c", 40 | "value": "d" 41 | } 42 | ], 43 | "hash": "/awesomeshit", 44 | "variable": [] 45 | }, 46 | "method": "GET", 47 | "header": [], 48 | "body": { 49 | "mode": "formdata", 50 | "formdata": [] 51 | }, 52 | "description": { 53 | "content": "V2 supported request description in object format", 54 | "type": "text/plain" 55 | } 56 | }, 57 | "response": [] 58 | } 59 | ] 60 | } 61 | -------------------------------------------------------------------------------- /examples/v2.1.0/proper-url-parsing.json: -------------------------------------------------------------------------------- 1 | { 2 | "variable": [], 3 | "info": { 4 | "name": "proper-url-parsing", 5 | "_postman_id": "7ea31a30-8377-0e56-d11f-5943e6527bca", 6 | "description": "Description", 7 | "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json" 8 | }, 9 | "item": [ 10 | { 11 | "name": "request with hostname as variable", 12 | "request": { 13 | "url": "https://ani{{yo}}ket:{{asd}}@{{hellohost}}:2002/crazyvar/{{yo}}/:awesome?a=b&c=d#/awesomeshit", 14 | "method": "GET", 15 | "headers": [], 16 | "body": { 17 | "mode": "formdata", 18 | "formdata": [] 19 | }, 20 | "description": "Description" 21 | }, 22 | "responses": [] 23 | } 24 | ] 25 | } 26 | -------------------------------------------------------------------------------- /examples/v2.1.0/rawjsonbody.json: -------------------------------------------------------------------------------- 1 | { 2 | "variable": [], 3 | "info": { 4 | "name": "rawjsonbody", 5 | "_postman_id": "c96a1f4e-f2e8-ed1f-3421-e16568f4b471", 6 | "description": "Description", 7 | "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json" 8 | }, 9 | "item": [ 10 | { 11 | "name": "httpbin.org/post", 12 | "request": { 13 | "url": { 14 | "raw": "httpbin.org/:method", 15 | "auth": {}, 16 | "host": [ 17 | "httpbin", 18 | "org" 19 | ], 20 | "path": [ 21 | ":method" 22 | ], 23 | "variable": [ 24 | { 25 | "value": "post", 26 | "id": "method" 27 | } 28 | ] 29 | }, 30 | "method": "POST", 31 | "headers": [ 32 | { 33 | "key": "Content-Type", 34 | "value": "application/json", 35 | "description": "Description" 36 | } 37 | ], 38 | "body": { 39 | "mode": "raw", 40 | "raw": "{\n \"asd\": \"tyyy\"\n}" 41 | }, 42 | "description": "Description" 43 | }, 44 | "responses": [] 45 | } 46 | ] 47 | } 48 | -------------------------------------------------------------------------------- /examples/v2.1.0/urlencoded-post-data.json: -------------------------------------------------------------------------------- 1 | { 2 | "variable": [], 3 | "info": { 4 | "name": "urlencodeddata", 5 | "_postman_id": "551c1361-2b81-68c7-677e-ec2efdd8322e", 6 | "description": "Description", 7 | "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json" 8 | }, 9 | "item": [ 10 | { 11 | "name": "http://httpbin.org/post", 12 | "request": { 13 | "url": "http://httpbin.org/post", 14 | "method": "POST", 15 | "headers": [], 16 | "body": { 17 | "mode": "urlencoded", 18 | "urlencoded": [ 19 | { 20 | "key": "akshay", 21 | "value": "bald", 22 | "type": "text", 23 | "enabled": true 24 | }, 25 | { 26 | "key": "yakshay", 27 | "value": "ybald", 28 | "type": "text", 29 | "enabled": true 30 | } 31 | ] 32 | }, 33 | "description": "Description" 34 | }, 35 | "responses": [ 36 | { 37 | "name": "samplerespose", 38 | "originalRequest": { 39 | "url": "http://httpbin.org/post", 40 | "method": "POST", 41 | "headers": [ 42 | { 43 | "key": "Cache-Control", 44 | "name": "Cache-Control", 45 | "value": "no-cache" 46 | }, 47 | { 48 | "key": "Postman-Token", 49 | "name": "Postman-Token", 50 | "value": "e8826f9c-70fa-0957-fe12-265257861623" 51 | }, 52 | { 53 | "key": "Content-Type", 54 | "name": "Content-Type", 55 | "value": "application/x-www-form-urlencoded" 56 | } 57 | ], 58 | "body": { 59 | "mode": "urlencoded", 60 | "urlencoded": [ 61 | { 62 | "key": "akshay", 63 | "value": "bald" 64 | }, 65 | { 66 | "key": "yakshay", 67 | "value": "ybald" 68 | } 69 | ] 70 | } 71 | }, 72 | "status": "OK", 73 | "code": 200, 74 | "_postman_previewlanguage": "javascript", 75 | "_postman_previewtype": "html", 76 | "header": [ 77 | { 78 | "name": "Access-Control-Allow-Credentials", 79 | "key": "Access-Control-Allow-Credentials", 80 | "value": "true", 81 | "description": "Indicates whether or not the response to the request can be exposed when the credentials flag is true. When used as part of a response to a preflight request, this indicates whether or not the actual request can be made using credentials." 82 | }, 83 | { 84 | "name": "Access-Control-Allow-Origin", 85 | "key": "Access-Control-Allow-Origin", 86 | "value": "chrome-extension://aicmkgpgakddgnaphhhpliifpcfhicfo", 87 | "description": "Specifies a URI that may access the resource. For requests without credentials, the server may specify '*' as a wildcard, thereby allowing any origin to access the resource." 88 | }, 89 | { 90 | "name": "Connection", 91 | "key": "Connection", 92 | "value": "keep-alive", 93 | "description": "Options that are desired for the connection" 94 | }, 95 | { 96 | "name": "Content-Length", 97 | "key": "Content-Length", 98 | "value": "768", 99 | "description": "The length of the response body in octets (8-bit bytes)" 100 | }, 101 | { 102 | "name": "Content-Type", 103 | "key": "Content-Type", 104 | "value": "application/json", 105 | "description": "The mime type of this content" 106 | }, 107 | { 108 | "name": "Date", 109 | "key": "Date", 110 | "value": "Thu, 11 Feb 2016 13:27:33 GMT", 111 | "description": "The date and time that the message was sent" 112 | }, 113 | { 114 | "name": "Server", 115 | "key": "Server", 116 | "value": "nginx", 117 | "description": "A name for the server" 118 | } 119 | ], 120 | "cookie": [], 121 | "responseTime": 925, 122 | "body": "{\n \"args\": {}, \n \"data\": \"\", \n \"files\": {}, \n \"form\": {\n \"akshay\": \"bald\", \n \"yakshay\": \"ybald\"\n }, \n \"headers\": {\n \"Accept\": \"*/*\", \n \"Accept-Encoding\": \"gzip\", \n \"Accept-Language\": \"en-US,en;q=0.8\", \n \"Cache-Control\": \"no-cache\", \n \"Content-Length\": \"25\", \n \"Content-Type\": \"application/x-www-form-urlencoded\", \n \"Cookie\": \"_ga=GA1.2.113558537.1435817423\", \n \"Host\": \"httpbin.org\", \n \"Origin\": \"chrome-extension://aicmkgpgakddgnaphhhpliifpcfhicfo\", \n \"Postman-Token\": \"e8826f9c-70fa-0957-fe12-265257861623\", \n \"User-Agent\": \"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/48.0.2564.109 Safari/537.36\"\n }, \n \"json\": null, \n \"origin\": \"106.51.38.69\", \n \"url\": \"http://httpbin.org/post\"\n}\n" 123 | } 124 | ] 125 | } 126 | ] 127 | } 128 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @module transformer 3 | */ 4 | module.exports = require('./lib'); 5 | -------------------------------------------------------------------------------- /lib/common/v1.js: -------------------------------------------------------------------------------- 1 | var _ = require('lodash').noConflict(), 2 | 3 | regexes = { 4 | fold: /\r\n([ \t])/g, 5 | trim: /^\s*(.*\S)?\s*$/, // eslint-disable-line security/detect-unsafe-regex 6 | header: /^((\/\/\s*)?\S+):(.*)$/gm // eslint-disable-line security/detect-unsafe-regex 7 | }, 8 | headersCommentPrefix = '//'; 9 | 10 | module.exports = { 11 | authMap: { 12 | apikeyAuth: 'apikey', 13 | basicAuth: 'basic', 14 | bearerAuth: 'bearer', 15 | digestAuth: 'digest', 16 | hawkAuth: 'hawk', 17 | oAuth1: 'oauth1', 18 | oAuth2: 'oauth2', 19 | ntlmAuth: 'ntlm', 20 | awsSigV4: 'awsv4', 21 | jwtAuth: 'jwt', 22 | asapAuth: 'asap', 23 | edgegridAuth: 'edgegrid', 24 | normal: null 25 | }, 26 | 27 | /** 28 | * Parses a string of headers to an object. 29 | * 30 | * @param {String} data - A string of newline concatenated header key-value pairs. 31 | * @param {?Boolean} [legacy] - A flag to indicate whether the parsing is being done for v1 normalization or v1 to 32 | * v2 conversion. 33 | * @returns {Object[]|*} - The parsed list of header key-value pair objects. 34 | * @private 35 | */ 36 | parseHeaders: function (data, legacy) { 37 | if (!data) { return; } 38 | 39 | var head, 40 | headers = [], 41 | statusValue = !legacy, 42 | match = regexes.header.exec(data), 43 | property = legacy ? 'enabled' : 'disabled'; 44 | 45 | data = data.toString().replace(regexes.fold, '$1'); 46 | 47 | while (match) { 48 | head = { 49 | key: match[1], 50 | value: match[3].replace(regexes.trim, '$1') 51 | }; 52 | 53 | if (_.startsWith(head.key, headersCommentPrefix)) { 54 | head[property] = statusValue; 55 | head.key = head.key.replace(headersCommentPrefix, '').trim(); 56 | } 57 | 58 | headers.push(head); 59 | match = regexes.header.exec(data); 60 | } 61 | 62 | return headers; 63 | } 64 | }; 65 | -------------------------------------------------------------------------------- /lib/common/v2.js: -------------------------------------------------------------------------------- 1 | var _ = require('lodash').noConflict(), 2 | util = require('../util'), 3 | 4 | /** 5 | * Replenishes missing ids in v2.0.0.x collections. 6 | * 7 | * @param {*} currentItem - A collection entity on which to check for ids. 8 | * @returns {Object|*} - The updated item, with the correct id fields in place. 9 | */ 10 | populateIds = function (currentItem) { 11 | if (!currentItem) { return; } 12 | 13 | // ID sanitization 14 | if (currentItem._postman_id) { 15 | currentItem.id = currentItem._postman_id; 16 | delete currentItem._postman_id; 17 | } 18 | 19 | !currentItem.id && (currentItem.id = util.uid()); 20 | 21 | if (currentItem.response && currentItem.response.length) { 22 | _.forEach(currentItem.response, populateIds); 23 | } 24 | 25 | if (currentItem.responses && currentItem.responses.length) { 26 | _.forEach(currentItem.responses, populateIds); 27 | } 28 | 29 | var itemArray = currentItem.items || currentItem.item; 30 | 31 | itemArray && itemArray.length && _.forEach(itemArray, populateIds); 32 | 33 | return currentItem; 34 | }; 35 | 36 | module.exports = { 37 | authMap: { 38 | apikey: 'apikeyAuth', 39 | basic: 'basicAuth', 40 | bearer: 'bearerAuth', 41 | digest: 'digestAuth', 42 | hawk: 'hawkAuth', 43 | oauth1: 'oAuth1', 44 | oauth2: 'oAuth2', 45 | ntlm: 'ntlmAuth', 46 | awsv4: 'awsSigV4', 47 | jwt: 'jwtAuth', 48 | asap: 'asapAuth', 49 | edgegrid: 'edgegridAuth', 50 | noauth: null 51 | }, 52 | modeMap: { 53 | file: 'binary', 54 | formdata: 'params', 55 | graphql: 'graphql', 56 | raw: 'raw', 57 | urlencoded: 'urlencoded' 58 | }, 59 | populateIds: populateIds 60 | }; 61 | -------------------------------------------------------------------------------- /lib/constants.js: -------------------------------------------------------------------------------- 1 | exports.SCHEMA_V2_URL = 'https://schema.getpostman.com/json/collection/v2.0.0/collection.json'; 2 | exports.SCHEMA_V2_1_0_URL = 'https://schema.getpostman.com/json/collection/v2.1.0/collection.json'; 3 | exports.SCHEMA_V1_URL = 'https://schema.getpostman.com/json/collection/v1.0.0/collection.json'; 4 | exports.PREREQUEST_EXT = '_preRequestScript'; 5 | exports.TESTS_EXT = '_tests'; 6 | -------------------------------------------------------------------------------- /lib/converters/index.js: -------------------------------------------------------------------------------- 1 | var semver = require('semver'), 2 | FN = 'function', 3 | generateConverter; // constructor 4 | 5 | /** 6 | * Prototype interface definition of a converter 7 | * 8 | * @param {Object} model - A manifest that defines the conversion process. 9 | * @param {String} model.input - The input version to convert from. 10 | * @param {String} model.output - The output version to convert to. 11 | * @param {Function} model.convert - A function to convert entire collections. 12 | * @param {Function} model.create - A function to perform creation operations. 13 | * @param {Function} [model.init] - An initializer function to bootstrap the generated converter. 14 | * 15 | * @throws {Error} If model definition does not meet requirements 16 | */ 17 | generateConverter = function (model) { 18 | var error; 19 | 20 | // validate the model 21 | if (!model) { 22 | error = 'invalid definition of converter'; 23 | } 24 | // ensure that the input version support is a valid semver 25 | else if (!semver.valid(model.input)) { 26 | error = 'input version support for converter is invalid'; 27 | } 28 | // ensure that the output version support is a valid semver 29 | else if (!semver.valid(model.output)) { 30 | error = 'output version support for converter is invalid'; 31 | } 32 | else if (typeof model.convert !== FN) { 33 | error = 'convert function is not defined'; 34 | } 35 | else if (typeof model.convertSingle !== FN) { 36 | error = 'convertSingle function is not defined'; 37 | } 38 | 39 | if (semver.satisfies(model.input, model.output)) { 40 | error = 'input version ' + model.input + ' matches output version ' + model.output + ' for converter'; 41 | } 42 | 43 | // If we had encountered any error during validation, we simply exit by executing the callback and forwarding the 44 | // error. 45 | if (error) { 46 | throw new Error(error); 47 | } 48 | 49 | return model; 50 | }; 51 | 52 | module.exports = { 53 | /** 54 | * All converters 55 | * 56 | * @type {object} 57 | * 58 | * @note this form of loading is most likely not browser friendly, find browser alternative 59 | */ 60 | converters: { 61 | 'converter-v1-to-v2': require('./v1.0.0/converter-v1-to-v2'), 62 | 'converter-v1-to-v21': require('./v1.0.0/converter-v1-to-v21'), 63 | 'converter-v2-to-v1': require('./v2.0.0/converter-v2-to-v1'), 64 | 'converter-v21-to-v1': require('./v2.1.0/converter-v21-to-v1') 65 | }, 66 | 67 | /** 68 | * Fetches a converter for the given input and output versions 69 | * 70 | * @param {String} inputVersion - The version to convert from. 71 | * @param {String} outputVersion - The version to convert to. 72 | * @returns {Converter} - A converter for the given set of options. 73 | */ 74 | getConverter: function (inputVersion, outputVersion) { 75 | var converter; 76 | 77 | inputVersion = semver.clean(inputVersion); 78 | outputVersion = semver.clean(outputVersion); 79 | 80 | for (converter in this.converters) { 81 | // eslint-disable-next-line no-prototype-builtins 82 | converter = this.converters.hasOwnProperty(converter) && this.converters[converter]; 83 | if (converter && semver.eq(converter.input, inputVersion) && semver.eq(converter.output, outputVersion)) { 84 | return generateConverter(converter); 85 | } 86 | } 87 | }, 88 | 89 | /** 90 | * Picks the appropriate converter and converts the given collection. 91 | * 92 | * @param {Object} collection - The collection to be converted. 93 | * @param {Object} options - The set of options for request conversion. 94 | * @param {Function} callback - The function to be invoked after the completion of conversion process. 95 | */ 96 | convert: function (collection, options, callback) { 97 | var chosenConverter = this.getConverter(options.inputVersion, options.outputVersion); 98 | 99 | if (!chosenConverter) { 100 | return callback(new Error('no conversion path found')); 101 | } 102 | 103 | return chosenConverter.convert(collection, options, callback); 104 | }, 105 | 106 | /** 107 | * Picks the appropriate converter and converts the given object. 108 | * 109 | * @param {Object} object - A single V1 request or a V2 Item. 110 | * @param {Object} options - The set of options for request conversion. 111 | * @param {Function} callback - The function to be invoked after the completion of conversion process. 112 | */ 113 | convertSingle: function (object, options, callback) { 114 | var chosenConverter = this.getConverter(options.inputVersion, options.outputVersion); 115 | 116 | if (!chosenConverter) { 117 | return callback(new Error('no conversion path found')); 118 | } 119 | 120 | return chosenConverter.convertSingle(object, options, callback); 121 | }, 122 | 123 | /** 124 | * Picks the appropriate converter and converts the given object. 125 | * 126 | * @param {Object} object - A single V1 Response or a V2 Response. 127 | * @param {Object} options - The set of options for response conversion. 128 | * @param {Function} callback - The function invoked to mark the completion of the conversion process. 129 | * @returns {*} 130 | */ 131 | convertResponse: function (object, options, callback) { 132 | var chosenConverter = this.getConverter(options.inputVersion, options.outputVersion); 133 | 134 | if (!chosenConverter) { 135 | return callback(new Error('no conversion path found')); 136 | } 137 | 138 | return chosenConverter.convertResponse(object, options, callback); 139 | }, 140 | 141 | /** 142 | * Returns a builder, which can be used to convert individual requests, etc. 143 | * 144 | * @param {Object} options - The set of options for builder creation. 145 | * @returns {Function} - The builder for the given set of options. 146 | */ 147 | builder: function (options) { 148 | var chosenConverter = this.getConverter(options.inputVersion, options.outputVersion); 149 | 150 | return chosenConverter.create(options); 151 | } 152 | }; 153 | -------------------------------------------------------------------------------- /lib/converters/v1.0.0/converter-v1-to-v21.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable object-shorthand */ 2 | 3 | var inherits = require('inherits'), 4 | _ = require('lodash').noConflict(), 5 | 6 | url = require('../../url'), 7 | util = require('../../util'), 8 | constants = require('../../constants'), 9 | BaseBuilders = require('./converter-v1-to-v2').Builders, 10 | 11 | Builders; 12 | 13 | inherits(Builders = function () { 14 | Builders.super_.apply(this, arguments); 15 | }, BaseBuilders); 16 | 17 | _.assign(Builders.prototype, { 18 | 19 | /** 20 | * Derives v2.1.0 collection info from a v1.0.0 collection object. 21 | * 22 | * @param {Object} collectionV1 - The v1.0.0 collection object to be converted to v2.1.0. 23 | * @return {Object} - The compiled v2.x collection info manifest. 24 | */ 25 | info: function (collectionV1) { 26 | var info = Builders.super_.prototype.info.call(this, collectionV1); 27 | 28 | info.schema = constants.SCHEMA_V2_1_0_URL; 29 | 30 | return info; 31 | }, 32 | 33 | /** 34 | * Converts collection request urls from v1.0.0 to v2.1.0 35 | * 36 | * @param {Object} requestV1 - The v1.0.0 request url to be converted to v2.1.0. 37 | * @return {Object} - The objectified v2.1.0 compliant URL. 38 | */ 39 | url: function (requestV1) { 40 | var v21Url = Builders.super_.prototype.url.call(this, requestV1); 41 | 42 | return _.isString(v21Url) ? url.parse(v21Url) : v21Url; 43 | }, 44 | 45 | /** 46 | * A number of auth parameter names have changed from V1 to V2. This function calls the appropriate 47 | * mapper function, and creates the V2 auth parameter object. 48 | * 49 | * @param {Object} entityV1 - A Collection V1 compliant request instance. 50 | * @param {?Object} options - The set of options for the current auth cleansing operation. 51 | * @param {?Boolean} [options.includeNoauth=false] - When set to true, noauth is set to null. 52 | * @returns {{type: *}} - The v2.1.0 compliant request object 53 | */ 54 | auth: function (entityV1, options) { 55 | // if the current auth manifest is at a parent level, no further transformation is needed. 56 | // @todo: Possible dead code, prune when confirmed 57 | if (util.notLegacy(entityV1, 'auth') && entityV1.currentHelper) { 58 | return util.sanitizeAuthArray(entityV1, options); 59 | } 60 | 61 | var auth = Builders.super_.prototype.auth.call(this, entityV1, options); 62 | 63 | return util.authMapToArray({ auth: auth }, options); 64 | } 65 | }); 66 | 67 | module.exports = { 68 | input: '1.0.0', 69 | output: '2.1.0', 70 | Builders: Builders, 71 | 72 | /** 73 | * Converts a single V1 request to a v2.1.0 item. 74 | * 75 | * @param {Object} request - The v1.0.0 request to be converted to a v2.1.0 format. 76 | * @param {Object} options - The set of options for the current conversion sequence. 77 | * @param {?Function} callback - The function invoked to mark the end of the current conversion process. 78 | * @returns {*} 79 | */ 80 | convertSingle: function (request, options, callback) { 81 | var err, 82 | converted, 83 | builders = new Builders(options); 84 | 85 | try { converted = builders.singleItem(_.cloneDeep(request)); } 86 | catch (e) { err = e; } 87 | 88 | if (callback) { return callback(err, converted); } 89 | 90 | if (err) { throw err; } 91 | 92 | return converted; 93 | }, 94 | 95 | /** 96 | * Converts a single V1 Response to a v2.1.0 Response. 97 | * 98 | * @param {Object} response - The V1 compliant response to convert to a v2.1.0 format. 99 | * @param {Object} options - The set of options for the current conversion process. 100 | * @param {?Function} callback - The function invoked to mark the completion of the response conversion. 101 | * @returns {*} 102 | */ 103 | convertResponse: function (response, options, callback) { 104 | var err, 105 | converted, 106 | builders = new Builders(options); 107 | 108 | try { converted = builders.singleResponse(_.cloneDeep(response)); } 109 | catch (e) { err = e; } 110 | 111 | if (callback) { return callback(err, converted); } 112 | 113 | if (err) { throw err; } 114 | 115 | return converted; 116 | }, 117 | 118 | /** 119 | * Converts a V1 collection to a V2 collection (performs ID replacement, etc as necessary). 120 | * 121 | * @param {Object} collection - The V1 collection instance to convert to a v2.1.0 format. 122 | * @param {Object} options - The set of options for the current conversion sequence. 123 | * @param {?Function} callback - The function invoked to mark the completion of the conversion process/ 124 | * @returns {*} 125 | */ 126 | convert: function (collection, options, callback) { 127 | collection = _.cloneDeep(collection); 128 | 129 | var auth, 130 | event, 131 | variable, 132 | newCollection = {}, 133 | units = ['info', 'item'], 134 | builders = new Builders(options), 135 | authOptions = { excludeNoauth: true }, 136 | varOpts = options && { fallback: options.env, ...options }; 137 | 138 | try { 139 | units.forEach(function (unit) { 140 | newCollection[unit] = builders[unit](collection); 141 | }); 142 | 143 | (auth = builders.auth(collection, authOptions)) && (newCollection.auth = auth); 144 | (event = builders.event(collection)) && (newCollection.event = event); 145 | (variable = builders.variable(collection, varOpts)) && (newCollection.variable = variable); 146 | util.addProtocolProfileBehavior(collection, newCollection); 147 | } 148 | catch (e) { 149 | if (callback) { return callback(e); } 150 | throw e; 151 | } 152 | 153 | if (callback) { return callback(null, newCollection); } 154 | 155 | return newCollection; 156 | } 157 | }; 158 | -------------------------------------------------------------------------------- /lib/converters/v2.1.0/converter-v21-to-v1.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable object-shorthand */ 2 | var _ = require('lodash').noConflict(), 3 | util = require('../../util'), 4 | inherits = require('inherits'), 5 | 6 | v2Common = require('../../common/v2'), 7 | BaseBuilders = require('../v2.0.0/converter-v2-to-v1').Builders, 8 | 9 | Builders; 10 | 11 | inherits(Builders = function () { 12 | Builders.super_.apply(this, arguments); 13 | }, BaseBuilders); 14 | 15 | _.assign(Builders.prototype, { 16 | /** 17 | * Converts arrays of v2.1 style auth params to their v1.0.0 equivalent objects. 18 | * 19 | * @param {Object} entity - A v2.1 compliant wrapped auth manifest. 20 | * @param {?Object} options - The set of options for the current auth cleansing operation. 21 | * @param {?Boolean} [options.includeNoauth=false] - When set to true, noauth is set to null. 22 | * @returns {Object} - A v1 compliant set of auth helper attributes. 23 | */ 24 | auth: function (entity, options) { 25 | return util.sanitizeAuthArray(entity, options); 26 | } 27 | }); 28 | 29 | module.exports = { 30 | input: '2.1.0', 31 | output: '1.0.0', 32 | Builders: Builders, 33 | 34 | /** 35 | * Converts a single V2 item to a V1 request. 36 | * 37 | * @param {Object} request - The request to be converted. 38 | * @param {Object} options - The set of options for request conversion. 39 | * @param {Function} callback - The function to be invoked after conversion has completed. 40 | */ 41 | convertSingle: function (request, options, callback) { 42 | var err, 43 | converted, 44 | clone = _.cloneDeep(request), 45 | builders = new Builders(options); 46 | 47 | try { 48 | clone = v2Common.populateIds(clone); 49 | converted = builders.request(clone); 50 | } 51 | catch (e) { err = e; } 52 | 53 | if (callback) { return callback(err, converted); } 54 | 55 | if (err) { throw err; } 56 | 57 | return converted; 58 | }, 59 | 60 | /** 61 | * Converts a single V2 item to a V1 request. 62 | * 63 | * @param {Object} response - The response to be converted. 64 | * @param {Object} options - The set of options for request conversion. 65 | * @param {Function} callback - The function to be invoked after conversion has completed. 66 | */ 67 | convertResponse: function (response, options, callback) { 68 | var builders = new Builders(options), 69 | converted, 70 | err; 71 | 72 | try { converted = builders.response(_.cloneDeep(response)); } 73 | catch (e) { err = e; } 74 | 75 | if (callback) { return callback(err, converted); } 76 | 77 | if (err) { throw err; } 78 | 79 | return converted; 80 | }, 81 | 82 | /** 83 | * Converts a V2 collection to a V1 collection (performs ID replacement, etc as necessary). 84 | * 85 | * @param {Object} collection - The collection to be converted. 86 | * @param {Object} options - The set of options for request conversion. 87 | * @param {Function} callback - The function to be invoked after conversion has completed. 88 | */ 89 | convert: function (collection, options, callback) { 90 | collection = _.cloneDeep(collection); 91 | 92 | var auth, 93 | events, 94 | variables, 95 | builders = new Builders(options), 96 | authOptions = { excludeNoauth: true }, 97 | units = ['order', 'folders_order', 'folders', 'requests'], 98 | varOpts = options && 99 | { fallback: options.env, retainIds: options.retainIds, noDefaults: options.noDefaults }, 100 | id = _.get(collection, 'info._postman_id') || _.get(collection, 'info.id'), 101 | info = collection && collection.info, 102 | newCollection = { 103 | id: id && options && options.retainIds ? id : util.uid(), 104 | name: info && info.name 105 | }; 106 | 107 | // ensure that each item has an id 108 | collection = v2Common.populateIds(collection); 109 | try { 110 | // eslint-disable-next-line max-len 111 | newCollection.description = builders.description(info && info.description); 112 | (auth = builders.auth(collection, authOptions)) && (newCollection.auth = auth); 113 | (events = builders.events(collection)) && (newCollection.events = events); 114 | (variables = builders.variables(collection, varOpts)) && (newCollection.variables = variables); 115 | util.addProtocolProfileBehavior(collection, newCollection); 116 | 117 | units.forEach(function (unit) { 118 | newCollection[unit] = builders[unit](collection); 119 | }); 120 | } 121 | catch (e) { 122 | if (callback) { return callback(e, null); } 123 | throw e; 124 | } 125 | 126 | if (callback) { return callback(null, newCollection); } 127 | 128 | return newCollection; 129 | } 130 | }; 131 | -------------------------------------------------------------------------------- /lib/index.js: -------------------------------------------------------------------------------- 1 | var semver = require('semver'), 2 | 3 | util = require('./util'), 4 | converter = require('./converters'), 5 | normalizers = require('./normalizers'); 6 | 7 | module.exports = { 8 | 9 | /** 10 | * Converts a Collection between different versions, based on the given input. 11 | * 12 | * @param {Object} collection - The collection object to be converted. 13 | * @param {Object} options - The set of conversion options. 14 | * @param {String} options.outputVersion - The version to convert to. 15 | * @param {String} options.inputVersion - The version to convert from. 16 | * @param {Function} callback - The function invoked to mark the completion of the conversion process. 17 | */ 18 | convert: function (collection, options, callback) { 19 | if (!options.outputVersion || !semver.valid(options.outputVersion, true)) { 20 | return callback(new Error('Output version not specified or invalid: ' + options.outputVersion)); 21 | } 22 | if (!options.inputVersion || !semver.valid(options.inputVersion, true)) { 23 | return callback(new Error('Input version not specified or invalid: ' + options.inputVersion)); 24 | } 25 | 26 | return converter.convert(collection, options, callback); 27 | }, 28 | 29 | normalize: normalizers.normalize, 30 | normalizeSingle: normalizers.normalizeSingle, 31 | normalizeResponse: normalizers.normalizeResponse, 32 | 33 | /** 34 | * Export the utilities 35 | */ 36 | util: util, 37 | 38 | /** 39 | * Checks whether the given object is a v1 collection 40 | * 41 | * @param {Object} object - The Object to check for v1 collection compliance. 42 | * @returns {Boolean} - A boolean result indicating whether or not the passed object was a v1 collection. 43 | */ 44 | isv1: function (object) { 45 | return Boolean(object && object.name && object.order && object.requests); 46 | }, 47 | 48 | /** 49 | * Checks whether the given object is a v2 collection 50 | * 51 | * @param {Object} object - The Object to check for v2 collection compliance. 52 | * @returns {Boolean} - A boolean result indicating whether or not the passed object was a v2 collection. 53 | */ 54 | isv2: function (object) { 55 | return Boolean(object && object.info && object.info.schema); 56 | }, 57 | 58 | /** 59 | * Converts a single V1 request to a V2 Item, or a V2 item to a single V1 request. 60 | * 61 | * @param {Object} object - A V1 request or a V2 item. 62 | * @param {Object} options - The set of options for response conversion. 63 | * @param {String} options.outputVersion - The version to convert to. 64 | * @param {String} options.inputVersion - The version to convert from. 65 | * @param {Function} callback - The function invoked to mark the completion of the conversion process. 66 | */ 67 | convertSingle: function (object, options, callback) { 68 | if (!options.outputVersion || !semver.valid(options.outputVersion, true)) { 69 | return callback(new Error('Output version not specified or invalid: ' + options.outputVersion)); 70 | } 71 | if (!options.inputVersion || !semver.valid(options.inputVersion, true)) { 72 | return callback(new Error('Input version not specified or invalid: ' + options.inputVersion)); 73 | } 74 | 75 | return converter.convertSingle(object, options, callback); 76 | }, 77 | 78 | /** 79 | * Converts a single V1 request to a V2 Item, or a V2 item to a single V1 request. 80 | * 81 | * @param {Object} object - A V1 request or a V2 item. 82 | * @param {Object} options - The set of options for response conversion. 83 | * @param {String} options.outputVersion - The version to convert to. 84 | * @param {String} options.inputVersion - The version to convert from. 85 | * @param {Function} callback - The function invoked to mark the completion of the conversion process. 86 | */ 87 | convertResponse: function (object, options, callback) { 88 | if (!options.outputVersion || !semver.valid(options.outputVersion, true)) { 89 | return callback(new Error('Output version not specified or invalid: ' + options.outputVersion)); 90 | } 91 | if (!options.inputVersion || !semver.valid(options.inputVersion, true)) { 92 | return callback(new Error('Input version not specified or invalid: ' + options.inputVersion)); 93 | } 94 | 95 | return converter.convertResponse(object, options, callback); 96 | } 97 | }; 98 | -------------------------------------------------------------------------------- /lib/normalizers/index.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable object-shorthand */ 2 | var semver = require('semver'), 3 | 4 | // @todo: Add support for more normalizers 5 | normalizers = { 6 | '1.0.0': require('./v1') 7 | }; 8 | 9 | module.exports = { 10 | /** 11 | * Accepts the arguments for normalization and invokes the appropriate normalizer with them. 12 | * 13 | * @param {Object} collection - The plain collection JSON to be normalized. 14 | * @param {Object} options - A set of options for the current normalization. 15 | * @param {String} options.normalizeVersion - The base collection schema version for which to normalize. 16 | * @param {?Boolean} [options.mutate=false] - When set to true, normalization is done in place. 17 | * @param {?Boolean} [options.noDefaults=false] - When set to true, sensible defaults are not added. 18 | * @param {?Boolean} [options.prioritizeV2=false] - When set to true, v2 style properties are checked first. 19 | * @param {?Boolean} [options.retainEmptyValues=false] - When set to true, empty values are set to '' instead of 20 | * being removed. 21 | * @param {Function} callback - A function invoked to indicate the completion of the normalization process. 22 | * @returns {*} 23 | */ 24 | normalize: function (collection, options, callback) { 25 | var version; 26 | 27 | if (!options || !(version = semver.valid(options.normalizeVersion, true)) || !normalizers[version]) { 28 | return callback(new Error('Version not specified or invalid: ' + options.normalizeVersion)); 29 | } 30 | 31 | return normalizers[version].normalize(collection, options, callback); 32 | }, 33 | 34 | /** 35 | * Normalizes a single request or item as per the provided version. 36 | * 37 | * @param {Object} object - The entity to be normalized. 38 | * @param {Object} options - The set of options to be applied to the current normalization. 39 | * @param {String} options.normalizeVersion - The base collection schema version for which to normalize. 40 | * @param {?Boolean} [options.mutate=false] - When set to true, normalization is done in place. 41 | * @param {?Boolean} [options.noDefaults=false] - When set to true, sensible defaults are not added. 42 | * @param {?Boolean} [options.prioritizeV2=false] - When set to true, v2 style properties are checked first. 43 | * @param {?Boolean} [options.retainEmptyValues=false] - When set to true, empty values are set to '' instead of 44 | * being removed. 45 | * @param {Function} callback - The function invoked when the normalization has completed. 46 | */ 47 | normalizeSingle: function (object, options, callback) { 48 | var version; 49 | 50 | if (!options || !(version = semver.valid(options.normalizeVersion, true)) || !normalizers[version]) { 51 | return callback(new Error('Version not specified or invalid: ' + options.normalizeVersion)); 52 | } 53 | 54 | return normalizers[version].normalizeSingle(object, options, callback); 55 | }, 56 | 57 | /** 58 | * Normalizes a single response as per the provided version. 59 | * 60 | * @param {Object} response - The response to be normalized. 61 | * @param {Object} options - The set of options to be applied to the current normalization. 62 | * @param {String} options.normalizeVersion - The base collection schema version for which to normalize. 63 | * @param {?Boolean} [options.mutate=false] - When set to true, normalization is done in place. 64 | * @param {?Boolean} [options.noDefaults=false] - When set to true, sensible defaults are not added. 65 | * @param {?Boolean} [options.prioritizeV2=false] - When set to true, v2 style properties are checked first. 66 | * @param {?Boolean} [options.retainEmptyValues=false] - When set to true, empty values are set to '' instead of 67 | * being removed. 68 | * @param {Function} callback - The function invoked when the normalization has completed. 69 | */ 70 | normalizeResponse: function (response, options, callback) { 71 | var version; 72 | 73 | if (!options || !(version = semver.valid(options.normalizeVersion, true)) || !normalizers[version]) { 74 | return callback(new Error('Version not specified or invalid: ' + options.normalizeVersion)); 75 | } 76 | 77 | return normalizers[version].normalizeResponse(response, options, callback); 78 | } 79 | }; 80 | -------------------------------------------------------------------------------- /npm/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 | }).then((version) => { 26 | console.info('🚀', version); 27 | }).catch((err) => { 28 | console.error('🔥', err); 29 | process.exit(1); 30 | }); 31 | -------------------------------------------------------------------------------- /npm/test-browser.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | // --------------------------------------------------------------------------------------------------------------------- 3 | // This script is intended to execute all unit tests in the Chrome Browser. 4 | // --------------------------------------------------------------------------------------------------------------------- 5 | 6 | const path = require('path'), 7 | 8 | chalk = require('chalk'), 9 | KarmaServer = require('karma').Server, 10 | 11 | KARMA_CONFIG_PATH = path.join(__dirname, '..', 'test', 'karma.conf'); 12 | 13 | module.exports = function (exit) { 14 | console.info(chalk.yellow.bold('Running unit tests within browser...')); 15 | 16 | (new KarmaServer({ // eslint-disable no-new 17 | cmd: 'start', 18 | configFile: KARMA_CONFIG_PATH 19 | }, exit)).start(); 20 | }; 21 | 22 | // ensure we run this script exports if this is a direct stdin.tty run 23 | !module.parent && module.exports(process.exit); 24 | -------------------------------------------------------------------------------- /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 chalk = require('chalk'), 7 | { ESLint } = require('eslint'), 8 | 9 | LINT_SOURCE_DIRS = [ 10 | './index.js', 11 | './lib/**/*.js', 12 | './bin/**/*.js', 13 | './test/**/*.js', 14 | './npm/**/*.js' 15 | ]; 16 | 17 | module.exports = async function (exit) { 18 | // banner line 19 | console.info(chalk.yellow.bold('\nLinting files using eslint...')); 20 | 21 | const eslint = new ESLint(), 22 | results = await eslint.lintFiles(LINT_SOURCE_DIRS), 23 | errorReport = ESLint.getErrorResults(results), 24 | formatter = await eslint.loadFormatter(); 25 | 26 | // log the result to CLI 27 | console.info(formatter.format(results)); 28 | 29 | (errorReport && !errorReport.length) && console.info(chalk.green('eslint ok!')); 30 | 31 | exit(Number(errorReport && errorReport.length) || 0); 32 | }; 33 | 34 | // ensure we run this script exports if this is a direct stdin.tty run 35 | !module.parent && module.exports(process.exit); 36 | -------------------------------------------------------------------------------- /npm/test-schema.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | // --------------------------------------------------------------------------------------------------------------------- 3 | // This script is intended to execute all schema tests. 4 | // --------------------------------------------------------------------------------------------------------------------- 5 | 6 | const path = require('path'), 7 | 8 | chalk = require('chalk'), 9 | Mocha = require('mocha'), 10 | recursive = require('recursive-readdir'), 11 | 12 | SPEC_SOURCE_DIR = path.join('test', 'schema'); 13 | 14 | module.exports = function (exit) { 15 | // banner line 16 | console.info(chalk.yellow.bold('Running schema 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 | var 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 | return mocha.run((runError) => { 33 | runError && console.error(runError.stack || runError); 34 | 35 | exit(runError ? 1 : 0); 36 | }); 37 | }); 38 | }; 39 | 40 | // ensure we run this script exports if this is a direct stdin.tty run 41 | !module.parent && module.exports(process.exit); 42 | -------------------------------------------------------------------------------- /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 | chalk = require('chalk'), 10 | packity = require('packity'), 11 | recursive = require('recursive-readdir'), 12 | 13 | SPEC_SOURCE_DIR = path.join(__dirname, '..', 'test', 'system'); 14 | 15 | module.exports = function (exit) { 16 | // banner line 17 | console.info(chalk.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 | // packity 42 | const options = { 43 | path: './', 44 | dev: true 45 | }; 46 | 47 | packity(options, (err, results) => { 48 | packity.cliReporter(options)(err, results); 49 | 50 | exit(err ? 1 : 0); 51 | }); 52 | }); 53 | }); 54 | }; 55 | 56 | // ensure we run this script exports if this is a direct stdin.tty run 57 | !module.parent && module.exports(process.exit); 58 | -------------------------------------------------------------------------------- /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 | chalk = require('chalk'), 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(chalk.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(process.exitCode || runError ? 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 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "postman-collection-transformer", 3 | "version": "4.1.11", 4 | "description": "Perform rapid conversation and validation of JSON structure between Postman Collection Format v1 and v2", 5 | "author": "Postman Inc.", 6 | "license": "Apache-2.0", 7 | "main": "index.js", 8 | "bin": "./bin/transform-collection.js", 9 | "homepage": "https://github.com/postmanlabs/postman-collection-transformer#readme", 10 | "bugs": { 11 | "url": "https://github.com/postmanlabs/postman-collection-transformer/issues", 12 | "email": "help@postman.com" 13 | }, 14 | "repository": { 15 | "type": "git", 16 | "url": "git+https://github.com/postmanlabs/postman-collection-transformer.git" 17 | }, 18 | "keywords": [ 19 | "postman", 20 | "collection", 21 | "json", 22 | "format", 23 | "converter", 24 | "transformer" 25 | ], 26 | "scripts": { 27 | "release": "node npm/release.js", 28 | "test": "npm run test-lint && npm run test-system && npm run test-unit && npm run test-schema && npm run test-browser", 29 | "test-browser": "node npm/test-browser.js", 30 | "test-lint": "node npm/test-lint.js", 31 | "test-schema": "node npm/test-schema.js", 32 | "test-system": "node npm/test-system.js", 33 | "test-unit": "nyc --nycrc-path=.nycrc.js node npm/test-unit.js" 34 | }, 35 | "dependencies": { 36 | "commander": "8.3.0", 37 | "inherits": "2.0.4", 38 | "lodash": "4.17.21", 39 | "semver": "7.5.4", 40 | "strip-json-comments": "3.1.1" 41 | }, 42 | "devDependencies": { 43 | "@postman/shipit": "^0.4.0", 44 | "async": "^3.2.4", 45 | "browserify": "^17.0.0", 46 | "chai": "^4.3.8", 47 | "chalk": "^4.1.2", 48 | "eslint": "^7.22.0", 49 | "eslint-plugin-jsdoc": "^36.1.1", 50 | "eslint-plugin-lodash": "^7.4.0", 51 | "eslint-plugin-mocha": "^10.1.0", 52 | "eslint-plugin-security": "^1.7.1", 53 | "js-yaml": "^4.0.0", 54 | "karma": "^6.4.2", 55 | "karma-browserify": "^8.1.0", 56 | "karma-chrome-launcher": "^3.2.0", 57 | "karma-mocha": "^2.0.1", 58 | "karma-mocha-reporter": "^2.2.5", 59 | "mocha": "^9.2.1", 60 | "nyc": "^15.1.0", 61 | "packity": "^0.3.4", 62 | "parse-gitignore": "^1.0.1", 63 | "pretty-ms": "^7.0.1", 64 | "recursive-readdir": "^2.2.3", 65 | "require-all": "^3.0.0", 66 | "shelljs": "^0.8.5", 67 | "superagent": "^8.1.2", 68 | "tv4": "^1.3.0", 69 | "watchify": "^4.0.0", 70 | "yankee": "^1.0.8" 71 | }, 72 | "engines": { 73 | "node": ">=10" 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /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 | "describe": true, 13 | "expect": true, 14 | "sinon": true, 15 | "it": true 16 | }, 17 | "rules": { 18 | // Mocha 19 | "mocha/handle-done-callback": "error", 20 | "mocha/max-top-level-suites": "error", 21 | "mocha/no-exclusive-tests": "error", 22 | "mocha/no-global-tests": "error", 23 | "mocha/no-hooks-for-single-case": "off", 24 | "mocha/no-hooks": "off", 25 | "mocha/no-identical-title": "error", 26 | "mocha/no-mocha-arrows": "error", 27 | "mocha/no-nested-tests": "error", 28 | "mocha/no-pending-tests": "error", 29 | "mocha/no-return-and-callback": "error", 30 | "mocha/no-sibling-hooks": "error", 31 | "mocha/no-skipped-tests": "warn", 32 | "mocha/no-synchronous-tests": "off", 33 | "mocha/no-top-level-hooks": "warn", 34 | "mocha/valid-test-description": "off", 35 | "mocha/valid-suite-description": "off", 36 | 37 | // Security 38 | "security/detect-non-literal-regexp": "off", 39 | "security/detect-unsafe-regex": "off" 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /test/karma.conf.js: -------------------------------------------------------------------------------- 1 | // Karma configuration 2 | module.exports = function (config) { 3 | var configuration = { 4 | 5 | // base path that will be used to resolve all patterns (eg. files, exclude) 6 | basePath: '', 7 | 8 | // frameworks to use 9 | // available frameworks: https://npmjs.org/browse/keyword/karma-adapter 10 | frameworks: ['mocha', 'browserify'], 11 | 12 | // list of files / patterns to load in the browser 13 | files: [ 14 | '../index.js', 15 | '../test/unit/**/*.js' 16 | ], 17 | 18 | // preprocess matching files before serving them to the browser 19 | // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor 20 | preprocessors: { 21 | '../index.js': ['browserify'], // Mention path as per your test js folder 22 | '../test/unit/**/*.js': ['browserify'] // Mention path as per your library js folder 23 | }, 24 | // test results reporter to use 25 | // possible values: 'dots', 'progress' 26 | // available reporters: https://npmjs.org/browse/keyword/karma-reporter 27 | reporters: ['mocha'], 28 | 29 | // web server port 30 | port: 9876, 31 | 32 | // the number of milliseconds to wait for an idle browser to come back up before bailing 33 | browserNoActivityTimeout: 20000, 34 | 35 | // enable / disable colors in the output (reporters and logs) 36 | colors: true, 37 | 38 | // level of logging 39 | // one of: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG 40 | logLevel: config.LOG_WARN, 41 | 42 | // enable / disable watching file and executing tests whenever any file changes 43 | autoWatch: false, 44 | 45 | // start these browsers 46 | // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher 47 | browsers: ['ChromeHeadless'], 48 | 49 | // Continuous Integration mode 50 | // if true, Karma captures browsers, runs the tests and exits 51 | singleRun: true, 52 | 53 | // Concurrency level 54 | // how many browser should be started simultaneously 55 | concurrency: Infinity, 56 | 57 | // Uncomment "karma-browserify" if you see an error like this: 58 | // Error: No provider for "framework:browserify"! (Resolving: framework:browserify) 59 | plugins: [ 60 | 'karma-mocha', 61 | 'karma-chrome-launcher', 62 | 'karma-browserify', 63 | 'karma-mocha-reporter' 64 | ], 65 | 66 | // Pass options to the client frameworks. 67 | client: { 68 | mocha: { 69 | timeout: 10000 // 10 seconds 70 | } 71 | } 72 | }; 73 | 74 | // Use `npm run test-browser -- --debug` to debug tests in Chrome console 75 | if (process.argv[2] === '--debug') { 76 | configuration.browsers = ['Chrome']; 77 | configuration.singleRun = false; 78 | } 79 | 80 | config.set(configuration); 81 | }; 82 | -------------------------------------------------------------------------------- /test/schema/example-validity.test.js: -------------------------------------------------------------------------------- 1 | var expect = require('chai').expect, 2 | requireAll = require('require-all'), 3 | path = require('path'), 4 | tv4 = require('tv4'), 5 | _ = require('lodash').noConflict(), 6 | agent = require('superagent'); 7 | 8 | describe('Example validity', function () { 9 | // The V1 collections contain random stuff for extremely old collections, so their tests are skipped 10 | describe.skip('v1.0.0', function () { 11 | var schemaUrl = require('../../lib/constants').SCHEMA_V1_URL, 12 | examplesDir = path.join(__dirname, '../../examples/v1.0.0'), 13 | schema, 14 | samples = requireAll(examplesDir); 15 | 16 | before(function (done) { 17 | agent.get(schemaUrl, function (error, response) { 18 | schema = _.isString(response.body) ? JSON.parse(response.body) : response.body; 19 | done(error); 20 | }); 21 | }); 22 | 23 | _.forEach(samples, function (sample, sampleName) { 24 | it('must be a valid V1 collection: ' + sampleName + '.json', function (done) { 25 | var validator = tv4.freshApi(), 26 | result; 27 | 28 | validator.addSchema(schema); 29 | // Some of the converter functions assign "undefined" value to some properties, 30 | // It is necessary to get rid of them (otherwise schema validation sees an "undefined" and fails). 31 | // Converting to and parsing from JSON does this. 32 | result = validator.validate(sample, schema); 33 | if (!result) { 34 | console.error(JSON.stringify(validator.error, null, 4)); // Helps debug on CI 35 | } 36 | if (validator.missing.length) { 37 | console.error(validator.missing); 38 | result = false; 39 | } 40 | expect(result).to.equal(true); 41 | done(); 42 | }); 43 | }); 44 | }); 45 | 46 | describe('v2.0.0', function () { 47 | var schemaUrl = require('../../lib/constants').SCHEMA_V2_URL, 48 | examplesDir = path.join(__dirname, '../../examples/v2.0.0'), 49 | schema, 50 | samples = requireAll(examplesDir); 51 | 52 | before(function (done) { 53 | agent.get(schemaUrl, function (error, response) { 54 | schema = _.isString(response.body) ? JSON.parse(response.body) : response.body; 55 | done(error); 56 | }); 57 | }); 58 | 59 | _.forEach(samples, function (sample, sampleName) { 60 | it('must be a valid V2 collection: ' + sampleName + '.json', function (done) { 61 | var validator = tv4.freshApi(), 62 | result; 63 | 64 | validator.addSchema(schema); 65 | // Some of the converter functions assign "undefined" value to some properties, 66 | // It is necessary to get rid of them (otherwise schema validation sees an "undefined" and fails). 67 | // Converting to and parsing from JSON does this. 68 | result = validator.validate(sample, schema); 69 | if (!result) { 70 | console.error(JSON.stringify(validator.error, null, 4)); // Helps debug on CI 71 | } 72 | if (validator.missing.length) { 73 | console.error(validator.missing); 74 | result = false; 75 | } 76 | expect(result).to.equal(true); 77 | done(); 78 | }); 79 | }); 80 | }); 81 | 82 | describe('v2.1.0', function () { 83 | var schemaUrl = require('../../lib/constants').SCHEMA_V2_1_0_URL, 84 | examplesDir = path.join(__dirname, '../../examples/v2.1.0'), 85 | schema, 86 | samples = requireAll(examplesDir); 87 | 88 | before(function (done) { 89 | agent.get(schemaUrl, function (error, response) { 90 | schema = _.isString(response.body) ? JSON.parse(response.body) : response.body; 91 | done(error); 92 | }); 93 | }); 94 | 95 | _.forEach(samples, function (sample, sampleName) { 96 | it('must be a valid V2 collection: ' + sampleName + '.json', function (done) { 97 | var validator = tv4.freshApi(), 98 | result; 99 | 100 | validator.addSchema(schema); 101 | // Some of the converter functions assign "undefined" value to some properties, 102 | // It is necessary to get rid of them (otherwise schema validation sees an "undefined" and fails). 103 | // Converting to and parsing from JSON does this. 104 | result = validator.validate(sample, schema); 105 | if (!result) { 106 | console.error(JSON.stringify(validator.error, null, 4)); // Helps debug on CI 107 | } 108 | if (validator.missing.length) { 109 | console.error(validator.missing); 110 | result = false; 111 | } 112 | expect(result).to.equal(true); 113 | done(); 114 | }); 115 | }); 116 | }); 117 | }); 118 | -------------------------------------------------------------------------------- /test/schema/url-parse.test.js: -------------------------------------------------------------------------------- 1 | var expect = require('chai').expect, 2 | util = require('../../lib/util'); 3 | 4 | describe('url parsing', function () { 5 | it('should correctly unparse query parameters', function () { 6 | var v2url = { 7 | raw: '{{baseurl}}/folder1/:uriParam/resource?foo={{foo.var}}&bar={{bar.var}}', 8 | auth: {}, 9 | host: [ 10 | '{{baseurl}}' 11 | ], 12 | path: [ 13 | 'folder1', 14 | ':uriParam', 15 | 'resource' 16 | ], 17 | query: [ 18 | { 19 | key: 'foo', 20 | value: '{{foo.var}}' 21 | }, 22 | { 23 | key: 'bar', 24 | value: '{{bar.var}}' 25 | } 26 | ], 27 | variable: [ 28 | { 29 | value: '', 30 | id: 'uriParam' 31 | } 32 | ] 33 | }; 34 | 35 | expect(util.urlunparse(v2url)).to.eql('{{baseurl}}/folder1/:uriParam/resource?foo={{foo.var}}&bar={{bar.var}}'); 36 | }); 37 | }); 38 | -------------------------------------------------------------------------------- /test/schema/v1.0.0/converter-v1-to-v21.test.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @fileoverview This test suite runs tests on the V1 to V2 converter. 3 | */ 4 | 5 | var expect = require('chai').expect, 6 | requireAll = require('require-all'), 7 | path = require('path'), 8 | tv4 = require('tv4'), 9 | _ = require('lodash').noConflict(), 10 | agent = require('superagent'); 11 | 12 | describe('v1.0.0 ==> v2.1.0', function () { 13 | var converter = require('../../../lib/converters/v1.0.0/converter-v1-to-v21'), 14 | reverseConverter = require('../../../lib/converters/v2.1.0/converter-v21-to-v1'), 15 | schemaUrl = require('../../../lib/constants').SCHEMA_V2_1_0_URL, 16 | examplesDir = path.join(__dirname, '../../../examples/v1.0.0'); 17 | 18 | describe('sample conversions', function () { 19 | var schema, 20 | samples = requireAll(examplesDir); 21 | 22 | before(function (done) { 23 | agent 24 | .get(schemaUrl) 25 | .set('Cache-Control', 'no-cache; no-store; must-revalidate') 26 | .end(function (error, response) { 27 | schema = _.isString(response.body) ? JSON.parse(response.body) : response.body; 28 | done(error); 29 | }); 30 | }); 31 | 32 | _.forEach(samples, function (sample, sampleName) { 33 | !_.includes(['echo', 'helpers', 'nestedEntities'], sampleName) && 34 | it('must create a valid V2.1.0 collection from ' + sampleName + '.json', function (done) { 35 | converter.convert(sample, {}, function (err, converted) { 36 | var validator = tv4.freshApi(), 37 | result; 38 | 39 | validator.addSchema(schema); 40 | 41 | // Some of the converter functions assign "undefined" value to some properties, 42 | // It is necessary to get rid of them (otherwise schema validation sees an "undefined" and fails). 43 | // Converting to and parsing from JSON does this. 44 | converted = JSON.parse(JSON.stringify(converted)); 45 | 46 | result = validator.validate(converted, schema); 47 | if (!result && process.env.CI) { // eslint-disable-line no-process-env 48 | console.error(JSON.stringify(validator.error, null, 4)); // Helps debug on CI 49 | } 50 | if (validator.missing.length) { 51 | console.error(validator.missing); 52 | result = false; 53 | } 54 | expect(err).to.equal(null); 55 | expect(result).to.equal(true); 56 | done(); 57 | }); 58 | }); 59 | }); 60 | 61 | _.forEach(samples, function (sample, sampleName) { 62 | !_.includes(['echo', 'helpers', 'nestedEntities'], sampleName) && 63 | it(`must create a valid V2.1.0 collection from ${sampleName}.json with synchronous API`, function (done) { 64 | var validator = tv4.freshApi(), 65 | result, 66 | converted; 67 | 68 | validator.addSchema(schema); 69 | converted = converter.convert(sample); 70 | 71 | // Some of the converter functions assign "undefined" value to some properties, 72 | // It is necessary to get rid of them (otherwise schema validation sees an "undefined" and fails). 73 | // Converting to and parsing from JSON does this. 74 | converted = JSON.parse(JSON.stringify(converted)); 75 | 76 | result = validator.validate(converted, schema); 77 | if (!result && process.env.CI) { // eslint-disable-line no-process-env 78 | console.error(JSON.stringify(validator.error, null, 4)); // Helps debug on CI 79 | } 80 | if (validator.missing.length) { 81 | console.error(validator.missing); 82 | result = false; 83 | } 84 | expect(result).to.equal(true); 85 | done(); 86 | }); 87 | }); 88 | }); 89 | 90 | describe('Exceptional cases', function () { 91 | it('should handle the edge case of "data" vs "rawModeData"', function () { 92 | var v1 = require('../../../examples/v1.0.0/simplest.json'), 93 | v21 = converter.convert(v1); 94 | 95 | expect(v21.item[0].request.body.raw).to.eql('something'); 96 | }); 97 | 98 | it('should strip out all request and folder ids by default', function () { 99 | var v1 = require('../../../examples/v1.0.0/simplest.json'), 100 | v21 = JSON.parse(JSON.stringify(converter.convert(v1))); 101 | 102 | expect(v21.item[0]).to.not.have.property('id'); 103 | expect(v21.item[0]).not.to.have.property('_postman_id'); 104 | }); 105 | 106 | it('should retain all request and folder ids if asked to', function () { 107 | var v1 = require('../../../examples/v1.0.0/simplest.json'), 108 | v21 = JSON.parse(JSON.stringify(converter.convert(v1, { 109 | retainIds: true 110 | }))); 111 | 112 | expect(v21.item[0]).to.have.property('id'); 113 | }); 114 | 115 | it('should mark commented out headers as disabled', function () { 116 | var v1 = require('../../../examples/v1.0.0/disabledheaders.json'), 117 | v21 = JSON.parse(JSON.stringify(converter.convert(v1, { 118 | retainIds: true 119 | }))); 120 | 121 | expect(v21.item[0].request.header[1].disabled).to.equal(true); 122 | }); 123 | 124 | it('should not set default request body for requests with no data', function () { 125 | var v1 = require('../../../examples/v1.0.0/emptydata.json'), 126 | v21 = JSON.parse(JSON.stringify(converter.convert(v1, { 127 | retainIds: true 128 | }))); 129 | 130 | expect(_.isEmpty(v21.item[0].request.body)).to.equal(true); 131 | }); 132 | 133 | it('should not set request body for requests with dataMode set to null but rawModeData set', function () { 134 | var v1 = require('../../../examples/v1.0.0/emptydatamode.json'), 135 | v2 = JSON.parse(JSON.stringify(converter.convert(v1, { 136 | retainIds: true, 137 | retainEmptyValues: true 138 | }))); 139 | 140 | expect(v2.item[0].request.body).to.be.null; 141 | }); 142 | 143 | it('should not set request body for requests with dataMode set to null but rawModeData set,' + 144 | ' retainEmptyValues set to false', function () { 145 | var v1 = require('../../../examples/v1.0.0/emptydatamode.json'), 146 | v2 = JSON.parse(JSON.stringify(converter.convert(v1, { 147 | retainIds: true 148 | }))); 149 | 150 | expect(v2.item[0].request.body).to.be.undefined; 151 | }); 152 | }); 153 | 154 | describe('Binary File reference', function () { 155 | it('should be converted to v2 correctly', function () { 156 | var v1 = require('../../../examples/v1.0.0/binary-upload.json'), 157 | v2 = JSON.parse(JSON.stringify(converter.convert(v1, { 158 | retainIds: true 159 | }))); 160 | 161 | expect(_.get(v2, 'item[0].request.body.file.src')).to.equal('sample.txt'); 162 | }); 163 | }); 164 | 165 | describe('Malformed V1 collections', function () { 166 | var malformedJson = require(path.join(examplesDir, 'malformed.json')); 167 | 168 | it('should remove duplicate / non existent folder/request ids', function (done) { 169 | var converted = JSON.parse(JSON.stringify(converter.convert(malformedJson))), 170 | reverted = JSON.parse(JSON.stringify(reverseConverter.convert(converted))); 171 | 172 | expect(reverted.order).to.have.length(1); 173 | expect(reverted.folders_order).to.have.length(2); 174 | 175 | expect(reverted.folders[1].order).to.have.length(2); // F5 176 | expect(reverted.folders[1].folders_order).to.have.length(4); // F5 177 | 178 | expect(reverted.folders[3].order).to.have.length(0); // F4 179 | expect(reverted.folders[4].order).to.have.length(0); // F5.F1 180 | done(); 181 | }); 182 | }); 183 | }); 184 | -------------------------------------------------------------------------------- /test/schema/v2.0.0/converter-v2-to-v1.test.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @fileoverview This test suite runs tests on the V2 to V1 converter. 3 | */ 4 | 5 | var expect = require('chai').expect, 6 | requireAll = require('require-all'), 7 | path = require('path'), 8 | tv4 = require('tv4'), 9 | _ = require('lodash').noConflict(), 10 | agent = require('superagent'); 11 | 12 | describe('v2.0.0 ==> v1.0.0', function () { 13 | var converter = require('../../../lib/converters/v2.0.0/converter-v2-to-v1'), 14 | schemaUrl = require('../../../lib/constants').SCHEMA_V1_URL, 15 | examplesDir = path.join(__dirname, '../../../examples/v2.0.0'); 16 | 17 | describe('sample conversions', function () { 18 | var schema, 19 | samples = requireAll(examplesDir); 20 | 21 | before(function (done) { 22 | agent 23 | .get(schemaUrl) 24 | .set('Cache-Control', 'no-cache; no-store; must-revalidate') 25 | .end(function (error, response) { 26 | schema = _.isString(response.body) ? JSON.parse(response.body) : response.body; 27 | done(error); 28 | }); 29 | }); 30 | 31 | _.forEach(samples, function (sample, sampleName) { 32 | it('must create a valid V1 collection from ' + sampleName + '.json', function (done) { 33 | converter.convert(sample, {}, function (err, converted) { 34 | var validator = tv4.freshApi(), 35 | result; 36 | 37 | validator.addSchema(schema); 38 | // Some of the converter functions assign "undefined" value to some properties, 39 | // It is necessary to get rid of them (otherwise schema validation sees an "undefined" and fails). 40 | // Converting to and parsing from JSON does this. 41 | converted = JSON.parse(JSON.stringify(converted)); 42 | result = validator.validate(converted, schema); 43 | if (!result && process.env.CI) { // eslint-disable-line no-process-env 44 | console.error(JSON.stringify(validator.error, null, 4)); // Helps debug on CI 45 | } 46 | if (validator.missing.length) { 47 | console.error(validator.missing); 48 | result = false; 49 | } 50 | expect(result).to.equal(true); 51 | expect(err).to.equal(null); 52 | done(); 53 | }); 54 | }); 55 | }); 56 | 57 | _.forEach(samples, function (sample, sampleName) { 58 | it('must create a valid V1 collection from ' + sampleName + '.json with synchronous API', function (done) { 59 | var validator = tv4.freshApi(), 60 | result, 61 | converted; 62 | 63 | validator.addSchema(schema); 64 | converted = converter.convert(sample); 65 | 66 | // Some of the converter functions assign "undefined" value to some properties, 67 | // It is necessary to get rid of them (otherwise schema validation sees an "undefined" and fails). 68 | // Converting to and parsing from JSON does this. 69 | converted = JSON.parse(JSON.stringify(converted)); 70 | 71 | result = validator.validate(converted, schema); 72 | if (!result && process.env.CI) { // eslint-disable-line no-process-env 73 | console.error(JSON.stringify(validator.error, null, 4)); // Helps debug on CI 74 | } 75 | if (validator.missing.length) { 76 | console.error(validator.missing); 77 | result = false; 78 | } 79 | expect(result).to.equal(true); 80 | done(); 81 | }); 82 | }); 83 | }); 84 | 85 | describe('Exceptional cases', function () { 86 | describe('Binary File reference', function () { 87 | it('should be converted to v1 correctly', function () { 88 | var v2 = require('../../../examples/v2.0.0/binary-upload.json'), 89 | v1 = JSON.parse(JSON.stringify(converter.convert(v2))); 90 | 91 | expect(_.get(v1, 'requests[0].dataMode')).to.equal('binary'); 92 | expect(_.get(v1, 'requests[0].rawModeData')).to.equal('sample.txt'); 93 | expect(_.isEmpty(_.get(v1, 'requests[0].data'))).to.equal(true); 94 | }); 95 | }); 96 | }); 97 | 98 | it.skip('must be compatible with both v2.0.0 and v2.1.0 formats', function () { 99 | var samples_2_1_0 = requireAll(path.join(__dirname, '../../examples/v2.1.0')), 100 | samples_2_0_0 = requireAll(path.join(__dirname, '../../examples/v2.0.0')), 101 | 102 | deepCompare = function (first, second, omitProperties) { 103 | if (_.isNaN(first) || 104 | _.isDate(first) || 105 | _.isString(first) || 106 | _.isBoolean(first) || 107 | _.isNumber(first) || 108 | _.isNull(first)) { 109 | return first === second; 110 | } 111 | 112 | for (var key in first) { 113 | if (!first.hasOwnProperty(key)) { // eslint-disable-line no-prototype-builtins 114 | continue; 115 | } 116 | if (_.includes(omitProperties, key)) { 117 | if (_.isArray(first[key])) { 118 | return first[key].length === second[key].length; 119 | } 120 | continue; 121 | } 122 | if (!deepCompare(first[key], second[key], omitProperties)) { 123 | return false; 124 | } 125 | } 126 | 127 | return true; 128 | }; 129 | 130 | expect(_.keys(samples_2_0_0)).to.eql(_.keys(samples_2_1_0)); 131 | 132 | _.forOwn(samples_2_0_0, function (sample, sampleName) { 133 | var convertedExpectation = converter.convert(sample), 134 | convertedActual = converter.convert(samples_2_1_0[sampleName]); 135 | 136 | expect(_.keys(convertedExpectation)).to.eql(_.keys(convertedActual)); 137 | expect(_.keys(convertedExpectation)).to.not.be.empty(); 138 | 139 | expect(deepCompare(convertedExpectation, convertedActual, ['id', 'order'])).to.equal(true); 140 | }); 141 | }); 142 | 143 | describe('responses_order', function () { 144 | it('should create responses_order field based on the order of responses', function (done) { 145 | const collection = { 146 | info: { 147 | _postman_id: '8eca8c11-c5ce-4032-b62c-568ca86dbe4c', 148 | schema: 'https://schema.getpostman.com/json/collection/v2.0.0/collection.json' 149 | }, 150 | item: [ 151 | { 152 | name: 'Test', 153 | request: { 154 | header: [] 155 | }, 156 | response: [ 157 | { 158 | id: 'Response1', 159 | name: 'Response1' 160 | }, 161 | { 162 | id: 'Response3', 163 | name: 'Response3' 164 | }, 165 | { 166 | id: 'Response2', 167 | name: 'Response2' 168 | } 169 | ] 170 | } 171 | ] 172 | }, 173 | converted = converter.convert(collection, { retainIds: true }); 174 | 175 | expect(converted).to.be.an('object'); 176 | expect(converted.requests).to.be.an('array'); 177 | expect(converted.requests[0]).to.be.an('object'); 178 | expect(converted.requests[0].responses_order).to.be.an('array'); 179 | 180 | expect(converted.requests[0].responses_order).to 181 | .eql(_.map(collection.item[0].response, 'id')); 182 | 183 | return done(); 184 | }); 185 | }); 186 | }); 187 | -------------------------------------------------------------------------------- /test/schema/v2.1.0/converter-v21-to-v1.test.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @fileoverview This test suite runs tests on the V2 to V1 converter. 3 | */ 4 | 5 | var expect = require('chai').expect, 6 | requireAll = require('require-all'), 7 | path = require('path'), 8 | tv4 = require('tv4'), 9 | _ = require('lodash').noConflict(), 10 | agent = require('superagent'); 11 | 12 | describe('v2.1.0 ==> v1.0.0', function () { 13 | var converter = require('../../../lib/converters/v2.1.0/converter-v21-to-v1'), 14 | schemaUrl = require('../../../lib/constants').SCHEMA_V1_URL, 15 | examplesDir = path.join(__dirname, '../../../examples/v2.1.0'); 16 | 17 | describe('sample conversions', function () { 18 | var schema, 19 | samples = requireAll(examplesDir); 20 | 21 | before(function (done) { 22 | agent 23 | .get(schemaUrl) 24 | .set('Cache-Control', 'no-cache; no-store; must-revalidate') 25 | .end(function (error, response) { 26 | schema = _.isString(response.body) ? JSON.parse(response.body) : response.body; 27 | done(error); 28 | }); 29 | }); 30 | 31 | _.forEach(samples, function (sample, sampleName) { 32 | it('must create a valid V1 collection from ' + sampleName + '.json', function (done) { 33 | converter.convert(sample, {}, function (err, converted) { 34 | var validator = tv4.freshApi(), 35 | result; 36 | 37 | validator.addSchema(schema); 38 | // Some of the converter functions assign "undefined" value to some properties, 39 | // It is necessary to get rid of them (otherwise schema validation sees an "undefined" and fails). 40 | // Converting to and parsing from JSON does this. 41 | converted = JSON.parse(JSON.stringify(converted)); 42 | result = validator.validate(converted, schema); 43 | if (!result && process.env.CI) { // eslint-disable-line no-process-env 44 | console.error(JSON.stringify(validator.error, null, 4)); // Helps debug on CI 45 | } 46 | if (validator.missing.length) { 47 | console.error(validator.missing); 48 | result = false; 49 | } 50 | expect(result).to.equal(true); 51 | expect(err).to.equal(null); 52 | done(); 53 | }); 54 | }); 55 | }); 56 | 57 | _.forEach(samples, function (sample, sampleName) { 58 | it('must create a valid V1 collection from ' + sampleName + '.json with synchronous API', function (done) { 59 | var validator = tv4.freshApi(), 60 | result, 61 | converted; 62 | 63 | validator.addSchema(schema); 64 | converted = converter.convert(sample); 65 | 66 | // Some of the converter functions assign "undefined" value to some properties, 67 | // It is necessary to get rid of them (otherwise schema validation sees an "undefined" and fails). 68 | // Converting to and parsing from JSON does this. 69 | converted = JSON.parse(JSON.stringify(converted)); 70 | 71 | result = validator.validate(converted, schema); 72 | if (!result && process.env.CI) { // eslint-disable-line no-process-env 73 | console.error(JSON.stringify(validator.error, null, 4)); // Helps debug on CI 74 | } 75 | if (validator.missing.length) { 76 | console.error(validator.missing); 77 | result = false; 78 | } 79 | expect(result).to.equal(true); 80 | done(); 81 | }); 82 | }); 83 | }); 84 | 85 | describe('Exceptional cases', function () { 86 | describe('Binary File reference', function () { 87 | it('should be converted to v1 correctly', function () { 88 | var v21 = require('../../../examples/v2.1.0/binary-upload.json'), 89 | v1 = JSON.parse(JSON.stringify(converter.convert(v21))); 90 | 91 | expect(_.get(v1, 'requests[0].dataMode')).to.equal('binary'); 92 | expect(_.get(v1, 'requests[0].rawModeData')).to.equal('sample.txt'); 93 | expect(_.isEmpty(_.get(v1, 'requests[0].data'))).to.equal(true); 94 | }); 95 | }); 96 | }); 97 | }); 98 | -------------------------------------------------------------------------------- /test/system/npm-publish.test.js: -------------------------------------------------------------------------------- 1 | const expect = require('chai').expect, 2 | // eslint-disable-next-line security/detect-child-process 3 | { execSync: exec } = require('child_process'); 4 | 5 | describe('npm publish', function () { 6 | // @note npm pack won't refresh the .cache because of prepublishOnly 7 | // but we make sure it's refreshed before running tests using pretest script 8 | const packageInfo = JSON.parse(exec('npm pack --dry-run --json'))[0], 9 | packagedFiles = packageInfo.files.map(({ path }) => { return path; }); 10 | 11 | it('should have a valid package name', function () { 12 | expect(packageInfo.name).to.equal('postman-collection-transformer'); 13 | }); 14 | 15 | it('should not publish unnecessary files', function () { 16 | const allowedFiles = ['index.js', 'package.json', 'LICENSE.md', 'README.md', 'CHANGELOG.yaml']; 17 | 18 | packagedFiles.map((path) => { 19 | expect(allowedFiles.includes(path) || 20 | path.startsWith('lib/') || 21 | path.startsWith('bin/')).to.be.true; 22 | }); 23 | }); 24 | }); 25 | -------------------------------------------------------------------------------- /test/unit/converter.test.js: -------------------------------------------------------------------------------- 1 | var expect = require('chai').expect, 2 | 3 | converter = require('../../lib/converters'); 4 | 5 | describe('converter', function () { 6 | it('should bail out with an error for invalid collection conversion paths', function (done) { 7 | converter.convert({}, { inputVersion: '1.0.0', outputVersion: '1.0.0' }, function (err) { 8 | expect(err).to.be.an.instanceOf(Error); 9 | done(); 10 | }); 11 | }); 12 | 13 | it('should bail out with an error for invalid request conversion paths', function (done) { 14 | converter.convertSingle({}, { inputVersion: '1.0.0', outputVersion: '1.0.0' }, function (err) { 15 | expect(err).to.be.an.instanceOf(Error); 16 | done(); 17 | }); 18 | }); 19 | 20 | it('should bail out with an error for invalid response conversion paths', function (done) { 21 | converter.convertResponse({}, { inputVersion: '1.0.0', outputVersion: '1.0.0' }, function (err) { 22 | expect(err).to.be.an.instanceOf(Error); 23 | done(); 24 | }); 25 | }); 26 | }); 27 | -------------------------------------------------------------------------------- /test/unit/fixtures/graphql-payload-in-both-key.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "collection", 3 | "name": "GraphQL Test", 4 | "id": "1069931-3bb3a9a3-37c0-43c4-8b87-d03c19a4b7d2", 5 | "order": [ 6 | "1069931-c59b3ff2-df0d-4c9c-a93a-496ffafd01b5" 7 | ], 8 | "requests": [ 9 | { 10 | "type": "request", 11 | "id": "1069931-c59b3ff2-df0d-4c9c-a93a-496ffafd01b5", 12 | "name": "New Request", 13 | "method": "GET", 14 | "url": "https://google.com", 15 | "data": { 16 | "query": "mutation {\n\n}", 17 | "variables": "{\n \n}" 18 | }, 19 | "dataOptions": { 20 | "graphql": {} 21 | }, 22 | "dataMode": "graphql", 23 | "graphqlModeData": { 24 | "query": "query Test { hello }", 25 | "operationName": "Test", 26 | "variables": "{}" 27 | } 28 | } 29 | ] 30 | } 31 | -------------------------------------------------------------------------------- /test/unit/fixtures/graphql-payload-in-data-key.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "collection", 3 | "name": "GraphQL Test", 4 | "id": "1069931-3bb3a9a3-37c0-43c4-8b87-d03c19a4b7d2", 5 | "order": [ 6 | "1069931-c59b3ff2-df0d-4c9c-a93a-496ffafd01b5" 7 | ], 8 | "requests": [ 9 | { 10 | "type": "request", 11 | "id": "1069931-c59b3ff2-df0d-4c9c-a93a-496ffafd01b5", 12 | "name": "New Request", 13 | "method": "GET", 14 | "url": "https://google.com", 15 | "data": { 16 | "query": "mutation {\n\n}", 17 | "variables": "{\n \n}" 18 | }, 19 | "dataOptions": { 20 | "graphql": {} 21 | }, 22 | "dataMode": "graphql" 23 | } 24 | ] 25 | } 26 | -------------------------------------------------------------------------------- /test/unit/fixtures/multi-level.v2.json: -------------------------------------------------------------------------------- 1 | { 2 | "info": { 3 | "_postman_id": "85a5a19a-744c-44a0-949f-6f782601ba41", 4 | "name": "Collection with multi level folders", 5 | "schema": "https://schema.getpostman.com/json/collection/v2.0.0/collection.json" 6 | }, 7 | "item": [ 8 | { 9 | "_postman_id": "09b61d0c-2ec1-422b-89b6-d144a97a01fe", 10 | "name": "F1", 11 | "description": "", 12 | "item": [ 13 | { 14 | "_postman_id": "b378f871-7a14-49a8-a7c7-65587014fded", 15 | "name": "F2", 16 | "description": "", 17 | "item": [ 18 | { 19 | "_postman_id": "199f3c2a-8a7f-4de1-b865-bff97be84a92", 20 | "name": "F3", 21 | "description": "", 22 | "item": [ 23 | { 24 | "_postman_id": "1d7d705a-1a96-4172-8b98-7d7ea57f379e", 25 | "name": "R3", 26 | "request": { 27 | "method": "GET", 28 | "header": [], 29 | "body": {}, 30 | "url": "" 31 | }, 32 | "response": [ 33 | { 34 | "id": "e337b92a-209e-4694-acfe-23aee3a94672", 35 | "name": "Example 1", 36 | "originalRequest": { 37 | "method": "GET", 38 | "header": [], 39 | "body": {}, 40 | "url": "" 41 | }, 42 | "status": "OK", 43 | "code": 200, 44 | "_postman_previewlanguage": "", 45 | "header": [], 46 | "cookie": [], 47 | "body": "" 48 | } 49 | ] 50 | } 51 | ], 52 | "_postman_isSubFolder": true 53 | }, 54 | { 55 | "_postman_id": "574bba1a-9301-4af3-afc7-2a22e9cced86", 56 | "name": "R2", 57 | "request": { 58 | "method": "GET", 59 | "header": [], 60 | "body": {}, 61 | "url": "" 62 | }, 63 | "response": [] 64 | } 65 | ], 66 | "_postman_isSubFolder": true 67 | }, 68 | { 69 | "_postman_id": "de84f8a8-0267-4e16-82de-acaf808db3dd", 70 | "name": "R1", 71 | "request": { 72 | "method": "GET", 73 | "header": [], 74 | "body": {}, 75 | "url": "" 76 | }, 77 | "response": [ 78 | { 79 | "id": "58a0ba3a-81cc-4c2c-bdd0-3bdc94e13ba8", 80 | "name": "Example 2", 81 | "originalRequest": { 82 | "method": "GET", 83 | "header": [], 84 | "body": {}, 85 | "url": "" 86 | }, 87 | "status": "OK", 88 | "code": 200, 89 | "_postman_previewlanguage": "", 90 | "header": [], 91 | "cookie": [], 92 | "body": "" 93 | } 94 | ] 95 | } 96 | ] 97 | }, 98 | { 99 | "_postman_id": "1e8f9ec8-64e6-4959-819b-112eb60ec8f0", 100 | "name": "F4", 101 | "description": "", 102 | "item": [ 103 | { 104 | "_postman_id": "03fc093c-f0a5-4cc9-9b92-d4df4d595916", 105 | "name": "F5", 106 | "description": "", 107 | "item": [ 108 | { 109 | "_postman_id": "0ae78c67-0cce-4883-97de-b55a7645f73f", 110 | "name": "R5", 111 | "request": { 112 | "method": "GET", 113 | "header": [], 114 | "body": {}, 115 | "url": "" 116 | }, 117 | "response": [] 118 | } 119 | ], 120 | "_postman_isSubFolder": true 121 | }, 122 | { 123 | "_postman_id": "ce3bb683-da8c-42d5-810f-d74e6dea5364", 124 | "name": "F6", 125 | "description": "", 126 | "item": [ 127 | { 128 | "_postman_id": "cd53ecd3-be93-4049-91e7-ca70ff91b9bd", 129 | "name": "R6", 130 | "request": { 131 | "method": "GET", 132 | "header": [], 133 | "body": {}, 134 | "url": "" 135 | }, 136 | "response": [ 137 | { 138 | "id": "39c2de71-9957-4c7f-acc1-1f6a9a1e3de4", 139 | "name": "Example 3", 140 | "originalRequest": { 141 | "method": "GET", 142 | "header": [], 143 | "body": {}, 144 | "url": "" 145 | }, 146 | "status": "OK", 147 | "code": 200, 148 | "_postman_previewlanguage": "", 149 | "header": [], 150 | "cookie": [], 151 | "body": "" 152 | } 153 | ] 154 | } 155 | ], 156 | "_postman_isSubFolder": true 157 | }, 158 | { 159 | "_postman_id": "09108595-be89-407c-aa40-5f5c3c92baaa", 160 | "name": "R4", 161 | "request": { 162 | "method": "GET", 163 | "header": [], 164 | "body": {}, 165 | "url": "" 166 | }, 167 | "response": [] 168 | } 169 | ] 170 | } 171 | ] 172 | } -------------------------------------------------------------------------------- /test/unit/fixtures/multi-level.v21.json: -------------------------------------------------------------------------------- 1 | { 2 | "info": { 3 | "_postman_id": "85a5a19a-744c-44a0-949f-6f782601ba41", 4 | "name": "Collection with multi level folders", 5 | "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json" 6 | }, 7 | "item": [ 8 | { 9 | "_postman_id": "789ec39c-1d49-4caa-b80c-db317f2a22fc", 10 | "name": "F1", 11 | "description": "", 12 | "item": [ 13 | { 14 | "_postman_id": "6a1b7c01-d90a-44d8-bb20-1c918ed7d05f", 15 | "name": "F2", 16 | "description": "", 17 | "item": [ 18 | { 19 | "_postman_id": "968a003d-8e5e-4f6e-9702-e555842eb816", 20 | "name": "F3", 21 | "description": "", 22 | "item": [ 23 | { 24 | "_postman_id": "a430a24d-de5e-452b-b4d9-cd61d9f72ab3", 25 | "name": "R3", 26 | "request": { 27 | "method": "GET", 28 | "header": [], 29 | "body": {}, 30 | "url": { 31 | "raw": "" 32 | } 33 | }, 34 | "response": [ 35 | { 36 | "id": "60b164cb-594c-45dc-88fc-33029a644bb2", 37 | "name": "Example 1", 38 | "originalRequest": { 39 | "method": "GET", 40 | "header": [], 41 | "body": {}, 42 | "url": { 43 | "raw": "" 44 | } 45 | }, 46 | "status": "OK", 47 | "code": 200, 48 | "_postman_previewlanguage": "", 49 | "header": [], 50 | "cookie": [], 51 | "body": "" 52 | } 53 | ] 54 | } 55 | ], 56 | "_postman_isSubFolder": true 57 | }, 58 | { 59 | "_postman_id": "0cfa0f79-d792-4808-80b7-554fe9b95e88", 60 | "name": "R2", 61 | "request": { 62 | "method": "GET", 63 | "header": [], 64 | "body": {}, 65 | "url": { 66 | "raw": "" 67 | } 68 | }, 69 | "response": [] 70 | } 71 | ], 72 | "_postman_isSubFolder": true 73 | }, 74 | { 75 | "_postman_id": "ebbf4eef-07b1-46f3-9263-763ce7249a12", 76 | "name": "R1", 77 | "request": { 78 | "method": "GET", 79 | "header": [], 80 | "body": {}, 81 | "url": { 82 | "raw": "" 83 | } 84 | }, 85 | "response": [ 86 | { 87 | "id": "be0e281a-6b5b-4542-8830-22ec13f0ad8f", 88 | "name": "Example 2", 89 | "originalRequest": { 90 | "method": "GET", 91 | "header": [], 92 | "body": {}, 93 | "url": { 94 | "raw": "" 95 | } 96 | }, 97 | "status": "OK", 98 | "code": 200, 99 | "_postman_previewlanguage": "", 100 | "header": [], 101 | "cookie": [], 102 | "body": "" 103 | } 104 | ] 105 | } 106 | ] 107 | }, 108 | { 109 | "_postman_id": "dd31e2af-e683-43e7-b2ba-b2ad465b60e8", 110 | "name": "F4", 111 | "description": "", 112 | "item": [ 113 | { 114 | "_postman_id": "2f42f3ea-c329-414d-8505-af15531943a0", 115 | "name": "F5", 116 | "description": "", 117 | "item": [ 118 | { 119 | "_postman_id": "1a2da58d-71df-4ee4-a075-ebde55480892", 120 | "name": "R5", 121 | "request": { 122 | "method": "GET", 123 | "header": [], 124 | "body": {}, 125 | "url": { 126 | "raw": "" 127 | } 128 | }, 129 | "response": [] 130 | } 131 | ], 132 | "_postman_isSubFolder": true 133 | }, 134 | { 135 | "_postman_id": "68f7d089-fcf9-4699-b34f-4f3ffb38fd02", 136 | "name": "F6", 137 | "description": "", 138 | "item": [ 139 | { 140 | "_postman_id": "867b4e33-0883-4cd3-b99c-a34841008d0a", 141 | "name": "R6", 142 | "request": { 143 | "method": "GET", 144 | "header": [], 145 | "body": {}, 146 | "url": { 147 | "raw": "" 148 | } 149 | }, 150 | "response": [ 151 | { 152 | "id": "61ed5253-6858-4ab9-8dcf-d34ae6ca068c", 153 | "name": "Example 3", 154 | "originalRequest": { 155 | "method": "GET", 156 | "header": [], 157 | "body": {}, 158 | "url": { 159 | "raw": "" 160 | } 161 | }, 162 | "status": "OK", 163 | "code": 200, 164 | "_postman_previewlanguage": "", 165 | "header": [], 166 | "cookie": [], 167 | "body": "" 168 | } 169 | ] 170 | } 171 | ], 172 | "_postman_isSubFolder": true 173 | }, 174 | { 175 | "_postman_id": "10ec1d43-1dc6-4955-a8ab-c6e5013dc591", 176 | "name": "R4", 177 | "request": { 178 | "method": "GET", 179 | "header": [], 180 | "body": {}, 181 | "url": { 182 | "raw": "" 183 | } 184 | }, 185 | "response": [] 186 | } 187 | ] 188 | } 189 | ] 190 | } -------------------------------------------------------------------------------- /test/unit/fixtures/request-body-file.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | v1: { 3 | id: '84b2b626-d3a6-0f31-c7a0-47733c01d0c2', 4 | name: 'body-src-check', 5 | order: [ 6 | '4f65e265-dd38-0a67-71a5-d9dd50fa37a1', 7 | 'c60ecf6a-6421-4446-859d-1b697f44e4e8', 8 | '3d2c6dbc-cefa-0951-2796-3f0142ff85c3' 9 | ], 10 | folders: [], 11 | folders_order: [], 12 | requests: [ 13 | { 14 | id: '4f65e265-dd38-0a67-71a5-d9dd50fa37a1', 15 | headers: '', 16 | headerData: [], 17 | url: 'https://postman-echo.com/post', 18 | queryParams: [], 19 | pathVariableData: [], 20 | method: 'POST', 21 | data: [ 22 | { 23 | key: 'file', 24 | value: 't.csv', 25 | description: 'Enabled CSV file', 26 | type: 'file' 27 | } 28 | ], 29 | dataMode: 'params', 30 | name: 'Formdata POST', 31 | collectionId: '84b2b626-d3a6-0f31-c7a0-47733c01d0c2', 32 | responses: [], 33 | responses_order: [] 34 | }, 35 | { 36 | id: 'c60ecf6a-6421-4446-859d-1b697f44e4e8', 37 | headers: '', 38 | headerData: [], 39 | url: 'https://postman-echo.com/post', 40 | queryParams: [], 41 | pathVariableData: [], 42 | method: 'POST', 43 | data: [ 44 | { 45 | key: 'file', 46 | value: ['t.csv', 's.csv'], 47 | description: 'Enabled CSV file', 48 | type: 'file' 49 | } 50 | ], 51 | dataMode: 'params', 52 | name: 'Formdata Multiple POST', 53 | collectionId: '84b2b626-d3a6-0f31-c7a0-47733c01d0c2', 54 | responses: [], 55 | responses_order: [] 56 | }, 57 | { 58 | id: '3d2c6dbc-cefa-0951-2796-3f0142ff85c3', 59 | headers: '', 60 | headerData: [], 61 | url: 'https://postman-echo.com/post', 62 | queryParams: [], 63 | pathVariableData: [], 64 | method: 'POST', 65 | dataMode: 'binary', 66 | name: 'Binary POST', 67 | collectionId: '84b2b626-d3a6-0f31-c7a0-47733c01d0c2', 68 | responses: [], 69 | rawModeData: 't.csv', 70 | responses_order: [] 71 | } 72 | ] 73 | }, 74 | v2: { 75 | info: { 76 | name: 'body-src-check', 77 | _postman_id: '84b2b626-d3a6-0f31-c7a0-47733c01d0c2', 78 | schema: 'https://schema.getpostman.com/json/collection/v2.0.0/collection.json' 79 | }, 80 | item: [ 81 | { 82 | id: '4f65e265-dd38-0a67-71a5-d9dd50fa37a1', 83 | name: 'Formdata POST', 84 | request: { 85 | url: 'https://postman-echo.com/post', 86 | method: 'POST', 87 | header: [], 88 | body: { 89 | mode: 'formdata', 90 | formdata: [ 91 | { 92 | key: 'file', 93 | description: 'Enabled CSV file', 94 | type: 'file', 95 | src: 't.csv' 96 | } 97 | ] 98 | } 99 | }, 100 | response: [] 101 | }, 102 | { 103 | id: 'c60ecf6a-6421-4446-859d-1b697f44e4e8', 104 | name: 'Formdata Multiple POST', 105 | request: { 106 | url: 'https://postman-echo.com/post', 107 | method: 'POST', 108 | header: [], 109 | body: { 110 | mode: 'formdata', 111 | formdata: [ 112 | { 113 | key: 'file', 114 | description: 'Enabled CSV file', 115 | type: 'file', 116 | src: ['t.csv', 's.csv'] 117 | } 118 | ] 119 | } 120 | }, 121 | response: [] 122 | }, 123 | { 124 | id: '3d2c6dbc-cefa-0951-2796-3f0142ff85c3', 125 | name: 'Binary POST', 126 | request: { 127 | url: 'https://postman-echo.com/post', 128 | method: 'POST', 129 | header: [], 130 | body: { 131 | mode: 'file', 132 | file: { 133 | src: 't.csv' 134 | } 135 | } 136 | }, 137 | response: [] 138 | } 139 | ] 140 | }, 141 | v21: { 142 | info: { 143 | name: 'body-src-check', 144 | _postman_id: '84b2b626-d3a6-0f31-c7a0-47733c01d0c2', 145 | schema: 'https://schema.getpostman.com/json/collection/v2.1.0/collection.json' 146 | }, 147 | item: [ 148 | { 149 | id: '4f65e265-dd38-0a67-71a5-d9dd50fa37a1', 150 | name: 'Formdata POST', 151 | request: { 152 | url: { 153 | raw: 'https://postman-echo.com/post', 154 | protocol: 'https', 155 | host: ['postman-echo', 'com'], 156 | path: ['post'] 157 | }, 158 | method: 'POST', 159 | header: [], 160 | body: { 161 | mode: 'formdata', 162 | formdata: [ 163 | { 164 | key: 'file', 165 | description: 'Enabled CSV file', 166 | type: 'file', 167 | src: 't.csv' 168 | } 169 | ] 170 | } 171 | }, 172 | response: [] 173 | }, 174 | { 175 | id: 'c60ecf6a-6421-4446-859d-1b697f44e4e8', 176 | name: 'Formdata Multiple POST', 177 | request: { 178 | url: { 179 | raw: 'https://postman-echo.com/post', 180 | protocol: 'https', 181 | host: ['postman-echo', 'com'], 182 | path: ['post'] 183 | }, 184 | method: 'POST', 185 | header: [], 186 | body: { 187 | mode: 'formdata', 188 | formdata: [ 189 | { 190 | key: 'file', 191 | description: 'Enabled CSV file', 192 | type: 'file', 193 | src: ['t.csv', 's.csv'] 194 | } 195 | ] 196 | } 197 | }, 198 | response: [] 199 | }, 200 | { 201 | id: '3d2c6dbc-cefa-0951-2796-3f0142ff85c3', 202 | name: 'Binary POST', 203 | request: { 204 | url: { 205 | raw: 'https://postman-echo.com/post', 206 | protocol: 'https', 207 | host: ['postman-echo', 'com'], 208 | path: ['post'] 209 | }, 210 | method: 'POST', 211 | header: [], 212 | body: { 213 | mode: 'file', 214 | file: { 215 | src: 't.csv' 216 | } 217 | } 218 | }, 219 | response: [] 220 | } 221 | ] 222 | } 223 | }; 224 | -------------------------------------------------------------------------------- /test/unit/lib.test.js: -------------------------------------------------------------------------------- 1 | var expect = require('chai').expect, 2 | 3 | transformer = require('../..'); 4 | 5 | describe('module', function () { 6 | describe('converter', function () { 7 | describe('convert', function () { 8 | it('should bail out with an error for falsy outputVersion values', function (done) { 9 | transformer.convert({}, { outputVersion: false }, function (err) { 10 | expect(err).to.be.an.instanceOf(Error); 11 | done(); 12 | }); 13 | }); 14 | 15 | it('should bail out with an error for invalid semver outputVersion values', function (done) { 16 | transformer.convert({}, { outputVersion: 'random' }, function (err) { 17 | expect(err).to.be.an.instanceOf(Error); 18 | done(); 19 | }); 20 | }); 21 | 22 | it('should bail out with an error for falsy inputVersion values', function (done) { 23 | transformer.convert({}, { outputVersion: '1.0.0', inputVersion: false }, function (err) { 24 | expect(err).to.be.an.instanceOf(Error); 25 | done(); 26 | }); 27 | }); 28 | 29 | it('should bail out with an error for invalid semver inputVersion values', function (done) { 30 | transformer.convert({}, { outputVersion: '1.0.0', inputVersion: 'random' }, function (err) { 31 | expect(err).to.be.an.instanceOf(Error); 32 | done(); 33 | }); 34 | }); 35 | }); 36 | 37 | describe('convertSingle', function () { 38 | it('should bail out with an error for falsy outputVersion values', function (done) { 39 | transformer.convertSingle({}, { outputVersion: false }, function (err) { 40 | expect(err).to.be.an.instanceOf(Error); 41 | done(); 42 | }); 43 | }); 44 | 45 | it('should bail out with an error for invalid semver outputVersion values', function (done) { 46 | transformer.convertSingle({}, { outputVersion: 'random' }, function (err) { 47 | expect(err).to.be.an.instanceOf(Error); 48 | done(); 49 | }); 50 | }); 51 | 52 | it('should bail out with an error for falsy inputVersion values', function (done) { 53 | transformer.convertSingle({}, { outputVersion: '1.0.0', inputVersion: false }, function (err) { 54 | expect(err).to.be.an.instanceOf(Error); 55 | done(); 56 | }); 57 | }); 58 | 59 | it('should bail out with an error for invalid semver inputVersion values', function (done) { 60 | transformer.convertSingle({}, { outputVersion: '1.0.0', inputVersion: 'random' }, function (err) { 61 | expect(err).to.be.an.instanceOf(Error); 62 | done(); 63 | }); 64 | }); 65 | }); 66 | 67 | describe('convertResponse', function () { 68 | it('should bail out with an error for falsy outputVersion values', function (done) { 69 | transformer.convertResponse({}, { outputVersion: false }, function (err) { 70 | expect(err).to.be.an.instanceOf(Error); 71 | done(); 72 | }); 73 | }); 74 | 75 | it('should bail out with an error for invalid semver outputVersion values', function (done) { 76 | transformer.convertResponse({}, { outputVersion: 'random' }, function (err) { 77 | expect(err).to.be.an.instanceOf(Error); 78 | done(); 79 | }); 80 | }); 81 | 82 | it('should bail out with an error for falsy inputVersion values', function (done) { 83 | transformer.convertResponse({}, { outputVersion: '1.0.0', inputVersion: false }, function (err) { 84 | expect(err).to.be.an.instanceOf(Error); 85 | done(); 86 | }); 87 | }); 88 | 89 | it('should bail out with an error for invalid semver inputVersion values', function (done) { 90 | transformer.convertResponse({}, { outputVersion: '1.0.0', inputVersion: 'random' }, function (err) { 91 | expect(err).to.be.an.instanceOf(Error); 92 | done(); 93 | }); 94 | }); 95 | }); 96 | }); 97 | 98 | describe('normalizer', function () { 99 | describe('normalize', function () { 100 | it('should bail out with an error for falsy normalizeVersion values', function (done) { 101 | transformer.normalize({}, { normalizeVersion: false }, function (err) { 102 | expect(err).to.be.an.instanceOf(Error); 103 | done(); 104 | }); 105 | }); 106 | 107 | it('should bail out with an error for invalid semver normalizeVersion values', function (done) { 108 | transformer.normalize({}, { normalizeVersion: 'random' }, function (err) { 109 | expect(err).to.be.an.instanceOf(Error); 110 | done(); 111 | }); 112 | }); 113 | 114 | it('should bail out with an error for non-handled normalizeVersion values', function (done) { 115 | transformer.normalize({}, { normalizeVersion: '9999.9999.9999' }, function (err) { 116 | expect(err).to.be.an.instanceOf(Error); 117 | done(); 118 | }); 119 | }); 120 | }); 121 | 122 | describe('normalizeSingle', function () { 123 | it('should bail out with an error for falsy normalizeVersion values', function (done) { 124 | transformer.normalizeSingle({}, { normalizeVersion: false }, function (err) { 125 | expect(err).to.be.an.instanceOf(Error); 126 | done(); 127 | }); 128 | }); 129 | 130 | it('should bail out with an error for invalid semver normalizeVersion values', function (done) { 131 | transformer.normalizeSingle({}, { normalizeVersion: 'random' }, function (err) { 132 | expect(err).to.be.an.instanceOf(Error); 133 | done(); 134 | }); 135 | }); 136 | 137 | it('should bail out with an error for non-handled normalizeVersion values', function (done) { 138 | transformer.normalizeSingle({}, { normalizeVersion: '9999.9999.9999' }, function (err) { 139 | expect(err).to.be.an.instanceOf(Error); 140 | done(); 141 | }); 142 | }); 143 | }); 144 | 145 | describe('normalizeResponse', function () { 146 | it('should bail out with an error for falsy normalizeVersion values', function (done) { 147 | transformer.normalizeResponse({}, { normalizeVersion: false }, function (err) { 148 | expect(err).to.be.an.instanceOf(Error); 149 | done(); 150 | }); 151 | }); 152 | 153 | it('should bail out with an error for invalid semver normalizeVersion values', function (done) { 154 | transformer.normalizeResponse({}, { normalizeVersion: 'random' }, function (err) { 155 | expect(err).to.be.an.instanceOf(Error); 156 | done(); 157 | }); 158 | }); 159 | 160 | it('should bail out with an error for non-handled normalizeVersion values', function (done) { 161 | transformer.normalizeResponse({}, { normalizeVersion: '9999.9999.9999' }, function (err) { 162 | expect(err).to.be.an.instanceOf(Error); 163 | done(); 164 | }); 165 | }); 166 | }); 167 | }); 168 | 169 | describe('isV1', function () { 170 | it('should return true/false for valid/invalid v1 collections', function () { 171 | expect(transformer.isv1).to.not.throw(); 172 | expect(transformer.isv1()).to.eql(false); 173 | expect(transformer.isv1({ name: 'Foo!', order: [], requests: [] })).to.eql(true); 174 | }); 175 | }); 176 | 177 | describe('isV2', function () { 178 | it('should return true/false for valid/invalid v2 collections', function () { 179 | expect(transformer.isv2).to.not.throw(); 180 | expect(transformer.isv2()).to.eql(false); 181 | expect(transformer.isv2({ 182 | info: { 183 | schema: 'https://schema.getpostman.com/json/collection/v2.0.0/collection.json' 184 | } 185 | })).to.eql(true); 186 | }); 187 | }); 188 | }); 189 | -------------------------------------------------------------------------------- /test/unit/util.test.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @fileoverview This test suite runs tests on the V1 to V2 converter. 3 | */ 4 | 5 | var _ = require('lodash'), 6 | expect = require('chai').expect, 7 | util = require('../../lib/util'); 8 | 9 | describe('util', function () { 10 | describe('handleVars', function () { 11 | it('should correctly fall back to defaults where applicable', function () { 12 | expect(util.handleVars({}, { 13 | retainIds: true, 14 | fallback: { values: [{ value: {}, disabled: 1 }] } 15 | })[0]).to.deep.include({ 16 | disabled: true 17 | }); 18 | }); 19 | 20 | it('should handle legacy `text` type', function () { 21 | expect(util.handleVars({}, { 22 | retainIds: true, 23 | fallback: { values: [{ value: 'foo', type: 'text' }] } 24 | })[0]).to.deep.include({ 25 | type: 'string' 26 | }); 27 | }); 28 | 29 | it('should retain id, if present on entity, and retainId is true', function () { 30 | const entity = { 31 | variables: [ 32 | { 33 | id: '1' 34 | } 35 | ] 36 | }, 37 | options = { 38 | noDefaults: true, 39 | retainIds: true 40 | }, 41 | processed = util.handleVars(entity, options); 42 | 43 | expect(processed[0]).to.have.property('id', '1'); 44 | }); 45 | 46 | it('should generate new id, if retainIds is false, and noDefaults is false', function () { 47 | const entity = { 48 | variables: [ 49 | { 50 | id: '1' 51 | } 52 | ] 53 | }, 54 | options = { 55 | noDefaults: false, 56 | retainIds: false 57 | }, 58 | processed = util.handleVars(entity, options); 59 | 60 | expect(processed[0].id).to.not.eql('1'); 61 | }); 62 | 63 | it('should generate new id, if absent on entity, if retainIds is true, and noDefaults is false', function () { 64 | const entity = { 65 | variables: [ 66 | {} 67 | ] 68 | }, 69 | options = { 70 | noDefaults: false, 71 | retainIds: true 72 | }, 73 | processed = util.handleVars(entity, options); 74 | 75 | expect(processed[0]).to.have.property('id'); 76 | }); 77 | }); 78 | 79 | describe('sanitizeAuthArray', function () { 80 | it('should correctly fall back to custom types when applicable', function () { 81 | expect(util.sanitizeAuthArray({ 82 | auth: { 83 | type: 'custom', 84 | custom: [{ key: 'foo', value: {} }] 85 | } 86 | })).to.eql({ 87 | type: 'custom', 88 | custom: [{ key: 'foo', value: {}, type: 'any' }] 89 | }); 90 | }); 91 | }); 92 | 93 | describe('notLegacy', function () { 94 | it('should bail out for falsy entities', function () { 95 | expect(util.notLegacy).not.to.throw(); 96 | expect(util.notLegacy()).to.eql(undefined); 97 | }); 98 | 99 | it('should should return true for unknown cases', function () { 100 | expect(util.notLegacy).not.to.throw(); 101 | expect(util.notLegacy({}, 'random')).to.eql(true); 102 | }); 103 | }); 104 | 105 | describe('auth mappers', function () { 106 | describe('legacy', function () { 107 | _.forEach(util.authMappersFromLegacy, function (func, auth) { 108 | it(`should handle falsy input correctly for ${auth}`, function () { 109 | expect(func).to.not.throw(); 110 | expect(func()).to.equal(undefined); 111 | expect(func({})).to.be.ok; 112 | }); 113 | }); 114 | }); 115 | 116 | describe('contemporary', function () { 117 | _.forEach(util.authMappersFromCurrent, function (func, auth) { 118 | it(`should handle falsy input correctly for ${auth}`, function () { 119 | expect(func).to.not.throw(); 120 | expect(func()).to.equal(undefined); 121 | expect(func({})).to.be.ok; 122 | }); 123 | }); 124 | }); 125 | }); 126 | 127 | describe('addProtocolProfileBehavior', function () { 128 | it('should add protocolProfileBehavior property to the destination object', function () { 129 | var source = { 130 | foo: 'bar', 131 | protocolProfileBehavior: { 132 | disableBodyPruning: true 133 | } 134 | }, 135 | destination = {}; 136 | 137 | expect(util.addProtocolProfileBehavior(source, destination)).to.be.true; 138 | expect(destination).to.eql({ 139 | protocolProfileBehavior: { 140 | disableBodyPruning: true 141 | } 142 | }); 143 | }); 144 | 145 | it('should not add protocolProfileBehavior property for invalid values', function () { 146 | var source = { 147 | protocolProfileBehavior: 'random' 148 | }, 149 | destination = {}; 150 | 151 | expect(util.addProtocolProfileBehavior(source, destination)).to.be.false; 152 | expect(destination).to.eql({}); 153 | }); 154 | 155 | it('should handle missing destination object correctly', function () { 156 | expect(util.addProtocolProfileBehavior({ 157 | protocolProfileBehavior: { 158 | disableBodyPruning: true 159 | } 160 | })).to.be.true; 161 | 162 | expect(util.addProtocolProfileBehavior({ 163 | protocolProfileBehavior: 'random' 164 | })).to.be.false; 165 | 166 | expect(util.addProtocolProfileBehavior({ 167 | protocolProfileBehavior: null 168 | })).to.be.false; 169 | 170 | expect(util.addProtocolProfileBehavior({ 171 | foo: 'bar' 172 | })).to.be.false; 173 | 174 | expect(util.addProtocolProfileBehavior('random')).to.be.false; 175 | 176 | expect(util.addProtocolProfileBehavior()).to.be.false; 177 | }); 178 | }); 179 | }); 180 | --------------------------------------------------------------------------------