# Suporte — Estratégia de Testes

> O módulo **não tem testes** na v6. Given o tamanho da entrega, a
> cobertura aqui proposta cobre a página ativa (caminho A) e, como
> opcional, o sistema de tickets (caminho B).

---

## 1. Precedente de harness

`v6/tests/DashboardTestCase.php`:
`createRole()`, `createUser()`, `setModules()`, `DatabaseTransactions`,
`withoutMiddleware(VerifyCsrfToken::class)`.

Para o módulo de suporte, o helper útil é `createUser()`, que autentica
um operador e cria a sessão.

---

## 2. Estratégia

| Tipo | Escopo |
|---|---|
| **Feature** | Acesso à página, exigência de login, renderização do fornecedor ativo, estado vazio |
| **Unit** | Nada a unit-testar no caminho A (a view faz tudo) |
| **Feature (caminho B)** | Abertura de ticket, protocolo, notificações, autorização |

---

## 3. Fixtures necessárias

### 3.1 Factory (caminho A)

```php
// database/factories/SupplierFactory.php
class SupplierFactory extends Factory
{
    protected $model = Supplier::class;

    public function definition(): array
    {
        return [
            'name'      => fake()->company(),
            'slug'      => fake()->unique()->slug(),
            'email'     => fake()->companyEmail(),
            'site'      => fake()->url(),
            'phone'     => fake()->numerify('###########'),
            'address'   => fake()->address(),
            'locale'    => 'https://www.google.com/maps/embed?pb=test',
            'image'     => 'img/icons_fornecedores/test.png',
            'icon'      => 'img/icons_fornecedores/test-icon.png',
            'fornecedor_ativo' => false,
        ];
    }

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

> O `SuplierTableSeeder` (`v6/database/seeds/SuplierTableSeeder.php`)
> faz `DB::table('suppliers')->truncate()` — ele **apaga** os dados. Não
> deve ser executado em teste; use a factory.

### 3.2 Configurações (caminho B)

O `SupportController` (órfão) lê as chaves `email`, `email_suporte` e
`titulo_site` da tabela `configurations`. O seeder
`v6/database/seeds/ConfigurationsTableSeeder.php` as popula. Em teste,
inserir apenas o necessário:

```php
DB::table('configurations')->insert([
    ['key' => 'email',         'value' => 'prefeitura@example.com'],
    ['key' => 'email_suporte', 'value' => 'suporte@example.com'],
    ['key' => 'titulo_site',   'value' => 'Prefeitura Teste'],
]);
```

---

## 4. Casos de teste

### 4.1 Página de suporte (caminho A)

| # | Arrange | Act | Assert |
|---|---|---|---|
| A1 | Sem autenticação | `GET /cms/suporte` | 302 (middleware `check.logged` redireciona ao dashboard) |
| A2 | Usuário autenticado, fornecedor ativo existente | `GET /cms/suporte` | 200 + view `admin.layouts.about` |
| A3 | Idem | o HTML | contém o nome, o e-mail, o telefone, o WhatsApp, o endereço e o `locale` no `iframe` |
| A4 | Usuário autenticado, **nenhum** fornecedor ativo | `GET /cms/suporte` | 200 + **HTML sem** o cartão do fornecedor (comportamento atual); na v7: mensagem "Nenhum fornecedor ativo cadastrado" |
| A5 | Dois fornecedores ativos | `GET /cms/suporte` | 200; apenas **um** é exibido (o `first()`); comportamento **não determinístico** — registrar como bug |
| A6 | Fornecedor com `image` nulo | `GET /cms/suporte` | 200 + `<img src=".../storage/">` quebrada |
| A7 | Usuário autenticado | a rota `informacoes-instituicao` existe | `route('informacoes-instituicao')` resolve sem exceção |
| A8 | Usuário autenticado | o menu do AdminLTE | o HTML contém o link "Suporte" apontando para `/cms/suporte` |

### 4.2 Segurança do entorno (caminho A, mas crítico)

| # | Arrange | Act | Assert |
|---|---|---|---|
| S1 | Qualquer visitante | `GET /init` | **hoje: 200 e cria `admin@admin.com` / `123123`**; na v7: **404** (rota removida) |
| S2 | Qualquer visitante | `GET /cms/modulos` | 302 (exige `check.logged`) |
| S3 | Usuário autenticado | `POST /cms/fornecedores_switch` | na v6: **sem** `check.logged` — registrar como falha (ver dossiê `fornecedores`) |

### 4.3 Sistema de tickets (caminho B — opcional)

| # | Arrange | Act | Assert |
|---|---|---|---|
| T1 | Usuário autenticado | `POST /api/support/tickets` com categoria, assunto e descrição | 201; linha em `support_tickets` com `protocol` preenchido |
| T2 | Idem, sem `subject` | `POST` | 422 com erro em `subject` |
| T3 | Idem, `description` com 3 caracteres | `POST` | 422 (min:5) |
| T4 | Idem | `POST` duas vezes em paralelo | protocolos **distintos** (bug do `max('id')+1`) |
| T5 | Ticket criado | `assertDatabaseHas('support_tickets', ...)` | `user_id` preenchido; `status = 'open'` |
| T6 | Ticket criado | `Notification::fake()` | notificação enviada ao e-mail de suporte **e** ao usuário |
| T7 | Perfil sem `suporte.index` | `GET /api/support/tickets` | 403 |
| T8 | Perfil sem `suporte.edit` | `POST /api/support/tickets/{ticket}/answer` | 403 |
| T9 | Usuário comum | `GET /api/support/tickets/{ticket}` de outro usuário | 403 |
| T10 | Ticket existente | `GET /api/support/tickets/{ticket}` | JSON com `protocol`, `subject`, `status`, `category`, `user` |
| T11 | Ticket existente | `PATCH /api/support/tickets/{ticket}` | `status` muda para `answered` |

### 4.4 Contrato de rota (caminho B)

| # | Arrange | Act | Assert |
|---|---|---|---|
| R1 | — | `route('suporte.index')` | resolve (hoje: lança `RouteNotFoundException`) |
| R2 | — | `route('suporte.create')` | resolve (hoje: idem) |
| R3 | — | `route('suporte.show', 1)` | resolve (hoje: idem) |
| R4 | — | `route('email')` | resolve (hoje: idem) |

---

## 5. Fixtures de view

| View | Variáveis |
|---|---|
| `admin.layouts.about` | injetado `dadosFornecedor` (model `Supplier`); usa `$fornecedor` |
| `prefecture.support.index` | `contents` (Collection de `Support`) — órfã |
| `prefecture.support.create` | `categories` (Collection) — órfã |
| `prefecture.support.show` | `content` (`Support`) — órfã |

---

## 6. Como rodar

```bash
cd v6/
composer install
./vendor/bin/phpunit --testsuite Feature
./vendor/bin/phpunit tests/Feature/Support/SupportPageTest.php
./vendor/bin/phpunit --filter testPaginaDeSuporteExibeFornecedorAtivo
```

Ambiente (de `v6/phpunit.xml`): `APP_ENV=testing`,
`CACHE_DRIVER=array`, `SESSION_DRIVER=array`, `QUEUE_DRIVER=sync`.

> A suíte usa `DatabaseTransactions`; o banco de teste precisa estar
> migrado. O `SupplierFactory` deve substituir o `SuplierTableSeeder`
> (que faz `truncate`).

---

## 7. Cobertura mínima aceitável para a v7

| Caminho | Arquivo de teste | Casos |
|---|---|---|
| A | `tests/Feature/Support/SupportPageTest.php` | A1-A8 |
| A | `tests/Feature/Support/InitRouteSecurityTest.php` | S1-S3 |
| B | `tests/Feature/Support/SupportTicketTest.php` | T1-T11 |
| B | `tests/Feature/Support/SupportRouteContractTest.php` | R1-R4 |

O caso **S1** (`GET /init`) deve ser tratado como **P0** na v7: a rota
precisa ser removida e o teste deve garantir que ela não volte.
