• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

AndreuCodina / CrossValidation / 5304511320

18 Jun 2023 03:52PM UTC coverage: 83.752% (-11.7%) from 95.463%
5304511320

Pull #40

github

web-flow
Merge ef6355e4d into d173638cd
Pull Request #40: Update coverage badge in README with pull requests

331 of 394 branches covered (84.01%)

Branch coverage included in aggregate %.

1035 of 1237 relevant lines covered (83.67%)

130.23 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

96.8
/src/CrossValidation/Errors/CompleteCrossError.cs
1
using System.Net;
2
using System.Runtime.CompilerServices;
3
using System.Text.RegularExpressions;
4
using CrossValidation.Exceptions;
5

6
namespace CrossValidation.Errors;
7

8
public interface ICrossError
9
{
10
    string? FieldName { get; set; }
11
    string? FieldDisplayName { get; set; }
12
    string? Code { get; set; }
13
    string? Message { get; set; }
14
    string? Details { get; set; }
15
    HttpStatusCode? HttpStatusCode { get; set; }
16
    Dictionary<string, object>? PlaceholderValues { get; set; }
17
    public Type? CrossErrorToException { get; set; }
18
    Func<object>? GetFieldValue { get; set; }
19
    bool IsCommon { get; set; }
20
    void AddPlaceholderValues();
21
    IEnumerable<string> GetFieldNames();
22
    Exception ToException();
23
}
24

25
public record CompleteCrossError : ICrossError
26
{
27
    private const string DefaultPlaceholderValue = "";
28
    private static readonly Regex PlaceholderRegex = new("{([^{}:]+)}", RegexOptions.Compiled);
1✔
29

30
    public string? FieldName { get; set; }
765✔
31
    public string? FieldDisplayName { get; set; }
710✔
32
    public string? Code { get; set; }
527✔
33
    public string? Message { get; set; }
1,228✔
34
    public string? Details { get; set; }
561✔
35
    public HttpStatusCode? HttpStatusCode { get; set; }
557✔
36
    public Dictionary<string, object>? PlaceholderValues { get; set; }
1,861✔
37
    public Type? CrossErrorToException { get; set; }
684✔
38
    public Func<object>? GetFieldValue { get; set; }
519✔
39
    public virtual bool IsCommon { get; set; } = false;
28✔
40

41
    public CompleteCrossError(
197✔
42
        string? Code = null,
197✔
43
        string? Message = null,
197✔
44
        string? Details = null,
197✔
45
        HttpStatusCode? HttpStatusCode = null,
197✔
46
        string? FieldName = null,
197✔
47
        string? FieldDisplayName = null,
197✔
48
        Type? CrossErrorToException = null)
197✔
49
    {
50
        this.Code = Code;
197✔
51
        this.Message = Message;
197✔
52
        
53
        if (Message is null && Code is not null)
197✔
54
        {
55
            this.Message = CrossValidationOptions.GetMessageFromCode(Code);
159✔
56
        }
57
        
58
        this.Details = Details;
197✔
59
        this.HttpStatusCode = HttpStatusCode;
197✔
60
        this.FieldName = FieldName;
197✔
61
        this.FieldDisplayName = FieldDisplayName;
197✔
62
        this.CrossErrorToException = CrossErrorToException ?? typeof(CrossException);
197✔
63
    }
197✔
64
    
65
    protected void AddPlaceholderValue(
66
        object? value,
67
        [CallerArgumentExpression(nameof(value))] string name = default!)
68
    {
69
        PlaceholderValues ??= new();
550✔
70

71
        if (PlaceholderValues.ContainsKey(name))
550!
72
        {
73
            throw new InvalidOperationException("Cannot add a placeholder with the same name twice");
×
74
        }
75

76
        PlaceholderValues.Add(name, value ?? DefaultPlaceholderValue);
550✔
77
    }
550✔
78

79
    public virtual void AddPlaceholderValues()
80
    {
81
        AddCommonPlaceholderValues();
168✔
82
        AddCustomErrorPlaceholderValues();
168✔
83
        ReplacePlaceholderValues();
168✔
84
    }
168✔
85

86
    /// <summary>
87
    /// Get error constructor parameter names
88
    /// </summary>
89
    public IEnumerable<string> GetFieldNames()
90
    {
91
        return GetType()
140✔
92
            .GetConstructors()
140✔
93
            .Single()
140✔
94
            .GetParameters()
140✔
95
            .Select(x => x.Name!);
203✔
96
    }
97

98
    public Exception ToException()
99
    {
100
        AddPlaceholderValues();
142✔
101
        var canUseCrossValidationCustomizations = CrossErrorToException!
142✔
102
            .GetInterface(nameof(ICrossErrorToException)) is not null;
142✔
103

104
        if (!canUseCrossValidationCustomizations)
142✔
105
        {
106
            throw (Exception)Activator.CreateInstance(CrossErrorToException, CreateExceptionMessage())!;
8✔
107
        }
108
        
109
        var fromCrossErrorMethod = CrossErrorToException.GetMethod(
134✔
110
            nameof(ICrossErrorToException.FromCrossError),
134✔
111
            new[] {typeof(ICrossError)})!;
134✔
112
        var parameters = new object[] {this};
134✔
113
        var exception = fromCrossErrorMethod.Invoke(null, parameters);
134✔
114
        return (Exception)exception!;
134✔
115
    }
116

117
    private string? CreateExceptionMessage()
118
    {
119
        string? message = null;
8✔
120
            
121
        if (FieldName is not null)
8✔
122
        {
123
            message = $"{FieldName}: ";
7✔
124
        }
125

126
        if (Message is not null)
8✔
127
        {
128
            if (message is not null)
8✔
129
            {
130
                message += Message;
7✔
131
            }
132
            else
133
            {
134
                message = Message;
1✔
135
            }
136
        }
137
            
138
        return message;
8✔
139
    }
140

141
    private void AddCommonPlaceholderValues()
142
    {
143
        AddPlaceholderValue(FieldName);
168✔
144
        AddPlaceholderValue(FieldDisplayName);
168✔
145

146
        if (GetFieldValue is not null)
168✔
147
        {
148
            AddPlaceholderValue(GetFieldValue!(), "FieldValue");
155✔
149
        }
150
    }
168✔
151

152
    private void AddCustomErrorPlaceholderValues()
153
    {
154
        var arePlaceholderValuesAdded = GetType().GetMethod(nameof(AddPlaceholderValues))!.DeclaringType == GetType();
168✔
155

156
        if (!arePlaceholderValuesAdded && (IsCommon || CrossValidationOptions.LocalizeErrorInClient))
168✔
157
        {
158
            var properties = GetType().GetProperties();
138✔
159
            var customPlaceholderNames = GetFieldNames();
138✔
160

161
            foreach (var customPlaceholderName in customPlaceholderNames)
392✔
162
            {
163
                var value = properties.Where(x => x.Name == customPlaceholderName)
127✔
164
                    .Select(x => x.GetValue(this)!)
58✔
165
                    .FirstOrDefault();
58✔
166
                AddPlaceholderValue(value ?? DefaultPlaceholderValue, customPlaceholderName);
58!
167
            }
168
        }
169
    }
168✔
170

171
    private void ReplacePlaceholderValues()
172
    {
173
        if (Message is null)
168✔
174
        {
175
            return;
17✔
176
        }
177

178
        Message = PlaceholderRegex.Replace(Message, evaluator =>
151✔
179
        {
151✔
180
            var key = evaluator.Groups[1].Value;
18✔
181

151✔
182
            if (!PlaceholderValues!.TryGetValue(key, out var value))
18✔
183
            {
151✔
184
                return evaluator.Value;
×
185
            }
151✔
186

151✔
187
            return value.ToString()!;
18✔
188
        });
151✔
189
    }
151✔
190
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc