< Summary

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

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%11100%
get_Errors()100%11100%

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
 22    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>
 28    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>
 33    public string[] FailedConditions => [.. _failedConditions];
 34
 35    /// <summary>
 36    /// Indicates whether all evaluated conditions have succeeded (i.e. there are no failures).
 37    /// </summary>
 38    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    {
 47        _expression = expression;
 48
 49        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    {
 59        _expression = !expression;
 60
 61        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    {
 76        ArgumentNullException.ThrowIfNull(error);
 77
 78        if (_expression is null)
 79        {
 80            throw new InvalidOperationException(
 81                $"{nameof(FailsWith)} must follow a call to {nameof(True)} or {nameof(False)}.");
 82        }
 83
 84        if (!_expression.Value)
 85        {
 86            _failedConditions.Add(error);
 87        }
 88
 89        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    {
 98        if (IsSatisfied)
 99        {
 100            return;
 101        }
 102
 103        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    {
 120        var output = new ProcessOutput();
 121
 122        output.AddErrors(_failedConditions.Select(error =>
 123            string.IsNullOrWhiteSpace(error) ? BlankFailureMessage : error));
 124
 125        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)
 1134    : 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>
 2139    public string[] Errors { get; } = errors;
 140}