// 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 FluentAssertions.Execution; using Microsoft.DotNet.Cli.Utils; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Threading.Tasks; namespace Microsoft.DotNet.Tools.Test.Utilities { public class DirectoryInfoAssertions { private DirectoryInfo _dirInfo; public DirectoryInfoAssertions(DirectoryInfo dir) { _dirInfo = dir; } public DirectoryInfo DirectoryInfo => _dirInfo; public AndConstraint Exist() { Execute.Assertion.ForCondition(_dirInfo.Exists) .FailWith(String.Format("Expected directory {0} does not exist.", _dirInfo.FullName)); return new AndConstraint(this); } public AndConstraint HaveFile(string expectedFile, string because = "", params object[] reasonArgs) { var file = _dirInfo.EnumerateFiles(expectedFile, SearchOption.TopDirectoryOnly).SingleOrDefault(); Execute.Assertion .ForCondition(file != null) .BecauseOf(because, reasonArgs) .FailWith($"Expected File {expectedFile} cannot be found in directory {_dirInfo.FullName}."); return new AndConstraint(this); } public AndConstraint HaveTextFile( string expectedFile, string expectedContents, string because = "", params object[] reasonArgs) { this.HaveFile(expectedFile, because, reasonArgs); var file = _dirInfo.EnumerateFiles(expectedFile, SearchOption.TopDirectoryOnly).SingleOrDefault(); var contents = File.ReadAllText(file.FullName); Execute.Assertion .ForCondition(contents.Equals(expectedContents)) .BecauseOf(because, reasonArgs) .FailWith($"Expected file {expectedFile} to contain \n\n{expectedContents}\n\nbut it contains\n\n{contents}\n"); return new AndConstraint(this); } public AndConstraint NotHaveFile( string expectedFile, string because = "", params object [] reasonArgs) { var file = _dirInfo.EnumerateFiles(expectedFile, SearchOption.TopDirectoryOnly).SingleOrDefault(); Execute.Assertion .ForCondition(file == null) .BecauseOf(because, reasonArgs) .FailWith(String.Format("File {0} should not be found in directory {1}.", expectedFile, _dirInfo.FullName)); return new AndConstraint(this); } public AndConstraint HaveFiles(IEnumerable expectedFiles) { foreach (var expectedFile in expectedFiles) { HaveFile(expectedFile); } return new AndConstraint(this); } public AndConstraint HaveTextFiles( IDictionary expectedFiles, string because = "", params object[] reasonArgs) { foreach (var expectedFile in expectedFiles) { HaveTextFile(expectedFile.Key, expectedFile.Value, because, reasonArgs); } return new AndConstraint(this); } public AndConstraint HaveFilesMatching( string expectedFilesSearchPattern, SearchOption searchOption, string because = "", params object[] reasonArgs) { var matchingFileExists = _dirInfo.EnumerateFiles(expectedFilesSearchPattern, searchOption).Any(); Execute.Assertion .ForCondition(matchingFileExists == true) .BecauseOf(because, reasonArgs) .FailWith(String.Format("Expected directory {0} to contain files matching {1}, but no matching file exists.", _dirInfo.FullName, expectedFilesSearchPattern)); return new AndConstraint(this); } public AndConstraint NotHaveFiles( IEnumerable expectedFiles, string because = "", params object [] reasonArgs) { foreach (var expectedFile in expectedFiles) { NotHaveFile(expectedFile, because, reasonArgs); } return new AndConstraint(this); } public AndConstraint NotHaveFilesMatching(string expectedFilesSearchPattern, SearchOption searchOption) { var matchingFileCount = _dirInfo.EnumerateFiles(expectedFilesSearchPattern, searchOption).Count(); Execute.Assertion.ForCondition(matchingFileCount == 0) .FailWith(String.Format("Found {0} files that should not exist in directory {1}. No file matching {2} should exist.", matchingFileCount, _dirInfo.FullName, expectedFilesSearchPattern)); return new AndConstraint(this); } public AndConstraint HaveDirectory(string expectedDir) { var dir = _dirInfo.EnumerateDirectories(expectedDir, SearchOption.TopDirectoryOnly).SingleOrDefault(); Execute.Assertion.ForCondition(dir != null) .FailWith(String.Format("Expected directory {0} cannot be found inside directory {1}.", expectedDir, _dirInfo.FullName)); return new AndConstraint(new DirectoryInfoAssertions(dir)); } public AndConstraint HaveDirectories(IEnumerable expectedDirs) { foreach (var expectedDir in expectedDirs) { HaveDirectory(expectedDir); } return new AndConstraint(this); } public AndConstraint NotHaveDirectory(string unexpectedDir) { var dir = _dirInfo.EnumerateDirectories(unexpectedDir, SearchOption.TopDirectoryOnly).SingleOrDefault(); Execute.Assertion.ForCondition(dir == null) .FailWith(String.Format("Directory {0} should not be found in directory {1}.", unexpectedDir, _dirInfo.FullName)); return new AndConstraint(new DirectoryInfoAssertions(dir)); } public AndConstraint NotHaveDirectories(IEnumerable unexpectedDirs) { foreach (var unexpectedDir in unexpectedDirs) { NotHaveDirectory(unexpectedDir); } return new AndConstraint(this); } public AndConstraint OnlyHaveFiles(IEnumerable expectedFiles) { var actualFiles = _dirInfo.EnumerateFiles("*", SearchOption.TopDirectoryOnly).Select(f => f.Name); var missingFiles = Enumerable.Except(expectedFiles, actualFiles); var extraFiles = Enumerable.Except(actualFiles, expectedFiles); var nl = Environment.NewLine; Execute.Assertion.ForCondition(!missingFiles.Any()) .FailWith($"Following files cannot be found inside directory {_dirInfo.FullName} {nl} {string.Join(nl, missingFiles)}"); Execute.Assertion.ForCondition(!extraFiles.Any()) .FailWith($"Following extra files are found inside directory {_dirInfo.FullName} {nl} {string.Join(nl, extraFiles)}"); return new AndConstraint(this); } public AndConstraint BeEmpty() { Execute.Assertion.ForCondition(!_dirInfo.EnumerateFileSystemInfos().Any()) .FailWith($"The directory {_dirInfo.FullName} is not empty."); return new AndConstraint(this); } public AndConstraint NotBeEmpty() { Execute.Assertion.ForCondition(_dirInfo.EnumerateFileSystemInfos().Any()) .FailWith($"The directory {_dirInfo.FullName} is empty."); return new AndConstraint(this); } public AndConstraint NotExist(string because = "", params object[] reasonArgs) { Execute.Assertion .ForCondition(_dirInfo.Exists == false) .BecauseOf(because, reasonArgs) .FailWith($"Expected directory {_dirInfo.FullName} to not exist, but it does."); return new AndConstraint(this); } } }