massa-br
Deterministic generator of valid Brazilian test data — CPF, CNPJ, CEP, phone, and more. Zero dependencies. Gerador determinístico de dados brasileiros válidos para testes — CPF, CNPJ, CEP, telefone e mais. Zero dependências.
English
Why another data generator?
Two properties set massa-br apart from a generic faker:
- Valid by construction — it doesn't emit "random numbers that look like a CPF". It generates the base digits and computes the check digits, so every value passes real validation: CPF, CNPJ (including the new alphanumeric format effective July 2026), CEP inside the actual UF range.
- Deterministic by seed — same seed, same output, on any machine. This turns "fake data" into reproducible fixtures: the test that passes in your CI passes identically on your teammate's.
Install
npm install --save-dev massa-br
Quick start
import { createGenerator } from 'massa-br';
const gen = createGenerator('order-2026'); // seed → reproducible data
gen.cpf(); // '52998224725'
gen.cpf({ mask: true }); // '529.982.247-25'
gen.cnpj(); // numeric, valid
gen.cnpj({ tipo: 'alfanumerico' }); // new 2026 format, e.g. '12ABC345000188'
gen.pessoa(); // coherent record (phone DDD & CEP match the UF)
API
| Method | Returns | Options |
|---|---|---|
gen.cpf(opts?) |
CPF string | { mask } |
gen.cnpj(opts?) |
CNPJ string | { mask, tipo: 'numerico' | 'alfanumerico' } |
gen.celular(uf?) |
mobile phone | UF code to match the area code |
gen.cep(uf?) |
postal code | UF code to match the range |
gen.nome() |
full name | — |
gen.email() |
— | |
gen.pessoa(opts?) |
full person object | { mask } |
Every generator also has a .many(count, { unique }):
gen.cpf.many(10_000, { unique: true }); // 10k valid CPFs, no collisions
Reproducible by design: keyed streams
Plain determinism has a trap: if output depends on call order, adding one gen.cpf() in the middle of a test shifts everything after it. Use .as(key) to get a stream that's stable regardless of order:
gen.as('customer-42').cpf(); // always the same, no matter what ran before
gen.as('customer-43').cpf(); // independent from customer-42
The pessoa() object
{
nome: 'Ana Silva',
cpf: '52998224725',
email: 'ana.silva12@gmail.com',
celular: '(11) 98765-4321',
nascimento: '1990-04-23',
endereco: { cep: '01310-100', uf: 'SP', cidade: 'São Paulo' }
}
Contributing
Issues and PRs are welcome. Run the tests with npm test (uses the native Node test runner, no dependencies).
License
MIT
Português
Por que mais um gerador de dados?
Duas propriedades separam o massa-br de um faker genérico:
- Válido por construção — ele não gera "número aleatório com cara de CPF". Ele gera os dígitos base e calcula os dígitos verificadores, então todo valor passa na validação real: CPF, CNPJ (incluindo o novo formato alfanumérico em vigor desde julho de 2026), CEP dentro da faixa real da UF.
- Determinístico por seed — mesma seed, mesma saída, em qualquer máquina. Isso transforma "dado fake" em fixture reproduzível: o teste que passou no seu CI passa igual no do colega.
Instalação
npm install --save-dev massa-br
Começo rápido
import { createGenerator } from 'massa-br';
const gen = createGenerator('pedido-2026'); // seed → dados reproduzíveis
gen.cpf(); // '52998224725'
gen.cpf({ mask: true }); // '529.982.247-25'
gen.cnpj(); // numérico, válido
gen.cnpj({ tipo: 'alfanumerico' }); // formato novo de 2026, ex.: '12ABC345000188'
gen.pessoa(); // registro coerente (DDD e CEP batem com a UF)
API
| Método | Retorna | Opções |
|---|---|---|
gen.cpf(opts?) |
string de CPF | { mask } |
gen.cnpj(opts?) |
string de CNPJ | { mask, tipo: 'numerico' | 'alfanumerico' } |
gen.celular(uf?) |
celular | UF para casar o DDD |
gen.cep(uf?) |
CEP | UF para casar a faixa |
gen.nome() |
nome completo | — |
gen.email() |
— | |
gen.pessoa(opts?) |
objeto pessoa completo | { mask } |
Todo gerador tem também um .many(count, { unique }):
gen.cpf.many(10_000, { unique: true }); // 10 mil CPFs válidos, sem colisão
Reproduzível de propósito: streams por chave
Determinismo puro tem uma armadilha: se a saída depende da ordem das chamadas, adicionar um gen.cpf() no meio do teste embaralha tudo depois. Use .as(key) para um stream estável independente da ordem:
gen.as('cliente-42').cpf(); // sempre o mesmo, não importa o que rodou antes
gen.as('cliente-43').cpf(); // independente do cliente-42
Licença
MIT