Files
fn_registry/functions/browser/chrome_launch_test.go
T
egutierrez bf1efb2099 feat: externalize apps/analysis to Gitea repos, add analysis table
- Migration 007: repo_url on apps table + analysis table with FTS5
- Analysis struct, parser, CRUD, validation, hash computation
- Selective purge: remote-only apps/analysis preserved across fn index
- CLI: fn app list/clone/pull, fn analysis list/clone/pull
- search/show/list now include analysis results
- Apps removed from git tracking (content lives in Gitea repos)
- .gitkeep for apps/ and analysis/ dirs
- Bash functions: jupyter analysis pipeline, shell utilities
- Browser domain: CDP functions moved from infra to browser

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 04:23:51 +02:00

232 lines
5.5 KiB
Go

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, "<html") {
t.Errorf("HTML no contiene tag <html>: %q", html[:min(200, len(html))])
}
if !strings.Contains(lower, "<body") {
t.Errorf("HTML no contiene tag <body>: %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())
})
}