From f0969e9618fb696ca7650ec050927f17ce1ecb24 Mon Sep 17 00:00:00 2001 From: Stef Heyenrath Date: Thu, 10 Sep 2026 20:28:43 +0200 Subject: [PATCH] Upgrade dependency RamlToOpenApiConverter to version 0.40.0 (#1505) * Upgrade dependency RamlToOpenApiConverter to version 0.40.0 * fix code comment * . * Potential fix for pull request finding 'Constant condition' Co-authored-by: Copilot Autofix powered by AI <223894421+github-code-quality[bot]@users.noreply.github.com> * Potential fix for pull request finding 'Constant condition' Co-authored-by: Copilot Autofix powered by AI <223894421+github-code-quality[bot]@users.noreply.github.com> * fix --------- Co-authored-by: Copilot Autofix powered by AI <223894421+github-code-quality[bot]@users.noreply.github.com> --- ...reMock.Net.OpenApiParser.ConsoleApp.csproj | 2 +- .../Extensions/DictionaryExtensions.cs | 33 ++++++++++-- .../Extensions/OpenApiSchemaExtensions.cs | 50 +++++++------------ .../Extensions/WireMockServerExtensions.cs | 19 ++++--- .../ILRepack.targets | 29 ----------- .../IWireMockOpenApiParser.cs | 10 ++-- .../Mappers/OpenApiPathsMapper.cs | 31 ++++-------- .../Models/OpenApiDiagnostic.cs | 28 ----------- .../Models/OpenApiError.cs | 46 ----------------- .../Models/OpenApiMapper.cs | 25 ---------- .../Utils/ExampleValueGenerator.cs | 2 +- .../WireMock.Net.OpenApiParser.csproj | 16 +----- .../WireMockOpenApiParser.cs | 47 +++++++++++------ .../WireMockOpenApiParserTests.cs | 35 ++++++++++++- .../OpenApiParser/invalid.yaml | 12 +++++ 15 files changed, 158 insertions(+), 227 deletions(-) delete mode 100644 src/WireMock.Net.OpenApiParser/ILRepack.targets delete mode 100644 src/WireMock.Net.OpenApiParser/Models/OpenApiDiagnostic.cs delete mode 100644 src/WireMock.Net.OpenApiParser/Models/OpenApiError.cs delete mode 100644 src/WireMock.Net.OpenApiParser/Models/OpenApiMapper.cs create mode 100644 test/WireMock.Net.Tests/OpenApiParser/invalid.yaml diff --git a/examples/WireMock.Net.OpenApiParser.ConsoleApp/WireMock.Net.OpenApiParser.ConsoleApp.csproj b/examples/WireMock.Net.OpenApiParser.ConsoleApp/WireMock.Net.OpenApiParser.ConsoleApp.csproj index d2651422..e35ba9fd 100644 --- a/examples/WireMock.Net.OpenApiParser.ConsoleApp/WireMock.Net.OpenApiParser.ConsoleApp.csproj +++ b/examples/WireMock.Net.OpenApiParser.ConsoleApp/WireMock.Net.OpenApiParser.ConsoleApp.csproj @@ -6,7 +6,7 @@ - + diff --git a/src/WireMock.Net.OpenApiParser/Extensions/DictionaryExtensions.cs b/src/WireMock.Net.OpenApiParser/Extensions/DictionaryExtensions.cs index 90546815..aec4ac2f 100644 --- a/src/WireMock.Net.OpenApiParser/Extensions/DictionaryExtensions.cs +++ b/src/WireMock.Net.OpenApiParser/Extensions/DictionaryExtensions.cs @@ -1,10 +1,13 @@ // Copyright © WireMock.Net -#if NETSTANDARD2_0 + +using System.Diagnostics.CodeAnalysis; + namespace System.Collections.Generic; internal static class DictionaryExtensions { +#if NETSTANDARD2_0 public static bool TryAdd(this Dictionary? dictionary, TKey key, TValue value) { if (dictionary is null || dictionary.ContainsKey(key)) @@ -16,5 +19,29 @@ internal static class DictionaryExtensions return true; } -} -#endif \ No newline at end of file +#endif + + public static bool TryGetFirstValue(this IDictionary? dictionary, out TValue? value) + { + if (dictionary != null && dictionary.Count > 0) + { + value = dictionary.First().Value; + return true; + } + + value = default; + return false; + } + + public static bool TryGetFirstOrDefault(this IDictionary? dictionary, out KeyValuePair value) + { + if (dictionary != null && dictionary.Count > 0) + { + value = dictionary.First(); + return true; + } + + value = default; + return false; + } +} \ No newline at end of file diff --git a/src/WireMock.Net.OpenApiParser/Extensions/OpenApiSchemaExtensions.cs b/src/WireMock.Net.OpenApiParser/Extensions/OpenApiSchemaExtensions.cs index dc17200c..b1be2f55 100644 --- a/src/WireMock.Net.OpenApiParser/Extensions/OpenApiSchemaExtensions.cs +++ b/src/WireMock.Net.OpenApiParser/Extensions/OpenApiSchemaExtensions.cs @@ -1,7 +1,5 @@ // Copyright © WireMock.Net -using System.Collections.Generic; -using System.Linq; using System.Reflection; using System.Text.Json; using System.Text.Json.Nodes; @@ -56,37 +54,25 @@ internal static class OpenApiSchemaExtensions public static SchemaFormat GetSchemaFormat(this IOpenApiSchema? schema) { - switch (schema?.Format) + return (schema?.Format) switch { - case "float": - return SchemaFormat.Float; + "float" => SchemaFormat.Float, + "double" => SchemaFormat.Double, + "int32" => SchemaFormat.Int32, + "int64" => SchemaFormat.Int64, + "date" => SchemaFormat.Date, + "date-time" => SchemaFormat.DateTime, + "password" => SchemaFormat.Password, + "byte" => SchemaFormat.Byte, + "binary" => SchemaFormat.Binary, + _ => SchemaFormat.Undefined, + }; + } - case "double": - return SchemaFormat.Double; - - case "int32": - return SchemaFormat.Int32; - - case "int64": - return SchemaFormat.Int64; - - case "date": - return SchemaFormat.Date; - - case "date-time": - return SchemaFormat.DateTime; - - case "password": - return SchemaFormat.Password; - - case "byte": - return SchemaFormat.Byte; - - case "binary": - return SchemaFormat.Binary; - - default: - return SchemaFormat.Undefined; - } + internal static JsonNode? FindFirstExample(this IOpenApiSchema? schema) + { +#pragma warning disable CS0618 // Type or member is obsolete + return schema?.Examples?.FirstOrDefault() ?? schema?.Example; +#pragma warning restore CS0618 // Type or member is obsolete } } \ No newline at end of file diff --git a/src/WireMock.Net.OpenApiParser/Extensions/WireMockServerExtensions.cs b/src/WireMock.Net.OpenApiParser/Extensions/WireMockServerExtensions.cs index 12297f65..7e763b55 100644 --- a/src/WireMock.Net.OpenApiParser/Extensions/WireMockServerExtensions.cs +++ b/src/WireMock.Net.OpenApiParser/Extensions/WireMockServerExtensions.cs @@ -1,10 +1,8 @@ // Copyright © WireMock.Net -using System.IO; -using System.Linq; using JetBrains.Annotations; +using Microsoft.OpenApi.Reader; using Stef.Validation; -using WireMock.Net.OpenApiParser.Models; using WireMock.Net.OpenApiParser.Settings; using WireMock.Server; @@ -16,7 +14,8 @@ namespace WireMock.Net.OpenApiParser.Extensions; public static class WireMockServerExtensions { /// - /// Register the mappings via an OpenAPI (swagger) V2/V3/V3.1 file. + /// Register the mappings via an OpenAPI (swagger) V2/V3/V3.1/V3.2 file. + /// In case of an error, no mappings are registered and contains the error details. /// /// The WireMockServer instance /// Path containing OpenAPI file to parse and use the mappings. @@ -28,7 +27,8 @@ public static class WireMockServerExtensions } /// - /// Register the mappings via an OpenAPI (swagger) V2/V3/V3.1 file. + /// Register the mappings via an OpenAPI (swagger) V2/V3/V3.1/V3.2 file. + /// In case of an error, no mappings are registered and contains the error details. /// /// The WireMockServer instance /// Path containing OpenAPI file to parse and use the mappings. @@ -46,7 +46,8 @@ public static class WireMockServerExtensions } /// - /// Register the mappings via an OpenAPI (swagger) V2/V3/V3.1 stream. + /// Register the mappings via an OpenAPI (swagger) V2/V3/V3.1/V3.2 stream. + /// In case of an error, no mappings are registered and contains the error details. /// /// The WireMockServer instance /// Stream containing OpenAPI description to parse and use the mappings. @@ -58,7 +59,8 @@ public static class WireMockServerExtensions } /// - /// Register the mappings via an OpenAPI (swagger) V2/V3/V3.1 stream. + /// Register the mappings via an OpenAPI (swagger) V2/V3/V3.1/V3.2 stream. + /// In case of an error, no mappings are registered and contains the error details. /// /// The WireMockServer instance /// Stream containing OpenAPI description to parse and use the mappings. @@ -77,7 +79,8 @@ public static class WireMockServerExtensions } /// - /// Register the mappings via an OpenAPI (swagger) V2/V3/V3.1 document. + /// Register the mappings via an OpenAPI (swagger) V2/V3/V3.1/V3.2 document. + /// In case of an error, no mappings are registered and contains the error details. /// /// The WireMockServer instance /// The OpenAPI document to use as mappings. diff --git a/src/WireMock.Net.OpenApiParser/ILRepack.targets b/src/WireMock.Net.OpenApiParser/ILRepack.targets deleted file mode 100644 index ae5e5336..00000000 --- a/src/WireMock.Net.OpenApiParser/ILRepack.targets +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/WireMock.Net.OpenApiParser/IWireMockOpenApiParser.cs b/src/WireMock.Net.OpenApiParser/IWireMockOpenApiParser.cs index 62f1588b..7c451558 100644 --- a/src/WireMock.Net.OpenApiParser/IWireMockOpenApiParser.cs +++ b/src/WireMock.Net.OpenApiParser/IWireMockOpenApiParser.cs @@ -1,9 +1,7 @@ // Copyright © WireMock.Net -using System.Collections.Generic; -using System.IO; +using Microsoft.OpenApi.Reader; using WireMock.Admin.Mappings; -using WireMock.Net.OpenApiParser.Models; using WireMock.Net.OpenApiParser.Settings; namespace WireMock.Net.OpenApiParser; @@ -15,6 +13,7 @@ public interface IWireMockOpenApiParser { /// /// Generate from a file-path. + /// In case of an error, an empty list is returned and contains the error details. /// /// The path to read the OpenApi/Swagger/V2/V3/V31 or Raml file. /// OpenApiDiagnostic output @@ -23,6 +22,7 @@ public interface IWireMockOpenApiParser /// /// Generate from a file-path. + /// In case of an error, an empty list is returned and contains the error details. /// /// The path to read the OpenApi/Swagger/V2/V3/V31 or Raml file. /// Additional settings @@ -40,6 +40,7 @@ public interface IWireMockOpenApiParser /// /// Generate from a . + /// In case of an error, an empty list is returned and contains the error details. /// /// The source stream /// OpenApiDiagnostic output @@ -48,6 +49,7 @@ public interface IWireMockOpenApiParser /// /// Generate from a . + /// In case of an error, an empty list is returned and contains the error details. /// /// The source stream /// Additional settings @@ -57,6 +59,7 @@ public interface IWireMockOpenApiParser /// /// Generate from a . + /// In case of an error, an empty list is returned and contains the error details. /// /// The source text /// OpenApiDiagnostic output @@ -65,6 +68,7 @@ public interface IWireMockOpenApiParser /// /// Generate from a . + /// In case of an error, an empty list is returned and contains the error details. /// /// The source text /// Additional settings diff --git a/src/WireMock.Net.OpenApiParser/Mappers/OpenApiPathsMapper.cs b/src/WireMock.Net.OpenApiParser/Mappers/OpenApiPathsMapper.cs index 088d1fd8..866a7419 100644 --- a/src/WireMock.Net.OpenApiParser/Mappers/OpenApiPathsMapper.cs +++ b/src/WireMock.Net.OpenApiParser/Mappers/OpenApiPathsMapper.cs @@ -53,7 +53,7 @@ internal class OpenApiPathsMapper(WireMockOpenApiParserSettings settings) Headers = MapRequestHeaders(requestHeaders), Body = GetRequestBodyModel(operation.RequestBody) }, - Response = GetResponseModel(operation.Responses?.FirstOrDefault()) + Response = operation.Responses?.TryGetFirstOrDefault(out var firstResponse) == true ? GetResponseModel(firstResponse) : new ResponseModel { StatusCode = 200 } }; } @@ -70,8 +70,7 @@ internal class OpenApiPathsMapper(WireMockOpenApiParserSettings settings) var requestExample = requestContent?.Example; var requestExamples = requestContent?.Examples; - var requestSchemaExample = requestContent?.Schema?.Example; - var requestSchemaExamples = requestContent?.Schema?.Examples; + var requestSchemaExample = requestContent?.Schema.FindFirstExample(); JsonNode? request; if (requestExample != null) @@ -86,10 +85,6 @@ internal class OpenApiPathsMapper(WireMockOpenApiParserSettings settings) { request = requestExamples.FirstOrDefault().Value.Value; } - else if (requestSchemaExamples != null) - { - request = requestSchemaExamples.FirstOrDefault(); - } else { var requestSchema = content?.FirstOrDefault().Value.Schema; @@ -99,16 +94,15 @@ internal class OpenApiPathsMapper(WireMockOpenApiParserSettings settings) return MapRequestBody(request) ?? new BodyModel(); } - private ResponseModel GetResponseModel(KeyValuePair? openApiResponse) + private ResponseModel GetResponseModel(KeyValuePair openApiResponse) { - var content = openApiResponse?.Value.Content; + var content = openApiResponse.Value.Content; TryGetContent(content, out var responseContent, out var contentType); var responseExample = responseContent?.Example; var responseExamples = responseContent?.Examples; - var responseSchemaExample = responseContent?.Schema?.Example; - var responseSchemaExamples = responseContent?.Schema?.Examples; + var responseSchemaExample = responseContent?.Schema.FindFirstExample(); JsonNode? response; if (responseExample != null) @@ -119,24 +113,19 @@ internal class OpenApiPathsMapper(WireMockOpenApiParserSettings settings) { response = responseSchemaExample; } - else if (responseExamples != null) + else if (responseExamples.TryGetFirstValue(out var firstResponseFromExamples)) { - response = responseExamples.FirstOrDefault().Value.Value; - } - else if (responseSchemaExamples != null) - { - response = responseSchemaExamples.FirstOrDefault(); + response = firstResponseFromExamples?.Value; } else { - var responseSchema = content?.FirstOrDefault().Value?.Schema; - response = MapSchemaToObject(responseSchema); + response = content.TryGetFirstValue(out var firstContent) ? MapSchemaToObject(firstContent?.Schema) : null; } return new ResponseModel { - StatusCode = int.TryParse(openApiResponse?.Key, out var httpStatusCode) ? httpStatusCode : 200, - Headers = MapHeaders(contentType, openApiResponse?.Value.Headers), + StatusCode = int.TryParse(openApiResponse.Key, out var httpStatusCode) ? httpStatusCode : 200, + Headers = MapHeaders(contentType, openApiResponse.Value.Headers), BodyAsJson = response != null ? JsonConvert.DeserializeObject(SystemTextJsonSerializer.Serialize(response)) : null }; } diff --git a/src/WireMock.Net.OpenApiParser/Models/OpenApiDiagnostic.cs b/src/WireMock.Net.OpenApiParser/Models/OpenApiDiagnostic.cs deleted file mode 100644 index 97473e60..00000000 --- a/src/WireMock.Net.OpenApiParser/Models/OpenApiDiagnostic.cs +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT license. - -using System.Collections.Generic; -using RamlToOpenApiConverter; - -namespace WireMock.Net.OpenApiParser.Models; - -/// -/// Object containing all diagnostic information related to Open API parsing. -/// -public class OpenApiDiagnostic -{ - /// - /// List of all errors. - /// - public List Errors { get; set; } = []; - - /// - /// List of all warnings - /// - public List Warnings { get; set; } = []; - - /// - /// Open API specification version of the document parsed. - /// - public OpenApiSpecificationVersion SpecificationVersion { get; set; } -} \ No newline at end of file diff --git a/src/WireMock.Net.OpenApiParser/Models/OpenApiError.cs b/src/WireMock.Net.OpenApiParser/Models/OpenApiError.cs deleted file mode 100644 index b3d8bbe0..00000000 --- a/src/WireMock.Net.OpenApiParser/Models/OpenApiError.cs +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT license. - -namespace WireMock.Net.OpenApiParser.Models; - -/// -/// Error related to the Open API Document. -/// -public class OpenApiError -{ - /// - /// Initializes the class. - /// - public OpenApiError(string? pointer, string message) - { - Pointer = pointer; - Message = message; - } - - /// - /// Initializes a copy of an object - /// - public OpenApiError(OpenApiError error) - { - Pointer = error.Pointer; - Message = error.Message; - } - - /// - /// Message explaining the error. - /// - public string Message { get; set; } - - /// - /// Pointer to the location of the error. - /// - public string? Pointer { get; set; } - - /// - /// Gets the string representation of . - /// - public override string ToString() - { - return Message + (!string.IsNullOrEmpty(Pointer) ? " [" + Pointer + "]" : ""); - } -} \ No newline at end of file diff --git a/src/WireMock.Net.OpenApiParser/Models/OpenApiMapper.cs b/src/WireMock.Net.OpenApiParser/Models/OpenApiMapper.cs deleted file mode 100644 index 9d84712e..00000000 --- a/src/WireMock.Net.OpenApiParser/Models/OpenApiMapper.cs +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright © WireMock.Net - -using System.Linq; -using RamlToOpenApiConverter; -using MicrosoftOpenApiDiagnostic = Microsoft.OpenApi.Reader.OpenApiDiagnostic; - -namespace WireMock.Net.OpenApiParser.Models; - -internal static class OpenApiMapper -{ - internal static OpenApiDiagnostic? Map(MicrosoftOpenApiDiagnostic? openApiDiagnostic) - { - if (openApiDiagnostic == null) - { - return null; - } - - return new OpenApiDiagnostic - { - Errors = openApiDiagnostic.Errors.Select(e => new OpenApiError(e.Pointer, e.Message)).ToList(), - Warnings = openApiDiagnostic.Warnings.Select(e => new OpenApiError(e.Pointer, e.Message)).ToList(), - SpecificationVersion = (OpenApiSpecificationVersion)openApiDiagnostic.SpecificationVersion - }; - } -} \ No newline at end of file diff --git a/src/WireMock.Net.OpenApiParser/Utils/ExampleValueGenerator.cs b/src/WireMock.Net.OpenApiParser/Utils/ExampleValueGenerator.cs index 2560873f..1ee9920f 100644 --- a/src/WireMock.Net.OpenApiParser/Utils/ExampleValueGenerator.cs +++ b/src/WireMock.Net.OpenApiParser/Utils/ExampleValueGenerator.cs @@ -39,7 +39,7 @@ internal class ExampleValueGenerator public JsonNode GetExampleValue(IOpenApiSchema? schema) { - var schemaExample = schema?.Example; + var schemaExample = schema?.FindFirstExample(); var schemaEnum = schema?.Enum?.FirstOrDefault(); _exampleValues.Schema = schema; diff --git a/src/WireMock.Net.OpenApiParser/WireMock.Net.OpenApiParser.csproj b/src/WireMock.Net.OpenApiParser/WireMock.Net.OpenApiParser.csproj index e0e78b5b..3a603126 100644 --- a/src/WireMock.Net.OpenApiParser/WireMock.Net.OpenApiParser.csproj +++ b/src/WireMock.Net.OpenApiParser/WireMock.Net.OpenApiParser.csproj @@ -1,4 +1,4 @@ - + An OpenApi (swagger) parser to generate MappingModel or mapping.json file. @@ -40,23 +40,11 @@ - - + - - - - - - - - - - - diff --git a/src/WireMock.Net.OpenApiParser/WireMockOpenApiParser.cs b/src/WireMock.Net.OpenApiParser/WireMockOpenApiParser.cs index 3ef51247..5d675ef3 100644 --- a/src/WireMock.Net.OpenApiParser/WireMockOpenApiParser.cs +++ b/src/WireMock.Net.OpenApiParser/WireMockOpenApiParser.cs @@ -1,8 +1,6 @@ // Copyright © WireMock.Net -using System; -using System.Collections.Generic; -using System.IO; +using System.Diagnostics.CodeAnalysis; using System.Text; using JetBrains.Annotations; using Microsoft.OpenApi; @@ -11,14 +9,12 @@ using Microsoft.OpenApi.YamlReader; using RamlToOpenApiConverter; using WireMock.Admin.Mappings; using WireMock.Net.OpenApiParser.Mappers; -using WireMock.Net.OpenApiParser.Models; using WireMock.Net.OpenApiParser.Settings; -using OpenApiDiagnostic = WireMock.Net.OpenApiParser.Models.OpenApiDiagnostic; namespace WireMock.Net.OpenApiParser; /// -/// Parse a OpenApi/Swagger/V2/V3/V3.1 to WireMock.Net MappingModels. +/// Parse a OpenApi/Swagger/V2/V3/V3.1/V3.2 to WireMock.Net MappingModels. /// public class WireMockOpenApiParser : IWireMockOpenApiParser { @@ -32,8 +28,15 @@ public class WireMockOpenApiParser : IWireMockOpenApiParser _readerSettings = new OpenApiReaderSettings(); _readerSettings.AddMicrosoftExtensionParsers(); _readerSettings.AddJsonReader(); - _readerSettings.TryAddReader(OpenApiConstants.Yaml, new OpenApiYamlReader()); - _readerSettings.TryAddReader(OpenApiConstants.Yml, new OpenApiYamlReader()); + + var openApiYamlReaderSettings = new OpenApiYamlReaderSettings + { + MaxAliasExpansionNodeCount = 1_000_000 + }; + var openApiYamlReader = new OpenApiYamlReader(openApiYamlReaderSettings); + + _readerSettings.TryAddReader(OpenApiConstants.Yaml, openApiYamlReader); + _readerSettings.TryAddReader(OpenApiConstants.Yml, openApiYamlReader); } /// @@ -55,7 +58,12 @@ public class WireMockOpenApiParser : IWireMockOpenApiParser } else { - document = Read(File.OpenRead(path), out diagnostic); + if (!TryRead(File.OpenRead(path), out var documentFromYaml, out diagnostic)) + { + return []; + } + + document = documentFromYaml; } return FromDocument(document, settings); @@ -74,14 +82,24 @@ public class WireMockOpenApiParser : IWireMockOpenApiParser [PublicAPI] public IReadOnlyList FromStream(Stream stream, out OpenApiDiagnostic diagnostic) { - return FromDocument(Read(stream, out diagnostic)); + if (TryRead(stream, out var openApiDocument, out diagnostic)) + { + return FromDocument(openApiDocument); + } + + return []; } /// [PublicAPI] public IReadOnlyList FromStream(Stream stream, WireMockOpenApiParserSettings settings, out OpenApiDiagnostic diagnostic) { - return FromDocument(Read(stream, out diagnostic), settings); + if (TryRead(stream, out var openApiDocument, out diagnostic)) + { + return FromDocument(openApiDocument, settings); + } + + return []; } /// @@ -98,7 +116,7 @@ public class WireMockOpenApiParser : IWireMockOpenApiParser return FromStream(new MemoryStream(Encoding.UTF8.GetBytes(text)), settings, out diagnostic); } - private OpenApiDocument Read(Stream stream, out OpenApiDiagnostic diagnostic) + private bool TryRead(Stream stream, [NotNullWhen(true)] out OpenApiDocument? openApiDocument, out OpenApiDiagnostic diagnostic) { if (stream is not MemoryStream memoryStream) { @@ -107,8 +125,9 @@ public class WireMockOpenApiParser : IWireMockOpenApiParser var result = OpenApiDocument.Load(memoryStream, settings: _readerSettings); - diagnostic = OpenApiMapper.Map(result.Diagnostic) ?? new OpenApiDiagnostic(); - return result.Document ?? throw new InvalidOperationException("The document is null."); + diagnostic = result.Diagnostic ?? new OpenApiDiagnostic(); + openApiDocument = result.Document; + return openApiDocument != null && !diagnostic.Errors.Any(); } private static MemoryStream ReadStreamIntoMemoryStream(Stream stream) diff --git a/test/WireMock.Net.Tests/OpenApiParser/WireMockOpenApiParserTests.cs b/test/WireMock.Net.Tests/OpenApiParser/WireMockOpenApiParserTests.cs index 3aeb1038..e7bf0777 100644 --- a/test/WireMock.Net.Tests/OpenApiParser/WireMockOpenApiParserTests.cs +++ b/test/WireMock.Net.Tests/OpenApiParser/WireMockOpenApiParserTests.cs @@ -36,12 +36,38 @@ public class WireMockOpenApiParserTests var openApiDocument = File.ReadAllText(Path.Combine("OpenApiParser", "payroc-openapi-spec.yaml")); // Act - var mappings = _sut.FromText(openApiDocument, settings, out _); + var mappings = _sut.FromText(openApiDocument, settings, out var diagnostic); + + // Assert + mappings.Should().NotBeEmpty(); + diagnostic.Should().NotBeNull(); + diagnostic.Errors.Should().BeEmpty(); // Verify await Verify(mappings); } + [Fact] + public void FromText_UsingInvalidYaml_ShouldReturnEmptyMappingsWithDiagnostic() + { + // Arrange + var settings = new WireMockOpenApiParserSettings + { + ExampleValues = _exampleValuesMock.Object + }; + + var openApiDocument = File.ReadAllText(Path.Combine("OpenApiParser", "invalid.yaml")); + + // Act + var mappings = _sut.FromText(openApiDocument, settings, out var diagnostic); + + // Assert + mappings.Should().BeEmpty(); + diagnostic.Should().NotBeNull(); + diagnostic.Errors.Should().HaveCount(1); + diagnostic.Errors[0].Message.Should().Be("Responses must contain at least one response"); + } + [Fact] public async Task FromText_UsingJson_WithPlainTextExample_ShouldReturnMappings() { @@ -54,7 +80,12 @@ public class WireMockOpenApiParserTests var openApiDocument = File.ReadAllText(Path.Combine("OpenApiParser", "oas-content-example.json")); // Act - var mappings = _sut.FromText(openApiDocument, settings, out _); + var mappings = _sut.FromText(openApiDocument, settings, out var diagnostic); + + // Assert + mappings.Should().NotBeEmpty(); + diagnostic.Should().NotBeNull(); + diagnostic.Errors.Should().BeEmpty(); // Verify await Verify(mappings); diff --git a/test/WireMock.Net.Tests/OpenApiParser/invalid.yaml b/test/WireMock.Net.Tests/OpenApiParser/invalid.yaml new file mode 100644 index 00000000..ccdff1d6 --- /dev/null +++ b/test/WireMock.Net.Tests/OpenApiParser/invalid.yaml @@ -0,0 +1,12 @@ +openapi: 3.2.0 +info: + version: '1' + title: Invalid API + description: Invalid + +paths: + /funding-recipients: + summary: Create and manage funding recipients. + post: + tags: + - Funding recipients \ No newline at end of file