diff --git a/src/WireMock.Net.Minimal/WebSockets/WebSocketBuilder.cs b/src/WireMock.Net.Minimal/WebSockets/WebSocketBuilder.cs index 12563104..7b83f9a4 100644 --- a/src/WireMock.Net.Minimal/WebSockets/WebSocketBuilder.cs +++ b/src/WireMock.Net.Minimal/WebSockets/WebSocketBuilder.cs @@ -1,6 +1,7 @@ // Copyright © WireMock.Net using System; +using System.Collections.Generic; using System.Threading.Tasks; using Stef.Validation; using WireMock.Settings; @@ -64,30 +65,40 @@ internal class WebSocketBuilder : IWebSocketBuilder return this; } - public IWebSocketBuilder WithText(string text) + public IWebSocketBuilder WithMessage(Action configure) { - Guard.NotNull(text); + Guard.NotNull(configure); + var messageBuilder = new WebSocketMessageBuilder(); + configure(messageBuilder); + return WithMessageHandler(async (message, context) => { - await context.SendAsync(text); + if (messageBuilder.Delay.HasValue) + { + await Task.Delay(messageBuilder.Delay.Value); + } + + await SendMessageAsync(context, messageBuilder); }); } - public IWebSocketBuilder WithBytes(byte[] bytes) + public IWebSocketBuilder WithMessages(Action configure) { - Guard.NotNull(bytes); - return WithMessageHandler(async (message, context) => - { - await context.SendAsync(bytes); - }); - } + Guard.NotNull(configure); + var messagesBuilder = new WebSocketMessagesBuilder(); + configure(messagesBuilder); - public IWebSocketBuilder WithJson(object data) - { - Guard.NotNull(data); return WithMessageHandler(async (message, context) => { - await context.SendAsJsonAsync(data); + foreach (var messageBuilder in messagesBuilder.Messages) + { + if (messageBuilder.Delay.HasValue) + { + await Task.Delay(messageBuilder.Delay.Value); + } + + await SendMessageAsync(context, messageBuilder); + } }); } @@ -155,4 +166,20 @@ internal class WebSocketBuilder : IWebSocketBuilder TransformerReplaceNodeOptions = transformerReplaceNodeOptions; return this; } + + private static async Task SendMessageAsync(IWebSocketContext context, WebSocketMessageBuilder messageBuilder) + { + switch (messageBuilder.Type) + { + case WebSocketMessageBuilder.MessageType.Text: + await context.SendAsync(messageBuilder.MessageText!); + break; + case WebSocketMessageBuilder.MessageType.Bytes: + await context.SendAsync(messageBuilder.MessageBytes!); + break; + case WebSocketMessageBuilder.MessageType.Json: + await context.SendAsJsonAsync(messageBuilder.MessageData!); + break; + } + } } \ No newline at end of file diff --git a/src/WireMock.Net.Minimal/WebSockets/WebSocketMessageBuilder.cs b/src/WireMock.Net.Minimal/WebSockets/WebSocketMessageBuilder.cs new file mode 100644 index 00000000..cc80ca4a --- /dev/null +++ b/src/WireMock.Net.Minimal/WebSockets/WebSocketMessageBuilder.cs @@ -0,0 +1,59 @@ +// Copyright © WireMock.Net + +using Stef.Validation; + +namespace WireMock.WebSockets; + +internal class WebSocketMessageBuilder : IWebSocketMessageBuilder +{ + public string? MessageText { get; private set; } + + public byte[]? MessageBytes { get; private set; } + + public object? MessageData { get; private set; } + + public TimeSpan? Delay { get; private set; } + + public MessageType Type { get; private set; } + + public IWebSocketMessageBuilder WithText(string text) + { + MessageText = Guard.NotNull(text); + Type = MessageType.Text; + return this; + } + + public IWebSocketMessageBuilder WithBytes(byte[] bytes) + { + MessageBytes = Guard.NotNull(bytes); + Type = MessageType.Bytes; + return this; + } + + public IWebSocketMessageBuilder WithJson(object data) + { + MessageData = Guard.NotNull(data); + Type = MessageType.Json; + return this; + } + + public IWebSocketMessageBuilder WithDelay(TimeSpan delay) + { + Delay = delay; + return this; + } + + public IWebSocketMessageBuilder WithDelay(int delayInMilliseconds) + { + Guard.Condition(delayInMilliseconds, d => d >= 0, nameof(delayInMilliseconds)); + Delay = TimeSpan.FromMilliseconds(delayInMilliseconds); + return this; + } + + internal enum MessageType + { + Text, + Bytes, + Json + } +} diff --git a/src/WireMock.Net.Minimal/WebSockets/WebSocketMessagesBuilder.cs b/src/WireMock.Net.Minimal/WebSockets/WebSocketMessagesBuilder.cs new file mode 100644 index 00000000..58bebba1 --- /dev/null +++ b/src/WireMock.Net.Minimal/WebSockets/WebSocketMessagesBuilder.cs @@ -0,0 +1,18 @@ +// Copyright © WireMock.Net + +using System.Collections.Generic; + +namespace WireMock.WebSockets; + +internal class WebSocketMessagesBuilder : IWebSocketMessagesBuilder +{ + internal List Messages { get; } = new(); + + public IWebSocketMessagesBuilder AddMessage(Action configure) + { + var messageBuilder = new WebSocketMessageBuilder(); + configure(messageBuilder); + Messages.Add(messageBuilder); + return this; + } +} diff --git a/src/WireMock.Net.Shared/WebSockets/IWebSocketBuilder.cs b/src/WireMock.Net.Shared/WebSockets/IWebSocketBuilder.cs index 36e21ccc..d45d8fb2 100644 --- a/src/WireMock.Net.Shared/WebSockets/IWebSocketBuilder.cs +++ b/src/WireMock.Net.Shared/WebSockets/IWebSocketBuilder.cs @@ -24,25 +24,18 @@ public interface IWebSocketBuilder IWebSocketBuilder WithEcho(); /// - /// Send a specific text message in response to any received message + /// Configure and send a single message in response to any received message /// - /// The text message to send + /// Action to configure the message [PublicAPI] - IWebSocketBuilder WithText(string text); + IWebSocketBuilder WithMessage(Action configure); /// - /// Send specific binary data in response to any received message + /// Configure and send multiple messages in response to any received message /// - /// The binary data to send + /// Action to configure the messages [PublicAPI] - IWebSocketBuilder WithBytes(byte[] bytes); - - /// - /// Send a JSON object in response to any received message - /// - /// The object to serialize and send as JSON - [PublicAPI] - IWebSocketBuilder WithJson(object data); + IWebSocketBuilder WithMessages(Action configure); /// /// Handle incoming WebSocket messages diff --git a/src/WireMock.Net.Shared/WebSockets/IWebSocketMessageBuilder.cs b/src/WireMock.Net.Shared/WebSockets/IWebSocketMessageBuilder.cs new file mode 100644 index 00000000..c6a02c0f --- /dev/null +++ b/src/WireMock.Net.Shared/WebSockets/IWebSocketMessageBuilder.cs @@ -0,0 +1,46 @@ +// Copyright © WireMock.Net + +using JetBrains.Annotations; + +namespace WireMock.WebSockets; + +/// +/// WebSocket Message Builder interface for building individual messages with optional delays +/// +public interface IWebSocketMessageBuilder +{ + /// + /// Send a specific text message + /// + /// The text message to send + [PublicAPI] + IWebSocketMessageBuilder WithText(string text); + + /// + /// Send specific binary data + /// + /// The binary data to send + [PublicAPI] + IWebSocketMessageBuilder WithBytes(byte[] bytes); + + /// + /// Send a JSON object + /// + /// The object to serialize and send as JSON + [PublicAPI] + IWebSocketMessageBuilder WithJson(object data); + + /// + /// Set a delay before sending the message (using TimeSpan) + /// + /// The delay before sending the message + [PublicAPI] + IWebSocketMessageBuilder WithDelay(TimeSpan delay); + + /// + /// Set a delay before sending the message (using milliseconds) + /// + /// The delay in milliseconds before sending the message + [PublicAPI] + IWebSocketMessageBuilder WithDelay(int delayInMilliseconds); +} diff --git a/src/WireMock.Net.Shared/WebSockets/IWebSocketMessagesBuilder.cs b/src/WireMock.Net.Shared/WebSockets/IWebSocketMessagesBuilder.cs new file mode 100644 index 00000000..b3435d30 --- /dev/null +++ b/src/WireMock.Net.Shared/WebSockets/IWebSocketMessagesBuilder.cs @@ -0,0 +1,18 @@ +// Copyright © WireMock.Net + +using JetBrains.Annotations; + +namespace WireMock.WebSockets; + +/// +/// WebSocket Messages Builder interface for building multiple messages +/// +public interface IWebSocketMessagesBuilder +{ + /// + /// Add a message to the sequence + /// + /// Action to configure the message + [PublicAPI] + IWebSocketMessagesBuilder AddMessage(Action configure); +} diff --git a/test/WireMock.Net.Tests/WebSockets/WebSocketIntegrationTests.cs b/test/WireMock.Net.Tests/WebSockets/WebSocketIntegrationTests.cs index da94c52f..64e79a6c 100644 --- a/test/WireMock.Net.Tests/WebSockets/WebSocketIntegrationTests.cs +++ b/test/WireMock.Net.Tests/WebSockets/WebSocketIntegrationTests.cs @@ -72,7 +72,7 @@ public class WebSocketIntegrationTests(ITestOutputHelper output) ) .RespondWith(Response.Create() .WithWebSocket(ws => ws - .WithText(responseMessage) + .WithMessage(m => m.WithText(responseMessage)) ) ); @@ -117,7 +117,7 @@ public class WebSocketIntegrationTests(ITestOutputHelper output) ) .RespondWith(Response.Create() .WithWebSocket(ws => ws - .WithText(responseMessage) + .WithMessage(m => m.WithText(responseMessage)) ) ); @@ -161,7 +161,7 @@ public class WebSocketIntegrationTests(ITestOutputHelper output) ) .RespondWith(Response.Create() .WithWebSocket(ws => ws - .WithBytes(responseBytes) + .WithMessage(m => m.WithBytes(responseBytes)) ) ); @@ -207,7 +207,7 @@ public class WebSocketIntegrationTests(ITestOutputHelper output) ) .RespondWith(Response.Create() .WithWebSocket(ws => ws - .WithBytes(responseBytes) + .WithMessage(m => m.WithBytes(responseBytes)) ) ); @@ -258,7 +258,7 @@ public class WebSocketIntegrationTests(ITestOutputHelper output) ) .RespondWith(Response.Create() .WithWebSocket(ws => ws - .WithJson(responseData) + .WithMessage(m => m.WithJson(responseData)) ) ); @@ -311,7 +311,7 @@ public class WebSocketIntegrationTests(ITestOutputHelper output) ) .RespondWith(Response.Create() .WithWebSocket(ws => ws - .WithJson(responseData) + .WithMessage(m => m.WithJson(responseData)) ) );