2016-12-14 23:53:11 +00:00
// 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 FluentAssertions ;
using Microsoft.Build.Construction ;
using Microsoft.DotNet.Cli.Sln.Internal ;
using Microsoft.DotNet.Tools.Test.Utilities ;
using System ;
using System.IO ;
using System.Linq ;
using Xunit ;
namespace Microsoft.DotNet.Cli.Add.Proj.Tests
{
public class GivenDotnetAddProj : TestBase
{
2016-12-16 09:04:09 +00:00
private string HelpText = @ ".NET Add Project to Solution Command
Usage : dotnet add < PROJECT_OR_SOLUTION > project [ options ] [ args ]
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
2016-12-17 07:59:58 +00:00
Additional Arguments :
Projects to add to solution
2016-12-16 09:04:09 +00:00
";
2016-12-14 23:53:11 +00:00
[Theory]
[InlineData("--help")]
[InlineData("-h")]
public void WhenHelpOptionIsPassedItPrintsUsage ( string helpArg )
{
var cmd = new DotnetCommand ( )
. ExecuteWithCapturedOutput ( $"add project {helpArg}" ) ;
cmd . Should ( ) . Pass ( ) ;
2016-12-28 22:50:34 +00:00
cmd . StdOut . Should ( ) . BeVisuallyEquivalentTo ( HelpText ) ;
2016-12-16 09:04:09 +00:00
}
2016-12-16 18:23:26 +00:00
[Theory]
[InlineData("")]
[InlineData("unknownCommandName")]
public void WhenNoCommandIsPassedItPrintsError ( string commandName )
2016-12-16 09:04:09 +00:00
{
var cmd = new DotnetCommand ( )
2016-12-16 18:23:26 +00:00
. ExecuteWithCapturedOutput ( $"add {commandName}" ) ;
2016-12-16 09:04:09 +00:00
cmd . Should ( ) . Fail ( ) ;
2016-12-16 18:23:26 +00:00
cmd . StdErr . Should ( ) . Be ( "Required command was not provided." ) ;
2016-12-14 23:53:11 +00:00
}
2016-12-16 16:41:47 +00:00
[Fact]
public void WhenTooManyArgumentsArePassedItPrintsError ( )
{
var cmd = new DotnetCommand ( )
. ExecuteWithCapturedOutput ( "add one.sln two.sln three.sln project" ) ;
cmd . Should ( ) . Fail ( ) ;
2016-12-16 18:23:26 +00:00
cmd . StdErr . Should ( ) . Be ( "Unrecognized command or argument 'two.sln'" ) ;
cmd . StdOut . Should ( ) . Be ( "Specify --help for a list of available options and commands." ) ;
2016-12-16 16:41:47 +00:00
}
2016-12-14 23:53:11 +00:00
[Theory]
[InlineData("idontexist.sln")]
[InlineData("ihave?invalidcharacters")]
[InlineData("ihaveinv@lidcharacters")]
[InlineData("ihaveinvalid/characters")]
[InlineData("ihaveinvalidchar\\acters")]
public void WhenNonExistingSolutionIsPassedItPrintsErrorAndUsage ( string solutionName )
{
var cmd = new DotnetCommand ( )
. ExecuteWithCapturedOutput ( $"add {solutionName} project p.csproj" ) ;
cmd . Should ( ) . Fail ( ) ;
2016-12-16 09:04:09 +00:00
cmd . StdErr . Should ( ) . Be ( $"Could not find solution or directory `{solutionName}`." ) ;
2016-12-28 22:50:34 +00:00
cmd . StdOut . Should ( ) . BeVisuallyEquivalentTo ( HelpText ) ;
2016-12-14 23:53:11 +00:00
}
[Fact]
public void WhenInvalidSolutionIsPassedItPrintsErrorAndUsage ( )
{
2016-12-16 09:04:09 +00:00
var projectDirectory = TestAssets
. Get ( "InvalidSolution" )
. CreateInstance ( )
. WithSourceFiles ( )
. Root
. FullName ;
2016-12-14 23:53:11 +00:00
var projectToAdd = Path . Combine ( "Lib" , "Lib.csproj" ) ;
var cmd = new DotnetCommand ( )
. WithWorkingDirectory ( projectDirectory )
. ExecuteWithCapturedOutput ( $"add InvalidSolution.sln project {projectToAdd}" ) ;
cmd . Should ( ) . Fail ( ) ;
2016-12-29 19:21:55 +00:00
cmd . StdErr . Should ( ) . Be ( "Invalid solution `InvalidSolution.sln`. Invalid format in line 1: File header is missing" ) ;
2016-12-28 22:50:34 +00:00
cmd . StdOut . Should ( ) . BeVisuallyEquivalentTo ( HelpText ) ;
2016-12-14 23:53:11 +00:00
}
[Fact]
public void WhenInvalidSolutionIsFoundItPrintsErrorAndUsage ( )
{
2016-12-16 09:04:09 +00:00
var projectDirectory = TestAssets
. Get ( "InvalidSolution" )
. CreateInstance ( )
. WithSourceFiles ( )
. Root
. FullName ;
var solutionPath = Path . Combine ( projectDirectory , "InvalidSolution.sln" ) ;
2016-12-14 23:53:11 +00:00
var projectToAdd = Path . Combine ( "Lib" , "Lib.csproj" ) ;
var cmd = new DotnetCommand ( )
. WithWorkingDirectory ( projectDirectory )
. ExecuteWithCapturedOutput ( $"add project {projectToAdd}" ) ;
cmd . Should ( ) . Fail ( ) ;
2016-12-29 19:21:55 +00:00
cmd . StdErr . Should ( ) . Be ( $"Invalid solution `{solutionPath}`. Invalid format in line 1: File header is missing" ) ;
2016-12-28 22:50:34 +00:00
cmd . StdOut . Should ( ) . BeVisuallyEquivalentTo ( HelpText ) ;
2016-12-14 23:53:11 +00:00
}
[Fact]
public void WhenNoProjectIsPassedItPrintsErrorAndUsage ( )
{
2016-12-16 09:04:09 +00:00
var projectDirectory = TestAssets
. Get ( "TestAppWithSlnAndCsprojFiles" )
. CreateInstance ( )
. WithSourceFiles ( )
. Root
. FullName ;
2016-12-14 23:53:11 +00:00
var cmd = new DotnetCommand ( )
. WithWorkingDirectory ( projectDirectory )
. ExecuteWithCapturedOutput ( @"add App.sln project" ) ;
cmd . Should ( ) . Fail ( ) ;
2016-12-16 09:04:09 +00:00
cmd . StdErr . Should ( ) . Be ( "You must specify at least one project to add." ) ;
2016-12-28 22:50:34 +00:00
cmd . StdOut . Should ( ) . BeVisuallyEquivalentTo ( HelpText ) ;
2016-12-14 23:53:11 +00:00
}
[Fact]
public void WhenNoSolutionExistsInTheDirectoryItPrintsErrorAndUsage ( )
{
2016-12-16 09:04:09 +00:00
var projectDirectory = TestAssets
. Get ( "TestAppWithSlnAndCsprojFiles" )
. CreateInstance ( )
. WithSourceFiles ( )
. Root
. FullName ;
var solutionPath = Path . Combine ( projectDirectory , "App" ) ;
2016-12-14 23:53:11 +00:00
var cmd = new DotnetCommand ( )
2016-12-16 09:04:09 +00:00
. WithWorkingDirectory ( solutionPath )
2016-12-14 23:53:11 +00:00
. ExecuteWithCapturedOutput ( @"add project App.csproj" ) ;
cmd . Should ( ) . Fail ( ) ;
2016-12-16 09:04:09 +00:00
cmd . StdErr . Should ( ) . Be ( $"Specified solution file {solutionPath + Path.DirectorySeparatorChar} does not exist, or there is no solution file in the directory." ) ;
2016-12-28 22:50:34 +00:00
cmd . StdOut . Should ( ) . BeVisuallyEquivalentTo ( HelpText ) ;
2016-12-14 23:53:11 +00:00
}
[Fact]
public void WhenMoreThanOneSolutionExistsInTheDirectoryItPrintsErrorAndUsage ( )
{
2016-12-16 09:04:09 +00:00
var projectDirectory = TestAssets
. Get ( "TestAppWithMultipleSlnFiles" )
. CreateInstance ( )
. WithSourceFiles ( )
. Root
. FullName ;
2016-12-14 23:53:11 +00:00
var projectToAdd = Path . Combine ( "Lib" , "Lib.csproj" ) ;
var cmd = new DotnetCommand ( )
. WithWorkingDirectory ( projectDirectory )
. ExecuteWithCapturedOutput ( $"add project {projectToAdd}" ) ;
cmd . Should ( ) . Fail ( ) ;
2016-12-16 09:04:09 +00:00
cmd . StdErr . Should ( ) . Be ( $"Found more than one solution file in {projectDirectory + Path.DirectorySeparatorChar}. Please specify which one to use." ) ;
2016-12-28 22:50:34 +00:00
cmd . StdOut . Should ( ) . BeVisuallyEquivalentTo ( HelpText ) ;
2016-12-14 23:53:11 +00:00
}
[Theory]
[InlineData("TestAppWithSlnAndCsprojFiles", "")]
[InlineData("TestAppWithSlnAndCsprojProjectGuidFiles", "{84A45D44-B677-492D-A6DA-B3A71135AB8E}")]
public void WhenValidProjectIsPassedItGetsNormalizedAndAddedAndSlnBuilds (
string testAsset ,
string projectGuid )
{
2016-12-16 09:04:09 +00:00
var projectDirectory = TestAssets
. Get ( testAsset )
. CreateInstance ( )
. WithSourceFiles ( )
. Root
. FullName ;
2016-12-14 23:53:11 +00:00
var projectToAdd = "Lib/Lib.csproj" ;
2016-12-20 23:04:01 +00:00
var projectPath = Path . Combine ( "Lib" , "Lib.csproj" ) ;
2016-12-14 23:53:11 +00:00
var cmd = new DotnetCommand ( )
. WithWorkingDirectory ( projectDirectory )
. ExecuteWithCapturedOutput ( $"add App.sln project {projectToAdd}" ) ;
cmd . Should ( ) . Pass ( ) ;
2016-12-20 23:04:01 +00:00
cmd . StdOut . Should ( ) . Be ( $"Project `{projectPath}` added to the solution." ) ;
2016-12-14 23:53:11 +00:00
cmd . StdErr . Should ( ) . BeEmpty ( ) ;
var slnFile = SlnFile . Read ( Path . Combine ( projectDirectory , "App.sln" ) ) ;
var matchingProjects = slnFile . Projects
. Where ( ( p ) = > p . Name = = "Lib" )
. ToList ( ) ;
matchingProjects . Count . Should ( ) . Be ( 1 ) ;
var slnProject = matchingProjects [ 0 ] ;
2016-12-20 23:04:01 +00:00
slnProject . FilePath . Should ( ) . Be ( projectPath ) ;
2016-12-14 23:53:11 +00:00
slnProject . TypeGuid . Should ( ) . Be ( ProjectTypeGuids . CPSProjectTypeGuid ) ;
if ( ! string . IsNullOrEmpty ( projectGuid ) )
{
slnProject . Id . Should ( ) . Be ( projectGuid ) ;
}
var restoreCmd = new DotnetCommand ( )
. WithWorkingDirectory ( projectDirectory )
. Execute ( $"restore {Path.Combine(" App ", " App . csproj ")}" ) ;
var buildCmd = new DotnetCommand ( )
. WithWorkingDirectory ( projectDirectory )
. Execute ( "build App.sln" ) ;
buildCmd . Should ( ) . Pass ( ) ;
}
[Fact]
public void WhenSolutionAlreadyContainsProjectItDoesntDuplicate ( )
{
2016-12-16 09:04:09 +00:00
var projectDirectory = TestAssets
. Get ( "TestAppWithSlnAndExistingCsprojReferences" )
. CreateInstance ( )
. WithSourceFiles ( )
. Root
. FullName ;
var solutionPath = Path . Combine ( projectDirectory , "App.sln" ) ;
2016-12-14 23:53:11 +00:00
var projectToAdd = Path . Combine ( "Lib" , "Lib.csproj" ) ;
var cmd = new DotnetCommand ( )
. WithWorkingDirectory ( projectDirectory )
. ExecuteWithCapturedOutput ( $"add App.sln project {projectToAdd}" ) ;
cmd . Should ( ) . Pass ( ) ;
2016-12-16 09:04:09 +00:00
cmd . StdOut . Should ( ) . Be ( $"Solution {solutionPath} already contains project {projectToAdd}." ) ;
2016-12-14 23:53:11 +00:00
cmd . StdErr . Should ( ) . BeEmpty ( ) ;
}
[Fact]
public void WhenPassedMultipleProjectsAndOneOfthemDoesNotExistItCancelsWholeOperation ( )
{
2016-12-16 09:04:09 +00:00
var projectDirectory = TestAssets
. Get ( "TestAppWithSlnAndCsprojFiles" )
. CreateInstance ( )
. WithSourceFiles ( )
. Root
. FullName ;
2016-12-14 23:53:11 +00:00
var slnFullPath = Path . Combine ( projectDirectory , "App.sln" ) ;
var contentBefore = File . ReadAllText ( slnFullPath ) ;
var projectToAdd = Path . Combine ( "Lib" , "Lib.csproj" ) ;
var cmd = new DotnetCommand ( )
. WithWorkingDirectory ( projectDirectory )
. ExecuteWithCapturedOutput ( $"add App.sln project {projectToAdd} idonotexist.csproj" ) ;
cmd . Should ( ) . Fail ( ) ;
2016-12-16 09:04:09 +00:00
cmd . StdErr . Should ( ) . Be ( "Project `idonotexist.csproj` does not exist." ) ;
2016-12-14 23:53:11 +00:00
File . ReadAllText ( slnFullPath )
. Should ( ) . BeEquivalentTo ( contentBefore ) ;
}
}
}