diff --git a/src/FluentAssertions.CSharpFunctionalExtensions.Spec/MaybeAssertionsSpec.cs b/src/FluentAssertions.CSharpFunctionalExtensions.Spec/MaybeAssertionsSpec.cs new file mode 100644 index 0000000..96b6461 --- /dev/null +++ b/src/FluentAssertions.CSharpFunctionalExtensions.Spec/MaybeAssertionsSpec.cs @@ -0,0 +1,55 @@ +using System; +using CSharpFunctionalExtensions; +using Xunit; + +namespace FluentAssertions.CSharpFunctionalExtensions.Spec +{ + public class MaybeAssertionsSpec + { + [Fact] + public void When_maybe_is_expected_to_have_value_and_it_does_should_not_throw() + { + Maybe x = "test"; + + x.Should().HaveValue("test"); + } + + [Fact] + public void When_maybe_is_expected_to_have_value_and_it_has_wrong_value_should_throw() + { + Maybe x = "oops"; + + Action act = () => x.Should().HaveValue("test", "it is test"); + + act.Should().Throw().WithMessage($"*value \"test\" because it is test, but with value \"oops\" it*"); + } + + [Fact] + public void When_maybe_is_expected_to_have_value_and_it_does_not_should_throw() + { + Maybe x = null; + + Action act = () => x.Should().HaveValue("test", "it is not None"); + + act.Should().Throw().WithMessage($"*value \"test\" because it is not None*"); + } + + [Fact] + public void When_maybe_is_expected_to_have_no_value_and_it_has_none_should_not_throw() + { + Maybe x = null; + + x.Should().HaveNoValue(); + } + + [Fact] + public void When_maybe_is_expected_to_have_no_value_and_it_has_one_should_throw() + { + Maybe x = "test"; + + Action act = () => x.Should().HaveNoValue("it is None"); + + act.Should().Throw().WithMessage($"*maybe to have no value because it is None, but with value \"test\" it*"); + } + } +} \ No newline at end of file diff --git a/src/FluentAssertions.CSharpFunctionalExtensions/MaybeExtensions.cs b/src/FluentAssertions.CSharpFunctionalExtensions/MaybeExtensions.cs new file mode 100644 index 0000000..f50819c --- /dev/null +++ b/src/FluentAssertions.CSharpFunctionalExtensions/MaybeExtensions.cs @@ -0,0 +1,51 @@ +using CSharpFunctionalExtensions; +using FluentAssertions.Execution; +using FluentAssertions.Primitives; + +namespace FluentAssertions.CSharpFunctionalExtensions +{ + public static class MaybeExtensions + { + public static MaybeAssertions Should(this Maybe instance) => new MaybeAssertions(instance); + } + + public class MaybeAssertions : ReferenceTypeAssertions, MaybeAssertions> + { + public MaybeAssertions(Maybe instance) => Subject = instance; + + protected override string Identifier => "maybe{T}"; + + public AndConstraint> HaveValue(T value, string because = "", params object[] becauseArgs) + { + Execute.Assertion + .BecauseOf(because, becauseArgs) + .Given(() => Subject) + .ForCondition(v => v.HasValue) + .FailWith( + "Expected a value {0}{reason}", + _ => value) + .Then + .Given(s => s.Value) + .ForCondition(v => v.Equals(value)) + .FailWith( + "Expected {context:maybe} to have value {0}{reason}, but with value {1} it", + _ => value, + v => v); + + return new AndConstraint>(this); + } + + public AndConstraint> HaveNoValue(string because = "", params object[] becauseArgs) + { + Execute.Assertion + .BecauseOf(because, becauseArgs) + .Given(() => Subject) + .ForCondition(v => v.HasNoValue) + .FailWith( + "Expected {context:maybe} to have no value{reason}, but with value {0} it", + v => v.HasNoValue ? default : v.Value); + + return new AndConstraint>(this); + } + } +} \ No newline at end of file