# Guia de Testes V2

Este documento é a referência autoritativa para escrever e executar testes na V2.
Cobre a estrutura-alvo, as regras de escrita, os comandos de execução e o checklist
de verificação pré-entrega. Leia este guia antes de criar ou modificar qualquer teste.

## 1. Estrutura-alvo

A suíte espelha estritamente a árvore de código-fonte `V2/`. O caminho de cada teste
é o caminho da classe sob teste, com o sufixo `Test.php`.

```
tests/
├── Unit/V2/                    # Suíte "V2 Unit"
│   ├── TestCase.php            # Base da suíte Unit (helper invokeMethod())
│   ├── Core/                   # Espelha V2/Core/
│   │   ├── Controllers/
│   │   ├── Helpers/
│   │   ├── Middleware/
│   │   ├── Services/
│   │   └── ViewComposers/
│   ├── Services/               # Espelha V2/Services/{Nome}/
│   │   └── {Nome}/
│   ├── Modules/                # Espelha V2/Modules/{Grupo}/{Modulo}/
│   │   └── {Grupo}/
│   │       └── {Modulo}/
│   └── Layouts/                # Espelha V2/layouts/ (Cms/ e Portal/)
│       ├── Cms/
│       └── Portal/
├── Feature/V2/                 # Suíte "V2 Feature"
│   ├── TestCase.php            # Base da suíte Feature (aplica DatabaseTransactions)
│   ├── Core/
│   ├── Services/
│   ├── Modules/
│   └── Layouts/
└── api/                        # Harness manual (scripts shell, ex.: unidade-regional-test.sh)
```

### Pontos-chave da estrutura

- **Suítes definidas no `phpunit.xml`:** `"V2 Unit"` varre `./tests/Unit/V2` e
  `"V2 Feature"` varre `./tests/Feature/V2` (sufixo `Test.php`).
- **Bases por suíte:** `tests/Unit/V2/TestCase.php` expõe o helper `invokeMethod()`
  para invocar métodos privados/protegidos; `tests/Feature/V2/TestCase.php` já aplica
  `DatabaseTransactions` automaticamente — o trait não precisa ser repetido nos testes.
- **Espelhamento estrito:** `V2/Services/FeedRSS/FeedRssService.php` → teste em
  `tests/Unit/V2/Services/FeedRSS/FeedRssServiceTest.php`. `V2/Modules/Conexoes/Associados/`
  → teste em `tests/Unit/V2/Modules/Conexoes/Associados/`. Sem atalhos de caminho.
- **`tests/api/`** é um harness **manual** (scripts bash que exercitam endpoints reais
  via curl), fora das suítes automatizadas.

## 2. Regras de escrita

### 2.1 Proporção mínima

- **1 teste unit + 1 teste feature por feature nova.** Sem exceção para código
  novo relevante. Isso garante que a lógica interna (unit) e a integração
  controller/rota (feature) sejam cobertas.

### 2.2 O que vai em cada suíte

| Suíte | Escopo | Nada de |
|-------|--------|---------|
| **Unit** (`tests/Unit/V2/`) | services, helpers, models | HTTP (sem `$this->get/post/json`) |
| **Feature** (`tests/Feature/V2/`) | controllers, rotas, integração | — |

- Unit testa **lógica pura**: métodos de serviço, DTOs, parsers, modelos isolados.
  Não faz chamadas HTTP e evita acoplar ao container de requests.
- Feature testa **fluxos reais**: chamadas a rotas, resposta de controllers,
  integração com banco e middleware.

### 2.3 Banco e transações

- A base Feature aplica `DatabaseTransactions` automaticamente. Os testes usam o
  **banco real do `.env`** (PostgreSQL). **Não há `.env.testing`** — não crie um.
- Na suíte Unit, adicione `use DatabaseTransactions;` **somente quando o teste
  escrever no banco** (ex.: model com `saved`, serviço que persiste). Testes de
  lógica pura não precisam.

### 2.4 Mocks e classes anônimas

- **Mocks apenas para serviços externos**: APIs remotas, envio de e-mail, etc.
  Nunca mocke código interno da V2 sem motivo.
- **Prefira classes anônimas em vez de `createMock()`** para double de classes
  internas. Isso é o *workaround* padrão para a combinação Mockery 0.9 + PHP 7.4,
  que é instável com `createMock()` para certas classes finais/privadas.

```php
$service = new class($deps) extends ServiceReal {
    public function chamaExterna(): string
    {
        return 'fake';
    }
};
```

### 2.5 Nomenclatura

- Convenção única: método anotado com **`/** @test */`** e **nome descritivo em
  camelCase** (frase, não `test_` prefixado).

```php
/** @test */
public function geraTokenComFormatoValido()
{
    // ...
}
```

### 2.6 Sintaxe e compatibilidade

- **Sintaxe PHP 7.4 permitida**: arrow functions (`fn()`), propriedades tipadas e
  `??=` são ok.
- **API PHPUnit ~6.0**: mantenha compatibilidade com a versão do framework — use
  os métodos de assert e convenções da API PHPUnit 6 (`assertStatus`, `assertJson`,
  etc.), não recursos de versões mais novas.

## 3. Execução

**Os testes SEMPRE rodam dentro do container Docker (serviço `app`). Nunca executar
no host.** Todo comando PHP/teste usa `docker compose exec app ...`.

```bash
# Suíte Unit
docker compose exec app vendor/bin/phpunit --testsuite "V2 Unit"

# Suíte Feature
docker compose exec app vendor/bin/phpunit --testsuite "V2 Feature"

# Todas as suítes
docker compose exec app vendor/bin/phpunit

# Filtrar por teste específico
docker compose exec app vendor/bin/phpunit --testsuite "V2 Unit" --filter NomeDoTeste
```

### Após criar classe nova

O `composer.json` usa `classmap-authoritative` + `optimize-autoloader`. Sem regerar
o autoload, a classe nova não é encontrada. **Rode sempre:**

```bash
docker compose exec app composer dump-autoload
```

## 4. Checklist de verificação pré-entrega

Antes de declarar a tarefa pronta:

- [ ] `docker compose exec app composer dump-autoload` (após adicionar classe nova).
- [ ] Suíte Unit verde: `docker compose exec app vendor/bin/phpunit --testsuite "V2 Unit"`.
- [ ] Suíte Feature verde: `docker compose exec app vendor/bin/phpunit --testsuite "V2 Feature"`.
- [ ] Zero `dd()` / `dump()` / `var_dump()` no código entregue (testes e fonte).
- [ ] Testes espelham o caminho `V2/` da classe sob teste.
- [ ] Feature test aplica `DatabaseTransactions` (automático na base) — sem poluir o banco real.
- [ ] Nenhum teste foi executado no host.

## 5. Testes UI/UX

Testes de consistência visual, acessibilidade e padrões de interação.
Localizados em `tests/Unit/V2/Layouts/Cms/` e `tests/Unit/V2/Layouts/Portal/`.
São **file-content-based** — leem arquivos Blade/CSS e validam padrões via string.

### 5.1 Categorias de teste

| Classe                              | O que valida                                                          |
| ----------------------------------- | --------------------------------------------------------------------- |
| `CmsButtonConsistencyTest`            | Padrão de classes de botão (`btn-primary`, `btn-outline-secondary`, `fw-bold`) |
| `PortalColorComplianceTest`           | Ausência de hex hardcoded, uso de CSS variables (`--tenant-*`)         |
| `CmsFormPatternTest`                  | Labels associados, `required`, confirmação em delete, `@method('PUT')`  |
| `CmsAccessibilityTest`                | Alt text, skip links, `aria-label`, `role="dialog"`, `<caption>`       |
| `CmsComponentUsageTest`               | Uso de `table-actions`, `status-badge`, `_confirm-modal`, `empty-state` |
| `CmsInteractionTest`                  | Loading states, confirmação em delete, Spotlight search, back-to-top  |

### 5.2 Padrões esperados

**Botões (CMS):**
- Save/submit: `btn btn-primary fw-bold d-inline-flex align-items-center gap-1`
- Back/cancel: `btn btn-outline-secondary`
- Delete/archive: `btn btn-outline-danger` ou `btn btn-danger`
- **Proibido**: `font-weight-bold` (usar `fw-bold`), `btn-xs` (inválido BS5)

**Cores (Portal):**
- Views NÃO devem conter hex hardcoded (`#xxx`) — exceto `colors.blade.php`
- Views devem usar `--tenant-primary`, `--tenant-secondary`, `--tenant-accent`
- Login CMS não deve sobrescrever tema com `style="background-color: ..."`

**Formulários (CMS):**
- Todo `<input>` tem `<label for>` ou `aria-label`
- Campos obrigatórios têm `required` ou `aria-required`
- Delete/archive têm confirmação (`confirm()` ou modal `_confirm-modal`)
- Updates usam `@method('PUT')` ou `@method('PATCH')`

**Acessibilidade (eMAG/WCAG):**
- Imagens `<img>` têm `alt` descritivo
- Botões icon-only têm `aria-label`
- Modais têm `role="dialog"`
- Tabelas têm `<caption>` ou `aria-label`

### 5.3 Como rodar

```bash
# Todos os testes UI/UX
docker compose exec app vendor/bin/phpunit --testsuite "V2 Unit" --filter "Layouts/(Cms|Portal)/"

# Apenas consistência de botões
docker compose exec app vendor/bin/phpunit tests/Unit/V2/Layouts/Cms/CmsButtonConsistencyTest.php

# Apenas conformidade de cores
docker compose exec app vendor/bin/phpunit tests/Unit/V2/Layouts/Portal/PortalColorComplianceTest.php

# Apenas acessibilidade
docker compose exec app vendor/bin/phpunit tests/Unit/V2/Layouts/Cms/CmsAccessibilityTest.php
```

### 5.4 Nota sobre falhas intencionais

Alguns testes UI/UX **falham propositalmente** — eles encontram inconsistências
reais no código. Isso é o comportamento esperado. As falhas servem como
**inventário de débito técnico** para correção gradual.

## 6. Roadmap (recomendações futuras)

Melhorias planejadas, ainda não implementadas:

- **Corrigir inconsistências UI/UX** encontradas pelos testes (font-weight-bold → fw-bold, btn-xs, hex hardcoded, delete forms sem confirmação).
- **Adotar componente `button.blade.php`** para loading states em todos os formulários CMS.
- **Factories + Faker** em `database/factories/` — reduzir a verbosidade de
  provisionamento de estado (usuários, roles, registros).
- **`.env.testing` + `migrate:fresh`** para isolamento completo do banco de
  desenvolvimento e execução em paralelo.
- **Xdebug no Dockerfile** para *coverage* real. O `phpunit.xml` já tem
  `coverage-clover` (`reports/clover.xml`) e `junit` (`reports/junit.xml`) configurados.
- **CI** em `.github/workflows` — rodar as suítes automaticamente a cada push/PR.
- **Laravel Dusk** para testes comportamentais (clique real, estados visuais, JavaScript).
