├── catalog-info.yaml ├── src └── main │ ├── java │ └── com │ │ └── postman │ │ └── collection │ │ ├── enumEventType.java │ │ ├── enumItemType.java │ │ ├── enumAuthType.java │ │ ├── RecursiveItemAddException.java │ │ ├── enumRawBodyLanguage.java │ │ ├── VariableResolutionException.java │ │ ├── enumHTTPRequestMethod.java │ │ ├── InvalidPropertyException.java │ │ ├── package-info.java │ │ ├── enumRequestBodyMode.java │ │ ├── Folder.java │ │ ├── IllegalPropertyAccessException.java │ │ ├── CollectionNotFoundException.java │ │ ├── ValidationException.java │ │ ├── DuplicateVariableKeyException.java │ │ ├── InvalidCollectionActionException.java │ │ ├── PostmanID.java │ │ ├── enumVariableResolution.java │ │ ├── adapter │ │ ├── StringMapSerializer.java │ │ ├── CollectionSerializer.java │ │ ├── AuthSerializer.java │ │ ├── PropertyListSerializer.java │ │ ├── PropertyDeserializer.java │ │ ├── ItemGroupDeserializer.java │ │ ├── PropertySerializer.java │ │ ├── ItemDeserializer.java │ │ └── AuthDeserializer.java │ │ ├── Request.java │ │ ├── Cookie.java │ │ ├── Property.java │ │ ├── PropertyList.java │ │ ├── Response.java │ │ ├── RequestBody.java │ │ ├── Event.java │ │ ├── ItemGroup.java │ │ ├── Item.java │ │ └── CollectionElement.java │ └── resources │ └── com │ └── postman │ └── collection │ ├── auth-query-tester.postman_collection.json │ ├── test-variable-types.postman_collection.json │ ├── example-url.postman_collection.json │ ├── example-weather.postman_collection.json │ ├── source-code.postman_collection.json │ ├── example-cat-facts-with-tests.postman_collection.json │ ├── example-catfact.postman_collection.json │ ├── example-lots-of-variables.postman_collection.json │ └── auth.postman_collection.json ├── .mvn ├── extensions.xml └── jgitver.config.xml ├── .github ├── dependabot.yml └── workflows │ ├── build-snapshot-jar.yml │ ├── test-compile.yml │ ├── build-gh-page.yml │ └── codeql.yml ├── pom.xml ├── README.md └── LICENSE /catalog-info.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: backstage.io/v1alpha1 2 | kind: Component 3 | metadata: 4 | name: JPostman 5 | annotations: 6 | github.com/project-slug: bidnessforb/JPostman 7 | spec: 8 | type: other 9 | lifecycle: unknown 10 | owner: guests 11 | -------------------------------------------------------------------------------- /src/main/java/com/postman/collection/enumEventType.java: -------------------------------------------------------------------------------- 1 | package com.postman.collection; 2 | /** 3 | * 4 | * 5 | * 6 | * 7 | * Enumerates the valid values for the listen property of an {@link com.postman.collection.Event} element. 8 | * 9 | * 10 | */ 11 | public enum enumEventType { 12 | PRE_REQUEST, 13 | TEST 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/com/postman/collection/enumItemType.java: -------------------------------------------------------------------------------- 1 | package com.postman.collection; 2 | /** 3 | * 4 | * 5 | * Enumerates the two types of objects that can serve as an element in a collections item array. A folder is an item that does not have a request. 6 | * 7 | * 8 | */ 9 | public enum enumItemType { 10 | FOLDER, 11 | REQUEST 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/com/postman/collection/enumAuthType.java: -------------------------------------------------------------------------------- 1 | package com.postman.collection; 2 | /** 3 | * 4 | * 5 | * Enumerates valid values for the type property of the auth element of a collection or request. 6 | * 7 | 8 | * 9 | * 10 | * 11 | * 12 | */ 13 | public enum enumAuthType { 14 | 15 | AKAMAI, APIKEY, AWS, BEARER, BASIC, DIGEST, HAWK, OAUTH1, OAUTH2, NTLM 16 | 17 | } 18 | -------------------------------------------------------------------------------- /.mvn/extensions.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | fr.brouillard.oss 5 | jgitver-maven-plugin 6 | 1.9.0 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/main/java/com/postman/collection/RecursiveItemAddException.java: -------------------------------------------------------------------------------- 1 | package com.postman.collection; 2 | /** 3 | * 4 | * 5 | * 6 | * Exception thrown if there is an attempt to add an item as a child to itself. 7 | * 8 | * 9 | * 10 | */ 11 | 12 | 13 | public class RecursiveItemAddException extends Exception { 14 | public RecursiveItemAddException(String message) { 15 | super(message); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/com/postman/collection/enumRawBodyLanguage.java: -------------------------------------------------------------------------------- 1 | package com.postman.collection; 2 | /** 3 | * 4 | * Enumerates valid values for the value of the options/raw/language property of a {@link com.postman.collection.RequestBody} object when that body's mode property 5 | * is set to raw 6 | * 7 | * 8 | */ 9 | public enum enumRawBodyLanguage { 10 | TEXT,JAVASCRIPT,JSON,HTML,XML,GRAPHQL; 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/com/postman/collection/VariableResolutionException.java: -------------------------------------------------------------------------------- 1 | package com.postman.collection; 2 | 3 | 4 | /** 5 | * 6 | * Error thrown if something prevents the resolution of a variable value, eg., the specified variable doesn't exist, etc. 7 | * 8 | * 9 | */ 10 | 11 | 12 | public class VariableResolutionException extends Exception { 13 | 14 | public VariableResolutionException(String message) { 15 | super(message); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/com/postman/collection/enumHTTPRequestMethod.java: -------------------------------------------------------------------------------- 1 | package com.postman.collection; 2 | /** 3 | * 4 | * 5 | * Enumerates valid HTTP methods, e.g, for the method property of a {@link com.postman.collection.RequestBody} element 6 | * 7 | * 8 | * 9 | */ 10 | public enum enumHTTPRequestMethod { 11 | 12 | GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS, COPY, LINK, UNLINK, PURGE, LOCK, UNLOCK, PROPFIND, VIEW, TRACE 13 | 14 | }; 15 | -------------------------------------------------------------------------------- /src/main/java/com/postman/collection/InvalidPropertyException.java: -------------------------------------------------------------------------------- 1 | package com.postman.collection; 2 | /** 3 | * 4 | * 5 | * Exception thrown when an invalid action is taken against an object property, eg., an attempt to see an {@link com.postman.collection.Event}'s exec property to null, etc. 6 | * 7 | * 8 | */ 9 | public class InvalidPropertyException extends Exception { 10 | public InvalidPropertyException(String msg) { 11 | super(msg); 12 | } 13 | 14 | } 15 | 16 | -------------------------------------------------------------------------------- /src/main/java/com/postman/collection/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * Encapsulates a Postman JSON collection and emulates functionality of the Postman SDK. 4 | * 5 | *

Collection JSON format v2.1.0 overview.

6 | * 7 | *

JPostman README

8 | * 9 | */ 10 | package com.postman.collection; 11 | -------------------------------------------------------------------------------- /src/main/java/com/postman/collection/enumRequestBodyMode.java: -------------------------------------------------------------------------------- 1 | package com.postman.collection; 2 | /** 3 | * 4 | * 5 | * Enumeration listing the possible values for the name of the property containing body data in a {@link com.postman.collection.Request} 6 | * 7 | *

Postman SDK analog: MODES

8 | * 9 | * 10 | * 11 | */ 12 | public enum enumRequestBodyMode { 13 | TEXT,FORMDATA,RAW,FILE,GRAPHQL,URLENCODED; 14 | } 15 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # To get started with Dependabot version updates, you'll need to specify which 2 | # package ecosystems to update and where the package manifests are located. 3 | # Please see the documentation for all configuration options: 4 | # https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates 5 | 6 | version: 2 7 | updates: 8 | - package-ecosystem: "maven" # See documentation for possible values 9 | directory: "/" # Location of package manifests 10 | schedule: 11 | interval: "weekly" 12 | -------------------------------------------------------------------------------- /src/main/java/com/postman/collection/Folder.java: -------------------------------------------------------------------------------- 1 | package com.postman.collection; 2 | /** 3 | * 4 | * 5 | * 6 | * Convenience class for the concept of a Folder in a Postman Collection. 7 | * 8 | *

Postman SDK analog: ItemGroup.

9 | * 10 | * 11 | * 12 | * 13 | * 14 | * 15 | * 16 | * 17 | * 18 | * 19 | */ 20 | public class Folder extends ItemGroup { 21 | 22 | 23 | public Folder(String name) { 24 | super(name); 25 | } 26 | 27 | 28 | 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/com/postman/collection/IllegalPropertyAccessException.java: -------------------------------------------------------------------------------- 1 | package com.postman.collection; 2 | /** 3 | * 4 | * 5 | * 6 | * Exception thrown when an invalid action is taken against PropertyList, eg., IndexOutOfBounds, attempts to set the raw property of a {@link com.postman.collection.BodyElement} when that body's mode is not raw etc. 7 | * 8 | * 9 | */ 10 | public class IllegalPropertyAccessException extends Exception { 11 | public IllegalPropertyAccessException(String message) { 12 | super(message); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/com/postman/collection/CollectionNotFoundException.java: -------------------------------------------------------------------------------- 1 | package com.postman.collection; 2 | /** 3 | * 4 | * Thrown when a collection is not found in Postman, or if a 404 is thrown attempting to retrieve 5 | * a collection from Postman by URI 6 | * 7 | */ 8 | public class CollectionNotFoundException extends Exception{ 9 | 10 | /** 11 | * 12 | * Default constructor 13 | * @param message The message to pass with the exception 14 | */ 15 | public CollectionNotFoundException(String message) { 16 | super(message); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/com/postman/collection/ValidationException.java: -------------------------------------------------------------------------------- 1 | package com.postman.collection; 2 | 3 | /** 4 | * 5 | * 6 | * Exception thrown if there is a system, syntax or other error/exception which interrupts or prevents actual validation of the element. 7 | * 8 | * 9 | * 10 | * 11 | */ 12 | 13 | 14 | public class ValidationException extends Exception { 15 | 16 | public ValidationException(Throwable cause) { 17 | super("Validation Exception", cause); 18 | } 19 | 20 | public ValidationException(String message) { 21 | super(message); 22 | 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/com/postman/collection/DuplicateVariableKeyException.java: -------------------------------------------------------------------------------- 1 | package com.postman.collection; 2 | /** 3 | * 4 | * 5 | * Exception thrown when an attempt is made to add a {@link com.postman.collection.Property} to a {@link com.postman.collection.PropertyList} with a duplicate key 6 | * 7 | * 8 | * 9 | */ 10 | public class DuplicateVariableKeyException extends Exception{ 11 | 12 | /** 13 | * 14 | * 15 | * Constructs the exception 16 | * 17 | * @param message The message to send with the exception 18 | */ 19 | public DuplicateVariableKeyException(String message) { 20 | super(message); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/com/postman/collection/InvalidCollectionActionException.java: -------------------------------------------------------------------------------- 1 | package com.postman.collection; 2 | /** 3 | * 4 | * 5 | * Exception thrown when an invalid action is attempted on a collection, eg. attempting to add an item to a non-existent parent, etc. 6 | * 7 | * 8 | * 9 | */ 10 | public class InvalidCollectionActionException extends Exception { 11 | /** 12 | * 13 | * 14 | * 15 | * @param message 16 | */ 17 | public InvalidCollectionActionException(String message) { 18 | super(message); 19 | } 20 | 21 | public InvalidCollectionActionException(Throwable cause) { 22 | super(cause); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/com/postman/collection/PostmanID.java: -------------------------------------------------------------------------------- 1 | package com.postman.collection; 2 | 3 | /** 4 | * 5 | * 6 | * Convenience class to enable TypeSafe references to Postman UUIDs. 7 | * 8 | *

NOTE: This class does not provide any validation.

9 | * 10 | * 11 | * 12 | */ 13 | 14 | 15 | public class PostmanID { 16 | private String ID; 17 | public PostmanID(String ID) { 18 | this.ID = ID; 19 | } 20 | 21 | 22 | /** 23 | * @return String 24 | */ 25 | public String toString() { 26 | return this.ID; 27 | } 28 | 29 | 30 | /** 31 | * @return String 32 | */ 33 | public String getID() { 34 | return this.ID; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/com/postman/collection/enumVariableResolution.java: -------------------------------------------------------------------------------- 1 | package com.postman.collection; 2 | /** 3 | * 4 | * 5 | *

Enumeration listing variable resolution strategies

6 | * 7 | * 8 | * 9 | * 10 | * 11 | * 12 | * 13 | * 14 | * 15 | * 16 | * 17 | * 18 | * 19 | * 20 | * 21 | * 22 | * 23 | * 24 | * 25 | *
StrategyDescription
RESOLVEResolve a variable token, eg. {{baseUrl}} into the value stored in this collections variable element
TRANSFORMTransform the Postman variable syntax into another syntax, For example, {{baseUrl}} to ${baseUrl} (JMeter syntax).
NONEReturn the literal value
26 | * 27 | * 28 | */ 29 | public enum enumVariableResolution { 30 | RESOLVE, TRANSFORM, NONE 31 | } 32 | -------------------------------------------------------------------------------- /.github/workflows/build-snapshot-jar.yml: -------------------------------------------------------------------------------- 1 | # This workflow will build a Java project with Maven, and cache/restore any dependencies to improve the workflow execution time 2 | # For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-java-with-maven 3 | 4 | # This workflow uses actions that are not certified by GitHub. 5 | # They are provided by a third-party and are governed by 6 | # separate terms of service, privacy policy, and support 7 | # documentation. 8 | 9 | name: Build LATEST Snapshot JAR 10 | 11 | on: 12 | push: 13 | branches: [ "main" ] 14 | #pull_request: 15 | # branches: [ "main" ] 16 | 17 | jobs: 18 | build: 19 | 20 | runs-on: ubuntu-latest 21 | 22 | steps: 23 | 24 | - uses: actions/checkout@v3 25 | - name: Set up JDK 18 26 | uses: actions/setup-java@v3 27 | with: 28 | java-version: '18' 29 | distribution: 'temurin' 30 | # cache: maven 31 | - name: Build with Maven 32 | run: mvn -B clean compile assembly:single 33 | #TODO: Upload as release artifact 34 | -------------------------------------------------------------------------------- /src/main/resources/com/postman/collection/auth-query-tester.postman_collection.json: -------------------------------------------------------------------------------- 1 | { 2 | "info": { 3 | "_postman_id": "2c9d1530-e082-4a03-bb10-a650c2880ee9", 4 | "name": "AUTH tester", 5 | "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json", 6 | "_exporter_id": "23889826" 7 | }, 8 | "item": [ 9 | { 10 | "name": "Test auth", 11 | "request": { 12 | "auth": { 13 | "type": "apikey", 14 | "apikey": [ 15 | { 16 | "key": "in", 17 | "value": "query", 18 | "type": "string" 19 | }, 20 | { 21 | "key": "key", 22 | "value": "API-KEY", 23 | "type": "string" 24 | }, 25 | { 26 | "key": "value", 27 | "value": "x-api-key", 28 | "type": "string" 29 | } 30 | ] 31 | }, 32 | "method": "GET", 33 | "header": [], 34 | "url": { 35 | "raw": "https://postman-echo.com/post", 36 | "protocol": "https", 37 | "host": [ 38 | "postman-echo", 39 | "com" 40 | ], 41 | "path": [ 42 | "post" 43 | ] 44 | } 45 | }, 46 | "response": [] 47 | } 48 | ] 49 | } -------------------------------------------------------------------------------- /src/main/java/com/postman/collection/adapter/StringMapSerializer.java: -------------------------------------------------------------------------------- 1 | package com.postman.collection.adapter; 2 | 3 | import com.google.gson.JsonObject; 4 | import com.google.gson.JsonElement; 5 | import com.google.gson.JsonSerializer; 6 | import java.util.HashMap; 7 | import com.google.gson.JsonSerializationContext; 8 | import java.util.Iterator; 9 | 10 | import java.lang.reflect.Type; 11 | 12 | public class StringMapSerializer implements JsonSerializer> { 13 | 14 | 15 | /** 16 | * @param src 17 | * @param typeOfSrc 18 | * @param context 19 | * @return JsonElement 20 | */ 21 | @Override 22 | public JsonElement serialize(HashMap src, Type typeOfSrc, JsonSerializationContext context) { 23 | 24 | JsonObject jsonMap = new JsonObject(); 25 | Iterator keys = src.keySet().iterator(); 26 | String curKey; 27 | while (keys.hasNext()) { 28 | curKey = keys.next(); 29 | jsonMap.addProperty(curKey, src.get(curKey)); 30 | } 31 | 32 | return jsonMap; 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /.github/workflows/test-compile.yml: -------------------------------------------------------------------------------- 1 | # This workflow will build a Java project with Maven, and cache/restore any dependencies to improve the workflow execution time 2 | # For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-java-with-maven 3 | 4 | # This workflow uses actions that are not certified by GitHub. 5 | # They are provided by a third-party and are governed by 6 | # separate terms of service, privacy policy, and support 7 | # documentation. 8 | 9 | name: Compile and unit test 10 | 11 | on: 12 | push: 13 | branches: 14 | - '!main' 15 | pull_request: 16 | workflow_dispatch: 17 | 18 | jobs: 19 | build: 20 | runs-on: ubuntu-latest 21 | 22 | steps: 23 | 24 | - uses: actions/checkout@v3 25 | - name: Set up JDK 18 26 | uses: actions/setup-java@v3 27 | with: 28 | java-version: '18' 29 | distribution: 'temurin' 30 | - name: Build and test with Maven 31 | env: 32 | POSTMAN_API_KEY: ${{ secrets.POSTMAN_API_KEY }} 33 | run: | 34 | mkdir ./test-output 35 | mvn test 36 | 37 | 38 | 39 | # Optional: Uploads the full dependency graph to GitHub to improve the quality of Dependabot alerts this repository can receive 40 | - name: Update dependency graph 41 | uses: advanced-security/maven-dependency-submission-action@571e99aab1055c2e71a1e2309b9691de18d6b7d6 42 | -------------------------------------------------------------------------------- /src/main/java/com/postman/collection/adapter/CollectionSerializer.java: -------------------------------------------------------------------------------- 1 | package com.postman.collection.adapter; 2 | 3 | import com.google.gson.JsonObject; 4 | import com.google.gson.JsonElement; 5 | import com.google.gson.JsonSerializer; 6 | import com.google.gson.JsonSerializationContext; 7 | import com.postman.collection.*; 8 | import java.lang.reflect.Type; 9 | 10 | 11 | /** 12 | * 13 | * Custom serializer for the collection element. JSON does not require a particular order in order to be valid. However, Postman always outputs collections in the same order. 14 | * This serializer replicates that order. 15 | * 16 | */ 17 | public class CollectionSerializer implements JsonSerializer { 18 | 19 | 20 | /** 21 | * @param src The Collection passed in by Gson 22 | * @param typeOfSrc The Java Type of the object being parsed 23 | * @param context Serialization context passed in by Gson 24 | * @return JsonElement The resulting Json 25 | */ 26 | @Override 27 | public JsonElement serialize(Collection src, Type typeOfSrc, JsonSerializationContext context) { 28 | 29 | JsonObject collJsonMap = new JsonObject(); 30 | 31 | collJsonMap.add("info", context.serialize(src.getInfo())); 32 | collJsonMap.add("item",context.serialize(src.getItems())); 33 | collJsonMap.add("event", context.serialize(src.getEvents())); 34 | collJsonMap.add("variable", context.serialize(src.getVariables())); 35 | collJsonMap.add("auth",context.serialize(src.getAuth())); 36 | 37 | return collJsonMap; 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/com/postman/collection/adapter/AuthSerializer.java: -------------------------------------------------------------------------------- 1 | package com.postman.collection.adapter; 2 | 3 | import com.postman.collection.*; 4 | import com.google.gson.JsonObject; 5 | import com.google.gson.JsonArray; 6 | import com.google.gson.JsonElement; 7 | 8 | import com.google.gson.JsonSerializer; 9 | import com.google.gson.JsonSerializationContext; 10 | import java.lang.reflect.Type; 11 | 12 | /** 13 | * 14 | * 15 | * Custom serializer for the auth element. 16 | * 17 | * 18 | */ 19 | public class AuthSerializer implements JsonSerializer { 20 | 21 | 22 | /** 23 | * @param src The {@link com.postman.collection.RequestAuth} object to be deserialized 24 | * @param typeOfSrc The type, {@link com.postman.collection.RequestAuth} 25 | * @param context Serialization context 26 | * @return JsonElement The JSON element returned by this serializer 27 | */ 28 | @Override 29 | public JsonElement serialize(RequestAuth src, Type typeOfSrc, JsonSerializationContext context) { 30 | JsonObject jsonAuth = new JsonObject(); 31 | JsonArray vars = new JsonArray(); 32 | 33 | jsonAuth.addProperty("type", src.getAuthTypeAsString()); 34 | 35 | JsonObject curJVar; 36 | 37 | 38 | for (Property curVar : src.getProperties()) { 39 | 40 | curJVar = new JsonObject(); 41 | curJVar.addProperty("key", curVar.getKey()); 42 | curJVar.addProperty("value", curVar.getValue()); 43 | curJVar.addProperty("type", "string"); 44 | vars.add(curJVar); 45 | } 46 | 47 | 48 | jsonAuth.add(src.getAuthTypeAsString(), vars); 49 | return jsonAuth; 50 | 51 | } 52 | }; 53 | -------------------------------------------------------------------------------- /src/main/java/com/postman/collection/adapter/PropertyListSerializer.java: -------------------------------------------------------------------------------- 1 | package com.postman.collection.adapter; 2 | 3 | import com.postman.collection.*; 4 | import com.google.gson.JsonObject; 5 | import com.google.gson.JsonArray; 6 | import com.google.gson.JsonElement; 7 | import com.google.gson.JsonSerializer; 8 | import com.google.gson.JsonSerializationContext; 9 | import java.lang.reflect.Type; 10 | import java.util.Iterator; 11 | import java.util.HashMap; 12 | 13 | 14 | 15 | 16 | public class PropertyListSerializer implements JsonSerializer> { 17 | 18 | /** 19 | * @param src 20 | * @param typeOfSrc 21 | * @param context 22 | * @return JsonElement 23 | */ 24 | public JsonElement serialize(HashMap src, Type typeOfSrc, 25 | JsonSerializationContext context) { 26 | JsonArray varArray = new JsonArray(); 27 | JsonObject varElement; 28 | String curKey; 29 | Property curVar = null; 30 | Iterator keys = src.keySet().iterator(); 31 | while (keys.hasNext()) { 32 | curKey = keys.next(); 33 | varElement = new JsonObject(); 34 | curVar = src.get(curKey); 35 | varElement.addProperty("key", curVar.getKey()); 36 | varElement.addProperty("value", curVar.getValue()); 37 | if (curVar.getDescription() != null) { 38 | varElement.addProperty("description", curVar.getDescription()); 39 | } 40 | if (curVar.getType() != null) { 41 | varElement.addProperty("type", curVar.getType()); 42 | } 43 | varArray.add(varElement); 44 | } 45 | 46 | return varArray; 47 | 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /.github/workflows/build-gh-page.yml: -------------------------------------------------------------------------------- 1 | # Simple workflow for deploying static content to GitHub Pages 2 | name: Build and Deploy javadocs 3 | 4 | on: 5 | # Runs on pushes targeting the default branch 6 | push: 7 | branches: ["main"] 8 | 9 | # Allows you to run this workflow manually from the Actions tab 10 | workflow_dispatch: 11 | 12 | # Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages 13 | permissions: 14 | contents: read 15 | pages: write 16 | id-token: write 17 | 18 | # Allow one concurrent deployment 19 | concurrency: 20 | group: "pages" 21 | cancel-in-progress: true 22 | 23 | jobs: 24 | # Single deploy job since we're just deploying 25 | deploy: 26 | environment: 27 | name: github-pages 28 | url: ${{ steps.deployment.outputs.page_url }} 29 | runs-on: ubuntu-latest 30 | steps: 31 | - name: Set up JDK 18 32 | uses: actions/setup-java@v3 33 | with: 34 | java-version: '18' 35 | distribution: 'temurin' 36 | - name: Checkout 37 | uses: actions/checkout@v3 38 | with: 39 | ref: main 40 | fetch-depth: 0 41 | - name: Update branch and javadocs 42 | run: | 43 | mvn -B clean compile assembly:single 44 | mvn javadoc:javadoc 45 | tar cvf github-pages.tar ./target/site/apidocs 46 | gzip github-pages.tar 47 | 48 | - name: Setup Pages 49 | uses: actions/configure-pages@v2 50 | - name: Upload artifact 51 | uses: actions/upload-pages-artifact@v1 52 | with: 53 | # Upload entire repositorys 54 | path: './target/site/apidocs' 55 | - name: Deploy to GitHub Pages 56 | id: deployment 57 | uses: actions/deploy-pages@v1 58 | -------------------------------------------------------------------------------- /src/main/java/com/postman/collection/adapter/PropertyDeserializer.java: -------------------------------------------------------------------------------- 1 | package com.postman.collection.adapter; 2 | 3 | import com.postman.collection.*; 4 | import com.google.gson.JsonObject; 5 | import com.google.gson.JsonDeserializationContext; 6 | import com.google.gson.JsonParseException; 7 | import com.google.gson.JsonElement; 8 | import com.google.gson.JsonDeserializer; 9 | import java.lang.reflect.Type; 10 | 11 | public class PropertyDeserializer implements JsonDeserializer { 12 | 13 | /** 14 | * 15 | * Custom 17 | * GSON deserializer for the {@link com.postman.collection.RequestAuth} object. 18 | * 19 | * 20 | * @param jElement 21 | * @param typeOfT 22 | * @param context 23 | * @return Property 24 | * @throws JsonParseException 25 | */ 26 | @Override 27 | public Property deserialize(JsonElement jElement, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { 28 | 29 | 30 | Property pvVar = null; 31 | JsonObject jObj = jElement.getAsJsonObject(); 32 | String curVal = ""; 33 | 34 | 35 | curVal = jObj.get("value") == null || jObj.get("value").isJsonNull() ? null : jObj.get("value").getAsString(); 36 | pvVar = new Property(jObj.get("key").getAsString(), curVal); 37 | 38 | if(jObj.get("type") != null) { 39 | pvVar.setType(jObj.get("type").getAsString()); 40 | } 41 | if(jObj.get("description") != null) 42 | { 43 | pvVar.setDescription(jObj.get("description").getAsString()); 44 | } 45 | 46 | return pvVar; 47 | 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/main/resources/com/postman/collection/test-variable-types.postman_collection.json: -------------------------------------------------------------------------------- 1 | { 2 | "info": { 3 | "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json", 4 | "name": "TEST-testAddVariables", 5 | "description": "TEST-testAddVariablesgenerated by Test: testAddVariables" 6 | }, 7 | "item": [], 8 | "variable": [ 9 | { 10 | "key": "String", 11 | "value": "value 1", 12 | "type":"string" 13 | }, 14 | { 15 | "key": "boolean", 16 | "value": true, 17 | "type":"boolean" 18 | }, 19 | { 20 | "key": "int", 21 | "value": 22, 22 | "type":"number" 23 | }, 24 | { 25 | "key": "int", 26 | "value": 22, 27 | "type":"any" 28 | }, 29 | { 30 | "key": "string with variable", 31 | "value": "{{stringvar}}", 32 | "type":"string" 33 | }, 34 | { 35 | "key": "boolean with variable", 36 | "value": "{{boolvar}}", 37 | "type":"boolean" 38 | }, 39 | { 40 | "key": "number with variable", 41 | "value": "{{numbervar}}", 42 | "type":"number" 43 | }, 44 | { 45 | "key": "any with variable", 46 | "value": "{{anyvar}}", 47 | "type":"any" 48 | }, 49 | { 50 | "key": "string with no value", 51 | "type":"string" 52 | }, 53 | { 54 | "key": "boolean with no value", 55 | "type":"boolean" 56 | }, 57 | { 58 | "key": "number with no value", 59 | "type":"number" 60 | }, 61 | { 62 | "key": "any with no value", 63 | "type":"any" 64 | } 65 | 66 | 67 | 68 | 69 | 70 | ] 71 | } -------------------------------------------------------------------------------- /.mvn/jgitver.config.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | CONFIGURABLE 6 | NEAREST 7 | true 8 | false 9 | false 10 | true 11 | false 12 | 8 13 | 14 | main 15 | ([0-9].[0-9].[0-9]) 17 | 18 | 19 | .mvn 20 | 21 | 22 | false 23 | 38 | 39 | -------------------------------------------------------------------------------- /src/main/java/com/postman/collection/adapter/ItemGroupDeserializer.java: -------------------------------------------------------------------------------- 1 | package com.postman.collection.adapter; 2 | 3 | import com.postman.collection.*; 4 | import com.google.gson.JsonObject; 5 | import com.google.gson.JsonDeserializationContext; 6 | import com.google.gson.JsonParseException; 7 | import com.google.gson.JsonElement; 8 | import com.google.gson.JsonDeserializer; 9 | import java.lang.reflect.Type; 10 | import java.util.ArrayList; 11 | import com.google.gson.reflect.TypeToken; 12 | /** 13 | * 14 | * 15 | * Deserializes ItemGroup objects, the item propertyList in a collection 16 | * 17 | * 18 | */ 19 | public class ItemGroupDeserializer implements JsonDeserializer { 20 | 21 | /** 22 | * 23 | * Deserialize a {@link com.postman.collection.ItemGroup} from the item propertyList 24 | * 25 | * 26 | * @param jElement The JSON element passed in by Gson 27 | * @param typeOfT The type for the adapter, {@link com.postman.collection.RequestAuth} 28 | * @param context Deserialization context 29 | * @return ItemGroup The assembed {@link com.postman.collection.ItemGroup} 30 | * @throws JsonParseException IF there are errors in the JSON element 31 | */ 32 | @Override 33 | public ItemGroup deserialize(JsonElement jElement, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { 34 | JsonObject jObject = jElement.getAsJsonObject(); 35 | Type typeItem = new TypeToken>(){}.getType(); 36 | Folder newFolder = null; 37 | newFolder = new Folder(jObject.getAsJsonPrimitive("name").getAsString()); 38 | if(jObject.get("description") != null) { 39 | newFolder.setDescription(jObject.getAsJsonPrimitive("description").getAsString()); 40 | } 41 | if(jObject.get("item") == null) { 42 | return newFolder; 43 | } 44 | ArrayList items = context.deserialize(jObject.getAsJsonArray("item"), typeItem); 45 | newFolder.setItems(items); 46 | 47 | return newFolder; 48 | 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/main/java/com/postman/collection/adapter/PropertySerializer.java: -------------------------------------------------------------------------------- 1 | package com.postman.collection.adapter; 2 | 3 | import com.postman.collection.*; 4 | import com.google.gson.JsonObject; 5 | import com.google.gson.JsonElement; 6 | import com.google.gson.JsonSerializer; 7 | 8 | import com.google.gson.JsonSerializationContext; 9 | 10 | 11 | import java.lang.reflect.Type; 12 | 13 | public class PropertySerializer implements JsonSerializer { 14 | 15 | 16 | /** 17 | * @param src 18 | * @param typeOfSrc 19 | * @param context 20 | * @return JsonElement 21 | */ 22 | @Override 23 | public JsonElement serialize(Property src, Type typeOfSrc, JsonSerializationContext context) { 24 | 25 | JsonObject jsonMap = new JsonObject(); 26 | jsonMap.addProperty("key", src.getKey()); 27 | String strKey = "value"; 28 | if(src.getKey() == null && src.getValue() == null) { 29 | return null; 30 | } 31 | if(src.getType() != null && src.getType().equals("boolean") && src.getValue() != null) { 32 | switch (src.getValue()) { 33 | case "true": { 34 | jsonMap.addProperty(strKey,true); 35 | break; 36 | } 37 | case "false": { 38 | jsonMap.addProperty(strKey,false); 39 | break; 40 | } 41 | default: { 42 | jsonMap.addProperty(strKey, src.getValue()); 43 | break; 44 | } 45 | 46 | 47 | } 48 | 49 | } 50 | else { 51 | if(src.getValue() == null) { 52 | jsonMap.addProperty(strKey, ""); 53 | } 54 | jsonMap.addProperty(strKey, src.getValue()); 55 | } 56 | if(src.getType() != null) { 57 | jsonMap.addProperty("type", src.getType()); 58 | } 59 | if(src.getDescription() != null) { 60 | jsonMap.addProperty("description", src.getDescription()); 61 | } 62 | 63 | return jsonMap; 64 | } 65 | 66 | } 67 | -------------------------------------------------------------------------------- /src/main/java/com/postman/collection/adapter/ItemDeserializer.java: -------------------------------------------------------------------------------- 1 | package com.postman.collection.adapter; 2 | 3 | import com.postman.collection.*; 4 | import com.google.gson.JsonObject; 5 | import com.google.gson.JsonDeserializationContext; 6 | import com.google.gson.JsonParseException; 7 | import com.google.gson.JsonElement; 8 | import com.google.gson.JsonDeserializer; 9 | import java.lang.reflect.Type; 10 | import java.util.ArrayList; 11 | import com.google.gson.reflect.TypeToken; 12 | 13 | 14 | /** 15 | * 16 | * 17 | * Custom deserializer for writing out the Item class, the item propertyList 18 | * 19 | * 20 | */ 21 | 22 | 23 | 24 | public class ItemDeserializer implements JsonDeserializer { 25 | 26 | /** 27 | * 28 | * Deserialize a {@link com.postman.collection.Item } 29 | * 30 | * 31 | * @param jElement The JSON element passed in by Gson 32 | * @param typeOfT The type for the adapter, {@link com.postman.collection.RequestAuth} 33 | * @param context Deserialization context 34 | * @return ItemAuth The assembed {@link com.postman.collection.Item} object 35 | * @throws JsonParseException IF there are errors in the JSON element 36 | */ 37 | @Override 38 | public Item deserialize(JsonElement jElement, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { 39 | JsonObject jObject = jElement.getAsJsonObject(); 40 | Request newRequest = null; 41 | 42 | if(jObject.get("request") == null) { 43 | return context.deserialize(jElement.getAsJsonObject(), ItemGroup.class); 44 | 45 | } 46 | Type typeEvent = new TypeToken>(){}.getType(); 47 | Type typeResponse = new TypeToken>(){}.getType(); 48 | newRequest = new Request(jObject.get("name").getAsString()); 49 | if(jObject.get("description") != null) { 50 | newRequest.setDescription(jObject.get("description").getAsString()); 51 | } 52 | 53 | RequestBody req = context.deserialize(jObject.getAsJsonObject("request"),RequestBody.class); 54 | newRequest.setRequestBody(req); 55 | ArrayList events = context.deserialize(jObject.getAsJsonArray("event"), typeEvent); 56 | newRequest.setEvents(events); 57 | ArrayList responses = context.deserialize(jObject.getAsJsonArray("response"), typeResponse); 58 | newRequest.setResponses(responses); 59 | return newRequest; 60 | 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/main/resources/com/postman/collection/example-url.postman_collection.json: -------------------------------------------------------------------------------- 1 | { 2 | "info": { 3 | "_postman_id": "974f2079-dce3-4418-8055-1c33c51ac7d5", 4 | "name": "Test URL", 5 | "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json", 6 | "_exporter_id": "23889826" 7 | }, 8 | "item": [ 9 | { 10 | "name": "URL 1", 11 | "request": { 12 | "method": "GET", 13 | "header": [], 14 | "url": { 15 | "raw": "http://foo.com/bar/bat.json", 16 | "protocol": "http", 17 | "host": [ 18 | "foo", 19 | "com" 20 | ], 21 | "path": [ 22 | "bar", 23 | "bat.json" 24 | ] 25 | } 26 | }, 27 | "response": [] 28 | }, 29 | { 30 | "name": "URL 2", 31 | "request": { 32 | "method": "GET", 33 | "header": [], 34 | "url": { 35 | "raw": "//foo.com/bar/bat.json", 36 | "path": [ 37 | "", 38 | "foo.com", 39 | "bar", 40 | "bat.json" 41 | ] 42 | } 43 | }, 44 | "response": [] 45 | }, 46 | { 47 | "name": "URL 3", 48 | "request": { 49 | "method": "GET", 50 | "header": [], 51 | "url": { 52 | "raw": "{{baseUrl}}/foo.com/bar/bat.json", 53 | "host": [ 54 | "{{baseUrl}}" 55 | ], 56 | "path": [ 57 | "foo.com", 58 | "bar", 59 | "bat.json" 60 | ] 61 | } 62 | }, 63 | "response": [] 64 | }, 65 | { 66 | "name": "URL 4", 67 | "request": { 68 | "method": "GET", 69 | "header": [], 70 | "url": { 71 | "raw": "http://foo.com/bar/bat.json?foo=1&bar=2", 72 | "protocol": "http", 73 | "host": [ 74 | "foo", 75 | "com" 76 | ], 77 | "path": [ 78 | "bar", 79 | "bat.json" 80 | ], 81 | "query": [ 82 | { 83 | "key": "foo", 84 | "value": "1" 85 | }, 86 | { 87 | "key": "bar", 88 | "value": "2" 89 | } 90 | ] 91 | } 92 | }, 93 | "response": [] 94 | }, 95 | { 96 | "name": "URL 5", 97 | "request": { 98 | "method": "GET", 99 | "header": [], 100 | "url": { 101 | "raw": "http://foo.com/bar/bat.json?foo=1&bar=", 102 | "protocol": "http", 103 | "host": [ 104 | "foo", 105 | "com" 106 | ], 107 | "path": [ 108 | "bar", 109 | "bat.json" 110 | ], 111 | "query": [ 112 | { 113 | "key": "foo", 114 | "value": "1" 115 | }, 116 | { 117 | "key": "bar", 118 | "value": "" 119 | } 120 | ] 121 | } 122 | }, 123 | "response": [] 124 | } 125 | ] 126 | } -------------------------------------------------------------------------------- /src/main/java/com/postman/collection/adapter/AuthDeserializer.java: -------------------------------------------------------------------------------- 1 | package com.postman.collection.adapter; 2 | 3 | import com.postman.collection.*; 4 | import com.google.gson.JsonObject; 5 | import com.google.gson.JsonArray; 6 | import com.google.gson.JsonDeserializationContext; 7 | import com.google.gson.JsonParseException; 8 | import com.google.gson.JsonElement; 9 | import com.google.gson.JsonDeserializer; 10 | import java.lang.reflect.Type; 11 | /** 12 | * 13 | * 14 | * 15 | * 16 | * Custom deserializer for the auth property object. 17 | * 18 | * 19 | * 20 | */ 21 | public class AuthDeserializer implements JsonDeserializer { 22 | 23 | /** 24 | * 25 | * Custom 27 | * GSON deserializer for the {@link com.postman.collection.RequestAuth} object. 28 | * 29 | * 30 | * @param jElement The JSON element passed in by Gson 31 | * @param typeOfT The type for the adapter, {@link com.postman.collection.RequestAuth} 32 | * @param context Deserialization context 33 | * @return {@link com.postman.collection.RequestAuth} The assembed {@link com.postman.collection.RequestAuth} object 34 | * @throws JsonParseException IF there are errors in the JSON element 35 | */ 36 | @Override 37 | public RequestAuth deserialize(JsonElement jElement, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { 38 | JsonObject jObject = jElement.getAsJsonObject(); 39 | JsonObject curVar; 40 | String type = jObject.get("type").getAsString(); 41 | JsonArray vars = jObject.get(type).getAsJsonArray(); 42 | Property pvVar; 43 | RequestAuth auth = new RequestAuth(jObject.get("type").getAsString()); 44 | String curKey; 45 | String curVal; 46 | String curType; 47 | for (int i = 0; i < vars.size(); i++) { 48 | curVar = vars.get(i).getAsJsonObject(); 49 | curVar.get("key"); 50 | 51 | curKey = curVar.get("key") == null ? null : curVar.get("key").getAsString(); 52 | curVal = curVar.get("value") == null ? null : curVar.get("value").getAsString(); 53 | curType = curVar.get("type") == null ? null : curVar.get("type").getAsString(); 54 | 55 | pvVar = new Property(curKey, curVal, null,curType); 56 | try { 57 | auth.addProperty(pvVar); 58 | } catch (Exception e) { 59 | e.printStackTrace(); 60 | } 61 | 62 | } 63 | 64 | return auth; 65 | 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /.github/workflows/codeql.yml: -------------------------------------------------------------------------------- 1 | # For most projects, this workflow file will not need changing; you simply need 2 | # to commit it to your repository. 3 | # 4 | # You may wish to alter this file to override the set of languages analyzed, 5 | # or to provide custom queries or build logic. 6 | # 7 | # ******** NOTE ******** 8 | # We have attempted to detect the languages in your repository. Please check 9 | # the `language` matrix defined below to confirm you have the correct set of 10 | # supported CodeQL languages. 11 | # 12 | name: "CodeQL" 13 | 14 | on: 15 | push: 16 | branches: [ "main" ] 17 | pull_request: 18 | # The branches below must be a subset of the branches above 19 | branches: [ "main" ] 20 | schedule: 21 | - cron: '35 3 * * 1' 22 | 23 | jobs: 24 | analyze: 25 | name: Analyze 26 | runs-on: ubuntu-latest 27 | permissions: 28 | actions: read 29 | contents: read 30 | security-events: write 31 | 32 | strategy: 33 | fail-fast: false 34 | matrix: 35 | language: [ 'java' ] 36 | # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ] 37 | # Use only 'java' to analyze code written in Java, Kotlin or both 38 | # Use only 'javascript' to analyze code written in JavaScript, TypeScript or both 39 | # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support 40 | 41 | steps: 42 | - name: Checkout repository 43 | uses: actions/checkout@v3 44 | - name: Set up JDK 18 45 | uses: actions/setup-java@v3 46 | with: 47 | java-version: '18' 48 | distribution: 'temurin' 49 | # cache: maven 50 | 51 | # Initializes the CodeQL tools for scanning. 52 | - name: Initialize CodeQL 53 | uses: github/codeql-action/init@v2 54 | with: 55 | languages: ${{ matrix.language }} 56 | # If you wish to specify custom queries, you can do so here or in a config file. 57 | # By default, queries listed here will override any specified in a config file. 58 | # Prefix the list here with "+" to use these queries and those in the config file. 59 | 60 | # Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs 61 | # queries: security-extended,security-and-quality 62 | 63 | 64 | # Autobuild attempts to build any compiled languages (C/C++, C#, Go, or Java). 65 | # If this step fails, then you should remove it and run the build manually (see below) 66 | - name: Autobuild 67 | uses: github/codeql-action/autobuild@v2 68 | 69 | # ℹ️ Command-line programs to run using the OS shell. 70 | # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun 71 | 72 | # If the Autobuild fails above, remove it and uncomment the following three lines. 73 | # modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance. 74 | 75 | # - run: | 76 | # echo "Run, Build Application using script" 77 | # ./location_of_script_within_repo/buildscript.sh 78 | 79 | - name: Perform CodeQL Analysis 80 | uses: github/codeql-action/analyze@v2 81 | with: 82 | category: "/language:${{matrix.language}}" 83 | -------------------------------------------------------------------------------- /src/main/java/com/postman/collection/Request.java: -------------------------------------------------------------------------------- 1 | package com.postman.collection; 2 | import java.util.ArrayList; 3 | 4 | /** 5 | * 6 | * 7 | * Encapsulates a Postman collection request. 8 | * 9 | *

Postman SDK analog: Request 10 | * 11 | * 12 | * 13 | */ 14 | 15 | 16 | public class Request extends Item { 17 | private RequestBody request = null; 18 | private ArrayList response = null; 19 | 20 | 21 | /** 22 | * 23 | * Create a request with the specific name and pre-populated {@link com.postman.collection.RequestBody}. 24 | * @param req A {@link com.postman.collection.RequestBody} instance. 25 | * @param name The name of the request. 26 | */ 27 | 28 | 29 | public Request(RequestBody req, String name) { 30 | super(name); 31 | this.request = req; 32 | req.setParent(this); 33 | } 34 | 35 | /** 36 | * 37 | * Create an empety Request with the specific name 38 | * 39 | * @param name The name of the request. 40 | */ 41 | public Request(String name) { 42 | super(name); 43 | } 44 | 45 | 46 | 47 | /** 48 | * 49 | * Return the object containing the values in the request property, or null if this item does not contain a request (e.g., is a folder); 50 | * 51 | * 52 | * @return RequestBody The request, or null if no request is defined. 53 | */ 54 | public RequestBody getRequestBody() { 55 | return request; 56 | } 57 | 58 | 59 | /** 60 | * 61 | * Set the object containing the values in the request property 62 | * 63 | * @param request 64 | */ 65 | public void setRequestBody(RequestBody request) { 66 | this.request = request; 67 | } 68 | 69 | 70 | /** 71 | * 72 | * Return an ArrayList<Response> containing the values in the response property array, or null if none are defined. 73 | * 74 | * 75 | * @return ArrayList<{@link com.postman.collection.Response Response}> The responses, or null if none are defined. 76 | */ 77 | public ArrayList getResponses() { 78 | return response; 79 | } 80 | 81 | 82 | /** 83 | * 84 | * Set the ArrayList<Response> containing the values in the response property array. Passing null to this method removes the response array 85 | * 86 | * @param response 87 | */ 88 | public void setResponses(ArrayList response) { 89 | this.response = response; 90 | } 91 | 92 | /** 93 | * 94 | * Add a Response object to the response array 95 | * 96 | * @param resp The new response 97 | * 98 | */ 99 | public void addResponse(Response resp) { 100 | if (this.response == null) { 101 | this.response = new ArrayList(); 102 | } 103 | this.response.add(resp); 104 | } 105 | /** 106 | * 107 | * Add a response object to the request contained by this collection specified by requestKey 108 | * 109 | * 110 | * @param requestKey Key identifying the request to add the response to 111 | * @param response New response to add to the request 112 | * @throws InvalidCollectionActionException If the specifyed request is not contained by this collection 113 | */ 114 | public void addResponse(String requestKey, Response response) throws InvalidCollectionActionException { 115 | RequestBody req = this.getRequestBody(); 116 | if(req == null) { 117 | throw new InvalidCollectionActionException("Request with key [" + requestKey + "] not found"); 118 | } 119 | this.addResponse(response); 120 | 121 | } 122 | 123 | 124 | } 125 | -------------------------------------------------------------------------------- /src/main/java/com/postman/collection/Cookie.java: -------------------------------------------------------------------------------- 1 | package com.postman.collection; 2 | 3 | /** 4 | * 5 | * Encapsulates the cookie property of a Postman Collection. 6 | * 7 | *

Postman SDK analog: Cookie.

8 | * 9 | *

NOTE: Provided for serialization/de-serialization only, doesn't provide any method capability.

10 | * 11 | * 12 | * 13 | * 14 | */ 15 | 16 | public class Cookie extends CollectionElement { 17 | private String domain = ""; 18 | private String expires = ""; 19 | private String maxAge = ""; 20 | private boolean hostOnly; 21 | private boolean httpOnly; 22 | private String name = ""; 23 | private String path = ""; 24 | private boolean secure; 25 | private boolean session; 26 | private String value = ""; 27 | private PropertyList extensions; 28 | 29 | public Cookie() { 30 | super(); 31 | } 32 | 33 | 34 | /** 35 | * @return String 36 | */ 37 | public String getDomain() { 38 | return domain; 39 | } 40 | 41 | 42 | /** 43 | * @param domain 44 | */ 45 | public void setDomain(String domain) { 46 | this.domain = domain; 47 | } 48 | 49 | 50 | /** 51 | * @return String 52 | */ 53 | public String getExpires() { 54 | return expires; 55 | } 56 | 57 | 58 | /** 59 | * @param expires 60 | */ 61 | public void setExpires(String expires) { 62 | this.expires = expires; 63 | } 64 | 65 | 66 | /** 67 | * @return String 68 | */ 69 | public String getMaxAge() { 70 | return maxAge; 71 | } 72 | 73 | 74 | /** 75 | * @param maxAge 76 | */ 77 | public void setMaxAge(String maxAge) { 78 | this.maxAge = maxAge; 79 | } 80 | 81 | 82 | /** 83 | * @return boolean 84 | */ 85 | public boolean isHostOnly() { 86 | return hostOnly; 87 | } 88 | 89 | 90 | /** 91 | * @param hostOnly 92 | */ 93 | public void setHostOnly(boolean hostOnly) { 94 | this.hostOnly = hostOnly; 95 | } 96 | 97 | 98 | /** 99 | * @return boolean 100 | */ 101 | public boolean isHttpOnly() { 102 | return httpOnly; 103 | } 104 | 105 | 106 | /** 107 | * @param httpOnly 108 | */ 109 | public void setHttpOnly(boolean httpOnly) { 110 | this.httpOnly = httpOnly; 111 | } 112 | 113 | 114 | /** 115 | * @return String 116 | */ 117 | public String getName() { 118 | return name; 119 | } 120 | 121 | 122 | /** 123 | * @param name 124 | */ 125 | public void setName(String name) { 126 | this.name = name; 127 | } 128 | 129 | 130 | /** 131 | * @return String 132 | */ 133 | public String getPath() { 134 | return path; 135 | } 136 | 137 | 138 | /** 139 | * @param path 140 | */ 141 | public void setPath(String path) { 142 | this.path = path; 143 | } 144 | 145 | 146 | /** 147 | * @return boolean 148 | */ 149 | public boolean isSecure() { 150 | return secure; 151 | } 152 | 153 | 154 | /** 155 | * @param secure 156 | */ 157 | public void setSecure(boolean secure) { 158 | this.secure = secure; 159 | } 160 | 161 | 162 | /** 163 | * @return boolean 164 | */ 165 | public boolean isSession() { 166 | return session; 167 | } 168 | 169 | 170 | /** 171 | * @param session 172 | */ 173 | public void setSession(boolean session) { 174 | this.session = session; 175 | } 176 | 177 | 178 | /** 179 | * @return String 180 | */ 181 | public String getValue() { 182 | return value; 183 | } 184 | 185 | 186 | /** 187 | * @param value 188 | */ 189 | public void setValue(String value) { 190 | this.value = value; 191 | } 192 | 193 | 194 | /** 195 | * @return ArrayList<{@link com.postman.collection.Property Property}> 196 | */ 197 | public PropertyList getExtensions() { 198 | return extensions; 199 | } 200 | 201 | 202 | /** 203 | * @param extensions 204 | */ 205 | public void setExtensions(PropertyList extensions) { 206 | this.extensions = extensions; 207 | } 208 | 209 | 210 | /** 211 | * @return String 212 | */ 213 | @Override 214 | public String getKey() { 215 | 216 | return getName(); 217 | } 218 | 219 | } 220 | -------------------------------------------------------------------------------- /src/main/java/com/postman/collection/Property.java: -------------------------------------------------------------------------------- 1 | package com.postman.collection; 2 | /** 3 | * 4 | * 5 | * Postman SDK analog: Not directly related, but probably close to PropertyBase 6 | * 7 | * 8 | *

Utility class to store key-value pairs with additional, optional description and type properties

9 | * 10 | * 11 | */ 12 | public class Property extends CollectionElement { 13 | private String key = ""; 14 | private String value = ""; 15 | private String description; 16 | private String type = "string"; 17 | 18 | 19 | /** 20 | * 21 | * Returns the Postman token for a variable, eg. the key surrounded by double curly braces {{}} 22 | * 23 | * 24 | * @return String The postman token 25 | */ 26 | public String getToken() { 27 | return "{{" + key + "}}"; 28 | } 29 | 30 | 31 | /** 32 | * 33 | * Constructs a Property with the specified properties. The type property is set to null 34 | * 35 | * @param key Value for the key property. NOTE: If a null key is provided it will be transformed to an empty string (""); 36 | * @param value Value for the value property 37 | * @param description Value for the description proptery 38 | */ 39 | 40 | public Property(String key, String value, String description) { 41 | this(key, value, description, null); 42 | 43 | } 44 | /** 45 | * 46 | * Constructs a Property with all specified properties. 47 | * 48 | * @param key Value for the key property. NOTE: If a null key is provided it will be transformed to an empty string (""); 49 | * @param value Value for the value property 50 | * @param description Value for the description property 51 | * @param type Value for the type property 52 | */ 53 | public Property(String key, String value, String description, String type) { 54 | this.key = key; 55 | this.value = value; 56 | this.description = description; 57 | this.type = type; 58 | } 59 | 60 | /** 61 | * 62 | * Constructs a Property with with just key and value properties 63 | * 64 | * @param key Value for the key property. NOTE: If a null key is provided it will be transformed to an empty string (""); 65 | * @param value Value for the value property 66 | */ 67 | 68 | public Property(String key, String value) { 69 | this(key, value, null, null); 70 | } 71 | 72 | 73 | /** 74 | * 75 | * returns the value of the key property 76 | * 77 | * @return String 78 | */ 79 | @Override 80 | public String getKey() { 81 | return key; 82 | } 83 | 84 | 85 | /** 86 | * 87 | * Sets the description property 88 | * 89 | * 90 | * @param desc 91 | */ 92 | public void setDescription(String desc) { 93 | this.description = desc; 94 | } 95 | 96 | 97 | /** 98 | * 99 | * Returns the description property, or null if it is not set 100 | * 101 | * @return String 102 | */ 103 | public String getDescription() { 104 | return this.description; 105 | } 106 | 107 | 108 | /** 109 | * 110 | * Sets the key value for this property 111 | * 112 | * @param key 113 | */ 114 | public void setKey(String key) { 115 | this.key = key; 116 | } 117 | 118 | 119 | /** 120 | * 121 | * Sets the value property for this property 122 | * @return String 123 | */ 124 | public String getValue() { 125 | return value; 126 | } 127 | 128 | 129 | /** 130 | * 131 | * Sets the value property for this variable 132 | * 133 | * @param value The value 134 | */ 135 | public void setValue(String value) { 136 | this.value = value; 137 | } 138 | 139 | 140 | /** 141 | * 142 | * Returns the type property for this variable 143 | * 144 | * @return String the type 145 | */ 146 | public String getType() { 147 | return this.type; 148 | } 149 | 150 | 151 | /** 152 | * 153 | * Sets the type property for this variable 154 | * 155 | * @param type The type, e.g., "string" or "boolean" 156 | */ 157 | public void setType(String type) { 158 | this.type = type; 159 | } 160 | 161 | 162 | /** 163 | * @param obj 164 | * @return boolean 165 | */ 166 | @Override 167 | public boolean equals(Object obj) { 168 | if(! (obj instanceof Property)) { 169 | return false; 170 | } 171 | Property varComp = (Property)obj; 172 | return (this.getKey().equals(varComp.getKey()) 173 | && (this.getValue() + "").equals(varComp.getValue() + "") 174 | && (this.getType() + "").equals(varComp.getType() + "") 175 | && (this.getDescription() + "").equals(varComp.getDescription() + "")); 176 | } 177 | 178 | } 179 | -------------------------------------------------------------------------------- /src/main/resources/com/postman/collection/example-weather.postman_collection.json: -------------------------------------------------------------------------------- 1 | { 2 | "info": { 3 | "_postman_id": "4cc9f91e-5c5d-4dd3-a081-e0ecbe2a9fea", 4 | "name": "Weather", 5 | "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json", 6 | "_exporter_id": "23889826" 7 | }, 8 | "item": [ 9 | { 10 | "name": "Call for San Francisco", 11 | "event": [ 12 | { 13 | "listen": "test", 14 | "script": { 15 | "exec": [ 16 | "if (pm.response.code === 200) {", 17 | " console.log(\"Received temperature for San Francisco..\");", 18 | " const responseJson = pm.response.json();", 19 | " var tempInK = responseJson['main']['temp'];", 20 | " var tempInF = 1.8*(tempInK-273) + 32;", 21 | " pm.collectionVariables.set(\"SanFranciscoTemp\", tempInF.toFixed(2));", 22 | " if (tempInF > 60) {", 23 | " console.log(\"temperature greater than 60F, call for Bangalore, India\");", 24 | " pm.collectionVariables.set(\"ResultCity\", \"BLR\");", 25 | " pm.collectionVariables.set(\"ResultLat\", pm.collectionVariables.get(\"BangaloreLat\"));", 26 | " pm.collectionVariables.set(\"ResultLog\", pm.collectionVariables.get(\"BangaloreLog\"));", 27 | " } else {", 28 | " console.log(\"temperature less than / equal to 60F, call for London, UK\");", 29 | " pm.collectionVariables.set(\"ResultCity\", \"LON\");", 30 | " pm.collectionVariables.set(\"ResultLat\", pm.collectionVariables.get(\"LondonLat\"));", 31 | " pm.collectionVariables.set(\"ResultLog\", pm.collectionVariables.get(\"LondonLog\"));", 32 | " }", 33 | "}" 34 | ], 35 | "type": "text/javascript" 36 | } 37 | } 38 | ], 39 | "request": { 40 | "method": "GET", 41 | "header": [], 42 | "url": { 43 | "raw": "https://api.openweathermap.org/data/2.5/weather?lat={{SanFranciscoLat}}&lon={{SanFranciscoLon}}&appid={{API_KEY}}", 44 | "protocol": "https", 45 | "host": [ 46 | "api", 47 | "openweathermap", 48 | "org" 49 | ], 50 | "path": [ 51 | "data", 52 | "2.5", 53 | "weather" 54 | ], 55 | "query": [ 56 | { 57 | "key": "lat", 58 | "value": "{{SanFranciscoLat}}" 59 | }, 60 | { 61 | "key": "lon", 62 | "value": "{{SanFranciscoLon}}" 63 | }, 64 | { 65 | "key": "appid", 66 | "value": "{{API_KEY}}" 67 | } 68 | ] 69 | } 70 | }, 71 | "response": [] 72 | }, 73 | { 74 | "name": "Result City Temp", 75 | "event": [ 76 | { 77 | "listen": "test", 78 | "script": { 79 | "exec": [ 80 | "if (pm.response.code === 200) {", 81 | " console.log(\"Received temperature for San Francisco..\");", 82 | " const responseJson = pm.response.json();", 83 | " var tempInK = responseJson['main']['temp'];", 84 | " var tempInF = 1.8*(tempInK-273) + 32;", 85 | " pm.collectionVariables.set(\"ResultCityTemp\", tempInF.toFixed(2));", 86 | "}" 87 | ], 88 | "type": "text/javascript" 89 | } 90 | } 91 | ], 92 | "request": { 93 | "method": "GET", 94 | "header": [], 95 | "url": { 96 | "raw": "https://api.openweathermap.org/data/2.5/weather?lat={{ResultLat}}&lon={{ResultLog}}&appid={{API_KEY}}", 97 | "protocol": "https", 98 | "host": [ 99 | "api", 100 | "openweathermap", 101 | "org" 102 | ], 103 | "path": [ 104 | "data", 105 | "2.5", 106 | "weather" 107 | ], 108 | "query": [ 109 | { 110 | "key": "lat", 111 | "value": "{{ResultLat}}" 112 | }, 113 | { 114 | "key": "lon", 115 | "value": "{{ResultLog}}" 116 | }, 117 | { 118 | "key": "appid", 119 | "value": "{{API_KEY}}" 120 | } 121 | ] 122 | } 123 | }, 124 | "response": [] 125 | } 126 | ], 127 | "event": [ 128 | { 129 | "listen": "prerequest", 130 | "script": { 131 | "type": "text/javascript", 132 | "exec": [ 133 | "//This is WEATHERs pre request script" 134 | ] 135 | } 136 | }, 137 | { 138 | "listen": "test", 139 | "script": { 140 | "type": "text/javascript", 141 | "exec": [ 142 | "//This is WEATHERs pre request script" 143 | ] 144 | } 145 | } 146 | ], 147 | "variable": [ 148 | { 149 | "key": "API_KEY", 150 | "value": "efd333ca516eb1af9c6f0b02b39e9bda", 151 | "type": "string" 152 | }, 153 | { 154 | "key": "SanFranciscoLat", 155 | "value": "37.7749", 156 | "type": "string" 157 | }, 158 | { 159 | "key": "SanFranciscoLon", 160 | "value": "122.4194", 161 | "type": "string" 162 | }, 163 | { 164 | "key": "BangaloreLat", 165 | "value": "12.9716", 166 | "type": "string" 167 | }, 168 | { 169 | "key": "BangaloreLog", 170 | "value": "77.5946", 171 | "type": "string" 172 | }, 173 | { 174 | "key": "LondonLat", 175 | "value": "51.5072", 176 | "type": "string" 177 | }, 178 | { 179 | "key": "LondonLog", 180 | "value": "0.1276", 181 | "type": "string" 182 | }, 183 | { 184 | "key": "ResultLat", 185 | "value": "", 186 | "type": "string" 187 | }, 188 | { 189 | "key": "ResultLog", 190 | "value": "", 191 | "type": "string" 192 | }, 193 | { 194 | "key": "ResultCity", 195 | "value": "", 196 | "type": "string" 197 | }, 198 | { 199 | "key": "ResultCityTemp", 200 | "value": "", 201 | "type": "string" 202 | }, 203 | { 204 | "key": "SanFranciscoTemp", 205 | "value": "", 206 | "type": "string" 207 | } 208 | ] 209 | } -------------------------------------------------------------------------------- /src/main/java/com/postman/collection/PropertyList.java: -------------------------------------------------------------------------------- 1 | package com.postman.collection; 2 | 3 | import java.util.ArrayList; 4 | 5 | 6 | 7 | /** 8 | * 9 | *

Postman SDK analog: PropertyList

10 | * 11 | * 12 | *

Extends ArrayList with Map like capabilities, including: 13 | *

    14 | *
  • Support for retrieving by variable key which is always {@link com.postman.collection.Property#getKey()} 15 | *
  • Support for retrieving by index 16 | *
  • Support for adding by index 17 | *
  • Duplicate keys are not allowed 18 | *
  • Null keys are allowed. 19 | *
  • Contains returns results based on {@link com.postman.collection.Property#equals(Object)} 20 | *
  • Set will set the value of the variable in this ListMap if it exists, otherwise it will set the value of the specified index 21 | *
  • the add method returns false if the specified key already exists in the collection and does not change the collection 22 | *
23 | * 24 | * 25 | * 26 | * 27 | * 28 | * 29 | */ 30 | public class PropertyList extends ArrayList 31 | { 32 | /** 33 | * Returns a PropertyList populated with the contents of vars 34 | * @param vars ArrayList<Property> of variables 35 | */ 36 | 37 | public PropertyList(ArrayList vars) { 38 | super(vars); 39 | } 40 | 41 | 42 | /** 43 | * 44 | * Returns an empty PropertyList 45 | */ 46 | public PropertyList() { 47 | super(new ArrayList()); 48 | } 49 | 50 | 51 | /** 52 | * 53 | * 54 | * Get a variable whose key matches key, or null if it is not present 55 | * 56 | * @param key 57 | * @return Property 58 | */ 59 | public Property get(String key) { 60 | 61 | 62 | for(Property curVar : this) { 63 | String curVarKey; 64 | if(key == null) { 65 | curVarKey = curVar.getKey(); 66 | if(curVarKey == null) { 67 | return curVar; 68 | } 69 | } 70 | else if (curVar.getKey() != null && curVar.getKey().equals(key)) 71 | return curVar; 72 | } 73 | 74 | 75 | return null; 76 | } 77 | 78 | 79 | /** 80 | * @param key 81 | * @return boolean 82 | */ 83 | public boolean containsKey(String key) { 84 | return(this.get(key) != null); 85 | } 86 | 87 | 88 | /** 89 | * @param index 90 | * @return Property 91 | */ 92 | @Override 93 | public Property get(int index) { 94 | return super.get(index); 95 | } 96 | 97 | 98 | /** 99 | * @param compare 100 | * @return boolean 101 | */ 102 | public boolean contains(Property compare) { 103 | for(Property curVar : this) { 104 | if(curVar.equals(compare)) { 105 | return true; 106 | } 107 | } 108 | return false; 109 | } 110 | 111 | 112 | /** 113 | * @param pvVar 114 | * @return int 115 | */ 116 | 117 | public int indexOf(Property pvVar) { 118 | for(int i = 0; i < this.size(); i++) 119 | { 120 | if(this.get(i).getKey().equals(pvVar.getKey())){ 121 | return i; 122 | } 123 | } 124 | return -1; 125 | } 126 | 127 | 128 | /** 129 | * @param pvVar 130 | * @return boolean 131 | */ 132 | @Override 133 | public boolean add(Property pvVar) { 134 | 135 | if(pvVar == null || (pvVar.getKey() == null && pvVar.getValue() == null)) { 136 | throw new NullPointerException("Key and Value properties are both null"); 137 | } 138 | if(this.containsKey(pvVar.getKey())) { 139 | this.set(pvVar); 140 | return true; 141 | } 142 | else { 143 | super.add(pvVar); 144 | return true; 145 | } 146 | } 147 | 148 | 149 | /** 150 | * @param vars 151 | * @return boolean 152 | */ 153 | public boolean addAll(PropertyList vars) { 154 | return this.addAll(this.size(), vars); 155 | } 156 | 157 | 158 | /** 159 | * @param index 160 | * @param vars 161 | * @return boolean 162 | */ 163 | public boolean addAll(int index, PropertyList vars) { 164 | boolean changed = false; 165 | 166 | for(int i = 0; i < vars.size(); i++) { 167 | if(!this.containsKey(vars.get(i).getKey())) { 168 | this.add(index, vars.get(i)); 169 | changed = true; 170 | } 171 | else { 172 | this.remove(i); 173 | this.add(i, vars.get(i)); 174 | changed = true; 175 | } 176 | 177 | } 178 | return changed; 179 | } 180 | 181 | 182 | /** 183 | * @param key 184 | */ 185 | public void remove(String key) { 186 | Property curVar; 187 | for(int i = 0 ; i < this.size() ; i++) { 188 | curVar = this.get(i); 189 | if(key == null) { 190 | if(curVar.getKey() == null) { 191 | this.remove(i); 192 | break; 193 | } 194 | } 195 | else if(curVar.getKey() != null && curVar.getKey().equals(key)) { 196 | this.remove(i); 197 | break; 198 | } 199 | } 200 | 201 | } 202 | 203 | 204 | /** 205 | * @param index 206 | * @param pvVar 207 | * @return Property 208 | * @throws IndexOutOfBoundsException 209 | */ 210 | @Override 211 | public Property set(int index, Property pvVar) throws IndexOutOfBoundsException { 212 | 213 | if(index > this.size()) { 214 | throw new IndexOutOfBoundsException("Index out of bounds: " + index + "> " + this.size()); 215 | } 216 | 217 | 218 | Property retVal = null; 219 | int curIndex; 220 | 221 | if((this.containsKey(pvVar.getKey()) && this.indexOf(pvVar) == index) || !this.containsKey(pvVar.getKey())) { 222 | retVal = super.set(index, pvVar); 223 | } 224 | else if(this.containsKey(pvVar.getKey()) && this.indexOf(pvVar) != index) { 225 | curIndex = this.indexOf(pvVar); 226 | retVal = super.remove(curIndex); 227 | super.add(curIndex, pvVar); 228 | } 229 | return retVal; 230 | 231 | } 232 | 233 | public Property set(Property pvVar) { 234 | if(!this.containsKey(pvVar.getKey())) { 235 | return null; 236 | } 237 | return this.set(this.indexOf(pvVar), pvVar); 238 | } 239 | 240 | 241 | } -------------------------------------------------------------------------------- /src/main/java/com/postman/collection/Response.java: -------------------------------------------------------------------------------- 1 | package com.postman.collection; 2 | 3 | import java.util.ArrayList; 4 | /** 5 | * 6 | * Class to encapsulate the response object property of a {@link com.postman.collection.Request}. 7 | * 8 | *

Postman SDK analog: Response.

9 | * 10 | * A RequestBody includes an optional array of expected responses: 11 | *
 12 |  *  "response": [
 13 |                 {
 14 |                     "name": "NORMAL Urlencoded",
 15 |                     "originalRequest": {
 16 |                         "method": "POST",
 17 |                         "url": {
 18 |                             "raw": "https://postman-echo.com/post",
 19 |                             "host": [
 20 |                                 "postman-echo",
 21 |                                 "com"
 22 |                             ],
 23 |                             "path": [
 24 |                                 "post"
 25 |                             ],
 26 |                             "protocol": "https"
 27 |                         },
 28 |                         "body": {
 29 |                             "mode": "urlencoded",
 30 |                             "urlencoded": [
 31 |                                 {
 32 |                                     "key": "x-field-2",
 33 |                                     "value": "value 2",
 34 |                                     "description": "This is value 2"
 35 |                                 },
 36 |                                 {
 37 |                                     "key": "x-field-1",
 38 |                                     "value": "value 1",
 39 |                                     "description": "This is value 1"
 40 |                                 }
 41 |                             ]
 42 |                         }
 43 |                     },
 44 |                     "code": 200,
 45 |                     "status": "OK",
 46 |                     "_postman_previewlanguage": "",
 47 |                     "body": "this is the expected response body"
 48 |                 }
 49 |             ]
 50 |             
51 | 52 | The response object includes a RequestBody object describing the original request associated with this response. 53 | 54 | * 55 | * 56 | */ 57 | public class Response extends CollectionElement { 58 | private String name = ""; 59 | private RequestBody originalRequest = null; 60 | private int code; 61 | private String status; 62 | private String _postman_previewlanguage = ""; 63 | private ArrayList cookie = null; 64 | private String body = ""; 65 | private PropertyList header; 66 | 67 | public Response(String name, RequestBody originalRequest, int code, String status, 68 | String _postman_previewlanguage, ArrayList cookie, String body) { 69 | this.name = name; 70 | this.originalRequest = originalRequest; 71 | this.code = code; 72 | this.status = status; 73 | this._postman_previewlanguage = _postman_previewlanguage; 74 | this.cookie = cookie; 75 | this.body = body; 76 | } 77 | 78 | 79 | /** 80 | * Set the value of the header element array with a pre-populated ArrayList of Property key-value pairs 81 | * 82 | * 83 | * @param headers 84 | */ 85 | public void setHeader(PropertyList headers) { 86 | this.header = headers; 87 | } 88 | 89 | 90 | /** 91 | * Get the ArrayList containing the key-value paris in the header element array 92 | * 93 | * @return ArrayList<{@link com.postman.collection.Property Property}> 94 | */ 95 | public PropertyList getHeader() { 96 | return this.header; 97 | } 98 | 99 | public Response(String name, RequestBody req, String status, int code, String body) { 100 | this.originalRequest = req; 101 | this.status = status; 102 | this.code = code; 103 | this.body = body; 104 | this.name = name; 105 | } 106 | 107 | 108 | /** 109 | * 110 | * Get the name of this response. 111 | * 112 | * @return String The name 113 | */ 114 | public String getName() { 115 | return name; 116 | } 117 | 118 | 119 | /** 120 | * Set the name of this response 121 | * 122 | * @param name The name 123 | */ 124 | public void setName(String name) { 125 | this.name = name; 126 | } 127 | 128 | 129 | /** 130 | * 131 | * Get the value of the originalRequest for this response as a RequestBody, or null if it has not been set. 132 | * 133 | * @return RequestBody 134 | */ 135 | public RequestBody getOriginalRequest() { 136 | return originalRequest; 137 | } 138 | 139 | 140 | /** 141 | * 142 | * Set the value of the originalRequest property 143 | * 144 | * @param originalRequest 145 | */ 146 | public void setOriginalRequest(RequestBody originalRequest) { 147 | this.originalRequest = originalRequest; 148 | } 149 | 150 | 151 | /** 152 | * 153 | * Get the value of the code property, the HTML status code associated with this response. 154 | * @return int 155 | */ 156 | public int getCode() { 157 | return code; 158 | } 159 | 160 | 161 | /** 162 | * Set the value of the code property, the HTML status code associated with this response. 163 | * 164 | * @param code 165 | */ 166 | public void setCode(int code) { 167 | this.code = code; 168 | } 169 | 170 | 171 | /** 172 | * 173 | * Get the value of the status property for this response, the string associated with the code> property, eg. "OK" 174 | * 175 | * @return String The status as a string, eg. "OK" 176 | */ 177 | public String getStatus() { 178 | return status; 179 | } 180 | 181 | 182 | /** 183 | * 184 | * Set the value of the status property for this response, the string associated with the code> property, eg. "OK" 185 | * 186 | * @param status The status. Not validated against existing http response codes 187 | */ 188 | public void setStatus(String status) { 189 | this.status = status; 190 | } 191 | 192 | 193 | /** 194 | * 195 | * Get the value of the _postman_previewlanguage property 196 | * @return String The language 197 | */ 198 | public String getPostmanPreviewlanguage() { 199 | return _postman_previewlanguage; 200 | } 201 | 202 | 203 | /** 204 | * 205 | * 206 | * Set the value of the _postman_previewlanguage property 207 | * 208 | * @param previewLanguage The language 209 | */ 210 | public void SetPostmanPreviewlanguage(String previewLanguage) { 211 | this._postman_previewlanguage = previewLanguage; 212 | } 213 | 214 | 215 | /** 216 | * 217 | * Return an ArrayList containing the Cookie objects comprising the value of the cookie array property 218 | * 219 | * @return ArrayList<{@link com.postman.collection.Cookie}> The cookies 220 | */ 221 | public ArrayList getCookies() { 222 | return cookie; 223 | } 224 | 225 | 226 | /** 227 | * 228 | * Set the value of the cookie array property with a pre-populated ArrayList 229 | * 230 | * @param cookie 231 | */ 232 | public void setCookies(ArrayList cookie) { 233 | this.cookie = cookie; 234 | } 235 | 236 | 237 | /** 238 | * 239 | * Get the value of the body property of the response, or null if not set. 240 | * 241 | * @return String The body 242 | */ 243 | public String getBody() { 244 | return body; 245 | } 246 | 247 | 248 | /** 249 | * Set the value of the body property of the response 250 | * 251 | * @param body The body. 252 | */ 253 | 254 | //TODO: Ensure string is properly escaped? 255 | public void setBody(String body) { 256 | this.body = body; 257 | } 258 | 259 | 260 | /** 261 | * 262 | * Return the Key for this object. Not currently implemented 263 | * 264 | * @return String The key 265 | */ 266 | @Override 267 | public String getKey() { 268 | 269 | return null; 270 | } 271 | 272 | } 273 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | scm:svn:http://127.0.0.1/dummy 7 | scm:svn:https://127.0.0.1/dummy 8 | HEAD 9 | http://127.0.0.1/dummy 10 | 11 | 4.0.0 12 | 13 | com.postman.collection 14 | jpostman 15 | 0.9 16 | 17 | jpostman 18 | 19 | http://www.example.com 20 | 21 | 22 | UTF-8 23 | 18 24 | 18 25 | 26 | 27 | 28 | 29 | 30 | com.google.code.gson 31 | gson 32 | 2.10.1 33 | 34 | 35 | 36 | junit 37 | junit 38 | 4.13.2 39 | test 40 | 41 | 42 | 43 | com.fasterxml.jackson.core 44 | jackson-databind 45 | 2.14.2 46 | 47 | 48 | com.flipkart.zjsonpatch 49 | zjsonpatch 50 | 0.4.14 51 | 52 | 53 | 54 | 55 | com.networknt 56 | json-schema-validator 57 | 1.0.79 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | maven-clean-plugin 70 | 3.2.0 71 | 72 | 73 | org.apache.maven.plugins 74 | maven-javadoc-plugin 75 | 3.5.0 76 | 77 | 78 | -Xdoclint:none 79 | 80 | 81 | 82 | 83 | maven-assembly-plugin 84 | 85 | JPostman-complete-${project.version} 86 | 87 | used version: ${jgitver.used_version} 88 | version calculated: ${jgitver.calculated_version} 89 | dirty: ${jgitver.dirty} 90 | head_committer_name: ${jgitver.head_committer_name} 91 | head_commiter_email: ${jgitver.head_commiter_email} 92 | head_commit_datetime: ${jgitver.head_commit_datetime} 93 | git_sha1_full: ${jgitver.git_sha1_full} 94 | git_sha1_8: ${jgitver.git_sha1_8} 95 | branch_name: ${jgitver.branch_name} 96 | head_tags: ${jgitver.head_tags} 97 | head_annotated_tags: ${jgitver.head_annotated_tags} 98 | head_lightweight_tags: ${jgitver.head_lightweight_tags} 99 | base_tag: ${jgitver.base_tag} 100 | all_tags: ${jgitver.all_tags} 101 | all_annotated_tags: ${jgitver.all_annotated_tags} 102 | all_lightweight_tags: ${jgitver.all_lightweight_tags} 103 | all_version_tags: ${jgitver.all_version_tags} 104 | all_version_annotated_tags: ${jgitver.all_version_annotated_tags} 105 | all_version_lightweight_tags: ${jgitver.all_version_lightweight_tags} 106 | 107 | false 108 | 109 | 110 | jar-with-dependencies 111 | 112 | 113 | 114 | com.postman.collection.Collection 115 | 116 | 117 | 118 | 119 | 120 | 121 | make-assembly 122 | package 123 | 124 | single 125 | 126 | 127 | 128 | 129 | 130 | 131 | maven-resources-plugin 132 | 3.3.1 133 | 134 | 141 | 142 | org.apache.maven.plugins 143 | maven-compiler-plugin 144 | 3.11.0 145 | 146 | 18 147 | 18 148 | 149 | 150 | 151 | maven-surefire-plugin 152 | 3.0.0 153 | 154 | 155 | maven-jar-plugin 156 | 3.3.0 157 | 158 | 159 | maven-install-plugin 160 | 3.1.1 161 | 162 | 163 | maven-deploy-plugin 164 | 3.1.1 165 | 166 | 167 | 168 | maven-site-plugin 169 | 3.12.1 170 | 171 | 172 | org.codehaus.mojo 173 | build-helper-maven-plugin 174 | 3.3.0 175 | 176 | 177 | parse-version 178 | 179 | parse-version 180 | 181 | 182 | 183 | 184 | 185 | maven-project-info-reports-plugin 186 | 3.4.2 187 | 188 | 189 | org.codehaus.mojo 190 | buildnumber-maven-plugin 191 | 3.0.0 192 | 193 | unknownbuild 194 | 195 | 196 | 197 | buildnumber 198 | validate 199 | 200 | create 201 | 202 | 203 | {0,number} 204 | 205 | buildNumber 206 | 207 | true 208 | true 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | -------------------------------------------------------------------------------- /src/main/java/com/postman/collection/RequestBody.java: -------------------------------------------------------------------------------- 1 | package com.postman.collection; 2 | 3 | 4 | /** 5 | * 6 | * 7 | * Encapsulates the request object property of a {@link com.postman.collection.Request} 8 | * 9 | *

Postman SDK analog: RequestBody.

10 | * 11 | *
{@code 
 12 | * {
 13 |     "name": "URL 7",
 14 |     "request": {
 15 |         "method": "GET",
 16 |         "header": [],
 17 |         "url": {
 18 |             "raw": "{{baseUrl}}foo.com/bar/:path1/bat.json?foo=1&bar=",
 19 |             "host": [
 20 |                 "{{baseUrl}}foo",
 21 |                 "com"
 22 |             ],
 23 |             "path": [
 24 |                 "bar",
 25 |                 ":path1",
 26 |                 "bat.json"
 27 |             ],
 28 |             "query": [
 29 |                 {
 30 |                     "key": "foo",
 31 |                     "value": "1"
 32 |                 },
 33 |                 {
 34 |                     "key": "bar",
 35 |                     "value": ""
 36 |                 }
 37 |             ],
 38 |             "variable": [
 39 |                 {
 40 |                     "key": "path1",
 41 |                     "value": "path-value"
 42 |                 }
 43 |             ]
 44 |         }
 45 |     },
 46 |     "response": []
 47 | }
 48 | }
* 49 | * 50 | */ 51 | public class RequestBody extends CollectionElement { 52 | private enumHTTPRequestMethod method = enumHTTPRequestMethod.GET; 53 | private Url url; 54 | private PropertyList header; 55 | private String description; 56 | private BodyElement body; 57 | private RequestAuth auth; 58 | private String name; 59 | 60 | 61 | /** 62 | * 63 | * Returns the value of the name property 64 | * 65 | * @return String 66 | */ 67 | public String getKey() { 68 | return this.name; 69 | } 70 | 71 | /** 72 | * Construct a RequestBody with the specified HTTP method, host and path. All URL components are constructed from the host and path strings. 73 | * 74 | * @param method Enumerated value for the HTTP method 75 | * @param host String containing the host portion of the URL. 76 | * @param path String containing the path portion of the URL. 77 | */ 78 | public RequestBody(enumHTTPRequestMethod method, String host, String path) throws DuplicateVariableKeyException { 79 | 80 | this.setMethod(method); 81 | 82 | this.setUrl(new Url(host, path)); 83 | 84 | } 85 | 86 | 87 | /** 88 | * Construct a RequestBody with the specified HTTP method, and Url. 89 | * 90 | * @param method Enumerated value for the HTTP method 91 | * @param url Pre-constructed Url object 92 | * 93 | */ 94 | public RequestBody(enumHTTPRequestMethod method, Url url) { 95 | 96 | this.setMethod(method); 97 | this.setUrl(url); 98 | } 99 | 100 | 101 | /** 102 | * 103 | * Set the values in the auth array with a pre-populated {@link com.postman.collection.RequestAuth} object. 104 | * 105 | * @param auth The auth 106 | */ 107 | public void setAuth(RequestAuth auth) { 108 | this.auth = auth; 109 | this.auth.setParent(this); 110 | } 111 | 112 | 113 | /** 114 | * 115 | * Get the {@link com.postman.collection.RequestAuth} object containing the values of the auth array, or null if it has not been set. 116 | * 117 | * @return RequestAuth The auth object containing the values. 118 | */ 119 | public RequestAuth getAuth() { 120 | return this.auth; 121 | } 122 | 123 | 124 | /** 125 | * 126 | * Construct a RequestBody object from a raw URL. All path, host, URL, auth and other property array elements are parsed out and populated 127 | * 128 | * 129 | * @param method Enumerated value for the HTTP method 130 | * @param URL The raw URL 131 | */ 132 | public RequestBody(enumHTTPRequestMethod method, String URL) throws DuplicateVariableKeyException { 133 | 134 | this.setUrl(new Url(URL)); 135 | this.setMethod(method); 136 | 137 | } 138 | 139 | 140 | /** 141 | * 142 | * Return the enumerated value of the method property 143 | * 144 | * @return enumHTTPRequestMethod 145 | */ 146 | public enumHTTPRequestMethod getMethod() { 147 | return method; 148 | } 149 | 150 | 151 | /** 152 | * 153 | * Set the value of the method property 154 | * 155 | * @param method 156 | */ 157 | public void setMethod(enumHTTPRequestMethod method) { 158 | this.method = method; 159 | } 160 | 161 | 162 | /** 163 | * 164 | * Return the Url containing the values of the url property array 165 | * 166 | * @return Url 167 | */ 168 | public Url getUrl() { 169 | return url; 170 | } 171 | 172 | 173 | /** 174 | * @param resolveVariables 175 | * @return String 176 | * @throws VariableResolutionException 177 | */ 178 | public String getUrl(boolean resolveVariables) throws VariableResolutionException { 179 | String retVal = this.url.getUrl(resolveVariables); 180 | if(resolveVariables) { 181 | try { 182 | retVal = this.getCollection().resolveVariables(retVal); 183 | 184 | } 185 | catch(Exception e) { 186 | e.printStackTrace(); 187 | } 188 | } 189 | 190 | return retVal; 191 | } 192 | 193 | 194 | /** 195 | * 196 | * Set the values of the url property 197 | * 198 | * @param url Url object containing the values 199 | */ 200 | public void setUrl(Url url) { 201 | this.url = url; 202 | this.url.setParent(this); 203 | } 204 | 205 | 206 | /** 207 | * 208 | * Return an ArrayList of Property objects containing the key-value pair values for the header property array 209 | * 210 | * 211 | * @return ArrayList<{@link com.postman.collection.Property Property}> The headers, or null if none are present 212 | */ 213 | public PropertyList getHeader() { 214 | return header; 215 | } 216 | 217 | 218 | /** 219 | * 220 | * Set the key-value pair values for the header property array 221 | * 222 | * @param header Header values 223 | */ 224 | public void setHeader(PropertyList header) { 225 | this.header = header; 226 | } 227 | 228 | 229 | /** 230 | * 231 | * Get the value of the description property, generally the documentation for the request 232 | * 233 | * @return String The description 234 | */ 235 | public String getDescription() { 236 | return description; 237 | } 238 | 239 | 240 | /** 241 | * Set the value of the description property, generally the documentation for the request 242 | * 243 | * 244 | * @param description The description 245 | */ 246 | public void setDescription(String description) { 247 | this.description = description; 248 | } 249 | 250 | 251 | /** 252 | * 253 | * Populate the body array with an empty body property object with the specified mode value. 254 | * 255 | * @param bodyMode The body mode, eg. RAW 256 | * @return PostmanBody The new body 257 | */ 258 | public BodyElement setBody(enumRequestBodyMode bodyMode) { 259 | return this.setBody(bodyMode, null); 260 | } 261 | 262 | 263 | /** 264 | * 265 | * 266 | * Populate the body array with the specified body content. The language property of the 267 | * request will best set to "text" 268 | * 269 | * 270 | * @param bodyMode Enumerated value for the mode property 271 | * @param rawContent The raw content for the body 272 | * @return PostmanBody The new body 273 | */ 274 | public BodyElement setBody(enumRequestBodyMode bodyMode, String rawContent) { 275 | this.setBody(new BodyElement(bodyMode, rawContent, enumRawBodyLanguage.TEXT)); 276 | return this.getBody(); 277 | } 278 | 279 | 280 | /** 281 | * Return the PostmanBody object containing the values in the body property object, or null if it has not been set. 282 | * 283 | * @return PostmanBody The body, or null. 284 | */ 285 | public BodyElement getBody() { 286 | return this.body; 287 | } 288 | 289 | 290 | 291 | /** 292 | * 293 | * Set the value of the body property object 294 | * 295 | * @param body The new body values 296 | */ 297 | public void setBody(BodyElement body) { 298 | this.body = body; 299 | this.body.setParent(this); 300 | } 301 | 302 | } 303 | -------------------------------------------------------------------------------- /src/main/java/com/postman/collection/Event.java: -------------------------------------------------------------------------------- 1 | package com.postman.collection; 2 | 3 | import java.util.ArrayList; 4 | /** 5 | * 6 | * Encapsulates members of the event array object. Events contain pre-request and test scripts for Folders, Requests, and Collections 7 | * 8 | *

Postman SDK analog: event.

9 | * 10 | *
 11 |  * "event": [  
 12 |     {
 13 |         "listen": "test",
 14 |         "script": {
 15 |             "exec": [
 16 |                 "pm.test(\"Status code is 200\", function () {",
 17 |                 "    pm.response.to.have.status(200);",
 18 |                 "});",
 19 |                 "",
 20 |                 "var latencyTestName = \"Response time is less than \" + pm.collectionVariables.get(\"latencyLimit\") + \" ms\";",
 21 |                 "",
 22 |                 "pm.test(latencyTestName, function () {",
 23 |                 "    pm.expect(pm.response.responseTime).to.be.below(parseInt(pm.collectionVariables.get(\"latencyLimit\")));",
 24 |                 "});",
 25 |                 "",
 26 |                 "pm.test(\"Response contains fact\", function () {",
 27 |                 "    var jsonData = pm.response.json();",
 28 |                 "    pm.expect(pm.response.json().length).to.be.greaterThan(1);",
 29 |                 "});"
 30 |             ],
 31 |             "type": "text/javascript"
 32 |         }
 33 |     },
 34 |     {
 35 |         "listen": "prerequest",
 36 |         "script": {
 37 |             "exec": [
 38 |                 "console.log(\"last fact: \" + pm.collectionVariables.get(\"curFact\"));"
 39 |             ],
 40 |             "type": "text/javascript"
 41 |         }
 42 |     }
 43 |     ]
 44 | 
 45 |                     
46 | * 47 | * 48 | */ 49 | public class Event extends CollectionElement { 50 | 51 | private String listen = ""; // basically the name 52 | private PostmanScript script = null; 53 | 54 | /** 55 | * 56 | * Create a new Event object with the specified EventType (eg., pre-request or test) and source code. The type property is excluded because it is always 'text/javascript', 57 | * although the schema does theoretically allow for different values 58 | * 59 | * 60 | * @param evtType Enumerated value of the event type, eg. pre-request or test 61 | * @param sourceCode Source code for the script 62 | * @param evtType Content type of the script, always "text/javascript" 63 | * 64 | */ 65 | public Event(enumEventType evtType, String sourceCode) { 66 | this.setEventType(evtType); 67 | this.setScript(new PostmanScript(this.getScriptType(), sourceCode)); 68 | } 69 | 70 | 71 | /** 72 | * 73 | * Unimplemented because type is always text/javascript 74 | /* 75 | public void setScriptType(String scriptType) { 76 | this.script.setType(scriptType); 77 | } 78 | */ 79 | 80 | 81 | /** 82 | * @return String 83 | */ 84 | public String getScriptType() { 85 | //return this.script.getType(); 86 | return "text/javascript"; 87 | } 88 | 89 | 90 | /** 91 | * 92 | * Returns the type of this script, eg., pre-request or test, as an enumerated value. 93 | * 94 | * @return enumEventType The event type 95 | */ 96 | public enumEventType getEventType() { 97 | if (this.getListen().equals("test")) { 98 | return enumEventType.TEST; 99 | } else if (this.getListen().equals("prerequest")) { 100 | return enumEventType.PRE_REQUEST; 101 | } else { 102 | return null; 103 | } 104 | } 105 | 106 | 107 | /** 108 | * 109 | * Sets the type of this event, eg. pre-request or test, as an enumerated value 110 | * 111 | * @param eventType The type of the event 112 | * 113 | */ 114 | public void setEventType(enumEventType eventType) { 115 | if (eventType == enumEventType.PRE_REQUEST) { 116 | this.setListen("prerequest"); 117 | } else if (eventType == enumEventType.TEST) { 118 | this.setListen("test"); 119 | } 120 | } 121 | 122 | 123 | /** 124 | * @return String 125 | */ 126 | private String getListen() { 127 | return listen; 128 | } 129 | 130 | 131 | /** 132 | * @param listen 133 | */ 134 | private void setListen(String listen) { 135 | this.listen = listen; 136 | } 137 | 138 | /** 139 | * 140 | * Get complete source for this script, or null if none is set. Concatenates all the elements of the exec array. 141 | * 142 | * @return 143 | */ 144 | public String getSourceCode() throws InvalidPropertyException { 145 | String srcCode = ""; 146 | if(this.getScript() == null || this.getScript().getSourceCode() == null) { 147 | return null; 148 | } 149 | String chunk = ""; 150 | for(int i = 0; i < this.getScript().getSourceCode().size(); i++) { 151 | 152 | chunk = this.getScript().getSourceCodeElement(i); 153 | srcCode = srcCode + (i > 0 && i < (this.getScript().getSourceCode().size() -1) ? "\n" : "") + chunk; 154 | } 155 | 156 | 157 | return srcCode; 158 | } 159 | 160 | 161 | /** 162 | * @return ArrayList<String> 163 | */ 164 | public ArrayList getSourceCodeElements() { 165 | if(this.getScript() == null || this.getScript().getSourceCode() == null) 166 | { 167 | return null; 168 | } 169 | else { 170 | return this.getScript().getSourceCode(); 171 | } 172 | } 173 | 174 | 175 | /** 176 | * 177 | * Set the source code for this script 178 | * 179 | * @param srcCode The source code (javascript) 180 | */ 181 | public void setSourceCode(String srcCode) { 182 | this.setScript(new PostmanScript("text/javascript", srcCode)); 183 | } 184 | 185 | 186 | 187 | 188 | /** 189 | * @return PostmanScript 190 | */ 191 | private PostmanScript getScript() { 192 | return script; 193 | } 194 | 195 | 196 | /** 197 | * @param script 198 | */ 199 | private void setScript(PostmanScript script) { 200 | this.script = script; 201 | } 202 | 203 | 204 | /** 205 | * @return String 206 | */ 207 | @Override 208 | public String getKey() { 209 | 210 | return listen; 211 | } 212 | 213 | 214 | /** 215 | * 216 | * Pre-pend source code to the end of the exec property array. 217 | * 218 | * @param code 219 | */ 220 | public void addSourceCodeElement(String code, int position) { 221 | if(this.getScript() == null) { 222 | this.setScript(new PostmanScript("text/javascript",code)); 223 | return; 224 | } 225 | this.getScript().addSourceCodeElement(code, position); 226 | 227 | } 228 | 229 | 230 | /** 231 | * @param position 232 | * @throws InvalidPropertyException 233 | */ 234 | public void removeSourceCodeElement(int position) throws InvalidPropertyException{ 235 | if(this.getScript() == null || this.getScript().getSourceCode() == null || position < 0 || position > this.getScript().getSourceCode().size()) { 236 | throw new InvalidPropertyException("Source code null or position out of bounds"); 237 | } 238 | this.getScript().removeSourceCodeElement(position); 239 | } 240 | 241 | public class PostmanScript extends CollectionElement { 242 | private String type = ""; 243 | private ArrayList exec; 244 | 245 | public PostmanScript(String scriptType, ArrayList sourceCode) { 246 | this.type = scriptType; 247 | exec = sourceCode; 248 | } 249 | 250 | public PostmanScript(String scriptType, String sourceCode) { 251 | this.exec = new ArrayList(); 252 | this.exec.add(sourceCode); 253 | this.type = scriptType; 254 | 255 | } 256 | 257 | public void addSourceCodeElement(String code, int position) { 258 | if(this.getSourceCode() == null || position < 0 || position > this.getSourceCode().size()) 259 | { 260 | this.exec = new ArrayList(); 261 | this.exec.add(code); 262 | } 263 | else { 264 | this.exec.add(code); 265 | } 266 | } 267 | 268 | public void removeSourceCodeElement(int position) throws InvalidPropertyException { 269 | 270 | if(this.exec == null || (position < 0 || position > this.exec.size())) { 271 | throw new InvalidPropertyException("Postion " + position + "out of bounds" ); 272 | } 273 | this.exec.remove(position); 274 | } 275 | 276 | 277 | 278 | public String getType() { 279 | return type; 280 | } 281 | 282 | public void setType(String type) { 283 | this.type = type; 284 | } 285 | 286 | public String getSourceCodeElement(int position) throws InvalidPropertyException { 287 | if(position < 0 || exec == null || position > (exec.size() - 1)) { 288 | throw new InvalidPropertyException("Source code not set or position out of bounds"); 289 | } 290 | return exec.get(position); 291 | } 292 | 293 | public ArrayListgetSourceCode() { 294 | return exec; 295 | } 296 | 297 | public void setSourceCode(ArrayList exec) { 298 | this.exec = exec; 299 | } 300 | 301 | @Override 302 | public String getKey() { 303 | 304 | return null; 305 | } 306 | 307 | } 308 | 309 | } 310 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # JPostman 2 | 3 | A Java wrapper for Postman collection files. 4 | 5 | [Docs](https://bidnessforb.github.io/JPostman) 6 | 7 | [Postman Collection Overview](https://collectionformat.gatsbyjs.io/docs/getting-started/overview/) 8 | 9 | [Postman Collection SDK (Node)](http://www.postmanlabs.com/postman-collection/index.html) 10 | 11 | ## Getting started 12 | 13 | 1. Download the JAR file from the releases tab 14 | 2. Import `com.postman.collection.Collection` in your source code. 15 | 3. Instantiate a new collection by passing the path to a Postman collection .json file to the `Collection.pmcFactory` method 16 | 17 | ```java 18 | Collection pmcTest = Collection.pmcFactory("/path/to/your/exported/collection.json"); 19 | ``` 20 | 21 | ## What you can do 22 | 23 | ### Integrate with Java applications and platforms 24 | 25 | Java is common in Enterprise software development environments. JPostman enables you to create a complete Java object model of a Postman collection from an exported collection JSON file. This provides a bridge for integrating 26 | with Java based applications and platforms such as JMeter. 27 | 28 | ### Create collections from exported `postman_collection.json` files 29 | ```java 30 | File jsonFile = new File("/path/to/your/exported/collection.json"); 31 | Collection pmcTest = Collection.pmcFactory(jsonFile); 32 | ``` 33 | 34 | You can experiment with example collections in the [Resources](https://github.com/BidnessForB/JPostman/tree/main/src/main/resources/com/postman/collection) folder. 35 | 36 | ### Import a collection directly from Postman 37 | 38 | Got a [Collection ID](https://support.postman.com/hc/en-us/articles/5063785095319-How-to-find-the-ID-of-an-element-in-Postman) and a [Postman API Key](https://learning.postman.com/docs/developer/intro-api/#generating-a-postman-api-key)? Create Collection object directly from Postman: 39 | 40 | ```java 41 | Collection pmcTest = Collection.pmcFactory(new PostmanID("")); 42 | ``` 43 | 44 | NOTE: You must set an environment variable named `POSTMAN_API_KEY` with the value of your Postman API key. 45 | 46 | ### Create Collections from scratch 47 | 48 | You can create a new, empty collection as well 49 | 50 | ```java 51 | Collection newColl = Collection.pmcFactory(); 52 | newColl.setName("My new collection"); 53 | ``` 54 | 55 | then create and add elements to your new collection 56 | 57 | ### Add requests 58 | 59 | You can add a new request just by providing a URL: 60 | 61 | ```java 62 | Collection newColl = Collection.pmcFactory(); 63 | newColl.addRequest("https://postman-echo.com/get"); 64 | ``` 65 | 66 | ### Edit collections: add, remove, edit and move Collection elements 67 | 68 | JPostman allows you to add new Folders and Requests to your Postman Collections. You can also add variables, Pre-Request and Test Scripts, requests, and responses. In fact, 69 | you can add, edit, or remove any element in a Postman collection. All `add` operations allow you to specify a position in the array of items on the object, meaning 70 | that you preserve the order of Folders, Requests, etc, in the collection. 71 | 72 | For example, adding a new Folder as the third `item` in the collection: 73 | 74 | ```java 75 | // Add a new folder to the 3rd position beneath the root of the collection 76 | Collection pmcTest = Collection.pmcFactory("/path/to/your/exported/collection.json"); 77 | Folder newFolder = new Folder("new Folder"); 78 | pmcTest.addFolder(newFolder, 2); 79 | 80 | ``` 81 | ### Move collection elements 82 | 83 | You can easily move elements from one parent to another. For example, move a request to a new folder, or a folder to another folder or to the top level in the collection. 84 | 85 | ```java 86 | Collection pmcTest = Collection.pmcFactory("/path/to/your/exported/collection.json"); 87 | Item newFolder1 = new Folder("new Folder One"); 88 | Item newFolder2 = new Folder("new Folder Two"); 89 | pmcTest.addFolder(newFolder1); 90 | pmcTest.addFolder(newFolder2); 91 | pmcTest.moveItem(newFolder2, newFolder1); 92 | ``` 93 | 94 | ### Combining collections 95 | 96 | You can combine collections as well. 97 | 98 | ```java 99 | // Combine collections, inserting the source collection as a Folder in the 2d position from the root of the target collection 100 | Collection pmcTarget = Collection.pmcFactory("/path/to/your/exported/collection.json"); 101 | Collection pmcSource = Collection.pmcFactory("/path/to/another/collection.json"); 102 | pmcTest.addCollection(pmcSource); 103 | ``` 104 | When a collection is added, a new Folder is created and all of the added collection's elements are linked to that folder. The folder in turn is then linked to the target collection. All folders, requests, pre-request and test scripts are copied over from the source to the target collection. Collection variables are appended to the target collections array of variables. 105 | 106 | There are options for copying (or not copying) the source collections scripts and variables as well. You can also specify a specific parent to receive the source collection. 107 | 108 | 109 | ### Write your edited collections to a JSON file 110 | 111 | JPostman allows you to generate JSON for your collections. You can also write your collections to a file which can then be imported into Postman. 112 | ```java 113 | 114 | // Combine collections, inserting the source collection as a Folder in the 2d position from the root of the target collection 115 | // Then set the value of a String variable to the JSON for the new, combined collection. 116 | Collection pmcTarget = Collection.pmcFactory("/path/to/your/exported/collection.json"); 117 | Collection pmcSource = Collection.pmcFactory("/path/to/another/collection.json"); 118 | pmcTest.addCollection(pmcSource); 119 | pmcTest.writeToFile("new-collection.json"); 120 | ``` 121 | 122 | ### Create or update a collection in Postman 123 | 124 | You can upsert (create or update) a collection in Postman, optionally adding it to a workspace. 125 | - If a collection does not have a collection ID, it will be created on Postman, and given the UUID returned by Postman 126 | - You can optionally include a workspace ID to link the newly created collection to that workspace 127 | 128 | ```java 129 | pmcTest.upsertToPostman(new PostmanID(")); 130 | ``` 131 | 132 | - If a collection has a collection ID, it will be updated in Postman. 133 | 134 | 135 | 136 | 137 | 138 | ### Validate collections (and any collection element) against the Postman Collection Schema 139 | 140 | Use the `Collection.validate() method to ensure that the JSON emitted by your instance of Collection conforms with the Postman Collection schema: 141 | 142 | ```java 143 | boolean isValid = myCollection.validate(); 144 | ``` 145 | 146 | JPostman uses the NetworkNT [json-schema-validator](https://github.com/networknt/json-schema-validator) to validate JSON against a JSON schema. 147 | 148 | If the `validate()` method returns `false`, call `getValidationMessages()` for an array of [ValidationMessage](https://javadoc.io/doc/com.networknt/json-schema-validator/1.0.51/com/networknt/schema/ValidationMessage.html) objects describing differences between your collections generated JSON and the Postman schema. 149 | 150 | #### Individual Elements 151 | Since collections and the elements they contain all extend the
CollectionElement class they have the potential to be individually validated as well. Currently, element validation is supported for: 152 | 153 | - Collection 154 | - Item 155 | - RequestAuth 156 | - BodyElement 157 | 158 | 159 | ## Implementation 160 | 161 | Java does not natively support JSON in the way that NodeJS does. Object models based on JSON must be manually constructed. Forutnately the brilliant folks at Google came up with [GSON](https://github.com/google/gson) a library that does this automatically. Basically you create Java classes with member variables that match the keys in the JSON file. GSON then parses the file and builds out the object model. GSON also allows for an object model to be written out to JSON. 162 | 163 | GSON does not link parents to their child objects, so deriving parent objects is not straightforward. In this implementation we recurse the object tree until we find the object which contains the target object, and return that as the parent. 164 | 165 | GSON also works with arrays by default rather than more convenient Java collections mechanisms like Collections, Maps, etc. This has the advantage of simplicity but does make adding, removing, or re-ordering collection elements somewhat more complex and onerous. 166 | 167 | ## Postman Collection File Structure 168 | 169 | You can review the schema for the Postman Collection v2.1 format [here](https://schema.getpostman.com/json/collection/v2.1.0/collection.json). The Postman team have provided a comprehensive overview of the Collection format [here](https://collectionformat.gatsbyjs.io/docs/getting-started/overview/) 170 | 171 | In a nutshell, a Postman collection file consists of the following elements 172 | 1. An `info` section containing collection metadata, including it's name, description, and Postman UID 173 | 2. Zero or more `item` elements, which can themselves contain an array if `item` elements. There are two types of `item` objects 174 | - A *Request* is an item that contains a `request` key. These are rendered in Postman as Requests. Request items do not contain sub-items, they are always leaf elements. 175 | - A *folder* is an item that contains zero or more sub-items, but which does NOT contain a `request` key. 176 | 3. Pre-Request and Test scripts are stored in an `event` key. Any item can have an `event` key. 177 | 4. Collection variables are stored under the `variables` key. 178 | 179 | Thus, a collection is `info`, `variables`, `events`, and an arry if `item`s, each of which can contain any number of sub-items. 180 | 181 | -------------------------------------------------------------------------------- /src/main/java/com/postman/collection/ItemGroup.java: -------------------------------------------------------------------------------- 1 | package com.postman.collection; 2 | import java.util.ArrayList; 3 | 4 | 5 | /** 6 | * 7 | * 8 | * Abstract class encapsulating a Postman ItemGroup. This class provides services for recursively finding, adding and removing child elements, eg., a request in a folder. 9 | 10 | *

Postman SDK analog: ItemGroup.

11 | * 12 | 13 | * 14 | * 15 | * 16 | * 17 | * 18 | * 19 | */ 20 | 21 | public abstract class ItemGroup extends Item { 22 | private ArrayList item; 23 | 24 | 25 | /** 26 | * 27 | * Return an ArrayList<{@link com.postman.collection.Item Item}> containing the tree of items owned by this item. 28 | * 29 | * * @return ArrayList<{@link com.postman.collection.Item Item}> The items 30 | */ 31 | public ArrayList getItems() { 32 | return item; 33 | } 34 | 35 | /** 36 | * 37 | * Recursively search the entire tree of items in the item property, optionally filter by item type (eg. FOLDER or REQUEST) 38 | * 39 | * 40 | * @param filter Enumerated value for the object type, eg., FOLDER or REQUEST. Passing null returns all items. 41 | * @return 42 | */ 43 | public ArrayList getItems(enumItemType filter) { 44 | ArrayList results = new ArrayList(); 45 | 46 | if (item == null) { 47 | return null; 48 | } 49 | 50 | for (Item curItem : item) { 51 | if(filter == null && !(curItem instanceof ItemGroup) ) { 52 | results.add(curItem); 53 | } 54 | else if(filter == null && curItem instanceof ItemGroup) { 55 | results.addAll(((ItemGroup)curItem).getItems(filter)); 56 | } 57 | else if (filter != null && curItem instanceof Folder) { 58 | if(filter == enumItemType.FOLDER) { 59 | results.add(curItem); 60 | } 61 | try { 62 | results.addAll(((Folder)curItem).getItems(filter)); 63 | 64 | } catch (Exception e) { 65 | e.printStackTrace(); 66 | } 67 | } 68 | else if((filter != null && filter == enumItemType.REQUEST && curItem instanceof Request)) { 69 | results.add(curItem); 70 | } 71 | 72 | 73 | } 74 | 75 | return results; 76 | } 77 | 78 | /** 79 | * 80 | * Set the value of the item array with an ArrayList<Item>. Passing null effectively removes all children from this item. 81 | * 82 | * @param items The items, or null to remove all items. 83 | */ 84 | public void setItems(ArrayList items) { 85 | this.item = items; 86 | } 87 | 88 | 89 | /** 90 | * 91 | * Recursively search the contents of the item array for the item with the specified key. Generally this is the name property for requests and folders. 92 | * 93 | * @param key The key (name) of the desired item 94 | * @return Item The item, if it is found in the item array, or null if it is not. 95 | */ 96 | public Item getItem(String key) { 97 | return this.getItem(key, null); 98 | } 99 | 100 | 101 | 102 | 103 | 104 | 105 | /** 106 | * 107 | * Recursively search the contents of the item array for the item with the specified key, optionally returning the item or it's parent item. 108 | * 109 | * 110 | * @param key The key (name) of the desired item 111 | * @param parent True to return the parent of the item, if found, false to return the item itself. 112 | * @param filter Optional, filter on object type, eg., FOLDER or REQUEST. If null, do not filter 113 | * @return Item The item if present, or null 114 | */ 115 | 116 | public Item getItem(String key, enumItemType filter) { 117 | Item result = null; 118 | if (this.item == null) { 119 | return null; 120 | } 121 | // recursively traverse items looking for name == key 122 | for (Item curItem : item) { 123 | if (item == null) 124 | return null; 125 | if(filter == null && curItem.getKey().equals(key)) { 126 | result = curItem; 127 | break; 128 | } 129 | if (curItem.getKey().equals(key)) { 130 | if (filter != null && (filter == enumItemType.REQUEST) && curItem instanceof Request) { 131 | result = curItem; 132 | } else if(filter != null && filter == enumItemType.FOLDER && curItem instanceof Folder) { 133 | result = (Item)curItem; 134 | } 135 | break; 136 | } else if (curItem instanceof ItemGroup) { 137 | result = ((ItemGroup)curItem).getItem(key, filter); 138 | if (result != null) { 139 | break; 140 | } 141 | } 142 | 143 | } 144 | 145 | return result; 146 | } 147 | /** 148 | * 149 | * Add multiple items to this item. 150 | * 151 | * @param newItems The items to add 152 | * 153 | */ 154 | public void addItems(ArrayList newItems) throws RecursiveItemAddException, IllegalPropertyAccessException { 155 | if (this.item == null) { 156 | this.item = new ArrayList(); 157 | } 158 | for(Item curItem : newItems) { 159 | this.addItem(curItem); 160 | } 161 | 162 | } 163 | 164 | /** 165 | * 166 | * Searches the direct children of this item (eg., non-recursively) to find an entry in the array that is the same Java instance as this item (Object.equals()) 167 | * 168 | * @param theItem The item to search for 169 | * @return boolean 170 | */ 171 | public boolean hasItem(Item theItem) { 172 | if (item == null) { 173 | return false; 174 | } 175 | for (Item curItem : item) { 176 | if (curItem.equals(theItem)) 177 | ; 178 | return true; 179 | } 180 | 181 | return false; 182 | } 183 | 184 | /** 185 | * 186 | * Append a new direct child item to the array of items in the item property. This method does not recursively check for circular additions/references. 187 | * 188 | * @param newItem The item to add 189 | * @throws RecursiveItemAddException If newItem is the same item instance as this item. 190 | * @throws IllegalPropertyAccessException If this item is a request 191 | */ 192 | public void addItem(Item newItem) throws RecursiveItemAddException, IllegalPropertyAccessException { 193 | //TODO: These should probably be private. 194 | if (newItem.equals(this)) { 195 | throw new RecursiveItemAddException("Cannot add an object to itself, lolz"); 196 | } 197 | 198 | if (this.item == null) { 199 | this.item = new ArrayList(); 200 | } 201 | newItem.setParent(this); 202 | this.item.add(newItem); 203 | 204 | 205 | } 206 | 207 | public ItemGroup(String name) { 208 | super(name); 209 | } 210 | 211 | 212 | /** 213 | * 214 | * 215 | * Add a new direct child item to the array of items in the item property at the specified index. This method does not recursively check for circular additions/references. 216 | * 217 | * @param newItem Item to add 218 | * @param position Index for new item 219 | * @throws IllegalPropertyAccessException If newItem is already a direct child of this item, or if position is < 0 or > the size of the existing array 220 | * @throws RecursiveItemAddException If newItem is already a child of this item 221 | * 222 | */ 223 | public void addItem(Item newItem, int position) throws IllegalPropertyAccessException, RecursiveItemAddException { 224 | if(this.item == null) { 225 | this.item = new ArrayList(); 226 | } 227 | if (this.hasItem(newItem)) { 228 | throw new IllegalPropertyAccessException("Item is already present"); 229 | } 230 | // If the newitem already owns this item, it's a circular recursion 231 | if (newItem instanceof ItemGroup && ((ItemGroup)newItem).getItem(this.getKey()) != null) 232 | 233 | { 234 | throw new RecursiveItemAddException("Item [" + newItem.getKey() + "] already contains this item [" + this.getKey()); 235 | } 236 | if(position < 0 || position > this.item.size()) { 237 | throw new IllegalPropertyAccessException("Position " + position + " is out of bounds"); 238 | } 239 | 240 | this.item.add(position, newItem); 241 | newItem.setParent(this); 242 | 243 | } 244 | 245 | 246 | /** 247 | * 248 | * Removes an item from the tree of items comprising the item property 249 | * 250 | * @param oldItem The item to remove 251 | * 252 | */ 253 | public void removeItem(Item oldItem) { 254 | this.removeItem(oldItem.getKey()); 255 | } 256 | 257 | /** 258 | * 259 | * Removes an item with the specified key from the tree of items comprising the item property 260 | * 261 | * @param key Key of the item to remove (ie. it's name) 262 | * 263 | */ 264 | public void removeItem(String key) { 265 | if (item == null) { 266 | return; 267 | } 268 | for (Item curItem : item) { 269 | if (curItem.getKey().equals(key)) { 270 | this.item.remove(curItem); 271 | break; 272 | } 273 | 274 | } 275 | 276 | } 277 | 278 | public Request getRequest(String key) { 279 | return (Request)this.getItem(key, enumItemType.REQUEST); 280 | } 281 | 282 | public Folder getFolder(String key) { 283 | return (Folder)this.getItem(key, enumItemType.FOLDER); 284 | 285 | } 286 | 287 | 288 | 289 | 290 | 291 | } 292 | -------------------------------------------------------------------------------- /src/main/resources/com/postman/collection/source-code.postman_collection.json: -------------------------------------------------------------------------------- 1 | { 2 | "info": { 3 | "_postman_id": "49e47697-1cd5-4dbf-8b12-471539723168", 4 | "name": "Reusable Test Code from GitHub", 5 | "description": "## Overview\n\nRetrieve and execute Postman tests from a GitHub repo. Requires a [GitHub PAT](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token). If your organization uses SAML for Single Sign-On (SSO), you'll need to [authorize your PAT for SSO](https://docs.github.com/en/rest/overview/other-authentication-methods#authenticating-for-saml-sso). The pre-request script uses the [GitHub REST API](https://docs.github.com/en/rest/repos/contents#get-repository-content) to retrieve and decode the content.\n\nNOTE: At the moment only content on the default branch is retrieved.\n\nNOTE: This script assumes that the content residing in GitHub are a [text files < 1MB in size](https://docs.github.com/en/rest/repos/contents#size-limits).\n\n## Using the Collection\n\n1. Create or update an environment with a secret variable named `GitHubPAT`and set it to your GitHub Personal Access Token. Your PAT will need [repo](https://docs.github.com/en/developers/apps/building-oauth-apps/scopes-for-oauth-apps#available-scopes) scope. \n **CAUTION**: Update the **current value** only to prevent your token leaking!!\n 1. If you don't have a GitHub PAT, you can easily [create one](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token).\n2. Create or update and environment variable called `postmanAPIKey` with your Postman API Key.\n3. Run the requests in the collection to demonstrate test code loaded from GitHub at the Collection, folder, and individual request level.\n \n\n## Collection variables\n\nThe following collection variables are designed to be edited by the end user as required. Other collection variables are for runtime use and are populated by code.\n\n| **Variable** | **Desc** |\n| --- | --- |\n| repoSlug | GitHub repo \"slug\" of the repository containing the test script snippets.

A \"slug\" is just the repo owner and repo name concatenated with a '/'
**EXAMPLE:** byrancross/postman-demo |\n| GitHub_collectionTestsPath | Path of the file containing the collection level test script snippets within the repo. Path is relative to the root of the repo and does _not_ include a leading slash.

**EXAMPLE**: code-snippets/my-code-snippet.js |\n| GitHub_folderTestsPath | Path of the file containing the collection level test script snippets within the repo.

**EXAMPLE**: code-snippets/my-code-snippet.js |\n| GitHub_APIBaseUrl | GitHub API base URL, currently `https://api.github.com` |\n| code_getCollectionLevelTests | Code to retrieve collection level test code from GitHub |\n| code_getFolderLevelTests | Code to retrieve folder level test code from GitHub |\n| TestLibrary_collection | Code retrieved from GitHub and executed at runtime at the collection level. |\n| TestLibrary_folder | Code retrieved from GitHub and executed at runtime at the folder level. |", 6 | "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json", 7 | "_exporter_id": "23889826" 8 | }, 9 | "item": [ 10 | { 11 | "name": "Folder level tests", 12 | "item": [ 13 | { 14 | "name": "Collection, Folder, and Request level scripts", 15 | "event": [ 16 | { 17 | "listen": "prerequest", 18 | "script": { 19 | "exec": [ 20 | "eval(pm.collectionVariables.get(\"code_getFolderLevelTests\"));", 21 | "", 22 | "//uncomment this line to load the Folder level tests", 23 | "//eval(pm.collectionVariables.get(\"code_getFolderLevelTests\"));" 24 | ], 25 | "type": "text/javascript" 26 | } 27 | }, 28 | { 29 | "listen": "test", 30 | "script": { 31 | "exec": [ 32 | "//Additional Request level tests go here", 33 | "", 34 | "pm.test(\"REQUEST Status code is 200\", function () {", 35 | " pm.response.to.have.status(200);", 36 | "});" 37 | ], 38 | "type": "text/javascript" 39 | } 40 | } 41 | ], 42 | "request": { 43 | "method": "GET", 44 | "header": [], 45 | "url": { 46 | "raw": "https://postman-echo.com/get", 47 | "protocol": "https", 48 | "host": [ 49 | "postman-echo", 50 | "com" 51 | ], 52 | "path": [ 53 | "get" 54 | ] 55 | }, 56 | "description": "Runs reusable tests defined at the collection and folder level. Folder level tests are practical at the moment until it becomes possible to [identify the current folder](https://github.com/postmanlabs/postman-app-support/issues/6926) at runtime." 57 | }, 58 | "response": [] 59 | } 60 | ], 61 | "description": "Shows the possibilities around defining different reusable test snippets at the Folder level.", 62 | "event": [ 63 | { 64 | "listen": "prerequest", 65 | "script": { 66 | "type": "text/javascript", 67 | "exec": [ 68 | "//This will be much more useful once it becomes possible to determine the current folder name", 69 | "// https://github.com/postmanlabs/postman-app-support/issues/6926", 70 | "", 71 | "eval(pm.collectionVariables.get(\"code_getFolderLevelTests\"));", 72 | "", 73 | "" 74 | ] 75 | } 76 | }, 77 | { 78 | "listen": "test", 79 | "script": { 80 | "type": "text/javascript", 81 | "exec": [ 82 | "eval(pm.collectionVariables.get(\"TestLibrary_folder\"));" 83 | ] 84 | } 85 | } 86 | ] 87 | }, 88 | { 89 | "name": "Collection and Request Level Tests", 90 | "event": [ 91 | { 92 | "listen": "test", 93 | "script": { 94 | "exec": [ 95 | "pm.test(\"REQUEST Status code is 200\", function () {", 96 | " pm.response.to.have.status(200);", 97 | "});" 98 | ], 99 | "type": "text/javascript" 100 | } 101 | }, 102 | { 103 | "listen": "prerequest", 104 | "script": { 105 | "exec": [ 106 | "//Do nothing, the collection level tests will run" 107 | ], 108 | "type": "text/javascript" 109 | } 110 | } 111 | ], 112 | "request": { 113 | "method": "GET", 114 | "header": [], 115 | "url": { 116 | "raw": "https://postman-echo.com/get", 117 | "protocol": "https", 118 | "host": [ 119 | "postman-echo", 120 | "com" 121 | ], 122 | "path": [ 123 | "get" 124 | ] 125 | } 126 | }, 127 | "response": [] 128 | } 129 | ], 130 | "auth": { 131 | "type": "bearer", 132 | "bearer": [ 133 | { 134 | "key": "token", 135 | "value": "{{postmanAPIKey}}", 136 | "type": "string" 137 | } 138 | ] 139 | }, 140 | "event": [ 141 | { 142 | "listen": "prerequest", 143 | "script": { 144 | "type": "text/javascript", 145 | "exec": [ 146 | "eval(pm.collectionVariables.get(\"code_getCollectionLevelTests\"));", 147 | "", 148 | "" 149 | ] 150 | } 151 | }, 152 | { 153 | "listen": "test", 154 | "script": { 155 | "type": "text/javascript", 156 | "exec": [ 157 | "eval(pm.collectionVariables.get(\"TestLibrary_collection\"));", 158 | "", 159 | "" 160 | ] 161 | } 162 | } 163 | ], 164 | "variable": [ 165 | { 166 | "key": "GitHub_APIBaseURL", 167 | "value": "https://api.github.com", 168 | "type": "string" 169 | }, 170 | { 171 | "key": "GitHub_repoSlug", 172 | "value": "bryancross/postman-demo", 173 | "type": "string" 174 | }, 175 | { 176 | "key": "GitHub_collectionTestsPath", 177 | "value": "test-snippets/collection-level-tests.js", 178 | "type": "string" 179 | }, 180 | { 181 | "key": "GitHub_folderTestsPath", 182 | "value": "test-snippets/folder-level-tests.js", 183 | "type": "string" 184 | }, 185 | { 186 | "key": "code_getCollectionLevelTests", 187 | "value": "/*\n * Example showing the code to retrieve snippets from GitHub\n * at the collection level. Stored in the code_getCollectionLevelTests\n * environment variable\n*/\n//Setup the URL components\nvar owner = pm.collectionVariables.get(\"owner\");\nvar repoSlug = pm.collectionVariables.get(\"GitHub_repoSlug\");\nvar path = pm.collectionVariables.get(\"GitHub_collectionTestsPath\");\nvar token = pm.environment.get(\"GitHubPAT\");\nvar baseUrl = pm.collectionVariables.get(\"GitHub_APIBaseURL\");\n//Build the URL\nvar url = baseUrl + \"/repos/\" + repoSlug + \"/contents/\" + path;\nconsole.log(\"URL: \" + url);\nconst postRequest = {\n url: url,\n method: 'get',\n header: {\n 'Content-Type': 'application/json',\n 'Authorization': 'bearer ' + token\n }\n};\npm.sendRequest(postRequest, (err, res) => {\n var jsonData = JSON.parse(res.text());\nvar base64content = jsonData.content;\nvar buff = new Buffer(base64content, 'base64');\nvar content = buff.toString('ascii');\npm.collectionVariables.set(\"TestLibrary_collection\", content);\n});", 188 | "type": "string" 189 | }, 190 | { 191 | "key": "code_getFolderLevelTests", 192 | "value": "/*\n * Example showing the code to retrieve snippets from GitHub\n * at the collection level. Stored in the code_getCollectionLevelTests\n * environment variable\n*/\n//Setup the URL components\nvar owner = pm.collectionVariables.get(\"owner\");\nvar repoSlug = pm.collectionVariables.get(\"GitHub_repoSlug\");\nvar path = pm.collectionVariables.get(\"GitHub_folderTestsPath\");\nvar token = pm.environment.get(\"GitHubPAT\");\nvar baseUrl = pm.collectionVariables.get(\"GitHub_APIBaseURL\");\n//Build the URL\nvar url = baseUrl + \"/repos/\" + repoSlug + \"/contents/\" + path;\nconsole.log(\"URL: \" + url);\nconst postRequest = {\n url: url,\n method: 'get',\n header: {\n 'Content-Type': 'application/json',\n 'Authorization': 'bearer ' + token\n }\n};\npm.sendRequest(postRequest, (err, res) => {\n var jsonData = JSON.parse(res.text());\nvar base64content = jsonData.content;\nvar buff = new Buffer(base64content, 'base64');\nvar content = buff.toString('ascii');\npm.collectionVariables.set(\"TestLibrary_folder\", content);\n});", 193 | "type": "string" 194 | }, 195 | { 196 | "key": "TestLibrary_collection", 197 | "value": "<>" 198 | }, 199 | { 200 | "key": "TestLibrary_folder", 201 | "value": "<>", 202 | "type": "string" 203 | } 204 | ] 205 | } -------------------------------------------------------------------------------- /src/main/java/com/postman/collection/Item.java: -------------------------------------------------------------------------------- 1 | package com.postman.collection; 2 | import java.util.ArrayList; 3 | /** 4 | * 5 | * Encapsulates the item object in the postman schema 6 | * 7 | *

Postman SDK analog: Item.

8 | 9 | *
 10 |      * {
 11 |     "name": "Get a list of facts",
 12 | 
 13 |     "event": [
 14 |         {
 15 |             "listen": "test",
 16 |             "script": {
 17 |                 "exec": [
 18 |                     "pm.test(\"Status code is 200\", function () {",
 19 |                     "    pm.response.to.have.status(200);",
 20 |                     "});",
 21 |                     "",
 22 |                     "var latencyTestName = \"Response time is less than \" + pm.collectionVariables.get(\"latencyLimit\") + \" ms\";",
 23 |                     "",
 24 |                     "pm.test(latencyTestName, function () {",
 25 |                     "    pm.expect(pm.response.responseTime).to.be.below(parseInt(pm.collectionVariables.get(\"latencyLimit\")));",
 26 |                     "});",
 27 |                     "",
 28 |                     "pm.test(\"Response contains fact\", function () {",
 29 |                     "    var jsonData = pm.response.json();",
 30 |                     "    pm.expect(pm.response.json().length).to.be.greaterThan(1);",
 31 |                     "});"
 32 |                 ],
 33 |                 "type": "text/javascript"
 34 |             }
 35 |         },
 36 |         {
 37 |             "listen": "prerequest",
 38 |             "script": {
 39 |                 "exec": [
 40 |                     "console.log(\"last fact: \" + pm.collectionVariables.get(\"curFact\"));"
 41 |                 ],
 42 |                 "type": "text/javascript"
 43 |             }
 44 |         }
 45 |     ],
 46 |     
 47 |     "request": {
 48 |         "method": "GET",
 49 |         "header": [
 50 |             {
 51 |                 "key": "Accept",
 52 |                 "value": "application/json"
 53 |             }
 54 |         ],
 55 |         "url": {
 56 |             "raw": "{{baseUrl}}/facts?max_length=200&limit=2",
 57 |             "host": [
 58 |                 "{{baseUrl}}"
 59 |             ],
 60 |             "path": [
 61 |                 "facts"
 62 |             ],
 63 |             "query": [
 64 |                 {
 65 |                     "key": "max_length",
 66 |                     "value": "200"
 67 |                 },
 68 |                 {
 69 |                     "key": "limit",
 70 |                     "value": "2",
 71 |                     "description": "limit the amount of results returned"
 72 |                 }
 73 |             ]
 74 |         },
 75 |         "description": "Returns a a list of facts"
 76 |     },
 77 |     "response": [
 78 |         {
 79 |             "name": "successful operation",
 80 |             "originalRequest": {
 81 |                 "method": "GET",
 82 |                 "header": [],
 83 |                 "url": {
 84 |                     "raw": "{{baseUrl}}/facts?max_length=200&limit=2",
 85 |                     "host": [
 86 |                         "{{baseUrl}}"
 87 |                     ],
 88 |                     "path": [
 89 |                         "facts"
 90 |                     ],
 91 |                     "query": [
 92 |                         {
 93 |                             "key": "max_length",
 94 |                             "value": "200"
 95 |                         },
 96 |                         {
 97 |                             "key": "limit",
 98 |                             "value": "2"
 99 |                         }
100 |                     ]
101 |                 }
102 |             },
103 |             "status": "OK",
104 |             "code": 200,
105 |             "_postman_previewlanguage": "json",
106 |             "header": [
107 |                 {
108 |                     "key": "Content-Type",
109 |                     "value": "application/json"
110 |                 }
111 |             ],
112 |             "cookie": [],
113 |             "body": "[\n  {\n    \"fact\": \"ex ad\",\n    \"length\": 200\n  }, (...)}\n]"
114 |         }
115 |     ]
116 | }
117 | ],
118 | "description": "Cat Facts"
119 | 
120 | }
121 | 
122 | 123 | 124 | Hierarchy 125 | 126 |

Folders and requests are both items. An item with no request property is rendered by the Postman UI as a Folder. Items with a request property 127 | are rendered as requests. Folders can contain other items, both folders and requests. Requests are always leaf nodes, they cannot contain other items.

128 | 129 |

A collection is the top level item in the hierarchy. It can contain a tree of items, but cannot itself be contained.

130 | 131 | */ 132 | public abstract class Item extends CollectionElement { 133 | 134 | private String description; 135 | private ArrayList event = null; 136 | private String name; 137 | 138 | 139 | private transient ItemGroup parent = null; 140 | 141 | 142 | 143 | protected Item() { 144 | 145 | } 146 | /** 147 | * 148 | * 149 | * Construct an empty item with only a name property and assign it as a child of parent 150 | * 151 | * @param name The name of the object 152 | * @param parent The Item containing this item. 153 | */ 154 | protected Item(String name, ItemGroup parent) { 155 | this(name); 156 | this.setParent(parent); 157 | 158 | } 159 | /** 160 | * * Construct an empty item with only a name>; property. Once added to a Collection, the Postman UI will render this object as an empty folder. 161 | 162 | * @param name The name of the object 163 | */ 164 | 165 | protected Item(String name) { 166 | this.setName(name); 167 | } 168 | 169 | 170 | 171 | /** 172 | * 173 | * Return the value of the description property 174 | * 175 | * @return String The description 176 | */ 177 | public String getDescription() { 178 | return description; 179 | } 180 | 181 | 182 | /** 183 | * 184 | * Set the value of the description property 185 | * 186 | * 187 | * @param description The description 188 | */ 189 | public void setDescription(String description) { 190 | this.description = description; 191 | } 192 | 193 | 194 | /** 195 | * 196 | * Return the ArrayList<Event> containing the objects comprising the event array 197 | * 198 | * @return ArrayList<Event> 199 | */ 200 | public ArrayList getEvents() { 201 | 202 | return event; 203 | } 204 | 205 | 206 | /** 207 | * 208 | * Get an event, specifying whether to return the pre-request script or test script associated with this item. 209 | * 210 | * 211 | * @param evtType Enumerated value for the event type, eg., pre-request or test. 212 | * @return Event The event, if it exists 213 | */ 214 | public Event getEvent(enumEventType evtType) { 215 | if (event == null) { 216 | return null; 217 | } 218 | for (int i = 0; i < event.size(); i++) { 219 | if (event.get(i).getEventType() == evtType) { 220 | return event.get(i); 221 | } 222 | } 223 | return null; 224 | } 225 | 226 | 227 | /** 228 | * Set the ArrayList<Event> comprising the values in the event array. 229 | * 230 | * @param events 231 | */ 232 | public void setEvents(ArrayList events) { 233 | this.event = events; 234 | } 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | /** 243 | * 244 | * Set the parent of this item. 245 | * 246 | * @param parent The parent item. 247 | */ 248 | public void setParent(ItemGroup parent) { 249 | this.parent = parent; 250 | } 251 | 252 | 253 | /** 254 | * 255 | * Get the parent of this item, or null if one is not defined (eg. this item is a collection); 256 | * 257 | * @return Item The parent item. 258 | */ 259 | @Override 260 | public ItemGroup getParent() { 261 | return this.parent; 262 | } 263 | 264 | 265 | 266 | 267 | 268 | 269 | /** 270 | * 271 | * Add an event to the array of items in the event property 272 | * 273 | * @param newEvent 274 | */ 275 | private void addEvent(Event newEvent) { 276 | if (event == null) { 277 | event = new ArrayList(); 278 | } 279 | if (this.getEvent(newEvent.getEventType()) == null) { 280 | event.add(newEvent); 281 | } else { 282 | event.remove(this.getEvent(newEvent.getEventType())); 283 | event.add(newEvent); 284 | } 285 | } 286 | 287 | 288 | 289 | /** 290 | * 291 | * Set the pre-request script for this item in the event array 292 | * 293 | * @param code The source code for the script 294 | * 295 | */ 296 | public void setPreRequestScript(String code) { 297 | 298 | Event prEvent = new Event(enumEventType.PRE_REQUEST, code); 299 | this.addEvent(prEvent); 300 | } 301 | 302 | 303 | /** 304 | * @return Event 305 | */ 306 | public Event getPreRequestScript() { 307 | return this.getEvent(enumEventType.PRE_REQUEST); 308 | } 309 | 310 | 311 | /** 312 | * @return Event 313 | */ 314 | public Event getTestScript() { 315 | return this.getEvent(enumEventType.TEST); 316 | } 317 | 318 | 319 | /** 320 | * Set the test script for this item in the event array 321 | * 322 | * @param code The source code for the script 323 | * 324 | */ 325 | public void setTestScript(String code) { 326 | 327 | Event prEvent = new Event(enumEventType.TEST, code); 328 | this.addEvent(prEvent); 329 | } 330 | 331 | 332 | 333 | /** 334 | * @return String 335 | */ 336 | public String getName() { 337 | return this.name; 338 | } 339 | 340 | 341 | /** 342 | * @param name 343 | */ 344 | public void setName(String name) { 345 | this.name = name; 346 | } 347 | /** 348 | * @return String 349 | */ 350 | @Override 351 | public String getKey() { 352 | 353 | return this.getName(); 354 | } 355 | 356 | 357 | 358 | 359 | 360 | } 361 | -------------------------------------------------------------------------------- /src/main/resources/com/postman/collection/example-cat-facts-with-tests.postman_collection.json: -------------------------------------------------------------------------------- 1 | { 2 | "info": { 3 | "_postman_id": "9de02cc3-33a8-4b7b-96a8-9ad727277e39", 4 | "name": "CatFacts Two TEST", 5 | "description": "Contact Support:\n Email: contact@catfact.ninja", 6 | "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json", 7 | "_exporter_id": "23889826" 8 | }, 9 | "item": [ 10 | { 11 | "name": "Facts", 12 | "item": [ 13 | { 14 | "name": "get Random Fact", 15 | "event": [ 16 | { 17 | "listen": "test", 18 | "script": { 19 | "exec": [ 20 | "pm.test(\"Status code is 200\", function () {", 21 | " pm.response.to.have.status(200);", 22 | "});", 23 | "", 24 | "var latencyTestName = \"Response time is less than \" + pm.collectionVariables.get(\"latencyLimit\") + \" ms\";", 25 | "", 26 | "pm.test(latencyTestName, function () {", 27 | " pm.expect(pm.response.responseTime).to.be.below(parseInt(pm.collectionVariables.get(\"latencyLimit\")));", 28 | "});", 29 | "", 30 | "pm.test(\"Response contains fact\", function () {", 31 | " var jsonData = pm.response.json();", 32 | " pm.expect(pm.response.json().fact).not.to.be.null;", 33 | "});", 34 | "", 35 | "pm.collectionVariables.set(\"curFact\",pm.response.json().fact);" 36 | ], 37 | "type": "text/javascript" 38 | } 39 | } 40 | ], 41 | "request": { 42 | "method": "GET", 43 | "header": [ 44 | { 45 | "key": "Accept", 46 | "value": "application/json" 47 | } 48 | ], 49 | "url": { 50 | "raw": "{{baseUrl}}/fact?max_length=200", 51 | "host": [ 52 | "{{baseUrl}}" 53 | ], 54 | "path": [ 55 | "fact" 56 | ], 57 | "query": [ 58 | { 59 | "key": "max_length", 60 | "value": "200", 61 | "description": "maximum length of returned fact" 62 | } 63 | ] 64 | }, 65 | "description": "## Get Random Fact:\n\nDoes what it says, returns a random fact" 66 | }, 67 | "response": [ 68 | { 69 | "name": "Normal response", 70 | "originalRequest": { 71 | "method": "GET", 72 | "header": [], 73 | "url": { 74 | "raw": "{{baseUrl}}/fact?max_length=200", 75 | "host": [ 76 | "{{baseUrl}}" 77 | ], 78 | "path": [ 79 | "fact" 80 | ], 81 | "query": [ 82 | { 83 | "key": "max_length", 84 | "value": "200" 85 | } 86 | ] 87 | } 88 | }, 89 | "status": "OK", 90 | "code": 200, 91 | "_postman_previewlanguage": "json", 92 | "header": [ 93 | { 94 | "key": "Content-Type", 95 | "value": "application/json" 96 | } 97 | ], 98 | "cookie": [], 99 | "body": "{\n \"fact\": \"in tempor Excepteur eiusmod\",\n \"length\": 200\n}" 100 | }, 101 | { 102 | "name": "Fact not found", 103 | "originalRequest": { 104 | "method": "GET", 105 | "header": [], 106 | "url": { 107 | "raw": "{{baseUrl}}/fact?max_length=200", 108 | "host": [ 109 | "{{baseUrl}}" 110 | ], 111 | "path": [ 112 | "fact" 113 | ], 114 | "query": [ 115 | { 116 | "key": "max_length", 117 | "value": "200" 118 | } 119 | ] 120 | } 121 | }, 122 | "status": "Not Found", 123 | "code": 404, 124 | "_postman_previewlanguage": "text", 125 | "header": [ 126 | { 127 | "key": "Content-Type", 128 | "value": "text/plain" 129 | } 130 | ], 131 | "cookie": [], 132 | "body": "" 133 | } 134 | ] 135 | }, 136 | { 137 | "name": "Get a list of facts", 138 | "event": [ 139 | { 140 | "listen": "test", 141 | "script": { 142 | "exec": [ 143 | "pm.test(\"Status code is 200\", function () {", 144 | " pm.response.to.have.status(200);", 145 | "});", 146 | "", 147 | "var latencyTestName = \"Response time is less than \" + pm.collectionVariables.get(\"latencyLimit\") + \" ms\";", 148 | "", 149 | "pm.test(latencyTestName, function () {", 150 | " pm.expect(pm.response.responseTime).to.be.below(parseInt(pm.collectionVariables.get(\"latencyLimit\")));", 151 | "});", 152 | "", 153 | "pm.test(\"Response contains fact\", function () {", 154 | " var jsonData = pm.response.json();", 155 | " pm.expect(pm.response.json().length).to.be.greaterThan(1);", 156 | "});" 157 | ], 158 | "type": "text/javascript" 159 | } 160 | }, 161 | { 162 | "listen": "prerequest", 163 | "script": { 164 | "exec": [ 165 | "console.log(\"last fact: \" + pm.collectionVariables.get(\"curFact\"));" 166 | ], 167 | "type": "text/javascript" 168 | } 169 | } 170 | ], 171 | "request": { 172 | "method": "GET", 173 | "header": [ 174 | { 175 | "key": "Accept", 176 | "value": "application/json" 177 | } 178 | ], 179 | "url": { 180 | "raw": "{{baseUrl}}/facts?max_length=200&limit=2", 181 | "host": [ 182 | "{{baseUrl}}" 183 | ], 184 | "path": [ 185 | "facts" 186 | ], 187 | "query": [ 188 | { 189 | "key": "max_length", 190 | "value": "200" 191 | }, 192 | { 193 | "key": "limit", 194 | "value": "2", 195 | "description": "limit the amount of results returned" 196 | } 197 | ] 198 | }, 199 | "description": "Returns a a list of facts" 200 | }, 201 | "response": [ 202 | { 203 | "name": "successful operation", 204 | "originalRequest": { 205 | "method": "GET", 206 | "header": [], 207 | "url": { 208 | "raw": "{{baseUrl}}/facts?max_length=200&limit=2", 209 | "host": [ 210 | "{{baseUrl}}" 211 | ], 212 | "path": [ 213 | "facts" 214 | ], 215 | "query": [ 216 | { 217 | "key": "max_length", 218 | "value": "200" 219 | }, 220 | { 221 | "key": "limit", 222 | "value": "2" 223 | } 224 | ] 225 | } 226 | }, 227 | "status": "OK", 228 | "code": 200, 229 | "_postman_previewlanguage": "json", 230 | "header": [ 231 | { 232 | "key": "Content-Type", 233 | "value": "application/json" 234 | } 235 | ], 236 | "cookie": [], 237 | "body": "[\n {\n \"fact\": \"ex ad\",\n \"length\": 200\n },\n {\n \"fact\": \"Ut dolor exercitation quis\",\n \"length\": 200\n }\n]" 238 | } 239 | ] 240 | } 241 | ], 242 | "description": "Cat Facts" 243 | }, 244 | { 245 | "name": "Breeds", 246 | "item": [ 247 | { 248 | "name": "get Breeds", 249 | "event": [ 250 | { 251 | "listen": "test", 252 | "script": { 253 | "exec": [ 254 | "pm.test(\"Status code is 200\", function () {", 255 | " pm.response.to.have.status(200);", 256 | "});", 257 | "", 258 | "var latencyTestName = \"Response time is less than \" + pm.collectionVariables.get(\"latencyLimit\") + \" ms\";", 259 | "", 260 | "pm.test(latencyTestName, function () {", 261 | " pm.expect(pm.response.responseTime).to.be.below(parseInt(pm.collectionVariables.get(\"latencyLimit\")));", 262 | "});", 263 | "", 264 | "", 265 | "pm.test(\"Response contains fact\", function () {", 266 | " var jsonData = pm.response.json();", 267 | " pm.expect(pm.response.json().length).to.be.greaterThan(1);", 268 | "});" 269 | ], 270 | "type": "text/javascript" 271 | } 272 | } 273 | ], 274 | "request": { 275 | "method": "GET", 276 | "header": [ 277 | { 278 | "key": "Accept", 279 | "value": "application/json" 280 | } 281 | ], 282 | "url": { 283 | "raw": "{{baseUrl}}/breeds?limit=2", 284 | "host": [ 285 | "{{baseUrl}}" 286 | ], 287 | "path": [ 288 | "breeds" 289 | ], 290 | "query": [ 291 | { 292 | "key": "limit", 293 | "value": "2", 294 | "description": "This is a description" 295 | } 296 | ] 297 | }, 298 | "description": "Returns a a list of breeds" 299 | }, 300 | "response": [ 301 | { 302 | "name": "Normal operation", 303 | "originalRequest": { 304 | "method": "GET", 305 | "header": [], 306 | "url": { 307 | "raw": "{{baseUrl}}/breeds?limit=2", 308 | "host": [ 309 | "{{baseUrl}}" 310 | ], 311 | "path": [ 312 | "breeds" 313 | ], 314 | "query": [ 315 | { 316 | "key": "limit", 317 | "value": "2" 318 | } 319 | ] 320 | } 321 | }, 322 | "status": "OK", 323 | "code": 200, 324 | "_postman_previewlanguage": "json", 325 | "header": [ 326 | { 327 | "key": "Content-Type", 328 | "value": "application/json" 329 | } 330 | ], 331 | "cookie": [], 332 | "body": "[\n {\n \"breed\": \"nulla nisi mollit laborum\",\n \"country\": \"anim et\",\n \"origin\": \"esse in incididunt\",\n \"coat\": \"aliqua amet sed pariatu\",\n \"pattern\": \"sed\"\n },\n {\n \"breed\": \"minim consectetur aliqua\",\n \"country\": \"ullamco proident dolor dolor pariatur\",\n \"origin\": \"dolor \",\n \"coat\": \"anim incididunt\",\n \"pattern\": \"nulla Excepteur in mollit\"\n }\n]" 333 | } 334 | ] 335 | } 336 | ], 337 | "description": "Breeds" 338 | } 339 | ], 340 | "event": [ 341 | { 342 | "listen": "prerequest", 343 | "script": { 344 | "type": "text/javascript", 345 | "exec": [ 346 | "" 347 | ] 348 | } 349 | }, 350 | { 351 | "listen": "test", 352 | "script": { 353 | "type": "text/javascript", 354 | "exec": [ 355 | "" 356 | ] 357 | } 358 | } 359 | ], 360 | "variable": [ 361 | { 362 | "key": "baseUrl", 363 | "value": "https://f653ab18-2f67-42d4-9ac2-d404779d7b24.mock.pstmn.io", 364 | "type": "string" 365 | }, 366 | { 367 | "key": "latencyLimit", 368 | "value": "800", 369 | "type": "string" 370 | }, 371 | { 372 | "key": "curFact", 373 | "value": "" 374 | } 375 | ] 376 | } -------------------------------------------------------------------------------- /src/main/resources/com/postman/collection/example-catfact.postman_collection.json: -------------------------------------------------------------------------------- 1 | { 2 | "info": { 3 | "_postman_id": "9029c796-2aae-40bc-9f3c-c4f8a892ebe4", 4 | "name": "Cat Fact", 5 | "description": "Contact Support:\n Email: contact@catfact.ninja", 6 | "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json", 7 | "_exporter_id": "23889826" 8 | }, 9 | "item": [ 10 | { 11 | "name": "Facts", 12 | "item": [ 13 | { 14 | "name": "get Random Fact", 15 | "event": [ 16 | { 17 | "listen": "test", 18 | "script": { 19 | "exec": [ 20 | "pm.test(\"Status code is 200\", function () {", 21 | " pm.response.to.have.status(200);", 22 | "});", 23 | "pm.test(\"Response time is less than 800ms\", function () {", 24 | " pm.expect(pm.response.responseTime).to.be.below(800);", 25 | "});" 26 | ], 27 | "type": "text/javascript" 28 | } 29 | } 30 | ], 31 | "request": { 32 | "method": "GET", 33 | "header": [ 34 | { 35 | "key": "Accept", 36 | "value": "application/json" 37 | }, 38 | { 39 | "key": "Header-1", 40 | "value": "Header-1value", 41 | "description": "This is header 1", 42 | "type": "text" 43 | }, 44 | { 45 | "key": "Header-2", 46 | "value": "Header-2value", 47 | "description": "This is header 2", 48 | "type": "text" 49 | } 50 | ], 51 | "url": { 52 | "raw": "{{baseUrl}}/fact?max_length=200", 53 | "host": [ 54 | "{{baseUrl}}" 55 | ], 56 | "path": [ 57 | "fact" 58 | ], 59 | "query": [ 60 | { 61 | "key": "max_length", 62 | "value": "200", 63 | "description": "maximum length of returned fact" 64 | } 65 | ] 66 | }, 67 | "description": "Returns a random fact\n\nThis is documentation added in the collection editor" 68 | }, 69 | "response": [ 70 | { 71 | "name": "Normal response", 72 | "originalRequest": { 73 | "method": "GET", 74 | "header": [], 75 | "url": { 76 | "raw": "{{baseUrl}}/fact?max_length=200", 77 | "host": [ 78 | "{{baseUrl}}" 79 | ], 80 | "path": [ 81 | "fact" 82 | ], 83 | "query": [ 84 | { 85 | "key": "max_length", 86 | "value": "200" 87 | } 88 | ] 89 | } 90 | }, 91 | "status": "OK", 92 | "code": 200, 93 | "_postman_previewlanguage": "json", 94 | "header": [ 95 | { 96 | "key": "Content-Type", 97 | "value": "application/json" 98 | } 99 | ], 100 | "cookie": [], 101 | "body": "{\n \"fact\": \"adipisicing cillum ullamco consectetur dolore\",\n \"length\": 200\n}" 102 | }, 103 | { 104 | "name": "Fact not found", 105 | "originalRequest": { 106 | "method": "GET", 107 | "header": [], 108 | "url": { 109 | "raw": "{{baseUrl}}/fact?max_length=200", 110 | "host": [ 111 | "{{baseUrl}}" 112 | ], 113 | "path": [ 114 | "fact" 115 | ], 116 | "query": [ 117 | { 118 | "key": "max_length", 119 | "value": "200" 120 | } 121 | ] 122 | } 123 | }, 124 | "status": "Not Found", 125 | "code": 404, 126 | "_postman_previewlanguage": "text", 127 | "header": [ 128 | { 129 | "key": "Content-Type", 130 | "value": "text/plain" 131 | } 132 | ], 133 | "cookie": [], 134 | "body": "" 135 | } 136 | ] 137 | }, 138 | { 139 | "name": "Get a list of facts", 140 | "request": { 141 | "method": "GET", 142 | "header": [ 143 | { 144 | "key": "Accept", 145 | "value": "application/json" 146 | } 147 | ], 148 | "url": { 149 | "raw": "{{baseUrl}}/facts?max_length=200&limit=2", 150 | "host": [ 151 | "{{baseUrl}}" 152 | ], 153 | "path": [ 154 | "facts" 155 | ], 156 | "query": [ 157 | { 158 | "key": "max_length", 159 | "value": "200" 160 | }, 161 | { 162 | "key": "limit", 163 | "value": "2", 164 | "description": "limit the amount of results returned" 165 | } 166 | ] 167 | }, 168 | "description": "Returns a a list of facts\n\nTHis is additional documentation added in the c ollection editor" 169 | }, 170 | "response": [ 171 | { 172 | "name": "successful operation", 173 | "originalRequest": { 174 | "method": "GET", 175 | "header": [], 176 | "url": { 177 | "raw": "{{baseUrl}}/facts?max_length=200&limit=2", 178 | "host": [ 179 | "{{baseUrl}}" 180 | ], 181 | "path": [ 182 | "facts" 183 | ], 184 | "query": [ 185 | { 186 | "key": "max_length", 187 | "value": "200" 188 | }, 189 | { 190 | "key": "limit", 191 | "value": "2" 192 | } 193 | ] 194 | } 195 | }, 196 | "status": "OK", 197 | "code": 200, 198 | "_postman_previewlanguage": "json", 199 | "header": [ 200 | { 201 | "key": "Content-Type", 202 | "value": "application/json" 203 | } 204 | ], 205 | "cookie": [], 206 | "body": "[\n {\n \"fact\": \"Lorem eiusmod culpa amet in\",\n \"length\": 200\n },\n {\n \"fact\": \"in\",\n \"length\": 200\n }\n]" 207 | } 208 | ] 209 | }, 210 | { 211 | "name": "Get a Specific Fact", 212 | "request": { 213 | "method": "GET", 214 | "header": [], 215 | "url": { 216 | "raw": "{{baseUrl}}/facts/:factID", 217 | "host": [ 218 | "{{baseUrl}}" 219 | ], 220 | "path": [ 221 | "facts", 222 | ":factID" 223 | ], 224 | "variable": [ 225 | { 226 | "key": "factID", 227 | "value": null 228 | } 229 | ] 230 | } 231 | }, 232 | "response": [] 233 | } 234 | ], 235 | "description": "Cat Facts", 236 | "event": [ 237 | { 238 | "listen": "prerequest", 239 | "script": { 240 | "type": "text/javascript", 241 | "exec": [ 242 | "//This is a folder PR Script" 243 | ] 244 | } 245 | }, 246 | { 247 | "listen": "test", 248 | "script": { 249 | "type": "text/javascript", 250 | "exec": [ 251 | "//THis is a folder test" 252 | ] 253 | } 254 | } 255 | ] 256 | }, 257 | { 258 | "name": "Breeds", 259 | "item": [ 260 | { 261 | "name": "get Breeds", 262 | "request": { 263 | "method": "GET", 264 | "header": [ 265 | { 266 | "key": "Accept", 267 | "value": "application/json" 268 | } 269 | ], 270 | "url": { 271 | "raw": "https://catfact.ninja/breeds?limit=2&foo={{foobar}}", 272 | "protocol": "https", 273 | "host": [ 274 | "catfact", 275 | "ninja" 276 | ], 277 | "path": [ 278 | "breeds" 279 | ], 280 | "query": [ 281 | { 282 | "key": "limit", 283 | "value": "2", 284 | "description": "This is a description" 285 | }, 286 | { 287 | "key": "foo", 288 | "value": "{{foobar}}", 289 | "description": "THis is the foo thing" 290 | } 291 | ] 292 | }, 293 | "description": "Returns a a list of breeds" 294 | }, 295 | "response": [ 296 | { 297 | "name": "Normal operation", 298 | "originalRequest": { 299 | "method": "GET", 300 | "header": [], 301 | "url": { 302 | "raw": "{{baseUrl}}/breeds?limit=2", 303 | "host": [ 304 | "{{baseUrl}}" 305 | ], 306 | "path": [ 307 | "breeds" 308 | ], 309 | "query": [ 310 | { 311 | "key": "limit", 312 | "value": "2" 313 | } 314 | ] 315 | } 316 | }, 317 | "status": "OK", 318 | "code": 200, 319 | "_postman_previewlanguage": "json", 320 | "header": [ 321 | { 322 | "key": "Content-Type", 323 | "value": "application/json" 324 | } 325 | ], 326 | "cookie": [], 327 | "body": "[\n {\n \"breed\": \"Excepteur d\",\n \"country\": \"ad consequ\",\n \"origin\": \"deserunt dolore\",\n \"coat\": \"consectetur officia dolore ut irure\",\n \"pattern\": \"nulla ea tempor magna\"\n },\n {\n \"breed\": \"ex nisi\",\n \"country\": \"dolor dolore c\",\n \"origin\": \"aute incididunt dolor Ut\",\n \"coat\": \"nulla ut sit eu Duis\",\n \"pattern\": \"cupidat\"\n }\n]" 328 | } 329 | ] 330 | }, 331 | { 332 | "name": "Add Breed", 333 | "request": { 334 | "method": "POST", 335 | "header": [], 336 | "body": { 337 | "mode": "raw", 338 | "raw": "{\n \"breed\": \"Epoxy\",\n \"country\": \"HomeDepot\",\n \"origin\": \"Artificial\",\n \"coat\": \"Sticky\",\n \"pattern\": \"Random\"\n },", 339 | "options": { 340 | "raw": { 341 | "language": "json" 342 | } 343 | } 344 | }, 345 | "url": { 346 | "raw": "https://catfact.ninja/breeds", 347 | "protocol": "https", 348 | "host": [ 349 | "catfact", 350 | "ninja" 351 | ], 352 | "path": [ 353 | "breeds" 354 | ] 355 | } 356 | }, 357 | "response": [] 358 | } 359 | ], 360 | "description": "Breeds" 361 | } 362 | ], 363 | "auth": { 364 | "type": "apikey", 365 | "apikey": [ 366 | { 367 | "key": "value", 368 | "value": "{{fakeAPIKey}}", 369 | "type": "string" 370 | }, 371 | { 372 | "key": "key", 373 | "value": "x-api-key", 374 | "type": "string" 375 | } 376 | ] 377 | }, 378 | "event": [ 379 | { 380 | "listen": "prerequest", 381 | "script": { 382 | "type": "text/javascript", 383 | "exec": [ 384 | "//Collection PR Script" 385 | ] 386 | } 387 | }, 388 | { 389 | "listen": "test", 390 | "script": { 391 | "type": "text/javascript", 392 | "exec": [ 393 | "//Collection Test Script" 394 | ] 395 | } 396 | } 397 | ], 398 | "variable": [ 399 | { 400 | "key": "baseUrl", 401 | "value": "https://f653ab18-2f67-42d4-9ac2-d404779d7b24.mock.pstmn.io", 402 | "type": "string" 403 | }, 404 | { 405 | "key": "foobar", 406 | "value": "This is the foo value", 407 | "type": "string" 408 | }, 409 | { 410 | "key": "testUrl", 411 | "value": "https://foobarbat.com", 412 | "type": "string" 413 | }, 414 | { 415 | "key": "fakeAPIKey", 416 | "value": "122", 417 | "type": "string" 418 | } 419 | ] 420 | } -------------------------------------------------------------------------------- /src/main/resources/com/postman/collection/example-lots-of-variables.postman_collection.json: -------------------------------------------------------------------------------- 1 | { 2 | "info": { 3 | "_postman_id": "54dfd5b0-4288-445a-bff4-8da0c045d0b0", 4 | "name": "VARIABLES lots of", 5 | "description": "Contact Support:\n Email: contact@catfact.ninja", 6 | "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json", 7 | "_exporter_id": "23889826" 8 | }, 9 | "item": [ 10 | { 11 | "name": "Facts", 12 | "item": [ 13 | { 14 | "name": "get Random Fact", 15 | "event": [ 16 | { 17 | "listen": "test", 18 | "script": { 19 | "exec": [ 20 | "pm.test(\"Status code is 200\", function () {", 21 | " pm.response.to.have.status(200);", 22 | "});", 23 | "pm.test(\"Response time is less than 800ms\", function () {", 24 | " pm.expect(pm.response.responseTime).to.be.below(800);", 25 | "});" 26 | ], 27 | "type": "text/javascript" 28 | } 29 | } 30 | ], 31 | "request": { 32 | "method": "GET", 33 | "header": [ 34 | { 35 | "key": "Accept", 36 | "value": "application/json" 37 | }, 38 | { 39 | "key": "Header-1", 40 | "value": "Header-1value", 41 | "description": "This is header 1", 42 | "type": "text" 43 | }, 44 | { 45 | "key": "Header-2", 46 | "value": "Header-2value", 47 | "description": "This is header 2", 48 | "type": "text" 49 | } 50 | ], 51 | "url": { 52 | "raw": "{{baseUrl}}/{{var2}}/:path1/bat.json?{{var1}}={{var2}}", 53 | "host": [ 54 | "{{baseUrl}}" 55 | ], 56 | "path": [ 57 | "var2", 58 | ":path1", 59 | "path1value" 60 | ], 61 | "query": [ 62 | { 63 | "key": "{{var1}}", 64 | "value": "{{var2}}" 65 | } 66 | ], 67 | "variable": [ 68 | { 69 | "key": "path1", 70 | "value": "path1value" 71 | } 72 | ] 73 | }, 74 | "description": "Returns a random fact\n\nThis is documentation added in the collection editor" 75 | }, 76 | "response": [ 77 | { 78 | "name": "Normal response", 79 | "originalRequest": { 80 | "method": "GET", 81 | "header": [], 82 | "url": { 83 | "raw": "{{baseUrl}}/fact?max_length=200", 84 | "host": [ 85 | "{{baseUrl}}" 86 | ], 87 | "path": [ 88 | "fact" 89 | ], 90 | "query": [ 91 | { 92 | "key": "max_length", 93 | "value": "200" 94 | } 95 | ] 96 | } 97 | }, 98 | "status": "OK", 99 | "code": 200, 100 | "_postman_previewlanguage": "json", 101 | "header": [ 102 | { 103 | "key": "Content-Type", 104 | "value": "application/json" 105 | } 106 | ], 107 | "cookie": [], 108 | "body": "{\n \"fact\": \"adipisicing cillum ullamco consectetur dolore\",\n \"length\": 200\n}" 109 | }, 110 | { 111 | "name": "Fact not found", 112 | "originalRequest": { 113 | "method": "GET", 114 | "header": [], 115 | "url": { 116 | "raw": "{{baseUrl}}/fact?max_length=200", 117 | "host": [ 118 | "{{baseUrl}}" 119 | ], 120 | "path": [ 121 | "fact" 122 | ], 123 | "query": [ 124 | { 125 | "key": "max_length", 126 | "value": "200" 127 | } 128 | ] 129 | } 130 | }, 131 | "status": "Not Found", 132 | "code": 404, 133 | "_postman_previewlanguage": "text", 134 | "header": [ 135 | { 136 | "key": "Content-Type", 137 | "value": "text/plain" 138 | } 139 | ], 140 | "cookie": [], 141 | "body": "" 142 | } 143 | ] 144 | }, 145 | { 146 | "name": "Get a list of facts", 147 | "request": { 148 | "method": "GET", 149 | "header": [ 150 | { 151 | "key": "Accept", 152 | "value": "application/json" 153 | } 154 | ], 155 | "url": { 156 | "raw": "{{baseUrl}}/facts?max_length=200&limit=2", 157 | "host": [ 158 | "{{baseUrl}}" 159 | ], 160 | "path": [ 161 | "facts" 162 | ], 163 | "query": [ 164 | { 165 | "key": "max_length", 166 | "value": "200" 167 | }, 168 | { 169 | "key": "limit", 170 | "value": "2", 171 | "description": "limit the amount of results returned" 172 | } 173 | ] 174 | }, 175 | "description": "Returns a a list of facts\n\nTHis is additional documentation added in the c ollection editor" 176 | }, 177 | "response": [ 178 | { 179 | "name": "successful operation", 180 | "originalRequest": { 181 | "method": "GET", 182 | "header": [], 183 | "url": { 184 | "raw": "{{baseUrl}}/facts?max_length=200&limit=2", 185 | "host": [ 186 | "{{baseUrl}}" 187 | ], 188 | "path": [ 189 | "facts" 190 | ], 191 | "query": [ 192 | { 193 | "key": "max_length", 194 | "value": "200" 195 | }, 196 | { 197 | "key": "limit", 198 | "value": "2" 199 | } 200 | ] 201 | } 202 | }, 203 | "status": "OK", 204 | "code": 200, 205 | "_postman_previewlanguage": "json", 206 | "header": [ 207 | { 208 | "key": "Content-Type", 209 | "value": "application/json" 210 | } 211 | ], 212 | "cookie": [], 213 | "body": "[\n {\n \"fact\": \"Lorem eiusmod culpa amet in\",\n \"length\": 200\n },\n {\n \"fact\": \"in\",\n \"length\": 200\n }\n]" 214 | } 215 | ] 216 | }, 217 | { 218 | "name": "Get a Specific Fact", 219 | "request": { 220 | "method": "GET", 221 | "header": [], 222 | "url": { 223 | "raw": "{{baseUrl}}/facts/:factID", 224 | "host": [ 225 | "{{baseUrl}}" 226 | ], 227 | "path": [ 228 | "facts", 229 | ":factID" 230 | ], 231 | "variable": [ 232 | { 233 | "key": "factID", 234 | "value": null 235 | } 236 | ] 237 | } 238 | }, 239 | "response": [] 240 | } 241 | ], 242 | "description": "Cat Facts", 243 | "event": [ 244 | { 245 | "listen": "prerequest", 246 | "script": { 247 | "type": "text/javascript", 248 | "exec": [ 249 | "//This is a folder PR Script" 250 | ] 251 | } 252 | }, 253 | { 254 | "listen": "test", 255 | "script": { 256 | "type": "text/javascript", 257 | "exec": [ 258 | "//THis is a folder test" 259 | ] 260 | } 261 | } 262 | ] 263 | }, 264 | { 265 | "name": "Breeds", 266 | "item": [ 267 | { 268 | "name": "get Breeds", 269 | "request": { 270 | "method": "GET", 271 | "header": [ 272 | { 273 | "key": "Accept", 274 | "value": "application/json" 275 | } 276 | ], 277 | "url": { 278 | "raw": "https://catfact.ninja/breeds?limit=2&foo=var2", 279 | "protocol": "https", 280 | "host": [ 281 | "catfact", 282 | "ninja" 283 | ], 284 | "path": [ 285 | "breeds" 286 | ], 287 | "query": [ 288 | { 289 | "key": "limit", 290 | "value": "2", 291 | "description": "This is a description" 292 | }, 293 | { 294 | "key": "foo", 295 | "value": "var2", 296 | "description": "THis is the foo thing" 297 | } 298 | ] 299 | }, 300 | "description": "Returns a a list of breeds" 301 | }, 302 | "response": [ 303 | { 304 | "name": "Normal operation", 305 | "originalRequest": { 306 | "method": "GET", 307 | "header": [], 308 | "url": { 309 | "raw": "{{baseUrl}}/breeds?limit=2", 310 | "host": [ 311 | "{{baseUrl}}" 312 | ], 313 | "path": [ 314 | "breeds" 315 | ], 316 | "query": [ 317 | { 318 | "key": "limit", 319 | "value": "2" 320 | } 321 | ] 322 | } 323 | }, 324 | "status": "OK", 325 | "code": 200, 326 | "_postman_previewlanguage": "json", 327 | "header": [ 328 | { 329 | "key": "Content-Type", 330 | "value": "application/json" 331 | } 332 | ], 333 | "cookie": [], 334 | "body": "[\n {\n \"breed\": \"Excepteur d\",\n \"country\": \"ad consequ\",\n \"origin\": \"deserunt dolore\",\n \"coat\": \"consectetur officia dolore ut irure\",\n \"pattern\": \"nulla ea tempor magna\"\n },\n {\n \"breed\": \"ex nisi\",\n \"country\": \"dolor dolore c\",\n \"origin\": \"aute incididunt dolor Ut\",\n \"coat\": \"nulla ut sit eu Duis\",\n \"pattern\": \"cupidat\"\n }\n]" 335 | } 336 | ] 337 | }, 338 | { 339 | "name": "Add Breed", 340 | "request": { 341 | "method": "POST", 342 | "header": [], 343 | "body": { 344 | "mode": "raw", 345 | "raw": "{\n \"breed\": \"Epoxy\",\n \"country\": \"HomeDepot\",\n \"origin\": \"Artificial\",\n \"coat\": \"Sticky\",\n \"pattern\": \"Random\"\n },", 346 | "options": { 347 | "raw": { 348 | "language": "json" 349 | } 350 | } 351 | }, 352 | "url": { 353 | "raw": "https://catfact.ninja/breeds", 354 | "protocol": "https", 355 | "host": [ 356 | "catfact", 357 | "ninja" 358 | ], 359 | "path": [ 360 | "breeds" 361 | ] 362 | } 363 | }, 364 | "response": [] 365 | } 366 | ], 367 | "description": "Breeds" 368 | } 369 | ], 370 | "auth": { 371 | "type": "apikey", 372 | "apikey": [ 373 | { 374 | "key": "value", 375 | "value": "{{fakeAPIKey}}", 376 | "type": "string" 377 | }, 378 | { 379 | "key": "key", 380 | "value": "x-api-key", 381 | "type": "string" 382 | } 383 | ] 384 | }, 385 | "event": [ 386 | { 387 | "listen": "prerequest", 388 | "script": { 389 | "type": "text/javascript", 390 | "exec": [ 391 | "//Collection PR Script" 392 | ] 393 | } 394 | }, 395 | { 396 | "listen": "test", 397 | "script": { 398 | "type": "text/javascript", 399 | "exec": [ 400 | "//Test PR Script" 401 | ] 402 | } 403 | } 404 | ], 405 | "variable": [ 406 | { 407 | "key": "baseUrl", 408 | "value": "https://f653ab18-2f67-42d4-9ac2-d404779d7b24.mock.pstmn.io", 409 | "type": "string" 410 | }, 411 | { 412 | "key": "var1", 413 | "value": "This is the foo value", 414 | "type": "string" 415 | }, 416 | { 417 | "key": "testUrl", 418 | "value": "https://foobarbat.com", 419 | "type": "string" 420 | }, 421 | { 422 | "key": "var2", 423 | "value": "333", 424 | "type": "string" 425 | } 426 | ] 427 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /src/main/java/com/postman/collection/CollectionElement.java: -------------------------------------------------------------------------------- 1 | package com.postman.collection; 2 | 3 | import com.networknt.schema.ValidationMessage; 4 | import java.util.ArrayList; 5 | import com.google.gson.Gson; 6 | import com.networknt.schema.JsonSchema; 7 | import com.fasterxml.jackson.databind.ObjectMapper; 8 | import com.networknt.schema.JsonSchemaFactory; 9 | import com.fasterxml.jackson.core.JsonProcessingException; 10 | import com.fasterxml.jackson.databind.JsonNode; 11 | import java.util.Set; 12 | 13 | import com.networknt.schema.SpecVersion; 14 | import java.net.URI; 15 | import java.net.URISyntaxException; 16 | import java.util.UUID; 17 | import com.flipkart.zjsonpatch.*; 18 | /** 19 | * Abstract Base Class for all objects which are part of a collection 20 | * 21 | */ 22 | public abstract class CollectionElement { 23 | 24 | private transient ArrayList validationMessages; 25 | private static final String defaultCollectionSchema = "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"; 26 | private static final String defaultValidationSchema = "https://schema.postman.com/collection/json/v2.1.0/draft-07/collection.json"; 27 | private transient UUID uuid = UUID.randomUUID(); 28 | private transient CollectionElement parent; 29 | 30 | public abstract String getKey(); 31 | 32 | 33 | /** 34 | * 35 | * 36 | * Validate the gson produced by this element against the PostmanSchema. Schema version is currently hardcoded to 37 | * v2.1.0. Validation is provided by the NetworkNT json-schema-validator 38 | * 39 | * @return boolean true if valid, false if not. If the schema is invalid, calling {@link com.postman.collection.Collection#getValidationMessages() } will return an containing the diffs 40 | * @throws ValidationException If an error is encountered accessing the schema or mapping the underlying JSON. 41 | */ 42 | public boolean validate() throws ValidationException { 43 | return this.validate(null); 44 | } 45 | 46 | 47 | 48 | /** 49 | * 50 | * Set the parent of this element, allowing for traversal up the chain of elements 51 | * 52 | * 53 | * @param parent The parent element 54 | */ 55 | public void setParent(CollectionElement parent) { 56 | this.parent = parent; 57 | } 58 | 59 | 60 | /** 61 | * 62 | * Get the parent element, or null if it is not set. 63 | * 64 | * @return CollectionElement The parent of this element 65 | */ 66 | public CollectionElement getParent() { 67 | return this.parent; 68 | } 69 | 70 | /** 71 | * 72 | * Convenience method allowing validation against a user-provided schema 73 | * 74 | * @param altSchemaJSON String containing the alternate schema JSON 75 | * @return boolean true if valid, false if not. If the schema is invalid, calling {@link com.postman.collection.Collection#getValidationMessages() } will return an containing the diffs 76 | * @throws ValidationException If there is an error in the validation process 77 | */ 78 | public boolean validate(String altSchemaJSON) throws ValidationException { 79 | 80 | ObjectMapper mapper = new ObjectMapper(); 81 | JsonSchema schema; 82 | 83 | String strSchemaRoot = CollectionElement.getDefaultValidationSchema(); 84 | String strSubSchema = ""; 85 | switch (this.getClass().getSimpleName()) { 86 | case "Item": { 87 | strSubSchema = "#/definitions/item"; 88 | break; 89 | } 90 | case "Collection": { 91 | strSubSchema = ""; 92 | break; 93 | } 94 | 95 | case "RequestAuth": { 96 | strSubSchema = "#/definitions/auth"; 97 | break; 98 | } 99 | case "BodyElement": { 100 | strSubSchema = "#/definitions/request/oneOf/0/properties/body"; 101 | break; 102 | } 103 | default: { 104 | strSubSchema = ""; 105 | } 106 | } 107 | 108 | JsonSchemaFactory factory = JsonSchemaFactory.getInstance(SpecVersion.VersionFlag.V7); 109 | if (altSchemaJSON == null) { 110 | try { 111 | schema = factory.getSchema(new URI(strSchemaRoot + strSubSchema)); 112 | } 113 | catch(URISyntaxException e) { 114 | throw new ValidationException(e); 115 | } 116 | 117 | } else { 118 | schema = factory.getSchema(altSchemaJSON); 119 | } 120 | JsonNode pmcNode; 121 | 122 | try { 123 | pmcNode = mapper.readTree(this.toJson()); 124 | } 125 | catch(JsonProcessingException e) { 126 | throw new ValidationException(e); 127 | } 128 | 129 | 130 | 131 | schema.initializeValidators(); 132 | Set errors = schema.validate(pmcNode); 133 | 134 | this.validationMessages = (errors == null || errors.size() == 0) ? new ArrayList() 135 | : new ArrayList(errors); 136 | boolean ignoreValidationErrors = true; 137 | 138 | 139 | //This hackery necessitated by the fact that collections returned from Postman can have 'default' as the type 140 | //for a value in the collection variables, which is not in the schema. 141 | //So we ignore it as an error if it is present. 142 | String valMsg = ""; 143 | String valPath = ""; 144 | for(ValidationMessage vm : this.validationMessages ) 145 | { 146 | valMsg = vm.getMessage(); 147 | valPath = vm.getPath(); 148 | 149 | ignoreValidationErrors = ignoreValidationErrors && valMsg.contains("$.variable[") && valMsg.contains(".type: does not have a value in the enumeration [string, boolean, any, number]"); 150 | } 151 | return ((this.validationMessages == null || this.validationMessages.size() == 0) || ignoreValidationErrors); 152 | 153 | } 154 | 155 | 156 | /** 157 | * 158 | * If an element is invalid, returns an ArrayList<ValidationMessage> containing one or more diff messages describing the differences. If the element is valid 159 | * the size of the returned ArrayList will be zero. 160 | * 161 | * @return ArrayList<ValidationMessage> An ArrayList containing zero or more validatin messages. 162 | */ 163 | public ArrayList getValidationMessages() { 164 | return this.validationMessages; 165 | } 166 | 167 | 168 | /** 169 | * 170 | * Render this element to JSON using the Gson conversion library. 171 | * 172 | * @return String The JSON rendered by Gson 173 | */ 174 | public String toJson() { 175 | return this.toJson(false, false); 176 | } 177 | 178 | 179 | /** 180 | * 181 | * Render this element to JSON using the Gson conversion library. The escape and resolveVariable arguments are currently not implemented 182 | * 183 | * 184 | * @param escape NOT IMPLEMENTED: Escaping scheme for JSON 185 | * @param resolveVariables NOT IMPLEMENTED: Whether to resolve variables to their corresponding values. 186 | * @return String The rendered JSON 187 | */ 188 | public String toJson(boolean escape, boolean resolveVariables) { 189 | return new Gson().toJson(this); 190 | } 191 | 192 | 193 | /** 194 | * 195 | * Get a unique UUID for this element. UUIDs are not persisted/serialized 196 | * 197 | * @return UUID A unique UUID 198 | */ 199 | public UUID getUUID() { 200 | return this.uuid; 201 | } 202 | 203 | 204 | /** 205 | * 206 | * Set a new unique UUID for this element. 207 | * 208 | * @param newID A new UUID 209 | */ 210 | public void setUUID(UUID newID) { 211 | this.uuid = newID; 212 | } 213 | 214 | 215 | /** 216 | * 217 | * Traverse the chain of parent elements upwards until a Collection is reached, or null if this element is not part of a collection. 218 | * 219 | * 220 | * @return Collection The collection at the top of the parent tree, or null. 221 | */ 222 | public Collection getCollection() { 223 | CollectionElement result = null; 224 | CollectionElement curItem = null; 225 | // recursively traverse items looking for name == key 226 | if(this.getParent() == null) { 227 | return this instanceof Collection ? (Collection)this : null; 228 | } 229 | while(result == null) { 230 | curItem = this.getParent(); 231 | if (curItem instanceof Collection) { 232 | result = curItem; 233 | break; 234 | } else { 235 | try { 236 | result = curItem.getCollection(); 237 | if(result == null) { 238 | return null; 239 | } 240 | } 241 | catch(Exception e) { 242 | e.printStackTrace(); 243 | } 244 | 245 | if (result instanceof Collection) { 246 | break; 247 | } 248 | } 249 | } 250 | 251 | 252 | return (Collection)result; 253 | } 254 | 255 | 256 | /** 257 | * 258 | * Determine whether 2 seperate instance of a JPostman class render semantically identical JSON. If the JSON is identical, the returned JsonNode will be empty (e.g., size() == 0). 259 | * If the documents are different, the JsonNode returned contains information about the differences. 260 | * 261 | * @param compare The CollectionElement to compare to this one. 262 | * @return JsonNode JsonNode containing an array of diff msgs. size() will be zero if there are no validation messages. 263 | * @throws ValidationException If there is an exception or error during the Validation process 264 | */ 265 | public JsonNode isEquivalentTo(CollectionElement compare) throws ValidationException { 266 | ObjectMapper jacksonObjectMapper; 267 | JsonNode beforeNode; 268 | JsonNode afterNode; 269 | JsonNode patch; 270 | 271 | jacksonObjectMapper = new ObjectMapper(); 272 | try { 273 | beforeNode = jacksonObjectMapper.readTree(this.toJson()); 274 | afterNode = jacksonObjectMapper.readTree(compare.toJson()); 275 | } 276 | catch(Exception e) { 277 | throw new ValidationException(e); 278 | } 279 | 280 | patch = JsonDiff.asJson(beforeNode, afterNode); 281 | 282 | return patch; 283 | } 284 | /** 285 | * 286 | *

Return the default schema appearing in the schema property in exported collections.

287 | *

288 | *

Current: https://schema.getpostman.com/json/collection/v2.1.0/collection.json

289 | * 290 | * @return The URI for default schema used to validate schemas 291 | */ 292 | public static String getDefaultCollectionSchema() { 293 | return defaultCollectionSchema; 294 | } 295 | /** 296 | * 297 | *

Return the default schema used to validate schemas. NOTE: AS of version Version 10.8.9 this is not the same 298 | * appearing in the schema property in exported collections.

299 | *

300 | *

Current: https://schema.postman.com/collection/json/v2.1.0/draft-07/collection.json

301 | * 302 | * @return The URI for default schema used to validate schemas 303 | */ 304 | public static String getDefaultValidationSchema() { 305 | return defaultValidationSchema; 306 | } 307 | } -------------------------------------------------------------------------------- /src/main/resources/com/postman/collection/auth.postman_collection.json: -------------------------------------------------------------------------------- 1 | { 2 | "info": { 3 | "_postman_id": "23889826-169dff8a-c684-4ccc-b8df-7ad436efda57", 4 | "name": "Auth", 5 | "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json", 6 | "_exporter_id": "23889826" 7 | }, 8 | "item": [ 9 | { 10 | "name": "Auth in Header", 11 | "item": [ 12 | { 13 | "name": "Inherit auth", 14 | "request": { 15 | "method": "GET", 16 | "header": [] 17 | }, 18 | "response": [] 19 | }, 20 | { 21 | "name": "No Auth", 22 | "request": { 23 | "method": "GET", 24 | "header": [] 25 | }, 26 | "response": [] 27 | }, 28 | { 29 | "name": "API-key", 30 | "request": { 31 | "auth": { 32 | "type": "apikey", 33 | "apikey": [ 34 | { 35 | "key": "value", 36 | "value": "API-KEY", 37 | "type": "string" 38 | }, 39 | { 40 | "key": "key", 41 | "value": "x-api-key", 42 | "type": "string" 43 | } 44 | ] 45 | }, 46 | "method": "GET", 47 | "header": [], 48 | "url": { 49 | "raw": "https://postman-echo.com/post", 50 | "protocol": "https", 51 | "host": [ 52 | "postman-echo", 53 | "com" 54 | ], 55 | "path": [ 56 | "post" 57 | ] 58 | } 59 | }, 60 | "response": [] 61 | }, 62 | { 63 | "name": "Bearer Token", 64 | "request": { 65 | "auth": { 66 | "type": "apikey", 67 | "apikey": [ 68 | { 69 | "key": "value", 70 | "value": "TOKEN", 71 | "type": "string" 72 | }, 73 | { 74 | "key": "key", 75 | "value": "x-api-key", 76 | "type": "string" 77 | } 78 | ] 79 | }, 80 | "method": "GET", 81 | "header": [], 82 | "url": { 83 | "raw": "https://postman-echo.com/post", 84 | "protocol": "https", 85 | "host": [ 86 | "postman-echo", 87 | "com" 88 | ], 89 | "path": [ 90 | "post" 91 | ] 92 | } 93 | }, 94 | "response": [] 95 | }, 96 | { 97 | "name": "Basic Auth", 98 | "request": { 99 | "auth": { 100 | "type": "basic", 101 | "basic": [ 102 | { 103 | "key": "password", 104 | "value": "fakepassword", 105 | "type": "string" 106 | }, 107 | { 108 | "key": "username", 109 | "value": "fakeusername", 110 | "type": "string" 111 | } 112 | ] 113 | }, 114 | "method": "GET", 115 | "header": [], 116 | "url": { 117 | "raw": "https://postman-echo.com/post", 118 | "protocol": "https", 119 | "host": [ 120 | "postman-echo", 121 | "com" 122 | ], 123 | "path": [ 124 | "post" 125 | ] 126 | } 127 | }, 128 | "response": [] 129 | }, 130 | { 131 | "name": "Digest", 132 | "request": { 133 | "auth": { 134 | "type": "digest", 135 | "digest": [ 136 | { 137 | "key": "opaque", 138 | "value": "OpaqueString", 139 | "type": "string" 140 | }, 141 | { 142 | "key": "clientNonce", 143 | "value": "2020202", 144 | "type": "string" 145 | }, 146 | { 147 | "key": "nonceCount", 148 | "value": "1010101", 149 | "type": "string" 150 | }, 151 | { 152 | "key": "qop", 153 | "value": "digest-qop", 154 | "type": "string" 155 | }, 156 | { 157 | "key": "algorithm", 158 | "value": "SHA-256", 159 | "type": "string" 160 | }, 161 | { 162 | "key": "nonce", 163 | "value": "digestnonce", 164 | "type": "string" 165 | }, 166 | { 167 | "key": "realm", 168 | "value": "digest@test.com", 169 | "type": "string" 170 | }, 171 | { 172 | "key": "password", 173 | "value": "digestPassword", 174 | "type": "string" 175 | }, 176 | { 177 | "key": "username", 178 | "value": "digestUsername", 179 | "type": "string" 180 | } 181 | ] 182 | }, 183 | "method": "GET", 184 | "header": [], 185 | "url": { 186 | "raw": "https://postman-echo.com/post", 187 | "protocol": "https", 188 | "host": [ 189 | "postman-echo", 190 | "com" 191 | ], 192 | "path": [ 193 | "post" 194 | ] 195 | } 196 | }, 197 | "response": [] 198 | }, 199 | { 200 | "name": "Oauth 1.0", 201 | "request": { 202 | "auth": { 203 | "type": "oauth1", 204 | "oauth1": [ 205 | { 206 | "key": "addEmptyParamsToSign", 207 | "value": true, 208 | "type": "boolean" 209 | }, 210 | { 211 | "key": "includeBodyHash", 212 | "value": true, 213 | "type": "boolean" 214 | }, 215 | { 216 | "key": "realm", 217 | "value": "testoauth@test.com", 218 | "type": "string" 219 | }, 220 | { 221 | "key": "nonce", 222 | "value": "oauthNonce", 223 | "type": "string" 224 | }, 225 | { 226 | "key": "timestamp", 227 | "value": "oauthTimestamp", 228 | "type": "string" 229 | }, 230 | { 231 | "key": "verifier", 232 | "value": "oauthVerifier", 233 | "type": "string" 234 | }, 235 | { 236 | "key": "callback", 237 | "value": "https://callback.url", 238 | "type": "string" 239 | }, 240 | { 241 | "key": "tokenSecret", 242 | "value": "oauthTokenSecret", 243 | "type": "string" 244 | }, 245 | { 246 | "key": "token", 247 | "value": "oauthToken", 248 | "type": "string" 249 | }, 250 | { 251 | "key": "consumerSecret", 252 | "value": "consumerSecret", 253 | "type": "string" 254 | }, 255 | { 256 | "key": "consumerKey", 257 | "value": "consumerKey", 258 | "type": "string" 259 | }, 260 | { 261 | "key": "signatureMethod", 262 | "value": "HMAC-SHA1", 263 | "type": "string" 264 | }, 265 | { 266 | "key": "version", 267 | "value": "1.0", 268 | "type": "string" 269 | }, 270 | { 271 | "key": "addParamsToHeader", 272 | "value": false, 273 | "type": "boolean" 274 | } 275 | ] 276 | }, 277 | "method": "GET", 278 | "header": [], 279 | "url": { 280 | "raw": "https://postman-echo.com/post", 281 | "protocol": "https", 282 | "host": [ 283 | "postman-echo", 284 | "com" 285 | ], 286 | "path": [ 287 | "post" 288 | ] 289 | } 290 | }, 291 | "response": [] 292 | }, 293 | { 294 | "name": "Oauth 2.0", 295 | "request": { 296 | "auth": { 297 | "type": "oauth2", 298 | "oauth2": [ 299 | { 300 | "key": "grant_type", 301 | "value": "authorization_code", 302 | "type": "string" 303 | }, 304 | { 305 | "key": "tokenName", 306 | "value": "Oauth2TokenName", 307 | "type": "string" 308 | }, 309 | { 310 | "key": "tokenType", 311 | "value": "", 312 | "type": "string" 313 | }, 314 | { 315 | "key": "accessToken", 316 | "value": "oauth2Token", 317 | "type": "string" 318 | }, 319 | { 320 | "key": "addTokenTo", 321 | "value": "header", 322 | "type": "string" 323 | } 324 | ] 325 | }, 326 | "method": "GET", 327 | "header": [], 328 | "url": { 329 | "raw": "https://postman-echo.com/post", 330 | "protocol": "https", 331 | "host": [ 332 | "postman-echo", 333 | "com" 334 | ], 335 | "path": [ 336 | "post" 337 | ] 338 | } 339 | }, 340 | "response": [] 341 | }, 342 | { 343 | "name": "Hawk", 344 | "request": { 345 | "auth": { 346 | "type": "hawk", 347 | "hawk": [ 348 | { 349 | "key": "includePayloadHash", 350 | "value": true, 351 | "type": "boolean" 352 | }, 353 | { 354 | "key": "timestamp", 355 | "value": "HawkTimestamp", 356 | "type": "string" 357 | }, 358 | { 359 | "key": "delegation", 360 | "value": "Hawk-dlg", 361 | "type": "string" 362 | }, 363 | { 364 | "key": "app", 365 | "value": "HawkAppID", 366 | "type": "string" 367 | }, 368 | { 369 | "key": "extraData", 370 | "value": "Hawk-ext", 371 | "type": "string" 372 | }, 373 | { 374 | "key": "nonce", 375 | "value": "HawkNonce", 376 | "type": "string" 377 | }, 378 | { 379 | "key": "user", 380 | "value": "HawkUser", 381 | "type": "string" 382 | }, 383 | { 384 | "key": "authKey", 385 | "value": "HawkAuthKey", 386 | "type": "string" 387 | }, 388 | { 389 | "key": "authId", 390 | "value": "hawkAuthID", 391 | "type": "string" 392 | }, 393 | { 394 | "key": "algorithm", 395 | "value": "sha256", 396 | "type": "string" 397 | } 398 | ] 399 | }, 400 | "method": "GET", 401 | "header": [], 402 | "url": { 403 | "raw": "https://postman-echo.com/post", 404 | "protocol": "https", 405 | "host": [ 406 | "postman-echo", 407 | "com" 408 | ], 409 | "path": [ 410 | "post" 411 | ] 412 | } 413 | }, 414 | "response": [] 415 | }, 416 | { 417 | "name": "AWS Signature", 418 | "request": { 419 | "auth": { 420 | "type": "awsv4", 421 | "awsv4": [ 422 | { 423 | "key": "sessionToken", 424 | "value": "awsSessiontoken", 425 | "type": "string" 426 | }, 427 | { 428 | "key": "service", 429 | "value": "awsServiceName", 430 | "type": "string" 431 | }, 432 | { 433 | "key": "region", 434 | "value": "awsRegion", 435 | "type": "string" 436 | }, 437 | { 438 | "key": "secretKey", 439 | "value": "awsSecretKey", 440 | "type": "string" 441 | }, 442 | { 443 | "key": "accessKey", 444 | "value": "awsAccessKey", 445 | "type": "string" 446 | }, 447 | { 448 | "key": "addAuthDataToQuery", 449 | "value": false, 450 | "type": "boolean" 451 | } 452 | ] 453 | }, 454 | "method": "GET", 455 | "header": [], 456 | "url": { 457 | "raw": "https://postman-echo.com/post", 458 | "protocol": "https", 459 | "host": [ 460 | "postman-echo", 461 | "com" 462 | ], 463 | "path": [ 464 | "post" 465 | ] 466 | } 467 | }, 468 | "response": [] 469 | }, 470 | { 471 | "name": "NTLM", 472 | "request": { 473 | "auth": { 474 | "type": "ntlm", 475 | "ntlm": [ 476 | { 477 | "key": "workstation", 478 | "value": "NTMLWorkstation", 479 | "type": "string" 480 | }, 481 | { 482 | "key": "domain", 483 | "value": "NTLMdomain", 484 | "type": "string" 485 | }, 486 | { 487 | "key": "password", 488 | "value": "NTLMPassword", 489 | "type": "string" 490 | }, 491 | { 492 | "key": "username", 493 | "value": "NTLMUsername", 494 | "type": "string" 495 | } 496 | ] 497 | }, 498 | "method": "GET", 499 | "header": [], 500 | "url": { 501 | "raw": "https://postman-echo.com/post", 502 | "protocol": "https", 503 | "host": [ 504 | "postman-echo", 505 | "com" 506 | ], 507 | "path": [ 508 | "post" 509 | ] 510 | } 511 | }, 512 | "response": [] 513 | }, 514 | { 515 | "name": "Akamai", 516 | "request": { 517 | "auth": { 518 | "type": "edgegrid", 519 | "edgegrid": [ 520 | { 521 | "key": "headersToSign", 522 | "value": "x-api-key", 523 | "type": "string" 524 | }, 525 | { 526 | "key": "baseURL", 527 | "value": "https://akamai-base.com", 528 | "type": "string" 529 | }, 530 | { 531 | "key": "timestamp", 532 | "value": "akamaiTimestamp", 533 | "type": "string" 534 | }, 535 | { 536 | "key": "nonce", 537 | "value": "akamaiNonce", 538 | "type": "string" 539 | }, 540 | { 541 | "key": "clientSecret", 542 | "value": "akamaiClientSecret", 543 | "type": "string" 544 | }, 545 | { 546 | "key": "clientToken", 547 | "value": "akamaiClientToken", 548 | "type": "string" 549 | }, 550 | { 551 | "key": "accessToken", 552 | "value": "akamaiToken", 553 | "type": "string" 554 | } 555 | ] 556 | }, 557 | "method": "GET", 558 | "header": [], 559 | "url": { 560 | "raw": "https://postman-echo.com/post", 561 | "protocol": "https", 562 | "host": [ 563 | "postman-echo", 564 | "com" 565 | ], 566 | "path": [ 567 | "post" 568 | ] 569 | } 570 | }, 571 | "response": [] 572 | } 573 | ] 574 | } 575 | ] 576 | } --------------------------------------------------------------------------------