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
51 changes: 48 additions & 3 deletions Source/Testably.Abstractions.FluentAssertions/FileAssertions.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Linq;
using System.IO;
using System.Linq;
using System.Text;

namespace Testably.Abstractions.FluentAssertions;
Expand All @@ -17,6 +18,50 @@ internal FileAssertions(IFileInfo? instance)
{
}

/// <summary>
/// Asserts that the current file does not have the given <paramref name="attribute" />.
/// </summary>
public AndConstraint<FileAssertions> DoesNotHaveAttribute(
FileAttributes attribute, string because = "", params object[] becauseArgs)
{
Execute.Assertion
.WithDefaultIdentifier(Identifier)
.BecauseOf(because, becauseArgs)
.ForCondition(Subject != null)
.FailWith(
$"You can't assert that the file does not have attribute {attribute} if it is null")
.Then
.Given(() => Subject!)
.ForCondition(fileInfo => !fileInfo.Attributes.HasFlag(attribute))
.FailWith(
$"Expected {{context}} {{0}} not to have attribute {attribute}{{reason}}, but it did.",
fileInfo => fileInfo.Name);

return new AndConstraint<FileAssertions>(this);
}

/// <summary>
/// Asserts that the current file has the given <paramref name="attribute" />.
/// </summary>
public AndConstraint<FileAssertions> HasAttribute(
FileAttributes attribute, string because = "", params object[] becauseArgs)
{
Execute.Assertion
.WithDefaultIdentifier(Identifier)
.BecauseOf(because, becauseArgs)
.ForCondition(Subject != null)
.FailWith(
$"You can't assert that the file has attribute {attribute} if it is null")
.Then
.Given(() => Subject!)
.ForCondition(fileInfo => fileInfo.Attributes.HasFlag(attribute))
.FailWith(
$"Expected {{context}} {{0}} to have attribute {attribute}{{reason}}, but it did not.",
fileInfo => fileInfo.Name);

return new AndConstraint<FileAssertions>(this);
}

/// <summary>
/// Asserts that the binary content of the current file is equivalent to the given <paramref name="bytes" />.
/// </summary>
Expand Down Expand Up @@ -99,7 +144,7 @@ public AndConstraint<FileAssertions> IsNotReadOnly(
.BecauseOf(because, becauseArgs)
.ForCondition(Subject != null)
.FailWith(
"You can't assert that the file is not read-only if the FileInfo is null")
"You can't assert that the file is not read-only if it is null")
.Then
.Given(() => Subject!)
.ForCondition(fileInfo => !fileInfo.IsReadOnly)
Expand All @@ -121,7 +166,7 @@ public AndConstraint<FileAssertions> IsReadOnly(
.BecauseOf(because, becauseArgs)
.ForCondition(Subject != null)
.FailWith(
"You can't assert that the file is read-only if the FileInfo is null")
"You can't assert that the file is read-only if it is null")
.Then
.Given(() => Subject!)
.ForCondition(fileInfo => fileInfo.IsReadOnly)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using System.IO;
using System.Text;

namespace Testably.Abstractions.FluentAssertions;
Expand Down Expand Up @@ -26,6 +27,16 @@ public AndConstraint<FileInfoAssertions> BeReadOnly(
return new AndConstraint<FileInfoAssertions>(this);
}

/// <summary>
/// Asserts that the current file has the given <paramref name="attribute" />.
/// </summary>
public AndConstraint<FileInfoAssertions> HaveAttribute(
FileAttributes attribute, string because = "", params object[] becauseArgs)
{
new FileAssertions(Subject).HasAttribute(attribute, because, becauseArgs);
return new AndConstraint<FileInfoAssertions>(this);
}

/// <summary>
/// Asserts that the binary content of the current file is equivalent to the given <paramref name="bytes" />.
/// </summary>
Expand Down Expand Up @@ -66,4 +77,14 @@ public AndConstraint<FileInfoAssertions> NotBeReadOnly(
new FileAssertions(Subject).IsNotReadOnly(because, becauseArgs);
return new AndConstraint<FileInfoAssertions>(this);
}

/// <summary>
/// Asserts that the current file does not have the given <paramref name="attribute" />.
/// </summary>
public AndConstraint<FileInfoAssertions> NotHaveAttribute(
FileAttributes attribute, string because = "", params object[] becauseArgs)
{
new FileAssertions(Subject).DoesNotHaveAttribute(attribute, because, becauseArgs);
return new AndConstraint<FileInfoAssertions>(this);
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using AutoFixture.Xunit2;
using FluentAssertions;
using System;
using System.IO;
using System.Linq;
using System.Text;
using Testably.Abstractions.Testing;
Expand All @@ -11,6 +12,79 @@ namespace Testably.Abstractions.FluentAssertions.Tests;

public class FileAssertionsTests
{
[Theory]
[AutoData]
public void DoesNotHaveAttribute_WithAttribute_ShouldThrow(
FileDescription fileDescription,
string because)
{
fileDescription.IsReadOnly = true;
MockFileSystem fileSystem = new();
fileSystem.Initialize()
.With(fileDescription);
FileAssertions? sut = fileSystem.Should().HaveFile(fileDescription.Name).Which;

Exception? exception = Record.Exception(() =>
{
sut.DoesNotHaveAttribute(FileAttributes.ReadOnly, because);
});

exception.Should().NotBeNull();
exception!.Message.Should()
.Be(
$"Expected file \"{fileDescription.Name}\" not to have attribute {FileAttributes.ReadOnly} {because}, but it did.");
}

[Theory]
[AutoData]
public void DoesNotHaveAttribute_WithoutAttribute_ShouldNotThrow(
FileDescription fileDescription)
{
fileDescription.IsReadOnly = false;
MockFileSystem fileSystem = new();
fileSystem.Initialize()
.With(fileDescription);
FileAssertions? sut = fileSystem.Should().HaveFile(fileDescription.Name).Which;

sut.DoesNotHaveAttribute(FileAttributes.ReadOnly);
}

[Theory]
[AutoData]
public void HasAttribute_WithAttribute_ShouldNotThrow(FileDescription fileDescription)
{
fileDescription.IsReadOnly = true;
MockFileSystem fileSystem = new();
fileSystem.Initialize()
.With(fileDescription);
FileAssertions? sut = fileSystem.Should().HaveFile(fileDescription.Name).Which;

sut.HasAttribute(FileAttributes.ReadOnly);
}

[Theory]
[AutoData]
public void HasAttribute_WithoutAttribute_ShouldThrow(
FileDescription fileDescription,
string because)
{
fileDescription.IsReadOnly = false;
MockFileSystem fileSystem = new();
fileSystem.Initialize()
.With(fileDescription);
FileAssertions? sut = fileSystem.Should().HaveFile(fileDescription.Name).Which;

Exception? exception = Record.Exception(() =>
{
sut.HasAttribute(FileAttributes.ReadOnly, because);
});

exception.Should().NotBeNull();
exception!.Message.Should()
.Be(
$"Expected file \"{fileDescription.Name}\" to have attribute {FileAttributes.ReadOnly} {because}, but it did not.");
}

[Theory]
[AutoData]
public void HasContent_Bytes_FullContent_ShouldNotThrow(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using AutoFixture.Xunit2;
using FluentAssertions;
using System;
using System.IO;
using System.IO.Abstractions;
using System.Linq;
using System.Text;
Expand Down Expand Up @@ -64,6 +65,58 @@ public void BeReadOnly_WithWritableFile_ShouldThrow(
$"Expected file \"{fileDescription.Name}\" to be read-only {because}, but it was not.");
}

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

Exception? exception = Record.Exception(() =>
{
sut.Should().HaveAttribute(FileAttributes.ReadOnly, because);
});

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

[Theory]
[AutoData]
public void HaveAttribute_WithAttribute_ShouldNotThrow(FileDescription fileDescription)
{
fileDescription.IsReadOnly = true;
MockFileSystem fileSystem = new();
fileSystem.Initialize()
.With(fileDescription);
IFileInfo sut = fileSystem.FileInfo.New(fileDescription.Name);

sut.Should().HaveAttribute(FileAttributes.ReadOnly);
}

[Theory]
[AutoData]
public void HaveAttribute_WithoutAttribute_ShouldThrow(
FileDescription fileDescription,
string because)
{
fileDescription.IsReadOnly = false;
MockFileSystem fileSystem = new();
fileSystem.Initialize()
.With(fileDescription);
IFileInfo sut = fileSystem.FileInfo.New(fileDescription.Name);

Exception? exception = Record.Exception(() =>
{
sut.Should().HaveAttribute(FileAttributes.ReadOnly, because);
});

exception.Should().NotBeNull();
exception!.Message.Should()
.Be(
$"Expected file \"{fileDescription.Name}\" to have attribute {FileAttributes.ReadOnly} {because}, but it did not.");
}

[Theory]
[AutoData]
public void HaveContent_Bytes_FullContent_ShouldNotThrow(
Expand Down Expand Up @@ -320,4 +373,56 @@ public void NotBeReadOnly_WithWritableFile_ShouldNotThrow(FileDescription fileDe

sut.Should().NotBeReadOnly();
}

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

Exception? exception = Record.Exception(() =>
{
sut.Should().NotHaveAttribute(FileAttributes.ReadOnly, because);
});

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

[Theory]
[AutoData]
public void NotHaveAttribute_WithAttribute_ShouldThrow(
FileDescription fileDescription,
string because)
{
fileDescription.IsReadOnly = true;
MockFileSystem fileSystem = new();
fileSystem.Initialize()
.With(fileDescription);
IFileInfo sut = fileSystem.FileInfo.New(fileDescription.Name);

Exception? exception = Record.Exception(() =>
{
sut.Should().NotHaveAttribute(FileAttributes.ReadOnly, because);
});

exception.Should().NotBeNull();
exception!.Message.Should()
.Be(
$"Expected file \"{fileDescription.Name}\" not to have attribute {FileAttributes.ReadOnly} {because}, but it did.");
}

[Theory]
[AutoData]
public void NotHaveAttribute_WithoutAttribute_ShouldNotThrow(FileDescription fileDescription)
{
fileDescription.IsReadOnly = false;
MockFileSystem fileSystem = new();
fileSystem.Initialize()
.With(fileDescription);
IFileInfo sut = fileSystem.FileInfo.New(fileDescription.Name);

sut.Should().NotHaveAttribute(FileAttributes.ReadOnly);
}
}