Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test: enhance OAS 3.1 tests #1858

Merged
merged 1 commit into from
Nov 28, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion NOTICE
Original file line number Diff line number Diff line change
@@ -1,4 +1,15 @@
Swagger Parser - ${pom.name}
Copyright (c) 2015. SmartBear Software Inc.
Swagger Parser - ${pom.name} is licensed under Apache 2.0 license.
Copy of the Apache 2.0 license can be found in `LICENSE` file.
Copy of the Apache 2.0 license can be found in `LICENSE` file.

ApiDOM
Copyright 2020 SmartBear Software Inc.
ApiDOM is licensed under Apache 2.0 license.
Directory modules/swagger-parser-v3/src/test/resources/3.1.0/dereference/fixtures was originally created under Apache 2.0 license in https://github.com/swagger-api/apidom repository.
Directory modules/swagger-parser-v3/src/test/resources/3.1.0/resolve/fixtures was originally created under Apache 2.0 license in https://github.com/swagger-api/apidom repository.
These directories have been copied into this project and modified. All modifications are licensed under Apache 2.0 License.
Copy of the Apache 2.0 license can be found in `LICENSES/Apache-2.0.txt` file.



7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

**NOTE:** If you're looking for `swagger-parser` 1.X and OpenAPI 2.0, please refer to [v1 branch](https://github.com/swagger-api/swagger-parser/tree/v1)

**NOTE:** Since version 2.1.0 Swagger Parser supports OpenAPI 3.1; see [this page](https://github.com/swagger-api/swagger-core/wiki/Swagger-2.X---OpenAPI-3.1) for details

![Build Master - Java 8, 11, and 14](https://github.com/swagger-api/swagger-parser/workflows/Build%20Test%20Deploy%20master/badge.svg?branch=master)

# Table of contents
Expand All @@ -18,6 +20,7 @@
- [Flatten](#3-flatten)
- [ResolveCombinators](#4-resolvecombinators)
- [Extensions](#extensions)
- [OpenAPI 3.1 Support](#openapi-31-support)
- [License](#license)

## Overview
Expand Down Expand Up @@ -657,6 +660,10 @@ This project has a core artifact--`swagger-parser`, which uses Java Service Prov

To build your own extension, you simply need to create a `src/main/resources/META-INF/services/io.swagger.v3.parser.core.extensions.SwaggerParserExtension` file with the full classname of your implementation. Your class must also implement the `io.swagger.v3.parser.core.extensions.SwaggerParserExtension` interface. Then, including your library with the `swagger-parser` module will cause it to be triggered automatically.

### OpenAPI 3.1 support

Since version 2.1.0 Swagger Parser supports OpenAPI 3.1; see [this page](https://github.com/swagger-api/swagger-core/wiki/Swagger-2.X---OpenAPI-3.1) for details

## Security contact

Please disclose any security-related issues or vulnerabilities by emailing [security@swagger.io](mailto:security@swagger.io), instead of using the public issue tracker.
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@
import io.swagger.v3.parser.core.models.SwaggerParseResult;
import io.swagger.v3.parser.processors.ComponentsProcessor;
import io.swagger.v3.parser.processors.PathsProcessor;
import io.swagger.v3.parser.reference.DereferencerContext;
import io.swagger.v3.parser.reference.DereferencersFactory;
import io.swagger.v3.parser.reference.OpenAPIDereferencer;
import io.swagger.v3.parser.util.OpenAPIDeserializer;
import io.swagger.v3.parser.util.ResolverFully;
import mockit.Injectable;
Expand Down Expand Up @@ -207,6 +210,172 @@ private void tearDownWireMockServer() {
this.wireMockServer.stop();
}

@Test
public void componentsResolver31() throws Exception {
final ObjectMapper mapper = new ObjectMapper(new YAMLFactory());

String pathFile = FileUtils.readFileToString(new File("src/test/resources/oas31.yaml.template"));
pathFile = pathFile.replace("${dynamicPort}", String.valueOf(this.serverPort));

final JsonNode rootNode = mapper.readTree(pathFile.getBytes());
final OpenAPIDeserializer deserializer = new OpenAPIDeserializer();
final SwaggerParseResult result = deserializer.deserialize(rootNode);

Assert.assertNotNull(result);
final OpenAPI openAPI = result.getOpenAPI();
Assert.assertNotNull(openAPI);
DereferencerContext dereferencerContext = new DereferencerContext(
result,
new ArrayList<>(),
null,
new ParseOptions(),
null,
null,
true
);
List<OpenAPIDereferencer> dereferencers = DereferencersFactory.getInstance().getDereferencers();
if (dereferencers.iterator().hasNext()) {
OpenAPIDereferencer dereferencer = dereferencers.iterator().next();
dereferencer.dereference(dereferencerContext, dereferencers.iterator());
}
assertEquals(dereferencerContext.getOpenApi(), openAPI);

Map<String, Schema> schemas = openAPI.getComponents().getSchemas();

//internal url schema
Schema pet = schemas.get("Pet");
Schema category = (Schema) pet.getProperties().get("category");
assertEquals(category.get$ref(),"#/components/schemas/Category");

//remote url schema
Schema user = (Schema) pet.getProperties().get("user");
// TODO uncomment when bundling of extenrnal refs gets implemented
// assertEquals(user.get$ref(),"#/components/schemas/User");


//ArraySchema items
Schema tagsProperty = (Schema) pet.getProperties().get("tags");
// TODO uncomment when bundling of extenrnal refs gets implemented
/* assertEquals(tagsProperty.getItems().get$ref(), "#/components/schemas/ExampleSchema" );
assertEquals(tagsProperty.getType(),"array");
Assert.assertNotNull(openAPI.getComponents().getSchemas().get("ExampleSchema"));*/

//Schema not
assertEquals(schemas.get("OrderRef").getNot().get$ref(), "#/components/schemas/Category");

//Schema additionalProperties
assertTrue(schemas.get("OrderRef").getAdditionalProperties() instanceof Schema);
Schema additionalProperties = (Schema) schemas.get("OrderRef").getAdditionalProperties();
// TODO uncomment when bundling of extenrnal refs gets implemented
// assertEquals(additionalProperties.get$ref(), "#/components/schemas/User");

//AllOfSchema
Schema extended = schemas.get("ExtendedErrorModel");
Schema root = (Schema) ((Schema)extended.getAllOf().get(0)).getProperties().get("rootCause");
assertEquals(root.get$ref(), "#/components/schemas/Category");


Map<String, ApiResponse> responses = openAPI.getComponents().getResponses();

//internal response headers
ApiResponse illegalInput = responses.get("IllegalInput");
assertEquals(illegalInput.getHeaders().get("X-Ref-Limit-Limit").get$ref(),"#/components/headers/X-Rate-Limit-Reset");

//internal response links
assertEquals(illegalInput.getLinks().get("address").get$ref(),"#/components/links/unsubscribe");

//internal url response schema
MediaType generalError = responses.get("GeneralError").getContent().get("application/json");
assertEquals(generalError.getSchema().get$ref(),"#/components/schemas/ExtendedErrorModel");


Map<String, RequestBody> requestBodies = openAPI.getComponents().getRequestBodies();

//internal url requestBody schema
RequestBody requestBody1 = requestBodies.get("requestBody1");
MediaType xmlMedia = requestBody1.getContent().get("application/json");
assertEquals(xmlMedia.getSchema().get$ref(),"#/components/schemas/Pet");

//internal url requestBody ArraySchema
RequestBody requestBody2 = requestBodies.get("requestBody2");
MediaType jsonMedia = requestBody2.getContent().get("application/json");
Schema items = jsonMedia.getSchema();
// TODO uncomment when bundling of extenrnal refs gets implemented
// assertEquals(items.getItems().get$ref(),"#/components/schemas/User");

//internal request body
assertEquals("#/components/requestBodies/requestBody2",requestBodies.get("requestBody3").get$ref());

//remote request body url
// TODO uncomment when bundling of extenrnal refs gets implemented
// assertEquals(requestBodies.get("reference").get$ref(),"#/components/requestBodies/remote_requestBody");

Map<String, Parameter> parameters = openAPI.getComponents().getParameters();

//remote url parameter
// TODO uncomment when bundling of extenrnal refs gets implemented
// assertEquals(parameters.get("remoteParameter").get$ref(),"#/components/parameters/parameter");


//internal Schema Parameter
assertEquals(parameters.get("newParam").getSchema().get$ref(),"#/components/schemas/Tag");


//parameter content schema

assertEquals(parameters.get("contentParameter").getContent().get("application/json").getSchema().get$ref(),"#/components/schemas/ExtendedErrorModel");

//internal Schema header
Map<String, Header> headers = openAPI.getComponents().getHeaders();
//header remote schema ref
// TODO uncomment when bundling of extenrnal refs gets implemented
// assertEquals(headers.get("X-Rate-Limit-Remaining").getSchema().get$ref(),"#/components/schemas/User");

//header examples
assertEquals(headers.get("X-Rate-Limit-Reset").getExamples().get("headerExample").get$ref(), "#/components/examples/dog" );
//remote header ref
// TODO uncomment when bundling of extenrnal refs gets implemented
// assertEquals(headers.get("X-Ref-Limit-Limit").get$ref(),"#/components/headers/X-Rate-Limit-Reset" );


//header content
assertEquals(headers.get("X-Rate-Limit-Reset").getContent().get("application/json").getSchema().get$ref(),"#/components/schemas/ExtendedErrorModel");

Map<String, Example> examples = openAPI.getComponents().getExamples();

//internal url example
Example frogExample = examples.get("frog");
assertEquals(frogExample.get$ref(),"#/components/examples/cat");

//remote example url
// TODO uncomment when bundling of extenrnal refs gets implemented
// assertEquals(examples.get("referenceCat").get$ref(),"#/components/examples/example");


SecurityScheme remoteScheme = openAPI.getComponents().getSecuritySchemes().get("remote_reference");
// TODO uncomment when bundling of extenrnal refs gets implemented
// assertEquals(remoteScheme.getType(), SecurityScheme.Type.OAUTH2);


Map<String, Link> links = openAPI.getComponents().getLinks();
//internal link
assertEquals(openAPI.getComponents().getLinks().get("referenced").get$ref(),"#/components/links/unsubscribe");
//remote ref link
// TODO uncomment when bundling of extenrnal refs gets implemented
// assertEquals(openAPI.getComponents().getLinks().get("subscribe").get$ref(),"#/components/links/link");


Map<String, Callback> callbacks = openAPI.getComponents().getCallbacks();
// internal callback reference
assertEquals(callbacks.get("referenced").get$ref(),"#/components/callbacks/failed");
//callback pathItem -> operation ->requestBody
assertEquals(callbacks.get("heartbeat").get("$request.query.heartbeat-url").getPost().getRequestBody().get$ref(),"#/components/requestBodies/requestBody3");
//remote callback ref
// TODO uncomment when bundling of extenrnal refs gets implemented
// assertEquals(callbacks.get("remoteCallback").get$ref(),"#/components/callbacks/callback");

}

@Test
public void componentsResolver() throws Exception {
final ObjectMapper mapper = new ObjectMapper(new YAMLFactory());
Expand Down Expand Up @@ -236,7 +405,7 @@ public void componentsResolver() throws Exception {


//ArraySchema items
ArraySchema tagsProperty = (ArraySchema) pet.getProperties().get("tags");
Schema tagsProperty = (ArraySchema) pet.getProperties().get("tags");
assertEquals(tagsProperty.getItems().get$ref(), "#/components/schemas/ExampleSchema" );
assertEquals(tagsProperty.getType(),"array");
Assert.assertNotNull(openAPI.getComponents().getSchemas().get("ExampleSchema"));
Expand All @@ -250,8 +419,8 @@ public void componentsResolver() throws Exception {
assertEquals(additionalProperties.get$ref(), "#/components/schemas/User");

//AllOfSchema
ComposedSchema extended = (ComposedSchema) schemas.get("ExtendedErrorModel");
Schema root = (Schema) extended.getAllOf().get(0).getProperties().get("rootCause");
Schema extended = (ComposedSchema) schemas.get("ExtendedErrorModel");
Schema root = (Schema)((Schema) extended.getAllOf().get(0)).getProperties().get("rootCause");
assertEquals(root.get$ref(), "#/components/schemas/Category");


Expand Down Expand Up @@ -595,7 +764,7 @@ public void testIssue1170(@Injectable final List<AuthorizationValue> auths) {
assertTrue(colouringPropertySchema == colouringsSchema);

}

@Test
public void testIssue1706() {
String path = "/issue-1706/SimpleRequestResponseRef.json";
Expand All @@ -606,19 +775,19 @@ public void testIssue1706() {
options.setResolveRequestBody(true);

OpenAPI openAPI = new OpenAPIV3Parser().readLocation(path, null, options).getOpenAPI();

// RequestBody should be inline
assertTrue(openAPI.getPaths().get("/resource").getPost().getRequestBody().get$ref() == null);
assertTrue(openAPI.getPaths().get("/resource").getPost().getRequestBody().getContent() != null);
assertTrue(openAPI.getPaths().get("/resource").getPost().getRequestBody().getContent().get("application/json").getSchema() instanceof ObjectSchema);

// Responses are already by default made inline in case referenced.
assertTrue(openAPI.getPaths().get("/resource").getPost().getResponses().get("200").get$ref() == null);
assertTrue(openAPI.getPaths().get("/resource").getPost().getResponses().get("200").getContent() != null);
assertTrue(openAPI.getPaths().get("/resource").getPost().getResponses().get("200").getContent().get("application/json").getSchema() instanceof ObjectSchema);
assertTrue(openAPI.getPaths().get("/resource").getPost().getResponses().get("200").getContent().get("application/json").getSchema() instanceof ObjectSchema);
}



@Test
public void selfReferenceTest(@Injectable final List<AuthorizationValue> auths) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package io.swagger.v3.parser.test;

import io.swagger.v3.core.util.Yaml31;
import io.swagger.v3.parser.OpenAPIV3Parser;
import io.swagger.v3.parser.core.models.ParseOptions;
import io.swagger.v3.parser.core.models.SwaggerParseResult;
import org.apache.commons.io.FileUtils;
import org.testng.annotations.Test;

import java.io.File;

public class OpenAPIV31ParserFSFullTest {

@Test
public void testFull() throws Exception {
ParseOptions p = new ParseOptions();
p.setResolve(true);
String uri = "3.1.0/dereference/fullFS/root.json";
SwaggerParseResult swaggerParseResult = new OpenAPIV3Parser().readLocation(uri, null, p);
org.testng.Assert.assertEquals(Yaml31.pretty(swaggerParseResult.getOpenAPI()), FileUtils.readFileToString(new File("src/test/resources/3.1.0/dereference/fullFS/dereferenced.yaml")));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
openapi: 3.1.0
servers:
- url: /
paths:
/path1:
summary: path item summary
description: /path3 ex2
get: {}
/relativeref:
get:
description: RelativeRef domain
operationId: RelativeRef PathItem
responses:
"200":
description: OK
/internalref:
$ref: '#/components/pathItems/InternalRef'
/internalreftoexternal:
$ref: '#/components/pathItems/InternalRefToExternal'
/internal:
get:
description: Internal PathItem
operationId: Internal PathItem
responses:
"200":
description: OK
components:
schemas:
Indirection:
type: object
description: VALUE ex3schema
properties:
prop1:
type: string
IndirectionSiblings:
type: object
description: IndirectionSiblings root
properties:
prop1:
type: string
parameters:
userId:
description: userId root
$ref: '#/components/parameters/indirection1'
indirection1:
$ref: '#/components/parameters/userIdRef'
indirection2:
description: indirection2 root
$ref: '#/components/parameters/userIdRef'
userIdRef:
name: userId
in: query
description: userIdRef root
required: true
style: form
explode: true
externalRef:
name: externalParameter
in: query
description: externalRef root
required: true
style: form
explode: true
externalRefIndirectPointer:
description: externalRefIndirectPointer root
$ref: '#/components/parameters/externalRefIndirect3'
externalRefIndirect3:
name: externalParameter3
in: query
description: externalRefIndirect3 root
required: true
style: form
explode: true
links:
link1:
operationRef: ./ex.json#/operation
pathItems:
InternalRefToExternal:
get:
description: DomainInternalRefToExternal domain
operationId: DomainInternalRefToExternal PathItem
responses:
"200":
description: OK
InternalRef:
get:
description: InternalRef root
operationId: InternalRef PathItem
responses:
"200":
description: OK
Loading