This repository has been archived by the owner on May 1, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 472
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added TextCharactersValidationBehavior (#363)
* Added TextCharactersValidationBehavior * Added unit tests * Fixed props naming * Update names. Added basic latin letters * Fixed build on Mac * Fixed warning * Removed redundant conditions * Restored removed line * Renamed class * Updated character type
- Loading branch information
1 parent
81f9899
commit b983c2d
Showing
6 changed files
with
168 additions
and
10 deletions.
There are no files selected for viewing
57 changes: 57 additions & 0 deletions
57
XamarinCommunityToolkit.UnitTests/Behaviors/CharactersValidationBehavior_Tests.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
using Xamarin.CommunityToolkit.Behaviors; | ||
using Xamarin.CommunityToolkit.UnitTests.Mocks; | ||
using Xamarin.Forms; | ||
using Xunit; | ||
|
||
namespace Xamarin.CommunityToolkit.UnitTests.Behaviors | ||
{ | ||
public class CharactersValidationBehavior_Tests | ||
{ | ||
public CharactersValidationBehavior_Tests() | ||
=> Device.PlatformServices = new MockPlatformServices(); | ||
|
||
[Theory] | ||
[InlineData(CharacterType.Any, 1, 2, "A", true)] | ||
[InlineData(CharacterType.Any, 0, int.MaxValue, "", true)] | ||
[InlineData(CharacterType.LowercaseLetter, 1, int.MaxValue, "WWWWWaWWWW", true)] | ||
[InlineData(CharacterType.UppercaseLetter, 1, int.MaxValue, "aaaaaaRRaaaa", true)] | ||
[InlineData(CharacterType.Letter, 4, int.MaxValue, "aaaaaaRRaaaa", true)] | ||
[InlineData(CharacterType.Digit, 1, int.MaxValue, "-1d", true)] | ||
[InlineData(CharacterType.Alphanumeric, 2, int.MaxValue, "@-3r", true)] | ||
[InlineData(CharacterType.NonAlphanumericSymbol, 10, int.MaxValue, "@-&^%!+()/", true)] | ||
[InlineData(CharacterType.LowercaseLatinLetter, 2, int.MaxValue, "HHHH a r.", true)] | ||
[InlineData(CharacterType.UppercaseLatinLetter, 2, int.MaxValue, "aaaaaa....R.R.R.aaaa", true)] | ||
[InlineData(CharacterType.LatinLetter, 5, int.MaxValue, "12345bBbBb", true)] | ||
[InlineData(CharacterType.Whitespace, 0, int.MaxValue, ";lkjhgfd@+fasf", true)] | ||
[InlineData(CharacterType.Any, 2, 2, "A", false)] | ||
[InlineData(CharacterType.Any, 2, 2, "AaA", false)] | ||
[InlineData(CharacterType.Any, 1, int.MaxValue, "", false)] | ||
[InlineData(CharacterType.Any, 1, int.MaxValue, null, false)] | ||
[InlineData(CharacterType.LowercaseLetter, 1, int.MaxValue, "WWWWWW", false)] | ||
[InlineData(CharacterType.UppercaseLetter, 1, int.MaxValue, "aaaaaa", false)] | ||
[InlineData(CharacterType.Letter, 4, int.MaxValue, "wHo", false)] | ||
[InlineData(CharacterType.Digit, 1, int.MaxValue, "-d", false)] | ||
[InlineData(CharacterType.Alphanumeric, 2, int.MaxValue, "@-3", false)] | ||
[InlineData(CharacterType.NonAlphanumericSymbol, 1, int.MaxValue, "WWWWWWWW", false)] | ||
[InlineData(CharacterType.LowercaseLatinLetter, 1, int.MaxValue, "Кириллица", false)] | ||
[InlineData(CharacterType.UppercaseLatinLetter, 1, int.MaxValue, "КИРИЛЛИЦА", false)] | ||
[InlineData(CharacterType.LatinLetter, 1, int.MaxValue, "Это Кириллица!", false)] | ||
[InlineData(CharacterType.Whitespace, 0, 0, "WWWWWW WWWWW", false)] | ||
public void IsValid(CharacterType characterType, int minimumCharactersNumber, int maximumCharactersNumber, string value, bool expectedValue) | ||
{ | ||
var behavior = new CharactersValidationBehavior | ||
{ | ||
CharacterType = characterType, | ||
MinimumCharacterCount = minimumCharactersNumber, | ||
MaximumCharacterCount = maximumCharactersNumber | ||
}; | ||
var entry = new Entry | ||
{ | ||
Text = value | ||
}; | ||
entry.Behaviors.Add(behavior); | ||
behavior.ForceValidate(); | ||
Assert.Equal(expectedValue, behavior.IsValid); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
20 changes: 20 additions & 0 deletions
20
XamarinCommunityToolkit/Behaviors/Validators/CharacterType.shared.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
using System; | ||
|
||
namespace Xamarin.CommunityToolkit.Behaviors | ||
{ | ||
[Flags] | ||
public enum CharacterType | ||
{ | ||
LowercaseLetter = 1, | ||
UppercaseLetter = 2, | ||
Letter = LowercaseLetter | UppercaseLetter, | ||
Digit = 4, | ||
Alphanumeric = Letter | Digit, | ||
Whitespace = 8, | ||
NonAlphanumericSymbol = 16, | ||
LowercaseLatinLetter = 32, | ||
UppercaseLatinLetter = 64, | ||
LatinLetter = LowercaseLatinLetter | UppercaseLatinLetter, | ||
Any = Alphanumeric | NonAlphanumericSymbol | Whitespace | ||
} | ||
} |
85 changes: 85 additions & 0 deletions
85
XamarinCommunityToolkit/Behaviors/Validators/CharactersValidationBehavior.shared.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using Xamarin.Forms; | ||
|
||
namespace Xamarin.CommunityToolkit.Behaviors | ||
{ | ||
public class CharactersValidationBehavior : TextValidationBehavior | ||
{ | ||
List<Predicate<char>> characterPredicates; | ||
|
||
public static readonly BindableProperty CharacterTypeProperty = | ||
BindableProperty.Create(nameof(CharacterType), typeof(CharacterType), typeof(CharactersValidationBehavior), CharacterType.Any, propertyChanged: OnCharacterTypePropertyChanged); | ||
|
||
public static readonly BindableProperty MinimumCharacterCountProperty = | ||
BindableProperty.Create(nameof(MinimumCharacterCount), typeof(int), typeof(CharactersValidationBehavior), 0, propertyChanged: OnValidationPropertyChanged); | ||
|
||
public static readonly BindableProperty MaximumCharacterCountProperty = | ||
BindableProperty.Create(nameof(MaximumCharacterCount), typeof(int), typeof(CharactersValidationBehavior), int.MaxValue, propertyChanged: OnValidationPropertyChanged); | ||
|
||
public CharactersValidationBehavior() | ||
=> OnCharacterTypePropertyChanged(); | ||
|
||
public CharacterType CharacterType | ||
{ | ||
get => (CharacterType)GetValue(CharacterTypeProperty); | ||
set => SetValue(CharacterTypeProperty, value); | ||
} | ||
|
||
public int MinimumCharacterCount | ||
{ | ||
get => (int)GetValue(MinimumCharacterCountProperty); | ||
set => SetValue(MinimumCharacterCountProperty, value); | ||
} | ||
|
||
public int MaximumCharacterCount | ||
{ | ||
get => (int)GetValue(MaximumCharacterCountProperty); | ||
set => SetValue(MaximumCharacterCountProperty, value); | ||
} | ||
|
||
protected override bool Validate(object value) | ||
=> base.Validate(value) && Validate(value?.ToString()); | ||
|
||
static void OnCharacterTypePropertyChanged(BindableObject bindable, object oldValue, object newValue) | ||
{ | ||
((CharactersValidationBehavior)bindable).OnCharacterTypePropertyChanged(); | ||
OnValidationPropertyChanged(bindable, oldValue, newValue); | ||
} | ||
|
||
static IEnumerable<Predicate<char>> GetCharacterPredicates(CharacterType characterType) | ||
{ | ||
if (characterType.HasFlag(CharacterType.LowercaseLetter)) | ||
yield return char.IsLower; | ||
|
||
if (characterType.HasFlag(CharacterType.UppercaseLetter)) | ||
yield return char.IsUpper; | ||
|
||
if (characterType.HasFlag(CharacterType.Digit)) | ||
yield return char.IsDigit; | ||
|
||
if (characterType.HasFlag(CharacterType.Whitespace)) | ||
yield return char.IsWhiteSpace; | ||
|
||
if (characterType.HasFlag(CharacterType.NonAlphanumericSymbol)) | ||
yield return c => !char.IsLetterOrDigit(c) && !char.IsWhiteSpace(c); | ||
|
||
if (characterType.HasFlag(CharacterType.LowercaseLatinLetter)) | ||
yield return c => c >= 'a' && c <= 'z'; | ||
|
||
if (characterType.HasFlag(CharacterType.UppercaseLatinLetter)) | ||
yield return c => c >= 'A' && c <= 'Z'; | ||
} | ||
|
||
void OnCharacterTypePropertyChanged() | ||
=> characterPredicates = GetCharacterPredicates(CharacterType).ToList(); | ||
|
||
bool Validate(string value) | ||
{ | ||
var count = value?.ToCharArray().Count(character => characterPredicates.Any(predicate => predicate.Invoke(character))) ?? 0; | ||
return count >= MinimumCharacterCount | ||
&& count <= MaximumCharacterCount; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters