Compare commits

..

41 Commits

Author SHA1 Message Date
Stef Heyenrath
1e968106d1 1.4.26 2021-11-04 07:10:56 +00:00
Daniel L. Romero
49e10ed20f Support basepath from servers (#675)
* Support basepath from servers

* Refactor BasePath

* Comments applied
2021-11-02 15:28:02 +01:00
Daniel L. Romero
c3ec3a66b3 Fix random generate data in url no spaces (#676)
* Fix random generate data in url no spaces

* Format class
2021-11-01 18:53:44 +01:00
Stef Heyenrath
5644491942 1.4.26 2021-10-30 09:26:33 +02:00
Stef Heyenrath
6e5e629525 "RandomDataGenerator.Net" Version="1.0.13" 2021-10-30 09:15:43 +02:00
Daniel L. Romero
77ee123340 Support examples random data generation (#673)
* Add Support Random Generation in Examples, this commit add the bool property DynamicExamples.

* Comments applied

* Remove  '#pragma warning disable 1591'
2021-10-30 09:13:24 +02:00
Daniel L. Romero
ae2a05e86b Improve method MapSchemaToObject to support array and object (#670) 2021-10-28 08:21:30 +02:00
Stef Heyenrath
0e06cf6346 1.4.25 2021-10-27 19:22:46 +02:00
Stef Heyenrath
e9db520cc3 Add TimeSettings (Start, End and TTL) (#661)
* time

* .

* UT

* using JetBrains.Annotations;
2021-10-27 18:57:13 +02:00
Stef Heyenrath
a0e661fae9 Support Schema Example and Support AllOf in definitions (#669)
* Support an Example within a Schema

* Support AllOf in definitions

* Refactor MapSchemaAllOfToObject method and add test files

* Include schema examples

* Refactor duplicate code, create method MapPropertyAsJObject

* Remove commented code

* Merge from master + update WireMock.Net.OpenApiParser.ConsoleApp

Co-authored-by: Daniel <raiga1234@gmail.com>
2021-10-27 09:40:12 +02:00
Stef Heyenrath
25666152bb Add JsonPartialWildcardMatcher (#667)
* JsonPartialWildcardMatcher

* .

* more tests
2021-10-27 08:16:18 +02:00
Stef Heyenrath
6f5eeb5359 Use IWireMockLogger in example 2021-10-26 18:40:34 +02:00
Stef Heyenrath
7ca2095576 Update logging (add version) 2021-10-24 10:44:39 +02:00
Daniel L. Romero
74edad517b Support Array in OpenApi Examples (#664) 2021-10-21 22:12:59 +02:00
Stef Heyenrath
6c65dfcff6 1.4.24 2021-10-20 20:40:02 +02:00
Stef Heyenrath
affe388e30 Add support for AzureAD authentication for REST admin interface (#637) 2021-10-20 16:39:51 +02:00
Stef Heyenrath
48b3e7a305 Add more tests for WithBody (Json and String) and WildcardMatcher 2021-10-19 09:28:52 +00:00
Stef Heyenrath
6194f4e460 Update NotNullOrEmptyMatcher to also implement IStringMatcher (#654)
* Update NotNullOrEmptyMatcher to also implement IStringMatcher

* NotNullOrEmptyMatcher_GetPatterns_Should_Return_EmptyArray

* 24
2021-10-15 12:59:03 +02:00
Stef Heyenrath
57cc616aa3 Implement PatternAsFile for StringMatcher (#651) 2021-10-15 08:54:12 +02:00
Daniel L. Romero
a2a581c84b Refactor method name MapHeaders and httpStatusCode (#649)
* Support edge case: first object, next an array.

* Add mapping to header parameters.

* Refactor the method MapHeadersParameters to MapHeaders

* Refactor method name 'cause is duplicate, only pass httpStatusCode when fail
2021-10-10 19:22:28 +02:00
Stef Heyenrath
e64ed45fcf Fix build from .NET452 and .NET461 example projects 2021-10-09 18:25:18 +02:00
Daniel L. Romero
267f0b7b6d Mapping headers in OpenAPI (#644)
* Support edge case: first object, next an array.

* Add mapping to header parameters.

* Refactor the method MapHeadersParameters to MapHeaders
2021-10-07 19:15:26 +02:00
Daniel L. Romero
34083d826e Support edge case: first object, next an array. (#643) 2021-10-06 17:18:46 +02:00
Stef Heyenrath
72eec7140b WireMock.FluentAssertions 2021-09-29 15:33:06 +00:00
Stef Heyenrath
6fa0f893e7 1.4.23 2021-09-27 21:06:05 +02:00
Stef Heyenrath
2ab075ee09 WireMock.Net.FluentAssertions : upgrade to latest FluentAssertions (#635)
* .

* #634

* fix UT
2021-09-27 21:03:54 +02:00
Stef Heyenrath
772398bea1 1.4.22 2021-09-22 11:39:36 +00:00
Stef Heyenrath
ba0b9d9fd8 Implement Random Delay (#633)
* implement random delays

* fixing CodeFactor issue

* fix code comments

* ...

* UT

Co-authored-by: Michael Yarichuk <michael.yarichuk@gmail.com>
2021-09-22 13:37:41 +02:00
Stef Heyenrath
c67bf75a4b Update FUNDING.yml 2021-09-16 22:25:23 +02:00
Stef Heyenrath
ed74871a26 1.4.21 2021-09-16 13:06:56 +00:00
Stef Heyenrath
cb66c04199 Add WireMock.org RestClient (#631)
* wip...

* x

* .

* .

* .

* r

* 1.4.21-preview-02

* 1.4.21-preview-03

* .

* usings

* wip

* .

* ut

* .

* .

* .

* tests

* .

* comments

* readme
2021-09-16 14:35:08 +02:00
Stef Heyenrath
fd28ebdffa update 'Solution Items' folder 2021-08-14 13:47:18 +02:00
Stef Heyenrath
ce36daa326 Create CreateRelease.yml 2021-08-14 13:45:54 +02:00
Stef Heyenrath
b5a5f5e464 1.4.20 2021-08-06 10:20:28 +00:00
Stef Heyenrath
f5d624eeed Fix issue with FluentBuilder (#628) 2021-08-06 12:17:05 +02:00
Stef Heyenrath
799ea2d219 1.4.19 2021-08-04 14:38:41 +00:00
Stef Heyenrath
0f99e06acc Add NotNullOrEmptyMatcher (#625) 2021-08-04 16:22:22 +02:00
Stef Heyenrath
9d0682bff6 Add FluentBuilder for client models (#622) 2021-08-04 15:40:35 +02:00
Stef Heyenrath
cb1d2a5294 1.4.18 2021-07-10 11:48:54 +02:00
Stef Heyenrath
4b435faf0b Update Handlebars.Net.Helpers.XPath to fix issue with 'xml version' (#619)
Update Handlebars.Net.Helpers.XPath to fix issue with 'xml version'
2021-07-10 11:43:59 +02:00
Stef Heyenrath
5e7cb44525 Update FUNDING.yml 2021-07-07 20:07:40 +02:00
184 changed files with 14488 additions and 2552 deletions

6
.editorconfig Normal file
View File

@@ -0,0 +1,6 @@
[*]
indent_style = space
indent_size = 4
end_of_line = crlf
charset = utf-8
trim_trailing_whitespace = true

2
.github/FUNDING.yml vendored
View File

@@ -1,6 +1,6 @@
# These are supported funding model platforms # These are supported funding model platforms
github: [StefH, WireMock-Net] github: # [StefH]
patreon: # Replace with a single Patreon username patreon: # Replace with a single Patreon username
open_collective: # wiremocknet open_collective: # wiremocknet
ko_fi: # Replace with a single Ko-fi username ko_fi: # Replace with a single Ko-fi username

15
.github/workflows/CreateRelease.yml vendored Normal file
View File

@@ -0,0 +1,15 @@
name: CreateRelease
on:
push:
tags:
- "*.*.*"
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Release
uses: softprops/action-gh-release@v1

File diff suppressed because it is too large Load Diff

View File

@@ -1,30 +1,36 @@
<Project> <Project>
<PropertyGroup> <PropertyGroup>
<MsBuildAllProjects>$(MsBuildAllProjects);$(MsBuildThisFileFullPath)</MsBuildAllProjects> <MsBuildAllProjects>$(MsBuildAllProjects);$(MsBuildThisFileFullPath)</MsBuildAllProjects>
</PropertyGroup> </PropertyGroup>
<PropertyGroup> <PropertyGroup>
<VersionPrefix>1.4.17</VersionPrefix> <VersionPrefix>1.4.26</VersionPrefix>
<PackageReleaseNotes>See CHANGELOG.md</PackageReleaseNotes> <PackageReleaseNotes>See CHANGELOG.md</PackageReleaseNotes>
<PackageIconUrl>https://raw.githubusercontent.com/WireMock-Net/WireMock.Net/master/WireMock.Net-Logo.png</PackageIconUrl> <PackageIcon>WireMock.Net-Logo.png</PackageIcon>
<PackageProjectUrl>https://github.com/WireMock-Net/WireMock.Net</PackageProjectUrl> <PackageProjectUrl>https://github.com/WireMock-Net/WireMock.Net</PackageProjectUrl>
<PackageLicenseExpression>Apache-2.0</PackageLicenseExpression> <PackageLicenseExpression>Apache-2.0</PackageLicenseExpression>
<RepositoryType>git</RepositoryType> <PackageReleaseNotes>$([System.IO.File]::ReadAllText("$(MSBuildProjectDirectory)/../../PackageReleaseNotes.txt"))</PackageReleaseNotes>
<RepositoryUrl>https://github.com/WireMock-Net/WireMock.Net</RepositoryUrl> <RepositoryType>git</RepositoryType>
<ApplicationIcon>../../WireMock.Net-Logo.ico</ApplicationIcon> <RepositoryUrl>https://github.com/WireMock-Net/WireMock.Net</RepositoryUrl>
</PropertyGroup> <ApplicationIcon>../../resources/WireMock.Net-Logo.ico</ApplicationIcon>
</PropertyGroup>
<PropertyGroup Condition="'$(TF_BUILD)' == 'true'"> <PropertyGroup Condition="'$(TF_BUILD)' == 'true'">
<ContinuousIntegrationBuild>true</ContinuousIntegrationBuild> <ContinuousIntegrationBuild>true</ContinuousIntegrationBuild>
</PropertyGroup> </PropertyGroup>
<Choose> <ItemGroup>
<!-- The environment variable `Prerelease` is set in the azure-pipelines.yml file. --> <None Include="../../resources/WireMock.Net-Logo.png" Pack="true" PackagePath="" />
<When Condition=" '$(Prerelease)' != '' "> <!--<None Include="../../PackageReadme.md" Pack="true" PackagePath=""/>-->
<PropertyGroup> </ItemGroup>
<!-- Set the version to x.x.x.x-{Prerelease}-1{Build_BuildId} (this is same buildId as defined in the azure-pipelines.yml file). -->
<VersionSuffix>$(Prerelease)-1$(BUILD_BUILDID)</VersionSuffix> <Choose>
</PropertyGroup> <!-- The environment variable `Prerelease` is set in the azure-pipelines.yml file. -->
</When> <When Condition=" '$(Prerelease)' != '' ">
</Choose> <PropertyGroup>
<!-- Set the version to x.x.x.x-{Prerelease}-1{Build_BuildId} (this is same buildId as defined in the azure-pipelines.yml file). -->
<VersionSuffix>$(Prerelease)-1$(BUILD_BUILDID)</VersionSuffix>
</PropertyGroup>
</When>
</Choose>
</Project> </Project>

View File

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

View File

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

View File

@@ -0,0 +1,6 @@
# {{releaseInfos.0.FriendlyName}} ({{formatDate releaseInfos.0.When "dd MMMM yyyy"}})
{{#each releaseInfos.0.issueInfos}}
- #{{Number}} {{Title}}{{#if Labels}} [{{join Labels ", "}}]{{/if}}
{{/each}}
The full release notes can be found here: https://github.com/WireMock-Net/WireMock.Net/blob/master/CHANGELOG.md

7
PackageReleaseNotes.txt Normal file
View File

@@ -0,0 +1,7 @@
# 1.4.26 (04 November 2021)
- #670 Improve method MapSchemaToObject to support array and object [feature]
- #673 Support examples random data generation
- #675 Support basepath from servers
- #676 Fix random generate data in url no spaces [feature]
The full release notes can be found here: https://github.com/WireMock-Net/WireMock.Net/blob/master/CHANGELOG.md

View File

@@ -34,9 +34,11 @@ For more info, see also this WIKI page: [What is WireMock.Net](https://github.co
| &nbsp;&nbsp;**WireMock.Net** | [![NuGet Badge WireMock.Net](https://buildstats.info/nuget/WireMock.Net)](https://www.nuget.org/packages/WireMock.Net) | [![MyGet Badge WireMock.Net](https://buildstats.info/myget/wiremock-net/WireMock.Net?includePreReleases=true)](https://www.myget.org/feed/wiremock-net/package/nuget/WireMock.Net) | &nbsp;&nbsp;**WireMock.Net** | [![NuGet Badge WireMock.Net](https://buildstats.info/nuget/WireMock.Net)](https://www.nuget.org/packages/WireMock.Net) | [![MyGet Badge WireMock.Net](https://buildstats.info/myget/wiremock-net/WireMock.Net?includePreReleases=true)](https://www.myget.org/feed/wiremock-net/package/nuget/WireMock.Net)
| &nbsp;&nbsp;**WireMock.Net.StandAlone** | [![NuGet Badge WireMock.Net](https://buildstats.info/nuget/WireMock.Net.StandAlone)](https://www.nuget.org/packages/WireMock.Net.StandAlone) | [![MyGet Badge WireMock.Net.StandAlone](https://buildstats.info/myget/wiremock-net/WireMock.Net.StandAlone?includePreReleases=true)](https://www.myget.org/feed/wiremock-net/package/nuget/WireMock.Net.StandAlone) | &nbsp;&nbsp;**WireMock.Net.StandAlone** | [![NuGet Badge WireMock.Net](https://buildstats.info/nuget/WireMock.Net.StandAlone)](https://www.nuget.org/packages/WireMock.Net.StandAlone) | [![MyGet Badge WireMock.Net.StandAlone](https://buildstats.info/myget/wiremock-net/WireMock.Net.StandAlone?includePreReleases=true)](https://www.myget.org/feed/wiremock-net/package/nuget/WireMock.Net.StandAlone)
| &nbsp;&nbsp;**WireMock.Net.FluentAssertions** | [![NuGet Badge WireMock.Net.FluentAssertions](https://buildstats.info/nuget/WireMock.Net.FluentAssertions)](https://www.nuget.org/packages/WireMock.Net.FluentAssertions) | [![MyGet Badge WireMock.Net.FluentAssertions](https://buildstats.info/myget/wiremock-net/WireMock.Net.FluentAssertions?includePreReleases=true)](https://www.myget.org/feed/wiremock-net/package/nuget/WireMock.Net.FluentAssertions) | &nbsp;&nbsp;**WireMock.Net.FluentAssertions** | [![NuGet Badge WireMock.Net.FluentAssertions](https://buildstats.info/nuget/WireMock.Net.FluentAssertions)](https://www.nuget.org/packages/WireMock.Net.FluentAssertions) | [![MyGet Badge WireMock.Net.FluentAssertions](https://buildstats.info/myget/wiremock-net/WireMock.Net.FluentAssertions?includePreReleases=true)](https://www.myget.org/feed/wiremock-net/package/nuget/WireMock.Net.FluentAssertions)
| &nbsp;&nbsp;**WireMock.Net.RestClient** | [![NuGet Badge WireMock.Net.RestClient](https://buildstats.info/nuget/WireMock.Net.RestClient)](https://www.nuget.org/packages/WireMock.Net.RestClient) | [![MyGet Badge WireMock.Net.RestClient](https://buildstats.info/myget/wiremock-net/WireMock.Net.RestClient?includePreReleases=true)](https://www.myget.org/feed/wiremock-net/package/nuget/WireMock.Net.RestClient)
| &nbsp;&nbsp;**WireMock.Net.Matchers.CSharpCode** | [![NuGet Badge WireMock.Net.Matchers.CSharpCode](https://buildstats.info/nuget/WireMock.Net.Matchers.CSharpCode)](https://www.nuget.org/packages/WireMock.Net.Matchers.CSharpCode) | [![MyGet Badge WireMock.Net.Matchers.CSharpCode](https://buildstats.info/myget/wiremock-net/WireMock.Net.Matchers.CSharpCode?includePreReleases=true)](https://www.myget.org/feed/wiremock-net/package/nuget/WireMock.Net.Matchers.CSharpCode) | &nbsp;&nbsp;**WireMock.Net.Matchers.CSharpCode** | [![NuGet Badge WireMock.Net.Matchers.CSharpCode](https://buildstats.info/nuget/WireMock.Net.Matchers.CSharpCode)](https://www.nuget.org/packages/WireMock.Net.Matchers.CSharpCode) | [![MyGet Badge WireMock.Net.Matchers.CSharpCode](https://buildstats.info/myget/wiremock-net/WireMock.Net.Matchers.CSharpCode?includePreReleases=true)](https://www.myget.org/feed/wiremock-net/package/nuget/WireMock.Net.Matchers.CSharpCode)
| &nbsp;&nbsp;**WireMock.Net.OpenApiParser** | [![NuGet Badge WireMock.Net.OpenApiParser](https://buildstats.info/nuget/WireMock.Net.OpenApiParser)](https://www.nuget.org/packages/WireMock.Net.OpenApiParser) | [![MyGet Badge WireMock.Net.OpenApiParser](https://buildstats.info/myget/wiremock-net/WireMock.Net.OpenApiParser?includePreReleases=true)](https://www.myget.org/feed/wiremock-net/package/nuget/WireMock.Net.OpenApiParser) | &nbsp;&nbsp;**WireMock.Net.OpenApiParser** | [![NuGet Badge WireMock.Net.OpenApiParser](https://buildstats.info/nuget/WireMock.Net.OpenApiParser)](https://www.nuget.org/packages/WireMock.Net.OpenApiParser) | [![MyGet Badge WireMock.Net.OpenApiParser](https://buildstats.info/myget/wiremock-net/WireMock.Net.OpenApiParser?includePreReleases=true)](https://www.myget.org/feed/wiremock-net/package/nuget/WireMock.Net.OpenApiParser)
| &nbsp;&nbsp;**WireMock.Net.RestClient** | [![NuGet Badge WireMock.Net.RestClient](https://buildstats.info/nuget/WireMock.Net.RestClient)](https://www.nuget.org/packages/WireMock.Net.RestClient) | [![MyGet Badge WireMock.Net.RestClient](https://buildstats.info/myget/wiremock-net/WireMock.Net.RestClient?includePreReleases=true)](https://www.myget.org/feed/wiremock-net/package/nuget/WireMock.Net.RestClient)
| &nbsp;&nbsp;**WireMock.Org.RestClient** | [![NuGet Badge WireMock.Org.RestClient](https://buildstats.info/nuget/WireMock.Org.RestClient)](https://www.nuget.org/packages/WireMock.Org.RestClient) | [![MyGet Badge WireMock.Org.RestClient](https://buildstats.info/myget/wiremock-net/WireMock.Org.RestClient?includePreReleases=true)](https://www.myget.org/feed/wiremock-net/package/nuget/WireMock.Org.RestClient)
## Development ## Development
For the supported frameworks and build information, see [this](https://github.com/WireMock-Net/WireMock.Net/wiki/Development-Information) page. For the supported frameworks and build information, see [this](https://github.com/WireMock-Net/WireMock.Net/wiki/Development-Information) page.

View File

@@ -1,7 +1,7 @@
Microsoft Visual Studio Solution File, Format Version 12.00 Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16 # Visual Studio Version 17
VisualStudioVersion = 16.0.30114.105 VisualStudioVersion = 17.0.31521.260
MinimumVisualStudioVersion = 10.0.40219.1 MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{8F890C6F-9ACC-438D-928A-AD61CDA862F2}" Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{8F890C6F-9ACC-438D-928A-AD61CDA862F2}"
EndProject EndProject
@@ -21,16 +21,15 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "examples", "examples", "{98
EndProject EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{7EFB2C5B-1BB2-4AAF-BC9F-216ED80C594D}" Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{7EFB2C5B-1BB2-4AAF-BC9F-216ED80C594D}"
ProjectSection(SolutionItems) = preProject ProjectSection(SolutionItems) = preProject
.editorconfig = .editorconfig
.gitignore = .gitignore .gitignore = .gitignore
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-nuget.yml = azure-pipelines-nuget.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
GitHubReleaseNotes.txt = GitHubReleaseNotes.txt Generate-ReleaseNotes.cmd = Generate-ReleaseNotes.cmd
nuget.config = nuget.config nuget.config = nuget.config
PackageReleaseNotes.template = PackageReleaseNotes.template
PackageReleaseNotes.txt = PackageReleaseNotes.txt
README.md = README.md README.md = README.md
EndProjectSection EndProjectSection
EndProject EndProject
@@ -82,6 +81,23 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WireMock.Net.Matchers.CShar
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WireMock.Net.Console.Net472.Classic", "examples\WireMock.Net.Console.Net472.Classic\WireMock.Net.Console.Net472.Classic.csproj", "{6580580B-1EFD-4922-B0EC-FF290DB279EE}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WireMock.Net.Console.Net472.Classic", "examples\WireMock.Net.Console.Net472.Classic\WireMock.Net.Console.Net472.Classic.csproj", "{6580580B-1EFD-4922-B0EC-FF290DB279EE}"
EndProject EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Actions", "Actions", "{1DAEFF47-D117-4E95-8B3E-4F7C8B92011A}"
ProjectSection(SolutionItems) = preProject
.github\workflows\CreateRelease.yml = .github\workflows\CreateRelease.yml
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Azure Pipelines", "Azure Pipelines", "{5B64F6CA-BF6B-4F67-BB2A-9C47E441703E}"
ProjectSection(SolutionItems) = preProject
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-nuget.yml = azure-pipelines-nuget.yml
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WireMock.Org.RestClient", "src\WireMock.Org.RestClient\WireMock.Org.RestClient.csproj", "{08B29DB1-FEFE-408A-AD0A-6BA6DDC8D70F}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WireMock.Org.Abstractions", "src\WireMock.Org.Abstractions\WireMock.Org.Abstractions.csproj", "{3BA5109E-5F30-4CC2-B699-02EC82560AA6}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU Debug|Any CPU = Debug|Any CPU
@@ -204,6 +220,14 @@ Global
{6580580B-1EFD-4922-B0EC-FF290DB279EE}.Debug|Any CPU.Build.0 = Debug|Any CPU {6580580B-1EFD-4922-B0EC-FF290DB279EE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6580580B-1EFD-4922-B0EC-FF290DB279EE}.Release|Any CPU.ActiveCfg = Release|Any CPU {6580580B-1EFD-4922-B0EC-FF290DB279EE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6580580B-1EFD-4922-B0EC-FF290DB279EE}.Release|Any CPU.Build.0 = Release|Any CPU {6580580B-1EFD-4922-B0EC-FF290DB279EE}.Release|Any CPU.Build.0 = Release|Any CPU
{08B29DB1-FEFE-408A-AD0A-6BA6DDC8D70F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{08B29DB1-FEFE-408A-AD0A-6BA6DDC8D70F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{08B29DB1-FEFE-408A-AD0A-6BA6DDC8D70F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{08B29DB1-FEFE-408A-AD0A-6BA6DDC8D70F}.Release|Any CPU.Build.0 = Release|Any CPU
{3BA5109E-5F30-4CC2-B699-02EC82560AA6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3BA5109E-5F30-4CC2-B699-02EC82560AA6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3BA5109E-5F30-4CC2-B699-02EC82560AA6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3BA5109E-5F30-4CC2-B699-02EC82560AA6}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE
@@ -238,6 +262,10 @@ Global
{3F8CF0AE-5F24-4A54-89E7-A3EE829DB5F8} = {985E0ADB-D4B4-473A-AA40-567E279B7946} {3F8CF0AE-5F24-4A54-89E7-A3EE829DB5F8} = {985E0ADB-D4B4-473A-AA40-567E279B7946}
{B6269AAC-170A-4346-8B9A-444DED3D9A44} = {8F890C6F-9ACC-438D-928A-AD61CDA862F2} {B6269AAC-170A-4346-8B9A-444DED3D9A44} = {8F890C6F-9ACC-438D-928A-AD61CDA862F2}
{6580580B-1EFD-4922-B0EC-FF290DB279EE} = {985E0ADB-D4B4-473A-AA40-567E279B7946} {6580580B-1EFD-4922-B0EC-FF290DB279EE} = {985E0ADB-D4B4-473A-AA40-567E279B7946}
{1DAEFF47-D117-4E95-8B3E-4F7C8B92011A} = {7EFB2C5B-1BB2-4AAF-BC9F-216ED80C594D}
{5B64F6CA-BF6B-4F67-BB2A-9C47E441703E} = {7EFB2C5B-1BB2-4AAF-BC9F-216ED80C594D}
{08B29DB1-FEFE-408A-AD0A-6BA6DDC8D70F} = {8F890C6F-9ACC-438D-928A-AD61CDA862F2}
{3BA5109E-5F30-4CC2-B699-02EC82560AA6} = {8F890C6F-9ACC-438D-928A-AD61CDA862F2}
EndGlobalSection EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {DC539027-9852-430C-B19F-FD035D018458} SolutionGuid = {DC539027-9852-430C-B19F-FD035D018458}

View File

@@ -22,6 +22,11 @@ namespace WireMock.Net.Client
var settings1 = await api.GetSettingsAsync(); var settings1 = await api.GetSettingsAsync();
Console.WriteLine($"settings1 = {JsonConvert.SerializeObject(settings1)}"); Console.WriteLine($"settings1 = {JsonConvert.SerializeObject(settings1)}");
var settingsViaBuilder = new FluentBuilder.SettingsModelBuilder()
.WithGlobalProcessingDelay(1077)
.WithoutGlobalProcessingDelay()
.Build();
settings1.GlobalProcessingDelay = 1077; settings1.GlobalProcessingDelay = 1077;
api.PostSettingsAsync(settings1).Wait(); api.PostSettingsAsync(settings1).Wait();

View File

@@ -3,12 +3,12 @@
<PropertyGroup> <PropertyGroup>
<OutputType>Exe</OutputType> <OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.1</TargetFramework> <TargetFramework>netcoreapp2.1</TargetFramework>
<ApplicationIcon>../../WireMock.Net-Logo.ico</ApplicationIcon> <ApplicationIcon>../../resources/WireMock.Net-Logo.ico</ApplicationIcon>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="11.0.2" /> <PackageReference Include="Newtonsoft.Json" Version="11.0.2" />
<PackageReference Include="RestEase" Version="1.4.10" /> <PackageReference Include="RestEase" Version="1.5.5" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View File

@@ -1,9 +1,8 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<OutputType>Exe</OutputType> <OutputType>Exe</OutputType>
<TargetFramework>net5.0</TargetFramework> <TargetFramework>net5.0</TargetFramework>
<ApplicationIcon>../../WireMock.Net-Logo.ico</ApplicationIcon>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@@ -3,7 +3,7 @@
<PropertyGroup> <PropertyGroup>
<OutputType>Exe</OutputType> <OutputType>Exe</OutputType>
<TargetFramework>netcoreapp1.1</TargetFramework> <TargetFramework>netcoreapp1.1</TargetFramework>
<ApplicationIcon>../../WireMock.Net-Logo.ico</ApplicationIcon> <ApplicationIcon>../../resources/WireMock.Net-Logo.ico</ApplicationIcon>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@@ -3,7 +3,7 @@
<PropertyGroup> <PropertyGroup>
<OutputType>Exe</OutputType> <OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.1</TargetFramework> <TargetFramework>netcoreapp2.1</TargetFramework>
<ApplicationIcon>../../WireMock.Net-Logo.ico</ApplicationIcon> <ApplicationIcon>../../resources/WireMock.Net-Logo.ico</ApplicationIcon>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@@ -3,7 +3,7 @@
<PropertyGroup> <PropertyGroup>
<OutputType>Exe</OutputType> <OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework> <TargetFramework>netcoreapp3.1</TargetFramework>
<ApplicationIcon>../../WireMock.Net-Logo.ico</ApplicationIcon> <ApplicationIcon>../../resources/WireMock.Net-Logo.ico</ApplicationIcon>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@@ -1,4 +1,4 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using WireMock.Handlers; using WireMock.Handlers;
@@ -80,6 +80,12 @@ namespace WireMock.Net.ConsoleApplication
return File.ReadAllBytes(AdjustPath(path)); return File.ReadAllBytes(AdjustPath(path));
} }
/// <inheritdoc cref="IFileSystemHandler.ReadFileAsString"/>
public string ReadFileAsString(string path)
{
return File.ReadAllText(path);
}
/// <summary> /// <summary>
/// Adjusts the path to the MappingFolder. /// Adjusts the path to the MappingFolder.
/// </summary> /// </summary>

View File

@@ -1,4 +1,4 @@
using Newtonsoft.Json; using Newtonsoft.Json;
using HandlebarsDotNet; using HandlebarsDotNet;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
@@ -59,7 +59,10 @@ namespace WireMock.Net.ConsoleApplication
//}, //},
PreWireMockMiddlewareInit = app => { System.Console.WriteLine($"PreWireMockMiddlewareInit : {app.GetType()}"); }, PreWireMockMiddlewareInit = app => { System.Console.WriteLine($"PreWireMockMiddlewareInit : {app.GetType()}"); },
PostWireMockMiddlewareInit = app => { System.Console.WriteLine($"PostWireMockMiddlewareInit : {app.GetType()}"); }, PostWireMockMiddlewareInit = app => { System.Console.WriteLine($"PostWireMockMiddlewareInit : {app.GetType()}"); },
#if USE_ASPNETCORE
AdditionalServiceRegistration = services => { System.Console.WriteLine($"AdditionalServiceRegistration : {services.GetType()}"); }, AdditionalServiceRegistration = services => { System.Console.WriteLine($"AdditionalServiceRegistration : {services.GetType()}"); },
#endif
Logger = new WireMockConsoleLogger(), Logger = new WireMockConsoleLogger(),
HandlebarsRegistrationCallback = (handlebarsContext, fileSystemHandler) => HandlebarsRegistrationCallback = (handlebarsContext, fileSystemHandler) =>
@@ -74,9 +77,17 @@ namespace WireMock.Net.ConsoleApplication
System.Console.WriteLine("WireMockServer listening at {0}", string.Join(",", server.Urls)); System.Console.WriteLine("WireMockServer listening at {0}", string.Join(",", server.Urls));
server.SetBasicAuthentication("a", "b"); server.SetBasicAuthentication("a", "b");
//server.SetAzureADAuthentication("6c2a4722-f3b9-4970-b8fc-fac41e29stef", "8587fde1-7824-42c7-8592-faf92b04stef");
// server.AllowPartialMapping(); // server.AllowPartialMapping();
server.Given(Request.Create().WithPath("/mypath").UsingPost())
.RespondWith(Response.Create()
.WithHeader("Content-Type", "application/json")
.WithBodyAsJson("{{JsonPath.SelectToken request.body \"..name\"}}")
.WithTransformer()
);
server server
.Given(Request.Create().WithPath(p => p.Contains("x")).UsingGet()) .Given(Request.Create().WithPath(p => p.Contains("x")).UsingGet())
.AtPriority(4) .AtPriority(4)

View File

@@ -33,9 +33,12 @@
<WarningLevel>4</WarningLevel> <WarningLevel>4</WarningLevel>
</PropertyGroup> </PropertyGroup>
<PropertyGroup> <PropertyGroup>
<ApplicationIcon>..\..\WireMock.Net-Logo.ico</ApplicationIcon> <ApplicationIcon>..\..\resources\WireMock.Net-Logo.ico</ApplicationIcon>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Reference Include="AnyOf, Version=0.2.0.0, Culture=neutral, PublicKeyToken=b35e6abbb527c6b1, processorArchitecture=MSIL">
<HintPath>..\..\packages\AnyOf.0.2.0\lib\net45\AnyOf.dll</HintPath>
</Reference>
<Reference Include="Handlebars, Version=2.0.4.0, Culture=neutral, PublicKeyToken=22225d0bf33cd661, processorArchitecture=MSIL"> <Reference Include="Handlebars, Version=2.0.4.0, Culture=neutral, PublicKeyToken=22225d0bf33cd661, processorArchitecture=MSIL">
<HintPath>..\..\packages\Handlebars.Net.2.0.4\lib\net452\Handlebars.dll</HintPath> <HintPath>..\..\packages\Handlebars.Net.2.0.4\lib\net452\Handlebars.dll</HintPath>
</Reference> </Reference>

View File

@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<packages> <packages>
<package id="AnyOf" version="0.2.0" targetFramework="net452" />
<package id="Handlebars.Net" version="2.0.4" targetFramework="net452" /> <package id="Handlebars.Net" version="2.0.4" targetFramework="net452" />
<package id="Handlebars.Net.Helpers" version="2.1.1-preview-01" targetFramework="net452" /> <package id="Handlebars.Net.Helpers" version="2.1.1-preview-01" targetFramework="net452" />
<package id="Handlebars.Net.Helpers.Core" version="2.1.1-preview-01" targetFramework="net452" /> <package id="Handlebars.Net.Helpers.Core" version="2.1.1-preview-01" targetFramework="net452" />

View File

@@ -35,6 +35,9 @@
<StartupObject>WireMock.Net.ConsoleApplication.Program</StartupObject> <StartupObject>WireMock.Net.ConsoleApplication.Program</StartupObject>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Reference Include="AnyOf, Version=0.2.0.0, Culture=neutral, PublicKeyToken=b35e6abbb527c6b1, processorArchitecture=MSIL">
<HintPath>..\..\packages\AnyOf.0.2.0\lib\net45\AnyOf.dll</HintPath>
</Reference>
<Reference Include="Handlebars, Version=2.0.4.0, Culture=neutral, PublicKeyToken=22225d0bf33cd661, processorArchitecture=MSIL"> <Reference Include="Handlebars, Version=2.0.4.0, Culture=neutral, PublicKeyToken=22225d0bf33cd661, processorArchitecture=MSIL">
<HintPath>..\..\packages\Handlebars.Net.2.0.4\lib\net46\Handlebars.dll</HintPath> <HintPath>..\..\packages\Handlebars.Net.2.0.4\lib\net46\Handlebars.dll</HintPath>
</Reference> </Reference>
@@ -47,6 +50,9 @@
<Reference Include="log4net, Version=2.0.12.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a, processorArchitecture=MSIL"> <Reference Include="log4net, Version=2.0.12.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a, processorArchitecture=MSIL">
<HintPath>..\..\packages\log4net.2.0.12\lib\net45\log4net.dll</HintPath> <HintPath>..\..\packages\log4net.2.0.12\lib\net45\log4net.dll</HintPath>
</Reference> </Reference>
<Reference Include="Microsoft.Extensions.DependencyInjection.Abstractions, Version=2.2.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
<HintPath>..\..\packages\Microsoft.Extensions.DependencyInjection.Abstractions.2.2.0\lib\netstandard2.0\Microsoft.Extensions.DependencyInjection.Abstractions.dll</HintPath>
</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>

View File

@@ -1,9 +1,11 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<packages> <packages>
<package id="AnyOf" version="0.2.0" targetFramework="net461" />
<package id="Handlebars.Net" version="2.0.4" targetFramework="net461" /> <package id="Handlebars.Net" version="2.0.4" targetFramework="net461" />
<package id="Handlebars.Net.Helpers" version="2.1.1-preview-01" targetFramework="net461" /> <package id="Handlebars.Net.Helpers" version="2.1.1-preview-01" targetFramework="net461" />
<package id="Handlebars.Net.Helpers.Core" version="2.1.1-preview-01" targetFramework="net461" /> <package id="Handlebars.Net.Helpers.Core" version="2.1.1-preview-01" targetFramework="net461" />
<package id="log4net" version="2.0.12" targetFramework="net461" /> <package id="log4net" version="2.0.12" targetFramework="net461" />
<package id="Microsoft.Extensions.DependencyInjection.Abstractions" version="2.2.0" targetFramework="net461" />
<package id="Newtonsoft.Json" version="11.0.2" targetFramework="net461" /> <package id="Newtonsoft.Json" version="11.0.2" targetFramework="net461" />
<package id="SimMetrics.Net" version="1.0.5" targetFramework="net461" /> <package id="SimMetrics.Net" version="1.0.5" targetFramework="net461" />
<package id="System.ValueTuple" version="4.3.0" targetFramework="net461" /> <package id="System.ValueTuple" version="4.3.0" targetFramework="net461" />

View File

@@ -39,6 +39,9 @@
<StartupObject>WireMock.Net.ConsoleApplication.Program</StartupObject> <StartupObject>WireMock.Net.ConsoleApplication.Program</StartupObject>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Reference Include="AnyOf, Version=0.2.0.0, Culture=neutral, PublicKeyToken=b35e6abbb527c6b1, processorArchitecture=MSIL">
<HintPath>..\..\packages\AnyOf.0.2.0\lib\net45\AnyOf.dll</HintPath>
</Reference>
<Reference Include="Fare, Version=2.1.0.0, Culture=neutral, PublicKeyToken=ea68d375bf33a7c8, processorArchitecture=MSIL"> <Reference Include="Fare, Version=2.1.0.0, Culture=neutral, PublicKeyToken=ea68d375bf33a7c8, processorArchitecture=MSIL">
<HintPath>..\..\packages\Fare.2.1.1\lib\net35\Fare.dll</HintPath> <HintPath>..\..\packages\Fare.2.1.1\lib\net35\Fare.dll</HintPath>
</Reference> </Reference>

View File

@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<packages> <packages>
<package id="AnyOf" version="0.2.0" targetFramework="net472" />
<package id="Fare" version="2.1.1" targetFramework="net472" /> <package id="Fare" version="2.1.1" targetFramework="net472" />
<package id="Handlebars.Net" version="2.0.4" targetFramework="net472" /> <package id="Handlebars.Net" version="2.0.4" targetFramework="net472" />
<package id="Handlebars.Net.Helpers" version="2.1.1-preview-01" targetFramework="net472" /> <package id="Handlebars.Net.Helpers" version="2.1.1-preview-01" targetFramework="net472" />

View File

@@ -3,7 +3,7 @@
<PropertyGroup> <PropertyGroup>
<OutputType>Exe</OutputType> <OutputType>Exe</OutputType>
<TargetFrameworks>netcoreapp2.1;netcoreapp3.1;net5.0</TargetFrameworks> <TargetFrameworks>netcoreapp2.1;netcoreapp3.1;net5.0</TargetFrameworks>
<ApplicationIcon>../../WireMock.Net-Logo.ico</ApplicationIcon> <ApplicationIcon>../../resources/WireMock.Net-Logo.ico</ApplicationIcon>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@@ -3,7 +3,7 @@
<PropertyGroup> <PropertyGroup>
<OutputType>Exe</OutputType> <OutputType>Exe</OutputType>
<TargetFramework>net5.0</TargetFramework> <TargetFramework>net5.0</TargetFramework>
<ApplicationIcon>../../WireMock.Net-Logo.ico</ApplicationIcon> <ApplicationIcon>../../resources/WireMock.Net-Logo.ico</ApplicationIcon>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@@ -0,0 +1,269 @@
{
"swagger": "2.0",
"info": {
"version": "1.0.0",
"title": "Swagger Petstore",
"description": "A sample API that uses a petstore as an example to demonstrate features in the swagger-2.0 specification",
"termsOfService": "http://swagger.io/terms/",
"contact": {
"name": "Swagger API Team"
},
"license": {
"name": "MIT"
}
},
"host": "petstore.swagger.io",
"basePath": "/api",
"schemes": [
"http"
],
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"paths": {
"/pets": {
"get": {
"description": "Returns all pets from the system that the user has access to",
"operationId": "findPets",
"produces": [
"application/json",
"application/xml",
"text/xml",
"text/html"
],
"parameters": [{
"name": "tags",
"in": "query",
"description": "tags to filter by",
"required": false,
"type": "array",
"items": {
"type": "string"
},
"collectionFormat": "csv"
},
{
"name": "limit",
"in": "query",
"description": "maximum number of results to return",
"required": false,
"type": "integer",
"format": "int32"
}
],
"responses": {
"200": {
"description": "pet response",
"schema": {
"example": [{
"name": "MEXAMPLE",
"tag": "MEXAMPLE",
"id": 9988
}, {
"name": "OtherExample",
"tag": "OtherExample",
"id": 8877
}],
"type": "array",
"items": {
"$ref": "#/definitions/Pet"
}
}
},
"default": {
"description": "unexpected error",
"schema": {
"$ref": "#/definitions/ErrorModel"
}
}
}
},
"post": {
"description": "Creates a new pet in the store. Duplicates are allowed",
"operationId": "addPet",
"produces": [
"application/json"
],
"parameters": [{
"name": "pet",
"in": "body",
"description": "Pet to add to the store",
"required": true,
"schema": {
"$ref": "#/definitions/NewPet"
}
}],
"responses": {
"200": {
"description": "pet response",
"schema": {
"$ref": "#/definitions/Pet"
}
},
"default": {
"description": "unexpected error",
"schema": {
"$ref": "#/definitions/ErrorModel"
}
}
}
}
},
"/pet": {
"get": {
"description": "Returns a pet from the system that the user has access to",
"operationId": "findPet",
"produces": [
"application/json",
"application/xml",
"text/xml",
"text/html"
],
"parameters": [{
"name": "tags",
"in": "query",
"description": "tags to filter by",
"required": false,
"type": "array",
"items": {
"type": "string"
},
"collectionFormat": "csv"
},
{
"name": "limit",
"in": "query",
"description": "maximum number of results to return",
"required": false,
"type": "integer",
"format": "int32"
}
],
"responses": {
"200": {
"description": "pet response",
"schema": {
"$ref": "#/definitions/Pet"
}
},
"default": {
"description": "unexpected error",
"schema": {
"$ref": "#/definitions/ErrorModel"
}
}
}
}
},
"/pets/{id}": {
"get": {
"description": "Returns a user based on a single ID, if the user does not have access to the pet",
"operationId": "findPetById",
"produces": [
"application/json",
"application/xml",
"text/xml",
"text/html"
],
"parameters": [{
"name": "id",
"in": "path",
"description": "ID of pet to fetch",
"required": true,
"type": "integer",
"format": "int64"
}],
"responses": {
"200": {
"description": "pet response",
"schema": {
"$ref": "#/definitions/Pet"
}
},
"default": {
"description": "unexpected error",
"schema": {
"$ref": "#/definitions/ErrorModel"
}
}
}
},
"delete": {
"description": "deletes a single pet based on the ID supplied",
"operationId": "deletePet",
"parameters": [{
"name": "id",
"in": "path",
"description": "ID of pet to delete",
"required": true,
"type": "integer",
"format": "int64"
}],
"responses": {
"204": {
"description": "pet deleted"
},
"default": {
"description": "unexpected error",
"schema": {
"$ref": "#/definitions/ErrorModel"
}
}
}
}
}
},
"definitions": {
"Pet": {
"type": "object",
"allOf": [{
"$ref": "#/definitions/NewPet"
},
{
"required": [
"id"
],
"properties": {
"id": {
"type": "integer",
"format": "int64"
}
}
}
]
},
"NewPet": {
"type": "object",
"required": [
"name"
],
"properties": {
"name": {
"type": "string"
},
"tag": {
"type": "string"
}
}
},
"ErrorModel": {
"type": "object",
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "integer",
"format": "int32"
},
"message": {
"type": "string"
}
}
}
}
}

View File

@@ -0,0 +1,732 @@
swagger: '2.0'
info:
description: 'This is a sample server Petstore server. Copied from https://github.com/swagger-api/swagger-codegen/blob/master/modules/swagger-codegen/src/test/resources/2_0/petstore.yaml.'
version: 1.0.0
title: Swagger Petstore
termsOfService: 'http://swagger.io/terms/'
contact:
email: apiteam@swagger.io
license:
name: Apache-2.0
url: 'http://www.apache.org/licenses/LICENSE-2.0.html'
host: petstore.swagger.io
basePath: /v2
tags:
- name: pet
description: Everything about your Pets
externalDocs:
description: Find out more
url: 'http://swagger.io'
- name: store
description: Access to Petstore orders
- name: user
description: Operations about user
externalDocs:
description: Find out more about our store
url: 'http://swagger.io'
schemes:
- http
paths:
/pet:
post:
tags:
- pet
summary: Add a new pet to the store
description: ''
operationId: addPet
consumes:
- application/json
- application/xml
produces:
- application/xml
- application/json
parameters:
- in: body
name: body
description: Pet object that needs to be added to the store
required: true
schema:
$ref: '#/definitions/Pet'
responses:
'405':
description: Invalid input
security:
- petstore_auth:
- 'write:pets'
- 'read:pets'
put:
tags:
- pet
summary: Update an existing pet
description: ''
operationId: updatePet
consumes:
- application/json
- application/xml
produces:
- application/xml
- application/json
parameters:
- in: body
name: body
description: Pet object that needs to be added to the store
required: true
schema:
$ref: '#/definitions/Pet'
responses:
'400':
description: Invalid ID supplied
'404':
description: Pet not found
'405':
description: Validation exception
security:
- petstore_auth:
- 'write:pets'
- 'read:pets'
/pet/findByStatus:
get:
tags:
- pet
summary: Finds Pets by status
description: Multiple status values can be provided with comma separated strings
operationId: findPetsByStatus
produces:
- application/xml
- application/json
parameters:
- name: status
in: query
description: Status values that need to be considered for filter
required: true
type: array
items:
type: string
enum:
- available
- pending
- sold
default: available
collectionFormat: csv
responses:
'200':
description: successful operation
schema:
type: array
items:
$ref: '#/definitions/Pet'
'400':
description: Invalid status value
security:
- petstore_auth:
- 'write:pets'
- 'read:pets'
/pet/findByTags:
get:
tags:
- pet
summary: Finds Pets by tags
description: 'Multiple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing.'
operationId: findPetsByTags
produces:
- application/xml
- application/json
parameters:
- name: tags
in: query
description: Tags to filter by
required: true
type: array
items:
type: string
collectionFormat: csv
responses:
'200':
description: successful operation
schema:
type: array
items:
$ref: '#/definitions/Pet'
'400':
description: Invalid tag value
security:
- petstore_auth:
- 'write:pets'
- 'read:pets'
deprecated: true
'/pet/{petId}':
get:
tags:
- pet
summary: Find pet by ID
description: Returns a single pet
operationId: getPetById
produces:
- application/xml
- application/json
parameters:
- name: petId
in: path
description: ID of pet to return
required: true
type: integer
format: int64
responses:
'200':
description: successful operation
schema:
$ref: '#/definitions/Pet'
'400':
description: Invalid ID supplied
'404':
description: Pet not found
security:
- api_key: []
post:
tags:
- pet
summary: Updates a pet in the store with form data
description: ''
operationId: updatePetWithForm
consumes:
- application/x-www-form-urlencoded
produces:
- application/xml
- application/json
parameters:
- name: petId
in: path
description: ID of pet that needs to be updated
required: true
type: integer
format: int64
- name: name
in: formData
description: Updated name of the pet
required: false
type: string
- name: status
in: formData
description: Updated status of the pet
required: false
type: string
responses:
'405':
description: Invalid input
security:
- petstore_auth:
- 'write:pets'
- 'read:pets'
delete:
tags:
- pet
summary: Deletes a pet
description: ''
operationId: deletePet
produces:
- application/xml
- application/json
parameters:
- name: api_key
in: header
required: false
type: string
- name: petId
in: path
description: Pet id to delete
required: true
type: integer
format: int64
responses:
'200':
description: successful operation
'400':
description: Invalid pet value
security:
- petstore_auth:
- 'write:pets'
- 'read:pets'
'/pet/{petId}/uploadImage':
post:
tags:
- pet
summary: uploads an image
description: ''
operationId: uploadFile
consumes:
- multipart/form-data
produces:
- application/json
parameters:
- name: petId
in: path
description: ID of pet to update
required: true
type: integer
format: int64
- name: additionalMetadata
in: formData
description: Additional data to pass to server
required: false
type: string
- name: file
in: formData
description: file to upload
required: false
type: file
responses:
'200':
description: successful operation
schema:
$ref: '#/definitions/ApiResponse'
security:
- petstore_auth:
- 'write:pets'
- 'read:pets'
/store/inventory:
get:
tags:
- store
summary: Returns pet inventories by status
description: Returns a map of status codes to quantities
operationId: getInventory
produces:
- application/json
parameters: []
responses:
'200':
description: successful operation
schema:
type: object
additionalProperties:
type: integer
format: int32
security:
- api_key: []
/store/order:
post:
tags:
- store
summary: Place an order for a pet
description: ''
operationId: placeOrder
produces:
- application/xml
- application/json
parameters:
- in: body
name: body
description: order placed for purchasing the pet
required: true
schema:
$ref: '#/definitions/Order'
responses:
'200':
description: successful operation
schema:
$ref: '#/definitions/Order'
'400':
description: Invalid Order
'/store/order/{orderId}':
get:
tags:
- store
summary: Find purchase order by ID
description: 'For valid response try integer IDs with value <= 5 or > 10. Other values will generated exceptions'
operationId: getOrderById
produces:
- application/xml
- application/json
parameters:
- name: orderId
in: path
description: ID of pet that needs to be fetched
required: true
type: integer
maximum: 5
minimum: 1
format: int64
responses:
'200':
description: successful operation
schema:
$ref: '#/definitions/Order'
'400':
description: Invalid ID supplied
'404':
description: Order not found
delete:
tags:
- store
summary: Delete purchase order by ID
description: For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers will generate API errors
operationId: deleteOrder
produces:
- application/xml
- application/json
parameters:
- name: orderId
in: path
description: ID of the order that needs to be deleted
required: true
type: string
responses:
'400':
description: Invalid ID supplied
'404':
description: Order not found
/user:
post:
tags:
- user
summary: Create user
description: This can only be done by the logged in user.
operationId: createUser
produces:
- application/xml
- application/json
parameters:
- in: body
name: body
description: Created user object
required: true
schema:
$ref: '#/definitions/User'
responses:
default:
description: successful operation
/user/createWithArray:
post:
tags:
- user
summary: Creates list of users with given input array
description: ''
operationId: createUsersWithArrayInput
produces:
- application/xml
- application/json
parameters:
- in: body
name: body
description: List of user object
required: true
schema:
type: array
items:
$ref: '#/definitions/User'
responses:
default:
description: successful operation
/user/createWithList:
post:
tags:
- user
summary: Creates list of users with given input array
description: ''
operationId: createUsersWithListInput
produces:
- application/xml
- application/json
parameters:
- in: body
name: body
description: List of user object
required: true
schema:
type: array
items:
$ref: '#/definitions/User'
responses:
default:
description: successful operation
/user/login:
get:
tags:
- user
summary: Logs user into the system
description: ''
operationId: loginUser
produces:
- application/xml
- application/json
parameters:
- name: username
in: query
description: The user name for login
required: true
type: string
- name: password
in: query
description: The password for login in clear text
required: true
type: string
responses:
'200':
description: successful operation
schema:
type: string
headers:
X-Rate-Limit:
type: integer
format: int32
description: calls per hour allowed by the user
X-Expires-After:
type: string
format: date-time
description: date in UTC when toekn expires
'400':
description: Invalid username/password supplied
/user/logout:
get:
tags:
- user
summary: Logs out current logged in user session
description: ''
operationId: logoutUser
produces:
- application/xml
- application/json
parameters: []
responses:
default:
description: successful operation
'/user/{username}':
get:
tags:
- user
summary: Get user by user name
description: ''
operationId: getUserByName
produces:
- application/xml
- application/json
parameters:
- name: username
in: path
description: 'The name that needs to be fetched. Use user1 for testing.'
required: true
type: string
responses:
'200':
description: successful operation
schema:
$ref: '#/definitions/User'
'400':
description: Invalid username supplied
'404':
description: User not found
put:
tags:
- user
summary: Updated user
description: This can only be done by the logged in user.
operationId: updateUser
produces:
- application/xml
- application/json
parameters:
- name: username
in: path
description: name that need to be deleted
required: true
type: string
- in: body
name: body
description: Updated user object
required: true
schema:
$ref: '#/definitions/User'
responses:
'400':
description: Invalid user supplied
'404':
description: User not found
delete:
tags:
- user
summary: Delete user
description: This can only be done by the logged in user.
operationId: deleteUser
produces:
- application/xml
- application/json
parameters:
- name: username
in: path
description: The name that needs to be deleted
required: true
type: string
responses:
'400':
description: Invalid username supplied
'404':
description: User not found
securityDefinitions:
petstore_auth:
type: oauth2
authorizationUrl: 'http://petstore.swagger.io/api/oauth/dialog'
flow: implicit
scopes:
'write:pets': modify pets in your account
'read:pets': read your pets
api_key:
type: apiKey
name: api_key
in: header
definitions:
Order:
title: Pet Order
description: An order for a pets from the pet store
type: object
properties:
id:
type: integer
format: int64
petId:
type: integer
format: int64
quantity:
type: integer
format: int32
shipDate:
type: string
format: date-time
status:
type: string
description: Order Status
enum:
- placed
- approved
- delivered
complete:
type: boolean
default: false
xml:
name: Order
Category:
title: Pet category
description: A category for a pet
type: object
properties:
id:
type: integer
format: int64
name:
type: string
xml:
name: Category
User:
title: a User
description: A User who is purchasing from the pet store
type: object
properties:
id:
type: integer
format: int64
username:
type: string
firstName:
type: string
lastName:
type: string
email:
type: string
password:
type: string
phone:
type: string
userStatus:
type: integer
format: int32
description: User Status
xml:
name: User
Tag:
title: Pet Tag
description: A tag for a pet
type: object
properties:
id:
type: integer
format: int64
name:
type: string
xml:
name: Tag
Pet:
title: a Pet
description: A pet for sale in the pet store
type: object
required:
- name
- photoUrls
properties:
id:
type: integer
format: int64
category:
$ref: '#/definitions/Category'
name:
type: string
example: doggie
photoUrls:
type: array
xml:
name: photoUrl
wrapped: true
items:
type: string
tags:
type: array
xml:
name: tag
wrapped: true
items:
$ref: '#/definitions/Tag'
status:
type: string
description: pet status in the store
enum:
- available
- pending
- sold
xml:
name: Pet
ApiResponse:
title: An uploaded response
description: Describes the result of uploading an image resource
type: object
properties:
code:
type: integer
format: int32
type:
type: string
message:
type: string
#issue: https://github.com/swagger-api/swagger-codegen/issues/7980
Amount:
type: object
description: >
some description
properties:
value:
format: double
type: number
minimum: 0.01
maximum: 1000000000000000
description: >
some description
currency:
$ref: '#/definitions/Currency'
required:
- value
- currency
Currency:
type: string
pattern: '^[A-Z]{3,3}$'
description: >
some description
externalDocs:
description: Find out more about Swagger
url: 'http://swagger.io'

View File

@@ -0,0 +1,109 @@
openapi: "3.0.0"
info:
version: 1.0.0
title: Swagger Petstore
license:
name: MIT
servers:
- url: http://petstore.swagger.io/v1
paths:
/pets:
get:
summary: List all pets
operationId: listPets
tags:
- pets
parameters:
- name: limit
in: query
description: How many items to return at one time (max 100)
required: false
schema:
type: integer
format: int32
responses:
200:
description: An paged array of pets
headers:
x-next:
description: A link to the next page of responses
schema:
type: string
content:
application/json:
schema:
$ref: "#/components/schemas/Pets"
default:
description: unexpected error
content:
application/json:
schema:
$ref: "#/components/schemas/Error"
post:
summary: Create a pet
operationId: createPets
tags:
- pets
responses:
201:
description: Null response
default:
description: unexpected error
content:
application/json:
schema:
$ref: "#/components/schemas/Error"
/pets/{petId}:
get:
summary: Info for a specific pet
operationId: showPetById
tags:
- pets
parameters:
- name: petId
in: path
required: true
description: The id of the pet to retrieve
schema:
type: string
responses:
200:
description: Expected response to a valid request
content:
application/json:
schema:
$ref: "#/components/schemas/Pets"
default:
description: unexpected error
content:
application/json:
schema:
$ref: "#/components/schemas/Error"
components:
schemas:
Pet:
required:
- id
- name
properties:
id:
type: integer
format: int64
name:
type: string
tag:
type: string
Pets:
type: array
items:
$ref: "#/components/schemas/Pet"
Error:
required:
- code
- message
properties:
code:
type: integer
format: int32
message:
type: string

View File

@@ -0,0 +1,96 @@
openapi: 3.0.1
info:
title: API_Test
version: v1
paths:
/WeatherForecast:
get:
tags:
- WeatherForecast
parameters:
- in: "header"
name: X-Correlation-ID
type: "string"
required: true
responses:
'200':
description: Success
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/WeatherForecast'
/leolplex:
get:
tags:
- WeatherForecast
parameters:
- in: "header"
name: X-Correlation-ID
type: "string"
required: true
responses:
'200':
description: Success
content:
application/json:
example:
- date: 2021-10-21T09:13:00.552+00:00
temperatureC: 111
temperatureF: 111
summary: Just-summary
- date: 2021-10-21T09:13:00.000+00:00
temperatureC: 222
temperatureF: 222
summary: Just-summary2
schema:
type: array
items:
$ref: '#/components/schemas/WeatherForecast'
/exampleop:
get:
responses:
"200":
description: OK
content:
application/json:
example:
id: 1
name: get food
completed: false
schema:
properties:
id:
type: integer
name:
type: string
completed:
type: boolean
completed_at:
type: string
format: date-time
nullable: true
required:
- id
- name
- completed
components:
schemas:
WeatherForecast:
type: object
properties:
date:
type: string
format: date-time
temperatureC:
type: integer
format: int32
temperatureF:
type: integer
format: int32
readOnly: true
summary:
type: string
nullable: true
additionalProperties: false

View File

@@ -1,5 +1,3 @@
using Microsoft.OpenApi.Readers;
using Newtonsoft.Json;
using System; using System;
using System.IO; using System.IO;
@@ -7,15 +5,23 @@ namespace WireMock.Net.OpenApiParser.ConsoleApp
{ {
class Program class Program
{ {
private static readonly JsonSerializerSettings Settings = new JsonSerializerSettings private const string Folder = "OpenApiFiles";
{
NullValueHandling = NullValueHandling.Ignore,
Formatting = Formatting.Indented
};
static void Main(string[] args) static void Main(string[] args)
{ {
Run.RunServer("petstore-openapi3.json"); var serverOpenAPIExamples = Run.RunServer(Path.Combine(Folder, "openAPIExamples.yaml"), "http://localhost:9091/");
var serverPetstore_V2_json = Run.RunServer(Path.Combine(Folder, "Swagger_Petstore_V2.0.json"), "http://localhost:9092/");
var serverPetstore_V2_yaml = Run.RunServer(Path.Combine(Folder, "Swagger_Petstore_V2.0.yaml"), "http://localhost:9093/");
var serverPetstore_V300_yaml = Run.RunServer(Path.Combine(Folder, "Swagger_Petstore_V3.0.0.yaml"), "http://localhost:9094/");
var serverPetstore_V302_json = Run.RunServer(Path.Combine(Folder, "Swagger_Petstore_V3.0.2.json"), "http://localhost:9095/");
Console.WriteLine("Press any key to stop the servers");
Console.ReadKey();
serverOpenAPIExamples.Stop();
serverPetstore_V2_json.Stop();
serverPetstore_V2_yaml.Stop();
serverPetstore_V300_yaml.Stop();
serverPetstore_V302_json.Stop();
//IWireMockOpenApiParser parser = new WireMockOpenApiParser(); //IWireMockOpenApiParser parser = new WireMockOpenApiParser();

View File

@@ -1,4 +1,4 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using WireMock.Admin.Mappings; using WireMock.Admin.Mappings;
@@ -13,14 +13,12 @@ namespace WireMock.Net.OpenApiParser.ConsoleApp
{ {
public static class Run public static class Run
{ {
public static void RunServer(string path) public static WireMockServer RunServer(string path, string url)
{ {
string url1 = "http://localhost:9091/";
var server = WireMockServer.Start(new WireMockServerSettings var server = WireMockServer.Start(new WireMockServerSettings
{ {
AllowCSharpCodeMatcher = true, AllowCSharpCodeMatcher = true,
Urls = new[] { url1 }, Urls = new[] { url },
StartAdminInterface = true, StartAdminInterface = true,
ReadStaticMappings = false, ReadStaticMappings = false,
WatchStaticMappings = false, WatchStaticMappings = false,
@@ -38,9 +36,7 @@ namespace WireMock.Net.OpenApiParser.ConsoleApp
server.WithMappingFromOpenApiFile(path, settings, out var diag); server.WithMappingFromOpenApiFile(path, settings, out var diag);
Console.WriteLine("Press any key to stop the server"); return server;
System.Console.ReadKey();
server.Stop();
} }
public static void RunServer(IEnumerable<MappingModel> mappings) public static void RunServer(IEnumerable<MappingModel> mappings)

View File

@@ -15,6 +15,21 @@
<None Update="infura.yaml"> <None Update="infura.yaml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None> </None>
<None Update="OpenApiFiles\openAPIExamples.yaml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="OpenApiFiles\Swagger_Petstore_V2.0.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="OpenApiFiles\Swagger_Petstore_V2.0.yaml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="OpenApiFiles\Swagger_Petstore_V3.0.0.yaml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="OpenApiFiles\Swagger_Petstore_V3.0.2.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="petstore-openapi3.json"> <None Update="petstore-openapi3.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None> </None>

View File

@@ -1,9 +1,8 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<OutputType>Exe</OutputType> <OutputType>Exe</OutputType>
<TargetFrameworks>netcoreapp3.1</TargetFrameworks> <TargetFrameworks>netcoreapp3.1</TargetFrameworks>
<ApplicationIcon>../../WireMock.Net-Logo.ico</ApplicationIcon>
<StartupObject>WireMock.Net.StandAlone.NETCoreApp.Program</StartupObject> <StartupObject>WireMock.Net.StandAlone.NETCoreApp.Program</StartupObject>
</PropertyGroup> </PropertyGroup>

View File

@@ -33,7 +33,7 @@
<WarningLevel>4</WarningLevel> <WarningLevel>4</WarningLevel>
</PropertyGroup> </PropertyGroup>
<PropertyGroup> <PropertyGroup>
<ApplicationIcon>..\..\WireMock.Net-Logo.ico</ApplicationIcon> <ApplicationIcon>..\..\resources\WireMock.Net-Logo.ico</ApplicationIcon>
</PropertyGroup> </PropertyGroup>
<PropertyGroup> <PropertyGroup>
<StartupObject>WireMock.Net.StandAlone.Net452.Program</StartupObject> <StartupObject>WireMock.Net.StandAlone.Net452.Program</StartupObject>

View File

@@ -204,8 +204,8 @@
<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"> <Reference Include="RestEase, Version=1.5.5.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\..\packages\RestEase.1.4.10\lib\net45\RestEase.dll</HintPath> <HintPath>..\..\packages\RestEase.1.5.5\lib\net45\RestEase.dll</HintPath>
</Reference> </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>

View File

@@ -59,7 +59,7 @@
<package id="MimeKitLite" version="2.0.7" targetFramework="net461" /> <package id="MimeKitLite" version="2.0.7" targetFramework="net461" />
<package id="Newtonsoft.Json" version="11.0.2" targetFramework="net461" /> <package id="Newtonsoft.Json" version="11.0.2" targetFramework="net461" />
<package id="Owin" version="1.0" targetFramework="net461" /> <package id="Owin" version="1.0" targetFramework="net461" />
<package id="RestEase" version="1.4.10" targetFramework="net461" /> <package id="RestEase" version="1.5.5" targetFramework="net461" />
<package id="SimMetrics.Net" version="1.0.5" targetFramework="net461" /> <package id="SimMetrics.Net" version="1.0.5" targetFramework="net461" />
<package id="System.Buffers" version="4.5.0" targetFramework="net461" /> <package id="System.Buffers" version="4.5.0" targetFramework="net461" />
<package id="System.Collections.Immutable" version="1.5.0" targetFramework="net461" /> <package id="System.Collections.Immutable" version="1.5.0" targetFramework="net461" />

View File

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 24 KiB

View File

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

View File

@@ -3,6 +3,7 @@
/// <summary> /// <summary>
/// Body Model /// Body Model
/// </summary> /// </summary>
[FluentBuilder.AutoGenerateBuilder]
public class BodyModel public class BodyModel
{ {
/// <summary> /// <summary>

View File

@@ -3,6 +3,7 @@
/// <summary> /// <summary>
/// ClientIPModel /// ClientIPModel
/// </summary> /// </summary>
[FluentBuilder.AutoGenerateBuilder]
public class ClientIPModel public class ClientIPModel
{ {
/// <summary> /// <summary>

View File

@@ -5,6 +5,7 @@ namespace WireMock.Admin.Mappings
/// <summary> /// <summary>
/// Cookie Model /// Cookie Model
/// </summary> /// </summary>
[FluentBuilder.AutoGenerateBuilder]
public class CookieModel public class CookieModel
{ {
/// <summary> /// <summary>

View File

@@ -3,6 +3,7 @@
/// <summary> /// <summary>
/// EncodingModel /// EncodingModel
/// </summary> /// </summary>
[FluentBuilder.AutoGenerateBuilder]
public class EncodingModel public class EncodingModel
{ {
/// <summary> /// <summary>

View File

@@ -3,6 +3,7 @@
/// <summary> /// <summary>
/// Fault Model /// Fault Model
/// </summary> /// </summary>
[FluentBuilder.AutoGenerateBuilder]
public class FaultModel public class FaultModel
{ {
/// <summary> /// <summary>

View File

@@ -5,6 +5,7 @@ namespace WireMock.Admin.Mappings
/// <summary> /// <summary>
/// Header Model /// Header Model
/// </summary> /// </summary>
[FluentBuilder.AutoGenerateBuilder]
public class HeaderModel public class HeaderModel
{ {
/// <summary> /// <summary>

View File

@@ -1,10 +1,12 @@
using System; using System;
using WireMock.Models;
namespace WireMock.Admin.Mappings namespace WireMock.Admin.Mappings
{ {
/// <summary> /// <summary>
/// MappingModel /// MappingModel
/// </summary> /// </summary>
[FluentBuilder.AutoGenerateBuilder]
public class MappingModel public class MappingModel
{ {
/// <summary> /// <summary>
@@ -12,6 +14,11 @@ namespace WireMock.Admin.Mappings
/// </summary> /// </summary>
public Guid? Guid { get; set; } public Guid? Guid { get; set; }
/// <summary>
/// Gets or sets the TimeSettings when which this mapping should be used.
/// </summary>
public TimeSettingsModel TimeSettings { get; set; }
/// <summary> /// <summary>
/// The unique title. /// The unique title.
/// </summary> /// </summary>

View File

@@ -1,8 +1,9 @@
namespace WireMock.Admin.Mappings namespace WireMock.Admin.Mappings
{ {
/// <summary> /// <summary>
/// MatcherModel /// MatcherModel
/// </summary> /// </summary>
[FluentBuilder.AutoGenerateBuilder]
public class MatcherModel public class MatcherModel
{ {
/// <summary> /// <summary>
@@ -11,15 +12,20 @@
public string Name { get; set; } public string Name { get; set; }
/// <summary> /// <summary>
/// Gets or sets the pattern. Can be a string (default) or an object; /// Gets or sets the pattern. Can be a string (default) or an object.
/// </summary> /// </summary>
public object Pattern { get; set; } public object Pattern { get; set; }
/// <summary> /// <summary>
/// Gets or sets the patterns. Can be array of strings (default) or an array of objects; /// Gets or sets the patterns. Can be array of strings (default) or an array of objects.
/// </summary> /// </summary>
public object[] Patterns { get; set; } public object[] Patterns { get; set; }
/// <summary>
/// Gets or sets the pattern as a file.
/// </summary>
public string PatternAsFile { get; set; }
/// <summary> /// <summary>
/// Gets or sets the ignore case. /// Gets or sets the ignore case.
/// </summary> /// </summary>

View File

@@ -3,6 +3,7 @@
/// <summary> /// <summary>
/// Param Model /// Param Model
/// </summary> /// </summary>
[FluentBuilder.AutoGenerateBuilder]
public class ParamModel public class ParamModel
{ {
/// <summary> /// <summary>

View File

@@ -3,6 +3,7 @@
/// <summary> /// <summary>
/// PathModel /// PathModel
/// </summary> /// </summary>
[FluentBuilder.AutoGenerateBuilder]
public class PathModel public class PathModel
{ {
/// <summary> /// <summary>

View File

@@ -5,6 +5,7 @@ namespace WireMock.Admin.Mappings
/// <summary> /// <summary>
/// RequestModel /// RequestModel
/// </summary> /// </summary>
[FluentBuilder.AutoGenerateBuilder]
public class RequestModel public class RequestModel
{ {
/// <summary> /// <summary>

View File

@@ -5,6 +5,7 @@ namespace WireMock.Admin.Mappings
/// <summary> /// <summary>
/// ResponseModel /// ResponseModel
/// </summary> /// </summary>
[FluentBuilder.AutoGenerateBuilder]
public class ResponseModel public class ResponseModel
{ {
/// <summary> /// <summary>
@@ -82,6 +83,16 @@ namespace WireMock.Admin.Mappings
/// </summary> /// </summary>
public int? Delay { get; set; } public int? Delay { get; set; }
/// <summary>
/// Gets or sets the minimum random delay in milliseconds.
/// </summary>
public int? MinimumRandomDelay { get; set; }
/// <summary>
/// Gets or sets the maximum random delay in milliseconds.
/// </summary>
public int? MaximumRandomDelay { get; set; }
/// <summary> /// <summary>
/// Gets or sets the Proxy URL. /// Gets or sets the Proxy URL.
/// </summary> /// </summary>

View File

@@ -5,6 +5,7 @@ namespace WireMock.Admin.Mappings
/// <summary> /// <summary>
/// Status /// Status
/// </summary> /// </summary>
[FluentBuilder.AutoGenerateBuilder]
public class StatusModel public class StatusModel
{ {
/// <summary> /// <summary>

View File

@@ -0,0 +1,26 @@
using System;
namespace WireMock.Models
{
/// <summary>
/// TimeSettingsModel: Start, End and TTL
/// </summary>
[FluentBuilder.AutoGenerateBuilder]
public class TimeSettingsModel
{
/// <summary>
/// Gets or sets the DateTime from which this mapping should be used. In case this is not defined, it's used (default behavior).
/// </summary>
public DateTime? Start { get; set; }
/// <summary>
/// Gets or sets the DateTime from until this mapping should be used. In case this is not defined, it's used forever (default behavior).
/// </summary>
public DateTime? End { get; set; }
/// <summary>
/// Gets or sets the TTL (Time To Live) in seconds for this mapping. In case this is not defined, it's used (default behavior).
/// </summary>
public int? TTL { get; set; }
}
}

View File

@@ -3,6 +3,7 @@
/// <summary> /// <summary>
/// UrlModel /// UrlModel
/// </summary> /// </summary>
[FluentBuilder.AutoGenerateBuilder]
public class UrlModel public class UrlModel
{ {
/// <summary> /// <summary>

View File

@@ -3,6 +3,7 @@
/// <summary> /// <summary>
/// WebProxy settings /// WebProxy settings
/// </summary> /// </summary>
[FluentBuilder.AutoGenerateBuilder]
public class WebProxyModel public class WebProxyModel
{ {
/// <summary> /// <summary>

View File

@@ -3,6 +3,7 @@
/// <summary> /// <summary>
/// The Webhook /// The Webhook
/// </summary> /// </summary>
[FluentBuilder.AutoGenerateBuilder]
public class WebhookModel public class WebhookModel
{ {
/// <summary> /// <summary>

View File

@@ -5,6 +5,7 @@ namespace WireMock.Admin.Mappings
/// <summary> /// <summary>
/// RequestModel /// RequestModel
/// </summary> /// </summary>
[FluentBuilder.AutoGenerateBuilder]
public class WebhookRequestModel public class WebhookRequestModel
{ {
/// <summary> /// <summary>

View File

@@ -5,6 +5,7 @@ namespace WireMock.Admin.Requests
/// <summary> /// <summary>
/// Request Log Model /// Request Log Model
/// </summary> /// </summary>
[FluentBuilder.AutoGenerateBuilder]
public class LogEntryModel public class LogEntryModel
{ {
/// <summary> /// <summary>

View File

@@ -5,6 +5,7 @@ namespace WireMock.Admin.Requests
/// <summary> /// <summary>
/// LogRequestMatchModel /// LogRequestMatchModel
/// </summary> /// </summary>
[FluentBuilder.AutoGenerateBuilder]
public class LogRequestMatchModel public class LogRequestMatchModel
{ {
/// <summary> /// <summary>

View File

@@ -8,6 +8,7 @@ namespace WireMock.Admin.Requests
/// <summary> /// <summary>
/// RequestMessage Model /// RequestMessage Model
/// </summary> /// </summary>
[FluentBuilder.AutoGenerateBuilder]
public class LogRequestModel public class LogRequestModel
{ {
/// <summary> /// <summary>

View File

@@ -7,6 +7,7 @@ namespace WireMock.Admin.Requests
/// <summary> /// <summary>
/// Response MessageModel /// Response MessageModel
/// </summary> /// </summary>
[FluentBuilder.AutoGenerateBuilder]
public class LogResponseModel public class LogResponseModel
{ {
/// <summary> /// <summary>

View File

@@ -3,6 +3,7 @@
/// <summary> /// <summary>
/// ScenarioStateModel /// ScenarioStateModel
/// </summary> /// </summary>
[FluentBuilder.AutoGenerateBuilder]
public class ScenarioStateModel public class ScenarioStateModel
{ {
/// <summary> /// <summary>

View File

@@ -3,6 +3,7 @@
/// <summary> /// <summary>
/// Settings /// Settings
/// </summary> /// </summary>
[FluentBuilder.AutoGenerateBuilder]
public class SettingsModel public class SettingsModel
{ {
/// <summary> /// <summary>

View File

@@ -1,4 +1,4 @@
using JetBrains.Annotations; using JetBrains.Annotations;
using System.Collections.Generic; using System.Collections.Generic;
namespace WireMock.Handlers namespace WireMock.Handlers
@@ -89,5 +89,12 @@ namespace WireMock.Handlers
/// <param name="filename">The filename.</param> /// <param name="filename">The filename.</param>
/// <returns>The file content as bytes.</returns> /// <returns>The file content as bytes.</returns>
byte[] ReadFile([NotNull] string filename); byte[] ReadFile([NotNull] string filename);
/// <summary>
/// Read a file as string.
/// </summary>
/// <param name="filename">The filename.</param>
/// <returns>The file content as a string.</returns>
string ReadFileAsString([NotNull] string filename);
} }
} }

View File

@@ -0,0 +1,25 @@
using System;
namespace WireMock.Models
{
/// <summary>
/// TimeSettings: Start, End and TTL
/// </summary>
public interface ITimeSettings
{
/// <summary>
/// Gets or sets the DateTime from which this mapping should be used. In case this is not defined, it's used (default behavior).
/// </summary>
DateTime? Start { get; set; }
/// <summary>
/// Gets or sets the DateTime from until this mapping should be used. In case this is not defined, it's used forever (default behavior).
/// </summary>
DateTime? End { get; set; }
/// <summary>
/// Gets or sets the TTL (Time To Live) in seconds for this mapping. In case this is not defined, it's used (default behavior).
/// </summary>
int? TTL { get; set; }
}
}

View File

@@ -1,4 +1,4 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.Specialized; using System.Collections.Specialized;
using JetBrains.Annotations; using JetBrains.Annotations;
@@ -104,9 +104,9 @@ namespace WireMock.Server
void ReadStaticMappings([CanBeNull] string folder = null); void ReadStaticMappings([CanBeNull] string folder = null);
/// <summary> /// <summary>
/// Removes the basic authentication. /// Removes the authentication.
/// </summary> /// </summary>
void RemoveBasicAuthentication(); void RemoveAuthentication();
/// <summary> /// <summary>
/// Resets LogEntries and Mappings. /// Resets LogEntries and Mappings.
@@ -134,6 +134,13 @@ namespace WireMock.Server
/// <param name="folder">The optional folder. If not defined, use {CurrentFolder}/__admin/mappings</param> /// <param name="folder">The optional folder. If not defined, use {CurrentFolder}/__admin/mappings</param>
void SaveStaticMappings([CanBeNull] string folder = null); void SaveStaticMappings([CanBeNull] string folder = null);
/// <summary>
/// Sets the basic authentication.
/// </summary>
/// <param name="tenant">The Tenant.</param>
/// <param name="audience">The Audience or Resource.</param>
void SetAzureADAuthentication([NotNull] string tenant, [NotNull] string audience);
/// <summary> /// <summary>
/// Sets the basic authentication. /// Sets the basic authentication.
/// </summary> /// </summary>

View File

@@ -1,37 +1,46 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<Description>Commonly used interfaces, models, enumerations and types.</Description> <Description>Commonly used models, enumerations and types.</Description>
<AssemblyTitle>WireMock.Net.Abstractions</AssemblyTitle> <AssemblyTitle>WireMock.Net.Abstractions</AssemblyTitle>
<Authors>Stef Heyenrath</Authors> <Authors>Stef Heyenrath</Authors>
<TargetFrameworks>net45;netstandard1.0;netstandard2.0;netstandard2.1</TargetFrameworks> <TargetFrameworks>net45;netstandard1.0;netstandard2.0;netstandard2.1</TargetFrameworks>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<AssemblyName>WireMock.Net.Abstractions</AssemblyName>
<PackageId>WireMock.Net.Abstractions</PackageId>
<PackageTags>wiremock;interfaces;models;classes;enumerations;types</PackageTags>
<RootNamespace>WireMock</RootNamespace>
<ProjectGuid>{B6269AAC-170A-4346-8B9A-579DED3D9A94}</ProjectGuid>
<PublishRepositoryUrl>true</PublishRepositoryUrl>
<AllowedOutputExtensionsInPackageBuildOutputFolder>$(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb</AllowedOutputExtensionsInPackageBuildOutputFolder>
<EmbedUntrackedSources>true</EmbedUntrackedSources>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<GenerateBindingRedirectsOutputType>true</GenerateBindingRedirectsOutputType>
<CodeAnalysisRuleSet>../WireMock.Net/WireMock.Net.ruleset</CodeAnalysisRuleSet>
<SignAssembly>true</SignAssembly>
<AssemblyOriginatorKeyFile>../WireMock.Net/WireMock.Net.snk</AssemblyOriginatorKeyFile>
<!--<DelaySign>true</DelaySign>-->
<PublicSign Condition=" '$(OS)' != 'Windows_NT' ">true</PublicSign>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Release' "> <GenerateDocumentationFile>true</GenerateDocumentationFile>
<!--<PathMap>$(MSBuildProjectDirectory)=/</PathMap>--> <NoWarn>$(NoWarn);1591;8603</NoWarn>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
</PropertyGroup>
<ItemGroup> <AssemblyName>WireMock.Net.Abstractions</AssemblyName>
<PackageReference Include="JetBrains.Annotations" Version="2020.1.0" PrivateAssets="All" /> <PackageId>WireMock.Net.Abstractions</PackageId>
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All" /> <PackageTags>wiremock;wiremock.org;interfaces;models;classes;enumerations;types</PackageTags>
</ItemGroup> <RootNamespace>WireMock</RootNamespace>
<ProjectGuid>{B6269AAC-170A-4346-8B9A-579DED3D9A94}</ProjectGuid>
<PublishRepositoryUrl>true</PublishRepositoryUrl>
<AllowedOutputExtensionsInPackageBuildOutputFolder>$(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb</AllowedOutputExtensionsInPackageBuildOutputFolder>
<EmbedUntrackedSources>true</EmbedUntrackedSources>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<GenerateBindingRedirectsOutputType>true</GenerateBindingRedirectsOutputType>
<CodeAnalysisRuleSet>../WireMock.Net/WireMock.Net.ruleset</CodeAnalysisRuleSet>
<SignAssembly>true</SignAssembly>
<AssemblyOriginatorKeyFile>../WireMock.Net/WireMock.Net.snk</AssemblyOriginatorKeyFile>
<!--<DelaySign>true</DelaySign>-->
<PublicSign Condition=" '$(OS)' != 'Windows_NT' ">true</PublicSign>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<!--<PathMap>$(MSBuildProjectDirectory)=/</PathMap>-->
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="JetBrains.Annotations" Version="2021.2.0" PrivateAssets="All" />
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All" />
<!-- See also https://mstack.nl/blog/20210801-source-generators -->
<PackageReference Include="FluentBuilder" Version="0.0.11">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>
</Project> </Project>

View File

@@ -36,7 +36,7 @@ namespace WireMock.FluentAssertions
[CustomAssertion] [CustomAssertion]
public AndConstraint<WireMockAssertions> WithHeader(string expectedKey, string value, string because = "", params object[] becauseArgs) public AndConstraint<WireMockAssertions> WithHeader(string expectedKey, string value, string because = "", params object[] becauseArgs)
=> WithHeader(expectedKey, new[] {value}, because, becauseArgs); => WithHeader(expectedKey, new[] { value }, because, becauseArgs);
[CustomAssertion] [CustomAssertion]
public AndConstraint<WireMockAssertions> WithHeader(string expectedKey, string[] expectedValues, string because = "", params object[] becauseArgs) public AndConstraint<WireMockAssertions> WithHeader(string expectedKey, string[] expectedValues, string because = "", params object[] becauseArgs)
@@ -69,7 +69,7 @@ namespace WireMock.FluentAssertions
return new AndConstraint<WireMockAssertions>(this); return new AndConstraint<WireMockAssertions>(this);
} }
[CustomAssertion] [CustomAssertion]
public AndConstraint<WireMockAssertions> AtUrl(string url, string because = "", params object[] becauseArgs) public AndConstraint<WireMockAssertions> AtUrl(string url, string because = "", params object[] becauseArgs)
{ {
@@ -85,10 +85,10 @@ namespace WireMock.FluentAssertions
.FailWith( .FailWith(
"Expected {context:wiremockserver} to have been called at address matching the url {0}{reason}, but didn't find it among the calls to {1}.", "Expected {context:wiremockserver} to have been called at address matching the url {0}{reason}, but didn't find it among the calls to {1}.",
_ => url, requests => requests.Select(request => request.Url)); _ => url, requests => requests.Select(request => request.Url));
return new AndConstraint<WireMockAssertions>(this); return new AndConstraint<WireMockAssertions>(this);
} }
[CustomAssertion] [CustomAssertion]
public AndConstraint<WireMockAssertions> WithProxyUrl(string proxyUrl, string because = "", params object[] becauseArgs) public AndConstraint<WireMockAssertions> WithProxyUrl(string proxyUrl, string because = "", params object[] becauseArgs)
{ {
@@ -104,10 +104,10 @@ namespace WireMock.FluentAssertions
.FailWith( .FailWith(
"Expected {context:wiremockserver} to have been called with proxy url {0}{reason}, but didn't find it among the calls with {1}.", "Expected {context:wiremockserver} to have been called with proxy url {0}{reason}, but didn't find it among the calls with {1}.",
_ => proxyUrl, requests => requests.Select(request => request.ProxyUrl)); _ => proxyUrl, requests => requests.Select(request => request.ProxyUrl));
return new AndConstraint<WireMockAssertions>(this); return new AndConstraint<WireMockAssertions>(this);
} }
[CustomAssertion] [CustomAssertion]
public AndConstraint<WireMockAssertions> FromClientIP(string clientIP, string because = "", params object[] becauseArgs) public AndConstraint<WireMockAssertions> FromClientIP(string clientIP, string because = "", params object[] becauseArgs)
{ {
@@ -123,7 +123,7 @@ namespace WireMock.FluentAssertions
.FailWith( .FailWith(
"Expected {context:wiremockserver} to have been called from client IP {0}{reason}, but didn't find it among the calls from IP(s) {1}.", "Expected {context:wiremockserver} to have been called from client IP {0}{reason}, but didn't find it among the calls from IP(s) {1}.",
_ => clientIP, requests => requests.Select(request => request.ClientIP)); _ => clientIP, requests => requests.Select(request => request.ClientIP));
return new AndConstraint<WireMockAssertions>(this); return new AndConstraint<WireMockAssertions>(this);
} }
} }

View File

@@ -4,23 +4,39 @@ using WireMock.Server;
// ReSharper disable once CheckNamespace // ReSharper disable once CheckNamespace
namespace WireMock.FluentAssertions namespace WireMock.FluentAssertions
{ {
/// <summary>
/// Contains a number of methods to assert that the <see cref="IWireMockServer"/> is in the expected state.
/// </summary>
public class WireMockReceivedAssertions : ReferenceTypeAssertions<IWireMockServer, WireMockReceivedAssertions> public class WireMockReceivedAssertions : ReferenceTypeAssertions<IWireMockServer, WireMockReceivedAssertions>
{ {
public WireMockReceivedAssertions(IWireMockServer server) /// <summary>
/// Create a WireMockReceivedAssertions.
/// </summary>
/// <param name="server">The <see cref="IWireMockServer"/>.</param>
public WireMockReceivedAssertions(IWireMockServer server) : base(server)
{ {
Subject = server;
} }
/// <summary>
/// Asserts if <see cref="IWireMockServer"/> has received a call.
/// </summary>
/// <returns><see cref="WireMockAssertions"/></returns>
public WireMockAssertions HaveReceivedACall() public WireMockAssertions HaveReceivedACall()
{ {
return new WireMockAssertions(Subject, null); return new WireMockAssertions(Subject, null);
} }
/// <summary>
/// Asserts if <see cref="IWireMockServer"/> has received n-calls.
/// </summary>
/// <param name="callsCount"></param>
/// <returns><see cref="WireMockANumberOfCallsAssertions"/></returns>
public WireMockANumberOfCallsAssertions HaveReceived(int callsCount) public WireMockANumberOfCallsAssertions HaveReceived(int callsCount)
{ {
return new WireMockANumberOfCallsAssertions(Subject, callsCount); return new WireMockANumberOfCallsAssertions(Subject, callsCount);
} }
/// <inheritdoc cref="ReferenceTypeAssertions{IWireMockServer, WireMockReceivedAssertions}.Identifier"/>
protected override string Identifier => "wiremockserver"; protected override string Identifier => "wiremockserver";
} }
} }

View File

@@ -3,8 +3,16 @@ using WireMock.Server;
// ReSharper disable once CheckNamespace // ReSharper disable once CheckNamespace
namespace WireMock.FluentAssertions namespace WireMock.FluentAssertions
{ {
/// <summary>
/// Contains extension methods for custom assertions in unit tests.
/// </summary>
public static class WireMockExtensions public static class WireMockExtensions
{ {
/// <summary>
/// Returns a <see cref="WireMockReceivedAssertions"/> object that can be used to assert the current <see cref="IWireMockServer"/>.
/// </summary>
/// <param name="instance">The WireMockServer</param>
/// <returns><see cref="WireMockReceivedAssertions"/></returns>
public static WireMockReceivedAssertions Should(this IWireMockServer instance) public static WireMockReceivedAssertions Should(this IWireMockServer instance)
{ {
return new WireMockReceivedAssertions(instance); return new WireMockReceivedAssertions(instance);

View File

@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<Description>FluentAssertions extensions for WireMock.Net</Description> <Description>FluentAssertions extensions for WireMock.Net</Description>
@@ -29,13 +29,20 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="FluentAssertions" Version="5.10.3" />
<PackageReference Include="JetBrains.Annotations" Version="2020.1.0" PrivateAssets="All" /> <PackageReference Include="JetBrains.Annotations" Version="2020.1.0" PrivateAssets="All" />
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All" /> <PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All" />
</ItemGroup> </ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'net451' or '$(TargetFramework)' == 'netstandard1.3'">
<PackageReference Include="FluentAssertions" Version="5.10.3" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' != 'net451' and '$(TargetFramework)' != 'netstandard1.3'">
<PackageReference Include="FluentAssertions" Version="6.1.0" />
</ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\WireMock.Net.Abstractions\WireMock.Net.Abstractions.csproj" /> <ProjectReference Include="..\WireMock.Net.Abstractions\WireMock.Net.Abstractions.csproj" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@@ -1,225 +1,228 @@
using System; using System;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
using System.Text; using System.Text;
using JetBrains.Annotations; using AnyOfTypes;
using Newtonsoft.Json.Linq; using JetBrains.Annotations;
using WireMock.Exceptions; using Newtonsoft.Json.Linq;
using WireMock.Validation; using WireMock.Exceptions;
using WireMock.Extensions;
namespace WireMock.Matchers using WireMock.Models;
{ using WireMock.Validation;
/// <summary>
/// CSharpCode / CS-Script Matcher namespace WireMock.Matchers
/// </summary> {
/// <inheritdoc cref="ICSharpCodeMatcher"/> /// <summary>
internal class CSharpCodeMatcher : ICSharpCodeMatcher /// CSharpCode / CS-Script Matcher
{ /// </summary>
private const string TemplateForIsMatchWithString = "public class CodeHelper {{ public bool IsMatch(string it) {{ {0} }} }}"; /// <inheritdoc cref="ICSharpCodeMatcher"/>
internal class CSharpCodeMatcher : ICSharpCodeMatcher
private const string TemplateForIsMatchWithDynamic = "public class CodeHelper {{ public bool IsMatch(dynamic it) {{ {0} }} }}"; {
private const string TemplateForIsMatchWithString = "public class CodeHelper {{ public bool IsMatch(string it) {{ {0} }} }}";
private readonly string[] _usings =
{ private const string TemplateForIsMatchWithDynamic = "public class CodeHelper {{ public bool IsMatch(dynamic it) {{ {0} }} }}";
"System",
"System.Linq", private readonly string[] _usings =
"System.Collections.Generic", {
"Microsoft.CSharp", "System",
"Newtonsoft.Json.Linq" "System.Linq",
}; "System.Collections.Generic",
"Microsoft.CSharp",
public MatchBehaviour MatchBehaviour { get; } "Newtonsoft.Json.Linq"
};
/// <inheritdoc cref="IMatcher.ThrowException"/>
public bool ThrowException { get; } public MatchBehaviour MatchBehaviour { get; }
private readonly string[] _patterns; /// <inheritdoc cref="IMatcher.ThrowException"/>
public bool ThrowException { get; }
/// <summary>
/// Initializes a new instance of the <see cref="CSharpCodeMatcher"/> class. private readonly AnyOf<string, StringPattern>[] _patterns;
/// </summary>
/// <param name="patterns">The patterns.</param> /// <summary>
public CSharpCodeMatcher([NotNull] params string[] patterns) : this(MatchBehaviour.AcceptOnMatch, patterns) /// Initializes a new instance of the <see cref="CSharpCodeMatcher"/> class.
{ /// </summary>
} /// <param name="patterns">The patterns.</param>
public CSharpCodeMatcher([NotNull] params AnyOf<string, StringPattern>[] patterns) : this(MatchBehaviour.AcceptOnMatch, patterns)
/// <summary> {
/// Initializes a new instance of the <see cref="CSharpCodeMatcher"/> class. }
/// </summary>
/// <param name="matchBehaviour">The match behaviour.</param> /// <summary>
/// <param name="patterns">The patterns.</param> /// Initializes a new instance of the <see cref="CSharpCodeMatcher"/> class.
public CSharpCodeMatcher(MatchBehaviour matchBehaviour, [NotNull] params string[] patterns) /// </summary>
{ /// <param name="matchBehaviour">The match behaviour.</param>
Check.NotNull(patterns, nameof(patterns)); /// <param name="patterns">The patterns.</param>
public CSharpCodeMatcher(MatchBehaviour matchBehaviour, [NotNull] params AnyOf<string, StringPattern>[] patterns)
MatchBehaviour = matchBehaviour; {
ThrowException = false; Check.NotNull(patterns, nameof(patterns));
_patterns = patterns;
} MatchBehaviour = matchBehaviour;
ThrowException = false;
public double IsMatch(string input) _patterns = patterns;
{ }
return IsMatchInternal(input);
} public double IsMatch(string input)
{
public double IsMatch(object input) return IsMatchInternal(input);
{ }
return IsMatchInternal(input);
} public double IsMatch(object input)
{
public double IsMatchInternal(object input) return IsMatchInternal(input);
{ }
double match = MatchScores.Mismatch;
public double IsMatchInternal(object input)
if (input != null) {
{ double match = MatchScores.Mismatch;
match = MatchScores.ToScore(_patterns.Select(pattern => IsMatch(input, pattern)));
} if (input != null)
return MatchBehaviourHelper.Convert(MatchBehaviour, match);
}
private bool IsMatch(dynamic input, string pattern)
{
bool isMatchWithString = input is string;
var inputValue = isMatchWithString ? input : JObject.FromObject(input);
string source = GetSourceForIsMatchWithString(pattern, isMatchWithString);
object result = null;
#if (NET451 || NET452)
var compilerParams = new System.CodeDom.Compiler.CompilerParameters
{
GenerateInMemory = true,
GenerateExecutable = false,
ReferencedAssemblies =
{
"System.dll",
"System.Core.dll",
"Microsoft.CSharp.dll",
"Newtonsoft.Json.dll"
}
};
using (var codeProvider = new Microsoft.CSharp.CSharpCodeProvider())
{
var compilerResults = codeProvider.CompileAssemblyFromSource(compilerParams, source);
if (compilerResults.Errors.Count != 0)
{
var errors = from System.CodeDom.Compiler.CompilerError er in compilerResults.Errors select er.ToString();
throw new WireMockException(string.Join(", ", errors));
}
object helper = compilerResults.CompiledAssembly.CreateInstance("CodeHelper");
if (helper == null)
{
throw new WireMockException("CSharpCodeMatcher: Unable to create instance from WireMock.CodeHelper");
}
var methodInfo = helper.GetType().GetMethod("IsMatch");
if (methodInfo == null)
{
throw new WireMockException("CSharpCodeMatcher: Unable to find method 'IsMatch' in WireMock.CodeHelper");
}
try
{
result = methodInfo.Invoke(helper, new[] { inputValue });
}
catch (Exception ex)
{
throw new WireMockException("CSharpCodeMatcher: Unable to call method 'IsMatch' in WireMock.CodeHelper", ex);
}
}
#elif (NET46 || NET461)
dynamic script;
try
{
script = CSScriptLibrary.CSScript.Evaluator.CompileCode(source).CreateObject("*");
}
catch (Exception ex)
{
throw new WireMockException("CSharpCodeMatcher: Unable to create compiler for WireMock.CodeHelper", ex);
}
try
{
result = script.IsMatch(inputValue);
}
catch (Exception ex)
{
throw new WireMockException("CSharpCodeMatcher: Problem calling method 'IsMatch' in WireMock.CodeHelper", ex);
}
#elif (NETSTANDARD2_0 || NETSTANDARD2_1 || NETCOREAPP3_1 || NET5_0)
Assembly assembly;
try
{ {
assembly = CSScriptLib.CSScript.Evaluator.CompileCode(source); match = MatchScores.ToScore(_patterns.Select(pattern => IsMatch(input, pattern.GetPattern())));
} }
catch (Exception ex)
{ return MatchBehaviourHelper.Convert(MatchBehaviour, match);
throw new WireMockException($"CSharpCodeMatcher: Unable to compile code `{source}` for WireMock.CodeHelper", ex); }
}
private bool IsMatch(dynamic input, string pattern)
dynamic script; {
bool isMatchWithString = input is string;
var inputValue = isMatchWithString ? input : JObject.FromObject(input);
string source = GetSourceForIsMatchWithString(pattern, isMatchWithString);
object result = null;
#if (NET451 || NET452)
var compilerParams = new System.CodeDom.Compiler.CompilerParameters
{
GenerateInMemory = true,
GenerateExecutable = false,
ReferencedAssemblies =
{
"System.dll",
"System.Core.dll",
"Microsoft.CSharp.dll",
"Newtonsoft.Json.dll"
}
};
using (var codeProvider = new Microsoft.CSharp.CSharpCodeProvider())
{
var compilerResults = codeProvider.CompileAssemblyFromSource(compilerParams, source);
if (compilerResults.Errors.Count != 0)
{
var errors = from System.CodeDom.Compiler.CompilerError er in compilerResults.Errors select er.ToString();
throw new WireMockException(string.Join(", ", errors));
}
object helper = compilerResults.CompiledAssembly.CreateInstance("CodeHelper");
if (helper == null)
{
throw new WireMockException("CSharpCodeMatcher: Unable to create instance from WireMock.CodeHelper");
}
var methodInfo = helper.GetType().GetMethod("IsMatch");
if (methodInfo == null)
{
throw new WireMockException("CSharpCodeMatcher: Unable to find method 'IsMatch' in WireMock.CodeHelper");
}
try
{
result = methodInfo.Invoke(helper, new[] { inputValue });
}
catch (Exception ex)
{
throw new WireMockException("CSharpCodeMatcher: Unable to call method 'IsMatch' in WireMock.CodeHelper", ex);
}
}
#elif (NET46 || NET461)
dynamic script;
try try
{ {
#if NETSTANDARD2_0 script = CSScriptLibrary.CSScript.Evaluator.CompileCode(source).CreateObject("*");
script = csscript.GenericExtensions.CreateObject(assembly, "*"); }
#else catch (Exception ex)
script = CSScriptLib.ReflectionExtensions.CreateObject(assembly, "*"); {
throw new WireMockException("CSharpCodeMatcher: Unable to create compiler for WireMock.CodeHelper", ex);
}
try
{
result = script.IsMatch(inputValue);
}
catch (Exception ex)
{
throw new WireMockException("CSharpCodeMatcher: Problem calling method 'IsMatch' in WireMock.CodeHelper", ex);
}
#elif (NETSTANDARD2_0 || NETSTANDARD2_1 || NETCOREAPP3_1 || NET5_0)
Assembly assembly;
try
{
assembly = CSScriptLib.CSScript.Evaluator.CompileCode(source);
}
catch (Exception ex)
{
throw new WireMockException($"CSharpCodeMatcher: Unable to compile code `{source}` for WireMock.CodeHelper", ex);
}
dynamic script;
try
{
#if NETSTANDARD2_0
script = csscript.GenericExtensions.CreateObject(assembly, "*");
#else
script = CSScriptLib.ReflectionExtensions.CreateObject(assembly, "*");
#endif #endif
} }
catch (Exception ex) catch (Exception ex)
{ {
throw new WireMockException("CSharpCodeMatcher: Unable to create object from assembly", ex); throw new WireMockException("CSharpCodeMatcher: Unable to create object from assembly", ex);
}
try
{
result = script.IsMatch(inputValue);
}
catch (Exception ex)
{
throw new WireMockException("CSharpCodeMatcher: Problem calling method 'IsMatch' in WireMock.CodeHelper", ex);
} }
#else
throw new NotSupportedException("The 'CSharpCodeMatcher' cannot be used in netstandard 1.3"); try
#endif {
try result = script.IsMatch(inputValue);
{ }
return (bool)result; catch (Exception ex)
} {
catch throw new WireMockException("CSharpCodeMatcher: Problem calling method 'IsMatch' in WireMock.CodeHelper", ex);
{ }
throw new WireMockException($"Unable to cast result '{result}' to bool"); #else
} throw new NotSupportedException("The 'CSharpCodeMatcher' cannot be used in netstandard 1.3");
} #endif
try
private string GetSourceForIsMatchWithString(string pattern, bool isMatchWithString) {
{ return (bool)result;
string template = isMatchWithString ? TemplateForIsMatchWithString : TemplateForIsMatchWithDynamic; }
catch
var stringBuilder = new StringBuilder(); {
throw new WireMockException($"Unable to cast result '{result}' to bool");
}
}
private string GetSourceForIsMatchWithString(string pattern, bool isMatchWithString)
{
string template = isMatchWithString ? TemplateForIsMatchWithString : TemplateForIsMatchWithDynamic;
var stringBuilder = new StringBuilder();
foreach (string @using in _usings) foreach (string @using in _usings)
{ {
stringBuilder.AppendLine($"using {@using};"); stringBuilder.AppendLine($"using {@using};");
} }
stringBuilder.AppendLine(); stringBuilder.AppendLine();
stringBuilder.AppendFormat(template, pattern); stringBuilder.AppendFormat(template, pattern);
return stringBuilder.ToString(); return stringBuilder.ToString();
} }
/// <inheritdoc cref="IStringMatcher.GetPatterns"/> /// <inheritdoc cref="IStringMatcher.GetPatterns"/>
public string[] GetPatterns() public AnyOf<string, StringPattern>[] GetPatterns()
{ {
return _patterns; return _patterns;
} }
/// <inheritdoc cref="IMatcher.Name"/> /// <inheritdoc cref="IMatcher.Name"/>
public string Name => "CSharpCodeMatcher"; public string Name => "CSharpCodeMatcher";
} }
} }

View File

@@ -26,34 +26,39 @@ namespace WireMock.Net.OpenApiParser.Mappers
_exampleValueGenerator = new ExampleValueGenerator(settings); _exampleValueGenerator = new ExampleValueGenerator(settings);
} }
public IEnumerable<MappingModel> ToMappingModels(OpenApiPaths paths) public IEnumerable<MappingModel> ToMappingModels(OpenApiPaths paths, IList<OpenApiServer> servers)
{ {
return paths.Select(p => MapPath(p.Key, p.Value)).SelectMany(x => x); return paths.Select(p => MapPath(p.Key, p.Value, servers)).SelectMany(x => x);
} }
private IEnumerable<MappingModel> MapPaths(OpenApiPaths paths) private IEnumerable<MappingModel> MapPaths(OpenApiPaths paths, IList<OpenApiServer> servers)
{ {
return paths.Select(p => MapPath(p.Key, p.Value)).SelectMany(x => x); return paths.Select(p => MapPath(p.Key, p.Value, servers)).SelectMany(x => x);
} }
private IEnumerable<MappingModel> MapPath(string path, OpenApiPathItem pathItem) private IEnumerable<MappingModel> MapPath(string path, OpenApiPathItem pathItem, IList<OpenApiServer> servers)
{ {
return pathItem.Operations.Select(o => MapOperationToMappingModel(path, o.Key.ToString().ToUpperInvariant(), o.Value)); return pathItem.Operations.Select(o => MapOperationToMappingModel(path, o.Key.ToString().ToUpperInvariant(), o.Value, servers));
} }
private MappingModel MapOperationToMappingModel(string path, string httpMethod, OpenApiOperation operation) private MappingModel MapOperationToMappingModel(string path, string httpMethod, OpenApiOperation operation, IList<OpenApiServer> servers)
{ {
var queryParameters = operation.Parameters.Where(p => p.In == ParameterLocation.Query); var queryParameters = operation.Parameters.Where(p => p.In == ParameterLocation.Query);
var pathParameters = operation.Parameters.Where(p => p.In == ParameterLocation.Path); var pathParameters = operation.Parameters.Where(p => p.In == ParameterLocation.Path);
var headers = operation.Parameters.Where(p => p.In == ParameterLocation.Header);
var response = operation.Responses.FirstOrDefault(); var response = operation.Responses.FirstOrDefault();
TryGetContent(response.Value?.Content, out OpenApiMediaType responseContent, out string responseContentType); TryGetContent(response.Value?.Content, out OpenApiMediaType responseContent, out string responseContentType);
var responseSchema = response.Value?.Content?.FirstOrDefault().Value?.Schema; var responseSchema = response.Value?.Content?.FirstOrDefault().Value?.Schema;
var responseExample = responseContent?.Example; var responseExample = responseContent?.Example;
var responseSchemaExample = responseContent?.Schema?.Example;
var body = responseExample != null ? MapOpenApiAnyToJToken(responseExample) : MapSchemaToObject(responseSchema); var body = responseExample != null ? MapOpenApiAnyToJToken(responseExample) :
responseSchemaExample != null ? MapOpenApiAnyToJToken(responseSchemaExample) :
MapSchemaToObject(responseSchema);
if (int.TryParse(response.Key, out var httpStatusCode)) if (!int.TryParse(response.Key, out var httpStatusCode))
{ {
httpStatusCode = 200; httpStatusCode = 200;
} }
@@ -64,8 +69,9 @@ namespace WireMock.Net.OpenApiParser.Mappers
Request = new RequestModel Request = new RequestModel
{ {
Methods = new[] { httpMethod }, Methods = new[] { httpMethod },
Path = MapPathWithParameters(path, pathParameters), Path = MapBasePath(servers) + MapPathWithParameters(path, pathParameters),
Params = MapQueryParameters(queryParameters) Params = MapQueryParameters(queryParameters),
Headers = MapRequestHeaders(headers)
}, },
Response = new ResponseModel Response = new ResponseModel
{ {
@@ -138,6 +144,11 @@ namespace WireMock.Net.OpenApiParser.Mappers
} }
} }
if (schema.AllOf.Count > 0)
{
jArray.Add(MapSchemaAllOfToObject(schema));
}
return jArray; return jArray;
case SchemaType.Boolean: case SchemaType.Boolean:
@@ -150,22 +161,17 @@ namespace WireMock.Net.OpenApiParser.Mappers
var propertyAsJObject = new JObject(); var propertyAsJObject = new JObject();
foreach (var schemaProperty in schema.Properties) foreach (var schemaProperty in schema.Properties)
{ {
string propertyName = schemaProperty.Key; propertyAsJObject.Add(MapPropertyAsJObject(schemaProperty.Value, schemaProperty.Key));
var openApiSchema = schemaProperty.Value; }
if (openApiSchema.GetSchemaType() == SchemaType.Object) if (schema.AllOf.Count > 0)
{
foreach (var property in schema.AllOf)
{ {
var mapped = MapSchemaToObject(schemaProperty.Value, schemaProperty.Key); foreach (var item in property.Properties)
if (mapped is JProperty jp)
{ {
propertyAsJObject.Add(jp); propertyAsJObject.Add(MapPropertyAsJObject(item.Value, item.Key));
} }
} }
else
{
bool propertyIsNullable = openApiSchema.Nullable || (openApiSchema.TryGetXNullable(out bool x) && x);
propertyAsJObject.Add(new JProperty(propertyName, _exampleValueGenerator.GetExampleValue(openApiSchema)));
}
} }
return name != null ? new JProperty(name, propertyAsJObject) : (JToken)propertyAsJObject; return name != null ? new JProperty(name, propertyAsJObject) : (JToken)propertyAsJObject;
@@ -175,6 +181,39 @@ namespace WireMock.Net.OpenApiParser.Mappers
} }
} }
private JObject MapSchemaAllOfToObject(OpenApiSchema schema)
{
var arrayItem = new JObject();
foreach (var property in schema.AllOf)
{
foreach (var item in property.Properties)
{
arrayItem.Add(MapPropertyAsJObject(item.Value, item.Key));
}
}
return arrayItem;
}
private object MapPropertyAsJObject(OpenApiSchema openApiSchema, string key)
{
if (openApiSchema.GetSchemaType() == SchemaType.Object || openApiSchema.GetSchemaType() == SchemaType.Array)
{
var mapped = MapSchemaToObject(openApiSchema, key);
if (mapped is JProperty jp)
{
return jp;
}
else
{
return new JProperty(key, mapped);
}
}
else
{
bool propertyIsNullable = openApiSchema.Nullable || (openApiSchema.TryGetXNullable(out bool x) && x);
return new JProperty(key, _exampleValueGenerator.GetExampleValue(openApiSchema));
}
}
private string MapPathWithParameters(string path, IEnumerable<OpenApiParameter> parameters) private string MapPathWithParameters(string path, IEnumerable<OpenApiParameter> parameters)
{ {
if (parameters == null) if (parameters == null)
@@ -191,6 +230,22 @@ namespace WireMock.Net.OpenApiParser.Mappers
return newPath; return newPath;
} }
private string MapBasePath(IList<OpenApiServer> servers)
{
if (servers == null || servers.Count == 0)
{
return string.Empty;
}
OpenApiServer server = servers.First();
Uri uriResult;
if (Uri.TryCreate(server.Url, UriKind.RelativeOrAbsolute, out uriResult))
{
return uriResult.IsAbsoluteUri ? uriResult.AbsolutePath : uriResult.ToString();
}
return string.Empty;
}
private JToken MapOpenApiAnyToJToken(IOpenApiAny any) private JToken MapOpenApiAnyToJToken(IOpenApiAny any)
{ {
if (any == null) if (any == null)
@@ -202,7 +257,14 @@ namespace WireMock.Net.OpenApiParser.Mappers
var writer = new OpenApiJsonWriter(outputString); var writer = new OpenApiJsonWriter(outputString);
any.Write(writer, OpenApiSpecVersion.OpenApi3_0); any.Write(writer, OpenApiSpecVersion.OpenApi3_0);
return JObject.Parse(outputString.ToString()); if (any.AnyType == AnyType.Array)
{
return JArray.Parse(outputString.ToString());
}
else
{
return JObject.Parse(outputString.ToString());
}
} }
private IDictionary<string, object> MapHeaders(string responseContentType, IDictionary<string, OpenApiHeader> headers) private IDictionary<string, object> MapHeaders(string responseContentType, IDictionary<string, OpenApiHeader> headers)
@@ -247,6 +309,26 @@ namespace WireMock.Net.OpenApiParser.Mappers
return list.Any() ? list : null; return list.Any() ? list : null;
} }
private IList<HeaderModel> MapRequestHeaders(IEnumerable<OpenApiParameter> headers)
{
var list = headers
.Select(qp => new HeaderModel
{
Name = qp.Name,
Matchers = new[]
{
new MatcherModel
{
Name = "ExactMatcher",
Pattern = GetDefaultValueAsStringForSchemaType(qp.Schema)
}
}
})
.ToList();
return list.Any() ? list : null;
}
private string GetDefaultValueAsStringForSchemaType(OpenApiSchema schema) private string GetDefaultValueAsStringForSchemaType(OpenApiSchema schema)
{ {
var value = _exampleValueGenerator.GetExampleValue(schema); var value = _exampleValueGenerator.GetExampleValue(schema);

View File

@@ -0,0 +1,52 @@
using System;
namespace WireMock.Net.OpenApiParser.Settings
{
/// <summary>
/// A interface defining the example values to use for the different types.
/// </summary>
public interface IWireMockOpenApiParserExampleValues
{
/// <summary>
/// An example value for a Boolean.
/// </summary>
bool Boolean { get; set; }
/// <summary>
/// An example value for an Integer.
/// </summary>
int Integer { get; set; }
/// <summary>
/// An example value for a Float.
/// </summary>
float Float { get; set; }
/// <summary>
/// An example value for a Double.
/// </summary>
double Double { get; set; }
/// <summary>
/// An example value for a Date.
/// </summary>
Func<DateTime> Date { get; set; }
/// <summary>
/// An example value for a DateTime.
/// </summary>
Func<DateTime> DateTime { get; set; }
/// <summary>
/// An example value for Bytes.
/// </summary>
byte[] Bytes { get; set; }
/// <summary>
/// An example value for a Object.
/// </summary>
object Object { get; set; }
/// <summary>
/// An example value for a String.
/// </summary>
string String { get; set; }
}
}

View File

@@ -0,0 +1,31 @@
using System;
using RandomDataGenerator.FieldOptions;
using RandomDataGenerator.Randomizers;
namespace WireMock.Net.OpenApiParser.Settings
{
/// <summary>
/// A class defining the random example values to use for the different types.
/// </summary>
public class WireMockOpenApiParserDynamicExampleValues : IWireMockOpenApiParserExampleValues
{
/// <inheritdoc />
public bool Boolean { get { return RandomizerFactory.GetRandomizer(new FieldOptionsBoolean()).Generate() ?? true; } set { } }
/// <inheritdoc />
public int Integer { get { return RandomizerFactory.GetRandomizer(new FieldOptionsInteger()).Generate() ?? 42; } set { } }
/// <inheritdoc />
public float Float { get { return RandomizerFactory.GetRandomizer(new FieldOptionsFloat()).Generate() ?? 4.2f; } set { } }
/// <inheritdoc />
public double Double { get { return RandomizerFactory.GetRandomizer(new FieldOptionsDouble()).Generate() ?? 4.2d; } set { } }
/// <inheritdoc />
public Func<DateTime> Date { get { return () => RandomizerFactory.GetRandomizer(new FieldOptionsDateTime()).Generate() ?? System.DateTime.UtcNow.Date; } set { } }
/// <inheritdoc />
public Func<DateTime> DateTime { get { return () => RandomizerFactory.GetRandomizer(new FieldOptionsDateTime()).Generate() ?? System.DateTime.UtcNow; } set { } }
/// <inheritdoc />
public byte[] Bytes { get { return RandomizerFactory.GetRandomizer(new FieldOptionsBytes()).Generate(); } set { } }
/// <inheritdoc />
public object Object { get; set; } = "example-object";
/// <inheritdoc />
public string String { get { return RandomizerFactory.GetRandomizer(new FieldOptionsTextRegex { Pattern = @"^[0-9]{2}[A-Z]{5}[0-9]{2}" }).Generate() ?? "example-string"; } set { } }
}
}

View File

@@ -5,26 +5,25 @@ namespace WireMock.Net.OpenApiParser.Settings
/// <summary> /// <summary>
/// A class defining the example values to use for the different types. /// A class defining the example values to use for the different types.
/// </summary> /// </summary>
public class WireMockOpenApiParserExampleValues public class WireMockOpenApiParserExampleValues : IWireMockOpenApiParserExampleValues
{ {
#pragma warning disable 1591 /// <inheritdoc />
public bool Boolean { get; set; } = true; public bool Boolean { get; set; } = true;
/// <inheritdoc />
public int Integer { get; set; } = 42; public int Integer { get; set; } = 42;
/// <inheritdoc />
public float Float { get; set; } = 4.2f; public float Float { get; set; } = 4.2f;
/// <inheritdoc />
public double Double { get; set; } = 4.2d; public double Double { get; set; } = 4.2d;
/// <inheritdoc />
public Func<DateTime> Date { get; set; } = () => System.DateTime.UtcNow.Date; public Func<DateTime> Date { get; set; } = () => System.DateTime.UtcNow.Date;
/// <inheritdoc />
public Func<DateTime> DateTime { get; set; } = () => System.DateTime.UtcNow; public Func<DateTime> DateTime { get; set; } = () => System.DateTime.UtcNow;
/// <inheritdoc />
public byte[] Bytes { get; set; } = { 48, 49, 50 }; public byte[] Bytes { get; set; } = { 48, 49, 50 };
/// <inheritdoc />
public object Object { get; set; } = "example-object"; public object Object { get; set; } = "example-object";
/// <inheritdoc />
public string String { get; set; } = "example-string"; public string String { get; set; } = "example-string";
#pragma warning restore 1591
} }
} }

View File

@@ -25,6 +25,11 @@ namespace WireMock.Net.OpenApiParser.Settings
/// <summary> /// <summary>
/// The example values to use /// The example values to use
/// </summary> /// </summary>
public WireMockOpenApiParserExampleValues ExampleValues { get; } = new WireMockOpenApiParserExampleValues(); public IWireMockOpenApiParserExampleValues ExampleValues { get; set; } = new WireMockOpenApiParserExampleValues();
/// <summary>
/// Are examples generated dynamically?
/// </summary>
public bool DynamicExamples { get; set; } = false;
} }
} }

View File

@@ -13,6 +13,14 @@ namespace WireMock.Net.OpenApiParser.Utils
public ExampleValueGenerator(WireMockOpenApiParserSettings settings) public ExampleValueGenerator(WireMockOpenApiParserSettings settings)
{ {
_settings = settings ?? throw new ArgumentNullException(nameof(settings)); _settings = settings ?? throw new ArgumentNullException(nameof(settings));
if (_settings.DynamicExamples)
{
_settings.ExampleValues = new WireMockOpenApiParserDynamicExampleValues();
}
else
{
_settings.ExampleValues = new WireMockOpenApiParserExampleValues();
}
} }
public object GetExampleValue(OpenApiSchema schema) public object GetExampleValue(OpenApiSchema schema)

View File

@@ -25,6 +25,7 @@
<PackageReference Include="RamlToOpenApiConverter" Version="0.1.1" /> <PackageReference Include="RamlToOpenApiConverter" Version="0.1.1" />
<PackageReference Include="JetBrains.Annotations" Version="2020.1.0" PrivateAssets="All" /> <PackageReference Include="JetBrains.Annotations" Version="2020.1.0" PrivateAssets="All" />
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All" /> <PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All" />
<PackageReference Include="RandomDataGenerator.Net" Version="1.0.13" />
<PackageReference Include="Stef.Validation" Version="0.0.3" /> <PackageReference Include="Stef.Validation" Version="0.0.3" />
</ItemGroup> </ItemGroup>

View File

@@ -62,7 +62,7 @@ namespace WireMock.Net.OpenApiParser
[PublicAPI] [PublicAPI]
public IEnumerable<MappingModel> FromDocument(OpenApiDocument openApiDocument, WireMockOpenApiParserSettings settings = null) public IEnumerable<MappingModel> FromDocument(OpenApiDocument openApiDocument, WireMockOpenApiParserSettings settings = null)
{ {
return new OpenApiPathsMapper(settings).ToMappingModels(openApiDocument.Paths); return new OpenApiPathsMapper(settings).ToMappingModels(openApiDocument.Paths, openApiDocument.Servers);
} }
} }
} }

View File

@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<Description>A RestClient using RestEase to access the admin interface.</Description> <Description>A RestClient using RestEase to access the admin interface.</Description>
@@ -31,7 +31,7 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All" /> <PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All" />
<PackageReference Include="RestEase" Version="1.4.10" /> <PackageReference Include="RestEase" Version="1.5.5" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View File

@@ -1,4 +1,5 @@
using System.Linq; using System.Linq;
using System.Reflection;
using JetBrains.Annotations; using JetBrains.Annotations;
using WireMock.Logging; using WireMock.Logging;
using WireMock.Server; using WireMock.Server;
@@ -12,6 +13,8 @@ namespace WireMock.Net.StandAlone
/// </summary> /// </summary>
public static class StandAloneApp public static class StandAloneApp
{ {
private static readonly string Version = typeof(StandAloneApp).GetTypeInfo().Assembly.GetName().Version.ToString();
/// <summary> /// <summary>
/// Start WireMock.Net standalone Server based on the IWireMockServerSettings. /// Start WireMock.Net standalone Server based on the IWireMockServerSettings.
/// </summary> /// </summary>
@@ -23,7 +26,8 @@ namespace WireMock.Net.StandAlone
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("Version [{0}]", Version);
settings.Logger?.Info("Server listening at {0}", string.Join(",", server.Urls));
return server; return server;
} }
@@ -40,7 +44,8 @@ namespace WireMock.Net.StandAlone
if (WireMockServerSettingsParser.TryParseArguments(args, out var settings, logger)) if (WireMockServerSettingsParser.TryParseArguments(args, out var settings, logger))
{ {
settings.Logger?.Debug("WireMock.Net server arguments [{0}]", string.Join(", ", args.Select(a => $"'{a}'"))); settings.Logger?.Info("Version [{0}]", Version);
settings.Logger?.Debug("Server arguments [{0}]", string.Join(", ", args.Select(a => $"'{a}'")));
return Start(settings); return Start(settings);
} }
@@ -61,7 +66,8 @@ namespace WireMock.Net.StandAlone
if (WireMockServerSettingsParser.TryParseArguments(args, out var settings, logger)) if (WireMockServerSettingsParser.TryParseArguments(args, out var settings, logger))
{ {
settings.Logger?.Debug("WireMock.Net server arguments [{0}]", string.Join(", ", args.Select(a => $"'{a}'"))); settings.Logger?.Info("Version [{0}]", Version);
settings.Logger?.Debug("Server arguments [{0}]", string.Join(", ", args.Select(a => $"'{a}'")));
server = Start(settings); server = Start(settings);
return true; return true;

View File

@@ -0,0 +1,71 @@
#if !NETSTANDARD1_3
using System.Globalization;
using System.IdentityModel.Tokens.Jwt;
using System.Text.RegularExpressions;
using AnyOfTypes;
using Microsoft.IdentityModel.Protocols;
using Microsoft.IdentityModel.Protocols.OpenIdConnect;
using Microsoft.IdentityModel.Tokens;
using WireMock.Matchers;
using WireMock.Models;
namespace WireMock.Authentication
{
/// <summary>
/// https://www.c-sharpcorner.com/article/how-to-validate-azure-ad-token-using-console-application/
/// https://stackoverflow.com/questions/38684865/validation-of-an-azure-ad-bearer-token-in-a-console-application
/// </summary>
internal class AzureADAuthenticationMatcher : IStringMatcher
{
private const string BearerPrefix = "Bearer ";
private readonly string _audience;
private readonly string _stsDiscoveryEndpoint;
public AzureADAuthenticationMatcher(string tenant, string audience)
{
_audience = audience;
_stsDiscoveryEndpoint = string.Format(CultureInfo.InvariantCulture, "https://login.microsoftonline.com/{0}/.well-known/openid-configuration", tenant);
}
public string Name => nameof(AzureADAuthenticationMatcher);
public MatchBehaviour MatchBehaviour => MatchBehaviour.AcceptOnMatch;
public bool ThrowException => false;
public AnyOf<string, StringPattern>[] GetPatterns()
{
return new AnyOf<string, StringPattern>[0];
}
public double IsMatch(string input)
{
var token = Regex.Replace(input, BearerPrefix, string.Empty, RegexOptions.IgnoreCase);
try
{
var configManager = new ConfigurationManager<OpenIdConnectConfiguration>(_stsDiscoveryEndpoint, new OpenIdConnectConfigurationRetriever());
var config = configManager.GetConfigurationAsync().GetAwaiter().GetResult();
var validationParameters = new TokenValidationParameters
{
ValidAudience = _audience,
ValidIssuer = config.Issuer,
IssuerSigningKeys = config.SigningKeys,
ValidateLifetime = true
};
// Throws an Exception as the token is invalid (expired, invalid-formatted, etc.)
new JwtSecurityTokenHandler().ValidateToken(token, validationParameters, out var _);
return MatchScores.Perfect;
}
catch
{
return MatchScores.Mismatch;
}
}
}
}
#endif

View File

@@ -0,0 +1,20 @@
using System;
using System.Text;
using WireMock.Matchers;
namespace WireMock.Authentication
{
internal class BasicAuthenticationMatcher : RegexMatcher
{
public BasicAuthenticationMatcher(string username, string password) : base(BuildPattern(username, password))
{
}
public override string Name => nameof(BasicAuthenticationMatcher);
private static string BuildPattern(string username, string password)
{
return "^(?i)BASIC " + Convert.ToBase64String(Encoding.GetEncoding("ISO-8859-1").GetBytes(username + ":" + password)) + "$";
}
}
}

View File

@@ -0,0 +1,26 @@
using System.Collections.Generic;
using System.Linq;
using AnyOfTypes;
using JetBrains.Annotations;
using WireMock.Models;
namespace WireMock.Extensions
{
internal static class AnyOfExtensions
{
public static string GetPattern([NotNull] this AnyOf<string, StringPattern> value)
{
return value.IsFirst ? value.First : value.Second.Pattern;
}
public static AnyOf<string, StringPattern>[] ToAnyOfPatterns([NotNull] this IEnumerable<string> patterns)
{
return patterns.Select(p => p.ToAnyOfPattern()).ToArray();
}
public static AnyOf<string, StringPattern> ToAnyOfPattern([CanBeNull] this string pattern)
{
return new AnyOf<string, StringPattern>(pattern);
}
}
}

View File

@@ -0,0 +1,35 @@
using System;
using JetBrains.Annotations;
using WireMock.Models;
namespace WireMock.Extensions
{
internal static class TimeSettingsExtensions
{
public static bool IsValid([CanBeNull] this ITimeSettings settings)
{
if (settings == null)
{
return true;
}
var now = DateTime.Now;
var start = settings.Start != null ? settings.Start.Value : now;
DateTime end;
if (settings.End != null)
{
end = settings.End.Value;
}
else if (settings.TTL != null)
{
end = start.AddSeconds(settings.TTL.Value);
}
else
{
end = DateTime.MaxValue;
}
return now >= start && now <= end;
}
}
}

View File

@@ -1,4 +1,4 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using WireMock.Util; using WireMock.Util;
using WireMock.Validation; using WireMock.Validation;
@@ -130,6 +130,12 @@ namespace WireMock.Handlers
return File.ReadAllBytes(AdjustPath(filename)); return File.ReadAllBytes(AdjustPath(filename));
} }
/// <inheritdoc cref="IFileSystemHandler.ReadFileAsString"/>
public string ReadFileAsString(string filename)
{
return File.ReadAllText(AdjustPath(Check.NotNullOrEmpty(filename, nameof(filename))));
}
/// <summary> /// <summary>
/// Adjusts the path to the MappingFolder. /// Adjusts the path to the MappingFolder.
/// </summary> /// </summary>
@@ -140,4 +146,4 @@ namespace WireMock.Handlers
return Path.Combine(GetMappingFolder(), filename); return Path.Combine(GetMappingFolder(), filename);
} }
} }
} }

View File

@@ -1,4 +1,4 @@
using JetBrains.Annotations; using JetBrains.Annotations;
using System; using System;
using System.Threading.Tasks; using System.Threading.Tasks;
using WireMock.Matchers.Request; using WireMock.Matchers.Request;
@@ -18,6 +18,11 @@ namespace WireMock
/// </summary> /// </summary>
Guid Guid { get; } Guid Guid { get; }
/// <summary>
/// Gets the TimeSettings (Start, End and TTL).
/// </summary>
ITimeSettings TimeSettings { get; }
/// <summary> /// <summary>
/// Gets the unique title. /// Gets the unique title.
/// </summary> /// </summary>

View File

@@ -1,4 +1,4 @@
using System; using System;
using System.Threading.Tasks; using System.Threading.Tasks;
using JetBrains.Annotations; using JetBrains.Annotations;
using WireMock.Matchers.Request; using WireMock.Matchers.Request;
@@ -13,51 +13,54 @@ namespace WireMock
/// </summary> /// </summary>
public class Mapping : IMapping public class Mapping : IMapping
{ {
/// <inheritdoc cref="IMapping.Guid" /> /// <inheritdoc />
public Guid Guid { get; } public Guid Guid { get; }
/// <inheritdoc cref="IMapping.Title" /> /// <inheritdoc />
public string Title { get; } public string Title { get; }
/// <inheritdoc cref="IMapping.Path" /> /// <inheritdoc />
public string Path { get; set; } public string Path { get; set; }
/// <inheritdoc cref="IMapping.Priority" /> /// <inheritdoc />
public int Priority { get; } public int Priority { get; }
/// <inheritdoc cref="IMapping.Scenario" /> /// <inheritdoc />
public string Scenario { get; } public string Scenario { get; }
/// <inheritdoc cref="IMapping.ExecutionConditionState" /> /// <inheritdoc />
public string ExecutionConditionState { get; } public string ExecutionConditionState { get; }
/// <inheritdoc cref="IMapping.NextState" /> /// <inheritdoc />
public string NextState { get; } public string NextState { get; }
/// <inheritdoc cref="IMapping.StateTimes" /> /// <inheritdoc />
public int? StateTimes { get; } public int? StateTimes { get; }
/// <inheritdoc cref="IMapping.RequestMatcher" /> /// <inheritdoc />
public IRequestMatcher RequestMatcher { get; } public IRequestMatcher RequestMatcher { get; }
/// <inheritdoc cref="IMapping.Provider" /> /// <inheritdoc />
public IResponseProvider Provider { get; } public IResponseProvider Provider { get; }
/// <inheritdoc cref="IMapping.Settings" /> /// <inheritdoc />
public IWireMockServerSettings Settings { get; } public IWireMockServerSettings Settings { get; }
/// <inheritdoc cref="IMapping.IsStartState" /> /// <inheritdoc />
public bool IsStartState => Scenario == null || Scenario != null && NextState != null && ExecutionConditionState == null; public bool IsStartState => Scenario == null || Scenario != null && NextState != null && ExecutionConditionState == null;
/// <inheritdoc cref="IMapping.IsAdminInterface" /> /// <inheritdoc />
public bool IsAdminInterface => Provider is DynamicResponseProvider || Provider is DynamicAsyncResponseProvider || Provider is ProxyAsyncResponseProvider; public bool IsAdminInterface => Provider is DynamicResponseProvider || Provider is DynamicAsyncResponseProvider || Provider is ProxyAsyncResponseProvider;
/// <inheritdoc cref="IMapping.LogMapping" /> /// <inheritdoc />
public bool LogMapping => !(Provider is DynamicResponseProvider || Provider is DynamicAsyncResponseProvider); public bool LogMapping => !(Provider is DynamicResponseProvider || Provider is DynamicAsyncResponseProvider);
/// <inheritdoc cref="IMapping.Webhooks" /> /// <inheritdoc />
public IWebhook[] Webhooks { get; } public IWebhook[] Webhooks { get; }
/// <inheritdoc />
public ITimeSettings TimeSettings { get; }
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="Mapping"/> class. /// Initializes a new instance of the <see cref="Mapping"/> class.
/// </summary> /// </summary>
@@ -73,6 +76,7 @@ namespace WireMock
/// <param name="nextState">The next state which will occur after the current mapping execution. [Optional]</param> /// <param name="nextState">The next state which will occur after the current mapping execution. [Optional]</param>
/// <param name="stateTimes">Only when the current state is executed this number, the next state which will occur. [Optional]</param> /// <param name="stateTimes">Only when the current state is executed this number, the next state which will occur. [Optional]</param>
/// <param name="webhooks">The Webhooks. [Optional]</param> /// <param name="webhooks">The Webhooks. [Optional]</param>
/// <param name="timeSettings">The TimeSettings. [Optional]</param>
public Mapping( public Mapping(
Guid guid, Guid guid,
[CanBeNull] string title, [CanBeNull] string title,
@@ -85,7 +89,8 @@ namespace WireMock
[CanBeNull] string executionConditionState, [CanBeNull] string executionConditionState,
[CanBeNull] string nextState, [CanBeNull] string nextState,
[CanBeNull] int? stateTimes, [CanBeNull] int? stateTimes,
[CanBeNull] IWebhook[] webhooks) [CanBeNull] IWebhook[] webhooks,
[CanBeNull] ITimeSettings timeSettings)
{ {
Guid = guid; Guid = guid;
Title = title; Title = title;
@@ -99,6 +104,7 @@ namespace WireMock
NextState = nextState; NextState = nextState;
StateTimes = stateTimes; StateTimes = stateTimes;
Webhooks = webhooks; Webhooks = webhooks;
TimeSettings = timeSettings;
} }
/// <inheritdoc cref="IMapping.ProvideResponseAsync" /> /// <inheritdoc cref="IMapping.ProvideResponseAsync" />

View File

@@ -0,0 +1,89 @@
using System.Collections.Generic;
using System.Linq;
using JetBrains.Annotations;
using Newtonsoft.Json.Linq;
namespace WireMock.Matchers
{
/// <summary>
/// Generic AbstractJsonPartialMatcher
/// </summary>
public abstract class AbstractJsonPartialMatcher : JsonMatcher
{
/// <summary>
/// Initializes a new instance of the <see cref="AbstractJsonPartialMatcher"/> class.
/// </summary>
/// <param name="value">The string value to check for equality.</param>
/// <param name="ignoreCase">Ignore the case from the PropertyName and PropertyValue (string only).</param>
/// <param name="throwException">Throw an exception when the internal matching fails because of invalid input.</param>
protected AbstractJsonPartialMatcher([NotNull] string value, bool ignoreCase = false, bool throwException = false)
: base(value, ignoreCase, throwException)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="AbstractJsonPartialMatcher"/> class.
/// </summary>
/// <param name="value">The object value to check for equality.</param>
/// <param name="ignoreCase">Ignore the case from the PropertyName and PropertyValue (string only).</param>
/// <param name="throwException">Throw an exception when the internal matching fails because of invalid input.</param>
protected AbstractJsonPartialMatcher([NotNull] object value, bool ignoreCase = false, bool throwException = false)
: base(value, ignoreCase, throwException)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="AbstractJsonPartialMatcher"/> class.
/// </summary>
/// <param name="matchBehaviour">The match behaviour.</param>
/// <param name="value">The value to check for equality.</param>
/// <param name="ignoreCase">Ignore the case from the PropertyName and PropertyValue (string only).</param>
/// <param name="throwException">Throw an exception when the internal matching fails because of invalid input.</param>
protected AbstractJsonPartialMatcher(MatchBehaviour matchBehaviour, [NotNull] object value, bool ignoreCase = false, bool throwException = false)
: base(matchBehaviour, value, ignoreCase, throwException)
{
}
/// <inheritdoc />
protected override bool IsMatch(JToken value, JToken input)
{
if (value == null || value == input)
{
return true;
}
if (input == null || value.Type != input.Type)
{
return false;
}
switch (value.Type)
{
case JTokenType.Object:
var nestedValues = value.ToObject<Dictionary<string, JToken>>();
return nestedValues?.Any() != true ||
nestedValues.All(pair => IsMatch(pair.Value, input.SelectToken(pair.Key)));
case JTokenType.Array:
var valuesArray = value.ToObject<JToken[]>();
var tokenArray = input.ToObject<JToken[]>();
if (valuesArray?.Any() != true)
{
return true;
}
return tokenArray?.Any() == true &&
valuesArray.All(subFilter => tokenArray.Any(subToken => IsMatch(subFilter, subToken)));
default:
return IsMatch(value.ToString(), input.ToString());
}
}
/// <summary>
/// Check if two strings are a match (matching can be done exact or wildcard)
/// </summary>
protected abstract bool IsMatch(string value, string input);
}
}

View File

@@ -1,5 +1,7 @@
using System.Net.Http.Headers; using System.Net.Http.Headers;
using AnyOfTypes;
using JetBrains.Annotations; using JetBrains.Annotations;
using WireMock.Models;
namespace WireMock.Matchers namespace WireMock.Matchers
{ {
@@ -9,14 +11,14 @@ namespace WireMock.Matchers
/// <seealso cref="RegexMatcher" /> /// <seealso cref="RegexMatcher" />
public class ContentTypeMatcher : WildcardMatcher public class ContentTypeMatcher : WildcardMatcher
{ {
private readonly string[] _patterns; private readonly AnyOf<string, StringPattern>[] _patterns;
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="ContentTypeMatcher"/> class. /// Initializes a new instance of the <see cref="ContentTypeMatcher"/> class.
/// </summary> /// </summary>
/// <param name="pattern">The pattern.</param> /// <param name="pattern">The pattern.</param>
/// <param name="ignoreCase">IgnoreCase (default false)</param> /// <param name="ignoreCase">IgnoreCase (default false)</param>
public ContentTypeMatcher([NotNull] string pattern, bool ignoreCase = false) : this(new[] { pattern }, ignoreCase) public ContentTypeMatcher([NotNull] AnyOf<string, StringPattern> pattern, bool ignoreCase = false) : this(new[] { pattern }, ignoreCase)
{ {
} }
@@ -26,7 +28,7 @@ namespace WireMock.Matchers
/// <param name="matchBehaviour">The match behaviour.</param> /// <param name="matchBehaviour">The match behaviour.</param>
/// <param name="pattern">The pattern.</param> /// <param name="pattern">The pattern.</param>
/// <param name="ignoreCase">IgnoreCase (default false)</param> /// <param name="ignoreCase">IgnoreCase (default false)</param>
public ContentTypeMatcher(MatchBehaviour matchBehaviour, [NotNull] string pattern, bool ignoreCase = false) : this(matchBehaviour, new[] { pattern }, ignoreCase) public ContentTypeMatcher(MatchBehaviour matchBehaviour, [NotNull] AnyOf<string, StringPattern> pattern, bool ignoreCase = false) : this(matchBehaviour, new[] { pattern }, ignoreCase)
{ {
} }
@@ -35,7 +37,7 @@ namespace WireMock.Matchers
/// </summary> /// </summary>
/// <param name="patterns">The patterns.</param> /// <param name="patterns">The patterns.</param>
/// <param name="ignoreCase">IgnoreCase (default false)</param> /// <param name="ignoreCase">IgnoreCase (default false)</param>
public ContentTypeMatcher([NotNull] string[] patterns, bool ignoreCase = false) : this(MatchBehaviour.AcceptOnMatch, patterns, ignoreCase) public ContentTypeMatcher([NotNull] AnyOf<string, StringPattern>[] patterns, bool ignoreCase = false) : this(MatchBehaviour.AcceptOnMatch, patterns, ignoreCase)
{ {
} }
@@ -46,7 +48,7 @@ namespace WireMock.Matchers
/// <param name="patterns">The patterns.</param> /// <param name="patterns">The patterns.</param>
/// <param name="ignoreCase">IgnoreCase (default false)</param> /// <param name="ignoreCase">IgnoreCase (default false)</param>
/// <param name="throwException">Throw an exception when the internal matching fails because of invalid input.</param> /// <param name="throwException">Throw an exception when the internal matching fails because of invalid input.</param>
public ContentTypeMatcher(MatchBehaviour matchBehaviour, [NotNull] string[] patterns, bool ignoreCase = false, bool throwException = false) : public ContentTypeMatcher(MatchBehaviour matchBehaviour, [NotNull] AnyOf<string, StringPattern>[] patterns, bool ignoreCase = false, bool throwException = false) :
base(matchBehaviour, patterns, ignoreCase, throwException) base(matchBehaviour, patterns, ignoreCase, throwException)
{ {
_patterns = patterns; _patterns = patterns;
@@ -64,7 +66,7 @@ namespace WireMock.Matchers
} }
/// <inheritdoc cref="IStringMatcher.GetPatterns"/> /// <inheritdoc cref="IStringMatcher.GetPatterns"/>
public override string[] GetPatterns() public override AnyOf<string, StringPattern>[] GetPatterns()
{ {
return _patterns; return _patterns;
} }

View File

@@ -1,5 +1,8 @@
using System.Linq; using System.Linq;
using AnyOfTypes;
using JetBrains.Annotations; using JetBrains.Annotations;
using WireMock.Extensions;
using WireMock.Models;
using WireMock.Validation; using WireMock.Validation;
namespace WireMock.Matchers namespace WireMock.Matchers
@@ -10,7 +13,7 @@ namespace WireMock.Matchers
/// <seealso cref="IStringMatcher" /> /// <seealso cref="IStringMatcher" />
public class ExactMatcher : IStringMatcher public class ExactMatcher : IStringMatcher
{ {
private readonly string[] _values; private readonly AnyOf<string, StringPattern>[] _values;
/// <inheritdoc cref="IMatcher.MatchBehaviour"/> /// <inheritdoc cref="IMatcher.MatchBehaviour"/>
public MatchBehaviour MatchBehaviour { get; } public MatchBehaviour MatchBehaviour { get; }
@@ -22,7 +25,7 @@ namespace WireMock.Matchers
/// Initializes a new instance of the <see cref="ExactMatcher"/> class. /// Initializes a new instance of the <see cref="ExactMatcher"/> class.
/// </summary> /// </summary>
/// <param name="values">The values.</param> /// <param name="values">The values.</param>
public ExactMatcher([NotNull] params string[] values) : this(MatchBehaviour.AcceptOnMatch, false, values) public ExactMatcher([NotNull] params AnyOf<string, StringPattern>[] values) : this(MatchBehaviour.AcceptOnMatch, false, values)
{ {
} }
@@ -32,9 +35,9 @@ namespace WireMock.Matchers
/// <param name="matchBehaviour">The match behaviour.</param> /// <param name="matchBehaviour">The match behaviour.</param>
/// <param name="throwException">Throw an exception when the internal matching fails because of invalid input.</param> /// <param name="throwException">Throw an exception when the internal matching fails because of invalid input.</param>
/// <param name="values">The values.</param> /// <param name="values">The values.</param>
public ExactMatcher(MatchBehaviour matchBehaviour, bool throwException = false, [NotNull] params string[] values) public ExactMatcher(MatchBehaviour matchBehaviour, bool throwException = false, [NotNull] params AnyOf<string, StringPattern>[] values)
{ {
Check.HasNoNulls(values, nameof(values)); Check.NotNull(values, nameof(values));
MatchBehaviour = matchBehaviour; MatchBehaviour = matchBehaviour;
ThrowException = throwException; ThrowException = throwException;
@@ -46,14 +49,14 @@ namespace WireMock.Matchers
{ {
if (_values.Length == 1) if (_values.Length == 1)
{ {
return MatchBehaviourHelper.Convert(MatchBehaviour, MatchScores.ToScore(_values[0] == input)); return MatchBehaviourHelper.Convert(MatchBehaviour, MatchScores.ToScore(_values[0].GetPattern() == input));
} }
return MatchBehaviourHelper.Convert(MatchBehaviour, MatchScores.ToScore(_values.Contains(input))); return MatchBehaviourHelper.Convert(MatchBehaviour, MatchScores.ToScore(_values.Select(v => v.GetPattern()).Contains(input)));
} }
/// <inheritdoc cref="IStringMatcher.GetPatterns"/> /// <inheritdoc cref="IStringMatcher.GetPatterns"/>
public string[] GetPatterns() public AnyOf<string, StringPattern>[] GetPatterns()
{ {
return _values; return _values;
} }

View File

@@ -1,4 +1,7 @@
namespace WireMock.Matchers using AnyOfTypes;
using WireMock.Models;
namespace WireMock.Matchers
{ {
/// <summary> /// <summary>
/// IStringMatcher /// IStringMatcher
@@ -17,6 +20,6 @@
/// Gets the patterns. /// Gets the patterns.
/// </summary> /// </summary>
/// <returns>Patterns</returns> /// <returns>Patterns</returns>
string[] GetPatterns(); AnyOf<string, StringPattern>[] GetPatterns();
} }
} }

View File

@@ -1,15 +1,15 @@
namespace WireMock.Matchers namespace WireMock.Matchers
{ {
/// <summary> /// <summary>
/// IValueMatcher /// IValueMatcher
/// </summary> /// </summary>
/// <seealso cref="IObjectMatcher" /> /// <seealso cref="IObjectMatcher" />
public interface IValueMatcher: IObjectMatcher public interface IValueMatcher : IObjectMatcher
{ {
/// <summary> /// <summary>
/// Gets the value (can be a string or an object). /// Gets the value (can be a string or an object).
/// </summary> /// </summary>
/// <returns>Value</returns> /// <returns>Value</returns>
object Value { get; } object Value { get; }
} }
} }

View File

@@ -1,7 +1,10 @@
using System.Linq; using System.Linq;
using AnyOfTypes;
using JetBrains.Annotations; using JetBrains.Annotations;
using Newtonsoft.Json; using Newtonsoft.Json;
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq;
using WireMock.Extensions;
using WireMock.Models;
using WireMock.Validation; using WireMock.Validation;
namespace WireMock.Matchers namespace WireMock.Matchers
@@ -13,7 +16,7 @@ namespace WireMock.Matchers
/// <seealso cref="IObjectMatcher" /> /// <seealso cref="IObjectMatcher" />
public class JsonPathMatcher : IStringMatcher, IObjectMatcher public class JsonPathMatcher : IStringMatcher, IObjectMatcher
{ {
private readonly string[] _patterns; private readonly AnyOf<string, StringPattern>[] _patterns;
/// <inheritdoc cref="IMatcher.MatchBehaviour"/> /// <inheritdoc cref="IMatcher.MatchBehaviour"/>
public MatchBehaviour MatchBehaviour { get; } public MatchBehaviour MatchBehaviour { get; }
@@ -25,7 +28,15 @@ namespace WireMock.Matchers
/// Initializes a new instance of the <see cref="JsonPathMatcher"/> class. /// Initializes a new instance of the <see cref="JsonPathMatcher"/> class.
/// </summary> /// </summary>
/// <param name="patterns">The patterns.</param> /// <param name="patterns">The patterns.</param>
public JsonPathMatcher([NotNull] params string[] patterns) : this(MatchBehaviour.AcceptOnMatch, false, patterns) public JsonPathMatcher([NotNull] params string[] patterns) : this(MatchBehaviour.AcceptOnMatch, false, patterns.ToAnyOfPatterns())
{
}
/// <summary>
/// Initializes a new instance of the <see cref="JsonPathMatcher"/> class.
/// </summary>
/// <param name="patterns">The patterns.</param>
public JsonPathMatcher([NotNull] params AnyOf<string, StringPattern>[] patterns) : this(MatchBehaviour.AcceptOnMatch, false, patterns)
{ {
} }
@@ -35,7 +46,7 @@ namespace WireMock.Matchers
/// <param name="matchBehaviour">The match behaviour.</param> /// <param name="matchBehaviour">The match behaviour.</param>
/// <param name="throwException">Throw an exception when the internal matching fails because of invalid input.</param> /// <param name="throwException">Throw an exception when the internal matching fails because of invalid input.</param>
/// <param name="patterns">The patterns.</param> /// <param name="patterns">The patterns.</param>
public JsonPathMatcher(MatchBehaviour matchBehaviour, bool throwException = false, [NotNull] params string[] patterns) public JsonPathMatcher(MatchBehaviour matchBehaviour, bool throwException = false, [NotNull] params AnyOf<string, StringPattern>[] patterns)
{ {
Check.NotNull(patterns, nameof(patterns)); Check.NotNull(patterns, nameof(patterns));
@@ -94,7 +105,7 @@ namespace WireMock.Matchers
} }
/// <inheritdoc cref="IStringMatcher.GetPatterns"/> /// <inheritdoc cref="IStringMatcher.GetPatterns"/>
public string[] GetPatterns() public AnyOf<string, StringPattern>[] GetPatterns()
{ {
return _patterns; return _patterns;
} }
@@ -104,7 +115,7 @@ namespace WireMock.Matchers
private double IsMatch(JToken jtoken) private double IsMatch(JToken jtoken)
{ {
return MatchScores.ToScore(_patterns.Select(pattern => jtoken.SelectToken(pattern) != null)); return MatchScores.ToScore(_patterns.Select(pattern => jtoken.SelectToken(pattern.GetPattern()) != null));
} }
} }
} }

View File

@@ -1,7 +1,10 @@
using DevLab.JmesPath; using AnyOfTypes;
using DevLab.JmesPath;
using JetBrains.Annotations; using JetBrains.Annotations;
using Newtonsoft.Json; using Newtonsoft.Json;
using System.Linq; using System.Linq;
using WireMock.Extensions;
using WireMock.Models;
using WireMock.Validation; using WireMock.Validation;
namespace WireMock.Matchers namespace WireMock.Matchers
@@ -11,7 +14,7 @@ namespace WireMock.Matchers
/// </summary> /// </summary>
public class JmesPathMatcher : IStringMatcher, IObjectMatcher public class JmesPathMatcher : IStringMatcher, IObjectMatcher
{ {
private readonly string[] _patterns; private readonly AnyOf<string, StringPattern>[] _patterns;
/// <inheritdoc cref="IMatcher.MatchBehaviour"/> /// <inheritdoc cref="IMatcher.MatchBehaviour"/>
public MatchBehaviour MatchBehaviour { get; } public MatchBehaviour MatchBehaviour { get; }
@@ -23,7 +26,15 @@ namespace WireMock.Matchers
/// Initializes a new instance of the <see cref="JmesPathMatcher"/> class. /// Initializes a new instance of the <see cref="JmesPathMatcher"/> class.
/// </summary> /// </summary>
/// <param name="patterns">The patterns.</param> /// <param name="patterns">The patterns.</param>
public JmesPathMatcher([NotNull] params string[] patterns) : this(MatchBehaviour.AcceptOnMatch, false, patterns) public JmesPathMatcher([NotNull] params string[] patterns) : this(MatchBehaviour.AcceptOnMatch, false, patterns.ToAnyOfPatterns())
{
}
/// <summary>
/// Initializes a new instance of the <see cref="JmesPathMatcher"/> class.
/// </summary>
/// <param name="patterns">The patterns.</param>
public JmesPathMatcher([NotNull] params AnyOf<string, StringPattern>[] patterns) : this(MatchBehaviour.AcceptOnMatch, false, patterns)
{ {
} }
@@ -32,7 +43,7 @@ namespace WireMock.Matchers
/// </summary> /// </summary>
/// <param name="throwException">Throw an exception when the internal matching fails because of invalid input.</param> /// <param name="throwException">Throw an exception when the internal matching fails because of invalid input.</param>
/// <param name="patterns">The patterns.</param> /// <param name="patterns">The patterns.</param>
public JmesPathMatcher(bool throwException = false, [NotNull] params string[] patterns) : this(MatchBehaviour.AcceptOnMatch, throwException, patterns) public JmesPathMatcher(bool throwException = false, [NotNull] params AnyOf<string, StringPattern>[] patterns) : this(MatchBehaviour.AcceptOnMatch, throwException, patterns)
{ {
} }
@@ -42,7 +53,7 @@ namespace WireMock.Matchers
/// <param name="matchBehaviour">The match behaviour.</param> /// <param name="matchBehaviour">The match behaviour.</param>
/// <param name="throwException">Throw an exception when the internal matching fails because of invalid input.</param> /// <param name="throwException">Throw an exception when the internal matching fails because of invalid input.</param>
/// <param name="patterns">The patterns.</param> /// <param name="patterns">The patterns.</param>
public JmesPathMatcher(MatchBehaviour matchBehaviour, bool throwException = false, [NotNull] params string[] patterns) public JmesPathMatcher(MatchBehaviour matchBehaviour, bool throwException = false, [NotNull] params AnyOf<string, StringPattern>[] patterns)
{ {
Check.NotNull(patterns, nameof(patterns)); Check.NotNull(patterns, nameof(patterns));
@@ -59,7 +70,7 @@ namespace WireMock.Matchers
{ {
try try
{ {
match = MatchScores.ToScore(_patterns.Select(pattern => bool.Parse(new JmesPath().Transform(input, pattern)))); match = MatchScores.ToScore(_patterns.Select(pattern => bool.Parse(new JmesPath().Transform(input, pattern.GetPattern()))));
} }
catch (JsonException) catch (JsonException)
{ {
@@ -89,7 +100,7 @@ namespace WireMock.Matchers
} }
/// <inheritdoc cref="IStringMatcher.GetPatterns"/> /// <inheritdoc cref="IStringMatcher.GetPatterns"/>
public string[] GetPatterns() public AnyOf<string, StringPattern>[] GetPatterns()
{ {
return _patterns; return _patterns;
} }

View File

@@ -1,87 +1,38 @@
using System.Collections.Generic;
using System.Linq;
using JetBrains.Annotations; using JetBrains.Annotations;
using Newtonsoft.Json.Linq;
namespace WireMock.Matchers namespace WireMock.Matchers
{ {
/// <summary> /// <summary>
/// JsonPartialMatcher /// JsonPartialMatcher
/// </summary> /// </summary>
public class JsonPartialMatcher : JsonMatcher public class JsonPartialMatcher : AbstractJsonPartialMatcher
{ {
/// <inheritdoc cref="IMatcher.Name"/> /// <inheritdoc />
public override string Name => "JsonPartialMatcher"; public override string Name => nameof(JsonPartialMatcher);
/// <summary> /// <inheritdoc />
/// Initializes a new instance of the <see cref="JsonPartialMatcher"/> class. public JsonPartialMatcher([NotNull] string value, bool ignoreCase = false, bool throwException = false)
/// </summary>
/// <param name="value">The string value to check for equality.</param>
/// <param name="ignoreCase">Ignore the case from the PropertyName and PropertyValue (string only).</param>
/// <param name="throwException">Throw an exception when the internal matching fails because of invalid input.</param>
public JsonPartialMatcher([NotNull] string value, bool ignoreCase = false, bool throwException = false)
: base(value, ignoreCase, throwException) : base(value, ignoreCase, throwException)
{ {
} }
/// <summary> /// <inheritdoc />
/// Initializes a new instance of the <see cref="JsonPartialMatcher"/> class. public JsonPartialMatcher([NotNull] object value, bool ignoreCase = false, bool throwException = false)
/// </summary>
/// <param name="value">The object value to check for equality.</param>
/// <param name="ignoreCase">Ignore the case from the PropertyName and PropertyValue (string only).</param>
/// <param name="throwException">Throw an exception when the internal matching fails because of invalid input.</param>
public JsonPartialMatcher([NotNull] object value, bool ignoreCase = false, bool throwException = false)
: base(value, ignoreCase, throwException) : base(value, ignoreCase, throwException)
{ {
} }
/// <summary> /// <inheritdoc />
/// Initializes a new instance of the <see cref="JsonPartialMatcher"/> class. public JsonPartialMatcher(MatchBehaviour matchBehaviour, [NotNull] object value, bool ignoreCase = false, bool throwException = false)
/// </summary>
/// <param name="matchBehaviour">The match behaviour.</param>
/// <param name="value">The value to check for equality.</param>
/// <param name="ignoreCase">Ignore the case from the PropertyName and PropertyValue (string only).</param>
/// <param name="throwException">Throw an exception when the internal matching fails because of invalid input.</param>
public JsonPartialMatcher(MatchBehaviour matchBehaviour, [NotNull] object value, bool ignoreCase = false, bool throwException = false)
: base(matchBehaviour, value, ignoreCase, throwException) : base(matchBehaviour, value, ignoreCase, throwException)
{ {
} }
/// <inheritdoc /> /// <inheritdoc />
protected override bool IsMatch(JToken value, JToken input) protected override bool IsMatch(string value, string input)
{ {
if (value == null || value == input) var exactStringMatcher = new ExactMatcher(MatchBehaviour.AcceptOnMatch, ThrowException, value);
{ return MatchScores.IsPerfect(exactStringMatcher.IsMatch(input));
return true;
}
if (input == null || value.Type != input.Type)
{
return false;
}
switch (value.Type)
{
case JTokenType.Object:
var nestedValues = value.ToObject<Dictionary<string, JToken>>();
return nestedValues?.Any() != true ||
nestedValues.All(pair => IsMatch(pair.Value, input.SelectToken(pair.Key)));
case JTokenType.Array:
var valuesArray = value.ToObject<JToken[]>();
var tokenArray = input.ToObject<JToken[]>();
if (valuesArray?.Any() != true)
{
return true;
}
return tokenArray?.Any() == true &&
valuesArray.All(subFilter => tokenArray.Any(subToken => IsMatch(subFilter, subToken)));
default:
return value.ToString() == input.ToString();
}
} }
} }
} }

View File

@@ -0,0 +1,38 @@
using JetBrains.Annotations;
namespace WireMock.Matchers
{
/// <summary>
/// JsonPartialWildCardMatcher
/// </summary>
public class JsonPartialWildcardMatcher : AbstractJsonPartialMatcher
{
/// <inheritdoc />
public override string Name => nameof(JsonPartialWildcardMatcher);
/// <inheritdoc />
public JsonPartialWildcardMatcher([NotNull] string value, bool ignoreCase = false, bool throwException = false)
: base(value, ignoreCase, throwException)
{
}
/// <inheritdoc />
public JsonPartialWildcardMatcher([NotNull] object value, bool ignoreCase = false, bool throwException = false)
: base(value, ignoreCase, throwException)
{
}
/// <inheritdoc />
public JsonPartialWildcardMatcher(MatchBehaviour matchBehaviour, [NotNull] object value, bool ignoreCase = false, bool throwException = false)
: base(matchBehaviour, value, ignoreCase, throwException)
{
}
/// <inheritdoc />
protected override bool IsMatch(string value, string input)
{
var wildcardStringMatcher = new WildcardMatcher(MatchBehaviour.AcceptOnMatch, value, IgnoreCase);
return MatchScores.IsPerfect(wildcardStringMatcher.IsMatch(input));
}
}
}

Some files were not shown because too many files have changed in this diff Show More