docs: issues técnicas para nuevas funcionalidades
Agrega 19 issues técnicas documentando funcionalidades implementadas y pendientes. Issues completadas (movidas a dev/issues/completed/): - 001-conversor-web-markdown.md - 002-accessibility-tree.md - 003-gestion-cookies-perfil.md - 004-gestion-extensiones-chrome.md - 005-eliminar-timeouts-innecesarios.md Issues implementadas: - 006-manejo-tabs-ventanas.md - 016-manejo-iframes.md - 017-actions-api.md - 018-file-uploads.md - 019-expected-conditions-mejoradas.md Issues pendientes (media prioridad): - 007-alert-prompt-confirm-handling.md - 008-screenshot-elementos-especificos.md - 009-pdf-generation.md - 010-device-emulation-completo.md - 011-downloads-handling.md Issues pendientes (baja prioridad / avanzado): - 012-browser-contexts-multi-sesion.md - 013-video-recording.md - 014-network-mocking-avanzado.md - 015-geolocation-permissions.md Incluye también dev/NUEVAS_FUNCIONALIDADES.md con resumen completo. Directorio: dev/
This commit is contained in:
@@ -0,0 +1,167 @@
|
||||
# Issue #005: Eliminar timeouts innecesarios del código
|
||||
|
||||
**Tipo**: Improvement
|
||||
**Prioridad**: Alta
|
||||
**Estado**: Pendiente
|
||||
|
||||
## Descripción
|
||||
|
||||
Eliminar todos los `time.Sleep()` y timeouts hardcodeados innecesarios del código, reemplazándolos con esperas basadas en eventos CDP cuando sea posible.
|
||||
|
||||
## Problema actual
|
||||
|
||||
El código tiene múltiples `time.Sleep()` arbitrarios:
|
||||
- `time.Sleep(2 * time.Second)` en examples/basic.go
|
||||
- `time.Sleep(3 * time.Second)` en cmd/list_blog.go
|
||||
- Timeouts hardcodeados en navegación
|
||||
|
||||
Estos timeouts son problemáticos porque:
|
||||
- No se adaptan a velocidad real de carga
|
||||
- Desperdicían tiempo en conexiones rápidas
|
||||
- Fallan en conexiones lentas
|
||||
- Hacen el código menos robusto
|
||||
|
||||
## Estrategia de reemplazo
|
||||
|
||||
### 1. Eventos CDP de carga de página
|
||||
|
||||
En lugar de:
|
||||
```go
|
||||
b.Navigate(ctx, url, nil)
|
||||
time.Sleep(3 * time.Second)
|
||||
```
|
||||
|
||||
Usar eventos CDP:
|
||||
```go
|
||||
opts := browser.DefaultNavigateOptions()
|
||||
opts.WaitUntil = "networkidle" // o "load" o "domcontentloaded"
|
||||
b.Navigate(ctx, url, opts)
|
||||
// No sleep necesario, Navigate espera el evento
|
||||
```
|
||||
|
||||
### 2. Esperar por selectores
|
||||
|
||||
En lugar de:
|
||||
```go
|
||||
time.Sleep(2 * time.Second)
|
||||
html, _ := b.GetHTML(ctx, ".content")
|
||||
```
|
||||
|
||||
Usar:
|
||||
```go
|
||||
b.WaitForSelector(ctx, ".content", 30*time.Second)
|
||||
html, _ := b.GetHTML(ctx, ".content")
|
||||
```
|
||||
|
||||
### 3. Esperar por condiciones JavaScript
|
||||
|
||||
En lugar de:
|
||||
```go
|
||||
time.Sleep(1 * time.Second)
|
||||
result, _ := b.Evaluate(ctx, "window.dataReady")
|
||||
```
|
||||
|
||||
Usar:
|
||||
```go
|
||||
b.WaitForFunction(ctx, "window.dataReady === true", 100*time.Millisecond)
|
||||
result, _ := b.Evaluate(ctx, "window.data")
|
||||
```
|
||||
|
||||
### 4. Eventos de red
|
||||
|
||||
Esperar que network esté idle:
|
||||
```go
|
||||
// Implementar WaitForNetworkIdle()
|
||||
b.WaitForNetworkIdle(ctx, 500*time.Millisecond, 30*time.Second)
|
||||
```
|
||||
|
||||
## Eventos CDP útiles
|
||||
|
||||
### Page domain
|
||||
- `Page.loadEventFired` - Página cargada completamente
|
||||
- `Page.domContentEventFired` - DOM listo
|
||||
- `Page.frameStoppedLoading` - Frame dejó de cargar
|
||||
|
||||
### Network domain
|
||||
- `Network.requestWillBeSent` - Request iniciado
|
||||
- `Network.responseReceived` - Response recibida
|
||||
- `Network.loadingFinished` - Recurso terminó de cargar
|
||||
- `Network.loadingFailed` - Recurso falló
|
||||
|
||||
## Métodos a implementar
|
||||
|
||||
```go
|
||||
// WaitForEvent espera un evento CDP específico
|
||||
func (b *Browser) WaitForEvent(ctx context.Context, eventName string, timeout time.Duration) error
|
||||
|
||||
// WaitForNetworkIdle espera que no haya requests de red por X tiempo
|
||||
func (b *Browser) WaitForNetworkIdle(ctx context.Context, idleTime, timeout time.Duration) error
|
||||
|
||||
// WaitForFunction espera que una función JS retorne true
|
||||
func (b *Browser) WaitForFunction(ctx context.Context, fn string, checkInterval time.Duration) error
|
||||
|
||||
// WaitForNavigation espera que navegación complete
|
||||
func (b *Browser) WaitForNavigation(ctx context.Context, timeout time.Duration) error
|
||||
```
|
||||
|
||||
## Archivos a revisar y actualizar
|
||||
|
||||
- [x] `examples/basic.go` - Eliminar time.Sleep
|
||||
- [x] `examples/advanced.go` - Reemplazar con esperas basadas en eventos
|
||||
- [x] `cmd/list_blog.go` - Usar WaitForSelector
|
||||
- [ ] `pkg/browser/navigation.go` - Mejorar Navigate() para esperar eventos
|
||||
- [ ] `pkg/browser/browser.go` - Agregar métodos de espera
|
||||
|
||||
## Implementación en Navigate()
|
||||
|
||||
```go
|
||||
func (b *Browser) Navigate(ctx context.Context, url string, opts *NavigateOptions) error {
|
||||
if opts == nil {
|
||||
opts = DefaultNavigateOptions()
|
||||
}
|
||||
|
||||
// Registrar listener ANTES de navegar
|
||||
loadedChan := make(chan struct{})
|
||||
b.client.On("Page.loadEventFired", func() {
|
||||
close(loadedChan)
|
||||
})
|
||||
|
||||
// Enviar comando de navegación
|
||||
_, err := b.client.SendCommand(ctx, "Page.navigate", map[string]interface{}{
|
||||
"url": url,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Esperar evento según opts.WaitUntil
|
||||
select {
|
||||
case <-loadedChan:
|
||||
return nil
|
||||
case <-ctx.Done():
|
||||
return ctx.Err()
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Beneficios
|
||||
|
||||
✅ **Más rápido**: No espera más de lo necesario
|
||||
✅ **Más robusto**: Falla con timeout claro, no con misterioso "elemento no encontrado"
|
||||
✅ **Más confiable**: Se adapta a velocidad real de página
|
||||
✅ **Mejor UX**: Feedback claro de qué se está esperando
|
||||
|
||||
## Testing
|
||||
|
||||
Probar con:
|
||||
- Conexiones rápidas (localhost)
|
||||
- Conexiones lentas (throttling)
|
||||
- Páginas con mucho JavaScript
|
||||
- Páginas con assets pesados
|
||||
- SPAs (React, Vue) que cargan async
|
||||
|
||||
## Referencias
|
||||
|
||||
- CDP Page events: https://chromedevtools.github.io/devtools-protocol/tot/Page/#event-loadEventFired
|
||||
- CDP Network events: https://chromedevtools.github.io/devtools-protocol/tot/Network/
|
||||
- Puppeteer waitFor: https://pptr.dev/guides/page-interactions#waiting
|
||||
Reference in New Issue
Block a user