# Drive — Estratégia de Testes

## 1. Estratégia

| Tipo | Ferramenta (v7) | Escopo |
|---|---|---|
| Feature (HTTP) | PHPUnit + `RefreshDatabase` + `Storage::fake('public')` | upload, listagem, exclusão, reordenação |
| Unit | PHPUnit | geração de nome, compressão, path |
| Integração | storage em disco de teste | gravação das versões `_min`, `_med`, `_larg` |
| Manual | checklist no CMS | grade, busca, copiar, baixar, excluir |

O legado **não tem** testes automatizados. O comportamento de maior risco é a autorização (hoje
qualquer usuário logado manipula arquivos) e o escopo da listagem.

## 2. Fixtures e factories

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

    public function definition(): array
    {
        return [
            'collection' => 'drive',
            'name' => 'foto.png',
            'file_name' => 'abc123.png',
            'mime_type' => 'image/png',
            'extension' => 'png',
            'size' => 1024,
            'disk' => 'public',
            'path' => 'media/drive/abc123.png',
            'sort_order' => 0,
        ];
    }

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

Para testar o legado (tabela `archives`), a fixture precisa:

| Campo | Valor |
|---|---|
| `name` | nome gerado |
| `path` | `storage/content/midias/<nome>` |
| `extension` | `png` |
| `type` | `image/png` |
| `hash` | md5 do arquivo |
| `contents_id` | `NULL` (Drive) ou o id do conteúdo (galeria) |

Seed de ambiente: categoria `midias` (id 31) e módulo `drive`.

## 3. Casos de teste

### 3.1 Upload

| # | Cenário | Arrange | Act | Assert |
|---|---|---|---|---|
| T1 | Upload de imagem no Drive | usuário logado | `POST /api/v1/cms/media` com `files[]` | 201; registro criado com `collection = drive` e `model_id` nulo |
| T2 | Arquivo gravado no disco | `Storage::fake('public')` | idem | o arquivo existe em `media/drive/` |
| T3 | Tipos não permitidos são rejeitados | — | `POST` com `.exe` | 422 |
| T4 | Arquivo acima do limite é rejeitado | — | `POST` com 30 MB | 422 |
| T5 | Upload múltiplo | — | `POST` com 3 arquivos | 3 registros criados |
| T6 | Nome original preservado | — | `POST` com `foto-da-cidade.png` | `name = foto-da-cidade.png` e `file_name` diferente |
| T7 | Versões da imagem geradas | `Storage::fake('public')` | `POST` com PNG 1200x800 | existem `*_min`, `*_med` e `*_larg` |
| T8 | Largura e altura preenchidas | idem | idem | `width = 1200`, `height = 800` |

### 3.2 Listagem

| # | Cenário | Arrange | Act | Assert |
|---|---|---|---|---|
| T9 | Drive lista apenas a coleção `drive` | 2 em `drive`, 3 em `galeria` | `GET /api/v1/cms/media?collection=drive` | apenas 2 itens |
| T10 | Paginação | 30 arquivos | `GET ?collection=drive&per_page=10` | 10 itens + metadados de paginação |
| T11 | Busca por nome | arquivos `cidade.png` e `escola.png` | `GET ?collection=drive&q=cidade` | apenas `cidade.png` |
| T12 | Ordem crescente por `sort_order` | — | `GET ?collection=drive` | ordenação respected |

### 3.3 Exclusão e ações

| # | Cenário | Arrange | Act | Assert |
|---|---|---|---|---|
| T13 | Excluir remove registro e arquivo | arquivo no disco | `DELETE /api/v1/cms/media/{id}` | 204; registro removido; arquivo ausente do disco |
| T14 | Download exige autenticação | usuário anônimo | `GET /api/v1/cms/media/{id}/download` | 401/403 |
| T15 | Permissão de exclusão | usuário sem `drive.delete` | `DELETE /api/v1/cms/media/{id}` | 403 |
| T16 | Reordenação | 3 arquivos | `PUT /api/v1/cms/media/ordem` com a nova ordem | `sort_order` = 1, 2, 3 |

### 3.4 Regressão do comportamento legado (documenta o que muda)

| # | Cenário | Assert |
|---|---|---|
| T17 | No legado, a listagem do Drive retorna arquivos de todos os módulos | teste do sistema legado, para dimensionar a mudança |
| T18 | No legado, a exclusão mantém o arquivo físico | idem |

## 4. Fixtures de view/seed

| Item | Origem |
|---|---|
| Categoria `midias` | `v6/database/seeds/CategoryContentTableSeeder.php` |
| Módulo `drive` | `v6/database/migrations/2024_11_01_150206_create_modulos_table.php` |
| Resource `drive` | `v6/database/seeds/ResourcesTableSeeder.php` |
| Permissões | `v6/database/seeds/RolesTableSeeder.php` (hoje `midias.*`) |
| Diretório de arquivos | `v6/storage/content/midias` (em produção: `public/storage/content/midias`) |

## 5. Como rodar

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

# módulo
php artisan test --filter=Media

# feature do upload
php artisan test tests/Feature/Cms/MediaUploadTest.php

# com storage falso e fila sync
php artisan test --filter=Media --without-queue
```

Com Pest:

```bash
pest tests/Feature/Cms/MediaTest.php
```

## 6. Checklist manual (v6)

1. Abrir `Drive` no menu lateral do CMS.
2. Enviar 3 imagens (uma JPG, uma PNG e um PDF) e observar a pré-visualização.
3. Digitar parte do nome na busca e confirmar o filtro (e observar o erro de JavaScript no console,
   descrito em `08-GAPS-E-DIVIDAS.md`).
4. Rolar a página e confirmar o carregamento progressivo.
5. Usar “Copiar” e colar a URL no navegador.
6. Usar “Baixar” e “Visualizar”.
7. Excluir um arquivo e confirmar que ele some da grade.
8. Abrir a galeria de uma notícia e confirmar que o upload vai para a pasta do conteúdo.
