From ae1e183e416d5f7fba480d284b52348d9ba81004 Mon Sep 17 00:00:00 2001 From: Justin Goshi Date: Fri, 16 Dec 2016 10:23:26 -0800 Subject: [PATCH] Complete the refactor and test improvements --- .../dotnet-dependency-tool-invoker.csproj | 2 +- .../CommandLine/CommandParsingException.cs | 16 ++++- src/dotnet/DotNetTopLevelCommandBase.cs | 6 +- .../commands/dotnet-list/IListSubCommand.cs | 13 ---- .../dotnet-list/ListSubCommandBase.cs | 71 ------------------- src/dotnet/commands/dotnet-list/Program.cs | 9 ++- .../dotnet-list/dotnet-list-p2ps/Program.cs | 66 +++++++++-------- .../dotnet-list/dotnet-list-proj/Program.cs | 58 +++++++-------- .../dotnet-add-p2p.Tests/GivenDotnetAddP2P.cs | 11 +++ .../GivenDotnetAddProj.cs | 14 ++-- .../GivenDotnetListP2Ps.cs | 65 ++++++++++++----- .../GivenDotnetListProj.cs | 37 +++++----- .../GivenDotnetRemoveP2P.cs | 11 +++ .../GivenDotnetRemoveProj.cs | 11 +++ 14 files changed, 188 insertions(+), 202 deletions(-) delete mode 100644 src/dotnet/commands/dotnet-list/IListSubCommand.cs delete mode 100644 src/dotnet/commands/dotnet-list/ListSubCommandBase.cs diff --git a/TestAssets/TestPackages/dotnet-dependency-tool-invoker/dotnet-dependency-tool-invoker.csproj b/TestAssets/TestPackages/dotnet-dependency-tool-invoker/dotnet-dependency-tool-invoker.csproj index cc26d6ade..b19a858f7 100644 --- a/TestAssets/TestPackages/dotnet-dependency-tool-invoker/dotnet-dependency-tool-invoker.csproj +++ b/TestAssets/TestPackages/dotnet-dependency-tool-invoker/dotnet-dependency-tool-invoker.csproj @@ -16,7 +16,7 @@ - + diff --git a/src/dotnet/CommandLine/CommandParsingException.cs b/src/dotnet/CommandLine/CommandParsingException.cs index e495534a3..375c17394 100644 --- a/src/dotnet/CommandLine/CommandParsingException.cs +++ b/src/dotnet/CommandLine/CommandParsingException.cs @@ -2,11 +2,14 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. using System; +using Microsoft.DotNet.Tools; namespace Microsoft.DotNet.Cli.CommandLine { internal class CommandParsingException : Exception { + private bool _isRequireSubCommandMissing; + public CommandParsingException( CommandLineApplication command, string message, @@ -14,10 +17,19 @@ namespace Microsoft.DotNet.Cli.CommandLine : base(message) { Command = command; - IsRequireSubCommandMissing = isRequireSubCommandMissing; + _isRequireSubCommandMissing = isRequireSubCommandMissing; } public CommandLineApplication Command { get; } - public bool IsRequireSubCommandMissing { get; } + + public override string Message + { + get + { + return _isRequireSubCommandMissing + ? CommonLocalizableStrings.RequiredCommandNotPassed + : base.Message; + } + } } } diff --git a/src/dotnet/DotNetTopLevelCommandBase.cs b/src/dotnet/DotNetTopLevelCommandBase.cs index 6a06cf7ef..4e0483503 100644 --- a/src/dotnet/DotNetTopLevelCommandBase.cs +++ b/src/dotnet/DotNetTopLevelCommandBase.cs @@ -76,11 +76,7 @@ namespace Microsoft.DotNet.Cli } catch (CommandParsingException e) { - string errorMessage = e.IsRequireSubCommandMissing - ? CommonLocalizableStrings.RequiredCommandNotPassed - : e.Message; - - Reporter.Error.WriteLine(errorMessage.Red()); + Reporter.Error.WriteLine(e.Message.Red()); return 1; } } diff --git a/src/dotnet/commands/dotnet-list/IListSubCommand.cs b/src/dotnet/commands/dotnet-list/IListSubCommand.cs deleted file mode 100644 index d0f674759..000000000 --- a/src/dotnet/commands/dotnet-list/IListSubCommand.cs +++ /dev/null @@ -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 Items { get; } - } -} diff --git a/src/dotnet/commands/dotnet-list/ListSubCommandBase.cs b/src/dotnet/commands/dotnet-list/ListSubCommandBase.cs deleted file mode 100644 index 5f773a68a..000000000 --- a/src/dotnet/commands/dotnet-list/ListSubCommandBase.cs +++ /dev/null @@ -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; - } - } -} diff --git a/src/dotnet/commands/dotnet-list/Program.cs b/src/dotnet/commands/dotnet-list/Program.cs index 365708664..4bd038b08 100644 --- a/src/dotnet/commands/dotnet-list/Program.cs +++ b/src/dotnet/commands/dotnet-list/Program.cs @@ -4,7 +4,6 @@ using System; using System.Collections.Generic; using Microsoft.DotNet.Cli; -using Microsoft.DotNet.Cli.CommandLine; using Microsoft.DotNet.Tools.List.ProjectToProjectReferences; using Microsoft.DotNet.Tools.List.ProjectsInSolution; @@ -14,11 +13,11 @@ namespace Microsoft.DotNet.Tools.List { protected override string CommandName => "list"; protected override string FullCommandNameLocalized => LocalizableStrings.NetListCommand; - internal override List> SubCommands => - new List> + internal override List> SubCommands => + new List> { - ListProjectsInSolutionCommand.CreateApplication, - ListProjectToProjectReferencesCommand.CreateApplication, + ListProjectsInSolutionCommand.Create, + ListProjectToProjectReferencesCommand.Create, }; public static int Run(string[] args) diff --git a/src/dotnet/commands/dotnet-list/dotnet-list-p2ps/Program.cs b/src/dotnet/commands/dotnet-list/dotnet-list-p2ps/Program.cs index 2cedca511..f3ce2f62c 100644 --- a/src/dotnet/commands/dotnet-list/dotnet-list-p2ps/Program.cs +++ b/src/dotnet/commands/dotnet-list/dotnet-list-p2ps/Program.cs @@ -2,52 +2,50 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. using Microsoft.Build.Evaluation; -using Microsoft.DotNet.Cli.CommandLine; -using System.Collections.Generic; -using Microsoft.DotNet.Tools.List; +using Microsoft.DotNet.Cli; +using Microsoft.DotNet.Cli.Utils; +using System.Linq; namespace Microsoft.DotNet.Tools.List.ProjectToProjectReferences { - public class ListProjectToProjectReferences : IListSubCommand + internal class ListProjectToProjectReferencesCommand : DotNetSubCommandBase { - private string _fileOrDirectory = null; - private IList _items = new List(); - - public ListProjectToProjectReferences(string fileOrDirectory) + public static DotNetSubCommandBase Create() + { + var command = new ListProjectToProjectReferencesCommand() + { + 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 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) { - _items.Add(p2p.Include); + Reporter.Output.WriteLine(p2p.Include); } - } - public string LocalizedErrorMessageNoItemsFound => string.Format( - LocalizableStrings.NoReferencesFound, - CommonLocalizableStrings.P2P, - _fileOrDirectory); - - public IList 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); + return 0; } } } diff --git a/src/dotnet/commands/dotnet-list/dotnet-list-proj/Program.cs b/src/dotnet/commands/dotnet-list/dotnet-list-proj/Program.cs index 8fec98706..a8f3a07b0 100644 --- a/src/dotnet/commands/dotnet-list/dotnet-list-proj/Program.cs +++ b/src/dotnet/commands/dotnet-list/dotnet-list-proj/Program.cs @@ -1,46 +1,46 @@ // 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; using Microsoft.DotNet.Cli.Sln.Internal; +using Microsoft.DotNet.Cli.Utils; using Microsoft.DotNet.Tools.Common; -using System.Collections.Generic; -using Microsoft.DotNet.Tools.List; namespace Microsoft.DotNet.Tools.List.ProjectsInSolution { - public class ListProjectsInSolution : IListSubCommand + internal class ListProjectsInSolutionCommand : DotNetSubCommandBase { - private IList _items = new List(); + 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); - foreach (var slnProject in slnFile.Projects) + if (slnFile.Projects.Count == 0) { - _items.Add(slnProject.FilePath); + Reporter.Output.WriteLine(CommonLocalizableStrings.NoProjectsFound); } - } - - public string LocalizedErrorMessageNoItemsFound => CommonLocalizableStrings.NoProjectsFound; - public IList Items => _items; - } - - public class ListProjectsInSolutionCommand : ListSubCommandBase - { - protected override string CommandName => "projects"; - protected override string LocalizedDisplayName => LocalizableStrings.AppFullName; - 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); + else + { + Reporter.Output.WriteLine($"{CommonLocalizableStrings.ProjectReferenceOneOrMore}"); + Reporter.Output.WriteLine(new string('-', CommonLocalizableStrings.ProjectReferenceOneOrMore.Length)); + foreach (var slnProject in slnFile.Projects) + { + Reporter.Output.WriteLine(slnProject.FilePath); + } + } + return 0; } } } diff --git a/test/dotnet-add-p2p.Tests/GivenDotnetAddP2P.cs b/test/dotnet-add-p2p.Tests/GivenDotnetAddP2P.cs index 7398b033c..c808b0be5 100644 --- a/test/dotnet-add-p2p.Tests/GivenDotnetAddP2P.cs +++ b/test/dotnet-add-p2p.Tests/GivenDotnetAddP2P.cs @@ -95,6 +95,17 @@ Args: 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] public void WhenTooManyArgumentsArePassedItPrintsError() { diff --git a/test/dotnet-add-proj.Tests/GivenDotnetAddProj.cs b/test/dotnet-add-proj.Tests/GivenDotnetAddProj.cs index a4c099ea3..421cd917e 100644 --- a/test/dotnet-add-proj.Tests/GivenDotnetAddProj.cs +++ b/test/dotnet-add-proj.Tests/GivenDotnetAddProj.cs @@ -39,14 +39,15 @@ Args: cmd.StdOut.Should().Be(HelpText); } - [Fact] - public void WhenTooManyArgumentsArePassedItPrintsError() + [Theory] + [InlineData("")] + [InlineData("unknownCommandName")] + public void WhenNoCommandIsPassedItPrintsError(string commandName) { var cmd = new DotnetCommand() - .ExecuteWithCapturedOutput("add one.sln two.sln three.sln project"); + .ExecuteWithCapturedOutput($"add {commandName}"); cmd.Should().Fail(); - cmd.StdErr.Should().Be("Unrecognized command or argument 'two.sln'"); - cmd.StdOut.Should().Be("Specify --help for a list of available options and commands."); + cmd.StdErr.Should().Be("Required command was not provided."); } [Fact] @@ -55,7 +56,8 @@ Args: var cmd = new DotnetCommand() .ExecuteWithCapturedOutput("add one.sln two.sln three.sln project"); 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] diff --git a/test/dotnet-list-p2ps.Tests/GivenDotnetListP2Ps.cs b/test/dotnet-list-p2ps.Tests/GivenDotnetListP2Ps.cs index e000de90a..29a099d86 100644 --- a/test/dotnet-list-p2ps.Tests/GivenDotnetListP2Ps.cs +++ b/test/dotnet-list-p2ps.Tests/GivenDotnetListP2Ps.cs @@ -13,11 +13,20 @@ namespace Microsoft.DotNet.Cli.List.P2P.Tests { public class GivenDotnetListP2Ps : TestBase { + private const string HelpText = @".NET Core Project-to-Project dependency viewer + +Usage: dotnet list p2ps [options] + +Arguments: + 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 ConditionFrameworkNet451 = "== 'net451'"; const string FrameworkNetCoreApp10Arg = "-f netcoreapp1.0"; const string ConditionFrameworkNetCoreApp10 = "== 'netcoreapp1.0'"; - const string UsageText = "Usage: dotnet list p2ps"; [Theory] [InlineData("--help")] @@ -26,7 +35,18 @@ namespace Microsoft.DotNet.Cli.List.P2P.Tests { var cmd = new ListP2PsCommand().Execute(helpArg); 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] @@ -36,7 +56,7 @@ namespace Microsoft.DotNet.Cli.List.P2P.Tests .WithProject("one two three") .Execute("proj.csproj"); cmd.ExitCode.Should().NotBe(0); - cmd.StdErr.Should().Contain("Unrecognized command or argument"); + cmd.StdErr.Should().Be("Unrecognized command or argument 'two'"); } [Theory] @@ -51,8 +71,8 @@ namespace Microsoft.DotNet.Cli.List.P2P.Tests .WithProject(projName) .Execute($"\"{setup.ValidRefCsprojPath}\""); cmd.ExitCode.Should().NotBe(0); - cmd.StdErr.Should().Contain("Could not find"); - cmd.StdOut.Should().Contain(UsageText); + cmd.StdErr.Should().Be($"Could not find project or directory `{projName}`."); + cmd.StdOut.Should().Be(HelpText); } [Fact] @@ -66,8 +86,8 @@ namespace Microsoft.DotNet.Cli.List.P2P.Tests .WithProject(projName) .Execute($"\"{setup.ValidRefCsprojPath}\""); cmd.ExitCode.Should().NotBe(0); - cmd.StdErr.Should().Contain(" is invalid."); - cmd.StdOut.Should().Contain(UsageText); + cmd.StdErr.Should().Be("Project `Broken/Broken.csproj` is invalid."); + cmd.StdOut.Should().Be(HelpText); } [Fact] @@ -75,12 +95,13 @@ namespace Microsoft.DotNet.Cli.List.P2P.Tests { var setup = Setup(); + var workingDir = Path.Combine(setup.TestRoot, "MoreThanOne"); var cmd = new ListP2PsCommand() - .WithWorkingDirectory(Path.Combine(setup.TestRoot, "MoreThanOne")) + .WithWorkingDirectory(workingDir) .Execute($"\"{setup.ValidRefCsprojRelToOtherProjPath}\""); cmd.ExitCode.Should().NotBe(0); - cmd.StdErr.Should().Contain("more than one"); - cmd.StdOut.Should().Contain(UsageText); + cmd.StdErr.Should().Be($"Found more than one project in `{workingDir + Path.DirectorySeparatorChar}`. Please specify which one to use."); + cmd.StdOut.Should().Be(HelpText); } [Fact] @@ -92,8 +113,8 @@ namespace Microsoft.DotNet.Cli.List.P2P.Tests .WithWorkingDirectory(setup.TestRoot) .Execute($"\"{setup.ValidRefCsprojPath}\""); cmd.ExitCode.Should().NotBe(0); - cmd.StdErr.Should().Contain("not find any"); - cmd.StdOut.Should().Contain(UsageText); + cmd.StdErr.Should().Be($"Could not find any project in `{setup.TestRoot + Path.DirectorySeparatorChar}`."); + cmd.StdOut.Should().Be(HelpText); } [Fact] @@ -105,12 +126,16 @@ namespace Microsoft.DotNet.Cli.List.P2P.Tests .WithProject(lib.CsProjPath) .Execute(); 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] public void ItPrintsSingleReference() { + const string OutputText = @"Project reference(s) +-------------------- +..\ItPrintsSingleReferenceref\ItPrintsSingleReferenceref.csproj"; + var lib = NewLib("ItPrintsSingleReference", "lib"); string ref1 = NewLib("ItPrintsSingleReference", "ref").CsProjPath; AddValidRef(ref1, lib); @@ -119,13 +144,18 @@ namespace Microsoft.DotNet.Cli.List.P2P.Tests .WithProject(lib.CsProjPath) .Execute(); cmd.Should().Pass(); - cmd.StdOut.Should().Contain("Project reference(s)"); - cmd.StdOut.Should().Contain(@"..\ItPrintsSingleReferenceref\ItPrintsSingleReferenceref.csproj"); + cmd.StdOut.Should().Be(OutputText); } [Fact] public void ItPrintsMultipleReferences() { + const string OutputText = @"Project reference(s) +-------------------- +..\ItPrintsSingleReferenceref1\ItPrintsSingleReferenceref1.csproj +..\ItPrintsSingleReferenceref2\ItPrintsSingleReferenceref2.csproj +..\ItPrintsSingleReferenceref3\ItPrintsSingleReferenceref3.csproj"; + var lib = NewLib("ItPrintsSingleReference", "lib"); string ref1 = NewLib("ItPrintsSingleReference", "ref1").CsProjPath; string ref2 = NewLib("ItPrintsSingleReference", "ref2").CsProjPath; @@ -139,10 +169,7 @@ namespace Microsoft.DotNet.Cli.List.P2P.Tests .WithProject(lib.CsProjPath) .Execute(); cmd.Should().Pass(); - cmd.StdOut.Should().Contain("Project reference(s)"); - cmd.StdOut.Should().Contain(@"..\ItPrintsSingleReferenceref1\ItPrintsSingleReferenceref1.csproj"); - cmd.StdOut.Should().Contain(@"..\ItPrintsSingleReferenceref2\ItPrintsSingleReferenceref2.csproj"); - cmd.StdOut.Should().Contain(@"..\ItPrintsSingleReferenceref3\ItPrintsSingleReferenceref3.csproj"); + cmd.StdOut.Should().Be(OutputText); } private TestSetup Setup([System.Runtime.CompilerServices.CallerMemberName] string callingMethod = nameof(Setup), string identifier = "") diff --git a/test/dotnet-list-proj.Tests/GivenDotnetListProj.cs b/test/dotnet-list-proj.Tests/GivenDotnetListProj.cs index 9c9049ed0..a2026c6ba 100644 --- a/test/dotnet-list-proj.Tests/GivenDotnetListProj.cs +++ b/test/dotnet-list-proj.Tests/GivenDotnetListProj.cs @@ -31,7 +31,7 @@ Options: var cmd = new DotnetCommand() .ExecuteWithCapturedOutput($"list projects {helpArg}"); cmd.Should().Pass(); - cmd.StdOut.Should().Contain(HelpText); + cmd.StdOut.Should().Be(HelpText); } [Theory] @@ -42,7 +42,7 @@ Options: var cmd = new DotnetCommand() .ExecuteWithCapturedOutput($"list {commandName}"); cmd.Should().Fail(); - cmd.StdErr.Should().Contain("Required command was not provided."); + cmd.StdErr.Should().Be("Required command was not provided."); } [Fact] @@ -51,7 +51,7 @@ Options: var cmd = new DotnetCommand() .ExecuteWithCapturedOutput("list one.sln two.sln three.sln projects"); cmd.Should().Fail(); - cmd.StdErr.Should().Contain("Unrecognized command or argument 'two.sln'"); + cmd.StdErr.Should().Be("Unrecognized command or argument 'two.sln'"); } [Theory] @@ -65,8 +65,8 @@ Options: var cmd = new DotnetCommand() .ExecuteWithCapturedOutput($"list {solutionName} projects"); cmd.Should().Fail(); - cmd.StdErr.Should().Contain($"Could not find solution or directory `{solutionName}`"); - cmd.StdOut.Should().Contain(HelpText); + cmd.StdErr.Should().Be($"Could not find solution or directory `{solutionName}`."); + cmd.StdOut.Should().Be(HelpText); } [Fact] @@ -83,8 +83,8 @@ Options: .WithWorkingDirectory(projectDirectory) .ExecuteWithCapturedOutput("list InvalidSolution.sln projects"); cmd.Should().Fail(); - cmd.StdErr.Should().Contain("Invalid solution `InvalidSolution.sln`"); - cmd.StdOut.Should().Contain(HelpText); + cmd.StdErr.Should().Be("Invalid solution `InvalidSolution.sln`."); + cmd.StdOut.Should().Be(HelpText); } [Fact] @@ -102,8 +102,8 @@ Options: .WithWorkingDirectory(projectDirectory) .ExecuteWithCapturedOutput("list projects"); cmd.Should().Fail(); - cmd.StdErr.Should().Contain($"Invalid solution `{solutionFullPath}`"); - cmd.StdOut.Should().Contain(HelpText); + cmd.StdErr.Should().Be($"Invalid solution `{solutionFullPath}`."); + cmd.StdOut.Should().Be(HelpText); } [Fact] @@ -121,8 +121,8 @@ Options: .WithWorkingDirectory(solutionDir) .ExecuteWithCapturedOutput("list projects"); 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.StdOut.Should().Contain(HelpText); + 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().Be(HelpText); } [Fact] @@ -139,8 +139,8 @@ Options: .WithWorkingDirectory(projectDirectory) .ExecuteWithCapturedOutput("list projects"); cmd.Should().Fail(); - cmd.StdErr.Should().Contain($"Found more than one solution file in {projectDirectory + Path.DirectorySeparatorChar}. Please specify which one to use."); - cmd.StdOut.Should().Contain(HelpText); + cmd.StdErr.Should().Be($"Found more than one solution file in {projectDirectory + Path.DirectorySeparatorChar}. Please specify which one to use."); + cmd.StdOut.Should().Be(HelpText); } [Fact] @@ -157,12 +157,17 @@ Options: .WithWorkingDirectory(projectDirectory) .ExecuteWithCapturedOutput("list projects"); cmd.Should().Pass(); - cmd.StdOut.Should().Contain("No projects found in the solution."); + cmd.StdOut.Should().Be("No projects found in the solution."); } [Fact] public void WhenProjectReferencesArePresentInTheSolutionItListsThem() { + const string OutputText = @"Project reference(s) +-------------------- +App\App.csproj +Lib\Lib.csproj"; + var projectDirectory = TestAssets .Get("TestAppWithSlnAndExistingCsprojReferences") .CreateInstance() @@ -174,9 +179,7 @@ Options: .WithWorkingDirectory(projectDirectory) .ExecuteWithCapturedOutput("list projects"); cmd.Should().Pass(); - cmd.StdOut.Should().Contain("Project reference(s)"); - cmd.StdOut.Should().Contain(@"App\App.csproj"); - cmd.StdOut.Should().Contain(@"Lib\Lib.csproj"); + cmd.StdOut.Should().Be(OutputText); } } } diff --git a/test/dotnet-remove-p2p.Tests/GivenDotnetRemoveP2P.cs b/test/dotnet-remove-p2p.Tests/GivenDotnetRemoveP2P.cs index 744e6a562..e528fe162 100644 --- a/test/dotnet-remove-p2p.Tests/GivenDotnetRemoveP2P.cs +++ b/test/dotnet-remove-p2p.Tests/GivenDotnetRemoveP2P.cs @@ -121,6 +121,17 @@ Args: 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] public void WhenTooManyArgumentsArePassedItPrintsError() { diff --git a/test/dotnet-remove-proj.Tests/GivenDotnetRemoveProj.cs b/test/dotnet-remove-proj.Tests/GivenDotnetRemoveProj.cs index 5855c4c2e..0b6cdfc3a 100644 --- a/test/dotnet-remove-proj.Tests/GivenDotnetRemoveProj.cs +++ b/test/dotnet-remove-proj.Tests/GivenDotnetRemoveProj.cs @@ -47,6 +47,17 @@ Args: 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] [InlineData("idontexist.sln")] [InlineData("ihave?invalidcharacters")]