From e8969998fbadd4d080f8627c14cc25097a4a6a8c Mon Sep 17 00:00:00 2001 From: Yohan Fraga Date: Tue, 18 Feb 2025 19:10:17 -0300 Subject: [PATCH 1/7] YFS - Start tests fixing --- .../AsyncApiDocumentBuilder.cs | 6 + .../AsyncApiDocumentV2Tests.cs | 530 +++++++++--------- 2 files changed, 271 insertions(+), 265 deletions(-) diff --git a/test/LEGO.AsyncAPI.Tests/AsyncApiDocumentBuilder.cs b/test/LEGO.AsyncAPI.Tests/AsyncApiDocumentBuilder.cs index 5b4bcc6..3d8ca89 100644 --- a/test/LEGO.AsyncAPI.Tests/AsyncApiDocumentBuilder.cs +++ b/test/LEGO.AsyncAPI.Tests/AsyncApiDocumentBuilder.cs @@ -46,6 +46,12 @@ public AsyncApiDocumentBuilder WithChannel(string key, AsyncApiChannel channel) return this; } + public AsyncApiDocumentBuilder WithOperation(string key, AsyncApiOperation operation) + { + this.document.Operations.Add(key, operation); + return this; + } + public AsyncApiDocumentBuilder WithComponent(string key, AsyncApiJsonSchema schema) { if (this.document.Components == null) diff --git a/test/LEGO.AsyncAPI.Tests/AsyncApiDocumentV2Tests.cs b/test/LEGO.AsyncAPI.Tests/AsyncApiDocumentV2Tests.cs index a16f78e..636b8db 100644 --- a/test/LEGO.AsyncAPI.Tests/AsyncApiDocumentV2Tests.cs +++ b/test/LEGO.AsyncAPI.Tests/AsyncApiDocumentV2Tests.cs @@ -218,17 +218,12 @@ public void V2_AsyncApiDocument_WithStreetLightsExample_SerializesAndDeserialize }) .WithServer("scram-connections", new AsyncApiServer { - Url = "test.mykafkacluster.org:18092", + Host = "test.mykafkacluster.org:18092", Protocol = "kafka-secure", Description = "Test broker secured with scramSha256", - Security = new List + Security = new List { - new AsyncApiSecurityRequirement - { - { - new AsyncApiSecuritySchemeReference("saslScram"), new List() - }, - }, + new AsyncApiSecuritySchemeReference("#/components/securitySchemes/saslScram"), }, Tags = new List { @@ -251,17 +246,12 @@ public void V2_AsyncApiDocument_WithStreetLightsExample_SerializesAndDeserialize }) .WithServer("mtls-connections", new AsyncApiServer { - Url = "test.mykafkacluster.org:28092", + Host = "test.mykafkacluster.org:28092", Protocol = "kafka-secure", Description = "Test broker secured with X509", - Security = new List + Security = new List { - new AsyncApiSecurityRequirement - { - { - new AsyncApiSecuritySchemeReference("certs"), new List() - }, - }, + new AsyncApiSecuritySchemeReference("#/components/securitySchemes/certs"), }, Tags = new List { @@ -294,19 +284,6 @@ public void V2_AsyncApiDocument_WithStreetLightsExample_SerializesAndDeserialize "streetlightId", new AsyncApiParameterReference("#/components/parameters/streetlightId") }, }, - Publish = new AsyncApiOperation() - { - Summary = "Inform about environmental lighting conditions of a particular streetlight.", - OperationId = "receiveLightMeasurement", - Traits = new List - { - new AsyncApiOperationTraitReference("#/components/operationTraits/kafka"), - }, - Message = new List - { - new AsyncApiMessageReference("#/components/messages/lightMeasured"), - }, - }, }) .WithChannel( "smartylighting.streetlights.1.0.action.{streetlightId}.turn.on", @@ -318,18 +295,6 @@ public void V2_AsyncApiDocument_WithStreetLightsExample_SerializesAndDeserialize "streetlightId", new AsyncApiParameterReference("#/components/parameters/streetlightId") }, }, - Subscribe = new AsyncApiOperation() - { - OperationId = "turnOn", - Traits = new List - { - new AsyncApiOperationTraitReference("#/components/operationTraits/kafka"), - }, - Message = new List - { - new AsyncApiMessageReference("#/components/messages/turnOnOff"), - }, - }, }) .WithChannel( "smartylighting.streetlights.1.0.action.{streetlightId}.turn.off", @@ -341,18 +306,6 @@ public void V2_AsyncApiDocument_WithStreetLightsExample_SerializesAndDeserialize "streetlightId", new AsyncApiParameterReference("#/components/parameters/streetlightId") }, }, - Subscribe = new AsyncApiOperation() - { - OperationId = "turnOff", - Traits = new List - { - new AsyncApiOperationTraitReference("#/components/operationTraits/kafka"), - }, - Message = new List - { - new AsyncApiMessageReference("#/components/messages/turnOnOff"), - }, - }, }) .WithChannel( "smartylighting.streetlights.1.0.action.{streetlightId}.dim", @@ -364,17 +317,58 @@ public void V2_AsyncApiDocument_WithStreetLightsExample_SerializesAndDeserialize "streetlightId", new AsyncApiParameterReference("#/components/parameters/streetlightId") }, }, - Subscribe = new AsyncApiOperation() + }) + .WithOperation("receiveLightMeasurement", new AsyncApiOperation() + { + Action = AsyncApiAction.Send, + Summary = "Inform about environmental lighting conditions of a particular streetlight.", + Channel = new AsyncApiChannelReference("#/channels/smartylighting.streetlights.1.0.event.{streetlightId}.lighting.measured"), + Traits = new List + { + new AsyncApiOperationTraitReference("#/components/operationTraits/kafka"), + }, + Messages = new List + { + new("#/components/messages/lightMeasured"), + }, + }) + .WithOperation("turnOn", new AsyncApiOperation() + { + Action = AsyncApiAction.Receive, + Channel = new AsyncApiChannelReference("#/channels/smartylighting.streetlights.1.0.action.{streetlightId}.turn.on"), + Traits = new List { - OperationId = "dimLight", - Traits = new List - { new AsyncApiOperationTraitReference("#/components/operationTraits/kafka"), - }, - Message = new List - { - new AsyncApiMessageReference("#/components/messages/dimLight"), - }, + }, + Messages = new List + { + new("#/components/messages/turnOnOff"), + }, + }) + .WithOperation("turnOff", new AsyncApiOperation() + { + Action = AsyncApiAction.Receive, + Channel = new AsyncApiChannelReference("#/channels/smartylighting.streetlights.1.0.action.{streetlightId}.turn.off"), + Traits = new List + { + new AsyncApiOperationTraitReference("#/components/operationTraits/kafka"), + }, + Messages = new List + { + new("#/components/messages/turnOnOff"), + }, + }) + .WithOperation("dimLight", new AsyncApiOperation() + { + Action = AsyncApiAction.Receive, + Channel = new AsyncApiChannelReference("#/channels/smartylighting.streetlights.1.0.action.{streetlightId}.dim"), + Traits = new List + { + new AsyncApiOperationTraitReference("#/components/operationTraits/kafka"), + }, + Messages = new List + { + new("#/components/messages/dimLight"), }, }) .WithComponent("lightMeasured", new AsyncApiMessage() @@ -476,23 +470,11 @@ public void V2_AsyncApiDocument_WithStreetLightsExample_SerializesAndDeserialize Format = "date-time", Description = "Date and time when the message was sent.", }) - .WithComponent("saslScram", new AsyncApiSecurityScheme - { - Type = SecuritySchemeType.ScramSha256, - Description = "Provide your username and password for SASL/SCRAM authentication", - }) - .WithComponent("certs", new AsyncApiSecurityScheme - { - Type = SecuritySchemeType.X509, - Description = "Download the certificate files from service provider", - }) + .WithComponent("saslScram", AsyncApiSecurityScheme.ScramSha256("Provide your username and password for SASL/SCRAM authentication")) + .WithComponent("certs", AsyncApiSecurityScheme.X509("Download the certificate files from service provider")) .WithComponent("streetlightId", new AsyncApiParameter() { Description = "The ID of the streetlight.", - Schema = new AsyncApiJsonSchema() - { - Type = SchemaType.String, - }, }) .WithComponent("commonHeaders", new AsyncApiMessageTrait() { @@ -677,6 +659,8 @@ public void V2_SerializeV2_WithFullSpec_Serializes() string messageTitle = "messageTitle"; string messageSummary = "messageSummary"; string messageName = "messageName"; + string messageKeyOne = "messageKeyOne"; + string messageKeyTwo = "messageKeyTwo"; string contentType = "contentType"; string schemaFormat = "schemaFormat"; string correlationLocation = "correlationLocation"; @@ -729,7 +713,7 @@ public void V2_SerializeV2_WithFullSpec_Serializes() { Implicit = new AsyncApiOAuthFlow { - Scopes = new Dictionary + AvailableScopes = new Dictionary { { scopeKey, scopeValue }, }, @@ -745,6 +729,100 @@ public void V2_SerializeV2_WithFullSpec_Serializes() } }, }, + Messages = new Dictionary() + { + { + messageKeyOne, new AsyncApiMessage + { + Description = messageDescription, + Title = messageTitle, + Summary = messageSummary, + Name = messageName, + ContentType = contentType, + } + }, + { + messageKeyTwo, new AsyncApiMessage + { + Description = messageDescription, + Title = messageTitle, + Summary = messageSummary, + Name = messageName, + ContentType = contentType, + CorrelationId = new AsyncApiCorrelationId + { + Location = correlationLocation, + Description = correlationDescription, + Extensions = new Dictionary + { + { extensionKey, new AsyncApiAny(extensionString) }, + }, + }, + Traits = new List + { + new AsyncApiMessageTrait + { + Name = traitName, + Title = traitTitle, + Headers = new AsyncApiJsonSchema + { + Title = schemaTitle, + WriteOnly = true, + Description = schemaDescription, + Examples = new List + { + new AsyncApiAny(new ExtensionClass + { + Key = anyStringValue, + OtherKey = anyLongValue, + }), + }, + }, + Examples = new List + { + new AsyncApiMessageExample + { + Summary = exampleSummary, + Name = exampleName, + Payload = new AsyncApiAny(new ExtensionClass + { + Key = anyStringValue, + OtherKey = anyLongValue, + }), + Extensions = new Dictionary + { + { extensionKey, new AsyncApiAny(extensionString) }, + }, + }, + }, + Description = traitDescription, + Summary = traitSummary, + Tags = new List + { + new AsyncApiTag + { + Name = tagName, + Description = tagDescription, + }, + }, + ExternalDocs = new AsyncApiExternalDocumentation + { + Url = new Uri(externalDocsUri), + Description = externalDocsDescription, + }, + Extensions = new Dictionary + { + { extensionKey, new AsyncApiAny(extensionString) }, + }, + }, + }, + Extensions = new Dictionary + { + { extensionKey, new AsyncApiAny(extensionString) }, + }, + } + }, + }, }, Servers = new Dictionary { @@ -753,20 +831,11 @@ public void V2_SerializeV2_WithFullSpec_Serializes() { Description = serverDescription, ProtocolVersion = protocolVersion, - Url = serverUrl, + Host = serverUrl, Protocol = protocol, - Security = new List + Security = new List { - new AsyncApiSecurityRequirement - { - { - new AsyncApiSecuritySchemeReference(securitySchemeName), - new List - { - requirementString, - } - }, - }, + new AsyncApiSecuritySchemeReference(securitySchemeName), }, } }, @@ -803,148 +872,66 @@ public void V2_SerializeV2_WithFullSpec_Serializes() channelKey, new AsyncApiChannel { Description = channelDescription, - Subscribe = new AsyncApiOperation + } + }, + }, + Operations = new Dictionary() + { + { + operationId, new AsyncApiOperation() + { + Description = operationDescription, + Summary = operationSummary, + Channel = new AsyncApiChannelReference($"#/channels/{channelKey}"), + ExternalDocs = new AsyncApiExternalDocumentation + { + Url = new Uri(externalDocsUri), + Description = externalDocsDescription, + }, + Messages = new List { - Description = operationDescription, - OperationId = operationId, - Summary = operationSummary, - ExternalDocs = new AsyncApiExternalDocumentation { - Url = new Uri(externalDocsUri), - Description = externalDocsDescription, + new($"#components/messages/{messageKeyOne}") }, - Message = new List { - { - new AsyncApiMessage - { - Description = messageDescription, - Title = messageTitle, - Summary = messageSummary, - Name = messageName, - ContentType = contentType, - } - }, - { - new AsyncApiMessage - { - Description = messageDescription, - Title = messageTitle, - Summary = messageSummary, - Name = messageName, - ContentType = contentType, - SchemaFormat = schemaFormat, - CorrelationId = new AsyncApiCorrelationId - { - Location = correlationLocation, - Description = correlationDescription, - Extensions = new Dictionary - { - { extensionKey, new AsyncApiAny(extensionString) }, - }, - }, - Traits = new List - { - new AsyncApiMessageTrait - { - Name = traitName, - Title = traitTitle, - Headers = new AsyncApiJsonSchema - { - Title = schemaTitle, - WriteOnly = true, - Description = schemaDescription, - Examples = new List - { - new AsyncApiAny(new ExtensionClass - { - Key = anyStringValue, - OtherKey = anyLongValue, - }), - }, - }, - Examples = new List - { - new AsyncApiMessageExample - { - Summary = exampleSummary, - Name = exampleName, - Payload = new AsyncApiAny(new ExtensionClass - { - Key = anyStringValue, - OtherKey = anyLongValue, - }), - Extensions = new Dictionary - { - { extensionKey, new AsyncApiAny(extensionString) }, - }, - }, - }, - Description = traitDescription, - Summary = traitSummary, - Tags = new List - { - new AsyncApiTag - { - Name = tagName, - Description = tagDescription, - }, - }, - ExternalDocs = new AsyncApiExternalDocumentation - { - Url = new Uri(externalDocsUri), - Description = externalDocsDescription, - }, - Extensions = new Dictionary - { - { extensionKey, new AsyncApiAny(extensionString) }, - }, - }, - }, - Extensions = new Dictionary - { - { extensionKey, new AsyncApiAny(extensionString) }, - }, - } - }, - }, - Extensions = new Dictionary - { - { extensionKey, new AsyncApiAny(extensionString) }, + new($"#components/messages/{messageKeyTwo}") }, - Tags = new List + }, + Extensions = new Dictionary + { + { extensionKey, new AsyncApiAny(extensionString) }, + }, + Tags = new List + { + new AsyncApiTag { - new AsyncApiTag - { - Name = tagName, - Description = tagDescription, - }, + Name = tagName, + Description = tagDescription, }, - Traits = new List + }, + Traits = new List + { + new AsyncApiOperationTrait { - new AsyncApiOperationTrait + Description = traitDescription, + Summary = traitSummary, + Tags = new List { - Description = traitDescription, - Summary = traitSummary, - Tags = new List - { - new AsyncApiTag - { - Name = tagName, - Description = tagDescription, - }, - }, - ExternalDocs = new AsyncApiExternalDocumentation - { - Url = new Uri(externalDocsUri), - Description = externalDocsDescription, - }, - OperationId = operationId, - Extensions = new Dictionary + new AsyncApiTag { - { extensionKey, new AsyncApiAny(extensionString) }, + Name = tagName, + Description = tagDescription, }, }, + ExternalDocs = new AsyncApiExternalDocumentation + { + Url = new Uri(externalDocsUri), + Description = externalDocsDescription, + }, + Extensions = new Dictionary + { + { extensionKey, new AsyncApiAny(extensionString) }, + }, }, }, } @@ -1010,7 +997,7 @@ public void V2_Read_WithAvroSchemaPayload_NoErrors() // Assert diagnostics.Errors.Should().HaveCount(0); - result.Channels.First().Value.Publish.Message.First().Payload.As().TryGetAs(out var record).Should().BeTrue(); + result.Operations.Values.FirstOrDefault(op => op.Action == AsyncApiAction.Send)!.Messages.First().Payload.As().TryGetAs(out var record).Should().BeTrue(); record.Name.Should().Be("UserSignedUp"); } @@ -1062,8 +1049,10 @@ public void V2_Read_WithJsonSchemaReference_NoErrors() // Assert diagnostics.Errors.Should().HaveCount(0); - result.Channels.First().Value.Publish.Message.First().Title.Should().Be("Message for schema validation testing that is a json object"); - result.Channels.First().Value.Publish.Message.First().Payload.As().Properties.Should().HaveCount(1); + + var message = result.Operations.Values.FirstOrDefault(op => op.Action == AsyncApiAction.Send)!.Messages.First(); + message.Title.Should().Be("Message for schema validation testing that is a json object"); + message.Payload.As().Properties.Should().HaveCount(1); } [Test] @@ -1110,8 +1099,8 @@ public void V2_Serialize_WithBindingReferences_SerializesDeserializes() { Description = "test description", Protocol = "pulsar+ssl", - Url = "example.com", - Bindings = new AsyncApiBindingsReference("#/components/serverBindings/bindings") + Host = "example.com", + Bindings = new AsyncApiBindingsReference("#/components/serverBindings/bindings"), }); doc.Components = new AsyncApiComponents() { @@ -1120,11 +1109,7 @@ public void V2_Serialize_WithBindingReferences_SerializesDeserializes() { "otherchannel", new AsyncApiChannel() { - Publish = new AsyncApiOperation() - { - Description = "test", - }, - Bindings = new AsyncApiBindingsReference("#/components/channelBindings/bindings") + Bindings = new AsyncApiBindingsReference("#/components/channelBindings/bindings"), } }, }, @@ -1153,6 +1138,16 @@ public void V2_Serialize_WithBindingReferences_SerializesDeserializes() } }, }, + Operations = new Dictionary() + { + { + "operation", new AsyncApiOperation() + { + Description = "test", + Channel = new AsyncApiChannelReference("#/components/channels/otherchannel"), + } + }, + }, }; doc.Channels.Add( "testChannel", @@ -1160,8 +1155,10 @@ public void V2_Serialize_WithBindingReferences_SerializesDeserializes() var actual = doc.Serialize(AsyncApiVersion.AsyncApi2_0, AsyncApiFormat.Yaml); actual.Should().BePlatformAgnosticEquivalentTo(expected); - var settings = new AsyncApiReaderSettings(); - settings.Bindings = BindingsCollection.Pulsar; + var settings = new AsyncApiReaderSettings + { + Bindings = BindingsCollection.Pulsar, + }; var reader = new AsyncApiStringReader(settings); var deserialized = reader.Read(actual, out var diagnostic); var serverBindings = deserialized.Servers.First().Value.Bindings; @@ -1173,7 +1170,7 @@ public void V2_Serialize_WithBindingReferences_SerializesDeserializes() } [Test] - public void V2_Serializev2_WithBindings_Serializes() + public void V2_SerializeV2_WithBindings_Serializes() { var expected = """ asyncapi: 2.6.0 @@ -1210,7 +1207,7 @@ public void V2_Serializev2_WithBindings_Serializes() { Description = "test description", Protocol = "pulsar+ssl", - Url = "example.com", + Host = "example.com", }); doc.Channels.Add( "testChannel", @@ -1226,52 +1223,55 @@ public void V2_Serializev2_WithBindings_Serializes() } }, }, - Publish = new AsyncApiOperation + }); + doc.Operations.Add("firstOperation", new AsyncApiOperation() + { + Messages = new List + { + new("#/components/messages/firstMessage"), + }, + }); + + doc.Components.Messages.Add("firstMessage", new AsyncApiMessage + { + Bindings = new AsyncApiBindings + { { - Message = new List + new HttpMessageBinding { + Headers = new AsyncApiJsonSchema { - new AsyncApiMessage - { - Bindings = new AsyncApiBindings - { - { - new HttpMessageBinding - { - Headers = new AsyncApiJsonSchema - { - Description = "this mah binding", - }, - } - }, - { - new KafkaMessageBinding - { - Key = new AsyncApiJsonSchema - { - Description = "this mah other binding", - }, - } - }, - }, - } + Description = "this mah binding", }, - }, + } }, - }); + { + new KafkaMessageBinding + { + Key = new AsyncApiJsonSchema + { + Description = "this mah other binding", + }, + } + }, + }, + }); + var actual = doc.Serialize(AsyncApiVersion.AsyncApi2_0, AsyncApiFormat.Yaml); - var settings = new AsyncApiReaderSettings(); - settings.Bindings = BindingsCollection.All; + var settings = new AsyncApiReaderSettings + { + Bindings = BindingsCollection.All, + }; var reader = new AsyncApiStringReader(settings); var deserialized = reader.Read(actual, out var diagnostic); // Assert actual.Should() .BePlatformAgnosticEquivalentTo(expected); - Assert.AreEqual(2, deserialized.Channels.First().Value.Publish.Message.First().Bindings.Count); + Assert.AreEqual(2, deserialized.Operations.First().Value.Messages.First().Bindings.Count); - var binding = deserialized.Channels.First().Value.Publish.Message.First().Bindings.First(); + var binding = deserialized.Operations.First().Value.Messages.First().Bindings.First(); Assert.AreEqual("http", binding.Key); var httpBinding = binding.Value as HttpMessageBinding; From c086aa8d37ff541b157f8786b15064f1d71874c4 Mon Sep 17 00:00:00 2001 From: Yohan Fraga Date: Tue, 18 Feb 2025 21:46:07 -0300 Subject: [PATCH 2/7] YFS - continue fixing tests --- src/LEGO.AsyncAPI/Models/AsyncApiChannel.cs | 10 +++++++- .../AsyncApiSecuritySchemeReference.cs | 10 ++++---- .../Writers/AsyncApiWriterExtensions.cs | 9 ++++++- .../AsyncApiDocumentV2Tests.cs | 24 +++++++++++-------- 4 files changed, 37 insertions(+), 16 deletions(-) diff --git a/src/LEGO.AsyncAPI/Models/AsyncApiChannel.cs b/src/LEGO.AsyncAPI/Models/AsyncApiChannel.cs index 905062a..eb54792 100644 --- a/src/LEGO.AsyncAPI/Models/AsyncApiChannel.cs +++ b/src/LEGO.AsyncAPI/Models/AsyncApiChannel.cs @@ -85,7 +85,7 @@ public virtual void SerializeV2(IAsyncApiWriter writer) // servers writer.WriteOptionalCollection(AsyncApiConstants.Servers, this.Servers.Select(s => s.Reference.FragmentId).ToList(), (w, s) => w.WriteValue(s)); - var operations = writer.Workspace.RootDocument?.Operations.Values.Where(operation => operation.Channel.Equals(this)); + var operations = writer.Workspace.RootDocument?.Operations.Values.Where(operation => this.CheckOperationChannel(operation, writer)); // subscribe (Now Send) writer.WriteOptionalObject(AsyncApiConstants.Subscribe, operations?.FirstOrDefault(o => o.Action == AsyncApiAction.Send), (w, s) => s?.SerializeV2(w)); @@ -141,5 +141,13 @@ public virtual void SerializeV3(IAsyncApiWriter writer) writer.WriteEndObject(); } + + // TODO: Validate with Alexander + private bool CheckOperationChannel(AsyncApiOperation operation, IAsyncApiWriter writer) + { + operation.Channel.Reference.Workspace = writer.Workspace; + + return operation.Channel.Equals(this); + } } } \ No newline at end of file diff --git a/src/LEGO.AsyncAPI/Models/References/AsyncApiSecuritySchemeReference.cs b/src/LEGO.AsyncAPI/Models/References/AsyncApiSecuritySchemeReference.cs index b09937e..12549be 100644 --- a/src/LEGO.AsyncAPI/Models/References/AsyncApiSecuritySchemeReference.cs +++ b/src/LEGO.AsyncAPI/Models/References/AsyncApiSecuritySchemeReference.cs @@ -94,17 +94,19 @@ public void SerializeAsSecurityRequirement(IAsyncApiWriter writer) writer.WritePropertyName(this.Reference.FragmentId.Split("/")[^1]); + + writer.WriteStartArray(); + if (this.Scopes.Any()) { - writer.WriteStartArray(); - foreach (var scope in this.Scopes) { writer.WriteValue(scope); } - - writer.WriteEndArray(); } + + writer.WriteEndArray(); + writer.WriteEndObject(); } } diff --git a/src/LEGO.AsyncAPI/Writers/AsyncApiWriterExtensions.cs b/src/LEGO.AsyncAPI/Writers/AsyncApiWriterExtensions.cs index c909e16..0e15178 100644 --- a/src/LEGO.AsyncAPI/Writers/AsyncApiWriterExtensions.cs +++ b/src/LEGO.AsyncAPI/Writers/AsyncApiWriterExtensions.cs @@ -1,5 +1,7 @@ // Copyright (c) The LEGO Group. All rights reserved. +using LEGO.AsyncAPI.Models; + namespace LEGO.AsyncAPI.Writers { using System; @@ -419,7 +421,12 @@ private static void WriteMapInternal( { foreach (var item in elements) { - writer.WritePropertyName(item.Key); + // TODO: Validate with Alexander if this is correct and how to make it work only on V2 + var key = item.Value is AsyncApiChannel channel + ? channel.Address + "." + item.Key + : item.Key; + + writer.WritePropertyName(key); if (item.Value != null) { action(writer, item.Key, item.Value); diff --git a/test/LEGO.AsyncAPI.Tests/AsyncApiDocumentV2Tests.cs b/test/LEGO.AsyncAPI.Tests/AsyncApiDocumentV2Tests.cs index 636b8db..66f97df 100644 --- a/test/LEGO.AsyncAPI.Tests/AsyncApiDocumentV2Tests.cs +++ b/test/LEGO.AsyncAPI.Tests/AsyncApiDocumentV2Tests.cs @@ -42,7 +42,7 @@ public void V2_AsyncApiDocument_WithStreetLightsExample_SerializesAndDeserialize url: https://www.apache.org/licenses/LICENSE-2.0 servers: scram-connections: - url: test.mykafkacluster.org:18092 + url: kafka-secure://test.mykafkacluster.org:18092 protocol: kafka-secure description: Test broker secured with scramSha256 security: @@ -55,7 +55,7 @@ public void V2_AsyncApiDocument_WithStreetLightsExample_SerializesAndDeserialize - name: visibility:private description: This resource is private and only available to certain users mtls-connections: - url: test.mykafkacluster.org:28092 + url: kafka-secure://test.mykafkacluster.org:28092 protocol: kafka-secure description: Test broker secured with X509 security: @@ -274,9 +274,10 @@ public void V2_AsyncApiDocument_WithStreetLightsExample_SerializesAndDeserialize }) .WithDefaultContentType() .WithChannel( - "smartylighting.streetlights.1.0.event.{streetlightId}.lighting.measured", + "lighting.measured", new AsyncApiChannel() { + Address = "smartylighting.streetlights.1.0.event.{streetlightId}", Description = "The topic on which measured values may be produced and consumed.", Parameters = new Dictionary { @@ -286,9 +287,10 @@ public void V2_AsyncApiDocument_WithStreetLightsExample_SerializesAndDeserialize }, }) .WithChannel( - "smartylighting.streetlights.1.0.action.{streetlightId}.turn.on", + "turn.on", new AsyncApiChannel() { + Address = "smartylighting.streetlights.1.0.action.{streetlightId}", Parameters = new Dictionary { { @@ -297,9 +299,10 @@ public void V2_AsyncApiDocument_WithStreetLightsExample_SerializesAndDeserialize }, }) .WithChannel( - "smartylighting.streetlights.1.0.action.{streetlightId}.turn.off", + "turn.off", new AsyncApiChannel() { + Address = "smartylighting.streetlights.1.0.action.{streetlightId}", Parameters = new Dictionary { { @@ -308,9 +311,10 @@ public void V2_AsyncApiDocument_WithStreetLightsExample_SerializesAndDeserialize }, }) .WithChannel( - "smartylighting.streetlights.1.0.action.{streetlightId}.dim", + "dim", new AsyncApiChannel() { + Address = "smartylighting.streetlights.1.0.action.{streetlightId}", Parameters = new Dictionary { { @@ -322,7 +326,7 @@ public void V2_AsyncApiDocument_WithStreetLightsExample_SerializesAndDeserialize { Action = AsyncApiAction.Send, Summary = "Inform about environmental lighting conditions of a particular streetlight.", - Channel = new AsyncApiChannelReference("#/channels/smartylighting.streetlights.1.0.event.{streetlightId}.lighting.measured"), + Channel = new AsyncApiChannelReference("#/channels/lighting.measured"), Traits = new List { new AsyncApiOperationTraitReference("#/components/operationTraits/kafka"), @@ -335,7 +339,7 @@ public void V2_AsyncApiDocument_WithStreetLightsExample_SerializesAndDeserialize .WithOperation("turnOn", new AsyncApiOperation() { Action = AsyncApiAction.Receive, - Channel = new AsyncApiChannelReference("#/channels/smartylighting.streetlights.1.0.action.{streetlightId}.turn.on"), + Channel = new AsyncApiChannelReference("#/channels/turn.on"), Traits = new List { new AsyncApiOperationTraitReference("#/components/operationTraits/kafka"), @@ -348,7 +352,7 @@ public void V2_AsyncApiDocument_WithStreetLightsExample_SerializesAndDeserialize .WithOperation("turnOff", new AsyncApiOperation() { Action = AsyncApiAction.Receive, - Channel = new AsyncApiChannelReference("#/channels/smartylighting.streetlights.1.0.action.{streetlightId}.turn.off"), + Channel = new AsyncApiChannelReference("#/channels/turn.off"), Traits = new List { new AsyncApiOperationTraitReference("#/components/operationTraits/kafka"), @@ -361,7 +365,7 @@ public void V2_AsyncApiDocument_WithStreetLightsExample_SerializesAndDeserialize .WithOperation("dimLight", new AsyncApiOperation() { Action = AsyncApiAction.Receive, - Channel = new AsyncApiChannelReference("#/channels/smartylighting.streetlights.1.0.action.{streetlightId}.dim"), + Channel = new AsyncApiChannelReference("#/channels/dim"), Traits = new List { new AsyncApiOperationTraitReference("#/components/operationTraits/kafka"), From 11d99df68d5c9490ad0c6acd0da6942f65d0c9b7 Mon Sep 17 00:00:00 2001 From: Yohan Fraga Date: Wed, 19 Feb 2025 18:34:21 -0300 Subject: [PATCH 3/7] YFS - Fix V2_AsyncApiDocument_WithStreetLightsExample_SerializesAndDeserializes --- src/LEGO.AsyncAPI/Models/AsyncApiChannel.cs | 3 +- src/LEGO.AsyncAPI/Models/AsyncApiDocument.cs | 33 +++++++++++++++++++ src/LEGO.AsyncAPI/Models/AsyncApiOperation.cs | 10 ++++-- .../AsyncApiDocumentV2Tests.cs | 19 ++++++----- 4 files changed, 52 insertions(+), 13 deletions(-) diff --git a/src/LEGO.AsyncAPI/Models/AsyncApiChannel.cs b/src/LEGO.AsyncAPI/Models/AsyncApiChannel.cs index eb54792..1ac5a95 100644 --- a/src/LEGO.AsyncAPI/Models/AsyncApiChannel.cs +++ b/src/LEGO.AsyncAPI/Models/AsyncApiChannel.cs @@ -85,7 +85,7 @@ public virtual void SerializeV2(IAsyncApiWriter writer) // servers writer.WriteOptionalCollection(AsyncApiConstants.Servers, this.Servers.Select(s => s.Reference.FragmentId).ToList(), (w, s) => w.WriteValue(s)); - var operations = writer.Workspace.RootDocument?.Operations.Values.Where(operation => this.CheckOperationChannel(operation, writer)); + var operations = writer.Workspace.RootDocument?.Operations.Values!.Where(operation => this.CheckOperationChannel(operation, writer)).ToList(); // subscribe (Now Send) writer.WriteOptionalObject(AsyncApiConstants.Subscribe, operations?.FirstOrDefault(o => o.Action == AsyncApiAction.Send), (w, s) => s?.SerializeV2(w)); @@ -142,7 +142,6 @@ public virtual void SerializeV3(IAsyncApiWriter writer) writer.WriteEndObject(); } - // TODO: Validate with Alexander private bool CheckOperationChannel(AsyncApiOperation operation, IAsyncApiWriter writer) { operation.Channel.Reference.Workspace = writer.Workspace; diff --git a/src/LEGO.AsyncAPI/Models/AsyncApiDocument.cs b/src/LEGO.AsyncAPI/Models/AsyncApiDocument.cs index 3b926d8..602ae2a 100644 --- a/src/LEGO.AsyncAPI/Models/AsyncApiDocument.cs +++ b/src/LEGO.AsyncAPI/Models/AsyncApiDocument.cs @@ -69,6 +69,7 @@ public void SerializeV2(IAsyncApiWriter writer) writer.Workspace.SetRootDocument(this); writer.Workspace.RegisterComponents(this); + this.RegisterChannels(writer); writer.WriteStartObject(); @@ -146,5 +147,37 @@ public void SerializeV3(IAsyncApiWriter writer) writer.WriteEndObject(); } + + private void RegisterChannels(IAsyncApiWriter writer) + { + const string baseUri = "#/"; + + if (this.Channels is null) + { + return; + } + + foreach (var item in this.Channels) + { + var location = baseUri + ReferenceType.Channel.GetDisplayName() + "/" + item.Key; + writer.Workspace.RegisterComponent(location, item.Value); + + if (item.Value.Messages is not null) + { + this.RegisterMessages(writer, item.Value, item.Key); + } + } + } + + private void RegisterMessages(IAsyncApiWriter writer, AsyncApiChannel channel, string channelKey) + { + var baseUri = $"#/channels/{channelKey}/"; + + foreach (var item in channel.Messages) + { + var location = baseUri + ReferenceType.Message.GetDisplayName() + "/" + item.Key; + writer.Workspace.RegisterComponent(location, item.Value); + } + } } } diff --git a/src/LEGO.AsyncAPI/Models/AsyncApiOperation.cs b/src/LEGO.AsyncAPI/Models/AsyncApiOperation.cs index 077a181..dc32ce6 100644 --- a/src/LEGO.AsyncAPI/Models/AsyncApiOperation.cs +++ b/src/LEGO.AsyncAPI/Models/AsyncApiOperation.cs @@ -23,7 +23,6 @@ public class AsyncApiOperation : IAsyncApiSerializable, IAsyncApiExtensible /// public virtual AsyncApiChannelReference Channel { get; set; } - /// /// unique string used to identify the operation. /// @@ -69,7 +68,11 @@ public class AsyncApiOperation : IAsyncApiSerializable, IAsyncApiExtensible /// public virtual IList Messages { get; set; } = new List(); + /// + /// The definition of the reply in a request-reply operation. + /// public virtual AsyncApiOperationReply Reply { get; set; } + /// public virtual IDictionary Extensions { get; set; } = new Dictionary(); @@ -81,7 +84,10 @@ public virtual void SerializeV2(IAsyncApiWriter writer) } writer.WriteStartObject(); - // writer.WriteOptionalProperty(AsyncApiConstants.OperationId, this.Title); + + var operationId = writer.Workspace.RootDocument.Operations.FirstOrDefault(pair => pair.Value == this).Key; + + writer.WriteOptionalProperty(AsyncApiConstants.OperationId, operationId); writer.WriteOptionalProperty(AsyncApiConstants.Summary, this.Summary); writer.WriteOptionalProperty(AsyncApiConstants.Description, this.Description); writer.WriteOptionalCollection(AsyncApiConstants.Security, this.Security, (w, t) => this.SerializeAsSecurityRequirement(t, w)); diff --git a/test/LEGO.AsyncAPI.Tests/AsyncApiDocumentV2Tests.cs b/test/LEGO.AsyncAPI.Tests/AsyncApiDocumentV2Tests.cs index 66f97df..822ca27 100644 --- a/test/LEGO.AsyncAPI.Tests/AsyncApiDocumentV2Tests.cs +++ b/test/LEGO.AsyncAPI.Tests/AsyncApiDocumentV2Tests.cs @@ -184,7 +184,7 @@ public void V2_AsyncApiDocument_WithStreetLightsExample_SerializesAndDeserialize streetlightId: description: The ID of the streetlight. schema: - type: string + default: '1' operationTraits: kafka: bindings: @@ -277,7 +277,7 @@ public void V2_AsyncApiDocument_WithStreetLightsExample_SerializesAndDeserialize "lighting.measured", new AsyncApiChannel() { - Address = "smartylighting.streetlights.1.0.event.{streetlightId}", + Address = "smartylighting.streetlights.1.0.event.{streetlightId}.lighting.measured", Description = "The topic on which measured values may be produced and consumed.", Parameters = new Dictionary { @@ -290,7 +290,7 @@ public void V2_AsyncApiDocument_WithStreetLightsExample_SerializesAndDeserialize "turn.on", new AsyncApiChannel() { - Address = "smartylighting.streetlights.1.0.action.{streetlightId}", + Address = "smartylighting.streetlights.1.0.action.{streetlightId}.turn.on", Parameters = new Dictionary { { @@ -302,7 +302,7 @@ public void V2_AsyncApiDocument_WithStreetLightsExample_SerializesAndDeserialize "turn.off", new AsyncApiChannel() { - Address = "smartylighting.streetlights.1.0.action.{streetlightId}", + Address = "smartylighting.streetlights.1.0.action.{streetlightId}.turn.off", Parameters = new Dictionary { { @@ -314,7 +314,7 @@ public void V2_AsyncApiDocument_WithStreetLightsExample_SerializesAndDeserialize "dim", new AsyncApiChannel() { - Address = "smartylighting.streetlights.1.0.action.{streetlightId}", + Address = "smartylighting.streetlights.1.0.action.{streetlightId}.dim", Parameters = new Dictionary { { @@ -324,7 +324,7 @@ public void V2_AsyncApiDocument_WithStreetLightsExample_SerializesAndDeserialize }) .WithOperation("receiveLightMeasurement", new AsyncApiOperation() { - Action = AsyncApiAction.Send, + Action = AsyncApiAction.Receive, Summary = "Inform about environmental lighting conditions of a particular streetlight.", Channel = new AsyncApiChannelReference("#/channels/lighting.measured"), Traits = new List @@ -338,7 +338,7 @@ public void V2_AsyncApiDocument_WithStreetLightsExample_SerializesAndDeserialize }) .WithOperation("turnOn", new AsyncApiOperation() { - Action = AsyncApiAction.Receive, + Action = AsyncApiAction.Send, Channel = new AsyncApiChannelReference("#/channels/turn.on"), Traits = new List { @@ -351,7 +351,7 @@ public void V2_AsyncApiDocument_WithStreetLightsExample_SerializesAndDeserialize }) .WithOperation("turnOff", new AsyncApiOperation() { - Action = AsyncApiAction.Receive, + Action = AsyncApiAction.Send, Channel = new AsyncApiChannelReference("#/channels/turn.off"), Traits = new List { @@ -364,7 +364,7 @@ public void V2_AsyncApiDocument_WithStreetLightsExample_SerializesAndDeserialize }) .WithOperation("dimLight", new AsyncApiOperation() { - Action = AsyncApiAction.Receive, + Action = AsyncApiAction.Send, Channel = new AsyncApiChannelReference("#/channels/dim"), Traits = new List { @@ -479,6 +479,7 @@ public void V2_AsyncApiDocument_WithStreetLightsExample_SerializesAndDeserialize .WithComponent("streetlightId", new AsyncApiParameter() { Description = "The ID of the streetlight.", + Default = "1", }) .WithComponent("commonHeaders", new AsyncApiMessageTrait() { From 0d53dc2db4a8e38596fd0ecc2006d77f2107bf0d Mon Sep 17 00:00:00 2001 From: Yohan Fraga Date: Wed, 19 Feb 2025 18:45:08 -0300 Subject: [PATCH 4/7] YFS - Remove unneeded changes --- src/LEGO.AsyncAPI/Models/AsyncApiChannel.cs | 2 +- src/LEGO.AsyncAPI/Writers/AsyncApiWriterExtensions.cs | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/LEGO.AsyncAPI/Models/AsyncApiChannel.cs b/src/LEGO.AsyncAPI/Models/AsyncApiChannel.cs index 1ac5a95..169a5c5 100644 --- a/src/LEGO.AsyncAPI/Models/AsyncApiChannel.cs +++ b/src/LEGO.AsyncAPI/Models/AsyncApiChannel.cs @@ -85,7 +85,7 @@ public virtual void SerializeV2(IAsyncApiWriter writer) // servers writer.WriteOptionalCollection(AsyncApiConstants.Servers, this.Servers.Select(s => s.Reference.FragmentId).ToList(), (w, s) => w.WriteValue(s)); - var operations = writer.Workspace.RootDocument?.Operations.Values!.Where(operation => this.CheckOperationChannel(operation, writer)).ToList(); + var operations = writer.Workspace.RootDocument?.Operations.Values.Where(operation => this.CheckOperationChannel(operation, writer)).ToList(); // subscribe (Now Send) writer.WriteOptionalObject(AsyncApiConstants.Subscribe, operations?.FirstOrDefault(o => o.Action == AsyncApiAction.Send), (w, s) => s?.SerializeV2(w)); diff --git a/src/LEGO.AsyncAPI/Writers/AsyncApiWriterExtensions.cs b/src/LEGO.AsyncAPI/Writers/AsyncApiWriterExtensions.cs index 7da3dbf..266d5ec 100644 --- a/src/LEGO.AsyncAPI/Writers/AsyncApiWriterExtensions.cs +++ b/src/LEGO.AsyncAPI/Writers/AsyncApiWriterExtensions.cs @@ -1,7 +1,5 @@ // Copyright (c) The LEGO Group. All rights reserved. -using LEGO.AsyncAPI.Models; - namespace LEGO.AsyncAPI.Writers { using System; From 26e67ff7aabbb19c64008053740d64ff5175d792 Mon Sep 17 00:00:00 2001 From: Yohan Fraga Date: Thu, 20 Feb 2025 12:09:59 -0300 Subject: [PATCH 5/7] YFS - Start fixing Tests --- .../Models/AsyncApiOperationTrait.cs | 6 +- .../AsyncApiDocumentV2Tests.cs | 204 +++++++++--------- 2 files changed, 106 insertions(+), 104 deletions(-) diff --git a/src/LEGO.AsyncAPI/Models/AsyncApiOperationTrait.cs b/src/LEGO.AsyncAPI/Models/AsyncApiOperationTrait.cs index 20ddcb7..dfc7522 100644 --- a/src/LEGO.AsyncAPI/Models/AsyncApiOperationTrait.cs +++ b/src/LEGO.AsyncAPI/Models/AsyncApiOperationTrait.cs @@ -1,5 +1,7 @@ // Copyright (c) The LEGO Group. All rights reserved. +using System.Linq; + namespace LEGO.AsyncAPI.Models { using System; @@ -59,7 +61,9 @@ public virtual void SerializeV2(IAsyncApiWriter writer) writer.WriteStartObject(); - //writer.WriteOptionalProperty(AsyncApiConstants.OperationId, this.OperationId); + var operation = writer.Workspace.RootDocument.Operations.FirstOrDefault(op => op.Value.Traits.Any(tr => tr == this)); + + writer.WriteOptionalProperty(AsyncApiConstants.OperationId, operation.Key); writer.WriteOptionalProperty(AsyncApiConstants.Summary, this.Summary); writer.WriteOptionalProperty(AsyncApiConstants.Description, this.Description); writer.WriteOptionalCollection(AsyncApiConstants.Security, this.Security, (w, t) => t.SerializeV2(w)); diff --git a/test/LEGO.AsyncAPI.Tests/AsyncApiDocumentV2Tests.cs b/test/LEGO.AsyncAPI.Tests/AsyncApiDocumentV2Tests.cs index 822ca27..41e5679 100644 --- a/test/LEGO.AsyncAPI.Tests/AsyncApiDocumentV2Tests.cs +++ b/test/LEGO.AsyncAPI.Tests/AsyncApiDocumentV2Tests.cs @@ -550,13 +550,12 @@ public void V2_SerializeV2_WithFullSpec_Serializes() id: documentId servers: myServer: - url: https://example.com/server + url: kafkaprotocol://example.com/server protocol: KafkaProtocol protocolVersion: protocolVersion description: serverDescription security: - - securitySchemeName: - - requirementItem + - securitySchemeName: [] channels: channel1: description: channelDescription @@ -592,7 +591,6 @@ public void V2_SerializeV2_WithFullSpec_Serializes() description: correlationDescription location: correlationLocation x-extension: value - schemaFormat: schemaFormat contentType: contentType name: messageName title: messageTitle @@ -686,7 +684,7 @@ public void V2_SerializeV2_WithFullSpec_Serializes() string serverKey = "myServer"; string serverDescription = "serverDescription"; string protocolVersion = "protocolVersion"; - string serverUrl = "https://example.com/server"; + string serverHost = "example.com/server"; string protocol = "KafkaProtocol"; string securirySchemeDescription = "securitySchemeDescription"; string securitySchemeName = "securitySchemeName"; @@ -734,100 +732,6 @@ public void V2_SerializeV2_WithFullSpec_Serializes() } }, }, - Messages = new Dictionary() - { - { - messageKeyOne, new AsyncApiMessage - { - Description = messageDescription, - Title = messageTitle, - Summary = messageSummary, - Name = messageName, - ContentType = contentType, - } - }, - { - messageKeyTwo, new AsyncApiMessage - { - Description = messageDescription, - Title = messageTitle, - Summary = messageSummary, - Name = messageName, - ContentType = contentType, - CorrelationId = new AsyncApiCorrelationId - { - Location = correlationLocation, - Description = correlationDescription, - Extensions = new Dictionary - { - { extensionKey, new AsyncApiAny(extensionString) }, - }, - }, - Traits = new List - { - new AsyncApiMessageTrait - { - Name = traitName, - Title = traitTitle, - Headers = new AsyncApiJsonSchema - { - Title = schemaTitle, - WriteOnly = true, - Description = schemaDescription, - Examples = new List - { - new AsyncApiAny(new ExtensionClass - { - Key = anyStringValue, - OtherKey = anyLongValue, - }), - }, - }, - Examples = new List - { - new AsyncApiMessageExample - { - Summary = exampleSummary, - Name = exampleName, - Payload = new AsyncApiAny(new ExtensionClass - { - Key = anyStringValue, - OtherKey = anyLongValue, - }), - Extensions = new Dictionary - { - { extensionKey, new AsyncApiAny(extensionString) }, - }, - }, - }, - Description = traitDescription, - Summary = traitSummary, - Tags = new List - { - new AsyncApiTag - { - Name = tagName, - Description = tagDescription, - }, - }, - ExternalDocs = new AsyncApiExternalDocumentation - { - Url = new Uri(externalDocsUri), - Description = externalDocsDescription, - }, - Extensions = new Dictionary - { - { extensionKey, new AsyncApiAny(extensionString) }, - }, - }, - }, - Extensions = new Dictionary - { - { extensionKey, new AsyncApiAny(extensionString) }, - }, - } - }, - }, }, Servers = new Dictionary { @@ -836,11 +740,11 @@ public void V2_SerializeV2_WithFullSpec_Serializes() { Description = serverDescription, ProtocolVersion = protocolVersion, - Host = serverUrl, + Host = serverHost, Protocol = protocol, Security = new List { - new AsyncApiSecuritySchemeReference(securitySchemeName), + new AsyncApiSecuritySchemeReference($"#/components/securitySchemes/{securitySchemeName}"), }, } }, @@ -877,6 +781,100 @@ public void V2_SerializeV2_WithFullSpec_Serializes() channelKey, new AsyncApiChannel { Description = channelDescription, + Messages = new Dictionary() + { + { + messageKeyOne, new AsyncApiMessage + { + Description = messageDescription, + Title = messageTitle, + Summary = messageSummary, + Name = messageName, + ContentType = contentType, + } + }, + { + messageKeyTwo, new AsyncApiMessage + { + Description = messageDescription, + Title = messageTitle, + Summary = messageSummary, + Name = messageName, + ContentType = contentType, + CorrelationId = new AsyncApiCorrelationId + { + Location = correlationLocation, + Description = correlationDescription, + Extensions = new Dictionary + { + { extensionKey, new AsyncApiAny(extensionString) }, + }, + }, + Traits = new List + { + new AsyncApiMessageTrait + { + Name = traitName, + Title = traitTitle, + Headers = new AsyncApiJsonSchema + { + Title = schemaTitle, + WriteOnly = true, + Description = schemaDescription, + Examples = new List + { + new AsyncApiAny(new ExtensionClass + { + Key = anyStringValue, + OtherKey = anyLongValue, + }), + }, + }, + Examples = new List + { + new AsyncApiMessageExample + { + Summary = exampleSummary, + Name = exampleName, + Payload = new AsyncApiAny(new ExtensionClass + { + Key = anyStringValue, + OtherKey = anyLongValue, + }), + Extensions = new Dictionary + { + { extensionKey, new AsyncApiAny(extensionString) }, + }, + }, + }, + Description = traitDescription, + Summary = traitSummary, + Tags = new List + { + new AsyncApiTag + { + Name = tagName, + Description = tagDescription, + }, + }, + ExternalDocs = new AsyncApiExternalDocumentation + { + Url = new Uri(externalDocsUri), + Description = externalDocsDescription, + }, + Extensions = new Dictionary + { + { extensionKey, new AsyncApiAny(extensionString) }, + }, + }, + }, + Extensions = new Dictionary + { + { extensionKey, new AsyncApiAny(extensionString) }, + }, + } + }, + }, } }, }, @@ -896,10 +894,10 @@ public void V2_SerializeV2_WithFullSpec_Serializes() Messages = new List { { - new($"#components/messages/{messageKeyOne}") + new($"#/channels/messages/{messageKeyOne}") }, { - new($"#components/messages/{messageKeyTwo}") + new($"#/channels/messages/{messageKeyTwo}") }, }, Extensions = new Dictionary From 5d81eaa5e6f16c1463ef66cf5479df87165beb14 Mon Sep 17 00:00:00 2001 From: Yohan Fraga Date: Thu, 20 Feb 2025 18:49:21 -0300 Subject: [PATCH 6/7] YFS - Remove operationId changes --- src/LEGO.AsyncAPI/AsyncApiWorkspace.cs | 5 +-- src/LEGO.AsyncAPI/Models/AsyncApiDocument.cs | 33 ------------------- src/LEGO.AsyncAPI/Models/AsyncApiOperation.cs | 4 +-- .../Models/AsyncApiOperationTrait.cs | 4 +-- 4 files changed, 5 insertions(+), 41 deletions(-) diff --git a/src/LEGO.AsyncAPI/AsyncApiWorkspace.cs b/src/LEGO.AsyncAPI/AsyncApiWorkspace.cs index ad0d867..3a366b8 100644 --- a/src/LEGO.AsyncAPI/AsyncApiWorkspace.cs +++ b/src/LEGO.AsyncAPI/AsyncApiWorkspace.cs @@ -29,14 +29,15 @@ public void RegisterComponents(AsyncApiDocument document) foreach (var channel in document.Channels) { location = channelBaseUri + channel.Key; - this.RegisterComponent(location, channel); + this.RegisterComponent(location, channel.Value); foreach (var message in channel.Value.Messages) { location = location + "/messages/" + message.Key; - this.RegisterComponent(location, message); + this.RegisterComponent(location, message.Value); } } + // Register Schema foreach (var item in document.Components.Schemas) { diff --git a/src/LEGO.AsyncAPI/Models/AsyncApiDocument.cs b/src/LEGO.AsyncAPI/Models/AsyncApiDocument.cs index ba99c2c..5808979 100644 --- a/src/LEGO.AsyncAPI/Models/AsyncApiDocument.cs +++ b/src/LEGO.AsyncAPI/Models/AsyncApiDocument.cs @@ -68,7 +68,6 @@ public void SerializeV2(IAsyncApiWriter writer) writer.Workspace.SetRootDocument(this); writer.Workspace.RegisterComponents(this); - this.RegisterChannels(writer); writer.WriteStartObject(); @@ -146,37 +145,5 @@ public void SerializeV3(IAsyncApiWriter writer) writer.WriteEndObject(); } - - private void RegisterChannels(IAsyncApiWriter writer) - { - const string baseUri = "#/"; - - if (this.Channels is null) - { - return; - } - - foreach (var item in this.Channels) - { - var location = baseUri + ReferenceType.Channel.GetDisplayName() + "/" + item.Key; - writer.Workspace.RegisterComponent(location, item.Value); - - if (item.Value.Messages is not null) - { - this.RegisterMessages(writer, item.Value, item.Key); - } - } - } - - private void RegisterMessages(IAsyncApiWriter writer, AsyncApiChannel channel, string channelKey) - { - var baseUri = $"#/channels/{channelKey}/"; - - foreach (var item in channel.Messages) - { - var location = baseUri + ReferenceType.Message.GetDisplayName() + "/" + item.Key; - writer.Workspace.RegisterComponent(location, item.Value); - } - } } } diff --git a/src/LEGO.AsyncAPI/Models/AsyncApiOperation.cs b/src/LEGO.AsyncAPI/Models/AsyncApiOperation.cs index 3799f83..a88f65f 100644 --- a/src/LEGO.AsyncAPI/Models/AsyncApiOperation.cs +++ b/src/LEGO.AsyncAPI/Models/AsyncApiOperation.cs @@ -84,9 +84,7 @@ public virtual void SerializeV2(IAsyncApiWriter writer) writer.WriteStartObject(); - var operationId = writer.Workspace.RootDocument.Operations.FirstOrDefault(pair => pair.Value == this).Key; - - writer.WriteOptionalProperty(AsyncApiConstants.OperationId, operationId); + // writer.WriteOptionalProperty(AsyncApiConstants.OperationId, this.OperationId); writer.WriteOptionalProperty(AsyncApiConstants.Summary, this.Summary); writer.WriteOptionalProperty(AsyncApiConstants.Description, this.Description); writer.WriteOptionalCollection(AsyncApiConstants.Security, this.Security, (w, t) => this.SerializeAsSecurityRequirement(t, w)); diff --git a/src/LEGO.AsyncAPI/Models/AsyncApiOperationTrait.cs b/src/LEGO.AsyncAPI/Models/AsyncApiOperationTrait.cs index dfc7522..a8d0575 100644 --- a/src/LEGO.AsyncAPI/Models/AsyncApiOperationTrait.cs +++ b/src/LEGO.AsyncAPI/Models/AsyncApiOperationTrait.cs @@ -61,9 +61,7 @@ public virtual void SerializeV2(IAsyncApiWriter writer) writer.WriteStartObject(); - var operation = writer.Workspace.RootDocument.Operations.FirstOrDefault(op => op.Value.Traits.Any(tr => tr == this)); - - writer.WriteOptionalProperty(AsyncApiConstants.OperationId, operation.Key); + // writer.WriteOptionalProperty(AsyncApiConstants.OperationId, this.OperationId); writer.WriteOptionalProperty(AsyncApiConstants.Summary, this.Summary); writer.WriteOptionalProperty(AsyncApiConstants.Description, this.Description); writer.WriteOptionalCollection(AsyncApiConstants.Security, this.Security, (w, t) => t.SerializeV2(w)); From 9212ba9f7c1080ad15fb91bf1e6ab1e5f150a0f0 Mon Sep 17 00:00:00 2001 From: Yohan Fraga Date: Thu, 20 Feb 2025 18:51:01 -0300 Subject: [PATCH 7/7] YFS - Fix operationId in v2 tests --- test/LEGO.AsyncAPI.Tests/AsyncApiDocumentV2Tests.cs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/test/LEGO.AsyncAPI.Tests/AsyncApiDocumentV2Tests.cs b/test/LEGO.AsyncAPI.Tests/AsyncApiDocumentV2Tests.cs index 9e0f5d8..bd7b46d 100644 --- a/test/LEGO.AsyncAPI.Tests/AsyncApiDocumentV2Tests.cs +++ b/test/LEGO.AsyncAPI.Tests/AsyncApiDocumentV2Tests.cs @@ -72,7 +72,6 @@ public void V2_AsyncApiDocument_WithStreetLightsExample_SerializesAndDeserialize 'smartylighting.streetlights.1.0.event.{streetlightId}.lighting.measured': description: The topic on which measured values may be produced and consumed. publish: - operationId: receiveLightMeasurement summary: Inform about environmental lighting conditions of a particular streetlight. traits: - $ref: '#/components/operationTraits/kafka' @@ -83,7 +82,6 @@ public void V2_AsyncApiDocument_WithStreetLightsExample_SerializesAndDeserialize $ref: '#/components/parameters/streetlightId' 'smartylighting.streetlights.1.0.action.{streetlightId}.turn.on': subscribe: - operationId: turnOn traits: - $ref: '#/components/operationTraits/kafka' message: @@ -93,7 +91,6 @@ public void V2_AsyncApiDocument_WithStreetLightsExample_SerializesAndDeserialize $ref: '#/components/parameters/streetlightId' 'smartylighting.streetlights.1.0.action.{streetlightId}.turn.off': subscribe: - operationId: turnOff traits: - $ref: '#/components/operationTraits/kafka' message: @@ -103,7 +100,6 @@ public void V2_AsyncApiDocument_WithStreetLightsExample_SerializesAndDeserialize $ref: '#/components/parameters/streetlightId' 'smartylighting.streetlights.1.0.action.{streetlightId}.dim': subscribe: - operationId: dimLight traits: - $ref: '#/components/operationTraits/kafka' message: