diff --git a/server/src/main/java/de/zalando/zally/util/OpenApiUtil.kt b/server/src/main/java/de/zalando/zally/util/OpenApiUtil.kt index c73c34c65..67cb12055 100644 --- a/server/src/main/java/de/zalando/zally/util/OpenApiUtil.kt +++ b/server/src/main/java/de/zalando/zally/util/OpenApiUtil.kt @@ -22,7 +22,7 @@ fun OpenAPI.getAllHeaders(): Set { .map { HeaderElement(it.key, it.value) } .toSet() - val fromComponentsParams = components.parameters.orEmpty().values.extractHeaders() + val fromComponentsParams = components?.parameters.orEmpty().values.extractHeaders() val fromPaths = paths.orEmpty().flatMap { (_, path) -> val fromPathParameters = path.parameters.extractHeaders() @@ -34,7 +34,7 @@ fun OpenAPI.getAllHeaders(): Set { fromPathParameters + fromOperations } - val fromComponentsHeaders = components.headers.orEmpty().map { HeaderElement(it.key, it.value) } + val fromComponentsHeaders = components?.headers.orEmpty().map { HeaderElement(it.key, it.value) } return fromComponentsParams + fromPaths + fromComponentsHeaders } @@ -43,9 +43,9 @@ fun OpenAPI.getAllHeaders(): Set { * Returns all defined schemas of an API specification * @return a collection of schemas */ -fun OpenAPI.getAllSchemas(): Collection> = this.components.schemas.orEmpty().values + - this.components.responses.values.flatMap { it.content.values.mapNotNull { it.schema } } + - this.components.requestBodies.values.flatMap { it.content.values.mapNotNull { it.schema } } + +fun OpenAPI.getAllSchemas(): Collection> = this.components?.schemas.orEmpty().values + + this.components?.responses.orEmpty().values.flatMap { it.content.orEmpty().values.mapNotNull { it.schema } } + + this.components?.requestBodies.orEmpty().values.flatMap { it.content.orEmpty().values.mapNotNull { it.schema } } + this.paths.orEmpty().flatMap { it.value.readOperations().flatMap { it.parameters.orEmpty().mapNotNull { it.schema } } } + @@ -109,7 +109,7 @@ fun OpenAPI.getAllProperties(): Map> { * Returns all defined parameters of an API specification * @return a collection of parameters */ -fun OpenAPI.getAllParameters(): Map = this.components.parameters.orEmpty() + +fun OpenAPI.getAllParameters(): Map = this.components?.parameters.orEmpty() + this.paths.orEmpty().values.flatMap { it.parameters.orEmpty().mapNotNull { it.name to it } } + this.paths.orEmpty().values.flatMap { it.readOperations() diff --git a/server/src/test/java/de/zalando/zally/util/OpenApiUtilTest.kt b/server/src/test/java/de/zalando/zally/util/OpenApiUtilTest.kt index 3ba2c365d..99315174d 100644 --- a/server/src/test/java/de/zalando/zally/util/OpenApiUtilTest.kt +++ b/server/src/test/java/de/zalando/zally/util/OpenApiUtilTest.kt @@ -1,26 +1,334 @@ package de.zalando.zally.util +import io.swagger.v3.oas.models.Components +import io.swagger.v3.oas.models.OpenAPI +import io.swagger.v3.oas.models.Operation +import io.swagger.v3.oas.models.PathItem +import io.swagger.v3.oas.models.Paths +import io.swagger.v3.oas.models.headers.Header +import io.swagger.v3.oas.models.media.Content +import io.swagger.v3.oas.models.media.MediaType +import io.swagger.v3.oas.models.media.Schema +import io.swagger.v3.oas.models.parameters.Parameter +import io.swagger.v3.oas.models.parameters.RequestBody +import io.swagger.v3.oas.models.responses.ApiResponse +import io.swagger.v3.oas.models.responses.ApiResponses import org.junit.Test +import org.assertj.core.api.Assertions.assertThat class OpenApiUtilTest { @Test fun `getAllHeaders should return headers from components parameters`() { + val api = OpenAPI().apply { + components = Components().apply { + parameters = mapOf("User-Agent" to Parameter().apply { + `in` = "header" + name = "User-Agent" + }) + } + } + val headers = api.getAllHeaders() + + assertThat(headers).isNotNull + assertThat(headers).hasSize(1) } @Test fun `getAllHeaders should return headers from paths`() { + val api = OpenAPI().apply { + val paths = Paths() + val pathItem = PathItem() + pathItem.get = Operation().apply { + parameters = listOf(Parameter().apply { + `in` = "header" + name = "User-Agent" + }) + } + paths.addPathItem("path", pathItem) + + this.paths = paths + } + + val headers = api.getAllHeaders() + + assertThat(headers).isNotNull + assertThat(headers).hasSize(1) + } + + @Test + fun `getAllHeaders should return headers from components`() { + val api = OpenAPI().apply { + components = Components().apply { + headers = mapOf("User-Agent" to Header()) + } + } + + val headers = api.getAllHeaders() + + assertThat(headers).isNotNull + assertThat(headers).hasSize(1) + } + + @Test + fun `getAllHeaders should return empty set if no headers specified`() { + val api = OpenAPI() + + val headers = api.getAllHeaders() + + assertThat(headers).isNotNull + assertThat(headers).isEmpty() + } + + @Test + fun `getAllSchemas should return component schemas`() { + val api = OpenAPI().apply { + components = Components().apply { + schemas = mapOf("pet" to Schema()) + } + } + + val schemas = api.getAllSchemas() + + assertThat(schemas).isNotNull + assertThat(schemas).hasSize(1) + } + + @Test + fun `getAllSchemas should return component response schemas`() { + val api = OpenAPI().apply { + components = Components().apply { + responses = mapOf("response" to ApiResponse().apply { + schemas = mapOf("pet" to Schema()) + }) + } + } + + val schemas = api.getAllSchemas() + + assertThat(schemas).isNotNull + assertThat(schemas).hasSize(1) + } + + @Test + fun `getAllSchemas should return component request body schemas`() { + val api = OpenAPI().apply { + components = Components().apply { + requestBodies = mapOf("request" to RequestBody().apply { + schemas = mapOf("pet" to Schema()) + }) + } + } + + val schemas = api.getAllSchemas() + + assertThat(schemas).isNotNull + assertThat(schemas).hasSize(1) + } + + @Test + fun `getAllSchemas should return operation parameter schemas`() { + val api = OpenAPI().apply { + val paths = Paths() + val pathItem = PathItem() + pathItem.get = Operation().apply { + parameters = listOf(Parameter().apply { + `in` = "body" + schema = Schema() + }) + } + paths.addPathItem("path", pathItem) + this.paths = paths + } + + val schemas = api.getAllSchemas() + + assertThat(schemas).isNotNull + assertThat(schemas).hasSize(1) + } + + @Test + fun `getAllSchemas should return operation response schemas`() { + val api = OpenAPI().apply { + val paths = Paths() + val pathItem = PathItem() + pathItem.get = Operation().apply { + val responses = ApiResponses() + responses.addApiResponse("response", ApiResponse().apply { + val content = Content() + content.addMediaType("application/json", MediaType().apply { + schema = Schema() + }) + this.content = content + }) + this.responses = responses + } + paths.addPathItem("path", pathItem) + this.paths = paths + } + + val schemas = api.getAllSchemas() + + assertThat(schemas).isNotNull + assertThat(schemas).hasSize(1) + } + @Test + fun `getAllSchemas should return operation request body schemas`() { + val api = OpenAPI().apply { + val paths = Paths() + val pathItem = PathItem() + pathItem.get = Operation().apply { + requestBody = RequestBody().apply { + val content = Content() + content.addMediaType("application/json", MediaType().apply { + schema = Schema() + }) + this.content = content + } + } + paths.addPathItem("path", pathItem) + this.paths = paths + } + + val schemas = api.getAllSchemas() + + assertThat(schemas).isNotNull + assertThat(schemas).hasSize(1) + } + + @Test + fun `getAllSchemas should return an empty collection if no schemas are specified`() { + val api = OpenAPI() + + val schemas = api.getAllSchemas() + + assertThat(schemas).isNotNull + assertThat(schemas).isEmpty() + } + + @Test + fun `getAllTransitiveSchemas should return a set of all schemas`() { + val api = OpenAPI().apply { + components = Components().apply { + schemas = mapOf("pet" to Schema().apply { + title = "pet" + properties = mapOf( + "name" to Schema().apply { title = "name" }, + "age" to Schema().apply { title = "age" } + ) + }) + } + } + + val schemas = api.getAllTransitiveSchemas() + + assertThat(schemas).isNotNull + assertThat(schemas).hasSize(2) + } + + @Test + fun `getAllTransitiveSchemas should return an empty set if no schemas are specified`() { + val api = OpenAPI() + + val schemas = api.getAllTransitiveSchemas() + + assertThat(schemas).isNotNull + assertThat(schemas).isEmpty() + } + + @Test + fun `getAllProperties should return a map of all properties`() { + val api = OpenAPI().apply { + components = Components().apply { + schemas = mapOf("pet" to Schema().apply { + title = "pet" + properties = mapOf( + "name" to Schema().apply { title = "name" }, + "age" to Schema().apply { title = "age" } + ) + }) + } + } + + val schemas = api.getAllProperties() + + assertThat(schemas).isNotNull + assertThat(schemas).hasSize(2) + } + + @Test + fun `getAllProperties should return an empty set if no properties are specified`() { + val api = OpenAPI() + + val schemas = api.getAllProperties() + + assertThat(schemas).isNotNull + assertThat(schemas).isEmpty() + } + + @Test + fun `getAllParameters should return components parameters`() { + val api = OpenAPI().apply { + components = Components().apply { + parameters = mapOf("pet" to Parameter().apply { + name = "name" + }) + } + } + + val schemas = api.getAllParameters() + + assertThat(schemas).isNotNull + assertThat(schemas).hasSize(1) + } + + @Test + fun `getAllParameters should return paths parameters`() { + val api = OpenAPI().apply { + val paths = Paths() + val pathItem = PathItem() + pathItem.parameters = listOf(Parameter().apply { + name = "name" + }) + paths.addPathItem("path", pathItem) + this.paths = paths + } + + val schemas = api.getAllParameters() + + assertThat(schemas).isNotNull + assertThat(schemas).hasSize(1) } @Test - fun `getAllHeaders should return headers from compoents`() { + fun `getAllParameters should return path operation parameters`() { + val api = OpenAPI().apply { + val paths = Paths() + val pathItem = PathItem() + pathItem.get = Operation().apply { + parameters = listOf(Parameter().apply { + name = "name" + }) + } + paths.addPathItem("path", pathItem) + this.paths = paths + } + val schemas = api.getAllParameters() + + assertThat(schemas).isNotNull + assertThat(schemas).hasSize(1) } @Test - fun `getAllHeaders should `() { + fun `getAllParameters should return an empty map if no parameters are specified`() { + val api = OpenAPI() + + val schemas = api.getAllParameters() + assertThat(schemas).isNotNull + assertThat(schemas).isEmpty() } } \ No newline at end of file