From 0dc267c1afc44336327b344b151584915de8583a Mon Sep 17 00:00:00 2001 From: Maggie Kimani Date: Tue, 12 Oct 2021 12:21:47 +0300 Subject: [PATCH 01/29] Add a mock OpenApiDocument --- .../Documents/OpenApiDocumentMock.cs | 725 ++++++++++++++++++ 1 file changed, 725 insertions(+) create mode 100644 test/Microsoft.OpenApi.Tests/Documents/OpenApiDocumentMock.cs diff --git a/test/Microsoft.OpenApi.Tests/Documents/OpenApiDocumentMock.cs b/test/Microsoft.OpenApi.Tests/Documents/OpenApiDocumentMock.cs new file mode 100644 index 000000000..8b354b36f --- /dev/null +++ b/test/Microsoft.OpenApi.Tests/Documents/OpenApiDocumentMock.cs @@ -0,0 +1,725 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using Microsoft.OpenApi.Any; +using Microsoft.OpenApi.Interfaces; +using Microsoft.OpenApi.Models; +using System.Collections.Generic; + +namespace OpenAPIService.Test +{ + /// + /// Mock class that creates a sample OpenAPI document. + /// + public static class OpenApiDocumentMock + { + /// + /// Creates an OpenAPI document. + /// + /// Instance of an OpenApi document + public static OpenApiDocument CreateOpenApiDocument() + { + var applicationJsonMediaType = "application/json"; + + var document = new OpenApiDocument() + { + Paths = new OpenApiPaths() + { + ["/"] = new OpenApiPathItem() // root path + { + Operations = new Dictionary + { + { + OperationType.Get, new OpenApiOperation + { + OperationId = "graphService.GetGraphService", + Responses = new OpenApiResponses() + { + { + "200",new OpenApiResponse() + { + Description = "OK" + } + } + } + } + } + } + }, + ["/reports/microsoft.graph.getTeamsUserActivityCounts(period={period})"] = new OpenApiPathItem() + { + Operations = new Dictionary + { + { + OperationType.Get, new OpenApiOperation + { + Tags = new List + { + { + new OpenApiTag() + { + Name = "reports.Functions" + } + } + }, + OperationId = "reports.getTeamsUserActivityCounts", + Summary = "Invoke function getTeamsUserActivityUserCounts", + Parameters = new List + { + { + new OpenApiParameter() + { + Name = "period", + In = ParameterLocation.Path, + Required = true, + Schema = new OpenApiSchema() + { + Type = "string" + } + } + } + }, + Responses = new OpenApiResponses() + { + { + "200", new OpenApiResponse() + { + Description = "Success", + Content = new Dictionary + { + { + applicationJsonMediaType, + new OpenApiMediaType + { + Schema = new OpenApiSchema + { + Type = "array" + } + } + } + } + } + } + } + } + } + } + }, + ["/reports/microsoft.graph.getTeamsUserActivityUserDetail(date={date})"] = new OpenApiPathItem() + { + Operations = new Dictionary + { + { + OperationType.Get, new OpenApiOperation + { + Tags = new List + { + { + new OpenApiTag() + { + Name = "reports.Functions" + } + } + }, + OperationId = "reports.getTeamsUserActivityUserDetail-a3f1", + Summary = "Invoke function getTeamsUserActivityUserDetail", + Parameters = new List + { + { + new OpenApiParameter() + { + Name = "period", + In = ParameterLocation.Path, + Required = true, + Schema = new OpenApiSchema() + { + Type = "string" + } + } + } + }, + Responses = new OpenApiResponses() + { + { + "200", new OpenApiResponse() + { + Description = "Success", + Content = new Dictionary + { + { + applicationJsonMediaType, + new OpenApiMediaType + { + Schema = new OpenApiSchema + { + Type = "array" + } + } + } + } + } + } + } + } + } + } + }, + ["/users"] = new OpenApiPathItem() + { + Operations = new Dictionary + { + { + OperationType.Get, new OpenApiOperation + { + Tags = new List + { + { + new OpenApiTag() + { + Name = "users.user" + } + } + }, + OperationId = "users.user.ListUser", + Summary = "Get entities from users", + Responses = new OpenApiResponses() + { + { + "200", new OpenApiResponse() + { + Description = "Retrieved entities", + Content = new Dictionary + { + { + applicationJsonMediaType, + new OpenApiMediaType + { + Schema = new OpenApiSchema + { + Title = "Collection of user", + Type = "object", + Properties = new Dictionary + { + { + "value", + new OpenApiSchema + { + Type = "array", + Items = new OpenApiSchema + { + Reference = new OpenApiReference + { + Type = ReferenceType.Schema, + Id = "microsoft.graph.user" + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + }, + ["/users/{user-id}"] = new OpenApiPathItem() + { + Operations = new Dictionary + { + { + OperationType.Get, new OpenApiOperation + { + Tags = new List + { + { + new OpenApiTag() + { + Name = "users.user" + } + } + }, + OperationId = "users.user.GetUser", + Summary = "Get entity from users by key", + Responses = new OpenApiResponses() + { + { + "200", new OpenApiResponse() + { + Description = "Retrieved entity", + Content = new Dictionary + { + { + applicationJsonMediaType, + new OpenApiMediaType + { + Schema = new OpenApiSchema + { + Reference = new OpenApiReference + { + Type = ReferenceType.Schema, + Id = "microsoft.graph.user" + } + } + } + } + } + } + } + } + } + }, + { + OperationType.Patch, new OpenApiOperation + { + Tags = new List + { + { + new OpenApiTag() + { + Name = "users.user" + } + } + }, + OperationId = "users.user.UpdateUser", + Summary = "Update entity in users", + Responses = new OpenApiResponses() + { + { + "204", new OpenApiResponse() + { + Description = "Success" + } + } + } + } + } + } + }, + ["/users/{user-id}/messages/{message-id}"] = new OpenApiPathItem() + { + Operations = new Dictionary + { + { + OperationType.Get, new OpenApiOperation + { + Tags = new List + { + { + new OpenApiTag() + { + Name = "users.message" + } + } + }, + OperationId = "users.GetMessages", + Summary = "Get messages from users", + Description = "The messages in a mailbox or folder. Read-only. Nullable.", + Parameters = new List + { + new OpenApiParameter() + { + Name = "$select", + In = ParameterLocation.Query, + Required = true, + Description = "Select properties to be returned", + Schema = new OpenApiSchema() + { + Type = "array" + } + // missing explode parameter + } + }, + Responses = new OpenApiResponses() + { + { + "200", new OpenApiResponse() + { + Description = "Retrieved navigation property", + Content = new Dictionary + { + { + applicationJsonMediaType, + new OpenApiMediaType + { + Schema = new OpenApiSchema + { + Reference = new OpenApiReference + { + Type = ReferenceType.Schema, + Id = "microsoft.graph.message" + } + } + } + } + } + } + } + } + } + } + } + }, + ["/administrativeUnits/{administrativeUnit-id}/microsoft.graph.restore"] = new OpenApiPathItem() + { + Operations = new Dictionary + { + { + OperationType.Post, new OpenApiOperation + { + Tags = new List + { + { + new OpenApiTag() + { + Name = "administrativeUnits.Actions" + } + } + }, + OperationId = "administrativeUnits.restore", + Summary = "Invoke action restore", + Parameters = new List + { + { + new OpenApiParameter() + { + Name = "administrativeUnit-id", + In = ParameterLocation.Path, + Required = true, + Description = "key: id of administrativeUnit", + Schema = new OpenApiSchema() + { + Type = "string" + } + } + } + }, + Responses = new OpenApiResponses() + { + { + "200", new OpenApiResponse() + { + Description = "Success", + Content = new Dictionary + { + { + applicationJsonMediaType, + new OpenApiMediaType + { + Schema = new OpenApiSchema + { + AnyOf = new List + { + new OpenApiSchema + { + Type = "string" + } + }, + Nullable = true + } + } + } + } + } + } + } + } + } + } + }, + ["/applications/{application-id}/logo"] = new OpenApiPathItem() + { + Operations = new Dictionary + { + { + OperationType.Put, new OpenApiOperation + { + Tags = new List + { + { + new OpenApiTag() + { + Name = "applications.application" + } + } + }, + OperationId = "applications.application.UpdateLogo", + Summary = "Update media content for application in applications", + Responses = new OpenApiResponses() + { + { + "204", new OpenApiResponse() + { + Description = "Success" + } + } + } + } + } + } + }, + ["/security/hostSecurityProfiles"] = new OpenApiPathItem() + { + Operations = new Dictionary + { + { + OperationType.Get, new OpenApiOperation + { + Tags = new List + { + { + new OpenApiTag() + { + Name = "security.hostSecurityProfile" + } + } + }, + OperationId = "security.ListHostSecurityProfiles", + Summary = "Get hostSecurityProfiles from security", + Responses = new OpenApiResponses() + { + { + "200", new OpenApiResponse() + { + Description = "Retrieved navigation property", + Content = new Dictionary + { + { + applicationJsonMediaType, + new OpenApiMediaType + { + Schema = new OpenApiSchema + { + Title = "Collection of hostSecurityProfile", + Type = "object", + Properties = new Dictionary + { + { + "value", + new OpenApiSchema + { + Type = "array", + Items = new OpenApiSchema + { + Reference = new OpenApiReference + { + Type = ReferenceType.Schema, + Id = "microsoft.graph.networkInterface" + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + }, + ["/communications/calls/{call-id}/microsoft.graph.keepAlive"] = new OpenApiPathItem() + { + Operations = new Dictionary + { + { + OperationType.Post, new OpenApiOperation + { + Tags = new List + { + { + new OpenApiTag() + { + Name = "communications.Actions" + } + } + }, + OperationId = "communications.calls.call.keepAlive", + Summary = "Invoke action keepAlive", + Parameters = new List + { + new OpenApiParameter() + { + Name = "call-id", + In = ParameterLocation.Path, + Description = "key: id of call", + Required = true, + Schema = new OpenApiSchema() + { + Type = "string" + }, + Extensions = new Dictionary + { + { + "x-ms-docs-key-type", new OpenApiString("call") + } + } + } + }, + Responses = new OpenApiResponses() + { + { + "204", new OpenApiResponse() + { + Description = "Success" + } + } + }, + Extensions = new Dictionary + { + { + "x-ms-docs-operation-type", new OpenApiString("action") + } + } + } + } + } + }, + ["/groups/{group-id}/events/{event-id}/calendar/events/microsoft.graph.delta"] = new OpenApiPathItem() + { + Operations = new Dictionary + { + { + OperationType.Get, new OpenApiOperation + { + Tags = new List + { + new OpenApiTag() + { + Name = "groups.Functions" + } + }, + OperationId = "groups.group.events.event.calendar.events.delta", + Summary = "Invoke function delta", + Parameters = new List + { + new OpenApiParameter() + { + Name = "group-id", + In = ParameterLocation.Path, + Description = "key: id of group", + Required = true, + Schema = new OpenApiSchema() + { + Type = "string" + }, + Extensions = new Dictionary + { + { + "x-ms-docs-key-type", new OpenApiString("group") + } + } + }, + new OpenApiParameter() + { + Name = "event-id", + In = ParameterLocation.Path, + Description = "key: id of event", + Required = true, + Schema = new OpenApiSchema() + { + Type = "string" + }, + Extensions = new Dictionary + { + { + "x-ms-docs-key-type", new OpenApiString("event") + } + } + } + }, + Responses = new OpenApiResponses() + { + { + "200", new OpenApiResponse() + { + Description = "Success", + Content = new Dictionary + { + { + applicationJsonMediaType, + new OpenApiMediaType + { + Schema = new OpenApiSchema + { + Type = "array", + Reference = new OpenApiReference + { + Type = ReferenceType.Schema, + Id = "microsoft.graph.event" + } + } + } + } + } + } + } + }, + Extensions = new Dictionary + { + { + "x-ms-docs-operation-type", new OpenApiString("function") + } + } + } + } + } + }, + ["/applications/{application-id}/createdOnBehalfOf/$ref"] = new OpenApiPathItem() + { + Operations = new Dictionary + { + { + OperationType.Get, new OpenApiOperation + { + Tags = new List + { + new OpenApiTag() + { + Name = "applications.directoryObject" + } + }, + OperationId = "applications.GetRefCreatedOnBehalfOf", + Summary = "Get ref of createdOnBehalfOf from applications" + } + } + } + } + }, + Components = new OpenApiComponents + { + Schemas = new Dictionary + { + { + "microsoft.graph.networkInterface", new OpenApiSchema + { + Title = "networkInterface", + Type = "object", + Properties = new Dictionary + { + { + "description", new OpenApiSchema + { + Type = "string", + Description = "Description of the NIC (e.g. Ethernet adapter, Wireless LAN adapter Local Area Connection <#>, etc.).", + Nullable = true + } + } + } + } + } + } + } + }; + + return document; + } + } +} From 0ecca08551dcab24364ff3e1c02cc88b649a0fb9 Mon Sep 17 00:00:00 2001 From: Maggie Kimani Date: Tue, 12 Oct 2021 12:22:03 +0300 Subject: [PATCH 02/29] Add tests for filtering validation --- .../Services/OpenApiFilterServiceTests.cs | 49 +++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 test/Microsoft.OpenApi.Tests/Services/OpenApiFilterServiceTests.cs diff --git a/test/Microsoft.OpenApi.Tests/Services/OpenApiFilterServiceTests.cs b/test/Microsoft.OpenApi.Tests/Services/OpenApiFilterServiceTests.cs new file mode 100644 index 000000000..7fedd989c --- /dev/null +++ b/test/Microsoft.OpenApi.Tests/Services/OpenApiFilterServiceTests.cs @@ -0,0 +1,49 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Services; +using OpenAPIService.Test; +using Xunit; + +namespace Microsoft.OpenApi.Tests.Services +{ + public class OpenApiFilterServiceTests + { + private const string Title = "Partial Graph API"; + private const string GraphVersion = "mock"; + private readonly OpenApiFilterService _openApiFilterService; + private readonly OpenApiDocument _openApiDocumentMock; + + public OpenApiFilterServiceTests() + { + _openApiFilterService = new OpenApiFilterService(); + _openApiDocumentMock = OpenApiDocumentMock.CreateOpenApiDocument(); + } + + [Theory] + [InlineData("users.user.ListUser")] + [InlineData("users.user.GetUser")] + [InlineData("administrativeUnits.restore")] + [InlineData("graphService.GetGraphService")] + public void ReturnFilteredOpenApiDocumentBasedOnOperationIds(string operationId) + { + // Act + var predicate = _openApiFilterService.CreatePredicate(operationId); + var subsetOpenApiDocument = _openApiFilterService.CreateFilteredDocument(_openApiDocumentMock, Title, GraphVersion, predicate); + + // Assert + Assert.NotNull(subsetOpenApiDocument); + Assert.Single(subsetOpenApiDocument.Paths); + } + + [Fact] + public void ThrowsInvalidOperationExceptionInCreatePredicateWhenInvalidOperationIdIsSpecified() + { + // Act and Assert + var message = Assert.Throws(() =>_openApiFilterService.CreatePredicate(null)).Message; + Assert.Equal("OperationId needs to be specified.", message); + } + } +} From 2f4a1c8007a7bb6ad90137a5166563703c6bd81c Mon Sep 17 00:00:00 2001 From: Maggie Kimani Date: Tue, 12 Oct 2021 12:24:08 +0300 Subject: [PATCH 03/29] Add an OpenApi filtering service for filtering an OpenApiDocument based on OperationId --- .../Services/OpenApiFilterService.cs | 186 ++++++++++++++++++ 1 file changed, 186 insertions(+) create mode 100644 src/Microsoft.OpenApi/Services/OpenApiFilterService.cs diff --git a/src/Microsoft.OpenApi/Services/OpenApiFilterService.cs b/src/Microsoft.OpenApi/Services/OpenApiFilterService.cs new file mode 100644 index 000000000..4f1795bc6 --- /dev/null +++ b/src/Microsoft.OpenApi/Services/OpenApiFilterService.cs @@ -0,0 +1,186 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using System.Collections.Generic; +using System.Linq; +using Microsoft.OpenApi.Models; + +namespace Microsoft.OpenApi.Services +{ + /// + /// + /// + public class OpenApiFilterService + { + public static readonly string GraphAuthorizationUrl = "https://login.microsoftonline.com/common/oauth2/v2.0/authorize"; + public static readonly string GraphTokenUrl = "https://login.microsoftonline.com/common/oauth2/v2.0/token"; + public static readonly string GraphUrl = "https://graph.microsoft.com/{0}/"; + public const string GraphVersion_V1 = "v1.0"; + + + public OpenApiDocument CreateSubsetOpenApiDocument(string operationIds, OpenApiDocument source, string title) + { + var predicate = CreatePredicate(operationIds); + + var subsetOpenApiDocument = CreateFilteredDocument(source, title, GraphVersion_V1, predicate); + + return subsetOpenApiDocument; + } + + public Func CreatePredicate(string operationIds) + { + string predicateSource = null; + + Func predicate; + if (operationIds != null) + { + if (operationIds == "*") + { + predicate = (o) => true; // All operations + } + else + { + var operationIdsArray = operationIds.Split(','); + predicate = (o) => operationIdsArray.Contains(o.OperationId); + } + + predicateSource = $"operationIds: {operationIds}"; + } + + else + { + throw new InvalidOperationException("OperationId needs to be specified."); + } + + return predicate; + } + /// + /// + /// + /// + /// + /// + /// + /// + public OpenApiDocument CreateFilteredDocument(OpenApiDocument source, string title, string graphVersion, Func predicate) + { + var subset = new OpenApiDocument + { + Info = new OpenApiInfo() + { + Title = title, + Version = graphVersion + }, + + Components = new OpenApiComponents() + }; + var aadv2Scheme = new OpenApiSecurityScheme() + { + Type = SecuritySchemeType.OAuth2, + Flows = new OpenApiOAuthFlows() + { + AuthorizationCode = new OpenApiOAuthFlow() + { + AuthorizationUrl = new Uri(GraphAuthorizationUrl), + TokenUrl = new Uri(GraphTokenUrl) + } + }, + Reference = new OpenApiReference() { Id = "azureaadv2", Type = ReferenceType.SecurityScheme }, + UnresolvedReference = false + }; + subset.Components.SecuritySchemes.Add("azureaadv2", aadv2Scheme); + + subset.SecurityRequirements.Add(new OpenApiSecurityRequirement() { { aadv2Scheme, Array.Empty() } }); + + subset.Servers.Add(new OpenApiServer() { Description = "Core", Url = string.Format(GraphUrl, graphVersion) }); + + var results = FindOperations(source, predicate); + foreach (var result in results) + { + OpenApiPathItem pathItem; + string pathKey = result.CurrentKeys.Path; + + if (subset.Paths == null) + { + subset.Paths = new OpenApiPaths(); + pathItem = new OpenApiPathItem(); + subset.Paths.Add(pathKey, pathItem); + } + else + { + if (!subset.Paths.TryGetValue(pathKey, out pathItem)) + { + pathItem = new OpenApiPathItem(); + subset.Paths.Add(pathKey, pathItem); + } + } + + pathItem.Operations.Add((OperationType)result.CurrentKeys.Operation, result.Operation); + } + + if (subset.Paths == null) + { + throw new ArgumentException("No paths found for the supplied parameters."); + } + + CopyReferences(subset); + + return subset; + } + + private static IList FindOperations(OpenApiDocument graphOpenApi, Func predicate) + { + var search = new OperationSearch(predicate); + var walker = new OpenApiWalker(search); + walker.Walk(graphOpenApi); + return search.SearchResults; + } + + private static void CopyReferences(OpenApiDocument target) + { + bool morestuff; + do + { + var copy = new CopyReferences(target); + var walker = new OpenApiWalker(copy); + walker.Walk(target); + + morestuff = AddReferences(copy.Components, target.Components); + + } while (morestuff); + } + + private static bool AddReferences(OpenApiComponents newComponents, OpenApiComponents target) + { + var moreStuff = false; + foreach (var item in newComponents.Schemas) + { + if (!target.Schemas.ContainsKey(item.Key)) + { + moreStuff = true; + target.Schemas.Add(item); + } + } + + foreach (var item in newComponents.Parameters) + { + if (!target.Parameters.ContainsKey(item.Key)) + { + moreStuff = true; + target.Parameters.Add(item); + } + } + + foreach (var item in newComponents.Responses) + { + if (!target.Responses.ContainsKey(item.Key)) + { + moreStuff = true; + target.Responses.Add(item); + } + } + return moreStuff; + } + } +} From 8e45f8b531cb03db9695c65d18bd6f40c156d746 Mon Sep 17 00:00:00 2001 From: Maggie Kimani Date: Tue, 12 Oct 2021 12:24:44 +0300 Subject: [PATCH 04/29] Add necessary packages --- src/Microsoft.OpenApi/Microsoft.OpenApi.csproj | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Microsoft.OpenApi/Microsoft.OpenApi.csproj b/src/Microsoft.OpenApi/Microsoft.OpenApi.csproj index d0ff2fbcd..4d305cfdc 100644 --- a/src/Microsoft.OpenApi/Microsoft.OpenApi.csproj +++ b/src/Microsoft.OpenApi/Microsoft.OpenApi.csproj @@ -1,6 +1,7 @@  netstandard2.0 + 9.0 true http://go.microsoft.com/fwlink/?LinkID=288890 https://github.com/Microsoft/OpenAPI.NET @@ -36,7 +37,8 @@ - + + From f270b908247e0bf9d5478d2b0f24e05233fa9ceb Mon Sep 17 00:00:00 2001 From: Maggie Kimani Date: Tue, 12 Oct 2021 15:54:42 +0300 Subject: [PATCH 05/29] Simplify using statement and switch condition --- src/Microsoft.OpenApi.Tool/OpenApiService.cs | 49 +++++++------------- 1 file changed, 16 insertions(+), 33 deletions(-) diff --git a/src/Microsoft.OpenApi.Tool/OpenApiService.cs b/src/Microsoft.OpenApi.Tool/OpenApiService.cs index c52c08941..80e6bf7bc 100644 --- a/src/Microsoft.OpenApi.Tool/OpenApiService.cs +++ b/src/Microsoft.OpenApi.Tool/OpenApiService.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.IO; using System.Linq; @@ -52,43 +52,26 @@ public static void ProcessOpenApiDocument( errorReport.AppendLine(error.ToString()); } - throw new ArgumentException(String.Join(Environment.NewLine, context.Errors.Select(e => e.Message).ToArray())); + throw new ArgumentException(string.Join(Environment.NewLine, context.Errors.Select(e => e.Message).ToArray())); } - using (var outputStream = output?.Create()) - { - TextWriter textWriter; + using var outputStream = output?.Create(); - if (outputStream != null) - { - textWriter = new StreamWriter(outputStream); - } - else - { - textWriter = Console.Out; - } + var textWriter = outputStream != null ? new StreamWriter(outputStream) : Console.Out; - var settings = new OpenApiWriterSettings() - { - ReferenceInline = inline == true ? ReferenceInlineSetting.InlineLocalReferences : ReferenceInlineSetting.DoNotInlineReferences - }; - IOpenApiWriter writer; - switch (format) - { - case OpenApiFormat.Json: - writer = new OpenApiJsonWriter(textWriter, settings); - break; - case OpenApiFormat.Yaml: - writer = new OpenApiYamlWriter(textWriter, settings); - break; - default: - throw new ArgumentException("Unknown format"); - } - - document.Serialize(writer, version); + var settings = new OpenApiWriterSettings() + { + ReferenceInline = inline ? ReferenceInlineSetting.InlineLocalReferences : ReferenceInlineSetting.DoNotInlineReferences + }; + IOpenApiWriter writer = format switch + { + OpenApiFormat.Json => new OpenApiJsonWriter(textWriter, settings), + OpenApiFormat.Yaml => new OpenApiYamlWriter(textWriter, settings), + _ => throw new ArgumentException("Unknown format"), + }; + document.Serialize(writer, version); - textWriter.Flush(); - } + textWriter.Flush(); } private static Stream GetStream(string input) From 9cda4fb5fc5467c8f5980bba930e27a58b773105 Mon Sep 17 00:00:00 2001 From: Maggie Kimani Date: Mon, 18 Oct 2021 11:00:52 +0300 Subject: [PATCH 06/29] Use static class reference --- .../Services/OpenApiFilterServiceTests.cs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/test/Microsoft.OpenApi.Tests/Services/OpenApiFilterServiceTests.cs b/test/Microsoft.OpenApi.Tests/Services/OpenApiFilterServiceTests.cs index 7fedd989c..4f6a9bcbf 100644 --- a/test/Microsoft.OpenApi.Tests/Services/OpenApiFilterServiceTests.cs +++ b/test/Microsoft.OpenApi.Tests/Services/OpenApiFilterServiceTests.cs @@ -13,12 +13,10 @@ public class OpenApiFilterServiceTests { private const string Title = "Partial Graph API"; private const string GraphVersion = "mock"; - private readonly OpenApiFilterService _openApiFilterService; private readonly OpenApiDocument _openApiDocumentMock; public OpenApiFilterServiceTests() { - _openApiFilterService = new OpenApiFilterService(); _openApiDocumentMock = OpenApiDocumentMock.CreateOpenApiDocument(); } @@ -30,8 +28,8 @@ public OpenApiFilterServiceTests() public void ReturnFilteredOpenApiDocumentBasedOnOperationIds(string operationId) { // Act - var predicate = _openApiFilterService.CreatePredicate(operationId); - var subsetOpenApiDocument = _openApiFilterService.CreateFilteredDocument(_openApiDocumentMock, Title, GraphVersion, predicate); + var predicate = OpenApiFilterService.CreatePredicate(operationId); + var subsetOpenApiDocument = OpenApiFilterService.CreateFilteredDocument(_openApiDocumentMock, Title, GraphVersion, predicate); // Assert Assert.NotNull(subsetOpenApiDocument); @@ -42,7 +40,7 @@ public void ReturnFilteredOpenApiDocumentBasedOnOperationIds(string operationId) public void ThrowsInvalidOperationExceptionInCreatePredicateWhenInvalidOperationIdIsSpecified() { // Act and Assert - var message = Assert.Throws(() =>_openApiFilterService.CreatePredicate(null)).Message; + var message = Assert.Throws(() =>OpenApiFilterService.CreatePredicate(null)).Message; Assert.Equal("OperationId needs to be specified.", message); } } From af61c14ff792cb3bcdda8b115caa23a7a4c6b774 Mon Sep 17 00:00:00 2001 From: Maggie Kimani Date: Mon, 18 Oct 2021 11:01:53 +0300 Subject: [PATCH 07/29] Add --filterbyOperationId command option --- src/Microsoft.OpenApi.Tool/Program.cs | 31 +++++---------------------- 1 file changed, 5 insertions(+), 26 deletions(-) diff --git a/src/Microsoft.OpenApi.Tool/Program.cs b/src/Microsoft.OpenApi.Tool/Program.cs index 446e2829a..938986350 100644 --- a/src/Microsoft.OpenApi.Tool/Program.cs +++ b/src/Microsoft.OpenApi.Tool/Program.cs @@ -1,34 +1,12 @@ -using System; -using System.CommandLine; +using System.CommandLine; using System.CommandLine.Invocation; using System.IO; using System.Threading.Tasks; -using Microsoft.OpenApi; namespace Microsoft.OpenApi.Tool { - class Program + static class Program { - static async Task OldMain(string[] args) - { - - var command = new RootCommand - { - new Option("--input", "Input OpenAPI description file path or URL", typeof(string) ), - new Option("--output","Output OpenAPI description file", typeof(FileInfo), arity: ArgumentArity.ZeroOrOne), - new Option("--version", "OpenAPI specification version", typeof(OpenApiSpecVersion)), - new Option("--format", "File format",typeof(OpenApiFormat) ), - new Option("--inline", "Inline $ref instances", typeof(bool) ), - new Option("--resolveExternal","Resolve external $refs", typeof(bool)) - }; - - command.Handler = CommandHandler.Create( - OpenApiService.ProcessOpenApiDocument); - - // Parse the incoming args and invoke the handler - return await command.InvokeAsync(args); - } - static async Task Main(string[] args) { var rootCommand = new RootCommand() { @@ -47,9 +25,10 @@ static async Task Main(string[] args) new Option("--version", "OpenAPI specification version", typeof(OpenApiSpecVersion)), new Option("--format", "File format",typeof(OpenApiFormat) ), new Option("--inline", "Inline $ref instances", typeof(bool) ), - new Option("--resolveExternal","Resolve external $refs", typeof(bool)) + new Option("--resolveExternal","Resolve external $refs", typeof(bool)), + new Option("--filterByOperationId", "Filters by OperationId provided", typeof(string)) }; - transformCommand.Handler = CommandHandler.Create( + transformCommand.Handler = CommandHandler.Create( OpenApiService.ProcessOpenApiDocument); rootCommand.Add(transformCommand); From d24442d45833859d9c73ccb8840c7f918cd3ac93 Mon Sep 17 00:00:00 2001 From: Maggie Kimani Date: Mon, 18 Oct 2021 11:02:39 +0300 Subject: [PATCH 08/29] Add filterByOperationId param and logic --- src/Microsoft.OpenApi.Tool/OpenApiService.cs | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/Microsoft.OpenApi.Tool/OpenApiService.cs b/src/Microsoft.OpenApi.Tool/OpenApiService.cs index 80e6bf7bc..7b56f4516 100644 --- a/src/Microsoft.OpenApi.Tool/OpenApiService.cs +++ b/src/Microsoft.OpenApi.Tool/OpenApiService.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.IO; using System.Linq; @@ -16,11 +16,15 @@ namespace Microsoft.OpenApi.Tool { static class OpenApiService { + public const string GraphVersion_V1 = "v1.0"; + public const string Title = "Partial Graph API"; + public static void ProcessOpenApiDocument( string input, FileInfo output, OpenApiSpecVersion version, OpenApiFormat format, + string filterbyOperationId, bool inline, bool resolveExternal) { @@ -35,12 +39,20 @@ public static void ProcessOpenApiDocument( var result = new OpenApiStreamReader(new OpenApiReaderSettings { - ReferenceResolution = resolveExternal == true ? ReferenceResolutionSetting.ResolveAllReferences : ReferenceResolutionSetting.ResolveLocalReferences, + ReferenceResolution = resolveExternal ? ReferenceResolutionSetting.ResolveAllReferences : ReferenceResolutionSetting.ResolveLocalReferences, RuleSet = ValidationRuleSet.GetDefaultRuleSet() } ).ReadAsync(stream).GetAwaiter().GetResult(); document = result.OpenApiDocument; + + // Check if filter options are provided, then execute + if (!string.IsNullOrEmpty(filterbyOperationId)) + { + var predicate = OpenApiFilterService.CreatePredicate(filterbyOperationId); + document = OpenApiFilterService.CreateFilteredDocument(document, Title, GraphVersion_V1, predicate); + } + var context = result.OpenApiDiagnostic; if (context.Errors.Count != 0) From 501e88cebec533095d1fade8e3e43f45c54d904c Mon Sep 17 00:00:00 2001 From: Maggie Kimani Date: Mon, 18 Oct 2021 11:56:26 +0300 Subject: [PATCH 09/29] Add static modifier --- src/Microsoft.OpenApi/Services/OpenApiFilterService.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Microsoft.OpenApi/Services/OpenApiFilterService.cs b/src/Microsoft.OpenApi/Services/OpenApiFilterService.cs index 4f1795bc6..86722316f 100644 --- a/src/Microsoft.OpenApi/Services/OpenApiFilterService.cs +++ b/src/Microsoft.OpenApi/Services/OpenApiFilterService.cs @@ -1,4 +1,4 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. +// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. using System; @@ -63,7 +63,7 @@ public Func CreatePredicate(string operationIds) /// /// /// - public OpenApiDocument CreateFilteredDocument(OpenApiDocument source, string title, string graphVersion, Func predicate) + public static OpenApiDocument CreateFilteredDocument(OpenApiDocument source, string title, string graphVersion, Func predicate) { var subset = new OpenApiDocument { From d5b1b5e3c61547259f1aa6704c1533ca0c337c6d Mon Sep 17 00:00:00 2001 From: Maggie Kimani Date: Mon, 18 Oct 2021 12:10:27 +0300 Subject: [PATCH 10/29] Clean up and add xml comments --- .../Services/OpenApiFilterService.cs | 36 +++++++++---------- 1 file changed, 16 insertions(+), 20 deletions(-) diff --git a/src/Microsoft.OpenApi/Services/OpenApiFilterService.cs b/src/Microsoft.OpenApi/Services/OpenApiFilterService.cs index 86722316f..49cecd41e 100644 --- a/src/Microsoft.OpenApi/Services/OpenApiFilterService.cs +++ b/src/Microsoft.OpenApi/Services/OpenApiFilterService.cs @@ -1,4 +1,4 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. +// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. using System; @@ -9,26 +9,21 @@ namespace Microsoft.OpenApi.Services { /// - /// + /// A service that slices an OpenApiDocument into a subset document /// - public class OpenApiFilterService + public static class OpenApiFilterService { public static readonly string GraphAuthorizationUrl = "https://login.microsoftonline.com/common/oauth2/v2.0/authorize"; public static readonly string GraphTokenUrl = "https://login.microsoftonline.com/common/oauth2/v2.0/token"; public static readonly string GraphUrl = "https://graph.microsoft.com/{0}/"; public const string GraphVersion_V1 = "v1.0"; - - public OpenApiDocument CreateSubsetOpenApiDocument(string operationIds, OpenApiDocument source, string title) - { - var predicate = CreatePredicate(operationIds); - - var subsetOpenApiDocument = CreateFilteredDocument(source, title, GraphVersion_V1, predicate); - - return subsetOpenApiDocument; - } - - public Func CreatePredicate(string operationIds) + /// + /// Create predicate function based on passed query parameters + /// + /// Comma delimited list of operationIds or * for all operations. + /// A predicate. + public static Func CreatePredicate(string operationIds) { string predicateSource = null; @@ -55,14 +50,15 @@ public Func CreatePredicate(string operationIds) return predicate; } + /// - /// + /// Create partial OpenAPI document based on the provided predicate. /// - /// - /// - /// - /// - /// + /// The target . + /// The OpenAPI document title. + /// Version of the target Microsoft Graph API. + /// A predicate function. + /// A partial OpenAPI document. public static OpenApiDocument CreateFilteredDocument(OpenApiDocument source, string title, string graphVersion, Func predicate) { var subset = new OpenApiDocument From 4016ba1fe3a09bbb1fade1e3d43ea5e8bdbb97b5 Mon Sep 17 00:00:00 2001 From: Maggie Kimani Date: Mon, 18 Oct 2021 12:37:34 +0300 Subject: [PATCH 11/29] Add a class that visits the OpenApi operations and returns the search results --- .../Services/OperationSearch.cs | 67 +++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 src/Microsoft.OpenApi/Services/OperationSearch.cs diff --git a/src/Microsoft.OpenApi/Services/OperationSearch.cs b/src/Microsoft.OpenApi/Services/OperationSearch.cs new file mode 100644 index 000000000..01b1b5f56 --- /dev/null +++ b/src/Microsoft.OpenApi/Services/OperationSearch.cs @@ -0,0 +1,67 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; +using System.Collections.Generic; +using System.Linq; +using Microsoft.OpenApi.Models; + +namespace Microsoft.OpenApi.Services +{ + public class OperationSearch : OpenApiVisitorBase + { + private readonly Func _predicate; + private readonly List _searchResults = new(); + + public IList SearchResults => _searchResults; + + public OperationSearch(Func predicate) + { + _predicate = predicate ?? throw new ArgumentNullException(nameof(predicate)); + } + + /// + /// Visits . + /// + /// The target . + public override void Visit(OpenApiOperation operation) + { + if (_predicate(operation)) + { + _searchResults.Add(new SearchResult() + { + Operation = operation, + CurrentKeys = CopyCurrentKeys(CurrentKeys) + }); + } + } + + /// + /// Visits list of . + /// + /// The target list of . + public override void Visit(IList parameters) + { + /* The Parameter.Explode property should be true + * if Parameter.Style == Form; but OData query params + * as used in Microsoft Graph implement explode: false + * ex: $select=id,displayName,givenName + */ + foreach (var parameter in parameters.Where(x => x.Style == ParameterStyle.Form)) + { + parameter.Explode = false; + } + + base.Visit(parameters); + } + + private static CurrentKeys CopyCurrentKeys(CurrentKeys currentKeys) + { + return new CurrentKeys + { + Path = currentKeys.Path, + Operation = currentKeys.Operation + }; + } + } +} From 73bef228c86b86abf96043855ecb981c2f39e720 Mon Sep 17 00:00:00 2001 From: Maggie Kimani Date: Mon, 18 Oct 2021 12:38:06 +0300 Subject: [PATCH 12/29] Add a search result object model --- src/Microsoft.OpenApi/Services/SearchResult.cs | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 src/Microsoft.OpenApi/Services/SearchResult.cs diff --git a/src/Microsoft.OpenApi/Services/SearchResult.cs b/src/Microsoft.OpenApi/Services/SearchResult.cs new file mode 100644 index 000000000..2b7d9f94a --- /dev/null +++ b/src/Microsoft.OpenApi/Services/SearchResult.cs @@ -0,0 +1,13 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using Microsoft.OpenApi.Models; + +namespace Microsoft.OpenApi.Services +{ + public class SearchResult + { + public CurrentKeys CurrentKeys { get; set; } + public OpenApiOperation Operation { get; set; } + } +} From a1d46e57da451ac5d68ccc2b26f811b4cd607896 Mon Sep 17 00:00:00 2001 From: Maggie Kimani Date: Mon, 18 Oct 2021 12:43:03 +0300 Subject: [PATCH 13/29] Copies OpenApiOperation references to the new subset document --- .../Services/CopyReferences.cs | 101 ++++++++++++++++++ 1 file changed, 101 insertions(+) create mode 100644 src/Microsoft.OpenApi/Services/CopyReferences.cs diff --git a/src/Microsoft.OpenApi/Services/CopyReferences.cs b/src/Microsoft.OpenApi/Services/CopyReferences.cs new file mode 100644 index 000000000..9fc25b210 --- /dev/null +++ b/src/Microsoft.OpenApi/Services/CopyReferences.cs @@ -0,0 +1,101 @@ +using System.Collections.Generic; +using Microsoft.OpenApi.Interfaces; +using Microsoft.OpenApi.Models; + +namespace Microsoft.OpenApi.Services +{ + internal class CopyReferences : OpenApiVisitorBase + { + private readonly OpenApiDocument target; + public OpenApiComponents Components = new OpenApiComponents(); + + public CopyReferences(OpenApiDocument target) + { + this.target = target; + } + + public override void Visit(IOpenApiReferenceable referenceable) + { + switch (referenceable) + { + case OpenApiSchema schema: + EnsureComponentsExists(); + EnsureSchemasExists(); + if (!Components.Schemas.ContainsKey(schema.Reference.Id)) + { + Components.Schemas.Add(schema.Reference.Id, schema); + } + break; + + case OpenApiParameter parameter: + EnsureComponentsExists(); + EnsureParametersExists(); + if (!Components.Parameters.ContainsKey(parameter.Reference.Id)) + { + Components.Parameters.Add(parameter.Reference.Id, parameter); + } + break; + + case OpenApiResponse response: + EnsureComponentsExists(); + EnsureResponsesExists(); + if (!Components.Responses.ContainsKey(response.Reference.Id)) + { + Components.Responses.Add(response.Reference.Id, response); + } + break; + + default: + break; + } + base.Visit(referenceable); + } + + public override void Visit(OpenApiSchema schema) + { + // This is needed to handle schemas used in Responses in components + if (schema.Reference != null) + { + EnsureComponentsExists(); + EnsureSchemasExists(); + if (!Components.Schemas.ContainsKey(schema.Reference.Id)) + { + Components.Schemas.Add(schema.Reference.Id, schema); + } + } + base.Visit(schema); + } + + private void EnsureComponentsExists() + { + if (target.Components == null) + { + target.Components = new OpenApiComponents(); + } + } + + private void EnsureSchemasExists() + { + if (target.Components.Schemas == null) + { + target.Components.Schemas = new Dictionary(); + } + } + + private void EnsureParametersExists() + { + if (target.Components.Parameters == null) + { + target.Components.Parameters = new Dictionary(); + } + } + + private void EnsureResponsesExists() + { + if (target.Components.Responses == null) + { + target.Components.Responses = new Dictionary(); + } + } + } +} From b3c79eb037df7027f9dc8456d92b17add26e1414 Mon Sep 17 00:00:00 2001 From: Maggie Kimani Date: Wed, 20 Oct 2021 09:57:44 +0300 Subject: [PATCH 14/29] Copy OpenApiInfo and components from the source document to the new subset doc --- .../Services/OpenApiFilterService.cs | 35 ++++--------------- 1 file changed, 7 insertions(+), 28 deletions(-) diff --git a/src/Microsoft.OpenApi/Services/OpenApiFilterService.cs b/src/Microsoft.OpenApi/Services/OpenApiFilterService.cs index 49cecd41e..37f7f5610 100644 --- a/src/Microsoft.OpenApi/Services/OpenApiFilterService.cs +++ b/src/Microsoft.OpenApi/Services/OpenApiFilterService.cs @@ -13,11 +13,6 @@ namespace Microsoft.OpenApi.Services /// public static class OpenApiFilterService { - public static readonly string GraphAuthorizationUrl = "https://login.microsoftonline.com/common/oauth2/v2.0/authorize"; - public static readonly string GraphTokenUrl = "https://login.microsoftonline.com/common/oauth2/v2.0/token"; - public static readonly string GraphUrl = "https://graph.microsoft.com/{0}/"; - public const string GraphVersion_V1 = "v1.0"; - /// /// Create predicate function based on passed query parameters /// @@ -55,41 +50,25 @@ public static Func CreatePredicate(string operationIds) /// Create partial OpenAPI document based on the provided predicate. /// /// The target . - /// The OpenAPI document title. - /// Version of the target Microsoft Graph API. /// A predicate function. /// A partial OpenAPI document. - public static OpenApiDocument CreateFilteredDocument(OpenApiDocument source, string title, string graphVersion, Func predicate) + public static OpenApiDocument CreateFilteredDocument(OpenApiDocument source, Func predicate) { + // Fetch and copy title, graphVersion and server info from OpenApiDoc var subset = new OpenApiDocument { Info = new OpenApiInfo() { - Title = title, - Version = graphVersion + Title = source.Info.Title, + Version = source.Info.Version }, Components = new OpenApiComponents() }; - var aadv2Scheme = new OpenApiSecurityScheme() - { - Type = SecuritySchemeType.OAuth2, - Flows = new OpenApiOAuthFlows() - { - AuthorizationCode = new OpenApiOAuthFlow() - { - AuthorizationUrl = new Uri(GraphAuthorizationUrl), - TokenUrl = new Uri(GraphTokenUrl) - } - }, - Reference = new OpenApiReference() { Id = "azureaadv2", Type = ReferenceType.SecurityScheme }, - UnresolvedReference = false - }; - subset.Components.SecuritySchemes.Add("azureaadv2", aadv2Scheme); - - subset.SecurityRequirements.Add(new OpenApiSecurityRequirement() { { aadv2Scheme, Array.Empty() } }); - subset.Servers.Add(new OpenApiServer() { Description = "Core", Url = string.Format(GraphUrl, graphVersion) }); + subset.Components.SecuritySchemes = source.Components.SecuritySchemes; + subset.SecurityRequirements = source.SecurityRequirements; + subset.Servers = source.Servers; var results = FindOperations(source, predicate); foreach (var result in results) From cd5f3faff6dd1e962cdaf103513f5e520950af34 Mon Sep 17 00:00:00 2001 From: Maggie Kimani Date: Wed, 20 Oct 2021 09:58:00 +0300 Subject: [PATCH 15/29] Add an info object to the mock document --- .../Microsoft.OpenApi.Tests/Documents/OpenApiDocumentMock.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test/Microsoft.OpenApi.Tests/Documents/OpenApiDocumentMock.cs b/test/Microsoft.OpenApi.Tests/Documents/OpenApiDocumentMock.cs index 8b354b36f..676bf8e65 100644 --- a/test/Microsoft.OpenApi.Tests/Documents/OpenApiDocumentMock.cs +++ b/test/Microsoft.OpenApi.Tests/Documents/OpenApiDocumentMock.cs @@ -23,6 +23,11 @@ public static OpenApiDocument CreateOpenApiDocument() var document = new OpenApiDocument() { + Info = new OpenApiInfo() + { + Title = "People", + Version = "v1.0" + }, Paths = new OpenApiPaths() { ["/"] = new OpenApiPathItem() // root path From 3c43ea176ac08db90ea02b561a8fb75092935595 Mon Sep 17 00:00:00 2001 From: Maggie Kimani Date: Wed, 20 Oct 2021 09:58:22 +0300 Subject: [PATCH 16/29] Clean up: Remove unnecessary params --- src/Microsoft.OpenApi.Tool/OpenApiService.cs | 5 +---- .../Services/OpenApiFilterServiceTests.cs | 4 +--- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/src/Microsoft.OpenApi.Tool/OpenApiService.cs b/src/Microsoft.OpenApi.Tool/OpenApiService.cs index 7b56f4516..fe1a9d9b4 100644 --- a/src/Microsoft.OpenApi.Tool/OpenApiService.cs +++ b/src/Microsoft.OpenApi.Tool/OpenApiService.cs @@ -16,9 +16,6 @@ namespace Microsoft.OpenApi.Tool { static class OpenApiService { - public const string GraphVersion_V1 = "v1.0"; - public const string Title = "Partial Graph API"; - public static void ProcessOpenApiDocument( string input, FileInfo output, @@ -50,7 +47,7 @@ public static void ProcessOpenApiDocument( if (!string.IsNullOrEmpty(filterbyOperationId)) { var predicate = OpenApiFilterService.CreatePredicate(filterbyOperationId); - document = OpenApiFilterService.CreateFilteredDocument(document, Title, GraphVersion_V1, predicate); + document = OpenApiFilterService.CreateFilteredDocument(document, predicate); } var context = result.OpenApiDiagnostic; diff --git a/test/Microsoft.OpenApi.Tests/Services/OpenApiFilterServiceTests.cs b/test/Microsoft.OpenApi.Tests/Services/OpenApiFilterServiceTests.cs index 4f6a9bcbf..308f00952 100644 --- a/test/Microsoft.OpenApi.Tests/Services/OpenApiFilterServiceTests.cs +++ b/test/Microsoft.OpenApi.Tests/Services/OpenApiFilterServiceTests.cs @@ -11,8 +11,6 @@ namespace Microsoft.OpenApi.Tests.Services { public class OpenApiFilterServiceTests { - private const string Title = "Partial Graph API"; - private const string GraphVersion = "mock"; private readonly OpenApiDocument _openApiDocumentMock; public OpenApiFilterServiceTests() @@ -29,7 +27,7 @@ public void ReturnFilteredOpenApiDocumentBasedOnOperationIds(string operationId) { // Act var predicate = OpenApiFilterService.CreatePredicate(operationId); - var subsetOpenApiDocument = OpenApiFilterService.CreateFilteredDocument(_openApiDocumentMock, Title, GraphVersion, predicate); + var subsetOpenApiDocument = OpenApiFilterService.CreateFilteredDocument(_openApiDocumentMock, predicate); // Assert Assert.NotNull(subsetOpenApiDocument); From 43f48ec9fc5caf2ed4a4b5b9b973b1b2c738de78 Mon Sep 17 00:00:00 2001 From: Maggie Kimani Date: Thu, 21 Oct 2021 23:11:11 +0300 Subject: [PATCH 17/29] Remove package reference --- src/Microsoft.OpenApi/Microsoft.OpenApi.csproj | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Microsoft.OpenApi/Microsoft.OpenApi.csproj b/src/Microsoft.OpenApi/Microsoft.OpenApi.csproj index 4d305cfdc..e16b84db0 100644 --- a/src/Microsoft.OpenApi/Microsoft.OpenApi.csproj +++ b/src/Microsoft.OpenApi/Microsoft.OpenApi.csproj @@ -38,7 +38,6 @@ - From 8ba33cdbba85b5ce517168e7554e7a503efe6891 Mon Sep 17 00:00:00 2001 From: Maggie Kimani Date: Thu, 21 Oct 2021 23:11:11 +0300 Subject: [PATCH 18/29] Revert "Remove package reference" This reverts commit 43f48ec9fc5caf2ed4a4b5b9b973b1b2c738de78. --- src/Microsoft.OpenApi/Microsoft.OpenApi.csproj | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Microsoft.OpenApi/Microsoft.OpenApi.csproj b/src/Microsoft.OpenApi/Microsoft.OpenApi.csproj index e16b84db0..4d305cfdc 100644 --- a/src/Microsoft.OpenApi/Microsoft.OpenApi.csproj +++ b/src/Microsoft.OpenApi/Microsoft.OpenApi.csproj @@ -38,6 +38,7 @@ + From 2397e9d94370f212668e10eb3eecb21354cc7350 Mon Sep 17 00:00:00 2001 From: Maggie Kimani Date: Tue, 26 Oct 2021 17:09:23 +0300 Subject: [PATCH 19/29] Update the Public API interface text file --- .../PublicApi/PublicApi.approved.txt | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt b/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt index d5a89e586..180a7fd81 100755 --- a/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt +++ b/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt @@ -954,6 +954,11 @@ namespace Microsoft.OpenApi.Services public string Response { get; set; } public string ServerVariable { get; } } + public static class OpenApiFilterService + { + public static Microsoft.OpenApi.Models.OpenApiDocument CreateFilteredDocument(Microsoft.OpenApi.Models.OpenApiDocument source, System.Func predicate) { } + public static System.Func CreatePredicate(string operationIds) { } + } public class OpenApiReferenceError : Microsoft.OpenApi.Models.OpenApiError { public OpenApiReferenceError(Microsoft.OpenApi.Exceptions.OpenApiException exception) { } @@ -1044,6 +1049,19 @@ namespace Microsoft.OpenApi.Services public System.IO.Stream GetArtifact(string location) { } public Microsoft.OpenApi.Interfaces.IOpenApiReferenceable ResolveReference(Microsoft.OpenApi.Models.OpenApiReference reference) { } } + public class OperationSearch : Microsoft.OpenApi.Services.OpenApiVisitorBase + { + public OperationSearch(System.Func predicate) { } + public System.Collections.Generic.IList SearchResults { get; } + public override void Visit(Microsoft.OpenApi.Models.OpenApiOperation operation) { } + public override void Visit(System.Collections.Generic.IList parameters) { } + } + public class SearchResult + { + public SearchResult() { } + public Microsoft.OpenApi.Services.CurrentKeys CurrentKeys { get; set; } + public Microsoft.OpenApi.Models.OpenApiOperation Operation { get; set; } + } } namespace Microsoft.OpenApi.Validations { From d13dcf41f987fba5585cfe8186bde9a47a689b20 Mon Sep 17 00:00:00 2001 From: Maggie Kimani Date: Tue, 26 Oct 2021 17:09:50 +0300 Subject: [PATCH 20/29] Remove unnecessary package dependency --- src/Microsoft.OpenApi/Microsoft.OpenApi.csproj | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Microsoft.OpenApi/Microsoft.OpenApi.csproj b/src/Microsoft.OpenApi/Microsoft.OpenApi.csproj index 4d305cfdc..9c36ab07c 100644 --- a/src/Microsoft.OpenApi/Microsoft.OpenApi.csproj +++ b/src/Microsoft.OpenApi/Microsoft.OpenApi.csproj @@ -37,7 +37,6 @@ - From 00dd9c47202e66c3dc031cb5aab72a4c66d8e003 Mon Sep 17 00:00:00 2001 From: Maggie Kimani Date: Mon, 1 Nov 2021 10:49:02 +0300 Subject: [PATCH 21/29] Allow filtering for multiple operationIds --- src/Microsoft.OpenApi.Tool/OpenApiService.cs | 9 ++++----- src/Microsoft.OpenApi.Tool/Program.cs | 2 +- src/Microsoft.OpenApi/Services/OpenApiFilterService.cs | 2 +- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/src/Microsoft.OpenApi.Tool/OpenApiService.cs b/src/Microsoft.OpenApi.Tool/OpenApiService.cs index fe1a9d9b4..fca5999a1 100644 --- a/src/Microsoft.OpenApi.Tool/OpenApiService.cs +++ b/src/Microsoft.OpenApi.Tool/OpenApiService.cs @@ -1,5 +1,4 @@ -using System; -using System.Collections.Generic; +using System; using System.IO; using System.Linq; using System.Net; @@ -21,7 +20,7 @@ public static void ProcessOpenApiDocument( FileInfo output, OpenApiSpecVersion version, OpenApiFormat format, - string filterbyOperationId, + string filterByOperationIds, bool inline, bool resolveExternal) { @@ -44,9 +43,9 @@ public static void ProcessOpenApiDocument( document = result.OpenApiDocument; // Check if filter options are provided, then execute - if (!string.IsNullOrEmpty(filterbyOperationId)) + if (!string.IsNullOrEmpty(filterByOperationIds)) { - var predicate = OpenApiFilterService.CreatePredicate(filterbyOperationId); + var predicate = OpenApiFilterService.CreatePredicate(filterByOperationIds); document = OpenApiFilterService.CreateFilteredDocument(document, predicate); } diff --git a/src/Microsoft.OpenApi.Tool/Program.cs b/src/Microsoft.OpenApi.Tool/Program.cs index 938986350..570f2ea1e 100644 --- a/src/Microsoft.OpenApi.Tool/Program.cs +++ b/src/Microsoft.OpenApi.Tool/Program.cs @@ -26,7 +26,7 @@ static async Task Main(string[] args) new Option("--format", "File format",typeof(OpenApiFormat) ), new Option("--inline", "Inline $ref instances", typeof(bool) ), new Option("--resolveExternal","Resolve external $refs", typeof(bool)), - new Option("--filterByOperationId", "Filters by OperationId provided", typeof(string)) + new Option("--filterByOperationIds", "Filters by OperationId provided", typeof(string)) }; transformCommand.Handler = CommandHandler.Create( OpenApiService.ProcessOpenApiDocument); diff --git a/src/Microsoft.OpenApi/Services/OpenApiFilterService.cs b/src/Microsoft.OpenApi/Services/OpenApiFilterService.cs index 37f7f5610..36a31fa26 100644 --- a/src/Microsoft.OpenApi/Services/OpenApiFilterService.cs +++ b/src/Microsoft.OpenApi/Services/OpenApiFilterService.cs @@ -59,7 +59,7 @@ public static OpenApiDocument CreateFilteredDocument(OpenApiDocument source, Fun { Info = new OpenApiInfo() { - Title = source.Info.Title, + Title = source.Info.Title + " - subset", Version = source.Info.Version }, From 3f3dae04bdff4da9b3801b2f1acd016ee1922b5d Mon Sep 17 00:00:00 2001 From: Maggie Kimani Date: Mon, 1 Nov 2021 10:49:59 +0300 Subject: [PATCH 22/29] Add check for writing to an already existing file --- src/Microsoft.OpenApi.Tool/OpenApiService.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/Microsoft.OpenApi.Tool/OpenApiService.cs b/src/Microsoft.OpenApi.Tool/OpenApiService.cs index fca5999a1..34f51af64 100644 --- a/src/Microsoft.OpenApi.Tool/OpenApiService.cs +++ b/src/Microsoft.OpenApi.Tool/OpenApiService.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.IO; using System.Linq; using System.Net; @@ -63,6 +63,11 @@ public static void ProcessOpenApiDocument( throw new ArgumentException(string.Join(Environment.NewLine, context.Errors.Select(e => e.Message).ToArray())); } + if (output.Exists) + { + throw new IOException("The file you're writing to already exists.Please input a new output path."); + } + using var outputStream = output?.Create(); var textWriter = outputStream != null ? new StreamWriter(outputStream) : Console.Out; From 27ab7f7655bd74aa038534288d66e8bc8b22c801 Mon Sep 17 00:00:00 2001 From: Maggie Kimani Date: Tue, 2 Nov 2021 09:30:58 +0300 Subject: [PATCH 23/29] Copy over all Info properties --- src/Microsoft.OpenApi/Services/OpenApiFilterService.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Microsoft.OpenApi/Services/OpenApiFilterService.cs b/src/Microsoft.OpenApi/Services/OpenApiFilterService.cs index 36a31fa26..1ef69ef18 100644 --- a/src/Microsoft.OpenApi/Services/OpenApiFilterService.cs +++ b/src/Microsoft.OpenApi/Services/OpenApiFilterService.cs @@ -59,7 +59,11 @@ public static OpenApiDocument CreateFilteredDocument(OpenApiDocument source, Fun { Info = new OpenApiInfo() { - Title = source.Info.Title + " - subset", + Title = source.Info.Title + " - Subset", + Description = source.Info.Description, + TermsOfService = source.Info.TermsOfService, + Contact = source.Info.Contact, + License = source.Info.License, Version = source.Info.Version }, From c3c0abcd97d68aa4cae19776c4a02dab9377b413 Mon Sep 17 00:00:00 2001 From: Maggie Kimani Date: Tue, 2 Nov 2021 21:57:25 +0300 Subject: [PATCH 24/29] Add license header --- src/Microsoft.OpenApi.Tool/Program.cs | 5 ++++- src/Microsoft.OpenApi/Services/CopyReferences.cs | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/Microsoft.OpenApi.Tool/Program.cs b/src/Microsoft.OpenApi.Tool/Program.cs index 570f2ea1e..21be3406b 100644 --- a/src/Microsoft.OpenApi.Tool/Program.cs +++ b/src/Microsoft.OpenApi.Tool/Program.cs @@ -1,4 +1,7 @@ -using System.CommandLine; +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System.CommandLine; using System.CommandLine.Invocation; using System.IO; using System.Threading.Tasks; diff --git a/src/Microsoft.OpenApi/Services/CopyReferences.cs b/src/Microsoft.OpenApi/Services/CopyReferences.cs index 9fc25b210..e1db1360d 100644 --- a/src/Microsoft.OpenApi/Services/CopyReferences.cs +++ b/src/Microsoft.OpenApi/Services/CopyReferences.cs @@ -1,4 +1,7 @@ -using System.Collections.Generic; +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System.Collections.Generic; using Microsoft.OpenApi.Interfaces; using Microsoft.OpenApi.Models; From dbd8d925f6ed24a3e20fb5e7008f2ff46b7e352b Mon Sep 17 00:00:00 2001 From: Maggie Kimani Date: Tue, 2 Nov 2021 21:58:56 +0300 Subject: [PATCH 25/29] Clean up and add XML documentations for public methods --- src/Microsoft.OpenApi.Tool/OpenApiService.cs | 20 ++++++------ .../Services/CopyReferences.cs | 32 ++++++++++++------- .../Services/OpenApiFilterService.cs | 6 +--- 3 files changed, 32 insertions(+), 26 deletions(-) diff --git a/src/Microsoft.OpenApi.Tool/OpenApiService.cs b/src/Microsoft.OpenApi.Tool/OpenApiService.cs index 34f51af64..d9e9fa930 100644 --- a/src/Microsoft.OpenApi.Tool/OpenApiService.cs +++ b/src/Microsoft.OpenApi.Tool/OpenApiService.cs @@ -1,4 +1,7 @@ -using System; +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +using System; using System.IO; using System.Linq; using System.Net; @@ -24,9 +27,13 @@ public static void ProcessOpenApiDocument( bool inline, bool resolveExternal) { - if (input == null) + if (string.IsNullOrEmpty(input)) { - throw new ArgumentNullException("input"); + throw new ArgumentNullException(nameof(input)); + } + if (output.Exists) + { + throw new IOException("The file you're writing to already exists. Please input a new output path."); } var stream = GetStream(input); @@ -51,7 +58,7 @@ public static void ProcessOpenApiDocument( var context = result.OpenApiDiagnostic; - if (context.Errors.Count != 0) + if (context.Errors.Count > 0) { var errorReport = new StringBuilder(); @@ -63,11 +70,6 @@ public static void ProcessOpenApiDocument( throw new ArgumentException(string.Join(Environment.NewLine, context.Errors.Select(e => e.Message).ToArray())); } - if (output.Exists) - { - throw new IOException("The file you're writing to already exists.Please input a new output path."); - } - using var outputStream = output?.Create(); var textWriter = outputStream != null ? new StreamWriter(outputStream) : Console.Out; diff --git a/src/Microsoft.OpenApi/Services/CopyReferences.cs b/src/Microsoft.OpenApi/Services/CopyReferences.cs index e1db1360d..24dcfee25 100644 --- a/src/Microsoft.OpenApi/Services/CopyReferences.cs +++ b/src/Microsoft.OpenApi/Services/CopyReferences.cs @@ -1,4 +1,4 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. +// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. using System.Collections.Generic; @@ -9,14 +9,18 @@ namespace Microsoft.OpenApi.Services { internal class CopyReferences : OpenApiVisitorBase { - private readonly OpenApiDocument target; - public OpenApiComponents Components = new OpenApiComponents(); + private readonly OpenApiDocument _target; + public OpenApiComponents Components = new(); public CopyReferences(OpenApiDocument target) { - this.target = target; + _target = target; } + /// + /// Visits IOpenApiReferenceable instances that are references and not in components. + /// + /// An IOpenApiReferenceable object. public override void Visit(IOpenApiReferenceable referenceable) { switch (referenceable) @@ -54,6 +58,10 @@ public override void Visit(IOpenApiReferenceable referenceable) base.Visit(referenceable); } + /// + /// Visits + /// + /// The OpenApiSchema to be visited. public override void Visit(OpenApiSchema schema) { // This is needed to handle schemas used in Responses in components @@ -71,33 +79,33 @@ public override void Visit(OpenApiSchema schema) private void EnsureComponentsExists() { - if (target.Components == null) + if (_target.Components == null) { - target.Components = new OpenApiComponents(); + _target.Components = new OpenApiComponents(); } } private void EnsureSchemasExists() { - if (target.Components.Schemas == null) + if (_target.Components.Schemas == null) { - target.Components.Schemas = new Dictionary(); + _target.Components.Schemas = new Dictionary(); } } private void EnsureParametersExists() { - if (target.Components.Parameters == null) + if (_target.Components.Parameters == null) { - target.Components.Parameters = new Dictionary(); + _target.Components.Parameters = new Dictionary(); } } private void EnsureResponsesExists() { - if (target.Components.Responses == null) + if (_target.Components.Responses == null) { - target.Components.Responses = new Dictionary(); + _target.Components.Responses = new Dictionary(); } } } diff --git a/src/Microsoft.OpenApi/Services/OpenApiFilterService.cs b/src/Microsoft.OpenApi/Services/OpenApiFilterService.cs index 1ef69ef18..ce347c234 100644 --- a/src/Microsoft.OpenApi/Services/OpenApiFilterService.cs +++ b/src/Microsoft.OpenApi/Services/OpenApiFilterService.cs @@ -1,4 +1,4 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. +// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. using System; @@ -20,8 +20,6 @@ public static class OpenApiFilterService /// A predicate. public static Func CreatePredicate(string operationIds) { - string predicateSource = null; - Func predicate; if (operationIds != null) { @@ -34,8 +32,6 @@ public static Func CreatePredicate(string operationIds) var operationIdsArray = operationIds.Split(','); predicate = (o) => operationIdsArray.Contains(o.OperationId); } - - predicateSource = $"operationIds: {operationIds}"; } else From a689c3631c212d2eccf22d6807ba5fbb413ad5cd Mon Sep 17 00:00:00 2001 From: Maggie Kimani Date: Tue, 2 Nov 2021 21:59:20 +0300 Subject: [PATCH 26/29] Copy over extensions object to new document --- src/Microsoft.OpenApi/Services/OpenApiFilterService.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Microsoft.OpenApi/Services/OpenApiFilterService.cs b/src/Microsoft.OpenApi/Services/OpenApiFilterService.cs index ce347c234..4fd09314e 100644 --- a/src/Microsoft.OpenApi/Services/OpenApiFilterService.cs +++ b/src/Microsoft.OpenApi/Services/OpenApiFilterService.cs @@ -1,4 +1,4 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. +// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. using System; @@ -60,7 +60,8 @@ public static OpenApiDocument CreateFilteredDocument(OpenApiDocument source, Fun TermsOfService = source.Info.TermsOfService, Contact = source.Info.Contact, License = source.Info.License, - Version = source.Info.Version + Version = source.Info.Version, + Extensions = source.Info.Extensions }, Components = new OpenApiComponents() From deaa2fed7de2b21464307018ba5af574c5fd7128 Mon Sep 17 00:00:00 2001 From: Maggie Kimani Date: Wed, 3 Nov 2021 10:01:31 +0300 Subject: [PATCH 27/29] Move declaration closer to first reference point --- src/Microsoft.OpenApi.Tool/OpenApiService.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/Microsoft.OpenApi.Tool/OpenApiService.cs b/src/Microsoft.OpenApi.Tool/OpenApiService.cs index d9e9fa930..74f9455f0 100644 --- a/src/Microsoft.OpenApi.Tool/OpenApiService.cs +++ b/src/Microsoft.OpenApi.Tool/OpenApiService.cs @@ -37,9 +37,6 @@ public static void ProcessOpenApiDocument( } var stream = GetStream(input); - - OpenApiDocument document; - var result = new OpenApiStreamReader(new OpenApiReaderSettings { ReferenceResolution = resolveExternal ? ReferenceResolutionSetting.ResolveAllReferences : ReferenceResolutionSetting.ResolveLocalReferences, @@ -47,6 +44,7 @@ public static void ProcessOpenApiDocument( } ).ReadAsync(stream).GetAwaiter().GetResult(); + OpenApiDocument document; document = result.OpenApiDocument; // Check if filter options are provided, then execute From 015b3cd27b7454e7b905c5e804365ec5fa013b5c Mon Sep 17 00:00:00 2001 From: Maggie Kimani Date: Thu, 4 Nov 2021 13:21:57 +0300 Subject: [PATCH 28/29] Code cleanup --- src/Microsoft.OpenApi.Tool/OpenApiService.cs | 5 ++++- src/Microsoft.OpenApi/Services/OpenApiFilterService.cs | 2 +- src/Microsoft.OpenApi/Services/OperationSearch.cs | 10 ++++++++++ src/Microsoft.OpenApi/Services/SearchResult.cs | 10 ++++++++++ .../Workspaces/OpenApiWorkspaceTests.cs | 9 +++++---- 5 files changed, 30 insertions(+), 6 deletions(-) diff --git a/src/Microsoft.OpenApi.Tool/OpenApiService.cs b/src/Microsoft.OpenApi.Tool/OpenApiService.cs index 74f9455f0..87f02dcce 100644 --- a/src/Microsoft.OpenApi.Tool/OpenApiService.cs +++ b/src/Microsoft.OpenApi.Tool/OpenApiService.cs @@ -31,6 +31,10 @@ public static void ProcessOpenApiDocument( { throw new ArgumentNullException(nameof(input)); } + if(output == null) + { + throw new ArgumentException(nameof(output)); + } if (output.Exists) { throw new IOException("The file you're writing to already exists. Please input a new output path."); @@ -123,7 +127,6 @@ internal static void ValidateOpenApiDocument(string input) document = new OpenApiStreamReader(new OpenApiReaderSettings { - //ReferenceResolution = resolveExternal == true ? ReferenceResolutionSetting.ResolveAllReferences : ReferenceResolutionSetting.ResolveLocalReferences, RuleSet = ValidationRuleSet.GetDefaultRuleSet() } ).Read(stream, out var context); diff --git a/src/Microsoft.OpenApi/Services/OpenApiFilterService.cs b/src/Microsoft.OpenApi/Services/OpenApiFilterService.cs index 4fd09314e..5b5e6f59f 100644 --- a/src/Microsoft.OpenApi/Services/OpenApiFilterService.cs +++ b/src/Microsoft.OpenApi/Services/OpenApiFilterService.cs @@ -75,7 +75,7 @@ public static OpenApiDocument CreateFilteredDocument(OpenApiDocument source, Fun foreach (var result in results) { OpenApiPathItem pathItem; - string pathKey = result.CurrentKeys.Path; + var pathKey = result.CurrentKeys.Path; if (subset.Paths == null) { diff --git a/src/Microsoft.OpenApi/Services/OperationSearch.cs b/src/Microsoft.OpenApi/Services/OperationSearch.cs index 01b1b5f56..35d36b38f 100644 --- a/src/Microsoft.OpenApi/Services/OperationSearch.cs +++ b/src/Microsoft.OpenApi/Services/OperationSearch.cs @@ -8,13 +8,23 @@ namespace Microsoft.OpenApi.Services { + /// + /// Visits OpenApi operations and parameters. + /// public class OperationSearch : OpenApiVisitorBase { private readonly Func _predicate; private readonly List _searchResults = new(); + /// + /// A list of operations from the operation search. + /// public IList SearchResults => _searchResults; + /// + /// The OperationSearch constructor. + /// + /// A predicate function. public OperationSearch(Func predicate) { _predicate = predicate ?? throw new ArgumentNullException(nameof(predicate)); diff --git a/src/Microsoft.OpenApi/Services/SearchResult.cs b/src/Microsoft.OpenApi/Services/SearchResult.cs index 2b7d9f94a..381a11f95 100644 --- a/src/Microsoft.OpenApi/Services/SearchResult.cs +++ b/src/Microsoft.OpenApi/Services/SearchResult.cs @@ -5,9 +5,19 @@ namespace Microsoft.OpenApi.Services { + /// + /// Defines a search result model for visited operations. + /// public class SearchResult { + /// + /// An object containing contextual information based on where the walker is currently referencing in an OpenApiDocument. + /// public CurrentKeys CurrentKeys { get; set; } + + /// + /// An Operation object. + /// public OpenApiOperation Operation { get; set; } } } diff --git a/test/Microsoft.OpenApi.Tests/Workspaces/OpenApiWorkspaceTests.cs b/test/Microsoft.OpenApi.Tests/Workspaces/OpenApiWorkspaceTests.cs index b82327a5d..2102328eb 100644 --- a/test/Microsoft.OpenApi.Tests/Workspaces/OpenApiWorkspaceTests.cs +++ b/test/Microsoft.OpenApi.Tests/Workspaces/OpenApiWorkspaceTests.cs @@ -1,5 +1,5 @@ // Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT license. +// Licensed under the MIT license. using System; using System.Collections.Generic; @@ -12,7 +12,7 @@ namespace Microsoft.OpenApi.Tests { - + public class OpenApiWorkspaceTests { [Fact] @@ -61,7 +61,7 @@ public void OpenApiWorkspacesAllowDocumentsToReferenceEachOther() } } } - } + } } }); workspace.AddDocument("common", new OpenApiDocument() { @@ -111,7 +111,7 @@ public void OpenApiWorkspacesAllowDocumentsToReferenceEachOther_short() re.CreateContent("application/json", co => co.Schema = new OpenApiSchema() { - Reference = new OpenApiReference() // Reference + Reference = new OpenApiReference() // Reference { Id = "test", Type = ReferenceType.Schema, @@ -150,6 +150,7 @@ public void OpenApiWorkspacesShouldNormalizeDocumentLocations() // Enable Workspace to load from any reader, not just streams. // Test fragments + [Fact] public void OpenApiWorkspacesShouldLoadDocumentFragments() { Assert.True(false); From d259cc1c40ccdaf91f3608851200d52dca6707a0 Mon Sep 17 00:00:00 2001 From: Maggie Kimani Date: Fri, 5 Nov 2021 11:15:40 +0300 Subject: [PATCH 29/29] Remove [Fact] attribute --- test/Microsoft.OpenApi.Tests/Workspaces/OpenApiWorkspaceTests.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/test/Microsoft.OpenApi.Tests/Workspaces/OpenApiWorkspaceTests.cs b/test/Microsoft.OpenApi.Tests/Workspaces/OpenApiWorkspaceTests.cs index 2102328eb..dd6e2554b 100644 --- a/test/Microsoft.OpenApi.Tests/Workspaces/OpenApiWorkspaceTests.cs +++ b/test/Microsoft.OpenApi.Tests/Workspaces/OpenApiWorkspaceTests.cs @@ -150,7 +150,6 @@ public void OpenApiWorkspacesShouldNormalizeDocumentLocations() // Enable Workspace to load from any reader, not just streams. // Test fragments - [Fact] public void OpenApiWorkspacesShouldLoadDocumentFragments() { Assert.True(false);