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
14 changes: 11 additions & 3 deletions Source/Testably.Expectations/Expect.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.IO;
using System.Runtime.CompilerServices;
using Testably.Expectations.Core;

Expand Down Expand Up @@ -86,11 +87,11 @@ public static That<TEnum> That<TEnum>(TEnum subject,
=> new(new ExpectationBuilder<TEnum?>(subject, doNotPopulateThisValue));

/// <summary>
/// Start expectations for the current <see cref="Exception" />s <paramref name="subject" />.
/// Start expectations for the current <see cref="Exception" /> <paramref name="subject" />.
/// </summary>
public static That<Exception?> That(Exception subject,
public static That<Exception?> That(Exception? subject,
[CallerArgumentExpression("subject")] string doNotPopulateThisValue = "")
=> new(new ExpectationBuilder<Exception>(subject, doNotPopulateThisValue));
=> new(new ExpectationBuilder<Exception?>(subject, doNotPopulateThisValue));

/// <summary>
/// Start expectations for current <see cref="Guid" /> <paramref name="subject" />.
Expand All @@ -113,6 +114,13 @@ public static That<Guid> That(Guid subject,
[CallerArgumentExpression("subject")] string doNotPopulateThisValue = "")
=> new(new ExpectationBuilder<object?>(subject, doNotPopulateThisValue));

/// <summary>
/// Start expectations for the current <see cref="Stream" /> <paramref name="subject" />.
/// </summary>
public static That<Stream?> That(Stream? subject,
[CallerArgumentExpression("subject")] string doNotPopulateThisValue = "")
=> new(new ExpectationBuilder<Stream?>(subject, doNotPopulateThisValue));

/// <summary>
/// Start expectations for the current <see cref="string" />? <paramref name="subject" />.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
using System;
using System.IO;
using Testably.Expectations.Core.Constraints;

// ReSharper disable once CheckNamespace
namespace Testably.Expectations;

public static partial class ThatStreamExtensions
{
private readonly struct Constraint(
string expectation,
Func<Stream?, bool> successIf,
Func<Stream?, string> onFailure)
: IConstraint<Stream?>
{
public ConstraintResult IsMetBy(Stream? actual)
{
if (successIf(actual))
{
return new ConstraintResult.Success<Stream?>(actual, ToString());
}

return new ConstraintResult.Failure(ToString(), onFailure(actual));
}

public override string ToString()
=> expectation;
}
}
190 changes: 190 additions & 0 deletions Source/Testably.Expectations/That/Streams/ThatStreamExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
using System;
using System.IO;
using System.Runtime.CompilerServices;
using Testably.Expectations.Core;
using Testably.Expectations.Core.Helpers;
using Testably.Expectations.Results;

// ReSharper disable once CheckNamespace
namespace Testably.Expectations;

/// <summary>
/// Expectations on <see cref="Stream" /> values.
/// </summary>
public static partial class ThatStreamExtensions
{
/// <summary>
/// Verifies that the subject <see cref="Stream" /> is not readable.
/// </summary>
public static AndOrExpectationResult<Stream?, That<Stream?>> IsNotReadable(
this That<Stream?> source)
=> new(source.ExpectationBuilder.Add(new Constraint(
"is not readable",
actual => actual?.CanRead == false,
actual => actual == null ? "found <null>" : "it was"),
b => b.AppendMethod(nameof(IsNotReadable))),
source);

/// <summary>
/// Verifies that the subject <see cref="Stream" /> is not read-only.
/// </summary>
public static AndOrExpectationResult<Stream?, That<Stream?>> IsNotReadOnly(
this That<Stream?> source)
=> new(source.ExpectationBuilder.Add(new Constraint(
"is not read-only",
actual => actual != null && !(actual is { CanWrite: false, CanRead: true }),
actual => actual == null ? "found <null>" : "it was"),
b => b.AppendMethod(nameof(IsNotReadOnly))),
source);

/// <summary>
/// Verifies that the subject <see cref="Stream" /> is not seekable.
/// </summary>
public static AndOrExpectationResult<Stream?, That<Stream?>> IsNotSeekable(
this That<Stream?> source)
=> new(source.ExpectationBuilder.Add(new Constraint(
"is not seekable",
actual => actual?.CanSeek == false,
actual => actual == null ? "found <null>" : "it was"),
b => b.AppendMethod(nameof(IsNotSeekable))),
source);

/// <summary>
/// Verifies that the subject <see cref="Stream" /> is not writable.
/// </summary>
public static AndOrExpectationResult<Stream?, That<Stream?>> IsNotWritable(
this That<Stream?> source)
=> new(source.ExpectationBuilder.Add(new Constraint(
"is not writable",
actual => actual?.CanWrite == false,
actual => actual == null ? "found <null>" : "it was"),
b => b.AppendMethod(nameof(IsNotWritable))),
source);

/// <summary>
/// Verifies that the subject <see cref="Stream" /> is not write-only.
/// </summary>
public static AndOrExpectationResult<Stream?, That<Stream?>> IsNotWriteOnly(
this That<Stream?> source)
=> new(source.ExpectationBuilder.Add(new Constraint(
"is not write-only",
actual => actual != null && !(actual is { CanWrite: true, CanRead: false }),
actual => actual == null ? "found <null>" : "it was"),
b => b.AppendMethod(nameof(IsNotWriteOnly))),
source);

/// <summary>
/// Verifies that the subject <see cref="Stream" /> is readable.
/// </summary>
public static AndOrExpectationResult<Stream?, That<Stream?>> IsReadable(
this That<Stream?> source)
=> new(source.ExpectationBuilder.Add(new Constraint(
"is readable",
actual => actual?.CanRead == true,
actual => actual == null ? "found <null>" : "it was not"),
b => b.AppendMethod(nameof(IsReadable))),
source);

/// <summary>
/// Verifies that the subject <see cref="Stream" /> is read-only.
/// </summary>
public static AndOrExpectationResult<Stream?, That<Stream?>> IsReadOnly(
this That<Stream?> source)
=> new(source.ExpectationBuilder.Add(new Constraint(
"is read-only",
actual => actual is { CanWrite: false, CanRead: true },
actual => actual == null ? "found <null>" : "it was not"),
b => b.AppendMethod(nameof(IsReadOnly))),
source);

/// <summary>
/// Verifies that the subject <see cref="Stream" /> is seekable.
/// </summary>
public static AndOrExpectationResult<Stream?, That<Stream?>> IsSeekable(
this That<Stream?> source)
=> new(source.ExpectationBuilder.Add(new Constraint(
"is seekable",
actual => actual?.CanSeek == true,
actual => actual == null ? "found <null>" : "it was not"),
b => b.AppendMethod(nameof(IsSeekable))),
source);

/// <summary>
/// Verifies that the subject <see cref="Stream" /> is writable.
/// </summary>
public static AndOrExpectationResult<Stream?, That<Stream?>> IsWritable(
this That<Stream?> source)
=> new(source.ExpectationBuilder.Add(new Constraint(
"is writable",
actual => actual?.CanWrite == true,
actual => actual == null ? "found <null>" : "it was not"),
b => b.AppendMethod(nameof(IsWritable))),
source);

/// <summary>
/// Verifies that the subject <see cref="Stream" /> is write-only.
/// </summary>
public static AndOrExpectationResult<Stream?, That<Stream?>> IsWriteOnly(
this That<Stream?> source)
=> new(source.ExpectationBuilder.Add(new Constraint(
"is write-only",
actual => actual is { CanWrite: true, CanRead: false },
actual => actual == null ? "found <null>" : "it was not"),
b => b.AppendMethod(nameof(IsWriteOnly))),
source);


/// <summary>
/// Verifies that the subject <see cref="Stream" /> has the <paramref name="expected" /> length.
/// </summary>
public static AndOrExpectationResult<Stream?, That<Stream?>> HasLength(this That<Stream?> source,
long expected,
[CallerArgumentExpression("expected")] string doNotPopulateThisValue = "")
=> new(source.ExpectationBuilder.Add(new Constraint(
$"has length {expected}",
actual => actual?.Length == expected,
actual => actual == null ? "found <null>" : $"it had length {actual.Length}"),
b => b.AppendMethod(nameof(HasLength), doNotPopulateThisValue)),
source);

/// <summary>
/// Verifies that the subject <see cref="Stream" /> has the <paramref name="expected" /> position.
/// </summary>
public static AndOrExpectationResult<Stream?, That<Stream?>> HasPosition(this That<Stream?> source,
long expected,
[CallerArgumentExpression("expected")] string doNotPopulateThisValue = "")
=> new(source.ExpectationBuilder.Add(new Constraint(
$"has position {expected}",
actual => actual?.Position == expected,
actual => actual == null ? "found <null>" : $"it had position {actual.Position}"),
b => b.AppendMethod(nameof(HasPosition), doNotPopulateThisValue)),
source);


/// <summary>
/// Verifies that the subject <see cref="Stream" /> has the <paramref name="expected" /> length.
/// </summary>
public static AndOrExpectationResult<Stream?, That<Stream?>> DoesNotHaveLength(this That<Stream?> source,
long expected,
[CallerArgumentExpression("expected")] string doNotPopulateThisValue = "")
=> new(source.ExpectationBuilder.Add(new Constraint(
$"does not have length {expected}",
actual => actual != null && actual.Length != expected,
actual => actual == null ? "found <null>" : "it had"),
b => b.AppendMethod(nameof(DoesNotHaveLength), doNotPopulateThisValue)),
source);

/// <summary>
/// Verifies that the subject <see cref="Stream" /> has the <paramref name="expected" /> position.
/// </summary>
public static AndOrExpectationResult<Stream?, That<Stream?>> DoesNotHavePosition(this That<Stream?> source,
long expected,
[CallerArgumentExpression("expected")] string doNotPopulateThisValue = "")
=> new(source.ExpectationBuilder.Add(new Constraint(
$"does not have position {expected}",
actual => actual != null && actual.Position != expected,
actual => actual == null ? "found <null>" : "it had"),
b => b.AppendMethod(nameof(DoesNotHavePosition), doNotPopulateThisValue)),
source);

}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ public sealed class IsNotTests
[Theory]
[InlineData(true)]
[InlineData(false)]
public async Task WhenValuesAreDifferent_ShouldSucceed(bool subject)
public async Task WhenSubjectIsDifferent_ShouldSucceed(bool subject)
{
bool unexpected = !subject;

Expand All @@ -20,7 +20,7 @@ async Task Act()
[Theory]
[InlineData(true)]
[InlineData(false)]
public async Task WhenValuesAreTheSame_ShouldFail(bool subject)
public async Task WhenSubjectIsTheSame_ShouldFail(bool subject)
{
bool unexpected = subject;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ public sealed class IsTests
[Theory]
[InlineData(true)]
[InlineData(false)]
public async Task WhenValuesAreDifferent_ShouldFail(bool subject)
public async Task WhenSubjectIsDifferent_ShouldFail(bool subject)
{
bool expected = !subject;

Expand All @@ -26,7 +26,7 @@ at Expect.That(subject).Is(expected)
[Theory]
[InlineData(true)]
[InlineData(false)]
public async Task WhenValuesAreTheSame_ShouldSucceed(bool subject)
public async Task WhenSubjectIsTheSame_ShouldSucceed(bool subject)
{
bool expected = subject;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ public sealed class IsNotTests
[InlineData(true)]
[InlineData(false)]
[InlineData(null)]
public async Task WhenValuesAreTheSame_ShouldFail(bool? subject)
public async Task WhenSubjectIsTheSame_ShouldFail(bool? subject)
{
bool? unexpected = subject;

Expand All @@ -31,7 +31,7 @@ at Expect.That(subject).IsNot(unexpected)
[InlineData(false, null)]
[InlineData(null, true)]
[InlineData(null, false)]
public async Task WhenValuesAreDifferent_ShouldSucceed(bool? subject, bool? unexpected)
public async Task WhenSubjectIsDifferent_ShouldSucceed(bool? subject, bool? unexpected)
{
async Task Act()
=> await Expect.That(subject).IsNot(unexpected);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ public sealed class IsTests
[InlineData(false, null)]
[InlineData(null, true)]
[InlineData(null, false)]
public async Task WhenValuesAreDifferent_ShouldFail(bool? subject, bool? expected)
public async Task WhenSubjectIsDifferent_ShouldFail(bool? subject, bool? expected)
{
async Task Act()
=> await Expect.That(subject).Is(expected);
Expand All @@ -29,7 +29,7 @@ at Expect.That(subject).Is(expected)
[InlineData(true)]
[InlineData(false)]
[InlineData(null)]
public async Task WhenValuesAreTheSame_ShouldSucceed(bool? subject)
public async Task WhenSubjectIsTheSame_ShouldSucceed(bool? subject)
{
bool? expected = subject;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ public sealed partial class ThatDateOnly
public sealed class IsNotTests
{
[Fact]
public async Task WhenValuesAreTheSame_ShouldFail()
public async Task WhenSubjectIsTheSame_ShouldFail()
{
DateOnly subject = CurrentTime();
DateOnly unexpected = subject;
Expand All @@ -24,7 +24,7 @@ at Expect.That(subject).IsNot(unexpected)
}

[Fact]
public async Task WhenValuesAreDifferent_ShouldSucceed()
public async Task WhenSubjectIsDifferent_ShouldSucceed()
{
DateOnly subject = CurrentTime();
DateOnly unexpected = LaterTime();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ public sealed partial class ThatDateOnly
public sealed class IsTests
{
[Fact]
public async Task WhenValuesAreDifferent_ShouldFail()
public async Task WhenSubjectIsDifferent_ShouldFail()
{
DateOnly subject = CurrentTime();
DateOnly expected = LaterTime();
Expand All @@ -24,7 +24,7 @@ at Expect.That(subject).Is(expected)
}

[Fact]
public async Task WhenValuesAreTheSame_ShouldSucceed()
public async Task WhenSubjectIsTheSame_ShouldSucceed()
{
DateOnly subject = CurrentTime();
DateOnly expected = subject;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ public sealed partial class ThatDateTime
public sealed class IsAfterTests
{
[Fact]
public async Task WhenValueIsEarlier_ShouldFail()
public async Task WhenSubjectIsEarlier_ShouldFail()
{
DateTime expected = CurrentTime();
DateTime subject = EarlierTime();
Expand All @@ -23,7 +23,7 @@ at Expect.That(subject).IsAfter(expected)
}

[Fact]
public async Task WhenValueIsSame_ShouldFail()
public async Task WhenSubjectIsSame_ShouldFail()
{
DateTime expected = CurrentTime();
DateTime subject = expected;
Expand All @@ -41,7 +41,7 @@ at Expect.That(subject).IsAfter(expected)
}

[Fact]
public async Task WhenValuesIsLater_ShouldSucceed()
public async Task WhenSubjectsIsLater_ShouldSucceed()
{
DateTime expected = CurrentTime();
DateTime subject = LaterTime();
Expand Down
Loading
Loading