diff --git a/examples/WireMock.Net.WebSocketExamples/Program.cs b/examples/WireMock.Net.WebSocketExamples/Program.cs index afb7ff43..c53f558d 100644 --- a/examples/WireMock.Net.WebSocketExamples/Program.cs +++ b/examples/WireMock.Net.WebSocketExamples/Program.cs @@ -20,8 +20,7 @@ public static class Program Console.WriteLine("Choose an example to run:"); Console.WriteLine("1. Echo Server"); Console.WriteLine("2. Custom Message Handler"); - Console.WriteLine("3. ..."); - Console.WriteLine("4. Scenario/State Machine"); + Console.WriteLine("3. Broadcast"); Console.WriteLine("5. WebSocket Proxy"); Console.WriteLine("6. Multiple WebSocket Endpoints"); Console.WriteLine("7. All Examples (runs all endpoints)"); @@ -41,9 +40,6 @@ public static class Program case "3": await RunBroadcastExample(); break; - case "4": - await RunScenarioExample(); - break; case "5": await RunProxyExample(); break; @@ -232,115 +228,6 @@ public static class Program server.Stop(); } - /// - /// Example 4: Scenario/State Machine - /// Demonstrates state transitions during WebSocket session - /// - private static async Task RunScenarioExample() - { - Console.WriteLine("\n=== Scenario/State Machine Example ==="); - Console.WriteLine("Starting WebSocket server with scenario support...\n"); - - var server = WireMockServer.Start(new WireMockServerSettings - { - Port = 9091, - Logger = new WireMockConsoleLogger() - }); - - // Initial state: Waiting for players - server - .Given(Request.Create() - .WithPath("/ws/game") - .WithWebSocketUpgrade() - ) - .InScenario("GameSession") - .WillSetStateTo("Lobby") - .RespondWith(Response.Create() - .WithWebSocket(ws => ws - .WithMessageHandler(async (msg, ctx) => - { - await ctx.SendAsync("Welcome to the game lobby! Type 'ready' to start or 'quit' to leave."); - }) - ) - ); - - // Lobby state: Waiting for ready - server - .Given(Request.Create() - .WithPath("/ws/game") - .WithWebSocketUpgrade() - ) - .InScenario("GameSession") - .WhenStateIs("Lobby") - .RespondWith(Response.Create() - .WithWebSocket(ws => ws - .WithMessageHandler(async (msg, ctx) => - { - var text = msg.Text?.ToLower() ?? string.Empty; - - if (text == "ready") - { - ctx.SetScenarioState("Playing"); - await ctx.SendAsync("Game started! Type 'attack' to attack, 'defend' to defend, or 'quit' to exit."); - } - else if (text == "quit") - { - await ctx.SendAsync("You left the lobby. Goodbye!"); - await ctx.CloseAsync(WebSocketCloseStatus.NormalClosure, "Player quit"); - } - else - { - await ctx.SendAsync("In lobby. Type 'ready' to start or 'quit' to leave."); - } - }) - ) - ); - - // Playing state: Game is active - server - .Given(Request.Create() - .WithPath("/ws/game") - .WithWebSocketUpgrade() - ) - .InScenario("GameSession") - .WhenStateIs("Playing") - .RespondWith(Response.Create() - .WithWebSocket(ws => ws - .WithMessageHandler(async (msg, ctx) => - { - var text = msg.Text?.ToLower() ?? string.Empty; - - if (text == "attack") - { - await ctx.SendAsync("You attacked! Critical hit! 💥"); - } - else if (text == "defend") - { - await ctx.SendAsync("You defended! Shield up! 🛡️"); - } - else if (text == "quit") - { - ctx.SetScenarioState("GameOver"); - await ctx.SendAsync("Game over! Thanks for playing."); - await ctx.CloseAsync(WebSocketCloseStatus.NormalClosure, "Game ended"); - } - else - { - await ctx.SendAsync("Unknown action. Type 'attack', 'defend', or 'quit'."); - } - }) - ) - ); - - Console.WriteLine($"Game server listening at: {server.Urls[0]}/ws/game"); - Console.WriteLine("\nConnect and follow the game flow:"); - Console.WriteLine(" wscat -c ws://localhost:9091/ws/game"); - Console.WriteLine("\nGame flow: Lobby -> Type 'ready' -> Playing -> Type 'attack'/'defend' -> Type 'quit'"); - Console.WriteLine("\nPress any key to stop server..."); - Console.ReadKey(); - server.Stop(); - } - /// /// Example 5: WebSocket Proxy /// Proxies WebSocket connections to another server @@ -547,9 +434,6 @@ public static class Program ) ); - // Game scenario endpoint - SetupGameScenario(server); - // Time endpoint server .Given(Request.Create() @@ -566,45 +450,6 @@ public static class Program ); } - private static void SetupGameScenario(WireMockServer server) - { - server - .Given(Request.Create() - .WithPath("/ws/game") - .WithWebSocketUpgrade() - ) - .InScenario("GameSession") - .WillSetStateTo("Lobby") - .RespondWith(Response.Create() - .WithWebSocket(ws => ws - .WithMessageHandler(async (msg, ctx) => - { - await ctx.SendAsync("Welcome! Type 'ready' to start."); - }) - ) - ); - - server - .Given(Request.Create() - .WithPath("/ws/game") - .WithWebSocketUpgrade() - ) - .InScenario("GameSession") - .WhenStateIs("Lobby") - .RespondWith(Response.Create() - .WithWebSocket(ws => ws - .WithMessageHandler(async (msg, ctx) => - { - if (msg.Text?.ToLower() == "ready") - { - ctx.SetScenarioState("Playing"); - await ctx.SendAsync("Game started!"); - } - }) - ) - ); - } - // Helper methods for testing private static async Task TestWebSocketEcho(string baseUrl) { diff --git a/src/WireMock.Net.Minimal/ResponseProviders/WebSocketResponseProvider.cs b/src/WireMock.Net.Minimal/ResponseProviders/WebSocketResponseProvider.cs index 0089cfe9..c3b5ce20 100644 --- a/src/WireMock.Net.Minimal/ResponseProviders/WebSocketResponseProvider.cs +++ b/src/WireMock.Net.Minimal/ResponseProviders/WebSocketResponseProvider.cs @@ -78,12 +78,6 @@ internal class WebSocketResponseProvider(WebSocketBuilder builder) : IResponsePr guidUtils ); - // Update scenario state following the same pattern as WireMockMiddleware - if (mapping.Scenario != null) - { - wsContext.UpdateScenarioState(); - } - // Add to registry if broadcast is enabled registry?.AddConnection(wsContext); diff --git a/src/WireMock.Net.Minimal/WebSockets/WireMockWebSocketContext.cs b/src/WireMock.Net.Minimal/WebSockets/WireMockWebSocketContext.cs index 08385897..2a5944b5 100644 --- a/src/WireMock.Net.Minimal/WebSockets/WireMockWebSocketContext.cs +++ b/src/WireMock.Net.Minimal/WebSockets/WireMockWebSocketContext.cs @@ -101,45 +101,6 @@ public class WireMockWebSocketContext : IWebSocketContext LogWebSocketMessage(WebSocketMessageDirection.Send, WebSocketMessageType.Close, $"CloseStatus: {closeStatus}, Description: {statusDescription}", null); } - /// - public void SetScenarioState(string nextState) - { - SetScenarioState(nextState, null); - } - - /// - public void SetScenarioState(string nextState, string? description) - { - if (Mapping.Scenario == null) - { - return; - } - - // Use the same logic as WireMockMiddleware - if (Options.Scenarios.TryGetValue(Mapping.Scenario, out var scenarioState)) - { - // Directly set the next state (bypass counter logic for manual WebSocket state changes) - scenarioState.NextState = nextState; - scenarioState.Started = true; - scenarioState.Finished = nextState == null; - - // Reset counter when manually setting state - scenarioState.Counter = 0; - } - else - { - // Create new scenario state if it doesn't exist - Options.Scenarios.TryAdd(Mapping.Scenario, new ScenarioState - { - Name = Mapping.Scenario, - NextState = nextState, - Started = true, - Finished = nextState == null, - Counter = 0 - }); - } - } - /// public async Task BroadcastTextAsync(string text, CancellationToken cancellationToken = default) { @@ -149,40 +110,6 @@ public class WireMockWebSocketContext : IWebSocketContext } } - /// - /// Update scenario state following the same pattern as WireMockMiddleware.UpdateScenarioState - /// This is called automatically when the WebSocket connection is established. - /// - internal void UpdateScenarioState() - { - if (Mapping.Scenario == null) - { - return; - } - - // Ensure scenario exists - if (!Options.Scenarios.TryGetValue(Mapping.Scenario, out var scenario)) - { - return; - } - - // Follow exact same logic as WireMockMiddleware.UpdateScenarioState - // Increase the number of times this state has been executed - scenario.Counter++; - - // Only if the number of times this state is executed equals the required StateTimes, - // proceed to next state and reset the counter to 0 - if (scenario.Counter == (Mapping.TimesInSameState ?? 1)) - { - scenario.NextState = Mapping.NextState; - scenario.Counter = 0; - } - - // Else just update Started and Finished - scenario.Started = true; - scenario.Finished = Mapping.NextState == null; - } - internal void LogWebSocketMessage( WebSocketMessageDirection direction, WebSocketMessageType messageType, diff --git a/src/WireMock.Net.Shared/WebSockets/IWebSocketContext.cs b/src/WireMock.Net.Shared/WebSockets/IWebSocketContext.cs index aca75940..3b5f950b 100644 --- a/src/WireMock.Net.Shared/WebSockets/IWebSocketContext.cs +++ b/src/WireMock.Net.Shared/WebSockets/IWebSocketContext.cs @@ -50,21 +50,6 @@ public interface IWebSocketContext /// Task CloseAsync(WebSocketCloseStatus closeStatus, string statusDescription); - /// - /// Manually set the scenario state. This bypasses the counter logic and directly sets the next state. - /// Use this for programmatic state changes during WebSocket sessions. - /// - /// The next state to transition to - void SetScenarioState(string nextState); - - /// - /// Manually set the scenario state with description. This bypasses the counter logic and directly sets the next state. - /// Use this for programmatic state changes during WebSocket sessions. - /// - /// The next state to transition to - /// Optional description for logging - void SetScenarioState(string nextState, string? description); - /// /// Broadcast text message to all connections in this mapping ///