diff --git a/src/Aspire.Hosting.NodeJs/NodeAppResource.cs b/src/Aspire.Hosting.NodeJs/NodeAppResource.cs index 6bb55c880d6..381d54a6200 100644 --- a/src/Aspire.Hosting.NodeJs/NodeAppResource.cs +++ b/src/Aspire.Hosting.NodeJs/NodeAppResource.cs @@ -1,5 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics.CodeAnalysis; +using System.Runtime.CompilerServices; using Aspire.Hosting.ApplicationModel; namespace Aspire.Hosting; @@ -11,7 +13,8 @@ namespace Aspire.Hosting; /// The command to execute. /// The working directory to use for the command. If null, the working directory of the current process is used. public class NodeAppResource(string name, string command, string workingDirectory) - : ExecutableResource(name, command, workingDirectory), IResourceWithServiceDiscovery + : ExecutableResource(ThrowIfNull(name), ThrowIfNull(command), ThrowIfNull(workingDirectory)), IResourceWithServiceDiscovery { - + private static string ThrowIfNull([NotNull] string? argument, [CallerArgumentExpression(nameof(argument))] string? paramName = null) + => argument ?? throw new ArgumentNullException(paramName); } diff --git a/src/Aspire.Hosting.NodeJs/NodeExtensions.cs b/src/Aspire.Hosting.NodeJs/NodeExtensions.cs index e0dba211468..dcae1462ca4 100644 --- a/src/Aspire.Hosting.NodeJs/NodeExtensions.cs +++ b/src/Aspire.Hosting.NodeJs/NodeExtensions.cs @@ -22,6 +22,10 @@ public static class NodeAppHostingExtension /// A reference to the . public static IResourceBuilder AddNodeApp(this IDistributedApplicationBuilder builder, string name, string scriptPath, string? workingDirectory = null, string[]? args = null) { + ArgumentNullException.ThrowIfNull(builder); + ArgumentNullException.ThrowIfNull(name); + ArgumentNullException.ThrowIfNull(scriptPath); + args ??= []; string[] effectiveArgs = [scriptPath, .. args]; workingDirectory ??= Path.GetDirectoryName(scriptPath)!; @@ -45,6 +49,12 @@ public static IResourceBuilder AddNodeApp(this IDistributedAppl /// A reference to the . public static IResourceBuilder AddNpmApp(this IDistributedApplicationBuilder builder, string name, string workingDirectory, string scriptName = "start", string[]? args = null) { + + ArgumentNullException.ThrowIfNull(builder); + ArgumentNullException.ThrowIfNull(name); + ArgumentNullException.ThrowIfNull(workingDirectory); + ArgumentNullException.ThrowIfNull(scriptName); + string[] allArgs = args is { Length: > 0 } ? ["run", scriptName, "--", .. args] : ["run", scriptName]; diff --git a/tests/Aspire.Hosting.NodeJs.Tests/NodeJsPublicApiTests.cs b/tests/Aspire.Hosting.NodeJs.Tests/NodeJsPublicApiTests.cs new file mode 100644 index 00000000000..d0276726df4 --- /dev/null +++ b/tests/Aspire.Hosting.NodeJs.Tests/NodeJsPublicApiTests.cs @@ -0,0 +1,140 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Xunit; + +namespace Aspire.Hosting.NodeJs.Tests; + +public class NodeJsPublicApiTests +{ + [Fact] + public void AddNodeAppShouldThrowWhenBuilderIsNull() + { + IDistributedApplicationBuilder builder = null!; + var name = "nodeapp"; + var scriptPath = ".\\app.js"; + + var action = () => builder.AddNodeApp(name: name, scriptPath: scriptPath); + + var exception = Assert.Throws(action); + Assert.Equal(nameof(builder), exception.ParamName); + } + + [Fact] + public void AddNodeAppShouldThrowWhenNameIsNull() + { + var builder = DistributedApplication.CreateBuilder(); + string name = null!; + var scriptPath = ".\\app.js"; + + var action = () => builder.AddNodeApp(name: name, scriptPath: scriptPath); + + var exception = Assert.Throws(action); + Assert.Equal(nameof(name), exception.ParamName); + } + + [Fact] + public void AddNodeAppShouldThrowWhenScriptPathIsNull() + { + var builder = DistributedApplication.CreateBuilder(); + var name = "nodeapp"; + string scriptPath = null!; + + var action = () => builder.AddNodeApp(name: name, scriptPath: scriptPath); + + var exception = Assert.Throws(action); + Assert.Equal(nameof(scriptPath), exception.ParamName); + } + + [Fact] + public void AddNpmAppShouldThrowWhenBuilderIsNull() + { + IDistributedApplicationBuilder builder = null!; + var name = "npmapp"; + var workingDirectory = ".\\app"; + + var action = () => builder.AddNpmApp(name: name, workingDirectory: workingDirectory); + + var exception = Assert.Throws(action); + Assert.Equal(nameof(builder), exception.ParamName); + } + + [Fact] + public void AddNpmAppShouldThrowWhenWorkingDirectoryIsNull() + { + var builder = DistributedApplication.CreateBuilder(); + var name = "npmapp"; + string workingDirectory = null!; + + var action = () => builder.AddNpmApp(name: name, workingDirectory: workingDirectory); + + var exception = Assert.Throws(action); + Assert.Equal(nameof(workingDirectory), exception.ParamName); + } + + [Fact] + public void AddNpmAppShouldThrowWhenNameIsNull() + { + var builder = DistributedApplication.CreateBuilder(); + string name = null!; + var workingDirectory = ".\\app"; + + var action = () => builder.AddNpmApp(name: name, workingDirectory: workingDirectory); + + var exception = Assert.Throws(action); + Assert.Equal(nameof(name), exception.ParamName); + } + + [Fact] + public void AddNpmAppShouldThrowWhenScriptNameIsNull() + { + var builder = DistributedApplication.CreateBuilder(); + var name = "npmapp"; + var workingDirectory = ".\\app"; + string scriptName = null!; + + var action = () => builder.AddNpmApp(name: name, workingDirectory: workingDirectory, scriptName: scriptName); + + var exception = Assert.Throws(action); + Assert.Equal(nameof(scriptName), exception.ParamName); + } + + [Fact] + public void CtorNodeAppResourceShouldThrowWhenNameIsNull() + { + string name = null!; + var command = "start"; + var workingDirectory = ".\\app"; + + var action = () => new NodeAppResource(name, command, workingDirectory); + + var exception = Assert.Throws(action); + Assert.Equal(nameof(name), exception.ParamName); + } + + [Fact] + public void CtorNodeAppResourceShouldThrowWhenCommandIsNull() + { + var name = "nodeapp"; + string command = null!; + var workingDirectory = ".\\app"; + + var action = () => new NodeAppResource(name, command, workingDirectory); + + var exception = Assert.Throws(action); + Assert.Equal(nameof(command), exception.ParamName); + } + + [Fact] + public void CtorNodeAppResourceShouldThrowWhenWorkingDirectoryIsNull() + { + var name = "nodeapp"; + var command = "start"; + string workingDirectory = null!; + + var action = () => new NodeAppResource(name, command, workingDirectory); + + var exception = Assert.Throws(action); + Assert.Equal(nameof(workingDirectory), exception.ParamName); + } +}