From 3728252617b2be2c6bdcc85f5111b028873128b5 Mon Sep 17 00:00:00 2001 From: Gregor Rayman Date: Tue, 10 Dec 2024 21:10:03 +0100 Subject: [PATCH] Fixes #3246 - swapped validation annotations minLength and maxLength in code generated from OpenAPI --- ...equestResponseBodyInlineMinMaxLength.scala | 33 ++++++++ .../src/test/resources/ValidatedData.scala | 2 +- .../resources/inline_schema_minmaxlength.json | 82 +++++++++++++++++++ .../zio/http/gen/scala/CodeGenSpec.scala | 10 +++ .../http/endpoint/openapi/JsonSchema.scala | 2 +- 5 files changed, 127 insertions(+), 2 deletions(-) create mode 100644 zio-http-gen/src/test/resources/EndpointWithRequestResponseBodyInlineMinMaxLength.scala create mode 100644 zio-http-gen/src/test/resources/inline_schema_minmaxlength.json diff --git a/zio-http-gen/src/test/resources/EndpointWithRequestResponseBodyInlineMinMaxLength.scala b/zio-http-gen/src/test/resources/EndpointWithRequestResponseBodyInlineMinMaxLength.scala new file mode 100644 index 0000000000..1808fd4a0a --- /dev/null +++ b/zio-http-gen/src/test/resources/EndpointWithRequestResponseBodyInlineMinMaxLength.scala @@ -0,0 +1,33 @@ +package test.api.v1 + +import test.component._ +import zio.schema._ + +object Entries { + import zio.http._ + import zio.http.endpoint._ + import zio.http.codec._ + val post = Endpoint(Method.POST / "api" / "v1" / "entries") + .in[POST.RequestBody] + .out[POST.ResponseBody](status = Status.Ok) + + object POST { + import zio.schema.annotation.validate + import zio.schema.validation.Validation + + case class RequestBody( + id: Int, + @validate[String](Validation.maxLength(255) && Validation.minLength(1)) name: String, + ) + object RequestBody { + implicit val codec: Schema[RequestBody] = DeriveSchema.gen[RequestBody] + } + case class ResponseBody( + id: Int, + @validate[String](Validation.maxLength(255) && Validation.minLength(1)) name: String, + ) + object ResponseBody { + implicit val codec: Schema[ResponseBody] = DeriveSchema.gen[ResponseBody] + } + } +} diff --git a/zio-http-gen/src/test/resources/ValidatedData.scala b/zio-http-gen/src/test/resources/ValidatedData.scala index 99a34b2588..95d28f3e21 100644 --- a/zio-http-gen/src/test/resources/ValidatedData.scala +++ b/zio-http-gen/src/test/resources/ValidatedData.scala @@ -5,7 +5,7 @@ import zio.schema.annotation.validate import zio.schema.validation.Validation case class ValidatedData( - @validate[String](Validation.minLength(10)) name: String, + @validate[String](Validation.maxLength(10)) name: String, @validate[Int](Validation.greaterThan(0) && Validation.lessThan(100)) age: Int, ) object ValidatedData { diff --git a/zio-http-gen/src/test/resources/inline_schema_minmaxlength.json b/zio-http-gen/src/test/resources/inline_schema_minmaxlength.json new file mode 100644 index 0000000000..e8844cd804 --- /dev/null +++ b/zio-http-gen/src/test/resources/inline_schema_minmaxlength.json @@ -0,0 +1,82 @@ +{ + "openapi" : "3.1.0", + "info" : { + "title" : "", + "version" : "" + }, + "paths" : { + "/api/v1/entries" : { + "post" : { + "requestBody" : + { + "content" : { + "application/json" : { + "schema" : + { + "type" : + "object", + "properties" : { + "id" : { + "type" : + "integer", + "format" : "int32" + }, + "name" : { + "type" : + "string", + "minLength" : 1, + "maxLength" : 255 + } + }, + "additionalProperties" : + true, + "required" : [ + "id", + "name" + ] + } + + } + }, + "required" : true + }, + "responses" : { + "200" : + { + "description" : "", + "content" : { + "application/json" : { + "schema" : + { + "type" : + "object", + "properties" : { + "id" : { + "type" : + "integer", + "format" : "int32" + }, + "name" : { + "type" : + "string", + "minLength" : 1, + "maxLength" : 255 + } + }, + "additionalProperties" : + true, + "required" : [ + "id", + "name" + ] + } + + } + } + } + }, + "deprecated" : false + } + } + } +} diff --git a/zio-http-gen/src/test/scala/zio/http/gen/scala/CodeGenSpec.scala b/zio-http-gen/src/test/scala/zio/http/gen/scala/CodeGenSpec.scala index 16ba55d5d4..fe0aa3f375 100644 --- a/zio-http-gen/src/test/scala/zio/http/gen/scala/CodeGenSpec.scala +++ b/zio-http-gen/src/test/scala/zio/http/gen/scala/CodeGenSpec.scala @@ -198,6 +198,16 @@ object CodeGenSpec extends ZIOSpecDefault { } } } @@ TestAspect.exceptScala3, // for some reason, the temp dir is empty in Scala 3 + test("OpenAPI spec with inline schema request and response body with minLength and maxLength") { + val openAPIString = stringFromResource("/inline_schema_minmaxlength.json") + + openApiFromJsonString(openAPIString) { openAPI => + codeGenFromOpenAPI(openAPI) { testDir => + fileShouldBe(testDir, "api/v1/Entries.scala", "/EndpointWithRequestResponseBodyInlineMinMaxLength.scala") + } + } + } @@ TestAspect.exceptScala3, // for some reason, the temp dir is empty in Scala 3 + test("OpenAPI spec with inline schema request and response body, with nested object schema") { val openAPIString = stringFromResource("/inline_schema_nested.json") diff --git a/zio-http/shared/src/main/scala/zio/http/endpoint/openapi/JsonSchema.scala b/zio-http/shared/src/main/scala/zio/http/endpoint/openapi/JsonSchema.scala index d2063c2bc8..748731c110 100644 --- a/zio-http/shared/src/main/scala/zio/http/endpoint/openapi/JsonSchema.scala +++ b/zio-http/shared/src/main/scala/zio/http/endpoint/openapi/JsonSchema.scala @@ -293,8 +293,8 @@ object JsonSchema { JsonSchema.String( schema.format.map(StringFormat.fromString), schema.pattern.map(Pattern.apply), - schema.minLength, schema.maxLength, + schema.minLength, ) case schema if schema.schemaType.contains(TypeOrTypes.Type("boolean")) => JsonSchema.Boolean