mirror of
https://github.com/wiremock/WireMock.Net.git
synced 2026-01-11 21:10:32 +01:00
Support deleting / resetting a single scenario (#834)
* Support deleting / resetting a single scenario * move files
This commit is contained in:
@@ -1,10 +1,18 @@
|
||||
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=AD/@EntryIndexedValue">AD</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=CONNECT/@EntryIndexedValue">CONNECT</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=CS/@EntryIndexedValue">CS</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=DELETE/@EntryIndexedValue">DELETE</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=EC/@EntryIndexedValue">EC</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=GET/@EntryIndexedValue">GET</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=HEAD/@EntryIndexedValue">HEAD</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=ID/@EntryIndexedValue">ID</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=IP/@EntryIndexedValue">IP</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=MD/@EntryIndexedValue">MD5</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=OPTIONS/@EntryIndexedValue">OPTIONS</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=PATCH/@EntryIndexedValue">PATCH</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=POST/@EntryIndexedValue">POST</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=PUT/@EntryIndexedValue">PUT</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=RSA/@EntryIndexedValue">RSA</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=SSL/@EntryIndexedValue">SSL</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=TE/@EntryIndexedValue">TE</s:String>
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
namespace WireMock.Http;
|
||||
namespace WireMock.Constants;
|
||||
|
||||
/// <summary>
|
||||
/// https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods
|
||||
/// </summary>
|
||||
internal static class HttpRequestMethods
|
||||
public static class HttpRequestMethod
|
||||
{
|
||||
public const string CONNECT = "CONNECT";
|
||||
public const string DELETE = "DELETE";
|
||||
@@ -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
|
||||
/// </summary>
|
||||
void ResetScenarios();
|
||||
|
||||
/// <summary>
|
||||
/// Resets a specific Scenario by the name.
|
||||
/// </summary>
|
||||
bool ResetScenario(string name);
|
||||
|
||||
/// <summary>
|
||||
/// Resets the LogEntries.
|
||||
/// </summary>
|
||||
|
||||
@@ -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<WireMockAssertions> UsingConnect(string because = "", params object[] becauseArgs)
|
||||
=> UsingMethod("CONNECT", because, becauseArgs);
|
||||
=> UsingMethod(HttpRequestMethod.CONNECT, because, becauseArgs);
|
||||
|
||||
[CustomAssertion]
|
||||
public AndConstraint<WireMockAssertions> UsingDelete(string because = "", params object[] becauseArgs)
|
||||
=> UsingMethod("DELETE", because, becauseArgs);
|
||||
=> UsingMethod(HttpRequestMethod.DELETE, because, becauseArgs);
|
||||
|
||||
[CustomAssertion]
|
||||
public AndConstraint<WireMockAssertions> UsingGet(string because = "", params object[] becauseArgs)
|
||||
=> UsingMethod("GET", because, becauseArgs);
|
||||
=> UsingMethod(HttpRequestMethod.GET, because, becauseArgs);
|
||||
|
||||
[CustomAssertion]
|
||||
public AndConstraint<WireMockAssertions> UsingHead(string because = "", params object[] becauseArgs)
|
||||
=> UsingMethod("HEAD", because, becauseArgs);
|
||||
=> UsingMethod(HttpRequestMethod.HEAD, because, becauseArgs);
|
||||
|
||||
[CustomAssertion]
|
||||
public AndConstraint<WireMockAssertions> UsingOptions(string because = "", params object[] becauseArgs)
|
||||
=> UsingMethod("OPTIONS", because, becauseArgs);
|
||||
=> UsingMethod(HttpRequestMethod.OPTIONS, because, becauseArgs);
|
||||
|
||||
[CustomAssertion]
|
||||
public AndConstraint<WireMockAssertions> UsingPost(string because = "", params object[] becauseArgs)
|
||||
=> UsingMethod("POST", because, becauseArgs);
|
||||
=> UsingMethod(HttpRequestMethod.POST, because, becauseArgs);
|
||||
|
||||
[CustomAssertion]
|
||||
public AndConstraint<WireMockAssertions> UsingPatch(string because = "", params object[] becauseArgs)
|
||||
=> UsingMethod("PATCH", because, becauseArgs);
|
||||
=> UsingMethod(HttpRequestMethod.PATCH, because, becauseArgs);
|
||||
|
||||
[CustomAssertion]
|
||||
public AndConstraint<WireMockAssertions> UsingPut(string because = "", params object[] becauseArgs)
|
||||
=> UsingMethod("PUT", because, becauseArgs);
|
||||
=> UsingMethod(HttpRequestMethod.PUT, because, becauseArgs);
|
||||
|
||||
[CustomAssertion]
|
||||
public AndConstraint<WireMockAssertions> UsingTrace(string because = "", params object[] becauseArgs)
|
||||
=> UsingMethod("TRACE", because, becauseArgs);
|
||||
=> UsingMethod(HttpRequestMethod.TRACE, because, becauseArgs);
|
||||
|
||||
[CustomAssertion]
|
||||
public AndConstraint<WireMockAssertions> UsingAnyMethod(string because = "", params object[] becauseArgs)
|
||||
|
||||
@@ -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<StatusModel> ResetScenariosAsync();
|
||||
|
||||
/// <summary>
|
||||
/// Delete (reset) a specific scenario
|
||||
/// </summary>
|
||||
[Delete("scenarios/{name}")]
|
||||
[AllowAnyStatusCode]
|
||||
Task<StatusModel> DeleteScenarioAsync([Path] string name);
|
||||
|
||||
/// <summary>
|
||||
/// Delete (reset) all scenarios
|
||||
/// </summary>
|
||||
[Post("scenarios/{name}/reset")]
|
||||
[AllowAnyStatusCode]
|
||||
Task<StatusModel> ResetScenarioAsync([Path] string name);
|
||||
|
||||
/// <summary>
|
||||
/// Create a new File
|
||||
/// </summary>
|
||||
|
||||
@@ -26,7 +26,7 @@ internal class WireMockMiddlewareOptions : IWireMockMiddlewareOptions
|
||||
|
||||
public ConcurrentDictionary<Guid, IMapping> Mappings { get; } = new ConcurrentDictionary<Guid, IMapping>();
|
||||
|
||||
public ConcurrentDictionary<string, ScenarioState> Scenarios { get; } = new();
|
||||
public ConcurrentDictionary<string, ScenarioState> Scenarios { get; } = new(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
public ConcurrentObservableCollection<LogEntry> LogEntries { get; } = new();
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
#pragma warning disable CS1591
|
||||
namespace WireMock.Pact.Models.V2;
|
||||
|
||||
public class Interaction
|
||||
|
||||
@@ -1,25 +1,25 @@
|
||||
namespace WireMock.Pact.Models.V2
|
||||
#pragma warning disable CS1591
|
||||
namespace WireMock.Pact.Models.V2;
|
||||
|
||||
public class MatchingRule
|
||||
{
|
||||
public class MatchingRule
|
||||
{
|
||||
/// <summary>
|
||||
/// type or regex
|
||||
/// </summary>
|
||||
public string Match { get; set; } = "type";
|
||||
/// <summary>
|
||||
/// type or regex
|
||||
/// </summary>
|
||||
public string Match { get; set; } = "type";
|
||||
|
||||
/// <summary>
|
||||
/// Used for Match = "type"
|
||||
/// </summary>
|
||||
public string Min { get; set; }
|
||||
/// <summary>
|
||||
/// Used for Match = "type"
|
||||
/// </summary>
|
||||
public string Min { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Used for Match = "type"
|
||||
/// </summary>
|
||||
public string Max { get; set; }
|
||||
/// <summary>
|
||||
/// Used for Match = "type"
|
||||
/// </summary>
|
||||
public string Max { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Used for Match = "regex"
|
||||
/// </summary>
|
||||
public string Regex { get; set; }
|
||||
}
|
||||
/// <summary>
|
||||
/// Used for Match = "regex"
|
||||
/// </summary>
|
||||
public string Regex { get; set; }
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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<Interaction> Interactions { get; set; } = new List<Interaction>();
|
||||
public List<Interaction> Interactions { get; set; } = new List<Interaction>();
|
||||
|
||||
public Metadata Metadata { get; set; }
|
||||
public Metadata Metadata { get; set; }
|
||||
|
||||
public Pacticipant Provider { get; set; }
|
||||
}
|
||||
public Pacticipant Provider { get; set; }
|
||||
}
|
||||
@@ -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<string, string>? Headers { get; set; }
|
||||
|
||||
public string Method { get; set; } = "GET";
|
||||
public string Method { get; set; } = HttpRequestMethod.GET;
|
||||
|
||||
public string? Path { get; set; } = "/";
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
#pragma warning disable CS1591
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace WireMock.Pact.Models.V2;
|
||||
|
||||
@@ -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; }
|
||||
}
|
||||
@@ -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";
|
||||
}
|
||||
@@ -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; }
|
||||
}
|
||||
@@ -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<string, string> Params { get; set; }
|
||||
}
|
||||
public class ProviderState
|
||||
{
|
||||
public string Name { get; set; }
|
||||
|
||||
public IDictionary<string, string> Params { get; set; }
|
||||
}
|
||||
@@ -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<string>(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
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
/// <inheritdoc />
|
||||
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;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
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;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
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;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
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;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
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;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
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;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
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;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
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;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ public class ScenarioState
|
||||
/// <summary>
|
||||
/// Gets or sets the Name (from the Scenario).
|
||||
/// </summary>
|
||||
public string? Name { get; set; }
|
||||
public string Name { get; set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the NextState.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -477,6 +477,13 @@ public partial class WireMockServer : IWireMockServer
|
||||
_options.Scenarios.Clear();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
[PublicAPI]
|
||||
public bool ResetScenario(string name)
|
||||
{
|
||||
return _options.Scenarios.ContainsKey(name) && _options.Scenarios.TryRemove(name, out _);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IWireMockServer.WithMapping(MappingModel[])" />
|
||||
[PublicAPI]
|
||||
public IWireMockServer WithMapping(params MappingModel[] mappings)
|
||||
|
||||
@@ -10,7 +10,7 @@ interface ITransformer
|
||||
|
||||
IBodyData? TransformBody(IMapping mapping, IRequestMessage originalRequestMessage, IResponseMessage originalResponseMessage, IBodyData? bodyData, ReplaceNodeOptions options);
|
||||
|
||||
IDictionary<string, WireMockList<string>>? TransformHeaders(IMapping mapping, IRequestMessage originalRequestMessage, IResponseMessage originalResponseMessage, IDictionary<string, WireMockList<string>>? headers);
|
||||
IDictionary<string, WireMockList<string>> TransformHeaders(IMapping mapping, IRequestMessage originalRequestMessage, IResponseMessage originalResponseMessage, IDictionary<string, WireMockList<string>>? headers);
|
||||
|
||||
string TransformString(IMapping mapping, IRequestMessage originalRequestMessage, IResponseMessage originalResponseMessage, string? value);
|
||||
}
|
||||
@@ -36,7 +36,7 @@ internal class Transformer : ITransformer
|
||||
return newBodyData;
|
||||
}
|
||||
|
||||
public IDictionary<string, WireMockList<string>>? TransformHeaders(
|
||||
public IDictionary<string, WireMockList<string>> 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)
|
||||
{
|
||||
|
||||
@@ -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<string, bool> BodyAllowedForMethods = new Dictionary<string, bool>
|
||||
{
|
||||
{ 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);
|
||||
|
||||
@@ -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<IWireMockAdminApi>(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<IWireMockAdminApi>(server.Urls[0]);
|
||||
|
||||
// Act
|
||||
var status = await api.ResetScenarioAsync(name).ConfigureAwait(false);
|
||||
status.Status.Should().Be("No scenario found by name 'x'.");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -117,7 +117,7 @@ public class WireMockServerProxyTests
|
||||
}
|
||||
|
||||
// Assert
|
||||
server.Mappings.Should().HaveCount(28);
|
||||
server.Mappings.Should().HaveCount(30);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user