Add model reference support to library and command line utility. (#81)
* Support many conversion options in the command-line tool. Support local reference files in file-based csdl in the library and command-line tool. * Added tests for references. * Updates from github review.
This commit is contained in:
parent
f6f26df6f2
commit
c1aa5a6f94
|
@ -162,7 +162,7 @@ namespace Microsoft.OpenApi.OData.Edm
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Check whether the operaiton is overload in the model.
|
/// Check whether the operation is overload in the model.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="model">The Edm model.</param>
|
/// <param name="model">The Edm model.</param>
|
||||||
/// <param name="operation">The test operations.</param>
|
/// <param name="operation">The test operations.</param>
|
||||||
|
@ -172,7 +172,7 @@ namespace Microsoft.OpenApi.OData.Edm
|
||||||
Utils.CheckArgumentNull(model, nameof(model));
|
Utils.CheckArgumentNull(model, nameof(model));
|
||||||
Utils.CheckArgumentNull(operation, nameof(operation));
|
Utils.CheckArgumentNull(operation, nameof(operation));
|
||||||
|
|
||||||
return model.SchemaElements.OfType<IEdmOperation>()
|
return model.GetAllElements().OfType<IEdmOperation>()
|
||||||
.Where(o => o.IsBound == operation.IsBound && o.FullName() == operation.FullName() &&
|
.Where(o => o.IsBound == operation.IsBound && o.FullName() == operation.FullName() &&
|
||||||
o.Parameters.First().Type.Definition == operation.Parameters.First().Type.Definition
|
o.Parameters.First().Type.Definition == operation.Parameters.First().Type.Definition
|
||||||
).Count() > 1;
|
).Count() > 1;
|
||||||
|
@ -197,5 +197,28 @@ namespace Microsoft.OpenApi.OData.Edm
|
||||||
return model.EntityContainer.OperationImports()
|
return model.EntityContainer.OperationImports()
|
||||||
.Where(o => o.Operation.IsBound == operationImport.Operation.IsBound && o.Name == operationImport.Name).Count() > 1;
|
.Where(o => o.Operation.IsBound == operationImport.Operation.IsBound && o.Name == operationImport.Name).Count() > 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get all of the elements in the model and its referenced models.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>All the elements.</returns>
|
||||||
|
public static IEnumerable<IEdmSchemaElement> GetAllElements(this IEdmModel model)
|
||||||
|
{
|
||||||
|
foreach (var element in model.SchemaElements.Where(el =>
|
||||||
|
!ODataConstants.StandardNamespaces.Any(std => el.Namespace.StartsWith(std))))
|
||||||
|
{
|
||||||
|
yield return element;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var refModel in model.ReferencedModels)
|
||||||
|
{
|
||||||
|
foreach (var element in refModel.SchemaElements.Where(el =>
|
||||||
|
!ODataConstants.StandardNamespaces.Any(std => el.Namespace.StartsWith(std))))
|
||||||
|
{
|
||||||
|
yield return element;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -71,7 +71,7 @@ namespace Microsoft.OpenApi.OData.Edm
|
||||||
{
|
{
|
||||||
IDictionary<string, IList<IEdmOperation>> edmOperationDict = new Dictionary<string, IList<IEdmOperation>>();
|
IDictionary<string, IList<IEdmOperation>> edmOperationDict = new Dictionary<string, IList<IEdmOperation>>();
|
||||||
|
|
||||||
foreach (var edmOperation in Model.SchemaElements.OfType<IEdmOperation>().Where(e => e.IsBound))
|
foreach (var edmOperation in Model.GetAllElements().OfType<IEdmOperation>().Where(e => e.IsBound))
|
||||||
{
|
{
|
||||||
IEdmOperationParameter bindingParameter = edmOperation.Parameters.First();
|
IEdmOperationParameter bindingParameter = edmOperation.Parameters.First();
|
||||||
|
|
||||||
|
|
|
@ -294,7 +294,7 @@ namespace Microsoft.OpenApi.OData.Edm
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private void RetrieveBoundOperationPaths()
|
private void RetrieveBoundOperationPaths()
|
||||||
{
|
{
|
||||||
foreach (var edmOperation in _model.SchemaElements.OfType<IEdmOperation>().Where(e => e.IsBound))
|
foreach (var edmOperation in _model.GetAllElements().OfType<IEdmOperation>().Where(e => e.IsBound))
|
||||||
{
|
{
|
||||||
if (!CanFilter(edmOperation))
|
if (!CanFilter(edmOperation))
|
||||||
{
|
{
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
// ------------------------------------------------------------
|
// ------------------------------------------------------------
|
||||||
|
|
||||||
using Microsoft.OData.Edm;
|
using Microsoft.OData.Edm;
|
||||||
|
using Microsoft.OpenApi.OData.Edm;
|
||||||
|
|
||||||
namespace Microsoft.OpenApi.OData.Generator
|
namespace Microsoft.OpenApi.OData.Generator
|
||||||
{
|
{
|
||||||
|
@ -30,7 +31,7 @@ namespace Microsoft.OpenApi.OData.Generator
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var element in model.SchemaElements)
|
foreach (var element in model.GetAllElements())
|
||||||
{
|
{
|
||||||
switch (element.SchemaElementKind)
|
switch (element.SchemaElementKind)
|
||||||
{
|
{
|
||||||
|
|
|
@ -34,7 +34,11 @@ namespace Microsoft.OpenApi.OData.Generator
|
||||||
|
|
||||||
// Each entity type, complex type, enumeration type, and type definition directly
|
// Each entity type, complex type, enumeration type, and type definition directly
|
||||||
// or indirectly used in the paths field is represented as a name / value pair of the schemas map.
|
// or indirectly used in the paths field is represented as a name / value pair of the schemas map.
|
||||||
foreach (var element in context.Model.SchemaElements.Where(c => !c.Namespace.StartsWith("Org.OData.")))
|
// Ideally this would be driven off the types used in the paths, but in practice, it is simply
|
||||||
|
// all of the types present in the model.
|
||||||
|
IEnumerable<IEdmSchemaElement> elements = context.Model.GetAllElements();
|
||||||
|
|
||||||
|
foreach (var element in elements)
|
||||||
{
|
{
|
||||||
switch (element.SchemaElementKind)
|
switch (element.SchemaElementKind)
|
||||||
{
|
{
|
||||||
|
|
|
@ -38,7 +38,11 @@ namespace Microsoft.OpenApi.OData.Generator
|
||||||
|
|
||||||
// Each entity type, complex type, enumeration type, and type definition directly
|
// Each entity type, complex type, enumeration type, and type definition directly
|
||||||
// or indirectly used in the paths field is represented as a name / value pair of the schemas map.
|
// or indirectly used in the paths field is represented as a name / value pair of the schemas map.
|
||||||
foreach (var element in context.Model.SchemaElements.Where(c => !c.Namespace.StartsWith("Org.OData.")))
|
// Ideally this would be driven off the types used in the paths, but in practice, it is simply
|
||||||
|
// all of the types present in the model.
|
||||||
|
IEnumerable<IEdmSchemaElement> elements = context.Model.GetAllElements();
|
||||||
|
|
||||||
|
foreach (var element in elements)
|
||||||
{
|
{
|
||||||
switch (element.SchemaElementKind)
|
switch (element.SchemaElementKind)
|
||||||
{
|
{
|
||||||
|
|
27
src/Microsoft.OpenApi.OData.Reader/OData/ODataConstants.cs
Normal file
27
src/Microsoft.OpenApi.OData.Reader/OData/ODataConstants.cs
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
// ------------------------------------------------------------
|
||||||
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information.
|
||||||
|
// ------------------------------------------------------------
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Microsoft.OpenApi.OData
|
||||||
|
{
|
||||||
|
internal static class ODataConstants
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Namespaces used in standard included models.
|
||||||
|
/// </summary>
|
||||||
|
public static IList<string> StandardNamespaces = new List<string>
|
||||||
|
{
|
||||||
|
"Org.OData.",
|
||||||
|
"Edm",
|
||||||
|
"OData.Community.",
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -45,6 +45,11 @@ namespace OoasUtil
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public OpenApiFormat? Format { get; private set; }
|
public OpenApiFormat? Format { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Whether KeyAsSegment is used.
|
||||||
|
/// </summary>
|
||||||
|
public bool? KeyAsSegment { get; private set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Output OpenApi Specification Version.
|
/// Output OpenApi Specification Version.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -60,6 +65,31 @@ namespace OoasUtil
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool IsLocalFile { get; private set; }
|
public bool IsLocalFile { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Set the output to produce all derived types in responses.
|
||||||
|
/// </summary>
|
||||||
|
public bool? DerivedTypesReferencesForResponses { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Set the output to expect all derived types in request bodies.
|
||||||
|
/// </summary>
|
||||||
|
public bool? DerivedTypesReferencesForRequestBody { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Set the output to expose pagination for collections.
|
||||||
|
/// </summary>
|
||||||
|
public bool? EnablePagination { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// tSet the output to use unqualified calls for bound operations.
|
||||||
|
/// </summary>
|
||||||
|
public bool? EnableUnqualifiedCall { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// tDisable examples in the schema.
|
||||||
|
/// </summary>
|
||||||
|
public bool? DisableSchemaExamples { get; private set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Process the arguments.
|
/// Process the arguments.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -98,6 +128,14 @@ namespace OoasUtil
|
||||||
i++;
|
i++;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case "--keyassegment":
|
||||||
|
case "-k":
|
||||||
|
if (!ProcessKeyAsSegment(true))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case "--yaml":
|
case "--yaml":
|
||||||
case "-y":
|
case "-y":
|
||||||
if (!ProcessTarget(OpenApiFormat.Yaml))
|
if (!ProcessTarget(OpenApiFormat.Yaml))
|
||||||
|
@ -132,6 +170,46 @@ namespace OoasUtil
|
||||||
i++;
|
i++;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case "--derivedtypesreferencesforresponses":
|
||||||
|
case "-drs":
|
||||||
|
if (!ProcessDerivedTypesReferencesForResponses(true))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "--derivedtypesreferencesforrequestbody":
|
||||||
|
case "-drq":
|
||||||
|
if (!ProcessDerivedTypesReferencesForRequestBody(true))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "--enablepagination":
|
||||||
|
case "-p":
|
||||||
|
if (!ProcessEnablePagination(true))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "--enableunqualifiedcall":
|
||||||
|
case "-u":
|
||||||
|
if (!ProcessEnableUnqualifiedCall(true))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "--disableschemaexamples":
|
||||||
|
case "-x":
|
||||||
|
if (!ProcessDisableSchemaExamples(true))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
PrintUsage();
|
PrintUsage();
|
||||||
return false;
|
return false;
|
||||||
|
@ -155,6 +233,36 @@ namespace OoasUtil
|
||||||
Version = OpenApiSpecVersion.OpenApi3_0;
|
Version = OpenApiSpecVersion.OpenApi3_0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (KeyAsSegment == null)
|
||||||
|
{
|
||||||
|
KeyAsSegment = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (DerivedTypesReferencesForResponses == null)
|
||||||
|
{
|
||||||
|
DerivedTypesReferencesForResponses = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (DerivedTypesReferencesForRequestBody == null)
|
||||||
|
{
|
||||||
|
DerivedTypesReferencesForRequestBody = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (EnablePagination == null)
|
||||||
|
{
|
||||||
|
EnablePagination = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (EnableUnqualifiedCall == null)
|
||||||
|
{
|
||||||
|
EnableUnqualifiedCall = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (DisableSchemaExamples == null)
|
||||||
|
{
|
||||||
|
DisableSchemaExamples = false;
|
||||||
|
}
|
||||||
|
|
||||||
_continue = ValidateArguments();
|
_continue = ValidateArguments();
|
||||||
return _continue;
|
return _continue;
|
||||||
}
|
}
|
||||||
|
@ -198,6 +306,84 @@ namespace OoasUtil
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool ProcessKeyAsSegment(bool keyAsSegment)
|
||||||
|
{
|
||||||
|
if (KeyAsSegment != null)
|
||||||
|
{
|
||||||
|
Console.WriteLine("[Error:] Multiple [--keyassegment|-k] are not allowed.\n");
|
||||||
|
PrintUsage();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
KeyAsSegment = keyAsSegment;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool ProcessDerivedTypesReferencesForResponses(bool derivedTypesReferencesForResponses)
|
||||||
|
{
|
||||||
|
if (DerivedTypesReferencesForResponses != null)
|
||||||
|
{
|
||||||
|
Console.WriteLine("[Error:] Multiple [--derivedtypesreferencesforresponses|-drs] are not allowed.\n");
|
||||||
|
PrintUsage();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
DerivedTypesReferencesForResponses = derivedTypesReferencesForResponses;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool ProcessDerivedTypesReferencesForRequestBody(bool derivedTypesReferencesForRequestBody)
|
||||||
|
{
|
||||||
|
if (DerivedTypesReferencesForRequestBody != null)
|
||||||
|
{
|
||||||
|
Console.WriteLine("[Error:] Multiple [--derivedtypesreferencesforrequestbody|-drq] are not allowed.\n");
|
||||||
|
PrintUsage();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
DerivedTypesReferencesForRequestBody = derivedTypesReferencesForRequestBody;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool ProcessEnablePagination(bool enablePagination)
|
||||||
|
{
|
||||||
|
if (EnablePagination != null)
|
||||||
|
{
|
||||||
|
Console.WriteLine("[Error:] Multiple [--enablepagination|-p] are not allowed.\n");
|
||||||
|
PrintUsage();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
EnablePagination = enablePagination;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool ProcessEnableUnqualifiedCall(bool enableUnqualifiedCall)
|
||||||
|
{
|
||||||
|
if (EnableUnqualifiedCall != null)
|
||||||
|
{
|
||||||
|
Console.WriteLine("[Error:] Multiple [--enableunqualifiedcall|-u] are not allowed.\n");
|
||||||
|
PrintUsage();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
EnableUnqualifiedCall = enableUnqualifiedCall;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool ProcessDisableSchemaExamples(bool disableSchemaExamples)
|
||||||
|
{
|
||||||
|
if (DisableSchemaExamples != null)
|
||||||
|
{
|
||||||
|
Console.WriteLine("[Error:] Multiple [--disableschemaexamples|-x] are not allowed.\n");
|
||||||
|
PrintUsage();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
DisableSchemaExamples = disableSchemaExamples;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
private bool ProcessTarget(int version)
|
private bool ProcessTarget(int version)
|
||||||
{
|
{
|
||||||
if (Version != null)
|
if (Version != null)
|
||||||
|
@ -256,6 +442,12 @@ namespace OoasUtil
|
||||||
sb.Append(" --version|-v\t\t\tDisplay version.\n");
|
sb.Append(" --version|-v\t\t\tDisplay version.\n");
|
||||||
sb.Append(" --input|-i CsdlFileOrUrl\tSet the CSDL file name or the OData Service Url.\n");
|
sb.Append(" --input|-i CsdlFileOrUrl\tSet the CSDL file name or the OData Service Url.\n");
|
||||||
sb.Append(" --output|-o OutputFile\tSet the output file name.\n");
|
sb.Append(" --output|-o OutputFile\tSet the output file name.\n");
|
||||||
|
sb.Append(" --keyassegment|-k\t\t\tSet the output to use key-as-segment style URLs.\n");
|
||||||
|
sb.Append(" --derivedtypesreferencesforresponses|-drs\t\t\tSet the output to produce all derived types in responses.\n");
|
||||||
|
sb.Append(" --derivedtypesreferencesforrequestbody|-drq\t\t\tSet the output to expect all derived types in request bodies.\n");
|
||||||
|
sb.Append(" --enablepagination|-p\t\t\tSet the output to expose pagination for collections.\n");
|
||||||
|
sb.Append(" --enableunqualifiedcall|-u\t\t\tSet the output to use unqualified calls for bound operations.\n");
|
||||||
|
sb.Append(" --disableschemaexamples|-x\t\t\tDisable examples in the schema.\n");
|
||||||
sb.Append(" --json|-j\t\t\tSet the output format as JSON.\n");
|
sb.Append(" --json|-j\t\t\tSet the output format as JSON.\n");
|
||||||
sb.Append(" --yaml|-y\t\t\tSet the output format as YAML.\n");
|
sb.Append(" --yaml|-y\t\t\tSet the output format as YAML.\n");
|
||||||
sb.Append(" --specversion|-s IntVersion\tSet the OpenApi Specification version of the output. Only 2 or 3 are supported.\n");
|
sb.Append(" --specversion|-s IntVersion\tSet the OpenApi Specification version of the output. Only 2 or 3 are supported.\n");
|
||||||
|
|
|
@ -6,10 +6,13 @@
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Xml;
|
||||||
using System.Xml.Linq;
|
using System.Xml.Linq;
|
||||||
using Microsoft.OData.Edm;
|
using Microsoft.OData.Edm;
|
||||||
using Microsoft.OData.Edm.Csdl;
|
using Microsoft.OData.Edm.Csdl;
|
||||||
using Microsoft.OpenApi;
|
using Microsoft.OpenApi;
|
||||||
|
using Microsoft.OpenApi.OData;
|
||||||
|
|
||||||
namespace OoasUtil
|
namespace OoasUtil
|
||||||
{
|
{
|
||||||
|
@ -28,9 +31,10 @@ namespace OoasUtil
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="input">The input.</param>
|
/// <param name="input">The input.</param>
|
||||||
/// <param name="output">The output.</param>
|
/// <param name="output">The output.</param>
|
||||||
/// <param name="target">The output target.</param>
|
/// <param name="format">The format.</param>
|
||||||
public FileOpenApiGenerator(string input, string output, OpenApiFormat format, OpenApiSpecVersion version)
|
/// <param name="settings">Conversion settings.</param>
|
||||||
: base(output, format, version)
|
public FileOpenApiGenerator(string input, string output, OpenApiFormat format, OpenApiConvertSettings settings)
|
||||||
|
: base(output, format, settings)
|
||||||
{
|
{
|
||||||
Input = input;
|
Input = input;
|
||||||
}
|
}
|
||||||
|
@ -43,7 +47,32 @@ namespace OoasUtil
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
string csdl = File.ReadAllText(Input);
|
string csdl = File.ReadAllText(Input);
|
||||||
return CsdlReader.Parse(XElement.Parse(csdl).CreateReader());
|
var directory = Path.GetDirectoryName(Input);
|
||||||
|
var parsed = XElement.Parse(csdl);
|
||||||
|
using (XmlReader mainReader = parsed.CreateReader())
|
||||||
|
{
|
||||||
|
return CsdlReader.Parse(mainReader, u =>
|
||||||
|
{
|
||||||
|
// Currently only support relative paths
|
||||||
|
if (u.IsAbsoluteUri)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"Referenced model must use relative paths to the main model.");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
var file = Path.Combine(directory, u.OriginalString);
|
||||||
|
string referenceText = File.ReadAllText(file);
|
||||||
|
var referenceParsed = XElement.Parse(referenceText);
|
||||||
|
XmlReader referenceReader = referenceParsed.CreateReader();
|
||||||
|
return referenceReader;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (EdmParseException parseException)
|
||||||
|
{
|
||||||
|
Console.WriteLine("Failed to parse the CSDL file.");
|
||||||
|
Console.WriteLine(string.Join(Environment.NewLine, parseException.Errors.Select(e => e.ToString())));
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
|
|
|
@ -24,27 +24,27 @@ namespace OoasUtil
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public OpenApiFormat Format { get; }
|
public OpenApiFormat Format { get; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Output specification version.
|
|
||||||
/// </summary>
|
|
||||||
public OpenApiSpecVersion Version { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Output file.
|
/// Output file.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string Output { get; }
|
public string Output { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Settings to use for conversion.
|
||||||
|
/// </summary>
|
||||||
|
public OpenApiConvertSettings Settings { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="OpenApiGenerator"/> class.
|
/// Initializes a new instance of the <see cref="OpenApiGenerator"/> class.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="input">The input.</param>
|
|
||||||
/// <param name="output">The output.</param>
|
/// <param name="output">The output.</param>
|
||||||
/// <param name="target">The output target.</param>
|
/// <param name="format">The output format.</param>
|
||||||
public OpenApiGenerator(string output, OpenApiFormat format, OpenApiSpecVersion version)
|
/// <param name="settings">Conversion settings.</param>
|
||||||
|
public OpenApiGenerator(string output, OpenApiFormat format, OpenApiConvertSettings settings)
|
||||||
{
|
{
|
||||||
Output = output;
|
Output = output;
|
||||||
Format = format;
|
Format = format;
|
||||||
Version = version;
|
Settings = settings;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -56,14 +56,12 @@ namespace OoasUtil
|
||||||
{
|
{
|
||||||
IEdmModel edmModel = GetEdmModel();
|
IEdmModel edmModel = GetEdmModel();
|
||||||
|
|
||||||
OpenApiConvertSettings settings = GetSettings();
|
this.ModifySettings();
|
||||||
|
|
||||||
settings.OpenApiSpecVersion = Version;
|
|
||||||
|
|
||||||
using (FileStream fs = File.Create(Output))
|
using (FileStream fs = File.Create(Output))
|
||||||
{
|
{
|
||||||
OpenApiDocument document = edmModel.ConvertToOpenApi(settings);
|
OpenApiDocument document = edmModel.ConvertToOpenApi(Settings);
|
||||||
document.Serialize(fs, settings.OpenApiSpecVersion, Format);
|
document.Serialize(fs, Settings.OpenApiSpecVersion, Format);
|
||||||
fs.Flush();
|
fs.Flush();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -76,9 +74,8 @@ namespace OoasUtil
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual OpenApiConvertSettings GetSettings()
|
protected virtual void ModifySettings()
|
||||||
{
|
{
|
||||||
return new OpenApiConvertSettings();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract IEdmModel GetEdmModel();
|
protected abstract IEdmModel GetEdmModel();
|
||||||
|
|
|
@ -5,6 +5,8 @@
|
||||||
//---------------------------------------------------------------------
|
//---------------------------------------------------------------------
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.Reflection;
|
||||||
|
using Microsoft.OpenApi.OData;
|
||||||
|
|
||||||
namespace OoasUtil
|
namespace OoasUtil
|
||||||
{
|
{
|
||||||
|
@ -29,13 +31,25 @@ namespace OoasUtil
|
||||||
}
|
}
|
||||||
|
|
||||||
OpenApiGenerator generator;
|
OpenApiGenerator generator;
|
||||||
|
|
||||||
|
OpenApiConvertSettings settings = new OpenApiConvertSettings
|
||||||
|
{
|
||||||
|
EnableKeyAsSegment = processer.KeyAsSegment,
|
||||||
|
EnableDerivedTypesReferencesForResponses = processer.DerivedTypesReferencesForResponses.Value,
|
||||||
|
EnableDerivedTypesReferencesForRequestBody = processer.DerivedTypesReferencesForRequestBody.Value,
|
||||||
|
EnablePagination = processer.EnablePagination.Value,
|
||||||
|
EnableUnqualifiedCall = processer.EnableUnqualifiedCall.Value,
|
||||||
|
ShowSchemaExamples = !processer.DisableSchemaExamples.Value,
|
||||||
|
OpenApiSpecVersion = processer.Version.Value,
|
||||||
|
};
|
||||||
|
|
||||||
if (processer.IsLocalFile)
|
if (processer.IsLocalFile)
|
||||||
{
|
{
|
||||||
generator = new FileOpenApiGenerator(processer.Input, processer.Output, processer.Format.Value, processer.Version.Value);
|
generator = new FileOpenApiGenerator(processer.Input, processer.Output, processer.Format.Value, settings);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
generator = new UrlOpenApiGenerator(new Uri(processer.Input), processer.Output, processer.Format.Value, processer.Version.Value);
|
generator = new UrlOpenApiGenerator(new Uri(processer.Input), processer.Output, processer.Format.Value, settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (generator.Generate())
|
if (generator.Generate())
|
||||||
|
|
|
@ -25,14 +25,38 @@ Output the "JSON" format Open API document;
|
||||||
|
|
||||||
Output the "YAML" format Open API document;
|
Output the "YAML" format Open API document;
|
||||||
|
|
||||||
### [--specversion|-s int]
|
### [--keyassegment|-k]
|
||||||
|
|
||||||
Indicate which version, either 2 or 3, of the OpenApi specification to output. Only 2 or 3 are supported;
|
Output the document using key-as-segment style URLs.;
|
||||||
|
|
||||||
|
### [--derivedtypesreferencesforresponses|-drs]
|
||||||
|
|
||||||
|
Output the document to expect all derived types in responses.;
|
||||||
|
|
||||||
|
### [--derivedtypesreferencesforrequestbody|-drq]
|
||||||
|
|
||||||
|
Output the document to expect all derived types in request bodies.;
|
||||||
|
|
||||||
|
### [--enablepagination|-p]
|
||||||
|
|
||||||
|
Output the document to expose pagination for collections.;
|
||||||
|
|
||||||
|
### [--enableunqualifiedcall|-u]
|
||||||
|
|
||||||
|
Output the document to use unqualified calls for bound operations.;
|
||||||
|
|
||||||
|
### [--disableschemaexamples|-x]
|
||||||
|
|
||||||
|
Output the document without examples in the schema.;
|
||||||
|
|
||||||
### [--yaml|-y]
|
### [--yaml|-y]
|
||||||
|
|
||||||
Output the "YAML" format Open API document;
|
Output the "YAML" format Open API document;
|
||||||
|
|
||||||
|
### [--specversion|-s int]
|
||||||
|
|
||||||
|
Indicate which version, either 2 or 3, of the OpenApi specification to output. Only 2 or 3 are supported;
|
||||||
|
|
||||||
### [--input|-i file]
|
### [--input|-i file]
|
||||||
|
|
||||||
Indicate to where to get CSDL, from file or from Uri.
|
Indicate to where to get CSDL, from file or from Uri.
|
||||||
|
@ -44,7 +68,7 @@ Indicate to output file name.
|
||||||
|
|
||||||
## Examples
|
## Examples
|
||||||
|
|
||||||
`OoasUtil.exe -j -s 3 -i http://services.odata.org/TrippinRESTierService -o trip.json`
|
`OoasUtil.exe -j -k -drs -drq -p -u -s 3 -i http://services.odata.org/TrippinRESTierService -o trip.json`
|
||||||
|
|
||||||
The content of `trip.json` is similar at https://github.com/xuzhg/OData.OpenAPI/blob/master/Microsoft.OData.OpenAPI/Microsoft.OData.OpenAPI.Tests/Resources/TripService.OpenApi.json
|
The content of `trip.json` is similar at https://github.com/xuzhg/OData.OpenAPI/blob/master/Microsoft.OData.OpenAPI/Microsoft.OData.OpenAPI.Tests/Resources/TripService.OpenApi.json
|
||||||
|
|
||||||
|
|
|
@ -31,9 +31,10 @@ namespace OoasUtil
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="input">The input.</param>
|
/// <param name="input">The input.</param>
|
||||||
/// <param name="output">The output.</param>
|
/// <param name="output">The output.</param>
|
||||||
/// <param name="target">The output target.</param>
|
/// <param name="format">The format.</param>
|
||||||
public UrlOpenApiGenerator(Uri input, string output, OpenApiFormat format, OpenApiSpecVersion version)
|
/// <param name="settings">Conversion settings.</param>
|
||||||
: base(output, format, version)
|
public UrlOpenApiGenerator(Uri input, string output, OpenApiFormat format, OpenApiConvertSettings settings)
|
||||||
|
: base(output, format, settings)
|
||||||
{
|
{
|
||||||
Input = input;
|
Input = input;
|
||||||
}
|
}
|
||||||
|
@ -58,12 +59,10 @@ namespace OoasUtil
|
||||||
return CsdlReader.Parse(XElement.Parse(csdl).CreateReader());
|
return CsdlReader.Parse(XElement.Parse(csdl).CreateReader());
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override OpenApiConvertSettings GetSettings()
|
protected override void ModifySettings()
|
||||||
{
|
{
|
||||||
return new OpenApiConvertSettings
|
base.ModifySettings();
|
||||||
{
|
Settings.ServiceRoot = Input;
|
||||||
ServiceRoot = Input
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information.
|
// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information.
|
||||||
// ------------------------------------------------------------
|
// ------------------------------------------------------------
|
||||||
|
|
||||||
|
using System;
|
||||||
using System.Xml.Linq;
|
using System.Xml.Linq;
|
||||||
using Microsoft.OData.Edm;
|
using Microsoft.OData.Edm;
|
||||||
using Microsoft.OData.Edm.Csdl;
|
using Microsoft.OData.Edm.Csdl;
|
||||||
|
@ -12,6 +13,8 @@ using Xunit;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Xml;
|
using System.Xml;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Net;
|
||||||
|
using System.Text;
|
||||||
using Microsoft.OData.Edm.Validation;
|
using Microsoft.OData.Edm.Validation;
|
||||||
using Xunit.Abstractions;
|
using Xunit.Abstractions;
|
||||||
|
|
||||||
|
@ -26,6 +29,8 @@ namespace Microsoft.OpenApi.OData.Tests
|
||||||
|
|
||||||
public static IEdmModel MultipleInheritanceEdmModel { get; }
|
public static IEdmModel MultipleInheritanceEdmModel { get; }
|
||||||
|
|
||||||
|
public static IEdmModel InheritanceEdmModelAcrossReferences { get; }
|
||||||
|
|
||||||
public static IEdmModel BasicEdmModel { get; }
|
public static IEdmModel BasicEdmModel { get; }
|
||||||
|
|
||||||
public static IEdmModel MultipleSchemasEdmModel { get; }
|
public static IEdmModel MultipleSchemasEdmModel { get; }
|
||||||
|
@ -46,6 +51,7 @@ namespace Microsoft.OpenApi.OData.Tests
|
||||||
ContractServiceModel = LoadEdmModel("Contract.OData.xml");
|
ContractServiceModel = LoadEdmModel("Contract.OData.xml");
|
||||||
GraphBetaModel = LoadEdmModel("Graph.Beta.OData.xml");
|
GraphBetaModel = LoadEdmModel("Graph.Beta.OData.xml");
|
||||||
MultipleSchemasEdmModel = LoadEdmModel("Multiple.Schema.OData.xml");
|
MultipleSchemasEdmModel = LoadEdmModel("Multiple.Schema.OData.xml");
|
||||||
|
InheritanceEdmModelAcrossReferences = CreateInheritanceEdmModelAcrossReferences();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static IEdmModel LoadEdmModel(string source)
|
private static IEdmModel LoadEdmModel(string source)
|
||||||
|
@ -160,6 +166,50 @@ namespace Microsoft.OpenApi.OData.Tests
|
||||||
return model;
|
return model;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static IEdmModel CreateInheritanceEdmModelAcrossReferences()
|
||||||
|
{
|
||||||
|
const string modelText =
|
||||||
|
@"<edmx:Edmx Version=""4.0"" xmlns:edmx=""http://docs.oasis-open.org/odata/ns/edmx"">
|
||||||
|
<edmx:Reference Uri=""subModel.csdl"">
|
||||||
|
<edmx:Include Alias=""subModel"" Namespace=""SubNS"" />
|
||||||
|
</edmx:Reference>
|
||||||
|
<edmx:DataServices>
|
||||||
|
<Schema Namespace=""NS"" xmlns=""http://docs.oasis-open.org/odata/ns/edm"">
|
||||||
|
<EntityType Name=""Customer"" BaseType=""SubNS.CustomerBase"">
|
||||||
|
<Property Name=""Extra"" Type=""Edm.Int32"" Nullable=""false"" />
|
||||||
|
</EntityType>
|
||||||
|
<EntityContainer Name =""Default"">
|
||||||
|
<EntitySet Name=""Customers"" EntityType=""NS.Customer"" />
|
||||||
|
</EntityContainer>
|
||||||
|
</Schema>
|
||||||
|
</edmx:DataServices>
|
||||||
|
</edmx:Edmx>";
|
||||||
|
const string subModelText =
|
||||||
|
@"<edmx:Edmx Version=""4.0"" xmlns:edmx=""http://docs.oasis-open.org/odata/ns/edmx"">
|
||||||
|
<edmx:DataServices>
|
||||||
|
<Schema Namespace=""SubNS"" xmlns=""http://docs.oasis-open.org/odata/ns/edm"">
|
||||||
|
<EntityType Name=""CustomerBase"">
|
||||||
|
<Key>
|
||||||
|
<PropertyRef Name=""ID"" />
|
||||||
|
</Key>
|
||||||
|
<Property Name=""ID"" Type=""Edm.Int32"" Nullable=""false"" />
|
||||||
|
</EntityType>
|
||||||
|
</Schema>
|
||||||
|
</edmx:DataServices>
|
||||||
|
</edmx:Edmx>";
|
||||||
|
|
||||||
|
IEdmModel model;
|
||||||
|
IEnumerable<EdmError> errors;
|
||||||
|
|
||||||
|
XElement parsed = XElement.Parse(modelText);
|
||||||
|
bool result = CsdlReader.TryParse(parsed.CreateReader(),
|
||||||
|
uri => XElement.Parse(subModelText).CreateReader(),
|
||||||
|
out model,
|
||||||
|
out errors);
|
||||||
|
Assert.True(result);
|
||||||
|
return model;
|
||||||
|
}
|
||||||
|
|
||||||
private static IEdmModel CreateEdmModel()
|
private static IEdmModel CreateEdmModel()
|
||||||
{
|
{
|
||||||
var model = new EdmModel();
|
var model = new EdmModel();
|
||||||
|
@ -359,12 +409,12 @@ namespace Microsoft.OpenApi.OData.Tests
|
||||||
|
|
||||||
public static string GetCsdl(IEdmModel model)
|
public static string GetCsdl(IEdmModel model)
|
||||||
{
|
{
|
||||||
string edmx = string.Empty;
|
string edmx = String.Empty;
|
||||||
|
|
||||||
using (StringWriter sw = new StringWriter())
|
using (StringWriter sw = new StringWriter())
|
||||||
{
|
{
|
||||||
XmlWriterSettings settings = new XmlWriterSettings();
|
XmlWriterSettings settings = new XmlWriterSettings();
|
||||||
settings.Encoding = System.Text.Encoding.UTF8;
|
settings.Encoding = Encoding.UTF8;
|
||||||
settings.Indent = true;
|
settings.Indent = true;
|
||||||
|
|
||||||
using (XmlWriter xw = XmlWriter.Create(sw, settings))
|
using (XmlWriter xw = XmlWriter.Create(sw, settings))
|
||||||
|
|
|
@ -3,8 +3,12 @@
|
||||||
// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information.
|
// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information.
|
||||||
// ------------------------------------------------------------
|
// ------------------------------------------------------------
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Xml.Linq;
|
||||||
using Microsoft.OData.Edm;
|
using Microsoft.OData.Edm;
|
||||||
|
using Microsoft.OData.Edm.Csdl;
|
||||||
|
using Microsoft.OData.Edm.Validation;
|
||||||
using Microsoft.OpenApi.OData.Tests;
|
using Microsoft.OpenApi.OData.Tests;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
|
@ -55,5 +59,21 @@ namespace Microsoft.OpenApi.OData.Edm.Tests
|
||||||
Assert.Equal(2, baseTypes.Count());
|
Assert.Equal(2, baseTypes.Count());
|
||||||
Assert.Equal(new[] { subEntityType, baseEntityType }, baseTypes);
|
Assert.Equal(new[] { subEntityType, baseEntityType }, baseTypes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void GetAllElementsReturnsElementsFromAllModels()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
IEdmModel model = EdmModelHelper.InheritanceEdmModelAcrossReferences;
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var elements = model.GetAllElements();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Collection(elements,
|
||||||
|
e => Assert.Equal("Customer", e.Name),
|
||||||
|
e => Assert.Equal("Default", e.Name),
|
||||||
|
e => Assert.Equal("CustomerBase", e.Name));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -335,6 +335,52 @@ namespace Microsoft.OpenApi.OData.Tests
|
||||||
}"
|
}"
|
||||||
.ChangeLineBreaks(), json);
|
.ChangeLineBreaks(), json);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void CreateEntityTypeWithCrossReferenceBaseSchemaReturnCorrectSchema()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
IEdmModel model = EdmModelHelper.InheritanceEdmModelAcrossReferences;
|
||||||
|
ODataContext context = new ODataContext(model, new OpenApiConvertSettings
|
||||||
|
{
|
||||||
|
ShowSchemaExamples = true
|
||||||
|
});
|
||||||
|
IEdmEntityType entity = model.SchemaElements.OfType<IEdmEntityType>().First(t => t.Name == "Customer");
|
||||||
|
Assert.NotNull(entity); // Guard
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var schema = context.CreateStructuredTypeSchema(entity);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.NotNull(schema);
|
||||||
|
Assert.True(String.IsNullOrEmpty(schema.Type));
|
||||||
|
|
||||||
|
Assert.NotNull(schema.AllOf);
|
||||||
|
Assert.Null(schema.AnyOf);
|
||||||
|
Assert.Null(schema.OneOf);
|
||||||
|
Assert.Null(schema.Properties);
|
||||||
|
|
||||||
|
Assert.Equal(2, schema.AllOf.Count);
|
||||||
|
var baseSchema = schema.AllOf.First();
|
||||||
|
Assert.NotNull(baseSchema.Reference);
|
||||||
|
Assert.Equal(ReferenceType.Schema, baseSchema.Reference.Type);
|
||||||
|
Assert.Equal("SubNS.CustomerBase", baseSchema.Reference.Id);
|
||||||
|
|
||||||
|
var declaredSchema = schema.AllOf.Last();
|
||||||
|
Assert.Equal("object", declaredSchema.Type);
|
||||||
|
Assert.Null(declaredSchema.AllOf);
|
||||||
|
Assert.Null(declaredSchema.AnyOf);
|
||||||
|
Assert.Null(declaredSchema.OneOf);
|
||||||
|
|
||||||
|
Assert.NotNull(declaredSchema.Properties);
|
||||||
|
Assert.Equal(1, declaredSchema.Properties.Count);
|
||||||
|
var property = Assert.Single(declaredSchema.Properties);
|
||||||
|
Assert.Equal("Extra", property.Key);
|
||||||
|
Assert.Equal("integer", property.Value.Type);
|
||||||
|
Assert.Null(property.Value.OneOf);
|
||||||
|
|
||||||
|
Assert.Equal("Customer", declaredSchema.Title);
|
||||||
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region EnumTypeSchema
|
#region EnumTypeSchema
|
||||||
|
|
|
@ -9,6 +9,7 @@ using Microsoft.OData.Edm;
|
||||||
using Microsoft.OpenApi.Models;
|
using Microsoft.OpenApi.Models;
|
||||||
using Microsoft.OpenApi.OData.Edm;
|
using Microsoft.OpenApi.OData.Edm;
|
||||||
using Microsoft.OpenApi.OData.Properties;
|
using Microsoft.OpenApi.OData.Properties;
|
||||||
|
using Microsoft.OpenApi.OData.Tests;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace Microsoft.OpenApi.OData.PathItem.Tests
|
namespace Microsoft.OpenApi.OData.PathItem.Tests
|
||||||
|
@ -75,6 +76,31 @@ namespace Microsoft.OpenApi.OData.PathItem.Tests
|
||||||
pathItem.Operations.Select(o => o.Key));
|
pathItem.Operations.Select(o => o.Key));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void CreateEntityPathItemReturnsCorrectPathItemWithReferences()
|
||||||
|
{
|
||||||
|
// Test that references don't disturb the paths.
|
||||||
|
|
||||||
|
// Arrange
|
||||||
|
IEdmModel model = EdmModelHelper.InheritanceEdmModelAcrossReferences;
|
||||||
|
ODataContext context = new ODataContext(model);
|
||||||
|
IEdmEntitySet entitySet = model.EntityContainer.FindEntitySet("Customers");
|
||||||
|
Assert.NotNull(entitySet); // guard
|
||||||
|
ODataPath path = new ODataPath(new ODataNavigationSourceSegment(entitySet), new ODataKeySegment(entitySet.EntityType()));
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var pathItem = _pathItemHandler.CreatePathItem(context, path);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.NotNull(pathItem);
|
||||||
|
|
||||||
|
Assert.NotNull(pathItem.Operations);
|
||||||
|
Assert.NotEmpty(pathItem.Operations);
|
||||||
|
Assert.Equal(3, pathItem.Operations.Count);
|
||||||
|
Assert.Equal(new OperationType[] { OperationType.Get, OperationType.Patch, OperationType.Delete },
|
||||||
|
pathItem.Operations.Select(o => o.Key));
|
||||||
|
}
|
||||||
|
|
||||||
[Theory]
|
[Theory]
|
||||||
[InlineData(true, new OperationType[] { OperationType.Get, OperationType.Patch, OperationType.Delete })]
|
[InlineData(true, new OperationType[] { OperationType.Get, OperationType.Patch, OperationType.Delete })]
|
||||||
[InlineData(false, new OperationType[] { OperationType.Patch, OperationType.Delete })]
|
[InlineData(false, new OperationType[] { OperationType.Patch, OperationType.Delete })]
|
||||||
|
|
Loading…
Reference in a new issue