From a2933e2c5df11a6b61781b759ef9da6b88a27b12 Mon Sep 17 00:00:00 2001 From: Marcin Kielar Date: Tue, 16 Jul 2024 08:59:09 +0200 Subject: [PATCH] Updated sttpApispec to 0.11 (which fixes softwaremill/sttp-apispec#174). Fixes #3901. Signed-off-by: Marcin Kielar --- .../docs/asyncapi/ExampleConverter.scala | 14 +++---- .../docs/asyncapi/MessagesForEndpoints.scala | 3 +- .../expected_json_example_name_summary.yml | 42 +++++++++++++++++++ .../test/resources/expected_json_examples.yml | 8 ++-- .../asyncapi/VerifyAsyncAPIYamlTest.scala | 19 +++++++++ project/Versions.scala | 2 +- 6 files changed, 73 insertions(+), 15 deletions(-) create mode 100644 docs/asyncapi-docs/src/test/resources/expected_json_example_name_summary.yml diff --git a/docs/asyncapi-docs/src/main/scala/sttp/tapir/docs/asyncapi/ExampleConverter.scala b/docs/asyncapi-docs/src/main/scala/sttp/tapir/docs/asyncapi/ExampleConverter.scala index 74b07d78bf..6d14a520e5 100644 --- a/docs/asyncapi-docs/src/main/scala/sttp/tapir/docs/asyncapi/ExampleConverter.scala +++ b/docs/asyncapi-docs/src/main/scala/sttp/tapir/docs/asyncapi/ExampleConverter.scala @@ -1,20 +1,20 @@ package sttp.tapir.docs.asyncapi import sttp.apispec._ +import sttp.apispec.asyncapi.MessageExample import sttp.tapir.{Codec, EndpointIO} import sttp.ws.WebSocketFrame private[asyncapi] object ExampleConverter { - def convertExamples[T](c: Codec[WebSocketFrame, T, _], examples: List[EndpointIO.Example[T]]): List[ExampleValue] = { + def convertExamples[T](c: Codec[WebSocketFrame, T, _], examples: List[EndpointIO.Example[T]]): List[MessageExample] = { examples .flatMap { example => - val exampleValue = c.encode(example.value) match { - case WebSocketFrame.Text(payload, _, _) => Some(payload) - case WebSocketFrame.Binary(_, _, _) => None - case _: WebSocketFrame.Control => None + c.encode(example.value) match { + case WebSocketFrame.Text(payload, _, _) => + Some(MessageExample(headers = None, Some(ExampleSingleValue(payload)), example.name, example.summary)) + case WebSocketFrame.Binary(_, _, _) => None + case _: WebSocketFrame.Control => None } - - exampleValue.map(ExampleSingleValue) } } } diff --git a/docs/asyncapi-docs/src/main/scala/sttp/tapir/docs/asyncapi/MessagesForEndpoints.scala b/docs/asyncapi-docs/src/main/scala/sttp/tapir/docs/asyncapi/MessagesForEndpoints.scala index cc1efd2718..3be81ea480 100644 --- a/docs/asyncapi-docs/src/main/scala/sttp/tapir/docs/asyncapi/MessagesForEndpoints.scala +++ b/docs/asyncapi-docs/src/main/scala/sttp/tapir/docs/asyncapi/MessagesForEndpoints.scala @@ -39,7 +39,6 @@ private[asyncapi] class MessagesForEndpoints(tschemaToASchema: TSchemaToASchema, ) private def message[T](ci: CodecWithInfo[T]): Message = { - val convertedExamples = ExampleConverter.convertExamples(ci.codec, ci.info.examples) SingleMessage( None, Some(Right(tschemaToASchema(ci.codec))), @@ -53,7 +52,7 @@ private[asyncapi] class MessagesForEndpoints(tschemaToASchema: TSchemaToASchema, Nil, None, Nil, - convertedExamples.map(example => Map("payload" -> (example :: Nil))), + ExampleConverter.convertExamples(ci.codec, ci.info.examples), Nil ) } diff --git a/docs/asyncapi-docs/src/test/resources/expected_json_example_name_summary.yml b/docs/asyncapi-docs/src/test/resources/expected_json_example_name_summary.yml new file mode 100644 index 0000000000..6db9ea6c70 --- /dev/null +++ b/docs/asyncapi-docs/src/test/resources/expected_json_example_name_summary.yml @@ -0,0 +1,42 @@ +asyncapi: 2.6.0 +info: + title: The fruit basket + version: '0.1' +channels: + /fruit: + subscribe: + operationId: onFruit + message: + $ref: '#/components/messages/integer' + publish: + operationId: sendFruit + message: + $ref: '#/components/messages/Fruit' + bindings: + ws: + method: GET +components: + schemas: + Fruit: + title: Fruit + type: object + required: + - f + properties: + f: + type: string + messages: + Fruit: + payload: + $ref: '#/components/schemas/Fruit' + contentType: application/json + examples: + - payload: + f: apple + name: Apple + summary: Sample representation of apple + integer: + payload: + type: integer + format: int32 + contentType: application/json diff --git a/docs/asyncapi-docs/src/test/resources/expected_json_examples.yml b/docs/asyncapi-docs/src/test/resources/expected_json_examples.yml index c3f86082d8..56e183aed2 100644 --- a/docs/asyncapi-docs/src/test/resources/expected_json_examples.yml +++ b/docs/asyncapi-docs/src/test/resources/expected_json_examples.yml @@ -32,14 +32,12 @@ components: contentType: application/json examples: - payload: - - f: apple + f: apple integer: payload: type: integer format: int32 contentType: application/json examples: - - payload: - - 10 - - payload: - - 42 + - payload: 10 + - payload: 42 \ No newline at end of file diff --git a/docs/asyncapi-docs/src/test/scala/sttp/tapir/docs/asyncapi/VerifyAsyncAPIYamlTest.scala b/docs/asyncapi-docs/src/test/scala/sttp/tapir/docs/asyncapi/VerifyAsyncAPIYamlTest.scala index 24758ddcd6..bd60d01d71 100644 --- a/docs/asyncapi-docs/src/test/scala/sttp/tapir/docs/asyncapi/VerifyAsyncAPIYamlTest.scala +++ b/docs/asyncapi-docs/src/test/scala/sttp/tapir/docs/asyncapi/VerifyAsyncAPIYamlTest.scala @@ -7,6 +7,7 @@ import sttp.apispec.asyncapi.{Info, Server} import sttp.capabilities.akka.AkkaStreams import sttp.model.HeaderNames import sttp.apispec.asyncapi.circe.yaml._ +import sttp.tapir.EndpointIO.Example import sttp.tapir.Schema.SName import sttp.tapir._ import sttp.tapir.docs.asyncapi.AsyncAPIDocsOptions.defaultOperationIdGenerator @@ -16,6 +17,7 @@ import sttp.tapir.docs.apispec.DocsExtension import sttp.tapir.tests.data.{Fruit, FruitAmount} import scala.io.Source +import scala.util.chaining.scalaUtilChainingOps class VerifyAsyncAPIYamlTest extends AnyFunSuite with Matchers { @@ -125,6 +127,23 @@ class VerifyAsyncAPIYamlTest extends AnyFunSuite with Matchers { actualYamlNoIndent shouldBe expectedYaml } + test("should include example name and summary") { + val e = endpoint + .in("fruit") + .out( + webSocketBody[Fruit, CodecFormat.Json, Int, CodecFormat.Json](AkkaStreams) + // TODO: missing `RequestInfo.example(example: EndpointIO.Example)` and friends + .pipe(e => e.copy(requestsInfo = e.requestsInfo.example(Example.of(Fruit("apple")).name("Apple").summary("Sample representation of apple")))) + ) + + val expectedYaml = loadYaml("expected_json_example_name_summary.yml") + + val actualYaml = AsyncAPIInterpreter().toAsyncAPI(e, "The fruit basket", "0.1").toYaml + val actualYamlNoIndent = noIndentation(actualYaml) + + actualYamlNoIndent shouldBe expectedYaml + } + test("should include required indicator for non optional inputs") { val e = endpoint .in("fruit" / query[Int]("limit").and(query[Option[Int]]("offset"))) diff --git a/project/Versions.scala b/project/Versions.scala index 6fc1a38e8b..48fa46b9d6 100644 --- a/project/Versions.scala +++ b/project/Versions.scala @@ -11,7 +11,7 @@ object Versions { val sttp = "3.9.7" val sttpModel = "1.7.11" val sttpShared = "1.3.19" - val sttpApispec = "0.10.0" + val sttpApispec = "0.11.0" val akkaHttp = "10.2.10" val akkaStreams = "2.6.20" val pekkoHttp = "1.0.1"