Skip to content

Commit 50d5920

Browse files
committed
feat: add intelligent timeout diagnostics system
Add smart diagnostic suggestions for timeout errors to improve DX - Created TimeoutDiagnostics module with contextual error analysis - Detects common timeout patterns: * Dynamic/loading content selectors * Complex and fragile selectors * Dynamic ID selectors * Network-related delays * Animation issues * Excessive DOM mutations - Provides actionable suggestions with docs links - Includes comprehensive test coverage (17 tests) - Fully documented with examples and integration guide Benefits: - Reduces debugging time for developers - Provides inline education about best practices - Decreases frustration with clearer error messages - Reduces support questions about timeouts Example output: ` cy.get() timed out waiting 4000ms Diagnostic Suggestions: 1. The selector appears to target dynamic/loading content a) Wait for the loading state to complete b) Consider using data-cy attributes c) Use cy.intercept() to wait for API requests Learn more: https://on.cypress.io/best-practices ` Related: Timeout errors are one of the most common issues users face
1 parent a388894 commit 50d5920

File tree

3 files changed

+695
-0
lines changed

3 files changed

+695
-0
lines changed
Lines changed: 198 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,198 @@
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

Comments
 (0)