package browser import ( "os" "strings" "testing" "time" ) // TestFindChrome verifica que el ejecutable de Chrome es localizable. func TestFindChrome(t *testing.T) { path, err := findChrome() if err != nil { t.Skipf("Chrome no encontrado (entorno sin Chrome): %v", err) } if path == "" { t.Error("findChrome retorno path vacio") } t.Logf("Chrome encontrado en: %s", path) } // TestChromeLaunchAndConnect lanza Chrome, conecta CDP, navega a about:blank y cierra. func TestChromeLaunchAndConnect(t *testing.T) { if testing.Short() { t.Skip("skip: requiere Chrome real (use -short=false para ejecutar)") } // Verificar que Chrome esta disponible if _, err := findChrome(); err != nil { t.Skipf("Chrome no disponible: %v", err) } opts := ChromeLaunchOpts{ Port: 9223, // puerto alternativo para no interferir con sesiones existentes UserDataDir: t.TempDir(), Headless: true, } pid, err := ChromeLaunch(opts) if err != nil { t.Fatalf("ChromeLaunch: %v", err) } t.Logf("Chrome lanzado con PID %d en puerto %d", pid, opts.Port) defer func() { if err := CdpClose(nil, pid); err != nil { t.Logf("CdpClose (pid only): %v", err) } }() // Conectar CDP conn, err := CdpConnect(opts.Port) if err != nil { t.Fatalf("CdpConnect: %v", err) } defer func() { if err := CdpClose(conn, 0); err != nil { t.Logf("CdpClose (conn): %v", err) } }() // Navegar a about:blank if err := CdpNavigate(conn, "about:blank"); err != nil { t.Fatalf("CdpNavigate about:blank: %v", err) } t.Log("Navegacion a about:blank exitosa") } // TestCdpEvaluate ejecuta JS simple en Chrome y verifica el resultado. func TestCdpEvaluate(t *testing.T) { if testing.Short() { t.Skip("skip: requiere Chrome real (use -short=false para ejecutar)") } if _, err := findChrome(); err != nil { t.Skipf("Chrome no disponible: %v", err) } opts := ChromeLaunchOpts{ Port: 9224, UserDataDir: t.TempDir(), Headless: true, } pid, err := ChromeLaunch(opts) if err != nil { t.Fatalf("ChromeLaunch: %v", err) } defer CdpClose(nil, pid) conn, err := CdpConnect(opts.Port) if err != nil { t.Fatalf("CdpConnect: %v", err) } defer CdpClose(conn, 0) if err := CdpNavigate(conn, "about:blank"); err != nil { t.Fatalf("CdpNavigate: %v", err) } t.Run("expresion aritmetica simple", func(t *testing.T) { result, err := CdpEvaluate(conn, "1 + 2") if err != nil { t.Fatalf("CdpEvaluate: %v", err) } if result != "3" { t.Errorf("esperado '3', got %q", result) } }) t.Run("string literal", func(t *testing.T) { result, err := CdpEvaluate(conn, `"hola mundo"`) if err != nil { t.Fatalf("CdpEvaluate: %v", err) } if result != "hola mundo" { t.Errorf("esperado 'hola mundo', got %q", result) } }) t.Run("typeof window", func(t *testing.T) { result, err := CdpEvaluate(conn, "typeof window") if err != nil { t.Fatalf("CdpEvaluate: %v", err) } if result != "object" { t.Errorf("esperado 'object', got %q", result) } }) } // TestCdpGetHTML obtiene el HTML de about:blank y verifica que contiene elementos basicos. func TestCdpGetHTML(t *testing.T) { if testing.Short() { t.Skip("skip: requiere Chrome real (use -short=false para ejecutar)") } if _, err := findChrome(); err != nil { t.Skipf("Chrome no disponible: %v", err) } opts := ChromeLaunchOpts{ Port: 9225, UserDataDir: t.TempDir(), Headless: true, } pid, err := ChromeLaunch(opts) if err != nil { t.Fatalf("ChromeLaunch: %v", err) } defer CdpClose(nil, pid) conn, err := CdpConnect(opts.Port) if err != nil { t.Fatalf("CdpConnect: %v", err) } defer CdpClose(conn, 0) if err := CdpNavigate(conn, "about:blank"); err != nil { t.Fatalf("CdpNavigate: %v", err) } t.Run("html de about blank contiene html y body", func(t *testing.T) { html, err := CdpGetHTML(conn) if err != nil { t.Fatalf("CdpGetHTML: %v", err) } lower := strings.ToLower(html) if !strings.Contains(lower, ": %q", html[:min(200, len(html))]) } if !strings.Contains(lower, ": %q", html[:min(200, len(html))]) } t.Logf("HTML (primeros 200 chars): %s", html[:min(200, len(html))]) }) } // TestCdpScreenshot toma un screenshot de about:blank y verifica que se crea el archivo PNG. func TestCdpScreenshot(t *testing.T) { if testing.Short() { t.Skip("skip: requiere Chrome real (use -short=false para ejecutar)") } if _, err := findChrome(); err != nil { t.Skipf("Chrome no disponible: %v", err) } opts := ChromeLaunchOpts{ Port: 9226, UserDataDir: t.TempDir(), Headless: true, } pid, err := ChromeLaunch(opts) if err != nil { t.Fatalf("ChromeLaunch: %v", err) } defer CdpClose(nil, pid) conn, err := CdpConnect(opts.Port) if err != nil { t.Fatalf("CdpConnect: %v", err) } defer CdpClose(conn, 0) if err := CdpNavigate(conn, "about:blank"); err != nil { t.Fatalf("CdpNavigate: %v", err) } // Esperar un momento para que la pagina cargue time.Sleep(500 * time.Millisecond) t.Run("screenshot png se crea correctamente", func(t *testing.T) { outputPath := t.TempDir() + "/screenshot.png" err := CdpScreenshot(conn, outputPath, CdpScreenshotOpts{FullPage: false}) if err != nil { t.Fatalf("CdpScreenshot: %v", err) } info, err := os.Stat(outputPath) if err != nil { t.Fatalf("screenshot no encontrado: %v", err) } if info.Size() == 0 { t.Error("screenshot vacio (0 bytes)") } t.Logf("Screenshot creado: %s (%d bytes)", outputPath, info.Size()) }) }