diff --git a/WireMock.Net Solution.sln.DotSettings b/WireMock.Net Solution.sln.DotSettings index 448c9dfd..99ef6d87 100644 --- a/WireMock.Net Solution.sln.DotSettings +++ b/WireMock.Net Solution.sln.DotSettings @@ -1,10 +1,18 @@  AD + CONNECT CS + DELETE EC + GET + HEAD ID IP MD5 + OPTIONS + PATCH + POST + PUT RSA SSL TE diff --git a/src/WireMock.Net/Http/HttpRequestMethods.cs b/src/WireMock.Net.Abstractions/Constants/HttpRequestMethod.cs similarity index 86% rename from src/WireMock.Net/Http/HttpRequestMethods.cs rename to src/WireMock.Net.Abstractions/Constants/HttpRequestMethod.cs index e33399db..6f689a09 100644 --- a/src/WireMock.Net/Http/HttpRequestMethods.cs +++ b/src/WireMock.Net.Abstractions/Constants/HttpRequestMethod.cs @@ -1,9 +1,9 @@ -namespace WireMock.Http; +namespace WireMock.Constants; /// /// https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods /// -internal static class HttpRequestMethods +public static class HttpRequestMethod { public const string CONNECT = "CONNECT"; public const string DELETE = "DELETE"; diff --git a/src/WireMock.Net.Abstractions/Server/IWireMockServer.cs b/src/WireMock.Net.Abstractions/Server/IWireMockServer.cs index 3393bdda..2775049b 100644 --- a/src/WireMock.Net.Abstractions/Server/IWireMockServer.cs +++ b/src/WireMock.Net.Abstractions/Server/IWireMockServer.cs @@ -1,10 +1,8 @@ using System; using System.Collections.Generic; using System.Collections.Specialized; -using JetBrains.Annotations; using WireMock.Admin.Mappings; using WireMock.Logging; -using WireMock.Matchers.Request; namespace WireMock.Server { @@ -144,6 +142,11 @@ namespace WireMock.Server /// void ResetScenarios(); + /// + /// Resets a specific Scenario by the name. + /// + bool ResetScenario(string name); + /// /// Resets the LogEntries. /// diff --git a/src/WireMock.Net.FluentAssertions/Assertions/WireMockAssertions.cs b/src/WireMock.Net.FluentAssertions/Assertions/WireMockAssertions.cs index 7fb7911f..cb170987 100644 --- a/src/WireMock.Net.FluentAssertions/Assertions/WireMockAssertions.cs +++ b/src/WireMock.Net.FluentAssertions/Assertions/WireMockAssertions.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.Linq; using FluentAssertions; using FluentAssertions.Execution; +using WireMock.Constants; using WireMock.Server; using WireMock.Types; @@ -169,39 +170,39 @@ public class WireMockAssertions [CustomAssertion] public AndConstraint UsingConnect(string because = "", params object[] becauseArgs) - => UsingMethod("CONNECT", because, becauseArgs); + => UsingMethod(HttpRequestMethod.CONNECT, because, becauseArgs); [CustomAssertion] public AndConstraint UsingDelete(string because = "", params object[] becauseArgs) - => UsingMethod("DELETE", because, becauseArgs); + => UsingMethod(HttpRequestMethod.DELETE, because, becauseArgs); [CustomAssertion] public AndConstraint UsingGet(string because = "", params object[] becauseArgs) - => UsingMethod("GET", because, becauseArgs); + => UsingMethod(HttpRequestMethod.GET, because, becauseArgs); [CustomAssertion] public AndConstraint UsingHead(string because = "", params object[] becauseArgs) - => UsingMethod("HEAD", because, becauseArgs); + => UsingMethod(HttpRequestMethod.HEAD, because, becauseArgs); [CustomAssertion] public AndConstraint UsingOptions(string because = "", params object[] becauseArgs) - => UsingMethod("OPTIONS", because, becauseArgs); + => UsingMethod(HttpRequestMethod.OPTIONS, because, becauseArgs); [CustomAssertion] public AndConstraint UsingPost(string because = "", params object[] becauseArgs) - => UsingMethod("POST", because, becauseArgs); + => UsingMethod(HttpRequestMethod.POST, because, becauseArgs); [CustomAssertion] public AndConstraint UsingPatch(string because = "", params object[] becauseArgs) - => UsingMethod("PATCH", because, becauseArgs); + => UsingMethod(HttpRequestMethod.PATCH, because, becauseArgs); [CustomAssertion] public AndConstraint UsingPut(string because = "", params object[] becauseArgs) - => UsingMethod("PUT", because, becauseArgs); + => UsingMethod(HttpRequestMethod.PUT, because, becauseArgs); [CustomAssertion] public AndConstraint UsingTrace(string because = "", params object[] becauseArgs) - => UsingMethod("TRACE", because, becauseArgs); + => UsingMethod(HttpRequestMethod.TRACE, because, becauseArgs); [CustomAssertion] public AndConstraint UsingAnyMethod(string because = "", params object[] becauseArgs) diff --git a/src/WireMock.Net.RestClient/IWireMockAdminApi.cs b/src/WireMock.Net.RestClient/IWireMockAdminApi.cs index 44737cbb..65a62bb4 100644 --- a/src/WireMock.Net.RestClient/IWireMockAdminApi.cs +++ b/src/WireMock.Net.RestClient/IWireMockAdminApi.cs @@ -1,4 +1,4 @@ -using RestEase; +using RestEase; using System; using System.Collections.Generic; using System.Net.Http.Headers; @@ -179,6 +179,20 @@ namespace WireMock.Client [Post("scenarios")] Task ResetScenariosAsync(); + /// + /// Delete (reset) a specific scenario + /// + [Delete("scenarios/{name}")] + [AllowAnyStatusCode] + Task DeleteScenarioAsync([Path] string name); + + /// + /// Delete (reset) all scenarios + /// + [Post("scenarios/{name}/reset")] + [AllowAnyStatusCode] + Task ResetScenarioAsync([Path] string name); + /// /// Create a new File /// diff --git a/src/WireMock.Net/Owin/WireMockMiddlewareOptions.cs b/src/WireMock.Net/Owin/WireMockMiddlewareOptions.cs index 568d1bd1..72cbe3cf 100644 --- a/src/WireMock.Net/Owin/WireMockMiddlewareOptions.cs +++ b/src/WireMock.Net/Owin/WireMockMiddlewareOptions.cs @@ -26,7 +26,7 @@ internal class WireMockMiddlewareOptions : IWireMockMiddlewareOptions public ConcurrentDictionary Mappings { get; } = new ConcurrentDictionary(); - public ConcurrentDictionary Scenarios { get; } = new(); + public ConcurrentDictionary Scenarios { get; } = new(StringComparer.OrdinalIgnoreCase); public ConcurrentObservableCollection LogEntries { get; } = new(); diff --git a/src/WireMock.Net/Pact/Models/V2/Interaction.cs b/src/WireMock.Net/Pact/Models/V2/Interaction.cs index f09dc1cc..b5d4de8e 100644 --- a/src/WireMock.Net/Pact/Models/V2/Interaction.cs +++ b/src/WireMock.Net/Pact/Models/V2/Interaction.cs @@ -1,3 +1,4 @@ +#pragma warning disable CS1591 namespace WireMock.Pact.Models.V2; public class Interaction diff --git a/src/WireMock.Net/Pact/Models/V2/MatchingRule.cs b/src/WireMock.Net/Pact/Models/V2/MatchingRule.cs index f5b147a4..6d08751b 100644 --- a/src/WireMock.Net/Pact/Models/V2/MatchingRule.cs +++ b/src/WireMock.Net/Pact/Models/V2/MatchingRule.cs @@ -1,25 +1,25 @@ -namespace WireMock.Pact.Models.V2 +#pragma warning disable CS1591 +namespace WireMock.Pact.Models.V2; + +public class MatchingRule { - public class MatchingRule - { - /// - /// type or regex - /// - public string Match { get; set; } = "type"; + /// + /// type or regex + /// + public string Match { get; set; } = "type"; - /// - /// Used for Match = "type" - /// - public string Min { get; set; } + /// + /// Used for Match = "type" + /// + public string Min { get; set; } - /// - /// Used for Match = "type" - /// - public string Max { get; set; } + /// + /// Used for Match = "type" + /// + public string Max { get; set; } - /// - /// Used for Match = "regex" - /// - public string Regex { get; set; } - } + /// + /// Used for Match = "regex" + /// + public string Regex { get; set; } } \ No newline at end of file diff --git a/src/WireMock.Net/Pact/Models/V2/Metadata.cs b/src/WireMock.Net/Pact/Models/V2/Metadata.cs index fbae2808..f3c8eddd 100644 --- a/src/WireMock.Net/Pact/Models/V2/Metadata.cs +++ b/src/WireMock.Net/Pact/Models/V2/Metadata.cs @@ -1,9 +1,9 @@ -namespace WireMock.Pact.Models.V2 -{ - public class Metadata - { - public string PactSpecificationVersion { get; set; } +#pragma warning disable CS1591 +namespace WireMock.Pact.Models.V2; - public PactSpecification PactSpecification { get; set; } = new PactSpecification(); - } +public class Metadata +{ + public string PactSpecificationVersion { get; set; } + + public PactSpecification PactSpecification { get; set; } = new PactSpecification(); } \ No newline at end of file diff --git a/src/WireMock.Net/Pact/Models/V2/Pact.cs b/src/WireMock.Net/Pact/Models/V2/Pact.cs index 9c75f80a..de8e904a 100644 --- a/src/WireMock.Net/Pact/Models/V2/Pact.cs +++ b/src/WireMock.Net/Pact/Models/V2/Pact.cs @@ -1,15 +1,15 @@ +#pragma warning disable CS1591 using System.Collections.Generic; -namespace WireMock.Pact.Models.V2 +namespace WireMock.Pact.Models.V2; + +public class Pact { - public class Pact - { - public Pacticipant Consumer { get; set; } + public Pacticipant Consumer { get; set; } - public List Interactions { get; set; } = new List(); + public List Interactions { get; set; } = new List(); - public Metadata Metadata { get; set; } + public Metadata Metadata { get; set; } - public Pacticipant Provider { get; set; } - } + public Pacticipant Provider { get; set; } } \ No newline at end of file diff --git a/src/WireMock.Net/Pact/Models/V2/PactRequest.cs b/src/WireMock.Net/Pact/Models/V2/PactRequest.cs index b4329b83..03ac4bc6 100644 --- a/src/WireMock.Net/Pact/Models/V2/PactRequest.cs +++ b/src/WireMock.Net/Pact/Models/V2/PactRequest.cs @@ -1,4 +1,6 @@ +#pragma warning disable CS1591 using System.Collections.Generic; +using WireMock.Constants; namespace WireMock.Pact.Models.V2; @@ -6,7 +8,7 @@ public class PactRequest { public IDictionary? Headers { get; set; } - public string Method { get; set; } = "GET"; + public string Method { get; set; } = HttpRequestMethod.GET; public string? Path { get; set; } = "/"; diff --git a/src/WireMock.Net/Pact/Models/V2/PactResponse.cs b/src/WireMock.Net/Pact/Models/V2/PactResponse.cs index d2bdc812..e5e4fbb8 100644 --- a/src/WireMock.Net/Pact/Models/V2/PactResponse.cs +++ b/src/WireMock.Net/Pact/Models/V2/PactResponse.cs @@ -1,3 +1,4 @@ +#pragma warning disable CS1591 using System.Collections.Generic; namespace WireMock.Pact.Models.V2; diff --git a/src/WireMock.Net/Pact/Models/V2/PactRust.cs b/src/WireMock.Net/Pact/Models/V2/PactRust.cs index 70347ca9..d9cd1e3b 100644 --- a/src/WireMock.Net/Pact/Models/V2/PactRust.cs +++ b/src/WireMock.Net/Pact/Models/V2/PactRust.cs @@ -1,11 +1,11 @@ -namespace WireMock.Pact.Models.V2 +#pragma warning disable CS1591 +namespace WireMock.Pact.Models.V2; + +public class PactRust { - public class PactRust - { - public string Ffi { get; set; } + public string Ffi { get; set; } - public string Mockserver { get; set; } + public string Mockserver { get; set; } - public string Models { get; set; } - } + public string Models { get; set; } } \ No newline at end of file diff --git a/src/WireMock.Net/Pact/Models/V2/PactSpecification.cs b/src/WireMock.Net/Pact/Models/V2/PactSpecification.cs index de7309be..c91515f8 100644 --- a/src/WireMock.Net/Pact/Models/V2/PactSpecification.cs +++ b/src/WireMock.Net/Pact/Models/V2/PactSpecification.cs @@ -1,7 +1,7 @@ -namespace WireMock.Pact.Models.V2 +#pragma warning disable CS1591 +namespace WireMock.Pact.Models.V2; + +public class PactSpecification { - public class PactSpecification - { - public string Version { get; set; } = "2.0"; - } + public string Version { get; set; } = "2.0"; } \ No newline at end of file diff --git a/src/WireMock.Net/Pact/Models/V2/Pacticipant.cs b/src/WireMock.Net/Pact/Models/V2/Pacticipant.cs index 3077835e..b701137e 100644 --- a/src/WireMock.Net/Pact/Models/V2/Pacticipant.cs +++ b/src/WireMock.Net/Pact/Models/V2/Pacticipant.cs @@ -1,7 +1,7 @@ -namespace WireMock.Pact.Models.V2 +#pragma warning disable CS1591 +namespace WireMock.Pact.Models.V2; + +public class Pacticipant { - public class Pacticipant - { - public string Name { get; set; } - } + public string Name { get; set; } } \ No newline at end of file diff --git a/src/WireMock.Net/Pact/Models/V2/ProviderState.cs b/src/WireMock.Net/Pact/Models/V2/ProviderState.cs index 0d163cc8..dd9a5a0d 100644 --- a/src/WireMock.Net/Pact/Models/V2/ProviderState.cs +++ b/src/WireMock.Net/Pact/Models/V2/ProviderState.cs @@ -1,11 +1,11 @@ +#pragma warning disable CS1591 using System.Collections.Generic; -namespace WireMock.Pact.Models.V2 -{ - public class ProviderState - { - public string Name { get; set; } +namespace WireMock.Pact.Models.V2; - public IDictionary Params { get; set; } - } +public class ProviderState +{ + public string Name { get; set; } + + public IDictionary Params { get; set; } } \ No newline at end of file diff --git a/src/WireMock.Net/Proxy/ProxyHelper.cs b/src/WireMock.Net/Proxy/ProxyHelper.cs index 26a32a8e..ed7270e5 100644 --- a/src/WireMock.Net/Proxy/ProxyHelper.cs +++ b/src/WireMock.Net/Proxy/ProxyHelper.cs @@ -1,17 +1,10 @@ -using Stef.Validation; using System; -using System.Collections.Generic; -using System.Linq; using System.Net.Http; using System.Threading.Tasks; -using WireMock.Constants; +using Stef.Validation; using WireMock.Http; -using WireMock.Matchers; -using WireMock.RequestBuilders; -using WireMock.ResponseBuilders; using WireMock.Serialization; using WireMock.Settings; -using WireMock.Types; using WireMock.Util; namespace WireMock.Proxy; @@ -62,69 +55,4 @@ internal class ProxyHelper return (responseMessage, newMapping); } - - private IMapping ToMapping(ProxyAndRecordSettings proxyAndRecordSettings, IRequestMessage requestMessage, ResponseMessage responseMessage) - { - var excludedHeaders = proxyAndRecordSettings.ExcludedHeaders ?? new string[] { }; - var excludedCookies = proxyAndRecordSettings.ExcludedCookies ?? new string[] { }; - - var request = Request.Create(); - request.WithPath(requestMessage.Path); - request.UsingMethod(requestMessage.Method); - - requestMessage.Query?.Loop((key, value) => request.WithParam(key, false, value.ToArray())); - requestMessage.Cookies?.Loop((key, value) => - { - if (!excludedCookies.Contains(key, StringComparer.OrdinalIgnoreCase)) - { - request.WithCookie(key, value); - } - }); - - var allExcludedHeaders = new List(excludedHeaders) { "Cookie" }; - requestMessage.Headers?.Loop((key, value) => - { - if (!allExcludedHeaders.Contains(key, StringComparer.OrdinalIgnoreCase)) - { - request.WithHeader(key, value.ToArray()); - } - }); - - bool throwExceptionWhenMatcherFails = _settings.ThrowExceptionWhenMatcherFails == true; - switch (requestMessage.BodyData?.DetectedBodyType) - { - case BodyType.Json: - request.WithBody(new JsonMatcher(MatchBehaviour.AcceptOnMatch, requestMessage.BodyData.BodyAsJson!, true, throwExceptionWhenMatcherFails)); - break; - - case BodyType.String: - request.WithBody(new ExactMatcher(MatchBehaviour.AcceptOnMatch, false, throwExceptionWhenMatcherFails, MatchOperator.Or, requestMessage.BodyData.BodyAsString)); - break; - - case BodyType.Bytes: - request.WithBody(new ExactObjectMatcher(MatchBehaviour.AcceptOnMatch, requestMessage.BodyData.BodyAsBytes, throwExceptionWhenMatcherFails)); - break; - } - - var response = Response.Create(responseMessage); - - return new Mapping - ( - guid: Guid.NewGuid(), - title: $"Proxy Mapping for {requestMessage.Method} {requestMessage.Path}", - description: string.Empty, - path: null, - settings: _settings, - request, - response, - priority: WireMockConstants.ProxyPriority, // This was 0 - scenario: null, - executionConditionState: null, - nextState: null, - stateTimes: null, - webhooks: null, - useWebhooksFireAndForget: null, - timeSettings: null - ); - } } \ No newline at end of file diff --git a/src/WireMock.Net/RequestBuilders/Request.UsingMethods.cs b/src/WireMock.Net/RequestBuilders/Request.UsingMethods.cs index a380c5b5..f5c4d1a4 100644 --- a/src/WireMock.Net/RequestBuilders/Request.UsingMethods.cs +++ b/src/WireMock.Net/RequestBuilders/Request.UsingMethods.cs @@ -1,10 +1,10 @@ // This source file is based on mock4net by Alexandre Victoor which is licensed under the Apache 2.0 License. // For more details see 'mock4net/LICENSE.txt' and 'mock4net/readme.md' in this project root. using System.Linq; -using WireMock.Http; +using Stef.Validation; +using WireMock.Constants; using WireMock.Matchers; using WireMock.Matchers.Request; -using Stef.Validation; namespace WireMock.RequestBuilders; @@ -13,63 +13,63 @@ public partial class Request /// public IRequestBuilder UsingConnect(MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch) { - _requestMatchers.Add(new RequestMessageMethodMatcher(matchBehaviour, MatchOperator.Or, HttpRequestMethods.CONNECT)); + _requestMatchers.Add(new RequestMessageMethodMatcher(matchBehaviour, MatchOperator.Or, HttpRequestMethod.CONNECT)); return this; } /// public IRequestBuilder UsingDelete(MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch) { - _requestMatchers.Add(new RequestMessageMethodMatcher(matchBehaviour, MatchOperator.Or, HttpRequestMethods.DELETE)); + _requestMatchers.Add(new RequestMessageMethodMatcher(matchBehaviour, MatchOperator.Or, HttpRequestMethod.DELETE)); return this; } /// public IRequestBuilder UsingGet(MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch) { - _requestMatchers.Add(new RequestMessageMethodMatcher(matchBehaviour, MatchOperator.Or, HttpRequestMethods.GET)); + _requestMatchers.Add(new RequestMessageMethodMatcher(matchBehaviour, MatchOperator.Or, HttpRequestMethod.GET)); return this; } /// public IRequestBuilder UsingHead(MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch) { - _requestMatchers.Add(new RequestMessageMethodMatcher(matchBehaviour, MatchOperator.Or, HttpRequestMethods.HEAD)); + _requestMatchers.Add(new RequestMessageMethodMatcher(matchBehaviour, MatchOperator.Or, HttpRequestMethod.HEAD)); return this; } /// public IRequestBuilder UsingOptions(MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch) { - _requestMatchers.Add(new RequestMessageMethodMatcher(matchBehaviour, MatchOperator.Or, HttpRequestMethods.OPTIONS)); + _requestMatchers.Add(new RequestMessageMethodMatcher(matchBehaviour, MatchOperator.Or, HttpRequestMethod.OPTIONS)); return this; } /// public IRequestBuilder UsingPost(MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch) { - _requestMatchers.Add(new RequestMessageMethodMatcher(matchBehaviour, MatchOperator.Or, HttpRequestMethods.POST)); + _requestMatchers.Add(new RequestMessageMethodMatcher(matchBehaviour, MatchOperator.Or, HttpRequestMethod.POST)); return this; } /// public IRequestBuilder UsingPatch(MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch) { - _requestMatchers.Add(new RequestMessageMethodMatcher(matchBehaviour, MatchOperator.Or, HttpRequestMethods.PATCH)); + _requestMatchers.Add(new RequestMessageMethodMatcher(matchBehaviour, MatchOperator.Or, HttpRequestMethod.PATCH)); return this; } /// public IRequestBuilder UsingPut(MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch) { - _requestMatchers.Add(new RequestMessageMethodMatcher(matchBehaviour, MatchOperator.Or, HttpRequestMethods.PUT)); + _requestMatchers.Add(new RequestMessageMethodMatcher(matchBehaviour, MatchOperator.Or, HttpRequestMethod.PUT)); return this; } /// public IRequestBuilder UsingTrace(MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch) { - _requestMatchers.Add(new RequestMessageMethodMatcher(matchBehaviour, MatchOperator.Or, HttpRequestMethods.TRACE)); + _requestMatchers.Add(new RequestMessageMethodMatcher(matchBehaviour, MatchOperator.Or, HttpRequestMethod.TRACE)); return this; } diff --git a/src/WireMock.Net/ScenarioState.cs b/src/WireMock.Net/ScenarioState.cs index 2c7f57a8..37e303e6 100644 --- a/src/WireMock.Net/ScenarioState.cs +++ b/src/WireMock.Net/ScenarioState.cs @@ -8,7 +8,7 @@ public class ScenarioState /// /// Gets or sets the Name (from the Scenario). /// - public string? Name { get; set; } + public string Name { get; set; } = null!; /// /// Gets or sets the NextState. diff --git a/src/WireMock.Net/Server/WireMockServer.Admin.cs b/src/WireMock.Net/Server/WireMockServer.Admin.cs index f8399fca..9e0e0424 100644 --- a/src/WireMock.Net/Server/WireMockServer.Admin.cs +++ b/src/WireMock.Net/Server/WireMockServer.Admin.cs @@ -46,6 +46,8 @@ public partial class WireMockServer private static readonly RegexMatcher AdminRequestContentTypeJson = new ContentTypeMatcher(WireMockConstants.ContentTypeJson, true); private static readonly RegexMatcher AdminMappingsGuidPathMatcher = new(@"^\/__admin\/mappings\/([0-9A-Fa-f]{8}[-][0-9A-Fa-f]{4}[-][0-9A-Fa-f]{4}[-][0-9A-Fa-f]{4}[-][0-9A-Fa-f]{12})$"); private static readonly RegexMatcher AdminRequestsGuidPathMatcher = new(@"^\/__admin\/requests\/([0-9A-Fa-f]{8}[-][0-9A-Fa-f]{4}[-][0-9A-Fa-f]{4}[-][0-9A-Fa-f]{4}[-][0-9A-Fa-f]{12})$"); + private static readonly RegexMatcher AdminScenariosNameMatcher = new(@"^\/__admin\/scenarios\/.+$"); + private static readonly RegexMatcher AdminScenariosNameWithResetMatcher = new(@"^\/__admin\/scenarios\/.+\/reset$"); private EnhancedFileSystemWatcher? _enhancedFileSystemWatcher; @@ -93,9 +95,11 @@ public partial class WireMockServer // __admin/scenarios Given(Request.Create().WithPath(AdminScenarios).UsingGet()).AtPriority(WireMockConstants.AdminPriority).RespondWith(new DynamicResponseProvider(ScenariosGet)); Given(Request.Create().WithPath(AdminScenarios).UsingDelete()).AtPriority(WireMockConstants.AdminPriority).RespondWith(new DynamicResponseProvider(ScenariosReset)); + Given(Request.Create().WithPath(AdminScenariosNameMatcher).UsingDelete()).AtPriority(WireMockConstants.AdminPriority).RespondWith(new DynamicResponseProvider(ScenarioReset)); // __admin/scenarios/reset Given(Request.Create().WithPath(AdminScenarios + "/reset").UsingPost()).AtPriority(WireMockConstants.AdminPriority).RespondWith(new DynamicResponseProvider(ScenariosReset)); + Given(Request.Create().WithPath(AdminScenariosNameWithResetMatcher).UsingPost()).AtPriority(WireMockConstants.AdminPriority).RespondWith(new DynamicResponseProvider(ScenarioReset)); // __admin/files/{filename} Given(Request.Create().WithPath(_adminFilesFilenamePathMatcher).UsingPost()).AtPriority(WireMockConstants.AdminPriority).RespondWith(new DynamicResponseProvider(FilePost)); @@ -610,6 +614,17 @@ public partial class WireMockServer return ResponseMessageBuilder.Create("Scenarios reset"); } + + private IResponseMessage ScenarioReset(IRequestMessage requestMessage) + { + var name = string.Equals(HttpRequestMethod.DELETE, requestMessage.Method, StringComparison.OrdinalIgnoreCase) ? + requestMessage.Path.Substring(AdminScenarios.Length + 1) : + requestMessage.Path.Split('/').Reverse().Skip(1).First(); + + return ResetScenario(name) ? + ResponseMessageBuilder.Create("Scenario reset") : + ResponseMessageBuilder.Create($"No scenario found by name '{name}'.", 404); + } #endregion #region Pact diff --git a/src/WireMock.Net/Server/WireMockServer.cs b/src/WireMock.Net/Server/WireMockServer.cs index 77efceb3..085cc073 100644 --- a/src/WireMock.Net/Server/WireMockServer.cs +++ b/src/WireMock.Net/Server/WireMockServer.cs @@ -477,6 +477,13 @@ public partial class WireMockServer : IWireMockServer _options.Scenarios.Clear(); } + /// + [PublicAPI] + public bool ResetScenario(string name) + { + return _options.Scenarios.ContainsKey(name) && _options.Scenarios.TryRemove(name, out _); + } + /// [PublicAPI] public IWireMockServer WithMapping(params MappingModel[] mappings) diff --git a/src/WireMock.Net/Transformers/ITransformer.cs b/src/WireMock.Net/Transformers/ITransformer.cs index b1797135..026f7bbc 100644 --- a/src/WireMock.Net/Transformers/ITransformer.cs +++ b/src/WireMock.Net/Transformers/ITransformer.cs @@ -10,7 +10,7 @@ interface ITransformer IBodyData? TransformBody(IMapping mapping, IRequestMessage originalRequestMessage, IResponseMessage originalResponseMessage, IBodyData? bodyData, ReplaceNodeOptions options); - IDictionary>? TransformHeaders(IMapping mapping, IRequestMessage originalRequestMessage, IResponseMessage originalResponseMessage, IDictionary>? headers); + IDictionary> TransformHeaders(IMapping mapping, IRequestMessage originalRequestMessage, IResponseMessage originalResponseMessage, IDictionary>? headers); string TransformString(IMapping mapping, IRequestMessage originalRequestMessage, IResponseMessage originalResponseMessage, string? value); } \ No newline at end of file diff --git a/src/WireMock.Net/Transformers/Transformer.cs b/src/WireMock.Net/Transformers/Transformer.cs index d53d4e45..cddf0b3f 100644 --- a/src/WireMock.Net/Transformers/Transformer.cs +++ b/src/WireMock.Net/Transformers/Transformer.cs @@ -36,7 +36,7 @@ internal class Transformer : ITransformer return newBodyData; } - public IDictionary>? TransformHeaders( + public IDictionary> TransformHeaders( IMapping mapping, IRequestMessage originalRequestMessage, IResponseMessage originalResponseMessage, @@ -239,6 +239,7 @@ internal class Transformer : ITransformer } } + // ReSharper disable once UnusedParameter.Local private static void ReplaceNodeValue(ReplaceNodeOptions options, JToken node, string transformedString) { StringUtils.TryParseQuotedString(transformedString, out var result, out _); @@ -270,13 +271,13 @@ internal class Transformer : ITransformer Encoding = original.Encoding, DetectedBodyType = original.DetectedBodyType, DetectedBodyTypeFromContentType = original.DetectedBodyTypeFromContentType, - BodyAsString = handlebarsContext.ParseAndRender(original.BodyAsString, model) + BodyAsString = handlebarsContext.ParseAndRender(original.BodyAsString!, model) }; } private static IBodyData TransformBodyAsFile(ITransformerContext handlebarsContext, object model, IBodyData original, bool useTransformerForBodyAsFile) { - string transformedBodyAsFilename = handlebarsContext.ParseAndRender(original.BodyAsFile, model); + string transformedBodyAsFilename = handlebarsContext.ParseAndRender(original.BodyAsFile!, model); if (!useTransformerForBodyAsFile) { diff --git a/src/WireMock.Net/Util/BodyParser.cs b/src/WireMock.Net/Util/BodyParser.cs index 3ba04391..5ff5a9dd 100644 --- a/src/WireMock.Net/Util/BodyParser.cs +++ b/src/WireMock.Net/Util/BodyParser.cs @@ -5,7 +5,7 @@ using System.Net.Http.Headers; using System.Text; using System.Threading.Tasks; using Stef.Validation; -using WireMock.Http; +using WireMock.Constants; using WireMock.Matchers; using WireMock.Types; @@ -29,15 +29,15 @@ internal static class BodyParser */ private static readonly IDictionary BodyAllowedForMethods = new Dictionary { - { HttpRequestMethods.HEAD, false }, - { HttpRequestMethods.GET, false }, - { HttpRequestMethods.PUT, true }, - { HttpRequestMethods.POST, true }, - { HttpRequestMethods.DELETE, true }, - { HttpRequestMethods.TRACE, false }, - { HttpRequestMethods.OPTIONS, true }, - { HttpRequestMethods.CONNECT, false }, - { HttpRequestMethods.PATCH, true } + { HttpRequestMethod.HEAD, false }, + { HttpRequestMethod.GET, false }, + { HttpRequestMethod.PUT, true }, + { HttpRequestMethod.POST, true }, + { HttpRequestMethod.DELETE, true }, + { HttpRequestMethod.TRACE, false }, + { HttpRequestMethod.OPTIONS, true }, + { HttpRequestMethod.CONNECT, false }, + { HttpRequestMethod.PATCH, true } }; private static readonly IStringMatcher[] MultipartContentTypesMatchers = { @@ -122,7 +122,7 @@ internal static class BodyParser // In case of MultiPart: check if the BodyAsBytes is a valid UTF8 or ASCII string, in that case read as String else keep as-is if (data.DetectedBodyTypeFromContentType == BodyType.MultiPart) { - if (BytesEncodingUtils.TryGetEncoding(data.BodyAsBytes, out Encoding encoding) && + if (BytesEncodingUtils.TryGetEncoding(data.BodyAsBytes, out var encoding) && SupportedBodyAsStringEncodingForMultipart.Select(x => x.Equals(encoding)).Any()) { data.BodyAsString = encoding.GetString(data.BodyAsBytes); diff --git a/test/WireMock.Net.Tests/WireMockAdminApiTests.cs b/test/WireMock.Net.Tests/WireMockAdminApiTests.cs index 9fea0a0c..d3b4ff1c 100644 --- a/test/WireMock.Net.Tests/WireMockAdminApiTests.cs +++ b/test/WireMock.Net.Tests/WireMockAdminApiTests.cs @@ -603,5 +603,31 @@ public class WireMockAdminApiTests server.Stop(); } + + [Fact] + public async Task IWireMockAdminApi_DeleteScenarioUsingDeleteAsync() + { + // Arrange + var name = "x"; + var server = WireMockServer.StartWithAdminInterface(); + var api = RestClient.For(server.Urls[0]); + + // Act + var status = await api.DeleteScenarioAsync(name).ConfigureAwait(false); + status.Status.Should().Be("No scenario found by name 'x'."); + } + + [Fact] + public async Task IWireMockAdminApi_DeleteScenarioUsingPostAsync() + { + // Arrange + var name = "x"; + var server = WireMockServer.StartWithAdminInterface(); + var api = RestClient.For(server.Urls[0]); + + // Act + var status = await api.ResetScenarioAsync(name).ConfigureAwait(false); + status.Status.Should().Be("No scenario found by name 'x'."); + } } #endif \ No newline at end of file diff --git a/test/WireMock.Net.Tests/WireMockServer.Proxy.cs b/test/WireMock.Net.Tests/WireMockServer.Proxy.cs index aa2a03a7..430a9b44 100644 --- a/test/WireMock.Net.Tests/WireMockServer.Proxy.cs +++ b/test/WireMock.Net.Tests/WireMockServer.Proxy.cs @@ -117,7 +117,7 @@ public class WireMockServerProxyTests } // Assert - server.Mappings.Should().HaveCount(28); + server.Mappings.Should().HaveCount(30); } [Fact] diff --git a/test/WireMock.Net.Tests/WireMockServer.Settings.cs b/test/WireMock.Net.Tests/WireMockServer.Settings.cs index 07337ac4..fe1d13dc 100644 --- a/test/WireMock.Net.Tests/WireMockServer.Settings.cs +++ b/test/WireMock.Net.Tests/WireMockServer.Settings.cs @@ -81,7 +81,7 @@ namespace WireMock.Net.Tests // Assert server.Mappings.Should().NotBeNull(); - server.Mappings.Should().HaveCount(26); + server.Mappings.Should().HaveCount(28); server.Mappings.All(m => m.Priority == WireMockConstants.AdminPriority).Should().BeTrue(); } @@ -100,9 +100,9 @@ namespace WireMock.Net.Tests // Assert server.Mappings.Should().NotBeNull(); - server.Mappings.Should().HaveCount(27); + server.Mappings.Should().HaveCount(29); - server.Mappings.Count(m => m.Priority == WireMockConstants.AdminPriority).Should().Be(26); + server.Mappings.Count(m => m.Priority == WireMockConstants.AdminPriority).Should().Be(28); server.Mappings.Count(m => m.Priority == WireMockConstants.ProxyPriority).Should().Be(1); }