File: CommandTests\Run\GivenDotnetRunBuildsCsProj.cs
Web Access
Project: ..\..\..\test\dotnet.Tests\dotnet.Tests.csproj (dotnet.Tests)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
#nullable disable
 
using Microsoft.DotNet.Cli.Commands;
using Microsoft.DotNet.Cli.Utils;
using Microsoft.TemplateEngine.Utils;
 
namespace Microsoft.DotNet.Cli.Run.Tests
{
    public class GivenDotnetRunBuildsCsproj : SdkTest
    {
        public GivenDotnetRunBuildsCsproj(ITestOutputHelper log) : base(log)
        {
        }
 
        [Fact]
        public void ItCanRunAMSBuildProject()
        {
            var testAppName = "MSBuildTestApp";
            var testInstance = _testAssetsManager.CopyTestAsset(testAppName)
                            .WithSource();
 
            var testProjectDirectory = testInstance.Path;
 
            new BuildCommand(testInstance)
                .Execute()
                .Should().Pass();
 
            new DotnetCommand(Log, "run")
                .WithWorkingDirectory(testProjectDirectory)
                .Execute()
                .Should().Pass()
                         .And.HaveStdOutContaining("Hello World!");
        }
 
        [Fact]
        public void ItImplicitlyRestoresAProjectWhenRunning()
        {
            var testAppName = "MSBuildTestApp";
            var testInstance = _testAssetsManager.CopyTestAsset(testAppName)
                            .WithSource();
 
            var testProjectDirectory = testInstance.Path;
 
            new DotnetCommand(Log, "run")
                .WithWorkingDirectory(testProjectDirectory)
                .Execute()
                .Should().Pass()
                         .And.HaveStdOutContaining("Hello World!");
        }
 
        [Fact]
        public void ItCanRunAMultiTFMProjectWithImplicitRestore()
        {
            var testInstance = _testAssetsManager.CopyTestAsset(
                    "NETFrameworkReferenceNETStandard20",
                    testAssetSubdirectory: TestAssetSubdirectories.DesktopTestProjects)
                .WithSource();
 
            string projectDirectory = Path.Combine(testInstance.Path, "MultiTFMTestApp");
 
            new DotnetCommand(Log, "run")
                .WithWorkingDirectory(projectDirectory)
                .Execute("--framework", ToolsetInfo.CurrentTargetFramework)
                .Should().Pass()
                         .And.HaveStdOutContaining("This string came from the test library!");
        }
 
        [Fact]
        public void ItDoesNotImplicitlyBuildAProjectWhenRunningWithTheNoBuildOption()
        {
            var testAppName = "MSBuildTestApp";
            var testInstance = _testAssetsManager.CopyTestAsset(testAppName)
                            .WithSource();
 
            var result = new DotnetCommand(Log, "run")
                .WithWorkingDirectory(testInstance.Path)
                .Execute("--no-build", "-v:m");
 
            result.Should().Fail();
            if (!TestContext.IsLocalized())
            {
                result.Should().NotHaveStdOutContaining("Restore");
            }
        }
 
        [Fact]
        public void ItDoesNotImplicitlyRestoreAProjectWhenRunningWithTheNoRestoreOption()
        {
            var testAppName = "MSBuildTestApp";
            var testInstance = _testAssetsManager.CopyTestAsset(testAppName)
                            .WithSource();
 
            var testProjectDirectory = testInstance.Path;
 
            new DotnetCommand(Log, "run")
                .WithWorkingDirectory(testProjectDirectory)
                .Execute("--no-restore")
                .Should().Fail()
                .And.HaveStdOutContaining("project.assets.json");
        }
 
        [Fact]
        public void ItBuildsTheProjectBeforeRunning()
        {
            var testAppName = "MSBuildTestApp";
            var testInstance = _testAssetsManager.CopyTestAsset(testAppName)
                            .WithSource();
 
            var testProjectDirectory = testInstance.Path;
 
            new DotnetCommand(Log, "run")
                .WithWorkingDirectory(testProjectDirectory)
                .Execute()
                .Should().Pass()
                         .And.HaveStdOutContaining("Hello World!");
        }
 
        [Fact]
        public void ItCanRunAMSBuildProjectWhenSpecifyingAFramework()
        {
            var testAppName = "MSBuildTestApp";
            var testInstance = _testAssetsManager.CopyTestAsset(testAppName)
                            .WithSource();
 
            var testProjectDirectory = testInstance.Path;
 
            new DotnetCommand(Log, "run")
                .WithWorkingDirectory(testProjectDirectory)
                .Execute("--framework", ToolsetInfo.CurrentTargetFramework)
                .Should().Pass()
                         .And.HaveStdOutContaining("Hello World!");
        }
 
        [Fact]
        public void ItRunsPortableAppsFromADifferentPathAfterBuilding()
        {
            var testInstance = _testAssetsManager.CopyTestAsset("MSBuildTestApp")
                .WithSource();
 
            new BuildCommand(testInstance)
                .Execute()
                .Should().Pass();
 
            new DotnetCommand(Log, "run")
                .WithWorkingDirectory(testInstance.Path)
                .Execute($"--no-build")
                .Should().Pass()
                         .And.HaveStdOutContaining("Hello World!");
        }
 
        [Fact]
        public void ItRunsPortableAppsFromADifferentPathWithoutBuilding()
        {
            var testAppName = "MSBuildTestApp";
            var testInstance = _testAssetsManager.CopyTestAsset(testAppName)
                .WithSource();
 
            var projectFile = Path.Combine(testInstance.Path, testAppName + ".csproj");
 
            new DotnetCommand(Log, "run")
                .WithWorkingDirectory(Directory.GetParent(testInstance.Path).FullName)
                .Execute($"--project", projectFile)
                .Should().Pass()
                         .And.HaveStdOutContaining("Hello World!")
                         .And.NotHaveStdOutContaining(CliCommandStrings.RunCommandProjectAbbreviationDeprecated);
        }
 
        [Fact]
        public void ItRunsPortableAppsFromADifferentPathSpecifyingOnlyTheDirectoryWithoutBuilding()
        {
            var testAppName = "MSBuildTestApp";
            var testInstance = _testAssetsManager.CopyTestAsset(testAppName)
                .WithSource();
 
            var testProjectDirectory = testInstance.Path;
 
            new DotnetCommand(Log, "run")
                .WithWorkingDirectory(Directory.GetParent(testInstance.Path).FullName)
                .Execute("--project", testProjectDirectory)
                .Should().Pass()
                         .And.HaveStdOutContaining("Hello World!")
                         .And.NotHaveStdOutContaining(CliCommandStrings.RunCommandProjectAbbreviationDeprecated);
        }
 
        [Fact]
        public void ItWarnsWhenShortFormOfProjectArgumentIsUsed()
        {
            var testAppName = "MSBuildTestApp";
            var testInstance = _testAssetsManager.CopyTestAsset(testAppName)
                .WithSource();
 
            var projectFile = Path.Combine(testInstance.Path, testAppName + ".csproj");
 
            new DotnetCommand(Log, "run")
                .WithWorkingDirectory(Directory.GetParent(testInstance.Path).FullName)
                .Execute($"-p", projectFile)
                .Should().Pass()
                         .And.HaveStdOutContaining("Hello World!")
                         .And.HaveStdOutContaining(CliCommandStrings.RunCommandProjectAbbreviationDeprecated);
        }
 
        [Theory]
        [InlineData("-p project1 -p project2")]
        [InlineData("--project project1 -p project2")]
        public void ItErrorsWhenMultipleProjectsAreSpecified(string args)
        {
            new DotnetCommand(Log, "run")
                .Execute(args.Split(" "))
                .Should()
                .Fail()
                .And
                .HaveStdErrContaining(CliStrings.OnlyOneProjectAllowed);
        }
 
        [Fact]
        public void ItRunsAppWhenRestoringToSpecificPackageDirectory()
        {
            var rootPath = _testAssetsManager.CreateTestDirectory().Path;
 
            string dir = "pkgs";
            string[] args = new string[] { "--packages", dir };
 
            string[] newArgs = new string[] { "console", "-o", rootPath, "--no-restore" };
            new DotnetNewCommand(Log)
                .WithVirtualHive()
                .WithWorkingDirectory(rootPath)
                .Execute(newArgs)
                .Should()
                .Pass();
 
            new DotnetRestoreCommand(Log)
                .WithWorkingDirectory(rootPath)
                .Execute(args)
                .Should()
                .Pass();
 
            new DotnetCommand(Log, "run")
                .WithWorkingDirectory(rootPath)
                .Execute("--no-restore")
                .Should().Pass()
                         .And.HaveStdOutContaining("Hello, World");
        }
 
        [Fact]
        public void ItReportsAGoodErrorWhenProjectHasMultipleFrameworks()
        {
            var testAppName = "MSBuildAppWithMultipleFrameworks";
            var testInstance = _testAssetsManager.CopyTestAsset(testAppName)
                .WithSource();
 
            // use --no-build so this test can run on all platforms.
            // the test app targets net451, which can't be built on non-Windows
            new DotnetCommand(Log, "run")
                .WithWorkingDirectory(testInstance.Path)
                .Execute("--no-build")
                .Should().Fail()
                    .And.HaveStdErrContaining("--framework");
        }
 
        [Fact]
        public void ItCanPassArgumentsToSubjectAppByDoubleDash()
        {
            const string testAppName = "MSBuildTestApp";
            var testInstance = _testAssetsManager.CopyTestAsset(testAppName)
                .WithSource();
 
            var testProjectDirectory = testInstance.Path;
 
            new DotnetCommand(Log, "run")
                .WithWorkingDirectory(testProjectDirectory)
                .Execute("--", "foo", "bar", "baz")
                .Should()
                .Pass()
                .And.HaveStdOutContaining("echo args:foo;bar;baz");
        }
 
        [Fact]
        public void ItCanPassOptionArgumentsToSubjectAppByDoubleDash()
        {
            const string testAppName = "MSBuildTestApp";
            var testInstance = _testAssetsManager.CopyTestAsset(testAppName)
                .WithSource();
 
            var testProjectDirectory = testInstance.Path;
 
            new DotnetCommand(Log, "run")
                .WithWorkingDirectory(testProjectDirectory)
                .Execute("--", "-d", "-a")
                .Should()
                .Pass()
                .And.HaveStdOutContaining("echo args:-d;-a");
        }
 
        [Fact]
        public void ItCanPassOptionAndArgumentsToSubjectAppByDoubleDash()
        {
            const string testAppName = "MSBuildTestApp";
            var testInstance = _testAssetsManager.CopyTestAsset(testAppName)
                .WithSource();
 
            var testProjectDirectory = testInstance.Path;
 
            new DotnetCommand(Log, "run")
                .WithWorkingDirectory(testProjectDirectory)
                .Execute("--", "foo", "-d", "-a")
                .Should()
                .Pass()
                .And.HaveStdOutContaining("echo args:foo;-d;-a");
        }
 
        [Fact]
        public void ItCanPassArgumentsToSubjectAppWithoutDoubleDash()
        {
            const string testAppName = "MSBuildTestApp";
            var testInstance = _testAssetsManager.CopyTestAsset(testAppName)
                .WithSource();
 
            var testProjectDirectory = testInstance.Path;
 
            new DotnetCommand(Log, "run")
                .WithWorkingDirectory(testProjectDirectory)
                .Execute("foo", "bar", "baz")
                .Should()
                .Pass()
                .And.HaveStdOutContaining("echo args:foo;bar;baz");
        }
 
        [Fact]
        public void ItCanPassUnrecognizedOptionArgumentsToSubjectAppWithoutDoubleDash()
        {
            const string testAppName = "MSBuildTestApp";
            var testInstance = _testAssetsManager.CopyTestAsset(testAppName)
                .WithSource();
 
            var testProjectDirectory = testInstance.Path;
 
            new DotnetCommand(Log, "run")
                .WithWorkingDirectory(testProjectDirectory)
                .Execute("-x", "-y", "-z")
                .Should()
                .Pass()
                .And.HaveStdOutContaining("echo args:-x;-y;-z");
        }
 
        [Fact]
        public void ItCanPassOptionArgumentsAndArgumentsToSubjectAppWithoutAndByDoubleDash()
        {
            const string testAppName = "MSBuildTestApp";
            var testInstance = _testAssetsManager.CopyTestAsset(testAppName)
                .WithSource();
 
            var testProjectDirectory = testInstance.Path;
 
            new DotnetCommand(Log, "run")
                .WithWorkingDirectory(testProjectDirectory)
                .Execute("foo", "--", "-z")
                .Should()
                .Pass()
                .And.HaveStdOutContaining("echo args:foo;-z");
        }
 
        [Fact]
        public void ItGivesAnErrorWhenAttemptingToUseALaunchProfileThatDoesNotExistWhenThereIsNoLaunchSettingsFile()
        {
            var testAppName = "MSBuildTestApp";
            var testInstance = _testAssetsManager.CopyTestAsset(testAppName)
                            .WithSource();
 
            var testProjectDirectory = testInstance.Path;
 
            var runResult = new DotnetCommand(Log, "run")
                .WithWorkingDirectory(testProjectDirectory)
                .Execute("--launch-profile", "test");
 
            runResult
                .Should().Pass()
                .And.HaveStdOutContaining("Hello World!")
                .And.HaveStdErrContaining(string.Format(CliCommandStrings.RunCommandExceptionCouldNotLocateALaunchSettingsFile, "test", $"""
                    {Path.Join(testInstance.Path, "Properties", "launchSettings.json")}
                    {Path.Join(testInstance.Path, "MSBuildTestApp.run.json")}
                    """));
        }
 
        [Fact]
        public void ItUsesLaunchProfileOfTheSpecifiedName()
        {
            var testAppName = "AppWithLaunchSettings";
            var testInstance = _testAssetsManager.CopyTestAsset(testAppName)
                            .WithSource();
 
            var testProjectDirectory = testInstance.Path;
 
            var cmd = new DotnetCommand(Log, "run")
                .WithWorkingDirectory(testProjectDirectory)
                .Execute("--launch-profile", "Second");
 
            cmd.Should().Pass()
                .And.HaveStdOutContaining("Second");
 
            cmd.StdErr.Should().BeEmpty();
        }
 
        [Fact]
        public void ItDefaultsToTheFirstUsableLaunchProfile()
        {
            var testAppName = "AppWithLaunchSettings";
            var testInstance = _testAssetsManager.CopyTestAsset(testAppName)
                            .WithSource();
 
            var testProjectDirectory = testInstance.Path;
            var launchSettingsPath = Path.Combine(testProjectDirectory, "Properties", "launchSettings.json");
 
            var cmd = new DotnetCommand(Log, "run", "--verbosity", "quiet")
                .WithWorkingDirectory(testProjectDirectory)
                .Execute();
 
            cmd.Should().Pass()
                .And.NotHaveStdOutContaining(string.Format(CliCommandStrings.UsingLaunchSettingsFromMessage, launchSettingsPath))
                .And.HaveStdOutContaining("First");
 
            cmd.StdErr.Should().BeEmpty();
        }
 
        [Fact]
        public void ItSetsTheDotnetLaunchProfileEnvironmentVariableToDefaultLaunchProfileName()
        {
            var testAppName = "AppThatOutputsDotnetLaunchProfile";
            var testInstance = _testAssetsManager.CopyTestAsset(testAppName)
                            .WithSource();
 
            var testProjectDirectory = testInstance.Path;
            var launchSettingsPath = Path.Combine(testProjectDirectory, "Properties", "launchSettings.json");
 
            var cmd = new DotnetCommand(Log, "run")
                .WithWorkingDirectory(testProjectDirectory)
                .Execute();
 
            cmd.Should().Pass()
                .And.HaveStdOutContaining("DOTNET_LAUNCH_PROFILE=<<<First>>>");
 
            cmd.StdErr.Should().BeEmpty();
        }
 
        [Fact]
        public void ItSetsTheDotnetLaunchProfileEnvironmentVariableToSuppliedLaunchProfileName()
        {
            var testAppName = "AppThatOutputsDotnetLaunchProfile";
            var testInstance = _testAssetsManager.CopyTestAsset(testAppName)
                            .WithSource();
 
            var testProjectDirectory = testInstance.Path;
            var launchSettingsPath = Path.Combine(testProjectDirectory, "Properties", "launchSettings.json");
 
            var cmd = new DotnetCommand(Log, "run")
                .WithWorkingDirectory(testProjectDirectory)
                .Execute("--launch-profile", "Second");
 
            cmd.Should().Pass()
                .And.HaveStdOutContaining("DOTNET_LAUNCH_PROFILE=<<<Second>>>");
 
            cmd.StdErr.Should().BeEmpty();
        }
 
        [Fact]
        public void ItSetsTheDotnetLaunchProfileEnvironmentVariableToEmptyWhenInvalidProfileSpecified()
        {
            var testAppName = "AppThatOutputsDotnetLaunchProfile";
            var testInstance = _testAssetsManager.CopyTestAsset(testAppName)
                            .WithSource();
 
            var testProjectDirectory = testInstance.Path;
            var launchSettingsPath = Path.Combine(testProjectDirectory, "Properties", "launchSettings.json");
 
            var cmd = new DotnetCommand(Log, "run")
                .WithWorkingDirectory(testProjectDirectory)
                .Execute("--launch-profile", "DoesNotExist");
 
            cmd.Should().Pass()
                .And.HaveStdOutContaining("DOTNET_LAUNCH_PROFILE=<<<>>>");
 
            cmd.StdErr.Should().Contain("DoesNotExist");
        }
 
        [Fact]
        public void ItSetsTheDotnetLaunchProfileEnvironmentVariableToEmptyWhenNoLaunchProfileSwitchIsUsed()
        {
            var testAppName = "AppThatOutputsDotnetLaunchProfile";
            var testInstance = _testAssetsManager.CopyTestAsset(testAppName)
                            .WithSource();
 
            var testProjectDirectory = testInstance.Path;
            var launchSettingsPath = Path.Combine(testProjectDirectory, "Properties", "launchSettings.json");
 
            var cmd = new DotnetCommand(Log, "run")
                .WithWorkingDirectory(testProjectDirectory)
                .Execute("--no-launch-profile");
 
            cmd.Should().Pass()
                .And.HaveStdOutContaining("DOTNET_LAUNCH_PROFILE=<<<>>>");
 
            cmd.StdErr.Should().BeEmpty();
        }
 
        [Fact]
        public void ItPrintsUsingLaunchSettingsMessageWhenNotQuiet()
        {
            var testInstance = _testAssetsManager.CopyTestAsset("AppWithLaunchSettings")
                            .WithSource();
 
            var testProjectDirectory = testInstance.Path;
            var launchSettingsPath = Path.Combine(testProjectDirectory, "Properties", "launchSettings.json");
 
            var cmd = new DotnetCommand(Log, "run")
                .WithWorkingDirectory(testProjectDirectory)
                .Execute("-v:m");
 
            cmd.Should().Pass()
                .And.HaveStdOutContaining(string.Format(CliCommandStrings.UsingLaunchSettingsFromMessage, launchSettingsPath))
                .And.HaveStdOutContaining("First");
 
            cmd.StdErr.Should().BeEmpty();
        }
 
        [Fact]
        public void ItPrefersTheValueOfAppUrlFromEnvVarOverTheProp()
        {
            var testAppName = "AppWithApplicationUrlInLaunchSettings";
            var testInstance = _testAssetsManager.CopyTestAsset(testAppName)
                            .WithSource();
 
            var testProjectDirectory = testInstance.Path;
 
            var cmd = new DotnetCommand(Log, "run")
                .WithWorkingDirectory(testProjectDirectory)
                .Execute("--launch-profile", "First");
 
            cmd.Should().Pass()
                .And.HaveStdOutContaining("http://localhost:12345/");
 
            cmd.StdErr.Should().BeEmpty();
        }
 
        [Fact]
        public void ItUsesTheValueOfAppUrlIfTheEnvVarIsNotSet()
        {
            var testAppName = "AppWithApplicationUrlInLaunchSettings";
            var testInstance = _testAssetsManager.CopyTestAsset(testAppName)
                            .WithSource();
 
            var testProjectDirectory = testInstance.Path;
 
            var cmd = new DotnetCommand(Log, "run")
                .WithWorkingDirectory(testProjectDirectory)
                .Execute("--launch-profile", "Second");
 
            cmd.Should().Pass()
                .And.HaveStdOutContaining("http://localhost:54321/");
 
            cmd.StdErr.Should().BeEmpty();
        }
 
        [Fact]
        public void ItGivesAnErrorWhenTheLaunchProfileNotFound()
        {
            var testAppName = "AppWithLaunchSettings";
            var testInstance = _testAssetsManager.CopyTestAsset(testAppName)
                            .WithSource();
 
            var testProjectDirectory = testInstance.Path;
 
            new DotnetCommand(Log, "run")
                .WithWorkingDirectory(testProjectDirectory)
                .Execute("--launch-profile", "Third")
                .Should().Pass()
                         .And.HaveStdOutContaining("(NO MESSAGE)")
                         .And.HaveStdErrContaining(string.Format(CliCommandStrings.RunCommandExceptionCouldNotApplyLaunchSettings, "Third", "").Trim());
        }
 
        [Fact]
        public void ItGivesAnErrorWhenTheLaunchProfileCanNotBeHandled()
        {
            var testAppName = "AppWithLaunchSettings";
            var testInstance = _testAssetsManager.CopyTestAsset(testAppName)
                            .WithSource();
 
            var testProjectDirectory = testInstance.Path;
 
            new DotnetCommand(Log, "run")
                .WithWorkingDirectory(testProjectDirectory)
                .Execute("--launch-profile", "IIS Express")
                .Should().Pass()
                         .And.HaveStdOutContaining("(NO MESSAGE)")
                         .And.HaveStdErrContaining(string.Format(CliCommandStrings.RunCommandExceptionCouldNotApplyLaunchSettings, "IIS Express", "").Trim());
        }
 
        [Fact]
        public void ItSkipsLaunchProfilesWhenTheSwitchIsSupplied()
        {
            var testAppName = "AppWithLaunchSettings";
            var testInstance = _testAssetsManager.CopyTestAsset(testAppName)
                            .WithSource();
 
            var testProjectDirectory = testInstance.Path;
 
            var cmd = new DotnetCommand(Log, "run")
                .WithWorkingDirectory(testProjectDirectory)
                .Execute("--no-launch-profile");
 
            cmd.Should().Pass()
                .And.HaveStdOutContaining("(NO MESSAGE)");
 
            cmd.StdErr.Should().BeEmpty();
        }
 
        [Fact]
        public void ItSkipsLaunchProfilesWhenTheSwitchIsSuppliedWithoutErrorWhenThereAreNoLaunchSettings()
        {
            var testAppName = "MSBuildTestApp";
            var testInstance = _testAssetsManager.CopyTestAsset(testAppName)
                            .WithSource();
 
            var testProjectDirectory = testInstance.Path;
 
            var cmd = new DotnetCommand(Log, "run")
                .WithWorkingDirectory(testProjectDirectory)
                .Execute("--no-launch-profile");
 
            cmd.Should().Pass()
                .And.HaveStdOutContaining("Hello World!");
 
            cmd.StdErr.Should().BeEmpty();
        }
 
        [Fact]
        public void ItSkipsLaunchProfilesWhenThereIsNoUsableDefault()
        {
            var testAppName = "AppWithLaunchSettingsNoDefault";
            var testInstance = _testAssetsManager.CopyTestAsset(testAppName)
                            .WithSource();
 
            var testProjectDirectory = testInstance.Path;
 
            var cmd = new DotnetCommand(Log, "run")
                .WithWorkingDirectory(testProjectDirectory)
                .Execute();
 
            cmd.Should().Pass()
                .And.HaveStdOutContaining("(NO MESSAGE)")
                .And.HaveStdErrContaining(string.Format(CliCommandStrings.RunCommandExceptionCouldNotApplyLaunchSettings, CliCommandStrings.DefaultLaunchProfileDisplayName, "").Trim());
        }
 
        [Fact]
        public void ItPrintsAnErrorWhenLaunchSettingsAreCorrupted()
        {
            var testAppName = "AppWithCorruptedLaunchSettings";
            var testInstance = _testAssetsManager.CopyTestAsset(testAppName)
                            .WithSource();
 
            var testProjectDirectory = testInstance.Path;
 
            var cmd = new DotnetCommand(Log, "run")
                .WithWorkingDirectory(testProjectDirectory)
                .Execute();
 
            cmd.Should().Pass()
                .And.HaveStdOutContaining("(NO MESSAGE)")
                .And.HaveStdErrContaining(string.Format(CliCommandStrings.RunCommandExceptionCouldNotApplyLaunchSettings, CliCommandStrings.DefaultLaunchProfileDisplayName, "").Trim());
        }
 
        [Fact]
        public void ItRunsWithTheSpecifiedVerbosity()
        {
            var testAppName = "MSBuildTestApp";
            var testInstance = _testAssetsManager.CopyTestAsset(testAppName)
                            .WithSource();
 
            var result = new DotnetCommand(Log, "run")
                .WithWorkingDirectory(testInstance.Path)
                .Execute("-v:n");
 
            result.Should().Pass()
                .And.HaveStdOutContaining("Hello World!");
 
            if (!TestContext.IsLocalized())
            {
                result.Should().HaveStdOutContaining("Restore")
                    .And.HaveStdOutContaining("CoreCompile");
            }
        }
 
        [Fact]
        public void ItDoesNotShowImportantLevelMessageByDefaultWhenInteractivityDisabled()
        {
            var testAppName = "MSBuildTestApp";
            var testInstance = _testAssetsManager.CopyTestAsset(testAppName)
                .WithSource()
                .WithProjectChanges(ProjectModification.AddDisplayMessageBeforeRestoreToProject);
 
            var result = new DotnetCommand(Log, "run", "--interactive", "false")
                .WithWorkingDirectory(testInstance.Path)
                .Execute();
 
            // this message should show because interactivity (and therefore nuget auth) is the default
            result.Should().Pass()
                .And.NotHaveStdOutContaining("Important text");
        }
 
        /// <summary>
        /// default verbosity for `run` is as quiet as possible, so it does not show important messages.
        /// NuGet authentication messages _are_ shown, but all other non-warning/-error messages are not.
        /// </summary>
        [Fact]
        public void ItDoesNotShowImportantLevelMessageWhenPassInteractive()
        {
            var testAppName = "MSBuildTestApp";
            var testInstance = _testAssetsManager.CopyTestAsset(testAppName)
                .WithSource()
                .WithProjectChanges(ProjectModification.AddDisplayMessageBeforeRestoreToProject);
 
            var result = new DotnetCommand(Log, "run")
                .WithWorkingDirectory(testInstance.Path)
                .Execute("--interactive");
 
            result.Should().Pass()
                .And.NotHaveStdOutContaining("Important text");
        }
 
        [Fact]
        public void ItShowsImportantLevelMessageWhenPassInteractiveAndVerbose()
        {
            var testAppName = "MSBuildTestApp";
            var testInstance = _testAssetsManager.CopyTestAsset(testAppName)
                .WithSource()
                .WithProjectChanges(ProjectModification.AddDisplayMessageBeforeRestoreToProject);
 
            var result = new DotnetCommand(Log, "run", "/v", "d")
                .WithWorkingDirectory(testInstance.Path)
                .Execute("--interactive");
 
            result.Should().Pass()
                .And.HaveStdOutContaining("Important text");
        }
 
 
        [Fact]
        public void ItPrintsDuplicateArguments()
        {
            var testAppName = "MSBuildTestApp";
            var testInstance = _testAssetsManager.CopyTestAsset(testAppName)
                .WithSource();
 
            var result = new DotnetCommand(Log, "run")
                .WithWorkingDirectory(testInstance.Path)
                .Execute("a", "b", "c", "a", "c");
 
            result.Should().Pass()
                .And.HaveStdOutContaining("echo args:a;b;c;a;c");
        }
 
        [Fact]
        public void ItRunsWithDotnetWithoutApphost()
        {
            var testInstance = _testAssetsManager.CopyTestAsset("AppOutputsExecutablePath").WithSource();
 
            var command = new DotnetCommand(Log, "run")
                .WithWorkingDirectory(testInstance.Path)
                .WithEnvironmentVariable("UseAppHost", "false");
 
            command.Execute()
                   .Should()
                   .Pass()
                   .And
                   .HaveStdOutContaining($"dotnet{Constants.ExeSuffix}");
        }
 
        [PlatformSpecificFact(TestPlatforms.Windows | TestPlatforms.Linux | TestPlatforms.FreeBSD)]
        public void ItRunsWithApphost()
        {
            var testInstance = _testAssetsManager.CopyTestAsset("AppOutputsExecutablePath").WithSource();
 
            var result = new DotnetCommand(Log, "run")
                .WithWorkingDirectory(testInstance.Path)
                .Execute();
 
            result.Should().Pass()
                .And.HaveStdOutContaining($"AppOutputsExecutablePath{Constants.ExeSuffix}");
        }
 
        [Fact]
        public void ItForwardsEmptyArgumentsToTheApp()
        {
            var testAppName = "TestAppSimple";
            var testInstance = _testAssetsManager.CopyTestAsset(testAppName)
                .WithSource();
 
            new DotnetCommand(Log, "run")
                .WithWorkingDirectory(testInstance.Path)
                .Execute("a", "", "c")
                .Should()
                .Pass()
                .And
                .HaveStdOutContaining($"0 = a{Environment.NewLine}1 = {Environment.NewLine}2 = c");
        }
 
        [Fact]
        public void ItDoesNotPrintBuildingMessageByDefault()
        {
            var expectedValue = "Building...";
            var testAppName = "TestAppSimple";
            var testInstance = _testAssetsManager.CopyTestAsset(testAppName)
                .WithSource();
 
            new DotnetCommand(Log, "run")
               .WithWorkingDirectory(testInstance.Path)
               .Execute()
               .Should()
               .Pass()
               .And
               .NotHaveStdOutContaining(expectedValue);
        }
 
        [Fact]
        public void ItPrintsBuildingMessageIfLaunchSettingHasDotnetRunMessagesSet()
        {
            var expectedValue = "Building...";
            var testAppName = "TestAppWithLaunchSettings";
            var testInstance = _testAssetsManager.CopyTestAsset(testAppName)
                .WithSource();
 
            new DotnetCommand(Log, "run")
               .WithWorkingDirectory(testInstance.Path)
               .Execute()
               .Should()
               .Pass()
               .And
               .HaveStdOutContaining(expectedValue);
        }
 
        [Fact]
        public void ItIncludesEnvironmentVariablesSpecifiedInLaunchSettings()
        {
            var expectedValue = "MyCoolEnvironmentVariableKey=MyCoolEnvironmentVariableValue";
            var testAppName = "TestAppWithLaunchSettings";
            var testInstance = _testAssetsManager.CopyTestAsset(testAppName)
                .WithSource();
 
            new DotnetCommand(Log, "run")
               .WithWorkingDirectory(testInstance.Path)
               .Execute()
               .Should()
               .Pass()
               .And
               .HaveStdOutContaining(expectedValue);
        }
 
        [Fact]
        public void EnvVariablesSpecifiedInLaunchProfileOverrideImplicitlySetVariables()
        {
            var testAppName = "TestAppWithLaunchSettings";
            var testInstance = _testAssetsManager.CopyTestAsset(testAppName)
                .WithSource();
 
            // Profile2 defines env variable DOTNET_LAUNCH_PROFILE=XYZ and ASPNETCORE_URLS=XYZ
 
            new DotnetCommand(Log, "run", "-lp", "Profile2")
               .WithWorkingDirectory(testInstance.Path)
               .Execute()
               .Should()
               .Pass()
               .And
               .HaveStdOutContaining("env: DOTNET_LAUNCH_PROFILE=XYZ")
               .And
               .HaveStdOutContaining("env: ASPNETCORE_URLS=XYZ");
        }
 
        [Fact]
        public void ItIncludesCommandArgumentsSpecifiedInLaunchSettings()
        {
            var testInstance = _testAssetsManager.CopyTestAsset("TestAppWithLaunchSettings")
                .WithSource();
 
            // launchSettings.json specifies commandLineArgs="TestAppCommandLineArguments SecondTestAppCommandLineArguments"
 
            new DotnetCommand(Log, "run")
               .WithWorkingDirectory(testInstance.Path)
               .Execute()
               .Should()
               .Pass()
               .And
               .HaveStdOutContaining("TestAppCommandLineArguments")
               .And
               .HaveStdOutContaining("SecondTestAppCommandLineArguments");
        }
 
        [Fact]
        public void ItIgnoresCommandArgumentsSpecifiedInLaunchSettings()
        {
            var testInstance = _testAssetsManager.CopyTestAsset("TestAppWithLaunchSettings")
                .WithSource();
 
            // launchSettings.json specifies commandLineArgs="TestAppCommandLineArguments SecondTestAppCommandLineArguments"
 
            new DotnetCommand(Log, "run", "--no-launch-profile-arguments")
               .WithWorkingDirectory(testInstance.Path)
               .Execute()
               .Should()
               .Pass()
               .And
               .NotHaveStdOutContaining("TestAppCommandLineArguments")
               .And
               .NotHaveStdOutContaining("SecondTestAppCommandLineArguments");
        }
 
        [Fact]
        public void ItCLIArgsOverrideCommandArgumentsSpecifiedInLaunchSettings()
        {
            var expectedValue = "TestAppCommandLineArguments";
            var secondExpectedValue = "SecondTestAppCommandLineArguments";
            var testAppName = "TestAppWithLaunchSettings";
            var testInstance = _testAssetsManager.CopyTestAsset(testAppName)
                .WithSource();
 
            new DotnetCommand(Log, "run", "-- test")
               .WithWorkingDirectory(testInstance.Path)
               .Execute()
               .Should()
               .Pass()
               .And
               .NotHaveStdOutContaining(expectedValue)
               .And
               .NotHaveStdOutContaining(secondExpectedValue);
        }
 
        [Fact]
        public void ItIncludesApplicationUrlSpecifiedInLaunchSettings()
        {
            var testInstance = _testAssetsManager.CopyTestAsset("TestAppWithLaunchSettings")
                .WithSource();
 
            new DotnetCommand(Log, "run")
               .WithWorkingDirectory(testInstance.Path)
               .Execute()
               .Should()
               .Pass()
               .And
               .HaveStdOutContaining("env: ASPNETCORE_URLS=http://localhost:5000");
        }
 
        [Theory]
        [InlineData("-e")]
        [InlineData("--environment")]
        public void EnvOptionOverridesCommandArgumentsSpecifiedInLaunchSettings(string optionName)
        {
            var testInstance = _testAssetsManager.CopyTestAsset("TestAppWithLaunchSettings")
                .WithSource();
 
            new DotnetCommand(Log, "run", optionName, "MyCoolEnvironmentVariableKey=OverriddenEnvironmentVariableValue")
               .WithWorkingDirectory(testInstance.Path)
               .Execute()
               .Should()
               .Pass()
               .And
               .HaveStdOutContaining("env: MyCoolEnvironmentVariableKey=OverriddenEnvironmentVariableValue");
        }
 
        [Fact]
        public void EnvOptionOverridesImplicitlySetVariables()
        {
            var testInstance = _testAssetsManager.CopyTestAsset("TestAppWithLaunchSettings")
                .WithSource();
 
            //
            var dotnetLaunchProfile = RuntimeInformation.IsOSPlatform(OSPlatform.Windows)
                ? "DOTNET_LAUNCH_profile"
                : "DOTNET_LAUNCH_PROFILE";
 
            new DotnetCommand(Log, "run", "-e", $"{dotnetLaunchProfile}=1", "-e", "ASPNETCORE_URLS=2")
               .WithWorkingDirectory(testInstance.Path)
               .Execute()
               .Should()
               .Pass()
               .And
               .HaveStdOutContaining("env: DOTNET_LAUNCH_PROFILE=1")
               .And
               .HaveStdOutContaining("env: ASPNETCORE_URLS=2");
        }
 
        [Fact]
        public void EnvOptionNotAppliedToBuild()
        {
            var testInstance = _testAssetsManager.CopyTestAsset("TestAppWithLaunchSettings")
                .WithSource();
 
            new DotnetCommand(Log, "run", "-e", "Configuration=XYZ")
               .WithWorkingDirectory(testInstance.Path)
               .Execute()
               .Should()
               .Pass()
               .And
               .HaveStdOutContaining("env: Configuration=XYZ");
        }
 
        [Fact]
        public void ItProvidesConsistentErrorMessageWhenProjectFileDoesNotExistWithNoBuild()
        {
            var tempDir = _testAssetsManager.CreateTestDirectory();
            var nonExistentProject = Path.Combine(tempDir.Path, "nonexistent.csproj");
 
            var result = new DotnetCommand(Log, "run")
                .WithWorkingDirectory(tempDir.Path)
                .Execute("--project", nonExistentProject, "--no-build");
 
            result.Should().Fail();
            if (!TestContext.IsLocalized())
            {
                // After the fix, we should get a clear error message about the file not existing
                var stderr = result.StdErr;
                
                // Should provide a clear error message about the project file not existing
                var hasExpectedErrorMessage = stderr.Contains("does not exist") || 
                                              stderr.Contains("not found") || 
                                              stderr.Contains("cannot find") || 
                                              stderr.Contains("could not find");
                                              
                hasExpectedErrorMessage.Should().BeTrue($"Expected error message to clearly indicate file doesn't exist, but got: {stderr}");
            }
        }
    }
}