|
// 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 System.Runtime.CompilerServices;
using Microsoft.DotNet.Cli.Utils;
using Microsoft.DotNet.Configurer;
//[assembly: CollectionBehavior(DisableTestParallelization = true)]
namespace Microsoft.DotNet.Tests
{
public class DotNetFirstTime
{
public DirectoryInfo NugetFallbackFolder;
public DirectoryInfo DotDotnetFolder;
public string TestDirectory;
public TestCommand Setup(ITestOutputHelper log, TestAssetsManager testAssets, [CallerMemberName] string testName = null)
{
TestDirectory = testAssets.CreateTestDirectory(testName).Path;
var testNuGetHome = Path.Combine(TestDirectory, "nuget_home");
var cliTestFallbackFolder = Path.Combine(testNuGetHome, ".dotnet", "NuGetFallbackFolder");
var profiled = Path.Combine(TestDirectory, "profile.d");
var pathsd = Path.Combine(TestDirectory, "paths.d");
var command = new DotnetCommand(log)
.WithWorkingDirectory(TestDirectory)
.WithEnvironmentVariable("APPDATA", testNuGetHome)
.WithEnvironmentVariable("DOTNET_CLI_TEST_FALLBACKFOLDER", cliTestFallbackFolder)
.WithEnvironmentVariable("DOTNET_CLI_TEST_LINUX_PROFILED_PATH", profiled)
.WithEnvironmentVariable("DOTNET_CLI_TEST_OSX_PATHSD_PATH", pathsd)
.WithEnvironmentVariable("SkipInvalidConfigurations", "true")
.WithEnvironmentVariable(CliFolderPathCalculator.DotnetHomeVariableName, testNuGetHome);
NugetFallbackFolder = new DirectoryInfo(cliTestFallbackFolder);
DotDotnetFolder = new DirectoryInfo(Path.Combine(testNuGetHome, ".dotnet"));
return command;
}
}
public class DotNetFirstTimeFixture : IDisposable
{
public CommandResult FirstDotnetNonVerbUseCommandResult;
public CommandResult FirstDotnetVerbUseCommandResult;
public CommandResult FirstDotnetWorkloadInfoResult;
public DirectoryInfo NugetFallbackFolder;
public DirectoryInfo DotDotnetFolder;
public string TestDirectory;
public Dictionary<string, string> ExtraEnvironmentVariables = new();
public void Init(ITestOutputHelper log, TestAssetsManager testAssets)
{
if (TestDirectory == null)
{
var dotnetFirstTime = new DotNetFirstTime();
var command = dotnetFirstTime.Setup(log, testAssets, testName: "Dotnet_first_time_experience_tests");
FirstDotnetNonVerbUseCommandResult = command.Execute("--info");
FirstDotnetVerbUseCommandResult = command.Execute("new", "--debug:ephemeral-hive");
TestDirectory = dotnetFirstTime.TestDirectory;
NugetFallbackFolder = dotnetFirstTime.NugetFallbackFolder;
DotDotnetFolder = dotnetFirstTime.DotDotnetFolder;
}
}
public void Dispose()
{
}
}
public class GivenThatTheUserIsRunningDotNetForTheFirstTime : SdkTest, IClassFixture<DotNetFirstTimeFixture>
{
DotNetFirstTimeFixture _fixture;
public GivenThatTheUserIsRunningDotNetForTheFirstTime(ITestOutputHelper log, DotNetFirstTimeFixture fixture) : base(log)
{
fixture.Init(log, _testAssetsManager);
_fixture = fixture;
}
[Fact]
public void UsingDotnetForTheFirstTimeSucceeds()
{
_fixture.FirstDotnetVerbUseCommandResult
.Should()
.Pass();
}
[Fact]
public void UsingDotnetForTheFirstTimeWithNonVerbsDoesNotPrintEula()
{
string firstTimeNonVerbUseMessage = Cli.Utils.LocalizableStrings.DotNetSdkInfoLabel;
_fixture.FirstDotnetNonVerbUseCommandResult.StdOut
.Should()
.StartWith(firstTimeNonVerbUseMessage);
}
[Fact]
public void ItShowsTheAppropriateMessageToTheUser()
{
var expectedVersion = GetDotnetVersion();
_fixture.FirstDotnetVerbUseCommandResult.StdErr
.Should()
.ContainVisuallySameFragment(string.Format(
Configurer.LocalizableStrings.FirstTimeMessageWelcome,
DotnetFirstTimeUseConfigurer.ParseDotNetVersion(expectedVersion),
expectedVersion))
.And.ContainVisuallySameFragment(Configurer.LocalizableStrings.FirstTimeMessageMoreInformation)
.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()
{
_fixture.DotDotnetFolder
.Should()
.HaveFile($"{GetDotnetVersion()}.dotnetFirstUseSentinel");
}
[Fact]
public void ItCreatesAnAspNetCertificateSentinelFileUnderTheDotDotNetFolder()
{
_fixture.DotDotnetFolder
.Should()
.HaveFile($"{GetDotnetVersion()}.aspNetCertificateSentinel");
}
[Fact]
public void ItDoesNotCreateAFirstUseSentinelFileNorAnAspNetCertificateSentinelFileUnderTheDotDotNetFolderWhenInternalReportInstallSuccessIsInvoked()
{
var dotnetFirstTime = new DotNetFirstTime();
var command = dotnetFirstTime.Setup(Log, _testAssetsManager);
// Disable telemetry to prevent the creation of the .dotnet folder
// for machineid and docker cache files
command = command.WithEnvironmentVariable("DOTNET_CLI_TELEMETRY_OPTOUT", "true");
command.Execute("internal-reportinstallsuccess", "test").Should().Pass();
var homeFolder = dotnetFirstTime.NugetFallbackFolder.Parent;
homeFolder.Should().NotExist();
}
[WindowsOnlyFact]
public void ItShowsTheTelemetryNoticeWhenInvokingACommandAfterInternalReportInstallSuccessHasBeenInvoked()
{
var dotnetFirstTime = new DotNetFirstTime();
var command = dotnetFirstTime.Setup(Log, _testAssetsManager);
command.Execute("internal-reportinstallsuccess", "test").Should().Pass();
var result = command.Execute("new", "--debug:ephemeral-hive");
var expectedVersion = GetDotnetVersion();
result.StdErr
.Should()
.ContainVisuallySameFragment(string.Format(
Configurer.LocalizableStrings.FirstTimeMessageWelcome,
DotnetFirstTimeUseConfigurer.ParseDotNetVersion(expectedVersion),
expectedVersion))
.And.ContainVisuallySameFragment(Configurer.LocalizableStrings.FirstTimeMessageMoreInformation);
}
[Fact]
public void ItShowsTheAspNetCertificateGenerationMessageWhenInvokingACommandAfterInternalReportInstallSuccessHasBeenInvoked()
{
var dotnetFirstTime = new DotNetFirstTime();
var command = dotnetFirstTime.Setup(Log, _testAssetsManager);
command.Execute("internal-reportinstallsuccess", "test").Should().Pass();
command.Execute("new", "--debug:ephemeral-hive");
}
[LinuxOnlyFact]
public void ItCreatesTheProfileFileOnLinuxWhenInvokedFromNativeInstaller()
{
var dotnetFirstTime = new DotNetFirstTime();
var command = dotnetFirstTime.Setup(Log, _testAssetsManager);
var profiled = Path.Combine(dotnetFirstTime.TestDirectory, "profile.d");
command.Execute("internal-reportinstallsuccess", "test").Should().Pass();
File.Exists(profiled).Should().BeTrue();
File.ReadAllText(profiled).Should().Be(
$"export PATH=\"$PATH:{CliFolderPathCalculator.ToolsShimPathInUnix.PathWithDollar}\"");
}
[MacOsOnlyFact]
public void ItCreatesThePathDFileOnMacOSWhenInvokedFromNativeInstaller()
{
var dotnetFirstTime = new DotNetFirstTime();
var command = dotnetFirstTime.Setup(Log, _testAssetsManager);
var pathsd = Path.Combine(dotnetFirstTime.TestDirectory, "paths.d");
command.Execute("internal-reportinstallsuccess", "test").Should().Pass();
File.Exists(pathsd).Should().BeTrue();
File.ReadAllText(pathsd).Should().Be(CliFolderPathCalculator.ToolsShimPathInUnix.PathWithTilde);
}
private string GetDotnetVersion()
{
return TestContext.Current.ToolsetUnderTest.SdkVersion;
}
}
}
|