# Executar no CI

> Fonte: https://astrallab.dev/pt/docs/ci

O `astral-test` executa os testes salvos de um projeto sem abrir o Astral e sem incluir nem baixar um navegador. Use-o no CI, ou no loop de um agente para repetir os testes depois de uma correção.

## Instalação

O `astral-test` é um único binário para macOS (Apple Silicon e Intel) e Linux x64, com link nos [downloads para desenvolvedores](https://astrallab.dev/#developer-downloads). Pode faltar uma versão para Windows em uma release porque o Windows [ainda não está verificado](https://astrallab.dev/pt/docs/platforms.md).

```bash
BASE=https://downloads.perseusoft.tech/astral-test/latest
curl -fsSLO "$BASE/astral-test-x86_64-unknown-linux-gnu.tar.gz"
tar xzf astral-test-x86_64-unknown-linux-gnu.tar.gz
./astral-test --version
```

Ele precisa de um navegador já instalado na máquina: Google Chrome, Chromium ou Microsoft Edge (o motor `cdp`; `ASTRAL_CHROME` aponta para um binário específico), qualquer navegador já iniciado com DevTools por meio de `--cdp-url`, ou o Lightpanda no seu `PATH` (o motor `lite`). O `astral-test doctor` informa o que encontrou e o que usaria.

## Comandos

```
astral-test run [PATH=.] [--env NAME] [--test ID]... [--collection ID]
                [--engine lite|cdp] [--cdp-url ws://...|http://...]
                [--reporter pretty|json|junit]... [--out DIR=astral-test-results]
                [--timeout-ms N=120000] [--bail] [--record off|steps|actions|video]
astral-test list [PATH=.] [--json]
astral-test doctor [PATH=.] [--engine lite|cdp] [--cdp-url ...] [--probe] [--json]
```

- Sem `--test` nem `--collection`, todos os testes salvos rodam, ordenados por id.
- `--env` aceita um ambiente do `config.json` ou uma URL http(s).
- `--bail` relata o restante como ignorado depois da primeira falha.
- Cada teste roda em um contexto de navegador novo: nenhum cookie nem armazenamento é herdado.

### Códigos de saída

| Código | Significado |
| --- | --- |
| 0   | Todos os testes selecionados passaram (os ignorados não contam como falha). |
| 1   | Pelo menos um teste falhou: o app não fez o que o teste espera. |
| 2   | Uso ou configuração: argumentos, projeto ou `config.json` inválidos, teste ou ambiente desconhecido, uma credencial que não pode ser resolvida. |
| 3   | Motor: nenhum navegador encontrado, ou ele não iniciou, não respondeu ou não permaneceu ativo. |

Com vários problemas, vence o mais grave: 3, depois 2, depois 1.

## Motores

|     | `lite` (Lightpanda) | `cdp` (Chrome, Chromium, Edge) |
| --- | --- | --- |
| Fidelidade | DOM e JavaScript, sem renderização nem layout CSS. | Completa. |
| Evidências | Árvores de página em vez de capturas de tela; sem vídeo. | Capturas de tela e uma gravação em PNG animado. |
| Verificações de layout | Relatadas como ignoradas, nunca como aprovadas. | Sim, com emulação de viewport. |
| Uso | Fluxos rápidos sem dependência visual. | Testes que dependem de layout e de capturas de tela. |

Por padrão, usa-se `lite` se o Lightpanda estiver instalado; caso contrário, `cdp`.

## Credenciais no CI

`{ "env": "ASTRAL_TEST_..." }` lê uma variável de ambiente do processo, que no CI é um segredo. `{ "local": "..." }` lê `.astral/secrets.local.json`. Uma referência `keychain` não está disponível fora do app: o teste falha com uma mensagem informando qual variável definir. Os valores secretos nunca aparecem na saída.

No CI, o repositório é a fonte da verdade: em um ambiente protegido, o `astral-test` confia na declaração `readOnly` do arquivo do teste, então uma mudança em `.astral/` precisa de revisão de código.

## Saída

### JUnit e artefatos

Com `--reporter junit` e `--out DIR` você obtém:

- `junit.xml`, um caso de teste por teste (e por viewport, com um sufixo como `[mobile]`).
- `<testId>/report.html` e `report.json`, o mesmo relatório que o app escreve.
- Capturas de tela (ou árvores de página no `lite`) e a árvore de página completa no ponto de uma falha.

### NDJSON para agentes

`--reporter json` imprime um objeto JSON por linha no stdout, descarregado conforme avança. Toda linha tem `type`, `schemaVersion` (atualmente 1) e `ts`.

```
run_start
  test_start                (per test)
    step_start / step_end   (per step, live)
  test_end                  (status, steps, failure, artifacts)
run_end                     (always the last line)
```

O `failure` de um teste que falhou diz qual passo falhou e por quê: seu tipo (assertion, action, script, timeout, config, engine ou stopped), a expectativa, o que era esperado e o que foi encontrado, o elemento alvo, a URL, um breve trecho da árvore de página ao redor do elemento, erros do console e requisições com falha, tudo com os segredos mascarados. `failed` é um veredito sobre o seu app; `error` significa que o teste não pôde rodar como configurado.

## GitHub Actions

```yaml
name: e2e
on: [push, pull_request]
jobs:
  astral-test:
    runs-on: ubuntu-latest          # Google Chrome is preinstalled
    steps:
      - uses: actions/checkout@v4
      - name: Install astral-test
        run: |
          curl -fsSL https://downloads.perseusoft.tech/astral-test/latest/astral-test-x86_64-unknown-linux-gnu.tar.gz \
            | sudo tar xz -C /usr/local/bin astral-test
      - name: Start the app under test
        run: npm ci && npm start &
      - name: Run saved tests
        run: astral-test run . --collection smoke --engine cdp --reporter pretty --reporter junit --out astral-test-results
        env:
          ASTRAL_TEST_SHOP_DEMO_PASSWORD: ${{ secrets.SHOP_DEMO_PASSWORD }}
      - if: always()
        uses: actions/upload-artifact@v4
        with: { name: astral-test-results, path: astral-test-results }
```

No GitLab, publique `astral-test-results/junit.xml` em `artifacts: reports: junit`.
