From 03a706600af070ce95011f1a149b507fbed2c097 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C4=B0nan=C3=A7=20G=C3=BCm=C3=BC=C5=9F?= Date: Wed, 15 May 2024 13:36:22 +0300 Subject: [PATCH 01/32] Fix BoundingBox mapping Although ElementHandle.BoundingBox always returns a nil error (as PW does), for consistency, it's better to reflect this in the API test here. --- browser/mapping_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/browser/mapping_test.go b/browser/mapping_test.go index e48a60500..7b954b7ec 100644 --- a/browser/mapping_test.go +++ b/browser/mapping_test.go @@ -422,7 +422,7 @@ type frameAPI interface { type elementHandleAPI interface { common.JSHandleAPI - BoundingBox() *common.Rect + BoundingBox() (*common.Rect, error) Check(opts goja.Value) Click(opts goja.Value) error ContentFrame() (*common.Frame, error) From a1b99556674a9a48a31cbe56f296d57e29feb653 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C4=B0nan=C3=A7=20G=C3=BCm=C3=BC=C5=9F?= Date: Wed, 15 May 2024 13:56:24 +0300 Subject: [PATCH 02/32] Refactor ElementHandle.Check to return err --- browser/mapping_test.go | 2 +- common/element_handle.go | 25 +++++++++++++------------ 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/browser/mapping_test.go b/browser/mapping_test.go index 7b954b7ec..cb1d79cb8 100644 --- a/browser/mapping_test.go +++ b/browser/mapping_test.go @@ -423,7 +423,7 @@ type elementHandleAPI interface { common.JSHandleAPI BoundingBox() (*common.Rect, error) - Check(opts goja.Value) + Check(opts goja.Value) error Click(opts goja.Value) error ContentFrame() (*common.Frame, error) Dblclick(opts goja.Value) diff --git a/common/element_handle.go b/common/element_handle.go index 6f506db59..809b9078a 100644 --- a/common/element_handle.go +++ b/common/element_handle.go @@ -1113,22 +1113,23 @@ func (h *ElementHandle) queryAll(selector string, eval evalFunc) ([]*ElementHand } // SetChecked checks or unchecks an element. -func (h *ElementHandle) SetChecked(checked bool, opts goja.Value) { - parsedOpts := NewElementHandleSetCheckedOptions(h.defaultTimeout()) - err := parsedOpts.Parse(h.ctx, opts) - if err != nil { - k6ext.Panic(h.ctx, "parsing setChecked options: %w", err) +func (h *ElementHandle) SetChecked(checked bool, opts goja.Value) error { + popts := NewElementHandleSetCheckedOptions(h.defaultTimeout()) + if err := popts.Parse(h.ctx, opts); err != nil { + return fmt.Errorf("parsing setChecked options: %w", err) } - fn := func(apiCtx context.Context, handle *ElementHandle, p *Position) (any, error) { + setChecked := func(apiCtx context.Context, handle *ElementHandle, p *Position) (any, error) { return nil, handle.setChecked(apiCtx, checked, p) } - pointerFn := h.newPointerAction(fn, &parsedOpts.ElementHandleBasePointerOptions) - _, err = call(h.ctx, pointerFn, parsedOpts.Timeout) - if err != nil { - k6ext.Panic(h.ctx, "checking element: %w", err) + setCheckedAction := h.newPointerAction(setChecked, &popts.ElementHandleBasePointerOptions) + if _, err := call(h.ctx, setCheckedAction, popts.Timeout); err != nil { + return fmt.Errorf("checking element: %w", err) } + applySlowMo(h.ctx) + + return nil } // Uncheck scrolls element into view, and if it's an input element of type @@ -1139,8 +1140,8 @@ func (h *ElementHandle) Uncheck(opts goja.Value) { // Check scrolls element into view, and if it's an input element of type // checkbox that is unchecked, clicks on it to mark it as checked. -func (h *ElementHandle) Check(opts goja.Value) { - h.SetChecked(true, opts) +func (h *ElementHandle) Check(opts goja.Value) error { + return h.SetChecked(true, opts) } func (h *ElementHandle) setChecked(apiCtx context.Context, checked bool, p *Position) error { From b92934c0e310d37430e189e3bacedf0b019ce467 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C4=B0nan=C3=A7=20G=C3=BCm=C3=BC=C5=9F?= Date: Wed, 15 May 2024 14:05:01 +0300 Subject: [PATCH 03/32] Refactor ElementHandle.Uncheck to return err --- browser/mapping_test.go | 2 +- common/element_handle.go | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/browser/mapping_test.go b/browser/mapping_test.go index cb1d79cb8..42a1a8cbc 100644 --- a/browser/mapping_test.go +++ b/browser/mapping_test.go @@ -453,7 +453,7 @@ type elementHandleAPI interface { Tap(opts goja.Value) error TextContent() string Type(text string, opts goja.Value) - Uncheck(opts goja.Value) + Uncheck(opts goja.Value) error WaitForElementState(state string, opts goja.Value) WaitForSelector(selector string, opts goja.Value) (*common.ElementHandle, error) } diff --git a/common/element_handle.go b/common/element_handle.go index 809b9078a..c89a2a071 100644 --- a/common/element_handle.go +++ b/common/element_handle.go @@ -1134,8 +1134,8 @@ func (h *ElementHandle) SetChecked(checked bool, opts goja.Value) error { // Uncheck scrolls element into view, and if it's an input element of type // checkbox that is already checked, clicks on it to mark it as unchecked. -func (h *ElementHandle) Uncheck(opts goja.Value) { - h.SetChecked(false, opts) +func (h *ElementHandle) Uncheck(opts goja.Value) error { + return h.SetChecked(false, opts) } // Check scrolls element into view, and if it's an input element of type From 25b83812a08306b0a8c7788f5d0c7efe004c1cbe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C4=B0nan=C3=A7=20G=C3=BCm=C3=BC=C5=9F?= Date: Wed, 15 May 2024 14:15:34 +0300 Subject: [PATCH 04/32] Refactor ElementHandle.Dblclick to return err --- browser/mapping_test.go | 2 +- common/element_handle.go | 26 +++++++++++++++----------- common/frame.go | 2 +- 3 files changed, 17 insertions(+), 13 deletions(-) diff --git a/browser/mapping_test.go b/browser/mapping_test.go index 42a1a8cbc..99355a927 100644 --- a/browser/mapping_test.go +++ b/browser/mapping_test.go @@ -426,7 +426,7 @@ type elementHandleAPI interface { Check(opts goja.Value) error Click(opts goja.Value) error ContentFrame() (*common.Frame, error) - Dblclick(opts goja.Value) + Dblclick(opts goja.Value) error DispatchEvent(typ string, props goja.Value) Fill(value string, opts goja.Value) Focus() diff --git a/common/element_handle.go b/common/element_handle.go index c89a2a071..4f258db2b 100644 --- a/common/element_handle.go +++ b/common/element_handle.go @@ -228,7 +228,7 @@ func compensateHalfIntegerRoundingError(p Position) Position { return p } -func (h *ElementHandle) dblClick(p *Position, opts *MouseClickOptions) error { +func (h *ElementHandle) dblclick(p *Position, opts *MouseClickOptions) error { return h.frame.page.Mouse.click(p.X, p.Y, opts) } @@ -750,20 +750,24 @@ func (h *ElementHandle) ContentFrame() (*Frame, error) { return frame, nil } -func (h *ElementHandle) Dblclick(opts goja.Value) { - actionOpts := NewElementHandleDblclickOptions(h.defaultTimeout()) - if err := actionOpts.Parse(h.ctx, opts); err != nil { - k6ext.Panic(h.ctx, "parsing element double click options: %w", err) +// Dblclick scrolls element into view and double clicks on the element. +func (h *ElementHandle) Dblclick(opts goja.Value) error { + popts := NewElementHandleDblclickOptions(h.defaultTimeout()) + if err := popts.Parse(h.ctx, opts); err != nil { + return fmt.Errorf("parsing element double click options: %w", err) } - fn := func(apiCtx context.Context, handle *ElementHandle, p *Position) (any, error) { - return nil, handle.dblClick(p, actionOpts.ToMouseClickOptions()) + + dblclick := func(_ context.Context, handle *ElementHandle, p *Position) (any, error) { + return nil, handle.dblclick(p, popts.ToMouseClickOptions()) } - pointerFn := h.newPointerAction(fn, &actionOpts.ElementHandleBasePointerOptions) - _, err := call(h.ctx, pointerFn, actionOpts.Timeout) - if err != nil { - k6ext.Panic(h.ctx, "double clicking on element: %w", err) + dblclickAction := h.newPointerAction(dblclick, &popts.ElementHandleBasePointerOptions) + if _, err := call(h.ctx, dblclickAction, popts.Timeout); err != nil { + return fmt.Errorf("double clicking on element: %w", err) } + applySlowMo(h.ctx) + + return nil } // DispatchEvent dispatches a DOM event to the element. diff --git a/common/frame.go b/common/frame.go index 2bd95ca15..bf1eefbd1 100644 --- a/common/frame.go +++ b/common/frame.go @@ -738,7 +738,7 @@ func (f *Frame) Dblclick(selector string, opts goja.Value) { // an error, or applies slow motion. func (f *Frame) dblclick(selector string, opts *FrameDblclickOptions) error { dblclick := func(apiCtx context.Context, eh *ElementHandle, p *Position) (any, error) { - return nil, eh.dblClick(p, opts.ToMouseClickOptions()) + return nil, eh.dblclick(p, opts.ToMouseClickOptions()) } act := f.newPointerAction( selector, DOMElementStateAttached, opts.Strict, dblclick, &opts.ElementHandleBasePointerOptions, From 893cc77f6a8b7f89199f7437cfe36cd70285587a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C4=B0nan=C3=A7=20G=C3=BCm=C3=BC=C5=9F?= Date: Wed, 15 May 2024 14:16:57 +0300 Subject: [PATCH 05/32] Refactor ElementHandle.Fill to return err --- browser/mapping_test.go | 2 +- common/element_handle.go | 26 ++++++++++++++++---------- tests/page_test.go | 2 +- 3 files changed, 18 insertions(+), 12 deletions(-) diff --git a/browser/mapping_test.go b/browser/mapping_test.go index 99355a927..f8270e2bc 100644 --- a/browser/mapping_test.go +++ b/browser/mapping_test.go @@ -428,7 +428,7 @@ type elementHandleAPI interface { ContentFrame() (*common.Frame, error) Dblclick(opts goja.Value) error DispatchEvent(typ string, props goja.Value) - Fill(value string, opts goja.Value) + Fill(value string, opts goja.Value) error Focus() GetAttribute(name string) goja.Value Hover(opts goja.Value) diff --git a/common/element_handle.go b/common/element_handle.go index 4f258db2b..792fd1497 100644 --- a/common/element_handle.go +++ b/common/element_handle.go @@ -787,21 +787,27 @@ func (h *ElementHandle) DispatchEvent(typ string, eventInit any) error { return nil } -func (h *ElementHandle) Fill(value string, opts goja.Value) { - actionOpts := NewElementHandleBaseOptions(h.defaultTimeout()) - if err := actionOpts.Parse(h.ctx, opts); err != nil { - k6ext.Panic(h.ctx, "parsing element fill options: %w", err) +// Fill types the given value into the element. +func (h *ElementHandle) Fill(value string, opts goja.Value) error { + popts := NewElementHandleBaseOptions(h.defaultTimeout()) + if err := popts.Parse(h.ctx, opts); err != nil { + return fmt.Errorf("parsing element fill options: %w", err) } - fn := func(apiCtx context.Context, handle *ElementHandle) (any, error) { + + fill := func(apiCtx context.Context, handle *ElementHandle) (any, error) { return nil, handle.fill(apiCtx, value) } - actFn := h.newAction([]string{"visible", "enabled", "editable"}, - fn, actionOpts.Force, actionOpts.NoWaitAfter, actionOpts.Timeout) - _, err := call(h.ctx, actFn, actionOpts.Timeout) - if err != nil { - k6ext.Panic(h.ctx, "handling element fill action: %w", err) + fillAction := h.newAction( + []string{"visible", "enabled", "editable"}, + fill, popts.Force, popts.NoWaitAfter, popts.Timeout, + ) + if _, err := call(h.ctx, fillAction, popts.Timeout); err != nil { + return fmt.Errorf("filling element: %w", err) } + applySlowMo(h.ctx) + + return nil } // Focus scrolls element into view and focuses the element. diff --git a/tests/page_test.go b/tests/page_test.go index cca51c328..81128e48b 100644 --- a/tests/page_test.go +++ b/tests/page_test.go @@ -495,7 +495,7 @@ func TestPageInputSpecialCharacters(t *testing.T) { `¯\_(ツ)_/¯`, } for _, want := range wants { - el.Fill("", nil) + require.NoError(t, el.Fill("", nil)) el.Type(want, nil) got := el.InputValue(nil) From 65d5eb753d3c68cd2b99682fba9f0fb10dd36db1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C4=B0nan=C3=A7=20G=C3=BCm=C3=BC=C5=9F?= Date: Wed, 15 May 2024 14:24:08 +0300 Subject: [PATCH 06/32] Refactor ElementHandle.DispatchEvent to return err --- browser/mapping_test.go | 2 +- common/element_handle.go | 9 +++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/browser/mapping_test.go b/browser/mapping_test.go index f8270e2bc..dbcce65ce 100644 --- a/browser/mapping_test.go +++ b/browser/mapping_test.go @@ -427,7 +427,7 @@ type elementHandleAPI interface { Click(opts goja.Value) error ContentFrame() (*common.Frame, error) Dblclick(opts goja.Value) error - DispatchEvent(typ string, props goja.Value) + DispatchEvent(typ string, props goja.Value) error Fill(value string, opts goja.Value) error Focus() GetAttribute(name string) goja.Value diff --git a/common/element_handle.go b/common/element_handle.go index 792fd1497..ee5da4b06 100644 --- a/common/element_handle.go +++ b/common/element_handle.go @@ -772,13 +772,14 @@ func (h *ElementHandle) Dblclick(opts goja.Value) error { // DispatchEvent dispatches a DOM event to the element. func (h *ElementHandle) DispatchEvent(typ string, eventInit any) error { - fn := func(apiCtx context.Context, handle *ElementHandle) (any, error) { + dispatchEvent := func(apiCtx context.Context, handle *ElementHandle) (any, error) { return handle.dispatchEvent(apiCtx, typ, eventInit) } opts := NewElementHandleBaseOptions(h.defaultTimeout()) - actFn := h.newAction([]string{}, fn, opts.Force, opts.NoWaitAfter, opts.Timeout) - _, err := call(h.ctx, actFn, opts.Timeout) - if err != nil { + dispatchEventAction := h.newAction( + []string{}, dispatchEvent, opts.Force, opts.NoWaitAfter, opts.Timeout, + ) + if _, err := call(h.ctx, dispatchEventAction, opts.Timeout); err != nil { return fmt.Errorf("dispatching element event %q: %w", typ, err) } From 3135ca90c26d63aaae2927f489a9cf6ddaf590e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C4=B0nan=C3=A7=20G=C3=BCm=C3=BC=C5=9F?= Date: Wed, 15 May 2024 14:26:23 +0300 Subject: [PATCH 07/32] Refactor ElementHandle.Focus to return err --- browser/mapping_test.go | 2 +- common/element_handle.go | 16 ++++++++++------ 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/browser/mapping_test.go b/browser/mapping_test.go index dbcce65ce..e5d1bafc0 100644 --- a/browser/mapping_test.go +++ b/browser/mapping_test.go @@ -429,7 +429,7 @@ type elementHandleAPI interface { Dblclick(opts goja.Value) error DispatchEvent(typ string, props goja.Value) error Fill(value string, opts goja.Value) error - Focus() + Focus() error GetAttribute(name string) goja.Value Hover(opts goja.Value) InnerHTML() string diff --git a/common/element_handle.go b/common/element_handle.go index ee5da4b06..484abfdb8 100644 --- a/common/element_handle.go +++ b/common/element_handle.go @@ -812,17 +812,21 @@ func (h *ElementHandle) Fill(value string, opts goja.Value) error { } // Focus scrolls element into view and focuses the element. -func (h *ElementHandle) Focus() { - fn := func(apiCtx context.Context, handle *ElementHandle) (any, error) { +func (h *ElementHandle) Focus() error { + focus := func(apiCtx context.Context, handle *ElementHandle) (any, error) { return nil, handle.focus(apiCtx, false) } opts := NewElementHandleBaseOptions(h.defaultTimeout()) - actFn := h.newAction([]string{}, fn, opts.Force, opts.NoWaitAfter, opts.Timeout) - _, err := call(h.ctx, actFn, opts.Timeout) - if err != nil { - k6ext.Panic(h.ctx, "focusing on element: %w", err) + focusAction := h.newAction( + []string{}, focus, opts.Force, opts.NoWaitAfter, opts.Timeout, + ) + if _, err := call(h.ctx, focusAction, opts.Timeout); err != nil { + return fmt.Errorf("focusing on element: %w", err) } + applySlowMo(h.ctx) + + return nil } // GetAttribute retrieves the value of specified element attribute. From 5be5fcd41e879c6a8ff1e577cfb0a22523613eb3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C4=B0nan=C3=A7=20G=C3=BCm=C3=BC=C5=9F?= Date: Wed, 15 May 2024 14:28:15 +0300 Subject: [PATCH 08/32] Refactor ElementHandle.GetAttribute to return err --- browser/mapping_test.go | 2 +- common/element_handle.go | 18 ++++++++++-------- tests/element_handle_test.go | 3 ++- 3 files changed, 13 insertions(+), 10 deletions(-) diff --git a/browser/mapping_test.go b/browser/mapping_test.go index e5d1bafc0..84548558e 100644 --- a/browser/mapping_test.go +++ b/browser/mapping_test.go @@ -430,7 +430,7 @@ type elementHandleAPI interface { DispatchEvent(typ string, props goja.Value) error Fill(value string, opts goja.Value) error Focus() error - GetAttribute(name string) goja.Value + GetAttribute(name string) (any, error) Hover(opts goja.Value) InnerHTML() string InnerText() string diff --git a/common/element_handle.go b/common/element_handle.go index 484abfdb8..61d3e0213 100644 --- a/common/element_handle.go +++ b/common/element_handle.go @@ -830,21 +830,23 @@ func (h *ElementHandle) Focus() error { } // GetAttribute retrieves the value of specified element attribute. -func (h *ElementHandle) GetAttribute(name string) any { - fn := func(apiCtx context.Context, handle *ElementHandle) (any, error) { +func (h *ElementHandle) GetAttribute(name string) (any, error) { + getAttribute := func(apiCtx context.Context, handle *ElementHandle) (any, error) { return handle.getAttribute(apiCtx, name) } opts := NewElementHandleBaseOptions(h.defaultTimeout()) - actFn := h.newAction([]string{}, fn, opts.Force, opts.NoWaitAfter, opts.Timeout) - v, err := call(h.ctx, actFn, opts.Timeout) + getAttributeAction := h.newAction( + []string{}, getAttribute, opts.Force, opts.NoWaitAfter, opts.Timeout, + ) + + v, err := call(h.ctx, getAttributeAction, opts.Timeout) if err != nil { - k6ext.Panic(h.ctx, "getting attribute of %q: %q", name, err) + return nil, fmt.Errorf("getting attribute %q of element: %w", name, err) } - applySlowMo(h.ctx) - // TODO: return any with error + applySlowMo(h.ctx) - return v + return v, nil } // Hover scrolls element into view and hovers over its center point. diff --git a/tests/element_handle_test.go b/tests/element_handle_test.go index c5bd5cb69..85f00708b 100644 --- a/tests/element_handle_test.go +++ b/tests/element_handle_test.go @@ -245,7 +245,8 @@ func TestElementHandleGetAttribute(t *testing.T) { el, err := p.Query("#dark-mode-toggle-X") require.NoError(t, err) - got := el.GetAttribute("href") + got, err := el.GetAttribute("href") + require.NoError(t, err) assert.Equal(t, want, got) } From f362eeacf77896bb9c38befa26137b38cc245ba1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C4=B0nan=C3=A7=20G=C3=BCm=C3=BC=C5=9F?= Date: Wed, 15 May 2024 14:34:45 +0300 Subject: [PATCH 09/32] Refactor ElementHandle.Hover to return err --- browser/mapping_test.go | 2 +- common/element_handle.go | 21 ++++++++++++--------- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/browser/mapping_test.go b/browser/mapping_test.go index 84548558e..827477498 100644 --- a/browser/mapping_test.go +++ b/browser/mapping_test.go @@ -431,7 +431,7 @@ type elementHandleAPI interface { Fill(value string, opts goja.Value) error Focus() error GetAttribute(name string) (any, error) - Hover(opts goja.Value) + Hover(opts goja.Value) error InnerHTML() string InnerText() string InputValue(opts goja.Value) string diff --git a/common/element_handle.go b/common/element_handle.go index 61d3e0213..471d59073 100644 --- a/common/element_handle.go +++ b/common/element_handle.go @@ -850,20 +850,23 @@ func (h *ElementHandle) GetAttribute(name string) (any, error) { } // Hover scrolls element into view and hovers over its center point. -func (h *ElementHandle) Hover(opts goja.Value) { - actionOpts := NewElementHandleHoverOptions(h.defaultTimeout()) - if err := actionOpts.Parse(h.ctx, opts); err != nil { - k6ext.Panic(h.ctx, "parsing element hover options: %w", err) +func (h *ElementHandle) Hover(opts goja.Value) error { + aopts := NewElementHandleHoverOptions(h.defaultTimeout()) + if err := aopts.Parse(h.ctx, opts); err != nil { + return fmt.Errorf("parsing element hover options: %w", err) } - fn := func(apiCtx context.Context, handle *ElementHandle, p *Position) (any, error) { + + hover := func(apiCtx context.Context, handle *ElementHandle, p *Position) (any, error) { return nil, handle.hover(apiCtx, p) } - pointerFn := h.newPointerAction(fn, &actionOpts.ElementHandleBasePointerOptions) - _, err := call(h.ctx, pointerFn, actionOpts.Timeout) - if err != nil { - k6ext.Panic(h.ctx, "hovering on element: %w", err) + hoverAction := h.newPointerAction(hover, &aopts.ElementHandleBasePointerOptions) + if _, err := call(h.ctx, hoverAction, aopts.Timeout); err != nil { + return fmt.Errorf("hovering on element: %w", err) } + applySlowMo(h.ctx) + + return nil } // InnerHTML returns the inner HTML of the element. From 6a32c2442cb00dd5674f5999fa5313e78858ac38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C4=B0nan=C3=A7=20G=C3=BCm=C3=BC=C5=9F?= Date: Wed, 15 May 2024 14:37:04 +0300 Subject: [PATCH 10/32] Refactor ElementHandle.InnerHTML to return err --- browser/mapping_test.go | 2 +- common/element_handle.go | 20 +++++++++++++------- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/browser/mapping_test.go b/browser/mapping_test.go index 827477498..0077c88f7 100644 --- a/browser/mapping_test.go +++ b/browser/mapping_test.go @@ -432,7 +432,7 @@ type elementHandleAPI interface { Focus() error GetAttribute(name string) (any, error) Hover(opts goja.Value) error - InnerHTML() string + InnerHTML() (string, error) InnerText() string InputValue(opts goja.Value) string IsChecked() bool diff --git a/common/element_handle.go b/common/element_handle.go index 471d59073..80ddb21ae 100644 --- a/common/element_handle.go +++ b/common/element_handle.go @@ -870,21 +870,27 @@ func (h *ElementHandle) Hover(opts goja.Value) error { } // InnerHTML returns the inner HTML of the element. -func (h *ElementHandle) InnerHTML() string { - fn := func(apiCtx context.Context, handle *ElementHandle) (any, error) { +func (h *ElementHandle) InnerHTML() (string, error) { + innerHTML := func(apiCtx context.Context, handle *ElementHandle) (any, error) { return handle.innerHTML(apiCtx) } opts := NewElementHandleBaseOptions(h.defaultTimeout()) - actFn := h.newAction([]string{}, fn, opts.Force, opts.NoWaitAfter, opts.Timeout) - v, err := call(h.ctx, actFn, opts.Timeout) + innerHTMLAction := h.newAction( + []string{}, innerHTML, opts.Force, opts.NoWaitAfter, opts.Timeout, + ) + v, err := call(h.ctx, innerHTMLAction, opts.Timeout) if err != nil { - k6ext.Panic(h.ctx, "getting element's inner HTML: %w", err) + return "", fmt.Errorf("getting element's inner HTML: %w", err) } + applySlowMo(h.ctx) - // TODO: handle error + s, ok := v.(string) + if !ok { + return "", fmt.Errorf("unexpected type %T (expecting string)", v) + } - return v.(string) //nolint:forcetypeassert + return s, nil } // InnerText returns the inner text of the element. From a5ca7d23ad50ad76d872825ee53c17d571b3e07f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C4=B0nan=C3=A7=20G=C3=BCm=C3=BC=C5=9F?= Date: Wed, 15 May 2024 14:39:03 +0300 Subject: [PATCH 11/32] Refactor ElementHandle.InnerText to return err --- browser/mapping_test.go | 2 +- common/element_handle.go | 20 +++++++++++++------- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/browser/mapping_test.go b/browser/mapping_test.go index 0077c88f7..f546e74a0 100644 --- a/browser/mapping_test.go +++ b/browser/mapping_test.go @@ -433,7 +433,7 @@ type elementHandleAPI interface { GetAttribute(name string) (any, error) Hover(opts goja.Value) error InnerHTML() (string, error) - InnerText() string + InnerText() (string, error) InputValue(opts goja.Value) string IsChecked() bool IsDisabled() bool diff --git a/common/element_handle.go b/common/element_handle.go index 80ddb21ae..01406333e 100644 --- a/common/element_handle.go +++ b/common/element_handle.go @@ -894,21 +894,27 @@ func (h *ElementHandle) InnerHTML() (string, error) { } // InnerText returns the inner text of the element. -func (h *ElementHandle) InnerText() string { - fn := func(apiCtx context.Context, handle *ElementHandle) (any, error) { +func (h *ElementHandle) InnerText() (string, error) { + innerText := func(apiCtx context.Context, handle *ElementHandle) (any, error) { return handle.innerText(apiCtx) } opts := NewElementHandleBaseOptions(h.defaultTimeout()) - actFn := h.newAction([]string{}, fn, opts.Force, opts.NoWaitAfter, opts.Timeout) - v, err := call(h.ctx, actFn, opts.Timeout) + innerTextAction := h.newAction( + []string{}, innerText, opts.Force, opts.NoWaitAfter, opts.Timeout.Abs(), + ) + v, err := call(h.ctx, innerTextAction, opts.Timeout) if err != nil { - k6ext.Panic(h.ctx, "getting element's inner text: %w", err) + return "", fmt.Errorf("getting element's inner text: %w", err) } + applySlowMo(h.ctx) - // TODO: handle error + s, ok := v.(string) + if !ok { + return "", fmt.Errorf("unexpected type %T (expecting string)", v) + } - return v.(string) //nolint:forcetypeassert + return s, nil } func (h *ElementHandle) InputValue(opts goja.Value) string { From 6982dad02f5f924af5010fac5387b481e3f65251 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C4=B0nan=C3=A7=20G=C3=BCm=C3=BC=C5=9F?= Date: Wed, 15 May 2024 14:54:00 +0300 Subject: [PATCH 12/32] Refactor ElementHandle.InputValue to return err --- browser/mapping_test.go | 2 +- common/element_handle.go | 26 ++++++++++++--------- tests/element_handle_test.go | 13 +++++++---- tests/keyboard_test.go | 44 +++++++++++++++++++++++++++--------- tests/page_test.go | 3 ++- 5 files changed, 60 insertions(+), 28 deletions(-) diff --git a/browser/mapping_test.go b/browser/mapping_test.go index f546e74a0..5e42306c3 100644 --- a/browser/mapping_test.go +++ b/browser/mapping_test.go @@ -434,7 +434,7 @@ type elementHandleAPI interface { Hover(opts goja.Value) error InnerHTML() (string, error) InnerText() (string, error) - InputValue(opts goja.Value) string + InputValue(opts goja.Value) (string, error) IsChecked() bool IsDisabled() bool IsEditable() bool diff --git a/common/element_handle.go b/common/element_handle.go index 01406333e..f558ae87c 100644 --- a/common/element_handle.go +++ b/common/element_handle.go @@ -917,24 +917,28 @@ func (h *ElementHandle) InnerText() (string, error) { return s, nil } -func (h *ElementHandle) InputValue(opts goja.Value) string { - actionOpts := NewElementHandleBaseOptions(h.defaultTimeout()) - if err := actionOpts.Parse(h.ctx, opts); err != nil { - k6ext.Panic(h.ctx, "parsing element input value options: %w", err) +// InputValue returns the value of the input element. +func (h *ElementHandle) InputValue(opts goja.Value) (string, error) { + aopts := NewElementHandleBaseOptions(h.defaultTimeout()) + if err := aopts.Parse(h.ctx, opts); err != nil { + return "", fmt.Errorf("parsing element input value options: %w", err) } - fn := func(apiCtx context.Context, handle *ElementHandle) (any, error) { + + inputValue := func(apiCtx context.Context, handle *ElementHandle) (any, error) { return handle.inputValue(apiCtx) } - actFn := h.newAction([]string{}, fn, actionOpts.Force, actionOpts.NoWaitAfter, actionOpts.Timeout) - v, err := call(h.ctx, actFn, actionOpts.Timeout) + inputValueAction := h.newAction([]string{}, inputValue, aopts.Force, aopts.NoWaitAfter, aopts.Timeout) + v, err := call(h.ctx, inputValueAction, aopts.Timeout) if err != nil { - k6ext.Panic(h.ctx, "getting element's input value: %w", err) + return "", fmt.Errorf("getting element's input value: %w", err) } - applySlowMo(h.ctx) - // TODO: return error + s, ok := v.(string) + if !ok { + return "", fmt.Errorf("unexpected type %T (expecting string)", v) + } - return v.(string) //nolint:forcetypeassert + return s, nil } // IsChecked checks if a checkbox or radio is checked. diff --git a/tests/element_handle_test.go b/tests/element_handle_test.go index 85f00708b..9fbcace4f 100644 --- a/tests/element_handle_test.go +++ b/tests/element_handle_test.go @@ -264,21 +264,24 @@ func TestElementHandleInputValue(t *testing.T) { element, err := p.Query("input") require.NoError(t, err) - value := element.InputValue(nil) + value, err := element.InputValue(nil) + require.NoError(t, err) element.Dispose() assert.Equal(t, value, "hello1", `expected input value "hello1", got %q`, value) element, err = p.Query("select") require.NoError(t, err) - value = element.InputValue(nil) + value, err = element.InputValue(nil) + require.NoError(t, err) element.Dispose() assert.Equal(t, value, "hello2", `expected input value "hello2", got %q`, value) element, err = p.Query("textarea") require.NoError(t, err) - value = element.InputValue(nil) + value, err = element.InputValue(nil) + require.NoError(t, err) element.Dispose() assert.Equal(t, value, "hello3", `expected input value "hello3", got %q`, value) } @@ -452,7 +455,9 @@ func TestElementHandlePress(t *testing.T) { el.Press("KeyB", nil) el.Press("Shift+KeyC", nil) - require.Equal(t, "AbC", el.InputValue(nil)) + v, err := el.InputValue(nil) + require.NoError(t, err) + require.Equal(t, "AbC", v) } func TestElementHandleQuery(t *testing.T) { diff --git a/tests/keyboard_test.go b/tests/keyboard_test.go index dc7fa4dcd..a8b5ee74b 100644 --- a/tests/keyboard_test.go +++ b/tests/keyboard_test.go @@ -42,10 +42,14 @@ func TestKeyboardPress(t *testing.T) { p.Focus("input", nil) require.NoError(t, kb.Type("Hello World!", nil)) - require.Equal(t, "Hello World!", el.InputValue(nil)) + v, err := el.InputValue(nil) + require.NoError(t, err) + require.Equal(t, "Hello World!", v) require.NoError(t, kb.Press("Backspace", nil)) - assert.Equal(t, "Hello World", el.InputValue(nil)) + v, err = el.InputValue(nil) + require.NoError(t, err) + assert.Equal(t, "Hello World", v) }) t.Run("combo", func(t *testing.T) { @@ -72,7 +76,9 @@ func TestKeyboardPress(t *testing.T) { require.NoError(t, kb.Press("Control+J", nil)) require.NoError(t, kb.Press("Control+k", nil)) - require.Equal(t, "+=@6AbC", el.InputValue(nil)) + v, err := el.InputValue(nil) + require.NoError(t, err) + require.Equal(t, "+=@6AbC", v) }) t.Run("meta", func(t *testing.T) { @@ -91,7 +97,9 @@ func TestKeyboardPress(t *testing.T) { require.NoError(t, kb.Press("Shift+b", nil)) require.NoError(t, kb.Press("Shift+C", nil)) - require.Equal(t, "AbC", el.InputValue(nil)) + v, err := el.InputValue(nil) + require.NoError(t, err) + require.Equal(t, "AbC", v) metaKey := "Control" if runtime.GOOS == "darwin" { @@ -99,7 +107,9 @@ func TestKeyboardPress(t *testing.T) { } require.NoError(t, kb.Press(metaKey+"+A", nil)) require.NoError(t, kb.Press("Delete", nil)) - assert.Equal(t, "", el.InputValue(nil)) + v, err = el.InputValue(nil) + require.NoError(t, err) + assert.Equal(t, "", v) }) t.Run("type does not split on +", func(t *testing.T) { @@ -115,7 +125,9 @@ func TestKeyboardPress(t *testing.T) { p.Focus("textarea", nil) require.NoError(t, kb.Type("L+m+KeyN", nil)) - assert.Equal(t, "L+m+KeyN", el.InputValue(nil)) + v, err := el.InputValue(nil) + require.NoError(t, err) + assert.Equal(t, "L+m+KeyN", v) }) t.Run("capitalization", func(t *testing.T) { @@ -143,7 +155,9 @@ func TestKeyboardPress(t *testing.T) { require.NoError(t, kb.Up("KeyH")) require.NoError(t, kb.Up("Shift")) - assert.Equal(t, "CdefGH", el.InputValue(nil)) + v, err := el.InputValue(nil) + require.NoError(t, err) + assert.Equal(t, "CdefGH", v) }) t.Run("type not affected by shift", func(t *testing.T) { @@ -162,7 +176,9 @@ func TestKeyboardPress(t *testing.T) { require.NoError(t, kb.Type("oPqR", nil)) require.NoError(t, kb.Up("Shift")) - assert.Equal(t, "oPqR", el.InputValue(nil)) + v, err := el.InputValue(nil) + require.NoError(t, err) + assert.Equal(t, "oPqR", v) }) t.Run("newline", func(t *testing.T) { @@ -181,7 +197,9 @@ func TestKeyboardPress(t *testing.T) { require.NoError(t, kb.Press("Enter", nil)) require.NoError(t, kb.Press("Enter", nil)) require.NoError(t, kb.Type("World!", nil)) - assert.Equal(t, "Hello\n\nWorld!", el.InputValue(nil)) + v, err := el.InputValue(nil) + require.NoError(t, err) + assert.Equal(t, "Hello\n\nWorld!", v) }) // Replicates the test from https://playwright.dev/docs/api/class-keyboard @@ -198,7 +216,9 @@ func TestKeyboardPress(t *testing.T) { p.Focus("input", nil) require.NoError(t, kb.Type("Hello World!", nil)) - require.Equal(t, "Hello World!", el.InputValue(nil)) + v, err := el.InputValue(nil) + require.NoError(t, err) + require.Equal(t, "Hello World!", v) require.NoError(t, kb.Press("ArrowLeft", nil)) // Should hold the key until Up() is called. @@ -211,6 +231,8 @@ func TestKeyboardPress(t *testing.T) { // Should delete the selection. require.NoError(t, kb.Press("Backspace", nil)) - assert.Equal(t, "Hello!", el.InputValue(nil)) + require.NoError(t, err) + require.NoError(t, err) + assert.Equal(t, "Hello World!", v) }) } diff --git a/tests/page_test.go b/tests/page_test.go index 81128e48b..729615599 100644 --- a/tests/page_test.go +++ b/tests/page_test.go @@ -498,7 +498,8 @@ func TestPageInputSpecialCharacters(t *testing.T) { require.NoError(t, el.Fill("", nil)) el.Type(want, nil) - got := el.InputValue(nil) + got, err := el.InputValue(nil) + require.NoError(t, err) assert.Equal(t, want, got) } } From 4c005983fb87d1b7ce8becf2aa801bf7f7f5bbe6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C4=B0nan=C3=A7=20G=C3=BCm=C3=BC=C5=9F?= Date: Wed, 15 May 2024 14:55:22 +0300 Subject: [PATCH 13/32] Fix forgotten keyboard tests for error checks It's not related to this PR, but I wanted to tackle them here for convenience. Apologies for the inconvinience. --- tests/keyboard_test.go | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/tests/keyboard_test.go b/tests/keyboard_test.go index a8b5ee74b..e68b17e6c 100644 --- a/tests/keyboard_test.go +++ b/tests/keyboard_test.go @@ -5,10 +5,10 @@ import ( "runtime" "testing" - "github.com/grafana/xk6-browser/keyboardlayout" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/grafana/xk6-browser/keyboardlayout" ) func TestKeyboardPress(t *testing.T) { @@ -22,11 +22,9 @@ func TestKeyboardPress(t *testing.T) { kb := p.GetKeyboard() layout := keyboardlayout.GetKeyboardLayout("us") - assert.NotPanics(t, func() { - for k := range layout.Keys { - require.NoError(t, kb.Press(string(k), nil)) - } - }) + for k := range layout.Keys { + assert.NoError(t, kb.Press(string(k), nil)) + } }) t.Run("backspace", func(t *testing.T) { @@ -227,7 +225,7 @@ func TestKeyboardPress(t *testing.T) { require.NoError(t, kb.Press("ArrowLeft", nil)) } // Should release the key but the selection should remain active. - kb.Up("Shift") + require.NoError(t, kb.Up("Shift")) // Should delete the selection. require.NoError(t, kb.Press("Backspace", nil)) From 795a56cbd23dffb91329b49e4afd95ca63058c64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C4=B0nan=C3=A7=20G=C3=BCm=C3=BC=C5=9F?= Date: Wed, 15 May 2024 14:59:58 +0300 Subject: [PATCH 14/32] Refactor ElementHandle.IsChecked to return err --- browser/mapping_test.go | 2 +- common/element_handle.go | 12 +++++++----- tests/element_handle_test.go | 8 ++++++-- 3 files changed, 14 insertions(+), 8 deletions(-) diff --git a/browser/mapping_test.go b/browser/mapping_test.go index 5e42306c3..83d272f83 100644 --- a/browser/mapping_test.go +++ b/browser/mapping_test.go @@ -435,7 +435,7 @@ type elementHandleAPI interface { InnerHTML() (string, error) InnerText() (string, error) InputValue(opts goja.Value) (string, error) - IsChecked() bool + IsChecked() (bool, error) IsDisabled() bool IsEditable() bool IsEnabled() bool diff --git a/common/element_handle.go b/common/element_handle.go index f558ae87c..60f3f0f5b 100644 --- a/common/element_handle.go +++ b/common/element_handle.go @@ -942,12 +942,14 @@ func (h *ElementHandle) InputValue(opts goja.Value) (string, error) { } // IsChecked checks if a checkbox or radio is checked. -func (h *ElementHandle) IsChecked() bool { - result, err := h.isChecked(h.ctx, 0) - if err != nil && !errors.Is(err, ErrTimedOut) { // We don't care anout timeout errors here! - k6ext.Panic(h.ctx, "checking element is checked: %w", err) +func (h *ElementHandle) IsChecked() (bool, error) { + ok, err := h.isChecked(h.ctx, 0) + // We don't care about timeout errors here! + if err != nil && !errors.Is(err, ErrTimedOut) { + return false, fmt.Errorf("checking element is checked: %w", err) } - return result + + return ok, nil } // IsDisabled checks if the element is disabled. diff --git a/tests/element_handle_test.go b/tests/element_handle_test.go index 9fbcace4f..d78e637db 100644 --- a/tests/element_handle_test.go +++ b/tests/element_handle_test.go @@ -295,13 +295,17 @@ func TestElementHandleIsChecked(t *testing.T) { element, err := p.Query("input") require.NoError(t, err) - assert.True(t, element.IsChecked(), "expected checkbox to be checked") + checked, err := element.IsChecked() + require.NoError(t, err) + assert.True(t, checked, "expected checkbox to be checked") element.Dispose() p.SetContent(``, nil) element, err = p.Query("input") require.NoError(t, err) - assert.False(t, element.IsChecked(), "expected checkbox to be unchecked") + checked, err = element.IsChecked() + require.NoError(t, err) + assert.False(t, checked, "expected checkbox to be unchecked") element.Dispose() } From e28d48a070b06f0a0f97af362ef7ea5df31e84c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C4=B0nan=C3=A7=20G=C3=BCm=C3=BC=C5=9F?= Date: Wed, 15 May 2024 15:00:50 +0300 Subject: [PATCH 15/32] Refactor ElementHandle.IsDisabled to return err --- browser/mapping_test.go | 2 +- common/element_handle.go | 12 +++++++----- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/browser/mapping_test.go b/browser/mapping_test.go index 83d272f83..35f48ad2c 100644 --- a/browser/mapping_test.go +++ b/browser/mapping_test.go @@ -436,7 +436,7 @@ type elementHandleAPI interface { InnerText() (string, error) InputValue(opts goja.Value) (string, error) IsChecked() (bool, error) - IsDisabled() bool + IsDisabled() (bool, error) IsEditable() bool IsEnabled() bool IsHidden() bool diff --git a/common/element_handle.go b/common/element_handle.go index 60f3f0f5b..961ff643c 100644 --- a/common/element_handle.go +++ b/common/element_handle.go @@ -953,12 +953,14 @@ func (h *ElementHandle) IsChecked() (bool, error) { } // IsDisabled checks if the element is disabled. -func (h *ElementHandle) IsDisabled() bool { - result, err := h.isDisabled(h.ctx, 0) - if err != nil && !errors.Is(err, ErrTimedOut) { // We don't care anout timeout errors here! - k6ext.Panic(h.ctx, "checking element is disabled: %w", err) +func (h *ElementHandle) IsDisabled() (bool, error) { + ok, err := h.isDisabled(h.ctx, 0) + // We don't care anout timeout errors here! + if err != nil && !errors.Is(err, ErrTimedOut) { + return false, fmt.Errorf("checking element is disabled: %w", err) } - return result + + return ok, nil } // IsEditable checks if the element is editable. From c4d6941e7d1b5839cc4c5410575ae090b772eea7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C4=B0nan=C3=A7=20G=C3=BCm=C3=BC=C5=9F?= Date: Wed, 15 May 2024 15:01:29 +0300 Subject: [PATCH 16/32] Refactor ElementHandle.IsEditable to return err --- browser/mapping_test.go | 2 +- common/element_handle.go | 12 +++++++----- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/browser/mapping_test.go b/browser/mapping_test.go index 35f48ad2c..e45bcf2ec 100644 --- a/browser/mapping_test.go +++ b/browser/mapping_test.go @@ -437,7 +437,7 @@ type elementHandleAPI interface { InputValue(opts goja.Value) (string, error) IsChecked() (bool, error) IsDisabled() (bool, error) - IsEditable() bool + IsEditable() (bool, error) IsEnabled() bool IsHidden() bool IsVisible() bool diff --git a/common/element_handle.go b/common/element_handle.go index 961ff643c..ff8f1f28a 100644 --- a/common/element_handle.go +++ b/common/element_handle.go @@ -964,12 +964,14 @@ func (h *ElementHandle) IsDisabled() (bool, error) { } // IsEditable checks if the element is editable. -func (h *ElementHandle) IsEditable() bool { - result, err := h.isEditable(h.ctx, 0) - if err != nil && !errors.Is(err, ErrTimedOut) { // We don't care anout timeout errors here! - k6ext.Panic(h.ctx, "checking element is editable: %w", err) +func (h *ElementHandle) IsEditable() (bool, error) { + ok, err := h.isEditable(h.ctx, 0) + // We don't care anout timeout errors here! + if err != nil && !errors.Is(err, ErrTimedOut) { + return false, fmt.Errorf("checking element is editable: %w", err) } - return result + + return ok, nil } // IsEnabled checks if the element is enabled. From e914ee4d661ae8d8c4a1f59ff0acb2de164f4c52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C4=B0nan=C3=A7=20G=C3=BCm=C3=BC=C5=9F?= Date: Wed, 15 May 2024 15:01:59 +0300 Subject: [PATCH 17/32] Refactor ElementHandle.IsEnabled to return err --- browser/mapping_test.go | 2 +- common/element_handle.go | 12 +++++++----- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/browser/mapping_test.go b/browser/mapping_test.go index e45bcf2ec..bec1d6f35 100644 --- a/browser/mapping_test.go +++ b/browser/mapping_test.go @@ -438,7 +438,7 @@ type elementHandleAPI interface { IsChecked() (bool, error) IsDisabled() (bool, error) IsEditable() (bool, error) - IsEnabled() bool + IsEnabled() (bool, error) IsHidden() bool IsVisible() bool OwnerFrame() (*common.Frame, error) diff --git a/common/element_handle.go b/common/element_handle.go index ff8f1f28a..71f8d5cd0 100644 --- a/common/element_handle.go +++ b/common/element_handle.go @@ -975,12 +975,14 @@ func (h *ElementHandle) IsEditable() (bool, error) { } // IsEnabled checks if the element is enabled. -func (h *ElementHandle) IsEnabled() bool { - result, err := h.isEnabled(h.ctx, 0) - if err != nil && !errors.Is(err, ErrTimedOut) { // We don't care anout timeout errors here! - k6ext.Panic(h.ctx, "checking element is enabled: %w", err) +func (h *ElementHandle) IsEnabled() (bool, error) { + ok, err := h.isEnabled(h.ctx, 0) + // We don't care anout timeout errors here! + if err != nil && !errors.Is(err, ErrTimedOut) { + return false, fmt.Errorf("checking element is enabled: %w", err) } - return result + + return ok, nil } // IsHidden checks if the element is hidden. From db1849e1c5806cbfedda01edb383d29b7da15361 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C4=B0nan=C3=A7=20G=C3=BCm=C3=BC=C5=9F?= Date: Wed, 15 May 2024 15:02:49 +0300 Subject: [PATCH 18/32] Refactor ElementHandle.IsHidden to return err --- browser/mapping_test.go | 2 +- common/element_handle.go | 12 +++++++----- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/browser/mapping_test.go b/browser/mapping_test.go index bec1d6f35..12e51afb0 100644 --- a/browser/mapping_test.go +++ b/browser/mapping_test.go @@ -439,7 +439,7 @@ type elementHandleAPI interface { IsDisabled() (bool, error) IsEditable() (bool, error) IsEnabled() (bool, error) - IsHidden() bool + IsHidden() (bool, error) IsVisible() bool OwnerFrame() (*common.Frame, error) Press(key string, opts goja.Value) diff --git a/common/element_handle.go b/common/element_handle.go index 71f8d5cd0..565a37e37 100644 --- a/common/element_handle.go +++ b/common/element_handle.go @@ -986,12 +986,14 @@ func (h *ElementHandle) IsEnabled() (bool, error) { } // IsHidden checks if the element is hidden. -func (h *ElementHandle) IsHidden() bool { - result, err := h.isHidden(h.ctx) - if err != nil && !errors.Is(err, ErrTimedOut) { // We don't care anout timeout errors here! - k6ext.Panic(h.ctx, "checking element is hidden: %w", err) +func (h *ElementHandle) IsHidden() (bool, error) { + ok, err := h.isHidden(h.ctx) + // We don't care anout timeout errors here! + if err != nil && !errors.Is(err, ErrTimedOut) { + return false, fmt.Errorf("checking element is hidden: %w", err) } - return result + + return ok, nil } // IsVisible checks if the element is visible. From 2ba400d2945398bad6340324e51766be725ffc30 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C4=B0nan=C3=A7=20G=C3=BCm=C3=BC=C5=9F?= Date: Wed, 15 May 2024 15:03:24 +0300 Subject: [PATCH 19/32] Refactor ElementHandle.IsVisible to return err --- browser/mapping_test.go | 2 +- common/element_handle.go | 12 +++++++----- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/browser/mapping_test.go b/browser/mapping_test.go index 12e51afb0..543af6ee1 100644 --- a/browser/mapping_test.go +++ b/browser/mapping_test.go @@ -440,7 +440,7 @@ type elementHandleAPI interface { IsEditable() (bool, error) IsEnabled() (bool, error) IsHidden() (bool, error) - IsVisible() bool + IsVisible() (bool, error) OwnerFrame() (*common.Frame, error) Press(key string, opts goja.Value) Query(selector string) (*common.ElementHandle, error) diff --git a/common/element_handle.go b/common/element_handle.go index 565a37e37..5d72e51ca 100644 --- a/common/element_handle.go +++ b/common/element_handle.go @@ -997,12 +997,14 @@ func (h *ElementHandle) IsHidden() (bool, error) { } // IsVisible checks if the element is visible. -func (h *ElementHandle) IsVisible() bool { - result, err := h.isVisible(h.ctx) - if err != nil && !errors.Is(err, ErrTimedOut) { // We don't care anout timeout errors here! - k6ext.Panic(h.ctx, "checking element is visible: %w", err) +func (h *ElementHandle) IsVisible() (bool, error) { + ok, err := h.isVisible(h.ctx) + // We don't care anout timeout errors here! + if err != nil && !errors.Is(err, ErrTimedOut) { + return false, fmt.Errorf("checking element is visible: %w", err) } - return result + + return ok, nil } // OwnerFrame returns the frame containing this element. From ab0f1cca8032fd1e164089cc4d805c9c79a52e39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C4=B0nan=C3=A7=20G=C3=BCm=C3=BC=C5=9F?= Date: Wed, 15 May 2024 15:06:09 +0300 Subject: [PATCH 20/32] Refactor ElementHandle.Press to return err --- browser/mapping_test.go | 2 +- common/element_handle.go | 24 +++++++++++++++--------- tests/element_handle_test.go | 6 +++--- 3 files changed, 19 insertions(+), 13 deletions(-) diff --git a/browser/mapping_test.go b/browser/mapping_test.go index 543af6ee1..68b9ad537 100644 --- a/browser/mapping_test.go +++ b/browser/mapping_test.go @@ -442,7 +442,7 @@ type elementHandleAPI interface { IsHidden() (bool, error) IsVisible() (bool, error) OwnerFrame() (*common.Frame, error) - Press(key string, opts goja.Value) + Press(key string, opts goja.Value) error Query(selector string) (*common.ElementHandle, error) QueryAll(selector string) ([]*common.ElementHandle, error) Screenshot(opts goja.Value) goja.ArrayBuffer diff --git a/common/element_handle.go b/common/element_handle.go index 5d72e51ca..6d074c446 100644 --- a/common/element_handle.go +++ b/common/element_handle.go @@ -1052,20 +1052,26 @@ func (h *ElementHandle) OwnerFrame() (*Frame, error) { return frame, nil } -func (h *ElementHandle) Press(key string, opts goja.Value) { - parsedOpts := NewElementHandlePressOptions(h.defaultTimeout()) - if err := parsedOpts.Parse(h.ctx, opts); err != nil { - k6ext.Panic(h.ctx, "parsing press %q options: %v", key, err) +// Press scrolls element into view and presses the given keys. +func (h *ElementHandle) Press(key string, opts goja.Value) error { + popts := NewElementHandlePressOptions(h.defaultTimeout()) + if err := popts.Parse(h.ctx, opts); err != nil { + return fmt.Errorf("parsing press %q options: %w", key, err) } - fn := func(apiCtx context.Context, handle *ElementHandle) (any, error) { + + press := func(apiCtx context.Context, handle *ElementHandle) (any, error) { return nil, handle.press(apiCtx, key, NewKeyboardOptions()) } - actFn := h.newAction([]string{}, fn, false, parsedOpts.NoWaitAfter, parsedOpts.Timeout) - _, err := call(h.ctx, actFn, parsedOpts.Timeout) - if err != nil { - k6ext.Panic(h.ctx, "pressing %q: %v", key, err) + pressAction := h.newAction( + []string{}, press, false, popts.NoWaitAfter, popts.Timeout, + ) + if _, err := call(h.ctx, pressAction, popts.Timeout); err != nil { + return fmt.Errorf("pressing %q on element: %w", key, err) } + applySlowMo(h.ctx) + + return nil } // Query runs "element.querySelector" within the page. If no element matches the selector, diff --git a/tests/element_handle_test.go b/tests/element_handle_test.go index d78e637db..974e7a9d2 100644 --- a/tests/element_handle_test.go +++ b/tests/element_handle_test.go @@ -455,9 +455,9 @@ func TestElementHandlePress(t *testing.T) { el, err := p.Query("input") require.NoError(t, err) - el.Press("Shift+KeyA", nil) - el.Press("KeyB", nil) - el.Press("Shift+KeyC", nil) + require.NoError(t, el.Press("Shift+KeyA", nil)) + require.NoError(t, el.Press("KeyB", nil)) + require.NoError(t, el.Press("Shift+KeyC", nil)) v, err := el.InputValue(nil) require.NoError(t, err) From bc6adc1204a8891ec44c50b18e809c505f0a4e24 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C4=B0nan=C3=A7=20G=C3=BCm=C3=BC=C5=9F?= Date: Wed, 15 May 2024 15:08:01 +0300 Subject: [PATCH 21/32] Remove applySlowMo from QueryAll No need to apply slow motion for querying actions. --- common/element_handle.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/common/element_handle.go b/common/element_handle.go index 6d074c446..52cef66ac 100644 --- a/common/element_handle.go +++ b/common/element_handle.go @@ -1113,8 +1113,6 @@ func (h *ElementHandle) Query(selector string, strict bool) (*ElementHandle, err // QueryAll queries element subtree for matching elements. // If no element matches the selector, the return value resolves to "null". func (h *ElementHandle) QueryAll(selector string) ([]*ElementHandle, error) { - defer applySlowMo(h.ctx) - handles, err := h.queryAll(selector, h.evalWithScript) if err != nil { return nil, fmt.Errorf("querying all selector %q: %w", selector, err) From 9bd5014ba6907817f7225c325f40b57510621518 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C4=B0nan=C3=A7=20G=C3=BCm=C3=BC=C5=9F?= Date: Wed, 15 May 2024 15:09:31 +0300 Subject: [PATCH 22/32] Refactor ElementHandle.Screenshot to return err --- browser/mapping_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/browser/mapping_test.go b/browser/mapping_test.go index 68b9ad537..bd4657731 100644 --- a/browser/mapping_test.go +++ b/browser/mapping_test.go @@ -445,7 +445,7 @@ type elementHandleAPI interface { Press(key string, opts goja.Value) error Query(selector string) (*common.ElementHandle, error) QueryAll(selector string) ([]*common.ElementHandle, error) - Screenshot(opts goja.Value) goja.ArrayBuffer + Screenshot(opts goja.Value) (goja.ArrayBuffer, error) ScrollIntoViewIfNeeded(opts goja.Value) SelectOption(values goja.Value, opts goja.Value) []string SelectText(opts goja.Value) From befc6da522ec6bafe6d84b234cbb6ce6c7a0db94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C4=B0nan=C3=A7=20G=C3=BCm=C3=BC=C5=9F?= Date: Wed, 15 May 2024 15:11:26 +0300 Subject: [PATCH 23/32] Refactor ElementHandle.ScrollIntoViewIfNeeded to return err --- browser/mapping_test.go | 2 +- common/element_handle.go | 24 ++++++++++++++++-------- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/browser/mapping_test.go b/browser/mapping_test.go index bd4657731..75f485e47 100644 --- a/browser/mapping_test.go +++ b/browser/mapping_test.go @@ -446,7 +446,7 @@ type elementHandleAPI interface { Query(selector string) (*common.ElementHandle, error) QueryAll(selector string) ([]*common.ElementHandle, error) Screenshot(opts goja.Value) (goja.ArrayBuffer, error) - ScrollIntoViewIfNeeded(opts goja.Value) + ScrollIntoViewIfNeeded(opts goja.Value) error SelectOption(values goja.Value, opts goja.Value) []string SelectText(opts goja.Value) SetInputFiles(files goja.Value, opts goja.Value) diff --git a/common/element_handle.go b/common/element_handle.go index 52cef66ac..2c6605aa0 100644 --- a/common/element_handle.go +++ b/common/element_handle.go @@ -616,8 +616,10 @@ func (h *ElementHandle) typ(apiCtx context.Context, text string, opts *KeyboardO return nil } -func (h *ElementHandle) waitAndScrollIntoViewIfNeeded(apiCtx context.Context, force, noWaitAfter bool, timeout time.Duration) error { - fn := func(apiCtx context.Context, handle *ElementHandle) (any, error) { +func (h *ElementHandle) waitAndScrollIntoViewIfNeeded( + _ context.Context, force, noWaitAfter bool, timeout time.Duration, +) error { + fn := func(apiCtx context.Context, _ *ElementHandle) (any, error) { fn := ` (element) => { element.scrollIntoViewIfNeeded(true); @@ -628,6 +630,7 @@ func (h *ElementHandle) waitAndScrollIntoViewIfNeeded(apiCtx context.Context, fo forceCallable: true, returnByValue: true, } + return h.eval(apiCtx, opts, fn) } actFn := h.newAction([]string{"visible", "stable"}, fn, force, noWaitAfter, timeout) @@ -1246,16 +1249,21 @@ func (h *ElementHandle) Screenshot( return buf, err } -func (h *ElementHandle) ScrollIntoViewIfNeeded(opts goja.Value) { - actionOpts := NewElementHandleBaseOptions(h.defaultTimeout()) - if err := actionOpts.Parse(h.ctx, opts); err != nil { - k6ext.Panic(h.ctx, "parsing scrollIntoViewIfNeeded options: %w", err) +// ScrollIntoViewIfNeeded scrolls element into view if needed. +func (h *ElementHandle) ScrollIntoViewIfNeeded(opts goja.Value) error { + aopts := NewElementHandleBaseOptions(h.defaultTimeout()) + if err := aopts.Parse(h.ctx, opts); err != nil { + return fmt.Errorf("parsing scrollIntoViewIfNeeded options: %w", err) } - err := h.waitAndScrollIntoViewIfNeeded(h.ctx, actionOpts.Force, actionOpts.NoWaitAfter, actionOpts.Timeout) + + err := h.waitAndScrollIntoViewIfNeeded(h.ctx, aopts.Force, aopts.NoWaitAfter, aopts.Timeout) if err != nil { - k6ext.Panic(h.ctx, "scrolling element into view: %w", err) + return fmt.Errorf("scrolling element into view: %w", err) } + applySlowMo(h.ctx) + + return nil } func (h *ElementHandle) SelectOption(values goja.Value, opts goja.Value) []string { From efab80ddb7c525753ef7d57b00e2e1891dcf6567 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C4=B0nan=C3=A7=20G=C3=BCm=C3=BC=C5=9F?= Date: Wed, 15 May 2024 15:18:11 +0300 Subject: [PATCH 24/32] Refactor ElementHandle.SelectOptions to return err --- browser/mapping_test.go | 2 +- common/element_handle.go | 24 ++++++++++++++---------- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/browser/mapping_test.go b/browser/mapping_test.go index 75f485e47..ad5fb2636 100644 --- a/browser/mapping_test.go +++ b/browser/mapping_test.go @@ -447,7 +447,7 @@ type elementHandleAPI interface { QueryAll(selector string) ([]*common.ElementHandle, error) Screenshot(opts goja.Value) (goja.ArrayBuffer, error) ScrollIntoViewIfNeeded(opts goja.Value) error - SelectOption(values goja.Value, opts goja.Value) []string + SelectOption(values goja.Value, opts goja.Value) ([]string, error) SelectText(opts goja.Value) SetInputFiles(files goja.Value, opts goja.Value) Tap(opts goja.Value) error diff --git a/common/element_handle.go b/common/element_handle.go index 2c6605aa0..2129168a6 100644 --- a/common/element_handle.go +++ b/common/element_handle.go @@ -1266,27 +1266,31 @@ func (h *ElementHandle) ScrollIntoViewIfNeeded(opts goja.Value) error { return nil } -func (h *ElementHandle) SelectOption(values goja.Value, opts goja.Value) []string { - actionOpts := NewElementHandleBaseOptions(h.defaultTimeout()) - if err := actionOpts.Parse(h.ctx, opts); err != nil { - k6ext.Panic(h.ctx, "parsing selectOption options: %w", err) +// SelectOption selects the options matching the given values. +func (h *ElementHandle) SelectOption(values goja.Value, opts goja.Value) ([]string, error) { + aopts := NewElementHandleBaseOptions(h.defaultTimeout()) + if err := aopts.Parse(h.ctx, opts); err != nil { + return nil, fmt.Errorf("parsing selectOption options: %w", err) } - fn := func(apiCtx context.Context, handle *ElementHandle) (any, error) { + + selectOption := func(apiCtx context.Context, handle *ElementHandle) (any, error) { return handle.selectOption(apiCtx, values) } - actFn := h.newAction([]string{}, fn, actionOpts.Force, actionOpts.NoWaitAfter, actionOpts.Timeout) - selectedOptions, err := call(h.ctx, actFn, actionOpts.Timeout) + selectOptionAction := h.newAction( + []string{}, selectOption, aopts.Force, aopts.NoWaitAfter, aopts.Timeout, + ) + selectedOptions, err := call(h.ctx, selectOptionAction, aopts.Timeout) if err != nil { - k6ext.Panic(h.ctx, "selecting options: %w", err) + return nil, fmt.Errorf("selecting options: %w", err) } var returnVal []string if err := convert(selectedOptions, &returnVal); err != nil { - k6ext.Panic(h.ctx, "unpacking selected options: %w", err) + return nil, fmt.Errorf("unpacking selected options: %w", err) } applySlowMo(h.ctx) - return returnVal + return returnVal, nil } func (h *ElementHandle) SelectText(opts goja.Value) { From c011e5b4a6a7859661624ea9d6c3172cba152f46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C4=B0nan=C3=A7=20G=C3=BCm=C3=BC=C5=9F?= Date: Wed, 15 May 2024 15:21:50 +0300 Subject: [PATCH 25/32] Refactor ElementHandle.SelectText to return err --- browser/mapping_test.go | 2 +- common/element_handle.go | 23 ++++++++++++++--------- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/browser/mapping_test.go b/browser/mapping_test.go index ad5fb2636..1e82aaf51 100644 --- a/browser/mapping_test.go +++ b/browser/mapping_test.go @@ -448,7 +448,7 @@ type elementHandleAPI interface { Screenshot(opts goja.Value) (goja.ArrayBuffer, error) ScrollIntoViewIfNeeded(opts goja.Value) error SelectOption(values goja.Value, opts goja.Value) ([]string, error) - SelectText(opts goja.Value) + SelectText(opts goja.Value) error SetInputFiles(files goja.Value, opts goja.Value) Tap(opts goja.Value) error TextContent() string diff --git a/common/element_handle.go b/common/element_handle.go index 2129168a6..ecadf42fd 100644 --- a/common/element_handle.go +++ b/common/element_handle.go @@ -1293,20 +1293,25 @@ func (h *ElementHandle) SelectOption(values goja.Value, opts goja.Value) ([]stri return returnVal, nil } -func (h *ElementHandle) SelectText(opts goja.Value) { - actionOpts := NewElementHandleBaseOptions(h.defaultTimeout()) - if err := actionOpts.Parse(h.ctx, opts); err != nil { - k6ext.Panic(h.ctx, "parsing selectText options: %w", err) +// SelectText selects the text of the element. +func (h *ElementHandle) SelectText(opts goja.Value) error { + aopts := NewElementHandleBaseOptions(h.defaultTimeout()) + if err := aopts.Parse(h.ctx, opts); err != nil { + return fmt.Errorf("parsing selectText options: %w", err) } - fn := func(apiCtx context.Context, handle *ElementHandle) (any, error) { + selectText := func(apiCtx context.Context, handle *ElementHandle) (any, error) { return nil, handle.selectText(apiCtx) } - actFn := h.newAction([]string{}, fn, actionOpts.Force, actionOpts.NoWaitAfter, actionOpts.Timeout) - _, err := call(h.ctx, actFn, actionOpts.Timeout) - if err != nil { - k6ext.Panic(h.ctx, "selecting text: %w", err) + selectTextAction := h.newAction( + []string{}, selectText, aopts.Force, aopts.NoWaitAfter, aopts.Timeout, + ) + if _, err := call(h.ctx, selectTextAction, aopts.Timeout); err != nil { + return fmt.Errorf("selecting text: %w", err) } + applySlowMo(h.ctx) + + return nil } // SetInputFiles sets the given files into the input file element. From d28d6de772ea870fd719c6f65d69d3a72b3adb48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C4=B0nan=C3=A7=20G=C3=BCm=C3=BC=C5=9F?= Date: Wed, 15 May 2024 15:24:18 +0300 Subject: [PATCH 26/32] Refactor ElementHandle.SetInputFiles for consistency --- browser/mapping_test.go | 2 +- common/element_handle.go | 11 +++++------ 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/browser/mapping_test.go b/browser/mapping_test.go index 1e82aaf51..4f98f23f4 100644 --- a/browser/mapping_test.go +++ b/browser/mapping_test.go @@ -449,7 +449,7 @@ type elementHandleAPI interface { ScrollIntoViewIfNeeded(opts goja.Value) error SelectOption(values goja.Value, opts goja.Value) ([]string, error) SelectText(opts goja.Value) error - SetInputFiles(files goja.Value, opts goja.Value) + SetInputFiles(files goja.Value, opts goja.Value) error Tap(opts goja.Value) error TextContent() string Type(text string, opts goja.Value) diff --git a/common/element_handle.go b/common/element_handle.go index ecadf42fd..e5d0d410f 100644 --- a/common/element_handle.go +++ b/common/element_handle.go @@ -1316,8 +1316,8 @@ func (h *ElementHandle) SelectText(opts goja.Value) error { // SetInputFiles sets the given files into the input file element. func (h *ElementHandle) SetInputFiles(files goja.Value, opts goja.Value) error { - actionOpts := NewElementHandleSetInputFilesOptions(h.defaultTimeout()) - if err := actionOpts.Parse(h.ctx, opts); err != nil { + aopts := NewElementHandleSetInputFilesOptions(h.defaultTimeout()) + if err := aopts.Parse(h.ctx, opts); err != nil { return fmt.Errorf("parsing setInputFiles options: %w", err) } @@ -1327,12 +1327,11 @@ func (h *ElementHandle) SetInputFiles(files goja.Value, opts goja.Value) error { return fmt.Errorf("parsing setInputFiles parameter: %w", err) } - fn := func(apiCtx context.Context, handle *ElementHandle) (any, error) { + setInputFiles := func(apiCtx context.Context, handle *ElementHandle) (any, error) { return nil, handle.setInputFiles(apiCtx, actionParam.Payload) } - actFn := h.newAction([]string{}, fn, actionOpts.Force, actionOpts.NoWaitAfter, actionOpts.Timeout) - _, err := call(h.ctx, actFn, actionOpts.Timeout) - if err != nil { + setInputFilesAction := h.newAction([]string{}, setInputFiles, aopts.Force, aopts.NoWaitAfter, aopts.Timeout) + if _, err := call(h.ctx, setInputFilesAction, aopts.Timeout); err != nil { return fmt.Errorf("setting input files: %w", err) } From 7fd44069bedcbea62fc65f45d4dcf0d1d5e5f04f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C4=B0nan=C3=A7=20G=C3=BCm=C3=BC=C5=9F?= Date: Wed, 15 May 2024 15:25:50 +0300 Subject: [PATCH 27/32] Refactor ElementHandle.TextContent to return err --- browser/mapping_test.go | 2 +- common/element_handle.go | 21 ++++++++++++++------- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/browser/mapping_test.go b/browser/mapping_test.go index 4f98f23f4..845fc29b3 100644 --- a/browser/mapping_test.go +++ b/browser/mapping_test.go @@ -451,7 +451,7 @@ type elementHandleAPI interface { SelectText(opts goja.Value) error SetInputFiles(files goja.Value, opts goja.Value) error Tap(opts goja.Value) error - TextContent() string + TextContent() (string, error) Type(text string, opts goja.Value) Uncheck(opts goja.Value) error WaitForElementState(state string, opts goja.Value) diff --git a/common/element_handle.go b/common/element_handle.go index e5d0d410f..b05b0c892 100644 --- a/common/element_handle.go +++ b/common/element_handle.go @@ -1383,21 +1383,28 @@ func (h *ElementHandle) tap(_ context.Context, p *Position) error { return h.frame.page.Touchscreen.tap(p.X, p.Y) } -func (h *ElementHandle) TextContent() string { - fn := func(apiCtx context.Context, handle *ElementHandle) (any, error) { +// TextContent returns the text content of the element. +func (h *ElementHandle) TextContent() (string, error) { + textContent := func(apiCtx context.Context, handle *ElementHandle) (any, error) { return handle.textContent(apiCtx) } opts := NewElementHandleBaseOptions(h.defaultTimeout()) - actFn := h.newAction([]string{}, fn, opts.Force, opts.NoWaitAfter, opts.Timeout) - v, err := call(h.ctx, actFn, opts.Timeout) + textContentAction := h.newAction( + []string{}, textContent, opts.Force, opts.NoWaitAfter, opts.Timeout, + ) + v, err := call(h.ctx, textContentAction, opts.Timeout) if err != nil { - k6ext.Panic(h.ctx, "getting text content of element: %w", err) + return "", fmt.Errorf("getting text content of element: %w", err) } + applySlowMo(h.ctx) - // TODO: handle error + s, ok := v.(string) + if !ok { + return "", fmt.Errorf("unexpected type %T (expecting string)", v) + } - return v.(string) //nolint:forcetypeassert + return s, nil } // Timeout will return the default timeout or the one set by the user. From 1164ef2cdc521b9af55af77799c88dcc19ee50bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C4=B0nan=C3=A7=20G=C3=BCm=C3=BC=C5=9F?= Date: Wed, 15 May 2024 15:29:38 +0300 Subject: [PATCH 28/32] Refactor ElementHandle.Type to return err --- browser/mapping_test.go | 2 +- common/element_handle.go | 23 ++++++++++++++--------- tests/mouse_test.go | 24 ++++++++++++++++++------ tests/page_test.go | 2 +- 4 files changed, 34 insertions(+), 17 deletions(-) diff --git a/browser/mapping_test.go b/browser/mapping_test.go index 845fc29b3..390ae2b0a 100644 --- a/browser/mapping_test.go +++ b/browser/mapping_test.go @@ -452,7 +452,7 @@ type elementHandleAPI interface { SetInputFiles(files goja.Value, opts goja.Value) error Tap(opts goja.Value) error TextContent() (string, error) - Type(text string, opts goja.Value) + Type(text string, opts goja.Value) error Uncheck(opts goja.Value) error WaitForElementState(state string, opts goja.Value) WaitForSelector(selector string, opts goja.Value) (*common.ElementHandle, error) diff --git a/common/element_handle.go b/common/element_handle.go index b05b0c892..c9e18ae3d 100644 --- a/common/element_handle.go +++ b/common/element_handle.go @@ -1414,20 +1414,25 @@ func (h *ElementHandle) Timeout() time.Duration { } // Type scrolls element into view, focuses element and types text. -func (h *ElementHandle) Type(text string, opts goja.Value) { - parsedOpts := NewElementHandleTypeOptions(h.defaultTimeout()) - if err := parsedOpts.Parse(h.ctx, opts); err != nil { - k6ext.Panic(h.ctx, "parsing type options: %v", err) +func (h *ElementHandle) Type(text string, opts goja.Value) error { + popts := NewElementHandleTypeOptions(h.defaultTimeout()) + if err := popts.Parse(h.ctx, opts); err != nil { + return fmt.Errorf("parsing type options: %w", err) } - fn := func(apiCtx context.Context, handle *ElementHandle) (any, error) { + + typ := func(apiCtx context.Context, handle *ElementHandle) (any, error) { return nil, handle.typ(apiCtx, text, NewKeyboardOptions()) } - actFn := h.newAction([]string{}, fn, false, parsedOpts.NoWaitAfter, parsedOpts.Timeout) - _, err := call(h.ctx, actFn, parsedOpts.Timeout) - if err != nil { - k6ext.Panic(h.ctx, "typing text %q: %w", text, err) + typeAction := h.newAction( + []string{}, typ, false, popts.NoWaitAfter, popts.Timeout, + ) + if _, err := call(h.ctx, typeAction, popts.Timeout); err != nil { + return fmt.Errorf("typing text %q: %w", text, err) } + applySlowMo(h.ctx) + + return nil } func (h *ElementHandle) WaitForElementState(state string, opts goja.Value) { diff --git a/tests/mouse_test.go b/tests/mouse_test.go index 5e04a99eb..e901b18c5 100644 --- a/tests/mouse_test.go +++ b/tests/mouse_test.go @@ -30,7 +30,9 @@ func TestMouseActions(t *testing.T) { require.NoError(t, m.Click(box.X, box.Y, nil)) // Verify the button's text changed - assert.Equal(t, "Clicked!", button.TextContent()) + text, err := button.TextContent() + require.NoError(t, err) + assert.Equal(t, "Clicked!", text) }) t.Run("double_click", func(t *testing.T) { @@ -59,12 +61,16 @@ func TestMouseActions(t *testing.T) { require.NoError(t, m.DblClick(box.X, box.Y, nil)) // Verify the button's text changed - assert.Equal(t, "Double Clicked!", button.TextContent()) + text, err := button.TextContent() + require.NoError(t, err) + assert.Equal(t, "Double Clicked!", text) // Also verify that the element was clicked twice clickCountDiv, err := p.Query("div#clicks") require.NoError(t, err) - assert.Equal(t, "2", clickCountDiv.TextContent()) + text, err = clickCountDiv.TextContent() + require.NoError(t, err) + assert.Equal(t, "2", text) }) t.Run("move", func(t *testing.T) { @@ -88,7 +94,9 @@ func TestMouseActions(t *testing.T) { // Simulate mouse move within the div box := area.BoundingBox() require.NoError(t, m.Move(box.X+50, box.Y+50, nil)) // Move to the center of the div - assert.Equal(t, "Mouse Moved", area.TextContent()) + text, err := area.TextContent() + require.NoError(t, err) + assert.Equal(t, "Mouse Moved", text) }) t.Run("move_down_up", func(t *testing.T) { @@ -112,8 +120,12 @@ func TestMouseActions(t *testing.T) { box := button.BoundingBox() require.NoError(t, m.Move(box.X, box.Y, nil)) require.NoError(t, m.Down(nil)) - assert.Equal(t, "Mouse Down", button.TextContent()) + text, err := button.TextContent() + require.NoError(t, err) + assert.Equal(t, "Mouse Down", text) require.NoError(t, m.Up(nil)) - assert.Equal(t, "Mouse Up", button.TextContent()) + text, err = button.TextContent() + require.NoError(t, err) + assert.Equal(t, "Mouse Up", text) }) } diff --git a/tests/page_test.go b/tests/page_test.go index 729615599..f2196728f 100644 --- a/tests/page_test.go +++ b/tests/page_test.go @@ -496,7 +496,7 @@ func TestPageInputSpecialCharacters(t *testing.T) { } for _, want := range wants { require.NoError(t, el.Fill("", nil)) - el.Type(want, nil) + require.NoError(t, el.Type(want, nil)) got, err := el.InputValue(nil) require.NoError(t, err) From 4aa7023d9800db4db4ce27c16c19c8095a98a441 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C4=B0nan=C3=A7=20G=C3=BCm=C3=BC=C5=9F?= Date: Wed, 15 May 2024 16:22:58 +0300 Subject: [PATCH 29/32] Fix WaitForElementState mapping API --- browser/mapping_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/browser/mapping_test.go b/browser/mapping_test.go index 390ae2b0a..b909460a3 100644 --- a/browser/mapping_test.go +++ b/browser/mapping_test.go @@ -454,7 +454,7 @@ type elementHandleAPI interface { TextContent() (string, error) Type(text string, opts goja.Value) error Uncheck(opts goja.Value) error - WaitForElementState(state string, opts goja.Value) + WaitForElementState(state string, opts goja.Value) error WaitForSelector(selector string, opts goja.Value) (*common.ElementHandle, error) } From b1d4c4a62cb1178a283d638c61410a3778f6d7f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C4=B0nan=C3=A7=20G=C3=BCm=C3=BC=C5=9F?= Date: Wed, 15 May 2024 15:31:21 +0300 Subject: [PATCH 30/32] Refactor ElementHandle.WaitForElementState to return err --- common/element_handle.go | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/common/element_handle.go b/common/element_handle.go index c9e18ae3d..6e5c76be0 100644 --- a/common/element_handle.go +++ b/common/element_handle.go @@ -1435,16 +1435,18 @@ func (h *ElementHandle) Type(text string, opts goja.Value) error { return nil } -func (h *ElementHandle) WaitForElementState(state string, opts goja.Value) { - parsedOpts := NewElementHandleWaitForElementStateOptions(h.defaultTimeout()) - err := parsedOpts.Parse(h.ctx, opts) - if err != nil { - k6ext.Panic(h.ctx, "parsing waitForElementState options: %w", err) +// WaitForElementState waits for the element to reach the given state. +func (h *ElementHandle) WaitForElementState(state string, opts goja.Value) error { + popts := NewElementHandleWaitForElementStateOptions(h.defaultTimeout()) + if err := popts.Parse(h.ctx, opts); err != nil { + return fmt.Errorf("parsing waitForElementState options: %w", err) } - _, err = h.waitForElementState(h.ctx, []string{state}, parsedOpts.Timeout) + _, err := h.waitForElementState(h.ctx, []string{state}, popts.Timeout) if err != nil { - k6ext.Panic(h.ctx, "waiting for element state %q: %w", state, err) + return fmt.Errorf("waiting for element state %q: %w", state, err) } + + return nil } // WaitForSelector waits for the selector to appear in the DOM. From c4e6994ee468ce5d4150926d279af957f381eadb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C4=B0nan=C3=A7=20G=C3=BCm=C3=BC=C5=9F?= Date: Wed, 15 May 2024 16:26:00 +0300 Subject: [PATCH 31/32] Refactor ElementHandle.Query to return err --- common/element_handle.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/common/element_handle.go b/common/element_handle.go index 6e5c76be0..debf301eb 100644 --- a/common/element_handle.go +++ b/common/element_handle.go @@ -1082,9 +1082,9 @@ func (h *ElementHandle) Press(key string, opts goja.Value) error { func (h *ElementHandle) Query(selector string, strict bool) (*ElementHandle, error) { parsedSelector, err := NewSelector(selector) if err != nil { - k6ext.Panic(h.ctx, "parsing selector %q: %w", selector, err) + return nil, fmt.Errorf("parsing selector %q: %w", selector, err) } - fn := ` + querySelector := ` (node, injected, selector, strict) => { return injected.querySelector(selector, strict, node || document); } @@ -1093,7 +1093,7 @@ func (h *ElementHandle) Query(selector string, strict bool) (*ElementHandle, err forceCallable: true, returnByValue: false, } - result, err := h.evalWithScript(h.ctx, opts, fn, parsedSelector, strict) + result, err := h.evalWithScript(h.ctx, opts, querySelector, parsedSelector, strict) if err != nil { return nil, fmt.Errorf("querying selector %q: %w", selector, err) } From 5c968cb4a8e5e58596b0c4d7d91bedbb4d4a1b4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C4=B0nan=C3=A7=20G=C3=BCm=C3=BC=C5=9F?= Date: Wed, 15 May 2024 16:29:31 +0300 Subject: [PATCH 32/32] Refactor errorFromDOMError to return err --- common/element_handle.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/common/element_handle.go b/common/element_handle.go index debf301eb..c0ff9e78e 100644 --- a/common/element_handle.go +++ b/common/element_handle.go @@ -1650,11 +1650,11 @@ func errorFromDOMError(v any) error { serr = e case error: if e == nil { - panic("DOM error is nil") + return errors.New("DOM error is nil") } err, serr = e, e.Error() default: - panic(fmt.Errorf("unexpected DOM error type %T", v)) + return fmt.Errorf("unexpected DOM error type %T", v) } var uerr *k6ext.UserFriendlyError if errors.As(err, &uerr) {