package browser import ( "context" "os" "path/filepath" "testing" "time" ) func TestLaunchBrowser(t *testing.T) { ctx := context.Background() // Crear directorio temporal para perfiles tempDir := t.TempDir() config := DefaultConfig() config.ProfilesBaseDir = tempDir config.ProfileName = "test-launch" config.StealthFlags.Headless = true config.StartTimeout = 15 * time.Second // Lanzar navegador b, err := Launch(ctx, config) if err != nil { t.Fatalf("Failed to launch browser: %v", err) } defer b.Close() // Verificar que el perfil se creó profilePath := filepath.Join(tempDir, "test-launch") if _, err := os.Stat(profilePath); os.IsNotExist(err) { t.Errorf("Profile directory not created: %s", profilePath) } // Verificar que tenemos debug URL if b.DebugURL() == "" { t.Error("Debug URL is empty") } // Verificar que tenemos target ID if b.TargetID() == "" { t.Error("Target ID is empty") } } func TestNavigate(t *testing.T) { ctx := context.Background() tempDir := t.TempDir() config := DefaultConfig() config.ProfilesBaseDir = tempDir config.ProfileName = "test-navigate" config.StealthFlags.Headless = true b, err := Launch(ctx, config) if err != nil { t.Fatalf("Failed to launch browser: %v", err) } defer b.Close() // Navegar a example.com opts := DefaultNavigateOptions() opts.Timeout = 15 * time.Second err = b.Navigate(ctx, "https://example.com", opts) if err != nil { t.Fatalf("Failed to navigate: %v", err) } // Verificar que estamos en la página correcta result, err := b.Evaluate(ctx, "window.location.href") if err != nil { t.Fatalf("Failed to evaluate location: %v", err) } url, ok := result.Value.(string) if !ok || url != "https://example.com/" { t.Errorf("Expected URL https://example.com/, got %v", result.Value) } } func TestScreenshot(t *testing.T) { ctx := context.Background() tempDir := t.TempDir() config := DefaultConfig() config.ProfilesBaseDir = tempDir config.ProfileName = "test-screenshot" config.StealthFlags.Headless = true b, err := Launch(ctx, config) if err != nil { t.Fatalf("Failed to launch browser: %v", err) } defer b.Close() // Navegar opts := DefaultNavigateOptions() opts.Timeout = 15 * time.Second if err := b.Navigate(ctx, "https://example.com", opts); err != nil { t.Logf("Navigation warning: %v", err) } // Tomar screenshot screenshot, err := b.Screenshot(ctx, false) if err != nil { t.Fatalf("Failed to take screenshot: %v", err) } // Verificar que tiene contenido if len(screenshot) == 0 { t.Error("Screenshot is empty") } // Verificar que es PNG válido (empieza con magic bytes) if len(screenshot) < 8 || screenshot[0] != 0x89 || screenshot[1] != 0x50 { t.Error("Screenshot is not a valid PNG") } } func TestEvaluate(t *testing.T) { ctx := context.Background() tempDir := t.TempDir() config := DefaultConfig() config.ProfilesBaseDir = tempDir config.ProfileName = "test-evaluate" config.StealthFlags.Headless = true b, err := Launch(ctx, config) if err != nil { t.Fatalf("Failed to launch browser: %v", err) } defer b.Close() // Navegar opts := DefaultNavigateOptions() opts.Timeout = 15 * time.Second if err := b.Navigate(ctx, "https://example.com", opts); err != nil { t.Logf("Navigation warning: %v", err) } // Evaluar JavaScript result, err := b.Evaluate(ctx, "2 + 2") if err != nil { t.Fatalf("Failed to evaluate: %v", err) } // Verificar resultado val, ok := result.Value.(float64) if !ok || val != 4 { t.Errorf("Expected 4, got %v", result.Value) } } func TestStealthFlags(t *testing.T) { ctx := context.Background() tempDir := t.TempDir() config := DefaultConfig() config.ProfilesBaseDir = tempDir config.ProfileName = "test-stealth" config.StealthFlags.Headless = true b, err := Launch(ctx, config) if err != nil { t.Fatalf("Failed to launch browser: %v", err) } defer b.Close() // Navegar opts := DefaultNavigateOptions() opts.Timeout = 15 * time.Second if err := b.Navigate(ctx, "https://example.com", opts); err != nil { t.Logf("Navigation warning: %v", err) } // Verificar navigator.webdriver = false result, err := b.Evaluate(ctx, "navigator.webdriver") if err != nil { t.Fatalf("Failed to evaluate webdriver: %v", err) } // Debe ser false o undefined if result.Value != false && result.Value != nil { t.Errorf("navigator.webdriver should be false, got %v", result.Value) } // Verificar window.chrome existe chromeExists, err := b.Evaluate(ctx, "typeof window.chrome !== 'undefined'") if err != nil { t.Fatalf("Failed to check chrome object: %v", err) } if chromeExists.Value != true { t.Error("window.chrome should exist") } } func TestRecorder(t *testing.T) { tempDir := t.TempDir() recordFile := filepath.Join(tempDir, "test-recording.log") recorder, err := NewRecorder(recordFile) if err != nil { t.Fatalf("Failed to create recorder: %v", err) } defer recorder.Close() // Registrar acción recorder.Record("TestAction", map[string]interface{}{ "param1": "value1", "param2": 123, }, "test result", nil) recorder.Close() // Verificar que el archivo existe y tiene contenido content, err := os.ReadFile(recordFile) if err != nil { t.Fatalf("Failed to read recording file: %v", err) } if len(content) == 0 { t.Error("Recording file is empty") } // Verificar que contiene JSON contentStr := string(content) if !contains(contentStr, "TestAction") { t.Error("Recording doesn't contain action name") } } func TestProfilePersistence(t *testing.T) { ctx := context.Background() tempDir := t.TempDir() profileName := "test-persistence" // Primera sesión: crear perfil config1 := DefaultConfig() config1.ProfilesBaseDir = tempDir config1.ProfileName = profileName config1.StealthFlags.Headless = true b1, err := Launch(ctx, config1) if err != nil { t.Fatalf("Failed to launch browser (session 1): %v", err) } // Verificar perfil creado profilePath := filepath.Join(tempDir, profileName) if _, err := os.Stat(profilePath); os.IsNotExist(err) { t.Fatalf("Profile not created: %s", profilePath) } b1.Close() // Segunda sesión: reutilizar perfil config2 := DefaultConfig() config2.ProfilesBaseDir = tempDir config2.ProfileName = profileName config2.StealthFlags.Headless = true b2, err := Launch(ctx, config2) if err != nil { t.Fatalf("Failed to launch browser (session 2): %v", err) } defer b2.Close() // Perfil debe seguir existiendo if _, err := os.Stat(profilePath); os.IsNotExist(err) { t.Error("Profile was deleted between sessions") } } // Helper function func contains(s, substr string) bool { return len(s) >= len(substr) && (s == substr || len(s) > len(substr) && containsHelper(s, substr)) } func containsHelper(s, substr string) bool { for i := 0; i <= len(s)-len(substr); i++ { if s[i:i+len(substr)] == substr { return true } } return false }