Skip to content

Commit

Permalink
Merge pull request #401 from christianhelle/openapi-generator
Browse files Browse the repository at this point in the history
Add CLI Tool support for OpenAPI Generator pass through commands
  • Loading branch information
christianhelle authored Aug 24, 2022
2 parents c92a86f + 9f30fe9 commit dc6b2ef
Show file tree
Hide file tree
Showing 15 changed files with 472 additions and 244 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
using System;
using ApiClientCodeGen.Tests.Common.Infrastructure;
using AutoFixture.Xunit2;
using ChristianHelle.DeveloperTools.CodeGenerators.ApiClient.CLI.Commands;
using ChristianHelle.DeveloperTools.CodeGenerators.ApiClient.Core;
using ChristianHelle.DeveloperTools.CodeGenerators.ApiClient.Core.Generators;
using FluentAssertions;
using Moq;
using Xunit;

namespace ChristianHelle.DeveloperTools.CodeGenerators.ApiClient.CLI.Tests.Command
{
public class OpenApiCSharpGeneratorCommandTests
{
[Theory, AutoMoqData]
public void DefaultNamespace_Should_NotBeNullOrWhiteSpace(OpenApiCSharpGeneratorCommand sut)
=> sut.DefaultNamespace.Should().NotBeNullOrWhiteSpace();

[Theory, AutoMoqData]
public void SwaggerFile_Should_NotBeNullOrWhiteSpace(OpenApiCSharpGeneratorCommand sut)
=> sut.SwaggerFile.Should().NotBeNullOrWhiteSpace();

[Theory, AutoMoqData]
public void OutputFile_Should_NotBeNullOrWhiteSpace(OpenApiCSharpGeneratorCommand sut)
=> sut.OutputFile.Should().NotBeNullOrWhiteSpace();

[Theory, AutoMoqData]
public void CreateGenerator_Should_NotNull(OpenApiCSharpGeneratorCommand sut)
=> sut.CreateGenerator().Should().NotBeNull();

[Theory, AutoMoqData]
public void OnExecuteAsync_Should_NotThrow(
[Frozen] IProgressReporter progressReporter,
[Frozen] ICodeGenerator generator,
OpenApiCSharpGeneratorCommand sut,
string code)
{
Mock.Get(generator)
.Setup(c => c.GenerateCode(progressReporter))
.Returns(code);

new Func<int>(sut.OnExecute).Should().NotThrow();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
using ApiClientCodeGen.Tests.Common.Infrastructure;
using ChristianHelle.DeveloperTools.CodeGenerators.ApiClient.CLI.Commands;
using ChristianHelle.DeveloperTools.CodeGenerators.ApiClient.Core.Generators;
using ChristianHelle.DeveloperTools.CodeGenerators.ApiClient.Core.Installer;
using ChristianHelle.DeveloperTools.CodeGenerators.ApiClient.Core.Options.General;
using ChristianHelle.DeveloperTools.CodeGenerators.ApiClient.Core.Options.OpenApiGenerator;
using FluentAssertions;
using Xunit;

namespace ChristianHelle.DeveloperTools.CodeGenerators.ApiClient.CLI.Tests.Command
{
public class OpenApiCSharpGeneratorFactoryTests
{
[Theory, AutoMoqData]
public void Create_Should_Return_NotNull(
OpenApiCSharpGeneratorFactory sut,
string swaggerFile,
string defaultNamespace,
IGeneralOptions options,
IOpenApiGeneratorOptions openApiGeneratorOptions,
IProcessLauncher processLauncher,
IDependencyInstaller dependencyInstaller)
=> sut.Create(
swaggerFile,
defaultNamespace,
options,
openApiGeneratorOptions,
processLauncher,
dependencyInstaller)
.Should()
.NotBeNull();
}
}
Original file line number Diff line number Diff line change
@@ -1,45 +1,80 @@
using System;
using System.IO;
using ApiClientCodeGen.Tests.Common.Infrastructure;
using AutoFixture.Xunit2;
using ChristianHelle.DeveloperTools.CodeGenerators.ApiClient.CLI.Commands;
using ChristianHelle.DeveloperTools.CodeGenerators.ApiClient.Core;
using ChristianHelle.DeveloperTools.CodeGenerators.ApiClient.Core.Generators;
using ChristianHelle.DeveloperTools.CodeGenerators.ApiClient.Core.Installer;
using ChristianHelle.DeveloperTools.CodeGenerators.ApiClient.Core.Options.General;
using FluentAssertions;
using Moq;
using Xunit;

namespace ChristianHelle.DeveloperTools.CodeGenerators.ApiClient.CLI.Tests.Command
{
public class OpenApiGeneratorCommandTests
{
{
[Theory, AutoMoqData]
public void DefaultNamespace_Should_NotBeNullOrWhiteSpace(OpenApiGeneratorCommand sut)
=> sut.DefaultNamespace.Should().NotBeNullOrWhiteSpace();
public void OutputPath_Should_NotBeNullOrWhiteSpace(OpenApiGeneratorCommand sut)
=> sut.OutputPath.Should().NotBeNullOrWhiteSpace();

[Theory, AutoMoqData]
public void SwaggerFile_Should_NotBeNullOrWhiteSpace(OpenApiGeneratorCommand sut)
=> sut.SwaggerFile.Should().NotBeNullOrWhiteSpace();

[Theory, AutoMoqData]
public void OutputFile_Should_NotBeNullOrWhiteSpace(OpenApiGeneratorCommand sut)
=> sut.OutputFile.Should().NotBeNullOrWhiteSpace();
=> sut.OutputPath.Should().NotBeNullOrWhiteSpace();

[Theory, AutoMoqData]
public void CreateGenerator_Should_NotNull(OpenApiGeneratorCommand sut)
=> sut.CreateGenerator().Should().NotBeNull();
public void OnExecuteAsync_Should_NotThrow(OpenApiGeneratorCommand sut)
{
sut.OutputPath = Directory.GetCurrentDirectory();
new Func<int>(sut.OnExecute).Should().NotThrow();
}

[Theory, AutoMoqData]
public void OnExecuteAsync_Should_NotThrow(
[Frozen] IProgressReporter progressReporter,
[Frozen] ICodeGenerator generator,
OpenApiGeneratorCommand sut,
string code)
public void OnExecute_Should_Create_Generator(
[Frozen] IOpenApiGeneratorFactory factory,
OpenApiGeneratorCommand sut)
{
Mock.Get(generator)
.Setup(c => c.GenerateCode(progressReporter))
.Returns(code);

new Func<int>(sut.OnExecute).Should().NotThrow();
sut.OutputPath = Directory.GetCurrentDirectory();
sut.OnExecute();

Mock.Get(factory)
.Verify(
c => c.Create(
sut.Generator,
sut.SwaggerFile,
sut.OutputPath,
It.IsAny<IGeneralOptions>(),
It.IsAny<IProcessLauncher>(),
It.IsAny<IDependencyInstaller>()));
}

[Theory, AutoMoqData]
public void OnExecute_Should_Write_To_IConsole(
[Frozen] IOpenApiGeneratorFactory factory,
OpenApiGeneratorCommand sut)
{
var path = Directory.CreateDirectory(
Path.Combine(
Path.GetTempPath(),
Guid.NewGuid().ToString("N")));

sut.OutputPath = path.FullName;
sut.SkipLogging = false;
sut.OnExecute();

Mock.Get(factory)
.Verify(
c => c.Create(
sut.Generator,
sut.SwaggerFile,
sut.OutputPath,
It.IsAny<IGeneralOptions>(),
It.IsAny<IProcessLauncher>(),
It.IsAny<IDependencyInstaller>()));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
using ChristianHelle.DeveloperTools.CodeGenerators.ApiClient.Core.Generators;
using ChristianHelle.DeveloperTools.CodeGenerators.ApiClient.Core.Installer;
using ChristianHelle.DeveloperTools.CodeGenerators.ApiClient.Core.Options.General;
using ChristianHelle.DeveloperTools.CodeGenerators.ApiClient.Core.Options.OpenApiGenerator;
using FluentAssertions;
using Xunit;

Expand All @@ -14,17 +13,17 @@ public class OpenApiGeneratorFactoryTests
[Theory, AutoMoqData]
public void Create_Should_Return_NotNull(
OpenApiGeneratorFactory sut,
string generator,
string swaggerFile,
string defaultNamespace,
string oututPath,
IGeneralOptions options,
IOpenApiGeneratorOptions openApiGeneratorOptions,
IProcessLauncher processLauncher,
IDependencyInstaller dependencyInstaller)
=> sut.Create(
generator,
swaggerFile,
defaultNamespace,
oututPath,
options,
openApiGeneratorOptions,
processLauncher,
dependencyInstaller)
.Should()
Expand Down
2 changes: 1 addition & 1 deletion src/CLI/ApiClientCodeGen.CLI/Commands/CSharpCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ namespace ChristianHelle.DeveloperTools.CodeGenerators.ApiClient.CLI.Commands
typeof(AutoRestCommand),
typeof(NSwagCommand),
typeof(SwaggerCodegenCommand),
typeof(OpenApiGeneratorCommand))]
typeof(OpenApiCSharpGeneratorCommand))]
public class CSharpCommand
{
public int OnExecute(CommandLineApplication app)
Expand Down
119 changes: 119 additions & 0 deletions src/CLI/ApiClientCodeGen.CLI/Commands/OpenApiCSharpGeneratorCommand.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
using System;
using ChristianHelle.DeveloperTools.CodeGenerators.ApiClient.Core;
using ChristianHelle.DeveloperTools.CodeGenerators.ApiClient.Core.Generators;
using ChristianHelle.DeveloperTools.CodeGenerators.ApiClient.Core.Installer;
using ChristianHelle.DeveloperTools.CodeGenerators.ApiClient.Core.Logging;
using ChristianHelle.DeveloperTools.CodeGenerators.ApiClient.Core.Options.General;
using ChristianHelle.DeveloperTools.CodeGenerators.ApiClient.Core.Options.OpenApiGenerator;
using McMaster.Extensions.CommandLineUtils;

namespace ChristianHelle.DeveloperTools.CodeGenerators.ApiClient.CLI.Commands
{
[Command("openapi", Description = "Generate C# API client using OpenAPI Generator")]
public class OpenApiCSharpGeneratorCommand : CodeGeneratorCommand, IOpenApiGeneratorOptions
{
private readonly IGeneralOptions options;
private readonly IOpenApiGeneratorOptions openApiGeneratorOptions;
private readonly IProcessLauncher processLauncher;
private readonly IOpenApiCSharpGeneratorFactory cSharpGeneratorFactory;
private readonly IDependencyInstaller dependencyInstaller;

public OpenApiCSharpGeneratorCommand(
IConsoleOutput console,
IProgressReporter? progressReporter,
IGeneralOptions options,
IOpenApiGeneratorOptions openApiGeneratorOptions,
IProcessLauncher processLauncher,
IOpenApiCSharpGeneratorFactory cSharpGeneratorFactory,
IDependencyInstaller dependencyInstaller) : base(console, progressReporter)
{
this.options = options ?? throw new ArgumentNullException(nameof(options));
this.openApiGeneratorOptions = openApiGeneratorOptions;
this.processLauncher = processLauncher ?? throw new ArgumentNullException(nameof(processLauncher));
this.cSharpGeneratorFactory = cSharpGeneratorFactory ?? throw new ArgumentNullException(nameof(cSharpGeneratorFactory));
this.dependencyInstaller = dependencyInstaller ?? throw new ArgumentNullException(nameof(dependencyInstaller));
}

[Option(
ShortName = "emit",
LongName = "emit-default-value",
Description =
"Set to true if the default value for a member should be generated in the serialization stream. " +
"Setting the EmitDefaultValue property to false is not a recommended practice. " +
"It should only be done if there is a specific need to do so " +
"(such as for interoperability or to reduce data size).")]
public bool EmitDefaultValue
{
get => openApiGeneratorOptions.EmitDefaultValue;
set => openApiGeneratorOptions.EmitDefaultValue = value;
}

[Option(
ShortName = "optional-args",
LongName = "optional-method-arguments",
Description = "C# Optional method argument, e.g. void square(int x=10) (.net 4.0+ only).")]
public bool MethodArgument
{
get => openApiGeneratorOptions.MethodArgument;
set => openApiGeneratorOptions.MethodArgument = value;
}

[Option(
ShortName = "gpc",
LongName = "generate-property-changed")]
public bool GeneratePropertyChanged
{
get => openApiGeneratorOptions.GeneratePropertyChanged;
set => openApiGeneratorOptions.GeneratePropertyChanged = value;
}

[Option(
ShortName = "collection",
LongName = "use-collection",
Description = "Deserialize array types to Collection<T> instead of List<T>.")]
public bool UseCollection
{
get => openApiGeneratorOptions.UseCollection;
set => openApiGeneratorOptions.UseCollection = value;
}

[Option(
ShortName = "datetimeoffset",
LongName = "use-datetimeoffset",
Description = "Use DateTimeOffset to model date-time properties")]
public bool UseDateTimeOffset
{
get => openApiGeneratorOptions.UseDateTimeOffset;
set => openApiGeneratorOptions.UseDateTimeOffset = value;
}

[Option(
ShortName = "f",
LongName = "target-framework",
Description = "The target .NET Standard / Core / Framework version")]
public OpenApiSupportedTargetFramework TargetFramework
{
get => openApiGeneratorOptions.TargetFramework;
set => openApiGeneratorOptions.TargetFramework = value;
}

[Option(
ShortName = "custom-props",
LongName = "custom-additional-properties",
Description = "Setting this will override all the other additional properties")]
public string? CustomAdditionalProperties
{
get => openApiGeneratorOptions.CustomAdditionalProperties;
set => openApiGeneratorOptions.CustomAdditionalProperties = value;
}

public override ICodeGenerator CreateGenerator()
=> cSharpGeneratorFactory.Create(
SwaggerFile,
DefaultNamespace,
options,
openApiGeneratorOptions,
processLauncher,
dependencyInstaller);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
using ChristianHelle.DeveloperTools.CodeGenerators.ApiClient.Core.Generators;
using ChristianHelle.DeveloperTools.CodeGenerators.ApiClient.Core.Generators.OpenApi;
using ChristianHelle.DeveloperTools.CodeGenerators.ApiClient.Core.Installer;
using ChristianHelle.DeveloperTools.CodeGenerators.ApiClient.Core.Options.General;
using ChristianHelle.DeveloperTools.CodeGenerators.ApiClient.Core.Options.OpenApiGenerator;

namespace ChristianHelle.DeveloperTools.CodeGenerators.ApiClient.CLI.Commands
{
public interface IOpenApiCSharpGeneratorFactory
{
ICodeGenerator Create(
string swaggerFile,
string defaultNamespace,
IGeneralOptions options,
IOpenApiGeneratorOptions openApiGeneratorOptions,
IProcessLauncher processLauncher,
IDependencyInstaller dependencyInstaller);
}

public class OpenApiCSharpGeneratorFactory : IOpenApiCSharpGeneratorFactory
{
public ICodeGenerator Create(
string swaggerFile,
string defaultNamespace,
IGeneralOptions options,
IOpenApiGeneratorOptions openApiGeneratorOptions,
IProcessLauncher processLauncher,
IDependencyInstaller dependencyInstaller)
=> new OpenApiCSharpCodeGenerator(
swaggerFile,
defaultNamespace,
options,
openApiGeneratorOptions,
processLauncher,
dependencyInstaller);
}
}
Loading

0 comments on commit dc6b2ef

Please sign in to comment.