feat: add SetDefaultTimeout to InteractiveBrowser interface
All checks were successful
CI / test (push) Successful in 45s
CI / vet (push) Successful in 49s
CI / build (push) Successful in 50s

Adds SetDefaultTimeout(time.Duration) to the InteractiveBrowser interface,
delegating to Playwright's Page and BrowserContext SetDefaultTimeout and
SetDefaultNavigationTimeout methods. This allows callers to set a timeout
so Playwright operations return an error instead of blocking forever when
the browser process crashes or the remote server becomes unresponsive.

Closes #86

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-17 01:59:16 +00:00
parent d89031b20d
commit adefaaef36
2 changed files with 20 additions and 0 deletions

View File

@@ -48,6 +48,16 @@ type InteractiveBrowser interface {
// Cookies returns all cookies from the browser context. // Cookies returns all cookies from the browser context.
Cookies() ([]Cookie, error) Cookies() ([]Cookie, error)
// SetDefaultTimeout sets the default timeout for all Playwright operations
// (navigation, clicks, screenshots, cookie extraction, etc.). A value of 0
// disables timeouts. By default, Playwright uses a 30-second timeout.
//
// This is the primary mechanism for preventing hung sessions: callers can
// set a timeout so that any Playwright call returns an error instead of
// blocking forever if the browser process crashes or the remote server
// becomes unresponsive.
SetDefaultTimeout(timeout time.Duration)
// Close tears down the browser. // Close tears down the browser.
Close() error Close() error
} }
@@ -246,6 +256,14 @@ func (ib *interactiveBrowser) Cookies() ([]Cookie, error) {
return cookies, nil return cookies, nil
} }
func (ib *interactiveBrowser) SetDefaultTimeout(timeout time.Duration) {
ms := float64(timeout.Milliseconds())
ib.page.SetDefaultTimeout(ms)
ib.page.SetDefaultNavigationTimeout(ms)
ib.ctx.SetDefaultTimeout(ms)
ib.ctx.SetDefaultNavigationTimeout(ms)
}
func (ib *interactiveBrowser) Close() error { func (ib *interactiveBrowser) Close() error {
if ib.detached { if ib.detached {
return nil return nil

View File

@@ -3,6 +3,7 @@ package extractor
import ( import (
"errors" "errors"
"testing" "testing"
"time"
) )
// mockInteractiveBrowser implements InteractiveBrowser for testing without Playwright. // mockInteractiveBrowser implements InteractiveBrowser for testing without Playwright.
@@ -22,6 +23,7 @@ func (m mockInteractiveBrowser) KeyboardPress(string) error { return
func (m mockInteractiveBrowser) KeyboardInsertText(string) error { return nil } func (m mockInteractiveBrowser) KeyboardInsertText(string) error { return nil }
func (m mockInteractiveBrowser) Screenshot(int) ([]byte, error) { return nil, nil } func (m mockInteractiveBrowser) Screenshot(int) ([]byte, error) { return nil, nil }
func (m mockInteractiveBrowser) Cookies() ([]Cookie, error) { return nil, nil } func (m mockInteractiveBrowser) Cookies() ([]Cookie, error) { return nil, nil }
func (m mockInteractiveBrowser) SetDefaultTimeout(time.Duration) {}
func (m mockInteractiveBrowser) Close() error { return nil } func (m mockInteractiveBrowser) Close() error { return nil }
func TestPromoteToInteractive_NonPromotable(t *testing.T) { func TestPromoteToInteractive_NonPromotable(t *testing.T) {