|
| 1 | +# Timeout Diagnostics - Smart Error Messages |
| 2 | + |
| 3 | +## 🎯 Objetivo |
| 4 | + |
| 5 | +Melhorar dramaticamente a experiência do desenvolvedor ao lidar com erros de timeout no Cypress, fornecendo **sugestões contextuais e acionáveis** baseadas na análise do contexto do erro. |
| 6 | + |
| 7 | +## 🚀 Motivação |
| 8 | + |
| 9 | +Erros de timeout são extremamente comuns em testes Cypress, mas as mensagens tradicionais são genéricas: |
| 10 | + |
| 11 | +``` |
| 12 | +cy.get() timed out waiting 4000ms |
| 13 | +``` |
| 14 | + |
| 15 | +Com este sistema, os desenvolvedores recebem diagnósticos inteligentes: |
| 16 | + |
| 17 | +``` |
| 18 | +cy.get() timed out waiting 4000ms |
| 19 | +
|
| 20 | +🔍 Diagnostic Suggestions: |
| 21 | +
|
| 22 | +1. The selector appears to target dynamic/loading content |
| 23 | + a) Wait for the loading state to complete: cy.get('.loading-spinner').should('not.exist') |
| 24 | + b) Consider using data-cy attributes instead of class names that indicate loading states |
| 25 | + c) Use cy.intercept() to wait for the API request that populates this content |
| 26 | + 📚 Learn more: https://on.cypress.io/best-practices#Selecting-Elements |
| 27 | +
|
| 28 | +2. 8 network requests are still pending |
| 29 | + a) Wait for specific API calls to complete using cy.intercept() |
| 30 | + b) Consider increasing the timeout if the requests are expected to be slow |
| 31 | + c) Check if some requests are failing or hanging in the Network tab |
| 32 | + d) Example: cy.intercept("GET", "/api/data").as("getData"); cy.wait("@getData") |
| 33 | + 📚 Learn more: https://on.cypress.io/intercept |
| 34 | +``` |
| 35 | + |
| 36 | +## ✨ Funcionalidades |
| 37 | + |
| 38 | +### 1. **Detecção de Seletores Problemáticos** |
| 39 | +- Identifica seletores que apontam para conteúdo dinâmico (loading, spinner, skeleton) |
| 40 | +- Detecta seletores complexos e frágeis |
| 41 | +- Alerta sobre IDs dinâmicos (ex: `#user-12345`) |
| 42 | + |
| 43 | +### 2. **Análise de Problemas de Rede** |
| 44 | +- Detecta múltiplas requisições pendentes |
| 45 | +- Identifica timeouts longos que sugerem operações assíncronas |
| 46 | +- Sugere uso de `cy.intercept()` para melhor controle |
| 47 | + |
| 48 | +### 3. **Diagnóstico de Animações** |
| 49 | +- Identifica quando animações estão causando delays |
| 50 | +- Sugere configurações para desabilitar animações em testes |
| 51 | + |
| 52 | +### 4. **Detecção de Mutações Excessivas do DOM** |
| 53 | +- Identifica quando o DOM está mudando rapidamente |
| 54 | +- Sugere esperar por estabilização antes de interagir |
| 55 | + |
| 56 | +### 5. **Sugestões Específicas por Comando** |
| 57 | +- Sugestões customizadas para cada tipo de comando (`get`, `click`, `type`, etc.) |
| 58 | +- Links para documentação relevante |
| 59 | + |
| 60 | +## 📦 Estrutura |
| 61 | + |
| 62 | +``` |
| 63 | +packages/driver/src/cypress/ |
| 64 | +└── timeout_diagnostics.ts # Lógica principal |
| 65 | +
|
| 66 | +packages/driver/test/unit/cypress/ |
| 67 | +└── timeout_diagnostics.spec.ts # Testes unitários |
| 68 | +``` |
| 69 | + |
| 70 | +## 🔧 API |
| 71 | + |
| 72 | +```typescript |
| 73 | +import { TimeoutDiagnostics } from './timeout_diagnostics' |
| 74 | + |
| 75 | +// Analisar contexto e obter sugestões |
| 76 | +const suggestions = TimeoutDiagnostics.analyze({ |
| 77 | + command: 'get', |
| 78 | + selector: '.loading-spinner', |
| 79 | + timeout: 4000, |
| 80 | + networkRequests: 5, |
| 81 | + animationsRunning: true, |
| 82 | +}) |
| 83 | + |
| 84 | +// Formatar sugestões para exibição |
| 85 | +const formatted = TimeoutDiagnostics.formatSuggestions(suggestions) |
| 86 | + |
| 87 | +// Enriquecer mensagem de erro existente |
| 88 | +const enhanced = TimeoutDiagnostics.enhanceTimeoutError( |
| 89 | + 'cy.get() timed out', |
| 90 | + context |
| 91 | +) |
| 92 | +``` |
| 93 | + |
| 94 | +## 🎨 Exemplos de Uso |
| 95 | + |
| 96 | +### Exemplo 1: Conteúdo Dinâmico |
| 97 | +```typescript |
| 98 | +// Teste que falha |
| 99 | +cy.get('.loading-spinner').click() |
| 100 | + |
| 101 | +// Erro melhorado sugere: |
| 102 | +// "Wait for the loading state to complete: |
| 103 | +// cy.get('.loading-spinner').should('not.exist')" |
| 104 | +``` |
| 105 | + |
| 106 | +### Exemplo 2: Problemas de Rede |
| 107 | +```typescript |
| 108 | +// Teste aguardando resposta API |
| 109 | +cy.get('.user-data').should('be.visible') |
| 110 | + |
| 111 | +// Erro melhorado sugere: |
| 112 | +// "Use cy.intercept() to wait for the specific request: |
| 113 | +// cy.intercept('GET', '/api/users').as('getUsers') |
| 114 | +// cy.wait('@getUsers')" |
| 115 | +``` |
| 116 | + |
| 117 | +### Exemplo 3: Animações |
| 118 | +```typescript |
| 119 | +// Elemento animando quando clica |
| 120 | +cy.get('.modal-button').click() |
| 121 | + |
| 122 | +// Erro melhorado sugere: |
| 123 | +// "Disable animations: .click({ waitForAnimations: false }) |
| 124 | +// Or globally: Cypress.config('animationDistanceThreshold', 0)" |
| 125 | +``` |
| 126 | + |
| 127 | +## 🔮 Integração Futura |
| 128 | + |
| 129 | +Para integrar completamente no Cypress, seria necessário: |
| 130 | + |
| 131 | +1. **Modificar `error_utils.ts`** para capturar contexto adicional durante timeouts |
| 132 | +2. **Coletar métricas** de rede, DOM e animações durante execução do comando |
| 133 | +3. **Integrar na pipeline de erro** existente do Cypress |
| 134 | +4. **Adicionar configuração** para habilitar/desabilitar diagnósticos |
| 135 | + |
| 136 | +```typescript |
| 137 | +// Exemplo de integração em error_utils.ts |
| 138 | +import TimeoutDiagnostics from './timeout_diagnostics' |
| 139 | + |
| 140 | +const createTimeoutError = (cmd, ms) => { |
| 141 | + const context = { |
| 142 | + command: cmd.get('name'), |
| 143 | + selector: cmd.get('selector'), |
| 144 | + timeout: ms, |
| 145 | + networkRequests: getNetworkMonitor().pendingCount(), |
| 146 | + animationsRunning: hasRunningAnimations(), |
| 147 | + domMutations: getDOMMutationCount(), |
| 148 | + } |
| 149 | + |
| 150 | + const baseMessage = `cy.${cmd.get('name')}() timed out waiting ${ms}ms` |
| 151 | + return TimeoutDiagnostics.enhanceTimeoutError(baseMessage, context) |
| 152 | +} |
| 153 | +``` |
| 154 | + |
| 155 | +## 📊 Benefícios |
| 156 | + |
| 157 | +1. **Reduz tempo de debugging**: Desenvolvedores identificam problemas mais rapidamente |
| 158 | +2. **Educação inline**: Ensina melhores práticas durante o desenvolvimento |
| 159 | +3. **Menos frustração**: Erros mais claros = desenvolvedores mais felizes |
| 160 | +4. **Reduz issues no GitHub**: Menos perguntas sobre "por que meu teste timeout?" |
| 161 | +5. **Melhora adoção**: Desenvolvedores iniciantes aprendem mais rápido |
| 162 | + |
| 163 | +## 🧪 Testes |
| 164 | + |
| 165 | +Execute os testes unitários: |
| 166 | + |
| 167 | +```bash |
| 168 | +cd packages/driver |
| 169 | +yarn test timeout_diagnostics.spec.ts |
| 170 | +``` |
| 171 | + |
| 172 | +Cobertura inclui: |
| 173 | +- ✅ Detecção de todos os tipos de problemas |
| 174 | +- ✅ Formatação de mensagens |
| 175 | +- ✅ Casos extremos e edge cases |
| 176 | +- ✅ Combinação de múltiplos diagnósticos |
| 177 | + |
| 178 | +## 🚀 Próximos Passos |
| 179 | + |
| 180 | +1. ✅ Criar módulo de diagnósticos com testes |
| 181 | +2. ⏳ Integrar com sistema de erros existente |
| 182 | +3. ⏳ Adicionar coleta de métricas de contexto |
| 183 | +4. ⏳ Criar configuração para habilitar/desabilitar |
| 184 | +5. ⏳ Adicionar mais padrões e sugestões baseado em feedback |
| 185 | +6. ⏳ Documentação para usuários finais |
| 186 | + |
| 187 | +## 🤝 Contribuindo |
| 188 | + |
| 189 | +Este é um sistema extensível. Para adicionar novos diagnósticos: |
| 190 | + |
| 191 | +1. Adicione padrão em `COMMON_PATTERNS` |
| 192 | +2. Crie método `analyze*Issues()` |
| 193 | +3. Adicione testes correspondentes |
| 194 | +4. Documente o novo diagnóstico |
| 195 | + |
| 196 | +## 📝 Licença |
| 197 | + |
| 198 | +MIT - Consistente com o projeto Cypress |
0 commit comments