3 Actions
Virgil edited this page 2026-02-19 16:56:00 +00:00

Actions

This page covers browser interactions: clicking, typing, navigation, screenshots, keyboard input, form manipulation, drag-and-drop, and the fluent action sequence builder.

See also: Home | Getting-Started | DOM-Queries | Console-Monitoring | Angular-Testing

Direct Methods

The Webview struct exposes high-level methods for the most common interactions.

Click

Clicks the centre of an element matching the CSS selector. Uses CDP Input.dispatchMouseEvent with real mouse coordinates from the element's bounding box. Falls back to a JavaScript .click() call if the element has no bounding box.

err := wv.Click("#submit-button")

Type

Types text into a focused input element, character by character. First focuses the element via JavaScript, then dispatches keyDown/keyUp events for each character.

err := wv.Type("#search-input", "browser automation")

Navigate

Navigates to a URL and waits for the page to fully load (document.readyState === "complete").

err := wv.Navigate("https://example.com/login")

Reload, GoBack, GoForward

err := wv.Reload()    // Reload current page (waits for load)
err := wv.GoBack()    // Navigate back in history
err := wv.GoForward() // Navigate forward in history

Screenshot

Captures a full-page PNG screenshot and returns the raw bytes.

data, err := wv.Screenshot()
if err == nil {
    os.WriteFile("capture.png", data, 0644)
}

Evaluate (JavaScript)

Executes JavaScript in the browser context and returns the result as a Go value.

result, err := wv.Evaluate("document.title")
title := result.(string)

result, err = wv.Evaluate("2 + 2")
sum := result.(float64) // 4

result, err = wv.Evaluate("document.querySelector('#app') !== null")
exists := result.(bool)

WaitForSelector

Polls every 100ms for an element to appear. Respects the configured timeout.

err := wv.WaitForSelector(".modal-open")

SetViewport

Overrides the viewport dimensions using the CDP Emulation domain.

err := wv.SetViewport(1920, 1080)

SetUserAgent

Sets a custom user agent string.

err := wv.SetUserAgent("MyBot/1.0")

UploadFile

Sets files on a file input element using CDP DOM.setFileInputFiles.

err := wv.UploadFile("input[type=file]", []string{"/path/to/document.pdf"})

DragAndDrop

Performs a drag-and-drop operation from one element to another using real mouse events (mousePressed, mouseMoved, mouseReleased).

err := wv.DragAndDrop("#draggable-item", "#drop-zone")

Action Interface

All browser actions implement the Action interface:

type Action interface {
    Execute(ctx context.Context, wv *Webview) error
}

This allows you to define custom actions and compose them with the built-in ones.

Built-in Action Types

Type Description Fields
ClickAction Left-click an element Selector
DoubleClickAction Double-click an element Selector
RightClickAction Right-click (context menu) Selector
HoverAction Hover over an element Selector
TypeAction Type text into an element Selector, Text
PressKeyAction Press a special key Key (e.g., "Enter", "Tab", "Escape")
NavigateAction Navigate to a URL URL
WaitAction Wait for a duration Duration
WaitForSelectorAction Wait for an element Selector
ScrollAction Scroll to coordinates X, Y
ScrollIntoViewAction Scroll element into view Selector
FocusAction Focus an element Selector
BlurAction Remove focus Selector
ClearAction Clear input value Selector
SelectAction Select dropdown option Selector, Value
CheckAction Check/uncheck checkbox Selector, Checked
SetValueAction Set input value Selector, Value
SetAttributeAction Set HTML attribute Selector, Attribute, Value
RemoveAttributeAction Remove HTML attribute Selector, Attribute

PressKeyAction Keys

The PressKeyAction supports these named keys with proper CDP key codes:

Enter, Tab, Escape, Backspace, Delete, ArrowUp, ArrowDown, ArrowLeft, ArrowRight, Home, End, PageUp, PageDown

For ordinary characters, pass the character directly (e.g., PressKeyAction{Key: "a"}).

// Press Enter after typing a search query
press := webview.PressKeyAction{Key: "Enter"}
press.Execute(ctx, wv)

ActionSequence

The ActionSequence builder lets you chain multiple actions into a single, reusable sequence with a fluent API.

seq := webview.NewActionSequence().
    Navigate("https://example.com/login").
    WaitForSelector("#email").
    Type("#email", "user@example.com").
    Type("#password", "secret").
    Click("#login-button").
    WaitForSelector(".dashboard")

ctx := context.Background()
if err := seq.Execute(ctx, wv); err != nil {
    log.Fatalf("login sequence failed: %v", err)
}

Fluent Methods

Method Adds
Navigate(url) NavigateAction
Click(selector) ClickAction
Type(selector, text) TypeAction
Wait(duration) WaitAction
WaitForSelector(selector) WaitForSelectorAction
Add(action) Any custom Action

Custom Actions in a Sequence

You can mix built-in actions with custom ones:

type ScreenshotAction struct {
    Path string
}

func (a ScreenshotAction) Execute(ctx context.Context, wv *webview.Webview) error {
    data, err := wv.Screenshot()
    if err != nil {
        return err
    }
    return os.WriteFile(a.Path, data, 0644)
}

seq := webview.NewActionSequence().
    Navigate("https://example.com").
    WaitForSelector(".loaded").
    Add(ScreenshotAction{Path: "result.png"})

Form Interaction Examples

Filling a Complete Form

// Text inputs
wv.Type("#first-name", "Jane")
wv.Type("#last-name", "Smith")

// Select dropdown
selectAction := webview.SelectAction{Selector: "#country", Value: "GB"}
selectAction.Execute(ctx, wv)

// Checkbox
checkAction := webview.CheckAction{Selector: "#terms", Checked: true}
checkAction.Execute(ctx, wv)

// Clear and retype
clearAction := webview.ClearAction{Selector: "#email"}
clearAction.Execute(ctx, wv)
wv.Type("#email", "jane@example.com")

// Submit
wv.Click("button[type=submit]")

Setting Values Directly

SetValueAction sets the value property and dispatches input and change events, which is useful for frameworks that listen on these events:

action := webview.SetValueAction{
    Selector: "#quantity",
    Value:    "5",
}
action.Execute(ctx, wv)

Practical Example: E2E Login Test

func TestLogin(t *testing.T) {
    wv, err := webview.New(
        webview.WithDebugURL("http://localhost:9222"),
        webview.WithTimeout(15 * time.Second),
    )
    if err != nil {
        t.Fatal(err)
    }
    defer wv.Close()

    // Navigate and fill login form
    wv.Navigate("http://localhost:3000/login")
    wv.WaitForSelector("#email")
    wv.Type("#email", "test@example.com")
    wv.Type("#password", "testpass123")
    wv.Click("#login-btn")

    // Verify redirect to dashboard
    wv.WaitForSelector(".dashboard-header")
    url, _ := wv.GetURL()
    if !strings.Contains(url, "/dashboard") {
        t.Errorf("expected dashboard URL, got %s", url)
    }

    // Capture evidence
    data, _ := wv.Screenshot()
    os.WriteFile("test-evidence.png", data, 0644)
}

Next Steps