From b993fc18f3a592c1dd23cb65d2a42fba1f73be54 Mon Sep 17 00:00:00 2001 From: Virgil Date: Wed, 1 Apr 2026 04:47:46 +0000 Subject: [PATCH] feat(webview): populate element content fields Co-Authored-By: Virgil --- webview.go | 53 +++++++++++++++++++++++++++++++++++++++++++++++++ webview_test.go | 20 +++++++++++++++++++ 2 files changed, 73 insertions(+) diff --git a/webview.go b/webview.go index 15cac55..b891aa9 100644 --- a/webview.go +++ b/webview.go @@ -679,6 +679,8 @@ func (wv *Webview) getElementInfo(ctx context.Context, nodeID int) (*ElementInfo } } + innerHTML, innerText := wv.getElementContent(ctx, nodeID) + // Get bounding box var box *BoundingBox if boxResult, err := wv.client.Call(ctx, "DOM.getBoxModel", map[string]any{ @@ -704,10 +706,61 @@ func (wv *Webview) getElementInfo(ctx context.Context, nodeID int) (*ElementInfo NodeID: nodeID, TagName: tagName, Attributes: attrs, + InnerHTML: innerHTML, + InnerText: innerText, BoundingBox: box, }, nil } +// getElementContent retrieves the element's inner HTML and inner text. +func (wv *Webview) getElementContent(ctx context.Context, nodeID int) (string, string) { + resolveResult, err := wv.client.Call(ctx, "DOM.resolveNode", map[string]any{ + "nodeId": nodeID, + }) + if err != nil { + return "", "" + } + + object, ok := resolveResult["object"].(map[string]any) + if !ok { + return "", "" + } + + objectID, ok := object["objectId"].(string) + if !ok || objectID == "" { + return "", "" + } + + callResult, err := wv.client.Call(ctx, "Runtime.callFunctionOn", map[string]any{ + "objectId": objectID, + "functionDeclaration": "function() { return { innerHTML: this.innerHTML || '', innerText: this.innerText || '' }; }", + "returnByValue": true, + "awaitPromise": true, + }) + if err != nil { + return "", "" + } + + return parseElementContent(callResult) +} + +// parseElementContent extracts inner HTML and inner text from a CDP response. +func parseElementContent(result map[string]any) (string, string) { + resultObj, ok := result["result"].(map[string]any) + if !ok { + return "", "" + } + + value, ok := resultObj["value"].(map[string]any) + if !ok { + return "", "" + } + + innerHTML, _ := value["innerHTML"].(string) + innerText, _ := value["innerText"].(string) + return innerHTML, innerText +} + // click performs a click on an element. func (wv *Webview) click(ctx context.Context, selector string) error { // Find element and get its center coordinates diff --git a/webview_test.go b/webview_test.go index dd32729..349373c 100644 --- a/webview_test.go +++ b/webview_test.go @@ -458,6 +458,26 @@ func TestGetString_Good(t *testing.T) { } } +// TestParseElementContent_Good verifies inner content extraction from CDP output. +func TestParseElementContent_Good(t *testing.T) { + result := map[string]any{ + "result": map[string]any{ + "value": map[string]any{ + "innerHTML": "Hello", + "innerText": "Hello", + }, + }, + } + + innerHTML, innerText := parseElementContent(result) + if innerHTML != "Hello" { + t.Fatalf("parseElementContent innerHTML = %q, want %q", innerHTML, "Hello") + } + if innerText != "Hello" { + t.Fatalf("parseElementContent innerText = %q, want %q", innerText, "Hello") + } +} + // TestWaitAction_Good_ContextCancelled verifies WaitAction respects context cancellation. func TestWaitAction_Good_ContextCancelled(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) -- 2.45.3