diff --git a/src/WireMock.Net/ResponseBuilders/Response.WithBody.cs b/src/WireMock.Net/ResponseBuilders/Response.WithBody.cs index 4d558889..14956902 100644 --- a/src/WireMock.Net/ResponseBuilders/Response.WithBody.cs +++ b/src/WireMock.Net/ResponseBuilders/Response.WithBody.cs @@ -13,6 +13,8 @@ namespace WireMock.ResponseBuilders; public partial class Response { + private bool _bodyFromFileSet; + /// public IResponseBuilder WithBody(Func bodyFactory, string? destination = BodyDestinationFormat.SameAsSource, Encoding? encoding = null) { @@ -78,6 +80,8 @@ public partial class Response { Guard.NotNull(filename); + _bodyFromFileSet = true; + ResponseMessage.BodyData = new BodyData { BodyAsFileIsCached = cache, diff --git a/src/WireMock.Net/ResponseBuilders/Response.WithTransformer.cs b/src/WireMock.Net/ResponseBuilders/Response.WithTransformer.cs new file mode 100644 index 00000000..0b2fc062 --- /dev/null +++ b/src/WireMock.Net/ResponseBuilders/Response.WithTransformer.cs @@ -0,0 +1,36 @@ +// Copyright © WireMock.Net + +using System; +using WireMock.Types; + +namespace WireMock.ResponseBuilders; + +public partial class Response +{ + /// + public IResponseBuilder WithTransformer(bool transformContentFromBodyAsFile) + { + return WithTransformer(TransformerType.Handlebars, transformContentFromBodyAsFile); + } + + /// + public IResponseBuilder WithTransformer(ReplaceNodeOptions options) + { + return WithTransformer(TransformerType.Handlebars, false, options); + } + + /// + public IResponseBuilder WithTransformer(TransformerType transformerType, bool transformContentFromBodyAsFile = false, ReplaceNodeOptions options = ReplaceNodeOptions.EvaluateAndTryToConvert) + { + if (_bodyFromFileSet) + { + throw new InvalidOperationException("WithTransformer should be used before WithBodyFromFile."); + } + + UseTransformer = true; + TransformerType = transformerType; + UseTransformerForBodyAsFile = transformContentFromBodyAsFile; + TransformerReplaceNodeOptions = options; + return this; + } +} \ No newline at end of file diff --git a/src/WireMock.Net/ResponseBuilders/Response.cs b/src/WireMock.Net/ResponseBuilders/Response.cs index e9e7537f..017f38e9 100644 --- a/src/WireMock.Net/ResponseBuilders/Response.cs +++ b/src/WireMock.Net/ResponseBuilders/Response.cs @@ -164,28 +164,6 @@ public partial class Response : IResponseBuilder return WithStatusCode((int)HttpStatusCode.NotFound); } - /// - public IResponseBuilder WithTransformer(bool transformContentFromBodyAsFile) - { - return WithTransformer(TransformerType.Handlebars, transformContentFromBodyAsFile); - } - - /// - public IResponseBuilder WithTransformer(ReplaceNodeOptions options) - { - return WithTransformer(TransformerType.Handlebars, false, options); - } - - /// - public IResponseBuilder WithTransformer(TransformerType transformerType, bool transformContentFromBodyAsFile = false, ReplaceNodeOptions options = ReplaceNodeOptions.EvaluateAndTryToConvert) - { - UseTransformer = true; - TransformerType = transformerType; - UseTransformerForBodyAsFile = transformContentFromBodyAsFile; - TransformerReplaceNodeOptions = options; - return this; - } - /// public IResponseBuilder WithDelay(TimeSpan delay) { @@ -286,7 +264,7 @@ public partial class Response : IResponseBuilder if (UseTransformer) { - // Check if the body matcher is a RequestMessageProtoBufMatcher and try to to decode the byte-array to a BodyAsJson. + // Check if the body matcher is a RequestMessageProtoBufMatcher and try to decode the byte-array to a BodyAsJson. if (mapping.RequestMatcher is Request requestMatcher && requestMessage is RequestMessage request) { var protoBufMatcher = requestMatcher.GetRequestMessageMatcher()?.Matcher; diff --git a/src/WireMock.Net/Transformers/Transformer.cs b/src/WireMock.Net/Transformers/Transformer.cs index 0e87813c..fb993f53 100644 --- a/src/WireMock.Net/Transformers/Transformer.cs +++ b/src/WireMock.Net/Transformers/Transformer.cs @@ -198,7 +198,7 @@ internal class Transformer : ITransformer private JToken ReplaceSingleNode(ITransformerContext transformerContext, ReplaceNodeOptions options, string stringValue, object model) { - string transformedString = transformerContext.ParseAndRender(stringValue, model); + var transformedString = transformerContext.ParseAndRender(stringValue, model); if (!string.Equals(stringValue, transformedString)) { @@ -346,7 +346,7 @@ internal class Transformer : ITransformer private static IBodyData TransformBodyAsFile(ITransformerContext transformerContext, object model, IBodyData original, bool useTransformerForBodyAsFile) { - string transformedBodyAsFilename = transformerContext.ParseAndRender(original.BodyAsFile!, model); + var transformedBodyAsFilename = transformerContext.ParseAndRender(original.BodyAsFile!, model); if (!useTransformerForBodyAsFile) { @@ -358,7 +358,7 @@ internal class Transformer : ITransformer }; } - string text = transformerContext.FileSystemHandler.ReadResponseBodyAsString(transformedBodyAsFilename); + var text = transformerContext.FileSystemHandler.ReadResponseBodyAsString(transformedBodyAsFilename); return new BodyData { DetectedBodyType = BodyType.String, diff --git a/test/WireMock.Net.Tests/ResponseBuilders/ResponseWithTransformerTests.cs b/test/WireMock.Net.Tests/ResponseBuilders/ResponseWithTransformerTests.cs index ae205fe8..278d4615 100644 --- a/test/WireMock.Net.Tests/ResponseBuilders/ResponseWithTransformerTests.cs +++ b/test/WireMock.Net.Tests/ResponseBuilders/ResponseWithTransformerTests.cs @@ -602,22 +602,21 @@ public class ResponseWithTransformerTests Check.That(response.Message.BodyData!.BodyAsFile).Equals(@"c:\1\test.xml"); } - [Theory] - [InlineData(TransformerType.Handlebars)] - //[InlineData(TransformerType.Scriban)] ["c:\\["1"]\\test.xml"] - //[InlineData(TransformerType.ScribanDotLiquid)] - public async Task Response_ProvideResponse_Transformer_WithBodyAsFile_And_TransformContentFromBodyAsFile(TransformerType transformerType) + [Fact] + public async Task Response_ProvideResponse_Transformer_WithBodyAsFile_And_TransformContentFromBodyAsFile() { // Assign var filesystemHandlerMock = new Mock(MockBehavior.Strict); - filesystemHandlerMock.Setup(fs => fs.ReadResponseBodyAsString(It.IsAny())).Returns(""); + filesystemHandlerMock + .Setup(fs => fs.ReadResponseBodyAsString(It.IsAny())) + .Returns(""); _settings.FileSystemHandler = filesystemHandlerMock.Object; var request = new RequestMessage(new UrlDetails("http://localhost/foo?MyUniqueNumber=1"), "GET", ClientIp); var responseBuilder = Response.Create() - .WithTransformer(transformerType, true) + .WithTransformer(transformContentFromBodyAsFile: true) .WithBodyFromFile(@"c:\\{{request.query.MyUniqueNumber}}\\test.xml"); // Act diff --git a/test/WireMock.Net.Tests/WireMockServerTests.WithTransformer.cs b/test/WireMock.Net.Tests/WireMockServerTests.WithTransformer.cs new file mode 100644 index 00000000..22e94056 --- /dev/null +++ b/test/WireMock.Net.Tests/WireMockServerTests.WithTransformer.cs @@ -0,0 +1,98 @@ +// Copyright © WireMock.Net + +using System; +using System.IO; +using System.Net.Http; +using System.Threading.Tasks; +using FluentAssertions; +using WireMock.RequestBuilders; +using WireMock.ResponseBuilders; +using WireMock.Server; +using Xunit; + +namespace WireMock.Net.Tests; + +public partial class WireMockServerTests +{ + private const string RequestXml = + """ + + + + """; + + private readonly string _responseFilePath = Path.Combine(Environment.CurrentDirectory, "__admin", "mappings", "responseWithTransformer.xml"); + + [Fact] + public async Task WireMockServer_WithTransformer_WithBody_ShouldWork() + { + // Arrange + using var server = WireMockServer.Start(); + server + .WhenRequest(req => req + .WithPath("/withbody") + .UsingPost()) + .ThenRespondWith(rsp => rsp + .WithSuccess() + .WithBody(File.ReadAllText(_responseFilePath)) + .WithTransformer()); + + // Act + var response = await GetResponseAsync(server, "/withbody"); + + // Assert + response.Should().Contain("Hello, Stef!"); + } + + [Fact] + public async Task WireMockServer_WithTransformerBefore_WithBodyFromFile_ShouldWork() + { + // Arrange + using var server = WireMockServer.Start(); + server + .WhenRequest(req => req + .WithPath("/withbodyfromfile") + .UsingPost()) + .ThenRespondWith(rsp => rsp + .WithSuccess() + .WithTransformer(transformContentFromBodyAsFile: true) + .WithBodyFromFile(_responseFilePath)); + + // Act + var response = await GetResponseAsync(server, "/withbodyfromfile"); + + // Assert + response.Should().Contain("Hello, Stef!"); + } + + [Fact] + public void WireMockServer_WithTransformerAfter_WithBodyFromFile_ShouldThrow() + { + // Act + var act = () => + { + using var server = WireMockServer.Start(); + server + .WhenRequest(req => req + .WithPath("/") + .UsingPost()) + .ThenRespondWith(rsp => rsp + .WithSuccess() + .WithBodyFromFile(_responseFilePath) + .WithTransformer(transformContentFromBodyAsFile: true)); + }; + + // Assert + act.Should().Throw().WithMessage("WithTransformer should be used before WithBodyFromFile."); + } + + private static async Task GetResponseAsync(WireMockServer server, string relativePath) + { + using HttpClient httpClient = new HttpClient(); + httpClient.BaseAddress = new Uri(server.Urls[0]); + + using var requestContent = new StringContent(RequestXml); + using var responseMsg = await httpClient.PostAsync(relativePath, requestContent); + return await responseMsg.Content.ReadAsStringAsync(); + } +} \ No newline at end of file diff --git a/test/WireMock.Net.Tests/__admin/mappings/responseWithTransformer.xml b/test/WireMock.Net.Tests/__admin/mappings/responseWithTransformer.xml new file mode 100644 index 00000000..f7b3846b --- /dev/null +++ b/test/WireMock.Net.Tests/__admin/mappings/responseWithTransformer.xml @@ -0,0 +1,3 @@ + + Hello, {{XPath.Evaluate request.body "//*[local-name()='Contact']/@FirstName"}}! +