diff --git a/Source/Testably.Abstractions.FluentAssertions/DirectoryAssertions.cs b/Source/Testably.Abstractions.FluentAssertions/DirectoryAssertions.cs index 36149a6..9577c76 100644 --- a/Source/Testably.Abstractions.FluentAssertions/DirectoryAssertions.cs +++ b/Source/Testably.Abstractions.FluentAssertions/DirectoryAssertions.cs @@ -22,10 +22,14 @@ public AndConstraint HasFileMatching( => HasFilesMatching(searchPattern, 1, because, becauseArgs); /// - /// Asserts that the current directory has at least files which match the . + /// Asserts that the current directory has at least files which match the + /// . /// public AndConstraint HasFilesMatching( - string searchPattern = "*", int minimumCount = 1, string because = "", params object[] becauseArgs) + string searchPattern = "*", + int minimumCount = 1, + string because = "", + params object[] becauseArgs) { Execute.Assertion .WithDefaultIdentifier(Identifier) @@ -39,10 +43,12 @@ public AndConstraint HasFilesMatching( "You can't assert a directory having files if you don't pass a proper name") .Then .Given(() => Subject!) - .ForCondition(directoryInfo => directoryInfo.GetFiles(searchPattern).Length > 0) + .ForCondition(directoryInfo + => directoryInfo.GetFiles(searchPattern).Length >= minimumCount) .FailWith( - $"Expected {{context}} {{1}} to contain at least {(minimumCount == 1 ? "one file" : $"{minimumCount} files")} matching {{0}}{{reason}}, but none was found.", - _ => searchPattern, directoryInfo => directoryInfo.Name); + $"Expected {{context}} {{1}} to contain at least {(minimumCount == 1 ? "one file" : $"{minimumCount} files")} matching {{0}}{{reason}}, but {(minimumCount == 1 ? "none was" : "only {2} were")} found.", + _ => searchPattern, directoryInfo => directoryInfo.Name, + directoryInfo => directoryInfo.GetFiles(searchPattern).Length); return new AndConstraint(this); } diff --git a/Source/Testably.Abstractions.FluentAssertions/Match.cs b/Source/Testably.Abstractions.FluentAssertions/Match.cs index 8a4a663..9fb397a 100644 --- a/Source/Testably.Abstractions.FluentAssertions/Match.cs +++ b/Source/Testably.Abstractions.FluentAssertions/Match.cs @@ -38,8 +38,8 @@ public static Match Wildcard(string pattern, bool ignoreCase = false) private sealed class WildcardMatch : Match { - private readonly string _originalPattern; private readonly bool _ignoreCase; + private readonly string _originalPattern; private readonly string _pattern; internal WildcardMatch(string pattern, bool ignoreCase) diff --git a/Tests/Testably.Abstractions.FluentAssertions.Tests/DirectoryAssertionsTests.cs b/Tests/Testably.Abstractions.FluentAssertions.Tests/DirectoryAssertionsTests.cs index de5ff3d..ad620c8 100644 --- a/Tests/Testably.Abstractions.FluentAssertions.Tests/DirectoryAssertionsTests.cs +++ b/Tests/Testably.Abstractions.FluentAssertions.Tests/DirectoryAssertionsTests.cs @@ -66,4 +66,37 @@ public void HasFileMatching_WithoutMatchingFile_ShouldThrow( .Be( $"Expected directory \"{directoryName}\" to contain at least one file matching \"{fileName}\" {because}, but none was found."); } + + [Theory] + [InlineAutoData(3, 5)] + [InlineAutoData(1, 2)] + public void HasFilesMatching_WithoutTooLittleFiles_ShouldThrow( + int matchingCount, + int expectedCount, + string directoryName, + string fileNamePrefix, + string because) + { + MockFileSystem fileSystem = new(); + fileSystem.Initialize() + .WithSubdirectory(directoryName); + for (int i = 0; i < matchingCount; i++) + { + fileSystem.File.WriteAllText( + fileSystem.Path.Combine(directoryName, $"{fileNamePrefix}-{i}.txt"), + "some content"); + } + + DirectoryAssertions? sut = fileSystem.Should().HaveDirectory(directoryName).Which; + + Exception? exception = Record.Exception(() => + { + sut.HasFilesMatching($"{fileNamePrefix}*", expectedCount, because); + }); + + exception.Should().NotBeNull(); + exception!.Message.Should() + .Be( + $"Expected directory \"{directoryName}\" to contain at least {expectedCount} files matching \"{fileNamePrefix}*\" {because}, but only {matchingCount} were found."); + } }