# Telefones Úteis — Estratégia de Testes

## 1. Estratégia

| Tipo | Ferramenta (v7) | Escopo |
|---|---|---|
| Feature (HTTP) | PHPUnit + `RefreshDatabase` | rotas do portal e do CMS, validação, permissões |
| Unit | PHPUnit | máscaras, presenters, helpers de view |
| Integração | Pest ou PHPUnit com PostgreSQL de teste | view SQL equivalente, ordenação |
| Manual | checklist no CMS | DataTable, exportações, exclusão em lote |

No legado **não existe** suíte de testes automatizados para este módulo; a verificação era manual.
A v7 deve cobrir, no mínimo, o contrato público (rota + listagem) e o contrato de escrita do CMS.

## 2. Fixtures e factories

```php
// database/factories/UsefulPhoneFactory.php  (exemplo ilustrativo)
class UsefulPhoneFactory extends Factory
{
    protected $model = UsefulPhone::class;

    public function definition(): array
    {
        return [
            'title' => 'Secretaria de Saúde',
            'phone' => '(88) 99999-9999',
            'slug' => Str::slug(Str::random(8)),
            'active' => true,
            'sort_order' => 1,
        ];
    }

    public function inativo(): static
    {
        return $this->state(fn () => ['active' => false]);
    }
}
```

Para testar o legado (tabela `contents`), a factory equivalente precisa criar:

| Campo | Valor |
|---|---|
| `title` | nome do setor |
| `text` | telefone |
| `category_contents_id` | id da categoria `telefones-uteis` (30) |
| `slug` | slug único |
| `status` | `true`/`false` |

Seed de ambiente de teste:

| Seed | Papel |
|---|---|
| `CategoryContentTableSeeder` (ou factory equivalente) | garante a categoria `telefones-uteis` |
| `ModulosTableSeeder` / `ResourcesTableSeeder` | garante o módulo e as permissões `telefones-uteis.*` |
| `MenuOrderSeeder` | garante o item no menu do CMS |

## 3. Casos de teste

### 3.1 Portal

| # | Cenário | Arrange | Act | Assert |
|---|---|---|---|---|
| T1 | Página pública lista os telefones | 2 conteúdos na categoria `telefones-uteis` | `GET /telefones-uteis` | status 200, ambas as views (title e text) presentes |
| T2 | Conteúdos de outras categorias não aparecem | 1 conteúdo `noticias`, 1 `telefones-uteis` | `GET /telefones-uteis` | o título da notícia não aparece na resposta |
| T3 | Conteúdo apagado não aparece | 1 telefone com `deleted_at` preenchido | `GET /telefones-uteis` | ausente na resposta |
| T4 | Telefone inativo aparece (comportamento legado) | 1 telefone com `status = false` | `GET /telefones-uteis` | **presente** na resposta (documenta a regra atual) |
| T5 | Resposta do endpoint JSON | idem T1 | `GET /api/v1/telefones-uteis` | estrutura `data[].title` / `data[].phone` |
| T6 | Filtro por texto | 3 telefones | `GET /api/v1/telefones-uteis?q=saude` | apenas o registro correspondente |

### 3.2 CMS

| # | Cenário | Arrange | Act | Assert |
|---|---|---|---|---|
| T7 | Criar telefone válido | usuário com `telefones-uteis.create` | `POST /cms/conteudo` com `title`, `text`, `category_contents_id` | 302, registro criado em `contents` com `text` = telefone |
| T8 | Título obrigatório | idem | `POST` sem `title` | erro de validação em `title` |
| T9 | Título acima de 120 caracteres | idem | `POST` com `title` de 121 chars | erro em `title` |
| T10 | Telefone obrigatório | idem | `POST` sem `text` | erro em `text` |
| T11 | `category_contents_id` inválido | idem | `POST` com `category_contents_id` não numérico | erro em `category_contents_id` |
| T12 | Editar telefone | registro existente | `PUT /cms/conteudo/{id}` | `title` e `text` atualizados |
| T13 | DataTable do CMS | 2 telefones | `GET /cms/datatable/telefones_uteis` | JSON com `data[].titulo` e `data[].id` |
| T14 | Permissões de edição | usuário sem `telefones-uteis.edit` | `GET /cms/datatable/telefones_uteis` | `data[].edit = false` |
| T15 | Exclusão em lote | 2 telefones | `POST /cms/conteudo/deleteAll` com `toDelete[]` | ambos removidos (soft delete) |
| T16 | Slug único | título já existente | `POST` com mesmo título | slug recebe sufixo, sem colisão |

## 4. Testes da view SQL (equivalente)

Para garantir paridade com o legado:

```sql
-- (exemplo ilustrativo) consulta que a view precisa reproduzir
SELECT row_number() OVER (ORDER BY c.created_at DESC) AS value,
       c.title AS titulo,
       c.id     AS id
FROM contents c
JOIN category_contents cc ON cc.id = c.category_contents_id
WHERE c.deleted_at IS NULL AND cc.slug = 'telefones-uteis'
ORDER BY c.created_at DESC;
```

| # | Cenário | Assert |
|---|---|---|
| T17 | View exclui apagados | linha apagada não aparece |
| T18 | View ordena por `created_at DESC` | `value` 1 é o registro mais recente |
| T19 | View não expõe o telefone | conjunto de colunas é exatamente `value`, `titulo`, `id` |

Se a v7 não mantiver a view SQL, T17-T19 devem ser reescritos como testes do escopo Eloquent equivalente.

## 5. Como rodar

```bash
# suíte completa
php artisan test

# apenas o módulo
php artisan test --filter=UsefulPhone

# feature tests do portal
php artisan test tests/Feature/Portal/UsefulPhoneTest.php

# com seed de categorias e permissões
php artisan test --filter=UsefulPhone --seed
```

Com Pest:

```bash
pest tests/Feature/Portal/UsefulPhoneTest.php
```

## 6. Checklist manual (v6, antes da migração)

1. Logar no CMS e abrir `Telefones Úteis` no menu lateral.
2. Cadastrar um telefone e confirmar que ele aparece na tabela com ID sequencial.
3. Editar o telefone e confirmar a alteração no portal.
4. No portal, abrir `/telefones-uteis`, digitar parte do título e confirmar o filtro.
5. Selecionar dois telefones e usar a exclusão em lote.
6. Exportar a tabela para Excel e PDF.
7. Repetir o passo 4 com cada layout disponível em `configurations.key = 'layout'`.
