# Glossário — Estratégia de Testes

> O legado não possui testes automatizados para este módulo (não há suíte em `v6/tests`
> que cobre `GlossaryController`). A v7 precisa de cobertura de feature e unit.

---

## 1. Estratégia

| Tipo | Objeto | Ferramenta sugerida (v7) |
|---|---|---|
| Feature | Rotas públicas `/glossario` e `/glossario-ajax/{letra}` | Pest ou PHPUnit + `RefreshDatabase` |
| Feature | Rotas do CMS (listar/criar/editar/excluir) | Pest + `actingAs` usuário com permissões |
| Unit | Normalização do termo (`normalized_term`) | PHPUnit puro (sem banco) |
| Integração | Busca global incluindo o glossário | Feature test do `/buscar` |
| Regressão de dado | Migração `contents` -> `glossary_terms` | Teste de migração com seed controlado |

## 2. Fixtures / factories necessárias

```php
// exemplo ilustrativo — v7
class GlossaryTermFactory extends Factory
{
    protected $model = GlossaryTerm::class;

    public function definition(): array
    {
        return [
            'term' => fake()->unique()->word(),
            'normalized_term' => Str::ascii(Str::lower(fake()->unique()->word())),
            'definition' => '<p>Definição de teste</p>',
            'status' => true,
        ];
    }
}
```

Categorias usadas no teste (seeds do ambiente):

| Seed | Uso |
|---|---|
| `v6/database/seeds/CategoryContentTableSeeder.php` (categoria `glossario`, id 11) | Recreate da categoria para testes que exercitem o CRUD genérico legado |
| `v6/database/seeds/ResourcesTableSeeder.php` (`glossario` -> modulo 24) | Permissões `glossario.*` para os testes de CMS |
| `v6/database/migrations/2024_11_01_150206_create_modulos_table.php` | Registro do módulo no menu do CMS |

## 3. Casos de teste — Portal

| # | Cenário | Arrange | Act | Assert |
|---|---|---|---|---|
| T1 | Página do glossário renderiza o índice A–Z | layout ativo `modelo1` | `get('/glossario')` | status 200; resposta contém 26 botões de letra |
| T2 | Carga "all" traz todos os verbetes | 3 verbetes | `get('/glossario-ajax/all')` | JSON `letterActive = ''`; `contentGlossary` com 3 itens |
| T3 | Filtro por letra | verbetes "Alíquota", "Balanço" | `get('/glossario-ajax/A')` | retorna apenas "Alíquota" |
| T4 | Letra sem resultados | nenhum verbete com "Z" | `get('/glossario-ajax/Z')` | `contentGlossary` vazio (array) |
| T5 | Resposta JSON não vaza campos internos | 1 verbete | `get('/glossario-ajax/all')` | no legado: chaves `id`,`title`,`text` presentes (documentar o risco); na v7: apenas `id`,`term`,`definition` |
| T6 | Verbete desativado não aparece (comportamentonovo) | `status = false` | `get('/glossario-ajax/all')` | v7: não retorna o verbete |
| T7 | Busca global encontra o verbete | verbete "Tributação" | `get('/buscar?text=Tributação')` / `post('/buscando')` | resultado contém o verbete e a categoria `glossario` |
| T8 | Busca sem acento encontra termo com acento | verbete "Alíquota" | buscar por "aliquota" | resultado encontrado (normalização do `FilterSearchAllSite`) |
| T9 | Layout `default` responde | template ativo `default` | `get('/glossario')` | v6: erro (view ausente) — registrar como bug; v7: status 200 |

## 4. Casos de teste — CMS

| # | Cenário | Arrange | Act | Assert |
|---|---|---|---|---|
| T10 | Listagem carrega o DataTable | usuário com `glossario.*`; 2 verbetes | `get('/cms/conteudos/glossario')` | status 200; HTML contém `tabela_glossario` |
| T11 | DataTable responde JSON | idem | `get('/cms/datatable/glossario')` | `data` com 2 linhas; cada linha com `edit`,`delete`,`active`,`inactivate` |
| T12 | Criar verbete | usuário com `glossario.create` | `post('/cms/conteudo', ['title'=>'Alíquota','text'=>'<p>Def</p>','category_contents_id'=>11])` | 201/302; registro em `contents` |
| T13 | Criar sem título | idem | `post` sem `title` | 302 com erros de validação; nenhum registro criado |
| T14 | Título acima de 120 caracteres | idem | `post` com `title` de 121 chars | falha de validação (`max:120`) |
| T15 | Editar verbete | verbete existente | `put('/cms/conteudo/{id}', ['title' => 'Alíquota', 'text' => '<p>Nova</p>', 'category_contents_id' => 11])` | texto atualizado |
| T16 | Excluir (soft delete) | verbete existente | `delete('/cms/conteudo/{id}')` | `deleted_at` preenchido; verbete fora da view `glossario` |
| T17 | Exclusão em lote | 2 verbetes marcados | `post('/cms/conteudo/deleteAll', ['toDelete' => [10, 11]])` | ambos removidos (soft delete) |
| T18 | Usuário sem permissão não acessa | usuário sem `glossario.create` | `get('/cms/conteudos/glossario')` | 403/redirect pelo `check.route.permission` |

## 5. Casos de teste — Regras de dados

| # | Cenário | Arrange | Act | Assert |
|---|---|---|---|---|
| T19 | View `glossario` reflete o `contents` | 3 verbetes, 1 soft-deleted | consultar a view | 2 linhas (`deleted_at IS NULL`) |
| T20 | `value` da view é sequencial | 3 verbetes com `created_at` distintos | consultar a view | `value` 1..3 em ordem `created_at DESC` |
| T21 | Nenhum verbete em categoria inexistente | categoria removida | `get('/glossario-ajax/all')` | lista vazia, sem erro 500 |

## 6. Como rodar

Legado (v6), verificações manuais:

```bash
cd /home/one/projects/maxima/v7/v6
php artisan route:list --name=glossario
php artisan serve
# portal:  http://localhost:8000/glossario
# ajax:    http://localhost:8000/glossario-ajax/all
# cms:     http://localhost:8000/cms/conteudos/glossario  (requer login)
# datatable: http://localhost:8000/cms/datatable/glossario
```

v7 (proposto):

```bash
php artisan test --filter=Glossary
php artisan test --testsuite=Feature --group=glossario
```

## 7. Dados de teste para o ambiente

| Item | Origem |
|---|---|
| Verbo "Alíquota" | seed de demonstração do CMS (`v6/database/seeds/ContentsTableSeeder.php`) |
| Categorias | `v6/database/seeds/CategoryContentTableSeeder.php` |
| Usuário com permissões | `v6/database/seeds/RolesTableSeeder.php` (papéis do CMS) |

## 8. Critérios de aceite da suíte

1. Todos os casos T1–T21 passam na v7.
2. T9 registra a correção do bug de layout ausente.
3. T5 verifica que o JSON público não expõe campos internos.
4. A migração `contents` -> `glossary_terms` mantém a contagem de verbetes (verificado por
   teste automatizado sobre um dump anonimizado).
