# Accessibility Testing: Garantindo Inclusão e Conformidade WCAG

**Meta Description:** Aprenda a testar acessibilidade: WCAG 2.1, ARIA, screen readers, testes automatizados e manuais para garantir que seu site é acessível a todos.

---

## O Que é Acessibilidade?

Acessibilidade web garante que pessoas com deficiências podem usar websites. No Brasil, a **Lei Brasileira de Inclusão (Lei 13.146/2015)** exige acessibilidade em sites públicos e de empresas.

### Por Que Importa?

- **Inclusão**: 15% da população tem algum tipo de deficiência
- **Legal**: Conformidade com LGPD e leis
- **SEO**: Sites acessíveis rankeiam melhor
- **UX**: Boas práticas beneficiam todos

---

## WCAG 2.1 - 4 Princípios

### 1. Perceivable (Perceptível)

```html
<!-- Imagens com alt text -->
<img src="logo.png" alt="Empresa X - Página inicial">

<!-- Vídeos com legendas -->
<video>
  <track kind="subtitles" src="legendas.vtt" srclang="pt" label="Português">
</video>

<!-- Contrast adequado -->
<style>
  .text {
    color: #1a1a1a;        /* Pior: #767676 = 4.5:1 em fundo branco */
    background: #ffffff;   /* Melhor: #1a1a1a = 21:1 em fundo branco */
  }
</style>
```

### 2. Operable (Operável)

```html
<!-- Navegação por teclado -->
<nav>
  <a href="#main" class="skip-link">Pular para conteúdo principal</a>
  <a href="#menu">Menu</a>
  <a href="#search">Busca</a>
</nav>

<style>
.skip-link {
  position: absolute;
  top: -40px;
  left: 0;
  background: #000;
  color: #fff;
  padding: 8px;
  z-index: 100;
}
.skip-link:focus {
  top: 0;
}
</style>

<!-- Focus visível -->
:focus {
  outline: 3px solid #005fcc;
  outline-offset: 2px;
}
```

### 3. Understandable (Compreensível)

```html
<!-- Labels em inputs -->
<label for="email">Email</label>
<input type="email" id="email" aria-describedby="email-hint">
<span id="email-hint">Formato: usuario@dominio.com</span>

<!-- Erros claros -->
<div class="error" role="alert">
  <span id="password-error">Senha deve ter:</span>
  <ul aria-labelledby="password-error">
    <li id="error-length">Mínimo 8 caracteres</li>
    <li id="error-number">Pelo menos 1 número</li>
  </ul>
</div>
```

### 4. Robust (Robusto)

```html
<!-- HTML semântico -->
<header role="banner">
  <nav role="navigation" aria-label="Menu principal">
  <main role="main">
  <article role="article">
  <aside role="complementary">
  <footer role="contentinfo">
```

---

## ARIA - Accessible Rich Internet Applications

### Roles

```html
<!-- Landmarks -->
<header role="banner">
<nav role="navigation">
<main role="main">
<aside role="complementary">
<footer role="contentinfo">

<!-- Widgets -->
<button role="button" aria-expanded="false">
<div role="menu" aria-label="Menu">
<div role="menuitem">
<div role="tablist">
<div role="tab">
<div role="tabpanel">
<div role="dialog" aria-modal="true" aria-labelledby="dialog-title">
```

### Estados e Propriedades

```html
<!-- Expanded/Collapsed -->
<button aria-expanded="false" aria-controls="menu-content">
<div id="menu-content" hidden>

<!-- Selected -->
<option aria-selected="true">
<tab aria-selected="true">

<!-- Disabled -->
<button aria-disabled="true">

<!-- Live Regions -->
<div aria-live="polite">Notificação</div>
<div aria-live="assertive">Erro</div>
<div aria-atomic="true">
```

---

## Testes Automatizados

### axe-core

```javascript
// Playwright + axe
const { test, expect } = require('@playwright/test');
const AxeBuilder = require('@axe-core/playwright').default;

test('accessibility on login page', async ({ page }) => {
  await page.goto('/login');
  
  const accessibilityScanResults = await new AxeBuilder({ page })
    .withTags(['wcag2a', 'wcag2aa', 'wcag21a', 'wcag21aa'])
    .analyze();
  
  // Log violations
  if (accessibilityScanResults.violations.length > 0) {
    console.log('Violations found:');
    accessibilityScanResults.violations.forEach(v => {
      console.log(`  - ${v.id}: ${v.description}`);
    });
  }
  
  // Fail if critical violations
  const critical = accessibilityScanResults.violations.filter(
    v => v.impact === 'critical'
  );
  expect(critical.length, `${critical.length} critical violations`).toBe(0);
});
```

```python
# pytest + axe
import pytest
from playwright.sync_api import Page

def test_accessibility(page: Page):
    page.goto('/login')
    
    results = page.run_axe()
    
    critical_violations = [
        v for v in results['violations']
        if v['impact'] in ['critical', 'serious']
    ]
    
    assert len(critical_violations) == 0, (
        f"Found {len(critical_violations)} critical accessibility violations"
    )
```

### Lighthouse CI

```yaml
# .github/workflows/a11y.yml
name: Accessibility Tests

on: [push, pull_request]

jobs:
  accessibility:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      
      - name: Run Lighthouse CI
        uses: treosh/lighthouse-ci-action@v10
        with:
          urls: |
            https://example.com/
            https://example.com/login
          budgetPath: ./lighthouse-budget.json
          uploadArtifacts: true
          temporaryPublicStorage: true

# lighthouse-budget.json
{
  "ci": {
    "collect": {
      "startServerCommand": "npm run start",
      "url": [
        "http://localhost:8080/"
      ]
    },
    "assert": {
      "assertions": {
        "categories:accessibility": ["error", {"minScore": 0.9}]
      }
    }
  }
}
```

---

## Testes Manuais

### Checklist de Testes Manuais

```markdown
# Accessibility Testing Checklist

## Navegação por Teclado
- [ ] Tab percorre todos os elementos interativos
- [ ] ordem de foco faz sentido
- [ ] Focus é sempre visível
- [ ] Links úteis no topo (skip link)
- [ ] ESC fecha modais
- [ ] Enter ativa botões e links

## Imagens
- [ ] Todas imagens têm alt text
- [ ] Alt text descreve conteúdo/função
- [ ] Imagens decorativas têm alt=""
- [ ] Textos em imagens evitados

## Contrastes
- [ ] Texto normal: 4.5:1 mínimo
- [ ] Texto grande (18pt+): 3:1 mínimo
- [ ] Gráficos: 3:1

## Formulários
- [ ] Labels associados a inputs
- [ ] Erros descritos claramente
- [ ] Campos obrigatórios marcados
- [ ] Autocomplete quando aplicável

## Semântica
- [ ] Cabeçalhos em ordem (h1 > h2 > h3)
- [ ] Listas usam <ul>/<ol>
- [ ] Tabelas têm headers
- [ ] Landmarks definidos

## ARIA
- [ ] ARIA usado quando HTML não é suficiente
- [ ] ARIA não sobrepõe semântica nativa
- [ ] Live regions atualizam corretamente
```

### Screen Reader Testing

```markdown
# Screen Reader Testing

## VoiceOver (macOS)
- Cmd + F5: Ativar VoiceOver
- Tab/Cmd + Option + Setas: Navegar
- Cmd + Option + U: Rotor

## NVDA (Windows)
- Insert + D: Ler documento
- Tab: Próximo elemento
- Insert + Espaço: Modo foco

## Verificar:
- [ ] Ordem de leitura faz sentido
- [ ] Imagens descritas
- [ ] Links têm contexto
- [ ] Formulários etiquetados
- [ ] Tabelas fazem sentido
- [ ] Headings navegáveis
```

---

## Ferramentas

| Ferramenta | Tipo | Custo |
|------------|------|-------|
| **axe DevTools** | Browser Extension | Grátis |
| **WAVE** | Browser Extension | Grátis |
| **Lighthouse** | DevTools/CLI | Grátis |
| **AXE-core** | Library | Grátis |
| **SiteImprove** | SaaS | Pago |
| **Deque aXe** | Enterprise | Pago |
| **Tenon.io** | API | Pago |

---

## Conclusão

Acessibilidade é fundamental para inclusão. As chaves são:

1. **Semântica primeiro** - Use HTML correto
2. **Teste automatizado** - Capture issues rapidamente
3. **Teste manual** - Screen readers e teclado
4. **WCAG compliance** - Atingir nível AA mínimo
5. **Continuous testing** - Integre ao CI/CD
