Files
navegator/dev/issues/007-alert-prompt-confirm-handling.md
T
Developer c165f2f788 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/
2026-03-25 00:49:06 +01:00

301 lines
7.8 KiB
Markdown

# Issue #007: Alert/Prompt/Confirm Handling
**Tipo**: Enhancement
**Prioridad**: Media
**Estado**: Pendiente
## Descripción
Implementar manejo de JavaScript dialogs (alert, prompt, confirm) que aparecen en páginas web.
## Funcionalidad deseada
### Tipos de dialogs
- **Alert**: `window.alert("mensaje")` - Solo botón OK
- **Confirm**: `window.confirm("¿Continuar?")` - OK/Cancel, retorna boolean
- **Prompt**: `window.prompt("Nombre:", "default")` - Input + OK/Cancel
### Operaciones
- Detectar cuando aparece un dialog
- Aceptar dialog (OK)
- Rechazar dialog (Cancel)
- Enviar texto a prompt
- Obtener mensaje del dialog
- Manejar dialogs automáticamente con reglas
## Implementación técnica
### Archivo sugerido
`pkg/browser/dialogs.go`
### CDP Domain
**Page.javascriptDialogOpening** - Evento cuando aparece dialog
**Page.handleJavaScriptDialog** - Responder al dialog
### API propuesta
```go
// DialogType tipo de dialog JavaScript
type DialogType string
const (
DialogTypeAlert DialogType = "alert"
DialogTypeConfirm DialogType = "confirm"
DialogTypePrompt DialogType = "prompt"
)
// DialogAction acción a tomar con el dialog
type DialogAction string
const (
DialogAccept DialogAction = "accept" // OK
DialogDismiss DialogAction = "dismiss" // Cancel
)
// Dialog representa un dialog JavaScript
type Dialog struct {
Type DialogType
Message string
DefaultPromptText string
}
// HandleDialog maneja un dialog JavaScript cuando aparece
func (b *Browser) HandleDialog(ctx context.Context, action DialogAction, promptText string) error
// OnDialog registra un handler para dialogs
func (b *Browser) OnDialog(handler func(*Dialog) (DialogAction, string)) error
// WaitForDialog espera a que aparezca un dialog
func (b *Browser) WaitForDialog(ctx context.Context) (*Dialog, error)
// AcceptDialog acepta el próximo dialog que aparezca
func (b *Browser) AcceptDialog(ctx context.Context) error
// DismissDialog rechaza el próximo dialog que aparezca
func (b *Browser) DismissDialog(ctx context.Context) error
// PromptDialog responde a un prompt con texto
func (b *Browser) PromptDialog(ctx context.Context, text string) error
// AutoHandleDialogs configura manejo automático de dialogs
func (b *Browser) AutoHandleDialogs(ctx context.Context, action DialogAction) error
```
## Casos de uso
### Caso 1: Aceptar alert automáticamente
```go
// Configurar manejo automático
b.AutoHandleDialogs(ctx, browser.DialogAccept)
// Cualquier alert será aceptado automáticamente
b.Click(ctx, "#trigger-alert")
```
### Caso 2: Manejar confirm con lógica
```go
b.OnDialog(func(dialog *browser.Dialog) (browser.DialogAction, string) {
log.Printf("Dialog: %s - %s", dialog.Type, dialog.Message)
if dialog.Type == browser.DialogTypeConfirm {
if strings.Contains(dialog.Message, "eliminar") {
return browser.DialogDismiss, "" // Cancelar eliminación
}
}
return browser.DialogAccept, ""
})
b.Click(ctx, "#delete-button")
```
### Caso 3: Responder a prompt
```go
// Esperar prompt y responder
go func() {
dialog, _ := b.WaitForDialog(ctx)
if dialog.Type == browser.DialogTypePrompt {
b.PromptDialog(ctx, "Mi nombre")
}
}()
b.Click(ctx, "#ask-name-button")
```
### Caso 4: Aceptar dialog específico
```go
// Preparar handler antes de la acción
b.AcceptDialog(ctx)
// Acción que genera dialog
b.Click(ctx, "#show-alert")
```
## Comandos CDP necesarios
```go
// 1. Habilitar eventos de dialog
{"method": "Page.enable"}
// 2. Escuchar evento de dialog
// Evento: "Page.javascriptDialogOpening"
// Params: {
// "url": "https://...",
// "message": "Mensaje del dialog",
// "type": "alert|confirm|prompt",
// "defaultPrompt": "texto default" // solo en prompt
// }
// 3. Responder al dialog
{"method": "Page.handleJavaScriptDialog", "params": {
"accept": true, // true = OK, false = Cancel
"promptText": "texto de respuesta" // opcional, solo para prompt
}}
```
## Implementación interna
```go
type dialogHandler struct {
action DialogAction
promptText string
callback func(*Dialog) (DialogAction, string)
done chan struct{}
}
func (b *Browser) setupDialogHandling() {
b.cdpClient.On("Page.javascriptDialogOpening", func(params json.RawMessage) {
var event struct {
Type string `json:"type"`
Message string `json:"message"`
DefaultPrompt string `json:"defaultPrompt"`
}
json.Unmarshal(params, &event)
dialog := &Dialog{
Type: DialogType(event.Type),
Message: event.Message,
DefaultPromptText: event.DefaultPrompt,
}
// Procesar con handler registrado
action, text := b.processDialog(dialog)
// Responder
b.cdpClient.SendCommand(context.Background(), "Page.handleJavaScriptDialog", map[string]interface{}{
"accept": action == DialogAccept,
"promptText": text,
})
})
}
```
## Consideraciones especiales
### Timing crítico
- Los dialogs **bloquean** JavaScript hasta que se responden
- Debe haber handler registrado ANTES de que aparezca el dialog
- Si no se maneja, Chrome esperará indefinidamente
### beforeunload dialogs
```go
// Dialogs de "¿Seguro que quieres salir?"
// Se generan al cerrar tab/navegador
b.OnDialog(func(dialog *Dialog) (browser.DialogAction, string) {
if dialog.Type == browser.DialogTypeBeforeUnload {
return browser.DialogAccept, "" // Permitir salir
}
return browser.DialogAccept, ""
})
```
### Headless mode
- En modo headless, los dialogs no se muestran visualmente
- Pero igual generan el evento y deben manejarse
- Importante para testing automatizado
### Timeout en dialogs
```go
// Implementar timeout para evitar quedar colgado
ctx, cancel := context.WithTimeout(ctx, 5*time.Second)
defer cancel()
dialog, err := b.WaitForDialog(ctx)
if err == context.DeadlineExceeded {
log.Println("No apareció dialog en 5s")
}
```
## Testing
### Página de prueba
```html
<!DOCTYPE html>
<html>
<body>
<button onclick="alert('Hola')">Alert</button>
<button onclick="confirm('¿Continuar?')">Confirm</button>
<button onclick="prompt('Nombre:')">Prompt</button>
<script>
// Test beforeunload
window.addEventListener('beforeunload', (e) => {
e.preventDefault();
e.returnValue = '';
});
</script>
</body>
</html>
```
### Tests
```go
func TestAlertHandling(t *testing.T) {
b.AutoHandleDialogs(ctx, browser.DialogAccept)
b.Navigate(ctx, "test.html", nil)
b.Click(ctx, "button:nth-child(1)")
// No debe quedar colgado
}
func TestPromptResponse(t *testing.T) {
b.OnDialog(func(d *browser.Dialog) (browser.DialogAction, string) {
if d.Type == browser.DialogTypePrompt {
return browser.DialogAccept, "Test Name"
}
return browser.DialogAccept, ""
})
b.Click(ctx, "button:nth-child(3)")
result, _ := b.Evaluate(ctx, "lastPromptResult")
assert.Equal(t, "Test Name", result.Value)
}
```
## Ejemplos de uso real
### Login con confirm
```go
b.OnDialog(func(d *browser.Dialog) (browser.DialogAction, string) {
if strings.Contains(d.Message, "logout") {
return browser.DialogAccept, ""
}
return browser.DialogDismiss, ""
})
b.Click(ctx, "#logout-button")
```
### Formulario con prompt
```go
b.PromptDialog(ctx, "usuario@example.com")
b.Click(ctx, "#ask-email-button")
```
## Referencias
- CDP Page.handleJavaScriptDialog: https://chromedevtools.github.io/devtools-protocol/tot/Page/#method-handleJavaScriptDialog
- CDP Page.javascriptDialogOpening: https://chromedevtools.github.io/devtools-protocol/tot/Page/#event-javascriptDialogOpening
- Playwright Dialogs: https://playwright.dev/docs/dialogs
- Selenium Alerts: https://www.selenium.dev/documentation/webdriver/interactions/alerts/