Skip to content

Commit

Permalink
Merge pull request #49 from eBay/byarger/parseOptions
Browse files Browse the repository at this point in the history
Issue 48 : Support OpenAPISchemaValidator's use of Swagger's ParseOptions
  • Loading branch information
yarg0007 committed Apr 29, 2024
2 parents bff0305 + e7f5cc7 commit 7ee5b97
Show file tree
Hide file tree
Showing 11 changed files with 371 additions and 23 deletions.
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
*.tar.gz
*.rar
*.har
*.json

# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
import com.ebay.nst.schema.validation.support.SchemaValidatorUtil;
import com.ebay.openapi.export.jsonschema.OpenApiToJsonSchema;
import com.fasterxml.jackson.databind.JsonNode;
import io.swagger.v3.parser.core.models.ParseOptions;

import java.util.Objects;

/**
Expand Down Expand Up @@ -51,6 +53,7 @@ public boolean getValue() {
private final boolean allowAdditionalProperties;
private final StatusCode statusCode;
private final Payload payload;
private final ParseOptions parseOptions;

/**
* Initialize the OpenAPI validator with the following values.
Expand All @@ -62,7 +65,7 @@ public boolean getValue() {
* @param requestMethod Request method to apply from the schema definition.
* @param allowAdditionalProperties Allow properties which are not in the schema definition
*/
private OpenApiSchemaValidator(String schemaResourcePath, String schemaPath, NstRequestType requestMethod, AllowAdditionalProperties allowAdditionalProperties, Payload payload, StatusCode statusCode) {
private OpenApiSchemaValidator(String schemaResourcePath, String schemaPath, NstRequestType requestMethod, AllowAdditionalProperties allowAdditionalProperties, Payload payload, StatusCode statusCode, ParseOptions parseOptions) {
this.schemaResourcePath = Objects.requireNonNull(schemaResourcePath, "Schema resource path cannot be null.");
this.schemaPath = Objects.requireNonNull(schemaPath, "Schema path cannot be null.");
this.requestMethod = Objects.requireNonNull(requestMethod, "Request method cannot be null.");
Expand All @@ -73,13 +76,14 @@ private OpenApiSchemaValidator(String schemaResourcePath, String schemaPath, Nst
}
this.payload = payload;
this.statusCode = statusCode;
this.parseOptions = parseOptions;
}

@Override
public void validate(String responseBody) throws SchemaValidationException {

OpenApiToJsonSchema openApiToJsonSchema = new OpenApiToJsonSchema(schemaResourcePath, schemaPath,
requestMethod, allowAdditionalProperties, payload.getValue(), statusCode.getValue());
requestMethod, allowAdditionalProperties, payload.getValue(), statusCode.getValue(), parseOptions);
openApiToJsonSchema.convert();
JsonNode jsonSchema = openApiToJsonSchema.getJsonSchema();

Expand All @@ -102,6 +106,7 @@ public static class Builder {
private AllowAdditionalProperties allowAdditionalProperties = AllowAdditionalProperties.YES;
private Payload payload = Payload.RESPONSE;
private StatusCode statusCode = StatusCode._200;
private ParseOptions parseOptions;

public Builder(String schemaResourcePath, String schemaPath, NstRequestType requestMethod) {
this.schemaResourcePath = Objects.requireNonNull(schemaResourcePath, "Schema resource path cannot be null.");
Expand Down Expand Up @@ -144,6 +149,16 @@ public Builder setStatusCode(StatusCode statusCode) {
return this;
}

/**
* Set the swagger parsing options. See: https://github.com/swagger-api/swagger-parser/tree/master?tab=readme-ov-file#options
* @param parseOptions Parsing options to use.
* @return Builder instance.
*/
public Builder setParseOptions(ParseOptions parseOptions) {
this.parseOptions = parseOptions;
return this;
}

/**
* Create a new OpenApiSchemaValidator instance based on the builder
* configuration.
Expand All @@ -152,7 +167,7 @@ public Builder setStatusCode(StatusCode statusCode) {
*/
public OpenApiSchemaValidator build() {
return new OpenApiSchemaValidator(schemaResourcePath, schemaPath, requestMethod, allowAdditionalProperties,
payload, statusCode);
payload, statusCode, parseOptions);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ public class OpenApiToJsonSchema {
private final List<EbaySchemaTransformer> transformers;
private final boolean useRequestModel;
private final String statusCode;
private final ParseOptions parseOptions;

/**
* Convert an OpenAPI yaml spec to JSON schema. Call 'convert()' to begin the
Expand All @@ -54,28 +55,37 @@ public class OpenApiToJsonSchema {
* @param statusCode Response code to use.
*/
public OpenApiToJsonSchema(String openApiSpecFilePath, String requestPath, NstRequestType requestMethod, boolean allowAdditionalProperties, boolean useRequestModel, String statusCode) {
this.openApiSpecFilePath = openApiSpecFilePath;
this.requestPath = requestPath;
this.requestMethod = requestMethod;
this.allowAdditionalProperties = allowAdditionalProperties;
this.useRequestModel = useRequestModel;
this.statusCode = statusCode;
this.transformers = createTransformers();
this(openApiSpecFilePath, requestPath, requestMethod, allowAdditionalProperties, useRequestModel, statusCode, new ParseOptions());
}

/**
* Convert an OpenAPI yaml spec to JSON schema. Call 'convert()' to begin the
* operation.
*
* @param openApiSpecFilePath Path to yaml spec to convert.
* @param requestPath The API request path to evaluate in the schema.
* @param requestMethod Request method corresponding to the requestPath to
* evaluate.
* @deprecated use {@link OpenApiToJsonSchema#OpenApiToJsonSchema(String, String, NstRequestType, boolean, boolean, String )}}
* @param openApiSpecFilePath Path to yaml spec to convert.
* @param requestPath The API request path to evaluate in the schema.
* @param requestMethod Request method corresponding to the requestPath to
* evaluate.
* @param allowAdditionalProperties when false, validation will fail if properties are
* present which are not defined in the schema
* @param useRequestModel True to use the request model path, false to use the
* response model path.
* @param statusCode Response code to use.
* @param parseOptions Swagger parsing options to use.
*/
@Deprecated
public OpenApiToJsonSchema(String openApiSpecFilePath, String requestPath, NstRequestType requestMethod) {
this(openApiSpecFilePath, requestPath, requestMethod, true, false, "200");
public OpenApiToJsonSchema(String openApiSpecFilePath, String requestPath, NstRequestType requestMethod, boolean allowAdditionalProperties, boolean useRequestModel, String statusCode, ParseOptions parseOptions) {
this.openApiSpecFilePath = openApiSpecFilePath;
this.requestPath = requestPath;
this.requestMethod = requestMethod;
this.allowAdditionalProperties = allowAdditionalProperties;
this.useRequestModel = useRequestModel;
this.statusCode = statusCode;
this.transformers = createTransformers();
if (parseOptions != null) {
this.parseOptions = parseOptions;
} else {
this.parseOptions = new ParseOptions();
}
}

/**
Expand Down Expand Up @@ -107,9 +117,7 @@ public synchronized JsonNode getJsonSchema() {
*/
public void convert() {

// Parse the OpenAPI yaml
ParseOptions options = new ParseOptions();
SwaggerParseResult parseResult = new OpenAPIV3Parser().readLocation(openApiSpecFilePath, null, options);
SwaggerParseResult parseResult = new OpenAPIV3Parser().readLocation(openApiSpecFilePath, null, parseOptions);
if (parseResult == null || parseResult.getOpenAPI() == null) {
throw new IllegalStateException("Unable to read yaml file from path: " + openApiSpecFilePath);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
package com.ebay.nst.schema.validation;

import com.ebay.nst.NstRequestType;
import com.ebay.nst.schema.validation.support.SchemaValidationException;
import com.ebay.utility.ResourceParser;
import io.swagger.v3.parser.core.models.ParseOptions;
import org.testng.annotations.Test;

public class OpenApiSchemaValidatorTest {

@Test
public void schemaValidatePassWithRelativePathRefs() throws Exception {

ParseOptions parseOptions = new ParseOptions();
parseOptions.setResolve(true);

OpenApiSchemaValidator validator = new OpenApiSchemaValidator.Builder("/com/ebay/nst/schema/validation/OpenApiSchemaValidatorTest/schema/root.yaml", "/test", NstRequestType.GET)
.allowAdditionalProperties(OpenApiSchemaValidator.AllowAdditionalProperties.NO).setParseOptions(parseOptions)
.build();

String testResponsePayload = ResourceParser.readInResourceFile("/com/ebay/nst/schema/validation/OpenApiSchemaValidatorTest/json/validResponse.json");

validator.validate(testResponsePayload);
}

@Test
public void schemaValidatePassWithAllLocalReferences() throws Exception {

OpenApiSchemaValidator validator = new OpenApiSchemaValidator.Builder("/com/ebay/nst/schema/validation/OpenApiSchemaValidatorTest/schema/singleRootDocumentWithReferences.yaml", "/test", NstRequestType.GET)
.allowAdditionalProperties(OpenApiSchemaValidator.AllowAdditionalProperties.NO)
.build();

String testResponsePayload = ResourceParser.readInResourceFile("/com/ebay/nst/schema/validation/OpenApiSchemaValidatorTest/json/validResponse.json");

validator.validate(testResponsePayload);
}

@Test
public void schemaValidatePassEverythingInline() throws Exception {

OpenApiSchemaValidator validator = new OpenApiSchemaValidator.Builder("/com/ebay/nst/schema/validation/OpenApiSchemaValidatorTest/schema/singleRootDocumentInlined.yaml", "/test", NstRequestType.GET)
.allowAdditionalProperties(OpenApiSchemaValidator.AllowAdditionalProperties.NO)
.build();

String testResponsePayload = ResourceParser.readInResourceFile("/com/ebay/nst/schema/validation/OpenApiSchemaValidatorTest/json/validResponse.json");

validator.validate(testResponsePayload);
}

@Test(expectedExceptions = SchemaValidationException.class)
public void schemaValidateFailWithRelativePathRefs() throws Exception {

ParseOptions parseOptions = new ParseOptions();
parseOptions.setResolve(true);

OpenApiSchemaValidator validator = new OpenApiSchemaValidator.Builder("/com/ebay/nst/schema/validation/OpenApiSchemaValidatorTest/schema/root.yaml", "/test", NstRequestType.GET)
.allowAdditionalProperties(OpenApiSchemaValidator.AllowAdditionalProperties.NO).setParseOptions(parseOptions)
.build();

String testResponsePayload = ResourceParser.readInResourceFile("/com/ebay/nst/schema/validation/OpenApiSchemaValidatorTest/json/invalidResponse.json");

validator.validate(testResponsePayload);
}

@Test(expectedExceptions = SchemaValidationException.class)
public void schemaValidateFailWithAllLocalReferences() throws Exception {

OpenApiSchemaValidator validator = new OpenApiSchemaValidator.Builder("/com/ebay/nst/schema/validation/OpenApiSchemaValidatorTest/schema/singleRootDocumentWithReferences.yaml", "/test", NstRequestType.GET)
.allowAdditionalProperties(OpenApiSchemaValidator.AllowAdditionalProperties.NO)
.build();

String testResponsePayload = ResourceParser.readInResourceFile("/com/ebay/nst/schema/validation/OpenApiSchemaValidatorTest/json/invalidResponse.json");

validator.validate(testResponsePayload);
}

@Test(expectedExceptions = SchemaValidationException.class)
public void schemaValidateFailEverythingInline() throws Exception {

OpenApiSchemaValidator validator = new OpenApiSchemaValidator.Builder("/com/ebay/nst/schema/validation/OpenApiSchemaValidatorTest/schema/singleRootDocumentInlined.yaml", "/test", NstRequestType.GET)
.allowAdditionalProperties(OpenApiSchemaValidator.AllowAdditionalProperties.NO)
.build();

String testResponsePayload = ResourceParser.readInResourceFile("/com/ebay/nst/schema/validation/OpenApiSchemaValidatorTest/json/invalidResponse.json");

validator.validate(testResponsePayload);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"numberOfFruit": 100,
"typesOfApples": [
{
"name": "Fuji",
"color": 1
},
{
"name": "Gala",
"color": "YELLOW"
}
],
"typesOfBananas": [
{
"name": "Big Yellow",
"color": "YELLOW"
},
{
"name": "Old Brown",
"color": 2
}
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"numberOfFruit": 100,
"typesOfApples": [
{
"name": "Fuji",
"color": "RED"
},
{
"name": "Gala",
"color": "YELLOW"
}
],
"typesOfBananas": [
{
"name": "Big Yellow",
"color": "YELLOW"
},
{
"name": "Old Brown",
"color": "BROWN"
}
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
openapi: 3.0.0
info:
title: Root Schema
description: >-
Root Schema
version: 1.0.0
servers:
- url: 'http://ebay.com'
description: QATE
paths:
/test:
get:
summary: placeholder summary
responses:
'200':
description: Success
content:
application/json:
schema:
$ref: '#/components/schemas/TestResponse'
components:
schemas:
TestResponse:
type: object
properties:
numberOfFruit:
type: integer
format: int32
typesOfApples:
type: array
items:
$ref: "types.yaml#/components/schemas/Apple"
typesOfBananas:
type: array
items:
$ref: "types.yaml#/components/schemas/Banana"
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
openapi: 3.0.0
info:
title: Root Schema
description: >-
Root Schema
version: 1.0.0
servers:
- url: 'http://ebay.com'
description: QATE
paths:
/test:
get:
summary: placeholder summary
responses:
'200':
description: Success
content:
application/json:
schema:
$ref: '#/components/schemas/TestResponse'
components:
schemas:
TestResponse:
type: object
properties:
numberOfFruit:
type: integer
format: int32
typesOfApples:
type: array
items:
type: object
properties:
name:
type: string
color:
type: string
enum:
- RED
- GREEN
- YELLOW
typesOfBananas:
type: array
items:
type: object
properties:
name:
type: string
color:
type: string
enum:
- YELLOW
- GREEN
- BROWN

0 comments on commit 7ee5b97

Please sign in to comment.