Skip to content

Commit 8772aa9

Browse files
bieluclaude
andcommitted
fix: keep unregistered bindings as errors
A binding without a registered parser is dropped from the model and is lost when the document is written back, so reading it stays an error with its original message. Adds tests covering a registered and an unregistered binding read together and re-serialized. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 parent 17089b5 commit 8772aa9

2 files changed

Lines changed: 59 additions & 14 deletions

File tree

‎src/ByteBard.AsyncAPI.Readers/BindingDeserializer.cs‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,9 @@ internal static AsyncApiBindings<TBinding> LoadBindings<TBinding>(
4040

4141
if (!parsers.TryGetValue(property.Name, out var parser))
4242
{
43-
context.Diagnostic.Warnings.Add(
44-
new AsyncApiError(context.GetLocation(), $"{bindingType} '{property.Name}' was ignored because no binding parser is registered for it."));
43+
// Reported as an error because the binding is dropped from the model and cannot be written back.
44+
context.Diagnostic.Errors.Add(
45+
new AsyncApiError(context.GetLocation(), $"{bindingType} {property.Name} is not found"));
4546
continue;
4647
}
4748

‎test/ByteBard.AsyncAPI.Tests/Bindings/BindingsDiagnostics_Should.cs‎

Lines changed: 56 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -55,30 +55,58 @@ public void MessageBindings_WithExtension_ReadsExtensionWithoutDiagnostics(Async
5555

5656
[TestCase(AsyncApiVersion.AsyncApi2_0)]
5757
[TestCase(AsyncApiVersion.AsyncApi3_0)]
58-
public void ServerBindings_WithUnregisteredBinding_AddsWarning(AsyncApiVersion version)
58+
public void ServerBindings_WithUnregisteredBinding_AddsError(AsyncApiVersion version)
5959
{
60-
AssertUnregisteredBindingWarns<IServerBinding>(version, "ServerBinding");
60+
AssertUnregisteredBindingErrors<IServerBinding>(version, "ServerBinding");
6161
}
6262

6363
[TestCase(AsyncApiVersion.AsyncApi2_0)]
6464
[TestCase(AsyncApiVersion.AsyncApi3_0)]
65-
public void ChannelBindings_WithUnregisteredBinding_AddsWarning(AsyncApiVersion version)
65+
public void ChannelBindings_WithUnregisteredBinding_AddsError(AsyncApiVersion version)
6666
{
67-
AssertUnregisteredBindingWarns<IChannelBinding>(version, "ChannelBinding");
67+
AssertUnregisteredBindingErrors<IChannelBinding>(version, "ChannelBinding");
6868
}
6969

7070
[TestCase(AsyncApiVersion.AsyncApi2_0)]
7171
[TestCase(AsyncApiVersion.AsyncApi3_0)]
72-
public void OperationBindings_WithUnregisteredBinding_AddsWarning(AsyncApiVersion version)
72+
public void OperationBindings_WithUnregisteredBinding_AddsError(AsyncApiVersion version)
7373
{
74-
AssertUnregisteredBindingWarns<IOperationBinding>(version, "OperationBinding");
74+
AssertUnregisteredBindingErrors<IOperationBinding>(version, "OperationBinding");
7575
}
7676

7777
[TestCase(AsyncApiVersion.AsyncApi2_0)]
7878
[TestCase(AsyncApiVersion.AsyncApi3_0)]
79-
public void MessageBindings_WithUnregisteredBinding_AddsWarning(AsyncApiVersion version)
79+
public void MessageBindings_WithUnregisteredBinding_AddsError(AsyncApiVersion version)
8080
{
81-
AssertUnregisteredBindingWarns<IMessageBinding>(version, "MessageBinding");
81+
AssertUnregisteredBindingErrors<IMessageBinding>(version, "MessageBinding");
82+
}
83+
84+
[TestCase(AsyncApiVersion.AsyncApi2_0)]
85+
[TestCase(AsyncApiVersion.AsyncApi3_0)]
86+
public void ServerBindings_WithRegisteredAndUnregisteredBinding_ReserializesOnlyRegisteredBinding(AsyncApiVersion version)
87+
{
88+
AssertUnregisteredBindingIsNotReserialized<IServerBinding>(version);
89+
}
90+
91+
[TestCase(AsyncApiVersion.AsyncApi2_0)]
92+
[TestCase(AsyncApiVersion.AsyncApi3_0)]
93+
public void ChannelBindings_WithRegisteredAndUnregisteredBinding_ReserializesOnlyRegisteredBinding(AsyncApiVersion version)
94+
{
95+
AssertUnregisteredBindingIsNotReserialized<IChannelBinding>(version);
96+
}
97+
98+
[TestCase(AsyncApiVersion.AsyncApi2_0)]
99+
[TestCase(AsyncApiVersion.AsyncApi3_0)]
100+
public void OperationBindings_WithRegisteredAndUnregisteredBinding_ReserializesOnlyRegisteredBinding(AsyncApiVersion version)
101+
{
102+
AssertUnregisteredBindingIsNotReserialized<IOperationBinding>(version);
103+
}
104+
105+
[TestCase(AsyncApiVersion.AsyncApi2_0)]
106+
[TestCase(AsyncApiVersion.AsyncApi3_0)]
107+
public void MessageBindings_WithRegisteredAndUnregisteredBinding_ReserializesOnlyRegisteredBinding(AsyncApiVersion version)
108+
{
109+
AssertUnregisteredBindingIsNotReserialized<IMessageBinding>(version);
82110
}
83111

84112
private static AsyncApiBindings<TBinding> Read<TBinding>(string input, AsyncApiVersion version, out AsyncApiDiagnostic diagnostic)
@@ -102,17 +130,33 @@ private static void AssertExtensionIsRead<TBinding>(AsyncApiVersion version)
102130
bindings.Extensions.Keys.Should().BeEquivalentTo("x-myextension");
103131
}
104132

105-
private static void AssertUnregisteredBindingWarns<TBinding>(AsyncApiVersion version, string bindingType)
133+
private static void AssertUnregisteredBindingErrors<TBinding>(AsyncApiVersion version, string bindingType)
106134
where TBinding : IBinding
107135
{
108136
// Act
109137
var bindings = Read<TBinding>(BindingsWithUnknownBinding, version, out var diagnostic);
110138

111139
// Assert
112-
diagnostic.Errors.Should().BeEmpty();
113-
diagnostic.Warnings.Select(w => w.Message).Should().BeEquivalentTo(
114-
$"{bindingType} 'unknown' was ignored because no binding parser is registered for it.");
140+
diagnostic.Errors.Select(e => e.Message).Should().BeEquivalentTo($"{bindingType} unknown is not found");
141+
diagnostic.Warnings.Should().BeEmpty();
115142
bindings.Keys.Should().BeEquivalentTo("kafka");
116143
}
144+
145+
private static void AssertUnregisteredBindingIsNotReserialized<TBinding>(AsyncApiVersion version)
146+
where TBinding : IBinding
147+
{
148+
// Arrange
149+
var bindings = Read<TBinding>(BindingsWithUnknownBinding, version, out var diagnostic);
150+
151+
// Act
152+
var reserialized = bindings.SerializeAsYaml(version);
153+
154+
// Assert
155+
// The model has no way to hold a binding without a parser, so it is lost on write.
156+
// That is why reading it must stay an error.
157+
diagnostic.Errors.Should().ContainSingle();
158+
reserialized.Should().Contain("kafka");
159+
reserialized.Should().NotContain("unknown");
160+
}
117161
}
118162
}

0 commit comments

Comments
 (0)