# Aula 4.10 - Testes, compilação e projeto final

## Identificação

- **Duração:** 2 horas
- **Tipo:** oficina integradora
- **Entrega:** painel Angular testado, compilado, documentado e apresentável
- **Laboratório:** [`../exemplos/aula-4.10/index.html`](../exemplos/aula-4.10/index.html)

## Introdução

### O que é um teste automatizado?

Teste automatizado é código que executa uma situação, observa o resultado e compara
esse resultado com uma expectativa.

```text
preparar cenário → executar comportamento → verificar resultado
```

Se a expectativa não for atendida, o teste falha e informa onde o comportamento
divergiu. Ele pode ser repetido por uma pessoa, pelo editor ou por um servidor de
integração contínua.

### Teste prova que não existem bugs?

Não. Um teste comprova somente o comportamento e os cenários que ele verificou. Uma
suíte ajuda a detectar regressões e aumenta a confiança, mas não substitui análise,
acessibilidade, segurança, validação real nem observação em produção.

### Testar é o mesmo que depurar?

Não. Testar detecta que o resultado não corresponde ao esperado. Depurar é investigar
por que isso aconteceu. Um teste pequeno e com nome claro facilita essa investigação.

### O que é uma suíte de testes?

É um conjunto organizado de casos relacionados. Podemos agrupar testes por serviço,
componente ou comportamento.

```ts
describe("TaskStore", () => {
  it("counts only open tasks", () => { /* ... */ });
  it("keeps a valid selection after removal", () => { /* ... */ });
});
```

### O que é Vitest?

Vitest é o executor de testes usado por padrão nos projetos Angular CLI atuais. Ele
oferece funções como `describe`, `it`, `expect` e `vi.fn`. O Angular continua
fornecendo `TestBed`, fixtures e utilitários para criar o ambiente da aplicação.

Projetos antigos podem usar Karma e Jasmine. Não reescreva testes apenas pelo nome da
ferramenta; planeje uma migração consciente.

### O que é compilação?

Compilação é o processo de transformar o código-fonte da aplicação em arquivos que um
navegador ou servidor poderá entregar.

```text
TypeScript + templates + CSS + assets
                ↓ ng build
      HTML + JavaScript + CSS otimizados
```

A compilação verifica compilação e produz artefatos. Ele não publica automaticamente, não
cria banco MySQL e não garante que a API esteja disponível.

### Compilação é igual a publicação?

Não. `ng build` cria a pasta de saída. Publicar significa enviar essa saída a um
servidor, CDN ou plataforma e configurar domínio, HTTPS, cache e fallback de rotas.

### Se compilou, funciona?

Não necessariamente. Uma aplicação pode compilar e ainda possuir link quebrado,
contraste ruim, API incorreta, erro de autorização ou rota que falha ao atualizar a
página. Testes e auditoria complementam a compilação.

### Desenvolvimento e produção são iguais?

Não. `ng serve` prioriza desenvolvimento, mensagens detalhadas e recarga rápida. A
configuração de produção aplica otimização, AOT, minificação, eliminação de código
inutilizado e outras transformações.

### O que será entregue nesta aula?

Concluiremos o painel Angular da Knowledge AI com evidências reproduzíveis:

```text
código → testes → compilação → auditoria → documentação → apresentação
```

## Objetivos

Ao final da aula, o aluno deverá conseguir:

1. explicar teste automatizado, suíte, caso e expectativa;
2. distinguir testes unitários, de componente, integração e ponta a ponta;
3. aplicar Arrange, Act e Assert;
4. testar funções puras e stores com signals;
5. criar componentes com `TestBed` e `ComponentFixture`;
6. verificar conteúdo e interação no DOM;
7. substituir dependências de modo controlado;
8. testar HTTP sem rede real;
9. verificar interceptors isoladamente;
10. interpretar cobertura sem transformá-la em objetivo vazio;
11. executar `ng test` localmente e em CI;
12. explicar e produzir uma compilação de produção;
13. auditar budgets, source maps, segredos e rotas SPA;
14. documentar, demonstrar e defender o projeto do módulo.

## Pré-requisitos

- Aulas 4.1 a 4.9 concluídas;
- componentes, templates, serviços, Router, formulários, HTTP e signals;
- noções de funções e testes do Módulo 3;
- terminal e scripts npm;
- HTML semântico e acessibilidade.

## Pergunta orientadora

> Que evidências demonstram que o painel está pronto para ser entregue e mantido?

## Roteiro sugerido

| Etapa | Duração |
|---|---:|
| Estratégia e anatomia dos testes | 20 min |
| Serviços, stores e componentes | 30 min |
| HTTP, interceptors e acessibilidade | 25 min |
| Compilação, segurança e hospedagem | 25 min |
| Auditoria e apresentação | 15 min |
| Encerramento | 5 min |

## 1. Pirâmide de testes

```text
              poucos testes E2E
          testes de integração/componente
        muitos testes unitários rápidos
```

Testes unitários isolam regras pequenas. Testes de componente combinam classe e
template. Integrações verificam fronteiras controladas. E2E percorre o sistema como
usuário. A proporção depende do risco, não de uma fórmula rígida.

## 2. O que testar primeiro

Priorize:

- regras de negócio;
- fluxos críticos;
- validação e autorização visual;
- transformação de dados externos;
- estados de erro e vazio;
- regressões já encontradas;
- acessibilidade essencial de interações.

Não comece testando getters triviais enquanto um envio crítico não possui cobertura.

## 3. Arrange, Act, Assert

```ts
it("marks a task as done", () => {
  // Arrange
  const store = createStoreWith([{ id: 1, done: false }]);

  // Act
  store.toggle(1);

  // Assert
  expect(store.tasks()[0].done).toBe(true);
});
```

Separar as fases deixa intenção e falha mais claras.

## 4. Um teste deve contar uma história

Prefira:

```text
should keep the selected task when it still exists
```

Evite:

```text
test 1
works
```

O nome deve indicar condição, ação e resultado relevante.

## 5. Teste funções puras sem Angular

```ts
describe("filterTasks", () => {
  it("returns only unfinished tasks for the open filter", () => {
    const result = filterTasks(TASKS, "open");
    expect(result.every((task) => !task.done)).toBe(true);
  });
});
```

Se uma regra não depende de DI, template ou framework, um teste direto é menor e mais
rápido.

## 6. Testando um serviço com `TestBed`

```ts
describe("TaskStore", () => {
  beforeEach(() => {
    TestBed.configureTestingModule({ providers: [TaskStore] });
  });

  it("derives the open count", () => {
    const store = TestBed.inject(TaskStore);
    expect(store.openCount()).toBe(2);
  });
});
```

`TestBed` cria um ambiente isolado de injeção. Reinicialize o estado entre casos para
que a ordem de execução não altere resultados.

## 7. Testando signals

Leia a API pública e execute comandos reais:

```ts
const before = store.openCount();
store.toggle(1);
expect(store.openCount()).toBe(before - 1);
```

Evite testar detalhes internos do grafo. O contrato relevante é o valor observado.

## 8. Mock, stub, fake e spy

| Dublê | Finalidade |
|---|---|
| stub | devolve respostas controladas |
| fake | implementação simplificada funcional |
| spy | registra chamadas e argumentos |
| mock | termo amplo; muitas ferramentas combinam stub e spy |

Use o menor dublê necessário. Dublês demais fazem o teste conhecer a implementação em
vez do comportamento.

## 9. Substituindo uma dependência

```ts
const apiStub = {
  list: vi.fn().mockReturnValue(of(TASKS)),
};

TestBed.configureTestingModule({
  providers: [
    TaskStore,
    { provide: TaskApi, useValue: apiStub },
  ],
});
```

O teste controla a fronteira sem chamar servidor real.

## 10. O que é `ComponentFixture`?

Fixture conecta instância, template renderizado e ciclo de detecção de mudanças.

```ts
const fixture = TestBed.createComponent(TaskCard);
fixture.componentRef.setInput("task", TASK);
await fixture.whenStable();
```

Use `fixture.nativeElement` para observar o DOM que o usuário receberia.

## 11. Teste de componente standalone

```ts
beforeEach(async () => {
  await TestBed.configureTestingModule({
    imports: [TaskCard],
  }).compileComponents();
});
```

Componentes standalone entram em `imports`, não em `declarations`.

## 12. Verificando o DOM

```ts
it("renders the task title", async () => {
  const fixture = TestBed.createComponent(TaskCard);
  fixture.componentRef.setInput("task", TASK);
  await fixture.whenStable();

  const title = fixture.nativeElement.querySelector("h3");
  expect(title.textContent).toContain(TASK.title);
});
```

Teste resultado visível. Evite acoplar a seletores decorativos que mudam com o CSS.

## 13. Interação do usuário

```ts
it("emits the task id when the button is clicked", async () => {
  const fixture = TestBed.createComponent(TaskCard);
  fixture.componentRef.setInput("task", TASK);
  const emitted = vi.fn();
  fixture.componentInstance.completed.subscribe(emitted);
  await fixture.whenStable();

  fixture.nativeElement.querySelector("button").click();

  expect(emitted).toHaveBeenCalledWith(TASK.id);
});
```

O teste percorre template, evento DOM e output.

## 14. Não teste apenas “deve criar”

```ts
expect(fixture.componentInstance).toBeTruthy();
```

Esse smoke test encontra falhas básicas de criação, mas não comprova comportamento.
Adicione casos que representem decisões reais.

## 15. Estado assíncrono

Teste loading, success, empty e error separadamente. Controle o tempo com ferramentas
do runner ou Observables determinísticos; não dependa de `setTimeout` real e rede.

## 16. Testando HTTP sem rede

```ts
TestBed.configureTestingModule({
  providers: [
    TaskApi,
    provideHttpClientTesting(),
  ],
});

const api = TestBed.inject(TaskApi);
const http = TestBed.inject(HttpTestingController);
const result = firstValueFrom(api.list());

const request = http.expectOne("/api/tasks");
expect(request.request.method).toBe("GET");
request.flush(TASKS);

expect(await result).toEqual(TASKS);
```

O backend de teste captura a requisição e devolve uma resposta controlada.

## 17. Verifique requisições pendentes

```ts
afterEach(() => {
  TestBed.inject(HttpTestingController).verify();
});
```

Isso detecta chamadas inesperadas ou esquecidas.

## 18. Testando interceptors

Quando o teste configurar recursos do cliente, registre primeiro `provideHttpClient`
e depois `provideHttpClientTesting`:

```ts
providers: [
  provideHttpClient(withInterceptors([correlationInterceptor])),
  provideHttpClientTesting(),
]
```

Teste um interceptor por vez quando possível.

## 19. Erro HTTP controlado

```ts
request.flush(
  { code: "INTERNAL_ERROR" },
  { status: 500, statusText: "Internal Server Error" },
);

await expect(result).rejects.toMatchObject({ status: 500 });
```

Nenhum servidor real precisa falhar para testar a interface de erro.

## 20. Testando acessibilidade essencial

Automatize verificações simples e mantenha revisão humana:

- botão nativo com nome acessível;
- label associado ao campo;
- erro ligado por `aria-describedby`;
- `role="status"` ou `role="alert"` correto;
- foco no resumo quando planejado;
- navegação completa por teclado;
- contraste e zoom em auditoria visual.

Automação não consegue avaliar toda a experiência de tecnologia assistiva.

## 21. Testes frágeis

Sinais comuns:

- dependem da ordem;
- usam tempos reais arbitrários;
- verificam métodos privados;
- quebram ao renomear uma classe CSS;
- reproduzem a implementação dentro da expectativa;
- compartilham estado mutável;
- usam rede ou data atual sem controle.

## 22. Executando os testes

```bash
ng test
```

No desenvolvimento, o modo observação repete os testes após alterações. Para uma
execução única explícita:

```bash
ng test --no-watch --no-progress
```

Em CI, o ambiente normalmente ativa o comportamento não interativo.

## 23. Cobertura de código

```bash
ng test --coverage
```

Cobertura informa quais linhas, funções e ramos foram executados. Cem por cento não
garante boas expectativas; baixa cobertura em fluxo crítico revela risco, mas a meta
deve apoiar qualidade, não gerar testes vazios.

## 24. O que é CI?

Integração contínua é um processo automatizado que valida mudanças em cada push ou
pull request.

```text
instalar → formatar/verificar → testar → compilar → publicar artefato
```

O fluxo deve falhar quando uma etapa obrigatória falhar.

## 25. Compilação de produção

```bash
ng build
```

Por padrão, o CLI atual utiliza a configuração de produção, salvo customização do
espaço de trabalho. Verifique o resultado no diretório configurado em `outputPath`.

## 26. O que a produção otimiza?

- compilação AOT de templates;
- bundling;
- minificação;
- tree shaking e eliminação de código morto;
- CSS e assets;
- remoção de recursos de desenvolvimento;
- hashing e cache conforme configuração.

O artefato deve ser testado no modo em que será hospedado.

## 27. Budget de bundle

Budgets geram aviso ou erro quando o tamanho ultrapassa limites:

```json
{
  "type": "initial",
  "maximumWarning": "500kB",
  "maximumError": "1MB"
}
```

Escolha limites baseados no produto e acompanhe regressões. Não aumente o teto sem
investigar o crescimento.

## 28. Source maps

Source maps ajudam a relacionar código otimizado ao fonte. Maps ocultos ainda podem
vazar se o servidor os publicar. Defina uma política de geração, armazenamento e
acesso para observabilidade.

## 29. Variáveis de ambiente não são cofres

Qualquer valor incorporado ao bundle do front-end pode ser encontrado no navegador.
URL pública e feature flag podem estar na configuração; senha MySQL, chave privada e
segredo de API não podem.

```text
Angular → apenas configuração pública
NestJS  → segredos do servidor
MySQL   → credenciais acessadas pelo back-end
```

## 30. Rotas na hospedagem

Uma SPA com Router precisa que o servidor devolva `index.html` para deep links:

```text
/tasks/42 → servidor entrega index.html → Angular resolve /tasks/42
```

Sem fallback, atualizar uma rota válida pode produzir 404 do servidor.

## 31. `base href`

Se a aplicação for publicada em subdiretório, confirme o caminho base e os assets.
Uma configuração incorreta pode carregar o HTML e falhar em scripts, estilos e rotas.

## 32. Cache e hashing

Arquivos com hash permitem cache longo porque um conteúdo novo recebe outro nome. O
HTML principal costuma exigir política mais curta para apontar aos bundles atuais.

## 33. Lista de verificação de segurança do bundle

- [ ] nenhum token real;
- [ ] nenhuma senha ou conexão MySQL;
- [ ] nenhum `.env` secreto copiado;
- [ ] nenhum source map público por acidente;
- [ ] nenhuma mensagem com stack trace ao usuário;
- [ ] URLs de API corretas;
- [ ] dependências e licenças revisadas;
- [ ] CSP e headers decididos na hospedagem.

## 34. README reproduzível

O README final deve explicar:

1. objetivo e público;
2. funcionalidades;
3. stack e arquitetura;
4. requisitos;
5. instalação;
6. execução local;
7. testes;
8. compilação;
9. configuração pública;
10. decisões e limitações;
11. acessibilidade;
12. demonstração e licença.

## 35. Projeto final do módulo

O painel da Knowledge AI deve conter:

- shell e navegação por rotas;
- dashboard;
- lista, filtro e detalhes de tarefas;
- cadastro e edição validados;
- componentes reutilizáveis;
- serviço/store com signals;
- integração HTTP tipada;
- loading, empty, success e error;
- interceptors e mensagens acessíveis;
- testes essenciais;
- compilação de produção;
- documentação reproduzível.

## 36. Arquitetura final

```text
Angular
├── páginas e layouts
├── componentes de apresentação
├── formulários e estado visual
├── stores e serviços
├── Router
├── HttpClient + interceptors
└── testes
        │ HTTP
        ▼
NestJS → Prisma → MySQL
```

O módulo entrega o front-end e contratos simulados. O back-end real será construído
nos próximos módulos.

## 37. Roteiro de apresentação

Em cinco minutos:

1. problema e usuário;
2. fluxo principal;
3. arquitetura e decisões;
4. demonstração de sucesso;
5. demonstração de erro e acessibilidade;
6. testes e compilação;
7. limitações e próximo passo.

Não percorra arquivos sem contexto; conte a história do produto e mostre evidências.

## 38. Laboratório guiado

Abra a [auditoria final do painel](../exemplos/aula-4.10/index.html).

### Etapa 1 — Selecione o perfil da entrega

Compare uma entrega incompleta com o painel preparado.

### Etapa 2 — Execute a suíte simulada

Observe testes de regra, store, componente, HTTP, interceptor e acessibilidade.

### Etapa 3 — Execute a compilação simulado

Acompanhe typecheck, AOT, otimização, budget e geração do artefato.

### Etapa 4 — Audite documentação e segurança

Marque critérios e veja como eles alteram a prontidão.

### Etapa 5 — Corrija falhas

Use “Preparar entrega completa” e compare o novo resultado.

### Etapa 6 — Gere o parecer

Leia bloqueios, evidências e recomendação de apresentação.

## 39. Sobre o laboratório estático

O laboratório ensina o fluxo de qualidade sem depender de um espaço de trabalho Angular
instalado dentro do curso. Os testes e a compilação são simulações determinísticas; a
pasta `src/app` contém exemplos Angular/Vitest equivalentes.

## 40. Erros comuns

### Testar só caminho feliz

Falhas de rede, validação, vazio e permissão ficam sem evidência.

### Confundir cobertura com qualidade

Linhas executadas podem não possuir expectativas úteis.

### Mockar tudo

O teste deixa de verificar integrações importantes.

### Usar produção real no teste

Resultados ficam lentos, perigosos e instáveis.

### Publicar `ng serve`

Servidor de desenvolvimento não é a entrega otimizada de produção.

### Colocar segredo em environment

O valor entra no bundle e fica público.

### Esquecer fallback SPA

Rotas funcionam por clique, mas falham ao atualizar.

### Não registrar comandos

Outra pessoa não consegue reproduzir teste e compilação.

## 41. Desafio individual

Produza um pacote de evidências com:

- pelo menos oito testes relevantes;
- teste de sucesso e erro HTTP;
- teste isolado de interceptor;
- teste de interação e semântica acessível;
- relatório de cobertura interpretado;
- compilação dentro do budget;
- auditoria de segredos;
- teste de deep link;
- README reproduzível;
- vídeo ou apresentação de cinco minutos.

## 42. Lista de verificação de conclusão

- [ ] Distingo teste, compilação e publicação.
- [ ] Escrevo testes com Arrange, Act e Assert.
- [ ] Testo comportamento, não detalhes privados.
- [ ] Sei usar `TestBed` e fixture.
- [ ] Testo HTTP sem rede real.
- [ ] Verifico estados de erro e acessibilidade.
- [ ] Entendo cobertura e seus limites.
- [ ] Gero uma compilação para produção.
- [ ] Audito segredos, budget e source maps.
- [ ] Documento e apresento o projeto.

## 43. Rubrica do projeto

| Critério | Pontos |
|---|---:|
| Componentes, templates e composição | 15 |
| Rotas e formulários | 15 |
| Serviços, signals e estado | 15 |
| HTTP, interceptors e erros | 15 |
| Acessibilidade | 10 |
| Testes automatizados | 15 |
| Compilação, segurança e desempenho | 10 |
| Documentação e apresentação | 5 |
| **Total** | **100** |

Para concluir, obtenha pelo menos 70 pontos e não possua bloqueio crítico de segurança,
compilação ou acessibilidade.

## 44. Resumo

- testes automatizados produzem evidências repetíveis;
- Vitest é o runner padrão dos projetos Angular CLI atuais;
- `TestBed` cria ambientes isolados para DI e componentes;
- o backend HTTP de teste evita rede real;
- cobertura mede execução, não qualidade da expectativa;
- compilação transforma fonte em artefato otimizado;
- publicação exige servidor, rotas, cache e segurança;
- o projeto final precisa ser reproduzível e defendido tecnicamente.

## 45. Fontes oficiais

- [Angular: visão geral de testes](https://angular.dev/guide/testing)
- [Angular: testes de componentes](https://angular.dev/guide/testing/components-basics)
- [Angular: testes de serviços](https://angular.dev/guide/testing/services)
- [Angular: testes HTTP](https://angular.dev/guide/http/testing)
- [Angular CLI: `ng build`](https://angular.dev/cli/build)
- [Angular: implantação e fallback de rotas](https://angular.dev/tools/cli/deployment)
- [Angular: configuração do espaço de trabalho](https://angular.dev/reference/configs/workspace-config)

## Próximo módulo

No Módulo 5, criaremos o back-end com Node.js e NestJS: ambiente de execução, módulos, controllers,
providers, DTOs, validação e os primeiros endpoints reais da Knowledge AI.
