Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
},
"cSpell.words": [
"csdl",
"Hidi"
"Hidi",
"Xunit"
]
}
2 changes: 1 addition & 1 deletion performance/resultsComparer/resultsComparer.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
<PackageReference Include="Microsoft.Extensions.Logging" Version="10.0.10" />
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="10.0.10" />
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="10.0.10" />
<PackageReference Include="System.CommandLine" Version="2.0.5" />
<PackageReference Include="System.CommandLine" Version="2.0.10" />
<PackageReference Include="system.text.json" Version="10.0.10" />
</ItemGroup>

Expand Down
2 changes: 1 addition & 1 deletion src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="System.CommandLine" Version="2.0.5" />
<PackageReference Include="System.CommandLine" Version="2.0.10" />
<PackageReference Include="Microsoft.OData.Edm" Version="8.4.4" />
<PackageReference Include="Microsoft.OpenApi.OData" Version="3.2.1" />
<PackageReference Include="Microsoft.OpenApi.ApiManifest" Version="3.0.0-preview.1" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,12 @@

<!-- Windows-specific dependencies -->
<ItemGroup Condition="'$(OS)' == 'Windows_NT'">
<PackageReference Include="Microsoft.VisualStudio.Threading.Analyzers" Version="17.14.15">
<PackageReference Include="Microsoft.VisualStudio.Threading.Analyzers" Version="18.7.23">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="Microsoft.Windows.Compatibility" Version="10.0.5" />
<PackageReference Include="System.Security.Cryptography.Xml" Version="10.0.6" />
<PackageReference Include="Microsoft.Windows.Compatibility" Version="10.0.10" />
<PackageReference Include="System.Security.Cryptography.Xml" Version="10.0.10" />
</ItemGroup>

<!-- Windows-specific resources -->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
<PackageReference Include="coverlet.msbuild" Version="10.0.1" PrivateAssets="all" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.8.1" />
<PackageReference Include="Moq" Version="4.20.72" />
<PackageReference Include="xunit" Version="2.9.3" />
<PackageReference Include="xunit.v3" Version="3.2.2" />
<PackageReference Include="xunit.runner.visualstudio" Version="3.1.5" PrivateAssets="all" />
<PackageReference Include="coverlet.collector" Version="10.0.1" PrivateAssets="all" />
</ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ public void ReturnFilteredOpenApiDocumentBasedOnOperationIdsAndTags(string? oper
public void ReturnFilteredOpenApiDocumentBasedOnPostmanCollection()
{
// Arrange
var filePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "UtilityFiles", "postmanCollection_ver2.json");
var filePath = Path.Join(AppDomain.CurrentDomain.BaseDirectory, "UtilityFiles", "postmanCollection_ver2.json");
var fileInput = new FileInfo(filePath);
var stream = fileInput.OpenRead();

Expand Down Expand Up @@ -158,7 +158,7 @@ public void CreateFilteredDocumentUsingPredicateFromRequestUrl()
public void ShouldParseNestedPostmanCollection()
{
// Arrange
var filePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "UtilityFiles", "postmanCollection_ver3.json");
var filePath = Path.Join(AppDomain.CurrentDomain.BaseDirectory, "UtilityFiles", "postmanCollection_ver3.json");
var fileInput = new FileInfo(filePath);
var stream = fileInput.OpenRead();

Expand All @@ -175,7 +175,7 @@ public void ShouldParseNestedPostmanCollection()
public void ThrowsExceptionWhenUrlsInCollectionAreMissingFromSourceDocument()
{
// Arrange
var filePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "UtilityFiles", "postmanCollection_ver1.json");
var filePath = Path.Join(AppDomain.CurrentDomain.BaseDirectory, "UtilityFiles", "postmanCollection_ver1.json");
var fileInput = new FileInfo(filePath);
var stream = fileInput.OpenRead();

Expand All @@ -192,7 +192,7 @@ public void ThrowsExceptionWhenUrlsInCollectionAreMissingFromSourceDocument()
public void ContinueProcessingWhenUrlsInCollectionAreMissingFromSourceDocument()
{
// Arrange
var filePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "UtilityFiles", "postmanCollection_ver4.json");
var filePath = Path.Join(AppDomain.CurrentDomain.BaseDirectory, "UtilityFiles", "postmanCollection_ver4.json");
var fileInput = new FileInfo(filePath);
var stream = fileInput.OpenRead();

Expand Down Expand Up @@ -291,14 +291,14 @@ public void CreatePredicateMatchesAbsoluteUrlsWhenSourceHasNoServers()
public async Task CopiesOverAllReferencedComponentsToTheSubsetDocumentCorrectly()
{
// Arrange
var filePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "UtilityFiles", "docWithReusableHeadersAndExamples.yaml");
var filePath = Path.Join(AppDomain.CurrentDomain.BaseDirectory, "UtilityFiles", "docWithReusableHeadersAndExamples.yaml");
var operationIds = "getItems";

// Act
using var stream = File.OpenRead(filePath);
var settings = new OpenApiReaderSettings();
settings.AddYamlReader();
var doc = (await OpenApiDocument.LoadAsync(stream, "yaml", settings)).Document;
var doc = (await OpenApiDocument.LoadAsync(stream, "yaml", settings, TestContext.Current.CancellationToken)).Document;

// validated the tags are read as references
var openApiOperationTags = doc?.Paths["/items"].Operations?[HttpMethod.Get].Tags?.ToArray();
Expand Down Expand Up @@ -344,7 +344,7 @@ public async Task CopiesOverAllReferencedComponentsToTheSubsetDocumentCorrectly(
}
};
subsetOpenApiDocument.SerializeAsV3(writer);
await writer.FlushAsync();
await writer.FlushAsync(TestContext.Current.CancellationToken);
var result = outputStringWriter.ToString();
Assert.NotEmpty(result);
}
Expand Down
86 changes: 46 additions & 40 deletions test/Microsoft.OpenApi.Hidi.Tests/Services/OpenApiServiceTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -134,13 +134,13 @@ public async Task ShowCommandGeneratesMermaidMarkdownFileWithMermaidDiagramAsync
// create a dummy ILogger instance for testing
var options = new HidiOptions
{
OpenApi = Path.Combine("UtilityFiles", "SampleOpenApi.yml"),
Output = new("sample.md")
OpenApi = Path.Join("UtilityFiles", "SampleOpenApi.yml"),
Output = new($"{nameof(ShowCommandGeneratesMermaidMarkdownFileWithMermaidDiagramAsync)}.md")
};

await OpenApiService.ShowOpenApiDocumentAsync(options, _logger);
await OpenApiService.ShowOpenApiDocumentAsync(options, _logger, TestContext.Current.CancellationToken);

var output = await File.ReadAllTextAsync(options.Output.FullName);
var output = await File.ReadAllTextAsync(options.Output.FullName, TestContext.Current.CancellationToken);
Assert.Contains("graph LR", output, StringComparison.Ordinal);
}

Expand All @@ -149,54 +149,54 @@ public async Task ShowCommandGeneratesMermaidHtmlFileWithMermaidDiagramAsync()
{
var options = new HidiOptions
{
OpenApi = Path.Combine("UtilityFiles", "SampleOpenApi.yml")
OpenApi = Path.Join("UtilityFiles", "SampleOpenApi.yml")
};
var filePath = await OpenApiService.ShowOpenApiDocumentAsync(options, _logger);
var filePath = await OpenApiService.ShowOpenApiDocumentAsync(options, _logger, TestContext.Current.CancellationToken);
Assert.True(File.Exists(filePath));
}

[Fact]
public Task ThrowIfOpenApiUrlIsNotProvidedWhenValidatingAsync()
{
return Assert.ThrowsAsync<ArgumentNullException>(() =>
OpenApiService.ValidateOpenApiDocumentAsync("", _logger));
OpenApiService.ValidateOpenApiDocumentAsync("", _logger, TestContext.Current.CancellationToken));
}

[Fact]
public Task ThrowIfURLIsNotResolvableWhenValidatingAsync()
{
return Assert.ThrowsAsync<InvalidOperationException>(() =>
OpenApiService.ValidateOpenApiDocumentAsync("https://example.org926F4F21-88E7-4DC5-BF88-6C529BB77844/itdoesnmatter", _logger));
OpenApiService.ValidateOpenApiDocumentAsync("https://example.org926F4F21-88E7-4DC5-BF88-6C529BB77844/itdoesnmatter", _logger, TestContext.Current.CancellationToken));
}

[Fact]
public Task ThrowIfFileDoesNotExistWhenValidatingAsync()
{
return Assert.ThrowsAsync<InvalidOperationException>(() =>
OpenApiService.ValidateOpenApiDocumentAsync("aFileThatBetterNotExist.fake", _logger));
OpenApiService.ValidateOpenApiDocumentAsync("aFileThatBetterNotExist.fake", _logger, TestContext.Current.CancellationToken));
}

[Fact]
public async Task ValidateCommandProcessesOpenApiAsync()
{
// create a dummy ILogger instance for testing
await OpenApiService.ValidateOpenApiDocumentAsync(Path.Combine("UtilityFiles", "SampleOpenApi.yml"), _logger);
await OpenApiService.ValidateOpenApiDocumentAsync(Path.Join("UtilityFiles", "SampleOpenApi.yml"), _logger, TestContext.Current.CancellationToken);

Assert.True(true);
}

[Fact]
public async Task ValidFileReturnsTrueAsync()
{
var isValid = await OpenApiService.ValidateOpenApiDocumentAsync(Path.Combine("UtilityFiles", "SampleOpenApi.yml"), _logger);
var isValid = await OpenApiService.ValidateOpenApiDocumentAsync(Path.Join("UtilityFiles", "SampleOpenApi.yml"), _logger, TestContext.Current.CancellationToken);

Assert.True(isValid);
}

[Fact]
public async Task InvalidFileReturnsFalseAsync()
{
var isValid = await OpenApiService.ValidateOpenApiDocumentAsync(Path.Combine("UtilityFiles", "InvalidSampleOpenApi.yml"), _logger);
var isValid = await OpenApiService.ValidateOpenApiDocumentAsync(Path.Join("UtilityFiles", "InvalidSampleOpenApi.yml"), _logger, TestContext.Current.CancellationToken);

Assert.False(isValid);
}
Expand All @@ -206,7 +206,7 @@ public async Task CancellingValidationReturnsNullAsync()
{
using var cts = new CancellationTokenSource();
await cts.CancelAsync();
var isValid = await OpenApiService.ValidateOpenApiDocumentAsync(Path.Combine("UtilityFiles", "SampleOpenApi.yml"), _logger, cts.Token);
var isValid = await OpenApiService.ValidateOpenApiDocumentAsync(Path.Join("UtilityFiles", "SampleOpenApi.yml"), _logger, cts.Token);

Assert.Null(isValid);
}
Expand All @@ -216,17 +216,17 @@ public async Task TransformCommandConvertsOpenApiAsync()
{
var options = new HidiOptions
{
OpenApi = Path.Combine("UtilityFiles", "SampleOpenApi.yml"),
Output = new("sample.json"),
OpenApi = Path.Join("UtilityFiles", "SampleOpenApi.yml"),
Output = new($"{nameof(TransformCommandConvertsOpenApiAsync)}.json"),
CleanOutput = true,
TerseOutput = false,
InlineLocal = false,
InlineExternal = false,
};
// create a dummy ILogger instance for testing
await OpenApiService.TransformOpenApiDocumentAsync(options, _logger);
await OpenApiService.TransformOpenApiDocumentAsync(options, _logger, TestContext.Current.CancellationToken);

var output = await File.ReadAllTextAsync("sample.json");
var output = await File.ReadAllTextAsync(options.Output.FullName, TestContext.Current.CancellationToken);
Assert.NotEmpty(output);
}

Expand All @@ -236,16 +236,17 @@ public async Task TransformCommandConvertsOpenApiWithDefaultOutputNameAsync()
{
var options = new HidiOptions
{
OpenApi = Path.Combine("UtilityFiles", "SampleOpenApi.yml"),
OpenApi = Path.Join("UtilityFiles", "SampleOpenApi.yml"),
CleanOutput = true,
TerseOutput = false,
InlineLocal = false,
InlineExternal = false,
Output = new FileInfo($"{nameof(TransformCommandConvertsOpenApiWithDefaultOutputNameAsync)}.yml")
};
// create a dummy ILogger instance for testing
await OpenApiService.TransformOpenApiDocumentAsync(options, _logger);
await OpenApiService.TransformOpenApiDocumentAsync(options, _logger, TestContext.Current.CancellationToken);

var output = await File.ReadAllTextAsync("output.yml");
var output = await File.ReadAllTextAsync(options.Output.FullName, TestContext.Current.CancellationToken);
Assert.NotEmpty(output);
}

Expand All @@ -254,7 +255,8 @@ public async Task TransformCommandConvertsOpenApiWithDefaultOutputNameAndSwitchF
{
var options = new HidiOptions
{
OpenApi = Path.Combine("UtilityFiles", "SampleOpenApi.yml"),
OpenApi = Path.Join("UtilityFiles", "SampleOpenApi.yml"),
Output = new($"{nameof(TransformCommandConvertsOpenApiWithDefaultOutputNameAndSwitchFormatAsync)}.yml"),
CleanOutput = true,
Version = "3.0",
OpenApiFormat = OpenApiConstants.Yaml,
Expand All @@ -263,9 +265,9 @@ public async Task TransformCommandConvertsOpenApiWithDefaultOutputNameAndSwitchF
InlineExternal = false,
};
// create a dummy ILogger instance for testing
await OpenApiService.TransformOpenApiDocumentAsync(options, _logger);
await OpenApiService.TransformOpenApiDocumentAsync(options, _logger, TestContext.Current.CancellationToken);

var output = await File.ReadAllTextAsync("output.yml");
var output = await File.ReadAllTextAsync(options.Output.FullName, TestContext.Current.CancellationToken);
Assert.NotEmpty(output);
}

Expand All @@ -280,16 +282,17 @@ public Task ThrowTransformCommandIfOpenApiAndCsdlAreEmptyAsync()
InlineExternal = false,
};
return Assert.ThrowsAsync<ArgumentException>(() =>
OpenApiService.TransformOpenApiDocumentAsync(options, _logger));
OpenApiService.TransformOpenApiDocumentAsync(options, _logger, TestContext.Current.CancellationToken));
}

[Fact]
public async Task TransformToPowerShellCompliantOpenApiAsync()
{
var settingsPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "UtilityFiles", "examplepowershellsettings.json");
var settingsPath = Path.Join(AppDomain.CurrentDomain.BaseDirectory, "UtilityFiles", "examplepowershellsettings.json");
var options = new HidiOptions
{
OpenApi = Path.Combine("UtilityFiles", "SampleOpenApi.yml"),
OpenApi = Path.Join("UtilityFiles", "SampleOpenApi.yml"),
Output = new($"{nameof(TransformToPowerShellCompliantOpenApiAsync)}.yaml"),
CleanOutput = true,
Version = "3.0",
OpenApiFormat = OpenApiConstants.Yaml,
Expand All @@ -299,24 +302,25 @@ public async Task TransformToPowerShellCompliantOpenApiAsync()
SettingsConfig = SettingsUtilities.GetConfiguration(settingsPath)
};
// create a dummy ILogger instance for testing
await OpenApiService.TransformOpenApiDocumentAsync(options, _logger);
await OpenApiService.TransformOpenApiDocumentAsync(options, _logger, TestContext.Current.CancellationToken);

var output = await File.ReadAllTextAsync("output.yaml");
var output = await File.ReadAllTextAsync(options.Output.FullName, TestContext.Current.CancellationToken);
Assert.NotEmpty(output);
}

[Fact]
public async Task InvokeTransformCommandAsync()
{
var rootCommand = Program.CreateRootCommand();
var openapi = Path.Combine(".", "UtilityFiles", "SampleOpenApi.yml");
var args = new[] { "transform", "-d", openapi, "-o", "sample.json", "--co" };
var openapi = Path.Join(".", "UtilityFiles", "SampleOpenApi.yml");
var outputPath = $"{nameof(InvokeTransformCommandAsync)}.json";
var args = new[] { "transform", "-d", openapi, "-o", outputPath, "--co" };
var parseResult = rootCommand.Parse(args);
var handler = Assert.IsType<AsynchronousCommandLineAction>(rootCommand.Subcommands.First(c => c.Name == "transform").Action, exactMatch: false);

await handler.InvokeAsync(parseResult);
await handler.InvokeAsync(parseResult, TestContext.Current.CancellationToken);

var output = await File.ReadAllTextAsync("sample.json");
var output = await File.ReadAllTextAsync(outputPath, TestContext.Current.CancellationToken);
Assert.NotEmpty(output);
}

Expand All @@ -325,29 +329,31 @@ public async Task InvokeTransformCommandAsync()
public async Task InvokeShowCommandAsync()
{
var rootCommand = Program.CreateRootCommand();
var openApi = Path.Combine(".", "UtilityFiles", "SampleOpenApi.yml");
var args = new[] { "show", "-d", openApi, "-o", "sample.md" };
var openApi = Path.Join(".", "UtilityFiles", "SampleOpenApi.yml");
var outputPath = $"{nameof(InvokeShowCommandAsync)}.md";
var args = new[] { "show", "-d", openApi, "-o", outputPath };
var parseResult = rootCommand.Parse(args);
var handler = Assert.IsType<AsynchronousCommandLineAction>(rootCommand.Subcommands.First(c => c.Name == "show").Action, exactMatch: false);

await handler.InvokeAsync(parseResult);
await handler.InvokeAsync(parseResult, TestContext.Current.CancellationToken);

var output = await File.ReadAllTextAsync("sample.md");
var output = await File.ReadAllTextAsync(outputPath, TestContext.Current.CancellationToken);
Assert.Contains("graph LR", output, StringComparison.Ordinal);
}

[Fact]
public async Task InvokePluginCommandAsync()
{
var rootCommand = Program.CreateRootCommand();
var manifest = Path.Combine(".", "UtilityFiles", "exampleapimanifest.json");
var args = new[] { "plugin", "-m", manifest, "--of", AppDomain.CurrentDomain.BaseDirectory };
var manifest = Path.Join(".", "UtilityFiles", "exampleapimanifest.json");
var outputPath = Path.Join(AppDomain.CurrentDomain.BaseDirectory, nameof(InvokePluginCommandAsync));
var args = new[] { "plugin", "-m", manifest, "--of", outputPath };
var parseResult = rootCommand.Parse(args);
var handler = Assert.IsType<AsynchronousCommandLineAction>(rootCommand.Subcommands.First(c => c.Name == "plugin").Action, exactMatch: false);

await handler.InvokeAsync(parseResult);
await handler.InvokeAsync(parseResult, TestContext.Current.CancellationToken);

using var jsDoc = JsonDocument.Parse(await File.ReadAllTextAsync("ai-plugin.json"));
using var jsDoc = JsonDocument.Parse(await File.ReadAllTextAsync(Path.Join(outputPath, "ai-plugin.json"), TestContext.Current.CancellationToken));
var openAiManifest = OpenAIPluginManifest.Load(jsDoc.RootElement);

Assert.NotNull(openAiManifest);
Expand Down
Loading
Loading