Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FindRequestByMappingGuidAsync #1043

Merged
merged 3 commits into from
Dec 21, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/WireMock.Net.Abstractions/Admin/Requests/LogEntryModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,12 @@ public class LogEntryModel
/// <summary>
/// The request.
/// </summary>
public LogRequestModel Request { get; set; }
public required LogRequestModel Request { get; init; }

/// <summary>
/// The response.
/// </summary>
public LogResponseModel Response { get; set; }
public required LogResponseModel Response { get; init; }

/// <summary>
/// The mapping unique identifier.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,11 @@
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>

<PackageReference Include="PolySharp" Version="1.14.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>

<ItemGroup Condition="$(TargetFramework.StartsWith('netstandard')) and '$(TargetFramework)' != 'netstandard1.0'">
Expand Down
12 changes: 10 additions & 2 deletions src/WireMock.Net.RestClient/IWireMockAdminApi.cs
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ public interface IWireMockAdminApi
/// Get a request based on the guid
/// </summary>
/// <param name="guid">The Guid</param>
/// <returns>MappingModel</returns>
/// <returns>LogEntryModel</returns>
/// <param name="cancellationToken">The optional cancellationToken.</param>
[Get("requests/{guid}")]
Task<LogEntryModel> GetRequestAsync([Path] Guid guid, CancellationToken cancellationToken = default);
Expand All @@ -192,14 +192,22 @@ public interface IWireMockAdminApi
Task<StatusModel> DeleteRequestAsync([Path] Guid guid, CancellationToken cancellationToken = default);

/// <summary>
/// Find a request based on the criteria
/// Find requests based on the criteria (<see cref="RequestModel"/>)
/// </summary>
/// <param name="model">The RequestModel</param>
/// <param name="cancellationToken">The optional cancellationToken.</param>
[Post("requests/find")]
[Header("Content-Type", "application/json")]
Task<IList<LogEntryModel>> FindRequestsAsync([Body] RequestModel model, CancellationToken cancellationToken = default);

/// <summary>
/// Find a request based on the Mapping Guid.
/// </summary>
/// <param name="mappingGuid">The Mapping Guid</param>
/// <param name="cancellationToken">The optional cancellationToken.</param>
[Get("requests/find")]
Task<LogEntryModel?> FindRequestByMappingGuidAsync([Query] Guid mappingGuid, CancellationToken cancellationToken = default);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should probably be FindRequestsByMappingGuidAsync, and return a collection


/// <summary>
/// Get all scenarios
/// </summary>
Expand Down
25 changes: 23 additions & 2 deletions src/WireMock.Net/Server/WireMockServer.Admin.cs
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ private void InitAdmin()

// __admin/requests/find
Given(Request.Create().WithPath(AdminRequests + "/find").UsingPost()).AtPriority(WireMockConstants.AdminPriority).RespondWith(new DynamicResponseProvider(RequestsFind));
Given(Request.Create().WithPath(AdminRequests + "/find").UsingGet().WithParam("mappingGuid", new NotNullOrEmptyMatcher())).AtPriority(WireMockConstants.AdminPriority).RespondWith(new DynamicResponseProvider(RequestFindByMappingGuid));

// __admin/scenarios
Given(Request.Create().WithPath(AdminScenarios).UsingGet()).AtPriority(WireMockConstants.AdminPriority).RespondWith(new DynamicResponseProvider(ScenariosGet));
Expand Down Expand Up @@ -436,7 +437,7 @@ private IResponseMessage MappingsPost(IRequestMessage requestMessage)
var mappingModels = DeserializeRequestMessageToArray<MappingModel>(requestMessage);
if (mappingModels.Length == 1)
{
Guid? guid = ConvertMappingAndRegisterAsRespondProvider(mappingModels[0]);
var guid = ConvertMappingAndRegisterAsRespondProvider(mappingModels[0]);
return ResponseMessageBuilder.Create(201, "Mapping added", guid);
}

Expand Down Expand Up @@ -535,7 +536,7 @@ private IResponseMessage RequestGet(IRequestMessage requestMessage)
{
if (TryParseGuidFromRequestMessage(requestMessage, out var guid))
{
var entry = LogEntries.FirstOrDefault(r => !r.RequestMessage.Path.StartsWith("/__admin/") && r.Guid == guid);
var entry = LogEntries.SingleOrDefault(r => !r.RequestMessage.Path.StartsWith("/__admin/") && r.Guid == guid);
if (entry is { })
{
var model = new LogEntryMapper(_options).Map(entry);
Expand Down Expand Up @@ -600,6 +601,26 @@ private IResponseMessage RequestsFind(IRequestMessage requestMessage)

return ToJson(result);
}

private IResponseMessage RequestFindByMappingGuid(IRequestMessage requestMessage)
{
if (requestMessage.Query != null &&
requestMessage.Query.TryGetValue("mappingGuid", out var value) &&
Guid.TryParse(value.ToString(), out var mappingGuid)
)
{
var logEntry = LogEntries.SingleOrDefault(le => !le.RequestMessage.Path.StartsWith("/__admin/") && le.MappingGuid == mappingGuid);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There could be more than one matching request, and in this case SingleOrDefault will throw.

if (logEntry != null)
{
var logEntryMapper = new LogEntryMapper(_options);
return ToJson(logEntryMapper.Map(logEntry));
}

return ResponseMessageBuilder.Create(HttpStatusCode.OK);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Returning 200 with an empty response is probably not what the client would expect. If the status code is 200, the client will expect the body to contain a LogEntryModel.

But anyway, I think this endpoint should return a collection (which will be empty if no match is found)

}

return ResponseMessageBuilder.Create(HttpStatusCode.BadRequest);
}
#endregion Requests/find

#region Scenarios
Expand Down
7 changes: 0 additions & 7 deletions src/WireMock.Net/WireMock.Net.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -72,13 +72,6 @@
<PackageReference Include="TinyMapper" Version="3.0.3" />
</ItemGroup>

<ItemGroup Condition="'$(Configuration)' == 'Debug - Sonar'">
<PackageReference Include="SonarAnalyzer.CSharp" Version="7.8.0.7320">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
</ItemGroup>

<ItemGroup Condition=" '$(TargetFramework)' != 'netstandard1.3' ">
<PackageReference Include="XPath2.Extensions" Version="1.1.4" />
<PackageReference Include="Microsoft.IdentityModel.Protocols.OpenIdConnect" Version="6.12.2" />
Expand Down
87 changes: 81 additions & 6 deletions test/WireMock.Net.Tests/WireMockAdminApiTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,10 @@ public async Task IWireMockAdminApi_FindRequestsAsync()
StartAdminInterface = true,
Logger = new WireMockNullLogger()
});
server
.Given(Request.Create().WithPath("/foo").UsingGet())
.RespondWith(Response.Create());

var serverUrl = "http://localhost:" + server.Ports[0];
await new HttpClient().GetAsync(serverUrl + "/foo").ConfigureAwait(false);
var api = RestClient.For<IWireMockAdminApi>(serverUrl);
Expand All @@ -242,11 +246,82 @@ public async Task IWireMockAdminApi_FindRequestsAsync()
var requests = await api.FindRequestsAsync(new RequestModel { Methods = new[] { "GET" } }).ConfigureAwait(false);

// Assert
Check.That(requests).HasSize(1);
requests.Should().HaveCount(1);
var requestLogged = requests.First();
Check.That(requestLogged.Request.Method).IsEqualTo("GET");
Check.That(requestLogged.Request.Body).IsNull();
Check.That(requestLogged.Request.Path).IsEqualTo("/foo");
requestLogged.Request.Method.Should().Be("GET");
requestLogged.Request.Body.Should().BeNull();
requestLogged.Request.Path.Should().Be("/foo");
}

[Fact]
public async Task IWireMockAdminApi_FindRequestByMappingGuidAsync_Found()
{
// Arrange
var mappingGuid = Guid.NewGuid();
var server = WireMockServer.Start(new WireMockServerSettings
{
StartAdminInterface = true,
Logger = new WireMockNullLogger()
});
server
.Given(Request.Create().WithPath("/foo").UsingGet())
.WithGuid(mappingGuid)
.RespondWith(Response.Create());

var serverUrl = "http://localhost:" + server.Ports[0];
await new HttpClient().GetAsync(serverUrl + "/foo").ConfigureAwait(false);
var api = RestClient.For<IWireMockAdminApi>(serverUrl);

// Act
var logEntryModel = await api.FindRequestByMappingGuidAsync(mappingGuid).ConfigureAwait(false);

// Assert
logEntryModel.Should().NotBeNull();
logEntryModel!.Request.Method.Should().Be("GET");
logEntryModel!.Request.Body.Should().BeNull();
logEntryModel!.Request.Path.Should().Be("/foo");
}

[Fact]
public async Task IWireMockAdminApi_FindRequestByMappingGuidAsync_NotFound()
{
// Arrange
var server = WireMockServer.Start(new WireMockServerSettings
{
StartAdminInterface = true,
Logger = new WireMockNullLogger()
});
server
.Given(Request.Create().WithPath("/foo").UsingGet())
.WithGuid(Guid.NewGuid())
.RespondWith(Response.Create());

var serverUrl = "http://localhost:" + server.Ports[0];
await new HttpClient().GetAsync(serverUrl + "/foo").ConfigureAwait(false);
var api = RestClient.For<IWireMockAdminApi>(serverUrl);

// Act
var logEntryModel = await api.FindRequestByMappingGuidAsync(Guid.NewGuid()).ConfigureAwait(false);

// Assert
logEntryModel.Should().BeNull();
}

[Fact]
public async Task IWireMockAdminApi_FindRequestByMappingGuidAsync_Invalid_ShouldReturnBadRequest()
{
// Arrange
var server = WireMockServer.Start(new WireMockServerSettings
{
StartAdminInterface = true,
Logger = new WireMockNullLogger()
});

// Act
var result = await server.CreateClient().GetAsync("/__admin/requests/find?mappingGuid=x");

// Assert
result.StatusCode.Should().Be(HttpStatusCode.BadRequest);
}

[Fact]
Expand Down Expand Up @@ -815,7 +890,7 @@ public async Task IWireMockAdminApi_GetMappingsCode()
.RespondWith(
Response.Create()
.WithStatusCode(HttpStatusCode.AlreadyReported)
.WithBodyAsJson(new { @as = 1, b=1.2, d=true, e=false, f=new[]{1,2,3,4}, g= new{z1=1, z2=2, z3=new []{"a","b","c"}, z4=new[]{new {a=1, b=2},new {a=2, b=3}}}, date_field = new DateTime(2023,05,08,11,20,19), string_field_with_date="2021-03-13T21:04:00Z", multiline_text= @"This
.WithBodyAsJson(new { @as = 1, b = 1.2, d = true, e = false, f = new[] { 1, 2, 3, 4 }, g = new { z1 = 1, z2 = 2, z3 = new[] { "a", "b", "c" }, z4 = new[] { new { a = 1, b = 2 }, new { a = 2, b = 3 } } }, date_field = new DateTime(2023, 05, 08, 11, 20, 19), string_field_with_date = "2021-03-13T21:04:00Z", multiline_text = @"This
is
multiline
text
Expand All @@ -826,7 +901,7 @@ public async Task IWireMockAdminApi_GetMappingsCode()
.Given(
Request.Create()
.WithPath("/foo3")
.WithBody(new JsonPartialMatcher(new { a=1, b=2}))
.WithBody(new JsonPartialMatcher(new { a = 1, b = 2 }))
.UsingPost()
)
.WithGuid(guid4)
Expand Down
2 changes: 1 addition & 1 deletion test/WireMock.Net.Tests/WireMockServer.Proxy.cs
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ public async Task WireMockServer_Proxy_AdminTrue_With_SaveMapping_Is_True_And_Sa
}

// Assert
server.Mappings.Should().HaveCount(34);
server.Mappings.Should().HaveCount(35);
}

[Fact]
Expand Down
6 changes: 3 additions & 3 deletions test/WireMock.Net.Tests/WireMockServer.Settings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ public void WireMockServer_WireMockServerSettings_PriorityFromAllAdminMappingsIs

// Assert
server.Mappings.Should().NotBeNull();
server.Mappings.Should().HaveCount(32);
server.Mappings.Should().HaveCount(33);
server.Mappings.All(m => m.Priority == WireMockConstants.AdminPriority).Should().BeTrue();
}

Expand All @@ -100,9 +100,9 @@ public void WireMockServer_WireMockServerSettings_ProxyAndRecordSettings_ProxyPr

// Assert
server.Mappings.Should().NotBeNull();
server.Mappings.Should().HaveCount(33);
server.Mappings.Should().HaveCount(34);

server.Mappings.Count(m => m.Priority == WireMockConstants.AdminPriority).Should().Be(32);
server.Mappings.Count(m => m.Priority == WireMockConstants.AdminPriority).Should().Be(33);
server.Mappings.Count(m => m.Priority == WireMockConstants.ProxyPriority).Should().Be(1);
}

Expand Down
Loading