From 9d18a7dff3e9fb839892f6937333d12de477a730 Mon Sep 17 00:00:00 2001 From: David Pine Date: Thu, 1 Feb 2024 06:51:09 -0600 Subject: [PATCH] More tests, rename a strategy, update README.md and add tests. --- README.md | 4 ++-- .../DefaultProfaneContentFilterService.cs | 4 ++-- .../ReplacementStrategyExtensions.cs | 11 ++++++---- ...rofaneFilter.cs => ProfaneSourceFilter.cs} | 2 +- .../Filters/ReplacementStrategy.cs | 4 ++-- .../Internals/MatchEvaluators.cs | 4 ++-- .../MatchEvaluatorTests.cs | 22 +++++++++++-------- 7 files changed, 29 insertions(+), 22 deletions(-) rename src/ProfanityFilter.Services/Filters/{ProfaneFilter.cs => ProfaneSourceFilter.cs} (91%) diff --git a/README.md b/README.md index 44d3b3e..58ccf7e 100644 --- a/README.md +++ b/README.md @@ -99,14 +99,14 @@ Each replacement strategy corresponds to a different way of replacing profane co | `ReplacementType.FirstLetterThenAsterisk` | `"FirstLetterThenAsterisk"` | Replaces profane content with asterisks after the first letter. For example, a swear word with four letters could look like this `f\*\*\*`. | | `ReplacementType.VowelAsterisk` | `"VowelAsterisk"` | Replaces profane content with asterisks, but only the vowels. For example, a swear word with four letters could look like this `sh\*t`. | | `ReplacementType.Bleep` | `"Bleep"` | Replaces profane content with asterisks, but only the vowels. For example, a swear word with four letters could look like this `sh\*t`. | -| `ReplacementType.RedactedBlackRectangle` | `"RedactedBlackRectangle"` | Replaces profane content with black rectangles to redact their content. For example, a swear word with four letters could look like this `████`. | +| `ReplacementType.RedactedRectangle` | `"RedactedRectangle"` | Replaces profane content with rectangles to redact their content. For example, a swear word with four letters could look like this `████`. | | `ReplacementType.StrikeThrough` | `"StrikeThrough"` | Encloses profane content with `~~` causing strikethrough rendering. For example, a swear word with four letters could look like this ~~`shit`~~. | | `ReplacementType.Underscores` | `"Underscores"` | Replaces profane content with underscores `_`. For example, a swear word with four letters could look like this `____`. | The value of the `replacement-strategy` input is case-insensitive, and accepts hyphened alternatives (such as `anger-emoji`) as well. > [!TIP] -> All asterisk replacement strategies are escaped with a backslash `\` to prevent markdown from rendering the asterisks as bold text. No need for you the escape these values yourself. +> All asterisk replacement strategies are escaped with a backslash `\` to prevent markdown from rendering the asterisks as bold text. No need for you the escape these values yourself. This excludes title updates, as markdown is supported there. ## 🏷️ Label requirements diff --git a/src/ProfanityFilter.Services/DefaultProfaneContentFilterService.cs b/src/ProfanityFilter.Services/DefaultProfaneContentFilterService.cs index dd6a2cd..de2a816 100644 --- a/src/ProfanityFilter.Services/DefaultProfaneContentFilterService.cs +++ b/src/ProfanityFilter.Services/DefaultProfaneContentFilterService.cs @@ -12,7 +12,7 @@ internal sealed class DefaultProfaneContentFilterService(IMemoryCache cache) : I /// /// A representing the asynchronous operation that /// returns a readonly dictionary of all profane words. - private async Task> ReadAllProfaneWordsAsync() + private async Task> ReadAllProfaneWordsAsync() { return await cache.GetOrCreateAsync(ProfaneListKey, async entry => { @@ -57,7 +57,7 @@ await Parallel.ForEachAsync(fileNames, return allWords.ToDictionary( static kvp => kvp.Key, - static kvp => new ProfaneFilter(kvp.Key, kvp.Value.ToFrozenSet())); + static kvp => new ProfaneSourceFilter(kvp.Key, kvp.Value.ToFrozenSet())); }) ?? []; } diff --git a/src/ProfanityFilter.Services/Extensions/ReplacementStrategyExtensions.cs b/src/ProfanityFilter.Services/Extensions/ReplacementStrategyExtensions.cs index 0a4e556..5aa017e 100644 --- a/src/ProfanityFilter.Services/Extensions/ReplacementStrategyExtensions.cs +++ b/src/ProfanityFilter.Services/Extensions/ReplacementStrategyExtensions.cs @@ -15,11 +15,13 @@ public static string ToSummaryString(this ReplacementStrategy replacementStrateg ReplacementStrategy.RandomAsterisk => "random asterisk", ReplacementStrategy.MiddleAsterisk => "middle asterisk", ReplacementStrategy.VowelAsterisk => "vowel asterisk", + ReplacementStrategy.FirstLetterThenAsterisk => "first letter then asterisk", ReplacementStrategy.AngerEmoji => "anger emoji", ReplacementStrategy.Bleep => "bleep", - ReplacementStrategy.RedactedBlackRectangle => "redacted black rectangle", + ReplacementStrategy.RedactedRectangle => "redacted rectangle", ReplacementStrategy.StrikeThrough => "string through", ReplacementStrategy.Underscores => "underscores", + _ => "asterisk", }; } @@ -28,18 +30,19 @@ internal static Func GetMatchEvaluator(this Replac { return replacementStrategy switch { - ReplacementStrategy.Asterisk => MatchEvaluators.AsteriskEvaluator, + ReplacementStrategy.Emoji => MatchEvaluators.EmojiEvaluator, ReplacementStrategy.RandomAsterisk => MatchEvaluators.RandomAsteriskEvaluator, ReplacementStrategy.MiddleAsterisk => MatchEvaluators.MiddleAsteriskEvaluator, ReplacementStrategy.MiddleSwearEmoji => MatchEvaluators.MiddleSwearEmojiEvaluator, ReplacementStrategy.VowelAsterisk => MatchEvaluators.VowelAsteriskEvaluator, + ReplacementStrategy.FirstLetterThenAsterisk => MatchEvaluators.FirstLetterThenAsteriskEvaluator, ReplacementStrategy.AngerEmoji => MatchEvaluators.AngerEmojiEvaluator, ReplacementStrategy.Bleep => MatchEvaluators.BleepEvaluator, - ReplacementStrategy.RedactedBlackRectangle => MatchEvaluators.RedactedBlackRectangleEvaluator, + ReplacementStrategy.RedactedRectangle => MatchEvaluators.RedactedRectangleEvaluator, ReplacementStrategy.StrikeThrough => MatchEvaluators.StrikeThroughEvaluator, ReplacementStrategy.Underscores => MatchEvaluators.UnderscoresEvaluator, - _ => MatchEvaluators.EmojiEvaluator, + _ => MatchEvaluators.AsteriskEvaluator, }; } } diff --git a/src/ProfanityFilter.Services/Filters/ProfaneFilter.cs b/src/ProfanityFilter.Services/Filters/ProfaneSourceFilter.cs similarity index 91% rename from src/ProfanityFilter.Services/Filters/ProfaneFilter.cs rename to src/ProfanityFilter.Services/Filters/ProfaneSourceFilter.cs index f377aa1..429f3c6 100644 --- a/src/ProfanityFilter.Services/Filters/ProfaneFilter.cs +++ b/src/ProfanityFilter.Services/Filters/ProfaneSourceFilter.cs @@ -3,7 +3,7 @@ namespace ProfanityFilter.Services; -internal record class ProfaneFilter( +internal record class ProfaneSourceFilter( string SourceName, FrozenSet ProfaneWords) { diff --git a/src/ProfanityFilter.Services/Filters/ReplacementStrategy.cs b/src/ProfanityFilter.Services/Filters/ReplacementStrategy.cs index c112ccc..1789211 100644 --- a/src/ProfanityFilter.Services/Filters/ReplacementStrategy.cs +++ b/src/ProfanityFilter.Services/Filters/ReplacementStrategy.cs @@ -61,9 +61,9 @@ public enum ReplacementStrategy /// /// Represents a replacement strategy where the profane word has each letter - /// replaced with the black rectangle symbol . + /// replaced with the rectangle symbol . /// - RedactedBlackRectangle, + RedactedRectangle, /// /// Represents a replacement strategy where the profane word is ~~struck through~~. diff --git a/src/ProfanityFilter.Services/Internals/MatchEvaluators.cs b/src/ProfanityFilter.Services/Internals/MatchEvaluators.cs index 35f2139..9afb2e8 100644 --- a/src/ProfanityFilter.Services/Internals/MatchEvaluators.cs +++ b/src/ProfanityFilter.Services/Internals/MatchEvaluators.cs @@ -169,9 +169,9 @@ internal static MatchEvaluator BleepEvaluator(FilterTarget target) => }; /// - /// A that replaces each letter in a string with the black rectangle symbol . + /// A that replaces each letter in a string with the rectangle symbol . /// - internal static MatchEvaluator RedactedBlackRectangleEvaluator(FilterTarget target) => + internal static MatchEvaluator RedactedRectangleEvaluator(FilterTarget target) => string (match) => { _ = target; diff --git a/tests/ProfanityFilter.Services.Tests/MatchEvaluatorTests.cs b/tests/ProfanityFilter.Services.Tests/MatchEvaluatorTests.cs index c681e6d..2d1cb52 100644 --- a/tests/ProfanityFilter.Services.Tests/MatchEvaluatorTests.cs +++ b/tests/ProfanityFilter.Services.Tests/MatchEvaluatorTests.cs @@ -48,29 +48,33 @@ public void EmojiEvaluator_Returns_Expected_Result() } [Theory] - [InlineData("Test", @"T\*st")] - [InlineData("swear", @"sw\*\*r")] - public void VowelAsteriskEvaluator_Returns_Expected_Result(string input, string expected) + [InlineData(FilterTarget.Body, "Test", @"T\*st")] + [InlineData(FilterTarget.Body, "swear", @"sw\*\*r")] + [InlineData(FilterTarget.Title, "Test", @"T*st")] + [InlineData(FilterTarget.Title, "swear", @"sw**r")] + public void VowelAsteriskEvaluator_Returns_Expected_Result(FilterTarget target, string input, string expected) { var regex = TestRegex(); var match = regex.Match(input); var sut = MatchEvaluators.VowelAsteriskEvaluator; - var actual = sut(FilterTarget.Body).Invoke(match); + var actual = sut(target).Invoke(match); Assert.Equal(expected, actual); } [Theory] - [InlineData("Test", @"T\*\*t")] - [InlineData("swear", @"s\*\*\*r")] - public void MiddleAsteriskEvaluator_Returns_Expected_Result(string input, string expected) + [InlineData(FilterTarget.Body, "Test", @"T\*\*t")] + [InlineData(FilterTarget.Body, "swear", @"s\*\*\*r")] + [InlineData(FilterTarget.Title, "Test", @"T**t")] + [InlineData(FilterTarget.Title, "swear", @"s***r")] + public void MiddleAsteriskEvaluator_Returns_Expected_Result(FilterTarget target, string input, string expected) { var regex = TestRegex(); var match = regex.Match(input); var sut = MatchEvaluators.MiddleAsteriskEvaluator; - var actual = sut(FilterTarget.Body).Invoke(match); + var actual = sut(target).Invoke(match); Assert.Equal(expected, actual); } @@ -96,7 +100,7 @@ public void RedactedBlackRectangleEvaluator_Returns_Expected_Result(string input { var regex = TestRegex(); var match = regex.Match(input); - var sut = MatchEvaluators.RedactedBlackRectangleEvaluator; + var sut = MatchEvaluators.RedactedRectangleEvaluator; var actual = sut(FilterTarget.Body).Invoke(match);