Skip to content

Commit

Permalink
features and fix bugs
Browse files Browse the repository at this point in the history
feature: unit test added on all validation package files

fix: i used switch case again in the api.go file

fix: fixed bugs related to strings in cpf.go file.
  • Loading branch information
dennersousa committed Feb 12, 2024
1 parent e0c9c75 commit 631229c
Show file tree
Hide file tree
Showing 9 changed files with 313 additions and 28 deletions.
9 changes: 7 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,21 @@ module verifycat

go 1.22

require github.com/gin-gonic/gin v1.9.1
require (
github.com/gin-gonic/gin v1.9.1
github.com/stretchr/testify v1.8.4
)

require (
github.com/bytedance/sonic v1.10.2 // indirect
github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d // indirect
github.com/chenzhuoyu/iasm v0.9.1 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/gabriel-vasile/mimetype v1.4.3 // indirect
github.com/gin-contrib/sse v0.1.0 // indirect
github.com/go-playground/locales v0.14.1 // indirect
github.com/go-playground/universal-translator v0.18.1 // indirect
github.com/go-playground/validator/v10 v10.17.0 // indirect
github.com/go-playground/validator/v10 v10.18.0 // indirect
github.com/goccy/go-json v0.10.2 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/klauspost/cpuid/v2 v2.2.6 // indirect
Expand All @@ -21,6 +25,7 @@ require (
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/pelletier/go-toml/v2 v2.1.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
github.com/ugorji/go/codec v1.2.12 // indirect
golang.org/x/arch v0.7.0 // indirect
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJn
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
github.com/go-playground/validator/v10 v10.17.0 h1:SmVVlfAOtlZncTxRuinDPomC2DkXJ4E5T9gDA0AIH74=
github.com/go-playground/validator/v10 v10.17.0/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU=
github.com/go-playground/validator/v10 v10.18.0 h1:BvolUXjp4zuvkZ5YN5t7ebzbhlUtPsPm2S9NAZ5nl9U=
github.com/go-playground/validator/v10 v10.18.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM=
github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
Expand Down
45 changes: 23 additions & 22 deletions validate/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,46 +20,47 @@ type CreditCardResult struct {
Brand string `json:"brand,omitempty"`
}

// Mapeamento de tipos para funções de validação
var validationFuncMap = map[string]func(string) (bool, string){
"cpf": func(value string) (bool, string) { return IsValidCPF(value), "" },
"cnpj": func(value string) (bool, string) { return IsValidCNPJ(value), "" },
"url": func(value string) (bool, string) { return IsValidURL(value), "" },
"creditcard": ValidateCreditCard,
"email": func(value string) (bool, string) { return IsValidEmail(value), "" },
}

func ValidateHandler(c *gin.Context) {
var req ValidationRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}

validationFunc, exists := validationFuncMap[req.Type]
if !exists {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid validation type"})
return
}

var isValid bool
var message string
var brand string

if req.Type == "creditcard" {
isValid, brand = validationFunc(req.Value)
} else {
isValid, _ = validationFunc(req.Value)
switch req.Type {
case "cpf":
isValid = IsValidCPF(req.Value)
message = "CPF"
case "cnpj":
isValid = IsValidCNPJ(req.Value)
message = "CNPJ"
case "url":
isValid = IsValidURL(req.Value)
message = "URL"
case "creditcard":
isValid, brand = ValidateCreditCard(req.Value)
message = "Credit Card"
case "email":
isValid = IsValidEmail(req.Value)
message = "Email"
default:
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid validation type"})
return
}

var result interface{}
if req.Type == "creditcard" {
result = struct {
ValidationResult
CreditCard CreditCardResult `json:"creditcard,omitempty"`
CreditCard CreditCardResult `json:"creditCard,omitempty"`
}{
ValidationResult: ValidationResult{
IsValid: isValid,
Message: req.Type,
Message: message,
},
CreditCard: CreditCardResult{
Brand: brand,
Expand All @@ -68,7 +69,7 @@ func ValidateHandler(c *gin.Context) {
} else {
result = ValidationResult{
IsValid: isValid,
Message: req.Type,
Message: message,
}
}

Expand Down
43 changes: 43 additions & 0 deletions validate/cnpj_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package validate

import (
"testing"
)

func TestIsValidCNPJ(t *testing.T) {
// Caso de teste para CNPJ válido
validCNPJ := "11.222.333/0001-81"
if !IsValidCNPJ(validCNPJ) {
t.Errorf("Expected CNPJ %s to be valid, but got invalid", validCNPJ)
}

// Caso de teste para CNPJ inválido
invalidCNPJ := "11.222.333/0001-82"
if IsValidCNPJ(invalidCNPJ) {
t.Errorf("Expected CNPJ %s to be invalid, but got valid", invalidCNPJ)
}

// Caso de teste para CNPJ vazio
emptyCNPJ := ""
if IsValidCNPJ(emptyCNPJ) {
t.Errorf("Expected empty CNPJ to be invalid, but got valid")
}

// Caso de teste para CNPJ com tamanho incorreto
invalidSizeCNPJ := "11.222.333"
if IsValidCNPJ(invalidSizeCNPJ) {
t.Errorf("Expected CNPJ %s with incorrect size to be invalid, but got valid", invalidSizeCNPJ)
}

// Caso de teste para CNPJ com dígitos repetidos
repeatedDigitsCNPJ := "11.111.111/1111-11"
if IsValidCNPJ(repeatedDigitsCNPJ) {
t.Errorf("Expected CNPJ %s with repeated digits to be invalid, but got valid", repeatedDigitsCNPJ)
}

// Caso de teste para CNPJ sem caracteres especiais
withoutSpecialCharsCNPJ := "11222333000181"
if !IsValidCNPJ(withoutSpecialCharsCNPJ) {
t.Errorf("Expected CNPJ %s without special characters to be valid, but got invalid", withoutSpecialCharsCNPJ)
}
}
18 changes: 14 additions & 4 deletions validate/cpf.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,11 @@ func IsValidCPF(cpf string) bool {
cpf = strings.ReplaceAll(cpf, ".", "")
cpf = strings.ReplaceAll(cpf, "-", "")

// Check if the CPF contains only numeric digits
if _, err := strconv.Atoi(cpf); err != nil {
return false
}

// Check for known invalid CPFs
if strings.Count(cpf, string(cpf[0])) == 11 {
return false
Expand All @@ -41,11 +46,16 @@ func IsValidCPF(cpf string) bool {
// Extract digits from CPF
digits := make([]int, 11)
for i := 0; i < 11; i++ {
digit, err := strconv.Atoi(string(cpf[i]))
if err != nil {
// Handle error as needed
if i < len(cpf) {
digit, err := strconv.Atoi(string(cpf[i]))
if err != nil {
// Handle error as needed
}
digits[i] = digit
} else {
// Handle the case where the string is too short
return false
}
digits[i] = digit
}

// Calculate the first verification digit
Expand Down
58 changes: 58 additions & 0 deletions validate/cpf_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package validate

import (
"fmt"
"testing"
)

func TestIsValidCPFAllSameNumbers(t *testing.T) {
// Test with CPFs where all numbers are the same (0 to 9)
for digit := 0; digit <= 9; digit++ {
allSameCPF := fmt.Sprintf("%d%d%d.%d%d%d.%d%d%d-%d%d", digit, digit, digit, digit, digit, digit, digit, digit, digit, digit, digit)
result := IsValidCPF(allSameCPF)

if result {
t.Errorf("Expected CPF %s to be invalid, but got valid", allSameCPF)
}
}
}

func TestIsValidCPFValid(t *testing.T) {
// Test a valid CPF
validCPF := "123.456.789-09"
result := IsValidCPF(validCPF)

if !result {
t.Errorf("Expected CPF %s to be valid, but got invalid", validCPF)
}
}

func TestIsValidCPFInvalid(t *testing.T) {
// Test an invalid CPF
invalidCPF := "111.222.333-44"
result := IsValidCPF(invalidCPF)

if result {
t.Errorf("Expected CPF %s to be invalid, but got valid", invalidCPF)
}
}

func TestIsValidCPFShortInput(t *testing.T) {
// Test with a short input string
shortCPF := "123.456"
result := IsValidCPF(shortCPF)

if result {
t.Errorf("Expected CPF %s to be invalid due to short input, but got valid", shortCPF)
}
}

func TestIsValidCPFNonNumericInput(t *testing.T) {
// Test with non-numeric input
nonNumericCPF := "ABC.DEF.GHI-JK"
result := IsValidCPF(nonNumericCPF)

if result {
t.Errorf("Expected CPF %s to be invalid due to non-numeric characters, but got valid", nonNumericCPF)
}
}
57 changes: 57 additions & 0 deletions validate/creditcard_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package validate

import (
"testing"
)

// TestIsValidCreditCard verifica se a função IsValidCreditCard funciona corretamente.
func TestIsValidCreditCard(t *testing.T) {
// Teste para um número de cartão válido
validCard := "1234567812345670"
if !IsValidCreditCard(validCard) {
t.Errorf("Erro para cartão válido. Esperado true, obteve false.")
}

// Teste para um número de cartão inválido
invalidCard := "1234-5678-1234-5678"
if IsValidCreditCard(invalidCard) {
t.Errorf("Erro para cartão inválido. Esperado false, obteve true.")
}
}

// TestValidateCreditCard verifica se a função ValidateCreditCard funciona corretamente.
func TestValidateCreditCard(t *testing.T) {
// Teste para um número de cartão válido
validCard := "4539445433274775"
isValid, brand := ValidateCreditCard(validCard)
if !isValid || brand != "Visa" {
t.Errorf("Erro para cartão válido. Esperado (true, 'Visa'), obteve (%t, '%s').", isValid, brand)
}

// Teste para um número de cartão inválido
invalidCard := "1234-5678-1234-5678"
isValid, brand = ValidateCreditCard(invalidCard)
if isValid || brand != "" {
t.Errorf("Erro para cartão inválido. Esperado (false, ''), obteve (%t, '%s').", isValid, brand)
}
}

// TestIdentifyCardBrand verifica se a função IdentifyCardBrand funciona corretamente.
func TestIdentifyCardBrand(t *testing.T) {
// Teste para diferentes marcas de cartão
visaCard := "4123456781234567"
if brand := IdentifyCardBrand(visaCard); brand != "Visa" {
t.Errorf("Erro para cartão Visa. Esperado 'Visa', obteve '%s'.", brand)
}

masterCard := "5212345678901234"
if brand := IdentifyCardBrand(masterCard); brand != "MasterCard" {
t.Errorf("Erro para cartão MasterCard. Esperado 'MasterCard', obteve '%s'.", brand)
}

amexCard := "371234567890123"
if brand := IdentifyCardBrand(amexCard); brand != "American Express" {
t.Errorf("Erro para cartão American Express. Esperado 'American Express', obteve '%s'.", brand)
}

}
59 changes: 59 additions & 0 deletions validate/email_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package validate

import (
"testing"
)

func TestIsValidEmail_ValidEmail(t *testing.T) {
email := "[email protected]"
result := IsValidEmail(email)

if !result {
t.Errorf("Expected email '%s' to be valid, but it was invalid", email)
}
}

func TestIsValidEmail_InvalidEmail(t *testing.T) {
email := "invalid-email"
result := IsValidEmail(email)

if result {
t.Errorf("Expected email '%s' to be invalid, but it was valid", email)
}
}

func TestIsValidEmail_EmptyEmail(t *testing.T) {
email := ""
result := IsValidEmail(email)

if result {
t.Errorf("Expected empty email to be invalid, but it was valid")
}
}

func TestIsValidEmail_InvalidCharacters(t *testing.T) {
email := "[email protected]"
result := IsValidEmail(email)

if result {
t.Errorf("Expected email '%s' with invalid characters to be invalid, but it was valid", email)
}
}

func TestIsValidEmail_InvalidDomain(t *testing.T) {
email := "test@example"
result := IsValidEmail(email)

if result {
t.Errorf("Expected email '%s' with invalid domain to be invalid, but it was valid", email)
}
}

func TestIsValidEmail_InvalidTLD(t *testing.T) {
email := "[email protected]"
result := IsValidEmail(email)

if result {
t.Errorf("Expected email '%s' with invalid top-level domain to be invalid, but it was valid", email)
}
}
Loading

0 comments on commit 631229c

Please sign in to comment.