From ed0873837bd7be7d791fc5a6b84c4e44ea76de6c Mon Sep 17 00:00:00 2001 From: Fabrice Lecomte Date: Tue, 9 Mar 2021 03:49:59 +0100 Subject: [PATCH] Test openapi schema parameters in path --- src/main/resources/openapi2.yaml | 87 +++++++++++++++++++ src/test/kotlin/integration/Article routes.kt | 23 ++--- .../kotlin/integration/steps/then/schema.kt | 30 ++++--- 3 files changed, 118 insertions(+), 22 deletions(-) diff --git a/src/main/resources/openapi2.yaml b/src/main/resources/openapi2.yaml index 029fd5f..2b206fc 100644 --- a/src/main/resources/openapi2.yaml +++ b/src/main/resources/openapi2.yaml @@ -38,6 +38,7 @@ paths: properties: result: type: array + maxItems: 50 items: properties: id: @@ -47,6 +48,7 @@ paths: type: string created_by: type: object + additionalProperties: false properties: id: type: string @@ -63,6 +65,7 @@ paths: workgroup: type: object nullable: true + additionalProperties: false properties: id: type: string @@ -71,6 +74,69 @@ paths: type: string draft: type: boolean + /articles/{article}: + parameters: + - $ref: '#/components/parameters/article' + get: + security: + - JWTAuth: [] + summary: Get one article + tags: + - article + operationId: getArticle + responses: + 200: + description: The Article objects + content: + application/json: + schema: + additionalProperties: false + properties: + id: + type: string + format: uuid + title: + type: string + anonymous: + type: boolean + content: + type: string + description: + type: string + tags: + type: array + items: + type: string + draft: + type: boolean + last_version: + type: boolean + created_by: + type: object + additionalProperties: false + properties: + id: + type: string + format: uuid + name: + type: object + properties: + first_name: + type: string + last_name: + type: string + email: + type: string + workgroup: + type: object + nullable: true + additionalProperties: false + properties: + id: + type: string + format: uuid + name: + type: string components: parameters: @@ -143,6 +209,17 @@ components: schema: type: string format: uuid + + article: + name: article + in: path + required: true + description: the ID of article + example: d91aa0cd-61d6-83cc-41bb-8d5656e130f7 + schema: + type: string + format: uuid + schemas: UUID: type: string @@ -159,6 +236,7 @@ components: properties: result: type: array + maxItems: 50 items: $ref: '#/components/schemas/UuidEntity' count: @@ -172,6 +250,7 @@ components: limit: type: integer minimum: 0 + maximum: 50 example: 50 offset: type: integer @@ -181,6 +260,14 @@ components: type: integer minimum: 0 example: 1 + + securitySchemes: + JWTAuth: + type: http + scheme: bearer + description: call /login to get token + bearerFormat: JWT + servers: - description: localhost url: http://localhost:8080 diff --git a/src/test/kotlin/integration/Article routes.kt b/src/test/kotlin/integration/Article routes.kt index 2654000..6c3f3ff 100644 --- a/src/test/kotlin/integration/Article routes.kt +++ b/src/test/kotlin/integration/Article routes.kt @@ -57,6 +57,18 @@ class `Article routes` : BaseTest() { } } + @Test + fun `I can get article by id`() { + withIntegrationApplication { + `Given I have article`(id = "65cda9f3-8991-4420-8d41-1da9da72c9bb") + `When I send a GET request`("/articles/65cda9f3-8991-4420-8d41-1da9da72c9bb") `Then the response should be` OK and { + `And the response should not be null`() + `And have property`("$.id") `whish contains` "65cda9f3-8991-4420-8d41-1da9da72c9bb" + `And schema must be valid`() + } + } + } + @Test fun `I can get versions of article by the id`() { withIntegrationApplication { @@ -69,17 +81,6 @@ class `Article routes` : BaseTest() { } } - @Test - fun `I can get article by id`() { - withIntegrationApplication { - `Given I have article`(id = "65cda9f3-8991-4420-8d41-1da9da72c9bb") - `When I send a GET request`("/articles/65cda9f3-8991-4420-8d41-1da9da72c9bb") `Then the response should be` OK and { - `And the response should not be null`() - `And have property`("$.id") `whish contains` "65cda9f3-8991-4420-8d41-1da9da72c9bb" - } - } - } - @Test fun `I can create an article`() { withIntegrationApplication { diff --git a/src/test/kotlin/integration/steps/then/schema.kt b/src/test/kotlin/integration/steps/then/schema.kt index eef0419..a2d2e83 100644 --- a/src/test/kotlin/integration/steps/then/schema.kt +++ b/src/test/kotlin/integration/steps/then/schema.kt @@ -17,13 +17,17 @@ import org.openapi4j.schema.validator.v3.SchemaValidator import java.io.File import kotlin.test.assertTrue -fun TestApplicationResponse.`And schema must be valid`() { - val uri = "/" + Url(call.request.uri).encodedPath - val operation = call.request.httpMethod - +fun TestApplicationResponse.`And schema must be valid`(route: String? = null) { OpenApi3Parser().parse(File("/openapi2.yaml".getResource().toURI()), true).let { api -> - api.getPath(uri) - ?.getOperation(operation.value.toLowerCase())?.apply { + val operation = call.request.httpMethod + val uri = route ?: "/" + Url(call.request.uri).encodedPath + val path = api.paths + .keys + .firstOrNull { uri.matches(it.replace("""\{[^{}]+}""".toRegex(), "[^/]+").toRegex()) } + + api.getPath(path) + ?.getOperation(operation.value.toLowerCase()) + ?.apply { val mediaType = call.request.contentType() val status = call.response.status() getResponse(status?.value?.toString() ?: error("HttpStatus not found")) @@ -38,11 +42,13 @@ fun TestApplicationResponse.`And schema must be valid`() { schemaValidator.validate(mapper.readTree(content), results) assertTrue(results.isValid, results.results().toString()) - } ?: error("""No path found for "$operation $uri" for status ${status.value} with media type "$mediaType".""") - }?.apply { + } + ?: error("""No path found for "$operation $uri" for status ${status.value} with media type "$mediaType".""") + } + ?.apply { Url(call.request.uri).parameters.forEach { parameter: String, values: List -> getParametersIn(api.context, "query") - ?.firstOrNull { it.name == "workgroup" }?.schema?.let { schema -> + ?.firstOrNull { it.name == parameter }?.schema?.let { schema -> val validationContext: ValidationContext = ValidationContext(api.context) val jsonNode: JsonNode = schema.toNode() val schemaValidator = SchemaValidator(validationContext, "", jsonNode) @@ -50,8 +56,10 @@ fun TestApplicationResponse.`And schema must be valid`() { schemaValidator.validate(TextNode(values.first()), params) assertTrue(params.isValid, params.results().toString()) - } ?: error("""No path found for "$operation $uri" for status "$parameter".""") + } + ?: error("""No path found for "$operation $uri" for status "$parameter".""") } - } ?: error("""No path found for "$operation $uri".""") + } + ?: error("""No path found for "$operation $uri".""") } }