[Feature/55] :: flexibility improvements#56
Conversation
📝 WalkthroughWalkthroughEste pull request refatora a API principal da biblioteca mocai, substituindo parâmetros posicionais por padrão de opções funcionais no Changes
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutos Possibly related PRs
Suggested labels
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 1 | ❌ 2❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (1 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 10
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
pkg/mocai/entities/voteregistration/countries/brazilian_vote_registration.go (1)
82-94:⚠️ Potential issue | 🟠 MajorO fallback de idioma está inconsistente com a API pública.
NewBrazilianVoteRegistration()fixaptbr, masNewBrazilianVoteRegistrationCustom()cai paraen_usquandolang == ""ou quando o idioma não é suportado. Isso faz o comportamento mudar só pela escolha do entrypoint e pode devolver chaves cruas de tradução.💡 Ajuste sugerido
func NewBrazilianVoteRegistrationCustom(lang string, isFormatted bool, rnd translations.RandSource) (*BrazilianVoteRegistration, error) { if lang == "" { - lang = "en_us" + lang = "ptbr" } @@ if !supported { - lang = "en_us" + lang = "ptbr" }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@pkg/mocai/entities/voteregistration/countries/brazilian_vote_registration.go` around lines 82 - 94, The language fallback in NewBrazilianVoteRegistrationCustom is inconsistent with NewBrazilianVoteRegistration (which uses "ptbr"); change NewBrazilianVoteRegistrationCustom so that when lang == "" or when the translations check for "invalid_vote_registration" indicates unsupported, it falls back to "ptbr" (not "en_us"), keeping the same behavior as NewBrazilianVoteRegistration and avoiding returning raw translation keys; update the lang default and unsupported-path assignment accordingly while preserving the translations.Get(...) check and rnd/isFormatted handling.
🧹 Nitpick comments (9)
pkg/mocai/entities/phone/generator.go (1)
27-44: Verificação deareaCodevazio pode ser redundante ou insuficiente.A verificação em
if areaCode == ""na linha 38 ocorre após selecionar um elemento da sliceareaCodes. Se a slice contém strings vazias, este check falha corretamente. Porém, como já existe uma verificaçãolen(areaCodes) == 0na linha 29, considere se a validação de strings vazias dentro da slice deveria ser feita de forma consistente com outros geradores (comoaddress/generator.goque validaTrimSpaceem cada item).♻️ Sugestão para validação consistente
func generatePhone(lang string, rnd translations.RandSource) (*Phone, error) { areaCodes := translations.GetList(lang, "phone_area_code") if len(areaCodes) == 0 { return nil, fmt.Errorf("%w: %s", ErrNoAreaCodes, translations.Get(lang, "no_data_available_for_area_codes")) } + for _, code := range areaCodes { + if strings.TrimSpace(code) == "" { + return nil, fmt.Errorf("%w: empty area code in list", ErrNoAreaCodes) + } + } if rnd == nil { rnd = translations.DefaultRandSource() } areaCode := areaCodes[rnd.Intn(len(areaCodes))] number := fmt.Sprintf("9%08d", rnd.Intn(100000000)) - if areaCode == "" { - return nil, fmt.Errorf("%w: %s", ErrGeneratingPhone, translations.Get(lang, "error_generating_phone")) - } return &Phone{ AreaCode: areaCode, Number: number, }, nil }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@pkg/mocai/entities/phone/generator.go` around lines 27 - 44, In generatePhone, ensure areaCodes from translations.GetList(lang, "phone_area_code") are validated for non-empty (trimmed) entries like other generators: filter the areaCodes slice to remove strings where strings.TrimSpace(item) == "" before checking length, return ErrNoAreaCodes with the existing translations.Get message if the filtered slice is empty, then select areaCode using rnd.Intn on the filtered slice; remove the redundant post-selection empty check (or keep it only as a defensive panic) and keep returning ErrGeneratingPhone using translations.Get(lang, "error_generating_phone") only when generation truly fails.pkg/mocai/entities/nationalid/countries/brazilian_national_id_test.go (1)
57-62: TesteTestRGErrorIsSentinelnão testa um cenário real de erro.O teste apenas verifica que
errors.Is(ErrConvertingDigit, ErrConvertingDigit)retornatrue, o que é sempre verdade por definição. Um teste mais útil seria provocar uma condição de erro real e verificar se o erro retornado é o sentinela esperado.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@pkg/mocai/entities/nationalid/countries/brazilian_national_id_test.go` around lines 57 - 62, The test TestRGErrorIsSentinel currently only compares ErrConvertingDigit to itself; instead produce a real wrapped error and assert errors.Is identifies the sentinel: create an error that wraps ErrConvertingDigit (e.g., via fmt.Errorf("failed converting digit: %w", ErrConvertingDigit) or using errors.Join/wrap from the codebase) and replace the current assertion with errors.Is(wrappedErr, ErrConvertingDigit); reference the test name TestRGErrorIsSentinel and the sentinel ErrConvertingDigit when making the change.pkg/mocai/entities/certificate/countries/brazilian_certificates_test.go (1)
50-67: Considere usar constantes exportadas para tipos de certidão.O teste verifica valores literais (1, 2, 3) para tipos de certidão. Se essas constantes forem exportadas no futuro, usar as constantes ao invés de valores literais tornaria os testes mais resilientes a mudanças.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@pkg/mocai/entities/certificate/countries/brazilian_certificates_test.go` around lines 50 - 67, Replace the literal type checks in TestCertificateTypes with the exported certificate type constants instead of numbers: update the assertions that inspect certs.BirthCertificate.Type, certs.MarriageCertificate.Type and certs.DeathCertificate.Type (produced by NewBrazilCertificatesCustom) to compare against the package's exported constants (e.g., BirthCertificateType, MarriageCertificateType, DeathCertificateType or whichever exported names exist) and adjust imports if necessary so the test uses those constants rather than 1, 2, 3.pkg/mocai/entities/cnpj/generator_test.go (1)
70-88: ExtrairfixedRandpara um pacote de test helpers.O helper
fixedRand(versão de sequência) é duplicado identicamente empkg/mocai/entities/cpf/generator_test.go. Considere centralizá-lo em um pacotetestutildentro deinternal/para evitar duplicação de código.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@pkg/mocai/entities/cnpj/generator_test.go` around lines 70 - 88, The duplicated test helper fixedRand (type fixedRand with method Intn) should be extracted into a shared internal testutil package: create an internal/testutil package exposing a fixedRand (or NewFixedRand) constructor and the same Intn behavior, move the implementation there, and update both generator_test.go files to import testutil and instantiate the helper from that package instead of duplicating the code; ensure the exported symbol names match usage and run tests to verify behavior remains identical.pkg/mocai/entities/cpf/generator_test.go (1)
74-79: O teste de erro sentinela é trivial e não valida o wrapping real.O teste
errors.Is(ErrInvalidCPF, ErrInvalidCPF)sempre retornarátruepara qualquer valor de erro. Para validar corretamente o padrão de sentinel error com wrapping (%w), considere testar um cenário onde o erro é retornado pela funçãoNewCPFe verificar seerrors.Is(wrappedErr, ErrInvalidCPF)funciona.♻️ Sugestão para teste mais significativo
func TestCPFErrorIsSentinel(t *testing.T) { - err := ErrInvalidCPF - if !errors.Is(err, ErrInvalidCPF) { - t.Error("expected ErrInvalidCPF to match with errors.Is") + // Verifica que o erro sentinela é compatível com errors.Is + wrappedErr := fmt.Errorf("%w: contexto adicional", ErrInvalidCPF) + if !errors.Is(wrappedErr, ErrInvalidCPF) { + t.Error("expected wrapped error to match ErrInvalidCPF with errors.Is") } }Isso requer adicionar
"fmt"aos imports.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@pkg/mocai/entities/cpf/generator_test.go` around lines 74 - 79, Replace the trivial self-comparison in TestCPFErrorIsSentinel with a wrapped-error scenario: call NewCPF with invalid input to obtain the error (or wrap ErrInvalidCPF via fmt.Errorf("%w", ErrInvalidCPF)) and then assert errors.Is(wrappedErr, ErrInvalidCPF) returns true; update TestCPFErrorIsSentinel to use the function that produces the error (NewCPF) and add the "fmt" import if you choose manual wrapping with fmt.Errorf.pkg/mocai/entities/cnpj/generator.go (1)
41-43: Inconsistência no padrão de erro comparado ao CPF.Na linha 42,
ErrInvalidCNPJLengthé retornado diretamente, enquanto emcpf/generator.go(linha 41), o erro é wrapped com uma mensagem localizada:fmt.Errorf("%w: %s", ErrInvalidCPF, translations.Get(lang, "invalid_cpf")).Para manter consistência no tratamento de erros e permitir mensagens localizadas, considere seguir o mesmo padrão.
♻️ Sugestão para consistência
A função
GenerateCNPJnão recebe o parâmetrolang, então seria necessário adicioná-lo para suportar mensagens localizadas, ou aceitar o erro não-localizado como design intencional para esta função.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@pkg/mocai/entities/cnpj/generator.go` around lines 41 - 43, The CNPJ generator returns ErrInvalidCNPJLength directly, causing inconsistency with CPF which wraps errors with localized messages; update GenerateCNPJ to accept a lang parameter (matching cpf/generator.go pattern) and when len(cnpj) != 14 return a wrapped error like fmt.Errorf("%w: %s", ErrInvalidCNPJ, translations.Get(lang, "invalid_cnpj")); ensure you reference ErrInvalidCNPJLength (or replace it with ErrInvalidCNPJ) and use translations.Get(lang, "invalid_cnpj") so error handling mirrors the CPF implementation (see GenerateCPF/ErrInvalidCPF usage).pkg/mocai/entities/voteregistration/countries/brazilian_vote_registration_test.go (1)
53-65: Os testes de erro sentinela são triviais.Assim como observado em
cpf/generator_test.go, os testeserrors.Is(ErrX, ErrX)sempre retornamtrue. Para validação mais significativa, considere testar cenários onde os erros são realmente retornados pelas funções de geração ou testar o wrapping comfmt.Errorf("%w", ...).🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@pkg/mocai/entities/voteregistration/countries/brazilian_vote_registration_test.go` around lines 53 - 65, The current TestVoteRegistrationErrorIsSentinel trivially compares each sentinel to itself; replace it with real error-origin tests: call the functions that can return these errors (e.g., the vote registration/validation/generation functions used elsewhere) and assert errors.Is(returnedErr, ErrInvalidVoteRegistration / ErrInvalidCheckDigit1 / ErrInvalidCheckDigit2); alternatively create a wrapped error with fmt.Errorf("%w", ErrInvalidCheckDigit1) and assert errors.Is on that wrapped error to verify sentinel matching (see cpf/generator_test.go for a pattern).pkg/mocai/mocker.go (2)
71-72: O caminho via provider perde oRandSourceda instância.
WithRandSourcesó atualizam.rndempkg/mocai/options.go:5-30, masGeneratePerson,GenerateCompanyeGenerateAddressempkg/mocai/provider.go:9-26não recebem esse valor. Se a intenção é manter determinismo por instância, o source precisa entrar nas interfaces — ou isso precisa ficar explícito na documentação do provider.Also applies to: 85-86, 104-105
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@pkg/mocai/mocker.go` around lines 71 - 72, The provider path is losing the instance RandSource because WithRandSource only sets m.rnd but provider methods GeneratePerson/GenerateCompany/GenerateAddress on personProvider/companyProvider/addressProvider don't accept it; update the provider interfaces to accept a RandSource (or add a SetRandSource method) and propagate m.rnd into calls from the methods in the Mocker (where you call personProvider.GeneratePerson, companyProvider.GenerateCompany, addressProvider.GenerateAddress), or alternatively pass m.rnd into those Generate* calls so the providers use the instance RNG; ensure symbols WithRandSource, m.rnd, GeneratePerson, GenerateCompany, GenerateAddress, personProvider, companyProvider and addressProvider are updated consistently.
56-66: Prefira retornar*Mockere deixar a interface no lado do consumo.Em Go,
NewXretornando interface costuma limitar a evolução da API pública sem ganho real. Quem quiser abstração ainda pode fazervar g MockGenerator = NewMocker(...).💡 Ajuste sugerido
-func NewMocker(opts ...Option) MockGenerator { +func NewMocker(opts ...Option) *Mocker { m := &Mocker{ lang: "ptbr", formatted: false, rnd: translations.DefaultRandSource(), } for _, opt := range opts { opt(m) } return m }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@pkg/mocai/mocker.go` around lines 56 - 66, Change NewMocker to return *Mocker instead of the MockGenerator interface: update the function signature NewMocker(opts ...Option) *Mocker and keep the constructor body as-is (it already constructs &Mocker). Ensure all Option functions and their types (those accepting m *Mocker) remain compatible, and update any call sites or tests that expect a MockGenerator to accept the concrete *Mocker (callers that need the interface can still assign var g MockGenerator = NewMocker(...)). Leave the MockGenerator interface declared but remove it from the public constructor return type.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@docs/localization/pt/README-PT.md`:
- Around line 5-6: The heading "#### [README (English)](/README.md)" is using h4
but should be h2 to preserve hierarchical order; update that Markdown heading
from "#### [README (English)](/README.md)" to "## [README
(English)](/README.md)" so it increments correctly from the document h1 to h2
and satisfies markdownlint/accessibility rules.
In `@pkg/mocai/entities/address/generator_test.go`:
- Around line 33-35: The test asserts Number must be positive but the generator
uses rnd.Intn(9999) (in generator.go) which can produce 0, so either relax the
test or fix the generator: if 0 is acceptable, change the test in
generator_test.go to assert addr.Number >= 0 (or remove the failing check); if 0
is not acceptable, change the generator's expression rnd.Intn(9999) to
rnd.Intn(9999) + 1 (in the function that creates addresses) so Number is always
> 0 and keep the existing test.
In `@pkg/mocai/entities/nationalid/countries/brazilian_national_id_test.go`:
- Around line 49-55: Rename the misleading test function TestRGReturnsError to a
name that reflects it expects no error (e.g., TestRGReturnsNoError or
TestRGSuccessfulGeneration); locate the test function declaration for
TestRGReturnsError in the file (which calls NewRGCustom("ptbr", false, nil) and
asserts err == nil) and rename the function identifier accordingly, and update
any references or test filters that may rely on the old name so the test suite
still runs.
In `@pkg/mocai/entities/nationalid/countries/brazilian_national_id.go`:
- Around line 21-31: The public API for NewRGCustom was changed (parameter order
and added error return), breaking consumers; revert NewRGCustom to its original
exported signature and semantics (original parameter order and single RG return)
and keep the new error-returning variant under a new symbol (e.g., NewRGCustomE
or NewRGCustomWithError) that calls generateBrazilianNationalIDCustom; ensure
generateBrazilianNationalIDCustom remains used by the new error-returning
wrapper while the restored NewRGCustom delegates to it and handles errors
internally so existing callers compile.
In `@pkg/mocai/mocker.go`:
- Around line 62-63: O loop que aplica opções pode executar um Option nil e
causar panic; dentro da função que aplica opts (onde a variável opts e o tipo
Option func(*Mocker) e a struct Mocker são usados), verifique cada opt por nil
antes de chamá-la (por exemplo: if opt == nil { continue }) ou filtre opções
nulas antes do loop, garantindo que apenas opções não-nulas sejam invocadas.
In `@pkg/mocai/options.go`:
- Around line 8-13: The WithLanguage option currently writes an empty string
into m.lang which overrides the default and causes inconsistent behavior; update
WithLanguage(func WithLanguage(lang string) Option) so it treats an empty lang
as a no-op (i.e., do not set m.lang when lang == "") or alternatively normalize
empty to the default "ptbr"; locate the Option closure in WithLanguage and add a
guard checking lang == "" and either return early without modifying m.lang or
set m.lang = "ptbr" to preserve the intended default for Mocker.
In `@pkg/mocai/translations/translations_test.go`:
- Around line 49-54: O teste deve parar imediatamente se GetList("test_lang",
"colors") devolver menos de 3 itens para evitar panics ao acessar val[0],
val[1], val[2]; substitua o t.Errorf de verificação de tamanho por t.Fatalf (por
exemplo na verificação em torno de len(val) != 3) para falhar fatalmente e
mantenha a verificação de conteúdo (os comparadores que usam
val[0]/val[1]/val[2]) após essa checagem segura; referências: função GetList e
as asserções no arquivo translations_test.go.
- Around line 132-146: The test TestGetUFMapReturnsDefensiveCopy is flaky
because it can pass when ufMap1 or ufMap2 is nil/empty and it checks a random
key; update the test to assert both GetUFMap("ptbr") results are non-nil and
non-empty, pick a concrete key from ufMap1 (e.g., first key via explicit
iteration), save its original value, modify that specific key in ufMap1, then
assert that ufMap2 still contains the original value for that same key;
reference GetUFMap and TestGetUFMapReturnsDefensiveCopy when making these
changes.
- Around line 98-102: The test currently passes nil which checks the "missing
list" case but not an actually empty slice; update
TestGetRandomReturnsKeyWhenListEmpty to also call GetRandom("nonexistent_lang",
"nonexistent_key", []string{}) (or replace the nil call with []string{}) and
assert the returned value is the key, ensuring GetRandom treats nil and
[]string{} the same; reference GetRandom and the test function name when making
the change.
In `@README.md`:
- Around line 22-31: A seção "## 📦 Supported Entities" removeu a menção ao
gerador de CNPJ standalone, gerando ambiguidade; atualize essa seção para
incluir explicitamente "CNPJ (standalone)" ou ajustar a linha "Company (name,
CNPJ)" para deixar claro que existe também um gerador direto de CNPJ na API
pública; revise o bloco de entidades (o título "Supported Entities" e as linhas
"Company" e "CNPJ") e reintroduza ou clarifique a entrada para CNPJ para
refletir a implementação atual.
---
Outside diff comments:
In
`@pkg/mocai/entities/voteregistration/countries/brazilian_vote_registration.go`:
- Around line 82-94: The language fallback in NewBrazilianVoteRegistrationCustom
is inconsistent with NewBrazilianVoteRegistration (which uses "ptbr"); change
NewBrazilianVoteRegistrationCustom so that when lang == "" or when the
translations check for "invalid_vote_registration" indicates unsupported, it
falls back to "ptbr" (not "en_us"), keeping the same behavior as
NewBrazilianVoteRegistration and avoiding returning raw translation keys; update
the lang default and unsupported-path assignment accordingly while preserving
the translations.Get(...) check and rnd/isFormatted handling.
---
Nitpick comments:
In `@pkg/mocai/entities/certificate/countries/brazilian_certificates_test.go`:
- Around line 50-67: Replace the literal type checks in TestCertificateTypes
with the exported certificate type constants instead of numbers: update the
assertions that inspect certs.BirthCertificate.Type,
certs.MarriageCertificate.Type and certs.DeathCertificate.Type (produced by
NewBrazilCertificatesCustom) to compare against the package's exported constants
(e.g., BirthCertificateType, MarriageCertificateType, DeathCertificateType or
whichever exported names exist) and adjust imports if necessary so the test uses
those constants rather than 1, 2, 3.
In `@pkg/mocai/entities/cnpj/generator_test.go`:
- Around line 70-88: The duplicated test helper fixedRand (type fixedRand with
method Intn) should be extracted into a shared internal testutil package: create
an internal/testutil package exposing a fixedRand (or NewFixedRand) constructor
and the same Intn behavior, move the implementation there, and update both
generator_test.go files to import testutil and instantiate the helper from that
package instead of duplicating the code; ensure the exported symbol names match
usage and run tests to verify behavior remains identical.
In `@pkg/mocai/entities/cnpj/generator.go`:
- Around line 41-43: The CNPJ generator returns ErrInvalidCNPJLength directly,
causing inconsistency with CPF which wraps errors with localized messages;
update GenerateCNPJ to accept a lang parameter (matching cpf/generator.go
pattern) and when len(cnpj) != 14 return a wrapped error like fmt.Errorf("%w:
%s", ErrInvalidCNPJ, translations.Get(lang, "invalid_cnpj")); ensure you
reference ErrInvalidCNPJLength (or replace it with ErrInvalidCNPJ) and use
translations.Get(lang, "invalid_cnpj") so error handling mirrors the CPF
implementation (see GenerateCPF/ErrInvalidCPF usage).
In `@pkg/mocai/entities/cpf/generator_test.go`:
- Around line 74-79: Replace the trivial self-comparison in
TestCPFErrorIsSentinel with a wrapped-error scenario: call NewCPF with invalid
input to obtain the error (or wrap ErrInvalidCPF via fmt.Errorf("%w",
ErrInvalidCPF)) and then assert errors.Is(wrappedErr, ErrInvalidCPF) returns
true; update TestCPFErrorIsSentinel to use the function that produces the error
(NewCPF) and add the "fmt" import if you choose manual wrapping with fmt.Errorf.
In `@pkg/mocai/entities/nationalid/countries/brazilian_national_id_test.go`:
- Around line 57-62: The test TestRGErrorIsSentinel currently only compares
ErrConvertingDigit to itself; instead produce a real wrapped error and assert
errors.Is identifies the sentinel: create an error that wraps ErrConvertingDigit
(e.g., via fmt.Errorf("failed converting digit: %w", ErrConvertingDigit) or
using errors.Join/wrap from the codebase) and replace the current assertion with
errors.Is(wrappedErr, ErrConvertingDigit); reference the test name
TestRGErrorIsSentinel and the sentinel ErrConvertingDigit when making the
change.
In `@pkg/mocai/entities/phone/generator.go`:
- Around line 27-44: In generatePhone, ensure areaCodes from
translations.GetList(lang, "phone_area_code") are validated for non-empty
(trimmed) entries like other generators: filter the areaCodes slice to remove
strings where strings.TrimSpace(item) == "" before checking length, return
ErrNoAreaCodes with the existing translations.Get message if the filtered slice
is empty, then select areaCode using rnd.Intn on the filtered slice; remove the
redundant post-selection empty check (or keep it only as a defensive panic) and
keep returning ErrGeneratingPhone using translations.Get(lang,
"error_generating_phone") only when generation truly fails.
In
`@pkg/mocai/entities/voteregistration/countries/brazilian_vote_registration_test.go`:
- Around line 53-65: The current TestVoteRegistrationErrorIsSentinel trivially
compares each sentinel to itself; replace it with real error-origin tests: call
the functions that can return these errors (e.g., the vote
registration/validation/generation functions used elsewhere) and assert
errors.Is(returnedErr, ErrInvalidVoteRegistration / ErrInvalidCheckDigit1 /
ErrInvalidCheckDigit2); alternatively create a wrapped error with
fmt.Errorf("%w", ErrInvalidCheckDigit1) and assert errors.Is on that wrapped
error to verify sentinel matching (see cpf/generator_test.go for a pattern).
In `@pkg/mocai/mocker.go`:
- Around line 71-72: The provider path is losing the instance RandSource because
WithRandSource only sets m.rnd but provider methods
GeneratePerson/GenerateCompany/GenerateAddress on
personProvider/companyProvider/addressProvider don't accept it; update the
provider interfaces to accept a RandSource (or add a SetRandSource method) and
propagate m.rnd into calls from the methods in the Mocker (where you call
personProvider.GeneratePerson, companyProvider.GenerateCompany,
addressProvider.GenerateAddress), or alternatively pass m.rnd into those
Generate* calls so the providers use the instance RNG; ensure symbols
WithRandSource, m.rnd, GeneratePerson, GenerateCompany, GenerateAddress,
personProvider, companyProvider and addressProvider are updated consistently.
- Around line 56-66: Change NewMocker to return *Mocker instead of the
MockGenerator interface: update the function signature NewMocker(opts ...Option)
*Mocker and keep the constructor body as-is (it already constructs &Mocker).
Ensure all Option functions and their types (those accepting m *Mocker) remain
compatible, and update any call sites or tests that expect a MockGenerator to
accept the concrete *Mocker (callers that need the interface can still assign
var g MockGenerator = NewMocker(...)). Leave the MockGenerator interface
declared but remove it from the public constructor return type.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 8fa23dec-fd47-4c5f-9284-7036c8ceb9cd
📒 Files selected for processing (34)
README.mddocs/localization/pt/README-PT.mdexamples/mocker/main.gopkg/mocai/entities/address/generator.gopkg/mocai/entities/address/generator_test.gopkg/mocai/entities/certificate/countries/brazilian_certificates.gopkg/mocai/entities/certificate/countries/brazilian_certificates_test.gopkg/mocai/entities/cnpj/generator.gopkg/mocai/entities/cnpj/generator_test.gopkg/mocai/entities/company/countries/brazilian_company.gopkg/mocai/entities/company/countries/generator_test.gopkg/mocai/entities/cpf/generator.gopkg/mocai/entities/cpf/generator_test.gopkg/mocai/entities/gender/gender.gopkg/mocai/entities/gender/gender_test.gopkg/mocai/entities/nationalid/countries/brazilian_national_id.gopkg/mocai/entities/nationalid/countries/brazilian_national_id_test.gopkg/mocai/entities/nationalid/generator.gopkg/mocai/entities/person/generator.gopkg/mocai/entities/person/generator_test.gopkg/mocai/entities/phone/generator.gopkg/mocai/entities/phone/generator_test.gopkg/mocai/entities/voteregistration/countries/brazilian_vote_registration.gopkg/mocai/entities/voteregistration/countries/brazilian_vote_registration_test.gopkg/mocai/entities/voteregistration/generator.gopkg/mocai/mocker.gopkg/mocai/mocker_test.gopkg/mocai/options.gopkg/mocai/provider.gopkg/mocai/translations/en_us.gopkg/mocai/translations/pt_br.gopkg/mocai/translations/safe_rand.gopkg/mocai/translations/translations.gopkg/mocai/translations/translations_test.go
| #### [README (English)](/README.md) | ||
|
|
There was a problem hiding this comment.
Corrija o nível do heading para manter a hierarquia correta.
O static analysis (markdownlint) indica que o heading na linha 5 usa #### (h4), mas deveria seguir a hierarquia incrementando de h1 para h2. Isso melhora a acessibilidade e a estrutura do documento.
📝 Correção sugerida
-#### [README (English)](/README.md)
+## [README (English)](/README.md)📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| #### [README (English)](/README.md) | |
| ## [README (English)](/README.md) | |
🧰 Tools
🪛 markdownlint-cli2 (0.22.0)
[warning] 5-5: Heading levels should only increment by one level at a time
Expected: h2; Actual: h4
(MD001, heading-increment)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@docs/localization/pt/README-PT.md` around lines 5 - 6, The heading "####
[README (English)](/README.md)" is using h4 but should be h2 to preserve
hierarchical order; update that Markdown heading from "#### [README
(English)](/README.md)" to "## [README (English)](/README.md)" so it increments
correctly from the document h1 to h2 and satisfies markdownlint/accessibility
rules.
| if addr.Number <= 0 { | ||
| t.Errorf("Number should be positive, got %d", addr.Number) | ||
| } |
There was a problem hiding this comment.
Asserção de Number pode falhar incorretamente.
O teste verifica addr.Number <= 0, mas o gerador em generator.go linha 94 usa rnd.Intn(9999) que pode retornar 0. Isso significa que Number = 0 é um valor válido gerado pelo sistema, mas o teste falharia nesse caso.
🐛 Correção sugerida
- if addr.Number <= 0 {
- t.Errorf("Number should be positive, got %d", addr.Number)
+ if addr.Number < 0 {
+ t.Errorf("Number should be non-negative, got %d", addr.Number)
}Alternativamente, se Number = 0 realmente não é desejado, o gerador deveria usar rnd.Intn(9999) + 1.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| if addr.Number <= 0 { | |
| t.Errorf("Number should be positive, got %d", addr.Number) | |
| } | |
| if addr.Number < 0 { | |
| t.Errorf("Number should be non-negative, got %d", addr.Number) | |
| } |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@pkg/mocai/entities/address/generator_test.go` around lines 33 - 35, The test
asserts Number must be positive but the generator uses rnd.Intn(9999) (in
generator.go) which can produce 0, so either relax the test or fix the
generator: if 0 is acceptable, change the test in generator_test.go to assert
addr.Number >= 0 (or remove the failing check); if 0 is not acceptable, change
the generator's expression rnd.Intn(9999) to rnd.Intn(9999) + 1 (in the function
that creates addresses) so Number is always > 0 and keep the existing test.
| func TestRGReturnsError(t *testing.T) { | ||
| _, err := NewRGCustom("ptbr", false, nil) | ||
|
|
||
| if err != nil { | ||
| t.Fatalf("unexpected error: %v", err) | ||
| } | ||
| } |
There was a problem hiding this comment.
Nome do teste TestRGReturnsError é enganoso.
O teste verifica que nenhum erro é retornado (linha 52-54), mas o nome sugere que testa um cenário de erro. Considere renomear para TestRGReturnsNoError ou TestRGSuccessfulGeneration.
💡 Sugestão de renomeação
-func TestRGReturnsError(t *testing.T) {
+func TestRGReturnsNoError(t *testing.T) {
_, err := NewRGCustom("ptbr", false, nil)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| func TestRGReturnsError(t *testing.T) { | |
| _, err := NewRGCustom("ptbr", false, nil) | |
| if err != nil { | |
| t.Fatalf("unexpected error: %v", err) | |
| } | |
| } | |
| func TestRGReturnsNoError(t *testing.T) { | |
| _, err := NewRGCustom("ptbr", false, nil) | |
| if err != nil { | |
| t.Fatalf("unexpected error: %v", err) | |
| } | |
| } |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@pkg/mocai/entities/nationalid/countries/brazilian_national_id_test.go` around
lines 49 - 55, Rename the misleading test function TestRGReturnsError to a name
that reflects it expects no error (e.g., TestRGReturnsNoError or
TestRGSuccessfulGeneration); locate the test function declaration for
TestRGReturnsError in the file (which calls NewRGCustom("ptbr", false, nil) and
asserts err == nil) and rename the function identifier accordingly, and update
any references or test filters that may rely on the old name so the test suite
still runs.
| // NewRGCustom generates a random RG (Brazilian Identity Card) using an injected random source and language. | ||
| // Returns an error if generation fails, instead of silently returning an empty RG. | ||
| func NewRGCustom(lang string, isFormatted bool, rnd translations.RandSource) (RG, error) { | ||
| if lang == "" { | ||
| lang = "ptbr" | ||
| } | ||
| rg, err := generateBrazilianNationalIDCustom(isFormatted, rnd, l) | ||
| rg, err := generateBrazilianNationalIDCustom(lang, isFormatted, rnd) | ||
| if err != nil { | ||
| return RG{} | ||
| return RG{}, err | ||
| } | ||
| return rg | ||
| return rg, nil |
There was a problem hiding this comment.
Essa mudança quebra a API pública de NewRGCustom.
A assinatura exportada mudou a ordem dos parâmetros e passou a exigir error no retorno. Isso faz consumidores externos deixarem de compilar mesmo que o uso anterior ainda fosse válido. Se a quebra for intencional, isso precisa ser tratado como breaking change explícita; caso contrário, vale preservar a entrada antiga e introduzir um novo símbolo para a variante com erro.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@pkg/mocai/entities/nationalid/countries/brazilian_national_id.go` around
lines 21 - 31, The public API for NewRGCustom was changed (parameter order and
added error return), breaking consumers; revert NewRGCustom to its original
exported signature and semantics (original parameter order and single RG return)
and keep the new error-returning variant under a new symbol (e.g., NewRGCustomE
or NewRGCustomWithError) that calls generateBrazilianNationalIDCustom; ensure
generateBrazilianNationalIDCustom remains used by the new error-returning
wrapper while the restored NewRGCustom delegates to it and handles errors
internally so existing callers compile.
| for _, opt := range opts { | ||
| opt(m) |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
cat -n pkg/mocai/mocker.go | head -80Repository: brazzcore/mocai
Length of output: 3337
🏁 Script executed:
grep -n "type Option" pkg/mocai/mocker.goRepository: brazzcore/mocai
Length of output: 41
🏁 Script executed:
rg "type Option" pkg/mocai/Repository: brazzcore/mocai
Length of output: 105
🏁 Script executed:
cat -n pkg/mocai/options.goRepository: brazzcore/mocai
Length of output: 1925
🏁 Script executed:
rg "NewMocker" --type go -A 3 -B 1 | head -60Repository: brazzcore/mocai
Length of output: 2828
Adicione verificação de nil para evitar panic com Option nulo.
Option é um func(*Mocker); um item nil na slice faz opt(m) panic, que pode ocorrer facilmente em composição condicional de opções.
💡 Ajuste sugerido
for _, opt := range opts {
- opt(m)
+ if opt != nil {
+ opt(m)
+ }
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| for _, opt := range opts { | |
| opt(m) | |
| for _, opt := range opts { | |
| if opt != nil { | |
| opt(m) | |
| } | |
| } |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@pkg/mocai/mocker.go` around lines 62 - 63, O loop que aplica opções pode
executar um Option nil e causar panic; dentro da função que aplica opts (onde a
variável opts e o tipo Option func(*Mocker) e a struct Mocker são usados),
verifique cada opt por nil antes de chamá-la (por exemplo: if opt == nil {
continue }) ou filtre opções nulas antes do loop, garantindo que apenas opções
não-nulas sejam invocadas.
| // WithLanguage sets the language for mock data generation. | ||
| // Default: "ptbr" | ||
| func WithLanguage(lang string) Option { | ||
| return func(m *Mocker) { | ||
| m.lang = lang | ||
| } |
There was a problem hiding this comment.
WithLanguage("") anula o default em vez de preservá-lo.
Como essa opção grava a string vazia sem normalização, o Mocker entra em caminhos diferentes dependendo da entidade: algumas geram ptbr, outras caem em en_us e outras falham. Trate vazio como no-op ou normalize para ptbr.
💡 Ajuste sugerido
func WithLanguage(lang string) Option {
return func(m *Mocker) {
- m.lang = lang
+ if lang == "" {
+ return
+ }
+ m.lang = lang
}
}🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@pkg/mocai/options.go` around lines 8 - 13, The WithLanguage option currently
writes an empty string into m.lang which overrides the default and causes
inconsistent behavior; update WithLanguage(func WithLanguage(lang string)
Option) so it treats an empty lang as a no-op (i.e., do not set m.lang when lang
== "") or alternatively normalize empty to the default "ptbr"; locate the Option
closure in WithLanguage and add a guard checking lang == "" and either return
early without modifying m.lang or set m.lang = "ptbr" to preserve the intended
default for Mocker.
| val := GetList("test_lang", "colors") | ||
| if len(val) != 3 { | ||
| t.Errorf("expected 3 items, got %d", len(val)) | ||
| } | ||
| if val[0] != "red" || val[1] != "green" || val[2] != "blue" { | ||
| t.Errorf("unexpected values: %v", val) |
There was a problem hiding this comment.
Use Fatalf no cheque de tamanho.
Se GetList voltar menos de 3 itens, o teste segue e pode estourar índice em val[0], val[1] ou val[2], escondendo a causa real.
💡 Ajuste sugerido
val := GetList("test_lang", "colors")
if len(val) != 3 {
- t.Errorf("expected 3 items, got %d", len(val))
+ t.Fatalf("expected 3 items, got %d", len(val))
}
if val[0] != "red" || val[1] != "green" || val[2] != "blue" {
t.Errorf("unexpected values: %v", val)
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| val := GetList("test_lang", "colors") | |
| if len(val) != 3 { | |
| t.Errorf("expected 3 items, got %d", len(val)) | |
| } | |
| if val[0] != "red" || val[1] != "green" || val[2] != "blue" { | |
| t.Errorf("unexpected values: %v", val) | |
| val := GetList("test_lang", "colors") | |
| if len(val) != 3 { | |
| t.Fatalf("expected 3 items, got %d", len(val)) | |
| } | |
| if val[0] != "red" || val[1] != "green" || val[2] != "blue" { | |
| t.Errorf("unexpected values: %v", val) | |
| } |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@pkg/mocai/translations/translations_test.go` around lines 49 - 54, O teste
deve parar imediatamente se GetList("test_lang", "colors") devolver menos de 3
itens para evitar panics ao acessar val[0], val[1], val[2]; substitua o t.Errorf
de verificação de tamanho por t.Fatalf (por exemplo na verificação em torno de
len(val) != 3) para falhar fatalmente e mantenha a verificação de conteúdo (os
comparadores que usam val[0]/val[1]/val[2]) após essa checagem segura;
referências: função GetList e as asserções no arquivo translations_test.go.
| func TestGetRandomReturnsKeyWhenListEmpty(t *testing.T) { | ||
| val := GetRandom("nonexistent_lang", "nonexistent_key", nil) | ||
| if val != "nonexistent_key" { | ||
| t.Errorf("expected key returned as-is, got %q", val) | ||
| } |
There was a problem hiding this comment.
O cenário aqui é “lista ausente”, não “lista vazia”.
Se GetRandom tratar nil e []string{} de forma diferente, a regressão passa neste teste. Vale registrar uma chave com slice vazio para cobrir o caso que o nome promete.
💡 Ajuste sugerido
func TestGetRandomReturnsKeyWhenListEmpty(t *testing.T) {
- val := GetRandom("nonexistent_lang", "nonexistent_key", nil)
- if val != "nonexistent_key" {
+ RegisterList("empty_rand_lang", map[string][]string{
+ "empty_key": {},
+ })
+ val := GetRandom("empty_rand_lang", "empty_key", nil)
+ if val != "empty_key" {
t.Errorf("expected key returned as-is, got %q", val)
}
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| func TestGetRandomReturnsKeyWhenListEmpty(t *testing.T) { | |
| val := GetRandom("nonexistent_lang", "nonexistent_key", nil) | |
| if val != "nonexistent_key" { | |
| t.Errorf("expected key returned as-is, got %q", val) | |
| } | |
| func TestGetRandomReturnsKeyWhenListEmpty(t *testing.T) { | |
| RegisterList("empty_rand_lang", map[string][]string{ | |
| "empty_key": {}, | |
| }) | |
| val := GetRandom("empty_rand_lang", "empty_key", nil) | |
| if val != "empty_key" { | |
| t.Errorf("expected key returned as-is, got %q", val) | |
| } | |
| } |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@pkg/mocai/translations/translations_test.go` around lines 98 - 102, The test
currently passes nil which checks the "missing list" case but not an actually
empty slice; update TestGetRandomReturnsKeyWhenListEmpty to also call
GetRandom("nonexistent_lang", "nonexistent_key", []string{}) (or replace the nil
call with []string{}) and assert the returned value is the key, ensuring
GetRandom treats nil and []string{} the same; reference GetRandom and the test
function name when making the change.
| func TestGetUFMapReturnsDefensiveCopy(t *testing.T) { | ||
| ufMap1 := GetUFMap("ptbr") | ||
| ufMap2 := GetUFMap("ptbr") | ||
|
|
||
| for k := range ufMap1 { | ||
| ufMap1[k] = "MODIFIED" | ||
| break | ||
| } | ||
|
|
||
| for k, v := range ufMap2 { | ||
| if v == "MODIFIED" { | ||
| t.Errorf("GetUFMap returned a shared reference, key %q was modified", k) | ||
| } | ||
| break | ||
| } |
There was a problem hiding this comment.
Esse teste de cópia defensiva pode passar em falso.
Hoje ele não falha se um dos mapas vier nil/vazio, e o segundo range valida uma chave aleatória — não necessariamente a mesma que foi alterada.
💡 Ajuste sugerido
func TestGetUFMapReturnsDefensiveCopy(t *testing.T) {
ufMap1 := GetUFMap("ptbr")
ufMap2 := GetUFMap("ptbr")
+ if len(ufMap1) == 0 || len(ufMap2) == 0 {
+ t.Fatal("expected non-empty UF maps for ptbr")
+ }
+ var modifiedKey string
for k := range ufMap1 {
+ modifiedKey = k
ufMap1[k] = "MODIFIED"
break
}
+ if modifiedKey == "" {
+ t.Fatal("expected at least one key in UF map")
+ }
- for k, v := range ufMap2 {
- if v == "MODIFIED" {
- t.Errorf("GetUFMap returned a shared reference, key %q was modified", k)
- }
- break
+ if ufMap2[modifiedKey] == "MODIFIED" {
+ t.Errorf("GetUFMap returned a shared reference, key %q was modified", modifiedKey)
}
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| func TestGetUFMapReturnsDefensiveCopy(t *testing.T) { | |
| ufMap1 := GetUFMap("ptbr") | |
| ufMap2 := GetUFMap("ptbr") | |
| for k := range ufMap1 { | |
| ufMap1[k] = "MODIFIED" | |
| break | |
| } | |
| for k, v := range ufMap2 { | |
| if v == "MODIFIED" { | |
| t.Errorf("GetUFMap returned a shared reference, key %q was modified", k) | |
| } | |
| break | |
| } | |
| func TestGetUFMapReturnsDefensiveCopy(t *testing.T) { | |
| ufMap1 := GetUFMap("ptbr") | |
| ufMap2 := GetUFMap("ptbr") | |
| if len(ufMap1) == 0 || len(ufMap2) == 0 { | |
| t.Fatal("expected non-empty UF maps for ptbr") | |
| } | |
| var modifiedKey string | |
| for k := range ufMap1 { | |
| modifiedKey = k | |
| ufMap1[k] = "MODIFIED" | |
| break | |
| } | |
| if modifiedKey == "" { | |
| t.Fatal("expected at least one key in UF map") | |
| } | |
| if ufMap2[modifiedKey] == "MODIFIED" { | |
| t.Errorf("GetUFMap returned a shared reference, key %q was modified", modifiedKey) | |
| } | |
| } |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@pkg/mocai/translations/translations_test.go` around lines 132 - 146, The test
TestGetUFMapReturnsDefensiveCopy is flaky because it can pass when ufMap1 or
ufMap2 is nil/empty and it checks a random key; update the test to assert both
GetUFMap("ptbr") results are non-nil and non-empty, pick a concrete key from
ufMap1 (e.g., first key via explicit iteration), save its original value, modify
that specific key in ufMap1, then assert that ufMap2 still contains the original
value for that same key; reference GetUFMap and TestGetUFMapReturnsDefensiveCopy
when making these changes.
| ## 📦 Supported Entities | ||
| - Person (with gender, age, CPF) | ||
| - Gender (standalone generation) | ||
| - Address (street, number, city, state, UF, ZIP) | ||
| - Phone (area code, number) | ||
| - Company (name, CNPJ) | ||
| - CPF (Brazilian individual taxpayer registry) | ||
| - CNPJ (Brazilian company registry) | ||
| - Certificates (Birth, Marriage, Death) | ||
| - National ID (RG) | ||
| - Voter Registration (Título de Eleitor) |
There was a problem hiding this comment.
A lista de entidades suportadas ficou incompleta.
O CNPJ standalone saiu daqui, mas a própria PR ainda refatora/adiciona cobertura para esse gerador. Isso passa a impressão de que a geração direta de CNPJ não faz mais parte da API pública.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@README.md` around lines 22 - 31, A seção "## 📦 Supported Entities" removeu a
menção ao gerador de CNPJ standalone, gerando ambiguidade; atualize essa seção
para incluir explicitamente "CNPJ (standalone)" ou ajustar a linha "Company
(name, CNPJ)" para deixar claro que existe também um gerador direto de CNPJ na
API pública; revise o bloco de entidades (o título "Supported Entities" e as
linhas "Company" e "CNPJ") e reintroduza ou clarifique a entrada para CNPJ para
refletir a implementação atual.
Summary by CodeRabbit
Release Notes
New Features
Refactor
Documentation
Tests