From d7aa45b5284cd0456ad8d98299c456d2cac2b654 Mon Sep 17 00:00:00 2001 From: Anthony Staunton Date: Wed, 20 Sep 2023 14:56:21 +0100 Subject: [PATCH 1/5] Adding Render for Asciidoc Format --- README.md | 16 +- .../openapitools/openapidiff/cli/Main.java | 14 + .../core/output/AsciidocRender.java | 311 ++++++++++++++++++ .../openapidiff/core/AsciidocRenderTest.java | 43 +++ 4 files changed, 383 insertions(+), 1 deletion(-) create mode 100644 core/src/main/java/org/openapitools/openapidiff/core/output/AsciidocRender.java create mode 100644 core/src/test/java/org/openapitools/openapidiff/core/AsciidocRenderTest.java diff --git a/README.md b/README.md index 60d722e7f..ce1ed5087 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ Compare two OpenAPI specifications (3.x) and render the difference to HTML plain * Depth comparison of parameters, responses, endpoint, http method (GET,POST,PUT,DELETE...) * Supports swagger api Authorization * Render difference of property with Expression Language -* HTML, Markdown & JSON render +* HTML, Markdown, Asciidoc & JSON render # Maven @@ -44,6 +44,7 @@ Available on [Docker Hub](https://hub.docker.com/r/openapitools/openapi-diff/) a ```bash # docker run openapitools/openapi-diff:latest usage: openapi-diff + --asciidoc export diff as asciidoc in given file --debug Print debugging information --error Print error information --fail-on-changed Fail if API changed but is backward @@ -101,6 +102,7 @@ openapi-diff can read OpenAPI specs from JSON files or HTTP URLs. ```bash $ openapi-diff --help usage: openapi-diff + --asciidoc export diff as asciidoc in given file --debug Print debugging information --error Print error information -h,--help print this message @@ -204,6 +206,18 @@ try { } ``` +#### Asciidoc + +```java +String render = new AsciidocRender().render(diff); +try { + FileWriter fw = new FileWriter("testDiff.adoc"); + fw.write(render); + fw.close(); +} catch (IOException e) { + e.printStackTrace(); +} +``` #### JSON diff --git a/cli/src/main/java/org/openapitools/openapidiff/cli/Main.java b/cli/src/main/java/org/openapitools/openapidiff/cli/Main.java index f19826a93..4970efcc7 100644 --- a/cli/src/main/java/org/openapitools/openapidiff/cli/Main.java +++ b/cli/src/main/java/org/openapitools/openapidiff/cli/Main.java @@ -17,6 +17,7 @@ import org.apache.commons.lang3.exception.ExceptionUtils; import org.openapitools.openapidiff.core.OpenApiCompare; import org.openapitools.openapidiff.core.model.ChangedOpenApi; +import org.openapitools.openapidiff.core.output.AsciidocRender; import org.openapitools.openapidiff.core.output.ConsoleRender; import org.openapitools.openapidiff.core.output.HtmlRender; import org.openapitools.openapidiff.core.output.JsonRender; @@ -88,6 +89,13 @@ public static void main(String... args) { .argName("file") .desc("export diff as markdown in given file") .build()); + options.addOption( + Option.builder() + .longOpt("asciidoc") + .hasArg() + .argName("file") + .desc("export diff as asciidoc in given file") + .build()); options.addOption( Option.builder() .longOpt("html") @@ -191,6 +199,12 @@ public static void main(String... args) { OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream); mdRender.render(result, outputStreamWriter); } + if (line.hasOption("asciidoc")) { + AsciidocRender adocRender = new AsciidocRender(); + FileOutputStream outputStream = new FileOutputStream(line.getOptionValue("asciidoc")); + OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream); + adocRender.render(result, outputStreamWriter); + } if (line.hasOption("text")) { FileOutputStream outputStream = new FileOutputStream(line.getOptionValue("text")); OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream); diff --git a/core/src/main/java/org/openapitools/openapidiff/core/output/AsciidocRender.java b/core/src/main/java/org/openapitools/openapidiff/core/output/AsciidocRender.java new file mode 100644 index 000000000..d11b3d3db --- /dev/null +++ b/core/src/main/java/org/openapitools/openapidiff/core/output/AsciidocRender.java @@ -0,0 +1,311 @@ +package org.openapitools.openapidiff.core.output; + +import static org.openapitools.openapidiff.core.model.Changed.result; + +import io.swagger.v3.oas.models.media.ArraySchema; +import io.swagger.v3.oas.models.media.Schema; +import io.swagger.v3.oas.models.parameters.Parameter; +import io.swagger.v3.oas.models.responses.ApiResponse; +import java.io.IOException; +import java.io.OutputStreamWriter; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Optional; +import org.apache.commons.lang3.StringUtils; +import org.openapitools.openapidiff.core.exception.RendererException; +import org.openapitools.openapidiff.core.model.*; +import org.openapitools.openapidiff.core.utils.RefPointer; +import org.openapitools.openapidiff.core.utils.RefType; + +public class AsciidocRender implements Render { + private static final int LINE_LENGTH = 74; + protected static RefPointer> refPointer = new RefPointer<>(RefType.SCHEMAS); + protected ChangedOpenApi diff; + + @Override + public void render(ChangedOpenApi diff, OutputStreamWriter outputStreamWriter) { + this.diff = diff; + if (diff.isUnchanged()) { + safelyAppend( + outputStreamWriter, + bigTitle( + diff.getNewSpecOpenApi().getInfo().getTitle(), + diff.getNewSpecOpenApi().getInfo().getVersion())); + safelyAppend(outputStreamWriter, System.lineSeparator()); + safelyAppend(outputStreamWriter, System.lineSeparator()); + safelyAppend(outputStreamWriter, "NOTE: No differences. Specifications are equivalents"); + } else { + safelyAppend( + outputStreamWriter, + bigTitle( + diff.getNewSpecOpenApi().getInfo().getTitle(), + diff.getNewSpecOpenApi().getInfo().getVersion())); + safelyAppend(outputStreamWriter, System.lineSeparator()); + safelyAppend(outputStreamWriter, ":reproducible:\n:sectlinks:\n:toc:\n"); + safelyAppend(outputStreamWriter, System.lineSeparator()); + + List newEndpoints = diff.getNewEndpoints(); + listEndpoints(newEndpoints, "What's New", outputStreamWriter); + + List missingEndpoints = diff.getMissingEndpoints(); + listEndpoints(missingEndpoints, "What's Deleted", outputStreamWriter); + + List deprecatedEndpoints = diff.getDeprecatedEndpoints(); + listEndpoints(deprecatedEndpoints, "What's Deprecated", outputStreamWriter); + + List changedOperations = diff.getChangedOperations(); + ol_changed(changedOperations, outputStreamWriter); + + safelyAppend(outputStreamWriter, System.lineSeparator()); + safelyAppend( + outputStreamWriter, + diff.isCompatible() + ? "NOTE: API changes are backward compatible" + : "WARNING: API changes broke backward compatibility"); + safelyAppend(outputStreamWriter, System.lineSeparator()); + } + try { + outputStreamWriter.close(); + } catch (IOException e) { + throw new RendererException(e); + } + } + + private void ol_changed( + List operations, OutputStreamWriter outputStreamWriter) { + if (null == operations || operations.isEmpty()) { + return; + } + safelyAppend(outputStreamWriter, title("What's Changed", 2)); + safelyAppend(outputStreamWriter, System.lineSeparator()); + for (ChangedOperation operation : operations) { + String pathUrl = operation.getPathUrl(); + String method = operation.getHttpMethod().toString(); + String desc = + Optional.ofNullable(operation.getSummary()).map(ChangedMetadata::getRight).orElse(""); + + safelyAppend(outputStreamWriter, itemEndpoint(method, pathUrl, desc)); + if (result(operation.getParameters()).isDifferent()) { + safelyAppend(outputStreamWriter, "* Parameter:\n"); + safelyAppend(outputStreamWriter, ul_param(operation.getParameters())); + safelyAppend(outputStreamWriter, System.lineSeparator()); + } + if (operation.resultRequestBody().isDifferent()) { + safelyAppend(outputStreamWriter, "* Request:\n"); + safelyAppend( + outputStreamWriter, ul_content(operation.getRequestBody().getContent(), true, 2)); + safelyAppend(outputStreamWriter, System.lineSeparator()); + } + if (operation.resultApiResponses().isDifferent()) { + safelyAppend(outputStreamWriter, "* Return Type:\n"); + safelyAppend(outputStreamWriter, ul_response(operation.getApiResponses())); + safelyAppend(outputStreamWriter, System.lineSeparator()); + } + } + } + + private String ul_response(ChangedApiResponse changedApiResponse) { + Map addResponses = changedApiResponse.getIncreased(); + Map delResponses = changedApiResponse.getMissing(); + Map changedResponses = changedApiResponse.getChanged(); + StringBuilder sb = new StringBuilder(); + for (String propName : addResponses.keySet()) { + sb.append(itemResponse("** Add ", propName)); + } + for (String propName : delResponses.keySet()) { + sb.append(itemResponse("** Deleted ", propName)); + } + for (Entry entry : changedResponses.entrySet()) { + sb.append(itemChangedResponse("** Changed ", entry.getKey(), entry.getValue())); + } + return sb.toString(); + } + + private String itemResponse(String title, String code) { + StringBuilder sb = new StringBuilder(); + String status = ""; + if (!code.equals("default") && !code.matches("[1-5]XX")) { + status = HttpStatus.getReasonPhrase(Integer.parseInt(code)); + } + sb.append(title).append(code).append(' ').append(status); + return sb.toString(); + } + + private String itemChangedResponse(String title, String contentType, ChangedResponse response) { + return itemResponse(title, contentType) + + "\n** Media types:\n" + + ul_content(response.getContent(), false, 3); + } + + private String ul_content(ChangedContent changedContent, boolean isRequest, int indent) { + StringBuilder sb = new StringBuilder(); + if (changedContent == null) { + return sb.toString(); + } + for (String propName : changedContent.getIncreased().keySet()) { + sb.append(itemContent("Added ", propName, indent)); + } + for (String propName : changedContent.getMissing().keySet()) { + sb.append(itemContent("Deleted ", propName, indent)); + } + for (String propName : changedContent.getChanged().keySet()) { + sb.append( + itemContent( + "Changed ", propName, indent, changedContent.getChanged().get(propName), isRequest)); + } + return sb.toString(); + } + + private String itemContent(String title, String contentType, int indent) { + return StringUtils.repeat('*', indent) + " " + title + contentType + "\n"; + } + + private String itemContent( + String title, + String contentType, + int indent, + ChangedMediaType changedMediaType, + boolean isRequest) { + StringBuilder sb = new StringBuilder(); + sb.append(itemContent(title, contentType, indent)) + .append(itemContent("Schema:", "", indent)) + .append(changedMediaType.isCompatible() ? "Backward compatible" : "Broken compatibility") + .append("\n"); + if (!changedMediaType.isCompatible()) { + sb.append(incompatibilities(changedMediaType.getSchema())); + } + return sb.toString(); + } + + private String incompatibilities(final ChangedSchema schema) { + return incompatibilities("", schema); + } + + private String incompatibilities(String propName, final ChangedSchema schema) { + StringBuilder sb = new StringBuilder(); + if (schema.getItems() != null) { + sb.append(items(propName, schema.getItems())); + } + if (schema.isCoreChanged() == DiffResult.INCOMPATIBLE && schema.isChangedType()) { + String type = type(schema.getOldSchema()) + " -> " + type(schema.getNewSchema()); + sb.append(property(propName, "Changed property type", type)); + } + String prefix = propName.isEmpty() ? "" : propName + "."; + sb.append( + properties(prefix, "Missing property", schema.getMissingProperties(), schema.getContext())); + schema + .getChangedProperties() + .forEach((name, property) -> sb.append(incompatibilities(prefix + name, property))); + return sb.toString(); + } + + private String items(String propName, ChangedSchema schema) { + return incompatibilities(propName + "[n]", schema); + } + + private String properties( + String propPrefix, String title, Map> properties, DiffContext context) { + StringBuilder sb = new StringBuilder(); + if (properties != null) { + properties.forEach((key, value) -> sb.append(resolveProperty(propPrefix, value, key, title))); + } + return sb.toString(); + } + + private String resolveProperty(String propPrefix, Schema value, String key, String title) { + try { + return property(propPrefix + key, title, resolve(value)); + } catch (Exception e) { + return property(propPrefix + key, title, type(value)); + } + } + + protected String property(String name, String title, Schema schema) { + return property(name, title, type(schema)); + } + + protected String property(String name, String title, String type) { + return String.format("*** %s: %s (%s)%n\n", title, name, type); + } + + protected Schema resolve(Schema schema) { + return refPointer.resolveRef( + diff.getNewSpecOpenApi().getComponents(), schema, schema.get$ref()); + } + + protected String type(Schema schema) { + String result = "object"; + if (schema == null) { + result = "no schema"; + } else if (schema instanceof ArraySchema) { + result = "array"; + } else if (schema.getType() != null) { + result = schema.getType(); + } + return result; + } + + private String ul_param(ChangedParameters changedParameters) { + List addParameters = changedParameters.getIncreased(); + List delParameters = changedParameters.getMissing(); + List changed = changedParameters.getChanged(); + StringBuilder sb = new StringBuilder(); + for (Parameter param : addParameters) { + sb.append(itemParam("** Add ", param)); + } + for (ChangedParameter param : changed) { + sb.append(li_changedParam(param)); + } + for (Parameter param : delParameters) { + sb.append(itemParam("** Delete ", param)); + } + return sb.toString(); + } + + private String itemParam(String title, Parameter param) { + return title + param.getName() + " in " + param.getIn() + System.lineSeparator(); + } + + private String li_changedParam(ChangedParameter changeParam) { + if (changeParam.isDeprecated()) { + return itemParam("** Deprecated ", changeParam.getNewParameter()); + } else { + return itemParam("** Changed ", changeParam.getNewParameter()); + } + } + + private String listEndpoints( + List endpoints, String title, OutputStreamWriter outputStreamWriter) { + if (null == endpoints || endpoints.isEmpty()) { + return ""; + } + StringBuilder sb = new StringBuilder(); + sb.append(title(title)); + for (Endpoint endpoint : endpoints) { + sb.append( + itemEndpoint( + endpoint.getMethod().toString(), endpoint.getPathUrl(), endpoint.getSummary())); + } + return sb.append(System.lineSeparator()).toString(); + } + + private String itemEndpoint(String method, String path, String desc) { + return String.format("=== %s%s%n", StringUtils.rightPad(method, 6), path); + } + + public String bigTitle(String title, String version) { + char ch = '='; + + return String.format("= %s (v %s)", title.toUpperCase(), version); + } + + public String title(String title) { + return this.title(title, '-'); + } + + public String title(String title, int level) { + String little = StringUtils.repeat("=", level); + return String.format("%s %s", little, title); + } +} diff --git a/core/src/test/java/org/openapitools/openapidiff/core/AsciidocRenderTest.java b/core/src/test/java/org/openapitools/openapidiff/core/AsciidocRenderTest.java new file mode 100644 index 000000000..f60386125 --- /dev/null +++ b/core/src/test/java/org/openapitools/openapidiff/core/AsciidocRenderTest.java @@ -0,0 +1,43 @@ +package org.openapitools.openapidiff.core; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.io.ByteArrayOutputStream; +import java.io.OutputStreamWriter; +import org.junit.jupiter.api.Test; +import org.openapitools.openapidiff.core.model.ChangedOpenApi; +import org.openapitools.openapidiff.core.output.AsciidocRender; + +public class AsciidocRenderTest { + @Test + public void renderDoesNotFailWhenPropertyHasBeenRemoved() { + AsciidocRender render = new AsciidocRender(); + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream); + ChangedOpenApi diff = + OpenApiCompare.fromLocations("missing_property_1.yaml", "missing_property_2.yaml"); + render.render(diff, outputStreamWriter); + assertThat(outputStream.toString()).isNotBlank(); + } + + @Test + public void renderDoesNotCauseStackOverflowWithRecursiveDefinitions() { + AsciidocRender render = new AsciidocRender(); + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream); + ChangedOpenApi diff = OpenApiCompare.fromLocations("recursive_old.yaml", "recursive_new.yaml"); + render.render(diff, outputStreamWriter); + assertThat(outputStream.toString()).isNotBlank(); + } + + @Test + public void renderDoesNotFailWhenHTTPStatusCodeIsRange() { + AsciidocRender render = new AsciidocRender(); + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream); + ChangedOpenApi diff = + OpenApiCompare.fromLocations("range_statuscode_1.yaml", "range_statuscode_2.yaml"); + render.render(diff, outputStreamWriter); + assertThat(outputStream.toString()).isNotBlank(); + } +} From 4a7236d8577d6dea340095780d055f13df387b1c Mon Sep 17 00:00:00 2001 From: Anthony Staunton Date: Wed, 20 Sep 2023 14:59:22 +0100 Subject: [PATCH 2/5] Fixing bug with Console Render Current output: -------------------------------------------------------------------------- -- What's Changed -- -------------------------------------------------------------------------- Request: - Deleted application/xml - Changed application/json Schema: Backward compatible - PUT /pet Documented Output: -------------------------------------------------------------------------- -- What's Changed -- -------------------------------------------------------------------------- - PUT /pet Request: - Deleted application/xml - Changed application/json Schema: Backward compatible --- .../org/openapitools/openapidiff/core/output/ConsoleRender.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/java/org/openapitools/openapidiff/core/output/ConsoleRender.java b/core/src/main/java/org/openapitools/openapidiff/core/output/ConsoleRender.java index a3e3a31ee..41713f64e 100644 --- a/core/src/main/java/org/openapitools/openapidiff/core/output/ConsoleRender.java +++ b/core/src/main/java/org/openapitools/openapidiff/core/output/ConsoleRender.java @@ -76,6 +76,7 @@ private void ol_changed( String desc = Optional.ofNullable(operation.getSummary()).map(ChangedMetadata::getRight).orElse(""); + safelyAppend(outputStreamWriter, itemEndpoint(method, pathUrl, desc)); if (result(operation.getParameters()).isDifferent()) { safelyAppend(outputStreamWriter, StringUtils.repeat(' ', 2)); safelyAppend(outputStreamWriter, "Parameter:"); @@ -94,7 +95,6 @@ private void ol_changed( safelyAppend(outputStreamWriter, System.lineSeparator()); safelyAppend(outputStreamWriter, ul_response(operation.getApiResponses())); } - safelyAppend(outputStreamWriter, itemEndpoint(method, pathUrl, desc)); } } From d7df464e09ce35e26ca4d4a7f4cfddeecd19db2c Mon Sep 17 00:00:00 2001 From: Anthony Staunton Date: Wed, 20 Sep 2023 15:26:00 +0100 Subject: [PATCH 3/5] Updating Asciidoc test to verify valid output --- .../openapidiff/core/AsciidocRenderTest.java | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/core/src/test/java/org/openapitools/openapidiff/core/AsciidocRenderTest.java b/core/src/test/java/org/openapitools/openapidiff/core/AsciidocRenderTest.java index f60386125..95a19e508 100644 --- a/core/src/test/java/org/openapitools/openapidiff/core/AsciidocRenderTest.java +++ b/core/src/test/java/org/openapitools/openapidiff/core/AsciidocRenderTest.java @@ -40,4 +40,32 @@ public void renderDoesNotFailWhenHTTPStatusCodeIsRange() { render.render(diff, outputStreamWriter); assertThat(outputStream.toString()).isNotBlank(); } + + @Test + public void validateAsciiDocChangeFile() { + AsciidocRender render = new AsciidocRender(); + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream); + ChangedOpenApi diff = + OpenApiCompare.fromLocations("missing_property_1.yaml", "missing_property_2.yaml"); + render.render(diff, outputStreamWriter); + assertThat(outputStream.toString()) + .isEqualTo( + "= TITLE (v 1.0.0)\n" + + ":reproducible:\n" + + ":sectlinks:\n" + + ":toc:\n" + + "\n" + + "== What's Changed\n" + + "=== GET /\n" + + "* Return Type:\n" + + "** Changed default \n" + + "** Media types:\n" + + "*** Changed application/json\n" + + "*** Schema:\n" + + "Backward compatible\n" + + "\n" + + "\n" + + "NOTE: API changes are backward compatible\n"); + } } From 769bc3b9080123b503e07c6c6ae2e3adf696b247 Mon Sep 17 00:00:00 2001 From: Anthony Staunton Date: Wed, 20 Sep 2023 15:26:40 +0100 Subject: [PATCH 4/5] Updating Maven Plugin to add Asciidoc Rebdering --- .../openapidiff/maven/OpenApiDiffMojo.java | 9 +++++++++ .../openapidiff/maven/OpenApiDiffMojoTest.java | 15 +++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/maven/src/main/java/org/openapitools/openapidiff/maven/OpenApiDiffMojo.java b/maven/src/main/java/org/openapitools/openapidiff/maven/OpenApiDiffMojo.java index 7e0e82fb7..c9aec95d1 100644 --- a/maven/src/main/java/org/openapitools/openapidiff/maven/OpenApiDiffMojo.java +++ b/maven/src/main/java/org/openapitools/openapidiff/maven/OpenApiDiffMojo.java @@ -14,6 +14,7 @@ import org.apache.maven.plugins.annotations.Parameter; import org.openapitools.openapidiff.core.OpenApiCompare; import org.openapitools.openapidiff.core.model.ChangedOpenApi; +import org.openapitools.openapidiff.core.output.AsciidocRender; import org.openapitools.openapidiff.core.output.ConsoleRender; import org.openapitools.openapidiff.core.output.JsonRender; import org.openapitools.openapidiff.core.output.MarkdownRender; @@ -46,6 +47,9 @@ public class OpenApiDiffMojo extends AbstractMojo { @Parameter(property = "markdownOutputFileName") String markdownOutputFileName; + @Parameter(property = "asciidocOutputFileName") + String asciidocOutputFileName; + @Override public void execute() throws MojoExecutionException, MojoFailureException { if (Boolean.TRUE.equals(skip)) { @@ -67,6 +71,7 @@ public void execute() throws MojoExecutionException, MojoFailureException { writeDiffAsTextToFile(diff); writeDiffAsJsonToFile(diff); writeDiffAsMarkdownToFile(diff); + writeDiffAsAsciidocToFile(diff); if (failOnIncompatible && diff.isIncompatible()) { throw new BackwardIncompatibilityException("The API changes broke backward compatibility"); @@ -91,4 +96,8 @@ private void writeDiffAsJsonToFile(final ChangedOpenApi diff) { private void writeDiffAsMarkdownToFile(final ChangedOpenApi diff) { writeToFile(new MarkdownRender(), diff, markdownOutputFileName); } + + private void writeDiffAsAsciidocToFile(final ChangedOpenApi diff) { + writeToFile(new AsciidocRender(), diff, asciidocOutputFileName); + } } diff --git a/maven/src/test/java/org/openapitools/openapidiff/maven/OpenApiDiffMojoTest.java b/maven/src/test/java/org/openapitools/openapidiff/maven/OpenApiDiffMojoTest.java index 10bd186e5..01f166fe4 100644 --- a/maven/src/test/java/org/openapitools/openapidiff/maven/OpenApiDiffMojoTest.java +++ b/maven/src/test/java/org/openapitools/openapidiff/maven/OpenApiDiffMojoTest.java @@ -25,6 +25,7 @@ class OpenApiDiffMojoTest { private final File consoleOutputfile = new File("target/diff.txt"); private final File markdownOutputfile = new File("target/diff.md"); private final File jsonOutputfile = new File("target/diff.json"); + private final File asciidocOutputfile = new File("target/diff.adoc"); @BeforeEach void setup() { @@ -158,6 +159,20 @@ void Should_outputToJsonFile_When_SpecIsDifferent() { assertTrue(Files.exists(jsonOutputfile.toPath())); } + @Test + void Should_outputToAsccidocFile_When_SpecIsDifferent() { + final OpenApiDiffMojo mojo = new OpenApiDiffMojo(); + mojo.oldSpec = oldSpecFile.getAbsolutePath(); + mojo.newSpec = newSpecFile.getAbsolutePath(); + + mojo.asciidocOutputFileName = asciidocOutputfile.getAbsolutePath(); + mojo.failOnChanged = true; + + assertThrows(ApiChangedException.class, mojo::execute); + + assertTrue(Files.exists(asciidocOutputfile.toPath())); + } + private void cleanupGeneratedFiles() { try { Files.deleteIfExists(Paths.get(consoleOutputfile.getPath())); From 5a6aff6170ca2e389961d140990c4bb3a7602611 Mon Sep 17 00:00:00 2001 From: Anthony Staunton Date: Wed, 20 Sep 2023 15:48:59 +0100 Subject: [PATCH 5/5] Fixing bug found in Asciidoc generated for Range Status changes, and adding in test case --- .../core/output/AsciidocRender.java | 4 +-- .../openapidiff/core/AsciidocRenderTest.java | 25 +++++++++++++++++++ 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/core/src/main/java/org/openapitools/openapidiff/core/output/AsciidocRender.java b/core/src/main/java/org/openapitools/openapidiff/core/output/AsciidocRender.java index d11b3d3db..997241dc2 100644 --- a/core/src/main/java/org/openapitools/openapidiff/core/output/AsciidocRender.java +++ b/core/src/main/java/org/openapitools/openapidiff/core/output/AsciidocRender.java @@ -128,13 +128,13 @@ private String itemResponse(String title, String code) { if (!code.equals("default") && !code.matches("[1-5]XX")) { status = HttpStatus.getReasonPhrase(Integer.parseInt(code)); } - sb.append(title).append(code).append(' ').append(status); + sb.append(title).append(code).append(' ').append(status).append("\n"); return sb.toString(); } private String itemChangedResponse(String title, String contentType, ChangedResponse response) { return itemResponse(title, contentType) - + "\n** Media types:\n" + + "** Media types:\n" + ul_content(response.getContent(), false, 3); } diff --git a/core/src/test/java/org/openapitools/openapidiff/core/AsciidocRenderTest.java b/core/src/test/java/org/openapitools/openapidiff/core/AsciidocRenderTest.java index 95a19e508..dae2440eb 100644 --- a/core/src/test/java/org/openapitools/openapidiff/core/AsciidocRenderTest.java +++ b/core/src/test/java/org/openapitools/openapidiff/core/AsciidocRenderTest.java @@ -68,4 +68,29 @@ public void validateAsciiDocChangeFile() { + "\n" + "NOTE: API changes are backward compatible\n"); } + + @Test + public void validateAsciiDocRangeStatus() { + AsciidocRender render = new AsciidocRender(); + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream); + ChangedOpenApi diff = + OpenApiCompare.fromLocations("range_statuscode_1.yaml", "range_statuscode_2.yaml"); + render.render(diff, outputStreamWriter); + assertThat(outputStream.toString()) + .isEqualTo( + "= PROJECTS API (v 1.0.0)\n" + + ":reproducible:\n" + + ":sectlinks:\n" + + ":toc:\n" + + "\n" + + "== What's Changed\n" + + "=== GET /pet/\n" + + "* Return Type:\n" + + "** Add 4XX \n" + + "** Deleted 405 Method Not Allowed\n" + + "\n" + + "\n" + + "WARNING: API changes broke backward compatibility\n"); + } }