Compare commits

..

2 Commits

Author SHA1 Message Date
Stef Heyenrath
9b09a0ae00 . 2024-05-05 09:45:18 +02:00
Stef Heyenrath
ad040fb63c Proxying should keep url encoding 2024-05-05 09:44:56 +02:00
69 changed files with 20310 additions and 1392 deletions

View File

@@ -1,4 +1,4 @@
name: Run Tests
name: Build with Tests
on:
pull_request:
@@ -10,29 +10,47 @@ on:
jobs:
windows-build-and-run:
name: Run Tests on Windows
runs-on: windows-2022
env:
IsRunningOnGitHubActions: 'true'
steps:
steps:
- uses: actions/checkout@v4
- uses: actions/setup-dotnet@v3
with:
dotnet-version: |
7.0.x
8.0.x
- name: 'Build Unit Tests'
run: |
dotnet build './test/WireMock.Net.Tests/WireMock.Net.Tests.csproj' -c Release --framework net7.0
- name: 'Run Unit Tests'
run: |
dotnet test './test/WireMock.Net.Tests/WireMock.Net.Tests.csproj' -c Release --framework net8.0
dotnet test './test/WireMock.Net.Tests/WireMock.Net.Tests.csproj' -c Release --framework net7.0
linux-build-and-run:
name: Run Tests on Linux
runs-on: ubuntu-latest
env:
IsRunningOnGitHubActions: 'true'
steps:
steps:
- uses: actions/checkout@v4
- uses: actions/setup-dotnet@v3
with:
dotnet-version: |
7.0.x
8.0.x
- name: 'Build Unit Tests'
run: |
dotnet build './test/WireMock.Net.Tests/WireMock.Net.Tests.csproj' -c Release --framework net7.0
- name: 'Run Unit Tests'
run: |
dotnet test './test/WireMock.Net.Tests/WireMock.Net.Tests.csproj' -c Release --framework net8.0
dotnet test './test/WireMock.Net.Tests/WireMock.Net.Tests.csproj' -c Release --framework net7.0

29
.runsettings Normal file
View File

@@ -0,0 +1,29 @@
<?xml version="1.0" encoding="utf-8"?>
<RunSettings>
<DataCollectionRunSettings>
<DataCollectors>
<DataCollector friendlyName="Code Coverage"
uri="datacollector://Microsoft/CodeCoverage/2.0"
assemblyQualifiedName="Microsoft.VisualStudio.Coverage.DynamicCoverageDataCollector, Microsoft.VisualStudio.TraceCollector, Version=11.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<Configuration>
<CodeCoverage>
<ModulePaths>
<Include>
<ModulePath>.*\.dll$</ModulePath>
</Include>
<Exclude>
<ModulePath>.*Validation.*</ModulePath>
<ModulePath>.*\.tests.dll$</ModulePath>
<ModulePath>.*simmetrics.*</ModulePath>
</Exclude>
</ModulePaths>
<UseVerifiableInstrumentation>True</UseVerifiableInstrumentation>
<AllowLowIntegrityProcesses>True</AllowLowIntegrityProcesses>
<CollectFromChildProcesses>True</CollectFromChildProcesses>
<CollectAspDotNet>False</CollectAspDotNet>
</CodeCoverage>
</Configuration>
</DataCollector>
</DataCollectors>
</DataCollectionRunSettings>
</RunSettings>

View File

@@ -0,0 +1,14 @@
{
"ServerUri": "https://sonarcloud.io",
"Organization": {
"Key": "stefh-github",
"Name": "Stef Heyenrath (Organization)"
},
"ProjectKey": "wiremock",
"Profiles": {
"CSharp": {
"ProfileKey": "AWRupN8iowGp6EI3lYmF",
"ProfileTimestamp": "2018-09-06T11:06:47+02:00"
}
}
}

View File

@@ -0,0 +1,362 @@
<?xml version="1.0" encoding="utf-8"?>
<RuleSet Name="SonarQube - wiremock Sonar way" Description="This rule set was automatically generated from SonarQube.&#xD;&#xA;https://sonarcloud.io/profiles/show?key=AWRupN8iowGp6EI3lYmF" ToolsVersion="15.0">
<Rules AnalyzerId="SonarAnalyzer.CSharp" RuleNamespace="SonarAnalyzer.CSharp">
<Rule Id="S100" Action="None" />
<Rule Id="S1006" Action="Warning" />
<Rule Id="S101" Action="Warning" />
<Rule Id="S103" Action="None" />
<Rule Id="S104" Action="None" />
<Rule Id="S1048" Action="Warning" />
<Rule Id="S105" Action="None" />
<Rule Id="S106" Action="None" />
<Rule Id="S1066" Action="Warning" />
<Rule Id="S1067" Action="None" />
<Rule Id="S107" Action="Warning" />
<Rule Id="S1075" Action="Warning" />
<Rule Id="S108" Action="Warning" />
<Rule Id="S109" Action="None" />
<Rule Id="S110" Action="Warning" />
<Rule Id="S1104" Action="Warning" />
<Rule Id="S1109" Action="None" />
<Rule Id="S1110" Action="Warning" />
<Rule Id="S1116" Action="Warning" />
<Rule Id="S1117" Action="Warning" />
<Rule Id="S1118" Action="Warning" />
<Rule Id="S112" Action="Warning" />
<Rule Id="S1121" Action="Warning" />
<Rule Id="S1123" Action="Warning" />
<Rule Id="S1125" Action="Warning" />
<Rule Id="S113" Action="None" />
<Rule Id="S1134" Action="Warning" />
<Rule Id="S1135" Action="Warning" />
<Rule Id="S1144" Action="Warning" />
<Rule Id="S1145" Action="None" />
<Rule Id="S1147" Action="None" />
<Rule Id="S1151" Action="None" />
<Rule Id="S1155" Action="Warning" />
<Rule Id="S1163" Action="Warning" />
<Rule Id="S1168" Action="Warning" />
<Rule Id="S1172" Action="Warning" />
<Rule Id="S1185" Action="Warning" />
<Rule Id="S1186" Action="Warning" />
<Rule Id="S1192" Action="None" />
<Rule Id="S1200" Action="None" />
<Rule Id="S1206" Action="Warning" />
<Rule Id="S121" Action="None" />
<Rule Id="S1210" Action="Warning" />
<Rule Id="S1215" Action="Warning" />
<Rule Id="S122" Action="None" />
<Rule Id="S1226" Action="None" />
<Rule Id="S1227" Action="None" />
<Rule Id="S1244" Action="None" />
<Rule Id="S125" Action="Warning" />
<Rule Id="S126" Action="None" />
<Rule Id="S1264" Action="Warning" />
<Rule Id="S127" Action="None" />
<Rule Id="S1301" Action="None" />
<Rule Id="S1309" Action="None" />
<Rule Id="S131" Action="None" />
<Rule Id="S1313" Action="None" />
<Rule Id="S134" Action="None" />
<Rule Id="S138" Action="None" />
<Rule Id="S1449" Action="None" />
<Rule Id="S1450" Action="Warning" />
<Rule Id="S1451" Action="None" />
<Rule Id="S1479" Action="Warning" />
<Rule Id="S1481" Action="Warning" />
<Rule Id="S1541" Action="None" />
<Rule Id="S1607" Action="Warning" />
<Rule Id="S1643" Action="Warning" />
<Rule Id="S1656" Action="Warning" />
<Rule Id="S1659" Action="None" />
<Rule Id="S1694" Action="None" />
<Rule Id="S1696" Action="None" />
<Rule Id="S1697" Action="None" />
<Rule Id="S1698" Action="None" />
<Rule Id="S1699" Action="Warning" />
<Rule Id="S1751" Action="Warning" />
<Rule Id="S1764" Action="Warning" />
<Rule Id="S1821" Action="None" />
<Rule Id="S1848" Action="Warning" />
<Rule Id="S1854" Action="Warning" />
<Rule Id="S1858" Action="None" />
<Rule Id="S1862" Action="Warning" />
<Rule Id="S1871" Action="Warning" />
<Rule Id="S1905" Action="Warning" />
<Rule Id="S1939" Action="Warning" />
<Rule Id="S1940" Action="Warning" />
<Rule Id="S1944" Action="Warning" />
<Rule Id="S1994" Action="None" />
<Rule Id="S2068" Action="Warning" />
<Rule Id="S2070" Action="None" />
<Rule Id="S2092" Action="None" />
<Rule Id="S2114" Action="Warning" />
<Rule Id="S2123" Action="Warning" />
<Rule Id="S2148" Action="None" />
<Rule Id="S2156" Action="None" />
<Rule Id="S2178" Action="Warning" />
<Rule Id="S2183" Action="Warning" />
<Rule Id="S2184" Action="Warning" />
<Rule Id="S2187" Action="Warning" />
<Rule Id="S2190" Action="Warning" />
<Rule Id="S2197" Action="None" />
<Rule Id="S2201" Action="Warning" />
<Rule Id="S2219" Action="Warning" />
<Rule Id="S2221" Action="None" />
<Rule Id="S2223" Action="Warning" />
<Rule Id="S2225" Action="Warning" />
<Rule Id="S2228" Action="None" />
<Rule Id="S2234" Action="Warning" />
<Rule Id="S2245" Action="Warning" />
<Rule Id="S2255" Action="Warning" />
<Rule Id="S2259" Action="Warning" />
<Rule Id="S2275" Action="Warning" />
<Rule Id="S2278" Action="Warning" />
<Rule Id="S2290" Action="Warning" />
<Rule Id="S2291" Action="Warning" />
<Rule Id="S2292" Action="Warning" />
<Rule Id="S2302" Action="None" />
<Rule Id="S2306" Action="Warning" />
<Rule Id="S2325" Action="None" />
<Rule Id="S2326" Action="Warning" />
<Rule Id="S2327" Action="Warning" />
<Rule Id="S2328" Action="Warning" />
<Rule Id="S2330" Action="None" />
<Rule Id="S2333" Action="None" />
<Rule Id="S2339" Action="None" />
<Rule Id="S2342" Action="Warning" />
<Rule Id="S2344" Action="Warning" />
<Rule Id="S2345" Action="Warning" />
<Rule Id="S2346" Action="Warning" />
<Rule Id="S2357" Action="None" />
<Rule Id="S2360" Action="None" />
<Rule Id="S2365" Action="Warning" />
<Rule Id="S2368" Action="Warning" />
<Rule Id="S2372" Action="Warning" />
<Rule Id="S2376" Action="Warning" />
<Rule Id="S2386" Action="Warning" />
<Rule Id="S2387" Action="None" />
<Rule Id="S2436" Action="Warning" />
<Rule Id="S2437" Action="Warning" />
<Rule Id="S2486" Action="Warning" />
<Rule Id="S2551" Action="Warning" />
<Rule Id="S2583" Action="Warning" />
<Rule Id="S2589" Action="Warning" />
<Rule Id="S2674" Action="None" />
<Rule Id="S2681" Action="Warning" />
<Rule Id="S2688" Action="Warning" />
<Rule Id="S2692" Action="Warning" />
<Rule Id="S2696" Action="Warning" />
<Rule Id="S2699" Action="None" />
<Rule Id="S2701" Action="None" />
<Rule Id="S2737" Action="Warning" />
<Rule Id="S2743" Action="Warning" />
<Rule Id="S2757" Action="Warning" />
<Rule Id="S2758" Action="Warning" />
<Rule Id="S2760" Action="None" />
<Rule Id="S2761" Action="Warning" />
<Rule Id="S2930" Action="Warning" />
<Rule Id="S2931" Action="None" />
<Rule Id="S2933" Action="Warning" />
<Rule Id="S2934" Action="Warning" />
<Rule Id="S2952" Action="None" />
<Rule Id="S2953" Action="Warning" />
<Rule Id="S2955" Action="None" />
<Rule Id="S2971" Action="Warning" />
<Rule Id="S2995" Action="Warning" />
<Rule Id="S2996" Action="Warning" />
<Rule Id="S2997" Action="Warning" />
<Rule Id="S3005" Action="Warning" />
<Rule Id="S3010" Action="Warning" />
<Rule Id="S3052" Action="None" />
<Rule Id="S3060" Action="Warning" />
<Rule Id="S3168" Action="Warning" />
<Rule Id="S3169" Action="Warning" />
<Rule Id="S3172" Action="Warning" />
<Rule Id="S3215" Action="None" />
<Rule Id="S3216" Action="None" />
<Rule Id="S3217" Action="Warning" />
<Rule Id="S3218" Action="Warning" />
<Rule Id="S3220" Action="Warning" />
<Rule Id="S3234" Action="None" />
<Rule Id="S3235" Action="None" />
<Rule Id="S3236" Action="Warning" />
<Rule Id="S3237" Action="Warning" />
<Rule Id="S3240" Action="None" />
<Rule Id="S3241" Action="Warning" />
<Rule Id="S3242" Action="None" />
<Rule Id="S3244" Action="Warning" />
<Rule Id="S3246" Action="Warning" />
<Rule Id="S3247" Action="Warning" />
<Rule Id="S3249" Action="Warning" />
<Rule Id="S3251" Action="Warning" />
<Rule Id="S3253" Action="None" />
<Rule Id="S3254" Action="None" />
<Rule Id="S3256" Action="Warning" />
<Rule Id="S3257" Action="None" />
<Rule Id="S3261" Action="Warning" />
<Rule Id="S3262" Action="Warning" />
<Rule Id="S3263" Action="Warning" />
<Rule Id="S3264" Action="Warning" />
<Rule Id="S3265" Action="Warning" />
<Rule Id="S3330" Action="None" />
<Rule Id="S3343" Action="Warning" />
<Rule Id="S3346" Action="Warning" />
<Rule Id="S3353" Action="None" />
<Rule Id="S3358" Action="Warning" />
<Rule Id="S3366" Action="None" />
<Rule Id="S3376" Action="Warning" />
<Rule Id="S3397" Action="Warning" />
<Rule Id="S3400" Action="Warning" />
<Rule Id="S3415" Action="Warning" />
<Rule Id="S3427" Action="Warning" />
<Rule Id="S3431" Action="None" />
<Rule Id="S3433" Action="Warning" />
<Rule Id="S3440" Action="Warning" />
<Rule Id="S3441" Action="None" />
<Rule Id="S3442" Action="Warning" />
<Rule Id="S3443" Action="Warning" />
<Rule Id="S3444" Action="Warning" />
<Rule Id="S3445" Action="Warning" />
<Rule Id="S3447" Action="Warning" />
<Rule Id="S3449" Action="Warning" />
<Rule Id="S3450" Action="Warning" />
<Rule Id="S3451" Action="Warning" />
<Rule Id="S3453" Action="Warning" />
<Rule Id="S3456" Action="Warning" />
<Rule Id="S3457" Action="Warning" />
<Rule Id="S3458" Action="Warning" />
<Rule Id="S3459" Action="Warning" />
<Rule Id="S3464" Action="Warning" />
<Rule Id="S3466" Action="Warning" />
<Rule Id="S3532" Action="None" />
<Rule Id="S3597" Action="Warning" />
<Rule Id="S3598" Action="Warning" />
<Rule Id="S3600" Action="Warning" />
<Rule Id="S3603" Action="Warning" />
<Rule Id="S3604" Action="Warning" />
<Rule Id="S3610" Action="Warning" />
<Rule Id="S3626" Action="Warning" />
<Rule Id="S3655" Action="Warning" />
<Rule Id="S3693" Action="Warning" />
<Rule Id="S3717" Action="None" />
<Rule Id="S3776" Action="Warning" />
<Rule Id="S3869" Action="Warning" />
<Rule Id="S3871" Action="Warning" />
<Rule Id="S3872" Action="None" />
<Rule Id="S3874" Action="None" />
<Rule Id="S3875" Action="Warning" />
<Rule Id="S3876" Action="None" />
<Rule Id="S3877" Action="Warning" />
<Rule Id="S3880" Action="None" />
<Rule Id="S3881" Action="Warning" />
<Rule Id="S3884" Action="Warning" />
<Rule Id="S3885" Action="Warning" />
<Rule Id="S3887" Action="Warning" />
<Rule Id="S3889" Action="Warning" />
<Rule Id="S3897" Action="Warning" />
<Rule Id="S3898" Action="None" />
<Rule Id="S3900" Action="None" />
<Rule Id="S3902" Action="None" />
<Rule Id="S3903" Action="Warning" />
<Rule Id="S3904" Action="Warning" />
<Rule Id="S3906" Action="None" />
<Rule Id="S3908" Action="None" />
<Rule Id="S3909" Action="None" />
<Rule Id="S3923" Action="Warning" />
<Rule Id="S3925" Action="Warning" />
<Rule Id="S3926" Action="Warning" />
<Rule Id="S3927" Action="Warning" />
<Rule Id="S3928" Action="Warning" />
<Rule Id="S3937" Action="None" />
<Rule Id="S3956" Action="None" />
<Rule Id="S3962" Action="None" />
<Rule Id="S3963" Action="Warning" />
<Rule Id="S3966" Action="Warning" />
<Rule Id="S3967" Action="None" />
<Rule Id="S3971" Action="Warning" />
<Rule Id="S3972" Action="Warning" />
<Rule Id="S3973" Action="Warning" />
<Rule Id="S3981" Action="Warning" />
<Rule Id="S3984" Action="Warning" />
<Rule Id="S3990" Action="None" />
<Rule Id="S3992" Action="None" />
<Rule Id="S3993" Action="None" />
<Rule Id="S3994" Action="None" />
<Rule Id="S3995" Action="None" />
<Rule Id="S3996" Action="None" />
<Rule Id="S3997" Action="None" />
<Rule Id="S3998" Action="Warning" />
<Rule Id="S4000" Action="None" />
<Rule Id="S4002" Action="None" />
<Rule Id="S4004" Action="None" />
<Rule Id="S4005" Action="None" />
<Rule Id="S4015" Action="Warning" />
<Rule Id="S4016" Action="Warning" />
<Rule Id="S4017" Action="None" />
<Rule Id="S4018" Action="None" />
<Rule Id="S4019" Action="Warning" />
<Rule Id="S4022" Action="None" />
<Rule Id="S4023" Action="None" />
<Rule Id="S4025" Action="None" />
<Rule Id="S4026" Action="None" />
<Rule Id="S4027" Action="None" />
<Rule Id="S4035" Action="Warning" />
<Rule Id="S4039" Action="None" />
<Rule Id="S4040" Action="None" />
<Rule Id="S4041" Action="None" />
<Rule Id="S4047" Action="None" />
<Rule Id="S4049" Action="None" />
<Rule Id="S4050" Action="None" />
<Rule Id="S4052" Action="None" />
<Rule Id="S4055" Action="None" />
<Rule Id="S4056" Action="None" />
<Rule Id="S4057" Action="None" />
<Rule Id="S4058" Action="None" />
<Rule Id="S4059" Action="None" />
<Rule Id="S4060" Action="None" />
<Rule Id="S4061" Action="Warning" />
<Rule Id="S4069" Action="None" />
<Rule Id="S4070" Action="None" />
<Rule Id="S4142" Action="None" />
<Rule Id="S4143" Action="Warning" />
<Rule Id="S4144" Action="Warning" />
<Rule Id="S4158" Action="Warning" />
<Rule Id="S4159" Action="Warning" />
<Rule Id="S4200" Action="Warning" />
<Rule Id="S4210" Action="Warning" />
<Rule Id="S4211" Action="Warning" />
<Rule Id="S4212" Action="None" />
<Rule Id="S4214" Action="Warning" />
<Rule Id="S4220" Action="Warning" />
<Rule Id="S4225" Action="None" />
<Rule Id="S4226" Action="None" />
<Rule Id="S4260" Action="Warning" />
<Rule Id="S4261" Action="None" />
<Rule Id="S4275" Action="Warning" />
<Rule Id="S4277" Action="Warning" />
<Rule Id="S4426" Action="Warning" />
<Rule Id="S4428" Action="Warning" />
<Rule Id="S4432" Action="None" />
<Rule Id="S4433" Action="Warning" />
<Rule Id="S4456" Action="Warning" />
<Rule Id="S4457" Action="Warning" />
<Rule Id="S4462" Action="None" />
<Rule Id="S4524" Action="Warning" />
<Rule Id="S4564" Action="None" />
<Rule Id="S4581" Action="Warning" />
<Rule Id="S4586" Action="Warning" />
<Rule Id="S818" Action="Warning" />
<Rule Id="S881" Action="None" />
<Rule Id="S907" Action="Warning" />
<Rule Id="S927" Action="Warning" />
</Rules>
<Rules AnalyzerId="SonarAnalyzer.Security" RuleNamespace="SonarAnalyzer.Security">
<Rule Id="S2076" Action="Warning" />
<Rule Id="S2078" Action="Warning" />
<Rule Id="S2083" Action="Warning" />
<Rule Id="S2091" Action="Warning" />
<Rule Id="S2631" Action="Warning" />
<Rule Id="S3649" Action="Warning" />
</Rules>
</RuleSet>

View File

@@ -1,40 +1,3 @@
# 1.5.60 (09 July 2024)
- [#1128](https://github.com/WireMock-Net/WireMock.Net/pull/1128) - Add Handlebars.Net.Helpers.Xslt [feature] contributed by [StefH](https://github.com/StefH)
- [#1130](https://github.com/WireMock-Net/WireMock.Net/pull/1130) - Add AdminPath to WireMockServerSettings [feature] contributed by [StefH](https://github.com/StefH)
- [#1131](https://github.com/WireMock-Net/WireMock.Net/pull/1131) - Add unit tests for AdminApiMappingBuilder [test] contributed by [StefH](https://github.com/StefH)
- [#1132](https://github.com/WireMock-Net/WireMock.Net/pull/1132) - Multipart Matcher Fix [bug] contributed by [rmeshksar](https://github.com/rmeshksar)
- [#1133](https://github.com/WireMock-Net/WireMock.Net/pull/1133) - Add unit tests for AdminApiMappingBuilder_ [test] contributed by [StefH](https://github.com/StefH)
- [#1134](https://github.com/WireMock-Net/WireMock.Net/pull/1134) - Remove some files and folders [refactor] contributed by [StefH](https://github.com/StefH)
- [#1119](https://github.com/WireMock-Net/WireMock.Net/issues/1119) - Error in RequestMessageMultiPartMatcher [bug]
- [#1121](https://github.com/WireMock-Net/WireMock.Net/issues/1121) - XML transformation [feature]
# 1.5.59 (26 June 2024)
- [#1127](https://github.com/WireMock-Net/WireMock.Net/pull/1127) - Made changes to accommodate breaking change in testcontainers-dotnet 3.9 [feature] contributed by [epDugas](https://github.com/epDugas)
# 1.5.58 (08 June 2024)
- [#1116](https://github.com/WireMock-Net/WireMock.Net/pull/1116) - Add some methods to the BodyModelBuilder [feature] contributed by [StefH](https://github.com/StefH)
- [#1117](https://github.com/WireMock-Net/WireMock.Net/issues/1117) - AbstractJsonPartialMatcher: Regex Value is Uppercased when IgnoreCase is set to true [bug]
# 1.5.57 (04 June 2024)
- [#1113](https://github.com/WireMock-Net/WireMock.Net/pull/1113) - Add some Extension methods to IWireMockAdminApi [feature] contributed by [StefH](https://github.com/StefH)
# 1.5.56 (03 June 2024)
- [#1111](https://github.com/WireMock-Net/WireMock.Net/pull/1111) - Fix Request.Create().WithBodyAsJson(...) [bug] contributed by [StefH](https://github.com/StefH)
- [#1112](https://github.com/WireMock-Net/WireMock.Net/pull/1112) - Add &quot;/__admin/health&quot; endpoint [feature] contributed by [StefH](https://github.com/StefH)
- [#1110](https://github.com/WireMock-Net/WireMock.Net/issues/1110) - Connection prematurely closed BEFORE response [bug]
# 1.5.55 (22 May 2024)
- [#1107](https://github.com/WireMock-Net/WireMock.Net/pull/1107) - When only Port is provided, bind to * (Fixes #1100) [bug] contributed by [StefH](https://github.com/StefH)
# 1.5.54 (18 May 2024)
- [#1100](https://github.com/WireMock-Net/WireMock.Net/pull/1100) - Add support to bind to ip-address instead of only localhost [feature] contributed by [StefH](https://github.com/StefH)
- [#1104](https://github.com/WireMock-Net/WireMock.Net/pull/1104) - Use try..catch to set encoding in WireMockConsoleLogger [feature] contributed by [asherber](https://github.com/asherber)
# 1.5.53 (08 May 2024)
- [#1093](https://github.com/WireMock-Net/WireMock.Net/pull/1093) - Update Handlebars.Net [feature] contributed by [StefH](https://github.com/StefH)
- [#1101](https://github.com/WireMock-Net/WireMock.Net/pull/1101) - Fix MappingConverter to support Body with JsonMatcher [bug] contributed by [StefH](https://github.com/StefH)
- [#1095](https://github.com/WireMock-Net/WireMock.Net/issues/1095) - When using C# code generation WithBody() matcher is not generated for POST Request [bug]
# 1.5.52 (06 April 2024)
- [#1091](https://github.com/WireMock-Net/WireMock.Net/pull/1091) - Add RegEx support to JsonMatcher [feature] contributed by [StefH](https://github.com/StefH)
- [#1088](https://github.com/WireMock-Net/WireMock.Net/issues/1088) - Regex support for JsonMatcher [feature]

View File

@@ -4,7 +4,7 @@
</PropertyGroup>
<PropertyGroup>
<VersionPrefix>1.5.60</VersionPrefix>
<VersionPrefix>1.5.52</VersionPrefix>
<PackageIcon>WireMock.Net-Logo.png</PackageIcon>
<PackageProjectUrl>https://github.com/WireMock-Net/WireMock.Net</PackageProjectUrl>
<PackageLicenseExpression>Apache-2.0</PackageLicenseExpression>

View File

@@ -1,7 +1,7 @@
rem https://github.com/StefH/GitHubReleaseNotes
SET version=1.5.60
SET version=1.5.52
GitHubReleaseNotes --output CHANGELOG.md --skip-empty-releases --exclude-labels question invalid doc duplicate example environment --version %version% --token %GH_TOKEN%
GitHubReleaseNotes --output CHANGELOG.md --skip-empty-releases --exclude-labels question invalid doc duplicate example --version %version% --token %GH_TOKEN%
GitHubReleaseNotes --output PackageReleaseNotes.txt --skip-empty-releases --exclude-labels question invalid doc duplicate example environment --template PackageReleaseNotes.template --version %version% --token %GH_TOKEN%
GitHubReleaseNotes --output PackageReleaseNotes.txt --skip-empty-releases --exclude-labels question invalid doc duplicate --template PackageReleaseNotes.template --version %version% --token %GH_TOKEN%

View File

@@ -1,11 +1,5 @@
# 1.5.60 (09 July 2024)
- #1128 Add Handlebars.Net.Helpers.Xslt [feature]
- #1130 Add AdminPath to WireMockServerSettings [feature]
- #1131 Add unit tests for AdminApiMappingBuilder [test]
- #1132 Multipart Matcher Fix [bug]
- #1133 Add unit tests for AdminApiMappingBuilder_ [test]
- #1134 Remove some files and folders [refactor]
- #1119 Error in RequestMessageMultiPartMatcher [bug]
- #1121 XML transformation [feature]
# 1.5.52 (06 April 2024)
- #1091 Add RegEx support to JsonMatcher [feature]
- #1088 Regex support for JsonMatcher [feature]
The full release notes can be found here: https://github.com/WireMock-Net/WireMock.Net/blob/master/CHANGELOG.md

View File

@@ -27,6 +27,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
Directory.Build.props = Directory.Build.props
.github\FUNDING.yml = .github\FUNDING.yml
Generate-ReleaseNotes.cmd = Generate-ReleaseNotes.cmd
nuget.config = nuget.config
PackageReadme.md = PackageReadme.md
PackageReleaseNotes.template = PackageReleaseNotes.template
PackageReleaseNotes.txt = PackageReleaseNotes.txt
@@ -69,7 +70,7 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WireMock.Net.Console.Net472
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Actions", "Actions", "{1DAEFF47-D117-4E95-8B3E-4F7C8B92011A}"
ProjectSection(SolutionItems) = preProject
.github\workflows\ci.yml = .github\workflows\ci.yml
..\System.Linq.Dynamic.Core\.github\workflows\ci.yml = ..\System.Linq.Dynamic.Core\.github\workflows\ci.yml
.github\workflows\CreateRelease.yml = .github\workflows\CreateRelease.yml
EndProjectSection
EndProject
@@ -105,7 +106,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tools", "tools", "{0147029F
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MultipartUploader", "tools\MultipartUploader\MultipartUploader.csproj", "{07C30227-ADEC-4BDE-8CDC-849D85A690BB}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WireMock.Net.Console.NET7.UsingNuGet", "examples\WireMock.Net.Console.NET7.UsingNuGet\WireMock.Net.Console.NET7.UsingNuGet.csproj", "{941229D6-191B-4B5E-AC81-0905EBF4F19D}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WireMock.Net.Console.NET7.UsingNuGet", "examples\WireMock.Net.Console.NET7.UsingNuGet\WireMock.Net.Console.NET7.UsingNuGet.csproj", "{941229D6-191B-4B5E-AC81-0905EBF4F19D}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WireMock.Net.Console.NET8", "examples\WireMock.Net.Console.NET8\WireMock.Net.Console.NET8.csproj", "{1EA72C0F-92E9-486B-8FFE-53F992BFC4AA}"
EndProject

View File

@@ -0,0 +1,21 @@
pool:
vmImage: 'Ubuntu-latest'
variables:
buildConfiguration: 'Release'
steps:
- task: UseDotNet@2
displayName: 'Use .NET 8'
inputs:
packageType: sdk
version: 8.0.x
- script: |
dotnet test ./test/WireMock.Net.Tests/WireMock.Net.Tests.csproj --configuration $(buildConfiguration) --framework net8.0 --logger trx
displayName: 'Test'
- task: PublishTestResults@2
inputs:
testRunner: VSTest
testResultsFiles: '**/*.trx'

View File

@@ -14,45 +14,53 @@ jobs:
echo "BuildId = $(buildId)"
displayName: 'Print buildId'
- script: |
dotnet tool install --global dotnet-sonarscanner
dotnet tool install --global dotnet-coverage
dotnet tool install --global coverlet.console
displayName: 'Install dotnet tools'
- task: UseDotNet@2
displayName: Use .NET 8.0
inputs:
packageType: 'sdk'
version: '8.0.x'
- task: PowerShell@2
displayName: "Use JDK17 by default"
displayName: "Use JDK11 by default"
inputs:
targetType: 'inline'
script: |
$jdkPath = $env:JAVA_HOME_17_X64
$jdkPath = $env:JAVA_HOME_11_X64
Write-Host "##vso[task.setvariable variable=JAVA_HOME]$jdkPath"
- script: |
dotnet dev-certs https --trust || true
displayName: 'dotnet dev-certs https'
# See: https://docs.sonarsource.com/sonarcloud/enriching/test-coverage/dotnet-test-coverage
- script: |
dotnet sonarscanner begin /k:"WireMock-Net_WireMock.Net" /o:"wiremock-net" /d:sonar.branch.name=$(Build.SourceBranchName) /d:sonar.host.url="https://sonarcloud.io" /d:sonar.token="$(SONAR_TOKEN)" /d:sonar.dotnet.excludeTestProjects=true /d:sonar.cs.vscoveragexml.reportsPaths=**/wiremock-coverage.xml /d:sonar.verbose=true
displayName: 'Begin analysis on SonarCloud'
- task: SonarCloudPrepare@1
displayName: 'Prepare analysis on SonarCloud'
condition: and(succeeded(), ne(variables['Build.Reason'], 'PullRequest')) # Do not run for PullRequests
inputs:
SonarCloud: SonarCloud
organization: wiremock-net
projectKey: 'WireMock-Net_WireMock.Net'
projectName: 'WireMock.Net'
extraProperties: |
sonar.cs.opencover.reportsPaths=**/coverage.net8.0.opencover.xml
- task: DotNetCoreCLI@2
displayName: 'Build Unit tests'
inputs:
command: 'build'
projects: './test/WireMock.Net.Tests/WireMock.Net.Tests.csproj'
arguments: '--configuration Debug --framework net8.0 --no-incremental'
arguments: '--configuration Debug --framework net8.0'
- task: CmdLine@2
inputs:
script: 'dotnet-coverage collect "dotnet test ./test/WireMock.Net.Tests/WireMock.Net.Tests.csproj --configuration Debug --no-build --framework net8.0" -f xml -o "wiremock-coverage.xml"'
script: 'dotnet test ./test/WireMock.Net.Tests/WireMock.Net.Tests.csproj --no-build --configuration Debug --framework net8.0'
displayName: 'Execute Unit Tests with Coverage'
- task: SonarCloudAnalyze@1
displayName: 'SonarCloud: Run Code Analysis'
condition: and(succeeded(), ne(variables['Build.Reason'], 'PullRequest')) # Do not run for PullRequests
- script: |
dotnet sonarscanner end /d:sonar.token="$(SONAR_TOKEN)"
displayName: 'End analysis on SonarCloud'
- task: SonarCloudPublish@1
displayName: 'SonarCloud: Publish Quality Gate Result'
condition: and(succeeded(), ne(variables['Build.Reason'], 'PullRequest')) # Do not run for PullRequests
- task: whitesource.ws-bolt.bolt.wss.WhiteSource Bolt@19

29
azure-pipelines-linux.yml Normal file
View File

@@ -0,0 +1,29 @@
trigger:
- none
pool:
vmImage: 'Ubuntu-latest'
variables:
buildProjects: '**/src/**/*.csproj'
buildConfiguration: 'Release'
steps:
- task: UseDotNet@2
displayName: 'Use .NET 8'
inputs:
packageType: sdk
version: 8.0.x
- task: DotNetCoreCLI@2
displayName: Build Release
inputs:
command: 'build'
arguments: /p:Configuration=$(buildConfiguration)
projects: $(buildProjects)
- task: PublishBuildArtifacts@1
displayName: Publish Artifacts
condition: succeeded()
inputs:
PathtoPublish: '$(Build.ArtifactStagingDirectory)'

View File

@@ -14,13 +14,10 @@ class Program
{
static async Task Main(string[] args)
{
// Start WireMock.Net tool with Admin interface
// dotnet-wiremock --StartAdminInterface
// Create an implementation of the IWireMockAdminApi and pass in the base URL for the API.
var api = RestClient.For<IWireMockAdminApi>("http://localhost:9091");
await api.ResetMappingsAsync().ConfigureAwait(false);
// await api.ResetMappingsAsync().ConfigureAwait(false);
var mappingBuilder = api.GetMappingBuilder();
mappingBuilder.Given(m => m
@@ -54,32 +51,13 @@ class Program
.WithPath("/bla3")
)
.WithResponse(rsp => rsp
.WithBodyAsJson(new
.WithBodyAsJson(new
{
x = "test"
}, true)
)
);
mappingBuilder.Given(m => m
.WithRequest(req => req
.WithPath("/test1")
.UsingPost()
.WithBody(b => b
.WithJmesPathMatcher("things.name == 'RequiredThing'")
)
)
.WithResponse(rsp => rsp
.WithHeaders(h => h.Add("Content-Type", "application/json"))
.WithDelay(TimeSpan.FromMilliseconds(50))
.WithStatusCode(200)
.WithBodyAsJson(new
{
status = "ok"
}, true)
)
);
var result = await mappingBuilder.BuildAndPostAsync().ConfigureAwait(false);
Console.WriteLine($"result = {JsonConvert.SerializeObject(result)}");
@@ -134,9 +112,6 @@ class Program
var getFileResult = await api.GetFileAsync("1.cs");
Console.WriteLine($"getFileResult = {getFileResult}");
Console.WriteLine("Press any key to reset mappings");
Console.ReadKey();
var resetMappingsAsync = await api.ResetMappingsAsync();
Console.WriteLine($"resetMappingsAsync = {resetMappingsAsync.Status}");

View File

@@ -0,0 +1,8 @@
{
"profiles": {
"WSL": {
"commandName": "WSL2",
"distributionName": ""
}
}
}

View File

@@ -2,7 +2,7 @@
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<TargetFramework>net7.0</TargetFramework>
<ApplicationIcon>../../resources/WireMock.Net-Logo.ico</ApplicationIcon>
</PropertyGroup>

View File

@@ -4,7 +4,6 @@ using System.Globalization;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Threading.Tasks;
using Newtonsoft.Json;
using WireMock.Logging;
@@ -95,48 +94,8 @@ message HelloReply {
fullName:String
}";
private static void RunOnLocal()
{
try
{
var server = WireMockServer.Start(new WireMockServerSettings
{
Port = 9091,
StartAdminInterface = true,
Logger = new WireMockConsoleLogger()
});
System.Console.WriteLine(string.Join(", ", server.Urls));
var requestJson = new { PricingContext = new { Market = "USA" } };
var responseJson = new { Market = "{{JsonPath.SelectToken request.body \"$.PricingContext.Market\"}}" };
server
.Given(Request.Create()
//.WithBody(new JsonMatcher(requestJson))
.WithBodyAsJson(requestJson)
.WithPath("/pricing")
.UsingPost()
)
.RespondWith(Response.Create()
.WithHeader("Content-Type", "application/json")
.WithBodyAsJson(responseJson)
.WithTransformer(true)
);
System.Console.WriteLine("Press any key to stop...");
System.Console.ReadKey();
server.Stop();
}
catch (Exception e)
{
System.Console.WriteLine(e);
}
}
public static void Run()
{
RunOnLocal();
return;
var mappingBuilder = new MappingBuilder();
mappingBuilder
.Given(Request
@@ -229,9 +188,7 @@ message HelloReply {
server.SetBasicAuthentication("a", "b");
//server.SetAzureADAuthentication("6c2a4722-f3b9-4970-b8fc-fac41e29stef", "8587fde1-7824-42c7-8592-faf92b04stef");
//var http = new HttpClient();
//var response = await http.GetAsync($"{_wireMockServer.Url}/pricing");
//var value = await response.Content.ReadAsStringAsync();
// server.AllowPartialMapping();
#if PROTOBUF
var protoBufJsonMatcher = new JsonPartialWildcardMatcher(new { name = "*" });
@@ -375,6 +332,7 @@ message HelloReply {
.WithHeader("Content-Type", "text/plain")
);
server
.Given(Request.Create()
.UsingMethod("GET")

View File

@@ -39,17 +39,17 @@
<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.6.0, Culture=neutral, PublicKeyToken=22225d0bf33cd661, processorArchitecture=MSIL">
<HintPath>..\..\packages\Handlebars.Net.2.1.6\lib\net451\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.4.3.0, Culture=neutral, PublicKeyToken=00d131fae0c250bc, processorArchitecture=MSIL">
<HintPath>..\..\packages\Handlebars.Net.Helpers.2.4.3\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.4.3.0, Culture=neutral, PublicKeyToken=00d131fae0c250bc, processorArchitecture=MSIL">
<HintPath>..\..\packages\Handlebars.Net.Helpers.Core.2.4.3\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.17.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a, processorArchitecture=MSIL">
<HintPath>..\..\packages\log4net.2.0.17\lib\net45\log4net.dll</HintPath>
<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>
</Reference>
<Reference Include="Microsoft.CSharp" />
<Reference Include="Microsoft.Owin.Host.HttpListener, Version=3.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">

View File

@@ -1,10 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="AnyOf" version="0.3.0" targetFramework="net452" />
<package id="Handlebars.Net" version="2.1.6" targetFramework="net452" />
<package id="Handlebars.Net.Helpers" version="2.4.3" targetFramework="net452" />
<package id="Handlebars.Net.Helpers.Core" version="2.4.3" targetFramework="net452" />
<package id="log4net" version="2.0.17" 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.3" targetFramework="net452" />
<package id="SimMetrics.Net" version="1.0.5" targetFramework="net452" />

View File

@@ -38,17 +38,17 @@
<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.6.0, Culture=neutral, PublicKeyToken=22225d0bf33cd661, processorArchitecture=MSIL">
<HintPath>..\..\packages\Handlebars.Net.2.1.6\lib\net451\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.4.3.0, Culture=neutral, PublicKeyToken=00d131fae0c250bc, processorArchitecture=MSIL">
<HintPath>..\..\packages\Handlebars.Net.Helpers.2.4.3\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.4.3.0, Culture=neutral, PublicKeyToken=00d131fae0c250bc, processorArchitecture=MSIL">
<HintPath>..\..\packages\Handlebars.Net.Helpers.Core.2.4.3\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.17.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a, processorArchitecture=MSIL">
<HintPath>..\..\packages\log4net.2.0.17\lib\net45\log4net.dll</HintPath>
<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>
</Reference>
<Reference Include="Microsoft.Extensions.DependencyInjection.Abstractions, Version=2.2.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
<HintPath>..\..\packages\Microsoft.Extensions.DependencyInjection.Abstractions.2.2.0\lib\netstandard2.0\Microsoft.Extensions.DependencyInjection.Abstractions.dll</HintPath>

View File

@@ -1,10 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="AnyOf" version="0.3.0" targetFramework="net461" />
<package id="Handlebars.Net" version="2.1.6" targetFramework="net461" />
<package id="Handlebars.Net.Helpers" version="2.4.3" targetFramework="net461" />
<package id="Handlebars.Net.Helpers.Core" version="2.4.3" targetFramework="net461" />
<package id="log4net" version="2.0.17" 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.3" targetFramework="net461" />
<package id="SimMetrics.Net" version="1.0.5" targetFramework="net461" />

View File

@@ -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.6.0, Culture=neutral, PublicKeyToken=22225d0bf33cd661, processorArchitecture=MSIL">
<HintPath>..\..\packages\Handlebars.Net.2.1.6\lib\net451\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.4.3.0, Culture=neutral, PublicKeyToken=00d131fae0c250bc, processorArchitecture=MSIL">
<HintPath>..\..\packages\Handlebars.Net.Helpers.2.4.3\lib\net46\Handlebars.Net.Helpers.dll</HintPath>
<Reference Include="Handlebars.Net.Helpers, Version=2.4.1.2, Culture=neutral, PublicKeyToken=00d131fae0c250bc, processorArchitecture=MSIL">
<HintPath>..\..\packages\Handlebars.Net.Helpers.2.4.1.2\lib\net46\Handlebars.Net.Helpers.dll</HintPath>
</Reference>
<Reference Include="HandlebarsDotNet.Helpers.Core, Version=2.4.3.0, Culture=neutral, PublicKeyToken=00d131fae0c250bc, processorArchitecture=MSIL">
<HintPath>..\..\packages\Handlebars.Net.Helpers.Core.2.4.3\lib\net46\HandlebarsDotNet.Helpers.Core.dll</HintPath>
<Reference Include="HandlebarsDotNet.Helpers.Core, Version=2.4.1.2, Culture=neutral, PublicKeyToken=00d131fae0c250bc, processorArchitecture=MSIL">
<HintPath>..\..\packages\Handlebars.Net.Helpers.Core.2.4.1.2\lib\net46\HandlebarsDotNet.Helpers.Core.dll</HintPath>
</Reference>
<Reference Include="HandlebarsDotNet.Helpers.DynamicLinq, Version=2.4.3.0, Culture=neutral, PublicKeyToken=00d131fae0c250bc, processorArchitecture=MSIL">
<HintPath>..\..\packages\Handlebars.Net.Helpers.DynamicLinq.2.4.3\lib\net46\HandlebarsDotNet.Helpers.DynamicLinq.dll</HintPath>
<Reference Include="HandlebarsDotNet.Helpers.DynamicLinq, Version=2.4.1.2, Culture=neutral, PublicKeyToken=00d131fae0c250bc, processorArchitecture=MSIL">
<HintPath>..\..\packages\Handlebars.Net.Helpers.DynamicLinq.2.4.1.2\lib\net46\HandlebarsDotNet.Helpers.DynamicLinq.dll</HintPath>
</Reference>
<Reference Include="HandlebarsDotNet.Helpers.Humanizer, Version=2.4.3.0, Culture=neutral, PublicKeyToken=00d131fae0c250bc, processorArchitecture=MSIL">
<HintPath>..\..\packages\Handlebars.Net.Helpers.Humanizer.2.4.3\lib\net46\HandlebarsDotNet.Helpers.Humanizer.dll</HintPath>
<Reference Include="HandlebarsDotNet.Helpers.Humanizer, Version=2.4.1.2, Culture=neutral, PublicKeyToken=00d131fae0c250bc, processorArchitecture=MSIL">
<HintPath>..\..\packages\Handlebars.Net.Helpers.Humanizer.2.4.1.2\lib\net46\HandlebarsDotNet.Helpers.Humanizer.dll</HintPath>
</Reference>
<Reference Include="HandlebarsDotNet.Helpers.Json, Version=2.4.3.0, Culture=neutral, PublicKeyToken=00d131fae0c250bc, processorArchitecture=MSIL">
<HintPath>..\..\packages\Handlebars.Net.Helpers.Json.2.4.3\lib\net46\HandlebarsDotNet.Helpers.Json.dll</HintPath>
<Reference Include="HandlebarsDotNet.Helpers.Json, Version=2.4.1.2, Culture=neutral, PublicKeyToken=00d131fae0c250bc, processorArchitecture=MSIL">
<HintPath>..\..\packages\Handlebars.Net.Helpers.Json.2.4.1.2\lib\net46\HandlebarsDotNet.Helpers.Json.dll</HintPath>
</Reference>
<Reference Include="HandlebarsDotNet.Helpers.Random, Version=2.4.3.0, Culture=neutral, PublicKeyToken=00d131fae0c250bc, processorArchitecture=MSIL">
<HintPath>..\..\packages\Handlebars.Net.Helpers.Random.2.4.3\lib\net46\HandlebarsDotNet.Helpers.Random.dll</HintPath>
<Reference Include="HandlebarsDotNet.Helpers.Random, Version=2.4.1.2, Culture=neutral, PublicKeyToken=00d131fae0c250bc, processorArchitecture=MSIL">
<HintPath>..\..\packages\Handlebars.Net.Helpers.Random.2.4.1.2\lib\net46\HandlebarsDotNet.Helpers.Random.dll</HintPath>
</Reference>
<Reference Include="HandlebarsDotNet.Helpers.Xeger, Version=2.4.3.0, Culture=neutral, PublicKeyToken=00d131fae0c250bc, processorArchitecture=MSIL">
<HintPath>..\..\packages\Handlebars.Net.Helpers.Xeger.2.4.3\lib\net46\HandlebarsDotNet.Helpers.Xeger.dll</HintPath>
<Reference Include="HandlebarsDotNet.Helpers.Xeger, Version=2.4.1.2, Culture=neutral, PublicKeyToken=00d131fae0c250bc, processorArchitecture=MSIL">
<HintPath>..\..\packages\Handlebars.Net.Helpers.Xeger.2.4.1.2\lib\net46\HandlebarsDotNet.Helpers.Xeger.dll</HintPath>
</Reference>
<Reference Include="HandlebarsDotNet.Helpers.XPath, Version=2.4.3.0, Culture=neutral, PublicKeyToken=00d131fae0c250bc, processorArchitecture=MSIL">
<HintPath>..\..\packages\Handlebars.Net.Helpers.XPath.2.4.3\lib\net46\HandlebarsDotNet.Helpers.XPath.dll</HintPath>
<Reference Include="HandlebarsDotNet.Helpers.XPath, Version=2.4.1.2, Culture=neutral, PublicKeyToken=00d131fae0c250bc, processorArchitecture=MSIL">
<HintPath>..\..\packages\Handlebars.Net.Helpers.XPath.2.4.1.2\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>
@@ -79,8 +79,8 @@
<Reference Include="JmesPath.Net, Version=1.0.125.0, Culture=neutral, PublicKeyToken=b29d616b7f4faff0, processorArchitecture=MSIL">
<HintPath>..\..\packages\JmesPath.Net.1.0.125\lib\net45\JmesPath.Net.dll</HintPath>
</Reference>
<Reference Include="log4net, Version=2.0.17.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a, processorArchitecture=MSIL">
<HintPath>..\..\packages\log4net.2.0.17\lib\net45\log4net.dll</HintPath>
<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>
</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>
@@ -307,8 +307,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.3.14.0, Culture=neutral, PublicKeyToken=0f07ec44de6ac832, processorArchitecture=MSIL">
<HintPath>..\..\packages\System.Linq.Dynamic.Core.1.3.14\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.2, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51">
<HintPath>..\..\packages/System.Memory.4.5.5/lib/net461/System.Memory.dll</HintPath>
@@ -358,11 +358,11 @@
<Reference Include="TinyMapper, Version=3.0.1.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\..\packages\TinyMapper.3.0.3\lib\net40\TinyMapper.dll</HintPath>
</Reference>
<Reference Include="XPath2, Version=1.1.5.0, Culture=neutral, PublicKeyToken=463c6d7fb740c7e5, processorArchitecture=MSIL">
<HintPath>..\..\packages\XPath2.1.1.5\lib\net452\XPath2.dll</HintPath>
<Reference Include="XPath2, Version=1.1.4.0, Culture=neutral, PublicKeyToken=463c6d7fb740c7e5, processorArchitecture=MSIL">
<HintPath>..\..\packages\XPath2.1.1.4\lib\net452\XPath2.dll</HintPath>
</Reference>
<Reference Include="XPath2.Extensions, Version=1.1.5.0, Culture=neutral, PublicKeyToken=463c6d7fb740c7e5, processorArchitecture=MSIL">
<HintPath>..\..\packages\XPath2.Extensions.1.1.5\lib\net452\XPath2.Extensions.dll</HintPath>
<Reference Include="XPath2.Extensions, Version=1.1.4.0, Culture=neutral, PublicKeyToken=463c6d7fb740c7e5, processorArchitecture=MSIL">
<HintPath>..\..\packages\XPath2.Extensions.1.1.4\lib\net452\XPath2.Extensions.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>

View File

@@ -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.6" targetFramework="net472" />
<package id="Handlebars.Net.Helpers" version="2.4.3" targetFramework="net472" />
<package id="Handlebars.Net.Helpers.Core" version="2.4.3" targetFramework="net472" />
<package id="Handlebars.Net.Helpers.DynamicLinq" version="2.4.3" targetFramework="net472" />
<package id="Handlebars.Net.Helpers.Humanizer" version="2.4.3" targetFramework="net472" />
<package id="Handlebars.Net.Helpers.Json" version="2.4.3" targetFramework="net472" />
<package id="Handlebars.Net.Helpers.Random" version="2.4.3" targetFramework="net472" />
<package id="Handlebars.Net.Helpers.Xeger" version="2.4.3" targetFramework="net472" />
<package id="Handlebars.Net.Helpers.XPath" version="2.4.3" targetFramework="net472" />
<package id="Handlebars.Net" version="2.1.4" targetFramework="net472" />
<package id="Handlebars.Net.Helpers" version="2.4.1.2" targetFramework="net472" />
<package id="Handlebars.Net.Helpers.Core" version="2.4.1.2" targetFramework="net472" />
<package id="Handlebars.Net.Helpers.DynamicLinq" version="2.4.1.2" targetFramework="net472" />
<package id="Handlebars.Net.Helpers.Humanizer" version="2.4.1.2" targetFramework="net472" />
<package id="Handlebars.Net.Helpers.Json" version="2.4.1.2" targetFramework="net472" />
<package id="Handlebars.Net.Helpers.Random" version="2.4.1.2" targetFramework="net472" />
<package id="Handlebars.Net.Helpers.Xeger" version="2.4.1.2" targetFramework="net472" />
<package id="Handlebars.Net.Helpers.XPath" version="2.4.1.2" 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" />
@@ -62,7 +62,7 @@
<package id="Humanizer.Core.zh-Hans" version="2.14.1" targetFramework="net472" />
<package id="Humanizer.Core.zh-Hant" version="2.14.1" targetFramework="net472" />
<package id="JmesPath.Net" version="1.0.125" targetFramework="net472" />
<package id="log4net" version="2.0.17" targetFramework="net472" />
<package id="log4net" version="2.0.15" targetFramework="net472" />
<package id="Microsoft.AspNet.WebApi.Client" version="5.2.8" targetFramework="net472" />
<package id="Microsoft.AspNetCore" version="2.2.0" targetFramework="net472" />
<package id="Microsoft.AspNetCore.Authentication.Abstractions" version="2.2.0" 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.34.0" targetFramework="net472" />
<package id="System.IO.Pipelines" version="4.5.3" targetFramework="net472" />
<package id="System.Linq.Dynamic.Core" version="1.3.14" targetFramework="net472" />
<package id="System.Linq.Dynamic.Core" version="1.3.1" targetFramework="net472" />
<package id="System.Memory" version="4.5.5" targetFramework="net472" />
<package id="System.Numerics.Vectors" version="4.5.0" targetFramework="net472" />
<package id="System.Reflection.Metadata" version="1.6.0" targetFramework="net472" />
@@ -151,6 +151,6 @@
<package id="System.Threading.Tasks.Extensions" version="4.5.4" targetFramework="net472" />
<package id="System.ValueTuple" version="4.5.0" targetFramework="net472" />
<package id="TinyMapper" version="3.0.3" targetFramework="net472" />
<package id="XPath2" version="1.1.5" targetFramework="net472" />
<package id="XPath2.Extensions" version="1.1.5" targetFramework="net472" />
<package id="XPath2" version="1.1.4" targetFramework="net472" />
<package id="XPath2.Extensions" version="1.1.4" targetFramework="net472" />
</packages>

View File

@@ -18,5 +18,6 @@ public class DynamicDataGeneration : WireMockOpenApiParserDynamicExampleValues
Pattern = $"[0-9A-Z]{{{maxLength}}}"
}).Generate() ?? "example-string";
}
set { }
}
}

6
nuget.config Normal file
View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<add key="nuget.org" value="https://www.nuget.org/api/v2/" />
</packageSources>
</configuration>

6907
report/coverage.info Normal file

File diff suppressed because it is too large Load Diff

12431
report/coverage.opencover.xml Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,5 @@
dotnet test ..\test\WireMock.Net.Tests\WireMock.Net.Tests.csproj -c Debug -f netcoreapp2.1 /p:CollectCoverage=true /p:CoverletOutputFormat=\"opencover,lcov\" /p:CoverletOutput="../../report/"
%USERPROFILE%\.nuget\packages\ReportGenerator\3.1.2\tools\ReportGenerator.exe -reports:"coverage.opencover.xml" -targetdir:"coverlet"
start coverlet\index.htm

View File

@@ -1,130 +0,0 @@
using System;
using System.Collections.Generic;
// ReSharper disable once CheckNamespace
namespace WireMock.Admin.Mappings;
/// <summary>
/// BodyModelBuilder
/// </summary>
public partial class BodyModelBuilder
{
public BodyModelBuilder WithNotNullOrEmptyMatcher(bool rejectOnMatch = false)
{
return WithMatcher(mb => mb
.WithName("NotNullOrEmptyMatcher")
.WithRejectOnMatch(rejectOnMatch)
);
}
public BodyModelBuilder WithCSharpCodeMatcher(string pattern, bool rejectOnMatch = false)
{
return WithMatcher("CSharpCodeMatcher", pattern, rejectOnMatch);
}
public BodyModelBuilder WithLinqMatcher(string pattern, bool rejectOnMatch = false)
{
return WithMatcher("LinqMatcher", pattern, rejectOnMatch);
}
public BodyModelBuilder WithExactMatcher(string pattern, bool rejectOnMatch = false)
{
return WithMatcher("ExactMatcher", pattern, rejectOnMatch);
}
public BodyModelBuilder WithExactObjectMatcher(object value, bool rejectOnMatch = false)
{
return WithMatcher("ExactObjectMatcher", value, rejectOnMatch);
}
public BodyModelBuilder WithGraphQLMatcher(string pattern, IDictionary<string, Type>? customScalars = null, bool rejectOnMatch = false)
{
return WithMatcher(mb => mb
.WithName("GraphQLMatcher")
.WithCustomScalars(customScalars)
.WithPattern(pattern)
.WithRejectOnMatch(rejectOnMatch)
);
}
public BodyModelBuilder WithProtoBufMatcher(string pattern, bool rejectOnMatch = false)
{
return WithMatcher(mb => mb
.WithName("ProtoBufMatcher")
.WithPattern(pattern)
.WithRejectOnMatch(rejectOnMatch)
);
}
public BodyModelBuilder WithRegexMatcher(string pattern, bool ignoreCase = false, bool rejectOnMatch = false)
{
return WithMatcher(mb => mb
.WithName("RegexMatcher")
.WithPattern(pattern)
.WithIgnoreCase(ignoreCase)
.WithRejectOnMatch(rejectOnMatch)
);
}
public BodyModelBuilder WithJsonMatcher(string pattern, bool ignoreCase = false, bool useRegex = false, bool rejectOnMatch = false)
{
return WithMatcher(mb => mb
.WithName("JsonMatcher")
.WithPattern(pattern)
.WithIgnoreCase(ignoreCase)
.WithRegex(useRegex)
.WithRejectOnMatch(rejectOnMatch)
);
}
public BodyModelBuilder WithJsonPartialMatcher(string pattern, bool ignoreCase = false, bool useRegex = false, bool rejectOnMatch = false)
{
return WithMatcher(mb => mb
.WithName("JsonPartialMatcher")
.WithPattern(pattern)
.WithIgnoreCase(ignoreCase)
.WithRegex(useRegex)
.WithRejectOnMatch(rejectOnMatch)
);
}
public BodyModelBuilder WithJsonPathMatcher(string pattern, bool rejectOnMatch = false)
{
return WithMatcher("JsonPathMatcher", pattern, rejectOnMatch);
}
public BodyModelBuilder WithJmesPathMatcher(string pattern, bool rejectOnMatch = false)
{
return WithMatcher("JmesPathMatcher", pattern, rejectOnMatch);
}
public BodyModelBuilder WithXPathMatcher(string pattern, XmlNamespace[]? xmlNamespaceMap = null, bool rejectOnMatch = false)
{
return WithMatcher(mb => mb
.WithName("PathMatcher")
.WithPattern(pattern)
.WithXmlNamespaceMap(xmlNamespaceMap)
.WithRejectOnMatch(rejectOnMatch)
);
}
public BodyModelBuilder WithWildcardMatcher(string pattern, bool ignoreCase = false, bool rejectOnMatch = false)
{
return WithMatcher("WildcardMatcher", pattern, rejectOnMatch, ignoreCase);
}
public BodyModelBuilder WithSimMetricsMatcher(string pattern, bool ignoreCase = false, bool rejectOnMatch = false)
{
return WithMatcher("SimMetricsMatcher", pattern, rejectOnMatch, ignoreCase);
}
private BodyModelBuilder WithMatcher(string name, object pattern, bool rejectOnMatch, bool ignoreCase = false)
{
return WithMatcher(mb => mb
.WithName(name)
.WithPattern(pattern)
.WithRejectOnMatch(rejectOnMatch)
.WithIgnoreCase(ignoreCase)
);
}
}

View File

@@ -23,10 +23,10 @@ public class WireMockOpenApiParserDynamicExampleValues : IWireMockOpenApiParserE
public virtual double Double => RandomizerFactory.GetRandomizer(new FieldOptionsDouble()).Generate() ?? 4.2d;
/// <inheritdoc />
public virtual Func<DateTime> Date => () => RandomizerFactory.GetRandomizer(new FieldOptionsDateTime()).Generate() ?? System.DateTime.UtcNow.Date;
public virtual Func<DateTime> Date { get { return () => RandomizerFactory.GetRandomizer(new FieldOptionsDateTime()).Generate() ?? System.DateTime.UtcNow.Date; } }
/// <inheritdoc />
public virtual Func<DateTime> DateTime => () => RandomizerFactory.GetRandomizer(new FieldOptionsDateTime()).Generate() ?? System.DateTime.UtcNow;
public virtual Func<DateTime> DateTime { get { return () => RandomizerFactory.GetRandomizer(new FieldOptionsDateTime()).Generate() ?? System.DateTime.UtcNow; } }
/// <inheritdoc />
public virtual byte[] Bytes => RandomizerFactory.GetRandomizer(new FieldOptionsBytes()).Generate();

View File

@@ -1,9 +1,3 @@
using System;
using System.Net.Http.Headers;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Stef.Validation;
using WireMock.Client.Builders;
namespace WireMock.Client.Extensions;
@@ -13,77 +7,13 @@ namespace WireMock.Client.Extensions;
/// </summary>
public static class WireMockAdminApiExtensions
{
private const int MaxRetries = 5;
private const int InitialWaitingTimeInMilliSeconds = 500;
private const string HealthStatusHealthy = "Healthy";
/// <summary>
/// Get a new <see cref="AdminApiMappingBuilder"/> for the <see cref="IWireMockAdminApi"/>.
/// </summary>
/// <param name="adminApi">See <see cref="IWireMockAdminApi"/>.</param>
/// <param name="api">See <see cref="IWireMockAdminApi"/>.</param>
/// <returns></returns>
public static AdminApiMappingBuilder GetMappingBuilder(this IWireMockAdminApi adminApi)
public static AdminApiMappingBuilder GetMappingBuilder(this IWireMockAdminApi api)
{
return new AdminApiMappingBuilder(adminApi);
}
/// <summary>
/// Set basic authentication to access the <see cref="IWireMockAdminApi"/>.
/// </summary>
/// <param name="adminApi">See <see cref="IWireMockAdminApi"/>.</param>
/// <param name="username">The admin username.</param>
/// <param name="password">The admin password.</param>
/// <returns><see cref="IWireMockAdminApi"/></returns>
public static IWireMockAdminApi WithAuthorization(this IWireMockAdminApi adminApi, string username, string password)
{
Guard.NotNull(adminApi);
Guard.NotNullOrEmpty(username);
Guard.NotNullOrEmpty(password);
adminApi.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(Encoding.UTF8.GetBytes($"{username}:{password}")));
return adminApi;
}
/// <summary>
/// Wait for the WireMock.Net server to be healthy. (The "/__admin/health" returns "Healthy").
/// </summary>
/// <param name="adminApi">See <see cref="IWireMockAdminApi"/>.</param>
/// <param name="maxRetries">The maximum number of retries. Default is <c>5</c>.</param>
/// <param name="cancellationToken">The optional <see cref="CancellationToken"/>.</param>
/// <returns>A completed Task in case the health endpoint is available, else throws a <see cref="InvalidOperationException"/>.</returns>
public static async Task WaitForHealthAsync(this IWireMockAdminApi adminApi, int maxRetries = MaxRetries, CancellationToken cancellationToken = default)
{
Guard.NotNull(adminApi);
var retries = 0;
var waitTime = InitialWaitingTimeInMilliSeconds;
var totalWaitTime = waitTime;
var isHealthy = await IsHealthyAsync(adminApi, cancellationToken);
while (!isHealthy && retries < MaxRetries && !cancellationToken.IsCancellationRequested)
{
waitTime = (int)(InitialWaitingTimeInMilliSeconds * Math.Pow(2, retries));
await Task.Delay(waitTime, cancellationToken);
isHealthy = await IsHealthyAsync(adminApi, cancellationToken);
retries++;
totalWaitTime += waitTime;
}
if (retries >= MaxRetries)
{
throw new InvalidOperationException($"The /__admin/health endpoint did not return 'Healthy' after {MaxRetries} retries and {totalWaitTime / 1000.0:0.0} seconds.");
}
}
private static async Task<bool> IsHealthyAsync(IWireMockAdminApi adminApi, CancellationToken cancellationToken)
{
try
{
var status = await adminApi.GetHealthAsync(cancellationToken);
return string.Equals(status, HealthStatusHealthy, StringComparison.OrdinalIgnoreCase);
}
catch
{
return false;
}
return new AdminApiMappingBuilder(api);
}
}

View File

@@ -24,24 +24,12 @@ public interface IWireMockAdminApi
[Header("Authorization")]
AuthenticationHeaderValue Authorization { get; set; }
/// <summary>
/// Get health status.
/// </summary>
/// <param name="cancellationToken">The optional cancellationToken.</param>
/// <returns>
/// Returns HttpStatusCode <c>200</c> with a value <c>Healthy</c> to indicate that WireMock.Net is healthy.
/// Else it returns HttpStatusCode <c>404</c>.
/// </returns>
[Get("health")]
[AllowAnyStatusCode]
Task<string> GetHealthAsync(CancellationToken cancellationToken = default);
/// <summary>
/// Get the settings.
/// </summary>
/// <returns>SettingsModel</returns>
[Get("settings")]
Task<SettingsModel> GetSettingsAsync(CancellationToken cancellationToken = default);
Task<SettingsModel> GetSettingsAsync();
/// <summary>
/// Update the settings.

View File

@@ -29,7 +29,7 @@
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Stef.Validation" Version="0.1.1" />
<PackageReference Include="Testcontainers" Version="[3.9.0]" />
<PackageReference Include="Testcontainers" Version="[3.7.0]" />
<PackageReference Include="JetBrains.Annotations" VersionOverride="2022.3.1" PrivateAssets="All" Version="2023.3.0" />
</ItemGroup>

View File

@@ -4,10 +4,10 @@ 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;
using WireMock.Client.Extensions;
using WireMock.Http;
namespace WireMock.Net.Testcontainers;
@@ -25,7 +25,8 @@ public sealed class WireMockContainer : DockerContainer
/// Initializes a new instance of the <see cref="WireMockContainer" /> class.
/// </summary>
/// <param name="configuration">The container configuration.</param>
public WireMockContainer(WireMockConfiguration configuration) : base(configuration)
/// <param name="logger">The logger.</param>
public WireMockContainer(WireMockConfiguration configuration, ILogger logger) : base(configuration, logger)
{
_configuration = Guard.NotNull(configuration);
}
@@ -46,7 +47,13 @@ public sealed class WireMockContainer : DockerContainer
ValidateIfRunning();
var api = RestClient.For<IWireMockAdminApi>(GetPublicUri());
return _configuration.HasBasicAuthentication ? api.WithAuthorization(_configuration.Username!, _configuration.Password!) : api;
if (_configuration.HasBasicAuthentication)
{
api.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(Encoding.ASCII.GetBytes($"{_configuration.Username}:{_configuration.Password}")));
}
return api;
}
/// <summary>

View File

@@ -138,7 +138,7 @@ public sealed class WireMockContainerBuilder : ContainerBuilder<WireMockContaine
{
Validate();
return new WireMockContainer(DockerResourceConfiguration);
return new WireMockContainer(DockerResourceConfiguration, TestcontainersSettings.Logger);
}
/// <inheritdoc />

View File

@@ -15,11 +15,7 @@ public class WireMockConsoleLogger : IWireMockLogger
/// </summary>
public WireMockConsoleLogger()
{
try
{
Console.OutputEncoding = System.Text.Encoding.UTF8;
}
catch { }
Console.OutputEncoding = System.Text.Encoding.UTF8;
}
/// <see cref="IWireMockLogger.Debug"/>

View File

@@ -31,6 +31,7 @@ public class JsonMatcher : IJsonMatcher
public bool Regex { get; }
private readonly JToken _valueAsJToken;
private readonly Func<JToken, JToken> _jTokenConverter;
/// <summary>
/// Initializes a new instance of the <see cref="JsonMatcher"/> class.
@@ -69,6 +70,7 @@ public class JsonMatcher : IJsonMatcher
Value = value;
_valueAsJToken = JsonUtils.ConvertValueToJToken(value);
_jTokenConverter = ignoreCase ? Rename : jToken => jToken;
}
/// <inheritdoc />
@@ -84,7 +86,7 @@ public class JsonMatcher : IJsonMatcher
{
var inputAsJToken = JsonUtils.ConvertValueToJToken(input);
var match = IsMatch(RenameJToken(_valueAsJToken), RenameJToken(inputAsJToken));
var match = IsMatch(_jTokenConverter(_valueAsJToken), _jTokenConverter(inputAsJToken));
score = MatchScores.ToScore(match);
}
catch (Exception ex)
@@ -177,59 +179,38 @@ public class JsonMatcher : IJsonMatcher
}
}
// https://stackoverflow.com/questions/11679804/json-net-rename-properties
private JToken RenameJToken(JToken input)
{
if (!IgnoreCase)
{
return input;
}
return input switch
{
JProperty property => RenameJProperty(property),
JArray array => RenameJArray(array),
JObject obj => RenameJObject(obj),
_ => input
};
}
private JProperty RenameJProperty(JProperty property)
{
if (!IgnoreCase)
{
return property;
}
var propertyValue = property.Value;
if (propertyValue.Type == JTokenType.String && !Regex)
{
var stringValue = propertyValue.Value<string>()!;
propertyValue = ToUpper(stringValue);
}
return new JProperty(ToUpper(property.Name)!, RenameJToken(propertyValue));
}
private JArray RenameJArray(JArray array)
{
if (Regex)
{
return array;
}
var renamedValues = array.Select(RenameJToken);
return new JArray(renamedValues);
}
private JObject RenameJObject(JObject obj)
{
var renamedProperties = obj.Properties().Select(RenameJProperty);
return new JObject(renamedProperties);
}
private static string? ToUpper(string? input)
{
return input?.ToUpperInvariant();
}
// https://stackoverflow.com/questions/11679804/json-net-rename-properties
private static JToken Rename(JToken json)
{
if (json is JProperty property)
{
JToken propertyValue = property.Value;
if (propertyValue.Type == JTokenType.String)
{
string stringValue = propertyValue.Value<string>()!;
propertyValue = ToUpper(stringValue);
}
return new JProperty(ToUpper(property.Name)!, Rename(propertyValue));
}
if (json is JArray array)
{
var renamedValues = array.Select(Rename);
return new JArray(renamedValues);
}
if (json is JObject obj)
{
var renamedProperties = obj.Properties().Select(Rename);
return new JObject(renamedProperties);
}
return json;
}
}

View File

@@ -71,21 +71,23 @@ public class RequestMessageMultiPartMatcher : IRequestMatcher
{
var mimePartMatchers = Matchers.OfType<MimePartMatcher>().ToArray();
foreach (var mimePartMatcher in Matchers.OfType<MimePartMatcher>().ToArray())
foreach (var mimePart in message.BodyParts.OfType<MimeKit.MimePart>())
{
score = MatchScores.Mismatch;
foreach (var mimeBodyPart in message.BodyParts.OfType<MimeKit.MimePart>())
var matchesForMimePart = new List<MatchResult> { default };
matchesForMimePart.AddRange(mimePartMatchers.Select(matcher => matcher.IsMatch(mimePart)));
score = matchesForMimePart.Select(m => m.Score).Max();
if (MatchScores.IsPerfect(score))
{
var matchResult = mimePartMatcher.IsMatch(mimeBodyPart);
if (matchResult.IsPerfect())
if (MatchOperator == MatchOperator.Or)
{
score = MatchScores.Perfect;
break;
}
}
if ((MatchOperator == MatchOperator.Or && MatchScores.IsPerfect(score))
|| (MatchOperator == MatchOperator.And && !MatchScores.IsPerfect(score)))
else
{
score = MatchScores.Mismatch;
break;
}
}

View File

@@ -1,7 +1,5 @@
#if USE_ASPNETCORE && !NETSTANDARD1_3
using System;
using System.Collections.Generic;
using System.Net;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Server.Kestrel.Core;
using Microsoft.AspNetCore.Server.Kestrel.Https;
@@ -27,7 +25,7 @@ namespace WireMock.Owin
{
if (urlDetail.IsHttps)
{
Listen(kestrelOptions, urlDetail, listenOptions =>
kestrelOptions.ListenAnyIP(urlDetail.Port, listenOptions =>
{
listenOptions.UseHttps(options =>
{
@@ -39,11 +37,10 @@ namespace WireMock.Owin
wireMockMiddlewareOptions.X509ThumbprintOrSubjectName,
wireMockMiddlewareOptions.X509CertificateFilePath,
wireMockMiddlewareOptions.X509CertificatePassword,
urlDetail.Host
);
urlDetail.Host);
}
options.ClientCertificateMode = (ClientCertificateMode)wireMockMiddlewareOptions.ClientCertificateMode;
options.ClientCertificateMode = (ClientCertificateMode) wireMockMiddlewareOptions.ClientCertificateMode;
if (wireMockMiddlewareOptions.AcceptAnyClientCertificate)
{
options.ClientCertificateValidation = (_, _, _) => true;
@@ -55,41 +52,20 @@ namespace WireMock.Owin
listenOptions.Protocols = HttpProtocols.Http2;
}
});
continue;
}
if (urlDetail.IsHttp2)
else if (urlDetail.IsHttp2)
{
Listen(kestrelOptions, urlDetail, listenOptions =>
kestrelOptions.ListenAnyIP(urlDetail.Port, listenOptions =>
{
listenOptions.Protocols = HttpProtocols.Http2;
});
continue;
}
Listen(kestrelOptions, urlDetail, _ => { });
else
{
kestrelOptions.ListenAnyIP(urlDetail.Port);
}
}
}
private static void Listen(KestrelServerOptions kestrelOptions, HostUrlDetails urlDetail, Action<ListenOptions> configure)
{
// Listens on ::1 and 127.0.0.1 with the given port.
if (urlDetail is { Port: > 0, Host: "localhost" or "127.0.0.1" or "0.0.0.0" or "::1" })
{
kestrelOptions.ListenLocalhost(urlDetail.Port, configure);
return;
}
// Try to parse the host as a valid IP address and bind to the given IP address and port.
if (IPAddress.TryParse(urlDetail.Host, out var ipAddress))
{
kestrelOptions.Listen(ipAddress, urlDetail.Port, configure);
return;
}
// Otherwise, listen on all IPs.
kestrelOptions.ListenAnyIP(urlDetail.Port, configure);
}
}
internal static class IWebHostBuilderExtensions

View File

@@ -6,7 +6,7 @@ namespace WireMock.Owin;
internal class HostUrlOptions
{
private const string Star = "*";
private const string Localhost = "localhost";
public ICollection<string>? Urls { get; set; }
@@ -25,16 +25,16 @@ internal class HostUrlOptions
{
var port = Port > 0 ? Port.Value : FindFreeTcpPort();
var scheme = HostingScheme == HostingScheme.Https ? "https" : "http";
list.Add(new HostUrlDetails { IsHttps = HostingScheme == HostingScheme.Https, IsHttp2 = UseHttp2 == true, Url = $"{scheme}://{Star}:{port}", Scheme = scheme, Host = Star, Port = port });
list.Add(new HostUrlDetails { IsHttps = HostingScheme == HostingScheme.Https, IsHttp2 = UseHttp2 == true, Url = $"{scheme}://{Localhost}:{port}", Scheme = scheme, Host = Localhost, Port = port });
}
if (HostingScheme == HostingScheme.HttpAndHttps)
{
var httpPort = Port > 0 ? Port.Value : FindFreeTcpPort();
list.Add(new HostUrlDetails { IsHttps = false, IsHttp2 = UseHttp2 == true, Url = $"http://{Star}:{httpPort}", Scheme = "http", Host = Star, Port = httpPort });
list.Add(new HostUrlDetails { IsHttps = false, IsHttp2 = UseHttp2 == true, Url = $"http://{Localhost}:{httpPort}", Scheme = "http", Host = Localhost, Port = httpPort });
var httpsPort = FindFreeTcpPort(); // In this scenario, always get a free port for https.
list.Add(new HostUrlDetails { IsHttps = true, IsHttp2 = UseHttp2 == true, Url = $"https://{Star}:{httpsPort}", Scheme = "https", Host = Star, Port = httpsPort });
list.Add(new HostUrlDetails { IsHttps = true, IsHttp2 = UseHttp2 == true, Url = $"https://{Localhost}:{httpsPort}", Scheme = "https", Host = Localhost, Port = httpsPort });
}
}
else

View File

@@ -51,13 +51,23 @@ public interface IBodyRequestBuilder : IProtoBufRequestBuilder
IRequestBuilder WithBody(object body, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch);
/// <summary>
/// WithBodyAsJson: A <see cref="JsonMatcher"/> will be used to match this object.
/// WithBody : Body as a string response based on a object (which will be converted to a JSON string using NewtonSoft.Json).
/// </summary>
/// <param name="body">The body.</param>
/// <param name="matchBehaviour">The match behaviour [default is AcceptOnMatch].</param>
/// <returns>A <see cref="IRequestBuilder"/>.</returns>
IRequestBuilder WithBodyAsJson(object body, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch);
/// <summary>
/// WithBody : Body as a string response based on a object (which will be converted to a JSON string using the <see cref="IJsonConverter"/>).
/// </summary>
/// <param name="body">The body.</param>
/// <param name="converter">The JsonConverter.</param>
/// <param name="options">The <see cref="JsonConverterOptions"/> [optional].</param>
/// <param name="matchBehaviour">The match behaviour [default is AcceptOnMatch].</param>
/// <returns>A <see cref="IRequestBuilder"/>.</returns>
IRequestBuilder WithBodyAsJson(object body, IJsonConverter converter, JsonConverterOptions? options = null, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch);
/// <summary>
/// WithBody: func (string)
/// </summary>

View File

@@ -2,6 +2,8 @@
// For more details see 'mock4net/LICENSE.txt' and 'mock4net/readme.md' in this project root.
using System;
using System.Collections.Generic;
using JsonConverter.Abstractions;
using Newtonsoft.Json;
using Stef.Validation;
using WireMock.Matchers;
using WireMock.Matchers.Request;
@@ -35,7 +37,19 @@ public partial class Request
/// <inheritdoc />
public IRequestBuilder WithBodyAsJson(object body, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch)
{
return WithBody(new IMatcher[] { new JsonMatcher(matchBehaviour, body) });
var bodyAsJsonString = JsonConvert.SerializeObject(body);
_requestMatchers.Add(new RequestMessageBodyMatcher(matchBehaviour, bodyAsJsonString));
return this;
}
/// <inheritdoc />
public IRequestBuilder WithBodyAsJson(object body, IJsonConverter converter, JsonConverterOptions? options = null, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch)
{
Guard.NotNull(converter);
var bodyAsJsonString = converter.Serialize(body, options);
_requestMatchers.Add(new RequestMessageBodyMatcher(matchBehaviour, bodyAsJsonString));
return this;
}
/// <inheritdoc />

View File

@@ -143,21 +143,25 @@ internal class MappingConverter
if (requestMessageBodyMatcher is { Matchers: { } })
{
var firstMatcher = requestMessageBodyMatcher.Matchers.FirstOrDefault();
if (firstMatcher is WildcardMatcher wildcardMatcher && wildcardMatcher.GetPatterns().Any())
if (requestMessageBodyMatcher.Matchers.OfType<WildcardMatcher>().FirstOrDefault() is { } wildcardMatcher && wildcardMatcher.GetPatterns().Any())
{
sb.AppendLine($" .WithBody({GetString(wildcardMatcher)})");
}
if (firstMatcher is JsonMatcher jsonMatcher)
else if (requestMessageBodyMatcher.Matchers.OfType<JsonPartialMatcher>().FirstOrDefault() is { Value: { } } jsonPartialMatcher)
{
var matcherType = jsonMatcher.GetType().Name;
sb.AppendLine($" .WithBody(new {matcherType}(");
sb.AppendLine($" value: {ConvertToAnonymousObjectDefinition(jsonMatcher.Value, 3)},");
sb.AppendLine($" ignoreCase: {ToCSharpBooleanLiteral(jsonMatcher.IgnoreCase)},");
sb.AppendLine($" regex: {ToCSharpBooleanLiteral(jsonMatcher.Regex)}");
sb.AppendLine(@" ))");
sb.AppendLine(@$" .WithBody(new JsonPartialMatcher(
value: {ToCSharpStringLiteral(jsonPartialMatcher.Value.ToString())},
ignoreCase: {ToCSharpBooleanLiteral(jsonPartialMatcher.IgnoreCase)},
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)},
regex: {ToCSharpBooleanLiteral(jsonPartialWildcardMatcher.Regex)}
))");
}
}

View File

@@ -19,7 +19,6 @@ using WireMock.Matchers.Request;
using WireMock.RequestBuilders;
using WireMock.ResponseProviders;
using WireMock.Serialization;
using WireMock.Settings;
using WireMock.Types;
using WireMock.Util;
@@ -31,116 +30,96 @@ namespace WireMock.Server;
public partial class WireMockServer
{
private const int EnhancedFileSystemWatcherTimeoutMs = 1000;
private const string DefaultAdminPathPrefix = "/__admin";
private const string AdminFiles = "/__admin/files";
private const string AdminMappings = "/__admin/mappings";
private const string AdminMappingsCode = "/__admin/mappings/code";
private const string AdminMappingsWireMockOrg = "/__admin/mappings/wiremock.org";
private const string AdminRequests = "/__admin/requests";
private const string AdminSettings = "/__admin/settings";
private const string AdminScenarios = "/__admin/scenarios";
private const string AdminOpenApi = "/__admin/openapi";
private const string QueryParamReloadStaticMappings = "reloadStaticMappings";
private static readonly Guid ProxyMappingGuid = new("e59914fd-782e-428e-91c1-4810ffb86567");
private static readonly RegexMatcher AdminRequestContentTypeJson = new ContentTypeMatcher(WireMockConstants.ContentTypeJson, true);
private static readonly RegexMatcher AdminMappingsGuidPathMatcher = new(@"^\/__admin\/mappings\/([0-9A-Fa-f]{8}[-][0-9A-Fa-f]{4}[-][0-9A-Fa-f]{4}[-][0-9A-Fa-f]{4}[-][0-9A-Fa-f]{12})$");
private static readonly RegexMatcher AdminMappingsCodeGuidPathMatcher = new(@"^\/__admin\/mappings\/code\/([0-9A-Fa-f]{8}[-][0-9A-Fa-f]{4}[-][0-9A-Fa-f]{4}[-][0-9A-Fa-f]{4}[-][0-9A-Fa-f]{12})$");
private static readonly RegexMatcher AdminRequestsGuidPathMatcher = new(@"^\/__admin\/requests\/([0-9A-Fa-f]{8}[-][0-9A-Fa-f]{4}[-][0-9A-Fa-f]{4}[-][0-9A-Fa-f]{4}[-][0-9A-Fa-f]{12})$");
private static readonly RegexMatcher AdminScenariosNameMatcher = new(@"^\/__admin\/scenarios\/.+$");
private static readonly RegexMatcher AdminScenariosNameWithResetMatcher = new(@"^\/__admin\/scenarios\/.+\/reset$");
private EnhancedFileSystemWatcher? _enhancedFileSystemWatcher;
private AdminPaths? _adminPaths;
private sealed class AdminPaths
{
private readonly string _prefix;
private readonly string _prefixEscaped;
public AdminPaths(WireMockServerSettings settings)
{
_prefix = settings.AdminPath ?? DefaultAdminPathPrefix;
_prefixEscaped = _prefix.Replace("/", "\\/");
}
public string Files => $"{_prefix}/files";
public string Health => $"{_prefix}/health";
public string Mappings => $"{_prefix}/mappings";
public string MappingsCode => $"{_prefix}/mappings/code";
public string MappingsWireMockOrg => $"{_prefix}mappings/wiremock.org";
public string Requests => $"{_prefix}/requests";
public string Settings => $"{_prefix}/settings";
public string Scenarios => $"{_prefix}/scenarios";
public string OpenApi => $"{_prefix}/openapi";
public RegexMatcher MappingsGuidPathMatcher => new($"^{_prefixEscaped}\\/mappings\\/([0-9A-Fa-f]{{8}}[-][0-9A-Fa-f]{{4}}[-][0-9A-Fa-f]{{4}}[-][0-9A-Fa-f]{{4}}[-][0-9A-Fa-f]{{12}})$");
public RegexMatcher MappingsCodeGuidPathMatcher => new($"^{_prefixEscaped}\\/mappings\\/code\\/([0-9A-Fa-f]{{8}}[-][0-9A-Fa-f]{{4}}[-][0-9A-Fa-f]{{4}}[-][0-9A-Fa-f]{{4}}[-][0-9A-Fa-f]{{12}})$");
public RegexMatcher RequestsGuidPathMatcher => new($"^{_prefixEscaped}\\/requests\\/([0-9A-Fa-f]{{8}}[-][0-9A-Fa-f]{{4}}[-][0-9A-Fa-f]{{4}}[-][0-9A-Fa-f]{{4}}[-][0-9A-Fa-f]{{12}})$");
public RegexMatcher ScenariosNameMatcher => new($"^{_prefixEscaped}\\/scenarios\\/.+$");
public RegexMatcher ScenariosNameWithResetMatcher => new($"^{_prefixEscaped}\\/scenarios\\/.+\\/reset$");
public RegexMatcher FilesFilenamePathMatcher => new($"^{_prefixEscaped}\\/files\\/.+$");
}
#region InitAdmin
private void InitAdmin()
{
_adminPaths = new AdminPaths(_settings);
// __admin/health
Given(Request.Create().WithPath(_adminPaths.Health).UsingGet()).AtPriority(WireMockConstants.AdminPriority).RespondWith(new DynamicResponseProvider(HealthGet));
// __admin/settings
Given(Request.Create().WithPath(_adminPaths.Settings).UsingGet()).AtPriority(WireMockConstants.AdminPriority).RespondWith(new DynamicResponseProvider(SettingsGet));
Given(Request.Create().WithPath(_adminPaths.Settings).UsingMethod("PUT", "POST").WithHeader(HttpKnownHeaderNames.ContentType, AdminRequestContentTypeJson)).AtPriority(WireMockConstants.AdminPriority).RespondWith(new DynamicResponseProvider(SettingsUpdate));
Given(Request.Create().WithPath(AdminSettings).UsingGet()).AtPriority(WireMockConstants.AdminPriority).RespondWith(new DynamicResponseProvider(SettingsGet));
Given(Request.Create().WithPath(AdminSettings).UsingMethod("PUT", "POST").WithHeader(HttpKnownHeaderNames.ContentType, AdminRequestContentTypeJson)).AtPriority(WireMockConstants.AdminPriority).RespondWith(new DynamicResponseProvider(SettingsUpdate));
// __admin/mappings
Given(Request.Create().WithPath(_adminPaths.Mappings).UsingGet()).AtPriority(WireMockConstants.AdminPriority).RespondWith(new DynamicResponseProvider(MappingsGet));
Given(Request.Create().WithPath(_adminPaths.Mappings).UsingPost().WithHeader(HttpKnownHeaderNames.ContentType, AdminRequestContentTypeJson)).AtPriority(WireMockConstants.AdminPriority).RespondWith(new DynamicResponseProvider(MappingsPost));
Given(Request.Create().WithPath(_adminPaths.Mappings).UsingDelete()).AtPriority(WireMockConstants.AdminPriority).RespondWith(new DynamicResponseProvider(MappingsDelete));
Given(Request.Create().WithPath(AdminMappings).UsingGet()).AtPriority(WireMockConstants.AdminPriority).RespondWith(new DynamicResponseProvider(MappingsGet));
Given(Request.Create().WithPath(AdminMappings).UsingPost().WithHeader(HttpKnownHeaderNames.ContentType, AdminRequestContentTypeJson)).AtPriority(WireMockConstants.AdminPriority).RespondWith(new DynamicResponseProvider(MappingsPost));
Given(Request.Create().WithPath(AdminMappings).UsingDelete()).AtPriority(WireMockConstants.AdminPriority).RespondWith(new DynamicResponseProvider(MappingsDelete));
// __admin/mappings/code
Given(Request.Create().WithPath(_adminPaths.MappingsCode).UsingGet()).AtPriority(WireMockConstants.AdminPriority).RespondWith(new DynamicResponseProvider(MappingsCodeGet));
Given(Request.Create().WithPath(AdminMappingsCode).UsingGet()).AtPriority(WireMockConstants.AdminPriority).RespondWith(new DynamicResponseProvider(MappingsCodeGet));
// __admin/mappings/wiremock.org
Given(Request.Create().WithPath(_adminPaths.MappingsWireMockOrg).UsingPost().WithHeader(HttpKnownHeaderNames.ContentType, AdminRequestContentTypeJson)).AtPriority(WireMockConstants.AdminPriority).RespondWith(new DynamicResponseProvider(MappingsPostWireMockOrg));
Given(Request.Create().WithPath(AdminMappingsWireMockOrg).UsingPost().WithHeader(HttpKnownHeaderNames.ContentType, AdminRequestContentTypeJson)).AtPriority(WireMockConstants.AdminPriority).RespondWith(new DynamicResponseProvider(MappingsPostWireMockOrg));
// __admin/mappings/reset
Given(Request.Create().WithPath(_adminPaths.Mappings + "/reset").UsingPost()).AtPriority(WireMockConstants.AdminPriority).RespondWith(new DynamicResponseProvider(MappingsReset));
Given(Request.Create().WithPath(AdminMappings + "/reset").UsingPost()).AtPriority(WireMockConstants.AdminPriority).RespondWith(new DynamicResponseProvider(MappingsReset));
// __admin/mappings/{guid}
Given(Request.Create().WithPath(_adminPaths.MappingsGuidPathMatcher).UsingGet()).AtPriority(WireMockConstants.AdminPriority).RespondWith(new DynamicResponseProvider(MappingGet));
Given(Request.Create().WithPath(_adminPaths.MappingsGuidPathMatcher).UsingPut().WithHeader(HttpKnownHeaderNames.ContentType, AdminRequestContentTypeJson)).AtPriority(WireMockConstants.AdminPriority).RespondWith(new DynamicResponseProvider(MappingPut));
Given(Request.Create().WithPath(_adminPaths.MappingsGuidPathMatcher).UsingDelete()).AtPriority(WireMockConstants.AdminPriority).RespondWith(new DynamicResponseProvider(MappingDelete));
Given(Request.Create().WithPath(AdminMappingsGuidPathMatcher).UsingGet()).AtPriority(WireMockConstants.AdminPriority).RespondWith(new DynamicResponseProvider(MappingGet));
Given(Request.Create().WithPath(AdminMappingsGuidPathMatcher).UsingPut().WithHeader(HttpKnownHeaderNames.ContentType, AdminRequestContentTypeJson)).AtPriority(WireMockConstants.AdminPriority).RespondWith(new DynamicResponseProvider(MappingPut));
Given(Request.Create().WithPath(AdminMappingsGuidPathMatcher).UsingDelete()).AtPriority(WireMockConstants.AdminPriority).RespondWith(new DynamicResponseProvider(MappingDelete));
// __admin/mappings/code/{guid}
Given(Request.Create().WithPath(_adminPaths.MappingsCodeGuidPathMatcher).UsingGet()).AtPriority(WireMockConstants.AdminPriority).RespondWith(new DynamicResponseProvider(MappingCodeGet));
Given(Request.Create().WithPath(AdminMappingsCodeGuidPathMatcher).UsingGet()).AtPriority(WireMockConstants.AdminPriority).RespondWith(new DynamicResponseProvider(MappingCodeGet));
// __admin/mappings/save
Given(Request.Create().WithPath($"{_adminPaths.Mappings}/save").UsingPost()).AtPriority(WireMockConstants.AdminPriority).RespondWith(new DynamicResponseProvider(MappingsSave));
Given(Request.Create().WithPath($"{AdminMappings}/save").UsingPost()).AtPriority(WireMockConstants.AdminPriority).RespondWith(new DynamicResponseProvider(MappingsSave));
// __admin/mappings/swagger
Given(Request.Create().WithPath($"{_adminPaths.Mappings}/swagger").UsingGet()).AtPriority(WireMockConstants.AdminPriority).RespondWith(new DynamicResponseProvider(SwaggerGet));
Given(Request.Create().WithPath($"{AdminMappings}/swagger").UsingGet()).AtPriority(WireMockConstants.AdminPriority).RespondWith(new DynamicResponseProvider(SwaggerGet));
// __admin/requests
Given(Request.Create().WithPath(_adminPaths.Requests).UsingGet()).AtPriority(WireMockConstants.AdminPriority).RespondWith(new DynamicResponseProvider(RequestsGet));
Given(Request.Create().WithPath(_adminPaths.Requests).UsingDelete()).AtPriority(WireMockConstants.AdminPriority).RespondWith(new DynamicResponseProvider(RequestsDelete));
Given(Request.Create().WithPath(AdminRequests).UsingGet()).AtPriority(WireMockConstants.AdminPriority).RespondWith(new DynamicResponseProvider(RequestsGet));
Given(Request.Create().WithPath(AdminRequests).UsingDelete()).AtPriority(WireMockConstants.AdminPriority).RespondWith(new DynamicResponseProvider(RequestsDelete));
// __admin/requests/reset
Given(Request.Create().WithPath(_adminPaths.Requests + "/reset").UsingPost()).AtPriority(WireMockConstants.AdminPriority).RespondWith(new DynamicResponseProvider(RequestsDelete));
Given(Request.Create().WithPath(AdminRequests + "/reset").UsingPost()).AtPriority(WireMockConstants.AdminPriority).RespondWith(new DynamicResponseProvider(RequestsDelete));
// __admin/request/{guid}
Given(Request.Create().WithPath(_adminPaths.RequestsGuidPathMatcher).UsingGet()).AtPriority(WireMockConstants.AdminPriority).RespondWith(new DynamicResponseProvider(RequestGet));
Given(Request.Create().WithPath(_adminPaths.RequestsGuidPathMatcher).UsingDelete()).AtPriority(WireMockConstants.AdminPriority).RespondWith(new DynamicResponseProvider(RequestDelete));
Given(Request.Create().WithPath(AdminRequestsGuidPathMatcher).UsingGet()).AtPriority(WireMockConstants.AdminPriority).RespondWith(new DynamicResponseProvider(RequestGet));
Given(Request.Create().WithPath(AdminRequestsGuidPathMatcher).UsingDelete()).AtPriority(WireMockConstants.AdminPriority).RespondWith(new DynamicResponseProvider(RequestDelete));
// __admin/requests/find
Given(Request.Create().WithPath(_adminPaths.Requests + "/find").UsingPost()).AtPriority(WireMockConstants.AdminPriority).RespondWith(new DynamicResponseProvider(RequestsFind));
Given(Request.Create().WithPath(_adminPaths.Requests + "/find").UsingGet().WithParam("mappingGuid", new NotNullOrEmptyMatcher())).AtPriority(WireMockConstants.AdminPriority).RespondWith(new DynamicResponseProvider(RequestsFindByMappingGuid));
Given(Request.Create().WithPath(AdminRequests + "/find").UsingPost()).AtPriority(WireMockConstants.AdminPriority).RespondWith(new DynamicResponseProvider(RequestsFind));
Given(Request.Create().WithPath(AdminRequests + "/find").UsingGet().WithParam("mappingGuid", new NotNullOrEmptyMatcher())).AtPriority(WireMockConstants.AdminPriority).RespondWith(new DynamicResponseProvider(RequestsFindByMappingGuid));
// __admin/scenarios
Given(Request.Create().WithPath(_adminPaths.Scenarios).UsingGet()).AtPriority(WireMockConstants.AdminPriority).RespondWith(new DynamicResponseProvider(ScenariosGet));
Given(Request.Create().WithPath(_adminPaths.Scenarios).UsingDelete()).AtPriority(WireMockConstants.AdminPriority).RespondWith(new DynamicResponseProvider(ScenariosReset));
Given(Request.Create().WithPath(_adminPaths.ScenariosNameMatcher).UsingDelete()).AtPriority(WireMockConstants.AdminPriority).RespondWith(new DynamicResponseProvider(ScenarioReset));
Given(Request.Create().WithPath(AdminScenarios).UsingGet()).AtPriority(WireMockConstants.AdminPriority).RespondWith(new DynamicResponseProvider(ScenariosGet));
Given(Request.Create().WithPath(AdminScenarios).UsingDelete()).AtPriority(WireMockConstants.AdminPriority).RespondWith(new DynamicResponseProvider(ScenariosReset));
Given(Request.Create().WithPath(AdminScenariosNameMatcher).UsingDelete()).AtPriority(WireMockConstants.AdminPriority).RespondWith(new DynamicResponseProvider(ScenarioReset));
// __admin/scenarios/reset
Given(Request.Create().WithPath(_adminPaths.Scenarios + "/reset").UsingPost()).AtPriority(WireMockConstants.AdminPriority).RespondWith(new DynamicResponseProvider(ScenariosReset));
Given(Request.Create().WithPath(_adminPaths.ScenariosNameWithResetMatcher).UsingPost()).AtPriority(WireMockConstants.AdminPriority).RespondWith(new DynamicResponseProvider(ScenarioReset));
Given(Request.Create().WithPath(AdminScenarios + "/reset").UsingPost()).AtPriority(WireMockConstants.AdminPriority).RespondWith(new DynamicResponseProvider(ScenariosReset));
Given(Request.Create().WithPath(AdminScenariosNameWithResetMatcher).UsingPost()).AtPriority(WireMockConstants.AdminPriority).RespondWith(new DynamicResponseProvider(ScenarioReset));
// __admin/files/{filename}
Given(Request.Create().WithPath(_adminPaths.FilesFilenamePathMatcher).UsingPost()).AtPriority(WireMockConstants.AdminPriority).RespondWith(new DynamicResponseProvider(FilePost));
Given(Request.Create().WithPath(_adminPaths.FilesFilenamePathMatcher).UsingPut()).AtPriority(WireMockConstants.AdminPriority).RespondWith(new DynamicResponseProvider(FilePut));
Given(Request.Create().WithPath(_adminPaths.FilesFilenamePathMatcher).UsingGet()).AtPriority(WireMockConstants.AdminPriority).RespondWith(new DynamicResponseProvider(FileGet));
Given(Request.Create().WithPath(_adminPaths.FilesFilenamePathMatcher).UsingHead()).AtPriority(WireMockConstants.AdminPriority).RespondWith(new DynamicResponseProvider(FileHead));
Given(Request.Create().WithPath(_adminPaths.FilesFilenamePathMatcher).UsingDelete()).AtPriority(WireMockConstants.AdminPriority).RespondWith(new DynamicResponseProvider(FileDelete));
Given(Request.Create().WithPath(AdminFilesFilenamePathMatcher).UsingPost()).AtPriority(WireMockConstants.AdminPriority).RespondWith(new DynamicResponseProvider(FilePost));
Given(Request.Create().WithPath(AdminFilesFilenamePathMatcher).UsingPut()).AtPriority(WireMockConstants.AdminPriority).RespondWith(new DynamicResponseProvider(FilePut));
Given(Request.Create().WithPath(AdminFilesFilenamePathMatcher).UsingGet()).AtPriority(WireMockConstants.AdminPriority).RespondWith(new DynamicResponseProvider(FileGet));
Given(Request.Create().WithPath(AdminFilesFilenamePathMatcher).UsingHead()).AtPriority(WireMockConstants.AdminPriority).RespondWith(new DynamicResponseProvider(FileHead));
Given(Request.Create().WithPath(AdminFilesFilenamePathMatcher).UsingDelete()).AtPriority(WireMockConstants.AdminPriority).RespondWith(new DynamicResponseProvider(FileDelete));
// __admin/openapi
Given(Request.Create().WithPath($"{_adminPaths.OpenApi}/convert").UsingPost()).AtPriority(WireMockConstants.AdminPriority).RespondWith(new DynamicResponseProvider(OpenApiConvertToMappings));
Given(Request.Create().WithPath($"{_adminPaths.OpenApi}/save").UsingPost()).AtPriority(WireMockConstants.AdminPriority).RespondWith(new DynamicResponseProvider(OpenApiSaveToMappings));
Given(Request.Create().WithPath($"{AdminOpenApi}/convert").UsingPost()).AtPriority(WireMockConstants.AdminPriority).RespondWith(new DynamicResponseProvider(OpenApiConvertToMappings));
Given(Request.Create().WithPath($"{AdminOpenApi}/save").UsingPost()).AtPriority(WireMockConstants.AdminPriority).RespondWith(new DynamicResponseProvider(OpenApiSaveToMappings));
}
#endregion
@@ -239,22 +218,6 @@ public partial class WireMockServer
}
#endregion
#region Health
private static IResponseMessage HealthGet(IRequestMessage requestMessage)
{
return new ResponseMessage
{
BodyData = new BodyData
{
DetectedBodyType = BodyType.String,
BodyAsString = "Healthy"
},
StatusCode = (int)HttpStatusCode.OK,
Headers = new Dictionary<string, WireMockList<string>> { { HttpKnownHeaderNames.ContentType, new WireMockList<string>(WireMockConstants.ContentTypeTextPlain) } }
};
}
#endregion
#region Settings
private IResponseMessage SettingsGet(IRequestMessage requestMessage)
{
@@ -381,13 +344,15 @@ public partial class WireMockServer
private static MappingConverterType GetMappingConverterType(IRequestMessage requestMessage)
{
var mappingConverterType = MappingConverterType.Server;
if (requestMessage.QueryIgnoreCase?.TryGetValue(nameof(MappingConverterType), out var values) == true &&
Enum.TryParse(values.FirstOrDefault(), true, out MappingConverterType parsed))
{
return parsed;
mappingConverterType = parsed;
}
return MappingConverterType.Server;
return mappingConverterType;
}
private IMapping? FindMappingByGuid(IRequestMessage requestMessage)
@@ -682,7 +647,7 @@ public partial class WireMockServer
private IResponseMessage ScenarioReset(IRequestMessage requestMessage)
{
var name = string.Equals(HttpRequestMethod.DELETE, requestMessage.Method, StringComparison.OrdinalIgnoreCase) ?
requestMessage.Path.Substring(_adminPaths!.Scenarios.Length + 1) :
requestMessage.Path.Substring(AdminScenarios.Length + 1) :
requestMessage.Path.Split('/').Reverse().Skip(1).First();
return ResetScenario(name) ?
@@ -867,4 +832,4 @@ public partial class WireMockServer
var singleResult = ((JObject)value).ToObject<T>();
return new[] { singleResult! };
}
}
}

View File

@@ -2,6 +2,7 @@ using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using WireMock.Matchers;
using WireMock.Types;
using WireMock.Util;
@@ -9,6 +10,7 @@ namespace WireMock.Server;
public partial class WireMockServer
{
private static readonly RegexMatcher AdminFilesFilenamePathMatcher = new(@"^\/__admin\/files\/.*$");
private static readonly Encoding[] FileBodyIsString = { Encoding.UTF8, Encoding.ASCII };
#region Files/{filename}
@@ -115,9 +117,9 @@ public partial class WireMockServer
return ResponseMessageBuilder.Create(HttpStatusCode.OK, "File deleted.");
}
private string GetFileNameFromRequestMessage(IRequestMessage requestMessage)
private static string GetFileNameFromRequestMessage(IRequestMessage requestMessage)
{
return Path.GetFileName(requestMessage.Path.Substring(_adminPaths!.Files.Length + 1));
return Path.GetFileName(requestMessage.Path.Substring(AdminFiles.Length + 1));
}
#endregion
}

View File

@@ -245,16 +245,16 @@ public class WireMockServerSettings
public bool CustomCertificateDefined => CertificateSettings?.IsDefined == true;
#if USE_ASPNETCORE
/// <summary>
/// Client certificate mode for the server
/// </summary>
[PublicAPI]
public ClientCertificateMode ClientCertificateMode { get; set; }
/// <summary>
/// Client certificate mode for the server
/// </summary>
[PublicAPI]
public ClientCertificateMode ClientCertificateMode { get; set; }
/// <summary>
/// Whether to accept any client certificate
/// </summary>
public bool AcceptAnyClientCertificate { get; set; }
/// <summary>
/// Whether to accept any client certificate
/// </summary>
public bool AcceptAnyClientCertificate { get; set; }
#endif
/// <summary>
@@ -320,11 +320,4 @@ public class WireMockServerSettings
/// </summary>
[PublicAPI]
public Dictionary<string, GraphQLSchemaDetails>? GraphQLSchemas { get; set; }
/// <summary>
/// The admin path to use for accessing the Admin REST interface.
/// If not set <c>__/admin</c> is used.
/// </summary>
[PublicAPI]
public string? AdminPath { get; set; }
}

View File

@@ -45,7 +45,6 @@ public static class WireMockServerSettingsParser
AdminAzureADTenant = parser.GetStringValue(nameof(WireMockServerSettings.AdminAzureADTenant)),
AdminPassword = parser.GetStringValue(nameof(WireMockServerSettings.AdminPassword)),
AdminUsername = parser.GetStringValue(nameof(WireMockServerSettings.AdminUsername)),
AdminPath = parser.GetStringValue(nameof(WireMockServerSettings.AdminPath), "/__admin"),
AllowBodyForAllHttpMethods = parser.GetBoolValue(nameof(WireMockServerSettings.AllowBodyForAllHttpMethods)),
AllowCSharpCodeMatcher = parser.GetBoolValue(nameof(WireMockServerSettings.AllowCSharpCodeMatcher)),
AllowOnlyDefinedHttpStatusCodeInResponse = parser.GetBoolValue(nameof(WireMockServerSettings.AllowOnlyDefinedHttpStatusCodeInResponse)),

View File

@@ -10,8 +10,6 @@ namespace WireMock.Util;
internal static class CSharpFormatter
{
private const string Null = "null";
#region Reserved Keywords
private static readonly HashSet<string> CSharpReservedKeywords = new(new[]
{
@@ -94,15 +92,17 @@ internal static class CSharpFormatter
"while"
});
#endregion
public static object ConvertToAnonymousObjectDefinition(object jsonBody, int ind = 2)
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, ind);
return ConvertJsonToAnonymousObjectDefinition(deserializedBody, 2);
}
public static string ConvertJsonToAnonymousObjectDefinition(JToken token, int ind = 0)

View File

@@ -181,17 +181,13 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Handlebars.Net.Helpers" Version="2.4.4" />
<PackageReference Include="Handlebars.Net.Helpers.DynamicLinq" Version="2.4.4" />
<PackageReference Include="Handlebars.Net.Helpers.Humanizer" Version="2.4.4" />
<PackageReference Include="Handlebars.Net.Helpers.Json" Version="2.4.4" />
<PackageReference Include="Handlebars.Net.Helpers.Random" Version="2.4.4" />
<PackageReference Include="Handlebars.Net.Helpers.Xeger" Version="2.4.4" />
<PackageReference Include="Handlebars.Net.Helpers.XPath" Version="2.4.4" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' != 'netstandard1.3' and '$(TargetFramework)' != 'net451' and '$(TargetFramework)' != 'net452' ">
<PackageReference Include="Handlebars.Net.Helpers.Xslt" Version="2.4.4" />
<PackageReference Include="Handlebars.Net.Helpers" Version="2.4.2.1" />
<PackageReference Include="Handlebars.Net.Helpers.DynamicLinq" Version="2.4.2.1" />
<PackageReference Include="Handlebars.Net.Helpers.Humanizer" Version="2.4.2.1" />
<PackageReference Include="Handlebars.Net.Helpers.Json" Version="2.4.2.1" />
<PackageReference Include="Handlebars.Net.Helpers.Random" Version="2.4.2.1" />
<PackageReference Include="Handlebars.Net.Helpers.XPath" Version="2.4.2.1" />
<PackageReference Include="Handlebars.Net.Helpers.Xeger" Version="2.4.2.1" />
</ItemGroup>
<ItemGroup>

View File

@@ -1,49 +1,11 @@
var server = WireMockServer.Start();
server
.Given(Request.Create()
.UsingMethod("POST")
.WithPath("/users/post1")
.WithBody(new JsonMatcher(
value: new
{
city = "Amsterdam",
country = "The Netherlands"
},
ignoreCase: false,
regex: false
))
)
.WithGuid("90356dba-b36c-469a-a17e-669cd84f1f05")
.RespondWith(Response.Create()
);
server
.Given(Request.Create()
.UsingMethod("POST")
.WithPath("/users/post2")
.WithBody(new JsonPartialMatcher(
value: new
{
city = "City",
country = "Country"
},
ignoreCase: false,
regex: false
))
)
.WithGuid("1b731398-4a5b-457f-a6e3-d65e541c428f")
.RespondWith(Response.Create()
.WithBody(@"Line1
Some ""value"" in Line2")
);
server
.Given(Request.Create()
.UsingMethod("GET")
.WithPath("/foo1")
.WithParam("p1", "xyz")
)
.WithGuid("f74fd144-df53-404f-8e35-da22a640bd5f")
.WithGuid("90356dba-b36c-469a-a17e-669cd84f1f05")
.RespondWith(Response.Create()
.WithStatusCode(200)
.WithBody("1")
@@ -56,7 +18,7 @@ server
.WithParam("p2", "abc")
.WithHeader("h1", "W/\"234f2q3r\"", true)
)
.WithGuid("4126dec8-470b-4eff-93bb-c24f83b8b1fd")
.WithGuid("1b731398-4a5b-457f-a6e3-d65e541c428f")
.RespondWith(Response.Create()
.WithStatusCode("201")
.WithHeader("hk", "hv")
@@ -69,7 +31,7 @@ server
.UsingMethod("DELETE")
.WithUrl("https://localhost/test")
)
.WithGuid("c9929240-7ae8-4a5d-8ed8-0913479f6eeb")
.WithGuid("f74fd144-df53-404f-8e35-da22a640bd5f")
.RespondWith(Response.Create()
.WithStatusCode(208)
.WithBodyAsJson(new
@@ -108,3 +70,20 @@ text
})
);
server
.Given(Request.Create()
.UsingMethod("POST")
.WithPath("/foo3")
.WithBody(new JsonPartialMatcher(
value: "{ a = 1, b = 2 }",
ignoreCase: false,
regex: false
))
)
.WithGuid("4126dec8-470b-4eff-93bb-c24f83b8b1fd")
.RespondWith(Response.Create()
.WithStatusCode(200)
.WithBody(@"Line1
Some ""value"" in Line2")
);

View File

@@ -17,7 +17,6 @@ using VerifyXunit;
using WireMock.Admin.Mappings;
using WireMock.Admin.Settings;
using WireMock.Client;
using WireMock.Client.Extensions;
using WireMock.Handlers;
using WireMock.Logging;
using WireMock.Matchers;
@@ -42,47 +41,6 @@ public partial class WireMockAdminApiTests
VerifyNewtonsoftJson.Enable(VerifySettings);
}
[Fact]
public async Task IWireMockAdminApi_WaitForHealthAsync_AndCall_GetHealthAsync_OK()
{
// Arrange
var adminUsername = $"username_{Guid.NewGuid()}";
var adminPassword = $"password_{Guid.NewGuid()}";
var server = WireMockServer.Start(w =>
{
w.StartAdminInterface = true;
w.AdminUsername = adminUsername;
w.AdminPassword = adminPassword;
});
var api = RestClient.For<IWireMockAdminApi>(server.Urls[0])
.WithAuthorization(adminUsername, adminPassword);
// Act 1
await api.WaitForHealthAsync().ConfigureAwait(false);
// Act 2
var status = await api.GetHealthAsync().ConfigureAwait(false);
status.Should().Be("Healthy");
}
[Fact]
public async Task IWireMockAdminApi_WaitForHealthAsync_AndCall_GetHealthAsync_ThrowsException()
{
// Arrange
var server = WireMockServer.Start(w =>
{
w.StartAdminInterface = true;
w.AdminUsername = $"username_{Guid.NewGuid()}";
w.AdminPassword = $"password_{Guid.NewGuid()}";
});
var api = RestClient.For<IWireMockAdminApi>(server.Urls[0]);
// Act
Func<Task> act = () => api.WaitForHealthAsync(maxRetries: 3);
await act.Should().ThrowAsync<InvalidOperationException>();
}
[Fact]
public async Task IWireMockAdminApi_GetSettingsAsync()
{
@@ -95,28 +53,6 @@ public partial class WireMockAdminApiTests
Check.That(settings).IsNotNull();
}
[Fact]
public async Task IWireMockAdminApi_GetSettingsAsync_ForDifferentAdminPath()
{
// Arrange
var server = WireMockServer.Start(w =>
{
w.StartAdminInterface = true;
w.AdminPath = "/foo/__admin";
});
var api = RestClient.For<IWireMockAdminApi>(server.Urls[0] + "/foo");
// Act
var settings = await api.GetSettingsAsync().ConfigureAwait(false);
// Assert
Check.That(settings).IsNotNull();
// Cleanup
server.Stop();
server.Dispose();
}
[Fact]
public async Task IWireMockAdminApi_PostSettingsAsync()
{
@@ -555,7 +491,7 @@ public partial class WireMockAdminApiTests
server.Stop();
}
[Fact]
public async Task IWireMockAdminApi_GetRequestsAsync_Json()
{
@@ -926,37 +862,8 @@ public partial class WireMockAdminApiTests
var guid2 = Guid.Parse("1b731398-4a5b-457f-a6e3-d65e541c428f");
var guid3 = Guid.Parse("f74fd144-df53-404f-8e35-da22a640bd5f");
var guid4 = Guid.Parse("4126DEC8-470B-4EFF-93BB-C24F83B8B1FD");
var guid5 = Guid.Parse("c9929240-7ae8-4a5d-8ed8-0913479f6eeb");
var server = WireMockServer.StartWithAdminInterface();
server
.Given(
Request.Create()
.WithPath("/users/post1")
.UsingPost()
.WithBody(new JsonMatcher(new
{
city = "Amsterdam",
country = "The Netherlands"
}))
)
.WithGuid(guid1)
.RespondWith(Response.Create());
server
.Given(
Request.Create()
.WithPath("/users/post2")
.UsingPost()
.WithBody(new JsonPartialMatcher(new
{
city = "City",
country = "Country"
}))
)
.WithGuid(guid2)
.RespondWith(Response.Create().WithBody("Line1\r\nSome \"value\" in Line2"));
server
.Given(
Request.Create()
@@ -964,7 +871,7 @@ public partial class WireMockAdminApiTests
.WithParam("p1", "xyz")
.UsingGet()
)
.WithGuid(guid3)
.WithGuid(guid1)
.RespondWith(
Response.Create()
.WithStatusCode(200)
@@ -979,7 +886,7 @@ public partial class WireMockAdminApiTests
.WithHeader("h1", "W/\"234f2q3r\"")
.UsingPost()
)
.WithGuid(guid4)
.WithGuid(guid2)
.RespondWith(
Response.Create()
.WithStatusCode("201")
@@ -994,43 +901,36 @@ public partial class WireMockAdminApiTests
.WithUrl("https://localhost/test")
.UsingDelete()
)
.WithGuid(guid5)
.WithGuid(guid3)
.RespondWith(
Response.Create()
.WithStatusCode(HttpStatusCode.AlreadyReported)
.WithBodyAsJson(new
{
@as = 1,
b = 1.2,
d = true,
e = false,
f = new[] { 1, 2, 3, 4 },
g = new
{
z1 = 1,
z2 = 2,
z3 = new[] { "a", "b", "c" },
z4 = new[]
{
new { a = 1, b = 2 },
new { a = 2, b = 3 }
}
},
date_field = new DateTime(2023, 05, 08, 11, 20, 19),
string_field_with_date = "2021-03-13T21:04:00Z",
multiline_text = @"This
.WithBodyAsJson(new { @as = 1, b = 1.2, d = true, e = false, f = new[] { 1, 2, 3, 4 }, g = new { z1 = 1, z2 = 2, z3 = new[] { "a", "b", "c" }, z4 = new[] { new { a = 1, b = 2 }, new { a = 2, b = 3 } } }, date_field = new DateTime(2023, 05, 08, 11, 20, 19), string_field_with_date = "2021-03-13T21:04:00Z", multiline_text = @"This
is
multiline
text
"
})
" })
);
server
.Given(
Request.Create()
.WithPath("/foo3")
.WithBody(new JsonPartialMatcher(new { a = 1, b = 2 }))
.UsingPost()
)
.WithGuid(guid4)
.RespondWith(
Response.Create()
.WithStatusCode(200)
.WithBody("Line1\r\nSome \"value\" in Line2")
);
// Act
var api = RestClient.For<IWireMockAdminApi>(server.Url);
var mappings = await api.GetMappingsAsync().ConfigureAwait(false);
mappings.Should().HaveCount(5);
mappings.Should().HaveCount(4);
var code = await api.GetMappingsCodeAsync().ConfigureAwait(false);

View File

@@ -1,32 +0,0 @@
{
Guid: 53241df5-582c-458a-a67b-6de3d1d0508e,
UpdatedAt: DateTime_1,
Title: This is my title 1,
Request: {
Path: {
Matchers: [
{
Name: WildcardMatcher,
Pattern: /bla1,
IgnoreCase: false
}
]
},
Methods: [
POST
],
Body: {
Matcher: {
Name: JsonPartialMatcher,
Pattern: {
test: abc
},
IgnoreCase: false,
Regex: false
}
}
},
Response: {
Body: The Response
}
}

View File

@@ -1,67 +0,0 @@
#if !(NET452 || NET461 || NETCOREAPP3_1)
using System;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Threading.Tasks;
using FluentAssertions;
using VerifyTests;
using VerifyXunit;
using WireMock.Client;
using WireMock.Client.Extensions;
using WireMock.Net.Tests.VerifyExtensions;
using WireMock.Server;
using Xunit;
namespace WireMock.Net.Tests.Client.Builders;
[ExcludeFromCodeCoverage]
[UsesVerify]
public class AdminApiMappingBuilderTests
{
private static readonly VerifySettings VerifySettings = new();
static AdminApiMappingBuilderTests()
{
VerifyNewtonsoftJson.Enable(VerifySettings);
}
[Fact]
public async Task GetMappingBuilder_BuildAndPostAsync()
{
using var server = WireMockServer.StartWithAdminInterface();
var api = RestEase.RestClient.For<IWireMockAdminApi>(server.Url!);
var guid = Guid.Parse("53241df5-582c-458a-a67b-6de3d1d0508e");
var mappingBuilder = api.GetMappingBuilder();
mappingBuilder.Given(m => m
.WithTitle("This is my title 1")
.WithGuid(guid)
.WithRequest(req => req
.UsingPost()
.WithPath("/bla1")
.WithBody(body => body
.WithMatcher(matcher => matcher
.WithName("JsonPartialMatcher")
.WithPattern(new { test = "abc" })
)
)
)
.WithResponse(rsp => rsp
.WithBody("The Response")
)
);
// Act
var status = await mappingBuilder.BuildAndPostAsync().ConfigureAwait(false);
// Assert
status.Status.Should().Be("Mapping added");
var getMappingResult = await api.GetMappingAsync(guid).ConfigureAwait(false);
await Verifier.Verify(getMappingResult, VerifySettings).DontScrubGuids();
server.Stop();
}
}
#endif

View File

@@ -1,40 +0,0 @@
using System;
using FluentAssertions;
using WireMock.Extensions;
using Xunit;
namespace WireMock.Net.Tests.Extensions;
public class EnumExtensionsTests
{
private enum TestEnum
{
Value1
}
[Fact]
public void EnumExtensions_GetFullyQualifiedEnumValue_ShouldReturnCorrectValue()
{
// Arrange
var enumValue = TestEnum.Value1;
// Act
var result = enumValue.GetFullyQualifiedEnumValue();
// Assert
result.Should().Be("WireMock.Net.Tests.Extensions.TestEnum.Value1");
}
[Fact]
public void EnumExtensions_GetFullyQualifiedEnumValue_ShouldThrowArgumentException_WhenTypeIsNotEnum()
{
// Arrange
int nonEnumValue = 42;
// Act
Action act = () => nonEnumValue.GetFullyQualifiedEnumValue();
// Assert
act.Should().Throw<ArgumentException>().WithMessage("T must be an enum");
}
}

View File

@@ -1,8 +1,9 @@
using NFluent;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using FluentAssertions;
using NFluent;
using WireMock.Http;
using WireMock.Models;
using WireMock.Types;

View File

@@ -31,35 +31,5 @@
BodyDestination: SameAsSource,
Body: { msg: "Hello world!"}
}
},
{
Guid: Guid_2,
UpdatedAt: 2023-01-14 15:16:17,
Request: {
Path: {
Matchers: [
{
Name: WildcardMatcher,
Pattern: /users/post2,
IgnoreCase: false
}
]
},
Methods: [
POST
],
Body: {
Matcher: {
Name: JsonMatcher,
Pattern: {
city: Amsterdam,
country: The Netherlands
},
IgnoreCase: false,
Regex: false
}
}
},
Response: {}
}
]

View File

@@ -1,30 +0,0 @@
var builder = new MappingBuilder();
builder
.Given(Request.Create()
.UsingMethod("GET")
.WithPath("/foo")
.WithParam("test", "it.Length < 10")
)
.WithGuid("41372914-1838-4c67-916b-b9aacdd096ce")
.RespondWith(Response.Create()
.WithBody("{ msg: \"Hello world!\"}")
);
builder
.Given(Request.Create()
.UsingMethod("POST")
.WithPath("/users/post2")
.WithBody(new JsonMatcher(
value: new
{
city = "Amsterdam",
country = "The Netherlands"
},
ignoreCase: false,
regex: false
))
)
.WithGuid("98fae52e-76df-47d9-876f-2ee32e931d9b")
.RespondWith(Response.Create()
);

View File

@@ -1,30 +0,0 @@
var server = WireMockServer.Start();
server
.Given(Request.Create()
.UsingMethod("GET")
.WithPath("/foo")
.WithParam("test", "it.Length < 10")
)
.WithGuid("41372914-1838-4c67-916b-b9aacdd096ce")
.RespondWith(Response.Create()
.WithBody("{ msg: \"Hello world!\"}")
);
server
.Given(Request.Create()
.UsingMethod("POST")
.WithPath("/users/post2")
.WithBody(new JsonMatcher(
value: new
{
city = "Amsterdam",
country = "The Netherlands"
},
ignoreCase: false,
regex: false
))
)
.WithGuid("98fae52e-76df-47d9-876f-2ee32e931d9b")
.RespondWith(Response.Create()
);

View File

@@ -31,34 +31,5 @@
BodyDestination: SameAsSource,
Body: { msg: "Hello world!"}
}
},
{
Guid: Guid_2,
UpdatedAt: 2023-01-14T15:16:17,
Request: {
Path: {
Matchers: [
{
Name: WildcardMatcher,
Pattern: /users/post2,
IgnoreCase: false
}
]
},
Methods: [
POST
],
Body: {
Matcher: {
Name: JsonMatcher,
Pattern: {
city: Amsterdam,
country: The Netherlands
},
IgnoreCase: false,
Regex: false
}
}
}
}
]

View File

@@ -13,7 +13,6 @@ using WireMock.RequestBuilders;
using WireMock.ResponseBuilders;
using WireMock.Serialization;
using WireMock.Settings;
using WireMock.Types;
using WireMock.Util;
using Xunit;
@@ -74,25 +73,6 @@ public class MappingBuilderTests
.RespondWith(Response.Create()
.WithBody(@"{ msg: ""Hello world!""}")
);
_sut.Given(Request.Create()
.WithPath("/users/post1")
.UsingPost()
.WithBodyAsJson(new
{
Request = "Hello?"
})
).RespondWith(Response.Create());
_sut.Given(Request.Create()
.WithPath("/users/post2")
.UsingPost()
.WithBody(new JsonMatcher(new
{
city = "Amsterdam",
country = "The Netherlands"
}))
).RespondWith(Response.Create());
}
[Fact]
@@ -115,26 +95,6 @@ public class MappingBuilderTests
return Verifier.VerifyJson(json, VerifySettings);
}
[Fact]
public Task ToCSharpCode_Server()
{
// Act
var code = _sut.ToCSharpCode(MappingConverterType.Server);
// Verify
return Verifier.Verify(code, VerifySettings);
}
[Fact]
public Task ToCSharpCode_Builder()
{
// Act
var code = _sut.ToCSharpCode(MappingConverterType.Builder);
// Verify
return Verifier.Verify(code, VerifySettings);
}
[Fact]
public void SaveMappingsToFile_FolderExists_IsFalse()
{
@@ -181,9 +141,9 @@ public class MappingBuilderTests
_sut.SaveMappingsToFolder(null);
// Verify
_fileSystemHandlerMock.Verify(fs => fs.GetMappingFolder(), Times.Exactly(2));
_fileSystemHandlerMock.Verify(fs => fs.FolderExists(mappingFolder), Times.Exactly(2));
_fileSystemHandlerMock.Verify(fs => fs.WriteMappingFile(It.IsAny<string>(), It.IsAny<string>()), Times.Exactly(2));
_fileSystemHandlerMock.Verify(fs => fs.GetMappingFolder(), Times.Once);
_fileSystemHandlerMock.Verify(fs => fs.FolderExists(mappingFolder), Times.Once);
_fileSystemHandlerMock.Verify(fs => fs.WriteMappingFile(It.IsAny<string>(), It.IsAny<string>()), Times.Once);
_fileSystemHandlerMock.VerifyNoOtherCalls();
}
@@ -199,8 +159,8 @@ public class MappingBuilderTests
// Verify
_fileSystemHandlerMock.Verify(fs => fs.GetMappingFolder(), Times.Never);
_fileSystemHandlerMock.Verify(fs => fs.FolderExists(path), Times.Exactly(2));
_fileSystemHandlerMock.Verify(fs => fs.WriteMappingFile(It.IsAny<string>(), It.IsAny<string>()), Times.Exactly(2));
_fileSystemHandlerMock.Verify(fs => fs.FolderExists(path), Times.Once);
_fileSystemHandlerMock.Verify(fs => fs.WriteMappingFile(It.IsAny<string>(), It.IsAny<string>()), Times.Once);
_fileSystemHandlerMock.VerifyNoOtherCalls();
}
}

View File

@@ -385,22 +385,4 @@ public class JsonPartialWildcardMatcherTests
// Assert
Assert.Equal(0.0, match);
}
[Fact]
public void JsonPartialWildcardMatcher_IsMatch_WithIgnoreCaseTrueAndRegexTrue_JObject()
{
// Assign
var matcher = new JsonPartialWildcardMatcher(new { id = 1, Number = "^\\d+$" }, ignoreCase: true, regex: true);
// Act
var jObject = new JObject
{
{ "Id", new JValue(1) },
{ "Number", new JValue(1) }
};
double match = matcher.IsMatch(jObject).Score;
// Assert
Assert.Equal(1.0, match);
}
}

View File

@@ -11,7 +11,7 @@ namespace WireMock.Net.Tests.Owin;
public class HostUrlOptionsTests
{
[Fact]
public void GetDetails_WithHostingSchemeHttpAndPort_ShouldReturnCorrectDetails()
public void GetDetails_WithNoUrlsAndHttpScheme_ShouldReturnCorrectDetails()
{
// Arrange
var options = new HostUrlOptions
@@ -28,14 +28,14 @@ public class HostUrlOptionsTests
var detail = details.Single();
detail.Should().Match<HostUrlDetails>(d =>
d.Scheme == "http" &&
d.Host == "*" &&
d.Host == "localhost" &&
d.Port == 8080 &&
d.IsHttps == false
);
}
[Fact]
public void GetDetails_WithHostingSchemeHttpsAndPort_ShouldReturnCorrectDetails()
public void GetDetails_WithNoUrlsAndHttpsScheme_ShouldReturnCorrectDetails()
{
// Arrange
var options = new HostUrlOptions
@@ -52,7 +52,7 @@ public class HostUrlOptionsTests
var detail = details.Single();
detail.Should().Match<HostUrlDetails>(d =>
d.Scheme == "https" &&
d.Host == "*" &&
d.Host == "localhost" &&
d.Port == 8081 &&
d.IsHttps == true
);

View File

@@ -3,6 +3,8 @@ 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;
@@ -291,7 +293,7 @@ public class RequestBuilderWithBodyTests
}
[Fact]
public void Request_WithBody_Object_JsonPathMatcher_true()
public void Request_WithBodyAsJson_Object_JsonPathMatcher_true()
{
// Arrange
var spec = Request.Create().UsingAnyMethod().WithBody(new JsonPathMatcher("$..things[?(@.name == 'RequiredThing')]"));
@@ -314,7 +316,7 @@ public class RequestBuilderWithBodyTests
}
[Fact]
public void Request_WithBody_Array_JsonPathMatcher_1()
public void Request_WithBodyAsJson_Array_JsonPathMatcher_1()
{
// Arrange
var spec = Request.Create().UsingAnyMethod().WithBody(new JsonPathMatcher("$..books[?(@.price < 10)]"));
@@ -337,7 +339,7 @@ public class RequestBuilderWithBodyTests
}
[Fact]
public void Request_WithBody_Array_JsonPathMatcher_2()
public void Request_WithBodyAsJson_Array_JsonPathMatcher_2()
{
// Arrange
var spec = Request.Create().UsingAnyMethod().WithBody(new JsonPathMatcher("$..[?(@.Id == 1)]"));
@@ -361,7 +363,7 @@ public class RequestBuilderWithBodyTests
}
[Fact]
public void Request_WithBody_ExactObjectMatcher_true()
public void Request_WithBodyAsObject_ExactObjectMatcher_true()
{
// Assign
object body = DateTime.MinValue;
@@ -382,7 +384,7 @@ public class RequestBuilderWithBodyTests
}
[Fact]
public void Request_WithBodyAsJson_UsingObject_UsesJsonMatcher()
public void Request_WithBodyAsJson_UsingObject()
{
// Assign
object body = new
@@ -393,8 +395,34 @@ public class RequestBuilderWithBodyTests
var bodyData = new BodyData
{
BodyAsJson = body,
DetectedBodyType = BodyType.Json
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

View File

@@ -1,7 +1,6 @@
#if MIMEKIT
using System;
using System.Collections.Generic;
using System.Linq;
using FluentAssertions;
using WireMock.Matchers;
using WireMock.Matchers.Request;
@@ -35,123 +34,8 @@ AAAADElEQVR4XmMQYNgAAADkAMHebX3mAAAAAElFTkSuQmCC
--=-5XgmpXt0XOfzdtcgNJc2ZQ==--
";
private static readonly MimePartMatcher PerfectTextPlainMatcher = new(
MatchBehaviour.AcceptOnMatch,
new ContentTypeMatcher("text/plain"),
null,
null,
new ExactMatcher("This is some plain text")
);
private static readonly MimePartMatcher PerfectPartTextMatcher = new(
MatchBehaviour.AcceptOnMatch,
new ContentTypeMatcher("text/json"),
null,
null,
new JsonMatcher(new { Key = "Value" }, true)
);
private static readonly MimePartMatcher PerfectImagePngMatcher = new(
MatchBehaviour.AcceptOnMatch,
new ContentTypeMatcher("image/png"),
new ExactMatcher("attachment; filename=\"image.png\""),
new ExactMatcher("base64"),
new ExactObjectMatcher(Convert.FromBase64String("iVBORw0KGgoAAAANSUhEUgAAAAIAAAACAgMAAAAP2OW3AAAADFBMVEX/tID/vpH/pWX/sHidUyjlAAAADElEQVR4XmMQYNgAAADkAMHebX3mAAAAAElFTkSuQmCC"))
);
private static readonly MimePartMatcher MismatchTextPlainMatcher = new(
MatchBehaviour.AcceptOnMatch,
new ContentTypeMatcher("text/plain"),
null,
null,
new ExactMatcher("--INVALID TEXT--")
);
private static readonly MimePartMatcher MismatchPartTextMatcher = new(
MatchBehaviour.AcceptOnMatch,
new ContentTypeMatcher("text/json"),
null,
null,
new JsonMatcher(new { Key = "InvalidValue" }, true)
);
private static readonly MimePartMatcher MismatchImagePngMatcher = new(
MatchBehaviour.AcceptOnMatch,
new ContentTypeMatcher("image/png"),
new ExactMatcher("attachment; filename=\"invalid.png\""),
new ExactMatcher("base64"),
null
);
public static TheoryData<IMatcher?, IMatcher?, IMatcher?> PerfectMatchersData => new()
{
{ PerfectTextPlainMatcher, null, null },
{ PerfectPartTextMatcher, null, null },
{ PerfectImagePngMatcher, null, null },
{ PerfectPartTextMatcher, PerfectTextPlainMatcher, null },
{ PerfectPartTextMatcher, PerfectImagePngMatcher, PerfectTextPlainMatcher },
};
public static TheoryData<IMatcher?, IMatcher?, IMatcher?> MismatchMatchersData => new()
{
{ MismatchTextPlainMatcher, null, null },
{ MismatchPartTextMatcher, null, null },
{ MismatchImagePngMatcher, null, null },
{ MismatchPartTextMatcher, MismatchTextPlainMatcher, null },
{ MismatchPartTextMatcher, MismatchImagePngMatcher, MismatchTextPlainMatcher },
};
public static TheoryData<IMatcher?, IMatcher?, IMatcher?> MixedMatchersData => new()
{
{ MismatchPartTextMatcher, PerfectTextPlainMatcher, null },
{ PerfectPartTextMatcher, MismatchImagePngMatcher, null },
};
[Theory]
[MemberData(nameof(PerfectMatchersData))]
public void RequestMessageBodyMatcher_GetMatchingScore_BodyAsMultiPart_Perfect(IMatcher? matcher1, IMatcher? matcher2, IMatcher? matcher3)
{
// Assign
var score = GetScore(matcher1, matcher2, matcher3);
// Assert
score.Should().Be(MatchScores.Perfect);
}
[Theory]
[MemberData(nameof(MismatchMatchersData))]
public void RequestMessageBodyMatcher_GetMatchingScore_BodyAsMultiPart_Mismatch(IMatcher? matcher1, IMatcher? matcher2, IMatcher? matcher3)
{
// Assign
var score = GetScore(matcher1, matcher2, matcher3);
// Assert
score.Should().Be(MatchScores.Mismatch);
}
[Theory]
[MemberData(nameof(MixedMatchersData))]
public void RequestMessageBodyMatcher_GetMatchingScore_BodyAsMultiPart_Mixed_With_And(IMatcher? matcher1, IMatcher? matcher2, IMatcher? matcher3)
{
// Assign
var score = GetScore(matcher1, matcher2, matcher3);
// Assert
score.Should().Be(MatchScores.Mismatch);
}
[Theory]
[MemberData(nameof(MixedMatchersData))]
public void RequestMessageBodyMatcher_GetMatchingScore_BodyAsMultiPart_Mixed_With_Or(IMatcher? matcher1, IMatcher? matcher2, IMatcher? matcher3)
{
// Assign
var score = GetScore(matcher1, matcher2, matcher3, MatchOperator.Or);
// Assert
score.Should().Be(MatchScores.Perfect);
}
private static double GetScore(IMatcher? matcher1, IMatcher? matcher2, IMatcher? matcher3, MatchOperator matchOperator = MatchOperator.And)
[Fact]
public void RequestMessageBodyMatcher_GetMatchingScore_BodyAsMultiPart()
{
// Assign
var body = new BodyData
@@ -160,20 +44,41 @@ AAAADElEQVR4XmMQYNgAAADkAMHebX3mAAAAAElFTkSuQmCC
DetectedBodyType = BodyType.MultiPart
};
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 partTextJsonContentTypeMatcher = new ContentTypeMatcher("text/json");
var partTextJsonContentMatcher = new JsonMatcher(new { Key = "Value" }, true);
var partTextMatcher = new MimePartMatcher(MatchBehaviour.AcceptOnMatch, partTextJsonContentTypeMatcher, null, null, partTextJsonContentMatcher);
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,
partTextMatcher,
imagePngMatcher
};
var headers = new Dictionary<string, string[]>
{
{ "Content-Type", new[] { @"multipart/mixed; boundary=""=-5XgmpXt0XOfzdtcgNJc2ZQ==""" } }
};
var requestMessage = new RequestMessage(new UrlDetails("http://localhost"), "GET", "127.0.0.1", body, headers);
var matchers = new IMatcher?[] { matcher1, matcher2, matcher3 }
.Where(m => m is not null)
.ToArray();
var matcher = new RequestMessageMultiPartMatcher(MatchBehaviour.AcceptOnMatch, matchOperator, matchers!);
var matcher = new RequestMessageMultiPartMatcher(matchers);
// Act
var result = new RequestMatchResult();
return matcher.GetMatchingScore(requestMessage, result);
var score = matcher.GetMatchingScore(requestMessage, result);
// Assert
score.Should().Be(MatchScores.Perfect);
}
}
#endif

View File

@@ -1,7 +1,6 @@
using System;
using System.Text;
using System.Threading.Tasks;
using FluentAssertions;
using Moq;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
@@ -355,7 +354,7 @@ public class ResponseWithHandlebarsJsonPathTests
public async Task Response_ProvideResponse_Transformer_WithBodyAsFile_JsonPath()
{
// Assign
const string jsonString = "{ \"MyUniqueNumber\": \"1\" }";
string jsonString = "{ \"MyUniqueNumber\": \"1\" }";
var bodyData = new BodyData
{
BodyAsString = jsonString,
@@ -366,17 +365,15 @@ public class ResponseWithHandlebarsJsonPathTests
};
var request = new RequestMessage(new UrlDetails("http://localhost/foo"), "POST", ClientIp, bodyData);
string jsonPath = "\"$.MyUniqueNumber\"";
var responseBuilder = Response.Create()
.WithTransformer()
// We need to use `c:\\\\` here because when just using `c:\\\`, the `\\` it will be interpreted as an escape character to skip / exclude / escape the whole {{}} expression.
// See https://handlebarsjs.com/guide/expressions.html#escaping-handlebars-expressions
.WithBodyFromFile("c:\\\\{{JsonPath.SelectToken request.body \"$.MyUniqueNumber\" }}\\test.json");
.WithBodyFromFile(@"c:\\{{JsonPath.SelectToken request.body " + jsonPath + "}}\\test.json"); // why use a \\ here ?
// Act
var response = await responseBuilder.ProvideResponseAsync(_mappingMock.Object, request, _settings).ConfigureAwait(false);
// Assert
response.Message.BodyData?.BodyAsFile.Should().Be(@"c:\1\test.json");
Check.That(response.Message.BodyData.BodyAsFile).Equals(@"c:\1\test.json");
}
}

View File

@@ -1,35 +0,0 @@
using FluentAssertions;
using WireMock.Settings;
using Xunit;
namespace WireMock.Net.Tests.Settings;
public class WireMockServerSettingsParserTests
{
[Fact]
public void TryParseArguments_With_Args()
{
// Act
var result = WireMockServerSettingsParser.TryParseArguments(new[]
{
"--adminPath", "ap"
}, null, out var settings);
// Assert
result.Should().BeTrue();
settings.Should().NotBeNull();
settings!.AdminPath.Should().Be("ap");
}
[Fact]
public void TryParseArguments_Without_Args()
{
// Act
var result = WireMockServerSettingsParser.TryParseArguments(new string[] { }, null, out var settings);
// Assert
result.Should().BeTrue();
settings.Should().NotBeNull();
settings!.AdminPath.Should().Be("/__admin");
}
}

View File

@@ -1,5 +1,4 @@
#if NET6_0_OR_GREATER
using System;
using System.Threading.Tasks;
using FluentAssertions;
using FluentAssertions.Execution;
@@ -14,12 +13,9 @@ public class TestcontainersTests
public async Task WireMockContainer_Build_and_StartAsync_and_StopAsync()
{
// Act
var adminUsername = $"username_{Guid.NewGuid()}";
var adminPassword = $"password_{Guid.NewGuid()}";
var wireMockContainer = new WireMockContainerBuilder()
.WithAutoRemove(true)
.WithCleanUp(true)
.WithAdminUserNameAndPassword(adminUsername, adminPassword)
.Build();
try

View File

@@ -9,7 +9,6 @@ using FluentAssertions;
using Moq;
using Newtonsoft.Json;
using NFluent;
using WireMock.Admin.Settings;
using WireMock.Handlers;
using WireMock.Logging;
using WireMock.RequestBuilders;
@@ -23,9 +22,13 @@ namespace WireMock.Net.Tests;
public class WireMockServerAdminTests
{
// For for AppVeyor + OpenCover
private static string GetCurrentFolder()
private string GetCurrentFolder()
{
return Directory.GetCurrentDirectory();
string current = Directory.GetCurrentDirectory();
//if (!current.EndsWith("WireMock.Net.Tests"))
// return Path.Combine(current, "test", "WireMock.Net.Tests");
return current;
}
[Fact]
@@ -465,9 +468,9 @@ public class WireMockServerAdminTests
Check.That(server.MappingModels.Count()).Equals(3);
var guid1 = server.MappingModels.ElementAt(0).Guid;
var guid2 = server.MappingModels.ElementAt(1).Guid;
var guid3 = server.MappingModels.ElementAt(2).Guid;
Guid? guid1 = server.MappingModels.ElementAt(0).Guid;
Guid? guid2 = server.MappingModels.ElementAt(1).Guid;
Guid? guid3 = server.MappingModels.ElementAt(2).Guid;
Check.That(guid1).IsNotNull();
Check.That(guid2).IsNotNull();
@@ -479,7 +482,7 @@ public class WireMockServerAdminTests
$"]";
// Act
var request = new HttpRequestMessage
var request = new HttpRequestMessage()
{
Method = HttpMethod.Delete,
RequestUri = new Uri($"http://localhost:{server.Ports[0]}/__admin/mappings"),
@@ -496,47 +499,4 @@ public class WireMockServerAdminTests
Check.That(response.StatusCode).Equals(HttpStatusCode.OK);
Check.That(await response.Content.ReadAsStringAsync().ConfigureAwait(false)).Equals($"{{\"Status\":\"Mappings deleted. Affected GUIDs: [{guid1}, {guid2}]\"}}");
}
[Fact]
public async Task WireMockServer_CreateClient_And_CallEndpoint()
{
// Arrange
var server = WireMockServer.Start();
var client = server.CreateClient();
// Act
await client.GetAsync($"{server.Url}/foo").ConfigureAwait(false);
// Assert
Check.That(server.LogEntries).HasSize(1);
var requestLogged = server.LogEntries.First();
Check.That(requestLogged.RequestMessage.Method).IsEqualTo("GET");
Check.That(requestLogged.RequestMessage.BodyData).IsNull();
// Cleanup
server.Stop();
server.Dispose();
}
[Fact]
public async Task WireMockServer_CreateClient_And_CallAdminSettingsEndpoint()
{
// Arrange
var server = WireMockServer.Start(w =>
{
w.StartAdminInterface = true;
w.AdminPath = "/adm";
});
var client = server.CreateClient();
// Act
var settings = await client.GetStringAsync($"{server.Url}/adm/settings").ConfigureAwait(false);
// Assert
settings.Should().NotBeNull();
// Cleanup
server.Stop();
server.Dispose();
}
}

View File

@@ -117,7 +117,7 @@ public class WireMockServerProxyTests
}
// Assert
server.Mappings.Should().HaveCount(36);
server.Mappings.Should().HaveCount(35);
}
[Fact]
@@ -967,4 +967,44 @@ public class WireMockServerProxyTests
server.Dispose();
}
// #1097
// https://stackoverflow.com/questions/52106567/how-to-stop-httprequestmessage-from-unencoding-3a-to-a-colon-in-the-request-uri
[Fact]
public async Task WireMockServer_Proxy_Should_Keep_UrlEncoding()
{
// Assign
string path = $"/prx_{Guid.NewGuid()}";
var serverForProxyForwarding = WireMockServer.Start();
serverForProxyForwarding
.Given(Request.Create().WithPath(path))
.RespondWith(Response.Create());
var settings = new WireMockServerSettings
{
ProxyAndRecordSettings = new ProxyAndRecordSettings
{
Url = serverForProxyForwarding.Urls[0],
SaveMapping = true,
SaveMappingToFile = false
}
};
var server = WireMockServer.Start(settings);
// Act
var requestUri = $"{server.Urls[0]}{path}with%20space_and_%3A_colon";
var requestMessage = new HttpRequestMessage
{
Method = HttpMethod.Get,
RequestUri = new Uri(requestUri)
};
await new HttpClient().SendAsync(requestMessage).ConfigureAwait(false);
// Assert
var receivedRequest = serverForProxyForwarding.LogEntries.First().RequestMessage;
receivedRequest.AbsolutePath.Should().EndWith("with space_and_:_colon");
// check that new proxied mapping is added
server.Mappings.Should().HaveCount(2);
}
}

View File

@@ -81,7 +81,7 @@ public class WireMockServerSettingsTests
// Assert
server.Mappings.Should().NotBeNull();
server.Mappings.Should().HaveCount(34);
server.Mappings.Should().HaveCount(33);
server.Mappings.All(m => m.Priority == WireMockConstants.AdminPriority).Should().BeTrue();
}
@@ -100,9 +100,9 @@ public class WireMockServerSettingsTests
// Assert
server.Mappings.Should().NotBeNull();
server.Mappings.Should().HaveCount(35);
server.Mappings.Should().HaveCount(34);
server.Mappings.Count(m => m.Priority == WireMockConstants.AdminPriority).Should().Be(34);
server.Mappings.Count(m => m.Priority == WireMockConstants.AdminPriority).Should().Be(33);
server.Mappings.Count(m => m.Priority == WireMockConstants.ProxyPriority).Should().Be(1);
}