Complete the refactor and test improvements

This commit is contained in:
Justin Goshi 2016-12-16 10:23:26 -08:00
parent 82f5278d8a
commit ae1e183e41
14 changed files with 188 additions and 202 deletions

View file

@ -16,7 +16,7 @@
<ItemGroup> <ItemGroup>
<Compile Include="**\*.cs" Exclude="bin\**;obj\**;**\*.xproj;packages\**" /> <Compile Include="**\*.cs" Exclude="bin\**;obj\**;**\*.xproj;packages\**" />
<Compile Include="..\..\..\src\dotnet\CommandLine\*.cs" Exclude="bin\**;obj\**;**\*.xproj;packages\**" /> <Compile Include="..\..\..\src\dotnet\CommandLine\*.cs;..\..\..\src\dotnet\CommonLocalizableStrings.cs;" Exclude="bin\**;obj\**;**\*.xproj;packages\**" />
<EmbeddedResource Include="**\*.resx" /> <EmbeddedResource Include="**\*.resx" />
<EmbeddedResource Include="compiler\resources\**\*" /> <EmbeddedResource Include="compiler\resources\**\*" />
</ItemGroup> </ItemGroup>

View file

@ -2,11 +2,14 @@
// Licensed under the MIT license. See LICENSE file in the project root for full license information. // Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System; using System;
using Microsoft.DotNet.Tools;
namespace Microsoft.DotNet.Cli.CommandLine namespace Microsoft.DotNet.Cli.CommandLine
{ {
internal class CommandParsingException : Exception internal class CommandParsingException : Exception
{ {
private bool _isRequireSubCommandMissing;
public CommandParsingException( public CommandParsingException(
CommandLineApplication command, CommandLineApplication command,
string message, string message,
@ -14,10 +17,19 @@ namespace Microsoft.DotNet.Cli.CommandLine
: base(message) : base(message)
{ {
Command = command; Command = command;
IsRequireSubCommandMissing = isRequireSubCommandMissing; _isRequireSubCommandMissing = isRequireSubCommandMissing;
} }
public CommandLineApplication Command { get; } public CommandLineApplication Command { get; }
public bool IsRequireSubCommandMissing { get; }
public override string Message
{
get
{
return _isRequireSubCommandMissing
? CommonLocalizableStrings.RequiredCommandNotPassed
: base.Message;
}
}
} }
} }

View file

@ -76,11 +76,7 @@ namespace Microsoft.DotNet.Cli
} }
catch (CommandParsingException e) catch (CommandParsingException e)
{ {
string errorMessage = e.IsRequireSubCommandMissing Reporter.Error.WriteLine(e.Message.Red());
? CommonLocalizableStrings.RequiredCommandNotPassed
: e.Message;
Reporter.Error.WriteLine(errorMessage.Red());
return 1; return 1;
} }
} }

View file

@ -1,13 +0,0 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System.Collections.Generic;
namespace Microsoft.DotNet.Tools.List
{
public interface IListSubCommand
{
string LocalizedErrorMessageNoItemsFound { get; }
IList<string> Items { get; }
}
}

View file

@ -1,71 +0,0 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using Microsoft.DotNet.Cli.CommandLine;
using Microsoft.DotNet.Cli.Utils;
using Microsoft.DotNet.Tools.Common;
using System.Collections.Generic;
using System.IO;
using System.Linq;
namespace Microsoft.DotNet.Tools.List
{
public abstract class ListSubCommandBase
{
protected abstract string CommandName { get; }
protected abstract string LocalizedDisplayName { get; }
protected abstract string LocalizedDescription { get; }
protected abstract IListSubCommand CreateIListSubCommand(string fileOrDirectory);
internal CommandLineApplication Create(CommandLineApplication parentApp)
{
CommandLineApplication app = parentApp.Command(CommandName, throwOnUnexpectedArg: false);
app.FullName = LocalizedDisplayName;
app.Description = LocalizedDescription;
app.HelpOption("-h|--help");
app.OnExecute(() => {
try
{
if (!parentApp.Arguments.Any())
{
throw new GracefulException(
CommonLocalizableStrings.RequiredArgumentNotPassed,
Constants.ProjectOrSolutionArgumentName);
}
var projectOrDirectory = parentApp.Arguments.First().Value;
if (string.IsNullOrEmpty(projectOrDirectory))
{
projectOrDirectory = PathUtility.EnsureTrailingSlash(Directory.GetCurrentDirectory());
}
var listCommand = CreateIListSubCommand(projectOrDirectory);
if (listCommand.Items.Count == 0)
{
Reporter.Output.WriteLine(listCommand.LocalizedErrorMessageNoItemsFound);
return 0;
}
Reporter.Output.WriteLine($"{CommonLocalizableStrings.ProjectReferenceOneOrMore}");
Reporter.Output.WriteLine(new string('-', CommonLocalizableStrings.ProjectReferenceOneOrMore.Length));
foreach (var item in listCommand.Items)
{
Reporter.Output.WriteLine(item);
}
return 0;
}
catch (GracefulException e)
{
Reporter.Error.WriteLine(e.Message.Red());
app.ShowHelp();
return 1;
}
});
return app;
}
}
}

View file

@ -4,7 +4,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using Microsoft.DotNet.Cli; using Microsoft.DotNet.Cli;
using Microsoft.DotNet.Cli.CommandLine;
using Microsoft.DotNet.Tools.List.ProjectToProjectReferences; using Microsoft.DotNet.Tools.List.ProjectToProjectReferences;
using Microsoft.DotNet.Tools.List.ProjectsInSolution; using Microsoft.DotNet.Tools.List.ProjectsInSolution;
@ -14,11 +13,11 @@ namespace Microsoft.DotNet.Tools.List
{ {
protected override string CommandName => "list"; protected override string CommandName => "list";
protected override string FullCommandNameLocalized => LocalizableStrings.NetListCommand; protected override string FullCommandNameLocalized => LocalizableStrings.NetListCommand;
internal override List<Func<CommandLineApplication, CommandLineApplication>> SubCommands => internal override List<Func<DotNetSubCommandBase>> SubCommands =>
new List<Func<CommandLineApplication, CommandLineApplication>> new List<Func<DotNetSubCommandBase>>
{ {
ListProjectsInSolutionCommand.CreateApplication, ListProjectsInSolutionCommand.Create,
ListProjectToProjectReferencesCommand.CreateApplication, ListProjectToProjectReferencesCommand.Create,
}; };
public static int Run(string[] args) public static int Run(string[] args)

View file

@ -2,52 +2,50 @@
// Licensed under the MIT license. See LICENSE file in the project root for full license information. // Licensed under the MIT license. See LICENSE file in the project root for full license information.
using Microsoft.Build.Evaluation; using Microsoft.Build.Evaluation;
using Microsoft.DotNet.Cli.CommandLine; using Microsoft.DotNet.Cli;
using System.Collections.Generic; using Microsoft.DotNet.Cli.Utils;
using Microsoft.DotNet.Tools.List; using System.Linq;
namespace Microsoft.DotNet.Tools.List.ProjectToProjectReferences namespace Microsoft.DotNet.Tools.List.ProjectToProjectReferences
{ {
public class ListProjectToProjectReferences : IListSubCommand internal class ListProjectToProjectReferencesCommand : DotNetSubCommandBase
{ {
private string _fileOrDirectory = null; public static DotNetSubCommandBase Create()
private IList<string> _items = new List<string>(); {
var command = new ListProjectToProjectReferencesCommand()
public ListProjectToProjectReferences(string fileOrDirectory) {
Name = "p2ps",
FullName = LocalizableStrings.AppFullName,
Description = LocalizableStrings.AppDescription,
};
command.HelpOption("-h|--help");
return command;
}
public override int Run(string fileOrDirectory)
{ {
_fileOrDirectory = fileOrDirectory;
var msbuildProj = MsbuildProject.FromFileOrDirectory(new ProjectCollection(), fileOrDirectory); var msbuildProj = MsbuildProject.FromFileOrDirectory(new ProjectCollection(), fileOrDirectory);
var p2ps = msbuildProj.GetProjectToProjectReferences(); var p2ps = msbuildProj.GetProjectToProjectReferences();
if (!p2ps.Any())
{
Reporter.Output.WriteLine(string.Format(
CommonLocalizableStrings.NoReferencesFound,
CommonLocalizableStrings.P2P,
fileOrDirectory));
return 0;
}
Reporter.Output.WriteLine($"{CommonLocalizableStrings.ProjectReferenceOneOrMore}");
Reporter.Output.WriteLine(new string('-', CommonLocalizableStrings.ProjectReferenceOneOrMore.Length));
foreach (var p2p in p2ps) foreach (var p2p in p2ps)
{ {
_items.Add(p2p.Include); Reporter.Output.WriteLine(p2p.Include);
} }
}
public string LocalizedErrorMessageNoItemsFound => string.Format( return 0;
LocalizableStrings.NoReferencesFound,
CommonLocalizableStrings.P2P,
_fileOrDirectory);
public IList<string> Items => _items;
}
public class ListProjectToProjectReferencesCommand : ListSubCommandBase
{
protected override string CommandName => "p2ps";
protected override string LocalizedDisplayName => LocalizableStrings.AppFullName;
protected override string LocalizedDescription => LocalizableStrings.AppDescription;
protected override IListSubCommand CreateIListSubCommand(string fileOrDirectory)
{
return new ListProjectToProjectReferences(fileOrDirectory);
}
internal static CommandLineApplication CreateApplication(CommandLineApplication parentApp)
{
var command = new ListProjectToProjectReferencesCommand();
return command.Create(parentApp);
} }
} }
} }

View file

@ -1,46 +1,46 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved. // Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information. // Licensed under the MIT license. See LICENSE file in the project root for full license information.
using Microsoft.DotNet.Cli.CommandLine; using Microsoft.DotNet.Cli;
using Microsoft.DotNet.Cli.Sln.Internal; using Microsoft.DotNet.Cli.Sln.Internal;
using Microsoft.DotNet.Cli.Utils;
using Microsoft.DotNet.Tools.Common; using Microsoft.DotNet.Tools.Common;
using System.Collections.Generic;
using Microsoft.DotNet.Tools.List;
namespace Microsoft.DotNet.Tools.List.ProjectsInSolution namespace Microsoft.DotNet.Tools.List.ProjectsInSolution
{ {
public class ListProjectsInSolution : IListSubCommand internal class ListProjectsInSolutionCommand : DotNetSubCommandBase
{ {
private IList<string> _items = new List<string>(); public static DotNetSubCommandBase Create()
{
var command = new ListProjectsInSolutionCommand()
{
Name = "projects",
FullName = LocalizableStrings.AppFullName,
Description = LocalizableStrings.AppDescription,
};
public ListProjectsInSolution(string fileOrDirectory) command.HelpOption("-h|--help");
return command;
}
public override int Run(string fileOrDirectory)
{ {
SlnFile slnFile = SlnFileFactory.CreateFromFileOrDirectory(fileOrDirectory); SlnFile slnFile = SlnFileFactory.CreateFromFileOrDirectory(fileOrDirectory);
foreach (var slnProject in slnFile.Projects) if (slnFile.Projects.Count == 0)
{ {
_items.Add(slnProject.FilePath); Reporter.Output.WriteLine(CommonLocalizableStrings.NoProjectsFound);
} }
} else
{
public string LocalizedErrorMessageNoItemsFound => CommonLocalizableStrings.NoProjectsFound; Reporter.Output.WriteLine($"{CommonLocalizableStrings.ProjectReferenceOneOrMore}");
public IList<string> Items => _items; Reporter.Output.WriteLine(new string('-', CommonLocalizableStrings.ProjectReferenceOneOrMore.Length));
} foreach (var slnProject in slnFile.Projects)
{
public class ListProjectsInSolutionCommand : ListSubCommandBase Reporter.Output.WriteLine(slnProject.FilePath);
{ }
protected override string CommandName => "projects"; }
protected override string LocalizedDisplayName => LocalizableStrings.AppFullName; return 0;
protected override string LocalizedDescription => LocalizableStrings.AppDescription;
protected override IListSubCommand CreateIListSubCommand(string fileOrDirectory)
{
return new ListProjectsInSolution(fileOrDirectory);
}
internal static CommandLineApplication CreateApplication(CommandLineApplication parentApp)
{
var command = new ListProjectsInSolutionCommand();
return command.Create(parentApp);
} }
} }
} }

View file

@ -95,6 +95,17 @@ Args:
cmd.StdOut.Should().Be(HelpText); cmd.StdOut.Should().Be(HelpText);
} }
[Theory]
[InlineData("")]
[InlineData("unknownCommandName")]
public void WhenNoCommandIsPassedItPrintsError(string commandName)
{
var cmd = new DotnetCommand()
.ExecuteWithCapturedOutput($"add {commandName}");
cmd.Should().Fail();
cmd.StdErr.Should().Be("Required command was not provided.");
}
[Fact] [Fact]
public void WhenTooManyArgumentsArePassedItPrintsError() public void WhenTooManyArgumentsArePassedItPrintsError()
{ {

View file

@ -39,14 +39,15 @@ Args:
cmd.StdOut.Should().Be(HelpText); cmd.StdOut.Should().Be(HelpText);
} }
[Fact] [Theory]
public void WhenTooManyArgumentsArePassedItPrintsError() [InlineData("")]
[InlineData("unknownCommandName")]
public void WhenNoCommandIsPassedItPrintsError(string commandName)
{ {
var cmd = new DotnetCommand() var cmd = new DotnetCommand()
.ExecuteWithCapturedOutput("add one.sln two.sln three.sln project"); .ExecuteWithCapturedOutput($"add {commandName}");
cmd.Should().Fail(); cmd.Should().Fail();
cmd.StdErr.Should().Be("Unrecognized command or argument 'two.sln'"); cmd.StdErr.Should().Be("Required command was not provided.");
cmd.StdOut.Should().Be("Specify --help for a list of available options and commands.");
} }
[Fact] [Fact]
@ -55,7 +56,8 @@ Args:
var cmd = new DotnetCommand() var cmd = new DotnetCommand()
.ExecuteWithCapturedOutput("add one.sln two.sln three.sln project"); .ExecuteWithCapturedOutput("add one.sln two.sln three.sln project");
cmd.Should().Fail(); cmd.Should().Fail();
cmd.StdErr.Should().Contain("Unrecognized command or argument"); cmd.StdErr.Should().Be("Unrecognized command or argument 'two.sln'");
cmd.StdOut.Should().Be("Specify --help for a list of available options and commands.");
} }
[Theory] [Theory]

View file

@ -13,11 +13,20 @@ namespace Microsoft.DotNet.Cli.List.P2P.Tests
{ {
public class GivenDotnetListP2Ps : TestBase public class GivenDotnetListP2Ps : TestBase
{ {
private const string HelpText = @".NET Core Project-to-Project dependency viewer
Usage: dotnet list <PROJECT_OR_SOLUTION> p2ps [options]
Arguments:
<PROJECT_OR_SOLUTION> The project or solution to operation on. If a file is not specified, the current directory is searched.
Options:
-h|--help Show help information";
const string FrameworkNet451Arg = "-f net451"; const string FrameworkNet451Arg = "-f net451";
const string ConditionFrameworkNet451 = "== 'net451'"; const string ConditionFrameworkNet451 = "== 'net451'";
const string FrameworkNetCoreApp10Arg = "-f netcoreapp1.0"; const string FrameworkNetCoreApp10Arg = "-f netcoreapp1.0";
const string ConditionFrameworkNetCoreApp10 = "== 'netcoreapp1.0'"; const string ConditionFrameworkNetCoreApp10 = "== 'netcoreapp1.0'";
const string UsageText = "Usage: dotnet list <PROJECT_OR_SOLUTION> p2ps";
[Theory] [Theory]
[InlineData("--help")] [InlineData("--help")]
@ -26,7 +35,18 @@ namespace Microsoft.DotNet.Cli.List.P2P.Tests
{ {
var cmd = new ListP2PsCommand().Execute(helpArg); var cmd = new ListP2PsCommand().Execute(helpArg);
cmd.Should().Pass(); cmd.Should().Pass();
cmd.StdOut.Should().Contain("Usage"); cmd.StdOut.Should().Be(HelpText);
}
[Theory]
[InlineData("")]
[InlineData("unknownCommandName")]
public void WhenNoCommandIsPassedItPrintsError(string commandName)
{
var cmd = new DotnetCommand()
.ExecuteWithCapturedOutput($"list {commandName}");
cmd.Should().Fail();
cmd.StdErr.Should().Be("Required command was not provided.");
} }
[Fact] [Fact]
@ -36,7 +56,7 @@ namespace Microsoft.DotNet.Cli.List.P2P.Tests
.WithProject("one two three") .WithProject("one two three")
.Execute("proj.csproj"); .Execute("proj.csproj");
cmd.ExitCode.Should().NotBe(0); cmd.ExitCode.Should().NotBe(0);
cmd.StdErr.Should().Contain("Unrecognized command or argument"); cmd.StdErr.Should().Be("Unrecognized command or argument 'two'");
} }
[Theory] [Theory]
@ -51,8 +71,8 @@ namespace Microsoft.DotNet.Cli.List.P2P.Tests
.WithProject(projName) .WithProject(projName)
.Execute($"\"{setup.ValidRefCsprojPath}\""); .Execute($"\"{setup.ValidRefCsprojPath}\"");
cmd.ExitCode.Should().NotBe(0); cmd.ExitCode.Should().NotBe(0);
cmd.StdErr.Should().Contain("Could not find"); cmd.StdErr.Should().Be($"Could not find project or directory `{projName}`.");
cmd.StdOut.Should().Contain(UsageText); cmd.StdOut.Should().Be(HelpText);
} }
[Fact] [Fact]
@ -66,8 +86,8 @@ namespace Microsoft.DotNet.Cli.List.P2P.Tests
.WithProject(projName) .WithProject(projName)
.Execute($"\"{setup.ValidRefCsprojPath}\""); .Execute($"\"{setup.ValidRefCsprojPath}\"");
cmd.ExitCode.Should().NotBe(0); cmd.ExitCode.Should().NotBe(0);
cmd.StdErr.Should().Contain(" is invalid."); cmd.StdErr.Should().Be("Project `Broken/Broken.csproj` is invalid.");
cmd.StdOut.Should().Contain(UsageText); cmd.StdOut.Should().Be(HelpText);
} }
[Fact] [Fact]
@ -75,12 +95,13 @@ namespace Microsoft.DotNet.Cli.List.P2P.Tests
{ {
var setup = Setup(); var setup = Setup();
var workingDir = Path.Combine(setup.TestRoot, "MoreThanOne");
var cmd = new ListP2PsCommand() var cmd = new ListP2PsCommand()
.WithWorkingDirectory(Path.Combine(setup.TestRoot, "MoreThanOne")) .WithWorkingDirectory(workingDir)
.Execute($"\"{setup.ValidRefCsprojRelToOtherProjPath}\""); .Execute($"\"{setup.ValidRefCsprojRelToOtherProjPath}\"");
cmd.ExitCode.Should().NotBe(0); cmd.ExitCode.Should().NotBe(0);
cmd.StdErr.Should().Contain("more than one"); cmd.StdErr.Should().Be($"Found more than one project in `{workingDir + Path.DirectorySeparatorChar}`. Please specify which one to use.");
cmd.StdOut.Should().Contain(UsageText); cmd.StdOut.Should().Be(HelpText);
} }
[Fact] [Fact]
@ -92,8 +113,8 @@ namespace Microsoft.DotNet.Cli.List.P2P.Tests
.WithWorkingDirectory(setup.TestRoot) .WithWorkingDirectory(setup.TestRoot)
.Execute($"\"{setup.ValidRefCsprojPath}\""); .Execute($"\"{setup.ValidRefCsprojPath}\"");
cmd.ExitCode.Should().NotBe(0); cmd.ExitCode.Should().NotBe(0);
cmd.StdErr.Should().Contain("not find any"); cmd.StdErr.Should().Be($"Could not find any project in `{setup.TestRoot + Path.DirectorySeparatorChar}`.");
cmd.StdOut.Should().Contain(UsageText); cmd.StdOut.Should().Be(HelpText);
} }
[Fact] [Fact]
@ -105,12 +126,16 @@ namespace Microsoft.DotNet.Cli.List.P2P.Tests
.WithProject(lib.CsProjPath) .WithProject(lib.CsProjPath)
.Execute(); .Execute();
cmd.Should().Pass(); cmd.Should().Pass();
cmd.StdOut.Should().Contain("There are no Project to Project references in project"); cmd.StdOut.Should().Be($"There are no Project to Project references in project {lib.CsProjPath}. ;; Project to Project is the type of the item being requested (project, package, p2p) and {lib.CsProjPath} is the object operated on (a project file or a solution file). ");
} }
[Fact] [Fact]
public void ItPrintsSingleReference() public void ItPrintsSingleReference()
{ {
const string OutputText = @"Project reference(s)
--------------------
..\ItPrintsSingleReferenceref\ItPrintsSingleReferenceref.csproj";
var lib = NewLib("ItPrintsSingleReference", "lib"); var lib = NewLib("ItPrintsSingleReference", "lib");
string ref1 = NewLib("ItPrintsSingleReference", "ref").CsProjPath; string ref1 = NewLib("ItPrintsSingleReference", "ref").CsProjPath;
AddValidRef(ref1, lib); AddValidRef(ref1, lib);
@ -119,13 +144,18 @@ namespace Microsoft.DotNet.Cli.List.P2P.Tests
.WithProject(lib.CsProjPath) .WithProject(lib.CsProjPath)
.Execute(); .Execute();
cmd.Should().Pass(); cmd.Should().Pass();
cmd.StdOut.Should().Contain("Project reference(s)"); cmd.StdOut.Should().Be(OutputText);
cmd.StdOut.Should().Contain(@"..\ItPrintsSingleReferenceref\ItPrintsSingleReferenceref.csproj");
} }
[Fact] [Fact]
public void ItPrintsMultipleReferences() public void ItPrintsMultipleReferences()
{ {
const string OutputText = @"Project reference(s)
--------------------
..\ItPrintsSingleReferenceref1\ItPrintsSingleReferenceref1.csproj
..\ItPrintsSingleReferenceref2\ItPrintsSingleReferenceref2.csproj
..\ItPrintsSingleReferenceref3\ItPrintsSingleReferenceref3.csproj";
var lib = NewLib("ItPrintsSingleReference", "lib"); var lib = NewLib("ItPrintsSingleReference", "lib");
string ref1 = NewLib("ItPrintsSingleReference", "ref1").CsProjPath; string ref1 = NewLib("ItPrintsSingleReference", "ref1").CsProjPath;
string ref2 = NewLib("ItPrintsSingleReference", "ref2").CsProjPath; string ref2 = NewLib("ItPrintsSingleReference", "ref2").CsProjPath;
@ -139,10 +169,7 @@ namespace Microsoft.DotNet.Cli.List.P2P.Tests
.WithProject(lib.CsProjPath) .WithProject(lib.CsProjPath)
.Execute(); .Execute();
cmd.Should().Pass(); cmd.Should().Pass();
cmd.StdOut.Should().Contain("Project reference(s)"); cmd.StdOut.Should().Be(OutputText);
cmd.StdOut.Should().Contain(@"..\ItPrintsSingleReferenceref1\ItPrintsSingleReferenceref1.csproj");
cmd.StdOut.Should().Contain(@"..\ItPrintsSingleReferenceref2\ItPrintsSingleReferenceref2.csproj");
cmd.StdOut.Should().Contain(@"..\ItPrintsSingleReferenceref3\ItPrintsSingleReferenceref3.csproj");
} }
private TestSetup Setup([System.Runtime.CompilerServices.CallerMemberName] string callingMethod = nameof(Setup), string identifier = "") private TestSetup Setup([System.Runtime.CompilerServices.CallerMemberName] string callingMethod = nameof(Setup), string identifier = "")

View file

@ -31,7 +31,7 @@ Options:
var cmd = new DotnetCommand() var cmd = new DotnetCommand()
.ExecuteWithCapturedOutput($"list projects {helpArg}"); .ExecuteWithCapturedOutput($"list projects {helpArg}");
cmd.Should().Pass(); cmd.Should().Pass();
cmd.StdOut.Should().Contain(HelpText); cmd.StdOut.Should().Be(HelpText);
} }
[Theory] [Theory]
@ -42,7 +42,7 @@ Options:
var cmd = new DotnetCommand() var cmd = new DotnetCommand()
.ExecuteWithCapturedOutput($"list {commandName}"); .ExecuteWithCapturedOutput($"list {commandName}");
cmd.Should().Fail(); cmd.Should().Fail();
cmd.StdErr.Should().Contain("Required command was not provided."); cmd.StdErr.Should().Be("Required command was not provided.");
} }
[Fact] [Fact]
@ -51,7 +51,7 @@ Options:
var cmd = new DotnetCommand() var cmd = new DotnetCommand()
.ExecuteWithCapturedOutput("list one.sln two.sln three.sln projects"); .ExecuteWithCapturedOutput("list one.sln two.sln three.sln projects");
cmd.Should().Fail(); cmd.Should().Fail();
cmd.StdErr.Should().Contain("Unrecognized command or argument 'two.sln'"); cmd.StdErr.Should().Be("Unrecognized command or argument 'two.sln'");
} }
[Theory] [Theory]
@ -65,8 +65,8 @@ Options:
var cmd = new DotnetCommand() var cmd = new DotnetCommand()
.ExecuteWithCapturedOutput($"list {solutionName} projects"); .ExecuteWithCapturedOutput($"list {solutionName} projects");
cmd.Should().Fail(); cmd.Should().Fail();
cmd.StdErr.Should().Contain($"Could not find solution or directory `{solutionName}`"); cmd.StdErr.Should().Be($"Could not find solution or directory `{solutionName}`.");
cmd.StdOut.Should().Contain(HelpText); cmd.StdOut.Should().Be(HelpText);
} }
[Fact] [Fact]
@ -83,8 +83,8 @@ Options:
.WithWorkingDirectory(projectDirectory) .WithWorkingDirectory(projectDirectory)
.ExecuteWithCapturedOutput("list InvalidSolution.sln projects"); .ExecuteWithCapturedOutput("list InvalidSolution.sln projects");
cmd.Should().Fail(); cmd.Should().Fail();
cmd.StdErr.Should().Contain("Invalid solution `InvalidSolution.sln`"); cmd.StdErr.Should().Be("Invalid solution `InvalidSolution.sln`.");
cmd.StdOut.Should().Contain(HelpText); cmd.StdOut.Should().Be(HelpText);
} }
[Fact] [Fact]
@ -102,8 +102,8 @@ Options:
.WithWorkingDirectory(projectDirectory) .WithWorkingDirectory(projectDirectory)
.ExecuteWithCapturedOutput("list projects"); .ExecuteWithCapturedOutput("list projects");
cmd.Should().Fail(); cmd.Should().Fail();
cmd.StdErr.Should().Contain($"Invalid solution `{solutionFullPath}`"); cmd.StdErr.Should().Be($"Invalid solution `{solutionFullPath}`.");
cmd.StdOut.Should().Contain(HelpText); cmd.StdOut.Should().Be(HelpText);
} }
[Fact] [Fact]
@ -121,8 +121,8 @@ Options:
.WithWorkingDirectory(solutionDir) .WithWorkingDirectory(solutionDir)
.ExecuteWithCapturedOutput("list projects"); .ExecuteWithCapturedOutput("list projects");
cmd.Should().Fail(); cmd.Should().Fail();
cmd.StdErr.Should().Contain($"Specified solution file {solutionDir + Path.DirectorySeparatorChar} does not exist, or there is no solution file in the directory"); cmd.StdErr.Should().Be($"Specified solution file {solutionDir + Path.DirectorySeparatorChar} does not exist, or there is no solution file in the directory.");
cmd.StdOut.Should().Contain(HelpText); cmd.StdOut.Should().Be(HelpText);
} }
[Fact] [Fact]
@ -139,8 +139,8 @@ Options:
.WithWorkingDirectory(projectDirectory) .WithWorkingDirectory(projectDirectory)
.ExecuteWithCapturedOutput("list projects"); .ExecuteWithCapturedOutput("list projects");
cmd.Should().Fail(); cmd.Should().Fail();
cmd.StdErr.Should().Contain($"Found more than one solution file in {projectDirectory + Path.DirectorySeparatorChar}. Please specify which one to use."); cmd.StdErr.Should().Be($"Found more than one solution file in {projectDirectory + Path.DirectorySeparatorChar}. Please specify which one to use.");
cmd.StdOut.Should().Contain(HelpText); cmd.StdOut.Should().Be(HelpText);
} }
[Fact] [Fact]
@ -157,12 +157,17 @@ Options:
.WithWorkingDirectory(projectDirectory) .WithWorkingDirectory(projectDirectory)
.ExecuteWithCapturedOutput("list projects"); .ExecuteWithCapturedOutput("list projects");
cmd.Should().Pass(); cmd.Should().Pass();
cmd.StdOut.Should().Contain("No projects found in the solution."); cmd.StdOut.Should().Be("No projects found in the solution.");
} }
[Fact] [Fact]
public void WhenProjectReferencesArePresentInTheSolutionItListsThem() public void WhenProjectReferencesArePresentInTheSolutionItListsThem()
{ {
const string OutputText = @"Project reference(s)
--------------------
App\App.csproj
Lib\Lib.csproj";
var projectDirectory = TestAssets var projectDirectory = TestAssets
.Get("TestAppWithSlnAndExistingCsprojReferences") .Get("TestAppWithSlnAndExistingCsprojReferences")
.CreateInstance() .CreateInstance()
@ -174,9 +179,7 @@ Options:
.WithWorkingDirectory(projectDirectory) .WithWorkingDirectory(projectDirectory)
.ExecuteWithCapturedOutput("list projects"); .ExecuteWithCapturedOutput("list projects");
cmd.Should().Pass(); cmd.Should().Pass();
cmd.StdOut.Should().Contain("Project reference(s)"); cmd.StdOut.Should().Be(OutputText);
cmd.StdOut.Should().Contain(@"App\App.csproj");
cmd.StdOut.Should().Contain(@"Lib\Lib.csproj");
} }
} }
} }

View file

@ -121,6 +121,17 @@ Args:
cmd.StdOut.Should().Be(HelpText); cmd.StdOut.Should().Be(HelpText);
} }
[Theory]
[InlineData("")]
[InlineData("unknownCommandName")]
public void WhenNoCommandIsPassedItPrintsError(string commandName)
{
var cmd = new DotnetCommand()
.ExecuteWithCapturedOutput($"remove {commandName}");
cmd.Should().Fail();
cmd.StdErr.Should().Be("Required command was not provided.");
}
[Fact] [Fact]
public void WhenTooManyArgumentsArePassedItPrintsError() public void WhenTooManyArgumentsArePassedItPrintsError()
{ {

View file

@ -47,6 +47,17 @@ Args:
cmd.StdOut.Should().Be("Specify --help for a list of available options and commands."); cmd.StdOut.Should().Be("Specify --help for a list of available options and commands.");
} }
[Theory]
[InlineData("")]
[InlineData("unknownCommandName")]
public void WhenNoCommandIsPassedItPrintsError(string commandName)
{
var cmd = new DotnetCommand()
.ExecuteWithCapturedOutput($"remove {commandName}");
cmd.Should().Fail();
cmd.StdErr.Should().Be("Required command was not provided.");
}
[Theory] [Theory]
[InlineData("idontexist.sln")] [InlineData("idontexist.sln")]
[InlineData("ihave?invalidcharacters")] [InlineData("ihave?invalidcharacters")]