diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 00000000..63434039 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,6 @@ +version: 2 +updates: + - package-ecosystem: maven + directory: / + schedule: + interval: daily \ No newline at end of file diff --git a/.github/workflows/push-and-pull_request.yml b/.github/workflows/push-and-pull_request.yml new file mode 100644 index 00000000..397fea74 --- /dev/null +++ b/.github/workflows/push-and-pull_request.yml @@ -0,0 +1,102 @@ +name: Build on Push and Pull Request +on: + - push + - pull_request + +jobs: + build: + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + # Supported versions as of https://en.wikipedia.org/wiki/Java_version_history + java-version: + - 8 + - 11 + - 16 + + name: Build with JDK ${{ matrix.java-version }} + steps: + - name: Cache Dependencies + uses: actions/cache@v2.1.7 + with: + key: maven-dependencies + path: ~/.m2/repository + - name: Check out + uses: actions/checkout@v2.4.0 + - name: Set up JDK ${{ matrix.java-version }} + uses: actions/setup-java@v2 + with: + distribution: adopt + java-version: ${{ matrix.java-version }} + gpg-private-key: ${{ secrets.GPG_PRIVATE_KEY }} + gpg-passphrase: GPG_PASSPHRASE + - name: Clean, Build, Install + run: | + set -o errexit -o pipefail + mvn clean install --activate-profiles dirty,dirty-package --update-snapshots --batch-mode --show-version 2>&1 | tee mvnout.txt + set +o errexit +o pipefail + - id: version + name: Evaluate Version + run: | + project_version=`mvn help:evaluate --quiet --define expression=project.version --define forceStdout` + echo "Version: ${project_version}" + + snapshot_version=`echo "${project_version}" | grep --perl-regexp --regexp="-SNAPSHOT$"` + if [ -n "${snapshot_version}" ]; then + echo "Identified as snapshot version" + echo "::set-output name=is-snapshot::true" + else + echo "Identified as release version" + echo "::set-output name=is-snapshot::false" + fi + - name: Test, Verify, Deploy + if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' && matrix.java-version == 8 && steps.version.outputs.is-snapshot == 'true' }} + run: | + set -o errexit -o pipefail + mvn deploy site --batch-mode --show-version 2>&1 | tee --append mvnout.txt + set +o errexit +o pipefail + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }} + - name: Test, Verify + if: ${{ github.event_name != 'push' || github.ref != 'refs/heads/master' || matrix.java-version != 8 || steps.version.outputs.is-snapshot != 'true' }} + run: | + set -o errexit -o pipefail + mvn verify site --define gpg.skip=true --batch-mode --show-version 2>&1 | tee --append mvnout.txt + set +o errexit +o pipefail + - name: Check Output + shell: bash {0} + run: | + chmod +x ./target/mvn-suppressions-parent.sh + mvnout=`cat mvnout.txt | grep --perl-regexp "(?i)\\[(ERR|WARN)" | ./target/mvn-suppressions-parent.sh "$JDK_VERSION"` + + if [ -n "${mvnout}" ]; then + echo "[ERROR] The Maven output contains the following unknown warnings and errors:" >&2 + echo "${mvnout}" >&2 + false + else + echo "[INFO] No unknown warnings and errors found." + echo "${mvnout}" >&2 + fi + env: + JDK_VERSION: ${{ matrix.java-version }} + - name: Prepare Site + if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' && matrix.java-version == 8 && steps.version.outputs.is-snapshot == 'true' }} + run: | + if [ -f ./target/site/index.html ]; then + rm ./target/site/index.html + fi + if [ -f ./CHANGELOG.md ]; then + cp ./CHANGELOG.md ./target/site/CHANGELOG.md + fi + if [ -f ./README.md ]; then + cp ./README.md ./target/site/README.md + fi + - name: Deploy Site + if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' && matrix.java-version == 8 && steps.version.outputs.is-snapshot == 'true' }} + uses: peaceiris/actions-gh-pages@v3.8.0 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + publish_dir: ./target/site + enable_jekyll: true \ No newline at end of file diff --git a/.gitignore b/.gitignore index 618c6c87..293daa8d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,24 +1,10 @@ -*.class - -.classpath -.project -.settings/* - -# Mobile Tools for Java (J2ME) -.mtj.tmp/ - -# Package Files # -*.jar -*.war -*.ear - -# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml -hs_err_pid* +/.idea/ +/.settings/ +/src/main/lombok/lombok.config +/src/test/lombok/lombok.config +/src/lombok.config /target/ -.idea -swagger-diff.iml -testDiff.html -testDiff.md -testDeprecatedApi.html -testNewApi.html - +/.checkstyle +/.classpath +/.project +/*.iml \ No newline at end of file diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 6479fd5a..00000000 --- a/.travis.yml +++ /dev/null @@ -1,6 +0,0 @@ -language: java -script: mvn clean install - -after_success: - - mvn clean cobertura:cobertura org.eluder.coveralls:coveralls-maven-plugin:report - diff --git a/LICENSE b/LICENSE.txt similarity index 100% rename from LICENSE rename to LICENSE.txt diff --git a/mvn-suppressions.sh b/mvn-suppressions.sh new file mode 100755 index 00000000..c2ba6b4f --- /dev/null +++ b/mvn-suppressions.sh @@ -0,0 +1,14 @@ +function suppressSiteWarnings() { + cat < /dev/stdin \ + | grep --invert-match --perl-regexp "^\\[WARNING\\] Unable to find a URL to the parent project\\. The parent menu will NOT be added\\.$" +} + +# JaCoCo Maven Plugin: The Maven Plugin is referencing a moved Maven artifact. +function suppressJaCoCoMavenPlugin() { + cat < /dev/stdin \ + | grep --invert-match --perl-regexp "^\\[WARNING\\] The artifact xml-apis:xml-apis:jar:2\\.0\\.2 has been relocated to xml-apis:xml-apis:jar:1\\.0\\.b2$" +} + +cat < /dev/stdin \ +| suppressSiteWarnings \ +| suppressJaCoCoMavenPlugin diff --git a/pom.xml b/pom.xml index 27fc64c4..e49c6107 100644 --- a/pom.xml +++ b/pom.xml @@ -1,23 +1,21 @@ - + + 4.0.0 - org.sonatype.oss - oss-parent - 7 + de.lars-sh + parent + 0.9.13 + - com.deepoove + com.hlag.api swagger-diff - 1.2.2 - jar + 1.2.3-SNAPSHOT swagger-diff diff swagger api document - https://github.com/Sayi/swagger-diff - + https://${parent-pom.github.organization}.github.io/${parent-pom.github.project}/ The Apache Software License, Version 2.0 @@ -32,173 +30,104 @@ + + false + false + java + Hapag-Lloyd + swagger-diff + disabled + disabled - - scm:git:git@github.com:Sayi/swagger-diff.git - scm:git:git@github.com:Sayi/swagger-diff.git - git@github.com:Sayi/swagger-diff.git - + true + true + true + true + true - - UTF-8 + + 3.1.2 - - - oss - https://oss.sonatype.org/content/repositories/snapshots/ - - - oss - https://oss.sonatype.org/service/local/staging/deploy/maven2/ - - - - io.swagger - swagger-parser - 1.0.31 + com.alibaba + fastjson + 2.0.21 - io.swagger - swagger-compat-spec-parser - 1.0.31 + com.beust + jcommander + 1.82 + + + com.fasterxml.jackson.core + jackson-databind + 2.14.1 + + + com.google.guava + guava + 31.1-jre com.j2html j2html - 1.2.0 + 1.6.0 - com.alibaba - fastjson - 1.2.31 + io.swagger + swagger-compat-spec-parser + 1.0.64 - com.beust - jcommander - 1.72 + io.swagger + swagger-models + 1.6.9 + + + io.swagger + swagger-parser + 1.0.64 + + + org.apache.commons + commons-lang3 + 3.12.0 org.slf4j - slf4j-nop - 1.6.3 - test + slf4j-api + 2.0.6 + junit junit - 4.8.2 + 4.13.2 + test + + + org.junit.vintage + junit-vintage-engine + 5.9.1 test - - - release - - - - maven-compiler-plugin - - 1.8 - 1.8 - UTF-8 - - 3.2 - - - - org.apache.maven.plugins - maven-source-plugin - 2.2.1 - - - package - - jar-no-fork - - - - - - - org.apache.maven.plugins - maven-javadoc-plugin - 2.9.1 - - true - true - true - true - true - - - - attach-javadocs - - jar - - - - - - - org.apache.maven.plugins - maven-gpg-plugin - 1.5 - - - verify - - sign - - - - - - - - - oss - https://oss.sonatype.org/content/repositories/snapshots/ - - - oss - https://oss.sonatype.org/service/local/staging/deploy/maven2/ - - - - - - - maven-compiler-plugin - - 1.8 - 1.8 - UTF-8 - - 3.2 - - - org.codehaus.mojo - cobertura-maven-plugin - 2.7 - - xml - 256m - - true - - - - org.eluder.coveralls - coveralls-maven-plugin - 4.3.0 - - + + + + maven-dependency-plugin + + + org.junit.vintage:junit-vintage-engine + + + + + diff --git a/src/main/java/com/deepoove/swagger/diff/SwaggerDiff.java b/src/main/java/com/deepoove/swagger/diff/SwaggerDiff.java index dfb3ebed..40b4e585 100644 --- a/src/main/java/com/deepoove/swagger/diff/SwaggerDiff.java +++ b/src/main/java/com/deepoove/swagger/diff/SwaggerDiff.java @@ -36,6 +36,7 @@ public class SwaggerDiff { * old api-doc location:Json or Http * @param newSpec * new api-doc location:Json or Http + * @return swagger differences */ public static SwaggerDiff compareV1(String oldSpec, String newSpec) { return compare(oldSpec, newSpec, null, null); @@ -48,6 +49,7 @@ public static SwaggerDiff compareV1(String oldSpec, String newSpec) { * old api-doc location:Json or Http * @param newSpec * new api-doc location:Json or Http + * @return swagger differences */ public static SwaggerDiff compareV2(String oldSpec, String newSpec) { return compare(oldSpec, newSpec, null, SWAGGER_VERSION_V2); @@ -59,6 +61,7 @@ public static SwaggerDiff compareV2(String oldSpec, String newSpec) { * * @param oldSpec old api-doc json as string * @param newSpec new api-doc json as string + * @return swagger differences */ public static SwaggerDiff compareV2Raw(String oldSpec, String newSpec) { return new SwaggerDiff(oldSpec, newSpec).compare(); @@ -71,6 +74,7 @@ public static SwaggerDiff compareV2Raw(String oldSpec, String newSpec) { * old Swagger specification document in v2.0 format as a JsonNode * @param newSpec * new Swagger specification document in v2.0 format as a JsonNode + * @return swagger differences */ public static SwaggerDiff compareV2(JsonNode oldSpec, JsonNode newSpec) { return new SwaggerDiff(oldSpec, newSpec).compare(); @@ -81,11 +85,6 @@ public static SwaggerDiff compare(String oldSpec, String newSpec, return new SwaggerDiff(oldSpec, newSpec, auths, version).compare(); } - - /** - * @param rawOldSpec - * @param rawNewSpec - */ private SwaggerDiff(String rawOldSpec, String rawNewSpec) { SwaggerParser swaggerParser = new SwaggerParser(); oldSpecSwagger = swaggerParser.parse(rawOldSpec); @@ -96,12 +95,6 @@ private SwaggerDiff(String rawOldSpec, String rawNewSpec) { } } - /** - * @param oldSpec - * @param newSpec - * @param auths - * @param version - */ private SwaggerDiff(String oldSpec, String newSpec, List auths, String version) { if (SWAGGER_VERSION_V2.equals(version)) { diff --git a/src/main/java/com/deepoove/swagger/diff/cli/CLI.java b/src/main/java/com/deepoove/swagger/diff/cli/CLI.java index 98c195ba..7ae8c8d4 100644 --- a/src/main/java/com/deepoove/swagger/diff/cli/CLI.java +++ b/src/main/java/com/deepoove/swagger/diff/cli/CLI.java @@ -15,7 +15,6 @@ * -output-mode markdown \n * * @author Sayi - * @version */ public class CLI { @@ -58,7 +57,7 @@ public void run(JCommander jCommander) { return; } if (v){ - JCommander.getConsole().println("1.2.2"); + jCommander.getConsole().println("1.2.2"); return; } @@ -66,7 +65,7 @@ public void run(JCommander jCommander) { ? SwaggerDiff.compareV2(oldSpec, newSpec) : SwaggerDiff.compareV1(oldSpec, newSpec); String render = getRender(outputMode).render(diff); - JCommander.getConsole().println(render); + jCommander.getConsole().println(render); } private Render getRender(String outputMode) { diff --git a/src/main/java/com/deepoove/swagger/diff/compare/ListDiff.java b/src/main/java/com/deepoove/swagger/diff/compare/ListDiff.java index 72a82795..682d58e6 100644 --- a/src/main/java/com/deepoove/swagger/diff/compare/ListDiff.java +++ b/src/main/java/com/deepoove/swagger/diff/compare/ListDiff.java @@ -3,17 +3,13 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; -import java.util.ListIterator; import java.util.Map; import java.util.function.BiFunction; -import com.google.common.collect.Lists; - /** * compare two Lists * * @author Sayi - * @version */ public class ListDiff { @@ -30,14 +26,15 @@ public static ListDiff diff(List left, List right) { } /** + * Compares two lists * - * @param left - * @param right + * @param the list key type + * @param left the left list + * @param right the right list * @param biFunc * if right List contains left element - * @return + * @return the list differences */ - @SuppressWarnings("unchecked") public static ListDiff diff(List left, List right, BiFunction, K, K> biFunc) { ListDiff instance = new ListDiff<>(); if (null == left && null == right) return instance; @@ -55,14 +52,7 @@ public static ListDiff diff(List left, List right, BiFunction listIterator = instance.increased.listIterator(); - while (listIterator.hasNext()) { - K k = listIterator.next(); - if (biFunc.apply(Lists.newArrayList(k), ele) != null) { - listIterator.remove(); - break; - } - } + instance.increased.remove(rightEle); instance.shared.put(ele, rightEle); } else { instance.missing.add(ele); diff --git a/src/main/java/com/deepoove/swagger/diff/compare/MapKeyDiff.java b/src/main/java/com/deepoove/swagger/diff/compare/MapKeyDiff.java index 532e00db..1a3ae1d5 100644 --- a/src/main/java/com/deepoove/swagger/diff/compare/MapKeyDiff.java +++ b/src/main/java/com/deepoove/swagger/diff/compare/MapKeyDiff.java @@ -10,7 +10,6 @@ * compare two Maps by key * * @author Sayi - * @version */ public class MapKeyDiff { diff --git a/src/main/java/com/deepoove/swagger/diff/compare/ModelDiff.java b/src/main/java/com/deepoove/swagger/diff/compare/ModelDiff.java index 600132f5..533268c0 100644 --- a/src/main/java/com/deepoove/swagger/diff/compare/ModelDiff.java +++ b/src/main/java/com/deepoove/swagger/diff/compare/ModelDiff.java @@ -23,7 +23,6 @@ * compare two model * * @author Sayi - * @version */ public class ModelDiff { diff --git a/src/main/java/com/deepoove/swagger/diff/compare/ParameterDiff.java b/src/main/java/com/deepoove/swagger/diff/compare/ParameterDiff.java index 30e8f3ba..56489648 100644 --- a/src/main/java/com/deepoove/swagger/diff/compare/ParameterDiff.java +++ b/src/main/java/com/deepoove/swagger/diff/compare/ParameterDiff.java @@ -14,6 +14,7 @@ import io.swagger.models.parameters.AbstractSerializableParameter; import io.swagger.models.parameters.BodyParameter; import io.swagger.models.parameters.Parameter; +import io.swagger.models.parameters.SerializableParameter; import io.swagger.models.properties.Property; import io.swagger.models.properties.StringProperty; @@ -21,7 +22,6 @@ * compare two parameter * * @author Sayi - * @version */ public class ParameterDiff { @@ -83,7 +83,7 @@ public ParameterDiff diff(List left, List right) { if (!leftPara.equals(rightPara)) { ElProperty elProperty = new ElProperty(); elProperty.setEl(rightPara.getName()); - elProperty.setProperty(mapToProperty(rightPara)); + elProperty.setProperty(mapToProperty((SerializableParameter) rightPara)); changedParameter.setChanged(Lists.newArrayList(elProperty)); } } @@ -109,7 +109,7 @@ public ParameterDiff diff(List left, List right) { return this; } - private Property mapToProperty(Parameter rightPara) { + private Property mapToProperty(SerializableParameter rightPara) { Property prop = new StringProperty(); prop.setAccess(rightPara.getAccess()); prop.setAllowEmptyValue(rightPara.getAllowEmptyValue()); diff --git a/src/main/java/com/deepoove/swagger/diff/compare/SpecificationDiff.java b/src/main/java/com/deepoove/swagger/diff/compare/SpecificationDiff.java index 2e0e6d66..162aba08 100644 --- a/src/main/java/com/deepoove/swagger/diff/compare/SpecificationDiff.java +++ b/src/main/java/com/deepoove/swagger/diff/compare/SpecificationDiff.java @@ -17,10 +17,16 @@ import io.swagger.models.Swagger; import io.swagger.models.parameters.Parameter; import io.swagger.models.properties.Property; +import io.swagger.models.utils.PropertyModelConverter; + +import java.util.*; +import java.util.Map.Entry; + +import static java.util.stream.Collectors.toMap; /** * compare two Swagger - * + * * @author Sayi * */ @@ -35,8 +41,8 @@ private SpecificationDiff() {} public static SpecificationDiff diff(Swagger oldSpec, Swagger newSpec) { if (null == oldSpec || null == newSpec) { throw new IllegalArgumentException("cannot diff null spec."); } SpecificationDiff instance = new SpecificationDiff(); - Map oldPaths = oldSpec.getPaths(); - Map newPaths = newSpec.getPaths(); + Map oldPaths = getPathsWithBasePath(oldSpec); + Map newPaths = getPathsWithBasePath(newSpec); // Diff path MapKeyDiff pathDiff = MapKeyDiff.diff(oldPaths, newPaths); @@ -119,12 +125,24 @@ public static SpecificationDiff diff(Swagger oldSpec, Swagger newSpec) { } + private static Map getPathsWithBasePath(Swagger spec) { + return spec.getPaths() + .entrySet() + .stream() + .collect(toMap(entry -> spec.getBasePath() + entry.getKey(), //keyMapper + Entry::getValue, //valueMapper + (u, v) -> { + throw new IllegalStateException(String.format("Duplicate key %s", u)); + }, //mergeFunction + LinkedHashMap::new)); //mapSupplier + } + private static Property getResponseProperty(Operation operation) { Map responses = operation.getResponses(); // temporary workaround for missing response messages if (responses == null) return null; Response response = responses.get("200"); - return null == response ? null : response.getSchema(); + return null == response ? null : new PropertyModelConverter().modelToProperty(response.getResponseSchema()); } private static List convert2EndpointList(Map map) { diff --git a/src/main/java/com/deepoove/swagger/diff/model/ElProperty.java b/src/main/java/com/deepoove/swagger/diff/model/ElProperty.java index cb2bf282..b5c32d2a 100644 --- a/src/main/java/com/deepoove/swagger/diff/model/ElProperty.java +++ b/src/main/java/com/deepoove/swagger/diff/model/ElProperty.java @@ -6,7 +6,6 @@ * property with expression Language grammar * * @author Sayi - * @version */ public class ElProperty { diff --git a/src/test/java/com/deepoove/swagger/test/SwaggerDiffTest.java b/src/test/java/com/deepoove/swagger/test/SwaggerDiffTest.java index 6405ab59..3032a8d0 100644 --- a/src/test/java/com/deepoove/swagger/test/SwaggerDiffTest.java +++ b/src/test/java/com/deepoove/swagger/test/SwaggerDiffTest.java @@ -25,7 +25,9 @@ public class SwaggerDiffTest { final String SWAGGER_V2_DOC1 = "petstore_v2_1.json"; final String SWAGGER_V2_DOC2 = "petstore_v2_2.json"; final String SWAGGER_V2_EMPTY_DOC = "petstore_v2_empty.json"; - final String SWAGGER_V2_HTTP = "http://petstore.swagger.io/v2/swagger.json"; + final String PATH_ORIGINAL_SWAGGER = "original-swagger.yaml"; + private String PATH_NONE_BREAKING_BASEPATH_CHANGED = + "change.non-breaking.basePath-changed.and.operations-changed.yaml"; @Test public void testEqual() { @@ -45,7 +47,7 @@ public void testNewApi() { try { FileWriter fw = new FileWriter( - "testNewApi.html"); + "target/testNewApi.html"); fw.write(html); fw.close(); @@ -70,7 +72,7 @@ public void testDeprecatedApi() { try { FileWriter fw = new FileWriter( - "testDeprecatedApi.html"); + "target/testDeprecatedApi.html"); fw.write(html); fw.close(); @@ -93,7 +95,7 @@ public void testDiff() { try { FileWriter fw = new FileWriter( - "testDiff.html"); + "target/testDiff.html"); fw.write(html); fw.close(); @@ -110,7 +112,7 @@ public void testDiffAndMarkdown() { String render = new MarkdownRender().render(diff); try { FileWriter fw = new FileWriter( - "testDiff.md"); + "target/testDiff.md"); fw.write(render); fw.close(); @@ -185,7 +187,7 @@ public void testJsonRender() { String render = new JsonRender().render(diff); try { FileWriter fw = new FileWriter( - "testDiff.json"); + "target/testDiff.json"); fw.write(render); fw.close(); @@ -198,7 +200,7 @@ public void testJsonRender() { public void testInputBodyArray() { SwaggerDiff diff = SwaggerDiff.compareV2(SWAGGER_V2_DOC1, SWAGGER_V2_DOC2); Map changedEndpointMap = diff.getChangedEndpoints().stream().collect(Collectors.toMap(ChangedEndpoint::getPathUrl, e -> e)); - Lists.newArrayList("/user/createWithArray", "/user/createWithList").forEach(name -> { + Lists.newArrayList("/v2/user/createWithArray", "/v2/user/createWithList").forEach(name -> { Assert.assertTrue("Expecting changed endpoint " + name, changedEndpointMap.containsKey(name)); ChangedEndpoint endpoint = changedEndpointMap.get(name); Assert.assertEquals(1, endpoint.getChangedOperations().size()); @@ -226,7 +228,7 @@ public void testInputBodyArray() { public void testResponseBodyArray() { SwaggerDiff diff = SwaggerDiff.compareV2(SWAGGER_V2_DOC1, SWAGGER_V2_DOC2); Map changedEndpointMap = diff.getChangedEndpoints().stream().collect(Collectors.toMap(ChangedEndpoint::getPathUrl, e -> e)); - Lists.newArrayList("/pet/findByStatus", "/pet/findByTags").forEach(name -> { + Lists.newArrayList("/v2/pet/findByStatus", "/v2/pet/findByTags").forEach(name -> { Assert.assertTrue("Expecting changed endpoint " + name, changedEndpointMap.containsKey(name)); ChangedEndpoint endpoint = changedEndpointMap.get(name); Assert.assertEquals(1, endpoint.getChangedOperations().size()); @@ -249,8 +251,8 @@ public void testResponseBodyArray() { public void testDetectProducesAndConsumes() { SwaggerDiff diff = SwaggerDiff.compareV2(SWAGGER_V2_DOC1, SWAGGER_V2_DOC2); Map changedEndpointMap = diff.getChangedEndpoints().stream().collect(Collectors.toMap(ChangedEndpoint::getPathUrl, e -> e)); - Assert.assertTrue("Expecting changed endpoint " + "/store/order", changedEndpointMap.containsKey("/store/order")); - ChangedEndpoint endpoint = changedEndpointMap.get("/store/order"); + Assert.assertTrue("Expecting changed endpoint " + "/v2/store/order", changedEndpointMap.containsKey("/v2/store/order")); + ChangedEndpoint endpoint = changedEndpointMap.get("/v2/store/order"); Assert.assertTrue("Expecting POST method change", endpoint.getChangedOperations().containsKey(HttpMethod.POST)); ChangedOperation changedOperation = endpoint.getChangedOperations().get(HttpMethod.POST); Assert.assertEquals(1, changedOperation.getAddConsumes().size()); @@ -263,8 +265,8 @@ public void testDetectProducesAndConsumes() { public void testChangedPropertyMetadata() { SwaggerDiff diff = SwaggerDiff.compareV2(SWAGGER_V2_DOC1, SWAGGER_V2_DOC2); Map changedEndpointMap = diff.getChangedEndpoints().stream().collect(Collectors.toMap(ChangedEndpoint::getPathUrl, e -> e)); - String postOrder = "/store/order"; - String getOrder = "/store/order/{orderId}"; + String postOrder = "/v2/store/order"; + String getOrder = "/v2/store/order/{orderId}"; Assert.assertTrue("Expecting changed endpoint " + postOrder, changedEndpointMap.containsKey(postOrder)); ChangedEndpoint postOrderChg = changedEndpointMap.get(postOrder); @@ -313,4 +315,10 @@ private void assertEqual(SwaggerDiff diff) { } + @Test + public void testBasePath_And_OperationUpdate_with_No_Breaking_Change(){ + SwaggerDiff diff = SwaggerDiff.compareV2(PATH_ORIGINAL_SWAGGER, PATH_NONE_BREAKING_BASEPATH_CHANGED); + assertEqual(diff); + } + } diff --git a/src/test/resources/change.non-breaking.basePath-changed.and.operations-changed.yaml b/src/test/resources/change.non-breaking.basePath-changed.and.operations-changed.yaml new file mode 100644 index 00000000..5f4964a0 --- /dev/null +++ b/src/test/resources/change.non-breaking.basePath-changed.and.operations-changed.yaml @@ -0,0 +1,700 @@ +swagger: "2.0" +info: + description: "This is a sample server Petstore server. You can find out more about Swagger at [http://swagger.io](http://swagger.io) or on [irc.freenode.net, #swagger](http://swagger.io/irc/). For this sample, you can use the api key `special-key` to test the authorization filters." + version: "1.0.0" + title: "Swagger Petstore" + termsOfService: "http://swagger.io/terms/" + contact: + email: "apiteam@swagger.io" + license: + name: "Apache 2.0" + url: "http://www.apache.org/licenses/LICENSE-2.0.html" +host: "petstore.swagger.io" +basePath: "/v2" +tags: +- name: "pet" + description: "Everything about your Pets" + externalDocs: + description: "Find out more" + url: "http://swagger.io" +- name: "store" + description: "Access to Petstore orders" +- name: "user" + description: "Operations about user" + externalDocs: + description: "Find out more about our store" + url: "http://swagger.io" +schemes: +- "https" +- "http" +paths: + /test/pet: + post: + tags: + - "pet" + summary: "Add a new pet to the store" + description: "" + operationId: "addPet" + consumes: + - "application/json" + - "application/xml" + produces: + - "application/xml" + - "application/json" + parameters: + - in: "body" + name: "body" + description: "Pet object that needs to be added to the store" + required: true + schema: + $ref: "#/definitions/Pet" + responses: + 405: + description: "Invalid input" + security: + - petstore_auth: + - "write:pets" + - "read:pets" + put: + tags: + - "pet" + summary: "Update an existing pet" + description: "" + operationId: "updatePet" + consumes: + - "application/json" + - "application/xml" + produces: + - "application/xml" + - "application/json" + parameters: + - in: "body" + name: "body" + description: "Pet object that needs to be added to the store" + required: true + schema: + $ref: "#/definitions/Pet" + responses: + 400: + description: "Invalid ID supplied" + 404: + description: "Pet not found" + 405: + description: "Validation exception" + security: + - petstore_auth: + - "write:pets" + - "read:pets" + /test/pet/findByStatus: + get: + tags: + - "pet" + summary: "Finds Pets by status" + description: "Multiple status values can be provided with comma separated strings" + operationId: "findPetsByStatus" + produces: + - "application/xml" + - "application/json" + parameters: + - name: "status" + in: "query" + description: "Status values that need to be considered for filter" + required: true + type: "array" + items: + type: "string" + enum: + - "available" + - "pending" + - "sold" + default: "available" + collectionFormat: "multi" + responses: + 200: + description: "successful operation" + schema: + type: "array" + items: + $ref: "#/definitions/Pet" + 400: + description: "Invalid status value" + security: + - petstore_auth: + - "write:pets" + - "read:pets" + /test/pet/findByTags: + get: + tags: + - "pet" + summary: "Finds Pets by tags" + description: "Muliple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing." + operationId: "findPetsByTags" + produces: + - "application/xml" + - "application/json" + parameters: + - name: "tags" + in: "query" + description: "Tags to filter by" + required: true + type: "array" + items: + type: "string" + collectionFormat: "multi" + responses: + 200: + description: "successful operation" + schema: + type: "array" + items: + $ref: "#/definitions/Pet" + 400: + description: "Invalid tag value" + security: + - petstore_auth: + - "write:pets" + - "read:pets" + deprecated: true + /test/pet/{petId}: + get: + tags: + - "pet" + summary: "Find pet by ID" + description: "Returns a single pet" + operationId: "getPetById" + produces: + - "application/xml" + - "application/json" + parameters: + - name: "petId" + in: "path" + description: "ID of pet to return" + required: true + type: "integer" + format: "int64" + responses: + 200: + description: "successful operation" + schema: + $ref: "#/definitions/Pet" + 400: + description: "Invalid ID supplied" + 404: + description: "Pet not found" + security: + - api_key: [] + post: + tags: + - "pet" + summary: "Updates a pet in the store with form data" + description: "" + operationId: "updatePetWithForm" + consumes: + - "application/x-www-form-urlencoded" + produces: + - "application/xml" + - "application/json" + parameters: + - name: "petId" + in: "path" + description: "ID of pet that needs to be updated" + required: true + type: "integer" + format: "int64" + - name: "name" + in: "formData" + description: "Updated name of the pet" + required: false + type: "string" + - name: "status" + in: "formData" + description: "Updated status of the pet" + required: false + type: "string" + responses: + 405: + description: "Invalid input" + security: + - petstore_auth: + - "write:pets" + - "read:pets" + delete: + tags: + - "pet" + summary: "Deletes a pet" + description: "" + operationId: "deletePet" + produces: + - "application/xml" + - "application/json" + parameters: + - name: "api_key" + in: "header" + required: false + type: "string" + - name: "petId" + in: "path" + description: "Pet id to delete" + required: true + type: "integer" + format: "int64" + responses: + 400: + description: "Invalid ID supplied" + 404: + description: "Pet not found" + security: + - petstore_auth: + - "write:pets" + - "read:pets" + /test/pet/{petId}/uploadImage: + post: + tags: + - "pet" + summary: "uploads an image" + description: "" + operationId: "uploadFile" + consumes: + - "multipart/form-data" + produces: + - "application/json" + parameters: + - name: "petId" + in: "path" + description: "ID of pet to update" + required: true + type: "integer" + format: "int64" + - name: "additionalMetadata" + in: "formData" + description: "Additional data to pass to server" + required: false + type: "string" + - name: "file" + in: "formData" + description: "file to upload" + required: false + type: "file" + responses: + 200: + description: "successful operation" + schema: + $ref: "#/definitions/ApiResponse" + security: + - petstore_auth: + - "write:pets" + - "read:pets" + /test/store/inventory: + get: + tags: + - "store" + summary: "Returns pet inventories by status" + description: "Returns a map of status codes to quantities" + operationId: "getInventory" + produces: + - "application/json" + parameters: [] + responses: + 200: + description: "successful operation" + schema: + type: "object" + additionalProperties: + type: "integer" + format: "int32" + security: + - api_key: [] + /test/store/order: + post: + tags: + - "store" + summary: "Place an order for a pet" + description: "" + operationId: "placeOrder" + produces: + - "application/xml" + - "application/json" + parameters: + - in: "body" + name: "body" + description: "order placed for purchasing the pet" + required: true + schema: + $ref: "#/definitions/Order" + responses: + 200: + description: "successful operation" + schema: + $ref: "#/definitions/Order" + 400: + description: "Invalid Order" + /test/store/order/{orderId}: + get: + tags: + - "store" + summary: "Find purchase order by ID" + description: "For valid response try integer IDs with value >= 1 and <= 10. Other values will generated exceptions" + operationId: "getOrderById" + produces: + - "application/xml" + - "application/json" + parameters: + - name: "orderId" + in: "path" + description: "ID of pet that needs to be fetched" + required: true + type: "integer" + maximum: 10.0 + minimum: 1.0 + format: "int64" + responses: + 200: + description: "successful operation" + schema: + $ref: "#/definitions/Order" + 400: + description: "Invalid ID supplied" + 404: + description: "Order not found" + delete: + tags: + - "store" + summary: "Delete purchase order by ID" + description: "For valid response try integer IDs with positive integer value. Negative or non-integer values will generate API errors" + operationId: "deleteOrder" + produces: + - "application/xml" + - "application/json" + parameters: + - name: "orderId" + in: "path" + description: "ID of the order that needs to be deleted" + required: true + type: "integer" + minimum: 1.0 + format: "int64" + responses: + 400: + description: "Invalid ID supplied" + 404: + description: "Order not found" + /test/user: + post: + tags: + - "user" + summary: "Create user" + description: "This can only be done by the logged in user." + operationId: "createUser" + produces: + - "application/xml" + - "application/json" + parameters: + - in: "body" + name: "body" + description: "Created user object" + required: true + schema: + $ref: "#/definitions/User" + responses: + default: + description: "successful operation" + /test/user/createWithArray: + post: + tags: + - "user" + summary: "Creates list of users with given input array" + description: "" + operationId: "createUsersWithArrayInput" + produces: + - "application/xml" + - "application/json" + parameters: + - in: "body" + name: "body" + description: "List of user object" + required: true + schema: + type: "array" + items: + $ref: "#/definitions/User" + responses: + default: + description: "successful operation" + /test/user/createWithList: + post: + tags: + - "user" + summary: "Creates list of users with given input array" + description: "" + operationId: "createUsersWithListInput" + produces: + - "application/xml" + - "application/json" + parameters: + - in: "body" + name: "body" + description: "List of user object" + required: true + schema: + type: "array" + items: + $ref: "#/definitions/User" + responses: + default: + description: "successful operation" + /test/user/login: + get: + tags: + - "user" + summary: "Logs user into the system" + description: "" + operationId: "loginUser" + produces: + - "application/xml" + - "application/json" + parameters: + - name: "username" + in: "query" + description: "The user name for login" + required: true + type: "string" + - name: "password" + in: "query" + description: "The password for login in clear text" + required: true + type: "string" + responses: + 200: + description: "successful operation" + schema: + type: "string" + headers: + X-Rate-Limit: + type: "integer" + format: "int32" + description: "calls per hour allowed by the user" + X-Expires-After: + type: "string" + format: "date-time" + description: "date in UTC when token expires" + 400: + description: "Invalid username/password supplied" + /test/user/logout: + get: + tags: + - "user" + summary: "Logs out current logged in user session" + description: "" + operationId: "logoutUser" + produces: + - "application/xml" + - "application/json" + parameters: [] + responses: + default: + description: "successful operation" + /test/user/{username}: + get: + tags: + - "user" + summary: "Get user by user name" + description: "" + operationId: "getUserByName" + produces: + - "application/xml" + - "application/json" + parameters: + - name: "username" + in: "path" + description: "The name that needs to be fetched. Use user1 for testing. " + required: true + type: "string" + responses: + 200: + description: "successful operation" + schema: + $ref: "#/definitions/User" + 400: + description: "Invalid username supplied" + 404: + description: "User not found" + put: + tags: + - "user" + summary: "Updated user" + description: "This can only be done by the logged in user." + operationId: "updateUser" + produces: + - "application/xml" + - "application/json" + parameters: + - name: "username" + in: "path" + description: "name that need to be updated" + required: true + type: "string" + - in: "body" + name: "body" + description: "Updated user object" + required: true + schema: + $ref: "#/definitions/User" + responses: + 400: + description: "Invalid user supplied" + 404: + description: "User not found" + delete: + tags: + - "user" + summary: "Delete user" + description: "This can only be done by the logged in user." + operationId: "deleteUser" + produces: + - "application/xml" + - "application/json" + parameters: + - name: "username" + in: "path" + description: "The name that needs to be deleted" + required: true + type: "string" + responses: + 400: + description: "Invalid username supplied" + 404: + description: "User not found" +securityDefinitions: + petstore_auth: + type: "oauth2" + authorizationUrl: "http://petstore.swagger.io/oauth/dialog" + flow: "implicit" + scopes: + write:pets: "modify pets in your account" + read:pets: "read your pets" + api_key: + type: "apiKey" + name: "api_key" + in: "header" +definitions: + Order: + type: "object" + properties: + id: + type: "integer" + format: "int64" + petId: + type: "integer" + format: "int64" + quantity: + type: "integer" + format: "int32" + shipDate: + type: "string" + format: "date-time" + status: + type: "string" + description: "Order Status" + enum: + - "placed" + - "approved" + - "delivered" + complete: + type: "boolean" + default: false + xml: + name: "Order" + Category: + type: "object" + properties: + id: + type: "integer" + format: "int64" + name: + type: "string" + xml: + name: "Category" + User: + type: "object" + properties: + id: + type: "integer" + format: "int64" + username: + type: "string" + firstName: + type: "string" + lastName: + type: "string" + email: + type: "string" + password: + type: "string" + phone: + type: "string" + userStatus: + type: "integer" + format: "int32" + description: "User Status" + xml: + name: "User" + Tag: + type: "object" + properties: + id: + type: "integer" + format: "int64" + name: + type: "string" + xml: + name: "Tag" + Pet: + type: "object" + required: + - "name" + - "photoUrls" + properties: + id: + type: "integer" + format: "int64" + category: + $ref: "#/definitions/Category" + name: + type: "string" + example: "doggie" + photoUrls: + type: "array" + xml: + name: "photoUrl" + wrapped: true + items: + type: "string" + tags: + type: "array" + xml: + name: "tag" + wrapped: true + items: + $ref: "#/definitions/Tag" + status: + type: "string" + description: "pet status in the store" + enum: + - "available" + - "pending" + - "sold" + xml: + name: "Pet" + ApiResponse: + type: "object" + properties: + code: + type: "integer" + format: "int32" + type: + type: "string" + message: + type: "string" +externalDocs: + description: "Find out more about Swagger" + url: "http://swagger.io" diff --git a/src/test/resources/original-swagger.yaml b/src/test/resources/original-swagger.yaml new file mode 100644 index 00000000..35138783 --- /dev/null +++ b/src/test/resources/original-swagger.yaml @@ -0,0 +1,700 @@ +swagger: "2.0" +info: + description: "This is a sample server Petstore server. You can find out more about Swagger at [http://swagger.io](http://swagger.io) or on [irc.freenode.net, #swagger](http://swagger.io/irc/). For this sample, you can use the api key `special-key` to test the authorization filters." + version: "1.0.0" + title: "Swagger Petstore" + termsOfService: "http://swagger.io/terms/" + contact: + email: "apiteam@swagger.io" + license: + name: "Apache 2.0" + url: "http://www.apache.org/licenses/LICENSE-2.0.html" +host: "petstore.swagger.io" +basePath: "/v2/test" +tags: +- name: "pet" + description: "Everything about your Pets" + externalDocs: + description: "Find out more" + url: "http://swagger.io" +- name: "store" + description: "Access to Petstore orders" +- name: "user" + description: "Operations about user" + externalDocs: + description: "Find out more about our store" + url: "http://swagger.io" +schemes: +- "https" +- "http" +paths: + /pet: + post: + tags: + - "pet" + summary: "Add a new pet to the store" + description: "" + operationId: "addPet" + consumes: + - "application/json" + - "application/xml" + produces: + - "application/xml" + - "application/json" + parameters: + - in: "body" + name: "body" + description: "Pet object that needs to be added to the store" + required: true + schema: + $ref: "#/definitions/Pet" + responses: + 405: + description: "Invalid input" + security: + - petstore_auth: + - "write:pets" + - "read:pets" + put: + tags: + - "pet" + summary: "Update an existing pet" + description: "" + operationId: "updatePet" + consumes: + - "application/json" + - "application/xml" + produces: + - "application/xml" + - "application/json" + parameters: + - in: "body" + name: "body" + description: "Pet object that needs to be added to the store" + required: true + schema: + $ref: "#/definitions/Pet" + responses: + 400: + description: "Invalid ID supplied" + 404: + description: "Pet not found" + 405: + description: "Validation exception" + security: + - petstore_auth: + - "write:pets" + - "read:pets" + /pet/findByStatus: + get: + tags: + - "pet" + summary: "Finds Pets by status" + description: "Multiple status values can be provided with comma separated strings" + operationId: "findPetsByStatus" + produces: + - "application/xml" + - "application/json" + parameters: + - name: "status" + in: "query" + description: "Status values that need to be considered for filter" + required: true + type: "array" + items: + type: "string" + enum: + - "available" + - "pending" + - "sold" + default: "available" + collectionFormat: "multi" + responses: + 200: + description: "successful operation" + schema: + type: "array" + items: + $ref: "#/definitions/Pet" + 400: + description: "Invalid status value" + security: + - petstore_auth: + - "write:pets" + - "read:pets" + /pet/findByTags: + get: + tags: + - "pet" + summary: "Finds Pets by tags" + description: "Muliple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing." + operationId: "findPetsByTags" + produces: + - "application/xml" + - "application/json" + parameters: + - name: "tags" + in: "query" + description: "Tags to filter by" + required: true + type: "array" + items: + type: "string" + collectionFormat: "multi" + responses: + 200: + description: "successful operation" + schema: + type: "array" + items: + $ref: "#/definitions/Pet" + 400: + description: "Invalid tag value" + security: + - petstore_auth: + - "write:pets" + - "read:pets" + deprecated: true + /pet/{petId}: + get: + tags: + - "pet" + summary: "Find pet by ID" + description: "Returns a single pet" + operationId: "getPetById" + produces: + - "application/xml" + - "application/json" + parameters: + - name: "petId" + in: "path" + description: "ID of pet to return" + required: true + type: "integer" + format: "int64" + responses: + 200: + description: "successful operation" + schema: + $ref: "#/definitions/Pet" + 400: + description: "Invalid ID supplied" + 404: + description: "Pet not found" + security: + - api_key: [] + post: + tags: + - "pet" + summary: "Updates a pet in the store with form data" + description: "" + operationId: "updatePetWithForm" + consumes: + - "application/x-www-form-urlencoded" + produces: + - "application/xml" + - "application/json" + parameters: + - name: "petId" + in: "path" + description: "ID of pet that needs to be updated" + required: true + type: "integer" + format: "int64" + - name: "name" + in: "formData" + description: "Updated name of the pet" + required: false + type: "string" + - name: "status" + in: "formData" + description: "Updated status of the pet" + required: false + type: "string" + responses: + 405: + description: "Invalid input" + security: + - petstore_auth: + - "write:pets" + - "read:pets" + delete: + tags: + - "pet" + summary: "Deletes a pet" + description: "" + operationId: "deletePet" + produces: + - "application/xml" + - "application/json" + parameters: + - name: "api_key" + in: "header" + required: false + type: "string" + - name: "petId" + in: "path" + description: "Pet id to delete" + required: true + type: "integer" + format: "int64" + responses: + 400: + description: "Invalid ID supplied" + 404: + description: "Pet not found" + security: + - petstore_auth: + - "write:pets" + - "read:pets" + /pet/{petId}/uploadImage: + post: + tags: + - "pet" + summary: "uploads an image" + description: "" + operationId: "uploadFile" + consumes: + - "multipart/form-data" + produces: + - "application/json" + parameters: + - name: "petId" + in: "path" + description: "ID of pet to update" + required: true + type: "integer" + format: "int64" + - name: "additionalMetadata" + in: "formData" + description: "Additional data to pass to server" + required: false + type: "string" + - name: "file" + in: "formData" + description: "file to upload" + required: false + type: "file" + responses: + 200: + description: "successful operation" + schema: + $ref: "#/definitions/ApiResponse" + security: + - petstore_auth: + - "write:pets" + - "read:pets" + /store/inventory: + get: + tags: + - "store" + summary: "Returns pet inventories by status" + description: "Returns a map of status codes to quantities" + operationId: "getInventory" + produces: + - "application/json" + parameters: [] + responses: + 200: + description: "successful operation" + schema: + type: "object" + additionalProperties: + type: "integer" + format: "int32" + security: + - api_key: [] + /store/order: + post: + tags: + - "store" + summary: "Place an order for a pet" + description: "" + operationId: "placeOrder" + produces: + - "application/xml" + - "application/json" + parameters: + - in: "body" + name: "body" + description: "order placed for purchasing the pet" + required: true + schema: + $ref: "#/definitions/Order" + responses: + 200: + description: "successful operation" + schema: + $ref: "#/definitions/Order" + 400: + description: "Invalid Order" + /store/order/{orderId}: + get: + tags: + - "store" + summary: "Find purchase order by ID" + description: "For valid response try integer IDs with value >= 1 and <= 10. Other values will generated exceptions" + operationId: "getOrderById" + produces: + - "application/xml" + - "application/json" + parameters: + - name: "orderId" + in: "path" + description: "ID of pet that needs to be fetched" + required: true + type: "integer" + maximum: 10.0 + minimum: 1.0 + format: "int64" + responses: + 200: + description: "successful operation" + schema: + $ref: "#/definitions/Order" + 400: + description: "Invalid ID supplied" + 404: + description: "Order not found" + delete: + tags: + - "store" + summary: "Delete purchase order by ID" + description: "For valid response try integer IDs with positive integer value. Negative or non-integer values will generate API errors" + operationId: "deleteOrder" + produces: + - "application/xml" + - "application/json" + parameters: + - name: "orderId" + in: "path" + description: "ID of the order that needs to be deleted" + required: true + type: "integer" + minimum: 1.0 + format: "int64" + responses: + 400: + description: "Invalid ID supplied" + 404: + description: "Order not found" + /user: + post: + tags: + - "user" + summary: "Create user" + description: "This can only be done by the logged in user." + operationId: "createUser" + produces: + - "application/xml" + - "application/json" + parameters: + - in: "body" + name: "body" + description: "Created user object" + required: true + schema: + $ref: "#/definitions/User" + responses: + default: + description: "successful operation" + /user/createWithArray: + post: + tags: + - "user" + summary: "Creates list of users with given input array" + description: "" + operationId: "createUsersWithArrayInput" + produces: + - "application/xml" + - "application/json" + parameters: + - in: "body" + name: "body" + description: "List of user object" + required: true + schema: + type: "array" + items: + $ref: "#/definitions/User" + responses: + default: + description: "successful operation" + /user/createWithList: + post: + tags: + - "user" + summary: "Creates list of users with given input array" + description: "" + operationId: "createUsersWithListInput" + produces: + - "application/xml" + - "application/json" + parameters: + - in: "body" + name: "body" + description: "List of user object" + required: true + schema: + type: "array" + items: + $ref: "#/definitions/User" + responses: + default: + description: "successful operation" + /user/login: + get: + tags: + - "user" + summary: "Logs user into the system" + description: "" + operationId: "loginUser" + produces: + - "application/xml" + - "application/json" + parameters: + - name: "username" + in: "query" + description: "The user name for login" + required: true + type: "string" + - name: "password" + in: "query" + description: "The password for login in clear text" + required: true + type: "string" + responses: + 200: + description: "successful operation" + schema: + type: "string" + headers: + X-Rate-Limit: + type: "integer" + format: "int32" + description: "calls per hour allowed by the user" + X-Expires-After: + type: "string" + format: "date-time" + description: "date in UTC when token expires" + 400: + description: "Invalid username/password supplied" + /user/logout: + get: + tags: + - "user" + summary: "Logs out current logged in user session" + description: "" + operationId: "logoutUser" + produces: + - "application/xml" + - "application/json" + parameters: [] + responses: + default: + description: "successful operation" + /user/{username}: + get: + tags: + - "user" + summary: "Get user by user name" + description: "" + operationId: "getUserByName" + produces: + - "application/xml" + - "application/json" + parameters: + - name: "username" + in: "path" + description: "The name that needs to be fetched. Use user1 for testing. " + required: true + type: "string" + responses: + 200: + description: "successful operation" + schema: + $ref: "#/definitions/User" + 400: + description: "Invalid username supplied" + 404: + description: "User not found" + put: + tags: + - "user" + summary: "Updated user" + description: "This can only be done by the logged in user." + operationId: "updateUser" + produces: + - "application/xml" + - "application/json" + parameters: + - name: "username" + in: "path" + description: "name that need to be updated" + required: true + type: "string" + - in: "body" + name: "body" + description: "Updated user object" + required: true + schema: + $ref: "#/definitions/User" + responses: + 400: + description: "Invalid user supplied" + 404: + description: "User not found" + delete: + tags: + - "user" + summary: "Delete user" + description: "This can only be done by the logged in user." + operationId: "deleteUser" + produces: + - "application/xml" + - "application/json" + parameters: + - name: "username" + in: "path" + description: "The name that needs to be deleted" + required: true + type: "string" + responses: + 400: + description: "Invalid username supplied" + 404: + description: "User not found" +securityDefinitions: + petstore_auth: + type: "oauth2" + authorizationUrl: "http://petstore.swagger.io/oauth/dialog" + flow: "implicit" + scopes: + write:pets: "modify pets in your account" + read:pets: "read your pets" + api_key: + type: "apiKey" + name: "api_key" + in: "header" +definitions: + Order: + type: "object" + properties: + id: + type: "integer" + format: "int64" + petId: + type: "integer" + format: "int64" + quantity: + type: "integer" + format: "int32" + shipDate: + type: "string" + format: "date-time" + status: + type: "string" + description: "Order Status" + enum: + - "placed" + - "approved" + - "delivered" + complete: + type: "boolean" + default: false + xml: + name: "Order" + Category: + type: "object" + properties: + id: + type: "integer" + format: "int64" + name: + type: "string" + xml: + name: "Category" + User: + type: "object" + properties: + id: + type: "integer" + format: "int64" + username: + type: "string" + firstName: + type: "string" + lastName: + type: "string" + email: + type: "string" + password: + type: "string" + phone: + type: "string" + userStatus: + type: "integer" + format: "int32" + description: "User Status" + xml: + name: "User" + Tag: + type: "object" + properties: + id: + type: "integer" + format: "int64" + name: + type: "string" + xml: + name: "Tag" + Pet: + type: "object" + required: + - "name" + - "photoUrls" + properties: + id: + type: "integer" + format: "int64" + category: + $ref: "#/definitions/Category" + name: + type: "string" + example: "doggie" + photoUrls: + type: "array" + xml: + name: "photoUrl" + wrapped: true + items: + type: "string" + tags: + type: "array" + xml: + name: "tag" + wrapped: true + items: + $ref: "#/definitions/Tag" + status: + type: "string" + description: "pet status in the store" + enum: + - "available" + - "pending" + - "sold" + xml: + name: "Pet" + ApiResponse: + type: "object" + properties: + code: + type: "integer" + format: "int32" + type: + type: "string" + message: + type: "string" +externalDocs: + description: "Find out more about Swagger" + url: "http://swagger.io"