diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..33c54c2 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,26 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [Unreleased] + +## [2.0.0] - 2025-03-26 + +### Added +- `Document` interface for document operations. +- `IsValid`, `Format`, and `Generate` methods for document validation and formatting. + +### Changed +- Converted voter registration functions to methods of `VoterRegistration` struct implementing the `Document` interface. +- Converted CPF functions to methods of `CPF` struct implementing the `Document` interface. +- Converted CNPJ functions to methods of `CNPJ` struct implementing the `Document` interface. +- Converted CNH functions to methods of `CNH` struct implementing the `Document` interface. +- Consolidated document operations into a unified interface with `IsValid`, `Format`, and `Generate` methods. +- Updated README to reflect method changes for `CNPJ` and `VoterRegistration`. +- Enhanced clarity on package functionality and usage examples in README. + +### Fixed +- Updated voter registration test to ignore voter output. \ No newline at end of file diff --git a/README.md b/README.md index 72cc53e..3b407d1 100644 --- a/README.md +++ b/README.md @@ -1,43 +1,65 @@ -# Brazil-Code +# Brazil Code -This is validator, generator and formats the brazil code as CPF and CNPJ +The `brazilcode` package provides functionality to validate, generate, and format Brazilian identification codes, including CPF, CNPJ, CNH, and Título de Eleitor (Voter Registration). -> Formats to use -- CPF -- CNPJ -- CNH - - VoterRegistration(Título de Eleitor) +## Supported Formats +- **CPF**: Cadastro de Pessoas Físicas (Individual Taxpayer Registry) +- **CNPJ**: Cadastro Nacional de Pessoas Jurídicas (National Register of Legal Entities) +- **CNH**: Carteira Nacional de Habilitação (National Driver's License) +- **Voter Registration (Título de Eleitor)**: Brazilian Electoral Registration Number -## Development -Import package with command in shell +## Installation +To install the `brazilcode` package, run the following command in your shell: ```shell $ go get github.com/potatowski/brazilcode ``` -In code just use the function with import -> Example: -```code + +## Usage +Once the package is installed, you can use the functions provided to generate, validate, and format documents. + +### Example Code: +```go package main import ( "fmt" - "github.com/potatowski/brazilcode" ) func main() { - doc, err := brazilcode.CNPJGenerate() + // Generate a CNPJ document + doc, err := brazilcode.CNPJ.Generate() if err != nil { panic(err) } - docFormatted, err := brazilcode.CNPJFormat(doc) + // Format the CNPJ document + docFormatted, err := brazilcode.CNPJ.Format(doc) if err != nil { panic(err) } + // Print both unformatted and formatted documents fmt.Println(doc, docFormatted) } ``` + +Alternatively, you can use the generic `Generate` and `Format` functions to generate and format any document type: +```go +doc, err := brazilcode.Generate("CNPJ") +if err != nil { + panic(err) +} + +docFormatted, err := brazilcode.Format("CNPJ", doc) +if err != nil { + panic(err) +} + +fmt.Println(doc, docFormatted) +``` + ## License +This project is licensed under the MIT License. -The MIT License © 2023 João Vitor Lima da Rocha +© 2023 João Vitor Lima da Rocha \ No newline at end of file diff --git a/brazilcode.go b/brazilcode.go index 31e8e35..262e7bb 100644 --- a/brazilcode.go +++ b/brazilcode.go @@ -1,131 +1,72 @@ package brazilcode import ( + "errors" + "github.com/potatowski/brazilcode/src/cnh" "github.com/potatowski/brazilcode/src/cnpj" "github.com/potatowski/brazilcode/src/cpf" + iface "github.com/potatowski/brazilcode/src/interface" "github.com/potatowski/brazilcode/src/voterRegistration" ) -var ( - //Errors about CNPJ - ErrCNPJInvalid = cnpj.ErrCNPJInvalid - ErrCNPJInvalidLength = cnpj.ErrCNPJInvalidLength - - //Errors about CPF - ErrCPFInvalidLength = cpf.ErrCPFInvalidLength - ErrCPFInvalid = cpf.ErrCPFInvalid - - //Errors about CNH - ErrCNHInvalid = cnh.ErrCNHInvalid - ErrCNHInvalidLength = cnh.ErrCNHInvalidLength - - //Errors about Voter Registration - ErrVoterRegistrationInvalid = voterRegistration.ErrVoterRegistrationInvalid - ErrVoterRegistrationInvalidLength = voterRegistration.ErrVoterRegistrationInvalidLength - ErrVoterRegistrationInvalidUF = voterRegistration.ErrVoterRegistrationInvalidUF - ErrVoterRegistrationLimit = voterRegistration.ErrVoterRegistrationLimit -) - -/* -CNPJIsValid check if the CNPJ is valid - - @param {string} doc - CNPJ - - @return {error} - error -*/ -func CNPJIsValid(doc string) error { - return cnpj.IsValid(doc) -} - -/* -CNPJFormat format the an valid CNPJ - - @param {string} doc - CNPJ - - @return {string} - CNPJ formatted - - @return {error} - error -*/ -func CNPJFormat(doc string) (string, error) { - return cnpj.Format(doc) -} - -/* -CNPJGenerate generate a valid CNPJ - - @return {string} - CNPJ - - @return {error} - error -*/ -func CNPJGenerate() (string, error) { - return cnpj.Generate() -} - -/* -CPFIsValid check if the CPF is valid - - @param {string} doc - CPF - - @return {error} - error -*/ -func CPFIsValid(doc string) error { - return cpf.IsValid(doc) -} - -/* -CPFFormat format the a valid CPF - - @param {string} doc - CPF - - @return {string} - CPF formatted - - @return {error} - error -*/ -func CPFFormat(doc string) (string, error) { - return cpf.Format(doc) -} - -/* -CPFGenerate generate a valid CPF - - @return {string} - CPF - - @return {error} - error -*/ -func CPFGenerate() (string, error) { - return cpf.Generate() -} - -/* -CNHIsValid check if the CNH is valid - - @param {string} doc - - @return {error} - error -*/ -func CNHIsValid(doc string) error { - return cnh.IsValid(doc) -} +var CPF = cpf.CPF{} +var CNPJ = cnpj.CNPJ{} +var CNH = cnh.CNH{} +var VoterRegistration = voterRegistration.VoterRegistration{} -/* -CNHGenerate generate a valid CNH - - @return {string} - CNH - - @return {error} - error -*/ -func CNHGenerate() (string, error) { - return cnh.Generate() +var Documents = map[string]iface.Document{ + "CPF": CPF, + "CNPJ": CNPJ, + "CNH": CNH, + "VoterRegistration": VoterRegistration, } -/* -VoterRegistrationIsValid check if the Voter Registration is valid - - @param {string} doc - Voter Registration - - @return {error} - error -*/ -func VoterRegistrationIsValid(doc string) error { - return voterRegistration.IsValid(doc) +// IsValid checks if the provided document is valid based on its type. +// It takes a document type (docType) and the document value (doc) as input. +// If the document type exists in the Documents map, it delegates the validation +// to the corresponding IsValid method of the document type. +// Returns nil if the document is valid, or an error if the document type is not supported +// or the document fails validation. +func IsValid(docType, doc string) error { + if d, exists := Documents[docType]; exists { + return d.IsValid(doc) + } + return errors.New("document type not supported") } -/* -VoterRegistrationFormat format the a valid Voter Registration - - @param {string} doc - Voter Registration - - @return {string} - Voter Registration formatted - - @return {error} - error -*/ -func VoterRegistrationFormat(doc string) (string, error) { - return voterRegistration.Format(doc) +// Format formats a given document string based on its type. +// It takes two parameters: docType, which specifies the type of the document +// (e.g., CPF, CNPJ), and doc, which is the document string to be formatted. +// If the document type is supported, it returns the formatted document string. +// Otherwise, it returns an error indicating that the document type is not supported. +// +// Parameters: +// - docType: A string representing the type of the document. +// - doc: A string representing the document to be formatted. +// +// Returns: +// - A formatted document string if the document type is supported. +// - An error if the document type is not supported. +func Format(docType, doc string) (string, error) { + if d, exists := Documents[docType]; exists { + return d.Format(doc) + } + return "", errors.New("document type not supported") } -/* -VoterRegistrationGenerate generate a valid Voter Registration - - @param {string} uf - UF is the state of Brazil or ZZ for foreigners - - @return {string} - - @return {error} -*/ -func VoterRegistrationGenerate(uf string) (string, error) { - return voterRegistration.Generate(uf) +// Generate generates a document based on the provided document type. +// It returns the generated document as a string and an error if the document type is not supported. +// +// Parameters: +// - docType: A string representing the type of document to generate. +// +// Returns: +// - string: The generated document. +// - error: An error if the document type is not supported. +func Generate(docType string) (string, error) { + if d, exists := Documents[docType]; exists { + return d.Generate() + } + return "", errors.New("document type not supported") } diff --git a/brazilcode_test.go b/brazilcode_test.go new file mode 100644 index 0000000..9a16da7 --- /dev/null +++ b/brazilcode_test.go @@ -0,0 +1,71 @@ +package brazilcode_test + +import ( + "testing" + + "github.com/potatowski/brazilcode" +) + +func TestIsValid(t *testing.T) { + tests := []struct { + docType string + doc string + wantErr bool + }{ + {"CPF", "12345678909", false}, + {"InvalidType", "", true}, + } + + for _, tt := range tests { + t.Run(tt.docType, func(t *testing.T) { + err := brazilcode.IsValid(tt.docType, tt.doc) + if (err != nil) != tt.wantErr { + t.Errorf("IsValid() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} + +func TestFormat(t *testing.T) { + tests := []struct { + docType string + doc string + want string + wantErr bool + }{ + {"CPF", "12345678909", "123.456.789-09", false}, + {"CPF", "12345678908", "", true}, + {"InvalidType", "xpto", "", true}, + } + + for _, tt := range tests { + t.Run(tt.docType, func(t *testing.T) { + got, err := brazilcode.Format(tt.docType, tt.doc) + if (err != nil) != tt.wantErr { + t.Errorf("Format() error = %v, wantErr %v", err, tt.wantErr) + } + if got != tt.want { + t.Errorf("Format() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestGenerate(t *testing.T) { + tests := []struct { + docType string + wantErr bool + }{ + {"CPF", false}, + {"InvalidType", true}, + } + + for _, tt := range tests { + t.Run(tt.docType, func(t *testing.T) { + _, err := brazilcode.Generate(tt.docType) + if (err != nil) != tt.wantErr { + t.Errorf("Generate() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/src/cnh/cnh.go b/src/cnh/cnh.go index a5d993f..978305c 100644 --- a/src/cnh/cnh.go +++ b/src/cnh/cnh.go @@ -3,26 +3,28 @@ package cnh import ( "fmt" - "github.com/potatowski/brazilcode/src" + "github.com/potatowski/brazilcode/src/utils" ) var ( - ErrCNHInvalidLength = fmt.Errorf("Invalid CNH length") - ErrCNHInvalid = fmt.Errorf("Invalid CNH") + ErrCNHInvalidLength = fmt.Errorf("invalid CNH length") + ErrCNHInvalid = fmt.Errorf("invalid CNH") ) +type CNH struct{} + /* IsValid check if the CNH is valid - @param {string} - @return {error} */ -func IsValid(doc string) error { - doc = src.RemoveChar(doc) +func (iDoc CNH) IsValid(doc string) error { + doc = utils.RemoveChar(doc) if len(doc) != 11 { return ErrCNHInvalidLength } - dv1, dv2, err := src.CalculateCNHDVs(doc) + dv1, dv2, err := utils.CalculateCNHDVs(doc) if err != nil { return err } @@ -34,20 +36,34 @@ func IsValid(doc string) error { return nil } +/* +Format is to format the CNH + - @param {string} doc + - @return {string, error} +*/ +func (iDoc CNH) Format(doc string) (string, error) { + err := iDoc.IsValid(doc) + if err != nil { + return "", err + } + + return doc, nil +} + /* Generate is to create a random CNH - @return {string} - @return {error} */ -func Generate() (string, error) { - cnh := src.GenerateRandomDoc(9, 10) - dv1, dv2, err := src.CalculateCNHDVs(cnh) +func (iDoc CNH) Generate() (string, error) { + cnh := utils.GenerateRandomDoc(9, 10) + dv1, dv2, err := utils.CalculateCNHDVs(cnh) if err != nil { return "", err } cnh += fmt.Sprintf("%d%d", dv1, dv2) - IsValid(cnh) + iDoc.IsValid(cnh) return cnh, nil } diff --git a/src/cnh/cnh_test.go b/src/cnh/cnh_test.go index 2809b43..0596c05 100644 --- a/src/cnh/cnh_test.go +++ b/src/cnh/cnh_test.go @@ -2,9 +2,14 @@ package cnh import ( "testing" + + iface "github.com/potatowski/brazilcode/src/interface" ) +var doc iface.Document = CNH{} + func TestIsValid(t *testing.T) { + testCases := []struct { name string doc string @@ -34,7 +39,7 @@ func TestIsValid(t *testing.T) { for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { - err := IsValid(tc.doc) + err := doc.IsValid(tc.doc) if err != tc.expected { t.Errorf("Expected error to be '%v' but got '%v'", tc.expected, err) } @@ -42,8 +47,43 @@ func TestIsValid(t *testing.T) { } } +func TestFormat(t *testing.T) { + testCases := []struct { + name string + doc string + expected string + expectedError error + }{ + { + name: "Valid CNH", + doc: "34390008188", + expected: "34390008188", + expectedError: nil, + }, + { + name: "Invalid CNH", + doc: "34390008181", + expected: "", + expectedError: ErrCNHInvalid, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + result, err := doc.Format(tc.doc) + if err != nil && err != tc.expectedError { + t.Errorf("Expected error to be '%v' but got '%v'", tc.expectedError, err) + } + + if result != tc.expected { + t.Errorf("Expected result to be '%v' but got '%v'", tc.expected, result) + } + }) + } +} + func TestGenerate(t *testing.T) { - cnh, err := Generate() + cnh, err := doc.Generate() if err != nil { t.Errorf("[TEST-CNH-generate] unexpected error: %v\n CNH generated: %s", err, cnh) } diff --git a/src/cnpj/cnpj.go b/src/cnpj/cnpj.go index a48af8d..93982de 100644 --- a/src/cnpj/cnpj.go +++ b/src/cnpj/cnpj.go @@ -4,21 +4,23 @@ import ( "errors" "fmt" - "github.com/potatowski/brazilcode/src" + "github.com/potatowski/brazilcode/src/utils" ) var ( - ErrCNPJInvalid = errors.New("Invalid CNPJ") - ErrCNPJInvalidLength = errors.New("Invalid CNPJ length") + ErrCNPJInvalid = errors.New("invalid CNPJ") + ErrCNPJInvalidLength = errors.New("invalid CNPJ length") ) +type CNPJ struct{} + /* IsValid check if the CNPJ is valid - @param {string} doc - @return {error} */ -func IsValid(doc string) error { - doc = src.RemoveChar(doc) +func (iDoc CNPJ) IsValid(doc string) error { + doc = utils.RemoveChar(doc) if len(doc) != 14 { return ErrCNPJInvalidLength } @@ -28,23 +30,23 @@ func IsValid(doc string) error { doc = doc[:12] var sum int - sum, err := src.Calculator(doc, 5) + sum, err := utils.Calculator(doc, 5) if err != nil { return err } - firstDigit := src.GetDigit(sum) + firstDigit := utils.GetDigit(sum) if firstDigit != int(firstDigitCheck) { return ErrCNPJInvalid } doc += fmt.Sprintf("%d", firstDigit) - sum, err = src.Calculator(doc, 6) + sum, err = utils.Calculator(doc, 6) if err != nil { return err } - secondDigit := src.GetDigit(sum) + secondDigit := utils.GetDigit(sum) if secondDigit != int(secondDigitCheck) { return ErrCNPJInvalid } @@ -57,8 +59,8 @@ Format is to format the CNPJ - @param {string} doc - @return {string, error} */ -func Format(doc string) (string, error) { - if err := IsValid(doc); err != nil { +func (iDoc CNPJ) Format(doc string) (string, error) { + if err := iDoc.IsValid(doc); err != nil { return "", err } return doc[:2] + "." + doc[2:5] + "." + doc[5:8] + "/" + doc[8:12] + "-" + doc[12:], nil @@ -68,24 +70,24 @@ func Format(doc string) (string, error) { Generate is to create a random CNPJ - @return {string} */ -func Generate() (string, error) { - cnpj := src.GenerateRandomDoc(12, 9) +func (iDoc CNPJ) Generate() (string, error) { + cnpj := utils.GenerateRandomDoc(12, 9) - sum, err := src.Calculator(cnpj, 5) + sum, err := utils.Calculator(cnpj, 5) if err != nil { return "", err } - cnpj += fmt.Sprintf("%d", src.GetDigit(sum)) + cnpj += fmt.Sprintf("%d", utils.GetDigit(sum)) - sum, err = src.Calculator(cnpj, 6) + sum, err = utils.Calculator(cnpj, 6) if err != nil { return "", err } - cnpj += fmt.Sprintf("%d", src.GetDigit(sum)) + cnpj += fmt.Sprintf("%d", utils.GetDigit(sum)) - if err := IsValid(cnpj); err != nil { + if err := iDoc.IsValid(cnpj); err != nil { return "", err } diff --git a/src/cnpj/cnpj_test.go b/src/cnpj/cnpj_test.go index e349aa8..59b6681 100644 --- a/src/cnpj/cnpj_test.go +++ b/src/cnpj/cnpj_test.go @@ -2,76 +2,111 @@ package cnpj import ( "testing" -) -func TestIsValid(t *testing.T) { - // Test case 1: CNPJ with valid check digits - err := IsValid("11.222.333/0001-81") - if err != nil { - t.Errorf("IsValid(\"11.222.333/0001-81\") returned an unexpected error: %v", err) - } + iface "github.com/potatowski/brazilcode/src/interface" +) - // Test case 2: CNPJ with invalid check digits - err = IsValid("11.222.333/0001-82") - expectedErr := ErrCNPJInvalid - if err == nil || err != expectedErr { - t.Errorf("IsValid(\"11.222.333/0001-82\") returned an unexpected error: %v; expected %v", err, expectedErr) - } +var doc iface.Document = CNPJ{} - // Test case 3: CNPJ with less than 14 digits - err = IsValid("11.222.333/0001-8") - expectedErr = ErrCNPJInvalidLength - if err == nil || err != expectedErr { - t.Errorf("IsValid(\"11.222.333/0001-8\") returned an unexpected error: %v; expected %v", err, expectedErr) - } - - // Test case 4: CNPJ with more than 14 digits - err = IsValid("11.222.333/0001-810") - expectedErr = ErrCNPJInvalidLength - if err == nil || err != expectedErr { - t.Errorf("IsValid(\"11.222.333/0001-810\") returned an unexpected error: %v; expected %v", err, expectedErr) - } +func TestIsValid(t *testing.T) { - // Test case 5: CNPJ with invalid characters - err = IsValid("11.222.333/00a1-81") - expectedErr = ErrCNPJInvalidLength - if err == nil || err != expectedErr { - t.Errorf("IsValid(\"11.222.333/00a1-81\") returned an unexpected error: %v; expected %v", err, expectedErr) + testCases := []struct { + name string + doc string + expected error + }{ + { + name: "CNPJ with valid check digits", + doc: "11.222.333/0001-81", + expected: nil, + }, + { + name: "CNPJ with invalid check digits", + doc: "11.222.333/0001-82", + expected: ErrCNPJInvalid, + }, + { + name: "CNPJ with less than 14 digits", + doc: "11.222.333/0001-8", + expected: ErrCNPJInvalidLength, + }, + { + name: "CNPJ with more than 14 digits", + doc: "11.222.333/0001-810", + expected: ErrCNPJInvalidLength, + }, + { + name: "CNPJ with invalid characters", + doc: "11.222.333/00a1-81", + expected: ErrCNPJInvalidLength, + }, + { + name: "CNPJ with invalid check digits", + doc: "11.222.333/0001-01", + expected: ErrCNPJInvalid, + }, } - // Test case 6: CNPJ with invalid check digits - err = IsValid("11.222.333/0001-01") - expectedErr = ErrCNPJInvalid - if err == nil || err != expectedErr { - t.Errorf("IsValid(\"11.222.333/0001-82\") returned an unexpected error: %v; expected %v", err, expectedErr) + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + err := doc.IsValid(tc.doc) + if err != tc.expected { + t.Errorf("Expected error to be '%v' but got '%v'", tc.expected, err) + } + }) } } func TestFormat(t *testing.T) { - // Test Case 1: CNPJ with valid check digits - cnpj := "11222333000181" - formattedCnpj, err := Format(cnpj) - if err != nil { - t.Errorf("unexpected error: %v", err) + testCases := []struct { + name string + doc string + expected string + expectedError error + }{ + { + name: "Valid CNPJ", + doc: "11222333000181", + expected: "11.222.333/0001-81", + expectedError: nil, + }, + { + name: "Invalid CNPJ - wrong length", + doc: "112223330001", + expected: "", + expectedError: ErrCNPJInvalidLength, + }, + { + name: "Invalid CNPJ - wrong first digit", + doc: "11222333000111", + expected: "", + expectedError: ErrCNPJInvalid, + }, + { + name: "Invalid CNPJ - wrong second digit", + doc: "11222333000182", + expected: "", + expectedError: ErrCNPJInvalid, + }, } - expectedResult := "11.222.333/0001-81" - if formattedCnpj != expectedResult { - t.Errorf("unexpected result: expected %v, got %v", expectedResult, formattedCnpj) - } + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + result, err := doc.Format(tc.doc) + if err != nil && err != tc.expectedError { + t.Errorf("Expected error to be '%v' but got '%v'", tc.expectedError, err) + } - // Test Case 2: CNPJ with invalid check digits - cnpj = "11222333000182" - _, err = Format(cnpj) - expectedErr := ErrCNPJInvalid - if err == nil || err != expectedErr { - t.Errorf("Format(\"11222333000182\") returned an unexpected error: %v; expected %v", err, expectedErr) + if result != tc.expected { + t.Errorf("Expected result to be '%v' but got '%v'", tc.expected, result) + } + }) } } func TestGenerate(t *testing.T) { - cnpj, err := Generate() + cnpj, err := doc.Generate() if err != nil { t.Errorf("unexpected error: %v", err) } diff --git a/src/cpf/cpf.go b/src/cpf/cpf.go index b053a41..5587f45 100644 --- a/src/cpf/cpf.go +++ b/src/cpf/cpf.go @@ -4,21 +4,23 @@ import ( "errors" "fmt" - "github.com/potatowski/brazilcode/src" + "github.com/potatowski/brazilcode/src/utils" ) var ( - ErrCPFInvalidLength = errors.New("Invalid CPF length") - ErrCPFInvalid = errors.New("Invalid CPF") + ErrCPFInvalidLength = errors.New("invalid CPF length") + ErrCPFInvalid = errors.New("invalid CPF") ) +type CPF struct{} + /* IsValid check if the CPF is valid - @param {string} doc - @return {error} */ -func IsValid(doc string) error { - doc = src.RemoveChar(doc) +func (iDoc CPF) IsValid(doc string) error { + doc = utils.RemoveChar(doc) if len(doc) != 11 { return ErrCPFInvalidLength } @@ -28,7 +30,7 @@ func IsValid(doc string) error { sum += int(doc[i]-'0') * (10 - i) } - firstDigit := src.GetDigit(sum) + firstDigit := utils.GetDigit(sum) if firstDigit != int(doc[9]-'0') { return ErrCPFInvalid } @@ -38,7 +40,7 @@ func IsValid(doc string) error { sum += int(doc[i]-'0') * (11 - i) } - secondDigit := src.GetDigit(sum) + secondDigit := utils.GetDigit(sum) if secondDigit != int(doc[10]-'0') { return ErrCPFInvalid @@ -52,8 +54,8 @@ Format is to format the CPF - @param {string} doc - @return {string} */ -func Format(doc string) (string, error) { - if err := IsValid(doc); err != nil { +func (iDoc CPF) Format(doc string) (string, error) { + if err := iDoc.IsValid(doc); err != nil { return "", err } @@ -64,24 +66,24 @@ func Format(doc string) (string, error) { Generate is to create a random CPF - @return {string, error} */ -func Generate() (string, error) { - cpf := src.GenerateRandomDoc(9, 9) +func (iDoc CPF) Generate() (string, error) { + cpf := utils.GenerateRandomDoc(9, 9) - sum, err := src.Calculator(cpf, 10) + sum, err := utils.Calculator(cpf, 10) if err != nil { return "", err } - cpf += fmt.Sprintf("%d", src.GetDigit(sum)) + cpf += fmt.Sprintf("%d", utils.GetDigit(sum)) - sum, err = src.Calculator(cpf, 11) + sum, err = utils.Calculator(cpf, 11) if err != nil { return "", err } - cpf += fmt.Sprintf("%d", src.GetDigit(sum)) + cpf += fmt.Sprintf("%d", utils.GetDigit(sum)) - if err := IsValid(cpf); err != nil { + if err := iDoc.IsValid(cpf); err != nil { return "", err } diff --git a/src/cpf/cpf_test.go b/src/cpf/cpf_test.go index 14e565b..ef419ab 100644 --- a/src/cpf/cpf_test.go +++ b/src/cpf/cpf_test.go @@ -2,8 +2,12 @@ package cpf import ( "testing" + + iface "github.com/potatowski/brazilcode/src/interface" ) +var doc iface.Document = CPF{} + func TestIsValid(t *testing.T) { testCases := []struct { name string @@ -34,7 +38,7 @@ func TestIsValid(t *testing.T) { for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { - err := IsValid(tc.doc) + err := doc.IsValid(tc.doc) if err != tc.expected { t.Errorf("Expected error to be '%v' but got '%v'", tc.expected, err) } @@ -77,7 +81,7 @@ func TestFormat(t *testing.T) { for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { - result, err := Format(tc.doc) + result, err := doc.Format(tc.doc) if err != nil && err != tc.expectedError { t.Errorf("Expected error to be '%v' but got '%v'", tc.expectedError, err) } @@ -90,12 +94,12 @@ func TestFormat(t *testing.T) { } func TestGenerate(t *testing.T) { - cnpj, err := Generate() + cpf, err := doc.Generate() if err != nil { t.Errorf("unexpected error: %v", err) } - if len(cnpj) != 11 { + if len(cpf) != 11 { t.Errorf("unexpected result: generated CPF has invalid length") } } diff --git a/src/interface/document.go b/src/interface/document.go new file mode 100644 index 0000000..5f465f9 --- /dev/null +++ b/src/interface/document.go @@ -0,0 +1,23 @@ +package iface + +/* +Document defines an interface for handling document-related operations. +It provides methods for validating, formatting, and generating documents. + +Methods: + + - IsValid(doc string) error: + Validates the given document string and returns an error if it is invalid. + + - Format(doc string) (string, error): + Formats the given document string into a standardized format and returns + the formatted string along with any potential error. + + - Generate() (string, error): + Generates a new document string and returns it along with any potential error. +*/ +type Document interface { + IsValid(doc string) error + Format(doc string) (string, error) + Generate() (string, error) +} diff --git a/src/utils.go b/src/utils/calculator.go similarity index 63% rename from src/utils.go rename to src/utils/calculator.go index fa3b40b..b7080b2 100644 --- a/src/utils.go +++ b/src/utils/calculator.go @@ -1,10 +1,7 @@ -package src +package utils import ( "errors" - "fmt" - "math/rand" - "regexp" ) /* @@ -46,43 +43,6 @@ func Calculator(doc string, first int) (int, error) { return sum, nil } -/* -GetDigit returns the digit of the document - - @param {int} sum - - @return {int} -*/ -func GetDigit(sum int) int { - rest := sum % 11 - if rest < 2 { - return 0 - } - return 11 - rest -} - -/* -RemoveChar returns the string without special characters - - @param {string} str - - @return {string} -*/ -func RemoveChar(str string) string { - return regexp.MustCompile("[^0-9]+").ReplaceAllString(str, "") -} - -/* -GenerateRandomDoc returns a random document - - @param {int} len - - @param {int} numberInRand - - @return {string} -*/ -func GenerateRandomDoc(len, numberInRand int) string { - var doc string - for i := 0; i < len; i++ { - doc += fmt.Sprintf("%d", rand.Intn(numberInRand)) - } - - return doc -} - /* CalculatorCNH returns the sum of the document - @param {string} doc @@ -149,23 +109,3 @@ func CalculateCNHDVs(cnh string) (int, int, error) { return dv1, dv2, nil } - -/* -GetDigitMoreThen returns the digit of the document - - @param {int} sum - - @param {bool} withAux - - @return {int} -*/ -func GetDigitMoreThen(sum int, withAux bool) (result int) { - digitCheck := sum % 11 - aux := 0 - if digitCheck >= 10 { - digitCheck = 0 - if withAux { - aux = 2 - } - } - - result = digitCheck - aux*2 - return result -} diff --git a/src/utils/calculator_test.go b/src/utils/calculator_test.go new file mode 100644 index 0000000..4b20259 --- /dev/null +++ b/src/utils/calculator_test.go @@ -0,0 +1,94 @@ +package utils_test + +import ( + "testing" + + "github.com/potatowski/brazilcode/src/utils" +) + +func TestCalculator(t *testing.T) { + // Test case 1: doc with less than 10 characters and first positive + result, err := utils.Calculator("1234", 4) + expected := 20 + if err != nil { + t.Errorf("unexpected error: %v", err) + } + if result != expected { + t.Errorf("Calculator(\"1234\", 4) = %d; expected %d", result, expected) + } + + // Test case 2: doc with more than 10 characters and first positive + result, err = utils.Calculator("12345678901", 1) + expected = 244 + if err != nil { + t.Errorf("unexpected error: %v", err) + } + if result != expected { + t.Errorf("Calculator(\"12345678901\", 1) = %d; expected %d", result, expected) + } + + // Test case 3: document equals "" + _, err = utils.Calculator("", 1) + if err == nil { + t.Errorf("expected an error about document") + } + + // Test case 4: param fisrt more than 0 + _, err = utils.Calculator("12345", -2) + if err == nil { + t.Errorf("expected an error about first more than 0") + } + + // Test case 5: param first equals 0 + _, err = utils.Calculator("12345", 0) + if err == nil { + t.Errorf("expected an error about first equals 0") + } +} +func TestCalculatorCNH(t *testing.T) { + doc := "12345678901" + first := 2 + incrementType := "increment" + + result, err := utils.CalculatorCNH(doc, first, incrementType) + if err != nil { + t.Errorf("CalculatorCNH(%q, %d, %q) returned an error: %v", doc, first, incrementType, err) + } + + expectedResult := 330 + if result != expectedResult { + t.Errorf("CalculatorCNH(%q, %d, %q) = %d, expected %d", doc, first, incrementType, result, expectedResult) + } + + incrementType = "invalid" + _, err = utils.CalculatorCNH(doc, first, incrementType) + if err == nil { + t.Errorf("CalculatorCNH(%q, %d, %q) did not return an error for invalid incrementType", doc, first, incrementType) + } +} + +func TestCalculateCNHDVs(t *testing.T) { + // Test case 1: valid CNH + cnh := "97625655678" + + dv1, dv2, err := utils.CalculateCNHDVs(cnh) + if err != nil { + t.Errorf("CalculateCNHDVs(%q) returned an error: %v", cnh, err) + } + + expectedDv1 := 7 + if dv1 != expectedDv1 { + t.Errorf("CalculateCNHDVs(%q) dv1 = %d, expected %d", cnh, dv1, expectedDv1) + } + expectedDv2 := 8 + if dv2 != expectedDv2 { + t.Errorf("CalculateCNHDVs(%q) dv2 = %d, expected %d", cnh, dv2, expectedDv2) + } + + // Test case 2: invalid CNH length + cnh = "12345678" + _, _, err = utils.CalculateCNHDVs(cnh) + if err == nil { + t.Errorf("CalculateCNHDVs(%q) did not return an error for invalid CNH", cnh) + } +} diff --git a/src/utils/digit.go b/src/utils/digit.go new file mode 100644 index 0000000..01c3970 --- /dev/null +++ b/src/utils/digit.go @@ -0,0 +1,34 @@ +package utils + +/* +GetDigit returns the digit of the document + - @param {int} sum + - @return {int} +*/ +func GetDigit(sum int) int { + rest := sum % 11 + if rest < 2 { + return 0 + } + return 11 - rest +} + +/* +GetDigitMoreThen returns the digit of the document + - @param {int} sum + - @param {bool} withAux + - @return {int} +*/ +func GetDigitMoreThen(sum int, withAux bool) (result int) { + digitCheck := sum % 11 + aux := 0 + if digitCheck >= 10 { + digitCheck = 0 + if withAux { + aux = 2 + } + } + + result = digitCheck - aux*2 + return result +} diff --git a/src/utils/digit_test.go b/src/utils/digit_test.go new file mode 100644 index 0000000..6d05b4b --- /dev/null +++ b/src/utils/digit_test.go @@ -0,0 +1,64 @@ +package utils_test + +import ( + "testing" + + "github.com/potatowski/brazilcode/src/utils" +) + +func TestGetDigit(t *testing.T) { + // Test case 1: sum with rest less than 2 + result := utils.GetDigit(287) + expected := 0 + if result != expected { + t.Errorf("GetDigit(22) = %d; expected %d", result, expected) + } + + // Test case 2: sum with rest more than or equals 2 + result = utils.GetDigit(237) + expected = 5 + if result != expected { + t.Errorf("GetDigit(27) = %d; expected %d", result, expected) + } +} + +func TestGetDigitMoreThen(t *testing.T) { + // Test case 1: valid sum with aux + sum := 20 + withAux := true + expectedResult := 9 + + result := utils.GetDigitMoreThen(sum, withAux) + if result != expectedResult { + t.Errorf("GetDigitMoreThen(%d, %t) = %d, expected %d", sum, withAux, result, expectedResult) + } + + // Test case 2: valid sum without aux + sum = 20 + withAux = false + expectedResult = 9 + + result = utils.GetDigitMoreThen(sum, withAux) + if result != expectedResult { + t.Errorf("GetDigitMoreThen(%d, %t) = %d, expected %d", sum, withAux, result, expectedResult) + } + + // Test case 3: digit check more than 9 + sum = 21 + withAux = false + expectedResult = 0 + result = utils.GetDigitMoreThen(sum, withAux) + if result != expectedResult { + t.Errorf("GetDigitMoreThen(%d, %t) = %d, expected %d", sum, withAux, result, expectedResult) + } + + // Test case 4: sum less than 0 + sum = -1 + withAux = true + expectedResult = -1 + + result = utils.GetDigitMoreThen(sum, withAux) + if result != expectedResult { + t.Errorf("GetDigitMoreThen(%d, %t) = %d, expected %d", sum, withAux, result, expectedResult) + } +} diff --git a/src/utils/text.go b/src/utils/text.go new file mode 100644 index 0000000..0f26b8c --- /dev/null +++ b/src/utils/text.go @@ -0,0 +1,31 @@ +package utils + +import ( + "fmt" + "math/rand" + "regexp" +) + +/* +RemoveChar returns the string without special characters + - @param {string} str + - @return {string} +*/ +func RemoveChar(str string) string { + return regexp.MustCompile("[^0-9]+").ReplaceAllString(str, "") +} + +/* +GenerateRandomDoc returns a random document + - @param {int} len + - @param {int} numberInRand + - @return {string} +*/ +func GenerateRandomDoc(len, numberInRand int) string { + var doc string + for i := 0; i < len; i++ { + doc += fmt.Sprintf("%d", rand.Intn(numberInRand)) + } + + return doc +} diff --git a/src/utils/text_test.go b/src/utils/text_test.go new file mode 100644 index 0000000..90c2b24 --- /dev/null +++ b/src/utils/text_test.go @@ -0,0 +1,59 @@ +package utils_test + +import ( + "math/rand" + "testing" + "time" + + "github.com/potatowski/brazilcode/src/utils" +) + +func TestRemoveChar(t *testing.T) { + // Test case 1: str with only numbers + result := utils.RemoveChar("12345") + expected := "12345" + if result != expected { + t.Errorf("RemoveChar(\"12345\") = %s; expected %s", result, expected) + } + + // Test case 2: str with only letters + result = utils.RemoveChar("abcde") + expected = "" + if result != expected { + t.Errorf("RemoveChar(\"abcde\") = %s; expected %s", result, expected) + } + + // Test case 3: str with numbers and letters + result = utils.RemoveChar("1a2b3c4d5e") + expected = "12345" + if result != expected { + t.Errorf("RemoveChar(\"1a2b3c4d5e\") = %s; expected %s", result, expected) + } + + // Test case 4: str equals "" + result = utils.RemoveChar("") + expected = "" + if result != expected { + t.Errorf("RemoveChar(\"\") = %s; expected %s", result, expected) + } +} + +func TestGenerateRandomDoc(t *testing.T) { + rand.Seed(time.Now().UnixNano()) + + length := 10 + numberInRand := 10 + doc := utils.GenerateRandomDoc(length, numberInRand) + + expectedLen := length + if len(doc) != expectedLen { + t.Errorf("GenerateRandomDoc() = %q, expected length %d", doc, expectedLen) + } + + for _, char := range doc { + if !('0' <= char && char <= '9') { + t.Errorf("GenerateRandomDoc() = %q, contains non-digit character %q", doc, char) + break + } + } +} diff --git a/src/utils_test.go b/src/utils_test.go deleted file mode 100644 index c5448d0..0000000 --- a/src/utils_test.go +++ /dev/null @@ -1,204 +0,0 @@ -package src_test - -import ( - "math/rand" - "testing" - "time" - - "github.com/potatowski/brazilcode/src" -) - -func TestCalculator(t *testing.T) { - // Test case 1: doc with less than 10 characters and first positive - result, err := src.Calculator("1234", 4) - expected := 20 - if err != nil { - t.Errorf("unexpected error: %v", err) - } - if result != expected { - t.Errorf("Calculator(\"1234\", 4) = %d; expected %d", result, expected) - } - - // Test case 2: doc with more than 10 characters and first positive - result, err = src.Calculator("12345678901", 1) - expected = 244 - if err != nil { - t.Errorf("unexpected error: %v", err) - } - if result != expected { - t.Errorf("Calculator(\"12345678901\", 1) = %d; expected %d", result, expected) - } - - // Test case 3: document equals "" - _, err = src.Calculator("", 1) - if err == nil { - t.Errorf("expected an error about document") - } - - // Test case 4: param fisrt more than 0 - _, err = src.Calculator("12345", -2) - if err == nil { - t.Errorf("expected an error about first more than 0") - } - - // Test case 5: param first equals 0 - _, err = src.Calculator("12345", 0) - if err == nil { - t.Errorf("expected an error about first equals 0") - } -} - -func TestGetDigit(t *testing.T) { - // Test case 1: sum with rest less than 2 - result := src.GetDigit(287) - expected := 0 - if result != expected { - t.Errorf("GetDigit(22) = %d; expected %d", result, expected) - } - - // Test case 2: sum with rest more than or equals 2 - result = src.GetDigit(237) - expected = 5 - if result != expected { - t.Errorf("GetDigit(27) = %d; expected %d", result, expected) - } -} - -func TestRemoveChar(t *testing.T) { - // Test case 1: str with only numbers - result := src.RemoveChar("12345") - expected := "12345" - if result != expected { - t.Errorf("RemoveChar(\"12345\") = %s; expected %s", result, expected) - } - - // Test case 2: str with only letters - result = src.RemoveChar("abcde") - expected = "" - if result != expected { - t.Errorf("RemoveChar(\"abcde\") = %s; expected %s", result, expected) - } - - // Test case 3: str with numbers and letters - result = src.RemoveChar("1a2b3c4d5e") - expected = "12345" - if result != expected { - t.Errorf("RemoveChar(\"1a2b3c4d5e\") = %s; expected %s", result, expected) - } - - // Test case 4: str equals "" - result = src.RemoveChar("") - expected = "" - if result != expected { - t.Errorf("RemoveChar(\"\") = %s; expected %s", result, expected) - } -} - -func TestGenerateRandomDoc(t *testing.T) { - rand.Seed(time.Now().UnixNano()) - - length := 10 - numberInRand := 10 - doc := src.GenerateRandomDoc(length, numberInRand) - - expectedLen := length - if len(doc) != expectedLen { - t.Errorf("GenerateRandomDoc() = %q, expected length %d", doc, expectedLen) - } - - for _, char := range doc { - if !('0' <= char && char <= '9') { - t.Errorf("GenerateRandomDoc() = %q, contains non-digit character %q", doc, char) - break - } - } -} - -func TestCalculatorCNH(t *testing.T) { - doc := "12345678901" - first := 2 - incrementType := "increment" - - result, err := src.CalculatorCNH(doc, first, incrementType) - if err != nil { - t.Errorf("CalculatorCNH(%q, %d, %q) returned an error: %v", doc, first, incrementType, err) - } - - expectedResult := 330 - if result != expectedResult { - t.Errorf("CalculatorCNH(%q, %d, %q) = %d, expected %d", doc, first, incrementType, result, expectedResult) - } - - incrementType = "invalid" - _, err = src.CalculatorCNH(doc, first, incrementType) - if err == nil { - t.Errorf("CalculatorCNH(%q, %d, %q) did not return an error for invalid incrementType", doc, first, incrementType) - } -} - -func TestCalculateCNHDVs(t *testing.T) { - // Test case 1: valid CNH - cnh := "97625655678" - - dv1, dv2, err := src.CalculateCNHDVs(cnh) - if err != nil { - t.Errorf("CalculateCNHDVs(%q) returned an error: %v", cnh, err) - } - - expectedDv1 := 7 - if dv1 != expectedDv1 { - t.Errorf("CalculateCNHDVs(%q) dv1 = %d, expected %d", cnh, dv1, expectedDv1) - } - expectedDv2 := 8 - if dv2 != expectedDv2 { - t.Errorf("CalculateCNHDVs(%q) dv2 = %d, expected %d", cnh, dv2, expectedDv2) - } - - // Test case 2: invalid CNH length - cnh = "12345678" - _, _, err = src.CalculateCNHDVs(cnh) - if err == nil { - t.Errorf("CalculateCNHDVs(%q) did not return an error for invalid CNH", cnh) - } -} - -func TestGetDigitMoreThen(t *testing.T) { - // Test case 1: valid sum with aux - sum := 20 - withAux := true - expectedResult := 9 - - result := src.GetDigitMoreThen(sum, withAux) - if result != expectedResult { - t.Errorf("GetDigitMoreThen(%d, %t) = %d, expected %d", sum, withAux, result, expectedResult) - } - - // Test case 2: valid sum without aux - sum = 20 - withAux = false - expectedResult = 9 - - result = src.GetDigitMoreThen(sum, withAux) - if result != expectedResult { - t.Errorf("GetDigitMoreThen(%d, %t) = %d, expected %d", sum, withAux, result, expectedResult) - } - - // Test case 3: digit check more than 9 - sum = 21 - withAux = false - expectedResult = 0 - result = src.GetDigitMoreThen(sum, withAux) - if result != expectedResult { - t.Errorf("GetDigitMoreThen(%d, %t) = %d, expected %d", sum, withAux, result, expectedResult) - } - - // Test case 4: sum less than 0 - sum = -1 - withAux = true - expectedResult = -1 - - result = src.GetDigitMoreThen(sum, withAux) - if result != expectedResult { - t.Errorf("GetDigitMoreThen(%d, %t) = %d, expected %d", sum, withAux, result, expectedResult) - } -} diff --git a/src/voterRegistration/voterRegistration.go b/src/voterRegistration/voterRegistration.go index b3d2ccf..6f2b755 100644 --- a/src/voterRegistration/voterRegistration.go +++ b/src/voterRegistration/voterRegistration.go @@ -4,7 +4,7 @@ import ( "errors" "fmt" - "github.com/potatowski/brazilcode/src" + "github.com/potatowski/brazilcode/src/utils" ) var ufToCode = map[string]string{ @@ -70,19 +70,21 @@ var codeToUf = map[string]string{ } var ( - ErrVoterRegistrationInvalid = errors.New("Invalid Voter Registration") - ErrVoterRegistrationInvalidLength = errors.New("Invalid Voter Registration length") - ErrVoterRegistrationInvalidUF = errors.New("Invalid UF") - ErrVoterRegistrationLimit = errors.New("Invalid Limit") + ErrVoterRegistrationInvalid = errors.New("invalid Voter Registration") + ErrVoterRegistrationInvalidLength = errors.New("invalid Voter Registration length") + ErrVoterRegistrationInvalidUF = errors.New("invalid UF") + ErrVoterRegistrationLimit = errors.New("invalid Limit") ) +type VoterRegistration struct{} + /* IsValid check if the Voter Registration is valid - @param {string} - @return {error} */ -func IsValid(voterRegistration string) error { - voterRegistration = src.RemoveChar(voterRegistration) +func (iDoc VoterRegistration) IsValid(voterRegistration string) error { + voterRegistration = utils.RemoveChar(voterRegistration) if len(voterRegistration) != 12 { return ErrVoterRegistrationInvalidLength } @@ -96,7 +98,7 @@ func IsValid(voterRegistration string) error { if err != nil { return err } - dv1 := src.GetDigitMoreThen(sum, false) + dv1 := utils.GetDigitMoreThen(sum, false) if dv1 != int(voterRegistration[10]-'0') { fmt.Println(dv1, voterRegistration[10]-'0') return ErrVoterRegistrationInvalid @@ -107,7 +109,7 @@ func IsValid(voterRegistration string) error { return err } - dv2 := src.GetDigitMoreThen(sum, false) + dv2 := utils.GetDigitMoreThen(sum, false) if dv2 != int(voterRegistration[11]-'0') { return ErrVoterRegistrationInvalid } @@ -120,8 +122,8 @@ Format is to format the Voter Registration - @param {string} voterRegistration - @return {string} */ -func Format(voterRegistration string) (string, error) { - if err := IsValid(voterRegistration); err != nil { +func (iDoc VoterRegistration) Format(voterRegistration string) (string, error) { + if err := iDoc.IsValid(voterRegistration); err != nil { return "", err } @@ -138,17 +140,15 @@ Generate is to create a random Voter Registration - @param {string} uf - @return {string, error} */ -func Generate(uf string) (string, error) { - voter := src.GenerateRandomDoc(8, 9) +func (iDoc VoterRegistration) Generate() (string, error) { + voter := utils.GenerateRandomDoc(8, 9) sum, err := calc(voter, 2, 9) if err != nil { return "", err } - dv1 := src.GetDigitMoreThen(sum, false) - if uf == "" { - uf = getRandomUF() - } + dv1 := utils.GetDigitMoreThen(sum, false) + uf := getRandomUF() ufRegister := ufToCode[uf] if ufRegister == "" { @@ -162,9 +162,9 @@ func Generate(uf string) (string, error) { return "", err } - dv2 := src.GetDigitMoreThen(sum, false) + dv2 := utils.GetDigitMoreThen(sum, false) voter += fmt.Sprintf("%d", dv2) - err = IsValid(voter) + err = iDoc.IsValid(voter) if err != nil { return "", err } diff --git a/src/voterRegistration/voterRegistration_test.go b/src/voterRegistration/voterRegistration_test.go index c81bfc8..2289ada 100644 --- a/src/voterRegistration/voterRegistration_test.go +++ b/src/voterRegistration/voterRegistration_test.go @@ -2,8 +2,12 @@ package voterRegistration import ( "testing" + + iface "github.com/potatowski/brazilcode/src/interface" ) +var doc iface.Document = VoterRegistration{} + func TestIsValid(t *testing.T) { tests := []struct { name string @@ -39,7 +43,7 @@ func TestIsValid(t *testing.T) { for _, test := range tests { t.Run(test.name, func(t *testing.T) { - err := IsValid(test.voterRegistration) + err := doc.IsValid(test.voterRegistration) if err != test.expectedError { t.Errorf("Expected error %v but got %v", test.expectedError, err) @@ -89,7 +93,7 @@ func TestFormat(t *testing.T) { for _, test := range tests { t.Run(test.name, func(t *testing.T) { - result, err := Format(test.voterRegistration) + result, err := doc.Format(test.voterRegistration) if err != test.expectedError { t.Errorf("Expected error %v but got %v", test.expectedError, err) } @@ -102,33 +106,7 @@ func TestFormat(t *testing.T) { } func TestGenerate(t *testing.T) { - // Test case 1: valid UF - uf := "MG" - voter, err := Generate(uf) - if err != nil { - t.Errorf("unexpected error: %v", err) - } - - if len(voter) != 12 { - t.Errorf("expected length 12, but got length %d", len(voter)) - } - - code := ufToCode[uf] - - if code != voter[8:10] { - t.Errorf("expected %s uf code, but got %s", uf, voter[8:10]) - } - - // Test case 2: invalid UF - uf = "XX" - _, err = Generate(uf) - if err == nil { - t.Errorf("expected error, but got nil") - } - - // Test case 3: empty UF - uf = "" - voter, err = Generate(uf) + _, err := doc.Generate() if err != nil { t.Errorf("unexpected error: %v", err) }