Compare commits

...

30 Commits

Author SHA1 Message Date
Stef Heyenrath
3e6eb256f5 wip 2020-03-02 13:25:53 +00:00
Stef Heyenrath
2851c820e0 1.1.9 2020-02-25 22:22:01 +01:00
Stef Heyenrath
13ab37dd3e LinqMatcher (#431) 2020-02-25 22:17:15 +01:00
Stef Heyenrath
f49046374a 1.1.8.0 2020-02-22 11:14:11 +01:00
Stef Heyenrath
69488ced5f fixes for Cookie and Header Reject on Match (#423) 2020-02-22 11:07:45 +01:00
Stef Heyenrath
e6bcd625f7 Don't return empty dictionary object for response headers in JSON mapping (#424) 2020-02-22 11:07:04 +01:00
Stef Heyenrath
d1b42bf436 wip (#421) 2020-02-15 08:30:08 +01:00
Stef Heyenrath
f4861d9bab /needs-a-key 2020-02-14 16:34:52 +01:00
Noah Lerner
4c01ef4838 Support multi line wild card matching (#419) 2020-02-13 20:05:56 +01:00
Stef Heyenrath
83866f5719 Example: RejectOnMatch 2020-02-11 08:55:06 +01:00
Stef Heyenrath
f72c3c33ef 1.1.7 2020-02-06 18:44:52 +01:00
Noah Lerner
32248b6585 Fix new Delete with body missing from IWireMockAdminApi interface (#413)
* Fix new Delete with body missing from IWireMockAdminApi interface

* Admin Delete with mappings in body (#409)

* Add unit test for delete with body

* change order of checks for readability. looks nicer.

* Allow body in DELETE requests

* Fix unit tests according to DELETE supporting body

* Re-run CI

* Fix DELETE with body unit test

* Fix ElementAt index in mappings list

* Fix DELETE with body unit test

* Fix theory tag must be accompanied by some InlineData or Member

* Fix didn't use correct checking syntax

* Fix wrap entire unit test in if region
2020-02-05 19:11:44 +01:00
Stef Heyenrath
1df4502631 fix (#414) 2020-02-05 19:09:57 +01:00
Noah Lerner
5e76a82a21 Improved relative path checking based on file existence (#411)
* Improved relative path checking based on file existence

If the file exists at the relative path, then use it. If not, then use the path as is.

* Apply File.Exists logic to ReadResponseBodyAsString as well

* Make path handling more robust since path is user defined

* Unit tests for relative path feature

* Replace all back and forward slashes with system dependent DirectorySeparatorChar

* Attempt fix broken directory separator chars for Unix platforms

* Revert wrapping GetMappingFolder with CleanPath

* Move CleanPath logic to its own class

* Remove whitespace

* Remove more whitespace

* Improve CleanPath method

* Move PathUtils tests to separate class

Add another test to ResponseWithBodyFromFileTests

* Fix Response_ProvideResponse_WithBodyFromFile_InAdminMappingFolder

* Debug Linux CI build

* Debug Linux CI

* print all files from admin mappings folder

* Debug CleanPath

* Fix removed leading directory separator char in Linux breaks file path

Remove debugging statements

* Move combine to PathUtils

* PathUtils + PathUtilsTests

* Remove replicated (3x) tests throughout ResponseWithBodyFromFileTests

Co-authored-by: Stef Heyenrath <Stef.Heyenrath@gmail.com>
2020-02-02 13:49:34 +01:00
Stef Heyenrath
06ae9d72c3 1.1.6.0 2020-01-27 18:51:31 +01:00
Stef Heyenrath
307a89d324 AllowAnyHttpStatusCodeInResponse (#407)
* .

* ,

* PUBLISH_TESTRESULTS

* fix logging

* fix compile error

* codefactor fix

* Debug - Sonar + other things in csproj
2020-01-27 18:47:58 +01:00
Stef Heyenrath
6ae7fc1d75 <VersionPrefix>1.1.5</VersionPrefix> 2020-01-25 18:06:51 +01:00
Stef Heyenrath
29e86abe12 1.1.5.0 2020-01-25 17:58:44 +01:00
Stef Heyenrath
710fc8dcf6 Fixed StatusCode = null or < 0 (#406)
* .

* fix tests

* responseModel.StatusCode is int statusCodeAsInt && statusCodeAsInt > 0

* < 0
2020-01-25 17:51:38 +01:00
Stef Heyenrath
dfbfa5fd35 1.1.4.0 2020-01-25 15:28:43 +01:00
Stef Heyenrath
69bbd76ca4 Log Exception (#405) 2020-01-25 15:25:47 +01:00
Stef Heyenrath
bd0c5a83c9 WireMock.Net.Service 2020-01-25 13:54:09 +01:00
Stef Heyenrath
a08efe2f78 steps: 2020-01-25 12:39:36 +01:00
Stef Heyenrath
6e151098e5 azure-pipelines 2020-01-25 12:29:13 +01:00
Stef Heyenrath
43d481435c 1.1.3 2020-01-22 16:40:10 +01:00
Kashif Jamal Soofi
ea1be6641a Fix for invalid cast exception (#403) 2020-01-22 14:27:44 +01:00
Stef Heyenrath
93613885c1 1.1.2.0 2020-01-09 20:18:07 +01:00
Vitaliy Davydiak
caee5895eb ResponseModel.StatusCode is deserialized as either string or long. (#399) 2020-01-09 20:15:15 +01:00
Stef Heyenrath
101d755a00 1.1.1.0 2020-01-09 18:04:41 +01:00
Kashif Jamal Soofi
368fdd4c7d Feature/xpath transformer (#398)
* XPath transformer, added handlerbars helper to select nodes using xpath and setting the outerxml value in response

* Added test to select attribute value and node text

* Removed extra empty lines
2020-01-09 17:51:44 +01:00
71 changed files with 1447 additions and 331 deletions

View File

@@ -1,3 +1,40 @@
# 1.1.9.0 (25 February 2020)
- [#431](https://github.com/WireMock-Net/WireMock.Net/pull/431) - Fix LinqMatcher for JSON int64 [bug] contributed by [StefH](https://github.com/StefH)
- [#425](https://github.com/WireMock-Net/WireMock.Net/issues/425) - Allow 64 bit numbers in JSON [bug]
# 1.1.8.0 (22 February 2020)
- [#419](https://github.com/WireMock-Net/WireMock.Net/pull/419) - Support multi line wild card matching [bug] contributed by [NoahLerner](https://github.com/NoahLerner)
- [#421](https://github.com/WireMock-Net/WireMock.Net/pull/421) - Fix: do not return empty matchers array when Func has been used [bug] contributed by [StefH](https://github.com/StefH)
- [#423](https://github.com/WireMock-Net/WireMock.Net/pull/423) - Fixes for Cookie and Header Reject on Match [bug] contributed by [StefH](https://github.com/StefH)
- [#424](https://github.com/WireMock-Net/WireMock.Net/pull/424) - Don't return empty dictionary object for response headers in JSON mapping [feature] contributed by [StefH](https://github.com/StefH)
- [#418](https://github.com/WireMock-Net/WireMock.Net/issues/418) - Body matching fails if body has newline [bug]
# 1.1.7.0 (06 February 2020)
- [#409](https://github.com/WireMock-Net/WireMock.Net/pull/409) - Admin Delete with mappings in body [feature] contributed by [NoahLerner](https://github.com/NoahLerner)
- [#411](https://github.com/WireMock-Net/WireMock.Net/pull/411) - Improved relative path checking based on file existence [feature] contributed by [NoahLerner](https://github.com/NoahLerner)
- [#413](https://github.com/WireMock-Net/WireMock.Net/pull/413) - Fix new Delete with body missing from IWireMockAdminApi interface contributed by [NoahLerner](https://github.com/NoahLerner)
- [#414](https://github.com/WireMock-Net/WireMock.Net/pull/414) - Fix logger in StandAlone [bug] contributed by [StefH](https://github.com/StefH)
- [#412](https://github.com/WireMock-Net/WireMock.Net/issues/412) - WireMock Standalone - null reference exception since settings.Logger [bug]
# 1.1.6.0 (27 January 2020)
- [#407](https://github.com/WireMock-Net/WireMock.Net/pull/407) - AllowAnyHttpStatusCodeInResponse [feature] contributed by [StefH](https://github.com/StefH)
# 1.1.5.0 (25 January 2020)
- [#405](https://github.com/WireMock-Net/WireMock.Net/pull/405) - Fix logging an Exception Message (linux docker on azure) [bug] contributed by [StefH](https://github.com/StefH)
- [#406](https://github.com/WireMock-Net/WireMock.Net/pull/406) - Fixed StatusCode = null or &lt; 0 [bug] contributed by [StefH](https://github.com/StefH)
# 1.1.3.0 (22 January 2020)
- [#403](https://github.com/WireMock-Net/WireMock.Net/pull/403) - Fix for invalid cast exception contributed by [kashifsoofi](https://github.com/kashifsoofi)
- [#402](https://github.com/WireMock-Net/WireMock.Net/issues/402) - Invalid Cast Exception [bug]
# 1.1.2.0 (09 January 2020)
- [#399](https://github.com/WireMock-Net/WireMock.Net/pull/399) - ResponseModel.StatusCode is deserialized as either string or long. [bug] contributed by [vitaliydavydiak](https://github.com/vitaliydavydiak)
- [#400](https://github.com/WireMock-Net/WireMock.Net/issues/400) - StatusCode not built correctly when loaded from mapping file. [bug]
# 1.1.1.0 (09 January 2020)
- [#398](https://github.com/WireMock-Net/WireMock.Net/pull/398) - Feature/xpath transformer [feature] contributed by [kashifsoofi](https://github.com/kashifsoofi)
- [#397](https://github.com/WireMock-Net/WireMock.Net/issues/397) - Question/Feature: Add support for selecting XPath in response template [feature]
# 1.1.0.0 (27 December 2019) # 1.1.0.0 (27 December 2019)
- [#363](https://github.com/WireMock-Net/WireMock.Net/pull/363) - WireMock.Net version 1.1.x contributed by [StefH](https://github.com/StefH) - [#363](https://github.com/WireMock-Net/WireMock.Net/pull/363) - WireMock.Net version 1.1.x contributed by [StefH](https://github.com/StefH)
@@ -26,7 +63,7 @@
- [#386](https://github.com/WireMock-Net/WireMock.Net/issues/386) - Is transforming contents of XML file supported.? [bug] - [#386](https://github.com/WireMock-Net/WireMock.Net/issues/386) - Is transforming contents of XML file supported.? [bug]
# 1.0.38.0 (30 November 2019) # 1.0.38.0 (30 November 2019)
- [#376](https://github.com/WireMock-Net/WireMock.Net/pull/376) - Support int values for states and scenario naming [feature] contributed by [thewholuver94](https://github.com/thewholuver94) - [#376](https://github.com/WireMock-Net/WireMock.Net/pull/376) - Support int values for states and scenario naming [feature] contributed by [NoahLerner](https://github.com/NoahLerner)
- [#378](https://github.com/WireMock-Net/WireMock.Net/pull/378) - Set handlebars dependency for .net 4.5.1 to fixed value [bug] contributed by [StefH](https://github.com/StefH) - [#378](https://github.com/WireMock-Net/WireMock.Net/pull/378) - Set handlebars dependency for .net 4.5.1 to fixed value [bug] contributed by [StefH](https://github.com/StefH)
- [#381](https://github.com/WireMock-Net/WireMock.Net/pull/381) - Use dotnet default development certificate for .NET Core 2.x [feature] contributed by [StefH](https://github.com/StefH) - [#381](https://github.com/WireMock-Net/WireMock.Net/pull/381) - Use dotnet default development certificate for .NET Core 2.x [feature] contributed by [StefH](https://github.com/StefH)
- [#377](https://github.com/WireMock-Net/WireMock.Net/issues/377) - Unable to build against .NET 4.5.1 because of Handlebars [bug] - [#377](https://github.com/WireMock-Net/WireMock.Net/issues/377) - Unable to build against .NET 4.5.1 because of Handlebars [bug]

View File

@@ -4,7 +4,7 @@
</PropertyGroup> </PropertyGroup>
<PropertyGroup> <PropertyGroup>
<VersionPrefix>1.1.0</VersionPrefix> <VersionPrefix>1.1.9</VersionPrefix>
</PropertyGroup> </PropertyGroup>
<Choose> <Choose>

View File

@@ -1,3 +1,3 @@
https://github.com/StefH/GitHubReleaseNotes https://github.com/StefH/GitHubReleaseNotes
GitHubReleaseNotes.exe --output CHANGELOG.md --skip-empty-releases --exclude-labels question invalid doc --version 1.1.0.0 GitHubReleaseNotes.exe --output CHANGELOG.md --skip-empty-releases --exclude-labels question invalid doc --version 1.1.9.0

View File

@@ -1,16 +1,17 @@
Microsoft Visual Studio Solution File, Format Version 12.00 Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15 # Visual Studio Version 16
VisualStudioVersion = 15.0.28307.902 VisualStudioVersion = 16.0.29709.97
MinimumVisualStudioVersion = 10.0.40219.1 MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{EF242EDF-7133-4277-9A0C-18744DE08707}" Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{EF242EDF-7133-4277-9A0C-18744DE08707}"
EndProject EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{197A0EE3-94E5-4807-BBCF-2F1BCA28A6AE}" Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{197A0EE3-94E5-4807-BBCF-2F1BCA28A6AE}"
ProjectSection(SolutionItems) = preProject ProjectSection(SolutionItems) = preProject
.runsettings = .runsettings .runsettings = .runsettings
azure-pipelines-ci-linux.yml = azure-pipelines-ci-linux.yml
azure-pipelines-ci.yml = azure-pipelines-ci.yml
azure-pipelines-linux.yml = azure-pipelines-linux.yml azure-pipelines-linux.yml = azure-pipelines-linux.yml
azure-pipelines-nuget.yml = azure-pipelines-nuget.yml azure-pipelines-nuget.yml = azure-pipelines-nuget.yml
azure-pipelines.yml = azure-pipelines.yml
build-info.md = build-info.md build-info.md = build-info.md
CHANGELOG.md = CHANGELOG.md CHANGELOG.md = CHANGELOG.md
Directory.Build.props = Directory.Build.props Directory.Build.props = Directory.Build.props
@@ -66,12 +67,18 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WireMock.Net.Console.Reques
EndProject EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug - Sonar|Any CPU = Debug - Sonar|Any CPU
Debug - Sonar|x64 = Debug - Sonar|x64
Debug|Any CPU = Debug|Any CPU Debug|Any CPU = Debug|Any CPU
Debug|x64 = Debug|x64 Debug|x64 = Debug|x64
Release|Any CPU = Release|Any CPU Release|Any CPU = Release|Any CPU
Release|x64 = Release|x64 Release|x64 = Release|x64
EndGlobalSection EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution GlobalSection(ProjectConfigurationPlatforms) = postSolution
{D3804228-91F4-4502-9595-39584E5A01AD}.Debug - Sonar|Any CPU.ActiveCfg = Debug|Any CPU
{D3804228-91F4-4502-9595-39584E5A01AD}.Debug - Sonar|Any CPU.Build.0 = Debug|Any CPU
{D3804228-91F4-4502-9595-39584E5A01AD}.Debug - Sonar|x64.ActiveCfg = Debug|Any CPU
{D3804228-91F4-4502-9595-39584E5A01AD}.Debug - Sonar|x64.Build.0 = Debug|Any CPU
{D3804228-91F4-4502-9595-39584E5A01AD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {D3804228-91F4-4502-9595-39584E5A01AD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D3804228-91F4-4502-9595-39584E5A01AD}.Debug|Any CPU.Build.0 = Debug|Any CPU {D3804228-91F4-4502-9595-39584E5A01AD}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D3804228-91F4-4502-9595-39584E5A01AD}.Debug|x64.ActiveCfg = Debug|Any CPU {D3804228-91F4-4502-9595-39584E5A01AD}.Debug|x64.ActiveCfg = Debug|Any CPU
@@ -80,6 +87,10 @@ Global
{D3804228-91F4-4502-9595-39584E5A01AD}.Release|Any CPU.Build.0 = Release|Any CPU {D3804228-91F4-4502-9595-39584E5A01AD}.Release|Any CPU.Build.0 = Release|Any CPU
{D3804228-91F4-4502-9595-39584E5A01AD}.Release|x64.ActiveCfg = Release|Any CPU {D3804228-91F4-4502-9595-39584E5A01AD}.Release|x64.ActiveCfg = Release|Any CPU
{D3804228-91F4-4502-9595-39584E5A01AD}.Release|x64.Build.0 = Release|Any CPU {D3804228-91F4-4502-9595-39584E5A01AD}.Release|x64.Build.0 = Release|Any CPU
{31DC2EF8-C3FE-467D-84BE-FB5D956E612E}.Debug - Sonar|Any CPU.ActiveCfg = Debug|Any CPU
{31DC2EF8-C3FE-467D-84BE-FB5D956E612E}.Debug - Sonar|Any CPU.Build.0 = Debug|Any CPU
{31DC2EF8-C3FE-467D-84BE-FB5D956E612E}.Debug - Sonar|x64.ActiveCfg = Debug|Any CPU
{31DC2EF8-C3FE-467D-84BE-FB5D956E612E}.Debug - Sonar|x64.Build.0 = Debug|Any CPU
{31DC2EF8-C3FE-467D-84BE-FB5D956E612E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {31DC2EF8-C3FE-467D-84BE-FB5D956E612E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{31DC2EF8-C3FE-467D-84BE-FB5D956E612E}.Debug|Any CPU.Build.0 = Debug|Any CPU {31DC2EF8-C3FE-467D-84BE-FB5D956E612E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{31DC2EF8-C3FE-467D-84BE-FB5D956E612E}.Debug|x64.ActiveCfg = Debug|Any CPU {31DC2EF8-C3FE-467D-84BE-FB5D956E612E}.Debug|x64.ActiveCfg = Debug|Any CPU
@@ -88,6 +99,10 @@ Global
{31DC2EF8-C3FE-467D-84BE-FB5D956E612E}.Release|Any CPU.Build.0 = Release|Any CPU {31DC2EF8-C3FE-467D-84BE-FB5D956E612E}.Release|Any CPU.Build.0 = Release|Any CPU
{31DC2EF8-C3FE-467D-84BE-FB5D956E612E}.Release|x64.ActiveCfg = Release|Any CPU {31DC2EF8-C3FE-467D-84BE-FB5D956E612E}.Release|x64.ActiveCfg = Release|Any CPU
{31DC2EF8-C3FE-467D-84BE-FB5D956E612E}.Release|x64.Build.0 = Release|Any CPU {31DC2EF8-C3FE-467D-84BE-FB5D956E612E}.Release|x64.Build.0 = Release|Any CPU
{FE281639-B014-4C8A-96FA-141164A74713}.Debug - Sonar|Any CPU.ActiveCfg = Debug|Any CPU
{FE281639-B014-4C8A-96FA-141164A74713}.Debug - Sonar|Any CPU.Build.0 = Debug|Any CPU
{FE281639-B014-4C8A-96FA-141164A74713}.Debug - Sonar|x64.ActiveCfg = Debug|Any CPU
{FE281639-B014-4C8A-96FA-141164A74713}.Debug - Sonar|x64.Build.0 = Debug|Any CPU
{FE281639-B014-4C8A-96FA-141164A74713}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {FE281639-B014-4C8A-96FA-141164A74713}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{FE281639-B014-4C8A-96FA-141164A74713}.Debug|Any CPU.Build.0 = Debug|Any CPU {FE281639-B014-4C8A-96FA-141164A74713}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FE281639-B014-4C8A-96FA-141164A74713}.Debug|x64.ActiveCfg = Debug|Any CPU {FE281639-B014-4C8A-96FA-141164A74713}.Debug|x64.ActiveCfg = Debug|Any CPU
@@ -96,6 +111,10 @@ Global
{FE281639-B014-4C8A-96FA-141164A74713}.Release|Any CPU.Build.0 = Release|Any CPU {FE281639-B014-4C8A-96FA-141164A74713}.Release|Any CPU.Build.0 = Release|Any CPU
{FE281639-B014-4C8A-96FA-141164A74713}.Release|x64.ActiveCfg = Release|Any CPU {FE281639-B014-4C8A-96FA-141164A74713}.Release|x64.ActiveCfg = Release|Any CPU
{FE281639-B014-4C8A-96FA-141164A74713}.Release|x64.Build.0 = Release|Any CPU {FE281639-B014-4C8A-96FA-141164A74713}.Release|x64.Build.0 = Release|Any CPU
{1995E414-F197-4AB4-90C2-68D806B5AF59}.Debug - Sonar|Any CPU.ActiveCfg = Debug|Any CPU
{1995E414-F197-4AB4-90C2-68D806B5AF59}.Debug - Sonar|Any CPU.Build.0 = Debug|Any CPU
{1995E414-F197-4AB4-90C2-68D806B5AF59}.Debug - Sonar|x64.ActiveCfg = Debug|Any CPU
{1995E414-F197-4AB4-90C2-68D806B5AF59}.Debug - Sonar|x64.Build.0 = Debug|Any CPU
{1995E414-F197-4AB4-90C2-68D806B5AF59}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {1995E414-F197-4AB4-90C2-68D806B5AF59}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1995E414-F197-4AB4-90C2-68D806B5AF59}.Debug|Any CPU.Build.0 = Debug|Any CPU {1995E414-F197-4AB4-90C2-68D806B5AF59}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1995E414-F197-4AB4-90C2-68D806B5AF59}.Debug|x64.ActiveCfg = Debug|Any CPU {1995E414-F197-4AB4-90C2-68D806B5AF59}.Debug|x64.ActiveCfg = Debug|Any CPU
@@ -104,6 +123,10 @@ Global
{1995E414-F197-4AB4-90C2-68D806B5AF59}.Release|Any CPU.Build.0 = Release|Any CPU {1995E414-F197-4AB4-90C2-68D806B5AF59}.Release|Any CPU.Build.0 = Release|Any CPU
{1995E414-F197-4AB4-90C2-68D806B5AF59}.Release|x64.ActiveCfg = Release|Any CPU {1995E414-F197-4AB4-90C2-68D806B5AF59}.Release|x64.ActiveCfg = Release|Any CPU
{1995E414-F197-4AB4-90C2-68D806B5AF59}.Release|x64.Build.0 = Release|Any CPU {1995E414-F197-4AB4-90C2-68D806B5AF59}.Release|x64.Build.0 = Release|Any CPU
{058D4B6C-C03E-49D0-91DB-A535B058FA0D}.Debug - Sonar|Any CPU.ActiveCfg = Debug|Any CPU
{058D4B6C-C03E-49D0-91DB-A535B058FA0D}.Debug - Sonar|Any CPU.Build.0 = Debug|Any CPU
{058D4B6C-C03E-49D0-91DB-A535B058FA0D}.Debug - Sonar|x64.ActiveCfg = Debug|Any CPU
{058D4B6C-C03E-49D0-91DB-A535B058FA0D}.Debug - Sonar|x64.Build.0 = Debug|Any CPU
{058D4B6C-C03E-49D0-91DB-A535B058FA0D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {058D4B6C-C03E-49D0-91DB-A535B058FA0D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{058D4B6C-C03E-49D0-91DB-A535B058FA0D}.Debug|Any CPU.Build.0 = Debug|Any CPU {058D4B6C-C03E-49D0-91DB-A535B058FA0D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{058D4B6C-C03E-49D0-91DB-A535B058FA0D}.Debug|x64.ActiveCfg = Debug|Any CPU {058D4B6C-C03E-49D0-91DB-A535B058FA0D}.Debug|x64.ActiveCfg = Debug|Any CPU
@@ -112,6 +135,10 @@ Global
{058D4B6C-C03E-49D0-91DB-A535B058FA0D}.Release|Any CPU.Build.0 = Release|Any CPU {058D4B6C-C03E-49D0-91DB-A535B058FA0D}.Release|Any CPU.Build.0 = Release|Any CPU
{058D4B6C-C03E-49D0-91DB-A535B058FA0D}.Release|x64.ActiveCfg = Release|Any CPU {058D4B6C-C03E-49D0-91DB-A535B058FA0D}.Release|x64.ActiveCfg = Release|Any CPU
{058D4B6C-C03E-49D0-91DB-A535B058FA0D}.Release|x64.Build.0 = Release|Any CPU {058D4B6C-C03E-49D0-91DB-A535B058FA0D}.Release|x64.Build.0 = Release|Any CPU
{10E16614-61CA-48D8-8BDD-664C13913DED}.Debug - Sonar|Any CPU.ActiveCfg = Debug|Any CPU
{10E16614-61CA-48D8-8BDD-664C13913DED}.Debug - Sonar|Any CPU.Build.0 = Debug|Any CPU
{10E16614-61CA-48D8-8BDD-664C13913DED}.Debug - Sonar|x64.ActiveCfg = Debug|Any CPU
{10E16614-61CA-48D8-8BDD-664C13913DED}.Debug - Sonar|x64.Build.0 = Debug|Any CPU
{10E16614-61CA-48D8-8BDD-664C13913DED}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {10E16614-61CA-48D8-8BDD-664C13913DED}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{10E16614-61CA-48D8-8BDD-664C13913DED}.Debug|Any CPU.Build.0 = Debug|Any CPU {10E16614-61CA-48D8-8BDD-664C13913DED}.Debug|Any CPU.Build.0 = Debug|Any CPU
{10E16614-61CA-48D8-8BDD-664C13913DED}.Debug|x64.ActiveCfg = Debug|Any CPU {10E16614-61CA-48D8-8BDD-664C13913DED}.Debug|x64.ActiveCfg = Debug|Any CPU
@@ -120,6 +147,10 @@ Global
{10E16614-61CA-48D8-8BDD-664C13913DED}.Release|Any CPU.Build.0 = Release|Any CPU {10E16614-61CA-48D8-8BDD-664C13913DED}.Release|Any CPU.Build.0 = Release|Any CPU
{10E16614-61CA-48D8-8BDD-664C13913DED}.Release|x64.ActiveCfg = Release|Any CPU {10E16614-61CA-48D8-8BDD-664C13913DED}.Release|x64.ActiveCfg = Release|Any CPU
{10E16614-61CA-48D8-8BDD-664C13913DED}.Release|x64.Build.0 = Release|Any CPU {10E16614-61CA-48D8-8BDD-664C13913DED}.Release|x64.Build.0 = Release|Any CPU
{668F689E-57B4-422E-8846-C0FF643CA999}.Debug - Sonar|Any CPU.ActiveCfg = Debug|Any CPU
{668F689E-57B4-422E-8846-C0FF643CA999}.Debug - Sonar|Any CPU.Build.0 = Debug|Any CPU
{668F689E-57B4-422E-8846-C0FF643CA999}.Debug - Sonar|x64.ActiveCfg = Debug|Any CPU
{668F689E-57B4-422E-8846-C0FF643CA999}.Debug - Sonar|x64.Build.0 = Debug|Any CPU
{668F689E-57B4-422E-8846-C0FF643CA999}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {668F689E-57B4-422E-8846-C0FF643CA999}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{668F689E-57B4-422E-8846-C0FF643CA999}.Debug|Any CPU.Build.0 = Debug|Any CPU {668F689E-57B4-422E-8846-C0FF643CA999}.Debug|Any CPU.Build.0 = Debug|Any CPU
{668F689E-57B4-422E-8846-C0FF643CA999}.Debug|x64.ActiveCfg = Debug|Any CPU {668F689E-57B4-422E-8846-C0FF643CA999}.Debug|x64.ActiveCfg = Debug|Any CPU
@@ -128,6 +159,10 @@ Global
{668F689E-57B4-422E-8846-C0FF643CA999}.Release|Any CPU.Build.0 = Release|Any CPU {668F689E-57B4-422E-8846-C0FF643CA999}.Release|Any CPU.Build.0 = Release|Any CPU
{668F689E-57B4-422E-8846-C0FF643CA999}.Release|x64.ActiveCfg = Release|Any CPU {668F689E-57B4-422E-8846-C0FF643CA999}.Release|x64.ActiveCfg = Release|Any CPU
{668F689E-57B4-422E-8846-C0FF643CA999}.Release|x64.Build.0 = Release|Any CPU {668F689E-57B4-422E-8846-C0FF643CA999}.Release|x64.Build.0 = Release|Any CPU
{049539C1-7A66-4559-AD7A-B1C73B97CBB0}.Debug - Sonar|Any CPU.ActiveCfg = Debug|Any CPU
{049539C1-7A66-4559-AD7A-B1C73B97CBB0}.Debug - Sonar|Any CPU.Build.0 = Debug|Any CPU
{049539C1-7A66-4559-AD7A-B1C73B97CBB0}.Debug - Sonar|x64.ActiveCfg = Debug|Any CPU
{049539C1-7A66-4559-AD7A-B1C73B97CBB0}.Debug - Sonar|x64.Build.0 = Debug|Any CPU
{049539C1-7A66-4559-AD7A-B1C73B97CBB0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {049539C1-7A66-4559-AD7A-B1C73B97CBB0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{049539C1-7A66-4559-AD7A-B1C73B97CBB0}.Debug|Any CPU.Build.0 = Debug|Any CPU {049539C1-7A66-4559-AD7A-B1C73B97CBB0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{049539C1-7A66-4559-AD7A-B1C73B97CBB0}.Debug|x64.ActiveCfg = Debug|Any CPU {049539C1-7A66-4559-AD7A-B1C73B97CBB0}.Debug|x64.ActiveCfg = Debug|Any CPU
@@ -136,6 +171,10 @@ Global
{049539C1-7A66-4559-AD7A-B1C73B97CBB0}.Release|Any CPU.Build.0 = Release|Any CPU {049539C1-7A66-4559-AD7A-B1C73B97CBB0}.Release|Any CPU.Build.0 = Release|Any CPU
{049539C1-7A66-4559-AD7A-B1C73B97CBB0}.Release|x64.ActiveCfg = Release|Any CPU {049539C1-7A66-4559-AD7A-B1C73B97CBB0}.Release|x64.ActiveCfg = Release|Any CPU
{049539C1-7A66-4559-AD7A-B1C73B97CBB0}.Release|x64.Build.0 = Release|Any CPU {049539C1-7A66-4559-AD7A-B1C73B97CBB0}.Release|x64.Build.0 = Release|Any CPU
{26433A8F-BF01-4962-97EB-81BFFBB61096}.Debug - Sonar|Any CPU.ActiveCfg = Debug|Any CPU
{26433A8F-BF01-4962-97EB-81BFFBB61096}.Debug - Sonar|Any CPU.Build.0 = Debug|Any CPU
{26433A8F-BF01-4962-97EB-81BFFBB61096}.Debug - Sonar|x64.ActiveCfg = Debug|x64
{26433A8F-BF01-4962-97EB-81BFFBB61096}.Debug - Sonar|x64.Build.0 = Debug|x64
{26433A8F-BF01-4962-97EB-81BFFBB61096}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {26433A8F-BF01-4962-97EB-81BFFBB61096}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{26433A8F-BF01-4962-97EB-81BFFBB61096}.Debug|Any CPU.Build.0 = Debug|Any CPU {26433A8F-BF01-4962-97EB-81BFFBB61096}.Debug|Any CPU.Build.0 = Debug|Any CPU
{26433A8F-BF01-4962-97EB-81BFFBB61096}.Debug|x64.ActiveCfg = Debug|x64 {26433A8F-BF01-4962-97EB-81BFFBB61096}.Debug|x64.ActiveCfg = Debug|x64
@@ -144,6 +183,10 @@ Global
{26433A8F-BF01-4962-97EB-81BFFBB61096}.Release|Any CPU.Build.0 = Release|Any CPU {26433A8F-BF01-4962-97EB-81BFFBB61096}.Release|Any CPU.Build.0 = Release|Any CPU
{26433A8F-BF01-4962-97EB-81BFFBB61096}.Release|x64.ActiveCfg = Release|x64 {26433A8F-BF01-4962-97EB-81BFFBB61096}.Release|x64.ActiveCfg = Release|x64
{26433A8F-BF01-4962-97EB-81BFFBB61096}.Release|x64.Build.0 = Release|x64 {26433A8F-BF01-4962-97EB-81BFFBB61096}.Release|x64.Build.0 = Release|x64
{23A9AA3C-40FC-42AA-8A5E-05899795A1C6}.Debug - Sonar|Any CPU.ActiveCfg = Debug|Any CPU
{23A9AA3C-40FC-42AA-8A5E-05899795A1C6}.Debug - Sonar|Any CPU.Build.0 = Debug|Any CPU
{23A9AA3C-40FC-42AA-8A5E-05899795A1C6}.Debug - Sonar|x64.ActiveCfg = Debug|Any CPU
{23A9AA3C-40FC-42AA-8A5E-05899795A1C6}.Debug - Sonar|x64.Build.0 = Debug|Any CPU
{23A9AA3C-40FC-42AA-8A5E-05899795A1C6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {23A9AA3C-40FC-42AA-8A5E-05899795A1C6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{23A9AA3C-40FC-42AA-8A5E-05899795A1C6}.Debug|Any CPU.Build.0 = Debug|Any CPU {23A9AA3C-40FC-42AA-8A5E-05899795A1C6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{23A9AA3C-40FC-42AA-8A5E-05899795A1C6}.Debug|x64.ActiveCfg = Debug|Any CPU {23A9AA3C-40FC-42AA-8A5E-05899795A1C6}.Debug|x64.ActiveCfg = Debug|Any CPU
@@ -152,6 +195,10 @@ Global
{23A9AA3C-40FC-42AA-8A5E-05899795A1C6}.Release|Any CPU.Build.0 = Release|Any CPU {23A9AA3C-40FC-42AA-8A5E-05899795A1C6}.Release|Any CPU.Build.0 = Release|Any CPU
{23A9AA3C-40FC-42AA-8A5E-05899795A1C6}.Release|x64.ActiveCfg = Release|Any CPU {23A9AA3C-40FC-42AA-8A5E-05899795A1C6}.Release|x64.ActiveCfg = Release|Any CPU
{23A9AA3C-40FC-42AA-8A5E-05899795A1C6}.Release|x64.Build.0 = Release|Any CPU {23A9AA3C-40FC-42AA-8A5E-05899795A1C6}.Release|x64.Build.0 = Release|Any CPU
{3C279524-DB73-4DE3-BEF1-F2B2958C9F65}.Debug - Sonar|Any CPU.ActiveCfg = Debug|Any CPU
{3C279524-DB73-4DE3-BEF1-F2B2958C9F65}.Debug - Sonar|Any CPU.Build.0 = Debug|Any CPU
{3C279524-DB73-4DE3-BEF1-F2B2958C9F65}.Debug - Sonar|x64.ActiveCfg = Debug|Any CPU
{3C279524-DB73-4DE3-BEF1-F2B2958C9F65}.Debug - Sonar|x64.Build.0 = Debug|Any CPU
{3C279524-DB73-4DE3-BEF1-F2B2958C9F65}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {3C279524-DB73-4DE3-BEF1-F2B2958C9F65}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3C279524-DB73-4DE3-BEF1-F2B2958C9F65}.Debug|Any CPU.Build.0 = Debug|Any CPU {3C279524-DB73-4DE3-BEF1-F2B2958C9F65}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3C279524-DB73-4DE3-BEF1-F2B2958C9F65}.Debug|x64.ActiveCfg = Debug|Any CPU {3C279524-DB73-4DE3-BEF1-F2B2958C9F65}.Debug|x64.ActiveCfg = Debug|Any CPU
@@ -160,6 +207,10 @@ Global
{3C279524-DB73-4DE3-BEF1-F2B2958C9F65}.Release|Any CPU.Build.0 = Release|Any CPU {3C279524-DB73-4DE3-BEF1-F2B2958C9F65}.Release|Any CPU.Build.0 = Release|Any CPU
{3C279524-DB73-4DE3-BEF1-F2B2958C9F65}.Release|x64.ActiveCfg = Release|Any CPU {3C279524-DB73-4DE3-BEF1-F2B2958C9F65}.Release|x64.ActiveCfg = Release|Any CPU
{3C279524-DB73-4DE3-BEF1-F2B2958C9F65}.Release|x64.Build.0 = Release|Any CPU {3C279524-DB73-4DE3-BEF1-F2B2958C9F65}.Release|x64.Build.0 = Release|Any CPU
{7F0B2446-0363-4720-AF46-F47F83B557DC}.Debug - Sonar|Any CPU.ActiveCfg = Debug|Any CPU
{7F0B2446-0363-4720-AF46-F47F83B557DC}.Debug - Sonar|Any CPU.Build.0 = Debug|Any CPU
{7F0B2446-0363-4720-AF46-F47F83B557DC}.Debug - Sonar|x64.ActiveCfg = Debug|Any CPU
{7F0B2446-0363-4720-AF46-F47F83B557DC}.Debug - Sonar|x64.Build.0 = Debug|Any CPU
{7F0B2446-0363-4720-AF46-F47F83B557DC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {7F0B2446-0363-4720-AF46-F47F83B557DC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7F0B2446-0363-4720-AF46-F47F83B557DC}.Debug|Any CPU.Build.0 = Debug|Any CPU {7F0B2446-0363-4720-AF46-F47F83B557DC}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7F0B2446-0363-4720-AF46-F47F83B557DC}.Debug|x64.ActiveCfg = Debug|Any CPU {7F0B2446-0363-4720-AF46-F47F83B557DC}.Debug|x64.ActiveCfg = Debug|Any CPU
@@ -168,6 +219,10 @@ Global
{7F0B2446-0363-4720-AF46-F47F83B557DC}.Release|Any CPU.Build.0 = Release|Any CPU {7F0B2446-0363-4720-AF46-F47F83B557DC}.Release|Any CPU.Build.0 = Release|Any CPU
{7F0B2446-0363-4720-AF46-F47F83B557DC}.Release|x64.ActiveCfg = Release|Any CPU {7F0B2446-0363-4720-AF46-F47F83B557DC}.Release|x64.ActiveCfg = Release|Any CPU
{7F0B2446-0363-4720-AF46-F47F83B557DC}.Release|x64.Build.0 = Release|Any CPU {7F0B2446-0363-4720-AF46-F47F83B557DC}.Release|x64.Build.0 = Release|Any CPU
{1261BB9B-A7D4-456C-8985-3CE560361B8E}.Debug - Sonar|Any CPU.ActiveCfg = Debug|Any CPU
{1261BB9B-A7D4-456C-8985-3CE560361B8E}.Debug - Sonar|Any CPU.Build.0 = Debug|Any CPU
{1261BB9B-A7D4-456C-8985-3CE560361B8E}.Debug - Sonar|x64.ActiveCfg = Debug|Any CPU
{1261BB9B-A7D4-456C-8985-3CE560361B8E}.Debug - Sonar|x64.Build.0 = Debug|Any CPU
{1261BB9B-A7D4-456C-8985-3CE560361B8E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {1261BB9B-A7D4-456C-8985-3CE560361B8E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1261BB9B-A7D4-456C-8985-3CE560361B8E}.Debug|Any CPU.Build.0 = Debug|Any CPU {1261BB9B-A7D4-456C-8985-3CE560361B8E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1261BB9B-A7D4-456C-8985-3CE560361B8E}.Debug|x64.ActiveCfg = Debug|Any CPU {1261BB9B-A7D4-456C-8985-3CE560361B8E}.Debug|x64.ActiveCfg = Debug|Any CPU
@@ -176,6 +231,10 @@ Global
{1261BB9B-A7D4-456C-8985-3CE560361B8E}.Release|Any CPU.Build.0 = Release|Any CPU {1261BB9B-A7D4-456C-8985-3CE560361B8E}.Release|Any CPU.Build.0 = Release|Any CPU
{1261BB9B-A7D4-456C-8985-3CE560361B8E}.Release|x64.ActiveCfg = Release|Any CPU {1261BB9B-A7D4-456C-8985-3CE560361B8E}.Release|x64.ActiveCfg = Release|Any CPU
{1261BB9B-A7D4-456C-8985-3CE560361B8E}.Release|x64.Build.0 = Release|Any CPU {1261BB9B-A7D4-456C-8985-3CE560361B8E}.Release|x64.Build.0 = Release|Any CPU
{668F689E-57B4-422E-8846-C0FF643CA268}.Debug - Sonar|Any CPU.ActiveCfg = Debug|Any CPU
{668F689E-57B4-422E-8846-C0FF643CA268}.Debug - Sonar|Any CPU.Build.0 = Debug|Any CPU
{668F689E-57B4-422E-8846-C0FF643CA268}.Debug - Sonar|x64.ActiveCfg = Debug|Any CPU
{668F689E-57B4-422E-8846-C0FF643CA268}.Debug - Sonar|x64.Build.0 = Debug|Any CPU
{668F689E-57B4-422E-8846-C0FF643CA268}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {668F689E-57B4-422E-8846-C0FF643CA268}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{668F689E-57B4-422E-8846-C0FF643CA268}.Debug|Any CPU.Build.0 = Debug|Any CPU {668F689E-57B4-422E-8846-C0FF643CA268}.Debug|Any CPU.Build.0 = Debug|Any CPU
{668F689E-57B4-422E-8846-C0FF643CA268}.Debug|x64.ActiveCfg = Debug|Any CPU {668F689E-57B4-422E-8846-C0FF643CA268}.Debug|x64.ActiveCfg = Debug|Any CPU
@@ -184,6 +243,10 @@ Global
{668F689E-57B4-422E-8846-C0FF643CA268}.Release|Any CPU.Build.0 = Release|Any CPU {668F689E-57B4-422E-8846-C0FF643CA268}.Release|Any CPU.Build.0 = Release|Any CPU
{668F689E-57B4-422E-8846-C0FF643CA268}.Release|x64.ActiveCfg = Release|Any CPU {668F689E-57B4-422E-8846-C0FF643CA268}.Release|x64.ActiveCfg = Release|Any CPU
{668F689E-57B4-422E-8846-C0FF643CA268}.Release|x64.Build.0 = Release|Any CPU {668F689E-57B4-422E-8846-C0FF643CA268}.Release|x64.Build.0 = Release|Any CPU
{83645809-9E01-4E81-8733-BA9497554ABF}.Debug - Sonar|Any CPU.ActiveCfg = Debug|Any CPU
{83645809-9E01-4E81-8733-BA9497554ABF}.Debug - Sonar|Any CPU.Build.0 = Debug|Any CPU
{83645809-9E01-4E81-8733-BA9497554ABF}.Debug - Sonar|x64.ActiveCfg = Debug|Any CPU
{83645809-9E01-4E81-8733-BA9497554ABF}.Debug - Sonar|x64.Build.0 = Debug|Any CPU
{83645809-9E01-4E81-8733-BA9497554ABF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {83645809-9E01-4E81-8733-BA9497554ABF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{83645809-9E01-4E81-8733-BA9497554ABF}.Debug|Any CPU.Build.0 = Debug|Any CPU {83645809-9E01-4E81-8733-BA9497554ABF}.Debug|Any CPU.Build.0 = Debug|Any CPU
{83645809-9E01-4E81-8733-BA9497554ABF}.Debug|x64.ActiveCfg = Debug|Any CPU {83645809-9E01-4E81-8733-BA9497554ABF}.Debug|x64.ActiveCfg = Debug|Any CPU
@@ -192,6 +255,10 @@ Global
{83645809-9E01-4E81-8733-BA9497554ABF}.Release|Any CPU.Build.0 = Release|Any CPU {83645809-9E01-4E81-8733-BA9497554ABF}.Release|Any CPU.Build.0 = Release|Any CPU
{83645809-9E01-4E81-8733-BA9497554ABF}.Release|x64.ActiveCfg = Release|Any CPU {83645809-9E01-4E81-8733-BA9497554ABF}.Release|x64.ActiveCfg = Release|Any CPU
{83645809-9E01-4E81-8733-BA9497554ABF}.Release|x64.Build.0 = Release|Any CPU {83645809-9E01-4E81-8733-BA9497554ABF}.Release|x64.Build.0 = Release|Any CPU
{B6269AAC-170A-43D6-8B9A-579DED3D9A96}.Debug - Sonar|Any CPU.ActiveCfg = Debug|Any CPU
{B6269AAC-170A-43D6-8B9A-579DED3D9A96}.Debug - Sonar|Any CPU.Build.0 = Debug|Any CPU
{B6269AAC-170A-43D6-8B9A-579DED3D9A96}.Debug - Sonar|x64.ActiveCfg = Debug|Any CPU
{B6269AAC-170A-43D6-8B9A-579DED3D9A96}.Debug - Sonar|x64.Build.0 = Debug|Any CPU
{B6269AAC-170A-43D6-8B9A-579DED3D9A96}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {B6269AAC-170A-43D6-8B9A-579DED3D9A96}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B6269AAC-170A-43D6-8B9A-579DED3D9A96}.Debug|Any CPU.Build.0 = Debug|Any CPU {B6269AAC-170A-43D6-8B9A-579DED3D9A96}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B6269AAC-170A-43D6-8B9A-579DED3D9A96}.Debug|x64.ActiveCfg = Debug|Any CPU {B6269AAC-170A-43D6-8B9A-579DED3D9A96}.Debug|x64.ActiveCfg = Debug|Any CPU
@@ -200,6 +267,10 @@ Global
{B6269AAC-170A-43D6-8B9A-579DED3D9A96}.Release|Any CPU.Build.0 = Release|Any CPU {B6269AAC-170A-43D6-8B9A-579DED3D9A96}.Release|Any CPU.Build.0 = Release|Any CPU
{B6269AAC-170A-43D6-8B9A-579DED3D9A96}.Release|x64.ActiveCfg = Release|Any CPU {B6269AAC-170A-43D6-8B9A-579DED3D9A96}.Release|x64.ActiveCfg = Release|Any CPU
{B6269AAC-170A-43D6-8B9A-579DED3D9A96}.Release|x64.Build.0 = Release|Any CPU {B6269AAC-170A-43D6-8B9A-579DED3D9A96}.Release|x64.Build.0 = Release|Any CPU
{B6269AAC-170A-4346-8B9A-579DED3D9A94}.Debug - Sonar|Any CPU.ActiveCfg = Debug|Any CPU
{B6269AAC-170A-4346-8B9A-579DED3D9A94}.Debug - Sonar|Any CPU.Build.0 = Debug|Any CPU
{B6269AAC-170A-4346-8B9A-579DED3D9A94}.Debug - Sonar|x64.ActiveCfg = Debug|Any CPU
{B6269AAC-170A-4346-8B9A-579DED3D9A94}.Debug - Sonar|x64.Build.0 = Debug|Any CPU
{B6269AAC-170A-4346-8B9A-579DED3D9A94}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {B6269AAC-170A-4346-8B9A-579DED3D9A94}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B6269AAC-170A-4346-8B9A-579DED3D9A94}.Debug|Any CPU.Build.0 = Debug|Any CPU {B6269AAC-170A-4346-8B9A-579DED3D9A94}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B6269AAC-170A-4346-8B9A-579DED3D9A94}.Debug|x64.ActiveCfg = Debug|Any CPU {B6269AAC-170A-4346-8B9A-579DED3D9A94}.Debug|x64.ActiveCfg = Debug|Any CPU
@@ -208,6 +279,10 @@ Global
{B6269AAC-170A-4346-8B9A-579DED3D9A94}.Release|Any CPU.Build.0 = Release|Any CPU {B6269AAC-170A-4346-8B9A-579DED3D9A94}.Release|Any CPU.Build.0 = Release|Any CPU
{B6269AAC-170A-4346-8B9A-579DED3D9A94}.Release|x64.ActiveCfg = Release|Any CPU {B6269AAC-170A-4346-8B9A-579DED3D9A94}.Release|x64.ActiveCfg = Release|Any CPU
{B6269AAC-170A-4346-8B9A-579DED3D9A94}.Release|x64.Build.0 = Release|Any CPU {B6269AAC-170A-4346-8B9A-579DED3D9A94}.Release|x64.Build.0 = Release|Any CPU
{B6269AAC-170A-43D5-8B9A-579DED3D9A95}.Debug - Sonar|Any CPU.ActiveCfg = Debug|Any CPU
{B6269AAC-170A-43D5-8B9A-579DED3D9A95}.Debug - Sonar|Any CPU.Build.0 = Debug|Any CPU
{B6269AAC-170A-43D5-8B9A-579DED3D9A95}.Debug - Sonar|x64.ActiveCfg = Debug|Any CPU
{B6269AAC-170A-43D5-8B9A-579DED3D9A95}.Debug - Sonar|x64.Build.0 = Debug|Any CPU
{B6269AAC-170A-43D5-8B9A-579DED3D9A95}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {B6269AAC-170A-43D5-8B9A-579DED3D9A95}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B6269AAC-170A-43D5-8B9A-579DED3D9A95}.Debug|Any CPU.Build.0 = Debug|Any CPU {B6269AAC-170A-43D5-8B9A-579DED3D9A95}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B6269AAC-170A-43D5-8B9A-579DED3D9A95}.Debug|x64.ActiveCfg = Debug|Any CPU {B6269AAC-170A-43D5-8B9A-579DED3D9A95}.Debug|x64.ActiveCfg = Debug|Any CPU
@@ -216,6 +291,10 @@ Global
{B6269AAC-170A-43D5-8B9A-579DED3D9A95}.Release|Any CPU.Build.0 = Release|Any CPU {B6269AAC-170A-43D5-8B9A-579DED3D9A95}.Release|Any CPU.Build.0 = Release|Any CPU
{B6269AAC-170A-43D5-8B9A-579DED3D9A95}.Release|x64.ActiveCfg = Release|Any CPU {B6269AAC-170A-43D5-8B9A-579DED3D9A95}.Release|x64.ActiveCfg = Release|Any CPU
{B6269AAC-170A-43D5-8B9A-579DED3D9A95}.Release|x64.Build.0 = Release|Any CPU {B6269AAC-170A-43D5-8B9A-579DED3D9A95}.Release|x64.Build.0 = Release|Any CPU
{A9D039B9-7509-4CF1-9EFD-87EB82998575}.Debug - Sonar|Any CPU.ActiveCfg = Debug|Any CPU
{A9D039B9-7509-4CF1-9EFD-87EB82998575}.Debug - Sonar|Any CPU.Build.0 = Debug|Any CPU
{A9D039B9-7509-4CF1-9EFD-87EB82998575}.Debug - Sonar|x64.ActiveCfg = Debug|Any CPU
{A9D039B9-7509-4CF1-9EFD-87EB82998575}.Debug - Sonar|x64.Build.0 = Debug|Any CPU
{A9D039B9-7509-4CF1-9EFD-87EB82998575}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {A9D039B9-7509-4CF1-9EFD-87EB82998575}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A9D039B9-7509-4CF1-9EFD-87EB82998575}.Debug|Any CPU.Build.0 = Debug|Any CPU {A9D039B9-7509-4CF1-9EFD-87EB82998575}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A9D039B9-7509-4CF1-9EFD-87EB82998575}.Debug|x64.ActiveCfg = Debug|Any CPU {A9D039B9-7509-4CF1-9EFD-87EB82998575}.Debug|x64.ActiveCfg = Debug|Any CPU

View File

@@ -0,0 +1,13 @@
pool:
vmImage: 'Ubuntu 16.04'
variables:
buildConfiguration: 'Release'
steps:
- script: |
dotnet test ./test/WireMock.Net.Tests/WireMock.Net.Tests.csproj --configuration $(buildConfiguration) --framework netcoreapp2.1 --logger trx
- task: PublishTestResults@2
inputs:
testRunner: VSTest
testResultsFiles: '**/*.trx'

View File

@@ -49,7 +49,9 @@ steps:
%USERPROFILE%\.nuget\packages\codecov\1.1.0\tools\codecov.exe -f "./test/WireMock.Net.Tests/coverage.opencover.xml" -t $(CODECOV_TOKEN) %USERPROFILE%\.nuget\packages\codecov\1.1.0\tools\codecov.exe -f "./test/WireMock.Net.Tests/coverage.opencover.xml" -t $(CODECOV_TOKEN)
displayName: Upload coverage to codecov.io displayName: Upload coverage to codecov.io
# https://github.com/microsoft/azure-pipelines-tasks/issues/12212
- task: PublishTestResults@2 - task: PublishTestResults@2
condition: and(succeeded(), eq(variables['PUBLISH_TESTRESULTS'], 'yes'))
inputs: inputs:
testRunner: VSTest testRunner: VSTest
testResultsFiles: '**/*.trx' testResultsFiles: '**/*.trx'

View File

@@ -1,13 +1,23 @@
trigger:
- none
pool: pool:
vmImage: 'Ubuntu 16.04' vmImage: 'Ubuntu 16.04'
variables: variables:
buildProjects: '**/src/**/*.csproj'
buildConfiguration: 'Release' buildConfiguration: 'Release'
steps: steps:
- script: | - task: DotNetCoreCLI@2
dotnet test ./test/WireMock.Net.Tests/WireMock.Net.Tests.csproj --configuration $(buildConfiguration) --framework netcoreapp2.1 --logger trx displayName: Build Release
- task: PublishTestResults@2
inputs: inputs:
testRunner: VSTest command: 'build'
testResultsFiles: '**/*.trx' arguments: /p:Configuration=$(buildConfiguration)
projects: $(buildProjects)
- task: PublishBuildArtifacts@1
displayName: Publish Artifacts
condition: succeeded()
inputs:
PathtoPublish: '$(Build.ArtifactStagingDirectory)'

View File

@@ -14,7 +14,7 @@
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\..\src\WireMock.Net.Abstractions\WireMock.Net.Abstractions.csproj" /> <ProjectReference Include="..\..\src\WireMock.Net.Abstractions\WireMock.Net.Abstractions.csproj" />
<ProjectReference Include="..\..\src\WireMock.Net.RestClient\WireMock.Net.RestClient.csproj" /> <ProjectReference Include="..\..\src\WireMock.Net.RestClient\WireMock.Net.RestClient.csproj" />
<ProjectReference Include="..\..\src\WireMock.Net\WireMock.Net.csproj" /> <!--<ProjectReference Include="..\..\src\WireMock.Net\WireMock.Net.csproj" />-->
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@@ -59,7 +59,9 @@ namespace WireMock.Net.ConsoleApplication
{ {
var transformer = new CustomNameTransformer(); var transformer = new CustomNameTransformer();
handlebarsContext.RegisterHelper(transformer.Name, transformer.Render); handlebarsContext.RegisterHelper(transformer.Name, transformer.Render);
} },
AllowAnyHttpStatusCodeInResponse = true
// Uncomment below if you want to use the CustomFileSystemFileHandler // Uncomment below if you want to use the CustomFileSystemFileHandler
// FileSystemHandler = new CustomFileSystemFileHandler() // FileSystemHandler = new CustomFileSystemFileHandler()

View File

@@ -8,6 +8,7 @@
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\..\src\WireMock.Net\WireMock.Net.csproj" /> <ProjectReference Include="..\..\src\WireMock.Net\WireMock.Net.csproj" />
<ProjectReference Include="..\..\src\WireMock.Net.Abstractions\WireMock.Net.Abstractions.csproj" />
<PackageReference Include="Newtonsoft.Json" Version="11.0.2" /> <PackageReference Include="Newtonsoft.Json" Version="11.0.2" />
</ItemGroup> </ItemGroup>

View File

@@ -47,18 +47,12 @@
<Reference Include="Microsoft.Owin.Hosting, Version=2.0.2.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"> <Reference Include="Microsoft.Owin.Hosting, Version=2.0.2.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\..\packages\Microsoft.Owin.Hosting.2.0.2\lib\net45\Microsoft.Owin.Hosting.dll</HintPath> <HintPath>..\..\packages\Microsoft.Owin.Hosting.2.0.2\lib\net45\Microsoft.Owin.Hosting.dll</HintPath>
</Reference> </Reference>
<Reference Include="MimeKitLite, Version=2.0.0.0, Culture=neutral, PublicKeyToken=bede1c8a46c66814, processorArchitecture=MSIL">
<HintPath>..\..\packages\MimeKitLite.2.0.1\lib\net45\MimeKitLite.dll</HintPath>
</Reference>
<Reference Include="Newtonsoft.Json, Version=11.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL"> <Reference Include="Newtonsoft.Json, Version=11.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\..\packages\Newtonsoft.Json.11.0.2\lib\net45\Newtonsoft.Json.dll</HintPath> <HintPath>..\..\packages\Newtonsoft.Json.11.0.2\lib\net45\Newtonsoft.Json.dll</HintPath>
</Reference> </Reference>
<Reference Include="Owin, Version=1.0.0.0, Culture=neutral, PublicKeyToken=f0ebd12fd5e55cc5, processorArchitecture=MSIL"> <Reference Include="Owin, Version=1.0.0.0, Culture=neutral, PublicKeyToken=f0ebd12fd5e55cc5, processorArchitecture=MSIL">
<HintPath>..\..\packages\Owin.1.0\lib\net40\Owin.dll</HintPath> <HintPath>..\..\packages\Owin.1.0\lib\net40\Owin.dll</HintPath>
</Reference> </Reference>
<Reference Include="RestEase, Version=1.4.10.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\..\packages\RestEase.1.4.10\lib\net45\RestEase.dll</HintPath>
</Reference>
<Reference Include="SimMetrics.Net, Version=1.0.5.0, Culture=neutral, PublicKeyToken=c58dc06d59f3391b, processorArchitecture=MSIL"> <Reference Include="SimMetrics.Net, Version=1.0.5.0, Culture=neutral, PublicKeyToken=c58dc06d59f3391b, processorArchitecture=MSIL">
<HintPath>..\..\packages\SimMetrics.Net.1.0.5\lib\net45\SimMetrics.Net.dll</HintPath> <HintPath>..\..\packages\SimMetrics.Net.1.0.5\lib\net45\SimMetrics.Net.dll</HintPath>
</Reference> </Reference>
@@ -86,8 +80,8 @@
<Reference Include="System.Data" /> <Reference Include="System.Data" />
<Reference Include="System.Net.Http" /> <Reference Include="System.Net.Http" />
<Reference Include="System.Xml" /> <Reference Include="System.Xml" />
<Reference Include="XPath2, Version=1.0.7.0, Culture=neutral, PublicKeyToken=463c6d7fb740c7e5, processorArchitecture=MSIL"> <Reference Include="XPath2, Version=1.0.9.0, Culture=neutral, PublicKeyToken=463c6d7fb740c7e5, processorArchitecture=MSIL">
<HintPath>..\..\packages\XPath2.1.0.6.1\lib\net40\XPath2.dll</HintPath> <HintPath>..\..\packages\XPath2.1.0.10\lib\net40\XPath2.dll</HintPath>
</Reference> </Reference>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View File

@@ -1,8 +1,9 @@
using log4net; using System;
using log4net;
using Newtonsoft.Json; using Newtonsoft.Json;
using Wiremock.Net.Service; using Wiremock.Net.Service;
using WireMock.Admin.Requests;
using WireMock.Logging; using WireMock.Logging;
using WireMock.Models.Requests;
namespace WireMock.Net.Service namespace WireMock.Net.Service
{ {
@@ -30,6 +31,11 @@ namespace WireMock.Net.Service
Log.ErrorFormat(formatString, args); Log.ErrorFormat(formatString, args);
} }
public void Error(string message, Exception exception)
{
Log.Error(message, exception);
}
public void DebugRequestResponse(LogEntryModel logEntryModel, bool isAdminRequest) public void DebugRequestResponse(LogEntryModel logEntryModel, bool isAdminRequest)
{ {
string message = JsonConvert.SerializeObject(logEntryModel, Formatting.Indented); string message = JsonConvert.SerializeObject(logEntryModel, Formatting.Indented);

View File

@@ -9,11 +9,9 @@
<package id="Microsoft.Owin" version="2.0.2" targetFramework="net452" /> <package id="Microsoft.Owin" version="2.0.2" targetFramework="net452" />
<package id="Microsoft.Owin.Host.HttpListener" version="2.0.2" targetFramework="net452" /> <package id="Microsoft.Owin.Host.HttpListener" version="2.0.2" targetFramework="net452" />
<package id="Microsoft.Owin.Hosting" version="2.0.2" targetFramework="net452" /> <package id="Microsoft.Owin.Hosting" version="2.0.2" targetFramework="net452" />
<package id="MimeKitLite" version="2.0.1" targetFramework="net452" />
<package id="Newtonsoft.Json" version="11.0.2" targetFramework="net452" /> <package id="Newtonsoft.Json" version="11.0.2" targetFramework="net452" />
<package id="Owin" version="1.0" targetFramework="net452" /> <package id="Owin" version="1.0" targetFramework="net452" />
<package id="RestEase" version="1.4.10" targetFramework="net452" />
<package id="SimMetrics.Net" version="1.0.5" targetFramework="net452" /> <package id="SimMetrics.Net" version="1.0.5" targetFramework="net452" />
<package id="System.Net.Http" version="4.3.3" targetFramework="net452" /> <package id="System.Net.Http" version="4.3.3" targetFramework="net452" />
<package id="XPath2" version="1.0.6.1" targetFramework="net452" /> <package id="XPath2" version="1.0.10" targetFramework="net452" />
</packages> </packages>

View File

@@ -2,7 +2,7 @@
<PropertyGroup> <PropertyGroup>
<OutputType>Exe</OutputType> <OutputType>Exe</OutputType>
<TargetFrameworks>netcoreapp2.1;netcoreapp2.0;netcoreapp1.1</TargetFrameworks> <TargetFrameworks>netcoreapp2.1</TargetFrameworks>
<ApplicationIcon>../../WireMock.Net-Logo.ico</ApplicationIcon> <ApplicationIcon>../../WireMock.Net-Logo.ico</ApplicationIcon>
<StartupObject>WireMock.Net.StandAlone.NETCoreApp.Program</StartupObject> <StartupObject>WireMock.Net.StandAlone.NETCoreApp.Program</StartupObject>
</PropertyGroup> </PropertyGroup>

View File

@@ -1,7 +1,8 @@
using log4net; using System;
using log4net;
using Newtonsoft.Json; using Newtonsoft.Json;
using WireMock.Admin.Requests;
using WireMock.Logging; using WireMock.Logging;
using WireMock.Models.Requests;
namespace WireMock.Net.StandAlone.NETCoreApp namespace WireMock.Net.StandAlone.NETCoreApp
{ {
@@ -29,6 +30,11 @@ namespace WireMock.Net.StandAlone.NETCoreApp
Log.ErrorFormat(formatString, args); Log.ErrorFormat(formatString, args);
} }
public void Error(string message, Exception exception)
{
Log.Error(message, exception);
}
public void DebugRequestResponse(LogEntryModel logEntryModel, bool isAdminRequest) public void DebugRequestResponse(LogEntryModel logEntryModel, bool isAdminRequest)
{ {
string message = JsonConvert.SerializeObject(logEntryModel, Formatting.Indented); string message = JsonConvert.SerializeObject(logEntryModel, Formatting.Indented);

View File

@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk.Web"> <Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup> <PropertyGroup>
<TargetFrameworks>netcoreapp2.0;netcoreapp2.1</TargetFrameworks> <TargetFramework>netcoreapp2.1</TargetFramework>
<RuntimeIdentifiers>win10-x64</RuntimeIdentifiers> <RuntimeIdentifiers>win10-x64</RuntimeIdentifiers>
<StartupObject>WireMock.Net.WebApplication.Program</StartupObject> <StartupObject>WireMock.Net.WebApplication.Program</StartupObject>
<AssemblyName>WireMock.Net.WebApplication</AssemblyName> <AssemblyName>WireMock.Net.WebApplication</AssemblyName>

View File

@@ -16,5 +16,15 @@ namespace WireMock.Admin.Mappings
/// Gets or sets the matchers. /// Gets or sets the matchers.
/// </summary> /// </summary>
public IList<MatcherModel> Matchers { get; set; } public IList<MatcherModel> Matchers { get; set; }
/// <summary>
/// Gets or sets the ignore case.
/// </summary>
public bool? IgnoreCase { get; set; }
/// <summary>
/// Reject on match.
/// </summary>
public bool? RejectOnMatch { get; set; }
} }
} }

View File

@@ -16,5 +16,15 @@ namespace WireMock.Admin.Mappings
/// Gets or sets the matchers. /// Gets or sets the matchers.
/// </summary> /// </summary>
public IList<MatcherModel> Matchers { get; set; } public IList<MatcherModel> Matchers { get; set; }
/// <summary>
/// Gets or sets the ignore case.
/// </summary>
public bool? IgnoreCase { get; set; }
/// <summary>
/// Reject on match.
/// </summary>
public bool? RejectOnMatch { get; set; }
} }
} }

View File

@@ -1,4 +1,5 @@
using JetBrains.Annotations; using System;
using JetBrains.Annotations;
using WireMock.Admin.Requests; using WireMock.Admin.Requests;
namespace WireMock.Logging namespace WireMock.Logging
@@ -45,6 +46,15 @@ namespace WireMock.Logging
[StringFormatMethod("formatString")] [StringFormatMethod("formatString")]
void Error([NotNull] string formatString, [NotNull] params object[] args); void Error([NotNull] string formatString, [NotNull] params object[] args);
/// <summary>
/// Writes the message at the Error level using the specified exception.
/// </summary>
/// <param name="formatString">The format string.</param>
/// <param name="exception">The exception.</param>
[PublicAPI]
[StringFormatMethod("formatString")]
void Error([NotNull] string formatString, [NotNull] Exception exception);
/// <summary> /// <summary>
/// Writes the LogEntryModel (LogRequestModel, LogResponseModel and more). /// Writes the LogEntryModel (LogRequestModel, LogResponseModel and more).
/// </summary> /// </summary>

View File

@@ -74,6 +74,14 @@ namespace WireMock.Client
[Delete("mappings")] [Delete("mappings")]
Task<StatusModel> DeleteMappingsAsync(); Task<StatusModel> DeleteMappingsAsync();
/// <summary>
/// Delete mappings according to GUIDs
/// </summary>
/// <param name="mappings">MappingModels</param>
[Delete("mappings")]
[Header("Content-Type", "application/json")]
Task<StatusModel> DeleteMappingsAsync([Body] IList<MappingModel> mappings);
/// <summary> /// <summary>
/// Delete (reset) all mappings. /// Delete (reset) all mappings.
/// </summary> /// </summary>

View File

@@ -17,13 +17,13 @@ namespace WireMock.Net.StandAlone
/// </summary> /// </summary>
/// <param name="settings">The FluentMockServerSettings</param> /// <param name="settings">The FluentMockServerSettings</param>
[PublicAPI] [PublicAPI]
public static WireMockServer Start([NotNull] FluentMockServerSettings settings) public static WireMockServer Start([NotNull] IWireMockServerSettings settings)
{ {
Check.NotNull(settings, nameof(settings)); Check.NotNull(settings, nameof(settings));
var server = WireMockServer.Start(settings); var server = WireMockServer.Start(settings);
settings.Logger.Info("WireMock.Net server listening at {0}", string.Join(",", server.Urls)); settings.Logger?.Info("WireMock.Net server listening at {0}", string.Join(",", server.Urls));
return server; return server;
} }
@@ -38,9 +38,9 @@ namespace WireMock.Net.StandAlone
{ {
Check.NotNull(args, nameof(args)); Check.NotNull(args, nameof(args));
var settings = (FluentMockServerSettings) WireMockServerSettingsParser.ParseArguments(args); var settings = WireMockServerSettingsParser.ParseArguments(args, logger);
settings.Logger.Debug("WireMock.Net server arguments [{0}]", string.Join(", ", args.Select(a => $"'{a}'"))); settings.Logger?.Debug("WireMock.Net server arguments [{0}]", string.Join(", ", args.Select(a => $"'{a}'")));
return Start(settings); return Start(settings);
} }

View File

@@ -1,5 +1,6 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using WireMock.Util;
using WireMock.Validation; using WireMock.Validation;
namespace WireMock.Handlers namespace WireMock.Handlers
@@ -80,20 +81,20 @@ namespace WireMock.Handlers
public byte[] ReadResponseBodyAsFile(string path) public byte[] ReadResponseBodyAsFile(string path)
{ {
Check.NotNullOrEmpty(path, nameof(path)); Check.NotNullOrEmpty(path, nameof(path));
path = PathUtils.CleanPath(path);
// In case the path is a filename, the path will be adjusted to the MappingFolder. // If the file exists at the given path relative to the MappingsFolder, then return that.
// Else the path will just be as-is. // Else the path will just be as-is.
return File.ReadAllBytes(Path.GetFileName(path) == path ? Path.Combine(GetMappingFolder(), path) : path); return File.ReadAllBytes(File.Exists(PathUtils.Combine(GetMappingFolder(), path)) ? PathUtils.Combine(GetMappingFolder(), path) : path);
} }
/// <inheritdoc cref="IFileSystemHandler.ReadResponseBodyAsString"/> /// <inheritdoc cref="IFileSystemHandler.ReadResponseBodyAsString"/>
public string ReadResponseBodyAsString(string path) public string ReadResponseBodyAsString(string path)
{ {
Check.NotNullOrEmpty(path, nameof(path)); Check.NotNullOrEmpty(path, nameof(path));
path = PathUtils.CleanPath(path);
// In case the path is a filename, the path will be adjusted to the MappingFolder. // In case the path is a filename, the path will be adjusted to the MappingFolder.
// Else the path will just be as-is. // Else the path will just be as-is.
return File.ReadAllText(Path.GetFileName(path) == path ? Path.Combine(GetMappingFolder(), path) : path); return File.ReadAllText(File.Exists(PathUtils.Combine(GetMappingFolder(), path)) ? PathUtils.Combine(GetMappingFolder(), path) : path);
} }
/// <inheritdoc cref="IFileSystemHandler.FileExists"/> /// <inheritdoc cref="IFileSystemHandler.FileExists"/>

View File

@@ -36,12 +36,27 @@ namespace WireMock.Logging
Console.WriteLine(Format("Warn", formatString, args)); Console.WriteLine(Format("Warn", formatString, args));
} }
/// <see cref="IWireMockLogger.Error"/> /// <see cref="IWireMockLogger.Error(string, object[])"/>
public void Error(string formatString, params object[] args) public void Error(string formatString, params object[] args)
{ {
Console.WriteLine(Format("Error", formatString, args)); Console.WriteLine(Format("Error", formatString, args));
} }
/// <see cref="IWireMockLogger.Error(string, Exception)"/>
public void Error(string formatString, Exception exception)
{
Console.WriteLine(Format("Error", formatString, exception.Message));
if (exception is AggregateException ae)
{
ae.Handle(ex =>
{
Console.WriteLine(Format("Error", "Exception {0}", exception.Message));
return true;
});
}
}
/// <see cref="IWireMockLogger.DebugRequestResponse"/> /// <see cref="IWireMockLogger.DebugRequestResponse"/>
public void DebugRequestResponse(LogEntryModel logEntryModel, bool isAdminRequest) public void DebugRequestResponse(LogEntryModel logEntryModel, bool isAdminRequest)
{ {

View File

@@ -1,4 +1,5 @@
using WireMock.Admin.Requests; using System;
using WireMock.Admin.Requests;
namespace WireMock.Logging namespace WireMock.Logging
{ {
@@ -26,12 +27,18 @@ namespace WireMock.Logging
// Log nothing // Log nothing
} }
/// <see cref="IWireMockLogger.Error"/> /// <see cref="IWireMockLogger.Error(string, object[])"/>
public void Error(string formatString, params object[] args) public void Error(string formatString, params object[] args)
{ {
// Log nothing // Log nothing
} }
/// <see cref="IWireMockLogger.Error(string, Exception)"/>
public void Error(string formatString, Exception exception)
{
// Log nothing
}
/// <see cref="IWireMockLogger.DebugRequestResponse"/> /// <see cref="IWireMockLogger.DebugRequestResponse"/>
public void DebugRequestResponse(LogEntryModel logEntryModel, bool isAdminRequest) public void DebugRequestResponse(LogEntryModel logEntryModel, bool isAdminRequest)
{ {

View File

@@ -61,7 +61,8 @@ namespace WireMock.Matchers
IgnoreCase = ignoreCase; IgnoreCase = ignoreCase;
MatchBehaviour = matchBehaviour; MatchBehaviour = matchBehaviour;
RegexOptions options = RegexOptions.Compiled; RegexOptions options = RegexOptions.Compiled | RegexOptions.Multiline;
if (ignoreCase) if (ignoreCase)
{ {
options |= RegexOptions.IgnoreCase; options |= RegexOptions.IgnoreCase;

View File

@@ -9,14 +9,15 @@ namespace WireMock.Matchers.Request
/// <summary> /// <summary>
/// The request cookie matcher. /// The request cookie matcher.
/// </summary> /// </summary>
/// <inheritdoc cref="IRequestMatcher"/>
public class RequestMessageCookieMatcher : IRequestMatcher public class RequestMessageCookieMatcher : IRequestMatcher
{ {
private readonly MatchBehaviour _matchBehaviour; private readonly MatchBehaviour _matchBehaviour;
private readonly bool _ignoreCase; private readonly bool _ignoreCase;
/// <value> /// <summary>
/// The funcs. /// The functions
/// </value> /// </summary>
public Func<IDictionary<string, string>, bool>[] Funcs { get; } public Func<IDictionary<string, string>, bool>[] Funcs { get; }
/// <summary> /// <summary>
@@ -32,11 +33,11 @@ namespace WireMock.Matchers.Request
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="RequestMessageCookieMatcher"/> class. /// Initializes a new instance of the <see cref="RequestMessageCookieMatcher"/> class.
/// </summary> /// </summary>
/// <param name="matchBehaviour">The match behaviour.</param>
/// <param name="name">The name.</param> /// <param name="name">The name.</param>
/// <param name="pattern">The pattern.</param> /// <param name="pattern">The pattern.</param>
/// <param name="ignoreCase">The ignoreCase.</param> /// <param name="ignoreCase">Ignore the case from the pattern.</param>
public RequestMessageCookieMatcher(MatchBehaviour matchBehaviour, [NotNull] string name, [NotNull] string pattern, bool ignoreCase = true) /// <param name="matchBehaviour">The match behaviour.</param>
public RequestMessageCookieMatcher(MatchBehaviour matchBehaviour, [NotNull] string name, [NotNull] string pattern, bool ignoreCase)
{ {
Check.NotNull(name, nameof(name)); Check.NotNull(name, nameof(name));
Check.NotNull(pattern, nameof(pattern)); Check.NotNull(pattern, nameof(pattern));
@@ -50,15 +51,32 @@ namespace WireMock.Matchers.Request
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="RequestMessageCookieMatcher"/> class. /// Initializes a new instance of the <see cref="RequestMessageCookieMatcher"/> class.
/// </summary> /// </summary>
/// <param name="matchBehaviour">The match behaviour.</param>
/// <param name="name">The name.</param>
/// <param name="patterns">The patterns.</param>
/// <param name="ignoreCase">Ignore the case from the pattern.</param>
public RequestMessageCookieMatcher(MatchBehaviour matchBehaviour, [NotNull] string name, bool ignoreCase, [NotNull] params string[] patterns) :
this(matchBehaviour, name, ignoreCase, patterns.Select(pattern => new WildcardMatcher(matchBehaviour, pattern, ignoreCase)).Cast<IStringMatcher>().ToArray())
{
Check.NotNull(patterns, nameof(patterns));
}
/// <summary>
/// Initializes a new instance of the <see cref="RequestMessageCookieMatcher"/> class.
/// </summary>
/// <param name="matchBehaviour">The match behaviour.</param>
/// <param name="name">The name.</param> /// <param name="name">The name.</param>
/// <param name="matchers">The matchers.</param> /// <param name="matchers">The matchers.</param>
public RequestMessageCookieMatcher([NotNull] string name, [NotNull] params IStringMatcher[] matchers) /// <param name="ignoreCase">Ignore the case from the pattern.</param>
public RequestMessageCookieMatcher(MatchBehaviour matchBehaviour, [NotNull] string name, bool ignoreCase, [NotNull] params IStringMatcher[] matchers)
{ {
Check.NotNull(name, nameof(name)); Check.NotNull(name, nameof(name));
Check.NotNull(matchers, nameof(matchers)); Check.NotNull(matchers, nameof(matchers));
_matchBehaviour = matchBehaviour;
Name = name; Name = name;
Matchers = matchers; Matchers = matchers;
_ignoreCase = ignoreCase;
} }
/// <summary> /// <summary>

View File

@@ -52,33 +52,32 @@ namespace WireMock.Matchers.Request
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="RequestMessageHeaderMatcher"/> class. /// Initializes a new instance of the <see cref="RequestMessageHeaderMatcher"/> class.
/// </summary> /// </summary>
/// <param name="matchBehaviour">The match behaviour.</param>
/// <param name="name">The name.</param> /// <param name="name">The name.</param>
/// <param name="patterns">The patterns.</param> /// <param name="patterns">The patterns.</param>
/// <param name="ignoreCase">Ignore the case from the pattern.</param> /// <param name="ignoreCase">Ignore the case from the pattern.</param>
/// <param name="matchBehaviour">The match behaviour.</param> public RequestMessageHeaderMatcher(MatchBehaviour matchBehaviour, [NotNull] string name, bool ignoreCase, [NotNull] params string[] patterns) :
public RequestMessageHeaderMatcher(MatchBehaviour matchBehaviour, [NotNull] string name, [NotNull] string[] patterns, bool ignoreCase) this(matchBehaviour, name, ignoreCase, patterns.Select(pattern => new WildcardMatcher(matchBehaviour, pattern, ignoreCase)).Cast<IStringMatcher>().ToArray())
{ {
Check.NotNull(name, nameof(name));
Check.NotNull(patterns, nameof(patterns)); Check.NotNull(patterns, nameof(patterns));
_matchBehaviour = matchBehaviour;
_ignoreCase = ignoreCase;
Name = name;
Matchers = patterns.Select(pattern => new WildcardMatcher(matchBehaviour, pattern, ignoreCase)).Cast<IStringMatcher>().ToArray();
} }
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="RequestMessageHeaderMatcher"/> class. /// Initializes a new instance of the <see cref="RequestMessageHeaderMatcher"/> class.
/// </summary> /// </summary>
/// <param name="matchBehaviour">The match behaviour.</param>
/// <param name="name">The name.</param> /// <param name="name">The name.</param>
/// <param name="matchers">The matchers.</param> /// <param name="matchers">The matchers.</param>
public RequestMessageHeaderMatcher([NotNull] string name, [NotNull] params IStringMatcher[] matchers) /// <param name="ignoreCase">Ignore the case from the pattern.</param>
public RequestMessageHeaderMatcher(MatchBehaviour matchBehaviour, [NotNull] string name, bool ignoreCase, [NotNull] params IStringMatcher[] matchers)
{ {
Check.NotNull(name, nameof(name)); Check.NotNull(name, nameof(name));
Check.NotNull(matchers, nameof(matchers)); Check.NotNull(matchers, nameof(matchers));
_matchBehaviour = matchBehaviour;
Name = name; Name = name;
Matchers = matchers; Matchers = matchers;
_ignoreCase = ignoreCase;
} }
/// <summary> /// <summary>
@@ -125,7 +124,7 @@ namespace WireMock.Matchers.Request
} }
WireMockList<string> list = headers[Name]; WireMockList<string> list = headers[Name];
return Matchers.Max(m => list.Max(value => m.IsMatch(value))); // TODO : is this correct ? return Matchers.Max(m => list.Max(m.IsMatch)); // TODO : is this correct ?
} }
} }
} }

View File

@@ -8,7 +8,6 @@ using JetBrains.Annotations;
using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using WireMock.Handlers;
using WireMock.HttpsCertificate; using WireMock.HttpsCertificate;
using WireMock.Logging; using WireMock.Logging;
using WireMock.Owin.Mappers; using WireMock.Owin.Mappers;
@@ -70,7 +69,6 @@ namespace WireMock.Owin
_host = builder _host = builder
.ConfigureServices(services => .ConfigureServices(services =>
{ {
services.AddSingleton(_options.FileSystemHandler);
services.AddSingleton(_options); services.AddSingleton(_options);
services.AddSingleton<IMappingMatcher, MappingMatcher>(); services.AddSingleton<IMappingMatcher, MappingMatcher>();
services.AddSingleton<IOwinRequestMapper, OwinRequestMapper>(); services.AddSingleton<IOwinRequestMapper, OwinRequestMapper>();

View File

@@ -39,5 +39,7 @@ namespace WireMock.Owin
IFileSystemHandler FileSystemHandler { get; set; } IFileSystemHandler FileSystemHandler { get; set; }
bool? AllowBodyForAllHttpMethods { get; set; } bool? AllowBodyForAllHttpMethods { get; set; }
bool? AllowAnyHttpStatusCodeInResponse { get; set; }
} }
} }

View File

@@ -1,16 +1,17 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Net;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using Newtonsoft.Json; using Newtonsoft.Json;
using RandomDataGenerator.FieldOptions; using RandomDataGenerator.FieldOptions;
using RandomDataGenerator.Randomizers; using RandomDataGenerator.Randomizers;
using WireMock.Exceptions;
using WireMock.Handlers; using WireMock.Handlers;
using WireMock.Http; using WireMock.Http;
using WireMock.ResponseBuilders; using WireMock.ResponseBuilders;
using WireMock.Types; using WireMock.Types;
using WireMock.Util;
using WireMock.Validation; using WireMock.Validation;
#if !USE_ASPNETCORE #if !USE_ASPNETCORE
using IResponse = Microsoft.Owin.IOwinResponse; using IResponse = Microsoft.Owin.IOwinResponse;
@@ -24,11 +25,11 @@ namespace WireMock.Owin.Mappers
/// <summary> /// <summary>
/// OwinResponseMapper /// OwinResponseMapper
/// </summary> /// </summary>
public class OwinResponseMapper : IOwinResponseMapper internal class OwinResponseMapper : IOwinResponseMapper
{ {
private readonly IRandomizerNumber<double> _randomizerDouble = RandomizerFactory.GetRandomizer(new FieldOptionsDouble { Min = 0, Max = 1 }); private readonly IRandomizerNumber<double> _randomizerDouble = RandomizerFactory.GetRandomizer(new FieldOptionsDouble { Min = 0, Max = 1 });
private readonly IRandomizerBytes _randomizerBytes = RandomizerFactory.GetRandomizer(new FieldOptionsBytes { Min = 100, Max = 200 }); private readonly IRandomizerBytes _randomizerBytes = RandomizerFactory.GetRandomizer(new FieldOptionsBytes { Min = 100, Max = 200 });
private readonly IFileSystemHandler _fileSystemHandler; private readonly IWireMockMiddlewareOptions _options;
private readonly Encoding _utf8NoBom = new UTF8Encoding(false); private readonly Encoding _utf8NoBom = new UTF8Encoding(false);
// https://msdn.microsoft.com/en-us/library/78h415ay(v=vs.110).aspx // https://msdn.microsoft.com/en-us/library/78h415ay(v=vs.110).aspx
@@ -43,12 +44,12 @@ namespace WireMock.Owin.Mappers
/// <summary> /// <summary>
/// Constructor /// Constructor
/// </summary> /// </summary>
/// <param name="fileSystemHandler">The IFileSystemHandler.</param> /// <param name="options">The IWireMockMiddlewareOptions.</param>
public OwinResponseMapper(IFileSystemHandler fileSystemHandler) public OwinResponseMapper(IWireMockMiddlewareOptions options)
{ {
Check.NotNull(fileSystemHandler, nameof(fileSystemHandler)); Check.NotNull(options, nameof(options));
_fileSystemHandler = fileSystemHandler; _options = options;
} }
/// <inheritdoc cref="IOwinResponseMapper.MapAsync"/> /// <inheritdoc cref="IOwinResponseMapper.MapAsync"/>
@@ -83,11 +84,13 @@ namespace WireMock.Owin.Mappers
switch (responseMessage.StatusCode) switch (responseMessage.StatusCode)
{ {
case int statusCodeAsInteger: case int statusCodeAsInteger:
response.StatusCode = statusCodeAsInteger; response.StatusCode = MapStatusCode(statusCodeAsInteger);
break; break;
case string statusCodeAsString: case string statusCodeAsString:
response.StatusCode = int.Parse(statusCodeAsString); // Note: this case will also match on null
int.TryParse(statusCodeAsString, out int result);
response.StatusCode = MapStatusCode(result);
break; break;
} }
@@ -99,6 +102,16 @@ namespace WireMock.Owin.Mappers
} }
} }
private int MapStatusCode(int code)
{
if (_options.AllowAnyHttpStatusCodeInResponse == true || Enum.IsDefined(typeof(HttpStatusCode), code))
{
return code;
}
return (int)HttpStatusCode.OK;
}
private bool IsFault(ResponseMessage responseMessage) private bool IsFault(ResponseMessage responseMessage)
{ {
return responseMessage.FaultPercentage == null || _randomizerDouble.Generate() <= responseMessage.FaultPercentage; return responseMessage.FaultPercentage == null || _randomizerDouble.Generate() <= responseMessage.FaultPercentage;
@@ -126,7 +139,7 @@ namespace WireMock.Owin.Mappers
break; break;
case BodyType.File: case BodyType.File:
bytes = _fileSystemHandler.ReadResponseBodyAsFile(responseMessage.BodyData.BodyAsFile); bytes = _options.FileSystemHandler.ReadResponseBodyAsFile(responseMessage.BodyData.BodyAsFile);
break; break;
} }

View File

@@ -6,7 +6,6 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using WireMock.Handlers;
using WireMock.Logging; using WireMock.Logging;
using WireMock.Owin.Mappers; using WireMock.Owin.Mappers;
using WireMock.Util; using WireMock.Util;
@@ -76,7 +75,7 @@ namespace WireMock.Owin
try try
{ {
var requestMapper = new OwinRequestMapper(); var requestMapper = new OwinRequestMapper();
var responseMapper = new OwinResponseMapper(_options.FileSystemHandler); var responseMapper = new OwinResponseMapper(_options);
var matcher = new MappingMatcher(_options); var matcher = new MappingMatcher(_options);
Action<IAppBuilder> startup = app => Action<IAppBuilder> startup = app =>

View File

@@ -42,5 +42,8 @@ namespace WireMock.Owin
/// <inheritdoc cref="IWireMockMiddlewareOptions.AllowBodyForAllHttpMethods"/> /// <inheritdoc cref="IWireMockMiddlewareOptions.AllowBodyForAllHttpMethods"/>
public bool? AllowBodyForAllHttpMethods { get; set; } public bool? AllowBodyForAllHttpMethods { get; set; }
/// <inheritdoc cref="IWireMockMiddlewareOptions.AllowAnyHttpStatusCodeInResponse"/>
public bool? AllowAnyHttpStatusCodeInResponse { get; set; }
} }
} }

View File

@@ -0,0 +1,85 @@
using JetBrains.Annotations;
using System;
using System.Collections.Generic;
using WireMock.Matchers;
namespace WireMock.RequestBuilders
{
/// <summary>
/// The CookieRequestBuilder interface.
/// </summary>
public interface ICookiesRequestBuilder : IParamsRequestBuilder
{
/// <summary>
/// WithCookie: matching based on name, pattern and matchBehaviour.
/// </summary>
/// <param name="name">The name.</param>
/// <param name="pattern">The pattern.</param>
/// <param name="matchBehaviour">The match behaviour.</param>
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
IRequestBuilder WithCookie([NotNull] string name, string pattern, MatchBehaviour matchBehaviour);
/// <summary>
/// WithCookie: matching based on name, pattern, ignoreCase and matchBehaviour.
/// </summary>
/// <param name="name">The name.</param>
/// <param name="pattern">The pattern.</param>
/// <param name="ignoreCase">Ignore the case from the pattern.</param>
/// <param name="matchBehaviour">The match behaviour.</param>
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
IRequestBuilder WithCookie([NotNull] string name, string pattern, bool ignoreCase = true, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch);
/// <summary>
/// WithCookie: matching based on name, patterns and matchBehaviour.
/// </summary>
/// <param name="name">The name.</param>
/// <param name="patterns">The patterns.</param>
/// <param name="matchBehaviour">The match behaviour.</param>
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
IRequestBuilder WithCookie([NotNull] string name, string[] patterns, MatchBehaviour matchBehaviour);
/// <summary>
/// WithCookie: matching based on name, patterns, ignoreCase and matchBehaviour.
/// </summary>
/// <param name="name">The name.</param>
/// <param name="patterns">The patterns.</param>
/// <param name="ignoreCase">Ignore the case from the pattern.</param>
/// <param name="matchBehaviour">The match behaviour.</param>
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
IRequestBuilder WithCookie([NotNull] string name, string[] patterns, bool ignoreCase = true, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch);
/// <summary>
/// WithCookie: matching based on name and IStringMatcher[].
/// </summary>
/// <param name="name">The name.</param>
/// <param name="matchers">The matchers.</param>
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
IRequestBuilder WithCookie([NotNull] string name, [NotNull] params IStringMatcher[] matchers);
/// <summary>
/// WithCookie: matching based on name, ignoreCase and IStringMatcher[].
/// </summary>
/// <param name="name">The name.</param>
/// <param name="ignoreCase">Ignore the case from the cookie-keys.</param>
/// <param name="matchers">The matchers.</param>
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
IRequestBuilder WithCookie([NotNull] string name, bool ignoreCase, [NotNull] params IStringMatcher[] matchers);
/// <summary>
/// WithCookie: matching based on name, ignoreCase, matchBehaviour and IStringMatcher[].
/// </summary>
/// <param name="name">The name.</param>
/// <param name="ignoreCase">Ignore the case from the cookie-keys.</param>
/// <param name="matchBehaviour">The match behaviour.</param>
/// <param name="matchers">The matchers.</param>
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
IRequestBuilder WithCookie([NotNull] string name, bool ignoreCase, MatchBehaviour matchBehaviour, [NotNull] params IStringMatcher[] matchers);
/// <summary>
/// WithCookie: matching based on functions.
/// </summary>
/// <param name="funcs">The cookies funcs.</param>
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
IRequestBuilder WithCookie([NotNull] params Func<IDictionary<string, string>, bool>[] funcs);
}
}

View File

@@ -6,9 +6,9 @@ using WireMock.Matchers;
namespace WireMock.RequestBuilders namespace WireMock.RequestBuilders
{ {
/// <summary> /// <summary>
/// The HeadersAndCookieRequestBuilder interface. /// The HeadersRequestBuilder interface.
/// </summary> /// </summary>
public interface IHeadersAndCookiesRequestBuilder : IParamsRequestBuilder public interface IHeadersRequestBuilder : ICookiesRequestBuilder
{ {
/// <summary> /// <summary>
/// WithHeader: matching based on name, pattern and matchBehaviour. /// WithHeader: matching based on name, pattern and matchBehaviour.
@@ -56,36 +56,30 @@ namespace WireMock.RequestBuilders
/// <returns>The <see cref="IRequestBuilder"/>.</returns> /// <returns>The <see cref="IRequestBuilder"/>.</returns>
IRequestBuilder WithHeader([NotNull] string name, [NotNull] params IStringMatcher[] matchers); IRequestBuilder WithHeader([NotNull] string name, [NotNull] params IStringMatcher[] matchers);
/// <summary>
/// WithHeader: matching based on name, ignoreCase and IStringMatcher[].
/// </summary>
/// <param name="name">The name.</param>
/// <param name="ignoreCase">Ignore the case from the header-keys.</param>
/// <param name="matchers">The matchers.</param>
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
IRequestBuilder WithHeader([NotNull] string name, bool ignoreCase, [NotNull] params IStringMatcher[] matchers);
/// <summary>
/// WithHeader: matching based on name, ignoreCase, matchBehaviour and IStringMatcher[].
/// </summary>
/// <param name="name">The name.</param>
/// <param name="ignoreCase">Ignore the case from the header-keys.</param>
/// <param name="matchBehaviour">The match behaviour.</param>
/// <param name="matchers">The matchers.</param>
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
IRequestBuilder WithHeader([NotNull] string name, bool ignoreCase, MatchBehaviour matchBehaviour, [NotNull] params IStringMatcher[] matchers);
/// <summary> /// <summary>
/// WithHeader: matching based on functions. /// WithHeader: matching based on functions.
/// </summary> /// </summary>
/// <param name="funcs">The headers funcs.</param> /// <param name="funcs">The headers funcs.</param>
/// <returns>The <see cref="IRequestBuilder"/>.</returns> /// <returns>The <see cref="IRequestBuilder"/>.</returns>
IRequestBuilder WithHeader([NotNull] params Func<IDictionary<string, string[]>, bool>[] funcs); IRequestBuilder WithHeader([NotNull] params Func<IDictionary<string, string[]>, bool>[] funcs);
/// <summary>
/// WithCookie: cookie matching based on name, pattern, ignoreCase and matchBehaviour.
/// </summary>
/// <param name="name">The name.</param>
/// <param name="pattern">The pattern.</param>
/// <param name="ignoreCase">Ignore the case from the pattern.</param>
/// <param name="matchBehaviour">The match behaviour.</param>
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
IRequestBuilder WithCookie([NotNull] string name, string pattern, bool ignoreCase = true, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch);
/// <summary>
/// WithCookie: matching based on name and IStringMatcher[].
/// </summary>
/// <param name="name">The name.</param>
/// <param name="matchers">The matchers.</param>
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
IRequestBuilder WithCookie([NotNull] string name, [NotNull] params IStringMatcher[] matchers);
/// <summary>
/// WithCookie: matching based on functions.
/// </summary>
/// <param name="funcs">The funcs.</param>
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
IRequestBuilder WithCookie([NotNull] params Func<IDictionary<string, string>, bool>[] funcs);
} }
} }

View File

@@ -7,7 +7,7 @@ namespace WireMock.RequestBuilders
/// <summary> /// <summary>
/// The MethodRequestBuilder interface. /// The MethodRequestBuilder interface.
/// </summary> /// </summary>
public interface IMethodRequestBuilder : IHeadersAndCookiesRequestBuilder public interface IMethodRequestBuilder : IHeadersRequestBuilder
{ {
/// <summary> /// <summary>
/// UsingDelete: add HTTP Method matching on `DELETE` and matchBehaviour (optional). /// UsingDelete: add HTTP Method matching on `DELETE` and matchBehaviour (optional).

View File

@@ -0,0 +1,82 @@
using System;
using System.Collections.Generic;
using WireMock.Matchers;
using WireMock.Matchers.Request;
using WireMock.Validation;
namespace WireMock.RequestBuilders
{
public partial class Request
{
/// <inheritdoc cref="ICookiesRequestBuilder.WithCookie(string, string, MatchBehaviour)"/>
public IRequestBuilder WithCookie(string name, string pattern, MatchBehaviour matchBehaviour)
{
return WithCookie(name, pattern, true, matchBehaviour);
}
/// <inheritdoc cref="ICookiesRequestBuilder.WithCookie(string, string, bool, MatchBehaviour)"/>
public IRequestBuilder WithCookie(string name, string pattern, bool ignoreCase = true, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch)
{
Check.NotNull(name, nameof(name));
Check.NotNull(pattern, nameof(pattern));
_requestMatchers.Add(new RequestMessageCookieMatcher(matchBehaviour, name, pattern, ignoreCase));
return this;
}
/// <inheritdoc cref="ICookiesRequestBuilder.WithCookie(string, string[], MatchBehaviour)"/>
public IRequestBuilder WithCookie(string name, string[] patterns, MatchBehaviour matchBehaviour)
{
return WithCookie(name, patterns, true, matchBehaviour);
}
/// <inheritdoc cref="ICookiesRequestBuilder.WithCookie(string, string[], bool, MatchBehaviour)"/>
public IRequestBuilder WithCookie(string name, string[] patterns, bool ignoreCase = true, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch)
{
Check.NotNull(name, nameof(name));
Check.NotNull(patterns, nameof(patterns));
_requestMatchers.Add(new RequestMessageCookieMatcher(matchBehaviour, name, ignoreCase, patterns));
return this;
}
/// <inheritdoc cref="ICookiesRequestBuilder.WithCookie(string, IStringMatcher[])"/>
public IRequestBuilder WithCookie(string name, params IStringMatcher[] matchers)
{
Check.NotNull(name, nameof(name));
Check.NotNullOrEmpty(matchers, nameof(matchers));
_requestMatchers.Add(new RequestMessageCookieMatcher(MatchBehaviour.AcceptOnMatch, name, false, matchers));
return this;
}
/// <inheritdoc cref="ICookiesRequestBuilder.WithCookie(string, bool, IStringMatcher[])"/>
public IRequestBuilder WithCookie(string name, bool ignoreCase, params IStringMatcher[] matchers)
{
Check.NotNull(name, nameof(name));
Check.NotNullOrEmpty(matchers, nameof(matchers));
_requestMatchers.Add(new RequestMessageCookieMatcher(MatchBehaviour.AcceptOnMatch, name, ignoreCase, matchers));
return this;
}
/// <inheritdoc cref="ICookiesRequestBuilder.WithCookie(string, IStringMatcher[])"/>
public IRequestBuilder WithCookie(string name, bool ignoreCase, MatchBehaviour matchBehaviour, params IStringMatcher[] matchers)
{
Check.NotNull(name, nameof(name));
Check.NotNullOrEmpty(matchers, nameof(matchers));
_requestMatchers.Add(new RequestMessageCookieMatcher(matchBehaviour, name, ignoreCase, matchers));
return this;
}
/// <inheritdoc cref="ICookiesRequestBuilder.WithCookie(Func{IDictionary{string, string}, bool}[])"/>
public IRequestBuilder WithCookie(params Func<IDictionary<string, string>, bool>[] funcs)
{
Check.NotNullOrEmpty(funcs, nameof(funcs));
_requestMatchers.Add(new RequestMessageCookieMatcher(funcs));
return this;
}
}
}

View File

@@ -0,0 +1,82 @@
using System;
using System.Collections.Generic;
using WireMock.Matchers;
using WireMock.Matchers.Request;
using WireMock.Validation;
namespace WireMock.RequestBuilders
{
public partial class Request
{
/// <inheritdoc cref="IHeadersRequestBuilder.WithHeader(string, string, MatchBehaviour)"/>
public IRequestBuilder WithHeader(string name, string pattern, MatchBehaviour matchBehaviour)
{
return WithHeader(name, pattern, true, matchBehaviour);
}
/// <inheritdoc cref="IHeadersRequestBuilder.WithHeader(string, string, bool, MatchBehaviour)"/>
public IRequestBuilder WithHeader(string name, string pattern, bool ignoreCase = true, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch)
{
Check.NotNull(name, nameof(name));
Check.NotNull(pattern, nameof(pattern));
_requestMatchers.Add(new RequestMessageHeaderMatcher(matchBehaviour, name, pattern, ignoreCase));
return this;
}
/// <inheritdoc cref="IHeadersRequestBuilder.WithHeader(string, string[], MatchBehaviour)"/>
public IRequestBuilder WithHeader(string name, string[] patterns, MatchBehaviour matchBehaviour)
{
return WithHeader(name, patterns, true, matchBehaviour);
}
/// <inheritdoc cref="IHeadersRequestBuilder.WithHeader(string, string[], bool, MatchBehaviour)"/>
public IRequestBuilder WithHeader(string name, string[] patterns, bool ignoreCase = true, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch)
{
Check.NotNull(name, nameof(name));
Check.NotNull(patterns, nameof(patterns));
_requestMatchers.Add(new RequestMessageHeaderMatcher(matchBehaviour, name, ignoreCase, patterns));
return this;
}
/// <inheritdoc cref="IHeadersRequestBuilder.WithHeader(string, IStringMatcher[])"/>
public IRequestBuilder WithHeader(string name, params IStringMatcher[] matchers)
{
Check.NotNull(name, nameof(name));
Check.NotNullOrEmpty(matchers, nameof(matchers));
_requestMatchers.Add(new RequestMessageHeaderMatcher(MatchBehaviour.AcceptOnMatch, name, false, matchers));
return this;
}
/// <inheritdoc cref="IHeadersRequestBuilder.WithHeader(string, bool, IStringMatcher[])"/>
public IRequestBuilder WithHeader(string name, bool ignoreCase, params IStringMatcher[] matchers)
{
Check.NotNull(name, nameof(name));
Check.NotNullOrEmpty(matchers, nameof(matchers));
_requestMatchers.Add(new RequestMessageHeaderMatcher(MatchBehaviour.AcceptOnMatch, name, ignoreCase, matchers));
return this;
}
/// <inheritdoc cref="IHeadersRequestBuilder.WithHeader(string, IStringMatcher[])"/>
public IRequestBuilder WithHeader(string name, bool ignoreCase, MatchBehaviour matchBehaviour, params IStringMatcher[] matchers)
{
Check.NotNull(name, nameof(name));
Check.NotNullOrEmpty(matchers, nameof(matchers));
_requestMatchers.Add(new RequestMessageHeaderMatcher(matchBehaviour, name, ignoreCase, matchers));
return this;
}
/// <inheritdoc cref="IHeadersRequestBuilder.WithHeader(Func{IDictionary{string, string[]}, bool}[])"/>
public IRequestBuilder WithHeader(params Func<IDictionary<string, string[]>, bool>[] funcs)
{
Check.NotNullOrEmpty(funcs, nameof(funcs));
_requestMatchers.Add(new RequestMessageHeaderMatcher(funcs));
return this;
}
}
}

View File

@@ -232,81 +232,5 @@ namespace WireMock.RequestBuilders
_requestMatchers.Add(new RequestMessageMethodMatcher(matchBehaviour, methods)); _requestMatchers.Add(new RequestMessageMethodMatcher(matchBehaviour, methods));
return this; return this;
} }
/// <inheritdoc cref="IHeadersAndCookiesRequestBuilder.WithHeader(string, string, MatchBehaviour)"/>
public IRequestBuilder WithHeader(string name, string pattern, MatchBehaviour matchBehaviour)
{
return WithHeader(name, pattern, true, matchBehaviour);
}
/// <inheritdoc cref="IHeadersAndCookiesRequestBuilder.WithHeader(string, string, bool, MatchBehaviour)"/>
public IRequestBuilder WithHeader(string name, string pattern, bool ignoreCase = true, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch)
{
Check.NotNull(name, nameof(name));
Check.NotNull(pattern, nameof(pattern));
_requestMatchers.Add(new RequestMessageHeaderMatcher(matchBehaviour, name, pattern, ignoreCase));
return this;
}
/// <inheritdoc cref="IHeadersAndCookiesRequestBuilder.WithHeader(string, string[], MatchBehaviour)"/>
public IRequestBuilder WithHeader(string name, string[] patterns, MatchBehaviour matchBehaviour)
{
return WithHeader(name, patterns, true, matchBehaviour);
}
/// <inheritdoc cref="IHeadersAndCookiesRequestBuilder.WithHeader(string, string[], bool, MatchBehaviour)"/>
public IRequestBuilder WithHeader(string name, string[] patterns, bool ignoreCase = true, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch)
{
Check.NotNull(name, nameof(name));
Check.NotNull(patterns, nameof(patterns));
_requestMatchers.Add(new RequestMessageHeaderMatcher(matchBehaviour, name, patterns, ignoreCase));
return this;
}
/// <inheritdoc cref="IHeadersAndCookiesRequestBuilder.WithHeader(string, IStringMatcher[])"/>
public IRequestBuilder WithHeader(string name, params IStringMatcher[] matchers)
{
Check.NotNull(name, nameof(name));
Check.NotNullOrEmpty(matchers, nameof(matchers));
_requestMatchers.Add(new RequestMessageHeaderMatcher(name, matchers));
return this;
}
/// <inheritdoc cref="IHeadersAndCookiesRequestBuilder.WithHeader(Func{IDictionary{string, string[]}, bool}[])"/>
public IRequestBuilder WithHeader(params Func<IDictionary<string, string[]>, bool>[] funcs)
{
Check.NotNullOrEmpty(funcs, nameof(funcs));
_requestMatchers.Add(new RequestMessageHeaderMatcher(funcs));
return this;
}
/// <inheritdoc cref="IHeadersAndCookiesRequestBuilder.WithCookie(string, string, bool, MatchBehaviour)"/>
public IRequestBuilder WithCookie(string name, string pattern, bool ignoreCase = true, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch)
{
_requestMatchers.Add(new RequestMessageCookieMatcher(matchBehaviour, name, pattern, ignoreCase));
return this;
}
/// <inheritdoc cref="IHeadersAndCookiesRequestBuilder.WithCookie(string, IStringMatcher[])"/>
public IRequestBuilder WithCookie(string name, params IStringMatcher[] matchers)
{
Check.NotNullOrEmpty(matchers, nameof(matchers));
_requestMatchers.Add(new RequestMessageCookieMatcher(name, matchers));
return this;
}
/// <inheritdoc cref="IHeadersAndCookiesRequestBuilder.WithCookie(Func{IDictionary{string, string}, bool}[])"/>
public IRequestBuilder WithCookie(params Func<IDictionary<string, string>, bool>[] funcs)
{
Check.NotNullOrEmpty(funcs, nameof(funcs));
_requestMatchers.Add(new RequestMessageCookieMatcher(funcs));
return this;
}
} }
} }

View File

@@ -1,12 +1,10 @@
using JetBrains.Annotations;
using Newtonsoft.Json;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Net; using System.Net;
using System.Net.Http;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using JetBrains.Annotations;
using WireMock.Http; using WireMock.Http;
using WireMock.ResponseProviders; using WireMock.ResponseProviders;
using WireMock.Settings; using WireMock.Settings;
@@ -60,7 +58,7 @@ namespace WireMock.ResponseBuilders
[PublicAPI] [PublicAPI]
public static IResponseBuilder Create([CanBeNull] ResponseMessage responseMessage = null) public static IResponseBuilder Create([CanBeNull] ResponseMessage responseMessage = null)
{ {
var message = responseMessage ?? new ResponseMessage { StatusCode = (int)HttpStatusCode.OK }; var message = responseMessage ?? new ResponseMessage(); // { StatusCode = (int)HttpStatusCode.OK };
return new Response(message); return new Response(message);
} }
@@ -341,25 +339,6 @@ namespace WireMock.ResponseBuilders
await Task.Delay(Delay.Value); await Task.Delay(Delay.Value);
} }
if (Callback != null)
{
var callbackResponseMessage = Callback(requestMessage);
if (!WithCallbackUsed)
{
// Copy StatusCode from ResponseMessage
callbackResponseMessage.StatusCode = ResponseMessage.StatusCode;
// Copy Headers from ResponseMessage (if defined)
if (ResponseMessage.Headers != null)
{
callbackResponseMessage.Headers = ResponseMessage.Headers;
}
}
return callbackResponseMessage;
}
if (ProxyUrl != null && _httpClientForProxy != null) if (ProxyUrl != null && _httpClientForProxy != null)
{ {
var requestUri = new Uri(requestMessage.Url); var requestUri = new Uri(requestMessage.Url);
@@ -369,19 +348,41 @@ namespace WireMock.ResponseBuilders
return await HttpClientHelper.SendAsync(_httpClientForProxy, requestMessage, proxyUriWithRequestPathAndQuery.AbsoluteUri); return await HttpClientHelper.SendAsync(_httpClientForProxy, requestMessage, proxyUriWithRequestPathAndQuery.AbsoluteUri);
} }
ResponseMessage responseMessage;
if (Callback == null)
{
responseMessage = ResponseMessage;
}
else
{
responseMessage = Callback(requestMessage);
if (!WithCallbackUsed)
{
// Copy StatusCode from ResponseMessage
responseMessage.StatusCode = ResponseMessage.StatusCode;
// Copy Headers from ResponseMessage (if defined)
if (ResponseMessage.Headers != null)
{
responseMessage.Headers = ResponseMessage.Headers;
}
}
}
if (UseTransformer) if (UseTransformer)
{ {
var factory = new HandlebarsContextFactory(settings.FileSystemHandler, settings.HandlebarsRegistrationCallback); var factory = new HandlebarsContextFactory(settings.FileSystemHandler, settings.HandlebarsRegistrationCallback);
var responseMessageTransformer = new ResponseMessageTransformer(factory); var responseMessageTransformer = new ResponseMessageTransformer(factory);
return responseMessageTransformer.Transform(requestMessage, ResponseMessage, UseTransformerForBodyAsFile); return responseMessageTransformer.Transform(requestMessage, responseMessage, UseTransformerForBodyAsFile);
} }
if (!UseTransformer && ResponseMessage.BodyData?.BodyAsFileIsCached == true) if (!UseTransformer && ResponseMessage.BodyData?.BodyAsFileIsCached == true)
{ {
ResponseMessage.BodyData.BodyAsBytes = settings.FileSystemHandler.ReadResponseBodyAsFile(ResponseMessage.BodyData.BodyAsFile); ResponseMessage.BodyData.BodyAsBytes = settings.FileSystemHandler.ReadResponseBodyAsFile(responseMessage.BodyData.BodyAsFile);
} }
return ResponseMessage; return responseMessage;
} }
} }
} }

View File

@@ -20,7 +20,7 @@ namespace WireMock
/// <summary> /// <summary>
/// Gets or sets the status code. /// Gets or sets the status code.
/// </summary> /// </summary>
public object StatusCode { get; set; } = 200; public object StatusCode { get; set; }
/// <summary> /// <summary>
/// Gets or sets the body. /// Gets or sets the body.

View File

@@ -5,9 +5,8 @@ using WireMock.Matchers.Request;
using WireMock.RequestBuilders; using WireMock.RequestBuilders;
using WireMock.ResponseBuilders; using WireMock.ResponseBuilders;
using WireMock.Settings; using WireMock.Settings;
using WireMock.Util;
using WireMock.Validation;
using WireMock.Types; using WireMock.Types;
using WireMock.Validation;
namespace WireMock.Serialization namespace WireMock.Serialization
{ {
@@ -27,9 +26,9 @@ namespace WireMock.Serialization
var request = (Request)mapping.RequestMatcher; var request = (Request)mapping.RequestMatcher;
var response = (Response)mapping.Provider; var response = (Response)mapping.Provider;
var clientIPMatchers = request.GetRequestMessageMatchers<RequestMessageClientIPMatcher>(); var clientIPMatchers = request.GetRequestMessageMatchers<RequestMessageClientIPMatcher>().Where(m => m.Matchers != null).SelectMany(m => m.Matchers).ToList();
var pathMatchers = request.GetRequestMessageMatchers<RequestMessagePathMatcher>(); var pathMatchers = request.GetRequestMessageMatchers<RequestMessagePathMatcher>().Where(m => m.Matchers != null).SelectMany(m => m.Matchers).ToList();
var urlMatchers = request.GetRequestMessageMatchers<RequestMessageUrlMatcher>(); var urlMatchers = request.GetRequestMessageMatchers<RequestMessageUrlMatcher>().Where(m => m.Matchers != null).SelectMany(m => m.Matchers).ToList();
var headerMatchers = request.GetRequestMessageMatchers<RequestMessageHeaderMatcher>(); var headerMatchers = request.GetRequestMessageMatchers<RequestMessageHeaderMatcher>();
var cookieMatchers = request.GetRequestMessageMatchers<RequestMessageCookieMatcher>(); var cookieMatchers = request.GetRequestMessageMatchers<RequestMessageCookieMatcher>();
var paramsMatchers = request.GetRequestMessageMatchers<RequestMessageParamMatcher>(); var paramsMatchers = request.GetRequestMessageMatchers<RequestMessageParamMatcher>();
@@ -46,36 +45,36 @@ namespace WireMock.Serialization
SetStateTo = mapping.NextState, SetStateTo = mapping.NextState,
Request = new RequestModel Request = new RequestModel
{ {
ClientIP = clientIPMatchers != null && clientIPMatchers.Any() ? new ClientIPModel ClientIP = clientIPMatchers.Any() ? new ClientIPModel
{ {
Matchers = _mapper.Map(clientIPMatchers.Where(m => m.Matchers != null).SelectMany(m => m.Matchers)) Matchers = _mapper.Map(clientIPMatchers)
} : null, } : null,
Path = pathMatchers != null && pathMatchers.Any() ? new PathModel Path = pathMatchers.Any() ? new PathModel
{ {
Matchers = _mapper.Map(pathMatchers.Where(m => m.Matchers != null).SelectMany(m => m.Matchers)) Matchers = _mapper.Map(pathMatchers)
} : null, } : null,
Url = urlMatchers != null && urlMatchers.Any() ? new UrlModel Url = urlMatchers.Any() ? new UrlModel
{ {
Matchers = _mapper.Map(urlMatchers.Where(m => m.Matchers != null).SelectMany(m => m.Matchers)) Matchers = _mapper.Map(urlMatchers)
} : null, } : null,
Methods = methodMatcher?.Methods, Methods = methodMatcher?.Methods,
Headers = headerMatchers != null && headerMatchers.Any() ? headerMatchers.Select(hm => new HeaderModel Headers = headerMatchers.Any() ? headerMatchers.Select(hm => new HeaderModel
{ {
Name = hm.Name, Name = hm.Name,
Matchers = _mapper.Map(hm.Matchers) Matchers = _mapper.Map(hm.Matchers)
}).ToList() : null, }).ToList() : null,
Cookies = cookieMatchers != null && cookieMatchers.Any() ? cookieMatchers.Select(cm => new CookieModel Cookies = cookieMatchers.Any() ? cookieMatchers.Select(cm => new CookieModel
{ {
Name = cm.Name, Name = cm.Name,
Matchers = _mapper.Map(cm.Matchers) Matchers = _mapper.Map(cm.Matchers)
}).ToList() : null, }).ToList() : null,
Params = paramsMatchers != null && paramsMatchers.Any() ? paramsMatchers.Select(pm => new ParamModel Params = paramsMatchers.Any() ? paramsMatchers.Select(pm => new ParamModel
{ {
Name = pm.Key, Name = pm.Key,
IgnoreCase = pm.IgnoreCase == true ? true : (bool?)null, IgnoreCase = pm.IgnoreCase == true ? true : (bool?)null,
@@ -125,11 +124,17 @@ namespace WireMock.Serialization
mappingModel.Response.WebProxy = null; mappingModel.Response.WebProxy = null;
mappingModel.Response.BodyDestination = response.ResponseMessage.BodyDestination; mappingModel.Response.BodyDestination = response.ResponseMessage.BodyDestination;
mappingModel.Response.StatusCode = response.ResponseMessage.StatusCode; mappingModel.Response.StatusCode = response.ResponseMessage.StatusCode;
mappingModel.Response.Headers = MapHeaders(response.ResponseMessage.Headers);
if (response.ResponseMessage.Headers != null && response.ResponseMessage.Headers.Count > 0)
{
mappingModel.Response.Headers = MapHeaders(response.ResponseMessage.Headers);
}
if (response.UseTransformer) if (response.UseTransformer)
{ {
mappingModel.Response.UseTransformer = response.UseTransformer; mappingModel.Response.UseTransformer = response.UseTransformer;
} }
if (response.UseTransformerForBodyAsFile) if (response.UseTransformerForBodyAsFile)
{ {
mappingModel.Response.UseTransformerForBodyAsFile = response.UseTransformerForBodyAsFile; mappingModel.Response.UseTransformerForBodyAsFile = response.UseTransformerForBodyAsFile;
@@ -198,12 +203,6 @@ namespace WireMock.Serialization
private static IDictionary<string, object> MapHeaders(IDictionary<string, WireMockList<string>> dictionary) private static IDictionary<string, object> MapHeaders(IDictionary<string, WireMockList<string>> dictionary)
{ {
var newDictionary = new Dictionary<string, object>(); var newDictionary = new Dictionary<string, object>();
if (dictionary == null || dictionary.Count == 0)
{
return newDictionary;
}
foreach (var entry in dictionary) foreach (var entry in dictionary)
{ {
object value = entry.Value.Count == 1 ? (object)entry.Value.ToString() : entry.Value; object value = entry.Value.Count == 1 ? (object)entry.Value.ToString() : entry.Value;

View File

@@ -5,6 +5,7 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Net;
using System.Net.Http; using System.Net.Http;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
@@ -554,11 +555,63 @@ namespace WireMock.Server
private ResponseMessage MappingsDelete(RequestMessage requestMessage) private ResponseMessage MappingsDelete(RequestMessage requestMessage)
{ {
ResetMappings(); if (!string.IsNullOrEmpty(requestMessage.Body))
{
var deletedGuids = MappingsDeleteMappingFromBody(requestMessage);
if (deletedGuids != null)
{
return ResponseMessageBuilder.Create($"Mappings deleted. Affected GUIDs: [{string.Join(", ", deletedGuids.ToArray())}]");
}
else
{
// return bad request
return ResponseMessageBuilder.Create("Poorly formed mapping JSON.", 400);
}
}
else
{
ResetMappings();
ResetScenarios(); ResetScenarios();
return ResponseMessageBuilder.Create("Mappings deleted"); return ResponseMessageBuilder.Create("Mappings deleted");
}
}
private IEnumerable<Guid> MappingsDeleteMappingFromBody(RequestMessage requestMessage)
{
var deletedGuids = new List<Guid>();
try
{
var mappingModels = DeserializeRequestMessageToArray<MappingModel>(requestMessage);
foreach (var mappingModel in mappingModels)
{
if (mappingModel.Guid.HasValue)
{
if (DeleteMapping(mappingModel.Guid.Value))
{
deletedGuids.Add(mappingModel.Guid.Value);
}
else
{
_settings.Logger.Debug($"Did not find/delete mapping with GUID: {mappingModel.Guid.Value}.");
}
}
}
}
catch (ArgumentException a)
{
_settings.Logger.Error("ArgumentException: {0}", a);
return null;
}
catch (Exception e)
{
_settings.Logger.Error("Exception: {0}", e);
return null;
}
return deletedGuids;
} }
private ResponseMessage MappingsReset(RequestMessage requestMessage) private ResponseMessage MappingsReset(RequestMessage requestMessage)
@@ -744,7 +797,12 @@ namespace WireMock.Server
{ {
foreach (var headerModel in requestModel.Headers.Where(h => h.Matchers != null)) foreach (var headerModel in requestModel.Headers.Where(h => h.Matchers != null))
{ {
requestBuilder = requestBuilder.WithHeader(headerModel.Name, headerModel.Matchers.Select(_matcherMapper.Map).OfType<IStringMatcher>().ToArray()); requestBuilder = requestBuilder.WithHeader(
headerModel.Name,
headerModel.IgnoreCase == true,
headerModel.RejectOnMatch == true ? MatchBehaviour.RejectOnMatch : MatchBehaviour.AcceptOnMatch,
headerModel.Matchers.Select(_matcherMapper.Map).OfType<IStringMatcher>().ToArray()
);
} }
} }
@@ -752,7 +810,11 @@ namespace WireMock.Server
{ {
foreach (var cookieModel in requestModel.Cookies.Where(c => c.Matchers != null)) foreach (var cookieModel in requestModel.Cookies.Where(c => c.Matchers != null))
{ {
requestBuilder = requestBuilder.WithCookie(cookieModel.Name, cookieModel.Matchers.Select(_matcherMapper.Map).OfType<IStringMatcher>().ToArray()); requestBuilder = requestBuilder.WithCookie(
cookieModel.Name,
cookieModel.IgnoreCase == true,
cookieModel.RejectOnMatch == true ? MatchBehaviour.RejectOnMatch : MatchBehaviour.AcceptOnMatch,
cookieModel.Matchers.Select(_matcherMapper.Map).OfType<IStringMatcher>().ToArray());
} }
} }
@@ -808,15 +870,14 @@ namespace WireMock.Server
return responseBuilder.WithProxy(proxyAndRecordSettings); return responseBuilder.WithProxy(proxyAndRecordSettings);
} }
switch (responseModel.StatusCode) if (responseModel.StatusCode is string statusCodeAsString)
{ {
case int statusCodeAsInteger: responseBuilder = responseBuilder.WithStatusCode(statusCodeAsString);
responseBuilder = responseBuilder.WithStatusCode(statusCodeAsInteger); }
break; else if (responseModel.StatusCode != null)
{
case string statusCodeAsString: // Convert to Int32 because Newtonsoft deserializes an 'object' with a number value to a long.
responseBuilder = responseBuilder.WithStatusCode(statusCodeAsString); responseBuilder = responseBuilder.WithStatusCode(Convert.ToInt32(responseModel.StatusCode));
break;
} }
if (responseModel.Headers != null) if (responseModel.Headers != null)
@@ -873,7 +934,7 @@ namespace WireMock.Server
DetectedBodyType = BodyType.String, DetectedBodyType = BodyType.String,
BodyAsString = JsonConvert.SerializeObject(result, keepNullValues ? _settingsIncludeNullValues : _jsonSerializerSettings) BodyAsString = JsonConvert.SerializeObject(result, keepNullValues ? _settingsIncludeNullValues : _jsonSerializerSettings)
}, },
StatusCode = 200, StatusCode = (int)HttpStatusCode.OK,
Headers = new Dictionary<string, WireMockList<string>> { { HttpKnownHeaderNames.ContentType, new WireMockList<string>(ContentTypeJson) } } Headers = new Dictionary<string, WireMockList<string>> { { HttpKnownHeaderNames.ContentType, new WireMockList<string>(ContentTypeJson) } }
}; };
} }

View File

@@ -258,7 +258,13 @@ namespace WireMock.Server
if (settings.AllowBodyForAllHttpMethods == true) if (settings.AllowBodyForAllHttpMethods == true)
{ {
_options.AllowBodyForAllHttpMethods = _settings.AllowBodyForAllHttpMethods; _options.AllowBodyForAllHttpMethods = _settings.AllowBodyForAllHttpMethods;
_settings.Logger.Info("AllowBodyForAllHttpMethods is set to {0}", _settings.AllowBodyForAllHttpMethods == true); _settings.Logger.Info("AllowBodyForAllHttpMethods is set to True");
}
if (settings.AllowAnyHttpStatusCodeInResponse == true)
{
_options.AllowAnyHttpStatusCodeInResponse = _settings.AllowAnyHttpStatusCodeInResponse;
_settings.Logger.Info("AllowAnyHttpStatusCodeInResponse is set to True");
} }
if (settings.AllowPartialMapping == true) if (settings.AllowPartialMapping == true)

View File

@@ -137,5 +137,11 @@ namespace WireMock.Settings
/// </summary> /// </summary>
[PublicAPI] [PublicAPI]
bool? AllowBodyForAllHttpMethods { get; set; } bool? AllowBodyForAllHttpMethods { get; set; }
/// <summary>
/// Allow any HttpStatusCode in the response. Also null, 0, empty or invalid. (default set to false).
/// </summary>
/// [PublicAPI]
bool? AllowAnyHttpStatusCodeInResponse { get; set; }
} }
} }

View File

@@ -101,5 +101,8 @@ namespace WireMock.Settings
/// <inheritdoc cref="IWireMockServerSettings.AllowBodyForAllHttpMethods"/> /// <inheritdoc cref="IWireMockServerSettings.AllowBodyForAllHttpMethods"/>
[PublicAPI] [PublicAPI]
public bool? AllowBodyForAllHttpMethods { get; set; } public bool? AllowBodyForAllHttpMethods { get; set; }
/// <inheritdoc cref="IWireMockServerSettings.AllowAnyHttpStatusCodeInResponse"/>
public bool? AllowAnyHttpStatusCodeInResponse { get; set; }
} }
} }

View File

@@ -34,7 +34,8 @@ namespace WireMock.Settings
MaxRequestLogCount = parser.GetIntValue("MaxRequestLogCount"), MaxRequestLogCount = parser.GetIntValue("MaxRequestLogCount"),
RequestLogExpirationDuration = parser.GetIntValue("RequestLogExpirationDuration"), RequestLogExpirationDuration = parser.GetIntValue("RequestLogExpirationDuration"),
AllowCSharpCodeMatcher = parser.GetBoolValue("AllowCSharpCodeMatcher"), AllowCSharpCodeMatcher = parser.GetBoolValue("AllowCSharpCodeMatcher"),
AllowBodyForAllHttpMethods = parser.GetBoolValue("AllowBodyForAllHttpMethods") AllowBodyForAllHttpMethods = parser.GetBoolValue("AllowBodyForAllHttpMethods"),
AllowAnyHttpStatusCodeInResponse = parser.GetBoolValue("AllowAnyHttpStatusCodeInResponse")
}; };
if (logger != null) if (logger != null)

View File

@@ -17,6 +17,8 @@ namespace WireMock.Transformers
HandleBarsXeger.Register(handlebarsContext); HandleBarsXeger.Register(handlebarsContext);
HandleBarsXPath.Register(handlebarsContext);
HandleBarsFile.Register(handlebarsContext, fileSystemHandler); HandleBarsFile.Register(handlebarsContext, fileSystemHandler);
} }
} }

View File

@@ -0,0 +1,102 @@
using HandlebarsDotNet;
using System;
using System.Text;
using System.Xml;
using System.Xml.XPath;
using WireMock.Validation;
#if !NETSTANDARD1_3
using Wmhelp.XPath2;
#endif
namespace WireMock.Transformers
{
internal static class HandleBarsXPath
{
public static void Register(IHandlebars handlebarsContext)
{
handlebarsContext.RegisterHelper("XPath.SelectSingleNode", (writer, context, arguments) =>
{
(XPathNavigator nav, string xpath) = ParseArguments(arguments);
try
{
#if NETSTANDARD1_3
var result = nav.SelectSingleNode(xpath);
#else
var result = nav.XPath2SelectSingleNode(xpath);
#endif
writer.WriteSafeString(result.OuterXml);
}
catch (Exception)
{
// Ignore Exception
}
});
handlebarsContext.RegisterHelper("XPath.SelectNodes", (writer, context, arguments) =>
{
(XPathNavigator nav, string xpath) = ParseArguments(arguments);
try
{
#if NETSTANDARD1_3
var result = nav.Select(xpath);
#else
var result = nav.XPath2SelectNodes(xpath);
#endif
var resultXml = new StringBuilder();
foreach (XPathNavigator node in result)
{
resultXml.Append(node.OuterXml);
}
writer.WriteSafeString(resultXml);
}
catch (Exception)
{
// Ignore Exception
}
});
handlebarsContext.RegisterHelper("XPath.Evaluate", (writer, context, arguments) =>
{
(XPathNavigator nav, string xpath) = ParseArguments(arguments);
try
{
#if NETSTANDARD1_3
var result = nav.Evaluate(xpath);
#else
var result = nav.XPath2Evaluate(xpath);
#endif
writer.WriteSafeString(result);
}
catch (Exception)
{
// Ignore Exception
}
});
}
private static (XPathNavigator nav, string xpath) ParseArguments(object[] arguments)
{
Check.Condition(arguments, args => args.Length == 2, nameof(arguments));
Check.NotNull(arguments[0], "arguments[0]");
Check.NotNullOrEmpty(arguments[1] as string, "arguments[1]");
XPathNavigator nav;
switch (arguments[0])
{
case string stringValue:
nav = new XmlDocument { InnerXml = stringValue }.CreateNavigator();
break;
default:
throw new NotSupportedException($"The value '{arguments[0]}' with type '{arguments[0]?.GetType()}' cannot be used in Handlebars XPath.");
}
return (nav, (string)arguments[1]);
}
}
}

View File

@@ -34,7 +34,7 @@ namespace WireMock.Util
{ "GET", false }, { "GET", false },
{ "PUT", true }, { "PUT", true },
{ "POST", true }, { "POST", true },
{ "DELETE", false }, { "DELETE", true },
{ "TRACE", false }, { "TRACE", false },
{ "OPTIONS", true }, { "OPTIONS", true },
{ "CONNECT", false }, { "CONNECT", false },

View File

@@ -151,7 +151,7 @@ namespace WireMock.Util
break; break;
case JTokenType.Integer: case JTokenType.Integer:
castText = $"int({path})"; castText = $"long({path})";
break; break;
case JTokenType.Null: case JTokenType.Null:

View File

@@ -0,0 +1,36 @@
using System.IO;
namespace WireMock.Util
{
internal static class PathUtils
{
/// <summary>
/// Robust handling of the user defined path.
/// Also supports Unix and Windows platforms
/// </summary>
/// <param name="path">The path to clean</param>
public static string CleanPath(string path)
{
return path?.Replace('/', Path.DirectorySeparatorChar).Replace('\\', Path.DirectorySeparatorChar);
}
/// <summary>
/// Removes leading directory separator chars from the filepath, which could break Path.Combine
/// </summary>
/// <param name="path">The path to remove the loading DirectorySeparatorChars</param>
public static string RemoveLeadingDirectorySeparators(string path)
{
return path?.TrimStart(new[] { Path.DirectorySeparatorChar });
}
/// <summary>
/// Combine two paths
/// </summary>
/// <param name="root">The root path</param>
/// <param name="path">The path</param>
public static string Combine(string root, string path)
{
return Path.Combine(root, RemoveLeadingDirectorySeparators(path));
}
}
}

View File

@@ -23,10 +23,9 @@
<IncludeSymbols>True</IncludeSymbols>--> <IncludeSymbols>True</IncludeSymbols>-->
<ProjectGuid>{D3804228-91F4-4502-9595-39584E5A01AD}</ProjectGuid> <ProjectGuid>{D3804228-91F4-4502-9595-39584E5A01AD}</ProjectGuid>
<PublishRepositoryUrl>true</PublishRepositoryUrl> <PublishRepositoryUrl>true</PublishRepositoryUrl>
<AllowedOutputExtensionsInPackageBuildOutputFolder>$(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb</AllowedOutputExtensionsInPackageBuildOutputFolder> <!--<AllowedOutputExtensionsInPackageBuildOutputFolder>$(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb</AllowedOutputExtensionsInPackageBuildOutputFolder>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects> <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<GenerateBindingRedirectsOutputType>true</GenerateBindingRedirectsOutputType> <GenerateBindingRedirectsOutputType>true</GenerateBindingRedirectsOutputType>-->
<CodeAnalysisRuleSet>WireMock.Net.ruleset</CodeAnalysisRuleSet>
<SignAssembly>true</SignAssembly> <SignAssembly>true</SignAssembly>
<AssemblyOriginatorKeyFile>WireMock.Net.snk</AssemblyOriginatorKeyFile> <AssemblyOriginatorKeyFile>WireMock.Net.snk</AssemblyOriginatorKeyFile>
<!--<DelaySign>true</DelaySign>--> <!--<DelaySign>true</DelaySign>-->
@@ -41,10 +40,14 @@
<Target Name="CheckIfShouldKillVBCSCompiler" /> <Target Name="CheckIfShouldKillVBCSCompiler" />
<PropertyGroup Condition="'$(Configuration)' == 'Release'"> <PropertyGroup Condition="'$(Configuration)' == 'Release'">
<PathMap>$(MSBuildProjectDirectory)=/</PathMap> <!--<PathMap>$(MSBuildProjectDirectory)=/</PathMap>-->
<GeneratePackageOnBuild>true</GeneratePackageOnBuild> <GeneratePackageOnBuild>true</GeneratePackageOnBuild>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)' == 'Debug - Sonar'">
<CodeAnalysisRuleSet>WireMock.Net.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition="'$(TargetFramework)' == 'netstandard1.3' or '$(TargetFramework)' == 'netstandard2.0'"> <PropertyGroup Condition="'$(TargetFramework)' == 'netstandard1.3' or '$(TargetFramework)' == 'netstandard2.0'">
<DefineConstants>NETSTANDARD;USE_ASPNETCORE</DefineConstants> <DefineConstants>NETSTANDARD;USE_ASPNETCORE</DefineConstants>
</PropertyGroup> </PropertyGroup>
@@ -58,7 +61,6 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Compile Remove="RequestBuilders\Request.WithFault.cs" />
<Compile Remove="Util\CloneUtils.cs" /> <Compile Remove="Util\CloneUtils.cs" />
<Compile Remove="Util\IndexableDictionary.cs" /> <Compile Remove="Util\IndexableDictionary.cs" />
<Compile Remove="Util\NamedReaderWriterLocker.cs" /> <Compile Remove="Util\NamedReaderWriterLocker.cs" />
@@ -78,8 +80,6 @@
<PackageReference Include="System.Linq.Dynamic.Core" Version="1.0.12" /> <PackageReference Include="System.Linq.Dynamic.Core" Version="1.0.12" />
<PackageReference Include="RandomDataGenerator.Net" Version="1.0.10" /> <PackageReference Include="RandomDataGenerator.Net" Version="1.0.10" />
<PackageReference Include="JmesPath.Net" Version="1.0.125" /> <PackageReference Include="JmesPath.Net" Version="1.0.125" />
<!--<PackageReference Include="CloneExtensionsEx" Version="1.0.2" />-->
<!--<PackageReference Include="FastDeepCloner" Version="1.2.5" />-->
</ItemGroup> </ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'net451' "> <ItemGroup Condition=" '$(TargetFramework)' == 'net451' ">

View File

@@ -70,12 +70,13 @@ namespace WireMock.Net.Tests.Matchers
// Assign // Assign
var input = new JObject var input = new JObject
{ {
{ "Id", new JValue(9) }, { "IntegerId", new JValue(9) },
{ "LongId", new JValue(long.MaxValue) },
{ "Name", new JValue("Test") } { "Name", new JValue("Test") }
}; };
// Act // Act
var matcher = new LinqMatcher("Id > 1 AND Name == \"Test\""); var matcher = new LinqMatcher("IntegerId > 1 AND LongId > 1 && Name == \"Test\"");
double match = matcher.IsMatch(input); double match = matcher.IsMatch(input);
// Assert // Assert

View File

@@ -9,6 +9,7 @@ using WireMock.Owin.Mappers;
using WireMock.ResponseBuilders; using WireMock.ResponseBuilders;
using WireMock.Types; using WireMock.Types;
using WireMock.Util; using WireMock.Util;
using WireMock.Owin;
#if NET452 #if NET452
using Microsoft.Owin; using Microsoft.Owin;
using IResponse = Microsoft.Owin.IOwinResponse; using IResponse = Microsoft.Owin.IOwinResponse;
@@ -30,6 +31,7 @@ namespace WireMock.Net.Tests.Owin.Mappers
private readonly Mock<Stream> _stream; private readonly Mock<Stream> _stream;
private readonly Mock<IHeaderDictionary> _headers; private readonly Mock<IHeaderDictionary> _headers;
private readonly Mock<IFileSystemHandler> _fileSystemHandlerMock; private readonly Mock<IFileSystemHandler> _fileSystemHandlerMock;
private readonly Mock<IWireMockMiddlewareOptions> _optionsMock;
public OwinResponseMapperTests() public OwinResponseMapperTests()
{ {
@@ -37,6 +39,13 @@ namespace WireMock.Net.Tests.Owin.Mappers
_stream.SetupAllProperties(); _stream.SetupAllProperties();
_stream.Setup(s => s.WriteAsync(It.IsAny<byte[]>(), It.IsAny<int>(), It.IsAny<int>(), It.IsAny<CancellationToken>())).Returns(CompletedTask); _stream.Setup(s => s.WriteAsync(It.IsAny<byte[]>(), It.IsAny<int>(), It.IsAny<int>(), It.IsAny<CancellationToken>())).Returns(CompletedTask);
_fileSystemHandlerMock = new Mock<IFileSystemHandler>();
_fileSystemHandlerMock.SetupAllProperties();
_optionsMock = new Mock<IWireMockMiddlewareOptions>();
_optionsMock.SetupAllProperties();
_optionsMock.SetupGet(o => o.FileSystemHandler).Returns(_fileSystemHandlerMock.Object);
_headers = new Mock<IHeaderDictionary>(); _headers = new Mock<IHeaderDictionary>();
_headers.SetupAllProperties(); _headers.SetupAllProperties();
#if NET452 #if NET452
@@ -50,10 +59,7 @@ namespace WireMock.Net.Tests.Owin.Mappers
_responseMock.SetupGet(r => r.Body).Returns(_stream.Object); _responseMock.SetupGet(r => r.Body).Returns(_stream.Object);
_responseMock.SetupGet(r => r.Headers).Returns(_headers.Object); _responseMock.SetupGet(r => r.Headers).Returns(_headers.Object);
_fileSystemHandlerMock = new Mock<IFileSystemHandler>(); _sut = new OwinResponseMapper(_optionsMock.Object);
_fileSystemHandlerMock.SetupAllProperties();
_sut = new OwinResponseMapper(_fileSystemHandlerMock.Object);
} }
[Fact] [Fact]
@@ -63,20 +69,78 @@ namespace WireMock.Net.Tests.Owin.Mappers
await _sut.MapAsync(null, _responseMock.Object); await _sut.MapAsync(null, _responseMock.Object);
} }
[Fact] [Theory]
public async Task OwinResponseMapper_MapAsync_StatusCode() [InlineData(0, 200)]
[InlineData(-1, 200)]
[InlineData(10000, 200)]
[InlineData(300, 300)]
public async Task OwinResponseMapper_MapAsync_StatusCode(object code, int expected)
{ {
// Arrange // Arrange
var responseMessage = new ResponseMessage var responseMessage = new ResponseMessage
{ {
StatusCode = 302 StatusCode = code
}; };
// Act // Act
await _sut.MapAsync(responseMessage, _responseMock.Object); await _sut.MapAsync(responseMessage, _responseMock.Object);
// Assert // Assert
_responseMock.VerifySet(r => r.StatusCode = 302, Times.Once); _responseMock.VerifySet(r => r.StatusCode = expected, Times.Once);
}
[Fact]
public async Task OwinResponseMapper_MapAsync_StatusCodeNull()
{
// Arrange
var responseMessage = new ResponseMessage
{
StatusCode = null
};
// Act
await _sut.MapAsync(responseMessage, _responseMock.Object);
// Assert
_responseMock.VerifyNoOtherCalls();
}
[Theory]
[InlineData(0, 0)]
[InlineData(-1, -1)]
[InlineData(10000, 10000)]
[InlineData(300, 300)]
public async Task OwinResponseMapper_MapAsync_StatusCode_WithAllowAll(object code, int expected)
{
// Arrange
_optionsMock.SetupGet(o => o.AllowAnyHttpStatusCodeInResponse).Returns(true);
var responseMessage = new ResponseMessage
{
StatusCode = code
};
// Act
await _sut.MapAsync(responseMessage, _responseMock.Object);
// Assert
_responseMock.VerifySet(r => r.StatusCode = expected, Times.Once);
}
[Fact]
public async Task OwinResponseMapper_MapAsync_StatusCode_WithAllowAll_Null()
{
// Arrange
_optionsMock.SetupGet(o => o.AllowAnyHttpStatusCodeInResponse).Returns(true);
var responseMessage = new ResponseMessage
{
StatusCode = null
};
// Act
await _sut.MapAsync(responseMessage, _responseMock.Object);
// Assert
_responseMock.VerifyNoOtherCalls();
} }
[Fact] [Fact]

View File

@@ -4,9 +4,7 @@ using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using Moq; using Moq;
using Newtonsoft.Json;
using NFluent; using NFluent;
using System.Linq;
using WireMock.Matchers; using WireMock.Matchers;
using WireMock.Matchers.Request; using WireMock.Matchers.Request;
using WireMock.Models; using WireMock.Models;

View File

@@ -14,7 +14,7 @@ namespace WireMock.Net.Tests.RequestMatchers
{ {
// Assign // Assign
var requestMessage = new RequestMessage(new UrlDetails("http://localhost"), "GET", "127.0.0.1"); var requestMessage = new RequestMessage(new UrlDetails("http://localhost"), "GET", "127.0.0.1");
var matcher = new RequestMessageCookieMatcher(MatchBehaviour.AcceptOnMatch, "c", "x"); var matcher = new RequestMessageCookieMatcher(MatchBehaviour.AcceptOnMatch, "c", false, "x");
// Act // Act
var result = new RequestMatchResult(); var result = new RequestMatchResult();
@@ -29,38 +29,7 @@ namespace WireMock.Net.Tests.RequestMatchers
{ {
// Assign // Assign
var requestMessage = new RequestMessage(new UrlDetails("http://localhost"), "GET", "127.0.0.1"); var requestMessage = new RequestMessage(new UrlDetails("http://localhost"), "GET", "127.0.0.1");
var matcher = new RequestMessageCookieMatcher(MatchBehaviour.RejectOnMatch, "c", "x"); var matcher = new RequestMessageCookieMatcher(MatchBehaviour.RejectOnMatch, "c", false, "x");
// Act
var result = new RequestMatchResult();
double score = matcher.GetMatchingScore(requestMessage, result);
// Assert
Check.That(score).IsEqualTo(1.0d);
}
[Fact]
public void RequestMessageCookieMatcher_GetMatchingScore_AcceptOnMatch_CookieDoesNotMatchPattern()
{
// Assign
var cookies = new Dictionary<string, string> { { "c", "x" } };
var requestMessage = new RequestMessage(new UrlDetails("http://localhost"), "GET", "127.0.0.1", null, null, cookies);
var matcher = new RequestMessageCookieMatcher(MatchBehaviour.AcceptOnMatch, "no-match", "123");
// Act
var result = new RequestMatchResult();
double score = matcher.GetMatchingScore(requestMessage, result);
// Assert
Check.That(score).IsEqualTo(0.0d);
}
[Fact]
public void RequestMessageCookieMatcher_GetMatchingScore_RejectOnMatch_CookieDoesNotMatchPattern()
{
// Assign
var cookies = new Dictionary<string, string> { { "h", "x" } };
var requestMessage = new RequestMessage(new UrlDetails("http://localhost"), "GET", "127.0.0.1", null, null, cookies);
var matcher = new RequestMessageCookieMatcher(MatchBehaviour.RejectOnMatch, "no-match", "123");
// Act // Act
var result = new RequestMatchResult(); var result = new RequestMatchResult();
@@ -76,7 +45,7 @@ namespace WireMock.Net.Tests.RequestMatchers
// Assign // Assign
var cookies = new Dictionary<string, string> { { "h", "x" } }; var cookies = new Dictionary<string, string> { { "h", "x" } };
var requestMessage = new RequestMessage(new UrlDetails("http://localhost"), "GET", "127.0.0.1", null, null, cookies); var requestMessage = new RequestMessage(new UrlDetails("http://localhost"), "GET", "127.0.0.1", null, null, cookies);
var matcher = new RequestMessageCookieMatcher(MatchBehaviour.AcceptOnMatch, "h", "x"); var matcher = new RequestMessageCookieMatcher(MatchBehaviour.AcceptOnMatch, "h", false, "x");
// Act // Act
var result = new RequestMatchResult(); var result = new RequestMatchResult();
@@ -92,7 +61,7 @@ namespace WireMock.Net.Tests.RequestMatchers
// Assign // Assign
var cookies = new Dictionary<string, string> { { "h", "x" } }; var cookies = new Dictionary<string, string> { { "h", "x" } };
var requestMessage = new RequestMessage(new UrlDetails("http://localhost"), "GET", "127.0.0.1", null, null, cookies); var requestMessage = new RequestMessage(new UrlDetails("http://localhost"), "GET", "127.0.0.1", null, null, cookies);
var matcher = new RequestMessageCookieMatcher(MatchBehaviour.RejectOnMatch, "h", "x"); var matcher = new RequestMessageCookieMatcher(MatchBehaviour.RejectOnMatch, "h", false, "x");
// Act // Act
var result = new RequestMatchResult(); var result = new RequestMatchResult();
@@ -108,7 +77,23 @@ namespace WireMock.Net.Tests.RequestMatchers
// Assign // Assign
var cookies = new Dictionary<string, string> { { "cook", "x" } }; var cookies = new Dictionary<string, string> { { "cook", "x" } };
var requestMessage = new RequestMessage(new UrlDetails("http://localhost"), "GET", "127.0.0.1", null, null, cookies); var requestMessage = new RequestMessage(new UrlDetails("http://localhost"), "GET", "127.0.0.1", null, null, cookies);
var matcher = new RequestMessageCookieMatcher("cook", new ExactMatcher("x")); var matcher = new RequestMessageCookieMatcher(MatchBehaviour.AcceptOnMatch, "cook", false, new ExactMatcher("x"));
// Act
var result = new RequestMatchResult();
double score = matcher.GetMatchingScore(requestMessage, result);
// Assert
Check.That(score).IsEqualTo(1.0d);
}
[Fact]
public void RequestMessageCookieMatcher_WithMissingCookie_When_RejectOnMatch_Is_True_Should_Match()
{
// Assign
var cookies = new Dictionary<string, string> { { "cook", "x" } };
var requestMessage = new RequestMessage(new UrlDetails("http://localhost"), "GET", "127.0.0.1", null, null, cookies);
var matcher = new RequestMessageCookieMatcher(MatchBehaviour.RejectOnMatch, "uhuh", false, new ExactMatcher("x"));
// Act // Act
var result = new RequestMatchResult(); var result = new RequestMatchResult();

View File

@@ -108,7 +108,7 @@ namespace WireMock.Net.Tests.RequestMatchers
// Assign // Assign
var headers = new Dictionary<string, string[]> { { "h", new[] { "x" } } }; var headers = new Dictionary<string, string[]> { { "h", new[] { "x" } } };
var requestMessage = new RequestMessage(new UrlDetails("http://localhost"), "GET", "127.0.0.1", null, headers); var requestMessage = new RequestMessage(new UrlDetails("http://localhost"), "GET", "127.0.0.1", null, headers);
var matcher = new RequestMessageHeaderMatcher("h", new ExactMatcher("x")); var matcher = new RequestMessageHeaderMatcher(MatchBehaviour.AcceptOnMatch, "h", false, new ExactMatcher("x"));
// Act // Act
var result = new RequestMatchResult(); var result = new RequestMatchResult();

View File

@@ -1,4 +1,6 @@
using FluentAssertions; using FluentAssertions;
using System;
using System.Collections.Generic;
using System.IO; using System.IO;
using System.Net; using System.Net;
using System.Net.Http; using System.Net.Http;
@@ -13,11 +15,10 @@ namespace WireMock.Net.Tests.ResponseBuilders
public class ResponseWithBodyFromFileTests public class ResponseWithBodyFromFileTests
{ {
[Fact] [Fact]
public async Task Response_ProvideResponse_WithBodyFromFile() public async Task Response_ProvideResponse_WithBodyFromFile_AbsolutePath()
{ {
// Arrange // Arrange
var server = WireMockServer.Start(); var server = WireMockServer.Start();
string path = Path.Combine(Directory.GetCurrentDirectory(), "__admin", "mappings", "MyXmlResponse.xml"); string path = Path.Combine(Directory.GetCurrentDirectory(), "__admin", "mappings", "MyXmlResponse.xml");
server server
@@ -36,14 +37,68 @@ namespace WireMock.Net.Tests.ResponseBuilders
); );
// Act // Act
var response1 = await new HttpClient().GetStringAsync("http://localhost:" + server.Ports[0] + "/v1/content"); var response = await new HttpClient().GetStringAsync("http://localhost:" + server.Ports[0] + "/v1/content");
var response2 = await new HttpClient().GetStringAsync("http://localhost:" + server.Ports[0] + "/v1/content");
var response3 = await new HttpClient().GetStringAsync("http://localhost:" + server.Ports[0] + "/v1/content");
// Assert // Assert
response1.Should().Contain("<hello>world</hello>"); response.Should().Contain("<hello>world</hello>");
response2.Should().Contain("<hello>world</hello>"); }
response3.Should().Contain("<hello>world</hello>");
[Fact]
public async Task Response_ProvideResponse_WithBodyFromFile_InSubDirectory()
{
// Arrange
var server = WireMockServer.Start();
string path = @"subdirectory/MyXmlResponse.xml";
server
.Given(
Request
.Create()
.UsingGet()
.WithPath("/v1/content")
)
.RespondWith(
Response
.Create()
.WithStatusCode(HttpStatusCode.OK)
.WithHeader("Content-Type", "application/xml")
.WithBodyFromFile(path)
);
// Act
var response = await new HttpClient().GetStringAsync("http://localhost:" + server.Ports[0] + "/v1/content");
// Assert
response.Should().Contain("<hello>world</hello>");
}
[Fact]
public async Task Response_ProvideResponse_WithBodyFromFile_InAdminMappingFolder()
{
// Arrange
var server = WireMockServer.Start();
string path = @"MyXmlResponse.xml";
server
.Given(
Request
.Create()
.UsingGet()
.WithPath("/v1/content")
)
.RespondWith(
Response
.Create()
.WithStatusCode(HttpStatusCode.OK)
.WithHeader("Content-Type", "application/xml")
.WithBodyFromFile(path)
);
// Act
var response = await new HttpClient().GetStringAsync("http://localhost:" + server.Ports[0] + "/v1/content");
// Assert
response.Should().Contain("<hello>world</hello>");
} }
} }
} }

View File

@@ -1,5 +1,5 @@
using System.Threading.Tasks; using System.Threading.Tasks;
using NFluent; using FluentAssertions;
using WireMock.Models; using WireMock.Models;
using WireMock.ResponseBuilders; using WireMock.ResponseBuilders;
using WireMock.Settings; using WireMock.Settings;
@@ -17,15 +17,49 @@ namespace WireMock.Net.Tests.ResponseBuilders
public async Task Response_WithCallback() public async Task Response_WithCallback()
{ {
// Assign // Assign
var request = new RequestMessage(new UrlDetails("http://localhost/foo"), "GET", "::1"); var requestMessage = new RequestMessage(new UrlDetails("http://localhost/foo"), "GET", "::1");
var response = Response.Create().WithCallback(req => new ResponseMessage { BodyData = new BodyData { DetectedBodyType = BodyType.String, BodyAsString = req.Path + "Bar" }, StatusCode = 302 }); var response = Response.Create()
.WithCallback(request => new ResponseMessage
{
BodyData = new BodyData
{
DetectedBodyType = BodyType.String,
BodyAsString = request.Path + "Bar"
},
StatusCode = 302
});
// Act // Act
var responseMessage = await response.ProvideResponseAsync(request, _settings); var responseMessage = await response.ProvideResponseAsync(requestMessage, _settings);
// Assert // Assert
Check.That(responseMessage.BodyData.BodyAsString).IsEqualTo("/fooBar"); responseMessage.BodyData.BodyAsString.Should().Be("/fooBar");
Check.That(responseMessage.StatusCode).IsEqualTo(302); responseMessage.StatusCode.Should().Be(302);
}
[Fact]
public async Task Response_WithCallback_And_UseTransformer_Is_True()
{
// Assign
var requestMessage = new RequestMessage(new UrlDetails("http://localhost/foo"), "GET", "::1");
var response = Response.Create()
.WithCallback(request => new ResponseMessage
{
BodyData = new BodyData
{
DetectedBodyType = BodyType.String,
BodyAsString = "{{request.Path}}Bar"
},
StatusCode = 302
})
.WithTransformer();
// Act
var responseMessage = await response.ProvideResponseAsync(requestMessage, _settings);
// Assert
responseMessage.BodyData.BodyAsString.Should().Be("/fooBar");
responseMessage.StatusCode.Should().Be(302);
} }
} }
} }

View File

@@ -105,6 +105,53 @@ namespace WireMock.Net.Tests.ResponseBuilders
Check.That(responseMessage.BodyData.BodyAsString).Equals("test keya=1 idx=1 idx=2 keyb=5"); Check.That(responseMessage.BodyData.BodyAsString).Equals("test keya=1 idx=1 idx=2 keyb=5");
} }
[Fact]
public async Task Response_ProvideResponse_Handlebars_StatusCode()
{
// Assign
var body = new BodyData
{
BodyAsString = "abc",
DetectedBodyType = BodyType.String
};
var request = new RequestMessage(new UrlDetails("http://localhost/foo?a=400"), "POST", ClientIp, body);
var response = Response.Create()
.WithStatusCode("{{request.query.a}}")
.WithBody("test")
.WithTransformer();
// Act
var responseMessage = await response.ProvideResponseAsync(request, _settings);
// Assert
Check.That(responseMessage.BodyData.BodyAsString).Equals("test");
Check.That(responseMessage.StatusCode).Equals("400");
}
[Fact]
public async Task Response_ProvideResponse_Handlebars_StatusCodeIsNull()
{
// Assign
var body = new BodyData
{
BodyAsString = "abc",
DetectedBodyType = BodyType.String
};
var request = new RequestMessage(new UrlDetails("http://localhost/foo?a=400"), "POST", ClientIp, body);
var response = Response.Create()
.WithBody("test")
.WithTransformer();
// Act
var responseMessage = await response.ProvideResponseAsync(request, _settings);
// Assert
Check.That(responseMessage.BodyData.BodyAsString).Equals("test");
Check.That(responseMessage.StatusCode).Equals(null);
}
[Fact] [Fact]
public async Task Response_ProvideResponse_Handlebars_Header() public async Task Response_ProvideResponse_Handlebars_Header()
{ {

View File

@@ -0,0 +1,166 @@
using System.Threading.Tasks;
using System.Xml;
using NFluent;
using WireMock.Models;
using WireMock.ResponseBuilders;
using WireMock.Settings;
using WireMock.Types;
using WireMock.Util;
using Xunit;
#if !NETSTANDARD1_3
using Wmhelp.XPath2;
#endif
namespace WireMock.Net.Tests.ResponseBuilders
{
public class ResponseWithHandlebarsXPathTests
{
private readonly WireMockServerSettings _settings = new WireMockServerSettings();
private const string ClientIp = "::1";
[Fact]
public async Task Response_ProvideResponse_Handlebars_XPath_SelectSingleNode_Request_BodyAsString()
{
// Assign
var body = new BodyData
{
BodyAsString = @"<todo-list>
<todo-item id='a1'>abc</todo-item>
<todo-item id='a2'>def</todo-item>
<todo-item id='a3'>xyz</todo-item>
</todo-list>",
DetectedBodyType = BodyType.String
};
var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "POST", ClientIp, body);
var response = Response.Create()
.WithHeader("Content-Type", "application/xml")
.WithBody("<response>{{XPath.SelectSingleNode request.body \"/todo-list/todo-item[1]\"}}</response>")
.WithTransformer();
// Act
var responseMessage = await response.ProvideResponseAsync(request, _settings);
// Assert
var nav = new XmlDocument { InnerXml = responseMessage.BodyData.BodyAsString }.CreateNavigator();
var node = nav.XPath2SelectSingleNode("/response/todo-item");
Check.That(node.Value).Equals("abc");
Check.That(node.GetAttribute("id", "")).Equals("a1");
}
[Fact]
public async Task Response_ProvideResponse_Handlebars_XPath_SelectSingleNode_Text_Request_BodyAsString()
{
// Assign
var body = new BodyData
{
BodyAsString = @"<todo-list>
<todo-item id='a1'>abc</todo-item>
<todo-item id='a2'>def</todo-item>
<todo-item id='a3'>xyz</todo-item>
</todo-list>",
DetectedBodyType = BodyType.String
};
var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "POST", ClientIp, body);
var response = Response.Create()
.WithHeader("Content-Type", "application/xml")
.WithBody("{{XPath.SelectSingleNode request.body \"/todo-list/todo-item[1]/text()\"}}")
.WithTransformer();
// Act
var responseMessage = await response.ProvideResponseAsync(request, _settings);
// Assert
Check.That(responseMessage.BodyData.BodyAsString).IsEqualTo("abc");
}
[Fact]
public async Task Response_ProvideResponse_Handlebars_XPath_SelectNodes_Request_BodyAsString()
{
// Assign
var body = new BodyData
{
BodyAsString = @"<todo-list>
<todo-item id='a1'>abc</todo-item>
<todo-item id='a2'>def</todo-item>
<todo-item id='a3'>xyz</todo-item>
</todo-list>",
DetectedBodyType = BodyType.String
};
var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "POST", ClientIp, body);
var response = Response.Create()
.WithHeader("Content-Type", "application/xml")
.WithBody("<response>{{XPath.SelectNodes request.body \"/todo-list/todo-item\"}}</response>")
.WithTransformer();
// Act
var responseMessage = await response.ProvideResponseAsync(request, _settings);
// Assert
var nav = new XmlDocument { InnerXml = responseMessage.BodyData.BodyAsString }.CreateNavigator();
var nodes = nav.XPath2SelectNodes("/response/todo-item");
Check.That(nodes.Count + 1).IsEqualTo(3);
}
[Fact]
public async Task Response_ProvideResponse_Handlebars_XPath_Evaluate_Request_BodyAsString()
{
// Assign
var body = new BodyData
{
BodyAsString = @"<todo-list>
<todo-item id='a1'>abc</todo-item>
<todo-item id='a2'>def</todo-item>
<todo-item id='a3'>xyz</todo-item>
</todo-list>",
DetectedBodyType = BodyType.String
};
var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "POST", ClientIp, body);
var response = Response.Create()
.WithHeader("Content-Type", "application/xml")
.WithBody("{{XPath.Evaluate request.body \"boolean(/todo-list[count(todo-item) = 3])\"}}")
.WithTransformer();
// Act
var responseMessage = await response.ProvideResponseAsync(request, _settings);
// Assert
Check.That(responseMessage.BodyData.BodyAsString).IsEqualIgnoringCase("True");
}
[Fact]
public async Task Response_ProvideResponse_Handlebars_XPath_Evaluate_Attribute_Request_BodyAsString()
{
// Assign
var body = new BodyData
{
BodyAsString = @"<todo-list>
<todo-item id='a1'>abc</todo-item>
<todo-item id='a2'>def</todo-item>
<todo-item id='a3'>xyz</todo-item>
</todo-list>",
DetectedBodyType = BodyType.String
};
var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "POST", ClientIp, body);
var response = Response.Create()
.WithHeader("Content-Type", "application/xml")
.WithBody("{{XPath.Evaluate request.body \"string(/todo-list/todo-item[1]/@id)\"}}")
.WithTransformer();
// Act
var responseMessage = await response.ProvideResponseAsync(request, _settings);
// Assert
Check.That(responseMessage.BodyData.BodyAsString).IsEqualTo("a1");
}
}
}

View File

@@ -1,6 +1,5 @@
using System; using System;
using FluentAssertions; using FluentAssertions;
using Moq;
using WireMock.RequestBuilders; using WireMock.RequestBuilders;
using WireMock.ResponseBuilders; using WireMock.ResponseBuilders;
using WireMock.Serialization; using WireMock.Serialization;
@@ -36,6 +35,7 @@ namespace WireMock.Net.Tests.Serialization
model.Priority.Should().BeNull(); model.Priority.Should().BeNull();
model.Response.BodyAsJsonIndented.Should().BeNull(); model.Response.BodyAsJsonIndented.Should().BeNull();
model.Response.UseTransformer.Should().BeNull(); model.Response.UseTransformer.Should().BeNull();
model.Response.Headers.Should().BeNull();
} }
[Fact] [Fact]

View File

@@ -148,7 +148,7 @@ Content-Type: text/html
[InlineData("GET", false)] [InlineData("GET", false)]
[InlineData("PUT", true)] [InlineData("PUT", true)]
[InlineData("POST", true)] [InlineData("POST", true)]
[InlineData("DELETE", false)] [InlineData("DELETE", true)]
[InlineData("TRACE", false)] [InlineData("TRACE", false)]
[InlineData("OPTIONS", true)] [InlineData("OPTIONS", true)]
[InlineData("CONNECT", false)] [InlineData("CONNECT", false)]

View File

@@ -52,7 +52,7 @@ namespace WireMock.Net.Tests.Util
{"Flt", new JValue(10.0f)}, {"Flt", new JValue(10.0f)},
{"Dbl", new JValue(Math.PI)}, {"Dbl", new JValue(Math.PI)},
{"Check", new JValue(true)}, {"Check", new JValue(true)},
{"Items", new JArray(new[] {new JValue(4), new JValue(8)})}, {"Items", new JArray(new[] { new JValue(4), new JValue(8) })},
{ {
"Child", new JObject "Child", new JObject
{ {
@@ -61,7 +61,8 @@ namespace WireMock.Net.Tests.Util
{"TS", new JValue(TimeSpan.FromMilliseconds(999))} {"TS", new JValue(TimeSpan.FromMilliseconds(999))}
} }
}, },
{"Id", new JValue(9)}, {"I", new JValue(9)},
{"L", new JValue(long.MaxValue)},
{"Name", new JValue("Test")} {"Name", new JValue("Test")}
}; };
@@ -70,10 +71,10 @@ namespace WireMock.Net.Tests.Util
// Assert // Assert
var queryable = new[] { j }.AsQueryable().Select(line); var queryable = new[] { j }.AsQueryable().Select(line);
bool result = queryable.Any("Id > 4"); bool result = queryable.Any("I > 1 && L > 1");
Check.That(result).IsTrue(); Check.That(result).IsTrue();
Check.That(line).IsEqualTo("new (Uri(U) as U, null as N, Guid(G) as G, double(Flt) as Flt, double(Dbl) as Dbl, bool(Check) as Check, (new [] { int(Items[0]), int(Items[1])}) as Items, new (int(Child.ChildId) as ChildId, DateTime(Child.ChildDateTime) as ChildDateTime, TimeSpan(Child.TS) as TS) as Child, int(Id) as Id, string(Name) as Name)"); Check.That(line).IsEqualTo("new (Uri(U) as U, null as N, Guid(G) as G, double(Flt) as Flt, double(Dbl) as Dbl, bool(Check) as Check, (new [] { long(Items[0]), long(Items[1])}) as Items, new (long(Child.ChildId) as ChildId, DateTime(Child.ChildDateTime) as ChildDateTime, TimeSpan(Child.TS) as TS) as Child, long(I) as I, long(L) as L, string(Name) as Name)");
} }
[Fact] [Fact]
@@ -82,7 +83,7 @@ namespace WireMock.Net.Tests.Util
// Assign // Assign
var j = new JObject var j = new JObject
{ {
{"B", new JValue(new byte[] {48, 49})} { "B", new JValue(new byte[] {48, 49}) }
}; };
// Act and Assert // Act and Assert

View File

@@ -0,0 +1,44 @@
using NFluent;
using System.IO;
using WireMock.Util;
using Xunit;
namespace WireMock.Net.Tests.Util
{
public class PathUtilsTests
{
[Theory]
[InlineData(@"subdirectory/MyXmlResponse.xml")]
[InlineData(@"subdirectory\MyXmlResponse.xml")]
public void PathUtils_CleanPath(string path)
{
// Act
var cleanPath = PathUtils.CleanPath(path);
// Assert
Check.That(cleanPath).Equals("subdirectory" + Path.DirectorySeparatorChar + "MyXmlResponse.xml");
}
[Theory]
[InlineData(null, null)]
[InlineData("", "")]
[InlineData("a", "a")]
[InlineData(@"/", "")]
[InlineData(@"//", "")]
[InlineData(@"//a", "a")]
[InlineData(@"\", "")]
[InlineData(@"\\", "")]
[InlineData(@"\\a", "a")]
public void PathUtils_CleanPath_RemoveLeadingDirectorySeparators(string path, string expected)
{
// Arrange
var cleanPath = PathUtils.CleanPath(path);
// Act
var withoutDirectorySeparators = PathUtils.RemoveLeadingDirectorySeparators(cleanPath);
// Assert
Check.That(withoutDirectorySeparators).Equals(expected);
}
}
}

View File

@@ -66,7 +66,7 @@
<ItemGroup> <ItemGroup>
<None Update="responsebody.json"> <None Update="responsebody.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None> </None>
<None Update="__admin\mappings\00000002-ee28-4f29-ae63-1ac9b0802d86.json"> <None Update="__admin\mappings\00000002-ee28-4f29-ae63-1ac9b0802d86.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
@@ -83,6 +83,9 @@
<None Update="__admin\mappings\MyXmlResponse.xml"> <None Update="__admin\mappings\MyXmlResponse.xml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None> </None>
<None Update="__admin\mappings\subdirectory\MyXmlResponse.xml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View File

@@ -12,6 +12,8 @@ using WireMock.Admin.Settings;
using WireMock.Client; using WireMock.Client;
using WireMock.Handlers; using WireMock.Handlers;
using WireMock.Logging; using WireMock.Logging;
using WireMock.Matchers;
using WireMock.Models;
using WireMock.Server; using WireMock.Server;
using WireMock.Settings; using WireMock.Settings;
using Xunit; using Xunit;
@@ -88,8 +90,13 @@ namespace WireMock.Net.Tests
server.Stop(); server.Stop();
} }
[Fact] [Theory]
public async Task IWireMockAdminApi_PostMappingAsync() [InlineData(null, null)]
[InlineData(-1, -1)]
[InlineData(0, 0)]
[InlineData(200, 200)]
[InlineData("200", "200")]
public async Task IWireMockAdminApi_PostMappingAsync(object statusCode, object expectedStatusCode)
{ {
// Arrange // Arrange
var server = WireMockServer.StartWithAdminInterface(); var server = WireMockServer.StartWithAdminInterface();
@@ -99,7 +106,7 @@ namespace WireMock.Net.Tests
var model = new MappingModel var model = new MappingModel
{ {
Request = new RequestModel { Path = "/1" }, Request = new RequestModel { Path = "/1" },
Response = new ResponseModel { Body = "txt", StatusCode = 200 }, Response = new ResponseModel { Body = "txt", StatusCode = statusCode },
Priority = 500, Priority = 500,
Title = "test" Title = "test"
}; };
@@ -114,6 +121,9 @@ namespace WireMock.Net.Tests
Check.That(mapping).IsNotNull(); Check.That(mapping).IsNotNull();
Check.That(mapping.Title).Equals("test"); Check.That(mapping.Title).Equals("test");
var response = await mapping.ProvideResponseAsync(new RequestMessage(new UrlDetails("http://localhost/1"), "GET", ""));
Check.That(response.StatusCode).Equals(expectedStatusCode);
server.Stop(); server.Stop();
} }

View File

@@ -1,7 +1,10 @@
using System; using System;
using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Net;
using System.Net.Http; using System.Net.Http;
using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using Moq; using Moq;
using Newtonsoft.Json; using Newtonsoft.Json;
@@ -42,7 +45,6 @@ namespace WireMock.Net.Tests
public void WireMockServer_Admin_ResetMappings() public void WireMockServer_Admin_ResetMappings()
{ {
var server = WireMockServer.Start(); var server = WireMockServer.Start();
string folder = Path.Combine(GetCurrentFolder(), "__admin", "mappings"); string folder = Path.Combine(GetCurrentFolder(), "__admin", "mappings");
server.ReadStaticMappings(folder); server.ReadStaticMappings(folder);
@@ -404,5 +406,64 @@ namespace WireMock.Net.Tests
staticMappingHandlerMock.Verify(m => m.FolderExists("folder"), Times.Once); staticMappingHandlerMock.Verify(m => m.FolderExists("folder"), Times.Once);
staticMappingHandlerMock.Verify(m => m.WriteMappingFile(Path.Combine("folder", guid + ".json"), It.IsAny<string>()), Times.Once); staticMappingHandlerMock.Verify(m => m.WriteMappingFile(Path.Combine("folder", guid + ".json"), It.IsAny<string>()), Times.Once);
} }
[Fact]
public async void WireMockServer_Admin_DeleteMappings()
{
// Arrange
var server = WireMockServer.Start(new WireMockServerSettings
{
StartAdminInterface = true,
ReadStaticMappings = false,
WatchStaticMappings = false,
WatchStaticMappingsInSubdirectories = false
});
server
.Given(Request.Create().WithPath("/path1"))
.AtPriority(0)
.RespondWith(Response.Create().WithStatusCode(200));
server
.Given(Request.Create().WithPath("/path2"))
.AtPriority(1)
.RespondWith(Response.Create().WithStatusCode(200));
server
.Given(Request.Create().WithPath("/path3"))
.AtPriority(2)
.RespondWith(Response.Create().WithStatusCode(200));
Check.That(server.MappingModels.Count()).Equals(3);
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();
Check.That(guid3).IsNotNull();
string guidsJsonBody = $"[" +
$"{{\"Guid\": \"{guid1}\"}}," +
$"{{\"Guid\": \"{guid2}\"}}" +
$"]";
// Act
var request = new HttpRequestMessage()
{
Method = HttpMethod.Delete,
RequestUri = new Uri($"http://localhost:{server.Ports[0]}/__admin/mappings"),
Content = new StringContent(guidsJsonBody, Encoding.UTF8, "application/json")
};
var response = await new HttpClient().SendAsync(request);
// Assert
IEnumerable<Guid> guids = server.MappingModels.Select(mapping => mapping.Guid.Value);
Check.That(guids.Contains(guid1.Value)).IsFalse();
Check.That(guids.Contains(guid2.Value)).IsFalse();
Check.That(guids.Contains(guid3.Value)).IsTrue();
Check.That(response.StatusCode).Equals(HttpStatusCode.OK);
Check.That(await response.Content.ReadAsStringAsync()).Equals($"{{\"Status\":\"Mappings deleted. Affected GUIDs: [{guid1}, {guid2}]\"}}");
}
} }
} }

View File

@@ -137,7 +137,25 @@ namespace WireMock.Net.Tests
Check.That(options.AllowBodyForAllHttpMethods).Equals(true); Check.That(options.AllowBodyForAllHttpMethods).Equals(true);
// Verify // Verify
_loggerMock.Verify(l => l.Info(It.IsAny<string>(), It.IsAny<bool>())); _loggerMock.Verify(l => l.Info(It.Is<string>(s => s.Contains("AllowBodyForAllHttpMethods") && s.Contains("True"))));
}
[Fact]
public void WireMockServer_WireMockServerSettings_AllowAnyHttpStatusCodeInResponse()
{
// Assign and Act
var server = WireMockServer.Start(new WireMockServerSettings
{
Logger = _loggerMock.Object,
AllowAnyHttpStatusCodeInResponse = true
});
// Assert
var options = server.GetPrivateFieldValue<IWireMockMiddlewareOptions>("_options");
Check.That(options.AllowAnyHttpStatusCodeInResponse).Equals(true);
// Verify
_loggerMock.Verify(l => l.Info(It.Is<string>(s => s.Contains("AllowAnyHttpStatusCodeInResponse") && s.Contains("True"))));
} }
[Fact] [Fact]

View File

@@ -160,12 +160,10 @@ namespace WireMock.Net.Tests
Check.That(response.Headers.Contains("Transfer-Encoding")).IsFalse(); Check.That(response.Headers.Contains("Transfer-Encoding")).IsFalse();
} }
[Theory]
[InlineData("DELETE")]
#if !NET452 #if !NET452
[Theory]
[InlineData("TRACE")] [InlineData("TRACE")]
[InlineData("GET")] [InlineData("GET")]
#endif
public async Task WireMockServer_Should_exclude_body_for_methods_where_body_is_definitely_disallowed(string method) public async Task WireMockServer_Should_exclude_body_for_methods_where_body_is_definitely_disallowed(string method)
{ {
// Assign // Assign
@@ -189,12 +187,14 @@ namespace WireMock.Net.Tests
// Assert // Assert
Check.That(response.StatusCode).Equals(HttpStatusCode.OK); Check.That(response.StatusCode).Equals(HttpStatusCode.OK);
} }
#endif
[Theory] [Theory]
[InlineData("POST")] [InlineData("POST")]
[InlineData("PUT")] [InlineData("PUT")]
[InlineData("OPTIONS")] [InlineData("OPTIONS")]
[InlineData("REPORT")] [InlineData("REPORT")]
[InlineData("DELETE")]
[InlineData("SOME-UNKNOWN-METHOD")] // default behavior for unknown methods is to allow a body (see BodyParser.ShouldParseBody) [InlineData("SOME-UNKNOWN-METHOD")] // default behavior for unknown methods is to allow a body (see BodyParser.ShouldParseBody)
public async Task WireMockServer_Should_not_exclude_body_for_supported_methods(string method) public async Task WireMockServer_Should_not_exclude_body_for_supported_methods(string method)
{ {

View File

@@ -0,0 +1,3 @@
<xml>
<hello>world</hello>
</xml>