From 9a6295fb90e55144a1bc089166c2e756b46f916f Mon Sep 17 00:00:00 2001 From: Nikolay Pianikov Date: Thu, 24 Oct 2024 18:51:32 +0300 Subject: [PATCH] Add comments --- CSharpInteractive.HostApi/DotNetCommands.cs | 507 +++++++++++++++--- CSharpInteractive.HostApi/DotNetCommands.tt | 119 ++-- .../DotNet/DotNetCommandLineExtensions.cs | 5 + CSharpInteractive.Tests/README_TEMPLATE.md | 354 ++++++++++-- CSharpInteractive.Tests/README_TEMPLATE.tt | 18 +- .../UsageScenarios/Comments/ArgsScenario.txt | 9 + .../Comments/CommandLineAsyncCancellation.txt | 9 + .../Comments/CommandLineAsyncScenario.txt | 11 + .../CommandLineInParallelScenario.txt | 12 + .../Comments/CommandLineOutputScenario.txt | 10 + .../Comments/CommandLineScenario.txt | 19 + .../CommandLineWithTimeoutScenario.txt | 7 + .../Comments/CommandLinesScenario.txt | 44 ++ .../Comments/DockerDotNetBuildScenario.txt | 27 + .../Comments/DockerRunScenario.txt | 11 + .../Comments/DotNetAddPackageScenario.txt | 20 + .../Comments/DotNetAddReferenceScenario.txt | 25 + .../Comments/DotNetBuildScenario.txt | 25 + .../DotNetBuildServerShutdownScenario.txt | 7 + .../Comments/DotNetCleanScenario.txt | 26 + .../Comments/DotNetCsiScenario.txt | 17 + .../Comments/DotNetCustomScenario.txt | 10 + .../Comments/DotNetExecScenario.txt | 19 + .../Comments/DotNetListPackageScenario.txt | 20 + .../Comments/DotNetListReferenceScenario.txt | 25 + .../Comments/DotNetMSBuildVSTestScenario.txt | 22 + .../Comments/DotNetPackScenario.txt | 17 + .../Comments/DotNetPublishScenario.txt | 18 + .../Comments/DotNetRemovePackageScenario.txt | 25 + .../DotNetRemoveReferenceScenario.txt | 30 ++ .../Comments/DotNetRestoreScenario.txt | 16 + .../Comments/DotNetRunScenario.txt | 23 + .../Comments/DotNetScenario.txt | 19 + .../Comments/DotNetTestScenario.txt | 22 + .../DotNetTestWithDotCoverScenario.txt | 51 ++ .../Comments/DotNetToolRestoreScenario.txt | 18 + .../Comments/DotNetVSTestScenario.txt | 31 ++ .../Comments/GetServiceScenario.txt | 4 + .../UsageScenarios/Comments/HostScenario.txt | 2 + .../Comments/LogErrorScenario.txt | 1 + .../Comments/LogInfoScenario.txt | 1 + .../Comments/LogTraceScenario.txt | 1 + .../Comments/LogWarningScenario.txt | 1 + .../Comments/MSBuildScenario.txt | 24 + .../Comments/NuGetRestoreAdvanced.txt | 13 + .../Comments/NuGetRestoreScenario.txt | 5 + .../UsageScenarios/Comments/PropsScenario.txt | 6 + .../Comments/ServiceCollectionScenario.txt | 20 + .../TeamCityServiceMessagesScenario.txt | 18 + .../Comments/WriteEmptyLineScenario.txt | 1 + .../Comments/WriteLineScenario.txt | 1 + .../Comments/WriteLineWithColourScenario.txt | 1 + .../DotNetAddPackageScenario.cs | 45 ++ .../DotNetAddReferenceScenario.cs | 50 ++ .../UsageScenarios/DotNetBuildScenario.cs | 23 +- .../UsageScenarios/DotNetExecScenario.cs | 44 ++ .../DotNetListPackageScenario.cs | 45 ++ .../DotNetListReferenceScenario.cs | 50 ++ .../DotNetRemovePackageScenario.cs | 50 ++ .../DotNetRemoveReferenceScenario.cs | 55 ++ .../UsageScenarios/DotNetScenario.cs | 44 ++ README.md | 417 ++++++++++---- 62 files changed, 2278 insertions(+), 292 deletions(-) create mode 100644 CSharpInteractive.Tests/UsageScenarios/Comments/ArgsScenario.txt create mode 100644 CSharpInteractive.Tests/UsageScenarios/Comments/CommandLineAsyncCancellation.txt create mode 100644 CSharpInteractive.Tests/UsageScenarios/Comments/CommandLineAsyncScenario.txt create mode 100644 CSharpInteractive.Tests/UsageScenarios/Comments/CommandLineInParallelScenario.txt create mode 100644 CSharpInteractive.Tests/UsageScenarios/Comments/CommandLineOutputScenario.txt create mode 100644 CSharpInteractive.Tests/UsageScenarios/Comments/CommandLineScenario.txt create mode 100644 CSharpInteractive.Tests/UsageScenarios/Comments/CommandLineWithTimeoutScenario.txt create mode 100644 CSharpInteractive.Tests/UsageScenarios/Comments/CommandLinesScenario.txt create mode 100644 CSharpInteractive.Tests/UsageScenarios/Comments/DockerDotNetBuildScenario.txt create mode 100644 CSharpInteractive.Tests/UsageScenarios/Comments/DockerRunScenario.txt create mode 100644 CSharpInteractive.Tests/UsageScenarios/Comments/DotNetAddPackageScenario.txt create mode 100644 CSharpInteractive.Tests/UsageScenarios/Comments/DotNetAddReferenceScenario.txt create mode 100644 CSharpInteractive.Tests/UsageScenarios/Comments/DotNetBuildScenario.txt create mode 100644 CSharpInteractive.Tests/UsageScenarios/Comments/DotNetBuildServerShutdownScenario.txt create mode 100644 CSharpInteractive.Tests/UsageScenarios/Comments/DotNetCleanScenario.txt create mode 100644 CSharpInteractive.Tests/UsageScenarios/Comments/DotNetCsiScenario.txt create mode 100644 CSharpInteractive.Tests/UsageScenarios/Comments/DotNetCustomScenario.txt create mode 100644 CSharpInteractive.Tests/UsageScenarios/Comments/DotNetExecScenario.txt create mode 100644 CSharpInteractive.Tests/UsageScenarios/Comments/DotNetListPackageScenario.txt create mode 100644 CSharpInteractive.Tests/UsageScenarios/Comments/DotNetListReferenceScenario.txt create mode 100644 CSharpInteractive.Tests/UsageScenarios/Comments/DotNetMSBuildVSTestScenario.txt create mode 100644 CSharpInteractive.Tests/UsageScenarios/Comments/DotNetPackScenario.txt create mode 100644 CSharpInteractive.Tests/UsageScenarios/Comments/DotNetPublishScenario.txt create mode 100644 CSharpInteractive.Tests/UsageScenarios/Comments/DotNetRemovePackageScenario.txt create mode 100644 CSharpInteractive.Tests/UsageScenarios/Comments/DotNetRemoveReferenceScenario.txt create mode 100644 CSharpInteractive.Tests/UsageScenarios/Comments/DotNetRestoreScenario.txt create mode 100644 CSharpInteractive.Tests/UsageScenarios/Comments/DotNetRunScenario.txt create mode 100644 CSharpInteractive.Tests/UsageScenarios/Comments/DotNetScenario.txt create mode 100644 CSharpInteractive.Tests/UsageScenarios/Comments/DotNetTestScenario.txt create mode 100644 CSharpInteractive.Tests/UsageScenarios/Comments/DotNetTestWithDotCoverScenario.txt create mode 100644 CSharpInteractive.Tests/UsageScenarios/Comments/DotNetToolRestoreScenario.txt create mode 100644 CSharpInteractive.Tests/UsageScenarios/Comments/DotNetVSTestScenario.txt create mode 100644 CSharpInteractive.Tests/UsageScenarios/Comments/GetServiceScenario.txt create mode 100644 CSharpInteractive.Tests/UsageScenarios/Comments/HostScenario.txt create mode 100644 CSharpInteractive.Tests/UsageScenarios/Comments/LogErrorScenario.txt create mode 100644 CSharpInteractive.Tests/UsageScenarios/Comments/LogInfoScenario.txt create mode 100644 CSharpInteractive.Tests/UsageScenarios/Comments/LogTraceScenario.txt create mode 100644 CSharpInteractive.Tests/UsageScenarios/Comments/LogWarningScenario.txt create mode 100644 CSharpInteractive.Tests/UsageScenarios/Comments/MSBuildScenario.txt create mode 100644 CSharpInteractive.Tests/UsageScenarios/Comments/NuGetRestoreAdvanced.txt create mode 100644 CSharpInteractive.Tests/UsageScenarios/Comments/NuGetRestoreScenario.txt create mode 100644 CSharpInteractive.Tests/UsageScenarios/Comments/PropsScenario.txt create mode 100644 CSharpInteractive.Tests/UsageScenarios/Comments/ServiceCollectionScenario.txt create mode 100644 CSharpInteractive.Tests/UsageScenarios/Comments/TeamCityServiceMessagesScenario.txt create mode 100644 CSharpInteractive.Tests/UsageScenarios/Comments/WriteEmptyLineScenario.txt create mode 100644 CSharpInteractive.Tests/UsageScenarios/Comments/WriteLineScenario.txt create mode 100644 CSharpInteractive.Tests/UsageScenarios/Comments/WriteLineWithColourScenario.txt create mode 100644 CSharpInteractive.Tests/UsageScenarios/DotNetAddPackageScenario.cs create mode 100644 CSharpInteractive.Tests/UsageScenarios/DotNetAddReferenceScenario.cs create mode 100644 CSharpInteractive.Tests/UsageScenarios/DotNetExecScenario.cs create mode 100644 CSharpInteractive.Tests/UsageScenarios/DotNetListPackageScenario.cs create mode 100644 CSharpInteractive.Tests/UsageScenarios/DotNetListReferenceScenario.cs create mode 100644 CSharpInteractive.Tests/UsageScenarios/DotNetRemovePackageScenario.cs create mode 100644 CSharpInteractive.Tests/UsageScenarios/DotNetRemoveReferenceScenario.cs create mode 100644 CSharpInteractive.Tests/UsageScenarios/DotNetScenario.cs diff --git a/CSharpInteractive.HostApi/DotNetCommands.cs b/CSharpInteractive.HostApi/DotNetCommands.cs index a96b89a..e719f48 100644 --- a/CSharpInteractive.HostApi/DotNetCommands.cs +++ b/CSharpInteractive.HostApi/DotNetCommands.cs @@ -10,6 +10,29 @@ namespace HostApi; /// You specify the path to an application .dll file to run the application. To run the application means to find and execute the entry point, which in the case of console apps is the Main method. For example, dotnet myapp.dll runs the myapp application. ///

///
.NET CLI command
+/// +/// +/// // Adds the namespace "HostApi" to use .NET build API +/// using HostApi; +/// +/// // Creates a new console project, running a command like: "dotnet new console -n MyApp --force" +/// new DotNetNew() +/// .WithTemplateName("console") +/// .WithName("MyApp") +/// .WithForce(true) +/// .Build().EnsureSuccess(); +/// +/// var tempDirectory = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); +/// new DotNetPublish() +/// .WithWorkingDirectory("MyApp") +/// .WithOutput(tempDirectory) +/// .Build().EnsureSuccess(); +/// +/// new DotNet() +/// .WithPathToApplication(Path.Combine(tempDirectory, "MyApp.dll")) +/// .Run().EnsureSuccess(); +/// +/// /// /// Specifies the set of command line arguments to use when starting the tool. /// Specifies the set of environment variables that apply to this process and its child processes. @@ -94,6 +117,29 @@ public IStartInfo GetStartInfo(IHost host) /// You specify the path to an application .dll file to run the application. To run the application means to find and execute the entry point, which in the case of console apps is the Main method. For example, dotnet myapp.dll runs the myapp application. ///

///
.NET CLI command
+/// +/// +/// // Adds the namespace "HostApi" to use .NET build API +/// using HostApi; +/// +/// // Creates a new console project, running a command like: "dotnet new console -n MyApp --force" +/// new DotNetNew() +/// .WithTemplateName("console") +/// .WithName("MyApp") +/// .WithForce(true) +/// .Build().EnsureSuccess(); +/// +/// var tempDirectory = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); +/// new DotNetPublish() +/// .WithWorkingDirectory("MyApp") +/// .WithOutput(tempDirectory) +/// .Build().EnsureSuccess(); +/// +/// new DotNetExec() +/// .WithPathToApplication(Path.Combine(tempDirectory, "MyApp.dll")) +/// .Run().EnsureSuccess(); +/// +/// /// /// Specifies the set of command line arguments to use when starting the tool. /// Specifies the set of environment variables that apply to this process and its child processes. @@ -173,6 +219,30 @@ public IStartInfo GetStartInfo(IHost host) /// This command provides a convenient option to add or update a package reference in a project file. When you run the command, there's a compatibility check to ensure the package is compatible with the frameworks in the project. If the check passes and the package isn't referenced in the project file, a <PackageReference> element is added to the project file. If the check passes and the package is already referenced in the project file, the <PackageReference> element is updated to the latest compatible version. After the project file is updated, dotnet restore is run. ///

///
.NET CLI command
+/// +/// +/// using HostApi; +/// +/// new DotNetNew() +/// .WithTemplateName("classlib") +/// .WithName("MyLib") +/// .WithForce(true) +/// .Build().EnsureSuccess(); +/// +/// var result = new DotNetAddPackage() +/// .WithWorkingDirectory("MyLib") +/// .WithPackage("Pure.DI") +/// .Run().EnsureSuccess(); +/// +/// var lines = new List<string>(); +/// new DotNetListPackage() +/// .WithWorkingDirectory("MyLib") +/// .WithVerbosity(DotNetVerbosity.Minimal) +/// .Run(output => lines.Add(output.Line)); +/// +/// lines.Any(i => i.Contains("Pure.DI")).ShouldBeTrue(result.ToString()); +/// +/// /// /// Specifies the set of command line arguments to use when starting the tool. /// Specifies the set of environment variables that apply to this process and its child processes. @@ -180,7 +250,7 @@ public IStartInfo GetStartInfo(IHost host) /// Overrides the tool executable path. /// Specifies the working directory for the tool to be started. /// The project or solution file to operate on. If not specified, the command searches the current directory for one. If more than one solution or project is found, an error is thrown. -/// The package reference to add. +/// The package reference to add. /// Adds a package reference only when targeting a specific framework. /// Doesn't execute an implicit restore when running the command. /// The directory where to restore the packages. The default package restore location is %userprofile%\.nuget\packages on Windows and ~/.nuget/packages on macOS and Linux. @@ -194,7 +264,7 @@ public partial record DotNetAddPackage( IEnumerable<(string name, string value)> Vars, IEnumerable Sources, string Project = "", - string PackageName = "", + string Package = "", string Framework = "", bool? NoRestore = default, string PackageDirectory = "", @@ -233,7 +303,7 @@ public IStartInfo GetStartInfo(IHost host) .AddArgs("add") .AddNotEmptyArgs(Project.ToArg()) .AddArgs("package") - .AddNotEmptyArgs(PackageName.ToArg()) + .AddNotEmptyArgs(Package.ToArg()) .AddArgs(Sources.ToArgs("--source", "")) .AddArgs(Framework.ToArgs("--framework", "")) .AddArgs(PackageDirectory.ToArgs("--package-directory", "")) @@ -247,7 +317,7 @@ public IStartInfo GetStartInfo(IHost host) } /// - public override string ToString() => (ExecutablePath == string.Empty ? "dotnet" : Path.GetFileNameWithoutExtension(ExecutablePath)).GetShortName("Adds or updates a package reference in a project file.", ShortName, "add", Project.ToArg(), "package", PackageName.ToArg()); + public override string ToString() => (ExecutablePath == string.Empty ? "dotnet" : Path.GetFileNameWithoutExtension(ExecutablePath)).GetShortName("Adds or updates a package reference in a project file.", ShortName, "add", Project.ToArg(), "package", Package.ToArg()); } /// @@ -256,6 +326,30 @@ public IStartInfo GetStartInfo(IHost host) /// This command provides a convenient option to list all NuGet package references for a specific project or a solution. You first need to build the project in order to have the assets needed for this command to process. ///

///
.NET CLI command
+/// +/// +/// using HostApi; +/// +/// new DotNetNew() +/// .WithTemplateName("classlib") +/// .WithName("MyLib") +/// .WithForce(true) +/// .Build().EnsureSuccess(); +/// +/// new DotNetAddPackage() +/// .WithWorkingDirectory("MyLib") +/// .WithPackage("Pure.DI") +/// .Run().EnsureSuccess(); +/// +/// var lines = new List<string>(); +/// var result = new DotNetListPackage() +/// .WithWorkingDirectory("MyLib") +/// .WithVerbosity(DotNetVerbosity.Minimal) +/// .Run(output => lines.Add(output.Line)); +/// +/// lines.Any(i => i.Contains("Pure.DI")).ShouldBeTrue(result.ToString()); +/// +/// ///
/// Specifies the set of command line arguments to use when starting the tool. /// Specifies the set of environment variables that apply to this process and its child processes. @@ -348,13 +442,42 @@ public IStartInfo GetStartInfo(IHost host) /// This command provides a convenient option to remove a NuGet package reference from a project. ///

///
.NET CLI command
+/// +/// +/// using HostApi; +/// +/// new DotNetNew() +/// .WithTemplateName("classlib") +/// .WithName("MyLib") +/// .WithForce(true) +/// .Build().EnsureSuccess(); +/// +/// new DotNetAddPackage() +/// .WithWorkingDirectory("MyLib") +/// .WithPackage("Pure.DI") +/// .Run().EnsureSuccess(); +/// +/// var result = new DotNetRemovePackage() +/// .WithWorkingDirectory("MyLib") +/// .WithPackage("Pure.DI") +/// .Run().EnsureSuccess(); +/// +/// var lines = new List<string>(); +/// new DotNetListPackage() +/// .WithWorkingDirectory("MyLib") +/// .WithVerbosity(DotNetVerbosity.Minimal) +/// .Run(output => lines.Add(output.Line)); +/// +/// lines.Any(i => i.Contains("Pure.DI")).ShouldBeFalse(result.ToString()); +/// +/// /// /// Specifies the set of command line arguments to use when starting the tool. /// Specifies the set of environment variables that apply to this process and its child processes. /// Overrides the tool executable path. /// Specifies the working directory for the tool to be started. /// The project or solution file to operate on. If not specified, the command searches the current directory for one. If more than one solution or project is found, an error is thrown. -/// The package reference to add. +/// The package reference to add. /// Enables diagnostic output. /// Specifies a short name for this operation. [Target] @@ -362,7 +485,7 @@ public partial record DotNetRemovePackage( IEnumerable Args, IEnumerable<(string name, string value)> Vars, string Project = "", - string PackageName = "", + string Package = "", bool? Diagnostics = default, string ExecutablePath = "", string WorkingDirectory = "", @@ -396,7 +519,7 @@ public IStartInfo GetStartInfo(IHost host) .AddArgs("remove") .AddNotEmptyArgs(Project.ToArg()) .AddArgs("package") - .AddNotEmptyArgs(PackageName.ToArg()) + .AddNotEmptyArgs(Package.ToArg()) .AddBooleanArgs( ("--diagnostics", Diagnostics) ) @@ -404,7 +527,7 @@ public IStartInfo GetStartInfo(IHost host) } /// - public override string ToString() => (ExecutablePath == string.Empty ? "dotnet" : Path.GetFileNameWithoutExtension(ExecutablePath)).GetShortName("Removes package reference from a project file.", ShortName, "remove", Project.ToArg(), "package", PackageName.ToArg()); + public override string ToString() => (ExecutablePath == string.Empty ? "dotnet" : Path.GetFileNameWithoutExtension(ExecutablePath)).GetShortName("Removes package reference from a project file.", ShortName, "remove", Project.ToArg(), "package", Package.ToArg()); } /// @@ -413,6 +536,35 @@ public IStartInfo GetStartInfo(IHost host) /// This command provides a convenient option to add project references to a project. After running the command, the <ProjectReference> elements are added to the project file. ///

///
.NET CLI command
+/// +/// +/// using HostApi; +/// +/// new DotNetNew() +/// .WithTemplateName("classlib") +/// .WithName("MyLib") +/// .WithForce(true) +/// .Build().EnsureSuccess(); +/// +/// new DotNetNew() +/// .WithTemplateName("xunit") +/// .WithName("MyTests") +/// .WithForce(true) +/// .Build().EnsureSuccess(); +/// +/// var result = new DotNetAddReference() +/// .WithProject(Path.Combine("MyTests", "MyTests.csproj")) +/// .WithReferences(Path.Combine("MyLib", "MyLib.csproj")) +/// .Run().EnsureSuccess(); +/// +/// var lines = new List<string>(); +/// new DotNetListReference() +/// .WithProject(Path.Combine("MyTests", "MyTests.csproj")) +/// .Run(output => lines.Add(output.Line)); +/// +/// lines.Any(i => i.Contains("MyLib.csproj")).ShouldBeTrue(result.ToString()); +/// +/// ///
/// Specifies the set of command line arguments to use when starting the tool. /// Specifies the set of environment variables that apply to this process and its child processes. @@ -463,8 +615,7 @@ public IStartInfo GetStartInfo(IHost host) .AddArgs("add") .AddNotEmptyArgs(Project.ToArg()) .AddArgs("reference") - .AddNotEmptyArgs(References.ToArray().ToArg()) - .AddArgs(References.ToArgs("--source", "")) + .AddNotEmptyArgs(References.ToArray()) .AddArgs(Framework.ToArgs("--framework", "")) .AddBooleanArgs( ("--diagnostics", Diagnostics) @@ -482,6 +633,35 @@ public IStartInfo GetStartInfo(IHost host) /// This command provides a convenient option to list project references for a given project. ///

///
.NET CLI command
+/// +/// +/// using HostApi; +/// +/// new DotNetNew() +/// .WithTemplateName("classlib") +/// .WithName("MyLib") +/// .WithForce(true) +/// .Build().EnsureSuccess(); +/// +/// new DotNetNew() +/// .WithTemplateName("xunit") +/// .WithName("MyTests") +/// .WithForce(true) +/// .Build().EnsureSuccess(); +/// +/// new DotNetAddReference() +/// .WithProject(Path.Combine("MyTests", "MyTests.csproj")) +/// .WithReferences(Path.Combine("MyLib", "MyLib.csproj")) +/// .Run().EnsureSuccess(); +/// +/// var lines = new List<string>(); +/// var result = new DotNetListReference() +/// .WithProject(Path.Combine("MyTests", "MyTests.csproj")) +/// .Run(output => lines.Add(output.Line)); +/// +/// lines.Any(i => i.Contains("MyLib.csproj")).ShouldBeTrue(result.ToString()); +/// +/// /// /// Specifies the set of command line arguments to use when starting the tool. /// Specifies the set of environment variables that apply to this process and its child processes. @@ -527,6 +707,7 @@ public IStartInfo GetStartInfo(IHost host) .WithVars(Vars.ToArray()) .AddArgs("list") .AddNotEmptyArgs(Project.ToArg()) + .AddArgs("reference") .AddBooleanArgs( ("--diagnostics", Diagnostics) ) @@ -534,7 +715,7 @@ public IStartInfo GetStartInfo(IHost host) } /// - public override string ToString() => (ExecutablePath == string.Empty ? "dotnet" : Path.GetFileNameWithoutExtension(ExecutablePath)).GetShortName("Lists project-to-project references.", ShortName, "list", Project.ToArg()); + public override string ToString() => (ExecutablePath == string.Empty ? "dotnet" : Path.GetFileNameWithoutExtension(ExecutablePath)).GetShortName("Lists project-to-project references.", ShortName, "list", Project.ToArg(), "reference"); } /// @@ -543,6 +724,40 @@ public IStartInfo GetStartInfo(IHost host) /// This command provides a convenient option to remove project references from a project. ///

///
.NET CLI command
+/// +/// +/// using HostApi; +/// +/// new DotNetNew() +/// .WithTemplateName("classlib") +/// .WithName("MyLib") +/// .WithForce(true) +/// .Build().EnsureSuccess(); +/// +/// new DotNetNew() +/// .WithTemplateName("xunit") +/// .WithName("MyTests") +/// .WithForce(true) +/// .Build().EnsureSuccess(); +/// +/// new DotNetAddReference() +/// .WithProject(Path.Combine("MyTests", "MyTests.csproj")) +/// .WithReferences(Path.Combine("MyLib", "MyLib.csproj")) +/// .Run().EnsureSuccess(); +/// +/// var result = new DotNetRemoveReference() +/// .WithProject(Path.Combine("MyTests", "MyTests.csproj")) +/// .WithReferences(Path.Combine("MyLib", "MyLib.csproj")) +/// .Run().EnsureSuccess(); +/// +/// var lines = new List<string>(); +/// new DotNetListReference() +/// .WithProject(Path.Combine("MyTests", "MyTests.csproj")) +/// .Run(output => lines.Add(output.Line)); +/// +/// lines.Any(i => i.Contains("MyLib.csproj")).ShouldBeFalse(result.ToString()); +/// +/// ///
/// Specifies the set of command line arguments to use when starting the tool. /// Specifies the set of environment variables that apply to this process and its child processes. @@ -593,8 +808,7 @@ public IStartInfo GetStartInfo(IHost host) .AddArgs("remove") .AddNotEmptyArgs(Project.ToArg()) .AddArgs("reference") - .AddNotEmptyArgs(References.ToArray().ToArg()) - .AddArgs(References.ToArgs("--source", "")) + .AddNotEmptyArgs(References.ToArray()) .AddArgs(Framework.ToArgs("--framework", "")) .AddBooleanArgs( ("--diagnostics", Diagnostics) @@ -614,16 +828,36 @@ public IStartInfo GetStartInfo(IHost host) ///

/// For executable projects targeting .NET Core 3.0 and later, library dependencies are copied to the output folder. This means that if there isn't any other publish-specific logic (such as Web projects have), the build output should be deployable. ///

+///
.NET CLI command
/// -/// -/// var configuration = Props.Get("configuration", "Release"); +/// +/// // Adds the namespace "HostApi" to use .NET build API +/// using HostApi; +/// +/// // Creates a new test project, running a command like: "dotnet new xunit -n MyTests --force" +/// new DotNetNew() +/// .WithTemplateName("xunit") +/// .WithName("MyTests") +/// .WithForce(true) +/// .Build().EnsureSuccess(); +/// +/// // Builds this project, running a command like: "dotnet build" from the directory "MyLib" +/// var messages = new List<BuildMessage>(); +/// var result = new DotNetBuild() +/// .WithWorkingDirectory("MyTests") +/// .Build(message => messages.Add(message)).EnsureSuccess(); /// +/// // The "result" variable provides details about a build +/// messages.Count.ShouldBeGreaterThan(0, result.ToString()); +/// result.Errors.Any(message => message.State == BuildMessageState.StdError).ShouldBeFalse(result.ToString()); +/// result.ExitCode.ShouldBe(0, result.ToString()); /// -/// new DotNetBuild().WithConfiguration(configuration) +/// // Runs tests in docker +/// result = new DotNetTest() +/// .WithWorkingDirectory("MyTests") /// .Build().EnsureSuccess(); -/// +/// /// -///
.NET CLI command
/// /// Specifies the set of command line arguments to use when starting the tool. /// Specifies the set of environment variables that apply to this process and its child processes. @@ -749,6 +983,17 @@ public IStartInfo GetStartInfo(IHost host) /// By default, all servers are shut down. ///

///
.NET CLI command
+/// +/// +/// // Adds the namespace "HostApi" to use .NET build API +/// using HostApi; +/// +/// // Shuts down all build servers that are started from dotnet. +/// new DotNetBuildServerShutdown() +/// .Run() +/// .EnsureSuccess(); +/// +/// /// /// Specifies the set of command line arguments to use when starting the tool. /// Specifies the set of environment variables that apply to this process and its child processes. @@ -811,6 +1056,36 @@ public IStartInfo GetStartInfo(IHost host) /// This command cleans the output of the previous build. It's implemented as an MSBuild target, so the project is evaluated when the command is run. Only the outputs created during the build are cleaned. Both intermediate (obj) and final output (bin) folders are cleaned. ///

///
.NET CLI command
+/// +/// +/// // Adds the namespace "HostApi" to use .NET build API +/// using HostApi; +/// +/// // Creates a new library project, running a command like: "dotnet new classlib -n MyLib --force" +/// var result = new DotNetNew() +/// .WithTemplateName("classlib") +/// .WithName("MyLib") +/// .WithForce(true) +/// .Build().EnsureSuccess(); +/// +/// result.ExitCode.ShouldBe(0); +/// +/// // Builds the library project, running a command like: "dotnet build" from the directory "MyLib" +/// result = new DotNetBuild() +/// .WithWorkingDirectory("MyLib") +/// .Build().EnsureSuccess(); +/// +/// result.ExitCode.ShouldBe(0); +/// +/// // Clean the project, running a command like: "dotnet clean" from the directory "MyLib" +/// result = new DotNetClean() +/// .WithWorkingDirectory("MyLib") +/// .Build().EnsureSuccess(); +/// +/// // The "result" variable provides details about a build +/// result.ExitCode.ShouldBe(0); +/// +/// /// /// Specifies the set of command line arguments to use when starting the tool. /// Specifies the set of environment variables that apply to this process and its child processes. @@ -993,15 +1268,6 @@ public IStartInfo GetStartInfo(IHost host) ///

/// This command creates a .NET project or other artifacts based on a template. The command calls the template engine to create the artifacts on disk based on the specified template and options. ///

-/// -/// -/// new DotNetNew() -/// .WithTemplateName("console") -/// .WithName("MyApp") -/// .WithForce(true) -/// .Run().EnsureSuccess(); -/// -/// ///
.NET CLI command
/// /// Specifies the set of command line arguments to use when starting the tool. @@ -1555,7 +1821,7 @@ public IStartInfo GetStartInfo(IHost host) /// Specifies the set of environment variables that apply to this process and its child processes. /// Overrides the tool executable path. /// Specifies the working directory for the tool to be started. -/// Name/ID of the package to delete. +/// Name/ID of the package to delete. /// Version of the package to delete. /// Forces the application to run using an invariant, English-based culture. /// The API key for the server. @@ -1567,7 +1833,7 @@ public IStartInfo GetStartInfo(IHost host) public partial record DotNetNuGetDelete( IEnumerable Args, IEnumerable<(string name, string value)> Vars, - string PackageName = "", + string Package = "", string PackageVersion = "", bool? ForceEnglishOutput = default, string ApiKey = "", @@ -1605,7 +1871,7 @@ public IStartInfo GetStartInfo(IHost host) .WithVars(Vars.ToArray()) .AddArgs("nuget") .AddArgs("delete") - .AddNotEmptyArgs(PackageName.ToArg()) + .AddNotEmptyArgs(Package.ToArg()) .AddNotEmptyArgs(PackageVersion.ToArg()) .AddArgs("--non-interactive") .AddArgs(ApiKey.ToArgs("--api-key", "")) @@ -1619,7 +1885,7 @@ public IStartInfo GetStartInfo(IHost host) } /// - public override string ToString() => (ExecutablePath == string.Empty ? "dotnet" : Path.GetFileNameWithoutExtension(ExecutablePath)).GetShortName("Deletes or unlists a package from the server.", ShortName, "nuget", "delete", PackageName.ToArg(), PackageVersion.ToArg()); + public override string ToString() => (ExecutablePath == string.Empty ? "dotnet" : Path.GetFileNameWithoutExtension(ExecutablePath)).GetShortName("Deletes or unlists a package from the server.", ShortName, "nuget", "delete", Package.ToArg(), PackageVersion.ToArg()); } /// @@ -2337,7 +2603,7 @@ public IStartInfo GetStartInfo(IHost host) .WithVars(Vars.ToArray()) .AddArgs("nuget") .AddArgs("verify") - .AddNotEmptyArgs(Packages.ToArray().ToArg()) + .AddNotEmptyArgs(Packages.ToArray()) .AddArgs(Packages.ToArgs("", "")) .AddArgs(Fingerprints.ToArgs("--certificate-fingerprint", "")) .AddArgs(ConfigFile.ToArgs("--configfile", "")) @@ -2920,7 +3186,7 @@ public IStartInfo GetStartInfo(IHost host) .WithVars(Vars.ToArray()) .AddArgs("nuget") .AddArgs("sign") - .AddNotEmptyArgs(Packages.ToArray().ToArg()) + .AddNotEmptyArgs(Packages.ToArray()) .AddArgs(CertificatePath.ToArgs("--certificate-path", "")) .AddArgs(CertificateStoreName.ToArgs("--certificate-store-name", "")) .AddArgs(CertificateStoreLocation.ToArgs("--certificate-store-location", "")) @@ -3289,13 +3555,28 @@ public IStartInfo GetStartInfo(IHost host) ///

/// By default, dotnet pack builds the project first. If you wish to avoid this behavior, pass the --no-build option. This option is often useful in Continuous Integration (CI) build scenarios where you know the code was previously built. ///

+///
.NET CLI command
/// -/// -/// new DotNetPack() +/// +/// // Adds the namespace "HostApi" to use .NET build API +/// using HostApi; +/// +/// // Creates a new library project, running a command like: "dotnet new classlib -n MyLib --force" +/// var result = new DotNetNew() +/// .WithTemplateName("classlib") +/// .WithName("MyLib") +/// .WithForce(true) /// .Build().EnsureSuccess(); -/// +/// +/// result.ExitCode.ShouldBe(0); +/// +/// // Creates a NuGet package of version 1.2.3 for the project, running a command like: "dotnet pack /p:version=1.2.3" from the directory "MyLib" +/// result = new DotNetPack() +/// .WithWorkingDirectory("MyLib") +/// .AddProps(("version", "1.2.3")) +/// .Build().EnsureSuccess(); +/// /// -///
.NET CLI command
///
/// Specifies the set of command line arguments to use when starting the tool. /// Specifies the set of environment variables that apply to this process and its child processes. @@ -3507,13 +3788,29 @@ public IStartInfo GetStartInfo(IHost host) ///

/// This command compiles the application, reads through its dependencies specified in the project file, and publishes the resulting set of files to a directory. ///

+///
.NET CLI command
/// -/// -/// new DotNetPublish().AddProps(("PublishDir", ".publish")) +/// +/// // Adds the namespace "HostApi" to use .NET build API +/// using HostApi; +/// +/// // Creates a new library project, running a command like: "dotnet new classlib -n MyLib --force" +/// var result = new DotNetNew() +/// .WithTemplateName("classlib") +/// .AddArgs("-f", "net8.0") +/// .WithName("MyLib") +/// .WithForce(true) +/// .Build().EnsureSuccess(); +/// +/// result.ExitCode.ShouldBe(0); +/// +/// // Publish the project, running a command like: "dotnet publish --framework net6.0" from the directory "MyLib" +/// result = new DotNetPublish() +/// .WithWorkingDirectory("MyLib") +/// .WithFramework("net8.0") /// .Build().EnsureSuccess(); -/// +/// /// -///
.NET CLI command
/// /// Specifies the set of command line arguments to use when starting the tool. /// Specifies the set of environment variables that apply to this process and its child processes. @@ -3644,13 +3941,27 @@ public IStartInfo GetStartInfo(IHost host) ///

/// Sometimes, it might be inconvenient to run the implicit NuGet restore with these commands. For example, some automated systems, such as build systems, need to call dotnet restore explicitly to control when the restore occurs so that they can control network usage. To prevent the implicit NuGet restore, you can use the --no-restore flag with any of these commands. ///

+///
.NET CLI command
/// -/// -/// new DotNetRestore() +/// +/// // Adds the namespace "HostApi" to use .NET build API +/// using HostApi; +/// +/// // Creates a new library project, running a command like: "dotnet new classlib -n MyLib --force" +/// var result = new DotNetNew() +/// .WithTemplateName("classlib") +/// .WithName("MyLib") +/// .WithForce(true) +/// .Build().EnsureSuccess(); +/// +/// result.ExitCode.ShouldBe(0); +/// +/// // Restore the project, running a command like: "dotnet restore" from the directory "MyLib" +/// result = new DotNetRestore() +/// .WithWorkingDirectory("MyLib") /// .Build().EnsureSuccess(); -/// +/// /// -///
.NET CLI command
/// /// Specifies the set of command line arguments to use when starting the tool. /// Specifies the set of environment variables that apply to this process and its child processes. @@ -3772,20 +4083,34 @@ public IStartInfo GetStartInfo(IHost host) ///

/// To run the application, the dotnet run command resolves the dependencies of the application that are outside of the shared runtime from the NuGet cache. Because it uses cached dependencies, it's not recommended to use dotnet run to run applications in production. Instead, create a deployment using the dotnet publish command and deploy the published output. ///

+///
.NET CLI command
/// -/// -/// new DotNetNew() +/// +/// // Adds the namespace "HostApi" to use .NET build API +/// using HostApi; +/// +/// // Creates a new console project, running a command like: "dotnet new console -n MyApp --force" +/// var result = new DotNetNew() /// .WithTemplateName("console") /// .WithName("MyApp") /// .WithForce(true) -/// .Run().EnsureSuccess(); +/// .Build().EnsureSuccess(); /// +/// result.ExitCode.ShouldBe(0); /// -/// new DotNetRun().WithWorkingDirectory("MyApp") -/// .Build().EnsureSuccess(); -/// +/// // Runs the console project using a command like: "dotnet run" from the directory "MyApp" +/// var stdOut = new List<string>(); +/// result = new DotNetRun() +/// .WithWorkingDirectory("MyApp") +/// .Build(message => stdOut.Add(message.Text)) +/// .EnsureSuccess(); +/// +/// result.ExitCode.ShouldBe(0); +/// +/// // Checks StdOut +/// stdOut.ShouldBe(new[] {"Hello, World!"}); +/// /// -///
.NET CLI command
/// /// Specifies the set of command line arguments to use when starting the tool. /// Specifies the set of environment variables that apply to this process and its child processes. @@ -4056,7 +4381,7 @@ public IStartInfo GetStartInfo(IHost host) .AddArgs("sln") .AddNotEmptyArgs(Solution.ToArg()) .AddArgs("add") - .AddNotEmptyArgs(Projects.ToArray().ToArg()) + .AddNotEmptyArgs(Projects.ToArray()) .AddArgs(SolutionFolder.ToArgs("--solution-folder", "")) .AddBooleanArgs( ("--in-root", InRoot), @@ -4120,7 +4445,7 @@ public IStartInfo GetStartInfo(IHost host) .AddArgs("sln") .AddNotEmptyArgs(Solution.ToArg()) .AddArgs("remove") - .AddNotEmptyArgs(Projects.ToArray().ToArg()) + .AddNotEmptyArgs(Projects.ToArray()) .AddBooleanArgs( ("--diagnostics", Diagnostics) ) @@ -4224,20 +4549,33 @@ public IStartInfo GetStartInfo(IHost host) ///

/// For multi-targeted projects, tests are run for each targeted framework. The test host and the unit test framework are packaged as NuGet packages and are restored as ordinary dependencies for the project. Starting with the .NET 9 SDK, these tests are run in parallel by default. To disable parallel execution, set the TestTfmsInParallel MSBuild property to false. ///

+///
.NET CLI command
/// -/// -/// new DotNetNew() +/// +/// // Adds the namespace "HostApi" to use .NET build API +/// using HostApi; +/// +/// // Creates a new test project, running a command like: "dotnet new mstest -n MyTests --force" +/// var result = new DotNetNew() /// .WithTemplateName("mstest") /// .WithName("MyTests") /// .WithForce(true) -/// .Run().EnsureSuccess(); +/// .Build().EnsureSuccess(); /// +/// result.ExitCode.ShouldBe(0); /// -/// new DotNetTest().WithWorkingDirectory("MyTests") -/// .Build().EnsureSuccess(); -/// +/// // Runs tests via a command like: "dotnet test" from the directory "MyTests" +/// result = new DotNetTest() +/// .WithWorkingDirectory("MyTests") +/// .Build() +/// .EnsureSuccess(); +/// +/// // The "result" variable provides details about a build +/// result.ExitCode.ShouldBe(0, result.ToString()); +/// result.Summary.Tests.ShouldBe(1, result.ToString()); +/// result.Tests.Count(test => test.State == TestState.Finished).ShouldBe(1, result.ToString()); +/// /// -///
.NET CLI command
/// /// Specifies the set of command line arguments to use when starting the tool. /// Specifies the set of environment variables that apply to this process and its child processes. @@ -4569,6 +4907,28 @@ public IStartInfo GetStartInfo(IHost host) /// This command finds the tool manifest file that is in scope for the current directory and installs the tools that are listed in it. For information about manifest files, see Install a local tool and Invoke a local tool. ///

///
.NET CLI command
+/// +/// +/// // Adds the namespace "HostApi" to use .NET build API +/// using HostApi; +/// +/// var projectDir = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString()[..4]); +/// Directory.CreateDirectory(projectDir); +/// +/// // Creates a local tool manifest +/// new DotNetNew() +/// .WithTemplateName("tool-manifest") +/// .WithWorkingDirectory(projectDir) +/// .Run() +/// .EnsureSuccess(); +/// +/// // Restore local tools +/// new DotNetToolRestore() +/// .WithWorkingDirectory(projectDir) +/// .Run() +/// .EnsureSuccess(); +/// +/// /// /// Specifies the set of command line arguments to use when starting the tool. /// Specifies the set of environment variables that apply to this process and its child processes. @@ -5151,7 +5511,7 @@ public IStartInfo GetStartInfo(IHost host) .AddArgs("tool") .AddArgs("workload") .AddArgs("install") - .AddNotEmptyArgs(Workloads.ToArray().ToArg()) + .AddNotEmptyArgs(Workloads.ToArray()) .AddArgs(Sources.ToArgs("--source", "")) .AddArgs(ConfigFile.ToArgs("--configfile", "")) .AddArgs(TempDir.ToArgs("--temp-dir", "")) @@ -5529,7 +5889,7 @@ public IStartInfo GetStartInfo(IHost host) .AddArgs("tool") .AddArgs("workload") .AddArgs("uninstall") - .AddNotEmptyArgs(Workloads.ToArray().ToArg()) + .AddNotEmptyArgs(Workloads.ToArray()) .AddBooleanArgs( ("--diagnostics", Diagnostics) ) @@ -5636,6 +5996,27 @@ public IStartInfo GetStartInfo(IHost host) /// /// Runs a C# script. ///
C# interactive
+/// +/// +/// // Adds the namespace "HostApi" to use .NET build API +/// using HostApi; +/// +/// var script = Path.GetTempFileName(); +/// File.WriteAllText(script, "Console.WriteLine($\"Hello, {Args[0]}!\");"); +/// +/// var stdOut = new List<string>(); +/// var result = new DotNetCsi() +/// .WithScript(script) +/// .AddArgs("World") +/// .Build(message => stdOut.Add(message.Text)) +/// .EnsureSuccess(); +/// +/// result.ExitCode.ShouldBe(0); +/// +/// // Checks StdOut +/// stdOut.Contains("Hello, World!").ShouldBeTrue(result.ToString()); +/// +/// ///
/// Specifies the set of command line arguments to use when starting the tool. /// Specifies the set of environment variables that apply to this process and its child processes. diff --git a/CSharpInteractive.HostApi/DotNetCommands.tt b/CSharpInteractive.HostApi/DotNetCommands.tt index b527e0a..bd0ab91 100644 --- a/CSharpInteractive.HostApi/DotNetCommands.tt +++ b/CSharpInteractive.HostApi/DotNetCommands.tt @@ -1,7 +1,7 @@ <#@ import namespace="System.Linq" #> -<#@ import namespace="System.Linq" #> -<#@ import namespace="System.Linq" #> <#@ import namespace="System.Collections.Generic" #> +<#@ import namespace="System.IO" #> +<#@ import namespace="System.Xml" #> // ReSharper disable UnusedMember.Global // ReSharper disable InconsistentNaming namespace HostApi; @@ -17,7 +17,7 @@ using Internal; string CreateCliRef(string command) => $"
.NET CLI command
"; - + var projectArg = new Arg("Project", "", "string", "The project or solution file to operate on. If not specified, the command searches the current directory for one. If more than one solution or project is found, an error is thrown.") { IsProject = true }; var solutionArg = new Arg("Solution", "", "string", "The solution file to use. If this argument is omitted, the command searches the current directory for one. If it finds no solution file or multiple solution files, the command fails.") { IsProject = true }; var propsArg = new Arg("Props", "--property", "IEnumerable<(string name, string value)>", "MSBuild options for setting properties.") { IsCollection = true }; @@ -116,11 +116,11 @@ using Internal; paraFinish, CreateCliRef("dotnet-add-package") ], - ["add", "$Project", "package", "$PackageName"], + ["add", "$Project", "package", "$Package"], [ sourcesArg, projectArg, - new Arg("PackageName", "", "string", "The package reference to add."), + new Arg("Package", "", "string", "The package reference to add."), frameworkArg with { Comments = "Adds a package reference only when targeting a specific framework." }, noRestoreArg, new Arg("PackageDirectory", "--package-directory", "string", @"The directory where to restore the packages. The default package restore location is %userprofile%\.nuget\packages on Windows and ~/.nuget/packages on macOS and Linux."), @@ -163,10 +163,10 @@ using Internal; paraFinish, CreateCliRef("dotnet-remove-package") ], - ["remove", "$Project", "package", "$PackageName"], + ["remove", "$Project", "package", "$Package"], [ projectArg, - new Arg("PackageName", "", "string", "The package reference to add."), + new Arg("Package", "", "string", "The package reference to add."), diagnosticsArg ] ), @@ -181,7 +181,7 @@ using Internal; ], ["add", "$Project", "reference", "$References"], [ - new Arg("References", "--source", "IEnumerable", "Project-to-project (P2P) references to add. Specify one or more projects. Glob patterns are supported on Unix/Linux-based systems.") { IsCollection = true }, + new Arg("References", "", "IEnumerable", "Project-to-project (P2P) references to add. Specify one or more projects. Glob patterns are supported on Unix/Linux-based systems.") { IsProject = true, IsCollection = true }, projectArg, frameworkArg with { Comments = "Adds project references only when targeting a specific framework using the TFM format." }, diagnosticsArg @@ -196,7 +196,7 @@ using Internal; paraFinish, CreateCliRef("dotnet-list-reference") ], - ["list", "$Project"], + ["list", "$Project", "reference"], [ projectArg, diagnosticsArg @@ -213,7 +213,7 @@ using Internal; ], ["remove", "$Project", "reference", "$References"], [ - new Arg("References", "--source", "IEnumerable", "Project-to-project (P2P) references to remove. You can specify one or multiple projects. Glob patterns are supported on Unix/Linux based terminals.") { IsCollection = true }, + new Arg("References", "", "IEnumerable", "Project-to-project (P2P) references to remove. You can specify one or multiple projects. Glob patterns are supported on Unix/Linux based terminals.") { IsProject = true, IsCollection = true }, projectArg, frameworkArg with { Comments = "Removes the reference only when targeting a specific framework using the TFM format." }, diagnosticsArg @@ -229,15 +229,6 @@ using Internal; paraStart, "For executable projects targeting .NET Core 3.0 and later, library dependencies are copied to the output folder. This means that if there isn't any other publish-specific logic (such as Web projects have), the build output should be deployable.", paraFinish, - exampleStart, - codeStart, - "var configuration = Props.Get(\"configuration\", \"Release\");", - "", - "", - "new DotNetBuild().WithConfiguration(configuration)", - " .Build().EnsureSuccess();", - codeFinish, - exampleFinish, CreateCliRef("dotnet-build") ], ["build", "$Project"], @@ -344,15 +335,6 @@ using Internal; paraStart, "This command creates a .NET project or other artifacts based on a template. The command calls the template engine to create the artifacts on disk based on the specified template and options.", paraFinish, - exampleStart, - codeStart, - "new DotNetNew()", - " .WithTemplateName(\"console\")", - " .WithName(\"MyApp\")", - " .WithForce(true)", - " .Run().EnsureSuccess();", - codeFinish, - exampleFinish, CreateCliRef("dotnet-new") ], ["new", "$TemplateName"], @@ -498,9 +480,9 @@ using Internal; paraFinish, CreateCliRef("dotnet-nuget-delete") ], - ["nuget", "delete", "$PackageName", "$PackageVersion"], + ["nuget", "delete", "$Package", "$PackageVersion"], [ - new Arg("PackageName", "", "string", "Name/ID of the package to delete.") { IsProject = true }, + new Arg("Package", "", "string", "Name/ID of the package to delete.") { IsProject = true }, new Arg("PackageVersion", "", "string", "Version of the package to delete.") { IsProject = true }, new Arg("ForceEnglishOutput", "--force-english-output", "bool?", "Forces the application to run using an invariant, English-based culture."), new Arg("ApiKey", "--api-key", "string", "The API key for the server."), @@ -931,12 +913,6 @@ using Internal; paraStart, "By default, dotnet pack builds the project first. If you wish to avoid this behavior, pass the --no-build option. This option is often useful in Continuous Integration (CI) build scenarios where you know the code was previously built.", paraFinish, - exampleStart, - codeStart, - "new DotNetPack()", - " .Build().EnsureSuccess();", - codeFinish, - exampleFinish, CreateCliRef("dotnet-pack") ], ["pack", "$Project"], @@ -997,12 +973,6 @@ using Internal; paraStart, "This command compiles the application, reads through its dependencies specified in the project file, and publishes the resulting set of files to a directory.", paraFinish, - exampleStart, - codeStart, - "new DotNetPublish().AddProps((\"PublishDir\", \".publish\"))", - " .Build().EnsureSuccess();", - codeFinish, - exampleFinish, CreateCliRef("dotnet-publish") ], ["publish", "$Project"], @@ -1044,12 +1014,6 @@ using Internal; paraStart, "Sometimes, it might be inconvenient to run the implicit NuGet restore with these commands. For example, some automated systems, such as build systems, need to call dotnet restore explicitly to control when the restore occurs so that they can control network usage. To prevent the implicit NuGet restore, you can use the --no-restore flag with any of these commands.", paraFinish, - exampleStart, - codeStart, - "new DotNetRestore()", - " .Build().EnsureSuccess();", - codeFinish, - exampleFinish, CreateCliRef("dotnet-restore") ], ["restore", "$Project"], @@ -1088,19 +1052,6 @@ using Internal; paraStart, "To run the application, the dotnet run command resolves the dependencies of the application that are outside of the shared runtime from the NuGet cache. Because it uses cached dependencies, it's not recommended to use dotnet run to run applications in production. Instead, create a deployment using the dotnet publish command and deploy the published output.", paraFinish, - exampleStart, - codeStart, - "new DotNetNew()", - " .WithTemplateName(\"console\")", - " .WithName(\"MyApp\")", - " .WithForce(true)", - " .Run().EnsureSuccess();", - "", - "", - "new DotNetRun().WithWorkingDirectory(\"MyApp\")", - " .Build().EnsureSuccess();", - codeFinish, - exampleFinish, CreateCliRef("dotnet-run") ], ["run"], @@ -1210,19 +1161,6 @@ using Internal; paraStart, "For multi-targeted projects, tests are run for each targeted framework. The test host and the unit test framework are packaged as NuGet packages and are restored as ordinary dependencies for the project. Starting with the .NET 9 SDK, these tests are run in parallel by default. To disable parallel execution, set the TestTfmsInParallel MSBuild property to false.", paraFinish, - exampleStart, - codeStart, - "new DotNetNew()", - " .WithTemplateName(\"mstest\")", - " .WithName(\"MyTests\")", - " .WithForce(true)", - " .Run().EnsureSuccess();", - "", - "", - "new DotNetTest().WithWorkingDirectory(\"MyTests\")", - " .Build().EnsureSuccess();", - codeFinish, - exampleFinish, CreateCliRef("dotnet-test") ], ["test", "$Project"], @@ -1636,6 +1574,33 @@ using Internal; /// <#= comment #> <# } + + var exampleFile = Path.Combine("..", "CSharpInteractive.Tests", "UsageScenarios", "Comments", $"{command.Name}Scenario.txt"); + if (File.Exists(exampleFile)) + { + var exampleLines = File.ReadAllLines(exampleFile); + if (exampleLines.Length > 0) + { +#> +/// <#= exampleStart #> +///<#= codeStart #> +<# + var doc = new XmlDocument(); + foreach (var exampleLine in exampleLines.Select(i => i.TrimEnd())) + { + var node = doc.CreateElement("root"); + node.InnerText = exampleLine; + var line = node.InnerXml; +#> +/// <#= line #> +<# + } +#> +///<#= codeFinish #> +/// <#= exampleFinish #> +<# + } + } #> /// /// Specifies the set of command line arguments to use when starting the tool. @@ -1743,8 +1708,12 @@ public partial record <#= command.Name #>( { notEmptyArg = $"{notEmptyArg}.ToArray()"; } + else + { + notEmptyArg = $"{notEmptyArg}.ToArg()"; + } #> - .AddNotEmptyArgs(<#= notEmptyArg #>.ToArg()) + .AddNotEmptyArgs(<#= notEmptyArg #>) <# } else diff --git a/CSharpInteractive.HostApi/Internal/DotNet/DotNetCommandLineExtensions.cs b/CSharpInteractive.HostApi/Internal/DotNet/DotNetCommandLineExtensions.cs index 4a0449b..d26442a 100644 --- a/CSharpInteractive.HostApi/Internal/DotNet/DotNetCommandLineExtensions.cs +++ b/CSharpInteractive.HostApi/Internal/DotNet/DotNetCommandLineExtensions.cs @@ -161,6 +161,11 @@ public static string[] ToArgs(this IEnumerable values, string name, stri } var str = string.Join(collectionSeparator, values); + if (string.IsNullOrWhiteSpace(str)) + { + return []; + } + return string.IsNullOrWhiteSpace(str) ? [] : [name, str]; } diff --git a/CSharpInteractive.Tests/README_TEMPLATE.md b/CSharpInteractive.Tests/README_TEMPLATE.md index 9605185..320485a 100644 --- a/CSharpInteractive.Tests/README_TEMPLATE.md +++ b/CSharpInteractive.Tests/README_TEMPLATE.md @@ -31,19 +31,28 @@ - [Build a project in a docker container](#build-a-project-in-a-docker-container) - [Running in docker](#running-in-docker) - .NET CLI + - [Adding a NuGet package](#adding-a-nuget-package) + - [Adding a NuGet package](#adding-a-nuget-package) + - [Adding a project reference](#adding-a-project-reference) - [Build a project](#build-a-project) - [Build a project using MSBuild](#build-a-project-using-msbuild) - [Clean a project](#clean-a-project) + - [Execute a dotnet application](#execute-a-dotnet-application) + - [NuGet package listing](#nuget-package-listing) - [Pack a project](#pack-a-project) + - [Project reference listing](#project-reference-listing) - [Publish a project](#publish-a-project) + - [Removing a NuGet package](#removing-a-nuget-package) - [Restore a project](#restore-a-project) - [Restore local tools](#restore-local-tools) - [Run a custom .NET command](#run-a-custom-.net-command) + - [Run a dotnet application](#run-a-dotnet-application) - [Run a project](#run-a-project) - [Run tests under dotCover](#run-tests-under-dotcover) - [Test a project](#test-a-project) - [Test a project using the MSBuild VSTest target](#test-a-project-using-the-msbuild-vstest-target) - [Test an assembly](#test-an-assembly) + - [Run C# script](#run-c#-script) - [Shuts down build servers](#shuts-down-build-servers) - TeamCity API - [TeamCity integration via service messages](#teamcity-integration-via-service-messages) @@ -411,8 +420,6 @@ int? exitCode = new CommandLine("cmd", "/c", "TIMEOUT", "/T", "120") .Run(default, TimeSpan.FromMilliseconds(1)) .EnsureSuccess() .ExitCode; - -exitCode.HasValue.ShouldBeFalse(); ``` @@ -447,10 +454,6 @@ var result = dockerRun .Build() .EnsureSuccess(); -// The "result" variable provides details about a build -result.Errors.Any(message => message.State == BuildMessageState.StdError).ShouldBeFalse(); -result.ExitCode.ShouldBe(0); - string ToAbsoluteLinuxPath(string path) => "/" + path.Replace(":", "").Replace('\\', '/'); ``` @@ -477,6 +480,69 @@ var result = new DockerRun(cmd, "mcr.microsoft.com/dotnet/sdk") +### Adding a NuGet package + + + +``` CSharp +using HostApi; + +new DotNetNew() + .WithTemplateName("classlib") + .WithName("MyLib") + .WithForce(true) + .Build().EnsureSuccess(); + +var result = new DotNetAddPackage() + .WithWorkingDirectory("MyLib") + .WithPackage("Pure.DI") + .Run().EnsureSuccess(); + +var lines = new List(); +new DotNetListPackage() + .WithWorkingDirectory("MyLib") + .WithVerbosity(DotNetVerbosity.Minimal) + .Run(output => lines.Add(output.Line)); + +lines.Any(i => i.Contains("Pure.DI")).ShouldBeTrue(result.ToString()); +``` + + + +### Adding a NuGet package + + + +``` CSharp +using HostApi; + +new DotNetNew() + .WithTemplateName("classlib") + .WithName("MyLib") + .WithForce(true) + .Build().EnsureSuccess(); + +new DotNetNew() + .WithTemplateName("xunit") + .WithName("MyTests") + .WithForce(true) + .Build().EnsureSuccess(); + +var result = new DotNetAddReference() + .WithProject(Path.Combine("MyTests", "MyTests.csproj")) + .WithReferences(Path.Combine("MyLib", "MyLib.csproj")) + .Run().EnsureSuccess(); + +var lines = new List(); +new DotNetListReference() + .WithProject(Path.Combine("MyTests", "MyTests.csproj")) + .Run(output => lines.Add(output.Line)); + +lines.Any(i => i.Contains("MyLib.csproj")).ShouldBeTrue(result.ToString()); +``` + + + ### Build a project @@ -485,31 +551,28 @@ var result = new DockerRun(cmd, "mcr.microsoft.com/dotnet/sdk") // Adds the namespace "HostApi" to use .NET build API using HostApi; -// Creates a new library project, running a command like: "dotnet new classlib -n MyLib --force" +// Creates a new test project, running a command like: "dotnet new xunit -n MyTests --force" new DotNetNew() .WithTemplateName("xunit") - .WithName("MyLib") + .WithName("MyTests") .WithForce(true) .Build().EnsureSuccess(); -// Builds the library project, running a command like: "dotnet build" from the directory "MyLib" +// Builds this project, running a command like: "dotnet build" from the directory "MyLib" +var messages = new List(); var result = new DotNetBuild() - .WithWorkingDirectory("MyLib") - .Build().EnsureSuccess(); + .WithWorkingDirectory("MyTests") + .Build(message => messages.Add(message)).EnsureSuccess(); // The "result" variable provides details about a build -result.Errors.Any(message => message.State == BuildMessageState.StdError).ShouldBeFalse(); -result.ExitCode.ShouldBe(0); +messages.Count.ShouldBeGreaterThan(0, result.ToString()); +result.Errors.Any(message => message.State == BuildMessageState.StdError).ShouldBeFalse(result.ToString()); +result.ExitCode.ShouldBe(0, result.ToString()); // Runs tests in docker result = new DotNetTest() - .WithWorkingDirectory("MyLib") - .Build() - .EnsureSuccess(); - -result.ExitCode.ShouldBe(0); -result.Summary.Tests.ShouldBe(1); -result.Tests.Count(test => test.State == TestState.Finished).ShouldBe(1); + .WithWorkingDirectory("MyTests") + .Build().EnsureSuccess(); ``` @@ -568,6 +631,97 @@ version.ShouldNotBeNull(); +### Execute a dotnet application + + + +``` CSharp +// Adds the namespace "HostApi" to use .NET build API +using HostApi; + +// Creates a new console project, running a command like: "dotnet new console -n MyApp --force" +new DotNetNew() + .WithTemplateName("console") + .WithName("MyApp") + .WithForce(true) + .Build().EnsureSuccess(); + +var tempDirectory = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); +new DotNetPublish() + .WithWorkingDirectory("MyApp") + .WithOutput(tempDirectory) + .Build().EnsureSuccess(); + +new DotNetExec() + .WithPathToApplication(Path.Combine(tempDirectory, "MyApp.dll")) + .Run().EnsureSuccess(); +``` + + + +### NuGet package listing + + + +``` CSharp +using HostApi; + +new DotNetNew() + .WithTemplateName("classlib") + .WithName("MyLib") + .WithForce(true) + .Build().EnsureSuccess(); + +new DotNetAddPackage() + .WithWorkingDirectory("MyLib") + .WithPackage("Pure.DI") + .Run().EnsureSuccess(); + +var lines = new List(); +var result = new DotNetListPackage() + .WithWorkingDirectory("MyLib") + .WithVerbosity(DotNetVerbosity.Minimal) + .Run(output => lines.Add(output.Line)); + +lines.Any(i => i.Contains("Pure.DI")).ShouldBeTrue(result.ToString()); +``` + + + +### Project reference listing + + + +``` CSharp +using HostApi; + +new DotNetNew() + .WithTemplateName("classlib") + .WithName("MyLib") + .WithForce(true) + .Build().EnsureSuccess(); + +new DotNetNew() + .WithTemplateName("xunit") + .WithName("MyTests") + .WithForce(true) + .Build().EnsureSuccess(); + +new DotNetAddReference() + .WithProject(Path.Combine("MyTests", "MyTests.csproj")) + .WithReferences(Path.Combine("MyLib", "MyLib.csproj")) + .Run().EnsureSuccess(); + +var lines = new List(); +var result = new DotNetListReference() + .WithProject(Path.Combine("MyTests", "MyTests.csproj")) + .Run(output => lines.Add(output.Line)); + +lines.Any(i => i.Contains("MyLib.csproj")).ShouldBeTrue(result.ToString()); +``` + + + ### Test a project using the MSBuild VSTest target @@ -621,8 +775,6 @@ result = new DotNetPack() .WithWorkingDirectory("MyLib") .AddProps(("version", "1.2.3")) .Build().EnsureSuccess(); - -result.ExitCode.ShouldBe(0); ``` @@ -650,8 +802,79 @@ result = new DotNetPublish() .WithWorkingDirectory("MyLib") .WithFramework("net8.0") .Build().EnsureSuccess(); +``` -result.ExitCode.ShouldBe(0); + + +### Removing a NuGet package + + + +``` CSharp +using HostApi; + +new DotNetNew() + .WithTemplateName("classlib") + .WithName("MyLib") + .WithForce(true) + .Build().EnsureSuccess(); + +new DotNetAddPackage() + .WithWorkingDirectory("MyLib") + .WithPackage("Pure.DI") + .Run().EnsureSuccess(); + +var result = new DotNetRemovePackage() + .WithWorkingDirectory("MyLib") + .WithPackage("Pure.DI") + .Run().EnsureSuccess(); + +var lines = new List(); +new DotNetListPackage() + .WithWorkingDirectory("MyLib") + .WithVerbosity(DotNetVerbosity.Minimal) + .Run(output => lines.Add(output.Line)); + +lines.Any(i => i.Contains("Pure.DI")).ShouldBeFalse(result.ToString()); +``` + + + +### Adding a project reference + + + +``` CSharp +using HostApi; + +new DotNetNew() + .WithTemplateName("classlib") + .WithName("MyLib") + .WithForce(true) + .Build().EnsureSuccess(); + +new DotNetNew() + .WithTemplateName("xunit") + .WithName("MyTests") + .WithForce(true) + .Build().EnsureSuccess(); + +new DotNetAddReference() + .WithProject(Path.Combine("MyTests", "MyTests.csproj")) + .WithReferences(Path.Combine("MyLib", "MyLib.csproj")) + .Run().EnsureSuccess(); + +var result = new DotNetRemoveReference() + .WithProject(Path.Combine("MyTests", "MyTests.csproj")) + .WithReferences(Path.Combine("MyLib", "MyLib.csproj")) + .Run().EnsureSuccess(); + +var lines = new List(); +new DotNetListReference() + .WithProject(Path.Combine("MyTests", "MyTests.csproj")) + .Run(output => lines.Add(output.Line)); + +lines.Any(i => i.Contains("MyLib.csproj")).ShouldBeFalse(result.ToString()); ``` @@ -677,8 +900,6 @@ result.ExitCode.ShouldBe(0); result = new DotNetRestore() .WithWorkingDirectory("MyLib") .Build().EnsureSuccess(); - -result.ExitCode.ShouldBe(0); ``` @@ -702,7 +923,8 @@ result.ExitCode.ShouldBe(0); // Runs the console project using a command like: "dotnet run" from the directory "MyApp" var stdOut = new List(); -result = new DotNetRun().WithWorkingDirectory("MyApp") +result = new DotNetRun() + .WithWorkingDirectory("MyApp") .Build(message => stdOut.Add(message.Text)) .EnsureSuccess(); @@ -714,6 +936,34 @@ stdOut.ShouldBe(new[] {"Hello, World!"}); +### Run a dotnet application + + + +``` CSharp +// Adds the namespace "HostApi" to use .NET build API +using HostApi; + +// Creates a new console project, running a command like: "dotnet new console -n MyApp --force" +new DotNetNew() + .WithTemplateName("console") + .WithName("MyApp") + .WithForce(true) + .Build().EnsureSuccess(); + +var tempDirectory = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); +new DotNetPublish() + .WithWorkingDirectory("MyApp") + .WithOutput(tempDirectory) + .Build().EnsureSuccess(); + +new DotNet() + .WithPathToApplication(Path.Combine(tempDirectory, "MyApp.dll")) + .Run().EnsureSuccess(); +``` + + + ### Test a project @@ -738,9 +988,9 @@ result = new DotNetTest() .EnsureSuccess(); // The "result" variable provides details about a build -result.ExitCode.ShouldBe(0); -result.Summary.Tests.ShouldBe(1); -result.Tests.Count(test => test.State == TestState.Finished).ShouldBe(1); +result.ExitCode.ShouldBe(0, result.ToString()); +result.Summary.Tests.ShouldBe(1, result.ToString()); +result.Tests.Count(test => test.State == TestState.Finished).ShouldBe(1, result.ToString()); ``` @@ -792,8 +1042,8 @@ var result = testUnderDotCover .Build().EnsureSuccess(); // The "result" variable provides details about a build -result.ExitCode.ShouldBe(0); -result.Tests.Count(i => i.State == TestState.Finished).ShouldBe(1); +result.ExitCode.ShouldBe(0, result.ToString()); +result.Tests.Count(i => i.State == TestState.Finished).ShouldBe(1, result.ToString()); // Generates a HTML code coverage report. new DotNetCustom("dotCover", "report", $"--source={dotCoverSnapshot}", $"--output={dotCoverReport}", "--reportType=HTML") @@ -847,7 +1097,7 @@ var result = new DotNetNew() .WithForce(true) .Build().EnsureSuccess(); -result.ExitCode.ShouldBe(0); +result.ExitCode.ShouldBe(0, result.ToString()); // Builds the test project, running a command like: "dotnet build -c Release" from the directory "MyTests" result = new DotNetBuild() @@ -856,7 +1106,7 @@ result = new DotNetBuild() .WithOutput("MyOutput") .Build().EnsureSuccess(); -result.ExitCode.ShouldBe(0); +result.ExitCode.ShouldBe(0, result.ToString()); // Runs tests via a command like: "dotnet vstest" from the directory "MyTests" result = new VSTest() @@ -865,9 +1115,9 @@ result = new VSTest() .Build().EnsureSuccess(); // The "result" variable provides details about a build -result.ExitCode.ShouldBe(0); -result.Summary.Tests.ShouldBe(1); -result.Tests.Count(test => test.State == TestState.Finished).ShouldBe(1); +result.ExitCode.ShouldBe(0, result.ToString()); +result.Summary.Tests.ShouldBe(1, result.ToString()); +result.Tests.Count(test => test.State == TestState.Finished).ShouldBe(1, result.ToString()); ``` @@ -887,7 +1137,7 @@ var result = new DotNetNew() .WithForce(true) .Build().EnsureSuccess(); -result.ExitCode.ShouldBe(0); +result.ExitCode.ShouldBe(0, result.ToString()); // Builds the library project, running a command like: "dotnet msbuild /t:Build -restore /p:configuration=Release -verbosity=detailed" from the directory "MyLib" result = new MSBuild() @@ -899,8 +1149,8 @@ result = new MSBuild() .Build().EnsureSuccess(); // The "result" variable provides details about a build -result.Errors.Any(message => message.State == BuildMessageState.StdError).ShouldBeFalse(); -result.ExitCode.ShouldBe(0); +result.Errors.Any(message => message.State == BuildMessageState.StdError).ShouldBeFalse(result.ToString()); +result.ExitCode.ShouldBe(0, result.ToString()); ``` @@ -921,6 +1171,32 @@ new DotNetBuildServerShutdown() +### Run C# script + + + +``` CSharp +// Adds the namespace "HostApi" to use .NET build API +using HostApi; + +var script = Path.GetTempFileName(); +File.WriteAllText(script, "Console.WriteLine($\"Hello, {Args[0]}!\");"); + +var stdOut = new List(); +var result = new DotNetCsi() + .WithScript(script) + .AddArgs("World") + .Build(message => stdOut.Add(message.Text)) + .EnsureSuccess(); + +result.ExitCode.ShouldBe(0); + +// Checks StdOut +stdOut.Contains("Hello, World!").ShouldBeTrue(result.ToString()); +``` + + + ### TeamCity integration via service messages For more details how to use TeamCity service message API please see [this](https://github.com/JetBrains/TeamCity.ServiceMessages) page. Instead of creating a root message writer like in the following example: diff --git a/CSharpInteractive.Tests/README_TEMPLATE.tt b/CSharpInteractive.Tests/README_TEMPLATE.tt index 4ad63b1..f0f995a 100644 --- a/CSharpInteractive.Tests/README_TEMPLATE.tt +++ b/CSharpInteractive.Tests/README_TEMPLATE.tt @@ -12,6 +12,19 @@ var solutionPath = Path.Combine(currentPath, ".."); var infos = new List>(); + var commentsDir = Path.Combine(scenariosPath, "Comments"); + if (Directory.Exists(commentsDir)) + { + foreach (var file in Directory.GetFiles(commentsDir, "*.txt")) + { + File.Delete(file); + } + } + else + { + Directory.CreateDirectory(commentsDir); + } + foreach (var file in Directory.GetFiles(scenariosPath, "*.cs")) { var isBody = false; @@ -127,12 +140,15 @@ <# foreach (var info in infos.OrderBy(i => i["tag"] + i["priority"]).Where(info => info["visible"] == "true")) { + var file = info["file"]; + var body = info["body"]; + File.WriteAllText(Path.Combine(commentsDir, Path.GetFileNameWithoutExtension(file) + ".txt"), body); #>### <#= info["description"] #> <#= info["header"] #> ``` CSharp -<#= info["body"] #>``` +<#= body #>``` <#= info["footer"] #> diff --git a/CSharpInteractive.Tests/UsageScenarios/Comments/ArgsScenario.txt b/CSharpInteractive.Tests/UsageScenarios/Comments/ArgsScenario.txt new file mode 100644 index 0000000..8f0d4ed --- /dev/null +++ b/CSharpInteractive.Tests/UsageScenarios/Comments/ArgsScenario.txt @@ -0,0 +1,9 @@ +if (Args.Count > 0) +{ + WriteLine(Args[0]); +} + +if (Args.Count > 1) +{ + WriteLine(Args[1]); +} diff --git a/CSharpInteractive.Tests/UsageScenarios/Comments/CommandLineAsyncCancellation.txt b/CSharpInteractive.Tests/UsageScenarios/Comments/CommandLineAsyncCancellation.txt new file mode 100644 index 0000000..20f98db --- /dev/null +++ b/CSharpInteractive.Tests/UsageScenarios/Comments/CommandLineAsyncCancellation.txt @@ -0,0 +1,9 @@ +// Adds the namespace "HostApi" to use Command Line API +using HostApi; + +var cancellationTokenSource = new CancellationTokenSource(); +var task = new CommandLine("cmd", "/c", "TIMEOUT", "/T", "120") + .RunAsync(default, cancellationTokenSource.Token); + +cancellationTokenSource.CancelAfter(TimeSpan.FromMilliseconds(100)); +task.IsCompleted.ShouldBeFalse(); diff --git a/CSharpInteractive.Tests/UsageScenarios/Comments/CommandLineAsyncScenario.txt b/CSharpInteractive.Tests/UsageScenarios/Comments/CommandLineAsyncScenario.txt new file mode 100644 index 0000000..1362e5d --- /dev/null +++ b/CSharpInteractive.Tests/UsageScenarios/Comments/CommandLineAsyncScenario.txt @@ -0,0 +1,11 @@ +// Adds the namespace "HostApi" to use Command Line API +using HostApi; + +await GetService() + .RunAsync(new CommandLine("cmd", "/C", "DIR")) + .EnsureSuccess(); + +// or the same thing using the extension method +var result = await new CommandLine("cmd", "/c", "DIR") + .RunAsync() + .EnsureSuccess(); diff --git a/CSharpInteractive.Tests/UsageScenarios/Comments/CommandLineInParallelScenario.txt b/CSharpInteractive.Tests/UsageScenarios/Comments/CommandLineInParallelScenario.txt new file mode 100644 index 0000000..f64e01e --- /dev/null +++ b/CSharpInteractive.Tests/UsageScenarios/Comments/CommandLineInParallelScenario.txt @@ -0,0 +1,12 @@ +// Adds the namespace "HostApi" to use Command Line API +using HostApi; + +var task = new CommandLine("cmd", "/c", "DIR") + .RunAsync() + .EnsureSuccess(); + +var result = new CommandLine("cmd", "/c", "SET") + .Run() + .EnsureSuccess(); + +await task; diff --git a/CSharpInteractive.Tests/UsageScenarios/Comments/CommandLineOutputScenario.txt b/CSharpInteractive.Tests/UsageScenarios/Comments/CommandLineOutputScenario.txt new file mode 100644 index 0000000..b3ec27e --- /dev/null +++ b/CSharpInteractive.Tests/UsageScenarios/Comments/CommandLineOutputScenario.txt @@ -0,0 +1,10 @@ +// Adds the namespace "HostApi" to use Command Line API +using HostApi; + +var lines = new List(); +var result = new CommandLine("cmd", "/c", "SET") + .AddVars(("MyEnv", "MyVal")) + .Run(output => lines.Add(output.Line)) + .EnsureSuccess(); + +lines.ShouldContain("MyEnv=MyVal"); diff --git a/CSharpInteractive.Tests/UsageScenarios/Comments/CommandLineScenario.txt b/CSharpInteractive.Tests/UsageScenarios/Comments/CommandLineScenario.txt new file mode 100644 index 0000000..766798c --- /dev/null +++ b/CSharpInteractive.Tests/UsageScenarios/Comments/CommandLineScenario.txt @@ -0,0 +1,19 @@ +// Adds the namespace "HostApi" to use Command Line API +using HostApi; + +GetService() + .Run(new CommandLine("cmd", "/c", "DIR")) + .EnsureSuccess(); + +// or the same thing using the extension method +new CommandLine("cmd", "/c", "DIR") + .Run() + .EnsureSuccess(); + +// using operator '+' +var cmd = new CommandLine("cmd") + "/c" + "DIR"; +cmd.Run().EnsureSuccess(); + +// with environment variables +cmd = new CommandLine("cmd") + "/c" + "DIR" + ("MyEnvVar", "Some Value"); +cmd.Run().EnsureSuccess(); diff --git a/CSharpInteractive.Tests/UsageScenarios/Comments/CommandLineWithTimeoutScenario.txt b/CSharpInteractive.Tests/UsageScenarios/Comments/CommandLineWithTimeoutScenario.txt new file mode 100644 index 0000000..a145f36 --- /dev/null +++ b/CSharpInteractive.Tests/UsageScenarios/Comments/CommandLineWithTimeoutScenario.txt @@ -0,0 +1,7 @@ +// Adds the namespace "HostApi" to use Command Line API +using HostApi; + +int? exitCode = new CommandLine("cmd", "/c", "TIMEOUT", "/T", "120") + .Run(default, TimeSpan.FromMilliseconds(1)) + .EnsureSuccess() + .ExitCode; diff --git a/CSharpInteractive.Tests/UsageScenarios/Comments/CommandLinesScenario.txt b/CSharpInteractive.Tests/UsageScenarios/Comments/CommandLinesScenario.txt new file mode 100644 index 0000000..af7598a --- /dev/null +++ b/CSharpInteractive.Tests/UsageScenarios/Comments/CommandLinesScenario.txt @@ -0,0 +1,44 @@ +// Adds the namespace "Script.Cmd" to use Command Line API +using HostApi; + +// Creates and run a simple command line +"whoami".AsCommandLine().Run().EnsureSuccess(); + +// Creates and run a simple command line +new CommandLine("whoami").Run().EnsureSuccess(); + +// Creates and run a command line with arguments +new CommandLine("cmd", "/c", "echo", "Hello").Run(); + +// Same as previous statement +new CommandLine("cmd", "/c") + .AddArgs("echo", "Hello") + .Run() + .EnsureSuccess(); + +(new CommandLine("cmd") + "/c" + "echo" + "Hello") + .Run() + .EnsureSuccess(); + +"cmd".AsCommandLine("/c", "echo", "Hello") + .Run() + .EnsureSuccess(); + +("cmd".AsCommandLine() + "/c" + "echo" + "Hello") + .Run() + .EnsureSuccess(); + +// Just builds a command line with multiple environment variables +var cmd = new CommandLine("cmd", "/c", "echo", "Hello") + .AddVars(("Var1", "val1"), ("var2", "Val2")); + +// Same as previous statement +cmd = new CommandLine("cmd") + "/c" + "echo" + "Hello" + ("Var1", "val1") + ("var2", "Val2"); + +// Builds a command line to run from a specific working directory +cmd = new CommandLine("cmd", "/c", "echo", "Hello") + .WithWorkingDirectory("MyDyrectory"); + +// Builds a command line and replaces all command line arguments +cmd = new CommandLine("cmd", "/c", "echo", "Hello") + .WithArgs("/c", "echo", "Hello !!!"); diff --git a/CSharpInteractive.Tests/UsageScenarios/Comments/DockerDotNetBuildScenario.txt b/CSharpInteractive.Tests/UsageScenarios/Comments/DockerDotNetBuildScenario.txt new file mode 100644 index 0000000..d4a6b1d --- /dev/null +++ b/CSharpInteractive.Tests/UsageScenarios/Comments/DockerDotNetBuildScenario.txt @@ -0,0 +1,27 @@ +// Adds the namespace "HostApi" to use .NET build API and Docker API +using HostApi; + +// Creates a base docker command line +var dockerRun = new DockerRun() + .WithAutoRemove(true) + .WithInteractive(true) + .WithImage("mcr.microsoft.com/dotnet/sdk") + .WithPlatform("linux") + .WithContainerWorkingDirectory("/MyProjects") + .AddVolumes((ToAbsoluteLinuxPath(Environment.CurrentDirectory), "/MyProjects")); + + +// Creates a new library project in a docker container +dockerRun + .WithCommandLine(new DotNetCustom("new", "classlib", "-n", "MyLib", "--force")) + .Run() + .EnsureSuccess(); + +// Builds the library project in a docker container +var result = dockerRun + .WithCommandLine(new DotNetBuild().WithProject("MyLib/MyLib.csproj")) + .Build() + .EnsureSuccess(); + +string ToAbsoluteLinuxPath(string path) => + "/" + path.Replace(":", "").Replace('\\', '/'); diff --git a/CSharpInteractive.Tests/UsageScenarios/Comments/DockerRunScenario.txt b/CSharpInteractive.Tests/UsageScenarios/Comments/DockerRunScenario.txt new file mode 100644 index 0000000..3c218ed --- /dev/null +++ b/CSharpInteractive.Tests/UsageScenarios/Comments/DockerRunScenario.txt @@ -0,0 +1,11 @@ +// Adds the namespace "HostApi" to use Command Line API and Docker API +using HostApi; + +// Creates some command line to run in a docker container +var cmd = new CommandLine("whoami"); + +// Runs the command line in a docker container +var result = new DockerRun(cmd, "mcr.microsoft.com/dotnet/sdk") + .WithAutoRemove(true) + .Run() + .EnsureSuccess(); diff --git a/CSharpInteractive.Tests/UsageScenarios/Comments/DotNetAddPackageScenario.txt b/CSharpInteractive.Tests/UsageScenarios/Comments/DotNetAddPackageScenario.txt new file mode 100644 index 0000000..e179949 --- /dev/null +++ b/CSharpInteractive.Tests/UsageScenarios/Comments/DotNetAddPackageScenario.txt @@ -0,0 +1,20 @@ +using HostApi; + +new DotNetNew() + .WithTemplateName("classlib") + .WithName("MyLib") + .WithForce(true) + .Build().EnsureSuccess(); + +var result = new DotNetAddPackage() + .WithWorkingDirectory("MyLib") + .WithPackage("Pure.DI") + .Run().EnsureSuccess(); + +var lines = new List(); +new DotNetListPackage() + .WithWorkingDirectory("MyLib") + .WithVerbosity(DotNetVerbosity.Minimal) + .Run(output => lines.Add(output.Line)); + +lines.Any(i => i.Contains("Pure.DI")).ShouldBeTrue(result.ToString()); diff --git a/CSharpInteractive.Tests/UsageScenarios/Comments/DotNetAddReferenceScenario.txt b/CSharpInteractive.Tests/UsageScenarios/Comments/DotNetAddReferenceScenario.txt new file mode 100644 index 0000000..93020f3 --- /dev/null +++ b/CSharpInteractive.Tests/UsageScenarios/Comments/DotNetAddReferenceScenario.txt @@ -0,0 +1,25 @@ +using HostApi; + +new DotNetNew() + .WithTemplateName("classlib") + .WithName("MyLib") + .WithForce(true) + .Build().EnsureSuccess(); + +new DotNetNew() + .WithTemplateName("xunit") + .WithName("MyTests") + .WithForce(true) + .Build().EnsureSuccess(); + +var result = new DotNetAddReference() + .WithProject(Path.Combine("MyTests", "MyTests.csproj")) + .WithReferences(Path.Combine("MyLib", "MyLib.csproj")) + .Run().EnsureSuccess(); + +var lines = new List(); +new DotNetListReference() + .WithProject(Path.Combine("MyTests", "MyTests.csproj")) + .Run(output => lines.Add(output.Line)); + +lines.Any(i => i.Contains("MyLib.csproj")).ShouldBeTrue(result.ToString()); diff --git a/CSharpInteractive.Tests/UsageScenarios/Comments/DotNetBuildScenario.txt b/CSharpInteractive.Tests/UsageScenarios/Comments/DotNetBuildScenario.txt new file mode 100644 index 0000000..b158ce4 --- /dev/null +++ b/CSharpInteractive.Tests/UsageScenarios/Comments/DotNetBuildScenario.txt @@ -0,0 +1,25 @@ +// Adds the namespace "HostApi" to use .NET build API +using HostApi; + +// Creates a new test project, running a command like: "dotnet new xunit -n MyTests --force" +new DotNetNew() + .WithTemplateName("xunit") + .WithName("MyTests") + .WithForce(true) + .Build().EnsureSuccess(); + +// Builds this project, running a command like: "dotnet build" from the directory "MyLib" +var messages = new List(); +var result = new DotNetBuild() + .WithWorkingDirectory("MyTests") + .Build(message => messages.Add(message)).EnsureSuccess(); + +// The "result" variable provides details about a build +messages.Count.ShouldBeGreaterThan(0, result.ToString()); +result.Errors.Any(message => message.State == BuildMessageState.StdError).ShouldBeFalse(result.ToString()); +result.ExitCode.ShouldBe(0, result.ToString()); + +// Runs tests in docker +result = new DotNetTest() + .WithWorkingDirectory("MyTests") + .Build().EnsureSuccess(); diff --git a/CSharpInteractive.Tests/UsageScenarios/Comments/DotNetBuildServerShutdownScenario.txt b/CSharpInteractive.Tests/UsageScenarios/Comments/DotNetBuildServerShutdownScenario.txt new file mode 100644 index 0000000..be7faf2 --- /dev/null +++ b/CSharpInteractive.Tests/UsageScenarios/Comments/DotNetBuildServerShutdownScenario.txt @@ -0,0 +1,7 @@ +// Adds the namespace "HostApi" to use .NET build API +using HostApi; + +// Shuts down all build servers that are started from dotnet. +new DotNetBuildServerShutdown() + .Run() + .EnsureSuccess(); diff --git a/CSharpInteractive.Tests/UsageScenarios/Comments/DotNetCleanScenario.txt b/CSharpInteractive.Tests/UsageScenarios/Comments/DotNetCleanScenario.txt new file mode 100644 index 0000000..7c1c96f --- /dev/null +++ b/CSharpInteractive.Tests/UsageScenarios/Comments/DotNetCleanScenario.txt @@ -0,0 +1,26 @@ +// Adds the namespace "HostApi" to use .NET build API +using HostApi; + +// Creates a new library project, running a command like: "dotnet new classlib -n MyLib --force" +var result = new DotNetNew() + .WithTemplateName("classlib") + .WithName("MyLib") + .WithForce(true) + .Build().EnsureSuccess(); + +result.ExitCode.ShouldBe(0); + +// Builds the library project, running a command like: "dotnet build" from the directory "MyLib" +result = new DotNetBuild() + .WithWorkingDirectory("MyLib") + .Build().EnsureSuccess(); + +result.ExitCode.ShouldBe(0); + +// Clean the project, running a command like: "dotnet clean" from the directory "MyLib" +result = new DotNetClean() + .WithWorkingDirectory("MyLib") + .Build().EnsureSuccess(); + +// The "result" variable provides details about a build +result.ExitCode.ShouldBe(0); diff --git a/CSharpInteractive.Tests/UsageScenarios/Comments/DotNetCsiScenario.txt b/CSharpInteractive.Tests/UsageScenarios/Comments/DotNetCsiScenario.txt new file mode 100644 index 0000000..07eaea8 --- /dev/null +++ b/CSharpInteractive.Tests/UsageScenarios/Comments/DotNetCsiScenario.txt @@ -0,0 +1,17 @@ +// Adds the namespace "HostApi" to use .NET build API +using HostApi; + +var script = Path.GetTempFileName(); +File.WriteAllText(script, "Console.WriteLine($\"Hello, {Args[0]}!\");"); + +var stdOut = new List(); +var result = new DotNetCsi() + .WithScript(script) + .AddArgs("World") + .Build(message => stdOut.Add(message.Text)) + .EnsureSuccess(); + +result.ExitCode.ShouldBe(0); + +// Checks StdOut +stdOut.Contains("Hello, World!").ShouldBeTrue(result.ToString()); diff --git a/CSharpInteractive.Tests/UsageScenarios/Comments/DotNetCustomScenario.txt b/CSharpInteractive.Tests/UsageScenarios/Comments/DotNetCustomScenario.txt new file mode 100644 index 0000000..2f6de90 --- /dev/null +++ b/CSharpInteractive.Tests/UsageScenarios/Comments/DotNetCustomScenario.txt @@ -0,0 +1,10 @@ +// Adds the namespace "HostApi" to use .NET build API +using HostApi; + +// Gets the dotnet version, running a command like: "dotnet --version" +NuGetVersion? version = default; +new DotNetCustom("--version") + .Run(message => NuGetVersion.TryParse(message.Line, out version)) + .EnsureSuccess(); + +version.ShouldNotBeNull(); diff --git a/CSharpInteractive.Tests/UsageScenarios/Comments/DotNetExecScenario.txt b/CSharpInteractive.Tests/UsageScenarios/Comments/DotNetExecScenario.txt new file mode 100644 index 0000000..16dd0e2 --- /dev/null +++ b/CSharpInteractive.Tests/UsageScenarios/Comments/DotNetExecScenario.txt @@ -0,0 +1,19 @@ +// Adds the namespace "HostApi" to use .NET build API +using HostApi; + +// Creates a new console project, running a command like: "dotnet new console -n MyApp --force" +new DotNetNew() + .WithTemplateName("console") + .WithName("MyApp") + .WithForce(true) + .Build().EnsureSuccess(); + +var tempDirectory = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); +new DotNetPublish() + .WithWorkingDirectory("MyApp") + .WithOutput(tempDirectory) + .Build().EnsureSuccess(); + +new DotNetExec() + .WithPathToApplication(Path.Combine(tempDirectory, "MyApp.dll")) + .Run().EnsureSuccess(); diff --git a/CSharpInteractive.Tests/UsageScenarios/Comments/DotNetListPackageScenario.txt b/CSharpInteractive.Tests/UsageScenarios/Comments/DotNetListPackageScenario.txt new file mode 100644 index 0000000..429cce2 --- /dev/null +++ b/CSharpInteractive.Tests/UsageScenarios/Comments/DotNetListPackageScenario.txt @@ -0,0 +1,20 @@ +using HostApi; + +new DotNetNew() + .WithTemplateName("classlib") + .WithName("MyLib") + .WithForce(true) + .Build().EnsureSuccess(); + +new DotNetAddPackage() + .WithWorkingDirectory("MyLib") + .WithPackage("Pure.DI") + .Run().EnsureSuccess(); + +var lines = new List(); +var result = new DotNetListPackage() + .WithWorkingDirectory("MyLib") + .WithVerbosity(DotNetVerbosity.Minimal) + .Run(output => lines.Add(output.Line)); + +lines.Any(i => i.Contains("Pure.DI")).ShouldBeTrue(result.ToString()); diff --git a/CSharpInteractive.Tests/UsageScenarios/Comments/DotNetListReferenceScenario.txt b/CSharpInteractive.Tests/UsageScenarios/Comments/DotNetListReferenceScenario.txt new file mode 100644 index 0000000..7dad8e2 --- /dev/null +++ b/CSharpInteractive.Tests/UsageScenarios/Comments/DotNetListReferenceScenario.txt @@ -0,0 +1,25 @@ +using HostApi; + +new DotNetNew() + .WithTemplateName("classlib") + .WithName("MyLib") + .WithForce(true) + .Build().EnsureSuccess(); + +new DotNetNew() + .WithTemplateName("xunit") + .WithName("MyTests") + .WithForce(true) + .Build().EnsureSuccess(); + +new DotNetAddReference() + .WithProject(Path.Combine("MyTests", "MyTests.csproj")) + .WithReferences(Path.Combine("MyLib", "MyLib.csproj")) + .Run().EnsureSuccess(); + +var lines = new List(); +var result = new DotNetListReference() + .WithProject(Path.Combine("MyTests", "MyTests.csproj")) + .Run(output => lines.Add(output.Line)); + +lines.Any(i => i.Contains("MyLib.csproj")).ShouldBeTrue(result.ToString()); diff --git a/CSharpInteractive.Tests/UsageScenarios/Comments/DotNetMSBuildVSTestScenario.txt b/CSharpInteractive.Tests/UsageScenarios/Comments/DotNetMSBuildVSTestScenario.txt new file mode 100644 index 0000000..c957f8c --- /dev/null +++ b/CSharpInteractive.Tests/UsageScenarios/Comments/DotNetMSBuildVSTestScenario.txt @@ -0,0 +1,22 @@ +// Adds the namespace "HostApi" to use .NET build API +using HostApi; + +// Creates a new test project, running a command like: "dotnet new mstest -n MyTests --force" +var result = new DotNetNew() + .WithTemplateName("mstest") + .WithName("MyTests") + .WithForce(true) + .Build().EnsureSuccess(); + +result.ExitCode.ShouldBe(0, result.ToString()); + +// Runs tests via a command like: "dotnet msbuild /t:VSTest" from the directory "MyTests" +result = new MSBuild() + .WithTarget("VSTest") + .WithWorkingDirectory("MyTests") + .Build().EnsureSuccess(); + +// The "result" variable provides details about a build +result.ExitCode.ShouldBe(0, result.ToString()); +result.Summary.Tests.ShouldBe(1, result.ToString()); +result.Tests.Count(test => test.State == TestState.Finished).ShouldBe(1, result.ToString()); diff --git a/CSharpInteractive.Tests/UsageScenarios/Comments/DotNetPackScenario.txt b/CSharpInteractive.Tests/UsageScenarios/Comments/DotNetPackScenario.txt new file mode 100644 index 0000000..d456d73 --- /dev/null +++ b/CSharpInteractive.Tests/UsageScenarios/Comments/DotNetPackScenario.txt @@ -0,0 +1,17 @@ +// Adds the namespace "HostApi" to use .NET build API +using HostApi; + +// Creates a new library project, running a command like: "dotnet new classlib -n MyLib --force" +var result = new DotNetNew() + .WithTemplateName("classlib") + .WithName("MyLib") + .WithForce(true) + .Build().EnsureSuccess(); + +result.ExitCode.ShouldBe(0); + +// Creates a NuGet package of version 1.2.3 for the project, running a command like: "dotnet pack /p:version=1.2.3" from the directory "MyLib" +result = new DotNetPack() + .WithWorkingDirectory("MyLib") + .AddProps(("version", "1.2.3")) + .Build().EnsureSuccess(); diff --git a/CSharpInteractive.Tests/UsageScenarios/Comments/DotNetPublishScenario.txt b/CSharpInteractive.Tests/UsageScenarios/Comments/DotNetPublishScenario.txt new file mode 100644 index 0000000..d04abc9 --- /dev/null +++ b/CSharpInteractive.Tests/UsageScenarios/Comments/DotNetPublishScenario.txt @@ -0,0 +1,18 @@ +// Adds the namespace "HostApi" to use .NET build API +using HostApi; + +// Creates a new library project, running a command like: "dotnet new classlib -n MyLib --force" +var result = new DotNetNew() + .WithTemplateName("classlib") + .AddArgs("-f", "net8.0") + .WithName("MyLib") + .WithForce(true) + .Build().EnsureSuccess(); + +result.ExitCode.ShouldBe(0); + +// Publish the project, running a command like: "dotnet publish --framework net6.0" from the directory "MyLib" +result = new DotNetPublish() + .WithWorkingDirectory("MyLib") + .WithFramework("net8.0") + .Build().EnsureSuccess(); diff --git a/CSharpInteractive.Tests/UsageScenarios/Comments/DotNetRemovePackageScenario.txt b/CSharpInteractive.Tests/UsageScenarios/Comments/DotNetRemovePackageScenario.txt new file mode 100644 index 0000000..d6f7971 --- /dev/null +++ b/CSharpInteractive.Tests/UsageScenarios/Comments/DotNetRemovePackageScenario.txt @@ -0,0 +1,25 @@ +using HostApi; + +new DotNetNew() + .WithTemplateName("classlib") + .WithName("MyLib") + .WithForce(true) + .Build().EnsureSuccess(); + +new DotNetAddPackage() + .WithWorkingDirectory("MyLib") + .WithPackage("Pure.DI") + .Run().EnsureSuccess(); + +var result = new DotNetRemovePackage() + .WithWorkingDirectory("MyLib") + .WithPackage("Pure.DI") + .Run().EnsureSuccess(); + +var lines = new List(); +new DotNetListPackage() + .WithWorkingDirectory("MyLib") + .WithVerbosity(DotNetVerbosity.Minimal) + .Run(output => lines.Add(output.Line)); + +lines.Any(i => i.Contains("Pure.DI")).ShouldBeFalse(result.ToString()); diff --git a/CSharpInteractive.Tests/UsageScenarios/Comments/DotNetRemoveReferenceScenario.txt b/CSharpInteractive.Tests/UsageScenarios/Comments/DotNetRemoveReferenceScenario.txt new file mode 100644 index 0000000..2c088d7 --- /dev/null +++ b/CSharpInteractive.Tests/UsageScenarios/Comments/DotNetRemoveReferenceScenario.txt @@ -0,0 +1,30 @@ +using HostApi; + +new DotNetNew() + .WithTemplateName("classlib") + .WithName("MyLib") + .WithForce(true) + .Build().EnsureSuccess(); + +new DotNetNew() + .WithTemplateName("xunit") + .WithName("MyTests") + .WithForce(true) + .Build().EnsureSuccess(); + +new DotNetAddReference() + .WithProject(Path.Combine("MyTests", "MyTests.csproj")) + .WithReferences(Path.Combine("MyLib", "MyLib.csproj")) + .Run().EnsureSuccess(); + +var result = new DotNetRemoveReference() + .WithProject(Path.Combine("MyTests", "MyTests.csproj")) + .WithReferences(Path.Combine("MyLib", "MyLib.csproj")) + .Run().EnsureSuccess(); + +var lines = new List(); +new DotNetListReference() + .WithProject(Path.Combine("MyTests", "MyTests.csproj")) + .Run(output => lines.Add(output.Line)); + +lines.Any(i => i.Contains("MyLib.csproj")).ShouldBeFalse(result.ToString()); diff --git a/CSharpInteractive.Tests/UsageScenarios/Comments/DotNetRestoreScenario.txt b/CSharpInteractive.Tests/UsageScenarios/Comments/DotNetRestoreScenario.txt new file mode 100644 index 0000000..6458012 --- /dev/null +++ b/CSharpInteractive.Tests/UsageScenarios/Comments/DotNetRestoreScenario.txt @@ -0,0 +1,16 @@ +// Adds the namespace "HostApi" to use .NET build API +using HostApi; + +// Creates a new library project, running a command like: "dotnet new classlib -n MyLib --force" +var result = new DotNetNew() + .WithTemplateName("classlib") + .WithName("MyLib") + .WithForce(true) + .Build().EnsureSuccess(); + +result.ExitCode.ShouldBe(0); + +// Restore the project, running a command like: "dotnet restore" from the directory "MyLib" +result = new DotNetRestore() + .WithWorkingDirectory("MyLib") + .Build().EnsureSuccess(); diff --git a/CSharpInteractive.Tests/UsageScenarios/Comments/DotNetRunScenario.txt b/CSharpInteractive.Tests/UsageScenarios/Comments/DotNetRunScenario.txt new file mode 100644 index 0000000..f5b8b8a --- /dev/null +++ b/CSharpInteractive.Tests/UsageScenarios/Comments/DotNetRunScenario.txt @@ -0,0 +1,23 @@ +// Adds the namespace "HostApi" to use .NET build API +using HostApi; + +// Creates a new console project, running a command like: "dotnet new console -n MyApp --force" +var result = new DotNetNew() + .WithTemplateName("console") + .WithName("MyApp") + .WithForce(true) + .Build().EnsureSuccess(); + +result.ExitCode.ShouldBe(0); + +// Runs the console project using a command like: "dotnet run" from the directory "MyApp" +var stdOut = new List(); +result = new DotNetRun() + .WithWorkingDirectory("MyApp") + .Build(message => stdOut.Add(message.Text)) + .EnsureSuccess(); + +result.ExitCode.ShouldBe(0); + +// Checks StdOut +stdOut.ShouldBe(new[] {"Hello, World!"}); diff --git a/CSharpInteractive.Tests/UsageScenarios/Comments/DotNetScenario.txt b/CSharpInteractive.Tests/UsageScenarios/Comments/DotNetScenario.txt new file mode 100644 index 0000000..93e9017 --- /dev/null +++ b/CSharpInteractive.Tests/UsageScenarios/Comments/DotNetScenario.txt @@ -0,0 +1,19 @@ +// Adds the namespace "HostApi" to use .NET build API +using HostApi; + +// Creates a new console project, running a command like: "dotnet new console -n MyApp --force" +new DotNetNew() + .WithTemplateName("console") + .WithName("MyApp") + .WithForce(true) + .Build().EnsureSuccess(); + +var tempDirectory = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); +new DotNetPublish() + .WithWorkingDirectory("MyApp") + .WithOutput(tempDirectory) + .Build().EnsureSuccess(); + +new DotNet() + .WithPathToApplication(Path.Combine(tempDirectory, "MyApp.dll")) + .Run().EnsureSuccess(); diff --git a/CSharpInteractive.Tests/UsageScenarios/Comments/DotNetTestScenario.txt b/CSharpInteractive.Tests/UsageScenarios/Comments/DotNetTestScenario.txt new file mode 100644 index 0000000..dbf9f2f --- /dev/null +++ b/CSharpInteractive.Tests/UsageScenarios/Comments/DotNetTestScenario.txt @@ -0,0 +1,22 @@ +// Adds the namespace "HostApi" to use .NET build API +using HostApi; + +// Creates a new test project, running a command like: "dotnet new mstest -n MyTests --force" +var result = new DotNetNew() + .WithTemplateName("mstest") + .WithName("MyTests") + .WithForce(true) + .Build().EnsureSuccess(); + +result.ExitCode.ShouldBe(0); + +// Runs tests via a command like: "dotnet test" from the directory "MyTests" +result = new DotNetTest() + .WithWorkingDirectory("MyTests") + .Build() + .EnsureSuccess(); + +// The "result" variable provides details about a build +result.ExitCode.ShouldBe(0, result.ToString()); +result.Summary.Tests.ShouldBe(1, result.ToString()); +result.Tests.Count(test => test.State == TestState.Finished).ShouldBe(1, result.ToString()); diff --git a/CSharpInteractive.Tests/UsageScenarios/Comments/DotNetTestWithDotCoverScenario.txt b/CSharpInteractive.Tests/UsageScenarios/Comments/DotNetTestWithDotCoverScenario.txt new file mode 100644 index 0000000..7d80fc1 --- /dev/null +++ b/CSharpInteractive.Tests/UsageScenarios/Comments/DotNetTestWithDotCoverScenario.txt @@ -0,0 +1,51 @@ +// Adds the namespace "HostApi" to use .NET build API +using HostApi; + +// Creates a new test project, running a command like: "dotnet new mstest -n MyTests --force" +new DotNetNew() + .WithTemplateName("mstest") + .WithName("MyTests") + .WithForce(true) + .Run().EnsureSuccess(); + +// Creates the tool manifest and installs the dotCover tool locally +// It is better to run the following 2 commands manually +// and commit these changes to a source control +new DotNetNew() + .WithTemplateName("tool-manifest") + .Run().EnsureSuccess(); + +new DotNetCustom("tool", "install", "--local", "JetBrains.dotCover.GlobalTool") + .Run().EnsureSuccess(); + +// Creates a test command +var test = new DotNetTest() + .WithProject("MyTests"); + +var dotCoverSnapshot = Path.Combine("MyTests", "dotCover.dcvr"); +var dotCoverReport = Path.Combine("MyTests", "dotCover.html"); +// Modifies the test command by putting "dotCover" in front of all arguments +// to have something like "dotnet dotcover test ..." +// and adding few specific arguments to the end +var testUnderDotCover = test.Customize(cmd => + cmd.ClearArgs() + + "dotcover" + + cmd.Args + + $"--dcOutput={dotCoverSnapshot}" + + "--dcFilters=+:module=TeamCity.CSharpInteractive.HostApi;+:module=dotnet-csi" + + "--dcAttributeFilters=System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage"); + +// Runs tests under dotCover via a command like: "dotnet dotcover test ..." +var result = testUnderDotCover + .Build().EnsureSuccess(); + +// The "result" variable provides details about a build +result.ExitCode.ShouldBe(0, result.ToString()); +result.Tests.Count(i => i.State == TestState.Finished).ShouldBe(1, result.ToString()); + +// Generates a HTML code coverage report. +new DotNetCustom("dotCover", "report", $"--source={dotCoverSnapshot}", $"--output={dotCoverReport}", "--reportType=HTML") + .Run().EnsureSuccess(); + +// Check for a dotCover report +File.Exists(dotCoverReport).ShouldBeTrue(); diff --git a/CSharpInteractive.Tests/UsageScenarios/Comments/DotNetToolRestoreScenario.txt b/CSharpInteractive.Tests/UsageScenarios/Comments/DotNetToolRestoreScenario.txt new file mode 100644 index 0000000..5ea03c5 --- /dev/null +++ b/CSharpInteractive.Tests/UsageScenarios/Comments/DotNetToolRestoreScenario.txt @@ -0,0 +1,18 @@ +// Adds the namespace "HostApi" to use .NET build API +using HostApi; + +var projectDir = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString()[..4]); +Directory.CreateDirectory(projectDir); + +// Creates a local tool manifest +new DotNetNew() + .WithTemplateName("tool-manifest") + .WithWorkingDirectory(projectDir) + .Run() + .EnsureSuccess(); + +// Restore local tools +new DotNetToolRestore() + .WithWorkingDirectory(projectDir) + .Run() + .EnsureSuccess(); diff --git a/CSharpInteractive.Tests/UsageScenarios/Comments/DotNetVSTestScenario.txt b/CSharpInteractive.Tests/UsageScenarios/Comments/DotNetVSTestScenario.txt new file mode 100644 index 0000000..17eeb2c --- /dev/null +++ b/CSharpInteractive.Tests/UsageScenarios/Comments/DotNetVSTestScenario.txt @@ -0,0 +1,31 @@ +// Adds the namespace "HostApi" to use .NET build API +using HostApi; + +// Creates a new test project, running a command like: "dotnet new mstest -n MyTests --force" +var result = new DotNetNew() + .WithTemplateName("mstest") + .WithName("MyTests") + .WithForce(true) + .Build().EnsureSuccess(); + +result.ExitCode.ShouldBe(0, result.ToString()); + +// Builds the test project, running a command like: "dotnet build -c Release" from the directory "MyTests" +result = new DotNetBuild() + .WithWorkingDirectory("MyTests") + .WithConfiguration("Release") + .WithOutput("MyOutput") + .Build().EnsureSuccess(); + +result.ExitCode.ShouldBe(0, result.ToString()); + +// Runs tests via a command like: "dotnet vstest" from the directory "MyTests" +result = new VSTest() + .AddTestFileNames(Path.Combine("MyOutput", "MyTests.dll")) + .WithWorkingDirectory("MyTests") + .Build().EnsureSuccess(); + +// The "result" variable provides details about a build +result.ExitCode.ShouldBe(0, result.ToString()); +result.Summary.Tests.ShouldBe(1, result.ToString()); +result.Tests.Count(test => test.State == TestState.Finished).ShouldBe(1, result.ToString()); diff --git a/CSharpInteractive.Tests/UsageScenarios/Comments/GetServiceScenario.txt b/CSharpInteractive.Tests/UsageScenarios/Comments/GetServiceScenario.txt new file mode 100644 index 0000000..d64ed0f --- /dev/null +++ b/CSharpInteractive.Tests/UsageScenarios/Comments/GetServiceScenario.txt @@ -0,0 +1,4 @@ +GetService(); + +var serviceProvider = GetService(); +serviceProvider.GetService(typeof(INuGet)); diff --git a/CSharpInteractive.Tests/UsageScenarios/Comments/HostScenario.txt b/CSharpInteractive.Tests/UsageScenarios/Comments/HostScenario.txt new file mode 100644 index 0000000..d7e1ca6 --- /dev/null +++ b/CSharpInteractive.Tests/UsageScenarios/Comments/HostScenario.txt @@ -0,0 +1,2 @@ +var packages = Host.GetService(); +Host.WriteLine("Hello"); diff --git a/CSharpInteractive.Tests/UsageScenarios/Comments/LogErrorScenario.txt b/CSharpInteractive.Tests/UsageScenarios/Comments/LogErrorScenario.txt new file mode 100644 index 0000000..eede6e0 --- /dev/null +++ b/CSharpInteractive.Tests/UsageScenarios/Comments/LogErrorScenario.txt @@ -0,0 +1 @@ +Error("Error info", "Error identifier"); diff --git a/CSharpInteractive.Tests/UsageScenarios/Comments/LogInfoScenario.txt b/CSharpInteractive.Tests/UsageScenarios/Comments/LogInfoScenario.txt new file mode 100644 index 0000000..d2d25ec --- /dev/null +++ b/CSharpInteractive.Tests/UsageScenarios/Comments/LogInfoScenario.txt @@ -0,0 +1 @@ +Info("Some info"); diff --git a/CSharpInteractive.Tests/UsageScenarios/Comments/LogTraceScenario.txt b/CSharpInteractive.Tests/UsageScenarios/Comments/LogTraceScenario.txt new file mode 100644 index 0000000..3761cd7 --- /dev/null +++ b/CSharpInteractive.Tests/UsageScenarios/Comments/LogTraceScenario.txt @@ -0,0 +1 @@ +Trace("Some trace info"); diff --git a/CSharpInteractive.Tests/UsageScenarios/Comments/LogWarningScenario.txt b/CSharpInteractive.Tests/UsageScenarios/Comments/LogWarningScenario.txt new file mode 100644 index 0000000..063bbae --- /dev/null +++ b/CSharpInteractive.Tests/UsageScenarios/Comments/LogWarningScenario.txt @@ -0,0 +1 @@ +Warning("Warning info"); diff --git a/CSharpInteractive.Tests/UsageScenarios/Comments/MSBuildScenario.txt b/CSharpInteractive.Tests/UsageScenarios/Comments/MSBuildScenario.txt new file mode 100644 index 0000000..5f11c8e --- /dev/null +++ b/CSharpInteractive.Tests/UsageScenarios/Comments/MSBuildScenario.txt @@ -0,0 +1,24 @@ +// Adds the namespace "HostApi" to use .NET build API +using HostApi; + +// Creates a new library project, running a command like: "dotnet new classlib -n MyLib --force" +var result = new DotNetNew() + .WithTemplateName("classlib") + .WithName("MyLib") + .WithForce(true) + .Build().EnsureSuccess(); + +result.ExitCode.ShouldBe(0, result.ToString()); + +// Builds the library project, running a command like: "dotnet msbuild /t:Build -restore /p:configuration=Release -verbosity=detailed" from the directory "MyLib" +result = new MSBuild() + .WithWorkingDirectory("MyLib") + .WithTarget("Build") + .WithRestore(true) + .AddProps(("configuration", "Release")) + .WithVerbosity(DotNetVerbosity.Detailed) + .Build().EnsureSuccess(); + +// The "result" variable provides details about a build +result.Errors.Any(message => message.State == BuildMessageState.StdError).ShouldBeFalse(result.ToString()); +result.ExitCode.ShouldBe(0, result.ToString()); diff --git a/CSharpInteractive.Tests/UsageScenarios/Comments/NuGetRestoreAdvanced.txt b/CSharpInteractive.Tests/UsageScenarios/Comments/NuGetRestoreAdvanced.txt new file mode 100644 index 0000000..9aae8ff --- /dev/null +++ b/CSharpInteractive.Tests/UsageScenarios/Comments/NuGetRestoreAdvanced.txt @@ -0,0 +1,13 @@ +// Adds the namespace "HostApi" to use INuGet +using HostApi; + +var packagesPath = Path.Combine( + Path.GetTempPath(), + Guid.NewGuid().ToString()[..4]); + +var settings = new NuGetRestoreSettings("IoC.Container") + .WithVersionRange(VersionRange.Parse("[1.3, 1.3.8)")) + .WithTargetFrameworkMoniker("net5.0") + .WithPackagesPath(packagesPath); + +IEnumerable packages = GetService().Restore(settings); diff --git a/CSharpInteractive.Tests/UsageScenarios/Comments/NuGetRestoreScenario.txt b/CSharpInteractive.Tests/UsageScenarios/Comments/NuGetRestoreScenario.txt new file mode 100644 index 0000000..f03990e --- /dev/null +++ b/CSharpInteractive.Tests/UsageScenarios/Comments/NuGetRestoreScenario.txt @@ -0,0 +1,5 @@ +// Adds the namespace "HostApi" to use INuGet +using HostApi; + +IEnumerable packages = GetService() + .Restore(new NuGetRestoreSettings("IoC.Container").WithVersionRange(VersionRange.All)); diff --git a/CSharpInteractive.Tests/UsageScenarios/Comments/PropsScenario.txt b/CSharpInteractive.Tests/UsageScenarios/Comments/PropsScenario.txt new file mode 100644 index 0000000..d01ce03 --- /dev/null +++ b/CSharpInteractive.Tests/UsageScenarios/Comments/PropsScenario.txt @@ -0,0 +1,6 @@ +WriteLine(Props["version"]); +WriteLine(Props.Get("configuration", "Release")); + +// Some CI/CDs have integration of these properties. +// For example in TeamCity this property with all changes will be available in the next TeamCity steps. +Props["version"] = "1.1.6"; diff --git a/CSharpInteractive.Tests/UsageScenarios/Comments/ServiceCollectionScenario.txt b/CSharpInteractive.Tests/UsageScenarios/Comments/ServiceCollectionScenario.txt new file mode 100644 index 0000000..e1b1b91 --- /dev/null +++ b/CSharpInteractive.Tests/UsageScenarios/Comments/ServiceCollectionScenario.txt @@ -0,0 +1,20 @@ +public void Run() +{ + var serviceProvider = + GetService() + .AddTransient() + .BuildServiceProvider(); + + var myTask = serviceProvider.GetRequiredService(); + var exitCode = myTask.Run(); + exitCode.ShouldBe(0); +} + +private class MyTask(ICommandLineRunner runner) +{ + public int? Run() => runner + .Run(new CommandLine("whoami")) + .EnsureSuccess() + .ExitCode; +} + diff --git a/CSharpInteractive.Tests/UsageScenarios/Comments/TeamCityServiceMessagesScenario.txt b/CSharpInteractive.Tests/UsageScenarios/Comments/TeamCityServiceMessagesScenario.txt new file mode 100644 index 0000000..6961188 --- /dev/null +++ b/CSharpInteractive.Tests/UsageScenarios/Comments/TeamCityServiceMessagesScenario.txt @@ -0,0 +1,18 @@ +// Adds a namespace to use ITeamCityWriter +using JetBrains.TeamCity.ServiceMessages.Write.Special; + +using var writer = GetService(); +using (var tests = writer.OpenBlock("My Tests")) +{ + using (var test = tests.OpenTest("Test1")) + { + test.WriteStdOutput("Hello"); + test.WriteImage("TestsResults/Test1Screenshot.jpg", "Screenshot"); + test.WriteDuration(TimeSpan.FromMilliseconds(10)); + } + + using (var test = tests.OpenTest("Test2")) + { + test.WriteIgnored("Some reason"); + } +} diff --git a/CSharpInteractive.Tests/UsageScenarios/Comments/WriteEmptyLineScenario.txt b/CSharpInteractive.Tests/UsageScenarios/Comments/WriteEmptyLineScenario.txt new file mode 100644 index 0000000..448b040 --- /dev/null +++ b/CSharpInteractive.Tests/UsageScenarios/Comments/WriteEmptyLineScenario.txt @@ -0,0 +1 @@ +WriteLine(); diff --git a/CSharpInteractive.Tests/UsageScenarios/Comments/WriteLineScenario.txt b/CSharpInteractive.Tests/UsageScenarios/Comments/WriteLineScenario.txt new file mode 100644 index 0000000..7f4afc1 --- /dev/null +++ b/CSharpInteractive.Tests/UsageScenarios/Comments/WriteLineScenario.txt @@ -0,0 +1 @@ +WriteLine("Hello"); diff --git a/CSharpInteractive.Tests/UsageScenarios/Comments/WriteLineWithColourScenario.txt b/CSharpInteractive.Tests/UsageScenarios/Comments/WriteLineWithColourScenario.txt new file mode 100644 index 0000000..15d058b --- /dev/null +++ b/CSharpInteractive.Tests/UsageScenarios/Comments/WriteLineWithColourScenario.txt @@ -0,0 +1 @@ +WriteLine("Hello", Header); diff --git a/CSharpInteractive.Tests/UsageScenarios/DotNetAddPackageScenario.cs b/CSharpInteractive.Tests/UsageScenarios/DotNetAddPackageScenario.cs new file mode 100644 index 0000000..0f513d2 --- /dev/null +++ b/CSharpInteractive.Tests/UsageScenarios/DotNetAddPackageScenario.cs @@ -0,0 +1,45 @@ +// ReSharper disable StringLiteralTypo +// ReSharper disable ObjectCreationAsStatement +// ReSharper disable ReturnValueOfPureMethodIsNotUsed +// ReSharper disable CommentTypo + +namespace CSharpInteractive.Tests.UsageScenarios; + +using HostApi; + +[CollectionDefinition("Integration", DisableParallelization = true)] +[Trait("Integration", "True")] +public class DotNetAddPackageScenario : BaseScenario +{ + [Fact] + public void Run() + { + // $visible=true + // $tag=07 .NET CLI + // $priority=01 + // $description=Adding a NuGet package + // { + // ## using HostApi; + + new DotNetNew() + .WithTemplateName("classlib") + .WithName("MyLib") + .WithForce(true) + .Build().EnsureSuccess(); + + var result = new DotNetAddPackage() + .WithWorkingDirectory("MyLib") + .WithPackage("Pure.DI") + .Run().EnsureSuccess(); + + var lines = new List(); + new DotNetListPackage() + .WithWorkingDirectory("MyLib") + .WithVerbosity(DotNetVerbosity.Minimal) + .Run(output => lines.Add(output.Line)); + + lines.Any(i => i.Contains("Pure.DI")).ShouldBeTrue(result.ToString()); + // } + result.ExitCode.ShouldBe(0, result.ToString()); + } +} \ No newline at end of file diff --git a/CSharpInteractive.Tests/UsageScenarios/DotNetAddReferenceScenario.cs b/CSharpInteractive.Tests/UsageScenarios/DotNetAddReferenceScenario.cs new file mode 100644 index 0000000..e6ccc20 --- /dev/null +++ b/CSharpInteractive.Tests/UsageScenarios/DotNetAddReferenceScenario.cs @@ -0,0 +1,50 @@ +// ReSharper disable StringLiteralTypo +// ReSharper disable ObjectCreationAsStatement +// ReSharper disable ReturnValueOfPureMethodIsNotUsed +// ReSharper disable CommentTypo + +namespace CSharpInteractive.Tests.UsageScenarios; + +using HostApi; + +[CollectionDefinition("Integration", DisableParallelization = true)] +[Trait("Integration", "True")] +public class DotNetAddReferenceScenario : BaseScenario +{ + [Fact] + public void Run() + { + // $visible=true + // $tag=07 .NET CLI + // $priority=01 + // $description=Adding a NuGet package + // { + // ## using HostApi; + + new DotNetNew() + .WithTemplateName("classlib") + .WithName("MyLib") + .WithForce(true) + .Build().EnsureSuccess(); + + new DotNetNew() + .WithTemplateName("xunit") + .WithName("MyTests") + .WithForce(true) + .Build().EnsureSuccess(); + + var result = new DotNetAddReference() + .WithProject(Path.Combine("MyTests", "MyTests.csproj")) + .WithReferences(Path.Combine("MyLib", "MyLib.csproj")) + .Run().EnsureSuccess(); + + var lines = new List(); + new DotNetListReference() + .WithProject(Path.Combine("MyTests", "MyTests.csproj")) + .Run(output => lines.Add(output.Line)); + + lines.Any(i => i.Contains("MyLib.csproj")).ShouldBeTrue(result.ToString()); + // } + result.ExitCode.ShouldBe(0, result.ToString()); + } +} \ No newline at end of file diff --git a/CSharpInteractive.Tests/UsageScenarios/DotNetBuildScenario.cs b/CSharpInteractive.Tests/UsageScenarios/DotNetBuildScenario.cs index afea731..4af68eb 100644 --- a/CSharpInteractive.Tests/UsageScenarios/DotNetBuildScenario.cs +++ b/CSharpInteractive.Tests/UsageScenarios/DotNetBuildScenario.cs @@ -22,33 +22,32 @@ public void Run() // Adds the namespace "HostApi" to use .NET build API // ## using HostApi; - // Creates a new library project, running a command like: "dotnet new classlib -n MyLib --force" + // Creates a new test project, running a command like: "dotnet new xunit -n MyTests --force" new DotNetNew() .WithTemplateName("xunit") - .WithName("MyLib") + .WithName("MyTests") .WithForce(true) .Build().EnsureSuccess(); - // Builds the library project, running a command like: "dotnet build" from the directory "MyLib" + // Builds this project, running a command like: "dotnet build" from the directory "MyLib" var messages = new List(); var result = new DotNetBuild() - .WithWorkingDirectory("MyLib") + .WithWorkingDirectory("MyTests") .Build(message => messages.Add(message)).EnsureSuccess(); // The "result" variable provides details about a build messages.Count.ShouldBeGreaterThan(0, result.ToString()); - result.Errors.Any(message => message.State == BuildMessageState.StdError).ShouldBeFalse(); - result.ExitCode.ShouldBe(0); + result.Errors.Any(message => message.State == BuildMessageState.StdError).ShouldBeFalse(result.ToString()); + result.ExitCode.ShouldBe(0, result.ToString()); // Runs tests in docker result = new DotNetTest() - .WithWorkingDirectory("MyLib") - .Build() - .EnsureSuccess(); + .WithWorkingDirectory("MyTests") + .Build().EnsureSuccess(); // } - result.ExitCode.ShouldBe(0); - result.Summary.Tests.ShouldBe(1); - result.Tests.Count(test => test.State == TestState.Finished).ShouldBe(1); + result.ExitCode.ShouldBe(0, result.ToString()); + result.Summary.Tests.ShouldBe(1, result.ToString()); + result.Tests.Count(test => test.State == TestState.Finished).ShouldBe(1, result.ToString()); } } \ No newline at end of file diff --git a/CSharpInteractive.Tests/UsageScenarios/DotNetExecScenario.cs b/CSharpInteractive.Tests/UsageScenarios/DotNetExecScenario.cs new file mode 100644 index 0000000..77d0461 --- /dev/null +++ b/CSharpInteractive.Tests/UsageScenarios/DotNetExecScenario.cs @@ -0,0 +1,44 @@ +// ReSharper disable StringLiteralTypo +// ReSharper disable ObjectCreationAsStatement +// ReSharper disable ReturnValueOfPureMethodIsNotUsed + +namespace CSharpInteractive.Tests.UsageScenarios; + +using System.Diagnostics.CodeAnalysis; +using HostApi; + +[CollectionDefinition("Integration", DisableParallelization = true)] +[Trait("Integration", "True")] +[SuppressMessage("Performance", "CA1861:Avoid constant arrays as arguments")] +public class DotNetExecScenario : BaseScenario +{ + [Fact] + public void Run() + { + // $visible=true + // $tag=07 .NET CLI + // $priority=01 + // $description=Execute a dotnet application + // { + // Adds the namespace "HostApi" to use .NET build API + // ## using HostApi; + + // Creates a new console project, running a command like: "dotnet new console -n MyApp --force" + new DotNetNew() + .WithTemplateName("console") + .WithName("MyApp") + .WithForce(true) + .Build().EnsureSuccess(); + + var tempDirectory = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); + new DotNetPublish() + .WithWorkingDirectory("MyApp") + .WithOutput(tempDirectory) + .Build().EnsureSuccess(); + + new DotNetExec() + .WithPathToApplication(Path.Combine(tempDirectory, "MyApp.dll")) + .Run().EnsureSuccess(); + // } + } +} \ No newline at end of file diff --git a/CSharpInteractive.Tests/UsageScenarios/DotNetListPackageScenario.cs b/CSharpInteractive.Tests/UsageScenarios/DotNetListPackageScenario.cs new file mode 100644 index 0000000..c6e2836 --- /dev/null +++ b/CSharpInteractive.Tests/UsageScenarios/DotNetListPackageScenario.cs @@ -0,0 +1,45 @@ +// ReSharper disable StringLiteralTypo +// ReSharper disable ObjectCreationAsStatement +// ReSharper disable ReturnValueOfPureMethodIsNotUsed +// ReSharper disable CommentTypo + +namespace CSharpInteractive.Tests.UsageScenarios; + +using HostApi; + +[CollectionDefinition("Integration", DisableParallelization = true)] +[Trait("Integration", "True")] +public class DotNetListPackageScenario : BaseScenario +{ + [Fact] + public void Run() + { + // $visible=true + // $tag=07 .NET CLI + // $priority=01 + // $description=NuGet package listing + // { + // ## using HostApi; + + new DotNetNew() + .WithTemplateName("classlib") + .WithName("MyLib") + .WithForce(true) + .Build().EnsureSuccess(); + + new DotNetAddPackage() + .WithWorkingDirectory("MyLib") + .WithPackage("Pure.DI") + .Run().EnsureSuccess(); + + var lines = new List(); + var result = new DotNetListPackage() + .WithWorkingDirectory("MyLib") + .WithVerbosity(DotNetVerbosity.Minimal) + .Run(output => lines.Add(output.Line)); + + lines.Any(i => i.Contains("Pure.DI")).ShouldBeTrue(result.ToString()); + // } + result.ExitCode.ShouldBe(0, result.ToString()); + } +} \ No newline at end of file diff --git a/CSharpInteractive.Tests/UsageScenarios/DotNetListReferenceScenario.cs b/CSharpInteractive.Tests/UsageScenarios/DotNetListReferenceScenario.cs new file mode 100644 index 0000000..346af6f --- /dev/null +++ b/CSharpInteractive.Tests/UsageScenarios/DotNetListReferenceScenario.cs @@ -0,0 +1,50 @@ +// ReSharper disable StringLiteralTypo +// ReSharper disable ObjectCreationAsStatement +// ReSharper disable ReturnValueOfPureMethodIsNotUsed +// ReSharper disable CommentTypo + +namespace CSharpInteractive.Tests.UsageScenarios; + +using HostApi; + +[CollectionDefinition("Integration", DisableParallelization = true)] +[Trait("Integration", "True")] +public class DotNetListReferenceScenario : BaseScenario +{ + [Fact] + public void Run() + { + // $visible=true + // $tag=07 .NET CLI + // $priority=01 + // $description=Project reference listing + // { + // ## using HostApi; + + new DotNetNew() + .WithTemplateName("classlib") + .WithName("MyLib") + .WithForce(true) + .Build().EnsureSuccess(); + + new DotNetNew() + .WithTemplateName("xunit") + .WithName("MyTests") + .WithForce(true) + .Build().EnsureSuccess(); + + new DotNetAddReference() + .WithProject(Path.Combine("MyTests", "MyTests.csproj")) + .WithReferences(Path.Combine("MyLib", "MyLib.csproj")) + .Run().EnsureSuccess(); + + var lines = new List(); + var result = new DotNetListReference() + .WithProject(Path.Combine("MyTests", "MyTests.csproj")) + .Run(output => lines.Add(output.Line)); + + lines.Any(i => i.Contains("MyLib.csproj")).ShouldBeTrue(result.ToString()); + // } + result.ExitCode.ShouldBe(0, result.ToString()); + } +} \ No newline at end of file diff --git a/CSharpInteractive.Tests/UsageScenarios/DotNetRemovePackageScenario.cs b/CSharpInteractive.Tests/UsageScenarios/DotNetRemovePackageScenario.cs new file mode 100644 index 0000000..1afa226 --- /dev/null +++ b/CSharpInteractive.Tests/UsageScenarios/DotNetRemovePackageScenario.cs @@ -0,0 +1,50 @@ +// ReSharper disable StringLiteralTypo +// ReSharper disable ObjectCreationAsStatement +// ReSharper disable ReturnValueOfPureMethodIsNotUsed +// ReSharper disable CommentTypo + +namespace CSharpInteractive.Tests.UsageScenarios; + +using HostApi; + +[CollectionDefinition("Integration", DisableParallelization = true)] +[Trait("Integration", "True")] +public class DotNetRemovePackageScenario : BaseScenario +{ + [Fact] + public void Run() + { + // $visible=true + // $tag=07 .NET CLI + // $priority=01 + // $description=Removing a NuGet package + // { + // ## using HostApi; + + new DotNetNew() + .WithTemplateName("classlib") + .WithName("MyLib") + .WithForce(true) + .Build().EnsureSuccess(); + + new DotNetAddPackage() + .WithWorkingDirectory("MyLib") + .WithPackage("Pure.DI") + .Run().EnsureSuccess(); + + var result = new DotNetRemovePackage() + .WithWorkingDirectory("MyLib") + .WithPackage("Pure.DI") + .Run().EnsureSuccess(); + + var lines = new List(); + new DotNetListPackage() + .WithWorkingDirectory("MyLib") + .WithVerbosity(DotNetVerbosity.Minimal) + .Run(output => lines.Add(output.Line)); + + lines.Any(i => i.Contains("Pure.DI")).ShouldBeFalse(result.ToString()); + // } + result.ExitCode.ShouldBe(0, result.ToString()); + } +} \ No newline at end of file diff --git a/CSharpInteractive.Tests/UsageScenarios/DotNetRemoveReferenceScenario.cs b/CSharpInteractive.Tests/UsageScenarios/DotNetRemoveReferenceScenario.cs new file mode 100644 index 0000000..1bd0ffe --- /dev/null +++ b/CSharpInteractive.Tests/UsageScenarios/DotNetRemoveReferenceScenario.cs @@ -0,0 +1,55 @@ +// ReSharper disable StringLiteralTypo +// ReSharper disable ObjectCreationAsStatement +// ReSharper disable ReturnValueOfPureMethodIsNotUsed +// ReSharper disable CommentTypo + +namespace CSharpInteractive.Tests.UsageScenarios; + +using HostApi; + +[CollectionDefinition("Integration", DisableParallelization = true)] +[Trait("Integration", "True")] +public class DotNetRemoveReferenceScenario : BaseScenario +{ + [Fact] + public void Run() + { + // $visible=true + // $tag=07 .NET CLI + // $priority=01 + // $description=Adding a project reference + // { + // ## using HostApi; + + new DotNetNew() + .WithTemplateName("classlib") + .WithName("MyLib") + .WithForce(true) + .Build().EnsureSuccess(); + + new DotNetNew() + .WithTemplateName("xunit") + .WithName("MyTests") + .WithForce(true) + .Build().EnsureSuccess(); + + new DotNetAddReference() + .WithProject(Path.Combine("MyTests", "MyTests.csproj")) + .WithReferences(Path.Combine("MyLib", "MyLib.csproj")) + .Run().EnsureSuccess(); + + var result = new DotNetRemoveReference() + .WithProject(Path.Combine("MyTests", "MyTests.csproj")) + .WithReferences(Path.Combine("MyLib", "MyLib.csproj")) + .Run().EnsureSuccess(); + + var lines = new List(); + new DotNetListReference() + .WithProject(Path.Combine("MyTests", "MyTests.csproj")) + .Run(output => lines.Add(output.Line)); + + lines.Any(i => i.Contains("MyLib.csproj")).ShouldBeFalse(result.ToString()); + // } + result.ExitCode.ShouldBe(0, result.ToString()); + } +} \ No newline at end of file diff --git a/CSharpInteractive.Tests/UsageScenarios/DotNetScenario.cs b/CSharpInteractive.Tests/UsageScenarios/DotNetScenario.cs new file mode 100644 index 0000000..2c0eb00 --- /dev/null +++ b/CSharpInteractive.Tests/UsageScenarios/DotNetScenario.cs @@ -0,0 +1,44 @@ +// ReSharper disable StringLiteralTypo +// ReSharper disable ObjectCreationAsStatement +// ReSharper disable ReturnValueOfPureMethodIsNotUsed + +namespace CSharpInteractive.Tests.UsageScenarios; + +using System.Diagnostics.CodeAnalysis; +using HostApi; + +[CollectionDefinition("Integration", DisableParallelization = true)] +[Trait("Integration", "True")] +[SuppressMessage("Performance", "CA1861:Avoid constant arrays as arguments")] +public class DotNetScenario : BaseScenario +{ + [Fact] + public void Run() + { + // $visible=true + // $tag=07 .NET CLI + // $priority=01 + // $description=Run a dotnet application + // { + // Adds the namespace "HostApi" to use .NET build API + // ## using HostApi; + + // Creates a new console project, running a command like: "dotnet new console -n MyApp --force" + new DotNetNew() + .WithTemplateName("console") + .WithName("MyApp") + .WithForce(true) + .Build().EnsureSuccess(); + + var tempDirectory = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); + new DotNetPublish() + .WithWorkingDirectory("MyApp") + .WithOutput(tempDirectory) + .Build().EnsureSuccess(); + + new DotNet() + .WithPathToApplication(Path.Combine(tempDirectory, "MyApp.dll")) + .Run().EnsureSuccess(); + // } + } +} \ No newline at end of file diff --git a/README.md b/README.md index 0d9fec1..bce59a0 100644 --- a/README.md +++ b/README.md @@ -150,19 +150,26 @@ The created project contains 2 entry points: - [Build a project in a docker container](#build-a-project-in-a-docker-container) - [Running in docker](#running-in-docker) - .NET CLI + - [Adding a NuGet package](#adding-a-nuget-package) + - [Adding a NuGet package](#adding-a-nuget-package) - [Build a project](#build-a-project) - [Build a project using MSBuild](#build-a-project-using-msbuild) - [Clean a project](#clean-a-project) + - [Execute a dotnet application](#execute-a-dotnet-application) + - [NuGet package listing](#nuget-package-listing) - [Pack a project](#pack-a-project) - [Publish a project](#publish-a-project) + - [Removing a NuGet package](#removing-a-nuget-package) - [Restore a project](#restore-a-project) - [Restore local tools](#restore-local-tools) - [Run a custom .NET command](#run-a-custom-.net-command) + - [Run a dotnet application](#run-a-dotnet-application) - [Run a project](#run-a-project) - [Run tests under dotCover](#run-tests-under-dotcover) - [Test a project](#test-a-project) - [Test a project using the MSBuild VSTest target](#test-a-project-using-the-msbuild-vstest-target) - [Test an assembly](#test-an-assembly) + - [Run C# script](#run-c#-script) - [Shuts down build servers](#shuts-down-build-servers) - TeamCity API - [TeamCity integration via service messages](#teamcity-integration-via-service-messages) @@ -530,8 +537,6 @@ int? exitCode = new CommandLine("cmd", "/c", "TIMEOUT", "/T", "120") .Run(default, TimeSpan.FromMilliseconds(1)) .EnsureSuccess() .ExitCode; - -exitCode.HasValue.ShouldBeFalse(); ``` @@ -566,10 +571,6 @@ var result = dockerRun .Build() .EnsureSuccess(); -// The "result" variable provides details about a build -result.Errors.Any(message => message.State == BuildMessageState.StdError).ShouldBeFalse(); -result.ExitCode.ShouldBe(0); - string ToAbsoluteLinuxPath(string path) => "/" + path.Replace(":", "").Replace('\\', '/'); ``` @@ -596,6 +597,69 @@ var result = new DockerRun(cmd, "mcr.microsoft.com/dotnet/sdk") +### Adding a NuGet package + + + +``` CSharp +using HostApi; + +new DotNetNew() + .WithTemplateName("classlib") + .WithName("MyLib") + .WithForce(true) + .Build().EnsureSuccess(); + +var result = new DotNetAddPackage() + .WithWorkingDirectory("MyLib") + .WithPackage("Pure.DI") + .Run().EnsureSuccess(); + +var lines = new List(); +new DotNetListPackage() + .WithWorkingDirectory("MyLib") + .WithVerbosity(DotNetVerbosity.Minimal) + .Run(output => lines.Add(output.Line)); + +lines.Any(i => i.Contains("Pure.DI")).ShouldBeTrue(result.ToString()); +``` + + + +### Adding a NuGet package + + + +``` CSharp +using HostApi; + +new DotNetNew() + .WithTemplateName("classlib") + .WithName("MyLib") + .WithForce(true) + .Build().EnsureSuccess(); + +new DotNetNew() + .WithTemplateName("xunit") + .WithName("MyTests") + .WithForce(true) + .Build().EnsureSuccess(); + +var result = new DotNetAddReference() + .WithProject(Path.Combine("MyTests", "MyTests.csproj")) + .WithReferences(Path.Combine("MyLib", "MyLib.csproj")) + .Run().EnsureSuccess(); + +var lines = new List(); +new DotNetListReference() + .WithProject(Path.Combine("MyTests", "MyTests.csproj")) + .Run(output => lines.Add(output.Line)); + +lines.Any(i => i.Contains("MyLib.csproj")).ShouldBeTrue(result.ToString()); +``` + + + ### Build a project @@ -604,30 +668,28 @@ var result = new DockerRun(cmd, "mcr.microsoft.com/dotnet/sdk") // Adds the namespace "HostApi" to use .NET build API using HostApi; -// Creates a new library project, running a command like: "dotnet new classlib -n MyLib --force" -new DotNetNew("xunit", "-n", "MyLib", "--force") - .Build() - .EnsureSuccess(); +// Creates a new test project, running a command like: "dotnet new xunit -n MyTests --force" +new DotNetNew() + .WithTemplateName("xunit") + .WithName("MyTests") + .WithForce(true) + .Build().EnsureSuccess(); -// Builds the library project, running a command like: "dotnet build" from the directory "MyLib" +// Builds this project, running a command like: "dotnet build" from the directory "MyLib" +var messages = new List(); var result = new DotNetBuild() - .WithWorkingDirectory("MyLib") - .Build() - .EnsureSuccess(); + .WithWorkingDirectory("MyTests") + .Build(message => messages.Add(message)).EnsureSuccess(); // The "result" variable provides details about a build -result.Errors.Any(message => message.State == BuildMessageState.StdError).ShouldBeFalse(); -result.ExitCode.ShouldBe(0); +messages.Count.ShouldBeGreaterThan(0, result.ToString()); +result.Errors.Any(message => message.State == BuildMessageState.StdError).ShouldBeFalse(result.ToString()); +result.ExitCode.ShouldBe(0, result.ToString()); // Runs tests in docker result = new DotNetTest() - .WithWorkingDirectory("MyLib") - .Build() - .EnsureSuccess(); - -result.ExitCode.ShouldBe(0); -result.Summary.Tests.ShouldBe(1); -result.Tests.Count(test => test.State == TestState.Finished).ShouldBe(1); + .WithWorkingDirectory("MyTests") + .Build().EnsureSuccess(); ``` @@ -641,25 +703,25 @@ result.Tests.Count(test => test.State == TestState.Finished).ShouldBe(1); using HostApi; // Creates a new library project, running a command like: "dotnet new classlib -n MyLib --force" -var result = new DotNetNew("classlib", "-n", "MyLib", "--force") - .Build() - .EnsureSuccess(); +var result = new DotNetNew() + .WithTemplateName("classlib") + .WithName("MyLib") + .WithForce(true) + .Build().EnsureSuccess(); result.ExitCode.ShouldBe(0); // Builds the library project, running a command like: "dotnet build" from the directory "MyLib" result = new DotNetBuild() .WithWorkingDirectory("MyLib") - .Build() - .EnsureSuccess(); + .Build().EnsureSuccess(); result.ExitCode.ShouldBe(0); // Clean the project, running a command like: "dotnet clean" from the directory "MyLib" result = new DotNetClean() .WithWorkingDirectory("MyLib") - .Build() - .EnsureSuccess(); + .Build().EnsureSuccess(); // The "result" variable provides details about a build result.ExitCode.ShouldBe(0); @@ -686,6 +748,63 @@ version.ShouldNotBeNull(); +### Execute a dotnet application + + + +``` CSharp +// Adds the namespace "HostApi" to use .NET build API +using HostApi; + +// Creates a new console project, running a command like: "dotnet new console -n MyApp --force" +new DotNetNew() + .WithTemplateName("console") + .WithName("MyApp") + .WithForce(true) + .Build().EnsureSuccess(); + +var tempDirectory = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); +new DotNetPublish() + .WithWorkingDirectory("MyApp") + .WithOutput(tempDirectory) + .Build().EnsureSuccess(); + +new DotNetExec() + .WithPathToApplication(Path.Combine(tempDirectory, "MyApp.dll")) + .Run().EnsureSuccess(); +``` + + + +### NuGet package listing + + + +``` CSharp +using HostApi; + +new DotNetNew() + .WithTemplateName("classlib") + .WithName("MyLib") + .WithForce(true) + .Build().EnsureSuccess(); + +new DotNetAddPackage() + .WithWorkingDirectory("MyLib") + .WithPackage("Pure.DI") + .Run().EnsureSuccess(); + +var lines = new List(); +var result = new DotNetListPackage() + .WithWorkingDirectory("MyLib") + .WithVerbosity(DotNetVerbosity.Minimal) + .Run(output => lines.Add(output.Line)); + +lines.Any(i => i.Contains("Pure.DI")).ShouldBeTrue(result.ToString()); +``` + + + ### Test a project using the MSBuild VSTest target @@ -695,23 +814,24 @@ version.ShouldNotBeNull(); using HostApi; // Creates a new test project, running a command like: "dotnet new mstest -n MyTests --force" -var result = new DotNetNew("mstest", "-n", "MyTests", "--force") - .Build() - .EnsureSuccess(); +var result = new DotNetNew() + .WithTemplateName("mstest") + .WithName("MyTests") + .WithForce(true) + .Build().EnsureSuccess(); -result.ExitCode.ShouldBe(0); +result.ExitCode.ShouldBe(0, result.ToString()); // Runs tests via a command like: "dotnet msbuild /t:VSTest" from the directory "MyTests" result = new MSBuild() .WithTarget("VSTest") .WithWorkingDirectory("MyTests") - .Build() - .EnsureSuccess(); + .Build().EnsureSuccess(); // The "result" variable provides details about a build -result.ExitCode.ShouldBe(0); -result.Summary.Tests.ShouldBe(1); -result.Tests.Count(test => test.State == TestState.Finished).ShouldBe(1); +result.ExitCode.ShouldBe(0, result.ToString()); +result.Summary.Tests.ShouldBe(1, result.ToString()); +result.Tests.Count(test => test.State == TestState.Finished).ShouldBe(1, result.ToString()); ``` @@ -725,9 +845,11 @@ result.Tests.Count(test => test.State == TestState.Finished).ShouldBe(1); using HostApi; // Creates a new library project, running a command like: "dotnet new classlib -n MyLib --force" -var result = new DotNetNew("classlib", "-n", "MyLib", "--force") - .Build() - .EnsureSuccess(); +var result = new DotNetNew() + .WithTemplateName("classlib") + .WithName("MyLib") + .WithForce(true) + .Build().EnsureSuccess(); result.ExitCode.ShouldBe(0); @@ -735,10 +857,7 @@ result.ExitCode.ShouldBe(0); result = new DotNetPack() .WithWorkingDirectory("MyLib") .AddProps(("version", "1.2.3")) - .Build() - .EnsureSuccess(); - -result.ExitCode.ShouldBe(0); + .Build().EnsureSuccess(); ``` @@ -752,9 +871,12 @@ result.ExitCode.ShouldBe(0); using HostApi; // Creates a new library project, running a command like: "dotnet new classlib -n MyLib --force" -var result = new DotNetNew("classlib", "-n", "MyLib", "--force", "-f", "net8.0") - .Build() - .EnsureSuccess(); +var result = new DotNetNew() + .WithTemplateName("classlib") + .AddArgs("-f", "net8.0") + .WithName("MyLib") + .WithForce(true) + .Build().EnsureSuccess(); result.ExitCode.ShouldBe(0); @@ -762,10 +884,41 @@ result.ExitCode.ShouldBe(0); result = new DotNetPublish() .WithWorkingDirectory("MyLib") .WithFramework("net8.0") - .Build() - .EnsureSuccess(); + .Build().EnsureSuccess(); +``` -result.ExitCode.ShouldBe(0); + + +### Removing a NuGet package + + + +``` CSharp +using HostApi; + +new DotNetNew() + .WithTemplateName("classlib") + .WithName("MyLib") + .WithForce(true) + .Build().EnsureSuccess(); + +new DotNetAddPackage() + .WithWorkingDirectory("MyLib") + .WithPackage("Pure.DI") + .Run().EnsureSuccess(); + +var result = new DotNetRemovePackage() + .WithWorkingDirectory("MyLib") + .WithPackage("Pure.DI") + .Run().EnsureSuccess(); + +var lines = new List(); +new DotNetListPackage() + .WithWorkingDirectory("MyLib") + .WithVerbosity(DotNetVerbosity.Minimal) + .Run(output => lines.Add(output.Line)); + +lines.Any(i => i.Contains("Pure.DI")).ShouldBeFalse(result.ToString()); ``` @@ -779,19 +932,18 @@ result.ExitCode.ShouldBe(0); using HostApi; // Creates a new library project, running a command like: "dotnet new classlib -n MyLib --force" -var result = new DotNetNew("classlib", "-n", "MyLib", "--force") - .Build() - .EnsureSuccess(); +var result = new DotNetNew() + .WithTemplateName("classlib") + .WithName("MyLib") + .WithForce(true) + .Build().EnsureSuccess(); result.ExitCode.ShouldBe(0); // Restore the project, running a command like: "dotnet restore" from the directory "MyLib" result = new DotNetRestore() .WithWorkingDirectory("MyLib") - .Build() - .EnsureSuccess(); - -result.ExitCode.ShouldBe(0); + .Build().EnsureSuccess(); ``` @@ -805,15 +957,18 @@ result.ExitCode.ShouldBe(0); using HostApi; // Creates a new console project, running a command like: "dotnet new console -n MyApp --force" -var result = new DotNetNew("console", "-n", "MyApp", "--force") - .Build() - .EnsureSuccess(); +var result = new DotNetNew() + .WithTemplateName("console") + .WithName("MyApp") + .WithForce(true) + .Build().EnsureSuccess(); result.ExitCode.ShouldBe(0); // Runs the console project using a command like: "dotnet run" from the directory "MyApp" var stdOut = new List(); -result = new DotNetRun().WithWorkingDirectory("MyApp") +result = new DotNetRun() + .WithWorkingDirectory("MyApp") .Build(message => stdOut.Add(message.Text)) .EnsureSuccess(); @@ -825,6 +980,34 @@ stdOut.ShouldBe(new[] {"Hello, World!"}); +### Run a dotnet application + + + +``` CSharp +// Adds the namespace "HostApi" to use .NET build API +using HostApi; + +// Creates a new console project, running a command like: "dotnet new console -n MyApp --force" +new DotNetNew() + .WithTemplateName("console") + .WithName("MyApp") + .WithForce(true) + .Build().EnsureSuccess(); + +var tempDirectory = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); +new DotNetPublish() + .WithWorkingDirectory("MyApp") + .WithOutput(tempDirectory) + .Build().EnsureSuccess(); + +new DotNet() + .WithPathToApplication(Path.Combine(tempDirectory, "MyApp.dll")) + .Run().EnsureSuccess(); +``` + + + ### Test a project @@ -834,9 +1017,11 @@ stdOut.ShouldBe(new[] {"Hello, World!"}); using HostApi; // Creates a new test project, running a command like: "dotnet new mstest -n MyTests --force" -var result = new DotNetNew("mstest", "-n", "MyTests", "--force") - .Build() - .EnsureSuccess(); +var result = new DotNetNew() + .WithTemplateName("mstest") + .WithName("MyTests") + .WithForce(true) + .Build().EnsureSuccess(); result.ExitCode.ShouldBe(0); @@ -847,9 +1032,9 @@ result = new DotNetTest() .EnsureSuccess(); // The "result" variable provides details about a build -result.ExitCode.ShouldBe(0); -result.Summary.Tests.ShouldBe(1); -result.Tests.Count(test => test.State == TestState.Finished).ShouldBe(1); +result.ExitCode.ShouldBe(0, result.ToString()); +result.Summary.Tests.ShouldBe(1, result.ToString()); +result.Tests.Count(test => test.State == TestState.Finished).ShouldBe(1, result.ToString()); ``` @@ -863,20 +1048,21 @@ result.Tests.Count(test => test.State == TestState.Finished).ShouldBe(1); using HostApi; // Creates a new test project, running a command like: "dotnet new mstest -n MyTests --force" -new DotNetNew("mstest", "-n", "MyTests", "--force") - .Run() - .EnsureSuccess(); +new DotNetNew() + .WithTemplateName("mstest") + .WithName("MyTests") + .WithForce(true) + .Run().EnsureSuccess(); // Creates the tool manifest and installs the dotCover tool locally // It is better to run the following 2 commands manually // and commit these changes to a source control -new DotNetNew("tool-manifest") - .Run() - .EnsureSuccess(); +new DotNetNew() + .WithTemplateName("tool-manifest") + .Run().EnsureSuccess(); new DotNetCustom("tool", "install", "--local", "JetBrains.dotCover.GlobalTool") - .Run() - .EnsureSuccess(); + .Run().EnsureSuccess(); // Creates a test command var test = new DotNetTest() @@ -897,12 +1083,11 @@ var testUnderDotCover = test.Customize(cmd => // Runs tests under dotCover via a command like: "dotnet dotcover test ..." var result = testUnderDotCover - .Build() - .EnsureSuccess(); + .Build().EnsureSuccess(); // The "result" variable provides details about a build -result.ExitCode.ShouldBe(0); -result.Tests.Count(i => i.State == TestState.Finished).ShouldBe(1); +result.ExitCode.ShouldBe(0, result.ToString()); +result.Tests.Count(i => i.State == TestState.Finished).ShouldBe(1, result.ToString()); // Generates a HTML code coverage report. new DotNetCustom("dotCover", "report", $"--source={dotCoverSnapshot}", $"--output={dotCoverReport}", "--reportType=HTML") @@ -926,7 +1111,8 @@ var projectDir = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString()[..4] Directory.CreateDirectory(projectDir); // Creates a local tool manifest -new DotNetNew("tool-manifest") +new DotNetNew() + .WithTemplateName("tool-manifest") .WithWorkingDirectory(projectDir) .Run() .EnsureSuccess(); @@ -949,33 +1135,33 @@ new DotNetToolRestore() using HostApi; // Creates a new test project, running a command like: "dotnet new mstest -n MyTests --force" -var result = new DotNetNew("mstest", "-n", "MyTests", "--force") - .Build() - .EnsureSuccess(); +var result = new DotNetNew() + .WithTemplateName("mstest") + .WithName("MyTests") + .WithForce(true) + .Build().EnsureSuccess(); -result.ExitCode.ShouldBe(0); +result.ExitCode.ShouldBe(0, result.ToString()); // Builds the test project, running a command like: "dotnet build -c Release" from the directory "MyTests" result = new DotNetBuild() .WithWorkingDirectory("MyTests") .WithConfiguration("Release") .WithOutput("MyOutput") - .Build() - .EnsureSuccess(); + .Build().EnsureSuccess(); -result.ExitCode.ShouldBe(0); +result.ExitCode.ShouldBe(0, result.ToString()); // Runs tests via a command like: "dotnet vstest" from the directory "MyTests" result = new VSTest() .AddTestFileNames(Path.Combine("MyOutput", "MyTests.dll")) .WithWorkingDirectory("MyTests") - .Build() - .EnsureSuccess(); + .Build().EnsureSuccess(); // The "result" variable provides details about a build -result.ExitCode.ShouldBe(0); -result.Summary.Tests.ShouldBe(1); -result.Tests.Count(test => test.State == TestState.Finished).ShouldBe(1); +result.ExitCode.ShouldBe(0, result.ToString()); +result.Summary.Tests.ShouldBe(1, result.ToString()); +result.Tests.Count(test => test.State == TestState.Finished).ShouldBe(1, result.ToString()); ``` @@ -989,11 +1175,13 @@ result.Tests.Count(test => test.State == TestState.Finished).ShouldBe(1); using HostApi; // Creates a new library project, running a command like: "dotnet new classlib -n MyLib --force" -var result = new DotNetNew("classlib", "-n", "MyLib", "--force") - .Build() - .EnsureSuccess(); +var result = new DotNetNew() + .WithTemplateName("classlib") + .WithName("MyLib") + .WithForce(true) + .Build().EnsureSuccess(); -result.ExitCode.ShouldBe(0); +result.ExitCode.ShouldBe(0, result.ToString()); // Builds the library project, running a command like: "dotnet msbuild /t:Build -restore /p:configuration=Release -verbosity=detailed" from the directory "MyLib" result = new MSBuild() @@ -1002,12 +1190,11 @@ result = new MSBuild() .WithRestore(true) .AddProps(("configuration", "Release")) .WithVerbosity(DotNetVerbosity.Detailed) - .Build() - .EnsureSuccess(); + .Build().EnsureSuccess(); // The "result" variable provides details about a build -result.Errors.Any(message => message.State == BuildMessageState.StdError).ShouldBeFalse(); -result.ExitCode.ShouldBe(0); +result.Errors.Any(message => message.State == BuildMessageState.StdError).ShouldBeFalse(result.ToString()); +result.ExitCode.ShouldBe(0, result.ToString()); ``` @@ -1028,6 +1215,32 @@ new DotNetBuildServerShutdown() +### Run C# script + + + +``` CSharp +// Adds the namespace "HostApi" to use .NET build API +using HostApi; + +var script = Path.GetTempFileName(); +File.WriteAllText(script, "Console.WriteLine($\"Hello, {Args[0]}!\");"); + +var stdOut = new List(); +var result = new DotNetCsi() + .WithScript(script) + .AddArgs("World") + .Build(message => stdOut.Add(message.Text)) + .EnsureSuccess(); + +result.ExitCode.ShouldBe(0); + +// Checks StdOut +stdOut.Contains("Hello, World!").ShouldBeTrue(result.ToString()); +``` + + + ### TeamCity integration via service messages For more details how to use TeamCity service message API please see [this](https://github.com/JetBrains/TeamCity.ServiceMessages) page. Instead of creating a root message writer like in the following example: