Update the OpenApiPathsMapper to handle Value/Wildcard (#691)

This commit is contained in:
Stef Heyenrath
2021-11-23 08:09:38 +01:00
committed by GitHub
parent 8865543bf1
commit 897ee9ffe3
8 changed files with 77 additions and 58 deletions

View File

@@ -8,11 +8,11 @@ namespace WireMock.Net.OpenApiParser.ConsoleApp
private const string Folder = "OpenApiFiles"; private const string Folder = "OpenApiFiles";
static void Main(string[] args) static void Main(string[] args)
{ {
var serverOpenAPIExamples = Run.RunServer(Path.Combine(Folder, "openAPIExamples.yaml"), "http://localhost:9091/"); var serverOpenAPIExamples = Run.RunServer(Path.Combine(Folder, "openAPIExamples.yaml"), "https://localhost:9091/");
var serverPetstore_V2_json = Run.RunServer(Path.Combine(Folder, "Swagger_Petstore_V2.0.json"), "http://localhost:9092/"); var serverPetstore_V2_json = Run.RunServer(Path.Combine(Folder, "Swagger_Petstore_V2.0.json"), "https://localhost:9092/");
var serverPetstore_V2_yaml = Run.RunServer(Path.Combine(Folder, "Swagger_Petstore_V2.0.yaml"), "http://localhost:9093/"); var serverPetstore_V2_yaml = Run.RunServer(Path.Combine(Folder, "Swagger_Petstore_V2.0.yaml"), "https://localhost:9093/");
var serverPetstore_V300_yaml = Run.RunServer(Path.Combine(Folder, "Swagger_Petstore_V3.0.0.yaml"), "http://localhost:9094/"); var serverPetstore_V300_yaml = Run.RunServer(Path.Combine(Folder, "Swagger_Petstore_V3.0.0.yaml"), "https://localhost:9094/");
var serverPetstore_V302_json = Run.RunServer(Path.Combine(Folder, "Swagger_Petstore_V3.0.2.json"), "http://localhost:9095/"); var serverPetstore_V302_json = Run.RunServer(Path.Combine(Folder, "Swagger_Petstore_V3.0.2.json"), "https://localhost:9095/");
Console.WriteLine("Press any key to stop the servers"); Console.WriteLine("Press any key to stop the servers");
Console.ReadKey(); Console.ReadKey();

View File

@@ -13,7 +13,7 @@ namespace WireMock.Net.OpenApiParser.ConsoleApp
{ {
public static class Run public static class Run
{ {
public static WireMockServer RunServer(string path, string url) public static WireMockServer RunServer(string path, string url, bool dynamicExamples = true)
{ {
var server = WireMockServer.Start(new WireMockServerSettings var server = WireMockServer.Start(new WireMockServerSettings
{ {
@@ -31,7 +31,9 @@ namespace WireMock.Net.OpenApiParser.ConsoleApp
var settings = new WireMockOpenApiParserSettings var settings = new WireMockOpenApiParserSettings
{ {
PathPatternToUse = ExampleValueType.Wildcard DynamicExamples = dynamicExamples,
PathPatternToUse = ExampleValueType.Wildcard,
HeaderPatternToUse = ExampleValueType.Wildcard
}; };
server.WithMappingFromOpenApiFile(path, settings, out var diag); server.WithMappingFromOpenApiFile(path, settings, out var diag);

View File

@@ -1,8 +1,8 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<OutputType>Exe</OutputType> <OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.1</TargetFramework> <TargetFramework>net5.0</TargetFramework>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@@ -0,0 +1,21 @@
#if NET46 || NETSTANDARD2_0
using System.Collections.Generic;
namespace WireMock.Net.OpenApiParser.Extensions
{
internal static class DictionaryExtensions
{
public static bool TryAdd<TKey, TValue>(this Dictionary<TKey, TValue> dictionary, TKey key, TValue value)
{
if (dictionary is null || dictionary.ContainsKey(key))
{
return false;
}
dictionary[key] = value;
return true;
}
}
}
#endif

View File

@@ -19,6 +19,8 @@ namespace WireMock.Net.OpenApiParser.Mappers
{ {
internal class OpenApiPathsMapper internal class OpenApiPathsMapper
{ {
private const string HeaderContentType = "Content-Type";
private readonly WireMockOpenApiParserSettings _settings; private readonly WireMockOpenApiParserSettings _settings;
private readonly ExampleValueGenerator _exampleValueGenerator; private readonly ExampleValueGenerator _exampleValueGenerator;
@@ -248,6 +250,7 @@ namespace WireMock.Net.OpenApiParser.Mappers
return new JProperty(key, _exampleValueGenerator.GetExampleValue(openApiSchema)); return new JProperty(key, _exampleValueGenerator.GetExampleValue(openApiSchema));
} }
} }
private string MapPathWithParameters(string path, IEnumerable<OpenApiParameter> parameters) private string MapPathWithParameters(string path, IEnumerable<OpenApiParameter> parameters)
{ {
if (parameters == null) if (parameters == null)
@@ -258,7 +261,8 @@ namespace WireMock.Net.OpenApiParser.Mappers
string newPath = path; string newPath = path;
foreach (var parameter in parameters) foreach (var parameter in parameters)
{ {
newPath = newPath.Replace($"{{{parameter.Name}}}", GetExampleValue(parameter.Schema, _settings.PathPatternToUse)); var exampleMatcherModel = GetExampleMatcherModel(parameter.Schema, _settings.PathPatternToUse);
newPath = newPath.Replace($"{{{parameter.Name}}}", exampleMatcherModel.Pattern as string);
} }
return newPath; return newPath;
@@ -305,19 +309,12 @@ namespace WireMock.Net.OpenApiParser.Mappers
{ {
var mappedHeaders = headers.ToDictionary( var mappedHeaders = headers.ToDictionary(
item => item.Key, item => item.Key,
item => GetExampleValue(null, _settings.HeaderPatternToUse) as object item => GetExampleMatcherModel(null, _settings.HeaderPatternToUse).Pattern
); );
if (!string.IsNullOrEmpty(responseContentType)) if (!string.IsNullOrEmpty(responseContentType))
{ {
if (!mappedHeaders.ContainsKey("Content-Type")) mappedHeaders.TryAdd(HeaderContentType, responseContentType);
{
mappedHeaders.Add("Content-Type", responseContentType);
}
else
{
mappedHeaders["Content-Type"] = responseContentType;
}
} }
return mappedHeaders.Keys.Any() ? mappedHeaders : null; return mappedHeaders.Keys.Any() ? mappedHeaders : null;
@@ -331,11 +328,7 @@ namespace WireMock.Net.OpenApiParser.Mappers
Name = qp.Name, Name = qp.Name,
Matchers = new[] Matchers = new[]
{ {
new MatcherModel GetExampleMatcherModel(qp.Schema, _settings.QueryParameterPatternToUse)
{
Name = "ExactMatcher",
Pattern = GetDefaultValueAsStringForSchemaType(qp.Schema)
}
} }
}) })
.ToList(); .ToList();
@@ -351,11 +344,7 @@ namespace WireMock.Net.OpenApiParser.Mappers
Name = qp.Name, Name = qp.Name,
Matchers = new[] Matchers = new[]
{ {
new MatcherModel GetExampleMatcherModel(qp.Schema, _settings.HeaderPatternToUse)
{
Name = "ExactMatcher",
Pattern = GetDefaultValueAsStringForSchemaType(qp.Schema)
}
} }
}) })
.ToList(); .ToList();
@@ -363,30 +352,26 @@ namespace WireMock.Net.OpenApiParser.Mappers
return list.Any() ? list : null; return list.Any() ? list : null;
} }
private string GetDefaultValueAsStringForSchemaType(OpenApiSchema schema) private MatcherModel GetExampleMatcherModel(OpenApiSchema schema, ExampleValueType type)
{
return type switch
{
ExampleValueType.Value => new MatcherModel { Name = "ExactMatcher", Pattern = GetExampleValueAsStringForSchemaType(schema) },
_ => new MatcherModel { Name = "WildcardMatcher", Pattern = "*" }
};
}
private string GetExampleValueAsStringForSchemaType(OpenApiSchema schema)
{ {
var value = _exampleValueGenerator.GetExampleValue(schema); var value = _exampleValueGenerator.GetExampleValue(schema);
switch (value) return value switch
{ {
case string valueAsString: string valueAsString => valueAsString,
return valueAsString;
default: _ => value.ToString(),
return value.ToString(); };
}
}
private string GetExampleValue(OpenApiSchema schema, ExampleValueType type)
{
switch (type)
{
case ExampleValueType.Value:
return GetDefaultValueAsStringForSchemaType(schema);
default:
return "*";
}
} }
} }
} }

View File

@@ -1,4 +1,4 @@
using WireMock.Net.OpenApiParser.Types; using WireMock.Net.OpenApiParser.Types;
namespace WireMock.Net.OpenApiParser.Settings namespace WireMock.Net.OpenApiParser.Settings
{ {
@@ -22,10 +22,15 @@ namespace WireMock.Net.OpenApiParser.Settings
/// </summary> /// </summary>
public ExampleValueType HeaderPatternToUse { get; set; } = ExampleValueType.Value; public ExampleValueType HeaderPatternToUse { get; set; } = ExampleValueType.Value;
/// <summary>
/// The example value type to use when generating a Query Parameter
/// </summary>
public ExampleValueType QueryParameterPatternToUse { get; set; } = ExampleValueType.Value;
/// <summary> /// <summary>
/// The example values to use /// The example values to use
/// </summary> /// </summary>
public IWireMockOpenApiParserExampleValues ExampleValues { get; set; } = new WireMockOpenApiParserExampleValues(); public IWireMockOpenApiParserExampleValues ExampleValues { get; set; }
/// <summary> /// <summary>
/// Are examples generated dynamically? /// Are examples generated dynamically?

View File

@@ -1,4 +1,4 @@
namespace WireMock.Net.OpenApiParser.Types namespace WireMock.Net.OpenApiParser.Types
{ {
/// <summary> /// <summary>
/// The example value to use /// The example value to use
@@ -6,7 +6,9 @@
public enum ExampleValueType public enum ExampleValueType
{ {
/// <summary> /// <summary>
/// Use a generated example value based on the SchemaType (default). /// 1. Use a generated example value based on the SchemaType (default).
/// 2. If there is no example value defined in the schema,
/// then the <see cref="Settings.IWireMockOpenApiParserExampleValues"/> will be used (custom, fixed or dynamic).
/// </summary> /// </summary>
Value, Value,

View File

@@ -17,13 +17,17 @@ namespace WireMock.Net.OpenApiParser.Utils
{ {
_settings = Guard.NotNull(settings, nameof(settings)); _settings = Guard.NotNull(settings, nameof(settings));
if (_settings.DynamicExamples) // Check if user provided an own implementation
if (settings.ExampleValues is null)
{ {
_settings.ExampleValues = new WireMockOpenApiParserDynamicExampleValues(); if (_settings.DynamicExamples)
} {
else _settings.ExampleValues = new WireMockOpenApiParserDynamicExampleValues();
{ }
_settings.ExampleValues = new WireMockOpenApiParserExampleValues(); else
{
_settings.ExampleValues = new WireMockOpenApiParserExampleValues();
}
} }
} }