# Relatório de Testes — Importação Prodata / Conta Angra

- Data da última execução: 2026-05-18
- Ferramenta: PHPUnit 10.5.60
- Runtime: PHP 8.2.28
- Configuração: `phpunit.xml` (padrão do projeto)
- Comando executado: `php vendor/bin/phpunit --filter=ImportacaoProdataContaAngra --testdox`

## Resultado consolidado (somente importação)

| Métrica | Valor |
| --- | ---: |
| Total de testes | 24 |
| Aprovados | 24 |
| Falhas | 0 |
| Asserções | 85 |
| Tempo total | ~5,2s |
| Memória pico | 48 MB |

> Há 1 aviso de `PHPUnit Deprecations` herdado do projeto (não relacionado a esta importação).

## Resultado da suite completa do projeto

| Métrica | Valor |
| --- | ---: |
| Total de testes | 38 |
| Aprovados | 34 |
| Erros | 3 |
| Falhas | 1 |
| Asserções | 109 |

### Falhas pré-existentes (não relacionadas à importação)

| Teste | Arquivo | Motivo |
| --- | --- | --- |
| `Iniciar solicitacao cria registro` | `AuthFlowsTest.php` | Classe `ServicoDeContaPublica` não encontrada — erro pré-existente, commit `a241db7e8` |
| `Enviar token recuperacao para usuario inexistente falha` | `AuthFlowsTest.php` | Classe `ServicoDeSenha` não encontrada — idem |
| `Recuperacao de senha com cpf ...` | `AuthFlowsTest.php` | Classe `ServicoDeSenha` não encontrada — idem |
| `Normalize currency fields normalizes all currency inputs` | `ProjetosProgramasValidationTest.php` | Falha de assertiva — erro pré-existente, commit `3a9f779ca` |

> **Conclusão**: a importação não introduziu nenhuma regressão. As 4 falhas acima existiam antes do desenvolvimento desta funcionalidade e estão em módulos completamente independentes.

## Mapa de cobertura

| Cenário do escopo | Teste que cobre | Localização |
| --- | --- | --- |
| Criação de usuários | `processar_linha_cria_usuario_novo_com_permissoes_padrao` / `seeder_cria_usuarios_novos_com_permissoes_padrao` | Unit + Feature |
| Atualização de usuários existentes | `dirty_check_atualiza_apenas_campos_divergentes` / `seeder_atualiza_usuario_existente_preservando_senha_e_permissoes` | Unit + Feature |
| Preservação de permissões | `atualizacao_preserva_permissoes_existentes` / `seeder_atualiza_usuario_existente_preservando_senha_e_permissoes` | Unit + Feature |
| Preservação de senha e configurações | `atualizacao_preserva_senha_phone_status` / `seeder_atualiza_usuario_existente_preservando_senha_e_permissoes` | Unit + Feature |
| DE-PARA de unidades | `seeder_aplica_de_para_de_unidades` / `seeder_resolve_unidade_via_match_automatico_de_structures_existentes` | Feature |
| Tratamento de registros inválidos | `validar_retorna_mensagem_para_cpf_invalido` / `validar_retorna_mensagem_para_email_invalido` / `validar_retorna_mensagem_para_structure_id_nulo` / `seeder_marca_registros_invalidos_e_continua_processando` | Unit + Feature |
| Idempotência da importação | `processar_linha_idempotente_marca_como_sincronizado_na_segunda_execucao` / `seeder_e_idempotente_marca_sincronizado_na_segunda_execucao` | Unit + Feature |
| Reexecução segura (dirty check) | `dirty_check_atualiza_apenas_campos_divergentes` | Unit |
| Conflito de e-mail (update) | `email_em_conflito_em_update_preserva_email_atual` | Unit |
| Conflito de e-mail (create) | `email_em_conflito_em_create_marca_invalido` | Unit |
| Performance em lote | `seeder_em_lote_de_50_registros_processa_em_tempo_aceitavel` | Feature |
| Normalização de CPF / e-mail / matrícula / nome | `normaliza_cpf_*` / `normaliza_email_*` / `normaliza_matricula_*` / `normaliza_nome_*` | Unit |
| CPF com zero à esquerda (planilha exporta 10 dígitos) | `normaliza_cpf_com_zero_a_esquerda_quando_planilha_exporta_dez_digitos` | Unit |
| Validação CPF (checksum) | `valida_cpf_com_checksum_oficial` / `validar_retorna_null_para_dados_validos` | Unit |

## Detalhe dos testes

### Feature — `Tests\Feature\Importacoes\ImportacaoProdataContaAngraSeederTest`

- [x] Seeder cria usuarios novos com permissoes padrao
- [x] Seeder atualiza usuario existente preservando senha e permissoes
- [x] Seeder e idempotente marca sincronizado na segunda execucao
- [x] Seeder aplica de para de unidades
- [x] Seeder marca registros invalidos e continua processando
- [x] Seeder em lote de 50 registros processa em tempo aceitavel
- [x] Seeder resolve unidade via match automatico de structures existentes

### Unit — `Tests\Unit\Importacoes\ImportacaoProdataContaAngraServiceTest`

- [x] Normaliza cpf removendo caracteres nao numericos
- [x] Normaliza cpf com zero a esquerda quando planilha exporta dez digitos
- [x] Normaliza email em minusculo e trim
- [x] Normaliza matricula mantendo apenas digitos
- [x] Normaliza nome em first e last
- [x] Valida cpf com checksum oficial
- [x] Validar retorna mensagem para cpf invalido
- [x] Validar retorna mensagem para email invalido
- [x] Validar retorna mensagem para structure id nulo
- [x] Validar retorna null para dados validos
- [x] Processar linha cria usuario novo com permissoes padrao
- [x] Processar linha idempotente marca como sincronizado na segunda execucao
- [x] Dirty check atualiza apenas campos divergentes
- [x] Atualizacao preserva senha phone status
- [x] Atualizacao preserva permissoes existentes
- [x] Email em conflito em update preserva email atual
- [x] Email em conflito em create marca invalido

## Garantias sobre usuários existentes

| Risco avaliado | Comportamento testado | Resultado |
| --- | --- | --- |
| Senha alterada na reimportação | `test_atualizacao_preserva_senha_phone_status` — verifica `password`, `isPasswordDefault` e `phoneNumber` após update | ✅ Preservada |
| Permissões apagadas na reimportação | `test_atualizacao_preserva_permissoes_existentes` — insere `SYSADMIN` manualmente e verifica após reimport | ✅ Preservadas |
| E-mail de usuário existente sobrescrito por conflito | `test_email_em_conflito_em_update_preserva_email_atual` | ✅ Mantém e-mail original |
| Usuário duplicado criado por e-mail conflitante | `test_email_em_conflito_em_create_marca_invalido` — verifica que o 2.º registro fica inválido e não cria usuário | ✅ Bloqueado |
| Dados ruidosos (CPF com 10 dígitos, maiúsculas, espaços) | `test_normaliza_cpf_com_zero_a_esquerda_*` / `normaliza_email_em_minusculo_e_trim` | ✅ Normalizados |
| Reimportação altera dados sem necessidade | `test_processar_linha_idempotente_*` / `test_dirty_check_*` — somente campos realmente diferentes são salvos | ✅ Idempotente |

## Helpers de teste

- `tests/Support/Importacoes/ImportacaoProdataTestHelpers.php`
  - `gerarCpfTeste(int|string $sufixo): string` — gera CPF de 11 dígitos com checksum válido, prefixo reservado `999`.
  - `getStructureIdTeste()` — usa `STRUCTURE_DEFAULT_ID` do `.env` com fallback para a primeira Structure ativa.
  - `getDuasStructuresTeste()` — duas Structures distintas para verificar mudança de unidade.
  - `limparUsuariosTeste()` — remove usuários e permissões criados durante o teste (todos com `cpf LIKE '999%'`).

## Como reproduzir localmente

```bash
# 1) Rodar todos os testes desta importação
php vendor/bin/phpunit --filter=ImportacaoProdataContaAngra

# 2) Saída em estilo testdox (legível para humanos)
php vendor/bin/phpunit --filter=ImportacaoProdataContaAngra --testdox

# 3) Rodar apenas o feature test
php vendor/bin/phpunit tests/Feature/Importacoes/ImportacaoProdataContaAngraSeederTest.php

# 4) Rodar apenas o unit test
php vendor/bin/phpunit tests/Unit/Importacoes/ImportacaoProdataContaAngraServiceTest.php

# 5) Rodar suite completa
php vendor/bin/phpunit --testdox
```

## Observações operacionais

- Os testes utilizam o banco MySQL real configurado em `.env` (o projeto não usa `RefreshDatabase`). Por segurança, CPFs e e-mails de teste usam prefixos reservados (`999*` para CPF e `*@example.com` para e-mail), e o `tearDown` remove os registros criados.
- Os testes de Feature criam temporariamente o arquivo `temp/importacao-prodata-contaangra/dados.csv` com casos sintéticos; se o CSV de produção existir, ele é renomeado para `.backup_<uniqid>` durante o teste e restaurado no `tearDown`.
- O DE-PARA é injetado por arquivo JSON pré-gravado no disco `local`, evitando qualquer prompt interativo durante a execução automatizada.
- O teste de lote (50 registros) executa em ~1s no ambiente local; o limite de aprovação é 30s (margem ampla para CI/produção).
