Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
namespace Testably.Abstractions.FluentAssertions;
using System.Linq;

namespace Testably.Abstractions.FluentAssertions;

/// <summary>
/// Assertions on <see cref="IDirectoryInfo" />.
Expand All @@ -14,6 +16,37 @@ internal DirectoryAssertions(IDirectoryInfo? instance)
{
}

/// <summary>
/// Asserts that the directory contains exactly one file matching the given <paramref name="searchPattern"/>.
/// </summary>
public AndWhichConstraint<FileSystemAssertions, FileAssertions> HasSingleFileMatching(
string searchPattern = "*", string because = "", params object[] becauseArgs)
{
Execute.Assertion
.WithDefaultIdentifier(Identifier)
.BecauseOf(because, becauseArgs)
.ForCondition(Subject != null)
.FailWith(
"You can't assert a directory having a given file if it is null")
.Then
.ForCondition(!string.IsNullOrEmpty(searchPattern))
.FailWith(
"You can't assert a directory having a given file if you don't pass a proper name")
.Then
.Given(() => Subject!)
.ForCondition(directoryInfo
=> directoryInfo.GetFiles(searchPattern).Length == 1)
.FailWith(
"Expected {context} {1} to contain exactly one file matching {0}{reason}, but found {2}.",
_ => searchPattern,
directoryInfo => directoryInfo.Name,
directoryInfo => directoryInfo.GetFiles(searchPattern).Length);

return new AndWhichConstraint<FileSystemAssertions, FileAssertions>(
new FileSystemAssertions(Subject!.FileSystem),
new FileAssertions(Subject!.GetFiles(searchPattern).Single()));
}

/// <summary>
/// Asserts that the current directory has at least one file which matches the <paramref name="searchPattern" />.
/// </summary>
Expand Down Expand Up @@ -47,7 +80,8 @@ public AndConstraint<DirectoryAssertions> HasFilesMatching(
=> directoryInfo.GetFiles(searchPattern).Length >= minimumCount)
.FailWith(
$"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,
_ => searchPattern,
directoryInfo => directoryInfo.Name,
directoryInfo => directoryInfo.GetFiles(searchPattern).Length);

return new AndConstraint<DirectoryAssertions>(this);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,13 @@ public AndConstraint<DirectoryInfoAssertions> HaveFileMatching(
new DirectoryAssertions(Subject).HasFileMatching(searchPattern, because, becauseArgs);
return new AndConstraint<DirectoryInfoAssertions>(this);
}

/// <summary>
/// Asserts that the directory contains exactly one file matching the given <paramref name="searchPattern" />.
/// </summary>
public AndWhichConstraint<FileSystemAssertions, FileAssertions> HaveSingleFile(
string searchPattern = "*", string because = "", params object[] becauseArgs)
{
return new DirectoryAssertions(Subject).HasSingleFileMatching(searchPattern, because, becauseArgs);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -99,4 +99,89 @@ public void HasFilesMatching_WithoutTooLittleFiles_ShouldThrow(
.Be(
$"Expected directory \"{directoryName}\" to contain at least {expectedCount} files matching \"{fileNamePrefix}*\" {because}, but only {matchingCount} were found.");
}

[Theory]
[InlineAutoData(null)]
[InlineAutoData("")]
public void HasSingleFileMatching_InvalidFileName_ShouldThrow(string? invalidFileName,
string because)
{
MockFileSystem fileSystem = new();
fileSystem.Initialize()
.WithSubdirectory("foo");
DirectoryAssertions? sut = fileSystem.Should().HaveDirectory("foo").Which;

Exception? exception = Record.Exception(() =>
{
sut.HasSingleFileMatching(invalidFileName!, because);
});

exception.Should().NotBeNull();
exception!.Message.Should().NotBeNullOrEmpty();
exception.Message.Should().NotContain(because);
}

[Theory]
[AutoData]
public void HasSingleFileMatching_WithMatchingFile_ShouldNotThrow(
string directoryName,
string fileName)
{
MockFileSystem fileSystem = new();
fileSystem.Initialize()
.WithSubdirectory(directoryName).Initialized(d => d
.WithFile(fileName));
DirectoryAssertions? sut = fileSystem.Should().HaveDirectory(directoryName).Which;

sut.HasSingleFileMatching(fileName);
}

[Theory]
[AutoData]
public void HasSingleFileMatching_WithMultipleMatchingFile_ShouldThrow(
string directoryName,
string fileName,
string because)
{
MockFileSystem fileSystem = new();
fileSystem.Initialize()
.WithSubdirectory(directoryName).Initialized(d => d
.WithFile($"{fileName}-1.txt")
.WithFile($"{fileName}-2.txt"));
DirectoryAssertions? sut = fileSystem.Should().HaveDirectory(directoryName).Which;

Exception? exception = Record.Exception(() =>
{
sut.HasSingleFileMatching($"{fileName}*", because);
});

exception.Should().NotBeNull();
exception!.Message.Should()
.Be(
$"Expected directory \"{directoryName}\" to contain exactly one file matching \"{fileName}*\" {because}, but found 2.");
}

[Theory]
[AutoData]
public void HasSingleFileMatching_WithoutMatchingFile_ShouldThrow(
string directoryName,
string fileName,
string because)
{
MockFileSystem fileSystem = new();
fileSystem.Initialize()
.WithSubdirectory(directoryName).Initialized(d => d
.WithFile("not-matching-file"));
DirectoryAssertions? sut = fileSystem.Should().HaveDirectory(directoryName).Which;

Exception? exception = Record.Exception(() =>
{
sut.HasSingleFileMatching(fileName, because);
});

exception.Should().NotBeNull();
exception!.Message.Should()
.Be(
$"Expected directory \"{directoryName}\" to contain exactly one file matching \"{fileName}\" {because}, but found 0.");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -84,4 +84,104 @@ public void HaveFileMatching_WithoutMatchingFile_ShouldThrow(
.Be(
$"Expected directory \"{directoryName}\" to contain at least one file matching \"{fileName}\" {because}, but none was found.");
}

[Theory]
[InlineAutoData(null)]
[InlineAutoData("")]
public void HaveSingleFile_InvalidFileName_ShouldThrow(string? invalidFileName,
string because)
{
MockFileSystem fileSystem = new();
fileSystem.Initialize()
.WithSubdirectory("foo");
IDirectoryInfo sut = fileSystem.DirectoryInfo.New("foo");

Exception? exception = Record.Exception(() =>
{
sut.Should().HaveSingleFile(invalidFileName!, because);
});

exception.Should().NotBeNull();
exception!.Message.Should().NotBeNullOrEmpty();
exception.Message.Should().NotContain(because);
}

[Theory]
[AutoData]
public void HaveSingleFile_Null_ShouldThrow(string because)
{
IDirectoryInfo? sut = null;

Exception? exception = Record.Exception(() =>
{
sut.Should().HaveSingleFile(because: because);
});

exception.Should().NotBeNull();
exception!.Message.Should().Contain("null");
exception.Message.Should().NotContain(because);
}

[Theory]
[AutoData]
public void HaveSingleFile_WithMatchingFile_ShouldNotThrow(
string directoryName,
string fileName)
{
MockFileSystem fileSystem = new();
fileSystem.Initialize()
.WithSubdirectory(directoryName).Initialized(d => d
.WithFile(fileName));
IDirectoryInfo sut = fileSystem.DirectoryInfo.New(directoryName);

sut.Should().HaveSingleFile(fileName);
}

[Theory]
[AutoData]
public void HaveSingleFile_WithMultipleMatchingFile_ShouldThrow(
string directoryName,
string because)
{
MockFileSystem fileSystem = new();
fileSystem.Initialize()
.WithSubdirectory(directoryName).Initialized(d => d
.WithFile("file1.txt")
.WithFile("file2.txt"));
IDirectoryInfo sut = fileSystem.DirectoryInfo.New(directoryName);

Exception? exception = Record.Exception(() =>
{
sut.Should().HaveSingleFile("file*.txt", because);
});

exception.Should().NotBeNull();
exception!.Message.Should()
.Be(
$"Expected directory \"{directoryName}\" to contain exactly one file matching \"file*.txt\" {because}, but found 2.");
}

[Theory]
[AutoData]
public void HaveSingleFile_WithoutMatchingFile_ShouldThrow(
string directoryName,
string fileName,
string because)
{
MockFileSystem fileSystem = new();
fileSystem.Initialize()
.WithSubdirectory(directoryName).Initialized(d => d
.WithFile("not-matching-file"));
IDirectoryInfo sut = fileSystem.DirectoryInfo.New(directoryName);

Exception? exception = Record.Exception(() =>
{
sut.Should().HaveSingleFile(fileName, because);
});

exception.Should().NotBeNull();
exception!.Message.Should()
.Be(
$"Expected directory \"{directoryName}\" to contain exactly one file matching \"{fileName}\" {because}, but found 0.");
}
}