|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using Microsoft.DotNet.Cli.Utils;
namespace Microsoft.DotNet.Cli.New.IntegrationTests
{
public partial class DotnetNewSearchTests : BaseIntegrationTest, IClassFixture<SharedHomeDirectory>
{
private readonly SharedHomeDirectory _sharedHome;
private readonly ITestOutputHelper _log;
public DotnetNewSearchTests(SharedHomeDirectory sharedHome, ITestOutputHelper log) : base(log)
{
_sharedHome = sharedHome;
_log = log;
}
[Theory]
[InlineData("console --search")]
[InlineData("--search console")]
[InlineData("search console")]
public void BasicTest(string testCase)
{
CommandResult commandResult = new DotnetNewCommand(_log, testCase.Split(" "))
.WithCustomHive(_sharedHome.HomeDirectory)
.Execute();
commandResult.Should()
.ExitWith(0)
.And.NotHaveStdErr()
.And.HaveStdOutContaining("Searching for the templates...")
.And.HaveStdOutContaining("Matches from template source: NuGet.org")
.And.HaveStdOutContaining("These templates matched your input: 'console'")
.And.HaveStdOutMatching("Template Name\\s+Short Name\\s+Language\\s+Package Name \\/ Owners\\s+Trusted\\s+Downloads")
.And.HaveStdOutContaining("To use the template, run the following command to install the package:")
.And.HaveStdOutContaining(" dotnet new install [<package>...]");
List<List<string>> tableOutput = ParseTableOutput(commandResult.StdOut, expectedColumns: new[] { "Template Name", "Short Name", "Language", "Package Name / Owners", "Trusted", "Downloads" });
Assert.True(AllRowsContain(tableOutput, new[] { "Template Name", "Short Name" }, "console"), "'Template Name' or 'Short Name' columns do not contain the criteria");
Assert.True(AtLeastOneRowIsNotEmpty(tableOutput, "Template Name"), "'Template Name' column contains empty values");
Assert.True(AtLeastOneRowIsNotEmpty(tableOutput, "Short Name"), "'Short Name' column contains empty values");
Assert.True(AllRowsAreNotEmpty(tableOutput, "Package Name / Owners"), "'Package Name / Owners' column contains empty values");
Assert.True(AtLeastOneRowIsNotEmpty(tableOutput, "Downloads"), "'Downloads' column contains empty values");
}
[Theory]
[InlineData("--search c")]
[InlineData("search c")]
public void CannotExecuteSearchWithShortCriteria(string testCase)
{
new DotnetNewCommand(_log, testCase.Split(" "))
.WithCustomHive(_sharedHome.HomeDirectory)
.Execute()
.Should().Fail()
.And.HaveStdErrContaining("Search failed: template name is too short, minimum 2 characters are required.");
}
[Theory]
[InlineData("--search fofofo", "'fofofo'")]
[InlineData("search fofofo", "'fofofo'")]
[InlineData("search fofofo --type item", "'fofofo', --type='item'")]
[InlineData("search fofofo --language Z#", "'fofofo', --language='Z#'")]
[InlineData("search -lang Z#", "-lang='Z#'")]
public void CanDisplayNoResults(string testCase, string criteria)
{
new DotnetNewCommand(_log, testCase.Split(" "))
.WithCustomHive(_sharedHome.HomeDirectory)
.Execute()
.Should().Fail()
.And.HaveStdErrContaining($"No templates found matching: {criteria}.");
}
[Theory]
[InlineData("azure --search --columns author")]
[InlineData("--search azure --columns author")]
[InlineData("search azure --columns author")]
public void ExamplePrefersMicrosoftPackage(string testCase)
{
CommandResult commandResult = new DotnetNewCommand(_log, testCase.Split(" "))
.WithCustomHive(_sharedHome.HomeDirectory)
.Execute();
commandResult.Should()
.ExitWith(0)
.And.NotHaveStdErr()
.And.HaveStdOutContaining("Searching for the templates...")
.And.HaveStdOutContaining("Matches from template source: NuGet.org")
.And.HaveStdOutMatching("Template Name\\s+Short Name\\s+Author\\s+Package Name \\/ Owners\\s+Trusted\\s+Downloads")
.And.HaveStdOutContaining("To use the template, run the following command to install the package:")
.And.HaveStdOutContaining(" dotnet new install [<package>...]");
List<List<string>> tableOutput = ParseTableOutput(commandResult.StdOut, expectedColumns: new[] { "Template Name", "Short Name", "Author", "Package Name / Owners", "Trusted", "Downloads" });
Assert.True(AllRowsContain(tableOutput, new[] { "Template Name", "Short Name" }, "azure"), "'Template Name' or 'Short Name' columns do not contain the criteria");
IEnumerable<List<string>> microsoftPackages = tableOutput.Where(row => row[2] == "Microsoft" && row[3].StartsWith("Microsoft", StringComparison.OrdinalIgnoreCase));
IEnumerable<string> installationCommands = microsoftPackages.Select(package => $"new install {package[3].Split(" /")[0]}").ToList();
bool ContainsOneOfInstallationCommands(string? output) => installationCommands.Any(command => output is not null && output.Contains(command));
commandResult.Should().HaveStdOutContaining(ContainsOneOfInstallationCommands, "Checks if the output contains one of the expected installation commands");
}
[Theory]
[InlineData("console --search --columns-all")]
[InlineData("--columns-all --search console")]
[InlineData("search console --columns-all")]
public void CanShowAllColumns(string testCase)
{
CommandResult commandResult = new DotnetNewCommand(_log, testCase.Split(" "))
.WithCustomHive(_sharedHome.HomeDirectory)
.Execute();
commandResult.Should()
.ExitWith(0)
.And.NotHaveStdErr()
.And.HaveStdOutContaining("Searching for the templates...")
.And.HaveStdOutContaining("Matches from template source: NuGet.org")
.And.HaveStdOutContaining("To use the template, run the following command to install the package:")
.And.HaveStdOutContaining(" dotnet new install [<package>...]");
List<List<string>> tableOutput = ParseTableOutput(commandResult.StdOut, expectedColumns: new[] { "Template Name", "Short Name", "Author", "Language", "Type", "Tags", "Package Name / Owners", "Trusted", "Downloads" });
Assert.True(AllRowsContain(tableOutput, new[] { "Template Name", "Short Name" }, "console"), "'Template Name' or 'Short Name' columns do not contain the criteria");
Assert.True(AtLeastOneRowIsNotEmpty(tableOutput, "Template Name"), "'Template Name' column contains empty values");
Assert.True(AtLeastOneRowIsNotEmpty(tableOutput, "Short Name"), "'Short Name' column contains empty values");
Assert.True(AllRowsAreNotEmpty(tableOutput, "Package Name / Owners"), "'Package Name / Owners' column contains empty values");
Assert.True(AtLeastOneRowIsNotEmpty(tableOutput, "Downloads"), "'Downloads' column contains empty values");
}
[Theory]
[InlineData("console --search --columns tags --tag Common")]
[InlineData("--search console --columns tags --tag Common")]
[InlineData("search console --columns tags --tag Common")]
public void CanFilterTags(string testCase)
{
CommandResult commandResult = new DotnetNewCommand(_log, testCase.Split(" "))
.WithCustomHive(_sharedHome.HomeDirectory)
.Execute();
commandResult.Should()
.ExitWith(0)
.And.NotHaveStdErr()
.And.HaveStdOutContaining("Searching for the templates...")
.And.HaveStdOutContaining("Matches from template source: NuGet.org")
.And.HaveStdOutContaining("These templates matched your input: 'console', --tag='Common'")
.And.HaveStdOutMatching("Template Name\\s+Short Name\\s+Tags\\s+Package Name \\/ Owners\\s+Trusted\\s+Downloads")
.And.HaveStdOutContaining("To use the template, run the following command to install the package:")
.And.HaveStdOutContaining(" dotnet new install [<package>...]");
List<List<string>> tableOutput = ParseTableOutput(commandResult.StdOut, expectedColumns: new[] { "Template Name", "Short Name", "Tags", "Package Name / Owners", "Trusted", "Downloads" });
Assert.True(AllRowsContain(tableOutput, new[] { "Template Name", "Short Name" }, "console"), "'Template Name' or 'Short Name' columns do not contain the criteria");
Assert.True(AllRowsContain(tableOutput, new[] { "Tags" }, "Common"), "'Tags' column does not contain the criteria");
Assert.True(AtLeastOneRowIsNotEmpty(tableOutput, "Template Name"), "'Template Name' column contains empty values");
Assert.True(AtLeastOneRowIsNotEmpty(tableOutput, "Short Name"), "'Short Name' column contains empty values");
Assert.True(AllRowsAreNotEmpty(tableOutput, "Tags"), "'Tags' column contains empty values");
Assert.True(AllRowsAreNotEmpty(tableOutput, "Package Name / Owners"), "'Package Name / Owners' column contains empty values");
Assert.True(AtLeastOneRowIsNotEmpty(tableOutput, "Downloads"), "'Downloads' column contains empty values");
}
[Theory]
[InlineData("--search --columns tags --tag Common")]
[InlineData("--columns tags --search --tag Common")]
[InlineData("search --columns tags --tag Common")]
public void CanFilterTags_WithoutName(string testCase)
{
CommandResult commandResult = new DotnetNewCommand(_log, testCase.Split(" "))
.WithCustomHive(_sharedHome.HomeDirectory)
.Execute();
commandResult.Should()
.ExitWith(0)
.And.NotHaveStdErr()
.And.HaveStdOutContaining("Searching for the templates...")
.And.HaveStdOutContaining("Matches from template source: NuGet.org")
.And.HaveStdOutContaining("These templates matched your input: --tag='Common'")
.And.HaveStdOutMatching("Template Name\\s+Short Name\\s+Tags\\s+Package Name \\/ Owners\\s+Trusted\\s+Downloads")
.And.HaveStdOutContaining("To use the template, run the following command to install the package:")
.And.HaveStdOutContaining(" dotnet new install [<package>...]");
List<List<string>> tableOutput = ParseTableOutput(commandResult.StdOut, expectedColumns: new[] { "Template Name", "Short Name", "Tags", "Package Name / Owners", "Trusted", "Downloads" });
Assert.True(AllRowsContain(tableOutput, new[] { "Tags" }, "Common"), "'Tags' column does not contain the criteria");
Assert.True(AtLeastOneRowIsNotEmpty(tableOutput, "Template Name"), "'Template Name' column contains empty values");
Assert.True(AtLeastOneRowIsNotEmpty(tableOutput, "Short Name"), "'Short Name' column contains empty values");
Assert.True(AllRowsAreNotEmpty(tableOutput, "Tags"), "'Tags' column contains empty values");
Assert.True(AllRowsAreNotEmpty(tableOutput, "Package Name / Owners"), "'Package Name / Owners' column contains empty values");
Assert.True(AtLeastOneRowIsNotEmpty(tableOutput, "Downloads"), "'Downloads' column contains empty values");
}
[Theory]
[InlineData("func --search --columns author --author micro")]
[InlineData("--search func --columns author --author micro")]
[InlineData("search func --columns author --author micro")]
public void CanFilterAuthor(string testCase)
{
CommandResult commandResult = new DotnetNewCommand(_log, testCase.Split(" "))
.WithCustomHive(_sharedHome.HomeDirectory)
.WithDebug()
.Execute();
commandResult.Should()
.ExitWith(0)
.And.NotHaveStdErr()
.And.HaveStdOutContaining("Searching for the templates...")
.And.HaveStdOutContaining("Matches from template source: NuGet.org")
.And.HaveStdOutContaining("These templates matched your input: 'func', --author='micro'")
.And.HaveStdOutMatching("Template Name\\s+Short Name\\s+Author\\s+Package Name \\/ Owners\\s+Trusted\\s+Downloads")
.And.HaveStdOutContaining("To use the template, run the following command to install the package:")
.And.HaveStdOutContaining(" dotnet new install [<package>...]");
List<List<string>> tableOutput = ParseTableOutput(commandResult.StdOut, expectedColumns: new[] { "Template Name", "Short Name", "Author", "Package Name / Owners", "Trusted", "Downloads" });
Assert.True(AllRowsContain(tableOutput, new[] { "Template Name", "Short Name" }, "func"), "'Template Name' or 'Short Name' columns do not contain the criteria");
Assert.True(AllRowsContain(tableOutput, new[] { "Author" }, "micro"), "'Author' column does not contain the criteria");
Assert.True(AtLeastOneRowIsNotEmpty(tableOutput, "Template Name"), "'Template Name' column contains empty values");
Assert.True(AtLeastOneRowIsNotEmpty(tableOutput, "Short Name"), "'Short Name' column contains empty values");
Assert.True(AllRowsAreNotEmpty(tableOutput, "Author"), "'Author' column contains empty values");
Assert.True(AllRowsAreNotEmpty(tableOutput, "Package Name / Owners"), "'Package Name / Owners' column contains empty values");
Assert.True(AtLeastOneRowIsNotEmpty(tableOutput, "Downloads"), "'Downloads' column contains empty values");
}
[Theory]
[InlineData("--search --columns author --author micro")]
[InlineData("search --columns author --author micro")]
public void CanFilterAuthor_WithoutName(string testCase)
{
CommandResult commandResult = new DotnetNewCommand(_log, testCase.Split(" "))
.WithCustomHive(_sharedHome.HomeDirectory)
.WithDebug()
.Execute();
commandResult.Should()
.ExitWith(0)
.And.NotHaveStdErr()
.And.HaveStdOutContaining("Searching for the templates...")
.And.HaveStdOutContaining("These templates matched your input: --author='micro'")
.And.HaveStdOutContaining("Matches from template source: NuGet.org")
.And.HaveStdOutMatching("Template Name\\s+Short Name\\s+Author\\s+Package Name \\/ Owners\\s+Trusted\\s+Downloads")
.And.HaveStdOutContaining("To use the template, run the following command to install the package:")
.And.HaveStdOutContaining(" dotnet new install [<package>...]");
List<List<string>> tableOutput = ParseTableOutput(commandResult.StdOut, expectedColumns: new[] { "Template Name", "Short Name", "Author", "Package Name / Owners", "Trusted", "Downloads" });
Assert.True(AllRowsContain(tableOutput, new[] { "Author" }, "micro"), "'Author' column does not contain the criteria");
Assert.True(SomeRowsContain(tableOutput, new[] { "Author" }, "Microsoft"), "'Author' column does not contain any rows with 'Microsoft'");
Assert.True(AtLeastOneRowIsNotEmpty(tableOutput, "Template Name"), "'Template Name' column contains empty values");
Assert.True(AtLeastOneRowIsNotEmpty(tableOutput, "Short Name"), "'Short Name' column contains empty values");
Assert.True(AllRowsAreNotEmpty(tableOutput, "Author"), "'Author' column contains empty values");
Assert.True(AllRowsAreNotEmpty(tableOutput, "Package Name / Owners"), "'Package Name / Owners' column contains empty values");
Assert.True(AtLeastOneRowIsNotEmpty(tableOutput, "Trusted"), "'Trusted' column contains empty values");
Assert.True(AtLeastOneRowIsNotEmpty(tableOutput, "Downloads"), "'Downloads' column contains empty values");
}
[Theory]
[InlineData("console --search --columns language --language Q#")]
[InlineData("--search console --columns language --language Q#")]
[InlineData("search console --columns language --language Q#")]
public void CanFilterLanguage(string testCase)
{
CommandResult commandResult = new DotnetNewCommand(_log, testCase.Split(" "))
.WithCustomHive(_sharedHome.HomeDirectory)
.Execute();
commandResult.Should()
.ExitWith(0)
.And.NotHaveStdErr()
.And.HaveStdOutContaining("Searching for the templates...")
.And.HaveStdOutContaining("These templates matched your input: 'console', --language='Q#'")
.And.HaveStdOutContaining("Matches from template source: NuGet.org")
.And.HaveStdOutMatching("Template Name\\s+Short Name\\s+Language\\s+Package Name \\/ Owners\\s+Trusted\\s+Downloads")
.And.HaveStdOutContaining("To use the template, run the following command to install the package:")
.And.HaveStdOutContaining(" dotnet new install [<package>...]");
List<List<string>> tableOutput = ParseTableOutput(commandResult.StdOut, expectedColumns: new[] { "Template Name", "Short Name", "Language", "Package Name / Owners", "Trusted", "Downloads" });
Assert.True(AllRowsContain(tableOutput, new[] { "Template Name", "Short Name" }, "console"), "'Template Name' or 'Short Name' columns do not contain the criteria");
Assert.True(AllRowsContain(tableOutput, new[] { "Language" }, "Q#"), "'Language' column does not contain criteria");
Assert.True(AtLeastOneRowIsNotEmpty(tableOutput, "Template Name"), "'Template Name' column contains empty values");
Assert.True(AtLeastOneRowIsNotEmpty(tableOutput, "Short Name"), "'Short Name' column contains empty values");
Assert.True(AllRowsAreNotEmpty(tableOutput, "Language"), "'Language' column contains empty values");
Assert.True(AllRowsAreNotEmpty(tableOutput, "Package Name / Owners"), "'Package Name / Owners' column contains empty values");
Assert.True(AtLeastOneRowIsNotEmpty(tableOutput, "Downloads"), "'Downloads' column contains empty values");
}
[Theory]
[InlineData("--search --columns language --language Q#", "--language")]
[InlineData("search --columns language --language Q#", "--language")]
[InlineData("--search --columns language -lang Q#", "-lang")]
[InlineData("search --columns language -lang Q#", "-lang")]
public void CanFilterLanguage_WithoutName(string testCase, string optionName)
{
CommandResult commandResult = new DotnetNewCommand(_log, testCase.Split(" "))
.WithCustomHive(_sharedHome.HomeDirectory)
.Execute();
commandResult.Should()
.ExitWith(0)
.And.NotHaveStdErr()
.And.HaveStdOutContaining("Searching for the templates...")
.And.HaveStdOutContaining($"These templates matched your input: {optionName}='Q#'")
.And.HaveStdOutContaining("Matches from template source: NuGet.org")
.And.HaveStdOutMatching("Template Name\\s+Short Name\\s+Language\\s+Package Name \\/ Owners\\s+Trusted\\s+Downloads")
.And.HaveStdOutContaining("To use the template, run the following command to install the package:")
.And.HaveStdOutContaining(" dotnet new install [<package>...]");
List<List<string>> tableOutput = ParseTableOutput(commandResult.StdOut, expectedColumns: new[] { "Template Name", "Short Name", "Language", "Package Name / Owners", "Trusted", "Downloads" });
Assert.True(AllRowsContain(tableOutput, new[] { "Language" }, "Q#"), "'Language' column does not contain criteria");
Assert.True(AtLeastOneRowIsNotEmpty(tableOutput, "Template Name"), "'Template Name' column contains empty values");
Assert.True(AtLeastOneRowIsNotEmpty(tableOutput, "Short Name"), "'Short Name' column contains empty values");
Assert.True(AllRowsAreNotEmpty(tableOutput, "Language"), "'Language' column contains empty values");
Assert.True(AllRowsAreNotEmpty(tableOutput, "Package Name / Owners"), "'Package Name / Owners' column contains empty values");
Assert.True(AtLeastOneRowIsNotEmpty(tableOutput, "Downloads"), "'Downloads' column contains empty values");
}
[Theory]
[InlineData("console --search --columns type --type item")]
[InlineData("--search console --columns type --type item")]
[InlineData("search console --columns type --type item")]
public void CanFilterType(string testCase)
{
CommandResult commandResult = new DotnetNewCommand(_log, testCase.Split(" "))
.WithCustomHive(_sharedHome.HomeDirectory).WithDebug()
.Execute();
commandResult.Should()
.ExitWith(0)
.And.NotHaveStdErr()
.And.HaveStdOutContaining("Searching for the templates...")
.And.HaveStdOutContaining("These templates matched your input: 'console', --type='item'")
.And.HaveStdOutContaining("Matches from template source: NuGet.org")
.And.HaveStdOutMatching("Template Name\\s+Short Name\\s+Type\\s+Package Name \\/ Owners\\s+Trusted\\s+Downloads")
.And.HaveStdOutContaining("To use the template, run the following command to install the package:")
.And.HaveStdOutContaining(" dotnet new install [<package>...]");
List<List<string>> tableOutput = ParseTableOutput(commandResult.StdOut, expectedColumns: new[] { "Template Name", "Short Name", "Type", "Package Name / Owners", "Trusted", "Downloads" });
Assert.True(AllRowsContain(tableOutput, new[] { "Template Name", "Short Name" }, "console"), "'Template Name' or 'Short Name' columns do not contain the criteria");
Assert.True(AllRowsEqual(tableOutput, new[] { "Type" }, "item"), "'Type' column does not contain criteria");
Assert.True(AtLeastOneRowIsNotEmpty(tableOutput, "Template Name"), "'Template Name' column contains empty values");
Assert.True(AtLeastOneRowIsNotEmpty(tableOutput, "Short Name"), "'Short Name' column contains empty values");
Assert.True(AllRowsAreNotEmpty(tableOutput, "Type"), "'Type' column contains empty values");
Assert.True(AllRowsAreNotEmpty(tableOutput, "Package Name / Owners"), "'Package Name / Owners' column contains empty values");
Assert.True(AtLeastOneRowIsNotEmpty(tableOutput, "Downloads"), "'Downloads' column contains empty values");
}
[Theory]
[InlineData("--search --columns type --type item")]
[InlineData("search --columns type --type item")]
public void CanFilterType_WithoutName(string testCase)
{
CommandResult commandResult = new DotnetNewCommand(_log, testCase.Split(" "))
.WithCustomHive(_sharedHome.HomeDirectory).WithDebug()
.Execute();
commandResult.Should()
.ExitWith(0)
.And.NotHaveStdErr()
.And.HaveStdOutContaining("Searching for the templates...")
.And.HaveStdOutContaining("These templates matched your input: --type='item'")
.And.HaveStdOutContaining("Matches from template source: NuGet.org")
.And.HaveStdOutMatching("Template Name\\s+Short Name\\s+Type\\s+Package Name \\/ Owners\\s+Trusted\\s+Downloads")
.And.HaveStdOutContaining("To use the template, run the following command to install the package:")
.And.HaveStdOutContaining(" dotnet new install [<package>...]");
List<List<string>> tableOutput = ParseTableOutput(commandResult.StdOut, expectedColumns: new[] { "Template Name", "Short Name", "Type", "Package Name / Owners", "Trusted", "Downloads" });
Assert.True(AllRowsEqual(tableOutput, new[] { "Type" }, "item"), "'Type' column does not contain criteria");
Assert.True(AtLeastOneRowIsNotEmpty(tableOutput, "Template Name"), "'Template Name' column contains empty values");
Assert.True(AtLeastOneRowIsNotEmpty(tableOutput, "Short Name"), "'Short Name' column contains empty values");
Assert.True(AllRowsAreNotEmpty(tableOutput, "Type"), "'Type' column contains empty values");
Assert.True(AllRowsAreNotEmpty(tableOutput, "Package Name / Owners"), "'Package Name / Owners' column contains empty values");
Assert.True(AtLeastOneRowIsNotEmpty(tableOutput, "Trusted"), "'Trusted' column contains empty values");
Assert.True(AtLeastOneRowIsNotEmpty(tableOutput, "Downloads"), "'Downloads' column contains empty values");
}
[Theory]
[InlineData("console --search --package core")]
[InlineData("--search console --package core")]
[InlineData("search console --package core")]
public void CanFilterPackage(string testCase)
{
CommandResult commandResult = new DotnetNewCommand(_log, testCase.Split(" "))
.WithCustomHive(_sharedHome.HomeDirectory)
.Execute();
commandResult.Should()
.ExitWith(0)
.And.NotHaveStdErr()
.And.HaveStdOutContaining("Searching for the templates...")
.And.HaveStdOutContaining("These templates matched your input: 'console', --package='core'")
.And.HaveStdOutContaining("Matches from template source: NuGet.org")
.And.HaveStdOutMatching("Template Name\\s+Short Name\\s+Language\\s+Package Name \\/ Owners\\s+Trusted\\s+Downloads")
.And.HaveStdOutContaining("To use the template, run the following command to install the package:")
.And.HaveStdOutContaining(" dotnet new install [<package>...]");
List<List<string>> tableOutput = ParseTableOutput(commandResult.StdOut, expectedColumns: new[] { "Template Name", "Short Name", "Language", "Package Name / Owners", "Trusted", "Downloads" });
Assert.True(AllRowsContain(tableOutput, new[] { "Template Name", "Short Name" }, "console"), "'Template Name' or 'Short Name' columns do not contain the criteria");
Assert.True(AllRowsContain(tableOutput, new[] { "Package Name / Owners" }, "core"), "'Package Name / Owners' column does not contain criteria");
Assert.True(AtLeastOneRowIsNotEmpty(tableOutput, "Template Name"), "'Template Name' column contains empty values");
Assert.True(AtLeastOneRowIsNotEmpty(tableOutput, "Short Name"), "'Short Name' column contains empty values");
Assert.True(AtLeastOneRowIsNotEmpty(tableOutput, "Trusted"), "'Trusted' column contains empty values");
Assert.True(AllRowsAreNotEmpty(tableOutput, "Package Name / Owners"), "'Package Name / Owners' column contains empty values");
Assert.True(AtLeastOneRowIsNotEmpty(tableOutput, "Downloads"), "'Downloads' column contains empty values");
}
[Theory]
[InlineData("--search --package core")]
[InlineData("search --package core")]
public void CanFilterPackage_WithoutName(string testCase)
{
CommandResult commandResult = new DotnetNewCommand(_log, testCase.Split(" "))
.WithCustomHive(_sharedHome.HomeDirectory)
.Execute();
commandResult.Should()
.ExitWith(0)
.And.NotHaveStdErr()
.And.HaveStdOutContaining("Searching for the templates...")
.And.HaveStdOutContaining("These templates matched your input: --package='core'")
.And.HaveStdOutContaining("Matches from template source: NuGet.org")
.And.HaveStdOutMatching("Template Name\\s+Short Name\\s+Language\\s+Package Name \\/ Owners\\s+Trusted\\s+Downloads")
.And.HaveStdOutContaining("To use the template, run the following command to install the package:")
.And.HaveStdOutContaining(" dotnet new install [<package>...]");
List<List<string>> tableOutput = ParseTableOutput(commandResult.StdOut, expectedColumns: new[] { "Template Name", "Short Name", "Language", "Package Name / Owners", "Trusted", "Downloads" });
Assert.True(AllRowsContain(tableOutput, new[] { "Package Name / Owners" }, "core"), "'Package Name / Owners' column does not contain criteria");
Assert.True(AllRowsAreNotEmpty(tableOutput, "Package Name / Owners"), "'Package Name \\/ Owners' column contains empty values");
Assert.True(AtLeastOneRowIsNotEmpty(tableOutput, "Template Name"), "'Template Name' column contains empty values");
Assert.True(AtLeastOneRowIsNotEmpty(tableOutput, "Short Name"), "'Short Name' column contains empty values");
Assert.True(AtLeastOneRowIsNotEmpty(tableOutput, "Trusted"), "'Trusted' column contains empty values");
Assert.True(AtLeastOneRowIsNotEmpty(tableOutput, "Downloads"), "'Downloads' column contains empty values");
}
#pragma warning disable xUnit1004
[Theory(Skip = "https://github.com/dotnet/sdk/issues/39772")]
#pragma warning restore xUnit1004
[InlineData("console --search")]
[InlineData("--search console")]
[InlineData("search console")]
public void CanSortByDownloadCountAndThenByName(string testCase)
{
CommandResult commandResult = new DotnetNewCommand(_log, testCase.Split(" "))
.WithCustomHive(_sharedHome.HomeDirectory)
.WithEnvironmentVariable("DOTNET_CLI_UI_LANGUAGE", "en-US")
.Execute();
commandResult.Should()
.ExitWith(0)
.And.NotHaveStdErr()
.And.HaveStdOutContaining("Searching for the templates...")
.And.HaveStdOutContaining("Matches from template source: NuGet.org")
.And.HaveStdOutMatching("Template Name\\s+Short Name\\s+Language\\s+Package Name \\/ Owners\\s+Trusted\\s+Downloads");
List<List<string>> tableOutput = ParseTableOutput(commandResult.StdOut, expectedColumns: new[] { "Template Name", "Short Name", "Language", "Package Name / Owners", "Trusted", "Downloads" });
Assert.True(tableOutput.Count > 2, "At least 2 search hits are expected");
// rows can be shrunk: ML.NET Console App for Training and ML.NET Console App for Train...
// in this case ML.NET Console App for Training < ML.NET Console App for Train...
// therefore use custom comparer
var nameComparer = new ShrinkAwareCurrentCultureStringComparer();
var downloadCountComparer = new DownloadCountComparer();
var orderedRows = tableOutput
.Skip(1)
.Select(x => new { name = x[0], count = x[5] })
.OrderByDescending(x => x.count, downloadCountComparer)
.ThenBy(x => x.name, nameComparer);
for (int i = 1; i < tableOutput.Count; i++)
{
Assert.Equal(orderedRows.ElementAt(i - 1).name, tableOutput[i][0]);
Assert.Equal(orderedRows.ElementAt(i - 1).count, tableOutput[i][5]);
}
}
#pragma warning disable xUnit1004 // Test methods should not be skipped
[Fact(Skip = "https://github.com/dotnet/sdk/issues/42541")]
#pragma warning restore xUnit1004 // Test methods should not be skipped
public void CanFilterByChoiceParameter()
{
CommandResult commandResult = new DotnetNewCommand(_log, "con", "--search", "--framework")
.WithCustomHive(_sharedHome.HomeDirectory)
.Execute();
commandResult.Should()
.ExitWith(0)
.And.HaveStdOutContaining("Searching for the templates...")
.And.HaveStdOutContaining("Matches from template source: NuGet.org")
.And.HaveStdOutContaining("These templates matched your input: 'con', --framework")
.And.HaveStdOutMatching("Template Name\\s+Short Name\\s+Language\\s+Package Name \\/ Owners\\s+Trusted\\s+Downloads")
.And.HaveStdOutContaining("To use the template, run the following command to install the package:")
.And.HaveStdOutContaining(" dotnet new install [<package>...]");
List<List<string>> tableOutput = ParseTableOutput(commandResult.StdOut, expectedColumns: new[] { "Template Name", "Short Name", "Language", "Package Name / Owners", "Trusted", "Downloads" });
Assert.True(AllRowsContain(tableOutput, new[] { "Template Name", "Short Name" }, "con"), "'Template Name' or 'Short Name' columns do not contain the criteria");
Assert.True(AtLeastOneRowIsNotEmpty(tableOutput, "Template Name"), "'Template Name' column contains empty values");
Assert.True(AtLeastOneRowIsNotEmpty(tableOutput, "Short Name"), "'Short Name' column contains empty values");
Assert.True(AllRowsAreNotEmpty(tableOutput, "Package Name / Owners"), "'Package Name / Owners' column contains empty values");
Assert.True(AtLeastOneRowIsNotEmpty(tableOutput, "Trusted"), "'Trusted' column contains empty values");
Assert.True(AtLeastOneRowIsNotEmpty(tableOutput, "Downloads"), "'Downloads' column contains empty values");
commandResult = new DotnetNewCommand(_log, "con", "--search", "-f")
.WithCustomHive(_sharedHome.HomeDirectory)
.Execute();
commandResult.Should()
.ExitWith(0)
.And.HaveStdOutContaining("Searching for the templates...")
.And.HaveStdOutContaining("Matches from template source: NuGet.org")
.And.HaveStdOutContaining("These templates matched your input: 'con', -f")
.And.HaveStdOutMatching("Template Name\\s+Short Name\\s+Language\\s+Package Name \\/ Owners\\s+Trusted\\s+Downloads")
.And.HaveStdOutContaining("To use the template, run the following command to install the package:")
.And.HaveStdOutContaining(" dotnet new install [<package>...]");
tableOutput = ParseTableOutput(commandResult.StdOut, expectedColumns: new[] { "Template Name", "Short Name", "Language", "Package Name / Owners", "Trusted", "Downloads" });
Assert.True(AllRowsContain(tableOutput, new[] { "Template Name", "Short Name" }, "con"), "'Template Name' or 'Short Name' columns do not contain the criteria");
Assert.True(AtLeastOneRowIsNotEmpty(tableOutput, "Template Name"), "'Template Name' column contains empty values");
Assert.True(AtLeastOneRowIsNotEmpty(tableOutput, "Short Name"), "'Short Name' column contains empty values");
Assert.True(AllRowsAreNotEmpty(tableOutput, "Package Name / Owners"), "'Package Name / Owners' column contains empty values");
Assert.True(AtLeastOneRowIsNotEmpty(tableOutput, "Downloads"), "'Downloads' column contains empty values");
commandResult = new DotnetNewCommand(_log, "--search", "-f")
.WithCustomHive(_sharedHome.HomeDirectory)
.Execute();
commandResult.Should()
.ExitWith(0)
.And.HaveStdOutContaining("Searching for the templates...")
.And.HaveStdOutContaining("Matches from template source: NuGet.org")
.And.HaveStdOutContaining("These templates matched your input: -f")
.And.HaveStdOutMatching("Template Name\\s+Short Name\\s+Language\\s+Package Name \\/ Owners\\s+Trusted\\s+Downloads")
.And.HaveStdOutContaining("To use the template, run the following command to install the package:")
.And.HaveStdOutContaining(" dotnet new install [<package>...]");
tableOutput = ParseTableOutput(commandResult.StdOut, expectedColumns: new[] { "Template Name", "Short Name", "Language", "Package Name / Owners", "Trusted", "Downloads" });
Assert.True(AtLeastOneRowIsNotEmpty(tableOutput, "Template Name"), "'Template Name' column contains empty values");
Assert.True(AtLeastOneRowIsNotEmpty(tableOutput, "Short Name"), "'Short Name' column contains empty values");
Assert.True(AllRowsAreNotEmpty(tableOutput, "Package Name / Owners"), "'Package Name / Owners' column contains empty values");
Assert.True(AtLeastOneRowIsNotEmpty(tableOutput, "Downloads"), "'Downloads' column contains empty values");
}
#pragma warning disable xUnit1004 // Test methods should not be skipped
[Fact(Skip = "https://github.com/dotnet/sdk/issues/42541")]
#pragma warning restore xUnit1004 // Test methods should not be skipped
public void CanFilterByNonChoiceParameter()
{
CommandResult commandResult = new DotnetNewCommand(_log, "con", "--search", "--langVersion")
.WithCustomHive(_sharedHome.HomeDirectory)
.WithDebug()
.Execute();
commandResult.Should()
.ExitWith(0)
.And.HaveStdOutContaining("Searching for the templates...")
.And.HaveStdOutContaining("Matches from template source: NuGet.org")
.And.HaveStdOutContaining("These templates matched your input: 'con', --langVersion")
.And.HaveStdOutMatching("Template Name\\s+Short Name\\s+Author\\s+Language\\s+Package Name \\/ Owners\\s+Trusted\\s+Downloads")
.And.HaveStdOutContaining("To use the template, run the following command to install the package:")
.And.HaveStdOutContaining(" dotnet new install [<package>...]");
List<List<string>> tableOutput = ParseTableOutput(commandResult.StdOut, expectedColumns: new[] { "Template Name", "Short Name", "Language", "Package Name / Owners", "Trusted", "Downloads" });
Assert.True(AllRowsContain(tableOutput, new[] { "Template Name", "Short Name" }, "con"), "'Template Name' or 'Short Name' columns do not contain the criteria");
Assert.True(AtLeastOneRowIsNotEmpty(tableOutput, "Template Name"), "'Template Name' column contains empty values");
Assert.True(AtLeastOneRowIsNotEmpty(tableOutput, "Short Name"), "'Short Name' column contains empty values");
Assert.True(AllRowsAreNotEmpty(tableOutput, "Package Name / Owners"), "'Package Name / Owners' column contains empty values");
Assert.True(AtLeastOneRowIsNotEmpty(tableOutput, "Downloads"), "'Downloads' column contains empty values");
commandResult = new DotnetNewCommand(_log, "--search", "--langVersion")
.WithCustomHive(_sharedHome.HomeDirectory)
.WithDebug()
.Execute();
commandResult.Should()
.ExitWith(0)
.And.HaveStdOutContaining("Searching for the templates...")
.And.HaveStdOutContaining("Matches from template source: NuGet.org")
.And.HaveStdOutContaining("These templates matched your input: --langVersion")
.And.HaveStdOutMatching("Template Name\\s+Short Name\\s+Author\\s+Language\\s+Package Name \\/ Owners\\s+Trusted\\s+Downloads")
.And.HaveStdOutContaining("To use the template, run the following command to install the package:")
.And.HaveStdOutContaining(" dotnet new install [<package>...]");
tableOutput = ParseTableOutput(commandResult.StdOut, expectedColumns: new[] { "Template Name", "Short Name", "Language", "Package Name / Owners", "Trusted", "Downloads" });
Assert.True(AtLeastOneRowIsNotEmpty(tableOutput, "Template Name"), "'Template Name' column contains empty values");
Assert.True(AtLeastOneRowIsNotEmpty(tableOutput, "Short Name"), "'Short Name' column contains empty values");
Assert.True(AllRowsAreNotEmpty(tableOutput, "Package Name / Owners"), "'Package Name / Owners' column contains empty values");
Assert.True(AtLeastOneRowIsNotEmpty(tableOutput, "Downloads"), "'Downloads' column contains empty values");
}
#pragma warning disable xUnit1004 // Test methods should not be skipped
[Fact(Skip = "https://github.com/dotnet/sdk/issues/42541")]
#pragma warning restore xUnit1004 // Test methods should not be skipped
public void IgnoresValueForNonChoiceParameter()
{
CommandResult commandResult = new DotnetNewCommand(_log, "con", "--search", "--langVersion", "smth")
.WithCustomHive(_sharedHome.HomeDirectory)
.WithDebug()
.Execute();
commandResult.Should()
.ExitWith(0)
.And.HaveStdOutContaining("Searching for the templates...")
.And.HaveStdOutContaining("Matches from template source: NuGet.org")
.And.HaveStdOutContaining("These templates matched your input: 'con', --langVersion")
.And.HaveStdOutMatching("Template Name\\s+Short Name\\s+Language\\s+Package Name \\/ Owners\\s+Trusted\\s+Downloads")
.And.HaveStdOutContaining("To use the template, run the following command to install the package:")
.And.HaveStdOutContaining(" dotnet new install [<package>...]");
List<List<string>> tableOutput = ParseTableOutput(commandResult.StdOut, expectedColumns: new[] { "Template Name", "Short Name", "Language", "Package Name / Owners", "Trusted", "Downloads" });
Assert.True(AllRowsContain(tableOutput, new[] { "Template Name", "Short Name" }, "con"), "'Template Name' or 'Short Name' columns do not contain the criteria");
Assert.True(AtLeastOneRowIsNotEmpty(tableOutput, "Template Name"), "'Template Name' column contains empty values");
Assert.True(AtLeastOneRowIsNotEmpty(tableOutput, "Short Name"), "'Short Name' column contains empty values");
Assert.True(AllRowsAreNotEmpty(tableOutput, "Package Name / Owners"), "'Package Name / Owners' column contains empty values");
Assert.True(AtLeastOneRowIsNotEmpty(tableOutput, "Downloads"), "'Downloads' column contains empty values");
commandResult = new DotnetNewCommand(_log, "--search", "--langVersion", "smth")
.WithCustomHive(_sharedHome.HomeDirectory)
.WithDebug()
.Execute();
commandResult.Should()
.ExitWith(0)
.And.HaveStdOutContaining("Searching for the templates...")
.And.HaveStdOutContaining("Matches from template source: NuGet.org")
.And.HaveStdOutContaining("These templates matched your input: --langVersion")
.And.HaveStdOutMatching("Template Name\\s+Short Name\\s+Language\\s+Package Name \\/ Owners\\s+Trusted\\s+Downloads")
.And.HaveStdOutContaining("To use the template, run the following command to install the package:")
.And.HaveStdOutContaining(" dotnet new install [<package>...]");
tableOutput = ParseTableOutput(commandResult.StdOut, expectedColumns: new[] { "Template Name", "Short Name", "Language", "Package Name / Owners", "Trusted", "Downloads" });
Assert.True(AtLeastOneRowIsNotEmpty(tableOutput, "Template Name"), "'Template Name' column contains empty values");
Assert.True(AtLeastOneRowIsNotEmpty(tableOutput, "Short Name"), "'Short Name' column contains empty values");
Assert.True(AllRowsAreNotEmpty(tableOutput, "Package Name / Owners"), "'Package Name / Owners' column contains empty values");
Assert.True(AtLeastOneRowIsNotEmpty(tableOutput, "Downloads"), "'Downloads' column contains empty values");
}
#pragma warning disable xUnit1004 // Test methods should not be skipped
[Fact(Skip = "https://github.com/dotnet/sdk/issues/42541")]
#pragma warning restore xUnit1004 // Test methods should not be skipped
public void CanFilterByChoiceParameterWithValue()
{
CommandResult commandResult = new DotnetNewCommand(_log, "con", "--search", "-f", "netcoreapp3.1")
.WithCustomHive(_sharedHome.HomeDirectory)
.WithDebug()
.Execute();
commandResult.Should()
.ExitWith(0)
.And.HaveStdOutContaining("Searching for the templates...")
.And.HaveStdOutContaining("Matches from template source: NuGet.org")
.And.HaveStdOutContaining("These templates matched your input: 'con', -f='netcoreapp3.1'")
.And.HaveStdOutMatching("Template Name\\s+Short Name\\s+Language\\s+Package Name \\/ Owners\\s+Trusted\\s+Downloads")
.And.HaveStdOutContaining("To use the template, run the following command to install the package:")
.And.HaveStdOutContaining(" dotnet new install [<package>...]");
List<List<string>> tableOutput = ParseTableOutput(commandResult.StdOut, expectedColumns: new[] { "Template Name", "Short Name", "Language", "Package Name / Owners", "Trusted", "Downloads" });
Assert.True(AllRowsContain(tableOutput, new[] { "Template Name", "Short Name" }, "con"), "'Template Name' or 'Short Name' columns do not contain the criteria");
Assert.True(AtLeastOneRowIsNotEmpty(tableOutput, "Template Name"), "'Template Name' column contains empty values");
Assert.True(AtLeastOneRowIsNotEmpty(tableOutput, "Short Name"), "'Short Name' column contains empty values");
Assert.True(AllRowsAreNotEmpty(tableOutput, "Package Name / Owners"), "'Package Name / Owners' column contains empty values");
Assert.True(AtLeastOneRowIsNotEmpty(tableOutput, "Downloads"), "'Downloads' column contains empty values");
commandResult = new DotnetNewCommand(_log, "--search", "-f", "net5.0")
.WithCustomHive(_sharedHome.HomeDirectory)
.WithDebug()
.Execute();
commandResult.Should()
.ExitWith(0)
.And.HaveStdOutContaining("Searching for the templates...")
.And.HaveStdOutContaining("Matches from template source: NuGet.org")
.And.HaveStdOutContaining("These templates matched your input: -f='net5.0'")
.And.HaveStdOutMatching("Template Name\\s+Short Name\\s+Language\\s+Package Name \\/ Owners\\s+Trusted\\s+Downloads")
.And.HaveStdOutContaining("To use the template, run the following command to install the package:")
.And.HaveStdOutContaining(" dotnet new install [<package>...]");
tableOutput = ParseTableOutput(commandResult.StdOut, expectedColumns: new[] { "Template Name", "Short Name", "Language", "Package Name / Owners", "Trusted", "Downloads" });
Assert.True(AtLeastOneRowIsNotEmpty(tableOutput, "Template Name"), "'Template Name' column contains empty values");
Assert.True(AtLeastOneRowIsNotEmpty(tableOutput, "Short Name"), "'Short Name' column contains empty values");
Assert.True(AllRowsAreNotEmpty(tableOutput, "Package Name / Owners"), "'Package Name / Owners' column contains empty values");
Assert.True(AtLeastOneRowIsNotEmpty(tableOutput, "Downloads"), "'Downloads' column contains empty values");
}
#pragma warning disable xUnit1004 // Test methods should not be skipped
[Fact(Skip = "https://github.com/dotnet/sdk/issues/42541")]
#pragma warning restore xUnit1004 // Test methods should not be skipped
public void CannotSearchTemplatesWithUnknownParameter()
{
new DotnetNewCommand(_log, "--search", "--unknown")
.WithCustomHive(_sharedHome.HomeDirectory)
.Execute()
.Should().Fail()
.And.HaveStdErrContaining("No templates found matching: --unknown.");
new DotnetNewCommand(_log, "con", "--search", "--unknown")
.WithCustomHive(_sharedHome.HomeDirectory)
.Execute()
.Should().Fail()
.And.HaveStdErrContaining("No templates found matching: 'con', --unknown.");
new DotnetNewCommand(_log, "con", "--search", "--unknown", "--language", "C#")
.WithCustomHive(_sharedHome.HomeDirectory)
.Execute()
.Should().Fail()
.And.HaveStdErrContaining("No templates found matching: 'con', language='C#', --unknown.");
}
[Theory]
[InlineData("zoop --search", "--search zoop")]
[InlineData("zoop --search --language F#", "--search zoop --language F#")]
[InlineData("zoop --search --columns-all", "--search zoop --columns-all")]
public void CanFallbackToSearchOption(string command1, string command2)
{
CommandResult commandResult1 = new DotnetNewCommand(_log, command1.Split())
.WithCustomHive(_sharedHome.HomeDirectory)
.Execute();
CommandResult commandResult2 = new DotnetNewCommand(_log, command2.Split())
.WithCustomHive(_sharedHome.HomeDirectory)
.Execute();
Assert.Equal(commandResult1.StdOut, commandResult2.StdOut);
}
[Theory]
[InlineData("--search foo --columns-all bar", "bar", "foo")]
[InlineData("--search foo bar", "bar", "foo")]
[InlineData("foo --search --columns-all --framework net6.0 bar", "bar|net6.0|foo", "--framework")]
[InlineData("foo --search --columns-all -other-param --framework net6.0 bar", "bar|net6.0|--framework|foo", "-other-param")]
[InlineData("search foo --columns-all bar", "bar", "foo")]
[InlineData("foo --search bar", "foo", "bar")]
[InlineData("foo --search bar --language F#", "foo", "bar")]
[InlineData("foo --search --columns-all bar", "foo", "bar")]
[InlineData("foo search bar", "foo", "bar")]
public void CannotSearchOnParseError(string command, string invalidArguments, string validArguments)
{
CommandResult commandResult = new DotnetNewCommand(_log, command.Split())
.WithCustomHive(_sharedHome.HomeDirectory)
.Execute();
commandResult.Should().Fail();
foreach (string arg in invalidArguments.Split('|'))
{
commandResult.Should().HaveStdErrMatching($"Unrecognized command or (argument\\(s\\)\\:|argument) '{arg}'");
}
foreach (string arg in validArguments.Split('|'))
{
commandResult.Should()
.NotHaveStdErrContaining($"Unrecognized command or argument '{arg}'")
.And.NotHaveStdErrContaining($"Unrecognized command or argument(s): '{arg}'");
}
}
[Fact]
public void CanShowDeprecationMessage_WhenLegacyCommandIsUsed()
{
const string deprecationMessage =
@"Warning: use of 'dotnet new --search' is deprecated. Use 'dotnet new search' instead.
For more information, run:
dotnet new search -h";
CommandResult commandResult = new DotnetNewCommand(_log, "--search", "console")
.WithCustomHive(_sharedHome.HomeDirectory)
.Execute();
commandResult.Should()
.ExitWith(0)
.And.NotHaveStdErr();
Assert.StartsWith(deprecationMessage, commandResult.StdOut);
}
[Fact]
public void DoNotShowDeprecationMessage_WhenNewCommandIsUsed()
{
CommandResult commandResult = new DotnetNewCommand(_log, "search", "console")
.WithCustomHive(_sharedHome.HomeDirectory)
.Execute();
commandResult.Should()
.ExitWith(0)
.And.NotHaveStdErr()
.And.NotHaveStdOutContaining("Warning")
.And.NotHaveStdOutContaining("deprecated");
}
private static bool AllRowsContain(List<List<string>> tableOutput, string[] columnsNames, string value)
{
IEnumerable<int> columnIndexes = columnsNames.Select(columnName => tableOutput[0].IndexOf(columnName));
for (int i = 1; i < tableOutput.Count; i++)
{
if (columnIndexes.Any(index => tableOutput[i][index].Contains(value, StringComparison.OrdinalIgnoreCase)))
{
continue;
}
// template name can be shortened so the name criteria might be truncated.
if (columnsNames.Contains("Template Name") && tableOutput[i][tableOutput[0].IndexOf("Template Name")].EndsWith("..."))
{
continue;
}
// tags can be shortened so the tag criteria might be truncated.
if (columnsNames.Contains("Tags") && tableOutput[i][tableOutput[0].IndexOf("Tags")].EndsWith("..."))
{
continue;
}
// tags can be shortened so the tag criteria might be truncated.
if (columnsNames.Contains("Tags") && tableOutput[i][tableOutput[0].IndexOf("Tags")].EndsWith("..."))
{
continue;
}
// if columns are template name and/or short name and they are empty - skip, grouping in done
bool criteriaA = columnsNames.Contains("Template Name")
&& string.IsNullOrWhiteSpace(tableOutput[i][tableOutput[0].IndexOf("Template Name")])
|| !columnsNames.Contains("Short Name");
bool criteriaB = columnsNames.Contains("Short Name")
&& string.IsNullOrWhiteSpace(tableOutput[i][tableOutput[0].IndexOf("Short Name")])
|| !columnsNames.Contains("Short Name");
bool criteriaC = columnsNames.Contains("Short Name") || columnsNames.Contains("Template Name");
if (criteriaA && criteriaB && criteriaC)
{
continue;
}
return false;
}
return true;
}
private static bool AllRowsEqual(List<List<string>> tableOutput, string[] columnsNames, string value)
{
IEnumerable<int> columnIndexes = columnsNames.Select(columnName => tableOutput[0].IndexOf(columnName));
for (int i = 1; i < tableOutput.Count; i++)
{
if (columnIndexes.Any(index => tableOutput[i][index].Equals(value, StringComparison.OrdinalIgnoreCase)))
{
continue;
}
return false;
}
return true;
}
private static bool SomeRowsContain(List<List<string>> tableOutput, string[] columnsNames, string value)
{
IEnumerable<int> columnIndexes = columnsNames.Select(columnName => tableOutput[0].IndexOf(columnName));
for (int i = 1; i < tableOutput.Count; i++)
{
if (columnIndexes.Any(index => tableOutput[i][index].Contains(value, StringComparison.OrdinalIgnoreCase)))
{
return true;
}
}
return false;
}
private static bool AllRowsAreNotEmpty(List<List<string>> tableOutput, string columnName)
{
int columnIndex = tableOutput[0].IndexOf(columnName);
return tableOutput.All(row => !string.IsNullOrWhiteSpace(row[columnIndex]));
}
private static bool AtLeastOneRowIsNotEmpty(List<List<string>> tableOutput, string columnName)
{
int columnIndex = tableOutput[0].IndexOf(columnName);
return tableOutput.Any(row => !string.IsNullOrWhiteSpace(row[columnIndex]));
}
private static List<List<string>> ParseTableOutput(string? stdOut, string[] expectedColumns)
{
string[] lines = stdOut?.Split(Environment.NewLine) ?? Array.Empty<string>();
int headerLineIndex = Array.FindIndex(lines, line => expectedColumns.All(column => line.Contains(column)));
string headerLine = lines[headerLineIndex];
//table ends before empty line
//or before first [Debug] entry
//table is written in single call, so there can be no [Debug] entry in the middle
int lastLineIndex = Array.FindIndex(lines, headerLineIndex + 1, line => (line.Length == 0 || line.Contains("[Debug]"))) - 1;
int[] columnIndexes = expectedColumns.Select(column => headerLine.IndexOf(column)).ToArray();
var parsedTable = new List<List<string>>();
// first array contain headers
var headerRow = new List<string>();
foreach (string expectedColumn in expectedColumns)
{
headerRow.Add(expectedColumn.Trim());
}
parsedTable.Add(headerRow);
//we start from 2nd row after header (1st row contains separator)
for (int i = headerLineIndex + 2; i <= lastLineIndex; i++)
{
List<string> parsedRow = new(SplitLineByColumns(lines[i], columnIndexes).Select(c => c.Trim()));
parsedTable.Add(parsedRow);
}
return parsedTable;
}
/// <summary>
/// Splits the given input string into multiple columns using the given indices.
/// Indices do not refer to the number of characters, but to the visual space occupied by characters when drawn.
/// </summary>
/// <param name="input">Input string to be splitted.</param>
/// <param name="indexes">Indices to split the string from.</param>
/// <returns></returns>
private static IEnumerable<string> SplitLineByColumns(string input, int[] indexes)
{
StringBuilder columnBuilder = new(capacity: 16);
int processedCharCount = 0;
int inputLength = input.Aggregate(0, (aggr, next) => aggr + Wcwidth.UnicodeCalculator.GetWidth(next));
for (int j = 0; j < indexes.Length; j++)
{
int unfilledColumnWidth = (j == indexes.Length - 1 ? inputLength : indexes[j + 1]) - indexes[j];
columnBuilder.Clear();
while (unfilledColumnWidth > 0)
{
char c = input[processedCharCount++];
int charLength = Wcwidth.UnicodeCalculator.GetWidth(c);
columnBuilder.Append(c);
unfilledColumnWidth -= charLength;
}
yield return columnBuilder.ToString();
}
}
private class ShrinkAwareCurrentCultureStringComparer : IComparer<string>
{
public int Compare(string? left, string? right)
{
if (string.IsNullOrEmpty(left) && string.IsNullOrEmpty(right))
{
return 0;
}
if (string.IsNullOrEmpty(left))
{
return -1;
}
if (string.IsNullOrEmpty(right))
{
return 1;
}
bool leftIsShrunk = left.EndsWith("...");
bool rightIsShrunk = right.EndsWith("...");
if (!(leftIsShrunk ^ rightIsShrunk))
{
// return string.Compare(left, right, StringComparison.CurrentCultureIgnoreCase);
return string.Compare(left, right, StringComparison.CurrentCultureIgnoreCase);
}
if (rightIsShrunk && left.StartsWith(right.Substring(0, right.Length - 3), StringComparison.CurrentCultureIgnoreCase))
{
return -1;
}
if (leftIsShrunk && right.StartsWith(left.Substring(0, left.Length - 3), StringComparison.CurrentCultureIgnoreCase))
{
return -1;
}
// return string.Compare(left, right, StringComparison.CurrentCultureIgnoreCase);
return string.Compare(left, right, StringComparison.CurrentCultureIgnoreCase);
}
}
private class DownloadCountComparer : IComparer<string>
{
public int Compare(string? x, string? y)
{
if (x == y || string.IsNullOrWhiteSpace(x) && string.IsNullOrWhiteSpace(y))
{
return 0;
}
if (string.IsNullOrWhiteSpace(x))
{
return -1;
}
if (string.IsNullOrWhiteSpace(y))
{
return 1;
}
int xInt = 0;
int yInt = 0;
if (x != "<1k")
{
_ = int.TryParse(x.Trim().AsSpan(0, x.Length - 1), System.Globalization.NumberStyles.AllowThousands, null, out xInt);
}
if (y != "<1k")
{
_ = int.TryParse(y.Trim().AsSpan(0, y.Length - 1), System.Globalization.NumberStyles.AllowThousands, null, out yInt);
}
return xInt.CompareTo(yInt);
}
}
}
}
|