├── .github └── workflows │ └── npm-publish.yaml ├── .gitignore ├── LICENSE ├── README.md ├── images ├── summary_report.png ├── tall_report.png └── wide_report.png ├── integration ├── package.json ├── petstore-collection.postman.json ├── petstore-openapi.yaml └── petstore-portman │ ├── newman-options.json │ └── portman-cli.json ├── lib ├── clireporter.js ├── index.js └── tracker.js ├── package-lock.json ├── package.json └── tests ├── dupe-ref.json ├── dupe-ref.yaml ├── dupe-schema.json ├── dupe-schema.yaml ├── invalid-schema.yaml ├── path-ordering.yaml ├── refpath.yaml ├── tracker.test.js └── valid-schema.yaml /.github/workflows/npm-publish.yaml: -------------------------------------------------------------------------------- 1 | name: Publish Package to npmjs 2 | on: 3 | release: 4 | types: [created] 5 | jobs: 6 | build: 7 | runs-on: ubuntu-latest 8 | steps: 9 | - uses: actions/checkout@v2 10 | # Setup .npmrc file to publish to npm 11 | - uses: actions/setup-node@v2 12 | with: 13 | node-version: '14.x' 14 | registry-url: 'https://registry.npmjs.org' 15 | - run: npm ci 16 | - run: npm test 17 | - run: npm publish 18 | env: 19 | NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} 20 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | tmp 2 | 3 | # Logs 4 | logs 5 | *.log 6 | npm-debug.log* 7 | yarn-debug.log* 8 | yarn-error.log* 9 | lerna-debug.log* 10 | 11 | # Diagnostic reports (https://nodejs.org/api/report.html) 12 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 13 | 14 | # Runtime data 15 | pids 16 | *.pid 17 | *.seed 18 | *.pid.lock 19 | 20 | # Directory for instrumented libs generated by jscoverage/JSCover 21 | lib-cov 22 | 23 | # Coverage directory used by tools like istanbul 24 | coverage 25 | *.lcov 26 | 27 | # nyc test coverage 28 | .nyc_output 29 | 30 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 31 | .grunt 32 | 33 | # Bower dependency directory (https://bower.io/) 34 | bower_components 35 | 36 | # node-waf configuration 37 | .lock-wscript 38 | 39 | # Compiled binary addons (https://nodejs.org/api/addons.html) 40 | build/Release 41 | 42 | # Dependency directories 43 | node_modules/ 44 | jspm_packages/ 45 | 46 | # TypeScript v1 declaration files 47 | typings/ 48 | 49 | # TypeScript cache 50 | *.tsbuildinfo 51 | 52 | # Optional npm cache directory 53 | .npm 54 | 55 | # Optional eslint cache 56 | .eslintcache 57 | 58 | # Microbundle cache 59 | .rpt2_cache/ 60 | .rts2_cache_cjs/ 61 | .rts2_cache_es/ 62 | .rts2_cache_umd/ 63 | 64 | # Optional REPL history 65 | .node_repl_history 66 | 67 | # Output of 'npm pack' 68 | *.tgz 69 | 70 | # Yarn Integrity file 71 | .yarn-integrity 72 | 73 | # dotenv environment variables file 74 | .env 75 | .env.test 76 | 77 | # parcel-bundler cache (https://parceljs.org/) 78 | .cache 79 | 80 | # Next.js build output 81 | .next 82 | 83 | # Nuxt.js build / generate output 84 | .nuxt 85 | dist 86 | 87 | # Gatsby files 88 | .cache/ 89 | # Comment in the public line in if your project uses Gatsby and *not* Next.js 90 | # https://nextjs.org/blog/next-9-1#public-directory-support 91 | # public 92 | 93 | # vuepress build output 94 | .vuepress/dist 95 | 96 | # Serverless directories 97 | .serverless/ 98 | 99 | # FuseBox cache 100 | .fusebox/ 101 | 102 | # DynamoDB Local files 103 | .dynamodb/ 104 | 105 | # TernJS port file 106 | .tern-port 107 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Nick Heap 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # newman-reporter-openapi 2 | ## Newman reporter for openapi spec coverage 3 | --- 4 | 5 | This is a Newman OpenAPI reporter for generating coverage reports from a Newman run based on an OpenAPI specification. 6 | 7 | It was inspired by the openapi-backend projects route matching and a desire to see how much of the OpenAPI spec automated test generators were producing. 8 | 9 | It determines coverage as how much of the path/method/response tree has requests made during the run. 10 | 11 | ``` 12 | ├── path 13 | | └── method 14 | | ├── response 15 | | ├── response 16 | | └── response 17 | └── path 18 | └── method 19 | ├── response 20 | └── response 21 | ``` 22 | 23 | It produces output like this: 24 | ![wide](https://github.com/NickHeap2/newman-reporter-openapi/blob/367b9daf8710e8e1f3f4b614604a27fecac7eaab/images/wide_report.png) 25 | 26 | ### Install the reporter 27 | --- 28 | ```console 29 | npm install newman-reporter-openapi 30 | or 31 | npm install -g newman-reporter-openapi 32 | ``` 33 | 34 | ### Reporter options 35 | --- 36 | 37 | Add the report as a custom Newman reporter: 38 | ```console 39 | newman --reporters openapi 40 | ``` 41 | 42 | You can include multiple Newman reporters like this: 43 | ```console 44 | newman --reporters "cli,openapi" 45 | ``` 46 | 47 | The only required parameter for the OpenAPI reporter is the OpenAPI spec using --reporter-openapi-spec: 48 | ```console 49 | --reporter-openapi-spec ./openapi.yaml 50 | ``` 51 | 52 | The reporter will check each Newman API call against the server list in your OpenAPI spec. 53 | 54 | If the server isn't in that list, for local testing for example, you can specify it via --reporter-openapi-serverUrl 55 | ```console 56 | --reporter-openapi-serverUrl http://127.0.0.1/3000 57 | ``` 58 | 59 | The reporter has three different report styles with different layouts. The default is wide. 60 | 61 | ```console 62 | --reporter-openapi-reportstyle wide 63 | --reporter-openapi-reportstyle tall 64 | --reporter-openapi-reportstyle summary 65 | ``` 66 | 67 | Coming soon --exportFilename for a json based export of the coverage. 68 | 69 | ### Report symbols 70 | --- 71 | 72 | In the reports the response codes have the following symbols: 73 | * \+ shows a response that was received 74 | * \- shows a response that was not received 75 | * \? shows a received response that was not part of the spec 76 | 77 | ### Report styles 78 | --- 79 | 80 | There are three different versions of the report. 81 | 82 | wide - best for when your spec has many different paths (the default) 83 | ![wide](https://github.com/NickHeap2/newman-reporter-openapi/blob/367b9daf8710e8e1f3f4b614604a27fecac7eaab/images/wide_report.png) 84 | 85 | tall - an option for APIs with a small number of paths otherwise it can get too tall 86 | ![tall](https://github.com/NickHeap2/newman-reporter-openapi/blob/2a95a92573fb1678fa03594f52c9648b1bc1921a/images/tall_report.png) 87 | 88 | summary - for a basic summary of the coverage without path or response details 89 | ![summary](https://github.com/NickHeap2/newman-reporter-openapi/blob/367b9daf8710e8e1f3f4b614604a27fecac7eaab/images/summary_report.png) -------------------------------------------------------------------------------- /images/summary_report.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NickHeap2/newman-reporter-openapi/00ce6cdcc7b10b825a6f0426a3d4bbf85f8ae4fd/images/summary_report.png -------------------------------------------------------------------------------- /images/tall_report.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NickHeap2/newman-reporter-openapi/00ce6cdcc7b10b825a6f0426a3d4bbf85f8ae4fd/images/tall_report.png -------------------------------------------------------------------------------- /images/wide_report.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NickHeap2/newman-reporter-openapi/00ce6cdcc7b10b825a6f0426a3d4bbf85f8ae4fd/images/wide_report.png -------------------------------------------------------------------------------- /integration/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "newman-reporter-openapi-tester", 3 | "version": "0.0.1", 4 | "description": "Newman reporter for openapi coverage tester", 5 | "scripts": { 6 | "start-petstore": ".\\node_modules\\.bin\\portman --baseUrl http://127.0.0.1:4010 --cliOptionsFile petstore-portman/portman-cli.json --newmanOptionsFile petstore-portman/newman-options.json" 7 | }, 8 | "files": [ 9 | "lib/**" 10 | ], 11 | "author": { 12 | "name": "Nick Heap", 13 | "email": "nickheap@gmail.com", 14 | "url": "https://github.com/NickHeap2" 15 | }, 16 | "license": "MIT", 17 | "devDependencies": { 18 | "@apideck/portman": "^1.12.1", 19 | "newman-reporter-openapi": "file:../newman-reporter-openapi-0.0.1.tgz" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /integration/petstore-collection.postman.json: -------------------------------------------------------------------------------- 1 | { 2 | "_": { 3 | "postman_id": "eaeacca3-dcfa-4c76-b50f-3b2e783dff9d" 4 | }, 5 | "item": [ 6 | { 7 | "id": "9d09c695-aa38-4414-bdec-f550fdf8eee9", 8 | "name": "pet", 9 | "description": { 10 | "content": "Everything about your Pets", 11 | "type": "text/plain" 12 | }, 13 | "item": [ 14 | { 15 | "id": "f4786e7c-3200-4652-bc0e-96ed2b9c884b", 16 | "name": "Update an existing pet", 17 | "request": { 18 | "name": "Update an existing pet", 19 | "description": { 20 | "content": "Update an existing pet by Id", 21 | "type": "text/plain" 22 | }, 23 | "url": { 24 | "path": [ 25 | "pet" 26 | ], 27 | "host": [ 28 | "{{baseUrl}}" 29 | ], 30 | "query": [], 31 | "variable": [] 32 | }, 33 | "header": [ 34 | { 35 | "key": "Content-Type", 36 | "value": "application/x-www-form-urlencoded" 37 | } 38 | ], 39 | "method": "PUT", 40 | "body": { 41 | "mode": "urlencoded", 42 | "urlencoded": [ 43 | { 44 | "disabled": false, 45 | "description": { 46 | "content": "(Required) ", 47 | "type": "text/plain" 48 | }, 49 | "key": "name", 50 | "value": "doggie" 51 | }, 52 | { 53 | "disabled": false, 54 | "description": { 55 | "content": "(Required) ", 56 | "type": "text/plain" 57 | }, 58 | "key": "photoUrls", 59 | "value": "elit mollit cupidatat" 60 | }, 61 | { 62 | "disabled": false, 63 | "description": { 64 | "content": "(Required) ", 65 | "type": "text/plain" 66 | }, 67 | "key": "photoUrls", 68 | "value": "cillum commodo" 69 | }, 70 | { 71 | "disabled": false, 72 | "key": "id", 73 | "value": "10" 74 | }, 75 | { 76 | "disabled": false, 77 | "key": "id", 78 | "value": "1" 79 | }, 80 | { 81 | "disabled": false, 82 | "key": "name", 83 | "value": "Dogs" 84 | }, 85 | { 86 | "disabled": false, 87 | "key": "tags", 88 | "value": "{\"id\":90427378,\"name\":\"eu commodo cupida\"}" 89 | }, 90 | { 91 | "disabled": false, 92 | "key": "tags", 93 | "value": "{\"id\":-58905690,\"name\":\"do ut ea consectetur\"}" 94 | }, 95 | { 96 | "disabled": false, 97 | "description": { 98 | "content": "pet status in the store", 99 | "type": "text/plain" 100 | }, 101 | "key": "status", 102 | "value": "pending" 103 | } 104 | ] 105 | }, 106 | "auth": { 107 | "type": "oauth2", 108 | "oauth2": [] 109 | } 110 | }, 111 | "response": [ 112 | { 113 | "_": { 114 | "postman_previewlanguage": "json" 115 | }, 116 | "id": "637ef932-dfae-421b-9bf4-a413eceda5bd", 117 | "name": "Successful operation", 118 | "originalRequest": { 119 | "url": { 120 | "path": [ 121 | "pet" 122 | ], 123 | "host": [ 124 | "{{baseUrl}}" 125 | ], 126 | "query": [], 127 | "variable": [] 128 | }, 129 | "header": [ 130 | { 131 | "description": { 132 | "content": "Added as a part of security scheme: oauth2", 133 | "type": "text/plain" 134 | }, 135 | "key": "Authorization", 136 | "value": "" 137 | } 138 | ], 139 | "method": "PUT", 140 | "body": { 141 | "mode": "urlencoded", 142 | "urlencoded": [ 143 | { 144 | "disabled": false, 145 | "description": { 146 | "content": "(Required) ", 147 | "type": "text/plain" 148 | }, 149 | "key": "name", 150 | "value": "doggie" 151 | }, 152 | { 153 | "disabled": false, 154 | "description": { 155 | "content": "(Required) ", 156 | "type": "text/plain" 157 | }, 158 | "key": "photoUrls", 159 | "value": "ipsum" 160 | }, 161 | { 162 | "disabled": false, 163 | "description": { 164 | "content": "(Required) ", 165 | "type": "text/plain" 166 | }, 167 | "key": "photoUrls", 168 | "value": "aliqua" 169 | }, 170 | { 171 | "disabled": false, 172 | "key": "id", 173 | "value": "10" 174 | }, 175 | { 176 | "disabled": false, 177 | "key": "id", 178 | "value": "1" 179 | }, 180 | { 181 | "disabled": false, 182 | "key": "name", 183 | "value": "Dogs" 184 | }, 185 | { 186 | "disabled": false, 187 | "key": "tags", 188 | "value": "{\"id\":24945634,\"name\":\"Excepteur in cupidatat eu\"}" 189 | }, 190 | { 191 | "disabled": false, 192 | "key": "tags", 193 | "value": "{\"id\":99529413,\"name\":\"cillum sunt cupidatat\"}" 194 | }, 195 | { 196 | "disabled": false, 197 | "description": { 198 | "content": "pet status in the store", 199 | "type": "text/plain" 200 | }, 201 | "key": "status", 202 | "value": "sold" 203 | } 204 | ] 205 | } 206 | }, 207 | "status": "OK", 208 | "code": 200, 209 | "header": [ 210 | { 211 | "key": "Content-Type", 212 | "value": "application/json" 213 | } 214 | ], 215 | "body": "{\n \"name\": \"doggie\",\n \"photoUrls\": [\n \"ipsum\",\n \"aliqua\"\n ],\n \"id\": 10,\n \"category\": {\n \"id\": 1,\n \"name\": \"Dogs\"\n },\n \"tags\": [\n {\n \"id\": 24945634,\n \"name\": \"Excepteur in cupidatat eu\"\n },\n {\n \"id\": 99529413,\n \"name\": \"cillum sunt cupidatat\"\n }\n ],\n \"status\": \"sold\"\n}", 216 | "cookie": [] 217 | }, 218 | { 219 | "_": { 220 | "postman_previewlanguage": "text" 221 | }, 222 | "id": "dfd31f3d-25d7-4441-91fc-9a99114dcdc0", 223 | "name": "Invalid ID supplied", 224 | "originalRequest": { 225 | "url": { 226 | "path": [ 227 | "pet" 228 | ], 229 | "host": [ 230 | "{{baseUrl}}" 231 | ], 232 | "query": [], 233 | "variable": [] 234 | }, 235 | "header": [ 236 | { 237 | "description": { 238 | "content": "Added as a part of security scheme: oauth2", 239 | "type": "text/plain" 240 | }, 241 | "key": "Authorization", 242 | "value": "" 243 | } 244 | ], 245 | "method": "PUT", 246 | "body": { 247 | "mode": "urlencoded", 248 | "urlencoded": [ 249 | { 250 | "disabled": false, 251 | "description": { 252 | "content": "(Required) ", 253 | "type": "text/plain" 254 | }, 255 | "key": "name", 256 | "value": "doggie" 257 | }, 258 | { 259 | "disabled": false, 260 | "description": { 261 | "content": "(Required) ", 262 | "type": "text/plain" 263 | }, 264 | "key": "photoUrls", 265 | "value": "ipsum" 266 | }, 267 | { 268 | "disabled": false, 269 | "description": { 270 | "content": "(Required) ", 271 | "type": "text/plain" 272 | }, 273 | "key": "photoUrls", 274 | "value": "aliqua" 275 | }, 276 | { 277 | "disabled": false, 278 | "key": "id", 279 | "value": "10" 280 | }, 281 | { 282 | "disabled": false, 283 | "key": "id", 284 | "value": "1" 285 | }, 286 | { 287 | "disabled": false, 288 | "key": "name", 289 | "value": "Dogs" 290 | }, 291 | { 292 | "disabled": false, 293 | "key": "tags", 294 | "value": "{\"id\":24945634,\"name\":\"Excepteur in cupidatat eu\"}" 295 | }, 296 | { 297 | "disabled": false, 298 | "key": "tags", 299 | "value": "{\"id\":99529413,\"name\":\"cillum sunt cupidatat\"}" 300 | }, 301 | { 302 | "disabled": false, 303 | "description": { 304 | "content": "pet status in the store", 305 | "type": "text/plain" 306 | }, 307 | "key": "status", 308 | "value": "sold" 309 | } 310 | ] 311 | } 312 | }, 313 | "status": "Bad Request", 314 | "code": 400, 315 | "header": [ 316 | { 317 | "key": "Content-Type", 318 | "value": "text/plain" 319 | } 320 | ], 321 | "body": "", 322 | "cookie": [] 323 | }, 324 | { 325 | "_": { 326 | "postman_previewlanguage": "text" 327 | }, 328 | "id": "3093a64f-c156-4355-ad8f-28c91abf517e", 329 | "name": "Pet not found", 330 | "originalRequest": { 331 | "url": { 332 | "path": [ 333 | "pet" 334 | ], 335 | "host": [ 336 | "{{baseUrl}}" 337 | ], 338 | "query": [], 339 | "variable": [] 340 | }, 341 | "header": [ 342 | { 343 | "description": { 344 | "content": "Added as a part of security scheme: oauth2", 345 | "type": "text/plain" 346 | }, 347 | "key": "Authorization", 348 | "value": "" 349 | } 350 | ], 351 | "method": "PUT", 352 | "body": { 353 | "mode": "urlencoded", 354 | "urlencoded": [ 355 | { 356 | "disabled": false, 357 | "description": { 358 | "content": "(Required) ", 359 | "type": "text/plain" 360 | }, 361 | "key": "name", 362 | "value": "doggie" 363 | }, 364 | { 365 | "disabled": false, 366 | "description": { 367 | "content": "(Required) ", 368 | "type": "text/plain" 369 | }, 370 | "key": "photoUrls", 371 | "value": "ipsum" 372 | }, 373 | { 374 | "disabled": false, 375 | "description": { 376 | "content": "(Required) ", 377 | "type": "text/plain" 378 | }, 379 | "key": "photoUrls", 380 | "value": "aliqua" 381 | }, 382 | { 383 | "disabled": false, 384 | "key": "id", 385 | "value": "10" 386 | }, 387 | { 388 | "disabled": false, 389 | "key": "id", 390 | "value": "1" 391 | }, 392 | { 393 | "disabled": false, 394 | "key": "name", 395 | "value": "Dogs" 396 | }, 397 | { 398 | "disabled": false, 399 | "key": "tags", 400 | "value": "{\"id\":24945634,\"name\":\"Excepteur in cupidatat eu\"}" 401 | }, 402 | { 403 | "disabled": false, 404 | "key": "tags", 405 | "value": "{\"id\":99529413,\"name\":\"cillum sunt cupidatat\"}" 406 | }, 407 | { 408 | "disabled": false, 409 | "description": { 410 | "content": "pet status in the store", 411 | "type": "text/plain" 412 | }, 413 | "key": "status", 414 | "value": "sold" 415 | } 416 | ] 417 | } 418 | }, 419 | "status": "Not Found", 420 | "code": 404, 421 | "header": [ 422 | { 423 | "key": "Content-Type", 424 | "value": "text/plain" 425 | } 426 | ], 427 | "body": "", 428 | "cookie": [] 429 | }, 430 | { 431 | "_": { 432 | "postman_previewlanguage": "text" 433 | }, 434 | "id": "98b9a1f8-3b51-4b01-b552-2cead0f60ad7", 435 | "name": "Validation exception", 436 | "originalRequest": { 437 | "url": { 438 | "path": [ 439 | "pet" 440 | ], 441 | "host": [ 442 | "{{baseUrl}}" 443 | ], 444 | "query": [], 445 | "variable": [] 446 | }, 447 | "header": [ 448 | { 449 | "description": { 450 | "content": "Added as a part of security scheme: oauth2", 451 | "type": "text/plain" 452 | }, 453 | "key": "Authorization", 454 | "value": "" 455 | } 456 | ], 457 | "method": "PUT", 458 | "body": { 459 | "mode": "urlencoded", 460 | "urlencoded": [ 461 | { 462 | "disabled": false, 463 | "description": { 464 | "content": "(Required) ", 465 | "type": "text/plain" 466 | }, 467 | "key": "name", 468 | "value": "doggie" 469 | }, 470 | { 471 | "disabled": false, 472 | "description": { 473 | "content": "(Required) ", 474 | "type": "text/plain" 475 | }, 476 | "key": "photoUrls", 477 | "value": "ipsum" 478 | }, 479 | { 480 | "disabled": false, 481 | "description": { 482 | "content": "(Required) ", 483 | "type": "text/plain" 484 | }, 485 | "key": "photoUrls", 486 | "value": "aliqua" 487 | }, 488 | { 489 | "disabled": false, 490 | "key": "id", 491 | "value": "10" 492 | }, 493 | { 494 | "disabled": false, 495 | "key": "id", 496 | "value": "1" 497 | }, 498 | { 499 | "disabled": false, 500 | "key": "name", 501 | "value": "Dogs" 502 | }, 503 | { 504 | "disabled": false, 505 | "key": "tags", 506 | "value": "{\"id\":24945634,\"name\":\"Excepteur in cupidatat eu\"}" 507 | }, 508 | { 509 | "disabled": false, 510 | "key": "tags", 511 | "value": "{\"id\":99529413,\"name\":\"cillum sunt cupidatat\"}" 512 | }, 513 | { 514 | "disabled": false, 515 | "description": { 516 | "content": "pet status in the store", 517 | "type": "text/plain" 518 | }, 519 | "key": "status", 520 | "value": "sold" 521 | } 522 | ] 523 | } 524 | }, 525 | "status": "Method Not Allowed", 526 | "code": 405, 527 | "header": [ 528 | { 529 | "key": "Content-Type", 530 | "value": "text/plain" 531 | } 532 | ], 533 | "body": "", 534 | "cookie": [] 535 | } 536 | ], 537 | "event": [] 538 | }, 539 | { 540 | "id": "fc75fd11-9543-4541-a0b3-44169f3ce0ff", 541 | "name": "Add a new pet to the store", 542 | "request": { 543 | "name": "Add a new pet to the store", 544 | "description": { 545 | "content": "Add a new pet to the store", 546 | "type": "text/plain" 547 | }, 548 | "url": { 549 | "path": [ 550 | "pet" 551 | ], 552 | "host": [ 553 | "{{baseUrl}}" 554 | ], 555 | "query": [], 556 | "variable": [] 557 | }, 558 | "header": [ 559 | { 560 | "key": "Content-Type", 561 | "value": "application/x-www-form-urlencoded" 562 | } 563 | ], 564 | "method": "POST", 565 | "body": { 566 | "mode": "urlencoded", 567 | "urlencoded": [ 568 | { 569 | "disabled": false, 570 | "description": { 571 | "content": "(Required) ", 572 | "type": "text/plain" 573 | }, 574 | "key": "name", 575 | "value": "doggie" 576 | }, 577 | { 578 | "disabled": false, 579 | "description": { 580 | "content": "(Required) ", 581 | "type": "text/plain" 582 | }, 583 | "key": "photoUrls", 584 | "value": "ipsum" 585 | }, 586 | { 587 | "disabled": false, 588 | "description": { 589 | "content": "(Required) ", 590 | "type": "text/plain" 591 | }, 592 | "key": "photoUrls", 593 | "value": "aliqua" 594 | }, 595 | { 596 | "disabled": false, 597 | "key": "id", 598 | "value": "10" 599 | }, 600 | { 601 | "disabled": false, 602 | "key": "id", 603 | "value": "1" 604 | }, 605 | { 606 | "disabled": false, 607 | "key": "name", 608 | "value": "Dogs" 609 | }, 610 | { 611 | "disabled": false, 612 | "key": "tags", 613 | "value": "{\"id\":24945634,\"name\":\"Excepteur in cupidatat eu\"}" 614 | }, 615 | { 616 | "disabled": false, 617 | "key": "tags", 618 | "value": "{\"id\":99529413,\"name\":\"cillum sunt cupidatat\"}" 619 | }, 620 | { 621 | "disabled": false, 622 | "description": { 623 | "content": "pet status in the store", 624 | "type": "text/plain" 625 | }, 626 | "key": "status", 627 | "value": "sold" 628 | } 629 | ] 630 | }, 631 | "auth": { 632 | "type": "oauth2", 633 | "oauth2": [] 634 | } 635 | }, 636 | "response": [ 637 | { 638 | "_": { 639 | "postman_previewlanguage": "json" 640 | }, 641 | "id": "306b8bdf-18f2-4a0e-9e28-50c47f7ded21", 642 | "name": "Successful operation", 643 | "originalRequest": { 644 | "url": { 645 | "path": [ 646 | "pet" 647 | ], 648 | "host": [ 649 | "{{baseUrl}}" 650 | ], 651 | "query": [], 652 | "variable": [] 653 | }, 654 | "header": [ 655 | { 656 | "description": { 657 | "content": "Added as a part of security scheme: oauth2", 658 | "type": "text/plain" 659 | }, 660 | "key": "Authorization", 661 | "value": "" 662 | } 663 | ], 664 | "method": "POST", 665 | "body": { 666 | "mode": "urlencoded", 667 | "urlencoded": [ 668 | { 669 | "disabled": false, 670 | "description": { 671 | "content": "(Required) ", 672 | "type": "text/plain" 673 | }, 674 | "key": "name", 675 | "value": "doggie" 676 | }, 677 | { 678 | "disabled": false, 679 | "description": { 680 | "content": "(Required) ", 681 | "type": "text/plain" 682 | }, 683 | "key": "photoUrls", 684 | "value": "ipsum" 685 | }, 686 | { 687 | "disabled": false, 688 | "description": { 689 | "content": "(Required) ", 690 | "type": "text/plain" 691 | }, 692 | "key": "photoUrls", 693 | "value": "aliqua" 694 | }, 695 | { 696 | "disabled": false, 697 | "key": "id", 698 | "value": "10" 699 | }, 700 | { 701 | "disabled": false, 702 | "key": "id", 703 | "value": "1" 704 | }, 705 | { 706 | "disabled": false, 707 | "key": "name", 708 | "value": "Dogs" 709 | }, 710 | { 711 | "disabled": false, 712 | "key": "tags", 713 | "value": "{\"id\":24945634,\"name\":\"Excepteur in cupidatat eu\"}" 714 | }, 715 | { 716 | "disabled": false, 717 | "key": "tags", 718 | "value": "{\"id\":99529413,\"name\":\"cillum sunt cupidatat\"}" 719 | }, 720 | { 721 | "disabled": false, 722 | "description": { 723 | "content": "pet status in the store", 724 | "type": "text/plain" 725 | }, 726 | "key": "status", 727 | "value": "sold" 728 | } 729 | ] 730 | } 731 | }, 732 | "status": "OK", 733 | "code": 200, 734 | "header": [ 735 | { 736 | "key": "Content-Type", 737 | "value": "application/json" 738 | } 739 | ], 740 | "body": "{\n \"name\": \"doggie\",\n \"photoUrls\": [\n \"ipsum\",\n \"aliqua\"\n ],\n \"id\": 10,\n \"category\": {\n \"id\": 1,\n \"name\": \"Dogs\"\n },\n \"tags\": [\n {\n \"id\": 24945634,\n \"name\": \"Excepteur in cupidatat eu\"\n },\n {\n \"id\": 99529413,\n \"name\": \"cillum sunt cupidatat\"\n }\n ],\n \"status\": \"sold\"\n}", 741 | "cookie": [] 742 | }, 743 | { 744 | "_": { 745 | "postman_previewlanguage": "text" 746 | }, 747 | "id": "e8291585-5135-451e-8b0c-c767519c674b", 748 | "name": "Invalid input", 749 | "originalRequest": { 750 | "url": { 751 | "path": [ 752 | "pet" 753 | ], 754 | "host": [ 755 | "{{baseUrl}}" 756 | ], 757 | "query": [], 758 | "variable": [] 759 | }, 760 | "header": [ 761 | { 762 | "description": { 763 | "content": "Added as a part of security scheme: oauth2", 764 | "type": "text/plain" 765 | }, 766 | "key": "Authorization", 767 | "value": "" 768 | } 769 | ], 770 | "method": "POST", 771 | "body": { 772 | "mode": "urlencoded", 773 | "urlencoded": [ 774 | { 775 | "disabled": false, 776 | "description": { 777 | "content": "(Required) ", 778 | "type": "text/plain" 779 | }, 780 | "key": "name", 781 | "value": "doggie" 782 | }, 783 | { 784 | "disabled": false, 785 | "description": { 786 | "content": "(Required) ", 787 | "type": "text/plain" 788 | }, 789 | "key": "photoUrls", 790 | "value": "ipsum" 791 | }, 792 | { 793 | "disabled": false, 794 | "description": { 795 | "content": "(Required) ", 796 | "type": "text/plain" 797 | }, 798 | "key": "photoUrls", 799 | "value": "aliqua" 800 | }, 801 | { 802 | "disabled": false, 803 | "key": "id", 804 | "value": "10" 805 | }, 806 | { 807 | "disabled": false, 808 | "key": "id", 809 | "value": "1" 810 | }, 811 | { 812 | "disabled": false, 813 | "key": "name", 814 | "value": "Dogs" 815 | }, 816 | { 817 | "disabled": false, 818 | "key": "tags", 819 | "value": "{\"id\":24945634,\"name\":\"Excepteur in cupidatat eu\"}" 820 | }, 821 | { 822 | "disabled": false, 823 | "key": "tags", 824 | "value": "{\"id\":99529413,\"name\":\"cillum sunt cupidatat\"}" 825 | }, 826 | { 827 | "disabled": false, 828 | "description": { 829 | "content": "pet status in the store", 830 | "type": "text/plain" 831 | }, 832 | "key": "status", 833 | "value": "sold" 834 | } 835 | ] 836 | } 837 | }, 838 | "status": "Method Not Allowed", 839 | "code": 405, 840 | "header": [ 841 | { 842 | "key": "Content-Type", 843 | "value": "text/plain" 844 | } 845 | ], 846 | "body": "", 847 | "cookie": [] 848 | } 849 | ], 850 | "event": [] 851 | }, 852 | { 853 | "id": "2dc4e9d4-d3cc-4f14-a64b-1b13d8300b91", 854 | "name": "Finds Pets by status", 855 | "request": { 856 | "name": "Finds Pets by status", 857 | "description": { 858 | "content": "Multiple status values can be provided with comma separated strings", 859 | "type": "text/plain" 860 | }, 861 | "url": { 862 | "path": [ 863 | "pet", 864 | "findByStatus" 865 | ], 866 | "host": [ 867 | "{{baseUrl}}" 868 | ], 869 | "query": [ 870 | { 871 | "disabled": false, 872 | "description": { 873 | "content": "Status values that need to be considered for filter", 874 | "type": "text/plain" 875 | }, 876 | "key": "status", 877 | "value": "available" 878 | } 879 | ], 880 | "variable": [] 881 | }, 882 | "method": "GET", 883 | "auth": { 884 | "type": "oauth2", 885 | "oauth2": [] 886 | } 887 | }, 888 | "response": [ 889 | { 890 | "_": { 891 | "postman_previewlanguage": "json" 892 | }, 893 | "id": "981e7d23-be41-41ef-96e2-ed61606ff118", 894 | "name": "successful operation", 895 | "originalRequest": { 896 | "url": { 897 | "path": [ 898 | "pet", 899 | "findByStatus" 900 | ], 901 | "host": [ 902 | "{{baseUrl}}" 903 | ], 904 | "query": [ 905 | { 906 | "key": "status", 907 | "value": "available" 908 | } 909 | ], 910 | "variable": [] 911 | }, 912 | "header": [ 913 | { 914 | "description": { 915 | "content": "Added as a part of security scheme: oauth2", 916 | "type": "text/plain" 917 | }, 918 | "key": "Authorization", 919 | "value": "" 920 | } 921 | ], 922 | "method": "GET", 923 | "body": {} 924 | }, 925 | "status": "OK", 926 | "code": 200, 927 | "header": [ 928 | { 929 | "key": "Content-Type", 930 | "value": "application/json" 931 | } 932 | ], 933 | "body": "[\n {\n \"name\": \"doggie\",\n \"photoUrls\": [\n \"proident est\",\n \"dolore non dolor\"\n ],\n \"id\": 10,\n \"category\": {\n \"id\": 1,\n \"name\": \"Dogs\"\n },\n \"tags\": [\n {\n \"id\": -79071447,\n \"name\": \"exercitation nisi mollit ullamco\"\n },\n {\n \"id\": -92943178,\n \"name\": \"officia ut\"\n }\n ],\n \"status\": \"sold\"\n },\n {\n \"name\": \"doggie\",\n \"photoUrls\": [\n \"dolor est\",\n \"sint tempor\"\n ],\n \"id\": 10,\n \"category\": {\n \"id\": 1,\n \"name\": \"Dogs\"\n },\n \"tags\": [\n {\n \"id\": 59926836,\n \"name\": \"irure\"\n },\n {\n \"id\": -18047884,\n \"name\": \"aute laboris culpa exercitation ullamco\"\n }\n ],\n \"status\": \"available\"\n }\n]", 934 | "cookie": [] 935 | }, 936 | { 937 | "_": { 938 | "postman_previewlanguage": "text" 939 | }, 940 | "id": "8cf5a412-b9cf-4312-b737-1ead0ae7a53a", 941 | "name": "Invalid status value", 942 | "originalRequest": { 943 | "url": { 944 | "path": [ 945 | "pet", 946 | "findByStatus" 947 | ], 948 | "host": [ 949 | "{{baseUrl}}" 950 | ], 951 | "query": [ 952 | { 953 | "key": "status", 954 | "value": "available" 955 | } 956 | ], 957 | "variable": [] 958 | }, 959 | "header": [ 960 | { 961 | "description": { 962 | "content": "Added as a part of security scheme: oauth2", 963 | "type": "text/plain" 964 | }, 965 | "key": "Authorization", 966 | "value": "" 967 | } 968 | ], 969 | "method": "GET", 970 | "body": {} 971 | }, 972 | "status": "Bad Request", 973 | "code": 400, 974 | "header": [ 975 | { 976 | "key": "Content-Type", 977 | "value": "text/plain" 978 | } 979 | ], 980 | "body": "", 981 | "cookie": [] 982 | } 983 | ], 984 | "event": [] 985 | }, 986 | { 987 | "id": "cc1504d0-4299-4060-a2e4-3ae5f8598821", 988 | "name": "Finds Pets by tags", 989 | "request": { 990 | "name": "Finds Pets by tags", 991 | "description": { 992 | "content": "Multiple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing.", 993 | "type": "text/plain" 994 | }, 995 | "url": { 996 | "path": [ 997 | "pet", 998 | "findByTags" 999 | ], 1000 | "host": [ 1001 | "{{baseUrl}}" 1002 | ], 1003 | "query": [ 1004 | { 1005 | "disabled": false, 1006 | "description": { 1007 | "content": "Tags to filter by", 1008 | "type": "text/plain" 1009 | }, 1010 | "key": "tags", 1011 | "value": "cillum" 1012 | }, 1013 | { 1014 | "disabled": false, 1015 | "description": { 1016 | "content": "Tags to filter by", 1017 | "type": "text/plain" 1018 | }, 1019 | "key": "tags", 1020 | "value": "officia dolore nulla ea mollit" 1021 | } 1022 | ], 1023 | "variable": [] 1024 | }, 1025 | "method": "GET", 1026 | "auth": { 1027 | "type": "oauth2", 1028 | "oauth2": [] 1029 | } 1030 | }, 1031 | "response": [ 1032 | { 1033 | "_": { 1034 | "postman_previewlanguage": "json" 1035 | }, 1036 | "id": "fb1a5c9f-f78b-4d15-958f-711986130177", 1037 | "name": "successful operation", 1038 | "originalRequest": { 1039 | "url": { 1040 | "path": [ 1041 | "pet", 1042 | "findByTags" 1043 | ], 1044 | "host": [ 1045 | "{{baseUrl}}" 1046 | ], 1047 | "query": [ 1048 | { 1049 | "key": "tags", 1050 | "value": "mollit consectetur non proident occaecat" 1051 | }, 1052 | { 1053 | "key": "tags", 1054 | "value": "enim pariatur Excepteur ex consequat" 1055 | } 1056 | ], 1057 | "variable": [] 1058 | }, 1059 | "header": [ 1060 | { 1061 | "description": { 1062 | "content": "Added as a part of security scheme: oauth2", 1063 | "type": "text/plain" 1064 | }, 1065 | "key": "Authorization", 1066 | "value": "" 1067 | } 1068 | ], 1069 | "method": "GET", 1070 | "body": {} 1071 | }, 1072 | "status": "OK", 1073 | "code": 200, 1074 | "header": [ 1075 | { 1076 | "key": "Content-Type", 1077 | "value": "application/json" 1078 | } 1079 | ], 1080 | "body": "[\n {\n \"name\": \"doggie\",\n \"photoUrls\": [\n \"proident est\",\n \"dolore non dolor\"\n ],\n \"id\": 10,\n \"category\": {\n \"id\": 1,\n \"name\": \"Dogs\"\n },\n \"tags\": [\n {\n \"id\": -79071447,\n \"name\": \"exercitation nisi mollit ullamco\"\n },\n {\n \"id\": -92943178,\n \"name\": \"officia ut\"\n }\n ],\n \"status\": \"sold\"\n },\n {\n \"name\": \"doggie\",\n \"photoUrls\": [\n \"dolor est\",\n \"sint tempor\"\n ],\n \"id\": 10,\n \"category\": {\n \"id\": 1,\n \"name\": \"Dogs\"\n },\n \"tags\": [\n {\n \"id\": 59926836,\n \"name\": \"irure\"\n },\n {\n \"id\": -18047884,\n \"name\": \"aute laboris culpa exercitation ullamco\"\n }\n ],\n \"status\": \"available\"\n }\n]", 1081 | "cookie": [] 1082 | }, 1083 | { 1084 | "_": { 1085 | "postman_previewlanguage": "text" 1086 | }, 1087 | "id": "f962618a-b174-4f6f-8ab0-5161663bac35", 1088 | "name": "Invalid tag value", 1089 | "originalRequest": { 1090 | "url": { 1091 | "path": [ 1092 | "pet", 1093 | "findByTags" 1094 | ], 1095 | "host": [ 1096 | "{{baseUrl}}" 1097 | ], 1098 | "query": [ 1099 | { 1100 | "key": "tags", 1101 | "value": "mollit consectetur non proident occaecat" 1102 | }, 1103 | { 1104 | "key": "tags", 1105 | "value": "enim pariatur Excepteur ex consequat" 1106 | } 1107 | ], 1108 | "variable": [] 1109 | }, 1110 | "header": [ 1111 | { 1112 | "description": { 1113 | "content": "Added as a part of security scheme: oauth2", 1114 | "type": "text/plain" 1115 | }, 1116 | "key": "Authorization", 1117 | "value": "" 1118 | } 1119 | ], 1120 | "method": "GET", 1121 | "body": {} 1122 | }, 1123 | "status": "Bad Request", 1124 | "code": 400, 1125 | "header": [ 1126 | { 1127 | "key": "Content-Type", 1128 | "value": "text/plain" 1129 | } 1130 | ], 1131 | "body": "", 1132 | "cookie": [] 1133 | } 1134 | ], 1135 | "event": [] 1136 | }, 1137 | { 1138 | "id": "6f4fe7dd-3506-42f2-8990-abf0348f9712", 1139 | "name": "Find pet by ID", 1140 | "request": { 1141 | "name": "Find pet by ID", 1142 | "description": { 1143 | "content": "Returns a single pet", 1144 | "type": "text/plain" 1145 | }, 1146 | "url": { 1147 | "path": [ 1148 | "pet", 1149 | ":petId" 1150 | ], 1151 | "host": [ 1152 | "{{baseUrl}}" 1153 | ], 1154 | "query": [], 1155 | "variable": [ 1156 | { 1157 | "disabled": false, 1158 | "description": { 1159 | "content": "(Required) ID of pet to return", 1160 | "type": "text/plain" 1161 | }, 1162 | "type": "any", 1163 | "value": "-28559843", 1164 | "key": "petId" 1165 | } 1166 | ] 1167 | }, 1168 | "method": "GET", 1169 | "auth": { 1170 | "type": "apikey", 1171 | "apikey": [ 1172 | { 1173 | "type": "any", 1174 | "value": "api_key", 1175 | "key": "key" 1176 | }, 1177 | { 1178 | "type": "any", 1179 | "value": "", 1180 | "key": "value" 1181 | }, 1182 | { 1183 | "type": "any", 1184 | "value": "header", 1185 | "key": "in" 1186 | } 1187 | ] 1188 | } 1189 | }, 1190 | "response": [ 1191 | { 1192 | "_": { 1193 | "postman_previewlanguage": "json" 1194 | }, 1195 | "id": "3dfc5450-7b8e-4588-a55f-a8fbba201671", 1196 | "name": "successful operation", 1197 | "originalRequest": { 1198 | "url": { 1199 | "path": [ 1200 | "pet", 1201 | ":petId" 1202 | ], 1203 | "host": [ 1204 | "{{baseUrl}}" 1205 | ], 1206 | "query": [], 1207 | "variable": [ 1208 | { 1209 | "disabled": false, 1210 | "description": { 1211 | "content": "(Required) ID of pet to return", 1212 | "type": "text/plain" 1213 | }, 1214 | "type": "any", 1215 | "value": "-28559843", 1216 | "key": "petId" 1217 | } 1218 | ] 1219 | }, 1220 | "header": [ 1221 | { 1222 | "description": { 1223 | "content": "Added as a part of security scheme: apikey", 1224 | "type": "text/plain" 1225 | }, 1226 | "key": "api_key", 1227 | "value": "" 1228 | } 1229 | ], 1230 | "method": "GET", 1231 | "body": {} 1232 | }, 1233 | "status": "OK", 1234 | "code": 200, 1235 | "header": [ 1236 | { 1237 | "key": "Content-Type", 1238 | "value": "application/json" 1239 | } 1240 | ], 1241 | "body": "{\n \"name\": \"doggie\",\n \"photoUrls\": [\n \"ipsum\",\n \"aliqua\"\n ],\n \"id\": 10,\n \"category\": {\n \"id\": 1,\n \"name\": \"Dogs\"\n },\n \"tags\": [\n {\n \"id\": 24945634,\n \"name\": \"Excepteur in cupidatat eu\"\n },\n {\n \"id\": 99529413,\n \"name\": \"cillum sunt cupidatat\"\n }\n ],\n \"status\": \"sold\"\n}", 1242 | "cookie": [] 1243 | }, 1244 | { 1245 | "_": { 1246 | "postman_previewlanguage": "text" 1247 | }, 1248 | "id": "345c9c17-e5f1-4f45-978d-56d71a2944ba", 1249 | "name": "Invalid ID supplied", 1250 | "originalRequest": { 1251 | "url": { 1252 | "path": [ 1253 | "pet", 1254 | ":petId" 1255 | ], 1256 | "host": [ 1257 | "{{baseUrl}}" 1258 | ], 1259 | "query": [], 1260 | "variable": [ 1261 | { 1262 | "disabled": false, 1263 | "description": { 1264 | "content": "(Required) ID of pet to return", 1265 | "type": "text/plain" 1266 | }, 1267 | "type": "any", 1268 | "value": "-28559843", 1269 | "key": "petId" 1270 | } 1271 | ] 1272 | }, 1273 | "header": [ 1274 | { 1275 | "description": { 1276 | "content": "Added as a part of security scheme: apikey", 1277 | "type": "text/plain" 1278 | }, 1279 | "key": "api_key", 1280 | "value": "" 1281 | } 1282 | ], 1283 | "method": "GET", 1284 | "body": {} 1285 | }, 1286 | "status": "Bad Request", 1287 | "code": 400, 1288 | "header": [ 1289 | { 1290 | "key": "Content-Type", 1291 | "value": "text/plain" 1292 | } 1293 | ], 1294 | "body": "", 1295 | "cookie": [] 1296 | }, 1297 | { 1298 | "_": { 1299 | "postman_previewlanguage": "text" 1300 | }, 1301 | "id": "ceba0aad-71f4-4afd-bb6e-903429c6bc78", 1302 | "name": "Pet not found", 1303 | "originalRequest": { 1304 | "url": { 1305 | "path": [ 1306 | "pet", 1307 | ":petId" 1308 | ], 1309 | "host": [ 1310 | "{{baseUrl}}" 1311 | ], 1312 | "query": [], 1313 | "variable": [ 1314 | { 1315 | "disabled": false, 1316 | "description": { 1317 | "content": "(Required) ID of pet to return", 1318 | "type": "text/plain" 1319 | }, 1320 | "type": "any", 1321 | "value": "-28559843", 1322 | "key": "petId" 1323 | } 1324 | ] 1325 | }, 1326 | "header": [ 1327 | { 1328 | "description": { 1329 | "content": "Added as a part of security scheme: apikey", 1330 | "type": "text/plain" 1331 | }, 1332 | "key": "api_key", 1333 | "value": "" 1334 | } 1335 | ], 1336 | "method": "GET", 1337 | "body": {} 1338 | }, 1339 | "status": "Not Found", 1340 | "code": 404, 1341 | "header": [ 1342 | { 1343 | "key": "Content-Type", 1344 | "value": "text/plain" 1345 | } 1346 | ], 1347 | "body": "", 1348 | "cookie": [] 1349 | } 1350 | ], 1351 | "event": [] 1352 | }, 1353 | { 1354 | "id": "01ead98c-74be-4241-82e7-78e50e4b268a", 1355 | "name": "Updates a pet in the store with form data", 1356 | "request": { 1357 | "name": "Updates a pet in the store with form data", 1358 | "description": { 1359 | "content": "", 1360 | "type": "text/plain" 1361 | }, 1362 | "url": { 1363 | "path": [ 1364 | "pet", 1365 | ":petId" 1366 | ], 1367 | "host": [ 1368 | "{{baseUrl}}" 1369 | ], 1370 | "query": [ 1371 | { 1372 | "disabled": false, 1373 | "description": { 1374 | "content": "Name of pet that needs to be updated", 1375 | "type": "text/plain" 1376 | }, 1377 | "key": "name", 1378 | "value": "Excepteu" 1379 | }, 1380 | { 1381 | "disabled": false, 1382 | "description": { 1383 | "content": "Status of pet that needs to be updated", 1384 | "type": "text/plain" 1385 | }, 1386 | "key": "status", 1387 | "value": "Excepteu" 1388 | } 1389 | ], 1390 | "variable": [ 1391 | { 1392 | "disabled": false, 1393 | "description": { 1394 | "content": "(Required) ID of pet that needs to be updated", 1395 | "type": "text/plain" 1396 | }, 1397 | "type": "any", 1398 | "value": "-28559843", 1399 | "key": "petId" 1400 | } 1401 | ] 1402 | }, 1403 | "method": "POST", 1404 | "auth": { 1405 | "type": "oauth2", 1406 | "oauth2": [] 1407 | } 1408 | }, 1409 | "response": [ 1410 | { 1411 | "_": { 1412 | "postman_previewlanguage": "text" 1413 | }, 1414 | "id": "139a6bf6-8a61-44a0-aa28-0a6df565a3aa", 1415 | "name": "Invalid input", 1416 | "originalRequest": { 1417 | "url": { 1418 | "path": [ 1419 | "pet", 1420 | ":petId" 1421 | ], 1422 | "host": [ 1423 | "{{baseUrl}}" 1424 | ], 1425 | "query": [ 1426 | { 1427 | "key": "name", 1428 | "value": "Excepteu" 1429 | }, 1430 | { 1431 | "key": "status", 1432 | "value": "Excepteu" 1433 | } 1434 | ], 1435 | "variable": [ 1436 | { 1437 | "disabled": false, 1438 | "description": { 1439 | "content": "(Required) ID of pet that needs to be updated", 1440 | "type": "text/plain" 1441 | }, 1442 | "type": "any", 1443 | "value": "-28559843", 1444 | "key": "petId" 1445 | } 1446 | ] 1447 | }, 1448 | "header": [ 1449 | { 1450 | "description": { 1451 | "content": "Added as a part of security scheme: oauth2", 1452 | "type": "text/plain" 1453 | }, 1454 | "key": "Authorization", 1455 | "value": "" 1456 | } 1457 | ], 1458 | "method": "POST", 1459 | "body": {} 1460 | }, 1461 | "status": "Method Not Allowed", 1462 | "code": 405, 1463 | "header": [ 1464 | { 1465 | "key": "Content-Type", 1466 | "value": "text/plain" 1467 | } 1468 | ], 1469 | "body": "", 1470 | "cookie": [] 1471 | } 1472 | ], 1473 | "event": [] 1474 | }, 1475 | { 1476 | "id": "14a92b08-7a10-48ba-8d0f-94acd0664e6d", 1477 | "name": "Deletes a pet", 1478 | "request": { 1479 | "name": "Deletes a pet", 1480 | "description": { 1481 | "content": "", 1482 | "type": "text/plain" 1483 | }, 1484 | "url": { 1485 | "path": [ 1486 | "pet", 1487 | ":petId" 1488 | ], 1489 | "host": [ 1490 | "{{baseUrl}}" 1491 | ], 1492 | "query": [], 1493 | "variable": [ 1494 | { 1495 | "disabled": false, 1496 | "description": { 1497 | "content": "(Required) Pet id to delete", 1498 | "type": "text/plain" 1499 | }, 1500 | "type": "any", 1501 | "value": "-28559843", 1502 | "key": "petId" 1503 | } 1504 | ] 1505 | }, 1506 | "header": [ 1507 | { 1508 | "disabled": false, 1509 | "description": { 1510 | "content": "", 1511 | "type": "text/plain" 1512 | }, 1513 | "key": "api_key", 1514 | "value": "Excepteu" 1515 | } 1516 | ], 1517 | "method": "DELETE", 1518 | "auth": { 1519 | "type": "oauth2", 1520 | "oauth2": [] 1521 | } 1522 | }, 1523 | "response": [ 1524 | { 1525 | "_": { 1526 | "postman_previewlanguage": "text" 1527 | }, 1528 | "id": "d7daeaa2-a34b-44b2-a684-c4a4d57828c6", 1529 | "name": "Invalid pet value", 1530 | "originalRequest": { 1531 | "url": { 1532 | "path": [ 1533 | "pet", 1534 | ":petId" 1535 | ], 1536 | "host": [ 1537 | "{{baseUrl}}" 1538 | ], 1539 | "query": [], 1540 | "variable": [ 1541 | { 1542 | "disabled": false, 1543 | "description": { 1544 | "content": "(Required) Pet id to delete", 1545 | "type": "text/plain" 1546 | }, 1547 | "type": "any", 1548 | "value": "-28559843", 1549 | "key": "petId" 1550 | } 1551 | ] 1552 | }, 1553 | "header": [ 1554 | { 1555 | "description": { 1556 | "content": "Added as a part of security scheme: oauth2", 1557 | "type": "text/plain" 1558 | }, 1559 | "key": "Authorization", 1560 | "value": "" 1561 | }, 1562 | { 1563 | "disabled": false, 1564 | "description": { 1565 | "content": "", 1566 | "type": "text/plain" 1567 | }, 1568 | "key": "api_key", 1569 | "value": "Excepteu" 1570 | } 1571 | ], 1572 | "method": "DELETE", 1573 | "body": {} 1574 | }, 1575 | "status": "Bad Request", 1576 | "code": 400, 1577 | "header": [ 1578 | { 1579 | "key": "Content-Type", 1580 | "value": "text/plain" 1581 | } 1582 | ], 1583 | "body": "", 1584 | "cookie": [] 1585 | } 1586 | ], 1587 | "event": [] 1588 | }, 1589 | { 1590 | "id": "125a3dc5-2a04-43d0-899e-0c7d42411a44", 1591 | "name": "uploads an image", 1592 | "request": { 1593 | "name": "uploads an image", 1594 | "description": { 1595 | "content": "", 1596 | "type": "text/plain" 1597 | }, 1598 | "url": { 1599 | "path": [ 1600 | "pet", 1601 | ":petId", 1602 | "uploadImage" 1603 | ], 1604 | "host": [ 1605 | "{{baseUrl}}" 1606 | ], 1607 | "query": [ 1608 | { 1609 | "disabled": false, 1610 | "description": { 1611 | "content": "Additional Metadata", 1612 | "type": "text/plain" 1613 | }, 1614 | "key": "additionalMetadata", 1615 | "value": "Excepteu" 1616 | } 1617 | ], 1618 | "variable": [ 1619 | { 1620 | "disabled": false, 1621 | "description": { 1622 | "content": "(Required) ID of pet to update", 1623 | "type": "text/plain" 1624 | }, 1625 | "type": "any", 1626 | "value": "-28559843", 1627 | "key": "petId" 1628 | } 1629 | ] 1630 | }, 1631 | "header": [ 1632 | { 1633 | "key": "Content-Type", 1634 | "value": "application/octet-stream" 1635 | } 1636 | ], 1637 | "method": "POST", 1638 | "body": { 1639 | "mode": "file" 1640 | }, 1641 | "auth": { 1642 | "type": "oauth2", 1643 | "oauth2": [] 1644 | } 1645 | }, 1646 | "response": [ 1647 | { 1648 | "_": { 1649 | "postman_previewlanguage": "json" 1650 | }, 1651 | "id": "c30644af-1d6d-4008-8046-f03019737e07", 1652 | "name": "successful operation", 1653 | "originalRequest": { 1654 | "url": { 1655 | "path": [ 1656 | "pet", 1657 | ":petId", 1658 | "uploadImage" 1659 | ], 1660 | "host": [ 1661 | "{{baseUrl}}" 1662 | ], 1663 | "query": [ 1664 | { 1665 | "key": "additionalMetadata", 1666 | "value": "Excepteu" 1667 | } 1668 | ], 1669 | "variable": [ 1670 | { 1671 | "disabled": false, 1672 | "description": { 1673 | "content": "(Required) ID of pet to update", 1674 | "type": "text/plain" 1675 | }, 1676 | "type": "any", 1677 | "value": "-28559843", 1678 | "key": "petId" 1679 | } 1680 | ] 1681 | }, 1682 | "header": [ 1683 | { 1684 | "description": { 1685 | "content": "Added as a part of security scheme: oauth2", 1686 | "type": "text/plain" 1687 | }, 1688 | "key": "Authorization", 1689 | "value": "" 1690 | } 1691 | ], 1692 | "method": "POST", 1693 | "body": { 1694 | "mode": "file" 1695 | } 1696 | }, 1697 | "status": "OK", 1698 | "code": 200, 1699 | "header": [ 1700 | { 1701 | "key": "Content-Type", 1702 | "value": "application/json" 1703 | } 1704 | ], 1705 | "body": "{\n \"code\": -68885608,\n \"type\": \"quis pariatur\",\n \"message\": \"tempor commodo occaecat laborum\"\n}", 1706 | "cookie": [] 1707 | } 1708 | ], 1709 | "event": [] 1710 | } 1711 | ], 1712 | "event": [] 1713 | }, 1714 | { 1715 | "id": "ffef3c19-2e54-459b-84db-8f892e175a1a", 1716 | "name": "store", 1717 | "description": { 1718 | "content": "Operations about user", 1719 | "type": "text/plain" 1720 | }, 1721 | "item": [ 1722 | { 1723 | "id": "34be82e2-e4fe-4ac8-bfd1-e6fbbdfdaae2", 1724 | "name": "Returns pet inventories by status", 1725 | "request": { 1726 | "name": "Returns pet inventories by status", 1727 | "description": { 1728 | "content": "Returns a map of status codes to quantities", 1729 | "type": "text/plain" 1730 | }, 1731 | "url": { 1732 | "path": [ 1733 | "store", 1734 | "inventory" 1735 | ], 1736 | "host": [ 1737 | "{{baseUrl}}" 1738 | ], 1739 | "query": [], 1740 | "variable": [] 1741 | }, 1742 | "method": "GET", 1743 | "auth": { 1744 | "type": "apikey", 1745 | "apikey": [ 1746 | { 1747 | "type": "any", 1748 | "value": "api_key", 1749 | "key": "key" 1750 | }, 1751 | { 1752 | "type": "any", 1753 | "value": "", 1754 | "key": "value" 1755 | }, 1756 | { 1757 | "type": "any", 1758 | "value": "header", 1759 | "key": "in" 1760 | } 1761 | ] 1762 | } 1763 | }, 1764 | "response": [ 1765 | { 1766 | "_": { 1767 | "postman_previewlanguage": "json" 1768 | }, 1769 | "id": "449d2129-fead-4dbe-a453-91c7a472e870", 1770 | "name": "successful operation", 1771 | "originalRequest": { 1772 | "url": { 1773 | "path": [ 1774 | "store", 1775 | "inventory" 1776 | ], 1777 | "host": [ 1778 | "{{baseUrl}}" 1779 | ], 1780 | "query": [], 1781 | "variable": [] 1782 | }, 1783 | "header": [ 1784 | { 1785 | "description": { 1786 | "content": "Added as a part of security scheme: apikey", 1787 | "type": "text/plain" 1788 | }, 1789 | "key": "api_key", 1790 | "value": "" 1791 | } 1792 | ], 1793 | "method": "GET", 1794 | "body": {} 1795 | }, 1796 | "status": "OK", 1797 | "code": 200, 1798 | "header": [ 1799 | { 1800 | "key": "Content-Type", 1801 | "value": "application/json" 1802 | } 1803 | ], 1804 | "body": "{}", 1805 | "cookie": [] 1806 | } 1807 | ], 1808 | "event": [] 1809 | }, 1810 | { 1811 | "id": "c895f4a1-e9b4-4b3f-aa30-e390b8594ccd", 1812 | "name": "Place an order for a pet", 1813 | "request": { 1814 | "name": "Place an order for a pet", 1815 | "description": { 1816 | "content": "Place a new order in the store", 1817 | "type": "text/plain" 1818 | }, 1819 | "url": { 1820 | "path": [ 1821 | "store", 1822 | "order" 1823 | ], 1824 | "host": [ 1825 | "{{baseUrl}}" 1826 | ], 1827 | "query": [], 1828 | "variable": [] 1829 | }, 1830 | "header": [ 1831 | { 1832 | "key": "Content-Type", 1833 | "value": "application/x-www-form-urlencoded" 1834 | } 1835 | ], 1836 | "method": "POST", 1837 | "body": { 1838 | "mode": "urlencoded", 1839 | "urlencoded": [ 1840 | { 1841 | "disabled": false, 1842 | "key": "id", 1843 | "value": "10" 1844 | }, 1845 | { 1846 | "disabled": false, 1847 | "key": "petId", 1848 | "value": "198772" 1849 | }, 1850 | { 1851 | "disabled": false, 1852 | "key": "quantity", 1853 | "value": "7" 1854 | }, 1855 | { 1856 | "disabled": false, 1857 | "key": "shipDate", 1858 | "value": "1977-01-20T07:09:20.183Z" 1859 | }, 1860 | { 1861 | "disabled": false, 1862 | "description": { 1863 | "content": "Order Status", 1864 | "type": "text/plain" 1865 | }, 1866 | "key": "status", 1867 | "value": "approved" 1868 | }, 1869 | { 1870 | "disabled": false, 1871 | "key": "complete", 1872 | "value": "false" 1873 | } 1874 | ] 1875 | } 1876 | }, 1877 | "response": [ 1878 | { 1879 | "_": { 1880 | "postman_previewlanguage": "json" 1881 | }, 1882 | "id": "b6e39f4b-83bc-4e12-8d70-991680f4e2c3", 1883 | "name": "successful operation", 1884 | "originalRequest": { 1885 | "url": { 1886 | "path": [ 1887 | "store", 1888 | "order" 1889 | ], 1890 | "host": [ 1891 | "{{baseUrl}}" 1892 | ], 1893 | "query": [], 1894 | "variable": [] 1895 | }, 1896 | "method": "POST", 1897 | "body": { 1898 | "mode": "urlencoded", 1899 | "urlencoded": [ 1900 | { 1901 | "disabled": false, 1902 | "key": "id", 1903 | "value": "10" 1904 | }, 1905 | { 1906 | "disabled": false, 1907 | "key": "petId", 1908 | "value": "198772" 1909 | }, 1910 | { 1911 | "disabled": false, 1912 | "key": "quantity", 1913 | "value": "7" 1914 | }, 1915 | { 1916 | "disabled": false, 1917 | "key": "shipDate", 1918 | "value": "1977-01-20T07:09:20.183Z" 1919 | }, 1920 | { 1921 | "disabled": false, 1922 | "description": { 1923 | "content": "Order Status", 1924 | "type": "text/plain" 1925 | }, 1926 | "key": "status", 1927 | "value": "approved" 1928 | }, 1929 | { 1930 | "disabled": false, 1931 | "key": "complete", 1932 | "value": "false" 1933 | } 1934 | ] 1935 | } 1936 | }, 1937 | "status": "OK", 1938 | "code": 200, 1939 | "header": [ 1940 | { 1941 | "key": "Content-Type", 1942 | "value": "application/json" 1943 | } 1944 | ], 1945 | "body": "{\n \"id\": 10,\n \"petId\": 198772,\n \"quantity\": 7,\n \"shipDate\": \"1977-01-20T07:09:20.183Z\",\n \"status\": \"approved\",\n \"complete\": false\n}", 1946 | "cookie": [] 1947 | }, 1948 | { 1949 | "_": { 1950 | "postman_previewlanguage": "text" 1951 | }, 1952 | "id": "97918f06-b6cf-496f-be6c-e9aad441e679", 1953 | "name": "Invalid input", 1954 | "originalRequest": { 1955 | "url": { 1956 | "path": [ 1957 | "store", 1958 | "order" 1959 | ], 1960 | "host": [ 1961 | "{{baseUrl}}" 1962 | ], 1963 | "query": [], 1964 | "variable": [] 1965 | }, 1966 | "method": "POST", 1967 | "body": { 1968 | "mode": "urlencoded", 1969 | "urlencoded": [ 1970 | { 1971 | "disabled": false, 1972 | "key": "id", 1973 | "value": "10" 1974 | }, 1975 | { 1976 | "disabled": false, 1977 | "key": "petId", 1978 | "value": "198772" 1979 | }, 1980 | { 1981 | "disabled": false, 1982 | "key": "quantity", 1983 | "value": "7" 1984 | }, 1985 | { 1986 | "disabled": false, 1987 | "key": "shipDate", 1988 | "value": "1977-01-20T07:09:20.183Z" 1989 | }, 1990 | { 1991 | "disabled": false, 1992 | "description": { 1993 | "content": "Order Status", 1994 | "type": "text/plain" 1995 | }, 1996 | "key": "status", 1997 | "value": "approved" 1998 | }, 1999 | { 2000 | "disabled": false, 2001 | "key": "complete", 2002 | "value": "false" 2003 | } 2004 | ] 2005 | } 2006 | }, 2007 | "status": "Method Not Allowed", 2008 | "code": 405, 2009 | "header": [ 2010 | { 2011 | "key": "Content-Type", 2012 | "value": "text/plain" 2013 | } 2014 | ], 2015 | "body": "", 2016 | "cookie": [] 2017 | } 2018 | ], 2019 | "event": [] 2020 | }, 2021 | { 2022 | "id": "198658f1-5c65-46ba-b988-ae18bfea2e44", 2023 | "name": "Find purchase order by ID", 2024 | "request": { 2025 | "name": "Find purchase order by ID", 2026 | "description": { 2027 | "content": "For valid response try integer IDs with value <= 5 or > 10. Other values will generated exceptions", 2028 | "type": "text/plain" 2029 | }, 2030 | "url": { 2031 | "path": [ 2032 | "store", 2033 | "order", 2034 | ":orderId" 2035 | ], 2036 | "host": [ 2037 | "{{baseUrl}}" 2038 | ], 2039 | "query": [], 2040 | "variable": [ 2041 | { 2042 | "disabled": false, 2043 | "description": { 2044 | "content": "(Required) ID of order that needs to be fetched", 2045 | "type": "text/plain" 2046 | }, 2047 | "type": "any", 2048 | "value": "-28559843", 2049 | "key": "orderId" 2050 | } 2051 | ] 2052 | }, 2053 | "method": "GET" 2054 | }, 2055 | "response": [ 2056 | { 2057 | "_": { 2058 | "postman_previewlanguage": "json" 2059 | }, 2060 | "id": "e4502a95-1701-4add-87fa-02cc09be5552", 2061 | "name": "successful operation", 2062 | "originalRequest": { 2063 | "url": { 2064 | "path": [ 2065 | "store", 2066 | "order", 2067 | ":orderId" 2068 | ], 2069 | "host": [ 2070 | "{{baseUrl}}" 2071 | ], 2072 | "query": [], 2073 | "variable": [ 2074 | { 2075 | "disabled": false, 2076 | "description": { 2077 | "content": "(Required) ID of order that needs to be fetched", 2078 | "type": "text/plain" 2079 | }, 2080 | "type": "any", 2081 | "value": "-28559843", 2082 | "key": "orderId" 2083 | } 2084 | ] 2085 | }, 2086 | "method": "GET", 2087 | "body": {} 2088 | }, 2089 | "status": "OK", 2090 | "code": 200, 2091 | "header": [ 2092 | { 2093 | "key": "Content-Type", 2094 | "value": "application/json" 2095 | } 2096 | ], 2097 | "body": "{\n \"id\": 10,\n \"petId\": 198772,\n \"quantity\": 7,\n \"shipDate\": \"1977-01-20T07:09:20.183Z\",\n \"status\": \"approved\",\n \"complete\": false\n}", 2098 | "cookie": [] 2099 | }, 2100 | { 2101 | "_": { 2102 | "postman_previewlanguage": "text" 2103 | }, 2104 | "id": "daba8438-d15a-4a31-b0c9-06d5a89c281f", 2105 | "name": "Invalid ID supplied", 2106 | "originalRequest": { 2107 | "url": { 2108 | "path": [ 2109 | "store", 2110 | "order", 2111 | ":orderId" 2112 | ], 2113 | "host": [ 2114 | "{{baseUrl}}" 2115 | ], 2116 | "query": [], 2117 | "variable": [ 2118 | { 2119 | "disabled": false, 2120 | "description": { 2121 | "content": "(Required) ID of order that needs to be fetched", 2122 | "type": "text/plain" 2123 | }, 2124 | "type": "any", 2125 | "value": "-28559843", 2126 | "key": "orderId" 2127 | } 2128 | ] 2129 | }, 2130 | "method": "GET", 2131 | "body": {} 2132 | }, 2133 | "status": "Bad Request", 2134 | "code": 400, 2135 | "header": [ 2136 | { 2137 | "key": "Content-Type", 2138 | "value": "text/plain" 2139 | } 2140 | ], 2141 | "body": "", 2142 | "cookie": [] 2143 | }, 2144 | { 2145 | "_": { 2146 | "postman_previewlanguage": "text" 2147 | }, 2148 | "id": "e9e83df7-5551-489b-83fa-681fd3d42df5", 2149 | "name": "Order not found", 2150 | "originalRequest": { 2151 | "url": { 2152 | "path": [ 2153 | "store", 2154 | "order", 2155 | ":orderId" 2156 | ], 2157 | "host": [ 2158 | "{{baseUrl}}" 2159 | ], 2160 | "query": [], 2161 | "variable": [ 2162 | { 2163 | "disabled": false, 2164 | "description": { 2165 | "content": "(Required) ID of order that needs to be fetched", 2166 | "type": "text/plain" 2167 | }, 2168 | "type": "any", 2169 | "value": "-28559843", 2170 | "key": "orderId" 2171 | } 2172 | ] 2173 | }, 2174 | "method": "GET", 2175 | "body": {} 2176 | }, 2177 | "status": "Not Found", 2178 | "code": 404, 2179 | "header": [ 2180 | { 2181 | "key": "Content-Type", 2182 | "value": "text/plain" 2183 | } 2184 | ], 2185 | "body": "", 2186 | "cookie": [] 2187 | } 2188 | ], 2189 | "event": [] 2190 | }, 2191 | { 2192 | "id": "a2a92235-ff90-4d3d-8804-682ff3194fa3", 2193 | "name": "Delete purchase order by ID", 2194 | "request": { 2195 | "name": "Delete purchase order by ID", 2196 | "description": { 2197 | "content": "For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers will generate API errors", 2198 | "type": "text/plain" 2199 | }, 2200 | "url": { 2201 | "path": [ 2202 | "store", 2203 | "order", 2204 | ":orderId" 2205 | ], 2206 | "host": [ 2207 | "{{baseUrl}}" 2208 | ], 2209 | "query": [], 2210 | "variable": [ 2211 | { 2212 | "disabled": false, 2213 | "description": { 2214 | "content": "(Required) ID of the order that needs to be deleted", 2215 | "type": "text/plain" 2216 | }, 2217 | "type": "any", 2218 | "value": "-28559843", 2219 | "key": "orderId" 2220 | } 2221 | ] 2222 | }, 2223 | "method": "DELETE" 2224 | }, 2225 | "response": [ 2226 | { 2227 | "_": { 2228 | "postman_previewlanguage": "text" 2229 | }, 2230 | "id": "da7988b3-dc23-4798-986c-ae27c3f8faf9", 2231 | "name": "Invalid ID supplied", 2232 | "originalRequest": { 2233 | "url": { 2234 | "path": [ 2235 | "store", 2236 | "order", 2237 | ":orderId" 2238 | ], 2239 | "host": [ 2240 | "{{baseUrl}}" 2241 | ], 2242 | "query": [], 2243 | "variable": [ 2244 | { 2245 | "disabled": false, 2246 | "description": { 2247 | "content": "(Required) ID of the order that needs to be deleted", 2248 | "type": "text/plain" 2249 | }, 2250 | "type": "any", 2251 | "value": "-28559843", 2252 | "key": "orderId" 2253 | } 2254 | ] 2255 | }, 2256 | "method": "DELETE", 2257 | "body": {} 2258 | }, 2259 | "status": "Bad Request", 2260 | "code": 400, 2261 | "header": [ 2262 | { 2263 | "key": "Content-Type", 2264 | "value": "text/plain" 2265 | } 2266 | ], 2267 | "body": "", 2268 | "cookie": [] 2269 | }, 2270 | { 2271 | "_": { 2272 | "postman_previewlanguage": "text" 2273 | }, 2274 | "id": "e261c821-fc12-4bdc-bc01-01337dc1bb05", 2275 | "name": "Order not found", 2276 | "originalRequest": { 2277 | "url": { 2278 | "path": [ 2279 | "store", 2280 | "order", 2281 | ":orderId" 2282 | ], 2283 | "host": [ 2284 | "{{baseUrl}}" 2285 | ], 2286 | "query": [], 2287 | "variable": [ 2288 | { 2289 | "disabled": false, 2290 | "description": { 2291 | "content": "(Required) ID of the order that needs to be deleted", 2292 | "type": "text/plain" 2293 | }, 2294 | "type": "any", 2295 | "value": "-28559843", 2296 | "key": "orderId" 2297 | } 2298 | ] 2299 | }, 2300 | "method": "DELETE", 2301 | "body": {} 2302 | }, 2303 | "status": "Not Found", 2304 | "code": 404, 2305 | "header": [ 2306 | { 2307 | "key": "Content-Type", 2308 | "value": "text/plain" 2309 | } 2310 | ], 2311 | "body": "", 2312 | "cookie": [] 2313 | } 2314 | ], 2315 | "event": [] 2316 | } 2317 | ], 2318 | "event": [] 2319 | }, 2320 | { 2321 | "id": "e53a85af-a2d2-4774-9d4e-57baea608730", 2322 | "name": "user", 2323 | "description": { 2324 | "content": "Access to Petstore orders", 2325 | "type": "text/plain" 2326 | }, 2327 | "item": [ 2328 | { 2329 | "id": "7331ec1e-b950-4896-96bd-82e4e83b7316", 2330 | "name": "Create user", 2331 | "request": { 2332 | "name": "Create user", 2333 | "description": { 2334 | "content": "This can only be done by the logged in user.", 2335 | "type": "text/plain" 2336 | }, 2337 | "url": { 2338 | "path": [ 2339 | "user" 2340 | ], 2341 | "host": [ 2342 | "{{baseUrl}}" 2343 | ], 2344 | "query": [], 2345 | "variable": [] 2346 | }, 2347 | "header": [ 2348 | { 2349 | "key": "Content-Type", 2350 | "value": "application/x-www-form-urlencoded" 2351 | } 2352 | ], 2353 | "method": "POST", 2354 | "body": { 2355 | "mode": "urlencoded", 2356 | "urlencoded": [ 2357 | { 2358 | "disabled": false, 2359 | "key": "id", 2360 | "value": "10" 2361 | }, 2362 | { 2363 | "disabled": false, 2364 | "key": "username", 2365 | "value": "theUser" 2366 | }, 2367 | { 2368 | "disabled": false, 2369 | "key": "firstName", 2370 | "value": "John" 2371 | }, 2372 | { 2373 | "disabled": false, 2374 | "key": "lastName", 2375 | "value": "James" 2376 | }, 2377 | { 2378 | "disabled": false, 2379 | "key": "email", 2380 | "value": "john@email.com" 2381 | }, 2382 | { 2383 | "disabled": false, 2384 | "key": "password", 2385 | "value": "12345" 2386 | }, 2387 | { 2388 | "disabled": false, 2389 | "key": "phone", 2390 | "value": "12345" 2391 | }, 2392 | { 2393 | "disabled": false, 2394 | "description": { 2395 | "content": "User Status", 2396 | "type": "text/plain" 2397 | }, 2398 | "key": "userStatus", 2399 | "value": "1" 2400 | } 2401 | ] 2402 | } 2403 | }, 2404 | "response": [ 2405 | { 2406 | "_": { 2407 | "postman_previewlanguage": "json" 2408 | }, 2409 | "id": "af8b38e1-ea3b-4248-bfd0-0091c8f26868", 2410 | "name": "successful operation", 2411 | "originalRequest": { 2412 | "url": { 2413 | "path": [ 2414 | "user" 2415 | ], 2416 | "host": [ 2417 | "{{baseUrl}}" 2418 | ], 2419 | "query": [], 2420 | "variable": [] 2421 | }, 2422 | "method": "POST", 2423 | "body": { 2424 | "mode": "urlencoded", 2425 | "urlencoded": [ 2426 | { 2427 | "disabled": false, 2428 | "key": "id", 2429 | "value": "10" 2430 | }, 2431 | { 2432 | "disabled": false, 2433 | "key": "username", 2434 | "value": "theUser" 2435 | }, 2436 | { 2437 | "disabled": false, 2438 | "key": "firstName", 2439 | "value": "John" 2440 | }, 2441 | { 2442 | "disabled": false, 2443 | "key": "lastName", 2444 | "value": "James" 2445 | }, 2446 | { 2447 | "disabled": false, 2448 | "key": "email", 2449 | "value": "john@email.com" 2450 | }, 2451 | { 2452 | "disabled": false, 2453 | "key": "password", 2454 | "value": "12345" 2455 | }, 2456 | { 2457 | "disabled": false, 2458 | "key": "phone", 2459 | "value": "12345" 2460 | }, 2461 | { 2462 | "disabled": false, 2463 | "description": { 2464 | "content": "User Status", 2465 | "type": "text/plain" 2466 | }, 2467 | "key": "userStatus", 2468 | "value": "1" 2469 | } 2470 | ] 2471 | } 2472 | }, 2473 | "status": "Internal Server Error", 2474 | "code": 500, 2475 | "header": [ 2476 | { 2477 | "key": "Content-Type", 2478 | "value": "application/json" 2479 | } 2480 | ], 2481 | "body": "{\n \"id\": 10,\n \"username\": \"theUser\",\n \"firstName\": \"John\",\n \"lastName\": \"James\",\n \"email\": \"john@email.com\",\n \"password\": \"12345\",\n \"phone\": \"12345\",\n \"userStatus\": 1\n}", 2482 | "cookie": [] 2483 | } 2484 | ], 2485 | "event": [] 2486 | }, 2487 | { 2488 | "id": "e4bf139c-073a-4af1-81cd-0ff7e3a85995", 2489 | "name": "Creates list of users with given input array", 2490 | "request": { 2491 | "name": "Creates list of users with given input array", 2492 | "description": { 2493 | "content": "Creates list of users with given input array", 2494 | "type": "text/plain" 2495 | }, 2496 | "url": { 2497 | "path": [ 2498 | "user", 2499 | "createWithList" 2500 | ], 2501 | "host": [ 2502 | "{{baseUrl}}" 2503 | ], 2504 | "query": [], 2505 | "variable": [] 2506 | }, 2507 | "header": [ 2508 | { 2509 | "key": "Content-Type", 2510 | "value": "application/json" 2511 | } 2512 | ], 2513 | "method": "POST", 2514 | "body": { 2515 | "mode": "raw", 2516 | "raw": "[\n {\n \"id\": 10,\n \"username\": \"theUser\",\n \"firstName\": \"John\",\n \"lastName\": \"James\",\n \"email\": \"john@email.com\",\n \"password\": \"12345\",\n \"phone\": \"12345\",\n \"userStatus\": 1\n },\n {\n \"id\": 10,\n \"username\": \"theUser\",\n \"firstName\": \"John\",\n \"lastName\": \"James\",\n \"email\": \"john@email.com\",\n \"password\": \"12345\",\n \"phone\": \"12345\",\n \"userStatus\": 1\n }\n]", 2517 | "options": { 2518 | "raw": { 2519 | "language": "json" 2520 | } 2521 | } 2522 | } 2523 | }, 2524 | "response": [ 2525 | { 2526 | "_": { 2527 | "postman_previewlanguage": "json" 2528 | }, 2529 | "id": "c78e2d7f-91ab-4df4-9031-3c291d4f0856", 2530 | "name": "Successful operation", 2531 | "originalRequest": { 2532 | "url": { 2533 | "path": [ 2534 | "user", 2535 | "createWithList" 2536 | ], 2537 | "host": [ 2538 | "{{baseUrl}}" 2539 | ], 2540 | "query": [], 2541 | "variable": [] 2542 | }, 2543 | "method": "POST", 2544 | "body": { 2545 | "mode": "raw", 2546 | "raw": "[\n {\n \"id\": 10,\n \"username\": \"theUser\",\n \"firstName\": \"John\",\n \"lastName\": \"James\",\n \"email\": \"john@email.com\",\n \"password\": \"12345\",\n \"phone\": \"12345\",\n \"userStatus\": 1\n },\n {\n \"id\": 10,\n \"username\": \"theUser\",\n \"firstName\": \"John\",\n \"lastName\": \"James\",\n \"email\": \"john@email.com\",\n \"password\": \"12345\",\n \"phone\": \"12345\",\n \"userStatus\": 1\n }\n]", 2547 | "options": { 2548 | "raw": { 2549 | "language": "json" 2550 | } 2551 | } 2552 | } 2553 | }, 2554 | "status": "OK", 2555 | "code": 200, 2556 | "header": [ 2557 | { 2558 | "key": "Content-Type", 2559 | "value": "application/json" 2560 | } 2561 | ], 2562 | "body": "{\n \"id\": 10,\n \"username\": \"theUser\",\n \"firstName\": \"John\",\n \"lastName\": \"James\",\n \"email\": \"john@email.com\",\n \"password\": \"12345\",\n \"phone\": \"12345\",\n \"userStatus\": 1\n}", 2563 | "cookie": [] 2564 | }, 2565 | { 2566 | "_": { 2567 | "postman_previewlanguage": "text" 2568 | }, 2569 | "id": "d5dbe242-ac58-470d-a894-c6b3a33542d5", 2570 | "name": "successful operation", 2571 | "originalRequest": { 2572 | "url": { 2573 | "path": [ 2574 | "user", 2575 | "createWithList" 2576 | ], 2577 | "host": [ 2578 | "{{baseUrl}}" 2579 | ], 2580 | "query": [], 2581 | "variable": [] 2582 | }, 2583 | "method": "POST", 2584 | "body": { 2585 | "mode": "raw", 2586 | "raw": "[\n {\n \"id\": 10,\n \"username\": \"theUser\",\n \"firstName\": \"John\",\n \"lastName\": \"James\",\n \"email\": \"john@email.com\",\n \"password\": \"12345\",\n \"phone\": \"12345\",\n \"userStatus\": 1\n },\n {\n \"id\": 10,\n \"username\": \"theUser\",\n \"firstName\": \"John\",\n \"lastName\": \"James\",\n \"email\": \"john@email.com\",\n \"password\": \"12345\",\n \"phone\": \"12345\",\n \"userStatus\": 1\n }\n]", 2587 | "options": { 2588 | "raw": { 2589 | "language": "json" 2590 | } 2591 | } 2592 | } 2593 | }, 2594 | "status": "Internal Server Error", 2595 | "code": 500, 2596 | "header": [ 2597 | { 2598 | "key": "Content-Type", 2599 | "value": "text/plain" 2600 | } 2601 | ], 2602 | "body": "", 2603 | "cookie": [] 2604 | } 2605 | ], 2606 | "event": [] 2607 | }, 2608 | { 2609 | "id": "b2014513-8bf4-4e34-bd12-0e8ab96151e2", 2610 | "name": "Logs user into the system", 2611 | "request": { 2612 | "name": "Logs user into the system", 2613 | "description": { 2614 | "content": "", 2615 | "type": "text/plain" 2616 | }, 2617 | "url": { 2618 | "path": [ 2619 | "user", 2620 | "login" 2621 | ], 2622 | "host": [ 2623 | "{{baseUrl}}" 2624 | ], 2625 | "query": [ 2626 | { 2627 | "disabled": false, 2628 | "description": { 2629 | "content": "The user name for login", 2630 | "type": "text/plain" 2631 | }, 2632 | "key": "username", 2633 | "value": "Excepteu" 2634 | }, 2635 | { 2636 | "disabled": false, 2637 | "description": { 2638 | "content": "The password for login in clear text", 2639 | "type": "text/plain" 2640 | }, 2641 | "key": "password", 2642 | "value": "Excepteu" 2643 | } 2644 | ], 2645 | "variable": [] 2646 | }, 2647 | "method": "GET" 2648 | }, 2649 | "response": [ 2650 | { 2651 | "_": { 2652 | "postman_previewlanguage": "json" 2653 | }, 2654 | "id": "9b2976d7-d04f-44ef-bb6b-9687c7821a62", 2655 | "name": "successful operation", 2656 | "originalRequest": { 2657 | "url": { 2658 | "path": [ 2659 | "user", 2660 | "login" 2661 | ], 2662 | "host": [ 2663 | "{{baseUrl}}" 2664 | ], 2665 | "query": [ 2666 | { 2667 | "key": "username", 2668 | "value": "Excepteu" 2669 | }, 2670 | { 2671 | "key": "password", 2672 | "value": "Excepteu" 2673 | } 2674 | ], 2675 | "variable": [] 2676 | }, 2677 | "method": "GET", 2678 | "body": {} 2679 | }, 2680 | "status": "OK", 2681 | "code": 200, 2682 | "header": [ 2683 | { 2684 | "disabled": false, 2685 | "description": { 2686 | "content": "calls per hour allowed by the user", 2687 | "type": "text/plain" 2688 | }, 2689 | "key": "X-Rate-Limit", 2690 | "value": "-28559843" 2691 | }, 2692 | { 2693 | "disabled": false, 2694 | "description": { 2695 | "content": "date in UTC when token expires", 2696 | "type": "text/plain" 2697 | }, 2698 | "key": "X-Expires-After", 2699 | "value": "1953-05-11T15:30:08.405Z" 2700 | }, 2701 | { 2702 | "key": "Content-Type", 2703 | "value": "application/json" 2704 | } 2705 | ], 2706 | "body": "\"Excepteu\"", 2707 | "cookie": [] 2708 | }, 2709 | { 2710 | "_": { 2711 | "postman_previewlanguage": "text" 2712 | }, 2713 | "id": "76755758-edfd-425a-ae01-994c552c381d", 2714 | "name": "Invalid username/password supplied", 2715 | "originalRequest": { 2716 | "url": { 2717 | "path": [ 2718 | "user", 2719 | "login" 2720 | ], 2721 | "host": [ 2722 | "{{baseUrl}}" 2723 | ], 2724 | "query": [ 2725 | { 2726 | "key": "username", 2727 | "value": "Excepteu" 2728 | }, 2729 | { 2730 | "key": "password", 2731 | "value": "Excepteu" 2732 | } 2733 | ], 2734 | "variable": [] 2735 | }, 2736 | "method": "GET", 2737 | "body": {} 2738 | }, 2739 | "status": "Bad Request", 2740 | "code": 400, 2741 | "header": [ 2742 | { 2743 | "key": "Content-Type", 2744 | "value": "text/plain" 2745 | } 2746 | ], 2747 | "body": "", 2748 | "cookie": [] 2749 | } 2750 | ], 2751 | "event": [] 2752 | }, 2753 | { 2754 | "id": "ca8f73ba-71bf-4f88-8be9-67062f8e7049", 2755 | "name": "Logs out current logged in user session", 2756 | "request": { 2757 | "name": "Logs out current logged in user session", 2758 | "description": { 2759 | "content": "", 2760 | "type": "text/plain" 2761 | }, 2762 | "url": { 2763 | "path": [ 2764 | "user", 2765 | "logout" 2766 | ], 2767 | "host": [ 2768 | "{{baseUrl}}" 2769 | ], 2770 | "query": [], 2771 | "variable": [] 2772 | }, 2773 | "method": "GET" 2774 | }, 2775 | "response": [ 2776 | { 2777 | "_": { 2778 | "postman_previewlanguage": "text" 2779 | }, 2780 | "id": "d05b4a93-69c8-4432-b196-620144622f88", 2781 | "name": "successful operation", 2782 | "originalRequest": { 2783 | "url": { 2784 | "path": [ 2785 | "user", 2786 | "logout" 2787 | ], 2788 | "host": [ 2789 | "{{baseUrl}}" 2790 | ], 2791 | "query": [], 2792 | "variable": [] 2793 | }, 2794 | "method": "GET", 2795 | "body": {} 2796 | }, 2797 | "status": "Internal Server Error", 2798 | "code": 500, 2799 | "header": [ 2800 | { 2801 | "key": "Content-Type", 2802 | "value": "text/plain" 2803 | } 2804 | ], 2805 | "body": "", 2806 | "cookie": [] 2807 | } 2808 | ], 2809 | "event": [] 2810 | }, 2811 | { 2812 | "id": "d6b90e72-379c-4c8e-8978-d285ef379df5", 2813 | "name": "Get user by user name", 2814 | "request": { 2815 | "name": "Get user by user name", 2816 | "description": { 2817 | "content": "", 2818 | "type": "text/plain" 2819 | }, 2820 | "url": { 2821 | "path": [ 2822 | "user", 2823 | ":username" 2824 | ], 2825 | "host": [ 2826 | "{{baseUrl}}" 2827 | ], 2828 | "query": [], 2829 | "variable": [ 2830 | { 2831 | "disabled": false, 2832 | "description": { 2833 | "content": "(Required) The name that needs to be fetched. Use user1 for testing. ", 2834 | "type": "text/plain" 2835 | }, 2836 | "type": "any", 2837 | "value": "Excepteu", 2838 | "key": "username" 2839 | } 2840 | ] 2841 | }, 2842 | "method": "GET" 2843 | }, 2844 | "response": [ 2845 | { 2846 | "_": { 2847 | "postman_previewlanguage": "json" 2848 | }, 2849 | "id": "90b28a0e-b3ad-4f78-8b34-94583e0271d1", 2850 | "name": "successful operation", 2851 | "originalRequest": { 2852 | "url": { 2853 | "path": [ 2854 | "user", 2855 | ":username" 2856 | ], 2857 | "host": [ 2858 | "{{baseUrl}}" 2859 | ], 2860 | "query": [], 2861 | "variable": [ 2862 | { 2863 | "disabled": false, 2864 | "description": { 2865 | "content": "(Required) The name that needs to be fetched. Use user1 for testing. ", 2866 | "type": "text/plain" 2867 | }, 2868 | "type": "any", 2869 | "value": "Excepteu", 2870 | "key": "username" 2871 | } 2872 | ] 2873 | }, 2874 | "method": "GET", 2875 | "body": {} 2876 | }, 2877 | "status": "OK", 2878 | "code": 200, 2879 | "header": [ 2880 | { 2881 | "key": "Content-Type", 2882 | "value": "application/json" 2883 | } 2884 | ], 2885 | "body": "{\n \"id\": 10,\n \"username\": \"theUser\",\n \"firstName\": \"John\",\n \"lastName\": \"James\",\n \"email\": \"john@email.com\",\n \"password\": \"12345\",\n \"phone\": \"12345\",\n \"userStatus\": 1\n}", 2886 | "cookie": [] 2887 | }, 2888 | { 2889 | "_": { 2890 | "postman_previewlanguage": "text" 2891 | }, 2892 | "id": "7deccc3a-7387-440d-a3cf-805d979c3ed1", 2893 | "name": "Invalid username supplied", 2894 | "originalRequest": { 2895 | "url": { 2896 | "path": [ 2897 | "user", 2898 | ":username" 2899 | ], 2900 | "host": [ 2901 | "{{baseUrl}}" 2902 | ], 2903 | "query": [], 2904 | "variable": [ 2905 | { 2906 | "disabled": false, 2907 | "description": { 2908 | "content": "(Required) The name that needs to be fetched. Use user1 for testing. ", 2909 | "type": "text/plain" 2910 | }, 2911 | "type": "any", 2912 | "value": "Excepteu", 2913 | "key": "username" 2914 | } 2915 | ] 2916 | }, 2917 | "method": "GET", 2918 | "body": {} 2919 | }, 2920 | "status": "Bad Request", 2921 | "code": 400, 2922 | "header": [ 2923 | { 2924 | "key": "Content-Type", 2925 | "value": "text/plain" 2926 | } 2927 | ], 2928 | "body": "", 2929 | "cookie": [] 2930 | }, 2931 | { 2932 | "_": { 2933 | "postman_previewlanguage": "text" 2934 | }, 2935 | "id": "391d676e-861e-44ed-acb6-8a9246304632", 2936 | "name": "User not found", 2937 | "originalRequest": { 2938 | "url": { 2939 | "path": [ 2940 | "user", 2941 | ":username" 2942 | ], 2943 | "host": [ 2944 | "{{baseUrl}}" 2945 | ], 2946 | "query": [], 2947 | "variable": [ 2948 | { 2949 | "disabled": false, 2950 | "description": { 2951 | "content": "(Required) The name that needs to be fetched. Use user1 for testing. ", 2952 | "type": "text/plain" 2953 | }, 2954 | "type": "any", 2955 | "value": "Excepteu", 2956 | "key": "username" 2957 | } 2958 | ] 2959 | }, 2960 | "method": "GET", 2961 | "body": {} 2962 | }, 2963 | "status": "Not Found", 2964 | "code": 404, 2965 | "header": [ 2966 | { 2967 | "key": "Content-Type", 2968 | "value": "text/plain" 2969 | } 2970 | ], 2971 | "body": "", 2972 | "cookie": [] 2973 | } 2974 | ], 2975 | "event": [] 2976 | }, 2977 | { 2978 | "id": "65d0c991-e60c-4efd-b4fe-aa1fd39ea7e1", 2979 | "name": "Update user", 2980 | "request": { 2981 | "name": "Update user", 2982 | "description": { 2983 | "content": "This can only be done by the logged in user.", 2984 | "type": "text/plain" 2985 | }, 2986 | "url": { 2987 | "path": [ 2988 | "user", 2989 | ":username" 2990 | ], 2991 | "host": [ 2992 | "{{baseUrl}}" 2993 | ], 2994 | "query": [], 2995 | "variable": [ 2996 | { 2997 | "disabled": false, 2998 | "description": { 2999 | "content": "(Required) name that need to be deleted", 3000 | "type": "text/plain" 3001 | }, 3002 | "type": "any", 3003 | "value": "Excepteu", 3004 | "key": "username" 3005 | } 3006 | ] 3007 | }, 3008 | "header": [ 3009 | { 3010 | "key": "Content-Type", 3011 | "value": "application/x-www-form-urlencoded" 3012 | } 3013 | ], 3014 | "method": "PUT", 3015 | "body": { 3016 | "mode": "urlencoded", 3017 | "urlencoded": [ 3018 | { 3019 | "disabled": false, 3020 | "key": "id", 3021 | "value": "10" 3022 | }, 3023 | { 3024 | "disabled": false, 3025 | "key": "username", 3026 | "value": "theUser" 3027 | }, 3028 | { 3029 | "disabled": false, 3030 | "key": "firstName", 3031 | "value": "John" 3032 | }, 3033 | { 3034 | "disabled": false, 3035 | "key": "lastName", 3036 | "value": "James" 3037 | }, 3038 | { 3039 | "disabled": false, 3040 | "key": "email", 3041 | "value": "john@email.com" 3042 | }, 3043 | { 3044 | "disabled": false, 3045 | "key": "password", 3046 | "value": "12345" 3047 | }, 3048 | { 3049 | "disabled": false, 3050 | "key": "phone", 3051 | "value": "12345" 3052 | }, 3053 | { 3054 | "disabled": false, 3055 | "description": { 3056 | "content": "User Status", 3057 | "type": "text/plain" 3058 | }, 3059 | "key": "userStatus", 3060 | "value": "1" 3061 | } 3062 | ] 3063 | } 3064 | }, 3065 | "response": [ 3066 | { 3067 | "_": { 3068 | "postman_previewlanguage": "text" 3069 | }, 3070 | "id": "675c6ccd-e696-42d8-992e-ed4084b19856", 3071 | "name": "successful operation", 3072 | "originalRequest": { 3073 | "url": { 3074 | "path": [ 3075 | "user", 3076 | ":username" 3077 | ], 3078 | "host": [ 3079 | "{{baseUrl}}" 3080 | ], 3081 | "query": [], 3082 | "variable": [ 3083 | { 3084 | "disabled": false, 3085 | "description": { 3086 | "content": "(Required) name that need to be deleted", 3087 | "type": "text/plain" 3088 | }, 3089 | "type": "any", 3090 | "value": "Excepteu", 3091 | "key": "username" 3092 | } 3093 | ] 3094 | }, 3095 | "method": "PUT", 3096 | "body": { 3097 | "mode": "urlencoded", 3098 | "urlencoded": [ 3099 | { 3100 | "disabled": false, 3101 | "key": "id", 3102 | "value": "10" 3103 | }, 3104 | { 3105 | "disabled": false, 3106 | "key": "username", 3107 | "value": "theUser" 3108 | }, 3109 | { 3110 | "disabled": false, 3111 | "key": "firstName", 3112 | "value": "John" 3113 | }, 3114 | { 3115 | "disabled": false, 3116 | "key": "lastName", 3117 | "value": "James" 3118 | }, 3119 | { 3120 | "disabled": false, 3121 | "key": "email", 3122 | "value": "john@email.com" 3123 | }, 3124 | { 3125 | "disabled": false, 3126 | "key": "password", 3127 | "value": "12345" 3128 | }, 3129 | { 3130 | "disabled": false, 3131 | "key": "phone", 3132 | "value": "12345" 3133 | }, 3134 | { 3135 | "disabled": false, 3136 | "description": { 3137 | "content": "User Status", 3138 | "type": "text/plain" 3139 | }, 3140 | "key": "userStatus", 3141 | "value": "1" 3142 | } 3143 | ] 3144 | } 3145 | }, 3146 | "status": "Internal Server Error", 3147 | "code": 500, 3148 | "header": [ 3149 | { 3150 | "key": "Content-Type", 3151 | "value": "text/plain" 3152 | } 3153 | ], 3154 | "body": "", 3155 | "cookie": [] 3156 | } 3157 | ], 3158 | "event": [] 3159 | }, 3160 | { 3161 | "id": "307d7af1-6135-4bab-98e3-44f36aeb9da4", 3162 | "name": "Delete user", 3163 | "request": { 3164 | "name": "Delete user", 3165 | "description": { 3166 | "content": "This can only be done by the logged in user.", 3167 | "type": "text/plain" 3168 | }, 3169 | "url": { 3170 | "path": [ 3171 | "user", 3172 | ":username" 3173 | ], 3174 | "host": [ 3175 | "{{baseUrl}}" 3176 | ], 3177 | "query": [], 3178 | "variable": [ 3179 | { 3180 | "disabled": false, 3181 | "description": { 3182 | "content": "(Required) The name that needs to be deleted", 3183 | "type": "text/plain" 3184 | }, 3185 | "type": "any", 3186 | "value": "Excepteu", 3187 | "key": "username" 3188 | } 3189 | ] 3190 | }, 3191 | "method": "DELETE" 3192 | }, 3193 | "response": [ 3194 | { 3195 | "_": { 3196 | "postman_previewlanguage": "text" 3197 | }, 3198 | "id": "67c6e03f-2dd2-43d1-93c6-d0207d0a262d", 3199 | "name": "Invalid username supplied", 3200 | "originalRequest": { 3201 | "url": { 3202 | "path": [ 3203 | "user", 3204 | ":username" 3205 | ], 3206 | "host": [ 3207 | "{{baseUrl}}" 3208 | ], 3209 | "query": [], 3210 | "variable": [ 3211 | { 3212 | "disabled": false, 3213 | "description": { 3214 | "content": "(Required) The name that needs to be deleted", 3215 | "type": "text/plain" 3216 | }, 3217 | "type": "any", 3218 | "value": "Excepteu", 3219 | "key": "username" 3220 | } 3221 | ] 3222 | }, 3223 | "method": "DELETE", 3224 | "body": {} 3225 | }, 3226 | "status": "Bad Request", 3227 | "code": 400, 3228 | "header": [ 3229 | { 3230 | "key": "Content-Type", 3231 | "value": "text/plain" 3232 | } 3233 | ], 3234 | "body": "", 3235 | "cookie": [] 3236 | }, 3237 | { 3238 | "_": { 3239 | "postman_previewlanguage": "text" 3240 | }, 3241 | "id": "d39e2ce9-6f1f-43bf-9601-2b9cc23f06cb", 3242 | "name": "User not found", 3243 | "originalRequest": { 3244 | "url": { 3245 | "path": [ 3246 | "user", 3247 | ":username" 3248 | ], 3249 | "host": [ 3250 | "{{baseUrl}}" 3251 | ], 3252 | "query": [], 3253 | "variable": [ 3254 | { 3255 | "disabled": false, 3256 | "description": { 3257 | "content": "(Required) The name that needs to be deleted", 3258 | "type": "text/plain" 3259 | }, 3260 | "type": "any", 3261 | "value": "Excepteu", 3262 | "key": "username" 3263 | } 3264 | ] 3265 | }, 3266 | "method": "DELETE", 3267 | "body": {} 3268 | }, 3269 | "status": "Not Found", 3270 | "code": 404, 3271 | "header": [ 3272 | { 3273 | "key": "Content-Type", 3274 | "value": "text/plain" 3275 | } 3276 | ], 3277 | "body": "", 3278 | "cookie": [] 3279 | } 3280 | ], 3281 | "event": [] 3282 | } 3283 | ], 3284 | "event": [] 3285 | } 3286 | ], 3287 | "event": [], 3288 | "variable": [ 3289 | { 3290 | "type": "string", 3291 | "value": "/api/v3", 3292 | "key": "baseUrl" 3293 | } 3294 | ], 3295 | "info": { 3296 | "_postman_id": "eaeacca3-dcfa-4c76-b50f-3b2e783dff9d", 3297 | "name": "Swagger Petstore - OpenAPI 3.0", 3298 | "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json", 3299 | "description": { 3300 | "content": "This is a sample Pet Store Server based on the OpenAPI 3.0 specification. You can find out more about\nSwagger at [http://swagger.io](http://swagger.io). In the third iteration of the pet store, we've switched to the design first approach!\nYou can now help us improve the API whether it's by making changes to the definition itself or to the code.\nThat way, with time, we can improve the API in general, and expose some of the new features in OAS3.\n\nSome useful links:\n- [The Pet Store repository](https://github.com/swagger-api/swagger-petstore)\n- [The source API definition for the Pet Store](https://github.com/swagger-api/swagger-petstore/blob/master/src/main/resources/openapi.yaml)\n\nContact Support:\n Email: apiteam@swagger.io", 3301 | "type": "text/plain" 3302 | } 3303 | } 3304 | } -------------------------------------------------------------------------------- /integration/petstore-openapi.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | openapi: 3.0.2 3 | info: 4 | title: Swagger Petstore - OpenAPI 3.0 5 | description: |- 6 | This is a sample Pet Store Server based on the OpenAPI 3.0 specification. You can find out more about 7 | Swagger at [http://swagger.io](http://swagger.io). In the third iteration of the pet store, we've switched to the design first approach! 8 | You can now help us improve the API whether it's by making changes to the definition itself or to the code. 9 | That way, with time, we can improve the API in general, and expose some of the new features in OAS3. 10 | 11 | Some useful links: 12 | - [The Pet Store repository](https://github.com/swagger-api/swagger-petstore) 13 | - [The source API definition for the Pet Store](https://github.com/swagger-api/swagger-petstore/blob/master/src/main/resources/openapi.yaml) 14 | termsOfService: http://swagger.io/terms/ 15 | contact: 16 | email: apiteam@swagger.io 17 | license: 18 | name: Apache 2.0 19 | url: http://www.apache.org/licenses/LICENSE-2.0.html 20 | version: 1.0.9 21 | externalDocs: 22 | description: Find out more about Swagger 23 | url: http://swagger.io 24 | servers: 25 | - url: "/api/v3" 26 | tags: 27 | - name: pet 28 | description: Everything about your Pets 29 | externalDocs: 30 | description: Find out more 31 | url: http://swagger.io 32 | - name: store 33 | description: Operations about user 34 | - name: user 35 | description: Access to Petstore orders 36 | externalDocs: 37 | description: Find out more about our store 38 | url: http://swagger.io 39 | paths: 40 | "/pet": 41 | put: 42 | tags: 43 | - pet 44 | summary: Update an existing pet 45 | description: Update an existing pet by Id 46 | operationId: updatePet 47 | requestBody: 48 | description: Update an existent pet in the store 49 | content: 50 | application/json: 51 | schema: 52 | "$ref": "#/components/schemas/Pet" 53 | application/xml: 54 | schema: 55 | "$ref": "#/components/schemas/Pet" 56 | application/x-www-form-urlencoded: 57 | schema: 58 | "$ref": "#/components/schemas/Pet" 59 | required: true 60 | responses: 61 | '200': 62 | description: Successful operation 63 | content: 64 | application/xml: 65 | schema: 66 | "$ref": "#/components/schemas/Pet" 67 | application/json: 68 | schema: 69 | "$ref": "#/components/schemas/Pet" 70 | '400': 71 | description: Invalid ID supplied 72 | '404': 73 | description: Pet not found 74 | '405': 75 | description: Validation exception 76 | security: 77 | - petstore_auth: 78 | - write:pets 79 | - read:pets 80 | post: 81 | tags: 82 | - pet 83 | summary: Add a new pet to the store 84 | description: Add a new pet to the store 85 | operationId: addPet 86 | requestBody: 87 | description: Create a new pet in the store 88 | content: 89 | application/json: 90 | schema: 91 | "$ref": "#/components/schemas/Pet" 92 | application/xml: 93 | schema: 94 | "$ref": "#/components/schemas/Pet" 95 | application/x-www-form-urlencoded: 96 | schema: 97 | "$ref": "#/components/schemas/Pet" 98 | required: true 99 | responses: 100 | '200': 101 | description: Successful operation 102 | content: 103 | application/xml: 104 | schema: 105 | "$ref": "#/components/schemas/Pet" 106 | application/json: 107 | schema: 108 | "$ref": "#/components/schemas/Pet" 109 | '405': 110 | description: Invalid input 111 | security: 112 | - petstore_auth: 113 | - write:pets 114 | - read:pets 115 | "/pet/findByStatus": 116 | get: 117 | tags: 118 | - pet 119 | summary: Finds Pets by status 120 | description: Multiple status values can be provided with comma separated strings 121 | operationId: findPetsByStatus 122 | parameters: 123 | - name: status 124 | in: query 125 | description: Status values that need to be considered for filter 126 | required: false 127 | explode: true 128 | schema: 129 | type: string 130 | default: available 131 | enum: 132 | - available 133 | - pending 134 | - sold 135 | responses: 136 | '200': 137 | description: successful operation 138 | content: 139 | application/xml: 140 | schema: 141 | type: array 142 | items: 143 | "$ref": "#/components/schemas/Pet" 144 | application/json: 145 | schema: 146 | type: array 147 | items: 148 | "$ref": "#/components/schemas/Pet" 149 | '400': 150 | description: Invalid status value 151 | security: 152 | - petstore_auth: 153 | - write:pets 154 | - read:pets 155 | "/pet/findByTags": 156 | get: 157 | tags: 158 | - pet 159 | summary: Finds Pets by tags 160 | description: Multiple tags can be provided with comma separated strings. Use 161 | tag1, tag2, tag3 for testing. 162 | operationId: findPetsByTags 163 | parameters: 164 | - name: tags 165 | in: query 166 | description: Tags to filter by 167 | required: false 168 | explode: true 169 | schema: 170 | type: array 171 | items: 172 | type: string 173 | responses: 174 | '200': 175 | description: successful operation 176 | content: 177 | application/xml: 178 | schema: 179 | type: array 180 | items: 181 | "$ref": "#/components/schemas/Pet" 182 | application/json: 183 | schema: 184 | type: array 185 | items: 186 | "$ref": "#/components/schemas/Pet" 187 | '400': 188 | description: Invalid tag value 189 | security: 190 | - petstore_auth: 191 | - write:pets 192 | - read:pets 193 | "/pet/{petId}": 194 | get: 195 | tags: 196 | - pet 197 | summary: Find pet by ID 198 | description: Returns a single pet 199 | operationId: getPetById 200 | parameters: 201 | - name: petId 202 | in: path 203 | description: ID of pet to return 204 | required: true 205 | schema: 206 | type: integer 207 | format: int64 208 | responses: 209 | '200': 210 | description: successful operation 211 | content: 212 | application/xml: 213 | schema: 214 | "$ref": "#/components/schemas/Pet" 215 | application/json: 216 | schema: 217 | "$ref": "#/components/schemas/Pet" 218 | '400': 219 | description: Invalid ID supplied 220 | '404': 221 | description: Pet not found 222 | security: 223 | - api_key: [] 224 | - petstore_auth: 225 | - write:pets 226 | - read:pets 227 | post: 228 | tags: 229 | - pet 230 | summary: Updates a pet in the store with form data 231 | description: '' 232 | operationId: updatePetWithForm 233 | parameters: 234 | - name: petId 235 | in: path 236 | description: ID of pet that needs to be updated 237 | required: true 238 | schema: 239 | type: integer 240 | format: int64 241 | - name: name 242 | in: query 243 | description: Name of pet that needs to be updated 244 | schema: 245 | type: string 246 | - name: status 247 | in: query 248 | description: Status of pet that needs to be updated 249 | schema: 250 | type: string 251 | responses: 252 | '405': 253 | description: Invalid input 254 | security: 255 | - petstore_auth: 256 | - write:pets 257 | - read:pets 258 | delete: 259 | tags: 260 | - pet 261 | summary: Deletes a pet 262 | description: '' 263 | operationId: deletePet 264 | parameters: 265 | - name: api_key 266 | in: header 267 | description: '' 268 | required: false 269 | schema: 270 | type: string 271 | - name: petId 272 | in: path 273 | description: Pet id to delete 274 | required: true 275 | schema: 276 | type: integer 277 | format: int64 278 | responses: 279 | '400': 280 | description: Invalid pet value 281 | security: 282 | - petstore_auth: 283 | - write:pets 284 | - read:pets 285 | "/pet/{petId}/uploadImage": 286 | post: 287 | tags: 288 | - pet 289 | summary: uploads an image 290 | description: '' 291 | operationId: uploadFile 292 | parameters: 293 | - name: petId 294 | in: path 295 | description: ID of pet to update 296 | required: true 297 | schema: 298 | type: integer 299 | format: int64 300 | - name: additionalMetadata 301 | in: query 302 | description: Additional Metadata 303 | required: false 304 | schema: 305 | type: string 306 | requestBody: 307 | content: 308 | application/octet-stream: 309 | schema: 310 | type: string 311 | format: binary 312 | responses: 313 | '200': 314 | description: successful operation 315 | content: 316 | application/json: 317 | schema: 318 | "$ref": "#/components/schemas/ApiResponse" 319 | security: 320 | - petstore_auth: 321 | - write:pets 322 | - read:pets 323 | "/store/inventory": 324 | get: 325 | tags: 326 | - store 327 | summary: Returns pet inventories by status 328 | description: Returns a map of status codes to quantities 329 | operationId: getInventory 330 | responses: 331 | '200': 332 | description: successful operation 333 | content: 334 | application/json: 335 | schema: 336 | type: object 337 | additionalProperties: 338 | type: integer 339 | format: int32 340 | security: 341 | - api_key: [] 342 | "/store/order": 343 | post: 344 | tags: 345 | - store 346 | summary: Place an order for a pet 347 | description: Place a new order in the store 348 | operationId: placeOrder 349 | requestBody: 350 | content: 351 | application/json: 352 | schema: 353 | "$ref": "#/components/schemas/Order" 354 | application/xml: 355 | schema: 356 | "$ref": "#/components/schemas/Order" 357 | application/x-www-form-urlencoded: 358 | schema: 359 | "$ref": "#/components/schemas/Order" 360 | responses: 361 | '200': 362 | description: successful operation 363 | content: 364 | application/json: 365 | schema: 366 | "$ref": "#/components/schemas/Order" 367 | '405': 368 | description: Invalid input 369 | "/store/order/{orderId}": 370 | get: 371 | tags: 372 | - store 373 | summary: Find purchase order by ID 374 | description: For valid response try integer IDs with value <= 5 or > 10. Other 375 | values will generated exceptions 376 | operationId: getOrderById 377 | parameters: 378 | - name: orderId 379 | in: path 380 | description: ID of order that needs to be fetched 381 | required: true 382 | schema: 383 | type: integer 384 | format: int64 385 | responses: 386 | '200': 387 | description: successful operation 388 | content: 389 | application/xml: 390 | schema: 391 | "$ref": "#/components/schemas/Order" 392 | application/json: 393 | schema: 394 | "$ref": "#/components/schemas/Order" 395 | '400': 396 | description: Invalid ID supplied 397 | '404': 398 | description: Order not found 399 | delete: 400 | tags: 401 | - store 402 | summary: Delete purchase order by ID 403 | description: For valid response try integer IDs with value < 1000. Anything 404 | above 1000 or nonintegers will generate API errors 405 | operationId: deleteOrder 406 | parameters: 407 | - name: orderId 408 | in: path 409 | description: ID of the order that needs to be deleted 410 | required: true 411 | schema: 412 | type: integer 413 | format: int64 414 | responses: 415 | '400': 416 | description: Invalid ID supplied 417 | '404': 418 | description: Order not found 419 | "/user": 420 | post: 421 | tags: 422 | - user 423 | summary: Create user 424 | description: This can only be done by the logged in user. 425 | operationId: createUser 426 | requestBody: 427 | description: Created user object 428 | content: 429 | application/json: 430 | schema: 431 | "$ref": "#/components/schemas/User" 432 | application/xml: 433 | schema: 434 | "$ref": "#/components/schemas/User" 435 | application/x-www-form-urlencoded: 436 | schema: 437 | "$ref": "#/components/schemas/User" 438 | responses: 439 | default: 440 | description: successful operation 441 | content: 442 | application/json: 443 | schema: 444 | "$ref": "#/components/schemas/User" 445 | application/xml: 446 | schema: 447 | "$ref": "#/components/schemas/User" 448 | "/user/createWithList": 449 | post: 450 | tags: 451 | - user 452 | summary: Creates list of users with given input array 453 | description: Creates list of users with given input array 454 | operationId: createUsersWithListInput 455 | requestBody: 456 | content: 457 | application/json: 458 | schema: 459 | type: array 460 | items: 461 | "$ref": "#/components/schemas/User" 462 | responses: 463 | '200': 464 | description: Successful operation 465 | content: 466 | application/xml: 467 | schema: 468 | "$ref": "#/components/schemas/User" 469 | application/json: 470 | schema: 471 | "$ref": "#/components/schemas/User" 472 | default: 473 | description: successful operation 474 | "/user/login": 475 | get: 476 | tags: 477 | - user 478 | summary: Logs user into the system 479 | description: '' 480 | operationId: loginUser 481 | parameters: 482 | - name: username 483 | in: query 484 | description: The user name for login 485 | required: false 486 | schema: 487 | type: string 488 | - name: password 489 | in: query 490 | description: The password for login in clear text 491 | required: false 492 | schema: 493 | type: string 494 | responses: 495 | '200': 496 | description: successful operation 497 | headers: 498 | X-Rate-Limit: 499 | description: calls per hour allowed by the user 500 | schema: 501 | type: integer 502 | format: int32 503 | X-Expires-After: 504 | description: date in UTC when token expires 505 | schema: 506 | type: string 507 | format: date-time 508 | content: 509 | application/xml: 510 | schema: 511 | type: string 512 | application/json: 513 | schema: 514 | type: string 515 | '400': 516 | description: Invalid username/password supplied 517 | "/user/logout": 518 | get: 519 | tags: 520 | - user 521 | summary: Logs out current logged in user session 522 | description: '' 523 | operationId: logoutUser 524 | parameters: [] 525 | responses: 526 | default: 527 | description: successful operation 528 | "/user/{username}": 529 | get: 530 | tags: 531 | - user 532 | summary: Get user by user name 533 | description: '' 534 | operationId: getUserByName 535 | parameters: 536 | - name: username 537 | in: path 538 | description: 'The name that needs to be fetched. Use user1 for testing. ' 539 | required: true 540 | schema: 541 | type: string 542 | responses: 543 | '200': 544 | description: successful operation 545 | content: 546 | application/xml: 547 | schema: 548 | "$ref": "#/components/schemas/User" 549 | application/json: 550 | schema: 551 | "$ref": "#/components/schemas/User" 552 | '400': 553 | description: Invalid username supplied 554 | '404': 555 | description: User not found 556 | put: 557 | tags: 558 | - user 559 | summary: Update user 560 | description: This can only be done by the logged in user. 561 | operationId: updateUser 562 | parameters: 563 | - name: username 564 | in: path 565 | description: name that need to be deleted 566 | required: true 567 | schema: 568 | type: string 569 | requestBody: 570 | description: Update an existent user in the store 571 | content: 572 | application/json: 573 | schema: 574 | "$ref": "#/components/schemas/User" 575 | application/xml: 576 | schema: 577 | "$ref": "#/components/schemas/User" 578 | application/x-www-form-urlencoded: 579 | schema: 580 | "$ref": "#/components/schemas/User" 581 | responses: 582 | default: 583 | description: successful operation 584 | delete: 585 | tags: 586 | - user 587 | summary: Delete user 588 | description: This can only be done by the logged in user. 589 | operationId: deleteUser 590 | parameters: 591 | - name: username 592 | in: path 593 | description: The name that needs to be deleted 594 | required: true 595 | schema: 596 | type: string 597 | responses: 598 | '400': 599 | description: Invalid username supplied 600 | '404': 601 | description: User not found 602 | components: 603 | schemas: 604 | Order: 605 | type: object 606 | properties: 607 | id: 608 | type: integer 609 | format: int64 610 | example: 10 611 | petId: 612 | type: integer 613 | format: int64 614 | example: 198772 615 | quantity: 616 | type: integer 617 | format: int32 618 | example: 7 619 | shipDate: 620 | type: string 621 | format: date-time 622 | status: 623 | type: string 624 | description: Order Status 625 | example: approved 626 | enum: 627 | - placed 628 | - approved 629 | - delivered 630 | complete: 631 | type: boolean 632 | xml: 633 | name: order 634 | Customer: 635 | type: object 636 | properties: 637 | id: 638 | type: integer 639 | format: int64 640 | example: 100000 641 | username: 642 | type: string 643 | example: fehguy 644 | address: 645 | type: array 646 | xml: 647 | name: addresses 648 | wrapped: true 649 | items: 650 | "$ref": "#/components/schemas/Address" 651 | xml: 652 | name: customer 653 | Address: 654 | type: object 655 | properties: 656 | street: 657 | type: string 658 | example: 437 Lytton 659 | city: 660 | type: string 661 | example: Palo Alto 662 | state: 663 | type: string 664 | example: CA 665 | zip: 666 | type: string 667 | example: '94301' 668 | xml: 669 | name: address 670 | Category: 671 | type: object 672 | properties: 673 | id: 674 | type: integer 675 | format: int64 676 | example: 1 677 | name: 678 | type: string 679 | example: Dogs 680 | xml: 681 | name: category 682 | User: 683 | type: object 684 | properties: 685 | id: 686 | type: integer 687 | format: int64 688 | example: 10 689 | username: 690 | type: string 691 | example: theUser 692 | firstName: 693 | type: string 694 | example: John 695 | lastName: 696 | type: string 697 | example: James 698 | email: 699 | type: string 700 | example: john@email.com 701 | password: 702 | type: string 703 | example: '12345' 704 | phone: 705 | type: string 706 | example: '12345' 707 | userStatus: 708 | type: integer 709 | description: User Status 710 | format: int32 711 | example: 1 712 | xml: 713 | name: user 714 | Tag: 715 | type: object 716 | properties: 717 | id: 718 | type: integer 719 | format: int64 720 | name: 721 | type: string 722 | xml: 723 | name: tag 724 | Pet: 725 | required: 726 | - name 727 | - photoUrls 728 | type: object 729 | properties: 730 | id: 731 | type: integer 732 | format: int64 733 | example: 10 734 | name: 735 | type: string 736 | example: doggie 737 | category: 738 | "$ref": "#/components/schemas/Category" 739 | photoUrls: 740 | type: array 741 | xml: 742 | wrapped: true 743 | items: 744 | type: string 745 | xml: 746 | name: photoUrl 747 | tags: 748 | type: array 749 | xml: 750 | wrapped: true 751 | items: 752 | "$ref": "#/components/schemas/Tag" 753 | status: 754 | type: string 755 | description: pet status in the store 756 | enum: 757 | - available 758 | - pending 759 | - sold 760 | xml: 761 | name: pet 762 | ApiResponse: 763 | type: object 764 | properties: 765 | code: 766 | type: integer 767 | format: int32 768 | type: 769 | type: string 770 | message: 771 | type: string 772 | xml: 773 | name: "##default" 774 | requestBodies: 775 | Pet: 776 | description: Pet object that needs to be added to the store 777 | content: 778 | application/json: 779 | schema: 780 | "$ref": "#/components/schemas/Pet" 781 | application/xml: 782 | schema: 783 | "$ref": "#/components/schemas/Pet" 784 | UserArray: 785 | description: List of user object 786 | content: 787 | application/json: 788 | schema: 789 | type: array 790 | items: 791 | "$ref": "#/components/schemas/User" 792 | securitySchemes: 793 | petstore_auth: 794 | type: oauth2 795 | flows: 796 | implicit: 797 | authorizationUrl: https://petstore3.swagger.io/oauth/authorize 798 | scopes: 799 | write:pets: modify pets in your account 800 | read:pets: read your pets 801 | api_key: 802 | type: apiKey 803 | name: api_key 804 | in: header 805 | -------------------------------------------------------------------------------- /integration/petstore-portman/newman-options.json: -------------------------------------------------------------------------------- 1 | { 2 | "reporters": [ "cli", "openapi" ], 3 | "reporter": { 4 | "openapi": { 5 | "spec": "./petstore-openapi.yaml", 6 | "exportFilename": "petstore-openapi-coverage.json", 7 | "serverUrl": "http://127.0.0.1:4010", 8 | "debug": false, 9 | "reportstyle": "wide" 10 | } 11 | }, 12 | "verbose": true 13 | } -------------------------------------------------------------------------------- /integration/petstore-portman/portman-cli.json: -------------------------------------------------------------------------------- 1 | { 2 | "local": "./petstore-openapi.yaml", 3 | "output": "petstore-collection.postman.json", 4 | "portmanConfigFile": "./petstore-portman/portman-config.json", 5 | "includeTests": true, 6 | "syncPostman": true, 7 | "runNewman": true, 8 | "baseUrl": "http://127.0.0.1:4010" 9 | } -------------------------------------------------------------------------------- /lib/clireporter.js: -------------------------------------------------------------------------------- 1 | const Table = require('cli-table3') 2 | const colors = require('colors/safe') 3 | 4 | // sets theme for colors for console logging 5 | colors.setTheme({ 6 | log: 'grey', 7 | info: 'cyan', 8 | warn: 'yellow', 9 | debug: 'blue', 10 | error: 'red' 11 | }) 12 | 13 | const table = new Table({ 14 | head: [], 15 | style: { 16 | head: [], 17 | border: [] 18 | } 19 | }) 20 | 21 | module.exports.logCoverage = logCoverage 22 | 23 | function logCoverage (coverage, openapiFilename, options) { 24 | const reportTitle = options.title || coverage.title 25 | 26 | const logPathsOnly = options.reportStyle === 'summary' 27 | const wideMode = options.reportStyle === 'wide' 28 | 29 | const columns = [] 30 | 31 | // get full list of unique methods to build widemode 32 | const wideModeMethods = [] 33 | if (wideMode) { 34 | for (const path in coverage) { 35 | if (path === 'callCount' || path === 'totalCalls' || path === 'callPercentage') { 36 | continue 37 | } 38 | const pathValue = coverage[path] 39 | 40 | for (const method in pathValue) { 41 | const methodValue = pathValue[method] 42 | if (typeof methodValue !== 'object') { 43 | continue 44 | } 45 | 46 | if (wideModeMethods.indexOf(method) === -1) { 47 | wideModeMethods.push(method) 48 | } 49 | } 50 | } 51 | 52 | columns.push('Path', 'Covered') 53 | for (const method of wideModeMethods) { 54 | columns.push(method.toUpperCase()) 55 | } 56 | 57 | table.push([{ colSpan: columns.length, content: `${reportTitle + ' '}OpenAPI coverage` }]) 58 | table.push([{ colSpan: columns.length, content: openapiFilename }]) 59 | table.push([{ colSpan: 1, content: '' }, { colSpan: columns.length - 1, hAlign: 'center', content: 'Coverage' }]) 60 | 61 | // write the generated columns 62 | table.push(columns) 63 | } else { 64 | columns.push('', 'Method', 'Covered', 'Covered Responses', 'Uncovered Responses', 'Unexpected Responses') 65 | 66 | table.push([{ colSpan: logPathsOnly ? 2 : columns.length, content: `${reportTitle + ' '}OpenAPI coverage` }]) 67 | table.push([{ colSpan: logPathsOnly ? 2 : columns.length, content: openapiFilename }]) 68 | table.push([{ colSpan: logPathsOnly ? 1 : 2, content: 'Path' }, { colSpan: logPathsOnly ? 1 : columns.length - 2, hAlign: 'center', content: 'Coverage' }]) 69 | 70 | if (!logPathsOnly) { 71 | table.push(columns) 72 | } 73 | } 74 | 75 | for (const path in coverage) { 76 | if (path === 'callCount' || path === 'totalCalls' || path === 'callPercentage' || path === 'title') { 77 | continue 78 | } 79 | 80 | const pathValue = coverage[path] 81 | 82 | const pathPercentageMessage = decoratePercentage(pathValue.callPercentage) 83 | 84 | const pathColumns = [] 85 | if (wideMode) { 86 | pathColumns.push({ colSpan: 1, content: path }, pathPercentageMessage) 87 | } else { 88 | pathColumns.push({ colSpan: logPathsOnly ? 1 : 2, content: path }, pathPercentageMessage) 89 | table.push(pathColumns) 90 | } 91 | 92 | if (logPathsOnly) { 93 | continue 94 | } 95 | 96 | const wideModeMethodResponses = {} 97 | for (const method in pathValue) { 98 | const methodValue = pathValue[method] 99 | if (typeof methodValue !== 'object') { 100 | continue 101 | } 102 | 103 | let coveredResponseList = '' 104 | let UncoveredResponseList = '' 105 | let UnexpectedResponseList = '' 106 | for (const response in methodValue.responses) { 107 | const responseValue = methodValue.responses[response] 108 | 109 | if (responseValue.isUnexpected) { 110 | UnexpectedResponseList += colors.red(`?${response} `) 111 | } else if (responseValue.callCount === 0) { 112 | UncoveredResponseList += colors.red(`-${response} `) 113 | } else { 114 | coveredResponseList += colors.green(`+${response} `) 115 | } 116 | } 117 | const allResponses = `${coveredResponseList}${UncoveredResponseList}${UnexpectedResponseList}` 118 | 119 | const methodPercentageMessage = decoratePercentage(methodValue.callPercentage) 120 | if (wideMode) { 121 | wideModeMethodResponses[method] = allResponses 122 | } else { 123 | table.push(['', method, methodPercentageMessage, coveredResponseList, UncoveredResponseList, UnexpectedResponseList]) 124 | } 125 | } 126 | 127 | if (wideMode) { 128 | for (const method of wideModeMethods) { 129 | const methodValue = wideModeMethodResponses[method] 130 | if (methodValue) { 131 | pathColumns.push(methodValue) 132 | } else { 133 | pathColumns.push('') 134 | } 135 | } 136 | table.push(pathColumns) 137 | } 138 | } 139 | 140 | const totalPercentageMessage = decoratePercentage(coverage.callPercentage) 141 | if (wideMode) { 142 | table.push([{ colSpan: 1, content: 'Total API Coverage' }, totalPercentageMessage]) 143 | } else { 144 | table.push([{ colSpan: logPathsOnly ? 1 : 2, content: 'Total API Coverage' }, totalPercentageMessage]) 145 | } 146 | 147 | console.log(table.toString()) 148 | } 149 | 150 | function decoratePercentage (percentageValue) { 151 | let percentageMessage = `${percentageValue}%` 152 | if (percentageValue >= 100) { 153 | percentageMessage = colors.green(percentageMessage) 154 | } else if (percentageValue <= 0) { 155 | percentageMessage = colors.red(percentageMessage) 156 | } 157 | 158 | return percentageMessage 159 | } 160 | -------------------------------------------------------------------------------- /lib/index.js: -------------------------------------------------------------------------------- 1 | const Tracker = require('./tracker') 2 | const cliReporter = require('./clireporter') 3 | 4 | const OpenAPICoverage = function (emitter, reporterOptions, collectionRunOptions) { 5 | console.log('OpenAPI reporter loaded') 6 | // emitter is is an event emitter that triggers the following events: https://github.com/postmanlabs/newman#newmanrunevents 7 | // reporterOptions is an object of the reporter specific options. See usage examples below for more details. 8 | // collectionRunOptions is an object of all the collection run options: 9 | // https://github.com/postmanlabs/newman#newmanrunoptions-object--callback-function--run-eventemitter 10 | 11 | // console.log(reporterOptions) 12 | // console.log(collectionRunOptions) 13 | // console.log(JSON.stringify(reporterOptions)) 14 | const openapiFilename = reporterOptions.spec || undefined 15 | const exportFilename = reporterOptions.export || undefined 16 | const debugMode = reporterOptions.debug || false 17 | const serverUrl = reporterOptions.serverUrl || undefined 18 | const title = reporterOptions.title || undefined 19 | 20 | const reportStyle = reporterOptions.reportstyle || 'wide' 21 | 22 | let tracker 23 | 24 | emitter.on('start', function (err, args) { 25 | if (err) { 26 | return 27 | } 28 | 29 | if (typeof openapiFilename !== 'string') { 30 | console.error('ERROR: An openapi spec path must be included with --reporter-openapi-spec {filename}') 31 | process.exit(1) 32 | } 33 | 34 | tracker = new Tracker() 35 | 36 | if (!tracker.specExists(openapiFilename)) { 37 | console.error(`OpenAPI spec ${openapiFilename} does not exist!`) 38 | process.exit(1) 39 | } 40 | 41 | tracker.initialise(openapiFilename) 42 | if (!tracker.getSchema()) { 43 | console.error(`ERROR: Openapi spec ${openapiFilename} could not be parsed!`) 44 | process.exit(1) 45 | } 46 | 47 | tracker.setDebugMode(debugMode) 48 | }) 49 | 50 | emitter.on('request', function (err, o) { 51 | if (err) { 52 | return 53 | } 54 | 55 | const req = o.request 56 | const res = o.response 57 | 58 | if (!res) { 59 | console.log('Request didn\'t have a response') 60 | return 61 | } 62 | 63 | // use url without query 64 | let url = req.url.toString() 65 | const queryParams = url.indexOf('?') 66 | if (queryParams > -1) { 67 | url = url.substring(0, queryParams) 68 | } 69 | 70 | tracker.updateOperation(url, req.method, res.code, { serverUrl }) 71 | }) 72 | 73 | emitter.on('beforeDone', function (err, o) { 74 | if (err) { 75 | return 76 | } 77 | const coverage = tracker.createCoverage() 78 | cliReporter.logCoverage(coverage, openapiFilename, { reportStyle, title }) 79 | 80 | if (exportFilename) { 81 | emitter.exports.push({ 82 | name: 'openapi-coverage', 83 | default: 'newman-openapi-coverage.json', 84 | path: exportFilename, 85 | content: JSON.stringify(coverage, null, 2) 86 | }) 87 | } 88 | }) 89 | } 90 | 91 | module.exports = OpenAPICoverage 92 | -------------------------------------------------------------------------------- /lib/tracker.js: -------------------------------------------------------------------------------- 1 | const deasync = require('deasync') 2 | const fs = require('fs') 3 | const refParser = require('@apidevtools/json-schema-ref-parser') 4 | 5 | module.exports = class Tracker { 6 | addCallCounts () { 7 | this.openAPIDocument.callCount = 0 8 | this.openAPIDocument.totalCalls = 0 9 | 10 | for (const path in this.openAPIDocument.paths) { 11 | const pathValue = this.openAPIDocument.paths[path] 12 | pathValue.callCount = 0 13 | pathValue.totalCalls = 0 14 | 15 | for (const method in pathValue) { 16 | if (method === 'callCount' || method === 'totalCalls') { 17 | continue 18 | } 19 | 20 | const methodValue = pathValue[method] 21 | methodValue.callCount = 0 22 | methodValue.totalCalls = 0 23 | 24 | for (const response in methodValue.responses) { 25 | const responseValue = methodValue.responses[response] 26 | responseValue.callCount = 0 27 | pathValue.totalCalls += 1 28 | methodValue.totalCalls += 1 29 | this.openAPIDocument.totalCalls += 1 30 | } 31 | } 32 | } 33 | } 34 | 35 | checkPath (url, path) { 36 | // number of path elements must match 37 | if (url.split('/').length !== path.split('/').length) { 38 | return false 39 | } 40 | 41 | if (path.indexOf('{') > 0) { 42 | const regex = /{.*?}/ig 43 | const matchPath = new RegExp('^' + path.replace(regex, '[^/]+') + '$') 44 | 45 | if (matchPath.test(url)) { 46 | return true 47 | } 48 | } else { 49 | if (url === path) { 50 | return true 51 | } 52 | } 53 | return false 54 | } 55 | 56 | createCoverage () { 57 | const coverage = { 58 | title: '' 59 | } 60 | if (this.openAPIDocument.info && this.openAPIDocument.info.title) { 61 | coverage.title = this.openAPIDocument.info.title 62 | } 63 | 64 | coverage.callCount = this.openAPIDocument.callCount 65 | coverage.totalCalls = this.openAPIDocument.totalCalls 66 | coverage.callPercentage = this.percentage(this.openAPIDocument.callCount, this.openAPIDocument.totalCalls) 67 | 68 | for (const path in this.openAPIDocument.paths) { 69 | const pathValue = this.openAPIDocument.paths[path] 70 | 71 | coverage[path] = { 72 | callCount: pathValue.callCount, 73 | totalCalls: pathValue.totalCalls, 74 | callPercentage: this.percentage(pathValue.callCount, pathValue.totalCalls) 75 | } 76 | 77 | for (const method in pathValue) { 78 | const methodValue = pathValue[method] 79 | if (typeof methodValue !== 'object') { 80 | continue 81 | } 82 | 83 | coverage[path][method] = { 84 | callCount: methodValue.callCount, 85 | totalCalls: methodValue.totalCalls, 86 | callPercentage: this.percentage(methodValue.callCount, methodValue.totalCalls), 87 | responses: {} 88 | } 89 | 90 | for (const response in methodValue.responses) { 91 | const responseValue = methodValue.responses[response] 92 | 93 | coverage[path][method].responses[response] = { 94 | callCount: responseValue.callCount, 95 | isUnexpected: responseValue.isUnexpected 96 | } 97 | } 98 | } 99 | } 100 | 101 | return coverage 102 | } 103 | 104 | async dereference (specFilename) { 105 | if (!this.isJestRunning()) { 106 | // use deasync to make this synchronous 107 | let complete = false 108 | refParser.dereference(specFilename, (err, schema) => { 109 | if (err) { 110 | console.error(`ERROR in RefParser: ${err.message ? err.message : err}`) 111 | } else { 112 | this.openAPIDocument = schema 113 | // make json unique 114 | this.openAPIDocument = JSON.parse(JSON.stringify(this.openAPIDocument)) 115 | console.log(`Parsed schema file ${specFilename}`) 116 | } 117 | complete = true 118 | }) 119 | deasync.loopWhile(() => { 120 | return !complete 121 | }) 122 | } else { 123 | try { 124 | this.openAPIDocument = await refParser.dereference(specFilename) 125 | // make json unique 126 | this.openAPIDocument = JSON.parse(JSON.stringify(this.openAPIDocument)) 127 | console.log(`Parsed schema file ${specFilename}`) 128 | } catch (err) { 129 | console.error(err) 130 | } 131 | } 132 | } 133 | 134 | getMethodCaseInsensitive (object, method) { 135 | for (const pathMethod in object) { 136 | if (pathMethod === 'callCount' || pathMethod === 'totalCalls') { 137 | continue 138 | } 139 | this.logDebug(` Checking method [${pathMethod}]...`) 140 | if (pathMethod.toLowerCase() === method.toLowerCase()) { 141 | this.logDebug(' Method matches') 142 | return object[pathMethod] 143 | } 144 | } 145 | 146 | return undefined 147 | } 148 | 149 | getPath (url) { 150 | // check all paths 151 | const pathMatches = Object.keys(this.openAPIDocument.paths) 152 | .filter((element) => { 153 | return this.checkPath(url, element) 154 | }) 155 | // fast first match 156 | if (pathMatches.length === 0) { 157 | return undefined 158 | } else if (pathMatches.length === 1) { 159 | const path = pathMatches[0] 160 | this.logDebug(` Found matching path [${path}]...`) 161 | return this.openAPIDocument.paths[path] 162 | } 163 | 164 | // more than one match so we need to pick one 165 | const urlParts = url.split('/') 166 | for (let partNumber = 1; partNumber < urlParts.length; partNumber++) { 167 | const urlPart = urlParts[partNumber] 168 | 169 | // check part in each path 170 | for (let pathNumber = pathMatches.length - 1; pathNumber >= 0; pathNumber--) { 171 | const path = pathMatches[pathNumber] 172 | // does part match? 173 | const pathParts = path.split('/') 174 | if (pathParts[partNumber] !== urlPart) { 175 | pathMatches.splice(pathNumber, 1) 176 | } 177 | } 178 | 179 | // are we left with one value? 180 | if (pathMatches.length === 1) { 181 | const path = pathMatches[0] 182 | this.logDebug(` Found matching path [${path}]...`) 183 | return this.openAPIDocument.paths[path] 184 | } else if (pathMatches.length === 0) { 185 | break 186 | } 187 | } 188 | 189 | return undefined 190 | } 191 | 192 | getSchema () { 193 | return this.openAPIDocument 194 | } 195 | 196 | getServer (url) { 197 | for (const server of this.openAPIDocument.servers) { 198 | this.logDebug(` Checking server [${server.url}]...`) 199 | if (url.startsWith(server.url)) { 200 | this.logDebug(' Server matches') 201 | return server.url 202 | } 203 | } 204 | return undefined 205 | } 206 | 207 | async initialise (specFilename) { 208 | if (!this.isJestRunning()) { 209 | this.dereference(specFilename) 210 | } else { 211 | await this.dereference(specFilename) 212 | } 213 | if (!this.openAPIDocument) { 214 | return 215 | } 216 | 217 | this.addCallCounts() 218 | } 219 | 220 | isJestRunning () { 221 | return process.env.JEST_WORKER_ID !== undefined 222 | } 223 | 224 | logDebug (message) { 225 | if (this.debugMode) { 226 | console.log(message) 227 | } 228 | } 229 | 230 | logError (message, context) { 231 | const output = { 232 | message, 233 | ...context 234 | } 235 | console.error(JSON.stringify(output, null, 2)) 236 | } 237 | 238 | percentage (calls, totalCalls) { 239 | if (totalCalls === 0) { 240 | return 0 241 | } 242 | return Math.round((100 * calls) / totalCalls) 243 | } 244 | 245 | setDebugMode (debugMode) { 246 | this.debugMode = debugMode 247 | } 248 | 249 | setSchema (schema) { 250 | this.openAPIDocument = schema 251 | if (this.openAPIDocument) { 252 | this.addCallCounts() 253 | } 254 | } 255 | 256 | specExists (specFilename) { 257 | return fs.existsSync(specFilename) && fs.lstatSync(specFilename).isFile() 258 | } 259 | 260 | updateOperation (url, method, code, options) { 261 | const fixedServerUrl = (options && options.serverUrl) || undefined 262 | 263 | this.logDebug(`Resolving [${url}] [${method}] [${code}] ...`) 264 | 265 | if (!this.openAPIDocument.servers) { 266 | console.error('ERROR: No servers!!!') 267 | return undefined 268 | } 269 | 270 | let server 271 | if (fixedServerUrl && url.startsWith(fixedServerUrl)) { 272 | this.logDebug(` Matched fixed server [${server}]...`) 273 | server = fixedServerUrl 274 | } else { 275 | server = this.getServer(url) 276 | if (!server) { 277 | this.logError('Error: No matching server!!!', { method, code, url }) 278 | return undefined 279 | } 280 | } 281 | 282 | let relativeUrl = url.replace(server, '') 283 | if (relativeUrl.endsWith('/')) { 284 | relativeUrl = relativeUrl.slice(0, -1) 285 | } 286 | 287 | if (!this.openAPIDocument.paths) { 288 | console.error('ERROR: No paths!!!') 289 | return undefined 290 | } 291 | 292 | this.logDebug(`Checking ${relativeUrl} for a Path`) 293 | 294 | const matchPath = this.getPath(relativeUrl) 295 | if (!matchPath) { 296 | this.logError('Error: Ambiguous or no matching path!!!', { method, code, url, server, relativeUrl }) 297 | return undefined 298 | } 299 | 300 | const matchMethod = this.getMethodCaseInsensitive(matchPath, method) 301 | if (!matchMethod) { 302 | this.logError('Error: No matching method!!!', { method, code, url, server, relativeUrl }) 303 | return undefined 304 | } 305 | 306 | let matchResponse = matchMethod.responses[code] 307 | if (!matchResponse) { 308 | // if there is no default method then we have no response match 309 | if (!matchMethod.responses.default) { 310 | // add this code in as unexpected 311 | matchMethod.responses[code] = { 312 | isUnexpected: true, 313 | callCount: 0 314 | } 315 | matchResponse = matchMethod.responses[code] 316 | this.logError('Error: No matching response!!!', { method, code, url, server, relativeUrl }) 317 | } else { 318 | matchResponse = matchMethod.responses.default 319 | } 320 | } 321 | 322 | if (matchResponse.callCount === 0 && !matchResponse.isUnexpected) { 323 | matchMethod.callCount++ 324 | matchPath.callCount++ 325 | this.openAPIDocument.callCount++ 326 | } 327 | matchResponse.callCount++ 328 | 329 | return { 330 | method, 331 | code, 332 | url, 333 | server, 334 | relativeUrl, 335 | matchPath, 336 | matchMethod, 337 | matchResponse 338 | } 339 | } 340 | } 341 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "newman-reporter-openapi", 3 | "version": "0.0.8", 4 | "description": "Newman reporter for OpenAPI coverage", 5 | "repository": { 6 | "type": "git", 7 | "url": "https://github.com/NickHeap2/newman-reporter-openapi.git" 8 | }, 9 | "keywords": [ 10 | "api", 11 | "api testing", 12 | "coverage", 13 | "newman", 14 | "newman-reporter", 15 | "newman reporter", 16 | "openapi", 17 | "portman", 18 | "postman", 19 | "reporter" 20 | ], 21 | "main": "lib/index.js", 22 | "scripts": { 23 | "debug": "newman", 24 | "lint": "standard \"**/*.js\"", 25 | "test": "jest", 26 | "pack": "npm pack", 27 | "install:local": "npm pack && npm i -g newman-reporter-openapi-0.0.6.tgz" 28 | }, 29 | "files": [ 30 | "lib/**" 31 | ], 32 | "author": { 33 | "name": "Nick Heap", 34 | "email": "nickheap@gmail.com", 35 | "url": "https://github.com/NickHeap2" 36 | }, 37 | "license": "MIT", 38 | "devDependencies": { 39 | "@types/jest": "^27.4.1", 40 | "jest": "^27.5.1", 41 | "standard": "^17.0.0" 42 | }, 43 | "dependencies": { 44 | "@apidevtools/json-schema-ref-parser": "^9.0.9", 45 | "deasync": "^0.1.26", 46 | "cli-table3": "^0.6.2", 47 | "colors": "^1.4.0" 48 | }, 49 | "standard": { 50 | "env": [ 51 | "jest" 52 | ], 53 | "ignore": [ 54 | "dist/**/*", 55 | "**/node_modules/**" 56 | ] 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /tests/dupe-ref.json: -------------------------------------------------------------------------------- 1 | { 2 | "description": "Bad request" 3 | } -------------------------------------------------------------------------------- /tests/dupe-ref.yaml: -------------------------------------------------------------------------------- 1 | description: Bad request -------------------------------------------------------------------------------- /tests/dupe-schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "openapi" : "3.0.0", 3 | "info" : { 4 | "title" : "Refpath spec", 5 | "description" : "Refpath spec", 6 | "version" : "1.0.1", 7 | "contact" : { 8 | "email" : "me@mail.com" 9 | } 10 | }, 11 | "servers" : [ { 12 | "url" : "/api" 13 | } ], 14 | "tags" : [ { 15 | "name" : "refpath" 16 | } ], 17 | "paths" : { 18 | "/refpath" : { 19 | "get" : { 20 | "tags" : [ "get" ], 21 | "summary" : "Get a refpath", 22 | "description" : "Get a refpath", 23 | "operationId" : "getRefpath", 24 | "responses" : { 25 | "200" : { 26 | "description" : "OK" 27 | }, 28 | "400" : { 29 | "$ref" : "dupe-ref.json" 30 | } 31 | } 32 | }, 33 | "post" : { 34 | "tags" : [ "post" ], 35 | "summary" : "Post a refpath", 36 | "description" : "Post a refpath", 37 | "operationId" : "postRefpath", 38 | "responses" : { 39 | "201" : { 40 | "description" : "Created" 41 | }, 42 | "400" : { 43 | "$ref" : "dupe-ref.json" 44 | } 45 | } 46 | } 47 | } 48 | } 49 | } -------------------------------------------------------------------------------- /tests/dupe-schema.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | openapi: 3.0.0 3 | info: 4 | title: "Refpath spec" 5 | description: "Refpath spec" 6 | version: 0.0.1 7 | contact: 8 | email: "me@mail.com" 9 | servers: 10 | - url: "/api" 11 | tags: 12 | - name: refpath 13 | paths: 14 | /refpath: 15 | get: 16 | tags: 17 | - get 18 | summary: Get a refpath 19 | description: Get a refpath 20 | operationId: getRefpath 21 | responses: 22 | "200": 23 | description: OK 24 | "400": 25 | $ref: dupe-ref.yaml 26 | 27 | post: 28 | tags: 29 | - post 30 | summary: Post a refpath 31 | description: Post a refpath 32 | operationId: postRefpath 33 | responses: 34 | "201": 35 | description: Created 36 | "400": 37 | $ref: dupe-ref.yaml 38 | -------------------------------------------------------------------------------- /tests/invalid-schema.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | openapi: 3.0.0 3 | info: 4 | title: "Refpath spec" 5 | description: "Refpath spec" 6 | version: 0.0.1 7 | contact: 8 | email: "me@mail.com" 9 | servers: 10 | - url: "/api" 11 | tags: 12 | - name: refpath 13 | paths: 14 | /refpath: 15 | $ref: "missing-refpath.yaml" 16 | -------------------------------------------------------------------------------- /tests/path-ordering.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | openapi: 3.0.0 3 | info: 4 | title: "Path ordering spec" 5 | description: "Path ordering spec" 6 | version: 0.0.1 7 | contact: 8 | email: "me@mail.com" 9 | servers: 10 | - url: "/api" 11 | tags: 12 | - name: refpath 13 | paths: 14 | /resource/{resourceId}: 15 | get: 16 | tags: 17 | - get 18 | summary: Get a resource 19 | description: Get a resource 20 | operationId: getResource 21 | parameters: 22 | - in: path 23 | name: resourceId 24 | required: true 25 | schema: 26 | type: string 27 | responses: 28 | "200": 29 | description: OK 30 | /resource/getall: 31 | get: 32 | tags: 33 | - get 34 | summary: Get all resources 35 | description: Get all resources 36 | operationId: getBulkResource 37 | responses: 38 | "200": 39 | description: OK 40 | /correctorder/getall: 41 | get: 42 | tags: 43 | - get 44 | summary: Get all resources 45 | description: Get all resources 46 | operationId: getCorrectOrder1 47 | responses: 48 | "200": 49 | description: OK 50 | /correctorder/{resourceId}: 51 | get: 52 | tags: 53 | - get 54 | summary: Get a resource 55 | description: Get a resource 56 | operationId: getCorrectOrder2 57 | parameters: 58 | - in: path 59 | name: resourceId 60 | required: true 61 | schema: 62 | type: string 63 | responses: 64 | "200": 65 | description: OK 66 | /resource/{resourceId}/subresourceB/{subresourceBId}: 67 | get: 68 | tags: 69 | - get 70 | summary: Get a B resource 71 | description: Get a B resource 72 | operationId: getResourceB 73 | parameters: 74 | - in: path 75 | name: resourceId 76 | required: true 77 | schema: 78 | type: string 79 | - in: path 80 | name: subresourceBId 81 | required: true 82 | schema: 83 | type: string 84 | responses: 85 | "200": 86 | description: OK 87 | /resource/{resourceId}/subresourceA/{subresourceAId}: 88 | get: 89 | tags: 90 | - get 91 | summary: Get a A resource 92 | description: Get a A resource 93 | operationId: getResourceA 94 | parameters: 95 | - in: path 96 | name: resourceId 97 | required: true 98 | schema: 99 | type: string 100 | - in: path 101 | name: subresourceAId 102 | required: true 103 | schema: 104 | type: string 105 | responses: 106 | "200": 107 | description: OK 108 | /ambiguous/{firstId}: 109 | get: 110 | tags: 111 | - get 112 | summary: Get an ambiguous 113 | description: Get an ambiguous 114 | operationId: getFirst 115 | parameters: 116 | - in: path 117 | name: firstId 118 | required: true 119 | schema: 120 | type: string 121 | responses: 122 | "200": 123 | description: OK 124 | /ambiguous/{secondId}: 125 | get: 126 | tags: 127 | - get 128 | summary: Get an ambiguous 129 | description: Get an ambiguous 130 | operationId: getSecond 131 | parameters: 132 | - in: path 133 | name: secondId 134 | required: true 135 | schema: 136 | type: string 137 | responses: 138 | "200": 139 | description: OK 140 | -------------------------------------------------------------------------------- /tests/refpath.yaml: -------------------------------------------------------------------------------- 1 | get: 2 | tags: 3 | - refpath 4 | summary: Get a refpath 5 | description: Get a refpath 6 | operationId: getRefpath 7 | -------------------------------------------------------------------------------- /tests/tracker.test.js: -------------------------------------------------------------------------------- 1 | /* globals describe it expect */ 2 | const Tracker = require('../lib/tracker') 3 | 4 | global.console = { 5 | warn: jest.fn(), 6 | log: jest.fn(), 7 | error: jest.fn() 8 | } 9 | 10 | let tracker 11 | 12 | describe('utils dereference', function () { 13 | beforeEach(() => { 14 | tracker = new Tracker() 15 | }) 16 | 17 | it('should load a valid spec and resolve it', async function () { 18 | await tracker.dereference('tests/valid-schema.yaml') 19 | const schema = tracker.getSchema() 20 | expect(schema).toBeDefined() 21 | 22 | expect(schema).toHaveProperty(['paths', '/refpath', 'get', 'summary']) 23 | expect(schema.paths['/refpath'].get.summary).toEqual('Get a refpath') 24 | expect(schema).not.toHaveProperty('callCount') 25 | 26 | // console.log(JSON.stringify(schema, null, 2)) 27 | }) 28 | 29 | it('should not dereference an invalid spec', async function () { 30 | await tracker.dereference('tests/invalid-schema.yaml') 31 | const schema = tracker.getSchema() 32 | expect(schema).not.toBeDefined() 33 | }) 34 | }) 35 | describe('utils initialise', function () { 36 | beforeEach(() => { 37 | tracker = new Tracker() 38 | }) 39 | 40 | it('should initialise a valid spec', async function () { 41 | await tracker.initialise('tests/valid-schema.yaml') 42 | const schema = tracker.getSchema() 43 | expect(schema).toBeDefined() 44 | 45 | expect(schema).toHaveProperty(['paths', '/refpath', 'get', 'summary']) 46 | expect(schema.paths['/refpath'].get.summary).toEqual('Get a refpath') 47 | expect(schema).toHaveProperty('callCount') 48 | expect(schema.callCount).toEqual(0) 49 | 50 | // console.log(JSON.stringify(schema, null, 2)) 51 | }) 52 | }) 53 | 54 | describe('utils path', function () { 55 | it('should match a path', function () { 56 | const result = tracker.checkPath('/test/path', '/test/path') 57 | expect(result).toBeTruthy() 58 | }) 59 | 60 | it('should not match a path', function () { 61 | const result = tracker.checkPath('/test/path', '/whatever') 62 | expect(result).toBeFalsy() 63 | }) 64 | 65 | it('should match a path', function () { 66 | const result = tracker.checkPath('/test/path', '/test/path') 67 | expect(result).toBeTruthy() 68 | }) 69 | 70 | it('should match a path with vars', function () { 71 | const result = tracker.checkPath('/test/12-34-56', '/test/{id}') 72 | expect(result).toBeTruthy() 73 | }) 74 | 75 | it('should match a path with a dash', function () { 76 | const result = tracker.checkPath('/pet/-93114376/uploadImage', '/pet/{petId}/uploadImage') 77 | expect(result).toBeTruthy() 78 | }) 79 | 80 | it('shouldn\'t match a path that is longer', function () { 81 | const result = tracker.checkPath('/pet/-93114376/uploadImage', '/pet/{petId}') 82 | expect(result).toBeFalsy() 83 | }) 84 | 85 | it('should match a path with percentages', function () { 86 | const result = tracker.checkPath('/user/ad%20labore', '/user/{username}') 87 | expect(result).toBeTruthy() 88 | }) 89 | 90 | it('should match a path with dashes', function () { 91 | const result = tracker.checkPath('/users/e64e18e9-d01b-4378-bf98-b4d21e307793/modules/68d902bf-07e9-4fd1-ab18-f17362de3608', '/users/{userId}/modules/{id}') 92 | expect(result).toBeTruthy() 93 | }) 94 | 95 | it('should match this path', function () { 96 | const result = tracker.checkPath('/applet-categories/7e74e7a8-a994-46c3-a79e-25ae44791983', '/applet-categories/{appletCategoryId}') 97 | expect(result).toBeTruthy() 98 | }) 99 | 100 | it('should match a path with dashes 2', function () { 101 | const result = tracker.checkPath('/workplaces/bsapi-workplace/groups/b0c535f5-1b8e-4388-8819-f73a9bda652d/modules/269198e4-d36d-4236-8b5a-f4a76bcb1f43', '/workplaces/{workplaceRef}/groups/{groupid}/modules/{id}') 102 | expect(result).toBeTruthy() 103 | }) 104 | 105 | it('should match a path with two vars', function () { 106 | const result = tracker.checkPath('/test/12-34-56/nested/09-87-65', '/test/{id}/nested/{nestedid}') 107 | expect(result).toBeTruthy() 108 | }) 109 | }) 110 | 111 | describe('utils updateOperation', function () { 112 | beforeEach(() => { 113 | tracker = new Tracker() 114 | tracker.logError = jest.fn() 115 | tracker.setSchema({ 116 | servers: [ 117 | { 118 | url: 'http://127.0.0.1:3000' 119 | } 120 | ], 121 | paths: { 122 | '/mittens': { 123 | delete: { 124 | responses: { 125 | 400: { 126 | } 127 | } 128 | } 129 | }, 130 | '/kittens': { 131 | post: { 132 | responses: { 133 | 201: { 134 | }, 135 | 400: { 136 | }, 137 | 401: { 138 | }, 139 | 403: { 140 | }, 141 | 409: { 142 | }, 143 | 415: { 144 | } 145 | } 146 | }, 147 | delete: { 148 | responses: { 149 | 400: { 150 | }, 151 | 404: { 152 | } 153 | } 154 | } 155 | } 156 | } 157 | }) 158 | }) 159 | 160 | it('should process a valid operation', function () { 161 | const result = tracker.updateOperation('http://127.0.0.1:3000/kittens', 'DELETE', '404') 162 | expect(result).toBeDefined() 163 | expect(tracker.logError).not.toHaveBeenCalled() 164 | }) 165 | 166 | it('should not process an operation with missing server', function () { 167 | const result = tracker.updateOperation('http://my-server0/kittens', 'DELETE', '404') 168 | expect(result).toBeUndefined() 169 | expect(tracker.logError).toHaveBeenCalledTimes(1) 170 | }) 171 | 172 | it('should not process an operation with missing path', function () { 173 | const result = tracker.updateOperation('http://127.0.0.1:3000/dogs', 'DELETE', '404') 174 | expect(result).toBeUndefined() 175 | expect(tracker.logError).toHaveBeenCalledTimes(1) 176 | }) 177 | 178 | it('should not process an operation with missing response', function () { 179 | const result = tracker.updateOperation('http://127.0.0.1:3000/kittens', 'DELETE', '401') 180 | expect(result).toBeDefined() 181 | expect(result).toHaveProperty('matchMethod') 182 | expect(result.matchMethod).toHaveProperty('responses') 183 | expect(result.matchMethod.responses).toHaveProperty('401') 184 | expect(result.matchMethod.responses['401']).toMatchObject({ isUnexpected: true }) 185 | expect(tracker.logError).toHaveBeenCalledTimes(1) 186 | }) 187 | 188 | it('should track responses', function () { 189 | let result 190 | 191 | // post 400 192 | result = tracker.updateOperation('http://127.0.0.1:3000/kittens', 'POST', '400') 193 | expect(result).toBeDefined() 194 | 195 | // check call counts 196 | expect(result).toHaveProperty('matchPath.callCount') 197 | expect(result.matchPath.callCount).toEqual(1) 198 | 199 | expect(result.matchPath).toHaveProperty('post.callCount') 200 | expect(result.matchPath.post.callCount).toEqual(1) 201 | 202 | expect(result.matchPath.post).toHaveProperty('responses.400.callCount') 203 | expect(result.matchPath.post.responses['400'].callCount).toEqual(1) 204 | 205 | // delete 400 206 | result = tracker.updateOperation('http://127.0.0.1:3000/kittens', 'DELETE', '400') 207 | expect(result).toBeDefined() 208 | 209 | // check call counts 210 | expect(result).toHaveProperty('matchPath.callCount') 211 | expect(result.matchPath.callCount).toEqual(2) 212 | 213 | expect(result.matchPath).toHaveProperty('delete.callCount') 214 | expect(result.matchPath.delete.callCount).toEqual(1) 215 | 216 | expect(result.matchPath.delete).toHaveProperty('responses.400.callCount') 217 | expect(result.matchPath.delete.responses['400'].callCount).toEqual(1) 218 | 219 | const coverage = tracker.createCoverage() 220 | // expect(coverage).toEqual('') 221 | expect(coverage).toHaveProperty('/kittens') 222 | expect(coverage['/kittens']).toHaveProperty('callCount') 223 | expect(coverage['/kittens'].callCount).toEqual(2) 224 | 225 | expect(coverage['/kittens']).toHaveProperty('post') 226 | expect(coverage['/kittens'].post).toHaveProperty('callCount') 227 | expect(coverage['/kittens'].post.callCount).toEqual(1) 228 | 229 | expect(coverage['/kittens'].post).toHaveProperty('responses.400.callCount') 230 | expect(coverage['/kittens'].post.responses['400'].callCount).toEqual(1) 231 | 232 | expect(coverage['/kittens']).toHaveProperty('delete') 233 | expect(coverage['/kittens'].delete).toHaveProperty('callCount') 234 | expect(coverage['/kittens'].delete.callCount).toEqual(1) 235 | 236 | expect(coverage['/kittens'].delete).toHaveProperty('responses.400') 237 | expect(coverage['/kittens'].delete.responses['400'].callCount).toEqual(1) 238 | }) 239 | 240 | it('should track multiple responses', function () { 241 | let result 242 | 243 | // first make some calls to things that don't exist 244 | result = tracker.updateOperation('http://127.0.0.1:3001/kittens', 'POST', '201') 245 | expect(result).toBeUndefined() 246 | result = tracker.updateOperation('http://127.0.0.1:3000/kittensaaa', 'GET', '404') 247 | expect(result).toBeUndefined() 248 | result = tracker.updateOperation('http://127.0.0.1:3000/kittens', 'PUT', '404') 249 | expect(result).toBeUndefined() 250 | 251 | // post 201 252 | result = tracker.updateOperation('http://127.0.0.1:3000/kittens', 'POST', '201') 253 | expect(result).toBeDefined() 254 | 255 | // check total calls from schema 256 | expect(result).toHaveProperty('matchPath.totalCalls') 257 | expect(result.matchPath.totalCalls).toEqual(8) 258 | 259 | expect(result).toHaveProperty('matchPath.post.totalCalls') 260 | expect(result.matchPath.post.totalCalls).toEqual(6) 261 | 262 | expect(result).toHaveProperty('matchPath.delete.totalCalls') 263 | expect(result.matchPath.delete.totalCalls).toEqual(2) 264 | 265 | // check call counts 266 | expect(result).toHaveProperty('matchPath.callCount') 267 | expect(result.matchPath.callCount).toEqual(1) 268 | 269 | expect(result.matchPath).toHaveProperty('post.callCount') 270 | expect(result.matchPath.callCount).toEqual(1) 271 | 272 | expect(result.matchPath.post).toHaveProperty('responses.201.callCount') 273 | expect(result.matchPath.post.responses['201'].callCount).toEqual(1) 274 | 275 | // post 201 276 | result = tracker.updateOperation('http://127.0.0.1:3000/kittens', 'POST', '201') 277 | expect(result).toBeDefined() 278 | 279 | // check call counts 280 | expect(result).toHaveProperty('matchPath.callCount') 281 | expect(result.matchPath.callCount).toEqual(1) 282 | 283 | expect(result.matchPath).toHaveProperty('post.callCount') 284 | expect(result.matchPath.callCount).toEqual(1) 285 | 286 | expect(result.matchPath.post).toHaveProperty('responses.201.callCount') 287 | expect(result.matchPath.post.responses['201'].callCount).toEqual(2) 288 | 289 | // post 400 290 | result = tracker.updateOperation('http://127.0.0.1:3000/kittens', 'POST', '400') 291 | expect(result).toBeDefined() 292 | 293 | // check call counts 294 | expect(result).toHaveProperty('matchPath.callCount') 295 | expect(result.matchPath.callCount).toEqual(2) 296 | 297 | expect(result.matchPath).toHaveProperty('post.callCount') 298 | expect(result.matchPath.callCount).toEqual(2) 299 | 300 | expect(result.matchPath.post).toHaveProperty('responses.400.callCount') 301 | expect(result.matchPath.post.responses['400'].callCount).toEqual(1) 302 | 303 | // post 404 304 | result = tracker.updateOperation('http://127.0.0.1:3000/kittens', 'POST', '404') 305 | expect(result).toBeDefined() 306 | 307 | // check call counts 308 | expect(result).toHaveProperty('matchPath.callCount') 309 | expect(result.matchPath.callCount).toEqual(2) 310 | 311 | expect(result.matchPath).toHaveProperty('post.callCount') 312 | expect(result.matchPath.post.callCount).toEqual(2) 313 | 314 | expect(result.matchPath.post).toHaveProperty('responses.404.callCount') 315 | expect(result.matchPath.post.responses['404'].callCount).toEqual(1) 316 | 317 | // delete 400 318 | result = tracker.updateOperation('http://127.0.0.1:3000/mittens', 'DELETE', '400') 319 | expect(result).toBeDefined() 320 | 321 | // check call counts 322 | expect(result).toHaveProperty('matchPath.callCount') 323 | expect(result.matchPath.callCount).toEqual(1) 324 | 325 | expect(result.matchPath).toHaveProperty('delete.callCount') 326 | expect(result.matchPath.delete.callCount).toEqual(1) 327 | 328 | expect(result.matchPath.delete).toHaveProperty('responses.400.callCount') 329 | expect(result.matchPath.delete.responses['400'].callCount).toEqual(1) 330 | 331 | // delete 400 332 | result = tracker.updateOperation('http://127.0.0.1:3000/kittens', 'DELETE', '400') 333 | expect(result).toBeDefined() 334 | 335 | // check call counts 336 | expect(result).toHaveProperty('matchPath.callCount') 337 | expect(result.matchPath.callCount).toEqual(3) 338 | 339 | expect(result.matchPath).toHaveProperty('delete.callCount') 340 | expect(result.matchPath.delete.callCount).toEqual(1) 341 | 342 | expect(result.matchPath.delete).toHaveProperty('responses.400.callCount') 343 | expect(result.matchPath.delete.responses['400'].callCount).toEqual(1) 344 | }) 345 | 346 | describe('utils coverage', function () { 347 | beforeEach(() => { 348 | tracker.logError = jest.fn() 349 | tracker.setSchema({ 350 | servers: [ 351 | { 352 | url: 'http://127.0.0.1:3000' 353 | } 354 | ], 355 | paths: { 356 | '/products': { 357 | post: { 358 | responses: { 359 | 201: { 360 | }, 361 | 400: { 362 | }, 363 | 401: { 364 | }, 365 | 403: { 366 | }, 367 | 409: { 368 | }, 369 | 415: { 370 | } 371 | } 372 | }, 373 | get: { 374 | responses: { 375 | 200: { 376 | }, 377 | 400: { 378 | }, 379 | 401: { 380 | }, 381 | 403: { 382 | } 383 | } 384 | } 385 | } 386 | } 387 | }) 388 | }) 389 | 390 | it('should get correct coverage for /products scenario', function () { 391 | // post 201 * 4 392 | for (let o = 0; o < 4; o++) { 393 | tracker.updateOperation('http://127.0.0.1:3000/products', 'POST', '201') 394 | } 395 | 396 | // post 409 * 3 397 | for (let o = 0; o < 3; o++) { 398 | tracker.updateOperation('http://127.0.0.1:3000/products', 'POST', '409') 399 | } 400 | 401 | // post 400 * 31 402 | for (let o = 0; o < 31; o++) { 403 | tracker.updateOperation('http://127.0.0.1:3000/products', 'POST', '400') 404 | } 405 | 406 | // post 415 * 1 407 | for (let o = 0; o < 1; o++) { 408 | tracker.updateOperation('http://127.0.0.1:3000/products', 'POST', '415') 409 | } 410 | 411 | // post 401 * 1 412 | for (let o = 0; o < 1; o++) { 413 | tracker.updateOperation('http://127.0.0.1:3000/products', 'POST', '401') 414 | } 415 | 416 | // get 200 * 3 417 | for (let o = 0; o < 3; o++) { 418 | tracker.updateOperation('http://127.0.0.1:3000/products', 'GET', '200') 419 | } 420 | 421 | // get 400 * 8 422 | for (let o = 0; o < 8; o++) { 423 | tracker.updateOperation('http://127.0.0.1:3000/products', 'GET', '400') 424 | } 425 | 426 | // get 403 * 1 427 | for (let o = 0; o < 1; o++) { 428 | tracker.updateOperation('http://127.0.0.1:3000/products', 'GET', '403') 429 | } 430 | 431 | // get 400 * 1 432 | for (let o = 0; o < 1; o++) { 433 | tracker.updateOperation('http://127.0.0.1:3000/products', 'GET', '400') 434 | } 435 | 436 | // get 401 * 1 437 | for (let o = 0; o < 1; o++) { 438 | tracker.updateOperation('http://127.0.0.1:3000/products', 'GET', '401') 439 | } 440 | 441 | const coverage = tracker.createCoverage() 442 | // expect(coverage).toEqual('') 443 | expect(coverage).toHaveProperty('/products') 444 | expect(coverage['/products']).toHaveProperty('callCount') 445 | expect(coverage['/products'].callCount).toEqual(9) 446 | 447 | expect(coverage['/products']).toHaveProperty('post') 448 | expect(coverage['/products'].post).toHaveProperty('callCount') 449 | expect(coverage['/products'].post.callCount).toEqual(5) 450 | 451 | expect(coverage['/products'].post).toHaveProperty('responses.201.callCount') 452 | expect(coverage['/products'].post.responses['201'].callCount).toEqual(4) 453 | 454 | expect(coverage['/products'].post).toHaveProperty('responses.409.callCount') 455 | expect(coverage['/products'].post.responses['409'].callCount).toEqual(3) 456 | 457 | expect(coverage['/products'].post).toHaveProperty('responses.400.callCount') 458 | expect(coverage['/products'].post.responses['400'].callCount).toEqual(31) 459 | 460 | expect(coverage['/products'].post).toHaveProperty('responses.415.callCount') 461 | expect(coverage['/products'].post.responses['415'].callCount).toEqual(1) 462 | 463 | expect(coverage['/products'].post).toHaveProperty('responses.401.callCount') 464 | expect(coverage['/products'].post.responses['401'].callCount).toEqual(1) 465 | 466 | expect(coverage['/products']).toHaveProperty('get') 467 | expect(coverage['/products'].get).toHaveProperty('callCount') 468 | expect(coverage['/products'].get.callCount).toEqual(4) 469 | 470 | expect(coverage['/products'].get).toHaveProperty('responses.200') 471 | expect(coverage['/products'].get.responses['200'].callCount).toEqual(3) 472 | 473 | expect(coverage['/products'].get).toHaveProperty('responses.400') 474 | expect(coverage['/products'].get.responses['400'].callCount).toEqual(9) 475 | 476 | expect(coverage['/products'].get).toHaveProperty('responses.403') 477 | expect(coverage['/products'].get.responses['403'].callCount).toEqual(1) 478 | 479 | expect(coverage['/products'].get).toHaveProperty('responses.401') 480 | expect(coverage['/products'].get.responses['401'].callCount).toEqual(1) 481 | }) 482 | }) 483 | }) 484 | 485 | describe('dupe ref scenario', function () { 486 | beforeEach(() => { 487 | tracker = new Tracker() 488 | tracker.logError = jest.fn() 489 | }) 490 | 491 | it('should work correctly', async function () { 492 | await tracker.initialise('tests/dupe-schema.yaml') 493 | const schema = tracker.getSchema() 494 | expect(schema).toBeDefined() 495 | 496 | const server = '/api' 497 | 498 | tracker.updateOperation(`${server}/refpath`, 'POST', '201') 499 | tracker.updateOperation(`${server}/refpath`, 'POST', '400') 500 | tracker.updateOperation(`${server}/refpath`, 'GET', '200') 501 | tracker.updateOperation(`${server}/refpath`, 'GET', '400') 502 | 503 | const coverage = tracker.createCoverage() 504 | expect(coverage).toHaveProperty('/refpath') 505 | expect(coverage['/refpath']).toHaveProperty('callCount') 506 | expect(coverage['/refpath'].callCount).toEqual(4) 507 | 508 | expect(coverage['/refpath']).toHaveProperty('post') 509 | expect(coverage['/refpath'].post).toHaveProperty('callCount') 510 | expect(coverage['/refpath'].post.callCount).toEqual(2) 511 | 512 | expect(coverage['/refpath'].post).toHaveProperty('responses.201.callCount') 513 | expect(coverage['/refpath'].post.responses['201'].callCount).toEqual(1) 514 | 515 | expect(coverage['/refpath'].post).toHaveProperty('responses.400.callCount') 516 | expect(coverage['/refpath'].post.responses['400'].callCount).toEqual(1) 517 | 518 | expect(coverage['/refpath']).toHaveProperty('get') 519 | expect(coverage['/refpath'].get).toHaveProperty('callCount') 520 | expect(coverage['/refpath'].get.callCount).toEqual(2) 521 | 522 | expect(coverage['/refpath'].get).toHaveProperty('responses.200') 523 | expect(coverage['/refpath'].get.responses['200'].callCount).toEqual(1) 524 | 525 | expect(coverage['/refpath'].get).toHaveProperty('responses.400') 526 | expect(coverage['/refpath'].get.responses['400'].callCount).toEqual(1) 527 | }) 528 | 529 | it('should work correctly', async function () { 530 | await tracker.initialise('tests/dupe-schema.json') 531 | const schema = tracker.getSchema() 532 | expect(schema).toBeDefined() 533 | 534 | const server = '/api' 535 | 536 | tracker.updateOperation(`${server}/refpath`, 'POST', '201') 537 | tracker.updateOperation(`${server}/refpath`, 'POST', '400') 538 | tracker.updateOperation(`${server}/refpath`, 'GET', '200') 539 | tracker.updateOperation(`${server}/refpath`, 'GET', '400') 540 | 541 | const coverage = tracker.createCoverage() 542 | expect(coverage).toHaveProperty('/refpath') 543 | expect(coverage['/refpath']).toHaveProperty('callCount') 544 | expect(coverage['/refpath'].callCount).toEqual(4) 545 | 546 | expect(coverage['/refpath']).toHaveProperty('post') 547 | expect(coverage['/refpath'].post).toHaveProperty('callCount') 548 | expect(coverage['/refpath'].post.callCount).toEqual(2) 549 | 550 | expect(coverage['/refpath'].post).toHaveProperty('responses.201.callCount') 551 | expect(coverage['/refpath'].post.responses['201'].callCount).toEqual(1) 552 | 553 | expect(coverage['/refpath'].post).toHaveProperty('responses.400.callCount') 554 | expect(coverage['/refpath'].post.responses['400'].callCount).toEqual(1) 555 | 556 | expect(coverage['/refpath']).toHaveProperty('get') 557 | expect(coverage['/refpath'].get).toHaveProperty('callCount') 558 | expect(coverage['/refpath'].get.callCount).toEqual(2) 559 | 560 | expect(coverage['/refpath'].get).toHaveProperty('responses.200') 561 | expect(coverage['/refpath'].get.responses['200'].callCount).toEqual(1) 562 | 563 | expect(coverage['/refpath'].get).toHaveProperty('responses.400') 564 | expect(coverage['/refpath'].get.responses['400'].callCount).toEqual(1) 565 | }) 566 | }) 567 | 568 | describe('path ordering scenario', function () { 569 | beforeEach(() => { 570 | tracker = new Tracker() 571 | tracker.logError = jest.fn() 572 | 573 | jest.resetAllMocks() 574 | }) 575 | 576 | it('should work correctly with concrete', async function () { 577 | await tracker.initialise('tests/path-ordering.yaml') 578 | const schema = tracker.getSchema() 579 | expect(schema).toBeDefined() 580 | 581 | const server = '/api' 582 | 583 | tracker.updateOperation(`${server}/resource/123/subresourceA/456`, 'GET', '200') 584 | tracker.updateOperation(`${server}/resource/getall`, 'GET', '200') 585 | tracker.updateOperation(`${server}/correctorder/getall`, 'GET', '200') 586 | 587 | const coverage = tracker.createCoverage() 588 | 589 | let resource = '/resource/{resourceId}/subresourceA/{subresourceAId}' 590 | expect(coverage).toHaveProperty(resource) 591 | expect(coverage[resource]).toHaveProperty('callCount') 592 | expect(coverage[resource].callCount).toEqual(1) 593 | 594 | resource = '/resource/{resourceId}/subresourceB/{subresourceBId}' 595 | expect(coverage).toHaveProperty(resource) 596 | expect(coverage[resource]).toHaveProperty('callCount') 597 | expect(coverage[resource].callCount).toEqual(0) 598 | 599 | resource = '/resource/getall' 600 | expect(coverage).toHaveProperty(resource) 601 | expect(coverage[resource]).toHaveProperty('callCount') 602 | expect(coverage[resource].callCount).toEqual(1) 603 | 604 | resource = '/resource/{resourceId}' 605 | expect(coverage).toHaveProperty(resource) 606 | expect(coverage[resource]).toHaveProperty('callCount') 607 | expect(coverage[resource].callCount).toEqual(0) 608 | 609 | resource = '/correctorder/getall' 610 | expect(coverage).toHaveProperty(resource) 611 | expect(coverage[resource]).toHaveProperty('callCount') 612 | expect(coverage[resource].callCount).toEqual(1) 613 | 614 | resource = '/correctorder/{resourceId}' 615 | expect(coverage).toHaveProperty(resource) 616 | expect(coverage[resource]).toHaveProperty('callCount') 617 | expect(coverage[resource].callCount).toEqual(0) 618 | }) 619 | 620 | it('should work correctly with reverse', async function () { 621 | await tracker.initialise('tests/path-ordering.yaml') 622 | const schema = tracker.getSchema() 623 | expect(schema).toBeDefined() 624 | 625 | const server = '/api' 626 | 627 | tracker.updateOperation(`${server}/resource/123/subresourceB/456`, 'GET', '200') 628 | tracker.updateOperation(`${server}/resource/123`, 'GET', '200') 629 | tracker.updateOperation(`${server}/correctorder/123`, 'GET', '200') 630 | 631 | const coverage = tracker.createCoverage() 632 | 633 | let resource = '/resource/{resourceId}/subresourceA/{subresourceAId}' 634 | expect(coverage).toHaveProperty(resource) 635 | expect(coverage[resource]).toHaveProperty('callCount') 636 | expect(coverage[resource].callCount).toEqual(0) 637 | 638 | resource = '/resource/{resourceId}/subresourceB/{subresourceBId}' 639 | expect(coverage).toHaveProperty(resource) 640 | expect(coverage[resource]).toHaveProperty('callCount') 641 | expect(coverage[resource].callCount).toEqual(1) 642 | 643 | resource = '/resource/getall' 644 | expect(coverage).toHaveProperty(resource) 645 | expect(coverage[resource]).toHaveProperty('callCount') 646 | expect(coverage[resource].callCount).toEqual(0) 647 | 648 | resource = '/resource/{resourceId}' 649 | expect(coverage).toHaveProperty(resource) 650 | expect(coverage[resource]).toHaveProperty('callCount') 651 | expect(coverage[resource].callCount).toEqual(1) 652 | 653 | resource = '/correctorder/getall' 654 | expect(coverage).toHaveProperty(resource) 655 | expect(coverage[resource]).toHaveProperty('callCount') 656 | expect(coverage[resource].callCount).toEqual(0) 657 | 658 | resource = '/correctorder/{resourceId}' 659 | expect(coverage).toHaveProperty(resource) 660 | expect(coverage[resource]).toHaveProperty('callCount') 661 | expect(coverage[resource].callCount).toEqual(1) 662 | }) 663 | 664 | it('should work correctly with ambiguous', async function () { 665 | await tracker.initialise('tests/path-ordering.yaml') 666 | const schema = tracker.getSchema() 667 | expect(schema).toBeDefined() 668 | 669 | const server = '/api' 670 | 671 | tracker.updateOperation(`${server}/ambiguous/123`, 'GET', '200') 672 | 673 | const coverage = tracker.createCoverage() 674 | 675 | expect(tracker.logError).toBeCalledTimes(1) 676 | expect(tracker.logError).toBeCalledWith('Error: Ambiguous or no matching path!!!', { code: '200', method: 'GET', relativeUrl: '/ambiguous/123', server: '/api', url: '/api/ambiguous/123' }) 677 | 678 | let resource = '/ambiguous/{firstId}' 679 | expect(coverage).toHaveProperty(resource) 680 | expect(coverage[resource]).toHaveProperty('callCount') 681 | expect(coverage[resource].callCount).toEqual(0) 682 | 683 | resource = '/ambiguous/{secondId}' 684 | expect(coverage).toHaveProperty(resource) 685 | expect(coverage[resource]).toHaveProperty('callCount') 686 | expect(coverage[resource].callCount).toEqual(0) 687 | }) 688 | }) 689 | -------------------------------------------------------------------------------- /tests/valid-schema.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | openapi: 3.0.0 3 | info: 4 | title: "Refpath spec" 5 | description: "Refpath spec" 6 | version: 0.0.1 7 | contact: 8 | email: "me@mail.com" 9 | servers: 10 | - url: "/api" 11 | tags: 12 | - name: refpath 13 | paths: 14 | /refpath: 15 | $ref: "refpath.yaml" 16 | --------------------------------------------------------------------------------