mirror of
https://github.com/wiremock/WireMock.Net.git
synced 2026-01-13 22:03:35 +01:00
Compare commits
33 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6aa7aac151 | ||
|
|
4688f556b5 | ||
|
|
a58ead7b4e | ||
|
|
58bfb3ea33 | ||
|
|
9c51548d2b | ||
|
|
98b8ede826 | ||
|
|
a6f3f976af | ||
|
|
b495eb83b1 | ||
|
|
9443e4f071 | ||
|
|
7a914481e5 | ||
|
|
1ad836659d | ||
|
|
ed7f9c1143 | ||
|
|
c92183558b | ||
|
|
8ce24249d0 | ||
|
|
7ca70309cb | ||
|
|
5d0bf6f4e1 | ||
|
|
f6e35cbe2d | ||
|
|
dc4c8d1dba | ||
|
|
adf1914877 | ||
|
|
1f1bc05f00 | ||
|
|
c107e38e3b | ||
|
|
a77c4fe1ac | ||
|
|
c1e71707c5 | ||
|
|
69499afe43 | ||
|
|
aadac78577 | ||
|
|
71393204cc | ||
|
|
e5cc6f570c | ||
|
|
7c3a0c815d | ||
|
|
e61f08fe48 | ||
|
|
11f4c47851 | ||
|
|
3956cd703b | ||
|
|
27682d0ce4 | ||
|
|
8444c8c506 |
53
CHANGELOG.md
53
CHANGELOG.md
@@ -1,3 +1,52 @@
|
||||
# 1.5.33 (03 August 2023)
|
||||
- [#972](https://github.com/WireMock-Net/WireMock.Net/pull/972) - JsonPartialMatcher - match guid and string contributed by [timurnes](https://github.com/timurnes)
|
||||
- [#976](https://github.com/WireMock-Net/WireMock.Net/pull/976) - Upgrade to Handlebars.Net.Helpers 2.4.0 to update XPath.SelectTokens and XPath.EvaluateToString [feature] contributed by [StefH](https://github.com/StefH)
|
||||
- [#981](https://github.com/WireMock-Net/WireMock.Net/pull/981) - Add MultiPart/MimePart Request Matcher [feature] contributed by [StefH](https://github.com/StefH)
|
||||
- [#968](https://github.com/WireMock-Net/WireMock.Net/issues/968) - Using request multipart in response template [feature]
|
||||
- [#969](https://github.com/WireMock-Net/WireMock.Net/issues/969) - Multipart validation [feature]
|
||||
- [#970](https://github.com/WireMock-Net/WireMock.Net/issues/970) - Loop through xml elements in handlebars template [feature]
|
||||
- [#971](https://github.com/WireMock-Net/WireMock.Net/issues/971) - JsonPartialMatcher - match guid and string [feature]
|
||||
|
||||
# 1.5.32 (15 July 2023)
|
||||
- [#966](https://github.com/WireMock-Net/WireMock.Net/pull/966) - Fixed JsonPathMatcher to match nested objects [bug] contributed by [StefH](https://github.com/StefH)
|
||||
- [#965](https://github.com/WireMock-Net/WireMock.Net/issues/965) - JsonPathMatcher does not match json body nested objects [bug]
|
||||
- [#967](https://github.com/WireMock-Net/WireMock.Net/issues/967) - ⭐10 million downloads ! ⭐ [feature]
|
||||
|
||||
# 1.5.31 (08 July 2023)
|
||||
- [#964](https://github.com/WireMock-Net/WireMock.Net/pull/964) - Add GraphQL Schema matching [feature] contributed by [StefH](https://github.com/StefH)
|
||||
|
||||
# 1.5.30 (28 June 2023)
|
||||
- [#959](https://github.com/WireMock-Net/WireMock.Net/pull/959) - Fixed logic for FluentAssertions WithHeader [bug] contributed by [StefH](https://github.com/StefH)
|
||||
- [#961](https://github.com/WireMock-Net/WireMock.Net/pull/961) - Add unit-test for Param MatcherModel LinqMatcher [test] contributed by [StefH](https://github.com/StefH)
|
||||
- [#962](https://github.com/WireMock-Net/WireMock.Net/pull/962) - Bump System.Linq.Dynamic.Core from 1.2.23 to 1.3.0 in /examples/WireMock.Net.Console.Net472.Classic [dependencies] contributed by [dependabot[bot]](https://github.com/apps/dependabot)
|
||||
- [#963](https://github.com/WireMock-Net/WireMock.Net/pull/963) - Bump System.Linq.Dynamic.Core from 1.2.23 to 1.3.0 in /examples/WireMock.Net.StandAlone.Net461 [dependencies] contributed by [dependabot[bot]](https://github.com/apps/dependabot)
|
||||
- [#958](https://github.com/WireMock-Net/WireMock.Net/issues/958) - [FluentAssertions] Should().HaveReceivedACall().WithHeader() only checks the first header with the matching key. [bug]
|
||||
|
||||
# 1.5.29 (22 June 2023)
|
||||
- [#954](https://github.com/WireMock-Net/WireMock.Net/pull/954) - Support setting WireMockServerSettings via Environment [feature] contributed by [StefH](https://github.com/StefH)
|
||||
- [#955](https://github.com/WireMock-Net/WireMock.Net/pull/955) - Fix some SonarCloud issues [refactor] contributed by [StefH](https://github.com/StefH)
|
||||
- [#953](https://github.com/WireMock-Net/WireMock.Net/issues/953) - How to use environment variable [feature]
|
||||
|
||||
# 1.5.28 (11 June 2023)
|
||||
- [#948](https://github.com/WireMock-Net/WireMock.Net/pull/948) - WireMock.Net.Testcontainers [feature] contributed by [StefH](https://github.com/StefH)
|
||||
- [#951](https://github.com/WireMock-Net/WireMock.Net/pull/951) - Allow setting the Content-Length header for a HTTP method HEAD [feature] contributed by [StefH](https://github.com/StefH)
|
||||
|
||||
# 1.5.27 (03 June 2023)
|
||||
- [#946](https://github.com/WireMock-Net/WireMock.Net/pull/946) - Add warning logging when sending a request to a Webhook does not return status 200 [feature] contributed by [StefH](https://github.com/StefH)
|
||||
- [#949](https://github.com/WireMock-Net/WireMock.Net/pull/949) - Add ".NET Framework 4.7" to WireMock.Net.FluentAssertions [feature] contributed by [StefH](https://github.com/StefH)
|
||||
- [#928](https://github.com/WireMock-Net/WireMock.Net/issues/928) - TypeLoadException when using WithHeader method. [bug]
|
||||
- [#945](https://github.com/WireMock-Net/WireMock.Net/issues/945) - Webhook logging [feature]
|
||||
|
||||
# 1.5.26 (25 May 2023)
|
||||
- [#938](https://github.com/WireMock-Net/WireMock.Net/pull/938) - Add more unitests for CSharpFormatter utils [test] contributed by [StefH](https://github.com/StefH)
|
||||
- [#939](https://github.com/WireMock-Net/WireMock.Net/pull/939) - WireMockMiddleware should use HandleRequestsSynchronously correctly [bug] contributed by [StefH](https://github.com/StefH)
|
||||
- [#940](https://github.com/WireMock-Net/WireMock.Net/pull/940) - Code generator improvements contributed by [cezarypiatek](https://github.com/cezarypiatek)
|
||||
- [#942](https://github.com/WireMock-Net/WireMock.Net/pull/942) - Add GetParameter method to IRequestMessage [feature] contributed by [StefH](https://github.com/StefH)
|
||||
- [#941](https://github.com/WireMock-Net/WireMock.Net/issues/941) - RequestMessage.GetParameter method missing from IRequestMessage interface [feature]
|
||||
|
||||
# 1.5.25 (13 May 2023)
|
||||
- [#934](https://github.com/WireMock-Net/WireMock.Net/pull/934) - Code generator improvements [feature] contributed by [cezarypiatek](https://github.com/cezarypiatek)
|
||||
|
||||
# 1.5.24 (07 May 2023)
|
||||
- [#926](https://github.com/WireMock-Net/WireMock.Net/pull/926) - Fix C# mapping code generator for header names [bug] contributed by [cezarypiatek](https://github.com/cezarypiatek)
|
||||
- [#927](https://github.com/WireMock-Net/WireMock.Net/pull/927) - Enrich generated code with status code [feature] contributed by [cezarypiatek](https://github.com/cezarypiatek)
|
||||
@@ -930,7 +979,7 @@
|
||||
- [#86](https://github.com/WireMock-Net/WireMock.Net/issues/86) - Feature : Add FileSystemWatcher logic for watching static mapping files [feature]
|
||||
|
||||
# 1.0.2.13 (23 January 2018)
|
||||
- [#79](https://github.com/WireMock-Net/WireMock.Net/pull/79) - Fix missed content headers contributed by [vladimir-fed](https://github.com/vladimir-fed)
|
||||
- [#79](https://github.com/WireMock-Net/WireMock.Net/pull/79) - Fix missed content headers contributed by [volodymyr-fed](https://github.com/volodymyr-fed)
|
||||
- [#57](https://github.com/WireMock-Net/WireMock.Net/issues/57) - ProxyAndRecord does not save query-parameters, headers and body [bug]
|
||||
- [#78](https://github.com/WireMock-Net/WireMock.Net/issues/78) - WireMock not working when attempting to access from anything other than localhost.
|
||||
|
||||
@@ -957,7 +1006,7 @@
|
||||
|
||||
# 1.0.2.7 (18 November 2017)
|
||||
- [#62](https://github.com/WireMock-Net/WireMock.Net/pull/62) - Add the Host, Protocol, Port and Origin to the Request message so they can be used in templating contributed by [alastairtree](https://github.com/alastairtree)
|
||||
- [#63](https://github.com/WireMock-Net/WireMock.Net/pull/63) - Fix issue with concurrent logging contributed by [vladimir-fed](https://github.com/vladimir-fed)
|
||||
- [#63](https://github.com/WireMock-Net/WireMock.Net/pull/63) - Fix issue with concurrent logging contributed by [volodymyr-fed](https://github.com/volodymyr-fed)
|
||||
- [#27](https://github.com/WireMock-Net/WireMock.Net/issues/27) - New feature: Record and Save
|
||||
- [#42](https://github.com/WireMock-Net/WireMock.Net/issues/42) - Enhancement - Save/load request logs to/from disk [feature]
|
||||
- [#53](https://github.com/WireMock-Net/WireMock.Net/issues/53) - New feature request: Access to Owin pipeline
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<VersionPrefix>1.5.24</VersionPrefix>
|
||||
<VersionPrefix>1.5.33</VersionPrefix>
|
||||
<PackageIcon>WireMock.Net-Logo.png</PackageIcon>
|
||||
<PackageProjectUrl>https://github.com/WireMock-Net/WireMock.Net</PackageProjectUrl>
|
||||
<PackageLicenseExpression>Apache-2.0</PackageLicenseExpression>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
rem https://github.com/StefH/GitHubReleaseNotes
|
||||
|
||||
SET version=1.5.24
|
||||
SET version=1.5.33
|
||||
|
||||
GitHubReleaseNotes --output CHANGELOG.md --skip-empty-releases --exclude-labels question invalid doc duplicate --version %version% --token %GH_TOKEN%
|
||||
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
# 1.5.24 (07 May 2023)
|
||||
- #926 Fix C# mapping code generator for header names [bug]
|
||||
- #927 Enrich generated code with status code [feature]
|
||||
- #930 Update C# mapping code generator for WithStatusCode [feature]
|
||||
- #931 Add property 'IsStartedWithAdminInterface' to 'IWireMockServer' [feature]
|
||||
- #933 C# code generator improvements [feature]
|
||||
# 1.5.33 (03 August 2023)
|
||||
- #972 JsonPartialMatcher - match guid and string
|
||||
- #976 Upgrade to Handlebars.Net.Helpers 2.4.0 to update XPath.SelectTokens and XPath.EvaluateToString [feature]
|
||||
- #981 Add MultiPart/MimePart Request Matcher [feature]
|
||||
- #968 Using request multipart in response template [feature]
|
||||
- #969 Multipart validation [feature]
|
||||
- #970 Loop through xml elements in handlebars template [feature]
|
||||
- #971 JsonPartialMatcher - match guid and string [feature]
|
||||
|
||||
The full release notes can be found here: https://github.com/WireMock-Net/WireMock.Net/blob/master/CHANGELOG.md
|
||||
@@ -22,7 +22,7 @@ For more info, see also this WIKI page: [What is WireMock.Net](https://github.co
|
||||
| | |
|
||||
| --- | --- |
|
||||
| ***Project*** | |
|
||||
| **Chat** | [](https://gitter.im/wiremock_dotnet/Lobby) |
|
||||
| **Chat** | [](https://slack.wiremock.org/) [](https://gitter.im/wiremock_dotnet/Lobby) |
|
||||
| **Issues** | [](https://github.com/WireMock-Net/WireMock.Net/issues) |
|
||||
| | |
|
||||
| ***Quality*** | |
|
||||
@@ -42,6 +42,7 @@ For more info, see also this WIKI page: [What is WireMock.Net](https://github.co
|
||||
| **WireMock.Net.OpenApiParser** | [](https://www.nuget.org/packages/WireMock.Net.OpenApiParser) | [](https://www.myget.org/feed/wiremock-net/package/nuget/WireMock.Net.OpenApiParser)
|
||||
| **WireMock.Net.RestClient** | [](https://www.nuget.org/packages/WireMock.Net.RestClient) | [](https://www.myget.org/feed/wiremock-net/package/nuget/WireMock.Net.RestClient)
|
||||
| **WireMock.Net.xUnit** | [](https://www.nuget.org/packages/WireMock.Net.xUnit) | [](https://www.myget.org/feed/wiremock-net/package/nuget/WireMock.Net.xUnit)
|
||||
| **WireMock.Net.Testcontainers** | [](https://www.nuget.org/packages/WireMock.Net.Testcontainers) | [](https://www.myget.org/feed/wiremock-net/package/nuget/WireMock.Net.Testcontainers)
|
||||
| **WireMock.Org.RestClient** | [](https://www.nuget.org/packages/WireMock.Org.RestClient) | [](https://www.myget.org/feed/wiremock-net/package/nuget/WireMock.Org.RestClient)
|
||||
|
||||
|
||||
@@ -68,13 +69,15 @@ WireMock.Net can be used in several ways:
|
||||
You can use your favorite test framework and use WireMock within your tests, see
|
||||
[Wiki : UnitTesting](https://github.com/StefH/WireMock.Net/wiki/Using-WireMock-in-UnitTests).
|
||||
|
||||
### Unit/Integration Testing using Testcontainers.DotNet
|
||||
You can use [Wiki : WireMock.Net.Testcontainers](https://github.com/WireMock-Net/WireMock.Net/wiki/Using-WireMock.Net.Testcontainers) to build a WireMock.Net Docker container which can be used in Unit/Integration testing.
|
||||
|
||||
### As a dotnet tool
|
||||
It's simple to install WireMock.Net as (global) dotnet tool, see [Wiki : dotnet tool](https://github.com/StefH/WireMock.Net/wiki/WireMock-as-dotnet-tool).
|
||||
|
||||
### As standalone process / console application
|
||||
This is quite straight forward to launch a mock server within a console application, see [Wiki : Standalone Process](https://github.com/StefH/WireMock.Net/wiki/WireMock-as-a-standalone-process).
|
||||
|
||||
|
||||
### As a Windows Service
|
||||
You can also run WireMock.Net as a Windows Service, follow this [WireMock-as-a-Windows-Service](https://github.com/WireMock-Net/WireMock.Net/wiki/WireMock-as-a-Windows-Service).
|
||||
|
||||
|
||||
@@ -111,6 +111,14 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WireMockAzureQueueExample",
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WireMockAzureQueueProxy", "examples\WireMockAzureQueueProxy\WireMockAzureQueueProxy.csproj", "{ADB557D8-D66B-4387-912B-3F73E290B478}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WireMock.Net.Testcontainers", "src\WireMock.Net.Testcontainers\WireMock.Net.Testcontainers.csproj", "{12B016A5-9D8B-4EFE-96C2-CA51BE43367D}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WireMock.Net.TestcontainersExample", "examples\WireMock.Net.TestcontainersExample\WireMock.Net.TestcontainersExample.csproj", "{56A38798-C48B-4A4A-B805-071E05C02CE1}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tools", "tools", "{0147029F-FA4A-44B3-B79A-3C3574054EE4}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MultipartUploader", "tools\MultipartUploader\MultipartUploader.csproj", "{07C30227-ADEC-4BDE-8CDC-849D85A690BB}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
@@ -265,6 +273,18 @@ Global
|
||||
{ADB557D8-D66B-4387-912B-3F73E290B478}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{ADB557D8-D66B-4387-912B-3F73E290B478}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{ADB557D8-D66B-4387-912B-3F73E290B478}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{12B016A5-9D8B-4EFE-96C2-CA51BE43367D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{12B016A5-9D8B-4EFE-96C2-CA51BE43367D}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{12B016A5-9D8B-4EFE-96C2-CA51BE43367D}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{12B016A5-9D8B-4EFE-96C2-CA51BE43367D}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{56A38798-C48B-4A4A-B805-071E05C02CE1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{56A38798-C48B-4A4A-B805-071E05C02CE1}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{56A38798-C48B-4A4A-B805-071E05C02CE1}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{56A38798-C48B-4A4A-B805-071E05C02CE1}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{07C30227-ADEC-4BDE-8CDC-849D85A690BB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{07C30227-ADEC-4BDE-8CDC-849D85A690BB}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{07C30227-ADEC-4BDE-8CDC-849D85A690BB}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{07C30227-ADEC-4BDE-8CDC-849D85A690BB}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
@@ -309,6 +329,9 @@ Global
|
||||
{7C2A9DE8-C89F-4841-9058-6B9BF81E5E34} = {985E0ADB-D4B4-473A-AA40-567E279B7946}
|
||||
{BAA9EC2A-874B-45CE-8E51-A73622DC7F3D} = {985E0ADB-D4B4-473A-AA40-567E279B7946}
|
||||
{ADB557D8-D66B-4387-912B-3F73E290B478} = {985E0ADB-D4B4-473A-AA40-567E279B7946}
|
||||
{12B016A5-9D8B-4EFE-96C2-CA51BE43367D} = {8F890C6F-9ACC-438D-928A-AD61CDA862F2}
|
||||
{56A38798-C48B-4A4A-B805-071E05C02CE1} = {985E0ADB-D4B4-473A-AA40-567E279B7946}
|
||||
{07C30227-ADEC-4BDE-8CDC-849D85A690BB} = {0147029F-FA4A-44B3-B79A-3C3574054EE4}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {DC539027-9852-430C-B19F-FD035D018458}
|
||||
|
||||
@@ -10,9 +10,11 @@
|
||||
<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/=OS/@EntryIndexedValue">OS</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/=QL/@EntryIndexedValue">QL</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>
|
||||
@@ -32,6 +34,7 @@
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Raml/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=randomizer/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Scriban/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=sheyenrath/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Sigil/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Stef/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=templated/@EntryIndexedValue">True</s:Boolean>
|
||||
|
||||
@@ -73,7 +73,6 @@ class Program
|
||||
|
||||
var settingsViaBuilder = new SettingsModelBuilder()
|
||||
.WithGlobalProcessingDelay(1077)
|
||||
.WithoutGlobalProcessingDelay()
|
||||
.Build();
|
||||
|
||||
settings1.GlobalProcessingDelay = 1077;
|
||||
|
||||
@@ -28,10 +28,10 @@
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\src\WireMock.Net\WireMock.Net.csproj" />
|
||||
<PackageReference Include="Handlebars.Net.Helpers" Version="2.*" />
|
||||
<PackageReference Include="Handlebars.Net.Helpers" Version="2.4.0" />
|
||||
<PackageReference Include="log4net" Version="2.0.15" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration" Version="5.0.0" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<DefineConstants>$(DefineConstants);GRAPHQL;MIMEKIT</DefineConstants>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
@@ -27,10 +28,9 @@
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\src\WireMock.Net\WireMock.Net.csproj" />
|
||||
<!--<PackageReference Include="Handlebars.Net.Helpers" Version="2.*" />-->
|
||||
<PackageReference Include="log4net" Version="2.0.15" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration" Version="6.0.0" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
||||
<PackageReference Include="MimeKitLite" Version="4.1.0.1" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -19,14 +19,14 @@
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\src\WireMock.Net\WireMock.Net.csproj" />
|
||||
<PackageReference Include="Handlebars.Net.Helpers" Version="2.*" />
|
||||
<PackageReference Include="Handlebars.Net.Helpers.DynamicLinq" Version="2.*" />
|
||||
<PackageReference Include="Handlebars.Net.Helpers.Json" Version="2.3.*" />
|
||||
<PackageReference Include="Handlebars.Net.Helpers.XPath" Version="2.*" />
|
||||
<PackageReference Include="Handlebars.Net.Helpers.Xeger" Version="2.3.*" />
|
||||
<PackageReference Include="Handlebars.Net.Helpers.Random" Version="2.3.*" />
|
||||
<PackageReference Include="Handlebars.Net.Helpers" Version="2.4.0" />
|
||||
<PackageReference Include="Handlebars.Net.Helpers.DynamicLinq" Version="2.4.0" />
|
||||
<PackageReference Include="Handlebars.Net.Helpers.Json" Version="2.4.0" />
|
||||
<PackageReference Include="Handlebars.Net.Helpers.XPath" Version="2.4.0" />
|
||||
<PackageReference Include="Handlebars.Net.Helpers.Xeger" Version="2.4.0" />
|
||||
<PackageReference Include="Handlebars.Net.Helpers.Random" Version="2.4.0" />
|
||||
<PackageReference Include="log4net" Version="2.0.15" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -31,14 +31,14 @@
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\src\WireMock.Net\WireMock.Net.csproj" />
|
||||
<PackageReference Include="Handlebars.Net.Helpers" Version="2.*" />
|
||||
<PackageReference Include="Handlebars.Net.Helpers.DynamicLinq" Version="2.*" />
|
||||
<PackageReference Include="Handlebars.Net.Helpers.Json" Version="2.3.*" />
|
||||
<PackageReference Include="Handlebars.Net.Helpers.XPath" Version="2.*" />
|
||||
<PackageReference Include="Handlebars.Net.Helpers.Xeger" Version="2.3.*" />
|
||||
<PackageReference Include="Handlebars.Net.Helpers.Random" Version="2.3.*" />
|
||||
<PackageReference Include="Handlebars.Net.Helpers" Version="2.4.0" />
|
||||
<PackageReference Include="Handlebars.Net.Helpers.DynamicLinq" Version="2.4.0" />
|
||||
<PackageReference Include="Handlebars.Net.Helpers.Json" Version="2.4.0" />
|
||||
<PackageReference Include="Handlebars.Net.Helpers.XPath" Version="2.4.0" />
|
||||
<PackageReference Include="Handlebars.Net.Helpers.Xeger" Version="2.4.0" />
|
||||
<PackageReference Include="Handlebars.Net.Helpers.Random" Version="2.4.0" />
|
||||
<PackageReference Include="log4net" Version="2.0.15" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -28,14 +28,14 @@
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\src\WireMock.Net\WireMock.Net.csproj" />
|
||||
<PackageReference Include="Handlebars.Net.Helpers" Version="2.*" />
|
||||
<PackageReference Include="Handlebars.Net.Helpers.DynamicLinq" Version="2.*" />
|
||||
<PackageReference Include="Handlebars.Net.Helpers.Json" Version="2.3.*" />
|
||||
<PackageReference Include="Handlebars.Net.Helpers.XPath" Version="2.*" />
|
||||
<PackageReference Include="Handlebars.Net.Helpers.Xeger" Version="2.3.*" />
|
||||
<PackageReference Include="Handlebars.Net.Helpers.Random" Version="2.3.*" />
|
||||
<PackageReference Include="Handlebars.Net.Helpers" Version="2.4.0" />
|
||||
<PackageReference Include="Handlebars.Net.Helpers.DynamicLinq" Version="2.4.0" />
|
||||
<PackageReference Include="Handlebars.Net.Helpers.Json" Version="2.4.0" />
|
||||
<PackageReference Include="Handlebars.Net.Helpers.XPath" Version="2.4.0" />
|
||||
<PackageReference Include="Handlebars.Net.Helpers.Xeger" Version="2.4.0" />
|
||||
<PackageReference Include="Handlebars.Net.Helpers.Random" Version="2.4.0" />
|
||||
<PackageReference Include="log4net" Version="2.0.15" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -42,6 +42,36 @@ namespace WireMock.Net.ConsoleApplication
|
||||
|
||||
public static class MainApp
|
||||
{
|
||||
private const string TestSchema = @"
|
||||
input MessageInput {
|
||||
content: String
|
||||
author: String
|
||||
}
|
||||
|
||||
type Message {
|
||||
id: ID!
|
||||
content: String
|
||||
author: String
|
||||
}
|
||||
|
||||
type Mutation {
|
||||
createMessage(input: MessageInput): Message
|
||||
updateMessage(id: ID!, input: MessageInput): Message
|
||||
}
|
||||
|
||||
type Query {
|
||||
greeting:String
|
||||
students:[Student]
|
||||
studentById(id:ID!):Student
|
||||
}
|
||||
|
||||
type Student {
|
||||
id:ID!
|
||||
firstName:String
|
||||
lastName:String
|
||||
fullName:String
|
||||
}";
|
||||
|
||||
public static void Run()
|
||||
{
|
||||
var mappingBuilder = new MappingBuilder();
|
||||
@@ -136,7 +166,51 @@ namespace WireMock.Net.ConsoleApplication
|
||||
//server.SetAzureADAuthentication("6c2a4722-f3b9-4970-b8fc-fac41e29stef", "8587fde1-7824-42c7-8592-faf92b04stef");
|
||||
|
||||
// server.AllowPartialMapping();
|
||||
#if GRAPHQL
|
||||
server
|
||||
.Given(Request.Create()
|
||||
.WithPath("/graphql")
|
||||
.UsingPost()
|
||||
.WithGraphQLSchema(TestSchema)
|
||||
)
|
||||
.RespondWith(Response.Create()
|
||||
.WithBody("GraphQL is ok")
|
||||
);
|
||||
#endif
|
||||
|
||||
#if MIMEKIT
|
||||
var textPlainContentTypeMatcher = new ContentTypeMatcher("text/plain");
|
||||
var textPlainContentMatcher = new ExactMatcher("This is some plain text");
|
||||
var textPlainMatcher = new MimePartMatcher(MatchBehaviour.AcceptOnMatch, textPlainContentTypeMatcher, null, null, textPlainContentMatcher);
|
||||
|
||||
var textJsonContentTypeMatcher = new ContentTypeMatcher("text/json");
|
||||
var textJsonContentMatcher = new JsonMatcher(new { Key = "Value" }, true);
|
||||
var textJsonMatcher = new MimePartMatcher(MatchBehaviour.AcceptOnMatch, textJsonContentTypeMatcher, null, null, textJsonContentMatcher);
|
||||
|
||||
var imagePngContentTypeMatcher = new ContentTypeMatcher("image/png");
|
||||
var imagePngContentDispositionMatcher = new ExactMatcher("attachment; filename=\"image.png\"");
|
||||
var imagePngContentTransferEncodingMatcher = new ExactMatcher("base64");
|
||||
var imagePngContentMatcher = new ExactObjectMatcher(Convert.FromBase64String("iVBORw0KGgoAAAANSUhEUgAAAAIAAAACAgMAAAAP2OW3AAAADFBMVEX/tID/vpH/pWX/sHidUyjlAAAADElEQVR4XmMQYNgAAADkAMHebX3mAAAAAElFTkSuQmCC"));
|
||||
var imagePngMatcher = new MimePartMatcher(MatchBehaviour.AcceptOnMatch, imagePngContentTypeMatcher, imagePngContentDispositionMatcher, imagePngContentTransferEncodingMatcher, imagePngContentMatcher);
|
||||
|
||||
var matchers = new IMatcher[]
|
||||
{
|
||||
textPlainMatcher,
|
||||
textJsonMatcher,
|
||||
imagePngMatcher
|
||||
};
|
||||
|
||||
server
|
||||
.Given(Request.Create()
|
||||
.WithPath("/multipart")
|
||||
.UsingPost()
|
||||
.WithMultiPart(matchers)
|
||||
)
|
||||
.WithGuid("b9c82182-e469-41da-bcaf-b6e3157fefdb")
|
||||
.RespondWith(Response.Create()
|
||||
.WithBody("MultiPart is ok")
|
||||
);
|
||||
#endif
|
||||
// 400 ms
|
||||
server
|
||||
.Given(Request.Create()
|
||||
@@ -676,8 +750,9 @@ namespace WireMock.Net.ConsoleApplication
|
||||
}));
|
||||
|
||||
server.Given(Request.Create().WithPath(new WildcardMatcher("/multi-webhook", true)).UsingPost())
|
||||
.WithWebhook(new[] {
|
||||
new Webhook()
|
||||
.WithWebhook
|
||||
(
|
||||
new Webhook
|
||||
{
|
||||
Request = new WebhookRequest
|
||||
{
|
||||
@@ -685,12 +760,13 @@ namespace WireMock.Net.ConsoleApplication
|
||||
Method = "post",
|
||||
BodyData = new BodyData
|
||||
{
|
||||
BodyAsString = "OK 1!", DetectedBodyType = BodyType.String
|
||||
BodyAsString = "OK 1!",
|
||||
DetectedBodyType = BodyType.String
|
||||
},
|
||||
Delay = 1000
|
||||
}
|
||||
},
|
||||
new Webhook()
|
||||
new Webhook
|
||||
{
|
||||
Request = new WebhookRequest
|
||||
{
|
||||
@@ -705,7 +781,7 @@ namespace WireMock.Net.ConsoleApplication
|
||||
MaximumRandomDelay = 7000
|
||||
}
|
||||
}
|
||||
})
|
||||
)
|
||||
.WithWebhookFireAndForget(true)
|
||||
.RespondWith(Response.Create().WithBody("a-response"));
|
||||
|
||||
|
||||
@@ -39,14 +39,14 @@
|
||||
<Reference Include="AnyOf, Version=0.3.0.0, Culture=neutral, PublicKeyToken=b35e6abbb527c6b1, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\AnyOf.0.3.0\lib\net45\AnyOf.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Handlebars, Version=2.1.2.0, Culture=neutral, PublicKeyToken=22225d0bf33cd661, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Handlebars.Net.2.1.2\lib\net452\Handlebars.dll</HintPath>
|
||||
<Reference Include="Handlebars, Version=2.1.4.0, Culture=neutral, PublicKeyToken=22225d0bf33cd661, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Handlebars.Net.2.1.4\lib\net452\Handlebars.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Handlebars.Net.Helpers, Version=2.3.12.0, Culture=neutral, PublicKeyToken=00d131fae0c250bc, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Handlebars.Net.Helpers.2.3.12\lib\net452\Handlebars.Net.Helpers.dll</HintPath>
|
||||
<Reference Include="Handlebars.Net.Helpers, Version=2.4.0.0, Culture=neutral, PublicKeyToken=00d131fae0c250bc, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Handlebars.Net.Helpers.2.4.0\lib\net452\Handlebars.Net.Helpers.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="HandlebarsDotNet.Helpers.Core, Version=2.3.12.0, Culture=neutral, PublicKeyToken=00d131fae0c250bc, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Handlebars.Net.Helpers.Core.2.3.12\lib\net452\HandlebarsDotNet.Helpers.Core.dll</HintPath>
|
||||
<Reference Include="HandlebarsDotNet.Helpers.Core, Version=2.4.0.0, Culture=neutral, PublicKeyToken=00d131fae0c250bc, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Handlebars.Net.Helpers.Core.2.4.0\lib\net452\HandlebarsDotNet.Helpers.Core.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="log4net, Version=2.0.15.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\log4net.2.0.15\lib\net45\log4net.dll</HintPath>
|
||||
@@ -56,7 +56,7 @@
|
||||
<HintPath>..\..\packages\Microsoft.Owin.Host.HttpListener.3.1.0\lib\net45\Microsoft.Owin.Host.HttpListener.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Newtonsoft.Json.13.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||
<HintPath>..\..\packages\Newtonsoft.Json.13.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="SimMetrics.Net, Version=1.0.5.0, Culture=neutral, PublicKeyToken=c58dc06d59f3391b, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\SimMetrics.Net.1.0.5\lib\net45\SimMetrics.Net.dll</HintPath>
|
||||
@@ -67,6 +67,7 @@
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Configuration" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Net.Http" />
|
||||
<Reference Include="System.ValueTuple, Version=4.0.3.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\System.ValueTuple.4.5.0\lib\netstandard1.0\System.ValueTuple.dll</HintPath>
|
||||
</Reference>
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="AnyOf" version="0.3.0" targetFramework="net452" />
|
||||
<package id="Handlebars.Net" version="2.1.2" targetFramework="net452" />
|
||||
<package id="Handlebars.Net.Helpers" version="2.3.12" targetFramework="net452" />
|
||||
<package id="Handlebars.Net.Helpers.Core" version="2.3.12" targetFramework="net452" />
|
||||
<package id="Handlebars.Net" version="2.1.4" targetFramework="net452" />
|
||||
<package id="Handlebars.Net.Helpers" version="2.4.0" targetFramework="net452" />
|
||||
<package id="Handlebars.Net.Helpers.Core" version="2.4.0" targetFramework="net452" />
|
||||
<package id="log4net" version="2.0.15" targetFramework="net452" />
|
||||
<package id="Microsoft.Owin.Host.HttpListener" version="3.1.0" targetFramework="net452" />
|
||||
<package id="Newtonsoft.Json" version="13.0.1" targetFramework="net452" />
|
||||
<package id="Newtonsoft.Json" version="13.0.3" targetFramework="net452" />
|
||||
<package id="SimMetrics.Net" version="1.0.5" targetFramework="net452" />
|
||||
<package id="Stef.Validation" version="0.1.1" targetFramework="net452" />
|
||||
<package id="System.ValueTuple" version="4.5.0" targetFramework="net452" />
|
||||
|
||||
@@ -38,14 +38,14 @@
|
||||
<Reference Include="AnyOf, Version=0.3.0.0, Culture=neutral, PublicKeyToken=b35e6abbb527c6b1, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\AnyOf.0.3.0\lib\net45\AnyOf.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Handlebars, Version=2.1.2.0, Culture=neutral, PublicKeyToken=22225d0bf33cd661, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Handlebars.Net.2.1.2\lib\net46\Handlebars.dll</HintPath>
|
||||
<Reference Include="Handlebars, Version=2.1.4.0, Culture=neutral, PublicKeyToken=22225d0bf33cd661, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Handlebars.Net.2.1.4\lib\net46\Handlebars.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Handlebars.Net.Helpers, Version=2.3.12.0, Culture=neutral, PublicKeyToken=00d131fae0c250bc, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Handlebars.Net.Helpers.2.3.12\lib\net46\Handlebars.Net.Helpers.dll</HintPath>
|
||||
<Reference Include="Handlebars.Net.Helpers, Version=2.4.0.0, Culture=neutral, PublicKeyToken=00d131fae0c250bc, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Handlebars.Net.Helpers.2.4.0\lib\net46\Handlebars.Net.Helpers.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="HandlebarsDotNet.Helpers.Core, Version=2.3.12.0, Culture=neutral, PublicKeyToken=00d131fae0c250bc, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Handlebars.Net.Helpers.Core.2.3.12\lib\net46\HandlebarsDotNet.Helpers.Core.dll</HintPath>
|
||||
<Reference Include="HandlebarsDotNet.Helpers.Core, Version=2.4.0.0, Culture=neutral, PublicKeyToken=00d131fae0c250bc, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Handlebars.Net.Helpers.Core.2.4.0\lib\net46\HandlebarsDotNet.Helpers.Core.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="log4net, Version=2.0.15.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\log4net.2.0.15\lib\net45\log4net.dll</HintPath>
|
||||
@@ -54,7 +54,7 @@
|
||||
<HintPath>..\..\packages\Microsoft.Extensions.DependencyInjection.Abstractions.2.2.0\lib\netstandard2.0\Microsoft.Extensions.DependencyInjection.Abstractions.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Newtonsoft.Json.13.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||
<HintPath>..\..\packages\Newtonsoft.Json.13.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="SimMetrics.Net, Version=1.0.5.0, Culture=neutral, PublicKeyToken=c58dc06d59f3391b, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\SimMetrics.Net.1.0.5\lib\net45\SimMetrics.Net.dll</HintPath>
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="AnyOf" version="0.3.0" targetFramework="net461" />
|
||||
<package id="Handlebars.Net" version="2.1.2" targetFramework="net461" />
|
||||
<package id="Handlebars.Net.Helpers" version="2.3.12" targetFramework="net461" />
|
||||
<package id="Handlebars.Net.Helpers.Core" version="2.3.12" targetFramework="net461" />
|
||||
<package id="Handlebars.Net" version="2.1.4" targetFramework="net461" />
|
||||
<package id="Handlebars.Net.Helpers" version="2.4.0" targetFramework="net461" />
|
||||
<package id="Handlebars.Net.Helpers.Core" version="2.4.0" targetFramework="net461" />
|
||||
<package id="log4net" version="2.0.15" targetFramework="net461" />
|
||||
<package id="Microsoft.Extensions.DependencyInjection.Abstractions" version="2.2.0" targetFramework="net461" />
|
||||
<package id="Newtonsoft.Json" version="13.0.1" targetFramework="net461" />
|
||||
<package id="Newtonsoft.Json" version="13.0.3" targetFramework="net461" />
|
||||
<package id="SimMetrics.Net" version="1.0.5" targetFramework="net461" />
|
||||
<package id="Stef.Validation" version="0.1.1" targetFramework="net461" />
|
||||
<package id="System.ValueTuple" version="4.5.0" targetFramework="net461" />
|
||||
|
||||
@@ -101,6 +101,10 @@
|
||||
<assemblyIdentity name="System.IdentityModel.Tokens.Jwt" publicKeyToken="31bf3856ad364e35" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-6.25.0.0" newVersion="6.25.0.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="NJsonSchema" publicKeyToken="c2f9c3bdfae56102" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-10.7.2.0" newVersion="10.7.2.0" />
|
||||
</dependentAssembly>
|
||||
</assemblyBinding>
|
||||
</runtime>
|
||||
</configuration>
|
||||
|
||||
@@ -46,32 +46,32 @@
|
||||
<Reference Include="Fare, Version=2.2.0.0, Culture=neutral, PublicKeyToken=ea68d375bf33a7c8, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Fare.2.2.1\lib\net35\Fare.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Handlebars, Version=2.1.2.0, Culture=neutral, PublicKeyToken=22225d0bf33cd661, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Handlebars.Net.2.1.2\lib\net46\Handlebars.dll</HintPath>
|
||||
<Reference Include="Handlebars, Version=2.1.4.0, Culture=neutral, PublicKeyToken=22225d0bf33cd661, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Handlebars.Net.2.1.4\lib\net46\Handlebars.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Handlebars.Net.Helpers, Version=2.3.12.0, Culture=neutral, PublicKeyToken=00d131fae0c250bc, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Handlebars.Net.Helpers.2.3.12\lib\net46\Handlebars.Net.Helpers.dll</HintPath>
|
||||
<Reference Include="Handlebars.Net.Helpers, Version=2.4.0.0, Culture=neutral, PublicKeyToken=00d131fae0c250bc, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Handlebars.Net.Helpers.2.4.0\lib\net46\Handlebars.Net.Helpers.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="HandlebarsDotNet.Helpers.Core, Version=2.3.12.0, Culture=neutral, PublicKeyToken=00d131fae0c250bc, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Handlebars.Net.Helpers.Core.2.3.12\lib\net46\HandlebarsDotNet.Helpers.Core.dll</HintPath>
|
||||
<Reference Include="HandlebarsDotNet.Helpers.Core, Version=2.4.0.0, Culture=neutral, PublicKeyToken=00d131fae0c250bc, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Handlebars.Net.Helpers.Core.2.4.0\lib\net46\HandlebarsDotNet.Helpers.Core.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="HandlebarsDotNet.Helpers.DynamicLinq, Version=2.3.12.0, Culture=neutral, PublicKeyToken=00d131fae0c250bc, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Handlebars.Net.Helpers.DynamicLinq.2.3.12\lib\net46\HandlebarsDotNet.Helpers.DynamicLinq.dll</HintPath>
|
||||
<Reference Include="HandlebarsDotNet.Helpers.DynamicLinq, Version=2.4.0.0, Culture=neutral, PublicKeyToken=00d131fae0c250bc, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Handlebars.Net.Helpers.DynamicLinq.2.4.0\lib\net46\HandlebarsDotNet.Helpers.DynamicLinq.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="HandlebarsDotNet.Helpers.Humanizer, Version=2.3.12.0, Culture=neutral, PublicKeyToken=00d131fae0c250bc, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Handlebars.Net.Helpers.Humanizer.2.3.12\lib\net46\HandlebarsDotNet.Helpers.Humanizer.dll</HintPath>
|
||||
<Reference Include="HandlebarsDotNet.Helpers.Humanizer, Version=2.4.0.0, Culture=neutral, PublicKeyToken=00d131fae0c250bc, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Handlebars.Net.Helpers.Humanizer.2.4.0\lib\net46\HandlebarsDotNet.Helpers.Humanizer.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="HandlebarsDotNet.Helpers.Json, Version=2.3.12.0, Culture=neutral, PublicKeyToken=00d131fae0c250bc, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Handlebars.Net.Helpers.Json.2.3.12\lib\net46\HandlebarsDotNet.Helpers.Json.dll</HintPath>
|
||||
<Reference Include="HandlebarsDotNet.Helpers.Json, Version=2.4.0.0, Culture=neutral, PublicKeyToken=00d131fae0c250bc, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Handlebars.Net.Helpers.Json.2.4.0\lib\net46\HandlebarsDotNet.Helpers.Json.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="HandlebarsDotNet.Helpers.Random, Version=2.3.12.0, Culture=neutral, PublicKeyToken=00d131fae0c250bc, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Handlebars.Net.Helpers.Random.2.3.12\lib\net46\HandlebarsDotNet.Helpers.Random.dll</HintPath>
|
||||
<Reference Include="HandlebarsDotNet.Helpers.Random, Version=2.4.0.0, Culture=neutral, PublicKeyToken=00d131fae0c250bc, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Handlebars.Net.Helpers.Random.2.4.0\lib\net46\HandlebarsDotNet.Helpers.Random.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="HandlebarsDotNet.Helpers.Xeger, Version=2.3.12.0, Culture=neutral, PublicKeyToken=00d131fae0c250bc, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Handlebars.Net.Helpers.Xeger.2.3.12\lib\net46\HandlebarsDotNet.Helpers.Xeger.dll</HintPath>
|
||||
<Reference Include="HandlebarsDotNet.Helpers.Xeger, Version=2.4.0.0, Culture=neutral, PublicKeyToken=00d131fae0c250bc, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Handlebars.Net.Helpers.Xeger.2.4.0\lib\net46\HandlebarsDotNet.Helpers.Xeger.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="HandlebarsDotNet.Helpers.XPath, Version=2.3.12.0, Culture=neutral, PublicKeyToken=00d131fae0c250bc, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Handlebars.Net.Helpers.XPath.2.3.12\lib\net46\HandlebarsDotNet.Helpers.XPath.dll</HintPath>
|
||||
<Reference Include="HandlebarsDotNet.Helpers.XPath, Version=2.4.0.0, Culture=neutral, PublicKeyToken=00d131fae0c250bc, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Handlebars.Net.Helpers.XPath.2.4.0\lib\net46\HandlebarsDotNet.Helpers.XPath.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Humanizer, Version=2.14.0.0, Culture=neutral, PublicKeyToken=979442b78dfc278e, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Humanizer.Core.2.14.1\lib\netstandard2.0\Humanizer.dll</HintPath>
|
||||
@@ -257,16 +257,16 @@
|
||||
<HintPath>..\..\packages\Namotion.Reflection.2.0.10\lib\net45\Namotion.Reflection.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Newtonsoft.Json.13.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||
<HintPath>..\..\packages\Newtonsoft.Json.13.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="NJsonSchema, Version=10.6.10.0, Culture=neutral, PublicKeyToken=c2f9c3bdfae56102, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\NJsonSchema.10.6.10\lib\net45\NJsonSchema.dll</HintPath>
|
||||
<Reference Include="NJsonSchema, Version=10.7.2.0, Culture=neutral, PublicKeyToken=c2f9c3bdfae56102, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\NJsonSchema.10.7.2\lib\net45\NJsonSchema.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="NJsonSchema.Extensions, Version=0.1.0.0, Culture=neutral, PublicKeyToken=e52fadf300daf456, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\NJsonSchema.Extensions.0.1.0\lib\net45\NJsonSchema.Extensions.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="NSwag.Core, Version=13.15.10.0, Culture=neutral, PublicKeyToken=c2d88086e098d109, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\NSwag.Core.13.15.10\lib\net45\NSwag.Core.dll</HintPath>
|
||||
<Reference Include="NSwag.Core, Version=13.16.1.0, Culture=neutral, PublicKeyToken=c2d88086e098d109, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\NSwag.Core.13.16.1\lib\net45\NSwag.Core.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="RandomDataGenerator, Version=1.0.16.0, Culture=neutral, PublicKeyToken=ae5c571d29a3b8d9, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\RandomDataGenerator.Net.1.0.17\lib\net45\RandomDataGenerator.dll</HintPath>
|
||||
@@ -302,8 +302,8 @@
|
||||
<Reference Include="System.IO.Pipelines, Version=4.0.0.1, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\System.IO.Pipelines.4.5.3\lib\netstandard2.0\System.IO.Pipelines.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Linq.Dynamic.Core, Version=1.2.23.0, Culture=neutral, PublicKeyToken=0f07ec44de6ac832, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\System.Linq.Dynamic.Core.1.2.23\lib\net46\System.Linq.Dynamic.Core.dll</HintPath>
|
||||
<Reference Include="System.Linq.Dynamic.Core, Version=1.3.1.0, Culture=neutral, PublicKeyToken=0f07ec44de6ac832, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\System.Linq.Dynamic.Core.1.3.1\lib\net46\System.Linq.Dynamic.Core.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Memory, Version=4.0.1.1, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\System.Memory.4.5.4\lib\net461\System.Memory.dll</HintPath>
|
||||
|
||||
@@ -2,15 +2,15 @@
|
||||
<packages>
|
||||
<package id="AnyOf" version="0.3.0" targetFramework="net472" />
|
||||
<package id="Fare" version="2.2.1" targetFramework="net472" />
|
||||
<package id="Handlebars.Net" version="2.1.2" targetFramework="net472" />
|
||||
<package id="Handlebars.Net.Helpers" version="2.3.12" targetFramework="net472" />
|
||||
<package id="Handlebars.Net.Helpers.Core" version="2.3.12" targetFramework="net472" />
|
||||
<package id="Handlebars.Net.Helpers.DynamicLinq" version="2.3.12" targetFramework="net472" />
|
||||
<package id="Handlebars.Net.Helpers.Humanizer" version="2.3.12" targetFramework="net472" />
|
||||
<package id="Handlebars.Net.Helpers.Json" version="2.3.12" targetFramework="net472" />
|
||||
<package id="Handlebars.Net.Helpers.Random" version="2.3.12" targetFramework="net472" />
|
||||
<package id="Handlebars.Net.Helpers.Xeger" version="2.3.12" targetFramework="net472" />
|
||||
<package id="Handlebars.Net.Helpers.XPath" version="2.3.12" targetFramework="net472" />
|
||||
<package id="Handlebars.Net" version="2.1.4" targetFramework="net472" />
|
||||
<package id="Handlebars.Net.Helpers" version="2.4.0" targetFramework="net472" />
|
||||
<package id="Handlebars.Net.Helpers.Core" version="2.4.0" targetFramework="net472" />
|
||||
<package id="Handlebars.Net.Helpers.DynamicLinq" version="2.4.0" targetFramework="net472" />
|
||||
<package id="Handlebars.Net.Helpers.Humanizer" version="2.4.0" targetFramework="net472" />
|
||||
<package id="Handlebars.Net.Helpers.Json" version="2.4.0" targetFramework="net472" />
|
||||
<package id="Handlebars.Net.Helpers.Random" version="2.4.0" targetFramework="net472" />
|
||||
<package id="Handlebars.Net.Helpers.Xeger" version="2.4.0" targetFramework="net472" />
|
||||
<package id="Handlebars.Net.Helpers.XPath" version="2.4.0" targetFramework="net472" />
|
||||
<package id="Humanizer" version="2.14.1" targetFramework="net472" />
|
||||
<package id="Humanizer.Core" version="2.14.1" targetFramework="net472" />
|
||||
<package id="Humanizer.Core.af" version="2.14.1" targetFramework="net472" />
|
||||
@@ -123,10 +123,10 @@
|
||||
<package id="Microsoft.IdentityModel.Tokens" version="6.25.0" targetFramework="net472" />
|
||||
<package id="Microsoft.Net.Http.Headers" version="2.2.0" targetFramework="net472" />
|
||||
<package id="Namotion.Reflection" version="2.0.10" targetFramework="net472" />
|
||||
<package id="Newtonsoft.Json" version="13.0.1" targetFramework="net472" />
|
||||
<package id="NJsonSchema" version="10.6.10" targetFramework="net472" />
|
||||
<package id="Newtonsoft.Json" version="13.0.3" targetFramework="net472" />
|
||||
<package id="NJsonSchema" version="10.7.2" targetFramework="net472" />
|
||||
<package id="NJsonSchema.Extensions" version="0.1.0" targetFramework="net472" />
|
||||
<package id="NSwag.Core" version="13.15.10" targetFramework="net472" />
|
||||
<package id="NSwag.Core" version="13.16.1" targetFramework="net472" />
|
||||
<package id="Nullable" version="1.3.1" targetFramework="net472" developmentDependency="true" />
|
||||
<package id="RandomDataGenerator.Net" version="1.0.17" targetFramework="net472" />
|
||||
<package id="Scriban.Signed" version="2.1.4" targetFramework="net472" />
|
||||
@@ -138,7 +138,7 @@
|
||||
<package id="System.Diagnostics.DiagnosticSource" version="4.5.0" targetFramework="net472" />
|
||||
<package id="System.IdentityModel.Tokens.Jwt" version="6.25.0" targetFramework="net472" />
|
||||
<package id="System.IO.Pipelines" version="4.5.3" targetFramework="net472" />
|
||||
<package id="System.Linq.Dynamic.Core" version="1.2.23" targetFramework="net472" />
|
||||
<package id="System.Linq.Dynamic.Core" version="1.3.1" targetFramework="net472" />
|
||||
<package id="System.Memory" version="4.5.4" targetFramework="net472" />
|
||||
<package id="System.Numerics.Vectors" version="4.5.0" targetFramework="net472" />
|
||||
<package id="System.Reflection.Metadata" version="1.6.0" targetFramework="net472" />
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\src\WireMock.Net\WireMock.Net.csproj" />
|
||||
<ProjectReference Include="..\..\src\WireMock.Net.Abstractions\WireMock.Net.Abstractions.csproj" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -72,7 +72,7 @@
|
||||
<HintPath>..\..\packages\Microsoft.Owin.Host.HttpListener.3.1.0\lib\net45\Microsoft.Owin.Host.HttpListener.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Newtonsoft.Json.13.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||
<HintPath>..\..\packages\Newtonsoft.Json.13.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Microsoft.Owin.Host.HttpListener" version="3.1.0" targetFramework="net452" />
|
||||
<package id="Newtonsoft.Json" version="13.0.1" targetFramework="net452" />
|
||||
<package id="Newtonsoft.Json" version="13.0.3" targetFramework="net452" />
|
||||
</packages>
|
||||
@@ -46,7 +46,7 @@
|
||||
<HintPath>..\..\packages\Microsoft.Owin.Hosting.2.0.2\lib\net45\Microsoft.Owin.Hosting.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Newtonsoft.Json.13.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||
<HintPath>..\..\packages\Newtonsoft.Json.13.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Owin, Version=1.0.0.0, Culture=neutral, PublicKeyToken=f0ebd12fd5e55cc5, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Owin.1.0\lib\net40\Owin.dll</HintPath>
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
<package id="Microsoft.Owin" version="4.2.2" targetFramework="net452" />
|
||||
<package id="Microsoft.Owin.Host.HttpListener" version="2.0.2" targetFramework="net452" />
|
||||
<package id="Microsoft.Owin.Hosting" version="2.0.2" targetFramework="net452" />
|
||||
<package id="Newtonsoft.Json" version="13.0.1" targetFramework="net452" />
|
||||
<package id="Newtonsoft.Json" version="13.0.3" targetFramework="net48" />
|
||||
<package id="Owin" version="1.0" targetFramework="net452" />
|
||||
<package id="SimMetrics.Net" version="1.0.5" targetFramework="net452" />
|
||||
<package id="System.Net.Http" version="4.3.4" targetFramework="net452" requireReinstallation="true" />
|
||||
|
||||
@@ -29,7 +29,7 @@ static class Program
|
||||
|
||||
XmlConfigurator.Configure(LogRepository, new FileInfo("log4net.config"));
|
||||
|
||||
if (!WireMockServerSettingsParser.TryParseArguments(args, out var settings, new WireMockLog4NetLogger()))
|
||||
if (!WireMockServerSettingsParser.TryParseArguments(args, Environment.GetEnvironmentVariables(), out var settings, new WireMockLog4NetLogger()))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ public class Program
|
||||
{
|
||||
XmlConfigurator.Configure(new FileInfo("log4net.config"));
|
||||
|
||||
if (WireMockServerSettingsParser.TryParseArguments(args, out var settings))
|
||||
if (WireMockServerSettingsParser.TryParseArguments(args, Environment.GetEnvironmentVariables(), out var settings))
|
||||
{
|
||||
Console.WriteLine("WireMock.Net server arguments [{0}]", string.Join(", ", args.Select(a => $"'{a}'")));
|
||||
|
||||
|
||||
@@ -46,7 +46,7 @@
|
||||
<HintPath>..\..\packages\Microsoft.Owin.Host.HttpListener.4.0.0\lib\net451\Microsoft.Owin.Host.HttpListener.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Newtonsoft.Json.13.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||
<HintPath>..\..\packages\Newtonsoft.Json.13.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Configuration" />
|
||||
|
||||
@@ -3,5 +3,5 @@
|
||||
<package id="log4net" version="2.0.15" targetFramework="net452" />
|
||||
<package id="Microsoft.AspNet.WebApi.Client" version="5.2.6" targetFramework="net452" />
|
||||
<package id="Microsoft.Owin.Host.HttpListener" version="4.0.0" targetFramework="net452" />
|
||||
<package id="Newtonsoft.Json" version="13.0.1" targetFramework="net452" />
|
||||
<package id="Newtonsoft.Json" version="13.0.3" targetFramework="net452" />
|
||||
</packages>
|
||||
@@ -9,7 +9,7 @@ static class Program
|
||||
{
|
||||
static void Main(string[] args)
|
||||
{
|
||||
if (WireMockServerSettingsParser.TryParseArguments(args, out var settings))
|
||||
if (WireMockServerSettingsParser.TryParseArguments(args, Environment.GetEnvironmentVariables(), out var settings))
|
||||
{
|
||||
Console.WriteLine("WireMock.Net server arguments [{0}]", string.Join(", ", args.Select(a => $"'{a}'")));
|
||||
|
||||
|
||||
@@ -39,8 +39,8 @@
|
||||
<StartupObject>WireMock.Net.StandAlone.Net461.Program</StartupObject>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Handlebars, Version=2.1.2.0, Culture=neutral, PublicKeyToken=22225d0bf33cd661, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Handlebars.Net.2.1.2\lib\net46\Handlebars.dll</HintPath>
|
||||
<Reference Include="Handlebars, Version=2.1.4.0, Culture=neutral, PublicKeyToken=22225d0bf33cd661, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Handlebars.Net.2.1.4\lib\net46\Handlebars.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.AspNetCore, Version=2.2.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Microsoft.AspNetCore.2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.dll</HintPath>
|
||||
@@ -205,7 +205,7 @@
|
||||
<HintPath>..\..\packages\MimeKitLite.2.0.7\lib\net45\MimeKitLite.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Newtonsoft.Json.13.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||
<HintPath>..\..\packages\Newtonsoft.Json.13.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Owin, Version=1.0.0.0, Culture=neutral, PublicKeyToken=f0ebd12fd5e55cc5, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Owin.1.0\lib\net40\Owin.dll</HintPath>
|
||||
@@ -235,8 +235,8 @@
|
||||
<Reference Include="System.IO.Pipelines, Version=4.0.0.1, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\System.IO.Pipelines.4.5.3\lib\netstandard2.0\System.IO.Pipelines.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Linq.Dynamic.Core, Version=1.2.23.0, Culture=neutral, PublicKeyToken=0f07ec44de6ac832, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\System.Linq.Dynamic.Core.1.2.23\lib\net46\System.Linq.Dynamic.Core.dll</HintPath>
|
||||
<Reference Include="System.Linq.Dynamic.Core, Version=1.3.1.0, Culture=neutral, PublicKeyToken=0f07ec44de6ac832, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\System.Linq.Dynamic.Core.1.3.1\lib\net46\System.Linq.Dynamic.Core.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Memory, Version=4.0.1.1, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\System.Memory.4.5.4\lib\net461\System.Memory.dll</HintPath>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Handlebars.Net" version="2.1.2" targetFramework="net461" />
|
||||
<package id="Handlebars.Net" version="2.1.4" targetFramework="net461" />
|
||||
<package id="Microsoft.AspNet.WebApi.Client" version="5.2.9" targetFramework="net461" />
|
||||
<package id="Microsoft.AspNet.WebApi.Core" version="5.2.9" targetFramework="net461" />
|
||||
<package id="Microsoft.AspNet.WebApi.Owin" version="5.2.9" targetFramework="net461" />
|
||||
@@ -59,7 +59,7 @@
|
||||
<package id="Microsoft.Owin.Host.HttpListener" version="4.2.2" targetFramework="net461" />
|
||||
<package id="Microsoft.Owin.Hosting" version="4.2.2" targetFramework="net461" />
|
||||
<package id="MimeKitLite" version="2.0.7" targetFramework="net461" />
|
||||
<package id="Newtonsoft.Json" version="13.0.1" targetFramework="net461" />
|
||||
<package id="Newtonsoft.Json" version="13.0.3" targetFramework="net461" />
|
||||
<package id="Owin" version="1.0" targetFramework="net461" />
|
||||
<package id="RestEase" version="1.5.7" targetFramework="net461" />
|
||||
<package id="SimMetrics.Net" version="1.0.5" targetFramework="net461" />
|
||||
@@ -68,7 +68,7 @@
|
||||
<package id="System.ComponentModel.Annotations" version="4.5.0" targetFramework="net461" />
|
||||
<package id="System.Diagnostics.DiagnosticSource" version="4.5.1" targetFramework="net461" />
|
||||
<package id="System.IO.Pipelines" version="4.5.3" targetFramework="net461" />
|
||||
<package id="System.Linq.Dynamic.Core" version="1.2.23" targetFramework="net461" />
|
||||
<package id="System.Linq.Dynamic.Core" version="1.3.1" targetFramework="net461" />
|
||||
<package id="System.Memory" version="4.5.4" targetFramework="net461" />
|
||||
<package id="System.Numerics.Vectors" version="4.5.0" targetFramework="net461" />
|
||||
<package id="System.Reflection.Metadata" version="1.6.0" targetFramework="net461" />
|
||||
|
||||
43
examples/WireMock.Net.TestcontainersExample/Program.cs
Normal file
43
examples/WireMock.Net.TestcontainersExample/Program.cs
Normal file
@@ -0,0 +1,43 @@
|
||||
using Newtonsoft.Json;
|
||||
using Testcontainers.MsSql;
|
||||
using WireMock.Net.Testcontainers;
|
||||
|
||||
namespace WireMock.Net.TestcontainersExample;
|
||||
|
||||
internal class Program
|
||||
{
|
||||
private static async Task Main(string[] args)
|
||||
{
|
||||
var container = new WireMockContainerBuilder()
|
||||
.WithAdminUserNameAndPassword("x", "y")
|
||||
.WithMappings(@"C:\Dev\GitHub\WireMock.Net\examples\WireMock.Net.Console.NET6\__admin\mappings")
|
||||
.WithWatchStaticMappings(true)
|
||||
.WithAutoRemove(true)
|
||||
.WithCleanUp(true)
|
||||
.Build();
|
||||
|
||||
await container.StartAsync().ConfigureAwait(false);
|
||||
|
||||
var logs = await container.GetLogsAsync(DateTime.Now.AddDays(-1)).ConfigureAwait(false);
|
||||
Console.WriteLine("logs = " + logs.Stdout);
|
||||
|
||||
var restEaseApiClient = container.CreateWireMockAdminClient();
|
||||
|
||||
var settings = await restEaseApiClient.GetSettingsAsync();
|
||||
Console.WriteLine("settings = " + JsonConvert.SerializeObject(settings, Formatting.Indented));
|
||||
|
||||
var mappings = await restEaseApiClient.GetMappingsAsync();
|
||||
Console.WriteLine("mappings = " + JsonConvert.SerializeObject(mappings, Formatting.Indented));
|
||||
|
||||
var client = container.CreateClient();
|
||||
var result = await client.GetStringAsync("/static/mapping");
|
||||
Console.WriteLine("result = " + result);
|
||||
|
||||
await container.StopAsync();
|
||||
|
||||
var sql = new MsSqlBuilder()
|
||||
.WithAutoRemove(true)
|
||||
.WithCleanUp(true)
|
||||
.Build();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Testcontainers.MsSql" Version="3.2.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\src\WireMock.Net.Testcontainers\WireMock.Net.Testcontainers.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Update="873d495f-940e-4b86-a1f4-4f0fc7be8b8b.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="6.0.0" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -12,13 +12,13 @@
|
||||
<ItemGroup Condition=" '$(TargetFramework)' == 'netcoreapp2.0'">
|
||||
<DotNetCliToolReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Tools" Version="2.0.2" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.9" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition=" '$(TargetFramework)' == 'netcoreapp2.1'">
|
||||
<DotNetCliToolReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Tools" Version="2.0.4" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.All" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="3.1.8" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -39,14 +39,38 @@ public class MatcherModel
|
||||
/// <summary>
|
||||
/// The Operator to use when multiple patterns are defined. Optional.
|
||||
/// - null = Same as "or".
|
||||
/// - "or" = Only one pattern should match.
|
||||
/// - "or" = Only one pattern is required to match.
|
||||
/// - "and" = All patterns should match.
|
||||
/// - "average" = The average value from all patterns.
|
||||
/// </summary>
|
||||
public string? MatchOperator { get; set; }
|
||||
|
||||
#region JsonPartialMatcher and JsonPartialWildcardMatcher
|
||||
/// <summary>
|
||||
/// Support Regex, only used for JsonPartialMatcher.
|
||||
/// Support Regex.
|
||||
/// </summary>
|
||||
public bool? Regex { get; set; }
|
||||
#endregion
|
||||
|
||||
#region MimePartMatcher
|
||||
/// <summary>
|
||||
/// ContentType Matcher (image/png; name=image.png)
|
||||
/// </summary>
|
||||
public MatcherModel? ContentTypeMatcher { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// ContentDisposition Matcher (attachment; filename=image.png)
|
||||
/// </summary>
|
||||
public MatcherModel? ContentDispositionMatcher { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// ContentTransferEncoding Matcher (base64)
|
||||
/// </summary>
|
||||
public MatcherModel? ContentTransferEncodingMatcher { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Content Matcher
|
||||
/// </summary>
|
||||
public MatcherModel? ContentMatcher { get; set; }
|
||||
#endregion
|
||||
}
|
||||
@@ -96,32 +96,39 @@ public interface IRequestMessage
|
||||
/// <summary>
|
||||
/// The original body as string. Convenience getter for Handlebars.
|
||||
/// </summary>
|
||||
string Body { get; }
|
||||
string? Body { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The body (as JSON object). Convenience getter for Handlebars.
|
||||
/// </summary>
|
||||
object BodyAsJson { get; }
|
||||
object? BodyAsJson { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The body (as bytearray). Convenience getter for Handlebars.
|
||||
/// </summary>
|
||||
byte[] BodyAsBytes { get; }
|
||||
byte[]? BodyAsBytes { get; }
|
||||
|
||||
#if MIMEKIT
|
||||
/// <summary>
|
||||
/// The original body as MimeMessage. Convenience getter for Handlebars.
|
||||
/// </summary>
|
||||
object? BodyAsMimeMessage { get; }
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// The detected body type. Convenience getter for Handlebars.
|
||||
/// </summary>
|
||||
string DetectedBodyType { get; }
|
||||
string? DetectedBodyType { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The detected body type from the Content-Type header. Convenience getter for Handlebars.
|
||||
/// </summary>
|
||||
string DetectedBodyTypeFromContentType { get; }
|
||||
string? DetectedBodyTypeFromContentType { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The detected compression from the Content-Encoding header. Convenience getter for Handlebars.
|
||||
/// </summary>
|
||||
string DetectedCompression { get; }
|
||||
string? DetectedCompression { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Host
|
||||
@@ -143,6 +150,14 @@ public interface IRequestMessage
|
||||
/// </summary>
|
||||
string Origin { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Get a query parameter.
|
||||
/// </summary>
|
||||
/// <param name="key">The key.</param>
|
||||
/// <param name="ignoreCase">Defines if the key should be matched using case-ignore.</param>
|
||||
/// <returns>The query parameter value as WireMockList or null when not found.</returns>
|
||||
WireMockList<string>? GetParameter(string key, bool ignoreCase = false);
|
||||
|
||||
#if NETSTANDARD1_3_OR_GREATER || NET461
|
||||
/// <summary>
|
||||
/// Gets the connection's client certificate
|
||||
|
||||
@@ -30,6 +30,10 @@
|
||||
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition=" '$(TargetFramework)' == 'netstandard2.0' or '$(TargetFramework)' == 'netstandard2.1'" >
|
||||
<DefineConstants>$(DefineConstants);GRAPHQL;MIMEKIT</DefineConstants>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="JetBrains.Annotations" Version="2022.3.1" PrivateAssets="All" />
|
||||
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.1.1" PrivateAssets="All" />
|
||||
|
||||
@@ -149,15 +149,15 @@ public class WireMockAssertions
|
||||
|
||||
using (new AssertionScope($"header \"{expectedKey}\" from requests sent with value(s)"))
|
||||
{
|
||||
var headerValues = _headers.First(h => h.Key == expectedKey).Value;
|
||||
var matchingHeaderValues = _headers.Where(h => h.Key == expectedKey).SelectMany(h => h.Value.ToArray()).ToArray();
|
||||
|
||||
if (expectedValues.Length == 1)
|
||||
{
|
||||
headerValues.Should().Contain(expectedValues.First(), because, becauseArgs);
|
||||
matchingHeaderValues.Should().Contain(expectedValues.First(), because, becauseArgs);
|
||||
}
|
||||
else
|
||||
{
|
||||
var trimmedHeaderValues = string.Join(",", headerValues.Select(x => x)).Split(',').Select(x => x.Trim()).ToList();
|
||||
var trimmedHeaderValues = string.Join(",", matchingHeaderValues.Select(x => x)).Split(',').Select(x => x.Trim()).ToList();
|
||||
foreach (var expectedValue in expectedValues)
|
||||
{
|
||||
trimmedHeaderValues.Should().Contain(expectedValue, because, becauseArgs);
|
||||
|
||||
@@ -1,49 +1,49 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<Description>FluentAssertions extensions for WireMock.Net</Description>
|
||||
<AssemblyTitle>WireMock.Net.FluentAssertions</AssemblyTitle>
|
||||
<Authors>Mahmoud Ali;Stef Heyenrath</Authors>
|
||||
<TargetFrameworks>net451;netstandard1.3;netstandard2.0;netstandard2.1</TargetFrameworks>
|
||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||
<AssemblyName>WireMock.Net.FluentAssertions</AssemblyName>
|
||||
<PackageId>WireMock.Net.FluentAssertions</PackageId>
|
||||
<PackageTags>wiremock;FluentAssertions;UnitTest;Assert;Assertions</PackageTags>
|
||||
<RootNamespace>WireMock.FluentAssertions</RootNamespace>
|
||||
<ProjectGuid>{B6269AAC-170A-4346-8B9A-579DED3D9A95}</ProjectGuid>
|
||||
<PublishRepositoryUrl>true</PublishRepositoryUrl>
|
||||
<AllowedOutputExtensionsInPackageBuildOutputFolder>$(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb</AllowedOutputExtensionsInPackageBuildOutputFolder>
|
||||
<EmbedUntrackedSources>true</EmbedUntrackedSources>
|
||||
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
||||
<GenerateBindingRedirectsOutputType>true</GenerateBindingRedirectsOutputType>
|
||||
<CodeAnalysisRuleSet>../WireMock.Net/WireMock.Net.ruleset</CodeAnalysisRuleSet>
|
||||
<SignAssembly>true</SignAssembly>
|
||||
<AssemblyOriginatorKeyFile>../WireMock.Net/WireMock.Net.snk</AssemblyOriginatorKeyFile>
|
||||
<!--<DelaySign>true</DelaySign>-->
|
||||
<PublicSign Condition=" '$(OS)' != 'Windows_NT' ">true</PublicSign>
|
||||
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
||||
<LangVersion>10</LangVersion>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<Description>FluentAssertions extensions for WireMock.Net</Description>
|
||||
<AssemblyTitle>WireMock.Net.FluentAssertions</AssemblyTitle>
|
||||
<Authors>Mahmoud Ali;Stef Heyenrath</Authors>
|
||||
<TargetFrameworks>net451;net47;netstandard1.3;netstandard2.0;netstandard2.1</TargetFrameworks>
|
||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||
<AssemblyName>WireMock.Net.FluentAssertions</AssemblyName>
|
||||
<PackageId>WireMock.Net.FluentAssertions</PackageId>
|
||||
<PackageTags>wiremock;FluentAssertions;UnitTest;Assert;Assertions</PackageTags>
|
||||
<RootNamespace>WireMock.FluentAssertions</RootNamespace>
|
||||
<ProjectGuid>{B6269AAC-170A-4346-8B9A-579DED3D9A95}</ProjectGuid>
|
||||
<PublishRepositoryUrl>true</PublishRepositoryUrl>
|
||||
<AllowedOutputExtensionsInPackageBuildOutputFolder>$(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb</AllowedOutputExtensionsInPackageBuildOutputFolder>
|
||||
<EmbedUntrackedSources>true</EmbedUntrackedSources>
|
||||
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
||||
<GenerateBindingRedirectsOutputType>true</GenerateBindingRedirectsOutputType>
|
||||
<CodeAnalysisRuleSet>../WireMock.Net/WireMock.Net.ruleset</CodeAnalysisRuleSet>
|
||||
<SignAssembly>true</SignAssembly>
|
||||
<AssemblyOriginatorKeyFile>../WireMock.Net/WireMock.Net.snk</AssemblyOriginatorKeyFile>
|
||||
<!--<DelaySign>true</DelaySign>-->
|
||||
<PublicSign Condition=" '$(OS)' != 'Windows_NT' ">true</PublicSign>
|
||||
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
||||
<LangVersion>10</LangVersion>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
|
||||
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
|
||||
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="JetBrains.Annotations" Version="2022.3.1" PrivateAssets="All" />
|
||||
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.1.1" PrivateAssets="All" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="JetBrains.Annotations" Version="2022.3.1" PrivateAssets="All" />
|
||||
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.1.1" PrivateAssets="All" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition="'$(TargetFramework)' == 'net451' or '$(TargetFramework)' == 'netstandard1.3'">
|
||||
<PackageReference Include="FluentAssertions" Version="5.10.3" />
|
||||
</ItemGroup>
|
||||
<ItemGroup Condition="'$(TargetFramework)' == 'net451' or '$(TargetFramework)' == 'netstandard1.3'">
|
||||
<PackageReference Include="FluentAssertions" Version="5.10.3" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition="'$(TargetFramework)' != 'net451' and '$(TargetFramework)' != 'netstandard1.3'">
|
||||
<PackageReference Include="FluentAssertions" Version="6.5.1" />
|
||||
</ItemGroup>
|
||||
<ItemGroup Condition="'$(TargetFramework)' != 'net451' and '$(TargetFramework)' != 'netstandard1.3'">
|
||||
<PackageReference Include="FluentAssertions" Version="6.5.1" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\WireMock.Net.Abstractions\WireMock.Net.Abstractions.csproj" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\WireMock.Net.Abstractions\WireMock.Net.Abstractions.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -320,14 +320,14 @@ internal class OpenApiPathsMapper
|
||||
var mappedHeaders = headers?.ToDictionary(
|
||||
item => item.Key,
|
||||
_ => GetExampleMatcherModel(null, _settings.HeaderPatternToUse).Pattern!
|
||||
);
|
||||
) ?? new Dictionary<string, object>();
|
||||
|
||||
if (!string.IsNullOrEmpty(responseContentType))
|
||||
{
|
||||
mappedHeaders.TryAdd(HeaderContentType, responseContentType!);
|
||||
}
|
||||
|
||||
return mappedHeaders?.Keys.Any() == true ? mappedHeaders : null;
|
||||
return mappedHeaders.Keys.Any() ? mappedHeaders : null;
|
||||
}
|
||||
|
||||
private IList<ParamModel>? MapQueryParameters(IEnumerable<OpenApiParameter> queryParameters)
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
<PackageReference Include="Microsoft.OpenApi.Readers" Version="1.2.3" />
|
||||
<PackageReference Include="Nullable" Version="1.3.1">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
|
||||
@@ -47,9 +47,9 @@ public class WireMockOpenApiParser : IWireMockOpenApiParser
|
||||
|
||||
/// <inheritdoc />
|
||||
[PublicAPI]
|
||||
public IReadOnlyList<MappingModel> FromDocument(OpenApiDocument openApiDocument, WireMockOpenApiParserSettings? settings = null)
|
||||
public IReadOnlyList<MappingModel> FromDocument(OpenApiDocument document, WireMockOpenApiParserSettings? settings = null)
|
||||
{
|
||||
return new OpenApiPathsMapper(settings ?? new WireMockOpenApiParserSettings()).ToMappingModels(openApiDocument.Paths, openApiDocument.Servers);
|
||||
return new OpenApiPathsMapper(settings ?? new WireMockOpenApiParserSettings()).ToMappingModels(document.Paths, document.Servers);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using System;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
@@ -24,7 +25,7 @@ public static class StandAloneApp
|
||||
[PublicAPI]
|
||||
public static WireMockServer Start(WireMockServerSettings settings)
|
||||
{
|
||||
Guard.NotNull(settings, nameof(settings));
|
||||
Guard.NotNull(settings);
|
||||
|
||||
var server = WireMockServer.Start(settings);
|
||||
|
||||
@@ -42,7 +43,7 @@ public static class StandAloneApp
|
||||
[PublicAPI]
|
||||
public static WireMockServer Start(string[] args, IWireMockLogger? logger = null)
|
||||
{
|
||||
Guard.NotNull(args, nameof(args));
|
||||
Guard.NotNull(args);
|
||||
|
||||
if (TryStart(args, out var server, logger))
|
||||
{
|
||||
@@ -61,9 +62,9 @@ public static class StandAloneApp
|
||||
[PublicAPI]
|
||||
public static bool TryStart(string[] args, [NotNullWhen(true)] out WireMockServer? server, IWireMockLogger? logger = null)
|
||||
{
|
||||
Guard.NotNull(args, nameof(args));
|
||||
Guard.NotNull(args);
|
||||
|
||||
if (WireMockServerSettingsParser.TryParseArguments(args, out var settings, logger))
|
||||
if (WireMockServerSettingsParser.TryParseArguments(args, Environment.GetEnvironmentVariables(), out var settings, logger))
|
||||
{
|
||||
settings.Logger?.Info("Version [{0}]", Version);
|
||||
settings.Logger?.Debug("Server arguments [{0}]", string.Join(", ", args.Select(a => $"'{a}'")));
|
||||
|
||||
7
src/WireMock.Net.Testcontainers/Models/ContainerInfo.cs
Normal file
7
src/WireMock.Net.Testcontainers/Models/ContainerInfo.cs
Normal file
@@ -0,0 +1,7 @@
|
||||
namespace WireMock.Net.Testcontainers.Models;
|
||||
|
||||
internal record ContainerInfo
|
||||
(
|
||||
string Image,
|
||||
string MappingsPath
|
||||
);
|
||||
@@ -0,0 +1,36 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<Description>A fluent testcontainer builder for the Docker version of WireMock.Net</Description>
|
||||
<TargetFrameworks>netstandard2.0;netstandard2.1</TargetFrameworks>
|
||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||
<PackageTags>wiremock;docker;testcontainer;testcontainers</PackageTags>
|
||||
<ProjectGuid>{12B016A5-9D8B-4EFE-96C2-CA51BE43367D}</ProjectGuid>
|
||||
<PublishRepositoryUrl>true</PublishRepositoryUrl>
|
||||
<CodeAnalysisRuleSet>../WireMock.Net/WireMock.Net.ruleset</CodeAnalysisRuleSet>
|
||||
<SignAssembly>true</SignAssembly>
|
||||
<AssemblyOriginatorKeyFile>../WireMock.Net/WireMock.Net.snk</AssemblyOriginatorKeyFile>
|
||||
<PublicSign Condition=" '$(OS)' != 'Windows_NT' ">true</PublicSign>
|
||||
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
||||
<LangVersion>10</LangVersion>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)' == 'Release'">
|
||||
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="IsExternalInit" Version="1.0.3">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.AspNet.WebApi.Client" Version="5.2.9" />
|
||||
<PackageReference Include="Stef.Validation" Version="0.1.1" />
|
||||
<PackageReference Include="Testcontainers" Version="3.2.0" />
|
||||
<PackageReference Include="JetBrains.Annotations" VersionOverride="2022.3.1" PrivateAssets="All" Version="2022.3.1" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\WireMock.Net.RestClient\WireMock.Net.RestClient.csproj" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
66
src/WireMock.Net.Testcontainers/WireMockConfiguration.cs
Normal file
66
src/WireMock.Net.Testcontainers/WireMockConfiguration.cs
Normal file
@@ -0,0 +1,66 @@
|
||||
using Docker.DotNet.Models;
|
||||
using DotNet.Testcontainers.Builders;
|
||||
using DotNet.Testcontainers.Configurations;
|
||||
using JetBrains.Annotations;
|
||||
|
||||
namespace WireMock.Net.Testcontainers;
|
||||
|
||||
/// <inheritdoc cref="ContainerConfiguration" />
|
||||
[PublicAPI]
|
||||
public sealed class WireMockConfiguration : ContainerConfiguration
|
||||
{
|
||||
#pragma warning disable CS1591
|
||||
public string? Username { get; }
|
||||
|
||||
public string? Password { get; }
|
||||
|
||||
public bool HasBasicAuthentication => !string.IsNullOrEmpty(Username) && !string.IsNullOrEmpty(Password);
|
||||
|
||||
public WireMockConfiguration(
|
||||
string? username = null,
|
||||
string? password = null
|
||||
)
|
||||
{
|
||||
Username = username;
|
||||
Password = password;
|
||||
}
|
||||
#pragma warning restore CS1591
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="WireMockConfiguration" /> class.
|
||||
/// </summary>
|
||||
/// <param name="resourceConfiguration">The Docker resource configuration.</param>
|
||||
public WireMockConfiguration(IResourceConfiguration<CreateContainerParameters> resourceConfiguration) : base(resourceConfiguration)
|
||||
{
|
||||
// Passes the configuration upwards to the base implementations to create an updated immutable copy.
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="WireMockConfiguration" /> class.
|
||||
/// </summary>
|
||||
/// <param name="resourceConfiguration">The Docker resource configuration.</param>
|
||||
public WireMockConfiguration(IContainerConfiguration resourceConfiguration) : base(resourceConfiguration)
|
||||
{
|
||||
// Passes the configuration upwards to the base implementations to create an updated immutable copy.
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="WireMockConfiguration" /> class.
|
||||
/// </summary>
|
||||
/// <param name="resourceConfiguration">The Docker resource configuration.</param>
|
||||
public WireMockConfiguration(WireMockConfiguration resourceConfiguration) : this(new WireMockConfiguration(), resourceConfiguration)
|
||||
{
|
||||
// Passes the configuration upwards to the base implementations to create an updated immutable copy.
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="WireMockConfiguration" /> class.
|
||||
/// </summary>
|
||||
/// <param name="oldValue">The old Docker resource configuration.</param>
|
||||
/// <param name="newValue">The new Docker resource configuration.</param>
|
||||
public WireMockConfiguration(WireMockConfiguration oldValue, WireMockConfiguration newValue) : base(oldValue, newValue)
|
||||
{
|
||||
Username = BuildConfiguration.Combine(oldValue.Username, newValue.Username);
|
||||
Password = BuildConfiguration.Combine(oldValue.Password, newValue.Password);
|
||||
}
|
||||
}
|
||||
110
src/WireMock.Net.Testcontainers/WireMockContainer.cs
Normal file
110
src/WireMock.Net.Testcontainers/WireMockContainer.cs
Normal file
@@ -0,0 +1,110 @@
|
||||
using System;
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Text;
|
||||
using DotNet.Testcontainers.Containers;
|
||||
using JetBrains.Annotations;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using RestEase;
|
||||
using Stef.Validation;
|
||||
using WireMock.Client;
|
||||
|
||||
namespace WireMock.Net.Testcontainers;
|
||||
|
||||
/// <summary>
|
||||
/// A container for running WireMock in a docker environment.
|
||||
/// </summary>
|
||||
public sealed class WireMockContainer : DockerContainer
|
||||
{
|
||||
internal const int ContainerPort = 80;
|
||||
|
||||
private readonly WireMockConfiguration _configuration;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="WireMockContainer" /> class.
|
||||
/// </summary>
|
||||
/// <param name="configuration">The container configuration.</param>
|
||||
/// <param name="logger">The logger.</param>
|
||||
public WireMockContainer(WireMockConfiguration configuration, ILogger logger) : base(configuration, logger)
|
||||
{
|
||||
_configuration = Guard.NotNull(configuration);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the public Url.
|
||||
/// </summary>
|
||||
[PublicAPI]
|
||||
public string GetPublicUrl() => GetPublicUri().ToString();
|
||||
|
||||
/// <summary>
|
||||
/// Create a RestEase Admin client which can be used to call the admin REST endpoint.
|
||||
/// </summary>
|
||||
/// <returns>A <see cref="IWireMockAdminApi"/></returns>
|
||||
[PublicAPI]
|
||||
public IWireMockAdminApi CreateWireMockAdminClient()
|
||||
{
|
||||
ValidateIfRunning();
|
||||
|
||||
var api = RestClient.For<IWireMockAdminApi>(GetPublicUri());
|
||||
|
||||
if (_configuration.HasBasicAuthentication)
|
||||
{
|
||||
api.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(Encoding.ASCII.GetBytes($"{_configuration.Username}:{_configuration.Password}")));
|
||||
}
|
||||
|
||||
return api;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a <see cref="HttpClient"/> which can be used to call this instance.
|
||||
/// <param name="handlers">
|
||||
/// An ordered list of System.Net.Http.DelegatingHandler instances to be invoked
|
||||
/// as an System.Net.Http.HttpRequestMessage travels from the System.Net.Http.HttpClient
|
||||
/// to the network and an System.Net.Http.HttpResponseMessage travels from the network
|
||||
/// back to System.Net.Http.HttpClient. The handlers are invoked in a top-down fashion.
|
||||
/// That is, the first entry is invoked first for an outbound request message but
|
||||
/// last for an inbound response message.
|
||||
/// </param>
|
||||
/// </summary>
|
||||
[PublicAPI]
|
||||
public HttpClient CreateClient(params DelegatingHandler[] handlers)
|
||||
{
|
||||
ValidateIfRunning();
|
||||
|
||||
var client = HttpClientFactory.Create(handlers);
|
||||
client.BaseAddress = GetPublicUri();
|
||||
return client;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a <see cref="HttpClient"/> (one for each URL) which can be used to call this instance.
|
||||
/// <param name="innerHandler">The inner handler represents the destination of the HTTP message channel.</param>
|
||||
/// <param name="handlers">
|
||||
/// An ordered list of System.Net.Http.DelegatingHandler instances to be invoked
|
||||
/// as an System.Net.Http.HttpRequestMessage travels from the System.Net.Http.HttpClient
|
||||
/// to the network and an System.Net.Http.HttpResponseMessage travels from the network
|
||||
/// back to System.Net.Http.HttpClient. The handlers are invoked in a top-down fashion.
|
||||
/// That is, the first entry is invoked first for an outbound request message but
|
||||
/// last for an inbound response message.
|
||||
/// </param>
|
||||
/// </summary>
|
||||
[PublicAPI]
|
||||
public HttpClient CreateClient(HttpMessageHandler innerHandler, params DelegatingHandler[] handlers)
|
||||
{
|
||||
ValidateIfRunning();
|
||||
|
||||
var client = HttpClientFactory.Create(innerHandler, handlers);
|
||||
client.BaseAddress = GetPublicUri();
|
||||
return client;
|
||||
}
|
||||
|
||||
private void ValidateIfRunning()
|
||||
{
|
||||
if (State != TestcontainersStates.Running)
|
||||
{
|
||||
throw new InvalidOperationException("Unable to create HttpClient because the WireMock.Net is not yet running.");
|
||||
}
|
||||
}
|
||||
|
||||
private Uri GetPublicUri() => new UriBuilder(Uri.UriSchemeHttp, Hostname, GetMappedPublicPort(ContainerPort)).Uri;
|
||||
}
|
||||
175
src/WireMock.Net.Testcontainers/WireMockContainerBuilder.cs
Normal file
175
src/WireMock.Net.Testcontainers/WireMockContainerBuilder.cs
Normal file
@@ -0,0 +1,175 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Docker.DotNet.Models;
|
||||
using DotNet.Testcontainers.Builders;
|
||||
using DotNet.Testcontainers.Configurations;
|
||||
using JetBrains.Annotations;
|
||||
using Stef.Validation;
|
||||
using WireMock.Net.Testcontainers.Models;
|
||||
|
||||
namespace WireMock.Net.Testcontainers;
|
||||
|
||||
/// <summary>
|
||||
/// An specific fluent Docker container builder for WireMock.Net
|
||||
/// </summary>
|
||||
public sealed class WireMockContainerBuilder : ContainerBuilder<WireMockContainerBuilder, WireMockContainer, WireMockConfiguration>
|
||||
{
|
||||
private readonly Dictionary<bool, ContainerInfo> _info = new()
|
||||
{
|
||||
{ false, new ContainerInfo("sheyenrath/wiremock.net:latest", "/app/__admin/mappings") },
|
||||
{ true, new ContainerInfo("sheyenrath/wiremock.net-windows:latest", @"c:\app\__admin\mappings") }
|
||||
};
|
||||
|
||||
private const string DefaultLogger = "WireMockConsoleLogger";
|
||||
|
||||
private readonly Lazy<Task<bool>> _isWindowsAsLazy = new(async () =>
|
||||
{
|
||||
using var dockerClientConfig = TestcontainersSettings.OS.DockerEndpointAuthConfig.GetDockerClientConfiguration();
|
||||
using var dockerClient = dockerClientConfig.CreateClient();
|
||||
|
||||
var version = await dockerClient.System.GetVersionAsync();
|
||||
return version.Os.IndexOf("Windows", StringComparison.OrdinalIgnoreCase) > -1;
|
||||
});
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ContainerBuilder" /> class.
|
||||
/// </summary>
|
||||
public WireMockContainerBuilder() : this(new WireMockConfiguration())
|
||||
{
|
||||
DockerResourceConfiguration = Init().DockerResourceConfiguration;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Automatically set the correct image (Linux or Windows) for WireMock which to create the container.
|
||||
/// </summary>
|
||||
/// <returns>A configured instance of <see cref="WireMockContainerBuilder"/></returns>
|
||||
[PublicAPI]
|
||||
public WireMockContainerBuilder WithImage()
|
||||
{
|
||||
var isWindows = _isWindowsAsLazy.Value.GetAwaiter().GetResult();
|
||||
return WithImage(_info[isWindows].Image);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the admin username and password for the container (basic authentication).
|
||||
/// </summary>
|
||||
/// <param name="username">The admin username.</param>
|
||||
/// <param name="password">The admin password.</param>
|
||||
/// <returns>A configured instance of <see cref="WireMockContainerBuilder"/></returns>
|
||||
public WireMockContainerBuilder WithAdminUserNameAndPassword(string username, string password)
|
||||
{
|
||||
Guard.NotNull(username);
|
||||
Guard.NotNull(password);
|
||||
|
||||
if (string.IsNullOrEmpty(username) && string.IsNullOrEmpty(password))
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
return Merge(DockerResourceConfiguration, new WireMockConfiguration(username, password))
|
||||
.WithCommand($"--AdminUserName {username}", $"--AdminPassword {password}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Use the WireMockNullLogger.
|
||||
/// </summary>
|
||||
/// <returns>A configured instance of <see cref="WireMockContainerBuilder"/></returns>
|
||||
[PublicAPI]
|
||||
public WireMockContainerBuilder WithNullLogger()
|
||||
{
|
||||
return WithCommand("--WireMockLogger WireMockNullLogger");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Defines if the static mappings should be read at startup (default set to false).
|
||||
/// </summary>
|
||||
/// <returns>A configured instance of <see cref="WireMockContainerBuilder"/></returns>
|
||||
[PublicAPI]
|
||||
public WireMockContainerBuilder WithReadStaticMappings()
|
||||
{
|
||||
return WithCommand("--ReadStaticMappings true");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Watch the static mapping files + folder for changes when running.
|
||||
/// </summary>
|
||||
/// <returns>A configured instance of <see cref="WireMockContainerBuilder"/></returns>
|
||||
[PublicAPI]
|
||||
public WireMockContainerBuilder WithWatchStaticMappings(bool includeSubDirectories)
|
||||
{
|
||||
return WithCommand("--WatchStaticMappings true").WithCommand($"--WatchStaticMappingsInSubdirectories {includeSubDirectories}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Specifies the path for the (static) mapping json files.
|
||||
/// </summary>
|
||||
/// <param name="path">The path</param>
|
||||
/// <returns></returns>
|
||||
[PublicAPI]
|
||||
public WireMockContainerBuilder WithMappings(string path)
|
||||
{
|
||||
Guard.NotNullOrEmpty(path);
|
||||
|
||||
var isWindows = _isWindowsAsLazy.Value.GetAwaiter().GetResult();
|
||||
|
||||
return WithReadStaticMappings().WithBindMount(path, _info[isWindows].MappingsPath);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="WireMockContainerBuilder" /> class.
|
||||
/// </summary>
|
||||
/// <param name="dockerResourceConfiguration">The Docker resource configuration.</param>
|
||||
private WireMockContainerBuilder(WireMockConfiguration dockerResourceConfiguration) : base(dockerResourceConfiguration)
|
||||
{
|
||||
DockerResourceConfiguration = dockerResourceConfiguration;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override WireMockConfiguration DockerResourceConfiguration { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public override WireMockContainer Build()
|
||||
{
|
||||
Validate();
|
||||
|
||||
return new WireMockContainer(DockerResourceConfiguration, TestcontainersSettings.Logger);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override WireMockContainerBuilder Init()
|
||||
{
|
||||
var builder = base.Init();
|
||||
|
||||
// In case no image has been set, set the image using internal logic.
|
||||
if (builder.DockerResourceConfiguration.Image == null)
|
||||
{
|
||||
builder = builder.WithImage();
|
||||
}
|
||||
|
||||
var isWindows = _isWindowsAsLazy.Value.GetAwaiter().GetResult();
|
||||
var waitForContainerOS = isWindows ? Wait.ForWindowsContainer() : Wait.ForUnixContainer();
|
||||
return builder
|
||||
.WithPortBinding(WireMockContainer.ContainerPort, true)
|
||||
.WithCommand($"--WireMockLogger {DefaultLogger}")
|
||||
.WithWaitStrategy(waitForContainerOS.UntilMessageIsLogged("By Stef Heyenrath"));
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override WireMockContainerBuilder Clone(IContainerConfiguration resourceConfiguration)
|
||||
{
|
||||
return Merge(DockerResourceConfiguration, new WireMockConfiguration(resourceConfiguration));
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override WireMockContainerBuilder Clone(IResourceConfiguration<CreateContainerParameters> resourceConfiguration)
|
||||
{
|
||||
return Merge(DockerResourceConfiguration, new WireMockConfiguration(resourceConfiguration));
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override WireMockContainerBuilder Merge(WireMockConfiguration oldValue, WireMockConfiguration newValue)
|
||||
{
|
||||
return new WireMockContainerBuilder(new WireMockConfiguration(oldValue, newValue));
|
||||
}
|
||||
}
|
||||
@@ -26,7 +26,7 @@
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.1.1" PrivateAssets="All" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
<PackageReference Include="Stef.Validation" Version="0.1.1" />
|
||||
<PackageReference Include="xUnit.abstractions" Version="2.0.3" />
|
||||
</ItemGroup>
|
||||
|
||||
17
src/WireMock.Net/.filenesting.json
Normal file
17
src/WireMock.Net/.filenesting.json
Normal file
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"help": "https://go.microsoft.com/fwlink/?linkid=866610",
|
||||
"root": true,
|
||||
|
||||
"dependentFileProviders": {
|
||||
"add": {
|
||||
"addedExtension": {},
|
||||
"pathSegment": {
|
||||
"add": {
|
||||
".*": [
|
||||
".cs"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
29
src/WireMock.Net/Extensions/DictionaryExtensions.cs
Normal file
29
src/WireMock.Net/Extensions/DictionaryExtensions.cs
Normal file
@@ -0,0 +1,29 @@
|
||||
using System.Collections;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using Stef.Validation;
|
||||
|
||||
namespace WireMock.Extensions;
|
||||
|
||||
internal static class DictionaryExtensions
|
||||
{
|
||||
public static bool TryGetStringValue(this IDictionary dictionary, string key, [NotNullWhen(true)] out string? value)
|
||||
{
|
||||
Guard.NotNull(dictionary);
|
||||
|
||||
if (dictionary[key] is string valueIsString)
|
||||
{
|
||||
value = valueIsString;
|
||||
return true;
|
||||
}
|
||||
|
||||
var valueToString = dictionary[key]?.ToString();
|
||||
if (valueToString != null)
|
||||
{
|
||||
value = valueToString;
|
||||
return true;
|
||||
}
|
||||
|
||||
value = default;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -5,12 +5,18 @@ using System.Net.Http;
|
||||
using System.Net.Http.Headers;
|
||||
using Newtonsoft.Json;
|
||||
using Stef.Validation;
|
||||
using WireMock.Constants;
|
||||
using WireMock.Types;
|
||||
|
||||
namespace WireMock.Http;
|
||||
|
||||
internal static class HttpRequestMessageHelper
|
||||
{
|
||||
private static readonly IDictionary<string, bool> ContentLengthHeaderAllowed = new Dictionary<string, bool>(StringComparer.OrdinalIgnoreCase)
|
||||
{
|
||||
{ HttpRequestMethod.HEAD, true }
|
||||
};
|
||||
|
||||
internal static HttpRequestMessage Create(IRequestMessage requestMessage, string url)
|
||||
{
|
||||
Guard.NotNull(requestMessage);
|
||||
@@ -25,21 +31,14 @@ internal static class HttpRequestMessageHelper
|
||||
MediaTypeHeaderValue.TryParse(value, out contentType);
|
||||
}
|
||||
|
||||
switch (requestMessage.BodyData?.DetectedBodyType)
|
||||
httpRequestMessage.Content = requestMessage.BodyData?.DetectedBodyType switch
|
||||
{
|
||||
case BodyType.Bytes:
|
||||
httpRequestMessage.Content = ByteArrayContentHelper.Create(requestMessage.BodyData.BodyAsBytes!, contentType);
|
||||
break;
|
||||
|
||||
case BodyType.Json:
|
||||
httpRequestMessage.Content = StringContentHelper.Create(JsonConvert.SerializeObject(requestMessage.BodyData.BodyAsJson), contentType);
|
||||
break;
|
||||
|
||||
case BodyType.String:
|
||||
case BodyType.FormUrlEncoded:
|
||||
httpRequestMessage.Content = StringContentHelper.Create(requestMessage.BodyData.BodyAsString!, contentType);
|
||||
break;
|
||||
}
|
||||
BodyType.Bytes => ByteArrayContentHelper.Create(requestMessage.BodyData.BodyAsBytes!, contentType),
|
||||
BodyType.Json => StringContentHelper.Create(JsonConvert.SerializeObject(requestMessage.BodyData.BodyAsJson), contentType),
|
||||
BodyType.String => StringContentHelper.Create(requestMessage.BodyData.BodyAsString!, contentType),
|
||||
BodyType.FormUrlEncoded => StringContentHelper.Create(requestMessage.BodyData.BodyAsString!, contentType),
|
||||
_ => httpRequestMessage.Content
|
||||
};
|
||||
|
||||
// Overwrite the host header
|
||||
httpRequestMessage.Headers.Host = new Uri(url).Authority;
|
||||
@@ -50,7 +49,19 @@ internal static class HttpRequestMessageHelper
|
||||
return httpRequestMessage;
|
||||
}
|
||||
|
||||
var excludeHeaders = new List<string> { HttpKnownHeaderNames.Host, HttpKnownHeaderNames.ContentLength };
|
||||
var excludeHeaders = new List<string> { HttpKnownHeaderNames.Host };
|
||||
|
||||
var contentLengthHeaderAllowed = ContentLengthHeaderAllowed.TryGetValue(requestMessage.Method, out var allowed) && allowed;
|
||||
if (contentLengthHeaderAllowed)
|
||||
{
|
||||
// Set Content to empty ByteArray to be able to set the Content-Length on the content in case of a HEAD method.
|
||||
httpRequestMessage.Content ??= new ByteArrayContent(EmptyArray<byte>.Value);
|
||||
}
|
||||
else
|
||||
{
|
||||
excludeHeaders.Add(HttpKnownHeaderNames.ContentLength);
|
||||
}
|
||||
|
||||
if (contentType != null)
|
||||
{
|
||||
// Content-Type should be set on the content
|
||||
|
||||
@@ -74,6 +74,13 @@ public abstract class AbstractJsonPartialMatcher : JsonMatcher
|
||||
}
|
||||
}
|
||||
|
||||
if (input != null &&
|
||||
((value.Type == JTokenType.Guid && input.Type == JTokenType.String) ||
|
||||
(value.Type == JTokenType.String && input.Type == JTokenType.Guid)))
|
||||
{
|
||||
return IsMatch(value.ToString(), input.ToString());
|
||||
}
|
||||
|
||||
if (input == null || value.Type != input.Type)
|
||||
{
|
||||
return false;
|
||||
|
||||
139
src/WireMock.Net/Matchers/GraphQLMatcher.cs
Normal file
139
src/WireMock.Net/Matchers/GraphQLMatcher.cs
Normal file
@@ -0,0 +1,139 @@
|
||||
#if GRAPHQL
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using AnyOfTypes;
|
||||
using GraphQL;
|
||||
using GraphQL.Types;
|
||||
using Newtonsoft.Json;
|
||||
using Stef.Validation;
|
||||
using WireMock.Models;
|
||||
|
||||
namespace WireMock.Matchers;
|
||||
|
||||
/// <summary>
|
||||
/// GrapQLMatcher Schema Matcher
|
||||
/// </summary>
|
||||
/// <inheritdoc cref="IStringMatcher"/>
|
||||
public class GraphQLMatcher : IStringMatcher
|
||||
{
|
||||
private sealed class GraphQLRequest
|
||||
{
|
||||
public string? Query { get; set; }
|
||||
|
||||
public Dictionary<string, object?>? Variables { get; set; }
|
||||
}
|
||||
|
||||
private readonly AnyOf<string, StringPattern>[] _patterns;
|
||||
|
||||
private readonly ISchema _schema;
|
||||
|
||||
/// <inheritdoc />
|
||||
public MatchBehaviour MatchBehaviour { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool ThrowException { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="LinqMatcher"/> class.
|
||||
/// </summary>
|
||||
/// <param name="schema">The schema.</param>
|
||||
/// <param name="matchBehaviour">The match behaviour.</param>
|
||||
/// <param name="throwException">Throw an exception when the internal matching fails because of invalid input.</param>
|
||||
/// <param name="matchOperator">The <see cref="Matchers.MatchOperator"/> to use. (default = "Or")</param>
|
||||
public GraphQLMatcher(AnyOf<string, StringPattern, ISchema> schema, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch, bool throwException = false, MatchOperator matchOperator = MatchOperator.Or)
|
||||
{
|
||||
Guard.NotNull(schema);
|
||||
MatchBehaviour = matchBehaviour;
|
||||
ThrowException = throwException;
|
||||
MatchOperator = matchOperator;
|
||||
|
||||
var patterns = new List<AnyOf<string, StringPattern>>();
|
||||
switch (schema.CurrentType)
|
||||
{
|
||||
case AnyOfType.First:
|
||||
patterns.Add(schema.First);
|
||||
_schema = BuildSchema(schema);
|
||||
break;
|
||||
|
||||
case AnyOfType.Second:
|
||||
patterns.Add(schema.Second);
|
||||
_schema = BuildSchema(schema.Second.Pattern);
|
||||
break;
|
||||
|
||||
case AnyOfType.Third:
|
||||
_schema = schema.Third;
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
_patterns = patterns.ToArray();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public double IsMatch(string? input)
|
||||
{
|
||||
var match = MatchScores.Mismatch;
|
||||
|
||||
try
|
||||
{
|
||||
var graphQLRequest = JsonConvert.DeserializeObject<GraphQLRequest>(input!)!;
|
||||
|
||||
var executionResult = new DocumentExecuter().ExecuteAsync(_ =>
|
||||
{
|
||||
_.ThrowOnUnhandledException = true;
|
||||
|
||||
_.Schema = _schema;
|
||||
_.Query = graphQLRequest.Query;
|
||||
|
||||
if (graphQLRequest.Variables != null)
|
||||
{
|
||||
_.Variables = new Inputs(graphQLRequest.Variables);
|
||||
}
|
||||
}).GetAwaiter().GetResult();
|
||||
|
||||
if (executionResult.Errors == null || executionResult.Errors.Count == 0)
|
||||
{
|
||||
match = MatchScores.Perfect;
|
||||
}
|
||||
else
|
||||
{
|
||||
var exceptions = executionResult.Errors.OfType<Exception>().ToArray();
|
||||
if (exceptions.Length == 1)
|
||||
{
|
||||
throw exceptions[0];
|
||||
}
|
||||
|
||||
throw new AggregateException(exceptions);
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
if (ThrowException)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
return MatchBehaviourHelper.Convert(MatchBehaviour, match);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public AnyOf<string, StringPattern>[] GetPatterns()
|
||||
{
|
||||
return _patterns;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public MatchOperator MatchOperator { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Name => nameof(GraphQLMatcher);
|
||||
|
||||
private static ISchema BuildSchema(string schema)
|
||||
{
|
||||
return Schema.For(schema);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,78 @@
|
||||
using Stef.Validation;
|
||||
using WireMock.Types;
|
||||
using WireMock.Util;
|
||||
|
||||
namespace WireMock.Matchers.Helpers;
|
||||
|
||||
internal static class BodyDataMatchScoreCalculator
|
||||
{
|
||||
public static double CalculateMatchScore(IBodyData? requestMessage, IMatcher matcher)
|
||||
{
|
||||
Guard.NotNull(matcher);
|
||||
|
||||
if (matcher is NotNullOrEmptyMatcher notNullOrEmptyMatcher)
|
||||
{
|
||||
switch (requestMessage?.DetectedBodyType)
|
||||
{
|
||||
case BodyType.Json:
|
||||
case BodyType.String:
|
||||
case BodyType.FormUrlEncoded:
|
||||
return notNullOrEmptyMatcher.IsMatch(requestMessage.BodyAsString);
|
||||
|
||||
case BodyType.Bytes:
|
||||
return notNullOrEmptyMatcher.IsMatch(requestMessage.BodyAsBytes);
|
||||
|
||||
default:
|
||||
return MatchScores.Mismatch;
|
||||
}
|
||||
}
|
||||
|
||||
if (matcher is ExactObjectMatcher exactObjectMatcher)
|
||||
{
|
||||
// If the body is a byte array, try to match.
|
||||
var detectedBodyType = requestMessage?.DetectedBodyType;
|
||||
if (detectedBodyType is BodyType.Bytes or BodyType.String or BodyType.FormUrlEncoded)
|
||||
{
|
||||
return exactObjectMatcher.IsMatch(requestMessage?.BodyAsBytes);
|
||||
}
|
||||
}
|
||||
|
||||
// Check if the matcher is a IObjectMatcher
|
||||
if (matcher is IObjectMatcher objectMatcher)
|
||||
{
|
||||
// If the body is a JSON object, try to match.
|
||||
if (requestMessage?.DetectedBodyType == BodyType.Json)
|
||||
{
|
||||
return objectMatcher.IsMatch(requestMessage.BodyAsJson);
|
||||
}
|
||||
|
||||
// If the body is a byte array, try to match.
|
||||
if (requestMessage?.DetectedBodyType == BodyType.Bytes)
|
||||
{
|
||||
return objectMatcher.IsMatch(requestMessage.BodyAsBytes);
|
||||
}
|
||||
}
|
||||
|
||||
// Check if the matcher is a IStringMatcher
|
||||
if (matcher is IStringMatcher stringMatcher)
|
||||
{
|
||||
// If the body is a Json or a String, use the BodyAsString to match on.
|
||||
if (requestMessage?.DetectedBodyType is BodyType.Json or BodyType.String or BodyType.FormUrlEncoded)
|
||||
{
|
||||
return stringMatcher.IsMatch(requestMessage.BodyAsString);
|
||||
}
|
||||
}
|
||||
|
||||
#if MIMEKIT_XXX
|
||||
if (matcher is MultiPartMatcher multiPartMatcher)
|
||||
{
|
||||
// If the body is a String or MultiPart, use the BodyAsString to match on.
|
||||
if (requestMessage?.DetectedBodyType is BodyType.String or BodyType.MultiPart)
|
||||
{
|
||||
return multiPartMatcher.IsMatch(requestMessage.BodyAsString);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return MatchScores.Mismatch;
|
||||
}
|
||||
}
|
||||
@@ -121,6 +121,32 @@ public class JsonPathMatcher : IStringMatcher, IObjectMatcher
|
||||
|
||||
private double IsMatch(JToken jToken)
|
||||
{
|
||||
return MatchScores.ToScore(_patterns.Select(pattern => jToken.SelectToken(pattern.GetPattern()) != null).ToArray(), MatchOperator);
|
||||
var array = ConvertJTokenToJArrayIfNeeded(jToken);
|
||||
|
||||
return MatchScores.ToScore(_patterns.Select(pattern => array.SelectToken(pattern.GetPattern())?.Any() == true).ToArray(), MatchOperator);
|
||||
}
|
||||
|
||||
// https://github.com/WireMock-Net/WireMock.Net/issues/965
|
||||
// https://stackoverflow.com/questions/66922188/newtonsoft-jsonpath-with-c-sharp-syntax
|
||||
// Filtering using SelectToken() isn't guaranteed to work for objects inside objects -- only objects inside arrays.
|
||||
// So this code checks if it's an JArray, if it's not an array, construct a new JArray.
|
||||
private static JToken ConvertJTokenToJArrayIfNeeded(JToken jToken)
|
||||
{
|
||||
if (jToken.Count() == 1)
|
||||
{
|
||||
var property = jToken.First();
|
||||
var item = property.First();
|
||||
if (item is JArray)
|
||||
{
|
||||
return jToken;
|
||||
}
|
||||
|
||||
return new JObject
|
||||
{
|
||||
[property.Path] = new JArray(item)
|
||||
};
|
||||
}
|
||||
|
||||
return jToken;
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,3 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Linq.Dynamic.Core;
|
||||
using AnyOfTypes;
|
||||
@@ -69,7 +68,7 @@ public class LinqMatcher : IObjectMatcher, IStringMatcher
|
||||
MatchOperator = matchOperator;
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IStringMatcher.IsMatch"/>
|
||||
/// <inheritdoc />
|
||||
public double IsMatch(string? input)
|
||||
{
|
||||
double match = MatchScores.Mismatch;
|
||||
@@ -95,7 +94,7 @@ public class LinqMatcher : IObjectMatcher, IStringMatcher
|
||||
return MatchBehaviourHelper.Convert(MatchBehaviour, match);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IObjectMatcher.IsMatch"/>
|
||||
/// <inheritdoc />
|
||||
public double IsMatch(object? input)
|
||||
{
|
||||
double match = MatchScores.Mismatch;
|
||||
@@ -110,45 +109,19 @@ public class LinqMatcher : IObjectMatcher, IStringMatcher
|
||||
jArray = new JArray { JToken.FromObject(input) };
|
||||
}
|
||||
|
||||
//enumerable = jArray.ToDynamicClassArray();
|
||||
|
||||
//JObject value;
|
||||
//switch (input)
|
||||
//{
|
||||
// case JObject valueAsJObject:
|
||||
// value = valueAsJObject;
|
||||
// break;
|
||||
|
||||
// case { } valueAsObject:
|
||||
// value = JObject.FromObject(valueAsObject);
|
||||
// break;
|
||||
|
||||
// default:
|
||||
// return MatchScores.Mismatch;
|
||||
//}
|
||||
|
||||
// Convert a single object to a Queryable JObject-list with 1 entry.
|
||||
//var queryable1 = new[] { value }.AsQueryable();
|
||||
var queryable = jArray.ToDynamicClassArray().AsQueryable();
|
||||
|
||||
try
|
||||
{
|
||||
// Generate the DynamicLinq select statement.
|
||||
//string dynamicSelect = JsonUtils.GenerateDynamicLinqStatement(value);
|
||||
|
||||
// Execute DynamicLinq Select statement.
|
||||
//var queryable2 = queryable1.Select(dynamicSelect);
|
||||
|
||||
// Use the Any(...) method to check if the result matches.
|
||||
|
||||
var patternsAsStringArray = _patterns.Select(p => p.GetPattern()).ToArray();
|
||||
var scores = patternsAsStringArray.Select(p => queryable.Any(p)).ToArray();
|
||||
|
||||
match = MatchScores.ToScore(_patterns.Select(pattern => queryable.Any(pattern.GetPattern())).ToArray(), MatchOperator);
|
||||
match = MatchScores.ToScore(scores, MatchOperator);
|
||||
|
||||
return MatchBehaviourHelper.Convert(MatchBehaviour, match);
|
||||
}
|
||||
catch (Exception e)
|
||||
catch
|
||||
{
|
||||
if (ThrowException)
|
||||
{
|
||||
@@ -159,7 +132,7 @@ public class LinqMatcher : IObjectMatcher, IStringMatcher
|
||||
return MatchBehaviourHelper.Convert(MatchBehaviour, match);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IStringMatcher.GetPatterns"/>
|
||||
/// <inheritdoc />
|
||||
public AnyOf<string, StringPattern>[] GetPatterns()
|
||||
{
|
||||
return _patterns;
|
||||
@@ -168,6 +141,6 @@ public class LinqMatcher : IObjectMatcher, IStringMatcher
|
||||
/// <inheritdoc />
|
||||
public MatchOperator MatchOperator { get; }
|
||||
|
||||
/// <inheritdoc cref="IMatcher.Name"/>
|
||||
/// <inheritdoc />
|
||||
public string Name => "LinqMatcher";
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
namespace WireMock.Matchers;
|
||||
|
||||
/// <summary>
|
||||
/// MatchBehaviour
|
||||
/// MatchBehaviour (Accept or Reject)
|
||||
/// </summary>
|
||||
public enum MatchBehaviour
|
||||
{
|
||||
|
||||
125
src/WireMock.Net/Matchers/MimePartMatcher.cs
Normal file
125
src/WireMock.Net/Matchers/MimePartMatcher.cs
Normal file
@@ -0,0 +1,125 @@
|
||||
#if MIMEKIT
|
||||
using System;
|
||||
using MimeKit;
|
||||
using WireMock.Matchers.Helpers;
|
||||
using WireMock.Util;
|
||||
|
||||
namespace WireMock.Matchers;
|
||||
|
||||
/// <summary>
|
||||
/// MimePartMatcher
|
||||
/// </summary>
|
||||
public class MimePartMatcher : IMatcher
|
||||
{
|
||||
private readonly Func<MimePart, double>[] _funcs;
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Name => nameof(MimePartMatcher);
|
||||
|
||||
/// <summary>
|
||||
/// ContentType Matcher (image/png; name=image.png.)
|
||||
/// </summary>
|
||||
public IStringMatcher? ContentTypeMatcher { get; }
|
||||
|
||||
/// <summary>
|
||||
/// ContentDisposition Matcher (attachment; filename=image.png)
|
||||
/// </summary>
|
||||
public IStringMatcher? ContentDispositionMatcher { get; }
|
||||
|
||||
/// <summary>
|
||||
/// ContentTransferEncoding Matcher (base64)
|
||||
/// </summary>
|
||||
public IStringMatcher? ContentTransferEncodingMatcher { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Content Matcher
|
||||
/// </summary>
|
||||
public IMatcher? ContentMatcher { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public MatchBehaviour MatchBehaviour { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool ThrowException { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="MimePartMatcher"/> class.
|
||||
/// </summary>
|
||||
public MimePartMatcher(
|
||||
MatchBehaviour matchBehaviour,
|
||||
IStringMatcher? contentTypeMatcher,
|
||||
IStringMatcher? contentDispositionMatcher,
|
||||
IStringMatcher? contentTransferEncodingMatcher,
|
||||
IMatcher? contentMatcher,
|
||||
bool throwException = false
|
||||
)
|
||||
{
|
||||
MatchBehaviour = matchBehaviour;
|
||||
ContentTypeMatcher = contentTypeMatcher;
|
||||
ContentDispositionMatcher = contentDispositionMatcher;
|
||||
ContentTransferEncodingMatcher = contentTransferEncodingMatcher;
|
||||
ContentMatcher = contentMatcher;
|
||||
ThrowException = throwException;
|
||||
|
||||
_funcs = new[]
|
||||
{
|
||||
mp => ContentTypeMatcher?.IsMatch(GetContentTypeAsString(mp.ContentType)) ?? MatchScores.Perfect,
|
||||
mp => ContentDispositionMatcher?.IsMatch(mp.ContentDisposition.ToString().Replace("Content-Disposition: ", string.Empty)) ?? MatchScores.Perfect,
|
||||
mp => ContentTransferEncodingMatcher?.IsMatch(mp.ContentTransferEncoding.ToString().ToLowerInvariant()) ?? MatchScores.Perfect,
|
||||
MatchOnContent
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the specified MimePart is match.
|
||||
/// </summary>
|
||||
/// <param name="mimePart">The MimePart.</param>
|
||||
/// <returns>A value between 0.0 - 1.0 of the similarity.</returns>
|
||||
public double IsMatch(MimePart mimePart)
|
||||
{
|
||||
var match = MatchScores.Mismatch;
|
||||
|
||||
try
|
||||
{
|
||||
if (Array.TrueForAll(_funcs, func => MatchScores.IsPerfect(func(mimePart))))
|
||||
{
|
||||
match = MatchScores.Perfect;
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
if (ThrowException)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
return MatchBehaviourHelper.Convert(MatchBehaviour, match);
|
||||
}
|
||||
|
||||
private double MatchOnContent(MimePart mimePart)
|
||||
{
|
||||
if (ContentMatcher == null)
|
||||
{
|
||||
return MatchScores.Perfect;
|
||||
}
|
||||
|
||||
var bodyParserSettings = new BodyParserSettings
|
||||
{
|
||||
Stream = mimePart.Content.Open(),
|
||||
ContentType = GetContentTypeAsString(mimePart.ContentType),
|
||||
DeserializeJson = true,
|
||||
ContentEncoding = null, // mimePart.ContentType.CharsetEncoding.ToString(),
|
||||
DecompressGZipAndDeflate = true
|
||||
};
|
||||
|
||||
var bodyData = BodyParser.ParseAsync(bodyParserSettings).ConfigureAwait(false).GetAwaiter().GetResult();
|
||||
return BodyDataMatchScoreCalculator.CalculateMatchScore(bodyData, ContentMatcher);
|
||||
}
|
||||
|
||||
private static string? GetContentTypeAsString(ContentType? contentType)
|
||||
{
|
||||
return contentType?.ToString().Replace("Content-Type: ", string.Empty);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -2,7 +2,7 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Stef.Validation;
|
||||
using WireMock.Types;
|
||||
using WireMock.Matchers.Helpers;
|
||||
using WireMock.Util;
|
||||
|
||||
namespace WireMock.Matchers.Request;
|
||||
@@ -149,69 +149,11 @@ public class RequestMessageBodyMatcher : IRequestMatcher
|
||||
return requestMatchResult.AddScore(GetType(), score);
|
||||
}
|
||||
|
||||
private static double CalculateMatchScore(IRequestMessage requestMessage, IMatcher matcher)
|
||||
{
|
||||
if (matcher is NotNullOrEmptyMatcher notNullOrEmptyMatcher)
|
||||
{
|
||||
switch (requestMessage.BodyData?.DetectedBodyType)
|
||||
{
|
||||
case BodyType.Json:
|
||||
case BodyType.String:
|
||||
case BodyType.FormUrlEncoded:
|
||||
return notNullOrEmptyMatcher.IsMatch(requestMessage.BodyData.BodyAsString);
|
||||
|
||||
case BodyType.Bytes:
|
||||
return notNullOrEmptyMatcher.IsMatch(requestMessage.BodyData.BodyAsBytes);
|
||||
|
||||
default:
|
||||
return MatchScores.Mismatch;
|
||||
}
|
||||
}
|
||||
|
||||
if (matcher is ExactObjectMatcher exactObjectMatcher)
|
||||
{
|
||||
// If the body is a byte array, try to match.
|
||||
var detectedBodyType = requestMessage.BodyData?.DetectedBodyType;
|
||||
if (detectedBodyType is BodyType.Bytes or BodyType.String or BodyType.FormUrlEncoded)
|
||||
{
|
||||
return exactObjectMatcher.IsMatch(requestMessage.BodyData?.BodyAsBytes);
|
||||
}
|
||||
}
|
||||
|
||||
// Check if the matcher is a IObjectMatcher
|
||||
if (matcher is IObjectMatcher objectMatcher)
|
||||
{
|
||||
// If the body is a JSON object, try to match.
|
||||
if (requestMessage?.BodyData?.DetectedBodyType == BodyType.Json)
|
||||
{
|
||||
return objectMatcher.IsMatch(requestMessage.BodyData.BodyAsJson);
|
||||
}
|
||||
|
||||
// If the body is a byte array, try to match.
|
||||
if (requestMessage?.BodyData?.DetectedBodyType == BodyType.Bytes)
|
||||
{
|
||||
return objectMatcher.IsMatch(requestMessage.BodyData.BodyAsBytes);
|
||||
}
|
||||
}
|
||||
|
||||
// Check if the matcher is a IStringMatcher
|
||||
if (matcher is IStringMatcher stringMatcher)
|
||||
{
|
||||
// If the body is a Json or a String, use the BodyAsString to match on.
|
||||
if (requestMessage?.BodyData?.DetectedBodyType is BodyType.Json or BodyType.String or BodyType.FormUrlEncoded)
|
||||
{
|
||||
return stringMatcher.IsMatch(requestMessage.BodyData.BodyAsString);
|
||||
}
|
||||
}
|
||||
|
||||
return MatchScores.Mismatch;
|
||||
}
|
||||
|
||||
private double CalculateMatchScore(IRequestMessage requestMessage)
|
||||
{
|
||||
if (Matchers != null)
|
||||
{
|
||||
var matchersResult = Matchers.Select(matcher => CalculateMatchScore(requestMessage, matcher)).ToArray();
|
||||
var matchersResult = Matchers.Select(matcher => BodyDataMatchScoreCalculator.CalculateMatchScore(requestMessage.BodyData, matcher)).ToArray();
|
||||
return MatchScores.ToScore(matchersResult, MatchOperator);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,105 @@
|
||||
using System.Linq;
|
||||
using Stef.Validation;
|
||||
using WireMock.Types;
|
||||
|
||||
namespace WireMock.Matchers.Request;
|
||||
|
||||
/// <summary>
|
||||
/// The request body GraphQL matcher.
|
||||
/// </summary>
|
||||
public class RequestMessageGraphQLMatcher : IRequestMatcher
|
||||
{
|
||||
/// <summary>
|
||||
/// The matchers.
|
||||
/// </summary>
|
||||
public IMatcher[]? Matchers { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="MatchOperator"/>
|
||||
/// </summary>
|
||||
public MatchOperator MatchOperator { get; } = MatchOperator.Or;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="RequestMessageGraphQLMatcher"/> class.
|
||||
/// </summary>
|
||||
/// <param name="matchBehaviour">The match behaviour.</param>
|
||||
/// <param name="schema">The schema.</param>
|
||||
public RequestMessageGraphQLMatcher(MatchBehaviour matchBehaviour, string schema) :
|
||||
this(CreateMatcherArray(matchBehaviour, schema))
|
||||
{
|
||||
}
|
||||
|
||||
#if GRAPHQL
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="RequestMessageGraphQLMatcher"/> class.
|
||||
/// </summary>
|
||||
/// <param name="matchBehaviour">The match behaviour.</param>
|
||||
/// <param name="schema">The schema.</param>
|
||||
public RequestMessageGraphQLMatcher(MatchBehaviour matchBehaviour, GraphQL.Types.ISchema schema) :
|
||||
this(CreateMatcherArray(matchBehaviour, new AnyOfTypes.AnyOf<string, Models.StringPattern, GraphQL.Types.ISchema>(schema)))
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="RequestMessageGraphQLMatcher"/> class.
|
||||
/// </summary>
|
||||
/// <param name="matchers">The matchers.</param>
|
||||
public RequestMessageGraphQLMatcher(params IMatcher[] matchers)
|
||||
{
|
||||
Matchers = Guard.NotNull(matchers);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="RequestMessageGraphQLMatcher"/> class.
|
||||
/// </summary>
|
||||
/// <param name="matchers">The matchers.</param>
|
||||
/// <param name="matchOperator">The <see cref="MatchOperator"/> to use.</param>
|
||||
public RequestMessageGraphQLMatcher(MatchOperator matchOperator, params IMatcher[] matchers)
|
||||
{
|
||||
Matchers = Guard.NotNull(matchers);
|
||||
MatchOperator = matchOperator;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public double GetMatchingScore(IRequestMessage requestMessage, IRequestMatchResult requestMatchResult)
|
||||
{
|
||||
var score = CalculateMatchScore(requestMessage);
|
||||
return requestMatchResult.AddScore(GetType(), score);
|
||||
}
|
||||
|
||||
private static double CalculateMatchScore(IRequestMessage requestMessage, IMatcher matcher)
|
||||
{
|
||||
// Check if the matcher is a IStringMatcher
|
||||
// If the body is a Json or a String, use the BodyAsString to match on.
|
||||
if (matcher is IStringMatcher stringMatcher && requestMessage.BodyData?.DetectedBodyType is BodyType.Json or BodyType.String or BodyType.FormUrlEncoded)
|
||||
{
|
||||
return stringMatcher.IsMatch(requestMessage.BodyData.BodyAsString);
|
||||
}
|
||||
|
||||
return MatchScores.Mismatch;
|
||||
}
|
||||
|
||||
private double CalculateMatchScore(IRequestMessage requestMessage)
|
||||
{
|
||||
if (Matchers == null)
|
||||
{
|
||||
return MatchScores.Mismatch;
|
||||
}
|
||||
|
||||
var matchersResult = Matchers.Select(matcher => CalculateMatchScore(requestMessage, matcher)).ToArray();
|
||||
return MatchScores.ToScore(matchersResult, MatchOperator);
|
||||
}
|
||||
|
||||
#if GRAPHQL
|
||||
private static IMatcher[] CreateMatcherArray(MatchBehaviour matchBehaviour, AnyOfTypes.AnyOf<string, Models.StringPattern, GraphQL.Types.ISchema> schema)
|
||||
{
|
||||
return new[] { new GraphQLMatcher(schema, matchBehaviour) }.Cast<IMatcher>().ToArray();
|
||||
}
|
||||
#else
|
||||
private static IMatcher[] CreateMatcherArray(MatchBehaviour matchBehaviour, object schema)
|
||||
{
|
||||
throw new System.NotSupportedException("The GrapQLMatcher can not be used for .NETStandard1.3 or .NET Framework 4.6.1 or lower.");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Stef.Validation;
|
||||
using WireMock.Http;
|
||||
using WireMock.Util;
|
||||
|
||||
namespace WireMock.Matchers.Request;
|
||||
|
||||
/// <summary>
|
||||
/// The request body MultiPart matcher.
|
||||
/// </summary>
|
||||
public class RequestMessageMultiPartMatcher : IRequestMatcher
|
||||
{
|
||||
/// <summary>
|
||||
/// The matchers.
|
||||
/// </summary>
|
||||
public IMatcher[]? Matchers { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="MatchOperator"/>
|
||||
/// </summary>
|
||||
public MatchOperator MatchOperator { get; } = MatchOperator.Or;
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="MatchBehaviour"/>
|
||||
/// </summary>
|
||||
public MatchBehaviour MatchBehaviour { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="RequestMessageMultiPartMatcher"/> class.
|
||||
/// </summary>
|
||||
/// <param name="matchers">The matchers.</param>
|
||||
public RequestMessageMultiPartMatcher(params IMatcher[] matchers)
|
||||
{
|
||||
Matchers = Guard.NotNull(matchers);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="RequestMessageMultiPartMatcher"/> class.
|
||||
/// </summary>
|
||||
/// <param name="matchBehaviour">The match behaviour.</param>
|
||||
/// <param name="matchOperator">The <see cref="MatchOperator"/> to use.</param>
|
||||
/// <param name="matchers">The matchers.</param>
|
||||
public RequestMessageMultiPartMatcher(MatchBehaviour matchBehaviour, MatchOperator matchOperator, params IMatcher[] matchers)
|
||||
{
|
||||
Matchers = Guard.NotNull(matchers);
|
||||
MatchBehaviour = matchBehaviour;
|
||||
MatchOperator = matchOperator;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public double GetMatchingScore(IRequestMessage requestMessage, IRequestMatchResult requestMatchResult)
|
||||
{
|
||||
#if !MIMEKIT
|
||||
throw new System.NotSupportedException("The MultiPartMatcher can not be used for .NETStandard1.3 or .NET Framework 4.6.1 or lower.");
|
||||
#else
|
||||
var match = MatchScores.Mismatch;
|
||||
|
||||
if (Matchers?.Any() != true)
|
||||
{
|
||||
return requestMatchResult.AddScore(GetType(), match);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var message = MimeKitUtils.GetMimeMessage(requestMessage.BodyData!, requestMessage.Headers![HttpKnownHeaderNames.ContentType].ToString());
|
||||
|
||||
var mimePartMatchers = Matchers.OfType<MimePartMatcher>().ToArray();
|
||||
|
||||
foreach (var mimePart in message.BodyParts.OfType<MimeKit.MimePart>())
|
||||
{
|
||||
var matchesForMimePart = new List<double> { MatchScores.Mismatch };
|
||||
matchesForMimePart.AddRange(mimePartMatchers.Select(matcher => matcher.IsMatch(mimePart)));
|
||||
|
||||
match = matchesForMimePart.Max();
|
||||
|
||||
if (MatchScores.IsPerfect(match))
|
||||
{
|
||||
if (MatchOperator == MatchOperator.Or)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
match = MatchScores.Mismatch;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Empty
|
||||
}
|
||||
|
||||
return requestMatchResult.AddScore(GetType(), match);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -29,17 +29,13 @@ namespace WireMock.Owin.Mappers
|
||||
|
||||
var headers = new Dictionary<string, string[]>();
|
||||
IEnumerable<string>? contentEncodingHeader = null;
|
||||
if (request.Headers.Any())
|
||||
foreach (var header in request.Headers)
|
||||
{
|
||||
headers = new Dictionary<string, string[]>();
|
||||
foreach (var header in request.Headers)
|
||||
{
|
||||
headers.Add(header.Key, header.Value);
|
||||
headers.Add(header.Key, header.Value!);
|
||||
|
||||
if (string.Equals(header.Key, HttpKnownHeaderNames.ContentEncoding, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
contentEncodingHeader = header.Value;
|
||||
}
|
||||
if (string.Equals(header.Key, HttpKnownHeaderNames.ContentEncoding, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
contentEncodingHeader = header.Value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -60,7 +60,7 @@ namespace WireMock.Owin
|
||||
public Task Invoke(IContext ctx)
|
||||
#endif
|
||||
{
|
||||
if (_options.HandleRequestsSynchronously.GetValueOrDefault(true))
|
||||
if (_options.HandleRequestsSynchronously.GetValueOrDefault(false))
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
@@ -216,7 +216,12 @@ namespace WireMock.Owin
|
||||
{
|
||||
try
|
||||
{
|
||||
await webhookSender.SendAsync(httpClientForWebhook, mapping, webhookRequest, request, response).ConfigureAwait(false);
|
||||
var result = await webhookSender.SendAsync(httpClientForWebhook, mapping, webhookRequest, request, response).ConfigureAwait(false);
|
||||
if (!result.IsSuccessStatusCode)
|
||||
{
|
||||
var content = await result.Content.ReadAsStringAsync().ConfigureAwait(false);
|
||||
_options.Logger.Warn($"Sending message to Webhook [{webHookIndex}] from Mapping '{mapping.Guid}' failed. HttpStatusCode: {result.StatusCode} Content: {content}");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
@@ -10,7 +10,7 @@ namespace WireMock.RequestBuilders;
|
||||
/// <summary>
|
||||
/// The BodyRequestBuilder interface.
|
||||
/// </summary>
|
||||
public interface IBodyRequestBuilder : IRequestMatcher
|
||||
public interface IBodyRequestBuilder : IGraphQLRequestBuilder
|
||||
{
|
||||
/// <summary>
|
||||
/// WithBody: IMatcher
|
||||
@@ -103,4 +103,12 @@ public interface IBodyRequestBuilder : IRequestMatcher
|
||||
/// <param name="func">The form-urlencoded values.</param>
|
||||
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
|
||||
IRequestBuilder WithBody(Func<IDictionary<string, string>?, bool> func);
|
||||
|
||||
/// <summary>
|
||||
/// WithBodyAsGraphQLSchema: Body as GraphQL schema as a string.
|
||||
/// </summary>
|
||||
/// <param name="body">The GraphQL schema.</param>
|
||||
/// <param name="matchBehaviour">The match behaviour. (Default is <c>MatchBehaviour.AcceptOnMatch</c>).</param>
|
||||
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
|
||||
IRequestBuilder WithBodyAsGraphQLSchema(string body, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch);
|
||||
}
|
||||
27
src/WireMock.Net/RequestBuilders/IGraphQLRequestBuilder.cs
Normal file
27
src/WireMock.Net/RequestBuilders/IGraphQLRequestBuilder.cs
Normal file
@@ -0,0 +1,27 @@
|
||||
using WireMock.Matchers;
|
||||
|
||||
namespace WireMock.RequestBuilders;
|
||||
|
||||
/// <summary>
|
||||
/// The GraphQLRequestBuilder interface.
|
||||
/// </summary>
|
||||
public interface IGraphQLRequestBuilder : IMultiPartRequestBuilder
|
||||
{
|
||||
/// <summary>
|
||||
/// WithGraphQLSchema: The GraphQL schema as a string.
|
||||
/// </summary>
|
||||
/// <param name="schema">The GraphQL schema.</param>
|
||||
/// <param name="matchBehaviour">The match behaviour. (Default is <c>MatchBehaviour.AcceptOnMatch</c>).</param>
|
||||
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
|
||||
IRequestBuilder WithGraphQLSchema(string schema, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch);
|
||||
|
||||
#if GRAPHQL
|
||||
/// <summary>
|
||||
/// WithGraphQLSchema: The GraphQL schema as a ISchema.
|
||||
/// </summary>
|
||||
/// <param name="schema">The GraphQL schema.</param>
|
||||
/// <param name="matchBehaviour">The match behaviour. (Default is <c>MatchBehaviour.AcceptOnMatch</c>).</param>
|
||||
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
|
||||
IRequestBuilder WithGraphQLSchema(GraphQL.Types.ISchema schema, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch);
|
||||
#endif
|
||||
}
|
||||
@@ -1,5 +1,3 @@
|
||||
using System;
|
||||
using JetBrains.Annotations;
|
||||
using WireMock.Matchers;
|
||||
|
||||
namespace WireMock.RequestBuilders;
|
||||
|
||||
34
src/WireMock.Net/RequestBuilders/IMultiPartRequestBuilder.cs
Normal file
34
src/WireMock.Net/RequestBuilders/IMultiPartRequestBuilder.cs
Normal file
@@ -0,0 +1,34 @@
|
||||
using WireMock.Matchers;
|
||||
using WireMock.Matchers.Request;
|
||||
|
||||
namespace WireMock.RequestBuilders;
|
||||
|
||||
/// <summary>
|
||||
/// The MultiPartRequestBuilder interface.
|
||||
/// </summary>
|
||||
public interface IMultiPartRequestBuilder : IRequestMatcher
|
||||
{
|
||||
/// <summary>
|
||||
/// WithMultiPart: IMatcher
|
||||
/// </summary>
|
||||
/// <param name="matcher">The matcher.</param>
|
||||
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
|
||||
IRequestBuilder WithMultiPart(IMatcher matcher);
|
||||
|
||||
/// <summary>
|
||||
/// WithMultiPart: IMatcher[], MatchBehaviour and MatchOperator
|
||||
/// </summary>
|
||||
/// <param name="matchers">The matchers.</param>
|
||||
/// <param name="matchBehaviour">The <see cref="MatchBehaviour"/> to use.</param>
|
||||
/// <param name="matchOperator">The <see cref="MatchOperator"/> to use.</param>
|
||||
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
|
||||
IRequestBuilder WithMultiPart(IMatcher[] matchers, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch, MatchOperator matchOperator = MatchOperator.Or);
|
||||
|
||||
/// <summary>
|
||||
/// WithMultiPart: MatchBehaviour and IMatcher[]
|
||||
/// </summary>
|
||||
/// <param name="matchBehaviour">The <see cref="MatchBehaviour"/> to use.</param>
|
||||
/// <param name="matchers">The matchers.</param>
|
||||
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
|
||||
IRequestBuilder WithMultiPart(MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch, params IMatcher[] matchers);
|
||||
}
|
||||
@@ -109,4 +109,10 @@ public partial class Request
|
||||
_requestMatchers.Add(new RequestMessageBodyMatcher(Guard.NotNull(func)));
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public IRequestBuilder WithBodyAsGraphQLSchema(string body, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch)
|
||||
{
|
||||
return WithGraphQLSchema(body, matchBehaviour);
|
||||
}
|
||||
}
|
||||
23
src/WireMock.Net/RequestBuilders/Request.WithGraphQL.cs
Normal file
23
src/WireMock.Net/RequestBuilders/Request.WithGraphQL.cs
Normal file
@@ -0,0 +1,23 @@
|
||||
using WireMock.Matchers;
|
||||
using WireMock.Matchers.Request;
|
||||
|
||||
namespace WireMock.RequestBuilders;
|
||||
|
||||
public partial class Request
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public IRequestBuilder WithGraphQLSchema(string schema, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch)
|
||||
{
|
||||
_requestMatchers.Add(new RequestMessageGraphQLMatcher(matchBehaviour, schema));
|
||||
return this;
|
||||
}
|
||||
|
||||
#if GRAPHQL
|
||||
/// <inheritdoc />
|
||||
public IRequestBuilder WithGraphQLSchema(GraphQL.Types.ISchema schema, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch)
|
||||
{
|
||||
_requestMatchers.Add(new RequestMessageGraphQLMatcher(matchBehaviour, schema));
|
||||
return this;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
28
src/WireMock.Net/RequestBuilders/Request.WithMultiPart.cs
Normal file
28
src/WireMock.Net/RequestBuilders/Request.WithMultiPart.cs
Normal file
@@ -0,0 +1,28 @@
|
||||
using WireMock.Matchers;
|
||||
using WireMock.Matchers.Request;
|
||||
|
||||
namespace WireMock.RequestBuilders;
|
||||
|
||||
public partial class Request
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public IRequestBuilder WithMultiPart(IMatcher matcher)
|
||||
{
|
||||
_requestMatchers.Add(new RequestMessageMultiPartMatcher(matcher));
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public IRequestBuilder WithMultiPart(IMatcher[] matchers, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch, MatchOperator matchOperator = MatchOperator.Or)
|
||||
{
|
||||
_requestMatchers.Add(new RequestMessageMultiPartMatcher(matchBehaviour, matchOperator, matchers));
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public IRequestBuilder WithMultiPart(MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch, params IMatcher[] matchers)
|
||||
{
|
||||
_requestMatchers.Add(new RequestMessageMultiPartMatcher(matchBehaviour, MatchOperator.Or, matchers));
|
||||
return this;
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,7 @@ using System.Net;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
#endif
|
||||
using Stef.Validation;
|
||||
using WireMock.Http;
|
||||
using WireMock.Models;
|
||||
using WireMock.Owin;
|
||||
using WireMock.Types;
|
||||
@@ -20,40 +21,40 @@ namespace WireMock;
|
||||
/// </summary>
|
||||
public class RequestMessage : IRequestMessage
|
||||
{
|
||||
/// <inheritdoc cref="IRequestMessage.ClientIP" />
|
||||
/// <inheritdoc />
|
||||
public string ClientIP { get; }
|
||||
|
||||
/// <inheritdoc cref="IRequestMessage.Url" />
|
||||
/// <inheritdoc />
|
||||
public string Url { get; }
|
||||
|
||||
/// <inheritdoc cref="IRequestMessage.AbsoluteUrl" />
|
||||
/// <inheritdoc />
|
||||
public string AbsoluteUrl { get; }
|
||||
|
||||
/// <inheritdoc cref="IRequestMessage.ProxyUrl" />
|
||||
/// <inheritdoc />
|
||||
public string? ProxyUrl { get; set; }
|
||||
|
||||
/// <inheritdoc cref="IRequestMessage.DateTime" />
|
||||
/// <inheritdoc />
|
||||
public DateTime DateTime { get; set; }
|
||||
|
||||
/// <inheritdoc cref="IRequestMessage.Path" />
|
||||
/// <inheritdoc />
|
||||
public string Path { get; }
|
||||
|
||||
/// <inheritdoc cref="IRequestMessage.AbsolutePath" />
|
||||
/// <inheritdoc />
|
||||
public string AbsolutePath { get; }
|
||||
|
||||
/// <inheritdoc cref="IRequestMessage.PathSegments" />
|
||||
/// <inheritdoc />
|
||||
public string[] PathSegments { get; }
|
||||
|
||||
/// <inheritdoc cref="IRequestMessage.AbsolutePathSegments" />
|
||||
/// <inheritdoc />
|
||||
public string[] AbsolutePathSegments { get; }
|
||||
|
||||
/// <inheritdoc cref="IRequestMessage.Method" />
|
||||
/// <inheritdoc />
|
||||
public string Method { get; }
|
||||
|
||||
/// <inheritdoc cref="IRequestMessage.Headers" />
|
||||
/// <inheritdoc />
|
||||
public IDictionary<string, WireMockList<string>>? Headers { get; }
|
||||
|
||||
/// <inheritdoc cref="IRequestMessage.Cookies" />
|
||||
/// <inheritdoc />
|
||||
public IDictionary<string, string>? Cookies { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -61,45 +62,50 @@ public class RequestMessage : IRequestMessage
|
||||
|
||||
/// <inheritdoc />
|
||||
public IDictionary<string, WireMockList<string>>? QueryIgnoreCase { get; }
|
||||
|
||||
/// <inheritdoc cref="IRequestMessage.RawQuery" />
|
||||
|
||||
/// <inheritdoc />
|
||||
public string RawQuery { get; }
|
||||
|
||||
/// <inheritdoc cref="IRequestMessage.BodyData" />
|
||||
/// <inheritdoc />
|
||||
public IBodyData? BodyData { get; }
|
||||
|
||||
/// <inheritdoc cref="IRequestMessage.Body" />
|
||||
public string Body { get; }
|
||||
/// <inheritdoc />
|
||||
public string? Body { get; }
|
||||
|
||||
/// <inheritdoc cref="IRequestMessage.BodyAsJson" />
|
||||
public object BodyAsJson { get; }
|
||||
/// <inheritdoc />
|
||||
public object? BodyAsJson { get; }
|
||||
|
||||
/// <inheritdoc cref="IRequestMessage.BodyAsBytes" />
|
||||
public byte[] BodyAsBytes { get; }
|
||||
/// <inheritdoc />
|
||||
public byte[]? BodyAsBytes { get; }
|
||||
|
||||
/// <inheritdoc cref="IRequestMessage.DetectedBodyType" />
|
||||
public string DetectedBodyType { get; }
|
||||
#if MIMEKIT
|
||||
/// <inheritdoc />
|
||||
public object? BodyAsMimeMessage { get; }
|
||||
#endif
|
||||
|
||||
/// <inheritdoc cref="IRequestMessage.DetectedBodyTypeFromContentType" />
|
||||
public string DetectedBodyTypeFromContentType { get; }
|
||||
/// <inheritdoc />
|
||||
public string? DetectedBodyType { get; }
|
||||
|
||||
/// <inheritdoc cref="IRequestMessage.DetectedCompression" />
|
||||
public string DetectedCompression { get; }
|
||||
/// <inheritdoc />
|
||||
public string? DetectedBodyTypeFromContentType { get; }
|
||||
|
||||
/// <inheritdoc cref="IRequestMessage.Host" />
|
||||
/// <inheritdoc />
|
||||
public string? DetectedCompression { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Host { get; }
|
||||
|
||||
/// <inheritdoc cref="IRequestMessage.Protocol" />
|
||||
/// <inheritdoc />
|
||||
public string Protocol { get; }
|
||||
|
||||
/// <inheritdoc cref="IRequestMessage.Port" />
|
||||
/// <inheritdoc />
|
||||
public int Port { get; }
|
||||
|
||||
/// <inheritdoc cref="IRequestMessage.Origin" />
|
||||
/// <inheritdoc />
|
||||
public string Origin { get; }
|
||||
|
||||
#if USE_ASPNETCORE
|
||||
/// <inheritdoc cref="IRequestMessage.ClientCertificate" />
|
||||
/// <inheritdoc />
|
||||
public X509Certificate2? ClientCertificate { get; }
|
||||
#endif
|
||||
|
||||
@@ -139,11 +145,11 @@ public class RequestMessage : IRequestMessage
|
||||
#if USE_ASPNETCORE
|
||||
, X509Certificate2? clientCertificate = null
|
||||
#endif
|
||||
)
|
||||
)
|
||||
{
|
||||
Guard.NotNull(urlDetails, nameof(urlDetails));
|
||||
Guard.NotNull(method, nameof(method));
|
||||
Guard.NotNull(clientIP, nameof(clientIP));
|
||||
Guard.NotNull(urlDetails);
|
||||
Guard.NotNull(method);
|
||||
Guard.NotNull(clientIP);
|
||||
|
||||
AbsoluteUrl = urlDetails.AbsoluteUrl.ToString();
|
||||
Url = urlDetails.Url.ToString();
|
||||
@@ -166,10 +172,22 @@ public class RequestMessage : IRequestMessage
|
||||
Body = BodyData?.BodyAsString;
|
||||
BodyAsJson = BodyData?.BodyAsJson;
|
||||
BodyAsBytes = BodyData?.BodyAsBytes;
|
||||
|
||||
DetectedBodyType = BodyData?.DetectedBodyType.ToString();
|
||||
DetectedBodyTypeFromContentType = BodyData?.DetectedBodyTypeFromContentType.ToString();
|
||||
DetectedCompression = BodyData?.DetectedCompression;
|
||||
|
||||
#if MIMEKIT
|
||||
try
|
||||
{
|
||||
BodyAsMimeMessage = MimeKitUtils.GetMimeMessage(BodyData, headers![HttpKnownHeaderNames.ContentType].First());
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Ignore exception from MimeMessage.Load
|
||||
}
|
||||
#endif
|
||||
|
||||
Headers = headers?.ToDictionary(header => header.Key, header => new WireMockList<string>(header.Value));
|
||||
Cookies = cookies;
|
||||
RawQuery = urlDetails.Url.Query;
|
||||
@@ -180,12 +198,7 @@ public class RequestMessage : IRequestMessage
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get a query parameter.
|
||||
/// </summary>
|
||||
/// <param name="key">The key.</param>
|
||||
/// <param name="ignoreCase">Defines if the key should be matched using case-ignore.</param>
|
||||
/// <returns>The query parameter.</returns>
|
||||
/// <inheritdoc />
|
||||
public WireMockList<string>? GetParameter(string key, bool ignoreCase = false)
|
||||
{
|
||||
if (Query == null)
|
||||
|
||||
@@ -5,7 +5,6 @@ using System.Net;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using Stef.Validation;
|
||||
using WireMock.Admin.Mappings;
|
||||
using WireMock.Constants;
|
||||
@@ -19,6 +18,8 @@ using WireMock.Settings;
|
||||
using WireMock.Types;
|
||||
using WireMock.Util;
|
||||
|
||||
using static WireMock.Util.CSharpFormatter;
|
||||
|
||||
namespace WireMock.Serialization;
|
||||
|
||||
internal class MappingConverter
|
||||
@@ -46,7 +47,9 @@ internal class MappingConverter
|
||||
var cookieMatchers = request.GetRequestMessageMatchers<RequestMessageCookieMatcher>();
|
||||
var paramsMatchers = request.GetRequestMessageMatchers<RequestMessageParamMatcher>();
|
||||
var methodMatcher = request.GetRequestMessageMatcher<RequestMessageMethodMatcher>();
|
||||
var bodyMatcher = request.GetRequestMessageMatcher<RequestMessageBodyMatcher>();
|
||||
var requestMessageBodyMatcher = request.GetRequestMessageMatcher<RequestMessageBodyMatcher>();
|
||||
var requestMessageGraphQLMatcher = request.GetRequestMessageMatcher<RequestMessageGraphQLMatcher>();
|
||||
var requestMessageMultiPartMatcher = request.GetRequestMessageMatcher<RequestMessageMultiPartMatcher>();
|
||||
|
||||
var sb = new StringBuilder();
|
||||
|
||||
@@ -105,13 +108,50 @@ internal class MappingConverter
|
||||
sb.AppendLine($" .WithCookie(\"{cookieMatcher.Name}\", {ToValueArguments(GetStringArray(cookieMatcher.Matchers!))}, true)");
|
||||
}
|
||||
|
||||
if (bodyMatcher is { Matchers: { } })
|
||||
#if GRAPHQL
|
||||
if (requestMessageGraphQLMatcher is { Matchers: { } })
|
||||
{
|
||||
var wildcardMatcher = bodyMatcher.Matchers.OfType<WildcardMatcher>().FirstOrDefault();
|
||||
if (wildcardMatcher is { } && wildcardMatcher.GetPatterns().Any())
|
||||
if (requestMessageGraphQLMatcher.Matchers.OfType<GraphQLMatcher>().FirstOrDefault() is { } graphQLMatcher && graphQLMatcher.GetPatterns().Any())
|
||||
{
|
||||
sb.AppendLine($" .WithGraphQLSchema({GetString(graphQLMatcher)})");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if MIMEKIT
|
||||
if (requestMessageMultiPartMatcher is { Matchers: { } })
|
||||
{
|
||||
if (requestMessageMultiPartMatcher.Matchers.OfType<MimePartMatcher>().Any())
|
||||
{
|
||||
sb.AppendLine(" // .WithMultiPart() is not yet supported");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (requestMessageBodyMatcher is { Matchers: { } })
|
||||
{
|
||||
if (requestMessageBodyMatcher.Matchers.OfType<WildcardMatcher>().FirstOrDefault() is { } wildcardMatcher && wildcardMatcher.GetPatterns().Any())
|
||||
{
|
||||
sb.AppendLine($" .WithBody({GetString(wildcardMatcher)})");
|
||||
}
|
||||
else if (requestMessageBodyMatcher.Matchers.OfType<JsonPartialMatcher>().FirstOrDefault() is { Value: { } } jsonPartialMatcher)
|
||||
{
|
||||
sb.AppendLine(@$" .WithBody(new JsonPartialMatcher(
|
||||
value: {ToCSharpStringLiteral(jsonPartialMatcher.Value.ToString())},
|
||||
ignoreCase: {ToCSharpBooleanLiteral(jsonPartialMatcher.IgnoreCase)},
|
||||
throwException: {ToCSharpBooleanLiteral(jsonPartialMatcher.ThrowException)},
|
||||
regex: {ToCSharpBooleanLiteral(jsonPartialMatcher.Regex)}
|
||||
))");
|
||||
}
|
||||
else if (requestMessageBodyMatcher.Matchers.OfType<JsonPartialWildcardMatcher>().FirstOrDefault() is { Value: { } } jsonPartialWildcardMatcher)
|
||||
{
|
||||
sb.AppendLine(@$" .WithBody(new JsonPartialWildcardMatcher(
|
||||
value: {ToCSharpStringLiteral(jsonPartialWildcardMatcher.Value.ToString())},
|
||||
ignoreCase: {ToCSharpBooleanLiteral(jsonPartialWildcardMatcher.IgnoreCase)},
|
||||
throwException: {ToCSharpBooleanLiteral(jsonPartialWildcardMatcher.ThrowException)},
|
||||
regex: {ToCSharpBooleanLiteral(jsonPartialWildcardMatcher.Regex)}
|
||||
))");
|
||||
}
|
||||
}
|
||||
|
||||
sb.AppendLine(@" )");
|
||||
@@ -150,18 +190,17 @@ internal class MappingConverter
|
||||
{
|
||||
case BodyType.String:
|
||||
case BodyType.FormUrlEncoded:
|
||||
sb.AppendLine($" .WithBody(\"{EscapeCSharpString(bodyData.BodyAsString)}\")");
|
||||
sb.AppendLine($" .WithBody({ToCSharpStringLiteral(bodyData.BodyAsString)})");
|
||||
break;
|
||||
case BodyType.Json:
|
||||
if (bodyData.BodyAsJson is string bodyStringValue)
|
||||
{
|
||||
sb.AppendLine($" .WithBody(\"{EscapeCSharpString(bodyStringValue)}\")");
|
||||
sb.AppendLine($" .WithBody({ToCSharpStringLiteral(bodyStringValue)})");
|
||||
}
|
||||
else
|
||||
else if (bodyData.BodyAsJson is { } jsonBody)
|
||||
{
|
||||
var serializedBody = JsonConvert.SerializeObject(bodyData.BodyAsJson);
|
||||
var deserializedBody = JToken.Parse(serializedBody);
|
||||
sb.AppendLine($" .WithBodyAsJson({ConvertJsonToAnonymousObjectDefinition(deserializedBody, 2)})");
|
||||
var anonymousObjectDefinition = ConvertToAnonymousObjectDefinition(jsonBody);
|
||||
sb.AppendLine($" .WithBodyAsJson({anonymousObjectDefinition})");
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -200,6 +239,8 @@ internal class MappingConverter
|
||||
var paramsMatchers = request.GetRequestMessageMatchers<RequestMessageParamMatcher>();
|
||||
var methodMatcher = request.GetRequestMessageMatcher<RequestMessageMethodMatcher>();
|
||||
var bodyMatcher = request.GetRequestMessageMatcher<RequestMessageBodyMatcher>();
|
||||
var graphQLMatcher = request.GetRequestMessageMatcher<RequestMessageGraphQLMatcher>();
|
||||
var multiPartMatcher = request.GetRequestMessageMatcher<RequestMessageMultiPartMatcher>();
|
||||
|
||||
var mappingModel = new MappingModel
|
||||
{
|
||||
@@ -285,7 +326,7 @@ internal class MappingConverter
|
||||
mappingModel.Response.Delay = (int?)(response.Delay == Timeout.InfiniteTimeSpan ? TimeSpan.MaxValue.TotalMilliseconds : response.Delay?.TotalMilliseconds);
|
||||
}
|
||||
|
||||
var nonNullableWebHooks = mapping.Webhooks?.Where(wh => wh != null).ToArray() ?? new IWebhook[0];
|
||||
var nonNullableWebHooks = mapping.Webhooks?.Where(wh => wh != null).ToArray() ?? EmptyArray<IWebhook>.Value;
|
||||
if (nonNullableWebHooks.Length == 1)
|
||||
{
|
||||
mappingModel.Webhook = WebhookMapper.Map(nonNullableWebHooks[0]);
|
||||
@@ -295,18 +336,21 @@ internal class MappingConverter
|
||||
mappingModel.Webhooks = mapping.Webhooks.Select(WebhookMapper.Map).ToArray();
|
||||
}
|
||||
|
||||
if (bodyMatcher?.Matchers != null)
|
||||
var bodyMatchers = multiPartMatcher?.Matchers ?? graphQLMatcher?.Matchers ?? bodyMatcher?.Matchers;
|
||||
var matchOperator = multiPartMatcher?.MatchOperator ?? graphQLMatcher?.MatchOperator ?? bodyMatcher?.MatchOperator;
|
||||
|
||||
if (bodyMatchers != null && matchOperator != null)
|
||||
{
|
||||
mappingModel.Request.Body = new BodyModel();
|
||||
|
||||
if (bodyMatcher.Matchers.Length == 1)
|
||||
if (bodyMatchers.Length == 1)
|
||||
{
|
||||
mappingModel.Request.Body.Matcher = _mapper.Map(bodyMatcher.Matchers[0]);
|
||||
mappingModel.Request.Body.Matcher = _mapper.Map(bodyMatchers[0]);
|
||||
}
|
||||
else if (bodyMatcher.Matchers.Length > 1)
|
||||
else if (bodyMatchers.Length > 1)
|
||||
{
|
||||
mappingModel.Request.Body.Matchers = _mapper.Map(bodyMatcher.Matchers);
|
||||
mappingModel.Request.Body.MatchOperator = bodyMatcher.MatchOperator.ToString();
|
||||
mappingModel.Request.Body.Matchers = _mapper.Map(bodyMatchers);
|
||||
mappingModel.Request.Body.MatchOperator = matchOperator.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -406,7 +450,7 @@ internal class MappingConverter
|
||||
|
||||
private static string GetString(IStringMatcher stringMatcher)
|
||||
{
|
||||
return stringMatcher.GetPatterns().Select(p => $"\"{p.GetPattern()}\"").First();
|
||||
return stringMatcher.GetPatterns().Select(p => ToCSharpStringLiteral(p.GetPattern())).First();
|
||||
}
|
||||
|
||||
private static string[] GetStringArray(IReadOnlyList<IStringMatcher> stringMatchers)
|
||||
@@ -459,11 +503,9 @@ internal class MappingConverter
|
||||
|
||||
private static string ToValueArguments(string[]? values, string defaultValue = "")
|
||||
{
|
||||
return values is { } ? string.Join(", ", values.Select(v => $"\"{EscapeCSharpString(v)}\"")) : $"\"{EscapeCSharpString(defaultValue)}\"";
|
||||
return values is { } ? string.Join(", ", values.Select(ToCSharpStringLiteral)) : ToCSharpStringLiteral(defaultValue);
|
||||
}
|
||||
|
||||
private static string? EscapeCSharpString(string? value) => value?.Replace("\"", "\\\"");
|
||||
|
||||
private static WebProxyModel? MapWebProxy(WebProxySettings? settings)
|
||||
{
|
||||
return settings != null ? new WebProxyModel
|
||||
@@ -492,49 +534,4 @@ internal class MappingConverter
|
||||
|
||||
return newDictionary;
|
||||
}
|
||||
|
||||
private static string ConvertJsonToAnonymousObjectDefinition(JToken token, int ind = 0)
|
||||
{
|
||||
return token switch
|
||||
{
|
||||
JArray jArray => FormatArray(jArray, ind),
|
||||
JObject jObject => FormatObject(jObject, ind),
|
||||
JProperty jProperty => $"{jProperty.Name} = {ConvertJsonToAnonymousObjectDefinition(jProperty.Value, ind)}",
|
||||
JValue jValue => jValue.Type switch
|
||||
{
|
||||
JTokenType.None => "null",
|
||||
JTokenType.Integer => jValue.Value?.ToString() ?? "null",
|
||||
JTokenType.Float => jValue.Value?.ToString() ?? "null",
|
||||
JTokenType.String => $"\"{EscapeCSharpString(jValue.Value?.ToString())}\"",
|
||||
JTokenType.Boolean => jValue.Value?.ToString()?.ToLower() ?? "null",
|
||||
JTokenType.Null => "null",
|
||||
JTokenType.Undefined => "null",
|
||||
_ => $"UNHANDLED_CASE: {jValue.Type}"
|
||||
},
|
||||
_ => $"UNHANDLED_CASE: {token}"
|
||||
};
|
||||
}
|
||||
|
||||
private static string FormatObject(JObject jObject, int ind)
|
||||
{
|
||||
var indStr = new string(' ', 4 * ind);
|
||||
var indStrSub = new string(' ', 4 * (ind + 1));
|
||||
var items = jObject.Properties().Select(x => ConvertJsonToAnonymousObjectDefinition(x, ind + 1));
|
||||
|
||||
return $"new\r\n{indStr}{{\r\n{indStrSub}{string.Join($",\r\n{indStrSub}", items)}\r\n{indStr}}}";
|
||||
}
|
||||
|
||||
private static string FormatArray(JArray jArray, int ind)
|
||||
{
|
||||
var hasComplexItems = jArray.FirstOrDefault() is JObject or JArray;
|
||||
var items = jArray.Select(x => ConvertJsonToAnonymousObjectDefinition(x, hasComplexItems ? ind + 1 : ind));
|
||||
if (hasComplexItems)
|
||||
{
|
||||
var indStr = new string(' ', 4 * ind);
|
||||
var indStrSub = new string(' ', 4 * (ind + 1));
|
||||
return $"new []\r\n{indStr}{{\r\n{indStrSub}{string.Join($",\r\n{indStrSub}", items)}\r\n{indStr}}}";
|
||||
}
|
||||
|
||||
return $"new [] {{ {string.Join(", ", items)} }}";
|
||||
}
|
||||
}
|
||||
@@ -71,7 +71,15 @@ internal class MatcherMapper
|
||||
|
||||
case nameof(ExactObjectMatcher):
|
||||
return CreateExactObjectMatcher(matchBehaviour, stringPatterns[0], throwExceptionWhenMatcherFails);
|
||||
#if GRAPHQL
|
||||
case nameof(GraphQLMatcher):
|
||||
return new GraphQLMatcher(stringPatterns[0].GetPattern(), matchBehaviour, throwExceptionWhenMatcherFails, matchOperator);
|
||||
#endif
|
||||
|
||||
#if MIMEKIT
|
||||
case nameof(MimePartMatcher):
|
||||
return CreateMimePartMatcher(matchBehaviour, matcher, throwExceptionWhenMatcherFails);
|
||||
#endif
|
||||
case nameof(RegexMatcher):
|
||||
return new RegexMatcher(matchBehaviour, stringPatterns, ignoreCase, throwExceptionWhenMatcherFails, useRegexExtended, matchOperator);
|
||||
|
||||
@@ -123,12 +131,7 @@ internal class MatcherMapper
|
||||
|
||||
public MatcherModel[]? Map(IEnumerable<IMatcher>? matchers)
|
||||
{
|
||||
if (matchers == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return matchers.Where(m => m != null).Select(Map).ToArray()!;
|
||||
return matchers?.Where(m => m != null).Select(Map).ToArray();
|
||||
}
|
||||
|
||||
public MatcherModel? Map(IMatcher? matcher)
|
||||
@@ -192,6 +195,15 @@ internal class MatcherMapper
|
||||
case ExactObjectMatcher exactObjectMatcher:
|
||||
model.Pattern = exactObjectMatcher.ValueAsObject ?? exactObjectMatcher.ValueAsBytes;
|
||||
break;
|
||||
|
||||
#if MIMEKIT
|
||||
case MimePartMatcher mimePartMatcher:
|
||||
model.ContentDispositionMatcher = Map(mimePartMatcher.ContentDispositionMatcher);
|
||||
model.ContentMatcher = Map(mimePartMatcher.ContentMatcher);
|
||||
model.ContentTransferEncodingMatcher = Map(mimePartMatcher.ContentTransferEncodingMatcher);
|
||||
model.ContentTypeMatcher = Map(mimePartMatcher.ContentTypeMatcher);
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
|
||||
return model;
|
||||
@@ -221,7 +233,7 @@ internal class MatcherMapper
|
||||
return new[] { new AnyOf<string, StringPattern>(new StringPattern { Pattern = pattern, PatternAsFile = patternAsFile }) };
|
||||
}
|
||||
|
||||
return new AnyOf<string, StringPattern>[0];
|
||||
return EmptyArray<AnyOf<string, StringPattern>>.Value;
|
||||
}
|
||||
|
||||
private static ExactObjectMatcher CreateExactObjectMatcher(MatchBehaviour matchBehaviour, AnyOf<string, StringPattern> stringPattern, bool throwException)
|
||||
@@ -238,4 +250,16 @@ internal class MatcherMapper
|
||||
|
||||
return new ExactObjectMatcher(matchBehaviour, bytePattern, throwException);
|
||||
}
|
||||
|
||||
#if MIMEKIT
|
||||
private MimePartMatcher CreateMimePartMatcher(MatchBehaviour matchBehaviour, MatcherModel? matcher, bool throwExceptionWhenMatcherFails)
|
||||
{
|
||||
var contentTypeMatcher = Map(matcher?.ContentTypeMatcher) as IStringMatcher;
|
||||
var contentDispositionMatcher = Map(matcher?.ContentDispositionMatcher) as IStringMatcher;
|
||||
var contentTransferEncodingMatcher = Map(matcher?.ContentTransferEncodingMatcher) as IStringMatcher;
|
||||
var contentMatcher = Map(matcher?.ContentMatcher);
|
||||
|
||||
return new MimePartMatcher(matchBehaviour, contentTypeMatcher, contentDispositionMatcher, contentTransferEncodingMatcher, contentMatcher, throwExceptionWhenMatcherFails);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -1,17 +1,21 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using WireMock.Extensions;
|
||||
|
||||
namespace WireMock.Settings;
|
||||
|
||||
// Based on http://blog.gauffin.org/2014/12/simple-command-line-parser/
|
||||
internal class SimpleCommandLineParser
|
||||
internal class SimpleSettingsParser
|
||||
{
|
||||
private const string Sigil = "--";
|
||||
private const string Prefix = $"{nameof(WireMockServerSettings)}__";
|
||||
private static readonly int PrefixLength = Prefix.Length;
|
||||
|
||||
private IDictionary<string, string[]> Arguments { get; } = new Dictionary<string, string[]>(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
public void Parse(string[] arguments)
|
||||
public void Parse(string[] arguments, IDictionary? environment = null)
|
||||
{
|
||||
string currentName = string.Empty;
|
||||
|
||||
@@ -44,6 +48,18 @@ internal class SimpleCommandLineParser
|
||||
{
|
||||
Arguments[currentName] = values.ToArray();
|
||||
}
|
||||
|
||||
// Now also parse environment
|
||||
if (environment != null)
|
||||
{
|
||||
foreach (string key in environment.Keys)
|
||||
{
|
||||
if (key.StartsWith(Prefix, StringComparison.OrdinalIgnoreCase) && environment.TryGetStringValue(key, out var value))
|
||||
{
|
||||
Arguments[key.Substring(PrefixLength)] = value.Split(' ').ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool Contains(string name)
|
||||
@@ -85,7 +101,16 @@ internal class SimpleCommandLineParser
|
||||
return Contains(name);
|
||||
}
|
||||
|
||||
public int? GetIntValue(string name, int? defaultValue = null)
|
||||
public int? GetIntValue(string name)
|
||||
{
|
||||
return GetValue<int?>(name, values =>
|
||||
{
|
||||
var value = values.FirstOrDefault();
|
||||
return !string.IsNullOrEmpty(value) ? int.Parse(value) : null;
|
||||
}, null);
|
||||
}
|
||||
|
||||
public int GetIntValue(string name, int defaultValue)
|
||||
{
|
||||
return GetValue(name, values =>
|
||||
{
|
||||
@@ -22,6 +22,8 @@ namespace WireMock.Settings;
|
||||
/// </summary>
|
||||
public class WireMockServerSettings
|
||||
{
|
||||
internal const int DefaultStartTimeout = 10000;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the http port.
|
||||
/// </summary>
|
||||
@@ -81,7 +83,7 @@ public class WireMockServerSettings
|
||||
/// StartTimeout
|
||||
/// </summary>
|
||||
[PublicAPI]
|
||||
public int StartTimeout { get; set; } = 10000;
|
||||
public int StartTimeout { get; set; } = DefaultStartTimeout;
|
||||
|
||||
/// <summary>
|
||||
/// Allow Partial Mapping (default set to false).
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using System.Collections;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
@@ -18,16 +19,16 @@ public static class WireMockServerSettingsParser
|
||||
/// Parse commandline arguments into WireMockServerSettings.
|
||||
/// </summary>
|
||||
/// <param name="args">The commandline arguments</param>
|
||||
/// <param name="environment">The environment settings (optional)</param>
|
||||
/// <param name="logger">The logger (optional, can be null)</param>
|
||||
/// <param name="settings">The parsed settings</param>
|
||||
[PublicAPI]
|
||||
public static bool TryParseArguments(string[] args, [NotNullWhen(true)] out WireMockServerSettings? settings,
|
||||
IWireMockLogger? logger = null)
|
||||
public static bool TryParseArguments(string[] args, IDictionary? environment, [NotNullWhen(true)] out WireMockServerSettings? settings, IWireMockLogger? logger = null)
|
||||
{
|
||||
Guard.HasNoNulls(args);
|
||||
|
||||
var parser = new SimpleCommandLineParser();
|
||||
parser.Parse(args);
|
||||
var parser = new SimpleSettingsParser();
|
||||
parser.Parse(args, environment);
|
||||
|
||||
if (parser.GetBoolSwitchValue("help"))
|
||||
{
|
||||
@@ -55,6 +56,7 @@ public static class WireMockServerSettingsParser
|
||||
RequestLogExpirationDuration = parser.GetIntValue("RequestLogExpirationDuration"),
|
||||
SaveUnmatchedRequests = parser.GetBoolValue(nameof(WireMockServerSettings.SaveUnmatchedRequests)),
|
||||
StartAdminInterface = parser.GetBoolValue("StartAdminInterface", true),
|
||||
StartTimeout = parser.GetIntValue(nameof(WireMockServerSettings.StartTimeout), WireMockServerSettings.DefaultStartTimeout),
|
||||
ThrowExceptionWhenMatcherFails = parser.GetBoolValue("ThrowExceptionWhenMatcherFails"),
|
||||
UseRegexExtended = parser.GetBoolValue(nameof(WireMockServerSettings.UseRegexExtended), true),
|
||||
WatchStaticMappings = parser.GetBoolValue("WatchStaticMappings"),
|
||||
@@ -79,8 +81,7 @@ public static class WireMockServerSettingsParser
|
||||
return true;
|
||||
}
|
||||
|
||||
private static void ParseLoggerSettings(WireMockServerSettings settings, IWireMockLogger? logger,
|
||||
SimpleCommandLineParser parser)
|
||||
private static void ParseLoggerSettings(WireMockServerSettings settings, IWireMockLogger? logger, SimpleSettingsParser parser)
|
||||
{
|
||||
var loggerType = parser.GetStringValue("WireMockLogger");
|
||||
switch (loggerType)
|
||||
@@ -103,7 +104,7 @@ public static class WireMockServerSettingsParser
|
||||
}
|
||||
}
|
||||
|
||||
private static void ParseProxyAndRecordSettings(WireMockServerSettings settings, SimpleCommandLineParser parser)
|
||||
private static void ParseProxyAndRecordSettings(WireMockServerSettings settings, SimpleSettingsParser parser)
|
||||
{
|
||||
var proxyUrl = parser.GetStringValue("ProxyURL") ?? parser.GetStringValue("ProxyUrl");
|
||||
if (!string.IsNullOrEmpty(proxyUrl))
|
||||
@@ -135,7 +136,7 @@ public static class WireMockServerSettingsParser
|
||||
}
|
||||
}
|
||||
|
||||
private static void ParsePortSettings(WireMockServerSettings settings, SimpleCommandLineParser parser)
|
||||
private static void ParsePortSettings(WireMockServerSettings settings, SimpleSettingsParser parser)
|
||||
{
|
||||
if (parser.Contains(nameof(WireMockServerSettings.Port)))
|
||||
{
|
||||
@@ -147,7 +148,7 @@ public static class WireMockServerSettingsParser
|
||||
}
|
||||
}
|
||||
|
||||
private static void ParseCertificateSettings(WireMockServerSettings settings, SimpleCommandLineParser parser)
|
||||
private static void ParseCertificateSettings(WireMockServerSettings settings, SimpleSettingsParser parser)
|
||||
{
|
||||
var certificateSettings = new WireMockCertificateSettings
|
||||
{
|
||||
@@ -163,7 +164,7 @@ public static class WireMockServerSettingsParser
|
||||
}
|
||||
}
|
||||
|
||||
private static void ParseWebProxyAddressSettings(ProxyAndRecordSettings settings, SimpleCommandLineParser parser)
|
||||
private static void ParseWebProxyAddressSettings(ProxyAndRecordSettings settings, SimpleSettingsParser parser)
|
||||
{
|
||||
string? proxyAddress = parser.GetStringValue("WebProxyAddress");
|
||||
if (!string.IsNullOrEmpty(proxyAddress))
|
||||
@@ -177,7 +178,7 @@ public static class WireMockServerSettingsParser
|
||||
}
|
||||
}
|
||||
|
||||
private static void ParseProxyUrlReplaceSettings(ProxyAndRecordSettings settings, SimpleCommandLineParser parser)
|
||||
private static void ParseProxyUrlReplaceSettings(ProxyAndRecordSettings settings, SimpleSettingsParser parser)
|
||||
{
|
||||
var proxyUrlReplaceOldValue = parser.GetStringValue("ProxyUrlReplaceOldValue");
|
||||
var proxyUrlReplaceNewValue = parser.GetStringValue("ProxyUrlReplaceNewValue");
|
||||
|
||||
180
src/WireMock.Net/Util/CSharpFormatter.cs
Normal file
180
src/WireMock.Net/Util/CSharpFormatter.cs
Normal file
@@ -0,0 +1,180 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace WireMock.Util;
|
||||
|
||||
internal static class CSharpFormatter
|
||||
{
|
||||
#region Reserved Keywords
|
||||
private static readonly HashSet<string> CSharpReservedKeywords = new(new[]
|
||||
{
|
||||
"abstract",
|
||||
"as",
|
||||
"base",
|
||||
"bool",
|
||||
"break",
|
||||
"byte",
|
||||
"case",
|
||||
"catch",
|
||||
"char",
|
||||
"checked",
|
||||
"class",
|
||||
"const",
|
||||
"continue",
|
||||
"decimal",
|
||||
"default",
|
||||
"delegate",
|
||||
"do",
|
||||
"double",
|
||||
"else",
|
||||
"enum",
|
||||
"event",
|
||||
"explicit",
|
||||
"extern",
|
||||
"false",
|
||||
"finally",
|
||||
"fixed",
|
||||
"float",
|
||||
"for",
|
||||
"foreach",
|
||||
"goto",
|
||||
"if",
|
||||
"implicit",
|
||||
"in",
|
||||
"int",
|
||||
"interface",
|
||||
"internal",
|
||||
"is",
|
||||
"lock",
|
||||
"long",
|
||||
"namespace",
|
||||
"new",
|
||||
"null",
|
||||
"object",
|
||||
"operator",
|
||||
"out",
|
||||
"override",
|
||||
"params",
|
||||
"private",
|
||||
"protected",
|
||||
"public",
|
||||
"readonly",
|
||||
"ref",
|
||||
"return",
|
||||
"sbyte",
|
||||
"sealed",
|
||||
"short",
|
||||
"sizeof",
|
||||
"stackalloc",
|
||||
"static",
|
||||
"string",
|
||||
"struct",
|
||||
"switch",
|
||||
"this",
|
||||
"throw",
|
||||
"true",
|
||||
"try",
|
||||
"typeof",
|
||||
"uint",
|
||||
"ulong",
|
||||
"unchecked",
|
||||
"unsafe",
|
||||
"ushort",
|
||||
"using",
|
||||
"virtual",
|
||||
"void",
|
||||
"volatile",
|
||||
"while"
|
||||
});
|
||||
#endregion
|
||||
|
||||
private const string Null = "null";
|
||||
|
||||
public static object ConvertToAnonymousObjectDefinition(object jsonBody)
|
||||
{
|
||||
var serializedBody = JsonConvert.SerializeObject(jsonBody);
|
||||
using var jsonReader = new JsonTextReader(new StringReader(serializedBody));
|
||||
jsonReader.DateParseHandling = DateParseHandling.None;
|
||||
var deserializedBody = JObject.Load(jsonReader);
|
||||
|
||||
return ConvertJsonToAnonymousObjectDefinition(deserializedBody, 2);
|
||||
}
|
||||
|
||||
public static string ConvertJsonToAnonymousObjectDefinition(JToken token, int ind = 0)
|
||||
{
|
||||
return token switch
|
||||
{
|
||||
JArray jArray => FormatArray(jArray, ind),
|
||||
JObject jObject => FormatObject(jObject, ind),
|
||||
JProperty jProperty => $"{FormatPropertyName(jProperty.Name)} = {ConvertJsonToAnonymousObjectDefinition(jProperty.Value, ind)}",
|
||||
JValue jValue => jValue.Type switch
|
||||
{
|
||||
JTokenType.None => Null,
|
||||
JTokenType.Integer => jValue.Value != null ? string.Format(CultureInfo.InvariantCulture, "{0}", jValue.Value) : Null,
|
||||
JTokenType.Float => jValue.Value != null ? string.Format(CultureInfo.InvariantCulture, "{0}", jValue.Value) : Null,
|
||||
JTokenType.String => ToCSharpStringLiteral(jValue.Value?.ToString()),
|
||||
JTokenType.Boolean => jValue.Value != null ? string.Format(CultureInfo.InvariantCulture, "{0}", jValue.Value).ToLower() : Null,
|
||||
JTokenType.Null => Null,
|
||||
JTokenType.Undefined => Null,
|
||||
JTokenType.Date when jValue.Value is DateTime dateValue =>
|
||||
$"DateTime.Parse({ToCSharpStringLiteral(dateValue.ToString("s"))})",
|
||||
_ => $"UNHANDLED_CASE: {jValue.Type}"
|
||||
},
|
||||
_ => $"UNHANDLED_CASE: {token}"
|
||||
};
|
||||
}
|
||||
|
||||
public static string ToCSharpBooleanLiteral(bool value) => value ? "true" : "false";
|
||||
|
||||
public static string ToCSharpStringLiteral(string? value)
|
||||
{
|
||||
if (string.IsNullOrEmpty(value))
|
||||
{
|
||||
return "\"\"";
|
||||
}
|
||||
|
||||
if (value.Contains('\n'))
|
||||
{
|
||||
var escapedValue = value?.Replace("\"", "\"\"") ?? string.Empty;
|
||||
return $"@\"{escapedValue}\"";
|
||||
}
|
||||
else
|
||||
{
|
||||
var escapedValue = value?.Replace("\"", "\\\"") ?? string.Empty;
|
||||
return $"\"{escapedValue}\"";
|
||||
}
|
||||
}
|
||||
|
||||
public static string FormatPropertyName(string propertyName)
|
||||
{
|
||||
return CSharpReservedKeywords.Contains(propertyName) ? "@" + propertyName : propertyName;
|
||||
}
|
||||
|
||||
private static string FormatObject(JObject jObject, int ind)
|
||||
{
|
||||
var indStr = new string(' ', 4 * ind);
|
||||
var indStrSub = new string(' ', 4 * (ind + 1));
|
||||
var items = jObject.Properties().Select(x => ConvertJsonToAnonymousObjectDefinition(x, ind + 1));
|
||||
|
||||
return $"new\r\n{indStr}{{\r\n{indStrSub}{string.Join($",\r\n{indStrSub}", items)}\r\n{indStr}}}";
|
||||
}
|
||||
|
||||
private static string FormatArray(JArray jArray, int ind)
|
||||
{
|
||||
var hasComplexItems = jArray.FirstOrDefault() is JObject or JArray;
|
||||
var items = jArray.Select(x => ConvertJsonToAnonymousObjectDefinition(x, hasComplexItems ? ind + 1 : ind));
|
||||
if (hasComplexItems)
|
||||
{
|
||||
var indStr = new string(' ', 4 * ind);
|
||||
var indStrSub = new string(' ', 4 * (ind + 1));
|
||||
return $"new []\r\n{indStr}{{\r\n{indStrSub}{string.Join($",\r\n{indStrSub}", items)}\r\n{indStr}}}";
|
||||
}
|
||||
|
||||
return $"new [] {{ {string.Join(", ", items)} }}";
|
||||
}
|
||||
}
|
||||
42
src/WireMock.Net/Util/MimeKitUtils.cs
Normal file
42
src/WireMock.Net/Util/MimeKitUtils.cs
Normal file
@@ -0,0 +1,42 @@
|
||||
#if MIMEKIT
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using MimeKit;
|
||||
using WireMock.Http;
|
||||
using WireMock.Types;
|
||||
|
||||
namespace WireMock.Util;
|
||||
|
||||
internal static class MimeKitUtils
|
||||
{
|
||||
public static MimeMessage GetMimeMessage(IBodyData? bodyData, string contentTypeHeaderValue)
|
||||
{
|
||||
var bytes = bodyData?.DetectedBodyType switch
|
||||
{
|
||||
// If the body is bytes, use the BodyAsBytes to match on.
|
||||
BodyType.Bytes => bodyData.BodyAsBytes!,
|
||||
|
||||
// If the body is a String or MultiPart, use the BodyAsString to match on.
|
||||
BodyType.String or BodyType.MultiPart => Encoding.UTF8.GetBytes(bodyData.BodyAsString!),
|
||||
|
||||
_ => throw new NotSupportedException()
|
||||
};
|
||||
|
||||
var fixedBytes = FixBytes(bytes, contentTypeHeaderValue);
|
||||
return MimeMessage.Load(new MemoryStream(fixedBytes));
|
||||
}
|
||||
|
||||
private static byte[] FixBytes(byte[] bytes, WireMockList<string> contentType)
|
||||
{
|
||||
var contentTypeBytes = Encoding.UTF8.GetBytes($"{HttpKnownHeaderNames.ContentType}: {contentType}\r\n\r\n");
|
||||
|
||||
var result = new byte[contentTypeBytes.Length + bytes.Length];
|
||||
|
||||
Buffer.BlockCopy(contentTypeBytes, 0, result, 0, contentTypeBytes.Length);
|
||||
Buffer.BlockCopy(bytes, 0, result, contentTypeBytes.Length, bytes.Length);
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
12
src/WireMock.Net/Util/StreamUtils.cs
Normal file
12
src/WireMock.Net/Util/StreamUtils.cs
Normal file
@@ -0,0 +1,12 @@
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
|
||||
namespace WireMock.Util;
|
||||
|
||||
internal static class StreamUtils
|
||||
{
|
||||
public static Stream CreateStream(string s)
|
||||
{
|
||||
return new MemoryStream(Encoding.UTF8.GetBytes(s));
|
||||
}
|
||||
}
|
||||
@@ -50,16 +50,20 @@
|
||||
<DefineConstants>$(DefineConstants);OPENAPIPARSER</DefineConstants>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(TargetFramework)' != 'netstandard1.3' and '$(TargetFramework)' != 'net451' and '$(TargetFramework)' != 'net452' and '$(TargetFramework)' != 'net46' and '$(TargetFramework)' != 'net461'">
|
||||
<DefineConstants>$(DefineConstants);GRAPHQL;MIMEKIT</DefineConstants>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Remove="Matchers\MultiPartMatcher.cs" />
|
||||
<Compile Remove="Util\FileSystemWatcherExtensions.cs" />
|
||||
<Compile Remove="Matchers\Request\IRequestMatcher.cs" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="JetBrains.Annotations" Version="2022.3.1" PrivateAssets="All" />
|
||||
<PackageReference Include="JsonConverter.Abstractions" Version="0.4.0" />
|
||||
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.1.1" PrivateAssets="All" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
<PackageReference Include="NJsonSchema.Extensions" Version="0.1.0" />
|
||||
<PackageReference Include="NSwag.Core" Version="13.16.1" />
|
||||
<PackageReference Include="SimMetrics.Net" Version="1.0.5" />
|
||||
@@ -154,6 +158,12 @@
|
||||
<PackageReference Include="Scriban.Signed" Version="5.5.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition="'$(TargetFramework)' != 'netstandard1.3' and '$(TargetFramework)' != 'net451' and '$(TargetFramework)' != 'net452' and '$(TargetFramework)' != 'net46' and '$(TargetFramework)' != 'net461'">
|
||||
<PackageReference Include="GraphQL" Version="7.5.0" />
|
||||
<PackageReference Include="GraphQL.NewtonsoftJson" Version="7.5.0" />
|
||||
<PackageReference Include="MimeKitLite" Version="4.1.0.1" PrivateAssets="all" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition=" '$(TargetFramework)' == 'netcoreapp3.1' ">
|
||||
<PackageReference Include="Nullable" Version="1.3.1">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
@@ -180,13 +190,13 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Handlebars.Net.Helpers" Version="2.3.15" />
|
||||
<PackageReference Include="Handlebars.Net.Helpers.DynamicLinq" Version="2.3.15" />
|
||||
<PackageReference Include="Handlebars.Net.Helpers.Humanizer" Version="2.3.15" />
|
||||
<PackageReference Include="Handlebars.Net.Helpers.Json" Version="2.3.15" />
|
||||
<PackageReference Include="Handlebars.Net.Helpers.Random" Version="2.3.15" />
|
||||
<PackageReference Include="Handlebars.Net.Helpers.XPath" Version="2.3.15" />
|
||||
<PackageReference Include="Handlebars.Net.Helpers.Xeger" Version="2.3.15" />
|
||||
<PackageReference Include="Handlebars.Net.Helpers" Version="2.4.0" />
|
||||
<PackageReference Include="Handlebars.Net.Helpers.DynamicLinq" Version="2.4.0" />
|
||||
<PackageReference Include="Handlebars.Net.Helpers.Humanizer" Version="2.4.0" />
|
||||
<PackageReference Include="Handlebars.Net.Helpers.Json" Version="2.4.0" />
|
||||
<PackageReference Include="Handlebars.Net.Helpers.Random" Version="2.4.0" />
|
||||
<PackageReference Include="Handlebars.Net.Helpers.XPath" Version="2.4.0" />
|
||||
<PackageReference Include="Handlebars.Net.Helpers.Xeger" Version="2.4.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
using System.Collections;
|
||||
using FluentAssertions;
|
||||
using WireMock.Extensions;
|
||||
using Xunit;
|
||||
|
||||
namespace WireMock.Net.Tests.Extensions;
|
||||
|
||||
public class DictionaryExtensionsTests
|
||||
{
|
||||
[Fact]
|
||||
public void TryGetStringValue_WhenKeyExistsAndValueIsString_ReturnsTrueAndStringValue()
|
||||
{
|
||||
// Arrange
|
||||
var dictionary = new Hashtable { { "key", "value" } };
|
||||
|
||||
// Act
|
||||
var result = dictionary.TryGetStringValue("key", out var value);
|
||||
|
||||
// Assert
|
||||
result.Should().BeTrue();
|
||||
value.Should().Be("value");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TryGetStringValue_WhenKeyExistsAndValueIsNotString_ReturnsTrueAndStringValue()
|
||||
{
|
||||
// Arrange
|
||||
var dictionary = new Hashtable { { "key", 123 } };
|
||||
|
||||
// Act
|
||||
var result = dictionary.TryGetStringValue("key", out var value);
|
||||
|
||||
// Assert
|
||||
result.Should().BeTrue();
|
||||
value.Should().Be("123");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TryGetStringValue_WhenKeyDoesNotExist_ReturnsFalseAndNull()
|
||||
{
|
||||
// Arrange
|
||||
var dictionary = new Hashtable { { "otherKey", "value" } };
|
||||
|
||||
// Act
|
||||
var result = dictionary.TryGetStringValue("key", out var value);
|
||||
|
||||
// Assert
|
||||
result.Should().BeFalse();
|
||||
value.Should().BeNull();
|
||||
}
|
||||
}
|
||||
@@ -210,6 +210,36 @@ public class WireMockAssertionsTests : IDisposable
|
||||
.Be($"{string.Join(NewLine, missingValue1Message, missingValue2Message)}{NewLine}");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task HaveReceivedACall_WithHeader_ShouldCheckAllRequests()
|
||||
{
|
||||
// Arrange
|
||||
using var server = WireMockServer.Start();
|
||||
using var client = server.CreateClient();
|
||||
|
||||
// Act 1
|
||||
await client.SendAsync(new HttpRequestMessage(HttpMethod.Get, "/")
|
||||
{
|
||||
Headers =
|
||||
{
|
||||
Authorization = new AuthenticationHeaderValue("Bearer", "invalidToken")
|
||||
}
|
||||
});
|
||||
|
||||
// Act 2
|
||||
await client.SendAsync(new HttpRequestMessage(HttpMethod.Get, "/")
|
||||
{
|
||||
Headers =
|
||||
{
|
||||
Authorization = new AuthenticationHeaderValue("Bearer", "validToken")
|
||||
}
|
||||
});
|
||||
|
||||
// Assert
|
||||
server.Should().HaveReceivedACall().WithHeader("Authorization", "Bearer invalidToken");
|
||||
server.Should().HaveReceivedACall().WithHeader("Authorization", "Bearer validToken");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task HaveReceivedACall_AtUrl_WhenACallWasMadeToUrl_Should_BeOK()
|
||||
{
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
using NFluent;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using FluentAssertions;
|
||||
using WireMock.Http;
|
||||
using WireMock.Models;
|
||||
using WireMock.Types;
|
||||
@@ -160,4 +162,29 @@ public class HttpRequestMessageHelperTests
|
||||
// Assert
|
||||
Check.That(message.Content.Headers.GetValues("Content-Type")).ContainsExactly("application/xml; charset=Ascii");
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("HEAD", true)]
|
||||
[InlineData("GET", false)]
|
||||
[InlineData("PUT", false)]
|
||||
[InlineData("POST", false)]
|
||||
[InlineData("DELETE", false)]
|
||||
[InlineData("TRACE", false)]
|
||||
[InlineData("OPTIONS", false)]
|
||||
[InlineData("CONNECT", false)]
|
||||
[InlineData("PATCH", false)]
|
||||
public void HttpRequestMessageHelper_Create_ContentLengthAllowedForMethod(string method, bool resultShouldBe)
|
||||
{
|
||||
// Arrange
|
||||
var key = "Content-Length";
|
||||
var value = 1234;
|
||||
var headers = new Dictionary<string, string[]> { { key, new[] { "1234" } } };
|
||||
var request = new RequestMessage(new UrlDetails("http://localhost/foo"), method, ClientIp, null, headers);
|
||||
|
||||
// Act
|
||||
var message = HttpRequestMessageHelper.Create(request, "http://url");
|
||||
|
||||
// Assert
|
||||
message.Content?.Headers.ContentLength.Should().Be(resultShouldBe ? value : null);
|
||||
}
|
||||
}
|
||||
@@ -14,6 +14,17 @@
|
||||
},
|
||||
Methods: [
|
||||
GET
|
||||
],
|
||||
Params: [
|
||||
{
|
||||
Name: test,
|
||||
Matchers: [
|
||||
{
|
||||
Name: LinqMatcher,
|
||||
Pattern: it.Length < 10
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
Response: {
|
||||
|
||||
@@ -14,6 +14,17 @@
|
||||
},
|
||||
Methods: [
|
||||
GET
|
||||
],
|
||||
Params: [
|
||||
{
|
||||
Name: test,
|
||||
Matchers: [
|
||||
{
|
||||
Name: LinqMatcher,
|
||||
Pattern: it.Length < 10
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
Response: {
|
||||
|
||||
@@ -6,6 +6,7 @@ using VerifyTests;
|
||||
using VerifyXunit;
|
||||
using WireMock.Handlers;
|
||||
using WireMock.Logging;
|
||||
using WireMock.Matchers;
|
||||
using WireMock.Net.Tests.VerifyExtensions;
|
||||
using WireMock.Owin;
|
||||
using WireMock.RequestBuilders;
|
||||
@@ -65,6 +66,7 @@ public class MappingBuilderTests
|
||||
|
||||
_sut.Given(Request.Create()
|
||||
.WithPath("/foo")
|
||||
.WithParam("test", new LinqMatcher("it.Length < 10"))
|
||||
.UsingGet()
|
||||
)
|
||||
.WithGuid(MappingGuid)
|
||||
|
||||
142
test/WireMock.Net.Tests/Matchers/GraphQLMatcherTests.cs
Normal file
142
test/WireMock.Net.Tests/Matchers/GraphQLMatcherTests.cs
Normal file
@@ -0,0 +1,142 @@
|
||||
#if GRAPHQL
|
||||
using System;
|
||||
using FluentAssertions;
|
||||
using GraphQLParser.Exceptions;
|
||||
using WireMock.Matchers;
|
||||
using WireMock.Models;
|
||||
using Xunit;
|
||||
|
||||
namespace WireMock.Net.Tests.Matchers;
|
||||
|
||||
public class GraphQLMatcherTests
|
||||
{
|
||||
private const string TestSchema = @"
|
||||
input MessageInput {
|
||||
content: String
|
||||
author: String
|
||||
}
|
||||
|
||||
type Message {
|
||||
id: ID!
|
||||
content: String
|
||||
author: String
|
||||
}
|
||||
|
||||
type Mutation {
|
||||
createMessage(input: MessageInput): Message
|
||||
updateMessage(id: ID!, input: MessageInput): Message
|
||||
}
|
||||
|
||||
type Query {
|
||||
greeting:String
|
||||
students:[Student]
|
||||
studentById(id:ID!):Student
|
||||
}
|
||||
|
||||
type Student {
|
||||
id:ID!
|
||||
firstName:String
|
||||
lastName:String
|
||||
fullName:String
|
||||
}";
|
||||
|
||||
[Fact]
|
||||
public void GraphQLMatcher_For_ValidSchema_And_CorrectQuery_IsMatch()
|
||||
{
|
||||
// Arrange
|
||||
var input = "{\"query\":\"{\\r\\n students {\\r\\n fullName\\r\\n id\\r\\n }\\r\\n}\"}";
|
||||
|
||||
// Act
|
||||
var matcher = new GraphQLMatcher(TestSchema);
|
||||
var result = matcher.IsMatch(input);
|
||||
|
||||
// Assert
|
||||
result.Should().Be(MatchScores.Perfect);
|
||||
|
||||
matcher.GetPatterns().Should().Contain(TestSchema);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GraphQLMatcher_For_ValidSchema_And_CorrectGraphQLQuery_IsMatch()
|
||||
{
|
||||
// Arrange
|
||||
var input = @"{
|
||||
""query"": ""query ($sid: ID!)\r\n{\r\n studentById(id: $sid) {\r\n fullName\r\n id\r\n }\r\n}"",
|
||||
""variables"": {
|
||||
""sid"": ""1""
|
||||
}
|
||||
}";
|
||||
// Act
|
||||
var matcher = new GraphQLMatcher(TestSchema);
|
||||
var result = matcher.IsMatch(input);
|
||||
|
||||
// Assert
|
||||
result.Should().Be(MatchScores.Perfect);
|
||||
|
||||
matcher.GetPatterns().Should().Contain(TestSchema);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GraphQLMatcher_For_ValidSchema_And_IncorrectQuery_IsMismatch()
|
||||
{
|
||||
// Arrange
|
||||
var input = @"
|
||||
{
|
||||
students {
|
||||
fullName
|
||||
id
|
||||
abc
|
||||
}
|
||||
}";
|
||||
// Act
|
||||
var matcher = new GraphQLMatcher(TestSchema);
|
||||
var result = matcher.IsMatch(input);
|
||||
|
||||
// Assert
|
||||
result.Should().Be(MatchScores.Mismatch);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GraphQLMatcher_For_ValidSchemaAsStringPattern_And_CorrectQuery_IsMatch()
|
||||
{
|
||||
// Arrange
|
||||
var input = "{\"query\":\"{\\r\\n students {\\r\\n fullName\\r\\n id\\r\\n }\\r\\n}\"}";
|
||||
var schema = new StringPattern
|
||||
{
|
||||
Pattern = TestSchema
|
||||
};
|
||||
|
||||
// Act
|
||||
var matcher = new GraphQLMatcher(schema);
|
||||
var result = matcher.IsMatch(input);
|
||||
|
||||
// Assert
|
||||
result.Should().Be(MatchScores.Perfect);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GraphQLMatcher_For_ValidSchema_And_IncorrectQueryWithError_WithThrowExceptionTrue_ThrowsException()
|
||||
{
|
||||
// Arrange
|
||||
var input = "{\"query\":\"{\\r\\n studentsX {\\r\\n fullName\\r\\n X\\r\\n }\\r\\n}\"}";
|
||||
|
||||
// Act
|
||||
var matcher = new GraphQLMatcher(TestSchema, MatchBehaviour.AcceptOnMatch, true);
|
||||
Action action = () => matcher.IsMatch(input);
|
||||
|
||||
// Assert
|
||||
action.Should().Throw<Exception>();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GraphQLMatcher_For_InvalidSchema_ThrowsGraphQLSyntaxErrorException()
|
||||
{
|
||||
// Act
|
||||
// ReSharper disable once ObjectCreationAsStatement
|
||||
Action action = () => _ = new GraphQLMatcher("in va lid");
|
||||
|
||||
// Assert
|
||||
action.Should().Throw<GraphQLSyntaxErrorException>();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -199,6 +199,27 @@ public class JsonPartialMatcherTests
|
||||
Assert.Equal(0.0, match);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void JsonPartialMatcher_IsMatch_GuidAsString_UsingRegex()
|
||||
{
|
||||
var guid = new Guid("1111238e-b775-44a9-a263-95e570135c94");
|
||||
var matcher = new JsonPartialMatcher(new {
|
||||
Id = 1,
|
||||
Name = "^1111[a-fA-F0-9]{4}(-[a-fA-F0-9]{4}){3}-[a-fA-F0-9]{12}$"
|
||||
}, false, false, true);
|
||||
|
||||
// Act
|
||||
var jObject = new JObject
|
||||
{
|
||||
{ "Id", new JValue(1) },
|
||||
{ "Name", new JValue(guid) }
|
||||
};
|
||||
double match = matcher.IsMatch(jObject);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(1.0, match);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void JsonPartialMatcher_IsMatch_WithIgnoreCaseTrue_JObject()
|
||||
{
|
||||
@@ -281,6 +302,25 @@ public class JsonPartialMatcherTests
|
||||
Assert.Equal(1.0, match);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void JsonPartialMatcher_IsMatch_GuidAsString()
|
||||
{
|
||||
// Assign
|
||||
var guid = Guid.NewGuid();
|
||||
var matcher = new JsonPartialMatcher(new { Id = 1, Name = guid });
|
||||
|
||||
// Act
|
||||
var jObject = new JObject
|
||||
{
|
||||
{ "Id", new JValue(1) },
|
||||
{ "Name", new JValue(guid.ToString()) }
|
||||
};
|
||||
double match = matcher.IsMatch(jObject);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(1.0, match);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void JsonPartialMatcher_IsMatch_WithIgnoreCaseTrue_JObjectAsString()
|
||||
{
|
||||
|
||||
@@ -11,7 +11,7 @@ public class JsonPathMatcherTests
|
||||
[Fact]
|
||||
public void JsonPathMatcher_GetName()
|
||||
{
|
||||
// Assign
|
||||
// Arrange
|
||||
var matcher = new JsonPathMatcher("X");
|
||||
|
||||
// Act
|
||||
@@ -24,7 +24,7 @@ public class JsonPathMatcherTests
|
||||
[Fact]
|
||||
public void JsonPathMatcher_GetPatterns()
|
||||
{
|
||||
// Assign
|
||||
// Arrange
|
||||
var matcher = new JsonPathMatcher("X");
|
||||
|
||||
// Act
|
||||
@@ -37,7 +37,7 @@ public class JsonPathMatcherTests
|
||||
[Fact]
|
||||
public void JsonPathMatcher_IsMatch_ByteArray()
|
||||
{
|
||||
// Assign
|
||||
// Arrange
|
||||
var bytes = EmptyArray<byte>.Value;
|
||||
var matcher = new JsonPathMatcher("");
|
||||
|
||||
@@ -51,7 +51,7 @@ public class JsonPathMatcherTests
|
||||
[Fact]
|
||||
public void JsonPathMatcher_IsMatch_NullString()
|
||||
{
|
||||
// Assign
|
||||
// Arrange
|
||||
string? s = null;
|
||||
var matcher = new JsonPathMatcher("");
|
||||
|
||||
@@ -65,7 +65,7 @@ public class JsonPathMatcherTests
|
||||
[Fact]
|
||||
public void JsonPathMatcher_IsMatch_NullObject()
|
||||
{
|
||||
// Assign
|
||||
// Arrange
|
||||
object? o = null;
|
||||
var matcher = new JsonPathMatcher("");
|
||||
|
||||
@@ -79,7 +79,7 @@ public class JsonPathMatcherTests
|
||||
[Fact]
|
||||
public void JsonPathMatcher_IsMatch_String_Exception_Mismatch()
|
||||
{
|
||||
// Assign
|
||||
// Arrange
|
||||
var matcher = new JsonPathMatcher("xxx");
|
||||
|
||||
// Act
|
||||
@@ -92,7 +92,7 @@ public class JsonPathMatcherTests
|
||||
[Fact]
|
||||
public void JsonPathMatcher_IsMatch_Object_Exception_Mismatch()
|
||||
{
|
||||
// Assign
|
||||
// Arrange
|
||||
var matcher = new JsonPathMatcher("");
|
||||
|
||||
// Act
|
||||
@@ -105,7 +105,7 @@ public class JsonPathMatcherTests
|
||||
[Fact]
|
||||
public void JsonPathMatcher_IsMatch_AnonymousObject()
|
||||
{
|
||||
// Assign
|
||||
// Arrange
|
||||
var matcher = new JsonPathMatcher("$..[?(@.Id == 1)]");
|
||||
|
||||
// Act
|
||||
@@ -115,10 +115,51 @@ public class JsonPathMatcherTests
|
||||
Check.That(match).IsEqualTo(1);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void JsonPathMatcher_IsMatch_AnonymousObject_WithNestedObject()
|
||||
{
|
||||
// Arrange
|
||||
var matcher = new JsonPathMatcher("$.things[?(@.name == 'x')]");
|
||||
|
||||
// Act
|
||||
double match = matcher.IsMatch(new { things = new { name = "x" } });
|
||||
|
||||
// Assert
|
||||
Check.That(match).IsEqualTo(1);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void JsonPathMatcher_IsMatch_String_WithNestedObject()
|
||||
{
|
||||
// Arrange
|
||||
var json = "{ \"things\": { \"name\": \"x\" } }";
|
||||
var matcher = new JsonPathMatcher("$.things[?(@.name == 'x')]");
|
||||
|
||||
// Act
|
||||
double match = matcher.IsMatch(json);
|
||||
|
||||
// Assert
|
||||
Check.That(match).IsEqualTo(1);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void JsonPathMatcher_IsNoMatch_String_WithNestedObject()
|
||||
{
|
||||
// Arrange
|
||||
var json = "{ \"things\": { \"name\": \"y\" } }";
|
||||
var matcher = new JsonPathMatcher("$.things[?(@.name == 'x')]");
|
||||
|
||||
// Act
|
||||
double match = matcher.IsMatch(json);
|
||||
|
||||
// Assert
|
||||
Check.That(match).IsEqualTo(0);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void JsonPathMatcher_IsMatch_JObject()
|
||||
{
|
||||
// Assign
|
||||
// Arrange
|
||||
string[] patterns = { "$..[?(@.Id == 1)]" };
|
||||
var matcher = new JsonPathMatcher(patterns);
|
||||
|
||||
@@ -137,7 +178,7 @@ public class JsonPathMatcherTests
|
||||
[Fact]
|
||||
public void JsonPathMatcher_IsMatch_JObject_Parsed()
|
||||
{
|
||||
// Assign
|
||||
// Arrange
|
||||
var matcher = new JsonPathMatcher("$..[?(@.Id == 1)]");
|
||||
|
||||
// Act
|
||||
@@ -150,7 +191,7 @@ public class JsonPathMatcherTests
|
||||
[Fact]
|
||||
public void JsonPathMatcher_IsMatch_RejectOnMatch()
|
||||
{
|
||||
// Assign
|
||||
// Arrange
|
||||
var matcher = new JsonPathMatcher(MatchBehaviour.RejectOnMatch, false, MatchOperator.Or, "$..[?(@.Id == 1)]");
|
||||
|
||||
// Act
|
||||
|
||||
99
test/WireMock.Net.Tests/Matchers/MimePartMatcherTests.cs
Normal file
99
test/WireMock.Net.Tests/Matchers/MimePartMatcherTests.cs
Normal file
@@ -0,0 +1,99 @@
|
||||
#if MIMEKIT
|
||||
using System;
|
||||
using System.Linq;
|
||||
using FluentAssertions;
|
||||
using MimeKit;
|
||||
using WireMock.Matchers;
|
||||
using WireMock.Util;
|
||||
using Xunit;
|
||||
|
||||
namespace WireMock.Net.Tests.Matchers;
|
||||
|
||||
public class MimePartMatcherTests
|
||||
{
|
||||
private const string TestMultiPart = @"From:
|
||||
Date: Sun, 23 Jul 2023 16:13:13 +0200
|
||||
Subject:
|
||||
Message-Id: <HZ3K1HEAJKU4.IO57XCVO4BWV@desktop-6dd5qi2>
|
||||
MIME-Version: 1.0
|
||||
Content-Type: multipart/mixed; boundary=""=-5XgmpXt0XOfzdtcgNJc2ZQ==""
|
||||
|
||||
--=-5XgmpXt0XOfzdtcgNJc2ZQ==
|
||||
Content-Type: text/plain; charset=utf-8
|
||||
|
||||
This is some plain text
|
||||
--=-5XgmpXt0XOfzdtcgNJc2ZQ==
|
||||
Content-Type: text/json; charset=utf-8
|
||||
|
||||
{
|
||||
""Key"": ""Value""
|
||||
}
|
||||
--=-5XgmpXt0XOfzdtcgNJc2ZQ==
|
||||
Content-Type: image/png; name=image.png
|
||||
Content-Disposition: attachment; filename=image.png
|
||||
Content-Transfer-Encoding: base64
|
||||
|
||||
iVBORw0KGgoAAAANSUhEUgAAAAIAAAACAgMAAAAP2OW3AAAADFBMVEX/tID/vpH/pWX/sHidUyjl
|
||||
AAAADElEQVR4XmMQYNgAAADkAMHebX3mAAAAAElFTkSuQmCC
|
||||
|
||||
--=-5XgmpXt0XOfzdtcgNJc2ZQ==--
|
||||
";
|
||||
|
||||
[Fact]
|
||||
public void MimePartMatcher_IsMatch_Part_TextPlain()
|
||||
{
|
||||
// Arrange
|
||||
var message = MimeMessage.Load(StreamUtils.CreateStream(TestMultiPart));
|
||||
var part = (MimePart)message.BodyParts.ToArray()[0];
|
||||
|
||||
// Act
|
||||
var contentTypeMatcher = new ContentTypeMatcher("text/plain");
|
||||
var contentMatcher = new ExactMatcher("This is some plain text");
|
||||
|
||||
var matcher = new MimePartMatcher(MatchBehaviour.AcceptOnMatch, contentTypeMatcher, null, null, contentMatcher);
|
||||
var result = matcher.IsMatch(part);
|
||||
|
||||
// Assert
|
||||
matcher.Name.Should().Be("MimePartMatcher");
|
||||
result.Should().Be(MatchScores.Perfect);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void MimePartMatcher_IsMatch_Part_TextJson()
|
||||
{
|
||||
// Arrange
|
||||
var message = MimeMessage.Load(StreamUtils.CreateStream(TestMultiPart));
|
||||
var part = (MimePart)message.BodyParts.ToArray()[1];
|
||||
|
||||
// Act
|
||||
var contentTypeMatcher = new ContentTypeMatcher("text/json");
|
||||
var contentMatcher = new JsonMatcher(new { Key = "Value" }, true);
|
||||
|
||||
var matcher = new MimePartMatcher(MatchBehaviour.AcceptOnMatch, contentTypeMatcher, null, null, contentMatcher);
|
||||
var result = matcher.IsMatch(part);
|
||||
|
||||
// Assert
|
||||
result.Should().Be(MatchScores.Perfect);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void MimePartMatcher_IsMatch_Part_ImagePng()
|
||||
{
|
||||
// Arrange
|
||||
var message = MimeMessage.Load(StreamUtils.CreateStream(TestMultiPart));
|
||||
var part = (MimePart)message.BodyParts.ToArray()[2];
|
||||
|
||||
// Act
|
||||
var contentTypeMatcher = new ContentTypeMatcher("image/png");
|
||||
var contentDispositionMatcher = new ExactMatcher("attachment; filename=\"image.png\"");
|
||||
var contentTransferEncodingMatcher = new ExactMatcher("base64");
|
||||
var contentMatcher = new ExactObjectMatcher(Convert.FromBase64String("iVBORw0KGgoAAAANSUhEUgAAAAIAAAACAgMAAAAP2OW3AAAADFBMVEX/tID/vpH/pWX/sHidUyjlAAAADElEQVR4XmMQYNgAAADkAMHebX3mAAAAAElFTkSuQmCC"));
|
||||
|
||||
var matcher = new MimePartMatcher(MatchBehaviour.AcceptOnMatch, contentTypeMatcher, contentDispositionMatcher, contentTransferEncodingMatcher, contentMatcher);
|
||||
var result = matcher.IsMatch(part);
|
||||
|
||||
// Assert
|
||||
result.Should().Be(MatchScores.Perfect);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -42,7 +42,14 @@ public class PactTests
|
||||
})
|
||||
);
|
||||
|
||||
server.SavePact(Path.Combine("../../../", "Pact", "files"), "pact-get.json");
|
||||
var folder = Path.Combine("../../../", "Pact", "files");
|
||||
var file = "pact-get.json";
|
||||
|
||||
// Act
|
||||
server.SavePact(folder, file);
|
||||
|
||||
// Assert
|
||||
File.ReadAllBytes(Path.Combine(folder, file)).Length.Should().BeGreaterThan(1);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -201,6 +208,13 @@ public class PactTests
|
||||
})
|
||||
);
|
||||
|
||||
server.SavePact(Path.Combine("../../../", "Pact", "files"), "pact-multiple.json");
|
||||
var folder = Path.Combine("../../../", "Pact", "files");
|
||||
var file = "pact-multiple.json";
|
||||
|
||||
// Act
|
||||
server.SavePact(folder, file);
|
||||
|
||||
// Assert
|
||||
File.ReadAllBytes(Path.Combine(folder, file)).Length.Should().BeGreaterThan(1);
|
||||
}
|
||||
}
|
||||
@@ -8,9 +8,9 @@ using WireMock.Types;
|
||||
using WireMock.Util;
|
||||
using Xunit;
|
||||
|
||||
namespace WireMock.Net.Tests;
|
||||
namespace WireMock.Net.Tests.RequestBuilders;
|
||||
|
||||
public class RequestTests
|
||||
public class RequestBuilderTests
|
||||
{
|
||||
private const string ClientIp = "::1";
|
||||
|
||||
@@ -1,17 +1,28 @@
|
||||
using System;
|
||||
using FluentAssertions;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using JsonConverter.Abstractions;
|
||||
using Moq;
|
||||
using Newtonsoft.Json;
|
||||
using NFluent;
|
||||
using WireMock.Matchers;
|
||||
using WireMock.Matchers.Request;
|
||||
using WireMock.Models;
|
||||
using WireMock.RequestBuilders;
|
||||
using WireMock.Types;
|
||||
using WireMock.Util;
|
||||
using Xunit;
|
||||
|
||||
namespace WireMock.Net.Tests.RequestBuilders;
|
||||
|
||||
public class RequestBuilderWithBodyTests
|
||||
{
|
||||
private const string ClientIp = "::1";
|
||||
|
||||
[Fact]
|
||||
public void RequestBuilder_WithBody_IMatcher()
|
||||
public void Request_WithBody_IMatcher()
|
||||
{
|
||||
// Assign
|
||||
var matcher = new WildcardMatcher("x");
|
||||
@@ -26,7 +37,7 @@ public class RequestBuilderWithBodyTests
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RequestBuilder_WithBody_IMatchers()
|
||||
public void Request_WithBody_IMatchers()
|
||||
{
|
||||
// Assign
|
||||
var matcher1 = new WildcardMatcher("x");
|
||||
@@ -40,4 +51,409 @@ public class RequestBuilderWithBodyTests
|
||||
matchers.Should().HaveCount(1);
|
||||
((RequestMessageBodyMatcher)matchers[0]).Matchers.Should().Contain(new[] { matcher1, matcher2 });
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Request_WithBody_FuncString()
|
||||
{
|
||||
// Assign
|
||||
var requestBuilder = Request.Create().UsingAnyMethod().WithBody(b => b != null && b.Contains("b"));
|
||||
|
||||
// Act
|
||||
var body = new BodyData
|
||||
{
|
||||
BodyAsString = "b",
|
||||
DetectedBodyType = BodyType.String
|
||||
};
|
||||
var request = new RequestMessage(new UrlDetails("http://localhost/foo"), "POST", ClientIp, body);
|
||||
|
||||
// Assert
|
||||
var requestMatchResult = new RequestMatchResult();
|
||||
Check.That(requestBuilder.GetMatchingScore(request, requestMatchResult)).IsEqualTo(1.0);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Request_WithBody_FuncJson()
|
||||
{
|
||||
// Assign
|
||||
var requestBuilder = Request.Create().UsingAnyMethod().WithBody(b => b != null);
|
||||
|
||||
// Act
|
||||
var body = new BodyData
|
||||
{
|
||||
BodyAsJson = 123,
|
||||
DetectedBodyType = BodyType.Json
|
||||
};
|
||||
var request = new RequestMessage(new UrlDetails("http://localhost/foo"), "POST", ClientIp, body);
|
||||
|
||||
// Assert
|
||||
var requestMatchResult = new RequestMatchResult();
|
||||
Check.That(requestBuilder.GetMatchingScore(request, requestMatchResult)).IsEqualTo(1.0);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Request_WithBody_FuncFormUrlEncoded()
|
||||
{
|
||||
// Assign
|
||||
var requestBuilder = Request.Create().UsingAnyMethod().WithBody((IDictionary<string, string>? values) => values != null);
|
||||
|
||||
// Act
|
||||
var body = new BodyData
|
||||
{
|
||||
BodyAsFormUrlEncoded = new Dictionary<string, string>(),
|
||||
DetectedBodyTypeFromContentType = BodyType.FormUrlEncoded,
|
||||
DetectedBodyType = BodyType.FormUrlEncoded
|
||||
};
|
||||
var request = new RequestMessage(new UrlDetails("http://localhost/foo"), "POST", ClientIp, body);
|
||||
|
||||
// Assert
|
||||
var requestMatchResult = new RequestMatchResult();
|
||||
Check.That(requestBuilder.GetMatchingScore(request, requestMatchResult)).IsEqualTo(1.0);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Request_WithBody_FuncBodyData()
|
||||
{
|
||||
// Assign
|
||||
var requestBuilder = Request.Create().UsingAnyMethod().WithBody((IBodyData? b) => b != null);
|
||||
|
||||
// Act
|
||||
var body = new BodyData
|
||||
{
|
||||
BodyAsJson = 123,
|
||||
DetectedBodyType = BodyType.Json
|
||||
};
|
||||
var request = new RequestMessage(new UrlDetails("http://localhost/foo"), "POST", ClientIp, body);
|
||||
|
||||
// Assert
|
||||
var requestMatchResult = new RequestMatchResult();
|
||||
Check.That(requestBuilder.GetMatchingScore(request, requestMatchResult)).IsEqualTo(1.0);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Request_WithBody_FuncByteArray()
|
||||
{
|
||||
// Assign
|
||||
var requestBuilder = Request.Create().UsingAnyMethod().WithBody((byte[]? b) => b != null);
|
||||
|
||||
// Act
|
||||
var body = new BodyData
|
||||
{
|
||||
BodyAsBytes = new byte[0],
|
||||
DetectedBodyType = BodyType.Bytes
|
||||
};
|
||||
var request = new RequestMessage(new UrlDetails("http://localhost/foo"), "POST", ClientIp, body);
|
||||
|
||||
// Assert
|
||||
var requestMatchResult = new RequestMatchResult();
|
||||
Check.That(requestBuilder.GetMatchingScore(request, requestMatchResult)).IsEqualTo(1.0);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Request_WithBodyExactMatcher()
|
||||
{
|
||||
// Arrange
|
||||
var requestBuilder = Request.Create().UsingAnyMethod().WithBody(new ExactMatcher("cat"));
|
||||
|
||||
// Act
|
||||
var body = new BodyData
|
||||
{
|
||||
BodyAsString = "cat",
|
||||
DetectedBodyType = BodyType.String
|
||||
};
|
||||
var request = new RequestMessage(new UrlDetails("http://localhost/foo"), "POST", ClientIp, body);
|
||||
|
||||
// Assert
|
||||
var requestMatchResult = new RequestMatchResult();
|
||||
Check.That(requestBuilder.GetMatchingScore(request, requestMatchResult)).IsEqualTo(1.0);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Request_WithBody_BodyDataAsString_Using_WildcardMatcher()
|
||||
{
|
||||
// Arrange
|
||||
var spec = Request.Create().WithPath("/foo").UsingAnyMethod().WithBody(new WildcardMatcher("H*o*"));
|
||||
|
||||
// Act
|
||||
var body = new BodyData
|
||||
{
|
||||
BodyAsString = "Hello world!",
|
||||
DetectedBodyType = BodyType.String
|
||||
};
|
||||
var request = new RequestMessage(new UrlDetails("http://localhost/foo"), "PUT", ClientIp, body);
|
||||
|
||||
// Assert
|
||||
var requestMatchResult = new RequestMatchResult();
|
||||
spec.GetMatchingScore(request, requestMatchResult).Should().Be(1.0);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Request_WithBody_BodyDataAsJson_Using_WildcardMatcher()
|
||||
{
|
||||
// Arrange
|
||||
var spec = Request.Create().WithPath("/foo").UsingAnyMethod().WithBody(new WildcardMatcher("*Hello*"));
|
||||
|
||||
// Act
|
||||
var body = new BodyData
|
||||
{
|
||||
BodyAsJson = new { Hi = "Hello world!" },
|
||||
BodyAsString = "{ Hi = \"Hello world!\" }",
|
||||
DetectedBodyType = BodyType.Json
|
||||
};
|
||||
var request = new RequestMessage(new UrlDetails("http://localhost/foo"), "PUT", ClientIp, body);
|
||||
|
||||
// Assert
|
||||
var requestMatchResult = new RequestMatchResult();
|
||||
spec.GetMatchingScore(request, requestMatchResult).Should().Be(1.0);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Request_WithBody_XPathMatcher_true()
|
||||
{
|
||||
// Arrange
|
||||
var spec = Request.Create().UsingAnyMethod().WithBody(new XPathMatcher("/todo-list[count(todo-item) = 3]"));
|
||||
|
||||
// Act
|
||||
var body = new BodyData
|
||||
{
|
||||
BodyAsString = @"
|
||||
<todo-list>
|
||||
<todo-item id='a1'>abc</todo-item>
|
||||
<todo-item id='a2'>def</todo-item>
|
||||
<todo-item id='a3'>xyz</todo-item>
|
||||
</todo-list>",
|
||||
DetectedBodyType = BodyType.String
|
||||
};
|
||||
var request = new RequestMessage(new UrlDetails("http://localhost/foo"), "PUT", ClientIp, body);
|
||||
|
||||
// Assert
|
||||
var requestMatchResult = new RequestMatchResult();
|
||||
Check.That(spec.GetMatchingScore(request, requestMatchResult)).IsEqualTo(1.0);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Request_WithBody_XPathMatcher_false()
|
||||
{
|
||||
// Arrange
|
||||
var spec = Request.Create().UsingAnyMethod().WithBody(new XPathMatcher("/todo-list[count(todo-item) = 99]"));
|
||||
|
||||
// Act
|
||||
var body = new BodyData
|
||||
{
|
||||
BodyAsString = @"
|
||||
<todo-list>
|
||||
<todo-item id='a1'>abc</todo-item>
|
||||
<todo-item id='a2'>def</todo-item>
|
||||
<todo-item id='a3'>xyz</todo-item>
|
||||
</todo-list>",
|
||||
DetectedBodyType = BodyType.String
|
||||
};
|
||||
var request = new RequestMessage(new UrlDetails("http://localhost/foo"), "PUT", ClientIp, body);
|
||||
|
||||
// Assert
|
||||
var requestMatchResult = new RequestMatchResult();
|
||||
Check.That(spec.GetMatchingScore(request, requestMatchResult)).IsNotEqualTo(1.0);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Request_WithBody_JsonPathMatcher_true()
|
||||
{
|
||||
// Arrange
|
||||
var spec = Request.Create().UsingAnyMethod().WithBody(new JsonPathMatcher("$..things[?(@.name == 'RequiredThing')]"));
|
||||
|
||||
// Act
|
||||
var body = new BodyData
|
||||
{
|
||||
BodyAsString = "{ \"things\": [ { \"name\": \"RequiredThing\" }, { \"name\": \"Wiremock\" } ] }",
|
||||
DetectedBodyType = BodyType.String
|
||||
};
|
||||
var request = new RequestMessage(new UrlDetails("http://localhost/foo"), "PUT", ClientIp, body);
|
||||
|
||||
// Assert
|
||||
var requestMatchResult = new RequestMatchResult();
|
||||
Check.That(spec.GetMatchingScore(request, requestMatchResult)).IsEqualTo(1.0);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Request_WithBodyJson_PathMatcher_false()
|
||||
{
|
||||
// Arrange
|
||||
var spec = Request.Create().UsingAnyMethod().WithBody(new JsonPathMatcher("$.things[?(@.name == 'RequiredThing')]"));
|
||||
|
||||
// Act
|
||||
var body = new BodyData
|
||||
{
|
||||
BodyAsString = "{ \"things\": { \"name\": \"Wiremock\" } }",
|
||||
DetectedBodyType = BodyType.String
|
||||
};
|
||||
var request = new RequestMessage(new UrlDetails("http://localhost/foo"), "PUT", ClientIp, body);
|
||||
|
||||
// Assert
|
||||
var requestMatchResult = new RequestMatchResult();
|
||||
Check.That(spec.GetMatchingScore(request, requestMatchResult)).IsNotEqualTo(1.0);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Request_WithBodyAsJson_Object_JsonPathMatcher_true()
|
||||
{
|
||||
// Arrange
|
||||
var spec = Request.Create().UsingAnyMethod().WithBody(new JsonPathMatcher("$..things[?(@.name == 'RequiredThing')]"));
|
||||
|
||||
// Act
|
||||
string jsonString = "{ \"things\": [ { \"name\": \"RequiredThing\" }, { \"name\": \"Wiremock\" } ] }";
|
||||
var bodyData = new BodyData
|
||||
{
|
||||
BodyAsJson = JsonConvert.DeserializeObject(jsonString),
|
||||
BodyAsString = jsonString,
|
||||
Encoding = Encoding.UTF8,
|
||||
DetectedBodyType = BodyType.Json
|
||||
};
|
||||
|
||||
var request = new RequestMessage(new UrlDetails("http://localhost/foo"), "PUT", ClientIp, bodyData);
|
||||
|
||||
// Assert
|
||||
var requestMatchResult = new RequestMatchResult();
|
||||
Check.That(spec.GetMatchingScore(request, requestMatchResult)).IsEqualTo(1.0);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Request_WithBodyAsJson_Array_JsonPathMatcher_1()
|
||||
{
|
||||
// Arrange
|
||||
var spec = Request.Create().UsingAnyMethod().WithBody(new JsonPathMatcher("$..books[?(@.price < 10)]"));
|
||||
|
||||
// Act
|
||||
string jsonString = "{ \"books\": [ { \"category\": \"test1\", \"price\": 8.95 }, { \"category\": \"test2\", \"price\": 20 } ] }";
|
||||
var bodyData = new BodyData
|
||||
{
|
||||
BodyAsJson = JsonConvert.DeserializeObject(jsonString),
|
||||
BodyAsString = jsonString,
|
||||
Encoding = Encoding.UTF8,
|
||||
DetectedBodyType = BodyType.Json
|
||||
};
|
||||
|
||||
var request = new RequestMessage(new UrlDetails("http://localhost/foo"), "PUT", ClientIp, bodyData);
|
||||
|
||||
// Assert
|
||||
var requestMatchResult = new RequestMatchResult();
|
||||
Check.That(spec.GetMatchingScore(request, requestMatchResult)).IsEqualTo(1.0);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Request_WithBodyAsJson_Array_JsonPathMatcher_2()
|
||||
{
|
||||
// Arrange
|
||||
var spec = Request.Create().UsingAnyMethod().WithBody(new JsonPathMatcher("$..[?(@.Id == 1)]"));
|
||||
|
||||
// Act
|
||||
string jsonString = "{ \"Id\": 1, \"Name\": \"Test\" }";
|
||||
var bodyData = new BodyData
|
||||
{
|
||||
BodyAsJson = JsonConvert.DeserializeObject(jsonString),
|
||||
BodyAsString = jsonString,
|
||||
Encoding = Encoding.UTF8,
|
||||
DetectedBodyType = BodyType.Json
|
||||
};
|
||||
|
||||
var request = new RequestMessage(new UrlDetails("http://localhost/foo"), "PUT", ClientIp, bodyData);
|
||||
|
||||
// Assert
|
||||
var requestMatchResult = new RequestMatchResult();
|
||||
double result = spec.GetMatchingScore(request, requestMatchResult);
|
||||
Check.That(result).IsEqualTo(1.0);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Request_WithBodyAsObject_ExactObjectMatcher_true()
|
||||
{
|
||||
// Assign
|
||||
object body = DateTime.MinValue;
|
||||
var requestBuilder = Request.Create().UsingAnyMethod().WithBody(body);
|
||||
|
||||
var bodyData = new BodyData
|
||||
{
|
||||
BodyAsJson = DateTime.MinValue,
|
||||
DetectedBodyType = BodyType.Json
|
||||
};
|
||||
|
||||
// Act
|
||||
var request = new RequestMessage(new UrlDetails("http://localhost/foo"), "PUT", ClientIp, bodyData);
|
||||
|
||||
// Assert
|
||||
var requestMatchResult = new RequestMatchResult();
|
||||
Check.That(requestBuilder.GetMatchingScore(request, requestMatchResult)).IsEqualTo(1.0);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Request_WithBodyAsJson_UsingObject()
|
||||
{
|
||||
// Assign
|
||||
object body = new
|
||||
{
|
||||
Test = "abc"
|
||||
};
|
||||
var requestBuilder = Request.Create().UsingAnyMethod().WithBodyAsJson(body);
|
||||
|
||||
var bodyData = new BodyData
|
||||
{
|
||||
BodyAsString = JsonConvert.SerializeObject(body),
|
||||
DetectedBodyType = BodyType.String
|
||||
};
|
||||
|
||||
// Act
|
||||
var request = new RequestMessage(new UrlDetails("http://localhost/foo"), "POST", ClientIp, bodyData);
|
||||
|
||||
// Assert
|
||||
var requestMatchResult = new RequestMatchResult();
|
||||
Check.That(requestBuilder.GetMatchingScore(request, requestMatchResult)).IsEqualTo(1.0);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Request_WithBodyAsJson_WithIJsonConverter_UsingObject()
|
||||
{
|
||||
// Assign
|
||||
var jsonConverterMock = new Mock<IJsonConverter>();
|
||||
jsonConverterMock.Setup(j => j.Serialize(It.IsAny<object>(), It.IsAny<JsonConverterOptions>())).Returns("test");
|
||||
object body = new
|
||||
{
|
||||
Any = "key"
|
||||
};
|
||||
var requestBuilder = Request.Create().UsingAnyMethod().WithBodyAsJson(body, jsonConverterMock.Object);
|
||||
|
||||
var bodyData = new BodyData
|
||||
{
|
||||
BodyAsString = "test",
|
||||
DetectedBodyType = BodyType.String
|
||||
};
|
||||
|
||||
// Act
|
||||
var request = new RequestMessage(new UrlDetails("http://localhost/foo"), "POST", ClientIp, bodyData);
|
||||
|
||||
// Assert
|
||||
var requestMatchResult = new RequestMatchResult();
|
||||
Check.That(requestBuilder.GetMatchingScore(request, requestMatchResult)).IsEqualTo(1.0);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(new byte[] { 1 }, BodyType.Bytes)]
|
||||
[InlineData(new byte[] { 48, 49, 50 }, BodyType.Bytes)]
|
||||
[InlineData(new byte[] { 48, 49, 50 }, BodyType.String)]
|
||||
public void Request_WithBodyAsBytes_ExactObjectMatcher_true(byte[] bytes, BodyType detectedBodyType)
|
||||
{
|
||||
// Assign
|
||||
byte[] body = bytes;
|
||||
var requestBuilder = Request.Create().UsingAnyMethod().WithBody(body);
|
||||
|
||||
var bodyData = new BodyData
|
||||
{
|
||||
BodyAsBytes = bytes,
|
||||
DetectedBodyType = detectedBodyType
|
||||
};
|
||||
|
||||
// Act
|
||||
var request = new RequestMessage(new UrlDetails("http://localhost/foo"), "PUT", ClientIp, bodyData);
|
||||
|
||||
// Assert
|
||||
var requestMatchResult = new RequestMatchResult();
|
||||
requestBuilder.GetMatchingScore(request, requestMatchResult).Should().Be(1.0);
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user