mirror of
https://github.com/wiremock/WireMock.Net.git
synced 2026-01-13 13:53:34 +01:00
Compare commits
14 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1e968106d1 | ||
|
|
49e10ed20f | ||
|
|
c3ec3a66b3 | ||
|
|
5644491942 | ||
|
|
6e5e629525 | ||
|
|
77ee123340 | ||
|
|
ae2a05e86b | ||
|
|
0e06cf6346 | ||
|
|
e9db520cc3 | ||
|
|
a0e661fae9 | ||
|
|
25666152bb | ||
|
|
6f5eeb5359 | ||
|
|
7ca2095576 | ||
|
|
74edad517b |
16
CHANGELOG.md
16
CHANGELOG.md
@@ -1,3 +1,15 @@
|
||||
# 1.4.26 (04 November 2021)
|
||||
- [#670](https://github.com/WireMock-Net/WireMock.Net/pull/670) - Improve method MapSchemaToObject to support array and object [feature] contributed by [leolplex](https://github.com/leolplex)
|
||||
- [#673](https://github.com/WireMock-Net/WireMock.Net/pull/673) - Support examples random data generation contributed by [leolplex](https://github.com/leolplex)
|
||||
- [#675](https://github.com/WireMock-Net/WireMock.Net/pull/675) - Support basepath from servers contributed by [leolplex](https://github.com/leolplex)
|
||||
- [#676](https://github.com/WireMock-Net/WireMock.Net/pull/676) - Fix random generate data in url no spaces [feature] contributed by [leolplex](https://github.com/leolplex)
|
||||
|
||||
# 1.4.25 (27 October 2021)
|
||||
- [#661](https://github.com/WireMock-Net/WireMock.Net/pull/661) - Add TimeSettings (Start, End and TTL) [feature] contributed by [StefH](https://github.com/StefH)
|
||||
- [#664](https://github.com/WireMock-Net/WireMock.Net/pull/664) - Support Array in OpenApiParser [feature] contributed by [leolplex](https://github.com/leolplex)
|
||||
- [#667](https://github.com/WireMock-Net/WireMock.Net/pull/667) - Add JsonPartialWildcardMatcher [feature] contributed by [StefH](https://github.com/StefH)
|
||||
- [#669](https://github.com/WireMock-Net/WireMock.Net/pull/669) - Support Schema Example and Support AllOf in definitions [feature] contributed by [StefH](https://github.com/StefH)
|
||||
|
||||
# 1.4.24 (20 October 2021)
|
||||
- [#637](https://github.com/WireMock-Net/WireMock.Net/pull/637) - Add support for AzureAD authentication for REST admin interface [feature] contributed by [StefH](https://github.com/StefH)
|
||||
- [#643](https://github.com/WireMock-Net/WireMock.Net/pull/643) - Support edge case: first object, next an array. [feature] contributed by [leolplex](https://github.com/leolplex)
|
||||
@@ -119,7 +131,6 @@
|
||||
- [#549](https://github.com/WireMock-Net/WireMock.Net/issues/549) - WithProxy(...) does not save the mappings to file [bug]
|
||||
|
||||
# 1.3.8 (03 December 2020)
|
||||
- [#539](https://github.com/WireMock-Net/WireMock.Net/pull/539) - Support for partial JSON matching contributed by [gleb-osokin](https://github.com/gleb-osokin)
|
||||
- [#542](https://github.com/WireMock-Net/WireMock.Net/pull/542) - Create dotnet-wiremock tool [feature] contributed by [StefH](https://github.com/StefH)
|
||||
- [#543](https://github.com/WireMock-Net/WireMock.Net/pull/543) - Add support for .NET 5 [feature] contributed by [StefH](https://github.com/StefH)
|
||||
- [#544](https://github.com/WireMock-Net/WireMock.Net/pull/544) - Use Java 11 in Azure Pipelines (needed for SonarCloud) [feature] contributed by [StefH](https://github.com/StefH)
|
||||
@@ -127,6 +138,9 @@
|
||||
- [#547](https://github.com/WireMock-Net/WireMock.Net/pull/547) - Fix Proxying with SSL and NetCoreApp3.1 [bug] contributed by [StefH](https://github.com/StefH)
|
||||
- [#524](https://github.com/WireMock-Net/WireMock.Net/issues/524) - Proxying with SSL Not Working in .NET Core 3.1 [bug]
|
||||
|
||||
# 1.3.7 (17 November 2020)
|
||||
- [#539](https://github.com/WireMock-Net/WireMock.Net/pull/539) - Support for partial JSON matching contributed by [gleb-osokin](https://github.com/gleb-osokin)
|
||||
|
||||
# 1.3.6 (10 November 2020)
|
||||
- [#529](https://github.com/WireMock-Net/WireMock.Net/pull/529) - Add assertions for ClientIP, Url and ProxyUrl [feature] contributed by [akamud](https://github.com/akamud)
|
||||
- [#535](https://github.com/WireMock-Net/WireMock.Net/pull/535) - WithCallback should use also use enum HttpStatusCode [bug] contributed by [StefH](https://github.com/StefH)
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<VersionPrefix>1.4.24</VersionPrefix>
|
||||
<VersionPrefix>1.4.26</VersionPrefix>
|
||||
<PackageReleaseNotes>See CHANGELOG.md</PackageReleaseNotes>
|
||||
<PackageIcon>WireMock.Net-Logo.png</PackageIcon>
|
||||
<PackageProjectUrl>https://github.com/WireMock-Net/WireMock.Net</PackageProjectUrl>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
rem https://github.com/StefH/GitHubReleaseNotes
|
||||
|
||||
SET version=1.4.24
|
||||
SET version=1.4.26
|
||||
|
||||
GitHubReleaseNotes --output CHANGELOG.md --skip-empty-releases --exclude-labels question invalid doc duplicate --version %version% --token %GH_TOKEN%
|
||||
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
# 1.4.24 (20 October 2021)
|
||||
- #637 Add support for AzureAD authentication for REST admin interface [feature]
|
||||
- #643 Support edge case: first object, next an array. [feature]
|
||||
- #644 Mapping headers in OpenAPI [feature]
|
||||
- #649 Refactor method name MapHeaders and httpStatusCode
|
||||
- #651 Implement PatternAsFile for StringMatcher [feature]
|
||||
- #654 Update NotNullOrEmptyMatcher to also implement IStringMatcher [feature]
|
||||
# 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
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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'
|
||||
@@ -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
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
@@ -1,5 +1,3 @@
|
||||
using Microsoft.OpenApi.Readers;
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
@@ -7,15 +5,23 @@ namespace WireMock.Net.OpenApiParser.ConsoleApp
|
||||
{
|
||||
class Program
|
||||
{
|
||||
private static readonly JsonSerializerSettings Settings = new JsonSerializerSettings
|
||||
{
|
||||
NullValueHandling = NullValueHandling.Ignore,
|
||||
Formatting = Formatting.Indented
|
||||
};
|
||||
|
||||
private const string Folder = "OpenApiFiles";
|
||||
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();
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using WireMock.Admin.Mappings;
|
||||
@@ -13,14 +13,12 @@ namespace WireMock.Net.OpenApiParser.ConsoleApp
|
||||
{
|
||||
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
|
||||
{
|
||||
AllowCSharpCodeMatcher = true,
|
||||
Urls = new[] { url1 },
|
||||
Urls = new[] { url },
|
||||
StartAdminInterface = true,
|
||||
ReadStaticMappings = false,
|
||||
WatchStaticMappings = false,
|
||||
@@ -38,9 +36,7 @@ namespace WireMock.Net.OpenApiParser.ConsoleApp
|
||||
|
||||
server.WithMappingFromOpenApiFile(path, settings, out var diag);
|
||||
|
||||
Console.WriteLine("Press any key to stop the server");
|
||||
System.Console.ReadKey();
|
||||
server.Stop();
|
||||
return server;
|
||||
}
|
||||
|
||||
public static void RunServer(IEnumerable<MappingModel> mappings)
|
||||
|
||||
@@ -15,6 +15,21 @@
|
||||
<None Update="infura.yaml">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</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">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System;
|
||||
using WireMock.Models;
|
||||
|
||||
namespace WireMock.Admin.Mappings
|
||||
{
|
||||
@@ -13,6 +14,11 @@ namespace WireMock.Admin.Mappings
|
||||
/// </summary>
|
||||
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>
|
||||
/// The unique title.
|
||||
/// </summary>
|
||||
|
||||
@@ -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; }
|
||||
}
|
||||
}
|
||||
25
src/WireMock.Net.Abstractions/Models/ITimeSettings.cs
Normal file
25
src/WireMock.Net.Abstractions/Models/ITimeSettings.cs
Normal 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; }
|
||||
}
|
||||
}
|
||||
@@ -26,22 +26,22 @@ namespace WireMock.Net.OpenApiParser.Mappers
|
||||
_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 pathParameters = operation.Parameters.Where(p => p.In == ParameterLocation.Path);
|
||||
@@ -52,8 +52,11 @@ namespace WireMock.Net.OpenApiParser.Mappers
|
||||
TryGetContent(response.Value?.Content, out OpenApiMediaType responseContent, out string responseContentType);
|
||||
var responseSchema = response.Value?.Content?.FirstOrDefault().Value?.Schema;
|
||||
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))
|
||||
{
|
||||
@@ -66,7 +69,7 @@ namespace WireMock.Net.OpenApiParser.Mappers
|
||||
Request = new RequestModel
|
||||
{
|
||||
Methods = new[] { httpMethod },
|
||||
Path = MapPathWithParameters(path, pathParameters),
|
||||
Path = MapBasePath(servers) + MapPathWithParameters(path, pathParameters),
|
||||
Params = MapQueryParameters(queryParameters),
|
||||
Headers = MapRequestHeaders(headers)
|
||||
},
|
||||
@@ -141,6 +144,11 @@ namespace WireMock.Net.OpenApiParser.Mappers
|
||||
}
|
||||
}
|
||||
|
||||
if (schema.AllOf.Count > 0)
|
||||
{
|
||||
jArray.Add(MapSchemaAllOfToObject(schema));
|
||||
}
|
||||
|
||||
return jArray;
|
||||
|
||||
case SchemaType.Boolean:
|
||||
@@ -153,25 +161,16 @@ namespace WireMock.Net.OpenApiParser.Mappers
|
||||
var propertyAsJObject = new JObject();
|
||||
foreach (var schemaProperty in schema.Properties)
|
||||
{
|
||||
string propertyName = schemaProperty.Key;
|
||||
var openApiSchema = schemaProperty.Value;
|
||||
if (openApiSchema.GetSchemaType() == SchemaType.Object || openApiSchema.GetSchemaType() == SchemaType.Array)
|
||||
propertyAsJObject.Add(MapPropertyAsJObject(schemaProperty.Value, schemaProperty.Key));
|
||||
}
|
||||
if (schema.AllOf.Count > 0)
|
||||
{
|
||||
foreach (var property in schema.AllOf)
|
||||
{
|
||||
var mapped = MapSchemaToObject(schemaProperty.Value, schemaProperty.Key);
|
||||
if (mapped is JProperty jp)
|
||||
foreach (var item in property.Properties)
|
||||
{
|
||||
propertyAsJObject.Add(jp);
|
||||
propertyAsJObject.Add(MapPropertyAsJObject(item.Value, item.Key));
|
||||
}
|
||||
else
|
||||
{
|
||||
propertyAsJObject.Add(new JProperty(schemaProperty.Key, mapped));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
bool propertyIsNullable = openApiSchema.Nullable || (openApiSchema.TryGetXNullable(out bool x) && x);
|
||||
|
||||
propertyAsJObject.Add(new JProperty(propertyName, _exampleValueGenerator.GetExampleValue(openApiSchema)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -182,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)
|
||||
{
|
||||
if (parameters == null)
|
||||
@@ -198,6 +230,22 @@ namespace WireMock.Net.OpenApiParser.Mappers
|
||||
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)
|
||||
{
|
||||
if (any == null)
|
||||
@@ -209,7 +257,14 @@ namespace WireMock.Net.OpenApiParser.Mappers
|
||||
var writer = new OpenApiJsonWriter(outputString);
|
||||
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)
|
||||
|
||||
@@ -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; }
|
||||
}
|
||||
}
|
||||
@@ -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 { } }
|
||||
}
|
||||
}
|
||||
@@ -5,26 +5,25 @@ namespace WireMock.Net.OpenApiParser.Settings
|
||||
/// <summary>
|
||||
/// A class defining the example values to use for the different types.
|
||||
/// </summary>
|
||||
public class WireMockOpenApiParserExampleValues
|
||||
public class WireMockOpenApiParserExampleValues : IWireMockOpenApiParserExampleValues
|
||||
{
|
||||
#pragma warning disable 1591
|
||||
/// <inheritdoc />
|
||||
public bool Boolean { get; set; } = true;
|
||||
|
||||
/// <inheritdoc />
|
||||
public int Integer { get; set; } = 42;
|
||||
|
||||
/// <inheritdoc />
|
||||
public float Float { get; set; } = 4.2f;
|
||||
|
||||
/// <inheritdoc />
|
||||
public double Double { get; set; } = 4.2d;
|
||||
|
||||
/// <inheritdoc />
|
||||
public Func<DateTime> Date { get; set; } = () => System.DateTime.UtcNow.Date;
|
||||
|
||||
/// <inheritdoc />
|
||||
public Func<DateTime> DateTime { get; set; } = () => System.DateTime.UtcNow;
|
||||
|
||||
/// <inheritdoc />
|
||||
public byte[] Bytes { get; set; } = { 48, 49, 50 };
|
||||
|
||||
/// <inheritdoc />
|
||||
public object Object { get; set; } = "example-object";
|
||||
|
||||
/// <inheritdoc />
|
||||
public string String { get; set; } = "example-string";
|
||||
#pragma warning restore 1591
|
||||
}
|
||||
}
|
||||
@@ -25,6 +25,11 @@ namespace WireMock.Net.OpenApiParser.Settings
|
||||
/// <summary>
|
||||
/// The example values to use
|
||||
/// </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;
|
||||
}
|
||||
}
|
||||
@@ -13,6 +13,14 @@ namespace WireMock.Net.OpenApiParser.Utils
|
||||
public ExampleValueGenerator(WireMockOpenApiParserSettings 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)
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
<PackageReference Include="RamlToOpenApiConverter" Version="0.1.1" />
|
||||
<PackageReference Include="JetBrains.Annotations" Version="2020.1.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" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
@@ -62,7 +62,7 @@ namespace WireMock.Net.OpenApiParser
|
||||
[PublicAPI]
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Linq;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using JetBrains.Annotations;
|
||||
using WireMock.Logging;
|
||||
using WireMock.Server;
|
||||
@@ -12,6 +13,8 @@ namespace WireMock.Net.StandAlone
|
||||
/// </summary>
|
||||
public static class StandAloneApp
|
||||
{
|
||||
private static readonly string Version = typeof(StandAloneApp).GetTypeInfo().Assembly.GetName().Version.ToString();
|
||||
|
||||
/// <summary>
|
||||
/// Start WireMock.Net standalone Server based on the IWireMockServerSettings.
|
||||
/// </summary>
|
||||
@@ -23,7 +26,8 @@ namespace WireMock.Net.StandAlone
|
||||
|
||||
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;
|
||||
}
|
||||
@@ -40,7 +44,8 @@ namespace WireMock.Net.StandAlone
|
||||
|
||||
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);
|
||||
}
|
||||
@@ -61,7 +66,8 @@ namespace WireMock.Net.StandAlone
|
||||
|
||||
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);
|
||||
return true;
|
||||
|
||||
@@ -1,23 +1,24 @@
|
||||
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(this AnyOf<string, StringPattern> value)
|
||||
public static string GetPattern([NotNull] this AnyOf<string, StringPattern> value)
|
||||
{
|
||||
return value.IsFirst ? value.First : value.Second.Pattern;
|
||||
}
|
||||
|
||||
public static AnyOf<string, StringPattern>[] ToAnyOfPatterns(this IEnumerable<string> patterns)
|
||||
public static AnyOf<string, StringPattern>[] ToAnyOfPatterns([NotNull] this IEnumerable<string> patterns)
|
||||
{
|
||||
return patterns.Select(p => p.ToAnyOfPattern()).ToArray();
|
||||
}
|
||||
|
||||
public static AnyOf<string, StringPattern> ToAnyOfPattern(this string pattern)
|
||||
public static AnyOf<string, StringPattern> ToAnyOfPattern([CanBeNull] this string pattern)
|
||||
{
|
||||
return new AnyOf<string, StringPattern>(pattern);
|
||||
}
|
||||
|
||||
35
src/WireMock.Net/Extensions/TimeSettingsExtensions.cs
Normal file
35
src/WireMock.Net/Extensions/TimeSettingsExtensions.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
using JetBrains.Annotations;
|
||||
using JetBrains.Annotations;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using WireMock.Matchers.Request;
|
||||
@@ -18,6 +18,11 @@ namespace WireMock
|
||||
/// </summary>
|
||||
Guid Guid { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the TimeSettings (Start, End and TTL).
|
||||
/// </summary>
|
||||
ITimeSettings TimeSettings { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the unique title.
|
||||
/// </summary>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using JetBrains.Annotations;
|
||||
using WireMock.Matchers.Request;
|
||||
@@ -13,51 +13,54 @@ namespace WireMock
|
||||
/// </summary>
|
||||
public class Mapping : IMapping
|
||||
{
|
||||
/// <inheritdoc cref="IMapping.Guid" />
|
||||
/// <inheritdoc />
|
||||
public Guid Guid { get; }
|
||||
|
||||
/// <inheritdoc cref="IMapping.Title" />
|
||||
/// <inheritdoc />
|
||||
public string Title { get; }
|
||||
|
||||
/// <inheritdoc cref="IMapping.Path" />
|
||||
/// <inheritdoc />
|
||||
public string Path { get; set; }
|
||||
|
||||
/// <inheritdoc cref="IMapping.Priority" />
|
||||
/// <inheritdoc />
|
||||
public int Priority { get; }
|
||||
|
||||
/// <inheritdoc cref="IMapping.Scenario" />
|
||||
/// <inheritdoc />
|
||||
public string Scenario { get; }
|
||||
|
||||
/// <inheritdoc cref="IMapping.ExecutionConditionState" />
|
||||
/// <inheritdoc />
|
||||
public string ExecutionConditionState { get; }
|
||||
|
||||
/// <inheritdoc cref="IMapping.NextState" />
|
||||
/// <inheritdoc />
|
||||
public string NextState { get; }
|
||||
|
||||
/// <inheritdoc cref="IMapping.StateTimes" />
|
||||
/// <inheritdoc />
|
||||
public int? StateTimes { get; }
|
||||
|
||||
/// <inheritdoc cref="IMapping.RequestMatcher" />
|
||||
/// <inheritdoc />
|
||||
public IRequestMatcher RequestMatcher { get; }
|
||||
|
||||
/// <inheritdoc cref="IMapping.Provider" />
|
||||
/// <inheritdoc />
|
||||
public IResponseProvider Provider { get; }
|
||||
|
||||
/// <inheritdoc cref="IMapping.Settings" />
|
||||
/// <inheritdoc />
|
||||
public IWireMockServerSettings Settings { get; }
|
||||
|
||||
/// <inheritdoc cref="IMapping.IsStartState" />
|
||||
/// <inheritdoc />
|
||||
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;
|
||||
|
||||
/// <inheritdoc cref="IMapping.LogMapping" />
|
||||
/// <inheritdoc />
|
||||
public bool LogMapping => !(Provider is DynamicResponseProvider || Provider is DynamicAsyncResponseProvider);
|
||||
|
||||
/// <inheritdoc cref="IMapping.Webhooks" />
|
||||
/// <inheritdoc />
|
||||
public IWebhook[] Webhooks { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public ITimeSettings TimeSettings { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Mapping"/> class.
|
||||
/// </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="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="timeSettings">The TimeSettings. [Optional]</param>
|
||||
public Mapping(
|
||||
Guid guid,
|
||||
[CanBeNull] string title,
|
||||
@@ -85,7 +89,8 @@ namespace WireMock
|
||||
[CanBeNull] string executionConditionState,
|
||||
[CanBeNull] string nextState,
|
||||
[CanBeNull] int? stateTimes,
|
||||
[CanBeNull] IWebhook[] webhooks)
|
||||
[CanBeNull] IWebhook[] webhooks,
|
||||
[CanBeNull] ITimeSettings timeSettings)
|
||||
{
|
||||
Guid = guid;
|
||||
Title = title;
|
||||
@@ -99,6 +104,7 @@ namespace WireMock
|
||||
NextState = nextState;
|
||||
StateTimes = stateTimes;
|
||||
Webhooks = webhooks;
|
||||
TimeSettings = timeSettings;
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IMapping.ProvideResponseAsync" />
|
||||
|
||||
89
src/WireMock.Net/Matchers/AbstractJsonPartialMatcher.cs
Normal file
89
src/WireMock.Net/Matchers/AbstractJsonPartialMatcher.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
@@ -1,87 +1,38 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using JetBrains.Annotations;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace WireMock.Matchers
|
||||
{
|
||||
/// <summary>
|
||||
/// JsonPartialMatcher
|
||||
/// </summary>
|
||||
public class JsonPartialMatcher : JsonMatcher
|
||||
public class JsonPartialMatcher : AbstractJsonPartialMatcher
|
||||
{
|
||||
/// <inheritdoc cref="IMatcher.Name"/>
|
||||
public override string Name => "JsonPartialMatcher";
|
||||
/// <inheritdoc />
|
||||
public override string Name => nameof(JsonPartialMatcher);
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="JsonPartialMatcher"/> 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>
|
||||
public JsonPartialMatcher([NotNull] string value, bool ignoreCase = false, bool throwException = false)
|
||||
/// <inheritdoc />
|
||||
public JsonPartialMatcher([NotNull] string value, bool ignoreCase = false, bool throwException = false)
|
||||
: base(value, ignoreCase, throwException)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="JsonPartialMatcher"/> 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>
|
||||
public JsonPartialMatcher([NotNull] object value, bool ignoreCase = false, bool throwException = false)
|
||||
/// <inheritdoc />
|
||||
public JsonPartialMatcher([NotNull] object value, bool ignoreCase = false, bool throwException = false)
|
||||
: base(value, ignoreCase, throwException)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="JsonPartialMatcher"/> 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>
|
||||
public JsonPartialMatcher(MatchBehaviour matchBehaviour, [NotNull] object value, bool ignoreCase = false, bool throwException = false)
|
||||
/// <inheritdoc />
|
||||
public JsonPartialMatcher(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)
|
||||
protected override bool IsMatch(string value, string 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 value.ToString() == input.ToString();
|
||||
}
|
||||
var exactStringMatcher = new ExactMatcher(MatchBehaviour.AcceptOnMatch, ThrowException, value);
|
||||
return MatchScores.IsPerfect(exactStringMatcher.IsMatch(input));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
38
src/WireMock.Net/Matchers/JsonPartialWildCardMatcher.cs
Normal file
38
src/WireMock.Net/Matchers/JsonPartialWildCardMatcher.cs
Normal 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));
|
||||
}
|
||||
}
|
||||
}
|
||||
19
src/WireMock.Net/Models/TimeSettings.cs
Normal file
19
src/WireMock.Net/Models/TimeSettings.cs
Normal file
@@ -0,0 +1,19 @@
|
||||
using System;
|
||||
|
||||
namespace WireMock.Models
|
||||
{
|
||||
/// <summary>
|
||||
/// TimeSettingsModel: Start, End and TTL
|
||||
/// </summary>
|
||||
public class TimeSettings : ITimeSettings
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public DateTime? Start { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public DateTime? End { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public int? TTL { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
#if USE_ASPNETCORE
|
||||
#if USE_ASPNETCORE
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
@@ -118,17 +118,17 @@ namespace WireMock.Owin
|
||||
});
|
||||
|
||||
#if NETSTANDARD1_3
|
||||
_logger.Info("WireMock.Net server using netstandard1.3");
|
||||
_logger.Info("Server using netstandard1.3");
|
||||
#elif NETSTANDARD2_0
|
||||
_logger.Info("WireMock.Net server using netstandard2.0");
|
||||
_logger.Info("Server using netstandard2.0");
|
||||
#elif NETSTANDARD2_1
|
||||
_logger.Info("WireMock.Net server using netstandard2.1");
|
||||
_logger.Info("Server using netstandard2.1");
|
||||
#elif NETCOREAPP3_1
|
||||
_logger.Info("WireMock.Net server using .NET Core 3.1");
|
||||
_logger.Info("Server using .NET Core 3.1");
|
||||
#elif NET5_0
|
||||
_logger.Info("WireMock.Net server using .NET 5.0");
|
||||
_logger.Info("Server using .NET 5.0");
|
||||
#elif NET46
|
||||
_logger.Info("WireMock.Net server using .NET Framework 4.6.1 or higher");
|
||||
_logger.Info("Server using .NET Framework 4.6.1 or higher");
|
||||
#endif
|
||||
|
||||
#if NETSTANDARD1_3
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using WireMock.Extensions;
|
||||
using WireMock.Validation;
|
||||
|
||||
namespace WireMock.Owin
|
||||
@@ -19,7 +20,8 @@ namespace WireMock.Owin
|
||||
public (MappingMatcherResult Match, MappingMatcherResult Partial) FindBestMatch(RequestMessage request)
|
||||
{
|
||||
var mappings = new List<MappingMatcherResult>();
|
||||
foreach (var mapping in _options.Mappings.Values)
|
||||
|
||||
foreach (var mapping in _options.Mappings.Values.Where(m => m.TimeSettings.IsValid()))
|
||||
{
|
||||
try
|
||||
{
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#if !USE_ASPNETCORE
|
||||
#if !USE_ASPNETCORE
|
||||
using JetBrains.Annotations;
|
||||
using Microsoft.Owin.Hosting;
|
||||
using Owin;
|
||||
@@ -63,9 +63,9 @@ namespace WireMock.Owin
|
||||
private void StartServers()
|
||||
{
|
||||
#if NET46
|
||||
_logger.Info("WireMock.Net server using .net 4.6.1 or higher");
|
||||
_logger.Info("Server using .net 4.6.1 or higher");
|
||||
#else
|
||||
_logger.Info("WireMock.Net server using .net 4.5.x");
|
||||
_logger.Info("Server using .net 4.5.x");
|
||||
#endif
|
||||
var servers = new List<IDisposable>();
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
@@ -21,8 +21,7 @@ namespace WireMock.Proxy
|
||||
|
||||
public ProxyHelper([NotNull] IWireMockServerSettings settings)
|
||||
{
|
||||
Check.NotNull(settings, nameof(settings));
|
||||
_settings = settings;
|
||||
_settings = Check.NotNull(settings, nameof(settings));
|
||||
}
|
||||
|
||||
public async Task<(ResponseMessage Message, IMapping Mapping)> SendAsync(
|
||||
@@ -105,7 +104,7 @@ namespace WireMock.Proxy
|
||||
|
||||
var response = Response.Create(responseMessage);
|
||||
|
||||
return new Mapping(Guid.NewGuid(), string.Empty, null, _settings, request, response, 0, null, null, null, null, null);
|
||||
return new Mapping(Guid.NewGuid(), string.Empty, null, _settings, request, response, 0, null, null, null, null, null, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,7 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using WireMock.Admin.Mappings;
|
||||
using WireMock.Matchers.Request;
|
||||
using WireMock.Models;
|
||||
using WireMock.RequestBuilders;
|
||||
using WireMock.ResponseBuilders;
|
||||
using WireMock.Settings;
|
||||
@@ -36,6 +37,7 @@ namespace WireMock.Serialization
|
||||
var mappingModel = new MappingModel
|
||||
{
|
||||
Guid = mapping.Guid,
|
||||
TimeSettings = TimeSettingsMapper.Map(mapping.TimeSettings),
|
||||
Title = mapping.Title,
|
||||
Priority = mapping.Priority != 0 ? mapping.Priority : (int?)null,
|
||||
Scenario = mapping.Scenario,
|
||||
|
||||
@@ -44,7 +44,7 @@ namespace WireMock.Serialization
|
||||
|
||||
switch (matcherName)
|
||||
{
|
||||
case "NotNullOrEmptyMatcher":
|
||||
case nameof(NotNullOrEmptyMatcher):
|
||||
return new NotNullOrEmptyMatcher(matchBehaviour);
|
||||
|
||||
case "CSharpCodeMatcher":
|
||||
@@ -55,42 +55,46 @@ namespace WireMock.Serialization
|
||||
|
||||
throw new NotSupportedException("It's not allowed to use the 'CSharpCodeMatcher' because IWireMockServerSettings.AllowCSharpCodeMatcher is not set to 'true'.");
|
||||
|
||||
case "LinqMatcher":
|
||||
case nameof(LinqMatcher):
|
||||
return new LinqMatcher(matchBehaviour, throwExceptionWhenMatcherFails, stringPatterns);
|
||||
|
||||
case "ExactMatcher":
|
||||
case nameof(ExactMatcher):
|
||||
return new ExactMatcher(matchBehaviour, throwExceptionWhenMatcherFails, stringPatterns);
|
||||
|
||||
case "ExactObjectMatcher":
|
||||
case nameof(ExactObjectMatcher):
|
||||
return CreateExactObjectMatcher(matchBehaviour, stringPatterns[0], throwExceptionWhenMatcherFails);
|
||||
|
||||
case "RegexMatcher":
|
||||
case nameof(RegexMatcher):
|
||||
return new RegexMatcher(matchBehaviour, stringPatterns, ignoreCase, throwExceptionWhenMatcherFails);
|
||||
|
||||
case "JsonMatcher":
|
||||
case nameof(JsonMatcher):
|
||||
object valueForJsonMatcher = matcher.Pattern ?? matcher.Patterns;
|
||||
return new JsonMatcher(matchBehaviour, valueForJsonMatcher, ignoreCase, throwExceptionWhenMatcherFails);
|
||||
|
||||
case "JsonPartialMatcher":
|
||||
case nameof(JsonPartialMatcher):
|
||||
object valueForJsonPartialMatcher = matcher.Pattern ?? matcher.Patterns;
|
||||
return new JsonPartialMatcher(matchBehaviour, valueForJsonPartialMatcher, ignoreCase, throwExceptionWhenMatcherFails);
|
||||
|
||||
case "JsonPathMatcher":
|
||||
case nameof(JsonPartialWildcardMatcher):
|
||||
object valueForJsonPartialWilcardMatcher = matcher.Pattern ?? matcher.Patterns;
|
||||
return new JsonPartialWildcardMatcher(matchBehaviour, valueForJsonPartialWilcardMatcher, ignoreCase, throwExceptionWhenMatcherFails);
|
||||
|
||||
case nameof(JsonPathMatcher):
|
||||
return new JsonPathMatcher(matchBehaviour, throwExceptionWhenMatcherFails, stringPatterns);
|
||||
|
||||
case "JmesPathMatcher":
|
||||
case nameof(JmesPathMatcher):
|
||||
return new JmesPathMatcher(matchBehaviour, throwExceptionWhenMatcherFails, stringPatterns);
|
||||
|
||||
case "XPathMatcher":
|
||||
case nameof(XPathMatcher):
|
||||
return new XPathMatcher(matchBehaviour, throwExceptionWhenMatcherFails, stringPatterns);
|
||||
|
||||
case "WildcardMatcher":
|
||||
case nameof(WildcardMatcher):
|
||||
return new WildcardMatcher(matchBehaviour, stringPatterns, ignoreCase, throwExceptionWhenMatcherFails);
|
||||
|
||||
case "ContentTypeMatcher":
|
||||
case nameof(ContentTypeMatcher):
|
||||
return new ContentTypeMatcher(matchBehaviour, stringPatterns, ignoreCase, throwExceptionWhenMatcherFails);
|
||||
|
||||
case "SimMetricsMatcher":
|
||||
case nameof(SimMetricsMatcher):
|
||||
SimMetricType type = SimMetricType.Levenstein;
|
||||
if (!string.IsNullOrEmpty(matcherType) && !Enum.TryParse(matcherType, out type))
|
||||
{
|
||||
|
||||
27
src/WireMock.Net/Serialization/TimeSettingsMapper.cs
Normal file
27
src/WireMock.Net/Serialization/TimeSettingsMapper.cs
Normal file
@@ -0,0 +1,27 @@
|
||||
using WireMock.Models;
|
||||
|
||||
namespace WireMock.Serialization
|
||||
{
|
||||
internal static class TimeSettingsMapper
|
||||
{
|
||||
public static TimeSettingsModel Map(ITimeSettings settings)
|
||||
{
|
||||
return settings != null ? new TimeSettingsModel
|
||||
{
|
||||
Start = settings.Start,
|
||||
End = settings.End,
|
||||
TTL = settings.TTL
|
||||
} : null;
|
||||
}
|
||||
|
||||
public static ITimeSettings Map(TimeSettingsModel settings)
|
||||
{
|
||||
return settings != null ? new TimeSettings
|
||||
{
|
||||
Start = settings.Start,
|
||||
End = settings.End,
|
||||
TTL = settings.TTL
|
||||
} : null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using JetBrains.Annotations;
|
||||
using WireMock.Models;
|
||||
@@ -24,6 +24,13 @@ namespace WireMock.Server
|
||||
/// <returns>The <see cref="IRespondWithAProvider"/>.</returns>
|
||||
IRespondWithAProvider WithGuid(Guid guid);
|
||||
|
||||
/// <summary>
|
||||
/// Define the TimeSettings for this mapping.
|
||||
/// </summary>
|
||||
/// <param name="timeSettings">The TimeSettings.</param>
|
||||
/// <returns>The <see cref="IRespondWithAProvider"/>.</returns>
|
||||
IRespondWithAProvider WithTimeSettings(ITimeSettings timeSettings);
|
||||
|
||||
/// <summary>
|
||||
/// Define a unique title for this mapping.
|
||||
/// </summary>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// This source file is based on mock4net by Alexandre Victoor which is licensed under the Apache 2.0 License.
|
||||
// This source file is based on mock4net by Alexandre Victoor which is licensed under the Apache 2.0 License.
|
||||
// For more details see 'mock4net/LICENSE.txt' and 'mock4net/readme.md' in this project root.
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
@@ -34,6 +34,8 @@ namespace WireMock.Server
|
||||
|
||||
public IWebhook[] Webhooks { get; private set; }
|
||||
|
||||
public ITimeSettings TimeSettings { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="RespondWithAProvider"/> class.
|
||||
/// </summary>
|
||||
@@ -55,7 +57,7 @@ namespace WireMock.Server
|
||||
/// <param name="provider">The provider.</param>
|
||||
public void RespondWith(IResponseProvider provider)
|
||||
{
|
||||
_registrationCallback(new Mapping(Guid, _title, _path, _settings, _requestMatcher, provider, _priority, _scenario, _executionConditionState, _nextState, _timesInSameState, Webhooks), _saveToFile);
|
||||
_registrationCallback(new Mapping(Guid, _title, _path, _settings, _requestMatcher, provider, _priority, _scenario, _executionConditionState, _nextState, _timesInSameState, Webhooks, TimeSettings), _saveToFile);
|
||||
}
|
||||
|
||||
/// <see cref="IRespondWithAProvider.WithGuid(string)"/>
|
||||
@@ -149,6 +151,16 @@ namespace WireMock.Server
|
||||
return WillSetStateTo(state.ToString(), times);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public IRespondWithAProvider WithTimeSettings(ITimeSettings timeSettings)
|
||||
{
|
||||
Check.NotNull(timeSettings, nameof(timeSettings));
|
||||
|
||||
TimeSettings = timeSettings;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <see cref="IRespondWithAProvider.WithWebhook(IWebhook[])"/>
|
||||
public IRespondWithAProvider WithWebhook(params IWebhook[] webhooks)
|
||||
{
|
||||
@@ -207,7 +219,7 @@ namespace WireMock.Server
|
||||
return this;
|
||||
}
|
||||
|
||||
private IWebhook InitWebhook(
|
||||
private static IWebhook InitWebhook(
|
||||
string url,
|
||||
string method,
|
||||
IDictionary<string, WireMockList<string>> headers,
|
||||
|
||||
@@ -450,6 +450,11 @@ namespace WireMock.Server
|
||||
respondProvider = respondProvider.WithGuid(mappingModel.Guid.Value);
|
||||
}
|
||||
|
||||
if (mappingModel.TimeSettings != null)
|
||||
{
|
||||
respondProvider = respondProvider.WithTimeSettings(TimeSettingsMapper.Map(mappingModel.TimeSettings));
|
||||
}
|
||||
|
||||
if (path != null)
|
||||
{
|
||||
respondProvider = respondProvider.WithPath(path);
|
||||
|
||||
@@ -4,7 +4,6 @@ using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using JetBrains.Annotations;
|
||||
using Newtonsoft.Json;
|
||||
@@ -13,7 +12,6 @@ using WireMock.Authentication;
|
||||
using WireMock.Exceptions;
|
||||
using WireMock.Handlers;
|
||||
using WireMock.Logging;
|
||||
using WireMock.Matchers;
|
||||
using WireMock.Matchers.Request;
|
||||
using WireMock.Owin;
|
||||
using WireMock.RequestBuilders;
|
||||
@@ -202,8 +200,8 @@ namespace WireMock.Server
|
||||
_settings.Logger = settings.Logger ?? new WireMockNullLogger();
|
||||
_settings.FileSystemHandler = settings.FileSystemHandler ?? new LocalFileSystemHandler();
|
||||
|
||||
_settings.Logger.Info("WireMock.Net by Stef Heyenrath (https://github.com/WireMock-Net/WireMock.Net)");
|
||||
_settings.Logger.Debug("WireMock.Net server settings {0}", JsonConvert.SerializeObject(settings, Formatting.Indented));
|
||||
_settings.Logger.Info("By Stef Heyenrath (https://github.com/WireMock-Net/WireMock.Net)");
|
||||
_settings.Logger.Debug("Server settings {0}", JsonConvert.SerializeObject(settings, Formatting.Indented));
|
||||
|
||||
HostUrlOptions urlOptions;
|
||||
if (settings.Urls != null)
|
||||
|
||||
@@ -50,17 +50,19 @@
|
||||
<DefineConstants>USE_ASPNETCORE;NET46</DefineConstants>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="JetBrains.Annotations" Version="2020.1.0" PrivateAssets="All" />
|
||||
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="11.0.2" />
|
||||
<PackageReference Include="SimMetrics.Net" Version="1.0.5" />
|
||||
<!--<PackageReference Include="Stef.Validation" Version="0.0.3" />-->
|
||||
<PackageReference Include="System.Linq.Dynamic.Core" Version="1.0.12" />
|
||||
<PackageReference Include="RandomDataGenerator.Net" Version="1.0.12" />
|
||||
<PackageReference Include="JmesPath.Net" Version="1.0.125" />
|
||||
<PackageReference Include="AnyOf" Version="0.2.0" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="JetBrains.Annotations" Version="2020.1.0" PrivateAssets="All" />
|
||||
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="11.0.2" />
|
||||
<PackageReference Include="SimMetrics.Net" Version="1.0.5" />
|
||||
<!--<PackageReference Include="Stef.Validation" Version="0.0.3" />-->
|
||||
<PackageReference Include="System.Linq.Dynamic.Core" Version="1.0.12" />
|
||||
<PackageReference Include="RandomDataGenerator.Net" Version="1.0.13" />
|
||||
<PackageReference Include="JmesPath.Net" Version="1.0.125" />
|
||||
<PackageReference Include="AnyOf" Version="0.2.0" />
|
||||
<!--<PackageReference Include="TinyMapper" Version="3.0.3" />-->
|
||||
<!--<PackageReference Include="Mapster" Version="7.2.0" />-->
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition="'$(Configuration)' == 'Debug - Sonar'">
|
||||
<PackageReference Include="SonarAnalyzer.CSharp" Version="7.8.0.7320">
|
||||
@@ -69,10 +71,10 @@
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition=" '$(TargetFramework)' != 'netstandard1.3' ">
|
||||
<PackageReference Include="XPath2.Extensions" Version="1.1.0" />
|
||||
<PackageReference Include="Microsoft.IdentityModel.Protocols.OpenIdConnect" Version="6.12.2" />
|
||||
</ItemGroup>
|
||||
<ItemGroup Condition=" '$(TargetFramework)' != 'netstandard1.3' ">
|
||||
<PackageReference Include="XPath2.Extensions" Version="1.1.0" />
|
||||
<PackageReference Include="Microsoft.IdentityModel.Protocols.OpenIdConnect" Version="6.12.2" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition=" '$(TargetFramework)' == 'net451' or '$(TargetFramework)' == 'net452' ">
|
||||
<!-- Required for WebRequestHandler -->
|
||||
@@ -81,6 +83,7 @@
|
||||
<PackageReference Include="Microsoft.AspNet.WebApi.OwinSelfHost" Version="5.2.6" />
|
||||
<PackageReference Include="System.ValueTuple" Version="4.5.0" />
|
||||
<PackageReference Include="Scriban.Signed" Version="2.1.4" />
|
||||
<PackageReference Include="Mapster" Version="7.2.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition=" '$(TargetFramework)' == 'net46' ">
|
||||
|
||||
@@ -1,15 +1,16 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using WireMock.Logging;
|
||||
using WireMock.Net.StandAlone;
|
||||
using WireMock.Server;
|
||||
|
||||
namespace WireMock
|
||||
namespace WireMock.Net
|
||||
{
|
||||
public class Program
|
||||
{
|
||||
private static int SleepTime = 30000;
|
||||
private static readonly ILogger Logger = LoggerFactory.Create(o =>
|
||||
private static readonly int SleepTime = 30000;
|
||||
private static readonly ILogger xLogger = LoggerFactory.Create(o =>
|
||||
{
|
||||
o.SetMinimumLevel(LogLevel.Debug);
|
||||
o.AddSimpleConsole(options =>
|
||||
@@ -18,18 +19,19 @@ namespace WireMock
|
||||
options.SingleLine = false;
|
||||
options.TimestampFormat = "yyyy-MM-ddTHH:mm:ss ";
|
||||
});
|
||||
}).CreateLogger(string.Empty);
|
||||
}).CreateLogger("WireMock.Net");
|
||||
private static readonly IWireMockLogger Logger = new WireMockLogger(xLogger);
|
||||
|
||||
private static WireMockServer Server;
|
||||
|
||||
static async Task Main(string[] args)
|
||||
{
|
||||
if (!StandAloneApp.TryStart(args, out Server, new WireMockLogger(Logger)))
|
||||
if (!StandAloneApp.TryStart(args, out Server, Logger))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Logger.LogInformation("Press Ctrl+C to shut down");
|
||||
Logger.Info("Press Ctrl+C to shut down");
|
||||
|
||||
Console.CancelKeyPress += (s, e) =>
|
||||
{
|
||||
@@ -43,16 +45,16 @@ namespace WireMock
|
||||
|
||||
while (true)
|
||||
{
|
||||
Logger.LogInformation("WireMock.Net server running : {IsStarted}", Server.IsStarted);
|
||||
Logger.Info("Server running : {IsStarted}", Server.IsStarted);
|
||||
await Task.Delay(SleepTime);
|
||||
}
|
||||
}
|
||||
|
||||
private static void Stop(string why)
|
||||
{
|
||||
Logger.LogInformation("WireMock.Net server stopping because '{why}'", why);
|
||||
Logger.Info("Server stopping because '{why}'", why);
|
||||
Server.Stop();
|
||||
Logger.LogInformation("WireMock.Net server stopped");
|
||||
Logger.Info("Server stopped");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,10 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Text.Json;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using WireMock.Admin.Requests;
|
||||
using WireMock.Logging;
|
||||
|
||||
namespace WireMock
|
||||
namespace WireMock.Net
|
||||
{
|
||||
public class WireMockLogger : IWireMockLogger
|
||||
{
|
||||
|
||||
@@ -0,0 +1,400 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using FluentAssertions;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using NFluent;
|
||||
using WireMock.Matchers;
|
||||
using Xunit;
|
||||
|
||||
namespace WireMock.Net.Tests.Matchers
|
||||
{
|
||||
public class JsonPartialWildcardMatcherTests
|
||||
{
|
||||
[Fact]
|
||||
public void JsonPartialWildcardMatcher_GetName()
|
||||
{
|
||||
// Assign
|
||||
var matcher = new JsonPartialWildcardMatcher("{}");
|
||||
|
||||
// Act
|
||||
string name = matcher.Name;
|
||||
|
||||
// Assert
|
||||
Check.That(name).Equals("JsonPartialWildcardMatcher");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void JsonPartialWildcardMatcher_GetValue()
|
||||
{
|
||||
// Assign
|
||||
var matcher = new JsonPartialWildcardMatcher("{}");
|
||||
|
||||
// Act
|
||||
object value = matcher.Value;
|
||||
|
||||
// Assert
|
||||
Check.That(value).Equals("{}");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void JsonPartialWildcardMatcher_WithInvalidStringValue_Should_ThrowException()
|
||||
{
|
||||
// Act
|
||||
Action action = () => new JsonPartialWildcardMatcher(MatchBehaviour.AcceptOnMatch, "{ \"Id\"");
|
||||
|
||||
// Assert
|
||||
action.Should().Throw<JsonException>();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void JsonPartialWildcardMatcher_WithInvalidObjectValue_Should_ThrowException()
|
||||
{
|
||||
// Act
|
||||
Action action = () => new JsonPartialWildcardMatcher(MatchBehaviour.AcceptOnMatch, new MemoryStream());
|
||||
|
||||
// Assert
|
||||
action.Should().Throw<JsonException>();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void JsonPartialWildcardMatcher_IsMatch_WithInvalidValue_And_ThrowExceptionIsFalse_Should_ReturnMismatch()
|
||||
{
|
||||
// Assign
|
||||
var matcher = new JsonPartialWildcardMatcher("");
|
||||
|
||||
// Act
|
||||
double match = matcher.IsMatch(new MemoryStream());
|
||||
|
||||
// Assert
|
||||
Check.That(match).IsEqualTo(0);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void JsonPartialWildcardMatcher_IsMatch_WithInvalidValue_And_ThrowExceptionIsTrue_Should_ReturnMismatch()
|
||||
{
|
||||
// Assign
|
||||
var matcher = new JsonPartialWildcardMatcher("", false, true);
|
||||
|
||||
// Act
|
||||
Action action = () => matcher.IsMatch(new MemoryStream());
|
||||
|
||||
// Assert
|
||||
action.Should().Throw<JsonException>();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void JsonPartialWildcardMatcher_IsMatch_ByteArray()
|
||||
{
|
||||
// Assign
|
||||
var bytes = new byte[0];
|
||||
var matcher = new JsonPartialWildcardMatcher("");
|
||||
|
||||
// Act
|
||||
double match = matcher.IsMatch(bytes);
|
||||
|
||||
// Assert
|
||||
Check.That(match).IsEqualTo(0);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void JsonPartialWildcardMatcher_IsMatch_NullString()
|
||||
{
|
||||
// Assign
|
||||
string s = null;
|
||||
var matcher = new JsonPartialWildcardMatcher("");
|
||||
|
||||
// Act
|
||||
double match = matcher.IsMatch(s);
|
||||
|
||||
// Assert
|
||||
Check.That(match).IsEqualTo(0);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void JsonPartialWildcardMatcher_IsMatch_NullObject()
|
||||
{
|
||||
// Assign
|
||||
object o = null;
|
||||
var matcher = new JsonPartialWildcardMatcher("");
|
||||
|
||||
// Act
|
||||
double match = matcher.IsMatch(o);
|
||||
|
||||
// Assert
|
||||
Check.That(match).IsEqualTo(0);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void JsonPartialWildcardMatcher_IsMatch_JArray()
|
||||
{
|
||||
// Assign
|
||||
var matcher = new JsonPartialWildcardMatcher(new[] { "x", "y" });
|
||||
|
||||
// Act
|
||||
var jArray = new JArray
|
||||
{
|
||||
"x",
|
||||
"y"
|
||||
};
|
||||
double match = matcher.IsMatch(jArray);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(1.0, match);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void JsonPartialWildcardMatcher_IsMatch_JObject()
|
||||
{
|
||||
// Assign
|
||||
var matcher = new JsonPartialWildcardMatcher(new { Id = 1, Name = "Test" });
|
||||
|
||||
// Act
|
||||
var jobject = new JObject
|
||||
{
|
||||
{ "Id", new JValue(1) },
|
||||
{ "Name", new JValue("Test") }
|
||||
};
|
||||
double match = matcher.IsMatch(jobject);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(1.0, match);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void JsonPartialWildcardMatcher_IsMatch_WithIgnoreCaseTrue_JObject()
|
||||
{
|
||||
// Assign
|
||||
var matcher = new JsonPartialWildcardMatcher(new { id = 1, Name = "test" }, true);
|
||||
|
||||
// Act
|
||||
var jobject = new JObject
|
||||
{
|
||||
{ "Id", new JValue(1) },
|
||||
{ "NaMe", new JValue("Test") }
|
||||
};
|
||||
double match = matcher.IsMatch(jobject);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(1.0, match);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void JsonPartialWildcardMatcher_IsMatch_JObjectParsed()
|
||||
{
|
||||
// Assign
|
||||
var matcher = new JsonPartialWildcardMatcher(new { Id = 1, Name = "Test" });
|
||||
|
||||
// Act
|
||||
var jobject = JObject.Parse("{ \"Id\" : 1, \"Name\" : \"Test\" }");
|
||||
double match = matcher.IsMatch(jobject);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(1.0, match);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void JsonPartialWildcardMatcher_IsMatch_WithIgnoreCaseTrue_JObjectParsed()
|
||||
{
|
||||
// Assign
|
||||
var matcher = new JsonPartialWildcardMatcher(new { Id = 1, Name = "TESt" }, true);
|
||||
|
||||
// Act
|
||||
var jobject = JObject.Parse("{ \"Id\" : 1, \"Name\" : \"Test\" }");
|
||||
double match = matcher.IsMatch(jobject);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(1.0, match);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void JsonPartialWildcardMatcher_IsMatch_JArrayAsString()
|
||||
{
|
||||
// Assign
|
||||
var matcher = new JsonPartialWildcardMatcher("[ \"x\", \"y\" ]");
|
||||
|
||||
// Act
|
||||
var jArray = new JArray
|
||||
{
|
||||
"x",
|
||||
"y"
|
||||
};
|
||||
double match = matcher.IsMatch(jArray);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(1.0, match);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void JsonPartialWildcardMatcher_IsMatch_JObjectAsString()
|
||||
{
|
||||
// Assign
|
||||
var matcher = new JsonPartialWildcardMatcher("{ \"Id\" : 1, \"Name\" : \"Test\" }");
|
||||
|
||||
// Act
|
||||
var jobject = new JObject
|
||||
{
|
||||
{ "Id", new JValue(1) },
|
||||
{ "Name", new JValue("Test") }
|
||||
};
|
||||
double match = matcher.IsMatch(jobject);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(1.0, match);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void JsonPartialWildcardMatcher_IsMatch_WithIgnoreCaseTrue_JObjectAsString()
|
||||
{
|
||||
// Assign
|
||||
var matcher = new JsonPartialWildcardMatcher("{ \"Id\" : 1, \"Name\" : \"test\" }", true);
|
||||
|
||||
// Act
|
||||
var jobject = new JObject
|
||||
{
|
||||
{ "Id", new JValue(1) },
|
||||
{ "Name", new JValue("Test") }
|
||||
};
|
||||
double match = matcher.IsMatch(jobject);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(1.0, match);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void JsonPartialWildcardMatcher_IsMatch_JObjectAsString_RejectOnMatch()
|
||||
{
|
||||
// Assign
|
||||
var matcher = new JsonPartialWildcardMatcher(MatchBehaviour.RejectOnMatch, "{ \"Id\" : 1, \"Name\" : \"Test\" }");
|
||||
|
||||
// Act
|
||||
var jobject = new JObject
|
||||
{
|
||||
{ "Id", new JValue(1) },
|
||||
{ "Name", new JValue("Test") }
|
||||
};
|
||||
double match = matcher.IsMatch(jobject);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(0.0, match);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void JsonPartialWildcardMatcher_IsMatch_JObjectWithDateTimeOffsetAsString()
|
||||
{
|
||||
// Assign
|
||||
var matcher = new JsonPartialWildcardMatcher("{ \"preferredAt\" : \"2019-11-21T10:32:53.2210009+00:00\" }");
|
||||
|
||||
// Act
|
||||
var jobject = new JObject
|
||||
{
|
||||
{ "preferredAt", new JValue("2019-11-21T10:32:53.2210009+00:00") }
|
||||
};
|
||||
double match = matcher.IsMatch(jobject);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(1.0, match);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("{\"test\":\"abc\"}", "{\"test\":\"abc\",\"other\":\"xyz\"}")]
|
||||
[InlineData("\"test\"", "\"test\"")]
|
||||
[InlineData("123", "123")]
|
||||
[InlineData("[\"test\"]", "[\"test\"]")]
|
||||
[InlineData("[\"test\"]", "[\"test\", \"other\"]")]
|
||||
[InlineData("[123]", "[123]")]
|
||||
[InlineData("[123]", "[123, 456]")]
|
||||
[InlineData("{ \"test\":\"value\" }", "{\"test\":\"value\",\"other\":123}")]
|
||||
[InlineData("{ \"test\":\"value\" }", "{\"test\":\"value\"}")]
|
||||
[InlineData("{\"test\":{\"nested\":\"value\"}}", "{\"test\":{\"nested\":\"value\"}}")]
|
||||
public void JsonPartialWildcardMatcher_IsMatch_StringInput_IsValidMatch(string value, string input)
|
||||
{
|
||||
// Assign
|
||||
var matcher = new JsonPartialWildcardMatcher(value);
|
||||
|
||||
// Act
|
||||
double match = matcher.IsMatch(input);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(1.0, match);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("{\"test\":\"*\"}", "{\"test\":\"xxx\",\"other\":\"xyz\"}")]
|
||||
[InlineData("\"t*t\"", "\"test\"")]
|
||||
public void JsonPartialWildcardMatcher_IsMatch_StringInputWithWildcard_IsValidMatch(string value, string input)
|
||||
{
|
||||
// Assign
|
||||
var matcher = new JsonPartialWildcardMatcher(value);
|
||||
|
||||
// Act
|
||||
double match = matcher.IsMatch(input);
|
||||
|
||||
// Assert
|
||||
match.Should().Be(1.0);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("\"test\"", null)]
|
||||
[InlineData("\"test1\"", "\"test2\"")]
|
||||
[InlineData("123", "1234")]
|
||||
[InlineData("[\"test\"]", "[\"test1\"]")]
|
||||
[InlineData("[\"test\"]", "[\"test1\", \"test2\"]")]
|
||||
[InlineData("[123]", "[1234]")]
|
||||
[InlineData("{}", "\"test\"")]
|
||||
[InlineData("{ \"test\":\"value\" }", "{\"test\":\"value2\"}")]
|
||||
[InlineData("{ \"test.nested\":\"value\" }", "{\"test\":{\"nested\":\"value1\"}}")]
|
||||
[InlineData("{\"test\":{\"test1\":\"value\"}}", "{\"test\":{\"test1\":\"value1\"}}")]
|
||||
[InlineData("[{ \"test.nested\":\"value\" }]", "[{\"test\":{\"nested\":\"value1\"}}]")]
|
||||
public void JsonPartialWildcardMatcher_IsMatch_StringInputWithInvalidMatch(string value, string input)
|
||||
{
|
||||
// Assign
|
||||
var matcher = new JsonPartialWildcardMatcher(value);
|
||||
|
||||
// Act
|
||||
double match = matcher.IsMatch(input);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(0.0, match);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("{ \"test.nested\":123 }", "{\"test\":{\"nested\":123}}")]
|
||||
[InlineData("{ \"test.nested\":[123, 456] }", "{\"test\":{\"nested\":[123, 456]}}")]
|
||||
[InlineData("{ \"test.nested\":\"value\" }", "{\"test\":{\"nested\":\"value\"}}")]
|
||||
[InlineData("{ \"['name.with.dot']\":\"value\" }", "{\"name.with.dot\":\"value\"}")]
|
||||
[InlineData("[{ \"test.nested\":\"value\" }]", "[{\"test\":{\"nested\":\"value\"}}]")]
|
||||
[InlineData("[{ \"['name.with.dot']\":\"value\" }]", "[{\"name.with.dot\":\"value\"}]")]
|
||||
public void JsonPartialWildcardMatcher_IsMatch_ValueAsJPathValidMatch(string value, string input)
|
||||
{
|
||||
// Assign
|
||||
var matcher = new JsonPartialWildcardMatcher(value);
|
||||
|
||||
// Act
|
||||
double match = matcher.IsMatch(input);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(1.0, match);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("{ \"test.nested\":123 }", "{\"test\":{\"nested\":456}}")]
|
||||
[InlineData("{ \"test.nested\":[123, 456] }", "{\"test\":{\"nested\":[1, 2]}}")]
|
||||
[InlineData("{ \"test.nested\":\"value\" }", "{\"test\":{\"nested\":\"value1\"}}")]
|
||||
[InlineData("{ \"['name.with.dot']\":\"value\" }", "{\"name.with.dot\":\"value1\"}")]
|
||||
[InlineData("[{ \"test.nested\":\"value\" }]", "[{\"test\":{\"nested\":\"value1\"}}]")]
|
||||
[InlineData("[{ \"['name.with.dot']\":\"value\" }]", "[{\"name.with.dot\":\"value1\"}]")]
|
||||
public void JsonPartialWildcardMatcher_IsMatch_ValueAsJPathInvalidMatch(string value, string input)
|
||||
{
|
||||
// Assign
|
||||
var matcher = new JsonPartialWildcardMatcher(value);
|
||||
|
||||
// Act
|
||||
double match = matcher.IsMatch(input);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(0.0, match);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Linq.Expressions;
|
||||
using System.Threading.Tasks;
|
||||
@@ -176,7 +176,7 @@ namespace WireMock.Net.Tests.Owin
|
||||
_mappingMock.SetupGet(m => m.Provider).Returns(responseBuilder);
|
||||
_mappingMock.SetupGet(m => m.Settings).Returns(settings);
|
||||
|
||||
var newMappingFromProxy = new Mapping(Guid.NewGuid(), "", null, settings, Request.Create(), Response.Create(), 0, null, null, null, null, null);
|
||||
var newMappingFromProxy = new Mapping(Guid.NewGuid(), "", null, settings, Request.Create(), Response.Create(), 0, null, null, null, null, null, null);
|
||||
_mappingMock.Setup(m => m.ProvideResponseAsync(It.IsAny<RequestMessage>())).ReturnsAsync((new ResponseMessage(), newMappingFromProxy));
|
||||
|
||||
var requestBuilder = Request.Create().UsingAnyMethod();
|
||||
@@ -230,7 +230,7 @@ namespace WireMock.Net.Tests.Owin
|
||||
_mappingMock.SetupGet(m => m.Provider).Returns(responseBuilder);
|
||||
_mappingMock.SetupGet(m => m.Settings).Returns(settings);
|
||||
|
||||
var newMappingFromProxy = new Mapping(Guid.NewGuid(), "", null, settings, Request.Create(), Response.Create(), 0, null, null, null, null, null);
|
||||
var newMappingFromProxy = new Mapping(Guid.NewGuid(), "", null, settings, Request.Create(), Response.Create(), 0, null, null, null, null, null, null);
|
||||
_mappingMock.Setup(m => m.ProvideResponseAsync(It.IsAny<RequestMessage>())).ReturnsAsync((new ResponseMessage(), newMappingFromProxy));
|
||||
|
||||
var requestBuilder = Request.Create().UsingAnyMethod();
|
||||
|
||||
@@ -51,7 +51,7 @@ namespace WireMock.Net.Tests.Serialization
|
||||
}
|
||||
}
|
||||
};
|
||||
var mapping = new Mapping(Guid.NewGuid(), "", null, _settings, request, response, 0, null, null, null, null, webhooks);
|
||||
var mapping = new Mapping(Guid.NewGuid(), "", null, _settings, request, response, 0, null, null, null, null, webhooks, null);
|
||||
|
||||
// Act
|
||||
var model = _sut.ToMappingModel(mapping);
|
||||
@@ -120,8 +120,7 @@ namespace WireMock.Net.Tests.Serialization
|
||||
}
|
||||
}
|
||||
};
|
||||
var mapping = new Mapping(Guid.NewGuid(), "", null, _settings, request, response, 0, null, null, null, null, webhooks
|
||||
);
|
||||
var mapping = new Mapping(Guid.NewGuid(), "", null, _settings, request, response, 0, null, null, null, null, webhooks, null);
|
||||
|
||||
// Act
|
||||
var model = _sut.ToMappingModel(mapping);
|
||||
@@ -153,7 +152,7 @@ namespace WireMock.Net.Tests.Serialization
|
||||
// Assign
|
||||
var request = Request.Create();
|
||||
var response = Response.Create().WithBodyAsJson(new { x = "x" }).WithTransformer();
|
||||
var mapping = new Mapping(Guid.NewGuid(), "", null, _settings, request, response, 42, null, null, null, null, null);
|
||||
var mapping = new Mapping(Guid.NewGuid(), "", null, _settings, request, response, 42, null, null, null, null, null, null);
|
||||
|
||||
// Act
|
||||
var model = _sut.ToMappingModel(mapping);
|
||||
@@ -164,6 +163,34 @@ namespace WireMock.Net.Tests.Serialization
|
||||
model.Response.UseTransformer.Should().BeTrue();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ToMappingModel_WithTimeSetrtings_ReturnsCorrectTimeSettings()
|
||||
{
|
||||
// Assign
|
||||
var start = DateTime.Now;
|
||||
var ttl = 100;
|
||||
var end = start.AddSeconds(ttl);
|
||||
var request = Request.Create();
|
||||
var response = Response.Create();
|
||||
var timeSettings = new TimeSettings
|
||||
{
|
||||
Start = start,
|
||||
End = end,
|
||||
TTL = ttl
|
||||
};
|
||||
var mapping = new Mapping(Guid.NewGuid(), "", null, _settings, request, response, 42, null, null, null, null, null, timeSettings);
|
||||
|
||||
// Act
|
||||
var model = _sut.ToMappingModel(mapping);
|
||||
|
||||
// Assert
|
||||
model.Should().NotBeNull();
|
||||
model.TimeSettings.Should().NotBeNull();
|
||||
model.TimeSettings.Start.Should().Be(start);
|
||||
model.TimeSettings.End.Should().Be(end);
|
||||
model.TimeSettings.TTL.Should().Be(ttl);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ToMappingModel_WithDelay_ReturnsCorrectModel()
|
||||
{
|
||||
@@ -171,7 +198,7 @@ namespace WireMock.Net.Tests.Serialization
|
||||
int delay = 1000;
|
||||
var request = Request.Create();
|
||||
var response = Response.Create().WithDelay(delay);
|
||||
var mapping = new Mapping(Guid.NewGuid(), "", null, _settings, request, response, 42, null, null, null, null, null);
|
||||
var mapping = new Mapping(Guid.NewGuid(), "", null, _settings, request, response, 42, null, null, null, null, null, null);
|
||||
|
||||
// Act
|
||||
var model = _sut.ToMappingModel(mapping);
|
||||
@@ -182,13 +209,13 @@ namespace WireMock.Net.Tests.Serialization
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ToMappingModel_WithRandomMininumDelay_ReturnsCorrectModel()
|
||||
public void ToMappingModel_WithRandomMinimumDelay_ReturnsCorrectModel()
|
||||
{
|
||||
// Assign
|
||||
int minimumDelay = 1000;
|
||||
var request = Request.Create();
|
||||
var response = Response.Create().WithRandomDelay(minimumDelay);
|
||||
var mapping = new Mapping(Guid.NewGuid(), "", null, _settings, request, response, 42, null, null, null, null, null);
|
||||
var mapping = new Mapping(Guid.NewGuid(), "", null, _settings, request, response, 42, null, null, null, null, null, null);
|
||||
|
||||
// Act
|
||||
var model = _sut.ToMappingModel(mapping);
|
||||
@@ -208,7 +235,7 @@ namespace WireMock.Net.Tests.Serialization
|
||||
int maximumDelay = 2000;
|
||||
var request = Request.Create();
|
||||
var response = Response.Create().WithRandomDelay(minimumDelay, maximumDelay);
|
||||
var mapping = new Mapping(Guid.NewGuid(), "", null, _settings, request, response, 42, null, null, null, null, null);
|
||||
var mapping = new Mapping(Guid.NewGuid(), "", null, _settings, request, response, 42, null, null, null, null, null, null);
|
||||
|
||||
// Act
|
||||
var model = _sut.ToMappingModel(mapping);
|
||||
|
||||
@@ -345,5 +345,24 @@ namespace WireMock.Net.Tests.Serialization
|
||||
matcher.MatchBehaviour.Should().Be(MatchBehaviour.AcceptOnMatch);
|
||||
matcher.Value.Should().BeEquivalentTo(pattern);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void MatcherMapper_Map_MatcherModel_JsonPartialWilcardMatcher_Patterns_As_Object()
|
||||
{
|
||||
// Assign
|
||||
object pattern = new { X = "*" };
|
||||
var model = new MatcherModel
|
||||
{
|
||||
Name = "JsonPartialWildcardMatcher",
|
||||
Pattern = pattern
|
||||
};
|
||||
|
||||
// Act
|
||||
var matcher = (JsonPartialWildcardMatcher)_sut.Map(model);
|
||||
|
||||
// Assert
|
||||
matcher.MatchBehaviour.Should().Be(MatchBehaviour.AcceptOnMatch);
|
||||
matcher.Value.Should().BeEquivalentTo(pattern);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<!--<PackageReference Include="Mapster" Version="7.2.0" />-->
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.5.0" />
|
||||
<PackageReference Include="xunit" Version="2.4.1" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
|
||||
@@ -51,7 +52,7 @@
|
||||
<PackageReference Include="Moq" Version="4.16.0" />
|
||||
<PackageReference Include="System.Threading" Version="4.3.0" />
|
||||
<PackageReference Include="RestEase" Version="1.5.5" />
|
||||
<PackageReference Include="RandomDataGenerator.Net" Version="1.0.12" />
|
||||
<PackageReference Include="RandomDataGenerator.Net" Version="1.0.13" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.5.0" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="11.0.2" />
|
||||
<PackageReference Include="NFluent" Version="2.7.1" />
|
||||
@@ -59,8 +60,9 @@
|
||||
<!--<PackageReference Include="ReportGenerator" Version="4.8.1" />-->
|
||||
<PackageReference Include="SimMetrics.Net" Version="1.0.5" />
|
||||
<PackageReference Include="System.Linq.Dynamic.Core" Version="1.0.12" />
|
||||
<!--<PackageReference Include="StrongNamer" Version="0.0.8" />-->
|
||||
<!--<PackageReference Include="StrongNamer" Version="0.2.5" />-->
|
||||
<PackageReference Include="AnyOf" Version="0.2.0" />
|
||||
<!--<PackageReference Include="TinyMapper" Version="3.0.3" />-->
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition="'$(TargetFramework)' == 'net452' or '$(TargetFramework)' == 'net461'">
|
||||
|
||||
Reference in New Issue
Block a user