# Testes — reset-item-missao

## Cobertura

| Componente | Tipo | Path | Status |
|---|---|---|---|
| `AcaoExtrato::MISSAO_REABERTA` — case exists + 3 match() | TDD unit (estático + runtime) | `componentes/Constelacoes/Logistica/MissaoLogistica/Testes/Satelites/VoltarItemPendenteTddTest.php` | ✅ pass |
| `StatusMissao` — lista de permitidos, bloqueados, rebote exclusivo | TDD unit (lógica pura) | idem | ✅ pass |
| `voltarItemPendente` — campos zerados, dados_adicionais intocado | TDD unit (análise estática + simulação) | idem | ✅ pass |
| `voltarItemPendente` — no-op item já pendente (regra 3) | TDD unit (análise estática) | idem | ✅ pass |
| `voltarItemPendente` — gating status bloqueados concluida/cancelada (AC1.6) | TDD unit (lógica pura) | idem | ✅ pass |
| `voltarItemPendente` — rebote aguardando_aprovacao → em_andamento (AC2.1) | TDD unit (lógica pura + análise estática) | idem | ✅ pass |
| `voltarItemPendente` — sem rebote para em_andamento, pausada, pendente, rascunho (AC2.2) | TDD unit (lógica pura) | idem | ✅ pass |
| `voltarItemPendente` — extrato ITEM_REINICIADO registrado (AC1.4) | TDD unit (análise estática) | idem | ✅ pass |
| `voltarItemPendente` — extrato MISSAO_REABERTA no rebote (AC2.3) | TDD unit (análise estática) | idem | ✅ pass |
| `voltarItemPendente` — mensagem diferenciada no rebote (AC2.5) | TDD unit (análise estática) | idem | ✅ pass |
| `voltarItemPendente` — best-effort revert se save() da missão falhar (AC2.4) | TDD unit (análise estática) | idem | ✅ pass |
| `voltarItemPendente` — não chama `transicionar()` (decisão TL) | TDD unit (análise estática) | idem | ✅ pass |
| `designacao_painel.php` — data-confirm-msg menciona rebote (AC3.1) | TDD unit (análise estática) | idem | ✅ pass |

**Total: 70 assertions, 0 falhas.**

## Gaps de cobertura (e justificativa)

- **Integration test contra `dev_gx_goldie`** — não executado. O fluxo usa `galaxia-action` (não `/api/v1/`), o handler é privado e instanciado via construtor com `$galaxia` injetado pelo framework. Para um integration test real seria necessário montar toda a sessão/tenancy e inserir fixtures de missão/item, o que ultrapassa o escopo do TDD standalone. Os cenários 5a–5d do techplan são documentados para teste manual.
- **Revert do extrato ITEM_REINICIADO após falha de save()** — o techplan aceita explicitamente esse risco residual (extrato orphan) e não exige reversão do extrato. Cobertura de teste seria irrelevante porque a spec define que o extrato é auxiliar e não reverte.
- **Tipos de missão (pesagem, separação, conferência, carregamento)** — a spec define "comportamento consistente para qualquer tipo"; não há ramificação por tipo no código, portanto um único cenário cobre todos.

## Output da execução

```
======================================================
TDD: VoltarItemPendente — reset-item-missao
======================================================

--- BLOCO 1: AcaoExtrato::MISSAO_REABERTA ---
✅ [PASS] AcaoExtrato deve ter case MISSAO_REABERTA = 'MISSAO_REABERTA'
✅ [PASS] AcaoExtrato::descricao() deve retornar texto para MISSAO_REABERTA
✅ [PASS] AcaoExtrato::icon() deve retornar ícone para MISSAO_REABERTA
✅ [PASS] AcaoExtrato::categoria() deve classificar MISSAO_REABERTA como 'missao'
✅ [PASS] AcaoExtrato::MISSAO_REABERTA->value deve ser 'MISSAO_REABERTA'
✅ [PASS] descricao() retorna texto correto
✅ [PASS] icon() retorna ícone correto
✅ [PASS] categoria() retorna 'missao'

--- BLOCO 2: StatusMissao — invariantes de gating ---
✅ [PASS] Status em_andamento deve estar na lista de permitidos
✅ [PASS] Status aguardando_aprovacao deve estar na lista de permitidos
✅ [PASS] Status pausada deve estar na lista de permitidos
✅ [PASS] Status pendente deve estar na lista de permitidos
✅ [PASS] Status rascunho deve estar na lista de permitidos
✅ [PASS] Status concluida NÃO deve estar na lista de permitidos
✅ [PASS] Status cancelada NÃO deve estar na lista de permitidos
✅ [PASS] Status em_andamento NÃO deve disparar rebote da missão
✅ [PASS] Status pausada NÃO deve disparar rebote da missão
✅ [PASS] Status pendente NÃO deve disparar rebote da missão
✅ [PASS] Status rascunho NÃO deve disparar rebote da missão
✅ [PASS] AGUARDANDO_APROVACAO e EM_ANDAMENTO são estados distintos (rebote é uma mudança real)
✅ [PASS] StatusItem::PENDENTE->value é 'pendente'

--- BLOCO 3: Análise estática de MissoesItensEdicao::voltarItemPendente ---
✅ [PASS] Método voltarItemPendente deve existir em MissoesItensEdicao
✅ [PASS] voltarItemPendente deve zerar 'quantidade_bipada' => 0
✅ [PASS] voltarItemPendente deve zerar 'dados_coletados' => null
✅ [PASS] voltarItemPendente NÃO deve alterar 'dados_adicionais'
✅ [PASS] voltarItemPendente deve zerar concluido_em e concluido_por
✅ [PASS] voltarItemPendente deve zerar iniciado_em e iniciado_por
✅ [PASS] voltarItemPendente deve zerar 'tempo_execucao'
✅ [PASS] voltarItemPendente deve zerar 'solicitou_recomeco' => 0
✅ [PASS] voltarItemPendente deve definir status = StatusItem::PENDENTE->value
✅ [PASS] voltarItemPendente deve appendar observação '[Resetado p/ pendente por ...]' preservando o histórico
✅ [PASS] voltarItemPendente deve registrar extrato ITEM_REINICIADO
✅ [PASS] voltarItemPendente deve retornar info quando item já está pendente
✅ [PASS] voltarItemPendente deve verificar statusPermitidos antes de agir
✅ [PASS] voltarItemPendente deve testar StatusMissao::AGUARDANDO_APROVACAO para rebote
✅ [PASS] voltarItemPendente NÃO deve chamar transicionar() — rebote é via update direto
✅ [PASS] voltarItemPendente deve registrar extrato MISSAO_REABERTA no rebote
✅ [PASS] voltarItemPendente deve retornar mensagem mencionando rebote da missão
✅ [PASS] voltarItemPendente deve retornar mensagem simples quando missão não rebotou
✅ [PASS] voltarItemPendente deve tentar reverter o item se update da missão falhar
✅ [PASS] MissoesItensEdicao deve importar MissaoLogistica para o rebote

--- BLOCO 4: Lógica pura de campos zerados (simulação sem banco) ---
✅ [PASS] Campo status zerado para 'pendente'
✅ [PASS] Campo quantidade_bipada zerado para 0
✅ [PASS] Campo dados_coletados zerado para null
✅ [PASS] Campo concluido_em zerado para null
✅ [PASS] Campo concluido_por zerado para null
✅ [PASS] Campo iniciado_em zerado para null
✅ [PASS] Campo iniciado_por zerado para null
✅ [PASS] Campo tempo_execucao zerado para null
✅ [PASS] Campo solicitou_recomeco zerado para 0
✅ [PASS] Observacoes preserva histórico e appenda o registro de reset
✅ [PASS] dados_adicionais NÃO deve estar no array de update (metadado de domínio intocado)

--- BLOCO 5: Regras de gating por status da missão (lógica pura) ---
✅ [PASS] em_andamento + concluido → ok
✅ [PASS] em_andamento NÃO dispara rebote
✅ [PASS] aguardando_aprovacao + concluido → ok
✅ [PASS] aguardando_aprovacao dispara rebote
✅ [PASS] Mensagem de rebote correta
✅ [PASS] item já pendente → noop
✅ [PASS] concluida → bloqueado
✅ [PASS] cancelada → bloqueado
✅ [PASS] pausada + em_andamento → ok
✅ [PASS] pausada NÃO dispara rebote
✅ [PASS] pendente → ok
✅ [PASS] pendente NÃO dispara rebote
✅ [PASS] rascunho → ok
✅ [PASS] rascunho NÃO dispara rebote

--- BLOCO 6: data-confirm-msg no designacao_painel.php ---
✅ [PASS] designacao_painel.php deve existir
✅ [PASS] data-confirm-msg deve mencionar Aguardando Aprovação
✅ [PASS] data-confirm-msg deve mencionar retorno para Em Andamento
✅ [PASS] Botão Reiniciar / voltarItemPendente ainda deve existir no painel

======================================================
RESULTADO: ✅ SUCESSO
Passaram: 70 | Falharam: 0
======================================================
```

## Bugs encontrados

Nenhum. O código de produção implementado pelo dev backend satisfaz todos os critérios de aceite da spec e do techplan verificáveis sem banco.
