Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

// MSTest-friendly mirror of the shared
// src\TemplateEngine\Tools\Shared\Microsoft.TemplateEngine.CommandUtils\CommandResultAssertions.cs.
//
// The shared file uses Xunit's Assert.True / Assert.False / Assert.NotNull APIs. When this
// project runs under MSTest.Sdk those names resolve to MSTest's Assert (via its implicit
// global using of Microsoft.VisualStudio.TestTools.UnitTesting) which does not expose those
// methods. Rather than dragging the Xunit global using in (which would conflict with MSTest's
// Assert), we exclude the shared file in the csproj and provide this local copy that uses the
// equivalent MSTest APIs: Assert.IsTrue / Assert.IsFalse / Assert.IsNotNull.

using System.Text.RegularExpressions;

namespace Microsoft.TemplateEngine.CommandUtils
{
internal class CommandResultAssertions
{
private readonly CommandResult _commandResult;

internal CommandResultAssertions(CommandResult commandResult)
{
_commandResult = commandResult;
}

internal CommandResultAssertions And => this;

internal CommandResultAssertions ExitWith(int expectedExitCode)
{
Assert.IsTrue(expectedExitCode == _commandResult.ExitCode, AppendDiagnosticsTo($"Expected command to exit with {expectedExitCode} but it did not."));
return this;
}

internal CommandResultAssertions Pass()
{
Assert.IsTrue(_commandResult.ExitCode == 0, AppendDiagnosticsTo("Expected command to pass but it did not."));
return this;
}

internal CommandResultAssertions Fail()
{
Assert.IsFalse(_commandResult.ExitCode == 0, AppendDiagnosticsTo("Expected command to fail but it passed."));
return this;
}

internal CommandResultAssertions HaveStdOut()
{
Assert.IsFalse(string.IsNullOrEmpty(_commandResult.StdOut), AppendDiagnosticsTo("Expected command to have standard output but it did not."));
return this;
}

internal CommandResultAssertions HaveStdOut(string expectedOutput)
{
Assert.IsNotNull(_commandResult.StdOut);
Assert.IsTrue(expectedOutput == _commandResult.StdOut, AppendDiagnosticsTo($"Expected standard output to be '{expectedOutput}' but it was not."));
return this;
}

internal CommandResultAssertions HaveStdOutContaining(string pattern)
{
Assert.IsNotNull(_commandResult.StdOut);
Assert.IsTrue(_commandResult.StdOut.Contains(pattern, StringComparison.Ordinal), AppendDiagnosticsTo($"Expected standard output to contain '{pattern}' but it did not."));
return this;
}

internal CommandResultAssertions HaveStdOutContaining(Func<string, bool> predicate, string description = "")
{
Assert.IsNotNull(_commandResult.StdOut);
Assert.IsTrue(predicate(_commandResult.StdOut), $"The command output did not contain expected result: {description} {Environment.NewLine}");
return this;
}

internal CommandResultAssertions NotHaveStdOutContaining(string pattern)
{
Assert.IsNotNull(_commandResult.StdOut);
Assert.IsTrue(!_commandResult.StdOut.Contains(pattern, StringComparison.Ordinal), AppendDiagnosticsTo($"Expected standard output to not contain '{pattern}' but it did."));
return this;
}

internal CommandResultAssertions HaveStdOutContainingIgnoreSpaces(string pattern)
{
Assert.IsNotNull(_commandResult.StdOut);
string commandResultNoSpaces = _commandResult.StdOut.Replace(" ", string.Empty);
Assert.IsTrue(commandResultNoSpaces.Contains(pattern, StringComparison.Ordinal), AppendDiagnosticsTo($"Expected standard output to contain '{pattern}' but it did not."));
return this;
}

internal CommandResultAssertions HaveStdOutContainingIgnoreCase(string pattern)
{
Assert.IsNotNull(_commandResult.StdOut);
Assert.IsTrue(_commandResult.StdOut.Contains(pattern, StringComparison.OrdinalIgnoreCase), AppendDiagnosticsTo($"Expected standard output to contain '{pattern}' but it did not."));
return this;
}

internal CommandResultAssertions HaveStdOutMatching(string pattern, RegexOptions options = RegexOptions.None)
{
Assert.IsNotNull(_commandResult.StdOut);
Assert.IsTrue(Regex.Match(_commandResult.StdOut, pattern, options).Success, AppendDiagnosticsTo($"Expected standard output to match pattern '{pattern}' but it did not."));
return this;
}

internal CommandResultAssertions NotHaveStdOutMatching(string pattern, RegexOptions options = RegexOptions.None)
{
Assert.IsNotNull(_commandResult.StdOut);
Assert.IsTrue(!Regex.Match(_commandResult.StdOut, pattern, options).Success, AppendDiagnosticsTo($"Expected standard output to not match pattern '{pattern}' but it did."));
return this;
}

internal CommandResultAssertions HaveStdErr()
{
Assert.IsNotNull(_commandResult.StdErr);
Assert.IsFalse(string.IsNullOrEmpty(_commandResult.StdErr), AppendDiagnosticsTo("Expected command to have standard error but it did not."));
return this;
}

internal CommandResultAssertions HaveStdErr(string expectedOutput)
{
Assert.IsNotNull(_commandResult.StdErr);
Assert.IsTrue(expectedOutput == _commandResult.StdErr, AppendDiagnosticsTo($"Expected standard error to be '{expectedOutput}' but it was not."));
return this;
}

internal CommandResultAssertions HaveStdErrContaining(string pattern)
{
Assert.IsNotNull(_commandResult.StdErr);
Assert.IsTrue(_commandResult.StdErr.Contains(pattern, StringComparison.Ordinal), AppendDiagnosticsTo($"Expected standard error to contain '{pattern}' but it did not."));
return this;
}

internal CommandResultAssertions NotHaveStdErrContaining(string pattern)
{
Assert.IsNotNull(_commandResult.StdErr);
Assert.IsTrue(!_commandResult.StdErr.Contains(pattern, StringComparison.Ordinal), AppendDiagnosticsTo($"Expected standard error to contain '{pattern}' but it did not."));
return this;
}

internal CommandResultAssertions HaveStdErrMatching(string pattern, RegexOptions options = RegexOptions.None)
{
Assert.IsNotNull(_commandResult.StdErr);
Assert.IsTrue(Regex.Match(_commandResult.StdErr, pattern, options).Success, AppendDiagnosticsTo($"Expected standard error to match pattern '{pattern}' but it did not."));
return this;
}

internal CommandResultAssertions NotHaveStdOut()
{
Assert.IsNotNull(_commandResult.StdOut);
Assert.IsTrue(string.IsNullOrEmpty(_commandResult.StdOut), AppendDiagnosticsTo("Expected command to not have standard output but it did."));
return this;
}

internal CommandResultAssertions NotHaveStdErr()
{
Assert.IsNotNull(_commandResult.StdErr);
Assert.IsTrue(string.IsNullOrEmpty(_commandResult.StdErr), AppendDiagnosticsTo("Expected command to not have standard error but it did."));
return this;
}

internal CommandResultAssertions HaveSkippedProjectCompilation(string skippedProject, string frameworkFullName)
{
Assert.IsNotNull(_commandResult.StdOut);
Assert.IsTrue(_commandResult.StdOut.Contains($"Project {skippedProject} ({frameworkFullName}) was previously compiled. Skipping compilation.", StringComparison.Ordinal), AppendDiagnosticsTo($"Expected standard output to contain 'Project {skippedProject} ({frameworkFullName}) was previously compiled. Skipping compilation.' but it did not."));
return this;
}

internal CommandResultAssertions HaveCompiledProject(string compiledProject, string frameworkFullName)
{
Assert.IsNotNull(_commandResult.StdOut);
Assert.IsTrue(_commandResult.StdOut.Contains($"Project {compiledProject} ({frameworkFullName}) will be compiled", StringComparison.Ordinal), AppendDiagnosticsTo($"Expected standard output to contain 'Project {compiledProject} ({frameworkFullName}) will be compiled' but it did not."));
return this;
}

private string AppendDiagnosticsTo(string s)
{
return (s + $"{Environment.NewLine}" +
$"File Name: {_commandResult.StartInfo.FileName}{Environment.NewLine}" +
$"Arguments: {_commandResult.StartInfo.Arguments}{Environment.NewLine}" +
$"Exit Code: {_commandResult.ExitCode}{Environment.NewLine}" +
$"StdOut:{Environment.NewLine}{_commandResult.StdOut}{Environment.NewLine}" +
$"StdErr:{Environment.NewLine}{_commandResult.StdErr}{Environment.NewLine}")
//escape curly braces for String.Format
.Replace("{", "{{").Replace("}", "}}");
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

// The shared Microsoft.TemplateEngine.CommandUtils sources (compiled into this project
// via <Compile Include="$(TemplateEngSrcDir)Tools\Shared\**\*.cs" />) reference
// xUnit's ITestOutputHelper by its short name. The Xunit type is provided
// transitively (compile-only) through the Microsoft.TemplateEngine.TestHelper project
// reference, but the global using normally added by xunit.v3.extensibility.core's
// build targets does not flow through ProjectReferences. We add the minimal alias
// here so the shared file compiles without dragging the entire Xunit global using
// (which would conflict with MSTest's Assert).
global using ITestOutputHelper = Xunit.ITestOutputHelper;
Original file line number Diff line number Diff line change
@@ -1,37 +1,35 @@
// Licensed to the .NET Foundation under one or more agreements.
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using Microsoft.Extensions.Logging;
using Microsoft.TemplateEngine.CommandUtils;
using Microsoft.TemplateEngine.TestHelper;
using Microsoft.TemplateEngine.Tests;
using Xunit;

namespace Microsoft.TemplateEngine.Authoring.Tasks.IntegrationTests
{
[TestClass]
public class LocalizeTemplateTests : TestBase
{
private readonly ITestOutputHelper _log;
public TestContext TestContext { get; set; } = null!;

public LocalizeTemplateTests(ITestOutputHelper log)
{
_log = log;
}
private ILogger Log => new TestContextLogger(TestContext);

[Fact]
[TestMethod]
public void CanRunTask()
{
string tmpDir = TestUtils.CreateTemporaryFolder();
TestUtils.DirectoryCopy("Resources/BasicTemplatePackage", tmpDir, true);
SetupNuGetConfigForPackagesLocation(tmpDir);

new DotnetCommand(_log, "add", "TemplatePackage.csproj", "package", "Microsoft.TemplateEngine.Authoring.Tasks", "--prerelease")
new DotnetCommand(Log, "add", "TemplatePackage.csproj", "package", "Microsoft.TemplateEngine.Authoring.Tasks", "--prerelease")
.WithoutTelemetry()
.WithWorkingDirectory(tmpDir)
.Execute()
.Should()
.Pass();

new DotnetCommand(_log, "build")
new DotnetCommand(Log, "build")
.WithoutTelemetry()
.WithWorkingDirectory(tmpDir)
.Execute()
Expand All @@ -40,28 +38,28 @@ public void CanRunTask()

string locFolder = Path.Combine(tmpDir, "content/TemplateWithSourceName/.template.config/localize");

Assert.True(Directory.Exists(locFolder));
Assert.Equal(14, Directory.GetFiles(locFolder).Length);
Assert.True(File.Exists(Path.Combine(locFolder, "templatestrings.de.json")));
Assert.IsTrue(Directory.Exists(locFolder));
Assert.AreEqual(14, Directory.GetFiles(locFolder).Length);
Assert.IsTrue(File.Exists(Path.Combine(locFolder, "templatestrings.de.json")));

Directory.Delete(tmpDir, true);
}

[Fact]
[TestMethod]
public void CanRunTaskSelectedLangs()
{
string tmpDir = TestUtils.CreateTemporaryFolder();
TestUtils.DirectoryCopy("Resources/TemplatePackageEnDe", tmpDir, true);
SetupNuGetConfigForPackagesLocation(tmpDir);

new DotnetCommand(_log, "add", "TemplatePackage.csproj", "package", "Microsoft.TemplateEngine.Authoring.Tasks", "--prerelease")
new DotnetCommand(Log, "add", "TemplatePackage.csproj", "package", "Microsoft.TemplateEngine.Authoring.Tasks", "--prerelease")
.WithoutTelemetry()
.WithWorkingDirectory(tmpDir)
.Execute()
.Should()
.Pass();

new DotnetCommand(_log, "build")
new DotnetCommand(Log, "build")
.WithoutTelemetry()
.WithWorkingDirectory(tmpDir)
.Execute()
Expand All @@ -70,29 +68,29 @@ public void CanRunTaskSelectedLangs()

string locFolder = Path.Combine(tmpDir, "content/TemplateWithSourceName/.template.config/localize");

Assert.True(Directory.Exists(locFolder));
Assert.Equal(2, Directory.GetFiles(locFolder).Length);
Assert.True(File.Exists(Path.Combine(locFolder, "templatestrings.de.json")));
Assert.False(File.Exists(Path.Combine(locFolder, "templatestrings.fr.json")));
Assert.IsTrue(Directory.Exists(locFolder));
Assert.AreEqual(2, Directory.GetFiles(locFolder).Length);
Assert.IsTrue(File.Exists(Path.Combine(locFolder, "templatestrings.de.json")));
Assert.IsFalse(File.Exists(Path.Combine(locFolder, "templatestrings.fr.json")));

Directory.Delete(tmpDir, true);
}

[Fact]
[TestMethod]
public void CanRunTaskSelectedTemplates()
{
string tmpDir = TestUtils.CreateTemporaryFolder();
TestUtils.DirectoryCopy("Resources/TemplatePackagePartiallyLocalized", tmpDir, true);
SetupNuGetConfigForPackagesLocation(tmpDir);

new DotnetCommand(_log, "add", "TemplatePackage.csproj", "package", "Microsoft.TemplateEngine.Authoring.Tasks", "--prerelease")
new DotnetCommand(Log, "add", "TemplatePackage.csproj", "package", "Microsoft.TemplateEngine.Authoring.Tasks", "--prerelease")
.WithoutTelemetry()
.WithWorkingDirectory(tmpDir)
.Execute()
.Should()
.Pass();

new DotnetCommand(_log, "build")
new DotnetCommand(Log, "build")
.WithoutTelemetry()
.WithWorkingDirectory(tmpDir)
.Execute()
Expand All @@ -102,29 +100,29 @@ public void CanRunTaskSelectedTemplates()
string locFolder = Path.Combine(tmpDir, "content/localized/.template.config/localize");
string noLocFolder = Path.Combine(tmpDir, "content/non-localized/.template.config/localize");

Assert.True(Directory.Exists(locFolder));
Assert.Equal(14, Directory.GetFiles(locFolder).Length);
Assert.True(File.Exists(Path.Combine(locFolder, "templatestrings.de.json")));
Assert.False(Directory.Exists(noLocFolder));
Assert.IsTrue(Directory.Exists(locFolder));
Assert.AreEqual(14, Directory.GetFiles(locFolder).Length);
Assert.IsTrue(File.Exists(Path.Combine(locFolder, "templatestrings.de.json")));
Assert.IsFalse(Directory.Exists(noLocFolder));

Directory.Delete(tmpDir, true);
}

[Fact]
[TestMethod]
public void CanRunTaskAndDetectError()
{
string tmpDir = TestUtils.CreateTemporaryFolder();
TestUtils.DirectoryCopy("Resources/InvalidTemplatePackage", tmpDir, true);
SetupNuGetConfigForPackagesLocation(tmpDir);

new DotnetCommand(_log, "add", "TemplatePackage.csproj", "package", "Microsoft.TemplateEngine.Authoring.Tasks", "--prerelease")
new DotnetCommand(Log, "add", "TemplatePackage.csproj", "package", "Microsoft.TemplateEngine.Authoring.Tasks", "--prerelease")
.WithoutTelemetry()
.WithWorkingDirectory(tmpDir)
.Execute()
.Should()
.Pass();

new DotnetCommand(_log, "build")
new DotnetCommand(Log, "build")
.WithoutTelemetry()
.WithWorkingDirectory(tmpDir)
.Execute()
Expand All @@ -135,9 +133,8 @@ public void CanRunTaskAndDetectError()

string locFolder = Path.Combine(tmpDir, "content/TemplateWithSourceName/.template.config/localize");

Assert.False(Directory.Exists(locFolder));
Assert.IsFalse(Directory.Exists(locFolder));
Directory.Delete(tmpDir, true);
}

}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="MSTest.Sdk">

<PropertyGroup>
<TargetFramework>$(NetCurrent)</TargetFramework>
Expand All @@ -9,11 +9,6 @@
<Compile Remove="Resources\**\*" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="Verify.XunitV3" />
<PackageReference Include="Verify.DiffPlex" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="$(TemplateEngSrcDir)Tools/Microsoft.TemplateEngine.Authoring.Tasks\Microsoft.TemplateEngine.Authoring.Tasks.csproj" />
<ProjectReference Include="$(TemplateEngTestDir)Microsoft.TemplateEngine.TestHelper\Microsoft.TemplateEngine.TestHelper.csproj" />
Expand All @@ -25,6 +20,9 @@

<ItemGroup>
<Compile Include="$(TemplateEngSrcDir)Tools\Shared\**\*.cs" Link="%(RecursiveDir)%(Filename)%(Extension)" />
<!-- The shared CommandResultAssertions.cs uses xUnit's Assert.True/False/NotNull which clash
with MSTest's Assert global using. Replace it with a local MSTest-friendly copy below. -->
<Compile Remove="$(TemplateEngSrcDir)Tools\Shared\Microsoft.TemplateEngine.CommandUtils\CommandResultAssertions.cs" />
</ItemGroup>

</Project>
Loading
Loading