Skip to content

Commit

Permalink
Add documentation module
Browse files Browse the repository at this point in the history
  • Loading branch information
mcruzdev committed Feb 10, 2024
1 parent c5efd5b commit d3dc028
Show file tree
Hide file tree
Showing 12 changed files with 277 additions and 1,255 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,11 @@ private static List<Stubbing> generateStubbings(Map.Entry<String, PathItem> entr
operationsMap.forEach(
(httpMethod, operation) -> {
Stubbing.StubbingBuilder builder = new Stubbing.StubbingBuilder();

Request request = Request.create(pathName, httpMethod.name());

int statusCode = getStatusCode(operation);

Response response = Response.create(
statusCode,
getResponseBody(String.valueOf(statusCode), operation));
Expand All @@ -62,37 +64,25 @@ private static List<Stubbing> generateStubbings(Map.Entry<String, PathItem> entr
}

private static String getResponseBody(final String statusCode, final Operation operation) {

if (operation.getResponses() == null) {
return "";
}

ApiResponse apiResponse = operation.getResponses().get(statusCode);
if (apiResponse == null) {
return "";
}

if (apiResponse.getContent() == null) {
return "";
if (Objects.isNull(apiResponse.getContent())) {
return null;
}

MediaType applicationJson = new ArrayList<>(apiResponse.getContent().entrySet())
.stream()
.filter(media -> media.getKey().equals(Response.DEFAULT_MEDIA_TYPE_APPLICATION_JSON))
.findFirst()
.orElseThrow(IllegalArgumentException::new)
.orElseThrow(
() -> new IllegalArgumentException(
"This extension only supports " + Response.DEFAULT_STATUS_CODE + "media type"))
.getValue();

return generateResponseBody(applicationJson.getSchema());

}

private static String generateResponseBody(final Schema<?> schema) {
String schemaType = schema.getType();
if (schemaType == null) {
return "";
}

String schemaType = Optional.ofNullable(schema.getType()).orElse(STRING_TYPE);
return switch (schemaType) {
case STRING_TYPE, INTEGER_TYPE -> (String) schema.getExample();
case OBJECT_TYPE -> readObjectExample(schema);
Expand Down Expand Up @@ -127,22 +117,18 @@ private static Map<String, Object> mapObjectExample(Map<String, Object> root, Sc
* This method attempts to retrieve the first status code defined in the {@link Operation} object.
* If the OpenAPI response contains only the "default" status code, this method will return
* {@link Response#DEFAULT_STATUS_CODE}.
* If the OpenAPI response contains more than one status code, the method returns the lowest one.
* For example, if the status codes are "200" and "400", the lowest one returned will be "200".
* If the OpenAPI response contains more than one status code, the method returns the first one.
* For example, if the status codes are "200" and after "400", this method will return the status "200".
*
* @param operation The {@link Operation} instance from which to extract the status code.
* @return An {@link Integer} representing the status code, such as 200, 201, or 400.
* @return An {@link Integer} representing the status code. e.g. 200, 300, 400, 500, etc.
*/
private static int getStatusCode(final Operation operation) {

if (operation.getResponses() == null) {
return Response.DEFAULT_STATUS_CODE;
}

final String defaultStatus = "default";
ArrayList<Map.Entry<String, ApiResponse>> apiResponses = new ArrayList<>(operation.getResponses().entrySet());
String statusCode = apiResponses.stream().findFirst()
.orElseThrow(IllegalArgumentException::new)
.orElseThrow(() -> new IllegalArgumentException("There is no status on operation"))
.getKey();

if (statusCode.contentEquals(defaultStatus)) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
package io.quarkiverse.openapi.wiremock.generator.deployment.wiremock.model;

import com.fasterxml.jackson.annotation.JsonInclude;

@JsonInclude(JsonInclude.Include.NON_EMPTY)
public class Response {

public static final Integer DEFAULT_STATUS_CODE = 200;
public static final String DEFAULT_RESPONSE_BODY = "{}";
public static final String DEFAULT_MEDIA_TYPE_APPLICATION_JSON = "application/json";
private final Integer status;
private final String body;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
import io.quarkiverse.openapi.wiremock.generator.deployment.wiremock.model.Stubbing;
import io.swagger.v3.oas.models.*;
import io.swagger.v3.oas.models.media.Schema;
import io.swagger.v3.oas.models.responses.ApiResponse;
import io.swagger.v3.oas.models.responses.ApiResponses;

class OpenApi2WiremockMapperTest {

Expand All @@ -18,7 +20,11 @@ void should_map_openapi_path_with_get_ping_to_wiremock_stubbing_correctly() {
// given
OpenAPI openAPI = new OpenAPI(SpecVersion.V31);
PathItem pathItem = new PathItem();
pathItem.operation(PathItem.HttpMethod.GET, new Operation());
Operation operation = new Operation();
ApiResponses apiResponses = new ApiResponses();
apiResponses.addApiResponse("200", new ApiResponse());
operation.setResponses(apiResponses);
pathItem.operation(PathItem.HttpMethod.GET, operation);
openAPI.setPaths(new Paths().addPathItem("/ping", pathItem));

// when
Expand All @@ -38,8 +44,15 @@ public void should_map_two_paths_to_two_stubbing_correctly() {
// given
OpenAPI openAPI = new OpenAPI(SpecVersion.V31);
PathItem pathItem = new PathItem();
pathItem.operation(PathItem.HttpMethod.GET, new Operation());
pathItem.operation(PathItem.HttpMethod.DELETE, new Operation());
ApiResponses apiResponses = new ApiResponses();
apiResponses.addApiResponse("200", new ApiResponse());
Operation getOperation = new Operation();
getOperation.setResponses(apiResponses);
pathItem.operation(PathItem.HttpMethod.GET, getOperation);
Operation deleteOperation = new Operation();

deleteOperation.setResponses(apiResponses);
pathItem.operation(PathItem.HttpMethod.DELETE, deleteOperation);
openAPI.setPaths(new Paths().addPathItem("/users/1", pathItem));

// when
Expand Down
5 changes: 5 additions & 0 deletions wiremock/docs/antora.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
name: quarkus-openapi-generator
title: Openapi Generator
version: dev
nav:
- modules/ROOT/nav.adoc
1 change: 1 addition & 0 deletions wiremock/docs/modules/ROOT/nav.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
* xref:index.adoc[Quarkus - Openapi Generator - Wiremock]
44 changes: 44 additions & 0 deletions wiremock/docs/modules/ROOT/pages/includes/features.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
The OpenAPI Generator Wiremock extensions maps OpenAPI specification and transform it into a https://wiremock.org/docs/stubbing/#bulk-importing-stubs[Bulk Importing Stubs] JSON file.

[[request-matching]]
=== Request Matching

To build the Wiremock https://wiremock.org/docs/request-matching/[Request Matching], this extension looks just to https://swagger.io/docs/specification/paths-and-operations/[Paths and Operations] OpenAPI fields.

The OpenAPI path is converted to https://swagger.io/docs/specification/paths-and-operations/[path template] following the https://www.rfc-editor.org/rfc/rfc6570[RFC 6570] standard.

[[responses]]

This extension will get the first Response status code Operation. For example, if you have the following OpenAPI Response:

[source,yaml]
----
responses:
"500":
description: "Internal Server Error"
"200":
description: "OK"
----

The extension will generate the following Wiremock Response templating:

[source,json]
----
{
"response": {
"status": 500
}
}
----

NOTE: If your Response entry does not contain `content` the Wiremock Stub `$.response.body` will be ignored.

[[media-type]]
=== Media type

IMPORTANT: This extension only supports `"application/json"` media type.

[[schema-type]]

For the first release, we chose to looks for the https://swagger.io/docs/specification/data-models/[Schema] `type` and supports only https://swagger.io/docs/specification/data-models/data-types/[Data Types] `object`, `string` and `integer` types.

81 changes: 81 additions & 0 deletions wiremock/docs/modules/ROOT/pages/includes/getting-started.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
Add the following dependency to your project's `pom.xml` file:

[source,xml]
----
<dependency>
<groupId>io.quarkiverse.openapi.generator</groupId>
<artifactId>quarkus-openapi-generator-wiremock</artifactId>
<version>3.0.0-SNAPSHOT</version>
</dependency>
----

You will also need to add or update the `quarkus-maven-plugin` configuration with the following:

WARNING: You probably already have this configuration if you created your application with https://code.quarkus.io/[Code Quarkus]. That said, double-check your configuration not to add another `plugin` entry.

[source,xml]
----
<plugin>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-maven-plugin</artifactId>
<extensions>true</extensions>
<executions>
<execution>
<goals>
<goal>build</goal>
<goal>generate-code</goal>
<goal>generate-code-tests</goal>
</goals>
</execution>
</executions>
</plugin>
----

Now, create the directory `openapi` under your `src/main/` path and add the OpenAPI spec files there. We support JSON, YAML and YML extensions.

[source,yaml]
----
openapi: 3.0.2
info:
title: Simple OpenAPI
version: 0.0.1-SNAPSHOT
paths:
/users:
get:
responses:
"200":
description: "OpenAPI Generator Wiremock Success"
content:
"application/json":
schema:
type: object
properties:
id:
type: integer
example: 1
name:
type: string
example: "John Doe"
----

Run `mvn compile` to generate your classes in `target/generated-sources/wiremock/mappings` path:

[source,json]
----
{
"mappings": [
{
"request": {
"urlPathTemplate": "/users",
"method": "GET"
},
"response": {
"status": 200,
"body": "{\"name\":\"John Doe\",\"id\":1}"
}
}
]
}
----

22 changes: 22 additions & 0 deletions wiremock/docs/modules/ROOT/pages/index.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
= Quarkus - Openapi Generator - Wiremock
:extension-status: preview


WARNING: This is the instructions for the latest SNAPSHOT version (main branch). Please, see the https://docs.quarkiverse.io/quarkus-openapi-generator/dev/index.html[latest **released** documentation] if you are looking for instructions.
Quarkus' extension for generation of server Stubs based on OpenAPI specification files.

This extension is for Wiremock Stubs generation for Dev Services only.

**Want to contribute? Great!** We try to make it easy, and all contributions, even the smaller ones, are more than welcome. This includes bug reports, fixes, documentation, examples... But first, read https://github.com/quarkiverse/quarkus-openapi-generator/blob/main/CONTRIBUTING.md[this page].

[[getting-started]]
== Getting Started

include::./includes/getting-started.adoc[leveloffset=+1, opts=optional]

[[features]]
== Wiremock Extension Features

include::./includes/features.adoc[leveloffset=+1, opts=optional]


71 changes: 71 additions & 0 deletions wiremock/docs/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>quarkus-openapi-generator-wiremock-parent</artifactId>
<groupId>io.quarkiverse.openapi.generator</groupId>
<version>3.0.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

<artifactId>quarkus-openapi-generator-wiremock-docs</artifactId>
<dependencies>
<!-- Make sure the doc is built after the other artifacts -->
<dependency>
<groupId>io.quarkiverse.openapi.generator</groupId>
<artifactId>quarkus-openapi-generator-deployment</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>it.ozimov</groupId>
<artifactId>yaml-properties-maven-plugin</artifactId>
<executions>
<execution>
<phase>initialize</phase>
<goals>
<goal>read-project-properties</goal>
</goals>
<configuration>
<files>
<file>${project.basedir}/../../.github/project.yml</file>
</files>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<executions>
<execution>
<id>copy-resources</id>
<phase>generate-resources</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>${project.basedir}/modules/ROOT/pages/includes/</outputDirectory>
<resources>
<resource>
<directory>${project.basedir}/../target/asciidoc/generated/config/</directory>
<include>quarkus-openapi-generator.adoc</include>
<filtering>false</filtering>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.asciidoctor</groupId>
<artifactId>asciidoctor-maven-plugin</artifactId>
</plugin>
</plugins>
</build>

</project>
Loading

0 comments on commit d3dc028

Please sign in to comment.