diff --git a/src/Serilog.Enrichers.Sensitive/EmailAddressMaskingOperator.cs b/src/Serilog.Enrichers.Sensitive/EmailAddressMaskingOperator.cs
index a60e59f..3269712 100644
--- a/src/Serilog.Enrichers.Sensitive/EmailAddressMaskingOperator.cs
+++ b/src/Serilog.Enrichers.Sensitive/EmailAddressMaskingOperator.cs
@@ -11,7 +11,7 @@ public EmailAddressMaskingOperator() : base(EmailPattern, RegexOptions.IgnoreCas
{
}
- protected override string PreprocessInput(string input)
+ protected override string PreprocessInput(string input, string? propertyName = null)
{
if (input.Contains("%40"))
{
@@ -20,7 +20,7 @@ protected override string PreprocessInput(string input)
return input;
}
- protected override bool ShouldMaskInput(string input)
+ protected override bool ShouldMaskInput(string input, string? propertyName = null)
{
return input.Contains("@");
}
diff --git a/src/Serilog.Enrichers.Sensitive/IMaskingOperator.cs b/src/Serilog.Enrichers.Sensitive/IMaskingOperator.cs
index 51c051b..94e5bf1 100644
--- a/src/Serilog.Enrichers.Sensitive/IMaskingOperator.cs
+++ b/src/Serilog.Enrichers.Sensitive/IMaskingOperator.cs
@@ -3,6 +3,7 @@
public interface IMaskingOperator
{
- MaskingResult Mask(string input, string mask);
+ MaskingResult MaskProperty(string propertyName, string input, string mask);
+ MaskingResult MaskMessage(string input, string mask);
}
}
\ No newline at end of file
diff --git a/src/Serilog.Enrichers.Sensitive/RegexMaskingOperator.cs b/src/Serilog.Enrichers.Sensitive/RegexMaskingOperator.cs
index ca55738..403a5a0 100644
--- a/src/Serilog.Enrichers.Sensitive/RegexMaskingOperator.cs
+++ b/src/Serilog.Enrichers.Sensitive/RegexMaskingOperator.cs
@@ -10,8 +10,8 @@ public abstract class RegexMaskingOperator : IMaskingOperator
{
private readonly Regex _regex;
- protected RegexMaskingOperator(string regexString)
- : this(regexString, RegexOptions.Compiled)
+ protected RegexMaskingOperator(string regexString)
+ : this(regexString, RegexOptions.Compiled)
{
}
@@ -25,7 +25,36 @@ protected RegexMaskingOperator(string regexString, RegexOptions options)
}
}
- public MaskingResult Mask(string input, string mask)
+ public MaskingResult MaskProperty(string propertyName, string input, string mask)
+ {
+ var preprocessedInput = PreprocessInput(input, propertyName);
+
+ if (!ShouldMaskInput(preprocessedInput, propertyName))
+ {
+ return MaskingResult.NoMatch;
+ }
+
+ var maskedResult = _regex.Replace(preprocessedInput, match =>
+ {
+ if (ShouldMaskMatch(match))
+ {
+ return match.Result(PreprocessMask(PreprocessMask(mask), match));
+ }
+
+ return match.Value;
+ });
+
+ var result = new MaskingResult
+ {
+ Result = maskedResult,
+ Match = maskedResult != input
+ };
+
+ return result;
+ }
+
+ public MaskingResult MaskMessage(string input, string mask)
+
{
var preprocessedInput = PreprocessInput(input);
@@ -34,16 +63,16 @@ public MaskingResult Mask(string input, string mask)
return MaskingResult.NoMatch;
}
- var maskedResult = _regex.Replace(preprocessedInput, match =>
- {
- if (ShouldMaskMatch(match))
- {
- return match.Result(PreprocessMask(PreprocessMask(mask), match));
- }
+ var maskedResult = _regex.Replace(preprocessedInput, match =>
+ {
+ if (ShouldMaskMatch(match))
+ {
+ return match.Result(PreprocessMask(PreprocessMask(mask), match));
+ }
+
+ return match.Value;
+ });
- return match.Value;
- });
-
var result = new MaskingResult
{
Result = maskedResult,
@@ -59,37 +88,37 @@ public MaskingResult Mask(string input, string mask)
/// The message template or the value of a property on the log event
/// true when the input should be masked, otherwise false. Defaults to true
/// This method provides an extension point to short-circuit the masking operation before the regular expression matching is performed
- protected virtual bool ShouldMaskInput(string input) => true;
+ protected virtual bool ShouldMaskInput(string input, string? propertyName = null) => true;
///
/// Perform any operations on the input value before masking the input
///
- /// The message template or the value of a property on the log event
+ /// The message template or the value of a property on the log event
/// The processed input, defaults to no pre-processing and returns the input
/// Use this method if the input is encoded using URL encoding for example
- protected virtual string PreprocessInput(string input) => input;
+ protected virtual string PreprocessInput(string input, string? propertyName = null) => input;
///
/// Perform any operations on the mask before masking the matched value
///
/// The mask value as specified on the
- /// The processed mask, defaults to no pre-processing and returns the input
+ /// The processed mask, defaults to no pre-processing and returns the input
protected virtual string PreprocessMask(string mask) => mask;
- ///
- /// Perform any operations on the mask before masking the matched value
- ///
- /// The mask value as specified on the
- /// The regex match
- /// The processed mask, defaults to no pre-processing and returns the input
- protected virtual string PreprocessMask(string mask, Match match) => mask;
+ ///
+ /// Perform any operations on the mask before masking the matched value
+ ///
+ /// The mask value as specified on the
+ /// The regex match
+ /// The processed mask, defaults to no pre-processing and returns the input
+ protected virtual string PreprocessMask(string mask, Match match) => mask;
///
/// Indicate whether the operator should continue with masking the matched value from the input
///
/// The match found by the regular expression of this operator
- /// true when the match should be masked, otherwise false. Defaults to true
- /// This method provides an extension point to short-circuit the masking operation if the value matches the regular expression but does not satisfy some additional criteria
- protected virtual bool ShouldMaskMatch(Match match) => true;
- }
+ /// true when the match should be masked, otherwise false. Defaults to true
+ /// This method provides an extension point to short-circuit the masking operation if the value matches the regular expression but does not satisfy some additional criteria
+ protected virtual bool ShouldMaskMatch(Match match) => true;
+ }
}
diff --git a/src/Serilog.Enrichers.Sensitive/SensitiveDataEnricher.cs b/src/Serilog.Enrichers.Sensitive/SensitiveDataEnricher.cs
index 75176f3..bde96a9 100644
--- a/src/Serilog.Enrichers.Sensitive/SensitiveDataEnricher.cs
+++ b/src/Serilog.Enrichers.Sensitive/SensitiveDataEnricher.cs
@@ -21,7 +21,7 @@ internal class SensitiveDataEnricher : ILogEventEnricher
private readonly MaskPropertyCollection _maskProperties;
private readonly List _excludeProperties;
- public SensitiveDataEnricher(SensitiveDataEnricherOptions options)
+ public SensitiveDataEnricher(SensitiveDataEnricherOptions options)
: this(options.Apply)
{
}
@@ -30,8 +30,8 @@ public SensitiveDataEnricher(
Action? options)
{
var enricherOptions = new SensitiveDataEnricherOptions(
- MaskingMode.Globally,
- DefaultMaskValue,
+ MaskingMode.Globally,
+ DefaultMaskValue,
DefaultOperators.Select(o => o.GetType().AssemblyQualifiedName),
new List(),
new List());
@@ -55,7 +55,7 @@ public SensitiveDataEnricher(
var fields = typeof(LogEvent).GetFields(BindingFlags.Instance | BindingFlags.NonPublic);
var backingField = fields.SingleOrDefault(f => f.Name.Contains(""));
-
+
if (backingField == null)
{
throw new InvalidOperationException(
@@ -114,7 +114,7 @@ public void Enrich(LogEvent logEvent, ILogEventPropertyFactory propertyFactory)
return (false, null);
}
- if(_maskProperties.TryGetProperty(property.Key, out var options))
+ if (_maskProperties.TryGetProperty(property.Key, out var options))
{
if (options == MaskOptions.Default)
{
@@ -136,7 +136,7 @@ public void Enrich(LogEvent logEvent, ILogEventPropertyFactory propertyFactory)
{
case ScalarValue { Value: string stringValue }:
{
- var (wasMasked, maskedValue) = ReplaceSensitiveDataFromString(stringValue);
+ var (wasMasked, maskedValue) = ReplaceSensitiveDataFromString(stringValue, property.Key);
if (wasMasked)
{
@@ -150,23 +150,23 @@ public void Enrich(LogEvent logEvent, ILogEventPropertyFactory propertyFactory)
// which is why this needs special handling and isn't
// caught by the string value above.
case ScalarValue { Value: Uri uriValue }:
- {
- var (wasMasked, maskedValue) = ReplaceSensitiveDataFromString(uriValue.ToString());
-
- if (wasMasked)
{
- return (true, new ScalarValue(new Uri(maskedValue)));
- }
+ var (wasMasked, maskedValue) = ReplaceSensitiveDataFromString(uriValue.ToString(), property.Key);
- return (false, null);
- }
+ if (wasMasked)
+ {
+ return (true, new ScalarValue(new Uri(maskedValue)));
+ }
+
+ return (false, null);
+ }
case SequenceValue sequenceValue:
var resultElements = new List();
var anyElementMasked = false;
foreach (var element in sequenceValue.Elements)
{
var (wasElementMasked, elementResult) = MaskProperty(new KeyValuePair(property.Key, element));
-
+
if (wasElementMasked)
{
resultElements.Add(elementResult!);
@@ -201,27 +201,27 @@ public void Enrich(LogEvent logEvent, ILogEventPropertyFactory propertyFactory)
return (anyMasked, new StructureValue(propList));
}
case DictionaryValue dictionaryValue:
- {
- var resultDictionary = new List>();
- var anyKeyMasked = false;
-
- foreach (var pair in dictionaryValue.Elements)
{
- var (wasPairMasked, pairResult) = MaskProperty(new KeyValuePair(pair.Key.Value as string, pair.Value));
+ var resultDictionary = new List>();
+ var anyKeyMasked = false;
- if (wasPairMasked)
- {
- resultDictionary.Add(new KeyValuePair(pair.Key, pairResult));
- anyKeyMasked = true;
- }
- else
+ foreach (var pair in dictionaryValue.Elements)
{
- resultDictionary.Add(new KeyValuePair(pair.Key, pair.Value));
+ var (wasPairMasked, pairResult) = MaskProperty(new KeyValuePair(pair.Key.Value as string, pair.Value));
+
+ if (wasPairMasked)
+ {
+ resultDictionary.Add(new KeyValuePair(pair.Key, pairResult));
+ anyKeyMasked = true;
+ }
+ else
+ {
+ resultDictionary.Add(new KeyValuePair(pair.Key, pair.Value));
+ }
}
- }
- return (anyKeyMasked, new DictionaryValue(resultDictionary));
- }
+ return (anyKeyMasked, new DictionaryValue(resultDictionary));
+ }
default:
return (false, null);
}
@@ -315,20 +315,23 @@ private string MaskWithOptions(string maskValue, MaskOptions options, string inp
{
return input.Substring(0, start).PadRight(pad, '*') + input.Substring(end);
}
-
+
return input.Substring(0, start) + DefaultMaskPad + input.Substring(end);
}
return maskValue;
}
- private (bool, string) ReplaceSensitiveDataFromString(string input)
+ private (bool, string) ReplaceSensitiveDataFromString(string input, string? propertyName = null)
{
var isMasked = false;
foreach (var maskingOperator in _maskingOperators)
{
- var maskResult = maskingOperator.Mask(input, _maskValue);
+
+ var maskResult = string.IsNullOrWhiteSpace(propertyName)
+ ? maskingOperator.MaskMessage(input, _maskValue)
+ : maskingOperator.MaskProperty(propertyName!, input, _maskValue);
if (maskResult.Match)
{
diff --git a/test/Serilog.Enrichers.Sensitive.Tests.Unit/Serilog.Enrichers.Sensitive.Tests.Unit.csproj b/test/Serilog.Enrichers.Sensitive.Tests.Unit/Serilog.Enrichers.Sensitive.Tests.Unit.csproj
index 1ceb44f..815b5e5 100644
--- a/test/Serilog.Enrichers.Sensitive.Tests.Unit/Serilog.Enrichers.Sensitive.Tests.Unit.csproj
+++ b/test/Serilog.Enrichers.Sensitive.Tests.Unit/Serilog.Enrichers.Sensitive.Tests.Unit.csproj
@@ -36,10 +36,10 @@
- PreserveNewest
+ Always
- PreserveNewest
+ Always
diff --git a/test/Serilog.Enrichers.Sensitive.Tests.Unit/WhenConfiguringFromJson.cs b/test/Serilog.Enrichers.Sensitive.Tests.Unit/WhenConfiguringFromJson.cs
index 65e2327..917dea6 100644
--- a/test/Serilog.Enrichers.Sensitive.Tests.Unit/WhenConfiguringFromJson.cs
+++ b/test/Serilog.Enrichers.Sensitive.Tests.Unit/WhenConfiguringFromJson.cs
@@ -72,4 +72,14 @@ public MaskingResult Mask(string input, string mask)
Result = mask
};
}
+
+ public MaskingResult MaskProperty(string propertyName, string input, string mask)
+ {
+ return Mask(input, mask);
+ }
+
+ public MaskingResult MaskMessage(string input, string mask)
+ {
+ return Mask(input, mask);
+ }
}
\ No newline at end of file
diff --git a/test/Serilog.Enrichers.Sensitive.Tests.Unit/WhenMaskingCreditCards.cs b/test/Serilog.Enrichers.Sensitive.Tests.Unit/WhenMaskingCreditCards.cs
index 37e4201..12d4229 100644
--- a/test/Serilog.Enrichers.Sensitive.Tests.Unit/WhenMaskingCreditCards.cs
+++ b/test/Serilog.Enrichers.Sensitive.Tests.Unit/WhenMaskingCreditCards.cs
@@ -5,31 +5,46 @@ namespace Serilog.Enrichers.Sensitive.Tests.Unit
{
public class WhenMaskingCreditCards
{
- private const string Mask = "***MASK***";
+ private const string Mask = "***MASK***";
- [Theory]
+ [Theory]
[InlineData("4111 1111 1111 1111", "***MASK***", true, false)]
[InlineData("4111-1111-1111-1111", "***MASK***", true, false)]
[InlineData("4111111111111111", "***MASK***", true, true)]
- [InlineData("4111 1111 1111 1111", "4111 ***MASK***11 1111", false, false)]
- [InlineData("4111-1111-1111-1111", "4111-***MASK***11-1111", false, false)]
- [InlineData("4111111111111111", "4111***MASK***111111", false, false)]
- [InlineData("4111 1111 1111 1111", "***MASK***", false, true)]
- [InlineData("4111-1111-1111-1111", "***MASK***", false, true)]
- [InlineData("4111111111111111", "***MASK***", false, true)]
+ [InlineData("4111 1111 1111 1111", "4111 ***MASK***11 1111", false, false)]
+ [InlineData("4111-1111-1111-1111", "4111-***MASK***11-1111", false, false)]
+ [InlineData("4111111111111111", "4111***MASK***111111", false, false)]
+ [InlineData("4111 1111 1111 1111", "***MASK***", false, true)]
+ [InlineData("4111-1111-1111-1111", "***MASK***", false, true)]
+ [InlineData("4111111111111111", "***MASK***", false, true)]
public void GivenCreditCard_ValuesAreMaskedFully(string cc, string result, bool fullMask, bool useDefaultConstructor)
{
- TheMaskedResultOf(cc, fullMask, useDefaultConstructor)
+ ThePropertyMaskedResultOf("anyPropertyName", cc, fullMask, useDefaultConstructor)
.Should()
.Be(result);
+
+ TheMessageMaskedResultOf(cc, fullMask, useDefaultConstructor)
+ .Should()
+ .Be(result);
+ }
+
+ private static string ThePropertyMaskedResultOf(string propertyName, string input, bool fullMask, bool useDefaultConstructor)
+ {
+ var maskingResult = (useDefaultConstructor ? new CreditCardMaskingOperator() : new CreditCardMaskingOperator(fullMask)).MaskProperty(propertyName, input, Mask);
+
+ return maskingResult.Match
+ ? maskingResult.Result
+ : input;
}
- private static string TheMaskedResultOf(string input, bool fullMask, bool useDefaultConstructor)
+
+
+ private static string TheMessageMaskedResultOf(string input, bool fullMask, bool useDefaultConstructor)
{
- var maskingResult = (useDefaultConstructor ? new CreditCardMaskingOperator() : new CreditCardMaskingOperator(fullMask)).Mask(input, Mask);
+ var maskingResult = (useDefaultConstructor ? new CreditCardMaskingOperator() : new CreditCardMaskingOperator(fullMask)).MaskMessage(input, Mask);
- return maskingResult.Match
- ? maskingResult.Result
+ return maskingResult.Match
+ ? maskingResult.Result
: input;
}
}
diff --git a/test/Serilog.Enrichers.Sensitive.Tests.Unit/WhenMaskingEmailAddresses.cs b/test/Serilog.Enrichers.Sensitive.Tests.Unit/WhenMaskingEmailAddresses.cs
index bb01f85..1110ca9 100644
--- a/test/Serilog.Enrichers.Sensitive.Tests.Unit/WhenMaskingEmailAddresses.cs
+++ b/test/Serilog.Enrichers.Sensitive.Tests.Unit/WhenMaskingEmailAddresses.cs
@@ -8,7 +8,11 @@ public class WhenMaskingEmailAddresses
[Fact]
public void GivenSimpleMailAddress_AddressIsMasked()
{
- TheMaskedResultOf("simple@email.com")
+ ThePropertyMaskedResultOf("anyPropertyName", "simple@email.com")
+ .Should()
+ .Be(Mask);
+
+ TheMessageMaskedResultOf("simple@email.com")
.Should()
.Be(Mask);
}
@@ -16,7 +20,11 @@ public void GivenSimpleMailAddress_AddressIsMasked()
[Fact]
public void GivenSimpleMailAddressButUppercase_AddressIsMasked()
{
- TheMaskedResultOf("SIMPLE@email.com")
+ ThePropertyMaskedResultOf("anyPropertyName", "SIMPLE@email.com")
+ .Should()
+ .Be(Mask);
+
+ TheMessageMaskedResultOf("SIMPLE@email.com")
.Should()
.Be(Mask);
}
@@ -24,7 +32,11 @@ public void GivenSimpleMailAddressButUppercase_AddressIsMasked()
[Fact]
public void GivenEmailAddressWithBoxQualifier_AddressIsMasked()
{
- TheMaskedResultOf("test+spamfolder@email.com")
+ ThePropertyMaskedResultOf("anyPropertyName", "test+spamfolder@email.com")
+ .Should()
+ .Be(Mask);
+
+ TheMessageMaskedResultOf("test+spamfolder@email.com")
.Should()
.Be(Mask);
}
@@ -32,7 +44,11 @@ public void GivenEmailAddressWithBoxQualifier_AddressIsMasked()
[Fact]
public void GivenEmailAddressWithSubdomains_AddressIsMasked()
{
- TheMaskedResultOf("test@sub.sub.sub.email.com")
+ ThePropertyMaskedResultOf("anyPropertyName", "test@sub.sub.sub.email.com")
+ .Should()
+ .Be(Mask);
+
+ TheMessageMaskedResultOf("test@sub.sub.sub.email.com")
.Should()
.Be(Mask);
}
@@ -40,7 +56,11 @@ public void GivenEmailAddressWithSubdomains_AddressIsMasked()
[Fact]
public void GivenEmailAddressInUrl_EntireStringIsMasked()
{
- TheMaskedResultOf("https://foo.com/api/1/some/endpoint?email=test@sub.sub.sub.email.com")
+ ThePropertyMaskedResultOf("anyPropertyName", "https://foo.com/api/1/some/endpoint?email=test@sub.sub.sub.email.com")
+ .Should()
+ .Be("https:" + Mask); // I don't even regex
+
+ TheMessageMaskedResultOf("https://foo.com/api/1/some/endpoint?email=test@sub.sub.sub.email.com")
.Should()
.Be("https:" + Mask); // I don't even regex
}
@@ -48,7 +68,11 @@ public void GivenEmailAddressInUrl_EntireStringIsMasked()
[Fact]
public void GivenEmailAddressUrlEncoded_AddressIsMasked()
{
- TheMaskedResultOf("test%40email.com")
+ ThePropertyMaskedResultOf("anyPropertyName", "test%40email.com")
+ .Should()
+ .Be(Mask); // I don't even regex
+
+ TheMessageMaskedResultOf("test%40email.com")
.Should()
.Be(Mask); // I don't even regex
}
@@ -72,9 +96,13 @@ public void GivenEmailAddressUrlEncoded_AddressIsMasked()
[InlineData(@"firstname-lastname@example.com")]
public void GivenValidEmailAddress_AddressIsMasked(string email)
{
- TheMaskedResultOf(email)
- .Should()
- .Be(Mask);
+ ThePropertyMaskedResultOf("anyPropertyName", email)
+ .Should()
+ .Be(Mask);
+
+ TheMessageMaskedResultOf(email)
+ .Should()
+ .Be(Mask);
}
[Theory]
@@ -90,9 +118,13 @@ public void GivenValidEmailAddress_AddressIsMasked(string email)
[InlineData("(),:;<>[\\]@example.com")]
public void GivenInvalidEmailAddress_StringIsNotMasked(string toTest)
{
- TheMaskedResultOf(toTest)
- .Should()
- .Be(toTest);
+ ThePropertyMaskedResultOf("anyPropertyName", toTest)
+ .Should()
+ .Be(toTest);
+
+ TheMessageMaskedResultOf(toTest)
+ .Should()
+ .Be(toTest);
}
[Theory]
@@ -106,17 +138,30 @@ public void GivenInvalidEmailAddress_StringIsNotMasked(string toTest)
[InlineData("this\\ is\"really\"not\\allowed@example.com", "this\\ is\"really\"not\\{0}")]
public void GivenInvalidEmailAddress_StringIsStillMasked(string toTest, string expectedMask)
{
- TheMaskedResultOf(toTest)
- .Should()
- .Be(string.Format(expectedMask, Mask));
+ ThePropertyMaskedResultOf("anyPropertyName", toTest)
+ .Should()
+ .Be(string.Format(expectedMask, Mask));
+
+ TheMessageMaskedResultOf(toTest)
+ .Should()
+ .Be(string.Format(expectedMask, Mask));
+ }
+
+ private static string TheMessageMaskedResultOf(string input)
+ {
+ var maskingResult = new EmailAddressMaskingOperator().MaskMessage(input, Mask);
+
+ return maskingResult.Match
+ ? maskingResult.Result
+ : input;
}
- private static string TheMaskedResultOf(string input)
+ private static string ThePropertyMaskedResultOf(string propertyName, string input)
{
- var maskingResult = new EmailAddressMaskingOperator().Mask(input, Mask);
+ var maskingResult = new EmailAddressMaskingOperator().MaskProperty(propertyName, input, Mask);
- return maskingResult.Match
- ? maskingResult.Result
+ return maskingResult.Match
+ ? maskingResult.Result
: input;
}
}
diff --git a/test/Serilog.Enrichers.Sensitive.Tests.Unit/WhenMaskingLogEventWithNonStringScalarValue.cs b/test/Serilog.Enrichers.Sensitive.Tests.Unit/WhenMaskingLogEventWithNonStringScalarValue.cs
index 565f917..f17e20f 100644
--- a/test/Serilog.Enrichers.Sensitive.Tests.Unit/WhenMaskingLogEventWithNonStringScalarValue.cs
+++ b/test/Serilog.Enrichers.Sensitive.Tests.Unit/WhenMaskingLogEventWithNonStringScalarValue.cs
@@ -88,7 +88,7 @@ public UriMaskingOperator() : base(SomePattern, RegexOptions.IgnoreCase | RegexO
{
}
- protected override string PreprocessInput(string input)
+ protected override string PreprocessInput(string input, string? logPropertyName = null)
{
return input;
}
diff --git a/test/Serilog.Enrichers.Sensitive.Tests.Unit/WhenMaskingWithRegexOperator.cs b/test/Serilog.Enrichers.Sensitive.Tests.Unit/WhenMaskingWithRegexOperator.cs
index 5175e55..6c87601 100644
--- a/test/Serilog.Enrichers.Sensitive.Tests.Unit/WhenMaskingWithRegexOperator.cs
+++ b/test/Serilog.Enrichers.Sensitive.Tests.Unit/WhenMaskingWithRegexOperator.cs
@@ -1,20 +1,20 @@
-using System;
+using FluentAssertions;
+using System;
using System.Text.RegularExpressions;
-using FluentAssertions;
using Xunit;
namespace Serilog.Enrichers.Sensitive.Tests.Unit
{
- public class WhenMaskingWithRegexOperator
- {
- private class RegexExtenderWithOptions : RegexMaskingOperator
+ public class WhenMaskingWithRegexOperator
+ {
+ private class RegexExtenderWithOptions : RegexMaskingOperator
{
private Func _preprocessMask;
- public RegexExtenderWithOptions(string regexPattern, Func? preprocessMask = null)
+ public RegexExtenderWithOptions(string regexPattern, Func? preprocessMask = null)
: base(regexPattern)
{
- _preprocessMask = preprocessMask ?? new Func((mask, _) => mask);
+ _preprocessMask = preprocessMask ?? new Func((mask, _) => mask);
}
protected override string PreprocessMask(string mask, Match match)
@@ -24,51 +24,68 @@ protected override string PreprocessMask(string mask, Match match)
}
- [Fact]
- public void GivenConstructor_NullPatternThrowsException()
- {
- var ex = Record.Exception(() => new RegexExtenderWithOptions(null!));
- ex
- .Should()
- .NotBeNull()
- .And
- .BeOfType();
- (ex as ArgumentNullException)?.ParamName
- .Should()
- .Be("regexString");
- }
+ [Fact]
+ public void GivenConstructor_NullPatternThrowsException()
+ {
+ var ex = Record.Exception(() => new RegexExtenderWithOptions(null!));
+ ex
+ .Should()
+ .NotBeNull()
+ .And
+ .BeOfType();
+ (ex as ArgumentNullException)?.ParamName
+ .Should()
+ .Be("regexString");
+ }
+
+ [Theory]
+ [InlineData("")]
+ [InlineData(" ")]
+ public void GivenConstructor_EmptyOrWhitespacePatternThrowsException(string regexPattern)
+ {
+ var ex = Record.Exception(() => new RegexExtenderWithOptions(regexPattern));
+ ex
+ .Should()
+ .NotBeNull()
+ .And
+ .BeOfType();
+ (ex as ArgumentOutOfRangeException)?.ParamName
+ .Should()
+ .Be("regexString");
+ }
- [Theory]
- [InlineData("")]
- [InlineData(" ")]
- public void GivenConstructor_EmptyOrWhitespacePatternThrowsException(string regexPattern)
- {
- var ex = Record.Exception(() => new RegexExtenderWithOptions(regexPattern));
- ex
- .Should()
- .NotBeNull()
- .And
- .BeOfType();
- (ex as ArgumentOutOfRangeException)?.ParamName
- .Should()
- .Be("regexString");
- }
+ [Fact]
+ public void GivenPreprocessMaskWithMatchIsUsed_MaskedValueIsModified_InProperty()
+ {
+ // Regex matches any character and has a match group for the last character.
+ // The mask provided to Mask() is ignored and instead it's set to mask all
+ // characters with '*' except the last one.
+ var result = new RegexExtenderWithOptions(
+ ".*([a-z])",
+ (mask, match) => match.Groups[1].Value.PadLeft(match.Value.Length, '*'))
+ .MaskProperty("anyName", "abc", "**MASK**");
+
+ result
+ .Result
+ .Should()
+ .Be("**c");
+ }
- [Fact]
- public void GivenPreprocessMaskWithMatchIsUsed_MaskedValueIsModified()
+ [Fact]
+ public void GivenPreprocessMaskWithMatchIsUsed_MaskedValueIsModified_InMessage()
{
- // Regex matches any character and has a match group for the last character.
- // The mask provided to Mask() is ignored and instead it's set to mask all
- // characters with '*' except the last one.
+ // Regex matches any character and has a match group for the last character.
+ // The mask provided to Mask() is ignored and instead it's set to mask all
+ // characters with '*' except the last one.
var result = new RegexExtenderWithOptions(
".*([a-z])",
(mask, match) => match.Groups[1].Value.PadLeft(match.Value.Length, '*'))
- .Mask("abc", "**MASK**");
+ .MaskMessage("abc", "**MASK**");
result
.Result
.Should()
.Be("**c");
}
- }
+ }
}
\ No newline at end of file