From d5d352560280b67e856d27cf3aeb21c7beb04d80 Mon Sep 17 00:00:00 2001 From: Snider Date: Wed, 15 Apr 2026 14:30:45 +0100 Subject: [PATCH] refactor(actions): expose fluent builders for all actions Co-Authored-By: Virgil --- actions.go | 70 +++++++++++++++++++++++++++++++++++++++++++++++++ webview_test.go | 46 ++++++++++++++++++++++++++++++++ 2 files changed, 116 insertions(+) diff --git a/actions.go b/actions.go index ab20a10..38537af 100644 --- a/actions.go +++ b/actions.go @@ -461,6 +461,76 @@ func (s *ActionSequence) WaitForSelector(selector string) *ActionSequence { return s.Add(WaitForSelectorAction{Selector: selector}) } +// Scroll adds a scroll action. +func (s *ActionSequence) Scroll(x, y int) *ActionSequence { + return s.Add(ScrollAction{X: x, Y: y}) +} + +// ScrollIntoView adds a scroll-into-view action. +func (s *ActionSequence) ScrollIntoView(selector string) *ActionSequence { + return s.Add(ScrollIntoViewAction{Selector: selector}) +} + +// Focus adds a focus action. +func (s *ActionSequence) Focus(selector string) *ActionSequence { + return s.Add(FocusAction{Selector: selector}) +} + +// Blur adds a blur action. +func (s *ActionSequence) Blur(selector string) *ActionSequence { + return s.Add(BlurAction{Selector: selector}) +} + +// Clear adds a clear action. +func (s *ActionSequence) Clear(selector string) *ActionSequence { + return s.Add(ClearAction{Selector: selector}) +} + +// Select adds a select action. +func (s *ActionSequence) Select(selector, value string) *ActionSequence { + return s.Add(SelectAction{Selector: selector, Value: value}) +} + +// Check adds a check action. +func (s *ActionSequence) Check(selector string, checked bool) *ActionSequence { + return s.Add(CheckAction{Selector: selector, Checked: checked}) +} + +// Hover adds a hover action. +func (s *ActionSequence) Hover(selector string) *ActionSequence { + return s.Add(HoverAction{Selector: selector}) +} + +// DoubleClick adds a double-click action. +func (s *ActionSequence) DoubleClick(selector string) *ActionSequence { + return s.Add(DoubleClickAction{Selector: selector}) +} + +// RightClick adds a right-click action. +func (s *ActionSequence) RightClick(selector string) *ActionSequence { + return s.Add(RightClickAction{Selector: selector}) +} + +// PressKey adds a key press action. +func (s *ActionSequence) PressKey(key string) *ActionSequence { + return s.Add(PressKeyAction{Key: key}) +} + +// SetAttribute adds a set-attribute action. +func (s *ActionSequence) SetAttribute(selector, attribute, value string) *ActionSequence { + return s.Add(SetAttributeAction{Selector: selector, Attribute: attribute, Value: value}) +} + +// RemoveAttribute adds a remove-attribute action. +func (s *ActionSequence) RemoveAttribute(selector, attribute string) *ActionSequence { + return s.Add(RemoveAttributeAction{Selector: selector, Attribute: attribute}) +} + +// SetValue adds a set-value action. +func (s *ActionSequence) SetValue(selector, value string) *ActionSequence { + return s.Add(SetValueAction{Selector: selector, Value: value}) +} + // Execute executes all actions in the sequence. func (s *ActionSequence) Execute(ctx context.Context, wv *Webview) error { for i, action := range s.actions { diff --git a/webview_test.go b/webview_test.go index f7ffae6..157422d 100644 --- a/webview_test.go +++ b/webview_test.go @@ -150,6 +150,52 @@ func TestActionSequence_Good(t *testing.T) { } } +// TestActionSequence_Good_AllBuilders verifies every fluent builder appends the expected action. +func TestActionSequence_Good_AllBuilders(t *testing.T) { + seq := NewActionSequence(). + Scroll(0, 500). + ScrollIntoView("#target"). + Focus("#input"). + Blur("#input"). + Clear("#input"). + Select("#dropdown", "option1"). + Check("#checkbox", true). + Hover("#menu-item"). + DoubleClick("#editable"). + RightClick("#context-menu-trigger"). + PressKey("Enter"). + SetAttribute("#element", "data-value", "test"). + RemoveAttribute("#element", "disabled"). + SetValue("#input", "new value") + + if len(seq.actions) != 14 { + t.Fatalf("Expected 14 actions, got %d", len(seq.actions)) + } + + wantTypes := []any{ + ScrollAction{X: 0, Y: 500}, + ScrollIntoViewAction{Selector: "#target"}, + FocusAction{Selector: "#input"}, + BlurAction{Selector: "#input"}, + ClearAction{Selector: "#input"}, + SelectAction{Selector: "#dropdown", Value: "option1"}, + CheckAction{Selector: "#checkbox", Checked: true}, + HoverAction{Selector: "#menu-item"}, + DoubleClickAction{Selector: "#editable"}, + RightClickAction{Selector: "#context-menu-trigger"}, + PressKeyAction{Key: "Enter"}, + SetAttributeAction{Selector: "#element", Attribute: "data-value", Value: "test"}, + RemoveAttributeAction{Selector: "#element", Attribute: "disabled"}, + SetValueAction{Selector: "#input", Value: "new value"}, + } + + for i, want := range wantTypes { + if got := seq.actions[i]; got != want { + t.Fatalf("action %d = %#v, want %#v", i, got, want) + } + } +} + // TestClickAction_Good verifies ClickAction struct. func TestClickAction_Good(t *testing.T) { action := ClickAction{Selector: "#submit"}