< Summary

Information
Class: ArturRios.Util.FlowControl.Condition
Assembly: ArturRios.Util
File(s): /home/ci/agent/workspace/dotnet-util-docs_main/app/src/FlowControl/Condition.cs
Line coverage
100%
Covered lines: 22
Uncovered lines: 0
Coverable lines: 22
Total lines: 140
Line coverage: 100%
Branch coverage
100%
Covered branches: 8
Total branches: 8
Branch coverage: 100%
Method coverage
100%
Covered methods: 9
Fully covered methods: 9
Total methods: 9
Method coverage: 100%
Full method coverage: 100%

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor()100%11100%
get_Create()100%11100%
get_FailedConditions()100%11100%
get_IsSatisfied()100%11100%
True(...)100%11100%
False(...)100%11100%
FailsWith(...)100%44100%
ThrowIfNotSatisfied()100%22100%
ToProcessOutput()100%22100%

File(s)

/home/ci/agent/workspace/dotnet-util-docs_main/app/src/FlowControl/Condition.cs

#LineLine coverage
 1using ArturRios.Output;
 2
 3namespace ArturRios.Util.FlowControl;
 4
 5/// <summary>
 6/// A fluent helper to evaluate multiple boolean conditions and aggregate failures.
 7/// </summary>
 8/// <remarks>
 9/// Use <see cref="True"/> or <see cref="False"/> to set the result of an expression and chain <see cref="FailsWith"/> t
 10/// After building all conditions call <see cref="ThrowIfNotSatisfied"/> or inspect <see cref="IsSatisfied"/> / <see cre
 11/// Failures are reported in the order they were recorded, and two conditions that fail with the same
 12/// message are reported twice: the count reflects conditions, not distinct wordings.
 13/// </remarks>
 14public class Condition
 15{
 16    /// <summary>
 17    /// The error <see cref="ToProcessOutput"/> reports for a condition that failed with an empty or
 18    /// whitespace message.
 19    /// </summary>
 20    public const string BlankFailureMessage = "A condition was not satisfied.";
 21
 1822    private readonly List<string> _failedConditions = [];
 23    private bool? _expression;
 24
 25    /// <summary>
 26    /// Creates a new <see cref="Condition"/> instance. Syntactic sugar for <c>new Condition()</c>.
 27    /// </summary>
 1828    public static Condition Create => new();
 29
 30    /// <summary>
 31    /// Gets an array of all failure messages collected by <see cref="FailsWith"/>, in the order they failed.
 32    /// </summary>
 833    public string[] FailedConditions => [.. _failedConditions];
 34
 35    /// <summary>
 36    /// Indicates whether all evaluated conditions have succeeded (i.e. there are no failures).
 37    /// </summary>
 838    public bool IsSatisfied => _failedConditions.Count == 0;
 39
 40    /// <summary>
 41    /// Sets the current expression result to <paramref name="expression"/>.
 42    /// </summary>
 43    /// <param name="expression">The boolean value representing the success of the condition.</param>
 44    /// <returns>The current <see cref="Condition"/> for fluent chaining.</returns>
 45    public Condition True(bool expression)
 46    {
 2047        _expression = expression;
 48
 2049        return this;
 50    }
 51
 52    /// <summary>
 53    /// Sets the current expression result to the negated value of <paramref name="expression"/>.
 54    /// </summary>
 55    /// <param name="expression">The boolean to negate.</param>
 56    /// <returns>The current <see cref="Condition"/> for fluent chaining.</returns>
 57    public Condition False(bool expression)
 58    {
 659        _expression = !expression;
 60
 661        return this;
 62    }
 63
 64    /// <summary>
 65    /// Adds an error message if the most recently set expression evaluated to <c>false</c>.
 66    /// </summary>
 67    /// <param name="error">The error message describing the failure.</param>
 68    /// <returns>The current <see cref="Condition"/> for fluent chaining.</returns>
 69    /// <exception cref="ArgumentNullException"><paramref name="error"/> is <c>null</c>.</exception>
 70    /// <exception cref="InvalidOperationException">
 71    /// No <see cref="True"/> or <see cref="False"/> call precedes this one. Recording a failure for an
 72    /// expression that was never evaluated would silently invent one.
 73    /// </exception>
 74    public Condition FailsWith(string error)
 75    {
 2876        ArgumentNullException.ThrowIfNull(error);
 77
 2778        if (_expression is null)
 79        {
 180            throw new InvalidOperationException(
 181                $"{nameof(FailsWith)} must follow a call to {nameof(True)} or {nameof(False)}.");
 82        }
 83
 2684        if (!_expression.Value)
 85        {
 1886            _failedConditions.Add(error);
 87        }
 88
 2689        return this;
 90    }
 91
 92    /// <summary>
 93    /// Throws a <see cref="ConditionFailedException"/> if any condition failed.
 94    /// </summary>
 95    /// <exception cref="ConditionFailedException">Thrown when <see cref="IsSatisfied"/> is false.</exception>
 96    public void ThrowIfNotSatisfied()
 97    {
 298        if (IsSatisfied)
 99        {
 1100            return;
 101        }
 102
 1103        throw new ConditionFailedException(FailedConditions);
 104    }
 105
 106    /// <summary>
 107    /// Converts the condition failures into a <see cref="ProcessOutput"/> instance.
 108    /// </summary>
 109    /// <returns>
 110    /// A <see cref="ProcessOutput"/> carrying one error per failed condition, in order, when the condition is
 111    /// not satisfied; its <see cref="ProcessOutput.Success"/> always agrees with <see cref="IsSatisfied"/>.
 112    /// </returns>
 113    /// <remarks>
 114    /// <see cref="ProcessOutput"/> drops empty and whitespace errors, so a condition that failed with such a
 115    /// message used to convert into a successful output. A blank message is therefore reported as
 116    /// <see cref="BlankFailureMessage"/> instead.
 117    /// </remarks>
 118    public ProcessOutput ToProcessOutput()
 119    {
 8120        var output = new ProcessOutput();
 121
 8122        output.AddErrors(_failedConditions.Select(error =>
 15123            string.IsNullOrWhiteSpace(error) ? BlankFailureMessage : error));
 124
 8125        return output;
 126    }
 127}
 128
 129/// <summary>
 130/// Exception raised when one or more conditions fail in a <see cref="Condition"/> chain.
 131/// </summary>
 132/// <param name="errors">The set of failure messages collected.</param>
 133public class ConditionFailedException(string[] errors)
 134    : Exception($"A total of {errors.Length} conditions failed: {string.Join("; ", errors)}")
 135{
 136    /// <summary>
 137    /// The failure messages that caused this exception, in the order they failed.
 138    /// </summary>
 139    public string[] Errors { get; } = errors;
 140}