diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index beabe34a69c9..56eddb899a16 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -6,6 +6,13 @@ Coding Style and Changes: Testing: - Large changes should always include test changes. - The Skip parameter of the Fact attribute to point to the specific issue link. +- To run tests in this repo: + - Use the repo-local dotnet instance: `./.dotnet/dotnet` + - For MSTest-style projects: `dotnet test path/to/project.csproj --filter "FullyQualifiedName~TestName"` + - For XUnit test assemblies: `dotnet exec artifacts/bin/redist/Debug/TestAssembly.dll -method "*TestMethodName*"` + - Examples: + - `dotnet test test/dotnet.Tests/dotnet.Tests.csproj --filter "Name~ItShowsTheAppropriateMessageToTheUser"` + - `dotnet exec artifacts/bin/redist/Debug/dotnet.Tests.dll -method "*ItShowsTheAppropriateMessageToTheUser*"` Output Considerations: - When considering how output should look, solicit advice from baronfel. diff --git a/src/Cli/dotnet/Program.cs b/src/Cli/dotnet/Program.cs index 7762b77e8c09..e62af96e193a 100644 --- a/src/Cli/dotnet/Program.cs +++ b/src/Cli/dotnet/Program.cs @@ -389,7 +389,7 @@ private static void ConfigureDotNetForFirstTimeUse( var environmentPath = EnvironmentPathFactory.CreateEnvironmentPath(isDotnetBeingInvokedFromNativeInstaller, environmentProvider); _ = new DotNetCommandFactory(alwaysRunOutOfProc: true); var aspnetCertificateGenerator = new AspNetCoreCertificateGenerator(); - var reporter = Reporter.Output; + var reporter = Reporter.Error; var dotnetConfigurer = new DotnetFirstTimeUseConfigurer( firstTimeUseNoticeSentinel, aspNetCertificateSentinel, diff --git a/test/dotnet.Tests/GivenThatTheUserIsRunningDotNetForTheFirstTime.cs b/test/dotnet.Tests/GivenThatTheUserIsRunningDotNetForTheFirstTime.cs index 77abe37fecfc..b67afbf7dacd 100644 --- a/test/dotnet.Tests/GivenThatTheUserIsRunningDotNetForTheFirstTime.cs +++ b/test/dotnet.Tests/GivenThatTheUserIsRunningDotNetForTheFirstTime.cs @@ -103,12 +103,12 @@ public void UsingDotnetForTheFirstTimeWithNonVerbsDoesNotPrintEula() .StartWith(firstTimeNonVerbUseMessage); } - [WindowsOnlyFact] + [Fact] public void ItShowsTheAppropriateMessageToTheUser() { var expectedVersion = GetDotnetVersion(); - _fixture.FirstDotnetVerbUseCommandResult.StdOut + _fixture.FirstDotnetVerbUseCommandResult.StdErr .Should() .ContainVisuallySameFragment(string.Format( Configurer.LocalizableStrings.FirstTimeMessageWelcome, @@ -118,6 +118,30 @@ public void ItShowsTheAppropriateMessageToTheUser() .And.NotContain("Restore completed in"); } + [WindowsOnlyFact] + public void FirstRunExperienceMessagesShouldGoToStdErr() + { + // This test ensures that first-run experience messages go to stderr, + // not stdout, to avoid interfering with completion commands and other + // tools that parse stdout. See: https://github.com/dotnet/sdk/issues/50444 + var expectedVersion = GetDotnetVersion(); + + // StdErr should contain first-run messages + _fixture.FirstDotnetVerbUseCommandResult.StdErr + .Should() + .ContainVisuallySameFragment(string.Format( + Configurer.LocalizableStrings.FirstTimeMessageWelcome, + DotnetFirstTimeUseConfigurer.ParseDotNetVersion(expectedVersion), + expectedVersion)) + .And.ContainVisuallySameFragment(Configurer.LocalizableStrings.FirstTimeMessageMoreInformation); + + // StdOut should NOT contain first-run messages (they should only be in stderr) + _fixture.FirstDotnetVerbUseCommandResult.StdOut + .Should() + .NotContain("Welcome to .NET") + .And.NotContain("Write your first app"); + } + [Fact] public void ItCreatesAFirstUseSentinelFileUnderTheDotDotNetFolder() { @@ -164,7 +188,7 @@ public void ItShowsTheTelemetryNoticeWhenInvokingACommandAfterInternalReportInst var expectedVersion = GetDotnetVersion(); - result.StdOut + result.StdErr .Should() .ContainVisuallySameFragment(string.Format( Configurer.LocalizableStrings.FirstTimeMessageWelcome,