diff --git a/README.md b/README.md index f226f19..dad5ffb 100644 --- a/README.md +++ b/README.md @@ -27,6 +27,7 @@ We already have some validators that you can use: - CreditCardNumberValidator - EmailValidator - DateValidator + - CpfValidator - (Brazilian Social Security Number) But feel free to implement yours or contribute with more validators 😉 diff --git a/src/Inquirer/Validators/CpfValidator.cs b/src/Inquirer/Validators/CpfValidator.cs new file mode 100644 index 0000000..59d6a54 --- /dev/null +++ b/src/Inquirer/Validators/CpfValidator.cs @@ -0,0 +1,76 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Text.RegularExpressions; + +namespace InquirerCore.Validators +{ + public class CpfValidator : IValidator + { + public bool Validate(string value) + { + if (string.IsNullOrEmpty(value)) + return false; + + // Remove spaces, dashes and dots + var cleanCpfNumber = new Regex(@"[\s-.]+") + .Replace(value, ""); + + // Is all digits with length equals 11? + var isValidNumberFormat = new Regex(@"^[0-9]{11}$") + .Match(cleanCpfNumber).Success; + + if (isValidNumberFormat) + return isValidCpfNumber(cleanCpfNumber); + + return false; + } + + private bool isValidCpfNumber(string value) + { + int[] multplier1 = new int[9] { 10, 9, 8, 7, 6, 5, 4, 3, 2 }; + int[] multiplier2 = new int[10] { 11, 10, 9, 8, 7, 6, 5, 4, 3, 2 }; + string tempCpf; + string digit; + int sum; + int rest; + tempCpf = value.Substring(0, 9); + sum = 0; + + for (int i = 0; i < 9; i++) + sum += int.Parse(tempCpf[i].ToString()) * multplier1[i]; + + rest = sum % 11; + + if (rest < 2) + rest = 0; + else + rest = 11 - rest; + + digit = rest.ToString(); + tempCpf = tempCpf + digit; + sum = 0; + + for (int i = 0; i < 10; i++) + sum += int.Parse(tempCpf[i].ToString()) * multiplier2[i]; + + rest = sum % 11; + + if (rest < 2) + rest = 0; + else + rest = 11 - rest; + + digit = digit + rest.ToString(); + + return value.EndsWith(digit); + } + + public string GetErrorMessage() + { + return "Answer accepts only CPF's numbers."; + } + + + } +} diff --git a/test/InquirerUnitTest/Validators/CpfValidatorUnitTest.cs b/test/InquirerUnitTest/Validators/CpfValidatorUnitTest.cs new file mode 100644 index 0000000..ced3838 --- /dev/null +++ b/test/InquirerUnitTest/Validators/CpfValidatorUnitTest.cs @@ -0,0 +1,49 @@ +using FluentAssertions; +using InquirerCore.Validators; +using System; +using System.Collections.Generic; +using System.Text; +using Xunit; + +namespace InquirerUnitTest.Validators +{ + public class CpfValidatorUnitTest + { + [Theory] + [InlineData("088.218.720-17")] + [InlineData("229.709.540-60")] + [InlineData("22970954060")] + public void ShouldAcceptCpfValues(string aDateValue) + { + var validator = new CpfValidator(); + + var isValid = validator.Validate(aDateValue); + + isValid.Should().BeTrue(); + } + + [Theory] + [InlineData("22970954060aa")] + [InlineData("22970954061")] + [InlineData("229709540/60")] + [InlineData("invalid")] + [InlineData("")] + [InlineData(null)] + public void ShouldNotAcceptNoCpfValues(string aNonDateValue) + { + var validator = new CpfValidator(); + + var isValid = validator.Validate(aNonDateValue); + + isValid.Should().BeFalse(); + } + + [Fact] + public void ShouldReturnErrorMessage() + { + var validator = new CpfValidator(); + + validator.GetErrorMessage().Should().Be("Answer accepts only CPF's numbers."); + } + } +}