# Destaques — Estratégia de Testes

## 1. Estado atual

O módulo **não possui nenhum teste**. A suíte existente em `v6/tests` cobre apenas o
Dashboard (`v6/tests/Feature/Dashboard*Test.php`), Google Analytics e revisões:

```
v6/tests/Feature/Dashboard*Test.php
v6/tests/Feature/GaConfigurationTest.php
v6/tests/Feature/GaWidgetsTest.php
v6/tests/Feature/RevisoesWidgetTest.php
v6/tests/Unit/Dashboard*Test.php
v6/tests/Unit/GoogleAnalyticsServiceTest.php
```

Configuração: `v6/phpunit.xml` (PHPUnit, suítes `Feature` e `Unit`, `bootstrap="vendor/autoload.php"`).
Base: `v6/tests/TestCase.php` e `v6/tests/CreatesApplication.php`.

A factory `v6/database/factories/HighlightFactory.php` existe mas está **vazia**
(retorna `[]`), portanto não serve como fixture.

## 2. Estratégia proposta

| Camada | Tipo | Foco |
|---|---|---|
| Unit | `tests/Unit/HighlightTest.php` | Model: casts, relação `archive()`, scope de publicado |
| Feature | `tests/Feature/HighlightControllerTest.php` | CRUD, reordenação, upload, toggle de status, permissões |
| Feature | `tests/Feature/HighlightPortalTest.php` | Renderização do carrossel na home e fallback para notícias |
| Feature | `tests/Feature/HighlightDatatableTest.php` | Endpoint do grid (colunas expostas pela view `highlight`) |

## 3. Fixtures necessárias

```php
// database/factories/HighlightFactory.php
$factory->define(\App\Http\Model\Prefecture\Highlight::class, function (Faker $faker) {
    return [
        'title'        => $faker->sentence(3),
        'subtitle'     => $faker->sentence(6),
        'text_button'  => 'Saiba mais',
        'url'          => $faker->url,
        'position'     => 1,
        'status'       => true,
        'status_button'=> true,
        'layout'       => 1,
        'is_blank'     => false,
    ];
});
```

Para o `Archive` da imagem:

```php
// database/factories/ArchiveFactory.php (trecho)
'path'        => 'storage/highlights/1/imagem.png',
'name'        => 'imagem.png',
'extension'   => 'png',
'type'        => 'image/png',
'highlight'   => 1,
'highlight_id'=> 1,
```

Imagem de teste: um PNG 1x1 gerado em `storage/framework/testing/destaque.png` e
injetado via `Storage::fake('public')`.

## 4. Casos de teste

### 4.1 Model (Unit)

| # | Arrange | Act | Assert |
|---|---|---|---|
| U1 | `Highlight::factory()->create(['status' => true])` | `$h->status` | `true` (após `cast`) |
| U2 | Destaque com `Archive` vinculado | `$h->archive->path` | Valor do `path` |
| U3 | Destaque sem `Archive` | `$h->archive` | `null` |
| U4 | 3 destaques, `position` 1,2,3 | `Highlight::published()->pluck('position')` | `[1,2,3]` em ordem |
| U5 | Destaque com `status = false` | `Highlight::published()` | Não retorna o registro |

### 4.2 Controller — CRUD (Feature)

| # | Arrange | Act | Assert |
|---|---|---|---|
| C1 | Usuário autenticado com permissão | `POST /cms/destaques` com imagem válida | `assertDatabaseHas('highlights', [...])`; redirect para `destaques.index` |
| C2 | Mesmo cenário | `POST /cms/destaques` sem imagem | `assertSessionHasErrors('archive_highlight')`; nenhum registro criado |
| C3 | Mesmo cenário | `POST` com `url` vazia | `assertSessionHasErrors('url')` |
| C4 | Destaque existente | `PUT /cms/destaques/{id}` alterando o título | `assertDatabaseHas('highlights', ['id' => $id, 'title' => 'Novo'])` |
| C5 | Destaque existente | `DELETE /cms/destaques/{id}` | `assertDatabaseMissing('highlights', ['id' => $id])`; `assertDatabaseMissing('archives', ['highlight_id' => $id])` |
| C6 | Destaque existente | `DELETE /cms/destaques/{id}` | Arquivo removido de `storage/highlights/{id}/` (**comportamento novo**, ausente no legado) |

### 4.3 Reordenação (Feature)

| # | Arrange | Act | Assert |
|---|---|---|---|
| R1 | Destaques nas posições 1, 2, 3 | Criar novo com `position = 2` | Posições passam a 1, 3, 4 (2 → 3, 3 → 4) |
| R2 | Destaques nas posições 1, 2, 3 | Editar o de posição 3 para `position = 1` | Posições passam a 2, 1, 3 — rebalanceadas |
| R3 | Destaques nas posições 1, 2, 3 | Editar o de posição 1 para `position = 3` | Posições passam a 1, 2, 3 — rebalanceadas |
| R4 | Formulário `create` | `GET /cms/destaques/create` | A view recebe `position` = primeira livre |

### 4.4 Status (Feature)

| # | Arrange | Act | Assert |
|---|---|---|---|
| S1 | Destaque com `status = true` | `POST /cms/destaques/{id}/status` | `status` passa a `null` (legado) / `false` (v7) |
| S2 | Destaque com `status = null` | `POST /cms/destaques/{id}/status` | `status` passa a `true` |
| S3 | Destaque inexistente | `POST /cms/destaques/999/status` | HTTP 500 com JSON `success` (comportamento legado) |
| S4 | Usuário sem permissão | `POST /cms/destaques/{id}/status` | HTTP 403 (v7 com Policy) |

### 4.5 Portal (Feature)

| # | Arrange | Act | Assert |
|---|---|---|---|
| P1 | 2 destaques com `status = true` | `GET /` | A view da home contém o título de ambos |
| P2 | Nenhum destaque ativo | `GET /` | A home exibe o carrossel de notícias (fallback) |
| P3 | Destaque com `status_button = false` | `GET /` | O texto do botão **não** aparece na resposta |
| P4 | Destaque com `layout = 1` e `status = true` | `GET /` | `$highlightFullScreen` não é `null` |
| P5 | Destaque ativo sem `Archive` | `GET /` | Não há erro ("Trying to get property of null") — o Blade usa `?? null` |

### 4.6 Datatable (regressão)

| # | Arrange | Act | Assert |
|---|---|---|---|
| D1 | — | `GET /cms/datatable/highlight` | HTTP 200 e JSON com `titulo`/`posicao` (vindos da view `highlight`) |

## 5. Cenários manuais (QA)

1. `/cms/destaques` → a lista carrega sem erro de SQL, com as colunas da view `highlight`.
2. Criar destaque com imagem PNG de 2 MB → arquivo em `storage/highlights/<id>/`.
3. Validar upload de arquivo não-imagem (`.pdf`) → mensagem "deve ser uma imagem válida".
4. Validar upload acima de 20 MB → mensagem de tamanho.
5. Publicar e abrir a home → o carrossel aparece; despublicar → volta ao de notícias.
6. Mover a posição de um destaque e recarregar a lista → ordem coerente.

## 6. Como rodar

```bash
cd v6

# suíte completa
./vendor/bin/phpunit

# apenas o módulo
./vendor/bin/phpunit tests/Feature/HighlightControllerTest.php
./vendor/bin/phpunit tests/Feature/HighlightPortalTest.php

# filtro por método
./vendor/bin/phpunit --filter test_reordenacao_ao_criar
```

Ambiente de teste: `.env.testing` com `DB_CONNECTION=pgsql`, base de testes isolada.
Como o módulo grava em `storage/highlights/`, usar `Storage::fake('public')` e
`Storage::fake('highlights')` para não tocar no disco.
